ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

mediadet.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.