1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * librav1e encoder 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * Copyright (c) 2019 Derek Buitenhuis 5cabdff1aSopenharmony_ci * 6cabdff1aSopenharmony_ci * This file is part of FFmpeg. 7cabdff1aSopenharmony_ci * 8cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 9cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 10cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 11cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 12cabdff1aSopenharmony_ci * 13cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 14cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 15cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16cabdff1aSopenharmony_ci * Lesser General Public License for more details. 17cabdff1aSopenharmony_ci * 18cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 19cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 20cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21cabdff1aSopenharmony_ci */ 22cabdff1aSopenharmony_ci 23cabdff1aSopenharmony_ci#include <rav1e.h> 24cabdff1aSopenharmony_ci 25cabdff1aSopenharmony_ci#include "libavutil/internal.h" 26cabdff1aSopenharmony_ci#include "libavutil/avassert.h" 27cabdff1aSopenharmony_ci#include "libavutil/base64.h" 28cabdff1aSopenharmony_ci#include "libavutil/common.h" 29cabdff1aSopenharmony_ci#include "libavutil/mathematics.h" 30cabdff1aSopenharmony_ci#include "libavutil/opt.h" 31cabdff1aSopenharmony_ci#include "libavutil/pixdesc.h" 32cabdff1aSopenharmony_ci#include "avcodec.h" 33cabdff1aSopenharmony_ci#include "bsf.h" 34cabdff1aSopenharmony_ci#include "codec_internal.h" 35cabdff1aSopenharmony_ci#include "encode.h" 36cabdff1aSopenharmony_ci#include "internal.h" 37cabdff1aSopenharmony_ci 38cabdff1aSopenharmony_citypedef struct librav1eContext { 39cabdff1aSopenharmony_ci const AVClass *class; 40cabdff1aSopenharmony_ci 41cabdff1aSopenharmony_ci RaContext *ctx; 42cabdff1aSopenharmony_ci AVFrame *frame; 43cabdff1aSopenharmony_ci RaFrame *rframe; 44cabdff1aSopenharmony_ci AVBSFContext *bsf; 45cabdff1aSopenharmony_ci 46cabdff1aSopenharmony_ci uint8_t *pass_data; 47cabdff1aSopenharmony_ci size_t pass_pos; 48cabdff1aSopenharmony_ci int pass_size; 49cabdff1aSopenharmony_ci 50cabdff1aSopenharmony_ci AVDictionary *rav1e_opts; 51cabdff1aSopenharmony_ci int quantizer; 52cabdff1aSopenharmony_ci int speed; 53cabdff1aSopenharmony_ci int tiles; 54cabdff1aSopenharmony_ci int tile_rows; 55cabdff1aSopenharmony_ci int tile_cols; 56cabdff1aSopenharmony_ci} librav1eContext; 57cabdff1aSopenharmony_ci 58cabdff1aSopenharmony_cistatic inline RaPixelRange range_map(enum AVPixelFormat pix_fmt, enum AVColorRange range) 59cabdff1aSopenharmony_ci{ 60cabdff1aSopenharmony_ci switch (pix_fmt) { 61cabdff1aSopenharmony_ci case AV_PIX_FMT_YUVJ420P: 62cabdff1aSopenharmony_ci case AV_PIX_FMT_YUVJ422P: 63cabdff1aSopenharmony_ci case AV_PIX_FMT_YUVJ444P: 64cabdff1aSopenharmony_ci return RA_PIXEL_RANGE_FULL; 65cabdff1aSopenharmony_ci } 66cabdff1aSopenharmony_ci 67cabdff1aSopenharmony_ci switch (range) { 68cabdff1aSopenharmony_ci case AVCOL_RANGE_JPEG: 69cabdff1aSopenharmony_ci return RA_PIXEL_RANGE_FULL; 70cabdff1aSopenharmony_ci case AVCOL_RANGE_MPEG: 71cabdff1aSopenharmony_ci default: 72cabdff1aSopenharmony_ci return RA_PIXEL_RANGE_LIMITED; 73cabdff1aSopenharmony_ci } 74cabdff1aSopenharmony_ci} 75cabdff1aSopenharmony_ci 76cabdff1aSopenharmony_cistatic inline RaChromaSampling pix_fmt_map(enum AVPixelFormat pix_fmt) 77cabdff1aSopenharmony_ci{ 78cabdff1aSopenharmony_ci switch (pix_fmt) { 79cabdff1aSopenharmony_ci case AV_PIX_FMT_YUV420P: 80cabdff1aSopenharmony_ci case AV_PIX_FMT_YUVJ420P: 81cabdff1aSopenharmony_ci case AV_PIX_FMT_YUV420P10: 82cabdff1aSopenharmony_ci case AV_PIX_FMT_YUV420P12: 83cabdff1aSopenharmony_ci return RA_CHROMA_SAMPLING_CS420; 84cabdff1aSopenharmony_ci case AV_PIX_FMT_YUV422P: 85cabdff1aSopenharmony_ci case AV_PIX_FMT_YUVJ422P: 86cabdff1aSopenharmony_ci case AV_PIX_FMT_YUV422P10: 87cabdff1aSopenharmony_ci case AV_PIX_FMT_YUV422P12: 88cabdff1aSopenharmony_ci return RA_CHROMA_SAMPLING_CS422; 89cabdff1aSopenharmony_ci case AV_PIX_FMT_YUV444P: 90cabdff1aSopenharmony_ci case AV_PIX_FMT_YUVJ444P: 91cabdff1aSopenharmony_ci case AV_PIX_FMT_YUV444P10: 92cabdff1aSopenharmony_ci case AV_PIX_FMT_YUV444P12: 93cabdff1aSopenharmony_ci return RA_CHROMA_SAMPLING_CS444; 94cabdff1aSopenharmony_ci default: 95cabdff1aSopenharmony_ci av_assert0(0); 96cabdff1aSopenharmony_ci } 97cabdff1aSopenharmony_ci} 98cabdff1aSopenharmony_ci 99cabdff1aSopenharmony_cistatic inline RaChromaSamplePosition chroma_loc_map(enum AVChromaLocation chroma_loc) 100cabdff1aSopenharmony_ci{ 101cabdff1aSopenharmony_ci switch (chroma_loc) { 102cabdff1aSopenharmony_ci case AVCHROMA_LOC_LEFT: 103cabdff1aSopenharmony_ci return RA_CHROMA_SAMPLE_POSITION_VERTICAL; 104cabdff1aSopenharmony_ci case AVCHROMA_LOC_TOPLEFT: 105cabdff1aSopenharmony_ci return RA_CHROMA_SAMPLE_POSITION_COLOCATED; 106cabdff1aSopenharmony_ci default: 107cabdff1aSopenharmony_ci return RA_CHROMA_SAMPLE_POSITION_UNKNOWN; 108cabdff1aSopenharmony_ci } 109cabdff1aSopenharmony_ci} 110cabdff1aSopenharmony_ci 111cabdff1aSopenharmony_cistatic int get_stats(AVCodecContext *avctx, int eos) 112cabdff1aSopenharmony_ci{ 113cabdff1aSopenharmony_ci librav1eContext *ctx = avctx->priv_data; 114cabdff1aSopenharmony_ci RaData* buf = rav1e_twopass_out(ctx->ctx); 115cabdff1aSopenharmony_ci if (!buf) 116cabdff1aSopenharmony_ci return 0; 117cabdff1aSopenharmony_ci 118cabdff1aSopenharmony_ci if (!eos) { 119cabdff1aSopenharmony_ci uint8_t *tmp = av_fast_realloc(ctx->pass_data, &ctx->pass_size, 120cabdff1aSopenharmony_ci ctx->pass_pos + buf->len); 121cabdff1aSopenharmony_ci if (!tmp) { 122cabdff1aSopenharmony_ci rav1e_data_unref(buf); 123cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 124cabdff1aSopenharmony_ci } 125cabdff1aSopenharmony_ci 126cabdff1aSopenharmony_ci ctx->pass_data = tmp; 127cabdff1aSopenharmony_ci memcpy(ctx->pass_data + ctx->pass_pos, buf->data, buf->len); 128cabdff1aSopenharmony_ci ctx->pass_pos += buf->len; 129cabdff1aSopenharmony_ci } else { 130cabdff1aSopenharmony_ci size_t b64_size = AV_BASE64_SIZE(ctx->pass_pos); 131cabdff1aSopenharmony_ci 132cabdff1aSopenharmony_ci memcpy(ctx->pass_data, buf->data, buf->len); 133cabdff1aSopenharmony_ci 134cabdff1aSopenharmony_ci avctx->stats_out = av_malloc(b64_size); 135cabdff1aSopenharmony_ci if (!avctx->stats_out) { 136cabdff1aSopenharmony_ci rav1e_data_unref(buf); 137cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 138cabdff1aSopenharmony_ci } 139cabdff1aSopenharmony_ci 140cabdff1aSopenharmony_ci av_base64_encode(avctx->stats_out, b64_size, ctx->pass_data, ctx->pass_pos); 141cabdff1aSopenharmony_ci 142cabdff1aSopenharmony_ci av_freep(&ctx->pass_data); 143cabdff1aSopenharmony_ci } 144cabdff1aSopenharmony_ci 145cabdff1aSopenharmony_ci rav1e_data_unref(buf); 146cabdff1aSopenharmony_ci 147cabdff1aSopenharmony_ci return 0; 148cabdff1aSopenharmony_ci} 149cabdff1aSopenharmony_ci 150cabdff1aSopenharmony_cistatic int set_stats(AVCodecContext *avctx) 151cabdff1aSopenharmony_ci{ 152cabdff1aSopenharmony_ci librav1eContext *ctx = avctx->priv_data; 153cabdff1aSopenharmony_ci int ret = 1; 154cabdff1aSopenharmony_ci 155cabdff1aSopenharmony_ci while (ret > 0 && ctx->pass_size - ctx->pass_pos > 0) { 156cabdff1aSopenharmony_ci ret = rav1e_twopass_in(ctx->ctx, ctx->pass_data + ctx->pass_pos, ctx->pass_size); 157cabdff1aSopenharmony_ci if (ret < 0) 158cabdff1aSopenharmony_ci return AVERROR_EXTERNAL; 159cabdff1aSopenharmony_ci ctx->pass_pos += ret; 160cabdff1aSopenharmony_ci } 161cabdff1aSopenharmony_ci 162cabdff1aSopenharmony_ci return 0; 163cabdff1aSopenharmony_ci} 164cabdff1aSopenharmony_ci 165cabdff1aSopenharmony_cistatic av_cold int librav1e_encode_close(AVCodecContext *avctx) 166cabdff1aSopenharmony_ci{ 167cabdff1aSopenharmony_ci librav1eContext *ctx = avctx->priv_data; 168cabdff1aSopenharmony_ci 169cabdff1aSopenharmony_ci if (ctx->ctx) { 170cabdff1aSopenharmony_ci rav1e_context_unref(ctx->ctx); 171cabdff1aSopenharmony_ci ctx->ctx = NULL; 172cabdff1aSopenharmony_ci } 173cabdff1aSopenharmony_ci if (ctx->rframe) { 174cabdff1aSopenharmony_ci rav1e_frame_unref(ctx->rframe); 175cabdff1aSopenharmony_ci ctx->rframe = NULL; 176cabdff1aSopenharmony_ci } 177cabdff1aSopenharmony_ci 178cabdff1aSopenharmony_ci av_frame_free(&ctx->frame); 179cabdff1aSopenharmony_ci av_bsf_free(&ctx->bsf); 180cabdff1aSopenharmony_ci av_freep(&ctx->pass_data); 181cabdff1aSopenharmony_ci 182cabdff1aSopenharmony_ci return 0; 183cabdff1aSopenharmony_ci} 184cabdff1aSopenharmony_ci 185cabdff1aSopenharmony_cistatic av_cold int librav1e_encode_init(AVCodecContext *avctx) 186cabdff1aSopenharmony_ci{ 187cabdff1aSopenharmony_ci librav1eContext *ctx = avctx->priv_data; 188cabdff1aSopenharmony_ci const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt); 189cabdff1aSopenharmony_ci RaConfig *cfg = NULL; 190cabdff1aSopenharmony_ci int rret; 191cabdff1aSopenharmony_ci int ret = 0; 192cabdff1aSopenharmony_ci 193cabdff1aSopenharmony_ci ctx->frame = av_frame_alloc(); 194cabdff1aSopenharmony_ci if (!ctx->frame) 195cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 196cabdff1aSopenharmony_ci 197cabdff1aSopenharmony_ci cfg = rav1e_config_default(); 198cabdff1aSopenharmony_ci if (!cfg) { 199cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Could not allocate rav1e config.\n"); 200cabdff1aSopenharmony_ci return AVERROR_EXTERNAL; 201cabdff1aSopenharmony_ci } 202cabdff1aSopenharmony_ci 203cabdff1aSopenharmony_ci /* 204cabdff1aSopenharmony_ci * Rav1e currently uses the time base given to it only for ratecontrol... where 205cabdff1aSopenharmony_ci * the inverse is taken and used as a framerate. So, do what we do in other wrappers 206cabdff1aSopenharmony_ci * and use the framerate if we can. 207cabdff1aSopenharmony_ci */ 208cabdff1aSopenharmony_ci if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { 209cabdff1aSopenharmony_ci rav1e_config_set_time_base(cfg, (RaRational) { 210cabdff1aSopenharmony_ci avctx->framerate.den, avctx->framerate.num 211cabdff1aSopenharmony_ci }); 212cabdff1aSopenharmony_ci } else { 213cabdff1aSopenharmony_ci rav1e_config_set_time_base(cfg, (RaRational) { 214cabdff1aSopenharmony_ci avctx->time_base.num * avctx->ticks_per_frame, 215cabdff1aSopenharmony_ci avctx->time_base.den 216cabdff1aSopenharmony_ci }); 217cabdff1aSopenharmony_ci } 218cabdff1aSopenharmony_ci 219cabdff1aSopenharmony_ci if ((avctx->flags & AV_CODEC_FLAG_PASS1 || avctx->flags & AV_CODEC_FLAG_PASS2) && !avctx->bit_rate) { 220cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "A bitrate must be set to use two pass mode.\n"); 221cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; 222cabdff1aSopenharmony_ci goto end; 223cabdff1aSopenharmony_ci } 224cabdff1aSopenharmony_ci 225cabdff1aSopenharmony_ci if (avctx->flags & AV_CODEC_FLAG_PASS2) { 226cabdff1aSopenharmony_ci if (!avctx->stats_in) { 227cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "No stats file provided for second pass.\n"); 228cabdff1aSopenharmony_ci ret = AVERROR(EINVAL); 229cabdff1aSopenharmony_ci goto end; 230cabdff1aSopenharmony_ci } 231cabdff1aSopenharmony_ci 232cabdff1aSopenharmony_ci ctx->pass_size = (strlen(avctx->stats_in) * 3) / 4; 233cabdff1aSopenharmony_ci ctx->pass_data = av_malloc(ctx->pass_size); 234cabdff1aSopenharmony_ci if (!ctx->pass_data) { 235cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Could not allocate stats buffer.\n"); 236cabdff1aSopenharmony_ci ret = AVERROR(ENOMEM); 237cabdff1aSopenharmony_ci goto end; 238cabdff1aSopenharmony_ci } 239cabdff1aSopenharmony_ci 240cabdff1aSopenharmony_ci ctx->pass_size = av_base64_decode(ctx->pass_data, avctx->stats_in, ctx->pass_size); 241cabdff1aSopenharmony_ci if (ctx->pass_size < 0) { 242cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Invalid pass file.\n"); 243cabdff1aSopenharmony_ci ret = AVERROR(EINVAL); 244cabdff1aSopenharmony_ci goto end; 245cabdff1aSopenharmony_ci } 246cabdff1aSopenharmony_ci } 247cabdff1aSopenharmony_ci 248cabdff1aSopenharmony_ci if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) { 249cabdff1aSopenharmony_ci const AVBitStreamFilter *filter = av_bsf_get_by_name("extract_extradata"); 250cabdff1aSopenharmony_ci int bret; 251cabdff1aSopenharmony_ci 252cabdff1aSopenharmony_ci if (!filter) { 253cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "extract_extradata bitstream filter " 254cabdff1aSopenharmony_ci "not found. This is a bug, please report it.\n"); 255cabdff1aSopenharmony_ci ret = AVERROR_BUG; 256cabdff1aSopenharmony_ci goto end; 257cabdff1aSopenharmony_ci } 258cabdff1aSopenharmony_ci 259cabdff1aSopenharmony_ci bret = av_bsf_alloc(filter, &ctx->bsf); 260cabdff1aSopenharmony_ci if (bret < 0) { 261cabdff1aSopenharmony_ci ret = bret; 262cabdff1aSopenharmony_ci goto end; 263cabdff1aSopenharmony_ci } 264cabdff1aSopenharmony_ci 265cabdff1aSopenharmony_ci bret = avcodec_parameters_from_context(ctx->bsf->par_in, avctx); 266cabdff1aSopenharmony_ci if (bret < 0) { 267cabdff1aSopenharmony_ci ret = bret; 268cabdff1aSopenharmony_ci goto end; 269cabdff1aSopenharmony_ci } 270cabdff1aSopenharmony_ci 271cabdff1aSopenharmony_ci bret = av_bsf_init(ctx->bsf); 272cabdff1aSopenharmony_ci if (bret < 0) { 273cabdff1aSopenharmony_ci ret = bret; 274cabdff1aSopenharmony_ci goto end; 275cabdff1aSopenharmony_ci } 276cabdff1aSopenharmony_ci } 277cabdff1aSopenharmony_ci 278cabdff1aSopenharmony_ci { 279cabdff1aSopenharmony_ci AVDictionaryEntry *en = NULL; 280cabdff1aSopenharmony_ci while ((en = av_dict_get(ctx->rav1e_opts, "", en, AV_DICT_IGNORE_SUFFIX))) { 281cabdff1aSopenharmony_ci int parse_ret = rav1e_config_parse(cfg, en->key, en->value); 282cabdff1aSopenharmony_ci if (parse_ret < 0) 283cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, "Invalid value for %s: %s.\n", en->key, en->value); 284cabdff1aSopenharmony_ci } 285cabdff1aSopenharmony_ci } 286cabdff1aSopenharmony_ci 287cabdff1aSopenharmony_ci rret = rav1e_config_parse_int(cfg, "width", avctx->width); 288cabdff1aSopenharmony_ci if (rret < 0) { 289cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Invalid width passed to rav1e.\n"); 290cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; 291cabdff1aSopenharmony_ci goto end; 292cabdff1aSopenharmony_ci } 293cabdff1aSopenharmony_ci 294cabdff1aSopenharmony_ci rret = rav1e_config_parse_int(cfg, "height", avctx->height); 295cabdff1aSopenharmony_ci if (rret < 0) { 296cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Invalid height passed to rav1e.\n"); 297cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; 298cabdff1aSopenharmony_ci goto end; 299cabdff1aSopenharmony_ci } 300cabdff1aSopenharmony_ci 301cabdff1aSopenharmony_ci rret = rav1e_config_parse_int(cfg, "threads", avctx->thread_count); 302cabdff1aSopenharmony_ci if (rret < 0) 303cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, "Invalid number of threads, defaulting to auto.\n"); 304cabdff1aSopenharmony_ci 305cabdff1aSopenharmony_ci if (ctx->speed >= 0) { 306cabdff1aSopenharmony_ci rret = rav1e_config_parse_int(cfg, "speed", ctx->speed); 307cabdff1aSopenharmony_ci if (rret < 0) { 308cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Could not set speed preset.\n"); 309cabdff1aSopenharmony_ci ret = AVERROR_EXTERNAL; 310cabdff1aSopenharmony_ci goto end; 311cabdff1aSopenharmony_ci } 312cabdff1aSopenharmony_ci } 313cabdff1aSopenharmony_ci 314cabdff1aSopenharmony_ci /* rav1e handles precedence between 'tiles' and cols/rows for us. */ 315cabdff1aSopenharmony_ci if (ctx->tiles > 0) { 316cabdff1aSopenharmony_ci rret = rav1e_config_parse_int(cfg, "tiles", ctx->tiles); 317cabdff1aSopenharmony_ci if (rret < 0) { 318cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Could not set number of tiles to encode with.\n"); 319cabdff1aSopenharmony_ci ret = AVERROR_EXTERNAL; 320cabdff1aSopenharmony_ci goto end; 321cabdff1aSopenharmony_ci } 322cabdff1aSopenharmony_ci } 323cabdff1aSopenharmony_ci if (ctx->tile_rows > 0) { 324cabdff1aSopenharmony_ci rret = rav1e_config_parse_int(cfg, "tile_rows", ctx->tile_rows); 325cabdff1aSopenharmony_ci if (rret < 0) { 326cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Could not set number of tile rows to encode with.\n"); 327cabdff1aSopenharmony_ci ret = AVERROR_EXTERNAL; 328cabdff1aSopenharmony_ci goto end; 329cabdff1aSopenharmony_ci } 330cabdff1aSopenharmony_ci } 331cabdff1aSopenharmony_ci if (ctx->tile_cols > 0) { 332cabdff1aSopenharmony_ci rret = rav1e_config_parse_int(cfg, "tile_cols", ctx->tile_cols); 333cabdff1aSopenharmony_ci if (rret < 0) { 334cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Could not set number of tile cols to encode with.\n"); 335cabdff1aSopenharmony_ci ret = AVERROR_EXTERNAL; 336cabdff1aSopenharmony_ci goto end; 337cabdff1aSopenharmony_ci } 338cabdff1aSopenharmony_ci } 339cabdff1aSopenharmony_ci 340cabdff1aSopenharmony_ci if (avctx->gop_size > 0) { 341cabdff1aSopenharmony_ci rret = rav1e_config_parse_int(cfg, "key_frame_interval", avctx->gop_size); 342cabdff1aSopenharmony_ci if (rret < 0) { 343cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Could not set max keyint.\n"); 344cabdff1aSopenharmony_ci ret = AVERROR_EXTERNAL; 345cabdff1aSopenharmony_ci goto end; 346cabdff1aSopenharmony_ci } 347cabdff1aSopenharmony_ci } 348cabdff1aSopenharmony_ci 349cabdff1aSopenharmony_ci if (avctx->keyint_min > 0) { 350cabdff1aSopenharmony_ci rret = rav1e_config_parse_int(cfg, "min_key_frame_interval", avctx->keyint_min); 351cabdff1aSopenharmony_ci if (rret < 0) { 352cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Could not set min keyint.\n"); 353cabdff1aSopenharmony_ci ret = AVERROR_EXTERNAL; 354cabdff1aSopenharmony_ci goto end; 355cabdff1aSopenharmony_ci } 356cabdff1aSopenharmony_ci } 357cabdff1aSopenharmony_ci 358cabdff1aSopenharmony_ci if (avctx->bit_rate && ctx->quantizer < 0) { 359cabdff1aSopenharmony_ci int max_quantizer = avctx->qmax >= 0 ? avctx->qmax : 255; 360cabdff1aSopenharmony_ci 361cabdff1aSopenharmony_ci rret = rav1e_config_parse_int(cfg, "quantizer", max_quantizer); 362cabdff1aSopenharmony_ci if (rret < 0) { 363cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Could not set max quantizer.\n"); 364cabdff1aSopenharmony_ci ret = AVERROR_EXTERNAL; 365cabdff1aSopenharmony_ci goto end; 366cabdff1aSopenharmony_ci } 367cabdff1aSopenharmony_ci 368cabdff1aSopenharmony_ci if (avctx->qmin >= 0) { 369cabdff1aSopenharmony_ci rret = rav1e_config_parse_int(cfg, "min_quantizer", avctx->qmin); 370cabdff1aSopenharmony_ci if (rret < 0) { 371cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Could not set min quantizer.\n"); 372cabdff1aSopenharmony_ci ret = AVERROR_EXTERNAL; 373cabdff1aSopenharmony_ci goto end; 374cabdff1aSopenharmony_ci } 375cabdff1aSopenharmony_ci } 376cabdff1aSopenharmony_ci 377cabdff1aSopenharmony_ci rret = rav1e_config_parse_int(cfg, "bitrate", avctx->bit_rate); 378cabdff1aSopenharmony_ci if (rret < 0) { 379cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Could not set bitrate.\n"); 380cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; 381cabdff1aSopenharmony_ci goto end; 382cabdff1aSopenharmony_ci } 383cabdff1aSopenharmony_ci } else if (ctx->quantizer >= 0) { 384cabdff1aSopenharmony_ci if (avctx->bit_rate) 385cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, "Both bitrate and quantizer specified. Using quantizer mode."); 386cabdff1aSopenharmony_ci 387cabdff1aSopenharmony_ci rret = rav1e_config_parse_int(cfg, "quantizer", ctx->quantizer); 388cabdff1aSopenharmony_ci if (rret < 0) { 389cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Could not set quantizer.\n"); 390cabdff1aSopenharmony_ci ret = AVERROR_EXTERNAL; 391cabdff1aSopenharmony_ci goto end; 392cabdff1aSopenharmony_ci } 393cabdff1aSopenharmony_ci } 394cabdff1aSopenharmony_ci 395cabdff1aSopenharmony_ci rret = rav1e_config_set_pixel_format(cfg, desc->comp[0].depth, 396cabdff1aSopenharmony_ci pix_fmt_map(avctx->pix_fmt), 397cabdff1aSopenharmony_ci chroma_loc_map(avctx->chroma_sample_location), 398cabdff1aSopenharmony_ci range_map(avctx->pix_fmt, avctx->color_range)); 399cabdff1aSopenharmony_ci if (rret < 0) { 400cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Failed to set pixel format properties.\n"); 401cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; 402cabdff1aSopenharmony_ci goto end; 403cabdff1aSopenharmony_ci } 404cabdff1aSopenharmony_ci 405cabdff1aSopenharmony_ci /* rav1e's colorspace enums match standard values. */ 406cabdff1aSopenharmony_ci rret = rav1e_config_set_color_description(cfg, (RaMatrixCoefficients) avctx->colorspace, 407cabdff1aSopenharmony_ci (RaColorPrimaries) avctx->color_primaries, 408cabdff1aSopenharmony_ci (RaTransferCharacteristics) avctx->color_trc); 409cabdff1aSopenharmony_ci if (rret < 0) { 410cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, "Failed to set color properties.\n"); 411cabdff1aSopenharmony_ci if (avctx->err_recognition & AV_EF_EXPLODE) { 412cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; 413cabdff1aSopenharmony_ci goto end; 414cabdff1aSopenharmony_ci } 415cabdff1aSopenharmony_ci } 416cabdff1aSopenharmony_ci 417cabdff1aSopenharmony_ci ctx->ctx = rav1e_context_new(cfg); 418cabdff1aSopenharmony_ci if (!ctx->ctx) { 419cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Failed to create rav1e encode context.\n"); 420cabdff1aSopenharmony_ci ret = AVERROR_EXTERNAL; 421cabdff1aSopenharmony_ci goto end; 422cabdff1aSopenharmony_ci } 423cabdff1aSopenharmony_ci 424cabdff1aSopenharmony_ci ret = 0; 425cabdff1aSopenharmony_ci 426cabdff1aSopenharmony_ciend: 427cabdff1aSopenharmony_ci 428cabdff1aSopenharmony_ci rav1e_config_unref(cfg); 429cabdff1aSopenharmony_ci 430cabdff1aSopenharmony_ci return ret; 431cabdff1aSopenharmony_ci} 432cabdff1aSopenharmony_ci 433cabdff1aSopenharmony_cistatic int librav1e_receive_packet(AVCodecContext *avctx, AVPacket *pkt) 434cabdff1aSopenharmony_ci{ 435cabdff1aSopenharmony_ci librav1eContext *ctx = avctx->priv_data; 436cabdff1aSopenharmony_ci RaFrame *rframe = ctx->rframe; 437cabdff1aSopenharmony_ci RaPacket *rpkt = NULL; 438cabdff1aSopenharmony_ci int ret; 439cabdff1aSopenharmony_ci 440cabdff1aSopenharmony_ci if (!rframe) { 441cabdff1aSopenharmony_ci AVFrame *frame = ctx->frame; 442cabdff1aSopenharmony_ci 443cabdff1aSopenharmony_ci ret = ff_encode_get_frame(avctx, frame); 444cabdff1aSopenharmony_ci if (ret < 0 && ret != AVERROR_EOF) 445cabdff1aSopenharmony_ci return ret; 446cabdff1aSopenharmony_ci 447cabdff1aSopenharmony_ci if (frame->buf[0]) { 448cabdff1aSopenharmony_ci const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format); 449cabdff1aSopenharmony_ci 450cabdff1aSopenharmony_ci int64_t *pts = av_malloc(sizeof(int64_t)); 451cabdff1aSopenharmony_ci if (!pts) { 452cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Could not allocate PTS buffer.\n"); 453cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 454cabdff1aSopenharmony_ci } 455cabdff1aSopenharmony_ci *pts = frame->pts; 456cabdff1aSopenharmony_ci 457cabdff1aSopenharmony_ci rframe = rav1e_frame_new(ctx->ctx); 458cabdff1aSopenharmony_ci if (!rframe) { 459cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Could not allocate new rav1e frame.\n"); 460cabdff1aSopenharmony_ci av_frame_unref(frame); 461cabdff1aSopenharmony_ci av_freep(&pts); 462cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 463cabdff1aSopenharmony_ci } 464cabdff1aSopenharmony_ci 465cabdff1aSopenharmony_ci for (int i = 0; i < desc->nb_components; i++) { 466cabdff1aSopenharmony_ci int shift = i ? desc->log2_chroma_h : 0; 467cabdff1aSopenharmony_ci int bytes = desc->comp[0].depth == 8 ? 1 : 2; 468cabdff1aSopenharmony_ci rav1e_frame_fill_plane(rframe, i, frame->data[i], 469cabdff1aSopenharmony_ci (frame->height >> shift) * frame->linesize[i], 470cabdff1aSopenharmony_ci frame->linesize[i], bytes); 471cabdff1aSopenharmony_ci } 472cabdff1aSopenharmony_ci av_frame_unref(frame); 473cabdff1aSopenharmony_ci rav1e_frame_set_opaque(rframe, pts, av_free); 474cabdff1aSopenharmony_ci } 475cabdff1aSopenharmony_ci } 476cabdff1aSopenharmony_ci 477cabdff1aSopenharmony_ci ret = rav1e_send_frame(ctx->ctx, rframe); 478cabdff1aSopenharmony_ci if (rframe) 479cabdff1aSopenharmony_ci if (ret == RA_ENCODER_STATUS_ENOUGH_DATA) { 480cabdff1aSopenharmony_ci ctx->rframe = rframe; /* Queue is full. Store the RaFrame to retry next call */ 481cabdff1aSopenharmony_ci } else { 482cabdff1aSopenharmony_ci rav1e_frame_unref(rframe); /* No need to unref if flushing. */ 483cabdff1aSopenharmony_ci ctx->rframe = NULL; 484cabdff1aSopenharmony_ci } 485cabdff1aSopenharmony_ci 486cabdff1aSopenharmony_ci switch (ret) { 487cabdff1aSopenharmony_ci case RA_ENCODER_STATUS_SUCCESS: 488cabdff1aSopenharmony_ci case RA_ENCODER_STATUS_ENOUGH_DATA: 489cabdff1aSopenharmony_ci break; 490cabdff1aSopenharmony_ci case RA_ENCODER_STATUS_FAILURE: 491cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Could not send frame: %s\n", rav1e_status_to_str(ret)); 492cabdff1aSopenharmony_ci return AVERROR_EXTERNAL; 493cabdff1aSopenharmony_ci default: 494cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Unknown return code %d from rav1e_send_frame: %s\n", ret, rav1e_status_to_str(ret)); 495cabdff1aSopenharmony_ci return AVERROR_UNKNOWN; 496cabdff1aSopenharmony_ci } 497cabdff1aSopenharmony_ci 498cabdff1aSopenharmony_ciretry: 499cabdff1aSopenharmony_ci 500cabdff1aSopenharmony_ci if (avctx->flags & AV_CODEC_FLAG_PASS1) { 501cabdff1aSopenharmony_ci int sret = get_stats(avctx, 0); 502cabdff1aSopenharmony_ci if (sret < 0) 503cabdff1aSopenharmony_ci return sret; 504cabdff1aSopenharmony_ci } else if (avctx->flags & AV_CODEC_FLAG_PASS2) { 505cabdff1aSopenharmony_ci int sret = set_stats(avctx); 506cabdff1aSopenharmony_ci if (sret < 0) 507cabdff1aSopenharmony_ci return sret; 508cabdff1aSopenharmony_ci } 509cabdff1aSopenharmony_ci 510cabdff1aSopenharmony_ci ret = rav1e_receive_packet(ctx->ctx, &rpkt); 511cabdff1aSopenharmony_ci switch (ret) { 512cabdff1aSopenharmony_ci case RA_ENCODER_STATUS_SUCCESS: 513cabdff1aSopenharmony_ci break; 514cabdff1aSopenharmony_ci case RA_ENCODER_STATUS_LIMIT_REACHED: 515cabdff1aSopenharmony_ci if (avctx->flags & AV_CODEC_FLAG_PASS1) { 516cabdff1aSopenharmony_ci int sret = get_stats(avctx, 1); 517cabdff1aSopenharmony_ci if (sret < 0) 518cabdff1aSopenharmony_ci return sret; 519cabdff1aSopenharmony_ci } 520cabdff1aSopenharmony_ci return AVERROR_EOF; 521cabdff1aSopenharmony_ci case RA_ENCODER_STATUS_ENCODED: 522cabdff1aSopenharmony_ci goto retry; 523cabdff1aSopenharmony_ci case RA_ENCODER_STATUS_NEED_MORE_DATA: 524cabdff1aSopenharmony_ci if (avctx->internal->draining) { 525cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Unexpected error when receiving packet after EOF.\n"); 526cabdff1aSopenharmony_ci return AVERROR_EXTERNAL; 527cabdff1aSopenharmony_ci } 528cabdff1aSopenharmony_ci return AVERROR(EAGAIN); 529cabdff1aSopenharmony_ci case RA_ENCODER_STATUS_FAILURE: 530cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Could not encode frame: %s\n", rav1e_status_to_str(ret)); 531cabdff1aSopenharmony_ci return AVERROR_EXTERNAL; 532cabdff1aSopenharmony_ci default: 533cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Unknown return code %d from rav1e_receive_packet: %s\n", ret, rav1e_status_to_str(ret)); 534cabdff1aSopenharmony_ci return AVERROR_UNKNOWN; 535cabdff1aSopenharmony_ci } 536cabdff1aSopenharmony_ci 537cabdff1aSopenharmony_ci ret = ff_get_encode_buffer(avctx, pkt, rpkt->len, 0); 538cabdff1aSopenharmony_ci if (ret < 0) { 539cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Could not allocate packet.\n"); 540cabdff1aSopenharmony_ci rav1e_packet_unref(rpkt); 541cabdff1aSopenharmony_ci return ret; 542cabdff1aSopenharmony_ci } 543cabdff1aSopenharmony_ci 544cabdff1aSopenharmony_ci memcpy(pkt->data, rpkt->data, rpkt->len); 545cabdff1aSopenharmony_ci 546cabdff1aSopenharmony_ci if (rpkt->frame_type == RA_FRAME_TYPE_KEY) 547cabdff1aSopenharmony_ci pkt->flags |= AV_PKT_FLAG_KEY; 548cabdff1aSopenharmony_ci 549cabdff1aSopenharmony_ci pkt->pts = pkt->dts = *((int64_t *) rpkt->opaque); 550cabdff1aSopenharmony_ci av_free(rpkt->opaque); 551cabdff1aSopenharmony_ci rav1e_packet_unref(rpkt); 552cabdff1aSopenharmony_ci 553cabdff1aSopenharmony_ci if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) { 554cabdff1aSopenharmony_ci int ret = av_bsf_send_packet(ctx->bsf, pkt); 555cabdff1aSopenharmony_ci if (ret < 0) { 556cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "extradata extraction send failed.\n"); 557cabdff1aSopenharmony_ci av_packet_unref(pkt); 558cabdff1aSopenharmony_ci return ret; 559cabdff1aSopenharmony_ci } 560cabdff1aSopenharmony_ci 561cabdff1aSopenharmony_ci ret = av_bsf_receive_packet(ctx->bsf, pkt); 562cabdff1aSopenharmony_ci if (ret < 0) { 563cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "extradata extraction receive failed.\n"); 564cabdff1aSopenharmony_ci av_packet_unref(pkt); 565cabdff1aSopenharmony_ci return ret; 566cabdff1aSopenharmony_ci } 567cabdff1aSopenharmony_ci } 568cabdff1aSopenharmony_ci 569cabdff1aSopenharmony_ci return 0; 570cabdff1aSopenharmony_ci} 571cabdff1aSopenharmony_ci 572cabdff1aSopenharmony_ci#define OFFSET(x) offsetof(librav1eContext, x) 573cabdff1aSopenharmony_ci#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM 574cabdff1aSopenharmony_ci 575cabdff1aSopenharmony_cistatic const AVOption options[] = { 576cabdff1aSopenharmony_ci { "qp", "use constant quantizer mode", OFFSET(quantizer), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 255, VE }, 577cabdff1aSopenharmony_ci { "speed", "what speed preset to use", OFFSET(speed), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 10, VE }, 578cabdff1aSopenharmony_ci { "tiles", "number of tiles encode with", OFFSET(tiles), AV_OPT_TYPE_INT, { .i64 = 0 }, -1, INT64_MAX, VE }, 579cabdff1aSopenharmony_ci { "tile-rows", "number of tiles rows to encode with", OFFSET(tile_rows), AV_OPT_TYPE_INT, { .i64 = 0 }, -1, INT64_MAX, VE }, 580cabdff1aSopenharmony_ci { "tile-columns", "number of tiles columns to encode with", OFFSET(tile_cols), AV_OPT_TYPE_INT, { .i64 = 0 }, -1, INT64_MAX, VE }, 581cabdff1aSopenharmony_ci { "rav1e-params", "set the rav1e configuration using a :-separated list of key=value parameters", OFFSET(rav1e_opts), AV_OPT_TYPE_DICT, { 0 }, 0, 0, VE }, 582cabdff1aSopenharmony_ci { NULL } 583cabdff1aSopenharmony_ci}; 584cabdff1aSopenharmony_ci 585cabdff1aSopenharmony_cistatic const FFCodecDefault librav1e_defaults[] = { 586cabdff1aSopenharmony_ci { "b", "0" }, 587cabdff1aSopenharmony_ci { "g", "0" }, 588cabdff1aSopenharmony_ci { "keyint_min", "0" }, 589cabdff1aSopenharmony_ci { "qmax", "-1" }, 590cabdff1aSopenharmony_ci { "qmin", "-1" }, 591cabdff1aSopenharmony_ci { NULL } 592cabdff1aSopenharmony_ci}; 593cabdff1aSopenharmony_ci 594cabdff1aSopenharmony_ciconst enum AVPixelFormat librav1e_pix_fmts[] = { 595cabdff1aSopenharmony_ci AV_PIX_FMT_YUV420P, 596cabdff1aSopenharmony_ci AV_PIX_FMT_YUVJ420P, 597cabdff1aSopenharmony_ci AV_PIX_FMT_YUV420P10, 598cabdff1aSopenharmony_ci AV_PIX_FMT_YUV420P12, 599cabdff1aSopenharmony_ci AV_PIX_FMT_YUV422P, 600cabdff1aSopenharmony_ci AV_PIX_FMT_YUVJ422P, 601cabdff1aSopenharmony_ci AV_PIX_FMT_YUV422P10, 602cabdff1aSopenharmony_ci AV_PIX_FMT_YUV422P12, 603cabdff1aSopenharmony_ci AV_PIX_FMT_YUV444P, 604cabdff1aSopenharmony_ci AV_PIX_FMT_YUVJ444P, 605cabdff1aSopenharmony_ci AV_PIX_FMT_YUV444P10, 606cabdff1aSopenharmony_ci AV_PIX_FMT_YUV444P12, 607cabdff1aSopenharmony_ci AV_PIX_FMT_NONE 608cabdff1aSopenharmony_ci}; 609cabdff1aSopenharmony_ci 610cabdff1aSopenharmony_cistatic const AVClass class = { 611cabdff1aSopenharmony_ci .class_name = "librav1e", 612cabdff1aSopenharmony_ci .item_name = av_default_item_name, 613cabdff1aSopenharmony_ci .option = options, 614cabdff1aSopenharmony_ci .version = LIBAVUTIL_VERSION_INT, 615cabdff1aSopenharmony_ci}; 616cabdff1aSopenharmony_ci 617cabdff1aSopenharmony_ciconst FFCodec ff_librav1e_encoder = { 618cabdff1aSopenharmony_ci .p.name = "librav1e", 619cabdff1aSopenharmony_ci .p.long_name = NULL_IF_CONFIG_SMALL("librav1e AV1"), 620cabdff1aSopenharmony_ci .p.type = AVMEDIA_TYPE_VIDEO, 621cabdff1aSopenharmony_ci .p.id = AV_CODEC_ID_AV1, 622cabdff1aSopenharmony_ci .init = librav1e_encode_init, 623cabdff1aSopenharmony_ci FF_CODEC_RECEIVE_PACKET_CB(librav1e_receive_packet), 624cabdff1aSopenharmony_ci .close = librav1e_encode_close, 625cabdff1aSopenharmony_ci .priv_data_size = sizeof(librav1eContext), 626cabdff1aSopenharmony_ci .p.priv_class = &class, 627cabdff1aSopenharmony_ci .defaults = librav1e_defaults, 628cabdff1aSopenharmony_ci .p.pix_fmts = librav1e_pix_fmts, 629cabdff1aSopenharmony_ci .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS | 630cabdff1aSopenharmony_ci AV_CODEC_CAP_DR1, 631cabdff1aSopenharmony_ci .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_AUTO_THREADS, 632cabdff1aSopenharmony_ci .p.wrapper_name = "librav1e", 633cabdff1aSopenharmony_ci}; 634