Implemented MJPG handler.
[wine/multimedia.git] / dlls / quartz / mpgparse.c
blob98f1e4e96390bcd4e707c683e8b0f0b535c1cb55
1 /*
2 * Implements MPEG-1 / MPEG-2 Parser(Splitter).
4 * FIXME - no splitter implementation.
5 * FIXME - no packet support (implemented payload only)
6 * FIXME - no seeking
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
25 #include "config.h"
27 #include "windef.h"
28 #include "winbase.h"
29 #include "wingdi.h"
30 #include "winuser.h"
31 #include "mmsystem.h"
32 #include "vfw.h"
33 #include "winerror.h"
34 #include "strmif.h"
35 #include "control.h"
36 #include "vfwmsgs.h"
37 #include "amvideo.h"
38 #include "mmreg.h"
39 #include "uuids.h"
40 #include "dvdmedia.h"
42 #include "wine/debug.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
45 #include "quartz_private.h"
46 #include "parser.h"
47 #include "mtype.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[] =
54 { 'I','n',0 };
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 };
59 /* FIXME */
60 static const WCHAR QUARTZ_MPGParserOutPin_UnknownTypePinName[] =
61 { 'O','u','t',0 };
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 /****************************************************************************
75 * CMPGParseImpl
79 typedef struct CMPGParseImpl CMPGParseImpl;
80 typedef struct CMPGParsePayload CMPGParsePayload;
82 enum MPGPayloadType
84 MPGPayload_Video = 0xe0,
85 MPGPayload_Audio = 0xc0,
88 struct CMPGParseImpl
90 LONGLONG llPosNext;
91 BOOL bRawPayload;
92 DWORD dwPayloadBlockSizeMax;
93 DWORD cPayloads;
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 )
111 return E_UNEXPECTED;
113 if ( This->bRawPayload )
115 if ( payloadtype != This->pPayloads[0].payloadtype )
116 return E_UNEXPECTED;
117 return IAsyncReader_SyncRead( pImpl->m_pReader, llPosStart, lLength, pbBuf );
119 else
121 FIXME( "not implemented\n" );
124 return E_NOTIMPL;
129 static HRESULT CMPGParseImpl_InitParser( CParserImpl* pImpl, ULONG* pcStreams )
131 CMPGParseImpl* This = NULL;
132 HRESULT hr;
133 DWORD n;
134 AM_MEDIA_TYPE mt;
135 BYTE hdrbuf[8];
137 TRACE("(%p,%p)\n",pImpl,pcStreams);
139 This = (CMPGParseImpl*)QUARTZ_AllocMem( sizeof(CMPGParseImpl) );
140 if ( This == NULL )
141 return E_OUTOFMEMORY;
142 pImpl->m_pUserData = This;
143 ZeroMemory( This, sizeof(CMPGParseImpl) );
145 hr = IAsyncReader_SyncRead( pImpl->m_pReader, 0, 8, hdrbuf );
146 if ( FAILED(hr) )
147 return hr;
148 if ( hr != S_OK )
149 return E_FAIL;
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" );
158 return E_FAIL;
160 else
161 if ( hdrbuf[0] == 0x00 && hdrbuf[1] == 0x00 &&
162 hdrbuf[2] == 0x01 && hdrbuf[3] == 0xb3 )
164 TRACE( "mpeg/video payload\n" );
165 This->llPosNext = 0;
166 This->bRawPayload = TRUE;
167 This->dwPayloadBlockSizeMax = 0x4000;
168 This->cPayloads = 1;
169 This->pPayloads = (CMPGParsePayload*)QUARTZ_AllocMem( sizeof(CMPGParsePayload) );
170 if ( This->pPayloads == NULL )
171 return E_OUTOFMEMORY;
172 *pcStreams = 1;
173 This->pPayloads[0].payloadtype = MPGPayload_Video;
174 This->pPayloads[0].bDataDiscontinuity = TRUE;
176 else
177 if ( hdrbuf[0] == 0xff && (hdrbuf[1]&0xf0) == 0xf0 )
179 TRACE( "mpeg/audio payload\n" );
180 This->llPosNext = 0;
181 This->bRawPayload = TRUE;
182 This->dwPayloadBlockSizeMax = 0;
183 This->cPayloads = 1;
184 This->pPayloads = (CMPGParsePayload*)QUARTZ_AllocMem( sizeof(CMPGParsePayload) );
185 if ( This->pPayloads == NULL )
186 return E_OUTOFMEMORY;
187 *pcStreams = 1;
188 This->pPayloads[0].payloadtype = MPGPayload_Audio;
189 This->pPayloads[0].bDataDiscontinuity = TRUE;
191 else
193 return E_FAIL;
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);
204 return S_OK;
207 static HRESULT CMPGParseImpl_UninitParser( CParserImpl* pImpl )
209 CMPGParseImpl* This = (CMPGParseImpl*)pImpl->m_pUserData;
210 ULONG nIndex;
212 TRACE("(%p)\n",This);
214 if ( This == NULL )
215 return NOERROR;
217 /* destruct */
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;
234 return NOERROR;
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 )
244 return NULL;
246 switch ( This->pPayloads[nStreamIndex].payloadtype )
248 case MPGPayload_Video:
249 return QUARTZ_MPGParserOutPin_VideoPinName;
250 case MPGPayload_Audio:
251 return QUARTZ_MPGParserOutPin_AudioPinName;
252 default:
253 FIXME("mpeg - unknown stream type %02x\n",This->pPayloads[nStreamIndex].payloadtype);
256 /* FIXME */
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;
263 HRESULT hr;
264 BYTE hdrbuf[140+10];
265 UINT seqhdrlen;
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);
274 if ( This == NULL )
275 return E_UNEXPECTED;
276 if ( nStreamIndex >= This->cPayloads )
277 return E_INVALIDARG;
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 );
287 if ( FAILED(hr) )
288 return hr;
289 if ( hr != S_OK )
290 return E_FAIL;
292 memcpy( &pmt->majortype, &MEDIATYPE_Video, sizeof(GUID) );
293 seqhdrlen = 12;
294 if ( hdrbuf[seqhdrlen-1] & 0x2 )
295 seqhdrlen += 64;
296 if ( hdrbuf[seqhdrlen-1] & 0x1 )
297 seqhdrlen += 64;
298 if ( hdrbuf[seqhdrlen ] == 0x00 && hdrbuf[seqhdrlen+1] == 0x00 &&
299 hdrbuf[seqhdrlen+2] == 0x01 && hdrbuf[seqhdrlen+3] == 0xb5 )
301 /* video MPEG-2 */
302 FIXME("video MPEG-2\n");
303 if ( (hdrbuf[seqhdrlen+4]&0xf0) != 0x1 )
304 return E_FAIL;
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 );
345 return S_OK;
347 else
349 /* MPEG-1 */
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 );
370 return S_OK;
371 case MPGPayload_Audio:
372 hr = CMPGParseImpl_SyncReadPayload(
373 pImpl, This, payloadtype, 0, 4, hdrbuf );
374 if ( FAILED(hr) )
375 return hr;
376 if ( hr != S_OK )
377 return E_FAIL;
379 memcpy( &pmt->majortype, &MEDIATYPE_Audio, sizeof(GUID) );
380 memcpy( &pmt->formattype, &FORMAT_WaveFormatEx, sizeof(GUID) );
382 if ( !( hdrbuf[1] & 0x8 ) )
384 /* FIXME!!! */
385 FIXME("audio not MPEG-1\n");
386 return E_FAIL;
388 else
390 /* MPEG-1 */
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 )
403 case 0x6:
404 TRACE("layer 1\n");
405 pmpg1wav->fwHeadLayer = ACM_MPEG_LAYER1;
406 break;
407 case 0x4:
408 TRACE("layer 2\n");
409 pmpg1wav->fwHeadLayer = ACM_MPEG_LAYER2;
410 break;
411 case 0x2:
412 TRACE("layer 3\n");
413 pmpg1wav->fwHeadLayer = ACM_MPEG_LAYER3;
414 break;
415 default: return E_FAIL;
418 switch ( pmpg1wav->fwHeadLayer )
420 case ACM_MPEG_LAYER1:
421 pmpg1wav->dwHeadBitrate = bitratesl1[hdrbuf[2]>>4]*1000;
422 break;
423 case ACM_MPEG_LAYER2:
424 pmpg1wav->dwHeadBitrate = bitratesl2[hdrbuf[2]>>4]*1000;
425 break;
426 case ACM_MPEG_LAYER3:
427 pmpg1wav->dwHeadBitrate = bitratesl3[hdrbuf[2]>>4]*1000;
428 break;
430 if ( pmpg1wav->dwHeadBitrate == 0 )
431 return E_FAIL;
433 switch ( hdrbuf[3] & 0xc0 )
435 case 0x00:
436 TRACE("STEREO\n");
437 pmpg1wav->fwHeadMode = ACM_MPEG_STEREO;
438 break;
439 case 0x40:
440 TRACE("JOINTSTEREO\n");
441 pmpg1wav->fwHeadMode = ACM_MPEG_JOINTSTEREO;
442 break;
443 case 0x80:
444 TRACE("DUALCHANNEL\n");
445 pmpg1wav->fwHeadMode = ACM_MPEG_DUALCHANNEL;
446 break;
447 case 0xc0:
448 TRACE("SINGLECHANNEL\n");
449 pmpg1wav->fwHeadMode = ACM_MPEG_SINGLECHANNEL;
450 break;
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 )
471 case 0x00:
472 TRACE("44100Hz\n");
473 pmpg1wav->wfx.nSamplesPerSec = 44100;
474 break;
475 case 0x01:
476 TRACE("48000Hz\n");
477 pmpg1wav->wfx.nSamplesPerSec = 48000;
478 break;
479 case 0x02:
480 TRACE("32000Hz\n");
481 pmpg1wav->wfx.nSamplesPerSec = 32000;
482 break;
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;
490 break;
491 case ACM_MPEG_LAYER2:
492 pmpg1wav->wfx.nBlockAlign = (1152>>3) * pmpg1wav->dwHeadBitrate / pmpg1wav->wfx.nSamplesPerSec;
493 break;
494 case ACM_MPEG_LAYER3:
495 pmpg1wav->wfx.nBlockAlign = 1;
496 break;
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);
511 return S_OK;
512 default:
513 FIXME("mpeg - unknown stream type %02x\n",This->pPayloads[nStreamIndex].payloadtype);
514 break;
517 FIXME("stub\n");
518 return E_NOTIMPL;
521 static HRESULT CMPGParseImpl_CheckStreamType( CParserImpl* pImpl, ULONG nStreamIndex, const AM_MEDIA_TYPE* pmt )
523 CMPGParseImpl* This = (CMPGParseImpl*)pImpl->m_pUserData;
524 HRESULT hr;
525 AM_MEDIA_TYPE mt;
526 MPEG1VIDEOINFO* pmpg1vi;
527 MPEG1VIDEOINFO* pmpg1viCheck;
528 MPEG2VIDEOINFO* pmpg2vi;
529 MPEG2VIDEOINFO* pmpg2viCheck;
530 WAVEFORMATEX* pwfx;
531 WAVEFORMATEX* pwfxCheck;
532 enum MPGPayloadType payloadtype;
534 TRACE("(%p,%lu,%p)\n",This,nStreamIndex,pmt);
536 if ( This == NULL )
537 return E_UNEXPECTED;
538 if ( nStreamIndex >= This->cPayloads )
539 return E_INVALIDARG;
541 hr = CMPGParseImpl_GetStreamType( pImpl, nStreamIndex, &mt );
542 if ( FAILED(hr) )
543 return hr;
544 if ( !IsEqualGUID( &pmt->majortype, &mt.majortype ) ||
545 !IsEqualGUID( &pmt->subtype, &mt.subtype ) ||
546 !IsEqualGUID( &pmt->formattype, &mt.formattype ) )
548 hr = E_FAIL;
549 goto end;
552 TRACE("check format\n");
553 hr = S_OK;
555 payloadtype = This->pPayloads[nStreamIndex].payloadtype;
556 switch ( payloadtype )
558 case MPGPayload_Video:
559 if ( IsEqualGUID( &mt.formattype, &FORMAT_MPEGVideo ) )
561 /* MPEG-1 Video */
562 if ( pmt->cbFormat != mt.cbFormat ||
563 pmt->pbFormat == NULL )
565 hr = E_FAIL;
566 goto end;
568 pmpg1vi = (MPEG1VIDEOINFO*)mt.pbFormat;
569 pmpg1viCheck = (MPEG1VIDEOINFO*)pmt->pbFormat;
570 if ( memcmp( pmpg1vi, pmpg1viCheck, sizeof(MPEG1VIDEOINFO) ) != 0 )
572 hr = E_FAIL;
573 goto end;
576 else
577 if ( IsEqualGUID( &mt.formattype, &FORMAT_MPEG2_VIDEO ) )
579 /* MPEG-2 Video */
580 if ( pmt->cbFormat != mt.cbFormat ||
581 pmt->pbFormat == NULL )
583 hr = E_FAIL;
584 goto end;
586 pmpg2vi = (MPEG2VIDEOINFO*)mt.pbFormat;
587 pmpg2viCheck = (MPEG2VIDEOINFO*)pmt->pbFormat;
588 if ( memcmp( pmpg2vi, pmpg2viCheck, sizeof(MPEG2VIDEOINFO) ) != 0 )
590 hr = E_FAIL;
591 goto end;
594 else
596 hr = E_FAIL;
597 goto end;
599 break;
600 case MPGPayload_Audio:
601 if ( IsEqualGUID( &mt.formattype, &FORMAT_WaveFormatEx ) )
603 if ( mt.cbFormat != pmt->cbFormat ||
604 pmt->pbFormat == NULL )
606 hr = E_FAIL;
607 goto end;
609 pwfx = (WAVEFORMATEX*)mt.pbFormat;
610 pwfxCheck = (WAVEFORMATEX*)pmt->pbFormat;
612 if ( memcmp( pwfx, pwfxCheck, sizeof(WAVEFORMATEX) ) != 0 )
614 hr = E_FAIL;
615 goto end;
618 else
620 hr = E_FAIL;
621 goto end;
624 break;
625 default:
626 FIXME( "unsupported payload type\n" );
627 hr = E_FAIL;
628 goto end;
631 hr = S_OK;
632 end:
633 QUARTZ_MediaType_Free( &mt );
635 TRACE("%08lx\n",hr);
637 return hr;
640 static HRESULT CMPGParseImpl_GetAllocProp( CParserImpl* pImpl, ALLOCATOR_PROPERTIES* pReqProp )
642 CMPGParseImpl* This = (CMPGParseImpl*)pImpl->m_pUserData;
644 TRACE("(%p,%p)\n",This,pReqProp);
646 if ( This == NULL )
647 return E_UNEXPECTED;
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);
657 return S_OK;
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;
664 if ( This == NULL )
665 return E_UNEXPECTED;
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 )
674 return E_UNEXPECTED;
675 *pnStreamIndex = 0;
676 *pllStart = This->llPosNext;
677 *plLength = This->dwPayloadBlockSizeMax;
678 *prtStart = 0;
679 *prtStop = 0;
680 if ( This->pPayloads[0].bDataDiscontinuity )
682 *pdwSampleFlags |= AM_SAMPLE_DATADISCONTINUITY;
683 This->pPayloads[0].bDataDiscontinuity = FALSE;
686 else
688 FIXME("stub\n");
689 return E_NOTIMPL;
692 return S_OK;
695 static HRESULT CMPGParseImpl_ProcessSample( CParserImpl* pImpl, ULONG nStreamIndex, LONGLONG llStart, LONG lLength, IMediaSample* pSample )
697 CMPGParseImpl* This = (CMPGParseImpl*)pImpl->m_pUserData;
698 HRESULT hr;
700 TRACE("(%p,%lu,%ld,%ld,%p)\n",This,nStreamIndex,(long)llStart,lLength,pSample);
702 if ( This == NULL )
703 return E_UNEXPECTED;
705 if ( This->bRawPayload )
707 hr = IMediaSample_SetTime(pSample,NULL,NULL);
708 if ( FAILED(hr) )
709 return hr;
712 return NOERROR;
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 */
730 /* for seeking */
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(
744 punkOuter,ppobj,
745 &CLSID_MPEG1Splitter,
746 QUARTZ_MPEG1Parser_Name,
747 QUARTZ_MPGParserInPin_Name,
748 &CMPGParseImpl_Handlers );