Fixed the behavior for SHGetFileInfo when the SHGFI_USEFILEATTRIBUTES
[wine] / dlls / quartz / parser.c
1 /*
2  * Implements IBaseFilter for parsers. (internal)
3  *
4  * hidenori@a2.ctktv.ne.jp
5  *
6  * FIXME - handle errors/flushing correctly.
7  * FIXME - handle seeking.
8  */
9
10 #include "config.h"
11
12 #include "windef.h"
13 #include "winbase.h"
14 #include "wingdi.h"
15 #include "winuser.h"
16 #include "mmsystem.h"
17 #include "winerror.h"
18 #include "strmif.h"
19 #include "control.h"
20 #include "vfwmsgs.h"
21 #include "uuids.h"
22
23 #include "debugtools.h"
24 DEFAULT_DEBUG_CHANNEL(quartz);
25
26 #include "quartz_private.h"
27 #include "parser.h"
28 #include "mtype.h"
29 #include "memalloc.h"
30
31 #define QUARTZ_MSG_FLUSH        (WM_APP+1)
32 #define QUARTZ_MSG_EXITTHREAD   (WM_APP+2)
33 #define QUARTZ_MSG_SEEK                 (WM_APP+3)
34
35 HRESULT CParserOutPinImpl_InitIMediaSeeking( CParserOutPinImpl* This );
36 void CParserOutPinImpl_UninitIMediaSeeking( CParserOutPinImpl* This );
37 HRESULT CParserOutPinImpl_InitIMediaPosition( CParserOutPinImpl* This );
38 void CParserOutPinImpl_UninitIMediaPosition( CParserOutPinImpl* This );
39
40 /***************************************************************************
41  *
42  *      CParserImpl internal methods
43  *
44  */
45
46 static
47 void CParserImpl_SetAsyncReader( CParserImpl* This, IAsyncReader* pReader )
48 {
49         if ( This->m_pReader != NULL )
50         {
51                 IAsyncReader_Release( This->m_pReader );
52                 This->m_pReader = NULL;
53         }
54         if ( pReader != NULL )
55         {
56                 This->m_pReader = pReader;
57                 IAsyncReader_AddRef(This->m_pReader);
58         }
59 }
60
61 static
62 void CParserImpl_ReleaseOutPins( CParserImpl* This )
63 {
64         ULONG nIndex;
65
66         if ( This->m_ppOutPins != NULL )
67         {
68                 for ( nIndex = 0; nIndex < This->m_cOutStreams; nIndex++ )
69                 {
70                         if ( This->m_ppOutPins[nIndex] != NULL )
71                         {
72                                 IUnknown_Release(This->m_ppOutPins[nIndex]->unk.punkControl);
73                                 This->m_ppOutPins[nIndex] = NULL;
74                         }
75                 }
76                 QUARTZ_FreeMem(This->m_ppOutPins);
77                 This->m_ppOutPins = NULL;
78         }
79         This->m_cOutStreams = 0;
80 }
81
82 static
83 BOOL CParserImpl_OutPinsAreConnected( CParserImpl* This )
84 {
85         QUARTZ_CompListItem*    pItem;
86         IPin*   pPin;
87         IPin*   pPinPeer;
88         HRESULT hr;
89
90         QUARTZ_CompList_Lock( This->basefilter.pOutPins );
91         pItem = QUARTZ_CompList_GetFirst( This->basefilter.pOutPins );
92         while ( pItem != NULL )
93         {
94                 if ( pItem == NULL )
95                         break;
96                 pPin = (IPin*)QUARTZ_CompList_GetItemPtr(pItem);
97                 pPinPeer = NULL;
98                 hr = IPin_ConnectedTo(pPin,&pPinPeer);
99                 if ( hr == S_OK && pPinPeer != NULL )
100                 {
101                         IPin_Release(pPinPeer);
102                         return TRUE;
103                 }
104                 pItem = QUARTZ_CompList_GetNext( This->basefilter.pOutPins, pItem );
105         }
106         QUARTZ_CompList_Unlock( This->basefilter.pOutPins );
107
108         return FALSE;
109 }
110
111 static
112 void CParserImpl_ReleaseListOfOutPins( CParserImpl* This )
113 {
114         QUARTZ_CompListItem*    pItem;
115
116         QUARTZ_CompList_Lock( This->basefilter.pOutPins );
117         while ( 1 )
118         {
119                 pItem = QUARTZ_CompList_GetFirst( This->basefilter.pOutPins );
120                 if ( pItem == NULL )
121                         break;
122                 QUARTZ_CompList_RemoveComp(
123                         This->basefilter.pOutPins,
124                         QUARTZ_CompList_GetItemPtr(pItem) );
125         }
126         QUARTZ_CompList_Unlock( This->basefilter.pOutPins );
127 }
128
129 static
130 void CParserImpl_ClearAllRequests( CParserImpl* This )
131 {
132         ULONG   nIndex;
133
134         TRACE("(%p)\n",This);
135
136         for ( nIndex = 0; nIndex < This->m_cOutStreams; nIndex++ )
137         {
138                 This->m_ppOutPins[nIndex]->m_bReqUsed = FALSE;
139                 This->m_ppOutPins[nIndex]->m_pReqSample = NULL;
140         }
141 }
142
143 static
144 void CParserImpl_ReleaseAllRequests( CParserImpl* This )
145 {
146         ULONG   nIndex;
147
148         TRACE("(%p)\n",This);
149
150         for ( nIndex = 0; nIndex < This->m_cOutStreams; nIndex++ )
151         {
152                 if ( This->m_ppOutPins[nIndex]->m_bReqUsed )
153                 {
154                         if ( This->m_ppOutPins[nIndex]->m_pReqSample != NULL )
155                         {
156                                 IMediaSample_Release(This->m_ppOutPins[nIndex]->m_pReqSample);
157                                 This->m_ppOutPins[nIndex]->m_pReqSample = NULL;
158                         }
159                         This->m_ppOutPins[nIndex]->m_bReqUsed = FALSE;
160                 }
161         }
162 }
163
164 static
165 BOOL CParserImpl_HasPendingSamples( CParserImpl* This )
166 {
167         ULONG   nIndex;
168
169         for ( nIndex = 0; nIndex < This->m_cOutStreams; nIndex++ )
170         {
171                 if ( This->m_ppOutPins[nIndex]->m_bReqUsed &&
172                          This->m_ppOutPins[nIndex]->m_pReqSample != NULL )
173                         return TRUE;
174         }
175
176         return FALSE;
177 }
178
179 static
180 HRESULT CParserImpl_FlushAllPendingSamples( CParserImpl* This )
181 {
182         HRESULT hr;
183         IMediaSample*   pSample;
184         DWORD_PTR       dwContext;
185
186         TRACE("(%p)\n",This);
187
188         /* remove all samples from queue */
189         hr = IAsyncReader_BeginFlush(This->m_pReader);
190         if ( FAILED(hr) )
191                 return hr;
192         IAsyncReader_EndFlush(This->m_pReader);
193
194         while ( 1 )
195         {
196                 hr = IAsyncReader_WaitForNext(This->m_pReader,0,&pSample,&dwContext);
197                 if ( hr != S_OK )
198                         break;
199         }
200         CParserImpl_ReleaseAllRequests(This);
201
202         return NOERROR;
203 }
204
205 static HRESULT CParserImpl_SendEndOfStream( CParserImpl* This )
206 {
207         ULONG   nIndex;
208         HRESULT hr;
209         HRESULT hrRet;
210         CParserOutPinImpl*      pOutPin;
211
212         TRACE("(%p)\n",This);
213         if ( This->m_bSendEOS )
214                 return NOERROR;
215         This->m_bSendEOS = TRUE;
216
217         hrRet = S_OK;
218         for ( nIndex = 0; nIndex < This->m_cOutStreams; nIndex++ )
219         {
220                 pOutPin = This->m_ppOutPins[nIndex];
221                 hr = CPinBaseImpl_SendEndOfStream(&pOutPin->pin);
222                 if ( FAILED(hr) )
223                 {
224                         if ( SUCCEEDED(hrRet) )
225                                 hrRet = hr;
226                 }
227                 else
228                 {
229                         if ( hr != S_OK && hrRet == S_OK )
230                                 hrRet = hr;
231                 }
232         }
233
234         return hrRet;
235 }
236
237 static HRESULT CParserImpl_SendFlush( CParserImpl* This )
238 {
239         ULONG   nIndex;
240         HRESULT hr;
241         HRESULT hrRet;
242         CParserOutPinImpl*      pOutPin;
243
244         TRACE("(%p)\n",This);
245         hrRet = S_OK;
246         for ( nIndex = 0; nIndex < This->m_cOutStreams; nIndex++ )
247         {
248                 pOutPin = This->m_ppOutPins[nIndex];
249                 hr = CPinBaseImpl_SendBeginFlush(&pOutPin->pin);
250                 if ( FAILED(hr) )
251                 {
252                         if ( SUCCEEDED(hrRet) )
253                                 hrRet = hr;
254                 }
255                 else
256                 {
257                         if ( hr != S_OK && hrRet == S_OK )
258                                 hrRet = hr;
259                         hr = CPinBaseImpl_SendEndFlush(&pOutPin->pin);
260                         if ( FAILED(hr) )
261                                 hrRet = hr;
262                 }
263         }
264
265         return hrRet;
266 }
267
268 static
269 HRESULT CParserImpl_ProcessNextSample( CParserImpl* This )
270 {
271         IMediaSample*   pSample;
272         DWORD_PTR       dwContext;
273         ULONG   nIndex;
274         HRESULT hr;
275         CParserOutPinImpl*      pOutPin;
276         MSG     msg;
277
278         while ( 1 )
279         {
280                 if ( PeekMessageA( &msg, (HWND)NULL, 0, 0, PM_REMOVE ) )
281                 {
282                         hr = NOERROR;
283                         switch ( msg.message )
284                         {
285                         case QUARTZ_MSG_FLUSH:
286                                 TRACE("Flush\n");
287                                 CParserImpl_FlushAllPendingSamples(This);
288                                 hr = CParserImpl_SendFlush(This);
289                                 break;
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);
297                                 return S_FALSE;
298                         case QUARTZ_MSG_SEEK:
299                                 FIXME("Seek\n");
300                                 CParserImpl_FlushAllPendingSamples(This);
301                                 break;
302                         default:
303                                 FIXME( "invalid message %04u\n", (unsigned)msg.message );
304                                 /* Notify (ABORT) */
305                                 hr = E_FAIL;
306                         }
307
308                         return hr;
309                 }
310
311                 hr = IAsyncReader_WaitForNext(This->m_pReader,PARSER_POLL_INTERVAL,&pSample,&dwContext);
312                 nIndex = (ULONG)dwContext;
313                 if ( hr != VFW_E_TIMEOUT )
314                         break;
315         }
316         if ( FAILED(hr) )
317         {
318                 return hr;
319         }
320
321         pOutPin = This->m_ppOutPins[nIndex];
322         if ( pOutPin != NULL && pOutPin->m_bReqUsed )
323         {
324                 if ( This->m_pHandler->pProcessSample != NULL )
325                         hr = This->m_pHandler->pProcessSample(This,nIndex,pOutPin->m_llReqStart,pOutPin->m_lReqLength,pOutPin->m_pReqSample);
326
327                 if ( SUCCEEDED(hr) )
328                 {
329                         if ( pOutPin->m_pOutPinAllocator != NULL &&
330                                  pOutPin->m_pOutPinAllocator != This->m_pAllocator )
331                         {
332                                 /* if pin has its own allocator, sample must be copied */
333                                 hr = IMemAllocator_GetBuffer( This->m_pAllocator, &pSample, NULL, NULL, 0 );
334                                 if ( SUCCEEDED(hr) )
335                                 {
336                                         hr = QUARTZ_IMediaSample_Copy(
337                                                 pSample, pOutPin->m_pReqSample, TRUE );
338                                         if ( SUCCEEDED(hr) )
339                                                 hr = CPinBaseImpl_SendSample(&pOutPin->pin,pSample);
340                                         IMediaSample_Release(pSample);
341                                 }
342                         }
343                         else
344                         {
345                                 hr = CPinBaseImpl_SendSample(&pOutPin->pin,pOutPin->m_pReqSample);
346                         }
347                 }
348
349                 if ( FAILED(hr) )
350                 {
351                         /* Notify (ABORT) */
352                 }
353
354                 IMediaSample_Release(pOutPin->m_pReqSample);
355                 pOutPin->m_pReqSample = NULL;
356                 pOutPin->m_bReqUsed = FALSE;
357         }
358
359         if ( SUCCEEDED(hr) )
360                 hr = NOERROR;
361
362         TRACE("return %08lx\n",hr);
363
364         return hr;
365 }
366
367 static
368 DWORD WINAPI CParserImpl_ThreadEntry( LPVOID pv )
369 {
370         CParserImpl*    This = (CParserImpl*)pv;
371         BOOL    bReqNext;
372         ULONG   nIndex = 0;
373         HRESULT hr;
374         REFERENCE_TIME  rtSampleTimeStart, rtSampleTimeEnd;
375         LONGLONG        llReqStart;
376         LONG    lReqLength;
377         REFERENCE_TIME  rtReqStart, rtReqStop;
378         IMediaSample*   pSample;
379         MSG     msg;
380
381         /* initialize the message queue. */
382         PeekMessageA( &msg, (HWND)NULL, 0, 0, PM_NOREMOVE );
383
384         CParserImpl_ClearAllRequests(This);
385
386         /* resume the owner thread. */
387         SetEvent( This->m_hEventInit );
388
389         TRACE( "Enter message loop.\n" );
390
391         bReqNext = TRUE;
392         while ( 1 )
393         {
394                 if ( bReqNext )
395                 {
396                         /* Get the next request.  */
397                         hr = This->m_pHandler->pGetNextRequest( This, &nIndex, &llReqStart, &lReqLength, &rtReqStart, &rtReqStop );
398                         if ( FAILED(hr) )
399                         {
400                                 /* Notify (ABORT) */
401                                 break;
402                         }
403                         if ( hr != S_OK )
404                         {
405                                 /* Flush pending samples. */
406                                 hr = S_OK;
407                                 while ( CParserImpl_HasPendingSamples(This) )
408                                 {
409                                         hr = CParserImpl_ProcessNextSample(This);
410                                         if ( hr != S_OK )
411                                                 break;
412                                 }
413                                 if ( hr != S_OK )
414                                 {
415                                         /* notification is already sent */
416                                         break;
417                                 }
418
419                                 /* Send End Of Stream. */
420                                 hr = CParserImpl_SendEndOfStream(This);
421                                 if ( hr != S_OK )
422                                 {
423                                         /* notification is already sent */
424                                         break;
425                                 }
426
427                                 /* Blocking... */
428                                 hr = CParserImpl_ProcessNextSample(This);
429                                 if ( hr != S_OK )
430                                 {
431                                         /* notification is already sent */
432                                         break;
433                                 }
434                                 continue;
435                         }
436                         if ( This->m_ppOutPins[nIndex]->pin.pPinConnectedTo == NULL )
437                                 continue;
438
439                         rtSampleTimeStart = This->basefilter.rtStart + llReqStart * QUARTZ_TIMEUNITS;
440                         rtSampleTimeEnd = (llReqStart + lReqLength) * QUARTZ_TIMEUNITS;
441                         bReqNext = FALSE;
442                 }
443
444                 if ( !This->m_ppOutPins[nIndex]->m_bReqUsed )
445                 {
446                         hr = IMemAllocator_GetBuffer( This->m_pAllocator, &pSample, NULL, NULL, 0 );
447                         if ( FAILED(hr) )
448                         {
449                                 /* Notify (ABORT) */
450                                 break;
451                         }
452                         hr = IMediaSample_SetTime(pSample,&rtSampleTimeStart,&rtSampleTimeEnd);
453                         if ( SUCCEEDED(hr) )
454                                 hr = IAsyncReader_Request(This->m_pReader,pSample,nIndex);
455                         if ( FAILED(hr) )
456                         {
457                                 /* Notify (ABORT) */
458                                 break;
459                         }
460
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;
467                         bReqNext = TRUE;
468                         continue;
469                 }
470
471                 hr = CParserImpl_ProcessNextSample(This);
472                 if ( hr != S_OK )
473                 {
474                         /* notification is already sent */
475                         break;
476                 }
477         }
478
479         return 0;
480 }
481
482 static
483 HRESULT CParserImpl_BeginThread( CParserImpl* This )
484 {
485         DWORD dwRes;
486         HANDLE hEvents[2];
487
488         if ( This->m_hEventInit != (HANDLE)NULL &&
489                  This->m_hThread != (HANDLE)NULL )
490                 return NOERROR;
491
492         This->m_hEventInit = CreateEventA(NULL,TRUE,FALSE,NULL);
493         if ( This->m_hEventInit == (HANDLE)NULL )
494                 return E_OUTOFMEMORY;
495
496         /* create the processing thread. */
497         This->m_hThread = CreateThread(
498                 NULL, 0,
499                 CParserImpl_ThreadEntry,
500                 (LPVOID)This,
501                 0, &This->m_dwThreadId );
502         if ( This->m_hThread == (HANDLE)NULL )
503                 return E_FAIL;
504
505         hEvents[0] = This->m_hEventInit;
506         hEvents[1] = This->m_hThread;
507
508         dwRes = WaitForMultipleObjects(2,hEvents,FALSE,INFINITE);
509         if ( dwRes != WAIT_OBJECT_0 )
510                 return E_FAIL;
511
512         return NOERROR;
513 }
514
515 static
516 void CParserImpl_EndThread( CParserImpl* This )
517 {
518         TRACE("(%p)\n",This);
519         if ( This->m_hThread != (HANDLE)NULL )
520         {
521                 if ( PostThreadMessageA(
522                         This->m_dwThreadId, QUARTZ_MSG_EXITTHREAD, 0, 0 ) )
523                 {
524                         WaitForSingleObject( This->m_hThread, INFINITE );
525                 }
526                 CloseHandle( This->m_hThread );
527                 This->m_hThread = (HANDLE)NULL;
528                 This->m_dwThreadId = 0;
529         }
530         if ( This->m_hEventInit != (HANDLE)NULL )
531         {
532                 CloseHandle( This->m_hEventInit );
533                 This->m_hEventInit = (HANDLE)NULL;
534         }
535 }
536
537 static
538 HRESULT CParserImpl_MemCommit( CParserImpl* This )
539 {
540         HRESULT hr;
541         ULONG   nIndex;
542         IMemAllocator*  pAlloc;
543
544         TRACE("(%p)\n",This);
545
546         if ( This->m_pAllocator == NULL )
547                 return E_UNEXPECTED;
548
549         hr = IMemAllocator_Commit( This->m_pAllocator );
550         if ( FAILED(hr) )
551                 return hr;
552
553         if ( This->m_ppOutPins != NULL && This->m_cOutStreams > 0 )
554         {
555                 for ( nIndex = 0; nIndex < This->m_cOutStreams; nIndex++ )
556                 {
557                         pAlloc = This->m_ppOutPins[nIndex]->m_pOutPinAllocator;
558                         if ( pAlloc != NULL && pAlloc != This->m_pAllocator )
559                         {
560                                 hr = IMemAllocator_Commit( pAlloc );
561                                 if ( FAILED(hr) )
562                                         return hr;
563                         }
564                 }
565         }
566
567         return NOERROR;
568 }
569
570 static
571 void CParserImpl_MemDecommit( CParserImpl* This )
572 {
573         ULONG   nIndex;
574         IMemAllocator*  pAlloc;
575
576         TRACE("(%p)\n",This);
577
578         if ( This->m_pAllocator != NULL )
579                 IMemAllocator_Decommit( This->m_pAllocator );
580
581         if ( This->m_ppOutPins != NULL && This->m_cOutStreams > 0 )
582         {
583                 for ( nIndex = 0; nIndex < This->m_cOutStreams; nIndex++ )
584                 {
585                         pAlloc = This->m_ppOutPins[nIndex]->m_pOutPinAllocator;
586                         if ( pAlloc != NULL )
587                                 IMemAllocator_Decommit( pAlloc );
588                 }
589         }
590 }
591
592
593
594 /***************************************************************************
595  *
596  *      CParserImpl methods
597  *
598  */
599
600 static HRESULT CParserImpl_OnActive( CBaseFilterImpl* pImpl )
601 {
602         CParserImpl_THIS(pImpl,basefilter);
603
604         TRACE( "(%p)\n", This );
605
606         if ( !CParserImpl_OutPinsAreConnected(This) )
607                 return NOERROR;
608
609         return NOERROR;
610 }
611
612 static HRESULT CParserImpl_OnInactive( CBaseFilterImpl* pImpl )
613 {
614         CParserImpl_THIS(pImpl,basefilter);
615         HRESULT hr;
616
617         TRACE( "(%p)\n", This );
618
619         if ( !CParserImpl_OutPinsAreConnected(This) )
620                 return NOERROR;
621
622         hr = CParserImpl_MemCommit(This);
623         if ( FAILED(hr) )
624                 return hr;
625         hr = CParserImpl_BeginThread(This);
626         if ( FAILED(hr) )
627         {
628                 CParserImpl_EndThread(This);
629                 return hr;
630         }
631
632         return NOERROR;
633 }
634
635 static HRESULT CParserImpl_OnStop( CBaseFilterImpl* pImpl )
636 {
637         CParserImpl_THIS(pImpl,basefilter);
638
639         FIXME( "(%p)\n", This );
640
641         CParserImpl_EndThread(This);
642         CParserImpl_MemDecommit(This);
643         This->m_bSendEOS = FALSE;
644
645         /* FIXME - reset streams. */
646
647         return NOERROR;
648 }
649
650
651 static const CBaseFilterHandlers filterhandlers =
652 {
653         CParserImpl_OnActive, /* pOnActive */
654         CParserImpl_OnInactive, /* pOnInactive */
655         CParserImpl_OnStop, /* pOnStop */
656 };
657
658
659 /***************************************************************************
660  *
661  *      CParserInPinImpl methods
662  *
663  */
664
665 static HRESULT CParserInPinImpl_OnPreConnect( CPinBaseImpl* pImpl, IPin* pPin )
666 {
667         CParserInPinImpl_THIS(pImpl,pin);
668         HRESULT hr;
669         ULONG   nIndex;
670         IUnknown*       punk;
671         IAsyncReader* pReader = NULL;
672         LPCWSTR pwszOutPinName;
673         IMemAllocator*  pAllocActual;
674         AM_MEDIA_TYPE*  pmt;
675
676         TRACE("(%p,%p)\n",This,pPin);
677
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 )
685         {
686                 FIXME("this parser is not implemented.\n");
687                 return E_NOTIMPL;
688         }
689
690         /* at first, release all output pins. */
691         if ( CParserImpl_OutPinsAreConnected(This->pParser) )
692                 return E_FAIL;
693         CParserImpl_ReleaseListOfOutPins(This->pParser);
694         CParserImpl_ReleaseOutPins(This->pParser);
695
696         CParserImpl_SetAsyncReader( This->pParser, NULL );
697         hr = IPin_QueryInterface( pPin, &IID_IAsyncReader, (void**)&pReader );
698         if ( FAILED(hr) )
699                 return hr;
700         CParserImpl_SetAsyncReader( This->pParser, pReader );
701         IAsyncReader_Release(pReader);
702
703         /* initialize parser. */
704         hr = This->pParser->m_pHandler->pInitParser(This->pParser,&This->pParser->m_cOutStreams);
705         if ( FAILED(hr) )
706                 return hr;
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;
713
714         /* create and initialize an allocator. */
715         hr = This->pParser->m_pHandler->pGetAllocProp(This->pParser,&This->pParser->m_propAlloc);
716         if ( FAILED(hr) )
717                 return hr;
718         if ( This->pParser->m_propAlloc.cbAlign == 0 )
719                 This->pParser->m_propAlloc.cbAlign = 1;
720
721         if ( This->pParser->m_pAllocator == NULL )
722         {
723                 hr = QUARTZ_CreateMemoryAllocator(NULL,(void**)&punk);
724                 if ( FAILED(hr) )
725                         return hr;
726                 hr = IUnknown_QueryInterface( punk, &IID_IMemAllocator, (void**)&This->pParser->m_pAllocator );
727                 IUnknown_Release(punk);
728                 if ( FAILED(hr) )
729                         return hr;
730         }
731         pAllocActual = NULL;
732         hr = IAsyncReader_RequestAllocator(pReader,This->pParser->m_pAllocator,&This->pParser->m_propAlloc,&pAllocActual);
733         if ( FAILED(hr) )
734                 return hr;
735         IMemAllocator_Release(This->pParser->m_pAllocator);
736         This->pParser->m_pAllocator = pAllocActual;
737
738         /* create output pins. */
739         for ( nIndex = 0; nIndex < This->pParser->m_cOutStreams; nIndex++ )
740         {
741                 pwszOutPinName = This->pParser->m_pHandler->pGetOutPinName(This->pParser,nIndex);
742                 if ( pwszOutPinName == NULL )
743                         return E_FAIL;
744                 hr = QUARTZ_CreateParserOutPin(
745                         This->pParser,
746                         &This->pParser->m_csParser,
747                         &This->pParser->m_ppOutPins[nIndex],
748                         nIndex, pwszOutPinName );
749                 if ( SUCCEEDED(hr) )
750                         hr = QUARTZ_CompList_AddTailComp(
751                                 This->pParser->basefilter.pOutPins,
752                                 (IUnknown*)&(This->pParser->m_ppOutPins[nIndex]->pin),
753                                 NULL, 0 );
754                 if ( FAILED(hr) )
755                         return hr;
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);
760                 if ( FAILED(hr) )
761                 {
762                         ZeroMemory( pmt, sizeof(AM_MEDIA_TYPE) );
763                         return hr;
764                 }
765                 This->pParser->m_ppOutPins[nIndex]->pin.cAcceptTypes = 1;
766                 This->pParser->m_ppOutPins[nIndex]->pin.pmtAcceptTypes = pmt;
767         }
768
769         return NOERROR;
770 }
771
772 static HRESULT CParserInPinImpl_OnDisconnect( CPinBaseImpl* pImpl )
773 {
774         CParserInPinImpl_THIS(pImpl,pin);
775
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 )
782         {
783                 IMemAllocator_Decommit(This->pParser->m_pAllocator);
784                 IMemAllocator_Release(This->pParser->m_pAllocator);
785                 This->pParser->m_pAllocator = NULL;
786         }
787
788         return NOERROR;
789 }
790
791 static HRESULT CParserInPinImpl_CheckMediaType( CPinBaseImpl* pImpl, const AM_MEDIA_TYPE* pmt )
792 {
793         CParserInPinImpl_THIS(pImpl,pin);
794
795         TRACE("(%p,%p)\n",This,pmt);
796
797         if ( !IsEqualGUID( &pmt->majortype, &MEDIATYPE_Stream ) )
798                 return E_FAIL;
799
800         return NOERROR;
801 }
802
803 static const CBasePinHandlers inputpinhandlers =
804 {
805         CParserInPinImpl_OnPreConnect, /* pOnPreConnect */
806         NULL, /* pOnPostConnect */
807         CParserInPinImpl_OnDisconnect, /* pOnDisconnect */
808         CParserInPinImpl_CheckMediaType, /* pCheckMediaType */
809         NULL, /* pQualityNotify */
810         NULL, /* pReceive */
811         NULL, /* pReceiveCanBlock */
812         NULL, /* pEndOfStream */
813         NULL, /* pBeginFlush */
814         NULL, /* pEndFlush */
815         NULL, /* pNewSegment */
816 };
817
818 /***************************************************************************
819  *
820  *      CParserOutPinImpl methods
821  *
822  */
823
824 static HRESULT CParserOutPinImpl_OnPostConnect( CPinBaseImpl* pImpl, IPin* pPin )
825 {
826         CParserOutPinImpl_THIS(pImpl,pin);
827         ALLOCATOR_PROPERTIES    propReq;
828         ALLOCATOR_PROPERTIES    propActual;
829         IMemAllocator*  pAllocator;
830         HRESULT hr;
831         BOOL    bNewAllocator = FALSE;
832
833         TRACE("(%p,%p)\n",This,pPin);
834
835         if ( This->pin.pMemInputPinConnectedTo == NULL )
836                 return E_UNEXPECTED;
837
838         if ( This->m_pOutPinAllocator != NULL )
839         {
840                 IMemAllocator_Release(This->m_pOutPinAllocator);
841                 This->m_pOutPinAllocator = NULL;
842         }
843
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 )
849         {
850                 if ( This->pParser->m_propAlloc.cbAlign != ( This->pParser->m_propAlloc.cbAlign / propReq.cbAlign * propReq.cbAlign ) )
851                         bNewAllocator = TRUE;
852         }
853         if ( propReq.cbPrefix != 0 )
854                 bNewAllocator = TRUE;
855         if ( !bNewAllocator )
856         {
857                 hr = IMemInputPin_NotifyAllocator(
858                         This->pin.pMemInputPinConnectedTo,
859                         This->pParser->m_pAllocator, FALSE );
860                 if ( hr == NOERROR )
861                 {
862                         This->m_pOutPinAllocator = This->pParser->m_pAllocator;
863                         IMemAllocator_AddRef(This->m_pOutPinAllocator);
864                         return NOERROR;
865                 }
866         }
867
868         hr = IMemInputPin_GetAllocator(
869                         This->pin.pMemInputPinConnectedTo, &pAllocator );
870         if ( FAILED(hr) )
871                 return hr;
872         hr = IMemAllocator_SetProperties( pAllocator, &This->pParser->m_propAlloc, &propActual );
873         if ( SUCCEEDED(hr) )
874                 hr = IMemInputPin_NotifyAllocator(
875                         This->pin.pMemInputPinConnectedTo, pAllocator, FALSE );
876         if ( FAILED(hr) )
877         {
878                 IMemAllocator_Release(pAllocator);
879                 return hr;
880         }
881
882         This->m_pOutPinAllocator = pAllocator;
883         return NOERROR;
884 }
885
886 static HRESULT CParserOutPinImpl_OnDisconnect( CPinBaseImpl* pImpl )
887 {
888         CParserOutPinImpl_THIS(pImpl,pin);
889
890         if ( This->m_pOutPinAllocator != NULL )
891         {
892                 IMemAllocator_Release(This->m_pOutPinAllocator);
893                 This->m_pOutPinAllocator = NULL;
894         }
895
896         return NOERROR;
897 }
898
899 static HRESULT CParserOutPinImpl_CheckMediaType( CPinBaseImpl* pImpl, const AM_MEDIA_TYPE* pmt )
900 {
901         CParserOutPinImpl_THIS(pImpl,pin);
902         HRESULT hr;
903
904         TRACE("(%p,%p)\n",This,pmt);
905         if ( pmt == NULL )
906                 return E_POINTER;
907
908         if ( This->pParser->m_pHandler->pCheckStreamType == NULL )
909                 return E_NOTIMPL;
910
911         hr = This->pParser->m_pHandler->pCheckStreamType( This->pParser, This->nStreamIndex, pmt );
912         if ( FAILED(hr) )
913                 return hr;
914
915         return NOERROR;
916 }
917
918
919 static const CBasePinHandlers outputpinhandlers =
920 {
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 */
932 };
933
934 /***************************************************************************
935  *
936  *      new/delete CParserImpl
937  *
938  */
939
940 /* can I use offsetof safely? - FIXME? */
941 static QUARTZ_IFEntry FilterIFEntries[] =
942 {
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) },
946 };
947
948 static void QUARTZ_DestroyParser(IUnknown* punk)
949 {
950         CParserImpl_THIS(punk,unk);
951
952         TRACE( "(%p)\n", This );
953
954         if ( This->m_pInPin != NULL )
955                 CParserInPinImpl_OnDisconnect(&This->m_pInPin->pin);
956
957         CParserImpl_SetAsyncReader( This, NULL );
958         if ( This->m_pAllocator != NULL )
959         {
960                 IMemAllocator_Release(This->m_pAllocator);
961                 This->m_pAllocator = NULL;
962         }
963         if ( This->m_pInPin != NULL )
964         {
965                 IUnknown_Release(This->m_pInPin->unk.punkControl);
966                 This->m_pInPin = NULL;
967         }
968         CParserImpl_ReleaseOutPins( This );
969
970         DeleteCriticalSection( &This->m_csParser );
971
972         CBaseFilterImpl_UninitIBaseFilter(&This->basefilter);
973 }
974
975 HRESULT QUARTZ_CreateParser(
976         IUnknown* punkOuter,void** ppobj,
977         const CLSID* pclsidParser,
978         LPCWSTR pwszParserName,
979         LPCWSTR pwszInPinName,
980         const ParserHandlers* pHandler )
981 {
982         CParserImpl*    This = NULL;
983         HRESULT hr;
984
985         TRACE("(%p,%p)\n",punkOuter,ppobj);
986
987         This = (CParserImpl*)
988                 QUARTZ_AllocObj( sizeof(CParserImpl) );
989         if ( This == NULL )
990                 return E_OUTOFMEMORY;
991         ZeroMemory( This, sizeof(CParserImpl) );
992
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;
1005
1006         QUARTZ_IUnkInit( &This->unk, punkOuter );
1007
1008         hr = CBaseFilterImpl_InitIBaseFilter(
1009                 &This->basefilter,
1010                 This->unk.punkControl,
1011                 pclsidParser,
1012                 pwszParserName,
1013                 &filterhandlers );
1014         if ( SUCCEEDED(hr) )
1015         {
1016                 /* construct this class. */
1017                 hr = S_OK;
1018
1019                 if ( FAILED(hr) )
1020                 {
1021                         CBaseFilterImpl_UninitIBaseFilter(&This->basefilter);
1022                 }
1023         }
1024
1025         if ( FAILED(hr) )
1026         {
1027                 QUARTZ_FreeObj(This);
1028                 return hr;
1029         }
1030
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 );
1035
1036         /* create the input pin. */
1037         hr = QUARTZ_CreateParserInPin(
1038                 This,
1039                 &This->m_csParser,
1040                 &This->m_pInPin,
1041                 pwszInPinName );
1042         if ( SUCCEEDED(hr) )
1043                 hr = QUARTZ_CompList_AddComp(
1044                         This->basefilter.pInPins,
1045                         (IUnknown*)&(This->m_pInPin->pin),
1046                         NULL, 0 );
1047
1048         if ( FAILED(hr) )
1049         {
1050                 IUnknown_Release( This->unk.punkControl );
1051                 return hr;
1052         }
1053
1054         *ppobj = (void*)&(This->unk);
1055
1056         return S_OK;
1057 }
1058
1059 /***************************************************************************
1060  *
1061  *      new/delete CParserInPinImpl
1062  *
1063  */
1064
1065 /* can I use offsetof safely? - FIXME? */
1066 static QUARTZ_IFEntry InPinIFEntries[] =
1067 {
1068   { &IID_IPin, offsetof(CParserInPinImpl,pin)-offsetof(CParserInPinImpl,unk) },
1069   { &IID_IMemInputPin, offsetof(CParserInPinImpl,meminput)-offsetof(CParserInPinImpl,unk) },
1070 };
1071
1072 static void QUARTZ_DestroyParserInPin(IUnknown* punk)
1073 {
1074         CParserInPinImpl_THIS(punk,unk);
1075
1076         TRACE( "(%p)\n", This );
1077
1078         CPinBaseImpl_UninitIPin( &This->pin );
1079         CMemInputPinBaseImpl_UninitIMemInputPin( &This->meminput );
1080 }
1081
1082 HRESULT QUARTZ_CreateParserInPin(
1083         CParserImpl* pFilter,
1084         CRITICAL_SECTION* pcsPin,
1085         CParserInPinImpl** ppPin,
1086         LPCWSTR pwszPinName )
1087 {
1088         CParserInPinImpl*       This = NULL;
1089         HRESULT hr;
1090
1091         TRACE("(%p,%p,%p)\n",pFilter,pcsPin,ppPin);
1092
1093         This = (CParserInPinImpl*)
1094                 QUARTZ_AllocObj( sizeof(CParserInPinImpl) );
1095         if ( This == NULL )
1096                 return E_OUTOFMEMORY;
1097
1098         QUARTZ_IUnkInit( &This->unk, NULL );
1099         This->pParser = pFilter;
1100
1101         hr = CPinBaseImpl_InitIPin(
1102                 &This->pin,
1103                 This->unk.punkControl,
1104                 pcsPin,
1105                 &pFilter->basefilter,
1106                 pwszPinName,
1107                 FALSE,
1108                 &inputpinhandlers );
1109
1110         if ( SUCCEEDED(hr) )
1111         {
1112                 hr = CMemInputPinBaseImpl_InitIMemInputPin(
1113                         &This->meminput,
1114                         This->unk.punkControl,
1115                         &This->pin );
1116                 if ( FAILED(hr) )
1117                 {
1118                         CPinBaseImpl_UninitIPin( &This->pin );
1119                 }
1120         }
1121
1122         if ( FAILED(hr) )
1123         {
1124                 QUARTZ_FreeObj(This);
1125                 return hr;
1126         }
1127
1128         This->unk.pEntries = InPinIFEntries;
1129         This->unk.dwEntries = sizeof(InPinIFEntries)/sizeof(InPinIFEntries[0]);
1130         This->unk.pOnFinalRelease = QUARTZ_DestroyParserInPin;
1131
1132         *ppPin = This;
1133
1134         TRACE("returned successfully.\n");
1135
1136         return S_OK;
1137 }
1138
1139
1140 /***************************************************************************
1141  *
1142  *      new/delete CParserOutPinImpl
1143  *
1144  */
1145
1146 /* can I use offsetof safely? - FIXME? */
1147 static QUARTZ_IFEntry OutPinIFEntries[] =
1148 {
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) },
1153 };
1154
1155 static void QUARTZ_DestroyParserOutPin(IUnknown* punk)
1156 {
1157         CParserOutPinImpl_THIS(punk,unk);
1158
1159         TRACE( "(%p)\n", This );
1160
1161         QUARTZ_MediaType_Free( &This->m_mtOut );
1162         if ( This->m_pOutPinAllocator != NULL )
1163                 IMemAllocator_Release(This->m_pOutPinAllocator);
1164
1165         CParserOutPinImpl_UninitIMediaPosition(This);
1166         CParserOutPinImpl_UninitIMediaSeeking(This);
1167         CQualityControlPassThruImpl_UninitIQualityControl( &This->qcontrol );
1168         CPinBaseImpl_UninitIPin( &This->pin );
1169
1170 }
1171
1172 HRESULT QUARTZ_CreateParserOutPin(
1173         CParserImpl* pFilter,
1174         CRITICAL_SECTION* pcsPin,
1175         CParserOutPinImpl** ppPin,
1176         ULONG nStreamIndex,
1177         LPCWSTR pwszPinName )
1178 {
1179         CParserOutPinImpl*      This = NULL;
1180         HRESULT hr;
1181
1182         TRACE("(%p,%p,%p)\n",pFilter,pcsPin,ppPin);
1183
1184         This = (CParserOutPinImpl*)
1185                 QUARTZ_AllocObj( sizeof(CParserOutPinImpl) );
1186         if ( This == NULL )
1187                 return E_OUTOFMEMORY;
1188
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;
1201
1202
1203         hr = CPinBaseImpl_InitIPin(
1204                 &This->pin,
1205                 This->unk.punkControl,
1206                 pcsPin,
1207                 &pFilter->basefilter,
1208                 pwszPinName,
1209                 TRUE,
1210                 &outputpinhandlers );
1211
1212         if ( SUCCEEDED(hr) )
1213         {
1214                 hr = CQualityControlPassThruImpl_InitIQualityControl(
1215                         &This->qcontrol,
1216                         This->unk.punkControl,
1217                         &This->pin );
1218                 if ( SUCCEEDED(hr) )
1219                 {
1220                         hr = CParserOutPinImpl_InitIMediaSeeking(This);
1221                         if ( SUCCEEDED(hr) )
1222                         {
1223                                 hr = CParserOutPinImpl_InitIMediaPosition(This);
1224                                 if ( FAILED(hr) )
1225                                 {
1226                                         CParserOutPinImpl_UninitIMediaSeeking(This);
1227                                 }
1228                         }
1229                         if ( FAILED(hr) )
1230                         {
1231                                 CQualityControlPassThruImpl_UninitIQualityControl( &This->qcontrol );
1232                         }
1233                 }
1234                 if ( FAILED(hr) )
1235                 {
1236                         CPinBaseImpl_UninitIPin( &This->pin );
1237                 }
1238         }
1239
1240         if ( FAILED(hr) )
1241         {
1242                 QUARTZ_FreeObj(This);
1243                 return hr;
1244         }
1245
1246         This->unk.pEntries = OutPinIFEntries;
1247         This->unk.dwEntries = sizeof(OutPinIFEntries)/sizeof(OutPinIFEntries[0]);
1248         This->unk.pOnFinalRelease = QUARTZ_DestroyParserOutPin;
1249
1250         *ppPin = This;
1251
1252         TRACE("returned successfully.\n");
1253
1254         return S_OK;
1255 }
1256
1257
1258 /***************************************************************************
1259  *
1260  *      IMediaSeeking for CParserOutPinImpl
1261  *
1262  */
1263
1264 static HRESULT WINAPI
1265 IMediaSeeking_fnQueryInterface(IMediaSeeking* iface,REFIID riid,void** ppobj)
1266 {
1267         CParserOutPinImpl_THIS(iface,mediaseeking);
1268
1269         TRACE("(%p)->()\n",This);
1270
1271         return IUnknown_QueryInterface(This->unk.punkControl,riid,ppobj);
1272 }
1273
1274 static ULONG WINAPI
1275 IMediaSeeking_fnAddRef(IMediaSeeking* iface)
1276 {
1277         CParserOutPinImpl_THIS(iface,mediaseeking);
1278
1279         TRACE("(%p)->()\n",This);
1280
1281         return IUnknown_AddRef(This->unk.punkControl);
1282 }
1283
1284 static ULONG WINAPI
1285 IMediaSeeking_fnRelease(IMediaSeeking* iface)
1286 {
1287         CParserOutPinImpl_THIS(iface,mediaseeking);
1288
1289         TRACE("(%p)->()\n",This);
1290
1291         return IUnknown_Release(This->unk.punkControl);
1292 }
1293
1294
1295 static HRESULT WINAPI
1296 IMediaSeeking_fnGetCapabilities(IMediaSeeking* iface,DWORD* pdwCaps)
1297 {
1298         CParserOutPinImpl_THIS(iface,mediaseeking);
1299
1300         FIXME("(%p)->() stub!\n",This);
1301
1302         return E_NOTIMPL;
1303 }
1304
1305 static HRESULT WINAPI
1306 IMediaSeeking_fnCheckCapabilities(IMediaSeeking* iface,DWORD* pdwCaps)
1307 {
1308         CParserOutPinImpl_THIS(iface,mediaseeking);
1309
1310         FIXME("(%p)->() stub!\n",This);
1311
1312         return E_NOTIMPL;
1313 }
1314
1315 static HRESULT WINAPI
1316 IMediaSeeking_fnIsFormatSupported(IMediaSeeking* iface,const GUID* pidFormat)
1317 {
1318         CParserOutPinImpl_THIS(iface,mediaseeking);
1319
1320         FIXME("(%p)->() stub!\n",This);
1321
1322         return E_NOTIMPL;
1323 }
1324
1325 static HRESULT WINAPI
1326 IMediaSeeking_fnQueryPreferredFormat(IMediaSeeking* iface,GUID* pidFormat)
1327 {
1328         CParserOutPinImpl_THIS(iface,mediaseeking);
1329
1330         FIXME("(%p)->() stub!\n",This);
1331
1332         return E_NOTIMPL;
1333 }
1334
1335 static HRESULT WINAPI
1336 IMediaSeeking_fnGetTimeFormat(IMediaSeeking* iface,GUID* pidFormat)
1337 {
1338         CParserOutPinImpl_THIS(iface,mediaseeking);
1339
1340         FIXME("(%p)->() stub!\n",This);
1341
1342         return E_NOTIMPL;
1343 }
1344
1345 static HRESULT WINAPI
1346 IMediaSeeking_fnIsUsingTimeFormat(IMediaSeeking* iface,const GUID* pidFormat)
1347 {
1348         CParserOutPinImpl_THIS(iface,mediaseeking);
1349
1350         FIXME("(%p)->() stub!\n",This);
1351
1352         return E_NOTIMPL;
1353 }
1354
1355 static HRESULT WINAPI
1356 IMediaSeeking_fnSetTimeFormat(IMediaSeeking* iface,const GUID* pidFormat)
1357 {
1358         CParserOutPinImpl_THIS(iface,mediaseeking);
1359
1360         FIXME("(%p)->() stub!\n",This);
1361
1362         return E_NOTIMPL;
1363 }
1364
1365 static HRESULT WINAPI
1366 IMediaSeeking_fnGetDuration(IMediaSeeking* iface,LONGLONG* pllDuration)
1367 {
1368         CParserOutPinImpl_THIS(iface,mediaseeking);
1369
1370         /* the following line may produce too many FIXMEs... */
1371         FIXME("(%p)->() stub!\n",This);
1372
1373         return E_NOTIMPL;
1374 }
1375
1376 static HRESULT WINAPI
1377 IMediaSeeking_fnGetStopPosition(IMediaSeeking* iface,LONGLONG* pllPos)
1378 {
1379         CParserOutPinImpl_THIS(iface,mediaseeking);
1380
1381         FIXME("(%p)->() stub!\n",This);
1382
1383         return E_NOTIMPL;
1384 }
1385
1386 static HRESULT WINAPI
1387 IMediaSeeking_fnGetCurrentPosition(IMediaSeeking* iface,LONGLONG* pllPos)
1388 {
1389         CParserOutPinImpl_THIS(iface,mediaseeking);
1390
1391         FIXME("(%p)->() stub!\n",This);
1392
1393         return E_NOTIMPL;
1394 }
1395
1396 static HRESULT WINAPI
1397 IMediaSeeking_fnConvertTimeFormat(IMediaSeeking* iface,LONGLONG* pllOut,const GUID* pidFmtOut,LONGLONG llIn,const GUID* pidFmtIn)
1398 {
1399         CParserOutPinImpl_THIS(iface,mediaseeking);
1400
1401         FIXME("(%p)->() stub!\n",This);
1402
1403         return E_NOTIMPL;
1404 }
1405
1406 static HRESULT WINAPI
1407 IMediaSeeking_fnSetPositions(IMediaSeeking* iface,LONGLONG* pllCur,DWORD dwCurFlags,LONGLONG* pllStop,DWORD dwStopFlags)
1408 {
1409         CParserOutPinImpl_THIS(iface,mediaseeking);
1410
1411         FIXME("(%p)->() stub!\n",This);
1412
1413         return E_NOTIMPL;
1414 }
1415
1416 static HRESULT WINAPI
1417 IMediaSeeking_fnGetPositions(IMediaSeeking* iface,LONGLONG* pllCur,LONGLONG* pllStop)
1418 {
1419         CParserOutPinImpl_THIS(iface,mediaseeking);
1420
1421         FIXME("(%p)->() stub!\n",This);
1422
1423         return E_NOTIMPL;
1424 }
1425
1426 static HRESULT WINAPI
1427 IMediaSeeking_fnGetAvailable(IMediaSeeking* iface,LONGLONG* pllFirst,LONGLONG* pllLast)
1428 {
1429         CParserOutPinImpl_THIS(iface,mediaseeking);
1430
1431         FIXME("(%p)->() stub!\n",This);
1432
1433         return E_NOTIMPL;
1434 }
1435
1436 static HRESULT WINAPI
1437 IMediaSeeking_fnSetRate(IMediaSeeking* iface,double dblRate)
1438 {
1439         CParserOutPinImpl_THIS(iface,mediaseeking);
1440
1441         FIXME("(%p)->() stub!\n",This);
1442
1443         return E_NOTIMPL;
1444 }
1445
1446 static HRESULT WINAPI
1447 IMediaSeeking_fnGetRate(IMediaSeeking* iface,double* pdblRate)
1448 {
1449         CParserOutPinImpl_THIS(iface,mediaseeking);
1450
1451         FIXME("(%p)->() stub!\n",This);
1452
1453         return E_NOTIMPL;
1454 }
1455
1456 static HRESULT WINAPI
1457 IMediaSeeking_fnGetPreroll(IMediaSeeking* iface,LONGLONG* pllPreroll)
1458 {
1459         CParserOutPinImpl_THIS(iface,mediaseeking);
1460
1461         FIXME("(%p)->() stub!\n",This);
1462
1463         return E_NOTIMPL;
1464 }
1465
1466
1467
1468
1469 static ICOM_VTABLE(IMediaSeeking) imediaseeking =
1470 {
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,
1494 };
1495
1496 HRESULT CParserOutPinImpl_InitIMediaSeeking( CParserOutPinImpl* This )
1497 {
1498         TRACE("(%p)\n",This);
1499         ICOM_VTBL(&This->mediaseeking) = &imediaseeking;
1500
1501         return NOERROR;
1502 }
1503
1504 void CParserOutPinImpl_UninitIMediaSeeking( CParserOutPinImpl* This )
1505 {
1506         TRACE("(%p)\n",This);
1507 }
1508
1509 /***************************************************************************
1510  *
1511  *      IMediaPosition for CParserOutPinImpl
1512  *
1513  */
1514
1515 static HRESULT WINAPI
1516 IMediaPosition_fnQueryInterface(IMediaPosition* iface,REFIID riid,void** ppobj)
1517 {
1518         CParserOutPinImpl_THIS(iface,mediaposition);
1519
1520         TRACE("(%p)->()\n",This);
1521
1522         return IUnknown_QueryInterface(This->unk.punkControl,riid,ppobj);
1523 }
1524
1525 static ULONG WINAPI
1526 IMediaPosition_fnAddRef(IMediaPosition* iface)
1527 {
1528         CParserOutPinImpl_THIS(iface,mediaposition);
1529
1530         TRACE("(%p)->()\n",This);
1531
1532         return IUnknown_AddRef(This->unk.punkControl);
1533 }
1534
1535 static ULONG WINAPI
1536 IMediaPosition_fnRelease(IMediaPosition* iface)
1537 {
1538         CParserOutPinImpl_THIS(iface,mediaposition);
1539
1540         TRACE("(%p)->()\n",This);
1541
1542         return IUnknown_Release(This->unk.punkControl);
1543 }
1544
1545 static HRESULT WINAPI
1546 IMediaPosition_fnGetTypeInfoCount(IMediaPosition* iface,UINT* pcTypeInfo)
1547 {
1548         CParserOutPinImpl_THIS(iface,mediaposition);
1549
1550         FIXME("(%p)->() stub!\n",This);
1551
1552         return E_NOTIMPL;
1553 }
1554
1555 static HRESULT WINAPI
1556 IMediaPosition_fnGetTypeInfo(IMediaPosition* iface,UINT iTypeInfo, LCID lcid, ITypeInfo** ppobj)
1557 {
1558         CParserOutPinImpl_THIS(iface,mediaposition);
1559
1560         FIXME("(%p)->() stub!\n",This);
1561
1562         return E_NOTIMPL;
1563 }
1564
1565 static HRESULT WINAPI
1566 IMediaPosition_fnGetIDsOfNames(IMediaPosition* iface,REFIID riid, LPOLESTR* ppwszName, UINT cNames, LCID lcid, DISPID* pDispId)
1567 {
1568         CParserOutPinImpl_THIS(iface,mediaposition);
1569
1570         FIXME("(%p)->() stub!\n",This);
1571
1572         return E_NOTIMPL;
1573 }
1574
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)
1577 {
1578         CParserOutPinImpl_THIS(iface,mediaposition);
1579
1580         FIXME("(%p)->() stub!\n",This);
1581
1582         return E_NOTIMPL;
1583 }
1584
1585
1586 static HRESULT WINAPI
1587 IMediaPosition_fnget_Duration(IMediaPosition* iface,REFTIME* prefTime)
1588 {
1589         CParserOutPinImpl_THIS(iface,mediaposition);
1590
1591         FIXME("(%p)->() stub!\n",This);
1592
1593         return E_NOTIMPL;
1594 }
1595
1596 static HRESULT WINAPI
1597 IMediaPosition_fnput_CurrentPosition(IMediaPosition* iface,REFTIME refTime)
1598 {
1599         CParserOutPinImpl_THIS(iface,mediaposition);
1600
1601         FIXME("(%p)->() stub!\n",This);
1602
1603         return E_NOTIMPL;
1604 }
1605
1606 static HRESULT WINAPI
1607 IMediaPosition_fnget_CurrentPosition(IMediaPosition* iface,REFTIME* prefTime)
1608 {
1609         CParserOutPinImpl_THIS(iface,mediaposition);
1610
1611         FIXME("(%p)->() stub!\n",This);
1612
1613         return E_NOTIMPL;
1614 }
1615
1616 static HRESULT WINAPI
1617 IMediaPosition_fnget_StopTime(IMediaPosition* iface,REFTIME* prefTime)
1618 {
1619         CParserOutPinImpl_THIS(iface,mediaposition);
1620
1621         FIXME("(%p)->() stub!\n",This);
1622
1623         return E_NOTIMPL;
1624 }
1625
1626 static HRESULT WINAPI
1627 IMediaPosition_fnput_StopTime(IMediaPosition* iface,REFTIME refTime)
1628 {
1629         CParserOutPinImpl_THIS(iface,mediaposition);
1630
1631         FIXME("(%p)->() stub!\n",This);
1632
1633         return E_NOTIMPL;
1634 }
1635
1636 static HRESULT WINAPI
1637 IMediaPosition_fnget_PrerollTime(IMediaPosition* iface,REFTIME* prefTime)
1638 {
1639         CParserOutPinImpl_THIS(iface,mediaposition);
1640
1641         FIXME("(%p)->() stub!\n",This);
1642
1643         return E_NOTIMPL;
1644 }
1645
1646 static HRESULT WINAPI
1647 IMediaPosition_fnput_PrerollTime(IMediaPosition* iface,REFTIME refTime)
1648 {
1649         CParserOutPinImpl_THIS(iface,mediaposition);
1650
1651         FIXME("(%p)->() stub!\n",This);
1652
1653         return E_NOTIMPL;
1654 }
1655
1656 static HRESULT WINAPI
1657 IMediaPosition_fnput_Rate(IMediaPosition* iface,double dblRate)
1658 {
1659         CParserOutPinImpl_THIS(iface,mediaposition);
1660
1661         return IMediaSeeking_SetRate(CParserOutPinImpl_IMediaSeeking(This),dblRate);
1662 }
1663
1664 static HRESULT WINAPI
1665 IMediaPosition_fnget_Rate(IMediaPosition* iface,double* pdblRate)
1666 {
1667         CParserOutPinImpl_THIS(iface,mediaposition);
1668
1669         return IMediaSeeking_GetRate(CParserOutPinImpl_IMediaSeeking(This),pdblRate);
1670 }
1671
1672 static HRESULT WINAPI
1673 IMediaPosition_fnCanSeekForward(IMediaPosition* iface,LONG* pCanSeek)
1674 {
1675         CParserOutPinImpl_THIS(iface,mediaposition);
1676
1677         FIXME("(%p)->() stub!\n",This);
1678
1679         return E_NOTIMPL;
1680 }
1681
1682 static HRESULT WINAPI
1683 IMediaPosition_fnCanSeekBackward(IMediaPosition* iface,LONG* pCanSeek)
1684 {
1685         CParserOutPinImpl_THIS(iface,mediaposition);
1686
1687         FIXME("(%p)->() stub!\n",This);
1688
1689         return E_NOTIMPL;
1690 }
1691
1692
1693 static ICOM_VTABLE(IMediaPosition) imediaposition =
1694 {
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,
1717 };
1718
1719
1720 HRESULT CParserOutPinImpl_InitIMediaPosition( CParserOutPinImpl* This )
1721 {
1722         TRACE("(%p)\n",This);
1723         ICOM_VTBL(&This->mediaposition) = &imediaposition;
1724
1725         return NOERROR;
1726 }
1727
1728 void CParserOutPinImpl_UninitIMediaPosition( CParserOutPinImpl* This )
1729 {
1730         TRACE("(%p)\n",This);
1731 }
1732