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