Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenparser.c
Go to the documentation of this file.
00001 /* 00002 * Parser (Base for parsers and splitters) 00003 * 00004 * Copyright 2003 Robert Shearman 00005 * Copyright 2004-2005 Christian Costa 00006 * 00007 * This library is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * This library is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with this library; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00020 */ 00021 00022 #include "quartz_private.h" 00023 #include "control_private.h" 00024 #include "pin.h" 00025 00026 #include "vfwmsgs.h" 00027 #include "amvideo.h" 00028 00029 #include "wine/unicode.h" 00030 #include "wine/debug.h" 00031 00032 #include <math.h> 00033 #include <assert.h> 00034 00035 #include "parser.h" 00036 00037 WINE_DEFAULT_DEBUG_CHANNEL(quartz); 00038 00039 static const WCHAR wcsInputPinName[] = {'i','n','p','u','t',' ','p','i','n',0}; 00040 static const IMediaSeekingVtbl Parser_Seeking_Vtbl; 00041 static const IPinVtbl Parser_OutputPin_Vtbl; 00042 static const IPinVtbl Parser_InputPin_Vtbl; 00043 00044 static HRESULT Parser_OutputPin_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt); 00045 static HRESULT Parser_ChangeCurrent(IBaseFilter *iface); 00046 static HRESULT Parser_ChangeStop(IBaseFilter *iface); 00047 static HRESULT Parser_ChangeRate(IBaseFilter *iface); 00048 00049 static inline ParserImpl *impl_from_IMediaSeeking( IMediaSeeking *iface ) 00050 { 00051 return (ParserImpl *)((char*)iface - FIELD_OFFSET(ParserImpl, mediaSeeking.lpVtbl)); 00052 } 00053 00054 00055 HRESULT Parser_Create(ParserImpl* pParser, const IBaseFilterVtbl *Parser_Vtbl, const CLSID* pClsid, PFN_PROCESS_SAMPLE fnProcessSample, PFN_QUERY_ACCEPT fnQueryAccept, PFN_PRE_CONNECT fnPreConnect, PFN_CLEANUP fnCleanup, PFN_DISCONNECT fnDisconnect, REQUESTPROC fnRequest, STOPPROCESSPROC fnDone, CHANGEPROC stop, CHANGEPROC current, CHANGEPROC rate) 00056 { 00057 HRESULT hr; 00058 PIN_INFO piInput; 00059 00060 /* pTransformFilter is already allocated */ 00061 pParser->clsid = *pClsid; 00062 pParser->lpVtbl = Parser_Vtbl; 00063 pParser->refCount = 1; 00064 InitializeCriticalSection(&pParser->csFilter); 00065 pParser->csFilter.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": ParserImpl.csFilter"); 00066 pParser->state = State_Stopped; 00067 pParser->pClock = NULL; 00068 pParser->fnDisconnect = fnDisconnect; 00069 ZeroMemory(&pParser->filterInfo, sizeof(FILTER_INFO)); 00070 pParser->lastpinchange = GetTickCount(); 00071 00072 pParser->cStreams = 0; 00073 pParser->ppPins = CoTaskMemAlloc(1 * sizeof(IPin *)); 00074 00075 /* construct input pin */ 00076 piInput.dir = PINDIR_INPUT; 00077 piInput.pFilter = (IBaseFilter *)pParser; 00078 lstrcpynW(piInput.achName, wcsInputPinName, sizeof(piInput.achName) / sizeof(piInput.achName[0])); 00079 00080 if (!current) 00081 current = Parser_ChangeCurrent; 00082 00083 if (!stop) 00084 stop = Parser_ChangeStop; 00085 00086 if (!rate) 00087 rate = Parser_ChangeRate; 00088 00089 MediaSeekingImpl_Init((IBaseFilter*)pParser, stop, current, rate, &pParser->mediaSeeking, &pParser->csFilter); 00090 pParser->mediaSeeking.lpVtbl = &Parser_Seeking_Vtbl; 00091 00092 hr = PullPin_Construct(&Parser_InputPin_Vtbl, &piInput, fnProcessSample, (LPVOID)pParser, fnQueryAccept, fnCleanup, fnRequest, fnDone, &pParser->csFilter, (IPin **)&pParser->pInputPin); 00093 00094 if (SUCCEEDED(hr)) 00095 { 00096 pParser->ppPins[0] = (IPin *)pParser->pInputPin; 00097 pParser->pInputPin->fnPreConnect = fnPreConnect; 00098 } 00099 else 00100 { 00101 CoTaskMemFree(pParser->ppPins); 00102 pParser->csFilter.DebugInfo->Spare[0] = 0; 00103 DeleteCriticalSection(&pParser->csFilter); 00104 CoTaskMemFree(pParser); 00105 } 00106 00107 return hr; 00108 } 00109 00110 HRESULT WINAPI Parser_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv) 00111 { 00112 ParserImpl *This = (ParserImpl *)iface; 00113 TRACE("(%s, %p)\n", qzdebugstr_guid(riid), ppv); 00114 00115 *ppv = NULL; 00116 00117 if (IsEqualIID(riid, &IID_IUnknown)) 00118 *ppv = This; 00119 else if (IsEqualIID(riid, &IID_IPersist)) 00120 *ppv = This; 00121 else if (IsEqualIID(riid, &IID_IMediaFilter)) 00122 *ppv = This; 00123 else if (IsEqualIID(riid, &IID_IBaseFilter)) 00124 *ppv = This; 00125 else if (IsEqualIID(riid, &IID_IMediaSeeking)) 00126 *ppv = &This->mediaSeeking; 00127 00128 if (*ppv) 00129 { 00130 IUnknown_AddRef((IUnknown *)(*ppv)); 00131 return S_OK; 00132 } 00133 00134 if (!IsEqualIID(riid, &IID_IPin) && !IsEqualIID(riid, &IID_IVideoWindow)) 00135 FIXME("No interface for %s!\n", qzdebugstr_guid(riid)); 00136 00137 return E_NOINTERFACE; 00138 } 00139 00140 ULONG WINAPI Parser_AddRef(IBaseFilter * iface) 00141 { 00142 ParserImpl *This = (ParserImpl *)iface; 00143 ULONG refCount = InterlockedIncrement(&This->refCount); 00144 00145 TRACE("(%p/%p)->() AddRef from %d\n", This, iface, refCount - 1); 00146 00147 return refCount; 00148 } 00149 00150 void Parser_Destroy(ParserImpl *This) 00151 { 00152 IPin *connected = NULL; 00153 ULONG pinref; 00154 00155 assert(!This->refCount); 00156 PullPin_WaitForStateChange(This->pInputPin, INFINITE); 00157 00158 if (This->pClock) 00159 IReferenceClock_Release(This->pClock); 00160 00161 /* Don't need to clean up output pins, freeing input pin will do that */ 00162 IPin_ConnectedTo((IPin *)This->pInputPin, &connected); 00163 if (connected) 00164 { 00165 assert(IPin_Disconnect(connected) == S_OK); 00166 IPin_Release(connected); 00167 assert(IPin_Disconnect((IPin *)This->pInputPin) == S_OK); 00168 } 00169 pinref = IPin_Release((IPin *)This->pInputPin); 00170 if (pinref) 00171 { 00172 /* Valgrind could find this, if I kill it here */ 00173 ERR("pinref should be null, is %u, destroying anyway\n", pinref); 00174 assert((LONG)pinref > 0); 00175 00176 while (pinref) 00177 pinref = IPin_Release((IPin *)This->pInputPin); 00178 } 00179 00180 CoTaskMemFree(This->ppPins); 00181 This->lpVtbl = NULL; 00182 00183 This->csFilter.DebugInfo->Spare[0] = 0; 00184 DeleteCriticalSection(&This->csFilter); 00185 00186 TRACE("Destroying parser\n"); 00187 CoTaskMemFree(This); 00188 } 00189 00190 ULONG WINAPI Parser_Release(IBaseFilter * iface) 00191 { 00192 ParserImpl *This = (ParserImpl *)iface; 00193 ULONG refCount = InterlockedDecrement(&This->refCount); 00194 00195 TRACE("(%p)->() Release from %d\n", This, refCount + 1); 00196 00197 if (!refCount) 00198 Parser_Destroy(This); 00199 00200 return refCount; 00201 } 00202 00205 HRESULT WINAPI Parser_GetClassID(IBaseFilter * iface, CLSID * pClsid) 00206 { 00207 ParserImpl *This = (ParserImpl *)iface; 00208 00209 TRACE("(%p)\n", pClsid); 00210 00211 *pClsid = This->clsid; 00212 00213 return S_OK; 00214 } 00215 00218 HRESULT WINAPI Parser_Stop(IBaseFilter * iface) 00219 { 00220 ParserImpl *This = (ParserImpl *)iface; 00221 PullPin *pin = (PullPin *)This->ppPins[0]; 00222 ULONG i; 00223 00224 TRACE("()\n"); 00225 00226 EnterCriticalSection(&pin->thread_lock); 00227 00228 IAsyncReader_BeginFlush(This->pInputPin->pReader); 00229 EnterCriticalSection(&This->csFilter); 00230 00231 if (This->state == State_Stopped) 00232 { 00233 LeaveCriticalSection(&This->csFilter); 00234 IAsyncReader_EndFlush(This->pInputPin->pReader); 00235 LeaveCriticalSection(&pin->thread_lock); 00236 return S_OK; 00237 } 00238 00239 This->state = State_Stopped; 00240 00241 for (i = 1; i < (This->cStreams + 1); i++) 00242 { 00243 OutputPin_DecommitAllocator((OutputPin *)This->ppPins[i]); 00244 } 00245 00246 LeaveCriticalSection(&This->csFilter); 00247 00248 PullPin_PauseProcessing(This->pInputPin); 00249 PullPin_WaitForStateChange(This->pInputPin, INFINITE); 00250 IAsyncReader_EndFlush(This->pInputPin->pReader); 00251 00252 LeaveCriticalSection(&pin->thread_lock); 00253 return S_OK; 00254 } 00255 00256 HRESULT WINAPI Parser_Pause(IBaseFilter * iface) 00257 { 00258 HRESULT hr = S_OK; 00259 ParserImpl *This = (ParserImpl *)iface; 00260 PullPin *pin = (PullPin *)This->ppPins[0]; 00261 00262 TRACE("()\n"); 00263 00264 EnterCriticalSection(&pin->thread_lock); 00265 EnterCriticalSection(&This->csFilter); 00266 00267 if (This->state == State_Paused) 00268 { 00269 LeaveCriticalSection(&This->csFilter); 00270 LeaveCriticalSection(&pin->thread_lock); 00271 return S_OK; 00272 } 00273 00274 if (This->state == State_Stopped) 00275 { 00276 LeaveCriticalSection(&This->csFilter); 00277 hr = IBaseFilter_Run(iface, -1); 00278 EnterCriticalSection(&This->csFilter); 00279 } 00280 00281 if (SUCCEEDED(hr)) 00282 This->state = State_Paused; 00283 00284 LeaveCriticalSection(&This->csFilter); 00285 LeaveCriticalSection(&pin->thread_lock); 00286 00287 return hr; 00288 } 00289 00290 HRESULT WINAPI Parser_Run(IBaseFilter * iface, REFERENCE_TIME tStart) 00291 { 00292 HRESULT hr = S_OK; 00293 ParserImpl *This = (ParserImpl *)iface; 00294 PullPin *pin = (PullPin *)This->ppPins[0]; 00295 00296 ULONG i; 00297 00298 TRACE("(%s)\n", wine_dbgstr_longlong(tStart)); 00299 00300 EnterCriticalSection(&pin->thread_lock); 00301 EnterCriticalSection(&This->csFilter); 00302 { 00303 HRESULT hr_any = VFW_E_NOT_CONNECTED; 00304 00305 if (This->state == State_Running || This->state == State_Paused) 00306 { 00307 This->state = State_Running; 00308 LeaveCriticalSection(&This->csFilter); 00309 LeaveCriticalSection(&pin->thread_lock); 00310 return S_OK; 00311 } 00312 00313 This->rtStreamStart = tStart; 00314 00315 for (i = 1; i < (This->cStreams + 1); i++) 00316 { 00317 hr = OutputPin_CommitAllocator((OutputPin *)This->ppPins[i]); 00318 if (SUCCEEDED(hr)) 00319 hr_any = hr; 00320 } 00321 00322 hr = hr_any; 00323 if (SUCCEEDED(hr)) 00324 { 00325 LeaveCriticalSection(&This->csFilter); 00326 hr = PullPin_StartProcessing(This->pInputPin); 00327 EnterCriticalSection(&This->csFilter); 00328 } 00329 00330 if (SUCCEEDED(hr)) 00331 This->state = State_Running; 00332 } 00333 LeaveCriticalSection(&This->csFilter); 00334 LeaveCriticalSection(&pin->thread_lock); 00335 00336 return hr; 00337 } 00338 00339 HRESULT WINAPI Parser_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState) 00340 { 00341 ParserImpl *This = (ParserImpl *)iface; 00342 PullPin *pin = (PullPin *)This->ppPins[0]; 00343 HRESULT hr = S_OK; 00344 00345 TRACE("(%d, %p)\n", dwMilliSecsTimeout, pState); 00346 00347 EnterCriticalSection(&pin->thread_lock); 00348 EnterCriticalSection(&This->csFilter); 00349 { 00350 *pState = This->state; 00351 } 00352 LeaveCriticalSection(&This->csFilter); 00353 00354 if (This->pInputPin && (PullPin_WaitForStateChange(This->pInputPin, dwMilliSecsTimeout) == S_FALSE)) 00355 hr = VFW_S_STATE_INTERMEDIATE; 00356 LeaveCriticalSection(&pin->thread_lock); 00357 00358 return hr; 00359 } 00360 00361 HRESULT WINAPI Parser_SetSyncSource(IBaseFilter * iface, IReferenceClock *pClock) 00362 { 00363 ParserImpl *This = (ParserImpl *)iface; 00364 PullPin *pin = (PullPin *)This->ppPins[0]; 00365 00366 TRACE("(%p)\n", pClock); 00367 00368 EnterCriticalSection(&pin->thread_lock); 00369 EnterCriticalSection(&This->csFilter); 00370 { 00371 if (This->pClock) 00372 IReferenceClock_Release(This->pClock); 00373 This->pClock = pClock; 00374 if (This->pClock) 00375 IReferenceClock_AddRef(This->pClock); 00376 } 00377 LeaveCriticalSection(&This->csFilter); 00378 LeaveCriticalSection(&pin->thread_lock); 00379 00380 return S_OK; 00381 } 00382 00383 HRESULT WINAPI Parser_GetSyncSource(IBaseFilter * iface, IReferenceClock **ppClock) 00384 { 00385 ParserImpl *This = (ParserImpl *)iface; 00386 00387 TRACE("(%p)\n", ppClock); 00388 00389 EnterCriticalSection(&This->csFilter); 00390 { 00391 *ppClock = This->pClock; 00392 if (This->pClock) 00393 IReferenceClock_AddRef(This->pClock); 00394 } 00395 LeaveCriticalSection(&This->csFilter); 00396 00397 return S_OK; 00398 } 00399 00402 /* FIXME: WRONG */ 00403 static HRESULT Parser_GetPin(IBaseFilter *iface, ULONG pos, IPin **pin, DWORD *lastsynctick) 00404 { 00405 ParserImpl *This = (ParserImpl *)iface; 00406 00407 *lastsynctick = This->lastpinchange; 00408 00409 TRACE("Asking for pos %x\n", pos); 00410 00411 /* Input pin also has a pin, hence the > and not >= */ 00412 if (pos > This->cStreams) 00413 return S_FALSE; 00414 00415 *pin = This->ppPins[pos]; 00416 IPin_AddRef(*pin); 00417 return S_OK; 00418 } 00419 00420 HRESULT WINAPI Parser_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum) 00421 { 00422 ParserImpl *This = (ParserImpl *)iface; 00423 00424 TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum); 00425 00426 return IEnumPinsImpl_Construct(ppEnum, Parser_GetPin, iface); 00427 } 00428 00429 HRESULT WINAPI Parser_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin) 00430 { 00431 FIXME("(%p)->(%s,%p)\n", iface, debugstr_w(Id), ppPin); 00432 00433 /* FIXME: critical section */ 00434 00435 return E_NOTIMPL; 00436 } 00437 00438 HRESULT WINAPI Parser_QueryFilterInfo(IBaseFilter * iface, FILTER_INFO *pInfo) 00439 { 00440 ParserImpl *This = (ParserImpl *)iface; 00441 00442 TRACE("(%p)\n", pInfo); 00443 00444 strcpyW(pInfo->achName, This->filterInfo.achName); 00445 pInfo->pGraph = This->filterInfo.pGraph; 00446 00447 if (pInfo->pGraph) 00448 IFilterGraph_AddRef(pInfo->pGraph); 00449 00450 return S_OK; 00451 } 00452 00453 HRESULT WINAPI Parser_JoinFilterGraph(IBaseFilter * iface, IFilterGraph *pGraph, LPCWSTR pName) 00454 { 00455 HRESULT hr = S_OK; 00456 ParserImpl *This = (ParserImpl *)iface; 00457 00458 TRACE("(%p, %s)\n", pGraph, debugstr_w(pName)); 00459 00460 EnterCriticalSection(&This->csFilter); 00461 { 00462 if (pName) 00463 strcpyW(This->filterInfo.achName, pName); 00464 else 00465 *This->filterInfo.achName = '\0'; 00466 This->filterInfo.pGraph = pGraph; /* NOTE: do NOT increase ref. count */ 00467 } 00468 LeaveCriticalSection(&This->csFilter); 00469 00470 return hr; 00471 } 00472 00473 HRESULT WINAPI Parser_QueryVendorInfo(IBaseFilter * iface, LPWSTR *pVendorInfo) 00474 { 00475 TRACE("(%p)\n", pVendorInfo); 00476 return E_NOTIMPL; 00477 } 00478 00479 HRESULT Parser_AddPin(ParserImpl * This, const PIN_INFO * piOutput, ALLOCATOR_PROPERTIES * props, const AM_MEDIA_TYPE * amt) 00480 { 00481 IPin ** ppOldPins; 00482 HRESULT hr; 00483 00484 ppOldPins = This->ppPins; 00485 00486 This->ppPins = CoTaskMemAlloc((This->cStreams + 2) * sizeof(IPin *)); 00487 memcpy(This->ppPins, ppOldPins, (This->cStreams + 1) * sizeof(IPin *)); 00488 00489 hr = OutputPin_Construct(&Parser_OutputPin_Vtbl, sizeof(Parser_OutputPin), piOutput, props, NULL, Parser_OutputPin_QueryAccept, &This->csFilter, This->ppPins + (This->cStreams + 1)); 00490 00491 if (SUCCEEDED(hr)) 00492 { 00493 IPin *pPin = This->ppPins[This->cStreams + 1]; 00494 Parser_OutputPin *pin = (Parser_OutputPin *)pPin; 00495 pin->pmt = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE)); 00496 CopyMediaType(pin->pmt, amt); 00497 pin->dwSamplesProcessed = 0; 00498 00499 pin->pin.pin.pUserData = This->ppPins[This->cStreams + 1]; 00500 pin->pin.pin.pinInfo.pFilter = (LPVOID)This; 00501 pin->pin.custom_allocator = 1; 00502 This->cStreams++; 00503 This->lastpinchange = GetTickCount(); 00504 CoTaskMemFree(ppOldPins); 00505 } 00506 else 00507 { 00508 CoTaskMemFree(This->ppPins); 00509 This->ppPins = ppOldPins; 00510 ERR("Failed with error %x\n", hr); 00511 } 00512 00513 return hr; 00514 } 00515 00516 static HRESULT Parser_RemoveOutputPins(ParserImpl * This) 00517 { 00518 /* NOTE: should be in critical section when calling this function */ 00519 HRESULT hr; 00520 ULONG i; 00521 IPin ** ppOldPins = This->ppPins; 00522 00523 TRACE("(%p)\n", This); 00524 00525 /* reduce the pin array down to 1 (just our input pin) */ 00526 This->ppPins = CoTaskMemAlloc(sizeof(IPin *) * 1); 00527 memcpy(This->ppPins, ppOldPins, sizeof(IPin *) * 1); 00528 00529 for (i = 0; i < This->cStreams; i++) 00530 { 00531 hr = OutputPin_DeliverDisconnect((OutputPin *)ppOldPins[i + 1]); 00532 TRACE("Disconnect: %08x\n", hr); 00533 IPin_Release(ppOldPins[i + 1]); 00534 } 00535 00536 This->lastpinchange = GetTickCount(); 00537 This->cStreams = 0; 00538 CoTaskMemFree(ppOldPins); 00539 00540 return S_OK; 00541 } 00542 00543 static HRESULT Parser_ChangeCurrent(IBaseFilter *iface) 00544 { 00545 FIXME("(%p) filter hasn't implemented current position change!\n", iface); 00546 return S_OK; 00547 } 00548 00549 static HRESULT Parser_ChangeStop(IBaseFilter *iface) 00550 { 00551 FIXME("(%p) filter hasn't implemented stop position change!\n", iface); 00552 return S_OK; 00553 } 00554 00555 static HRESULT Parser_ChangeRate(IBaseFilter *iface) 00556 { 00557 FIXME("(%p) filter hasn't implemented rate change!\n", iface); 00558 return S_OK; 00559 } 00560 00561 00562 static HRESULT WINAPI Parser_Seeking_QueryInterface(IMediaSeeking * iface, REFIID riid, LPVOID * ppv) 00563 { 00564 ParserImpl *This = impl_from_IMediaSeeking(iface); 00565 00566 return IUnknown_QueryInterface((IUnknown *)This, riid, ppv); 00567 } 00568 00569 static ULONG WINAPI Parser_Seeking_AddRef(IMediaSeeking * iface) 00570 { 00571 ParserImpl *This = impl_from_IMediaSeeking(iface); 00572 00573 return IUnknown_AddRef((IUnknown *)This); 00574 } 00575 00576 static ULONG WINAPI Parser_Seeking_Release(IMediaSeeking * iface) 00577 { 00578 ParserImpl *This = impl_from_IMediaSeeking(iface); 00579 00580 return IUnknown_Release((IUnknown *)This); 00581 } 00582 00583 static const IMediaSeekingVtbl Parser_Seeking_Vtbl = 00584 { 00585 Parser_Seeking_QueryInterface, 00586 Parser_Seeking_AddRef, 00587 Parser_Seeking_Release, 00588 MediaSeekingImpl_GetCapabilities, 00589 MediaSeekingImpl_CheckCapabilities, 00590 MediaSeekingImpl_IsFormatSupported, 00591 MediaSeekingImpl_QueryPreferredFormat, 00592 MediaSeekingImpl_GetTimeFormat, 00593 MediaSeekingImpl_IsUsingTimeFormat, 00594 MediaSeekingImpl_SetTimeFormat, 00595 MediaSeekingImpl_GetDuration, 00596 MediaSeekingImpl_GetStopPosition, 00597 MediaSeekingImpl_GetCurrentPosition, 00598 MediaSeekingImpl_ConvertTimeFormat, 00599 MediaSeekingImpl_SetPositions, 00600 MediaSeekingImpl_GetPositions, 00601 MediaSeekingImpl_GetAvailable, 00602 MediaSeekingImpl_SetRate, 00603 MediaSeekingImpl_GetRate, 00604 MediaSeekingImpl_GetPreroll 00605 }; 00606 00607 static HRESULT WINAPI Parser_OutputPin_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv) 00608 { 00609 Parser_OutputPin *This = (Parser_OutputPin *)iface; 00610 00611 TRACE("(%s, %p)\n", qzdebugstr_guid(riid), ppv); 00612 00613 *ppv = NULL; 00614 00615 if (IsEqualIID(riid, &IID_IUnknown)) 00616 *ppv = iface; 00617 else if (IsEqualIID(riid, &IID_IPin)) 00618 *ppv = iface; 00619 else if (IsEqualIID(riid, &IID_IMediaSeeking)) 00620 { 00621 return IBaseFilter_QueryInterface(This->pin.pin.pinInfo.pFilter, &IID_IMediaSeeking, ppv); 00622 } 00623 00624 if (*ppv) 00625 { 00626 IUnknown_AddRef((IUnknown *)(*ppv)); 00627 return S_OK; 00628 } 00629 00630 FIXME("No interface for %s!\n", qzdebugstr_guid(riid)); 00631 00632 return E_NOINTERFACE; 00633 } 00634 00635 static ULONG WINAPI Parser_OutputPin_Release(IPin * iface) 00636 { 00637 Parser_OutputPin *This = (Parser_OutputPin *)iface; 00638 ULONG refCount = InterlockedDecrement(&This->pin.pin.refCount); 00639 00640 TRACE("(%p)->() Release from %d\n", iface, refCount + 1); 00641 00642 if (!refCount) 00643 { 00644 FreeMediaType(This->pmt); 00645 CoTaskMemFree(This->pmt); 00646 FreeMediaType(&This->pin.pin.mtCurrent); 00647 CoTaskMemFree(This); 00648 return 0; 00649 } 00650 return refCount; 00651 } 00652 00653 static HRESULT WINAPI Parser_OutputPin_EnumMediaTypes(IPin * iface, IEnumMediaTypes ** ppEnum) 00654 { 00655 ENUMMEDIADETAILS emd; 00656 Parser_OutputPin *This = (Parser_OutputPin *)iface; 00657 00658 TRACE("(%p)\n", ppEnum); 00659 00660 /* override this method to allow enumeration of your types */ 00661 emd.cMediaTypes = 1; 00662 emd.pMediaTypes = This->pmt; 00663 00664 return IEnumMediaTypesImpl_Construct(&emd, ppEnum); 00665 } 00666 00667 static HRESULT WINAPI Parser_OutputPin_Connect(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt) 00668 { 00669 Parser_OutputPin *This = (Parser_OutputPin *)iface; 00670 ParserImpl *parser = (ParserImpl *)This->pin.pin.pinInfo.pFilter; 00671 00672 /* Set the allocator to our input pin's */ 00673 EnterCriticalSection(This->pin.pin.pCritSec); 00674 This->pin.alloc = parser->pInputPin->pAlloc; 00675 LeaveCriticalSection(This->pin.pin.pCritSec); 00676 00677 return OutputPin_Connect(iface, pReceivePin, pmt); 00678 } 00679 00680 static HRESULT Parser_OutputPin_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt) 00681 { 00682 Parser_OutputPin *This = iface; 00683 00684 TRACE("()\n"); 00685 dump_AM_MEDIA_TYPE(pmt); 00686 00687 return (memcmp(This->pmt, pmt, sizeof(AM_MEDIA_TYPE)) == 0); 00688 } 00689 00690 static const IPinVtbl Parser_OutputPin_Vtbl = 00691 { 00692 Parser_OutputPin_QueryInterface, 00693 IPinImpl_AddRef, 00694 Parser_OutputPin_Release, 00695 Parser_OutputPin_Connect, 00696 OutputPin_ReceiveConnection, 00697 OutputPin_Disconnect, 00698 IPinImpl_ConnectedTo, 00699 IPinImpl_ConnectionMediaType, 00700 IPinImpl_QueryPinInfo, 00701 IPinImpl_QueryDirection, 00702 IPinImpl_QueryId, 00703 IPinImpl_QueryAccept, 00704 Parser_OutputPin_EnumMediaTypes, 00705 IPinImpl_QueryInternalConnections, 00706 OutputPin_EndOfStream, 00707 OutputPin_BeginFlush, 00708 OutputPin_EndFlush, 00709 OutputPin_NewSegment 00710 }; 00711 00712 static HRESULT WINAPI Parser_PullPin_Disconnect(IPin * iface) 00713 { 00714 HRESULT hr; 00715 PullPin *This = (PullPin *)iface; 00716 00717 TRACE("()\n"); 00718 00719 EnterCriticalSection(&This->thread_lock); 00720 EnterCriticalSection(This->pin.pCritSec); 00721 { 00722 if (This->pin.pConnectedTo) 00723 { 00724 FILTER_STATE state; 00725 ParserImpl *Parser = (ParserImpl *)This->pin.pinInfo.pFilter; 00726 00727 LeaveCriticalSection(This->pin.pCritSec); 00728 hr = IBaseFilter_GetState(This->pin.pinInfo.pFilter, INFINITE, &state); 00729 EnterCriticalSection(This->pin.pCritSec); 00730 00731 if (SUCCEEDED(hr) && (state == State_Stopped) && SUCCEEDED(Parser->fnDisconnect(Parser))) 00732 { 00733 LeaveCriticalSection(This->pin.pCritSec); 00734 PullPin_Disconnect(iface); 00735 EnterCriticalSection(This->pin.pCritSec); 00736 hr = Parser_RemoveOutputPins((ParserImpl *)This->pin.pinInfo.pFilter); 00737 } 00738 else 00739 hr = VFW_E_NOT_STOPPED; 00740 } 00741 else 00742 hr = S_FALSE; 00743 } 00744 LeaveCriticalSection(This->pin.pCritSec); 00745 LeaveCriticalSection(&This->thread_lock); 00746 00747 return hr; 00748 } 00749 00750 static HRESULT WINAPI Parser_PullPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt) 00751 { 00752 HRESULT hr; 00753 00754 TRACE("()\n"); 00755 00756 hr = PullPin_ReceiveConnection(iface, pReceivePin, pmt); 00757 if (FAILED(hr)) 00758 { 00759 IPinImpl *This = (IPinImpl *)iface; 00760 00761 EnterCriticalSection(This->pCritSec); 00762 Parser_RemoveOutputPins((ParserImpl *)This->pinInfo.pFilter); 00763 LeaveCriticalSection(This->pCritSec); 00764 } 00765 00766 return hr; 00767 } 00768 00769 static const IPinVtbl Parser_InputPin_Vtbl = 00770 { 00771 PullPin_QueryInterface, 00772 IPinImpl_AddRef, 00773 PullPin_Release, 00774 InputPin_Connect, 00775 Parser_PullPin_ReceiveConnection, 00776 Parser_PullPin_Disconnect, 00777 IPinImpl_ConnectedTo, 00778 IPinImpl_ConnectionMediaType, 00779 IPinImpl_QueryPinInfo, 00780 IPinImpl_QueryDirection, 00781 IPinImpl_QueryId, 00782 IPinImpl_QueryAccept, 00783 IPinImpl_EnumMediaTypes, 00784 IPinImpl_QueryInternalConnections, 00785 PullPin_EndOfStream, 00786 PullPin_BeginFlush, 00787 PullPin_EndFlush, 00788 PullPin_NewSegment 00789 }; Generated on Mon May 28 2012 04:17:16 for ReactOS by
1.7.6.1
|