音视频编解码 -- 编码参数 CRF

news2024/11/24 7:01:05

之前多多少少接触过一些编解码参数,CRF 参数也用过,但是最近在和朋友们聊天时,说到使用 FFMPEG 过程中碰到 CRF 参数,以及具体作用流程,这个之前一直没有跟踪过,也没有详细记录过,所以吊起了自己的好奇心,于是决定搞清楚一下,便开始了这次 CRF 的神奇之旅。CRF 简介:

恒定速率因子(CRF,Constant Rate Factor)是一种编码模式,可以向上或向下调整文件数据速率以达到选定的质量级别,而不是特定的数据速率。

如果要保持最佳质量,而又不怎么担心文件大小,这时候就可以使用 CRF 速率控制模式。 这是大多数情况下建议的速率控制模式。当输出文件的大小不太重要时,此方法允许编码器尝试为整个文件实现期望目标视频质量的文件输出,即所谓的一次编码便可在预期视频质量下获得最大的视频压缩效率。CRF 模式主要原理是在编码过程中通过动态调整每帧视频的 QP 值,以便可以获得保持所需视频质量水平比特率。

但是 CRF 缺点是不能告知编码器期望获得特定大小的文件或不超过特定大小或比特率。同时需要注意的是采用 CRF 时不建议直接用来编码视频以进行流媒体传输。

通常建议一般使用两种速率控制模式:恒定速率因子(CRF)或 2-pass ABR。 速率控制决定每个帧将使用多少位。 这将确定文件大小以及质量分配方式。CRF 实操演示

通过 FFMPEG 二进制文件尝试用参数 CRF 进行压缩,如下图所示:

FFMPEG 采用 CRF 分别为 18、24 进行压缩,以及和源文件的比较。

ffmpeg -i test.mp4 -c:v libx264 -crf 18 test18.mp4

实际转码中

转码结束后,会显示具体的编码相关信息,包括 ref,crf 值,qp 量化步长等,以及 I 帧、P 帧、B 帧所占比重。还包含了音频相关信息如下图:

用命令 ffmpeg -i test.mp4 -c:v libx264 -crf 24 test24.mp4,进行 CRF=24 的转码,转码结果如下图所示:

转码后分别对三个文件进行参数查看,并形成对比,其结果如下图所示:

上述参数只能大概了解三个视频基本信息,之后通过 Elecard eye 专业工具查看该变化产生原因的直观图,三个文件码流分析结果:

三个文件对比情况总结如下:

可以看出:CRF 参数的使用,I 帧数量急剧减少、同时引入 B 帧;熵编码采用了 CABAC 方式,这样压缩率就提升很多,文件大小变小。同时随着 CRF 值变大,P 帧和 B 帧压缩率也变大,文件更小。CRF 代码走读

虽然之前走读过 FFMPEG 代码,但是具体 CRF 参数的品读还没完全注意到过。为了不是一知半解的明白该问题,还是强迫自己走一遍代码,增强印象,深刻认识,也为关心该参数的小伙伴铺垫一下基础。*•CRF 定义

【学习地址】:FFmpeg/WebRTC/RTMP/NDK/Android音视频流媒体高级开发
【文章福利】:免费领取更多音视频学习资料包、大厂面试题、技术视频和学习路线图,资料包括(C/C++,Linux,FFmpeg webRTC rtmp hls rtsp ffplay srs 等等)有需要的可以点击1079654574加群领取哦~

  

首先在 X264 中可以看到该值的定义:

typedef struct X264Context {
    AVClass        *class;
    x264_param_t    params;
    ......
​
    float crf;
​
    ......
    }

在 AVOption 具体定义如下:

static const AVOption options[] = {
    { "preset",        "Set the encoding preset (cf. x264 --fullhelp)",   OFFSET(preset),        AV_OPT_TYPE_STRING, { .str = "medium" }, 0, 0, VE},
    { "tune",          "Tune the encoding params (cf. x264 --fullhelp)",  OFFSET(tune),          AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE},
    { "profile",       "Set profile restrictions (cf. x264 --fullhelp) ", OFFSET(profile),       AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE},
......
    {"x264opts", "x264 options", OFFSET(x264opts), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, VE},
    { "crf",           "Select the quality for constant quality mode",    OFFSET(crf),           AV_OPT_TYPE_FLOAT,  {.dbl = -1 }, -1, FLT_MAX, VE },
    { "crf_max",       "In CRF mode, prevents VBV from lowering quality beyond this point.",OFFSET(crf_max), AV_OPT_TYPE_FLOAT, {.dbl = -1 }, -1, FLT_MAX, VE },
......
}

