H264编码系列之profile & level控制

Sequence Paramater Set(SPS)(序列参数集)

(1). profile_idc:

标识当前H.264码流的profile。我们知道,H.264中定义了三种常用的档次profile:

  • 基准档次:baseline profile;
  • 主要档次:main profile;
  • 扩展档次:extended profile;

在H.264的SPS中,第一个字节表示profile_idc,根据profile_idc的值可以确定码流符合哪一种档次。判断规律为:

  • profile_idc = 66 → baseline profile;
  • profile_idc = 77 → main profile;
  • profile_idc = 88 → extended profile;

在新版的标准中,还包括了High、High 10、High 4:2:2、High 4:4:4、High 10 Intra、High 4:2:2 Intra、High 4:4:4 Intra、CAVLC 4:4:4 Intra等,每一种都由不同的profile_idc表示。

另外,constraint_set0_flag ~ constraint_set5_flag是在编码的档次方面对码流增加的其他一些额外限制性条件。

在我们实验码流中,profile_idc = 0x42 = 66,因此码流的档次为baseline profile。

(2). level_idc

标识当前码流的Level。编码的Level定义了某种条件下的最大视频分辨率、最大视频帧率等参数,码流所遵从的level由level_idc指定。

当前码流中,level_idc = 0x1e = 30,因此码流的级别为3。

(3). seq_parameter_set_id

表示当前的序列参数集的id。通过该id值,图像参数集pps可以引用其代表的sps中的参数。

(4). log2_max_frame_num_minus4

用于计算MaxFrameNum的值。计算公式为MaxFrameNum = 2^(log2_max_frame_num_minus4 + 4)。MaxFrameNum是frame_num的上限值,frame_num是图像序号的一种表示方法,在帧间编码中常用作一种参考帧标记的手段。

(5). pic_order_cnt_type

表示解码picture order count(POC)的方法。POC是另一种计量图像序号的方式,与frame_num有着不同的计算方法。该语法元素的取值为0、1或2。

(6). log2_max_pic_order_cnt_lsb_minus4

用于计算MaxPicOrderCntLsb的值,该值表示POC的上限。计算方法为MaxPicOrderCntLsb = 2^(log2_max_pic_order_cnt_lsb_minus4 + 4)。

(7). max_num_ref_frames

用于表示参考帧的最大数目。

(8). gaps_in_frame_num_value_allowed_flag

标识位,说明frame_num中是否允许不连续的值。

(9). pic_width_in_mbs_minus1

本句法元素加 1 后指明图像宽度,以宏块为单位:

PicWidthInMbs = pic_width_in_mbs_minus1 + 1

通过这个句法元素解码器可以计算得到亮度分量以像素为单位的图像宽度:

PicWidthInSamplesL = PicWidthInMbs * 16

从而也可以得到色度分量以像素为单位的图像宽度:

PicWidthInSamplesC = PicWidthInMbs * 8

以上变量 PicWidthInSamplesL、PicWidthInSamplesC 分别表示图像的亮度、色度分量以像素为单位的宽。

H.264 将图像的大小在序列参数集中定义,意味着可以在通信过程中随着序列参数集动态地改变图像的大小,在后文中可以看到,甚至可以将传送的图像剪裁后输出。

(10). pic_height_in_map_units_minus1

本句法元素加 1 后指明图像高度:

PicHeightInMapUnits = pic_height_in_map_units_minus1 + 1
PicSizeInMapUnits = PicWidthInMbs * PicHeightInMapUnits

图像的高度的计算要比宽度的计算复杂,因为一个图像可以是帧也可以是场,从这个句法元素可以在帧模式和场模式下分别计算出出亮度、色度的高。值得注意的是,这里以 map_unit 为单位,map_unit的含义由后文叙述。

(11). frame_mbs_only_flag

标识位,说明宏块的编码方式。当该标识位为0时,宏块可能为帧编码或场编码;该标识位为1时,所有宏块都采用帧编码。根据该标识位取值不同,PicHeightInMapUnits的含义也不同,为0时表示一场数据按宏块计算的高度,为1时表示一帧数据按宏块计算的高度。

按照宏块计算的图像实际高度FrameHeightInMbs的计算方法为:

FrameHeightInMbs = ( 2 − frame_mbs_only_flag ) * PicHeightInMapUnits

(12). mb_adaptive_frame_field_flag

标识位,说明是否采用了宏块级的帧场自适应编码。当该标识位为0时,不存在帧编码和场编码之间的切换;当标识位为1时,宏块可能在帧编码和场编码模式之间进行选择。

(13). direct_8x8_inference_flag

标识位,用于B_Skip、B_Direct模式运动矢量的推导计算。

(14). frame_cropping_flag

标识位,说明是否需要对输出的图像帧进行裁剪。

(15). vui_parameters_present_flag

标识位,说明SPS中是否存在VUI信息。

H264编码profile & level控制

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

  1. Baseline Profile:基本画质。支持I/P 帧,只支持无交错(Progressive)和CAVLC;
  2. Extended profile:进阶画质。支持I/P/B/SP/SI 帧,只支持无交错(Progressive)和CAVLC;(用的少)
  3. Main profile:主流画质。提供I/P/B 帧,支持无交错(Progressive)和交错(Interlaced), 也支持CAVLC 和CABAC 的支持;
  4. 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则多应用于广电和存储领域。

profile主要参数

下图清楚的给出不同的profile&level的性能区别。

 

