音视频基础扫盲之视频码率控制策略(CBR、VBR还是ABR)
视频码率控制策略
CBR(Constant Bit Rate)、VBR(Variable Bit Rate)和ABR(Average Bit Rate)是三种常见的比特率控制方式,以视频码率控制为例,视频码率控制策略主要是在保证视频质量的前提下,尽可能地降低码率以减少存储和传输成本。
一、固定码率(CBR)
-
原理:
- 固定码率控制策略使视频在整个编码过程中保持恒定的码率。无论视频内容的复杂程度如何变化,编码器都会努力将输出码率控制在一个固定的值。
- 编码器通过调整量化参数(QP)等参数来实现码率的稳定。当视频画面比较复杂时,可能会牺牲一定的图像质量以保持码率不超过设定值;当画面相对简单时,也不会降低码率以提高图像质量。
-
应用场景:
- 适用于对带宽要求严格的场景,如网络直播、视频会议等。在这些场景中,稳定的码率可以确保视频流的流畅传输,避免因码率波动导致的卡顿和缓冲。
- 例如,在网络直播中,如果码率波动过大,可能会导致观众端的播放卡顿,影响观看体验。使用 CBR 可以保证直播流的码率稳定,让观众能够流畅地观看直播。
二、可变码率(VBR)
-
原理:
- 可变码率控制策略允许码率根据视频内容的复杂程度动态变化。编码器会分析视频的每一帧,对于复杂的帧分配较高的码率以保证图像质量,对于简单的帧分配较低的码率以节省空间。
- VBR 通常有不同的质量模式可供选择,如高质量模式、中等质量模式和低质量模式等。高质量模式会在保证图像质量的前提下尽量提高码率,而低质量模式则会更严格地控制码率以降低文件大小。
-
应用场景:
- 适用于对视频质量要求较高的场景,如视频制作、电影存储等。在这些场景中,可以根据视频内容的复杂程度自动调整码率,以在保证图像质量的同时尽可能地减少文件大小。
- 例如,在制作高清电影时,使用 VBR 可以在保证画面质量的前提下,对于一些静态场景或简单画面降低码率,从而减少存储成本。
三、平均码率(ABR)
-
原理:
- 平均码率控制策略是一种介于 CBR 和 VBR 之间的方法。它设定一个平均码率目标,编码器在编码过程中会尽量使整个视频的平均码率接近这个目标值。
- 与 CBR 不同的是,ABR 允许码率在一定范围内波动;与 VBR 不同的是,ABR 会更加注重整体的平均码率控制,而不是完全根据每一帧的复杂程度来调整码率。
-
应用场景:
- 适用于一些对码率稳定性和视频质量都有一定要求的场景,如在线视频播放、视频点播等。在这些场景中,既需要保证视频流的相对稳定,又希望能够在一定程度上根据视频内容调整码率以提高图像质量。
- 例如,在在线视频播放平台上,使用 ABR 可以在保证视频流基本稳定的前提下,对于一些精彩的画面或复杂场景适当提高码率,以提升用户的观看体验。
四、基于内容感知的码率控制
-
原理:
- 这种码率控制策略利用人工智能和机器学习技术,对视频内容进行分析和理解。编码器会根据视频的场景、物体、运动等特征来动态调整码率分配。
- 例如,对于画面中的重要物体或人物,可以分配较高的码率以保证清晰显示;对于背景或不太重要的区域,可以分配较低的码率以节省空间。
-
应用场景:
- 适用于对视频质量和用户体验要求较高的场景,如智能监控、虚拟现实等。在这些场景中,通过对视频内容的智能分析,可以更好地满足用户的需求,提高视频的观看效果。
- 例如,在智能监控系统中,基于内容感知的码率控制可以对监控画面中的关键区域(如入口、重要设备等)分配较高的码率,以便在需要时能够清晰地查看这些区域的情况。
应用举例
以大牛直播SDK的Android平台RTMP推送模块为例,我们在视频软、硬编码设计接口设计的时候,也做了相应的支持。
以硬编码为例,接口设计如下:
/*
* SmartPublisherJniV2.java
* Copyright © 2014~2024 daniusdk.com All rights reserved.
* WeChat: xinsheng120
*/
/**
* Set Video H.264 HW Encoder, if support HW encoder, it will return 0(设置H.264硬编码)
*
* @param kbps: the kbps of different resolution.
*
* @return {0} if successful
*/
public native int SetSmartPublisherVideoHWEncoder(long handle, int kbps);
/**
* Set Video H.265(hevc) hardware encoder, if support H.265(hevc) hardware encoder, it will return 0(设置H.265硬编码)
*
* @param kbps: the kbps of different resolution.
*
* @return {0} if successful
*/
public native int SetSmartPublisherVideoHevcHWEncoder(long handle, int kbps);
/**
* 设置视频硬编码是否使用 Native Media NDK, 默认是不使用, 安卓5.0以下设备不支持
* @param handle
* @param is_native: 0表示不使用, 1表示使用, sdk默认是0.
* @return {0} if successful
*/
public native int SetNativeMediaNDK(long handle, int is_native);
/*
* 设置视频硬编码码率控制模式
* @param hw_bitrate_mode: -1表示使用默认值, 不设置也会使用默认值, 0:CQ, 1:VBR, 2:CBR, 3:CBR_FD, 请参考:android.media.MediaCodecInfo.EncoderCapabilities
* 注意硬编码和手机硬件有关,多数手机只支持部分码率模式, 另外硬编码设备差异很大,不同设备同一码率控制模式效果可能不一样
* @return {0} if successful
*/
public native int SetVideoHWEncoderBitrateMode(long handle, int hw_bitrate_mode);
/*
* 设置视频硬编码复杂度, 安卓5.0及以上支持
* @param hw_complexity: -1表示不设置, 请参考:android.media.MediaCodecInfo.EncoderCapabilities.getComplexityRange() 和 android.media.MediaFormat.KEY_COMPLEXITY
* 注意硬编码和手机硬件有关,部分手机可能不支持此设置
* @return {0} if successful
*/
public native int SetVideoHWEncoderComplexity(long handle, int hw_complexity);
/*
* 设置视频硬编码质量, 安卓9及以上支持, 仅当硬编码器码率控制模式(BitrateMode)是CQ(constant-quality mode)时才有效
* @param hw_quality: -1表示不设置, 请参考:android.media.MediaCodecInfo.EncoderCapabilities.getQualityRange() 和 android.media.MediaFormat.KEY_QUALITY
* 注意硬编码和手机硬件有关,部分手机可能不支持此设置
* @return {0} if successful
*/
public native int SetVideoHWEncoderQuality(long handle, int hw_quality);
/*
* 设置H.264硬编码Profile, 安卓7及以上支持
* @param hw_avc_profile: 0表示使用默认值, 0x01: Baseline, 0x02: Main, 0x08: High, 0x10000: ConstrainedBaseline, 0x80000: ConstrainedHigh;
* 注意: ConstrainedBaseline 和 ConstrainedHigh 可能多数设备不支持,
* H.264推荐使用 High 或者 ConstrainedHigh, 如果您使用的手机硬解码解不了,那还是设置Baseline
* 如果设置的Profile硬编码器不支持,应编码器会使用默认值
* 具体参考:android.media.MediaCodecInfo.CodecProfileLevel
* @return {0} if successful
*/
public native int SetAVCHWEncoderProfile(long handle, int hw_avc_profile);
/*
* 设置H.264硬编码Level, 这个只有在设置了Profile的情况下才有效, 安卓7及以上支持
* @param hw_avc_level: 0表示使用默认值, 0x100: Level3, 0x200: Level3.1, 0x400: Level3.2,
* 0x800: Level4, 0x1000: Level4.1, 0x2000: Level4.2,
* 0x4000: Level5, 0x8000: Level5.1, 0x10000: Level5.2,
* 0x20000: Level6, 0x40000: Level6.1, 0x80000: Level6.2,
* 如果设置的level太高硬编码器不支持,SDK内部会做相应调整
* 注意: 640*480@25fps最小支持的是Level3, 720p最小支持的是Level3.1, 1080p最小支持的是Level4
* 具体参考:android.media.MediaCodecInfo.CodecProfileLevel
* @return {0} if successful
*/
public native int SetAVCHWEncoderLevel(long handle, int hw_avc_level);
感兴趣的开发者,可以酌情参考,有问题可以单独跟我探讨。