我是靠谱客的博主 大力口红,最近开发中收集的这篇文章主要介绍流媒体-H264协议-编码-x264学习-相关概念x264编译及文件解析(一),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

  1. 流媒体-H264协议-编码-x264学习-相关概念x264编译及文件解析(一)
  2. 流媒体-H264协议-编码-x264学习-主要结构体(二)
  3. 流媒体-H264协议-编码-x264学习-主要函数(三)
  4. 流媒体-H264协议-编码-x264学习-C++11多线程实现编码(四)

文章目录

    • 一、ffmpeg相关指令
    • 二、windows10编译x264
      • x264源码下载
      • msys2下载
        • 最常用的pacman命令
        • MSYS2的源配置
        • 安装依赖
      • 编译
      • poxports工具下载
      • vc的lib工具生成lib库
    • 三、概念
      • H.264/AVC
      • 白平衡
      • 指数哥伦布码编码
      • 帧内编码
      • 基于波形的一系列视频编码标准
      • 基于内容的编码
        • 预测编码
        • 帧内预测 intra
          • 4x4亮度块预测模式
          • 16x16亮度块预测模式
      • 帧间预测 inter
        • 运动估计搜索算法
          • 运动矢量
          • 运动补偿
      • 变换编码
      • 熵编码
      • 序列参数集 Sequence Paramater Set(SPS)
      • 图像参数集Picture Paramater Set(PPS)
      • 参数图像
      • 片(条带) Slice
      • IDR帧(Instantaneous Decoding Refresh)即时解码刷新
      • H.264 的功能分层:VCL和NAL
        • NAL 单元
      • vui(Video Usability Information Guide) 视频可用性信息
      • YUV 编码类型
      • 码率
        • 码率类型
        • 码率控制类型
      • 量化参数(QP,Quantizer Parameter)
      • x264参数preset、tune、profile和level
    • 四、srs3.0中source.200kbps.768x320.flv转h264视频二进制文件解析
      • h264码流NAL单元分割
      • NAL头部:一字节[详情ITU-T H.264建议书 7.4语义]
      • NAL有校负载
        • EBSP:扩展字节序列载荷(Extended Byte String Payload)
        • RBSP:原始字节序列载荷(Raw Byte Sequence Payload)
        • SODB:数据字节流 (String Of Data Bits)
        • 解析SEI信息
        • 解析SPS
        • 解析PPS
        • 解析Slice
    • 主要参考文献

一、ffmpeg相关指令

ffmpeg 常用命令汇总

//从mp4封装格式中抽取h264 码流
ffmpeg -i test.mp4 -codec copy -bsf: h264_mp4toannexb -f h264 out.264
//抽取音频
ffmpeg -i test.mp4 -vn -acodec copy
out.aac
//生成原生的yuv数据
ffmpeg -i test.mp4 -pix_fmt yuv420p -vcodec rawvideo -an out.yuv

二、windows10编译x264

x264源码下载

x264源码下载,需要翻墙下载。

msys2下载

msys2官网,需要翻墙下载。
Minimal GNU(POSIX)system on Windows,是一个小型的GNU环境,包括基本的bash,make等等。提供了一个易于使用的环境,用于构建,安装和运行本机Windows软件,与Cygwin大致功能相当即在windows平台上提供运行的类UNIX模拟环境。

最常用的pacman命令

pacman -Syu: 升级系统及所有已经安装的软件。
pacman -S 软件名: 安装软件。也可以同时安装多个包,只需以空格分隔包名即可。
pacman -Rs 软件名: 删除软件,同时删除本机上只有该软件依赖的软件。
pacman -Ru 软件名: 删除软件,同时删除不再被任何软件所需要的依赖。
pacman -Ssq 关键字: 在仓库中搜索含关键字的软件包,并用简洁方式显示。
pacman -Qs 关键字: 搜索已安装的软件包。
pacman -Qi 软件名: 查看某个软件包信息,显示软件简介,构架,依赖,大小等详细信息。
pacman -Sg: 列出软件仓库上所有的软件包组。
pacman -Sg 软件包组: 查看某软件包组所包含的所有软件包。
pacman -Sc:清理未安装的包文件,包文件位于 /var/cache/pacman/pkg/ 目录。
pacman -Scc:清理所有的缓存文件。

MSYS2的源配置

MSYS2配置清华镜像修改msys2安装目录下的etcpacman.d文件夹里面的3个mirrorlist.*文件,依样画葫芦把镜像添加再更新即可。

//编辑 /etc/pacman.d/mirrorlist.mingw32 ,在文件开头添加:
Server = https://mirrors.tuna.tsinghua.edu.cn/msys2/mingw/i686
//编辑 /etc/pacman.d/mirrorlist.mingw64 ,在文件开头添加:
Server = https://mirrors.tuna.tsinghua.edu.cn/msys2/mingw/x86_64
//编辑 /etc/pacman.d/mirrorlist.msys ,在文件开头添加:
Server = https://mirrors.tuna.tsinghua.edu.cn/msys2/msys/$arch
//然后执行 pacman -Sy 刷新软件包数据即可。

安装依赖

 pacman -S mingw-w64-x86_64-gcc yasm make nasm //安装mingw-w64-x86_64-gcc yasm make nasm

