mf: Add sample grabber sink stub.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
e73d824121
commit
dfd8457fd5
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
FIXME("%p, %p, %p.\n", attributes, user_context, obj);
|
||||
return CONTAINING_RECORD(iface, struct sample_grabber, IMFMediaSink_iface);
|
||||
}
|
||||
|
||||
static struct sample_grabber_stream *impl_from_IMFStreamSink(IMFStreamSink *iface)
|
||||
{
|
||||
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,
|
||||
|
|
|
@ -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);
|
||||
|
||||
IMFActivate_Release(activate);
|
||||
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);
|
||||
|
||||
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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -89,6 +89,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),
|
||||
|
@ -652,6 +660,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)
|
||||
|
@ -672,6 +687,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,
|
||||
|
|
Loading…
Reference in New Issue