[FFmpeg-devel] [PATCH v3] avcodec: Add librav1e encoder

James Almer jamrial at gmail.com
Thu May 30 05:12:11 EEST 2019


On 5/29/2019 3:28 PM, Derek Buitenhuis wrote:
> Uses the crav1e C bindings for rav1e.
> 
> Port to the new send/receive API by: James Almer <jamrial at gmail.com>.
> 
> Signed-off-by: Derek Buitenhuis <derek.buitenhuis at gmail.com>
> ---
> Changes since v2:
> 
>     * Removed 4:0:0 support; seems broken in rav1e (ref: https://github.com/xiph/rav1e/issues/1312)
>     * Moved to use FF_CODEC_CAP_INIT_CLEANUP.
>     * Set time base for ratecontrol purposes (tested, as well).
>     * Used desc->nb_components for loop.
> ---
>  configure              |   4 +
>  doc/encoders.texi      |  29 +++
>  doc/general.texi       |   7 +
>  libavcodec/Makefile    |   1 +
>  libavcodec/allcodecs.c |   1 +
>  libavcodec/librav1e.c  | 415 +++++++++++++++++++++++++++++++++++++++++
>  6 files changed, 457 insertions(+)
>  create mode 100644 libavcodec/librav1e.c

[...]

> +static av_cold int librav1e_encode_init(AVCodecContext *avctx)
> +{
> +    librav1eContext *ctx = avctx->priv_data;
> +    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt);
> +    RaConfig *cfg = NULL;
> +    int rret;
> +    int ret = 0;
> +
> +    cfg = rav1e_config_default();
> +    if (!cfg) {
> +        av_log(avctx, AV_LOG_ERROR, "Could not allocate rav1e config.\n");
> +        ret = AVERROR_EXTERNAL;

You can return directly here.

> +        goto end;
> +    }
> +
> +    rav1e_config_set_time_base(cfg, (RaRational) {
> +                               avctx->time_base.num * avctx->ticks_per_frame,
> +                               avctx->time_base.den
> +                               });
> +
> +    if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
> +         const AVBitStreamFilter *filter = av_bsf_get_by_name("extract_extradata");
> +         int bret;
> +
> +         if (!filter) {
> +            av_log(avctx, AV_LOG_ERROR, "extract_extradata bitstream filter "
> +                   "not found. This is a bug, please report it.\n");
> +            ret = AVERROR_BUG;
> +            goto end;
> +         }
> +
> +         bret = av_bsf_alloc(filter, &ctx->bsf);
> +         if (bret < 0) {
> +             ret = bret;
> +             goto end;
> +         }
> +
> +         bret = avcodec_parameters_from_context(ctx->bsf->par_in, avctx);
> +         if (bret < 0) {
> +             ret = bret;
> +             goto end;
> +         }
> +
> +         bret = av_bsf_init(ctx->bsf);
> +         if (bret < 0) {
> +             ret = bret;
> +             goto end;
> +         }
> +    }
> +
> +    if (ctx->rav1e_opts) {
> +        AVDictionary *dict    = NULL;
> +        AVDictionaryEntry *en = NULL;
> +
> +        if (!av_dict_parse_string(&dict, ctx->rav1e_opts, "=", ":", 0)) {
> +            while (en = av_dict_get(dict, "", en, AV_DICT_IGNORE_SUFFIX)) {
> +                int parse_ret = rav1e_config_parse(cfg, en->key, en->value);
> +                if (parse_ret < 0)
> +                    av_log(avctx, AV_LOG_WARNING, "Invalid value for %s: %s.\n", en->key, en->value);
> +            }
> +            av_dict_free(&dict);
> +        }
> +    }
> +
> +    rret = rav1e_config_parse_int(cfg, "width", avctx->width);
> +    if (rret < 0) {
> +        av_log(avctx, AV_LOG_ERROR, "Invalid width passed to rav1e.\n");
> +        ret = AVERROR_INVALIDDATA;
> +        goto end;
> +    }
> +
> +    rret = rav1e_config_parse_int(cfg, "height", avctx->height);
> +    if (rret < 0) {
> +        av_log(avctx, AV_LOG_ERROR, "Invalid width passed to rav1e.\n");
> +        ret = AVERROR_INVALIDDATA;
> +        goto end;
> +    }
> +
> +    rret = rav1e_config_parse_int(cfg, "threads", avctx->thread_count);
> +    if (rret < 0)
> +        av_log(avctx, AV_LOG_WARNING, "Invalid number of threads, defaulting to auto.\n");
> +
> +    if (avctx->bit_rate && ctx->quantizer < 0) {
> +        int max_quantizer = avctx->qmax >= 0 ? avctx->qmax : 255;
> +
> +        rret = rav1e_config_parse_int(cfg, "quantizer", max_quantizer);
> +        if (rret < 0) {
> +            av_log(avctx, AV_LOG_ERROR, "Could not set max quantizer.\n");
> +            ret = AVERROR_EXTERNAL;
> +            goto end;
> +        }
> +
> +        rret = rav1e_config_parse_int(cfg, "bitrate", avctx->bit_rate);
> +        if (rret < 0) {
> +            av_log(avctx, AV_LOG_ERROR, "Could not set bitrate.\n");
> +            ret = AVERROR_INVALIDDATA;
> +            goto end;
> +        }
> +    } else if (ctx->quantizer >= 0) {
> +        rret = rav1e_config_parse_int(cfg, "quantizer", ctx->quantizer);
> +        if (rret < 0) {
> +            av_log(avctx, AV_LOG_ERROR, "Could not set quantizer.\n");
> +            ret = AVERROR_EXTERNAL;
> +            goto end;
> +        }
> +    }
> +
> +    rret = rav1e_config_set_pixel_format(cfg, desc->comp[0].depth,
> +                                         pix_fmt_map(avctx->pix_fmt),
> +                                         chroma_loc_map(avctx->chroma_sample_location),
> +                                         range_map(avctx->color_range));
> +    if (rret < 0) {
> +        av_log(avctx, AV_LOG_ERROR, "Failed to set pixel format properties.\n");
> +        ret = AVERROR_INVALIDDATA;
> +        goto end;
> +    }
> +
> +    /* rav1e's colorspace enums match standard values. */
> +    rret = rav1e_config_set_color_description(cfg, (RaMatrixCoefficients) avctx->colorspace,
> +                                              (RaColorPrimaries) avctx->color_primaries,
> +                                              (RaTransferCharacteristics) avctx->color_trc);
> +    if (rret < 0) {
> +        av_log(avctx, AV_LOG_WARNING, "Failed to set color properties.\n");
> +        if (avctx->err_recognition & AV_EF_EXPLODE) {
> +            ret = AVERROR_INVALIDDATA;
> +            goto end;
> +        }
> +    }
> +
> +    ctx->ctx = rav1e_context_new(cfg);
> +    if (!ctx->ctx) {
> +        av_log(avctx, AV_LOG_ERROR, "Failed to create rav1e encode context.\n");
> +        ret = AVERROR_EXTERNAL;
> +        goto end;
> +    }
> +
> +    ret = 0;
> +
> +end:
> +    if (cfg)

If you change the above then this check becomes unnecessary, as cfg will
never be NULL here.

> +        rav1e_config_unref(cfg);
> +
> +    return ret;
> +}


More information about the ffmpeg-devel mailing list