编译

打开MSYS2 MinGW 64-bit,进入到x264源码所在路径,x86_64-w64-mingw32编译windows环境目标文件,执行:

#
./configure --host=x86_64-w64-mingw32 --enable-shared --enable-static --prefix=/usr/local/x264
platform:
X86_64
byte order:
little-endian
system:
WINDOWS
cli:
yes
libx264:
internal
shared:
yes
static:
yes
bashcompletion: no
asm:
yes
interlaced:
yes
avs:
avisynth
lavf:
no
ffms:
no
mp4:
no
gpl:
yes
thread:
win32
opencl:
yes
filters:
crop select_every
lto:
no
debug:
no
gprof:
no
strip:
no
PIC:
yes
bit depth:
all
chroma format:
all
You can run 'make' or 'make fprofiled' now.

编译安装

make && make install

查看生成文件

cd /usr/local/x264
# ls -R
.:
bin
include
lib
./bin:
libx264-161.dll
x264.exe
./include:
x264.h
x264_config.h
./lib:
libx264.a
libx264.dll.a
pkgconfig
./lib/pkgconfig:
x264.pc

poxports工具下载

windows下使用此工具利用dll动态库生成lib静态库

 .pexports.exe .libx264-161.dll > .libx264-161.def //使用pexports工具生成libx264-161.def

vc的lib工具生成lib库

lib可执行文件在Microsoft Visual Studio2017ProfessionalVCToolsMSVC14.16.27023binHostx64x64目录下:

 .lib.exe /machine:x64 /def:libx264-161.def //在当前目录下生成libx264-161.lib

三、概念

H.264/AVC

MPEG( Moving Picture Experts Group)和 VCEG( Video Coding Experts Group)已经联合开发了一个比早期研发的MPEG和H.263性能更好的视频压缩编码标准,这就是被命名为 AVC( Advanced Video Coding)的,也被称为ITU-TH.264建议和MPEG-4的第10部分的标准,在这里,就简称它为 H.264/AVC 或 H.264。

白平衡

  1. 白平衡其基本概念是“不管在任何光源下,都能将白色物体还原为白色”衡,在不同的光线下,由于图像传感器输出的不平衡性,造成其输出的彩色失真:或者图像偏蓝,或者偏红,对在特定光源下拍摄时出现的偏色现象,通过加强对应的补色来进行补偿。
  2. 涉及到另一个重要的概念:色温。所谓色温,简而言之,就是定量地以开尔文温度表示色彩,色温是指绝对黑体从绝对零度(-273℃)开始加温后所呈现的颜色。某一种色光比其它色光的色温高时,说明该色光比其它色光偏蓝,反之则偏红;同样,当一种色光比其它色光偏蓝时说明该色光的色温偏高,反之偏低。
  3. 白平衡就是针对不同色温条件下,通过调整摄像机内部的色彩电路使拍摄出来的影像抵消偏色,更接近人眼的视觉习惯。白平衡可以简单地理解为在任意色温条件下,摄像机镜头所拍摄的标准白色经过电路的调整,使之成像后仍然为白色。
  4. 作用:1、纠正色温,还原拍主体的色彩,使在不同光源条件下拍摄的画面同人眼观看的画面色彩相近。2、通过控制色温,可以获得色彩效果迥异的照片

指数哥伦布码编码

[参考:指数哥伦布编码]

帧内编码

基于波形的一系列视频编码标准

基于内容的编码

预测编码

帧内预测 intra

[参考:帧内预测]
对于一幅图像,相邻的两个像素的亮度和色度值之间经常是比较接近的,也就是颜色是逐渐变化的,不会一下子突变成完全不一样的颜色。而进行视频编码,目的就是利用这个相关性,来进行压缩。帧内预测是利用视频空间域的相关性,使用同一帧图像内邻近已编码像素预测当前的像素,以达到有效去除视频时域冗余的目的。

4x4亮度块预测模式

9种方式

16x16亮度块预测模式

4种方式

帧间预测 inter

帧间预测主要包括运动估计(运动搜索方法、运动估计准则、亚像素插值和运动矢量估计)和运动补偿

运动估计搜索算法

[参考:运动估计搜索算法]

运动矢量
运动补偿

变换编码

熵编码

序列参数集 Sequence Paramater Set(SPS)

[参考:序列参数集]

SPS中保存了一组编码视频序列(Coded video sequence)的全局参数。所谓的编码视频序列即原始视频的一帧一帧的像素数据经过编码之后的结构组成的序列。而每一帧的编码后数据所依赖的参数保存于图像参数集中。
一个SPS和PPS的NAL Unit通常位于整个码流的起始位置。但在某些特殊情况下,在码流中间也可能出现这两种结构,主要原因可能为:

  1. 解码器需要在码流中间开始解码;
  2. 编码器在编码的过程中改变了码流的参数(如图像分辨率等);

图像参数集Picture Paramater Set(PPS)

[参考:图像参数解析]

通常情况下,PPS类似于SPS,在H.264的裸码流中单独保存在一个NAL Unit中,只是PPS NAL Unit的nal_unit_type值为8;而在封装格式中,PPS通常与SPS一起,保存在视频文件的文件头中。

参数图像

