我有一个使用 ffmpeg 作为后端的 C++ 年工作的图像编码器。我正在拍摄视频并将帧保存为 jpeg,但我很难调整输出 jpeg 的质量。
我尝试过的事情:
设置AVCodecContext
的global_quality
和compression_level
字段。
我也尝试使用AVDictionary
选项设置qscale
,但在那里也没有成功。
我知道这是可能的,因为使用命令行
我可以ffmpeg -i INPUT -q:v 2 output_frame_%02d.jpg
并获得更高质量的图像。
-q
选项的命令行影响两件事
enc_ctx->flags |= AV_CODEC_FLAG_QSCALE;
enc_ctx->global_quality = FF_QP2LAMBDA * qscale;
其中enc_ctx是输出流的 AVCodecContext,FF_QP2LAMBDA是 118
当您使用接口函数时,例如
avcodec_decode_video2
avcodec_encode_video2
avcodec_send_frame
avcodec_receive_packet
flags
和global_quality
不起作用。您应该在./libavcodec/mpegvideo_enc.c中static int encode_picture(MpegEncContext *s, int picture_number)
修改第3814 行:
...
if (estimate_qp(s, 0) < 0)
return -1;
s->qscale = 5; //modify qscale here
if (s->qscale < 3 && s->max_qcoeff <= 128 &&
s->pict_type == AV_PICTURE_TYPE_I &&
!(s->avctx->flags & AV_CODEC_FLAG_QSCALE))
s->qscale= 3; //reduce clipping problems
...
就我而言,设置global_quality不起作用。
我更改了 qmin 而不是 global_quality它起作用了。
jpegContext->flags |= AV_CODEC_FLAG_QSCALE;
jpegContext->qmin = 3;
或更改 pFrame 的质量
jpegContext->flags |= AV_CODEC_FLAG_QSCALE;
pFrame->quality = FF_QP2LAMBDA * qscale;
有关实际示例,请参阅此项目