1 /* DirectShow Media Detector object (QEDIT.DLL)
3 * Copyright 2008 Google (Lei Zhang, Dan Hipschman)
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
30 #include "qedit_private.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(qedit);
35 typedef struct MediaDetImpl {
36 IMediaDet IMediaDet_iface;
40 IBaseFilter *splitter;
46 static inline MediaDetImpl *impl_from_IMediaDet(IMediaDet *iface)
48 return CONTAINING_RECORD(iface, MediaDetImpl, IMediaDet_iface);
51 static void MD_cleanup(MediaDetImpl *This)
53 if (This->cur_pin) IPin_Release(This->cur_pin);
55 if (This->source) IBaseFilter_Release(This->source);
57 if (This->splitter) IBaseFilter_Release(This->splitter);
58 This->splitter = NULL;
59 if (This->graph) IGraphBuilder_Release(This->graph);
61 This->num_streams = -1;
65 static ULONG WINAPI MediaDet_AddRef(IMediaDet* iface)
67 MediaDetImpl *This = impl_from_IMediaDet(iface);
68 ULONG refCount = InterlockedIncrement(&This->refCount);
69 TRACE("(%p)->() AddRef from %d\n", This, refCount - 1);
73 static ULONG WINAPI MediaDet_Release(IMediaDet* iface)
75 MediaDetImpl *This = impl_from_IMediaDet(iface);
76 ULONG refCount = InterlockedDecrement(&This->refCount);
77 TRACE("(%p)->() Release from %d\n", This, refCount + 1);
89 static HRESULT WINAPI MediaDet_QueryInterface(IMediaDet* iface, REFIID riid,
92 MediaDetImpl *This = impl_from_IMediaDet(iface);
93 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
95 if (IsEqualIID(riid, &IID_IUnknown) ||
96 IsEqualIID(riid, &IID_IMediaDet)) {
97 MediaDet_AddRef(iface);
102 WARN("(%p, %s,%p): not found\n", This, debugstr_guid(riid), ppvObject);
103 return E_NOINTERFACE;
106 static HRESULT WINAPI MediaDet_get_Filter(IMediaDet* iface, IUnknown **pVal)
108 MediaDetImpl *This = impl_from_IMediaDet(iface);
109 FIXME("(%p)->(%p): not implemented!\n", This, pVal);
113 static HRESULT WINAPI MediaDet_put_Filter(IMediaDet* iface, IUnknown *newVal)
115 MediaDetImpl *This = impl_from_IMediaDet(iface);
116 FIXME("(%p)->(%p): not implemented!\n", This, newVal);
120 static HRESULT WINAPI MediaDet_get_OutputStreams(IMediaDet* iface, LONG *pVal)
122 MediaDetImpl *This = impl_from_IMediaDet(iface);
127 TRACE("(%p)\n", This);
132 if (This->num_streams != -1)
134 *pVal = This->num_streams;
140 hr = IBaseFilter_EnumPins(This->splitter, &pins);
144 while (IEnumPins_Next(pins, 1, &pin, NULL) == S_OK)
147 hr = IPin_QueryDirection(pin, &dir);
151 IEnumPins_Release(pins);
155 if (dir == PINDIR_OUTPUT)
158 IEnumPins_Release(pins);
160 This->num_streams = *pVal;
164 static HRESULT WINAPI MediaDet_get_CurrentStream(IMediaDet* iface, LONG *pVal)
166 MediaDetImpl *This = impl_from_IMediaDet(iface);
167 TRACE("(%p)\n", This);
172 *pVal = This->cur_stream;
176 static HRESULT SetCurPin(MediaDetImpl *This, LONG strm)
182 assert(This->splitter);
183 assert(0 <= strm && strm < This->num_streams);
187 IPin_Release(This->cur_pin);
188 This->cur_pin = NULL;
191 hr = IBaseFilter_EnumPins(This->splitter, &pins);
195 while (IEnumPins_Next(pins, 1, &pin, NULL) == S_OK && !This->cur_pin)
198 hr = IPin_QueryDirection(pin, &dir);
202 IEnumPins_Release(pins);
206 if (dir == PINDIR_OUTPUT && strm-- == 0)
211 IEnumPins_Release(pins);
213 assert(This->cur_pin);
217 static HRESULT WINAPI MediaDet_put_CurrentStream(IMediaDet* iface, LONG newVal)
219 MediaDetImpl *This = impl_from_IMediaDet(iface);
222 TRACE("(%p)->(%d)\n", This, newVal);
224 if (This->num_streams == -1)
227 hr = MediaDet_get_OutputStreams(iface, &n);
232 if (newVal < 0 || This->num_streams <= newVal)
235 hr = SetCurPin(This, newVal);
239 This->cur_stream = newVal;
243 static HRESULT WINAPI MediaDet_get_StreamType(IMediaDet* iface, GUID *pVal)
245 MediaDetImpl *This = impl_from_IMediaDet(iface);
246 FIXME("(%p)->(%p): not implemented!\n", This, debugstr_guid(pVal));
250 static HRESULT WINAPI MediaDet_get_StreamTypeB(IMediaDet* iface, BSTR *pVal)
252 MediaDetImpl *This = impl_from_IMediaDet(iface);
253 FIXME("(%p)->(%p): not implemented!\n", This, pVal);
257 static HRESULT WINAPI MediaDet_get_StreamLength(IMediaDet* iface, double *pVal)
259 MediaDetImpl *This = impl_from_IMediaDet(iface);
260 FIXME("(%p): stub!\n", This);
261 return VFW_E_INVALIDMEDIATYPE;
264 static HRESULT WINAPI MediaDet_get_Filename(IMediaDet* iface, BSTR *pVal)
266 MediaDetImpl *This = impl_from_IMediaDet(iface);
267 IFileSourceFilter *file;
271 TRACE("(%p)\n", This);
277 /* MSDN says it should return E_FAIL if no file is open, but tests
282 hr = IBaseFilter_QueryInterface(This->source, &IID_IFileSourceFilter,
287 hr = IFileSourceFilter_GetCurFile(file, &name, NULL);
288 IFileSourceFilter_Release(file);
292 *pVal = SysAllocString(name);
295 return E_OUTOFMEMORY;
300 /* From quartz, 2008/04/07 */
301 static HRESULT GetFilterInfo(IMoniker *pMoniker, GUID *pclsid, VARIANT *pvar)
303 static const WCHAR wszClsidName[] = {'C','L','S','I','D',0};
304 static const WCHAR wszFriendlyName[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0};
305 IPropertyBag *pPropBagCat = NULL;
309 V_VT(pvar) = VT_BSTR;
311 hr = IMoniker_BindToStorage(pMoniker, NULL, NULL, &IID_IPropertyBag,
312 (LPVOID *) &pPropBagCat);
315 hr = IPropertyBag_Read(pPropBagCat, wszClsidName, pvar, NULL);
319 hr = CLSIDFromString(V_UNION(pvar, bstrVal), pclsid);
321 V_VT(pvar) = VT_BSTR;
325 hr = IPropertyBag_Read(pPropBagCat, wszFriendlyName, pvar, NULL);
328 TRACE("Moniker = %s - %s\n", debugstr_guid(pclsid),
329 debugstr_w(V_UNION(pvar, bstrVal)));
332 IPropertyBag_Release(pPropBagCat);
337 static HRESULT GetSplitter(MediaDetImpl *This)
339 IFileSourceFilter *file;
344 IEnumMoniker *filters;
348 IBaseFilter *splitter;
350 IPin *source_pin, *splitter_pin;
353 hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER,
354 &IID_IFilterMapper2, (void **) &map);
358 hr = IBaseFilter_QueryInterface(This->source, &IID_IFileSourceFilter,
362 IFilterMapper2_Release(map);
366 hr = IFileSourceFilter_GetCurFile(file, &name, &mt);
367 IFileSourceFilter_Release(file);
371 IFilterMapper2_Release(map);
374 type[0] = mt.majortype;
375 type[1] = mt.subtype;
376 CoTaskMemFree(mt.pbFormat);
378 hr = IFilterMapper2_EnumMatchingFilters(map, &filters, 0, TRUE,
379 MERIT_UNLIKELY, FALSE, 1, type,
380 NULL, NULL, FALSE, TRUE,
381 0, NULL, NULL, NULL);
382 IFilterMapper2_Release(map);
387 while (IEnumMoniker_Next(filters, 1, &mon, NULL) == S_OK)
389 hr = GetFilterInfo(mon, &clsid, &var);
390 IMoniker_Release(mon);
394 hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER,
395 &IID_IBaseFilter, (void **) &splitter);
402 hr = IGraphBuilder_AddFilter(This->graph, splitter,
403 V_UNION(&var, bstrVal));
405 This->splitter = splitter;
409 hr = IBaseFilter_EnumPins(This->source, &pins);
412 IEnumPins_Next(pins, 1, &source_pin, NULL);
413 IEnumPins_Release(pins);
415 hr = IBaseFilter_EnumPins(splitter, &pins);
418 IPin_Release(source_pin);
421 IEnumPins_Next(pins, 1, &splitter_pin, NULL);
422 IEnumPins_Release(pins);
424 hr = IPin_Connect(source_pin, splitter_pin, NULL);
425 IPin_Release(source_pin);
426 IPin_Release(splitter_pin);
431 IBaseFilter_Release(splitter);
432 This->splitter = NULL;
435 IEnumMoniker_Release(filters);
442 static HRESULT WINAPI MediaDet_put_Filename(IMediaDet* iface, BSTR newVal)
444 static const WCHAR reader[] = {'R','e','a','d','e','r',0};
445 MediaDetImpl *This = impl_from_IMediaDet(iface);
450 TRACE("(%p)->(%s)\n", This, debugstr_w(newVal));
454 WARN("MSDN says not to call this method twice\n");
458 hr = CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
459 &IID_IGraphBuilder, (void **) &gb);
463 hr = IGraphBuilder_AddSourceFilter(gb, newVal, reader, &bf);
466 IGraphBuilder_Release(gb);
472 hr = GetSplitter(This);
476 return MediaDet_put_CurrentStream(iface, 0);
479 static HRESULT WINAPI MediaDet_GetBitmapBits(IMediaDet* iface,
481 LONG *pBufferSize, char *pBuffer,
482 LONG Width, LONG Height)
484 MediaDetImpl *This = impl_from_IMediaDet(iface);
485 FIXME("(%p)->(%f %p %p %d %d): not implemented!\n", This, StreamTime, pBufferSize, pBuffer,
490 static HRESULT WINAPI MediaDet_WriteBitmapBits(IMediaDet* iface,
491 double StreamTime, LONG Width,
492 LONG Height, BSTR Filename)
494 MediaDetImpl *This = impl_from_IMediaDet(iface);
495 FIXME("(%p)->(%f %d %d %p): not implemented!\n", This, StreamTime, Width, Height, Filename);
499 static HRESULT WINAPI MediaDet_get_StreamMediaType(IMediaDet* iface,
502 MediaDetImpl *This = impl_from_IMediaDet(iface);
503 IEnumMediaTypes *types;
507 TRACE("(%p)\n", This);
515 hr = IPin_EnumMediaTypes(This->cur_pin, &types);
518 hr = (IEnumMediaTypes_Next(types, 1, &pmt, NULL) == S_OK
521 IEnumMediaTypes_Release(types);
533 static HRESULT WINAPI MediaDet_GetSampleGrabber(IMediaDet* iface,
534 ISampleGrabber **ppVal)
536 MediaDetImpl *This = impl_from_IMediaDet(iface);
537 FIXME("(%p)->(%p): not implemented!\n", This, ppVal);
541 static HRESULT WINAPI MediaDet_get_FrameRate(IMediaDet* iface, double *pVal)
543 MediaDetImpl *This = impl_from_IMediaDet(iface);
548 TRACE("(%p)\n", This);
553 hr = MediaDet_get_StreamMediaType(iface, &mt);
557 if (!IsEqualGUID(&mt.majortype, &MEDIATYPE_Video))
559 CoTaskMemFree(mt.pbFormat);
560 return VFW_E_INVALIDMEDIATYPE;
563 vh = (VIDEOINFOHEADER *) mt.pbFormat;
564 *pVal = 1.0e7 / (double) vh->AvgTimePerFrame;
566 CoTaskMemFree(mt.pbFormat);
570 static HRESULT WINAPI MediaDet_EnterBitmapGrabMode(IMediaDet* iface,
573 MediaDetImpl *This = impl_from_IMediaDet(iface);
574 FIXME("(%p)->(%f): not implemented!\n", This, SeekTime);
578 static const IMediaDetVtbl IMediaDet_VTable =
580 MediaDet_QueryInterface,
585 MediaDet_get_OutputStreams,
586 MediaDet_get_CurrentStream,
587 MediaDet_put_CurrentStream,
588 MediaDet_get_StreamType,
589 MediaDet_get_StreamTypeB,
590 MediaDet_get_StreamLength,
591 MediaDet_get_Filename,
592 MediaDet_put_Filename,
593 MediaDet_GetBitmapBits,
594 MediaDet_WriteBitmapBits,
595 MediaDet_get_StreamMediaType,
596 MediaDet_GetSampleGrabber,
597 MediaDet_get_FrameRate,
598 MediaDet_EnterBitmapGrabMode,
601 HRESULT MediaDet_create(IUnknown * pUnkOuter, LPVOID * ppv) {
602 MediaDetImpl* obj = NULL;
604 TRACE("(%p,%p)\n", ppv, pUnkOuter);
607 return CLASS_E_NOAGGREGATION;
609 obj = CoTaskMemAlloc(sizeof(MediaDetImpl));
612 return E_OUTOFMEMORY;
614 ZeroMemory(obj, sizeof(MediaDetImpl));
617 obj->IMediaDet_iface.lpVtbl = &IMediaDet_VTable;
620 obj->splitter = NULL;
622 obj->num_streams = -1;