2 * Implements IEnumMediaTypes and helper functions. (internal)
4 * hidenori@a2.ctktv.ne.jp
19 #include "debugtools.h"
20 DEFAULT_DEBUG_CHANNEL(quartz);
22 #include "quartz_private.h"
27 /****************************************************************************/
31 HRESULT QUARTZ_MediaType_Copy(
32 AM_MEDIA_TYPE* pmtDst,
33 const AM_MEDIA_TYPE* pmtSrc )
35 memcpy( &pmtDst->majortype, &pmtSrc->majortype, sizeof(GUID) );
36 memcpy( &pmtDst->subtype, &pmtSrc->subtype, sizeof(GUID) );
37 pmtDst->bFixedSizeSamples = pmtSrc->bFixedSizeSamples;
38 pmtDst->bTemporalCompression = pmtSrc->bTemporalCompression;
39 pmtDst->lSampleSize = pmtSrc->lSampleSize;
40 memcpy( &pmtDst->formattype, &pmtSrc->formattype, sizeof(GUID) );
42 pmtDst->cbFormat = pmtSrc->cbFormat;
43 pmtDst->pbFormat = NULL;
45 if ( pmtSrc->pbFormat != NULL && pmtSrc->cbFormat != 0 )
47 pmtDst->pbFormat = (BYTE*)CoTaskMemAlloc( pmtSrc->cbFormat );
48 if ( pmtDst->pbFormat == NULL )
50 CoTaskMemFree( pmtDst );
53 memcpy( pmtDst->pbFormat, pmtSrc->pbFormat, pmtSrc->cbFormat );
56 if ( pmtSrc->pUnk != NULL )
58 pmtDst->pUnk = pmtSrc->pUnk;
59 IUnknown_AddRef( pmtSrc->pUnk );
65 void QUARTZ_MediaType_Free(
68 if ( pmt->pUnk != NULL )
70 IUnknown_Release( pmt->pUnk );
73 if ( pmt->pbFormat != NULL )
75 CoTaskMemFree( pmt->pbFormat );
81 AM_MEDIA_TYPE* QUARTZ_MediaType_Duplicate(
82 const AM_MEDIA_TYPE* pmtSrc )
84 AM_MEDIA_TYPE* pmtDup;
86 pmtDup = (AM_MEDIA_TYPE*)CoTaskMemAlloc( sizeof(AM_MEDIA_TYPE) );
89 if ( QUARTZ_MediaType_Copy( pmtDup, pmtSrc ) != S_OK )
91 CoTaskMemFree( pmtDup );
98 void QUARTZ_MediaType_Destroy(
101 QUARTZ_MediaType_Free( pmt );
102 CoTaskMemFree( pmt );
105 void QUARTZ_MediaSubType_FromFourCC(
106 GUID* psubtype, DWORD dwFourCC )
108 TRACE( "FourCC %c%c%c%c\n",
109 (int)(dwFourCC>> 0)&0xff,
110 (int)(dwFourCC>> 8)&0xff,
111 (int)(dwFourCC>>16)&0xff,
112 (int)(dwFourCC>>24)&0xff );
113 memcpy( psubtype, &MEDIASUBTYPE_PCM, sizeof(GUID) );
114 psubtype->Data1 = dwFourCC;
117 BOOL QUARTZ_MediaSubType_IsFourCC(
118 const GUID* psubtype )
122 QUARTZ_MediaSubType_FromFourCC(
123 &guidTemp, psubtype->Data1 );
124 return IsEqualGUID( psubtype, &guidTemp );
127 HRESULT QUARTZ_MediaSubType_FromBitmap(
128 GUID* psubtype, const BITMAPINFOHEADER* pbi )
133 if ( (pbi->biCompression & 0xffff0000) != 0 )
136 if ( pbi->biWidth <= 0 || pbi->biHeight == 0 )
140 switch ( pbi->biCompression )
143 if ( pbi->biPlanes != 1 )
145 switch ( pbi->biBitCount )
148 memcpy( psubtype, &MEDIASUBTYPE_RGB1, sizeof(GUID) );
152 memcpy( psubtype, &MEDIASUBTYPE_RGB4, sizeof(GUID) );
156 memcpy( psubtype, &MEDIASUBTYPE_RGB8, sizeof(GUID) );
160 memcpy( psubtype, &MEDIASUBTYPE_RGB555, sizeof(GUID) );
164 memcpy( psubtype, &MEDIASUBTYPE_RGB24, sizeof(GUID) );
168 memcpy( psubtype, &MEDIASUBTYPE_RGB32, sizeof(GUID) );
174 if ( pbi->biPlanes == 1 && pbi->biHeight > 0 &&
175 pbi->biBitCount == 8 )
177 QUARTZ_MediaSubType_FromFourCC( psubtype, mmioFOURCC('M','R','L','E') );
182 if ( pbi->biPlanes == 1 && pbi->biHeight > 0 &&
183 pbi->biBitCount == 4 )
185 QUARTZ_MediaSubType_FromFourCC( psubtype, mmioFOURCC('M','R','L','E') );
190 if ( pbi->biPlanes != 1 )
192 pdwBitf = (DWORD*)( (BYTE*)pbi + sizeof(BITMAPINFOHEADER) );
193 switch ( pbi->biBitCount )
196 if ( pdwBitf[0] == 0x7c00 &&
197 pdwBitf[1] == 0x03e0 &&
198 pdwBitf[2] == 0x001f )
200 memcpy( psubtype, &MEDIASUBTYPE_RGB555, sizeof(GUID) );
203 if ( pdwBitf[0] == 0xf800 &&
204 pdwBitf[1] == 0x07e0 &&
205 pdwBitf[2] == 0x001f )
207 memcpy( psubtype, &MEDIASUBTYPE_RGB565, sizeof(GUID) );
212 if ( pdwBitf[0] == 0x00ff0000 &&
213 pdwBitf[1] == 0x0000ff00 &&
214 pdwBitf[2] == 0x000000ff )
216 memcpy( psubtype, &MEDIASUBTYPE_RGB32, sizeof(GUID) );
227 void QUARTZ_PatchBitmapInfoHeader( BITMAPINFOHEADER* pbi )
229 switch ( pbi->biCompression )
231 case mmioFOURCC('R','G','B',' '):
232 pbi->biCompression = 0;
234 case mmioFOURCC('R','L','E',' '):
235 case mmioFOURCC('M','R','L','E'):
236 case mmioFOURCC('R','L','E','8'):
237 case mmioFOURCC('R','L','E','4'):
238 if ( pbi->biBitCount == 4 )
239 pbi->biCompression = 2;
241 pbi->biCompression = 1;
246 BOOL QUARTZ_BitmapHasFixedSample( const BITMAPINFOHEADER* pbi )
248 switch ( pbi->biCompression )
252 case mmioFOURCC('I','4','2','0'):
253 case mmioFOURCC('I','Y','U','V'):
254 case mmioFOURCC('Y','U','Y','V'):
255 case mmioFOURCC('Y','V','U','9'):
256 case mmioFOURCC('Y','4','1','1'):
257 case mmioFOURCC('Y','4','1','P'):
258 case mmioFOURCC('Y','U','Y','2'):
259 case mmioFOURCC('Y','V','Y','U'):
260 case mmioFOURCC('U','Y','V','Y'):
261 case mmioFOURCC('Y','2','1','1'):
262 case mmioFOURCC('Y','V','1','2'):
270 /****************************************************************************/
272 typedef struct IEnumMediaTypesImpl
274 ICOM_VFIELD(IEnumMediaTypes);
275 } IEnumMediaTypesImpl;
280 IEnumMediaTypesImpl enummtype;
281 struct QUARTZ_IFEntry IFEntries[1];
283 AM_MEDIA_TYPE* pTypes;
288 #define CEnumMediaTypes_THIS(iface,member) CEnumMediaTypes* This = ((CEnumMediaTypes*)(((char*)iface)-offsetof(CEnumMediaTypes,member)))
292 static HRESULT WINAPI
293 IEnumMediaTypes_fnQueryInterface(IEnumMediaTypes* iface,REFIID riid,void** ppobj)
295 CEnumMediaTypes_THIS(iface,enummtype);
297 TRACE("(%p)->()\n",This);
299 return IUnknown_QueryInterface(This->unk.punkControl,riid,ppobj);
303 IEnumMediaTypes_fnAddRef(IEnumMediaTypes* iface)
305 CEnumMediaTypes_THIS(iface,enummtype);
307 TRACE("(%p)->()\n",This);
309 return IUnknown_AddRef(This->unk.punkControl);
313 IEnumMediaTypes_fnRelease(IEnumMediaTypes* iface)
315 CEnumMediaTypes_THIS(iface,enummtype);
317 TRACE("(%p)->()\n",This);
319 return IUnknown_Release(This->unk.punkControl);
322 static HRESULT WINAPI
323 IEnumMediaTypes_fnNext(IEnumMediaTypes* iface,ULONG cReq,AM_MEDIA_TYPE** ppmtype,ULONG* pcFetched)
325 CEnumMediaTypes_THIS(iface,enummtype);
329 TRACE("(%p)->(%lu,%p,%p)\n",This,cReq,ppmtype,pcFetched);
331 if ( pcFetched == NULL && cReq > 1 )
333 if ( ppmtype == NULL )
336 EnterCriticalSection( &This->cs );
342 if ( This->cCur >= This->cTypes )
347 ppmtype[ cFetched ] =
348 QUARTZ_MediaType_Duplicate( &This->pTypes[ This->cCur ] );
349 if ( ppmtype[ cFetched ] == NULL )
352 while ( cFetched > 0 )
355 QUARTZ_MediaType_Destroy( ppmtype[ cFetched ] );
366 LeaveCriticalSection( &This->cs );
368 if ( pcFetched != NULL )
369 *pcFetched = cFetched;
374 static HRESULT WINAPI
375 IEnumMediaTypes_fnSkip(IEnumMediaTypes* iface,ULONG cSkip)
377 CEnumMediaTypes_THIS(iface,enummtype);
380 TRACE("(%p)->()\n",This);
382 EnterCriticalSection( &This->cs );
387 if ( This->cCur >= This->cTypes )
396 LeaveCriticalSection( &This->cs );
401 static HRESULT WINAPI
402 IEnumMediaTypes_fnReset(IEnumMediaTypes* iface)
404 CEnumMediaTypes_THIS(iface,enummtype);
406 TRACE("(%p)->()\n",This);
408 EnterCriticalSection( &This->cs );
412 LeaveCriticalSection( &This->cs );
417 static HRESULT WINAPI
418 IEnumMediaTypes_fnClone(IEnumMediaTypes* iface,IEnumMediaTypes** ppobj)
420 CEnumMediaTypes_THIS(iface,enummtype);
423 TRACE("(%p)->()\n",This);
428 EnterCriticalSection( &This->cs );
430 hr = QUARTZ_CreateEnumMediaTypes(
432 This->pTypes, This->cTypes );
434 IEnumMediaTypes_Skip( *ppobj, This->cCur );
436 LeaveCriticalSection( &This->cs );
442 static ICOM_VTABLE(IEnumMediaTypes) ienummtype =
444 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
445 /* IUnknown fields */
446 IEnumMediaTypes_fnQueryInterface,
447 IEnumMediaTypes_fnAddRef,
448 IEnumMediaTypes_fnRelease,
449 /* IEnumMediaTypes fields */
450 IEnumMediaTypes_fnNext,
451 IEnumMediaTypes_fnSkip,
452 IEnumMediaTypes_fnReset,
453 IEnumMediaTypes_fnClone,
457 /* can I use offsetof safely? - FIXME? */
458 static QUARTZ_IFEntry IFEntries[] =
460 { &IID_IEnumMediaTypes, offsetof(CEnumMediaTypes,enummtype)-offsetof(CEnumMediaTypes,unk) },
464 void QUARTZ_DestroyEnumMediaTypes(IUnknown* punk)
466 CEnumMediaTypes_THIS(punk,unk);
469 if ( This->pTypes != NULL )
471 for ( i = 0; i < This->cTypes; i++ )
472 QUARTZ_MediaType_Free( &This->pTypes[i] );
473 QUARTZ_FreeMem( This->pTypes );
476 DeleteCriticalSection( &This->cs );
479 HRESULT QUARTZ_CreateEnumMediaTypes(
480 IEnumMediaTypes** ppobj,
481 const AM_MEDIA_TYPE* pTypes, ULONG cTypes )
483 CEnumMediaTypes* penum;
484 AM_MEDIA_TYPE* pTypesDup = NULL;
488 TRACE("(%p,%p,%lu)\n",ppobj,pTypes,cTypes);
492 pTypesDup = (AM_MEDIA_TYPE*)QUARTZ_AllocMem(
493 sizeof( AM_MEDIA_TYPE ) * cTypes );
494 if ( pTypesDup == NULL )
495 return E_OUTOFMEMORY;
500 hr = QUARTZ_MediaType_Copy( &pTypesDup[i], &pTypes[i] );
506 QUARTZ_MediaType_Free( &pTypesDup[i] );
508 QUARTZ_FreeMem( pTypesDup );
516 penum = (CEnumMediaTypes*)QUARTZ_AllocObj( sizeof(CEnumMediaTypes) );
519 return E_OUTOFMEMORY;
521 penum->pTypes = pTypesDup;
522 penum->cTypes = cTypes;
525 QUARTZ_IUnkInit( &penum->unk, NULL );
526 ICOM_VTBL(&penum->enummtype) = &ienummtype;
528 penum->unk.pEntries = IFEntries;
529 penum->unk.dwEntries = sizeof(IFEntries)/sizeof(IFEntries[0]);
530 penum->unk.pOnFinalRelease = QUARTZ_DestroyEnumMediaTypes;
532 InitializeCriticalSection( &penum->cs );
534 *ppobj = (IEnumMediaTypes*)(&penum->enummtype);