ffmpeg输出q=28什么意思?
微wx笑 2023-03-05【音频视频】 2 0关键字: ffmpeg
参考:ffmpeg命令分析-print命令如下:ffmpeg -i a.mp4 -vcodec libx264 -preset placebo output.mp4本文不讲上面的命令行参数实现,而是打算讲解,ffmpeg 转码过程中输出的 frame
参考:ffmpeg命令分析-print
命令如下:ffmpeg -i a.mp4 -vcodec libx264 -preset placebo output.mp4
本文不讲上面的命令行参数实现,而是打算讲解,ffmpeg 转码过程中输出的 frame ,fps,q,size, bitrate ,speed 的意义,如下图。
最重要的是speed,转码速度
从ffmpeg.c 里可以看出,上面的红色圈出来的是 print_report() 函数打印的,下面就来分析 print_report() 的实现,流程图如下:
print_report() 入口会做一个时间判断,每 隔0.5 秒才打印一次日志,代码如下:
if (!is_last_report) {
if (last_time == -1) {
last_time = cur_time;
return;
}
//50万微妙,0.5秒统计一次。
if ((cur_time - last_time) < 500000) //注意这里
return;
last_time = cur_time;
}
后续的代码没有什么好分析,逻辑比较简单,自行查看即可。
frame= 160 fps= 37 q=28.0 size= 0kB time=00:00:07.23 bitrate= 0.1kbits/s speed=1.68x
打印日志的参数解析如下:
1,frame ,用的是 ost->frame_number 赋值,代表当前编码到视频流的第几帧。
2,fps,用上面的 frame 除以时间得到,代表一秒编码了多少个视频帧。
3,q,编码质量,也是针对视频的。q 的计算方式如下:
q = ost->quality / (float) FF_QP2LAMBDA;
可以看到,q 是 从ost->quality 来的,那 ost->quality 的值是在哪里赋值的呢?代码如下:
ffmpeg.c 742行
uint8_t *sd = av_packet_get_side_data(pkt, AV_PKT_DATA_QUALITY_STATS,NULL);
ost->quality = sd ? AV_RL32(sd) : -1;
可以看到,流的质量quality,应该是一个累计的值。我个人猜测编码器会根据以往编码的Frame 不断计算这个值,然后放进去 AVPacket 的side_data 里面。
可以 av_packet_get_side_data() 获取到 side_data,side_data 的前32位就是 quality,AV_PKT_DATA_QUALITY_STATS 这个side_data的定义如下。
libavcodec\avcodec.h 1266行
/**
* This side data contains quality related information from the encoder.
* @code
* u32le quality factor of the compressed frame. Allowed range is between 1 (good) and FF_LAMBDA_MAX (bad).
* u8 picture type
* u8 error count
* u16 reserved
* u64le[error count] sum of squared differences between encoder in and output
* @endcode
*/
AV_PKT_DATA_QUALITY_STATS,
前面 3个参数都是针对 视频流 的分析
4,size,写入文件的数据大小,通过 avio_size(oc->pb) 获得。
5,bitrate,比特率,这个bitrate 的单位是 kbits/s ,不是 kb/s ,要注意。 kbits/s 是指每秒传输多少千比特,一个字节有8个比特。
所以源码里 bitrate 的计算方式如下:
ffmpeg.c 1769行
bitrate = pts && total_size >= 0 ? total_size * 8 / (pts / 1000.0) : -1;
total_size 是avio_size() 返回的,单位是字节,所以乘以 8,pts 的单位是微妙,除以1000后等于 千分之一秒。千分之一秒能传输 ( total_size * 8) 大小的比特。那1秒就能够传输 ( total_size * 8) * 1000 大小的比特。但是输出的单位不是比特,而是千比特,kbits,前面有个k,所以这个乘以1000就可以抵消掉。就形成源码的计算方式。
6,speed,编码速度。用输出流的最后一个AVPacket的pts 除以程序运行时间。哪个流的最后AVPacket的pts最大就以哪个流的pts为准,输出流最后一个AVPacket的pts通过函数 av_stream_get_end_pts() 获得。
这样就比较好理解了,如果现在已经编码到视频流的第10秒的数据帧,但是转码程序只运行了2秒,那speed转码速度就是 10 /2 ,speed等于5.
ffmpeg.c 1770行
speed = t != 0.0 ? (double)pts / AV_TIME_BASE / t : -1;
print_report 里面 的qp_hist 跟 AV_CODEC_FLAG_PSNR 本次不讲解,因为我也不知道是做什么的
————————————————
版权声明:本文为CSDN博主「Loken2020」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u012117034/article/details/123453863
本文由 微wx笑 创作,采用 署名-非商业性使用-相同方式共享 4.0 许可协议,转载请附上原文出处链接及本声明。
原文链接:https://www.ivu4e.cn/toolbox/media/2023-03-05/1743.html