| File: | root/firefox-clang/media/ffvpx/libavcodec/libaomenc.c |
| Warning: | line 896, column 44 Division by zero |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* | ||||
| 2 | * Copyright (c) 2010, Google, Inc. | ||||
| 3 | * | ||||
| 4 | * This file is part of FFmpeg. | ||||
| 5 | * | ||||
| 6 | * FFmpeg is free software; you can redistribute it and/or | ||||
| 7 | * 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 | * | ||||
| 11 | * FFmpeg is distributed in the hope that it will be useful, | ||||
| 12 | * 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 | ||||
| 17 | * License along with FFmpeg; if not, write to the Free Software | ||||
| 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||||
| 19 | */ | ||||
| 20 | |||||
| 21 | /** | ||||
| 22 | * @file | ||||
| 23 | * AV1 encoder support via libaom | ||||
| 24 | */ | ||||
| 25 | |||||
| 26 | #include <limits.h> | ||||
| 27 | |||||
| 28 | #define AOM_DISABLE_CTRL_TYPECHECKS1 1 | ||||
| 29 | #include <aom/aom_encoder.h> | ||||
| 30 | #include <aom/aomcx.h> | ||||
| 31 | |||||
| 32 | #include "libavutil/avassert.h" | ||||
| 33 | #include "libavutil/avstring.h" | ||||
| 34 | #include "libavutil/base64.h" | ||||
| 35 | #include "libavutil/cpu.h" | ||||
| 36 | #include "libavutil/hdr_dynamic_metadata.h" | ||||
| 37 | #include "libavutil/imgutils.h" | ||||
| 38 | #include "libavutil/mathematics.h" | ||||
| 39 | #include "libavutil/mem.h" | ||||
| 40 | #include "libavutil/opt.h" | ||||
| 41 | #include "libavutil/pixdesc.h" | ||||
| 42 | |||||
| 43 | #include "av1.h" | ||||
| 44 | #include "avcodec.h" | ||||
| 45 | #include "bsf.h" | ||||
| 46 | #include "bytestream.h" | ||||
| 47 | #include "codec_internal.h" | ||||
| 48 | #include "dovi_rpu.h" | ||||
| 49 | #include "encode.h" | ||||
| 50 | #include "internal.h" | ||||
| 51 | #include "itut35.h" | ||||
| 52 | #include "libaom.h" | ||||
| 53 | #include "profiles.h" | ||||
| 54 | |||||
| 55 | /* | ||||
| 56 | * Portion of struct aom_codec_cx_pkt from aom_encoder.h. | ||||
| 57 | * One encoded frame returned from the library. | ||||
| 58 | */ | ||||
| 59 | struct FrameListData { | ||||
| 60 | void *buf; /**< compressed data buffer */ | ||||
| 61 | size_t sz; /**< length of compressed data */ | ||||
| 62 | int64_t pts; /**< time stamp to show frame | ||||
| 63 | (in timebase units) */ | ||||
| 64 | unsigned long duration; /**< duration to show frame | ||||
| 65 | (in timebase units) */ | ||||
| 66 | uint32_t flags; /**< flags for this frame */ | ||||
| 67 | uint64_t sse[4]; | ||||
| 68 | int have_sse; /**< true if we have pending sse[] */ | ||||
| 69 | uint64_t frame_number; | ||||
| 70 | struct FrameListData *next; | ||||
| 71 | }; | ||||
| 72 | |||||
| 73 | typedef struct AOMEncoderContext { | ||||
| 74 | AVClass *class; | ||||
| 75 | AVBSFContext *bsf; | ||||
| 76 | DOVIContext dovi; | ||||
| 77 | struct aom_codec_ctx encoder; | ||||
| 78 | struct aom_image rawimg; | ||||
| 79 | struct aom_fixed_buf twopass_stats; | ||||
| 80 | unsigned twopass_stats_size; | ||||
| 81 | struct FrameListData *coded_frame_list; | ||||
| 82 | int cpu_used; | ||||
| 83 | int auto_alt_ref; | ||||
| 84 | int arnr_max_frames; | ||||
| 85 | int arnr_strength; | ||||
| 86 | int aq_mode; | ||||
| 87 | int lag_in_frames; | ||||
| 88 | int error_resilient; | ||||
| 89 | int crf; | ||||
| 90 | int static_thresh; | ||||
| 91 | int drop_threshold; | ||||
| 92 | int denoise_noise_level; | ||||
| 93 | int denoise_block_size; | ||||
| 94 | uint64_t sse[4]; | ||||
| 95 | int have_sse; /**< true if we have pending sse[] */ | ||||
| 96 | uint64_t frame_number; | ||||
| 97 | int rc_undershoot_pct; | ||||
| 98 | int rc_overshoot_pct; | ||||
| 99 | int minsection_pct; | ||||
| 100 | int maxsection_pct; | ||||
| 101 | int frame_parallel; | ||||
| 102 | int tile_cols, tile_rows; | ||||
| 103 | int tile_cols_log2, tile_rows_log2; | ||||
| 104 | aom_superblock_size_t superblock_size; | ||||
| 105 | int uniform_tiles; | ||||
| 106 | int row_mt; | ||||
| 107 | int enable_cdef; | ||||
| 108 | int enable_global_motion; | ||||
| 109 | int enable_intrabc; | ||||
| 110 | int enable_restoration; | ||||
| 111 | int usage; | ||||
| 112 | int tune; | ||||
| 113 | int still_picture; | ||||
| 114 | int enable_rect_partitions; | ||||
| 115 | int enable_1to4_partitions; | ||||
| 116 | int enable_ab_partitions; | ||||
| 117 | int enable_angle_delta; | ||||
| 118 | int enable_cfl_intra; | ||||
| 119 | int enable_paeth_intra; | ||||
| 120 | int enable_smooth_intra; | ||||
| 121 | int enable_intra_edge_filter; | ||||
| 122 | int enable_palette; | ||||
| 123 | int enable_filter_intra; | ||||
| 124 | int enable_flip_idtx; | ||||
| 125 | int enable_tx64; | ||||
| 126 | int reduced_tx_type_set; | ||||
| 127 | int use_intra_dct_only; | ||||
| 128 | int use_inter_dct_only; | ||||
| 129 | int use_intra_default_tx_only; | ||||
| 130 | int enable_ref_frame_mvs; | ||||
| 131 | int enable_interinter_wedge; | ||||
| 132 | int enable_interintra_wedge; | ||||
| 133 | int enable_interintra_comp; | ||||
| 134 | int enable_masked_comp; | ||||
| 135 | int enable_obmc; | ||||
| 136 | int enable_onesided_comp; | ||||
| 137 | int enable_reduced_reference_set; | ||||
| 138 | int enable_smooth_interintra; | ||||
| 139 | int enable_diff_wtd_comp; | ||||
| 140 | int enable_dist_wtd_comp; | ||||
| 141 | int enable_dual_filter; | ||||
| 142 | AVDictionary *svc_parameters; | ||||
| 143 | AVDictionary *aom_params; | ||||
| 144 | } AOMContext; | ||||
| 145 | |||||
| 146 | #define OFFSET(x)__builtin_offsetof(AOMContext, x) offsetof(AOMContext, x)__builtin_offsetof(AOMContext, x) | ||||
| 147 | |||||
| 148 | static const char *const ctlidstr[] = { | ||||
| 149 | [AOME_SET_CPUUSED] = "AOME_SET_CPUUSED", | ||||
| 150 | [AOME_SET_CQ_LEVEL] = "AOME_SET_CQ_LEVEL", | ||||
| 151 | [AOME_SET_ENABLEAUTOALTREF] = "AOME_SET_ENABLEAUTOALTREF", | ||||
| 152 | [AOME_SET_ARNR_MAXFRAMES] = "AOME_SET_ARNR_MAXFRAMES", | ||||
| 153 | [AOME_SET_ARNR_STRENGTH] = "AOME_SET_ARNR_STRENGTH", | ||||
| 154 | [AOME_SET_STATIC_THRESHOLD] = "AOME_SET_STATIC_THRESHOLD", | ||||
| 155 | [AV1E_SET_COLOR_RANGE] = "AV1E_SET_COLOR_RANGE", | ||||
| 156 | [AV1E_SET_COLOR_PRIMARIES] = "AV1E_SET_COLOR_PRIMARIES", | ||||
| 157 | [AV1E_SET_MATRIX_COEFFICIENTS] = "AV1E_SET_MATRIX_COEFFICIENTS", | ||||
| 158 | [AV1E_SET_TRANSFER_CHARACTERISTICS] = "AV1E_SET_TRANSFER_CHARACTERISTICS", | ||||
| 159 | [AV1E_SET_AQ_MODE] = "AV1E_SET_AQ_MODE", | ||||
| 160 | [AV1E_SET_FRAME_PARALLEL_DECODING] = "AV1E_SET_FRAME_PARALLEL_DECODING", | ||||
| 161 | [AV1E_SET_SUPERBLOCK_SIZE] = "AV1E_SET_SUPERBLOCK_SIZE", | ||||
| 162 | [AV1E_SET_TILE_COLUMNS] = "AV1E_SET_TILE_COLUMNS", | ||||
| 163 | [AV1E_SET_TILE_ROWS] = "AV1E_SET_TILE_ROWS", | ||||
| 164 | [AV1E_SET_ENABLE_RESTORATION] = "AV1E_SET_ENABLE_RESTORATION", | ||||
| 165 | [AV1E_SET_ROW_MT] = "AV1E_SET_ROW_MT", | ||||
| 166 | [AV1E_SET_DENOISE_NOISE_LEVEL] = "AV1E_SET_DENOISE_NOISE_LEVEL", | ||||
| 167 | [AV1E_SET_DENOISE_BLOCK_SIZE] = "AV1E_SET_DENOISE_BLOCK_SIZE", | ||||
| 168 | [AV1E_SET_MAX_REFERENCE_FRAMES] = "AV1E_SET_MAX_REFERENCE_FRAMES", | ||||
| 169 | [AV1E_SET_ENABLE_GLOBAL_MOTION] = "AV1E_SET_ENABLE_GLOBAL_MOTION", | ||||
| 170 | [AV1E_SET_ENABLE_INTRABC] = "AV1E_SET_ENABLE_INTRABC", | ||||
| 171 | [AV1E_SET_ENABLE_CDEF] = "AV1E_SET_ENABLE_CDEF", | ||||
| 172 | [AOME_SET_TUNING] = "AOME_SET_TUNING", | ||||
| 173 | [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", | ||||
| 176 | [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", | ||||
| 183 | [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", | ||||
| 189 | [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", | ||||
| 201 | #ifdef AOM_CTRL_AV1E_GET_NUM_OPERATING_POINTS | ||||
| 202 | [AV1E_GET_NUM_OPERATING_POINTS] = "AV1E_GET_NUM_OPERATING_POINTS", | ||||
| 203 | #endif | ||||
| 204 | [AV1E_GET_SEQ_LEVEL_IDX] = "AV1E_GET_SEQ_LEVEL_IDX", | ||||
| 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 | ||||
| 208 | [AV1_GET_NEW_FRAME_IMAGE] = "AV1_GET_NEW_FRAME_IMAGE", | ||||
| 209 | [AV1E_SET_SVC_PARAMS] = "AV1E_SET_SVC_PARAMS", | ||||
| 210 | }; | ||||
| 211 | |||||
| 212 | static av_cold__attribute__((cold)) void log_encoder_error(AVCodecContext *avctx, const char *desc) | ||||
| 213 | { | ||||
| 214 | AOMContext *ctx = avctx->priv_data; | ||||
| 215 | const char *error = aom_codec_error(&ctx->encoder); | ||||
| 216 | const char *detail = aom_codec_error_detail(&ctx->encoder); | ||||
| 217 | |||||
| 218 | av_log(avctx, AV_LOG_ERROR16, "%s: %s\n", desc, error); | ||||
| 219 | if (detail) | ||||
| 220 | av_log(avctx, AV_LOG_ERROR16, " Additional information: %s\n", detail); | ||||
| 221 | } | ||||
| 222 | |||||
| 223 | static av_cold__attribute__((cold)) void dump_enc_cfg(AVCodecContext *avctx, | ||||
| 224 | const struct aom_codec_enc_cfg *cfg, | ||||
| 225 | int level) | ||||
| 226 | { | ||||
| 227 | int width = -30; | ||||
| 228 | |||||
| 229 | av_log(avctx, level, "aom_codec_enc_cfg\n"); | ||||
| 230 | av_log(avctx, level, "generic settings\n" | ||||
| 231 | " %*s%u\n %*s%u\n %*s%u\n %*s%u\n %*s%u\n" | ||||
| 232 | " %*s%u\n %*s%u\n" | ||||
| 233 | " %*s{%u/%u}\n %*s%u\n %*s%d\n %*s%u\n", | ||||
| 234 | width, "g_usage:", cfg->g_usage, | ||||
| 235 | width, "g_threads:", cfg->g_threads, | ||||
| 236 | width, "g_profile:", cfg->g_profile, | ||||
| 237 | width, "g_w:", cfg->g_w, | ||||
| 238 | width, "g_h:", cfg->g_h, | ||||
| 239 | width, "g_bit_depth:", cfg->g_bit_depth, | ||||
| 240 | width, "g_input_bit_depth:", cfg->g_input_bit_depth, | ||||
| 241 | width, "g_timebase:", cfg->g_timebase.num, cfg->g_timebase.den, | ||||
| 242 | width, "g_error_resilient:", cfg->g_error_resilient, | ||||
| 243 | width, "g_pass:", cfg->g_pass, | ||||
| 244 | width, "g_lag_in_frames:", cfg->g_lag_in_frames); | ||||
| 245 | av_log(avctx, level, "rate control settings\n" | ||||
| 246 | " %*s%u\n %*s%d\n %*s%p(%zu)\n %*s%u\n", | ||||
| 247 | width, "rc_dropframe_thresh:", cfg->rc_dropframe_thresh, | ||||
| 248 | width, "rc_end_usage:", cfg->rc_end_usage, | ||||
| 249 | width, "rc_twopass_stats_in:", cfg->rc_twopass_stats_in.buf, cfg->rc_twopass_stats_in.sz, | ||||
| 250 | width, "rc_target_bitrate:", cfg->rc_target_bitrate); | ||||
| 251 | av_log(avctx, level, "quantizer settings\n" | ||||
| 252 | " %*s%u\n %*s%u\n", | ||||
| 253 | width, "rc_min_quantizer:", cfg->rc_min_quantizer, | ||||
| 254 | width, "rc_max_quantizer:", cfg->rc_max_quantizer); | ||||
| 255 | av_log(avctx, level, "bitrate tolerance\n" | ||||
| 256 | " %*s%u\n %*s%u\n", | ||||
| 257 | width, "rc_undershoot_pct:", cfg->rc_undershoot_pct, | ||||
| 258 | width, "rc_overshoot_pct:", cfg->rc_overshoot_pct); | ||||
| 259 | av_log(avctx, level, "decoder buffer model\n" | ||||
| 260 | " %*s%u\n %*s%u\n %*s%u\n", | ||||
| 261 | width, "rc_buf_sz:", cfg->rc_buf_sz, | ||||
| 262 | width, "rc_buf_initial_sz:", cfg->rc_buf_initial_sz, | ||||
| 263 | width, "rc_buf_optimal_sz:", cfg->rc_buf_optimal_sz); | ||||
| 264 | av_log(avctx, level, "2 pass rate control settings\n" | ||||
| 265 | " %*s%u\n %*s%u\n %*s%u\n", | ||||
| 266 | width, "rc_2pass_vbr_bias_pct:", cfg->rc_2pass_vbr_bias_pct, | ||||
| 267 | width, "rc_2pass_vbr_minsection_pct:", cfg->rc_2pass_vbr_minsection_pct, | ||||
| 268 | width, "rc_2pass_vbr_maxsection_pct:", cfg->rc_2pass_vbr_maxsection_pct); | ||||
| 269 | av_log(avctx, level, "keyframing settings\n" | ||||
| 270 | " %*s%d\n %*s%u\n %*s%u\n", | ||||
| 271 | width, "kf_mode:", cfg->kf_mode, | ||||
| 272 | width, "kf_min_dist:", cfg->kf_min_dist, | ||||
| 273 | width, "kf_max_dist:", cfg->kf_max_dist); | ||||
| 274 | av_log(avctx, level, "tile settings\n" | ||||
| 275 | " %*s%d\n %*s%d\n", | ||||
| 276 | width, "tile_width_count:", cfg->tile_width_count, | ||||
| 277 | width, "tile_height_count:", cfg->tile_height_count); | ||||
| 278 | av_log(avctx, level, "\n"); | ||||
| 279 | } | ||||
| 280 | |||||
| 281 | static void coded_frame_add(void *list, struct FrameListData *cx_frame) | ||||
| 282 | { | ||||
| 283 | struct FrameListData **p = list; | ||||
| 284 | |||||
| 285 | while (*p) | ||||
| 286 | p = &(*p)->next; | ||||
| 287 | *p = cx_frame; | ||||
| 288 | cx_frame->next = NULL((void*)0); | ||||
| 289 | } | ||||
| 290 | |||||
| 291 | static av_cold__attribute__((cold)) void free_coded_frame(struct FrameListData *cx_frame) | ||||
| 292 | { | ||||
| 293 | av_freep(&cx_frame->buf); | ||||
| 294 | av_freep(&cx_frame); | ||||
| 295 | } | ||||
| 296 | |||||
| 297 | static av_cold__attribute__((cold)) void free_frame_list(struct FrameListData *list) | ||||
| 298 | { | ||||
| 299 | struct FrameListData *p = list; | ||||
| 300 | |||||
| 301 | while (p) { | ||||
| 302 | list = list->next; | ||||
| 303 | free_coded_frame(p); | ||||
| 304 | p = list; | ||||
| 305 | } | ||||
| 306 | } | ||||
| 307 | |||||
| 308 | static av_cold__attribute__((cold)) int codecctl_int(AVCodecContext *avctx, | ||||
| 309 | int id, | ||||
| 310 | int val) | ||||
| 311 | { | ||||
| 312 | AOMContext *ctx = avctx->priv_data; | ||||
| 313 | char buf[80]; | ||||
| 314 | int width = -30; | ||||
| 315 | int res; | ||||
| 316 | |||||
| 317 | snprintf(buf, sizeof(buf), "%s:", ctlidstr[id]); | ||||
| 318 | av_log(avctx, AV_LOG_DEBUG48, " %*s%d\n", width, buf, val); | ||||
| 319 | |||||
| 320 | res = aom_codec_control(&ctx->encoder, id, val); | ||||
| 321 | if (res != AOM_CODEC_OK) { | ||||
| 322 | snprintf(buf, sizeof(buf), "Failed to set %s codec control", | ||||
| 323 | ctlidstr[id]); | ||||
| 324 | log_encoder_error(avctx, buf); | ||||
| 325 | return AVERROR(EINVAL)(-(22)); | ||||
| 326 | } | ||||
| 327 | |||||
| 328 | return 0; | ||||
| 329 | } | ||||
| 330 | |||||
| 331 | static int add_hdr_plus(AVCodecContext *avctx, struct aom_image *img, const AVFrame *frame) | ||||
| 332 | { | ||||
| 333 | // Check for HDR10+ | ||||
| 334 | AVFrameSideData *side_data = | ||||
| 335 | av_frame_get_side_data(frame, AV_FRAME_DATA_DYNAMIC_HDR_PLUS); | ||||
| 336 | if (!side_data) | ||||
| 337 | return 0; | ||||
| 338 | |||||
| 339 | size_t payload_size; | ||||
| 340 | AVDynamicHDRPlus *hdr_plus = (AVDynamicHDRPlus *)side_data->buf->data; | ||||
| 341 | int res = av_dynamic_hdr_plus_to_t35(hdr_plus, NULL((void*)0), &payload_size); | ||||
| 342 | if (res < 0) { | ||||
| 343 | log_encoder_error(avctx, "Error finding the size of HDR10+"); | ||||
| 344 | return res; | ||||
| 345 | } | ||||
| 346 | |||||
| 347 | uint8_t *hdr_plus_buf; | ||||
| 348 | // Extra bytes for the country code, provider code, provider oriented code and app id. | ||||
| 349 | const size_t hdr_plus_buf_size = payload_size + 6; | ||||
| 350 | hdr_plus_buf = av_malloc(hdr_plus_buf_size); | ||||
| 351 | if (!hdr_plus_buf) | ||||
| 352 | return AVERROR(ENOMEM)(-(12)); | ||||
| 353 | |||||
| 354 | uint8_t *payload = hdr_plus_buf; | ||||
| 355 | // See "HDR10+ AV1 Metadata Handling Specification" v1.0.1, Section 2.1. | ||||
| 356 | bytestream_put_byte(&payload, ITU_T_T35_COUNTRY_CODE_US0xB5); | ||||
| 357 | bytestream_put_be16(&payload, ITU_T_T35_PROVIDER_CODE_SAMSUNG0x003C); | ||||
| 358 | bytestream_put_be16(&payload, 0x0001); // provider_oriented_code | ||||
| 359 | bytestream_put_byte(&payload, 0x04); // application_identifier | ||||
| 360 | |||||
| 361 | res = av_dynamic_hdr_plus_to_t35(hdr_plus, &payload, &payload_size); | ||||
| 362 | if (res < 0) { | ||||
| 363 | av_free(hdr_plus_buf); | ||||
| 364 | log_encoder_error(avctx, "Error encoding HDR10+ from side data"); | ||||
| 365 | return res; | ||||
| 366 | } | ||||
| 367 | |||||
| 368 | res = aom_img_add_metadata(img, OBU_METADATA_TYPE_ITUT_T35, | ||||
| 369 | hdr_plus_buf, hdr_plus_buf_size, AOM_MIF_ANY_FRAME); | ||||
| 370 | av_free(hdr_plus_buf); | ||||
| 371 | if (res < 0) { | ||||
| 372 | log_encoder_error(avctx, "Error adding HDR10+ to aom_img"); | ||||
| 373 | return res; | ||||
| 374 | } | ||||
| 375 | return 0; | ||||
| 376 | } | ||||
| 377 | |||||
| 378 | #if defined(AOM_CTRL_AV1E_GET_NUM_OPERATING_POINTS) && \ | ||||
| 379 | defined(AOM_CTRL_AV1E_GET_SEQ_LEVEL_IDX) && \ | ||||
| 380 | defined(AOM_CTRL_AV1E_GET_TARGET_SEQ_LEVEL_IDX) | ||||
| 381 | static av_cold__attribute__((cold)) int codecctl_intp(AVCodecContext *avctx, | ||||
| 382 | int id, | ||||
| 383 | int* ptr) | ||||
| 384 | { | ||||
| 385 | AOMContext *ctx = avctx->priv_data; | ||||
| 386 | char buf[80]; | ||||
| 387 | int width = -30; | ||||
| 388 | int res; | ||||
| 389 | |||||
| 390 | res = aom_codec_control(&ctx->encoder, id, ptr); | ||||
| 391 | if (res != AOM_CODEC_OK) { | ||||
| 392 | snprintf(buf, sizeof(buf), "Failed to get %s codec control", | ||||
| 393 | ctlidstr[id]); | ||||
| 394 | log_encoder_error(avctx, buf); | ||||
| 395 | return AVERROR(EINVAL)(-(22)); | ||||
| 396 | } | ||||
| 397 | |||||
| 398 | snprintf(buf, sizeof(buf), "%s:", ctlidstr[id]); | ||||
| 399 | av_log(avctx, AV_LOG_DEBUG48, " %*s%d\n", width, buf, *ptr); | ||||
| 400 | |||||
| 401 | return 0; | ||||
| 402 | } | ||||
| 403 | #endif | ||||
| 404 | |||||
| 405 | static av_cold__attribute__((cold)) int codecctl_imgp(AVCodecContext *avctx, | ||||
| 406 | int id, | ||||
| 407 | struct aom_image *img) | ||||
| 408 | { | ||||
| 409 | AOMContext *ctx = avctx->priv_data; | ||||
| 410 | char buf[80]; | ||||
| 411 | int res; | ||||
| 412 | |||||
| 413 | snprintf(buf, sizeof(buf), "%s:", ctlidstr[id]); | ||||
| 414 | |||||
| 415 | res = aom_codec_control(&ctx->encoder, id, img); | ||||
| 416 | if (res != AOM_CODEC_OK) { | ||||
| 417 | snprintf(buf, sizeof(buf), "Failed to get %s codec control", | ||||
| 418 | ctlidstr[id]); | ||||
| 419 | log_encoder_error(avctx, buf); | ||||
| 420 | return AVERROR(EINVAL)(-(22)); | ||||
| 421 | } | ||||
| 422 | |||||
| 423 | return 0; | ||||
| 424 | } | ||||
| 425 | |||||
| 426 | static av_cold__attribute__((cold)) int codecctl_svcp(AVCodecContext *avctx, | ||||
| 427 | #ifdef UENUM1BYTE | ||||
| 428 | aome_enc_control_id id, | ||||
| 429 | #else | ||||
| 430 | enum aome_enc_control_id id, | ||||
| 431 | #endif | ||||
| 432 | aom_svc_params_t *svc_params) | ||||
| 433 | { | ||||
| 434 | AOMContext *ctx = avctx->priv_data; | ||||
| 435 | char buf[80]; | ||||
| 436 | int res; | ||||
| 437 | |||||
| 438 | snprintf(buf, sizeof(buf), "%s:", ctlidstr[id]); | ||||
| 439 | |||||
| 440 | res = aom_codec_control(&ctx->encoder, id, svc_params); | ||||
| 441 | if (res != AOM_CODEC_OK) { | ||||
| 442 | snprintf(buf, sizeof(buf), "Failed to get %s codec control", | ||||
| 443 | ctlidstr[id]); | ||||
| 444 | log_encoder_error(avctx, buf); | ||||
| 445 | return AVERROR(EINVAL)(-(22)); | ||||
| 446 | } | ||||
| 447 | |||||
| 448 | return 0; | ||||
| 449 | } | ||||
| 450 | |||||
| 451 | static av_cold__attribute__((cold)) int aom_free(AVCodecContext *avctx) | ||||
| 452 | { | ||||
| 453 | AOMContext *ctx = avctx->priv_data; | ||||
| 454 | |||||
| 455 | #if defined(AOM_CTRL_AV1E_GET_NUM_OPERATING_POINTS) && \ | ||||
| 456 | defined(AOM_CTRL_AV1E_GET_SEQ_LEVEL_IDX) && \ | ||||
| 457 | defined(AOM_CTRL_AV1E_GET_TARGET_SEQ_LEVEL_IDX) | ||||
| 458 | if (ctx->encoder.iface && !(avctx->flags & AV_CODEC_FLAG_PASS1(1 << 9))) { | ||||
| 459 | int num_operating_points; | ||||
| 460 | int levels[32]; | ||||
| 461 | int target_levels[32]; | ||||
| 462 | |||||
| 463 | if (!codecctl_intp(avctx, AV1E_GET_NUM_OPERATING_POINTS, | ||||
| 464 | &num_operating_points) && | ||||
| 465 | !codecctl_intp(avctx, AV1E_GET_SEQ_LEVEL_IDX, levels) && | ||||
| 466 | !codecctl_intp(avctx, AV1E_GET_TARGET_SEQ_LEVEL_IDX, | ||||
| 467 | target_levels)) { | ||||
| 468 | for (int i = 0; i < num_operating_points; i++) { | ||||
| 469 | if (levels[i] > target_levels[i]) { | ||||
| 470 | // Warn when the target level was not met | ||||
| 471 | av_log(avctx, AV_LOG_WARNING24, | ||||
| 472 | "Could not encode to target level %d.%d for " | ||||
| 473 | "operating point %d. The output level is %d.%d.\n", | ||||
| 474 | 2 + (target_levels[i] >> 2), target_levels[i] & 3, | ||||
| 475 | i, 2 + (levels[i] >> 2), levels[i] & 3); | ||||
| 476 | } else if (target_levels[i] < 31) { | ||||
| 477 | // Log the encoded level if a target level was given | ||||
| 478 | av_log(avctx, AV_LOG_INFO32, | ||||
| 479 | "Output level for operating point %d is %d.%d.\n", | ||||
| 480 | i, 2 + (levels[i] >> 2), levels[i] & 3); | ||||
| 481 | } | ||||
| 482 | } | ||||
| 483 | } | ||||
| 484 | } | ||||
| 485 | #endif | ||||
| 486 | |||||
| 487 | aom_codec_destroy(&ctx->encoder); | ||||
| 488 | aom_img_remove_metadata(&ctx->rawimg); | ||||
| 489 | av_freep(&ctx->twopass_stats.buf); | ||||
| 490 | av_freep(&avctx->stats_out); | ||||
| 491 | free_frame_list(ctx->coded_frame_list); | ||||
| 492 | av_bsf_free(&ctx->bsf); | ||||
| 493 | ff_dovi_ctx_unref(&ctx->dovi); | ||||
| 494 | return 0; | ||||
| 495 | } | ||||
| 496 | |||||
| 497 | static void aom_svc_parse_int_array(int *dest, char *value, int max_entries) | ||||
| 498 | { | ||||
| 499 | int dest_idx = 0; | ||||
| 500 | char *saveptr = NULL((void*)0); | ||||
| 501 | char *token = av_strtok(value, ",", &saveptr); | ||||
| 502 | |||||
| 503 | while (token && dest_idx < max_entries) { | ||||
| 504 | dest[dest_idx++] = strtoul(token, NULL((void*)0), 10); | ||||
| 505 | token = av_strtok(NULL((void*)0), ",", &saveptr); | ||||
| 506 | } | ||||
| 507 | } | ||||
| 508 | |||||
| 509 | static int set_pix_fmt(AVCodecContext *avctx, aom_codec_caps_t codec_caps, | ||||
| 510 | struct aom_codec_enc_cfg *enccfg, aom_codec_flags_t *flags, | ||||
| 511 | aom_img_fmt_t *img_fmt) | ||||
| 512 | { | ||||
| 513 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt); | ||||
| 514 | enccfg->g_bit_depth = enccfg->g_input_bit_depth = desc->comp[0].depth; | ||||
| 515 | switch (avctx->pix_fmt) { | ||||
| 516 | case AV_PIX_FMT_GRAY8: | ||||
| 517 | enccfg->monochrome = 1; | ||||
| 518 | /* Fall-through */ | ||||
| 519 | case AV_PIX_FMT_YUV420P: | ||||
| 520 | enccfg->g_profile = AV_PROFILE_AV1_MAIN0; | ||||
| 521 | *img_fmt = AOM_IMG_FMT_I420; | ||||
| 522 | return 0; | ||||
| 523 | case AV_PIX_FMT_YUV422P: | ||||
| 524 | enccfg->g_profile = AV_PROFILE_AV1_PROFESSIONAL2; | ||||
| 525 | *img_fmt = AOM_IMG_FMT_I422; | ||||
| 526 | return 0; | ||||
| 527 | case AV_PIX_FMT_YUV444P: | ||||
| 528 | case AV_PIX_FMT_GBRP: | ||||
| 529 | enccfg->g_profile = AV_PROFILE_AV1_HIGH1; | ||||
| 530 | *img_fmt = AOM_IMG_FMT_I444; | ||||
| 531 | return 0; | ||||
| 532 | case AV_PIX_FMT_GRAY10AV_PIX_FMT_GRAY10LE: | ||||
| 533 | case AV_PIX_FMT_GRAY12AV_PIX_FMT_GRAY12LE: | ||||
| 534 | enccfg->monochrome = 1; | ||||
| 535 | /* Fall-through */ | ||||
| 536 | case AV_PIX_FMT_YUV420P10AV_PIX_FMT_YUV420P10LE: | ||||
| 537 | case AV_PIX_FMT_YUV420P12AV_PIX_FMT_YUV420P12LE: | ||||
| 538 | if (codec_caps & AOM_CODEC_CAP_HIGHBITDEPTH0x40000) { | ||||
| 539 | enccfg->g_profile = | ||||
| 540 | enccfg->g_bit_depth == 10 ? AV_PROFILE_AV1_MAIN0 : AV_PROFILE_AV1_PROFESSIONAL2; | ||||
| 541 | *img_fmt = AOM_IMG_FMT_I42016; | ||||
| 542 | *flags |= AOM_CODEC_USE_HIGHBITDEPTH0x40000; | ||||
| 543 | return 0; | ||||
| 544 | } | ||||
| 545 | break; | ||||
| 546 | case AV_PIX_FMT_YUV422P10AV_PIX_FMT_YUV422P10LE: | ||||
| 547 | case AV_PIX_FMT_YUV422P12AV_PIX_FMT_YUV422P12LE: | ||||
| 548 | if (codec_caps & AOM_CODEC_CAP_HIGHBITDEPTH0x40000) { | ||||
| 549 | enccfg->g_profile = AV_PROFILE_AV1_PROFESSIONAL2; | ||||
| 550 | *img_fmt = AOM_IMG_FMT_I42216; | ||||
| 551 | *flags |= AOM_CODEC_USE_HIGHBITDEPTH0x40000; | ||||
| 552 | return 0; | ||||
| 553 | } | ||||
| 554 | break; | ||||
| 555 | case AV_PIX_FMT_YUV444P10AV_PIX_FMT_YUV444P10LE: | ||||
| 556 | case AV_PIX_FMT_YUV444P12AV_PIX_FMT_YUV444P12LE: | ||||
| 557 | case AV_PIX_FMT_GBRP10AV_PIX_FMT_GBRP10LE: | ||||
| 558 | case AV_PIX_FMT_GBRP12AV_PIX_FMT_GBRP12LE: | ||||
| 559 | if (codec_caps & AOM_CODEC_CAP_HIGHBITDEPTH0x40000) { | ||||
| 560 | enccfg->g_profile = | ||||
| 561 | enccfg->g_bit_depth == 10 ? AV_PROFILE_AV1_HIGH1 : AV_PROFILE_AV1_PROFESSIONAL2; | ||||
| 562 | *img_fmt = AOM_IMG_FMT_I44416; | ||||
| 563 | *flags |= AOM_CODEC_USE_HIGHBITDEPTH0x40000; | ||||
| 564 | return 0; | ||||
| 565 | } | ||||
| 566 | break; | ||||
| 567 | default: | ||||
| 568 | break; | ||||
| 569 | } | ||||
| 570 | av_log(avctx, AV_LOG_ERROR16, "Unsupported pixel format.\n"); | ||||
| 571 | return AVERROR_INVALIDDATA(-(int)(('I') | (('N') << 8) | (('D') << 16) | (( unsigned)('A') << 24))); | ||||
| 572 | } | ||||
| 573 | |||||
| 574 | static void set_color_range(AVCodecContext *avctx) | ||||
| 575 | { | ||||
| 576 | aom_color_range_t aom_cr; | ||||
| 577 | switch (avctx->color_range) { | ||||
| 578 | case AVCOL_RANGE_UNSPECIFIED: | ||||
| 579 | case AVCOL_RANGE_MPEG: aom_cr = AOM_CR_STUDIO_RANGE; break; | ||||
| 580 | case AVCOL_RANGE_JPEG: aom_cr = AOM_CR_FULL_RANGE; break; | ||||
| 581 | default: | ||||
| 582 | av_log(avctx, AV_LOG_WARNING24, "Unsupported color range (%d)\n", | ||||
| 583 | avctx->color_range); | ||||
| 584 | return; | ||||
| 585 | } | ||||
| 586 | |||||
| 587 | codecctl_int(avctx, AV1E_SET_COLOR_RANGE, aom_cr); | ||||
| 588 | } | ||||
| 589 | |||||
| 590 | static int count_uniform_tiling(int dim, int sb_size, int tiles_log2) | ||||
| 591 | { | ||||
| 592 | int sb_dim = (dim + sb_size - 1) / sb_size; | ||||
| 593 | int tile_dim = (sb_dim + (1 << tiles_log2) - 1) >> tiles_log2; | ||||
| 594 | av_assert0(tile_dim > 0)do { if (!(tile_dim > 0)) { av_log(((void*)0), 0, "Assertion %s failed at %s:%d\n" , "tile_dim > 0", "/root/firefox-clang/media/ffvpx/libavcodec/libaomenc.c" , 594); abort(); } } while (0); | ||||
| 595 | return (sb_dim + tile_dim - 1) / tile_dim; | ||||
| 596 | } | ||||
| 597 | |||||
| 598 | static int choose_tiling(AVCodecContext *avctx, | ||||
| 599 | struct aom_codec_enc_cfg *enccfg) | ||||
| 600 | { | ||||
| 601 | AOMContext *ctx = avctx->priv_data; | ||||
| 602 | int sb_128x128_possible, sb_size, sb_width, sb_height; | ||||
| 603 | int uniform_rows, uniform_cols; | ||||
| 604 | int uniform_64x64_possible, uniform_128x128_possible; | ||||
| 605 | int tile_size, rounding, i; | ||||
| 606 | |||||
| 607 | if (ctx->tile_cols_log2 >= 0) | ||||
| 608 | ctx->tile_cols = 1 << ctx->tile_cols_log2; | ||||
| 609 | if (ctx->tile_rows_log2 >= 0) | ||||
| 610 | ctx->tile_rows = 1 << ctx->tile_rows_log2; | ||||
| 611 | |||||
| 612 | if (ctx->tile_cols == 0) { | ||||
| 613 | ctx->tile_cols = (avctx->width + AV1_MAX_TILE_WIDTH - 1) / | ||||
| 614 | AV1_MAX_TILE_WIDTH; | ||||
| 615 | if (ctx->tile_cols > 1) { | ||||
| 616 | av_log(avctx, AV_LOG_DEBUG48, "Automatically using %d tile " | ||||
| 617 | "columns to fill width.\n", ctx->tile_cols); | ||||
| 618 | } | ||||
| 619 | } | ||||
| 620 | av_assert0(ctx->tile_cols > 0)do { if (!(ctx->tile_cols > 0)) { av_log(((void*)0), 0, "Assertion %s failed at %s:%d\n", "ctx->tile_cols > 0" , "/root/firefox-clang/media/ffvpx/libavcodec/libaomenc.c", 620 ); abort(); } } while (0); | ||||
| 621 | if (ctx->tile_rows == 0) { | ||||
| 622 | int max_tile_width = | ||||
| 623 | FFALIGN((FFALIGN(avctx->width, 128) +(((((((avctx->width)+(128)-1)&~((128)-1)) + ctx->tile_cols - 1) / ctx->tile_cols)+(128)-1)&~((128)-1)) | ||||
| 624 | ctx->tile_cols - 1) / ctx->tile_cols, 128)(((((((avctx->width)+(128)-1)&~((128)-1)) + ctx->tile_cols - 1) / ctx->tile_cols)+(128)-1)&~((128)-1)); | ||||
| 625 | ctx->tile_rows = | ||||
| 626 | (max_tile_width * FFALIGN(avctx->height, 128)(((avctx->height)+(128)-1)&~((128)-1)) + | ||||
| 627 | AV1_MAX_TILE_AREA - 1) / AV1_MAX_TILE_AREA; | ||||
| 628 | if (ctx->tile_rows > 1) { | ||||
| 629 | av_log(avctx, AV_LOG_DEBUG48, "Automatically using %d tile " | ||||
| 630 | "rows to fill area.\n", ctx->tile_rows); | ||||
| 631 | } | ||||
| 632 | } | ||||
| 633 | av_assert0(ctx->tile_rows > 0)do { if (!(ctx->tile_rows > 0)) { av_log(((void*)0), 0, "Assertion %s failed at %s:%d\n", "ctx->tile_rows > 0" , "/root/firefox-clang/media/ffvpx/libavcodec/libaomenc.c", 633 ); abort(); } } while (0); | ||||
| 634 | |||||
| 635 | if ((avctx->width + 63) / 64 < ctx->tile_cols || | ||||
| 636 | (avctx->height + 63) / 64 < ctx->tile_rows) { | ||||
| 637 | av_log(avctx, AV_LOG_ERROR16, "Invalid tile sizing: frame not " | ||||
| 638 | "large enough to fit specified tile arrangement.\n"); | ||||
| 639 | return AVERROR(EINVAL)(-(22)); | ||||
| 640 | } | ||||
| 641 | if (ctx->tile_cols > AV1_MAX_TILE_COLS || | ||||
| 642 | ctx->tile_rows > AV1_MAX_TILE_ROWS) { | ||||
| 643 | av_log(avctx, AV_LOG_ERROR16, "Invalid tile sizing: AV1 does " | ||||
| 644 | "not allow more than %dx%d tiles.\n", | ||||
| 645 | AV1_MAX_TILE_COLS, AV1_MAX_TILE_ROWS); | ||||
| 646 | return AVERROR(EINVAL)(-(22)); | ||||
| 647 | } | ||||
| 648 | if (avctx->width / ctx->tile_cols > AV1_MAX_TILE_WIDTH) { | ||||
| 649 | av_log(avctx, AV_LOG_ERROR16, "Invalid tile sizing: AV1 does " | ||||
| 650 | "not allow tiles of width greater than %d.\n", | ||||
| 651 | AV1_MAX_TILE_WIDTH); | ||||
| 652 | return AVERROR(EINVAL)(-(22)); | ||||
| 653 | } | ||||
| 654 | |||||
| 655 | ctx->superblock_size = AOM_SUPERBLOCK_SIZE_DYNAMIC; | ||||
| 656 | |||||
| 657 | if (ctx->tile_cols == 1 && ctx->tile_rows == 1) { | ||||
| 658 | av_log(avctx, AV_LOG_DEBUG48, "Using a single tile.\n"); | ||||
| 659 | return 0; | ||||
| 660 | } | ||||
| 661 | |||||
| 662 | sb_128x128_possible = | ||||
| 663 | (avctx->width + 127) / 128 >= ctx->tile_cols && | ||||
| 664 | (avctx->height + 127) / 128 >= ctx->tile_rows; | ||||
| 665 | |||||
| 666 | ctx->tile_cols_log2 = ctx->tile_cols == 1 ? 0 : | ||||
| 667 | av_log2(ctx->tile_cols - 1)(31 - __builtin_clz((ctx->tile_cols - 1)|1)) + 1; | ||||
| 668 | ctx->tile_rows_log2 = ctx->tile_rows == 1 ? 0 : | ||||
| 669 | av_log2(ctx->tile_rows - 1)(31 - __builtin_clz((ctx->tile_rows - 1)|1)) + 1; | ||||
| 670 | |||||
| 671 | uniform_cols = count_uniform_tiling(avctx->width, | ||||
| 672 | 64, ctx->tile_cols_log2); | ||||
| 673 | uniform_rows = count_uniform_tiling(avctx->height, | ||||
| 674 | 64, ctx->tile_rows_log2); | ||||
| 675 | av_log(avctx, AV_LOG_DEBUG48, "Uniform with 64x64 superblocks " | ||||
| 676 | "-> %dx%d tiles.\n", uniform_cols, uniform_rows); | ||||
| 677 | uniform_64x64_possible = uniform_cols == ctx->tile_cols && | ||||
| 678 | uniform_rows == ctx->tile_rows; | ||||
| 679 | |||||
| 680 | if (sb_128x128_possible) { | ||||
| 681 | uniform_cols = count_uniform_tiling(avctx->width, | ||||
| 682 | 128, ctx->tile_cols_log2); | ||||
| 683 | uniform_rows = count_uniform_tiling(avctx->height, | ||||
| 684 | 128, ctx->tile_rows_log2); | ||||
| 685 | av_log(avctx, AV_LOG_DEBUG48, "Uniform with 128x128 superblocks " | ||||
| 686 | "-> %dx%d tiles.\n", uniform_cols, uniform_rows); | ||||
| 687 | uniform_128x128_possible = uniform_cols == ctx->tile_cols && | ||||
| 688 | uniform_rows == ctx->tile_rows; | ||||
| 689 | } else { | ||||
| 690 | av_log(avctx, AV_LOG_DEBUG48, "128x128 superblocks not possible.\n"); | ||||
| 691 | uniform_128x128_possible = 0; | ||||
| 692 | } | ||||
| 693 | |||||
| 694 | ctx->uniform_tiles = 1; | ||||
| 695 | if (uniform_64x64_possible && uniform_128x128_possible) { | ||||
| 696 | av_log(avctx, AV_LOG_DEBUG48, "Using uniform tiling with dynamic " | ||||
| 697 | "superblocks (tile_cols_log2 = %d, tile_rows_log2 = %d).\n", | ||||
| 698 | ctx->tile_cols_log2, ctx->tile_rows_log2); | ||||
| 699 | return 0; | ||||
| 700 | } | ||||
| 701 | if (uniform_64x64_possible && !sb_128x128_possible) { | ||||
| 702 | av_log(avctx, AV_LOG_DEBUG48, "Using uniform tiling with 64x64 " | ||||
| 703 | "superblocks (tile_cols_log2 = %d, tile_rows_log2 = %d).\n", | ||||
| 704 | ctx->tile_cols_log2, ctx->tile_rows_log2); | ||||
| 705 | ctx->superblock_size = AOM_SUPERBLOCK_SIZE_64X64; | ||||
| 706 | return 0; | ||||
| 707 | } | ||||
| 708 | if (uniform_128x128_possible) { | ||||
| 709 | av_log(avctx, AV_LOG_DEBUG48, "Using uniform tiling with 128x128 " | ||||
| 710 | "superblocks (tile_cols_log2 = %d, tile_rows_log2 = %d).\n", | ||||
| 711 | ctx->tile_cols_log2, ctx->tile_rows_log2); | ||||
| 712 | ctx->superblock_size = AOM_SUPERBLOCK_SIZE_128X128; | ||||
| 713 | return 0; | ||||
| 714 | } | ||||
| 715 | ctx->uniform_tiles = 0; | ||||
| 716 | |||||
| 717 | if (sb_128x128_possible) { | ||||
| 718 | sb_size = 128; | ||||
| 719 | ctx->superblock_size = AOM_SUPERBLOCK_SIZE_128X128; | ||||
| 720 | } else { | ||||
| 721 | sb_size = 64; | ||||
| 722 | ctx->superblock_size = AOM_SUPERBLOCK_SIZE_64X64; | ||||
| 723 | } | ||||
| 724 | av_log(avctx, AV_LOG_DEBUG48, "Using fixed tiling with %dx%d " | ||||
| 725 | "superblocks (tile_cols = %d, tile_rows = %d).\n", | ||||
| 726 | sb_size, sb_size, ctx->tile_cols, ctx->tile_rows); | ||||
| 727 | |||||
| 728 | enccfg->tile_width_count = ctx->tile_cols; | ||||
| 729 | enccfg->tile_height_count = ctx->tile_rows; | ||||
| 730 | |||||
| 731 | sb_width = (avctx->width + sb_size - 1) / sb_size; | ||||
| 732 | sb_height = (avctx->height + sb_size - 1) / sb_size; | ||||
| 733 | |||||
| 734 | tile_size = sb_width / ctx->tile_cols; | ||||
| 735 | rounding = sb_width % ctx->tile_cols; | ||||
| 736 | for (i = 0; i < ctx->tile_cols; i++) { | ||||
| 737 | enccfg->tile_widths[i] = tile_size + | ||||
| 738 | (i < rounding / 2 || | ||||
| 739 | i > ctx->tile_cols - 1 - (rounding + 1) / 2); | ||||
| 740 | } | ||||
| 741 | |||||
| 742 | tile_size = sb_height / ctx->tile_rows; | ||||
| 743 | rounding = sb_height % ctx->tile_rows; | ||||
| 744 | for (i = 0; i < ctx->tile_rows; i++) { | ||||
| 745 | enccfg->tile_heights[i] = tile_size + | ||||
| 746 | (i < rounding / 2 || | ||||
| 747 | i > ctx->tile_rows - 1 - (rounding + 1) / 2); | ||||
| 748 | } | ||||
| 749 | |||||
| 750 | return 0; | ||||
| 751 | } | ||||
| 752 | |||||
| 753 | |||||
| 754 | static const struct { | ||||
| 755 | int aom_enum; | ||||
| 756 | unsigned offset; | ||||
| 757 | } option_map[] = { | ||||
| 758 | { AOME_SET_ENABLEAUTOALTREF, OFFSET(auto_alt_ref)__builtin_offsetof(AOMContext, auto_alt_ref) }, | ||||
| 759 | { AOME_SET_ARNR_MAXFRAMES, OFFSET(arnr_max_frames)__builtin_offsetof(AOMContext, arnr_max_frames) }, | ||||
| 760 | { AOME_SET_ARNR_STRENGTH, OFFSET(arnr_strength)__builtin_offsetof(AOMContext, arnr_strength) }, | ||||
| 761 | { AV1E_SET_ENABLE_CDEF, OFFSET(enable_cdef)__builtin_offsetof(AOMContext, enable_cdef) }, | ||||
| 762 | { AV1E_SET_ENABLE_RESTORATION, OFFSET(enable_restoration)__builtin_offsetof(AOMContext, enable_restoration) }, | ||||
| 763 | { AV1E_SET_ENABLE_RECT_PARTITIONS, OFFSET(enable_rect_partitions)__builtin_offsetof(AOMContext, enable_rect_partitions) }, | ||||
| 764 | { AV1E_SET_ENABLE_1TO4_PARTITIONS, OFFSET(enable_1to4_partitions)__builtin_offsetof(AOMContext, enable_1to4_partitions) }, | ||||
| 765 | { AV1E_SET_ENABLE_AB_PARTITIONS, OFFSET(enable_ab_partitions)__builtin_offsetof(AOMContext, enable_ab_partitions) }, | ||||
| 766 | { AV1E_SET_ENABLE_ANGLE_DELTA, OFFSET(enable_angle_delta)__builtin_offsetof(AOMContext, enable_angle_delta) }, | ||||
| 767 | { AV1E_SET_ENABLE_CFL_INTRA, OFFSET(enable_cfl_intra)__builtin_offsetof(AOMContext, enable_cfl_intra) }, | ||||
| 768 | { AV1E_SET_ENABLE_FILTER_INTRA, OFFSET(enable_filter_intra)__builtin_offsetof(AOMContext, enable_filter_intra) }, | ||||
| 769 | { AV1E_SET_ENABLE_INTRA_EDGE_FILTER, OFFSET(enable_intra_edge_filter)__builtin_offsetof(AOMContext, enable_intra_edge_filter) }, | ||||
| 770 | { AV1E_SET_ENABLE_PAETH_INTRA, OFFSET(enable_paeth_intra)__builtin_offsetof(AOMContext, enable_paeth_intra) }, | ||||
| 771 | { AV1E_SET_ENABLE_SMOOTH_INTRA, OFFSET(enable_smooth_intra)__builtin_offsetof(AOMContext, enable_smooth_intra) }, | ||||
| 772 | { AV1E_SET_ENABLE_PALETTE, OFFSET(enable_palette)__builtin_offsetof(AOMContext, enable_palette) }, | ||||
| 773 | { AV1E_SET_ENABLE_TX64, OFFSET(enable_tx64)__builtin_offsetof(AOMContext, enable_tx64) }, | ||||
| 774 | { AV1E_SET_ENABLE_FLIP_IDTX, OFFSET(enable_flip_idtx)__builtin_offsetof(AOMContext, enable_flip_idtx) }, | ||||
| 775 | { AV1E_SET_INTRA_DCT_ONLY, OFFSET(use_intra_dct_only)__builtin_offsetof(AOMContext, use_intra_dct_only) }, | ||||
| 776 | { AV1E_SET_INTER_DCT_ONLY, OFFSET(use_inter_dct_only)__builtin_offsetof(AOMContext, use_inter_dct_only) }, | ||||
| 777 | { AV1E_SET_INTRA_DEFAULT_TX_ONLY, OFFSET(use_intra_default_tx_only)__builtin_offsetof(AOMContext, use_intra_default_tx_only) }, | ||||
| 778 | { AV1E_SET_REDUCED_TX_TYPE_SET, OFFSET(reduced_tx_type_set)__builtin_offsetof(AOMContext, reduced_tx_type_set) }, | ||||
| 779 | { AV1E_SET_ENABLE_REF_FRAME_MVS, OFFSET(enable_ref_frame_mvs)__builtin_offsetof(AOMContext, enable_ref_frame_mvs) }, | ||||
| 780 | { AV1E_SET_REDUCED_REFERENCE_SET, OFFSET(enable_reduced_reference_set)__builtin_offsetof(AOMContext, enable_reduced_reference_set) }, | ||||
| 781 | { AV1E_SET_ENABLE_DIFF_WTD_COMP, OFFSET(enable_diff_wtd_comp)__builtin_offsetof(AOMContext, enable_diff_wtd_comp) }, | ||||
| 782 | { AV1E_SET_ENABLE_DIST_WTD_COMP, OFFSET(enable_dist_wtd_comp)__builtin_offsetof(AOMContext, enable_dist_wtd_comp) }, | ||||
| 783 | { AV1E_SET_ENABLE_DUAL_FILTER, OFFSET(enable_dual_filter)__builtin_offsetof(AOMContext, enable_dual_filter) }, | ||||
| 784 | { AV1E_SET_ENABLE_INTERINTER_WEDGE, OFFSET(enable_interinter_wedge)__builtin_offsetof(AOMContext, enable_interinter_wedge) }, | ||||
| 785 | { AV1E_SET_ENABLE_MASKED_COMP, OFFSET(enable_masked_comp)__builtin_offsetof(AOMContext, enable_masked_comp) }, | ||||
| 786 | { AV1E_SET_ENABLE_INTERINTRA_COMP, OFFSET(enable_interintra_comp)__builtin_offsetof(AOMContext, enable_interintra_comp) }, | ||||
| 787 | { AV1E_SET_ENABLE_INTERINTRA_WEDGE, OFFSET(enable_interintra_wedge)__builtin_offsetof(AOMContext, enable_interintra_wedge) }, | ||||
| 788 | { AV1E_SET_ENABLE_OBMC, OFFSET(enable_obmc)__builtin_offsetof(AOMContext, enable_obmc) }, | ||||
| 789 | { AV1E_SET_ENABLE_ONESIDED_COMP, OFFSET(enable_onesided_comp)__builtin_offsetof(AOMContext, enable_onesided_comp) }, | ||||
| 790 | { AV1E_SET_ENABLE_SMOOTH_INTERINTRA, OFFSET(enable_smooth_interintra)__builtin_offsetof(AOMContext, enable_smooth_interintra) }, | ||||
| 791 | }; | ||||
| 792 | |||||
| 793 | static av_cold__attribute__((cold)) int aom_init(AVCodecContext *avctx, | ||||
| 794 | const struct aom_codec_iface *iface) | ||||
| 795 | { | ||||
| 796 | AOMContext *ctx = avctx->priv_data; | ||||
| 797 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt); | ||||
| 798 | struct aom_codec_enc_cfg enccfg = { 0 }; | ||||
| 799 | aom_codec_flags_t flags = | ||||
| 800 | (avctx->flags & AV_CODEC_FLAG_PSNR(1 << 15)) ? AOM_CODEC_USE_PSNR0x10000 : 0; | ||||
| |||||
| 801 | int res; | ||||
| 802 | aom_img_fmt_t img_fmt; | ||||
| 803 | aom_codec_caps_t codec_caps = aom_codec_get_caps(iface); | ||||
| 804 | |||||
| 805 | av_log(avctx, AV_LOG_INFO32, "%s\n", aom_codec_version_str()); | ||||
| 806 | av_log(avctx, AV_LOG_VERBOSE40, "%s\n", aom_codec_build_config()); | ||||
| 807 | |||||
| 808 | if ((res = aom_codec_enc_config_default(iface, &enccfg, ctx->usage)) != AOM_CODEC_OK) { | ||||
| 809 | av_log(avctx, AV_LOG_ERROR16, "Failed to get config: %s\n", | ||||
| 810 | aom_codec_err_to_string(res)); | ||||
| 811 | return AVERROR(EINVAL)(-(22)); | ||||
| 812 | } | ||||
| 813 | |||||
| 814 | if (set_pix_fmt(avctx, codec_caps, &enccfg, &flags, &img_fmt)) | ||||
| 815 | return AVERROR(EINVAL)(-(22)); | ||||
| 816 | |||||
| 817 | if(!avctx->bit_rate) | ||||
| 818 | if(avctx->rc_max_rate || avctx->rc_buffer_size || avctx->rc_initial_buffer_occupancy) { | ||||
| 819 | av_log( avctx, AV_LOG_ERROR16, "Rate control parameters set without a bitrate\n"); | ||||
| 820 | return AVERROR(EINVAL)(-(22)); | ||||
| 821 | } | ||||
| 822 | |||||
| 823 | dump_enc_cfg(avctx, &enccfg, AV_LOG_DEBUG48); | ||||
| 824 | |||||
| 825 | enccfg.g_w = avctx->width; | ||||
| 826 | enccfg.g_h = avctx->height; | ||||
| 827 | enccfg.g_timebase.num = avctx->time_base.num; | ||||
| 828 | enccfg.g_timebase.den = avctx->time_base.den; | ||||
| 829 | enccfg.g_threads = | ||||
| 830 | FFMIN(avctx->thread_count ? avctx->thread_count : av_cpu_count(), 64)((avctx->thread_count ? avctx->thread_count : av_cpu_count ()) > (64) ? (64) : (avctx->thread_count ? avctx->thread_count : av_cpu_count())); | ||||
| 831 | |||||
| 832 | if (ctx->lag_in_frames >= 0) | ||||
| 833 | enccfg.g_lag_in_frames = ctx->lag_in_frames; | ||||
| 834 | |||||
| 835 | if (avctx->flags & AV_CODEC_FLAG_PASS1(1 << 9)) | ||||
| 836 | enccfg.g_pass = AOM_RC_FIRST_PASS; | ||||
| 837 | else if (avctx->flags & AV_CODEC_FLAG_PASS2(1 << 10)) | ||||
| 838 | enccfg.g_pass = AOM_RC_LAST_PASS; | ||||
| 839 | else | ||||
| 840 | enccfg.g_pass = AOM_RC_ONE_PASS; | ||||
| 841 | |||||
| 842 | if (avctx->rc_min_rate == avctx->rc_max_rate && | ||||
| 843 | avctx->rc_min_rate == avctx->bit_rate && avctx->bit_rate) { | ||||
| 844 | enccfg.rc_end_usage = AOM_CBR; | ||||
| 845 | } else if (ctx->crf >= 0) { | ||||
| 846 | enccfg.rc_end_usage = AOM_CQ; | ||||
| 847 | if (!avctx->bit_rate) | ||||
| 848 | enccfg.rc_end_usage = AOM_Q; | ||||
| 849 | } | ||||
| 850 | |||||
| 851 | if (avctx->bit_rate) { | ||||
| 852 | enccfg.rc_target_bitrate = av_rescale_rnd(avctx->bit_rate, 1, 1000, | ||||
| 853 | AV_ROUND_NEAR_INF); | ||||
| 854 | } else if (enccfg.rc_end_usage != AOM_Q) { | ||||
| 855 | enccfg.rc_end_usage = AOM_Q; | ||||
| 856 | ctx->crf = 32; | ||||
| 857 | av_log(avctx, AV_LOG_WARNING24, | ||||
| 858 | "Neither bitrate nor constrained quality specified, using default CRF of %d\n", | ||||
| 859 | ctx->crf); | ||||
| 860 | } | ||||
| 861 | |||||
| 862 | if (avctx->qmin >= 0) | ||||
| 863 | enccfg.rc_min_quantizer = avctx->qmin; | ||||
| 864 | if (avctx->qmax >= 0) { | ||||
| 865 | enccfg.rc_max_quantizer = avctx->qmax; | ||||
| 866 | } else if (!ctx->crf
| ||||
| 867 | enccfg.rc_max_quantizer = 0; | ||||
| 868 | } | ||||
| 869 | |||||
| 870 | if (enccfg.rc_end_usage
| ||||
| 871 | if (ctx->crf < enccfg.rc_min_quantizer || ctx->crf > enccfg.rc_max_quantizer) { | ||||
| 872 | av_log(avctx, AV_LOG_ERROR16, | ||||
| 873 | "CQ level %d must be between minimum and maximum quantizer value (%d-%d)\n", | ||||
| 874 | ctx->crf, enccfg.rc_min_quantizer, enccfg.rc_max_quantizer); | ||||
| 875 | return AVERROR(EINVAL)(-(22)); | ||||
| 876 | } | ||||
| 877 | } | ||||
| 878 | |||||
| 879 | enccfg.rc_dropframe_thresh = ctx->drop_threshold; | ||||
| 880 | |||||
| 881 | // 0-100 (0 => CBR, 100 => VBR) | ||||
| 882 | enccfg.rc_2pass_vbr_bias_pct = round(avctx->qcompress * 100); | ||||
| 883 | if (ctx->minsection_pct >= 0) | ||||
| 884 | enccfg.rc_2pass_vbr_minsection_pct = ctx->minsection_pct; | ||||
| 885 | else if (avctx->bit_rate
| ||||
| 886 | enccfg.rc_2pass_vbr_minsection_pct = | ||||
| 887 | avctx->rc_min_rate * 100LL / avctx->bit_rate; | ||||
| 888 | if (ctx->maxsection_pct >= 0) | ||||
| 889 | enccfg.rc_2pass_vbr_maxsection_pct = ctx->maxsection_pct; | ||||
| 890 | else if (avctx->rc_max_rate) | ||||
| 891 | enccfg.rc_2pass_vbr_maxsection_pct = | ||||
| 892 | avctx->rc_max_rate * 100LL / avctx->bit_rate; | ||||
| 893 | |||||
| 894 | if (avctx->rc_buffer_size) | ||||
| 895 | enccfg.rc_buf_sz = | ||||
| 896 | avctx->rc_buffer_size * 1000LL / avctx->bit_rate; | ||||
| |||||
| 897 | if (avctx->rc_initial_buffer_occupancy) | ||||
| 898 | enccfg.rc_buf_initial_sz = | ||||
| 899 | avctx->rc_initial_buffer_occupancy * 1000LL / avctx->bit_rate; | ||||
| 900 | enccfg.rc_buf_optimal_sz = enccfg.rc_buf_sz * 5 / 6; | ||||
| 901 | |||||
| 902 | if (ctx->rc_undershoot_pct >= 0) | ||||
| 903 | enccfg.rc_undershoot_pct = ctx->rc_undershoot_pct; | ||||
| 904 | if (ctx->rc_overshoot_pct >= 0) | ||||
| 905 | enccfg.rc_overshoot_pct = ctx->rc_overshoot_pct; | ||||
| 906 | |||||
| 907 | // _enc_init() will balk if kf_min_dist differs from max w/AOM_KF_AUTO | ||||
| 908 | if (avctx->keyint_min >= 0 && avctx->keyint_min == avctx->gop_size) | ||||
| 909 | enccfg.kf_min_dist = avctx->keyint_min; | ||||
| 910 | if (avctx->gop_size >= 0) | ||||
| 911 | enccfg.kf_max_dist = avctx->gop_size; | ||||
| 912 | |||||
| 913 | if (enccfg.g_pass == AOM_RC_FIRST_PASS) | ||||
| 914 | enccfg.g_lag_in_frames = 0; | ||||
| 915 | else if (enccfg.g_pass == AOM_RC_LAST_PASS) { | ||||
| 916 | int decode_size, ret; | ||||
| 917 | |||||
| 918 | if (!avctx->stats_in) { | ||||
| 919 | av_log(avctx, AV_LOG_ERROR16, "No stats file for second pass\n"); | ||||
| 920 | return AVERROR_INVALIDDATA(-(int)(('I') | (('N') << 8) | (('D') << 16) | (( unsigned)('A') << 24))); | ||||
| 921 | } | ||||
| 922 | |||||
| 923 | ctx->twopass_stats.sz = strlen(avctx->stats_in) * 3 / 4; | ||||
| 924 | ret = av_reallocp(&ctx->twopass_stats.buf, ctx->twopass_stats.sz); | ||||
| 925 | if (ret < 0) { | ||||
| 926 | av_log(avctx, AV_LOG_ERROR16, | ||||
| 927 | "Stat buffer alloc (%zu bytes) failed\n", | ||||
| 928 | ctx->twopass_stats.sz); | ||||
| 929 | ctx->twopass_stats.sz = 0; | ||||
| 930 | return ret; | ||||
| 931 | } | ||||
| 932 | decode_size = av_base64_decode(ctx->twopass_stats.buf, avctx->stats_in, | ||||
| 933 | ctx->twopass_stats.sz); | ||||
| 934 | if (decode_size < 0) { | ||||
| 935 | av_log(avctx, AV_LOG_ERROR16, "Stat buffer decode failed\n"); | ||||
| 936 | return AVERROR_INVALIDDATA(-(int)(('I') | (('N') << 8) | (('D') << 16) | (( unsigned)('A') << 24))); | ||||
| 937 | } | ||||
| 938 | |||||
| 939 | ctx->twopass_stats.sz = decode_size; | ||||
| 940 | enccfg.rc_twopass_stats_in = ctx->twopass_stats; | ||||
| 941 | } | ||||
| 942 | |||||
| 943 | /* 0-3: For non-zero values the encoder increasingly optimizes for reduced | ||||
| 944 | * complexity playback on low powered devices at the expense of encode | ||||
| 945 | * quality. */ | ||||
| 946 | if (avctx->profile != AV_PROFILE_UNKNOWN-99) | ||||
| 947 | enccfg.g_profile = avctx->profile; | ||||
| 948 | |||||
| 949 | enccfg.g_error_resilient = ctx->error_resilient; | ||||
| 950 | |||||
| 951 | res = choose_tiling(avctx, &enccfg); | ||||
| 952 | if (res < 0) | ||||
| 953 | return res; | ||||
| 954 | |||||
| 955 | if (ctx->still_picture) { | ||||
| 956 | // Set the maximum number of frames to 1. This will let libaom set | ||||
| 957 | // still_picture and reduced_still_picture_header to 1 in the Sequence | ||||
| 958 | // Header as required by AVIF still images. | ||||
| 959 | enccfg.g_limit = 1; | ||||
| 960 | // Reduce memory usage for still images. | ||||
| 961 | enccfg.g_lag_in_frames = 0; | ||||
| 962 | // All frames will be key frames. | ||||
| 963 | enccfg.kf_max_dist = 0; | ||||
| 964 | enccfg.kf_mode = AOM_KF_DISABLED; | ||||
| 965 | } | ||||
| 966 | |||||
| 967 | /* Construct Encoder Context */ | ||||
| 968 | res = aom_codec_enc_init(&ctx->encoder, iface, &enccfg, flags)aom_codec_enc_init_ver(&ctx->encoder, iface, &enccfg , flags, (10 + (7 + (9)) + 3)); | ||||
| 969 | if (res != AOM_CODEC_OK) { | ||||
| 970 | dump_enc_cfg(avctx, &enccfg, AV_LOG_WARNING24); | ||||
| 971 | log_encoder_error(avctx, "Failed to initialize encoder"); | ||||
| 972 | return AVERROR(EINVAL)(-(22)); | ||||
| 973 | } | ||||
| 974 | dump_enc_cfg(avctx, &enccfg, AV_LOG_DEBUG48); | ||||
| 975 | |||||
| 976 | // codec control failures are currently treated only as warnings | ||||
| 977 | av_log(avctx, AV_LOG_DEBUG48, "aom_codec_control\n"); | ||||
| 978 | codecctl_int(avctx, AOME_SET_CPUUSED, ctx->cpu_used); | ||||
| 979 | |||||
| 980 | for (size_t i = 0; i < FF_ARRAY_ELEMS(option_map)(sizeof(option_map) / sizeof((option_map)[0])); ++i) { | ||||
| 981 | int val = *(int*)((char*)ctx + option_map[i].offset); | ||||
| 982 | if (val >= 0) | ||||
| 983 | codecctl_int(avctx, option_map[i].aom_enum, val); | ||||
| 984 | } | ||||
| 985 | codecctl_int(avctx, AOME_SET_STATIC_THRESHOLD, ctx->static_thresh); | ||||
| 986 | if (ctx->crf >= 0) | ||||
| 987 | codecctl_int(avctx, AOME_SET_CQ_LEVEL, ctx->crf); | ||||
| 988 | if (ctx->tune >= 0) | ||||
| 989 | codecctl_int(avctx, AOME_SET_TUNING, ctx->tune); | ||||
| 990 | |||||
| 991 | if (desc->flags & AV_PIX_FMT_FLAG_RGB(1 << 5)) { | ||||
| 992 | codecctl_int(avctx, AV1E_SET_COLOR_PRIMARIES, AVCOL_PRI_BT709); | ||||
| 993 | codecctl_int(avctx, AV1E_SET_MATRIX_COEFFICIENTS, AVCOL_SPC_RGB); | ||||
| 994 | codecctl_int(avctx, AV1E_SET_TRANSFER_CHARACTERISTICS, AVCOL_TRC_IEC61966_2_1); | ||||
| 995 | } else { | ||||
| 996 | codecctl_int(avctx, AV1E_SET_COLOR_PRIMARIES, avctx->color_primaries); | ||||
| 997 | codecctl_int(avctx, AV1E_SET_MATRIX_COEFFICIENTS, avctx->colorspace); | ||||
| 998 | codecctl_int(avctx, AV1E_SET_TRANSFER_CHARACTERISTICS, avctx->color_trc); | ||||
| 999 | } | ||||
| 1000 | if (ctx->aq_mode >= 0) | ||||
| 1001 | codecctl_int(avctx, AV1E_SET_AQ_MODE, ctx->aq_mode); | ||||
| 1002 | if (ctx->frame_parallel >= 0) | ||||
| 1003 | codecctl_int(avctx, AV1E_SET_FRAME_PARALLEL_DECODING, ctx->frame_parallel); | ||||
| 1004 | set_color_range(avctx); | ||||
| 1005 | |||||
| 1006 | codecctl_int(avctx, AV1E_SET_SUPERBLOCK_SIZE, ctx->superblock_size); | ||||
| 1007 | if (ctx->uniform_tiles) { | ||||
| 1008 | codecctl_int(avctx, AV1E_SET_TILE_COLUMNS, ctx->tile_cols_log2); | ||||
| 1009 | codecctl_int(avctx, AV1E_SET_TILE_ROWS, ctx->tile_rows_log2); | ||||
| 1010 | } | ||||
| 1011 | |||||
| 1012 | if (ctx->denoise_noise_level >= 0) | ||||
| 1013 | codecctl_int(avctx, AV1E_SET_DENOISE_NOISE_LEVEL, ctx->denoise_noise_level); | ||||
| 1014 | if (ctx->denoise_block_size >= 0) | ||||
| 1015 | codecctl_int(avctx, AV1E_SET_DENOISE_BLOCK_SIZE, ctx->denoise_block_size); | ||||
| 1016 | if (ctx->enable_global_motion >= 0) | ||||
| 1017 | codecctl_int(avctx, AV1E_SET_ENABLE_GLOBAL_MOTION, ctx->enable_global_motion); | ||||
| 1018 | if (avctx->refs >= 3) { | ||||
| 1019 | codecctl_int(avctx, AV1E_SET_MAX_REFERENCE_FRAMES, avctx->refs); | ||||
| 1020 | } | ||||
| 1021 | if (ctx->row_mt >= 0) | ||||
| 1022 | codecctl_int(avctx, AV1E_SET_ROW_MT, ctx->row_mt); | ||||
| 1023 | if (ctx->enable_intrabc >= 0) | ||||
| 1024 | codecctl_int(avctx, AV1E_SET_ENABLE_INTRABC, ctx->enable_intrabc); | ||||
| 1025 | |||||
| 1026 | if (enccfg.rc_end_usage == AOM_CBR) { | ||||
| 1027 | aom_svc_params_t svc_params = {}; | ||||
| 1028 | svc_params.framerate_factor[0] = 1; | ||||
| 1029 | svc_params.number_spatial_layers = 1; | ||||
| 1030 | svc_params.number_temporal_layers = 1; | ||||
| 1031 | |||||
| 1032 | AVDictionaryEntry *en = NULL((void*)0); | ||||
| 1033 | while ((en = av_dict_get(ctx->svc_parameters, "", en, AV_DICT_IGNORE_SUFFIX2))) { | ||||
| 1034 | if (!strlen(en->value)) | ||||
| 1035 | return AVERROR(EINVAL)(-(22)); | ||||
| 1036 | |||||
| 1037 | if (!strcmp(en->key, "number_spatial_layers")) | ||||
| 1038 | svc_params.number_spatial_layers = strtoul(en->value, NULL((void*)0), 10); | ||||
| 1039 | else if (!strcmp(en->key, "number_temporal_layers")) | ||||
| 1040 | svc_params.number_temporal_layers = strtoul(en->value, NULL((void*)0), 10); | ||||
| 1041 | else if (!strcmp(en->key, "max_quantizers")) | ||||
| 1042 | aom_svc_parse_int_array(svc_params.max_quantizers, en->value, AOM_MAX_LAYERS32); | ||||
| 1043 | else if (!strcmp(en->key, "min_quantizers")) | ||||
| 1044 | aom_svc_parse_int_array(svc_params.min_quantizers, en->value, AOM_MAX_LAYERS32); | ||||
| 1045 | else if (!strcmp(en->key, "scaling_factor_num")) | ||||
| 1046 | aom_svc_parse_int_array(svc_params.scaling_factor_num, en->value, AOM_MAX_SS_LAYERS4); | ||||
| 1047 | else if (!strcmp(en->key, "scaling_factor_den")) | ||||
| 1048 | aom_svc_parse_int_array(svc_params.scaling_factor_den, en->value, AOM_MAX_SS_LAYERS4); | ||||
| 1049 | else if (!strcmp(en->key, "layer_target_bitrate")) | ||||
| 1050 | aom_svc_parse_int_array(svc_params.layer_target_bitrate, en->value, AOM_MAX_LAYERS32); | ||||
| 1051 | else if (!strcmp(en->key, "framerate_factor")) | ||||
| 1052 | aom_svc_parse_int_array(svc_params.framerate_factor, en->value, AOM_MAX_TS_LAYERS8); | ||||
| 1053 | } | ||||
| 1054 | |||||
| 1055 | res = codecctl_svcp(avctx, AV1E_SET_SVC_PARAMS, &svc_params); | ||||
| 1056 | if (res < 0) | ||||
| 1057 | return res; | ||||
| 1058 | } | ||||
| 1059 | |||||
| 1060 | |||||
| 1061 | #if AOM_ENCODER_ABI_VERSION(10 + (7 + (9)) + 3) >= 23 | ||||
| 1062 | { | ||||
| 1063 | const AVDictionaryEntry *en = NULL((void*)0); | ||||
| 1064 | |||||
| 1065 | while ((en = av_dict_iterate(ctx->aom_params, en))) { | ||||
| 1066 | int ret = aom_codec_set_option(&ctx->encoder, en->key, en->value); | ||||
| 1067 | if (ret != AOM_CODEC_OK) { | ||||
| 1068 | log_encoder_error(avctx, en->key); | ||||
| 1069 | return AVERROR_EXTERNAL(-(int)(('E') | (('X') << 8) | (('T') << 16) | (( unsigned)(' ') << 24))); | ||||
| 1070 | } | ||||
| 1071 | } | ||||
| 1072 | } | ||||
| 1073 | #endif | ||||
| 1074 | |||||
| 1075 | // provide dummy value to initialize wrapper, values will be updated each _encode() | ||||
| 1076 | aom_img_wrap(&ctx->rawimg, img_fmt, avctx->width, avctx->height, 1, | ||||
| 1077 | (unsigned char*)1); | ||||
| 1078 | |||||
| 1079 | if (codec_caps & AOM_CODEC_CAP_HIGHBITDEPTH0x40000) | ||||
| 1080 | ctx->rawimg.bit_depth = enccfg.g_bit_depth; | ||||
| 1081 | |||||
| 1082 | ctx->dovi.logctx = avctx; | ||||
| 1083 | if ((res = ff_dovi_configure(&ctx->dovi, avctx)) < 0) | ||||
| 1084 | return res; | ||||
| 1085 | |||||
| 1086 | if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER(1 << 22)) { | ||||
| 1087 | const AVBitStreamFilter *filter = av_bsf_get_by_name("extract_extradata"); | ||||
| 1088 | int ret; | ||||
| 1089 | |||||
| 1090 | if (!filter) { | ||||
| 1091 | av_log(avctx, AV_LOG_ERROR16, "extract_extradata bitstream filter " | ||||
| 1092 | "not found. This is a bug, please report it.\n"); | ||||
| 1093 | return AVERROR_BUG(-(int)(('B') | (('U') << 8) | (('G') << 16) | (( unsigned)('!') << 24))); | ||||
| 1094 | } | ||||
| 1095 | ret = av_bsf_alloc(filter, &ctx->bsf); | ||||
| 1096 | if (ret < 0) | ||||
| 1097 | return ret; | ||||
| 1098 | |||||
| 1099 | ret = avcodec_parameters_from_context(ctx->bsf->par_in, avctx); | ||||
| 1100 | if (ret < 0) | ||||
| 1101 | return ret; | ||||
| 1102 | |||||
| 1103 | ret = av_bsf_init(ctx->bsf); | ||||
| 1104 | if (ret < 0) | ||||
| 1105 | return ret; | ||||
| 1106 | } | ||||
| 1107 | |||||
| 1108 | AVCPBProperties *cpb_props = ff_encode_add_cpb_side_data(avctx); | ||||
| 1109 | if (!cpb_props) | ||||
| 1110 | return AVERROR(ENOMEM)(-(12)); | ||||
| 1111 | |||||
| 1112 | if (enccfg.rc_end_usage == AOM_CBR || | ||||
| 1113 | enccfg.g_pass != AOM_RC_ONE_PASS) { | ||||
| 1114 | cpb_props->max_bitrate = avctx->rc_max_rate; | ||||
| 1115 | cpb_props->min_bitrate = avctx->rc_min_rate; | ||||
| 1116 | cpb_props->avg_bitrate = avctx->bit_rate; | ||||
| 1117 | } | ||||
| 1118 | cpb_props->buffer_size = avctx->rc_buffer_size; | ||||
| 1119 | |||||
| 1120 | return 0; | ||||
| 1121 | } | ||||
| 1122 | |||||
| 1123 | static inline void cx_pktcpy(AOMContext *ctx, | ||||
| 1124 | struct FrameListData *dst, | ||||
| 1125 | const struct aom_codec_cx_pkt *src) | ||||
| 1126 | { | ||||
| 1127 | dst->pts = src->data.frame.pts; | ||||
| 1128 | dst->duration = src->data.frame.duration; | ||||
| 1129 | dst->flags = src->data.frame.flags; | ||||
| 1130 | dst->sz = src->data.frame.sz; | ||||
| 1131 | dst->buf = src->data.frame.buf; | ||||
| 1132 | dst->frame_number = ++ctx->frame_number; | ||||
| 1133 | dst->have_sse = ctx->have_sse; | ||||
| 1134 | if (ctx->have_sse) { | ||||
| 1135 | /* associate last-seen SSE to the frame. */ | ||||
| 1136 | /* Transfers ownership from ctx to dst. */ | ||||
| 1137 | memcpy(dst->sse, ctx->sse, sizeof(dst->sse)); | ||||
| 1138 | ctx->have_sse = 0; | ||||
| 1139 | } | ||||
| 1140 | } | ||||
| 1141 | |||||
| 1142 | /** | ||||
| 1143 | * Store coded frame information in format suitable for return from encode2(). | ||||
| 1144 | * | ||||
| 1145 | * Write information from @a cx_frame to @a pkt | ||||
| 1146 | * @return packet data size on success | ||||
| 1147 | * @return a negative AVERROR on error | ||||
| 1148 | */ | ||||
| 1149 | static int storeframe(AVCodecContext *avctx, struct FrameListData *cx_frame, | ||||
| 1150 | AVPacket *pkt) | ||||
| 1151 | { | ||||
| 1152 | AOMContext *ctx = avctx->priv_data; | ||||
| 1153 | enum AVPictureType pict_type; | ||||
| 1154 | int ret = ff_get_encode_buffer(avctx, pkt, cx_frame->sz, 0); | ||||
| 1155 | if (ret < 0) { | ||||
| 1156 | av_log(avctx, AV_LOG_ERROR16, | ||||
| 1157 | "Error getting output packet of size %zu.\n", cx_frame->sz); | ||||
| 1158 | return ret; | ||||
| 1159 | } | ||||
| 1160 | memcpy(pkt->data, cx_frame->buf, pkt->size); | ||||
| 1161 | pkt->pts = pkt->dts = cx_frame->pts; | ||||
| 1162 | pkt->duration = cx_frame->duration; | ||||
| 1163 | |||||
| 1164 | if (!!(cx_frame->flags & AOM_FRAME_IS_KEY0x1u)) { | ||||
| 1165 | pkt->flags |= AV_PKT_FLAG_KEY0x0001; | ||||
| 1166 | pict_type = AV_PICTURE_TYPE_I; | ||||
| 1167 | } else if (cx_frame->flags & AOM_FRAME_IS_INTRAONLY0x10u) { | ||||
| 1168 | pict_type = AV_PICTURE_TYPE_I; | ||||
| 1169 | } else { | ||||
| 1170 | pict_type = AV_PICTURE_TYPE_P; | ||||
| 1171 | } | ||||
| 1172 | |||||
| 1173 | ff_encode_add_stats_side_data(pkt, 0, cx_frame->sse + 1, | ||||
| 1174 | cx_frame->have_sse ? 3 : 0, pict_type); | ||||
| 1175 | |||||
| 1176 | if (cx_frame->have_sse) { | ||||
| 1177 | int i; | ||||
| 1178 | for (i = 0; i < 3; ++i) { | ||||
| 1179 | avctx->error[i] += cx_frame->sse[i + 1]; | ||||
| 1180 | } | ||||
| 1181 | cx_frame->have_sse = 0; | ||||
| 1182 | } | ||||
| 1183 | |||||
| 1184 | if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER(1 << 22)) { | ||||
| 1185 | ret = av_bsf_send_packet(ctx->bsf, pkt); | ||||
| 1186 | if (ret < 0) { | ||||
| 1187 | av_log(avctx, AV_LOG_ERROR16, "extract_extradata filter " | ||||
| 1188 | "failed to send input packet\n"); | ||||
| 1189 | return ret; | ||||
| 1190 | } | ||||
| 1191 | ret = av_bsf_receive_packet(ctx->bsf, pkt); | ||||
| 1192 | |||||
| 1193 | if (ret < 0) { | ||||
| 1194 | av_log(avctx, AV_LOG_ERROR16, "extract_extradata filter " | ||||
| 1195 | "failed to receive output packet\n"); | ||||
| 1196 | return ret; | ||||
| 1197 | } | ||||
| 1198 | } | ||||
| 1199 | return pkt->size; | ||||
| 1200 | } | ||||
| 1201 | |||||
| 1202 | /** | ||||
| 1203 | * Queue multiple output frames from the encoder, returning the front-most. | ||||
| 1204 | * In cases where aom_codec_get_cx_data() returns more than 1 frame append | ||||
| 1205 | * the frame queue. Return the head frame if available. | ||||
| 1206 | * @return Stored frame size | ||||
| 1207 | * @return AVERROR(EINVAL) on output size error | ||||
| 1208 | * @return AVERROR(ENOMEM) on coded frame queue data allocation error | ||||
| 1209 | */ | ||||
| 1210 | static int queue_frames(AVCodecContext *avctx, AVPacket *pkt_out) | ||||
| 1211 | { | ||||
| 1212 | AOMContext *ctx = avctx->priv_data; | ||||
| 1213 | const struct aom_codec_cx_pkt *pkt; | ||||
| 1214 | const void *iter = NULL((void*)0); | ||||
| 1215 | int size = 0; | ||||
| 1216 | |||||
| 1217 | if (ctx->coded_frame_list) { | ||||
| 1218 | struct FrameListData *cx_frame = ctx->coded_frame_list; | ||||
| 1219 | /* return the leading frame if we've already begun queueing */ | ||||
| 1220 | size = storeframe(avctx, cx_frame, pkt_out); | ||||
| 1221 | if (size < 0) | ||||
| 1222 | return size; | ||||
| 1223 | ctx->coded_frame_list = cx_frame->next; | ||||
| 1224 | free_coded_frame(cx_frame); | ||||
| 1225 | } | ||||
| 1226 | |||||
| 1227 | /* consume all available output from the encoder before returning. buffers | ||||
| 1228 | * are only good through the next aom_codec call */ | ||||
| 1229 | while ((pkt = aom_codec_get_cx_data(&ctx->encoder, &iter))) { | ||||
| 1230 | switch (pkt->kind) { | ||||
| 1231 | case AOM_CODEC_CX_FRAME_PKT: | ||||
| 1232 | if (!size) { | ||||
| 1233 | struct FrameListData cx_frame; | ||||
| 1234 | |||||
| 1235 | /* avoid storing the frame when the list is empty and we haven't yet | ||||
| 1236 | * provided a frame for output */ | ||||
| 1237 | av_assert0(!ctx->coded_frame_list)do { if (!(!ctx->coded_frame_list)) { av_log(((void*)0), 0 , "Assertion %s failed at %s:%d\n", "!ctx->coded_frame_list" , "/root/firefox-clang/media/ffvpx/libavcodec/libaomenc.c", 1237 ); abort(); } } while (0); | ||||
| 1238 | cx_pktcpy(ctx, &cx_frame, pkt); | ||||
| 1239 | size = storeframe(avctx, &cx_frame, pkt_out); | ||||
| 1240 | if (size < 0) | ||||
| 1241 | return size; | ||||
| 1242 | } else { | ||||
| 1243 | struct FrameListData *cx_frame = | ||||
| 1244 | av_malloc(sizeof(struct FrameListData)); | ||||
| 1245 | |||||
| 1246 | if (!cx_frame) { | ||||
| 1247 | av_log(avctx, AV_LOG_ERROR16, | ||||
| 1248 | "Frame queue element alloc failed\n"); | ||||
| 1249 | return AVERROR(ENOMEM)(-(12)); | ||||
| 1250 | } | ||||
| 1251 | cx_pktcpy(ctx, cx_frame, pkt); | ||||
| 1252 | cx_frame->buf = av_malloc(cx_frame->sz); | ||||
| 1253 | |||||
| 1254 | if (!cx_frame->buf) { | ||||
| 1255 | av_log(avctx, AV_LOG_ERROR16, | ||||
| 1256 | "Data buffer alloc (%zu bytes) failed\n", | ||||
| 1257 | cx_frame->sz); | ||||
| 1258 | av_freep(&cx_frame); | ||||
| 1259 | return AVERROR(ENOMEM)(-(12)); | ||||
| 1260 | } | ||||
| 1261 | memcpy(cx_frame->buf, pkt->data.frame.buf, pkt->data.frame.sz); | ||||
| 1262 | coded_frame_add(&ctx->coded_frame_list, cx_frame); | ||||
| 1263 | } | ||||
| 1264 | break; | ||||
| 1265 | case AOM_CODEC_STATS_PKT: | ||||
| 1266 | { | ||||
| 1267 | struct aom_fixed_buf *stats = &ctx->twopass_stats; | ||||
| 1268 | uint8_t *tmp = av_fast_realloc(stats->buf, | ||||
| 1269 | &ctx->twopass_stats_size, | ||||
| 1270 | stats->sz + | ||||
| 1271 | pkt->data.twopass_stats.sz); | ||||
| 1272 | if (!tmp) { | ||||
| 1273 | av_freep(&stats->buf); | ||||
| 1274 | stats->sz = 0; | ||||
| 1275 | av_log(avctx, AV_LOG_ERROR16, "Stat buffer realloc failed\n"); | ||||
| 1276 | return AVERROR(ENOMEM)(-(12)); | ||||
| 1277 | } | ||||
| 1278 | stats->buf = tmp; | ||||
| 1279 | memcpy((uint8_t *)stats->buf + stats->sz, | ||||
| 1280 | pkt->data.twopass_stats.buf, pkt->data.twopass_stats.sz); | ||||
| 1281 | stats->sz += pkt->data.twopass_stats.sz; | ||||
| 1282 | break; | ||||
| 1283 | } | ||||
| 1284 | case AOM_CODEC_PSNR_PKT: | ||||
| 1285 | { | ||||
| 1286 | av_assert0(!ctx->have_sse)do { if (!(!ctx->have_sse)) { av_log(((void*)0), 0, "Assertion %s failed at %s:%d\n" , "!ctx->have_sse", "/root/firefox-clang/media/ffvpx/libavcodec/libaomenc.c" , 1286); abort(); } } while (0); | ||||
| 1287 | ctx->sse[0] = pkt->data.psnr.sse[0]; | ||||
| 1288 | ctx->sse[1] = pkt->data.psnr.sse[1]; | ||||
| 1289 | ctx->sse[2] = pkt->data.psnr.sse[2]; | ||||
| 1290 | ctx->sse[3] = pkt->data.psnr.sse[3]; | ||||
| 1291 | ctx->have_sse = 1; | ||||
| 1292 | break; | ||||
| 1293 | } | ||||
| 1294 | case AOM_CODEC_CUSTOM_PKT: | ||||
| 1295 | // ignore unsupported/unrecognized packet types | ||||
| 1296 | break; | ||||
| 1297 | } | ||||
| 1298 | } | ||||
| 1299 | |||||
| 1300 | return size; | ||||
| 1301 | } | ||||
| 1302 | |||||
| 1303 | static enum AVPixelFormat aomfmt_to_pixfmt(struct aom_image *img) | ||||
| 1304 | { | ||||
| 1305 | switch (img->fmt) { | ||||
| 1306 | case AOM_IMG_FMT_I420: | ||||
| 1307 | case AOM_IMG_FMT_I42016: | ||||
| 1308 | if (img->bit_depth == 8) | ||||
| 1309 | return img->monochrome ? AV_PIX_FMT_GRAY8 : AV_PIX_FMT_YUV420P; | ||||
| 1310 | else if (img->bit_depth == 10) | ||||
| 1311 | return img->monochrome ? AV_PIX_FMT_GRAY10AV_PIX_FMT_GRAY10LE : AV_PIX_FMT_YUV420P10AV_PIX_FMT_YUV420P10LE; | ||||
| 1312 | else | ||||
| 1313 | return img->monochrome ? AV_PIX_FMT_GRAY12AV_PIX_FMT_GRAY12LE : AV_PIX_FMT_YUV420P12AV_PIX_FMT_YUV420P12LE; | ||||
| 1314 | case AOM_IMG_FMT_I422: | ||||
| 1315 | case AOM_IMG_FMT_I42216: | ||||
| 1316 | if (img->bit_depth == 8) | ||||
| 1317 | return AV_PIX_FMT_YUV422P; | ||||
| 1318 | else if (img->bit_depth == 10) | ||||
| 1319 | return AV_PIX_FMT_YUV422P10AV_PIX_FMT_YUV422P10LE; | ||||
| 1320 | else | ||||
| 1321 | return AV_PIX_FMT_YUV422P12AV_PIX_FMT_YUV422P12LE; | ||||
| 1322 | case AOM_IMG_FMT_I444: | ||||
| 1323 | case AOM_IMG_FMT_I44416: | ||||
| 1324 | if (img->bit_depth == 8) | ||||
| 1325 | return AV_PIX_FMT_YUV444P; | ||||
| 1326 | else if (img->bit_depth == 10) | ||||
| 1327 | return AV_PIX_FMT_YUV444P10AV_PIX_FMT_YUV444P10LE; | ||||
| 1328 | else | ||||
| 1329 | return AV_PIX_FMT_YUV444P12AV_PIX_FMT_YUV444P12LE; | ||||
| 1330 | }; | ||||
| 1331 | return AV_PIX_FMT_NONE; | ||||
| 1332 | } | ||||
| 1333 | |||||
| 1334 | static int aom_encode(AVCodecContext *avctx, AVPacket *pkt, | ||||
| 1335 | const AVFrame *frame, int *got_packet) | ||||
| 1336 | { | ||||
| 1337 | AOMContext *ctx = avctx->priv_data; | ||||
| 1338 | struct aom_image *rawimg = NULL((void*)0); | ||||
| 1339 | int64_t timestamp = 0; | ||||
| 1340 | unsigned long duration = 0; | ||||
| 1341 | int res, coded_size; | ||||
| 1342 | aom_enc_frame_flags_t flags = 0; | ||||
| 1343 | AVFrameSideData *sd; | ||||
| 1344 | |||||
| 1345 | if (frame) { | ||||
| 1346 | rawimg = &ctx->rawimg; | ||||
| 1347 | aom_img_remove_metadata(rawimg); | ||||
| 1348 | rawimg->planes[AOM_PLANE_Y0] = frame->data[0]; | ||||
| 1349 | rawimg->planes[AOM_PLANE_U1] = frame->data[1]; | ||||
| 1350 | rawimg->planes[AOM_PLANE_V2] = frame->data[2]; | ||||
| 1351 | rawimg->stride[AOM_PLANE_Y0] = frame->linesize[0]; | ||||
| 1352 | rawimg->stride[AOM_PLANE_U1] = frame->linesize[1]; | ||||
| 1353 | rawimg->stride[AOM_PLANE_V2] = frame->linesize[2]; | ||||
| 1354 | timestamp = frame->pts; | ||||
| 1355 | |||||
| 1356 | if (frame->duration > ULONG_MAX(9223372036854775807L *2UL+1UL)) { | ||||
| 1357 | av_log(avctx, AV_LOG_WARNING24, | ||||
| 1358 | "Frame duration too large: %"PRId64"l" "d""\n", frame->duration); | ||||
| 1359 | } else if (frame->duration) | ||||
| 1360 | duration = frame->duration; | ||||
| 1361 | else if (avctx->framerate.num > 0 && avctx->framerate.den > 0) | ||||
| 1362 | duration = av_rescale_q(1, av_inv_q(avctx->framerate), avctx->time_base); | ||||
| 1363 | else { | ||||
| 1364 | duration = 1; | ||||
| 1365 | } | ||||
| 1366 | |||||
| 1367 | switch (frame->color_range) { | ||||
| 1368 | case AVCOL_RANGE_MPEG: | ||||
| 1369 | rawimg->range = AOM_CR_STUDIO_RANGE; | ||||
| 1370 | break; | ||||
| 1371 | case AVCOL_RANGE_JPEG: | ||||
| 1372 | rawimg->range = AOM_CR_FULL_RANGE; | ||||
| 1373 | break; | ||||
| 1374 | } | ||||
| 1375 | |||||
| 1376 | aom_img_remove_metadata(rawimg); | ||||
| 1377 | sd = av_frame_get_side_data(frame, AV_FRAME_DATA_DOVI_METADATA); | ||||
| 1378 | if (ctx->dovi.cfg.dv_profile && sd) { | ||||
| 1379 | const AVDOVIMetadata *metadata = (const AVDOVIMetadata *)sd->data; | ||||
| 1380 | uint8_t *t35; | ||||
| 1381 | int size; | ||||
| 1382 | if ((res = ff_dovi_rpu_generate(&ctx->dovi, metadata, FF_DOVI_WRAP_T35, | ||||
| 1383 | &t35, &size)) < 0) | ||||
| 1384 | return res; | ||||
| 1385 | res = aom_img_add_metadata(rawimg, OBU_METADATA_TYPE_ITUT_T35, | ||||
| 1386 | t35, size, AOM_MIF_ANY_FRAME); | ||||
| 1387 | av_free(t35); | ||||
| 1388 | if (res != AOM_CODEC_OK) | ||||
| 1389 | return AVERROR(ENOMEM)(-(12)); | ||||
| 1390 | } else if (ctx->dovi.cfg.dv_profile) { | ||||
| 1391 | av_log(avctx, AV_LOG_ERROR16, "Dolby Vision enabled, but received frame " | ||||
| 1392 | "without AV_FRAME_DATA_DOVI_METADATA\n"); | ||||
| 1393 | return AVERROR_INVALIDDATA(-(int)(('I') | (('N') << 8) | (('D') << 16) | (( unsigned)('A') << 24))); | ||||
| 1394 | } | ||||
| 1395 | |||||
| 1396 | if (frame->pict_type == AV_PICTURE_TYPE_I) | ||||
| 1397 | flags |= AOM_EFLAG_FORCE_KF(1 << 0); | ||||
| 1398 | |||||
| 1399 | AVDictionaryEntry* en = av_dict_get(frame->metadata, "temporal_id", NULL((void*)0), 0); | ||||
| 1400 | if (en) { | ||||
| 1401 | aom_svc_layer_id_t layer_id = {}; | ||||
| 1402 | layer_id.temporal_layer_id = strtoul(en->value, NULL((void*)0), 10); | ||||
| 1403 | av_log(avctx, AV_LOG_DEBUG48, "Frame pts % " PRId64"l" "d" " temporal layer id %d", | ||||
| 1404 | frame->pts, layer_id.temporal_layer_id); | ||||
| 1405 | if (!ctx->svc_parameters) { | ||||
| 1406 | av_log(avctx, AV_LOG_WARNING24, | ||||
| 1407 | "Temporal SVC not enabled, but temporal layer id received."); | ||||
| 1408 | } | ||||
| 1409 | res = aom_codec_control(&ctx->encoder, AV1E_SET_SVC_LAYER_ID, &layer_id); | ||||
| 1410 | if (res != AOM_CODEC_OK) { | ||||
| 1411 | av_log(avctx, AV_LOG_ERROR16, | ||||
| 1412 | "Error setting temporal layer id %d on frame pts % " PRId64"l" "d" "\n", | ||||
| 1413 | layer_id.temporal_layer_id, frame->pts); | ||||
| 1414 | return res; | ||||
| 1415 | } | ||||
| 1416 | } | ||||
| 1417 | |||||
| 1418 | res = add_hdr_plus(avctx, rawimg, frame); | ||||
| 1419 | if (res < 0) | ||||
| 1420 | return res; | ||||
| 1421 | } | ||||
| 1422 | |||||
| 1423 | res = aom_codec_encode(&ctx->encoder, rawimg, timestamp, duration, flags); | ||||
| 1424 | if (res != AOM_CODEC_OK) { | ||||
| 1425 | log_encoder_error(avctx, "Error encoding frame"); | ||||
| 1426 | return AVERROR_INVALIDDATA(-(int)(('I') | (('N') << 8) | (('D') << 16) | (( unsigned)('A') << 24))); | ||||
| 1427 | } | ||||
| 1428 | coded_size = queue_frames(avctx, pkt); | ||||
| 1429 | if (coded_size < 0) | ||||
| 1430 | return coded_size; | ||||
| 1431 | |||||
| 1432 | if (!frame && avctx->flags & AV_CODEC_FLAG_PASS1(1 << 9)) { | ||||
| 1433 | size_t b64_size = AV_BASE64_SIZE(ctx->twopass_stats.sz)(((ctx->twopass_stats.sz)+2) / 3 * 4 + 1); | ||||
| 1434 | |||||
| 1435 | avctx->stats_out = av_malloc(b64_size); | ||||
| 1436 | if (!avctx->stats_out) { | ||||
| 1437 | av_log(avctx, AV_LOG_ERROR16, "Stat buffer alloc (%zu bytes) failed\n", | ||||
| 1438 | b64_size); | ||||
| 1439 | return AVERROR(ENOMEM)(-(12)); | ||||
| 1440 | } | ||||
| 1441 | av_base64_encode(avctx->stats_out, b64_size, ctx->twopass_stats.buf, | ||||
| 1442 | ctx->twopass_stats.sz); | ||||
| 1443 | } | ||||
| 1444 | |||||
| 1445 | *got_packet = !!coded_size; | ||||
| 1446 | |||||
| 1447 | if (*got_packet && avctx->flags & AV_CODEC_FLAG_RECON_FRAME(1 << 6)) { | ||||
| 1448 | AVCodecInternal *avci = avctx->internal; | ||||
| 1449 | struct aom_image img; | ||||
| 1450 | |||||
| 1451 | av_frame_unref(avci->recon_frame); | ||||
| 1452 | |||||
| 1453 | res = codecctl_imgp(avctx, AV1_GET_NEW_FRAME_IMAGE, &img); | ||||
| 1454 | if (res < 0) | ||||
| 1455 | return res; | ||||
| 1456 | |||||
| 1457 | avci->recon_frame->format = aomfmt_to_pixfmt(&img); | ||||
| 1458 | if (avci->recon_frame->format == AV_PIX_FMT_NONE) { | ||||
| 1459 | av_log(ctx, AV_LOG_ERROR16, | ||||
| 1460 | "Unhandled reconstructed frame colorspace: %d\n", | ||||
| 1461 | img.fmt); | ||||
| 1462 | return AVERROR(ENOSYS)(-(38)); | ||||
| 1463 | } | ||||
| 1464 | |||||
| 1465 | avci->recon_frame->width = img.d_w; | ||||
| 1466 | avci->recon_frame->height = img.d_h; | ||||
| 1467 | |||||
| 1468 | res = av_frame_get_buffer(avci->recon_frame, 0); | ||||
| 1469 | if (res < 0) | ||||
| 1470 | return res; | ||||
| 1471 | |||||
| 1472 | if ((img.fmt & AOM_IMG_FMT_HIGHBITDEPTH0x800) && img.bit_depth == 8) | ||||
| 1473 | ff_aom_image_copy_16_to_8(avci->recon_frame, &img); | ||||
| 1474 | else { | ||||
| 1475 | const uint8_t *planes[4] = { img.planes[0], img.planes[1], img.planes[2] }; | ||||
| 1476 | const int stride[4] = { img.stride[0], img.stride[1], img.stride[2] }; | ||||
| 1477 | |||||
| 1478 | av_image_copy(avci->recon_frame->data, avci->recon_frame->linesize, planes, | ||||
| 1479 | stride, avci->recon_frame->format, img.d_w, img.d_h); | ||||
| 1480 | } | ||||
| 1481 | } | ||||
| 1482 | |||||
| 1483 | return 0; | ||||
| 1484 | } | ||||
| 1485 | |||||
| 1486 | static const enum AVPixelFormat av1_pix_fmts[] = { | ||||
| 1487 | AV_PIX_FMT_YUV420P, | ||||
| 1488 | AV_PIX_FMT_YUV422P, | ||||
| 1489 | AV_PIX_FMT_YUV444P, | ||||
| 1490 | AV_PIX_FMT_GBRP, | ||||
| 1491 | AV_PIX_FMT_NONE | ||||
| 1492 | }; | ||||
| 1493 | |||||
| 1494 | static const enum AVPixelFormat av1_pix_fmts_with_gray[] = { | ||||
| 1495 | AV_PIX_FMT_YUV420P, | ||||
| 1496 | AV_PIX_FMT_YUV422P, | ||||
| 1497 | AV_PIX_FMT_YUV444P, | ||||
| 1498 | AV_PIX_FMT_GBRP, | ||||
| 1499 | AV_PIX_FMT_GRAY8, | ||||
| 1500 | AV_PIX_FMT_NONE | ||||
| 1501 | }; | ||||
| 1502 | |||||
| 1503 | static const enum AVPixelFormat av1_pix_fmts_highbd[] = { | ||||
| 1504 | AV_PIX_FMT_YUV420P, | ||||
| 1505 | AV_PIX_FMT_YUV422P, | ||||
| 1506 | AV_PIX_FMT_YUV444P, | ||||
| 1507 | AV_PIX_FMT_GBRP, | ||||
| 1508 | AV_PIX_FMT_YUV420P10AV_PIX_FMT_YUV420P10LE, | ||||
| 1509 | AV_PIX_FMT_YUV422P10AV_PIX_FMT_YUV422P10LE, | ||||
| 1510 | AV_PIX_FMT_YUV444P10AV_PIX_FMT_YUV444P10LE, | ||||
| 1511 | AV_PIX_FMT_YUV420P12AV_PIX_FMT_YUV420P12LE, | ||||
| 1512 | AV_PIX_FMT_YUV422P12AV_PIX_FMT_YUV422P12LE, | ||||
| 1513 | AV_PIX_FMT_YUV444P12AV_PIX_FMT_YUV444P12LE, | ||||
| 1514 | AV_PIX_FMT_GBRP10AV_PIX_FMT_GBRP10LE, | ||||
| 1515 | AV_PIX_FMT_GBRP12AV_PIX_FMT_GBRP12LE, | ||||
| 1516 | AV_PIX_FMT_NONE | ||||
| 1517 | }; | ||||
| 1518 | |||||
| 1519 | static const enum AVPixelFormat av1_pix_fmts_highbd_with_gray[] = { | ||||
| 1520 | AV_PIX_FMT_YUV420P, | ||||
| 1521 | AV_PIX_FMT_YUV422P, | ||||
| 1522 | AV_PIX_FMT_YUV444P, | ||||
| 1523 | AV_PIX_FMT_GBRP, | ||||
| 1524 | AV_PIX_FMT_YUV420P10AV_PIX_FMT_YUV420P10LE, | ||||
| 1525 | AV_PIX_FMT_YUV422P10AV_PIX_FMT_YUV422P10LE, | ||||
| 1526 | AV_PIX_FMT_YUV444P10AV_PIX_FMT_YUV444P10LE, | ||||
| 1527 | AV_PIX_FMT_YUV420P12AV_PIX_FMT_YUV420P12LE, | ||||
| 1528 | AV_PIX_FMT_YUV422P12AV_PIX_FMT_YUV422P12LE, | ||||
| 1529 | AV_PIX_FMT_YUV444P12AV_PIX_FMT_YUV444P12LE, | ||||
| 1530 | AV_PIX_FMT_GBRP10AV_PIX_FMT_GBRP10LE, | ||||
| 1531 | AV_PIX_FMT_GBRP12AV_PIX_FMT_GBRP12LE, | ||||
| 1532 | AV_PIX_FMT_GRAY8, | ||||
| 1533 | AV_PIX_FMT_GRAY10AV_PIX_FMT_GRAY10LE, | ||||
| 1534 | AV_PIX_FMT_GRAY12AV_PIX_FMT_GRAY12LE, | ||||
| 1535 | AV_PIX_FMT_NONE | ||||
| 1536 | }; | ||||
| 1537 | |||||
| 1538 | static int av1_get_supported_config(const AVCodecContext *avctx, | ||||
| 1539 | const AVCodec *codec, | ||||
| 1540 | enum AVCodecConfig config, | ||||
| 1541 | unsigned flags, const void **out, | ||||
| 1542 | int *out_num) | ||||
| 1543 | { | ||||
| 1544 | if (config == AV_CODEC_CONFIG_PIX_FORMAT) { | ||||
| 1545 | int supports_monochrome = aom_codec_version() >= 20001; | ||||
| 1546 | aom_codec_caps_t codec_caps = aom_codec_get_caps(aom_codec_av1_cx()); | ||||
| 1547 | if (codec_caps & AOM_CODEC_CAP_HIGHBITDEPTH0x40000) { | ||||
| 1548 | if (supports_monochrome) { | ||||
| 1549 | *out = av1_pix_fmts_highbd_with_gray; | ||||
| 1550 | *out_num = FF_ARRAY_ELEMS(av1_pix_fmts_highbd_with_gray)(sizeof(av1_pix_fmts_highbd_with_gray) / sizeof((av1_pix_fmts_highbd_with_gray )[0])) - 1; | ||||
| 1551 | } else { | ||||
| 1552 | *out = av1_pix_fmts_highbd; | ||||
| 1553 | *out_num = FF_ARRAY_ELEMS(av1_pix_fmts_highbd)(sizeof(av1_pix_fmts_highbd) / sizeof((av1_pix_fmts_highbd)[0 ])) - 1; | ||||
| 1554 | } | ||||
| 1555 | } else { | ||||
| 1556 | if (supports_monochrome) { | ||||
| 1557 | *out = av1_pix_fmts_with_gray; | ||||
| 1558 | *out_num = FF_ARRAY_ELEMS(av1_pix_fmts_with_gray)(sizeof(av1_pix_fmts_with_gray) / sizeof((av1_pix_fmts_with_gray )[0])) - 1; | ||||
| 1559 | } else { | ||||
| 1560 | *out = av1_pix_fmts; | ||||
| 1561 | *out_num = FF_ARRAY_ELEMS(av1_pix_fmts)(sizeof(av1_pix_fmts) / sizeof((av1_pix_fmts)[0])) - 1; | ||||
| 1562 | } | ||||
| 1563 | } | ||||
| 1564 | return 0; | ||||
| 1565 | } | ||||
| 1566 | |||||
| 1567 | return ff_default_get_supported_config(avctx, codec, config, flags, out, out_num); | ||||
| 1568 | } | ||||
| 1569 | |||||
| 1570 | static av_cold__attribute__((cold)) int av1_init(AVCodecContext *avctx) | ||||
| 1571 | { | ||||
| 1572 | return aom_init(avctx, aom_codec_av1_cx()); | ||||
| 1573 | } | ||||
| 1574 | |||||
| 1575 | #define VE(1 << 4) | (1 << 0) AV_OPT_FLAG_VIDEO_PARAM(1 << 4) | AV_OPT_FLAG_ENCODING_PARAM(1 << 0) | ||||
| 1576 | static const AVOption options[] = { | ||||
| 1577 | { "cpu-used", "Quality/Speed ratio modifier", OFFSET(cpu_used)__builtin_offsetof(AOMContext, cpu_used), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 8, VE(1 << 4) | (1 << 0)}, | ||||
| 1578 | { "auto-alt-ref", "Enable use of alternate reference " | ||||
| 1579 | "frames (2-pass only)", OFFSET(auto_alt_ref)__builtin_offsetof(AOMContext, auto_alt_ref), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 2, VE(1 << 4) | (1 << 0)}, | ||||
| 1580 | { "lag-in-frames", "Number of frames to look ahead at for " | ||||
| 1581 | "alternate reference frame selection", OFFSET(lag_in_frames)__builtin_offsetof(AOMContext, lag_in_frames), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX2147483647, VE(1 << 4) | (1 << 0)}, | ||||
| 1582 | { "arnr-max-frames", "altref noise reduction max frame count", OFFSET(arnr_max_frames)__builtin_offsetof(AOMContext, arnr_max_frames), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX2147483647, VE(1 << 4) | (1 << 0)}, | ||||
| 1583 | { "arnr-strength", "altref noise reduction filter strength", OFFSET(arnr_strength)__builtin_offsetof(AOMContext, arnr_strength), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 6, VE(1 << 4) | (1 << 0)}, | ||||
| 1584 | { "aq-mode", "adaptive quantization mode", OFFSET(aq_mode)__builtin_offsetof(AOMContext, aq_mode), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 4, VE(1 << 4) | (1 << 0), .unit = "aq_mode"}, | ||||
| 1585 | { "none", "Aq not used", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, 0, 0, VE(1 << 4) | (1 << 0), .unit = "aq_mode"}, | ||||
| 1586 | { "variance", "Variance based Aq", 0, AV_OPT_TYPE_CONST, {.i64 = 1}, 0, 0, VE(1 << 4) | (1 << 0), .unit = "aq_mode"}, | ||||
| 1587 | { "complexity", "Complexity based Aq", 0, AV_OPT_TYPE_CONST, {.i64 = 2}, 0, 0, VE(1 << 4) | (1 << 0), .unit = "aq_mode"}, | ||||
| 1588 | { "cyclic", "Cyclic Refresh Aq", 0, AV_OPT_TYPE_CONST, {.i64 = 3}, 0, 0, VE(1 << 4) | (1 << 0), .unit = "aq_mode"}, | ||||
| 1589 | { "error-resilience", "Error resilience configuration", OFFSET(error_resilient)__builtin_offsetof(AOMContext, error_resilient), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN(-2147483647 -1), INT_MAX2147483647, VE(1 << 4) | (1 << 0), .unit = "er"}, | ||||
| 1590 | { "default", "Improve resiliency against losses of whole frames", 0, AV_OPT_TYPE_CONST, {.i64 = AOM_ERROR_RESILIENT_DEFAULT0x1}, 0, 0, VE(1 << 4) | (1 << 0), .unit = "er"}, | ||||
| 1591 | { "crf", "Select the quality for constant quality mode", offsetof(AOMContext, crf)__builtin_offsetof(AOMContext, crf), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 63, VE(1 << 4) | (1 << 0) }, | ||||
| 1592 | { "static-thresh", "A change threshold on blocks below which they will be skipped by the encoder", OFFSET(static_thresh)__builtin_offsetof(AOMContext, static_thresh), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX2147483647, VE(1 << 4) | (1 << 0) }, | ||||
| 1593 | { "drop-threshold", "Frame drop threshold", offsetof(AOMContext, drop_threshold)__builtin_offsetof(AOMContext, drop_threshold), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN(-2147483647 -1), INT_MAX2147483647, VE(1 << 4) | (1 << 0) }, | ||||
| 1594 | { "denoise-noise-level", "Amount of noise to be removed", OFFSET(denoise_noise_level)__builtin_offsetof(AOMContext, denoise_noise_level), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX2147483647, VE(1 << 4) | (1 << 0)}, | ||||
| 1595 | { "denoise-block-size", "Denoise block size ", OFFSET(denoise_block_size)__builtin_offsetof(AOMContext, denoise_block_size), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX2147483647, VE(1 << 4) | (1 << 0)}, | ||||
| 1596 | { "undershoot-pct", "Datarate undershoot (min) target (%)", OFFSET(rc_undershoot_pct)__builtin_offsetof(AOMContext, rc_undershoot_pct), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 100, VE(1 << 4) | (1 << 0)}, | ||||
| 1597 | { "overshoot-pct", "Datarate overshoot (max) target (%)", OFFSET(rc_overshoot_pct)__builtin_offsetof(AOMContext, rc_overshoot_pct), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 1000, VE(1 << 4) | (1 << 0)}, | ||||
| 1598 | { "minsection-pct", "GOP min bitrate (% of target)", OFFSET(minsection_pct)__builtin_offsetof(AOMContext, minsection_pct), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 100, VE(1 << 4) | (1 << 0)}, | ||||
| 1599 | { "maxsection-pct", "GOP max bitrate (% of target)", OFFSET(maxsection_pct)__builtin_offsetof(AOMContext, maxsection_pct), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 5000, VE(1 << 4) | (1 << 0)}, | ||||
| 1600 | { "frame-parallel", "Enable frame parallel decodability features", OFFSET(frame_parallel)__builtin_offsetof(AOMContext, frame_parallel), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE(1 << 4) | (1 << 0)}, | ||||
| 1601 | { "tiles", "Tile columns x rows", OFFSET(tile_cols)__builtin_offsetof(AOMContext, tile_cols), AV_OPT_TYPE_IMAGE_SIZE, { .str = NULL((void*)0) }, 0, 0, VE(1 << 4) | (1 << 0) }, | ||||
| 1602 | { "tile-columns", "Log2 of number of tile columns to use", OFFSET(tile_cols_log2)__builtin_offsetof(AOMContext, tile_cols_log2), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 6, VE(1 << 4) | (1 << 0)}, | ||||
| 1603 | { "tile-rows", "Log2 of number of tile rows to use", OFFSET(tile_rows_log2)__builtin_offsetof(AOMContext, tile_rows_log2), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 6, VE(1 << 4) | (1 << 0)}, | ||||
| 1604 | { "row-mt", "Enable row based multi-threading", OFFSET(row_mt)__builtin_offsetof(AOMContext, row_mt), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE(1 << 4) | (1 << 0)}, | ||||
| 1605 | { "enable-cdef", "Enable CDEF filtering", OFFSET(enable_cdef)__builtin_offsetof(AOMContext, enable_cdef), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE(1 << 4) | (1 << 0)}, | ||||
| 1606 | { "enable-global-motion", "Enable global motion", OFFSET(enable_global_motion)__builtin_offsetof(AOMContext, enable_global_motion), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE(1 << 4) | (1 << 0)}, | ||||
| 1607 | { "enable-intrabc", "Enable intra block copy prediction mode", OFFSET(enable_intrabc)__builtin_offsetof(AOMContext, enable_intrabc), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE(1 << 4) | (1 << 0)}, | ||||
| 1608 | { "enable-restoration", "Enable Loop Restoration filtering", OFFSET(enable_restoration)__builtin_offsetof(AOMContext, enable_restoration), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE(1 << 4) | (1 << 0)}, | ||||
| 1609 | { "usage", "Quality and compression efficiency vs speed trade-off", OFFSET(usage)__builtin_offsetof(AOMContext, usage), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX2147483647, VE(1 << 4) | (1 << 0), .unit = "usage"}, | ||||
| 1610 | { "good", "Good quality", 0, AV_OPT_TYPE_CONST, {.i64 = 0 /* AOM_USAGE_GOOD_QUALITY */}, 0, 0, VE(1 << 4) | (1 << 0), .unit = "usage"}, | ||||
| 1611 | { "realtime", "Realtime encoding", 0, AV_OPT_TYPE_CONST, {.i64 = 1 /* AOM_USAGE_REALTIME */}, 0, 0, VE(1 << 4) | (1 << 0), .unit = "usage"}, | ||||
| 1612 | { "allintra", "All Intra encoding", 0, AV_OPT_TYPE_CONST, {.i64 = 2 /* AOM_USAGE_ALL_INTRA */}, 0, 0, VE(1 << 4) | (1 << 0), .unit = "usage"}, | ||||
| 1613 | { "tune", "The metric that the encoder tunes for. Automatically chosen by the encoder by default", OFFSET(tune)__builtin_offsetof(AOMContext, tune), AV_OPT_TYPE_INT, {.i64 = -1}, -1, AOM_TUNE_SSIM, VE(1 << 4) | (1 << 0), .unit = "tune"}, | ||||
| 1614 | { "psnr", NULL((void*)0), 0, AV_OPT_TYPE_CONST, {.i64 = AOM_TUNE_PSNR}, 0, 0, VE(1 << 4) | (1 << 0), .unit = "tune"}, | ||||
| 1615 | { "ssim", NULL((void*)0), 0, AV_OPT_TYPE_CONST, {.i64 = AOM_TUNE_SSIM}, 0, 0, VE(1 << 4) | (1 << 0), .unit = "tune"}, | ||||
| 1616 | FF_AV1_PROFILE_OPTS{"main", ((void*)0), 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, (-2147483647 -1), 2147483647, (1 << 0) | (1 << 4), .unit = "avctx.profile" }, {"high", ((void*)0), 0, AV_OPT_TYPE_CONST, {.i64 = 1 }, (- 2147483647 -1), 2147483647, (1 << 0) | (1 << 4), . unit = "avctx.profile"}, {"professional", ((void*)0), 0, AV_OPT_TYPE_CONST , {.i64 = 2 }, (-2147483647 -1), 2147483647, (1 << 0) | (1 << 4), .unit = "avctx.profile"}, | ||||
| 1617 | { "still-picture", "Encode in single frame mode (typically used for still AVIF images).", OFFSET(still_picture)__builtin_offsetof(AOMContext, still_picture), AV_OPT_TYPE_BOOL, {.i64 = 0}, -1, 1, VE(1 << 4) | (1 << 0) }, | ||||
| 1618 | { "dolbyvision", "Enable Dolby Vision RPU coding", OFFSET(dovi.enable)__builtin_offsetof(AOMContext, dovi.enable), AV_OPT_TYPE_BOOL, {.i64 = FF_DOVI_AUTOMATIC-1 }, -1, 1, VE(1 << 4) | (1 << 0), .unit = "dovi" }, | ||||
| 1619 | { "auto", NULL((void*)0), 0, AV_OPT_TYPE_CONST, {.i64 = FF_DOVI_AUTOMATIC-1}, .flags = VE(1 << 4) | (1 << 0), .unit = "dovi" }, | ||||
| 1620 | { "enable-rect-partitions", "Enable rectangular partitions", OFFSET(enable_rect_partitions)__builtin_offsetof(AOMContext, enable_rect_partitions), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE(1 << 4) | (1 << 0)}, | ||||
| 1621 | { "enable-1to4-partitions", "Enable 1:4/4:1 partitions", OFFSET(enable_1to4_partitions)__builtin_offsetof(AOMContext, enable_1to4_partitions), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE(1 << 4) | (1 << 0)}, | ||||
| 1622 | { "enable-ab-partitions", "Enable ab shape partitions", OFFSET(enable_ab_partitions)__builtin_offsetof(AOMContext, enable_ab_partitions), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE(1 << 4) | (1 << 0)}, | ||||
| 1623 | { "enable-angle-delta", "Enable angle delta intra prediction", OFFSET(enable_angle_delta)__builtin_offsetof(AOMContext, enable_angle_delta), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE(1 << 4) | (1 << 0)}, | ||||
| 1624 | { "enable-cfl-intra", "Enable chroma predicted from luma intra prediction", OFFSET(enable_cfl_intra)__builtin_offsetof(AOMContext, enable_cfl_intra), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE(1 << 4) | (1 << 0)}, | ||||
| 1625 | { "enable-filter-intra", "Enable filter intra predictor", OFFSET(enable_filter_intra)__builtin_offsetof(AOMContext, enable_filter_intra), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE(1 << 4) | (1 << 0)}, | ||||
| 1626 | { "enable-intra-edge-filter", "Enable intra edge filter", OFFSET(enable_intra_edge_filter)__builtin_offsetof(AOMContext, enable_intra_edge_filter), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE(1 << 4) | (1 << 0)}, | ||||
| 1627 | { "enable-smooth-intra", "Enable smooth intra prediction mode", OFFSET(enable_smooth_intra)__builtin_offsetof(AOMContext, enable_smooth_intra), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE(1 << 4) | (1 << 0)}, | ||||
| 1628 | { "enable-paeth-intra", "Enable paeth predictor in intra prediction", OFFSET(enable_paeth_intra)__builtin_offsetof(AOMContext, enable_paeth_intra), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE(1 << 4) | (1 << 0)}, | ||||
| 1629 | { "enable-palette", "Enable palette prediction mode", OFFSET(enable_palette)__builtin_offsetof(AOMContext, enable_palette), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE(1 << 4) | (1 << 0)}, | ||||
| 1630 | { "enable-flip-idtx", "Enable extended transform type", OFFSET(enable_flip_idtx)__builtin_offsetof(AOMContext, enable_flip_idtx), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE(1 << 4) | (1 << 0)}, | ||||
| 1631 | { "enable-tx64", "Enable 64-pt transform", OFFSET(enable_tx64)__builtin_offsetof(AOMContext, enable_tx64), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE(1 << 4) | (1 << 0)}, | ||||
| 1632 | { "reduced-tx-type-set", "Use reduced set of transform types", OFFSET(reduced_tx_type_set)__builtin_offsetof(AOMContext, reduced_tx_type_set), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE(1 << 4) | (1 << 0)}, | ||||
| 1633 | { "use-intra-dct-only", "Use DCT only for INTRA modes", OFFSET(use_intra_dct_only)__builtin_offsetof(AOMContext, use_intra_dct_only), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE(1 << 4) | (1 << 0)}, | ||||
| 1634 | { "use-inter-dct-only", "Use DCT only for INTER modes", OFFSET(use_inter_dct_only)__builtin_offsetof(AOMContext, use_inter_dct_only), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE(1 << 4) | (1 << 0)}, | ||||
| 1635 | { "use-intra-default-tx-only", "Use default-transform only for INTRA modes", OFFSET(use_intra_default_tx_only)__builtin_offsetof(AOMContext, use_intra_default_tx_only), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE(1 << 4) | (1 << 0)}, | ||||
| 1636 | { "enable-ref-frame-mvs", "Enable temporal mv prediction", OFFSET(enable_ref_frame_mvs)__builtin_offsetof(AOMContext, enable_ref_frame_mvs), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE(1 << 4) | (1 << 0)}, | ||||
| 1637 | { "enable-reduced-reference-set", "Use reduced set of single and compound references", OFFSET(enable_reduced_reference_set)__builtin_offsetof(AOMContext, enable_reduced_reference_set), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE(1 << 4) | (1 << 0)}, | ||||
| 1638 | { "enable-obmc", "Enable obmc", OFFSET(enable_obmc)__builtin_offsetof(AOMContext, enable_obmc), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE(1 << 4) | (1 << 0)}, | ||||
| 1639 | { "enable-dual-filter", "Enable dual filter", OFFSET(enable_dual_filter)__builtin_offsetof(AOMContext, enable_dual_filter), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE(1 << 4) | (1 << 0)}, | ||||
| 1640 | { "enable-diff-wtd-comp", "Enable difference-weighted compound", OFFSET(enable_diff_wtd_comp)__builtin_offsetof(AOMContext, enable_diff_wtd_comp), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE(1 << 4) | (1 << 0)}, | ||||
| 1641 | { "enable-dist-wtd-comp", "Enable distance-weighted compound", OFFSET(enable_dist_wtd_comp)__builtin_offsetof(AOMContext, enable_dist_wtd_comp), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE(1 << 4) | (1 << 0)}, | ||||
| 1642 | { "enable-onesided-comp", "Enable one sided compound", OFFSET(enable_onesided_comp)__builtin_offsetof(AOMContext, enable_onesided_comp), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE(1 << 4) | (1 << 0)}, | ||||
| 1643 | { "enable-interinter-wedge", "Enable interinter wedge compound", OFFSET(enable_interinter_wedge)__builtin_offsetof(AOMContext, enable_interinter_wedge), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE(1 << 4) | (1 << 0)}, | ||||
| 1644 | { "enable-interintra-wedge", "Enable interintra wedge compound", OFFSET(enable_interintra_wedge)__builtin_offsetof(AOMContext, enable_interintra_wedge), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE(1 << 4) | (1 << 0)}, | ||||
| 1645 | { "enable-masked-comp", "Enable masked compound", OFFSET(enable_masked_comp)__builtin_offsetof(AOMContext, enable_masked_comp), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE(1 << 4) | (1 << 0)}, | ||||
| 1646 | { "enable-interintra-comp", "Enable interintra compound", OFFSET(enable_interintra_comp)__builtin_offsetof(AOMContext, enable_interintra_comp), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE(1 << 4) | (1 << 0)}, | ||||
| 1647 | { "enable-smooth-interintra", "Enable smooth interintra mode", OFFSET(enable_smooth_interintra)__builtin_offsetof(AOMContext, enable_smooth_interintra), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE(1 << 4) | (1 << 0)}, | ||||
| 1648 | { "svc-parameters", "SVC configuration using a :-separated list of key=value parameters (only applied in CBR mode)", OFFSET(svc_parameters)__builtin_offsetof(AOMContext, svc_parameters), AV_OPT_TYPE_DICT, { 0 }, 0, 0, VE(1 << 4) | (1 << 0)}, | ||||
| 1649 | #if AOM_ENCODER_ABI_VERSION(10 + (7 + (9)) + 3) >= 23 | ||||
| 1650 | { "aom-params", "Set libaom options using a :-separated list of key=value pairs", OFFSET(aom_params)__builtin_offsetof(AOMContext, aom_params), AV_OPT_TYPE_DICT, { 0 }, 0, 0, VE(1 << 4) | (1 << 0) }, | ||||
| 1651 | #endif | ||||
| 1652 | { NULL((void*)0) }, | ||||
| 1653 | }; | ||||
| 1654 | |||||
| 1655 | static const FFCodecDefault defaults[] = { | ||||
| 1656 | { "b", "0" }, | ||||
| 1657 | { "qmin", "-1" }, | ||||
| 1658 | { "qmax", "-1" }, | ||||
| 1659 | { "g", "-1" }, | ||||
| 1660 | { "keyint_min", "-1" }, | ||||
| 1661 | { NULL((void*)0) }, | ||||
| 1662 | }; | ||||
| 1663 | |||||
| 1664 | static const AVClass class_aom = { | ||||
| 1665 | .class_name = "libaom-av1 encoder", | ||||
| 1666 | .item_name = av_default_item_name, | ||||
| 1667 | .option = options, | ||||
| 1668 | .version = LIBAVUTIL_VERSION_INT((60)<<16 | (29)<<8 | (100)), | ||||
| 1669 | }; | ||||
| 1670 | |||||
| 1671 | FFCodec ff_libaom_av1_encoder = { | ||||
| 1672 | .p.name = "libaom-av1", | ||||
| 1673 | CODEC_LONG_NAME("libaom AV1").p.long_name = "libaom AV1", | ||||
| 1674 | .p.type = AVMEDIA_TYPE_VIDEO, | ||||
| 1675 | .p.id = AV_CODEC_ID_AV1, | ||||
| 1676 | .p.capabilities = AV_CODEC_CAP_DR1(1 << 1) | AV_CODEC_CAP_DELAY(1 << 5) | | ||||
| 1677 | AV_CODEC_CAP_ENCODER_RECON_FRAME(1 << 22) | | ||||
| 1678 | AV_CODEC_CAP_OTHER_THREADS(1 << 15), | ||||
| 1679 | .color_ranges = AVCOL_RANGE_MPEG | AVCOL_RANGE_JPEG, | ||||
| 1680 | .p.profiles = NULL_IF_CONFIG_SMALL(ff_av1_profiles)ff_av1_profiles, | ||||
| 1681 | .p.priv_class = &class_aom, | ||||
| 1682 | .p.wrapper_name = "libaom", | ||||
| 1683 | .priv_data_size = sizeof(AOMContext), | ||||
| 1684 | .init = av1_init, | ||||
| 1685 | FF_CODEC_ENCODE_CB(aom_encode).is_decoder = 0, .cb_type = FF_CODEC_CB_TYPE_ENCODE, .cb.encode = (aom_encode), | ||||
| 1686 | .close = aom_free, | ||||
| 1687 | .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE(1 << 0) | | ||||
| 1688 | FF_CODEC_CAP_INIT_CLEANUP(1 << 1) | | ||||
| 1689 | FF_CODEC_CAP_AUTO_THREADS(1 << 7), | ||||
| 1690 | .defaults = defaults, | ||||
| 1691 | .get_supported_config = av1_get_supported_config, | ||||
| 1692 | }; |