| File: | root/firefox-clang/media/ffvpx/libavcodec/libvpxenc.c |
| Warning: | line 1147, 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 | * VP8/9 encoder support via libvpx | |||
| 24 | */ | |||
| 25 | ||||
| 26 | #include "config_components.h" | |||
| 27 | ||||
| 28 | #define VPX_DISABLE_CTRL_TYPECHECKS1 1 | |||
| 29 | #define VPX_CODEC_DISABLE_COMPAT1 1 | |||
| 30 | #include <vpx/vpx_encoder.h> | |||
| 31 | #include <vpx/vp8cx.h> | |||
| 32 | ||||
| 33 | #include "avcodec.h" | |||
| 34 | #include "codec_internal.h" | |||
| 35 | #include "encode.h" | |||
| 36 | #include "libavutil/avassert.h" | |||
| 37 | #include "libavutil/mem.h" | |||
| 38 | #include "libvpx.h" | |||
| 39 | #include "profiles.h" | |||
| 40 | #include "libavutil/avstring.h" | |||
| 41 | #include "libavutil/base64.h" | |||
| 42 | #include "libavutil/common.h" | |||
| 43 | #include "libavutil/cpu.h" | |||
| 44 | #include "libavutil/fifo.h" | |||
| 45 | #include "libavutil/internal.h" | |||
| 46 | #include "libavutil/intreadwrite.h" | |||
| 47 | #include "libavutil/mathematics.h" | |||
| 48 | #include "libavutil/opt.h" | |||
| 49 | #include "libavutil/pixdesc.h" | |||
| 50 | ||||
| 51 | #define IS_VP9(avctx)(1 && avctx->codec_id == AV_CODEC_ID_VP9) (CONFIG_LIBVPX_VP9_ENCODER1 && avctx->codec_id == AV_CODEC_ID_VP9) | |||
| 52 | #define IS_VP8(avctx)(1 && avctx->codec_id == AV_CODEC_ID_VP8) (CONFIG_LIBVPX_VP8_ENCODER1 && avctx->codec_id == AV_CODEC_ID_VP8) | |||
| 53 | ||||
| 54 | /** | |||
| 55 | * Portion of struct vpx_codec_cx_pkt from vpx_encoder.h. | |||
| 56 | * One encoded frame returned from the library. | |||
| 57 | */ | |||
| 58 | struct FrameListData { | |||
| 59 | void *buf; /**< compressed data buffer */ | |||
| 60 | size_t sz; /**< length of compressed data */ | |||
| 61 | int64_t pts; /**< time stamp to show frame | |||
| 62 | (in timebase units) */ | |||
| 63 | uint32_t flags; /**< flags for this frame */ | |||
| 64 | uint64_t sse[4]; | |||
| 65 | int have_sse; /**< true if we have pending sse[] */ | |||
| 66 | struct FrameListData *next; | |||
| 67 | }; | |||
| 68 | ||||
| 69 | typedef struct FrameData { | |||
| 70 | int64_t pts; | |||
| 71 | int64_t duration; | |||
| 72 | ||||
| 73 | void *frame_opaque; | |||
| 74 | AVBufferRef *frame_opaque_ref; | |||
| 75 | ||||
| 76 | AVBufferRef *hdr10_plus; | |||
| 77 | } FrameData; | |||
| 78 | ||||
| 79 | typedef struct VPxEncoderContext { | |||
| 80 | AVClass *class; | |||
| 81 | struct vpx_codec_ctx encoder; | |||
| 82 | struct vpx_image rawimg; | |||
| 83 | struct vpx_codec_ctx encoder_alpha; | |||
| 84 | struct vpx_image rawimg_alpha; | |||
| 85 | uint8_t is_alpha; | |||
| 86 | struct vpx_fixed_buf twopass_stats; | |||
| 87 | unsigned twopass_stats_size; | |||
| 88 | int deadline; //i.e., RT/GOOD/BEST | |||
| 89 | uint64_t sse[4]; | |||
| 90 | int have_sse; /**< true if we have pending sse[] */ | |||
| 91 | struct FrameListData *coded_frame_list; | |||
| 92 | struct FrameListData *alpha_coded_frame_list; | |||
| 93 | ||||
| 94 | int cpu_used; | |||
| 95 | int sharpness; | |||
| 96 | /** | |||
| 97 | * VP8 specific flags, see VP8F_* below. | |||
| 98 | */ | |||
| 99 | int flags; | |||
| 100 | #define VP8F_ERROR_RESILIENT0x00000001 0x00000001 ///< Enable measures appropriate for streaming over lossy links | |||
| 101 | #define VP8F_AUTO_ALT_REF0x00000002 0x00000002 ///< Enable automatic alternate reference frame generation | |||
| 102 | ||||
| 103 | int auto_alt_ref; | |||
| 104 | ||||
| 105 | int arnr_max_frames; | |||
| 106 | int arnr_strength; | |||
| 107 | int arnr_type; | |||
| 108 | ||||
| 109 | int tune; | |||
| 110 | ||||
| 111 | int lag_in_frames; | |||
| 112 | int error_resilient; | |||
| 113 | int crf; | |||
| 114 | int static_thresh; | |||
| 115 | int max_intra_rate; | |||
| 116 | int rc_undershoot_pct; | |||
| 117 | int rc_overshoot_pct; | |||
| 118 | ||||
| 119 | AVDictionary *vpx_ts_parameters; | |||
| 120 | int *ts_layer_flags; | |||
| 121 | int current_temporal_idx; | |||
| 122 | ||||
| 123 | // VP8-only | |||
| 124 | int screen_content_mode; | |||
| 125 | ||||
| 126 | // VP9-only | |||
| 127 | int lossless; | |||
| 128 | int tile_columns; | |||
| 129 | int tile_rows; | |||
| 130 | int frame_parallel; | |||
| 131 | int aq_mode; | |||
| 132 | int drop_threshold; | |||
| 133 | int noise_sensitivity; | |||
| 134 | int vpx_cs; | |||
| 135 | float level; | |||
| 136 | int row_mt; | |||
| 137 | int tune_content; | |||
| 138 | int corpus_complexity; | |||
| 139 | int tpl_model; | |||
| 140 | int min_gf_interval; | |||
| 141 | ||||
| 142 | // This FIFO is used to propagate various properties from frames to packets. | |||
| 143 | AVFifo *fifo; | |||
| 144 | /** | |||
| 145 | * If the driver does not support ROI then warn the first time we | |||
| 146 | * encounter a frame with ROI side data. | |||
| 147 | */ | |||
| 148 | int roi_warned; | |||
| 149 | #if CONFIG_LIBVPX_VP9_ENCODER1 && defined(VPX_CTRL_VP9E_SET_MAX_INTER_BITRATE_PCT) | |||
| 150 | vpx_svc_ref_frame_config_t ref_frame_config; | |||
| 151 | #endif | |||
| 152 | } VPxContext; | |||
| 153 | ||||
| 154 | /** String mappings for enum vp8e_enc_control_id */ | |||
| 155 | static const char *const ctlidstr[] = { | |||
| 156 | [VP8E_SET_CPUUSED] = "VP8E_SET_CPUUSED", | |||
| 157 | [VP8E_SET_ENABLEAUTOALTREF] = "VP8E_SET_ENABLEAUTOALTREF", | |||
| 158 | [VP8E_SET_NOISE_SENSITIVITY] = "VP8E_SET_NOISE_SENSITIVITY", | |||
| 159 | [VP8E_SET_STATIC_THRESHOLD] = "VP8E_SET_STATIC_THRESHOLD", | |||
| 160 | [VP8E_SET_TOKEN_PARTITIONS] = "VP8E_SET_TOKEN_PARTITIONS", | |||
| 161 | [VP8E_SET_ARNR_MAXFRAMES] = "VP8E_SET_ARNR_MAXFRAMES", | |||
| 162 | [VP8E_SET_ARNR_STRENGTH] = "VP8E_SET_ARNR_STRENGTH", | |||
| 163 | [VP8E_SET_ARNR_TYPE] = "VP8E_SET_ARNR_TYPE", | |||
| 164 | [VP8E_SET_TUNING] = "VP8E_SET_TUNING", | |||
| 165 | [VP8E_SET_CQ_LEVEL] = "VP8E_SET_CQ_LEVEL", | |||
| 166 | [VP8E_SET_MAX_INTRA_BITRATE_PCT] = "VP8E_SET_MAX_INTRA_BITRATE_PCT", | |||
| 167 | [VP8E_SET_SHARPNESS] = "VP8E_SET_SHARPNESS", | |||
| 168 | [VP8E_SET_TEMPORAL_LAYER_ID] = "VP8E_SET_TEMPORAL_LAYER_ID", | |||
| 169 | [VP8E_SET_SCREEN_CONTENT_MODE] = "VP8E_SET_SCREEN_CONTENT_MODE", | |||
| 170 | #if CONFIG_LIBVPX_VP9_ENCODER1 | |||
| 171 | [VP9E_SET_LOSSLESS] = "VP9E_SET_LOSSLESS", | |||
| 172 | [VP9E_SET_TILE_COLUMNS] = "VP9E_SET_TILE_COLUMNS", | |||
| 173 | [VP9E_SET_TILE_ROWS] = "VP9E_SET_TILE_ROWS", | |||
| 174 | [VP9E_SET_FRAME_PARALLEL_DECODING] = "VP9E_SET_FRAME_PARALLEL_DECODING", | |||
| 175 | [VP9E_SET_AQ_MODE] = "VP9E_SET_AQ_MODE", | |||
| 176 | [VP9E_SET_COLOR_SPACE] = "VP9E_SET_COLOR_SPACE", | |||
| 177 | [VP9E_SET_SVC_LAYER_ID] = "VP9E_SET_SVC_LAYER_ID", | |||
| 178 | #if VPX_ENCODER_ABI_VERSION(18 + (4 + (5)) + (7 + 5)) >= 12 | |||
| 179 | [VP9E_SET_SVC_PARAMETERS] = "VP9E_SET_SVC_PARAMETERS", | |||
| 180 | [VP9E_SET_SVC_REF_FRAME_CONFIG] = "VP9E_SET_SVC_REF_FRAME_CONFIG", | |||
| 181 | #endif | |||
| 182 | [VP9E_SET_SVC] = "VP9E_SET_SVC", | |||
| 183 | #if VPX_ENCODER_ABI_VERSION(18 + (4 + (5)) + (7 + 5)) >= 11 | |||
| 184 | [VP9E_SET_COLOR_RANGE] = "VP9E_SET_COLOR_RANGE", | |||
| 185 | #endif | |||
| 186 | #if VPX_ENCODER_ABI_VERSION(18 + (4 + (5)) + (7 + 5)) >= 12 | |||
| 187 | [VP9E_SET_TARGET_LEVEL] = "VP9E_SET_TARGET_LEVEL", | |||
| 188 | [VP9E_GET_LEVEL] = "VP9E_GET_LEVEL", | |||
| 189 | #endif | |||
| 190 | #ifdef VPX_CTRL_VP9E_SET_ROW_MT | |||
| 191 | [VP9E_SET_ROW_MT] = "VP9E_SET_ROW_MT", | |||
| 192 | #endif | |||
| 193 | #ifdef VPX_CTRL_VP9E_SET_TUNE_CONTENT | |||
| 194 | [VP9E_SET_TUNE_CONTENT] = "VP9E_SET_TUNE_CONTENT", | |||
| 195 | #endif | |||
| 196 | #ifdef VPX_CTRL_VP9E_SET_TPL | |||
| 197 | [VP9E_SET_TPL] = "VP9E_SET_TPL", | |||
| 198 | #endif | |||
| 199 | #ifdef VPX_CTRL_VP9E_SET_MIN_GF_INTERVAL | |||
| 200 | [VP9E_SET_MIN_GF_INTERVAL] = "VP9E_SET_MIN_GF_INTERVAL", | |||
| 201 | #endif | |||
| 202 | #endif | |||
| 203 | }; | |||
| 204 | ||||
| 205 | static av_cold__attribute__((cold)) void log_encoder_error(void *logctx, struct vpx_codec_ctx *encoder, const char *desc) | |||
| 206 | { | |||
| 207 | const char *error = vpx_codec_error(encoder); | |||
| 208 | const char *detail = vpx_codec_error_detail(encoder); | |||
| 209 | ||||
| 210 | av_log(logctx, AV_LOG_ERROR16, "%s: %s\n", desc, error); | |||
| 211 | if (detail) | |||
| 212 | av_log(logctx, AV_LOG_ERROR16, " Additional information: %s\n", detail); | |||
| 213 | } | |||
| 214 | ||||
| 215 | static av_cold__attribute__((cold)) void dump_enc_cfg(AVCodecContext *avctx, | |||
| 216 | const struct vpx_codec_enc_cfg *cfg, | |||
| 217 | int level) | |||
| 218 | { | |||
| 219 | int width = -30; | |||
| 220 | int i; | |||
| 221 | ||||
| 222 | av_log(avctx, level, "vpx_codec_enc_cfg\n"); | |||
| 223 | av_log(avctx, level, "generic settings\n" | |||
| 224 | " %*s%u\n %*s%u\n %*s%u\n %*s%u\n %*s%u\n" | |||
| 225 | #if CONFIG_LIBVPX_VP9_ENCODER1 | |||
| 226 | " %*s%u\n %*s%u\n" | |||
| 227 | #endif | |||
| 228 | " %*s{%u/%u}\n %*s%u\n %*s%d\n %*s%u\n", | |||
| 229 | width, "g_usage:", cfg->g_usage, | |||
| 230 | width, "g_threads:", cfg->g_threads, | |||
| 231 | width, "g_profile:", cfg->g_profile, | |||
| 232 | width, "g_w:", cfg->g_w, | |||
| 233 | width, "g_h:", cfg->g_h, | |||
| 234 | #if CONFIG_LIBVPX_VP9_ENCODER1 | |||
| 235 | width, "g_bit_depth:", cfg->g_bit_depth, | |||
| 236 | width, "g_input_bit_depth:", cfg->g_input_bit_depth, | |||
| 237 | #endif | |||
| 238 | width, "g_timebase:", cfg->g_timebase.num, cfg->g_timebase.den, | |||
| 239 | width, "g_error_resilient:", cfg->g_error_resilient, | |||
| 240 | width, "g_pass:", cfg->g_pass, | |||
| 241 | width, "g_lag_in_frames:", cfg->g_lag_in_frames); | |||
| 242 | av_log(avctx, level, "rate control settings\n" | |||
| 243 | " %*s%u\n %*s%u\n %*s%u\n %*s%u\n" | |||
| 244 | " %*s%d\n %*s%p(%zu)\n %*s%u\n", | |||
| 245 | width, "rc_dropframe_thresh:", cfg->rc_dropframe_thresh, | |||
| 246 | width, "rc_resize_allowed:", cfg->rc_resize_allowed, | |||
| 247 | width, "rc_resize_up_thresh:", cfg->rc_resize_up_thresh, | |||
| 248 | width, "rc_resize_down_thresh:", cfg->rc_resize_down_thresh, | |||
| 249 | width, "rc_end_usage:", cfg->rc_end_usage, | |||
| 250 | width, "rc_twopass_stats_in:", cfg->rc_twopass_stats_in.buf, cfg->rc_twopass_stats_in.sz, | |||
| 251 | width, "rc_target_bitrate:", cfg->rc_target_bitrate); | |||
| 252 | av_log(avctx, level, "quantizer settings\n" | |||
| 253 | " %*s%u\n %*s%u\n", | |||
| 254 | width, "rc_min_quantizer:", cfg->rc_min_quantizer, | |||
| 255 | width, "rc_max_quantizer:", cfg->rc_max_quantizer); | |||
| 256 | av_log(avctx, level, "bitrate tolerance\n" | |||
| 257 | " %*s%u\n %*s%u\n", | |||
| 258 | width, "rc_undershoot_pct:", cfg->rc_undershoot_pct, | |||
| 259 | width, "rc_overshoot_pct:", cfg->rc_overshoot_pct); | |||
| 260 | av_log(avctx, level, "temporal layering settings\n" | |||
| 261 | " %*s%u\n", width, "ts_number_layers:", cfg->ts_number_layers); | |||
| 262 | if (avctx->codec_id == AV_CODEC_ID_VP8) { | |||
| 263 | av_log(avctx, level, | |||
| 264 | "\n %*s", width, "ts_target_bitrate:"); | |||
| 265 | for (i = 0; i < VPX_TS_MAX_LAYERS5; i++) | |||
| 266 | av_log(avctx, level, | |||
| 267 | "%u ", cfg->ts_target_bitrate[i]); | |||
| 268 | } | |||
| 269 | #if (VPX_ENCODER_ABI_VERSION(18 + (4 + (5)) + (7 + 5)) >= 12) && CONFIG_LIBVPX_VP9_ENCODER1 | |||
| 270 | if (avctx->codec_id == AV_CODEC_ID_VP9) { | |||
| 271 | av_log(avctx, level, | |||
| 272 | "\n %*s", width, "layer_target_bitrate:"); | |||
| 273 | for (i = 0; i < VPX_TS_MAX_LAYERS5; i++) | |||
| 274 | av_log(avctx, level, | |||
| 275 | "%u ", cfg->layer_target_bitrate[i]); | |||
| 276 | } | |||
| 277 | #endif | |||
| 278 | av_log(avctx, level, "\n"); | |||
| 279 | av_log(avctx, level, | |||
| 280 | "\n %*s", width, "ts_rate_decimator:"); | |||
| 281 | for (i = 0; i < VPX_TS_MAX_LAYERS5; i++) | |||
| 282 | av_log(avctx, level, "%u ", cfg->ts_rate_decimator[i]); | |||
| 283 | av_log(avctx, level, "\n"); | |||
| 284 | av_log(avctx, level, | |||
| 285 | "\n %*s%u\n", width, "ts_periodicity:", cfg->ts_periodicity); | |||
| 286 | av_log(avctx, level, | |||
| 287 | "\n %*s", width, "ts_layer_id:"); | |||
| 288 | for (i = 0; i < VPX_TS_MAX_PERIODICITY16; i++) | |||
| 289 | av_log(avctx, level, "%u ", cfg->ts_layer_id[i]); | |||
| 290 | av_log(avctx, level, "\n"); | |||
| 291 | av_log(avctx, level, "decoder buffer model\n" | |||
| 292 | " %*s%u\n %*s%u\n %*s%u\n", | |||
| 293 | width, "rc_buf_sz:", cfg->rc_buf_sz, | |||
| 294 | width, "rc_buf_initial_sz:", cfg->rc_buf_initial_sz, | |||
| 295 | width, "rc_buf_optimal_sz:", cfg->rc_buf_optimal_sz); | |||
| 296 | av_log(avctx, level, "2 pass rate control settings\n" | |||
| 297 | " %*s%u\n %*s%u\n %*s%u\n", | |||
| 298 | width, "rc_2pass_vbr_bias_pct:", cfg->rc_2pass_vbr_bias_pct, | |||
| 299 | width, "rc_2pass_vbr_minsection_pct:", cfg->rc_2pass_vbr_minsection_pct, | |||
| 300 | width, "rc_2pass_vbr_maxsection_pct:", cfg->rc_2pass_vbr_maxsection_pct); | |||
| 301 | #if VPX_ENCODER_ABI_VERSION(18 + (4 + (5)) + (7 + 5)) >= 14 | |||
| 302 | av_log(avctx, level, " %*s%u\n", | |||
| 303 | width, "rc_2pass_vbr_corpus_complexity:", cfg->rc_2pass_vbr_corpus_complexity); | |||
| 304 | #endif | |||
| 305 | av_log(avctx, level, "keyframing settings\n" | |||
| 306 | " %*s%d\n %*s%u\n %*s%u\n", | |||
| 307 | width, "kf_mode:", cfg->kf_mode, | |||
| 308 | width, "kf_min_dist:", cfg->kf_min_dist, | |||
| 309 | width, "kf_max_dist:", cfg->kf_max_dist); | |||
| 310 | av_log(avctx, level, "\n"); | |||
| 311 | } | |||
| 312 | ||||
| 313 | static void coded_frame_add(void *list, struct FrameListData *cx_frame) | |||
| 314 | { | |||
| 315 | struct FrameListData **p = list; | |||
| 316 | ||||
| 317 | while (*p) | |||
| 318 | p = &(*p)->next; | |||
| 319 | *p = cx_frame; | |||
| 320 | cx_frame->next = NULL((void*)0); | |||
| 321 | } | |||
| 322 | ||||
| 323 | static av_cold__attribute__((cold)) void free_coded_frame(struct FrameListData *cx_frame) | |||
| 324 | { | |||
| 325 | av_freep(&cx_frame->buf); | |||
| 326 | av_freep(&cx_frame); | |||
| 327 | } | |||
| 328 | ||||
| 329 | static av_cold__attribute__((cold)) void free_frame_list(struct FrameListData *list) | |||
| 330 | { | |||
| 331 | struct FrameListData *p = list; | |||
| 332 | ||||
| 333 | while (p) { | |||
| 334 | list = list->next; | |||
| 335 | free_coded_frame(p); | |||
| 336 | p = list; | |||
| 337 | } | |||
| 338 | } | |||
| 339 | ||||
| 340 | static void frame_data_uninit(FrameData *fd) | |||
| 341 | { | |||
| 342 | av_buffer_unref(&fd->frame_opaque_ref); | |||
| 343 | av_buffer_unref(&fd->hdr10_plus); | |||
| 344 | } | |||
| 345 | ||||
| 346 | static av_cold__attribute__((cold)) void fifo_free(AVFifo **fifo) | |||
| 347 | { | |||
| 348 | FrameData fd; | |||
| 349 | while (av_fifo_read(*fifo, &fd, 1) >= 0) | |||
| 350 | frame_data_uninit(&fd); | |||
| 351 | av_fifo_freep2(fifo); | |||
| 352 | } | |||
| 353 | ||||
| 354 | static int encoder_can_drop_frames(AVCodecContext *avctx) | |||
| 355 | { | |||
| 356 | VPxContext *ctx = avctx->priv_data; | |||
| 357 | ||||
| 358 | return (ctx->drop_threshold > 0) || (ctx->screen_content_mode == 2); | |||
| 359 | } | |||
| 360 | ||||
| 361 | static int frame_data_submit(AVCodecContext *avctx, AVFifo *fifo, | |||
| 362 | const AVFrame *frame) | |||
| 363 | { | |||
| 364 | VPxContext *ctx = avctx->priv_data; | |||
| 365 | const struct vpx_codec_enc_cfg *enccfg = ctx->encoder.config.enc; | |||
| 366 | ||||
| 367 | FrameData fd = { .pts = frame->pts }; | |||
| 368 | int ret; | |||
| 369 | ||||
| 370 | if (IS_VP9(avctx)(1 && avctx->codec_id == AV_CODEC_ID_VP9) && | |||
| 371 | // Keep HDR10+ if it has bit depth higher than 8 and | |||
| 372 | // it has PQ trc (SMPTE2084). | |||
| 373 | enccfg->g_bit_depth > 8 && avctx->color_trc == AVCOL_TRC_SMPTE2084) { | |||
| 374 | const AVFrameSideData *sd = av_frame_get_side_data(frame, AV_FRAME_DATA_DYNAMIC_HDR_PLUS); | |||
| 375 | ||||
| 376 | if (sd) { | |||
| 377 | fd.hdr10_plus = av_buffer_ref(sd->buf); | |||
| 378 | if (!fd.hdr10_plus) | |||
| 379 | return AVERROR(ENOMEM)(-(12)); | |||
| 380 | } | |||
| 381 | } | |||
| 382 | ||||
| 383 | fd.duration = frame->duration; | |||
| 384 | fd.frame_opaque = frame->opaque; | |||
| 385 | if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE(1 << 7) && frame->opaque_ref) { | |||
| 386 | ret = av_buffer_replace(&fd.frame_opaque_ref, frame->opaque_ref); | |||
| 387 | if (ret < 0) | |||
| 388 | goto fail; | |||
| 389 | } | |||
| 390 | ||||
| 391 | ret = av_fifo_write(fifo, &fd, 1); | |||
| 392 | if (ret == AVERROR(ENOSPC)(-(28))) { | |||
| 393 | FrameData fd2; | |||
| 394 | ||||
| 395 | av_log(avctx, AV_LOG_WARNING24, "FIFO full, will drop a front element\n"); | |||
| 396 | ||||
| 397 | ret = av_fifo_read(fifo, &fd2, 1); | |||
| 398 | if (ret >= 0) { | |||
| 399 | frame_data_uninit(&fd2); | |||
| 400 | ret = av_fifo_write(fifo, &fd, 1); | |||
| 401 | } | |||
| 402 | } | |||
| 403 | ||||
| 404 | if (ret < 0) | |||
| 405 | goto fail; | |||
| 406 | ||||
| 407 | return 0; | |||
| 408 | fail: | |||
| 409 | frame_data_uninit(&fd); | |||
| 410 | return ret; | |||
| 411 | } | |||
| 412 | ||||
| 413 | static int frame_data_apply(AVCodecContext *avctx, AVFifo *fifo, AVPacket *pkt) | |||
| 414 | { | |||
| 415 | FrameData fd; | |||
| 416 | uint8_t *data; | |||
| 417 | int ret = 0; | |||
| 418 | ||||
| 419 | while (1) { | |||
| 420 | if (av_fifo_peek(fifo, &fd, 1, 0) < 0) | |||
| 421 | return 0; | |||
| 422 | ||||
| 423 | if (fd.pts == pkt->pts) { | |||
| 424 | break; | |||
| 425 | } | |||
| 426 | ||||
| 427 | if (!encoder_can_drop_frames(avctx)) { | |||
| 428 | av_log(avctx, AV_LOG_WARNING24, | |||
| 429 | "Mismatching timestamps: libvpx %"PRId64"l" "d"" queued %"PRId64"l" "d""; " | |||
| 430 | "this is a bug, please report it\n", pkt->pts, fd.pts); | |||
| 431 | goto skip; | |||
| 432 | } | |||
| 433 | ||||
| 434 | av_log(avctx, AV_LOG_DEBUG48, "Dropped frame with pts %"PRId64"l" "d""\n", | |||
| 435 | fd.pts); | |||
| 436 | av_fifo_drain2(fifo, 1); | |||
| 437 | frame_data_uninit(&fd); | |||
| 438 | } | |||
| 439 | ||||
| 440 | pkt->duration = fd.duration; | |||
| 441 | if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE(1 << 7)) { | |||
| 442 | pkt->opaque = fd.frame_opaque; | |||
| 443 | pkt->opaque_ref = fd.frame_opaque_ref; | |||
| 444 | fd.frame_opaque_ref = NULL((void*)0); | |||
| 445 | } | |||
| 446 | ||||
| 447 | if (fd.hdr10_plus) { | |||
| 448 | data = av_packet_new_side_data(pkt, AV_PKT_DATA_DYNAMIC_HDR10_PLUS, fd.hdr10_plus->size); | |||
| 449 | if (!data) { | |||
| 450 | ret = AVERROR(ENOMEM)(-(12)); | |||
| 451 | goto skip; | |||
| 452 | } | |||
| 453 | ||||
| 454 | memcpy(data, fd.hdr10_plus->data, fd.hdr10_plus->size); | |||
| 455 | } | |||
| 456 | ||||
| 457 | skip: | |||
| 458 | av_fifo_drain2(fifo, 1); | |||
| 459 | frame_data_uninit(&fd); | |||
| 460 | ||||
| 461 | return ret; | |||
| 462 | } | |||
| 463 | ||||
| 464 | static av_cold__attribute__((cold)) int codecctl_int(AVCodecContext *avctx, | |||
| 465 | enum vp8e_enc_control_id id, int val) | |||
| 466 | { | |||
| 467 | VPxContext *ctx = avctx->priv_data; | |||
| 468 | char buf[80]; | |||
| 469 | int width = -30; | |||
| 470 | int res; | |||
| 471 | ||||
| 472 | snprintf(buf, sizeof(buf), "%s:", ctlidstr[id]); | |||
| 473 | av_log(avctx, AV_LOG_DEBUG48, " %*s%d\n", width, buf, val); | |||
| 474 | ||||
| 475 | res = vpx_codec_control(&ctx->encoder, id, val)vpx_codec_control_(&ctx->encoder, id, val); | |||
| 476 | if (res != VPX_CODEC_OK) { | |||
| 477 | snprintf(buf, sizeof(buf), "Failed to set %s codec control", | |||
| 478 | ctlidstr[id]); | |||
| 479 | log_encoder_error(avctx, &ctx->encoder, buf); | |||
| 480 | return AVERROR(EINVAL)(-(22)); | |||
| 481 | } | |||
| 482 | ||||
| 483 | if (ctx->is_alpha && id != VP9E_SET_COLOR_SPACE) { | |||
| 484 | int res_alpha = vpx_codec_control(&ctx->encoder_alpha, id, val)vpx_codec_control_(&ctx->encoder_alpha, id, val); | |||
| 485 | if (res_alpha != VPX_CODEC_OK) { | |||
| 486 | snprintf(buf, sizeof(buf), "Failed to set %s alpha codec control", | |||
| 487 | ctlidstr[id]); | |||
| 488 | log_encoder_error(avctx, &ctx->encoder_alpha, buf); | |||
| 489 | return AVERROR(EINVAL)(-(22)); | |||
| 490 | } | |||
| 491 | } | |||
| 492 | ||||
| 493 | return 0; | |||
| 494 | } | |||
| 495 | ||||
| 496 | #if VPX_ENCODER_ABI_VERSION(18 + (4 + (5)) + (7 + 5)) >= 12 | |||
| 497 | static av_cold__attribute__((cold)) int codecctl_intp(AVCodecContext *avctx, | |||
| 498 | enum vp8e_enc_control_id id, int *val) | |||
| 499 | { | |||
| 500 | VPxContext *ctx = avctx->priv_data; | |||
| 501 | char buf[80]; | |||
| 502 | int width = -30; | |||
| 503 | int res; | |||
| 504 | ||||
| 505 | snprintf(buf, sizeof(buf), "%s:", ctlidstr[id]); | |||
| 506 | av_log(avctx, AV_LOG_DEBUG48, " %*s%d\n", width, buf, *val); | |||
| 507 | ||||
| 508 | res = vpx_codec_control(&ctx->encoder, id, val)vpx_codec_control_(&ctx->encoder, id, val); | |||
| 509 | if (res != VPX_CODEC_OK) { | |||
| 510 | snprintf(buf, sizeof(buf), "Failed to set %s codec control", | |||
| 511 | ctlidstr[id]); | |||
| 512 | log_encoder_error(avctx, &ctx->encoder, buf); | |||
| 513 | return AVERROR(EINVAL)(-(22)); | |||
| 514 | } | |||
| 515 | ||||
| 516 | if (ctx->is_alpha) { | |||
| 517 | int res_alpha = vpx_codec_control(&ctx->encoder_alpha, id, val)vpx_codec_control_(&ctx->encoder_alpha, id, val); | |||
| 518 | if (res_alpha != VPX_CODEC_OK) { | |||
| 519 | snprintf(buf, sizeof(buf), "Failed to set %s alpha codec control", | |||
| 520 | ctlidstr[id]); | |||
| 521 | log_encoder_error(avctx, &ctx->encoder_alpha, buf); | |||
| 522 | return AVERROR(EINVAL)(-(22)); | |||
| 523 | } | |||
| 524 | } | |||
| 525 | ||||
| 526 | return 0; | |||
| 527 | } | |||
| 528 | #endif | |||
| 529 | ||||
| 530 | static av_cold__attribute__((cold)) int vpx_free(AVCodecContext *avctx) | |||
| 531 | { | |||
| 532 | VPxContext *ctx = avctx->priv_data; | |||
| 533 | ||||
| 534 | #if VPX_ENCODER_ABI_VERSION(18 + (4 + (5)) + (7 + 5)) >= 12 | |||
| 535 | if (avctx->codec_id == AV_CODEC_ID_VP9 && ctx->level >= 0 && | |||
| 536 | !(avctx->flags & AV_CODEC_FLAG_PASS1(1 << 9))) { | |||
| 537 | int level_out = 0; | |||
| 538 | if (!codecctl_intp(avctx, VP9E_GET_LEVEL, &level_out)) | |||
| 539 | av_log(avctx, AV_LOG_INFO32, "Encoded level %.1f\n", level_out * 0.1); | |||
| 540 | } | |||
| 541 | #endif | |||
| 542 | ||||
| 543 | av_freep(&ctx->ts_layer_flags); | |||
| 544 | ||||
| 545 | vpx_codec_destroy(&ctx->encoder); | |||
| 546 | if (ctx->is_alpha) { | |||
| 547 | vpx_codec_destroy(&ctx->encoder_alpha); | |||
| 548 | av_freep(&ctx->rawimg_alpha.planes[VPX_PLANE_U1]); | |||
| 549 | av_freep(&ctx->rawimg_alpha.planes[VPX_PLANE_V2]); | |||
| 550 | } | |||
| 551 | av_freep(&ctx->twopass_stats.buf); | |||
| 552 | av_freep(&avctx->stats_out); | |||
| 553 | free_frame_list(ctx->coded_frame_list); | |||
| 554 | free_frame_list(ctx->alpha_coded_frame_list); | |||
| 555 | if (ctx->fifo) | |||
| 556 | fifo_free(&ctx->fifo); | |||
| 557 | return 0; | |||
| 558 | } | |||
| 559 | ||||
| 560 | static void vp8_ts_parse_int_array(int *dest, char *value, size_t value_len, int max_entries) | |||
| 561 | { | |||
| 562 | int dest_idx = 0; | |||
| 563 | char *saveptr = NULL((void*)0); | |||
| 564 | char *token = av_strtok(value, ",", &saveptr); | |||
| 565 | ||||
| 566 | while (token && dest_idx < max_entries) { | |||
| 567 | dest[dest_idx++] = strtoul(token, NULL((void*)0), 10); | |||
| 568 | token = av_strtok(NULL((void*)0), ",", &saveptr); | |||
| 569 | } | |||
| 570 | } | |||
| 571 | ||||
| 572 | #if CONFIG_LIBVPX_VP9_ENCODER1 && defined(VPX_CTRL_VP9E_SET_MAX_INTER_BITRATE_PCT) | |||
| 573 | static void vp8_ts_parse_int64_array(int64_t *dest, char *value, size_t value_len, int max_entries) | |||
| 574 | { | |||
| 575 | int dest_idx = 0; | |||
| 576 | char *saveptr = NULL((void*)0); | |||
| 577 | char *token = av_strtok(value, ",", &saveptr); | |||
| 578 | ||||
| 579 | while (token && dest_idx < max_entries) { | |||
| 580 | dest[dest_idx++] = strtoull(token, NULL((void*)0), 10); | |||
| 581 | token = av_strtok(NULL((void*)0), ",", &saveptr); | |||
| 582 | } | |||
| 583 | } | |||
| 584 | #endif | |||
| 585 | ||||
| 586 | static void set_temporal_layer_pattern(int layering_mode, vpx_codec_enc_cfg_t *cfg, | |||
| 587 | int *layer_flags, int *flag_periodicity) | |||
| 588 | { | |||
| 589 | switch (layering_mode) { | |||
| 590 | case 2: { | |||
| 591 | /** | |||
| 592 | * 2-layers, 2-frame period. | |||
| 593 | */ | |||
| 594 | static const int ids[2] = { 0, 1 }; | |||
| 595 | cfg->ts_periodicity = 2; | |||
| 596 | *flag_periodicity = 2; | |||
| 597 | cfg->ts_number_layers = 2; | |||
| 598 | cfg->ts_rate_decimator[0] = 2; | |||
| 599 | cfg->ts_rate_decimator[1] = 1; | |||
| 600 | memcpy(cfg->ts_layer_id, ids, sizeof(ids)); | |||
| 601 | ||||
| 602 | layer_flags[0] = | |||
| 603 | VP8_EFLAG_NO_REF_GF(1 << 17) | VP8_EFLAG_NO_REF_ARF(1 << 21) | | |||
| 604 | VP8_EFLAG_NO_UPD_GF(1 << 22) | VP8_EFLAG_NO_UPD_ARF(1 << 23); | |||
| 605 | layer_flags[1] = | |||
| 606 | VP8_EFLAG_NO_UPD_ARF(1 << 23) | VP8_EFLAG_NO_UPD_GF(1 << 22) | | |||
| 607 | VP8_EFLAG_NO_UPD_LAST(1 << 18) | | |||
| 608 | VP8_EFLAG_NO_REF_ARF(1 << 21) | VP8_EFLAG_NO_REF_GF(1 << 17); | |||
| 609 | break; | |||
| 610 | } | |||
| 611 | case 3: { | |||
| 612 | /** | |||
| 613 | * 3-layers structure with one reference frame. | |||
| 614 | * This works same as temporal_layering_mode 3. | |||
| 615 | * | |||
| 616 | * 3-layers, 4-frame period. | |||
| 617 | */ | |||
| 618 | static const int ids[4] = { 0, 2, 1, 2 }; | |||
| 619 | cfg->ts_periodicity = 4; | |||
| 620 | *flag_periodicity = 4; | |||
| 621 | cfg->ts_number_layers = 3; | |||
| 622 | cfg->ts_rate_decimator[0] = 4; | |||
| 623 | cfg->ts_rate_decimator[1] = 2; | |||
| 624 | cfg->ts_rate_decimator[2] = 1; | |||
| 625 | memcpy(cfg->ts_layer_id, ids, sizeof(ids)); | |||
| 626 | ||||
| 627 | /** | |||
| 628 | * 0=L, 1=GF, 2=ARF, | |||
| 629 | * Intra-layer prediction disabled. | |||
| 630 | */ | |||
| 631 | layer_flags[0] = | |||
| 632 | VP8_EFLAG_NO_REF_GF(1 << 17) | VP8_EFLAG_NO_REF_ARF(1 << 21) | | |||
| 633 | VP8_EFLAG_NO_UPD_GF(1 << 22) | VP8_EFLAG_NO_UPD_ARF(1 << 23); | |||
| 634 | layer_flags[1] = | |||
| 635 | VP8_EFLAG_NO_REF_GF(1 << 17) | VP8_EFLAG_NO_REF_ARF(1 << 21) | | |||
| 636 | VP8_EFLAG_NO_UPD_LAST(1 << 18) | VP8_EFLAG_NO_UPD_GF(1 << 22) | | |||
| 637 | VP8_EFLAG_NO_UPD_ARF(1 << 23); | |||
| 638 | layer_flags[2] = | |||
| 639 | VP8_EFLAG_NO_REF_GF(1 << 17) | VP8_EFLAG_NO_REF_ARF(1 << 21) | | |||
| 640 | VP8_EFLAG_NO_UPD_ARF(1 << 23) | VP8_EFLAG_NO_UPD_LAST(1 << 18); | |||
| 641 | layer_flags[3] = | |||
| 642 | VP8_EFLAG_NO_REF_LAST(1 << 16) | VP8_EFLAG_NO_REF_ARF(1 << 21) | | |||
| 643 | VP8_EFLAG_NO_UPD_LAST(1 << 18) | VP8_EFLAG_NO_UPD_GF(1 << 22) | | |||
| 644 | VP8_EFLAG_NO_UPD_ARF(1 << 23); | |||
| 645 | break; | |||
| 646 | } | |||
| 647 | case 4: { | |||
| 648 | /** | |||
| 649 | * 3-layers structure. | |||
| 650 | * added dependency between the two TL2 frames (on top of case 3). | |||
| 651 | * 3-layers, 4-frame period. | |||
| 652 | */ | |||
| 653 | static const int ids[4] = { 0, 2, 1, 2 }; | |||
| 654 | cfg->ts_periodicity = 4; | |||
| 655 | *flag_periodicity = 4; | |||
| 656 | cfg->ts_number_layers = 3; | |||
| 657 | cfg->ts_rate_decimator[0] = 4; | |||
| 658 | cfg->ts_rate_decimator[1] = 2; | |||
| 659 | cfg->ts_rate_decimator[2] = 1; | |||
| 660 | memcpy(cfg->ts_layer_id, ids, sizeof(ids)); | |||
| 661 | ||||
| 662 | /** | |||
| 663 | * 0=L, 1=GF, 2=ARF, Intra-layer prediction disabled. | |||
| 664 | */ | |||
| 665 | layer_flags[0] = | |||
| 666 | VP8_EFLAG_NO_REF_GF(1 << 17) | VP8_EFLAG_NO_REF_ARF(1 << 21) | | |||
| 667 | VP8_EFLAG_NO_UPD_GF(1 << 22) | VP8_EFLAG_NO_UPD_ARF(1 << 23); | |||
| 668 | layer_flags[1] = | |||
| 669 | VP8_EFLAG_NO_REF_GF(1 << 17) | VP8_EFLAG_NO_REF_ARF(1 << 21) | | |||
| 670 | VP8_EFLAG_NO_UPD_LAST(1 << 18) | VP8_EFLAG_NO_UPD_GF(1 << 22); | |||
| 671 | layer_flags[2] = | |||
| 672 | VP8_EFLAG_NO_REF_GF(1 << 17) | VP8_EFLAG_NO_REF_ARF(1 << 21) | | |||
| 673 | VP8_EFLAG_NO_UPD_ARF(1 << 23) | VP8_EFLAG_NO_UPD_LAST(1 << 18); | |||
| 674 | layer_flags[3] = | |||
| 675 | VP8_EFLAG_NO_REF_LAST(1 << 16) | | |||
| 676 | VP8_EFLAG_NO_UPD_LAST(1 << 18) | VP8_EFLAG_NO_UPD_GF(1 << 22) | | |||
| 677 | VP8_EFLAG_NO_UPD_ARF(1 << 23); | |||
| 678 | break; | |||
| 679 | } | |||
| 680 | default: | |||
| 681 | /** | |||
| 682 | * do not change the layer_flags or the flag_periodicity in this case; | |||
| 683 | * it might be that the code is using external flags to be used. | |||
| 684 | */ | |||
| 685 | break; | |||
| 686 | ||||
| 687 | } | |||
| 688 | } | |||
| 689 | ||||
| 690 | static int vpx_ts_param_parse(VPxContext *ctx, struct vpx_codec_enc_cfg *enccfg, | |||
| 691 | char *key, char *value, enum AVCodecID codec_id) | |||
| 692 | { | |||
| 693 | size_t value_len = strlen(value); | |||
| 694 | int ts_layering_mode = 0; | |||
| 695 | ||||
| 696 | if (!value_len) | |||
| 697 | return -1; | |||
| 698 | ||||
| 699 | if (!strcmp(key, "ts_number_layers")) | |||
| 700 | enccfg->ts_number_layers = strtoul(value, &value, 10); | |||
| 701 | else if (!strcmp(key, "ts_target_bitrate")) { | |||
| 702 | if (codec_id == AV_CODEC_ID_VP8) | |||
| 703 | vp8_ts_parse_int_array(enccfg->ts_target_bitrate, value, value_len, VPX_TS_MAX_LAYERS5); | |||
| 704 | #if (VPX_ENCODER_ABI_VERSION(18 + (4 + (5)) + (7 + 5)) >= 12) && CONFIG_LIBVPX_VP9_ENCODER1 | |||
| 705 | if (codec_id == AV_CODEC_ID_VP9) | |||
| 706 | vp8_ts_parse_int_array(enccfg->layer_target_bitrate, value, value_len, VPX_TS_MAX_LAYERS5); | |||
| 707 | #endif | |||
| 708 | } else if (!strcmp(key, "ts_rate_decimator")) { | |||
| 709 | vp8_ts_parse_int_array(enccfg->ts_rate_decimator, value, value_len, VPX_TS_MAX_LAYERS5); | |||
| 710 | } else if (!strcmp(key, "ts_periodicity")) { | |||
| 711 | enccfg->ts_periodicity = strtoul(value, &value, 10); | |||
| 712 | } else if (!strcmp(key, "ts_layer_id")) { | |||
| 713 | vp8_ts_parse_int_array(enccfg->ts_layer_id, value, value_len, VPX_TS_MAX_PERIODICITY16); | |||
| 714 | } else if (!strcmp(key, "ts_layering_mode")) { | |||
| 715 | /* option for pre-defined temporal structures in function set_temporal_layer_pattern. */ | |||
| 716 | ts_layering_mode = strtoul(value, &value, 10); | |||
| 717 | } | |||
| 718 | ||||
| 719 | #if (VPX_ENCODER_ABI_VERSION(18 + (4 + (5)) + (7 + 5)) >= 12) && CONFIG_LIBVPX_VP9_ENCODER1 | |||
| 720 | enccfg->temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS; // only bypass mode is supported for now. | |||
| 721 | enccfg->ss_number_layers = 1; // TODO: add spatial scalability support. | |||
| 722 | #endif | |||
| 723 | if (ts_layering_mode) { | |||
| 724 | // make sure the ts_layering_mode comes at the end of the ts_parameter string to ensure that | |||
| 725 | // correct configuration is done. | |||
| 726 | ctx->ts_layer_flags = av_malloc_array(VPX_TS_MAX_PERIODICITY16, sizeof(*ctx->ts_layer_flags)); | |||
| 727 | set_temporal_layer_pattern(ts_layering_mode, enccfg, ctx->ts_layer_flags, &enccfg->ts_periodicity); | |||
| 728 | } | |||
| 729 | ||||
| 730 | return 0; | |||
| 731 | } | |||
| 732 | ||||
| 733 | #if CONFIG_LIBVPX_VP9_ENCODER1 && defined(VPX_CTRL_VP9E_SET_MAX_INTER_BITRATE_PCT) | |||
| 734 | static int vpx_ref_frame_config_set_value(vpx_svc_ref_frame_config_t *ref_frame_config, | |||
| 735 | int ss_number_layers, char *key, char *value) | |||
| 736 | { | |||
| 737 | size_t value_len = strlen(value); | |||
| 738 | ||||
| 739 | if (!value_len) | |||
| 740 | return AVERROR(EINVAL)(-(22)); | |||
| 741 | ||||
| 742 | if (!strcmp(key, "rfc_update_buffer_slot")) { | |||
| 743 | vp8_ts_parse_int_array(ref_frame_config->update_buffer_slot, value, value_len, ss_number_layers); | |||
| 744 | } else if (!strcmp(key, "rfc_update_last")) { | |||
| 745 | vp8_ts_parse_int_array(ref_frame_config->update_last, value, value_len, ss_number_layers); | |||
| 746 | } else if (!strcmp(key, "rfc_update_golden")) { | |||
| 747 | vp8_ts_parse_int_array(ref_frame_config->update_golden, value, value_len, ss_number_layers); | |||
| 748 | } else if (!strcmp(key, "rfc_update_alt_ref")) { | |||
| 749 | vp8_ts_parse_int_array(ref_frame_config->update_alt_ref, value, value_len, ss_number_layers); | |||
| 750 | } else if (!strcmp(key, "rfc_lst_fb_idx")) { | |||
| 751 | vp8_ts_parse_int_array(ref_frame_config->lst_fb_idx, value, value_len, ss_number_layers); | |||
| 752 | } else if (!strcmp(key, "rfc_gld_fb_idx")) { | |||
| 753 | vp8_ts_parse_int_array(ref_frame_config->gld_fb_idx, value, value_len, ss_number_layers); | |||
| 754 | } else if (!strcmp(key, "rfc_alt_fb_idx")) { | |||
| 755 | vp8_ts_parse_int_array(ref_frame_config->alt_fb_idx, value, value_len, ss_number_layers); | |||
| 756 | } else if (!strcmp(key, "rfc_reference_last")) { | |||
| 757 | vp8_ts_parse_int_array(ref_frame_config->reference_last, value, value_len, ss_number_layers); | |||
| 758 | } else if (!strcmp(key, "rfc_reference_golden")) { | |||
| 759 | vp8_ts_parse_int_array(ref_frame_config->reference_golden, value, value_len, ss_number_layers); | |||
| 760 | } else if (!strcmp(key, "rfc_reference_alt_ref")) { | |||
| 761 | vp8_ts_parse_int_array(ref_frame_config->reference_alt_ref, value, value_len, ss_number_layers); | |||
| 762 | } else if (!strcmp(key, "rfc_reference_duration")) { | |||
| 763 | vp8_ts_parse_int64_array(ref_frame_config->duration, value, value_len, ss_number_layers); | |||
| 764 | } | |||
| 765 | ||||
| 766 | return 0; | |||
| 767 | } | |||
| 768 | ||||
| 769 | static int vpx_parse_ref_frame_config_element(vpx_svc_ref_frame_config_t *ref_frame_config, | |||
| 770 | int ss_number_layers, const char **buf) | |||
| 771 | { | |||
| 772 | const char key_val_sep[] = "="; | |||
| 773 | const char pairs_sep[] = ":"; | |||
| 774 | char *key = av_get_token(buf, key_val_sep); | |||
| 775 | char *val = NULL((void*)0); | |||
| 776 | int ret; | |||
| 777 | ||||
| 778 | if (key && *key && strspn(*buf, key_val_sep)) { | |||
| 779 | (*buf)++; | |||
| 780 | val = av_get_token(buf, pairs_sep); | |||
| 781 | } | |||
| 782 | ||||
| 783 | if (key && *key && val && *val) | |||
| 784 | ret = vpx_ref_frame_config_set_value(ref_frame_config, ss_number_layers, key, val); | |||
| 785 | else | |||
| 786 | ret = AVERROR(EINVAL)(-(22)); | |||
| 787 | ||||
| 788 | av_freep(&key); | |||
| 789 | av_freep(&val); | |||
| 790 | ||||
| 791 | return ret; | |||
| 792 | } | |||
| 793 | ||||
| 794 | static int vpx_parse_ref_frame_config(vpx_svc_ref_frame_config_t *ref_frame_config, | |||
| 795 | int ss_number_layers, const char *str) | |||
| 796 | { | |||
| 797 | int ret = 0; | |||
| 798 | ||||
| 799 | while (*str) { | |||
| 800 | ret = | |||
| 801 | vpx_parse_ref_frame_config_element(ref_frame_config, ss_number_layers, &str); | |||
| 802 | if (ret < 0) | |||
| 803 | return ret; | |||
| 804 | ||||
| 805 | if (*str) | |||
| 806 | str++; | |||
| 807 | } | |||
| 808 | ||||
| 809 | return ret; | |||
| 810 | } | |||
| 811 | #endif | |||
| 812 | ||||
| 813 | #if CONFIG_LIBVPX_VP9_ENCODER1 | |||
| 814 | static int set_pix_fmt(AVCodecContext *avctx, vpx_codec_caps_t codec_caps, | |||
| 815 | struct vpx_codec_enc_cfg *enccfg, vpx_codec_flags_t *flags, | |||
| 816 | vpx_img_fmt_t *img_fmt) | |||
| 817 | { | |||
| 818 | VPxContext *ctx = avctx->priv_data; | |||
| 819 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt); | |||
| 820 | enccfg->g_bit_depth = enccfg->g_input_bit_depth = desc->comp[0].depth; | |||
| 821 | switch (avctx->pix_fmt) { | |||
| 822 | case AV_PIX_FMT_YUV420P: | |||
| 823 | case AV_PIX_FMT_YUVA420P: | |||
| 824 | enccfg->g_profile = 0; | |||
| 825 | *img_fmt = VPX_IMG_FMT_I420; | |||
| 826 | return 0; | |||
| 827 | case AV_PIX_FMT_YUV422P: | |||
| 828 | case AV_PIX_FMT_YUVA422P: | |||
| 829 | enccfg->g_profile = 1; | |||
| 830 | *img_fmt = VPX_IMG_FMT_I422; | |||
| 831 | return 0; | |||
| 832 | case AV_PIX_FMT_YUV440P: | |||
| 833 | enccfg->g_profile = 1; | |||
| 834 | *img_fmt = VPX_IMG_FMT_I440; | |||
| 835 | return 0; | |||
| 836 | case AV_PIX_FMT_GBRP: | |||
| 837 | case AV_PIX_FMT_GBRAP: | |||
| 838 | ctx->vpx_cs = VPX_CS_SRGB; | |||
| 839 | case AV_PIX_FMT_YUV444P: | |||
| 840 | case AV_PIX_FMT_YUVA444P: | |||
| 841 | if (avctx->colorspace == AVCOL_SPC_RGB) | |||
| 842 | ctx->vpx_cs = VPX_CS_SRGB; | |||
| 843 | enccfg->g_profile = 1; | |||
| 844 | *img_fmt = VPX_IMG_FMT_I444; | |||
| 845 | return 0; | |||
| 846 | case AV_PIX_FMT_YUV420P10AV_PIX_FMT_YUV420P10LE: | |||
| 847 | case AV_PIX_FMT_YUVA420P10AV_PIX_FMT_YUVA420P10LE: | |||
| 848 | case AV_PIX_FMT_YUV420P12AV_PIX_FMT_YUV420P12LE: | |||
| 849 | if (codec_caps & VPX_CODEC_CAP_HIGHBITDEPTH0x4) { | |||
| 850 | enccfg->g_profile = 2; | |||
| 851 | *img_fmt = VPX_IMG_FMT_I42016; | |||
| 852 | *flags |= VPX_CODEC_USE_HIGHBITDEPTH0x40000; | |||
| 853 | return 0; | |||
| 854 | } | |||
| 855 | break; | |||
| 856 | case AV_PIX_FMT_YUV422P10AV_PIX_FMT_YUV422P10LE: | |||
| 857 | case AV_PIX_FMT_YUVA422P10AV_PIX_FMT_YUVA422P10LE: | |||
| 858 | case AV_PIX_FMT_YUV422P12AV_PIX_FMT_YUV422P12LE: | |||
| 859 | if (codec_caps & VPX_CODEC_CAP_HIGHBITDEPTH0x4) { | |||
| 860 | enccfg->g_profile = 3; | |||
| 861 | *img_fmt = VPX_IMG_FMT_I42216; | |||
| 862 | *flags |= VPX_CODEC_USE_HIGHBITDEPTH0x40000; | |||
| 863 | return 0; | |||
| 864 | } | |||
| 865 | break; | |||
| 866 | case AV_PIX_FMT_YUV440P10AV_PIX_FMT_YUV440P10LE: | |||
| 867 | case AV_PIX_FMT_YUV440P12AV_PIX_FMT_YUV440P12LE: | |||
| 868 | if (codec_caps & VPX_CODEC_CAP_HIGHBITDEPTH0x4) { | |||
| 869 | enccfg->g_profile = 3; | |||
| 870 | *img_fmt = VPX_IMG_FMT_I44016; | |||
| 871 | *flags |= VPX_CODEC_USE_HIGHBITDEPTH0x40000; | |||
| 872 | return 0; | |||
| 873 | } | |||
| 874 | break; | |||
| 875 | case AV_PIX_FMT_GBRP10AV_PIX_FMT_GBRP10LE: | |||
| 876 | case AV_PIX_FMT_GBRAP10AV_PIX_FMT_GBRAP10LE: | |||
| 877 | case AV_PIX_FMT_GBRP12AV_PIX_FMT_GBRP12LE: | |||
| 878 | case AV_PIX_FMT_GBRAP12AV_PIX_FMT_GBRAP12LE: | |||
| 879 | ctx->vpx_cs = VPX_CS_SRGB; | |||
| 880 | case AV_PIX_FMT_YUV444P10AV_PIX_FMT_YUV444P10LE: | |||
| 881 | case AV_PIX_FMT_YUVA444P10AV_PIX_FMT_YUVA444P10LE: | |||
| 882 | case AV_PIX_FMT_YUV444P12AV_PIX_FMT_YUV444P12LE: | |||
| 883 | case AV_PIX_FMT_YUVA444P12AV_PIX_FMT_YUVA444P12LE: | |||
| 884 | if (avctx->colorspace == AVCOL_SPC_RGB) | |||
| 885 | ctx->vpx_cs = VPX_CS_SRGB; | |||
| 886 | if (codec_caps & VPX_CODEC_CAP_HIGHBITDEPTH0x4) { | |||
| 887 | enccfg->g_profile = 3; | |||
| 888 | *img_fmt = VPX_IMG_FMT_I44416; | |||
| 889 | *flags |= VPX_CODEC_USE_HIGHBITDEPTH0x40000; | |||
| 890 | return 0; | |||
| 891 | } | |||
| 892 | break; | |||
| 893 | default: | |||
| 894 | break; | |||
| 895 | } | |||
| 896 | av_log(avctx, AV_LOG_ERROR16, "Unsupported pixel format.\n"); | |||
| 897 | return AVERROR_INVALIDDATA(-(int)(('I') | (('N') << 8) | (('D') << 16) | (( unsigned)('A') << 24))); | |||
| 898 | } | |||
| 899 | ||||
| 900 | static int set_colorspace(AVCodecContext *avctx) | |||
| 901 | { | |||
| 902 | enum vpx_color_space vpx_cs; | |||
| 903 | VPxContext *ctx = avctx->priv_data; | |||
| 904 | ||||
| 905 | if (ctx->vpx_cs) { | |||
| 906 | vpx_cs = ctx->vpx_cs; | |||
| 907 | } else { | |||
| 908 | switch (avctx->colorspace) { | |||
| 909 | case AVCOL_SPC_RGB: | |||
| 910 | av_log(avctx, AV_LOG_ERROR16, | |||
| 911 | "RGB colorspace is not compatible with pixel format %s.\n", | |||
| 912 | av_get_pix_fmt_name(avctx->pix_fmt)); | |||
| 913 | return AVERROR(EINVAL)(-(22)); | |||
| 914 | case AVCOL_SPC_BT709: vpx_cs = VPX_CS_BT_709; break; | |||
| 915 | case AVCOL_SPC_UNSPECIFIED: vpx_cs = VPX_CS_UNKNOWN; break; | |||
| 916 | case AVCOL_SPC_RESERVED: vpx_cs = VPX_CS_RESERVED; break; | |||
| 917 | case AVCOL_SPC_BT470BG: vpx_cs = VPX_CS_BT_601; break; | |||
| 918 | case AVCOL_SPC_SMPTE170M: vpx_cs = VPX_CS_SMPTE_170; break; | |||
| 919 | case AVCOL_SPC_SMPTE240M: vpx_cs = VPX_CS_SMPTE_240; break; | |||
| 920 | case AVCOL_SPC_BT2020_NCL: vpx_cs = VPX_CS_BT_2020; break; | |||
| 921 | default: | |||
| 922 | av_log(avctx, AV_LOG_WARNING24, "Unsupported colorspace (%d)\n", | |||
| 923 | avctx->colorspace); | |||
| 924 | return 0; | |||
| 925 | } | |||
| 926 | } | |||
| 927 | codecctl_int(avctx, VP9E_SET_COLOR_SPACE, vpx_cs); | |||
| 928 | return 0; | |||
| 929 | } | |||
| 930 | ||||
| 931 | #if VPX_ENCODER_ABI_VERSION(18 + (4 + (5)) + (7 + 5)) >= 11 | |||
| 932 | static void set_color_range(AVCodecContext *avctx) | |||
| 933 | { | |||
| 934 | enum vpx_color_range vpx_cr; | |||
| 935 | switch (avctx->color_range) { | |||
| 936 | case AVCOL_RANGE_UNSPECIFIED: | |||
| 937 | case AVCOL_RANGE_MPEG: vpx_cr = VPX_CR_STUDIO_RANGE; break; | |||
| 938 | case AVCOL_RANGE_JPEG: vpx_cr = VPX_CR_FULL_RANGE; break; | |||
| 939 | default: | |||
| 940 | av_log(avctx, AV_LOG_WARNING24, "Unsupported color range (%d)\n", | |||
| 941 | avctx->color_range); | |||
| 942 | return; | |||
| 943 | } | |||
| 944 | ||||
| 945 | codecctl_int(avctx, VP9E_SET_COLOR_RANGE, vpx_cr); | |||
| 946 | } | |||
| 947 | #endif | |||
| 948 | #endif | |||
| 949 | ||||
| 950 | /** | |||
| 951 | * Set the target bitrate to VPX library default. Also set CRF to 32 if needed. | |||
| 952 | */ | |||
| 953 | static void set_vp8_defaults(AVCodecContext *avctx, | |||
| 954 | struct vpx_codec_enc_cfg *enccfg) | |||
| 955 | { | |||
| 956 | VPxContext *ctx = avctx->priv_data; | |||
| 957 | av_assert0(!avctx->bit_rate)do { if (!(!avctx->bit_rate)) { av_log(((void*)0), 0, "Assertion %s failed at %s:%d\n" , "!avctx->bit_rate", "/root/firefox-clang/media/ffvpx/libavcodec/libvpxenc.c" , 957); abort(); } } while (0); | |||
| 958 | avctx->bit_rate = enccfg->rc_target_bitrate * 1000; | |||
| 959 | if (enccfg->rc_end_usage == VPX_CQ) { | |||
| 960 | av_log(avctx, AV_LOG_WARNING24, | |||
| 961 | "Bitrate not specified for constrained quality mode, using default of %dkbit/sec\n", | |||
| 962 | enccfg->rc_target_bitrate); | |||
| 963 | } else { | |||
| 964 | enccfg->rc_end_usage = VPX_CQ; | |||
| 965 | ctx->crf = 32; | |||
| 966 | av_log(avctx, AV_LOG_WARNING24, | |||
| 967 | "Neither bitrate nor constrained quality specified, using default CRF of %d and bitrate of %dkbit/sec\n", | |||
| 968 | ctx->crf, enccfg->rc_target_bitrate); | |||
| 969 | } | |||
| 970 | } | |||
| 971 | ||||
| 972 | ||||
| 973 | #if CONFIG_LIBVPX_VP9_ENCODER1 | |||
| 974 | /** | |||
| 975 | * Keep the target bitrate at 0 to engage constant quality mode. If CRF is not | |||
| 976 | * set, use 32. | |||
| 977 | */ | |||
| 978 | static void set_vp9_defaults(AVCodecContext *avctx, | |||
| 979 | struct vpx_codec_enc_cfg *enccfg) | |||
| 980 | { | |||
| 981 | VPxContext *ctx = avctx->priv_data; | |||
| 982 | av_assert0(!avctx->bit_rate)do { if (!(!avctx->bit_rate)) { av_log(((void*)0), 0, "Assertion %s failed at %s:%d\n" , "!avctx->bit_rate", "/root/firefox-clang/media/ffvpx/libavcodec/libvpxenc.c" , 982); abort(); } } while (0); | |||
| 983 | if (enccfg->rc_end_usage != VPX_Q && ctx->lossless < 0) { | |||
| 984 | enccfg->rc_end_usage = VPX_Q; | |||
| 985 | ctx->crf = 32; | |||
| 986 | av_log(avctx, AV_LOG_WARNING24, | |||
| 987 | "Neither bitrate nor constrained quality specified, using default CRF of %d\n", | |||
| 988 | ctx->crf); | |||
| 989 | } | |||
| 990 | } | |||
| 991 | #endif | |||
| 992 | ||||
| 993 | /** | |||
| 994 | * Called when the bitrate is not set. It sets appropriate default values for | |||
| 995 | * bitrate and CRF. | |||
| 996 | */ | |||
| 997 | static void set_vpx_defaults(AVCodecContext *avctx, | |||
| 998 | struct vpx_codec_enc_cfg *enccfg) | |||
| 999 | { | |||
| 1000 | av_assert0(!avctx->bit_rate)do { if (!(!avctx->bit_rate)) { av_log(((void*)0), 0, "Assertion %s failed at %s:%d\n" , "!avctx->bit_rate", "/root/firefox-clang/media/ffvpx/libavcodec/libvpxenc.c" , 1000); abort(); } } while (0); | |||
| 1001 | #if CONFIG_LIBVPX_VP9_ENCODER1 | |||
| 1002 | if (avctx->codec_id == AV_CODEC_ID_VP9) { | |||
| 1003 | set_vp9_defaults(avctx, enccfg); | |||
| 1004 | return; | |||
| 1005 | } | |||
| 1006 | #endif | |||
| 1007 | set_vp8_defaults(avctx, enccfg); | |||
| 1008 | } | |||
| 1009 | ||||
| 1010 | static av_cold__attribute__((cold)) int vpx_init(AVCodecContext *avctx, | |||
| 1011 | const struct vpx_codec_iface *iface) | |||
| 1012 | { | |||
| 1013 | VPxContext *ctx = avctx->priv_data; | |||
| 1014 | struct vpx_codec_enc_cfg enccfg = { 0 }; | |||
| 1015 | struct vpx_codec_enc_cfg enccfg_alpha; | |||
| 1016 | vpx_codec_flags_t flags = (avctx->flags & AV_CODEC_FLAG_PSNR(1 << 15)) ? VPX_CODEC_USE_PSNR0x10000 : 0; | |||
| ||||
| 1017 | AVCPBProperties *cpb_props; | |||
| 1018 | int res; | |||
| 1019 | vpx_img_fmt_t img_fmt = VPX_IMG_FMT_I420; | |||
| 1020 | #if CONFIG_LIBVPX_VP9_ENCODER1 | |||
| 1021 | vpx_codec_caps_t codec_caps = vpx_codec_get_caps(iface); | |||
| 1022 | vpx_svc_extra_cfg_t svc_params; | |||
| 1023 | #endif | |||
| 1024 | const AVDictionaryEntry* en = NULL((void*)0); | |||
| 1025 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt); | |||
| 1026 | ||||
| 1027 | av_log(avctx, AV_LOG_INFO32, "%s\n", vpx_codec_version_str()); | |||
| 1028 | av_log(avctx, AV_LOG_VERBOSE40, "%s\n", vpx_codec_build_config()); | |||
| 1029 | ||||
| 1030 | if (desc && (desc->flags & AV_PIX_FMT_FLAG_ALPHA(1 << 7))) { | |||
| 1031 | ctx->is_alpha = 1; | |||
| 1032 | if (avctx->pix_fmt != AV_PIX_FMT_YUVA420P && avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL-2) { | |||
| 1033 | av_log(avctx, AV_LOG_ERROR16, | |||
| 1034 | "Pixel format '%s' is not widely supported. " | |||
| 1035 | "Use -strict experimental to use it anyway, or use 'yuva420p' pixel format instead.\n", | |||
| 1036 | av_get_pix_fmt_name(avctx->pix_fmt)); | |||
| 1037 | return AVERROR(EINVAL)(-(22)); | |||
| 1038 | } | |||
| 1039 | } | |||
| 1040 | ||||
| 1041 | if ((res = vpx_codec_enc_config_default(iface, &enccfg, 0)) != VPX_CODEC_OK) { | |||
| 1042 | av_log(avctx, AV_LOG_ERROR16, "Failed to get config: %s\n", | |||
| 1043 | vpx_codec_err_to_string(res)); | |||
| 1044 | return AVERROR(EINVAL)(-(22)); | |||
| 1045 | } | |||
| 1046 | ||||
| 1047 | ctx->fifo = av_fifo_alloc2(1, sizeof(FrameData), AV_FIFO_FLAG_AUTO_GROW(1 << 0)); | |||
| 1048 | if (!ctx->fifo) | |||
| 1049 | return AVERROR(ENOMEM)(-(12)); | |||
| 1050 | ||||
| 1051 | #if CONFIG_LIBVPX_VP9_ENCODER1 | |||
| 1052 | if (avctx->codec_id == AV_CODEC_ID_VP9) { | |||
| 1053 | if (set_pix_fmt(avctx, codec_caps, &enccfg, &flags, &img_fmt)) | |||
| 1054 | return AVERROR(EINVAL)(-(22)); | |||
| 1055 | } | |||
| 1056 | #endif | |||
| 1057 | ||||
| 1058 | if(!avctx->bit_rate) | |||
| 1059 | if(avctx->rc_max_rate || avctx->rc_buffer_size || avctx->rc_initial_buffer_occupancy) { | |||
| 1060 | av_log( avctx, AV_LOG_ERROR16, "Rate control parameters set without a bitrate\n"); | |||
| 1061 | return AVERROR(EINVAL)(-(22)); | |||
| 1062 | } | |||
| 1063 | ||||
| 1064 | dump_enc_cfg(avctx, &enccfg, AV_LOG_DEBUG48); | |||
| 1065 | ||||
| 1066 | enccfg.g_w = avctx->width; | |||
| 1067 | enccfg.g_h = avctx->height; | |||
| 1068 | enccfg.g_timebase.num = avctx->time_base.num; | |||
| 1069 | enccfg.g_timebase.den = avctx->time_base.den; | |||
| 1070 | enccfg.g_threads = | |||
| 1071 | FFMIN(avctx->thread_count ? avctx->thread_count : av_cpu_count(), MAX_VPX_THREADS)((avctx->thread_count ? avctx->thread_count : av_cpu_count ()) > (64) ? (64) : (avctx->thread_count ? avctx->thread_count : av_cpu_count())); | |||
| 1072 | enccfg.g_lag_in_frames= ctx->lag_in_frames; | |||
| 1073 | ||||
| 1074 | if (avctx->flags & AV_CODEC_FLAG_PASS1(1 << 9)) | |||
| 1075 | enccfg.g_pass = VPX_RC_FIRST_PASS; | |||
| 1076 | else if (avctx->flags & AV_CODEC_FLAG_PASS2(1 << 10)) | |||
| 1077 | enccfg.g_pass = VPX_RC_LAST_PASS; | |||
| 1078 | else | |||
| 1079 | enccfg.g_pass = VPX_RC_ONE_PASS; | |||
| 1080 | ||||
| 1081 | if (avctx->rc_min_rate == avctx->rc_max_rate && | |||
| 1082 | avctx->rc_min_rate == avctx->bit_rate && avctx->bit_rate) { | |||
| 1083 | enccfg.rc_end_usage = VPX_CBR; | |||
| 1084 | } else if (ctx->crf >= 0) { | |||
| 1085 | enccfg.rc_end_usage = VPX_CQ; | |||
| 1086 | #if CONFIG_LIBVPX_VP9_ENCODER1 | |||
| 1087 | if (!avctx->bit_rate && avctx->codec_id == AV_CODEC_ID_VP9) | |||
| 1088 | enccfg.rc_end_usage = VPX_Q; | |||
| 1089 | #endif | |||
| 1090 | } | |||
| 1091 | ||||
| 1092 | if (avctx->bit_rate) { | |||
| 1093 | enccfg.rc_target_bitrate = av_rescale_rnd(avctx->bit_rate, 1, 1000, | |||
| 1094 | AV_ROUND_NEAR_INF); | |||
| 1095 | #if CONFIG_LIBVPX_VP9_ENCODER1 | |||
| 1096 | enccfg.ss_target_bitrate[0] = enccfg.rc_target_bitrate; | |||
| 1097 | #endif | |||
| 1098 | } else { | |||
| 1099 | // Set bitrate to default value. Also sets CRF to default if needed. | |||
| 1100 | set_vpx_defaults(avctx, &enccfg); | |||
| 1101 | } | |||
| 1102 | ||||
| 1103 | if (avctx->codec_id == AV_CODEC_ID_VP9 && ctx->lossless == 1) { | |||
| 1104 | enccfg.rc_min_quantizer = | |||
| 1105 | enccfg.rc_max_quantizer = 0; | |||
| 1106 | } else { | |||
| 1107 | if (avctx->qmin >= 0) | |||
| 1108 | enccfg.rc_min_quantizer = avctx->qmin; | |||
| 1109 | if (avctx->qmax >= 0) | |||
| 1110 | enccfg.rc_max_quantizer = avctx->qmax; | |||
| 1111 | } | |||
| 1112 | ||||
| 1113 | if (enccfg.rc_end_usage
| |||
| 1114 | #if CONFIG_LIBVPX_VP9_ENCODER1 | |||
| 1115 | || enccfg.rc_end_usage == VPX_Q | |||
| 1116 | #endif | |||
| 1117 | ) { | |||
| 1118 | if (ctx->crf < enccfg.rc_min_quantizer || ctx->crf > enccfg.rc_max_quantizer) { | |||
| 1119 | av_log(avctx, AV_LOG_ERROR16, | |||
| 1120 | "CQ level %d must be between minimum and maximum quantizer value (%d-%d)\n", | |||
| 1121 | ctx->crf, enccfg.rc_min_quantizer, enccfg.rc_max_quantizer); | |||
| 1122 | return AVERROR(EINVAL)(-(22)); | |||
| 1123 | } | |||
| 1124 | } | |||
| 1125 | ||||
| 1126 | enccfg.rc_dropframe_thresh = ctx->drop_threshold; | |||
| 1127 | ||||
| 1128 | //0-100 (0 => CBR, 100 => VBR) | |||
| 1129 | enccfg.rc_2pass_vbr_bias_pct = lrint(avctx->qcompress * 100); | |||
| 1130 | if (avctx->bit_rate) | |||
| 1131 | enccfg.rc_2pass_vbr_minsection_pct = | |||
| 1132 | avctx->rc_min_rate * 100LL / avctx->bit_rate; | |||
| 1133 | if (avctx->rc_max_rate) | |||
| 1134 | enccfg.rc_2pass_vbr_maxsection_pct = | |||
| 1135 | avctx->rc_max_rate * 100LL / avctx->bit_rate; | |||
| 1136 | #if CONFIG_LIBVPX_VP9_ENCODER1 | |||
| 1137 | if (avctx->codec_id
| |||
| 1138 | #if VPX_ENCODER_ABI_VERSION(18 + (4 + (5)) + (7 + 5)) >= 14 | |||
| 1139 | if (ctx->corpus_complexity >= 0) | |||
| 1140 | enccfg.rc_2pass_vbr_corpus_complexity = ctx->corpus_complexity; | |||
| 1141 | #endif | |||
| 1142 | } | |||
| 1143 | #endif | |||
| 1144 | ||||
| 1145 | if (avctx->rc_buffer_size) | |||
| 1146 | enccfg.rc_buf_sz = | |||
| 1147 | avctx->rc_buffer_size * 1000LL / avctx->bit_rate; | |||
| ||||
| 1148 | if (avctx->rc_initial_buffer_occupancy) | |||
| 1149 | enccfg.rc_buf_initial_sz = | |||
| 1150 | avctx->rc_initial_buffer_occupancy * 1000LL / avctx->bit_rate; | |||
| 1151 | enccfg.rc_buf_optimal_sz = enccfg.rc_buf_sz * 5 / 6; | |||
| 1152 | if (ctx->rc_undershoot_pct >= 0) | |||
| 1153 | enccfg.rc_undershoot_pct = ctx->rc_undershoot_pct; | |||
| 1154 | if (ctx->rc_overshoot_pct >= 0) | |||
| 1155 | enccfg.rc_overshoot_pct = ctx->rc_overshoot_pct; | |||
| 1156 | ||||
| 1157 | //_enc_init() will balk if kf_min_dist differs from max w/VPX_KF_AUTO | |||
| 1158 | if (avctx->keyint_min >= 0 && avctx->keyint_min == avctx->gop_size) | |||
| 1159 | enccfg.kf_min_dist = avctx->keyint_min; | |||
| 1160 | if (avctx->gop_size >= 0) | |||
| 1161 | enccfg.kf_max_dist = avctx->gop_size; | |||
| 1162 | ||||
| 1163 | if (enccfg.g_pass == VPX_RC_FIRST_PASS) | |||
| 1164 | enccfg.g_lag_in_frames = 0; | |||
| 1165 | else if (enccfg.g_pass == VPX_RC_LAST_PASS) { | |||
| 1166 | int decode_size, ret; | |||
| 1167 | ||||
| 1168 | if (!avctx->stats_in) { | |||
| 1169 | av_log(avctx, AV_LOG_ERROR16, "No stats file for second pass\n"); | |||
| 1170 | return AVERROR_INVALIDDATA(-(int)(('I') | (('N') << 8) | (('D') << 16) | (( unsigned)('A') << 24))); | |||
| 1171 | } | |||
| 1172 | ||||
| 1173 | ctx->twopass_stats.sz = strlen(avctx->stats_in) * 3 / 4; | |||
| 1174 | ret = av_reallocp(&ctx->twopass_stats.buf, ctx->twopass_stats.sz); | |||
| 1175 | if (ret < 0) { | |||
| 1176 | av_log(avctx, AV_LOG_ERROR16, | |||
| 1177 | "Stat buffer alloc (%zu bytes) failed\n", | |||
| 1178 | ctx->twopass_stats.sz); | |||
| 1179 | ctx->twopass_stats.sz = 0; | |||
| 1180 | return ret; | |||
| 1181 | } | |||
| 1182 | decode_size = av_base64_decode(ctx->twopass_stats.buf, avctx->stats_in, | |||
| 1183 | ctx->twopass_stats.sz); | |||
| 1184 | if (decode_size < 0) { | |||
| 1185 | av_log(avctx, AV_LOG_ERROR16, "Stat buffer decode failed\n"); | |||
| 1186 | return AVERROR_INVALIDDATA(-(int)(('I') | (('N') << 8) | (('D') << 16) | (( unsigned)('A') << 24))); | |||
| 1187 | } | |||
| 1188 | ||||
| 1189 | ctx->twopass_stats.sz = decode_size; | |||
| 1190 | enccfg.rc_twopass_stats_in = ctx->twopass_stats; | |||
| 1191 | } | |||
| 1192 | ||||
| 1193 | /* 0-3: For non-zero values the encoder increasingly optimizes for reduced | |||
| 1194 | complexity playback on low powered devices at the expense of encode | |||
| 1195 | quality. */ | |||
| 1196 | if (avctx->profile != AV_PROFILE_UNKNOWN-99) | |||
| 1197 | enccfg.g_profile = avctx->profile; | |||
| 1198 | ||||
| 1199 | enccfg.g_error_resilient = ctx->error_resilient || ctx->flags & VP8F_ERROR_RESILIENT0x00000001; | |||
| 1200 | ||||
| 1201 | while ((en = av_dict_iterate(ctx->vpx_ts_parameters, en))) { | |||
| 1202 | if (vpx_ts_param_parse(ctx, &enccfg, en->key, en->value, avctx->codec_id) < 0) | |||
| 1203 | av_log(avctx, AV_LOG_WARNING24, | |||
| 1204 | "Error parsing option '%s = %s'.\n", | |||
| 1205 | en->key, en->value); | |||
| 1206 | } | |||
| 1207 | ||||
| 1208 | /* Construct Encoder Context */ | |||
| 1209 | res = vpx_codec_enc_init(&ctx->encoder, iface, &enccfg, flags)vpx_codec_enc_init_ver(&ctx->encoder, iface, &enccfg , flags, (18 + (4 + (5)) + (7 + 5))); | |||
| 1210 | if (res != VPX_CODEC_OK) { | |||
| 1211 | dump_enc_cfg(avctx, &enccfg, AV_LOG_WARNING24); | |||
| 1212 | log_encoder_error(avctx, &ctx->encoder, "Failed to initialize encoder"); | |||
| 1213 | return AVERROR(EINVAL)(-(22)); | |||
| 1214 | } | |||
| 1215 | dump_enc_cfg(avctx, &enccfg, AV_LOG_DEBUG48); | |||
| 1216 | ||||
| 1217 | #if CONFIG_LIBVPX_VP9_ENCODER1 | |||
| 1218 | if (avctx->codec_id == AV_CODEC_ID_VP9 && enccfg.ts_number_layers > 1) { | |||
| 1219 | memset(&svc_params, 0, sizeof(svc_params)); | |||
| 1220 | for (int i = 0; i < enccfg.ts_number_layers; ++i) { | |||
| 1221 | svc_params.max_quantizers[i] = enccfg.rc_max_quantizer; | |||
| 1222 | svc_params.min_quantizers[i] = enccfg.rc_min_quantizer; | |||
| 1223 | } | |||
| 1224 | svc_params.scaling_factor_num[0] = enccfg.g_h; | |||
| 1225 | svc_params.scaling_factor_den[0] = enccfg.g_h; | |||
| 1226 | #if VPX_ENCODER_ABI_VERSION(18 + (4 + (5)) + (7 + 5)) >= 12 | |||
| 1227 | codecctl_int(avctx, VP9E_SET_SVC, 1); | |||
| 1228 | codecctl_intp(avctx, VP9E_SET_SVC_PARAMETERS, (int *)&svc_params); | |||
| 1229 | #endif | |||
| 1230 | } | |||
| 1231 | #endif | |||
| 1232 | if (ctx->is_alpha) { | |||
| 1233 | enccfg_alpha = enccfg; | |||
| 1234 | enccfg_alpha.g_profile = (flags & VPX_CODEC_USE_HIGHBITDEPTH0x40000) ? 2 : 0; | |||
| 1235 | res = vpx_codec_enc_init(&ctx->encoder_alpha, iface, &enccfg_alpha, flags)vpx_codec_enc_init_ver(&ctx->encoder_alpha, iface, & enccfg_alpha, flags, (18 + (4 + (5)) + (7 + 5))); | |||
| 1236 | if (res != VPX_CODEC_OK) { | |||
| 1237 | log_encoder_error(avctx, &ctx->encoder_alpha, "Failed to initialize alpha encoder"); | |||
| 1238 | return AVERROR(EINVAL)(-(22)); | |||
| 1239 | } | |||
| 1240 | } | |||
| 1241 | ||||
| 1242 | //codec control failures are currently treated only as warnings | |||
| 1243 | av_log(avctx, AV_LOG_DEBUG48, "vpx_codec_control\n"); | |||
| 1244 | codecctl_int(avctx, VP8E_SET_CPUUSED, ctx->cpu_used); | |||
| 1245 | if (ctx->flags & VP8F_AUTO_ALT_REF0x00000002) | |||
| 1246 | ctx->auto_alt_ref = 1; | |||
| 1247 | if (ctx->auto_alt_ref >= 0) | |||
| 1248 | codecctl_int(avctx, VP8E_SET_ENABLEAUTOALTREF, | |||
| 1249 | avctx->codec_id == AV_CODEC_ID_VP8 ? !!ctx->auto_alt_ref : ctx->auto_alt_ref); | |||
| 1250 | if (ctx->arnr_max_frames >= 0) | |||
| 1251 | codecctl_int(avctx, VP8E_SET_ARNR_MAXFRAMES, ctx->arnr_max_frames); | |||
| 1252 | if (ctx->arnr_strength >= 0) | |||
| 1253 | codecctl_int(avctx, VP8E_SET_ARNR_STRENGTH, ctx->arnr_strength); | |||
| 1254 | if (ctx->arnr_type >= 0) | |||
| 1255 | codecctl_int(avctx, VP8E_SET_ARNR_TYPE, ctx->arnr_type); | |||
| 1256 | if (ctx->tune >= 0) | |||
| 1257 | codecctl_int(avctx, VP8E_SET_TUNING, ctx->tune); | |||
| 1258 | ||||
| 1259 | if (ctx->auto_alt_ref && ctx->is_alpha && avctx->codec_id == AV_CODEC_ID_VP8) { | |||
| 1260 | av_log(avctx, AV_LOG_ERROR16, "Transparency encoding with auto_alt_ref does not work\n"); | |||
| 1261 | return AVERROR(EINVAL)(-(22)); | |||
| 1262 | } | |||
| 1263 | ||||
| 1264 | if (ctx->sharpness >= 0) | |||
| 1265 | codecctl_int(avctx, VP8E_SET_SHARPNESS, ctx->sharpness); | |||
| 1266 | ||||
| 1267 | if (CONFIG_LIBVPX_VP8_ENCODER1 && avctx->codec_id == AV_CODEC_ID_VP8) { | |||
| 1268 | codecctl_int(avctx, VP8E_SET_NOISE_SENSITIVITY, ctx->noise_sensitivity); | |||
| 1269 | codecctl_int(avctx, VP8E_SET_TOKEN_PARTITIONS, av_log2(avctx->slices)(31 - __builtin_clz((avctx->slices)|1))); | |||
| 1270 | } | |||
| 1271 | codecctl_int(avctx, VP8E_SET_STATIC_THRESHOLD, ctx->static_thresh); | |||
| 1272 | if (ctx->crf >= 0) | |||
| 1273 | codecctl_int(avctx, VP8E_SET_CQ_LEVEL, ctx->crf); | |||
| 1274 | if (ctx->max_intra_rate >= 0) | |||
| 1275 | codecctl_int(avctx, VP8E_SET_MAX_INTRA_BITRATE_PCT, ctx->max_intra_rate); | |||
| 1276 | ||||
| 1277 | #if CONFIG_LIBVPX_VP9_ENCODER1 | |||
| 1278 | if (avctx->codec_id == AV_CODEC_ID_VP9) { | |||
| 1279 | if (ctx->lossless >= 0) | |||
| 1280 | codecctl_int(avctx, VP9E_SET_LOSSLESS, ctx->lossless); | |||
| 1281 | if (ctx->tile_columns >= 0) | |||
| 1282 | codecctl_int(avctx, VP9E_SET_TILE_COLUMNS, ctx->tile_columns); | |||
| 1283 | if (ctx->tile_rows >= 0) | |||
| 1284 | codecctl_int(avctx, VP9E_SET_TILE_ROWS, ctx->tile_rows); | |||
| 1285 | if (ctx->frame_parallel >= 0) | |||
| 1286 | codecctl_int(avctx, VP9E_SET_FRAME_PARALLEL_DECODING, ctx->frame_parallel); | |||
| 1287 | if (ctx->aq_mode >= 0) | |||
| 1288 | codecctl_int(avctx, VP9E_SET_AQ_MODE, ctx->aq_mode); | |||
| 1289 | res = set_colorspace(avctx); | |||
| 1290 | if (res < 0) | |||
| 1291 | return res; | |||
| 1292 | #if VPX_ENCODER_ABI_VERSION(18 + (4 + (5)) + (7 + 5)) >= 11 | |||
| 1293 | set_color_range(avctx); | |||
| 1294 | #endif | |||
| 1295 | #if VPX_ENCODER_ABI_VERSION(18 + (4 + (5)) + (7 + 5)) >= 12 | |||
| 1296 | codecctl_int(avctx, VP9E_SET_TARGET_LEVEL, ctx->level < 0 ? 255 : lrint(ctx->level * 10)); | |||
| 1297 | #endif | |||
| 1298 | #ifdef VPX_CTRL_VP9E_SET_ROW_MT | |||
| 1299 | if (ctx->row_mt >= 0) | |||
| 1300 | codecctl_int(avctx, VP9E_SET_ROW_MT, ctx->row_mt); | |||
| 1301 | #endif | |||
| 1302 | #ifdef VPX_CTRL_VP9E_SET_TUNE_CONTENT | |||
| 1303 | if (ctx->tune_content >= 0) | |||
| 1304 | codecctl_int(avctx, VP9E_SET_TUNE_CONTENT, ctx->tune_content); | |||
| 1305 | #endif | |||
| 1306 | #ifdef VPX_CTRL_VP9E_SET_TPL | |||
| 1307 | if (ctx->tpl_model >= 0) | |||
| 1308 | codecctl_int(avctx, VP9E_SET_TPL, ctx->tpl_model); | |||
| 1309 | #endif | |||
| 1310 | #ifdef VPX_CTRL_VP9E_SET_MIN_GF_INTERVAL | |||
| 1311 | if (ctx->min_gf_interval >= 0) | |||
| 1312 | codecctl_int(avctx, VP9E_SET_MIN_GF_INTERVAL, ctx->min_gf_interval); | |||
| 1313 | #endif | |||
| 1314 | } | |||
| 1315 | #endif | |||
| 1316 | if (avctx->codec_id == AV_CODEC_ID_VP8 && ctx->screen_content_mode >= 0) { | |||
| 1317 | if (ctx->screen_content_mode == 2 && ctx->is_alpha) { | |||
| 1318 | av_log(avctx, AV_LOG_ERROR16, | |||
| 1319 | "Transparency encoding with screen mode with aggressive rate control not supported\n"); | |||
| 1320 | return AVERROR(EINVAL)(-(22)); | |||
| 1321 | } | |||
| 1322 | codecctl_int(avctx, VP8E_SET_SCREEN_CONTENT_MODE, ctx->screen_content_mode); | |||
| 1323 | } | |||
| 1324 | ||||
| 1325 | av_log(avctx, AV_LOG_DEBUG48, "Using deadline: %d\n", ctx->deadline); | |||
| 1326 | ||||
| 1327 | //provide dummy value to initialize wrapper, values will be updated each _encode() | |||
| 1328 | vpx_img_wrap(&ctx->rawimg, img_fmt, avctx->width, avctx->height, 1, | |||
| 1329 | (unsigned char*)1); | |||
| 1330 | #if CONFIG_LIBVPX_VP9_ENCODER1 | |||
| 1331 | if (avctx->codec_id == AV_CODEC_ID_VP9 && (codec_caps & VPX_CODEC_CAP_HIGHBITDEPTH0x4)) | |||
| 1332 | ctx->rawimg.bit_depth = enccfg.g_bit_depth; | |||
| 1333 | #endif | |||
| 1334 | ||||
| 1335 | cpb_props = ff_encode_add_cpb_side_data(avctx); | |||
| 1336 | if (!cpb_props) | |||
| 1337 | return AVERROR(ENOMEM)(-(12)); | |||
| 1338 | ||||
| 1339 | if (enccfg.rc_end_usage == VPX_CBR || | |||
| 1340 | enccfg.g_pass != VPX_RC_ONE_PASS) { | |||
| 1341 | cpb_props->max_bitrate = avctx->rc_max_rate; | |||
| 1342 | cpb_props->min_bitrate = avctx->rc_min_rate; | |||
| 1343 | cpb_props->avg_bitrate = avctx->bit_rate; | |||
| 1344 | } | |||
| 1345 | cpb_props->buffer_size = avctx->rc_buffer_size; | |||
| 1346 | ||||
| 1347 | return 0; | |||
| 1348 | } | |||
| 1349 | ||||
| 1350 | static inline void cx_pktcpy(struct FrameListData *dst, | |||
| 1351 | const struct vpx_codec_cx_pkt *src, | |||
| 1352 | VPxContext *ctx) | |||
| 1353 | { | |||
| 1354 | dst->pts = src->data.frame.pts; | |||
| 1355 | dst->flags = src->data.frame.flags; | |||
| 1356 | dst->sz = src->data.frame.sz; | |||
| 1357 | dst->buf = src->data.frame.buf; | |||
| 1358 | dst->have_sse = 0; | |||
| 1359 | /* For alt-ref frame, don't store PSNR */ | |||
| 1360 | if (!(dst->flags & VPX_FRAME_IS_INVISIBLE0x4u)) { | |||
| 1361 | dst->have_sse = ctx->have_sse; | |||
| 1362 | if (ctx->have_sse) { | |||
| 1363 | /* associate last-seen SSE to the frame. */ | |||
| 1364 | /* Transfers ownership from ctx to dst. */ | |||
| 1365 | /* WARNING! This makes the assumption that PSNR_PKT comes | |||
| 1366 | just before the frame it refers to! */ | |||
| 1367 | memcpy(dst->sse, ctx->sse, sizeof(dst->sse)); | |||
| 1368 | ctx->have_sse = 0; | |||
| 1369 | } | |||
| 1370 | } | |||
| 1371 | } | |||
| 1372 | ||||
| 1373 | /** | |||
| 1374 | * Store coded frame information in format suitable for return from encode2(). | |||
| 1375 | * | |||
| 1376 | * Write information from @a cx_frame to @a pkt | |||
| 1377 | * @return packet data size on success | |||
| 1378 | * @return a negative AVERROR on error | |||
| 1379 | */ | |||
| 1380 | static int storeframe(AVCodecContext *avctx, struct FrameListData *cx_frame, | |||
| 1381 | struct FrameListData *alpha_cx_frame, AVPacket *pkt) | |||
| 1382 | { | |||
| 1383 | VPxContext *ctx = avctx->priv_data; | |||
| 1384 | int ret = ff_get_encode_buffer(avctx, pkt, cx_frame->sz, 0); | |||
| 1385 | uint8_t *side_data; | |||
| 1386 | enum AVPictureType pict_type; | |||
| 1387 | int quality; | |||
| 1388 | ||||
| 1389 | if (ret < 0) | |||
| 1390 | return ret; | |||
| 1391 | ||||
| 1392 | memcpy(pkt->data, cx_frame->buf, pkt->size); | |||
| 1393 | pkt->pts = pkt->dts = cx_frame->pts; | |||
| 1394 | ||||
| 1395 | if (!!(cx_frame->flags & VPX_FRAME_IS_KEY0x1u)) { | |||
| 1396 | pict_type = AV_PICTURE_TYPE_I; | |||
| 1397 | pkt->flags |= AV_PKT_FLAG_KEY0x0001; | |||
| 1398 | } else { | |||
| 1399 | pict_type = AV_PICTURE_TYPE_P; | |||
| 1400 | } | |||
| 1401 | ||||
| 1402 | ret = vpx_codec_control(&ctx->encoder, VP8E_GET_LAST_QUANTIZER_64, &quality)vpx_codec_control_(&ctx->encoder, VP8E_GET_LAST_QUANTIZER_64 , &quality); | |||
| 1403 | if (ret != VPX_CODEC_OK) | |||
| 1404 | quality = 0; | |||
| 1405 | ff_encode_add_stats_side_data(pkt, quality * FF_QP2LAMBDA118, cx_frame->sse + 1, | |||
| 1406 | cx_frame->have_sse ? 3 : 0, pict_type); | |||
| 1407 | ||||
| 1408 | if (cx_frame->have_sse) { | |||
| 1409 | /* Beware of the Y/U/V/all order! */ | |||
| 1410 | for (int i = 0; i < 3; ++i) | |||
| 1411 | avctx->error[i] += cx_frame->sse[i + 1]; | |||
| 1412 | cx_frame->have_sse = 0; | |||
| 1413 | } | |||
| 1414 | if (alpha_cx_frame) { | |||
| 1415 | side_data = av_packet_new_side_data(pkt, | |||
| 1416 | AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL, | |||
| 1417 | alpha_cx_frame->sz + 8); | |||
| 1418 | if (!side_data) { | |||
| 1419 | av_packet_unref(pkt); | |||
| 1420 | return AVERROR(ENOMEM)(-(12)); | |||
| 1421 | } | |||
| 1422 | AV_WB64(side_data, 1)((((union unaligned_64 *) (side_data))->l) = (av_bswap64(1 ))); | |||
| 1423 | memcpy(side_data + 8, alpha_cx_frame->buf, alpha_cx_frame->sz); | |||
| 1424 | } | |||
| 1425 | ret = frame_data_apply(avctx, ctx->fifo, pkt); | |||
| 1426 | if (ret < 0) | |||
| 1427 | return ret; | |||
| 1428 | ||||
| 1429 | return pkt->size; | |||
| 1430 | } | |||
| 1431 | ||||
| 1432 | /** | |||
| 1433 | * Queue multiple output frames from the encoder, returning the front-most. | |||
| 1434 | * In cases where vpx_codec_get_cx_data() returns more than 1 frame append | |||
| 1435 | * the frame queue. Return the head frame if available. | |||
| 1436 | * @return Stored frame size | |||
| 1437 | * @return AVERROR(EINVAL) on output size error | |||
| 1438 | * @return AVERROR(ENOMEM) on coded frame queue data allocation error | |||
| 1439 | */ | |||
| 1440 | static int queue_frames(AVCodecContext *avctx, struct vpx_codec_ctx *encoder, | |||
| 1441 | struct FrameListData **frame_list, AVPacket *pkt_out) | |||
| 1442 | { | |||
| 1443 | VPxContext *ctx = avctx->priv_data; | |||
| 1444 | const struct vpx_codec_cx_pkt *pkt; | |||
| 1445 | const void *iter = NULL((void*)0); | |||
| 1446 | int size = 0; | |||
| 1447 | ||||
| 1448 | if (!ctx->is_alpha && *frame_list) { | |||
| 1449 | struct FrameListData *cx_frame = *frame_list; | |||
| 1450 | /* return the leading frame if we've already begun queueing */ | |||
| 1451 | size = storeframe(avctx, cx_frame, NULL((void*)0), pkt_out); | |||
| 1452 | if (size < 0) | |||
| 1453 | return size; | |||
| 1454 | *frame_list = cx_frame->next; | |||
| 1455 | free_coded_frame(cx_frame); | |||
| 1456 | } | |||
| 1457 | ||||
| 1458 | /* consume all available output from the encoder before returning. buffers | |||
| 1459 | are only good through the next vpx_codec call */ | |||
| 1460 | while (pkt = vpx_codec_get_cx_data(encoder, &iter)) { | |||
| 1461 | switch (pkt->kind) { | |||
| 1462 | case VPX_CODEC_CX_FRAME_PKT: | |||
| 1463 | if (!ctx->is_alpha && !size) { | |||
| 1464 | struct FrameListData cx_frame; | |||
| 1465 | ||||
| 1466 | /* avoid storing the frame when the list is empty and we haven't yet | |||
| 1467 | provided a frame for output */ | |||
| 1468 | 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/libvpxenc.c", 1468 ); abort(); } } while (0); | |||
| 1469 | cx_pktcpy(&cx_frame, pkt, ctx); | |||
| 1470 | size = storeframe(avctx, &cx_frame, NULL((void*)0), pkt_out); | |||
| 1471 | if (size < 0) | |||
| 1472 | return size; | |||
| 1473 | } else { | |||
| 1474 | struct FrameListData *cx_frame = av_malloc(sizeof(*cx_frame)); | |||
| 1475 | ||||
| 1476 | if (!cx_frame) { | |||
| 1477 | av_log(avctx, AV_LOG_ERROR16, | |||
| 1478 | "Frame queue element alloc failed\n"); | |||
| 1479 | return AVERROR(ENOMEM)(-(12)); | |||
| 1480 | } | |||
| 1481 | cx_pktcpy(cx_frame, pkt, ctx); | |||
| 1482 | cx_frame->buf = av_malloc(cx_frame->sz); | |||
| 1483 | ||||
| 1484 | if (!cx_frame->buf) { | |||
| 1485 | av_log(avctx, AV_LOG_ERROR16, | |||
| 1486 | "Data buffer alloc (%zu bytes) failed\n", | |||
| 1487 | cx_frame->sz); | |||
| 1488 | av_freep(&cx_frame); | |||
| 1489 | return AVERROR(ENOMEM)(-(12)); | |||
| 1490 | } | |||
| 1491 | memcpy(cx_frame->buf, pkt->data.frame.buf, pkt->data.frame.sz); | |||
| 1492 | coded_frame_add(frame_list, cx_frame); | |||
| 1493 | } | |||
| 1494 | break; | |||
| 1495 | case VPX_CODEC_STATS_PKT: { | |||
| 1496 | struct vpx_fixed_buf *stats = &ctx->twopass_stats; | |||
| 1497 | uint8_t *tmp; | |||
| 1498 | if (!pkt_out) | |||
| 1499 | break; | |||
| 1500 | tmp = av_fast_realloc(stats->buf, | |||
| 1501 | &ctx->twopass_stats_size, | |||
| 1502 | stats->sz + | |||
| 1503 | pkt->data.twopass_stats.sz); | |||
| 1504 | if (!tmp) { | |||
| 1505 | av_freep(&stats->buf); | |||
| 1506 | stats->sz = 0; | |||
| 1507 | av_log(avctx, AV_LOG_ERROR16, "Stat buffer realloc failed\n"); | |||
| 1508 | return AVERROR(ENOMEM)(-(12)); | |||
| 1509 | } | |||
| 1510 | stats->buf = tmp; | |||
| 1511 | memcpy((uint8_t*)stats->buf + stats->sz, | |||
| 1512 | pkt->data.twopass_stats.buf, pkt->data.twopass_stats.sz); | |||
| 1513 | stats->sz += pkt->data.twopass_stats.sz; | |||
| 1514 | break; | |||
| 1515 | } | |||
| 1516 | case VPX_CODEC_PSNR_PKT: | |||
| 1517 | if (!pkt_out) | |||
| 1518 | break; | |||
| 1519 | 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/libvpxenc.c" , 1519); abort(); } } while (0); | |||
| 1520 | ctx->sse[0] = pkt->data.psnr.sse[0]; | |||
| 1521 | ctx->sse[1] = pkt->data.psnr.sse[1]; | |||
| 1522 | ctx->sse[2] = pkt->data.psnr.sse[2]; | |||
| 1523 | ctx->sse[3] = pkt->data.psnr.sse[3]; | |||
| 1524 | ctx->have_sse = 1; | |||
| 1525 | break; | |||
| 1526 | case VPX_CODEC_CUSTOM_PKT: | |||
| 1527 | //ignore unsupported/unrecognized packet types | |||
| 1528 | break; | |||
| 1529 | } | |||
| 1530 | } | |||
| 1531 | ||||
| 1532 | return size; | |||
| 1533 | } | |||
| 1534 | ||||
| 1535 | static int set_roi_map(AVCodecContext *avctx, const AVFrameSideData *sd, int frame_width, int frame_height, | |||
| 1536 | vpx_roi_map_t *roi_map, int block_size, int segment_cnt) | |||
| 1537 | { | |||
| 1538 | /** | |||
| 1539 | * range of vpx_roi_map_t.delta_q[i] is [-63, 63] | |||
| 1540 | */ | |||
| 1541 | #define MAX_DELTA_Q63 63 | |||
| 1542 | ||||
| 1543 | const AVRegionOfInterest *roi = NULL((void*)0); | |||
| 1544 | int nb_rois; | |||
| 1545 | uint32_t self_size; | |||
| 1546 | int segment_id; | |||
| 1547 | ||||
| 1548 | /* record the mapping from delta_q to "segment id + 1" in segment_mapping[]. | |||
| 1549 | * the range of delta_q is [-MAX_DELTA_Q, MAX_DELTA_Q], | |||
| 1550 | * and its corresponding array index is [0, 2 * MAX_DELTA_Q], | |||
| 1551 | * and so the length of the mapping array is 2 * MAX_DELTA_Q + 1. | |||
| 1552 | * "segment id + 1", so we can say there's no mapping if the value of array element is zero. | |||
| 1553 | */ | |||
| 1554 | int segment_mapping[2 * MAX_DELTA_Q63 + 1] = { 0 }; | |||
| 1555 | ||||
| 1556 | memset(roi_map, 0, sizeof(*roi_map)); | |||
| 1557 | ||||
| 1558 | /* segment id 0 in roi_map is reserved for the areas not covered by AVRegionOfInterest. | |||
| 1559 | * segment id 0 in roi_map is also for the areas with AVRegionOfInterest.qoffset near 0. | |||
| 1560 | * (delta_q of segment id 0 is 0). | |||
| 1561 | */ | |||
| 1562 | segment_mapping[MAX_DELTA_Q63] = 1; | |||
| 1563 | segment_id = 1; | |||
| 1564 | ||||
| 1565 | roi = (const AVRegionOfInterest*)sd->data; | |||
| 1566 | self_size = roi->self_size; | |||
| 1567 | if (!self_size || sd->size % self_size) { | |||
| 1568 | av_log(avctx, AV_LOG_ERROR16, "Invalid AVRegionOfInterest.self_size.\n"); | |||
| 1569 | return AVERROR(EINVAL)(-(22)); | |||
| 1570 | } | |||
| 1571 | nb_rois = sd->size / self_size; | |||
| 1572 | ||||
| 1573 | /* This list must be iterated from zero because regions are | |||
| 1574 | * defined in order of decreasing importance. So discard less | |||
| 1575 | * important areas if they exceed the segment count. | |||
| 1576 | */ | |||
| 1577 | for (int i = 0; i < nb_rois; i++) { | |||
| 1578 | int delta_q; | |||
| 1579 | int mapping_index; | |||
| 1580 | ||||
| 1581 | roi = (const AVRegionOfInterest*)(sd->data + self_size * i); | |||
| 1582 | if (!roi->qoffset.den) { | |||
| 1583 | av_log(avctx, AV_LOG_ERROR16, "AVRegionOfInterest.qoffset.den must not be zero.\n"); | |||
| 1584 | return AVERROR(EINVAL)(-(22)); | |||
| 1585 | } | |||
| 1586 | ||||
| 1587 | delta_q = (int)(roi->qoffset.num * 1.0f / roi->qoffset.den * MAX_DELTA_Q63); | |||
| 1588 | delta_q = av_clipav_clip_c(delta_q, -MAX_DELTA_Q63, MAX_DELTA_Q63); | |||
| 1589 | ||||
| 1590 | mapping_index = delta_q + MAX_DELTA_Q63; | |||
| 1591 | if (!segment_mapping[mapping_index]) { | |||
| 1592 | if (segment_id == segment_cnt) { | |||
| 1593 | av_log(avctx, AV_LOG_WARNING24, | |||
| 1594 | "ROI only supports %d segments (and segment 0 is reserved for non-ROIs), skipping the left ones.\n", | |||
| 1595 | segment_cnt); | |||
| 1596 | break; | |||
| 1597 | } | |||
| 1598 | ||||
| 1599 | segment_mapping[mapping_index] = segment_id + 1; | |||
| 1600 | roi_map->delta_q[segment_id] = delta_q; | |||
| 1601 | segment_id++; | |||
| 1602 | } | |||
| 1603 | } | |||
| 1604 | ||||
| 1605 | roi_map->rows = (frame_height + block_size - 1) / block_size; | |||
| 1606 | roi_map->cols = (frame_width + block_size - 1) / block_size; | |||
| 1607 | roi_map->roi_map = av_calloc(roi_map->rows * roi_map->cols, sizeof(*roi_map->roi_map)); | |||
| 1608 | if (!roi_map->roi_map) { | |||
| 1609 | av_log(avctx, AV_LOG_ERROR16, "roi_map alloc failed.\n"); | |||
| 1610 | return AVERROR(ENOMEM)(-(12)); | |||
| 1611 | } | |||
| 1612 | ||||
| 1613 | /* This list must be iterated in reverse, so for the case that | |||
| 1614 | * two regions are overlapping, the more important area takes effect. | |||
| 1615 | */ | |||
| 1616 | for (int i = nb_rois - 1; i >= 0; i--) { | |||
| 1617 | int delta_q; | |||
| 1618 | int mapping_value; | |||
| 1619 | int starty, endy, startx, endx; | |||
| 1620 | ||||
| 1621 | roi = (const AVRegionOfInterest*)(sd->data + self_size * i); | |||
| 1622 | ||||
| 1623 | starty = av_clipav_clip_c(roi->top / block_size, 0, roi_map->rows); | |||
| 1624 | endy = av_clipav_clip_c((roi->bottom + block_size - 1) / block_size, 0, roi_map->rows); | |||
| 1625 | startx = av_clipav_clip_c(roi->left / block_size, 0, roi_map->cols); | |||
| 1626 | endx = av_clipav_clip_c((roi->right + block_size - 1) / block_size, 0, roi_map->cols); | |||
| 1627 | ||||
| 1628 | delta_q = (int)(roi->qoffset.num * 1.0f / roi->qoffset.den * MAX_DELTA_Q63); | |||
| 1629 | delta_q = av_clipav_clip_c(delta_q, -MAX_DELTA_Q63, MAX_DELTA_Q63); | |||
| 1630 | ||||
| 1631 | mapping_value = segment_mapping[delta_q + MAX_DELTA_Q63]; | |||
| 1632 | if (mapping_value) { | |||
| 1633 | for (int y = starty; y < endy; y++) | |||
| 1634 | for (int x = startx; x < endx; x++) | |||
| 1635 | roi_map->roi_map[x + y * roi_map->cols] = mapping_value - 1; | |||
| 1636 | } | |||
| 1637 | } | |||
| 1638 | ||||
| 1639 | return 0; | |||
| 1640 | } | |||
| 1641 | ||||
| 1642 | static int vp9_encode_set_roi(AVCodecContext *avctx, int frame_width, int frame_height, const AVFrameSideData *sd) | |||
| 1643 | { | |||
| 1644 | VPxContext *ctx = avctx->priv_data; | |||
| 1645 | ||||
| 1646 | #ifdef VPX_CTRL_VP9E_SET_ROI_MAP | |||
| 1647 | int version = vpx_codec_version(); | |||
| 1648 | int major = VPX_VERSION_MAJOR(version)(((version) >> 16) & 0xff); | |||
| 1649 | int minor = VPX_VERSION_MINOR(version)(((version) >> 8) & 0xff); | |||
| 1650 | int patch = VPX_VERSION_PATCH(version)(((version) >> 0) & 0xff); | |||
| 1651 | ||||
| 1652 | if (major > 1 || (major == 1 && minor > 8) || (major == 1 && minor == 8 && patch >= 1)) { | |||
| 1653 | vpx_roi_map_t roi_map; | |||
| 1654 | const int segment_cnt = 8; | |||
| 1655 | const int block_size = 8; | |||
| 1656 | int ret; | |||
| 1657 | ||||
| 1658 | if (ctx->aq_mode > 0 || ctx->cpu_used < 5 || ctx->deadline != VPX_DL_REALTIME1ul) { | |||
| 1659 | if (!ctx->roi_warned) { | |||
| 1660 | ctx->roi_warned = 1; | |||
| 1661 | av_log(avctx, AV_LOG_WARNING24, "ROI is only enabled when aq_mode is 0, cpu_used >= 5 " | |||
| 1662 | "and deadline is REALTIME, so skipping ROI.\n"); | |||
| 1663 | return AVERROR(EINVAL)(-(22)); | |||
| 1664 | } | |||
| 1665 | } | |||
| 1666 | ||||
| 1667 | ret = set_roi_map(avctx, sd, frame_width, frame_height, &roi_map, block_size, segment_cnt); | |||
| 1668 | if (ret) { | |||
| 1669 | log_encoder_error(avctx, &ctx->encoder, "Failed to set_roi_map.\n"); | |||
| 1670 | return ret; | |||
| 1671 | } | |||
| 1672 | ||||
| 1673 | memset(roi_map.ref_frame, -1, sizeof(roi_map.ref_frame)); | |||
| 1674 | ||||
| 1675 | if (vpx_codec_control(&ctx->encoder, VP9E_SET_ROI_MAP, &roi_map)vpx_codec_control_(&ctx->encoder, VP9E_SET_ROI_MAP, & roi_map)) { | |||
| 1676 | log_encoder_error(avctx, &ctx->encoder, "Failed to set VP9E_SET_ROI_MAP codec control.\n"); | |||
| 1677 | ret = AVERROR_INVALIDDATA(-(int)(('I') | (('N') << 8) | (('D') << 16) | (( unsigned)('A') << 24))); | |||
| 1678 | } | |||
| 1679 | av_freep(&roi_map.roi_map); | |||
| 1680 | return ret; | |||
| 1681 | } | |||
| 1682 | #endif | |||
| 1683 | ||||
| 1684 | if (!ctx->roi_warned) { | |||
| 1685 | ctx->roi_warned = 1; | |||
| 1686 | av_log(avctx, AV_LOG_WARNING24, "ROI is not supported, please upgrade libvpx to version >= 1.8.1. " | |||
| 1687 | "You may need to rebuild ffmpeg.\n"); | |||
| 1688 | } | |||
| 1689 | return 0; | |||
| 1690 | } | |||
| 1691 | ||||
| 1692 | static int vp8_encode_set_roi(AVCodecContext *avctx, int frame_width, int frame_height, const AVFrameSideData *sd) | |||
| 1693 | { | |||
| 1694 | vpx_roi_map_t roi_map; | |||
| 1695 | const int segment_cnt = 4; | |||
| 1696 | const int block_size = 16; | |||
| 1697 | VPxContext *ctx = avctx->priv_data; | |||
| 1698 | ||||
| 1699 | int ret = set_roi_map(avctx, sd, frame_width, frame_height, &roi_map, block_size, segment_cnt); | |||
| 1700 | if (ret) { | |||
| 1701 | log_encoder_error(avctx, &ctx->encoder, "Failed to set_roi_map.\n"); | |||
| 1702 | return ret; | |||
| 1703 | } | |||
| 1704 | ||||
| 1705 | if (vpx_codec_control(&ctx->encoder, VP8E_SET_ROI_MAP, &roi_map)vpx_codec_control_(&ctx->encoder, VP8E_SET_ROI_MAP, & roi_map)) { | |||
| 1706 | log_encoder_error(avctx, &ctx->encoder, "Failed to set VP8E_SET_ROI_MAP codec control.\n"); | |||
| 1707 | ret = AVERROR_INVALIDDATA(-(int)(('I') | (('N') << 8) | (('D') << 16) | (( unsigned)('A') << 24))); | |||
| 1708 | } | |||
| 1709 | ||||
| 1710 | av_freep(&roi_map.roi_map); | |||
| 1711 | return ret; | |||
| 1712 | } | |||
| 1713 | ||||
| 1714 | static int realloc_alpha_uv(AVCodecContext *avctx, int width, int height) | |||
| 1715 | { | |||
| 1716 | VPxContext *ctx = avctx->priv_data; | |||
| 1717 | struct vpx_image *rawimg_alpha = &ctx->rawimg_alpha; | |||
| 1718 | unsigned char **planes = rawimg_alpha->planes; | |||
| 1719 | int *stride = rawimg_alpha->stride; | |||
| 1720 | ||||
| 1721 | if (!planes[VPX_PLANE_U1] || | |||
| 1722 | !planes[VPX_PLANE_V2] || | |||
| 1723 | width != (int)rawimg_alpha->d_w || | |||
| 1724 | height != (int)rawimg_alpha->d_h) { | |||
| 1725 | vpx_img_fmt_t alpha_fmt = ctx->rawimg.bit_depth > 8 ? | |||
| 1726 | VPX_IMG_FMT_I42016 : VPX_IMG_FMT_I420; | |||
| 1727 | av_freep(&planes[VPX_PLANE_U1]); | |||
| 1728 | av_freep(&planes[VPX_PLANE_V2]); | |||
| 1729 | ||||
| 1730 | vpx_img_wrap(rawimg_alpha, alpha_fmt, width, height, 1, | |||
| 1731 | (unsigned char*)1); | |||
| 1732 | planes[VPX_PLANE_U1] = av_malloc_array(stride[VPX_PLANE_U1], height); | |||
| 1733 | planes[VPX_PLANE_V2] = av_malloc_array(stride[VPX_PLANE_V2], height); | |||
| 1734 | if (!planes[VPX_PLANE_U1] || !planes[VPX_PLANE_V2]) | |||
| 1735 | return AVERROR(ENOMEM)(-(12)); | |||
| 1736 | ||||
| 1737 | if (ctx->rawimg.bit_depth > 8) { | |||
| 1738 | int val = 0x80 << (ctx->rawimg.bit_depth - 8); | |||
| 1739 | AV_WN16(planes[VPX_PLANE_U], val)((((union unaligned_16 *) (planes[1]))->l) = (val)); | |||
| 1740 | AV_WN16(planes[VPX_PLANE_V], val)((((union unaligned_16 *) (planes[2]))->l) = (val)); | |||
| 1741 | av_memcpy_backptr(planes[VPX_PLANE_U1] + 2, 2, stride[VPX_PLANE_U1] * height - 2); | |||
| 1742 | av_memcpy_backptr(planes[VPX_PLANE_V2] + 2, 2, stride[VPX_PLANE_V2] * height - 2); | |||
| 1743 | } else { | |||
| 1744 | memset(planes[VPX_PLANE_U1], 0x80, stride[VPX_PLANE_U1] * height); | |||
| 1745 | memset(planes[VPX_PLANE_V2], 0x80, stride[VPX_PLANE_V2] * height); | |||
| 1746 | } | |||
| 1747 | } | |||
| 1748 | ||||
| 1749 | return 0; | |||
| 1750 | } | |||
| 1751 | ||||
| 1752 | static int vpx_encode(AVCodecContext *avctx, AVPacket *pkt, | |||
| 1753 | const AVFrame *frame, int *got_packet) | |||
| 1754 | { | |||
| 1755 | VPxContext *ctx = avctx->priv_data; | |||
| 1756 | struct vpx_image *rawimg = NULL((void*)0); | |||
| 1757 | struct vpx_image *rawimg_alpha = NULL((void*)0); | |||
| 1758 | int64_t timestamp = 0; | |||
| 1759 | int res, coded_size; | |||
| 1760 | vpx_enc_frame_flags_t flags = 0; | |||
| 1761 | const struct vpx_codec_enc_cfg *enccfg = ctx->encoder.config.enc; | |||
| 1762 | vpx_svc_layer_id_t layer_id; | |||
| 1763 | int layer_id_valid = 0; | |||
| 1764 | unsigned long duration = 0; | |||
| 1765 | ||||
| 1766 | if (avctx->qmax >= 0 && enccfg->rc_max_quantizer != avctx->qmax) { | |||
| 1767 | struct vpx_codec_enc_cfg cfg = *enccfg; | |||
| 1768 | cfg.rc_max_quantizer = avctx->qmax; | |||
| 1769 | res = vpx_codec_enc_config_set(&ctx->encoder, &cfg); | |||
| 1770 | if (res != VPX_CODEC_OK) { | |||
| 1771 | log_encoder_error(avctx, &ctx->encoder, "Error reconfiguring encoder"); | |||
| 1772 | return AVERROR_INVALIDDATA(-(int)(('I') | (('N') << 8) | (('D') << 16) | (( unsigned)('A') << 24))); | |||
| 1773 | } | |||
| 1774 | } | |||
| 1775 | ||||
| 1776 | if (frame) { | |||
| 1777 | const AVFrameSideData *sd = av_frame_get_side_data(frame, AV_FRAME_DATA_REGIONS_OF_INTEREST); | |||
| 1778 | rawimg = &ctx->rawimg; | |||
| 1779 | rawimg->planes[VPX_PLANE_Y0] = frame->data[0]; | |||
| 1780 | rawimg->planes[VPX_PLANE_U1] = frame->data[1]; | |||
| 1781 | rawimg->planes[VPX_PLANE_V2] = frame->data[2]; | |||
| 1782 | rawimg->stride[VPX_PLANE_Y0] = frame->linesize[0]; | |||
| 1783 | rawimg->stride[VPX_PLANE_U1] = frame->linesize[1]; | |||
| 1784 | rawimg->stride[VPX_PLANE_V2] = frame->linesize[2]; | |||
| 1785 | if (ctx->is_alpha) { | |||
| 1786 | rawimg_alpha = &ctx->rawimg_alpha; | |||
| 1787 | res = realloc_alpha_uv(avctx, frame->width, frame->height); | |||
| 1788 | if (res < 0) | |||
| 1789 | return res; | |||
| 1790 | rawimg_alpha->planes[VPX_PLANE_Y0] = frame->data[3]; | |||
| 1791 | rawimg_alpha->stride[VPX_PLANE_Y0] = frame->linesize[3]; | |||
| 1792 | } | |||
| 1793 | timestamp = frame->pts; | |||
| 1794 | #if VPX_IMAGE_ABI_VERSION(5) >= 4 | |||
| 1795 | switch (frame->color_range) { | |||
| 1796 | case AVCOL_RANGE_MPEG: | |||
| 1797 | rawimg->range = VPX_CR_STUDIO_RANGE; | |||
| 1798 | break; | |||
| 1799 | case AVCOL_RANGE_JPEG: | |||
| 1800 | rawimg->range = VPX_CR_FULL_RANGE; | |||
| 1801 | break; | |||
| 1802 | } | |||
| 1803 | #endif | |||
| 1804 | if (frame->pict_type == AV_PICTURE_TYPE_I) | |||
| 1805 | flags |= VPX_EFLAG_FORCE_KF(1 << 0); | |||
| 1806 | if (frame->metadata) { | |||
| 1807 | AVDictionaryEntry* en = av_dict_get(frame->metadata, "vp8-flags", NULL((void*)0), 0); | |||
| 1808 | if (en) { | |||
| 1809 | flags |= strtoul(en->value, NULL((void*)0), 10); | |||
| 1810 | } | |||
| 1811 | ||||
| 1812 | memset(&layer_id, 0, sizeof(layer_id)); | |||
| 1813 | ||||
| 1814 | en = av_dict_get(frame->metadata, "temporal_id", NULL((void*)0), 0); | |||
| 1815 | if (en) { | |||
| 1816 | layer_id.temporal_layer_id = strtoul(en->value, NULL((void*)0), 10); | |||
| 1817 | #ifdef VPX_CTRL_VP9E_SET_MAX_INTER_BITRATE_PCT | |||
| 1818 | layer_id.temporal_layer_id_per_spatial[0] = layer_id.temporal_layer_id; | |||
| 1819 | #endif | |||
| 1820 | layer_id_valid = 1; | |||
| 1821 | } | |||
| 1822 | #if CONFIG_LIBVPX_VP9_ENCODER1 && defined(VPX_CTRL_VP9E_SET_MAX_INTER_BITRATE_PCT) | |||
| 1823 | en = av_dict_get(frame->metadata, "ref-frame-config", NULL((void*)0), 0); | |||
| 1824 | ||||
| 1825 | if (en) { | |||
| 1826 | if (avctx->codec_id == AV_CODEC_ID_VP9) { | |||
| 1827 | int ret = vpx_parse_ref_frame_config(&ctx->ref_frame_config, | |||
| 1828 | enccfg->ss_number_layers, en->value); | |||
| 1829 | if (ret < 0) { | |||
| 1830 | av_log(avctx, AV_LOG_WARNING24, | |||
| 1831 | "Error parsing ref_frame_config option %s.\n", en->value); | |||
| 1832 | return ret; | |||
| 1833 | } | |||
| 1834 | ||||
| 1835 | codecctl_intp(avctx, VP9E_SET_SVC_REF_FRAME_CONFIG, (int *)&ctx->ref_frame_config); | |||
| 1836 | } else { | |||
| 1837 | av_log(avctx, AV_LOG_WARNING24, | |||
| 1838 | "Ignoring ref-frame-config for a non-VP9 codec\n"); | |||
| 1839 | } | |||
| 1840 | } | |||
| 1841 | #endif | |||
| 1842 | } | |||
| 1843 | ||||
| 1844 | if (sd) { | |||
| 1845 | if (avctx->codec_id == AV_CODEC_ID_VP8) { | |||
| 1846 | vp8_encode_set_roi(avctx, frame->width, frame->height, sd); | |||
| 1847 | } else { | |||
| 1848 | vp9_encode_set_roi(avctx, frame->width, frame->height, sd); | |||
| 1849 | } | |||
| 1850 | } | |||
| 1851 | ||||
| 1852 | if (!(avctx->flags & AV_CODEC_FLAG_PASS1(1 << 9))) { | |||
| 1853 | res = frame_data_submit(avctx, ctx->fifo, frame); | |||
| 1854 | if (res < 0) | |||
| 1855 | return res; | |||
| 1856 | } | |||
| 1857 | } | |||
| 1858 | ||||
| 1859 | // this is for encoding with preset temporal layering patterns defined in | |||
| 1860 | // set_temporal_layer_pattern function. | |||
| 1861 | if (enccfg->ts_number_layers > 1 && ctx->ts_layer_flags) { | |||
| 1862 | if (flags & VPX_EFLAG_FORCE_KF(1 << 0)) { | |||
| 1863 | // keyframe, reset temporal layering. | |||
| 1864 | ctx->current_temporal_idx = 0; | |||
| 1865 | flags = VPX_EFLAG_FORCE_KF(1 << 0); | |||
| 1866 | } else { | |||
| 1867 | flags = 0; | |||
| 1868 | } | |||
| 1869 | ||||
| 1870 | /* get the flags from the temporal layer configuration. */ | |||
| 1871 | flags |= ctx->ts_layer_flags[ctx->current_temporal_idx]; | |||
| 1872 | ||||
| 1873 | memset(&layer_id, 0, sizeof(layer_id)); | |||
| 1874 | #if VPX_ENCODER_ABI_VERSION(18 + (4 + (5)) + (7 + 5)) >= 12 | |||
| 1875 | layer_id.spatial_layer_id = 0; | |||
| 1876 | #endif | |||
| 1877 | layer_id.temporal_layer_id = enccfg->ts_layer_id[ctx->current_temporal_idx]; | |||
| 1878 | #ifdef VPX_CTRL_VP9E_SET_MAX_INTER_BITRATE_PCT | |||
| 1879 | layer_id.temporal_layer_id_per_spatial[0] = layer_id.temporal_layer_id; | |||
| 1880 | #endif | |||
| 1881 | layer_id_valid = 1; | |||
| 1882 | } | |||
| 1883 | ||||
| 1884 | if (layer_id_valid) { | |||
| 1885 | if (avctx->codec_id == AV_CODEC_ID_VP8) { | |||
| 1886 | codecctl_int(avctx, VP8E_SET_TEMPORAL_LAYER_ID, layer_id.temporal_layer_id); | |||
| 1887 | } | |||
| 1888 | #if CONFIG_LIBVPX_VP9_ENCODER1 && VPX_ENCODER_ABI_VERSION(18 + (4 + (5)) + (7 + 5)) >= 12 | |||
| 1889 | else if (avctx->codec_id == AV_CODEC_ID_VP9) { | |||
| 1890 | codecctl_intp(avctx, VP9E_SET_SVC_LAYER_ID, (int *)&layer_id); | |||
| 1891 | } | |||
| 1892 | #endif | |||
| 1893 | } | |||
| 1894 | ||||
| 1895 | if (frame && frame->duration > ULONG_MAX(9223372036854775807L *2UL+1UL)) { | |||
| 1896 | av_log(avctx, AV_LOG_WARNING24, | |||
| 1897 | "Frame duration too large: %"PRId64"l" "d""\n", frame->duration); | |||
| 1898 | } else if (frame && frame->duration) | |||
| 1899 | duration = frame->duration; | |||
| 1900 | else if (avctx->framerate.num > 0 && avctx->framerate.den > 0) | |||
| 1901 | duration = av_rescale_q(1, av_inv_q(avctx->framerate), avctx->time_base); | |||
| 1902 | else { | |||
| 1903 | duration = 1; | |||
| 1904 | } | |||
| 1905 | ||||
| 1906 | res = vpx_codec_encode(&ctx->encoder, rawimg, timestamp, | |||
| 1907 | duration, flags, ctx->deadline); | |||
| 1908 | if (res != VPX_CODEC_OK) { | |||
| 1909 | log_encoder_error(avctx, &ctx->encoder, "Error encoding frame"); | |||
| 1910 | return AVERROR_INVALIDDATA(-(int)(('I') | (('N') << 8) | (('D') << 16) | (( unsigned)('A') << 24))); | |||
| 1911 | } | |||
| 1912 | ||||
| 1913 | if (ctx->is_alpha) { | |||
| 1914 | res = vpx_codec_encode(&ctx->encoder_alpha, rawimg_alpha, timestamp, | |||
| 1915 | duration, flags, ctx->deadline); | |||
| 1916 | if (res != VPX_CODEC_OK) { | |||
| 1917 | log_encoder_error(avctx, &ctx->encoder_alpha, "Error encoding alpha frame"); | |||
| 1918 | return AVERROR_INVALIDDATA(-(int)(('I') | (('N') << 8) | (('D') << 16) | (( unsigned)('A') << 24))); | |||
| 1919 | } | |||
| 1920 | } | |||
| 1921 | ||||
| 1922 | coded_size = queue_frames(avctx, &ctx->encoder, &ctx->coded_frame_list, pkt); | |||
| 1923 | if (ctx->is_alpha) { | |||
| 1924 | queue_frames(avctx, &ctx->encoder_alpha, &ctx->alpha_coded_frame_list, NULL((void*)0)); | |||
| 1925 | ||||
| 1926 | if (ctx->coded_frame_list && ctx->alpha_coded_frame_list) { | |||
| 1927 | struct FrameListData *cx_frame = ctx->coded_frame_list; | |||
| 1928 | struct FrameListData *alpha_cx_frame = ctx->alpha_coded_frame_list; | |||
| 1929 | av_assert0(!coded_size)do { if (!(!coded_size)) { av_log(((void*)0), 0, "Assertion %s failed at %s:%d\n" , "!coded_size", "/root/firefox-clang/media/ffvpx/libavcodec/libvpxenc.c" , 1929); abort(); } } while (0); | |||
| 1930 | /* return the leading frame if we've already begun queueing */ | |||
| 1931 | coded_size = storeframe(avctx, cx_frame, alpha_cx_frame, pkt); | |||
| 1932 | if (coded_size < 0) | |||
| 1933 | return coded_size; | |||
| 1934 | ctx->coded_frame_list = cx_frame->next; | |||
| 1935 | ctx->alpha_coded_frame_list = alpha_cx_frame->next; | |||
| 1936 | free_coded_frame(cx_frame); | |||
| 1937 | free_coded_frame(alpha_cx_frame); | |||
| 1938 | } | |||
| 1939 | } | |||
| 1940 | ||||
| 1941 | if (!frame && avctx->flags & AV_CODEC_FLAG_PASS1(1 << 9)) { | |||
| 1942 | unsigned int b64_size = AV_BASE64_SIZE(ctx->twopass_stats.sz)(((ctx->twopass_stats.sz)+2) / 3 * 4 + 1); | |||
| 1943 | ||||
| 1944 | avctx->stats_out = av_malloc(b64_size); | |||
| 1945 | if (!avctx->stats_out) { | |||
| 1946 | av_log(avctx, AV_LOG_ERROR16, "Stat buffer alloc (%d bytes) failed\n", | |||
| 1947 | b64_size); | |||
| 1948 | return AVERROR(ENOMEM)(-(12)); | |||
| 1949 | } | |||
| 1950 | av_base64_encode(avctx->stats_out, b64_size, ctx->twopass_stats.buf, | |||
| 1951 | ctx->twopass_stats.sz); | |||
| 1952 | } else if (enccfg->ts_number_layers > 1 && ctx->ts_layer_flags) { | |||
| 1953 | ctx->current_temporal_idx = (ctx->current_temporal_idx + 1) % enccfg->ts_periodicity; | |||
| 1954 | } | |||
| 1955 | ||||
| 1956 | *got_packet = !!coded_size; | |||
| 1957 | return 0; | |||
| 1958 | } | |||
| 1959 | ||||
| 1960 | #define OFFSET(x)__builtin_offsetof(VPxContext, x) offsetof(VPxContext, x)__builtin_offsetof(VPxContext, x) | |||
| 1961 | #define VE(1 << 4) | (1 << 0) AV_OPT_FLAG_VIDEO_PARAM(1 << 4) | AV_OPT_FLAG_ENCODING_PARAM(1 << 0) | |||
| 1962 | ||||
| 1963 | #define COMMON_OPTIONS \ | |||
| 1964 | { "lag-in-frames", "Number of frames to look ahead for " \ | |||
| 1965 | "alternate reference frame selection", OFFSET(lag_in_frames)__builtin_offsetof(VPxContext, lag_in_frames), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX2147483647, VE(1 << 4) | (1 << 0)}, \ | |||
| 1966 | { "arnr-maxframes", "altref noise reduction max frame count", OFFSET(arnr_max_frames)__builtin_offsetof(VPxContext, arnr_max_frames), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX2147483647, VE(1 << 4) | (1 << 0)}, \ | |||
| 1967 | { "arnr-strength", "altref noise reduction filter strength", OFFSET(arnr_strength)__builtin_offsetof(VPxContext, arnr_strength), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX2147483647, VE(1 << 4) | (1 << 0)}, \ | |||
| 1968 | { "arnr-type", "altref noise reduction filter type", OFFSET(arnr_type)__builtin_offsetof(VPxContext, arnr_type), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX2147483647, VE(1 << 4) | (1 << 0), .unit = "arnr_type"}, \ | |||
| 1969 | { "backward", NULL((void*)0), 0, AV_OPT_TYPE_CONST, {.i64 = 1}, 0, 0, VE(1 << 4) | (1 << 0), .unit = "arnr_type" }, \ | |||
| 1970 | { "forward", NULL((void*)0), 0, AV_OPT_TYPE_CONST, {.i64 = 2}, 0, 0, VE(1 << 4) | (1 << 0), .unit = "arnr_type" }, \ | |||
| 1971 | { "centered", NULL((void*)0), 0, AV_OPT_TYPE_CONST, {.i64 = 3}, 0, 0, VE(1 << 4) | (1 << 0), .unit = "arnr_type" }, \ | |||
| 1972 | { "tune", "Tune the encoding to a specific scenario", OFFSET(tune)__builtin_offsetof(VPxContext, tune), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX2147483647, VE(1 << 4) | (1 << 0), .unit = "tune"}, \ | |||
| 1973 | { "psnr", NULL((void*)0), 0, AV_OPT_TYPE_CONST, {.i64 = VP8_TUNE_PSNR}, 0, 0, VE(1 << 4) | (1 << 0), .unit = "tune"}, \ | |||
| 1974 | { "ssim", NULL((void*)0), 0, AV_OPT_TYPE_CONST, {.i64 = VP8_TUNE_SSIM}, 0, 0, VE(1 << 4) | (1 << 0), .unit = "tune"}, \ | |||
| 1975 | { "deadline", "Time to spend encoding, in microseconds.", OFFSET(deadline)__builtin_offsetof(VPxContext, deadline), AV_OPT_TYPE_INT, {.i64 = VPX_DL_GOOD_QUALITY1000000ul}, INT_MIN(-2147483647 -1), INT_MAX2147483647, VE(1 << 4) | (1 << 0), .unit = "quality"}, \ | |||
| 1976 | { "best", NULL((void*)0), 0, AV_OPT_TYPE_CONST, {.i64 = VPX_DL_BEST_QUALITY0ul}, 0, 0, VE(1 << 4) | (1 << 0), .unit = "quality"}, \ | |||
| 1977 | { "good", NULL((void*)0), 0, AV_OPT_TYPE_CONST, {.i64 = VPX_DL_GOOD_QUALITY1000000ul}, 0, 0, VE(1 << 4) | (1 << 0), .unit = "quality"}, \ | |||
| 1978 | { "realtime", NULL((void*)0), 0, AV_OPT_TYPE_CONST, {.i64 = VPX_DL_REALTIME1ul}, 0, 0, VE(1 << 4) | (1 << 0), .unit = "quality"}, \ | |||
| 1979 | { "error-resilient", "Error resilience configuration", OFFSET(error_resilient)__builtin_offsetof(VPxContext, error_resilient), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN(-2147483647 -1), INT_MAX2147483647, VE(1 << 4) | (1 << 0), .unit = "er"}, \ | |||
| 1980 | { "max-intra-rate", "Maximum I-frame bitrate (pct) 0=unlimited", OFFSET(max_intra_rate)__builtin_offsetof(VPxContext, max_intra_rate), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX2147483647, VE(1 << 4) | (1 << 0)}, \ | |||
| 1981 | { "default", "Improve resiliency against losses of whole frames", 0, AV_OPT_TYPE_CONST, {.i64 = VPX_ERROR_RESILIENT_DEFAULT0x1u}, 0, 0, VE(1 << 4) | (1 << 0), .unit = "er"}, \ | |||
| 1982 | { "partitions", "The frame partitions are independently decodable " \ | |||
| 1983 | "by the bool decoder, meaning that partitions can be decoded even " \ | |||
| 1984 | "though earlier partitions have been lost. Note that intra prediction" \ | |||
| 1985 | " is still done over the partition boundary.", 0, AV_OPT_TYPE_CONST, {.i64 = VPX_ERROR_RESILIENT_PARTITIONS0x2u}, 0, 0, VE(1 << 4) | (1 << 0), .unit = "er"}, \ | |||
| 1986 | { "crf", "Select the quality for constant quality mode", offsetof(VPxContext, crf)__builtin_offsetof(VPxContext, crf), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 63, VE(1 << 4) | (1 << 0) }, \ | |||
| 1987 | { "static-thresh", "A change threshold on blocks below which they will be skipped by the encoder", OFFSET(static_thresh)__builtin_offsetof(VPxContext, static_thresh), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX2147483647, VE(1 << 4) | (1 << 0) }, \ | |||
| 1988 | { "drop-threshold", "Frame drop threshold", offsetof(VPxContext, drop_threshold)__builtin_offsetof(VPxContext, drop_threshold), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN(-2147483647 -1), INT_MAX2147483647, VE(1 << 4) | (1 << 0) }, \ | |||
| 1989 | { "noise-sensitivity", "Noise sensitivity", OFFSET(noise_sensitivity)__builtin_offsetof(VPxContext, noise_sensitivity), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 4, VE(1 << 4) | (1 << 0)}, \ | |||
| 1990 | { "undershoot-pct", "Datarate undershoot (min) target (%)", OFFSET(rc_undershoot_pct)__builtin_offsetof(VPxContext, rc_undershoot_pct), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 100, VE(1 << 4) | (1 << 0) }, \ | |||
| 1991 | { "overshoot-pct", "Datarate overshoot (max) target (%)", OFFSET(rc_overshoot_pct)__builtin_offsetof(VPxContext, rc_overshoot_pct), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1000, VE(1 << 4) | (1 << 0) }, \ | |||
| 1992 | { "ts-parameters", "Temporal scaling configuration using a :-separated list of key=value parameters", OFFSET(vpx_ts_parameters)__builtin_offsetof(VPxContext, vpx_ts_parameters), AV_OPT_TYPE_DICT, {.str=NULL((void*)0)}, 0, 0, VE(1 << 4) | (1 << 0)}, \ | |||
| 1993 | ||||
| 1994 | #define LEGACY_OPTIONS \ | |||
| 1995 | {"speed", "", offsetof(VPxContext, cpu_used)__builtin_offsetof(VPxContext, cpu_used), AV_OPT_TYPE_INT, {.i64 = 1}, -16, 16, VE(1 << 4) | (1 << 0)}, \ | |||
| 1996 | {"quality", "", offsetof(VPxContext, deadline)__builtin_offsetof(VPxContext, deadline), AV_OPT_TYPE_INT, {.i64 = VPX_DL_GOOD_QUALITY1000000ul}, INT_MIN(-2147483647 -1), INT_MAX2147483647, VE(1 << 4) | (1 << 0), .unit = "quality"}, \ | |||
| 1997 | {"vp8flags", "", offsetof(VPxContext, flags)__builtin_offsetof(VPxContext, flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, 0, UINT_MAX(2147483647 *2U +1U), VE(1 << 4) | (1 << 0), .unit = "flags"}, \ | |||
| 1998 | {"error_resilient", "enable error resilience", 0, AV_OPT_TYPE_CONST, {.i64 = VP8F_ERROR_RESILIENT0x00000001}, INT_MIN(-2147483647 -1), INT_MAX2147483647, VE(1 << 4) | (1 << 0), .unit = "flags"}, \ | |||
| 1999 | {"altref", "enable use of alternate reference frames (VP8/2-pass only)", 0, AV_OPT_TYPE_CONST, {.i64 = VP8F_AUTO_ALT_REF0x00000002}, INT_MIN(-2147483647 -1), INT_MAX2147483647, VE(1 << 4) | (1 << 0), .unit = "flags"}, \ | |||
| 2000 | {"arnr_max_frames", "altref noise reduction max frame count", offsetof(VPxContext, arnr_max_frames)__builtin_offsetof(VPxContext, arnr_max_frames), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 15, VE(1 << 4) | (1 << 0)}, \ | |||
| 2001 | {"arnr_strength", "altref noise reduction filter strength", offsetof(VPxContext, arnr_strength)__builtin_offsetof(VPxContext, arnr_strength), AV_OPT_TYPE_INT, {.i64 = 3}, 0, 6, VE(1 << 4) | (1 << 0)}, \ | |||
| 2002 | {"arnr_type", "altref noise reduction filter type", offsetof(VPxContext, arnr_type)__builtin_offsetof(VPxContext, arnr_type), AV_OPT_TYPE_INT, {.i64 = 3}, 1, 3, VE(1 << 4) | (1 << 0)}, \ | |||
| 2003 | {"rc_lookahead", "Number of frames to look ahead for alternate reference frame selection", offsetof(VPxContext, lag_in_frames)__builtin_offsetof(VPxContext, lag_in_frames), AV_OPT_TYPE_INT, {.i64 = 25}, 0, 25, VE(1 << 4) | (1 << 0)}, \ | |||
| 2004 | {"sharpness", "Increase sharpness at the expense of lower PSNR", offsetof(VPxContext, sharpness)__builtin_offsetof(VPxContext, sharpness), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 7, VE(1 << 4) | (1 << 0)}, | |||
| 2005 | ||||
| 2006 | #if CONFIG_LIBVPX_VP8_ENCODER1 | |||
| 2007 | static const AVOption vp8_options[] = { | |||
| 2008 | COMMON_OPTIONS | |||
| 2009 | { "auto-alt-ref", "Enable use of alternate reference " | |||
| 2010 | "frames (2-pass only)", OFFSET(auto_alt_ref)__builtin_offsetof(VPxContext, auto_alt_ref), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 2, VE(1 << 4) | (1 << 0)}, | |||
| 2011 | { "cpu-used", "Quality/Speed ratio modifier", OFFSET(cpu_used)__builtin_offsetof(VPxContext, cpu_used), AV_OPT_TYPE_INT, {.i64 = 1}, -16, 16, VE(1 << 4) | (1 << 0)}, | |||
| 2012 | { "screen-content-mode", "Encoder screen content mode", OFFSET(screen_content_mode)__builtin_offsetof(VPxContext, screen_content_mode), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 2, VE(1 << 4) | (1 << 0)}, | |||
| 2013 | LEGACY_OPTIONS | |||
| 2014 | { NULL((void*)0) } | |||
| 2015 | }; | |||
| 2016 | #endif | |||
| 2017 | ||||
| 2018 | #if CONFIG_LIBVPX_VP9_ENCODER1 | |||
| 2019 | static const AVOption vp9_options[] = { | |||
| 2020 | COMMON_OPTIONS | |||
| 2021 | { "auto-alt-ref", "Enable use of alternate reference " | |||
| 2022 | "frames (2-pass only)", OFFSET(auto_alt_ref)__builtin_offsetof(VPxContext, auto_alt_ref), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 6, VE(1 << 4) | (1 << 0)}, | |||
| 2023 | { "cpu-used", "Quality/Speed ratio modifier", OFFSET(cpu_used)__builtin_offsetof(VPxContext, cpu_used), AV_OPT_TYPE_INT, {.i64 = 1}, -8, 8, VE(1 << 4) | (1 << 0)}, | |||
| 2024 | { "lossless", "Lossless mode", OFFSET(lossless)__builtin_offsetof(VPxContext, lossless), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 1, VE(1 << 4) | (1 << 0)}, | |||
| 2025 | { "tile-columns", "Number of tile columns to use, log2", OFFSET(tile_columns)__builtin_offsetof(VPxContext, tile_columns), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 6, VE(1 << 4) | (1 << 0)}, | |||
| 2026 | { "tile-rows", "Number of tile rows to use, log2", OFFSET(tile_rows)__builtin_offsetof(VPxContext, tile_rows), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 2, VE(1 << 4) | (1 << 0)}, | |||
| 2027 | { "frame-parallel", "Enable frame parallel decodability features", OFFSET(frame_parallel)__builtin_offsetof(VPxContext, frame_parallel), AV_OPT_TYPE_BOOL,{.i64 = -1}, -1, 1, VE(1 << 4) | (1 << 0)}, | |||
| 2028 | #if VPX_ENCODER_ABI_VERSION(18 + (4 + (5)) + (7 + 5)) >= 12 | |||
| 2029 | { "aq-mode", "adaptive quantization mode", OFFSET(aq_mode)__builtin_offsetof(VPxContext, aq_mode), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 4, VE(1 << 4) | (1 << 0), .unit = "aq_mode"}, | |||
| 2030 | #else | |||
| 2031 | { "aq-mode", "adaptive quantization mode", OFFSET(aq_mode)__builtin_offsetof(VPxContext, aq_mode), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 3, VE(1 << 4) | (1 << 0), .unit = "aq_mode"}, | |||
| 2032 | #endif | |||
| 2033 | { "none", "Aq not used", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, 0, 0, VE(1 << 4) | (1 << 0), .unit = "aq_mode" }, | |||
| 2034 | { "variance", "Variance based Aq", 0, AV_OPT_TYPE_CONST, {.i64 = 1}, 0, 0, VE(1 << 4) | (1 << 0), .unit = "aq_mode" }, | |||
| 2035 | { "complexity", "Complexity based Aq", 0, AV_OPT_TYPE_CONST, {.i64 = 2}, 0, 0, VE(1 << 4) | (1 << 0), .unit = "aq_mode" }, | |||
| 2036 | { "cyclic", "Cyclic Refresh Aq", 0, AV_OPT_TYPE_CONST, {.i64 = 3}, 0, 0, VE(1 << 4) | (1 << 0), .unit = "aq_mode" }, | |||
| 2037 | #if VPX_ENCODER_ABI_VERSION(18 + (4 + (5)) + (7 + 5)) >= 12 | |||
| 2038 | { "equator360", "360 video Aq", 0, AV_OPT_TYPE_CONST, {.i64 = 4}, 0, 0, VE(1 << 4) | (1 << 0), .unit = "aq_mode" }, | |||
| 2039 | {"level", "Specify level", OFFSET(level)__builtin_offsetof(VPxContext, level), AV_OPT_TYPE_FLOAT, {.dbl=-1}, -1, 6.2, VE(1 << 4) | (1 << 0)}, | |||
| 2040 | #endif | |||
| 2041 | #ifdef VPX_CTRL_VP9E_SET_ROW_MT | |||
| 2042 | {"row-mt", "Row based multi-threading", OFFSET(row_mt)__builtin_offsetof(VPxContext, row_mt), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE(1 << 4) | (1 << 0)}, | |||
| 2043 | #endif | |||
| 2044 | #ifdef VPX_CTRL_VP9E_SET_TUNE_CONTENT | |||
| 2045 | #if VPX_ENCODER_ABI_VERSION(18 + (4 + (5)) + (7 + 5)) >= 14 | |||
| 2046 | { "tune-content", "Tune content type", OFFSET(tune_content)__builtin_offsetof(VPxContext, tune_content), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 2, VE(1 << 4) | (1 << 0), .unit = "tune_content" }, | |||
| 2047 | #else | |||
| 2048 | { "tune-content", "Tune content type", OFFSET(tune_content)__builtin_offsetof(VPxContext, tune_content), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 1, VE(1 << 4) | (1 << 0), .unit = "tune_content" }, | |||
| 2049 | #endif | |||
| 2050 | { "default", "Regular video content", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, 0, 0, VE(1 << 4) | (1 << 0), .unit = "tune_content" }, | |||
| 2051 | { "screen", "Screen capture content", 0, AV_OPT_TYPE_CONST, {.i64 = 1}, 0, 0, VE(1 << 4) | (1 << 0), .unit = "tune_content" }, | |||
| 2052 | #if VPX_ENCODER_ABI_VERSION(18 + (4 + (5)) + (7 + 5)) >= 14 | |||
| 2053 | { "film", "Film content; improves grain retention", 0, AV_OPT_TYPE_CONST, {.i64 = 2}, 0, 0, VE(1 << 4) | (1 << 0), .unit = "tune_content" }, | |||
| 2054 | #endif | |||
| 2055 | #endif | |||
| 2056 | #if VPX_ENCODER_ABI_VERSION(18 + (4 + (5)) + (7 + 5)) >= 14 | |||
| 2057 | { "corpus-complexity", "corpus vbr complexity midpoint", OFFSET(corpus_complexity)__builtin_offsetof(VPxContext, corpus_complexity), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 10000, VE(1 << 4) | (1 << 0) }, | |||
| 2058 | #endif | |||
| 2059 | #ifdef VPX_CTRL_VP9E_SET_TPL | |||
| 2060 | { "enable-tpl", "Enable temporal dependency model", OFFSET(tpl_model)__builtin_offsetof(VPxContext, tpl_model), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE(1 << 4) | (1 << 0) }, | |||
| 2061 | #endif | |||
| 2062 | #ifdef VPX_CTRL_VP9E_SET_MIN_GF_INTERVAL | |||
| 2063 | { "min-gf-interval", "Minimum golden/alternate reference frame interval", OFFSET(min_gf_interval)__builtin_offsetof(VPxContext, min_gf_interval), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX2147483647, VE(1 << 4) | (1 << 0) }, | |||
| 2064 | #endif | |||
| 2065 | LEGACY_OPTIONS | |||
| 2066 | { NULL((void*)0) } | |||
| 2067 | }; | |||
| 2068 | #endif | |||
| 2069 | ||||
| 2070 | #undef COMMON_OPTIONS | |||
| 2071 | #undef LEGACY_OPTIONS | |||
| 2072 | ||||
| 2073 | static const FFCodecDefault defaults[] = { | |||
| 2074 | { "b", "0" }, | |||
| 2075 | { "qmin", "-1" }, | |||
| 2076 | { "qmax", "-1" }, | |||
| 2077 | { "g", "-1" }, | |||
| 2078 | { "keyint_min", "-1" }, | |||
| 2079 | { NULL((void*)0) }, | |||
| 2080 | }; | |||
| 2081 | ||||
| 2082 | #if CONFIG_LIBVPX_VP8_ENCODER1 | |||
| 2083 | static av_cold__attribute__((cold)) int vp8_init(AVCodecContext *avctx) | |||
| 2084 | { | |||
| 2085 | return vpx_init(avctx, vpx_codec_vp8_cx()); | |||
| 2086 | } | |||
| 2087 | ||||
| 2088 | static const AVClass class_vp8 = { | |||
| 2089 | .class_name = "libvpx-vp8 encoder", | |||
| 2090 | .item_name = av_default_item_name, | |||
| 2091 | .option = vp8_options, | |||
| 2092 | .version = LIBAVUTIL_VERSION_INT((60)<<16 | (29)<<8 | (100)), | |||
| 2093 | }; | |||
| 2094 | ||||
| 2095 | const FFCodec ff_libvpx_vp8_encoder = { | |||
| 2096 | .p.name = "libvpx", | |||
| 2097 | CODEC_LONG_NAME("libvpx VP8").p.long_name = "libvpx VP8", | |||
| 2098 | .p.type = AVMEDIA_TYPE_VIDEO, | |||
| 2099 | .p.id = AV_CODEC_ID_VP8, | |||
| 2100 | .p.capabilities = AV_CODEC_CAP_DR1(1 << 1) | AV_CODEC_CAP_DELAY(1 << 5) | | |||
| 2101 | AV_CODEC_CAP_OTHER_THREADS(1 << 15) | | |||
| 2102 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE(1 << 20), | |||
| 2103 | .priv_data_size = sizeof(VPxContext), | |||
| 2104 | .init = vp8_init, | |||
| 2105 | FF_CODEC_ENCODE_CB(vpx_encode).is_decoder = 0, .cb_type = FF_CODEC_CB_TYPE_ENCODE, .cb.encode = (vpx_encode), | |||
| 2106 | .close = vpx_free, | |||
| 2107 | .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE(1 << 0) | | |||
| 2108 | FF_CODEC_CAP_INIT_CLEANUP(1 << 1) | | |||
| 2109 | FF_CODEC_CAP_AUTO_THREADS(1 << 7), | |||
| 2110 | CODEC_PIXFMTS(AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUVA420P)GCC diagnostic push
GCC diagnostic ignored "-Wdeprecated-declarations" .p.pix_fmts = ((((const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P , AV_PIX_FMT_YUVA420P, AV_PIX_FMT_NONE }))) GCC diagnostic pop , | |||
| 2111 | .color_ranges = AVCOL_RANGE_MPEG | AVCOL_RANGE_JPEG, | |||
| 2112 | .p.priv_class = &class_vp8, | |||
| 2113 | .defaults = defaults, | |||
| 2114 | .p.wrapper_name = "libvpx", | |||
| 2115 | }; | |||
| 2116 | #endif /* CONFIG_LIBVPX_VP8_ENCODER */ | |||
| 2117 | ||||
| 2118 | #if CONFIG_LIBVPX_VP9_ENCODER1 | |||
| 2119 | static av_cold__attribute__((cold)) int vp9_init(AVCodecContext *avctx) | |||
| 2120 | { | |||
| 2121 | return vpx_init(avctx, vpx_codec_vp9_cx()); | |||
| 2122 | } | |||
| 2123 | ||||
| 2124 | static const enum AVPixelFormat vp9_pix_fmts_highcol[] = { | |||
| 2125 | AV_PIX_FMT_YUV420P, | |||
| 2126 | AV_PIX_FMT_YUVA420P, | |||
| 2127 | AV_PIX_FMT_YUV422P, | |||
| 2128 | AV_PIX_FMT_YUVA422P, | |||
| 2129 | AV_PIX_FMT_YUV440P, | |||
| 2130 | AV_PIX_FMT_YUV444P, | |||
| 2131 | AV_PIX_FMT_YUVA444P, | |||
| 2132 | AV_PIX_FMT_GBRP, | |||
| 2133 | AV_PIX_FMT_GBRAP, | |||
| 2134 | AV_PIX_FMT_NONE | |||
| 2135 | }; | |||
| 2136 | ||||
| 2137 | static const enum AVPixelFormat vp9_pix_fmts_highbd[] = { | |||
| 2138 | AV_PIX_FMT_YUV420P, | |||
| 2139 | AV_PIX_FMT_YUVA420P, | |||
| 2140 | AV_PIX_FMT_YUV422P, | |||
| 2141 | AV_PIX_FMT_YUVA422P, | |||
| 2142 | AV_PIX_FMT_YUV440P, | |||
| 2143 | AV_PIX_FMT_YUV444P, | |||
| 2144 | AV_PIX_FMT_YUVA444P, | |||
| 2145 | AV_PIX_FMT_YUV420P10AV_PIX_FMT_YUV420P10LE, | |||
| 2146 | AV_PIX_FMT_YUVA420P10AV_PIX_FMT_YUVA420P10LE, | |||
| 2147 | AV_PIX_FMT_YUV422P10AV_PIX_FMT_YUV422P10LE, | |||
| 2148 | AV_PIX_FMT_YUVA422P10AV_PIX_FMT_YUVA422P10LE, | |||
| 2149 | AV_PIX_FMT_YUV440P10AV_PIX_FMT_YUV440P10LE, | |||
| 2150 | AV_PIX_FMT_YUV444P10AV_PIX_FMT_YUV444P10LE, | |||
| 2151 | AV_PIX_FMT_YUVA444P10AV_PIX_FMT_YUVA444P10LE, | |||
| 2152 | AV_PIX_FMT_YUV420P12AV_PIX_FMT_YUV420P12LE, | |||
| 2153 | AV_PIX_FMT_YUV422P12AV_PIX_FMT_YUV422P12LE, | |||
| 2154 | AV_PIX_FMT_YUV440P12AV_PIX_FMT_YUV440P12LE, | |||
| 2155 | AV_PIX_FMT_YUV444P12AV_PIX_FMT_YUV444P12LE, | |||
| 2156 | AV_PIX_FMT_YUVA444P12AV_PIX_FMT_YUVA444P12LE, | |||
| 2157 | AV_PIX_FMT_GBRP, | |||
| 2158 | AV_PIX_FMT_GBRAP, | |||
| 2159 | AV_PIX_FMT_GBRP10AV_PIX_FMT_GBRP10LE, | |||
| 2160 | AV_PIX_FMT_GBRAP10AV_PIX_FMT_GBRAP10LE, | |||
| 2161 | AV_PIX_FMT_GBRP12AV_PIX_FMT_GBRP12LE, | |||
| 2162 | AV_PIX_FMT_GBRAP12AV_PIX_FMT_GBRAP12LE, | |||
| 2163 | AV_PIX_FMT_NONE | |||
| 2164 | }; | |||
| 2165 | ||||
| 2166 | static int vp9_get_supported_config(const AVCodecContext *avctx, | |||
| 2167 | const AVCodec *codec, | |||
| 2168 | enum AVCodecConfig config, | |||
| 2169 | unsigned flags, const void **out, | |||
| 2170 | int *out_num) | |||
| 2171 | { | |||
| 2172 | if (config == AV_CODEC_CONFIG_PIX_FORMAT) { | |||
| 2173 | vpx_codec_caps_t codec_caps = vpx_codec_get_caps(vpx_codec_vp9_cx()); | |||
| 2174 | if (codec_caps & VPX_CODEC_CAP_HIGHBITDEPTH0x4) { | |||
| 2175 | *out = vp9_pix_fmts_highbd; | |||
| 2176 | *out_num = FF_ARRAY_ELEMS(vp9_pix_fmts_highbd)(sizeof(vp9_pix_fmts_highbd) / sizeof((vp9_pix_fmts_highbd)[0 ])) - 1; | |||
| 2177 | } else { | |||
| 2178 | *out = vp9_pix_fmts_highcol; | |||
| 2179 | *out_num = FF_ARRAY_ELEMS(vp9_pix_fmts_highcol)(sizeof(vp9_pix_fmts_highcol) / sizeof((vp9_pix_fmts_highcol) [0])) - 1; | |||
| 2180 | } | |||
| 2181 | return 0; | |||
| 2182 | } | |||
| 2183 | ||||
| 2184 | return ff_default_get_supported_config(avctx, codec, config, flags, out, out_num); | |||
| 2185 | } | |||
| 2186 | ||||
| 2187 | static const AVClass class_vp9 = { | |||
| 2188 | .class_name = "libvpx-vp9 encoder", | |||
| 2189 | .item_name = av_default_item_name, | |||
| 2190 | .option = vp9_options, | |||
| 2191 | .version = LIBAVUTIL_VERSION_INT((60)<<16 | (29)<<8 | (100)), | |||
| 2192 | }; | |||
| 2193 | ||||
| 2194 | FFCodec ff_libvpx_vp9_encoder = { | |||
| 2195 | .p.name = "libvpx-vp9", | |||
| 2196 | CODEC_LONG_NAME("libvpx VP9").p.long_name = "libvpx VP9", | |||
| 2197 | .p.type = AVMEDIA_TYPE_VIDEO, | |||
| 2198 | .p.id = AV_CODEC_ID_VP9, | |||
| 2199 | .p.capabilities = AV_CODEC_CAP_DR1(1 << 1) | AV_CODEC_CAP_DELAY(1 << 5) | | |||
| 2200 | AV_CODEC_CAP_OTHER_THREADS(1 << 15) | | |||
| 2201 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE(1 << 20), | |||
| 2202 | .p.profiles = NULL_IF_CONFIG_SMALL(ff_vp9_profiles)ff_vp9_profiles, | |||
| 2203 | .p.priv_class = &class_vp9, | |||
| 2204 | .p.wrapper_name = "libvpx", | |||
| 2205 | .priv_data_size = sizeof(VPxContext), | |||
| 2206 | .init = vp9_init, | |||
| 2207 | .color_ranges = AVCOL_RANGE_MPEG | AVCOL_RANGE_JPEG, | |||
| 2208 | FF_CODEC_ENCODE_CB(vpx_encode).is_decoder = 0, .cb_type = FF_CODEC_CB_TYPE_ENCODE, .cb.encode = (vpx_encode), | |||
| 2209 | .close = vpx_free, | |||
| 2210 | .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE(1 << 0) | | |||
| 2211 | FF_CODEC_CAP_INIT_CLEANUP(1 << 1) | | |||
| 2212 | FF_CODEC_CAP_AUTO_THREADS(1 << 7), | |||
| 2213 | .defaults = defaults, | |||
| 2214 | .get_supported_config = vp9_get_supported_config, | |||
| 2215 | }; | |||
| 2216 | #endif /* CONFIG_LIBVPX_VP9_ENCODER */ |