H.264 媒体流 AnnexB 和 AVCC 格式分析 及 FFmpeg 解析mp4的H.264码流方法
H264码流分两种组织方式,一种是AnnexB格式,一种是AVCC格式。
作者:码农小明
来源:https://blog.csdn.net/shaosunrise/article/details/121548065
首先要了解的是H.264编码规范只是规定了如何编码,并没有规定以何种方式来排列编码后的数据。
就如同AES算法只是规定如何加密一组数据,并没有强制规定如果分组。H.264规范没有规定如何组织数据,但是在附录B中提供了一种可选方案,即Annex B格式。
H.264 NALU 概念
H.264视频编码后的数据叫 NALU(Network Abstraction Layer Units)
。
NALU有多种类型,分为两大类:VCL(Video Coding Layer)
和 非VCL
。VCL是图像编码数据,非VCL为编码参数信息。
NALU结构头部指明类型,类型字段如下。
SPS:序列参数集,包含解码配置,比如profile level 分辨率和帧率等。
PPS:图像参数集,包含有关熵编码模式、分片组、运动预测和去块滤波器等信息。
IDR: 立即解码刷新单元,这种NALU包含一个完整的图像序列,不依赖其他NALU就可以独立解码和显示,即一种特殊的I帧。
值得注意的是,一个NALU即使是VCL NALU 也并不一定表示一个视频帧。因为一个帧的数据可能比较多,可以分片为多个NALU来储存。一个或者多个NALU组成一个访问单元AU,一个AU包含一个完整的帧。
H.264 码流格式
H264码流分两种组织方式,一种是AnnexB格式,一种是AVCC格式。
AnnexB格式
[start code]NALU | [start code] NALU |...
这种格式比较常见,也就是我们熟悉的每个帧前面都有0x00 00 00 01
或者0x00 00 01
作为起始码。
h264文件就是采用的这种格式,每个帧前面都要有个起始码。
SPS PPS等也作为一类NALU存储在这个码流中,一般在码流最前面。也就是说这种格式包含VCL 和 非VCL 类型的NALU。
AVCC格式
([extradata]) | ([length] NALU) | ([length] NALU) | ...
这种模式也叫AVC1格式,没有起始码,每个帧最前面几个字节(通常4字节)是帧长度。
这里的NALU一般没有SPS PPS等参数信息,参数信息属于额外数据extradata存在其他地方。
比如ffmpeg中解析mp4文件后sps pps存在streams[index]->codecpar->extradata;中。
也就是说这种码流通常只包含VCL类型NALU。
这些extradata通常有如下格式(可以根据这个规则ffmpeg解析mp4文件的SPS和PPS)
第1字节:version (通常0x01)
第2字节:avc profile (值同第1个sps的第2字节)
第3字节:avc compatibility (值同第1个sps的第3字节)
第4字节:avc level (值同第1个sps的第3字节)
第5字节前6位:保留全1
第5字节后2位:NALU Length 字段大小减1,通常这个值为3,即NAL码流中使用3+1=4字节表示NALU的长度
第6字节前3位:保留,全1
第6字节后5位:SPS NALU的个数,通常为1
第7字节开始后接1个或者多个SPS数据SPS结构 [16位 SPS长度][SPS NALU data]SPS数据后
第1字节:PPS的个数,通常为1
第2字节开始接1个或多个PPS数据PPS结构 [16位 PPS长度][SPS NALU data]
FFmpeg解析mp4中H.264 码流
MP4文件中编码信息是存储在文件开始或者文件末尾的,详细结构这里不详述了。就知道不是和图像数据放在一起的就可以了。FFmpeg使用av_read_frame(AVFormatContext *s, AVPacket *pkt)函数读mp4文件,读到packet里面仅仅是VCL编码数据NAL,并且这个编码数据是AVCC格式组织的码流,直接保存成.264文件没法播放。
先说一下思路:
1 .从avFmtCtx->streams[_videoStreamIndex]->codecpar->extradata中解析SPS和PPS数据,数据格式上一节已经描述了。解析出SPS PPS数据加上4字节的0001的起始码拼装成nnexB格式的NALU,先写入文件。
通过av_read_frame(AVFormatContext *s, AVPacket *pkt)读取到数据存放在pkt->data中,长度为pkt->size。
注意:这1个pkt->data中的数据可能是多个NALU的数据!!!这些数据按([length] NALU) | ([length] NALU) | ...规则排列。先取前4字节作为长度,读取指定长度的数据加上起始码拼NALU。然后同样的方式读取后面的数据,直到总长度等于pkt->size。
FFmpeg 解析mp4中H264码流 代码示例
这里就只贴关键部分代码。省略前面打开文件和查询流信息等操作。
//...AVPacket spsPacket, ppsPacket, tmpPacket;uint8_t startCode[4] = {0x00, 0x00, 0x00, 0x01};bool sendSpsPps = false;while (av_read_frame(_avFmtCtx, _avPacket) == 0) { // 能读到数据返回0,循环读取// 根据pkt->stream_index判断是不是视频流if (_avPacket->stream_index == _videoStreamIndex) {// 仅1次处理sps pps,也可以拿在while外面if (!sendSpsPps) { int spsLength = 0;int ppsLength = 0;// extradata 数据指针,方便操作取其指针uint8_t *ex = _avFmtCtx->streams[_videoStreamIndex]->codecpar->extradata;// extradata;第6字节后5位表示SPS个数,通常为1,这里就省略判断处理,严谨期间还是要判断// 直接 取第7 8 俩字节作为SPS长度spsLength = (ex[6] << 8) | ex[7];// x[8+spsLength]表示PPS个数,通常为1,这里就省略判断处理// 取接下来两位作为PPS长度ppsLength = (ex[8 + spsLength + 1] << 8) | ex[8 + spsLength + 2];// 为spsPacket ppsPacket的data分配内存,类似malloc// 如果只是为了保存文件,可以不使用pkt结构,直接malloc就行// 分配的空间为sps或pps长度加上4字节的起始码av_new_packet(&spsPacket, spsLength + 4);av_new_packet(&ppsPacket, ppsLength + 4);// 给SPS拼前4字节起始码memcpy(spsPacket.data, startCode, 4);// 把SPS数据拼在起始码后面memcpy(spsPacket.data + 4, ex + 8, spsLength);// TODO: 这里可以把spsPacket.data数据写入文件 // 给PPS拼前4字节起始码memcpy(ppsPacket.data, startCode, 4);// 把PPS数据拼在起始码后面memcpy(ppsPacket.data + 4, ex + 8 + spsLength + 2 + 1, ppsLength);// TODO: 这里可以把ppsPacket.data数据写入文件 sendSpsPps = true;}// 下面处理读到pkt中的数据int nalLength = 0;uint8_t *data = _avPacket->data;// _avPacket->data中可能有多个NALU,循环处理while (data < _avPacket->data + _avPacket->size) {// 取前4字节作为nal的长度nalLength = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];if (nalLength > 0) {memcpy(data, startCode, 4); // 拼起始码tmpPacket = *_avPacket; // 仅为了复制packet的其他信息,保存文件可忽略tmpPacket.data = data; // 把tmpPkt指针偏移到实际数据位置tmpPacket.size = nalLength + 4; // 长度为nal长度+起始码4//TODO: 处理这个NALU的数据,可以直接把tmpPacket.data写入文件}data = data + 4 + nalLength; // 处理data中下一个NALU数据}}av_packet_unref(_avPacket);}
上述代码FFmpeg 4.4使用正常。
此外,FFmpeg也提供了h264_mp4toannexb_filter相关的过滤器进行相应转换的操作,这里不示例怎么用了。
最后欢迎大家加入 音视频开发进阶 知识星球 ,这里有知识干货、编程答疑、开发教程,还有很多精彩分享。
更多内容可以在星球菜单中找到,随着时间推移,干货也会越来越多!!!
给出 10元 优惠券,涨价在即,目前还是白菜价,基本上提几个问题就回本,投资自己就是最好的投资!!!
加我微信 ezglumes ,拉你进技术交流群
推荐阅读:
音视频开发工作经验分享 || 视频版
OpenGL ES 学习资源分享
开通专辑 | 细数那些年写过的技术文章专辑
Android NDK 免费视频在线学习!!!
你想要的音视频开发资料库来了
推荐几个堪称教科书级别的 Android 音视频入门项目
觉得不错,点个在看呗~
H.264 媒体流 AnnexB 和 AVCC 格式分析 及 FFmpeg 解析mp4的H.264码流方法相关推荐
- python 读取文件读出来是什么格式-深入学习python解析并读取PDF文件内容的方法...
这篇文章主要学习了python解析并读取PDF文件内容的方法,包括对学习库的应用,python2.7和python3.6中python解析PDF文件内容库的更新,包括对pdfminer库的详细解释和应 ...
- 用于MPEG-4视听流的RTP负载格式
MPEG-4的rtp协议封装 英文原版 RFC 3016:http://www.rfc-editor.org/rfc/rfc3016.txt 中文翻译: 组织:中国互动出版网(http://www.c ...
- 码流格式: Annex-B, AVCC(H.264)与HVCC(H.265), extradata详解
1.前言 介绍H.264结构的文章铺天盖地,无责任翻译.无责任转载以及部分经验之谈(目前搜索最靠前的一篇实际是对stackoverflow上答案的翻译..链接后面给出了),所以缺的不是资料,是叙述准确 ...
- 五. H.264的码流封装格式
H.264的语法元素进行编码后,生成的输出数据都封装为NAL Unit进行传递,多个NAL Unit的数据组合在一起形成总的输出码流.对于不同的应用场景,NAL规定了一种通用的格式适应不同的传输封装类 ...
- nalu格式annex-B和avcc
一 annexb和avcc Annexb 视频编码成的包叫做Network Abstraction Layer Units, 也简称为NALU.NAL,每个NALU包都可以被单独的解析和处理,每个NA ...
- H.264基础知识及视频码流解析
H.264基础知识及视频码流解析 目录 H.264概述 H264相关概念 H264压缩方式 H264分层结构 H264码流结构 H264的NAL单元 H.264视频码流解析及代码实现 1. H.264 ...
- 原始 H.264 码流播放
我们平时遇到的视频文件各式各样,五花八门.通常它们会根据格式的不同,而有着不同的扩展名,比如 avi,rmvb,mkv,mp4 等等等.这些格式代表的都是 封装格式. 这些文件通常产生的过程是这样的: ...
- 视音频数据处理入门:H.264视频码流解析
===================================================== 视音频数据处理入门系列文章:视音频数据处理入门:RGB.YUV像素数据处理视音频数据处理入门 ...
- 【数据压缩】H.264文件解析和码流分析
一.实验课要求 选择一个.mp4或者.264文件. 在码流分析仪软件中打开该文件,从几个层次进行分析: 分析SPS和PPS里都包含哪些主要的信息,给出参数值.(例如分辨率.帧率.GOP结构等等) 以一 ...
最新文章
- IntelliJ 发布 2020 RoadMap,中文版终于要来了?
- Weblogic配置故障转移
- Python内置函数zip map filter的使用
- ESB学习笔记(Spring Integration实战)
- Photoshop的基本操作
- Python3 爬虫学习笔记 C11【数据储存系列 — MongoDB】
- Linux内核网络数据包处理流程
- Qt实践录:一些界面设计的记录示例
- thinkphp系统常量与自定义常量
- [Telink][TLSR8251] [泰凌微][SDK3.4] 上手第二步 框架介绍
- TscanCode代码扫描工具
- IE浏览器验证码不刷新
- 基于captcha的图形验证码实现
- 银光团队项目正式启动,欢迎您的参与!
- 【无标题】求X的n次方函数
- 根据ip查询地理位置
- 【2G模组Air202开发】Lua脚本编程实现MQTT协议连接Tlink平台(三)
- 没有足够的内存继续执行程序.(mscorlib)
- 专家观点:Facebook的衰落
- 在10Gbps网络下开启Huawei CE6850交换机的ECN功能并实验DCTCP协议