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查看,结构如下图

X264编码写FLV,F4V点滴记录 - niulei20012001 - niulei20012001的博客
依次为:SPS->PPS->SEI->IDR->nonIDR...nonIDR->SPS->PPS->IDR->nonIDR...nonIDR->SPS->PPS->IDR->nonIDR...nonIDR->----

 1.下图为SPS(Sequence parameter set)详细参数

X264编码写FLV,F4V点滴记录 - niulei20012001 - niulei20012001的博客
前3个单元是程序设置的
//拷贝一个完整NALU,不拷贝起始前缀0x000001或0x00000001
     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
下面的seq_parameter_set_rbsp中的内容待研究
2.下图为PPS(Picture parameter set)详细参数
X264编码写FLV,F4V点滴记录 - niulei20012001 - niulei20012001的博客
其中前3个参数是和SPS一样的
下面的pic_parameter_set_rbsp参数待研究
3.下图为SEI附加增强信息(Supplemental enhancement information)的信息
X264编码写FLV,F4V点滴记录 - niulei20012001 - niulei20012001的博客
00000025   00 00 01 06 05 FF FF 5C DC 45 E9 BD E6 D9 48 B7  .....??\蹺榻尜H?
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编码器的一些设置参数信息;
4.下图是IDR(coded slice of an IDR picture)的信息
X264编码写FLV,F4V点滴记录 - niulei20012001 - niulei20012001的博客
 这个里面包含的都是IDR关键帧的数据
5.下图是non-IDR(coded slice of an non-IDR picture)的信息
X264编码写FLV,F4V点滴记录 - niulei20012001 - niulei20012001的博客
 这个里面包含的是非关键帧的数据
为了描述关键帧和非关键帧的区别,先引用一篇文章

“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;

 关于NALU的类型(nal_unit_type)说明:
#define NALU_TYPE_SLICE 1
#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
每个NALU第一个byte & 0x1f 就可以得出它的类型,比如上图第一个NALU:67 & 0x1f = 7,则此单元是SPS,第三个:68 & 0x1f = 8,则此单元是PPS,所以看前面每个数据片中前3个信息的第3个信息,通过程序描述如下:
nalu->nal_unit_type = (nalu->buf[0]) & 0x1f;// 5 bit NALU_TYPE_xxxx
7.flv文件结构分析
FLV是一个二进制文件,包含FLV Header和 File Body,File Body中又包含很多的Prevoius Tag Size和Tag组成,tag又可以分成三类:audio,video,script,分别代表音频流,视频流,脚本流,而每个tag又由Tag和Previous Tag Size对组成,Previous Tag Size紧跟在每个Tag之后,占4个字节表示一个UI32类型的数值,表示前面一个Tag的大小;
X264编码写FLV,F4V点滴记录 - niulei20012001 - niulei20012001的博客
整个的flv文件其实是:FLV header (占用9个byte)+ previous tag size0(占用4个byte 默认为00 00 00 00) + Metadata Tag(关于FLV视频和音频的参数信息,如duration、width、height等,具体占用大小按实际大小计算) + previous tag size(占用4个byte 表示前一个Tag的大小,这里指Metadata的长度) + Video Tag1(视频配置信息,大小按实际大小计算) + previous tag size1(占用4个byte 视频配置信息大小)+  Audio Tag2(音频配置信息,大小按实际大小计算) +previous tag size2(占用4个byte 音频配置信息大小)+ ... +tagN + previous tag sizeN
从tag3开始,依次记录的就是音视频数据及其大小了,下面对上面红色的部分作一一分析。
 7.1 FLV Header分析
X264编码写FLV,F4V点滴记录 - niulei20012001 - niulei20012001的博客
FLV Header一共由9个byte组成:
前3个bytes是文件类型,总是“FLV”,也就是(0x46 0x4C 0x56)。
第4个btye是版本号,目前固定为0x01。
第5个byte是流的信息,倒数第一个bit是1表示有视频(0x01,00000001),倒数第三个bit是1表示有音频(0x04,00000100),有视频又有音频就是0x01 | 0x04(0x05,00000101),其他都应该是0。
最后4个bytes表示FLV 头的长度,3+1+1+4 = 9。
7.2 FLV body分析
FLV header后面就是FLV body:
FLV body由若干个tag 组成。每一个tag第一部分是tag header,tag header长度为11bytes,但是每个tag header前面有4bytes记录着上一个tag的长度;因为第一个tag的前一个tag长度为0,因此后面首先紧跟着的就是4个00,即为First Tag Size,如下图选择区域所示
X264编码写FLV,F4V点滴记录 - niulei20012001 - niulei20012001的博客
7.2.1 tag header分析
第1个byte为记录着tag的类型,音频(0x8),视频(0x9),脚本(0x12);
第2-4bytes是数据区的长度,UI24类型的值,也就是tag data的长度;注:这个长度等于最后的Tag Size-11
第5-7个bytes是时间戳,UI24类型的值,单位是毫秒,类型为0x12脚本类型数据,则时间戳为0,时间戳控制着文件播放的速度,可以根据音视频的帧率类设置;
第8个byte是扩展时间戳,当24位数值不够时,该字节作为最高位将时间戳扩展为32位值;
第9-11个bytes是streamID,UI24类型的值,但是总为0;
tag header 长度为1+3+3+1+3=11。
再后面就是数据区了(tag data),就是h264的裸流。 
X264编码写FLV,F4V点滴记录 - niulei20012001 - niulei20012001的博客
 上图是Metadata Tag的header,只设置了tag类型和数据区长度;
 
