hwcontext_qsv: Support derivation from child devices

This commit is contained in:
Mark Thompson 2017-03-04 23:57:43 +00:00
parent e669db7610
commit aa51bb3d27
1 changed files with 84 additions and 29 deletions

View File

@ -792,21 +792,96 @@ static mfxIMPL choose_implementation(const char *device)
return impl;
}
static int qsv_device_create(AVHWDeviceContext *ctx, const char *device,
AVDictionary *opts, int flags)
static int qsv_device_derive_from_child(AVHWDeviceContext *ctx,
mfxIMPL implementation,
AVHWDeviceContext *child_device_ctx,
int flags)
{
AVQSVDeviceContext *hwctx = ctx->hwctx;
QSVDevicePriv *priv;
enum AVHWDeviceType child_device_type;
AVDictionaryEntry *e;
QSVDeviceContext *s = ctx->internal->priv;
mfxVersion ver = { { 3, 1 } };
mfxIMPL impl;
mfxHDL handle;
mfxHandleType handle_type;
mfxStatus err;
int ret;
switch (child_device_ctx->type) {
#if CONFIG_VAAPI
case AV_HWDEVICE_TYPE_VAAPI:
{
AVVAAPIDeviceContext *child_device_hwctx = child_device_ctx->hwctx;
handle_type = MFX_HANDLE_VA_DISPLAY;
handle = (mfxHDL)child_device_hwctx->display;
}
break;
#endif
#if CONFIG_DXVA2
case AV_HWDEVICE_TYPE_DXVA2:
{
AVDXVA2DeviceContext *child_device_hwctx = child_device_ctx->hwctx;
handle_type = MFX_HANDLE_D3D9_DEVICE_MANAGER;
handle = (mfxHDL)child_device_hwctx->devmgr;
}
break;
#endif
default:
ret = AVERROR(ENOSYS);
goto fail;
}
err = MFXInit(implementation, &ver, &hwctx->session);
if (err != MFX_ERR_NONE) {
av_log(ctx, AV_LOG_ERROR, "Error initializing an MFX session: "
"%d.\n", err);
ret = AVERROR_UNKNOWN;
goto fail;
}
err = MFXVideoCORE_SetHandle(hwctx->session, handle_type, handle);
if (err != MFX_ERR_NONE) {
av_log(ctx, AV_LOG_ERROR, "Error setting child device handle: "
"%d\n", err);
ret = AVERROR_UNKNOWN;
goto fail;
}
ret = qsv_device_init(ctx);
if (ret < 0)
goto fail;
if (s->handle_type != handle_type) {
av_log(ctx, AV_LOG_ERROR, "Error in child device handle setup: "
"type mismatch (%d != %d).\n", s->handle_type, handle_type);
err = AVERROR_UNKNOWN;
goto fail;
}
return 0;
fail:
if (hwctx->session)
MFXClose(hwctx->session);
return ret;
}
static int qsv_device_derive(AVHWDeviceContext *ctx,
AVHWDeviceContext *child_device_ctx, int flags)
{
return qsv_device_derive_from_child(ctx, MFX_IMPL_HARDWARE_ANY,
child_device_ctx, flags);
}
static int qsv_device_create(AVHWDeviceContext *ctx, const char *device,
AVDictionary *opts, int flags)
{
QSVDevicePriv *priv;
enum AVHWDeviceType child_device_type;
AVHWDeviceContext *child_device;
AVDictionaryEntry *e;
mfxIMPL impl;
int ret;
priv = av_mallocz(sizeof(*priv));
if (!priv)
return AVERROR(ENOMEM);
@ -830,32 +905,11 @@ static int qsv_device_create(AVHWDeviceContext *ctx, const char *device,
if (ret < 0)
return ret;
{
AVHWDeviceContext *child_device_ctx = (AVHWDeviceContext*)priv->child_device_ctx->data;
#if CONFIG_VAAPI
AVVAAPIDeviceContext *child_device_hwctx = child_device_ctx->hwctx;
handle_type = MFX_HANDLE_VA_DISPLAY;
handle = (mfxHDL)child_device_hwctx->display;
#elif CONFIG_DXVA2
AVDXVA2DeviceContext *child_device_hwctx = child_device_ctx->hwctx;
handle_type = MFX_HANDLE_D3D9_DEVICE_MANAGER;
handle = (mfxHDL)child_device_hwctx->devmgr;
#endif
}
child_device = (AVHWDeviceContext*)priv->child_device_ctx->data;
impl = choose_implementation(device);
err = MFXInit(impl, &ver, &hwctx->session);
if (err != MFX_ERR_NONE) {
av_log(ctx, AV_LOG_ERROR, "Error initializing an MFX session\n");
return AVERROR_UNKNOWN;
}
err = MFXVideoCORE_SetHandle(hwctx->session, handle_type, handle);
if (err != MFX_ERR_NONE)
return AVERROR_UNKNOWN;
return 0;
return qsv_device_derive_from_child(ctx, impl, child_device, 0);
}
const HWContextType ff_hwcontext_type_qsv = {
@ -868,6 +922,7 @@ const HWContextType ff_hwcontext_type_qsv = {
.frames_priv_size = sizeof(QSVFramesContext),
.device_create = qsv_device_create,
.device_derive = qsv_device_derive,
.device_init = qsv_device_init,
.frames_get_constraints = qsv_frames_get_constraints,
.frames_init = qsv_frames_init,