libvlc: use a callback to select the plane to render to

When rendering in Direct3D11 to NV12 we use 2 planes in the same texture.
This commit is contained in:
Steve Lhomme 2019-05-09 14:13:59 +02:00
parent 9b6e022193
commit cf16b6f0e7
7 changed files with 62 additions and 12 deletions

View File

@ -172,6 +172,15 @@ static bool StartRendering_cb( void *opaque, bool enter, const libvlc_video_dire
return true;
}
static bool SelectPlane_cb( void *opaque, size_t plane )
{
struct render_context *ctx = static_cast<struct render_context *>( opaque );
if ( plane != 0 ) // we only support one packed RGBA plane (DXGI_FORMAT_R8G8B8A8_UNORM)
return false;
ctx->d3dctx->OMSetRenderTargets( 1, &ctx->textureRenderTarget, NULL );
return true;
}
static bool Setup_cb( void **opaque, const libvlc_video_direct3d_device_cfg_t *cfg, libvlc_video_direct3d_device_setup_t *out )
{
struct render_context *ctx = static_cast<struct render_context *>(*opaque);
@ -442,7 +451,7 @@ int WINAPI WinMain(HINSTANCE hInstance,
/* Tell VLC to render into our D3D11 environment */
libvlc_video_direct3d_set_callbacks( p_mp, libvlc_video_direct3d_engine_d3d11,
Setup_cb, Cleanup_cb, UpdateOutput_cb, Swap_cb, StartRendering_cb,
Setup_cb, Cleanup_cb, UpdateOutput_cb, Swap_cb, StartRendering_cb, SelectPlane_cb,
&Context );
libvlc_media_player_play( p_mp );

View File

@ -349,7 +349,7 @@ int WINAPI WinMain(HINSTANCE hInstance,
/* Tell VLC to render into our D3D9 environment */
libvlc_video_direct3d_set_callbacks( p_mp, libvlc_video_direct3d_engine_d3d9,
Setup_cb, Cleanup_cb, UpdateOutput_cb, Swap_cb, StartRendering_cb,
Setup_cb, Cleanup_cb, UpdateOutput_cb, Swap_cb, StartRendering_cb, NULL,
&Context );
libvlc_media_player_play( p_mp );

View File

@ -742,6 +742,25 @@ typedef struct
*/
typedef bool( *libvlc_video_direct3d_start_end_rendering_cb )( void *opaque, bool enter, const libvlc_video_direct3d_hdr10_metadata_t *hdr10 );
/** Tell the host the rendering for the given plane is about to start
*
* \param opaque private pointer set on the opaque parameter of @a libvlc_video_direct3d_device_setup_cb() [IN]
* \param plane number of the rendering plane to select
* \return true on success
* \version LibVLC 4.0.0 or later
*
* \note This is only used with \ref libvlc_video_direct3d_engine_d3d11.
*
* The host should call OMSetRenderTargets for Direct3D11. If this callback is
* not used (set to NULL in @a libvlc_video_direct3d_set_callbacks()) OMSetRenderTargets
* has to be set during the @a libvlc_video_direct3d_start_end_rendering_cb()
* entering call.
*
* The number of planes depend on the DXGI_FORMAT returned during the
* \ref LIBVLC_VIDEO_UPDATE_OUTPUT call. It's usually one plane except for
* semi-planar formats like DXGI_FORMAT_NV12 or DXGI_FORMAT_P010.
*/
typedef bool( *libvlc_video_direct3d_select_plane_cb )( void *opaque, size_t plane );
/**
* Set callbacks and data to render decoded video to a custom Direct3D output
@ -770,6 +789,7 @@ int libvlc_video_direct3d_set_callbacks( libvlc_media_player_t *mp,
libvlc_video_direct3d_update_output_cb update_output_cb,
libvlc_video_swap_cb swap_cb,
libvlc_video_direct3d_start_end_rendering_cb makeCurrent_cb,
libvlc_video_direct3d_select_plane_cb select_plane_cb,
void* opaque );
/**

View File

@ -646,6 +646,7 @@ libvlc_media_player_new( libvlc_instance_t *instance )
var_Create( mp, "vout-cb-swap", VLC_VAR_ADDRESS );
var_Create( mp, "vout-cb-get-proc-address", VLC_VAR_ADDRESS );
var_Create( mp, "vout-cb-make-current", VLC_VAR_ADDRESS );
var_Create( mp, "vout-cb-select-plane", VLC_VAR_ADDRESS );
var_Create (mp, "avcodec-hw", VLC_VAR_STRING);
var_Create (mp, "drawable-xid", VLC_VAR_INTEGER);
@ -1209,6 +1210,7 @@ int libvlc_video_direct3d_set_callbacks( libvlc_media_player_t *mp,
libvlc_video_direct3d_update_output_cb update_output_cb,
libvlc_video_swap_cb swap_cb,
libvlc_video_direct3d_start_end_rendering_cb makeCurrent_cb,
libvlc_video_direct3d_select_plane_cb select_plane_cb,
void* opaque )
{
var_SetString( mp, "window", "wdummy");
@ -1232,6 +1234,7 @@ int libvlc_video_direct3d_set_callbacks( libvlc_media_player_t *mp,
var_SetAddress( mp, "vout-cb-update-output", update_output_cb );
var_SetAddress( mp, "vout-cb-swap", swap_cb );
var_SetAddress( mp, "vout-cb-make-current", makeCurrent_cb );
var_SetAddress( mp, "vout-cb-select-plane", select_plane_cb );
return 1;
}

View File

@ -44,7 +44,7 @@
void D3D11_RenderQuad(d3d11_device_t *d3d_dev, d3d_quad_t *quad, d3d_vshader_t *vsshader,
ID3D11ShaderResourceView *resourceView[D3D11_MAX_SHADER_VIEW],
ID3D11RenderTargetView *d3drenderTargetView[D3D11_MAX_RENDER_TARGET])
d3d11_select_plane_t selectPlane, void *selectOpaque)
{
UINT offset = 0;
@ -73,14 +73,13 @@ void D3D11_RenderQuad(d3d11_device_t *d3d_dev, d3d_quad_t *quad, d3d_vshader_t *
if (!quad->d3dpixelShader[i])
break;
if (unlikely(!selectPlane(selectOpaque, i)))
continue;
ID3D11DeviceContext_PSSetShader(d3d_dev->d3dcontext, quad->d3dpixelShader[i], NULL, 0);
ID3D11DeviceContext_RSSetViewports(d3d_dev->d3dcontext, 1, &quad->cropViewport[i]);
if (d3drenderTargetView[0])
/* TODO: handle outside selection of the render sub-target */
ID3D11DeviceContext_OMSetRenderTargets(d3d_dev->d3dcontext, 1, &d3drenderTargetView[i], NULL);
ID3D11DeviceContext_DrawIndexed(d3d_dev->d3dcontext, quad->indexCount, 0, 0);
}

View File

@ -45,9 +45,11 @@ typedef struct d3d_vertex_t {
} texture;
} d3d_vertex_t;
typedef bool (*d3d11_select_plane_t)(void *opaque, size_t plane_index);
void D3D11_RenderQuad(d3d11_device_t *, d3d_quad_t *, d3d_vshader_t *,
ID3D11ShaderResourceView *resourceViews[D3D11_MAX_SHADER_VIEW],
ID3D11RenderTargetView *renderTarget[D3D11_MAX_RENDER_TARGET]);
d3d11_select_plane_t selectPlane, void *selectOpaque);
int D3D11_AllocateQuad(vlc_object_t *, d3d11_device_t *, video_projection_mode_t, d3d_quad_t *);
#define D3D11_AllocateQuad(a,b,c,d) D3D11_AllocateQuad(VLC_OBJECT(a),b,c,d)