CRF 仍然属于 Rate control 的一中,所以可以看到其 RC 相关定义如下:

#define X264_RC_CQP                  0
#define X264_RC_CRF                  1
#define X264_RC_ABR                  2

•FFMPEG 接口梳理

涉及到 FFMPEG 代码走读的部分太多了,在此只是简述 CRF 对应的部分,其他编解码流程大家可以根据网上其他大神的代码走读流程完成即可。此篇文章默认大家有足够基础:X264 的编解码入口符合 FFMPEG 接口定义,对应关系如下图所示:

此处借用雷神的一张图说明:(https://blog.csdn.net/leixiaohua1020/article/details/45960409)

  • X264_init()

X264_init 函数主要作用就是将之前赋值和初始化的 option 值依次传递到 libx264 模块中,进行 X264 参数初始化,以及 RC 参数赋值。这些值是从 AVCodecContext 传递过来,以及 X264Context 的默认值。熟悉 FFMPEG 的人都了解,AVCodecContext 中包含输入命令行中编解码选项值,以及 FFMPEG 命令中包含的 option 值,而 X264Context 包含 x264 的相关选项,两者结合构成完整的 x264 编解码选项值。

在 X264_init 的最后,进行 X264Codec 的 OPEN 动作,以及编码全局 header 的动作。

  • x264_param_default

x264_param_default 设置默认参数,包括其他的选项值,在此只关心 CRF 相关选项。x264_param_default 中将 CRF 默认开启,同时设置 CRF 选项 f_rf_constant 置为 23,这也是其他很多文章中讲到的默认值 23 的原因。

同时注意,观察到在 x264_param_default 默认参数中 B 帧是再次设置并置位的,而且 cabac 默认开启。所以如果用 FFMPEG bin 文件进行转码出来的文件中 cabac 是默认开启的,这也是工具端查看时会出现 CABAC 以及增加 B 帧的根本原因了。

  • x264_encoder_open

在初始化具体参数后,init 函数接下来进行 x264_encoder_open(相关代码位于 encoder\encoder.c)的操作,这时会具体打开到 x264 中 h264 相关编码器。

之后在 x264_encoder_open 中主要用于打开编码器,其中校验、初始化了 libx264 编码所需要的各种变量,并完成 sps、pps、qm 初始化。

  • validate_parameters

调用 validate_parameters 会进行输入参数的校验,防止输入参数异常导致编码失败。此函数中完成 CRF 相关参数校验、更新和赋值。

其他流程部分可以参考其他大神的文章,再次不再累述。(雷神的解析非常详尽了,敬请膜拜即可x264源代码简单分析:编码器主干部分-1_雷霄骅(leixiaohua1020)的专栏-CSDN博客)

  • x264_ratecontrol_new

x264_encoder_open 最后会调用 x264_ratecontrol_new 完成码率控制相关变量初始化。

x264_ratecontrol_new,主要设置码率控制的核心参数,需要对 x264 码率控制比较了解才能真正明白,否则会容易看晕。

x264_ratecontrol_new 函数中依据传入参数是 CRF 模式,以及 b_stat_read 默认值为 0 即可将 b_abr 参数的置位为 1,同时 b_2pass 置位为 0,也就是说 CRF 模式在 rate_control 中按照 abr、非 2-pass 进行处理的。

在 x264_ratecontrol_init_reconfigurable 函数中会进行 VBV 参数初始化,以及 CRF 相关参数 base_cplx、rate_factor_constant 的更新。

同时 x264_ratecontrol_init_reconfigurable 中设置被调用时,传入 b_init=1 的参数,这时 CRF 置位了 VBV 模式,为后续的 rate_control 做了铺垫。

  • X264_frame

X264_frame()用于依据传入 packet 数据进行一帧视频数据的完整编码。该函数部分定义如下所示。

  • reconfig_encoder

reconfig_encoder 主要作用就是将 RC 相关的参数和 AVCodecContext 中参数进行比较,如果不一致,则重新配置编码器。比如 CRF 值初始设置为 24,但是命令行中设置为 18,这时两个值不一致,则需要按照命令行中值进行赋值并重新配置编码器,以便最终符合用户预期。具体配置大家简单看一下就好,这里不再展开。

  • x264_encoder_encode

x264_encoder_encode 是真正编码的开始,在 x264_encoder_encode 这个函数里面将一帧完整 YUV 图像编码成 H264 视频流,这个过程可以参考雷神的文章,解析非常好,blog.csdn.net/leixiaohua1…

这边关心的是 CRF 中涉及到的部分内容,在 x264_encoder_encode 中和码率控制相关的内容主要是一下接口:

x264_thread_sync_ratecontrol():

x264_ratecontrol_zone_init():

x264_ratecontrol_start():开启码率控制,针对每一帧进行码率控制。在 x264_ratecontrol_start 中会根据码率控制模式的不同,选择不同的 qp 进行压缩。之前分析可知,CRF 是属于 abr 模式,同时增加了 B 帧,所以导致每帧图像的 qp 都是不同的,这样压缩后相同质量的条件下编码后文件大小就不能确定了。

x264_ratecontrol_qp():

码率控制是一个大块内容,设计的算法也比较复杂,该文只关注了如何将 crf 模式转换到 vbv 模式,以及对影响编码的部分参数,整个过程下一篇文章我们再进行分析和跟踪。

以上是个人的一些看法,可能有不正确的地方,欢迎大家一起讨论学习。

如果该文章对您有帮忙,欢迎点赞,收藏,转发、关注,在下持续更新音视频相关内容。

作者:声网

链接:音视频编解码 -- 编码参数 CRF - 掘金 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/91365.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【笔记】计算机组成原理复习重点——篇四

计算机组成原理复习重点笔记 第4章 存 储 器 4.1 概述 存储一个二进制位的物理器件叫存储元。地址码相同的多个存储元构成一个存储单元。若干个存储单元构成存储体。多个存储体构成存储器。多个存储器构成存储体系。存储元→存储单元→存储体→存储器→存储体系 4…

pytorch实现运动鞋分类

🍨 本文为🔗365天深度学习训练营 中的学习记录博客🍦 参考文章地址: 365天深度学习训练营-第P5周:运动鞋分类🍖 作者:K同学啊一、前期准备 1. 设置GPU import torch from torch import nn imp…

Spring Batch 批处理-作业监听器

引言 接着上篇:Spring Batch 批处理-作业增量参数,了解作业参数增量器后,本篇就来了解一下Spirng Batch 作业监听器,看能玩出啥花样。 作业监听器 Spring Batch 步骤/作业的设计延续Spring传统设计模式,加入生命周期…

「Electron|快速开始」来写个Hello World桌面应用吧

本文主要介绍如何快速使用Electron生成一个Hello World应用 文章目录主要步骤一、准备工作创建项目安装electron二、编写electron应用所需的基本内容首先,我们需要给electron应用一个入口创建窗口往窗口里面放一个HTML界面,写上"Hello World!"…

计算机网络技术-常见网络命令

文档下载:https://download.csdn.net/download/weixin_57836618/87294136 实验2 常见网络命令 1. 实验目的与意义 ① 通过实验熟悉与网络相关的组件的含义和用途。 ② 了解系统网络命令的含义、用途和操作方法。 ③ 能够查看网络的状态,对网络进行简…

DEiT实战:使用DEiT实现图像分类任务(一)

DEiT实战摘要安装包安装timm数据增强Cutout和MixupEMA项目结构计算mean和std生成数据集摘要 DEiT是FaceBook在2020年提出的一篇Transformer模型。该模型解决了Transformer难以训练的问题,三天内使用4块GPU,完成了ImageNet的训练,并且没有使用…

mPEG-N3;mPEG-Azide;甲氧基聚乙二醇叠氮CAS:89485-61-0

叠氮化物/叠氮基官能化的甲氧基聚乙二醇(mPEG-N3)是一种单官能PEG衍生物,可用于修饰蛋白质,肽和其他材料。 叠氮化物基团可以在铜催化的水溶液中与炔烃反应。 也可以容易地还原成胺基。 名称 甲氧基聚乙二醇叠氮 mPEG-N3 别称 甲…

周志华 《机器学习初步》模型评估与选择

周志华 《机器学习初步》模型评估与选择 Datawhale2022年12月组队学习 ✌ 文章目录周志华 《机器学习初步》模型评估与选择一.泛化能力二.过拟合和欠拟合泛化误差 VS 经验误差过拟合 VS 欠拟合三.模型选择的三大问题如何获得测试结果:评估方法如何评估性能优劣&…

工厂设备管理中经常会遇到哪些问题?

我调查过上百家企业的设备管理问题,发现大家认为所有设备管理问题中,最典型的问题主要包括以下五个方面: 1)领导不重视管理 “生产量是最重要的”、“销售额是最重要”、“重ERP,轻现场管理”……等管理理念是企业中的…