为了提高预测精度,H.264编码器可从一组前面或后面已编码图像中选出一个或两个与当前最匹配的图像作为帧间编码间的参数图像,这样一来,复杂度大为增加,但多次比较的结果,使匹配后的预测精度显著改进。 H.264 中最多可从 15个参数图像中进行选择,选出最佳的匹配图像。

片(条带) Slice

[参考:片 Slice]

  1. 一个视频图像可编码成一个或更多个片,每片包含整数个宏块( MB),即每片至少一个 MB,最多时每片包含整个图像的宏块。总之,一幅图像中每片的宏块数不一定固定。
  2. 设片的目的是为了限制误码的扩散和传输,应使编码片相互间是独立的。某片的预测不能以其它片中的宏块为参考图像,这样某一片中的预测误差才不会传播到其它片中去。
  3. 编码片共有 5 种不同类型,除已讲过的 I 片、 P 片、 B 片外,还有 SP 片和 SI 片。其中 SP(切换P)是用于不同编码流之间的切换;它包含P和/或I宏块。它是扩展档次中必须具有的切换,它包含了一种特殊类型的编码宏块,叫做SI宏块,SI也是扩展档次中的必备功能。在I slice中只包含I宏块,不能包含P或B宏块;在P和B slice中,除了相应的P和B类型宏块之外,还可以包含I类型宏块

IDR帧(Instantaneous Decoding Refresh)即时解码刷新

I 和 IDR 帧都是使用帧内预测的。它们都是同一个东西而已,在编码和解码中为了方便,要首个 I 帧和其他 I 帧区别开,所以才把第一个首个I帧叫IDR,这样就方便控制编码和解码流程。IDR帧的作用是立刻刷新,使错误不致传播,从IDR帧开始,重新算一个新的序列开始编码。++GOP(Group of picture)关键帧的周期,也就是两个IDR帧之间的距离++。

举个例子,在一段视频中,存在以下帧:I P B P B P B B P I P B…
如果这段视频应用了多重参照帧,那么蓝色的P帧在参照他前面的I帧(红色)的同时,还可能会参照 I 帧之前的 P (绿色),由于I帧前后的场景可能会有很大的反差甚至根本不同,所以此时 P 帧参考I帧之前的帧不但会没有意义,反而会造成很多问题。所以一种新型的帧被引入,那就是 IDR 帧。如果这段视频应用了多重参考帧的同时采用了IDR帧,那么帧的顺序就会变成这样:I P B P B P B B P IDR P B…

由于 IDR 帧禁止后面的帧向自己前面的帧参照,所以这回那个蓝色的 P 帧就不会参照绿色的 P 帧了

H.264 的功能分层:VCL和NAL

视频编码层( VCL)和网络提取层( NAL, Network Abstraction Layer)。VCL数据即编码处理的输出,它表示被压缩编码后的视频数据序列。在VCL数据传输或存储之前,这些编码的 VCL 数据,先被映射或封装进 NAL 单元中

NAL 单元

[参考:H.264/AVC视频编解码技术详解 六、H.264的NAL解析]

vui(Video Usability Information Guide) 视频可用性信息

X264算法参数二(VUI参数配置)

YUV 编码类型

色度抽样(4:2:0)到底是什么意思 颜色是由亮度(Luminance或Luma)和色度(chromaticity)共同表示的,色度是不包括亮度在内的颜色的性质,它反映的是颜色的色调和饱和度(指色彩的鲜艳程度,也称作纯度).如何理解 YUV

码率

码率就是数据传输时单位时间传送的数据位数,一般我们用的单位是kbps即千位每秒。也就是取样率(并不等同与采样率,采样率的单位是Hz,表示每秒采样的次数),单位时间内取样率越大,精度就越高,处理出来的文件就越接近原始文件。

码率类型

  • VBR(Variable Bitrate)动态比特率 也就是没有固定的比特率,压缩软件在压缩时根据音频数据即时确定使用什么比特率,这是以质量为前提兼顾文件大小的方式,推荐编码模式;

  • ABR(Average Bitrate)平均比特率 是VBR的一种插值参数。LAME针对CBR不佳的文件体积比和VBR生成文件大小不定的特点独创了这种编码模式。ABR在指定的文件大小内,以每50帧(30帧约1秒)为一段,低频和不敏感频率使用相对低的流量,高频和大动态表现时使用高流量,可以做为VBR和CBR的一种折衷选择。

  • CBR(Constant Bitrate),常数比特率 指文件从头到尾都是一种位速率。相对于VBR和ABR来讲,它压缩出来的文件体积很大,而且音质相对于VBR和ABR不会有明显的提高。

码率控制类型

[参考:X264码率控制总结1——ABR,CQP,CRF]

X264显式支持的一趟码率控制方法有:ABR, CQP, CRF. 缺省方法是CRF。这三种方式的优先级是ABR > CQP > CRF。图像编解码:CRF(质量/码率控制)和QP

  • ABR:恒定平均目标码率。想要选择这种码率控制方法,必须先设置bitrate
  • CQP:恒定QP. 无缺省值
  • CRF:恒定Rate Factor (码率系数)缺省值23

量化参数(QP,Quantizer Parameter)

[参考:H264量化参数QP]