View File

@ -169,6 +169,7 @@ struct vout_display_sys_t
libvlc_video_direct3d_update_output_cb updateOutputCb;
libvlc_video_swap_cb swapCb;
libvlc_video_direct3d_start_end_rendering_cb startEndRenderingCb;
libvlc_video_direct3d_select_plane_cb selectPlaneCb;
};
static picture_pool_t *Pool(vout_display_t *, unsigned);
@ -636,6 +637,16 @@ static bool LocalSwapchainStartEndRendering( void *opaque, bool enter, const lib
return true;
}
static bool LocalSwapchainSelectPlane( void *opaque, size_t plane )
{
struct d3d11_local_swapchain *display = opaque;
if (!display->swapchainTargetView[plane])
return false;
ID3D11DeviceContext_OMSetRenderTargets(display->d3d_dev.d3dcontext, 1,
&display->swapchainTargetView[plane], NULL);
return true;
}
static int Open(vout_display_t *vd, const vout_display_cfg_t *cfg,
video_format_t *fmtp, vlc_video_context *context)
{
@ -668,6 +679,7 @@ static int Open(vout_display_t *vd, const vout_display_cfg_t *cfg,
sys->updateOutputCb = var_InheritAddress( vd, "vout-cb-update-output" );
sys->swapCb = var_InheritAddress( vd, "vout-cb-swap" );
sys->startEndRenderingCb = var_InheritAddress( vd, "vout-cb-make-current" );
sys->selectPlaneCb = var_InheritAddress( vd, "vout-cb-select-plane" );
if ( sys->setupDeviceCb == NULL || sys->swapCb == NULL || sys->startEndRenderingCb == NULL || sys->updateOutputCb == NULL )
{
@ -680,6 +692,7 @@ static int Open(vout_display_t *vd, const vout_display_cfg_t *cfg,
sys->updateOutputCb = LocalSwapchainUpdateOutput;
sys->swapCb = LocalSwapchainSwap;
sys->startEndRenderingCb = LocalSwapchainStartEndRendering;
sys->selectPlaneCb = LocalSwapchainSelectPlane;
#if VLC_WINSTORE_APP
/* LEGACY, the d3dcontext and swapchain were given by the host app */
@ -957,6 +970,12 @@ static int Control(vout_display_t *vd, int query, va_list args)
return res;
}
static bool SelectRenderPlane(void *opaque, size_t plane)
{
vout_display_sys_t *sys = opaque;
return sys->selectPlaneCb(sys->outside_opaque, plane);
}
static void PreparePicture(vout_display_t *vd, picture_t *picture, subpicture_t *subpicture)
{
vout_display_sys_t *sys = vd->sys;
@ -1069,8 +1088,7 @@ static void PreparePicture(vout_display_t *vd, picture_t *picture, subpicture_t
}
D3D11_RenderQuad(&sys->d3d_dev, &sys->picQuad,
vd->source.projection_mode == PROJECTION_MODE_RECTANGULAR ? &sys->flatVShader : &sys->projectionVShader,
renderSrc,
sys->internal_swapchain.swapchainTargetView); /* NULL with external rendering */
renderSrc, SelectRenderPlane, sys);
if (subpicture) {
// draw the additional vertices
@ -1079,8 +1097,7 @@ static void PreparePicture(vout_display_t *vd, picture_t *picture, subpicture_t
{
d3d_quad_t *quad = (d3d_quad_t *) sys->d3dregions[i]->p_sys;
D3D11_RenderQuad(&sys->d3d_dev, quad, &sys->flatVShader,
quad->picSys.renderSrc,
sys->internal_swapchain.swapchainTargetView); /* NULL with external rendering */
quad->picSys.renderSrc, SelectRenderPlane, sys);
}
}
}