Nikolay Sivov : mfreadwrite/writer: Create archive sink automatically when writer is created from url/bytestream.
Alexandre Julliard
julliard at winehq.org
Thu Aug 11 15:27:34 CDT 2022
Module: wine
Branch: master
Commit: aaebf839f701655361b612cf6e238f80a21d3e8e
URL: https://gitlab.winehq.org/wine/wine/-/commit/aaebf839f701655361b612cf6e238f80a21d3e8e
Author: Nikolay Sivov <nsivov at codeweavers.com>
Date: Thu Aug 11 12:07:41 2022 +0300
mfreadwrite/writer: Create archive sink automatically when writer is created from url/bytestream.
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
dlls/mfreadwrite/Makefile.in | 2 +-
dlls/mfreadwrite/mf_private.h | 4 +-
dlls/mfreadwrite/reader.c | 6 +-
dlls/mfreadwrite/writer.c | 127 +++++++++++++++++++++++++++++++++++-------
4 files changed, 115 insertions(+), 24 deletions(-)
diff --git a/dlls/mfreadwrite/Makefile.in b/dlls/mfreadwrite/Makefile.in
index 440d5ba96cd..552ba6d2638 100644
--- a/dlls/mfreadwrite/Makefile.in
+++ b/dlls/mfreadwrite/Makefile.in
@@ -1,6 +1,6 @@
MODULE = mfreadwrite.dll
IMPORTLIB = mfreadwrite
-IMPORTS = mfuuid uuid mfplat ole32
+IMPORTS = mfuuid uuid mfplat ole32 kernelbase
EXTRADLLFLAGS = -Wb,--prefer-native
diff --git a/dlls/mfreadwrite/mf_private.h b/dlls/mfreadwrite/mf_private.h
index 4e23ab7b3e0..7d8172a383a 100644
--- a/dlls/mfreadwrite/mf_private.h
+++ b/dlls/mfreadwrite/mf_private.h
@@ -16,7 +16,7 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
-extern HRESULT create_sink_writer_from_stream(IMFByteStream *stream, IMFAttributes *attributes,
- REFIID riid, void **out) DECLSPEC_HIDDEN;
+extern HRESULT create_sink_writer_from_url(const WCHAR *url, IMFByteStream *stream,
+ IMFAttributes *attributes, REFIID riid, void **out) DECLSPEC_HIDDEN;
extern HRESULT create_sink_writer_from_sink(IMFMediaSink *sink, IMFAttributes *attributes,
REFIID riid, void **out) DECLSPEC_HIDDEN;
diff --git a/dlls/mfreadwrite/reader.c b/dlls/mfreadwrite/reader.c
index 76348458fac..aac59deba76 100644
--- a/dlls/mfreadwrite/reader.c
+++ b/dlls/mfreadwrite/reader.c
@@ -2594,6 +2594,10 @@ static HRESULT WINAPI readwrite_factory_CreateInstanceFromURL(IMFReadWriteClassF
{
return create_source_reader_from_url(url, attributes, &IID_IMFSourceReader, out);
}
+ else if (IsEqualGUID(clsid, &CLSID_MFSinkWriter))
+ {
+ return create_sink_writer_from_url(url, NULL, attributes, riid, out);
+ }
FIXME("Unsupported %s.\n", debugstr_guid(clsid));
@@ -2621,7 +2625,7 @@ static HRESULT WINAPI readwrite_factory_CreateInstanceFromObject(IMFReadWriteCla
hr = IUnknown_QueryInterface(unk, &IID_IMFMediaSink, (void **)&sink);
if (stream)
- hr = create_sink_writer_from_stream(stream, attributes, riid, out);
+ hr = create_sink_writer_from_url(NULL, stream, attributes, riid, out);
else if (sink)
hr = create_sink_writer_from_sink(sink, attributes, riid, out);
diff --git a/dlls/mfreadwrite/writer.c b/dlls/mfreadwrite/writer.c
index 1f33c0791ec..a3f77c4415b 100644
--- a/dlls/mfreadwrite/writer.c
+++ b/dlls/mfreadwrite/writer.c
@@ -22,6 +22,8 @@
#include "mfapi.h"
#include "mfidl.h"
#include "mfreadwrite.h"
+#include "pathcch.h"
+#include "wine/mfinternal.h"
#include "mf_private.h"
#include "wine/debug.h"
@@ -196,24 +198,6 @@ HRESULT create_sink_writer_from_sink(IMFMediaSink *sink, IMFAttributes *attribut
return hr;
}
-HRESULT create_sink_writer_from_stream(IMFByteStream *stream, IMFAttributes *attributes,
- REFIID riid, void **out)
-{
- struct sink_writer *object;
- HRESULT hr;
-
- object = malloc(sizeof(*object));
- if (!object)
- return E_OUTOFMEMORY;
-
- object->IMFSinkWriter_iface.lpVtbl = &sink_writer_vtbl;
- object->refcount = 1;
-
- hr = IMFSinkWriter_QueryInterface(&object->IMFSinkWriter_iface, riid, out);
- IMFSinkWriter_Release(&object->IMFSinkWriter_iface);
- return hr;
-}
-
/***********************************************************************
* MFCreateSinkWriterFromMediaSink (mfreadwrite.@)
*/
@@ -224,13 +208,116 @@ HRESULT WINAPI MFCreateSinkWriterFromMediaSink(IMFMediaSink *sink, IMFAttributes
return create_sink_writer_from_sink(sink, attributes, &IID_IMFSinkWriter, (void **)writer);
}
+static HRESULT sink_writer_get_sink_factory_class(const WCHAR *url, IMFAttributes *attributes, CLSID *clsid)
+{
+ static const struct extension_map
+ {
+ const WCHAR *ext;
+ const GUID *guid;
+ } ext_map[] =
+ {
+ { L".mp4", &MFTranscodeContainerType_MPEG4 },
+ { L".mp3", &MFTranscodeContainerType_MP3 },
+ { L".wav", &MFTranscodeContainerType_WAVE },
+ { L".avi", &MFTranscodeContainerType_AVI },
+ };
+ static const struct
+ {
+ const GUID *container;
+ const CLSID *clsid;
+ } class_map[] =
+ {
+ { &MFTranscodeContainerType_MPEG4, &CLSID_MFMPEG4SinkClassFactory },
+ { &MFTranscodeContainerType_MP3, &CLSID_MFMP3SinkClassFactory },
+ { &MFTranscodeContainerType_WAVE, &CLSID_MFWAVESinkClassFactory },
+ { &MFTranscodeContainerType_AVI, &CLSID_MFAVISinkClassFactory },
+ };
+ const WCHAR *extension;
+ GUID container;
+ unsigned int i;
+
+ if (url)
+ {
+ if (!attributes || FAILED(IMFAttributes_GetGUID(attributes, &MF_TRANSCODE_CONTAINERTYPE, &container)))
+ {
+ const struct extension_map *map = NULL;
+
+ if (FAILED(PathCchFindExtension(url, PATHCCH_MAX_CCH, &extension))) return E_INVALIDARG;
+ if (!extension || !*extension) return E_INVALIDARG;
+
+ for (i = 0; i < ARRAY_SIZE(ext_map); ++i)
+ {
+ map = &ext_map[i];
+
+ if (!wcsicmp(map->ext, extension))
+ break;
+ }
+
+ if (!map)
+ {
+ WARN("Couldn't find container type for extension %s.\n", debugstr_w(extension));
+ return E_INVALIDARG;
+ }
+
+ container = *map->guid;
+ }
+ }
+ else
+ {
+ if (!attributes) return E_INVALIDARG;
+ if (FAILED(IMFAttributes_GetGUID(attributes, &MF_TRANSCODE_CONTAINERTYPE, &container))) return E_INVALIDARG;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(class_map); ++i)
+ {
+ if (IsEqualGUID(&container, &class_map[i].container))
+ {
+ *clsid = *class_map[i].clsid;
+ return S_OK;
+ }
+ }
+
+ WARN("Couldn't find factory class for container %s.\n", debugstr_guid(&container));
+ return E_INVALIDARG;
+}
+
+HRESULT create_sink_writer_from_url(const WCHAR *url, IMFByteStream *bytestream, IMFAttributes *attributes,
+ REFIID riid, void **out)
+{
+ IMFSinkClassFactory *factory;
+ IMFMediaSink *sink;
+ CLSID clsid;
+ HRESULT hr;
+
+ if (FAILED(hr = sink_writer_get_sink_factory_class(url, attributes, &clsid))) return hr;
+
+ if (FAILED(hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IMFSinkClassFactory, (void **)&factory)))
+ {
+ WARN("Failed to create a sink factory, hr %#lx.\n", hr);
+ return hr;
+ }
+
+ hr = IMFSinkClassFactory_CreateMediaSink(factory, bytestream, NULL, NULL, &sink);
+ IMFSinkClassFactory_Release(factory);
+ if (FAILED(hr))
+ {
+ WARN("Failed to create a sink, hr %#lx.\n", hr);
+ return hr;
+ }
+
+ hr = create_sink_writer_from_sink(sink, attributes, riid, out);
+ IMFMediaSink_Release(sink);
+
+ return hr;
+}
+
/***********************************************************************
* MFCreateSinkWriterFromURL (mfreadwrite.@)
*/
HRESULT WINAPI MFCreateSinkWriterFromURL(const WCHAR *url, IMFByteStream *bytestream, IMFAttributes *attributes,
IMFSinkWriter **writer)
{
- FIXME("%s, %p, %p, %p.\n", debugstr_w(url), bytestream, attributes, writer);
+ TRACE("%s, %p, %p, %p.\n", debugstr_w(url), bytestream, attributes, writer);
- return E_NOTIMPL;
+ return create_sink_writer_from_url(url, bytestream, attributes, &IID_IMFSinkWriter, (void **)writer);
}
More information about the wine-cvs
mailing list