量化参数,反映了空间细节压缩情况。值越小,量化越精细,图像质量越高,产生的码流也越长。如QP小,大部分的细节都会被保留;QP增大,一些细节丢失,码率降低,但图像失真加强和质量下降。量化参数QP是量化步长Qstep的序号,QP取最小值0时,表示量化最精细;相反,QP取最大值51时,表示量化是最粗糙的。

x264参数preset、tune、profile和level

  1. preset是编码速度

从最快到最慢。无特殊要求选fast即可,编码加快,意味着信息丢失越严重,输出图像质量越差。

/****************************************************************************
* Advanced parameter handling functions
****************************************************************************/
/* 这些功能充分展示了x264的preset-tune-profile系统的全部功能,便于调整大量内部参数
*
* 为了复制x264CLI的选项处理,必须按以下顺序调用这些函数:
* 1) x264_param_default_preset
* 2) Custom user options (via param_parse or directly assigned variables)
* 3) x264_param_apply_fastfirstpass
* 4) x264_param_apply_profile
*
* 另外, 如果 preset 被设置为 "placebo"或者--slow-firstpass则x264CLI不执行第三步
/* x264_param_default_preset:
*
The same as x264_param_default, but also use the passed preset and tune
*
to modify the default settings.
*
(either can be NULL, which implies no preset or no tune, respectively)
*
*
Currently available presets are, ordered from fastest to slowest: */
static const char * const x264_preset_names[] = { "ultrafast", "superfast", "veryfast", "faster", "fast",
"medium", "slow", "slower", "veryslow", "placebo", 0 };

预设值也可以按数字索引,如x264_param_default_preset(&param, “3”, … ),ultrafast 对应 “0” placebo对应 “9”,当然,如果在两者之间添加新的预设值,这种映射可能会发生变化,但始终是从最快到最慢排序的
警告:这些预设的速度会急剧增加,Ultrafast是placebo的100倍

  1. tune是编码质量和画面细节相关的参数

tune是x264中重要性仅次于preset的选项,它是视觉优化的参数,tune可以理解为视频偏好(或者视频类型),tune不是一个单一的参数,而是由一组参数构成。

static const char * const x264_tune_names[] = { "film", "animation", "grain", "stillimage",
"psnr", "ssim", "fastdecode", "zerolatency", 0 };
  • film:电影类型,对视频的质量非常严格时使用该选项
  • animation:动画片,压缩的视频是动画片时使用该选项
  • grain:颗粒物很重,该选项适用于颗粒感很重的视频
  • stillimage:静态图像,该选项主要用于静止画面比较多的视频
  • psnr:提高psnr,该选项编码出来的视频psnr比较高
  • ssim:提高ssim,该选项编码出来的视频ssim比较高
  • fastdecode:快速解码,该选项有利于快速解码
  • zerolatency:零延迟,该选项主要用于视频直播
  1. profile是约束条件

H.264有四种画质级别,分别是baseline, extended, main, high

static const char * const x264_profile_names[] = { "baseline", "main", "high", "high10", "high422", "high444", 0 };
  • Baseline Profile:基本画质。支持I/P 帧,只支持无交错(Progressive)和CAVLC;
  • Extended profile:进阶画质。支持I/P/B/SP/SI 帧,只支持无交错(Progressive)和CAVLC;(用的少)
  • Main profile:主流画质。提供I/P/B 帧,支持无交错(Progressive)和交错(Interlaced), 也支持CAVLC 和CABAC 的支持;
  • High profile:高级画质。在main Profile 的基础上增加了8x8内部预测、自定义量化、 无损视频编码和更多的YUV 格式;

H.264 Baseline profile、Extended profile和Main profile都是针对8位样本数据、4:2:0格式(YUV)的视频序列。在相同配置情况下,High profile(HP)可以比Main profile(MP)降低10%的码率。 根据应用领域的不同,Baseline profile多应用于实时通信领域,Main profile多应用于流媒体领域,High profile则多应用于广电和存储领域。
4. level:level_idc属性:参考H264编码profile & level控制

  • 在给定的profile下,level通常与解码器的处理能力和内存容量相对应。每一个档次设置不同的参数(如取样速率、图像尺寸、编码比特率等),得到对应的编解码器性能的不同level
  • Description: Set bitstream Level IDC. 默认为 21,设置为 0 表示终止
  • 注:与ProfileIDC类似,LevelIDC在编码过程中设置了一定的限制,如支持的分辨率、最大引用数、帧速率等,见H.264/AVC附录A
Options:Options:description
101(supports only QCIF format and below with 380160 samples/sec)
111.1(CIF and below. 768000 samples/sec)
121.2(CIF and below. 1536000 samples/sec)
131.3(CIF and below. 3041280 samples/sec)
202(CIF and below. 3041280 samples/sec)
212.1(Supports HHR formats. Enables Interlace support. 5068800 samples/sec)
222.2(Supports SD/4CIF formats. Enables Interlace support. 5184000 samples/sec)
303(Supports SD/4CIF formats. Enables Interlace support. 10368000 samples/sec)
313.1(Supports 720p HD format. Enables Interlace support. 27648000 samples/sec)
323.2(Supports SXGA format. Enables Interlace support. 55296000 samples/sec)
404(Supports 2Kx1K format. Enables Interlace support. 62914560 samples/sec)
414.1(Supports 2Kx1K format. Enables Interlace support. 62914560 samples/sec)
424.2(Supports 2Kx1K format. Frame coding only. 125829120 samples/sec)
505(Supports 3672x1536 format. Frame coding only. 150994944 samples/sec)
515.1(Supports 4096x2304 format. Frame coding only. 251658240 samples/sec)
  1. 参数设置函数