不同profile支持的参数特性

Level 主要参数

不同Level对应的特性

ffmpeg如何控制profile&level

举3个例子:

ffmpeg -i input.mp4 -profile:v baseline -level 3.0 output_baseline_30.h264
ffmpeg -i input.mp4 -profile:v main -level 4.2 output_main_42.h264
ffmpeg -i input.mp4 -profile:v high -level 5.1 output_high_51.h264

转码后用mediainfo进行分析

  •  

     

    output_baseline_30.h264 baseline对应profile_idc = 66,level对应level_idc=30。

    output_baseline_30.h264

  •  

     

    output_main_42.h264 baseline对应profile_idc = 77,level对应level_idc=42。

    output_main_42

  •  

     

    output_high_51.h264 baseline对应profile_idc = 100,level对应level_idc=51。

    output_high_51

如果ffmpeg编译时加了external的libx264,那就这么写:

ffmpeg -i input.mp4 -c:v libx264 -x264-params "profile=high:level=3.0" output.mp4

 

 

通常情况下压缩比例来说,baseline< main < high,对于带宽比较局限的在线视频,可能会选择high,但有些时候,做个小视频,希望所有的设备基本都能解码(有些低端设备或早期的设备只能解码 baseline),那就牺牲文件大小吧,用baseline!

不同profile和level压缩后的文件大小对比

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1)解码支持的协议特性:h.264 main profile完整规格,严格参照2005年3月正式发布的协议文档(T-REC-H.264-200503-P!!MSW-E.doc)实现。Main profile的特性参见协议附录A对profile以及level的描述。 2)解码库采用的测试工具集:ALLEGRO,HHI,JVT提供的baseline(FMO/ASO特性除外), main profile专业测试码流,以及超过20家IPTV厂家的商用码流。其中专业测试码流是业界用来确保解码芯片规格完备的利器。 3)解码容错处理:重用相同协议规格解码芯片IP验证使用的工具集,含盖了几乎所有的业务功能,边界条件,系统异常等问题的测试用例。 4)是针对X86平台开发的在windows系统下的版本:采用intel的编译器,slice以上层解码主要采用C语言实现,宏块层解码大量使用了MMX,SSE2技术进行高性能并行解码设计。由于main profile的复杂度比较高,不推荐在不支持MMX,SSE2技术的计算机上使用本解码库产品。 5)产品标杆:在性能指标上一直参照业界性能最佳coreAVC解码库进行对比开发,目前纯解码性能稳定在其120%以上,而且对协议规格的遵守方面则具有明显优势。本解码库吸收了JM 10.2在调测ALLEGRO等专业测试码流时发现的若干问题,而coreAVC提供的demo程序只能通过一些最基本的测试码流。业界比较知名的公司还有ateme, elecard和cyberlink。 6)接口形式:提供5个独立的API函数(open, close, decode, get, set)。其中decode函数只负责解析接收到的用户指定长度的符合协议附录B描述的视频流;在解码库内部维护解码图像缓冲区,通过get和set函数来实现播放显示与解码对重构图像的地址交互,避免YUV数据的多次拷贝。 技术支持联系:kwen_zhang@hotmail.com
以下是使用 FFmpeg 库设置 H.264 编码器的 profilelevel 的示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdint.h> #include <inttypes.h> #include <unistd.h> #include <libavcodec/avcodec.h> int main(int argc, char *argv[]) { AVCodec *codec; AVCodecContext *codec_ctx = NULL; AVDictionary *opts = NULL; int ret; avcodec_register_all(); codec = avcodec_find_encoder_by_name("libx264"); if (codec == NULL) { fprintf(stderr, "Codec 'libx264' not found\n"); return 1; } codec_ctx = avcodec_alloc_context3(codec); if (codec_ctx == NULL) { fprintf(stderr, "Failed to allocate codec context\n"); return 1; } codec_ctx->width = 1280; codec_ctx->height = 720; codec_ctx->time_base.num = 1; codec_ctx->time_base.den = 30; codec_ctx->framerate.num = 30; codec_ctx->framerate.den = 1; codec_ctx->gop_size = 30; codec_ctx->pix_fmt = AV_PIX_FMT_YUV420P; codec_ctx->profile = FF_PROFILE_H264_HIGH; // 设置 profile codec_ctx->level = 41; // 设置 level av_dict_set(&opts, "preset", "medium", 0); av_dict_set(&opts, "tune", "zerolatency", 0); if (avcodec_open2(codec_ctx, codec, &opts) < 0) { fprintf(stderr, "Failed to open codec\n"); return 1; } // ... avcodec_close(codec_ctx); avcodec_free_context(&codec_ctx); av_dict_free(&opts); return 0; } ``` 在上面的代码中,`codec_ctx->profile` 和 `codec_ctx->level` 分别用于设置 H.264 编码器的 profilelevel。可以通过设置 `codec_ctx->profile` 的值为 `FF_PROFILE_H264_BASELINE`、`FF_PROFILE_H264_MAIN` 或 `FF_PROFILE_H264_HIGH` 来选择不同的 profile。而 `codec_ctx->level` 的值可以设置为对应的 level 值,比如 `10`、`11`、`31`、`41` 等。 需要注意的是,不同的 profilelevel 有不同的编码复杂度和兼容性,需要根据实际情况选择合适的参数。同时,需要使用 FFmpeg 版本 4.0 或以上才支持设置 profilelevel
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值