mfxStatus Initialize(mfxIMPL impl, mfxVersion ver, mfxSession *pSession, mfxFrameAllocator* pmfxAllocator, bool bCreateSharedHandles) { mfxStatus sts = MFX_ERR_NONE; // Initialize Intel Media SDK Session sts = MFXInit(impl, &ver, pSession); MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts); // Create VA display mfxHDL displayHandle = { 0 }; sts = CreateVAEnvDRM(&displayHandle); MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts); // Provide VA display handle to Media SDK sts = MFXVideoCORE_SetHandle(*pSession, MFX_HANDLE_VA_DISPLAY, displayHandle); MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts); // If mfxFrameAllocator is provided it means we need to setup memory allocator if (pmfxAllocator) { pmfxAllocator->pthis = *pSession; // We use Media SDK session ID as the allocation identifier pmfxAllocator->Alloc = simple_alloc; pmfxAllocator->Free = simple_free; pmfxAllocator->Lock = simple_lock; pmfxAllocator->Unlock = simple_unlock; pmfxAllocator->GetHDL = simple_gethdl; // Since we are using video memory we must provide Media SDK with an external allocator sts = MFXVideoCORE_SetFrameAllocator(*pSession, pmfxAllocator); MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts); } return sts; }
/* 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; }
static int init_out_session(AVFilterContext *ctx) { QSVScaleContext *s = ctx->priv; AVHWFramesContext *in_frames_ctx = (AVHWFramesContext*)ctx->inputs[0]->hw_frames_ctx->data; AVHWFramesContext *out_frames_ctx = (AVHWFramesContext*)ctx->outputs[0]->hw_frames_ctx->data; AVQSVFramesContext *in_frames_hwctx = in_frames_ctx->hwctx; AVQSVFramesContext *out_frames_hwctx = out_frames_ctx->hwctx; AVQSVDeviceContext *device_hwctx = in_frames_ctx->device_ctx->hwctx; int opaque = !!(in_frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME); mfxHDL handle = NULL; mfxHandleType handle_type; mfxVersion ver; mfxIMPL impl; mfxVideoParam par; mfxStatus err; int i; /* extract the properties of the "master" session given to us */ err = MFXQueryIMPL(device_hwctx->session, &impl); if (err == MFX_ERR_NONE) err = MFXQueryVersion(device_hwctx->session, &ver); if (err != MFX_ERR_NONE) { av_log(ctx, AV_LOG_ERROR, "Error querying the session attributes\n"); return AVERROR_UNKNOWN; } for (i = 0; i < FF_ARRAY_ELEMS(handle_types); i++) { err = MFXVideoCORE_GetHandle(device_hwctx->session, handle_types[i], &handle); if (err == MFX_ERR_NONE) { handle_type = handle_types[i]; break; } } /* create a "slave" session with those same properties, to be used for * actual scaling */ err = MFXInit(impl, &ver, &s->session); if (err != MFX_ERR_NONE) { av_log(ctx, AV_LOG_ERROR, "Error initializing a session for scaling\n"); return AVERROR_UNKNOWN; } if (handle) { err = MFXVideoCORE_SetHandle(s->session, handle_type, handle); if (err != MFX_ERR_NONE) return AVERROR_UNKNOWN; } memset(&par, 0, sizeof(par)); if (opaque) { 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; s->surface_ptrs_out = av_mallocz_array(out_frames_hwctx->nb_surfaces, sizeof(*s->surface_ptrs_out)); if (!s->surface_ptrs_out) 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; s->opaque_alloc.In.Surfaces = s->surface_ptrs_in; s->opaque_alloc.In.NumSurface = s->nb_surface_ptrs_in; s->opaque_alloc.In.Type = in_frames_hwctx->frame_type; s->opaque_alloc.Out.Surfaces = s->surface_ptrs_out; s->opaque_alloc.Out.NumSurface = s->nb_surface_ptrs_out; s->opaque_alloc.Out.Type = out_frames_hwctx->frame_type; s->opaque_alloc.Header.BufferId = MFX_EXTBUFF_OPAQUE_SURFACE_ALLOCATION; s->opaque_alloc.Header.BufferSz = sizeof(s->opaque_alloc); s->ext_buffers[0] = (mfxExtBuffer*)&s->opaque_alloc; par.ExtParam = s->ext_buffers; par.NumExtParam = FF_ARRAY_ELEMS(s->ext_buffers); par.IOPattern = MFX_IOPATTERN_IN_OPAQUE_MEMORY | MFX_IOPATTERN_OUT_OPAQUE_MEMORY; } else { mfxFrameAllocator frame_allocator = { .pthis = ctx, .Alloc = frame_alloc, .Lock = frame_lock, .Unlock = frame_unlock, .GetHDL = frame_get_hdl, .Free = frame_free, }; s->mem_ids_in = av_mallocz_array(in_frames_hwctx->nb_surfaces, sizeof(*s->mem_ids_in)); if (!s->mem_ids_in) return AVERROR(ENOMEM); for (i = 0; i < in_frames_hwctx->nb_surfaces; i++) s->mem_ids_in[i] = in_frames_hwctx->surfaces[i].Data.MemId; s->nb_mem_ids_in = in_frames_hwctx->nb_surfaces; s->mem_ids_out = av_mallocz_array(out_frames_hwctx->nb_surfaces, sizeof(*s->mem_ids_out)); if (!s->mem_ids_out) return AVERROR(ENOMEM); for (i = 0; i < out_frames_hwctx->nb_surfaces; i++) s->mem_ids_out[i] = out_frames_hwctx->surfaces[i].Data.MemId; s->nb_mem_ids_out = out_frames_hwctx->nb_surfaces; err = MFXVideoCORE_SetFrameAllocator(s->session, &frame_allocator); if (err != MFX_ERR_NONE) return AVERROR_UNKNOWN; par.IOPattern = MFX_IOPATTERN_IN_VIDEO_MEMORY | MFX_IOPATTERN_OUT_VIDEO_MEMORY; } par.AsyncDepth = 1; // TODO async par.vpp.In = in_frames_hwctx->surfaces[0].Info; par.vpp.Out = out_frames_hwctx->surfaces[0].Info; /* Apparently VPP requires the frame rate to be set to some value, otherwise * init will fail (probably for the framerate conversion filter). Since we * are only doing scaling here, we just invent an arbitrary * value */ par.vpp.In.FrameRateExtN = 25; par.vpp.In.FrameRateExtD = 1; par.vpp.Out.FrameRateExtN = 25; par.vpp.Out.FrameRateExtD = 1; err = MFXVideoVPP_Init(s->session, &par); if (err != MFX_ERR_NONE) { av_log(ctx, AV_LOG_ERROR, "Error opening the VPP for scaling\n"); return AVERROR_UNKNOWN; } return 0; }
static int qsv_init_internal_session(AVHWFramesContext *ctx, mfxSession *session, int upload) { QSVFramesContext *s = ctx->internal->priv; AVQSVFramesContext *frames_hwctx = ctx->hwctx; QSVDeviceContext *device_priv = ctx->device_ctx->internal->priv; int opaque = !!(frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME); mfxFrameAllocator frame_allocator = { .pthis = ctx, .Alloc = frame_alloc, .Lock = frame_lock, .Unlock = frame_unlock, .GetHDL = frame_get_hdl, .Free = frame_free, }; mfxVideoParam par; mfxStatus err; err = MFXInit(device_priv->impl, &device_priv->ver, session); if (err != MFX_ERR_NONE) { av_log(ctx, AV_LOG_ERROR, "Error initializing an internal session\n"); return AVERROR_UNKNOWN; } if (device_priv->handle) { err = MFXVideoCORE_SetHandle(*session, device_priv->handle_type, device_priv->handle); if (err != MFX_ERR_NONE) return AVERROR_UNKNOWN; } if (!opaque) { err = MFXVideoCORE_SetFrameAllocator(*session, &frame_allocator); if (err != MFX_ERR_NONE) return AVERROR_UNKNOWN; } memset(&par, 0, sizeof(par)); if (opaque) { par.ExtParam = s->ext_buffers; par.NumExtParam = FF_ARRAY_ELEMS(s->ext_buffers); par.IOPattern = upload ? MFX_IOPATTERN_OUT_OPAQUE_MEMORY : MFX_IOPATTERN_IN_OPAQUE_MEMORY; } else { par.IOPattern = upload ? MFX_IOPATTERN_OUT_VIDEO_MEMORY : MFX_IOPATTERN_IN_VIDEO_MEMORY; } par.IOPattern |= upload ? MFX_IOPATTERN_IN_SYSTEM_MEMORY : MFX_IOPATTERN_OUT_SYSTEM_MEMORY; par.AsyncDepth = 1; par.vpp.In = frames_hwctx->surfaces[0].Info; /* Apparently VPP requires the frame rate to be set to some value, otherwise * init will fail (probably for the framerate conversion filter). Since we * are only doing data upload/download here, we just invent an arbitrary * value */ par.vpp.In.FrameRateExtN = 25; par.vpp.In.FrameRateExtD = 1; par.vpp.Out = par.vpp.In; err = MFXVideoVPP_Init(*session, &par); if (err != MFX_ERR_NONE) { av_log(ctx, AV_LOG_VERBOSE, "Error opening the internal VPP session." "Surface upload/download will not be possible\n"); MFXClose(*session); *session = NULL; } return 0; }