/****************************************************************************
* Basic parameter handling functions
****************************************************************************/
/* x264_param_default:
*
fill x264_param_t with default values and do CPU detection */
X264_API void x264_param_default( x264_param_t * );
/*
多个 tunings 可以被使用通过 ",./-+"分隔符分割,
*
多个 psy tunings 不能被使用.
*
film, animation, grain, stillimage, psnr, and ssim 属于 psy tunings.
*
*
returns 0 on success, negative on failure (e.g. invalid preset/tune name). */
X264_API int x264_param_default_preset( x264_param_t *, const char *preset, const char *tune );
/*
(can be NULL, in which case the function will do nothing)
*
*
不保证设置的profile被使用:如果 "High" 被设置已经 Baseline-compatible,流将会保持baseline.
*
简而言之,它不会增加设置,只会降低设置
*
*
returns 0 on success, negative on failure (e.g. invalid profile name). */
X264_API int x264_param_apply_profile( x264_param_t *, const char *profile );

四、srs3.0中source.200kbps.768x320.flv转h264视频二进制文件解析

h264码流NAL单元分割

实际的H264数据帧中,往往帧前面带有00 00 00 01 或 00 00 01分隔符

NAL头部:一字节[详情ITU-T H.264建议书 7.4语义]

H264数据帧分割之后的下一个字节就是NALU类型,将其转为二进制数据后,解读顺序为从左往右算:

  1. 第1位禁止位,值为1表示语法出错,应设置为0
  2. 第2~3位为参考级别
  • 主要表示NAL的优先级。当该值为正时,表示当前NAL Unit中包含了SPS、PPS和作为参考帧的Slice等重要数据
  1. 第4~8为是nal单元类型
  • 包括VCL层和非VCL层的多种数据类型。
  1. 常见的nal_unit_type取值有:
  • 1表示非IDR帧编码条带
  • 2表示编码条带数据分割块 A
  • 3表示编码条带数据分割块 B
  • 4表示编码条带数据分割块 C
  • 5表示IDR帧
  • 6表示辅助性增强信息(SEI)
  • 7表示SPS
  • 8表示PPS

NAL有校负载

EBSP:扩展字节序列载荷(Extended Byte String Payload)

等同于NAL Body的数据本身。在EBSP中包含了一个特殊的字节0x03,表示防止竞争校验字节:

emulation_prevention_three_byte:设置该值的目的是为了防止NAL Body内部出现于NAL Unit起始码0x 00 00 01或0x 00 00 00 01冲突。
当内部的连续4字节数据出现了下列情况时:

0x 00 00 00
0x 00 00 01
0x 00 00 02
0x 00 00 03

在两个0字节之后会插入值为3的一个字节,形成下列情况:

0x 00 00 03 00
0x 00 00 03 01
0x 00 00 03 02
0x 00 00 03 03

在进行解析时需要将附加的03字节去掉,得到RBSP数据。

RBSP:原始字节序列载荷(Raw Byte Sequence Payload)

相当于NAL Body去掉emulation_prevention_three_byte之后的数据,是对原始的语法元素码流进一步处理后产生的数据。相比于原始的语法元素码流,RBSP在末尾添加了rbsp_trailing_bits()部分,其主要目的是字节对齐。每个rbsp_trailing_bits()包括一个1bit和若干个0bit,0bit的个数不定,以实现字节的对齐。

SODB:数据字节流 (String Of Data Bits)

表示H.264的语法元素编码完成后的实际的原始二进制码流。SODB通常不能保证字节对齐

解析SEI信息

解析一字节NAL头得到类型为6,即附加增强信息

06-->0 00 00110
//类型6:附加增强信息(SEI),图像的额外信息

根据[ITU-T H.264建议书 7语法和语义7.3.2.++3++]进行解析负载类型和负载长度:

sei_message( )
{
payloadType = 0
while( next_bits( 8 ) == 0xFF )
//第一个FF之前的字节组合数为payloadType
{
ff_byte /* equal to 0xFF */
payloadType += 255
}
last_payload_type_byte // 8位
payloadType += last_payload_type_byte
payloadSize = 0
while( next_bits( 8 ) = = 0xFF )
{
ff_byte /* equal to 0xFF */
payloadSize += 255
}
last_payload_size_byte
payloadSize += last_payload_size_byte
sei_payload( payloadType, payloadSize )
}

0x05 FF FF AC得出负载类型和负载长度

  1. 负载类型:0x05–>5;
  2. 负载长度FF FF AC–>682 (FF + FF + AC = 2AA)

根据[++ITU-T H.264建议书 辅助增强信息 D.1 SEI在和语法++]解析负载数据:

User_data_unregistered( payloadSize )
{
uuid_iso_iec_11578 // u(128) 16字节编号
for( i = 16; i < payloadSize; I++ )
user_data_payload_byte //
}

