Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenmediadet.c
Go to the documentation of this file.
00001 /* DirectShow Media Detector object (QEDIT.DLL) 00002 * 00003 * Copyright 2008 Google (Lei Zhang, Dan Hipschman) 00004 * 00005 * This library is free software; you can redistribute it and/or 00006 * modify it under the terms of the GNU Lesser General Public 00007 * License as published by the Free Software Foundation; either 00008 * version 2.1 of the License, or (at your option) any later version. 00009 * 00010 * This library is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 * Lesser General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU Lesser General Public 00016 * License along with this library; if not, write to the Free Software 00017 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00018 */ 00019 00020 #include <assert.h> 00021 #include <stdarg.h> 00022 00023 #define COBJMACROS 00024 00025 #include "windef.h" 00026 #include "winbase.h" 00027 #include "winuser.h" 00028 #include "ole2.h" 00029 00030 #include "qedit_private.h" 00031 #include "wine/debug.h" 00032 00033 WINE_DEFAULT_DEBUG_CHANNEL(qedit); 00034 00035 typedef struct MediaDetImpl { 00036 const IMediaDetVtbl *MediaDet_Vtbl; 00037 LONG refCount; 00038 IGraphBuilder *graph; 00039 IBaseFilter *source; 00040 IBaseFilter *splitter; 00041 LONG num_streams; 00042 LONG cur_stream; 00043 IPin *cur_pin; 00044 } MediaDetImpl; 00045 00046 static void MD_cleanup(MediaDetImpl *This) 00047 { 00048 if (This->cur_pin) IPin_Release(This->cur_pin); 00049 This->cur_pin = NULL; 00050 if (This->source) IBaseFilter_Release(This->source); 00051 This->source = NULL; 00052 if (This->splitter) IBaseFilter_Release(This->splitter); 00053 This->splitter = NULL; 00054 if (This->graph) IGraphBuilder_Release(This->graph); 00055 This->graph = NULL; 00056 This->num_streams = -1; 00057 This->cur_stream = 0; 00058 } 00059 00060 static ULONG WINAPI MediaDet_AddRef(IMediaDet* iface) 00061 { 00062 MediaDetImpl *This = (MediaDetImpl *)iface; 00063 ULONG refCount = InterlockedIncrement(&This->refCount); 00064 TRACE("(%p)->() AddRef from %d\n", This, refCount - 1); 00065 return refCount; 00066 } 00067 00068 static ULONG WINAPI MediaDet_Release(IMediaDet* iface) 00069 { 00070 MediaDetImpl *This = (MediaDetImpl *)iface; 00071 ULONG refCount = InterlockedDecrement(&This->refCount); 00072 TRACE("(%p)->() Release from %d\n", This, refCount + 1); 00073 00074 if (refCount == 0) 00075 { 00076 MD_cleanup(This); 00077 CoTaskMemFree(This); 00078 return 0; 00079 } 00080 00081 return refCount; 00082 } 00083 00084 static HRESULT WINAPI MediaDet_QueryInterface(IMediaDet* iface, REFIID riid, 00085 void **ppvObject) 00086 { 00087 MediaDetImpl *This = (MediaDetImpl *)iface; 00088 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject); 00089 00090 if (IsEqualIID(riid, &IID_IUnknown) || 00091 IsEqualIID(riid, &IID_IMediaDet)) { 00092 MediaDet_AddRef(iface); 00093 *ppvObject = This; 00094 return S_OK; 00095 } 00096 *ppvObject = NULL; 00097 WARN("(%p, %s,%p): not found\n", This, debugstr_guid(riid), ppvObject); 00098 return E_NOINTERFACE; 00099 } 00100 00101 static HRESULT WINAPI MediaDet_get_Filter(IMediaDet* iface, IUnknown **pVal) 00102 { 00103 MediaDetImpl *This = (MediaDetImpl *)iface; 00104 FIXME("(%p)->(%p): not implemented!\n", This, pVal); 00105 return E_NOTIMPL; 00106 } 00107 00108 static HRESULT WINAPI MediaDet_put_Filter(IMediaDet* iface, IUnknown *newVal) 00109 { 00110 MediaDetImpl *This = (MediaDetImpl *)iface; 00111 FIXME("(%p)->(%p): not implemented!\n", This, newVal); 00112 return E_NOTIMPL; 00113 } 00114 00115 static HRESULT WINAPI MediaDet_get_OutputStreams(IMediaDet* iface, LONG *pVal) 00116 { 00117 MediaDetImpl *This = (MediaDetImpl *)iface; 00118 IEnumPins *pins; 00119 IPin *pin; 00120 HRESULT hr; 00121 00122 TRACE("(%p)\n", This); 00123 00124 if (!This->splitter) 00125 return E_INVALIDARG; 00126 00127 if (This->num_streams != -1) 00128 { 00129 *pVal = This->num_streams; 00130 return S_OK; 00131 } 00132 00133 *pVal = 0; 00134 00135 hr = IBaseFilter_EnumPins(This->splitter, &pins); 00136 if (FAILED(hr)) 00137 return hr; 00138 00139 while (IEnumPins_Next(pins, 1, &pin, NULL) == S_OK) 00140 { 00141 PIN_DIRECTION dir; 00142 hr = IPin_QueryDirection(pin, &dir); 00143 IPin_Release(pin); 00144 if (FAILED(hr)) 00145 { 00146 IEnumPins_Release(pins); 00147 return hr; 00148 } 00149 00150 if (dir == PINDIR_OUTPUT) 00151 ++*pVal; 00152 } 00153 IEnumPins_Release(pins); 00154 00155 This->num_streams = *pVal; 00156 return S_OK; 00157 } 00158 00159 static HRESULT WINAPI MediaDet_get_CurrentStream(IMediaDet* iface, LONG *pVal) 00160 { 00161 MediaDetImpl *This = (MediaDetImpl *)iface; 00162 TRACE("(%p)\n", This); 00163 00164 if (!pVal) 00165 return E_POINTER; 00166 00167 *pVal = This->cur_stream; 00168 return S_OK; 00169 } 00170 00171 static HRESULT SetCurPin(MediaDetImpl *This, LONG strm) 00172 { 00173 IEnumPins *pins; 00174 IPin *pin; 00175 HRESULT hr; 00176 00177 assert(This->splitter); 00178 assert(0 <= strm && strm < This->num_streams); 00179 00180 if (This->cur_pin) 00181 { 00182 IPin_Release(This->cur_pin); 00183 This->cur_pin = NULL; 00184 } 00185 00186 hr = IBaseFilter_EnumPins(This->splitter, &pins); 00187 if (FAILED(hr)) 00188 return hr; 00189 00190 while (IEnumPins_Next(pins, 1, &pin, NULL) == S_OK && !This->cur_pin) 00191 { 00192 PIN_DIRECTION dir; 00193 hr = IPin_QueryDirection(pin, &dir); 00194 if (FAILED(hr)) 00195 { 00196 IPin_Release(pin); 00197 IEnumPins_Release(pins); 00198 return hr; 00199 } 00200 00201 if (dir == PINDIR_OUTPUT && strm-- == 0) 00202 This->cur_pin = pin; 00203 else 00204 IPin_Release(pin); 00205 } 00206 IEnumPins_Release(pins); 00207 00208 assert(This->cur_pin); 00209 return S_OK; 00210 } 00211 00212 static HRESULT WINAPI MediaDet_put_CurrentStream(IMediaDet* iface, LONG newVal) 00213 { 00214 MediaDetImpl *This = (MediaDetImpl *)iface; 00215 HRESULT hr; 00216 00217 TRACE("(%p)->(%d)\n", This, newVal); 00218 00219 if (This->num_streams == -1) 00220 { 00221 LONG n; 00222 hr = MediaDet_get_OutputStreams(iface, &n); 00223 if (FAILED(hr)) 00224 return hr; 00225 } 00226 00227 if (newVal < 0 || This->num_streams <= newVal) 00228 return E_INVALIDARG; 00229 00230 hr = SetCurPin(This, newVal); 00231 if (FAILED(hr)) 00232 return hr; 00233 00234 This->cur_stream = newVal; 00235 return S_OK; 00236 } 00237 00238 static HRESULT WINAPI MediaDet_get_StreamType(IMediaDet* iface, GUID *pVal) 00239 { 00240 MediaDetImpl *This = (MediaDetImpl *)iface; 00241 FIXME("(%p)->(%p): not implemented!\n", This, debugstr_guid(pVal)); 00242 return E_NOTIMPL; 00243 } 00244 00245 static HRESULT WINAPI MediaDet_get_StreamTypeB(IMediaDet* iface, BSTR *pVal) 00246 { 00247 MediaDetImpl *This = (MediaDetImpl *)iface; 00248 FIXME("(%p)->(%p): not implemented!\n", This, pVal); 00249 return E_NOTIMPL; 00250 } 00251 00252 static HRESULT WINAPI MediaDet_get_StreamLength(IMediaDet* iface, double *pVal) 00253 { 00254 MediaDetImpl *This = (MediaDetImpl *)iface; 00255 FIXME("(%p): stub!\n", This); 00256 return VFW_E_INVALIDMEDIATYPE; 00257 } 00258 00259 static HRESULT WINAPI MediaDet_get_Filename(IMediaDet* iface, BSTR *pVal) 00260 { 00261 MediaDetImpl *This = (MediaDetImpl *)iface; 00262 IFileSourceFilter *file; 00263 LPOLESTR name; 00264 HRESULT hr; 00265 00266 TRACE("(%p)\n", This); 00267 00268 if (!pVal) 00269 return E_POINTER; 00270 00271 *pVal = NULL; 00272 /* MSDN says it should return E_FAIL if no file is open, but tests 00273 show otherwise. */ 00274 if (!This->source) 00275 return S_OK; 00276 00277 hr = IBaseFilter_QueryInterface(This->source, &IID_IFileSourceFilter, 00278 (void **) &file); 00279 if (FAILED(hr)) 00280 return hr; 00281 00282 hr = IFileSourceFilter_GetCurFile(file, &name, NULL); 00283 IFileSourceFilter_Release(file); 00284 if (FAILED(hr)) 00285 return hr; 00286 00287 *pVal = SysAllocString(name); 00288 CoTaskMemFree(name); 00289 if (!*pVal) 00290 return E_OUTOFMEMORY; 00291 00292 return S_OK; 00293 } 00294 00295 /* From quartz, 2008/04/07 */ 00296 static HRESULT GetFilterInfo(IMoniker *pMoniker, GUID *pclsid, VARIANT *pvar) 00297 { 00298 static const WCHAR wszClsidName[] = {'C','L','S','I','D',0}; 00299 static const WCHAR wszFriendlyName[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0}; 00300 IPropertyBag *pPropBagCat = NULL; 00301 HRESULT hr; 00302 00303 VariantInit(pvar); 00304 V_VT(pvar) = VT_BSTR; 00305 00306 hr = IMoniker_BindToStorage(pMoniker, NULL, NULL, &IID_IPropertyBag, 00307 (LPVOID *) &pPropBagCat); 00308 00309 if (SUCCEEDED(hr)) 00310 hr = IPropertyBag_Read(pPropBagCat, wszClsidName, pvar, NULL); 00311 00312 if (SUCCEEDED(hr)) 00313 { 00314 hr = CLSIDFromString(V_UNION(pvar, bstrVal), pclsid); 00315 VariantClear(pvar); 00316 V_VT(pvar) = VT_BSTR; 00317 } 00318 00319 if (SUCCEEDED(hr)) 00320 hr = IPropertyBag_Read(pPropBagCat, wszFriendlyName, pvar, NULL); 00321 00322 if (SUCCEEDED(hr)) 00323 TRACE("Moniker = %s - %s\n", debugstr_guid(pclsid), 00324 debugstr_w(V_UNION(pvar, bstrVal))); 00325 00326 if (pPropBagCat) 00327 IPropertyBag_Release(pPropBagCat); 00328 00329 return hr; 00330 } 00331 00332 static HRESULT GetSplitter(MediaDetImpl *This) 00333 { 00334 IFileSourceFilter *file; 00335 LPOLESTR name; 00336 AM_MEDIA_TYPE mt; 00337 GUID type[2]; 00338 IFilterMapper2 *map; 00339 IEnumMoniker *filters; 00340 IMoniker *mon; 00341 VARIANT var; 00342 GUID clsid; 00343 IBaseFilter *splitter; 00344 IEnumPins *pins; 00345 IPin *source_pin, *splitter_pin; 00346 HRESULT hr; 00347 00348 hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER, 00349 &IID_IFilterMapper2, (void **) &map); 00350 if (FAILED(hr)) 00351 return hr; 00352 00353 hr = IBaseFilter_QueryInterface(This->source, &IID_IFileSourceFilter, 00354 (void **) &file); 00355 if (FAILED(hr)) 00356 { 00357 IFilterMapper2_Release(map); 00358 return hr; 00359 } 00360 00361 hr = IFileSourceFilter_GetCurFile(file, &name, &mt); 00362 IFileSourceFilter_Release(file); 00363 CoTaskMemFree(name); 00364 if (FAILED(hr)) 00365 { 00366 IFilterMapper2_Release(map); 00367 return hr; 00368 } 00369 type[0] = mt.majortype; 00370 type[1] = mt.subtype; 00371 CoTaskMemFree(mt.pbFormat); 00372 00373 hr = IFilterMapper2_EnumMatchingFilters(map, &filters, 0, TRUE, 00374 MERIT_UNLIKELY, FALSE, 1, type, 00375 NULL, NULL, FALSE, TRUE, 00376 0, NULL, NULL, NULL); 00377 IFilterMapper2_Release(map); 00378 if (FAILED(hr)) 00379 return hr; 00380 00381 hr = IEnumMoniker_Next(filters, 1, &mon, NULL); 00382 IEnumMoniker_Release(filters); 00383 if (hr != S_OK) /* No matches, what do we do? */ 00384 return E_NOINTERFACE; 00385 00386 hr = GetFilterInfo(mon, &clsid, &var); 00387 IMoniker_Release(mon); 00388 if (FAILED(hr)) 00389 return hr; 00390 00391 hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, 00392 &IID_IBaseFilter, (void **) &splitter); 00393 if (FAILED(hr)) 00394 { 00395 VariantClear(&var); 00396 return hr; 00397 } 00398 00399 hr = IGraphBuilder_AddFilter(This->graph, splitter, 00400 V_UNION(&var, bstrVal)); 00401 VariantClear(&var); 00402 if (FAILED(hr)) 00403 { 00404 IBaseFilter_Release(splitter); 00405 return hr; 00406 } 00407 This->splitter = splitter; 00408 00409 hr = IBaseFilter_EnumPins(This->source, &pins); 00410 if (FAILED(hr)) 00411 return hr; 00412 IEnumPins_Next(pins, 1, &source_pin, NULL); 00413 IEnumPins_Release(pins); 00414 00415 hr = IBaseFilter_EnumPins(splitter, &pins); 00416 if (FAILED(hr)) 00417 { 00418 IPin_Release(source_pin); 00419 return hr; 00420 } 00421 IEnumPins_Next(pins, 1, &splitter_pin, NULL); 00422 IEnumPins_Release(pins); 00423 00424 hr = IPin_Connect(source_pin, splitter_pin, NULL); 00425 IPin_Release(source_pin); 00426 IPin_Release(splitter_pin); 00427 if (FAILED(hr)) 00428 return hr; 00429 00430 return S_OK; 00431 } 00432 00433 static HRESULT WINAPI MediaDet_put_Filename(IMediaDet* iface, BSTR newVal) 00434 { 00435 static const WCHAR reader[] = {'R','e','a','d','e','r',0}; 00436 MediaDetImpl *This = (MediaDetImpl *)iface; 00437 IGraphBuilder *gb; 00438 IBaseFilter *bf; 00439 HRESULT hr; 00440 00441 TRACE("(%p)->(%s)\n", This, debugstr_w(newVal)); 00442 00443 if (This->graph) 00444 { 00445 WARN("MSDN says not to call this method twice\n"); 00446 MD_cleanup(This); 00447 } 00448 00449 hr = CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, 00450 &IID_IGraphBuilder, (void **) &gb); 00451 if (FAILED(hr)) 00452 return hr; 00453 00454 hr = IGraphBuilder_AddSourceFilter(gb, newVal, reader, &bf); 00455 if (FAILED(hr)) 00456 { 00457 IGraphBuilder_Release(gb); 00458 return hr; 00459 } 00460 00461 This->graph = gb; 00462 This->source = bf; 00463 hr = GetSplitter(This); 00464 if (FAILED(hr)) 00465 return hr; 00466 00467 return MediaDet_put_CurrentStream(iface, 0); 00468 } 00469 00470 static HRESULT WINAPI MediaDet_GetBitmapBits(IMediaDet* iface, 00471 double StreamTime, 00472 LONG *pBufferSize, char *pBuffer, 00473 LONG Width, LONG Height) 00474 { 00475 MediaDetImpl *This = (MediaDetImpl *)iface; 00476 FIXME("(%p)->(%f %p %p %d %d): not implemented!\n", This, StreamTime, pBufferSize, pBuffer, 00477 Width, Height); 00478 return E_NOTIMPL; 00479 } 00480 00481 static HRESULT WINAPI MediaDet_WriteBitmapBits(IMediaDet* iface, 00482 double StreamTime, LONG Width, 00483 LONG Height, BSTR Filename) 00484 { 00485 MediaDetImpl *This = (MediaDetImpl *)iface; 00486 FIXME("(%p)->(%f %d %d %p): not implemented!\n", This, StreamTime, Width, Height, Filename); 00487 return E_NOTIMPL; 00488 } 00489 00490 static HRESULT WINAPI MediaDet_get_StreamMediaType(IMediaDet* iface, 00491 AM_MEDIA_TYPE *pVal) 00492 { 00493 MediaDetImpl *This = (MediaDetImpl *)iface; 00494 IEnumMediaTypes *types; 00495 AM_MEDIA_TYPE *pmt; 00496 HRESULT hr; 00497 00498 TRACE("(%p)\n", This); 00499 00500 if (!pVal) 00501 return E_POINTER; 00502 00503 if (!This->cur_pin) 00504 return E_INVALIDARG; 00505 00506 hr = IPin_EnumMediaTypes(This->cur_pin, &types); 00507 if (SUCCEEDED(hr)) 00508 { 00509 hr = (IEnumMediaTypes_Next(types, 1, &pmt, NULL) == S_OK 00510 ? S_OK 00511 : E_NOINTERFACE); 00512 IEnumMediaTypes_Release(types); 00513 } 00514 00515 if (SUCCEEDED(hr)) 00516 { 00517 *pVal = *pmt; 00518 CoTaskMemFree(pmt); 00519 } 00520 00521 return hr; 00522 } 00523 00524 static HRESULT WINAPI MediaDet_GetSampleGrabber(IMediaDet* iface, 00525 ISampleGrabber **ppVal) 00526 { 00527 MediaDetImpl *This = (MediaDetImpl *)iface; 00528 FIXME("(%p)->(%p): not implemented!\n", This, ppVal); 00529 return E_NOTIMPL; 00530 } 00531 00532 static HRESULT WINAPI MediaDet_get_FrameRate(IMediaDet* iface, double *pVal) 00533 { 00534 MediaDetImpl *This = (MediaDetImpl *)iface; 00535 AM_MEDIA_TYPE mt; 00536 VIDEOINFOHEADER *vh; 00537 HRESULT hr; 00538 00539 TRACE("(%p)\n", This); 00540 00541 if (!pVal) 00542 return E_POINTER; 00543 00544 hr = MediaDet_get_StreamMediaType(iface, &mt); 00545 if (FAILED(hr)) 00546 return hr; 00547 00548 if (!IsEqualGUID(&mt.majortype, &MEDIATYPE_Video)) 00549 { 00550 CoTaskMemFree(mt.pbFormat); 00551 return VFW_E_INVALIDMEDIATYPE; 00552 } 00553 00554 vh = (VIDEOINFOHEADER *) mt.pbFormat; 00555 *pVal = 1.0e7 / (double) vh->AvgTimePerFrame; 00556 00557 CoTaskMemFree(mt.pbFormat); 00558 return S_OK; 00559 } 00560 00561 static HRESULT WINAPI MediaDet_EnterBitmapGrabMode(IMediaDet* iface, 00562 double SeekTime) 00563 { 00564 MediaDetImpl *This = (MediaDetImpl *)iface; 00565 FIXME("(%p)->(%f): not implemented!\n", This, SeekTime); 00566 return E_NOTIMPL; 00567 } 00568 00569 static const IMediaDetVtbl IMediaDet_VTable = 00570 { 00571 MediaDet_QueryInterface, 00572 MediaDet_AddRef, 00573 MediaDet_Release, 00574 MediaDet_get_Filter, 00575 MediaDet_put_Filter, 00576 MediaDet_get_OutputStreams, 00577 MediaDet_get_CurrentStream, 00578 MediaDet_put_CurrentStream, 00579 MediaDet_get_StreamType, 00580 MediaDet_get_StreamTypeB, 00581 MediaDet_get_StreamLength, 00582 MediaDet_get_Filename, 00583 MediaDet_put_Filename, 00584 MediaDet_GetBitmapBits, 00585 MediaDet_WriteBitmapBits, 00586 MediaDet_get_StreamMediaType, 00587 MediaDet_GetSampleGrabber, 00588 MediaDet_get_FrameRate, 00589 MediaDet_EnterBitmapGrabMode, 00590 }; 00591 00592 HRESULT MediaDet_create(IUnknown * pUnkOuter, LPVOID * ppv) { 00593 MediaDetImpl* obj = NULL; 00594 00595 TRACE("(%p,%p)\n", ppv, pUnkOuter); 00596 00597 if (pUnkOuter) 00598 return CLASS_E_NOAGGREGATION; 00599 00600 obj = CoTaskMemAlloc(sizeof(MediaDetImpl)); 00601 if (NULL == obj) { 00602 *ppv = NULL; 00603 return E_OUTOFMEMORY; 00604 } 00605 ZeroMemory(obj, sizeof(MediaDetImpl)); 00606 00607 obj->refCount = 1; 00608 obj->MediaDet_Vtbl = &IMediaDet_VTable; 00609 obj->graph = NULL; 00610 obj->source = NULL; 00611 obj->splitter = NULL; 00612 obj->cur_pin = NULL; 00613 obj->num_streams = -1; 00614 obj->cur_stream = 0; 00615 *ppv = obj; 00616 00617 return S_OK; 00618 } Generated on Fri May 25 2012 04:19:46 for ReactOS by
1.7.6.1
|