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