X264编码封装FLV,F4V点滴记录
来源:互联网 发布:手机免费读书软件 编辑:程序博客网 时间:2024/06/16 05:37
本文引用了部分前人的程序和相关文章,经过总结和重新加入了自己的理解,特此对前人的辛苦研究表示感谢!
http://www.cnblogs.com/chef/archive/2012/07/18/2597279.html
http://blog.csdn.net/yeyumin89/article/details/7932368
http://blog.csdn.net/yeyumin89/article/details/7932431
http://blog.sina.com.cn/s/blog_48f93b530100eyoe.html
http://blog.csdn.net/b4362928/article/details/4970169
http://www.cnblogs.com/haibindev/archive/2011/12/29/2305712.html
X264编码后的数据,使用H264VideoESViewer查看,结构如下图
1.下图为SPS(Sequence parameter set)详细参数
memcpy (nalu->buf, &h264Buffer[nalu->startcodeprefix_len], nalu->len);
nalu->forbidden_bit = nalu->buf[0] & 0x80; //1 bit should be always FALSE
nalu->nal_reference_idc = nalu->buf[0] & 0x60; // 2 bit NALU_PRIORITY_xxxx
nalu->nal_unit_type = (nalu->buf[0]) & 0x1f;// 5 bit NALU_TYPE_xxxx
00000035 96 2C D8 20 D9 23 EE EF 78 32 36 34 20 2D 20 63 ???铒x264 - c
00000045 6F 72 65 20 31 32 35 20 2D 20 48 2E 32 36 34 2F ore 125 - H.264/
00000055 4D 50 45 47 2D 34 20 41 56 43 20 63 6F 64 65 63 MPEG-4 AVC codec
00000065 20 2D 20 43 6F 70 79 6C 65 66 74 20 32 30 30 33 - Copyleft 2003
00000075 2D 32 30 31 32 20 2D 20 68 74 74 70 3A 2F 2F 77 -2012 - http://w
00000085 77 77 2E 76 69 64 65 6F 6C 61 6E 2E 6F 72 67 2F ww.videolan.org/
00000095 78 32 36 34 2E 68 74 6D 6C 20 2D 20 6F 70 74 69 x264.html - opti
000000A5 6F 6E 73 3A 20 63 61 62 61 63 3D 31 20 72 65 66 ons: cabac=1 ref
000000B5 3D 34 20 64 65 62 6C 6F 63 6B 3D 31 3A 30 3A 30 =4 deblock=1:0:0
000000C5 20 61 6E 61 6C 79 73 65 3D 30 78 33 3A 30 78 31 analyse=0x3:0x1
000000D5 31 33 20 6D 65 3D 64 69 61 20 73 75 62 6D 65 3D 13 me=dia subme=
000000E5 37 20 70 73 79 3D 31 20 70 73 79 5F 72 64 3D 31 7 psy=1 psy_rd=1
000000F5 2E 30 30 3A 30 2E 30 30 20 6D 69 78 65 64 5F 72 .00:0.00 mixed_r
00000105 65 66 3D 31 20 6D 65 5F 72 61 6E 67 65 3D 31 36 ef=1 me_range=16
00000115 20 63 68 72 6F 6D 61 5F 6D 65 3D 31 20 74 72 65 chroma_me=1 tre
00000125 6C 6C 69 73 3D 31 20 38 78 38 64 63 74 3D 31 20 llis=1 8x8dct=1
00000135 63 71 6D 3D 30 20 64 65 61 64 7A 6F 6E 65 3D 32 cqm=0 deadzone=2
00000145 31 2C 31 31 20 66 61 73 74 5F 70 73 6B 69 70 3D 1,11 fast_pskip=
00000155 31 20 63 68 72 6F 6D 61 5F 71 70 5F 6F 66 66 73 1 chroma_qp_offs
00000165 65 74 3D 2D 32 20 74 68 72 65 61 64 73 3D 36 20 et=-2 threads=6
00000175 6C 6F 6F 6B 61 68 65 61 64 5F 74 68 72 65 61 64 lookahead_thread
00000185 73 3D 31 20 73 6C 69 63 65 64 5F 74 68 72 65 61 s=1 sliced_threa
00000195 64 73 3D 30 20 6E 72 3D 30 20 64 65 63 69 6D 61 ds=0 nr=0 decima
000001A5 74 65 3D 31 20 69 6E 74 65 72 6C 61 63 65 64 3D te=1 interlaced=
000001B5 30 20 62 6C 75 72 61 79 5F 63 6F 6D 70 61 74 3D 0 bluray_compat=
000001C5 30 20 63 6F 6E 73 74 72 61 69 6E 65 64 5F 69 6E 0 constrained_in
000001D5 74 72 61 3D 30 20 62 66 72 61 6D 65 73 3D 30 20 tra=0 bframes=0
000001E5 77 65 69 67 68 74 70 3D 32 20 6B 65 79 69 6E 74 weightp=2 keyint
000001F5 3D 35 30 20 6B 65 79 69 6E 74 5F 6D 69 6E 3D 35 =50 keyint_min=5
00000205 20 73 63 65 6E 65 63 75 74 3D 34 30 20 69 6E 74 scenecut=40 int
00000215 72 61 5F 72 65 66 72 65 73 68 3D 30 20 72 63 3D ra_refresh=0 rc=
00000225 61 62 72 20 6D 62 74 72 65 65 3D 30 20 62 69 74 abr mbtree=0 bit
00000235 72 61 74 65 3D 39 30 20 72 61 74 65 74 6F 6C 3D rate=90 ratetol=
00000245 31 2E 30 20 71 63 6F 6D 70 3D 30 2E 36 30 20 71 1.0 qcomp=0.60 q
00000255 70 6D 69 6E 3D 31 30 20 71 70 6D 61 78 3D 33 30 pmin=10 qpmax=30
00000265 20 71 70 73 74 65 70 3D 34 20 69 70 5F 72 61 74 qpstep=4 ip_rat
00000275 69 6F 3D 31 2E 34 30 20 61 71 3D 31 3A 31 2E 30 io=1.40 aq=1:1.0
00000285 30 00 80 0.?
这个SEI信息主要描述的是X264编码器的一些设置参数信息;
“DR(Instantaneous Decoding Refresh)--即时解码刷新。
I和IDR帧都是使用帧内预测的。它们都是同一个东西而已,在编码和解码中为了方便,要首个I帧和其他I帧区别开,所以才把第一个首个I帧叫IDR,这样就方便控制编码和解码流程。IDR帧的作用是立刻刷新,使错误不致传播,从IDR帧开始,重新算一个新的序列开始编码。而I帧不具有随机访问的能力,这个功能是由IDR承担。IDR会导致DPB(DecodedPictureBuffer 参考帧列表——这是关键所在)清空,而I不会。IDR图像一定是I图像,但I图像不一定是IDR图像。一个序列中可以有很多的I图像,I图像之后的图像可以引用I图像之间的图像做运动参考。一个序列中可以有很多的I图像,I图像之后的图象可以引用I图像之间的图像做运动参考。
对于IDR帧来说,在IDR帧之后的所有帧都不能引用任何IDR帧之前的帧的内容,与此相反,对于普通的I-帧来说,位于其之后的B-和P-帧可以引用位于普通I-帧之前的I-帧。从随机存取的视频流中,播放器永远可以从一个IDR帧播放(视频拖动的时候,只有拖到IDR帧位置才能继续播放),因为在它之后没有任何帧引用之前的帧。但是,不能在一个没有IDR帧的视频中从任意点开始播放,因为后面的帧总是会引用前面的帧。”
上文的描述中I帧指的应该就是普通帧(也叫非关键帧、non-IDR帧),IDR显然就是指关键帧
6.讲一下X264实时编码和发送的过程
1)X264初始化,指定编码图像的width、height、fps、bitrate、quality
2)编码送过来的YUV420数据
3)如果编码出数据,则送去按0x000001或0x00000001解析,找到0x000001或0x00000001的头的数据,然后将尾随的数据封包到一个nalu单元中,并设置一个nalu的相关参数,并发送出去,nalu单元的格式如下:
typedef struct
{
int startcodeprefix_len; //! 4 for parameter sets and first slice in picture, 3 for everything else (suggested)
unsigned len; //! Length of the NAL unit (Excluding the start code, which does not belong to the NALU)
unsigned max_size; //! Nal Unit Buffer size
int forbidden_bit; //! should be always FALSE
int nal_reference_idc; //! NALU_PRIORITY_xxxx
int nal_unit_type; //! NALU_TYPE_xxxx
char *buf; //! contains the first byte followed by the EBSP
unsigned short lost_packets; //! true, if packet loss is detected
} NALU_t;
#define NALU_TYPE_DPA 2
#define NALU_TYPE_DPB 3
#define NALU_TYPE_DPC 4
#define NALU_TYPE_IDR 5
#define NALU_TYPE_SEI 6
#define NALU_TYPE_SPS 7
#define NALU_TYPE_PPS 8
#define NALU_TYPE_AUD 9
#define NALU_TYPE_EOSEQ 10
#define NALU_TYPE_EOSTREAM 11
#define NALU_TYPE_FILL 12
从tag3开始,依次记录的就是音视频数据及其大小了,下面对上面红色的部分作一一分析。
第2-4bytes是数据区的长度,UI24类型的值,也就是tag data的长度;注:这个长度等于最后的Tag Size-11
tag data如果是音频数据,第1个byte记录audio信息:
第1-4个bits表示音频格式(全部格式请看官方文档):
·0 -- 未压缩
·1 -- ADPCM
·2 -- MP3
·4 -- Nellymoser 16-kHz mono
·5 -- Nellymoser 8-kHz mono
·10 -- AAC
第5-6个bits表示SampleRate:
·0 -- 5.5KHz
·1 -- 11kHz
·2 -- 22kHz
·3 -- 44kHz
第7个bit表示采样长度:
·0 -- snd8Bit
·1 -- snd16Bit
第8个bit表示类型:
·0 -- sndMomo
·1 -- sndStereo
然后后面的就是真实的音频数据。
7.2.2.2 tag data是视频数据
如果是视频数据,第一个byte记录video信息:
第1-4个bits表示类型:
·1-- keyframe
·2 -- inner frame
·3 -- disposable inner frame (h.263 only)
·4 -- generated keyframe
第5-8bits表示解码器ID:
·2 -- seronson h.263
·3 -- screen video
·4 -- On2 VP6
·5 -- On2 VP6 with alpha channel
·6 -- Screen video version 2
·7 -- AVC (h.264)
然后后面的就是真实的视频数据。
1)第一个AMF包封装字符串类型数据,用来装入一个“onMetaData”标志,这个标志与Adobe的一些API调用有关,在此不细述。
2)第二个AMF包封装一个数组类型,这个数组中包含了音视频信息项的名称和值。具体说明如下,大家可以参照图片上的数据进行理解。
关于元素值的数据类型说明:
数据类型占用1个字节(详细内容请参看FLV官方pdf文档)
0 = Number type //DOUBLE(8个字节的double数据)
1 = Boolean type //UI8(1个字节)
2 = String type //SCRIPTDATASTRING
3 = Object type //SCRIPTDATAOBJECT[n]
4 = MovieClip type //SCRIPTDATASTRING
5 = Null type
6 = Undefined type
7 = Reference type //UI16(2个字节)
8 = ECMA array type //SCRIPTDATAVARIABLE[ECMAArrayLength]
10 = Strict array type //SCRIPTDATAVARIABLE[n]
11 = Date type //SCRIPTDATADATE
12 = Long string type //SCRIPTDATALONGSTRING
下面的参数引用自video_file_format_spec_v10.pdf文档中
■ duration: a DOUBLE indicating the total duration of the file in seconds
■ width: a DOUBLE indicating the width of the video in pixels
■ height: a DOUBLE indicating the height of the video in pixels
■ videodatarate: a DOUBLE indicating the video bit rate in kilobits per second
■ framerate: a DOUBLE indicating the number of frames per second
■ videocodecid: a DOUBLE indicating the video codec ID used in the file (see “Video tags” on page 8 for available CodecID values)
■ audiosamplerate: a DOUBLE indicating the frequency at which the audio stream is replayed
■ audiosamplesize: a DOUBLE indicating the resolution of a single audio sample
■ stereo: a BOOL indicating whether the data is stereo
■ audiocodecid: a DOUBLE indicating the audio codec ID used in the file (see “Audio tags” on page 6 for available SoundFormat values)
■ filesize: a DOUBLE indicating the total size of the file in bytes
最后再加上变量的结束标志00 00 09。
7.2.3 tag size分析
在数据区域后面接的就是上个数据的总长度,从上图中看出为00 00 01 17,数据总长为279个。
7.3 Video Tag1分析(视频配置信息)
一般h264数据最开始的两个NALU就是SPS和PPS
下图是一个视频配置的Tag,因为是一个Tag,因此遵循上面讲的关于Tag的定义:
1)前11个byte是Tag header,09表示和视频相关的Tag信息,00 00 1D表示数据区的长度29位(29+11=40刚好和其后的00 00 00 28=40相一致),其他的00未使用,共占用11位;
2)第12个byte“17”的高四位为1表示关键帧,为2表示非关键帧,低4位7表示AVC (h.264);
3)第13个byte位"00”表示AVCPacket type,这里是AVC sequence header,必须写入0x00(注意:这里如果写0x01,整个flv就不能被识别);
4)第14-16的3个byte位默认为00;
5)其余剩下的按下图定义
7.4 Video Tag Size1分析(视频配置信息大小)
数据大小为00 00 00 28,前面已经证明过;
7.5 Audio Tag2分析(音频配置信息)
7.6 Audio Tag Size2分析(音频配置信息大小)
7.7 写入视频数据
视频数据的格式:视频数据头(11 bytes)+视频数据类型(5 bytes)+数据区长度(4 bytes)+视频数据(video buffer size bytes)+此Tag总数据大小(4 bytes)
7.7.1视频数据Header(11 bytes)
按FLV定义的规范写入,第1个字节0x09是Tag类型,这里代表视频数据;第2-4个字节0x00 0x4C 0x9B,视频数据区长度;第5-7个字节0x00 0x00 0x1E,时间戳,第8个字节时间戳扩展,第9-11个字节streamID,默认0x00;上图中粉红色选择区域就是视频数据Header区域。
如果录像播放的速度快或慢,则是时间戳没有处理好,下面给出一个解决方案:首先创建线程采集图像到YUV,然后单独一个线程在固定时间(比如10帧/秒,则sleep(100))内送去编码,这里要考虑一下编码占用的时间,这个时间也必须包含在100毫秒之内,这里可以在while循环前使用DWORD begint = GetTickCount()记录起始时间,然后在编码结束后DWORD endt = GetTickCount()再记录结束时间,最后sleep的时间是Sleep(100-(endt-begint)),然后再送去写FLV文件,没写一个Tag,则时间戳加100ms,这样处理后,可保证录像播放的速度正常。
1 = key frame (for AVC, a seekable frame)
2 = inter frame (for AVC, a non-seekable frame)
3 = disposable inter frame (H.263 only)
4 = generated key frame (reserved for server use only)
5 = video info/command frameCodecIDUB [4]Codec Identifier. The following values are defined:
2 = Sorenson H.263
3 = Screen video
4 = On2 VP6
5 = On2 VP6 with alpha channel
6 = Screen video version 2
7 = AVCAVCPacketTypeIF CodecID == 7
UI8
The following values are defined:
0 = AVC sequence header
1 = AVC NALU
2 = AVC end of sequence (lower level NALU sequence ender is not required or supported)
SI24IF AVCPacketType == 1
Composition time offset
ELSE
0
See ISO 14496-12, 8.15.3 for an explanation of composition
times. The offset in an FLV file is always in milliseconds.
VideoTagHeader的头1个字节,也就是接跟着StreamID的1个字节包含着视频帧类型及视频CodecID最基本信息.表里列的十分清楚.
IF AVCPacketType == 0 AVCDecoderConfigurationRecord(AVC sequence header)
IF AVCPacketType == 1 One or more NALUs (Full frames are required)
如果此帧数据是描述的sps或pps信息,则设置AVCPacketType = 0
如果此帧数据是关键帧,则设置AVCPacketType = 1
如果此帧数据是普通帧,则设置AVCPacketType = 2
AVCDecoderConfigurationRecord.包含着是H.264解码相关比较重要的sps和pps信息,再给AVC解码器送数据 流之前一定要把sps和pps信息送出,否则的话解码器不能正常解码。而且在解码器stop之后再次start之前,如seek、快进快退状态切换等,都 需要重新送一遍sps和pps的信息.AVCDecoderConfigurationRecord在FLV文件中一般情况也是出现1次,也就是第一个 video tag.
使用ffmpeg或X264编码出的每一次数据,数据都会是以00 00 01或00 00 00 01起始符开始,在打包时,将前面的00 00 01或 00 00 00 01去除,然后再加上4个字节的真实视频数据的大小。
如原来数据为00 00 01 99 88 77 66 55 44 33 22 11,则打包的程序为(数据区长度(4 bytes)+视频数据(video buffer size bytes))00 00 00 09 99 88 77 66 55 44 33 22 11,原始数据区总长为12个,新封装的数据长度为13个,这个地方需要注意。
7.8 视频数据的时间戳设置
每一个视频Tag的前11个bytes的第5-7个bytes是时间戳,UI24类型的值,单位是毫秒,类型为0x12脚本类型数据,则时间戳为0,时间戳控制着文件播放的速度,可以根据音视频的帧率类设置,下面讲讲具体的设置方法;
- X264编码封装FLV,F4V点滴记录
- F4V/FLV转换工具
- flv/f4v/m4v
- 用于 Flash 的 FLV 和 F4V 视频格式
- 服务器iis支持flv,f4v,mp4
- F4V
- F4V
- flv封装ffmpeg编码的视音频笔记(一)
- flv封装ffmpeg编码的视音频笔记(二)
- FLASH FLV及F4V原版官方格式 不必翻译
- IIS设置支持flv,f4v,mp4,ogv,webm
- X264编码
- X264编码
- X264编码
- X264编码
- X264编码
- x264记录
- flv封装格式详解
- 添加图片水印
- 最大连续子序列和——动态规划
- 08-索引模版--Index Templates--es横向扩展设计
- 23设计模式之原型模式(Prototype)
- 日常
- X264编码封装FLV,F4V点滴记录
- 有感于STL的内存管理
- 关于 行舟 关于 进退
- BackboneJs入门学习[08]—Router路由初探
- I/O流 使用举例
- 软件测试的知识总结2(周末版)
- 将h.264视频流封装成flv格式文件
- Kafka分布式消息系统
- android之ContentResolver与ContentProvider