16个字节uuid,uuid_iso_iec_11578 应有一个由 UUID 指定的值,依照 ISO/IEC 11578:1996 附件 A 的规程:

00000000
dc 45 e9 bd e6 d9 48
|..........E....H|
00000010
b7 96 2c d8 20 d9 23 ee
ef
|..,. .#..

剩余682-16 = 662字节数据,其语法和语义由 UUID 生成器指明:

00000000
|
|
00000010
78 32 36 34 20 2d 20
|
x264 - |
00000020
63 6f 72 65 20 31 33 38
20 2d 20 48 2e 32 36 34
|core 138 - H.264|
00000030
2f 4d 50 45 47 2d 34 20
41 56 43 20 63 6f 64 65
|/MPEG-4 AVC code|
00000040
63 20 2d 20 43 6f 70 79
6c 65 66 74 20 32 30 30
|c - Copyleft 200|
00000050
33 2d 32 30 31 33 20 2d
20 68 74 74 70 3a 2f 2f
|3-2013 - http://|
00000060
77 77 77 2e 76 69 64 65
6f 6c 61 6e 2e 6f 72 67
|www.videolan.org|
00000070
2f 78 32 36 34 2e 68 74
6d 6c 20 2d 20 6f 70 74
|/x264.html - opt|
00000080
69 6f 6e 73 3a 20 63 61
62 61 63 3d 31 20 72 65
|ions: cabac=1 re|
00000090
66 3d 33 20 64 65 62 6c
6f 63 6b 3d 31 3a 30 3a
|f=3 deblock=1:0:|
000000a0
30 20 61 6e 61 6c 79 73
65 3d 30 78 33 3a 30 78
|0 analyse=0x3:0x|
000000b0
31 33 33 20 6d 65 3d 68
65 78 20 73 75 62 6d 65
|133 me=hex subme|
000000c0
3d 37 20 70 73 79 3d 31
20 70 73 79 5f 72 64 3d
|=7 psy=1 psy_rd=|
000000d0
31 2e 30 30 3a 30 2e 30
30 20 6d 69 78 65 64 5f
|1.00:0.00 mixed_|
000000e0
72 65 66 3d 31 20 6d 65
5f 72 61 6e 67 65 3d 31
|ref=1 me_range=1|
000000f0
36 20 63 68 72 6f 6d 61
5f 6d 65 3d 31 20 74 72
|6 chroma_me=1 tr|
00000100
65 6c 6c 69 73 3d 31 20
38 78 38 64 63 74 3d 31
|ellis=1 8x8dct=1|
00000110
20 63 71 6d 3d 30 20 64
65 61 64 7a 6f 6e 65 3d
| cqm=0 deadzone=|
00000120
32 31 2c 31 31 20 66 61
73 74 5f 70 73 6b 69 70
|21,11 fast_pskip|
00000130
3d 31 20 63 68 72 6f 6d
61 5f 71 70 5f 6f 66 66
|=1 chroma_qp_off|
00000140
73 65 74 3d 2d 32 20 74
68 72 65 61 64 73 3d 38
|set=-2 threads=8|
00000150
20 6c 6f 6f 6b 61 68 65
61 64 5f 74 68 72 65 61
| lookahead_threa|
00000160
64 73 3d 31 20 73 6c 69
63 65 64 5f 74 68 72 65
|ds=1 sliced_thre|
00000170
61 64 73 3d 30 20 6e 72
3d 30 20 64 65 63 69 6d
|ads=0 nr=0 decim|
00000180
61 74 65 3d 31 20 69 6e
74 65 72 6c 61 63 65 64
|ate=1 interlaced|
00000190
3d 30 20 62 6c 75 72 61
79 5f 63 6f 6d 70 61 74
|=0 bluray_compat|
000001a0
3d 30 20 63 6f 6e 73 74
72 61 69 6e 65 64 5f 69
|=0 constrained_i|
000001b0
6e 74 72 61 3d 30 20 62
66 72 61 6d 65 73 3d 33
|ntra=0 bframes=3|
000001c0
20 62 5f 70 79 72 61 6d
69 64 3d 32 20 62 5f 61
| b_pyramid=2 b_a|
000001d0
64 61 70 74 3d 31 20 62
5f 62 69 61 73 3d 30 20
|dapt=1 b_bias=0 |
000001e0
64 69 72 65 63 74 3d 31
20 77 65 69 67 68 74 62
|direct=1 weightb|
000001f0
3d 31 20 6f 70 65 6e 5f
67 6f 70 3d 30 20 77 65
|=1 open_gop=0 we|
00000200
69 67 68 74 70 3d 32 20
6b 65 79 69 6e 74 3d 32
|ightp=2 keyint=2|
00000210
35 30 20 6b 65 79 69 6e
74 5f 6d 69 6e 3d 32 35
|50 keyint_min=25|
00000220
20 73 63 65 6e 65 63 75
74 3d 34 30 20 69 6e 74
| scenecut=40 int|
00000230
72 61 5f 72 65 66 72 65
73 68 3d 30 20 72 63 5f
|ra_refresh=0 rc_|
00000240
6c 6f 6f 6b 61 68 65 61
64 3d 34 30 20 72 63 3d
|lookahead=40 rc=|
00000250
61 62 72 20 6d 62 74 72
65 65 3d 31 20 62 69 74
|abr mbtree=1 bit|
00000260
72 61 74 65 3d 32 30 36
20 72 61 74 65 74 6f 6c
|rate=206 ratetol|
00000270
3d 31 2e 30 20 71 63 6f
6d 70 3d 30 2e 36 30 20
|=1.0 qcomp=0.60 |
00000280
71 70 6d 69 6e 3d 31 30
20 71 70 6d 61 78 3d 35
|qpmin=10 qpmax=5|
00000290
31 20 71 70 73 74 65 70
3d 34 20 69 70 5f 72 61
|1 qpstep=4 ip_ra|
000002a0
74 69 6f 3d 31 2e 34 31
20 61 71 3d 31 3a 31 2e
|tio=1.41 aq=1:1.|
000002b0
30 30 00

