一、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保留。

nalu type

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的组成

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 格式解析相关推荐

  1. FLV文件(H264 + AAC)格式超详细分析

    最近自己动手将H264视频流和AAC音频流合成flv文件,但是没有采用开源的ffmpeg的api来处理音视频流.方法就是模仿ffmpeg中libavformat/flvenc.c 文件写代码来完成音视 ...

  2. 【音频】AAC格式解析

    一.AAC概述 AAC是高级音频编码(Advanced Audio Coding)的缩写,出现于1997年,最初是基于MPEG-2的音频编码技术.由Fraunhofer IIS.Dolby Labor ...

  3. 人肉解析系列(一)————FLV-java你所关心的,我这里都有。附源码。非FFmpeg相关,纯java人肉解析。手写FLV。H264 AAC转FLV

    第一次写博客,不知道有没有什么潜规则.总之呢,是好是坏都已经在落笔的那一刻开始了. 说起直播,各位都不陌生,毕竟国内这几年直播,短视频等视频行业大火,让所有程序员对直播都能如数家珍,随口便能讲出几种协 ...

  4. h264和aac格式介绍及mp4文件的封装

    mp4封装 目录 h264视频流格式介绍 aac音频流格式介绍 h264视频文件读取 通过帧索引解析h264文件 通过解析h264结构读取文件 aac音频文件读取 mp4封装 初始化 数据封装 关闭m ...

  5. 【Android RTMP】音频数据采集编码 ( AAC 音频格式解析 | FLV 音频数据标签解析 | AAC 音频数据标签头 | 音频解码配置信息 )

    文章目录 安卓直播推流专栏博客总结 一. AAC 音频格式解析 二. FLV 音频数据标签解析 1. 分析 FLV 格式中的 AAC 音频格式数据 2. AAC 音频特殊配置 3. AAC 音频数据标 ...

  6. 多媒体音频格式解析WMA WAV OGG AAC APE FLAC

    无论是MP3还是MP4,甚至手机和多媒体DC,产品所支持的各种格式往往让人眼花缭乱.特别是对于刚上手的新手玩家来说,各种格式都有哪些特性,在实际 使用当中有多少格式实用或者必须,其实有很多方面需要我们 ...

  7. 海康摄像头PS流格式解析(RTP/PS/H264)

    海康威视视频录像以PS格式打包,解析的过程按照PS包-->system header--->program stream map--->音视频PES包一路下来,海康在包中自定义了一些 ...

  8. MP3、AAC、WMA、Ogg、MPC、WAV、FLAC、APE、WV、CD、MIDI、RealVideo等音频格式解析及对比

    音频格式详解 无论是随身听还是手机或者是多媒体DC,产品支持的音频格式多样,然而它们都有各自的特性.我们在应用中选择的时候必须考虑到各种格式的适用场合,这要求我们对很多方面有个系统的了解. 有损压缩格 ...

  9. AAC音频格式解析(ADTS)

    一.AAC文件头信息 1.1 adts_fixed_header 1.2 adts_variable_header 二.代码实现结合 FFmpeg 保存AAC 文件 2.1 FFmpeg读取 AAC数 ...

  10. 1小时学会:最简单的iOS直播推流(八)h264/aac 软编码

    最简单的iOS 推流代码,视频捕获,软编码(faac,x264),硬编码(aac,h264),美颜,flv编码,rtmp协议,陆续更新代码解析,你想学的知识这里都有,愿意懂直播技术的同学快来看!! 源 ...

最新文章

  1. hdu 2665(主席树查询区间k大值)
  2. STM32产品名称命名规则
  3. [XSY] 最长公共子串对(后缀自动机)
  4. Python语法异常 Exception
  5. Anaconda中如何查看已经安装的包
  6. java实现代理服务器,接收客户端连接,发送到对应服务器
  7. (教程)手把手教你如何申请软件著作权
  8. 半正定矩阵的对角元素不小于该矩阵的最小特征值
  9. 主成分与因子分析异同_主成分和因子分析原理及比较
  10. Java为Excel导出增加批注(POI)
  11. Win11更新提示安装错误0x80248007怎么办?0x80248007下载错误解决方法汇总
  12. boost中regex使用时出现的问题
  13. 同花顺资金监测精鹰指标公式源码 通过资金监测强弱
  14. devcpp中使用unordered_map
  15. 计算机专业逻辑推理题,逻辑推理试题
  16. 解决win7系统电脑右下角小喇叭有个小叉
  17. 一篇文章讲清NB-IoT技术
  18. OCR财务报表识别方案
  19. 百度ECharts图形报表的介绍以及应用案例理解
  20. kaliWEB渗透笔记

热门文章

  1. 还是忍不住转下 --你喜欢的只是那个不喜欢你的她
  2. 五大常用办公软件-office办公软件
  3. Max动画分割脚本 Unity 自动识别动画分割信息
  4. 从授时服务器上获得时间
  5. 缘灭--HashMap底层原理之1.8put源码篇(三)
  6. 首款MeeGo系统上网本 华硕Eee PC X101H独家首测(1)
  7. ZOJ 3899 State Reversing【NTT】
  8. 图解 K8S(04):吃透 Pod 中的第三类容器 -- init 容器
  9. 利用计算机解决古代数学问题鸡兔同笼,古代数学-鸡兔同笼:7种解法,你发现了几种呢?...
  10. 【游戏开发】多人游戏网络同步相关技术(设计篇)