首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无法复制FFMpeg Prores质量设置

无法复制FFMpeg Prores质量设置
EN

Stack Overflow用户
提问于 2017-02-03 19:55:29
回答 1查看 408关注 0票数 1

使用ffmpeg作为图书馆。我希望创造一个全球质量滑块与非常不一致的结果。AvCodecContext::global_quality似乎是一个很好的起点。并非所有有损编解码器都引用此成员,但它似乎适用于ProRes。

代码语言:javascript
复制
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。

代码语言:javascript
复制
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的摘录

代码语言:javascript
复制
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:输出

代码语言:javascript
复制
profile 4, 1020 slices, interlacing: no, 6576 bits per MB
frame size upper bound: 11429274

在我的应用程序:上从ffmpeg avlog输出的

代码语言:javascript
复制
profile 4, 1020 slices, interlacing: no, 1425 bits per MB
frame size upper bound: 6170103
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-02-03 21:22:11

有一些黑客支持旧的编解码器。因此输入值在内部被乘以。一个人需要和ffmpeg.exe做同样的事情

代码语言:javascript
复制
#define FF_QP2LAMBDA 118

//from ffmpeg_opt.c

ost->enc_ctx->global_quality = FF_QP2LAMBDA * qscale;
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42032065

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档