Nikolay Sivov : mfreadwrite/reader: Create sample allocator for video streams.
Alexandre Julliard
julliard at winehq.org
Wed Feb 10 15:34:02 CST 2021
Module: wine
Branch: master
Commit: beb9c6578ad8e21eb4b34366dbc3dff8b8c2ae5d
URL: https://source.winehq.org/git/wine.git/?a=commit;h=beb9c6578ad8e21eb4b34366dbc3dff8b8c2ae5d
Author: Nikolay Sivov <nsivov at codeweavers.com>
Date: Wed Feb 10 13:32:30 2021 +0300
mfreadwrite/reader: Create sample allocator for video streams.
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/mfreadwrite/reader.c | 78 +++++++++++++++++++++++++++++++++-
dlls/mfreadwrite/tests/Makefile.in | 2 +-
dlls/mfreadwrite/tests/mfplat.c | 85 ++++++++++++++++++++++++++++++++++++++
3 files changed, 163 insertions(+), 2 deletions(-)
diff --git a/dlls/mfreadwrite/reader.c b/dlls/mfreadwrite/reader.c
index 86507bde5a1..6a69196054a 100644
--- a/dlls/mfreadwrite/reader.c
+++ b/dlls/mfreadwrite/reader.c
@@ -33,6 +33,9 @@
#include "mferror.h"
#include "mfidl.h"
#include "mfreadwrite.h"
+#include "d3d9.h"
+#include "initguid.h"
+#include "dxva2api.h"
#include "wine/debug.h"
#include "wine/heap.h"
@@ -108,6 +111,7 @@ struct media_stream
IMFMediaStream *stream;
IMFMediaType *current;
IMFTransform *decoder;
+ IMFVideoSampleAllocatorEx *allocator;
unsigned int id;
unsigned int index;
enum media_stream_state state;
@@ -157,6 +161,9 @@ enum source_reader_flags
SOURCE_READER_FLUSHING = 0x1,
SOURCE_READER_SEEKING = 0x2,
SOURCE_READER_SHUTDOWN_ON_RELEASE = 0x4,
+ SOURCE_READER_D3D9_DEVICE_MANAGER = 0x8,
+ SOURCE_READER_DXGI_DEVICE_MANAGER = 0x10,
+ SOURCE_READER_HAS_DEVICE_MANAGER = SOURCE_READER_D3D9_DEVICE_MANAGER | SOURCE_READER_DXGI_DEVICE_MANAGER,
};
struct source_reader
@@ -170,6 +177,7 @@ struct source_reader
IMFPresentationDescriptor *descriptor;
IMFSourceReaderCallback *async_callback;
IMFAttributes *attributes;
+ IUnknown *device_manager;
unsigned int first_audio_stream_index;
unsigned int first_video_stream_index;
unsigned int last_read_index;
@@ -1283,6 +1291,8 @@ static ULONG WINAPI src_reader_Release(IMFSourceReader *iface)
IMFMediaType_Release(stream->current);
if (stream->decoder)
IMFTransform_Release(stream->decoder);
+ if (stream->allocator)
+ IMFVideoSampleAllocatorEx_Release(stream->allocator);
}
source_reader_release_responses(reader, NULL);
heap_free(reader->streams);
@@ -1519,6 +1529,48 @@ static HRESULT source_reader_set_compatible_media_type(struct source_reader *rea
return type_set ? S_OK : S_FALSE;
}
+static HRESULT source_reader_setup_sample_allocator(struct source_reader *reader, unsigned int index,
+ IMFMediaType *media_type)
+{
+ struct media_stream *stream = &reader->streams[index];
+ GUID major = { 0 };
+ HRESULT hr;
+
+ IMFMediaType_GetMajorType(media_type, &major);
+ if (!IsEqualGUID(&major, &MFMediaType_Video))
+ return S_OK;
+
+ if (!(reader->flags & SOURCE_READER_HAS_DEVICE_MANAGER))
+ return S_OK;
+
+ if (reader->flags & SOURCE_READER_DXGI_DEVICE_MANAGER)
+ {
+ FIXME("DXGI device manager is not supported.\n");
+ return S_OK;
+ }
+
+ if (!stream->allocator)
+ {
+ if (FAILED(hr = MFCreateVideoSampleAllocatorEx(&IID_IMFVideoSampleAllocatorEx, (void **)&stream->allocator)))
+ {
+ WARN("Failed to create sample allocator, hr %#x.\n", hr);
+ return hr;
+ }
+ }
+
+ IMFVideoSampleAllocatorEx_UninitializeSampleAllocator(stream->allocator);
+ if (FAILED(hr = IMFVideoSampleAllocatorEx_SetDirectXManager(stream->allocator, reader->device_manager)))
+ {
+ WARN("Failed to set device manager, hr %#x.\n", hr);
+ return hr;
+ }
+
+ if (FAILED(hr = IMFVideoSampleAllocatorEx_InitializeSampleAllocatorEx(stream->allocator, 2, 8, NULL, media_type)))
+ WARN("Failed to initialize sample allocator, hr %#x.\n", hr);
+
+ return hr;
+}
+
static HRESULT source_reader_configure_decoder(struct source_reader *reader, DWORD index, const CLSID *clsid,
IMFMediaType *input_type, IMFMediaType *output_type)
{
@@ -1668,8 +1720,11 @@ static HRESULT WINAPI src_reader_SetCurrentMediaType(IMFSourceReader *iface, DWO
EnterCriticalSection(&reader->cs);
- if ((hr = source_reader_set_compatible_media_type(reader, index, type)) == S_FALSE)
+ hr = source_reader_set_compatible_media_type(reader, index, type);
+ if (hr == S_FALSE)
hr = source_reader_create_decoder_for_stream(reader, index, type);
+ if (SUCCEEDED(hr))
+ hr = source_reader_setup_sample_allocator(reader, index, type);
LeaveCriticalSection(&reader->cs);
@@ -2172,6 +2227,27 @@ static HRESULT create_source_reader_from_source(IMFMediaSource *source, IMFAttri
(void **)&object->async_callback);
if (object->async_callback)
TRACE("Using async callback %p.\n", object->async_callback);
+
+ IMFAttributes_GetUnknown(attributes, &MF_SOURCE_READER_D3D_MANAGER, &IID_IUnknown, (void **)&object->device_manager);
+ if (object->device_manager)
+ {
+ IUnknown *unk = NULL;
+
+ if (SUCCEEDED(IUnknown_QueryInterface(object->device_manager, &IID_IMFDXGIDeviceManager, (void **)&unk)))
+ object->flags |= SOURCE_READER_DXGI_DEVICE_MANAGER;
+ else if (SUCCEEDED(IUnknown_QueryInterface(object->device_manager, &IID_IDirect3DDeviceManager9, (void **)&unk)))
+ object->flags |= SOURCE_READER_D3D9_DEVICE_MANAGER;
+
+ if (!(object->flags & (SOURCE_READER_HAS_DEVICE_MANAGER)))
+ {
+ WARN("Unknown device manager.\n");
+ IUnknown_Release(object->device_manager);
+ object->device_manager = NULL;
+ }
+
+ if (unk)
+ IUnknown_Release(unk);
+ }
}
hr = IMFSourceReader_QueryInterface(&object->IMFSourceReader_iface, riid, out);
diff --git a/dlls/mfreadwrite/tests/Makefile.in b/dlls/mfreadwrite/tests/Makefile.in
index ae86fed95f6..c7476c14c6b 100644
--- a/dlls/mfreadwrite/tests/Makefile.in
+++ b/dlls/mfreadwrite/tests/Makefile.in
@@ -1,5 +1,5 @@
TESTDLL = mfreadwrite.dll
-IMPORTS = ole32 mfplat mfreadwrite mfuuid
+IMPORTS = ole32 user32 d3d9 dxva2 mfplat mfreadwrite mfuuid
C_SRCS = \
mfplat.c
diff --git a/dlls/mfreadwrite/tests/mfplat.c b/dlls/mfreadwrite/tests/mfplat.c
index 9d84265244a..c6191767164 100644
--- a/dlls/mfreadwrite/tests/mfplat.c
+++ b/dlls/mfreadwrite/tests/mfplat.c
@@ -37,6 +37,8 @@ DEFINE_GUID(GUID_NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
#include "mfidl.h"
#include "mferror.h"
#include "mfreadwrite.h"
+#include "d3d9.h"
+#include "dxva2api.h"
#include "wine/heap.h"
#include "wine/test.h"
@@ -48,6 +50,37 @@ static ULONG get_refcount(void *iface)
return IUnknown_Release(unknown);
}
+static HWND create_window(void)
+{
+ RECT r = {0, 0, 640, 480};
+
+ AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW | WS_VISIBLE, FALSE);
+
+ return CreateWindowA("static", "mfreadwrite_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
+ 0, 0, r.right - r.left, r.bottom - r.top, NULL, NULL, NULL, NULL);
+}
+
+static IDirect3DDevice9 *create_d3d9_device(IDirect3D9 *d3d9, HWND focus_window)
+{
+ D3DPRESENT_PARAMETERS present_parameters = {0};
+ IDirect3DDevice9 *device = NULL;
+
+ present_parameters.BackBufferWidth = 640;
+ present_parameters.BackBufferHeight = 480;
+ present_parameters.BackBufferFormat = D3DFMT_X8R8G8B8;
+ present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
+ present_parameters.hDeviceWindow = focus_window;
+ present_parameters.Windowed = TRUE;
+ present_parameters.EnableAutoDepthStencil = TRUE;
+ present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
+ present_parameters.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
+
+ IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
+ D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device);
+
+ return device;
+}
+
static HRESULT (WINAPI *pMFCreateMFByteStreamOnStream)(IStream *stream, IMFByteStream **bytestream);
static void init_functions(void)
@@ -1054,6 +1087,57 @@ static void test_source_reader_from_media_source(void)
fail_request_sample = FALSE;
}
+static void test_reader_d3d9(void)
+{
+ IDirect3DDeviceManager9 *d3d9_manager;
+ IDirect3DDevice9 *d3d9_device;
+ IMFAttributes *attributes;
+ IMFSourceReader *reader;
+ IMFMediaSource *source;
+ IDirect3D9 *d3d9;
+ HWND window;
+ HRESULT hr;
+ UINT token;
+
+ window = create_window();
+ d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
+ ok(!!d3d9, "Failed to create a D3D9 object.\n");
+ if (!(d3d9_device = create_d3d9_device(d3d9, window)))
+ {
+ skip("Failed to create a D3D9 device, skipping tests.\n");
+ goto done;
+ }
+
+ hr = DXVA2CreateDirect3DDeviceManager9(&token, &d3d9_manager);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ hr = IDirect3DDeviceManager9_ResetDevice(d3d9_manager, d3d9_device, token);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ source = create_test_source();
+ ok(!!source, "Failed to create test source.\n");
+
+ hr = MFCreateAttributes(&attributes, 1);
+ ok(hr == S_OK, "Failed to create attributes object, hr %#x.\n", hr);
+
+ hr = IMFAttributes_SetUnknown(attributes, &MF_SOURCE_READER_D3D_MANAGER, (IUnknown *)d3d9_manager);
+ ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
+
+ hr = MFCreateSourceReaderFromMediaSource(source, attributes, &reader);
+ ok(hr == S_OK, "Failed to create source reader, hr %#x.\n", hr);
+
+ IMFAttributes_Release(attributes);
+
+ IMFSourceReader_Release(reader);
+
+ IDirect3DDeviceManager9_Release(d3d9_manager);
+ IDirect3DDevice9_Release(d3d9_device);
+
+done:
+ IDirect3D9_Release(d3d9);
+ DestroyWindow(window);
+}
+
START_TEST(mfplat)
{
HRESULT hr;
@@ -1066,6 +1150,7 @@ START_TEST(mfplat)
test_factory();
test_source_reader();
test_source_reader_from_media_source();
+ test_reader_d3d9();
hr = MFShutdown();
ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
More information about the wine-cvs
mailing list