1. 计算 AVCDecoderConfigurationRecord  得到 CodecPrivateData 数据(只有第一帧需要);
  2. 计算 NALUs 得到帧数据。

计算 AVCDecoderConfigurationRecord  得到 CodecPrivateData 数据

H.264 视频流的 CodecPrivateData 实际上就是 AVCDecoderConfigurationRecord 中 SequenceParameterSets(SPS)和 PictureParameterSets(PPS)使用 byte[] {00, 00, 01} 连接的字节数组。

注意!FLV 文件中第一个 VIDEOTAG 的 VIDEODATA 的 AVCVIDEOPACKET 的 Data 总是 AVCDecoderConfigurationRecord(在 ISO/IEC 14496-15 中定义),解码的时候注意跳过这个 VIDOETAG。

AVCDecoderConfigurationRecord 结构的定义:

aligned(8) class AVCDecoderConfigurationRecord { 
unsigned int(8) configurationVersion = 1; 
unsigned int(8) AVCProfileIndication; 
unsigned int(8) profile_compatibility; 
unsigned int(8) AVCLevelIndication; 
bit(6) reserved = ‘111111’b; 
unsigned int(2) lengthSizeMinusOne; 
bit(3) reserved = ‘111’b; 
unsigned int(5) numOfSequenceParameterSets; 
for (i=0; i< numOfSequenceParameterSets; i++) { 
unsigned int(16) sequenceParameterSetLength ; 
bit(8*sequenceParameterSetLength) sequenceParameterSetNALUnit; 

unsigned int(8) numOfPictureParameterSets; 
for (i=0; i< numOfPictureParameterSets; i++) { 
unsigned int(16) pictureParameterSetLength; 
bit(8*pictureParameterSetLength) pictureParameterSetNALUnit; 

}

下面蓝色的部分就是 FLV 文件中的 AVCDecoderConfigurationRecord 部分。

00000130h: 00 00 00 17 00 00 00 00 01 4D 40 15 FF E1 00 0A ; .........M@.?. 
00000140h: 67 4D 40 15 96 53 01 00 4A 20 01 00 05 68 E9 23 ; gM@.朣..J ...h? 
00000150h: 88 00 00 00 00 2A 08 00 00 52 00 00 00 00 00 00 ; ?...*...R......

根据 AVCDecoderConfigurationRecord 结构的定义:

  • configurationVersion = 01
  • AVCProfileIndication = 4D
  • profile_compatibility = 40
  • AVCLevelIndication = 15
  • lengthSizeMinusOne = FF <- 非常重要,是 H.264 视频中 NALU 的长度,计算方法是 1 + (lengthSizeMinusOne & 3)
  • numOfSequenceParameterSets = E1 <- SPS 的个数,计算方法是 numOfSequenceParameterSets & 0x1F
  • sequenceParameterSetLength = 00 0A <- SPS 的长度
  • sequenceParameterSetNALUnits = 67 4D 40 15 96 53 01 00 4A 20 <- SPS
  • numOfPictureParameterSets = 01 <- PPS 的个数
  • pictureParameterSetLength = 00 05 <- PPS 的长度
  • pictureParameterSetNALUnits = 68 E9 23 88 00 <- PPS

因此 CodecPrivateData 的字符串表示就是 000001674D4015965301004A2000000168E9238800

但是设置 MediaStreamAttributeKeys.CodecPrivateData 是没用的(只有 H.264 是这样,其他类型的视频流仍然需要设置),只有将 CodecPrivateData 写入 H.264 视频流第一帧数据的前面 Silverlight 才能正常解码。

也就是说,Silverlight 的 H.264 解码器会读取第一帧前面的 CodecPrivateData 数据来进行配置。

因为 CodecPrivateData 数据已经包含视频流的解码器参数(包括视频的宽高),所以就不需要设置 MediaStreamAttributeKeys.CodecPrivateData、MediaStreamAttributeKeys.Width 和 MediaStreamAttributeKeys.Height 了。

计算 NALU 得到帧数据

FLV 文件中 VIDEOTAG 的 VIDEODATA 的 AVCVIDEOPACKET 的 Data 不是原始视频帧数据,而是一个或更多个 NALU 数据片段。在这篇文章中,你认为 H.264 视频帧数据是由多个 NALU 组成的。当然实际上并不是这样,关于这部分的概念请自行 Google,本文将不做讨论。

下面是 FLV 文件中 VIDEOTAG 的 VIDEODATA 的 AVCVIDEOPACKET 的 Data 属性的数据(第一帧数据)。

  • 红色的部分是 NALU 数据的长度,而红色部分的长度则由 lengthSizeMinusOne 决定。
  • 蓝色的部分是 NALU 数据部分。
  • 删除的部分是废弃的数据。

00000300h: 00 00 00 00 00 17 01 00 00 22 00 00 00 31 65 88 ; ........."...1e? 
00000310h: 80 40 05 B7 95 53 67 FF 84 6C 07 EB 00 F8 45 FB ; €@.窌Sg刲.?鳨? 
00000320h: F9 15 71 0D A4 C5 2C 00 00 03 00 00 03 00 3F 2B ; ?q.づ,.......?+ 
00000330h: 5B 06 57 48 29 F4 08 00 00 0A 10 02 D0 7A FE 00 ; [.WH)?.....衵? 
00000340h: 00 00 38 65 01 22 22 01 00 17 B7 95 53 67 FF 84 ; ..8e.""...窌Sg? 
00000350h: 6C 07 EB 00 F8 45 FB F9 15 71 0D A4 C5 2C 00 E8 ; l.?鳨.q.づ,.? 
00000360h: F3 37 75 43 90 00 00 03 00 15 EF AA A8 53 86 01 ; ?uC?....铼⊿? 
00000370h: DD 57 60 00 00 03 01 59 0C F4 3C 00 00 00 33 65 ; 軼`....Y.?...3e 
00000380h: 00 90 88 80 40 05 B7 95 53 67 FF 84 6C 07 EB 00 ; .悎€@.窌Sg刲.? 
00000390h: F8 45 FB F9 15 71 0D A4 C5 2C 00 00 03 00 00 03 ; 鳨.q.づ,...... 
000003a0h: 00 3F 2B 5B 06 57 48 29 F4 08 00 00 0A 10 02 D0 ; .?+[.WH)?.....? 
000003b0h: 7A FE 00 00 00 38 65 00 D8 88 80 40 05 B7 95 53 ; z?..8e.貓€@.窌S 
000003c0h: 67 FF 84 6C 07 EB 00 F8 45 FB F9 15 71 0D A4 C5 ; g刲.?鳨.q.づ 
000003d0h: 2C 00 E8 F3 37 75 43 90 00 00 03 00 15 EF AA A8 ; ,.梵7uC?....铼? 
000003e0h: 53 86 01 DD 57 60 00 00 03 01 59 0C F4 3C 00 00 ; S?軼`....Y.?.. 
000003f0h: 00 F4 08 00 01 33 00 00 17 00 00 00 00 AF 01 27 ; .?..3.......?'

帧数据是将多个 NALU 使用 byte[] {00, 00, 01} 连接的字节数组。

byte[] = {

00,00,01,65,88, 
80,40,05,B7,95,53,67,FF,84,6C,07,EB,00,F8,45,FB, 
F9,15,71,0D,A4,C5,2C,00,00,03,00,00,03,00,3F,2B, 
5B,06,57,48,29,F4,08,00,00,0A,10,02,D0,7A,FE,

00,00,01,65,01,22,22,01,00,17,B7,95,53,67,FF,84, 
6C,07,EB,00,F8,45,FB,F9,15,71,0D,A4,C5,2C,00,E8, 
F3,37,75,43,90,00,00,03,00,15,EF,AA,A8,53,86,01, 
DD,57,60,00,00,03,01,59,0C,F4,3C,

00,00,01,65, 
00,90,88,80,40,05,B7,95,53,67,FF,84,6C,07,EB,00, 
F8,45,FB,F9,15,71,0D,A4,C5,2C,00,00,03,00,00,03, 
00,3F,2B,5B,06,57,48,29,F4,08,00,00,0A,10,02,D0, 
7A,FE,

00,00,01,65,00,D8,88,80,40,05,B7,95,53, 
67,FF,84,6C,07,EB,00,F8,45,FB,F9,15,71,0D,A4,C5, 
2C,00,E8,F3,37,75,43,90,00,00,03,00,15,EF,AA,A8, 
53,86,01,DD,57,60,00,00,03,01,59,0C,F4,3C

};

如果是第一帧数据,那么前面还要加上 CodecPrivateData 数据。

byte[] = {

00,00,01,67,4D,40,15,96,53,01,00,4A,20,

00,00,01,68,E9,23,88,00,

00,00,01,65,88, 
80,40,05,B7,95,53,67,FF,84,6C,07,EB,00,F8,45,FB, 
F9,15,71,0D,A4,C5,2C,00,00,03,00,00,03,00,3F,2B, 
5B,06,57,48,29,F4,08,00,00,0A,10,02,D0,7A,FE,

00,00,01,65,01,22,22,01,00,17,B7,95,53,67,FF,84, 
6C,07,EB,00,F8,45,FB,F9,15,71,0D,A4,C5,2C,00,E8, 
F3,37,75,43,90,00,00,03,00,15,EF,AA,A8,53,86,01, 
DD,57,60,00,00,03,01,59,0C,F4,3C,

00,00,01,65, 
00,90,88,80,40,05,B7,95,53,67,FF,84,6C,07,EB,00, 
F8,45,FB,F9,15,71,0D,A4,C5,2C,00,00,03,00,00,03, 
00,3F,2B,5B,06,57,48,29,F4,08,00,00,0A,10,02,D0, 
7A,FE,

00,00,01,65,00,D8,88,80,40,05,B7,95,53, 
67,FF,84,6C,07,EB,00,F8,45,FB,F9,15,71,0D,A4,C5, 
2C,00,E8,F3,37,75,43,90,00,00,03,00,15,EF,AA,A8, 
53,86,01,DD,57,60,00,00,03,01,59,0C,F4,3C

};

(转)h264中avc和flv数据的解析的更多相关文章

  1. JSON(三)——java中对于JSON格式数据的解析之json-lib与jackson

    java中对于JSON格式数据的操作,主要是json格式字符串与JavaBean之间的相互转换.java中能够解析JSON格式数据的框架有很多,比如json-lib,jackson,阿里巴巴的fast ...

  2. h264 封装 RTMP中FLV数据的解析 rtmp协议简单解析以及用其发送h264的flv文件

    一个完整的多媒体文件是由音频和视频2部分组成的.H264.Xvid等就是视频编码格式,MP3.AAC等就是音频编码格式.字幕文件只是其中附带部分. 把视频编码和音频编码打包成一个完整的多媒体文件,可以 ...

  3. android基础---->JSON数据的解析

    上篇博客,我们谈到了XML两种常用的解析技术,详细可以参见我的博客(android基础---->XMl数据的解析).网络传输另外一种数据格式JSON就是我们今天要讲的,它是比XML体积更小的数据 ...

  4. 嵌入式 H264中的SPS、PPS提取与作用

    使用RTP传输H264的时候,需要用到sdp协议描述,其中有两项:Sequence Parameter Sets (SPS) 和Picture Parameter Set (PPS)需要用到,那么这两 ...

  5. H264中的SPS、PPS提取与作用

    牛逼的视频会议网站:http://wmnmtm.blog.163.com/blog/#m=0 ++++++++++++++++++++++++++++++++++++++++++++++++++++ ...

  6. (转) 从ffmpeg中提取出YUV数据

    有时需要从ffmpeg中提取出YUV数据用作预览,另存什么的. ffmpeg是先解码成YUV, 再以这个YUV作为输入进行编码,所以YUV数据有两种:  解码后的YUV数据, 以及  编码重建的YUV ...

  7. H264中的SPS、PPS提取与作用<转>

    牛逼的视频会议网站:http://wmnmtm.blog.163.com/blog/#m=0 ++++++++++++++++++++++++++++++++++++++++++++++++++++ ...

  8. 分享一个SQLSERVER脚本(计算数据库中各个表的数据量和每行记录所占用空间)

    分享一个SQLSERVER脚本(计算数据库中各个表的数据量和每行记录所占用空间) 很多时候我们都需要计算数据库中各个表的数据量和每行记录所占用空间 这里共享一个脚本 CREATE TABLE #tab ...

  9. struts2中从后台读取数据到<s:select>

    看到网上好多有struts2中从后台读取数据到<s:select>的,但都 不太详细,可能是我自己理解不了吧!所以我自己做了 一个,其中可能 有很多不好的地方,望广大网友指出 结果如图 p ...

随机推荐

  1. Eloqument 学习

    参考地址:https://d.laravel-china.org/docs/5.5/eloquent#mass-assignment

  2. HDU 4614 Vases and Flowers(线段树+记录区间始末点或乱搞)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4614 题目大意:有n个空花瓶,有两种操作: 操作①:给出两个数字A,B,表示从第A个花瓶开始插花,插B ...

  3. Synergy,一个软件团队质量改进之路之一 --- 规划

    关于质量改进 ISO9001:2000的核心思想是持续改进 ISO关于质量管理有8项原则: 原则一: 以顾客为关注焦点 原则二: 领导作用 原则三: 全员参与 原则四: 过程方法 原则五:管理的系统方 ...

  4. booklist for machine learning

    Recommended Books Here is a list of books which I have read and feel it is worth recommending to fri ...

  5. WP主题模板制作修改教程

    WP主题模板制作修改教程 实际上,当我们打开某个主题的文件夹时,看到的并不止这两个文件,而是更多.但一般来说,在一个完整的 WP 主题文件夹中都应该包含下列文件(也称为模板文件):页面 模板文件 用途 ...

  6. awk书上练习

    文件car: plym fury chevy malibu ford mustang volvo s80 ford thundbd chevy malibu bmw 325i honda accord ...

  7. JavaScript 中的原型(总则)

    1. 一切函数都是对象 2. 一切对象都是由函数创建的,所有函数都是由Function创建的,每个函数都是一个Function对象. 3. 对象.__proto__ === 函数.prototype ...

  8. [转]C/C++关于全局变量和局部变量初始化与不初始化的区别

    原文链接:http://www.kingofcoders.com/viewNews.php?type=newsCpp&id=189&number=4836955386 在C语言里,全局 ...

  9. easyui layout 左右面板折叠后 显示标题

    (function($){ var buttonDir = {north:'down',south:'up',east:'left',west:'right'};    $.extend($.fn.l ...

  10. Django学习笔记-2018.11.17

    URL配置: 项目下的urls.py配置的为URL总路径,在使用第二种方法在app下配置的urls.py是在总路径下的分路径 Templates: DTL初步使用 render()函数支持dict类型 ...