mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-11-21 16:46:54 -08:00
Rebase against 03eaa2cc93e5e2ea4c36495870c268797aea3ca8.
This commit is contained in:
parent
44f49e8001
commit
f7739e7052
@ -1,100 +0,0 @@
|
||||
From 1558eef3ca2e063c10b29796ba85f1c891170c61 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Tue, 27 Oct 2020 09:44:11 -0500
|
||||
Subject: [PATCH] mfreadwrite: Abort ReadSample when unable to request any
|
||||
samples.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/mfreadwrite/reader.c | 14 +++++++++++---
|
||||
dlls/mfreadwrite/tests/mfplat.c | 26 ++++++++++++++++++++++++++
|
||||
2 files changed, 37 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/dlls/mfreadwrite/reader.c b/dlls/mfreadwrite/reader.c
|
||||
index 96a82b798ab..7dcae5a1cfa 100644
|
||||
--- a/dlls/mfreadwrite/reader.c
|
||||
+++ b/dlls/mfreadwrite/reader.c
|
||||
@@ -439,7 +439,8 @@ static HRESULT source_reader_new_stream_handler(struct source_reader *reader, IM
|
||||
}
|
||||
|
||||
if (reader->streams[i].requests)
|
||||
- source_reader_request_sample(reader, &reader->streams[i]);
|
||||
+ if (FAILED(source_reader_request_sample(reader, &reader->streams[i])))
|
||||
+ WakeAllConditionVariable(&reader->sample_event);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1780,10 +1781,17 @@ static HRESULT source_reader_read_sample(struct source_reader *reader, DWORD ind
|
||||
stream->requests++;
|
||||
if (FAILED(hr = source_reader_request_sample(reader, stream)))
|
||||
WARN("Failed to request a sample, hr %#x.\n", hr);
|
||||
+ if (stream->stream && !(stream->flags & STREAM_FLAG_SAMPLE_REQUESTED))
|
||||
+ {
|
||||
+ *actual_index = index;
|
||||
+ *stream_flags = MF_SOURCE_READERF_ERROR;
|
||||
+ *timestamp = 0;
|
||||
+ break;
|
||||
+ }
|
||||
SleepConditionVariableCS(&reader->sample_event, &reader->cs, INFINITE);
|
||||
}
|
||||
-
|
||||
- source_reader_get_read_result(reader, stream, flags, &hr, actual_index, stream_flags,
|
||||
+ if (SUCCEEDED(hr))
|
||||
+ source_reader_get_read_result(reader, stream, flags, &hr, actual_index, stream_flags,
|
||||
timestamp, sample);
|
||||
}
|
||||
}
|
||||
diff --git a/dlls/mfreadwrite/tests/mfplat.c b/dlls/mfreadwrite/tests/mfplat.c
|
||||
index cfe68cb6736..0e5053f905f 100644
|
||||
--- a/dlls/mfreadwrite/tests/mfplat.c
|
||||
+++ b/dlls/mfreadwrite/tests/mfplat.c
|
||||
@@ -158,6 +158,8 @@ static HRESULT WINAPI test_media_stream_GetStreamDescriptor(IMFMediaStream *ifac
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
+static BOOL fail_request_sample;
|
||||
+
|
||||
static HRESULT WINAPI test_media_stream_RequestSample(IMFMediaStream *iface, IUnknown *token)
|
||||
{
|
||||
struct test_media_stream *stream = impl_from_IMFMediaStream(iface);
|
||||
@@ -165,6 +167,9 @@ static HRESULT WINAPI test_media_stream_RequestSample(IMFMediaStream *iface, IUn
|
||||
IMFSample *sample;
|
||||
HRESULT hr;
|
||||
|
||||
+ if (fail_request_sample)
|
||||
+ return E_NOTIMPL;
|
||||
+
|
||||
hr = MFCreateSample(&sample);
|
||||
ok(hr == S_OK, "Failed to create a sample, hr %#x.\n", hr);
|
||||
hr = IMFSample_SetSampleTime(sample, 123);
|
||||
@@ -977,6 +982,27 @@ static void test_source_reader_from_media_source(void)
|
||||
ok(hr == MF_E_NOTACCEPTING, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
IMFSourceReader_Release(reader);
|
||||
+ IMFMediaSource_Release(source);
|
||||
+
|
||||
+ /* RequestSample failure. */
|
||||
+ source = create_test_source();
|
||||
+ ok(!!source, "Failed to create test source.\n");
|
||||
+
|
||||
+ fail_request_sample = TRUE;
|
||||
+
|
||||
+ hr = MFCreateSourceReaderFromMediaSource(source, NULL, &reader);
|
||||
+ ok(hr == S_OK, "Failed to create source reader, hr %#x.\n", hr);
|
||||
+
|
||||
+ hr = IMFSourceReader_SetStreamSelection(reader, 0, TRUE);
|
||||
+ ok(hr == S_OK, "Failed to select a stream, hr %#x.\n", hr);
|
||||
+
|
||||
+ hr = IMFSourceReader_ReadSample(reader, 0, 0, &actual_index, &stream_flags, ×tamp, &sample);
|
||||
+ ok(hr == E_NOTIMPL, "Unexpected ReadSample result, hr %#x.\n", hr);
|
||||
+
|
||||
+ IMFSourceReader_Release(reader);
|
||||
+ IMFMediaSource_Release(source);
|
||||
+
|
||||
+ fail_request_sample = FALSE;
|
||||
}
|
||||
|
||||
START_TEST(mfplat)
|
||||
--
|
||||
2.28.0
|
||||
|
@ -1,583 +0,0 @@
|
||||
From 34618e06f5d5ca7c90fbe9b788efb5c9ef86ee50 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Tue, 24 Mar 2020 16:15:35 -0500
|
||||
Subject: [PATCH] winegstreamer: Implement IMFMediaSource::Start.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/mfplat/tests/mfplat.c | 8 +-
|
||||
dlls/winegstreamer/gst_private.h | 1 +
|
||||
dlls/winegstreamer/media_source.c | 307 +++++++++++++++++++++++++++++-
|
||||
dlls/winegstreamer/mfplat.c | 130 +++++++++++++
|
||||
4 files changed, 438 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c
|
||||
index 6a1a5bafc1a..a080035e477 100644
|
||||
--- a/dlls/mfplat/tests/mfplat.c
|
||||
+++ b/dlls/mfplat/tests/mfplat.c
|
||||
@@ -603,10 +603,7 @@ todo_wine
|
||||
|
||||
var.vt = VT_EMPTY;
|
||||
hr = IMFMediaSource_Start(mediasource, descriptor, &GUID_NULL, &var);
|
||||
-todo_wine
|
||||
ok(hr == S_OK, "Failed to start media source, hr %#x.\n", hr);
|
||||
- if (FAILED(hr))
|
||||
- goto skip_source_tests;
|
||||
|
||||
get_event((IMFMediaEventGenerator *)mediasource, MENewStream, &var);
|
||||
ok(var.vt == VT_UNKNOWN, "Unexpected value type %u from MENewStream event.\n", var.vt);
|
||||
@@ -624,10 +621,13 @@ todo_wine
|
||||
hr = IMFMediaStream_RequestSample(video_stream, NULL);
|
||||
if (i == sample_count)
|
||||
break;
|
||||
+todo_wine
|
||||
ok(hr == S_OK, "Failed to request sample %u, hr %#x.\n", i + 1, hr);
|
||||
if (hr != S_OK)
|
||||
break;
|
||||
}
|
||||
+ if (FAILED(hr))
|
||||
+ goto skip_source_tests;
|
||||
|
||||
for (i = 0; i < sample_count; ++i)
|
||||
{
|
||||
@@ -665,11 +665,11 @@ todo_wine
|
||||
|
||||
hr = IMFMediaStream_RequestSample(video_stream, NULL);
|
||||
ok(hr == MF_E_END_OF_STREAM, "Unexpected hr %#x.\n", hr);
|
||||
- IMFMediaStream_Release(video_stream);
|
||||
|
||||
get_event((IMFMediaEventGenerator *)mediasource, MEEndOfPresentation, NULL);
|
||||
|
||||
skip_source_tests:
|
||||
+ IMFMediaStream_Release(video_stream);
|
||||
IMFMediaTypeHandler_Release(handler);
|
||||
IMFPresentationDescriptor_Release(descriptor);
|
||||
|
||||
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
|
||||
index 57d40d19a89..3a8020b6760 100644
|
||||
--- a/dlls/winegstreamer/gst_private.h
|
||||
+++ b/dlls/winegstreamer/gst_private.h
|
||||
@@ -79,6 +79,7 @@ extern HRESULT mfplat_get_class_object(REFCLSID rclsid, REFIID riid, void **obj)
|
||||
|
||||
HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj) DECLSPEC_HIDDEN;
|
||||
IMFMediaType *mf_media_type_from_caps(const GstCaps *caps) DECLSPEC_HIDDEN;
|
||||
+GstCaps *caps_from_mf_media_type(IMFMediaType *type) DECLSPEC_HIDDEN;
|
||||
|
||||
HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj) DECLSPEC_HIDDEN;
|
||||
|
||||
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
|
||||
index 9b2c2174318..9c6e7bfd539 100644
|
||||
--- a/dlls/winegstreamer/media_source.c
|
||||
+++ b/dlls/winegstreamer/media_source.c
|
||||
@@ -55,14 +55,38 @@ struct media_stream
|
||||
{
|
||||
STREAM_INACTIVE,
|
||||
STREAM_SHUTDOWN,
|
||||
+ STREAM_RUNNING,
|
||||
} state;
|
||||
DWORD stream_id;
|
||||
};
|
||||
|
||||
+enum source_async_op
|
||||
+{
|
||||
+ SOURCE_ASYNC_START,
|
||||
+};
|
||||
+
|
||||
+struct source_async_command
|
||||
+{
|
||||
+ IUnknown IUnknown_iface;
|
||||
+ LONG refcount;
|
||||
+ enum source_async_op op;
|
||||
+ union
|
||||
+ {
|
||||
+ struct
|
||||
+ {
|
||||
+ IMFPresentationDescriptor *descriptor;
|
||||
+ GUID format;
|
||||
+ PROPVARIANT position;
|
||||
+ } start;
|
||||
+ } u;
|
||||
+};
|
||||
+
|
||||
struct media_source
|
||||
{
|
||||
IMFMediaSource IMFMediaSource_iface;
|
||||
+ IMFAsyncCallback async_commands_callback;
|
||||
LONG ref;
|
||||
+ DWORD async_commands_queue;
|
||||
IMFMediaEventQueue *event_queue;
|
||||
IMFByteStream *byte_stream;
|
||||
struct media_stream **streams;
|
||||
@@ -76,6 +100,7 @@ struct media_source
|
||||
{
|
||||
SOURCE_OPENING,
|
||||
SOURCE_STOPPED,
|
||||
+ SOURCE_RUNNING,
|
||||
SOURCE_SHUTDOWN,
|
||||
} state;
|
||||
HANDLE no_more_pads_event;
|
||||
@@ -91,7 +116,260 @@ static inline struct media_source *impl_from_IMFMediaSource(IMFMediaSource *ifac
|
||||
return CONTAINING_RECORD(iface, struct media_source, IMFMediaSource_iface);
|
||||
}
|
||||
|
||||
-static GstFlowReturn bytestream_wrapper_pull(GstPad *pad, GstObject *parent, guint64 ofs, guint len,
|
||||
+static inline struct media_source *impl_from_async_commands_callback_IMFAsyncCallback(IMFAsyncCallback *iface)
|
||||
+{
|
||||
+ return CONTAINING_RECORD(iface, struct media_source, async_commands_callback);
|
||||
+}
|
||||
+
|
||||
+static inline struct source_async_command *impl_from_async_command_IUnknown(IUnknown *iface)
|
||||
+{
|
||||
+ return CONTAINING_RECORD(iface, struct source_async_command, IUnknown_iface);
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI source_async_command_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
|
||||
+{
|
||||
+ if (IsEqualIID(riid, &IID_IUnknown))
|
||||
+ {
|
||||
+ *obj = iface;
|
||||
+ IUnknown_AddRef(iface);
|
||||
+ return S_OK;
|
||||
+ }
|
||||
+
|
||||
+ WARN("Unsupported interface %s.\n", debugstr_guid(riid));
|
||||
+ *obj = NULL;
|
||||
+ return E_NOINTERFACE;
|
||||
+}
|
||||
+
|
||||
+static ULONG WINAPI source_async_command_AddRef(IUnknown *iface)
|
||||
+{
|
||||
+ struct source_async_command *command = impl_from_async_command_IUnknown(iface);
|
||||
+ return InterlockedIncrement(&command->refcount);
|
||||
+}
|
||||
+
|
||||
+static ULONG WINAPI source_async_command_Release(IUnknown *iface)
|
||||
+{
|
||||
+ struct source_async_command *command = impl_from_async_command_IUnknown(iface);
|
||||
+ ULONG refcount = InterlockedDecrement(&command->refcount);
|
||||
+
|
||||
+ if (!refcount)
|
||||
+ {
|
||||
+ if (command->op == SOURCE_ASYNC_START)
|
||||
+ PropVariantClear(&command->u.start.position);
|
||||
+ heap_free(command);
|
||||
+ }
|
||||
+
|
||||
+ return refcount;
|
||||
+}
|
||||
+
|
||||
+static const IUnknownVtbl source_async_command_vtbl =
|
||||
+{
|
||||
+ source_async_command_QueryInterface,
|
||||
+ source_async_command_AddRef,
|
||||
+ source_async_command_Release,
|
||||
+};
|
||||
+
|
||||
+static HRESULT source_create_async_op(enum source_async_op op, struct source_async_command **ret)
|
||||
+{
|
||||
+ struct source_async_command *command;
|
||||
+
|
||||
+ if (!(command = heap_alloc_zero(sizeof(*command))))
|
||||
+ return E_OUTOFMEMORY;
|
||||
+
|
||||
+ command->IUnknown_iface.lpVtbl = &source_async_command_vtbl;
|
||||
+ command->op = op;
|
||||
+
|
||||
+ *ret = command;
|
||||
+
|
||||
+ return S_OK;
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI callback_QueryInterface(IMFAsyncCallback *iface, REFIID riid, void **obj)
|
||||
+{
|
||||
+ TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
|
||||
+
|
||||
+ if (IsEqualIID(riid, &IID_IMFAsyncCallback) ||
|
||||
+ IsEqualIID(riid, &IID_IUnknown))
|
||||
+ {
|
||||
+ *obj = iface;
|
||||
+ IMFAsyncCallback_AddRef(iface);
|
||||
+ return S_OK;
|
||||
+ }
|
||||
+
|
||||
+ WARN("Unsupported %s.\n", debugstr_guid(riid));
|
||||
+ *obj = NULL;
|
||||
+ return E_NOINTERFACE;
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI callback_GetParameters(IMFAsyncCallback *iface,
|
||||
+ DWORD *flags, DWORD *queue)
|
||||
+{
|
||||
+ return E_NOTIMPL;
|
||||
+}
|
||||
+
|
||||
+static ULONG WINAPI source_async_commands_callback_AddRef(IMFAsyncCallback *iface)
|
||||
+{
|
||||
+ struct media_source *source = impl_from_async_commands_callback_IMFAsyncCallback(iface);
|
||||
+ return IMFMediaSource_AddRef(&source->IMFMediaSource_iface);
|
||||
+}
|
||||
+
|
||||
+static ULONG WINAPI source_async_commands_callback_Release(IMFAsyncCallback *iface)
|
||||
+{
|
||||
+ struct media_source *source = impl_from_async_commands_callback_IMFAsyncCallback(iface);
|
||||
+ return IMFMediaSource_Release(&source->IMFMediaSource_iface);
|
||||
+}
|
||||
+
|
||||
+static IMFStreamDescriptor *stream_descriptor_from_id(IMFPresentationDescriptor *pres_desc, DWORD id, BOOL *selected)
|
||||
+{
|
||||
+ ULONG sd_count;
|
||||
+ IMFStreamDescriptor *ret;
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ if (FAILED(IMFPresentationDescriptor_GetStreamDescriptorCount(pres_desc, &sd_count)))
|
||||
+ return NULL;
|
||||
+
|
||||
+ for (i = 0; i < sd_count; i++)
|
||||
+ {
|
||||
+ DWORD stream_id;
|
||||
+
|
||||
+ if (FAILED(IMFPresentationDescriptor_GetStreamDescriptorByIndex(pres_desc, i, selected, &ret)))
|
||||
+ return NULL;
|
||||
+
|
||||
+ if (SUCCEEDED(IMFStreamDescriptor_GetStreamIdentifier(ret, &stream_id)) && stream_id == id)
|
||||
+ return ret;
|
||||
+
|
||||
+ IMFStreamDescriptor_Release(ret);
|
||||
+ }
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+static void start_pipeline(struct media_source *source, struct source_async_command *command)
|
||||
+{
|
||||
+ PROPVARIANT *position = &command->u.start.position;
|
||||
+ BOOL seek_message = source->state != SOURCE_STOPPED && position->vt != VT_EMPTY;
|
||||
+ GstStateChangeReturn ret;
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ gst_element_set_state(source->container, GST_STATE_PAUSED);
|
||||
+ ret = gst_element_get_state(source->container, NULL, NULL, -1);
|
||||
+ assert(ret == GST_STATE_CHANGE_SUCCESS);
|
||||
+
|
||||
+ /* seek to beginning on stop->play */
|
||||
+ if (source->state == SOURCE_STOPPED && position->vt == VT_EMPTY)
|
||||
+ {
|
||||
+ position->vt = VT_I8;
|
||||
+ position->u.hVal.QuadPart = 0;
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < source->stream_count; i++)
|
||||
+ {
|
||||
+ struct media_stream *stream;
|
||||
+ IMFStreamDescriptor *sd;
|
||||
+ IMFMediaTypeHandler *mth;
|
||||
+ IMFMediaType *current_mt;
|
||||
+ GstCaps *current_caps;
|
||||
+ GstCaps *prev_caps;
|
||||
+ DWORD stream_id;
|
||||
+ BOOL was_active;
|
||||
+ BOOL selected;
|
||||
+
|
||||
+ stream = source->streams[i];
|
||||
+
|
||||
+ IMFStreamDescriptor_GetStreamIdentifier(stream->descriptor, &stream_id);
|
||||
+
|
||||
+ sd = stream_descriptor_from_id(command->u.start.descriptor, stream_id, &selected);
|
||||
+ IMFStreamDescriptor_Release(sd);
|
||||
+
|
||||
+ was_active = stream->state != STREAM_INACTIVE;
|
||||
+
|
||||
+ stream->state = selected ? STREAM_RUNNING : STREAM_INACTIVE;
|
||||
+
|
||||
+ if (selected)
|
||||
+ {
|
||||
+ IMFStreamDescriptor_GetMediaTypeHandler(stream->descriptor, &mth);
|
||||
+ IMFMediaTypeHandler_GetCurrentMediaType(mth, ¤t_mt);
|
||||
+ current_caps = caps_from_mf_media_type(current_mt);
|
||||
+ g_object_get(stream->appsink, "caps", &prev_caps, NULL);
|
||||
+ if (!prev_caps || !gst_caps_is_equal(prev_caps, current_caps))
|
||||
+ {
|
||||
+ GstEvent *reconfigure_event = gst_event_new_reconfigure();
|
||||
+ g_object_set(stream->appsink, "caps", current_caps, NULL);
|
||||
+ gst_pad_push_event(gst_element_get_static_pad(stream->appsink, "sink"), reconfigure_event);
|
||||
+ }
|
||||
+
|
||||
+ gst_caps_unref(current_caps);
|
||||
+ if (prev_caps)
|
||||
+ gst_caps_unref(prev_caps);
|
||||
+ IMFMediaType_Release(current_mt);
|
||||
+ IMFMediaTypeHandler_Release(mth);
|
||||
+ }
|
||||
+
|
||||
+ g_object_set(stream->appsink, "drop", !selected, NULL);
|
||||
+
|
||||
+ if (position->vt != VT_EMPTY)
|
||||
+ {
|
||||
+ GstEvent *seek_event = gst_event_new_seek(1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH,
|
||||
+ GST_SEEK_TYPE_SET, position->u.hVal.QuadPart / 100, GST_SEEK_TYPE_NONE, 0);
|
||||
+
|
||||
+ gst_pad_push_event(stream->my_sink, seek_event);
|
||||
+ }
|
||||
+
|
||||
+ if (selected)
|
||||
+ {
|
||||
+ TRACE("Stream %u (%p) selected\n", i, stream);
|
||||
+ IMFMediaEventQueue_QueueEventParamUnk(source->event_queue,
|
||||
+ was_active ? MEUpdatedStream : MENewStream, &GUID_NULL,
|
||||
+ S_OK, (IUnknown*) &stream->IMFMediaStream_iface);
|
||||
+
|
||||
+ IMFMediaEventQueue_QueueEventParamVar(stream->event_queue,
|
||||
+ seek_message ? MEStreamSeeked : MEStreamStarted, &GUID_NULL, S_OK, position);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ IMFMediaEventQueue_QueueEventParamVar(source->event_queue,
|
||||
+ seek_message ? MESourceSeeked : MESourceStarted,
|
||||
+ &GUID_NULL, S_OK, position);
|
||||
+
|
||||
+ source->state = SOURCE_RUNNING;
|
||||
+
|
||||
+ gst_element_set_state(source->container, GST_STATE_PLAYING);
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI source_async_commands_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result)
|
||||
+{
|
||||
+ struct media_source *source = impl_from_async_commands_callback_IMFAsyncCallback(iface);
|
||||
+ struct source_async_command *command;
|
||||
+ IUnknown *state;
|
||||
+ HRESULT hr;
|
||||
+
|
||||
+ if (source->state == SOURCE_SHUTDOWN)
|
||||
+ return S_OK;
|
||||
+
|
||||
+ if (FAILED(hr = IMFAsyncResult_GetState(result, &state)))
|
||||
+ return hr;
|
||||
+
|
||||
+ command = impl_from_async_command_IUnknown(state);
|
||||
+ switch (command->op)
|
||||
+ {
|
||||
+ case SOURCE_ASYNC_START:
|
||||
+ start_pipeline(source, command);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ IUnknown_Release(state);
|
||||
+
|
||||
+ return S_OK;
|
||||
+}
|
||||
+
|
||||
+static const IMFAsyncCallbackVtbl source_async_commands_callback_vtbl =
|
||||
+{
|
||||
+ callback_QueryInterface,
|
||||
+ source_async_commands_callback_AddRef,
|
||||
+ source_async_commands_callback_Release,
|
||||
+ callback_GetParameters,
|
||||
+ source_async_commands_Invoke,
|
||||
+};
|
||||
+
|
||||
+GstFlowReturn bytestream_wrapper_pull(GstPad *pad, GstObject *parent, guint64 ofs, guint len,
|
||||
GstBuffer **buf)
|
||||
{
|
||||
struct media_source *source = gst_pad_get_element_private(pad);
|
||||
@@ -683,16 +961,30 @@ static HRESULT WINAPI media_source_CreatePresentationDescriptor(IMFMediaSource *
|
||||
}
|
||||
|
||||
static HRESULT WINAPI media_source_Start(IMFMediaSource *iface, IMFPresentationDescriptor *descriptor,
|
||||
- const GUID *time_format, const PROPVARIANT *start_position)
|
||||
+ const GUID *time_format, const PROPVARIANT *position)
|
||||
{
|
||||
struct media_source *source = impl_from_IMFMediaSource(iface);
|
||||
+ struct source_async_command *command;
|
||||
+ HRESULT hr;
|
||||
|
||||
- FIXME("(%p)->(%p, %p, %p): stub\n", source, descriptor, time_format, start_position);
|
||||
+ TRACE("(%p)->(%p, %p, %p)\n", source, descriptor, time_format, position);
|
||||
|
||||
if (source->state == SOURCE_SHUTDOWN)
|
||||
return MF_E_SHUTDOWN;
|
||||
|
||||
- return E_NOTIMPL;
|
||||
+ if (!(IsEqualIID(time_format, &GUID_NULL)))
|
||||
+ return MF_E_UNSUPPORTED_TIME_FORMAT;
|
||||
+
|
||||
+ if (SUCCEEDED(hr = source_create_async_op(SOURCE_ASYNC_START, &command)))
|
||||
+ {
|
||||
+ command->u.start.descriptor = descriptor;
|
||||
+ command->u.start.format = *time_format;
|
||||
+ PropVariantCopy(&command->u.start.position, position);
|
||||
+
|
||||
+ hr = MFPutWorkItem(source->async_commands_queue, &source->async_commands_callback, &command->IUnknown_iface);
|
||||
+ }
|
||||
+
|
||||
+ return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI media_source_Stop(IMFMediaSource *iface)
|
||||
@@ -773,6 +1065,9 @@ static HRESULT WINAPI media_source_Shutdown(IMFMediaSource *iface)
|
||||
if (source->no_more_pads_event)
|
||||
CloseHandle(source->no_more_pads_event);
|
||||
|
||||
+ if (source->async_commands_queue)
|
||||
+ MFUnlockWorkQueue(source->async_commands_queue);
|
||||
+
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -853,6 +1148,7 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
object->IMFMediaSource_iface.lpVtbl = &IMFMediaSource_vtbl;
|
||||
+ object->async_commands_callback.lpVtbl = &source_async_commands_callback_vtbl;
|
||||
object->ref = 1;
|
||||
object->byte_stream = bytestream;
|
||||
IMFByteStream_AddRef(bytestream);
|
||||
@@ -861,6 +1157,9 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
|
||||
if (FAILED(hr = MFCreateEventQueue(&object->event_queue)))
|
||||
goto fail;
|
||||
|
||||
+ if (FAILED(hr = MFAllocateWorkQueue(&object->async_commands_queue)))
|
||||
+ goto fail;
|
||||
+
|
||||
object->container = gst_bin_new(NULL);
|
||||
object->bus = gst_bus_new();
|
||||
gst_bus_set_sync_handler(object->bus, mf_src_bus_watch_wrapper, object, NULL);
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index 2e8b0978648..46bbb2ac2b1 100644
|
||||
--- a/dlls/winegstreamer/mfplat.c
|
||||
+++ b/dlls/winegstreamer/mfplat.c
|
||||
@@ -601,3 +601,133 @@ IMFMediaType *mf_media_type_from_caps(const GstCaps *caps)
|
||||
|
||||
return media_type;
|
||||
}
|
||||
+
|
||||
+GstCaps *caps_from_mf_media_type(IMFMediaType *type)
|
||||
+{
|
||||
+ GUID major_type;
|
||||
+ GUID subtype;
|
||||
+ GstCaps *output = NULL;
|
||||
+
|
||||
+ if (FAILED(IMFMediaType_GetMajorType(type, &major_type)))
|
||||
+ return NULL;
|
||||
+ if (FAILED(IMFMediaType_GetGUID(type, &MF_MT_SUBTYPE, &subtype)))
|
||||
+ return NULL;
|
||||
+
|
||||
+ if (IsEqualGUID(&major_type, &MFMediaType_Video))
|
||||
+ {
|
||||
+ UINT64 frame_rate = 0, frame_size = 0;
|
||||
+ DWORD width, height;
|
||||
+ GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
|
||||
+ GUID subtype_base;
|
||||
+ GstVideoInfo info;
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ if (FAILED(IMFMediaType_GetUINT64(type, &MF_MT_FRAME_SIZE, &frame_size)))
|
||||
+ return NULL;
|
||||
+ width = frame_size >> 32;
|
||||
+ height = frame_size;
|
||||
+
|
||||
+ output = gst_caps_new_empty_simple("video/x-raw");
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(uncompressed_video_formats); i++)
|
||||
+ {
|
||||
+ if (IsEqualGUID(uncompressed_video_formats[i].subtype, &subtype))
|
||||
+ {
|
||||
+ format = uncompressed_video_formats[i].format;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ subtype_base = subtype;
|
||||
+ subtype_base.Data1 = 0;
|
||||
+ if (format == GST_VIDEO_FORMAT_UNKNOWN && IsEqualGUID(&MFVideoFormat_Base, &subtype_base))
|
||||
+ format = gst_video_format_from_fourcc(subtype.Data1);
|
||||
+
|
||||
+ if (format == GST_VIDEO_FORMAT_UNKNOWN)
|
||||
+ {
|
||||
+ FIXME("Unrecognized format %s\n", debugstr_guid(&subtype));
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ gst_video_info_set_format(&info, format, width, height);
|
||||
+ output = gst_video_info_to_caps(&info);
|
||||
+
|
||||
+ if (frame_size)
|
||||
+ {
|
||||
+ gst_caps_set_simple(output, "width", G_TYPE_INT, width, NULL);
|
||||
+ gst_caps_set_simple(output, "height", G_TYPE_INT, height, NULL);
|
||||
+ }
|
||||
+ if (SUCCEEDED(IMFMediaType_GetUINT64(type, &MF_MT_FRAME_RATE, &frame_rate)))
|
||||
+ {
|
||||
+ /* Darksiders: Warmastered Edition uses a MF_MT_FRAME_RATE of 0,
|
||||
+ and gstreamer won't accept an undefined number as the framerate. */
|
||||
+ if (!(DWORD32)frame_rate)
|
||||
+ frame_rate = 1;
|
||||
+ gst_caps_set_simple(output, "framerate", GST_TYPE_FRACTION, frame_rate >> 32, (DWORD32) frame_rate, NULL);
|
||||
+ }
|
||||
+ return output;
|
||||
+ }
|
||||
+ else if (IsEqualGUID(&major_type, &MFMediaType_Audio))
|
||||
+ {
|
||||
+ DWORD rate, channels, channel_mask, bitrate;
|
||||
+
|
||||
+ if (IsEqualGUID(&subtype, &MFAudioFormat_Float))
|
||||
+ {
|
||||
+ output = gst_caps_new_empty_simple("audio/x-raw");
|
||||
+
|
||||
+ gst_caps_set_simple(output, "format", G_TYPE_STRING, "F32LE", NULL);
|
||||
+ gst_caps_set_simple(output, "layout", G_TYPE_STRING, "interleaved", NULL);
|
||||
+ }
|
||||
+ else if (IsEqualGUID(&subtype, &MFAudioFormat_PCM))
|
||||
+ {
|
||||
+ DWORD bits_per_sample;
|
||||
+
|
||||
+ if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_BITS_PER_SAMPLE, &bits_per_sample)))
|
||||
+ {
|
||||
+ char format[6];
|
||||
+ char type;
|
||||
+
|
||||
+ type = bits_per_sample > 8 ? 'S' : 'U';
|
||||
+
|
||||
+ output = gst_caps_new_empty_simple("audio/x-raw");
|
||||
+
|
||||
+ sprintf(format, "%c%u%s", type, bits_per_sample, bits_per_sample > 8 ? "LE" : "");
|
||||
+
|
||||
+ gst_caps_set_simple(output, "format", G_TYPE_STRING, format, NULL);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ ERR("Bits per sample not set.\n");
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ FIXME("Unrecognized subtype %s\n", debugstr_guid(&subtype));
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &rate)))
|
||||
+ {
|
||||
+ gst_caps_set_simple(output, "rate", G_TYPE_INT, rate, NULL);
|
||||
+ }
|
||||
+ if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_NUM_CHANNELS, &channels)))
|
||||
+ {
|
||||
+ gst_caps_set_simple(output, "channels", G_TYPE_INT, channels, NULL);
|
||||
+ }
|
||||
+ if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_CHANNEL_MASK, &channel_mask)))
|
||||
+ {
|
||||
+ gst_caps_set_simple(output, "channel-mask", GST_TYPE_BITMASK, (guint64) channel_mask, NULL);
|
||||
+ }
|
||||
+
|
||||
+ if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_AVG_BITRATE, &bitrate)))
|
||||
+ {
|
||||
+ gst_caps_set_simple(output, "bitrate", G_TYPE_INT, bitrate, NULL);
|
||||
+ }
|
||||
+
|
||||
+ return output;
|
||||
+ }
|
||||
+
|
||||
+ FIXME("Unrecognized major type %s\n", debugstr_guid(&major_type));
|
||||
+ return NULL;
|
||||
+}
|
||||
--
|
||||
2.28.0
|
||||
|
@ -1,312 +0,0 @@
|
||||
From 28b1e11eb783b9bf8643209023723cf81e2be941 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Thu, 8 Oct 2020 16:39:53 -0500
|
||||
Subject: [PATCH] winegstreamer: Implement IMFMediaStream::RequestSample.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/mfplat/tests/mfplat.c | 4 --
|
||||
dlls/mfreadwrite/tests/mfplat.c | 4 +-
|
||||
dlls/winegstreamer/gst_private.h | 1 +
|
||||
dlls/winegstreamer/media_source.c | 92 ++++++++++++++++++++++++++++++-
|
||||
dlls/winegstreamer/mfplat.c | 69 +++++++++++++++++++++++
|
||||
5 files changed, 164 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c
|
||||
index a080035e477..8f9fb3faff3 100644
|
||||
--- a/dlls/mfplat/tests/mfplat.c
|
||||
+++ b/dlls/mfplat/tests/mfplat.c
|
||||
@@ -621,13 +621,10 @@ todo_wine
|
||||
hr = IMFMediaStream_RequestSample(video_stream, NULL);
|
||||
if (i == sample_count)
|
||||
break;
|
||||
-todo_wine
|
||||
ok(hr == S_OK, "Failed to request sample %u, hr %#x.\n", i + 1, hr);
|
||||
if (hr != S_OK)
|
||||
break;
|
||||
}
|
||||
- if (FAILED(hr))
|
||||
- goto skip_source_tests;
|
||||
|
||||
for (i = 0; i < sample_count; ++i)
|
||||
{
|
||||
@@ -668,7 +665,6 @@ todo_wine
|
||||
|
||||
get_event((IMFMediaEventGenerator *)mediasource, MEEndOfPresentation, NULL);
|
||||
|
||||
-skip_source_tests:
|
||||
IMFMediaStream_Release(video_stream);
|
||||
IMFMediaTypeHandler_Release(handler);
|
||||
IMFPresentationDescriptor_Release(descriptor);
|
||||
diff --git a/dlls/mfreadwrite/tests/mfplat.c b/dlls/mfreadwrite/tests/mfplat.c
|
||||
index 0e5053f905f..ba457181a61 100644
|
||||
--- a/dlls/mfreadwrite/tests/mfplat.c
|
||||
+++ b/dlls/mfreadwrite/tests/mfplat.c
|
||||
@@ -727,7 +727,6 @@ static void test_source_reader(void)
|
||||
|
||||
hr = IMFSourceReader_ReadSample(reader, MF_SOURCE_READER_FIRST_AUDIO_STREAM, 0, &actual_index, &stream_flags,
|
||||
×tamp, &sample);
|
||||
-todo_wine
|
||||
ok(hr == S_OK, "Failed to get a sample, hr %#x.\n", hr);
|
||||
if (hr != S_OK)
|
||||
goto skip_read_sample;
|
||||
@@ -753,8 +752,11 @@ todo_wine
|
||||
×tamp, &sample);
|
||||
ok(hr == S_OK, "Failed to get a sample, hr %#x.\n", hr);
|
||||
ok(actual_index == 0, "Unexpected stream index %u\n", actual_index);
|
||||
+todo_wine
|
||||
+{
|
||||
ok(stream_flags == MF_SOURCE_READERF_ENDOFSTREAM, "Unexpected stream flags %#x.\n", stream_flags);
|
||||
ok(!sample, "Unexpected sample object.\n");
|
||||
+}
|
||||
|
||||
hr = IMFSourceReader_ReadSample(reader, MF_SOURCE_READER_FIRST_AUDIO_STREAM, MF_SOURCE_READER_CONTROLF_DRAIN,
|
||||
&actual_index, &stream_flags, ×tamp, &sample);
|
||||
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
|
||||
index 3a8020b6760..28e424439d8 100644
|
||||
--- a/dlls/winegstreamer/gst_private.h
|
||||
+++ b/dlls/winegstreamer/gst_private.h
|
||||
@@ -80,6 +80,7 @@ extern HRESULT mfplat_get_class_object(REFCLSID rclsid, REFIID riid, void **obj)
|
||||
HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj) DECLSPEC_HIDDEN;
|
||||
IMFMediaType *mf_media_type_from_caps(const GstCaps *caps) DECLSPEC_HIDDEN;
|
||||
GstCaps *caps_from_mf_media_type(IMFMediaType *type) DECLSPEC_HIDDEN;
|
||||
+IMFSample *mf_sample_from_gst_buffer(GstBuffer *in) DECLSPEC_HIDDEN;
|
||||
|
||||
HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj) DECLSPEC_HIDDEN;
|
||||
|
||||
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
|
||||
index 9c6e7bfd539..ef694bf194a 100644
|
||||
--- a/dlls/winegstreamer/media_source.c
|
||||
+++ b/dlls/winegstreamer/media_source.c
|
||||
@@ -58,11 +58,13 @@ struct media_stream
|
||||
STREAM_RUNNING,
|
||||
} state;
|
||||
DWORD stream_id;
|
||||
+ BOOL eos;
|
||||
};
|
||||
|
||||
enum source_async_op
|
||||
{
|
||||
SOURCE_ASYNC_START,
|
||||
+ SOURCE_ASYNC_REQUEST_SAMPLE,
|
||||
};
|
||||
|
||||
struct source_async_command
|
||||
@@ -78,6 +80,11 @@ struct source_async_command
|
||||
GUID format;
|
||||
PROPVARIANT position;
|
||||
} start;
|
||||
+ struct
|
||||
+ {
|
||||
+ struct media_stream *stream;
|
||||
+ IUnknown *token;
|
||||
+ } request_sample;
|
||||
} u;
|
||||
};
|
||||
|
||||
@@ -311,6 +318,8 @@ static void start_pipeline(struct media_source *source, struct source_async_comm
|
||||
GST_SEEK_TYPE_SET, position->u.hVal.QuadPart / 100, GST_SEEK_TYPE_NONE, 0);
|
||||
|
||||
gst_pad_push_event(stream->my_sink, seek_event);
|
||||
+
|
||||
+ stream->eos = FALSE;
|
||||
}
|
||||
|
||||
if (selected)
|
||||
@@ -334,6 +343,59 @@ static void start_pipeline(struct media_source *source, struct source_async_comm
|
||||
gst_element_set_state(source->container, GST_STATE_PLAYING);
|
||||
}
|
||||
|
||||
+static void dispatch_end_of_presentation(struct media_source *source)
|
||||
+{
|
||||
+ PROPVARIANT empty = {.vt = VT_EMPTY};
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ /* A stream has ended, check whether all have */
|
||||
+ for (i = 0; i < source->stream_count; i++)
|
||||
+ {
|
||||
+ struct media_stream *stream = source->streams[i];
|
||||
+
|
||||
+ if (stream->state != STREAM_INACTIVE && !stream->eos)
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ IMFMediaEventQueue_QueueEventParamVar(source->event_queue, MEEndOfPresentation, &GUID_NULL, S_OK, &empty);
|
||||
+}
|
||||
+
|
||||
+static void wait_on_sample(struct media_stream *stream, IUnknown *token)
|
||||
+{
|
||||
+ PROPVARIANT empty_var = {.vt = VT_EMPTY};
|
||||
+ GstSample *gst_sample;
|
||||
+ GstBuffer *buffer;
|
||||
+ IMFSample *sample;
|
||||
+
|
||||
+ TRACE("%p, %p\n", stream, token);
|
||||
+
|
||||
+ g_signal_emit_by_name(stream->appsink, "pull-sample", &gst_sample);
|
||||
+ if (gst_sample)
|
||||
+ {
|
||||
+ buffer = gst_sample_get_buffer(gst_sample);
|
||||
+
|
||||
+ TRACE("PTS = %llu\n", (unsigned long long int) GST_BUFFER_PTS(buffer));
|
||||
+
|
||||
+ sample = mf_sample_from_gst_buffer(buffer);
|
||||
+ gst_sample_unref(gst_sample);
|
||||
+
|
||||
+ if (token)
|
||||
+ IMFSample_SetUnknown(sample, &MFSampleExtension_Token, token);
|
||||
+
|
||||
+ IMFMediaEventQueue_QueueEventParamUnk(stream->event_queue, MEMediaSample, &GUID_NULL, S_OK, (IUnknown *)sample);
|
||||
+ IMFSample_Release(sample);
|
||||
+ }
|
||||
+
|
||||
+ g_object_get(stream->appsink, "eos", &stream->eos, NULL);
|
||||
+ if (stream->eos)
|
||||
+ {
|
||||
+ if (token)
|
||||
+ IUnknown_Release(token);
|
||||
+ IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEEndOfStream, &GUID_NULL, S_OK, &empty_var);
|
||||
+ dispatch_end_of_presentation(stream->parent_source);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static HRESULT WINAPI source_async_commands_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result)
|
||||
{
|
||||
struct media_source *source = impl_from_async_commands_callback_IMFAsyncCallback(iface);
|
||||
@@ -353,6 +415,9 @@ static HRESULT WINAPI source_async_commands_Invoke(IMFAsyncCallback *iface, IMFA
|
||||
case SOURCE_ASYNC_START:
|
||||
start_pipeline(source, command);
|
||||
break;
|
||||
+ case SOURCE_ASYNC_REQUEST_SAMPLE:
|
||||
+ wait_on_sample(command->u.request_sample.stream, command->u.request_sample.token);
|
||||
+ break;
|
||||
}
|
||||
|
||||
IUnknown_Release(state);
|
||||
@@ -640,13 +705,37 @@ static HRESULT WINAPI media_stream_GetStreamDescriptor(IMFMediaStream* iface, IM
|
||||
static HRESULT WINAPI media_stream_RequestSample(IMFMediaStream *iface, IUnknown *token)
|
||||
{
|
||||
struct media_stream *stream = impl_from_IMFMediaStream(iface);
|
||||
+ struct source_async_command *command;
|
||||
+ HRESULT hr;
|
||||
|
||||
TRACE("(%p)->(%p)\n", iface, token);
|
||||
|
||||
if (stream->state == STREAM_SHUTDOWN)
|
||||
return MF_E_SHUTDOWN;
|
||||
|
||||
- return E_NOTIMPL;
|
||||
+ if (stream->state == STREAM_INACTIVE)
|
||||
+ {
|
||||
+ WARN("Stream isn't active\n");
|
||||
+ return MF_E_MEDIA_SOURCE_WRONGSTATE;
|
||||
+ }
|
||||
+
|
||||
+ if (stream->eos)
|
||||
+ {
|
||||
+ return MF_E_END_OF_STREAM;
|
||||
+ }
|
||||
+
|
||||
+ if (SUCCEEDED(hr = source_create_async_op(SOURCE_ASYNC_REQUEST_SAMPLE, &command)))
|
||||
+ {
|
||||
+ command->u.request_sample.stream = stream;
|
||||
+ if (token)
|
||||
+ IUnknown_AddRef(token);
|
||||
+ command->u.request_sample.token = token;
|
||||
+
|
||||
+ /* Once pause support is added, this will need to put into a stream queue, and synchronization will need to be added*/
|
||||
+ hr = MFPutWorkItem(stream->parent_source->async_commands_queue, &stream->parent_source->async_commands_callback, &command->IUnknown_iface);
|
||||
+ }
|
||||
+
|
||||
+ return hr;
|
||||
}
|
||||
|
||||
static const IMFMediaStreamVtbl media_stream_vtbl =
|
||||
@@ -729,6 +818,7 @@ static HRESULT new_media_stream(struct media_source *source, GstPad *pad, DWORD
|
||||
object->stream_id = stream_id;
|
||||
|
||||
object->state = STREAM_INACTIVE;
|
||||
+ object->eos = FALSE;
|
||||
|
||||
if (FAILED(hr = MFCreateEventQueue(&object->event_queue)))
|
||||
goto fail;
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index 46bbb2ac2b1..908f3d83ef9 100644
|
||||
--- a/dlls/winegstreamer/mfplat.c
|
||||
+++ b/dlls/winegstreamer/mfplat.c
|
||||
@@ -731,3 +731,72 @@ GstCaps *caps_from_mf_media_type(IMFMediaType *type)
|
||||
FIXME("Unrecognized major type %s\n", debugstr_guid(&major_type));
|
||||
return NULL;
|
||||
}
|
||||
+
|
||||
+/* IMFSample = GstBuffer
|
||||
+ IMFBuffer = GstMemory */
|
||||
+
|
||||
+/* TODO: Future optimization could be to create a custom
|
||||
+ IMFMediaBuffer wrapper around GstMemory, and to utilize
|
||||
+ gst_memory_new_wrapped on IMFMediaBuffer data. However,
|
||||
+ this wouldn't work if we allow the callers to allocate
|
||||
+ the buffers. */
|
||||
+
|
||||
+IMFSample* mf_sample_from_gst_buffer(GstBuffer *gst_buffer)
|
||||
+{
|
||||
+ IMFMediaBuffer *mf_buffer = NULL;
|
||||
+ GstMapInfo map_info = {0};
|
||||
+ LONGLONG duration, time;
|
||||
+ BYTE *mapped_buf = NULL;
|
||||
+ IMFSample *out = NULL;
|
||||
+ HRESULT hr;
|
||||
+
|
||||
+ if (FAILED(hr = MFCreateSample(&out)))
|
||||
+ goto done;
|
||||
+
|
||||
+ duration = GST_BUFFER_DURATION(gst_buffer);
|
||||
+ time = GST_BUFFER_PTS(gst_buffer);
|
||||
+
|
||||
+ if (FAILED(hr = IMFSample_SetSampleDuration(out, duration / 100)))
|
||||
+ goto done;
|
||||
+
|
||||
+ if (FAILED(hr = IMFSample_SetSampleTime(out, time / 100)))
|
||||
+ goto done;
|
||||
+
|
||||
+ if (!gst_buffer_map(gst_buffer, &map_info, GST_MAP_READ))
|
||||
+ {
|
||||
+ hr = E_FAIL;
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ if (FAILED(hr = MFCreateMemoryBuffer(map_info.maxsize, &mf_buffer)))
|
||||
+ goto done;
|
||||
+
|
||||
+ if (FAILED(hr = IMFMediaBuffer_Lock(mf_buffer, &mapped_buf, NULL, NULL)))
|
||||
+ goto done;
|
||||
+
|
||||
+ memcpy(mapped_buf, map_info.data, map_info.size);
|
||||
+
|
||||
+ if (FAILED(hr = IMFMediaBuffer_Unlock(mf_buffer)))
|
||||
+ goto done;
|
||||
+
|
||||
+ if (FAILED(hr = IMFMediaBuffer_SetCurrentLength(mf_buffer, map_info.size)))
|
||||
+ goto done;
|
||||
+
|
||||
+ if (FAILED(hr = IMFSample_AddBuffer(out, mf_buffer)))
|
||||
+ goto done;
|
||||
+
|
||||
+done:
|
||||
+ if (mf_buffer)
|
||||
+ IMFMediaBuffer_Release(mf_buffer);
|
||||
+ if (map_info.data)
|
||||
+ gst_buffer_unmap(gst_buffer, &map_info);
|
||||
+ if (FAILED(hr))
|
||||
+ {
|
||||
+ ERR("Failed to copy IMFSample to GstBuffer, hr = %#x\n", hr);
|
||||
+ if (out)
|
||||
+ IMFSample_Release(out);
|
||||
+ out = NULL;
|
||||
+ }
|
||||
+
|
||||
+ return out;
|
||||
+}
|
||||
--
|
||||
2.28.0
|
||||
|
@ -1,4 +1,4 @@
|
||||
From 525bedb342d7f9964f755a378008170410e8777f Mon Sep 17 00:00:00 2001
|
||||
From e97b113c42663be4b989c098703013da75a6ad1a Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Wed, 29 Jan 2020 15:30:49 -0600
|
||||
Subject: [PATCH] mf: Introduce handler helper.
|
||||
@ -16,12 +16,12 @@ Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
create mode 100644 dlls/mf/handler.h
|
||||
|
||||
diff --git a/dlls/mf/Makefile.in b/dlls/mf/Makefile.in
|
||||
index f1d0571d143..1f741269f71 100644
|
||||
index cd50a849b7c..67a7e8a79b6 100644
|
||||
--- a/dlls/mf/Makefile.in
|
||||
+++ b/dlls/mf/Makefile.in
|
||||
@@ -7,6 +7,7 @@ EXTRADLLFLAGS = -mno-cygwin
|
||||
|
||||
@@ -8,6 +8,7 @@ EXTRADLLFLAGS = -mno-cygwin
|
||||
C_SRCS = \
|
||||
copier.c \
|
||||
evr.c \
|
||||
+ handler.c \
|
||||
main.c \
|
||||
@ -432,7 +432,7 @@ index 00000000000..fbebd26e8d0
|
||||
+HRESULT handler_cancel_object_creation(struct handler *handler, IUnknown *cancel_cookie);
|
||||
\ No newline at end of file
|
||||
diff --git a/dlls/mf/main.c b/dlls/mf/main.c
|
||||
index c48fc81a1d2..7b36a16ee71 100644
|
||||
index 2caf50c54e0..cf58c899843 100644
|
||||
--- a/dlls/mf/main.c
|
||||
+++ b/dlls/mf/main.c
|
||||
@@ -27,6 +27,7 @@
|
||||
@ -932,7 +932,7 @@ index e578d194f7f..f2e87494459 100644
|
||||
media_source.c \
|
||||
mediatype.c \
|
||||
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
|
||||
index 6873b4e7844..66aa7d92ed8 100644
|
||||
index 337c4f52c35..5eeb0e1ffcb 100644
|
||||
--- a/dlls/winegstreamer/media_source.c
|
||||
+++ b/dlls/winegstreamer/media_source.c
|
||||
@@ -23,6 +23,7 @@
|
||||
@ -943,7 +943,7 @@ index 6873b4e7844..66aa7d92ed8 100644
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
@@ -1498,21 +1499,11 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
|
||||
@@ -1500,21 +1501,11 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
|
||||
return hr;
|
||||
}
|
||||
|
||||
@ -966,7 +966,7 @@ index 6873b4e7844..66aa7d92ed8 100644
|
||||
};
|
||||
|
||||
static struct winegstreamer_stream_handler *impl_from_IMFByteStreamHandler(IMFByteStreamHandler *iface)
|
||||
@@ -1520,11 +1511,6 @@ static struct winegstreamer_stream_handler *impl_from_IMFByteStreamHandler(IMFBy
|
||||
@@ -1522,11 +1513,6 @@ static struct winegstreamer_stream_handler *impl_from_IMFByteStreamHandler(IMFBy
|
||||
return CONTAINING_RECORD(iface, struct winegstreamer_stream_handler, IMFByteStreamHandler_iface);
|
||||
}
|
||||
|
||||
@ -978,7 +978,7 @@ index 6873b4e7844..66aa7d92ed8 100644
|
||||
static HRESULT WINAPI winegstreamer_stream_handler_QueryInterface(IMFByteStreamHandler *iface, REFIID riid, void **obj)
|
||||
{
|
||||
TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
|
||||
@@ -1554,247 +1540,44 @@ static ULONG WINAPI winegstreamer_stream_handler_AddRef(IMFByteStreamHandler *if
|
||||
@@ -1556,247 +1542,44 @@ static ULONG WINAPI winegstreamer_stream_handler_AddRef(IMFByteStreamHandler *if
|
||||
|
||||
static ULONG WINAPI winegstreamer_stream_handler_Release(IMFByteStreamHandler *iface)
|
||||
{
|
||||
@ -1233,7 +1233,7 @@ index 6873b4e7844..66aa7d92ed8 100644
|
||||
}
|
||||
|
||||
static HRESULT WINAPI winegstreamer_stream_handler_GetMaxNumberOfBytesRequiredForResolution(IMFByteStreamHandler *iface, QWORD *bytes)
|
||||
@@ -1814,47 +1597,16 @@ static const IMFByteStreamHandlerVtbl winegstreamer_stream_handler_vtbl =
|
||||
@@ -1816,47 +1599,16 @@ static const IMFByteStreamHandlerVtbl winegstreamer_stream_handler_vtbl =
|
||||
winegstreamer_stream_handler_GetMaxNumberOfBytesRequiredForResolution,
|
||||
};
|
||||
|
||||
@ -1284,7 +1284,7 @@ index 6873b4e7844..66aa7d92ed8 100644
|
||||
|
||||
if (FAILED(hr = media_source_constructor(stream, &new_source)))
|
||||
return hr;
|
||||
@@ -1873,64 +1625,6 @@ static HRESULT winegstreamer_stream_handler_create_object(struct winegstreamer_s
|
||||
@@ -1875,64 +1627,6 @@ static HRESULT winegstreamer_stream_handler_create_object(struct winegstreamer_s
|
||||
}
|
||||
}
|
||||
|
||||
@ -1349,7 +1349,7 @@ index 6873b4e7844..66aa7d92ed8 100644
|
||||
HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj)
|
||||
{
|
||||
struct winegstreamer_stream_handler *this;
|
||||
@@ -1942,11 +1636,9 @@ HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj)
|
||||
@@ -1944,11 +1638,9 @@ HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj)
|
||||
if (!this)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
From 5356d013c808b240697ad2d54c0c9594e118ee10 Mon Sep 17 00:00:00 2001
|
||||
From cce3f184251778d5a224a6566eb6e25f72c3a40e Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Mon, 9 Mar 2020 11:59:17 -0500
|
||||
Subject: [PATCH] Improve tests
|
||||
@ -13,7 +13,7 @@ Subject: [PATCH] Improve tests
|
||||
create mode 100644 dlls/mfreadwrite/tests/test.mp4
|
||||
|
||||
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c
|
||||
index 8f9fb3faff3..cec79b5b21e 100644
|
||||
index fed6b392b21..aa73e7efd39 100644
|
||||
--- a/dlls/mfplat/tests/mfplat.c
|
||||
+++ b/dlls/mfplat/tests/mfplat.c
|
||||
@@ -438,6 +438,9 @@ static BOOL get_event(IMFMediaEventGenerator *generator, MediaEventType expected
|
||||
@ -75,9 +75,9 @@ index 8f9fb3faff3..cec79b5b21e 100644
|
||||
- sample_count = 10;
|
||||
+ sample_count = 60;
|
||||
|
||||
/* Request one beyond EOS, otherwise EndOfStream isn't queued. */
|
||||
for (i = 0; i <= sample_count; ++i)
|
||||
@@ -629,9 +647,14 @@ todo_wine
|
||||
for (i = 0; i < sample_count; ++i)
|
||||
{
|
||||
@@ -628,9 +646,14 @@ todo_wine
|
||||
for (i = 0; i < sample_count; ++i)
|
||||
{
|
||||
static const LONGLONG MILLI_TO_100_NANO = 10000;
|
||||
@ -93,7 +93,7 @@ index 8f9fb3faff3..cec79b5b21e 100644
|
||||
BOOL ret;
|
||||
|
||||
ret = get_event((IMFMediaEventGenerator *)video_stream, MEMediaSample, &var);
|
||||
@@ -642,19 +665,38 @@ todo_wine
|
||||
@@ -641,19 +664,38 @@ todo_wine
|
||||
ok(var.vt == VT_UNKNOWN, "Unexpected value type %u from MEMediaSample event.\n", var.vt);
|
||||
sample = (IMFSample *)var.punkVal;
|
||||
|
||||
@ -141,7 +141,7 @@ index 8f9fb3faff3..cec79b5b21e 100644
|
||||
}
|
||||
|
||||
if (i == sample_count)
|
||||
@@ -712,6 +754,178 @@ todo_wine
|
||||
@@ -723,6 +765,178 @@ todo_wine
|
||||
DeleteFileW(filename);
|
||||
}
|
||||
|
||||
@ -320,7 +320,7 @@ index 8f9fb3faff3..cec79b5b21e 100644
|
||||
static void init_functions(void)
|
||||
{
|
||||
HMODULE mod = GetModuleHandleA("mfplat.dll");
|
||||
@@ -5822,6 +6036,7 @@ START_TEST(mfplat)
|
||||
@@ -5855,6 +6069,7 @@ START_TEST(mfplat)
|
||||
test_MFCreateMFByteStreamOnStream();
|
||||
test_system_memory_buffer();
|
||||
test_source_resolver();
|
||||
@ -2679,7 +2679,7 @@ zKs;bQARC}!xiSZ6ESNJ5P+CoKB<O7nEod-NqPX>NU0kHoiM#Wkq*n&-SMq0^0~2cD
|
||||
TJ;x-N6hTeOp(eUDP!ruh^$B~#
|
||||
|
||||
diff --git a/dlls/mfreadwrite/tests/mfplat.c b/dlls/mfreadwrite/tests/mfplat.c
|
||||
index ba457181a61..e90e980f997 100644
|
||||
index ef25bbcb3eb..985490d348c 100644
|
||||
--- a/dlls/mfreadwrite/tests/mfplat.c
|
||||
+++ b/dlls/mfreadwrite/tests/mfplat.c
|
||||
@@ -629,9 +629,17 @@ static void test_source_reader(void)
|
||||
@ -2848,9 +2848,9 @@ index ba457181a61..e90e980f997 100644
|
||||
×tamp, &sample);
|
||||
ok(hr == S_OK, "Failed to get a sample, hr %#x.\n", hr);
|
||||
ok(actual_index == 0, "Unexpected stream index %u\n", actual_index);
|
||||
@@ -758,28 +778,28 @@ todo_wine
|
||||
ok(!sample, "Unexpected sample object.\n");
|
||||
}
|
||||
@@ -770,28 +790,28 @@ todo_wine
|
||||
ok(!sample, "Unexpected sample object.\n");
|
||||
}
|
||||
|
||||
- hr = IMFSourceReader_ReadSample(reader, MF_SOURCE_READER_FIRST_AUDIO_STREAM, MF_SOURCE_READER_CONTROLF_DRAIN,
|
||||
+ hr = IMFSourceReader_ReadSample(reader, MF_SOURCE_READER_FIRST_VIDEO_STREAM, MF_SOURCE_READER_CONTROLF_DRAIN,
|
||||
@ -2882,7 +2882,7 @@ index ba457181a61..e90e980f997 100644
|
||||
&actual_index, &stream_flags, NULL, &sample);
|
||||
ok(hr == S_OK, "Failed to get a sample, hr %#x.\n", hr);
|
||||
ok(actual_index == 0, "Unexpected stream index %u\n", actual_index);
|
||||
@@ -788,28 +808,33 @@ todo_wine
|
||||
@@ -800,28 +820,33 @@ todo_wine
|
||||
|
||||
hr = IMFSourceReader_ReadSample(reader, MF_SOURCE_READER_ANY_STREAM, MF_SOURCE_READER_CONTROLF_DRAIN,
|
||||
&actual_index, &stream_flags, NULL, &sample);
|
||||
|
@ -1,4 +1,4 @@
|
||||
From d7be1597dcffd2c2822c9b6f33a4b22cdf33220c Mon Sep 17 00:00:00 2001
|
||||
From 97213490527eb3adab5279dc4b56284b44234573 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Wed, 25 Mar 2020 13:58:36 -0500
|
||||
Subject: [PATCH] Revert "Improve tests"
|
||||
@ -14,7 +14,7 @@ This reverts commit 603b1717a2b511a66d3be99ab5761d49cd5ef34d.
|
||||
delete mode 100644 dlls/mfreadwrite/tests/test.mp4
|
||||
|
||||
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c
|
||||
index cec79b5b21e..50555c6ca67 100644
|
||||
index aa73e7efd39..1d9d1e326c9 100644
|
||||
--- a/dlls/mfplat/tests/mfplat.c
|
||||
+++ b/dlls/mfplat/tests/mfplat.c
|
||||
@@ -438,9 +438,6 @@ static BOOL get_event(IMFMediaEventGenerator *generator, MediaEventType expected
|
||||
@ -75,9 +75,9 @@ index cec79b5b21e..50555c6ca67 100644
|
||||
- sample_count = 60;
|
||||
+ sample_count = 10;
|
||||
|
||||
/* Request one beyond EOS, otherwise EndOfStream isn't queued. */
|
||||
for (i = 0; i <= sample_count; ++i)
|
||||
@@ -647,14 +628,9 @@ static void test_source_resolver(void)
|
||||
for (i = 0; i < sample_count; ++i)
|
||||
{
|
||||
@@ -646,14 +627,9 @@ static void test_source_resolver(void)
|
||||
for (i = 0; i < sample_count; ++i)
|
||||
{
|
||||
static const LONGLONG MILLI_TO_100_NANO = 10000;
|
||||
@ -93,7 +93,7 @@ index cec79b5b21e..50555c6ca67 100644
|
||||
BOOL ret;
|
||||
|
||||
ret = get_event((IMFMediaEventGenerator *)video_stream, MEMediaSample, &var);
|
||||
@@ -665,38 +641,19 @@ static void test_source_resolver(void)
|
||||
@@ -664,38 +640,19 @@ static void test_source_resolver(void)
|
||||
ok(var.vt == VT_UNKNOWN, "Unexpected value type %u from MEMediaSample event.\n", var.vt);
|
||||
sample = (IMFSample *)var.punkVal;
|
||||
|
||||
@ -141,7 +141,7 @@ index cec79b5b21e..50555c6ca67 100644
|
||||
}
|
||||
|
||||
if (i == sample_count)
|
||||
@@ -754,178 +711,6 @@ static void test_source_resolver(void)
|
||||
@@ -765,178 +722,6 @@ static void test_source_resolver(void)
|
||||
DeleteFileW(filename);
|
||||
}
|
||||
|
||||
@ -320,7 +320,7 @@ index cec79b5b21e..50555c6ca67 100644
|
||||
static void init_functions(void)
|
||||
{
|
||||
HMODULE mod = GetModuleHandleA("mfplat.dll");
|
||||
@@ -6036,7 +5821,6 @@ START_TEST(mfplat)
|
||||
@@ -6069,7 +5854,6 @@ START_TEST(mfplat)
|
||||
test_MFCreateMFByteStreamOnStream();
|
||||
test_system_memory_buffer();
|
||||
test_source_resolver();
|
||||
@ -2679,7 +2679,7 @@ zfQ)qlARIsx0Hh62ATV5k(+0j9`c{9|0J%OK0QBskcDevpw=lTjNcF>i79OBj+33Px
|
||||
p$lCDV^w{Kgb))}cXN3$%0oA>6Mg|4R>N*%cfv|D$vvG28{1-l>vtIxJ
|
||||
|
||||
diff --git a/dlls/mfreadwrite/tests/mfplat.c b/dlls/mfreadwrite/tests/mfplat.c
|
||||
index e90e980f997..7b66a414a51 100644
|
||||
index 985490d348c..03f0d9a1c2a 100644
|
||||
--- a/dlls/mfreadwrite/tests/mfplat.c
|
||||
+++ b/dlls/mfreadwrite/tests/mfplat.c
|
||||
@@ -629,15 +629,10 @@ static void test_source_reader(void)
|
||||
@ -2845,9 +2845,9 @@ index e90e980f997..7b66a414a51 100644
|
||||
×tamp, &sample);
|
||||
ok(hr == S_OK, "Failed to get a sample, hr %#x.\n", hr);
|
||||
ok(actual_index == 0, "Unexpected stream index %u\n", actual_index);
|
||||
@@ -778,28 +759,28 @@ todo_wine
|
||||
ok(!sample, "Unexpected sample object.\n");
|
||||
}
|
||||
@@ -790,28 +771,28 @@ todo_wine
|
||||
ok(!sample, "Unexpected sample object.\n");
|
||||
}
|
||||
|
||||
- hr = IMFSourceReader_ReadSample(reader, MF_SOURCE_READER_FIRST_VIDEO_STREAM, MF_SOURCE_READER_CONTROLF_DRAIN,
|
||||
+ hr = IMFSourceReader_ReadSample(reader, MF_SOURCE_READER_FIRST_AUDIO_STREAM, MF_SOURCE_READER_CONTROLF_DRAIN,
|
||||
@ -2879,7 +2879,7 @@ index e90e980f997..7b66a414a51 100644
|
||||
&actual_index, &stream_flags, NULL, &sample);
|
||||
ok(hr == S_OK, "Failed to get a sample, hr %#x.\n", hr);
|
||||
ok(actual_index == 0, "Unexpected stream index %u\n", actual_index);
|
||||
@@ -808,33 +789,28 @@ todo_wine
|
||||
@@ -820,33 +801,28 @@ todo_wine
|
||||
|
||||
hr = IMFSourceReader_ReadSample(reader, MF_SOURCE_READER_ANY_STREAM, MF_SOURCE_READER_CONTROLF_DRAIN,
|
||||
&actual_index, &stream_flags, NULL, &sample);
|
||||
|
@ -51,7 +51,7 @@ usage()
|
||||
# Get the upstream commit sha
|
||||
upstream_commit()
|
||||
{
|
||||
echo "c9e2deac39924473ac538ee22a2a0c0dbe3bad85"
|
||||
echo "03eaa2cc93e5e2ea4c36495870c268797aea3ca8"
|
||||
}
|
||||
|
||||
# Show version information
|
||||
@ -2842,9 +2842,6 @@ if test "$enable_mfplat_streaming_support" -eq 1; then
|
||||
patch_apply mfplat-streaming-support/0003-mfmediaengine-Issue-MF_MEDIA_ENGINE_EVENT_PLAYING-up.patch
|
||||
patch_apply mfplat-streaming-support/0004-mfmediaengine-Issue-MF_MEDIA_ENGINE_EVENT_ENDED-upon.patch
|
||||
patch_apply mfplat-streaming-support/0005-mf-Unconditionally-deliver-NULL-EOS-samples.patch
|
||||
patch_apply mfplat-streaming-support/0008-mfreadwrite-Abort-ReadSample-when-unable-to-request-.patch
|
||||
patch_apply mfplat-streaming-support/0009-winegstreamer-Implement-IMFMediaSource-Start.patch
|
||||
patch_apply mfplat-streaming-support/0010-winegstreamer-Implement-IMFMediaStream-RequestSample.patch
|
||||
patch_apply mfplat-streaming-support/0011-winegstreamer-Insert-parser-into-pipeline-to-rectify.patch
|
||||
patch_apply mfplat-streaming-support/0012-winegstreamer-Translate-H.264-caps-to-attributes.patch
|
||||
patch_apply mfplat-streaming-support/0013-winegstreamer-Translate-WMV-caps-to-attributes.patch
|
||||
|
@ -1 +1 @@
|
||||
c9e2deac39924473ac538ee22a2a0c0dbe3bad85
|
||||
03eaa2cc93e5e2ea4c36495870c268797aea3ca8
|
||||
|
Loading…
x
Reference in New Issue
Block a user