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