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

samplegrabber.c
Go to the documentation of this file.
00001 /*              DirectShow Sample Grabber object (QEDIT.DLL)
00002  *
00003  * Copyright 2009 Paul Chitescu
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 static WCHAR const vendor_name[] = { 'W', 'i', 'n', 'e', 0 };
00036 static WCHAR const pin_in_name[] = { 'I', 'n', 0 };
00037 static WCHAR const pin_out_name[] = { 'O', 'u', 't', 0 };
00038 
00039 IEnumPins *pinsenum_create(IBaseFilter *filter, IPin **pins, ULONG pinCount);
00040 IEnumMediaTypes *mediaenum_create(const AM_MEDIA_TYPE *mtype);
00041 
00042 /* Fixed pins enumerator, holds filter referenced */
00043 typedef struct _PE_Impl {
00044     IEnumPins pe;
00045     IBaseFilter *filter;
00046     LONG refCount;
00047     ULONG numPins;
00048     ULONG index;
00049     IPin *pins[0];
00050 } PE_Impl;
00051 
00052 
00053 /* IEnumPins interface implementation */
00054 
00055 /* IUnknown */
00056 static ULONG WINAPI
00057 Fixed_IEnumPins_AddRef(IEnumPins *iface)
00058 {
00059     PE_Impl *This = (PE_Impl *)iface;
00060     ULONG refCount = InterlockedIncrement(&This->refCount);
00061     TRACE("(%p) new ref = %u\n", This, refCount);
00062     return refCount;
00063 }
00064 
00065 /* IUnknown */
00066 static ULONG WINAPI
00067 Fixed_IEnumPins_Release(IEnumPins *iface)
00068 {
00069     PE_Impl *This = (PE_Impl *)iface;
00070     ULONG refCount = InterlockedDecrement(&This->refCount);
00071     TRACE("(%p) new ref = %u\n", This, refCount);
00072     if (refCount == 0)
00073     {
00074         IBaseFilter_Release(This->filter);
00075         CoTaskMemFree(This);
00076         return 0;
00077     }
00078     return refCount;
00079 }
00080 
00081 /* IUnknown */
00082 static HRESULT WINAPI
00083 Fixed_IEnumPins_QueryInterface(IEnumPins *iface, REFIID riid, void **ppvObject)
00084 {
00085     PE_Impl *This = (PE_Impl *)iface;
00086     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
00087 
00088     if (IsEqualIID(riid, &IID_IUnknown) ||
00089         IsEqualIID(riid, &IID_IEnumPins)) {
00090     Fixed_IEnumPins_AddRef(iface);
00091         *ppvObject = &(This->pins);
00092         return S_OK;
00093     }
00094     *ppvObject = NULL;
00095     WARN("(%p, %s,%p): not found\n", This, debugstr_guid(riid), ppvObject);
00096     return E_NOINTERFACE;
00097 }
00098 
00099 /* IEnumPins */
00100 static HRESULT WINAPI
00101 Fixed_IEnumPins_Next(IEnumPins *iface, ULONG nPins, IPin **pins, ULONG *fetched)
00102 {
00103     PE_Impl *This = (PE_Impl *)iface;
00104     ULONG count = 0;
00105     TRACE("(%p)->(%u, %p, %p) index = %u\n", This, nPins, pins, fetched, This->index);
00106     if (!nPins)
00107         return E_INVALIDARG;
00108     if (!pins || ((nPins != 1) && !fetched))
00109         return E_POINTER;
00110     while ((count < nPins) && (This->index < This->numPins)) {
00111         IPin *pin = This->pins[This->index++];
00112         IPin_AddRef(pin);
00113         pins[count++] = pin;
00114     }
00115     if (fetched)
00116         *fetched = count;
00117     return (count == nPins) ? S_OK : S_FALSE;
00118 }
00119 
00120 /* IEnumPins */
00121 static HRESULT WINAPI
00122 Fixed_IEnumPins_Skip(IEnumPins *iface, ULONG nPins)
00123 {
00124     PE_Impl *This = (PE_Impl *)iface;
00125     TRACE("(%p)->(%u) index = %u\n", This, nPins, This->index);
00126     nPins += This->index;
00127     if (nPins >= This->numPins) {
00128         This->index = This->numPins;
00129         return S_FALSE;
00130     }
00131     This->index = nPins;
00132     return S_OK;
00133 }
00134 
00135 /* IEnumPins */
00136 static HRESULT WINAPI
00137 Fixed_IEnumPins_Reset(IEnumPins *iface)
00138 {
00139     PE_Impl *This = (PE_Impl *)iface;
00140     TRACE("(%p)->() index = %u\n", This, This->index);
00141     This->index = 0;
00142     return S_OK;
00143 }
00144 
00145 /* IEnumPins */
00146 static HRESULT WINAPI
00147 Fixed_IEnumPins_Clone(IEnumPins *iface, IEnumPins **pins)
00148 {
00149     PE_Impl *This = (PE_Impl *)iface;
00150     TRACE("(%p)->(%p) index = %u\n", This, pins, This->index);
00151     if (!pins)
00152         return E_POINTER;
00153     *pins = pinsenum_create(This->filter, This->pins, This->numPins);
00154     if (!*pins)
00155         return E_OUTOFMEMORY;
00156     ((PE_Impl *)*pins)->index = This->index;
00157     return S_OK;
00158 }
00159 
00160 
00161 /* Virtual tables and constructor */
00162 
00163 static const IEnumPinsVtbl IEnumPins_VTable =
00164 {
00165     Fixed_IEnumPins_QueryInterface,
00166     Fixed_IEnumPins_AddRef,
00167     Fixed_IEnumPins_Release,
00168     Fixed_IEnumPins_Next,
00169     Fixed_IEnumPins_Skip,
00170     Fixed_IEnumPins_Reset,
00171     Fixed_IEnumPins_Clone,
00172 };
00173 
00174 IEnumPins *pinsenum_create(IBaseFilter *filter, IPin **pins, ULONG pinCount)
00175 {
00176     ULONG len = sizeof(PE_Impl) + (pinCount * sizeof(IPin *));
00177     PE_Impl *obj = CoTaskMemAlloc(len);
00178     if (obj) {
00179         ULONG i;
00180         ZeroMemory(obj, len);
00181         obj->pe.lpVtbl = &IEnumPins_VTable;
00182         obj->refCount = 1;
00183         obj->filter = filter;
00184         obj->numPins = pinCount;
00185         obj->index = 0;
00186         for (i=0; i<pinCount; i++)
00187             obj->pins[i] = pins[i];
00188         IBaseFilter_AddRef(filter);
00189     }
00190     return &obj->pe;
00191 }
00192 
00193 
00194 /* Single media type enumerator */
00195 typedef struct _ME_Impl {
00196     IEnumMediaTypes me;
00197     LONG refCount;
00198     BOOL past;
00199     AM_MEDIA_TYPE mtype;
00200 } ME_Impl;
00201 
00202 
00203 /* IEnumMediaTypes interface implementation */
00204 
00205 /* IUnknown */
00206 static ULONG WINAPI
00207 Single_IEnumMediaTypes_AddRef(IEnumMediaTypes *iface)
00208 {
00209     ME_Impl *This = (ME_Impl *)iface;
00210     ULONG refCount = InterlockedIncrement(&This->refCount);
00211     TRACE("(%p) new ref = %u\n", This, refCount);
00212     return refCount;
00213 }
00214 
00215 /* IUnknown */
00216 static ULONG WINAPI
00217 Single_IEnumMediaTypes_Release(IEnumMediaTypes *iface)
00218 {
00219     ME_Impl *This = (ME_Impl *)iface;
00220     ULONG refCount = InterlockedDecrement(&This->refCount);
00221     TRACE("(%p) new ref = %u\n", This, refCount);
00222     if (refCount == 0)
00223     {
00224         if (This->mtype.pbFormat)
00225             CoTaskMemFree(This->mtype.pbFormat);
00226         CoTaskMemFree(This);
00227         return 0;
00228     }
00229     return refCount;
00230 }
00231 
00232 /* IUnknown */
00233 static HRESULT WINAPI
00234 Single_IEnumMediaTypes_QueryInterface(IEnumMediaTypes *iface, REFIID riid, void **ppvObject)
00235 {
00236     ME_Impl *This = (ME_Impl *)iface;
00237     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
00238 
00239     if (IsEqualIID(riid, &IID_IUnknown) ||
00240         IsEqualIID(riid, &IID_IEnumMediaTypes)) {
00241         Single_IEnumMediaTypes_AddRef(iface);
00242         *ppvObject = &(This->me);
00243         return S_OK;
00244     }
00245     *ppvObject = NULL;
00246     WARN("(%p, %s,%p): not found\n", This, debugstr_guid(riid), ppvObject);
00247     return E_NOINTERFACE;
00248 }
00249 
00250 /* IEnumMediaTypes */
00251 static HRESULT WINAPI
00252 Single_IEnumMediaTypes_Next(IEnumMediaTypes *iface, ULONG nTypes, AM_MEDIA_TYPE **types, ULONG *fetched)
00253 {
00254     ME_Impl *This = (ME_Impl *)iface;
00255     ULONG count = 0;
00256     TRACE("(%p)->(%u, %p, %p)\n", This, nTypes, types, fetched);
00257     if (!nTypes)
00258         return E_INVALIDARG;
00259     if (!types || ((nTypes != 1) && !fetched))
00260         return E_POINTER;
00261     if (!This->past && !IsEqualGUID(&This->mtype.majortype,&GUID_NULL)) {
00262         AM_MEDIA_TYPE *mtype = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
00263         *mtype = This->mtype;
00264         if (mtype->cbFormat) {
00265             mtype->pbFormat = CoTaskMemAlloc(mtype->cbFormat);
00266             CopyMemory(mtype->pbFormat, This->mtype.pbFormat, mtype->cbFormat);
00267         }
00268         *types = mtype;
00269         This->past = TRUE;
00270         count = 1;
00271     }
00272     if (fetched)
00273         *fetched = count;
00274     return (count == nTypes) ? S_OK : S_FALSE;
00275 }
00276 
00277 /* IEnumMediaTypes */
00278 static HRESULT WINAPI
00279 Single_IEnumMediaTypes_Skip(IEnumMediaTypes *iface, ULONG nTypes)
00280 {
00281     ME_Impl *This = (ME_Impl *)iface;
00282     TRACE("(%p)->(%u)\n", This, nTypes);
00283     if (nTypes)
00284         This->past = TRUE;
00285     return This->past ? S_FALSE : S_OK;
00286 }
00287 
00288 /* IEnumMediaTypes */
00289 static HRESULT WINAPI
00290 Single_IEnumMediaTypes_Reset(IEnumMediaTypes *iface)
00291 {
00292     ME_Impl *This = (ME_Impl *)iface;
00293     TRACE("(%p)->()\n", This);
00294     This->past = FALSE;
00295     return S_OK;
00296 }
00297 
00298 /* IEnumMediaTypes */
00299 static HRESULT WINAPI
00300 Single_IEnumMediaTypes_Clone(IEnumMediaTypes *iface, IEnumMediaTypes **me)
00301 {
00302     ME_Impl *This = (ME_Impl *)iface;
00303     TRACE("(%p)->(%p)\n", This, me);
00304     if (!me)
00305         return E_POINTER;
00306     *me = mediaenum_create(&This->mtype);
00307     if (!*me)
00308         return E_OUTOFMEMORY;
00309     ((ME_Impl *)*me)->past = This->past;
00310     return S_OK;
00311 }
00312 
00313 
00314 /* Virtual tables and constructor */
00315 
00316 static const IEnumMediaTypesVtbl IEnumMediaTypes_VTable =
00317 {
00318     Single_IEnumMediaTypes_QueryInterface,
00319     Single_IEnumMediaTypes_AddRef,
00320     Single_IEnumMediaTypes_Release,
00321     Single_IEnumMediaTypes_Next,
00322     Single_IEnumMediaTypes_Skip,
00323     Single_IEnumMediaTypes_Reset,
00324     Single_IEnumMediaTypes_Clone,
00325 };
00326 
00327 IEnumMediaTypes *mediaenum_create(const AM_MEDIA_TYPE *mtype)
00328 {
00329     ME_Impl *obj = CoTaskMemAlloc(sizeof(ME_Impl));
00330     if (obj) {
00331         ZeroMemory(obj, sizeof(ME_Impl));
00332         obj->me.lpVtbl = &IEnumMediaTypes_VTable;
00333         obj->refCount = 1;
00334         obj->past = FALSE;
00335         if (mtype) {
00336             obj->mtype = *mtype;
00337             obj->mtype.pUnk = NULL;
00338             if (mtype->cbFormat) {
00339                 obj->mtype.pbFormat = CoTaskMemAlloc(mtype->cbFormat);
00340                 CopyMemory(obj->mtype.pbFormat, mtype->pbFormat, mtype->cbFormat);
00341             }
00342             else
00343                 obj->mtype.pbFormat = NULL;
00344         }
00345         else
00346             obj->mtype.majortype = GUID_NULL;
00347     }
00348     return &obj->me;
00349 }
00350 
00351 
00352 /* Sample Grabber pin implementation */
00353 typedef struct _SG_Pin {
00354     const IPinVtbl* lpVtbl;
00355     PIN_DIRECTION dir;
00356     WCHAR const *name;
00357     struct _SG_Impl *sg;
00358     IPin *pair;
00359 } SG_Pin;
00360 
00361 /* Sample Grabber filter implementation */
00362 typedef struct _SG_Impl {
00363     const IBaseFilterVtbl* IBaseFilter_Vtbl;
00364     const ISampleGrabberVtbl* ISampleGrabber_Vtbl;
00365     const IMemInputPinVtbl* IMemInputPin_Vtbl;
00366     /* TODO: IMediaPosition, IMediaSeeking, IQualityControl */
00367     LONG refCount;
00368     CRITICAL_SECTION critSect;
00369     FILTER_INFO info;
00370     FILTER_STATE state;
00371     AM_MEDIA_TYPE mtype;
00372     SG_Pin pin_in;
00373     SG_Pin pin_out;
00374     IMemAllocator *allocator;
00375     IReferenceClock *refClock;
00376     IMemInputPin *memOutput;
00377     ISampleGrabberCB *grabberIface;
00378     LONG grabberMethod;
00379     LONG oneShot;
00380     LONG bufferLen;
00381     void* bufferData;
00382 } SG_Impl;
00383 
00384 enum {
00385     OneShot_None,
00386     OneShot_Wait,
00387     OneShot_Past,
00388 };
00389 
00390 /* Get the SampleGrabber implementation This pointer from various interface pointers */
00391 static inline SG_Impl *impl_from_IBaseFilter(IBaseFilter *iface)
00392 {
00393     return (SG_Impl *)((char*)iface - FIELD_OFFSET(SG_Impl, IBaseFilter_Vtbl));
00394 }
00395 
00396 static inline SG_Impl *impl_from_ISampleGrabber(ISampleGrabber *iface)
00397 {
00398     return (SG_Impl *)((char*)iface - FIELD_OFFSET(SG_Impl, ISampleGrabber_Vtbl));
00399 }
00400 
00401 static inline SG_Impl *impl_from_IMemInputPin(IMemInputPin *iface)
00402 {
00403     return (SG_Impl *)((char*)iface - FIELD_OFFSET(SG_Impl, IMemInputPin_Vtbl));
00404 }
00405 
00406 
00407 /* Cleanup at end of life */
00408 static void SampleGrabber_cleanup(SG_Impl *This)
00409 {
00410     TRACE("(%p)\n", This);
00411     if (This->info.pGraph)
00412     WARN("(%p) still joined to filter graph %p\n", This, This->info.pGraph);
00413     if (This->allocator)
00414         IMemAllocator_Release(This->allocator);
00415     if (This->refClock)
00416     IReferenceClock_Release(This->refClock);
00417     if (This->memOutput)
00418         IMemInputPin_Release(This->memOutput);
00419     if (This->grabberIface)
00420         ISampleGrabberCB_Release(This->grabberIface);
00421     if (This->mtype.pbFormat)
00422         CoTaskMemFree(This->mtype.pbFormat);
00423     if (This->bufferData)
00424         CoTaskMemFree(This->bufferData);
00425     This->critSect.DebugInfo->Spare[0] = 0;
00426     DeleteCriticalSection(&This->critSect);
00427 }
00428 
00429 /* Common helper AddRef called from all interfaces */
00430 static ULONG SampleGrabber_addref(SG_Impl *This)
00431 {
00432     ULONG refCount = InterlockedIncrement(&This->refCount);
00433     TRACE("(%p) new ref = %u\n", This, refCount);
00434     return refCount;
00435 }
00436 
00437 /* Common helper Release called from all interfaces */
00438 static ULONG SampleGrabber_release(SG_Impl *This)
00439 {
00440     ULONG refCount = InterlockedDecrement(&This->refCount);
00441     TRACE("(%p) new ref = %u\n", This, refCount);
00442     if (refCount == 0)
00443     {
00444         SampleGrabber_cleanup(This);
00445         CoTaskMemFree(This);
00446         return 0;
00447     }
00448     return refCount;
00449 }
00450 
00451 /* Common helper QueryInterface called from all interfaces */
00452 static HRESULT SampleGrabber_query(SG_Impl *This, REFIID riid, void **ppvObject)
00453 {
00454     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
00455 
00456     if (IsEqualIID(riid, &IID_IUnknown) ||
00457         IsEqualIID(riid, &IID_IPersist) ||
00458         IsEqualIID(riid, &IID_IMediaFilter) ||
00459         IsEqualIID(riid, &IID_IBaseFilter)) {
00460         SampleGrabber_addref(This);
00461         *ppvObject = &(This->IBaseFilter_Vtbl);
00462         return S_OK;
00463     }
00464     else if (IsEqualIID(riid, &IID_ISampleGrabber)) {
00465         SampleGrabber_addref(This);
00466         *ppvObject = &(This->ISampleGrabber_Vtbl);
00467         return S_OK;
00468     }
00469     else if (IsEqualIID(riid, &IID_IMemInputPin)) {
00470         SampleGrabber_addref(This);
00471         *ppvObject = &(This->IMemInputPin_Vtbl);
00472         return S_OK;
00473     }
00474     else if (IsEqualIID(riid, &IID_IMediaPosition))
00475         FIXME("IMediaPosition not implemented\n");
00476     else if (IsEqualIID(riid, &IID_IMediaSeeking))
00477         FIXME("IMediaSeeking not implemented\n");
00478     else if (IsEqualIID(riid, &IID_IQualityControl))
00479         FIXME("IQualityControl not implemented\n");
00480     *ppvObject = NULL;
00481     WARN("(%p, %s,%p): not found\n", This, debugstr_guid(riid), ppvObject);
00482     return E_NOINTERFACE;
00483 }
00484 
00485 /* Helper that buffers data and/or calls installed sample callbacks */
00486 static void SampleGrabber_callback(SG_Impl *This, IMediaSample *sample)
00487 {
00488     double time = 0.0;
00489     REFERENCE_TIME tStart, tEnd;
00490     if (This->bufferLen >= 0) {
00491         BYTE *data = 0;
00492         LONG size = IMediaSample_GetActualDataLength(sample);
00493         if (size >= 0 && SUCCEEDED(IMediaSample_GetPointer(sample, &data))) {
00494             if (!data)
00495                 size = 0;
00496             EnterCriticalSection(&This->critSect);
00497             if (This->bufferLen != size) {
00498                 if (This->bufferData)
00499                     CoTaskMemFree(This->bufferData);
00500                 This->bufferData = size ? CoTaskMemAlloc(size) : NULL;
00501                 This->bufferLen = size;
00502             }
00503             if (size)
00504                 CopyMemory(This->bufferData, data, size);
00505             LeaveCriticalSection(&This->critSect);
00506         }
00507     }
00508     if (!This->grabberIface)
00509         return;
00510     if (SUCCEEDED(IMediaSample_GetTime(sample, &tStart, &tEnd)))
00511         time = 1e-7 * tStart;
00512     switch (This->grabberMethod) {
00513         case 0:
00514         {
00515         ULONG ref = IMediaSample_AddRef(sample);
00516         ISampleGrabberCB_SampleCB(This->grabberIface, time, sample);
00517         ref = IMediaSample_Release(sample) + 1 - ref;
00518         if (ref)
00519         {
00520             ERR("(%p) Callback referenced sample %p by %u\n", This, sample, ref);
00521             /* ugly as hell but some apps are sooo buggy */
00522             while (ref--)
00523             IMediaSample_Release(sample);
00524         }
00525         }
00526             break;
00527         case 1:
00528             {
00529                 BYTE *data = 0;
00530                 LONG size = IMediaSample_GetActualDataLength(sample);
00531                 if (size && SUCCEEDED(IMediaSample_GetPointer(sample, &data)) && data)
00532                     ISampleGrabberCB_BufferCB(This->grabberIface, time, data, size);
00533             }
00534             break;
00535         case -1:
00536             break;
00537         default:
00538             FIXME("unsupported method %d\n", This->grabberMethod);
00539             /* do not bother us again */
00540             This->grabberMethod = -1;
00541     }
00542 }
00543 
00544 
00545 /* SampleGrabber implementation of IBaseFilter interface */
00546 
00547 /* IUnknown */
00548 static HRESULT WINAPI
00549 SampleGrabber_IBaseFilter_QueryInterface(IBaseFilter *iface, REFIID riid, void **ppvObject)
00550 {
00551     return SampleGrabber_query(impl_from_IBaseFilter(iface), riid, ppvObject);
00552 }
00553 
00554 /* IUnknown */
00555 static ULONG WINAPI
00556 SampleGrabber_IBaseFilter_AddRef(IBaseFilter *iface)
00557 {
00558     return SampleGrabber_addref(impl_from_IBaseFilter(iface));
00559 }
00560 
00561 /* IUnknown */
00562 static ULONG WINAPI
00563 SampleGrabber_IBaseFilter_Release(IBaseFilter *iface)
00564 {
00565     return SampleGrabber_release(impl_from_IBaseFilter(iface));
00566 }
00567 
00568 /* IPersist */
00569 static HRESULT WINAPI
00570 SampleGrabber_IBaseFilter_GetClassID(IBaseFilter *iface, CLSID *pClassID)
00571 {
00572     TRACE("(%p)\n", pClassID);
00573     if (!pClassID)
00574         return E_POINTER;
00575     *pClassID = CLSID_SampleGrabber;
00576     return S_OK;
00577 }
00578 
00579 /* IMediaFilter */
00580 static HRESULT WINAPI
00581 SampleGrabber_IBaseFilter_Stop(IBaseFilter *iface)
00582 {
00583     SG_Impl *This = impl_from_IBaseFilter(iface);
00584     TRACE("(%p)\n", This);
00585     This->state = State_Stopped;
00586     return S_OK;
00587 }
00588 
00589 /* IMediaFilter */
00590 static HRESULT WINAPI
00591 SampleGrabber_IBaseFilter_Pause(IBaseFilter *iface)
00592 {
00593     SG_Impl *This = impl_from_IBaseFilter(iface);
00594     TRACE("(%p)\n", This);
00595     This->state = State_Paused;
00596     return S_OK;
00597 }
00598 
00599 /* IMediaFilter */
00600 static HRESULT WINAPI
00601 SampleGrabber_IBaseFilter_Run(IBaseFilter *iface, REFERENCE_TIME tStart)
00602 {
00603     SG_Impl *This = impl_from_IBaseFilter(iface);
00604     TRACE("(%p)\n", This);
00605     This->state = State_Running;
00606     return S_OK;
00607 }
00608 
00609 /* IMediaFilter */
00610 static HRESULT WINAPI
00611 SampleGrabber_IBaseFilter_GetState(IBaseFilter *iface, DWORD msTout, FILTER_STATE *state)
00612 {
00613     SG_Impl *This = impl_from_IBaseFilter(iface);
00614     TRACE("(%p)->(%u, %p)\n", This, msTout, state);
00615     if (!state)
00616         return E_POINTER;
00617     *state = This->state;
00618     return S_OK;
00619 }
00620 
00621 /* IMediaFilter */
00622 static HRESULT WINAPI
00623 SampleGrabber_IBaseFilter_SetSyncSource(IBaseFilter *iface, IReferenceClock *clock)
00624 {
00625     SG_Impl *This = impl_from_IBaseFilter(iface);
00626     TRACE("(%p)->(%p)\n", This, clock);
00627     if (clock != This->refClock)
00628     {
00629     if (clock)
00630         IReferenceClock_AddRef(clock);
00631     if (This->refClock)
00632         IReferenceClock_Release(This->refClock);
00633     This->refClock = clock;
00634     }
00635     return S_OK;
00636 }
00637 
00638 /* IMediaFilter */
00639 static HRESULT WINAPI
00640 SampleGrabber_IBaseFilter_GetSyncSource(IBaseFilter *iface, IReferenceClock **clock)
00641 {
00642     SG_Impl *This = impl_from_IBaseFilter(iface);
00643     TRACE("(%p)->(%p)\n", This, clock);
00644     if (!clock)
00645         return E_POINTER;
00646     if (This->refClock)
00647     IReferenceClock_AddRef(This->refClock);
00648     *clock = This->refClock;
00649     return S_OK;
00650 }
00651 
00652 /* IBaseFilter */
00653 static HRESULT WINAPI
00654 SampleGrabber_IBaseFilter_EnumPins(IBaseFilter *iface, IEnumPins **pins)
00655 {
00656     SG_Impl *This = impl_from_IBaseFilter(iface);
00657     IPin *pin[2];
00658     TRACE("(%p)->(%p)\n", This, pins);
00659     if (!pins)
00660         return E_POINTER;
00661     pin[0] = (IPin*)&This->pin_in.lpVtbl;
00662     pin[1] = (IPin*)&This->pin_out.lpVtbl;
00663     *pins = pinsenum_create(iface, pin, 2);
00664     return *pins ? S_OK : E_OUTOFMEMORY;
00665 }
00666 
00667 /* IBaseFilter */
00668 static HRESULT WINAPI
00669 SampleGrabber_IBaseFilter_FindPin(IBaseFilter *iface, LPCWSTR id, IPin **pin)
00670 {
00671     SG_Impl *This = impl_from_IBaseFilter(iface);
00672     TRACE("(%p)->(%s, %p)\n", This, debugstr_w(id), pin);
00673     if (!id || !pin)
00674         return E_POINTER;
00675     if (!lstrcmpiW(id,pin_in_name))
00676     {
00677         SampleGrabber_addref(This);
00678         *pin = (IPin*)&(This->pin_in.lpVtbl);
00679         return S_OK;
00680     }
00681     else if (!lstrcmpiW(id,pin_out_name))
00682     {
00683         SampleGrabber_addref(This);
00684         *pin = (IPin*)&(This->pin_out.lpVtbl);
00685         return S_OK;
00686     }
00687     *pin = NULL;
00688     return VFW_E_NOT_FOUND;
00689 }
00690 
00691 /* IBaseFilter */
00692 static HRESULT WINAPI
00693 SampleGrabber_IBaseFilter_QueryFilterInfo(IBaseFilter *iface, FILTER_INFO *info)
00694 {
00695     SG_Impl *This = impl_from_IBaseFilter(iface);
00696     TRACE("(%p)->(%p)\n", This, info);
00697     if (!info)
00698         return E_POINTER;
00699     if (This->info.pGraph)
00700     IFilterGraph_AddRef(This->info.pGraph);
00701     *info = This->info;
00702     return S_OK;
00703 }
00704 
00705 /* IBaseFilter */
00706 static HRESULT WINAPI
00707 SampleGrabber_IBaseFilter_JoinFilterGraph(IBaseFilter *iface, IFilterGraph *graph, LPCWSTR name)
00708 {
00709     SG_Impl *This = impl_from_IBaseFilter(iface);
00710     TRACE("(%p)->(%p, %s)\n", This, graph, debugstr_w(name));
00711     This->info.pGraph = graph;
00712     if (name)
00713     lstrcpynW(This->info.achName,name,MAX_FILTER_NAME);
00714     This->oneShot = OneShot_None;
00715     return S_OK;
00716 }
00717 
00718 /* IBaseFilter */
00719 static HRESULT WINAPI
00720 SampleGrabber_IBaseFilter_QueryVendorInfo(IBaseFilter *iface, LPWSTR *vendor)
00721 {
00722     TRACE("(%p)\n", vendor);
00723     if (!vendor)
00724         return E_POINTER;
00725     *vendor = CoTaskMemAlloc(sizeof(vendor_name));
00726     CopyMemory(*vendor, vendor_name, sizeof(vendor_name));
00727     return S_OK;
00728 }
00729 
00730 
00731 /* SampleGrabber implementation of ISampleGrabber interface */
00732 
00733 /* IUnknown */
00734 static HRESULT WINAPI
00735 SampleGrabber_ISampleGrabber_QueryInterface(ISampleGrabber *iface, REFIID riid, void **ppvObject)
00736 {
00737     return SampleGrabber_query(impl_from_ISampleGrabber(iface), riid, ppvObject);
00738 }
00739 
00740 /* IUnknown */
00741 static ULONG WINAPI
00742 SampleGrabber_ISampleGrabber_AddRef(ISampleGrabber *iface)
00743 {
00744     return SampleGrabber_addref(impl_from_ISampleGrabber(iface));
00745 }
00746 
00747 /* IUnknown */
00748 static ULONG WINAPI
00749 SampleGrabber_ISampleGrabber_Release(ISampleGrabber *iface)
00750 {
00751     return SampleGrabber_release(impl_from_ISampleGrabber(iface));
00752 }
00753 
00754 /* ISampleGrabber */
00755 static HRESULT WINAPI
00756 SampleGrabber_ISampleGrabber_SetOneShot(ISampleGrabber *iface, BOOL oneShot)
00757 {
00758     SG_Impl *This = impl_from_ISampleGrabber(iface);
00759     TRACE("(%p)->(%u)\n", This, oneShot);
00760     This->oneShot = oneShot ? OneShot_Wait : OneShot_None;
00761     return S_OK;
00762 }
00763 
00764 /* ISampleGrabber */
00765 static HRESULT WINAPI
00766 SampleGrabber_ISampleGrabber_SetMediaType(ISampleGrabber *iface, const AM_MEDIA_TYPE *type)
00767 {
00768     SG_Impl *This = impl_from_ISampleGrabber(iface);
00769     TRACE("(%p)->(%p)\n", This, type);
00770     if (!type)
00771         return E_POINTER;
00772     TRACE("Media type: %s/%s ssize: %u format: %s (%u bytes)\n",
00773     debugstr_guid(&type->majortype), debugstr_guid(&type->subtype),
00774     type->lSampleSize,
00775     debugstr_guid(&type->formattype), type->cbFormat);
00776     if (This->mtype.pbFormat)
00777         CoTaskMemFree(This->mtype.pbFormat);
00778     This->mtype = *type;
00779     This->mtype.pUnk = NULL;
00780     if (type->cbFormat) {
00781         This->mtype.pbFormat = CoTaskMemAlloc(type->cbFormat);
00782         CopyMemory(This->mtype.pbFormat, type->pbFormat, type->cbFormat);
00783     }
00784     else
00785         This->mtype.pbFormat = NULL;
00786     return S_OK;
00787 }
00788 
00789 /* ISampleGrabber */
00790 static HRESULT WINAPI
00791 SampleGrabber_ISampleGrabber_GetConnectedMediaType(ISampleGrabber *iface, AM_MEDIA_TYPE *type)
00792 {
00793     SG_Impl *This = impl_from_ISampleGrabber(iface);
00794     TRACE("(%p)->(%p)\n", This, type);
00795     if (!type)
00796         return E_POINTER;
00797     if (!This->pin_in.pair)
00798         return VFW_E_NOT_CONNECTED;
00799     *type = This->mtype;
00800     if (type->cbFormat) {
00801         type->pbFormat = CoTaskMemAlloc(type->cbFormat);
00802         CopyMemory(type->pbFormat, This->mtype.pbFormat, type->cbFormat);
00803     }
00804     return S_OK;
00805 }
00806 
00807 /* ISampleGrabber */
00808 static HRESULT WINAPI
00809 SampleGrabber_ISampleGrabber_SetBufferSamples(ISampleGrabber *iface, BOOL bufferEm)
00810 {
00811     SG_Impl *This = impl_from_ISampleGrabber(iface);
00812     TRACE("(%p)->(%u)\n", This, bufferEm);
00813     EnterCriticalSection(&This->critSect);
00814     if (bufferEm) {
00815         if (This->bufferLen < 0)
00816             This->bufferLen = 0;
00817     }
00818     else
00819         This->bufferLen = -1;
00820     LeaveCriticalSection(&This->critSect);
00821     return S_OK;
00822 }
00823 
00824 /* ISampleGrabber */
00825 static HRESULT WINAPI
00826 SampleGrabber_ISampleGrabber_GetCurrentBuffer(ISampleGrabber *iface, LONG *bufSize, LONG *buffer)
00827 {
00828     SG_Impl *This = impl_from_ISampleGrabber(iface);
00829     HRESULT ret = S_OK;
00830     TRACE("(%p)->(%p, %p)\n", This, bufSize, buffer);
00831     if (!bufSize)
00832         return E_POINTER;
00833     EnterCriticalSection(&This->critSect);
00834     if (!This->pin_in.pair)
00835         ret = VFW_E_NOT_CONNECTED;
00836     else if (This->bufferLen < 0)
00837         ret = E_INVALIDARG;
00838     else if (This->bufferLen == 0)
00839         ret = VFW_E_WRONG_STATE;
00840     else {
00841         if (buffer) {
00842             if (*bufSize >= This->bufferLen)
00843                 CopyMemory(buffer, This->bufferData, This->bufferLen);
00844             else
00845                 ret = E_OUTOFMEMORY;
00846         }
00847         *bufSize = This->bufferLen;
00848     }
00849     LeaveCriticalSection(&This->critSect);
00850     return ret;
00851 }
00852 
00853 /* ISampleGrabber */
00854 static HRESULT WINAPI
00855 SampleGrabber_ISampleGrabber_GetCurrentSample(ISampleGrabber *iface, IMediaSample **sample)
00856 {
00857     /* MS doesn't implement it either, no one should call it */
00858     WARN("(%p): not implemented\n", sample);
00859     return E_NOTIMPL;
00860 }
00861 
00862 /* ISampleGrabber */
00863 static HRESULT WINAPI
00864 SampleGrabber_ISampleGrabber_SetCallback(ISampleGrabber *iface, ISampleGrabberCB *cb, LONG whichMethod)
00865 {
00866     SG_Impl *This = impl_from_ISampleGrabber(iface);
00867     TRACE("(%p)->(%p, %u)\n", This, cb, whichMethod);
00868     if (This->grabberIface)
00869         ISampleGrabberCB_Release(This->grabberIface);
00870     This->grabberIface = cb;
00871     This->grabberMethod = whichMethod;
00872     if (cb)
00873         ISampleGrabberCB_AddRef(cb);
00874     return S_OK;
00875 }
00876 
00877 
00878 /* SampleGrabber implementation of IMemInputPin interface */
00879 
00880 /* IUnknown */
00881 static HRESULT WINAPI
00882 SampleGrabber_IMemInputPin_QueryInterface(IMemInputPin *iface, REFIID riid, void **ppvObject)
00883 {
00884     return SampleGrabber_query(impl_from_IMemInputPin(iface), riid, ppvObject);
00885 }
00886 
00887 /* IUnknown */
00888 static ULONG WINAPI
00889 SampleGrabber_IMemInputPin_AddRef(IMemInputPin *iface)
00890 {
00891     return SampleGrabber_addref(impl_from_IMemInputPin(iface));
00892 }
00893 
00894 /* IUnknown */
00895 static ULONG WINAPI
00896 SampleGrabber_IMemInputPin_Release(IMemInputPin *iface)
00897 {
00898     return SampleGrabber_release(impl_from_IMemInputPin(iface));
00899 }
00900 
00901 /* IMemInputPin */
00902 static HRESULT WINAPI
00903 SampleGrabber_IMemInputPin_GetAllocator(IMemInputPin *iface, IMemAllocator **allocator)
00904 {
00905     SG_Impl *This = impl_from_IMemInputPin(iface);
00906     TRACE("(%p)->(%p) allocator = %p\n", This, allocator, This->allocator);
00907     if (!allocator)
00908         return E_POINTER;
00909     *allocator = This->allocator;
00910     if (!*allocator)
00911         return VFW_E_NO_ALLOCATOR;
00912     IMemAllocator_AddRef(*allocator);
00913     return S_OK;
00914 }
00915 
00916 /* IMemInputPin */
00917 static HRESULT WINAPI
00918 SampleGrabber_IMemInputPin_NotifyAllocator(IMemInputPin *iface, IMemAllocator *allocator, BOOL readOnly)
00919 {
00920     SG_Impl *This = impl_from_IMemInputPin(iface);
00921     TRACE("(%p)->(%p, %u) allocator = %p\n", This, allocator, readOnly, This->allocator);
00922     if (This->allocator == allocator)
00923         return S_OK;
00924     if (This->allocator)
00925         IMemAllocator_Release(This->allocator);
00926     This->allocator = allocator;
00927     if (allocator)
00928         IMemAllocator_AddRef(allocator);
00929     return S_OK;
00930 }
00931 
00932 /* IMemInputPin */
00933 static HRESULT WINAPI
00934 SampleGrabber_IMemInputPin_GetAllocatorRequirements(IMemInputPin *iface, ALLOCATOR_PROPERTIES *props)
00935 {
00936     SG_Impl *This = impl_from_IMemInputPin(iface);
00937     FIXME("(%p)->(%p): semi-stub\n", This, props);
00938     if (!props)
00939         return E_POINTER;
00940     return This->memOutput ? IMemInputPin_GetAllocatorRequirements(This->memOutput, props) : E_NOTIMPL;
00941 }
00942 
00943 /* IMemInputPin */
00944 static HRESULT WINAPI
00945 SampleGrabber_IMemInputPin_Receive(IMemInputPin *iface, IMediaSample *sample)
00946 {
00947     SG_Impl *This = impl_from_IMemInputPin(iface);
00948     HRESULT hr;
00949     TRACE("(%p)->(%p) output = %p, grabber = %p\n", This, sample, This->memOutput, This->grabberIface);
00950     if (!sample)
00951         return E_POINTER;
00952     if ((This->state != State_Running) || (This->oneShot == OneShot_Past))
00953         return S_FALSE;
00954     SampleGrabber_callback(This, sample);
00955     hr = This->memOutput ? IMemInputPin_Receive(This->memOutput, sample) : S_OK;
00956     if (This->oneShot == OneShot_Wait) {
00957         This->oneShot = OneShot_Past;
00958         hr = S_FALSE;
00959         if (This->pin_out.pair)
00960             IPin_EndOfStream(This->pin_out.pair);
00961     }
00962     return hr;
00963 }
00964 
00965 /* IMemInputPin */
00966 static HRESULT WINAPI
00967 SampleGrabber_IMemInputPin_ReceiveMultiple(IMemInputPin *iface, IMediaSample **samples, LONG nSamples, LONG *nProcessed)
00968 {
00969     SG_Impl *This = impl_from_IMemInputPin(iface);
00970     LONG idx;
00971     TRACE("(%p)->(%p, %u, %p) output = %p, grabber = %p\n", This, samples, nSamples, nProcessed, This->memOutput, This->grabberIface);
00972     if (!samples || !nProcessed)
00973         return E_POINTER;
00974     if ((This->state != State_Running) || (This->oneShot == OneShot_Past))
00975         return S_FALSE;
00976     for (idx = 0; idx < nSamples; idx++)
00977         SampleGrabber_callback(This, samples[idx]);
00978     return This->memOutput ? IMemInputPin_ReceiveMultiple(This->memOutput, samples, nSamples, nProcessed) : S_OK;
00979 }
00980 
00981 /* IMemInputPin */
00982 static HRESULT WINAPI
00983 SampleGrabber_IMemInputPin_ReceiveCanBlock(IMemInputPin *iface)
00984 {
00985     SG_Impl *This = impl_from_IMemInputPin(iface);
00986     TRACE("(%p)\n", This);
00987     return This->memOutput ? IMemInputPin_ReceiveCanBlock(This->memOutput) : S_OK;
00988 }
00989 
00990 
00991 /* SampleGrabber member pin implementation */
00992 
00993 /* IUnknown */
00994 static ULONG WINAPI
00995 SampleGrabber_IPin_AddRef(IPin *iface)
00996 {
00997     return SampleGrabber_addref(((SG_Pin *)iface)->sg);
00998 }
00999 
01000 /* IUnknown */
01001 static ULONG WINAPI
01002 SampleGrabber_IPin_Release(IPin *iface)
01003 {
01004     return SampleGrabber_release(((SG_Pin *)iface)->sg);
01005 }
01006 
01007 /* IUnknown */
01008 static HRESULT WINAPI
01009 SampleGrabber_IPin_QueryInterface(IPin *iface, REFIID riid, void **ppvObject)
01010 {
01011     SG_Pin *This = (SG_Pin *)iface;
01012     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
01013 
01014     if (IsEqualIID(riid, &IID_IUnknown) ||
01015         IsEqualIID(riid, &IID_IPin)) {
01016         SampleGrabber_addref(This->sg);
01017         *ppvObject = This;
01018         return S_OK;
01019     }
01020     else if (IsEqualIID(riid, &IID_IMemInputPin)) {
01021         SampleGrabber_addref(This->sg);
01022         *ppvObject = &(This->sg->IMemInputPin_Vtbl);
01023         return S_OK;
01024     }
01025     *ppvObject = NULL;
01026     WARN("(%p, %s,%p): not found\n", This, debugstr_guid(riid), ppvObject);
01027     return E_NOINTERFACE;
01028 }
01029 
01030 /* IPin - input pin */
01031 static HRESULT WINAPI
01032 SampleGrabber_In_IPin_Connect(IPin *iface, IPin *receiver, const AM_MEDIA_TYPE *mtype)
01033 {
01034     WARN("(%p, %p): unexpected\n", receiver, mtype);
01035     return E_UNEXPECTED;
01036 }
01037 
01038 /* IPin - output pin */
01039 static HRESULT WINAPI
01040 SampleGrabber_Out_IPin_Connect(IPin *iface, IPin *receiver, const AM_MEDIA_TYPE *type)
01041 {
01042     SG_Pin *This = (SG_Pin *)iface;
01043     HRESULT hr;
01044     TRACE("(%p)->(%p, %p)\n", This, receiver, type);
01045     if (!receiver)
01046         return E_POINTER;
01047     if (This->pair)
01048         return VFW_E_ALREADY_CONNECTED;
01049     if (This->sg->state != State_Stopped)
01050         return VFW_E_NOT_STOPPED;
01051     if (type) {
01052     TRACE("Media type: %s/%s ssize: %u format: %s (%u bytes)\n",
01053         debugstr_guid(&type->majortype), debugstr_guid(&type->subtype),
01054         type->lSampleSize,
01055         debugstr_guid(&type->formattype), type->cbFormat);
01056     if (!IsEqualGUID(&This->sg->mtype.majortype,&GUID_NULL) &&
01057         !IsEqualGUID(&This->sg->mtype.majortype,&type->majortype))
01058         return VFW_E_TYPE_NOT_ACCEPTED;
01059     if (!IsEqualGUID(&This->sg->mtype.subtype,&MEDIASUBTYPE_None) &&
01060         !IsEqualGUID(&This->sg->mtype.subtype,&type->subtype))
01061         return VFW_E_TYPE_NOT_ACCEPTED;
01062     if (!IsEqualGUID(&This->sg->mtype.formattype,&GUID_NULL) &&
01063         !IsEqualGUID(&This->sg->mtype.formattype,&FORMAT_None) &&
01064         !IsEqualGUID(&This->sg->mtype.formattype,&type->formattype))
01065         return VFW_E_TYPE_NOT_ACCEPTED;
01066     }
01067     else
01068     type = &This->sg->mtype;
01069     if (!IsEqualGUID(&type->formattype, &FORMAT_None) &&
01070     !IsEqualGUID(&type->formattype, &GUID_NULL) &&
01071     !type->pbFormat)
01072     return VFW_E_TYPE_NOT_ACCEPTED;
01073     hr = IPin_ReceiveConnection(receiver,(IPin*)&This->lpVtbl,type);
01074     if (FAILED(hr))
01075     return hr;
01076     This->pair = receiver;
01077     if (This->sg->memOutput) {
01078         IMemInputPin_Release(This->sg->memOutput);
01079         This->sg->memOutput = NULL;
01080     }
01081     IPin_QueryInterface(receiver,&IID_IMemInputPin,(void **)&(This->sg->memOutput));
01082     TRACE("(%p) Accepted IPin %p, IMemInputPin %p\n", This, receiver, This->sg->memOutput);
01083     return S_OK;
01084 }
01085 
01086 /* IPin - input pin */
01087 static HRESULT WINAPI
01088 SampleGrabber_In_IPin_ReceiveConnection(IPin *iface, IPin *connector, const AM_MEDIA_TYPE *type)
01089 {
01090     SG_Pin *This = (SG_Pin *)iface;
01091     TRACE("(%p)->(%p, %p)\n", This, connector, type);
01092     if (!connector)
01093         return E_POINTER;
01094     if (This->pair)
01095         return VFW_E_ALREADY_CONNECTED;
01096     if (This->sg->state != State_Stopped)
01097         return VFW_E_NOT_STOPPED;
01098     if (type) {
01099     TRACE("Media type: %s/%s ssize: %u format: %s (%u bytes)\n",
01100         debugstr_guid(&type->majortype), debugstr_guid(&type->subtype),
01101         type->lSampleSize,
01102         debugstr_guid(&type->formattype), type->cbFormat);
01103     if (!IsEqualGUID(&type->formattype, &FORMAT_None) &&
01104         !IsEqualGUID(&type->formattype, &GUID_NULL) &&
01105         !type->pbFormat)
01106         return VFW_E_INVALIDMEDIATYPE;
01107     if (!IsEqualGUID(&This->sg->mtype.majortype,&GUID_NULL) &&
01108         !IsEqualGUID(&This->sg->mtype.majortype,&type->majortype))
01109         return VFW_E_TYPE_NOT_ACCEPTED;
01110     if (!IsEqualGUID(&This->sg->mtype.subtype,&MEDIASUBTYPE_None) &&
01111         !IsEqualGUID(&This->sg->mtype.subtype,&type->subtype))
01112         return VFW_E_TYPE_NOT_ACCEPTED;
01113     if (!IsEqualGUID(&This->sg->mtype.formattype,&GUID_NULL) &&
01114         !IsEqualGUID(&This->sg->mtype.formattype,&FORMAT_None) &&
01115         !IsEqualGUID(&This->sg->mtype.formattype,&type->formattype))
01116         return VFW_E_TYPE_NOT_ACCEPTED;
01117         if (This->sg->mtype.pbFormat)
01118             CoTaskMemFree(This->sg->mtype.pbFormat);
01119         This->sg->mtype = *type;
01120         This->sg->mtype.pUnk = NULL;
01121         if (type->cbFormat) {
01122             This->sg->mtype.pbFormat = CoTaskMemAlloc(type->cbFormat);
01123             CopyMemory(This->sg->mtype.pbFormat, type->pbFormat, type->cbFormat);
01124         }
01125         else
01126             This->sg->mtype.pbFormat = NULL;
01127     }
01128     This->pair = connector;
01129     TRACE("(%p) Accepted IPin %p\n", This, connector);
01130     return S_OK;
01131 }
01132 
01133 /* IPin - output pin */
01134 static HRESULT WINAPI
01135 SampleGrabber_Out_IPin_ReceiveConnection(IPin *iface, IPin *connector, const AM_MEDIA_TYPE *mtype)
01136 {
01137     WARN("(%p, %p): unexpected\n", connector, mtype);
01138     return E_UNEXPECTED;
01139 }
01140 
01141 /* IPin - input pin */
01142 static HRESULT WINAPI
01143 SampleGrabber_In_IPin_Disconnect(IPin *iface)
01144 {
01145     SG_Pin *This = (SG_Pin *)iface;
01146     TRACE("(%p)->() pair = %p\n", This, This->pair);
01147     if (This->sg->state != State_Stopped)
01148         return VFW_E_NOT_STOPPED;
01149     if (This->pair) {
01150         This->pair = NULL;
01151         return S_OK;
01152     }
01153     return S_FALSE;
01154 }
01155 
01156 /* IPin - output pin */
01157 static HRESULT WINAPI
01158 SampleGrabber_Out_IPin_Disconnect(IPin *iface)
01159 {
01160     SG_Pin *This = (SG_Pin *)iface;
01161     TRACE("(%p)->() pair = %p\n", This, This->pair);
01162     if (This->sg->state != State_Stopped)
01163         return VFW_E_NOT_STOPPED;
01164     if (This->pair) {
01165         This->pair = NULL;
01166         if (This->sg->memOutput) {
01167             IMemInputPin_Release(This->sg->memOutput);
01168             This->sg->memOutput = NULL;
01169         }
01170         return S_OK;
01171     }
01172     return S_FALSE;
01173 }
01174 
01175 /* IPin */
01176 static HRESULT WINAPI
01177 SampleGrabber_IPin_ConnectedTo(IPin *iface, IPin **pin)
01178 {
01179     SG_Pin *This = (SG_Pin *)iface;
01180     TRACE("(%p)->(%p) pair = %p\n", This, pin, This->pair);
01181     if (!pin)
01182         return E_POINTER;
01183     *pin = This->pair;
01184     if (*pin) {
01185         IPin_AddRef(*pin);
01186         return S_OK;
01187     }
01188     return VFW_E_NOT_CONNECTED;
01189 }
01190 
01191 /* IPin */
01192 static HRESULT WINAPI
01193 SampleGrabber_IPin_ConnectionMediaType(IPin *iface, AM_MEDIA_TYPE *mtype)
01194 {
01195     SG_Pin *This = (SG_Pin *)iface;
01196     TRACE("(%p)->(%p)\n", This, mtype);
01197     if (!mtype)
01198         return E_POINTER;
01199     if (!This->pair)
01200         return VFW_E_NOT_CONNECTED;
01201     *mtype = This->sg->mtype;
01202     if (mtype->cbFormat) {
01203         mtype->pbFormat = CoTaskMemAlloc(mtype->cbFormat);
01204         CopyMemory(mtype->pbFormat, This->sg->mtype.pbFormat, mtype->cbFormat);
01205     }
01206     return S_OK;
01207 }
01208 
01209 /* IPin */
01210 static HRESULT WINAPI
01211 SampleGrabber_IPin_QueryPinInfo(IPin *iface, PIN_INFO *info)
01212 {
01213     SG_Pin *This = (SG_Pin *)iface;
01214     TRACE("(%p)->(%p)\n", This, info);
01215     if (!info)
01216         return E_POINTER;
01217     SampleGrabber_addref(This->sg);
01218     info->pFilter = (IBaseFilter *)This->sg;
01219     info->dir = This->dir;
01220     lstrcpynW(info->achName,This->name,MAX_PIN_NAME);
01221     return S_OK;
01222 }
01223 
01224 /* IPin */
01225 static HRESULT WINAPI
01226 SampleGrabber_IPin_QueryDirection(IPin *iface, PIN_DIRECTION *dir)
01227 {
01228     SG_Pin *This = (SG_Pin *)iface;
01229     TRACE("(%p)->(%p)\n", This, dir);
01230     if (!dir)
01231         return E_POINTER;
01232     *dir = This->dir;
01233     return S_OK;
01234 }
01235 
01236 /* IPin */
01237 static HRESULT WINAPI
01238 SampleGrabber_IPin_QueryId(IPin *iface, LPWSTR *id)
01239 {
01240     SG_Pin *This = (SG_Pin *)iface;
01241     int len;
01242     TRACE("(%p)->(%p)\n", This, id);
01243     if (!id)
01244         return E_POINTER;
01245     len = sizeof(WCHAR)*(1+lstrlenW(This->name));
01246     *id = CoTaskMemAlloc(len);
01247     CopyMemory(*id, This->name, len);
01248     return S_OK;
01249 }
01250 
01251 /* IPin */
01252 static HRESULT WINAPI
01253 SampleGrabber_IPin_QueryAccept(IPin *iface, const AM_MEDIA_TYPE *mtype)
01254 {
01255     TRACE("(%p)\n", mtype);
01256     return S_OK;
01257 }
01258 
01259 /* IPin */
01260 static HRESULT WINAPI
01261 SampleGrabber_IPin_EnumMediaTypes(IPin *iface, IEnumMediaTypes **mtypes)
01262 {
01263     SG_Pin *This = (SG_Pin *)iface;
01264     TRACE("(%p)->(%p)\n", This, mtypes);
01265     if (!mtypes)
01266         return E_POINTER;
01267     *mtypes = mediaenum_create(This->sg->pin_in.pair ? &This->sg->mtype : NULL);
01268     return *mtypes ? S_OK : E_OUTOFMEMORY;
01269 }
01270 
01271 /* IPin - input pin */
01272 static HRESULT WINAPI
01273 SampleGrabber_In_IPin_QueryInternalConnections(IPin *iface, IPin **pins, ULONG *nPins)
01274 {
01275     SG_Pin *This = (SG_Pin *)iface;
01276     TRACE("(%p)->(%p, %p) size = %u\n", This, pins, nPins, (nPins ? *nPins : 0));
01277     if (!nPins)
01278         return E_POINTER;
01279     if (*nPins) {
01280     if (!pins)
01281         return E_POINTER;
01282     IPin_AddRef((IPin*)&This->sg->pin_out.lpVtbl);
01283     *pins = (IPin*)&This->sg->pin_out.lpVtbl;
01284     *nPins = 1;
01285     return S_OK;
01286     }
01287     *nPins = 1;
01288     return S_FALSE;
01289 }
01290 
01291 /* IPin - output pin */
01292 static HRESULT WINAPI
01293 SampleGrabber_Out_IPin_QueryInternalConnections(IPin *iface, IPin **pins, ULONG *nPins)
01294 {
01295     WARN("(%p, %p): unexpected\n", pins, nPins);
01296     if (nPins)
01297         *nPins = 0;
01298     return E_NOTIMPL;
01299 }
01300 
01301 /* IPin */
01302 static HRESULT WINAPI
01303 SampleGrabber_IPin_EndOfStream(IPin *iface)
01304 {
01305     FIXME(": stub\n");
01306     return S_OK;
01307 }
01308 
01309 /* IPin */
01310 static HRESULT WINAPI
01311 SampleGrabber_IPin_BeginFlush(IPin *iface)
01312 {
01313     FIXME(": stub\n");
01314     return S_OK;
01315 }
01316 
01317 /* IPin */
01318 static HRESULT WINAPI
01319 SampleGrabber_IPin_EndFlush(IPin *iface)
01320 {
01321     FIXME(": stub\n");
01322     return S_OK;
01323 }
01324 
01325 /* IPin */
01326 static HRESULT WINAPI
01327 SampleGrabber_IPin_NewSegment(IPin *iface, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double rate)
01328 {
01329     FIXME(": stub\n");
01330     return S_OK;
01331 }
01332 
01333 
01334 /* SampleGrabber vtables and constructor */
01335 
01336 static const IBaseFilterVtbl IBaseFilter_VTable =
01337 {
01338     SampleGrabber_IBaseFilter_QueryInterface,
01339     SampleGrabber_IBaseFilter_AddRef,
01340     SampleGrabber_IBaseFilter_Release,
01341     SampleGrabber_IBaseFilter_GetClassID,
01342     SampleGrabber_IBaseFilter_Stop,
01343     SampleGrabber_IBaseFilter_Pause,
01344     SampleGrabber_IBaseFilter_Run,
01345     SampleGrabber_IBaseFilter_GetState,
01346     SampleGrabber_IBaseFilter_SetSyncSource,
01347     SampleGrabber_IBaseFilter_GetSyncSource,
01348     SampleGrabber_IBaseFilter_EnumPins,
01349     SampleGrabber_IBaseFilter_FindPin,
01350     SampleGrabber_IBaseFilter_QueryFilterInfo,
01351     SampleGrabber_IBaseFilter_JoinFilterGraph,
01352     SampleGrabber_IBaseFilter_QueryVendorInfo,
01353 };
01354 
01355 static const ISampleGrabberVtbl ISampleGrabber_VTable =
01356 {
01357     SampleGrabber_ISampleGrabber_QueryInterface,
01358     SampleGrabber_ISampleGrabber_AddRef,
01359     SampleGrabber_ISampleGrabber_Release,
01360     SampleGrabber_ISampleGrabber_SetOneShot,
01361     SampleGrabber_ISampleGrabber_SetMediaType,
01362     SampleGrabber_ISampleGrabber_GetConnectedMediaType,
01363     SampleGrabber_ISampleGrabber_SetBufferSamples,
01364     SampleGrabber_ISampleGrabber_GetCurrentBuffer,
01365     SampleGrabber_ISampleGrabber_GetCurrentSample,
01366     SampleGrabber_ISampleGrabber_SetCallback,
01367 };
01368 
01369 static const IMemInputPinVtbl IMemInputPin_VTable =
01370 {
01371     SampleGrabber_IMemInputPin_QueryInterface,
01372     SampleGrabber_IMemInputPin_AddRef,
01373     SampleGrabber_IMemInputPin_Release,
01374     SampleGrabber_IMemInputPin_GetAllocator,
01375     SampleGrabber_IMemInputPin_NotifyAllocator,
01376     SampleGrabber_IMemInputPin_GetAllocatorRequirements,
01377     SampleGrabber_IMemInputPin_Receive,
01378     SampleGrabber_IMemInputPin_ReceiveMultiple,
01379     SampleGrabber_IMemInputPin_ReceiveCanBlock,
01380 };
01381 
01382 static const IPinVtbl IPin_In_VTable =
01383 {
01384     SampleGrabber_IPin_QueryInterface,
01385     SampleGrabber_IPin_AddRef,
01386     SampleGrabber_IPin_Release,
01387     SampleGrabber_In_IPin_Connect,
01388     SampleGrabber_In_IPin_ReceiveConnection,
01389     SampleGrabber_In_IPin_Disconnect,
01390     SampleGrabber_IPin_ConnectedTo,
01391     SampleGrabber_IPin_ConnectionMediaType,
01392     SampleGrabber_IPin_QueryPinInfo,
01393     SampleGrabber_IPin_QueryDirection,
01394     SampleGrabber_IPin_QueryId,
01395     SampleGrabber_IPin_QueryAccept,
01396     SampleGrabber_IPin_EnumMediaTypes,
01397     SampleGrabber_In_IPin_QueryInternalConnections,
01398     SampleGrabber_IPin_EndOfStream,
01399     SampleGrabber_IPin_BeginFlush,
01400     SampleGrabber_IPin_EndFlush,
01401     SampleGrabber_IPin_NewSegment,
01402 };
01403 
01404 static const IPinVtbl IPin_Out_VTable =
01405 {
01406     SampleGrabber_IPin_QueryInterface,
01407     SampleGrabber_IPin_AddRef,
01408     SampleGrabber_IPin_Release,
01409     SampleGrabber_Out_IPin_Connect,
01410     SampleGrabber_Out_IPin_ReceiveConnection,
01411     SampleGrabber_Out_IPin_Disconnect,
01412     SampleGrabber_IPin_ConnectedTo,
01413     SampleGrabber_IPin_ConnectionMediaType,
01414     SampleGrabber_IPin_QueryPinInfo,
01415     SampleGrabber_IPin_QueryDirection,
01416     SampleGrabber_IPin_QueryId,
01417     SampleGrabber_IPin_QueryAccept,
01418     SampleGrabber_IPin_EnumMediaTypes,
01419     SampleGrabber_Out_IPin_QueryInternalConnections,
01420     SampleGrabber_IPin_EndOfStream,
01421     SampleGrabber_IPin_BeginFlush,
01422     SampleGrabber_IPin_EndFlush,
01423     SampleGrabber_IPin_NewSegment,
01424 };
01425 
01426 HRESULT SampleGrabber_create(IUnknown *pUnkOuter, LPVOID *ppv)
01427 {
01428     SG_Impl* obj = NULL;
01429 
01430     TRACE("(%p,%p)\n", ppv, pUnkOuter);
01431 
01432     if (pUnkOuter)
01433         return CLASS_E_NOAGGREGATION;
01434 
01435     obj = CoTaskMemAlloc(sizeof(SG_Impl));
01436     if (NULL == obj) {
01437         *ppv = NULL;
01438         return E_OUTOFMEMORY;
01439     }
01440     ZeroMemory(obj, sizeof(SG_Impl));
01441 
01442     obj->refCount = 1;
01443     obj->IBaseFilter_Vtbl = &IBaseFilter_VTable;
01444     obj->ISampleGrabber_Vtbl = &ISampleGrabber_VTable;
01445     obj->IMemInputPin_Vtbl = &IMemInputPin_VTable;
01446     obj->pin_in.lpVtbl = &IPin_In_VTable;
01447     obj->pin_in.dir = PINDIR_INPUT;
01448     obj->pin_in.name = pin_in_name;
01449     obj->pin_in.sg = obj;
01450     obj->pin_in.pair = NULL;
01451     obj->pin_out.lpVtbl = &IPin_Out_VTable;
01452     obj->pin_out.dir = PINDIR_OUTPUT;
01453     obj->pin_out.name = pin_out_name;
01454     obj->pin_out.sg = obj;
01455     obj->pin_out.pair = NULL;
01456     InitializeCriticalSection(&obj->critSect);
01457     obj->critSect.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": SG_Impl.critSect");
01458     obj->info.achName[0] = 0;
01459     obj->info.pGraph = NULL;
01460     obj->state = State_Stopped;
01461     obj->mtype.majortype = GUID_NULL;
01462     obj->mtype.subtype = MEDIASUBTYPE_None;
01463     obj->mtype.formattype = FORMAT_None;
01464     obj->allocator = NULL;
01465     obj->refClock = NULL;
01466     obj->memOutput = NULL;
01467     obj->grabberIface = NULL;
01468     obj->grabberMethod = -1;
01469     obj->oneShot = OneShot_None;
01470     obj->bufferLen = -1;
01471     obj->bufferData = NULL;
01472     *ppv = obj;
01473 
01474     return S_OK;
01475 }

Generated on Sat May 26 2012 04:20:27 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.