结尾比特即rbsp trailing bits,在user_data_unregistered()里面都是按字节写入的,所以此时的NAL unit结尾写入的字节一定是0x80.

解析SPS

[ITU-T H.264建议书 7.3.2 原始字节序列载荷和RBSP尾比特语法]
[参考:H264码流中SPS PPS详解]

在H.264标准协议中规定类型7表示该NAL Unit内保存的数据为Sequence Paramater Set。在H.264的各种语法元素中,SPS中的信息至关重要。如果其中的数据丢失或出现错误,那么解码过程很可能会失败。

NAL头部一字节为:0x67

0x67 ---> 0 11 00111:禁止位为0;优先级为3;NAL类型为7--序列参数集

在H.264的SPS中:

  1. 第一个字节:profile_idc表示画质级别–>0x64:100;
  2. 第二字节:constraint_set0_flag ~ constraint_set3_flag,reserved_zero_4bits /* equal to 0 */–>0x00
  3. 第三字节:level_idc表示当前码流的Level–>0x20
  4. 无符号指数哥伦布码编码的语法元素:seq_parameter_set_id表示当前的序列参数集的id。通过该id值,图像参数集pps可以引用其代表的sps中的参数,该值的取值范围为[0,31]–>0xAC
  5. 如下:
H.264
NAL unit header or first byte of the payload
0... .... = F bit: No bit errors or other syntax violations
.11. .... = Nal_ref_idc (NRI): 3
...0 0111 = Type: NAL unit - Sequence parameter set (7)
H264 NAL Unit Payload
0110 0100 = Profile_idc: High profile (100)
0... .... = Constraint_set0_flag: 0
.0.. .... = Constraint_set1_flag: 0
..0. .... = Constraint_set2_flag: 0
...0 .... = Constraint_set3_flag: 0
.... 0... = Constraint_set4_flag: 0
.... .0.. = Constraint_set5_flag: 0
.... ..00 = Reserved_zero_2bits: 0
0010 0000 = Level_id: 32 [Level 3.2 20 Mb/s]
1... .... = seq_parameter_set_id: 0
//用于识别图像参数集所指的序列参数集, [0-31]
.010 .... = chroma_format_id: 1
//与亮度取样对应的色度取样
.... 1... = bit_depth_luma_minus8: 0
.... .1.. = bit_depth_chroma_minus8: 0
.... ..0. = qpprime_y_zero_transform_bypass_flag: 0
.... ...0 = seq_scaling_matrix_present_flag: 0
1... .... = log2_max_frame_num_minus4: 0
//此参数计算得出MaxFrameNum的值
.1.. .... = pic_order_cnt_type: 0
//解码图像顺序的计数方法 [0-2]
..01 1... = log2_max_pic_order_cnt_lsb_minus4: 2
.... .001
01.. .... = num_ref_frames: 4
..0. .... = gaps_in_frame_num_value_allowed_flag: 0
...0 0000
1100 00.. = pic_width_in_mbs_minus1: 47
//以宏块为单元的每个解码图像的宽度
.... ..00
0010 100. = pic_height_in_map_units_minus1: 19
.... ...1 = frame_mbs_only_flag: 1 //等于 0 表示编码视频序列的编码图像可能是编码场或编码帧
//1 表示编码视频序列的每个编码图像都是一个仅包含帧宏块的编码帧
1... .... = direct_8x8_inference_flag: 1
.0.. .... = frame_cropping_flag: 0
..1. .... = vui_parameters_present_flag: 1
...1 .... = aspect_ratio_info_present_flag: 1
.... 0000
0001 .... = aspect_ratio_idc: 1
.... 0... = overscan_info_present_flag: 0
.... .0.. = video_signal_type_present_flag: 0
.... ..0. = chroma_loc_info_present_flag: 0
.... ...1 = timing_info_present_flag: 1
0000 0000
0000 0000
0000 0000
0000 0001 = num_units_in_tick: 1
0000 0000
0000 0000
0000 0000
0011 0010 = time_scale: 50
0... .... = fixed_frame_rate_flag: 0
.0.. .... = nal_hrd_parameters_present_flag: 0
..0. .... = vcl_hrd_parameters_present_flag: 0
...0 .... = pic_struct_present_flag: 0
.... 1... = bitstream_restriction_flag: 1
.... .1.. = motion_vectors_over_pic_boundaries_flag: 1
.... ..1. = max_bytes_per_pic_denom: 0
.... ...1 = max_bits_per_mb_denom: 0
0001 100. = max_mv_length_horizontal: 11
.... ...0
0011 00.. = log2_max_mv_length_vertical: 11
.... ..01
1... .... = num_reorder_frames: 2
.001 01.. = max_dec_frame_buffering: 4
.... ..1. = rbsp_stop_bit: 1
.... ...0 = rbsp_trailing_bits: 0

