Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/samplegrabber.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
diff --git a/dlls/mf/samplegrabber.c b/dlls/mf/samplegrabber.c index 3f9644432d..23bfa06fce 100644 --- a/dlls/mf/samplegrabber.c +++ b/dlls/mf/samplegrabber.c @@ -613,6 +613,11 @@ static struct scheduled_sample *stream_get_next_sample(struct sample_grabber_str return sample; }
+static void sample_grabber_stream_request_sample(struct sample_grabber_stream *stream) +{ + IMFStreamSink_QueueEvent(&stream->IMFStreamSink_iface, MEStreamSinkRequestSample, &GUID_NULL, S_OK, NULL); +} + static HRESULT WINAPI sample_grabber_stream_timer_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result) { struct sample_grabber_stream *stream = impl_from_IMFAsyncCallback(iface); @@ -634,6 +639,7 @@ static HRESULT WINAPI sample_grabber_stream_timer_callback_Invoke(IMFAsyncCallba if (FAILED(hr = stream_schedule_sample(stream, sample))) WARN("Failed to schedule a sample, hr %#x.\n", hr); } + sample_grabber_stream_request_sample(stream); }
LeaveCriticalSection(&stream->cs); @@ -950,6 +956,7 @@ static void sample_grabber_set_state(struct sample_grabber *grabber, enum sink_s MEStreamSinkStarted, /* SINK_STATE_RUNNING */ }; BOOL set_state = FALSE; + unsigned int i;
EnterCriticalSection(&grabber->cs);
@@ -970,6 +977,12 @@ static void sample_grabber_set_state(struct sample_grabber *grabber, enum sink_s if (set_state) { grabber->stream->state = state; + if (state == SINK_STATE_RUNNING) + { + /* Every transition to running state sends a bunch requests to build up initial queue. */ + for (i = 0; i < 4; ++i) + sample_grabber_stream_request_sample(grabber->stream); + } IMFStreamSink_QueueEvent(&grabber->stream->IMFStreamSink_iface, events[state], &GUID_NULL, S_OK, NULL); } }
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/Makefile.in | 2 +- dlls/mf/samplegrabber.c | 163 ++++++++++++++++++++++++++++++---------- 2 files changed, 124 insertions(+), 41 deletions(-)
diff --git a/dlls/mf/Makefile.in b/dlls/mf/Makefile.in index d9c85c435f..bdf5887572 100644 --- a/dlls/mf/Makefile.in +++ b/dlls/mf/Makefile.in @@ -1,6 +1,6 @@ MODULE = mf.dll IMPORTLIB = mf -IMPORTS = mfplat uuid mfuuid +IMPORTS = mfplat ole32 uuid mfuuid
C_SRCS = \ main.c \ diff --git a/dlls/mf/samplegrabber.c b/dlls/mf/samplegrabber.c index 23bfa06fce..ed07116a4e 100644 --- a/dlls/mf/samplegrabber.c +++ b/dlls/mf/samplegrabber.c @@ -37,10 +37,25 @@ enum sink_state
struct sample_grabber;
-struct scheduled_sample +enum scheduled_item_type +{ + ITEM_TYPE_SAMPLE, + ITEM_TYPE_MARKER, +}; + +struct scheduled_item { struct list entry; - IMFSample *sample; + enum scheduled_item_type type; + union + { + IMFSample *sample; + struct + { + MFSTREAMSINK_MARKER_TYPE type; + PROPVARIANT context; + } marker; + } u; };
struct sample_grabber_stream @@ -52,7 +67,7 @@ struct sample_grabber_stream struct sample_grabber *sink; IMFMediaEventQueue *event_queue; enum sink_state state; - struct list samples; + struct list items; IUnknown *cancel_key; CRITICAL_SECTION cs; }; @@ -156,18 +171,26 @@ static ULONG WINAPI sample_grabber_stream_AddRef(IMFStreamSink *iface) return refcount; }
-static void stream_release_pending_entry(struct sample_grabber_stream *stream, struct scheduled_sample *sample) +static void stream_release_pending_item(struct sample_grabber_stream *stream, struct scheduled_item *item) { - list_remove(&sample->entry); - IMFSample_Release(sample->sample); - heap_free(sample); + list_remove(&item->entry); + switch (item->type) + { + case ITEM_TYPE_SAMPLE: + IMFSample_Release(item->u.sample); + break; + case ITEM_TYPE_MARKER: + PropVariantClear(&item->u.marker.context); + break; + } + heap_free(item); }
static ULONG WINAPI sample_grabber_stream_Release(IMFStreamSink *iface) { struct sample_grabber_stream *stream = impl_from_IMFStreamSink(iface); ULONG refcount = InterlockedDecrement(&stream->refcount); - struct scheduled_sample *sample, *next_sample; + struct scheduled_item *item, *next_item;
TRACE("%p, refcount %u.\n", iface, refcount);
@@ -186,9 +209,9 @@ static ULONG WINAPI sample_grabber_stream_Release(IMFStreamSink *iface) IMFMediaEventQueue_Shutdown(stream->event_queue); IMFMediaEventQueue_Release(stream->event_queue); } - LIST_FOR_EACH_ENTRY_SAFE(sample, next_sample, &stream->samples, struct scheduled_sample, entry) + LIST_FOR_EACH_ENTRY_SAFE(item, next_item, &stream->items, struct scheduled_item, entry) { - stream_release_pending_entry(stream, sample); + stream_release_pending_item(stream, item); } DeleteCriticalSection(&stream->cs); heap_free(stream); @@ -321,7 +344,7 @@ static HRESULT sample_grabber_report_sample(struct sample_grabber *grabber, IMFS return hr; }
-static HRESULT stream_schedule_sample(struct sample_grabber_stream *stream, struct scheduled_sample *pending) +static HRESULT stream_schedule_sample(struct sample_grabber_stream *stream, struct scheduled_item *item) { LONGLONG sampletime; HRESULT hr; @@ -329,7 +352,7 @@ static HRESULT stream_schedule_sample(struct sample_grabber_stream *stream, stru if (!stream->sink) return MF_E_STREAMSINK_REMOVED;
- if (FAILED(hr = IMFSample_GetSampleTime(pending->sample, &sampletime))) + if (FAILED(hr = IMFSample_GetSampleTime(item->u.sample, &sampletime))) return hr;
if (stream->cancel_key) @@ -349,26 +372,27 @@ static HRESULT stream_schedule_sample(struct sample_grabber_stream *stream, stru
static HRESULT stream_queue_sample(struct sample_grabber_stream *stream, IMFSample *sample) { - struct scheduled_sample *pending; + struct scheduled_item *item; LONGLONG sampletime; HRESULT hr;
if (FAILED(hr = IMFSample_GetSampleTime(sample, &sampletime))) return hr;
- if (!(pending = heap_alloc_zero(sizeof(*pending)))) + if (!(item = heap_alloc_zero(sizeof(*item)))) return E_OUTOFMEMORY;
- pending->sample = sample; - IMFSample_AddRef(pending->sample); - list_init(&pending->entry); - if (list_empty(&stream->samples)) - hr = stream_schedule_sample(stream, pending); + item->type = ITEM_TYPE_SAMPLE; + item->u.sample = sample; + IMFSample_AddRef(item->u.sample); + list_init(&item->entry); + if (list_empty(&stream->items)) + hr = stream_schedule_sample(stream, item);
if (SUCCEEDED(hr)) - list_add_tail(&stream->samples, &pending->entry); + list_add_tail(&stream->items, &item->entry); else - stream_release_pending_entry(stream, pending); + stream_release_pending_item(stream, item);
return hr; } @@ -407,12 +431,58 @@ static HRESULT WINAPI sample_grabber_stream_ProcessSample(IMFStreamSink *iface, return hr; }
+static void sample_grabber_stream_report_marker(struct sample_grabber_stream *stream, const PROPVARIANT *context, + HRESULT hr) +{ + IMFStreamSink_QueueEvent(&stream->IMFStreamSink_iface, MEStreamSinkMarker, &GUID_NULL, hr, context); +} + +static HRESULT stream_place_marker(struct sample_grabber_stream *stream, MFSTREAMSINK_MARKER_TYPE marker_type, + const PROPVARIANT *context_value) +{ + struct scheduled_item *item; + HRESULT hr; + + if (list_empty(&stream->items)) + { + sample_grabber_stream_report_marker(stream, context_value, S_OK); + return S_OK; + } + + if (!(item = heap_alloc_zero(sizeof(*item)))) + return E_OUTOFMEMORY; + + item->type = ITEM_TYPE_MARKER; + item->u.marker.type = marker_type; + list_init(&item->entry); + hr = PropVariantCopy(&item->u.marker.context, context_value); + if (SUCCEEDED(hr)) + list_add_tail(&stream->items, &item->entry); + else + stream_release_pending_item(stream, item); + + return hr; +} + static HRESULT WINAPI sample_grabber_stream_PlaceMarker(IMFStreamSink *iface, MFSTREAMSINK_MARKER_TYPE marker_type, const PROPVARIANT *marker_value, const PROPVARIANT *context_value) { - FIXME("%p, %d, %p, %p.\n", iface, marker_type, marker_value, context_value); + struct sample_grabber_stream *stream = impl_from_IMFStreamSink(iface); + HRESULT hr = S_OK;
- return E_NOTIMPL; + TRACE("%p, %d, %p, %p.\n", iface, marker_type, marker_value, context_value); + + if (!stream->sink) + return MF_E_STREAMSINK_REMOVED; + + EnterCriticalSection(&stream->cs); + + if (stream->state == SINK_STATE_RUNNING) + hr = stream_place_marker(stream, marker_type, context_value); + + LeaveCriticalSection(&stream->cs); + + return hr; }
static HRESULT WINAPI sample_grabber_stream_Flush(IMFStreamSink *iface) @@ -602,15 +672,15 @@ static HRESULT WINAPI sample_grabber_stream_timer_callback_GetParameters(IMFAsyn return E_NOTIMPL; }
-static struct scheduled_sample *stream_get_next_sample(struct sample_grabber_stream *stream) +static struct scheduled_item *stream_get_next_item(struct sample_grabber_stream *stream) { - struct scheduled_sample *sample = NULL; + struct scheduled_item *item = NULL; struct list *e;
- if ((e = list_head(&stream->samples))) - sample = LIST_ENTRY(e, struct scheduled_sample, entry); + if ((e = list_head(&stream->items))) + item = LIST_ENTRY(e, struct scheduled_item, entry);
- return sample; + return item; }
static void sample_grabber_stream_request_sample(struct sample_grabber_stream *stream) @@ -621,25 +691,38 @@ static void sample_grabber_stream_request_sample(struct sample_grabber_stream *s static HRESULT WINAPI sample_grabber_stream_timer_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result) { struct sample_grabber_stream *stream = impl_from_IMFAsyncCallback(iface); - struct scheduled_sample *sample; + struct scheduled_item *item; HRESULT hr;
EnterCriticalSection(&stream->cs);
/* Report and schedule next. */ - if (stream->sink && (sample = stream_get_next_sample(stream))) + if (stream->sink && (item = stream_get_next_item(stream))) { - if (FAILED(hr = sample_grabber_report_sample(stream->sink, sample->sample))) - WARN("Failed to report a sample, hr %#x.\n", hr); - - stream_release_pending_entry(stream, sample); - - if ((sample = stream_get_next_sample(stream))) + while (item) { - if (FAILED(hr = stream_schedule_sample(stream, sample))) - WARN("Failed to schedule a sample, hr %#x.\n", hr); + switch (item->type) + { + case ITEM_TYPE_SAMPLE: + if (FAILED(hr = sample_grabber_report_sample(stream->sink, item->u.sample))) + WARN("Failed to report a sample, hr %#x.\n", hr); + stream_release_pending_item(stream, item); + item = stream_get_next_item(stream); + if (item && item->type == ITEM_TYPE_SAMPLE) + { + if (FAILED(hr = stream_schedule_sample(stream, item))) + WARN("Failed to schedule a sample, hr %#x.\n", hr); + sample_grabber_stream_request_sample(stream); + item = NULL; + } + break; + case ITEM_TYPE_MARKER: + sample_grabber_stream_report_marker(stream, &item->u.marker.context, S_OK); + stream_release_pending_item(stream, item); + item = stream_get_next_item(stream); + break; + } } - sample_grabber_stream_request_sample(stream); }
LeaveCriticalSection(&stream->cs); @@ -1132,7 +1215,7 @@ static HRESULT sample_grabber_create_stream(struct sample_grabber *sink, struct object->refcount = 1; object->sink = sink; IMFMediaSink_AddRef(&object->sink->IMFMediaSink_iface); - list_init(&object->samples); + list_init(&object->items); InitializeCriticalSection(&object->cs);
if (FAILED(hr = MFCreateEventQueue(&object->event_queue)))
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/samplegrabber.c | 41 +++++++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 8 deletions(-)
diff --git a/dlls/mf/samplegrabber.c b/dlls/mf/samplegrabber.c index ed07116a4e..9cf94654e5 100644 --- a/dlls/mf/samplegrabber.c +++ b/dlls/mf/samplegrabber.c @@ -171,7 +171,7 @@ static ULONG WINAPI sample_grabber_stream_AddRef(IMFStreamSink *iface) return refcount; }
-static void stream_release_pending_item(struct sample_grabber_stream *stream, struct scheduled_item *item) +static void stream_release_pending_item(struct scheduled_item *item) { list_remove(&item->entry); switch (item->type) @@ -211,7 +211,7 @@ static ULONG WINAPI sample_grabber_stream_Release(IMFStreamSink *iface) } LIST_FOR_EACH_ENTRY_SAFE(item, next_item, &stream->items, struct scheduled_item, entry) { - stream_release_pending_item(stream, item); + stream_release_pending_item(item); } DeleteCriticalSection(&stream->cs); heap_free(stream); @@ -392,7 +392,7 @@ static HRESULT stream_queue_sample(struct sample_grabber_stream *stream, IMFSamp if (SUCCEEDED(hr)) list_add_tail(&stream->items, &item->entry); else - stream_release_pending_item(stream, item); + stream_release_pending_item(item);
return hr; } @@ -459,7 +459,7 @@ static HRESULT stream_place_marker(struct sample_grabber_stream *stream, MFSTREA if (SUCCEEDED(hr)) list_add_tail(&stream->items, &item->entry); else - stream_release_pending_item(stream, item); + stream_release_pending_item(item);
return hr; } @@ -487,9 +487,34 @@ static HRESULT WINAPI sample_grabber_stream_PlaceMarker(IMFStreamSink *iface, MF
static HRESULT WINAPI sample_grabber_stream_Flush(IMFStreamSink *iface) { - FIXME("%p.\n", iface); + struct sample_grabber_stream *stream = impl_from_IMFStreamSink(iface); + struct scheduled_item *item, *next_item;
- return E_NOTIMPL; + TRACE("%p.\n", iface); + + if (!stream->sink) + return MF_E_STREAMSINK_REMOVED; + + EnterCriticalSection(&stream->cs); + + LIST_FOR_EACH_ENTRY_SAFE(item, next_item, &stream->items, struct scheduled_item, entry) + { + /* Samples are discarded, markers are processed immediately. */ + switch (item->type) + { + case ITEM_TYPE_SAMPLE: + break; + case ITEM_TYPE_MARKER: + sample_grabber_stream_report_marker(stream, &item->u.marker.context, E_ABORT); + break; + } + + stream_release_pending_item(item); + } + + LeaveCriticalSection(&stream->cs); + + return S_OK; }
static const IMFStreamSinkVtbl sample_grabber_stream_vtbl = @@ -706,7 +731,7 @@ static HRESULT WINAPI sample_grabber_stream_timer_callback_Invoke(IMFAsyncCallba case ITEM_TYPE_SAMPLE: if (FAILED(hr = sample_grabber_report_sample(stream->sink, item->u.sample))) WARN("Failed to report a sample, hr %#x.\n", hr); - stream_release_pending_item(stream, item); + stream_release_pending_item(item); item = stream_get_next_item(stream); if (item && item->type == ITEM_TYPE_SAMPLE) { @@ -718,7 +743,7 @@ static HRESULT WINAPI sample_grabber_stream_timer_callback_Invoke(IMFAsyncCallba break; case ITEM_TYPE_MARKER: sample_grabber_stream_report_marker(stream, &item->u.marker.context, S_OK); - stream_release_pending_item(stream, item); + stream_release_pending_item(item); item = stream_get_next_item(stream); break; }
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/main.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c index 460f21e3b6..224ba6eaf0 100644 --- a/dlls/mfplat/main.c +++ b/dlls/mfplat/main.c @@ -5982,6 +5982,7 @@ struct event_queue CONDITION_VARIABLE update_event; struct list events; BOOL is_shut_down; + BOOL notified; IMFAsyncResult *subscriber; };
@@ -6105,9 +6106,10 @@ static HRESULT WINAPI eventqueue_GetEvent(IMFMediaEventQueue *iface, DWORD flags
static void queue_notify_subscriber(struct event_queue *queue) { - if (list_empty(&queue->events) || !queue->subscriber) + if (list_empty(&queue->events) || !queue->subscriber || queue->notified) return;
+ queue->notified = TRUE; MFPutWorkItemEx(MFASYNC_CALLBACK_QUEUE_STANDARD, queue->subscriber); }
@@ -6163,6 +6165,7 @@ static HRESULT WINAPI eventqueue_EndGetEvent(IMFMediaEventQueue *iface, IMFAsync if (queue->subscriber) IMFAsyncResult_Release(queue->subscriber); queue->subscriber = NULL; + queue->notified = FALSE; hr = *event ? S_OK : E_FAIL; }
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/main.c | 41 ++++++ dlls/mfplat/mfplat.spec | 1 + dlls/mfplat/tests/mfplat.c | 274 +++++++++++++++++++++++++++++++++++++ include/mfapi.h | 2 + 4 files changed, 318 insertions(+)
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c index 224ba6eaf0..4082f9e2ac 100644 --- a/dlls/mfplat/main.c +++ b/dlls/mfplat/main.c @@ -45,6 +45,17 @@ WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
static LONG platform_lock;
+struct local_handler +{ + struct list entry; + WCHAR *scheme; + IMFActivate *activate; +}; + +static CRITICAL_SECTION local_handlers_section = { NULL, -1, 0, 0, 0, 0 }; + +static struct list local_scheme_handlers = LIST_INIT(local_scheme_handlers); + struct system_clock { IMFClock IMFClock_iface; @@ -7283,3 +7294,33 @@ HRESULT WINAPI MFCancelCreateFile(IUnknown *cancel_cookie)
return hr; } + +/*********************************************************************** + * MFRegisterLocalSchemeHandler (mfplat.@) + */ +HRESULT WINAPI MFRegisterLocalSchemeHandler(const WCHAR *scheme, IMFActivate *activate) +{ + struct local_handler *handler; + + TRACE("%s, %p.\n", debugstr_w(scheme), activate); + + if (!scheme || !activate) + return E_INVALIDARG; + + if (!(handler = heap_alloc(sizeof(*handler)))) + return E_OUTOFMEMORY; + + if (!(handler->scheme = heap_strdupW(scheme))) + { + heap_free(handler); + return E_OUTOFMEMORY; + } + handler->activate = activate; + IMFActivate_AddRef(handler->activate); + + EnterCriticalSection(&local_handlers_section); + list_add_head(&local_scheme_handlers, &handler->entry); + LeaveCriticalSection(&local_handlers_section); + + return S_OK; +} diff --git a/dlls/mfplat/mfplat.spec b/dlls/mfplat/mfplat.spec index 3ebbdbdd4b..2dfa92f202 100644 --- a/dlls/mfplat/mfplat.spec +++ b/dlls/mfplat/mfplat.spec @@ -128,6 +128,7 @@ @ stdcall MFPutWorkItemEx(long ptr) @ stdcall MFPutWorkItemEx2(long long ptr) @ stub MFRecordError +@ stdcall MFRegisterLocalSchemeHandler(wstr ptr) @ stdcall MFRemovePeriodicCallback(long) @ stdcall MFScheduleWorkItem(ptr ptr int64 ptr) @ stdcall MFScheduleWorkItemEx(ptr int64 ptr) diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c index 295863716b..ab651c54f2 100644 --- a/dlls/mfplat/tests/mfplat.c +++ b/dlls/mfplat/tests/mfplat.c @@ -71,6 +71,9 @@ static HRESULT (WINAPI *pMFPutWaitingWorkItem)(HANDLE event, LONG priority, IMFA static HRESULT (WINAPI *pMFAllocateSerialWorkQueue)(DWORD queue, DWORD *serial_queue); static HRESULT (WINAPI *pMFAddPeriodicCallback)(MFPERIODICCALLBACK callback, IUnknown *context, DWORD *key); static HRESULT (WINAPI *pMFRemovePeriodicCallback)(DWORD key); +static HRESULT (WINAPI *pMFRegisterLocalByteStreamHandler)(const WCHAR *extension, const WCHAR *mime, + IMFActivate *activate); +static HRESULT (WINAPI *pMFRegisterLocalSchemeHandler)(const WCHAR *scheme, IMFActivate *activate);
static const WCHAR mp4file[] = {'t','e','s','t','.','m','p','4',0}; static const WCHAR fileschemeW[] = {'f','i','l','e',':','/','/',0}; @@ -517,6 +520,8 @@ static void init_functions(void) X(MFHeapAlloc); X(MFHeapFree); X(MFPutWaitingWorkItem); + X(MFRegisterLocalByteStreamHandler); + X(MFRegisterLocalSchemeHandler); X(MFRemovePeriodicCallback); #undef X
@@ -3320,6 +3325,274 @@ static void test_async_create_file(void) ok(ret, "Failed to delete test file.\n"); }
+struct activate_object +{ + IMFActivate IMFActivate_iface; + LONG refcount; +}; + +static HRESULT WINAPI activate_object_QueryInterface(IMFActivate *iface, REFIID riid, void **obj) +{ + if (IsEqualIID(riid, &IID_IMFActivate) || + IsEqualIID(riid, &IID_IMFAttributes) || + IsEqualIID(riid, &IID_IUnknown)) + { + *obj = iface; + IMFActivate_AddRef(iface); + return S_OK; + } + + *obj = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI activate_object_AddRef(IMFActivate *iface) +{ + return 2; +} + +static ULONG WINAPI activate_object_Release(IMFActivate *iface) +{ + return 1; +} + +static HRESULT WINAPI activate_object_GetItem(IMFActivate *iface, REFGUID key, PROPVARIANT *value) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI activate_object_GetItemType(IMFActivate *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI activate_object_CompareItem(IMFActivate *iface, REFGUID key, REFPROPVARIANT value, BOOL *result) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI activate_object_Compare(IMFActivate *iface, IMFAttributes *theirs, MF_ATTRIBUTES_MATCH_TYPE type, + BOOL *result) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI activate_object_GetUINT32(IMFActivate *iface, REFGUID key, UINT32 *value) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI activate_object_GetUINT64(IMFActivate *iface, REFGUID key, UINT64 *value) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI activate_object_GetDouble(IMFActivate *iface, REFGUID key, double *value) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI activate_object_GetGUID(IMFActivate *iface, REFGUID key, GUID *value) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI activate_object_GetStringLength(IMFActivate *iface, REFGUID key, UINT32 *length) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI activate_object_GetString(IMFActivate *iface, REFGUID key, WCHAR *value, + UINT32 size, UINT32 *length) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI activate_object_GetAllocatedString(IMFActivate *iface, REFGUID key, + WCHAR **value, UINT32 *length) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI activate_object_GetBlobSize(IMFActivate *iface, REFGUID key, UINT32 *size) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI activate_object_GetBlob(IMFActivate *iface, REFGUID key, UINT8 *buf, + UINT32 bufsize, UINT32 *blobsize) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI activate_object_GetAllocatedBlob(IMFActivate *iface, REFGUID key, UINT8 **buf, UINT32 *size) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI activate_object_GetUnknown(IMFActivate *iface, REFGUID key, REFIID riid, void **ppv) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI activate_object_SetItem(IMFActivate *iface, REFGUID key, REFPROPVARIANT value) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI activate_object_DeleteItem(IMFActivate *iface, REFGUID key) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI activate_object_DeleteAllItems(IMFActivate *iface) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI activate_object_SetUINT32(IMFActivate *iface, REFGUID key, UINT32 value) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI activate_object_SetUINT64(IMFActivate *iface, REFGUID key, UINT64 value) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI activate_object_SetDouble(IMFActivate *iface, REFGUID key, double value) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI activate_object_SetGUID(IMFActivate *iface, REFGUID key, REFGUID value) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI activate_object_SetString(IMFActivate *iface, REFGUID key, const WCHAR *value) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI activate_object_SetBlob(IMFActivate *iface, REFGUID key, const UINT8 *buf, UINT32 size) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI activate_object_SetUnknown(IMFActivate *iface, REFGUID key, IUnknown *unknown) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI activate_object_LockStore(IMFActivate *iface) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI activate_object_UnlockStore(IMFActivate *iface) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI activate_object_GetCount(IMFActivate *iface, UINT32 *count) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI activate_object_GetItemByIndex(IMFActivate *iface, UINT32 index, GUID *key, PROPVARIANT *value) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI activate_object_CopyAllItems(IMFActivate *iface, IMFAttributes *dest) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI activate_object_ActivateObject(IMFActivate *iface, REFIID riid, void **obj) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI activate_object_ShutdownObject(IMFActivate *iface) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI activate_object_DetachObject(IMFActivate *iface) +{ + return E_NOTIMPL; +} + +static const IMFActivateVtbl activate_object_vtbl = +{ + activate_object_QueryInterface, + activate_object_AddRef, + activate_object_Release, + activate_object_GetItem, + activate_object_GetItemType, + activate_object_CompareItem, + activate_object_Compare, + activate_object_GetUINT32, + activate_object_GetUINT64, + activate_object_GetDouble, + activate_object_GetGUID, + activate_object_GetStringLength, + activate_object_GetString, + activate_object_GetAllocatedString, + activate_object_GetBlobSize, + activate_object_GetBlob, + activate_object_GetAllocatedBlob, + activate_object_GetUnknown, + activate_object_SetItem, + activate_object_DeleteItem, + activate_object_DeleteAllItems, + activate_object_SetUINT32, + activate_object_SetUINT64, + activate_object_SetDouble, + activate_object_SetGUID, + activate_object_SetString, + activate_object_SetBlob, + activate_object_SetUnknown, + activate_object_LockStore, + activate_object_UnlockStore, + activate_object_GetCount, + activate_object_GetItemByIndex, + activate_object_CopyAllItems, + activate_object_ActivateObject, + activate_object_ShutdownObject, + activate_object_DetachObject, +}; + +static void test_local_handlers(void) +{ + IMFActivate local_activate = { &activate_object_vtbl }; + static const WCHAR localW[] = {'l','o','c','a','l',0}; + HRESULT hr; + + if (!pMFRegisterLocalSchemeHandler) + { + win_skip("Local handlers are not supported.\n"); + return; + } + + hr = pMFRegisterLocalSchemeHandler(NULL, NULL); + ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr); + + hr = pMFRegisterLocalSchemeHandler(localW, NULL); + ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr); + + hr = pMFRegisterLocalSchemeHandler(NULL, &local_activate); + ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr); + + hr = pMFRegisterLocalSchemeHandler(localW, &local_activate); + ok(hr == S_OK, "Failed to register scheme handler, hr %#x.\n", hr); + + hr = pMFRegisterLocalSchemeHandler(localW, &local_activate); + ok(hr == S_OK, "Failed to register scheme handler, hr %#x.\n", hr); +} + START_TEST(mfplat) { CoInitialize(NULL); @@ -3355,6 +3628,7 @@ START_TEST(mfplat) test_wrapped_media_type(); test_MFCreateWaveFormatExFromMFMediaType(); test_async_create_file(); + test_local_handlers();
CoUninitialize(); } diff --git a/include/mfapi.h b/include/mfapi.h index 3809a95142..67977063d5 100644 --- a/include/mfapi.h +++ b/include/mfapi.h @@ -410,6 +410,8 @@ HRESULT WINAPI MFPutWorkItem(DWORD queue, IMFAsyncCallback *callback, IUnknown * HRESULT WINAPI MFPutWorkItem2(DWORD queue, LONG priority, IMFAsyncCallback *callback, IUnknown *state); HRESULT WINAPI MFPutWorkItemEx(DWORD queue, IMFAsyncResult *result); HRESULT WINAPI MFPutWorkItemEx2(DWORD queue, LONG priority, IMFAsyncResult *result); +HRESULT WINAPI MFRegisterLocalByteStreamHandler(const WCHAR *extension, const WCHAR *mime, IMFActivate *activate); +HRESULT WINAPI MFRegisterLocalSchemeHandler(const WCHAR *scheme, IMFActivate *activate); HRESULT WINAPI MFScheduleWorkItem(IMFAsyncCallback *callback, IUnknown *state, INT64 timeout, MFWORKITEM_KEY *key); HRESULT WINAPI MFScheduleWorkItemEx(IMFAsyncResult *result, INT64 timeout, MFWORKITEM_KEY *key); HRESULT WINAPI MFTRegister(CLSID clsid, GUID category, LPWSTR name, UINT32 flags, UINT32 cinput,
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=53404
Your paranoid android.
=== debian9 (32 bit WoW report) ===
mfplat: mfplat.c:2866: Test failed: Unexpected refcount 1. Unhandled exception: page fault on read access to 0x00000009 in 32-bit code (0x7ed89cb2).
Report errors: mfplat:mfplat crashed (c0000005)