[PATCH v1 3/3] mfreadwrite: Implement MF_SOURCE_READER_ASYNC_CALLBACK.
Derek Lesho
dlesho at codeweavers.com
Tue Mar 17 11:48:45 CDT 2020
Signed-off-by: Derek Lesho <dlesho at codeweavers.com>
---
dlls/mfreadwrite/main.c | 143 +++++++++++++++++++++++++++++++-
dlls/mfreadwrite/tests/mfplat.c | 20 ++++-
2 files changed, 159 insertions(+), 4 deletions(-)
diff --git a/dlls/mfreadwrite/main.c b/dlls/mfreadwrite/main.c
index 7ebfa0cc21..2a0a1287d6 100644
--- a/dlls/mfreadwrite/main.c
+++ b/dlls/mfreadwrite/main.c
@@ -102,6 +102,7 @@ struct media_stream
enum media_stream_state state;
BOOL selected;
BOOL presented;
+ DWORD read_samples_queue;
};
struct source_reader
@@ -109,6 +110,7 @@ struct source_reader
IMFSourceReader IMFSourceReader_iface;
IMFAsyncCallback source_events_callback;
IMFAsyncCallback stream_events_callback;
+ IMFAsyncCallback read_samples_callback;
LONG refcount;
IMFMediaSource *source;
IMFPresentationDescriptor *descriptor;
@@ -143,6 +145,11 @@ static struct source_reader *impl_from_stream_callback_IMFAsyncCallback(IMFAsync
return CONTAINING_RECORD(iface, struct source_reader, stream_events_callback);
}
+static struct source_reader *impl_from_read_samples_callback_IMFAsyncCallback(IMFAsyncCallback *iface)
+{
+ return CONTAINING_RECORD(iface, struct source_reader, read_samples_callback);
+}
+
static inline struct sink_writer *impl_from_IMFSinkWriter(IMFSinkWriter *iface)
{
return CONTAINING_RECORD(iface, struct sink_writer, IMFSinkWriter_iface);
@@ -587,6 +594,8 @@ static ULONG WINAPI src_reader_Release(IMFSourceReader *iface)
list_remove(&ptr->entry);
heap_free(ptr);
}
+
+ MFUnlockWorkQueue(stream->read_samples_queue);
}
heap_free(reader->streams);
DeleteCriticalSection(&reader->cs);
@@ -1187,13 +1196,138 @@ static HRESULT source_reader_read_sample(struct source_reader *reader, DWORD ind
return hr;
}
-static HRESULT source_reader_read_sample_async(struct source_reader *reader, DWORD index, DWORD flags)
+static HRESULT WINAPI source_reader_read_samples_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 ULONG WINAPI source_reader_read_samples_callback_AddRef(IMFAsyncCallback *iface)
+{
+ struct source_reader *reader = impl_from_read_samples_callback_IMFAsyncCallback(iface);
+ return IMFSourceReader_AddRef(&reader->IMFSourceReader_iface);
+}
+
+static ULONG WINAPI source_reader_read_samples_callback_Release(IMFAsyncCallback *iface)
{
- FIXME("Async mode is not implemented.\n");
+ struct source_reader *reader = impl_from_read_samples_callback_IMFAsyncCallback(iface);
+ return IMFSourceReader_Release(&reader->IMFSourceReader_iface);
+}
+static HRESULT WINAPI source_reader_read_samples_callback_GetParameters(IMFAsyncCallback *iface,
+ DWORD *flags, DWORD *queue)
+{
return E_NOTIMPL;
}
+static HRESULT WINAPI source_reader_read_samples_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result)
+{
+ struct source_reader *reader = impl_from_read_samples_callback_IMFAsyncCallback(iface);
+ IMFMediaStream *state = (IMFMediaStream *) IMFAsyncResult_GetStateNoAddRef(result);
+ DWORD id = 0;
+ HRESULT hr;
+
+ TRACE("%p, %p\n", iface, result);
+
+ if (FAILED(hr = media_stream_get_id(state, &id)))
+ {
+ WARN("Bad stream %p, hr %#x.\n", state, hr);
+ }
+
+ for (unsigned int i = 0; i < reader->stream_count; ++i)
+ {
+ if (id == reader->streams[i].id)
+ {
+ struct media_stream *stream = &reader->streams[i];
+ IMFSample *sample = NULL;
+ DWORD stream_flags;
+ LONGLONG timestamp = 0;
+
+ hr = next_sample(stream, &sample, &stream_flags, FALSE);
+ if (sample)
+ {
+ IMFSample_GetSampleTime(sample, ×tamp);
+ }
+
+ TRACE("Invoking read sample callback %p with (hr = %#x, stream_idx = %u, flags = %#x, timestamp %lu, sample %p)\n", reader->async_callback, hr, i, stream_flags, timestamp, sample);
+ hr = IMFSourceReaderCallback_OnReadSample(reader->async_callback, hr, i, stream_flags, timestamp, sample);
+ IMFSample_Release(sample);
+ return hr;
+ }
+ }
+
+ return S_OK;
+}
+
+static const IMFAsyncCallbackVtbl read_samples_callback_vtbl =
+{
+ source_reader_read_samples_callback_QueryInterface,
+ source_reader_read_samples_callback_AddRef,
+ source_reader_read_samples_callback_Release,
+ source_reader_read_samples_callback_GetParameters,
+ source_reader_read_samples_callback_Invoke,
+};
+
+static HRESULT source_reader_read_sample_async(struct source_reader *reader, DWORD index, DWORD flags)
+{
+ struct media_stream *stream;
+ DWORD stream_index;
+ HRESULT hr = S_OK;
+ BOOL selected;
+
+ switch (index)
+ {
+ case MF_SOURCE_READER_FIRST_VIDEO_STREAM:
+ stream_index = reader->first_video_stream_index;
+ break;
+ case MF_SOURCE_READER_FIRST_AUDIO_STREAM:
+ stream_index = reader->first_audio_stream_index;
+ break;
+ case MF_SOURCE_READER_ANY_STREAM:
+ FIXME("Non-specific requests are not supported.\n");
+ return E_NOTIMPL;
+ default:
+ stream_index = index;
+ }
+
+ /* Can't read from deselected streams. */
+ if (FAILED(hr = source_reader_get_stream_selection(reader, stream_index, &selected)) && !selected)
+ return hr;
+
+ stream = &reader->streams[stream_index];
+
+ if (FAILED(hr = source_reader_start_source(reader)))
+ return hr;
+
+ EnterCriticalSection(&stream->cs);
+ while(!stream->stream)
+ {
+ SleepConditionVariableCS(&stream->sample_event, &stream->cs, INFINITE);
+ }
+ LeaveCriticalSection(&stream->cs);
+
+ TRACE("Dispatching read sample callback for stream %p\n", stream->stream);
+ if (FAILED(hr = MFPutWorkItem(stream->read_samples_queue, &reader->read_samples_callback, (IUnknown*)stream->stream)))
+ {
+ WARN("Failed to submit item hr = %#x\n", hr);
+ return E_FAIL;
+ }
+
+ return S_OK;
+}
+
static HRESULT WINAPI src_reader_ReadSample(IMFSourceReader *iface, DWORD index, DWORD flags, DWORD *actual_index,
DWORD *stream_flags, LONGLONG *timestamp, IMFSample **sample)
{
@@ -1379,6 +1513,7 @@ static HRESULT create_source_reader_from_source(IMFMediaSource *source, IMFAttri
object->IMFSourceReader_iface.lpVtbl = &srcreader_vtbl;
object->source_events_callback.lpVtbl = &source_events_callback_vtbl;
object->stream_events_callback.lpVtbl = &stream_events_callback_vtbl;
+ object->read_samples_callback.lpVtbl = &read_samples_callback_vtbl;
object->refcount = 1;
object->source = source;
IMFMediaSource_AddRef(object->source);
@@ -1404,6 +1539,10 @@ static HRESULT create_source_reader_from_source(IMFMediaSource *source, IMFAttri
IMFMediaType *src_type;
BOOL selected;
+
+ if (FAILED(hr = MFAllocateWorkQueue(&object->streams[i].read_samples_queue)))
+ break;
+
if (FAILED(hr = MFCreateMediaType(&object->streams[i].current)))
break;
diff --git a/dlls/mfreadwrite/tests/mfplat.c b/dlls/mfreadwrite/tests/mfplat.c
index e03d74981a..2bc9e2c40f 100644
--- a/dlls/mfreadwrite/tests/mfplat.c
+++ b/dlls/mfreadwrite/tests/mfplat.c
@@ -562,11 +562,18 @@ static ULONG WINAPI async_callback_Release(IMFSourceReaderCallback *iface)
return refcount;
}
+static HANDLE on_read_sample_event = INVALID_HANDLE_VALUE;
+
static HRESULT WINAPI async_callback_OnReadSample(IMFSourceReaderCallback *iface, HRESULT hr, DWORD stream_index,
DWORD stream_flags, LONGLONG timestamp, IMFSample *sample)
{
- ok(0, "Unexpected call.\n");
- return E_NOTIMPL;
+ ok(hr == S_OK, "Unexpected hr %#x\n", hr);
+ ok(!stream_flags, "Unexpected stream flags %#x.\n", stream_flags);
+ ok(!!sample, "Didn't receive sample.\n");
+
+ SetEvent(on_read_sample_event);
+
+ return S_OK;
}
static HRESULT WINAPI async_callback_OnFlush(IMFSourceReaderCallback *iface, DWORD stream_index)
@@ -951,6 +958,15 @@ todo_wine
hr = IMFSourceReader_ReadSample(reader, 0, 0, NULL, NULL, NULL, &sample);
ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+ on_read_sample_event = CreateEventA(NULL, FALSE, FALSE, NULL);
+
+ hr = IMFSourceReader_ReadSample(reader, 0, 0, NULL, NULL, NULL, NULL);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ ok(WaitForSingleObject(on_read_sample_event, 3000) == WAIT_OBJECT_0, "Sample never triggered.\n");
+
+ CloseHandle(on_read_sample_event);
+
IMFSourceReader_Release(reader);
}
--
2.25.1
More information about the wine-devel
mailing list