1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * Intel MediaSDK QSV codec-independent code 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * copyright (c) 2013 Luca Barbato 5cabdff1aSopenharmony_ci * copyright (c) 2015 Anton Khirnov <anton@khirnov.net> 6cabdff1aSopenharmony_ci * 7cabdff1aSopenharmony_ci * This file is part of FFmpeg. 8cabdff1aSopenharmony_ci * 9cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 10cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 11cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 12cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 13cabdff1aSopenharmony_ci * 14cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 15cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 16cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17cabdff1aSopenharmony_ci * Lesser General Public License for more details. 18cabdff1aSopenharmony_ci * 19cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 20cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 21cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 22cabdff1aSopenharmony_ci */ 23cabdff1aSopenharmony_ci 24cabdff1aSopenharmony_ci#include "config_components.h" 25cabdff1aSopenharmony_ci 26cabdff1aSopenharmony_ci#include <stdint.h> 27cabdff1aSopenharmony_ci#include <string.h> 28cabdff1aSopenharmony_ci#include <sys/types.h> 29cabdff1aSopenharmony_ci 30cabdff1aSopenharmony_ci#include <mfx/mfxvideo.h> 31cabdff1aSopenharmony_ci 32cabdff1aSopenharmony_ci#include "libavutil/common.h" 33cabdff1aSopenharmony_ci#include "libavutil/fifo.h" 34cabdff1aSopenharmony_ci#include "libavutil/frame.h" 35cabdff1aSopenharmony_ci#include "libavutil/hwcontext.h" 36cabdff1aSopenharmony_ci#include "libavutil/hwcontext_qsv.h" 37cabdff1aSopenharmony_ci#include "libavutil/mem.h" 38cabdff1aSopenharmony_ci#include "libavutil/log.h" 39cabdff1aSopenharmony_ci#include "libavutil/opt.h" 40cabdff1aSopenharmony_ci#include "libavutil/pixfmt.h" 41cabdff1aSopenharmony_ci#include "libavutil/time.h" 42cabdff1aSopenharmony_ci#include "libavutil/imgutils.h" 43cabdff1aSopenharmony_ci#include "libavutil/film_grain_params.h" 44cabdff1aSopenharmony_ci 45cabdff1aSopenharmony_ci#include "avcodec.h" 46cabdff1aSopenharmony_ci#include "codec_internal.h" 47cabdff1aSopenharmony_ci#include "internal.h" 48cabdff1aSopenharmony_ci#include "decode.h" 49cabdff1aSopenharmony_ci#include "hwconfig.h" 50cabdff1aSopenharmony_ci#include "qsv.h" 51cabdff1aSopenharmony_ci#include "qsv_internal.h" 52cabdff1aSopenharmony_ci 53cabdff1aSopenharmony_cistatic const AVRational mfx_tb = { 1, 90000 }; 54cabdff1aSopenharmony_ci 55cabdff1aSopenharmony_ci#define PTS_TO_MFX_PTS(pts, pts_tb) ((pts) == AV_NOPTS_VALUE ? \ 56cabdff1aSopenharmony_ci MFX_TIMESTAMP_UNKNOWN : pts_tb.num ? \ 57cabdff1aSopenharmony_ci av_rescale_q(pts, pts_tb, mfx_tb) : pts) 58cabdff1aSopenharmony_ci 59cabdff1aSopenharmony_ci#define MFX_PTS_TO_PTS(mfx_pts, pts_tb) ((mfx_pts) == MFX_TIMESTAMP_UNKNOWN ? \ 60cabdff1aSopenharmony_ci AV_NOPTS_VALUE : pts_tb.num ? \ 61cabdff1aSopenharmony_ci av_rescale_q(mfx_pts, mfx_tb, pts_tb) : mfx_pts) 62cabdff1aSopenharmony_ci 63cabdff1aSopenharmony_citypedef struct QSVAsyncFrame { 64cabdff1aSopenharmony_ci mfxSyncPoint *sync; 65cabdff1aSopenharmony_ci QSVFrame *frame; 66cabdff1aSopenharmony_ci} QSVAsyncFrame; 67cabdff1aSopenharmony_ci 68cabdff1aSopenharmony_citypedef struct QSVContext { 69cabdff1aSopenharmony_ci // the session used for decoding 70cabdff1aSopenharmony_ci mfxSession session; 71cabdff1aSopenharmony_ci mfxVersion ver; 72cabdff1aSopenharmony_ci 73cabdff1aSopenharmony_ci // the session we allocated internally, in case the caller did not provide 74cabdff1aSopenharmony_ci // one 75cabdff1aSopenharmony_ci QSVSession internal_qs; 76cabdff1aSopenharmony_ci 77cabdff1aSopenharmony_ci QSVFramesContext frames_ctx; 78cabdff1aSopenharmony_ci 79cabdff1aSopenharmony_ci /** 80cabdff1aSopenharmony_ci * a linked list of frames currently being used by QSV 81cabdff1aSopenharmony_ci */ 82cabdff1aSopenharmony_ci QSVFrame *work_frames; 83cabdff1aSopenharmony_ci 84cabdff1aSopenharmony_ci AVFifo *async_fifo; 85cabdff1aSopenharmony_ci int zero_consume_run; 86cabdff1aSopenharmony_ci int reinit_flag; 87cabdff1aSopenharmony_ci 88cabdff1aSopenharmony_ci enum AVPixelFormat orig_pix_fmt; 89cabdff1aSopenharmony_ci uint32_t fourcc; 90cabdff1aSopenharmony_ci mfxFrameInfo frame_info; 91cabdff1aSopenharmony_ci AVBufferPool *pool; 92cabdff1aSopenharmony_ci int suggest_pool_size; 93cabdff1aSopenharmony_ci int initialized; 94cabdff1aSopenharmony_ci 95cabdff1aSopenharmony_ci // options set by the caller 96cabdff1aSopenharmony_ci int async_depth; 97cabdff1aSopenharmony_ci int iopattern; 98cabdff1aSopenharmony_ci int gpu_copy; 99cabdff1aSopenharmony_ci 100cabdff1aSopenharmony_ci char *load_plugins; 101cabdff1aSopenharmony_ci 102cabdff1aSopenharmony_ci mfxExtBuffer **ext_buffers; 103cabdff1aSopenharmony_ci int nb_ext_buffers; 104cabdff1aSopenharmony_ci} QSVContext; 105cabdff1aSopenharmony_ci 106cabdff1aSopenharmony_cistatic const AVCodecHWConfigInternal *const qsv_hw_configs[] = { 107cabdff1aSopenharmony_ci &(const AVCodecHWConfigInternal) { 108cabdff1aSopenharmony_ci .public = { 109cabdff1aSopenharmony_ci .pix_fmt = AV_PIX_FMT_QSV, 110cabdff1aSopenharmony_ci .methods = AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX | 111cabdff1aSopenharmony_ci AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX, 112cabdff1aSopenharmony_ci .device_type = AV_HWDEVICE_TYPE_QSV, 113cabdff1aSopenharmony_ci }, 114cabdff1aSopenharmony_ci .hwaccel = NULL, 115cabdff1aSopenharmony_ci }, 116cabdff1aSopenharmony_ci NULL 117cabdff1aSopenharmony_ci}; 118cabdff1aSopenharmony_ci 119cabdff1aSopenharmony_cistatic int qsv_get_continuous_buffer(AVCodecContext *avctx, AVFrame *frame, 120cabdff1aSopenharmony_ci AVBufferPool *pool) 121cabdff1aSopenharmony_ci{ 122cabdff1aSopenharmony_ci int ret = 0; 123cabdff1aSopenharmony_ci 124cabdff1aSopenharmony_ci ff_decode_frame_props(avctx, frame); 125cabdff1aSopenharmony_ci 126cabdff1aSopenharmony_ci frame->width = avctx->width; 127cabdff1aSopenharmony_ci frame->height = avctx->height; 128cabdff1aSopenharmony_ci 129cabdff1aSopenharmony_ci switch (avctx->pix_fmt) { 130cabdff1aSopenharmony_ci case AV_PIX_FMT_NV12: 131cabdff1aSopenharmony_ci frame->linesize[0] = FFALIGN(avctx->width, 128); 132cabdff1aSopenharmony_ci break; 133cabdff1aSopenharmony_ci case AV_PIX_FMT_P010: 134cabdff1aSopenharmony_ci case AV_PIX_FMT_YUYV422: 135cabdff1aSopenharmony_ci frame->linesize[0] = 2 * FFALIGN(avctx->width, 128); 136cabdff1aSopenharmony_ci break; 137cabdff1aSopenharmony_ci case AV_PIX_FMT_Y210: 138cabdff1aSopenharmony_ci frame->linesize[0] = 4 * FFALIGN(avctx->width, 128); 139cabdff1aSopenharmony_ci break; 140cabdff1aSopenharmony_ci default: 141cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Unsupported pixel format.\n"); 142cabdff1aSopenharmony_ci return AVERROR(EINVAL); 143cabdff1aSopenharmony_ci } 144cabdff1aSopenharmony_ci 145cabdff1aSopenharmony_ci frame->buf[0] = av_buffer_pool_get(pool); 146cabdff1aSopenharmony_ci if (!frame->buf[0]) 147cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 148cabdff1aSopenharmony_ci 149cabdff1aSopenharmony_ci frame->data[0] = frame->buf[0]->data; 150cabdff1aSopenharmony_ci if (avctx->pix_fmt == AV_PIX_FMT_NV12 || 151cabdff1aSopenharmony_ci avctx->pix_fmt == AV_PIX_FMT_P010) { 152cabdff1aSopenharmony_ci frame->linesize[1] = frame->linesize[0]; 153cabdff1aSopenharmony_ci frame->data[1] = frame->data[0] + 154cabdff1aSopenharmony_ci frame->linesize[0] * FFALIGN(avctx->height, 64); 155cabdff1aSopenharmony_ci } 156cabdff1aSopenharmony_ci 157cabdff1aSopenharmony_ci ret = ff_attach_decode_data(frame); 158cabdff1aSopenharmony_ci if (ret < 0) 159cabdff1aSopenharmony_ci return ret; 160cabdff1aSopenharmony_ci 161cabdff1aSopenharmony_ci return 0; 162cabdff1aSopenharmony_ci} 163cabdff1aSopenharmony_ci 164cabdff1aSopenharmony_cistatic int qsv_init_session(AVCodecContext *avctx, QSVContext *q, mfxSession session, 165cabdff1aSopenharmony_ci AVBufferRef *hw_frames_ref, AVBufferRef *hw_device_ref) 166cabdff1aSopenharmony_ci{ 167cabdff1aSopenharmony_ci int ret; 168cabdff1aSopenharmony_ci 169cabdff1aSopenharmony_ci if (q->gpu_copy == MFX_GPUCOPY_ON && 170cabdff1aSopenharmony_ci !(q->iopattern & MFX_IOPATTERN_OUT_SYSTEM_MEMORY)) { 171cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, "GPU-accelerated memory copy " 172cabdff1aSopenharmony_ci "only works in system memory mode.\n"); 173cabdff1aSopenharmony_ci q->gpu_copy = MFX_GPUCOPY_OFF; 174cabdff1aSopenharmony_ci } 175cabdff1aSopenharmony_ci if (session) { 176cabdff1aSopenharmony_ci q->session = session; 177cabdff1aSopenharmony_ci } else if (hw_frames_ref) { 178cabdff1aSopenharmony_ci if (q->internal_qs.session) { 179cabdff1aSopenharmony_ci MFXClose(q->internal_qs.session); 180cabdff1aSopenharmony_ci q->internal_qs.session = NULL; 181cabdff1aSopenharmony_ci } 182cabdff1aSopenharmony_ci av_buffer_unref(&q->frames_ctx.hw_frames_ctx); 183cabdff1aSopenharmony_ci 184cabdff1aSopenharmony_ci q->frames_ctx.hw_frames_ctx = av_buffer_ref(hw_frames_ref); 185cabdff1aSopenharmony_ci if (!q->frames_ctx.hw_frames_ctx) 186cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 187cabdff1aSopenharmony_ci 188cabdff1aSopenharmony_ci ret = ff_qsv_init_session_frames(avctx, &q->internal_qs.session, 189cabdff1aSopenharmony_ci &q->frames_ctx, q->load_plugins, 190cabdff1aSopenharmony_ci q->iopattern == MFX_IOPATTERN_OUT_OPAQUE_MEMORY, 191cabdff1aSopenharmony_ci q->gpu_copy); 192cabdff1aSopenharmony_ci if (ret < 0) { 193cabdff1aSopenharmony_ci av_buffer_unref(&q->frames_ctx.hw_frames_ctx); 194cabdff1aSopenharmony_ci return ret; 195cabdff1aSopenharmony_ci } 196cabdff1aSopenharmony_ci 197cabdff1aSopenharmony_ci q->session = q->internal_qs.session; 198cabdff1aSopenharmony_ci } else if (hw_device_ref) { 199cabdff1aSopenharmony_ci if (q->internal_qs.session) { 200cabdff1aSopenharmony_ci MFXClose(q->internal_qs.session); 201cabdff1aSopenharmony_ci q->internal_qs.session = NULL; 202cabdff1aSopenharmony_ci } 203cabdff1aSopenharmony_ci 204cabdff1aSopenharmony_ci ret = ff_qsv_init_session_device(avctx, &q->internal_qs.session, 205cabdff1aSopenharmony_ci hw_device_ref, q->load_plugins, q->gpu_copy); 206cabdff1aSopenharmony_ci if (ret < 0) 207cabdff1aSopenharmony_ci return ret; 208cabdff1aSopenharmony_ci 209cabdff1aSopenharmony_ci q->session = q->internal_qs.session; 210cabdff1aSopenharmony_ci } else { 211cabdff1aSopenharmony_ci if (!q->internal_qs.session) { 212cabdff1aSopenharmony_ci ret = ff_qsv_init_internal_session(avctx, &q->internal_qs, 213cabdff1aSopenharmony_ci q->load_plugins, q->gpu_copy); 214cabdff1aSopenharmony_ci if (ret < 0) 215cabdff1aSopenharmony_ci return ret; 216cabdff1aSopenharmony_ci } 217cabdff1aSopenharmony_ci 218cabdff1aSopenharmony_ci q->session = q->internal_qs.session; 219cabdff1aSopenharmony_ci } 220cabdff1aSopenharmony_ci 221cabdff1aSopenharmony_ci if (MFXQueryVersion(q->session, &q->ver) != MFX_ERR_NONE) { 222cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Error querying the session version. \n"); 223cabdff1aSopenharmony_ci q->session = NULL; 224cabdff1aSopenharmony_ci 225cabdff1aSopenharmony_ci if (q->internal_qs.session) { 226cabdff1aSopenharmony_ci MFXClose(q->internal_qs.session); 227cabdff1aSopenharmony_ci q->internal_qs.session = NULL; 228cabdff1aSopenharmony_ci } 229cabdff1aSopenharmony_ci 230cabdff1aSopenharmony_ci return AVERROR_EXTERNAL; 231cabdff1aSopenharmony_ci } 232cabdff1aSopenharmony_ci 233cabdff1aSopenharmony_ci /* make sure the decoder is uninitialized */ 234cabdff1aSopenharmony_ci MFXVideoDECODE_Close(q->session); 235cabdff1aSopenharmony_ci 236cabdff1aSopenharmony_ci return 0; 237cabdff1aSopenharmony_ci} 238cabdff1aSopenharmony_ci 239cabdff1aSopenharmony_cistatic int qsv_decode_preinit(AVCodecContext *avctx, QSVContext *q, enum AVPixelFormat pix_fmt, mfxVideoParam *param) 240cabdff1aSopenharmony_ci{ 241cabdff1aSopenharmony_ci mfxSession session = NULL; 242cabdff1aSopenharmony_ci int iopattern = 0; 243cabdff1aSopenharmony_ci int ret; 244cabdff1aSopenharmony_ci enum AVPixelFormat pix_fmts[3] = { 245cabdff1aSopenharmony_ci AV_PIX_FMT_QSV, /* opaque format in case of video memory output */ 246cabdff1aSopenharmony_ci pix_fmt, /* system memory format obtained from bitstream parser */ 247cabdff1aSopenharmony_ci AV_PIX_FMT_NONE }; 248cabdff1aSopenharmony_ci 249cabdff1aSopenharmony_ci ret = ff_get_format(avctx, pix_fmts); 250cabdff1aSopenharmony_ci if (ret < 0) { 251cabdff1aSopenharmony_ci q->orig_pix_fmt = avctx->pix_fmt = AV_PIX_FMT_NONE; 252cabdff1aSopenharmony_ci return ret; 253cabdff1aSopenharmony_ci } 254cabdff1aSopenharmony_ci 255cabdff1aSopenharmony_ci if (!q->async_fifo) { 256cabdff1aSopenharmony_ci q->async_fifo = av_fifo_alloc2(q->async_depth, sizeof(QSVAsyncFrame), 0); 257cabdff1aSopenharmony_ci if (!q->async_fifo) 258cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 259cabdff1aSopenharmony_ci } 260cabdff1aSopenharmony_ci 261cabdff1aSopenharmony_ci if (avctx->pix_fmt == AV_PIX_FMT_QSV && avctx->hwaccel_context) { 262cabdff1aSopenharmony_ci AVQSVContext *user_ctx = avctx->hwaccel_context; 263cabdff1aSopenharmony_ci session = user_ctx->session; 264cabdff1aSopenharmony_ci iopattern = user_ctx->iopattern; 265cabdff1aSopenharmony_ci q->ext_buffers = user_ctx->ext_buffers; 266cabdff1aSopenharmony_ci q->nb_ext_buffers = user_ctx->nb_ext_buffers; 267cabdff1aSopenharmony_ci } 268cabdff1aSopenharmony_ci 269cabdff1aSopenharmony_ci if (avctx->hw_device_ctx && !avctx->hw_frames_ctx && ret == AV_PIX_FMT_QSV) { 270cabdff1aSopenharmony_ci AVHWFramesContext *hwframes_ctx; 271cabdff1aSopenharmony_ci AVQSVFramesContext *frames_hwctx; 272cabdff1aSopenharmony_ci 273cabdff1aSopenharmony_ci avctx->hw_frames_ctx = av_hwframe_ctx_alloc(avctx->hw_device_ctx); 274cabdff1aSopenharmony_ci 275cabdff1aSopenharmony_ci if (!avctx->hw_frames_ctx) { 276cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "av_hwframe_ctx_alloc failed\n"); 277cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 278cabdff1aSopenharmony_ci } 279cabdff1aSopenharmony_ci 280cabdff1aSopenharmony_ci hwframes_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; 281cabdff1aSopenharmony_ci frames_hwctx = hwframes_ctx->hwctx; 282cabdff1aSopenharmony_ci hwframes_ctx->width = FFALIGN(avctx->coded_width, 32); 283cabdff1aSopenharmony_ci hwframes_ctx->height = FFALIGN(avctx->coded_height, 32); 284cabdff1aSopenharmony_ci hwframes_ctx->format = AV_PIX_FMT_QSV; 285cabdff1aSopenharmony_ci hwframes_ctx->sw_format = avctx->sw_pix_fmt; 286cabdff1aSopenharmony_ci hwframes_ctx->initial_pool_size = q->suggest_pool_size + 16 + avctx->extra_hw_frames; 287cabdff1aSopenharmony_ci frames_hwctx->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET; 288cabdff1aSopenharmony_ci 289cabdff1aSopenharmony_ci ret = av_hwframe_ctx_init(avctx->hw_frames_ctx); 290cabdff1aSopenharmony_ci 291cabdff1aSopenharmony_ci if (ret < 0) { 292cabdff1aSopenharmony_ci av_log(NULL, AV_LOG_ERROR, "Error initializing a QSV frame pool\n"); 293cabdff1aSopenharmony_ci av_buffer_unref(&avctx->hw_frames_ctx); 294cabdff1aSopenharmony_ci return ret; 295cabdff1aSopenharmony_ci } 296cabdff1aSopenharmony_ci } 297cabdff1aSopenharmony_ci 298cabdff1aSopenharmony_ci if (avctx->hw_frames_ctx) { 299cabdff1aSopenharmony_ci AVHWFramesContext *frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; 300cabdff1aSopenharmony_ci AVQSVFramesContext *frames_hwctx = frames_ctx->hwctx; 301cabdff1aSopenharmony_ci 302cabdff1aSopenharmony_ci if (!iopattern) { 303cabdff1aSopenharmony_ci if (frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME) 304cabdff1aSopenharmony_ci iopattern = MFX_IOPATTERN_OUT_OPAQUE_MEMORY; 305cabdff1aSopenharmony_ci else if (frames_hwctx->frame_type & MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET) 306cabdff1aSopenharmony_ci iopattern = MFX_IOPATTERN_OUT_VIDEO_MEMORY; 307cabdff1aSopenharmony_ci } 308cabdff1aSopenharmony_ci } 309cabdff1aSopenharmony_ci 310cabdff1aSopenharmony_ci if (!iopattern) 311cabdff1aSopenharmony_ci iopattern = MFX_IOPATTERN_OUT_SYSTEM_MEMORY; 312cabdff1aSopenharmony_ci q->iopattern = iopattern; 313cabdff1aSopenharmony_ci 314cabdff1aSopenharmony_ci ff_qsv_print_iopattern(avctx, q->iopattern, "Decoder"); 315cabdff1aSopenharmony_ci 316cabdff1aSopenharmony_ci ret = qsv_init_session(avctx, q, session, avctx->hw_frames_ctx, avctx->hw_device_ctx); 317cabdff1aSopenharmony_ci if (ret < 0) { 318cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Error initializing an MFX session\n"); 319cabdff1aSopenharmony_ci return ret; 320cabdff1aSopenharmony_ci } 321cabdff1aSopenharmony_ci 322cabdff1aSopenharmony_ci param->IOPattern = q->iopattern; 323cabdff1aSopenharmony_ci param->AsyncDepth = q->async_depth; 324cabdff1aSopenharmony_ci param->ExtParam = q->ext_buffers; 325cabdff1aSopenharmony_ci param->NumExtParam = q->nb_ext_buffers; 326cabdff1aSopenharmony_ci 327cabdff1aSopenharmony_ci return 0; 328cabdff1aSopenharmony_ci } 329cabdff1aSopenharmony_ci 330cabdff1aSopenharmony_cistatic int qsv_decode_init_context(AVCodecContext *avctx, QSVContext *q, mfxVideoParam *param) 331cabdff1aSopenharmony_ci{ 332cabdff1aSopenharmony_ci int ret; 333cabdff1aSopenharmony_ci 334cabdff1aSopenharmony_ci avctx->width = param->mfx.FrameInfo.CropW; 335cabdff1aSopenharmony_ci avctx->height = param->mfx.FrameInfo.CropH; 336cabdff1aSopenharmony_ci avctx->coded_width = param->mfx.FrameInfo.Width; 337cabdff1aSopenharmony_ci avctx->coded_height = param->mfx.FrameInfo.Height; 338cabdff1aSopenharmony_ci avctx->level = param->mfx.CodecLevel; 339cabdff1aSopenharmony_ci avctx->profile = param->mfx.CodecProfile; 340cabdff1aSopenharmony_ci avctx->field_order = ff_qsv_map_picstruct(param->mfx.FrameInfo.PicStruct); 341cabdff1aSopenharmony_ci avctx->pix_fmt = ff_qsv_map_fourcc(param->mfx.FrameInfo.FourCC); 342cabdff1aSopenharmony_ci 343cabdff1aSopenharmony_ci ret = MFXVideoDECODE_Init(q->session, param); 344cabdff1aSopenharmony_ci if (ret < 0) 345cabdff1aSopenharmony_ci return ff_qsv_print_error(avctx, ret, 346cabdff1aSopenharmony_ci "Error initializing the MFX video decoder"); 347cabdff1aSopenharmony_ci 348cabdff1aSopenharmony_ci q->frame_info = param->mfx.FrameInfo; 349cabdff1aSopenharmony_ci 350cabdff1aSopenharmony_ci if (!avctx->hw_frames_ctx) 351cabdff1aSopenharmony_ci q->pool = av_buffer_pool_init(av_image_get_buffer_size(avctx->pix_fmt, 352cabdff1aSopenharmony_ci FFALIGN(avctx->width, 128), FFALIGN(avctx->height, 64), 1), av_buffer_allocz); 353cabdff1aSopenharmony_ci return 0; 354cabdff1aSopenharmony_ci} 355cabdff1aSopenharmony_ci 356cabdff1aSopenharmony_cistatic int qsv_decode_header(AVCodecContext *avctx, QSVContext *q, 357cabdff1aSopenharmony_ci const AVPacket *avpkt, enum AVPixelFormat pix_fmt, 358cabdff1aSopenharmony_ci mfxVideoParam *param) 359cabdff1aSopenharmony_ci{ 360cabdff1aSopenharmony_ci int ret; 361cabdff1aSopenharmony_ci mfxExtVideoSignalInfo video_signal_info = { 0 }; 362cabdff1aSopenharmony_ci mfxExtBuffer *header_ext_params[1] = { (mfxExtBuffer *)&video_signal_info }; 363cabdff1aSopenharmony_ci mfxBitstream bs = { 0 }; 364cabdff1aSopenharmony_ci 365cabdff1aSopenharmony_ci if (avpkt->size) { 366cabdff1aSopenharmony_ci bs.Data = avpkt->data; 367cabdff1aSopenharmony_ci bs.DataLength = avpkt->size; 368cabdff1aSopenharmony_ci bs.MaxLength = bs.DataLength; 369cabdff1aSopenharmony_ci bs.TimeStamp = PTS_TO_MFX_PTS(avpkt->pts, avctx->pkt_timebase); 370cabdff1aSopenharmony_ci if (avctx->field_order == AV_FIELD_PROGRESSIVE) 371cabdff1aSopenharmony_ci bs.DataFlag |= MFX_BITSTREAM_COMPLETE_FRAME; 372cabdff1aSopenharmony_ci } else 373cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 374cabdff1aSopenharmony_ci 375cabdff1aSopenharmony_ci 376cabdff1aSopenharmony_ci if(!q->session) { 377cabdff1aSopenharmony_ci ret = qsv_decode_preinit(avctx, q, pix_fmt, param); 378cabdff1aSopenharmony_ci if (ret < 0) 379cabdff1aSopenharmony_ci return ret; 380cabdff1aSopenharmony_ci } 381cabdff1aSopenharmony_ci 382cabdff1aSopenharmony_ci ret = ff_qsv_codec_id_to_mfx(avctx->codec_id); 383cabdff1aSopenharmony_ci if (ret < 0) 384cabdff1aSopenharmony_ci return ret; 385cabdff1aSopenharmony_ci 386cabdff1aSopenharmony_ci param->mfx.CodecId = ret; 387cabdff1aSopenharmony_ci video_signal_info.Header.BufferId = MFX_EXTBUFF_VIDEO_SIGNAL_INFO; 388cabdff1aSopenharmony_ci video_signal_info.Header.BufferSz = sizeof(video_signal_info); 389cabdff1aSopenharmony_ci // The SDK doesn't support other ext buffers when calling MFXVideoDECODE_DecodeHeader, 390cabdff1aSopenharmony_ci // so do not append this buffer to the existent buffer array 391cabdff1aSopenharmony_ci param->ExtParam = header_ext_params; 392cabdff1aSopenharmony_ci param->NumExtParam = 1; 393cabdff1aSopenharmony_ci ret = MFXVideoDECODE_DecodeHeader(q->session, &bs, param); 394cabdff1aSopenharmony_ci if (MFX_ERR_MORE_DATA == ret) { 395cabdff1aSopenharmony_ci return AVERROR(EAGAIN); 396cabdff1aSopenharmony_ci } 397cabdff1aSopenharmony_ci if (ret < 0) 398cabdff1aSopenharmony_ci return ff_qsv_print_error(avctx, ret, 399cabdff1aSopenharmony_ci "Error decoding stream header"); 400cabdff1aSopenharmony_ci 401cabdff1aSopenharmony_ci avctx->color_range = video_signal_info.VideoFullRange ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG; 402cabdff1aSopenharmony_ci 403cabdff1aSopenharmony_ci if (video_signal_info.ColourDescriptionPresent) { 404cabdff1aSopenharmony_ci avctx->color_primaries = video_signal_info.ColourPrimaries; 405cabdff1aSopenharmony_ci avctx->color_trc = video_signal_info.TransferCharacteristics; 406cabdff1aSopenharmony_ci avctx->colorspace = video_signal_info.MatrixCoefficients; 407cabdff1aSopenharmony_ci } 408cabdff1aSopenharmony_ci 409cabdff1aSopenharmony_ci param->ExtParam = q->ext_buffers; 410cabdff1aSopenharmony_ci param->NumExtParam = q->nb_ext_buffers; 411cabdff1aSopenharmony_ci 412cabdff1aSopenharmony_ci#if QSV_VERSION_ATLEAST(1, 34) 413cabdff1aSopenharmony_ci if (QSV_RUNTIME_VERSION_ATLEAST(q->ver, 1, 34) && avctx->codec_id == AV_CODEC_ID_AV1) 414cabdff1aSopenharmony_ci param->mfx.FilmGrain = (avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN) ? 0 : param->mfx.FilmGrain; 415cabdff1aSopenharmony_ci#endif 416cabdff1aSopenharmony_ci 417cabdff1aSopenharmony_ci return 0; 418cabdff1aSopenharmony_ci} 419cabdff1aSopenharmony_ci 420cabdff1aSopenharmony_cistatic int alloc_frame(AVCodecContext *avctx, QSVContext *q, QSVFrame *frame) 421cabdff1aSopenharmony_ci{ 422cabdff1aSopenharmony_ci int ret; 423cabdff1aSopenharmony_ci 424cabdff1aSopenharmony_ci if (q->pool) 425cabdff1aSopenharmony_ci ret = qsv_get_continuous_buffer(avctx, frame->frame, q->pool); 426cabdff1aSopenharmony_ci else 427cabdff1aSopenharmony_ci ret = ff_get_buffer(avctx, frame->frame, AV_GET_BUFFER_FLAG_REF); 428cabdff1aSopenharmony_ci 429cabdff1aSopenharmony_ci if (ret < 0) 430cabdff1aSopenharmony_ci return ret; 431cabdff1aSopenharmony_ci 432cabdff1aSopenharmony_ci if (frame->frame->format == AV_PIX_FMT_QSV) { 433cabdff1aSopenharmony_ci frame->surface = *(mfxFrameSurface1*)frame->frame->data[3]; 434cabdff1aSopenharmony_ci } else { 435cabdff1aSopenharmony_ci ret = ff_qsv_map_frame_to_surface(frame->frame, &frame->surface); 436cabdff1aSopenharmony_ci if (ret < 0) { 437cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "map frame to surface failed.\n"); 438cabdff1aSopenharmony_ci return ret; 439cabdff1aSopenharmony_ci } 440cabdff1aSopenharmony_ci } 441cabdff1aSopenharmony_ci 442cabdff1aSopenharmony_ci frame->surface.Info = q->frame_info; 443cabdff1aSopenharmony_ci 444cabdff1aSopenharmony_ci if (q->frames_ctx.mids) { 445cabdff1aSopenharmony_ci ret = ff_qsv_find_surface_idx(&q->frames_ctx, frame); 446cabdff1aSopenharmony_ci if (ret < 0) 447cabdff1aSopenharmony_ci return ret; 448cabdff1aSopenharmony_ci 449cabdff1aSopenharmony_ci frame->surface.Data.MemId = &q->frames_ctx.mids[ret]; 450cabdff1aSopenharmony_ci } 451cabdff1aSopenharmony_ci 452cabdff1aSopenharmony_ci frame->surface.Data.ExtParam = frame->ext_param; 453cabdff1aSopenharmony_ci frame->surface.Data.NumExtParam = 0; 454cabdff1aSopenharmony_ci frame->num_ext_params = 0; 455cabdff1aSopenharmony_ci frame->dec_info.Header.BufferId = MFX_EXTBUFF_DECODED_FRAME_INFO; 456cabdff1aSopenharmony_ci frame->dec_info.Header.BufferSz = sizeof(frame->dec_info); 457cabdff1aSopenharmony_ci ff_qsv_frame_add_ext_param(avctx, frame, (mfxExtBuffer *)&frame->dec_info); 458cabdff1aSopenharmony_ci#if QSV_VERSION_ATLEAST(1, 34) 459cabdff1aSopenharmony_ci if (QSV_RUNTIME_VERSION_ATLEAST(q->ver, 1, 34) && avctx->codec_id == AV_CODEC_ID_AV1) { 460cabdff1aSopenharmony_ci frame->av1_film_grain_param.Header.BufferId = MFX_EXTBUFF_AV1_FILM_GRAIN_PARAM; 461cabdff1aSopenharmony_ci frame->av1_film_grain_param.Header.BufferSz = sizeof(frame->av1_film_grain_param); 462cabdff1aSopenharmony_ci frame->av1_film_grain_param.FilmGrainFlags = 0; 463cabdff1aSopenharmony_ci ff_qsv_frame_add_ext_param(avctx, frame, (mfxExtBuffer *)&frame->av1_film_grain_param); 464cabdff1aSopenharmony_ci } 465cabdff1aSopenharmony_ci#endif 466cabdff1aSopenharmony_ci 467cabdff1aSopenharmony_ci frame->used = 1; 468cabdff1aSopenharmony_ci 469cabdff1aSopenharmony_ci return 0; 470cabdff1aSopenharmony_ci} 471cabdff1aSopenharmony_ci 472cabdff1aSopenharmony_cistatic void qsv_clear_unused_frames(QSVContext *q) 473cabdff1aSopenharmony_ci{ 474cabdff1aSopenharmony_ci QSVFrame *cur = q->work_frames; 475cabdff1aSopenharmony_ci while (cur) { 476cabdff1aSopenharmony_ci if (cur->used && !cur->surface.Data.Locked && !cur->queued) { 477cabdff1aSopenharmony_ci cur->used = 0; 478cabdff1aSopenharmony_ci av_frame_unref(cur->frame); 479cabdff1aSopenharmony_ci } 480cabdff1aSopenharmony_ci cur = cur->next; 481cabdff1aSopenharmony_ci } 482cabdff1aSopenharmony_ci} 483cabdff1aSopenharmony_ci 484cabdff1aSopenharmony_cistatic int get_surface(AVCodecContext *avctx, QSVContext *q, mfxFrameSurface1 **surf) 485cabdff1aSopenharmony_ci{ 486cabdff1aSopenharmony_ci QSVFrame *frame, **last; 487cabdff1aSopenharmony_ci int ret; 488cabdff1aSopenharmony_ci 489cabdff1aSopenharmony_ci qsv_clear_unused_frames(q); 490cabdff1aSopenharmony_ci 491cabdff1aSopenharmony_ci frame = q->work_frames; 492cabdff1aSopenharmony_ci last = &q->work_frames; 493cabdff1aSopenharmony_ci while (frame) { 494cabdff1aSopenharmony_ci if (!frame->used) { 495cabdff1aSopenharmony_ci ret = alloc_frame(avctx, q, frame); 496cabdff1aSopenharmony_ci if (ret < 0) 497cabdff1aSopenharmony_ci return ret; 498cabdff1aSopenharmony_ci *surf = &frame->surface; 499cabdff1aSopenharmony_ci return 0; 500cabdff1aSopenharmony_ci } 501cabdff1aSopenharmony_ci 502cabdff1aSopenharmony_ci last = &frame->next; 503cabdff1aSopenharmony_ci frame = frame->next; 504cabdff1aSopenharmony_ci } 505cabdff1aSopenharmony_ci 506cabdff1aSopenharmony_ci frame = av_mallocz(sizeof(*frame)); 507cabdff1aSopenharmony_ci if (!frame) 508cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 509cabdff1aSopenharmony_ci frame->frame = av_frame_alloc(); 510cabdff1aSopenharmony_ci if (!frame->frame) { 511cabdff1aSopenharmony_ci av_freep(&frame); 512cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 513cabdff1aSopenharmony_ci } 514cabdff1aSopenharmony_ci *last = frame; 515cabdff1aSopenharmony_ci 516cabdff1aSopenharmony_ci ret = alloc_frame(avctx, q, frame); 517cabdff1aSopenharmony_ci if (ret < 0) 518cabdff1aSopenharmony_ci return ret; 519cabdff1aSopenharmony_ci 520cabdff1aSopenharmony_ci *surf = &frame->surface; 521cabdff1aSopenharmony_ci 522cabdff1aSopenharmony_ci return 0; 523cabdff1aSopenharmony_ci} 524cabdff1aSopenharmony_ci 525cabdff1aSopenharmony_cistatic QSVFrame *find_frame(QSVContext *q, mfxFrameSurface1 *surf) 526cabdff1aSopenharmony_ci{ 527cabdff1aSopenharmony_ci QSVFrame *cur = q->work_frames; 528cabdff1aSopenharmony_ci while (cur) { 529cabdff1aSopenharmony_ci if (surf == &cur->surface) 530cabdff1aSopenharmony_ci return cur; 531cabdff1aSopenharmony_ci cur = cur->next; 532cabdff1aSopenharmony_ci } 533cabdff1aSopenharmony_ci return NULL; 534cabdff1aSopenharmony_ci} 535cabdff1aSopenharmony_ci 536cabdff1aSopenharmony_ci#if QSV_VERSION_ATLEAST(1, 34) 537cabdff1aSopenharmony_cistatic int qsv_export_film_grain(AVCodecContext *avctx, mfxExtAV1FilmGrainParam *ext_param, AVFrame *frame) 538cabdff1aSopenharmony_ci{ 539cabdff1aSopenharmony_ci AVFilmGrainParams *fgp; 540cabdff1aSopenharmony_ci AVFilmGrainAOMParams *aom; 541cabdff1aSopenharmony_ci int i; 542cabdff1aSopenharmony_ci 543cabdff1aSopenharmony_ci if (!(ext_param->FilmGrainFlags & MFX_FILM_GRAIN_APPLY)) 544cabdff1aSopenharmony_ci return 0; 545cabdff1aSopenharmony_ci 546cabdff1aSopenharmony_ci fgp = av_film_grain_params_create_side_data(frame); 547cabdff1aSopenharmony_ci 548cabdff1aSopenharmony_ci if (!fgp) 549cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 550cabdff1aSopenharmony_ci 551cabdff1aSopenharmony_ci fgp->type = AV_FILM_GRAIN_PARAMS_AV1; 552cabdff1aSopenharmony_ci fgp->seed = ext_param->GrainSeed; 553cabdff1aSopenharmony_ci aom = &fgp->codec.aom; 554cabdff1aSopenharmony_ci 555cabdff1aSopenharmony_ci aom->chroma_scaling_from_luma = !!(ext_param->FilmGrainFlags & MFX_FILM_GRAIN_CHROMA_SCALING_FROM_LUMA); 556cabdff1aSopenharmony_ci aom->scaling_shift = ext_param->GrainScalingMinus8 + 8; 557cabdff1aSopenharmony_ci aom->ar_coeff_lag = ext_param->ArCoeffLag; 558cabdff1aSopenharmony_ci aom->ar_coeff_shift = ext_param->ArCoeffShiftMinus6 + 6; 559cabdff1aSopenharmony_ci aom->grain_scale_shift = ext_param->GrainScaleShift; 560cabdff1aSopenharmony_ci aom->overlap_flag = !!(ext_param->FilmGrainFlags & MFX_FILM_GRAIN_OVERLAP); 561cabdff1aSopenharmony_ci aom->limit_output_range = !!(ext_param->FilmGrainFlags & MFX_FILM_GRAIN_CLIP_TO_RESTRICTED_RANGE); 562cabdff1aSopenharmony_ci 563cabdff1aSopenharmony_ci aom->num_y_points = ext_param->NumYPoints; 564cabdff1aSopenharmony_ci 565cabdff1aSopenharmony_ci for (i = 0; i < aom->num_y_points; i++) { 566cabdff1aSopenharmony_ci aom->y_points[i][0] = ext_param->PointY[i].Value; 567cabdff1aSopenharmony_ci aom->y_points[i][1] = ext_param->PointY[i].Scaling; 568cabdff1aSopenharmony_ci } 569cabdff1aSopenharmony_ci 570cabdff1aSopenharmony_ci aom->num_uv_points[0] = ext_param->NumCbPoints; 571cabdff1aSopenharmony_ci 572cabdff1aSopenharmony_ci for (i = 0; i < aom->num_uv_points[0]; i++) { 573cabdff1aSopenharmony_ci aom->uv_points[0][i][0] = ext_param->PointCb[i].Value; 574cabdff1aSopenharmony_ci aom->uv_points[0][i][1] = ext_param->PointCb[i].Scaling; 575cabdff1aSopenharmony_ci } 576cabdff1aSopenharmony_ci 577cabdff1aSopenharmony_ci aom->num_uv_points[1] = ext_param->NumCrPoints; 578cabdff1aSopenharmony_ci 579cabdff1aSopenharmony_ci for (i = 0; i < aom->num_uv_points[1]; i++) { 580cabdff1aSopenharmony_ci aom->uv_points[1][i][0] = ext_param->PointCr[i].Value; 581cabdff1aSopenharmony_ci aom->uv_points[1][i][1] = ext_param->PointCr[i].Scaling; 582cabdff1aSopenharmony_ci } 583cabdff1aSopenharmony_ci 584cabdff1aSopenharmony_ci for (i = 0; i < 24; i++) 585cabdff1aSopenharmony_ci aom->ar_coeffs_y[i] = ext_param->ArCoeffsYPlus128[i] - 128; 586cabdff1aSopenharmony_ci 587cabdff1aSopenharmony_ci for (i = 0; i < 25; i++) { 588cabdff1aSopenharmony_ci aom->ar_coeffs_uv[0][i] = ext_param->ArCoeffsCbPlus128[i] - 128; 589cabdff1aSopenharmony_ci aom->ar_coeffs_uv[1][i] = ext_param->ArCoeffsCrPlus128[i] - 128; 590cabdff1aSopenharmony_ci } 591cabdff1aSopenharmony_ci 592cabdff1aSopenharmony_ci aom->uv_mult[0] = ext_param->CbMult; 593cabdff1aSopenharmony_ci aom->uv_mult[1] = ext_param->CrMult; 594cabdff1aSopenharmony_ci aom->uv_mult_luma[0] = ext_param->CbLumaMult; 595cabdff1aSopenharmony_ci aom->uv_mult_luma[1] = ext_param->CrLumaMult; 596cabdff1aSopenharmony_ci aom->uv_offset[0] = ext_param->CbOffset; 597cabdff1aSopenharmony_ci aom->uv_offset[1] = ext_param->CrOffset; 598cabdff1aSopenharmony_ci 599cabdff1aSopenharmony_ci return 0; 600cabdff1aSopenharmony_ci} 601cabdff1aSopenharmony_ci#endif 602cabdff1aSopenharmony_ci 603cabdff1aSopenharmony_cistatic int qsv_decode(AVCodecContext *avctx, QSVContext *q, 604cabdff1aSopenharmony_ci AVFrame *frame, int *got_frame, 605cabdff1aSopenharmony_ci const AVPacket *avpkt) 606cabdff1aSopenharmony_ci{ 607cabdff1aSopenharmony_ci mfxFrameSurface1 *insurf; 608cabdff1aSopenharmony_ci mfxFrameSurface1 *outsurf; 609cabdff1aSopenharmony_ci mfxSyncPoint *sync; 610cabdff1aSopenharmony_ci mfxBitstream bs = { { { 0 } } }; 611cabdff1aSopenharmony_ci int ret; 612cabdff1aSopenharmony_ci 613cabdff1aSopenharmony_ci if (avpkt->size) { 614cabdff1aSopenharmony_ci bs.Data = avpkt->data; 615cabdff1aSopenharmony_ci bs.DataLength = avpkt->size; 616cabdff1aSopenharmony_ci bs.MaxLength = bs.DataLength; 617cabdff1aSopenharmony_ci bs.TimeStamp = PTS_TO_MFX_PTS(avpkt->pts, avctx->pkt_timebase); 618cabdff1aSopenharmony_ci if (avctx->field_order == AV_FIELD_PROGRESSIVE) 619cabdff1aSopenharmony_ci bs.DataFlag |= MFX_BITSTREAM_COMPLETE_FRAME; 620cabdff1aSopenharmony_ci } 621cabdff1aSopenharmony_ci 622cabdff1aSopenharmony_ci sync = av_mallocz(sizeof(*sync)); 623cabdff1aSopenharmony_ci if (!sync) { 624cabdff1aSopenharmony_ci av_freep(&sync); 625cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 626cabdff1aSopenharmony_ci } 627cabdff1aSopenharmony_ci 628cabdff1aSopenharmony_ci do { 629cabdff1aSopenharmony_ci ret = get_surface(avctx, q, &insurf); 630cabdff1aSopenharmony_ci if (ret < 0) { 631cabdff1aSopenharmony_ci av_freep(&sync); 632cabdff1aSopenharmony_ci return ret; 633cabdff1aSopenharmony_ci } 634cabdff1aSopenharmony_ci 635cabdff1aSopenharmony_ci ret = MFXVideoDECODE_DecodeFrameAsync(q->session, avpkt->size ? &bs : NULL, 636cabdff1aSopenharmony_ci insurf, &outsurf, sync); 637cabdff1aSopenharmony_ci if (ret == MFX_WRN_DEVICE_BUSY) 638cabdff1aSopenharmony_ci av_usleep(500); 639cabdff1aSopenharmony_ci 640cabdff1aSopenharmony_ci } while (ret == MFX_WRN_DEVICE_BUSY || ret == MFX_ERR_MORE_SURFACE); 641cabdff1aSopenharmony_ci 642cabdff1aSopenharmony_ci if (ret == MFX_ERR_INCOMPATIBLE_VIDEO_PARAM) { 643cabdff1aSopenharmony_ci q->reinit_flag = 1; 644cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_DEBUG, "Video parameter change\n"); 645cabdff1aSopenharmony_ci av_freep(&sync); 646cabdff1aSopenharmony_ci return 0; 647cabdff1aSopenharmony_ci } 648cabdff1aSopenharmony_ci 649cabdff1aSopenharmony_ci if (ret != MFX_ERR_NONE && 650cabdff1aSopenharmony_ci ret != MFX_ERR_MORE_DATA && 651cabdff1aSopenharmony_ci ret != MFX_WRN_VIDEO_PARAM_CHANGED && 652cabdff1aSopenharmony_ci ret != MFX_ERR_MORE_SURFACE) { 653cabdff1aSopenharmony_ci av_freep(&sync); 654cabdff1aSopenharmony_ci return ff_qsv_print_error(avctx, ret, 655cabdff1aSopenharmony_ci "Error during QSV decoding."); 656cabdff1aSopenharmony_ci } 657cabdff1aSopenharmony_ci 658cabdff1aSopenharmony_ci /* make sure we do not enter an infinite loop if the SDK 659cabdff1aSopenharmony_ci * did not consume any data and did not return anything */ 660cabdff1aSopenharmony_ci if (!*sync && !bs.DataOffset) { 661cabdff1aSopenharmony_ci bs.DataOffset = avpkt->size; 662cabdff1aSopenharmony_ci ++q->zero_consume_run; 663cabdff1aSopenharmony_ci if (q->zero_consume_run > 1) 664cabdff1aSopenharmony_ci ff_qsv_print_warning(avctx, ret, "A decode call did not consume any data"); 665cabdff1aSopenharmony_ci } else { 666cabdff1aSopenharmony_ci q->zero_consume_run = 0; 667cabdff1aSopenharmony_ci } 668cabdff1aSopenharmony_ci 669cabdff1aSopenharmony_ci if (*sync) { 670cabdff1aSopenharmony_ci QSVAsyncFrame aframe; 671cabdff1aSopenharmony_ci QSVFrame *out_frame = find_frame(q, outsurf); 672cabdff1aSopenharmony_ci 673cabdff1aSopenharmony_ci if (!out_frame) { 674cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 675cabdff1aSopenharmony_ci "The returned surface does not correspond to any frame\n"); 676cabdff1aSopenharmony_ci av_freep(&sync); 677cabdff1aSopenharmony_ci return AVERROR_BUG; 678cabdff1aSopenharmony_ci } 679cabdff1aSopenharmony_ci 680cabdff1aSopenharmony_ci out_frame->queued += 1; 681cabdff1aSopenharmony_ci 682cabdff1aSopenharmony_ci aframe = (QSVAsyncFrame){ sync, out_frame }; 683cabdff1aSopenharmony_ci av_fifo_write(q->async_fifo, &aframe, 1); 684cabdff1aSopenharmony_ci } else { 685cabdff1aSopenharmony_ci av_freep(&sync); 686cabdff1aSopenharmony_ci } 687cabdff1aSopenharmony_ci 688cabdff1aSopenharmony_ci if ((av_fifo_can_read(q->async_fifo) >= q->async_depth) || 689cabdff1aSopenharmony_ci (!avpkt->size && av_fifo_can_read(q->async_fifo))) { 690cabdff1aSopenharmony_ci QSVAsyncFrame aframe; 691cabdff1aSopenharmony_ci AVFrame *src_frame; 692cabdff1aSopenharmony_ci 693cabdff1aSopenharmony_ci av_fifo_read(q->async_fifo, &aframe, 1); 694cabdff1aSopenharmony_ci aframe.frame->queued -= 1; 695cabdff1aSopenharmony_ci 696cabdff1aSopenharmony_ci if (avctx->pix_fmt != AV_PIX_FMT_QSV) { 697cabdff1aSopenharmony_ci do { 698cabdff1aSopenharmony_ci ret = MFXVideoCORE_SyncOperation(q->session, *aframe.sync, 1000); 699cabdff1aSopenharmony_ci } while (ret == MFX_WRN_IN_EXECUTION); 700cabdff1aSopenharmony_ci } 701cabdff1aSopenharmony_ci 702cabdff1aSopenharmony_ci av_freep(&aframe.sync); 703cabdff1aSopenharmony_ci 704cabdff1aSopenharmony_ci src_frame = aframe.frame->frame; 705cabdff1aSopenharmony_ci 706cabdff1aSopenharmony_ci ret = av_frame_ref(frame, src_frame); 707cabdff1aSopenharmony_ci if (ret < 0) 708cabdff1aSopenharmony_ci return ret; 709cabdff1aSopenharmony_ci 710cabdff1aSopenharmony_ci outsurf = &aframe.frame->surface; 711cabdff1aSopenharmony_ci 712cabdff1aSopenharmony_ci frame->pts = MFX_PTS_TO_PTS(outsurf->Data.TimeStamp, avctx->pkt_timebase); 713cabdff1aSopenharmony_ci#if QSV_VERSION_ATLEAST(1, 34) 714cabdff1aSopenharmony_ci if ((avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN) && 715cabdff1aSopenharmony_ci QSV_RUNTIME_VERSION_ATLEAST(q->ver, 1, 34) && 716cabdff1aSopenharmony_ci avctx->codec_id == AV_CODEC_ID_AV1) { 717cabdff1aSopenharmony_ci ret = qsv_export_film_grain(avctx, &aframe.frame->av1_film_grain_param, frame); 718cabdff1aSopenharmony_ci 719cabdff1aSopenharmony_ci if (ret < 0) 720cabdff1aSopenharmony_ci return ret; 721cabdff1aSopenharmony_ci } 722cabdff1aSopenharmony_ci#endif 723cabdff1aSopenharmony_ci 724cabdff1aSopenharmony_ci frame->repeat_pict = 725cabdff1aSopenharmony_ci outsurf->Info.PicStruct & MFX_PICSTRUCT_FRAME_TRIPLING ? 4 : 726cabdff1aSopenharmony_ci outsurf->Info.PicStruct & MFX_PICSTRUCT_FRAME_DOUBLING ? 2 : 727cabdff1aSopenharmony_ci outsurf->Info.PicStruct & MFX_PICSTRUCT_FIELD_REPEATED ? 1 : 0; 728cabdff1aSopenharmony_ci frame->top_field_first = 729cabdff1aSopenharmony_ci outsurf->Info.PicStruct & MFX_PICSTRUCT_FIELD_TFF; 730cabdff1aSopenharmony_ci frame->interlaced_frame = 731cabdff1aSopenharmony_ci !(outsurf->Info.PicStruct & MFX_PICSTRUCT_PROGRESSIVE); 732cabdff1aSopenharmony_ci frame->pict_type = ff_qsv_map_pictype(aframe.frame->dec_info.FrameType); 733cabdff1aSopenharmony_ci //Key frame is IDR frame is only suitable for H264. For HEVC, IRAPs are key frames. 734cabdff1aSopenharmony_ci if (avctx->codec_id == AV_CODEC_ID_H264) 735cabdff1aSopenharmony_ci frame->key_frame = !!(aframe.frame->dec_info.FrameType & MFX_FRAMETYPE_IDR); 736cabdff1aSopenharmony_ci 737cabdff1aSopenharmony_ci /* update the surface properties */ 738cabdff1aSopenharmony_ci if (avctx->pix_fmt == AV_PIX_FMT_QSV) 739cabdff1aSopenharmony_ci ((mfxFrameSurface1*)frame->data[3])->Info = outsurf->Info; 740cabdff1aSopenharmony_ci 741cabdff1aSopenharmony_ci *got_frame = 1; 742cabdff1aSopenharmony_ci } 743cabdff1aSopenharmony_ci 744cabdff1aSopenharmony_ci return bs.DataOffset; 745cabdff1aSopenharmony_ci} 746cabdff1aSopenharmony_ci 747cabdff1aSopenharmony_cistatic void qsv_decode_close_qsvcontext(QSVContext *q) 748cabdff1aSopenharmony_ci{ 749cabdff1aSopenharmony_ci QSVFrame *cur = q->work_frames; 750cabdff1aSopenharmony_ci 751cabdff1aSopenharmony_ci if (q->session) 752cabdff1aSopenharmony_ci MFXVideoDECODE_Close(q->session); 753cabdff1aSopenharmony_ci 754cabdff1aSopenharmony_ci if (q->async_fifo) { 755cabdff1aSopenharmony_ci QSVAsyncFrame aframe; 756cabdff1aSopenharmony_ci while (av_fifo_read(q->async_fifo, &aframe, 1) >= 0) 757cabdff1aSopenharmony_ci av_freep(&aframe.sync); 758cabdff1aSopenharmony_ci av_fifo_freep2(&q->async_fifo); 759cabdff1aSopenharmony_ci } 760cabdff1aSopenharmony_ci 761cabdff1aSopenharmony_ci while (cur) { 762cabdff1aSopenharmony_ci q->work_frames = cur->next; 763cabdff1aSopenharmony_ci av_frame_free(&cur->frame); 764cabdff1aSopenharmony_ci av_freep(&cur); 765cabdff1aSopenharmony_ci cur = q->work_frames; 766cabdff1aSopenharmony_ci } 767cabdff1aSopenharmony_ci 768cabdff1aSopenharmony_ci ff_qsv_close_internal_session(&q->internal_qs); 769cabdff1aSopenharmony_ci 770cabdff1aSopenharmony_ci av_buffer_unref(&q->frames_ctx.hw_frames_ctx); 771cabdff1aSopenharmony_ci av_buffer_unref(&q->frames_ctx.mids_buf); 772cabdff1aSopenharmony_ci av_buffer_pool_uninit(&q->pool); 773cabdff1aSopenharmony_ci} 774cabdff1aSopenharmony_ci 775cabdff1aSopenharmony_cistatic int qsv_process_data(AVCodecContext *avctx, QSVContext *q, 776cabdff1aSopenharmony_ci AVFrame *frame, int *got_frame, const AVPacket *pkt) 777cabdff1aSopenharmony_ci{ 778cabdff1aSopenharmony_ci int ret; 779cabdff1aSopenharmony_ci mfxVideoParam param = { 0 }; 780cabdff1aSopenharmony_ci enum AVPixelFormat pix_fmt = AV_PIX_FMT_NV12; 781cabdff1aSopenharmony_ci 782cabdff1aSopenharmony_ci if (!pkt->size) 783cabdff1aSopenharmony_ci return qsv_decode(avctx, q, frame, got_frame, pkt); 784cabdff1aSopenharmony_ci 785cabdff1aSopenharmony_ci /* TODO: flush delayed frames on reinit */ 786cabdff1aSopenharmony_ci 787cabdff1aSopenharmony_ci // sw_pix_fmt, coded_width/height should be set for ff_get_format(), 788cabdff1aSopenharmony_ci // assume sw_pix_fmt is NV12 and coded_width/height to be 1280x720, 789cabdff1aSopenharmony_ci // the assumption may be not corret but will be updated after header decoded if not true. 790cabdff1aSopenharmony_ci if (q->orig_pix_fmt != AV_PIX_FMT_NONE) 791cabdff1aSopenharmony_ci pix_fmt = q->orig_pix_fmt; 792cabdff1aSopenharmony_ci if (!avctx->coded_width) 793cabdff1aSopenharmony_ci avctx->coded_width = 1280; 794cabdff1aSopenharmony_ci if (!avctx->coded_height) 795cabdff1aSopenharmony_ci avctx->coded_height = 720; 796cabdff1aSopenharmony_ci 797cabdff1aSopenharmony_ci /* decode zero-size pkt to flush the buffered pkt before reinit */ 798cabdff1aSopenharmony_ci if (q->reinit_flag) { 799cabdff1aSopenharmony_ci AVPacket zero_pkt = {0}; 800cabdff1aSopenharmony_ci ret = qsv_decode(avctx, q, frame, got_frame, &zero_pkt); 801cabdff1aSopenharmony_ci if (ret < 0 || *got_frame) 802cabdff1aSopenharmony_ci return ret; 803cabdff1aSopenharmony_ci } 804cabdff1aSopenharmony_ci 805cabdff1aSopenharmony_ci if (q->reinit_flag || !q->session || !q->initialized) { 806cabdff1aSopenharmony_ci mfxFrameAllocRequest request; 807cabdff1aSopenharmony_ci memset(&request, 0, sizeof(request)); 808cabdff1aSopenharmony_ci 809cabdff1aSopenharmony_ci q->reinit_flag = 0; 810cabdff1aSopenharmony_ci ret = qsv_decode_header(avctx, q, pkt, pix_fmt, ¶m); 811cabdff1aSopenharmony_ci if (ret < 0) { 812cabdff1aSopenharmony_ci if (ret == AVERROR(EAGAIN)) 813cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_INFO, "More data is required to decode header\n"); 814cabdff1aSopenharmony_ci else 815cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Error decoding header\n"); 816cabdff1aSopenharmony_ci goto reinit_fail; 817cabdff1aSopenharmony_ci } 818cabdff1aSopenharmony_ci param.IOPattern = q->iopattern; 819cabdff1aSopenharmony_ci 820cabdff1aSopenharmony_ci q->orig_pix_fmt = avctx->pix_fmt = pix_fmt = ff_qsv_map_fourcc(param.mfx.FrameInfo.FourCC); 821cabdff1aSopenharmony_ci 822cabdff1aSopenharmony_ci avctx->coded_width = param.mfx.FrameInfo.Width; 823cabdff1aSopenharmony_ci avctx->coded_height = param.mfx.FrameInfo.Height; 824cabdff1aSopenharmony_ci 825cabdff1aSopenharmony_ci ret = MFXVideoDECODE_QueryIOSurf(q->session, ¶m, &request); 826cabdff1aSopenharmony_ci if (ret < 0) 827cabdff1aSopenharmony_ci return ff_qsv_print_error(avctx, ret, "Error querying IO surface"); 828cabdff1aSopenharmony_ci 829cabdff1aSopenharmony_ci q->suggest_pool_size = request.NumFrameSuggested; 830cabdff1aSopenharmony_ci 831cabdff1aSopenharmony_ci ret = qsv_decode_preinit(avctx, q, pix_fmt, ¶m); 832cabdff1aSopenharmony_ci if (ret < 0) 833cabdff1aSopenharmony_ci goto reinit_fail; 834cabdff1aSopenharmony_ci q->initialized = 0; 835cabdff1aSopenharmony_ci } 836cabdff1aSopenharmony_ci 837cabdff1aSopenharmony_ci if (!q->initialized) { 838cabdff1aSopenharmony_ci ret = qsv_decode_init_context(avctx, q, ¶m); 839cabdff1aSopenharmony_ci if (ret < 0) 840cabdff1aSopenharmony_ci goto reinit_fail; 841cabdff1aSopenharmony_ci q->initialized = 1; 842cabdff1aSopenharmony_ci } 843cabdff1aSopenharmony_ci 844cabdff1aSopenharmony_ci return qsv_decode(avctx, q, frame, got_frame, pkt); 845cabdff1aSopenharmony_ci 846cabdff1aSopenharmony_cireinit_fail: 847cabdff1aSopenharmony_ci q->orig_pix_fmt = avctx->pix_fmt = AV_PIX_FMT_NONE; 848cabdff1aSopenharmony_ci return ret; 849cabdff1aSopenharmony_ci} 850cabdff1aSopenharmony_ci 851cabdff1aSopenharmony_cienum LoadPlugin { 852cabdff1aSopenharmony_ci LOAD_PLUGIN_NONE, 853cabdff1aSopenharmony_ci LOAD_PLUGIN_HEVC_SW, 854cabdff1aSopenharmony_ci LOAD_PLUGIN_HEVC_HW, 855cabdff1aSopenharmony_ci}; 856cabdff1aSopenharmony_ci 857cabdff1aSopenharmony_citypedef struct QSVDecContext { 858cabdff1aSopenharmony_ci AVClass *class; 859cabdff1aSopenharmony_ci QSVContext qsv; 860cabdff1aSopenharmony_ci 861cabdff1aSopenharmony_ci int load_plugin; 862cabdff1aSopenharmony_ci 863cabdff1aSopenharmony_ci AVFifo *packet_fifo; 864cabdff1aSopenharmony_ci 865cabdff1aSopenharmony_ci AVPacket buffer_pkt; 866cabdff1aSopenharmony_ci} QSVDecContext; 867cabdff1aSopenharmony_ci 868cabdff1aSopenharmony_cistatic void qsv_clear_buffers(QSVDecContext *s) 869cabdff1aSopenharmony_ci{ 870cabdff1aSopenharmony_ci AVPacket pkt; 871cabdff1aSopenharmony_ci while (av_fifo_read(s->packet_fifo, &pkt, 1) >= 0) 872cabdff1aSopenharmony_ci av_packet_unref(&pkt); 873cabdff1aSopenharmony_ci 874cabdff1aSopenharmony_ci av_packet_unref(&s->buffer_pkt); 875cabdff1aSopenharmony_ci} 876cabdff1aSopenharmony_ci 877cabdff1aSopenharmony_cistatic av_cold int qsv_decode_close(AVCodecContext *avctx) 878cabdff1aSopenharmony_ci{ 879cabdff1aSopenharmony_ci QSVDecContext *s = avctx->priv_data; 880cabdff1aSopenharmony_ci 881cabdff1aSopenharmony_ci qsv_decode_close_qsvcontext(&s->qsv); 882cabdff1aSopenharmony_ci 883cabdff1aSopenharmony_ci qsv_clear_buffers(s); 884cabdff1aSopenharmony_ci 885cabdff1aSopenharmony_ci av_fifo_freep2(&s->packet_fifo); 886cabdff1aSopenharmony_ci 887cabdff1aSopenharmony_ci return 0; 888cabdff1aSopenharmony_ci} 889cabdff1aSopenharmony_ci 890cabdff1aSopenharmony_cistatic av_cold int qsv_decode_init(AVCodecContext *avctx) 891cabdff1aSopenharmony_ci{ 892cabdff1aSopenharmony_ci QSVDecContext *s = avctx->priv_data; 893cabdff1aSopenharmony_ci int ret; 894cabdff1aSopenharmony_ci const char *uid = NULL; 895cabdff1aSopenharmony_ci 896cabdff1aSopenharmony_ci if (avctx->codec_id == AV_CODEC_ID_VP8) { 897cabdff1aSopenharmony_ci uid = "f622394d8d87452f878c51f2fc9b4131"; 898cabdff1aSopenharmony_ci } else if (avctx->codec_id == AV_CODEC_ID_VP9) { 899cabdff1aSopenharmony_ci uid = "a922394d8d87452f878c51f2fc9b4131"; 900cabdff1aSopenharmony_ci } 901cabdff1aSopenharmony_ci else if (avctx->codec_id == AV_CODEC_ID_HEVC && s->load_plugin != LOAD_PLUGIN_NONE) { 902cabdff1aSopenharmony_ci static const char * const uid_hevcdec_sw = "15dd936825ad475ea34e35f3f54217a6"; 903cabdff1aSopenharmony_ci static const char * const uid_hevcdec_hw = "33a61c0b4c27454ca8d85dde757c6f8e"; 904cabdff1aSopenharmony_ci 905cabdff1aSopenharmony_ci if (s->qsv.load_plugins[0]) { 906cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, 907cabdff1aSopenharmony_ci "load_plugins is not empty, but load_plugin is not set to 'none'." 908cabdff1aSopenharmony_ci "The load_plugin value will be ignored.\n"); 909cabdff1aSopenharmony_ci } else { 910cabdff1aSopenharmony_ci if (s->load_plugin == LOAD_PLUGIN_HEVC_SW) 911cabdff1aSopenharmony_ci uid = uid_hevcdec_sw; 912cabdff1aSopenharmony_ci else 913cabdff1aSopenharmony_ci uid = uid_hevcdec_hw; 914cabdff1aSopenharmony_ci } 915cabdff1aSopenharmony_ci } 916cabdff1aSopenharmony_ci if (uid) { 917cabdff1aSopenharmony_ci av_freep(&s->qsv.load_plugins); 918cabdff1aSopenharmony_ci s->qsv.load_plugins = av_strdup(uid); 919cabdff1aSopenharmony_ci if (!s->qsv.load_plugins) 920cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 921cabdff1aSopenharmony_ci } 922cabdff1aSopenharmony_ci 923cabdff1aSopenharmony_ci s->qsv.orig_pix_fmt = AV_PIX_FMT_NV12; 924cabdff1aSopenharmony_ci s->packet_fifo = av_fifo_alloc2(1, sizeof(AVPacket), 925cabdff1aSopenharmony_ci AV_FIFO_FLAG_AUTO_GROW); 926cabdff1aSopenharmony_ci if (!s->packet_fifo) { 927cabdff1aSopenharmony_ci ret = AVERROR(ENOMEM); 928cabdff1aSopenharmony_ci goto fail; 929cabdff1aSopenharmony_ci } 930cabdff1aSopenharmony_ci 931cabdff1aSopenharmony_ci if (!avctx->pkt_timebase.num) 932cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, "Invalid pkt_timebase, passing timestamps as-is.\n"); 933cabdff1aSopenharmony_ci 934cabdff1aSopenharmony_ci return 0; 935cabdff1aSopenharmony_cifail: 936cabdff1aSopenharmony_ci qsv_decode_close(avctx); 937cabdff1aSopenharmony_ci return ret; 938cabdff1aSopenharmony_ci} 939cabdff1aSopenharmony_ci 940cabdff1aSopenharmony_cistatic int qsv_decode_frame(AVCodecContext *avctx, AVFrame *frame, 941cabdff1aSopenharmony_ci int *got_frame, AVPacket *avpkt) 942cabdff1aSopenharmony_ci{ 943cabdff1aSopenharmony_ci QSVDecContext *s = avctx->priv_data; 944cabdff1aSopenharmony_ci int ret; 945cabdff1aSopenharmony_ci 946cabdff1aSopenharmony_ci /* buffer the input packet */ 947cabdff1aSopenharmony_ci if (avpkt->size) { 948cabdff1aSopenharmony_ci AVPacket input_ref; 949cabdff1aSopenharmony_ci 950cabdff1aSopenharmony_ci ret = av_packet_ref(&input_ref, avpkt); 951cabdff1aSopenharmony_ci if (ret < 0) 952cabdff1aSopenharmony_ci return ret; 953cabdff1aSopenharmony_ci av_fifo_write(s->packet_fifo, &input_ref, 1); 954cabdff1aSopenharmony_ci } 955cabdff1aSopenharmony_ci 956cabdff1aSopenharmony_ci /* process buffered data */ 957cabdff1aSopenharmony_ci while (!*got_frame) { 958cabdff1aSopenharmony_ci /* prepare the input data */ 959cabdff1aSopenharmony_ci if (s->buffer_pkt.size <= 0) { 960cabdff1aSopenharmony_ci /* no more data */ 961cabdff1aSopenharmony_ci if (!av_fifo_can_read(s->packet_fifo)) 962cabdff1aSopenharmony_ci return avpkt->size ? avpkt->size : qsv_process_data(avctx, &s->qsv, frame, got_frame, avpkt); 963cabdff1aSopenharmony_ci /* in progress of reinit, no read from fifo and keep the buffer_pkt */ 964cabdff1aSopenharmony_ci if (!s->qsv.reinit_flag) { 965cabdff1aSopenharmony_ci av_packet_unref(&s->buffer_pkt); 966cabdff1aSopenharmony_ci av_fifo_read(s->packet_fifo, &s->buffer_pkt, 1); 967cabdff1aSopenharmony_ci } 968cabdff1aSopenharmony_ci } 969cabdff1aSopenharmony_ci 970cabdff1aSopenharmony_ci ret = qsv_process_data(avctx, &s->qsv, frame, got_frame, &s->buffer_pkt); 971cabdff1aSopenharmony_ci if (ret < 0){ 972cabdff1aSopenharmony_ci /* Drop buffer_pkt when failed to decode the packet. Otherwise, 973cabdff1aSopenharmony_ci the decoder will keep decoding the failure packet. */ 974cabdff1aSopenharmony_ci av_packet_unref(&s->buffer_pkt); 975cabdff1aSopenharmony_ci return ret; 976cabdff1aSopenharmony_ci } 977cabdff1aSopenharmony_ci if (s->qsv.reinit_flag) 978cabdff1aSopenharmony_ci continue; 979cabdff1aSopenharmony_ci 980cabdff1aSopenharmony_ci s->buffer_pkt.size -= ret; 981cabdff1aSopenharmony_ci s->buffer_pkt.data += ret; 982cabdff1aSopenharmony_ci } 983cabdff1aSopenharmony_ci 984cabdff1aSopenharmony_ci return avpkt->size; 985cabdff1aSopenharmony_ci} 986cabdff1aSopenharmony_ci 987cabdff1aSopenharmony_cistatic void qsv_decode_flush(AVCodecContext *avctx) 988cabdff1aSopenharmony_ci{ 989cabdff1aSopenharmony_ci QSVDecContext *s = avctx->priv_data; 990cabdff1aSopenharmony_ci 991cabdff1aSopenharmony_ci qsv_clear_buffers(s); 992cabdff1aSopenharmony_ci 993cabdff1aSopenharmony_ci s->qsv.orig_pix_fmt = AV_PIX_FMT_NONE; 994cabdff1aSopenharmony_ci s->qsv.initialized = 0; 995cabdff1aSopenharmony_ci} 996cabdff1aSopenharmony_ci 997cabdff1aSopenharmony_ci#define OFFSET(x) offsetof(QSVDecContext, x) 998cabdff1aSopenharmony_ci#define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM 999cabdff1aSopenharmony_ci 1000cabdff1aSopenharmony_ci#define DEFINE_QSV_DECODER_WITH_OPTION(x, X, bsf_name, opt) \ 1001cabdff1aSopenharmony_cistatic const AVClass x##_qsv_class = { \ 1002cabdff1aSopenharmony_ci .class_name = #x "_qsv", \ 1003cabdff1aSopenharmony_ci .item_name = av_default_item_name, \ 1004cabdff1aSopenharmony_ci .option = opt, \ 1005cabdff1aSopenharmony_ci .version = LIBAVUTIL_VERSION_INT, \ 1006cabdff1aSopenharmony_ci}; \ 1007cabdff1aSopenharmony_ciconst FFCodec ff_##x##_qsv_decoder = { \ 1008cabdff1aSopenharmony_ci .p.name = #x "_qsv", \ 1009cabdff1aSopenharmony_ci .p.long_name = NULL_IF_CONFIG_SMALL(#X " video (Intel Quick Sync Video acceleration)"), \ 1010cabdff1aSopenharmony_ci .priv_data_size = sizeof(QSVDecContext), \ 1011cabdff1aSopenharmony_ci .p.type = AVMEDIA_TYPE_VIDEO, \ 1012cabdff1aSopenharmony_ci .p.id = AV_CODEC_ID_##X, \ 1013cabdff1aSopenharmony_ci .init = qsv_decode_init, \ 1014cabdff1aSopenharmony_ci FF_CODEC_DECODE_CB(qsv_decode_frame), \ 1015cabdff1aSopenharmony_ci .flush = qsv_decode_flush, \ 1016cabdff1aSopenharmony_ci .close = qsv_decode_close, \ 1017cabdff1aSopenharmony_ci .bsfs = bsf_name, \ 1018cabdff1aSopenharmony_ci .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HYBRID, \ 1019cabdff1aSopenharmony_ci .p.priv_class = &x##_qsv_class, \ 1020cabdff1aSopenharmony_ci .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, \ 1021cabdff1aSopenharmony_ci AV_PIX_FMT_P010, \ 1022cabdff1aSopenharmony_ci AV_PIX_FMT_YUYV422, \ 1023cabdff1aSopenharmony_ci AV_PIX_FMT_Y210, \ 1024cabdff1aSopenharmony_ci AV_PIX_FMT_QSV, \ 1025cabdff1aSopenharmony_ci AV_PIX_FMT_NONE }, \ 1026cabdff1aSopenharmony_ci .hw_configs = qsv_hw_configs, \ 1027cabdff1aSopenharmony_ci .p.wrapper_name = "qsv", \ 1028cabdff1aSopenharmony_ci}; \ 1029cabdff1aSopenharmony_ci 1030cabdff1aSopenharmony_ci#define DEFINE_QSV_DECODER(x, X, bsf_name) DEFINE_QSV_DECODER_WITH_OPTION(x, X, bsf_name, options) 1031cabdff1aSopenharmony_ci 1032cabdff1aSopenharmony_ci#if CONFIG_HEVC_QSV_DECODER 1033cabdff1aSopenharmony_cistatic const AVOption hevc_options[] = { 1034cabdff1aSopenharmony_ci { "async_depth", "Internal parallelization depth, the higher the value the higher the latency.", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = ASYNC_DEPTH_DEFAULT }, 1, INT_MAX, VD }, 1035cabdff1aSopenharmony_ci 1036cabdff1aSopenharmony_ci { "load_plugin", "A user plugin to load in an internal session", OFFSET(load_plugin), AV_OPT_TYPE_INT, { .i64 = LOAD_PLUGIN_HEVC_HW }, LOAD_PLUGIN_NONE, LOAD_PLUGIN_HEVC_HW, VD, "load_plugin" }, 1037cabdff1aSopenharmony_ci { "none", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_NONE }, 0, 0, VD, "load_plugin" }, 1038cabdff1aSopenharmony_ci { "hevc_sw", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_HEVC_SW }, 0, 0, VD, "load_plugin" }, 1039cabdff1aSopenharmony_ci { "hevc_hw", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_HEVC_HW }, 0, 0, VD, "load_plugin" }, 1040cabdff1aSopenharmony_ci 1041cabdff1aSopenharmony_ci { "load_plugins", "A :-separate list of hexadecimal plugin UIDs to load in an internal session", 1042cabdff1aSopenharmony_ci OFFSET(qsv.load_plugins), AV_OPT_TYPE_STRING, { .str = "" }, 0, 0, VD }, 1043cabdff1aSopenharmony_ci 1044cabdff1aSopenharmony_ci { "gpu_copy", "A GPU-accelerated copy between video and system memory", OFFSET(qsv.gpu_copy), AV_OPT_TYPE_INT, { .i64 = MFX_GPUCOPY_DEFAULT }, MFX_GPUCOPY_DEFAULT, MFX_GPUCOPY_OFF, VD, "gpu_copy"}, 1045cabdff1aSopenharmony_ci { "default", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_GPUCOPY_DEFAULT }, 0, 0, VD, "gpu_copy"}, 1046cabdff1aSopenharmony_ci { "on", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_GPUCOPY_ON }, 0, 0, VD, "gpu_copy"}, 1047cabdff1aSopenharmony_ci { "off", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_GPUCOPY_OFF }, 0, 0, VD, "gpu_copy"}, 1048cabdff1aSopenharmony_ci { NULL }, 1049cabdff1aSopenharmony_ci}; 1050cabdff1aSopenharmony_ciDEFINE_QSV_DECODER_WITH_OPTION(hevc, HEVC, "hevc_mp4toannexb", hevc_options) 1051cabdff1aSopenharmony_ci#endif 1052cabdff1aSopenharmony_ci 1053cabdff1aSopenharmony_cistatic const AVOption options[] = { 1054cabdff1aSopenharmony_ci { "async_depth", "Internal parallelization depth, the higher the value the higher the latency.", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = ASYNC_DEPTH_DEFAULT }, 1, INT_MAX, VD }, 1055cabdff1aSopenharmony_ci 1056cabdff1aSopenharmony_ci { "gpu_copy", "A GPU-accelerated copy between video and system memory", OFFSET(qsv.gpu_copy), AV_OPT_TYPE_INT, { .i64 = MFX_GPUCOPY_DEFAULT }, MFX_GPUCOPY_DEFAULT, MFX_GPUCOPY_OFF, VD, "gpu_copy"}, 1057cabdff1aSopenharmony_ci { "default", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_GPUCOPY_DEFAULT }, 0, 0, VD, "gpu_copy"}, 1058cabdff1aSopenharmony_ci { "on", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_GPUCOPY_ON }, 0, 0, VD, "gpu_copy"}, 1059cabdff1aSopenharmony_ci { "off", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_GPUCOPY_OFF }, 0, 0, VD, "gpu_copy"}, 1060cabdff1aSopenharmony_ci { NULL }, 1061cabdff1aSopenharmony_ci}; 1062cabdff1aSopenharmony_ci 1063cabdff1aSopenharmony_ci#if CONFIG_H264_QSV_DECODER 1064cabdff1aSopenharmony_ciDEFINE_QSV_DECODER(h264, H264, "h264_mp4toannexb") 1065cabdff1aSopenharmony_ci#endif 1066cabdff1aSopenharmony_ci 1067cabdff1aSopenharmony_ci#if CONFIG_MPEG2_QSV_DECODER 1068cabdff1aSopenharmony_ciDEFINE_QSV_DECODER(mpeg2, MPEG2VIDEO, NULL) 1069cabdff1aSopenharmony_ci#endif 1070cabdff1aSopenharmony_ci 1071cabdff1aSopenharmony_ci#if CONFIG_VC1_QSV_DECODER 1072cabdff1aSopenharmony_ciDEFINE_QSV_DECODER(vc1, VC1, NULL) 1073cabdff1aSopenharmony_ci#endif 1074cabdff1aSopenharmony_ci 1075cabdff1aSopenharmony_ci#if CONFIG_MJPEG_QSV_DECODER 1076cabdff1aSopenharmony_ciDEFINE_QSV_DECODER(mjpeg, MJPEG, NULL) 1077cabdff1aSopenharmony_ci#endif 1078cabdff1aSopenharmony_ci 1079cabdff1aSopenharmony_ci#if CONFIG_VP8_QSV_DECODER 1080cabdff1aSopenharmony_ciDEFINE_QSV_DECODER(vp8, VP8, NULL) 1081cabdff1aSopenharmony_ci#endif 1082cabdff1aSopenharmony_ci 1083cabdff1aSopenharmony_ci#if CONFIG_VP9_QSV_DECODER 1084cabdff1aSopenharmony_ciDEFINE_QSV_DECODER(vp9, VP9, NULL) 1085cabdff1aSopenharmony_ci#endif 1086cabdff1aSopenharmony_ci 1087cabdff1aSopenharmony_ci#if CONFIG_AV1_QSV_DECODER 1088cabdff1aSopenharmony_ciDEFINE_QSV_DECODER(av1, AV1, NULL) 1089cabdff1aSopenharmony_ci#endif 1090