使用ffmpeg作为图书馆。我希望创造一个全球质量滑块与非常不一致的结果。AvCodecContext::global_quality似乎是一个很好的起点。并非所有有损编解码器都引用此成员,但它似乎适用于ProRes。
c:\>ffmpeg.exe -i test.mov -c:v prores_ks -q:v 28 out.mov # output 10mb file
c:\>ffmpeg.exe -i test.mov -c:v prores_ks -q:v 2 out.mov # output 28mb file太棒了。现在让我们用代码来做。基于Muxing.c。我对代码进行了大量的提炼,只是为了提示我调用哪个api。
AVStream* AddStream(AVFormatContext* formatContext, int quality)
{
AVCodec* codec = AVFindEncoder("prores_ks");
AVStream* newStream = avformat_new_stream(formatContext, codec);
newStream->id = formatContext->nb_streams - 1;
AVCodecContext c = avcodec_alloc_context3(codec);
c->codec_id = AV_CODEC_ID_PRORES;
c->codec_type = AVMEDIA_TYPE_VIDEO;
c->width = 1920;
c->height = 1080;
newStream->time_base = av_inv_q(frameRate);
c->time_base = av_inv_q(frameRate);
c->pix_fmt = AV_PIX_FMT_YUVA444P10;
c->global_quality = quality;
return newStream;
}
......
//excerpt from WriteFrame()
AVPacket pkt;
av_init_packet(&pkt);
pkt.data= pVideoBuffer;
pkt.size= iVideoBufferSize;
int gotpkt = 0;
int ret = avcodec_encode_video2(pCodecContext, &pkt, pPicture, &gotpkt);
if (ret == 0)
{
av_packet_rescale_ts(&pkt, pCodecContext->time_base, pVideoStream->time_base);
if (gotpkt) {
ret = av_interleaved_write_frame(pFormatContext, &pkt);
}
}我无法获得质量来影响输出的大小。有什么想法吗?
这是proresenc_kostya.c的摘录
ctx->force_quant = avctx->global_quality / FF_QP2LAMBDA;
if (!ctx->force_quant) {
if (!ctx->bits_per_mb) {
for (i = 0; i < NUM_MB_LIMITS - 1; i++)
if (prores_mb_limits[i] >= ctx->mb_width * ctx->mb_height *
ctx->pictures_per_frame)
break;
ctx->bits_per_mb = ctx->profile_info->br_tab[i];
} else if (ctx->bits_per_mb < 128) {
av_log(avctx, AV_LOG_ERROR, "too few bits per MB, please set at least 128\n");
return AVERROR_INVALIDDATA;
}
min_quant = ctx->profile_info->min_quant;
max_quant = ctx->profile_info->max_quant;
for (i = min_quant; i < MAX_STORED_Q; i++) {
for (j = 0; j < 64; j++)
ctx->quants[i][j] = ctx->quant_mat[j] * i;
}
ctx->slice_q = av_malloc(ctx->slices_per_picture * sizeof(*ctx->slice_q));
if (!ctx->slice_q) {
encode_close(avctx);
return AVERROR(ENOMEM);
}
ctx->tdata = av_mallocz(avctx->thread_count * sizeof(*ctx->tdata));
if (!ctx->tdata) {
encode_close(avctx);
return AVERROR(ENOMEM);
}
for (j = 0; j < avctx->thread_count; j++) {
ctx->tdata[j].nodes = av_malloc((ctx->slices_width + 1)
* TRELLIS_WIDTH
* sizeof(*ctx->tdata->nodes));
if (!ctx->tdata[j].nodes) {
encode_close(avctx);
return AVERROR(ENOMEM);
}
for (i = min_quant; i < max_quant + 2; i++) {
ctx->tdata[j].nodes[i].prev_node = -1;
ctx->tdata[j].nodes[i].bits = 0;
ctx->tdata[j].nodes[i].score = 0;
}
}
} 编辑:
来自的ffmpeg.exe:输出
profile 4, 1020 slices, interlacing: no, 6576 bits per MB
frame size upper bound: 11429274在我的应用程序:上从ffmpeg avlog输出的
profile 4, 1020 slices, interlacing: no, 1425 bits per MB
frame size upper bound: 6170103发布于 2017-02-03 21:22:11
有一些黑客支持旧的编解码器。因此输入值在内部被乘以。一个人需要和ffmpeg.exe做同样的事情
#define FF_QP2LAMBDA 118
//from ffmpeg_opt.c
ost->enc_ctx->global_quality = FF_QP2LAMBDA * qscale;https://stackoverflow.com/questions/42032065
复制相似问题