镜像法的理解——工程电磁场 P9

模型一:无限大导体平面 此处有几点理解需要格外谈一下 1. 只有在有电力线的地方,才会产生电场的作用 2.对于下平面的分析,下平面如果存在电荷的话,必然存在电力线,那么从无穷远处做功到此处,必然会存在电…

Java网络多线程——UDP编程

UDP编程通信 基本介绍 类DatagramSocket和DatagramPacket【数据包/数据报】实现了基于UDP协议网络程序。UDP数据报通过数据报套接字DatagramSocket发送和接收,系统不保证UDP数据报一定能安全送到目的地,也不确信什么时候可以抵达。DatagramPacket对象封…

从「堆叠」到「降本」,智能汽车传感器颠覆性革命即将到来!

随着汽车智能化的演进,传感器的堆叠造成了整车成本的急剧上升。尤其是多传感器融合(摄像头、毫米波雷达和激光雷达)技术作为当下的主流趋势之一,焦点依然回到成本层面。 同时,传统的整车电子架构和计算能力的限制&…

Flutter 小技巧之快速理解手势逻辑

又到了小技巧系列更新时间,今天我们主要分享 Flutter 里的手势触摸逻辑,其实在很久之前我就写过 《面深入触摸和滑动原理》相关的源码分析文章,但是最近有人说源码分析看不懂,有没有简要好理解的,那么本篇就用更简单的…

