[4/5] qedit: Implement IMediaDet_get_OutputStreams.

Dan Hipschman dsh at linux.ucla.edu
Tue Apr 8 18:53:52 CDT 2008


---
 dlls/qedit/mediadet.c           |  170 ++++++++++++++++++++++++++++++++++++++-
 dlls/qedit/tests/mediadet.c     |   90 ++++++++++++++++++--
 dlls/qedit/tests/qedit.rc       |    6 +-
 dlls/qedit/tests/rc.h           |   29 +++++++
 dlls/qedit/tests/test_sound.avi |  Bin 0 -> 6070 bytes
 5 files changed, 282 insertions(+), 13 deletions(-)
 create mode 100644 dlls/qedit/tests/rc.h
 create mode 100644 dlls/qedit/tests/test_sound.avi

diff --git a/dlls/qedit/mediadet.c b/dlls/qedit/mediadet.c
index 062c105..3a7cc1b 100644
--- a/dlls/qedit/mediadet.c
+++ b/dlls/qedit/mediadet.c
@@ -36,12 +36,15 @@ typedef struct MediaDetImpl {
     LONG refCount;
     IGraphBuilder *graph;
     IBaseFilter *source;
+    IBaseFilter *splitter;
 } MediaDetImpl;
 
 static void MD_cleanup(MediaDetImpl *This)
 {
     if (This->source) IBaseFilter_Release(This->source);
     This->source = NULL;
+    if (This->splitter) IBaseFilter_Release(This->splitter);
+    This->splitter = NULL;
     if (This->graph) IGraphBuilder_Release(This->graph);
     This->graph = NULL;
 }
@@ -104,8 +107,38 @@ static HRESULT WINAPI MediaDet_put_Filter(IMediaDet* iface, IUnknown *newVal)
 static HRESULT WINAPI MediaDet_get_OutputStreams(IMediaDet* iface, long *pVal)
 {
     MediaDetImpl *This = (MediaDetImpl *)iface;
-    FIXME("(%p)->(%p): not implemented!\n", This, pVal);
-    return E_NOTIMPL;
+    IEnumPins *pins;
+    IPin *pin;
+    HRESULT hr;
+
+    TRACE("(%p)\n", This);
+
+    if (!This->splitter)
+        return E_INVALIDARG;
+
+    *pVal = 0;
+
+    hr = IBaseFilter_EnumPins(This->splitter, &pins);
+    if (FAILED(hr))
+        return hr;
+
+    while (IEnumPins_Next(pins, 1, &pin, NULL) == S_OK)
+    {
+        PIN_DIRECTION dir;
+        hr = IPin_QueryDirection(pin, &dir);
+        IPin_Release(pin);
+        if (FAILED(hr))
+        {
+            IEnumPins_Release(pins);
+            return hr;
+        }
+
+        if (dir == PINDIR_OUTPUT)
+            ++*pVal;
+    }
+    IEnumPins_Release(pins);
+
+    return S_OK;
 }
 
 static HRESULT WINAPI MediaDet_get_CurrentStream(IMediaDet* iface, long *pVal)
@@ -179,6 +212,136 @@ static HRESULT WINAPI MediaDet_get_Filename(IMediaDet* iface, BSTR *pVal)
     return S_OK;
 }
 
