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
;
103 static HRESULT
CMPGParseImpl_GetStreamType( CParserImpl
* pImpl
, ULONG nStreamIndex
, AM_MEDIA_TYPE
* pmt
);
105 static HRESULT
CMPGParseImpl_SyncReadPayload(
106 CParserImpl
* pImpl
, CMPGParseImpl
* This
,
107 enum MPGPayloadType payloadtype
,
108 LONGLONG llPosStart
, LONG lLength
, BYTE
* pbBuf
)
110 if ( This
== NULL
|| This
->pPayloads
== NULL
)
113 if ( This
->bRawPayload
)
115 if ( payloadtype
!= This
->pPayloads
[0].payloadtype
)
117 return IAsyncReader_SyncRead( pImpl
->m_pReader
, llPosStart
, lLength
, pbBuf
);
121 FIXME( "not implemented\n" );
129 static HRESULT
CMPGParseImpl_InitParser( CParserImpl
* pImpl
, ULONG
* pcStreams
)
131 CMPGParseImpl
* This
= NULL
;
137 TRACE("(%p,%p)\n",pImpl
,pcStreams
);
139 This
= (CMPGParseImpl
*)QUARTZ_AllocMem( sizeof(CMPGParseImpl
) );
141 return E_OUTOFMEMORY
;
142 pImpl
->m_pUserData
= This
;
143 ZeroMemory( This
, sizeof(CMPGParseImpl
) );
145 hr
= IAsyncReader_SyncRead( pImpl
->m_pReader
, 0, 8, hdrbuf
);
151 if ( hdrbuf
[0] == 0x00 && hdrbuf
[1] == 0x00 &&
152 hdrbuf
[2] == 0x01 && hdrbuf
[3] == 0xba )
154 This
->bRawPayload
= FALSE
;
155 This
->dwPayloadBlockSizeMax
= 0;
157 FIXME( "no mpeg/system support\n" );
161 if ( hdrbuf
[0] == 0x00 && hdrbuf
[1] == 0x00 &&
162 hdrbuf
[2] == 0x01 && hdrbuf
[3] == 0xb3 )
164 TRACE( "mpeg/video payload\n" );
166 This
->bRawPayload
= TRUE
;
167 This
->dwPayloadBlockSizeMax
= 0x4000;
169 This
->pPayloads
= (CMPGParsePayload
*)QUARTZ_AllocMem( sizeof(CMPGParsePayload
) );
170 if ( This
->pPayloads
== NULL
)
171 return E_OUTOFMEMORY
;
173 This
->pPayloads
[0].payloadtype
= MPGPayload_Video
;
174 This
->pPayloads
[0].bDataDiscontinuity
= TRUE
;
177 if ( hdrbuf
[0] == 0xff && (hdrbuf
[1]&0xf0) == 0xf0 )
179 TRACE( "mpeg/audio payload\n" );
181 This
->bRawPayload
= TRUE
;
182 This
->dwPayloadBlockSizeMax
= 0;
184 This
->pPayloads
= (CMPGParsePayload
*)QUARTZ_AllocMem( sizeof(CMPGParsePayload
) );
185 if ( This
->pPayloads
== NULL
)
186 return E_OUTOFMEMORY
;
188 This
->pPayloads
[0].payloadtype
= MPGPayload_Audio
;
189 This
->pPayloads
[0].bDataDiscontinuity
= TRUE
;
196 /* To determine block size, scan all payloads. */
197 ZeroMemory( &mt
, sizeof(mt
) );
198 for ( n
= 0; n
< This
->cPayloads
; n
++ )
200 CMPGParseImpl_GetStreamType(pImpl
,n
,&mt
);
201 QUARTZ_MediaType_Free(&mt
);
207 static HRESULT
CMPGParseImpl_UninitParser( CParserImpl
* pImpl
)
209 CMPGParseImpl
* This
= (CMPGParseImpl
*)pImpl
->m_pUserData
;
212 TRACE("(%p)\n",This
);
219 if ( This
->pPayloads
!= NULL
)
221 for ( nIndex
= 0; nIndex
< This
->cPayloads
; nIndex
++ )
223 /* release this stream */
227 QUARTZ_FreeMem( This
->pPayloads
);
228 This
->pPayloads
= NULL
;
231 QUARTZ_FreeMem( This
);
232 pImpl
->m_pUserData
= NULL
;
237 static LPCWSTR
CMPGParseImpl_GetOutPinName( CParserImpl
* pImpl
, ULONG nStreamIndex
)
239 CMPGParseImpl
* This
= (CMPGParseImpl
*)pImpl
->m_pUserData
;
241 TRACE("(%p,%lu)\n",This
,nStreamIndex
);
243 if ( This
== NULL
|| nStreamIndex
>= This
->cPayloads
)
246 switch ( This
->pPayloads
[nStreamIndex
].payloadtype
)
248 case MPGPayload_Video
:
249 return QUARTZ_MPGParserOutPin_VideoPinName
;
250 case MPGPayload_Audio
:
251 return QUARTZ_MPGParserOutPin_AudioPinName
;
253 FIXME("mpeg - unknown stream type %02x\n",This
->pPayloads
[nStreamIndex
].payloadtype
);
257 return QUARTZ_MPGParserOutPin_UnknownTypePinName
;
260 static HRESULT
CMPGParseImpl_GetStreamType( CParserImpl
* pImpl
, ULONG nStreamIndex
, AM_MEDIA_TYPE
* pmt
)
262 CMPGParseImpl
* This
= (CMPGParseImpl
*)pImpl
->m_pUserData
;
266 MPEG1VIDEOINFO
* pmpg1vi
;
267 MPEG2VIDEOINFO
* pmpg2vi
;
268 MPEG1WAVEFORMAT
* pmpg1wav
;
269 enum MPGPayloadType payloadtype
;
270 DWORD dwPayloadBlockSize
;
272 TRACE("(%p,%lu,%p)\n",This
,nStreamIndex
,pmt
);
276 if ( nStreamIndex
>= This
->cPayloads
)
279 ZeroMemory( pmt
, sizeof(AM_MEDIA_TYPE
) );
281 payloadtype
= This
->pPayloads
[nStreamIndex
].payloadtype
;
282 switch ( payloadtype
)
284 case MPGPayload_Video
:
285 hr
= CMPGParseImpl_SyncReadPayload(
286 pImpl
, This
, payloadtype
, 0, 140+10, hdrbuf
);
292 memcpy( &pmt
->majortype
, &MEDIATYPE_Video
, sizeof(GUID
) );
294 if ( hdrbuf
[seqhdrlen
-1] & 0x2 )
296 if ( hdrbuf
[seqhdrlen
-1] & 0x1 )
298 if ( hdrbuf
[seqhdrlen
] == 0x00 && hdrbuf
[seqhdrlen
+1] == 0x00 &&
299 hdrbuf
[seqhdrlen
+2] == 0x01 && hdrbuf
[seqhdrlen
+3] == 0xb5 )
302 FIXME("video MPEG-2\n");
303 if ( (hdrbuf
[seqhdrlen
+4]&0xf0) != 0x1 )
305 memcpy( &pmt
->subtype
, &MEDIASUBTYPE_MPEG2_VIDEO
, sizeof(GUID
) );
306 memcpy( &pmt
->formattype
, &FORMAT_MPEG2_VIDEO
, sizeof(GUID
) );
307 pmt
->bFixedSizeSamples
= 0;
308 pmt
->bTemporalCompression
= 1;
309 pmt
->lSampleSize
= 0;
310 pmt
->cbFormat
= sizeof(MPEG2VIDEOINFO
);
311 pmt
->pbFormat
= (BYTE
*)CoTaskMemAlloc( sizeof(MPEG2VIDEOINFO
) );
312 if ( pmt
->pbFormat
== NULL
)
313 return E_OUTOFMEMORY
;
314 ZeroMemory( pmt
->pbFormat
, sizeof(MPEG2VIDEOINFO
) );
315 pmpg2vi
= (MPEG2VIDEOINFO
*)pmt
->pbFormat
;
316 pmpg2vi
->hdr
.bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
317 pmpg2vi
->hdr
.bmiHeader
.biWidth
= ((UINT
)hdrbuf
[4] << 4) | ((UINT
)hdrbuf
[5] >> 4); /* FIXME! */
318 pmpg2vi
->hdr
.bmiHeader
.biHeight
= (((UINT
)hdrbuf
[5] & 0xf) << 8) | ((UINT
)hdrbuf
[6]); /* FIXME! */
319 pmpg2vi
->hdr
.dwInterlaceFlags
= AMINTERLACE_FieldPatBothRegular
; /* FIXME? */
320 pmpg2vi
->hdr
.dwCopyProtectFlags
= AMCOPYPROTECT_RestrictDuplication
; /* FIXME? */
321 pmpg2vi
->hdr
.dwPictAspectRatioX
= 1; /* FIXME? */
322 pmpg2vi
->hdr
.dwPictAspectRatioY
= 1; /* FIXME? */
323 pmpg2vi
->dwStartTimeCode
= 0;
324 pmpg2vi
->cbSequenceHeader
= seqhdrlen
+ 10;
325 switch ( hdrbuf
[seqhdrlen
+4] & 0xf )
327 case 5: pmpg2vi
->dwProfile
= AM_MPEG2Profile_Simple
; break;
328 case 4: pmpg2vi
->dwProfile
= AM_MPEG2Profile_Main
; break;
329 case 3: pmpg2vi
->dwProfile
= AM_MPEG2Profile_SNRScalable
; break;
330 case 2: pmpg2vi
->dwProfile
= AM_MPEG2Profile_SpatiallyScalable
; break;
331 case 1: pmpg2vi
->dwProfile
= AM_MPEG2Profile_High
; break;
332 default: return E_FAIL
;
334 switch ( hdrbuf
[seqhdrlen
+5] >> 4 )
336 case 10: pmpg2vi
->dwLevel
= AM_MPEG2Level_Low
; break;
337 case 8: pmpg2vi
->dwLevel
= AM_MPEG2Level_Main
; break;
338 case 6: pmpg2vi
->dwLevel
= AM_MPEG2Level_High1440
; break;
339 case 4: pmpg2vi
->dwLevel
= AM_MPEG2Level_High
; break;
340 default: return E_FAIL
;
342 pmpg2vi
->dwFlags
= 0; /* FIXME? */
343 memcpy( pmpg2vi
->dwSequenceHeader
, hdrbuf
, seqhdrlen
+ 10 );
350 memcpy( &pmt
->subtype
, &MEDIASUBTYPE_MPEG1Payload
, sizeof(GUID
) );
351 memcpy( &pmt
->formattype
, &FORMAT_MPEGVideo
, sizeof(GUID
) );
352 pmt
->bFixedSizeSamples
= 0;
353 pmt
->bTemporalCompression
= 1;
354 pmt
->lSampleSize
= 0;
355 pmt
->cbFormat
= sizeof(MPEG1VIDEOINFO
);
356 pmt
->pbFormat
= (BYTE
*)CoTaskMemAlloc( sizeof(MPEG1VIDEOINFO
) );
357 if ( pmt
->pbFormat
== NULL
)
358 return E_OUTOFMEMORY
;
359 ZeroMemory( pmt
->pbFormat
, sizeof(MPEG1VIDEOINFO
) );
360 pmpg1vi
= (MPEG1VIDEOINFO
*)pmt
->pbFormat
;
361 pmpg1vi
->hdr
.bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
362 pmpg1vi
->hdr
.bmiHeader
.biWidth
= ((UINT
)hdrbuf
[4] << 4) | ((UINT
)hdrbuf
[5] >> 4);
363 pmpg1vi
->hdr
.bmiHeader
.biHeight
= (((UINT
)hdrbuf
[5] & 0xf) << 8) | ((UINT
)hdrbuf
[6]);
364 pmpg1vi
->hdr
.bmiHeader
.biPlanes
= 1;
365 pmpg1vi
->dwStartTimeCode
= 0;
366 pmpg1vi
->cbSequenceHeader
= seqhdrlen
;
367 memcpy( pmpg1vi
->bSequenceHeader
, hdrbuf
, seqhdrlen
);
371 case MPGPayload_Audio
:
372 hr
= CMPGParseImpl_SyncReadPayload(
373 pImpl
, This
, payloadtype
, 0, 4, hdrbuf
);
379 memcpy( &pmt
->majortype
, &MEDIATYPE_Audio
, sizeof(GUID
) );
380 memcpy( &pmt
->formattype
, &FORMAT_WaveFormatEx
, sizeof(GUID
) );
382 if ( !( hdrbuf
[1] & 0x8 ) )
385 FIXME("audio not MPEG-1\n");
391 memcpy( &pmt
->subtype
, &MEDIASUBTYPE_MPEG1AudioPayload
, sizeof(GUID
) );
392 pmt
->bFixedSizeSamples
= 0;
393 pmt
->bTemporalCompression
= 1;
394 pmt
->lSampleSize
= 0;
395 pmt
->cbFormat
= sizeof(MPEG1WAVEFORMAT
);
396 pmt
->pbFormat
= (BYTE
*)CoTaskMemAlloc( sizeof(MPEG1WAVEFORMAT
) );
397 if ( pmt
->pbFormat
== NULL
)
398 return E_OUTOFMEMORY
;
399 ZeroMemory( pmt
->pbFormat
, sizeof(MPEG1WAVEFORMAT
) );
400 pmpg1wav
= (MPEG1WAVEFORMAT
*)pmt
->pbFormat
;
401 switch ( hdrbuf
[1] & 0x6 )
405 pmpg1wav
->fwHeadLayer
= ACM_MPEG_LAYER1
;
409 pmpg1wav
->fwHeadLayer
= ACM_MPEG_LAYER2
;
413 pmpg1wav
->fwHeadLayer
= ACM_MPEG_LAYER3
;
415 default: return E_FAIL
;
418 switch ( pmpg1wav
->fwHeadLayer
)
420 case ACM_MPEG_LAYER1
:
421 pmpg1wav
->dwHeadBitrate
= bitratesl1
[hdrbuf
[2]>>4]*1000;
423 case ACM_MPEG_LAYER2
:
424 pmpg1wav
->dwHeadBitrate
= bitratesl2
[hdrbuf
[2]>>4]*1000;
426 case ACM_MPEG_LAYER3
:
427 pmpg1wav
->dwHeadBitrate
= bitratesl3
[hdrbuf
[2]>>4]*1000;
430 if ( pmpg1wav
->dwHeadBitrate
== 0 )
433 switch ( hdrbuf
[3] & 0xc0 )
437 pmpg1wav
->fwHeadMode
= ACM_MPEG_STEREO
;
440 TRACE("JOINTSTEREO\n");
441 pmpg1wav
->fwHeadMode
= ACM_MPEG_JOINTSTEREO
;
444 TRACE("DUALCHANNEL\n");
445 pmpg1wav
->fwHeadMode
= ACM_MPEG_DUALCHANNEL
;
448 TRACE("SINGLECHANNEL\n");
449 pmpg1wav
->fwHeadMode
= ACM_MPEG_SINGLECHANNEL
;
453 pmpg1wav
->fwHeadModeExt
= (hdrbuf
[3] & 0x30) >> 4; /* FIXME?? */
454 pmpg1wav
->wHeadEmphasis
= (hdrbuf
[3] & 0x03); /* FIXME?? */
455 pmpg1wav
->fwHeadFlags
= ACM_MPEG_ID_MPEG1
;
456 if ( hdrbuf
[1] & 0x1 )
457 pmpg1wav
->fwHeadFlags
|= ACM_MPEG_PROTECTIONBIT
;
458 if ( hdrbuf
[2] & 0x1 )
459 pmpg1wav
->fwHeadFlags
|= ACM_MPEG_PRIVATEBIT
;
460 if ( hdrbuf
[3] & 0x8 )
461 pmpg1wav
->fwHeadFlags
|= ACM_MPEG_COPYRIGHT
;
462 if ( hdrbuf
[3] & 0x4 )
463 pmpg1wav
->fwHeadFlags
|= ACM_MPEG_ORIGINALHOME
;
464 pmpg1wav
->dwPTSLow
= 0;
465 pmpg1wav
->dwPTSHigh
= 0;
467 pmpg1wav
->wfx
.wFormatTag
= WAVE_FORMAT_MPEG
;
468 pmpg1wav
->wfx
.nChannels
= (pmpg1wav
->fwHeadMode
!= ACM_MPEG_SINGLECHANNEL
) ? 2 : 1;
469 switch ( hdrbuf
[2] & 0x0c )
473 pmpg1wav
->wfx
.nSamplesPerSec
= 44100;
477 pmpg1wav
->wfx
.nSamplesPerSec
= 48000;
481 pmpg1wav
->wfx
.nSamplesPerSec
= 32000;
483 default: return E_FAIL
;
485 pmpg1wav
->wfx
.nAvgBytesPerSec
= pmpg1wav
->dwHeadBitrate
>> 3;
486 switch ( pmpg1wav
->fwHeadLayer
)
488 case ACM_MPEG_LAYER1
:
489 pmpg1wav
->wfx
.nBlockAlign
= (384>>3) * pmpg1wav
->dwHeadBitrate
/ pmpg1wav
->wfx
.nSamplesPerSec
;
491 case ACM_MPEG_LAYER2
:
492 pmpg1wav
->wfx
.nBlockAlign
= (1152>>3) * pmpg1wav
->dwHeadBitrate
/ pmpg1wav
->wfx
.nSamplesPerSec
;
494 case ACM_MPEG_LAYER3
:
495 pmpg1wav
->wfx
.nBlockAlign
= 1;
498 pmpg1wav
->wfx
.wBitsPerSample
= 0;
499 pmpg1wav
->wfx
.cbSize
= sizeof(MPEG1WAVEFORMAT
) - sizeof(WAVEFORMATEX
);
500 if ( pmpg1wav
->fwHeadLayer
!= ACM_MPEG_LAYER3
)
502 pmt
->bFixedSizeSamples
= 1;
503 pmt
->lSampleSize
= pmpg1wav
->wfx
.nBlockAlign
;
505 dwPayloadBlockSize
= (pmpg1wav
->wfx
.nAvgBytesPerSec
+ pmpg1wav
->wfx
.nBlockAlign
- 1) / pmpg1wav
->wfx
.nBlockAlign
;
506 if ( dwPayloadBlockSize
> This
->dwPayloadBlockSizeMax
)
507 This
->dwPayloadBlockSizeMax
= dwPayloadBlockSize
;
508 TRACE("payload block size = %lu\n",dwPayloadBlockSize
);
513 FIXME("mpeg - unknown stream type %02x\n",This
->pPayloads
[nStreamIndex
].payloadtype
);
521 static HRESULT
CMPGParseImpl_CheckStreamType( CParserImpl
* pImpl
, ULONG nStreamIndex
, const AM_MEDIA_TYPE
* pmt
)
523 CMPGParseImpl
* This
= (CMPGParseImpl
*)pImpl
->m_pUserData
;
526 MPEG1VIDEOINFO
* pmpg1vi
;
527 MPEG1VIDEOINFO
* pmpg1viCheck
;
528 MPEG2VIDEOINFO
* pmpg2vi
;
529 MPEG2VIDEOINFO
* pmpg2viCheck
;
531 WAVEFORMATEX
* pwfxCheck
;
532 enum MPGPayloadType payloadtype
;
534 TRACE("(%p,%lu,%p)\n",This
,nStreamIndex
,pmt
);
538 if ( nStreamIndex
>= This
->cPayloads
)
541 hr
= CMPGParseImpl_GetStreamType( pImpl
, nStreamIndex
, &mt
);
544 if ( !IsEqualGUID( &pmt
->majortype
, &mt
.majortype
) ||
545 !IsEqualGUID( &pmt
->subtype
, &mt
.subtype
) ||
546 !IsEqualGUID( &pmt
->formattype
, &mt
.formattype
) )
552 TRACE("check format\n");
555 payloadtype
= This
->pPayloads
[nStreamIndex
].payloadtype
;
556 switch ( payloadtype
)
558 case MPGPayload_Video
:
559 if ( IsEqualGUID( &mt
.formattype
, &FORMAT_MPEGVideo
) )
562 if ( pmt
->cbFormat
!= mt
.cbFormat
||
563 pmt
->pbFormat
== NULL
)
568 pmpg1vi
= (MPEG1VIDEOINFO
*)mt
.pbFormat
;
569 pmpg1viCheck
= (MPEG1VIDEOINFO
*)pmt
->pbFormat
;
570 if ( memcmp( pmpg1vi
, pmpg1viCheck
, sizeof(MPEG1VIDEOINFO
) ) != 0 )
577 if ( IsEqualGUID( &mt
.formattype
, &FORMAT_MPEG2_VIDEO
) )
580 if ( pmt
->cbFormat
!= mt
.cbFormat
||
581 pmt
->pbFormat
== NULL
)
586 pmpg2vi
= (MPEG2VIDEOINFO
*)mt
.pbFormat
;
587 pmpg2viCheck
= (MPEG2VIDEOINFO
*)pmt
->pbFormat
;
588 if ( memcmp( pmpg2vi
, pmpg2viCheck
, sizeof(MPEG2VIDEOINFO
) ) != 0 )
600 case MPGPayload_Audio
:
601 if ( IsEqualGUID( &mt
.formattype
, &FORMAT_WaveFormatEx
) )
603 if ( mt
.cbFormat
!= pmt
->cbFormat
||
604 pmt
->pbFormat
== NULL
)
609 pwfx
= (WAVEFORMATEX
*)mt
.pbFormat
;
610 pwfxCheck
= (WAVEFORMATEX
*)pmt
->pbFormat
;
612 if ( memcmp( pwfx
, pwfxCheck
, sizeof(WAVEFORMATEX
) ) != 0 )
626 FIXME( "unsupported payload type\n" );
633 QUARTZ_MediaType_Free( &mt
);
640 static HRESULT
CMPGParseImpl_GetAllocProp( CParserImpl
* pImpl
, ALLOCATOR_PROPERTIES
* pReqProp
)
642 CMPGParseImpl
* This
= (CMPGParseImpl
*)pImpl
->m_pUserData
;
644 TRACE("(%p,%p)\n",This
,pReqProp
);
649 ZeroMemory( pReqProp
, sizeof(ALLOCATOR_PROPERTIES
) );
650 pReqProp
->cBuffers
= This
->cPayloads
;
651 pReqProp
->cbBuffer
= This
->dwPayloadBlockSizeMax
;
653 TRACE("buf %d size %d\n",
654 (int)This
->cPayloads
,
655 (int)This
->dwPayloadBlockSizeMax
);
660 static HRESULT
CMPGParseImpl_GetNextRequest( CParserImpl
* pImpl
, ULONG
* pnStreamIndex
, LONGLONG
* pllStart
, LONG
* plLength
, REFERENCE_TIME
* prtStart
, REFERENCE_TIME
* prtStop
, DWORD
* pdwSampleFlags
)
662 CMPGParseImpl
* This
= (CMPGParseImpl
*)pImpl
->m_pUserData
;
666 *pdwSampleFlags
= AM_SAMPLE_SPLICEPOINT
;
668 TRACE("(%p)\n",This
);
670 if ( This
->bRawPayload
)
672 if ( This
->dwPayloadBlockSizeMax
== 0 ||
673 This
->cPayloads
!= 1 || This
->pPayloads
== NULL
)
676 *pllStart
= This
->llPosNext
;
677 *plLength
= This
->dwPayloadBlockSizeMax
;
680 if ( This
->pPayloads
[0].bDataDiscontinuity
)
682 *pdwSampleFlags
|= AM_SAMPLE_DATADISCONTINUITY
;
683 This
->pPayloads
[0].bDataDiscontinuity
= FALSE
;
695 static HRESULT
CMPGParseImpl_ProcessSample( CParserImpl
* pImpl
, ULONG nStreamIndex
, LONGLONG llStart
, LONG lLength
, IMediaSample
* pSample
)
697 CMPGParseImpl
* This
= (CMPGParseImpl
*)pImpl
->m_pUserData
;
700 TRACE("(%p,%lu,%ld,%ld,%p)\n",This
,nStreamIndex
,(long)llStart
,lLength
,pSample
);
705 if ( This
->bRawPayload
)
707 hr
= IMediaSample_SetTime(pSample
,NULL
,NULL
);
716 static const struct ParserHandlers CMPGParseImpl_Handlers
=
718 CMPGParseImpl_InitParser
,
719 CMPGParseImpl_UninitParser
,
720 CMPGParseImpl_GetOutPinName
,
721 CMPGParseImpl_GetStreamType
,
722 CMPGParseImpl_CheckStreamType
,
723 CMPGParseImpl_GetAllocProp
,
724 CMPGParseImpl_GetNextRequest
,
725 CMPGParseImpl_ProcessSample
,
727 /* for IQualityControl */
728 NULL
, /* pQualityNotify */
731 NULL
, /* pGetSeekingCaps */
732 NULL
, /* pIsTimeFormatSupported */
733 NULL
, /* pGetCurPos */
734 NULL
, /* pSetCurPos */
735 NULL
, /* pGetDuration */
736 NULL
, /* pGetStopPos */
737 NULL
, /* pSetStopPos */
738 NULL
, /* pGetPreroll */
741 HRESULT
QUARTZ_CreateMPEG1Splitter(IUnknown
* punkOuter
,void** ppobj
)
743 return QUARTZ_CreateParser(
745 &CLSID_MPEG1Splitter
,
746 QUARTZ_MPEG1Parser_Name
,
747 QUARTZ_MPGParserInPin_Name
,
748 &CMPGParseImpl_Handlers
);