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 const IMediaDetVtbl
*MediaDet_Vtbl
;
40 IBaseFilter
*splitter
;
46 static void MD_cleanup(MediaDetImpl
*This
)
48 if (This
->cur_pin
) IPin_Release(This
->cur_pin
);
50 if (This
->source
) IBaseFilter_Release(This
->source
);
52 if (This
->splitter
) IBaseFilter_Release(This
->splitter
);
53 This
->splitter
= NULL
;
54 if (This
->graph
) IGraphBuilder_Release(This
->graph
);
56 This
->num_streams
= -1;
60 static ULONG WINAPI
MediaDet_AddRef(IMediaDet
* iface
)
62 MediaDetImpl
*This
= (MediaDetImpl
*)iface
;
63 ULONG refCount
= InterlockedIncrement(&This
->refCount
);
64 TRACE("(%p)->() AddRef from %d\n", This
, refCount
- 1);
68 static ULONG WINAPI
MediaDet_Release(IMediaDet
* iface
)
70 MediaDetImpl
*This
= (MediaDetImpl
*)iface
;
71 ULONG refCount
= InterlockedDecrement(&This
->refCount
);
72 TRACE("(%p)->() Release from %d\n", This
, refCount
+ 1);
84 static HRESULT WINAPI
MediaDet_QueryInterface(IMediaDet
* iface
, REFIID riid
,
87 MediaDetImpl
*This
= (MediaDetImpl
*)iface
;
88 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppvObject
);
90 if (IsEqualIID(riid
, &IID_IUnknown
) ||
91 IsEqualIID(riid
, &IID_IMediaDet
)) {
92 MediaDet_AddRef(iface
);
97 WARN("(%p, %s,%p): not found\n", This
, debugstr_guid(riid
), ppvObject
);
101 static HRESULT WINAPI
MediaDet_get_Filter(IMediaDet
* iface
, IUnknown
**pVal
)
103 MediaDetImpl
*This
= (MediaDetImpl
*)iface
;
104 FIXME("(%p)->(%p): not implemented!\n", This
, pVal
);
108 static HRESULT WINAPI
MediaDet_put_Filter(IMediaDet
* iface
, IUnknown
*newVal
)
110 MediaDetImpl
*This
= (MediaDetImpl
*)iface
;
111 FIXME("(%p)->(%p): not implemented!\n", This
, newVal
);
115 static HRESULT WINAPI
MediaDet_get_OutputStreams(IMediaDet
* iface
, LONG
*pVal
)
117 MediaDetImpl
*This
= (MediaDetImpl
*)iface
;
122 TRACE("(%p)\n", This
);
127 if (This
->num_streams
!= -1)
129 *pVal
= This
->num_streams
;
135 hr
= IBaseFilter_EnumPins(This
->splitter
, &pins
);
139 while (IEnumPins_Next(pins
, 1, &pin
, NULL
) == S_OK
)
142 hr
= IPin_QueryDirection(pin
, &dir
);
146 IEnumPins_Release(pins
);
150 if (dir
== PINDIR_OUTPUT
)
153 IEnumPins_Release(pins
);
155 This
->num_streams
= *pVal
;
159 static HRESULT WINAPI
MediaDet_get_CurrentStream(IMediaDet
* iface
, LONG
*pVal
)
161 MediaDetImpl
*This
= (MediaDetImpl
*)iface
;
162 TRACE("(%p)\n", This
);
167 *pVal
= This
->cur_stream
;
171 static HRESULT
SetCurPin(MediaDetImpl
*This
, LONG strm
)
177 assert(This
->splitter
);
178 assert(0 <= strm
&& strm
< This
->num_streams
);
182 IPin_Release(This
->cur_pin
);
183 This
->cur_pin
= NULL
;
186 hr
= IBaseFilter_EnumPins(This
->splitter
, &pins
);
190 while (IEnumPins_Next(pins
, 1, &pin
, NULL
) == S_OK
&& !This
->cur_pin
)
193 hr
= IPin_QueryDirection(pin
, &dir
);
197 IEnumPins_Release(pins
);
201 if (dir
== PINDIR_OUTPUT
&& strm
-- == 0)
206 IEnumPins_Release(pins
);
208 assert(This
->cur_pin
);
212 static HRESULT WINAPI
MediaDet_put_CurrentStream(IMediaDet
* iface
, LONG newVal
)
214 MediaDetImpl
*This
= (MediaDetImpl
*)iface
;
217 TRACE("(%p)->(%d)\n", This
, newVal
);
219 if (This
->num_streams
== -1)
222 hr
= MediaDet_get_OutputStreams(iface
, &n
);
227 if (newVal
< 0 || This
->num_streams
<= newVal
)
230 hr
= SetCurPin(This
, newVal
);
234 This
->cur_stream
= newVal
;
238 static HRESULT WINAPI
MediaDet_get_StreamType(IMediaDet
* iface
, GUID
*pVal
)
240 MediaDetImpl
*This
= (MediaDetImpl
*)iface
;
241 FIXME("(%p)->(%p): not implemented!\n", This
, debugstr_guid(pVal
));
245 static HRESULT WINAPI
MediaDet_get_StreamTypeB(IMediaDet
* iface
, BSTR
*pVal
)
247 MediaDetImpl
*This
= (MediaDetImpl
*)iface
;
248 FIXME("(%p)->(%p): not implemented!\n", This
, pVal
);
252 static HRESULT WINAPI
MediaDet_get_StreamLength(IMediaDet
* iface
, double *pVal
)
254 MediaDetImpl
*This
= (MediaDetImpl
*)iface
;
255 FIXME("(%p): stub!\n", This
);
256 return VFW_E_INVALIDMEDIATYPE
;
259 static HRESULT WINAPI
MediaDet_get_Filename(IMediaDet
* iface
, BSTR
*pVal
)
261 MediaDetImpl
*This
= (MediaDetImpl
*)iface
;
262 IFileSourceFilter
*file
;
266 TRACE("(%p)\n", This
);
272 /* MSDN says it should return E_FAIL if no file is open, but tests
277 hr
= IBaseFilter_QueryInterface(This
->source
, &IID_IFileSourceFilter
,
282 hr
= IFileSourceFilter_GetCurFile(file
, &name
, NULL
);
283 IFileSourceFilter_Release(file
);
287 *pVal
= SysAllocString(name
);
290 return E_OUTOFMEMORY
;
295 /* From quartz, 2008/04/07 */
296 static HRESULT
GetFilterInfo(IMoniker
*pMoniker
, GUID
*pclsid
, VARIANT
*pvar
)
298 static const WCHAR wszClsidName
[] = {'C','L','S','I','D',0};
299 static const WCHAR wszFriendlyName
[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0};
300 IPropertyBag
*pPropBagCat
= NULL
;
304 V_VT(pvar
) = VT_BSTR
;
306 hr
= IMoniker_BindToStorage(pMoniker
, NULL
, NULL
, &IID_IPropertyBag
,
307 (LPVOID
*) &pPropBagCat
);
310 hr
= IPropertyBag_Read(pPropBagCat
, wszClsidName
, pvar
, NULL
);
314 hr
= CLSIDFromString(V_UNION(pvar
, bstrVal
), pclsid
);
316 V_VT(pvar
) = VT_BSTR
;
320 hr
= IPropertyBag_Read(pPropBagCat
, wszFriendlyName
, pvar
, NULL
);
323 TRACE("Moniker = %s - %s\n", debugstr_guid(pclsid
),
324 debugstr_w(V_UNION(pvar
, bstrVal
)));
327 IPropertyBag_Release(pPropBagCat
);
332 static HRESULT
GetSplitter(MediaDetImpl
*This
)
334 IFileSourceFilter
*file
;
339 IEnumMoniker
*filters
;
343 IBaseFilter
*splitter
;
345 IPin
*source_pin
, *splitter_pin
;
348 hr
= CoCreateInstance(&CLSID_FilterMapper2
, NULL
, CLSCTX_INPROC_SERVER
,
349 &IID_IFilterMapper2
, (void **) &map
);
353 hr
= IBaseFilter_QueryInterface(This
->source
, &IID_IFileSourceFilter
,
357 IFilterMapper2_Release(map
);
361 hr
= IFileSourceFilter_GetCurFile(file
, &name
, &mt
);
362 IFileSourceFilter_Release(file
);
366 IFilterMapper2_Release(map
);
369 type
[0] = mt
.majortype
;
370 type
[1] = mt
.subtype
;
371 CoTaskMemFree(mt
.pbFormat
);
373 hr
= IFilterMapper2_EnumMatchingFilters(map
, &filters
, 0, TRUE
,
374 MERIT_UNLIKELY
, FALSE
, 1, type
,
375 NULL
, NULL
, FALSE
, TRUE
,
376 0, NULL
, NULL
, NULL
);
377 IFilterMapper2_Release(map
);
381 hr
= IEnumMoniker_Next(filters
, 1, &mon
, NULL
);
382 IEnumMoniker_Release(filters
);
383 if (hr
!= S_OK
) /* No matches, what do we do? */
384 return E_NOINTERFACE
;
386 hr
= GetFilterInfo(mon
, &clsid
, &var
);
387 IMoniker_Release(mon
);
391 hr
= CoCreateInstance(&clsid
, NULL
, CLSCTX_INPROC_SERVER
,
392 &IID_IBaseFilter
, (void **) &splitter
);
399 hr
= IGraphBuilder_AddFilter(This
->graph
, splitter
,
400 V_UNION(&var
, bstrVal
));
404 IBaseFilter_Release(splitter
);
407 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
);
433 static HRESULT WINAPI
MediaDet_put_Filename(IMediaDet
* iface
, BSTR newVal
)
435 static const WCHAR reader
[] = {'R','e','a','d','e','r',0};
436 MediaDetImpl
*This
= (MediaDetImpl
*)iface
;
441 TRACE("(%p)->(%s)\n", This
, debugstr_w(newVal
));
445 WARN("MSDN says not to call this method twice\n");
449 hr
= CoCreateInstance(&CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
,
450 &IID_IGraphBuilder
, (void **) &gb
);
454 hr
= IGraphBuilder_AddSourceFilter(gb
, newVal
, reader
, &bf
);
457 IGraphBuilder_Release(gb
);
463 hr
= GetSplitter(This
);
467 return MediaDet_put_CurrentStream(iface
, 0);
470 static HRESULT WINAPI
MediaDet_GetBitmapBits(IMediaDet
* iface
,
472 LONG
*pBufferSize
, char *pBuffer
,
473 LONG Width
, LONG Height
)
475 MediaDetImpl
*This
= (MediaDetImpl
*)iface
;
476 FIXME("(%p)->(%f %p %p %d %d): not implemented!\n", This
, StreamTime
, pBufferSize
, pBuffer
,
481 static HRESULT WINAPI
MediaDet_WriteBitmapBits(IMediaDet
* iface
,
482 double StreamTime
, LONG Width
,
483 LONG Height
, BSTR Filename
)
485 MediaDetImpl
*This
= (MediaDetImpl
*)iface
;
486 FIXME("(%p)->(%f %d %d %p): not implemented!\n", This
, StreamTime
, Width
, Height
, Filename
);
490 static HRESULT WINAPI
MediaDet_get_StreamMediaType(IMediaDet
* iface
,
493 MediaDetImpl
*This
= (MediaDetImpl
*)iface
;
494 IEnumMediaTypes
*types
;
498 TRACE("(%p)\n", This
);
506 hr
= IPin_EnumMediaTypes(This
->cur_pin
, &types
);
509 hr
= (IEnumMediaTypes_Next(types
, 1, &pmt
, NULL
) == S_OK
512 IEnumMediaTypes_Release(types
);
524 static HRESULT WINAPI
MediaDet_GetSampleGrabber(IMediaDet
* iface
,
525 ISampleGrabber
**ppVal
)
527 MediaDetImpl
*This
= (MediaDetImpl
*)iface
;
528 FIXME("(%p)->(%p): not implemented!\n", This
, ppVal
);
532 static HRESULT WINAPI
MediaDet_get_FrameRate(IMediaDet
* iface
, double *pVal
)
534 MediaDetImpl
*This
= (MediaDetImpl
*)iface
;
539 TRACE("(%p)\n", This
);
544 hr
= MediaDet_get_StreamMediaType(iface
, &mt
);
548 if (!IsEqualGUID(&mt
.majortype
, &MEDIATYPE_Video
))
550 CoTaskMemFree(mt
.pbFormat
);
551 return VFW_E_INVALIDMEDIATYPE
;
554 vh
= (VIDEOINFOHEADER
*) mt
.pbFormat
;
555 *pVal
= 1.0e7
/ (double) vh
->AvgTimePerFrame
;
557 CoTaskMemFree(mt
.pbFormat
);
561 static HRESULT WINAPI
MediaDet_EnterBitmapGrabMode(IMediaDet
* iface
,
564 MediaDetImpl
*This
= (MediaDetImpl
*)iface
;
565 FIXME("(%p)->(%f): not implemented!\n", This
, SeekTime
);
569 static const IMediaDetVtbl IMediaDet_VTable
=
571 MediaDet_QueryInterface
,
576 MediaDet_get_OutputStreams
,
577 MediaDet_get_CurrentStream
,
578 MediaDet_put_CurrentStream
,
579 MediaDet_get_StreamType
,
580 MediaDet_get_StreamTypeB
,
581 MediaDet_get_StreamLength
,
582 MediaDet_get_Filename
,
583 MediaDet_put_Filename
,
584 MediaDet_GetBitmapBits
,
585 MediaDet_WriteBitmapBits
,
586 MediaDet_get_StreamMediaType
,
587 MediaDet_GetSampleGrabber
,
588 MediaDet_get_FrameRate
,
589 MediaDet_EnterBitmapGrabMode
,
592 HRESULT
MediaDet_create(IUnknown
* pUnkOuter
, LPVOID
* ppv
) {
593 MediaDetImpl
* obj
= NULL
;
595 TRACE("(%p,%p)\n", ppv
, pUnkOuter
);
598 return CLASS_E_NOAGGREGATION
;
600 obj
= CoTaskMemAlloc(sizeof(MediaDetImpl
));
603 return E_OUTOFMEMORY
;
605 ZeroMemory(obj
, sizeof(MediaDetImpl
));
608 obj
->MediaDet_Vtbl
= &IMediaDet_VTable
;
611 obj
->splitter
= NULL
;
613 obj
->num_streams
= -1;