+/* From quartz, 2008/04/07 */
+static HRESULT GetFilterInfo(IMoniker *pMoniker, GUID *pclsid, VARIANT *pvar)
+{
+    static const WCHAR wszClsidName[] = {'C','L','S','I','D',0};
+    static const WCHAR wszFriendlyName[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0};
+    IPropertyBag *pPropBagCat = NULL;
+    HRESULT hr;
+
+    VariantInit(pvar);
+    V_VT(pvar) = VT_BSTR;
+
+    hr = IMoniker_BindToStorage(pMoniker, NULL, NULL, &IID_IPropertyBag,
+                                (LPVOID *) &pPropBagCat);
+
+    if (SUCCEEDED(hr))
+        hr = IPropertyBag_Read(pPropBagCat, wszClsidName, pvar, NULL);
+
+    if (SUCCEEDED(hr))
+        hr = CLSIDFromString(V_UNION(pvar, bstrVal), pclsid);
+
+    if (SUCCEEDED(hr))
+        hr = IPropertyBag_Read(pPropBagCat, wszFriendlyName, pvar, NULL);
+
+    if (SUCCEEDED(hr))
+        TRACE("Moniker = %s - %s\n", debugstr_guid(pclsid),
+              debugstr_w(V_UNION(pvar, bstrVal)));
+
+    if (pPropBagCat)
+        IPropertyBag_Release(pPropBagCat);
+
+    return hr;
+}
+
+static HRESULT GetSplitter(MediaDetImpl *This)
+{
+    IFileSourceFilter *file;
+    LPOLESTR name;
+    AM_MEDIA_TYPE mt;
+    GUID type[2];
+    IFilterMapper2 *map;
+    IEnumMoniker *filters;
+    IMoniker *mon;
+    VARIANT var;
+    GUID clsid;
+    IBaseFilter *splitter;
+    IEnumPins *pins;
+    IPin *source_pin, *splitter_pin;
+    HRESULT hr;
+
+    hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER,
+                          &IID_IFilterMapper2, (void **) &map);
+    if (FAILED(hr))
+        return hr;
+
+    hr = IBaseFilter_QueryInterface(This->source, &IID_IFileSourceFilter,
+                                    (void **) &file);
+    if (FAILED(hr))
+    {
+        IFilterMapper2_Release(map);
+        return hr;
+    }
+
+    hr = IFileSourceFilter_GetCurFile(file, &name, &mt);
+    IFileSourceFilter_Release(file);
+    CoTaskMemFree(name);
+    if (FAILED(hr))
+    {
+        IFilterMapper2_Release(map);
+        return hr;
+    }
+    type[0] = mt.majortype;
+    type[1] = mt.subtype;
+    CoTaskMemFree(mt.pbFormat);
+
+    hr = IFilterMapper2_EnumMatchingFilters(map, &filters, 0, TRUE,
+                                            MERIT_UNLIKELY, FALSE, 1, type,
+                                            NULL, NULL, FALSE, TRUE,
+                                            0, NULL, NULL, NULL);
+    IFilterMapper2_Release(map);
+    if (FAILED(hr))
+        return hr;
+
+    hr = IEnumMoniker_Next(filters, 1, &mon, NULL);
+    IEnumMoniker_Release(filters);
+    if (hr != S_OK)    /* No matches, what do we do?  */
+        return E_NOINTERFACE;
+
+    hr = GetFilterInfo(mon, &clsid, &var);
+    IMoniker_Release(mon);
+    if (FAILED(hr))
+        return hr;
+
+    hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER,
+                          &IID_IBaseFilter, (void **) &splitter);
+    if (FAILED(hr))
+        return hr;
+
+    hr = IGraphBuilder_AddFilter(This->graph, splitter,
+                                 V_UNION(&var, bstrVal));
+    if (FAILED(hr))
+    {
+        IBaseFilter_Release(splitter);
+        return hr;
+    }
+    This->splitter = splitter;
+
+    hr = IBaseFilter_EnumPins(This->source, &pins);
+    if (FAILED(hr))
+        return hr;
+    IEnumPins_Next(pins, 1, &source_pin, NULL);
+    IEnumPins_Release(pins);
+
+    hr = IBaseFilter_EnumPins(splitter, &pins);
+    if (FAILED(hr))
+    {
+        IPin_Release(source_pin);
+        return hr;
+    }
+    IEnumPins_Next(pins, 1, &splitter_pin, NULL);
+    IEnumPins_Release(pins);
+
+    hr = IPin_Connect(source_pin, splitter_pin, NULL);
+    IPin_Release(source_pin);
+    IPin_Release(splitter_pin);
+    if (FAILED(hr))
+        return hr;
+
+    return S_OK;
+}
+
 static HRESULT WINAPI MediaDet_put_Filename(IMediaDet* iface, BSTR newVal)
 {
     static const WCHAR reader[] = {'R','e','a','d','e','r',0};
@@ -209,7 +372,7 @@ static HRESULT WINAPI MediaDet_put_Filename(IMediaDet* iface, BSTR newVal)
 
     This->graph = gb;
     This->source = bf;
-    return S_OK;
+    return GetSplitter(This);
 }
 
 static HRESULT WINAPI MediaDet_GetBitmapBits(IMediaDet* iface,
@@ -305,6 +468,7 @@ HRESULT MediaDet_create(IUnknown * pUnkOuter, LPVOID * ppv) {
     obj->MediaDet_Vtbl = &IMediaDet_VTable;
     obj->graph = NULL;
     obj->source = NULL;
+    obj->splitter = NULL;
     *ppv = obj;
 
     return S_OK;
diff --git a/dlls/qedit/tests/mediadet.c b/dlls/qedit/tests/mediadet.c
index 3e6e48f..237dfb9 100644
--- a/dlls/qedit/tests/mediadet.c
+++ b/dlls/qedit/tests/mediadet.c
@@ -26,10 +26,12 @@
 #include "uuids.h"
 #include "wine/test.h"
 #include "qedit.h"
+#include "rc.h"
 
 static WCHAR test_avi_filename[MAX_PATH];
+static WCHAR test_sound_avi_filename[MAX_PATH];
 
-static BOOL init_tests(void)
+static BOOL unpack_avi_file(int id, WCHAR name[MAX_PATH])
 {
     static WCHAR temp_path[MAX_PATH];
     static WCHAR prefix[] = {'D','E','S',0};
@@ -40,7 +42,7 @@ static BOOL init_tests(void)
     DWORD size, written;
     HANDLE fh;
 
-    res = FindResourceW(NULL, (LPWSTR) 1, (LPWSTR) 256);
+    res = FindResourceW(NULL, (LPWSTR) id, (LPWSTR) AVI_RES_TYPE);
     if (!res)
         return FALSE;
 
@@ -60,14 +62,14 @@ static BOOL init_tests(void)
         return FALSE;
 
     /* We might end up relying on the extension here, so .TMP is no good.  */
-    if (!GetTempFileNameW(temp_path, prefix, 0, test_avi_filename))
+    if (!GetTempFileNameW(temp_path, prefix, 0, name))
         return FALSE;
 
-    DeleteFileW(test_avi_filename);
-    lstrcpyW(test_avi_filename + lstrlenW(test_avi_filename) - 3, avi);
+    DeleteFileW(name);
+    lstrcpyW(name + lstrlenW(name) - 3, avi);
 
-    fh = CreateFileW(test_avi_filename, GENERIC_WRITE, 0, NULL,
-                     CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
+    fh = CreateFileW(name, GENERIC_WRITE, 0, NULL, CREATE_NEW,
+                     FILE_ATTRIBUTE_NORMAL, NULL);
     if (fh == INVALID_HANDLE_VALUE)
         return FALSE;
 
@@ -79,6 +81,12 @@ static BOOL init_tests(void)
     return TRUE;
 }
 
+static BOOL init_tests(void)
+{
+    return unpack_avi_file(TEST_AVI_RES, test_avi_filename)
+        && unpack_avi_file(TEST_SOUND_AVI_RES, test_sound_avi_filename);
+}
+
 static void test_mediadet(void)
 {
     HRESULT hr;
@@ -87,7 +95,9 @@ static void test_mediadet(void)
     long nstrms = 0;
     long strm;
     AM_MEDIA_TYPE mt;
+    int flags;
 
+    /* test.avi has one video stream.  */
     hr = CoCreateInstance(&CLSID_MediaDet, NULL, CLSCTX_INPROC_SERVER,
             &IID_IMediaDet, (LPVOID*)&pM);
     ok(hr == S_OK, "CoCreateInstance failed with %x\n", hr);
@@ -105,14 +115,19 @@ static void test_mediadet(void)
     ok(hr == S_OK, "IMediaDet_get_Filename\n");
     ok(filename == NULL, "IMediaDet_get_Filename\n");
 
+    nstrms = -1;
+    hr = IMediaDet_get_OutputStreams(pM, &nstrms);
+    ok(hr == E_INVALIDARG, "IMediaDet_get_OutputStreams\n");
+    ok(nstrms == -1, "IMediaDet_get_OutputStreams\n");
+
     filename = SysAllocString(test_avi_filename);
     hr = IMediaDet_put_Filename(pM, filename);
     ok(hr == S_OK, "IMediaDet_put_Filename -> %x\n", hr);
     SysFreeString(filename);
 
     hr = IMediaDet_get_OutputStreams(pM, &nstrms);
-    todo_wine ok(hr == S_OK, "IMediaDet_get_OutputStreams\n");
-    todo_wine ok(nstrms == 1, "IMediaDet_get_OutputStreams\n");
+    ok(hr == S_OK, "IMediaDet_get_OutputStreams\n");
+    ok(nstrms == 1, "IMediaDet_get_OutputStreams\n");
 
     filename = NULL;
     hr = IMediaDet_get_Filename(pM, &filename);
@@ -142,6 +157,63 @@ static void test_mediadet(void)
     ok(hr == 0, "IMediaDet_Release returned: %x\n", hr);
 
     DeleteFileW(test_avi_filename);
+
+    /* test_sound.avi has one video stream and one audio stream.  */
+    hr = CoCreateInstance(&CLSID_MediaDet, NULL, CLSCTX_INPROC_SERVER,
+            &IID_IMediaDet, (LPVOID*)&pM);
+    ok(hr == S_OK, "CoCreateInstance failed with %x\n", hr);
+    ok(pM != NULL, "pM is NULL\n");
+
+    filename = SysAllocString(test_sound_avi_filename);
+    hr = IMediaDet_put_Filename(pM, filename);
+    ok(hr == S_OK, "IMediaDet_put_Filename -> %x\n", hr);
+    SysFreeString(filename);
+
+    hr = IMediaDet_get_OutputStreams(pM, &nstrms);
+    ok(hr == S_OK, "IMediaDet_get_OutputStreams\n");
+    ok(nstrms == 2, "IMediaDet_get_OutputStreams\n");
+
+    filename = NULL;
+    hr = IMediaDet_get_Filename(pM, &filename);
+    ok(hr == S_OK, "IMediaDet_get_Filename\n");
+    ok(lstrcmpW(filename, test_sound_avi_filename) == 0,
+       "IMediaDet_get_Filename\n");
+    SysFreeString(filename);
+
+    /* I don't know if the stream order is deterministic.  Just check
+       for both an audio and video stream.  */
+    flags = 0;
+
+    hr = IMediaDet_put_CurrentStream(pM, 0);
+    todo_wine ok(hr == S_OK, "IMediaDet_put_CurrentStream\n");
+
+    ZeroMemory(&mt, sizeof mt);
+    hr = IMediaDet_get_StreamMediaType(pM, &mt);
+    todo_wine ok(hr == S_OK, "IMediaDet_get_StreamMediaType\n");
+    flags += (IsEqualGUID(&mt.majortype, &MEDIATYPE_Video)
+              ? 1
+              : (IsEqualGUID(&mt.majortype, &MEDIATYPE_Audio)
+                 ? 2
+                 : 0));
+
+    hr = IMediaDet_put_CurrentStream(pM, 1);
+    todo_wine ok(hr == S_OK, "IMediaDet_put_CurrentStream\n");
+
+    ZeroMemory(&mt, sizeof mt);
+    hr = IMediaDet_get_StreamMediaType(pM, &mt);
+    todo_wine ok(hr == S_OK, "IMediaDet_get_StreamMediaType\n");
+    flags += (IsEqualGUID(&mt.majortype, &MEDIATYPE_Video)
+              ? 1
+              : (IsEqualGUID(&mt.majortype, &MEDIATYPE_Audio)
+                 ? 2
+                 : 0));
+
+    todo_wine ok(flags == 3, "IMediaDet_get_StreamMediaType\n");
+
+    hr = IMediaDet_Release(pM);
+    ok(hr == 0, "IMediaDet_Release returned: %x\n", hr);
+
+    DeleteFileW(test_sound_avi_filename);
 }
 
 START_TEST(mediadet)
diff --git a/dlls/qedit/tests/qedit.rc b/dlls/qedit/tests/qedit.rc
index b138624..a0b8b80 100644
--- a/dlls/qedit/tests/qedit.rc
+++ b/dlls/qedit/tests/qedit.rc
@@ -18,5 +18,9 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
+#include "rc.h"
+
 /* @makedep: test.avi */
-1 256 test.avi
+TEST_AVI_RES       AVI_RES_TYPE test.avi
+/* @makedep: sound_test.avi */
+TEST_SOUND_AVI_RES AVI_RES_TYPE test_sound.avi
diff --git a/dlls/qedit/tests/rc.h b/dlls/qedit/tests/rc.h
new file mode 100644
index 0000000..1de98d9
--- /dev/null
+++ b/dlls/qedit/tests/rc.h
@@ -0,0 +1,29 @@
+/*
+ * Resource identifiers for qedit tests.
+ *
+ * Copyright 2008 Google (Dan Hipschman)
+ *
+ * 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
+ */
+
+#ifndef QEDIT_TESTS_RC_INCLUDED
+#define QEDIT_TESTS_RC_INCLUDED
+
+#define TEST_AVI_RES       1
+#define TEST_SOUND_AVI_RES 2
+
+#define AVI_RES_TYPE 256
+
+#endif /* QEDIT_TESTS_RC_INCLUDED */
diff --git a/dlls/qedit/tests/test_sound.avi b/dlls/qedit/tests/test_sound.avi
new file mode 100644
index 0000000000000000000000000000000000000000..9edbb8de7f856d9f739dd3c9d75805b386942c0a
GIT binary patch
literal 6070
zcmWIYbaPuL&cNUp=BeQ0862X<$iR at 1Qk0WemYHF}z`(Ge4JZHw0-OvCFdh?BOaVws
zK-tI?$gC2eKygV?4iJOQD$7hMjtnz2LRJSdj|(aQHk%DumVrS5XgW}Tng&o9gcX1o
zWFIpF4+F at o1{NR(4S?*91BxNromiSu3^pH0Er?&P4G|~;azGdakkx_g76OYgg4Kf5
zGcs at hML@PV0BKJ at H-FDyw-93>+t)QOIX at +}NWsX;K+n=r+fdJ-peWV6q^QzJJGrdb
z$iTqNz|hcK*Pt}1G_R!8LJt at gUZH;8Wqb?_(Y6Y{0Xd14K;2oTdD#jni6x1O3bwJM
z;-ld(njS{;#b`M&S`Lhs1Eb}@XgM%i4vdxqqvgP8IWSrdP+kszda-Tn3=FyXWtj$s
z<w>AEaD9DUdDgt|Eo_mId;ZQWoG2jHIP2N}`<)sL++mx4|9>z+m4VxD>CgX<XK698
zJJ0|A|HV>c1~%LNPyb)9ab#fB?)dQk%}!SaX3f%<|KA-5WMq`def<B;)dUu1$*8OU
zKHM(g<l*x^_~qr3Ha!(ClitgJUe0h5<Fsf!`}_IgKpAe6vV%V#FH2PwFwWZa<?iZY
z9WnFdrO&Rft2dLkjG2A=%&HE1ZI9T#qkC5MxLbuLwQX86zbn)`Hnn}}tQqy;N!j^b
z6FRy|Q;W-LyIUI?^RjDdTYDO7t1`1|n|dZRRTZb at HnvZk+)$C9QrOrreM)UvR(eHK
z=hWWn@~pJF&hBaLMP=D}9qk<xn~ICGOFBAwCp8oo<dn8|_4U=27Uh(+cJ=qxl@%0J
zHg`?ztS-qftnKKZ&|F%SU)l(gDJd+dXzlLrt}QMsu4(D&ZmTUTDXVSm>}aYfEvsp0
zX=`q%s;H{1Z)<I=t*EMRY;I|&GB8L<W&n<S{2v9QAut*OBQ^vYM!|><fy|T&Lj~YC
bGN>jN0MekrZBUI2svki7I?&KGu$}+_GFY=_

literal 0
HcmV?d00001

-- 
1.5.3.7




More information about the wine-patches mailing list