Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygensamplegrabber.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
1.7.6.1
|