winegstreamer: Add stubs for media sink.
This commit is contained in:
parent
b2a099b3ce
commit
0aeab6b7ee
5 changed files with 296 additions and 0 deletions
|
@ -11,6 +11,7 @@ C_SRCS = \
|
|||
color_convert.c \
|
||||
h264_decoder.c \
|
||||
main.c \
|
||||
media_sink.c \
|
||||
media_source.c \
|
||||
mfplat.c \
|
||||
quartz_parser.c \
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "mfidl.h"
|
||||
#include "wine/debug.h"
|
||||
#include "wine/strmbase.h"
|
||||
#include "wine/mfinternal.h"
|
||||
|
||||
#include "unixlib.h"
|
||||
|
||||
|
@ -121,6 +122,7 @@ HRESULT wma_decoder_create(IUnknown *outer, IUnknown **out);
|
|||
HRESULT wmv_decoder_create(IUnknown *outer, IUnknown **out);
|
||||
HRESULT resampler_create(IUnknown *outer, IUnknown **out);
|
||||
HRESULT color_convert_create(IUnknown *outer, IUnknown **out);
|
||||
HRESULT sink_class_factory_create(IUnknown *outer, IUnknown **out);
|
||||
|
||||
bool amt_from_wg_format(AM_MEDIA_TYPE *mt, const struct wg_format *format, bool wm);
|
||||
bool amt_to_wg_format(const AM_MEDIA_TYPE *mt, struct wg_format *format);
|
||||
|
|
|
@ -612,6 +612,7 @@ static struct class_factory wma_decoder_cf = {{&class_factory_vtbl}, wma_decoder
|
|||
static struct class_factory wmv_decoder_cf = {{&class_factory_vtbl}, wmv_decoder_create};
|
||||
static struct class_factory resampler_cf = {{&class_factory_vtbl}, resampler_create};
|
||||
static struct class_factory color_convert_cf = {{&class_factory_vtbl}, color_convert_create};
|
||||
static struct class_factory sink_class_factory_cf = {{&class_factory_vtbl}, sink_class_factory_create};
|
||||
|
||||
HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID iid, void **out)
|
||||
{
|
||||
|
@ -646,6 +647,8 @@ HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID iid, void **out)
|
|||
factory = &resampler_cf;
|
||||
else if (IsEqualGUID(clsid, &CLSID_CColorConvertDMO))
|
||||
factory = &color_convert_cf;
|
||||
else if (IsEqualGUID(clsid, &CLSID_MFMP3SinkClassFactory))
|
||||
factory = &sink_class_factory_cf;
|
||||
else
|
||||
{
|
||||
FIXME("%s not implemented, returning CLASS_E_CLASSNOTAVAILABLE.\n", debugstr_guid(clsid));
|
||||
|
|
284
dlls/winegstreamer/media_sink.c
Normal file
284
dlls/winegstreamer/media_sink.c
Normal file
|
@ -0,0 +1,284 @@
|
|||
/* Gstreamer Media Sink
|
||||
*
|
||||
* Copyright 2023 Ziqing Hui for CodeWeavers
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include "gst_private.h"
|
||||
#include "mferror.h"
|
||||
|
||||
#include "wine/debug.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
|
||||
|
||||
struct media_sink
|
||||
{
|
||||
IMFFinalizableMediaSink IMFFinalizableMediaSink_iface;
|
||||
LONG refcount;
|
||||
CRITICAL_SECTION cs;
|
||||
bool shutdown;
|
||||
|
||||
IMFByteStream *bytestream;
|
||||
};
|
||||
|
||||
static struct media_sink *impl_from_IMFFinalizableMediaSink(IMFFinalizableMediaSink *iface)
|
||||
{
|
||||
return CONTAINING_RECORD(iface, struct media_sink, IMFFinalizableMediaSink_iface);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI media_sink_QueryInterface(IMFFinalizableMediaSink *iface, REFIID riid, void **obj)
|
||||
{
|
||||
TRACE("iface %p, riid %s, obj %p.\n", iface, debugstr_guid(riid), obj);
|
||||
|
||||
if (IsEqualIID(riid, &IID_IMFFinalizableMediaSink) ||
|
||||
IsEqualIID(riid, &IID_IMFMediaSink) ||
|
||||
IsEqualIID(riid, &IID_IUnknown))
|
||||
{
|
||||
*obj = iface;
|
||||
}
|
||||
else
|
||||
{
|
||||
WARN("Unsupported interface %s.\n", debugstr_guid(riid));
|
||||
*obj = NULL;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
IUnknown_AddRef((IUnknown *)*obj);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static ULONG WINAPI media_sink_AddRef(IMFFinalizableMediaSink *iface)
|
||||
{
|
||||
struct media_sink *media_sink = impl_from_IMFFinalizableMediaSink(iface);
|
||||
ULONG refcount = InterlockedIncrement(&media_sink->refcount);
|
||||
TRACE("iface %p, refcount %lu.\n", iface, refcount);
|
||||
return refcount;
|
||||
}
|
||||
|
||||
static ULONG WINAPI media_sink_Release(IMFFinalizableMediaSink *iface)
|
||||
{
|
||||
struct media_sink *media_sink = impl_from_IMFFinalizableMediaSink(iface);
|
||||
ULONG refcount = InterlockedDecrement(&media_sink->refcount);
|
||||
|
||||
TRACE("iface %p, refcount %lu.\n", iface, refcount);
|
||||
|
||||
if (!refcount)
|
||||
{
|
||||
IMFFinalizableMediaSink_Shutdown(iface);
|
||||
IMFByteStream_Release(media_sink->bytestream);
|
||||
media_sink->cs.DebugInfo->Spare[0] = 0;
|
||||
DeleteCriticalSection(&media_sink->cs);
|
||||
free(media_sink);
|
||||
}
|
||||
|
||||
return refcount;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI media_sink_GetCharacteristics(IMFFinalizableMediaSink *iface, DWORD *flags)
|
||||
{
|
||||
FIXME("iface %p, flags %p stub!\n", iface, flags);
|
||||
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI media_sink_AddStreamSink(IMFFinalizableMediaSink *iface, DWORD stream_sink_id,
|
||||
IMFMediaType *media_type, IMFStreamSink **stream_sink)
|
||||
{
|
||||
FIXME("iface %p, stream_sink_id %#lx, media_type %p, stream_sink %p stub!\n",
|
||||
iface, stream_sink_id, media_type, stream_sink);
|
||||
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI media_sink_RemoveStreamSink(IMFFinalizableMediaSink *iface, DWORD stream_sink_id)
|
||||
{
|
||||
FIXME("iface %p, stream_sink_id %#lx stub!\n", iface, stream_sink_id);
|
||||
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI media_sink_GetStreamSinkCount(IMFFinalizableMediaSink *iface, DWORD *count)
|
||||
{
|
||||
FIXME("iface %p, count %p stub!\n", iface, count);
|
||||
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI media_sink_GetStreamSinkByIndex(IMFFinalizableMediaSink *iface, DWORD index,
|
||||
IMFStreamSink **stream)
|
||||
{
|
||||
FIXME("iface %p, index %lu, stream %p stub!\n", iface, index, stream);
|
||||
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI media_sink_GetStreamSinkById(IMFFinalizableMediaSink *iface, DWORD stream_sink_id,
|
||||
IMFStreamSink **stream)
|
||||
{
|
||||
FIXME("iface %p, stream_sink_id %#lx, stream %p stub!\n", iface, stream_sink_id, stream);
|
||||
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI media_sink_SetPresentationClock(IMFFinalizableMediaSink *iface, IMFPresentationClock *clock)
|
||||
{
|
||||
FIXME("iface %p, clock %p stub!\n", iface, clock);
|
||||
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI media_sink_GetPresentationClock(IMFFinalizableMediaSink *iface, IMFPresentationClock **clock)
|
||||
{
|
||||
FIXME("iface %p, clock %p stub!\n", iface, clock);
|
||||
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI media_sink_Shutdown(IMFFinalizableMediaSink *iface)
|
||||
{
|
||||
struct media_sink *media_sink = impl_from_IMFFinalizableMediaSink(iface);
|
||||
|
||||
TRACE("iface %p.\n", iface);
|
||||
|
||||
EnterCriticalSection(&media_sink->cs);
|
||||
|
||||
if (media_sink->shutdown)
|
||||
{
|
||||
LeaveCriticalSection(&media_sink->cs);
|
||||
return MF_E_SHUTDOWN;
|
||||
}
|
||||
|
||||
IMFByteStream_Close(media_sink->bytestream);
|
||||
|
||||
media_sink->shutdown = TRUE;
|
||||
|
||||
LeaveCriticalSection(&media_sink->cs);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI media_sink_BeginFinalize(IMFFinalizableMediaSink *iface, IMFAsyncCallback *callback, IUnknown *state)
|
||||
{
|
||||
FIXME("iface %p, callback %p, state %p stub!\n", iface, callback, state);
|
||||
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI media_sink_EndFinalize(IMFFinalizableMediaSink *iface, IMFAsyncResult *result)
|
||||
{
|
||||
FIXME("iface %p, result %p stub!\n", iface, result);
|
||||
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static const IMFFinalizableMediaSinkVtbl media_sink_vtbl =
|
||||
{
|
||||
media_sink_QueryInterface,
|
||||
media_sink_AddRef,
|
||||
media_sink_Release,
|
||||
media_sink_GetCharacteristics,
|
||||
media_sink_AddStreamSink,
|
||||
media_sink_RemoveStreamSink,
|
||||
media_sink_GetStreamSinkCount,
|
||||
media_sink_GetStreamSinkByIndex,
|
||||
media_sink_GetStreamSinkById,
|
||||
media_sink_SetPresentationClock,
|
||||
media_sink_GetPresentationClock,
|
||||
media_sink_Shutdown,
|
||||
media_sink_BeginFinalize,
|
||||
media_sink_EndFinalize,
|
||||
};
|
||||
|
||||
static HRESULT media_sink_create(IMFByteStream *bytestream, struct media_sink **out)
|
||||
{
|
||||
struct media_sink *media_sink;
|
||||
|
||||
TRACE("bytestream %p, out %p.\n", bytestream, out);
|
||||
|
||||
if (!bytestream)
|
||||
return E_POINTER;
|
||||
|
||||
if (!(media_sink = calloc(1, sizeof(*media_sink))))
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
media_sink->IMFFinalizableMediaSink_iface.lpVtbl = &media_sink_vtbl;
|
||||
media_sink->refcount = 1;
|
||||
InitializeCriticalSection(&media_sink->cs);
|
||||
media_sink->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": cs");
|
||||
IMFByteStream_AddRef((media_sink->bytestream = bytestream));
|
||||
|
||||
*out = media_sink;
|
||||
TRACE("Created media sink %p.\n", media_sink);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI sink_class_factory_QueryInterface(IMFSinkClassFactory *iface, REFIID riid, void **out)
|
||||
{
|
||||
if (IsEqualIID(riid, &IID_IMFSinkClassFactory)
|
||||
|| IsEqualIID(riid, &IID_IUnknown))
|
||||
{
|
||||
*out = iface;
|
||||
IMFSinkClassFactory_AddRef(iface);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
*out = NULL;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
static ULONG WINAPI sink_class_factory_AddRef(IMFSinkClassFactory *iface)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
static ULONG WINAPI sink_class_factory_Release(IMFSinkClassFactory *iface)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI sink_class_factory_CreateMediaSink(IMFSinkClassFactory *iface, IMFByteStream *bytestream,
|
||||
IMFMediaType *video_type, IMFMediaType *audio_type, IMFMediaSink **out)
|
||||
{
|
||||
struct media_sink *media_sink;
|
||||
HRESULT hr;
|
||||
|
||||
TRACE("iface %p, bytestream %p, video_type %p, audio_type %p, out %p.\n",
|
||||
iface, bytestream, video_type, audio_type, out);
|
||||
|
||||
if (FAILED(hr = media_sink_create(bytestream, &media_sink)))
|
||||
return hr;
|
||||
|
||||
*out = (IMFMediaSink *)&media_sink->IMFFinalizableMediaSink_iface;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static const IMFSinkClassFactoryVtbl sink_class_factory_vtbl =
|
||||
{
|
||||
sink_class_factory_QueryInterface,
|
||||
sink_class_factory_AddRef,
|
||||
sink_class_factory_Release,
|
||||
sink_class_factory_CreateMediaSink,
|
||||
};
|
||||
|
||||
static IMFSinkClassFactory sink_class_factory = { &sink_class_factory_vtbl };
|
||||
|
||||
HRESULT sink_class_factory_create(IUnknown *outer, IUnknown **out)
|
||||
{
|
||||
*out = (IUnknown *)&sink_class_factory;
|
||||
return S_OK;
|
||||
}
|
|
@ -111,3 +111,9 @@ coclass CResamplerMediaObject {}
|
|||
uuid(98230571-0087-4204-b020-3282538e57d3)
|
||||
]
|
||||
coclass CColorConvertDMO {}
|
||||
|
||||
[
|
||||
threading(both),
|
||||
uuid(11275a82-5e5a-47fd-a01c-3683c12fb196)
|
||||
]
|
||||
coclass MFMP3SinkClassFactory {}
|
||||
|
|
Loading…
Add table
Reference in a new issue