Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/main.c | 2 +- dlls/mf/samplegrabber.c | 422 +++++++++++++++++++++++++++++++++++++++- dlls/mf/tests/mf.c | 139 ++++++++++++- include/mferror.h | 14 ++ include/mfidl.idl | 32 +++ 5 files changed, 602 insertions(+), 7 deletions(-)
diff --git a/dlls/mf/main.c b/dlls/mf/main.c index b5b4b0e7c8..6db13f19db 100644 --- a/dlls/mf/main.c +++ b/dlls/mf/main.c @@ -395,7 +395,7 @@ static HRESULT WINAPI activate_object_ActivateObject(IMFActivate *iface, REFIID if (FAILED(hr = activate->funcs->create_object((IMFAttributes *)iface, activate->context, &object))) return hr;
- if (!InterlockedCompareExchangePointer((void **)&activate->object, object, NULL)) + if (InterlockedCompareExchangePointer((void **)&activate->object, object, NULL)) IUnknown_Release(object); }
diff --git a/dlls/mf/samplegrabber.c b/dlls/mf/samplegrabber.c index 7b3536467c..997c9db539 100644 --- a/dlls/mf/samplegrabber.c +++ b/dlls/mf/samplegrabber.c @@ -19,6 +19,7 @@ #define COBJMACROS
#include "mfidl.h" +#include "mferror.h" #include "mf_private.h"
#include "wine/debug.h" @@ -26,6 +27,24 @@
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
+struct sample_grabber_stream +{ + IMFStreamSink IMFStreamSink_iface; + LONG refcount; + IMFMediaSink *sink; +}; + +struct sample_grabber +{ + IMFMediaSink IMFMediaSink_iface; + LONG refcount; + IMFSampleGrabberSinkCallback *callback; + IMFMediaType *media_type; + BOOL is_shut_down; + IMFStreamSink *stream; + CRITICAL_SECTION cs; +}; + struct sample_grabber_activate_context { IMFMediaType *media_type; @@ -40,13 +59,412 @@ static void sample_grabber_free_private(void *user_context) heap_free(context); }
-static HRESULT sample_grabber_create_object(IMFAttributes *attributes, void *user_context, IUnknown **obj) +static struct sample_grabber *impl_from_IMFMediaSink(IMFMediaSink *iface) +{ + return CONTAINING_RECORD(iface, struct sample_grabber, IMFMediaSink_iface); +} + +static struct sample_grabber_stream *impl_from_IMFStreamSink(IMFStreamSink *iface) { - FIXME("%p, %p, %p.\n", attributes, user_context, obj); + return CONTAINING_RECORD(iface, struct sample_grabber_stream, IMFStreamSink_iface); +} + +static HRESULT WINAPI sample_grabber_stream_QueryInterface(IMFStreamSink *iface, REFIID riid, void **obj) +{ + struct sample_grabber_stream *stream = impl_from_IMFStreamSink(iface); + + TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj); + + if (IsEqualIID(riid, &IID_IMFStreamSink) || + IsEqualIID(riid, &IID_IUnknown)) + { + *obj = &stream->IMFStreamSink_iface; + } + else + { + WARN("Unsupported %s.\n", debugstr_guid(riid)); + *obj = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown *)*obj); + + return S_OK; +} + +static ULONG WINAPI sample_grabber_stream_AddRef(IMFStreamSink *iface) +{ + struct sample_grabber_stream *stream = impl_from_IMFStreamSink(iface); + ULONG refcount = InterlockedIncrement(&stream->refcount); + + TRACE("%p, refcount %u.\n", iface, refcount); + + return refcount; +} + +static ULONG WINAPI sample_grabber_stream_Release(IMFStreamSink *iface) +{ + struct sample_grabber_stream *stream = impl_from_IMFStreamSink(iface); + ULONG refcount = InterlockedDecrement(&stream->refcount); + + TRACE("%p, refcount %u.\n", iface, refcount); + + if (!refcount) + { + IMFMediaSink_Release(stream->sink); + heap_free(stream); + } + + return refcount; +} + +static HRESULT WINAPI sample_grabber_stream_GetEvent(IMFStreamSink *iface, DWORD flags, IMFMediaEvent **event) +{ + FIXME("%p, %#x, %p.\n", iface, flags, event);
return E_NOTIMPL; }
+static HRESULT WINAPI sample_grabber_stream_BeginGetEvent(IMFStreamSink *iface, IMFAsyncCallback *callback, + IUnknown *state) +{ + FIXME("%p, %p, %p.\n", iface, callback, state); + + return E_NOTIMPL; +} + +static HRESULT WINAPI sample_grabber_stream_EndGetEvent(IMFStreamSink *iface, IMFAsyncResult *result, + IMFMediaEvent **event) +{ + FIXME("%p, %p, %p.\n", iface, result, event); + + return E_NOTIMPL; +} + +static HRESULT WINAPI sample_grabber_stream_QueueEvent(IMFStreamSink *iface, MediaEventType event_type, + REFGUID ext_type, HRESULT hr, const PROPVARIANT *value) +{ + FIXME("%p, %u, %s, %#x, %p.\n", iface, event_type, debugstr_guid(ext_type), hr, value); + + return E_NOTIMPL; +} + +static HRESULT WINAPI sample_grabber_stream_GetMediaSink(IMFStreamSink *iface, IMFMediaSink **sink) +{ + struct sample_grabber_stream *stream = impl_from_IMFStreamSink(iface); + + TRACE("%p, %p.\n", iface, sink); + + *sink = stream->sink; + IMFMediaSink_AddRef(*sink); + + return S_OK; +} + +static HRESULT WINAPI sample_grabber_stream_GetIdentifier(IMFStreamSink *iface, DWORD *identifier) +{ + TRACE("%p, %p.\n", iface, identifier); + + *identifier = 0; + + return S_OK; +} + +static HRESULT WINAPI sample_grabber_stream_GetMediaTypeHandler(IMFStreamSink *iface, IMFMediaTypeHandler **handler) +{ + FIXME("%p, %p.\n", iface, handler); + + return E_NOTIMPL; +} + +static HRESULT WINAPI sample_grabber_stream_ProcessSample(IMFStreamSink *iface, IMFSample *sample) +{ + FIXME("%p, %p.\n", iface, sample); + + return E_NOTIMPL; +} + +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); + + return E_NOTIMPL; +} + +static HRESULT WINAPI sample_grabber_stream_Flush(IMFStreamSink *iface) +{ + FIXME("%p.\n", iface); + + return E_NOTIMPL; +} + +static const IMFStreamSinkVtbl sample_grabber_stream_vtbl = +{ + sample_grabber_stream_QueryInterface, + sample_grabber_stream_AddRef, + sample_grabber_stream_Release, + sample_grabber_stream_GetEvent, + sample_grabber_stream_BeginGetEvent, + sample_grabber_stream_EndGetEvent, + sample_grabber_stream_QueueEvent, + sample_grabber_stream_GetMediaSink, + sample_grabber_stream_GetIdentifier, + sample_grabber_stream_GetMediaTypeHandler, + sample_grabber_stream_ProcessSample, + sample_grabber_stream_PlaceMarker, + sample_grabber_stream_Flush, +}; + +static HRESULT WINAPI sample_grabber_sink_QueryInterface(IMFMediaSink *iface, REFIID riid, void **obj) +{ + struct sample_grabber *grabber = impl_from_IMFMediaSink(iface); + + TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj); + + if (IsEqualIID(riid, &IID_IMFMediaSink) || + IsEqualIID(riid, &IID_IUnknown)) + { + *obj = &grabber->IMFMediaSink_iface; + } + else + { + WARN("Unsupported %s.\n", debugstr_guid(riid)); + *obj = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown *)*obj); + + return S_OK; +} + +static ULONG WINAPI sample_grabber_sink_AddRef(IMFMediaSink *iface) +{ + struct sample_grabber *grabber = impl_from_IMFMediaSink(iface); + ULONG refcount = InterlockedIncrement(&grabber->refcount); + + TRACE("%p, refcount %u.\n", iface, refcount); + + return refcount; +} + +static ULONG WINAPI sample_grabber_sink_Release(IMFMediaSink *iface) +{ + struct sample_grabber *grabber = impl_from_IMFMediaSink(iface); + ULONG refcount = InterlockedDecrement(&grabber->refcount); + + TRACE("%p, refcount %u.\n", iface, refcount); + + if (!refcount) + { + IMFSampleGrabberSinkCallback_Release(grabber->callback); + IMFMediaType_Release(grabber->media_type); + DeleteCriticalSection(&grabber->cs); + heap_free(grabber); + } + + return refcount; +} + +static HRESULT WINAPI sample_grabber_sink_GetCharacteristics(IMFMediaSink *iface, DWORD *flags) +{ + struct sample_grabber *grabber = impl_from_IMFMediaSink(iface); + + TRACE("%p, %p.\n", iface, flags); + + if (grabber->is_shut_down) + return MF_E_SHUTDOWN; + + *flags = MEDIASINK_FIXED_STREAMS; + + return S_OK; +} + +static HRESULT WINAPI sample_grabber_sink_AddStreamSink(IMFMediaSink *iface, DWORD stream_sink_id, + IMFMediaType *media_type, IMFStreamSink **stream_sink) +{ + struct sample_grabber *grabber = impl_from_IMFMediaSink(iface); + + TRACE("%p, %#x, %p, %p.\n", iface, stream_sink_id, media_type, stream_sink); + + return grabber->is_shut_down ? MF_E_SHUTDOWN : MF_E_STREAMSINKS_FIXED; +} + +static HRESULT WINAPI sample_grabber_sink_RemoveStreamSink(IMFMediaSink *iface, DWORD stream_sink_id) +{ + struct sample_grabber *grabber = impl_from_IMFMediaSink(iface); + + TRACE("%p, %#x.\n", iface, stream_sink_id); + + return grabber->is_shut_down ? MF_E_SHUTDOWN : MF_E_STREAMSINKS_FIXED; +} + +static HRESULT WINAPI sample_grabber_sink_GetStreamSinkCount(IMFMediaSink *iface, DWORD *count) +{ + struct sample_grabber *grabber = impl_from_IMFMediaSink(iface); + + TRACE("%p, %p.\n", iface, count); + + if (grabber->is_shut_down) + return MF_E_SHUTDOWN; + + *count = 1; + + return S_OK; +} + +static HRESULT WINAPI sample_grabber_sink_GetStreamSinkByIndex(IMFMediaSink *iface, DWORD index, + IMFStreamSink **stream) +{ + struct sample_grabber *grabber = impl_from_IMFMediaSink(iface); + HRESULT hr = S_OK; + + TRACE("%p, %u, %p.\n", iface, index, stream); + + if (grabber->is_shut_down) + return MF_E_SHUTDOWN; + + EnterCriticalSection(&grabber->cs); + + if (grabber->is_shut_down) + hr = MF_E_SHUTDOWN; + else if (index > 0) + hr = MF_E_INVALIDINDEX; + else + { + *stream = grabber->stream; + IMFStreamSink_AddRef(*stream); + } + + LeaveCriticalSection(&grabber->cs); + + return hr; +} + +static HRESULT WINAPI sample_grabber_sink_GetStreamSinkById(IMFMediaSink *iface, DWORD stream_sink_id, + IMFStreamSink **stream) +{ + struct sample_grabber *grabber = impl_from_IMFMediaSink(iface); + HRESULT hr = S_OK; + + TRACE("%p, %#x, %p.\n", iface, stream_sink_id, stream); + + EnterCriticalSection(&grabber->cs); + + if (grabber->is_shut_down) + hr = MF_E_SHUTDOWN; + else if (stream_sink_id > 0) + hr = MF_E_INVALIDSTREAMNUMBER; + else + { + *stream = grabber->stream; + IMFStreamSink_AddRef(*stream); + } + + LeaveCriticalSection(&grabber->cs); + + return hr; +} + +static HRESULT WINAPI sample_grabber_sink_SetPresentationClock(IMFMediaSink *iface, IMFPresentationClock *clock) +{ + FIXME("%p, %p.\n", iface, clock); + + return E_NOTIMPL; +} + +static HRESULT WINAPI sample_grabber_sink_GetPresentationClock(IMFMediaSink *iface, IMFPresentationClock **clock) +{ + FIXME("%p, %p.\n", iface, clock); + + return E_NOTIMPL; +} + +static HRESULT WINAPI sample_grabber_sink_Shutdown(IMFMediaSink *iface) +{ + struct sample_grabber *grabber = impl_from_IMFMediaSink(iface); + + TRACE("%p.\n", iface); + + if (grabber->is_shut_down) + return MF_E_SHUTDOWN; + + EnterCriticalSection(&grabber->cs); + grabber->is_shut_down = TRUE; + IMFStreamSink_Release(grabber->stream); + grabber->stream = NULL; + EnterCriticalSection(&grabber->cs); + + return E_NOTIMPL; +} + +static const IMFMediaSinkVtbl sample_grabber_sink_vtbl = +{ + sample_grabber_sink_QueryInterface, + sample_grabber_sink_AddRef, + sample_grabber_sink_Release, + sample_grabber_sink_GetCharacteristics, + sample_grabber_sink_AddStreamSink, + sample_grabber_sink_RemoveStreamSink, + sample_grabber_sink_GetStreamSinkCount, + sample_grabber_sink_GetStreamSinkByIndex, + sample_grabber_sink_GetStreamSinkById, + sample_grabber_sink_SetPresentationClock, + sample_grabber_sink_GetPresentationClock, + sample_grabber_sink_Shutdown, +}; + +static HRESULT sample_grabber_create_stream(IMFMediaSink *sink, IMFStreamSink **stream) +{ + struct sample_grabber_stream *object; + + object = heap_alloc_zero(sizeof(*object)); + if (!object) + return E_OUTOFMEMORY; + + object->IMFStreamSink_iface.lpVtbl = &sample_grabber_stream_vtbl; + object->refcount = 1; + object->sink = sink; + IMFMediaSink_AddRef(object->sink); + + *stream = &object->IMFStreamSink_iface; + + return S_OK; +} + +static HRESULT sample_grabber_create_object(IMFAttributes *attributes, void *user_context, IUnknown **obj) +{ + struct sample_grabber_activate_context *context = user_context; + struct sample_grabber *object; + HRESULT hr; + + TRACE("%p, %p, %p.\n", attributes, user_context, obj); + + object = heap_alloc_zero(sizeof(*object)); + if (!object) + return E_OUTOFMEMORY; + + object->IMFMediaSink_iface.lpVtbl = &sample_grabber_sink_vtbl; + object->refcount = 1; + object->callback = context->callback; + IMFSampleGrabberSinkCallback_AddRef(object->callback); + object->media_type = context->media_type; + IMFMediaType_AddRef(object->media_type); + InitializeCriticalSection(&object->cs); + if (FAILED(hr = sample_grabber_create_stream(&object->IMFMediaSink_iface, &object->stream))) + { + IMFMediaSink_Release(&object->IMFMediaSink_iface); + return hr; + } + + *obj = (IUnknown *)&object->IMFMediaSink_iface; + + TRACE("Created %p.\n", *obj); + + return S_OK; +} + static const struct activate_funcs sample_grabber_activate_funcs = { sample_grabber_create_object, diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 37bcb8d029..2987e86f4b 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -1230,7 +1230,6 @@ todo_wine ok(hr == MF_E_TOPO_SINK_ACTIVATES_UNSUPPORTED, "Unexpected hr %#x.\n", hr);
hr = IMFActivate_ActivateObject(sink_activate, &IID_IMFMediaSink, (void **)&sink); -todo_wine ok(hr == S_OK, "Failed to activate, hr %#x.\n", hr);
hr = IMFTopologyNode_SetObject(sink_node, (IUnknown *)sink); @@ -1639,9 +1638,16 @@ static IMFSampleGrabberSinkCallback grabber_callback = { &grabber_callback_vtbl
static void test_sample_grabber(void) { + IMFMediaTypeHandler *handler, *handler2; + IMFStreamSink *stream, *stream2; + IMFClockStateSink *clocksink; + IMFMediaEventGenerator *eg; + IMFMediaSink *sink, *sink2; IMFMediaType *media_type; + DWORD flags, count, id; IMFActivate *activate; ULONG refcount; + IUnknown *unk; HRESULT hr;
hr = MFCreateMediaType(&media_type); @@ -1656,10 +1662,135 @@ static void test_sample_grabber(void) hr = MFCreateSampleGrabberSinkActivate(media_type, &grabber_callback, &activate); ok(hr == S_OK, "Failed to create grabber activate, hr %#x.\n", hr);
- refcount = IMFMediaType_Release(media_type); - ok(refcount == 1, "Unexpected refcount %u.\n", refcount); + hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + + hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink); + ok(hr == S_OK, "Failed to activate object, hr %#x.\n", hr); + + hr = IMFMediaSink_GetCharacteristics(sink, &flags); + ok(hr == S_OK, "Failed to get sink flags, hr %#x.\n", hr); + ok(flags & MEDIASINK_FIXED_STREAMS, "Unexpected flags %#x.\n", flags); + + hr = IMFMediaSink_GetStreamSinkCount(sink, &count); + ok(hr == S_OK, "Failed to get stream count, hr %#x.\n", hr); + ok(count == 1, "Unexpected stream count %u.\n", count); + + EXPECT_REF(sink, 3); + hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream); + ok(hr == S_OK, "Failed to get sink stream, hr %#x.\n", hr); + EXPECT_REF(sink, 3); + EXPECT_REF(stream, 2); + + hr = IMFStreamSink_GetIdentifier(stream, &id); + ok(hr == S_OK, "Failed to get stream id, hr %#x.\n", hr); + ok(id == 0, "Unexpected id %#x.\n", id); + + hr = IMFStreamSink_GetMediaSink(stream, &sink2); + ok(hr == S_OK, "Failed to get media sink, hr %x.\n", hr); + ok(sink2 == sink, "Unexpected sink.\n"); + IMFMediaSink_Release(sink2); + + hr = IMFMediaSink_GetStreamSinkByIndex(sink, 1, &stream2); + ok(hr == MF_E_INVALIDINDEX, "Unexpected hr %#x.\n", hr); + + hr = IMFMediaSink_GetStreamSinkById(sink, 1, &stream2); + ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr); + + hr = IMFMediaSink_AddStreamSink(sink, 1, NULL, &stream2); + ok(hr == MF_E_STREAMSINKS_FIXED, "Unexpected hr %#x.\n", hr); + + hr = IMFMediaSink_RemoveStreamSink(sink, 0); + ok(hr == MF_E_STREAMSINKS_FIXED, "Unexpected hr %#x.\n", hr);
- IMFActivate_Release(activate); + hr = IMFMediaSink_RemoveStreamSink(sink, 1); + ok(hr == MF_E_STREAMSINKS_FIXED, "Unexpected hr %#x.\n", hr); + + hr = IMFMediaSink_QueryInterface(sink, &IID_IMFClockStateSink, (void **)&clocksink); +todo_wine + ok(hr == S_OK, "Failed to get interface, hr %#x.\n", hr); + if (SUCCEEDED(hr)) + IMFClockStateSink_Release(clocksink); + + hr = IMFMediaSink_QueryInterface(sink, &IID_IMFMediaEventGenerator, (void **)&eg); +todo_wine + ok(hr == S_OK, "Failed to get interface, hr %#x.\n", hr); + if (SUCCEEDED(hr)) + IMFMediaEventGenerator_Release(eg); + + hr = IMFMediaSink_QueryInterface(sink, &IID_IMFPresentationTimeSource, (void **)&unk); + ok(hr == E_NOINTERFACE, "Unexpected hr %#x.\n", hr); + + hr = IMFStreamSink_QueryInterface(stream, &IID_IMFMediaTypeHandler, (void **)&handler2); +todo_wine + ok(hr == S_OK, "Failed to get handler interface, hr %#x.\n", hr); + + if (SUCCEEDED(hr)) + { + hr = IMFStreamSink_GetMediaTypeHandler(stream, &handler); + ok(hr == S_OK, "Failed to get type handler, hr %#x.\n", hr); + hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, &count); + ok(hr == S_OK, "Failed to get media type count, hr %#x.\n", hr); + ok(count == 0, "Unexpected count %u.\n", count); + + ok(handler == handler2, "Unexpected handler.\n"); + + IMFMediaTypeHandler_Release(handler); + IMFMediaTypeHandler_Release(handler2); + } + + hr = IMFActivate_ShutdownObject(activate); +todo_wine + ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr); + + hr = IMFMediaSink_Shutdown(sink); + ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr); + + hr = IMFMediaSink_Shutdown(sink); + ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr); + + hr = IMFMediaSink_GetCharacteristics(sink, &flags); + ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr); + + hr = IMFMediaSink_AddStreamSink(sink, 1, NULL, &stream2); + ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr); + + hr = IMFMediaSink_GetStreamSinkCount(sink, &count); + ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr); + + hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream2); + ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#x.\n", hr); + + hr = IMFStreamSink_GetMediaSink(stream, &sink2); + ok(hr == S_OK, "Failed to get media sink, hr %x.\n", hr); + ok(sink2 == sink, "Unexpected sink.\n"); + IMFMediaSink_Release(sink2); + + hr = IMFStreamSink_GetIdentifier(stream, &id); + ok(hr == S_OK, "Failed to get stream id, hr %#x.\n", hr); + ok(id == 0, "Unexpected id %#x.\n", id); + + hr = IMFStreamSink_GetMediaTypeHandler(stream, &handler); +todo_wine + ok(hr == S_OK, "Failed to get type handler, hr %#x.\n", hr); + if (SUCCEEDED(hr)) + { + hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, &count); + ok(hr == S_OK, "Failed to get media type count, hr %#x.\n", hr); + ok(count == 0, "Unexpected count %u.\n", count); + + IMFMediaTypeHandler_Release(handler); + } + + IMFMediaSink_Release(sink); + IMFStreamSink_Release(stream); + + refcount = IMFActivate_Release(activate); + ok(!refcount, "Unexpected refcount %u.\n", refcount); + + IMFMediaType_Release(media_type); }
START_TEST(mf) diff --git a/include/mferror.h b/include/mferror.h index a0acf90f8b..4d3a530734 100644 --- a/include/mferror.h +++ b/include/mferror.h @@ -94,6 +94,20 @@ #define MF_E_MEDIA_SOURCE_NO_STREAMS_SELECTED _HRESULT_TYPEDEF_(0xc00d3e9c) #define MF_E_UNSUPPORTED_CHARACTERISTICS _HRESULT_TYPEDEF_(0xc00d3e9e)
+#define MF_E_STREAMSINK_REMOVED _HRESULT_TYPEDEF_(0xc00d4a38) +#define MF_E_STREAMSINKS_OUT_OF_SYNC _HRESULT_TYPEDEF_(0xc00d4a3a) +#define MF_E_STREAMSINKS_FIXED _HRESULT_TYPEDEF_(0xc00d4a3b) +#define MF_E_STREAMSINK_EXISTS _HRESULT_TYPEDEF_(0xc00d4a3c) +#define MF_E_SAMPLEALLOCATOR_CANCELED _HRESULT_TYPEDEF_(0xc00d4a3d) +#define MF_E_SAMPLEALLOCATOR_EMPTY _HRESULT_TYPEDEF_(0xc00d4a3e) +#define MF_E_SINK_ALREADYSTOPPED _HRESULT_TYPEDEF_(0xc00d4a3f) +#define MF_E_ASF_FILESINK_BITRATE_UNKNOWN _HRESULT_TYPEDEF_(0xc00d4a40) +#define MF_E_SINK_NO_STREAMS _HRESULT_TYPEDEF_(0xc00d4a41) +#define MF_S_SINK_NOT_FINALIZED _HRESULT_TYPEDEF_(0x000d4a42) +#define MF_E_METADATA_TOO_LONG _HRESULT_TYPEDEF_(0xc00d4a43) +#define MF_E_SINK_NO_SAMPLES_PROCESSED _HRESULT_TYPEDEF_(0xc00d4a44) +#define MF_E_SINK_HEADERS_NOT_FOUND _HRESULT_TYPEDEF_(0xc00d4a45) + #define MF_E_TOPO_INVALID_OPTIONAL_NODE _HRESULT_TYPEDEF_(0xc00d520e) #define MF_E_TOPO_CANNOT_FIND_DECRYPTOR _HRESULT_TYPEDEF_(0xc00d5211) #define MF_E_TOPO_CODEC_NOT_FOUND _HRESULT_TYPEDEF_(0xc00d5212) diff --git a/include/mfidl.idl b/include/mfidl.idl index c024e67378..a5882e98e5 100644 --- a/include/mfidl.idl +++ b/include/mfidl.idl @@ -83,6 +83,14 @@ typedef enum _MF_TOPOLOGY_RESOLUTION_STATUS_FLAGS MF_OPTIONAL_NODE_REJECTED_PROTECTED_PROCESS = 0x00000002, } MF_TOPOLOGY_RESOLUTION_STATUS_FLAGS;
+typedef enum _MFSTREAMSINK_MARKER_TYPE +{ + MFSTREAMSINK_MARKER_DEFAULT, + MFSTREAMSINK_MARKER_ENDOFSEGMENT, + MFSTREAMSINK_MARKER_TICK, + MFSTREAMSINK_MARKER_EVENT, +} MFSTREAMSINK_MARKER_TYPE; + [ object, uuid(2eb1e945-18b8-4139-9b1a-d5d584818530), @@ -646,6 +654,13 @@ interface IMFPresentationClock : IMFClock HRESULT Pause(); }
+cpp_quote("#define MEDIASINK_FIXED_STREAMS 0x00000001") +cpp_quote("#define MEDIASINK_CANNOT_MATCH_CLOCK 0x00000002") +cpp_quote("#define MEDIASINK_RATELESS 0x00000004") +cpp_quote("#define MEDIASINK_CLOCK_REQUIRED 0x00000008") +cpp_quote("#define MEDIASINK_CAN_PREROLL 0x00000010") +cpp_quote("#define MEDIASINK_REQUIRE_REFERENCE_MEDIATYPE 0x00000020") + [ object, uuid(6ef2a660-47c0-4666-b13d-cbb717f2fa2c) @@ -666,6 +681,23 @@ interface IMFMediaSink : IUnknown HRESULT Shutdown(); }
+[ + object, + uuid(0a97b3cf-8e7c-4a3d-8f8c-0c843dc247fb), +] +interface IMFStreamSink : IMFMediaEventGenerator +{ + HRESULT GetMediaSink([out] IMFMediaSink **sink); + HRESULT GetIdentifier([out] DWORD *identifier); + HRESULT GetMediaTypeHandler([out] IMFMediaTypeHandler **handler); + HRESULT ProcessSample([in] IMFSample *sample); + HRESULT PlaceMarker( + [in] MFSTREAMSINK_MARKER_TYPE marker_type, + [in] const PROPVARIANT *marker_value, + [in] const PROPVARIANT *context_value); + HRESULT Flush(); +} + typedef enum _MFSHUTDOWN_STATUS { MFSHUTDOWN_INITIATED,