1 /* compile: g++ d3d11_player.cpp -o d3d11_player.exe -L<path/libvlc> -lvlc -ld3d11 -ld3dcompiler_47 -luuid */
3 /* This is the most extreme use case where libvlc is given its own ID3D11DeviceContext
4 and draws in a texture shared with the ID3D11DeviceContext of the app.
6 It's possible to share the ID3D11DeviceContext as long as the proper PixelShader
7 calls are overridden in the app after each libvlc drawing (see libvlc D3D11 doc).
9 It's also possible to use the SwapChain directly with libvlc and let it draw on its
10 entire area instead of drawing in a texture.
15 #include <d3dcompiler.h>
21 #ifdef DEBUG_D3D11_LEAKS
22 # include <initguid.h>
23 # include <dxgidebug.h>
28 #define SCREEN_WIDTH 1500
29 #define SCREEN_HEIGHT 900
30 #define BORDER_LEFT (-0.95f)
31 #define BORDER_RIGHT ( 0.85f)
32 #define BORDER_TOP ( 0.95f)
33 #define BORDER_BOTTOM (-0.90f)
35 #define check_leak(x) assert(x)
41 libvlc_media_player_t
*p_mp
;
43 /* resources shared by VLC */
44 ID3D11Device
*d3deviceVLC
;
45 ID3D11DeviceContext
*d3dctxVLC
;
48 ID3D11Texture2D
*textureVLC
; // shared between VLC and the app
49 ID3D11RenderTargetView
*textureRenderTarget
;
50 HANDLE sharedHandled
; // handle of the texture used by VLC and the app
52 /* texture VLC renders into */
53 ID3D11Texture2D
*texture
;
54 ID3D11ShaderResourceView
*textureShaderInput
;
57 /* Direct3D11 device/context */
58 ID3D11Device
*d3device
;
59 ID3D11DeviceContext
*d3dctx
;
61 IDXGISwapChain
*swapchain
;
62 ID3D11RenderTargetView
*swapchainRenderTarget
;
64 /* our vertex/pixel shader */
65 ID3D11VertexShader
*pVS
;
66 ID3D11PixelShader
*pPS
;
67 ID3D11InputLayout
*pShadersInputLayout
;
69 UINT vertexBufferStride
;
70 ID3D11Buffer
*pVertexBuffer
;
73 ID3D11Buffer
*pIndexBuffer
;
75 ID3D11SamplerState
*samplerState
;
77 CRITICAL_SECTION sizeLock
; // the ReportSize callback cannot be called during/after the Cleanup_cb is called
78 unsigned width
, height
;
79 void (*ReportSize
)(void *ReportOpaque
, unsigned width
, unsigned height
);
83 static const char *shaderStr
= "\
84 Texture2D shaderTexture;\n\
85 SamplerState samplerState;\n\
88 float4 position : SV_POSITION;\n\
89 float4 textureCoord : TEXCOORD0;\n\
92 float4 PShader(PS_INPUT In) : SV_TARGET\n\
94 return shaderTexture.Sample(samplerState, In.textureCoord);\n\
99 float4 position : POSITION;\n\
100 float4 textureCoord : TEXCOORD0;\n\
105 float4 position : SV_POSITION;\n\
106 float4 textureCoord : TEXCOORD0;\n\
109 VS_OUTPUT VShader(VS_INPUT In)\n\
115 struct SHADER_INPUT
{
127 static void init_direct3d(struct render_context
*ctx
)
130 DXGI_SWAP_CHAIN_DESC scd
= { };
133 scd
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
134 scd
.BufferDesc
.Width
= SCREEN_WIDTH
;
135 scd
.BufferDesc
.Height
= SCREEN_HEIGHT
;
136 scd
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
137 scd
.OutputWindow
= ctx
->hWnd
;
138 scd
.SampleDesc
.Count
= 1;
140 scd
.Flags
= DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
;
142 UINT creationFlags
= 0;
144 creationFlags
|= D3D11_CREATE_DEVICE_DEBUG
;
147 D3D11CreateDeviceAndSwapChain(NULL
,
148 D3D_DRIVER_TYPE_HARDWARE
,
160 /* The ID3D11Device must have multithread protection */
161 ID3D10Multithread
*pMultithread
;
162 hr
= ctx
->d3device
->QueryInterface( __uuidof(ID3D10Multithread
), (void **)&pMultithread
);
164 pMultithread
->SetMultithreadProtected(TRUE
);
165 pMultithread
->Release();
169 // GetWindowRect(hWnd, ¤tRect);
170 //currentRect.right - currentRect.left;
171 //currentRect.bottom - currentRect.top;
173 D3D11_VIEWPORT viewport
= { 0, 0, SCREEN_WIDTH
, SCREEN_HEIGHT
, 0, 0 };
175 ctx
->d3dctx
->RSSetViewports(1, &viewport
);
177 D3D11CreateDevice(NULL
,
178 D3D_DRIVER_TYPE_HARDWARE
,
180 creationFlags
| D3D11_CREATE_DEVICE_VIDEO_SUPPORT
, /* needed for hardware decoding */
183 &ctx
->d3deviceVLC
, NULL
, &ctx
->d3dctxVLC
);
185 ID3D11Texture2D
*pBackBuffer
;
186 ctx
->swapchain
->GetBuffer(0, __uuidof(ID3D11Texture2D
), (LPVOID
*)&pBackBuffer
);
188 ctx
->d3device
->CreateRenderTargetView(pBackBuffer
, NULL
, &ctx
->swapchainRenderTarget
);
189 pBackBuffer
->Release();
191 ctx
->d3dctx
->OMSetRenderTargets(1, &ctx
->swapchainRenderTarget
, NULL
);
193 ID3D10Blob
*VS
, *PS
, *pErrBlob
;
195 hr
= D3DCompile(shaderStr
, strlen(shaderStr
),
196 NULL
, NULL
, NULL
, "VShader", "vs_4_0", 0, 0, &VS
, &pErrBlob
);
197 err
= pErrBlob
? (char*)pErrBlob
->GetBufferPointer() : NULL
;
198 hr
= D3DCompile(shaderStr
, strlen(shaderStr
),
199 NULL
, NULL
, NULL
, "PShader", "ps_4_0", 0, 0, &PS
, &pErrBlob
);
200 err
= pErrBlob
? (char*)pErrBlob
->GetBufferPointer() : NULL
;
202 ctx
->d3device
->CreateVertexShader(VS
->GetBufferPointer(), VS
->GetBufferSize(), NULL
, &ctx
->pVS
);
203 ctx
->d3device
->CreatePixelShader(PS
->GetBufferPointer(), PS
->GetBufferSize(), NULL
, &ctx
->pPS
);
205 D3D11_INPUT_ELEMENT_DESC ied
[] =
207 { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT
, 0, D3D11_APPEND_ALIGNED_ELEMENT
, D3D11_INPUT_PER_VERTEX_DATA
, 0},
208 { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT
, 0, D3D11_APPEND_ALIGNED_ELEMENT
, D3D11_INPUT_PER_VERTEX_DATA
, 0},
211 hr
= ctx
->d3device
->CreateInputLayout(ied
, 2, VS
->GetBufferPointer(), VS
->GetBufferSize(), &ctx
->pShadersInputLayout
);
212 SHADER_INPUT OurVertices
[] =
214 {{BORDER_LEFT
, BORDER_BOTTOM
, 0.0f
}, {0.0f
, 1.0f
}},
215 {{BORDER_RIGHT
, BORDER_BOTTOM
, 0.0f
}, {1.0f
, 1.0f
}},
216 {{BORDER_RIGHT
, BORDER_TOP
, 0.0f
}, {1.0f
, 0.0f
}},
217 {{BORDER_LEFT
, BORDER_TOP
, 0.0f
}, {0.0f
, 0.0f
}},
220 D3D11_BUFFER_DESC bd
;
221 ZeroMemory(&bd
, sizeof(bd
));
223 bd
.Usage
= D3D11_USAGE_DYNAMIC
;
224 bd
.ByteWidth
= sizeof(OurVertices
);
225 bd
.BindFlags
= D3D11_BIND_VERTEX_BUFFER
;
226 bd
.CPUAccessFlags
= D3D11_CPU_ACCESS_WRITE
;
228 ctx
->d3device
->CreateBuffer(&bd
, NULL
, &ctx
->pVertexBuffer
);
229 ctx
->vertexBufferStride
= sizeof(OurVertices
[0]);
231 D3D11_MAPPED_SUBRESOURCE ms
;
232 ctx
->d3dctx
->Map(ctx
->pVertexBuffer
, NULL
, D3D11_MAP_WRITE_DISCARD
, NULL
, &ms
);
233 memcpy(ms
.pData
, OurVertices
, sizeof(OurVertices
));
234 ctx
->d3dctx
->Unmap(ctx
->pVertexBuffer
, NULL
);
236 ctx
->quadIndexCount
= 6;
237 D3D11_BUFFER_DESC quadDesc
= { };
238 quadDesc
.Usage
= D3D11_USAGE_DYNAMIC
;
239 quadDesc
.ByteWidth
= sizeof(WORD
) * ctx
->quadIndexCount
;
240 quadDesc
.BindFlags
= D3D11_BIND_INDEX_BUFFER
;
241 quadDesc
.CPUAccessFlags
= D3D11_CPU_ACCESS_WRITE
;
242 ctx
->d3device
->CreateBuffer(&quadDesc
, NULL
, &ctx
->pIndexBuffer
);
244 ctx
->d3dctx
->Map(ctx
->pIndexBuffer
, NULL
, D3D11_MAP_WRITE_DISCARD
, NULL
, &ms
);
245 WORD
*triangle_pos
= static_cast<WORD
*>(ms
.pData
);
253 ctx
->d3dctx
->Unmap(ctx
->pIndexBuffer
, NULL
);
255 ctx
->d3dctx
->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST
);
257 ctx
->d3dctx
->IASetInputLayout(ctx
->pShadersInputLayout
);
259 ctx
->d3dctx
->IASetVertexBuffers(0, 1, &ctx
->pVertexBuffer
, &ctx
->vertexBufferStride
, &offset
);
260 ctx
->d3dctx
->IASetIndexBuffer(ctx
->pIndexBuffer
, DXGI_FORMAT_R16_UINT
, 0);
262 ctx
->d3dctx
->VSSetShader(ctx
->pVS
, 0, 0);
263 ctx
->d3dctx
->PSSetShader(ctx
->pPS
, 0, 0);
265 D3D11_SAMPLER_DESC sampDesc
;
266 ZeroMemory(&sampDesc
, sizeof(sampDesc
));
267 sampDesc
.Filter
= D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT
;
268 sampDesc
.AddressU
= D3D11_TEXTURE_ADDRESS_CLAMP
;
269 sampDesc
.AddressV
= D3D11_TEXTURE_ADDRESS_CLAMP
;
270 sampDesc
.AddressW
= D3D11_TEXTURE_ADDRESS_CLAMP
;
271 sampDesc
.ComparisonFunc
= D3D11_COMPARISON_ALWAYS
;
273 sampDesc
.MaxLOD
= D3D11_FLOAT32_MAX
;
275 hr
= ctx
->d3device
->CreateSamplerState(&sampDesc
, &ctx
->samplerState
);
276 ctx
->d3dctx
->PSSetSamplers(0, 1, &ctx
->samplerState
);
280 static void release_textures(struct render_context
*ctx
)
283 if (ctx
->resized
.sharedHandled
)
285 CloseHandle(ctx
->resized
.sharedHandled
);
286 ctx
->resized
.sharedHandled
= NULL
;
288 if (ctx
->resized
.textureVLC
)
290 ref
= ctx
->resized
.textureVLC
->Release();
291 check_leak(ref
== 0);
292 ctx
->resized
.textureVLC
= NULL
;
294 if (ctx
->resized
.textureShaderInput
)
296 ref
= ctx
->resized
.textureShaderInput
->Release();
297 check_leak(ref
== 0);
298 ctx
->resized
.textureShaderInput
= NULL
;
300 if (ctx
->resized
.textureRenderTarget
)
302 ref
= ctx
->resized
.textureRenderTarget
->Release();
303 check_leak(ref
== 0);
304 ctx
->resized
.textureRenderTarget
= NULL
;
306 if (ctx
->resized
.texture
)
308 ref
= ctx
->resized
.texture
->Release();
309 check_leak(ref
== 0);
310 ctx
->resized
.texture
= NULL
;
314 static void list_dxgi_leaks(void)
316 #ifdef DEBUG_D3D11_LEAKS
317 HMODULE dxgidebug_dll
= LoadLibrary(TEXT("DXGIDEBUG.DLL"));
320 typedef HRESULT (WINAPI
* LPDXGIGETDEBUGINTERFACE
)(REFIID
, void ** );
321 LPDXGIGETDEBUGINTERFACE pf_DXGIGetDebugInterface
;
322 pf_DXGIGetDebugInterface
= reinterpret_cast<LPDXGIGETDEBUGINTERFACE
>(
323 reinterpret_cast<void*>( GetProcAddress( dxgidebug_dll
, "DXGIGetDebugInterface" ) ) );
324 if (pf_DXGIGetDebugInterface
)
326 IDXGIDebug
*pDXGIDebug
;
327 if (SUCCEEDED(pf_DXGIGetDebugInterface(__uuidof(IDXGIDebug
), (void**)&pDXGIDebug
)))
328 pDXGIDebug
->ReportLiveObjects(DXGI_DEBUG_ALL
, DXGI_DEBUG_RLO_ALL
);
329 pDXGIDebug
->Release();
331 FreeLibrary(dxgidebug_dll
);
333 #endif // DEBUG_D3D11_LEAKS
336 static void release_direct3d(struct render_context
*ctx
)
340 release_textures(ctx
);
342 ref
= ctx
->d3dctxVLC
->Release();
343 check_leak(ref
== 0);
344 ref
= ctx
->d3deviceVLC
->Release();
345 check_leak(ref
== 0);
347 ref
= ctx
->samplerState
->Release();
348 check_leak(ref
== 0);
349 ref
= ctx
->pShadersInputLayout
->Release();
350 check_leak(ref
== 0);
351 ref
= ctx
->pVS
->Release();
352 check_leak(ref
== 0);
353 ref
= ctx
->pPS
->Release();
354 check_leak(ref
== 0);
355 ref
= ctx
->pIndexBuffer
->Release();
356 check_leak(ref
== 0);
357 ref
= ctx
->pVertexBuffer
->Release();
358 check_leak(ref
== 0);
359 ref
= ctx
->swapchain
->Release();
360 check_leak(ref
== 0);
361 ref
= ctx
->swapchainRenderTarget
->Release();
362 check_leak(ref
== 0);
363 ref
= ctx
->d3dctx
->Release();
364 check_leak(ref
== 0);
365 ref
= ctx
->d3device
->Release();
366 check_leak(ref
== 0);
371 static bool UpdateOutput_cb( void *opaque
, const libvlc_video_render_cfg_t
*cfg
, libvlc_video_output_cfg_t
*out
)
373 struct render_context
*ctx
= static_cast<struct render_context
*>( opaque
);
377 DXGI_FORMAT renderFormat
= DXGI_FORMAT_R8G8B8A8_UNORM
;
379 release_textures(ctx
);
381 /* interim texture */
382 D3D11_TEXTURE2D_DESC texDesc
= { };
383 texDesc
.MipLevels
= 1;
384 texDesc
.SampleDesc
.Count
= 1;
385 texDesc
.MiscFlags
= 0;
386 texDesc
.BindFlags
= D3D11_BIND_RENDER_TARGET
| D3D11_BIND_SHADER_RESOURCE
;
387 texDesc
.Usage
= D3D11_USAGE_DEFAULT
;
388 texDesc
.CPUAccessFlags
= 0;
389 texDesc
.ArraySize
= 1;
390 texDesc
.Format
= renderFormat
;
391 texDesc
.Height
= cfg
->height
;
392 texDesc
.Width
= cfg
->width
;
393 texDesc
.MiscFlags
= D3D11_RESOURCE_MISC_SHARED
| D3D11_RESOURCE_MISC_SHARED_NTHANDLE
;
395 hr
= ctx
->d3device
->CreateTexture2D( &texDesc
, NULL
, &ctx
->resized
.texture
);
396 if (FAILED(hr
)) return false;
398 IDXGIResource1
* sharedResource
= NULL
;
399 ctx
->resized
.texture
->QueryInterface(__uuidof(IDXGIResource1
), (LPVOID
*) &sharedResource
);
400 hr
= sharedResource
->CreateSharedHandle(NULL
, DXGI_SHARED_RESOURCE_READ
|DXGI_SHARED_RESOURCE_WRITE
, NULL
, &ctx
->resized
.sharedHandled
);
401 sharedResource
->Release();
403 ID3D11Device1
* d3d11VLC1
;
404 ctx
->d3deviceVLC
->QueryInterface(__uuidof(ID3D11Device1
), (LPVOID
*) &d3d11VLC1
);
405 hr
= d3d11VLC1
->OpenSharedResource1(ctx
->resized
.sharedHandled
, __uuidof(ID3D11Texture2D
), (void**)&ctx
->resized
.textureVLC
);
406 d3d11VLC1
->Release();
408 D3D11_SHADER_RESOURCE_VIEW_DESC resviewDesc
;
409 ZeroMemory(&resviewDesc
, sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC
));
410 resviewDesc
.ViewDimension
= D3D11_SRV_DIMENSION_TEXTURE2D
;
411 resviewDesc
.Texture2D
.MipLevels
= 1;
412 resviewDesc
.Format
= texDesc
.Format
;
413 hr
= ctx
->d3device
->CreateShaderResourceView(ctx
->resized
.texture
, &resviewDesc
, &ctx
->resized
.textureShaderInput
);
414 if (FAILED(hr
)) return false;
416 ctx
->d3dctx
->PSSetShaderResources(0, 1, &ctx
->resized
.textureShaderInput
);
418 D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc
= {
419 .Format
= texDesc
.Format
,
420 .ViewDimension
= D3D11_RTV_DIMENSION_TEXTURE2D
,
422 hr
= ctx
->d3deviceVLC
->CreateRenderTargetView(ctx
->resized
.textureVLC
, &renderTargetViewDesc
, &ctx
->resized
.textureRenderTarget
);
423 if (FAILED(hr
)) return false;
425 ctx
->d3dctxVLC
->OMSetRenderTargets( 1, &ctx
->resized
.textureRenderTarget
, NULL
);
427 out
->dxgi_format
= renderFormat
;
428 out
->full_range
= true;
429 out
->colorspace
= libvlc_video_colorspace_BT709
;
430 out
->primaries
= libvlc_video_primaries_BT709
;
431 out
->transfer
= libvlc_video_transfer_func_SRGB
;
436 static void Swap_cb( void* opaque
)
438 struct render_context
*ctx
= static_cast<struct render_context
*>( opaque
);
439 ctx
->swapchain
->Present( 0, 0 );
442 static bool StartRendering_cb( void *opaque
, bool enter
)
444 struct render_context
*ctx
= static_cast<struct render_context
*>( opaque
);
447 // DEBUG: draw greenish background to show where libvlc doesn't draw in the texture
448 // Normally you should Clear with a black background
449 static const FLOAT greenRGBA
[4] = {0.5f
, 0.5f
, 0.0f
, 1.0f
};
450 ctx
->d3dctxVLC
->ClearRenderTargetView( ctx
->resized
.textureRenderTarget
, greenRGBA
);
454 static const FLOAT orangeRGBA
[4] = {1.0f
, 0.5f
, 0.0f
, 1.0f
};
455 ctx
->d3dctx
->ClearRenderTargetView(ctx
->swapchainRenderTarget
, orangeRGBA
);
457 // Render into the swapchain
458 // We start the drawing of the shared texture in our app as early as possible
459 // in hope it's done as soon as Swap_cb is called
460 ctx
->d3dctx
->DrawIndexed(ctx
->quadIndexCount
, 0, 0);
466 static bool SelectPlane_cb( void *opaque
, size_t plane
)
468 struct render_context
*ctx
= static_cast<struct render_context
*>( opaque
);
469 if ( plane
!= 0 ) // we only support one packed RGBA plane (DXGI_FORMAT_R8G8B8A8_UNORM)
474 static bool Setup_cb( void **opaque
, const libvlc_video_setup_device_cfg_t
*cfg
, libvlc_video_setup_device_info_t
*out
)
476 struct render_context
*ctx
= static_cast<struct render_context
*>(*opaque
);
480 out
->d3d11
.device_context
= ctx
->d3dctxVLC
;
484 static void Cleanup_cb( void *opaque
)
486 // here we can release all things Direct3D11 for good (if playing only one file)
487 struct render_context
*ctx
= static_cast<struct render_context
*>( opaque
);
488 release_direct3d(ctx
);
491 static void Resize_cb( void *opaque
,
492 void (*report_size_change
)(void *report_opaque
, unsigned width
, unsigned height
),
493 void *report_opaque
)
495 struct render_context
*ctx
= static_cast<struct render_context
*>( opaque
);
496 EnterCriticalSection(&ctx
->sizeLock
);
497 ctx
->ReportSize
= report_size_change
;
498 ctx
->ReportOpaque
= report_opaque
;
500 if (ctx
->ReportSize
!= nullptr)
502 /* report our initial size */
503 ctx
->ReportSize(ctx
->ReportOpaque
, ctx
->width
, ctx
->height
);
505 LeaveCriticalSection(&ctx
->sizeLock
);
508 static const char *AspectRatio
= NULL
;
510 static LRESULT CALLBACK
WindowProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
512 if( message
== WM_CREATE
)
514 /* Store p_mp for future use */
515 CREATESTRUCT
*c
= (CREATESTRUCT
*)lParam
;
516 SetWindowLongPtr( hWnd
, GWLP_USERDATA
, (LONG_PTR
)c
->lpCreateParams
);
520 LONG_PTR p_user_data
= GetWindowLongPtr( hWnd
, GWLP_USERDATA
);
521 if( p_user_data
== 0 )
522 return DefWindowProc(hWnd
, message
, wParam
, lParam
);
523 struct render_context
*ctx
= (struct render_context
*)p_user_data
;
529 /* tell libvlc that our size has changed */
530 ctx
->width
= LOWORD(lParam
) * (BORDER_RIGHT
- BORDER_LEFT
) / 2.0f
; /* remove the orange part ! */
531 ctx
->height
= HIWORD(lParam
) * (BORDER_TOP
- BORDER_BOTTOM
) / 2.0f
;
532 EnterCriticalSection(&ctx
->sizeLock
);
533 if (ctx
->ReportSize
!= nullptr)
534 ctx
->ReportSize(ctx
->ReportOpaque
, ctx
->width
, ctx
->height
);
535 LeaveCriticalSection(&ctx
->sizeLock
);
546 int key
= tolower( (unsigned char)MapVirtualKey( wParam
, 2 ) );
549 if (AspectRatio
== NULL
)
550 AspectRatio
= "16:10";
551 else if (strcmp(AspectRatio
,"16:10")==0)
552 AspectRatio
= "16:9";
553 else if (strcmp(AspectRatio
,"16:9")==0)
555 else if (strcmp(AspectRatio
,"4:3")==0)
556 AspectRatio
= "185:100";
557 else if (strcmp(AspectRatio
,"185:100")==0)
558 AspectRatio
= "221:100";
559 else if (strcmp(AspectRatio
,"221:100")==0)
560 AspectRatio
= "235:100";
561 else if (strcmp(AspectRatio
,"235:100")==0)
562 AspectRatio
= "239:100";
563 else if (strcmp(AspectRatio
,"239:100")==0)
565 else if (strcmp(AspectRatio
,"5:3")==0)
567 else if (strcmp(AspectRatio
,"5:4")==0)
569 else if (strcmp(AspectRatio
,"1:1")==0)
571 libvlc_video_set_aspect_ratio( ctx
->p_mp
, AspectRatio
);
578 return DefWindowProc (hWnd
, message
, wParam
, lParam
);
581 int WINAPI
WinMain(HINSTANCE hInstance
,
582 HINSTANCE hPrevInstance
,
587 struct render_context Context
= { };
589 libvlc_instance_t
*p_libvlc
;
590 libvlc_media_t
*p_media
;
593 /* remove "" around the given path */
594 if (lpCmdLine
[0] == '"')
596 file_path
= strdup( lpCmdLine
+1 );
597 if (file_path
[strlen(file_path
)-1] == '"')
598 file_path
[strlen(file_path
)-1] = '\0';
601 file_path
= strdup( lpCmdLine
);
603 p_libvlc
= libvlc_new( 0, NULL
);
604 p_media
= libvlc_media_new_path( p_libvlc
, file_path
);
606 Context
.p_mp
= libvlc_media_player_new_from_media( p_media
);
608 InitializeCriticalSection(&Context
.sizeLock
);
610 ZeroMemory(&wc
, sizeof(WNDCLASSEX
));
612 wc
.cbSize
= sizeof(WNDCLASSEX
);
613 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
614 wc
.lpfnWndProc
= WindowProc
;
615 wc
.hInstance
= hInstance
;
616 wc
.hCursor
= LoadCursor(NULL
, IDC_ARROW
);
617 wc
.lpszClassName
= "WindowClass";
619 RegisterClassEx(&wc
);
621 RECT wr
= {0, 0, SCREEN_WIDTH
, SCREEN_HEIGHT
};
622 AdjustWindowRect(&wr
, WS_OVERLAPPEDWINDOW
, FALSE
);
624 Context
.hWnd
= CreateWindowEx(0,
628 CW_USEDEFAULT
, CW_USEDEFAULT
,
636 ShowWindow(Context
.hWnd
, nCmdShow
);
638 // DON'T use with callbacks libvlc_media_player_set_hwnd(p_mp, hWnd);
640 /* Tell VLC to render into our D3D11 environment */
641 libvlc_video_set_output_callbacks( Context
.p_mp
, libvlc_video_engine_d3d11
,
642 Setup_cb
, Cleanup_cb
, Resize_cb
, UpdateOutput_cb
, Swap_cb
, StartRendering_cb
,
643 nullptr, nullptr, SelectPlane_cb
,
646 libvlc_media_player_play( Context
.p_mp
);
652 if(PeekMessage(&msg
, NULL
, 0, 0, PM_REMOVE
))
654 TranslateMessage(&msg
);
655 DispatchMessage(&msg
);
657 if(msg
.message
== WM_QUIT
)
662 libvlc_media_player_stop_async( Context
.p_mp
);
664 libvlc_media_player_release( Context
.p_mp
);
665 libvlc_media_release( p_media
);
666 libvlc_release( p_libvlc
);
668 DeleteCriticalSection(&Context
.sizeLock
);