H264-AAC 格式解析
一、H264的一些概念
本文章不在于写多么专业的知识理论,只是为了记录自己的所见所闻并让初学者能从很简单快捷的认识到H264,不至于一说这些东西都高大上不容易理解。有句话说无人教入门很难,有人教三分钟即会。
1.脱壳操作
在编码时,每遇到两个字节连续为0,就插入一个字节的0x03。解码时将0x03去掉。 也称为脱壳操作。
2.分层
H.264的功能分为两层,视频编码层(VCL) 和网络提取层 (NAL)
VCL:通俗的讲就是编码后输出的数据,但是VCL数据是没法在网络中直接传送的,这时候就需要网络提取层NAL
NAL:在VCL数据传输或存储之前,需要封装成NAL单元再在网络中传送
二、NAL单元格式:
NAL单元序列是由一系列的NAL组成
NAL分为三部分:StartCode、NAL头与RBSP
NAL头:1字节,也由三部分组成
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
禁止位 |
重要标识 |
载荷数据类型 |
1.forbidder_bit(1bit) :禁止位
编码中默认值为0,当网络识别此单元中存在比特错误时,可将其设为1,以便接收方丢掉该单元,主要 用于适应不同种类的网络环境(比如有线无线相结合的环境)。
2.nal_reference_bit(2bit):优先级
用于在重构过程中标记一个NAL单元的重要性,值越大,越重要。值为0表示这个NAL单元没有用于预测,因此可被解码器抛弃而不会有错误扩散;值高于0表示此NAL单元要用于无漂移重构,且值越高,对此NAL单元丢失的影响越大。
3.nal_unit_type(5bit):类型
可以表示NALU的32种不同类型特征,类型1~12是H.264定义的,类型24~31是用于H.264以外的,RTP负荷规范使用这其中的一些值来定义包聚合和分裂,其他值为H.264保留。
nal_unit_type |
NAL类型 |
0 |
未使用 |
1 |
不分区、非IDR图像的片 |
2 |
片分区A |
3 |
片分区B |
4 |
片分区C |
5 |
IDR图像的片 |
6 |
补充增强信息单元(SEI) |
7 |
序列参数集 |
8 |
图像参数集 |
9 |
分解符 |
10 |
序列结束 |
11 |
码流结束 |
12 |
填充 |
13..23 |
保留 |
24..31 |
未使用 |
RBSP的组成
SPS |
SEI |
PPS |
I片 |
图像定界符 |
P片 |
P片 |
RBSP序列举例 |
常见的H264的数据格式
00 00 00 01 67 (SPS)
00 00 00 01 68 (PPS)
00 00 00 01 65 ( IDR 帧,也就是常说的I帧)
00 00 00 01 61 (P帧)
00 00 00 01 41 (不分区、非IDR图像的片)
我遇到的H264一般都是 67 68 65 41 41 41 ....
67的各种进制表示
禁止位:0
优先级位:11
类型:00111 十进制位7也就是SPS
- 7为序列参数集(SPS),
- 8为图像参数集(PPS),
- 5代表I帧。
- 1代表非I帧。
由此可知,61和41其实都是P帧(type值为1),只是重要级别不一样(它们的NRI一个是11BIN,一个是10BIN)
实际电脑摄像头数据分析
我的电脑摄像头采集的都是67 68 65 65 41 41 ... 67 68 65 65 41 41 ...
分割符都是四个字节 00 00 00 01,发现67 68 的分隔符都是4个字节,但是65 与 41 的分隔符就有可能是3个字节即 00 00 01
解析SPS,PPS
/// <summary>
/// 获取关键帧中的sps,pps,该方法自动解析了分隔符长度
/// </summary>
/// <param name="rawData">收到的实际数据</param>
/// <returns>这个返回值也可以作为判断关键帧来使用,因为sps,pps应该算关键帧里的</returns>
public static true GetSPS_PPS(byte[] rawData, out byte[] sps, out byte[] pps)
{try{int i = 0;int spsIndex = 0; //sps的索引位置(即67的索引位置)int ppsIndex = 0; //pps的索引位置(即68的索引位置)int keyIndex = 0; //关键帧的索引位置(即65的索引位置)int ppsSeparatorLen = 3; //SPS,PPS的分隔符长度int keySeparatorLen = 3; //数据的分隔符长度while (i < rawData.Length - 3){if (rawData[i] == 0 && rawData[i + 1] == 0 && rawData[i + 2] == 1){if ((rawData[i + 3] & 0x1f) == 5 || (rawData[i + 3] & 0x1f) == 6) //{keyIndex = i + 3;if (rawData[i - 1] == 0){keySeparatorLen = 4;}break;}if ((rawData[i + 3] & 0x1f) == 7){spsIndex = i + 3;}else if ((rawData[i + 3] & 0x1f) == 8){ppsIndex = i + 3;if (rawData[i - 1] == 0){ppsSeparatorLen = 4;}}}i++;}sps = new byte[ppsIndex - spsIndex - ppsSeparatorLen];Array.Copy(rawData, spsIndex, sps, 0, sps.Length);pps = new byte[keyIndex - ppsIndex - keySeparatorLen];Array.Copy(rawData, ppsIndex, pps, 0, pps.Length); return true;}catch (Exception e){Console.WriteLine(e);} sps = new byte[0]; pps = new byte[0];return false;
}
三、AAC 音频
AAC有两种格式一种是ASIF格式另一种是ADTS格式,ASIF格式只有一个信息头,所以在解码的时候只能从头开始,改格式一般用在磁盘中。ADTS格式是每帧都带有消息头,所以呢可以从ADTS格式的任意帧开始解码。ADTS是帧序列,本身具备流特征,在音频流的传输与处理方面更加合适。
ADTS结构
AAC的前7个字节也就是ADTS头
实际数据: adts:FF F1 54 40 40 01 00
都是以FFF开头,也特别好认,可以直接把收到的AAC音频存到文件里用播放器就可以播放
ADTS分为两部分:
第一部分:adts fixed header
采样率
根据sampling frequency index 采样率下标在下面可以找到对应的采样率
- 0: 96000 Hz
- 1: 88200 Hz
- 2: 64000 Hz
- 3: 48000 Hz
- 4: 44100 Hz
- 5: 32000 Hz
- 6: 24000 Hz
- 7: 22050 Hz
- 8: 16000 Hz
- 9: 12000 Hz
- 10: 11025 Hz
- 11: 8000 Hz
- 12: 7350 Hz
- 13: Reserved
- 14: Reserved
- 15: frequency is written explictly
channel configuration: 声道数
- 0: Defined in AOT Specifc Config
- 1: 1 channel: front-center
- 2: 2 channels: front-left, front-right
- 3: 3 channels: front-center, front-left, front-right
- 4: 4 channels: front-center, front-left, front-right, back-center
- 5: 5 channels: front-center, front-left, front-right, back-left, back-right
- 6: 6 channels: front-center, front-left, front-right, back-left, back-right, LFE-channel
- 7: 8 channels: front-center, front-left, front-right, side-left, side-right, back-left, back-right, LFE-channel
- 8-15: Reserved
第二部分 adts variable header
解析adts header
#region Get information form AAC Header
/// <summary>
/// 解析AAC头,从中拿到如下几个播放信息
/// </summary>
/// <param name="adtsHeader">adts Header,音频的前7个字节</param>
/// <param name="id">MPEG Version: 0 for MPEG-4, 1 for MPEG-2</param>
/// <param name="profile">表示使用哪个级别的AAC,有些芯片只支持AAC LC 。在MPEG-2 AAC中定义了3种:</param>
/// <param name="acquisitionRate">表示使用的采样率下标,通过这个下标在 Sampling Frequencies[ ]数组中查找得知采样率的值</param>
/// <param name="channel">表示声道数 </param>
/// <param name="frame_length"> 一个ADTS帧的长度包括ADTS头和AAC原始流.</param>
public void AnalysisAACHeader(byte[] adtsHeader, out int id, out int profile, out int acquisitionRate, out int channel, out int frameLength)
{id = (int)((adtsHeader[1] & 0x08) >> 3);profile = (int)((adtsHeader[2] & 0xc0) >> 6);acquisitionRate = (int)((adtsHeader[2] & 0x3c) >> 2);GetacquisitionRate(ref acquisitionRate);channel = (int)(adtsHeader[2] & 0x01) << 2 | (int)((adtsHeader[3] & 0xc0) >> 6);frameLength = ((int)(adtsHeader[3] & 0x03) << 8) | ((int)(adtsHeader[4] & 0xe0) << 3) | ((int)(adtsHeader[4] & 0x1f) << 3) | (int)((adtsHeader[5] & 0xe0) >> 5);
}/// <summary>
/// 解析AAC头,从中拿到如下几个播放信息
/// </summary>
/// <param name="acquisitionRate">采样率索引</param>
public void GetacquisitionRate(out int acquisitionRate)
{acquisitionRate = 0;switch (acquisitionRate){case 0:acquisitionRate = 96000;break;case 1:acquisitionRate = 88200;break;case 2:acquisitionRate = 64000;break;case 3:acquisitionRate = 48000;break;case 4:acquisitionRate = 44100;break;case 5:acquisitionRate = 32000;break;case 6:acquisitionRate = 24000;break;case 7:acquisitionRate = 22050;break;case 8:acquisitionRate = 16000;break;case 9:acquisitionRate = 12000;break;case 10:acquisitionRate = 11025;break;case 11:acquisitionRate = 8000;break;}
}
#endregion
H264-AAC 格式解析相关推荐
- FLV文件(H264 + AAC)格式超详细分析
最近自己动手将H264视频流和AAC音频流合成flv文件,但是没有采用开源的ffmpeg的api来处理音视频流.方法就是模仿ffmpeg中libavformat/flvenc.c 文件写代码来完成音视 ...
- 【音频】AAC格式解析
一.AAC概述 AAC是高级音频编码(Advanced Audio Coding)的缩写,出现于1997年,最初是基于MPEG-2的音频编码技术.由Fraunhofer IIS.Dolby Labor ...
- 人肉解析系列(一)————FLV-java你所关心的,我这里都有。附源码。非FFmpeg相关,纯java人肉解析。手写FLV。H264 AAC转FLV
第一次写博客,不知道有没有什么潜规则.总之呢,是好是坏都已经在落笔的那一刻开始了. 说起直播,各位都不陌生,毕竟国内这几年直播,短视频等视频行业大火,让所有程序员对直播都能如数家珍,随口便能讲出几种协 ...
- h264和aac格式介绍及mp4文件的封装
mp4封装 目录 h264视频流格式介绍 aac音频流格式介绍 h264视频文件读取 通过帧索引解析h264文件 通过解析h264结构读取文件 aac音频文件读取 mp4封装 初始化 数据封装 关闭m ...
- 【Android RTMP】音频数据采集编码 ( AAC 音频格式解析 | FLV 音频数据标签解析 | AAC 音频数据标签头 | 音频解码配置信息 )
文章目录 安卓直播推流专栏博客总结 一. AAC 音频格式解析 二. FLV 音频数据标签解析 1. 分析 FLV 格式中的 AAC 音频格式数据 2. AAC 音频特殊配置 3. AAC 音频数据标 ...
- 多媒体音频格式解析WMA WAV OGG AAC APE FLAC
无论是MP3还是MP4,甚至手机和多媒体DC,产品所支持的各种格式往往让人眼花缭乱.特别是对于刚上手的新手玩家来说,各种格式都有哪些特性,在实际 使用当中有多少格式实用或者必须,其实有很多方面需要我们 ...
- 海康摄像头PS流格式解析(RTP/PS/H264)
海康威视视频录像以PS格式打包,解析的过程按照PS包-->system header--->program stream map--->音视频PES包一路下来,海康在包中自定义了一些 ...
- MP3、AAC、WMA、Ogg、MPC、WAV、FLAC、APE、WV、CD、MIDI、RealVideo等音频格式解析及对比
音频格式详解 无论是随身听还是手机或者是多媒体DC,产品支持的音频格式多样,然而它们都有各自的特性.我们在应用中选择的时候必须考虑到各种格式的适用场合,这要求我们对很多方面有个系统的了解. 有损压缩格 ...
- AAC音频格式解析(ADTS)
一.AAC文件头信息 1.1 adts_fixed_header 1.2 adts_variable_header 二.代码实现结合 FFmpeg 保存AAC 文件 2.1 FFmpeg读取 AAC数 ...
- 1小时学会:最简单的iOS直播推流(八)h264/aac 软编码
最简单的iOS 推流代码,视频捕获,软编码(faac,x264),硬编码(aac,h264),美颜,flv编码,rtmp协议,陆续更新代码解析,你想学的知识这里都有,愿意懂直播技术的同学快来看!! 源 ...
最新文章
- hdu 2665(主席树查询区间k大值)
- STM32产品名称命名规则
- [XSY] 最长公共子串对(后缀自动机)
- Python语法异常 Exception
- Anaconda中如何查看已经安装的包
- java实现代理服务器,接收客户端连接,发送到对应服务器
- (教程)手把手教你如何申请软件著作权
- 半正定矩阵的对角元素不小于该矩阵的最小特征值
- 主成分与因子分析异同_主成分和因子分析原理及比较
- Java为Excel导出增加批注(POI)
- Win11更新提示安装错误0x80248007怎么办?0x80248007下载错误解决方法汇总
- boost中regex使用时出现的问题
- 同花顺资金监测精鹰指标公式源码 通过资金监测强弱
- devcpp中使用unordered_map
- 计算机专业逻辑推理题,逻辑推理试题
- 解决win7系统电脑右下角小喇叭有个小叉
- 一篇文章讲清NB-IoT技术
- OCR财务报表识别方案
- 百度ECharts图形报表的介绍以及应用案例理解
- kaliWEB渗透笔记
热门文章
- 还是忍不住转下 --你喜欢的只是那个不喜欢你的她
- 五大常用办公软件-office办公软件
- Max动画分割脚本 Unity 自动识别动画分割信息
- 从授时服务器上获得时间
- 缘灭--HashMap底层原理之1.8put源码篇(三)
- 首款MeeGo系统上网本 华硕Eee PC X101H独家首测(1)
- ZOJ 3899 State Reversing【NTT】
- 图解 K8S(04):吃透 Pod 中的第三类容器 -- init 容器
- 利用计算机解决古代数学问题鸡兔同笼,古代数学-鸡兔同笼:7种解法,你发现了几种呢?...
- 【游戏开发】多人游戏网络同步相关技术(设计篇)