[附源码]Node.js计算机毕业设计高校图书馆网站Express

项目运行 环境配置: Node.js最新版 Vscode Mysql5.7 HBuilderXNavicat11Vue。 项目技术: Express框架 Node.js Vue 等等组成,B/S模式 Vscode管理前后端分离等等。 环境需要 1.运行环境:最好是Nodejs最新版,我…

高通平台 5G RF调试总结

目录: 1.QRCT4的使用 2.RFC配置 3.5G CA 配置概括 4.RFPD 运行及错误分析 5.CA吞吐率问题分析 最新的5G HImalyaa平台RFC的配置方法和之前的平台发生了根本性的变化,主要体现在使用QRCT4工具来配置RFC XML文件,然后根据XML文件编译生成s…

MobileNetV3原理说明及实践落地

本文参考: pytorch实现并训练MobileNetV3 - 灰信网(软件开发博客聚合) 【神经网络】(16) MobileNetV3 代码复现,网络解析,附Tensorflow完整代码 - 代码天地 1 MobileNetV3与V1、V2对比 (1)Mob…

【LeetCode每日一题:1945. 字符串转化后的各位数字之和~~~模拟】

题目描述 给你一个由小写字母组成的字符串 s ,以及一个整数 k 。 首先,用字母在字母表中的位置替换该字母,将 s 转化 为一个整数(也就是,‘a’ 用 1 替换,‘b’ 用 2 替换,… ‘z’ 用 26 替换…

匿名浏览器是什么?为什么联盟营销需要借助匿名浏览器?

这段时间小伙伴们都对联盟营销很感兴趣,东哥也是陆陆续续出了两三篇相关的科普文章,今天继续给大家介绍匿名浏览器在联盟营销上的帮助,毕竟互联网时代,学会如何借助工具高效工作是很重要的。关于联盟营销的概念科普文章大家可以看…

学不会的python之通过某几个关键字排序、分组一个字典列表(列表中嵌套字典)

通过某个关键字排序、分组一个字典列表排序问题描述解决方案1.operator 模块的 itemgetter 函数2.lambda 表达式引申分组问题描述解决方案1.itertools.groupby() 函数2.defaultdict() 构建多值字典排序 问题描述 现在你有一个字典列表(列表中嵌套字典),你想要根据…

web 向 unity 传输文件流 blob 记录

场景:web 与unity 通信,向 unity 传输文件 二进制流。 由 unity 转换并下载文件。 流程: web 端将缓存的 blob 数据流读取为 base64 编码的数据 → 传给 unity, →unity 解码转换 base64 数据并下载。 web 端: 1、 将数据转换成…