blob: 7865ae161f057d55ab968482b72b85486ee9779a [file] [log] [blame]
Luca Barbato43778a52018-02-11 20:33:251/*
2 * Copyright (c) 2010, Google, Inc.
3 *
James Almer99cc3cf2018-03-29 02:15:184 * This file is part of FFmpeg.
Luca Barbato43778a52018-02-11 20:33:255 *
James Almer99cc3cf2018-03-29 02:15:186 * FFmpeg is free software; you can redistribute it and/or
Luca Barbato43778a52018-02-11 20:33:257 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
James Almer99cc3cf2018-03-29 02:15:1811 * FFmpeg is distributed in the hope that it will be useful,
Luca Barbato43778a52018-02-11 20:33:2512 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
James Almer99cc3cf2018-03-29 02:15:1817 * License along with FFmpeg; if not, write to the Free Software
Luca Barbato43778a52018-02-11 20:33:2518 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
James Almer99cc3cf2018-03-29 02:15:1821/**
22 * @file
23 * AV1 encoder support via libaom
24 */
25
Luca Barbato43778a52018-02-11 20:33:2526#define AOM_DISABLE_CTRL_TYPECHECKS 1
27#include <aom/aom_encoder.h>
28#include <aom/aomcx.h>
29
James Almerc42c99c2018-03-30 01:35:3330#include "libavutil/avassert.h"
Luca Barbato43778a52018-02-11 20:33:2531#include "libavutil/base64.h"
32#include "libavutil/common.h"
Andreas Rheinhardt69f120e2021-06-12 20:10:1133#include "libavutil/cpu.h"
Luca Barbato43778a52018-02-11 20:33:2534#include "libavutil/mathematics.h"
35#include "libavutil/opt.h"
36#include "libavutil/pixdesc.h"
37
Mark Thompson70709552018-10-22 22:40:0738#include "av1.h"
Luca Barbato43778a52018-02-11 20:33:2539#include "avcodec.h"
Andreas Rheinhardt57b5ec62021-06-11 21:35:3340#include "bsf.h"
Andreas Rheinhardta688f3c2022-03-16 17:18:2841#include "codec_internal.h"
Andreas Rheinhardt044daa72021-04-24 23:43:2642#include "encode.h"
Luca Barbato43778a52018-02-11 20:33:2543#include "internal.h"
James Almer6e190392020-06-02 21:38:3344#include "packet_internal.h"
James Almerc0f0c9f2018-03-29 02:28:3445#include "profiles.h"
Luca Barbato43778a52018-02-11 20:33:2546
47/*
48 * Portion of struct aom_codec_cx_pkt from aom_encoder.h.
49 * One encoded frame returned from the library.
50 */
51struct FrameListData {
James Almer99cc3cf2018-03-29 02:15:1852 void *buf; /**< compressed data buffer */
53 size_t sz; /**< length of compressed data */
54 int64_t pts; /**< time stamp to show frame
55 (in timebase units) */
56 unsigned long duration; /**< duration to show frame
57 (in timebase units) */
58 uint32_t flags; /**< flags for this frame */
Sam Johne2658322018-09-28 22:09:0559 uint64_t sse[4];
60 int have_sse; /**< true if we have pending sse[] */
61 uint64_t frame_number;
Luca Barbato43778a52018-02-11 20:33:2562 struct FrameListData *next;
63};
64
65typedef struct AOMEncoderContext {
66 AVClass *class;
James Almera754af92018-07-07 19:33:1667 AVBSFContext *bsf;
Luca Barbato43778a52018-02-11 20:33:2568 struct aom_codec_ctx encoder;
69 struct aom_image rawimg;
70 struct aom_fixed_buf twopass_stats;
71 struct FrameListData *coded_frame_list;
72 int cpu_used;
73 int auto_alt_ref;
Sam John via ffmpeg-devel995889a2019-03-29 16:58:3874 int arnr_max_frames;
75 int arnr_strength;
76 int aq_mode;
Luca Barbato43778a52018-02-11 20:33:2577 int lag_in_frames;
78 int error_resilient;
79 int crf;
80 int static_thresh;
81 int drop_threshold;
Sam John via ffmpeg-devel995889a2019-03-29 16:58:3882 int denoise_noise_level;
83 int denoise_block_size;
Sam Johne2658322018-09-28 22:09:0584 uint64_t sse[4];
85 int have_sse; /**< true if we have pending sse[] */
86 uint64_t frame_number;
Sam John via ffmpeg-devel995889a2019-03-29 16:58:3887 int rc_undershoot_pct;
88 int rc_overshoot_pct;
89 int minsection_pct;
90 int maxsection_pct;
91 int frame_parallel;
Mark Thompson70709552018-10-22 22:40:0792 int tile_cols, tile_rows;
93 int tile_cols_log2, tile_rows_log2;
94 aom_superblock_size_t superblock_size;
95 int uniform_tiles;
James Almerd12d4d42018-12-08 23:14:1296 int row_mt;
Sam John via ffmpeg-devel995889a2019-03-29 16:58:3897 int enable_cdef;
98 int enable_global_motion;
99 int enable_intrabc;
Wang Cao8c9d82a2019-12-23 20:16:24100 int enable_restoration;
James Almerc4615002020-01-23 00:02:17101 int usage;
Wang Caobd3389e2020-04-03 21:00:26102 int tune;
Vignesh Venkatasubramanianab05e9a2022-05-02 21:37:01103 int still_picture;
Wang Caoaa5c6f32020-06-26 00:55:13104 int enable_rect_partitions;
105 int enable_1to4_partitions;
106 int enable_ab_partitions;
Wang Cao297d5a12020-06-26 00:55:14107 int enable_angle_delta;
108 int enable_cfl_intra;
109 int enable_paeth_intra;
110 int enable_smooth_intra;
111 int enable_intra_edge_filter;
112 int enable_palette;
113 int enable_filter_intra;
Wang Cao498ad7b2020-07-22 23:12:01114 int enable_flip_idtx;
115 int enable_tx64;
116 int reduced_tx_type_set;
117 int use_intra_dct_only;
118 int use_inter_dct_only;
119 int use_intra_default_tx_only;
Wang Cao017bf962020-07-22 23:11:12120 int enable_ref_frame_mvs;
121 int enable_interinter_wedge;
122 int enable_interintra_wedge;
123 int enable_interintra_comp;
124 int enable_masked_comp;
125 int enable_obmc;
126 int enable_onesided_comp;
127 int enable_reduced_reference_set;
128 int enable_smooth_interintra;
129 int enable_diff_wtd_comp;
130 int enable_dist_wtd_comp;
131 int enable_dual_filter;
Bohan Li82aab8a2021-02-09 04:04:41132 AVDictionary *aom_params;
Luca Barbato43778a52018-02-11 20:33:25133} AOMContext;
134
135static const char *const ctlidstr[] = {
136 [AOME_SET_CPUUSED] = "AOME_SET_CPUUSED",
137 [AOME_SET_CQ_LEVEL] = "AOME_SET_CQ_LEVEL",
138 [AOME_SET_ENABLEAUTOALTREF] = "AOME_SET_ENABLEAUTOALTREF",
Sam John via ffmpeg-devel995889a2019-03-29 16:58:38139 [AOME_SET_ARNR_MAXFRAMES] = "AOME_SET_ARNR_MAXFRAMES",
140 [AOME_SET_ARNR_STRENGTH] = "AOME_SET_ARNR_STRENGTH",
Luca Barbato43778a52018-02-11 20:33:25141 [AOME_SET_STATIC_THRESHOLD] = "AOME_SET_STATIC_THRESHOLD",
James Almer99cc3cf2018-03-29 02:15:18142 [AV1E_SET_COLOR_RANGE] = "AV1E_SET_COLOR_RANGE",
James Almere5819fa2018-03-29 04:03:24143 [AV1E_SET_COLOR_PRIMARIES] = "AV1E_SET_COLOR_PRIMARIES",
144 [AV1E_SET_MATRIX_COEFFICIENTS] = "AV1E_SET_MATRIX_COEFFICIENTS",
145 [AV1E_SET_TRANSFER_CHARACTERISTICS] = "AV1E_SET_TRANSFER_CHARACTERISTICS",
Sam John via ffmpeg-devel995889a2019-03-29 16:58:38146 [AV1E_SET_AQ_MODE] = "AV1E_SET_AQ_MODE",
147 [AV1E_SET_FRAME_PARALLEL_DECODING] = "AV1E_SET_FRAME_PARALLEL_DECODING",
Mark Thompson70709552018-10-22 22:40:07148 [AV1E_SET_SUPERBLOCK_SIZE] = "AV1E_SET_SUPERBLOCK_SIZE",
149 [AV1E_SET_TILE_COLUMNS] = "AV1E_SET_TILE_COLUMNS",
150 [AV1E_SET_TILE_ROWS] = "AV1E_SET_TILE_ROWS",
Wang Cao8c9d82a2019-12-23 20:16:24151 [AV1E_SET_ENABLE_RESTORATION] = "AV1E_SET_ENABLE_RESTORATION",
James Almerd12d4d42018-12-08 23:14:12152#ifdef AOM_CTRL_AV1E_SET_ROW_MT
153 [AV1E_SET_ROW_MT] = "AV1E_SET_ROW_MT",
154#endif
Sam John via ffmpeg-devel995889a2019-03-29 16:58:38155#ifdef AOM_CTRL_AV1E_SET_DENOISE_NOISE_LEVEL
156 [AV1E_SET_DENOISE_NOISE_LEVEL] = "AV1E_SET_DENOISE_NOISE_LEVEL",
157#endif
158#ifdef AOM_CTRL_AV1E_SET_DENOISE_BLOCK_SIZE
159 [AV1E_SET_DENOISE_BLOCK_SIZE] = "AV1E_SET_DENOISE_BLOCK_SIZE",
160#endif
161#ifdef AOM_CTRL_AV1E_SET_MAX_REFERENCE_FRAMES
162 [AV1E_SET_MAX_REFERENCE_FRAMES] = "AV1E_SET_MAX_REFERENCE_FRAMES",
163#endif
164#ifdef AOM_CTRL_AV1E_SET_ENABLE_GLOBAL_MOTION
165 [AV1E_SET_ENABLE_GLOBAL_MOTION] = "AV1E_SET_ENABLE_GLOBAL_MOTION",
166#endif
167#ifdef AOM_CTRL_AV1E_SET_ENABLE_INTRABC
168 [AV1E_SET_ENABLE_INTRABC] = "AV1E_SET_ENABLE_INTRABC",
169#endif
170 [AV1E_SET_ENABLE_CDEF] = "AV1E_SET_ENABLE_CDEF",
Wang Caobd3389e2020-04-03 21:00:26171 [AOME_SET_TUNING] = "AOME_SET_TUNING",
James Zernd2947162020-07-02 02:53:54172#if AOM_ENCODER_ABI_VERSION >= 22
Wang Caoaa5c6f32020-06-26 00:55:13173 [AV1E_SET_ENABLE_1TO4_PARTITIONS] = "AV1E_SET_ENABLE_1TO4_PARTITIONS",
174 [AV1E_SET_ENABLE_AB_PARTITIONS] = "AV1E_SET_ENABLE_AB_PARTITIONS",
175 [AV1E_SET_ENABLE_RECT_PARTITIONS] = "AV1E_SET_ENABLE_RECT_PARTITIONS",
Wang Cao297d5a12020-06-26 00:55:14176 [AV1E_SET_ENABLE_ANGLE_DELTA] = "AV1E_SET_ENABLE_ANGLE_DELTA",
177 [AV1E_SET_ENABLE_CFL_INTRA] = "AV1E_SET_ENABLE_CFL_INTRA",
178 [AV1E_SET_ENABLE_FILTER_INTRA] = "AV1E_SET_ENABLE_FILTER_INTRA",
179 [AV1E_SET_ENABLE_INTRA_EDGE_FILTER] = "AV1E_SET_ENABLE_INTRA_EDGE_FILTER",
180 [AV1E_SET_ENABLE_PAETH_INTRA] = "AV1E_SET_ENABLE_PAETH_INTRA",
181 [AV1E_SET_ENABLE_SMOOTH_INTRA] = "AV1E_SET_ENABLE_SMOOTH_INTRA",
182 [AV1E_SET_ENABLE_PALETTE] = "AV1E_SET_ENABLE_PALETTE",
Wang Cao498ad7b2020-07-22 23:12:01183 [AV1E_SET_ENABLE_FLIP_IDTX] = "AV1E_SET_ENABLE_FLIP_IDTX",
184 [AV1E_SET_ENABLE_TX64] = "AV1E_SET_ENABLE_TX64",
185 [AV1E_SET_INTRA_DCT_ONLY] = "AV1E_SET_INTRA_DCT_ONLY",
186 [AV1E_SET_INTER_DCT_ONLY] = "AV1E_SET_INTER_DCT_ONLY",
187 [AV1E_SET_INTRA_DEFAULT_TX_ONLY] = "AV1E_SET_INTRA_DEFAULT_TX_ONLY",
188 [AV1E_SET_REDUCED_TX_TYPE_SET] = "AV1E_SET_REDUCED_TX_TYPE_SET",
Wang Cao017bf962020-07-22 23:11:12189 [AV1E_SET_ENABLE_DIFF_WTD_COMP] = "AV1E_SET_ENABLE_DIFF_WTD_COMP",
190 [AV1E_SET_ENABLE_DIST_WTD_COMP] = "AV1E_SET_ENABLE_DIST_WTD_COMP",
191 [AV1E_SET_ENABLE_DUAL_FILTER] = "AV1E_SET_ENABLE_DUAL_FILTER",
192 [AV1E_SET_ENABLE_INTERINTER_WEDGE] = "AV1E_SET_ENABLE_INTERINTER_WEDGE",
193 [AV1E_SET_ENABLE_INTERINTRA_WEDGE] = "AV1E_SET_ENABLE_INTERINTRA_WEDGE",
194 [AV1E_SET_ENABLE_MASKED_COMP] = "AV1E_SET_ENABLE_MASKED_COMP",
195 [AV1E_SET_ENABLE_INTERINTRA_COMP] = "AV1E_SET_ENABLE_INTERINTRA_COMP",
196 [AV1E_SET_ENABLE_OBMC] = "AV1E_SET_ENABLE_OBMC",
197 [AV1E_SET_ENABLE_ONESIDED_COMP] = "AV1E_SET_ENABLE_ONESIDED_COMP",
198 [AV1E_SET_REDUCED_REFERENCE_SET] = "AV1E_SET_REDUCED_REFERENCE_SET",
199 [AV1E_SET_ENABLE_SMOOTH_INTERINTRA] = "AV1E_SET_ENABLE_SMOOTH_INTERINTRA",
200 [AV1E_SET_ENABLE_REF_FRAME_MVS] = "AV1E_SET_ENABLE_REF_FRAME_MVS",
James Zernd2947162020-07-02 02:53:54201#endif
Bohan Li950123d2022-04-19 18:18:51202#ifdef AOM_CTRL_AV1E_GET_SEQ_LEVEL_IDX
203 [AV1E_GET_SEQ_LEVEL_IDX] = "AV1E_GET_SEQ_LEVEL_IDX",
204#endif
205#ifdef AOM_CTRL_AV1E_GET_TARGET_SEQ_LEVEL_IDX
206 [AV1E_GET_TARGET_SEQ_LEVEL_IDX] = "AV1E_GET_TARGET_SEQ_LEVEL_IDX",
207#endif
Luca Barbato43778a52018-02-11 20:33:25208};
209
210static av_cold void log_encoder_error(AVCodecContext *avctx, const char *desc)
211{
212 AOMContext *ctx = avctx->priv_data;
213 const char *error = aom_codec_error(&ctx->encoder);
214 const char *detail = aom_codec_error_detail(&ctx->encoder);
215
216 av_log(avctx, AV_LOG_ERROR, "%s: %s\n", desc, error);
217 if (detail)
218 av_log(avctx, AV_LOG_ERROR, " Additional information: %s\n", detail);
219}
220
221static av_cold void dump_enc_cfg(AVCodecContext *avctx,
Matthieu Patou268f1342021-06-14 18:18:24222 const struct aom_codec_enc_cfg *cfg,
223 int level)
Luca Barbato43778a52018-02-11 20:33:25224{
225 int width = -30;
Luca Barbato43778a52018-02-11 20:33:25226
227 av_log(avctx, level, "aom_codec_enc_cfg\n");
228 av_log(avctx, level, "generic settings\n"
229 " %*s%u\n %*s%u\n %*s%u\n %*s%u\n %*s%u\n"
James Almer99cc3cf2018-03-29 02:15:18230 " %*s%u\n %*s%u\n"
Luca Barbato43778a52018-02-11 20:33:25231 " %*s{%u/%u}\n %*s%u\n %*s%d\n %*s%u\n",
James Almer99cc3cf2018-03-29 02:15:18232 width, "g_usage:", cfg->g_usage,
233 width, "g_threads:", cfg->g_threads,
234 width, "g_profile:", cfg->g_profile,
235 width, "g_w:", cfg->g_w,
236 width, "g_h:", cfg->g_h,
237 width, "g_bit_depth:", cfg->g_bit_depth,
238 width, "g_input_bit_depth:", cfg->g_input_bit_depth,
239 width, "g_timebase:", cfg->g_timebase.num, cfg->g_timebase.den,
Luca Barbato43778a52018-02-11 20:33:25240 width, "g_error_resilient:", cfg->g_error_resilient,
James Almer99cc3cf2018-03-29 02:15:18241 width, "g_pass:", cfg->g_pass,
242 width, "g_lag_in_frames:", cfg->g_lag_in_frames);
Luca Barbato43778a52018-02-11 20:33:25243 av_log(avctx, level, "rate control settings\n"
James Almer416d3542018-03-29 03:51:48244 " %*s%u\n %*s%d\n %*s%p(%"SIZE_SPECIFIER")\n %*s%u\n",
Luca Barbato43778a52018-02-11 20:33:25245 width, "rc_dropframe_thresh:", cfg->rc_dropframe_thresh,
James Almer99cc3cf2018-03-29 02:15:18246 width, "rc_end_usage:", cfg->rc_end_usage,
Luca Barbato43778a52018-02-11 20:33:25247 width, "rc_twopass_stats_in:", cfg->rc_twopass_stats_in.buf, cfg->rc_twopass_stats_in.sz,
James Almer99cc3cf2018-03-29 02:15:18248 width, "rc_target_bitrate:", cfg->rc_target_bitrate);
Luca Barbato43778a52018-02-11 20:33:25249 av_log(avctx, level, "quantizer settings\n"
250 " %*s%u\n %*s%u\n",
251 width, "rc_min_quantizer:", cfg->rc_min_quantizer,
252 width, "rc_max_quantizer:", cfg->rc_max_quantizer);
253 av_log(avctx, level, "bitrate tolerance\n"
254 " %*s%u\n %*s%u\n",
255 width, "rc_undershoot_pct:", cfg->rc_undershoot_pct,
James Almer99cc3cf2018-03-29 02:15:18256 width, "rc_overshoot_pct:", cfg->rc_overshoot_pct);
Luca Barbato43778a52018-02-11 20:33:25257 av_log(avctx, level, "decoder buffer model\n"
258 " %*s%u\n %*s%u\n %*s%u\n",
James Almer99cc3cf2018-03-29 02:15:18259 width, "rc_buf_sz:", cfg->rc_buf_sz,
Luca Barbato43778a52018-02-11 20:33:25260 width, "rc_buf_initial_sz:", cfg->rc_buf_initial_sz,
261 width, "rc_buf_optimal_sz:", cfg->rc_buf_optimal_sz);
262 av_log(avctx, level, "2 pass rate control settings\n"
263 " %*s%u\n %*s%u\n %*s%u\n",
James Almer99cc3cf2018-03-29 02:15:18264 width, "rc_2pass_vbr_bias_pct:", cfg->rc_2pass_vbr_bias_pct,
Luca Barbato43778a52018-02-11 20:33:25265 width, "rc_2pass_vbr_minsection_pct:", cfg->rc_2pass_vbr_minsection_pct,
266 width, "rc_2pass_vbr_maxsection_pct:", cfg->rc_2pass_vbr_maxsection_pct);
267 av_log(avctx, level, "keyframing settings\n"
268 " %*s%d\n %*s%u\n %*s%u\n",
James Almer99cc3cf2018-03-29 02:15:18269 width, "kf_mode:", cfg->kf_mode,
Luca Barbato43778a52018-02-11 20:33:25270 width, "kf_min_dist:", cfg->kf_min_dist,
271 width, "kf_max_dist:", cfg->kf_max_dist);
Mark Thompson70709552018-10-22 22:40:07272 av_log(avctx, level, "tile settings\n"
273 " %*s%d\n %*s%d\n",
274 width, "tile_width_count:", cfg->tile_width_count,
275 width, "tile_height_count:", cfg->tile_height_count);
Luca Barbato43778a52018-02-11 20:33:25276 av_log(avctx, level, "\n");
277}
278
279static void coded_frame_add(void *list, struct FrameListData *cx_frame)
280{
281 struct FrameListData **p = list;
282
283 while (*p)
284 p = &(*p)->next;
285 *p = cx_frame;
286 cx_frame->next = NULL;
287}
288
289static av_cold void free_coded_frame(struct FrameListData *cx_frame)
290{
291 av_freep(&cx_frame->buf);
292 av_freep(&cx_frame);
293}
294
295static av_cold void free_frame_list(struct FrameListData *list)
296{
297 struct FrameListData *p = list;
298
299 while (p) {
300 list = list->next;
301 free_coded_frame(p);
302 p = list;
303 }
304}
305
306static av_cold int codecctl_int(AVCodecContext *avctx,
Helmut K. C. Tessarekaaf91712018-12-19 17:13:26307#ifdef UENUM1BYTE
308 aome_enc_control_id id,
309#else
310 enum aome_enc_control_id id,
311#endif
312 int val)
Luca Barbato43778a52018-02-11 20:33:25313{
314 AOMContext *ctx = avctx->priv_data;
315 char buf[80];
316 int width = -30;
317 int res;
318
319 snprintf(buf, sizeof(buf), "%s:", ctlidstr[id]);
320 av_log(avctx, AV_LOG_DEBUG, " %*s%d\n", width, buf, val);
321
322 res = aom_codec_control(&ctx->encoder, id, val);
323 if (res != AOM_CODEC_OK) {
324 snprintf(buf, sizeof(buf), "Failed to set %s codec control",
325 ctlidstr[id]);
326 log_encoder_error(avctx, buf);
327 return AVERROR(EINVAL);
328 }
329
330 return 0;
331}
332
Bohan Li950123d2022-04-19 18:18:51333#if defined(AOM_CTRL_AV1E_GET_SEQ_LEVEL_IDX) && \
334 defined(AOM_CTRL_AV1E_GET_TARGET_SEQ_LEVEL_IDX)
335static av_cold int codecctl_intp(AVCodecContext *avctx,
336#ifdef UENUM1BYTE
337 aome_enc_control_id id,
338#else
339 enum aome_enc_control_id id,
340#endif
341 int* ptr)
342{
343 AOMContext *ctx = avctx->priv_data;
344 char buf[80];
345 int width = -30;
346 int res;
347
348 snprintf(buf, sizeof(buf), "%s:", ctlidstr[id]);
349 av_log(avctx, AV_LOG_DEBUG, " %*s%d\n", width, buf, *ptr);
350
351 res = aom_codec_control(&ctx->encoder, id, ptr);
352 if (res != AOM_CODEC_OK) {
353 snprintf(buf, sizeof(buf), "Failed to set %s codec control",
354 ctlidstr[id]);
355 log_encoder_error(avctx, buf);
356 return AVERROR(EINVAL);
357 }
358
359 return 0;
360}
361#endif
362
Luca Barbato43778a52018-02-11 20:33:25363static av_cold int aom_free(AVCodecContext *avctx)
364{
365 AOMContext *ctx = avctx->priv_data;
366
Bohan Li950123d2022-04-19 18:18:51367#if defined(AOM_CTRL_AV1E_GET_SEQ_LEVEL_IDX) && \
368 defined(AOM_CTRL_AV1E_GET_TARGET_SEQ_LEVEL_IDX)
369 if (!(avctx->flags & AV_CODEC_FLAG_PASS1)) {
370 int levels[32] = { 0 };
371 int target_levels[32] = { 0 };
372
373 if (!codecctl_intp(avctx, AV1E_GET_SEQ_LEVEL_IDX, levels) &&
374 !codecctl_intp(avctx, AV1E_GET_TARGET_SEQ_LEVEL_IDX,
375 target_levels)) {
376 for (int i = 0; i < 32; i++) {
377 if (levels[i] > target_levels[i]) {
378 // Warn when the target level was not met
379 av_log(avctx, AV_LOG_WARNING,
380 "Could not encode to target level %d.%d for "
381 "operating point %d. The output level is %d.%d.\n",
382 2 + (target_levels[i] >> 2), target_levels[i] & 3,
383 i, 2 + (levels[i] >> 2), levels[i] & 3);
384 } else if (target_levels[i] < 31) {
385 // Log the encoded level if a target level was given
386 av_log(avctx, AV_LOG_INFO,
387 "Output level for operating point %d is %d.%d.\n",
388 i, 2 + (levels[i] >> 2), levels[i] & 3);
389 }
390 }
391 }
392 }
393#endif
394
Luca Barbato43778a52018-02-11 20:33:25395 aom_codec_destroy(&ctx->encoder);
396 av_freep(&ctx->twopass_stats.buf);
397 av_freep(&avctx->stats_out);
398 free_frame_list(ctx->coded_frame_list);
James Almera754af92018-07-07 19:33:16399 av_bsf_free(&ctx->bsf);
Luca Barbato43778a52018-02-11 20:33:25400 return 0;
401}
402
James Almer99cc3cf2018-03-29 02:15:18403static int set_pix_fmt(AVCodecContext *avctx, aom_codec_caps_t codec_caps,
404 struct aom_codec_enc_cfg *enccfg, aom_codec_flags_t *flags,
405 aom_img_fmt_t *img_fmt)
406{
407 AOMContext av_unused *ctx = avctx->priv_data;
James Almer36e51c12020-07-17 20:46:32408 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt);
409 enccfg->g_bit_depth = enccfg->g_input_bit_depth = desc->comp[0].depth;
James Almer99cc3cf2018-03-29 02:15:18410 switch (avctx->pix_fmt) {
Philip Langdale40135822020-12-08 00:33:29411 case AV_PIX_FMT_GRAY8:
412 enccfg->monochrome = 1;
413 /* Fall-through */
James Almer99cc3cf2018-03-29 02:15:18414 case AV_PIX_FMT_YUV420P:
415 enccfg->g_profile = FF_PROFILE_AV1_MAIN;
416 *img_fmt = AOM_IMG_FMT_I420;
417 return 0;
418 case AV_PIX_FMT_YUV422P:
419 enccfg->g_profile = FF_PROFILE_AV1_PROFESSIONAL;
420 *img_fmt = AOM_IMG_FMT_I422;
421 return 0;
James Almer99cc3cf2018-03-29 02:15:18422 case AV_PIX_FMT_YUV444P:
Lynne6a2f3f62020-07-16 10:39:05423 case AV_PIX_FMT_GBRP:
James Almer99cc3cf2018-03-29 02:15:18424 enccfg->g_profile = FF_PROFILE_AV1_HIGH;
425 *img_fmt = AOM_IMG_FMT_I444;
426 return 0;
Philip Langdale40135822020-12-08 00:33:29427 case AV_PIX_FMT_GRAY10:
428 case AV_PIX_FMT_GRAY12:
429 enccfg->monochrome = 1;
430 /* Fall-through */
James Almer99cc3cf2018-03-29 02:15:18431 case AV_PIX_FMT_YUV420P10:
432 case AV_PIX_FMT_YUV420P12:
433 if (codec_caps & AOM_CODEC_CAP_HIGHBITDEPTH) {
James Almer99cc3cf2018-03-29 02:15:18434 enccfg->g_profile =
435 enccfg->g_bit_depth == 10 ? FF_PROFILE_AV1_MAIN : FF_PROFILE_AV1_PROFESSIONAL;
436 *img_fmt = AOM_IMG_FMT_I42016;
437 *flags |= AOM_CODEC_USE_HIGHBITDEPTH;
438 return 0;
439 }
440 break;
441 case AV_PIX_FMT_YUV422P10:
442 case AV_PIX_FMT_YUV422P12:
443 if (codec_caps & AOM_CODEC_CAP_HIGHBITDEPTH) {
James Almer99cc3cf2018-03-29 02:15:18444 enccfg->g_profile = FF_PROFILE_AV1_PROFESSIONAL;
445 *img_fmt = AOM_IMG_FMT_I42216;
446 *flags |= AOM_CODEC_USE_HIGHBITDEPTH;
447 return 0;
448 }
449 break;
James Almer99cc3cf2018-03-29 02:15:18450 case AV_PIX_FMT_YUV444P10:
451 case AV_PIX_FMT_YUV444P12:
Lynne6a2f3f62020-07-16 10:39:05452 case AV_PIX_FMT_GBRP10:
453 case AV_PIX_FMT_GBRP12:
James Almer99cc3cf2018-03-29 02:15:18454 if (codec_caps & AOM_CODEC_CAP_HIGHBITDEPTH) {
James Almer99cc3cf2018-03-29 02:15:18455 enccfg->g_profile =
456 enccfg->g_bit_depth == 10 ? FF_PROFILE_AV1_HIGH : FF_PROFILE_AV1_PROFESSIONAL;
457 *img_fmt = AOM_IMG_FMT_I44416;
458 *flags |= AOM_CODEC_USE_HIGHBITDEPTH;
459 return 0;
460 }
461 break;
462 default:
463 break;
464 }
465 av_log(avctx, AV_LOG_ERROR, "Unsupported pixel format.\n");
466 return AVERROR_INVALIDDATA;
467}
468
469static void set_color_range(AVCodecContext *avctx)
470{
Helmut K. C. Tessarekaaf91712018-12-19 17:13:26471 aom_color_range_t aom_cr;
James Almer99cc3cf2018-03-29 02:15:18472 switch (avctx->color_range) {
473 case AVCOL_RANGE_UNSPECIFIED:
474 case AVCOL_RANGE_MPEG: aom_cr = AOM_CR_STUDIO_RANGE; break;
475 case AVCOL_RANGE_JPEG: aom_cr = AOM_CR_FULL_RANGE; break;
476 default:
477 av_log(avctx, AV_LOG_WARNING, "Unsupported color range (%d)\n",
478 avctx->color_range);
479 return;
480 }
481
482 codecctl_int(avctx, AV1E_SET_COLOR_RANGE, aom_cr);
483}
484
Mark Thompson70709552018-10-22 22:40:07485static int count_uniform_tiling(int dim, int sb_size, int tiles_log2)
486{
487 int sb_dim = (dim + sb_size - 1) / sb_size;
488 int tile_dim = (sb_dim + (1 << tiles_log2) - 1) >> tiles_log2;
489 av_assert0(tile_dim > 0);
490 return (sb_dim + tile_dim - 1) / tile_dim;
491}
492
493static int choose_tiling(AVCodecContext *avctx,
494 struct aom_codec_enc_cfg *enccfg)
495{
496 AOMContext *ctx = avctx->priv_data;
497 int sb_128x128_possible, sb_size, sb_width, sb_height;
498 int uniform_rows, uniform_cols;
499 int uniform_64x64_possible, uniform_128x128_possible;
500 int tile_size, rounding, i;
501
502 if (ctx->tile_cols_log2 >= 0)
503 ctx->tile_cols = 1 << ctx->tile_cols_log2;
504 if (ctx->tile_rows_log2 >= 0)
505 ctx->tile_rows = 1 << ctx->tile_rows_log2;
506
507 if (ctx->tile_cols == 0) {
508 ctx->tile_cols = (avctx->width + AV1_MAX_TILE_WIDTH - 1) /
509 AV1_MAX_TILE_WIDTH;
510 if (ctx->tile_cols > 1) {
511 av_log(avctx, AV_LOG_DEBUG, "Automatically using %d tile "
512 "columns to fill width.\n", ctx->tile_cols);
513 }
514 }
515 av_assert0(ctx->tile_cols > 0);
516 if (ctx->tile_rows == 0) {
517 int max_tile_width =
518 FFALIGN((FFALIGN(avctx->width, 128) +
519 ctx->tile_cols - 1) / ctx->tile_cols, 128);
520 ctx->tile_rows =
521 (max_tile_width * FFALIGN(avctx->height, 128) +
522 AV1_MAX_TILE_AREA - 1) / AV1_MAX_TILE_AREA;
523 if (ctx->tile_rows > 1) {
524 av_log(avctx, AV_LOG_DEBUG, "Automatically using %d tile "
525 "rows to fill area.\n", ctx->tile_rows);
526 }
527 }
528 av_assert0(ctx->tile_rows > 0);
529
530 if ((avctx->width + 63) / 64 < ctx->tile_cols ||
531 (avctx->height + 63) / 64 < ctx->tile_rows) {
532 av_log(avctx, AV_LOG_ERROR, "Invalid tile sizing: frame not "
533 "large enough to fit specified tile arrangement.\n");
534 return AVERROR(EINVAL);
535 }
536 if (ctx->tile_cols > AV1_MAX_TILE_COLS ||
537 ctx->tile_rows > AV1_MAX_TILE_ROWS) {
538 av_log(avctx, AV_LOG_ERROR, "Invalid tile sizing: AV1 does "
539 "not allow more than %dx%d tiles.\n",
540 AV1_MAX_TILE_COLS, AV1_MAX_TILE_ROWS);
541 return AVERROR(EINVAL);
542 }
543 if (avctx->width / ctx->tile_cols > AV1_MAX_TILE_WIDTH) {
544 av_log(avctx, AV_LOG_ERROR, "Invalid tile sizing: AV1 does "
545 "not allow tiles of width greater than %d.\n",
546 AV1_MAX_TILE_WIDTH);
547 return AVERROR(EINVAL);
548 }
549
550 ctx->superblock_size = AOM_SUPERBLOCK_SIZE_DYNAMIC;
551
552 if (ctx->tile_cols == 1 && ctx->tile_rows == 1) {
553 av_log(avctx, AV_LOG_DEBUG, "Using a single tile.\n");
554 return 0;
555 }
556
557 sb_128x128_possible =
558 (avctx->width + 127) / 128 >= ctx->tile_cols &&
559 (avctx->height + 127) / 128 >= ctx->tile_rows;
560
561 ctx->tile_cols_log2 = ctx->tile_cols == 1 ? 0 :
562 av_log2(ctx->tile_cols - 1) + 1;
563 ctx->tile_rows_log2 = ctx->tile_rows == 1 ? 0 :
564 av_log2(ctx->tile_rows - 1) + 1;
565
566 uniform_cols = count_uniform_tiling(avctx->width,
567 64, ctx->tile_cols_log2);
568 uniform_rows = count_uniform_tiling(avctx->height,
569 64, ctx->tile_rows_log2);
570 av_log(avctx, AV_LOG_DEBUG, "Uniform with 64x64 superblocks "
571 "-> %dx%d tiles.\n", uniform_cols, uniform_rows);
572 uniform_64x64_possible = uniform_cols == ctx->tile_cols &&
573 uniform_rows == ctx->tile_rows;
574
575 if (sb_128x128_possible) {
576 uniform_cols = count_uniform_tiling(avctx->width,
577 128, ctx->tile_cols_log2);
578 uniform_rows = count_uniform_tiling(avctx->height,
579 128, ctx->tile_rows_log2);
580 av_log(avctx, AV_LOG_DEBUG, "Uniform with 128x128 superblocks "
581 "-> %dx%d tiles.\n", uniform_cols, uniform_rows);
582 uniform_128x128_possible = uniform_cols == ctx->tile_cols &&
583 uniform_rows == ctx->tile_rows;
584 } else {
585 av_log(avctx, AV_LOG_DEBUG, "128x128 superblocks not possible.\n");
586 uniform_128x128_possible = 0;
587 }
588
589 ctx->uniform_tiles = 1;
590 if (uniform_64x64_possible && uniform_128x128_possible) {
591 av_log(avctx, AV_LOG_DEBUG, "Using uniform tiling with dynamic "
592 "superblocks (tile_cols_log2 = %d, tile_rows_log2 = %d).\n",
593 ctx->tile_cols_log2, ctx->tile_rows_log2);
594 return 0;
595 }
596 if (uniform_64x64_possible && !sb_128x128_possible) {
597 av_log(avctx, AV_LOG_DEBUG, "Using uniform tiling with 64x64 "
598 "superblocks (tile_cols_log2 = %d, tile_rows_log2 = %d).\n",
599 ctx->tile_cols_log2, ctx->tile_rows_log2);
600 ctx->superblock_size = AOM_SUPERBLOCK_SIZE_64X64;
601 return 0;
602 }
603 if (uniform_128x128_possible) {
604 av_log(avctx, AV_LOG_DEBUG, "Using uniform tiling with 128x128 "
605 "superblocks (tile_cols_log2 = %d, tile_rows_log2 = %d).\n",
606 ctx->tile_cols_log2, ctx->tile_rows_log2);
607 ctx->superblock_size = AOM_SUPERBLOCK_SIZE_128X128;
608 return 0;
609 }
610 ctx->uniform_tiles = 0;
611
612 if (sb_128x128_possible) {
613 sb_size = 128;
614 ctx->superblock_size = AOM_SUPERBLOCK_SIZE_128X128;
615 } else {
616 sb_size = 64;
617 ctx->superblock_size = AOM_SUPERBLOCK_SIZE_64X64;
618 }
619 av_log(avctx, AV_LOG_DEBUG, "Using fixed tiling with %dx%d "
620 "superblocks (tile_cols = %d, tile_rows = %d).\n",
621 sb_size, sb_size, ctx->tile_cols, ctx->tile_rows);
622
623 enccfg->tile_width_count = ctx->tile_cols;
624 enccfg->tile_height_count = ctx->tile_rows;
625
626 sb_width = (avctx->width + sb_size - 1) / sb_size;
627 sb_height = (avctx->height + sb_size - 1) / sb_size;
628
629 tile_size = sb_width / ctx->tile_cols;
630 rounding = sb_width % ctx->tile_cols;
631 for (i = 0; i < ctx->tile_cols; i++) {
632 enccfg->tile_widths[i] = tile_size +
633 (i < rounding / 2 ||
634 i > ctx->tile_cols - 1 - (rounding + 1) / 2);
635 }
636
637 tile_size = sb_height / ctx->tile_rows;
638 rounding = sb_height % ctx->tile_rows;
639 for (i = 0; i < ctx->tile_rows; i++) {
640 enccfg->tile_heights[i] = tile_size +
641 (i < rounding / 2 ||
642 i > ctx->tile_rows - 1 - (rounding + 1) / 2);
643 }
644
645 return 0;
646}
647
James Almer99cc3cf2018-03-29 02:15:18648static av_cold int aom_init(AVCodecContext *avctx,
649 const struct aom_codec_iface *iface)
Luca Barbato43778a52018-02-11 20:33:25650{
651 AOMContext *ctx = avctx->priv_data;
James Almer36e51c12020-07-17 20:46:32652 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt);
Luca Barbato43778a52018-02-11 20:33:25653 struct aom_codec_enc_cfg enccfg = { 0 };
Sam Johne2658322018-09-28 22:09:05654#ifdef AOM_FRAME_IS_INTRAONLY
655 aom_codec_flags_t flags =
656 (avctx->flags & AV_CODEC_FLAG_PSNR) ? AOM_CODEC_USE_PSNR : 0;
657#else
James Almer99cc3cf2018-03-29 02:15:18658 aom_codec_flags_t flags = 0;
Sam Johne2658322018-09-28 22:09:05659#endif
Luca Barbato43778a52018-02-11 20:33:25660 AVCPBProperties *cpb_props;
661 int res;
James Almer99cc3cf2018-03-29 02:15:18662 aom_img_fmt_t img_fmt;
663 aom_codec_caps_t codec_caps = aom_codec_get_caps(iface);
Luca Barbato43778a52018-02-11 20:33:25664
665 av_log(avctx, AV_LOG_INFO, "%s\n", aom_codec_version_str());
666 av_log(avctx, AV_LOG_VERBOSE, "%s\n", aom_codec_build_config());
667
James Zerncb23c1e2021-08-14 02:00:50668 if ((res = aom_codec_enc_config_default(iface, &enccfg, ctx->usage)) != AOM_CODEC_OK) {
Luca Barbato43778a52018-02-11 20:33:25669 av_log(avctx, AV_LOG_ERROR, "Failed to get config: %s\n",
670 aom_codec_err_to_string(res));
671 return AVERROR(EINVAL);
672 }
James Almer99cc3cf2018-03-29 02:15:18673
674 if (set_pix_fmt(avctx, codec_caps, &enccfg, &flags, &img_fmt))
675 return AVERROR(EINVAL);
676
677 if(!avctx->bit_rate)
678 if(avctx->rc_max_rate || avctx->rc_buffer_size || avctx->rc_initial_buffer_occupancy) {
679 av_log( avctx, AV_LOG_ERROR, "Rate control parameters set without a bitrate\n");
680 return AVERROR(EINVAL);
681 }
682
Matthieu Patou268f1342021-06-14 18:18:24683 dump_enc_cfg(avctx, &enccfg, AV_LOG_DEBUG);
Luca Barbato43778a52018-02-11 20:33:25684
685 enccfg.g_w = avctx->width;
686 enccfg.g_h = avctx->height;
687 enccfg.g_timebase.num = avctx->time_base.num;
688 enccfg.g_timebase.den = avctx->time_base.den;
Jun Zhaob87063c2018-11-27 09:18:26689 enccfg.g_threads =
690 FFMIN(avctx->thread_count ? avctx->thread_count : av_cpu_count(), 64);
Luca Barbato43778a52018-02-11 20:33:25691
Luca Barbato43778a52018-02-11 20:33:25692 if (ctx->lag_in_frames >= 0)
693 enccfg.g_lag_in_frames = ctx->lag_in_frames;
694
695 if (avctx->flags & AV_CODEC_FLAG_PASS1)
696 enccfg.g_pass = AOM_RC_FIRST_PASS;
697 else if (avctx->flags & AV_CODEC_FLAG_PASS2)
698 enccfg.g_pass = AOM_RC_LAST_PASS;
699 else
700 enccfg.g_pass = AOM_RC_ONE_PASS;
701
James Almer99cc3cf2018-03-29 02:15:18702 if (avctx->rc_min_rate == avctx->rc_max_rate &&
703 avctx->rc_min_rate == avctx->bit_rate && avctx->bit_rate) {
704 enccfg.rc_end_usage = AOM_CBR;
705 } else if (ctx->crf >= 0) {
706 enccfg.rc_end_usage = AOM_CQ;
707 if (!avctx->bit_rate)
708 enccfg.rc_end_usage = AOM_Q;
709 }
710
711 if (avctx->bit_rate) {
Luca Barbato43778a52018-02-11 20:33:25712 enccfg.rc_target_bitrate = av_rescale_rnd(avctx->bit_rate, 1, 1000,
713 AV_ROUND_NEAR_INF);
James Almer25abaf32018-03-29 19:18:27714 } else if (enccfg.rc_end_usage != AOM_Q) {
elliottkea673a02019-09-15 21:02:50715 enccfg.rc_end_usage = AOM_Q;
716 ctx->crf = 32;
717 av_log(avctx, AV_LOG_WARNING,
718 "Neither bitrate nor constrained quality specified, using default CRF of %d\n",
719 ctx->crf);
James Almer99cc3cf2018-03-29 02:15:18720 }
Luca Barbato43778a52018-02-11 20:33:25721
James Almer99cc3cf2018-03-29 02:15:18722 if (avctx->qmin >= 0)
Luca Barbato43778a52018-02-11 20:33:25723 enccfg.rc_min_quantizer = avctx->qmin;
Carl Eugen Hoyos288ca1c2021-03-20 18:27:48724 if (avctx->qmax >= 0) {
Luca Barbato43778a52018-02-11 20:33:25725 enccfg.rc_max_quantizer = avctx->qmax;
Carl Eugen Hoyos288ca1c2021-03-20 18:27:48726 } else if (!ctx->crf) {
727 enccfg.rc_max_quantizer = 0;
728 }
Luca Barbato43778a52018-02-11 20:33:25729
James Almer25abaf32018-03-29 19:18:27730 if (enccfg.rc_end_usage == AOM_CQ || enccfg.rc_end_usage == AOM_Q) {
James Almer99cc3cf2018-03-29 02:15:18731 if (ctx->crf < enccfg.rc_min_quantizer || ctx->crf > enccfg.rc_max_quantizer) {
732 av_log(avctx, AV_LOG_ERROR,
733 "CQ level %d must be between minimum and maximum quantizer value (%d-%d)\n",
734 ctx->crf, enccfg.rc_min_quantizer, enccfg.rc_max_quantizer);
735 return AVERROR(EINVAL);
736 }
737 }
738
Luca Barbato43778a52018-02-11 20:33:25739 enccfg.rc_dropframe_thresh = ctx->drop_threshold;
740
741 // 0-100 (0 => CBR, 100 => VBR)
742 enccfg.rc_2pass_vbr_bias_pct = round(avctx->qcompress * 100);
Sam John via ffmpeg-devel995889a2019-03-29 16:58:38743 if (ctx->minsection_pct >= 0)
744 enccfg.rc_2pass_vbr_minsection_pct = ctx->minsection_pct;
745 else if (avctx->bit_rate)
James Almer99cc3cf2018-03-29 02:15:18746 enccfg.rc_2pass_vbr_minsection_pct =
747 avctx->rc_min_rate * 100LL / avctx->bit_rate;
Sam John via ffmpeg-devel995889a2019-03-29 16:58:38748 if (ctx->maxsection_pct >= 0)
749 enccfg.rc_2pass_vbr_maxsection_pct = ctx->maxsection_pct;
750 else if (avctx->rc_max_rate)
Luca Barbato43778a52018-02-11 20:33:25751 enccfg.rc_2pass_vbr_maxsection_pct =
752 avctx->rc_max_rate * 100LL / avctx->bit_rate;
753
754 if (avctx->rc_buffer_size)
755 enccfg.rc_buf_sz =
756 avctx->rc_buffer_size * 1000LL / avctx->bit_rate;
757 if (avctx->rc_initial_buffer_occupancy)
758 enccfg.rc_buf_initial_sz =
759 avctx->rc_initial_buffer_occupancy * 1000LL / avctx->bit_rate;
760 enccfg.rc_buf_optimal_sz = enccfg.rc_buf_sz * 5 / 6;
761
Sam John via ffmpeg-devel995889a2019-03-29 16:58:38762 if (ctx->rc_undershoot_pct >= 0)
763 enccfg.rc_undershoot_pct = ctx->rc_undershoot_pct;
764 if (ctx->rc_overshoot_pct >= 0)
765 enccfg.rc_overshoot_pct = ctx->rc_overshoot_pct;
766
Luca Barbato43778a52018-02-11 20:33:25767 // _enc_init() will balk if kf_min_dist differs from max w/AOM_KF_AUTO
768 if (avctx->keyint_min >= 0 && avctx->keyint_min == avctx->gop_size)
769 enccfg.kf_min_dist = avctx->keyint_min;
770 if (avctx->gop_size >= 0)
771 enccfg.kf_max_dist = avctx->gop_size;
772
773 if (enccfg.g_pass == AOM_RC_FIRST_PASS)
774 enccfg.g_lag_in_frames = 0;
775 else if (enccfg.g_pass == AOM_RC_LAST_PASS) {
776 int decode_size, ret;
777
778 if (!avctx->stats_in) {
779 av_log(avctx, AV_LOG_ERROR, "No stats file for second pass\n");
780 return AVERROR_INVALIDDATA;
781 }
782
783 ctx->twopass_stats.sz = strlen(avctx->stats_in) * 3 / 4;
784 ret = av_reallocp(&ctx->twopass_stats.buf, ctx->twopass_stats.sz);
785 if (ret < 0) {
786 av_log(avctx, AV_LOG_ERROR,
James Almer99cc3cf2018-03-29 02:15:18787 "Stat buffer alloc (%"SIZE_SPECIFIER" bytes) failed\n",
Luca Barbato43778a52018-02-11 20:33:25788 ctx->twopass_stats.sz);
James Almer99cc3cf2018-03-29 02:15:18789 ctx->twopass_stats.sz = 0;
Luca Barbato43778a52018-02-11 20:33:25790 return ret;
791 }
792 decode_size = av_base64_decode(ctx->twopass_stats.buf, avctx->stats_in,
793 ctx->twopass_stats.sz);
794 if (decode_size < 0) {
795 av_log(avctx, AV_LOG_ERROR, "Stat buffer decode failed\n");
796 return AVERROR_INVALIDDATA;
797 }
798
799 ctx->twopass_stats.sz = decode_size;
800 enccfg.rc_twopass_stats_in = ctx->twopass_stats;
801 }
802
803 /* 0-3: For non-zero values the encoder increasingly optimizes for reduced
804 * complexity playback on low powered devices at the expense of encode
805 * quality. */
806 if (avctx->profile != FF_PROFILE_UNKNOWN)
807 enccfg.g_profile = avctx->profile;
Luca Barbato43778a52018-02-11 20:33:25808
809 enccfg.g_error_resilient = ctx->error_resilient;
810
Mark Thompson70709552018-10-22 22:40:07811 res = choose_tiling(avctx, &enccfg);
812 if (res < 0)
813 return res;
814
Vignesh Venkatasubramanianab05e9a2022-05-02 21:37:01815 if (ctx->still_picture) {
816 // Set the maximum number of frames to 1. This will let libaom set
817 // still_picture and reduced_still_picture_header to 1 in the Sequence
818 // Header as required by AVIF still images.
819 enccfg.g_limit = 1;
820 // Reduce memory usage for still images.
821 enccfg.g_lag_in_frames = 0;
822 // All frames will be key frames.
823 enccfg.kf_max_dist = 0;
824 enccfg.kf_mode = AOM_KF_DISABLED;
825 }
826
Luca Barbato43778a52018-02-11 20:33:25827 /* Construct Encoder Context */
James Almer99cc3cf2018-03-29 02:15:18828 res = aom_codec_enc_init(&ctx->encoder, iface, &enccfg, flags);
Luca Barbato43778a52018-02-11 20:33:25829 if (res != AOM_CODEC_OK) {
Matthieu Patou268f1342021-06-14 18:18:24830 dump_enc_cfg(avctx, &enccfg, AV_LOG_WARNING);
Luca Barbato43778a52018-02-11 20:33:25831 log_encoder_error(avctx, "Failed to initialize encoder");
832 return AVERROR(EINVAL);
833 }
Matthieu Patou268f1342021-06-14 18:18:24834 dump_enc_cfg(avctx, &enccfg, AV_LOG_DEBUG);
Luca Barbato43778a52018-02-11 20:33:25835
836 // codec control failures are currently treated only as warnings
837 av_log(avctx, AV_LOG_DEBUG, "aom_codec_control\n");
James Almer99cc3cf2018-03-29 02:15:18838 codecctl_int(avctx, AOME_SET_CPUUSED, ctx->cpu_used);
Luca Barbato43778a52018-02-11 20:33:25839 if (ctx->auto_alt_ref >= 0)
840 codecctl_int(avctx, AOME_SET_ENABLEAUTOALTREF, ctx->auto_alt_ref);
Sam John via ffmpeg-devel995889a2019-03-29 16:58:38841 if (ctx->arnr_max_frames >= 0)
842 codecctl_int(avctx, AOME_SET_ARNR_MAXFRAMES, ctx->arnr_max_frames);
843 if (ctx->arnr_strength >= 0)
844 codecctl_int(avctx, AOME_SET_ARNR_STRENGTH, ctx->arnr_strength);
845 if (ctx->enable_cdef >= 0)
846 codecctl_int(avctx, AV1E_SET_ENABLE_CDEF, ctx->enable_cdef);
Wang Cao8c9d82a2019-12-23 20:16:24847 if (ctx->enable_restoration >= 0)
848 codecctl_int(avctx, AV1E_SET_ENABLE_RESTORATION, ctx->enable_restoration);
James Zernd2947162020-07-02 02:53:54849#if AOM_ENCODER_ABI_VERSION >= 22
Wang Caoaa5c6f32020-06-26 00:55:13850 if (ctx->enable_rect_partitions >= 0)
851 codecctl_int(avctx, AV1E_SET_ENABLE_RECT_PARTITIONS, ctx->enable_rect_partitions);
852 if (ctx->enable_1to4_partitions >= 0)
853 codecctl_int(avctx, AV1E_SET_ENABLE_1TO4_PARTITIONS, ctx->enable_1to4_partitions);
854 if (ctx->enable_ab_partitions >= 0)
855 codecctl_int(avctx, AV1E_SET_ENABLE_AB_PARTITIONS, ctx->enable_ab_partitions);
Wang Cao297d5a12020-06-26 00:55:14856 if (ctx->enable_angle_delta >= 0)
857 codecctl_int(avctx, AV1E_SET_ENABLE_ANGLE_DELTA, ctx->enable_angle_delta);
858 if (ctx->enable_cfl_intra >= 0)
859 codecctl_int(avctx, AV1E_SET_ENABLE_CFL_INTRA, ctx->enable_cfl_intra);
860 if (ctx->enable_filter_intra >= 0)
861 codecctl_int(avctx, AV1E_SET_ENABLE_FILTER_INTRA, ctx->enable_filter_intra);
862 if (ctx->enable_intra_edge_filter >= 0)
863 codecctl_int(avctx, AV1E_SET_ENABLE_INTRA_EDGE_FILTER, ctx->enable_intra_edge_filter);
864 if (ctx->enable_paeth_intra >= 0)
865 codecctl_int(avctx, AV1E_SET_ENABLE_PAETH_INTRA, ctx->enable_paeth_intra);
866 if (ctx->enable_smooth_intra >= 0)
867 codecctl_int(avctx, AV1E_SET_ENABLE_SMOOTH_INTRA, ctx->enable_smooth_intra);
868 if (ctx->enable_palette >= 0)
869 codecctl_int(avctx, AV1E_SET_ENABLE_PALETTE, ctx->enable_palette);
Wang Cao498ad7b2020-07-22 23:12:01870 if (ctx->enable_tx64 >= 0)
871 codecctl_int(avctx, AV1E_SET_ENABLE_TX64, ctx->enable_tx64);
872 if (ctx->enable_flip_idtx >= 0)
873 codecctl_int(avctx, AV1E_SET_ENABLE_FLIP_IDTX, ctx->enable_flip_idtx);
874 if (ctx->use_intra_dct_only >= 0)
875 codecctl_int(avctx, AV1E_SET_INTRA_DCT_ONLY, ctx->use_intra_dct_only);
876 if (ctx->use_inter_dct_only >= 0)
877 codecctl_int(avctx, AV1E_SET_INTER_DCT_ONLY, ctx->use_inter_dct_only);
878 if (ctx->use_intra_default_tx_only >= 0)
879 codecctl_int(avctx, AV1E_SET_INTRA_DEFAULT_TX_ONLY, ctx->use_intra_default_tx_only);
880 if (ctx->reduced_tx_type_set >= 0)
881 codecctl_int(avctx, AV1E_SET_REDUCED_TX_TYPE_SET, ctx->reduced_tx_type_set);
Wang Cao017bf962020-07-22 23:11:12882 if (ctx->enable_ref_frame_mvs >= 0)
883 codecctl_int(avctx, AV1E_SET_ENABLE_REF_FRAME_MVS, ctx->enable_ref_frame_mvs);
884 if (ctx->enable_reduced_reference_set >= 0)
885 codecctl_int(avctx, AV1E_SET_REDUCED_REFERENCE_SET, ctx->enable_reduced_reference_set);
886 if (ctx->enable_diff_wtd_comp >= 0)
887 codecctl_int(avctx, AV1E_SET_ENABLE_DIFF_WTD_COMP, ctx->enable_diff_wtd_comp);
888 if (ctx->enable_dist_wtd_comp >= 0)
889 codecctl_int(avctx, AV1E_SET_ENABLE_DIST_WTD_COMP, ctx->enable_dist_wtd_comp);
890 if (ctx->enable_dual_filter >= 0)
891 codecctl_int(avctx, AV1E_SET_ENABLE_DUAL_FILTER, ctx->enable_dual_filter);
892 if (ctx->enable_interinter_wedge >= 0)
893 codecctl_int(avctx, AV1E_SET_ENABLE_INTERINTER_WEDGE, ctx->enable_interinter_wedge);
894 if (ctx->enable_masked_comp >= 0)
895 codecctl_int(avctx, AV1E_SET_ENABLE_MASKED_COMP, ctx->enable_masked_comp);
896 if (ctx->enable_interintra_comp >= 0)
897 codecctl_int(avctx, AV1E_SET_ENABLE_INTERINTRA_COMP, ctx->enable_interintra_comp);
898 if (ctx->enable_interintra_wedge >= 0)
899 codecctl_int(avctx, AV1E_SET_ENABLE_INTERINTRA_WEDGE, ctx->enable_interintra_wedge);
900 if (ctx->enable_obmc >= 0)
901 codecctl_int(avctx, AV1E_SET_ENABLE_OBMC, ctx->enable_obmc);
902 if (ctx->enable_onesided_comp >= 0)
903 codecctl_int(avctx, AV1E_SET_ENABLE_ONESIDED_COMP, ctx->enable_onesided_comp);
904 if (ctx->enable_smooth_interintra >= 0)
905 codecctl_int(avctx, AV1E_SET_ENABLE_SMOOTH_INTERINTRA, ctx->enable_smooth_interintra);
James Zernd2947162020-07-02 02:53:54906#endif
Wang Cao8c9d82a2019-12-23 20:16:24907
Luca Barbato43778a52018-02-11 20:33:25908 codecctl_int(avctx, AOME_SET_STATIC_THRESHOLD, ctx->static_thresh);
James Almer99cc3cf2018-03-29 02:15:18909 if (ctx->crf >= 0)
910 codecctl_int(avctx, AOME_SET_CQ_LEVEL, ctx->crf);
Wang Caobd3389e2020-04-03 21:00:26911 if (ctx->tune >= 0)
912 codecctl_int(avctx, AOME_SET_TUNING, ctx->tune);
James Almer99cc3cf2018-03-29 02:15:18913
James Almer36e51c12020-07-17 20:46:32914 if (desc->flags & AV_PIX_FMT_FLAG_RGB) {
Lynne6a2f3f62020-07-16 10:39:05915 codecctl_int(avctx, AV1E_SET_COLOR_PRIMARIES, AVCOL_PRI_BT709);
916 codecctl_int(avctx, AV1E_SET_MATRIX_COEFFICIENTS, AVCOL_SPC_RGB);
917 codecctl_int(avctx, AV1E_SET_TRANSFER_CHARACTERISTICS, AVCOL_TRC_IEC61966_2_1);
918 } else {
919 codecctl_int(avctx, AV1E_SET_COLOR_PRIMARIES, avctx->color_primaries);
920 codecctl_int(avctx, AV1E_SET_MATRIX_COEFFICIENTS, avctx->colorspace);
921 codecctl_int(avctx, AV1E_SET_TRANSFER_CHARACTERISTICS, avctx->color_trc);
922 }
Sam John via ffmpeg-devel995889a2019-03-29 16:58:38923 if (ctx->aq_mode >= 0)
924 codecctl_int(avctx, AV1E_SET_AQ_MODE, ctx->aq_mode);
925 if (ctx->frame_parallel >= 0)
926 codecctl_int(avctx, AV1E_SET_FRAME_PARALLEL_DECODING, ctx->frame_parallel);
James Almer99cc3cf2018-03-29 02:15:18927 set_color_range(avctx);
Luca Barbato43778a52018-02-11 20:33:25928
Mark Thompson70709552018-10-22 22:40:07929 codecctl_int(avctx, AV1E_SET_SUPERBLOCK_SIZE, ctx->superblock_size);
930 if (ctx->uniform_tiles) {
931 codecctl_int(avctx, AV1E_SET_TILE_COLUMNS, ctx->tile_cols_log2);
932 codecctl_int(avctx, AV1E_SET_TILE_ROWS, ctx->tile_rows_log2);
933 }
934
Sam John via ffmpeg-devel995889a2019-03-29 16:58:38935#ifdef AOM_CTRL_AV1E_SET_DENOISE_NOISE_LEVEL
936 if (ctx->denoise_noise_level >= 0)
937 codecctl_int(avctx, AV1E_SET_DENOISE_NOISE_LEVEL, ctx->denoise_noise_level);
938#endif
939#ifdef AOM_CTRL_AV1E_SET_DENOISE_BLOCK_SIZE
940 if (ctx->denoise_block_size >= 0)
941 codecctl_int(avctx, AV1E_SET_DENOISE_BLOCK_SIZE, ctx->denoise_block_size);
942#endif
943#ifdef AOM_CTRL_AV1E_SET_ENABLE_GLOBAL_MOTION
944 if (ctx->enable_global_motion >= 0)
945 codecctl_int(avctx, AV1E_SET_ENABLE_GLOBAL_MOTION, ctx->enable_global_motion);
946#endif
947#ifdef AOM_CTRL_AV1E_SET_MAX_REFERENCE_FRAMES
948 if (avctx->refs >= 3) {
949 codecctl_int(avctx, AV1E_SET_MAX_REFERENCE_FRAMES, avctx->refs);
950 }
951#endif
James Almerd12d4d42018-12-08 23:14:12952#ifdef AOM_CTRL_AV1E_SET_ROW_MT
James Almer0856c5d2019-03-29 17:55:00953 if (ctx->row_mt >= 0)
954 codecctl_int(avctx, AV1E_SET_ROW_MT, ctx->row_mt);
James Almerd12d4d42018-12-08 23:14:12955#endif
Sam John via ffmpeg-devel995889a2019-03-29 16:58:38956#ifdef AOM_CTRL_AV1E_SET_ENABLE_INTRABC
957 if (ctx->enable_intrabc >= 0)
958 codecctl_int(avctx, AV1E_SET_ENABLE_INTRABC, ctx->enable_intrabc);
959#endif
James Almerd12d4d42018-12-08 23:14:12960
Bohan Li82aab8a2021-02-09 04:04:41961#if AOM_ENCODER_ABI_VERSION >= 23
962 {
963 AVDictionaryEntry *en = NULL;
964
965 while ((en = av_dict_get(ctx->aom_params, "", en, AV_DICT_IGNORE_SUFFIX))) {
966 int ret = aom_codec_set_option(&ctx->encoder, en->key, en->value);
967 if (ret != AOM_CODEC_OK) {
968 log_encoder_error(avctx, en->key);
969 return AVERROR_EXTERNAL;
970 }
971 }
972 }
973#endif
974
Luca Barbato43778a52018-02-11 20:33:25975 // provide dummy value to initialize wrapper, values will be updated each _encode()
James Almer99cc3cf2018-03-29 02:15:18976 aom_img_wrap(&ctx->rawimg, img_fmt, avctx->width, avctx->height, 1,
977 (unsigned char*)1);
978
979 if (codec_caps & AOM_CODEC_CAP_HIGHBITDEPTH)
980 ctx->rawimg.bit_depth = enccfg.g_bit_depth;
Luca Barbato43778a52018-02-11 20:33:25981
982 cpb_props = ff_add_cpb_side_data(avctx);
983 if (!cpb_props)
984 return AVERROR(ENOMEM);
985
James Almera754af92018-07-07 19:33:16986 if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
987 const AVBitStreamFilter *filter = av_bsf_get_by_name("extract_extradata");
988 int ret;
989
990 if (!filter) {
991 av_log(avctx, AV_LOG_ERROR, "extract_extradata bitstream filter "
992 "not found. This is a bug, please report it.\n");
993 return AVERROR_BUG;
994 }
995 ret = av_bsf_alloc(filter, &ctx->bsf);
996 if (ret < 0)
997 return ret;
998
999 ret = avcodec_parameters_from_context(ctx->bsf->par_in, avctx);
1000 if (ret < 0)
1001 return ret;
1002
1003 ret = av_bsf_init(ctx->bsf);
1004 if (ret < 0)
1005 return ret;
1006 }
1007
Luca Barbato43778a52018-02-11 20:33:251008 if (enccfg.rc_end_usage == AOM_CBR ||
1009 enccfg.g_pass != AOM_RC_ONE_PASS) {
1010 cpb_props->max_bitrate = avctx->rc_max_rate;
1011 cpb_props->min_bitrate = avctx->rc_min_rate;
1012 cpb_props->avg_bitrate = avctx->bit_rate;
1013 }
1014 cpb_props->buffer_size = avctx->rc_buffer_size;
1015
1016 return 0;
1017}
1018
Sam Johne2658322018-09-28 22:09:051019static inline void cx_pktcpy(AOMContext *ctx,
1020 struct FrameListData *dst,
Luca Barbato43778a52018-02-11 20:33:251021 const struct aom_codec_cx_pkt *src)
1022{
1023 dst->pts = src->data.frame.pts;
1024 dst->duration = src->data.frame.duration;
1025 dst->flags = src->data.frame.flags;
1026 dst->sz = src->data.frame.sz;
1027 dst->buf = src->data.frame.buf;
Sam Johne2658322018-09-28 22:09:051028#ifdef AOM_FRAME_IS_INTRAONLY
Sam Johne2658322018-09-28 22:09:051029 dst->frame_number = ++ctx->frame_number;
1030 dst->have_sse = ctx->have_sse;
1031 if (ctx->have_sse) {
1032 /* associate last-seen SSE to the frame. */
1033 /* Transfers ownership from ctx to dst. */
1034 memcpy(dst->sse, ctx->sse, sizeof(dst->sse));
1035 ctx->have_sse = 0;
1036 }
1037#endif
Luca Barbato43778a52018-02-11 20:33:251038}
1039
1040/**
1041 * Store coded frame information in format suitable for return from encode2().
1042 *
1043 * Write information from @a cx_frame to @a pkt
1044 * @return packet data size on success
1045 * @return a negative AVERROR on error
1046 */
1047static int storeframe(AVCodecContext *avctx, struct FrameListData *cx_frame,
1048 AVPacket *pkt)
1049{
James Almera754af92018-07-07 19:33:161050 AOMContext *ctx = avctx->priv_data;
Carl Eugen Hoyos1e8475b2019-04-16 12:20:431051 int av_unused pict_type;
Andreas Rheinhardt044daa72021-04-24 23:43:261052 int ret = ff_get_encode_buffer(avctx, pkt, cx_frame->sz, 0);
Luca Barbato43778a52018-02-11 20:33:251053 if (ret < 0) {
1054 av_log(avctx, AV_LOG_ERROR,
James Almer99cc3cf2018-03-29 02:15:181055 "Error getting output packet of size %"SIZE_SPECIFIER".\n", cx_frame->sz);
Luca Barbato43778a52018-02-11 20:33:251056 return ret;
1057 }
1058 memcpy(pkt->data, cx_frame->buf, pkt->size);
1059 pkt->pts = pkt->dts = cx_frame->pts;
1060
Sam Johne2658322018-09-28 22:09:051061 if (!!(cx_frame->flags & AOM_FRAME_IS_KEY)) {
Luca Barbato43778a52018-02-11 20:33:251062 pkt->flags |= AV_PKT_FLAG_KEY;
Sam Johne2658322018-09-28 22:09:051063#ifdef AOM_FRAME_IS_INTRAONLY
1064 pict_type = AV_PICTURE_TYPE_I;
1065 } else if (cx_frame->flags & AOM_FRAME_IS_INTRAONLY) {
1066 pict_type = AV_PICTURE_TYPE_I;
1067 } else {
1068 pict_type = AV_PICTURE_TYPE_P;
1069 }
1070
1071 ff_side_data_set_encoder_stats(pkt, 0, cx_frame->sse + 1,
1072 cx_frame->have_sse ? 3 : 0, pict_type);
1073
1074 if (cx_frame->have_sse) {
1075 int i;
1076 for (i = 0; i < 3; ++i) {
1077 avctx->error[i] += cx_frame->sse[i + 1];
1078 }
1079 cx_frame->have_sse = 0;
1080#endif
1081 }
James Almera754af92018-07-07 19:33:161082
1083 if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
1084 ret = av_bsf_send_packet(ctx->bsf, pkt);
1085 if (ret < 0) {
1086 av_log(avctx, AV_LOG_ERROR, "extract_extradata filter "
1087 "failed to send input packet\n");
1088 return ret;
1089 }
1090 ret = av_bsf_receive_packet(ctx->bsf, pkt);
1091
1092 if (ret < 0) {
1093 av_log(avctx, AV_LOG_ERROR, "extract_extradata filter "
1094 "failed to receive output packet\n");
1095 return ret;
1096 }
1097 }
Luca Barbato43778a52018-02-11 20:33:251098 return pkt->size;
1099}
1100
1101/**
1102 * Queue multiple output frames from the encoder, returning the front-most.
1103 * In cases where aom_codec_get_cx_data() returns more than 1 frame append
1104 * the frame queue. Return the head frame if available.
1105 * @return Stored frame size
1106 * @return AVERROR(EINVAL) on output size error
1107 * @return AVERROR(ENOMEM) on coded frame queue data allocation error
1108 */
1109static int queue_frames(AVCodecContext *avctx, AVPacket *pkt_out)
1110{
1111 AOMContext *ctx = avctx->priv_data;
1112 const struct aom_codec_cx_pkt *pkt;
1113 const void *iter = NULL;
1114 int size = 0;
1115
1116 if (ctx->coded_frame_list) {
1117 struct FrameListData *cx_frame = ctx->coded_frame_list;
1118 /* return the leading frame if we've already begun queueing */
1119 size = storeframe(avctx, cx_frame, pkt_out);
1120 if (size < 0)
1121 return size;
1122 ctx->coded_frame_list = cx_frame->next;
1123 free_coded_frame(cx_frame);
1124 }
1125
1126 /* consume all available output from the encoder before returning. buffers
1127 * are only good through the next aom_codec call */
1128 while ((pkt = aom_codec_get_cx_data(&ctx->encoder, &iter))) {
1129 switch (pkt->kind) {
1130 case AOM_CODEC_CX_FRAME_PKT:
1131 if (!size) {
1132 struct FrameListData cx_frame;
1133
1134 /* avoid storing the frame when the list is empty and we haven't yet
1135 * provided a frame for output */
James Almerc42c99c2018-03-30 01:35:331136 av_assert0(!ctx->coded_frame_list);
Sam Johne2658322018-09-28 22:09:051137 cx_pktcpy(ctx, &cx_frame, pkt);
Luca Barbato43778a52018-02-11 20:33:251138 size = storeframe(avctx, &cx_frame, pkt_out);
1139 if (size < 0)
1140 return size;
1141 } else {
1142 struct FrameListData *cx_frame =
1143 av_malloc(sizeof(struct FrameListData));
1144
1145 if (!cx_frame) {
1146 av_log(avctx, AV_LOG_ERROR,
1147 "Frame queue element alloc failed\n");
1148 return AVERROR(ENOMEM);
1149 }
Sam Johne2658322018-09-28 22:09:051150 cx_pktcpy(ctx, cx_frame, pkt);
Luca Barbato43778a52018-02-11 20:33:251151 cx_frame->buf = av_malloc(cx_frame->sz);
1152
1153 if (!cx_frame->buf) {
1154 av_log(avctx, AV_LOG_ERROR,
James Almer99cc3cf2018-03-29 02:15:181155 "Data buffer alloc (%"SIZE_SPECIFIER" bytes) failed\n",
Luca Barbato43778a52018-02-11 20:33:251156 cx_frame->sz);
1157 av_freep(&cx_frame);
1158 return AVERROR(ENOMEM);
1159 }
1160 memcpy(cx_frame->buf, pkt->data.frame.buf, pkt->data.frame.sz);
1161 coded_frame_add(&ctx->coded_frame_list, cx_frame);
1162 }
1163 break;
1164 case AOM_CODEC_STATS_PKT:
1165 {
1166 struct aom_fixed_buf *stats = &ctx->twopass_stats;
1167 int err;
1168 if ((err = av_reallocp(&stats->buf,
1169 stats->sz +
1170 pkt->data.twopass_stats.sz)) < 0) {
1171 stats->sz = 0;
1172 av_log(avctx, AV_LOG_ERROR, "Stat buffer realloc failed\n");
1173 return err;
1174 }
1175 memcpy((uint8_t *)stats->buf + stats->sz,
1176 pkt->data.twopass_stats.buf, pkt->data.twopass_stats.sz);
1177 stats->sz += pkt->data.twopass_stats.sz;
1178 break;
1179 }
Sam Johne2658322018-09-28 22:09:051180#ifdef AOM_FRAME_IS_INTRAONLY
1181 case AOM_CODEC_PSNR_PKT:
1182 {
1183 av_assert0(!ctx->have_sse);
1184 ctx->sse[0] = pkt->data.psnr.sse[0];
1185 ctx->sse[1] = pkt->data.psnr.sse[1];
1186 ctx->sse[2] = pkt->data.psnr.sse[2];
1187 ctx->sse[3] = pkt->data.psnr.sse[3];
1188 ctx->have_sse = 1;
1189 break;
1190 }
1191#endif
Luca Barbato43778a52018-02-11 20:33:251192 case AOM_CODEC_CUSTOM_PKT:
1193 // ignore unsupported/unrecognized packet types
1194 break;
1195 }
1196 }
1197
1198 return size;
1199}
1200
1201static int aom_encode(AVCodecContext *avctx, AVPacket *pkt,
1202 const AVFrame *frame, int *got_packet)
1203{
1204 AOMContext *ctx = avctx->priv_data;
1205 struct aom_image *rawimg = NULL;
1206 int64_t timestamp = 0;
1207 int res, coded_size;
1208 aom_enc_frame_flags_t flags = 0;
1209
1210 if (frame) {
1211 rawimg = &ctx->rawimg;
1212 rawimg->planes[AOM_PLANE_Y] = frame->data[0];
1213 rawimg->planes[AOM_PLANE_U] = frame->data[1];
1214 rawimg->planes[AOM_PLANE_V] = frame->data[2];
1215 rawimg->stride[AOM_PLANE_Y] = frame->linesize[0];
1216 rawimg->stride[AOM_PLANE_U] = frame->linesize[1];
1217 rawimg->stride[AOM_PLANE_V] = frame->linesize[2];
1218 timestamp = frame->pts;
1219 switch (frame->color_range) {
1220 case AVCOL_RANGE_MPEG:
1221 rawimg->range = AOM_CR_STUDIO_RANGE;
1222 break;
1223 case AVCOL_RANGE_JPEG:
1224 rawimg->range = AOM_CR_FULL_RANGE;
1225 break;
1226 }
1227
1228 if (frame->pict_type == AV_PICTURE_TYPE_I)
1229 flags |= AOM_EFLAG_FORCE_KF;
1230 }
1231
1232 res = aom_codec_encode(&ctx->encoder, rawimg, timestamp,
1233 avctx->ticks_per_frame, flags);
1234 if (res != AOM_CODEC_OK) {
1235 log_encoder_error(avctx, "Error encoding frame");
1236 return AVERROR_INVALIDDATA;
1237 }
1238 coded_size = queue_frames(avctx, pkt);
1239
1240 if (!frame && avctx->flags & AV_CODEC_FLAG_PASS1) {
1241 size_t b64_size = AV_BASE64_SIZE(ctx->twopass_stats.sz);
1242
1243 avctx->stats_out = av_malloc(b64_size);
1244 if (!avctx->stats_out) {
James Almer99cc3cf2018-03-29 02:15:181245 av_log(avctx, AV_LOG_ERROR, "Stat buffer alloc (%"SIZE_SPECIFIER" bytes) failed\n",
Luca Barbato43778a52018-02-11 20:33:251246 b64_size);
1247 return AVERROR(ENOMEM);
1248 }
1249 av_base64_encode(avctx->stats_out, b64_size, ctx->twopass_stats.buf,
1250 ctx->twopass_stats.sz);
1251 }
1252
1253 *got_packet = !!coded_size;
1254 return 0;
1255}
1256
James Almer99cc3cf2018-03-29 02:15:181257static const enum AVPixelFormat av1_pix_fmts[] = {
1258 AV_PIX_FMT_YUV420P,
1259 AV_PIX_FMT_YUV422P,
1260 AV_PIX_FMT_YUV444P,
Lynne6a2f3f62020-07-16 10:39:051261 AV_PIX_FMT_GBRP,
James Almer99cc3cf2018-03-29 02:15:181262 AV_PIX_FMT_NONE
1263};
1264
Philip Langdale40135822020-12-08 00:33:291265static const enum AVPixelFormat av1_pix_fmts_with_gray[] = {
1266 AV_PIX_FMT_YUV420P,
1267 AV_PIX_FMT_YUV422P,
1268 AV_PIX_FMT_YUV444P,
1269 AV_PIX_FMT_GBRP,
1270 AV_PIX_FMT_GRAY8,
1271 AV_PIX_FMT_NONE
1272};
1273
James Almer99cc3cf2018-03-29 02:15:181274static const enum AVPixelFormat av1_pix_fmts_highbd[] = {
1275 AV_PIX_FMT_YUV420P,
1276 AV_PIX_FMT_YUV422P,
1277 AV_PIX_FMT_YUV444P,
Lynne6a2f3f62020-07-16 10:39:051278 AV_PIX_FMT_GBRP,
James Almer99cc3cf2018-03-29 02:15:181279 AV_PIX_FMT_YUV420P10,
1280 AV_PIX_FMT_YUV422P10,
1281 AV_PIX_FMT_YUV444P10,
1282 AV_PIX_FMT_YUV420P12,
1283 AV_PIX_FMT_YUV422P12,
1284 AV_PIX_FMT_YUV444P12,
Lynne6a2f3f62020-07-16 10:39:051285 AV_PIX_FMT_GBRP10,
1286 AV_PIX_FMT_GBRP12,
James Almer99cc3cf2018-03-29 02:15:181287 AV_PIX_FMT_NONE
1288};
1289
Philip Langdale40135822020-12-08 00:33:291290static const enum AVPixelFormat av1_pix_fmts_highbd_with_gray[] = {
1291 AV_PIX_FMT_YUV420P,
1292 AV_PIX_FMT_YUV422P,
1293 AV_PIX_FMT_YUV444P,
1294 AV_PIX_FMT_GBRP,
1295 AV_PIX_FMT_YUV420P10,
1296 AV_PIX_FMT_YUV422P10,
1297 AV_PIX_FMT_YUV444P10,
1298 AV_PIX_FMT_YUV420P12,
1299 AV_PIX_FMT_YUV422P12,
1300 AV_PIX_FMT_YUV444P12,
1301 AV_PIX_FMT_GBRP10,
1302 AV_PIX_FMT_GBRP12,
1303 AV_PIX_FMT_GRAY8,
1304 AV_PIX_FMT_GRAY10,
1305 AV_PIX_FMT_GRAY12,
1306 AV_PIX_FMT_NONE
1307};
1308
Andreas Rheinhardt20f97272022-03-16 20:09:541309static av_cold void av1_init_static(FFCodec *codec)
James Almer99cc3cf2018-03-29 02:15:181310{
Philip Langdale40135822020-12-08 00:33:291311 int supports_monochrome = aom_codec_version() >= 20001;
James Almer99cc3cf2018-03-29 02:15:181312 aom_codec_caps_t codec_caps = aom_codec_get_caps(aom_codec_av1_cx());
1313 if (codec_caps & AOM_CODEC_CAP_HIGHBITDEPTH)
Andreas Rheinhardt20f97272022-03-16 20:09:541314 codec->p.pix_fmts = supports_monochrome ? av1_pix_fmts_highbd_with_gray :
1315 av1_pix_fmts_highbd;
James Almer99cc3cf2018-03-29 02:15:181316 else
Andreas Rheinhardt20f97272022-03-16 20:09:541317 codec->p.pix_fmts = supports_monochrome ? av1_pix_fmts_with_gray :
1318 av1_pix_fmts;
James Almer49d37b42020-05-27 01:27:421319
1320 if (aom_codec_version_major() < 2)
Andreas Rheinhardt20f97272022-03-16 20:09:541321 codec->p.capabilities |= AV_CODEC_CAP_EXPERIMENTAL;
James Almer99cc3cf2018-03-29 02:15:181322}
1323
1324static av_cold int av1_init(AVCodecContext *avctx)
1325{
1326 return aom_init(avctx, aom_codec_av1_cx());
1327}
1328
Luca Barbato43778a52018-02-11 20:33:251329#define OFFSET(x) offsetof(AOMContext, x)
1330#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
1331static const AVOption options[] = {
Gyan Doshi076b1962018-08-05 06:03:451332 { "cpu-used", "Quality/Speed ratio modifier", OFFSET(cpu_used), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 8, VE},
Luca Barbato43778a52018-02-11 20:33:251333 { "auto-alt-ref", "Enable use of alternate reference "
James Almer99cc3cf2018-03-29 02:15:181334 "frames (2-pass only)", OFFSET(auto_alt_ref), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 2, VE},
Luca Barbato43778a52018-02-11 20:33:251335 { "lag-in-frames", "Number of frames to look ahead at for "
1336 "alternate reference frame selection", OFFSET(lag_in_frames), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, VE},
Sam John via ffmpeg-devel995889a2019-03-29 16:58:381337 { "arnr-max-frames", "altref noise reduction max frame count", OFFSET(arnr_max_frames), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, VE},
1338 { "arnr-strength", "altref noise reduction filter strength", OFFSET(arnr_strength), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 6, VE},
1339 { "aq-mode", "adaptive quantization mode", OFFSET(aq_mode), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 4, VE, "aq_mode"},
1340 { "none", "Aq not used", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, 0, 0, VE, "aq_mode"},
1341 { "variance", "Variance based Aq", 0, AV_OPT_TYPE_CONST, {.i64 = 1}, 0, 0, VE, "aq_mode"},
1342 { "complexity", "Complexity based Aq", 0, AV_OPT_TYPE_CONST, {.i64 = 2}, 0, 0, VE, "aq_mode"},
1343 { "cyclic", "Cyclic Refresh Aq", 0, AV_OPT_TYPE_CONST, {.i64 = 3}, 0, 0, VE, "aq_mode"},
Luca Barbato43778a52018-02-11 20:33:251344 { "error-resilience", "Error resilience configuration", OFFSET(error_resilient), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX, VE, "er"},
1345 { "default", "Improve resiliency against losses of whole frames", 0, AV_OPT_TYPE_CONST, {.i64 = AOM_ERROR_RESILIENT_DEFAULT}, 0, 0, VE, "er"},
James Almer99cc3cf2018-03-29 02:15:181346 { "crf", "Select the quality for constant quality mode", offsetof(AOMContext, crf), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 63, VE },
Luca Barbato43778a52018-02-11 20:33:251347 { "static-thresh", "A change threshold on blocks below which they will be skipped by the encoder", OFFSET(static_thresh), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE },
1348 { "drop-threshold", "Frame drop threshold", offsetof(AOMContext, drop_threshold), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, VE },
Sam John via ffmpeg-devel995889a2019-03-29 16:58:381349 { "denoise-noise-level", "Amount of noise to be removed", OFFSET(denoise_noise_level), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, VE},
1350 { "denoise-block-size", "Denoise block size ", OFFSET(denoise_block_size), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, VE},
1351 { "undershoot-pct", "Datarate undershoot (min) target (%)", OFFSET(rc_undershoot_pct), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 100, VE},
1352 { "overshoot-pct", "Datarate overshoot (max) target (%)", OFFSET(rc_overshoot_pct), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 1000, VE},
1353 { "minsection-pct", "GOP min bitrate (% of target)", OFFSET(minsection_pct), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 100, VE},
1354 { "maxsection-pct", "GOP max bitrate (% of target)", OFFSET(maxsection_pct), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 5000, VE},
1355 { "frame-parallel", "Enable frame parallel decodability features", OFFSET(frame_parallel), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE},
Mark Thompson70709552018-10-22 22:40:071356 { "tiles", "Tile columns x rows", OFFSET(tile_cols), AV_OPT_TYPE_IMAGE_SIZE, { .str = NULL }, 0, 0, VE },
1357 { "tile-columns", "Log2 of number of tile columns to use", OFFSET(tile_cols_log2), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 6, VE},
1358 { "tile-rows", "Log2 of number of tile rows to use", OFFSET(tile_rows_log2), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 6, VE},
James Almer0856c5d2019-03-29 17:55:001359 { "row-mt", "Enable row based multi-threading", OFFSET(row_mt), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE},
Sam John via ffmpeg-devel995889a2019-03-29 16:58:381360 { "enable-cdef", "Enable CDEF filtering", OFFSET(enable_cdef), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE},
1361 { "enable-global-motion", "Enable global motion", OFFSET(enable_global_motion), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE},
James Almer0e1ea032019-04-02 22:54:341362 { "enable-intrabc", "Enable intra block copy prediction mode", OFFSET(enable_intrabc), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE},
Wang Cao8c9d82a2019-12-23 20:16:241363 { "enable-restoration", "Enable Loop Restoration filtering", OFFSET(enable_restoration), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE},
James Zern0ece8052020-04-11 22:22:351364 { "usage", "Quality and compression efficiency vs speed trade-off", OFFSET(usage), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, VE, "usage"},
James Almerc4615002020-01-23 00:02:171365 { "good", "Good quality", 0, AV_OPT_TYPE_CONST, {.i64 = 0 /* AOM_USAGE_GOOD_QUALITY */}, 0, 0, VE, "usage"},
1366 { "realtime", "Realtime encoding", 0, AV_OPT_TYPE_CONST, {.i64 = 1 /* AOM_USAGE_REALTIME */}, 0, 0, VE, "usage"},
Vignesh Venkatasubramanianf55c9142022-05-18 17:37:551367 { "allintra", "All Intra encoding", 0, AV_OPT_TYPE_CONST, {.i64 = 2 /* AOM_USAGE_ALL_INTRA */}, 0, 0, VE, "usage"},
Wang Caobd3389e2020-04-03 21:00:261368 { "tune", "The metric that the encoder tunes for. Automatically chosen by the encoder by default", OFFSET(tune), AV_OPT_TYPE_INT, {.i64 = -1}, -1, AOM_TUNE_SSIM, VE, "tune"},
1369 { "psnr", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AOM_TUNE_PSNR}, 0, 0, VE, "tune"},
1370 { "ssim", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AOM_TUNE_SSIM}, 0, 0, VE, "tune"},
James Almer82b64e92020-06-26 02:28:571371 FF_AV1_PROFILE_OPTS
Vignesh Venkatasubramanianab05e9a2022-05-02 21:37:011372 { "still-picture", "Encode in single frame mode (typically used for still AVIF images).", OFFSET(still_picture), AV_OPT_TYPE_BOOL, {.i64 = 0}, -1, 1, VE },
Wang Caoaa5c6f32020-06-26 00:55:131373 { "enable-rect-partitions", "Enable rectangular partitions", OFFSET(enable_rect_partitions), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE},
1374 { "enable-1to4-partitions", "Enable 1:4/4:1 partitions", OFFSET(enable_1to4_partitions), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE},
1375 { "enable-ab-partitions", "Enable ab shape partitions", OFFSET(enable_ab_partitions), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE},
Wang Cao297d5a12020-06-26 00:55:141376 { "enable-angle-delta", "Enable angle delta intra prediction", OFFSET(enable_angle_delta), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE},
1377 { "enable-cfl-intra", "Enable chroma predicted from luma intra prediction", OFFSET(enable_cfl_intra), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE},
1378 { "enable-filter-intra", "Enable filter intra predictor", OFFSET(enable_filter_intra), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE},
1379 { "enable-intra-edge-filter", "Enable intra edge filter", OFFSET(enable_intra_edge_filter), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE},
1380 { "enable-smooth-intra", "Enable smooth intra prediction mode", OFFSET(enable_smooth_intra), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE},
1381 { "enable-paeth-intra", "Enable paeth predictor in intra prediction", OFFSET(enable_paeth_intra), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE},
1382 { "enable-palette", "Enable palette prediction mode", OFFSET(enable_palette), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE},
Wang Cao498ad7b2020-07-22 23:12:011383 { "enable-flip-idtx", "Enable extended transform type", OFFSET(enable_flip_idtx), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE},
1384 { "enable-tx64", "Enable 64-pt transform", OFFSET(enable_tx64), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE},
1385 { "reduced-tx-type-set", "Use reduced set of transform types", OFFSET(reduced_tx_type_set), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE},
1386 { "use-intra-dct-only", "Use DCT only for INTRA modes", OFFSET(use_intra_dct_only), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE},
1387 { "use-inter-dct-only", "Use DCT only for INTER modes", OFFSET(use_inter_dct_only), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE},
1388 { "use-intra-default-tx-only", "Use default-transform only for INTRA modes", OFFSET(use_intra_default_tx_only), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE},
Wang Cao017bf962020-07-22 23:11:121389 { "enable-ref-frame-mvs", "Enable temporal mv prediction", OFFSET(enable_ref_frame_mvs), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE},
1390 { "enable-reduced-reference-set", "Use reduced set of single and compound references", OFFSET(enable_reduced_reference_set), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE},
1391 { "enable-obmc", "Enable obmc", OFFSET(enable_obmc), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE},
1392 { "enable-dual-filter", "Enable dual filter", OFFSET(enable_dual_filter), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE},
1393 { "enable-diff-wtd-comp", "Enable difference-weighted compound", OFFSET(enable_diff_wtd_comp), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE},
1394 { "enable-dist-wtd-comp", "Enable distance-weighted compound", OFFSET(enable_dist_wtd_comp), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE},
1395 { "enable-onesided-comp", "Enable one sided compound", OFFSET(enable_onesided_comp), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE},
1396 { "enable-interinter-wedge", "Enable interinter wedge compound", OFFSET(enable_interinter_wedge), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE},
1397 { "enable-interintra-wedge", "Enable interintra wedge compound", OFFSET(enable_interintra_wedge), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE},
1398 { "enable-masked-comp", "Enable masked compound", OFFSET(enable_masked_comp), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE},
1399 { "enable-interintra-comp", "Enable interintra compound", OFFSET(enable_interintra_comp), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE},
1400 { "enable-smooth-interintra", "Enable smooth interintra mode", OFFSET(enable_smooth_interintra), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE},
Bohan Li82aab8a2021-02-09 04:04:411401#if AOM_ENCODER_ABI_VERSION >= 23
1402 { "aom-params", "Set libaom options using a :-separated list of key=value pairs", OFFSET(aom_params), AV_OPT_TYPE_DICT, { 0 }, 0, 0, VE },
1403#endif
Sam John via ffmpeg-devel995889a2019-03-29 16:58:381404 { NULL },
Luca Barbato43778a52018-02-11 20:33:251405};
1406
Andreas Rheinhardt5aabb252022-03-16 20:26:111407static const FFCodecDefault defaults[] = {
elliottk711c59b2019-08-21 19:18:201408 { "b", "0" },
Luca Barbato43778a52018-02-11 20:33:251409 { "qmin", "-1" },
1410 { "qmax", "-1" },
1411 { "g", "-1" },
1412 { "keyint_min", "-1" },
1413 { NULL },
1414};
1415
1416static const AVClass class_aom = {
James Almer99cc3cf2018-03-29 02:15:181417 .class_name = "libaom-av1 encoder",
Luca Barbato43778a52018-02-11 20:33:251418 .item_name = av_default_item_name,
1419 .option = options,
1420 .version = LIBAVUTIL_VERSION_INT,
1421};
1422
Andreas Rheinhardt20f97272022-03-16 20:09:541423FFCodec ff_libaom_av1_encoder = {
1424 .p.name = "libaom-av1",
1425 .p.long_name = NULL_IF_CONFIG_SMALL("libaom AV1"),
1426 .p.type = AVMEDIA_TYPE_VIDEO,
1427 .p.id = AV_CODEC_ID_AV1,
1428 .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
Andreas Rheinhardt044daa72021-04-24 23:43:261429 AV_CODEC_CAP_OTHER_THREADS,
Andreas Rheinhardt20f97272022-03-16 20:09:541430 .p.profiles = NULL_IF_CONFIG_SMALL(ff_av1_profiles),
1431 .p.priv_class = &class_aom,
1432 .p.wrapper_name = "libaom",
Luca Barbato43778a52018-02-11 20:33:251433 .priv_data_size = sizeof(AOMContext),
James Almer99cc3cf2018-03-29 02:15:181434 .init = av1_init,
Andreas Rheinhardt4243da42022-03-30 21:28:241435 FF_CODEC_ENCODE_CB(aom_encode),
Luca Barbato43778a52018-02-11 20:33:251436 .close = aom_free,
Anton Khirnov8a129072021-03-09 17:00:441437 .caps_internal = FF_CODEC_CAP_AUTO_THREADS,
Luca Barbato43778a52018-02-11 20:33:251438 .defaults = defaults,
James Almer99cc3cf2018-03-29 02:15:181439 .init_static_data = av1_init_static,
Luca Barbato43778a52018-02-11 20:33:251440};