2 * Implements MPEG-1 / MPEG-2 Parser(Splitter).
4 * FIXME - no splitter implementation.
5 * FIXME - no packet support (implemented payload only)
8 * Copyright (C) 2002 Hidenori TAKESHIMA <hidenori@a2.ctktv.ne.jp>
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
42 #include "wine/debug.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
45 #include "quartz_private.h"
49 static const WCHAR QUARTZ_MPEG1Parser_Name[] =
50 { 'M','P','E','G','-','I',' ','S','p','l','i','t','t','e','r',0 };
51 static const WCHAR QUARTZ_MPEG2Parser_Name[] =
52 { 'M','P','E','G','-','2',' ','S','p','l','i','t','t','e','r',0 };
53 static const WCHAR QUARTZ_MPGParserInPin_Name[] =
55 static const WCHAR QUARTZ_MPGParserOutPin_VideoPinName[] =
56 { 'V','i','d','e','o',0 };
57 static const WCHAR QUARTZ_MPGParserOutPin_AudioPinName[] =
58 { 'A','u','d','i','o',0 };
60 static const WCHAR QUARTZ_MPGParserOutPin_UnknownTypePinName[] =
65 static DWORD bitratesl1[16] =
66 { 0, 32, 64, 96,128,160,192,224,256,288,320,352,384,416,448, 0};
67 static DWORD bitratesl2[16] =
68 { 0, 32, 48, 56, 64, 80, 96,112,128,160,192,224,256,320,384, 0};
69 static DWORD bitratesl3[16] =
70 { 0, 32, 40, 48, 56, 64, 80, 96,112,128,160,192,224,256,320, 0};
73 /****************************************************************************
79 typedef struct CMPGParseImpl CMPGParseImpl;
80 typedef struct CMPGParsePayload CMPGParsePayload;
84 MPGPayload_Video = 0xe0,
85 MPGPayload_Audio = 0xc0,
92 DWORD dwPayloadBlockSizeMax;
94 CMPGParsePayload* pPayloads;
97 struct CMPGParsePayload
99 enum MPGPayloadType payloadtype;
100 BOOL bDataDiscontinuity;
104 static HRESULT CMPGParseImpl_SyncReadPayload(
105 CParserImpl* pImpl, CMPGParseImpl* This,
106 enum MPGPayloadType payloadtype,
107 LONGLONG llPosStart, LONG lLength, BYTE* pbBuf )
109 if ( This == NULL || This->pPayloads == NULL )
112 if ( This->bRawPayload )
114 if ( payloadtype != This->pPayloads[0].payloadtype )
116 return IAsyncReader_SyncRead( pImpl->m_pReader, llPosStart, lLength, pbBuf );
120 FIXME( "not implemented\n" );
128 static HRESULT CMPGParseImpl_InitParser( CParserImpl* pImpl, ULONG* pcStreams )
130 CMPGParseImpl* This = NULL;
134 TRACE("(%p,%p)\n",pImpl,pcStreams);
136 This = (CMPGParseImpl*)QUARTZ_AllocMem( sizeof(CMPGParseImpl) );
138 return E_OUTOFMEMORY;
139 pImpl->m_pUserData = This;
140 ZeroMemory( This, sizeof(CMPGParseImpl) );
142 hr = IAsyncReader_SyncRead( pImpl->m_pReader, 0, 8, hdrbuf );
148 if ( hdrbuf[0] == 0x00 && hdrbuf[1] == 0x00 &&
149 hdrbuf[2] == 0x01 && hdrbuf[3] == 0xba )
151 This->bRawPayload = FALSE;
152 This->dwPayloadBlockSizeMax = 0;
154 FIXME( "no mpeg/system support\n" );
158 if ( hdrbuf[0] == 0x00 && hdrbuf[1] == 0x00 &&
159 hdrbuf[2] == 0x01 && hdrbuf[3] == 0xb3 )
161 TRACE( "mpeg/video payload\n" );
163 This->bRawPayload = TRUE;
164 This->dwPayloadBlockSizeMax = 0x4000;
166 This->pPayloads = (CMPGParsePayload*)QUARTZ_AllocMem( sizeof(CMPGParsePayload) );
167 if ( This->pPayloads == NULL )
168 return E_OUTOFMEMORY;
170 This->pPayloads[0].payloadtype = MPGPayload_Video;
171 This->pPayloads[0].bDataDiscontinuity = TRUE;
174 if ( hdrbuf[0] == 0xff && (hdrbuf[1]&0xf0) == 0xf0 )
176 TRACE( "mpeg/audio payload\n" );
178 This->bRawPayload = TRUE;
179 This->dwPayloadBlockSizeMax = 0;
181 This->pPayloads = (CMPGParsePayload*)QUARTZ_AllocMem( sizeof(CMPGParsePayload) );
182 if ( This->pPayloads == NULL )
183 return E_OUTOFMEMORY;
185 This->pPayloads[0].payloadtype = MPGPayload_Audio;
186 This->pPayloads[0].bDataDiscontinuity = TRUE;
196 static HRESULT CMPGParseImpl_UninitParser( CParserImpl* pImpl )
198 CMPGParseImpl* This = (CMPGParseImpl*)pImpl->m_pUserData;
201 TRACE("(%p)\n",This);
208 if ( This->pPayloads != NULL )
210 for ( nIndex = 0; nIndex < This->cPayloads; nIndex++ )
212 /* release this stream */
216 QUARTZ_FreeMem( This->pPayloads );
217 This->pPayloads = NULL;
220 QUARTZ_FreeMem( This );
221 pImpl->m_pUserData = NULL;
226 static LPCWSTR CMPGParseImpl_GetOutPinName( CParserImpl* pImpl, ULONG nStreamIndex )
228 CMPGParseImpl* This = (CMPGParseImpl*)pImpl->m_pUserData;
230 TRACE("(%p,%lu)\n",This,nStreamIndex);
232 if ( This == NULL || nStreamIndex >= This->cPayloads )
235 switch ( This->pPayloads[nStreamIndex].payloadtype )
237 case MPGPayload_Video:
238 return QUARTZ_MPGParserOutPin_VideoPinName;
239 case MPGPayload_Audio:
240 return QUARTZ_MPGParserOutPin_AudioPinName;
242 FIXME("mpeg - unknown stream type %02x\n",This->pPayloads[nStreamIndex].payloadtype);
246 return QUARTZ_MPGParserOutPin_UnknownTypePinName;
249 static HRESULT CMPGParseImpl_GetStreamType( CParserImpl* pImpl, ULONG nStreamIndex, AM_MEDIA_TYPE* pmt )
251 CMPGParseImpl* This = (CMPGParseImpl*)pImpl->m_pUserData;
255 MPEG1VIDEOINFO* pmpg1vi;
256 MPEG2VIDEOINFO* pmpg2vi;
257 MPEG1WAVEFORMAT* pmpg1wav;
258 enum MPGPayloadType payloadtype;
259 DWORD dwPayloadBlockSize;
261 TRACE("(%p,%lu,%p)\n",This,nStreamIndex,pmt);
265 if ( nStreamIndex >= This->cPayloads )
268 ZeroMemory( pmt, sizeof(AM_MEDIA_TYPE) );
270 payloadtype = This->pPayloads[nStreamIndex].payloadtype;
271 switch ( payloadtype )
273 case MPGPayload_Video:
274 hr = CMPGParseImpl_SyncReadPayload(
275 pImpl, This, payloadtype, 0, 140+10, hdrbuf );
281 memcpy( &pmt->majortype, &MEDIATYPE_Video, sizeof(GUID) );
283 if ( hdrbuf[seqhdrlen-1] & 0x2 )
285 if ( hdrbuf[seqhdrlen-1] & 0x1 )
287 if ( hdrbuf[seqhdrlen ] == 0x00 && hdrbuf[seqhdrlen+1] == 0x00 &&
288 hdrbuf[seqhdrlen+2] == 0x01 && hdrbuf[seqhdrlen+3] == 0xb5 )
291 FIXME("video MPEG-2\n");
292 if ( (hdrbuf[seqhdrlen+4]&0xf0) != 0x1 )
294 memcpy( &pmt->subtype, &MEDIASUBTYPE_MPEG2_VIDEO, sizeof(GUID) );
295 memcpy( &pmt->formattype, &FORMAT_MPEG2_VIDEO, sizeof(GUID) );
296 pmt->bFixedSizeSamples = 0;
297 pmt->bTemporalCompression = 1;
298 pmt->lSampleSize = 0;
299 pmt->cbFormat = sizeof(MPEG2VIDEOINFO);
300 pmt->pbFormat = (BYTE*)CoTaskMemAlloc( sizeof(MPEG2VIDEOINFO) );
301 if ( pmt->pbFormat == NULL )
302 return E_OUTOFMEMORY;
303 ZeroMemory( pmt->pbFormat, sizeof(MPEG2VIDEOINFO) );
304 pmpg2vi = (MPEG2VIDEOINFO*)pmt->pbFormat;
305 pmpg2vi->hdr.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
306 pmpg2vi->hdr.bmiHeader.biWidth = ((UINT)hdrbuf[4] << 4) | ((UINT)hdrbuf[5] >> 4); /* FIXME! */
307 pmpg2vi->hdr.bmiHeader.biHeight = (((UINT)hdrbuf[5] & 0xf) << 8) | ((UINT)hdrbuf[6]); /* FIXME! */
308 pmpg2vi->hdr.dwInterlaceFlags = AMINTERLACE_FieldPatBothRegular; /* FIXME? */
309 pmpg2vi->hdr.dwCopyProtectFlags = AMCOPYPROTECT_RestrictDuplication; /* FIXME? */
310 pmpg2vi->hdr.dwPictAspectRatioX = 1; /* FIXME? */
311 pmpg2vi->hdr.dwPictAspectRatioY = 1; /* FIXME? */
312 pmpg2vi->dwStartTimeCode = 0;
313 pmpg2vi->cbSequenceHeader = seqhdrlen + 10;
314 switch ( hdrbuf[seqhdrlen+4] & 0xf )
316 case 5: pmpg2vi->dwProfile = AM_MPEG2Profile_Simple; break;
317 case 4: pmpg2vi->dwProfile = AM_MPEG2Profile_Main; break;
318 case 3: pmpg2vi->dwProfile = AM_MPEG2Profile_SNRScalable; break;
319 case 2: pmpg2vi->dwProfile = AM_MPEG2Profile_SpatiallyScalable; break;
320 case 1: pmpg2vi->dwProfile = AM_MPEG2Profile_High; break;
321 default: return E_FAIL;
323 switch ( hdrbuf[seqhdrlen+5] >> 4 )
325 case 10: pmpg2vi->dwLevel = AM_MPEG2Level_Low; break;
326 case 8: pmpg2vi->dwLevel = AM_MPEG2Level_Main; break;
327 case 6: pmpg2vi->dwLevel = AM_MPEG2Level_High1440; break;
328 case 4: pmpg2vi->dwLevel = AM_MPEG2Level_High; break;
329 default: return E_FAIL;
331 pmpg2vi->dwFlags = 0; /* FIXME? */
332 memcpy( pmpg2vi->dwSequenceHeader, hdrbuf, seqhdrlen + 10 );
339 memcpy( &pmt->subtype, &MEDIASUBTYPE_MPEG1Payload, sizeof(GUID) );
340 memcpy( &pmt->formattype, &FORMAT_MPEGVideo, sizeof(GUID) );
341 pmt->bFixedSizeSamples = 0;
342 pmt->bTemporalCompression = 1;
343 pmt->lSampleSize = 0;
344 pmt->cbFormat = sizeof(MPEG1VIDEOINFO);
345 pmt->pbFormat = (BYTE*)CoTaskMemAlloc( sizeof(MPEG1VIDEOINFO) );
346 if ( pmt->pbFormat == NULL )
347 return E_OUTOFMEMORY;
348 ZeroMemory( pmt->pbFormat, sizeof(MPEG1VIDEOINFO) );
349 pmpg1vi = (MPEG1VIDEOINFO*)pmt->pbFormat;
350 pmpg1vi->hdr.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
351 pmpg1vi->hdr.bmiHeader.biWidth = ((UINT)hdrbuf[4] << 4) | ((UINT)hdrbuf[5] >> 4);
352 pmpg1vi->hdr.bmiHeader.biHeight = (((UINT)hdrbuf[5] & 0xf) << 8) | ((UINT)hdrbuf[6]);
353 pmpg1vi->hdr.bmiHeader.biPlanes = 1;
354 pmpg1vi->dwStartTimeCode = 0;
355 pmpg1vi->cbSequenceHeader = seqhdrlen;
356 memcpy( pmpg1vi->bSequenceHeader, hdrbuf, seqhdrlen );
360 case MPGPayload_Audio:
361 hr = CMPGParseImpl_SyncReadPayload(
362 pImpl, This, payloadtype, 0, 4, hdrbuf );
368 memcpy( &pmt->majortype, &MEDIATYPE_Audio, sizeof(GUID) );
369 memcpy( &pmt->formattype, &FORMAT_WaveFormatEx, sizeof(GUID) );
371 if ( !( hdrbuf[1] & 0x8 ) )
374 FIXME("audio not MPEG-1\n");
380 memcpy( &pmt->subtype, &MEDIASUBTYPE_MPEG1AudioPayload, sizeof(GUID) );
381 pmt->bFixedSizeSamples = 0;
382 pmt->bTemporalCompression = 1;
383 pmt->lSampleSize = 0;
384 pmt->cbFormat = sizeof(MPEG1WAVEFORMAT);
385 pmt->pbFormat = (BYTE*)CoTaskMemAlloc( sizeof(MPEG1WAVEFORMAT) );
386 if ( pmt->pbFormat == NULL )
387 return E_OUTOFMEMORY;
388 ZeroMemory( pmt->pbFormat, sizeof(MPEG1WAVEFORMAT) );
389 pmpg1wav = (MPEG1WAVEFORMAT*)pmt->pbFormat;
390 switch ( hdrbuf[1] & 0x6 )
394 pmpg1wav->fwHeadLayer = ACM_MPEG_LAYER1;
398 pmpg1wav->fwHeadLayer = ACM_MPEG_LAYER2;
402 pmpg1wav->fwHeadLayer = ACM_MPEG_LAYER3;
404 default: return E_FAIL;
407 switch ( pmpg1wav->fwHeadLayer )
409 case ACM_MPEG_LAYER1:
410 pmpg1wav->dwHeadBitrate = bitratesl1[hdrbuf[2]>>4]*1000;
412 case ACM_MPEG_LAYER2:
413 pmpg1wav->dwHeadBitrate = bitratesl2[hdrbuf[2]>>4]*1000;
415 case ACM_MPEG_LAYER3:
416 pmpg1wav->dwHeadBitrate = bitratesl3[hdrbuf[2]>>4]*1000;
419 if ( pmpg1wav->dwHeadBitrate == 0 )
422 switch ( hdrbuf[3] & 0xc0 )
426 pmpg1wav->fwHeadMode = ACM_MPEG_STEREO;
429 TRACE("JOINTSTEREO\n");
430 pmpg1wav->fwHeadMode = ACM_MPEG_JOINTSTEREO;
433 TRACE("DUALCHANNEL\n");
434 pmpg1wav->fwHeadMode = ACM_MPEG_DUALCHANNEL;
437 TRACE("SINGLECHANNEL\n");
438 pmpg1wav->fwHeadMode = ACM_MPEG_SINGLECHANNEL;
442 pmpg1wav->fwHeadModeExt = (hdrbuf[3] & 0x30) >> 4; /* FIXME?? */
443 pmpg1wav->wHeadEmphasis = (hdrbuf[3] & 0x03); /* FIXME?? */
444 pmpg1wav->fwHeadFlags = ACM_MPEG_ID_MPEG1;
445 if ( hdrbuf[1] & 0x1 )
446 pmpg1wav->fwHeadFlags |= ACM_MPEG_PROTECTIONBIT;
447 if ( hdrbuf[2] & 0x1 )
448 pmpg1wav->fwHeadFlags |= ACM_MPEG_PRIVATEBIT;
449 if ( hdrbuf[3] & 0x8 )
450 pmpg1wav->fwHeadFlags |= ACM_MPEG_COPYRIGHT;
451 if ( hdrbuf[3] & 0x4 )
452 pmpg1wav->fwHeadFlags |= ACM_MPEG_ORIGINALHOME;
453 pmpg1wav->dwPTSLow = 0;
454 pmpg1wav->dwPTSHigh = 0;
456 pmpg1wav->wfx.wFormatTag = WAVE_FORMAT_MPEG;
457 pmpg1wav->wfx.nChannels = (pmpg1wav->fwHeadMode != ACM_MPEG_SINGLECHANNEL) ? 2 : 1;
458 switch ( hdrbuf[2] & 0x0c )
462 pmpg1wav->wfx.nSamplesPerSec = 44100;
466 pmpg1wav->wfx.nSamplesPerSec = 48000;
470 pmpg1wav->wfx.nSamplesPerSec = 32000;
472 default: return E_FAIL;
474 pmpg1wav->wfx.nAvgBytesPerSec = pmpg1wav->dwHeadBitrate >> 3;
475 switch ( pmpg1wav->fwHeadLayer )
477 case ACM_MPEG_LAYER1:
478 pmpg1wav->wfx.nBlockAlign = (384>>3) * pmpg1wav->dwHeadBitrate / pmpg1wav->wfx.nSamplesPerSec;
480 case ACM_MPEG_LAYER2:
481 pmpg1wav->wfx.nBlockAlign = (1152>>3) * pmpg1wav->dwHeadBitrate / pmpg1wav->wfx.nSamplesPerSec;
483 case ACM_MPEG_LAYER3:
484 pmpg1wav->wfx.nBlockAlign = 1;
487 pmpg1wav->wfx.wBitsPerSample = 0;
488 pmpg1wav->wfx.cbSize = sizeof(MPEG1WAVEFORMAT) - sizeof(WAVEFORMATEX);
489 if ( pmpg1wav->fwHeadLayer != ACM_MPEG_LAYER3 )
491 pmt->bFixedSizeSamples = 1;
492 pmt->lSampleSize = pmpg1wav->wfx.nBlockAlign;
494 dwPayloadBlockSize = (pmpg1wav->wfx.nAvgBytesPerSec + pmpg1wav->wfx.nBlockAlign - 1) / pmpg1wav->wfx.nBlockAlign;
495 if ( dwPayloadBlockSize > This->dwPayloadBlockSizeMax )
496 This->dwPayloadBlockSizeMax = dwPayloadBlockSize;
501 FIXME("mpeg - unknown stream type %02x\n",This->pPayloads[nStreamIndex].payloadtype);
509 static HRESULT CMPGParseImpl_CheckStreamType( CParserImpl* pImpl, ULONG nStreamIndex, const AM_MEDIA_TYPE* pmt )
511 CMPGParseImpl* This = (CMPGParseImpl*)pImpl->m_pUserData;
514 MPEG1VIDEOINFO* pmpg1vi;
515 MPEG1VIDEOINFO* pmpg1viCheck;
516 MPEG2VIDEOINFO* pmpg2vi;
517 MPEG2VIDEOINFO* pmpg2viCheck;
519 WAVEFORMATEX* pwfxCheck;
520 enum MPGPayloadType payloadtype;
522 TRACE("(%p,%lu,%p)\n",This,nStreamIndex,pmt);
526 if ( nStreamIndex >= This->cPayloads )
529 hr = CMPGParseImpl_GetStreamType( pImpl, nStreamIndex, &mt );
532 if ( !IsEqualGUID( &pmt->majortype, &mt.majortype ) ||
533 !IsEqualGUID( &pmt->subtype, &mt.subtype ) ||
534 !IsEqualGUID( &pmt->formattype, &mt.formattype ) )
540 TRACE("check format\n");
543 payloadtype = This->pPayloads[nStreamIndex].payloadtype;
544 switch ( payloadtype )
546 case MPGPayload_Video:
547 if ( IsEqualGUID( &mt.formattype, &FORMAT_MPEGVideo ) )
550 if ( pmt->cbFormat != mt.cbFormat ||
551 pmt->pbFormat == NULL )
556 pmpg1vi = (MPEG1VIDEOINFO*)mt.pbFormat;
557 pmpg1viCheck = (MPEG1VIDEOINFO*)pmt->pbFormat;
558 if ( memcmp( pmpg1vi, pmpg1viCheck, sizeof(MPEG1VIDEOINFO) ) != 0 )
565 if ( IsEqualGUID( &mt.formattype, &FORMAT_MPEG2_VIDEO ) )
568 if ( pmt->cbFormat != mt.cbFormat ||
569 pmt->pbFormat == NULL )
574 pmpg2vi = (MPEG2VIDEOINFO*)mt.pbFormat;
575 pmpg2viCheck = (MPEG2VIDEOINFO*)pmt->pbFormat;
576 if ( memcmp( pmpg2vi, pmpg2viCheck, sizeof(MPEG2VIDEOINFO) ) != 0 )
588 case MPGPayload_Audio:
589 if ( IsEqualGUID( &mt.formattype, &FORMAT_WaveFormatEx ) )
591 if ( mt.cbFormat != pmt->cbFormat ||
592 pmt->pbFormat == NULL )
597 pwfx = (WAVEFORMATEX*)mt.pbFormat;
598 pwfxCheck = (WAVEFORMATEX*)pmt->pbFormat;
600 if ( memcmp( pwfx, pwfxCheck, sizeof(WAVEFORMATEX) ) != 0 )
614 FIXME( "unsupported payload type\n" );
621 QUARTZ_MediaType_Free( &mt );
628 static HRESULT CMPGParseImpl_GetAllocProp( CParserImpl* pImpl, ALLOCATOR_PROPERTIES* pReqProp )
630 CMPGParseImpl* This = (CMPGParseImpl*)pImpl->m_pUserData;
632 TRACE("(%p,%p)\n",This,pReqProp);
637 ZeroMemory( pReqProp, sizeof(ALLOCATOR_PROPERTIES) );
638 pReqProp->cBuffers = This->cPayloads;
639 pReqProp->cbBuffer = This->dwPayloadBlockSizeMax;
644 static HRESULT CMPGParseImpl_GetNextRequest( CParserImpl* pImpl, ULONG* pnStreamIndex, LONGLONG* pllStart, LONG* plLength, REFERENCE_TIME* prtStart, REFERENCE_TIME* prtStop, DWORD* pdwSampleFlags )
646 CMPGParseImpl* This = (CMPGParseImpl*)pImpl->m_pUserData;
650 *pdwSampleFlags = AM_SAMPLE_SPLICEPOINT;
652 TRACE("(%p)\n",This);
654 if ( This->bRawPayload )
656 if ( This->dwPayloadBlockSizeMax == 0 ||
657 This->cPayloads != 1 || This->pPayloads == NULL )
660 *pllStart = This->llPosNext;
661 *plLength = This->dwPayloadBlockSizeMax;
664 if ( This->pPayloads[0].bDataDiscontinuity )
666 *pdwSampleFlags |= AM_SAMPLE_DATADISCONTINUITY;
667 This->pPayloads[0].bDataDiscontinuity = FALSE;
679 static HRESULT CMPGParseImpl_ProcessSample( CParserImpl* pImpl, ULONG nStreamIndex, LONGLONG llStart, LONG lLength, IMediaSample* pSample )
681 CMPGParseImpl* This = (CMPGParseImpl*)pImpl->m_pUserData;
684 TRACE("(%p,%lu,%ld,%ld,%p)\n",This,nStreamIndex,(long)llStart,lLength,pSample);
689 if ( This->bRawPayload )
691 hr = IMediaSample_SetTime(pSample,NULL,NULL);
700 static const struct ParserHandlers CMPGParseImpl_Handlers =
702 CMPGParseImpl_InitParser,
703 CMPGParseImpl_UninitParser,
704 CMPGParseImpl_GetOutPinName,
705 CMPGParseImpl_GetStreamType,
706 CMPGParseImpl_CheckStreamType,
707 CMPGParseImpl_GetAllocProp,
708 CMPGParseImpl_GetNextRequest,
709 CMPGParseImpl_ProcessSample,
711 /* for IQualityControl */
712 NULL, /* pQualityNotify */
715 NULL, /* pGetSeekingCaps */
716 NULL, /* pIsTimeFormatSupported */
717 NULL, /* pGetCurPos */
718 NULL, /* pSetCurPos */
719 NULL, /* pGetDuration */
720 NULL, /* pGetStopPos */
721 NULL, /* pSetStopPos */
722 NULL, /* pGetPreroll */
725 HRESULT QUARTZ_CreateMPEG1Splitter(IUnknown* punkOuter,void** ppobj)
727 return QUARTZ_CreateParser(
729 &CLSID_MPEG1Splitter,
730 QUARTZ_MPEG1Parser_Name,
731 QUARTZ_MPGParserInPin_Name,
732 &CMPGParseImpl_Handlers );