From: Conor McCarthy cmccarthy@codeweavers.com
Output frames will be transferred via render if the destination texture format differs. --- dlls/mfmediaengine/main.c | 62 +++++++++++++++++++++++- dlls/mfmediaengine/mediaengine_private.h | 1 + dlls/mfmediaengine/tests/mfmediaengine.c | 10 +--- dlls/mfmediaengine/video_frame_sink.c | 10 ++++ 4 files changed, 72 insertions(+), 11 deletions(-)
diff --git a/dlls/mfmediaengine/main.c b/dlls/mfmediaengine/main.c index 607c587aab5..9d25473ae87 100644 --- a/dlls/mfmediaengine/main.c +++ b/dlls/mfmediaengine/main.c @@ -1291,6 +1291,7 @@ static HRESULT media_engine_create_topology(struct media_engine *engine, IMFMedi IMFPresentationDescriptor *pd; IMFTopoLoader *topo_loader; DWORD stream_count = 0, i; + IMFMediaType *media_type; UINT64 duration; HRESULT hr;
@@ -1427,7 +1428,15 @@ static HRESULT media_engine_create_topology(struct media_engine *engine, IMFMedi
if (SUCCEEDED(hr) && SUCCEEDED(hr = MFCreateTopoLoader(&topo_loader))) { - hr = IMFTopoLoader_Load(topo_loader, topology, &resolved_topology, NULL); + if (FAILED(hr = IMFTopoLoader_Load(topo_loader, topology, &resolved_topology, NULL)) + && svr_node && SUCCEEDED(hr = create_video_media_type_from_fourcc(&media_type, + MFMapDXGIFormatToDX9Format(DXGI_FORMAT_B8G8R8A8_UNORM)))) + { + video_frame_sink_set_media_type(engine->presentation.frame_sink, media_type); + IMFMediaType_Release(media_type); + engine->video_frame.output_format = DXGI_FORMAT_B8G8R8A8_UNORM; + hr = IMFTopoLoader_Load(topo_loader, topology, &resolved_topology, NULL); + } IMFTopoLoader_Release(topo_loader); } if (SUCCEEDED(hr)) @@ -2529,6 +2538,53 @@ static HRESULT get_d3d11_resource_from_sample(IMFSample *sample, ID3D11Texture2D return hr; }
+static DXGI_FORMAT dxgi_format_get_typeless_format(DXGI_FORMAT format) +{ + switch (format) + { + case DXGI_FORMAT_R32G32B32A32_TYPELESS: + case DXGI_FORMAT_R32G32B32A32_FLOAT: + case DXGI_FORMAT_R32G32B32A32_UINT: + case DXGI_FORMAT_R32G32B32A32_SINT: + return DXGI_FORMAT_R32G32B32A32_TYPELESS; + + case DXGI_FORMAT_R16G16B16A16_TYPELESS: + case DXGI_FORMAT_R16G16B16A16_FLOAT: + case DXGI_FORMAT_R16G16B16A16_UNORM: + case DXGI_FORMAT_R16G16B16A16_UINT: + case DXGI_FORMAT_R16G16B16A16_SNORM: + case DXGI_FORMAT_R16G16B16A16_SINT: + return DXGI_FORMAT_R16G16B16A16_TYPELESS; + + case DXGI_FORMAT_R10G10B10A2_TYPELESS: + case DXGI_FORMAT_R10G10B10A2_UNORM: + case DXGI_FORMAT_R10G10B10A2_UINT: + return DXGI_FORMAT_R10G10B10A2_TYPELESS; + + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + case DXGI_FORMAT_R8G8B8A8_UINT: + case DXGI_FORMAT_R8G8B8A8_SNORM: + case DXGI_FORMAT_R8G8B8A8_SINT: + return DXGI_FORMAT_R8G8B8A8_TYPELESS; + + case DXGI_FORMAT_B8G8R8A8_UNORM: + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + return DXGI_FORMAT_B8G8R8A8_TYPELESS; + + case DXGI_FORMAT_B8G8R8X8_TYPELESS: + case DXGI_FORMAT_B8G8R8X8_UNORM: + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + return DXGI_FORMAT_B8G8R8X8_TYPELESS; + + default: + WARN("Unhandled format %#x.\n", format); + return format; + } +} + static BOOL transfer_needs_render_pipeline(const D3D11_TEXTURE2D_DESC *src_desc, const D3D11_TEXTURE2D_DESC *dst_desc, const D3D11_BOX *src_box, const RECT *dst_rect) { @@ -2537,7 +2593,9 @@ static BOOL transfer_needs_render_pipeline(const D3D11_TEXTURE2D_DESC *src_desc, || dst_rect->bottom - dst_rect->top != src_box->bottom - src_box->top)) return TRUE;
- return FALSE; + /* If block-compressed formats were to show up in the dst then we + * would need to also check copy-to-BC and byte count compatibility. */ + return dxgi_format_get_typeless_format(src_desc->Format) != dxgi_format_get_typeless_format(dst_desc->Format); }
static HRESULT media_engine_render_d3d11(struct media_engine *engine, ID3D11Texture2D *texture, diff --git a/dlls/mfmediaengine/mediaengine_private.h b/dlls/mfmediaengine/mediaengine_private.h index 3b280a6d1ee..095deb93147 100644 --- a/dlls/mfmediaengine/mediaengine_private.h +++ b/dlls/mfmediaengine/mediaengine_private.h @@ -22,6 +22,7 @@ struct video_frame_sink;
HRESULT create_video_frame_sink(IMFMediaType *media_type, IUnknown *device_manager, IMFAsyncCallback *events_callback, struct video_frame_sink **sink); +void video_frame_sink_set_media_type(struct video_frame_sink *sink, IMFMediaType *media_type); HRESULT video_frame_sink_query_iface(struct video_frame_sink *object, REFIID riid, void **obj); ULONG video_frame_sink_release(struct video_frame_sink *sink); int video_frame_sink_get_sample(struct video_frame_sink *sink, IMFSample **sample); diff --git a/dlls/mfmediaengine/tests/mfmediaengine.c b/dlls/mfmediaengine/tests/mfmediaengine.c index 9e0d5e16fb9..ea26024289a 100644 --- a/dlls/mfmediaengine/tests/mfmediaengine.c +++ b/dlls/mfmediaengine/tests/mfmediaengine.c @@ -1239,7 +1239,6 @@ static HRESULT WINAPI test_transfer_notify_EventNotify(IMFMediaEngineNotify *ifa break;
case MF_MEDIA_ENGINE_EVENT_ERROR: - todo_wine_if(param2 == MF_E_NO_MORE_TYPES) ok(broken(param2 == MF_E_UNSUPPORTED_BYTESTREAM_TYPE || param2 == MF_E_INVALIDMEDIATYPE), "Unexpected error %#lx\n", param2); notify->error = param2; @@ -1465,7 +1464,7 @@ static void test_TransferVideoFrame_10bit(void)
if (FAILED(notify->error)) { - skip("Media engine reported error %#lx, skipping tests.\n", notify->error); + win_skip("Media engine reported error %#lx, skipping tests.\n", notify->error); goto done; }
@@ -1504,19 +1503,12 @@ static void test_TransferVideoFrame_10bit(void) ok(!!map_desc.pData, "got pData %p\n", map_desc.pData); ok(map_desc.DepthPitch == 16384, "got DepthPitch %u\n", map_desc.DepthPitch); ok(map_desc.RowPitch == desc.Width * 4, "got RowPitch %u\n", map_desc.RowPitch); - todo_wine check_r10g10b10a2_diff(&map_desc, 32, 5, 0x3ff, 0x3ff, 0x3ff, 24); - todo_wine check_r10g10b10a2_diff(&map_desc, 32, 14, 0x3fa, 0x3ff, 0x4, 31); - todo_wine check_r10g10b10a2_diff(&map_desc, 32, 23, 0x5, 0x3ff, 0x3ff, 25); - todo_wine check_r10g10b10a2_diff(&map_desc, 32, 32, 0x1, 0x3ff, 0x6, 27); - todo_wine check_r10g10b10a2_diff(&map_desc, 32, 41, 0x3fd, 0, 0x3f7, 10); - todo_wine check_r10g10b10a2_diff(&map_desc, 32, 50, 0x3fd, 0, 0, 10); - todo_wine check_r10g10b10a2_diff(&map_desc, 32, 59, 0x2, 0, 0x3ff, 10); ID3D11DeviceContext_Unmap(context, (ID3D11Resource *)rb_texture, 0);
diff --git a/dlls/mfmediaengine/video_frame_sink.c b/dlls/mfmediaengine/video_frame_sink.c index f710466fed4..76e88b84e4b 100644 --- a/dlls/mfmediaengine/video_frame_sink.c +++ b/dlls/mfmediaengine/video_frame_sink.c @@ -1214,6 +1214,16 @@ failed: return hr; }
+void video_frame_sink_set_media_type(struct video_frame_sink *sink, IMFMediaType *media_type) +{ + IMFMediaType_Release(sink->media_type); + IMFMediaType_Release(sink->current_media_type); + sink->media_type = media_type; + IMFMediaType_AddRef(sink->media_type); + sink->current_media_type = media_type; + IMFMediaType_AddRef(sink->current_media_type); +} + HRESULT video_frame_sink_query_iface(struct video_frame_sink *sink, REFIID riid, void **obj) { return IMFStreamSink_QueryInterface(&sink->IMFStreamSink_iface, riid, obj);