前面写了flv文件的解析,有h264裸流的话就开始封装吧。网上大多数都是用ffmeg库来做这个工作的,哎,学习资料少学不会,还是自己动手吧。

封装前要先了解下h.264格式,只需要知道一点点就可以了,我看了h.264官方文档,我靠,3百多页,还全是中文,什么,是中文?既然是中文的我就勉强看下吧,我靠,看起来还很复杂的,果断不看了,不需要,也没时间,我又不做解码,这东西具体步骤资料又少,基本都是那一两篇转来转去,这还要感谢我上一篇提到的那个连接的兄弟,记录下过程,不然以后就忘干净了。
h264是一个个NALU单元组成的,每个单元以00 00 01 或者 00 00 00 01分隔开来,每2个00 00 00 01之间就是一个NALU单元。我们实际上就是将一个个NALU单元封装进FLV文件。
每个NALU单元开头第一个byte的低5bits表示着该单元的类型,即NAL 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。
前一章说到如果数据是AAC或者AVC的话,则有一个音频和视频的配置信息需要写入前两个tag(metadata之后),AAC音频就不说了,在ISO-14496-3 Audio 中有描述,给一张图。
说下AVC视频流的configuretion,ISO-14496-15 AVC file format 有详细描述,先给两张图,一张是说明,一张是实际截图。
这个例子是对应我第一个截图来的,一般h264数据最开始的两个NALU就是PSP和PPS,但是我现在还没有明白为什么我的那个h264裸流在开始的时候会有两个SPS、PPS,而且之后数据还会不时的出现,但是我没有管这个,依然只各弄了一个进去,其他的忽略掉了,反正多余的我都忽略了,也没发现有什么错。反正首先把音视频的配置信息封进metadata之后的tag,然后就可以封数据了。再说下元数据,flv header之后就是它了,再之后就是音视频配置信息,再后面就是音视频数据,元数据前一章说了是amf格式的,安格式封就行了,测试其实没有元数据视频也可以正常播放,等会再简单说下amf吧。

现在开始封装h264数据吧,前一章提到了flv关于AVC的格式,除开元数据,其他数据是:一个byte的video信息+一个byte的AVCPacket type+3个bytes的无用数据(composition time,当AVC时无用,全是0)+ 4个bytes的NALU单元长度 + N个bytes的NALU数据,所以包头数据长度信息是刚才提到的信息的总和长度。要强调下,当音视频配置信息tag的时候,是没有4个bytes的NALU单元长度的。
AVC的配置信息时,先上一个图,
17 -- 高4bits:1,keyframe。 低4bits:7,代表AVC。 后面一个byte 0x00,AVCPacket type,代表AVC sequence header。后3个bytes无意义,之后就是decoder configuration record的内容了。 图中绿色后面 00 00 00 28就是前面tag的总长度。

当NALU第一个byte xx & 0x1f == 5的时候,说明该单元是一个I frame,关键帧
17 -- 和上面的一样。 01 -- AVC NALU。蓝色框内的4个bytes记录后面NALU数据的长度。65 & 0x1f == 5.
如果NALU第一个byte xx & 0x1f != 5的时候,就不是一个I frame
27 -- 高4bits:2,inter frame ,P frame。 低4bits:7,AVC NALU。其他都一样。图中绿色后面 00 00 00 28就是前面tag的总长度。
整个的flv文件其实是:FLV header + previous tag size0 + tag1 + previous tag size1 + tag2 + previous tag size2 + ... +tagN + previous tag sizeN。
tag1是metadata,记录视频的一些信息;tag2是视频配置信息(AVC decoder configuration record),tag3是音频配置信息(如果没有音频则去掉此项),tag4以及之后的tag就是音视频数据了。
每一个结构怎么封都说清楚了,安上面的步骤一个一个NALU封就行了。
封包的时候要特别注意一下包头里面的时间戳,因为这个控制着播放的速度,如果不填,全是0的话,播放会相当快,一般按视频帧率来设置。我这个h264流是8帧的,所以我每个tag的时间间隔是125ms左右。
注意了,flv里面的数据都是大端模式,放数据进去要转换一下,如果你是通常的小端的机器的话。
到这里应该差不多了吧,我是一个NALU单元封装成一个tag,我也是刚接触,不知道上述还有哪些地方不合理,不过测试没有发现问题。我也才接触这东西,如果有知情人,望解释一下为什么有多个PPS SPS,谢谢。
至于rtmp协议发送flv,之后再写吧。

转载于:https://www.cnblogs.com/GoAhead/archive/2012/12/21/2828066.html

