1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * libx265 encoder 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * Copyright (c) 2013-2014 Derek Buitenhuis 5cabdff1aSopenharmony_ci * 6cabdff1aSopenharmony_ci * This file is part of FFmpeg. 7cabdff1aSopenharmony_ci * 8cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 9cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 10cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 11cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 12cabdff1aSopenharmony_ci * 13cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 14cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 15cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16cabdff1aSopenharmony_ci * Lesser General Public License for more details. 17cabdff1aSopenharmony_ci * 18cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 19cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 20cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21cabdff1aSopenharmony_ci */ 22cabdff1aSopenharmony_ci 23cabdff1aSopenharmony_ci#if defined(_MSC_VER) 24cabdff1aSopenharmony_ci#define X265_API_IMPORTS 1 25cabdff1aSopenharmony_ci#endif 26cabdff1aSopenharmony_ci 27cabdff1aSopenharmony_ci#include <x265.h> 28cabdff1aSopenharmony_ci#include <float.h> 29cabdff1aSopenharmony_ci 30cabdff1aSopenharmony_ci#include "libavutil/internal.h" 31cabdff1aSopenharmony_ci#include "libavutil/common.h" 32cabdff1aSopenharmony_ci#include "libavutil/opt.h" 33cabdff1aSopenharmony_ci#include "libavutil/pixdesc.h" 34cabdff1aSopenharmony_ci#include "avcodec.h" 35cabdff1aSopenharmony_ci#include "codec_internal.h" 36cabdff1aSopenharmony_ci#include "encode.h" 37cabdff1aSopenharmony_ci#include "internal.h" 38cabdff1aSopenharmony_ci#include "packet_internal.h" 39cabdff1aSopenharmony_ci#include "sei.h" 40cabdff1aSopenharmony_ci 41cabdff1aSopenharmony_citypedef struct libx265Context { 42cabdff1aSopenharmony_ci const AVClass *class; 43cabdff1aSopenharmony_ci 44cabdff1aSopenharmony_ci x265_encoder *encoder; 45cabdff1aSopenharmony_ci x265_param *params; 46cabdff1aSopenharmony_ci const x265_api *api; 47cabdff1aSopenharmony_ci 48cabdff1aSopenharmony_ci float crf; 49cabdff1aSopenharmony_ci int cqp; 50cabdff1aSopenharmony_ci int forced_idr; 51cabdff1aSopenharmony_ci char *preset; 52cabdff1aSopenharmony_ci char *tune; 53cabdff1aSopenharmony_ci char *profile; 54cabdff1aSopenharmony_ci AVDictionary *x265_opts; 55cabdff1aSopenharmony_ci 56cabdff1aSopenharmony_ci void *sei_data; 57cabdff1aSopenharmony_ci int sei_data_size; 58cabdff1aSopenharmony_ci int udu_sei; 59cabdff1aSopenharmony_ci 60cabdff1aSopenharmony_ci /** 61cabdff1aSopenharmony_ci * If the encoder does not support ROI then warn the first time we 62cabdff1aSopenharmony_ci * encounter a frame with ROI side data. 63cabdff1aSopenharmony_ci */ 64cabdff1aSopenharmony_ci int roi_warned; 65cabdff1aSopenharmony_ci} libx265Context; 66cabdff1aSopenharmony_ci 67cabdff1aSopenharmony_cistatic int is_keyframe(NalUnitType naltype) 68cabdff1aSopenharmony_ci{ 69cabdff1aSopenharmony_ci switch (naltype) { 70cabdff1aSopenharmony_ci case NAL_UNIT_CODED_SLICE_BLA_W_LP: 71cabdff1aSopenharmony_ci case NAL_UNIT_CODED_SLICE_BLA_W_RADL: 72cabdff1aSopenharmony_ci case NAL_UNIT_CODED_SLICE_BLA_N_LP: 73cabdff1aSopenharmony_ci case NAL_UNIT_CODED_SLICE_IDR_W_RADL: 74cabdff1aSopenharmony_ci case NAL_UNIT_CODED_SLICE_IDR_N_LP: 75cabdff1aSopenharmony_ci case NAL_UNIT_CODED_SLICE_CRA: 76cabdff1aSopenharmony_ci return 1; 77cabdff1aSopenharmony_ci default: 78cabdff1aSopenharmony_ci return 0; 79cabdff1aSopenharmony_ci } 80cabdff1aSopenharmony_ci} 81cabdff1aSopenharmony_ci 82cabdff1aSopenharmony_cistatic av_cold int libx265_encode_close(AVCodecContext *avctx) 83cabdff1aSopenharmony_ci{ 84cabdff1aSopenharmony_ci libx265Context *ctx = avctx->priv_data; 85cabdff1aSopenharmony_ci 86cabdff1aSopenharmony_ci ctx->api->param_free(ctx->params); 87cabdff1aSopenharmony_ci av_freep(&ctx->sei_data); 88cabdff1aSopenharmony_ci 89cabdff1aSopenharmony_ci if (ctx->encoder) 90cabdff1aSopenharmony_ci ctx->api->encoder_close(ctx->encoder); 91cabdff1aSopenharmony_ci 92cabdff1aSopenharmony_ci return 0; 93cabdff1aSopenharmony_ci} 94cabdff1aSopenharmony_ci 95cabdff1aSopenharmony_cistatic av_cold int libx265_param_parse_float(AVCodecContext *avctx, 96cabdff1aSopenharmony_ci const char *key, float value) 97cabdff1aSopenharmony_ci{ 98cabdff1aSopenharmony_ci libx265Context *ctx = avctx->priv_data; 99cabdff1aSopenharmony_ci char buf[256]; 100cabdff1aSopenharmony_ci 101cabdff1aSopenharmony_ci snprintf(buf, sizeof(buf), "%2.2f", value); 102cabdff1aSopenharmony_ci if (ctx->api->param_parse(ctx->params, key, buf) == X265_PARAM_BAD_VALUE) { 103cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Invalid value %2.2f for param \"%s\".\n", value, key); 104cabdff1aSopenharmony_ci return AVERROR(EINVAL); 105cabdff1aSopenharmony_ci } 106cabdff1aSopenharmony_ci 107cabdff1aSopenharmony_ci return 0; 108cabdff1aSopenharmony_ci} 109cabdff1aSopenharmony_ci 110cabdff1aSopenharmony_cistatic av_cold int libx265_param_parse_int(AVCodecContext *avctx, 111cabdff1aSopenharmony_ci const char *key, int value) 112cabdff1aSopenharmony_ci{ 113cabdff1aSopenharmony_ci libx265Context *ctx = avctx->priv_data; 114cabdff1aSopenharmony_ci char buf[256]; 115cabdff1aSopenharmony_ci 116cabdff1aSopenharmony_ci snprintf(buf, sizeof(buf), "%d", value); 117cabdff1aSopenharmony_ci if (ctx->api->param_parse(ctx->params, key, buf) == X265_PARAM_BAD_VALUE) { 118cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Invalid value %d for param \"%s\".\n", value, key); 119cabdff1aSopenharmony_ci return AVERROR(EINVAL); 120cabdff1aSopenharmony_ci } 121cabdff1aSopenharmony_ci 122cabdff1aSopenharmony_ci return 0; 123cabdff1aSopenharmony_ci} 124cabdff1aSopenharmony_ci 125cabdff1aSopenharmony_cistatic av_cold int libx265_encode_init(AVCodecContext *avctx) 126cabdff1aSopenharmony_ci{ 127cabdff1aSopenharmony_ci libx265Context *ctx = avctx->priv_data; 128cabdff1aSopenharmony_ci AVCPBProperties *cpb_props = NULL; 129cabdff1aSopenharmony_ci const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt); 130cabdff1aSopenharmony_ci int ret; 131cabdff1aSopenharmony_ci 132cabdff1aSopenharmony_ci ctx->api = x265_api_get(desc->comp[0].depth); 133cabdff1aSopenharmony_ci if (!ctx->api) 134cabdff1aSopenharmony_ci ctx->api = x265_api_get(0); 135cabdff1aSopenharmony_ci 136cabdff1aSopenharmony_ci ctx->params = ctx->api->param_alloc(); 137cabdff1aSopenharmony_ci if (!ctx->params) { 138cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Could not allocate x265 param structure.\n"); 139cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 140cabdff1aSopenharmony_ci } 141cabdff1aSopenharmony_ci 142cabdff1aSopenharmony_ci if (ctx->api->param_default_preset(ctx->params, ctx->preset, ctx->tune) < 0) { 143cabdff1aSopenharmony_ci int i; 144cabdff1aSopenharmony_ci 145cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Error setting preset/tune %s/%s.\n", ctx->preset, ctx->tune); 146cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_INFO, "Possible presets:"); 147cabdff1aSopenharmony_ci for (i = 0; x265_preset_names[i]; i++) 148cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_INFO, " %s", x265_preset_names[i]); 149cabdff1aSopenharmony_ci 150cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_INFO, "\n"); 151cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_INFO, "Possible tunes:"); 152cabdff1aSopenharmony_ci for (i = 0; x265_tune_names[i]; i++) 153cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_INFO, " %s", x265_tune_names[i]); 154cabdff1aSopenharmony_ci 155cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_INFO, "\n"); 156cabdff1aSopenharmony_ci 157cabdff1aSopenharmony_ci return AVERROR(EINVAL); 158cabdff1aSopenharmony_ci } 159cabdff1aSopenharmony_ci 160cabdff1aSopenharmony_ci ctx->params->frameNumThreads = avctx->thread_count; 161cabdff1aSopenharmony_ci if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { 162cabdff1aSopenharmony_ci ctx->params->fpsNum = avctx->framerate.num; 163cabdff1aSopenharmony_ci ctx->params->fpsDenom = avctx->framerate.den; 164cabdff1aSopenharmony_ci } else { 165cabdff1aSopenharmony_ci ctx->params->fpsNum = avctx->time_base.den; 166cabdff1aSopenharmony_ci ctx->params->fpsDenom = avctx->time_base.num * avctx->ticks_per_frame; 167cabdff1aSopenharmony_ci } 168cabdff1aSopenharmony_ci ctx->params->sourceWidth = avctx->width; 169cabdff1aSopenharmony_ci ctx->params->sourceHeight = avctx->height; 170cabdff1aSopenharmony_ci ctx->params->bEnablePsnr = !!(avctx->flags & AV_CODEC_FLAG_PSNR); 171cabdff1aSopenharmony_ci ctx->params->bOpenGOP = !(avctx->flags & AV_CODEC_FLAG_CLOSED_GOP); 172cabdff1aSopenharmony_ci 173cabdff1aSopenharmony_ci /* Tune the CTU size based on input resolution. */ 174cabdff1aSopenharmony_ci if (ctx->params->sourceWidth < 64 || ctx->params->sourceHeight < 64) 175cabdff1aSopenharmony_ci ctx->params->maxCUSize = 32; 176cabdff1aSopenharmony_ci if (ctx->params->sourceWidth < 32 || ctx->params->sourceHeight < 32) 177cabdff1aSopenharmony_ci ctx->params->maxCUSize = 16; 178cabdff1aSopenharmony_ci if (ctx->params->sourceWidth < 16 || ctx->params->sourceHeight < 16) { 179cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Image size is too small (%dx%d).\n", 180cabdff1aSopenharmony_ci ctx->params->sourceWidth, ctx->params->sourceHeight); 181cabdff1aSopenharmony_ci return AVERROR(EINVAL); 182cabdff1aSopenharmony_ci } 183cabdff1aSopenharmony_ci 184cabdff1aSopenharmony_ci 185cabdff1aSopenharmony_ci ctx->params->vui.bEnableVideoSignalTypePresentFlag = 1; 186cabdff1aSopenharmony_ci 187cabdff1aSopenharmony_ci if (avctx->color_range != AVCOL_RANGE_UNSPECIFIED) 188cabdff1aSopenharmony_ci ctx->params->vui.bEnableVideoFullRangeFlag = 189cabdff1aSopenharmony_ci avctx->color_range == AVCOL_RANGE_JPEG; 190cabdff1aSopenharmony_ci else 191cabdff1aSopenharmony_ci ctx->params->vui.bEnableVideoFullRangeFlag = 192cabdff1aSopenharmony_ci (desc->flags & AV_PIX_FMT_FLAG_RGB) || 193cabdff1aSopenharmony_ci avctx->pix_fmt == AV_PIX_FMT_YUVJ420P || 194cabdff1aSopenharmony_ci avctx->pix_fmt == AV_PIX_FMT_YUVJ422P || 195cabdff1aSopenharmony_ci avctx->pix_fmt == AV_PIX_FMT_YUVJ444P; 196cabdff1aSopenharmony_ci 197cabdff1aSopenharmony_ci if ((avctx->color_primaries <= AVCOL_PRI_SMPTE432 && 198cabdff1aSopenharmony_ci avctx->color_primaries != AVCOL_PRI_UNSPECIFIED) || 199cabdff1aSopenharmony_ci (avctx->color_trc <= AVCOL_TRC_ARIB_STD_B67 && 200cabdff1aSopenharmony_ci avctx->color_trc != AVCOL_TRC_UNSPECIFIED) || 201cabdff1aSopenharmony_ci (avctx->colorspace <= AVCOL_SPC_ICTCP && 202cabdff1aSopenharmony_ci avctx->colorspace != AVCOL_SPC_UNSPECIFIED)) { 203cabdff1aSopenharmony_ci 204cabdff1aSopenharmony_ci ctx->params->vui.bEnableColorDescriptionPresentFlag = 1; 205cabdff1aSopenharmony_ci 206cabdff1aSopenharmony_ci // x265 validates the parameters internally 207cabdff1aSopenharmony_ci ctx->params->vui.colorPrimaries = avctx->color_primaries; 208cabdff1aSopenharmony_ci ctx->params->vui.transferCharacteristics = avctx->color_trc; 209cabdff1aSopenharmony_ci#if X265_BUILD >= 159 210cabdff1aSopenharmony_ci if (avctx->color_trc == AVCOL_TRC_ARIB_STD_B67) 211cabdff1aSopenharmony_ci ctx->params->preferredTransferCharacteristics = ctx->params->vui.transferCharacteristics; 212cabdff1aSopenharmony_ci#endif 213cabdff1aSopenharmony_ci ctx->params->vui.matrixCoeffs = avctx->colorspace; 214cabdff1aSopenharmony_ci } 215cabdff1aSopenharmony_ci 216cabdff1aSopenharmony_ci // chroma sample location values are to be ignored in case of non-4:2:0 217cabdff1aSopenharmony_ci // according to the specification, so we only write them out in case of 218cabdff1aSopenharmony_ci // 4:2:0 (log2_chroma_{w,h} == 1). 219cabdff1aSopenharmony_ci ctx->params->vui.bEnableChromaLocInfoPresentFlag = 220cabdff1aSopenharmony_ci avctx->chroma_sample_location != AVCHROMA_LOC_UNSPECIFIED && 221cabdff1aSopenharmony_ci desc->log2_chroma_w == 1 && desc->log2_chroma_h == 1; 222cabdff1aSopenharmony_ci 223cabdff1aSopenharmony_ci if (ctx->params->vui.bEnableChromaLocInfoPresentFlag) { 224cabdff1aSopenharmony_ci ctx->params->vui.chromaSampleLocTypeTopField = 225cabdff1aSopenharmony_ci ctx->params->vui.chromaSampleLocTypeBottomField = 226cabdff1aSopenharmony_ci avctx->chroma_sample_location - 1; 227cabdff1aSopenharmony_ci } 228cabdff1aSopenharmony_ci 229cabdff1aSopenharmony_ci if (avctx->sample_aspect_ratio.num > 0 && avctx->sample_aspect_ratio.den > 0) { 230cabdff1aSopenharmony_ci char sar[12]; 231cabdff1aSopenharmony_ci int sar_num, sar_den; 232cabdff1aSopenharmony_ci 233cabdff1aSopenharmony_ci av_reduce(&sar_num, &sar_den, 234cabdff1aSopenharmony_ci avctx->sample_aspect_ratio.num, 235cabdff1aSopenharmony_ci avctx->sample_aspect_ratio.den, 65535); 236cabdff1aSopenharmony_ci snprintf(sar, sizeof(sar), "%d:%d", sar_num, sar_den); 237cabdff1aSopenharmony_ci if (ctx->api->param_parse(ctx->params, "sar", sar) == X265_PARAM_BAD_VALUE) { 238cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Invalid SAR: %d:%d.\n", sar_num, sar_den); 239cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 240cabdff1aSopenharmony_ci } 241cabdff1aSopenharmony_ci } 242cabdff1aSopenharmony_ci 243cabdff1aSopenharmony_ci switch (desc->log2_chroma_w) { 244cabdff1aSopenharmony_ci // 4:4:4, RGB. gray 245cabdff1aSopenharmony_ci case 0: 246cabdff1aSopenharmony_ci // gray 247cabdff1aSopenharmony_ci if (desc->nb_components == 1) { 248cabdff1aSopenharmony_ci if (ctx->api->api_build_number < 85) { 249cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 250cabdff1aSopenharmony_ci "libx265 version is %d, must be at least 85 for gray encoding.\n", 251cabdff1aSopenharmony_ci ctx->api->api_build_number); 252cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 253cabdff1aSopenharmony_ci } 254cabdff1aSopenharmony_ci ctx->params->internalCsp = X265_CSP_I400; 255cabdff1aSopenharmony_ci break; 256cabdff1aSopenharmony_ci } 257cabdff1aSopenharmony_ci 258cabdff1aSopenharmony_ci // set identity matrix for RGB 259cabdff1aSopenharmony_ci if (desc->flags & AV_PIX_FMT_FLAG_RGB) { 260cabdff1aSopenharmony_ci ctx->params->vui.matrixCoeffs = AVCOL_SPC_RGB; 261cabdff1aSopenharmony_ci ctx->params->vui.bEnableVideoSignalTypePresentFlag = 1; 262cabdff1aSopenharmony_ci ctx->params->vui.bEnableColorDescriptionPresentFlag = 1; 263cabdff1aSopenharmony_ci } 264cabdff1aSopenharmony_ci 265cabdff1aSopenharmony_ci ctx->params->internalCsp = X265_CSP_I444; 266cabdff1aSopenharmony_ci break; 267cabdff1aSopenharmony_ci // 4:2:0, 4:2:2 268cabdff1aSopenharmony_ci case 1: 269cabdff1aSopenharmony_ci ctx->params->internalCsp = desc->log2_chroma_h == 1 ? 270cabdff1aSopenharmony_ci X265_CSP_I420 : X265_CSP_I422; 271cabdff1aSopenharmony_ci break; 272cabdff1aSopenharmony_ci default: 273cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 274cabdff1aSopenharmony_ci "Pixel format '%s' cannot be mapped to a libx265 CSP!\n", 275cabdff1aSopenharmony_ci desc->name); 276cabdff1aSopenharmony_ci return AVERROR_BUG; 277cabdff1aSopenharmony_ci } 278cabdff1aSopenharmony_ci 279cabdff1aSopenharmony_ci if (ctx->crf >= 0) { 280cabdff1aSopenharmony_ci char crf[6]; 281cabdff1aSopenharmony_ci 282cabdff1aSopenharmony_ci snprintf(crf, sizeof(crf), "%2.2f", ctx->crf); 283cabdff1aSopenharmony_ci if (ctx->api->param_parse(ctx->params, "crf", crf) == X265_PARAM_BAD_VALUE) { 284cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Invalid crf: %2.2f.\n", ctx->crf); 285cabdff1aSopenharmony_ci return AVERROR(EINVAL); 286cabdff1aSopenharmony_ci } 287cabdff1aSopenharmony_ci } else if (avctx->bit_rate > 0) { 288cabdff1aSopenharmony_ci ctx->params->rc.bitrate = avctx->bit_rate / 1000; 289cabdff1aSopenharmony_ci ctx->params->rc.rateControlMode = X265_RC_ABR; 290cabdff1aSopenharmony_ci } else if (ctx->cqp >= 0) { 291cabdff1aSopenharmony_ci ret = libx265_param_parse_int(avctx, "qp", ctx->cqp); 292cabdff1aSopenharmony_ci if (ret < 0) 293cabdff1aSopenharmony_ci return ret; 294cabdff1aSopenharmony_ci } 295cabdff1aSopenharmony_ci 296cabdff1aSopenharmony_ci#if X265_BUILD >= 89 297cabdff1aSopenharmony_ci if (avctx->qmin >= 0) { 298cabdff1aSopenharmony_ci ret = libx265_param_parse_int(avctx, "qpmin", avctx->qmin); 299cabdff1aSopenharmony_ci if (ret < 0) 300cabdff1aSopenharmony_ci return ret; 301cabdff1aSopenharmony_ci } 302cabdff1aSopenharmony_ci if (avctx->qmax >= 0) { 303cabdff1aSopenharmony_ci ret = libx265_param_parse_int(avctx, "qpmax", avctx->qmax); 304cabdff1aSopenharmony_ci if (ret < 0) 305cabdff1aSopenharmony_ci return ret; 306cabdff1aSopenharmony_ci } 307cabdff1aSopenharmony_ci#endif 308cabdff1aSopenharmony_ci if (avctx->max_qdiff >= 0) { 309cabdff1aSopenharmony_ci ret = libx265_param_parse_int(avctx, "qpstep", avctx->max_qdiff); 310cabdff1aSopenharmony_ci if (ret < 0) 311cabdff1aSopenharmony_ci return ret; 312cabdff1aSopenharmony_ci } 313cabdff1aSopenharmony_ci if (avctx->qblur >= 0) { 314cabdff1aSopenharmony_ci ret = libx265_param_parse_float(avctx, "qblur", avctx->qblur); 315cabdff1aSopenharmony_ci if (ret < 0) 316cabdff1aSopenharmony_ci return ret; 317cabdff1aSopenharmony_ci } 318cabdff1aSopenharmony_ci if (avctx->qcompress >= 0) { 319cabdff1aSopenharmony_ci ret = libx265_param_parse_float(avctx, "qcomp", avctx->qcompress); 320cabdff1aSopenharmony_ci if (ret < 0) 321cabdff1aSopenharmony_ci return ret; 322cabdff1aSopenharmony_ci } 323cabdff1aSopenharmony_ci if (avctx->i_quant_factor >= 0) { 324cabdff1aSopenharmony_ci ret = libx265_param_parse_float(avctx, "ipratio", avctx->i_quant_factor); 325cabdff1aSopenharmony_ci if (ret < 0) 326cabdff1aSopenharmony_ci return ret; 327cabdff1aSopenharmony_ci } 328cabdff1aSopenharmony_ci if (avctx->b_quant_factor >= 0) { 329cabdff1aSopenharmony_ci ret = libx265_param_parse_float(avctx, "pbratio", avctx->b_quant_factor); 330cabdff1aSopenharmony_ci if (ret < 0) 331cabdff1aSopenharmony_ci return ret; 332cabdff1aSopenharmony_ci } 333cabdff1aSopenharmony_ci 334cabdff1aSopenharmony_ci ctx->params->rc.vbvBufferSize = avctx->rc_buffer_size / 1000; 335cabdff1aSopenharmony_ci ctx->params->rc.vbvMaxBitrate = avctx->rc_max_rate / 1000; 336cabdff1aSopenharmony_ci 337cabdff1aSopenharmony_ci cpb_props = ff_add_cpb_side_data(avctx); 338cabdff1aSopenharmony_ci if (!cpb_props) 339cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 340cabdff1aSopenharmony_ci cpb_props->buffer_size = ctx->params->rc.vbvBufferSize * 1000; 341cabdff1aSopenharmony_ci cpb_props->max_bitrate = ctx->params->rc.vbvMaxBitrate * 1000LL; 342cabdff1aSopenharmony_ci cpb_props->avg_bitrate = ctx->params->rc.bitrate * 1000LL; 343cabdff1aSopenharmony_ci 344cabdff1aSopenharmony_ci if (!(avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER)) 345cabdff1aSopenharmony_ci ctx->params->bRepeatHeaders = 1; 346cabdff1aSopenharmony_ci 347cabdff1aSopenharmony_ci if (avctx->gop_size >= 0) { 348cabdff1aSopenharmony_ci ret = libx265_param_parse_int(avctx, "keyint", avctx->gop_size); 349cabdff1aSopenharmony_ci if (ret < 0) 350cabdff1aSopenharmony_ci return ret; 351cabdff1aSopenharmony_ci } 352cabdff1aSopenharmony_ci if (avctx->keyint_min > 0) { 353cabdff1aSopenharmony_ci ret = libx265_param_parse_int(avctx, "min-keyint", avctx->keyint_min); 354cabdff1aSopenharmony_ci if (ret < 0) 355cabdff1aSopenharmony_ci return ret; 356cabdff1aSopenharmony_ci } 357cabdff1aSopenharmony_ci if (avctx->max_b_frames >= 0) { 358cabdff1aSopenharmony_ci ret = libx265_param_parse_int(avctx, "bframes", avctx->max_b_frames); 359cabdff1aSopenharmony_ci if (ret < 0) 360cabdff1aSopenharmony_ci return ret; 361cabdff1aSopenharmony_ci } 362cabdff1aSopenharmony_ci if (avctx->refs >= 0) { 363cabdff1aSopenharmony_ci ret = libx265_param_parse_int(avctx, "ref", avctx->refs); 364cabdff1aSopenharmony_ci if (ret < 0) 365cabdff1aSopenharmony_ci return ret; 366cabdff1aSopenharmony_ci } 367cabdff1aSopenharmony_ci 368cabdff1aSopenharmony_ci { 369cabdff1aSopenharmony_ci AVDictionaryEntry *en = NULL; 370cabdff1aSopenharmony_ci while ((en = av_dict_get(ctx->x265_opts, "", en, AV_DICT_IGNORE_SUFFIX))) { 371cabdff1aSopenharmony_ci int parse_ret = ctx->api->param_parse(ctx->params, en->key, en->value); 372cabdff1aSopenharmony_ci 373cabdff1aSopenharmony_ci switch (parse_ret) { 374cabdff1aSopenharmony_ci case X265_PARAM_BAD_NAME: 375cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, 376cabdff1aSopenharmony_ci "Unknown option: %s.\n", en->key); 377cabdff1aSopenharmony_ci break; 378cabdff1aSopenharmony_ci case X265_PARAM_BAD_VALUE: 379cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, 380cabdff1aSopenharmony_ci "Invalid value for %s: %s.\n", en->key, en->value); 381cabdff1aSopenharmony_ci break; 382cabdff1aSopenharmony_ci default: 383cabdff1aSopenharmony_ci break; 384cabdff1aSopenharmony_ci } 385cabdff1aSopenharmony_ci } 386cabdff1aSopenharmony_ci } 387cabdff1aSopenharmony_ci 388cabdff1aSopenharmony_ci if (ctx->params->rc.vbvBufferSize && avctx->rc_initial_buffer_occupancy > 1000 && 389cabdff1aSopenharmony_ci ctx->params->rc.vbvBufferInit == 0.9) { 390cabdff1aSopenharmony_ci ctx->params->rc.vbvBufferInit = (float)avctx->rc_initial_buffer_occupancy / 1000; 391cabdff1aSopenharmony_ci } 392cabdff1aSopenharmony_ci 393cabdff1aSopenharmony_ci if (ctx->profile) { 394cabdff1aSopenharmony_ci if (ctx->api->param_apply_profile(ctx->params, ctx->profile) < 0) { 395cabdff1aSopenharmony_ci int i; 396cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Invalid or incompatible profile set: %s.\n", ctx->profile); 397cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_INFO, "Possible profiles:"); 398cabdff1aSopenharmony_ci for (i = 0; x265_profile_names[i]; i++) 399cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_INFO, " %s", x265_profile_names[i]); 400cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_INFO, "\n"); 401cabdff1aSopenharmony_ci return AVERROR(EINVAL); 402cabdff1aSopenharmony_ci } 403cabdff1aSopenharmony_ci } 404cabdff1aSopenharmony_ci 405cabdff1aSopenharmony_ci ctx->encoder = ctx->api->encoder_open(ctx->params); 406cabdff1aSopenharmony_ci if (!ctx->encoder) { 407cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Cannot open libx265 encoder.\n"); 408cabdff1aSopenharmony_ci libx265_encode_close(avctx); 409cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 410cabdff1aSopenharmony_ci } 411cabdff1aSopenharmony_ci 412cabdff1aSopenharmony_ci if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) { 413cabdff1aSopenharmony_ci x265_nal *nal; 414cabdff1aSopenharmony_ci int nnal; 415cabdff1aSopenharmony_ci 416cabdff1aSopenharmony_ci avctx->extradata_size = ctx->api->encoder_headers(ctx->encoder, &nal, &nnal); 417cabdff1aSopenharmony_ci if (avctx->extradata_size <= 0) { 418cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Cannot encode headers.\n"); 419cabdff1aSopenharmony_ci libx265_encode_close(avctx); 420cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 421cabdff1aSopenharmony_ci } 422cabdff1aSopenharmony_ci 423cabdff1aSopenharmony_ci avctx->extradata = av_malloc(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); 424cabdff1aSopenharmony_ci if (!avctx->extradata) { 425cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 426cabdff1aSopenharmony_ci "Cannot allocate HEVC header of size %d.\n", avctx->extradata_size); 427cabdff1aSopenharmony_ci libx265_encode_close(avctx); 428cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 429cabdff1aSopenharmony_ci } 430cabdff1aSopenharmony_ci 431cabdff1aSopenharmony_ci memcpy(avctx->extradata, nal[0].payload, avctx->extradata_size); 432cabdff1aSopenharmony_ci memset(avctx->extradata + avctx->extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); 433cabdff1aSopenharmony_ci } 434cabdff1aSopenharmony_ci 435cabdff1aSopenharmony_ci return 0; 436cabdff1aSopenharmony_ci} 437cabdff1aSopenharmony_ci 438cabdff1aSopenharmony_cistatic av_cold int libx265_encode_set_roi(libx265Context *ctx, const AVFrame *frame, x265_picture* pic) 439cabdff1aSopenharmony_ci{ 440cabdff1aSopenharmony_ci AVFrameSideData *sd = av_frame_get_side_data(frame, AV_FRAME_DATA_REGIONS_OF_INTEREST); 441cabdff1aSopenharmony_ci if (sd) { 442cabdff1aSopenharmony_ci if (ctx->params->rc.aqMode == X265_AQ_NONE) { 443cabdff1aSopenharmony_ci if (!ctx->roi_warned) { 444cabdff1aSopenharmony_ci ctx->roi_warned = 1; 445cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_WARNING, "Adaptive quantization must be enabled to use ROI encoding, skipping ROI.\n"); 446cabdff1aSopenharmony_ci } 447cabdff1aSopenharmony_ci } else { 448cabdff1aSopenharmony_ci /* 8x8 block when qg-size is 8, 16*16 block otherwise. */ 449cabdff1aSopenharmony_ci int mb_size = (ctx->params->rc.qgSize == 8) ? 8 : 16; 450cabdff1aSopenharmony_ci int mbx = (frame->width + mb_size - 1) / mb_size; 451cabdff1aSopenharmony_ci int mby = (frame->height + mb_size - 1) / mb_size; 452cabdff1aSopenharmony_ci int qp_range = 51 + 6 * (pic->bitDepth - 8); 453cabdff1aSopenharmony_ci int nb_rois; 454cabdff1aSopenharmony_ci const AVRegionOfInterest *roi; 455cabdff1aSopenharmony_ci uint32_t roi_size; 456cabdff1aSopenharmony_ci float *qoffsets; /* will be freed after encode is called. */ 457cabdff1aSopenharmony_ci 458cabdff1aSopenharmony_ci roi = (const AVRegionOfInterest*)sd->data; 459cabdff1aSopenharmony_ci roi_size = roi->self_size; 460cabdff1aSopenharmony_ci if (!roi_size || sd->size % roi_size != 0) { 461cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_ERROR, "Invalid AVRegionOfInterest.self_size.\n"); 462cabdff1aSopenharmony_ci return AVERROR(EINVAL); 463cabdff1aSopenharmony_ci } 464cabdff1aSopenharmony_ci nb_rois = sd->size / roi_size; 465cabdff1aSopenharmony_ci 466cabdff1aSopenharmony_ci qoffsets = av_calloc(mbx * mby, sizeof(*qoffsets)); 467cabdff1aSopenharmony_ci if (!qoffsets) 468cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 469cabdff1aSopenharmony_ci 470cabdff1aSopenharmony_ci // This list must be iterated in reverse because the first 471cabdff1aSopenharmony_ci // region in the list applies when regions overlap. 472cabdff1aSopenharmony_ci for (int i = nb_rois - 1; i >= 0; i--) { 473cabdff1aSopenharmony_ci int startx, endx, starty, endy; 474cabdff1aSopenharmony_ci float qoffset; 475cabdff1aSopenharmony_ci 476cabdff1aSopenharmony_ci roi = (const AVRegionOfInterest*)(sd->data + roi_size * i); 477cabdff1aSopenharmony_ci 478cabdff1aSopenharmony_ci starty = FFMIN(mby, roi->top / mb_size); 479cabdff1aSopenharmony_ci endy = FFMIN(mby, (roi->bottom + mb_size - 1)/ mb_size); 480cabdff1aSopenharmony_ci startx = FFMIN(mbx, roi->left / mb_size); 481cabdff1aSopenharmony_ci endx = FFMIN(mbx, (roi->right + mb_size - 1)/ mb_size); 482cabdff1aSopenharmony_ci 483cabdff1aSopenharmony_ci if (roi->qoffset.den == 0) { 484cabdff1aSopenharmony_ci av_free(qoffsets); 485cabdff1aSopenharmony_ci av_log(ctx, AV_LOG_ERROR, "AVRegionOfInterest.qoffset.den must not be zero.\n"); 486cabdff1aSopenharmony_ci return AVERROR(EINVAL); 487cabdff1aSopenharmony_ci } 488cabdff1aSopenharmony_ci qoffset = roi->qoffset.num * 1.0f / roi->qoffset.den; 489cabdff1aSopenharmony_ci qoffset = av_clipf(qoffset * qp_range, -qp_range, +qp_range); 490cabdff1aSopenharmony_ci 491cabdff1aSopenharmony_ci for (int y = starty; y < endy; y++) 492cabdff1aSopenharmony_ci for (int x = startx; x < endx; x++) 493cabdff1aSopenharmony_ci qoffsets[x + y*mbx] = qoffset; 494cabdff1aSopenharmony_ci } 495cabdff1aSopenharmony_ci 496cabdff1aSopenharmony_ci pic->quantOffsets = qoffsets; 497cabdff1aSopenharmony_ci } 498cabdff1aSopenharmony_ci } 499cabdff1aSopenharmony_ci return 0; 500cabdff1aSopenharmony_ci} 501cabdff1aSopenharmony_ci 502cabdff1aSopenharmony_cistatic int libx265_encode_frame(AVCodecContext *avctx, AVPacket *pkt, 503cabdff1aSopenharmony_ci const AVFrame *pic, int *got_packet) 504cabdff1aSopenharmony_ci{ 505cabdff1aSopenharmony_ci libx265Context *ctx = avctx->priv_data; 506cabdff1aSopenharmony_ci x265_picture x265pic; 507cabdff1aSopenharmony_ci x265_picture x265pic_out = { 0 }; 508cabdff1aSopenharmony_ci x265_nal *nal; 509cabdff1aSopenharmony_ci uint8_t *dst; 510cabdff1aSopenharmony_ci int pict_type; 511cabdff1aSopenharmony_ci int payload = 0; 512cabdff1aSopenharmony_ci int nnal; 513cabdff1aSopenharmony_ci int ret; 514cabdff1aSopenharmony_ci int i; 515cabdff1aSopenharmony_ci 516cabdff1aSopenharmony_ci ctx->api->picture_init(ctx->params, &x265pic); 517cabdff1aSopenharmony_ci 518cabdff1aSopenharmony_ci if (pic) { 519cabdff1aSopenharmony_ci x265_sei *sei = &x265pic.userSEI; 520cabdff1aSopenharmony_ci sei->numPayloads = 0; 521cabdff1aSopenharmony_ci for (i = 0; i < 3; i++) { 522cabdff1aSopenharmony_ci x265pic.planes[i] = pic->data[i]; 523cabdff1aSopenharmony_ci x265pic.stride[i] = pic->linesize[i]; 524cabdff1aSopenharmony_ci } 525cabdff1aSopenharmony_ci 526cabdff1aSopenharmony_ci x265pic.pts = pic->pts; 527cabdff1aSopenharmony_ci x265pic.bitDepth = av_pix_fmt_desc_get(avctx->pix_fmt)->comp[0].depth; 528cabdff1aSopenharmony_ci 529cabdff1aSopenharmony_ci x265pic.sliceType = pic->pict_type == AV_PICTURE_TYPE_I ? 530cabdff1aSopenharmony_ci (ctx->forced_idr ? X265_TYPE_IDR : X265_TYPE_I) : 531cabdff1aSopenharmony_ci pic->pict_type == AV_PICTURE_TYPE_P ? X265_TYPE_P : 532cabdff1aSopenharmony_ci pic->pict_type == AV_PICTURE_TYPE_B ? X265_TYPE_B : 533cabdff1aSopenharmony_ci X265_TYPE_AUTO; 534cabdff1aSopenharmony_ci 535cabdff1aSopenharmony_ci ret = libx265_encode_set_roi(ctx, pic, &x265pic); 536cabdff1aSopenharmony_ci if (ret < 0) 537cabdff1aSopenharmony_ci return ret; 538cabdff1aSopenharmony_ci 539cabdff1aSopenharmony_ci if (pic->reordered_opaque) { 540cabdff1aSopenharmony_ci x265pic.userData = av_malloc(sizeof(pic->reordered_opaque)); 541cabdff1aSopenharmony_ci if (!x265pic.userData) { 542cabdff1aSopenharmony_ci av_freep(&x265pic.quantOffsets); 543cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 544cabdff1aSopenharmony_ci } 545cabdff1aSopenharmony_ci 546cabdff1aSopenharmony_ci memcpy(x265pic.userData, &pic->reordered_opaque, sizeof(pic->reordered_opaque)); 547cabdff1aSopenharmony_ci } 548cabdff1aSopenharmony_ci 549cabdff1aSopenharmony_ci if (ctx->udu_sei) { 550cabdff1aSopenharmony_ci for (i = 0; i < pic->nb_side_data; i++) { 551cabdff1aSopenharmony_ci AVFrameSideData *side_data = pic->side_data[i]; 552cabdff1aSopenharmony_ci void *tmp; 553cabdff1aSopenharmony_ci x265_sei_payload *sei_payload; 554cabdff1aSopenharmony_ci 555cabdff1aSopenharmony_ci if (side_data->type != AV_FRAME_DATA_SEI_UNREGISTERED) 556cabdff1aSopenharmony_ci continue; 557cabdff1aSopenharmony_ci 558cabdff1aSopenharmony_ci tmp = av_fast_realloc(ctx->sei_data, 559cabdff1aSopenharmony_ci &ctx->sei_data_size, 560cabdff1aSopenharmony_ci (sei->numPayloads + 1) * sizeof(*sei_payload)); 561cabdff1aSopenharmony_ci if (!tmp) { 562cabdff1aSopenharmony_ci av_freep(&x265pic.userData); 563cabdff1aSopenharmony_ci av_freep(&x265pic.quantOffsets); 564cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 565cabdff1aSopenharmony_ci } 566cabdff1aSopenharmony_ci ctx->sei_data = tmp; 567cabdff1aSopenharmony_ci sei->payloads = ctx->sei_data; 568cabdff1aSopenharmony_ci sei_payload = &sei->payloads[sei->numPayloads]; 569cabdff1aSopenharmony_ci sei_payload->payload = side_data->data; 570cabdff1aSopenharmony_ci sei_payload->payloadSize = side_data->size; 571cabdff1aSopenharmony_ci /* Equal to libx265 USER_DATA_UNREGISTERED */ 572cabdff1aSopenharmony_ci sei_payload->payloadType = SEI_TYPE_USER_DATA_UNREGISTERED; 573cabdff1aSopenharmony_ci sei->numPayloads++; 574cabdff1aSopenharmony_ci } 575cabdff1aSopenharmony_ci } 576cabdff1aSopenharmony_ci } 577cabdff1aSopenharmony_ci 578cabdff1aSopenharmony_ci ret = ctx->api->encoder_encode(ctx->encoder, &nal, &nnal, 579cabdff1aSopenharmony_ci pic ? &x265pic : NULL, &x265pic_out); 580cabdff1aSopenharmony_ci 581cabdff1aSopenharmony_ci av_freep(&x265pic.quantOffsets); 582cabdff1aSopenharmony_ci 583cabdff1aSopenharmony_ci if (ret < 0) 584cabdff1aSopenharmony_ci return AVERROR_EXTERNAL; 585cabdff1aSopenharmony_ci 586cabdff1aSopenharmony_ci if (!nnal) 587cabdff1aSopenharmony_ci return 0; 588cabdff1aSopenharmony_ci 589cabdff1aSopenharmony_ci for (i = 0; i < nnal; i++) 590cabdff1aSopenharmony_ci payload += nal[i].sizeBytes; 591cabdff1aSopenharmony_ci 592cabdff1aSopenharmony_ci ret = ff_get_encode_buffer(avctx, pkt, payload, 0); 593cabdff1aSopenharmony_ci if (ret < 0) { 594cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Error getting output packet.\n"); 595cabdff1aSopenharmony_ci return ret; 596cabdff1aSopenharmony_ci } 597cabdff1aSopenharmony_ci dst = pkt->data; 598cabdff1aSopenharmony_ci 599cabdff1aSopenharmony_ci for (i = 0; i < nnal; i++) { 600cabdff1aSopenharmony_ci memcpy(dst, nal[i].payload, nal[i].sizeBytes); 601cabdff1aSopenharmony_ci dst += nal[i].sizeBytes; 602cabdff1aSopenharmony_ci 603cabdff1aSopenharmony_ci if (is_keyframe(nal[i].type)) 604cabdff1aSopenharmony_ci pkt->flags |= AV_PKT_FLAG_KEY; 605cabdff1aSopenharmony_ci } 606cabdff1aSopenharmony_ci 607cabdff1aSopenharmony_ci pkt->pts = x265pic_out.pts; 608cabdff1aSopenharmony_ci pkt->dts = x265pic_out.dts; 609cabdff1aSopenharmony_ci 610cabdff1aSopenharmony_ci switch (x265pic_out.sliceType) { 611cabdff1aSopenharmony_ci case X265_TYPE_IDR: 612cabdff1aSopenharmony_ci case X265_TYPE_I: 613cabdff1aSopenharmony_ci pict_type = AV_PICTURE_TYPE_I; 614cabdff1aSopenharmony_ci break; 615cabdff1aSopenharmony_ci case X265_TYPE_P: 616cabdff1aSopenharmony_ci pict_type = AV_PICTURE_TYPE_P; 617cabdff1aSopenharmony_ci break; 618cabdff1aSopenharmony_ci case X265_TYPE_B: 619cabdff1aSopenharmony_ci case X265_TYPE_BREF: 620cabdff1aSopenharmony_ci pict_type = AV_PICTURE_TYPE_B; 621cabdff1aSopenharmony_ci break; 622cabdff1aSopenharmony_ci default: 623cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Unknown picture type encountered.\n"); 624cabdff1aSopenharmony_ci return AVERROR_EXTERNAL; 625cabdff1aSopenharmony_ci } 626cabdff1aSopenharmony_ci 627cabdff1aSopenharmony_ci#if X265_BUILD >= 130 628cabdff1aSopenharmony_ci if (x265pic_out.sliceType == X265_TYPE_B) 629cabdff1aSopenharmony_ci#else 630cabdff1aSopenharmony_ci if (x265pic_out.frameData.sliceType == 'b') 631cabdff1aSopenharmony_ci#endif 632cabdff1aSopenharmony_ci pkt->flags |= AV_PKT_FLAG_DISPOSABLE; 633cabdff1aSopenharmony_ci 634cabdff1aSopenharmony_ci ff_side_data_set_encoder_stats(pkt, x265pic_out.frameData.qp * FF_QP2LAMBDA, NULL, 0, pict_type); 635cabdff1aSopenharmony_ci 636cabdff1aSopenharmony_ci if (x265pic_out.userData) { 637cabdff1aSopenharmony_ci memcpy(&avctx->reordered_opaque, x265pic_out.userData, sizeof(avctx->reordered_opaque)); 638cabdff1aSopenharmony_ci av_freep(&x265pic_out.userData); 639cabdff1aSopenharmony_ci } else 640cabdff1aSopenharmony_ci avctx->reordered_opaque = 0; 641cabdff1aSopenharmony_ci 642cabdff1aSopenharmony_ci *got_packet = 1; 643cabdff1aSopenharmony_ci return 0; 644cabdff1aSopenharmony_ci} 645cabdff1aSopenharmony_ci 646cabdff1aSopenharmony_cistatic const enum AVPixelFormat x265_csp_eight[] = { 647cabdff1aSopenharmony_ci AV_PIX_FMT_YUV420P, 648cabdff1aSopenharmony_ci AV_PIX_FMT_YUVJ420P, 649cabdff1aSopenharmony_ci AV_PIX_FMT_YUV422P, 650cabdff1aSopenharmony_ci AV_PIX_FMT_YUVJ422P, 651cabdff1aSopenharmony_ci AV_PIX_FMT_YUV444P, 652cabdff1aSopenharmony_ci AV_PIX_FMT_YUVJ444P, 653cabdff1aSopenharmony_ci AV_PIX_FMT_GBRP, 654cabdff1aSopenharmony_ci AV_PIX_FMT_GRAY8, 655cabdff1aSopenharmony_ci AV_PIX_FMT_NONE 656cabdff1aSopenharmony_ci}; 657cabdff1aSopenharmony_ci 658cabdff1aSopenharmony_cistatic const enum AVPixelFormat x265_csp_ten[] = { 659cabdff1aSopenharmony_ci AV_PIX_FMT_YUV420P, 660cabdff1aSopenharmony_ci AV_PIX_FMT_YUVJ420P, 661cabdff1aSopenharmony_ci AV_PIX_FMT_YUV422P, 662cabdff1aSopenharmony_ci AV_PIX_FMT_YUVJ422P, 663cabdff1aSopenharmony_ci AV_PIX_FMT_YUV444P, 664cabdff1aSopenharmony_ci AV_PIX_FMT_YUVJ444P, 665cabdff1aSopenharmony_ci AV_PIX_FMT_GBRP, 666cabdff1aSopenharmony_ci AV_PIX_FMT_YUV420P10, 667cabdff1aSopenharmony_ci AV_PIX_FMT_YUV422P10, 668cabdff1aSopenharmony_ci AV_PIX_FMT_YUV444P10, 669cabdff1aSopenharmony_ci AV_PIX_FMT_GBRP10, 670cabdff1aSopenharmony_ci AV_PIX_FMT_GRAY8, 671cabdff1aSopenharmony_ci AV_PIX_FMT_GRAY10, 672cabdff1aSopenharmony_ci AV_PIX_FMT_NONE 673cabdff1aSopenharmony_ci}; 674cabdff1aSopenharmony_ci 675cabdff1aSopenharmony_cistatic const enum AVPixelFormat x265_csp_twelve[] = { 676cabdff1aSopenharmony_ci AV_PIX_FMT_YUV420P, 677cabdff1aSopenharmony_ci AV_PIX_FMT_YUVJ420P, 678cabdff1aSopenharmony_ci AV_PIX_FMT_YUV422P, 679cabdff1aSopenharmony_ci AV_PIX_FMT_YUVJ422P, 680cabdff1aSopenharmony_ci AV_PIX_FMT_YUV444P, 681cabdff1aSopenharmony_ci AV_PIX_FMT_YUVJ444P, 682cabdff1aSopenharmony_ci AV_PIX_FMT_GBRP, 683cabdff1aSopenharmony_ci AV_PIX_FMT_YUV420P10, 684cabdff1aSopenharmony_ci AV_PIX_FMT_YUV422P10, 685cabdff1aSopenharmony_ci AV_PIX_FMT_YUV444P10, 686cabdff1aSopenharmony_ci AV_PIX_FMT_GBRP10, 687cabdff1aSopenharmony_ci AV_PIX_FMT_YUV420P12, 688cabdff1aSopenharmony_ci AV_PIX_FMT_YUV422P12, 689cabdff1aSopenharmony_ci AV_PIX_FMT_YUV444P12, 690cabdff1aSopenharmony_ci AV_PIX_FMT_GBRP12, 691cabdff1aSopenharmony_ci AV_PIX_FMT_GRAY8, 692cabdff1aSopenharmony_ci AV_PIX_FMT_GRAY10, 693cabdff1aSopenharmony_ci AV_PIX_FMT_GRAY12, 694cabdff1aSopenharmony_ci AV_PIX_FMT_NONE 695cabdff1aSopenharmony_ci}; 696cabdff1aSopenharmony_ci 697cabdff1aSopenharmony_cistatic av_cold void libx265_encode_init_csp(FFCodec *codec) 698cabdff1aSopenharmony_ci{ 699cabdff1aSopenharmony_ci if (x265_api_get(12)) 700cabdff1aSopenharmony_ci codec->p.pix_fmts = x265_csp_twelve; 701cabdff1aSopenharmony_ci else if (x265_api_get(10)) 702cabdff1aSopenharmony_ci codec->p.pix_fmts = x265_csp_ten; 703cabdff1aSopenharmony_ci else if (x265_api_get(8)) 704cabdff1aSopenharmony_ci codec->p.pix_fmts = x265_csp_eight; 705cabdff1aSopenharmony_ci} 706cabdff1aSopenharmony_ci 707cabdff1aSopenharmony_ci#define OFFSET(x) offsetof(libx265Context, x) 708cabdff1aSopenharmony_ci#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM 709cabdff1aSopenharmony_cistatic const AVOption options[] = { 710cabdff1aSopenharmony_ci { "crf", "set the x265 crf", OFFSET(crf), AV_OPT_TYPE_FLOAT, { .dbl = -1 }, -1, FLT_MAX, VE }, 711cabdff1aSopenharmony_ci { "qp", "set the x265 qp", OFFSET(cqp), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, VE }, 712cabdff1aSopenharmony_ci { "forced-idr", "if forcing keyframes, force them as IDR frames", OFFSET(forced_idr),AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, 713cabdff1aSopenharmony_ci { "preset", "set the x265 preset", OFFSET(preset), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE }, 714cabdff1aSopenharmony_ci { "tune", "set the x265 tune parameter", OFFSET(tune), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE }, 715cabdff1aSopenharmony_ci { "profile", "set the x265 profile", OFFSET(profile), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE }, 716cabdff1aSopenharmony_ci { "udu_sei", "Use user data unregistered SEI if available", OFFSET(udu_sei), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, 717cabdff1aSopenharmony_ci { "x265-params", "set the x265 configuration using a :-separated list of key=value parameters", OFFSET(x265_opts), AV_OPT_TYPE_DICT, { 0 }, 0, 0, VE }, 718cabdff1aSopenharmony_ci { NULL } 719cabdff1aSopenharmony_ci}; 720cabdff1aSopenharmony_ci 721cabdff1aSopenharmony_cistatic const AVClass class = { 722cabdff1aSopenharmony_ci .class_name = "libx265", 723cabdff1aSopenharmony_ci .item_name = av_default_item_name, 724cabdff1aSopenharmony_ci .option = options, 725cabdff1aSopenharmony_ci .version = LIBAVUTIL_VERSION_INT, 726cabdff1aSopenharmony_ci}; 727cabdff1aSopenharmony_ci 728cabdff1aSopenharmony_cistatic const FFCodecDefault x265_defaults[] = { 729cabdff1aSopenharmony_ci { "b", "0" }, 730cabdff1aSopenharmony_ci { "bf", "-1" }, 731cabdff1aSopenharmony_ci { "g", "-1" }, 732cabdff1aSopenharmony_ci { "keyint_min", "-1" }, 733cabdff1aSopenharmony_ci { "refs", "-1" }, 734cabdff1aSopenharmony_ci { "qmin", "-1" }, 735cabdff1aSopenharmony_ci { "qmax", "-1" }, 736cabdff1aSopenharmony_ci { "qdiff", "-1" }, 737cabdff1aSopenharmony_ci { "qblur", "-1" }, 738cabdff1aSopenharmony_ci { "qcomp", "-1" }, 739cabdff1aSopenharmony_ci { "i_qfactor", "-1" }, 740cabdff1aSopenharmony_ci { "b_qfactor", "-1" }, 741cabdff1aSopenharmony_ci { NULL }, 742cabdff1aSopenharmony_ci}; 743cabdff1aSopenharmony_ci 744cabdff1aSopenharmony_ciFFCodec ff_libx265_encoder = { 745cabdff1aSopenharmony_ci .p.name = "libx265", 746cabdff1aSopenharmony_ci .p.long_name = NULL_IF_CONFIG_SMALL("libx265 H.265 / HEVC"), 747cabdff1aSopenharmony_ci .p.type = AVMEDIA_TYPE_VIDEO, 748cabdff1aSopenharmony_ci .p.id = AV_CODEC_ID_HEVC, 749cabdff1aSopenharmony_ci .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | 750cabdff1aSopenharmony_ci AV_CODEC_CAP_OTHER_THREADS | 751cabdff1aSopenharmony_ci AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, 752cabdff1aSopenharmony_ci .p.priv_class = &class, 753cabdff1aSopenharmony_ci .p.wrapper_name = "libx265", 754cabdff1aSopenharmony_ci .init = libx265_encode_init, 755cabdff1aSopenharmony_ci .init_static_data = libx265_encode_init_csp, 756cabdff1aSopenharmony_ci FF_CODEC_ENCODE_CB(libx265_encode_frame), 757cabdff1aSopenharmony_ci .close = libx265_encode_close, 758cabdff1aSopenharmony_ci .priv_data_size = sizeof(libx265Context), 759cabdff1aSopenharmony_ci .defaults = x265_defaults, 760cabdff1aSopenharmony_ci .caps_internal = FF_CODEC_CAP_AUTO_THREADS, 761cabdff1aSopenharmony_ci}; 762