解析PPS

NAL头部一字节为:0x68

0x68 ---> 0 11 01000:禁止位为0;优先级为3;NAL类型为8--图像参数集

在H.264的PPS中,解析过程看建议书:…

H.264
NAL unit header or first byte of the payload
0... .... = F bit: No bit errors or other syntax violations
.11. .... = Nal_ref_idc (NRI): 3
...0 1000 = Type: NAL unit - Picture parameter set (8)
H264 NAL Unit Payload
1... .... = pic_parameter_set_id: 0 //标识在条带头中提到的图像参数集 [0-255]
.1.. .... = seq_parameter_set_id: 0 //指活动的序列参数集
..1. .... = entropy_coding_mode_flag: 1 //用于选取语法元素的熵编码方式
...0 .... = pic_order_present_flag: 0
.... 1... = num_slice_groups_minus1: 0 //加 1 表示一个图像中的条带组数
.... .011 = num_ref_idx_l0_active_minus1: 2
1... .... = num_ref_idx_l1_active_minus1: 0
.1.. .... = weighted_pred_flag: 1
..10 .... = weighted_bipred_idc: 2
.... 1... = pic_init_qp_minus26: 0
.... .1.. = pic_init_qs_minus26: 0
.... ..00
101. .... = chroma_qp_index_offset(se(v)): -2
...1 .... = deblocking_filter_control_present_flag: 1
.... 0... = constrained_intra_pred_flag: 0
.... .0.. = redundant_pic_cnt_present_flag: 0
.... ..1. = transform_8x8_mode_flag: 1
.... ...0 = pic_scaling_matrix_present_flag: 0
0010 1... = second_chroma_qp_index_offset(se(v)): -2
.... .1.. = rbsp_stop_bit: 1
.... ..00 = rbsp_trailing_bits: 0

解析Slice

片(条带类型):

slice_type
slice_type 的名称
0
P (P 条带)
1
B (B 条带)
2
I (I 条带)
3
SP (SP 条带)
4
SI (SI 条带)
5
P (P 条带)
6
B (B 条带)
7
I (I 条带)
8
SP (SP 条带)
9
SI (SI 条带)

解析数据示例:

001a0498h: 00 00 00 01 41 9B B4 4B E1 08 43 C8 CD 14 78 10 | óÌ.».g‹ßž]©à7.ɏ|
001a04a8h: 20 4A 05 31 42 40 22 BF E4 02 56 2C 4B EC 4A D5 | -=*ä+.§x.å...G.|
...

NAL头部一字节为:0x41

0x41 ---> 0 10 00001:禁止位为0;优先级为2;NAL类型为1--一个非 IDR 图像的编码条带

slice头部,具体查看建议书7.3.3 条带头语法,例:

slice_header( ) {
first_mb_in_slice
//2
ue(v):无符号指数哥伦布边贸
slice_type
//2 ue(v)
pic_parameter_set_id
// 2 ue(v)
frame_num // 2 u(v)
if( !frame_mbs_only_flag ) { //在sps中为1,跳过
field_pic_flag
//u(1)-->一字节
if( field_pic_flag )
bottom_field_flag
}
if( nal_unit_type == 5 )
idr_pic_id
if( pic_order_cnt_type = = 0 )
{
pic_order_cnt_lsb
if( pic_order_present_flag && !field_pic_flag )
delta_pic_order_cnt_bottom
}
...
if( slice_type = = P | | slice_type = = SP | | slice_type = = B ) //P条带
{
num_ref_idx_active_override_flag
//u(1)
if( num_ref_idx_active_override_flag )
{
num_ref_idx_l0_active_minus1
if( slice_type = = B )
num_ref_idx_l1_active_minus1
}
}
}
...

9B B4改成二进制数:1001 1011 1011 0100
解码过程:
1 00110 1 1 1 011 010 0

1、获取二进制序列开头连续的N个0
2、读取之后的N+1位的值,假设为X
3、X-1获取解码后的值

得到:

first_mb_in_slice = 0;
slice_type = 5;
pic_parameter_set_id = 0;
frame_num = 0;
frame_mbs_only_flag = 1
field_pic_flag = 0;
...

主要参考文献

  1. [ITU-T H.264建议书]
  2. ffmpeg 常用命令汇总
  3. 指数哥伦布编码
  4. H264码流中SPS PPS详解
  5. H.264/AVC视频编解码技术详解

最后

以上就是大力口红为你收集整理的流媒体-H264协议-编码-x264学习-相关概念x264编译及文件解析(一)的全部内容,希望文章能够帮你解决流媒体-H264协议-编码-x264学习-相关概念x264编译及文件解析(一)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(61)

评论列表共有 0 条评论

立即
投稿
返回
顶部