/* create the QSV session */ static int init_vpp_session(AVFilterContext *avctx, QSVVPPContext *s) { AVFilterLink *inlink = avctx->inputs[0]; AVFilterLink *outlink = avctx->outputs[0]; AVQSVFramesContext *in_frames_hwctx = NULL; AVQSVFramesContext *out_frames_hwctx = NULL; AVBufferRef *device_ref; AVHWDeviceContext *device_ctx; AVQSVDeviceContext *device_hwctx; mfxHDL handle; mfxHandleType handle_type; mfxVersion ver; mfxIMPL impl; int ret, i; if (inlink->hw_frames_ctx) { AVHWFramesContext *frames_ctx = (AVHWFramesContext *)inlink->hw_frames_ctx->data; device_ref = frames_ctx->device_ref; in_frames_hwctx = frames_ctx->hwctx; s->in_mem_mode = in_frames_hwctx->frame_type; s->surface_ptrs_in = av_mallocz_array(in_frames_hwctx->nb_surfaces, sizeof(*s->surface_ptrs_in)); if (!s->surface_ptrs_in) return AVERROR(ENOMEM); for (i = 0; i < in_frames_hwctx->nb_surfaces; i++) s->surface_ptrs_in[i] = in_frames_hwctx->surfaces + i; s->nb_surface_ptrs_in = in_frames_hwctx->nb_surfaces; } else if (avctx->hw_device_ctx) { device_ref = avctx->hw_device_ctx; s->in_mem_mode = MFX_MEMTYPE_SYSTEM_MEMORY; } else { av_log(avctx, AV_LOG_ERROR, "No hw context provided.\n"); return AVERROR(EINVAL); } device_ctx = (AVHWDeviceContext *)device_ref->data; device_hwctx = device_ctx->hwctx; if (outlink->format == AV_PIX_FMT_QSV) { AVHWFramesContext *out_frames_ctx; AVBufferRef *out_frames_ref = av_hwframe_ctx_alloc(device_ref); if (!out_frames_ref) return AVERROR(ENOMEM); s->out_mem_mode = IS_OPAQUE_MEMORY(s->in_mem_mode) ? MFX_MEMTYPE_OPAQUE_FRAME : MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET; out_frames_ctx = (AVHWFramesContext *)out_frames_ref->data; out_frames_hwctx = out_frames_ctx->hwctx; out_frames_ctx->format = AV_PIX_FMT_QSV; out_frames_ctx->width = FFALIGN(outlink->w, 32); out_frames_ctx->height = FFALIGN(outlink->h, 32); out_frames_ctx->sw_format = s->out_sw_format; out_frames_ctx->initial_pool_size = 64; out_frames_hwctx->frame_type = s->out_mem_mode; ret = av_hwframe_ctx_init(out_frames_ref); if (ret < 0) { av_buffer_unref(&out_frames_ref); av_log(avctx, AV_LOG_ERROR, "Error creating frames_ctx for output pad.\n"); return ret; } s->surface_ptrs_out = av_mallocz_array(out_frames_hwctx->nb_surfaces, sizeof(*s->surface_ptrs_out)); if (!s->surface_ptrs_out) { av_buffer_unref(&out_frames_ref); return AVERROR(ENOMEM); } for (i = 0; i < out_frames_hwctx->nb_surfaces; i++) s->surface_ptrs_out[i] = out_frames_hwctx->surfaces + i; s->nb_surface_ptrs_out = out_frames_hwctx->nb_surfaces; av_buffer_unref(&outlink->hw_frames_ctx); outlink->hw_frames_ctx = out_frames_ref; } else s->out_mem_mode = MFX_MEMTYPE_SYSTEM_MEMORY; /* extract the properties of the "master" session given to us */ ret = MFXQueryIMPL(device_hwctx->session, &impl); if (ret == MFX_ERR_NONE) ret = MFXQueryVersion(device_hwctx->session, &ver); if (ret != MFX_ERR_NONE) { av_log(avctx, AV_LOG_ERROR, "Error querying the session attributes\n"); return AVERROR_UNKNOWN; } for (i = 0; i < FF_ARRAY_ELEMS(handle_types); i++) { ret = MFXVideoCORE_GetHandle(device_hwctx->session, handle_types[i], &handle); if (ret == MFX_ERR_NONE) { handle_type = handle_types[i]; break; } } if (ret != MFX_ERR_NONE) { av_log(avctx, AV_LOG_ERROR, "Error getting the session handle\n"); return AVERROR_UNKNOWN; } /* create a "slave" session with those same properties, to be used for vpp */ ret = MFXInit(impl, &ver, &s->session); if (ret != MFX_ERR_NONE) { av_log(avctx, AV_LOG_ERROR, "Error initializing a session for scaling\n"); return AVERROR_UNKNOWN; } if (handle) { ret = MFXVideoCORE_SetHandle(s->session, handle_type, handle); if (ret != MFX_ERR_NONE) return AVERROR_UNKNOWN; } if (QSV_RUNTIME_VERSION_ATLEAST(ver, 1, 25)) { ret = MFXJoinSession(device_hwctx->session, s->session); if (ret != MFX_ERR_NONE) return AVERROR_UNKNOWN; } if (IS_OPAQUE_MEMORY(s->in_mem_mode) || IS_OPAQUE_MEMORY(s->out_mem_mode)) { s->opaque_alloc.In.Surfaces = s->surface_ptrs_in; s->opaque_alloc.In.NumSurface = s->nb_surface_ptrs_in; s->opaque_alloc.In.Type = s->in_mem_mode; s->opaque_alloc.Out.Surfaces = s->surface_ptrs_out; s->opaque_alloc.Out.NumSurface = s->nb_surface_ptrs_out; s->opaque_alloc.Out.Type = s->out_mem_mode; s->opaque_alloc.Header.BufferId = MFX_EXTBUFF_OPAQUE_SURFACE_ALLOCATION; s->opaque_alloc.Header.BufferSz = sizeof(s->opaque_alloc); } else if (IS_VIDEO_MEMORY(s->in_mem_mode) || IS_VIDEO_MEMORY(s->out_mem_mode)) { mfxFrameAllocator frame_allocator = { .pthis = s, .Alloc = frame_alloc, .Lock = frame_lock, .Unlock = frame_unlock, .GetHDL = frame_get_hdl, .Free = frame_free, }; ret = MFXVideoCORE_SetFrameAllocator(s->session, &frame_allocator); if (ret != MFX_ERR_NONE) return AVERROR_UNKNOWN; }
int ff_qsv_init_session_device(AVCodecContext *avctx, mfxSession *psession, AVBufferRef *device_ref, const char *load_plugins) { static const mfxHandleType handle_types[] = { MFX_HANDLE_VA_DISPLAY, MFX_HANDLE_D3D9_DEVICE_MANAGER, MFX_HANDLE_D3D11_DEVICE, }; AVHWDeviceContext *device_ctx = (AVHWDeviceContext*)device_ref->data; AVQSVDeviceContext *device_hwctx = device_ctx->hwctx; mfxSession parent_session = device_hwctx->session; mfxSession session; mfxVersion ver; mfxIMPL impl; mfxHDL handle = NULL; mfxHandleType handle_type; mfxStatus err; int i, ret; err = MFXQueryIMPL(parent_session, &impl); if (err == MFX_ERR_NONE) err = MFXQueryVersion(parent_session, &ver); if (err != MFX_ERR_NONE) return ff_qsv_print_error(avctx, err, "Error querying the session attributes"); for (i = 0; i < FF_ARRAY_ELEMS(handle_types); i++) { err = MFXVideoCORE_GetHandle(parent_session, handle_types[i], &handle); if (err == MFX_ERR_NONE) { handle_type = handle_types[i]; break; } handle = NULL; } if (!handle) { av_log(avctx, AV_LOG_VERBOSE, "No supported hw handle could be retrieved " "from the session\n"); } err = MFXInit(impl, &ver, &session); if (err != MFX_ERR_NONE) return ff_qsv_print_error(avctx, err, "Error initializing a child MFX session"); if (handle) { err = MFXVideoCORE_SetHandle(session, handle_type, handle); if (err != MFX_ERR_NONE) return ff_qsv_print_error(avctx, err, "Error setting a HW handle"); } if (QSV_RUNTIME_VERSION_ATLEAST(ver, 1, 25)) { err = MFXJoinSession(parent_session, session); if (err != MFX_ERR_NONE) return ff_qsv_print_error(avctx, err, "Error joining session"); } ret = qsv_load_plugins(session, load_plugins, avctx); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Error loading plugins\n"); return ret; } *psession = session; return 0; }