7.2.2 tag data分析
tag data数据类型又可分为音频数据、视频数据、脚本数据。
7.2.2.1 tag data是音频数据

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)

然后后面的就是真实的视频数据。

  7.2.2.3 tag data是脚本数据(Metadata Tag)
       该类型Tag又通常被称为Metadata Tag,会放一些关于FLV视频和音频的参数信息,如duration、width、height等。通常该类型Tag会跟在File Header后面作为第一个Tag出现,而且只有一个。

       一般来说,该Tag Data结构包含两个AMF包。AMF(Action Message Format)是Adobe设计的一种通用数据封装格式,在Adobe的很多产品中应用,简单来说,AMF将不同类型的数据用统一的格式来描述。

       1)第一个AMF包封装字符串类型数据,用来装入一个“onMetaData”标志,这个标志与Adobe的一些API调用有关,在此不细述。

       2)第二个AMF包封装一个数组类型,这个数组中包含了音视频信息项的名称和值。具体说明如下,大家可以参照图片上的数据进行理解。

第一个AMF包:

第1个字节表示AMF包类型,一般总是0x02,表示字符串,其他值表示意义请查阅文档。

第2-3个字节为UI16类型值,表示字符串的长度,一般总是0x000A(“onMetaData”长度)。

后面字节为字符串数据,一般总为“onMetaData”。

X264编码写FLV,F4V点滴记录 - niulei20012001 - niulei20012001的博客

 

第二个AMF包:

第1个字节表示AMF包类型,一般总是0x08,表示数组。

第2-5个字节为UI32类型值,表示数组元素的个数。

后面即为各数组元素的封装,数组元素为元素名称和值组成的对。表示方法如下:

第1-2个字节表示元素名称的长度,假设为L。

后面跟着为长度为L的字符串。

第L+3个字节表示元素值的类型。

后面跟着为对应值,占用字节数取决于值的类型。

关于元素值的数据类型说明:
数据类型占用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

X264编码写FLV,F4V点滴记录 - niulei20012001 - niulei20012001的博客

 下面的参数引用自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

X264编码写FLV,F4V点滴记录 - niulei20012001 - niulei20012001的博客

 

X264编码写FLV,F4V点滴记录 - niulei20012001 - niulei20012001的博客
上图将依次标识出了,参数名称长度-参数名称-参数值数据类型-参数值,并用绿色竖线隔开,图中共标识了12个参数信息,其中唯一不同参数的数据类型已经用粉红色方框表示,其他都是double类型。

 最后再加上变量的结束标志00 00 09。

 7.2.3 tag size分析

在数据区域后面接的就是上个数据的总长度,从上图中看出为00 00 01 17,数据总长为279个。

X264编码写FLV,F4V点滴记录 - niulei20012001 - niulei20012001的博客


7.3 Video Tag1分析(视频配置信息)

一般h264数据最开始的两个NALU就是SPS和PPS

下图是一个视频配置的Tag,因为是一个Tag,因此遵循上面讲的关于Tag的定义:X264编码写FLV,F4V点滴记录 - niulei20012001 - niulei20012001的博客

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)其余剩下的按下图定义

X264编码写FLV,F4V点滴记录 - niulei20012001 - niulei20012001的博客
 

 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)

X264编码写FLV,F4V点滴记录 - niulei20012001 - niulei20012001的博客
 

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,这样处理后,可保证录像播放的速度正常。

7.7.2视频数据类型(5 bytes)
第1个字节0x17,高4位1表示关键帧,低4位表示AVC(h264);第2个字节表示AVCPacket type;最后3个字节,默认0x00;上图中红色选择区域就是视频数据类型区域。
FieldTypeCommentFrame TypeUB [4]Type of video frame. The following values are defined:
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 frame
CodecIDUB [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 = AVC
AVCPacketTypeIF 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)

CompositionTimeIF CodecID == 7
SI24
IF 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.

7.7.3数据区长度(4 bytes)+视频数据(video buffer size bytes)
使用4个字节表示视频数据区域的实际视频数据大小;上图中用蓝色选择区域表示。

使用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,时间戳控制着文件播放的速度,可以根据音视频的帧率类设置,下面讲讲具体的设置方法;


0 0
原创粉丝点击