[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