2 * Implements IBaseFilter for parsers. (internal)
4 * hidenori@a2.ctktv.ne.jp
6 * FIXME - handle errors/flushing correctly.
7 * FIXME - handle seeking.
23 #include "debugtools.h"
24 DEFAULT_DEBUG_CHANNEL(quartz);
26 #include "quartz_private.h"
31 #define QUARTZ_MSG_FLUSH (WM_APP+1)
32 #define QUARTZ_MSG_EXITTHREAD (WM_APP+2)
33 #define QUARTZ_MSG_SEEK (WM_APP+3)
35 HRESULT CParserOutPinImpl_InitIMediaSeeking( CParserOutPinImpl* This );
36 void CParserOutPinImpl_UninitIMediaSeeking( CParserOutPinImpl* This );
37 HRESULT CParserOutPinImpl_InitIMediaPosition( CParserOutPinImpl* This );
38 void CParserOutPinImpl_UninitIMediaPosition( CParserOutPinImpl* This );
40 /***************************************************************************
42 * CParserImpl internal methods
47 void CParserImpl_SetAsyncReader( CParserImpl* This, IAsyncReader* pReader )
49 if ( This->m_pReader != NULL )
51 IAsyncReader_Release( This->m_pReader );
52 This->m_pReader = NULL;
54 if ( pReader != NULL )
56 This->m_pReader = pReader;
57 IAsyncReader_AddRef(This->m_pReader);
62 void CParserImpl_ReleaseOutPins( CParserImpl* This )
66 if ( This->m_ppOutPins != NULL )
68 for ( nIndex = 0; nIndex < This->m_cOutStreams; nIndex++ )
70 if ( This->m_ppOutPins[nIndex] != NULL )
72 IUnknown_Release(This->m_ppOutPins[nIndex]->unk.punkControl);
73 This->m_ppOutPins[nIndex] = NULL;
76 QUARTZ_FreeMem(This->m_ppOutPins);
77 This->m_ppOutPins = NULL;
79 This->m_cOutStreams = 0;
83 BOOL CParserImpl_OutPinsAreConnected( CParserImpl* This )
85 QUARTZ_CompListItem* pItem;
90 QUARTZ_CompList_Lock( This->basefilter.pOutPins );
91 pItem = QUARTZ_CompList_GetFirst( This->basefilter.pOutPins );
92 while ( pItem != NULL )
96 pPin = (IPin*)QUARTZ_CompList_GetItemPtr(pItem);
98 hr = IPin_ConnectedTo(pPin,&pPinPeer);
99 if ( hr == S_OK && pPinPeer != NULL )
101 IPin_Release(pPinPeer);
104 pItem = QUARTZ_CompList_GetNext( This->basefilter.pOutPins, pItem );
106 QUARTZ_CompList_Unlock( This->basefilter.pOutPins );
112 void CParserImpl_ReleaseListOfOutPins( CParserImpl* This )
114 QUARTZ_CompListItem* pItem;
116 QUARTZ_CompList_Lock( This->basefilter.pOutPins );
119 pItem = QUARTZ_CompList_GetFirst( This->basefilter.pOutPins );
122 QUARTZ_CompList_RemoveComp(
123 This->basefilter.pOutPins,
124 QUARTZ_CompList_GetItemPtr(pItem) );
126 QUARTZ_CompList_Unlock( This->basefilter.pOutPins );
130 void CParserImpl_ClearAllRequests( CParserImpl* This )
134 TRACE("(%p)\n",This);
136 for ( nIndex = 0; nIndex < This->m_cOutStreams; nIndex++ )
138 This->m_ppOutPins[nIndex]->m_bReqUsed = FALSE;
139 This->m_ppOutPins[nIndex]->m_pReqSample = NULL;
144 void CParserImpl_ReleaseAllRequests( CParserImpl* This )
148 TRACE("(%p)\n",This);
150 for ( nIndex = 0; nIndex < This->m_cOutStreams; nIndex++ )
152 if ( This->m_ppOutPins[nIndex]->m_bReqUsed )
154 if ( This->m_ppOutPins[nIndex]->m_pReqSample != NULL )
156 IMediaSample_Release(This->m_ppOutPins[nIndex]->m_pReqSample);
157 This->m_ppOutPins[nIndex]->m_pReqSample = NULL;
159 This->m_ppOutPins[nIndex]->m_bReqUsed = FALSE;
165 BOOL CParserImpl_HasPendingSamples( CParserImpl* This )
169 for ( nIndex = 0; nIndex < This->m_cOutStreams; nIndex++ )
171 if ( This->m_ppOutPins[nIndex]->m_bReqUsed &&
172 This->m_ppOutPins[nIndex]->m_pReqSample != NULL )
180 HRESULT CParserImpl_FlushAllPendingSamples( CParserImpl* This )
183 IMediaSample* pSample;
186 TRACE("(%p)\n",This);
188 /* remove all samples from queue */
189 hr = IAsyncReader_BeginFlush(This->m_pReader);
192 IAsyncReader_EndFlush(This->m_pReader);
196 hr = IAsyncReader_WaitForNext(This->m_pReader,0,&pSample,&dwContext);
200 CParserImpl_ReleaseAllRequests(This);
205 static HRESULT CParserImpl_SendEndOfStream( CParserImpl* This )
210 CParserOutPinImpl* pOutPin;
212 TRACE("(%p)\n",This);
213 if ( This->m_bSendEOS )
215 This->m_bSendEOS = TRUE;
218 for ( nIndex = 0; nIndex < This->m_cOutStreams; nIndex++ )
220 pOutPin = This->m_ppOutPins[nIndex];
221 hr = CPinBaseImpl_SendEndOfStream(&pOutPin->pin);
224 if ( SUCCEEDED(hrRet) )
229 if ( hr != S_OK && hrRet == S_OK )
237 static HRESULT CParserImpl_SendFlush( CParserImpl* This )
242 CParserOutPinImpl* pOutPin;
244 TRACE("(%p)\n",This);
246 for ( nIndex = 0; nIndex < This->m_cOutStreams; nIndex++ )
248 pOutPin = This->m_ppOutPins[nIndex];
249 hr = CPinBaseImpl_SendBeginFlush(&pOutPin->pin);
252 if ( SUCCEEDED(hrRet) )
257 if ( hr != S_OK && hrRet == S_OK )
259 hr = CPinBaseImpl_SendEndFlush(&pOutPin->pin);
269 HRESULT CParserImpl_ProcessNextSample( CParserImpl* This )
271 IMediaSample* pSample;
275 CParserOutPinImpl* pOutPin;
280 if ( PeekMessageA( &msg, (HWND)NULL, 0, 0, PM_REMOVE ) )
283 switch ( msg.message )
285 case QUARTZ_MSG_FLUSH:
287 CParserImpl_FlushAllPendingSamples(This);
288 hr = CParserImpl_SendFlush(This);
290 case QUARTZ_MSG_EXITTHREAD:
291 TRACE("(%p) EndThread\n",This);
292 CParserImpl_FlushAllPendingSamples(This);
293 CParserImpl_ClearAllRequests(This);
294 CParserImpl_SendFlush(This);
295 CParserImpl_SendEndOfStream(This);
296 TRACE("(%p) exit thread\n",This);
298 case QUARTZ_MSG_SEEK:
300 CParserImpl_FlushAllPendingSamples(This);
303 FIXME( "invalid message %04u\n", (unsigned)msg.message );
311 hr = IAsyncReader_WaitForNext(This->m_pReader,PARSER_POLL_INTERVAL,&pSample,&dwContext);
312 nIndex = (ULONG)dwContext;
313 if ( hr != VFW_E_TIMEOUT )
321 pOutPin = This->m_ppOutPins[nIndex];
322 if ( pOutPin != NULL && pOutPin->m_bReqUsed )
324 if ( This->m_pHandler->pProcessSample != NULL )
325 hr = This->m_pHandler->pProcessSample(This,nIndex,pOutPin->m_llReqStart,pOutPin->m_lReqLength,pOutPin->m_pReqSample);
329 if ( pOutPin->m_pOutPinAllocator != NULL &&
330 pOutPin->m_pOutPinAllocator != This->m_pAllocator )
332 /* if pin has its own allocator, sample must be copied */
333 hr = IMemAllocator_GetBuffer( This->m_pAllocator, &pSample, NULL, NULL, 0 );
336 hr = QUARTZ_IMediaSample_Copy(
337 pSample, pOutPin->m_pReqSample, TRUE );
339 hr = CPinBaseImpl_SendSample(&pOutPin->pin,pSample);
340 IMediaSample_Release(pSample);
345 hr = CPinBaseImpl_SendSample(&pOutPin->pin,pOutPin->m_pReqSample);
354 IMediaSample_Release(pOutPin->m_pReqSample);
355 pOutPin->m_pReqSample = NULL;
356 pOutPin->m_bReqUsed = FALSE;
362 TRACE("return %08lx\n",hr);
368 DWORD WINAPI CParserImpl_ThreadEntry( LPVOID pv )
370 CParserImpl* This = (CParserImpl*)pv;
374 REFERENCE_TIME rtSampleTimeStart, rtSampleTimeEnd;
377 REFERENCE_TIME rtReqStart, rtReqStop;
378 IMediaSample* pSample;
381 /* initialize the message queue. */
382 PeekMessageA( &msg, (HWND)NULL, 0, 0, PM_NOREMOVE );
384 CParserImpl_ClearAllRequests(This);
386 /* resume the owner thread. */
387 SetEvent( This->m_hEventInit );
389 TRACE( "Enter message loop.\n" );
396 /* Get the next request. */
397 hr = This->m_pHandler->pGetNextRequest( This, &nIndex, &llReqStart, &lReqLength, &rtReqStart, &rtReqStop );
405 /* Flush pending samples. */
407 while ( CParserImpl_HasPendingSamples(This) )
409 hr = CParserImpl_ProcessNextSample(This);
415 /* notification is already sent */
419 /* Send End Of Stream. */
420 hr = CParserImpl_SendEndOfStream(This);
423 /* notification is already sent */
428 hr = CParserImpl_ProcessNextSample(This);
431 /* notification is already sent */
436 if ( This->m_ppOutPins[nIndex]->pin.pPinConnectedTo == NULL )
439 rtSampleTimeStart = This->basefilter.rtStart + llReqStart * QUARTZ_TIMEUNITS;
440 rtSampleTimeEnd = (llReqStart + lReqLength) * QUARTZ_TIMEUNITS;
444 if ( !This->m_ppOutPins[nIndex]->m_bReqUsed )
446 hr = IMemAllocator_GetBuffer( This->m_pAllocator, &pSample, NULL, NULL, 0 );
452 hr = IMediaSample_SetTime(pSample,&rtSampleTimeStart,&rtSampleTimeEnd);
454 hr = IAsyncReader_Request(This->m_pReader,pSample,nIndex);
461 This->m_ppOutPins[nIndex]->m_bReqUsed = TRUE;
462 This->m_ppOutPins[nIndex]->m_pReqSample = pSample;
463 This->m_ppOutPins[nIndex]->m_llReqStart = llReqStart;
464 This->m_ppOutPins[nIndex]->m_lReqLength = lReqLength;
465 This->m_ppOutPins[nIndex]->m_rtReqStart = rtSampleTimeStart;
466 This->m_ppOutPins[nIndex]->m_rtReqStop = rtSampleTimeEnd;
471 hr = CParserImpl_ProcessNextSample(This);
474 /* notification is already sent */
483 HRESULT CParserImpl_BeginThread( CParserImpl* This )
488 if ( This->m_hEventInit != (HANDLE)NULL &&
489 This->m_hThread != (HANDLE)NULL )
492 This->m_hEventInit = CreateEventA(NULL,TRUE,FALSE,NULL);
493 if ( This->m_hEventInit == (HANDLE)NULL )
494 return E_OUTOFMEMORY;
496 /* create the processing thread. */
497 This->m_hThread = CreateThread(
499 CParserImpl_ThreadEntry,
501 0, &This->m_dwThreadId );
502 if ( This->m_hThread == (HANDLE)NULL )
505 hEvents[0] = This->m_hEventInit;
506 hEvents[1] = This->m_hThread;
508 dwRes = WaitForMultipleObjects(2,hEvents,FALSE,INFINITE);
509 if ( dwRes != WAIT_OBJECT_0 )
516 void CParserImpl_EndThread( CParserImpl* This )
518 TRACE("(%p)\n",This);
519 if ( This->m_hThread != (HANDLE)NULL )
521 if ( PostThreadMessageA(
522 This->m_dwThreadId, QUARTZ_MSG_EXITTHREAD, 0, 0 ) )
524 WaitForSingleObject( This->m_hThread, INFINITE );
526 CloseHandle( This->m_hThread );
527 This->m_hThread = (HANDLE)NULL;
528 This->m_dwThreadId = 0;
530 if ( This->m_hEventInit != (HANDLE)NULL )
532 CloseHandle( This->m_hEventInit );
533 This->m_hEventInit = (HANDLE)NULL;
538 HRESULT CParserImpl_MemCommit( CParserImpl* This )
542 IMemAllocator* pAlloc;
544 TRACE("(%p)\n",This);
546 if ( This->m_pAllocator == NULL )
549 hr = IMemAllocator_Commit( This->m_pAllocator );
553 if ( This->m_ppOutPins != NULL && This->m_cOutStreams > 0 )
555 for ( nIndex = 0; nIndex < This->m_cOutStreams; nIndex++ )
557 pAlloc = This->m_ppOutPins[nIndex]->m_pOutPinAllocator;
558 if ( pAlloc != NULL && pAlloc != This->m_pAllocator )
560 hr = IMemAllocator_Commit( pAlloc );
571 void CParserImpl_MemDecommit( CParserImpl* This )
574 IMemAllocator* pAlloc;
576 TRACE("(%p)\n",This);
578 if ( This->m_pAllocator != NULL )
579 IMemAllocator_Decommit( This->m_pAllocator );
581 if ( This->m_ppOutPins != NULL && This->m_cOutStreams > 0 )
583 for ( nIndex = 0; nIndex < This->m_cOutStreams; nIndex++ )
585 pAlloc = This->m_ppOutPins[nIndex]->m_pOutPinAllocator;
586 if ( pAlloc != NULL )
587 IMemAllocator_Decommit( pAlloc );
594 /***************************************************************************
596 * CParserImpl methods
600 static HRESULT CParserImpl_OnActive( CBaseFilterImpl* pImpl )
602 CParserImpl_THIS(pImpl,basefilter);
604 TRACE( "(%p)\n", This );
606 if ( !CParserImpl_OutPinsAreConnected(This) )
612 static HRESULT CParserImpl_OnInactive( CBaseFilterImpl* pImpl )
614 CParserImpl_THIS(pImpl,basefilter);
617 TRACE( "(%p)\n", This );
619 if ( !CParserImpl_OutPinsAreConnected(This) )
622 hr = CParserImpl_MemCommit(This);
625 hr = CParserImpl_BeginThread(This);
628 CParserImpl_EndThread(This);
635 static HRESULT CParserImpl_OnStop( CBaseFilterImpl* pImpl )
637 CParserImpl_THIS(pImpl,basefilter);
639 FIXME( "(%p)\n", This );
641 CParserImpl_EndThread(This);
642 CParserImpl_MemDecommit(This);
643 This->m_bSendEOS = FALSE;
645 /* FIXME - reset streams. */
651 static const CBaseFilterHandlers filterhandlers =
653 CParserImpl_OnActive, /* pOnActive */
654 CParserImpl_OnInactive, /* pOnInactive */
655 CParserImpl_OnStop, /* pOnStop */
659 /***************************************************************************
661 * CParserInPinImpl methods
665 static HRESULT CParserInPinImpl_OnPreConnect( CPinBaseImpl* pImpl, IPin* pPin )
667 CParserInPinImpl_THIS(pImpl,pin);
671 IAsyncReader* pReader = NULL;
672 LPCWSTR pwszOutPinName;
673 IMemAllocator* pAllocActual;
676 TRACE("(%p,%p)\n",This,pPin);
678 if ( This->pParser->m_pHandler->pInitParser == NULL ||
679 This->pParser->m_pHandler->pUninitParser == NULL ||
680 This->pParser->m_pHandler->pGetOutPinName == NULL ||
681 This->pParser->m_pHandler->pGetStreamType == NULL ||
682 This->pParser->m_pHandler->pCheckStreamType == NULL ||
683 This->pParser->m_pHandler->pGetAllocProp == NULL ||
684 This->pParser->m_pHandler->pGetNextRequest == NULL )
686 FIXME("this parser is not implemented.\n");
690 /* at first, release all output pins. */
691 if ( CParserImpl_OutPinsAreConnected(This->pParser) )
693 CParserImpl_ReleaseListOfOutPins(This->pParser);
694 CParserImpl_ReleaseOutPins(This->pParser);
696 CParserImpl_SetAsyncReader( This->pParser, NULL );
697 hr = IPin_QueryInterface( pPin, &IID_IAsyncReader, (void**)&pReader );
700 CParserImpl_SetAsyncReader( This->pParser, pReader );
701 IAsyncReader_Release(pReader);
703 /* initialize parser. */
704 hr = This->pParser->m_pHandler->pInitParser(This->pParser,&This->pParser->m_cOutStreams);
707 This->pParser->m_ppOutPins = (CParserOutPinImpl**)QUARTZ_AllocMem(
708 sizeof(CParserOutPinImpl*) * This->pParser->m_cOutStreams );
709 if ( This->pParser->m_ppOutPins == NULL )
710 return E_OUTOFMEMORY;
711 for ( nIndex = 0; nIndex < This->pParser->m_cOutStreams; nIndex++ )
712 This->pParser->m_ppOutPins[nIndex] = NULL;
714 /* create and initialize an allocator. */
715 hr = This->pParser->m_pHandler->pGetAllocProp(This->pParser,&This->pParser->m_propAlloc);
718 if ( This->pParser->m_propAlloc.cbAlign == 0 )
719 This->pParser->m_propAlloc.cbAlign = 1;
721 if ( This->pParser->m_pAllocator == NULL )
723 hr = QUARTZ_CreateMemoryAllocator(NULL,(void**)&punk);
726 hr = IUnknown_QueryInterface( punk, &IID_IMemAllocator, (void**)&This->pParser->m_pAllocator );
727 IUnknown_Release(punk);
732 hr = IAsyncReader_RequestAllocator(pReader,This->pParser->m_pAllocator,&This->pParser->m_propAlloc,&pAllocActual);
735 IMemAllocator_Release(This->pParser->m_pAllocator);
736 This->pParser->m_pAllocator = pAllocActual;
738 /* create output pins. */
739 for ( nIndex = 0; nIndex < This->pParser->m_cOutStreams; nIndex++ )
741 pwszOutPinName = This->pParser->m_pHandler->pGetOutPinName(This->pParser,nIndex);
742 if ( pwszOutPinName == NULL )
744 hr = QUARTZ_CreateParserOutPin(
746 &This->pParser->m_csParser,
747 &This->pParser->m_ppOutPins[nIndex],
748 nIndex, pwszOutPinName );
750 hr = QUARTZ_CompList_AddTailComp(
751 This->pParser->basefilter.pOutPins,
752 (IUnknown*)&(This->pParser->m_ppOutPins[nIndex]->pin),
756 pmt = &This->pParser->m_ppOutPins[nIndex]->m_mtOut;
757 QUARTZ_MediaType_Free( pmt );
758 ZeroMemory( pmt, sizeof(AM_MEDIA_TYPE) );
759 hr = This->pParser->m_pHandler->pGetStreamType(This->pParser,nIndex,pmt);
762 ZeroMemory( pmt, sizeof(AM_MEDIA_TYPE) );
765 This->pParser->m_ppOutPins[nIndex]->pin.cAcceptTypes = 1;
766 This->pParser->m_ppOutPins[nIndex]->pin.pmtAcceptTypes = pmt;
772 static HRESULT CParserInPinImpl_OnDisconnect( CPinBaseImpl* pImpl )
774 CParserInPinImpl_THIS(pImpl,pin);
776 CParserImpl_OnInactive(&This->pParser->basefilter);
777 CParserImpl_OnStop(&This->pParser->basefilter);
778 if ( This->pParser->m_pHandler->pUninitParser != NULL )
779 This->pParser->m_pHandler->pUninitParser(This->pParser);
780 CParserImpl_SetAsyncReader( This->pParser, NULL );
781 if ( This->pParser->m_pAllocator != NULL )
783 IMemAllocator_Decommit(This->pParser->m_pAllocator);
784 IMemAllocator_Release(This->pParser->m_pAllocator);
785 This->pParser->m_pAllocator = NULL;
791 static HRESULT CParserInPinImpl_CheckMediaType( CPinBaseImpl* pImpl, const AM_MEDIA_TYPE* pmt )
793 CParserInPinImpl_THIS(pImpl,pin);
795 TRACE("(%p,%p)\n",This,pmt);
797 if ( !IsEqualGUID( &pmt->majortype, &MEDIATYPE_Stream ) )
803 static const CBasePinHandlers inputpinhandlers =
805 CParserInPinImpl_OnPreConnect, /* pOnPreConnect */
806 NULL, /* pOnPostConnect */
807 CParserInPinImpl_OnDisconnect, /* pOnDisconnect */
808 CParserInPinImpl_CheckMediaType, /* pCheckMediaType */
809 NULL, /* pQualityNotify */
811 NULL, /* pReceiveCanBlock */
812 NULL, /* pEndOfStream */
813 NULL, /* pBeginFlush */
814 NULL, /* pEndFlush */
815 NULL, /* pNewSegment */
818 /***************************************************************************
820 * CParserOutPinImpl methods
824 static HRESULT CParserOutPinImpl_OnPostConnect( CPinBaseImpl* pImpl, IPin* pPin )
826 CParserOutPinImpl_THIS(pImpl,pin);
827 ALLOCATOR_PROPERTIES propReq;
828 ALLOCATOR_PROPERTIES propActual;
829 IMemAllocator* pAllocator;
831 BOOL bNewAllocator = FALSE;
833 TRACE("(%p,%p)\n",This,pPin);
835 if ( This->pin.pMemInputPinConnectedTo == NULL )
838 if ( This->m_pOutPinAllocator != NULL )
840 IMemAllocator_Release(This->m_pOutPinAllocator);
841 This->m_pOutPinAllocator = NULL;
844 /* try to use This->pParser->m_pAllocator. */
845 ZeroMemory( &propReq, sizeof(ALLOCATOR_PROPERTIES) );
846 hr = IMemInputPin_GetAllocatorRequirements(
847 This->pin.pMemInputPinConnectedTo, &propReq );
848 if ( propReq.cbAlign != 0 )
850 if ( This->pParser->m_propAlloc.cbAlign != ( This->pParser->m_propAlloc.cbAlign / propReq.cbAlign * propReq.cbAlign ) )
851 bNewAllocator = TRUE;
853 if ( propReq.cbPrefix != 0 )
854 bNewAllocator = TRUE;
855 if ( !bNewAllocator )
857 hr = IMemInputPin_NotifyAllocator(
858 This->pin.pMemInputPinConnectedTo,
859 This->pParser->m_pAllocator, FALSE );
862 This->m_pOutPinAllocator = This->pParser->m_pAllocator;
863 IMemAllocator_AddRef(This->m_pOutPinAllocator);
868 hr = IMemInputPin_GetAllocator(
869 This->pin.pMemInputPinConnectedTo, &pAllocator );
872 hr = IMemAllocator_SetProperties( pAllocator, &This->pParser->m_propAlloc, &propActual );
874 hr = IMemInputPin_NotifyAllocator(
875 This->pin.pMemInputPinConnectedTo, pAllocator, FALSE );
878 IMemAllocator_Release(pAllocator);
882 This->m_pOutPinAllocator = pAllocator;
886 static HRESULT CParserOutPinImpl_OnDisconnect( CPinBaseImpl* pImpl )
888 CParserOutPinImpl_THIS(pImpl,pin);
890 if ( This->m_pOutPinAllocator != NULL )
892 IMemAllocator_Release(This->m_pOutPinAllocator);
893 This->m_pOutPinAllocator = NULL;
899 static HRESULT CParserOutPinImpl_CheckMediaType( CPinBaseImpl* pImpl, const AM_MEDIA_TYPE* pmt )
901 CParserOutPinImpl_THIS(pImpl,pin);
904 TRACE("(%p,%p)\n",This,pmt);
908 if ( This->pParser->m_pHandler->pCheckStreamType == NULL )
911 hr = This->pParser->m_pHandler->pCheckStreamType( This->pParser, This->nStreamIndex, pmt );
919 static const CBasePinHandlers outputpinhandlers =
921 NULL, /* pOnPreConnect */
922 CParserOutPinImpl_OnPostConnect, /* pOnPostConnect */
923 CParserOutPinImpl_OnDisconnect, /* pOnDisconnect */
924 CParserOutPinImpl_CheckMediaType, /* pCheckMediaType */
925 NULL, /* pQualityNotify */
926 OutputPinSync_Receive, /* pReceive */
927 OutputPinSync_ReceiveCanBlock, /* pReceiveCanBlock */
928 OutputPinSync_EndOfStream, /* pEndOfStream */
929 OutputPinSync_BeginFlush, /* pBeginFlush */
930 OutputPinSync_EndFlush, /* pEndFlush */
931 OutputPinSync_NewSegment, /* pNewSegment */
934 /***************************************************************************
936 * new/delete CParserImpl
940 /* can I use offsetof safely? - FIXME? */
941 static QUARTZ_IFEntry FilterIFEntries[] =
943 { &IID_IPersist, offsetof(CParserImpl,basefilter)-offsetof(CParserImpl,unk) },
944 { &IID_IMediaFilter, offsetof(CParserImpl,basefilter)-offsetof(CParserImpl,unk) },
945 { &IID_IBaseFilter, offsetof(CParserImpl,basefilter)-offsetof(CParserImpl,unk) },
948 static void QUARTZ_DestroyParser(IUnknown* punk)
950 CParserImpl_THIS(punk,unk);
952 TRACE( "(%p)\n", This );
954 if ( This->m_pInPin != NULL )
955 CParserInPinImpl_OnDisconnect(&This->m_pInPin->pin);
957 CParserImpl_SetAsyncReader( This, NULL );
958 if ( This->m_pAllocator != NULL )
960 IMemAllocator_Release(This->m_pAllocator);
961 This->m_pAllocator = NULL;
963 if ( This->m_pInPin != NULL )
965 IUnknown_Release(This->m_pInPin->unk.punkControl);
966 This->m_pInPin = NULL;
968 CParserImpl_ReleaseOutPins( This );
970 DeleteCriticalSection( &This->m_csParser );
972 CBaseFilterImpl_UninitIBaseFilter(&This->basefilter);
975 HRESULT QUARTZ_CreateParser(
976 IUnknown* punkOuter,void** ppobj,
977 const CLSID* pclsidParser,
978 LPCWSTR pwszParserName,
979 LPCWSTR pwszInPinName,
980 const ParserHandlers* pHandler )
982 CParserImpl* This = NULL;
985 TRACE("(%p,%p)\n",punkOuter,ppobj);
987 This = (CParserImpl*)
988 QUARTZ_AllocObj( sizeof(CParserImpl) );
990 return E_OUTOFMEMORY;
991 ZeroMemory( This, sizeof(CParserImpl) );
993 This->m_pInPin = NULL;
994 This->m_cOutStreams = 0;
995 This->m_ppOutPins = NULL;
996 This->m_pReader = NULL;
997 This->m_pAllocator = NULL;
998 ZeroMemory( &This->m_propAlloc, sizeof(ALLOCATOR_PROPERTIES) );
999 This->m_hEventInit = (HANDLE)NULL;
1000 This->m_hThread = (HANDLE)NULL;
1001 This->m_dwThreadId = 0;
1002 This->m_bSendEOS = FALSE;
1003 This->m_pHandler = pHandler;
1004 This->m_pUserData = NULL;
1006 QUARTZ_IUnkInit( &This->unk, punkOuter );
1008 hr = CBaseFilterImpl_InitIBaseFilter(
1010 This->unk.punkControl,
1014 if ( SUCCEEDED(hr) )
1016 /* construct this class. */
1021 CBaseFilterImpl_UninitIBaseFilter(&This->basefilter);
1027 QUARTZ_FreeObj(This);
1031 This->unk.pEntries = FilterIFEntries;
1032 This->unk.dwEntries = sizeof(FilterIFEntries)/sizeof(FilterIFEntries[0]);
1033 This->unk.pOnFinalRelease = QUARTZ_DestroyParser;
1034 InitializeCriticalSection( &This->m_csParser );
1036 /* create the input pin. */
1037 hr = QUARTZ_CreateParserInPin(
1042 if ( SUCCEEDED(hr) )
1043 hr = QUARTZ_CompList_AddComp(
1044 This->basefilter.pInPins,
1045 (IUnknown*)&(This->m_pInPin->pin),
1050 IUnknown_Release( This->unk.punkControl );
1054 *ppobj = (void*)&(This->unk);
1059 /***************************************************************************
1061 * new/delete CParserInPinImpl
1065 /* can I use offsetof safely? - FIXME? */
1066 static QUARTZ_IFEntry InPinIFEntries[] =
1068 { &IID_IPin, offsetof(CParserInPinImpl,pin)-offsetof(CParserInPinImpl,unk) },
1069 { &IID_IMemInputPin, offsetof(CParserInPinImpl,meminput)-offsetof(CParserInPinImpl,unk) },
1072 static void QUARTZ_DestroyParserInPin(IUnknown* punk)
1074 CParserInPinImpl_THIS(punk,unk);
1076 TRACE( "(%p)\n", This );
1078 CPinBaseImpl_UninitIPin( &This->pin );
1079 CMemInputPinBaseImpl_UninitIMemInputPin( &This->meminput );
1082 HRESULT QUARTZ_CreateParserInPin(
1083 CParserImpl* pFilter,
1084 CRITICAL_SECTION* pcsPin,
1085 CParserInPinImpl** ppPin,
1086 LPCWSTR pwszPinName )
1088 CParserInPinImpl* This = NULL;
1091 TRACE("(%p,%p,%p)\n",pFilter,pcsPin,ppPin);
1093 This = (CParserInPinImpl*)
1094 QUARTZ_AllocObj( sizeof(CParserInPinImpl) );
1096 return E_OUTOFMEMORY;
1098 QUARTZ_IUnkInit( &This->unk, NULL );
1099 This->pParser = pFilter;
1101 hr = CPinBaseImpl_InitIPin(
1103 This->unk.punkControl,
1105 &pFilter->basefilter,
1108 &inputpinhandlers );
1110 if ( SUCCEEDED(hr) )
1112 hr = CMemInputPinBaseImpl_InitIMemInputPin(
1114 This->unk.punkControl,
1118 CPinBaseImpl_UninitIPin( &This->pin );
1124 QUARTZ_FreeObj(This);
1128 This->unk.pEntries = InPinIFEntries;
1129 This->unk.dwEntries = sizeof(InPinIFEntries)/sizeof(InPinIFEntries[0]);
1130 This->unk.pOnFinalRelease = QUARTZ_DestroyParserInPin;
1134 TRACE("returned successfully.\n");
1140 /***************************************************************************
1142 * new/delete CParserOutPinImpl
1146 /* can I use offsetof safely? - FIXME? */
1147 static QUARTZ_IFEntry OutPinIFEntries[] =
1149 { &IID_IPin, offsetof(CParserOutPinImpl,pin)-offsetof(CParserOutPinImpl,unk) },
1150 { &IID_IQualityControl, offsetof(CParserOutPinImpl,qcontrol)-offsetof(CParserOutPinImpl,unk) },
1151 { &IID_IMediaSeeking, offsetof(CParserOutPinImpl,mediaseeking)-offsetof(CParserOutPinImpl,unk) },
1152 { &IID_IMediaPosition, offsetof(CParserOutPinImpl,mediaposition)-offsetof(CParserOutPinImpl,unk) },
1155 static void QUARTZ_DestroyParserOutPin(IUnknown* punk)
1157 CParserOutPinImpl_THIS(punk,unk);
1159 TRACE( "(%p)\n", This );
1161 QUARTZ_MediaType_Free( &This->m_mtOut );
1162 if ( This->m_pOutPinAllocator != NULL )
1163 IMemAllocator_Release(This->m_pOutPinAllocator);
1165 CParserOutPinImpl_UninitIMediaPosition(This);
1166 CParserOutPinImpl_UninitIMediaSeeking(This);
1167 CQualityControlPassThruImpl_UninitIQualityControl( &This->qcontrol );
1168 CPinBaseImpl_UninitIPin( &This->pin );
1172 HRESULT QUARTZ_CreateParserOutPin(
1173 CParserImpl* pFilter,
1174 CRITICAL_SECTION* pcsPin,
1175 CParserOutPinImpl** ppPin,
1177 LPCWSTR pwszPinName )
1179 CParserOutPinImpl* This = NULL;
1182 TRACE("(%p,%p,%p)\n",pFilter,pcsPin,ppPin);
1184 This = (CParserOutPinImpl*)
1185 QUARTZ_AllocObj( sizeof(CParserOutPinImpl) );
1187 return E_OUTOFMEMORY;
1189 QUARTZ_IUnkInit( &This->unk, NULL );
1190 This->pParser = pFilter;
1191 This->nStreamIndex = nStreamIndex;
1192 ZeroMemory( &This->m_mtOut, sizeof(AM_MEDIA_TYPE) );
1193 This->m_pOutPinAllocator = NULL;
1194 This->m_pUserData = NULL;
1195 This->m_bReqUsed = FALSE;
1196 This->m_pReqSample = NULL;
1197 This->m_llReqStart = 0;
1198 This->m_lReqLength = 0;
1199 This->m_rtReqStart = 0;
1200 This->m_rtReqStop = 0;
1203 hr = CPinBaseImpl_InitIPin(
1205 This->unk.punkControl,
1207 &pFilter->basefilter,
1210 &outputpinhandlers );
1212 if ( SUCCEEDED(hr) )
1214 hr = CQualityControlPassThruImpl_InitIQualityControl(
1216 This->unk.punkControl,
1218 if ( SUCCEEDED(hr) )
1220 hr = CParserOutPinImpl_InitIMediaSeeking(This);
1221 if ( SUCCEEDED(hr) )
1223 hr = CParserOutPinImpl_InitIMediaPosition(This);
1226 CParserOutPinImpl_UninitIMediaSeeking(This);
1231 CQualityControlPassThruImpl_UninitIQualityControl( &This->qcontrol );
1236 CPinBaseImpl_UninitIPin( &This->pin );
1242 QUARTZ_FreeObj(This);
1246 This->unk.pEntries = OutPinIFEntries;
1247 This->unk.dwEntries = sizeof(OutPinIFEntries)/sizeof(OutPinIFEntries[0]);
1248 This->unk.pOnFinalRelease = QUARTZ_DestroyParserOutPin;
1252 TRACE("returned successfully.\n");
1258 /***************************************************************************
1260 * IMediaSeeking for CParserOutPinImpl
1264 static HRESULT WINAPI
1265 IMediaSeeking_fnQueryInterface(IMediaSeeking* iface,REFIID riid,void** ppobj)
1267 CParserOutPinImpl_THIS(iface,mediaseeking);
1269 TRACE("(%p)->()\n",This);
1271 return IUnknown_QueryInterface(This->unk.punkControl,riid,ppobj);
1275 IMediaSeeking_fnAddRef(IMediaSeeking* iface)
1277 CParserOutPinImpl_THIS(iface,mediaseeking);
1279 TRACE("(%p)->()\n",This);
1281 return IUnknown_AddRef(This->unk.punkControl);
1285 IMediaSeeking_fnRelease(IMediaSeeking* iface)
1287 CParserOutPinImpl_THIS(iface,mediaseeking);
1289 TRACE("(%p)->()\n",This);
1291 return IUnknown_Release(This->unk.punkControl);
1295 static HRESULT WINAPI
1296 IMediaSeeking_fnGetCapabilities(IMediaSeeking* iface,DWORD* pdwCaps)
1298 CParserOutPinImpl_THIS(iface,mediaseeking);
1300 FIXME("(%p)->() stub!\n",This);
1305 static HRESULT WINAPI
1306 IMediaSeeking_fnCheckCapabilities(IMediaSeeking* iface,DWORD* pdwCaps)
1308 CParserOutPinImpl_THIS(iface,mediaseeking);
1310 FIXME("(%p)->() stub!\n",This);
1315 static HRESULT WINAPI
1316 IMediaSeeking_fnIsFormatSupported(IMediaSeeking* iface,const GUID* pidFormat)
1318 CParserOutPinImpl_THIS(iface,mediaseeking);
1320 FIXME("(%p)->() stub!\n",This);
1325 static HRESULT WINAPI
1326 IMediaSeeking_fnQueryPreferredFormat(IMediaSeeking* iface,GUID* pidFormat)
1328 CParserOutPinImpl_THIS(iface,mediaseeking);
1330 FIXME("(%p)->() stub!\n",This);
1335 static HRESULT WINAPI
1336 IMediaSeeking_fnGetTimeFormat(IMediaSeeking* iface,GUID* pidFormat)
1338 CParserOutPinImpl_THIS(iface,mediaseeking);
1340 FIXME("(%p)->() stub!\n",This);
1345 static HRESULT WINAPI
1346 IMediaSeeking_fnIsUsingTimeFormat(IMediaSeeking* iface,const GUID* pidFormat)
1348 CParserOutPinImpl_THIS(iface,mediaseeking);
1350 FIXME("(%p)->() stub!\n",This);
1355 static HRESULT WINAPI
1356 IMediaSeeking_fnSetTimeFormat(IMediaSeeking* iface,const GUID* pidFormat)
1358 CParserOutPinImpl_THIS(iface,mediaseeking);
1360 FIXME("(%p)->() stub!\n",This);
1365 static HRESULT WINAPI
1366 IMediaSeeking_fnGetDuration(IMediaSeeking* iface,LONGLONG* pllDuration)
1368 CParserOutPinImpl_THIS(iface,mediaseeking);
1370 /* the following line may produce too many FIXMEs... */
1371 FIXME("(%p)->() stub!\n",This);
1376 static HRESULT WINAPI
1377 IMediaSeeking_fnGetStopPosition(IMediaSeeking* iface,LONGLONG* pllPos)
1379 CParserOutPinImpl_THIS(iface,mediaseeking);
1381 FIXME("(%p)->() stub!\n",This);
1386 static HRESULT WINAPI
1387 IMediaSeeking_fnGetCurrentPosition(IMediaSeeking* iface,LONGLONG* pllPos)
1389 CParserOutPinImpl_THIS(iface,mediaseeking);
1391 FIXME("(%p)->() stub!\n",This);
1396 static HRESULT WINAPI
1397 IMediaSeeking_fnConvertTimeFormat(IMediaSeeking* iface,LONGLONG* pllOut,const GUID* pidFmtOut,LONGLONG llIn,const GUID* pidFmtIn)
1399 CParserOutPinImpl_THIS(iface,mediaseeking);
1401 FIXME("(%p)->() stub!\n",This);
1406 static HRESULT WINAPI
1407 IMediaSeeking_fnSetPositions(IMediaSeeking* iface,LONGLONG* pllCur,DWORD dwCurFlags,LONGLONG* pllStop,DWORD dwStopFlags)
1409 CParserOutPinImpl_THIS(iface,mediaseeking);
1411 FIXME("(%p)->() stub!\n",This);
1416 static HRESULT WINAPI
1417 IMediaSeeking_fnGetPositions(IMediaSeeking* iface,LONGLONG* pllCur,LONGLONG* pllStop)
1419 CParserOutPinImpl_THIS(iface,mediaseeking);
1421 FIXME("(%p)->() stub!\n",This);
1426 static HRESULT WINAPI
1427 IMediaSeeking_fnGetAvailable(IMediaSeeking* iface,LONGLONG* pllFirst,LONGLONG* pllLast)
1429 CParserOutPinImpl_THIS(iface,mediaseeking);
1431 FIXME("(%p)->() stub!\n",This);
1436 static HRESULT WINAPI
1437 IMediaSeeking_fnSetRate(IMediaSeeking* iface,double dblRate)
1439 CParserOutPinImpl_THIS(iface,mediaseeking);
1441 FIXME("(%p)->() stub!\n",This);
1446 static HRESULT WINAPI
1447 IMediaSeeking_fnGetRate(IMediaSeeking* iface,double* pdblRate)
1449 CParserOutPinImpl_THIS(iface,mediaseeking);
1451 FIXME("(%p)->() stub!\n",This);
1456 static HRESULT WINAPI
1457 IMediaSeeking_fnGetPreroll(IMediaSeeking* iface,LONGLONG* pllPreroll)
1459 CParserOutPinImpl_THIS(iface,mediaseeking);
1461 FIXME("(%p)->() stub!\n",This);
1469 static ICOM_VTABLE(IMediaSeeking) imediaseeking =
1471 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1472 /* IUnknown fields */
1473 IMediaSeeking_fnQueryInterface,
1474 IMediaSeeking_fnAddRef,
1475 IMediaSeeking_fnRelease,
1476 /* IMediaSeeking fields */
1477 IMediaSeeking_fnGetCapabilities,
1478 IMediaSeeking_fnCheckCapabilities,
1479 IMediaSeeking_fnIsFormatSupported,
1480 IMediaSeeking_fnQueryPreferredFormat,
1481 IMediaSeeking_fnGetTimeFormat,
1482 IMediaSeeking_fnIsUsingTimeFormat,
1483 IMediaSeeking_fnSetTimeFormat,
1484 IMediaSeeking_fnGetDuration,
1485 IMediaSeeking_fnGetStopPosition,
1486 IMediaSeeking_fnGetCurrentPosition,
1487 IMediaSeeking_fnConvertTimeFormat,
1488 IMediaSeeking_fnSetPositions,
1489 IMediaSeeking_fnGetPositions,
1490 IMediaSeeking_fnGetAvailable,
1491 IMediaSeeking_fnSetRate,
1492 IMediaSeeking_fnGetRate,
1493 IMediaSeeking_fnGetPreroll,
1496 HRESULT CParserOutPinImpl_InitIMediaSeeking( CParserOutPinImpl* This )
1498 TRACE("(%p)\n",This);
1499 ICOM_VTBL(&This->mediaseeking) = &imediaseeking;
1504 void CParserOutPinImpl_UninitIMediaSeeking( CParserOutPinImpl* This )
1506 TRACE("(%p)\n",This);
1509 /***************************************************************************
1511 * IMediaPosition for CParserOutPinImpl
1515 static HRESULT WINAPI
1516 IMediaPosition_fnQueryInterface(IMediaPosition* iface,REFIID riid,void** ppobj)
1518 CParserOutPinImpl_THIS(iface,mediaposition);
1520 TRACE("(%p)->()\n",This);
1522 return IUnknown_QueryInterface(This->unk.punkControl,riid,ppobj);
1526 IMediaPosition_fnAddRef(IMediaPosition* iface)
1528 CParserOutPinImpl_THIS(iface,mediaposition);
1530 TRACE("(%p)->()\n",This);
1532 return IUnknown_AddRef(This->unk.punkControl);
1536 IMediaPosition_fnRelease(IMediaPosition* iface)
1538 CParserOutPinImpl_THIS(iface,mediaposition);
1540 TRACE("(%p)->()\n",This);
1542 return IUnknown_Release(This->unk.punkControl);
1545 static HRESULT WINAPI
1546 IMediaPosition_fnGetTypeInfoCount(IMediaPosition* iface,UINT* pcTypeInfo)
1548 CParserOutPinImpl_THIS(iface,mediaposition);
1550 FIXME("(%p)->() stub!\n",This);
1555 static HRESULT WINAPI
1556 IMediaPosition_fnGetTypeInfo(IMediaPosition* iface,UINT iTypeInfo, LCID lcid, ITypeInfo** ppobj)
1558 CParserOutPinImpl_THIS(iface,mediaposition);
1560 FIXME("(%p)->() stub!\n",This);
1565 static HRESULT WINAPI
1566 IMediaPosition_fnGetIDsOfNames(IMediaPosition* iface,REFIID riid, LPOLESTR* ppwszName, UINT cNames, LCID lcid, DISPID* pDispId)
1568 CParserOutPinImpl_THIS(iface,mediaposition);
1570 FIXME("(%p)->() stub!\n",This);
1575 static HRESULT WINAPI
1576 IMediaPosition_fnInvoke(IMediaPosition* iface,DISPID DispId, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarRes, EXCEPINFO* pExcepInfo, UINT* puArgErr)
1578 CParserOutPinImpl_THIS(iface,mediaposition);
1580 FIXME("(%p)->() stub!\n",This);
1586 static HRESULT WINAPI
1587 IMediaPosition_fnget_Duration(IMediaPosition* iface,REFTIME* prefTime)
1589 CParserOutPinImpl_THIS(iface,mediaposition);
1591 FIXME("(%p)->() stub!\n",This);
1596 static HRESULT WINAPI
1597 IMediaPosition_fnput_CurrentPosition(IMediaPosition* iface,REFTIME refTime)
1599 CParserOutPinImpl_THIS(iface,mediaposition);
1601 FIXME("(%p)->() stub!\n",This);
1606 static HRESULT WINAPI
1607 IMediaPosition_fnget_CurrentPosition(IMediaPosition* iface,REFTIME* prefTime)
1609 CParserOutPinImpl_THIS(iface,mediaposition);
1611 FIXME("(%p)->() stub!\n",This);
1616 static HRESULT WINAPI
1617 IMediaPosition_fnget_StopTime(IMediaPosition* iface,REFTIME* prefTime)
1619 CParserOutPinImpl_THIS(iface,mediaposition);
1621 FIXME("(%p)->() stub!\n",This);
1626 static HRESULT WINAPI
1627 IMediaPosition_fnput_StopTime(IMediaPosition* iface,REFTIME refTime)
1629 CParserOutPinImpl_THIS(iface,mediaposition);
1631 FIXME("(%p)->() stub!\n",This);
1636 static HRESULT WINAPI
1637 IMediaPosition_fnget_PrerollTime(IMediaPosition* iface,REFTIME* prefTime)
1639 CParserOutPinImpl_THIS(iface,mediaposition);
1641 FIXME("(%p)->() stub!\n",This);
1646 static HRESULT WINAPI
1647 IMediaPosition_fnput_PrerollTime(IMediaPosition* iface,REFTIME refTime)
1649 CParserOutPinImpl_THIS(iface,mediaposition);
1651 FIXME("(%p)->() stub!\n",This);
1656 static HRESULT WINAPI
1657 IMediaPosition_fnput_Rate(IMediaPosition* iface,double dblRate)
1659 CParserOutPinImpl_THIS(iface,mediaposition);
1661 return IMediaSeeking_SetRate(CParserOutPinImpl_IMediaSeeking(This),dblRate);
1664 static HRESULT WINAPI
1665 IMediaPosition_fnget_Rate(IMediaPosition* iface,double* pdblRate)
1667 CParserOutPinImpl_THIS(iface,mediaposition);
1669 return IMediaSeeking_GetRate(CParserOutPinImpl_IMediaSeeking(This),pdblRate);
1672 static HRESULT WINAPI
1673 IMediaPosition_fnCanSeekForward(IMediaPosition* iface,LONG* pCanSeek)
1675 CParserOutPinImpl_THIS(iface,mediaposition);
1677 FIXME("(%p)->() stub!\n",This);
1682 static HRESULT WINAPI
1683 IMediaPosition_fnCanSeekBackward(IMediaPosition* iface,LONG* pCanSeek)
1685 CParserOutPinImpl_THIS(iface,mediaposition);
1687 FIXME("(%p)->() stub!\n",This);
1693 static ICOM_VTABLE(IMediaPosition) imediaposition =
1695 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1696 /* IUnknown fields */
1697 IMediaPosition_fnQueryInterface,
1698 IMediaPosition_fnAddRef,
1699 IMediaPosition_fnRelease,
1700 /* IDispatch fields */
1701 IMediaPosition_fnGetTypeInfoCount,
1702 IMediaPosition_fnGetTypeInfo,
1703 IMediaPosition_fnGetIDsOfNames,
1704 IMediaPosition_fnInvoke,
1705 /* IMediaPosition fields */
1706 IMediaPosition_fnget_Duration,
1707 IMediaPosition_fnput_CurrentPosition,
1708 IMediaPosition_fnget_CurrentPosition,
1709 IMediaPosition_fnget_StopTime,
1710 IMediaPosition_fnput_StopTime,
1711 IMediaPosition_fnget_PrerollTime,
1712 IMediaPosition_fnput_PrerollTime,
1713 IMediaPosition_fnput_Rate,
1714 IMediaPosition_fnget_Rate,
1715 IMediaPosition_fnCanSeekForward,
1716 IMediaPosition_fnCanSeekBackward,
1720 HRESULT CParserOutPinImpl_InitIMediaPosition( CParserOutPinImpl* This )
1722 TRACE("(%p)\n",This);
1723 ICOM_VTBL(&This->mediaposition) = &imediaposition;
1728 void CParserOutPinImpl_UninitIMediaPosition( CParserOutPinImpl* This )
1730 TRACE("(%p)\n",This);