(转载)将h.264视频流封装成flv格式文件(二.开始动手)http://blog.csdn.net/yeyumin89/article/details/7932431...相关推荐

  1. 将h.264视频流封装成flv格式文件(一.flv格式)

    原帖地址:http://blog.csdn.net/yeyumin89/article/details/7932368 原帖虽然贵为好贴,看感觉看起来有点乱,没有层次感,贴过来,修改下格式,阅读起来方 ...

  2. 将h.264视频流封装成flv格式文件

    https://blog.csdn.net/leixiaohua1020/article/details/84519384 https://blog.csdn.net/xin_hua_3/articl ...

  3. Ubuntu安装软件是始终出现dpkg错误(转载,原文链接:https://blog.csdn.net/cyf15238622067/article/details/53534629)

    Ubuntu安装软件是始终出现dpkg错误 一.设置镜像 二. 出现错误死循环时,使用下述命令 sudo dpkg -i --force-overwrite sudo dpkg -i --force- ...

  4. Android Volley完全解析(二),使用Volley加载网络图片 转载:http://blog.csdn.net/guolin_blog/article/details/174

    转载:http://blog.csdn.net/guolin_blog/article/details/17482165 在上一篇文章中,我们了解了Volley到底是什么,以及它的基本用法.本篇文章中 ...

  5. Android Volley完全解析(一),初识Volley的基本用法 转载地址:http://blog.csdn.net/guolin_blog/article/details/17482095

    转载地址:http://blog.csdn.net/guolin_blog/article/details/17482095 1. Volley简介 我们平时在开发Android应用的时候不可避免地都 ...

  6. 从request获取各种路径总结 转载:http://blog.csdn.net/piaoxuan1987/article/details/8541839 equest.getRealPath()

    https://www.cnblogs.com/hello-yao-ge/p/6606564.html 转载:http://blog.csdn.net/piaoxuan1987/article/det ...

  7. Win10双击调试 转载 http://blog.csdn.net/sagittarius_warrior/article/details/51305046

    转:注1:本文非本人所写,尊重原作者劳动成果.仅是对原文备份. http://blog.csdn.net/sagittarius_warrior/article/details/51305046(原来 ...

  8. WordPress数据库的基本构造(转载自http://blog.csdn.net/ppiao1970hank/article/details/6301812)...

    转载自http://blog.csdn.net/ppiao1970hank/article/details/6301812 WordPress使用MySQL数据库.作为一个开发者,我们有必要掌握Wor ...

  9. 手机网络抓包 转载记录http://blog.csdn.net/skylin19840101/article/details/43485911

    Fiddler不但能截获各种浏览器发出的HTTP请求, 也可以截获各种智能手机发出的HTTP/HTTPS请求.Fiddler能捕获IOS设备发出的请求,比如IPhone, IPad, MacBook. ...

  10. 转载 http://blog.csdn.net/dengta_snowwhite/article/details/6418384

    从SDCard保存的txt文件读取中文到android系统中会出现乱码问题,如何解决这个乱码问题,网上有不少解答方法,譬如说利用String temp1 =EncodingUtils.getStrin ...

最新文章

  1. Java注解---通俗易懂
  2. Asp.net中Postback及Callback
  3. 如何在电脑上使用python-如何在Windows上使用Python进行开发
  4. 基于组合遗传粒子群算法的旅行商问题求解
  5. mysql各种联结的区别_mysql几种连接方式区别
  6. HDU 1754线段树
  7. Pytorch基础(五)nn模块及optimizer
  8. Andrew Ng机器学习公开课笔记 -- 朴素贝叶斯算法
  9. 使用NodeJS调用Dubbo工程
  10. linux开发环境搭建(4)-从SD卡启动uboot
  11. C与指针——指针(一)
  12. Spark快速大数据分析——Spark的Hadoop配置(肆)
  13. [转载] 信息系统项目管理师论文范例:论软件项目的进度管理
  14. 编译开源路由下iNode客户端njit8021xclient
  15. 计算机语言分几级,计算机语言分为三类:机器语言、低级语言和高级语言。()...
  16. php密码如何用星号表示,输入密码显示星号的写法实例
  17. C++游戏《Flappy bird》
  18. 搜狗泛站怎么做?搜狗泛域名泛目录收录方法
  19. 003竞品分析的思考、理解和一些框架
  20. 编写名为censor的函数,用来把字符串中出现的每一处字母“foo”替换成“xxx”。例如,字符串“food fool”会变为“xxxd xxxl”。再不失清晰性的前提下程序越短越好

热门文章

  1. EMNLP 2020 可解释性推理
  2. 【NLP基础】信息抽取(Information Extraction:NER(命名实体识别),关系抽取)
  3. 深度学习14-实战三-Google涂鸦识别挑战项目(上)
  4. bug2-Internal Error: Blas GEMM launch failed 问题
  5. 机器学习实战笔记1-机器学习基础
  6. Pytorch中RNN输出的h_n和output是什么
  7. 一文掌握 Docker 技术体系
  8. 业务请求量膨胀的扩容技术实践
  9. 真·不怪云原生:探寻IT大厂逐渐云化的秘密!
  10. 移动Web界面样式-CSS3