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 memcpy( psubtype, &MEDIASUBTYPE_PCM, sizeof(GUID) );
109 psubtype->Data1 = dwFourCC;
112 BOOL QUARTZ_MediaSubType_IsFourCC(
113 const GUID* psubtype )
117 QUARTZ_MediaSubType_FromFourCC(
118 &guidTemp, psubtype->Data1 );
119 return IsEqualGUID( psubtype, &guidTemp );
122 HRESULT QUARTZ_MediaSubType_FromBitmap(
123 GUID* psubtype, const BITMAPINFOHEADER* pbi )
128 if ( (pbi->biCompression & 0xffff) != 0 )
131 if ( pbi->biWidth <= 0 || pbi->biHeight == 0 )
135 switch ( pbi->biCompression )
138 if ( pbi->biPlanes != 1 )
140 switch ( pbi->biBitCount )
143 memcpy( psubtype, &MEDIASUBTYPE_RGB1, sizeof(GUID) );
147 memcpy( psubtype, &MEDIASUBTYPE_RGB4, sizeof(GUID) );
151 memcpy( psubtype, &MEDIASUBTYPE_RGB8, sizeof(GUID) );
155 memcpy( psubtype, &MEDIASUBTYPE_RGB555, sizeof(GUID) );
159 memcpy( psubtype, &MEDIASUBTYPE_RGB24, sizeof(GUID) );
163 memcpy( psubtype, &MEDIASUBTYPE_RGB32, sizeof(GUID) );
169 if ( pbi->biPlanes == 1 && pbi->biHeight > 0 &&
170 pbi->biBitCount == 8 )
172 QUARTZ_MediaSubType_FromFourCC( psubtype, mmioFOURCC('M','R','L','E') );
177 if ( pbi->biPlanes == 1 && pbi->biHeight > 0 &&
178 pbi->biBitCount == 4 )
180 QUARTZ_MediaSubType_FromFourCC( psubtype, mmioFOURCC('M','R','L','E') );
185 if ( pbi->biPlanes != 1 )
187 pdwBitf = (DWORD*)( (BYTE*)pbi + sizeof(BITMAPINFOHEADER) );
188 switch ( pbi->biBitCount )
191 if ( pdwBitf[0] == 0x7c00 &&
192 pdwBitf[1] == 0x03e0 &&
193 pdwBitf[2] == 0x001f )
195 memcpy( psubtype, &MEDIASUBTYPE_RGB555, sizeof(GUID) );
198 if ( pdwBitf[0] == 0xf800 &&
199 pdwBitf[1] == 0x07e0 &&
200 pdwBitf[2] == 0x001f )
202 memcpy( psubtype, &MEDIASUBTYPE_RGB565, sizeof(GUID) );
207 if ( pdwBitf[0] == 0x00ff0000 &&
208 pdwBitf[1] == 0x0000ff00 &&
209 pdwBitf[2] == 0x000000ff )
211 memcpy( psubtype, &MEDIASUBTYPE_RGB32, sizeof(GUID) );
222 BOOL QUARTZ_BitmapHasFixedSample( const BITMAPINFOHEADER* pbi )
224 switch ( pbi->biCompression )
228 case mmioFOURCC('I','4','2','0'):
229 case mmioFOURCC('I','Y','U','V'):
230 case mmioFOURCC('Y','U','Y','V'):
231 case mmioFOURCC('Y','V','U','9'):
232 case mmioFOURCC('Y','4','1','1'):
233 case mmioFOURCC('Y','4','1','P'):
234 case mmioFOURCC('Y','U','Y','2'):
235 case mmioFOURCC('Y','V','Y','U'):
236 case mmioFOURCC('U','Y','V','Y'):
237 case mmioFOURCC('Y','2','1','1'):
238 case mmioFOURCC('Y','V','1','2'):
246 /****************************************************************************/
248 typedef struct IEnumMediaTypesImpl
250 ICOM_VFIELD(IEnumMediaTypes);
251 } IEnumMediaTypesImpl;
256 IEnumMediaTypesImpl enummtype;
257 struct QUARTZ_IFEntry IFEntries[1];
259 AM_MEDIA_TYPE* pTypes;
264 #define CEnumMediaTypes_THIS(iface,member) CEnumMediaTypes* This = ((CEnumMediaTypes*)(((char*)iface)-offsetof(CEnumMediaTypes,member)))
268 static HRESULT WINAPI
269 IEnumMediaTypes_fnQueryInterface(IEnumMediaTypes* iface,REFIID riid,void** ppobj)
271 CEnumMediaTypes_THIS(iface,enummtype);
273 TRACE("(%p)->()\n",This);
275 return IUnknown_QueryInterface(This->unk.punkControl,riid,ppobj);
279 IEnumMediaTypes_fnAddRef(IEnumMediaTypes* iface)
281 CEnumMediaTypes_THIS(iface,enummtype);
283 TRACE("(%p)->()\n",This);
285 return IUnknown_AddRef(This->unk.punkControl);
289 IEnumMediaTypes_fnRelease(IEnumMediaTypes* iface)
291 CEnumMediaTypes_THIS(iface,enummtype);
293 TRACE("(%p)->()\n",This);
295 return IUnknown_Release(This->unk.punkControl);
298 static HRESULT WINAPI
299 IEnumMediaTypes_fnNext(IEnumMediaTypes* iface,ULONG cReq,AM_MEDIA_TYPE** ppmtype,ULONG* pcFetched)
301 CEnumMediaTypes_THIS(iface,enummtype);
305 TRACE("(%p)->(%lu,%p,%p)\n",This,cReq,ppmtype,pcFetched);
307 if ( pcFetched == NULL && cReq > 1 )
309 if ( ppmtype == NULL )
312 EnterCriticalSection( &This->cs );
318 if ( This->cCur >= This->cTypes )
323 ppmtype[ cFetched ] =
324 QUARTZ_MediaType_Duplicate( &This->pTypes[ This->cCur ] );
325 if ( ppmtype[ cFetched ] == NULL )
328 while ( cFetched > 0 )
331 QUARTZ_MediaType_Destroy( ppmtype[ cFetched ] );
342 LeaveCriticalSection( &This->cs );
344 if ( pcFetched != NULL )
345 *pcFetched = cFetched;
350 static HRESULT WINAPI
351 IEnumMediaTypes_fnSkip(IEnumMediaTypes* iface,ULONG cSkip)
353 CEnumMediaTypes_THIS(iface,enummtype);
356 TRACE("(%p)->()\n",This);
358 EnterCriticalSection( &This->cs );
363 if ( This->cCur >= This->cTypes )
372 LeaveCriticalSection( &This->cs );
377 static HRESULT WINAPI
378 IEnumMediaTypes_fnReset(IEnumMediaTypes* iface)
380 CEnumMediaTypes_THIS(iface,enummtype);
382 TRACE("(%p)->()\n",This);
384 EnterCriticalSection( &This->cs );
388 LeaveCriticalSection( &This->cs );
393 static HRESULT WINAPI
394 IEnumMediaTypes_fnClone(IEnumMediaTypes* iface,IEnumMediaTypes** ppobj)
396 CEnumMediaTypes_THIS(iface,enummtype);
399 TRACE("(%p)->()\n",This);
404 EnterCriticalSection( &This->cs );
406 hr = QUARTZ_CreateEnumMediaTypes(
408 This->pTypes, This->cTypes );
410 IEnumMediaTypes_Skip( *ppobj, This->cCur );
412 LeaveCriticalSection( &This->cs );
418 static ICOM_VTABLE(IEnumMediaTypes) ienummtype =
420 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
421 /* IUnknown fields */
422 IEnumMediaTypes_fnQueryInterface,
423 IEnumMediaTypes_fnAddRef,
424 IEnumMediaTypes_fnRelease,
425 /* IEnumMediaTypes fields */
426 IEnumMediaTypes_fnNext,
427 IEnumMediaTypes_fnSkip,
428 IEnumMediaTypes_fnReset,
429 IEnumMediaTypes_fnClone,
433 /* can I use offsetof safely? - FIXME? */
434 static QUARTZ_IFEntry IFEntries[] =
436 { &IID_IEnumMediaTypes, offsetof(CEnumMediaTypes,enummtype)-offsetof(CEnumMediaTypes,unk) },
440 void QUARTZ_DestroyEnumMediaTypes(IUnknown* punk)
442 CEnumMediaTypes_THIS(punk,unk);
445 if ( This->pTypes != NULL )
447 for ( i = 0; i < This->cTypes; i++ )
448 QUARTZ_MediaType_Free( &This->pTypes[i] );
449 QUARTZ_FreeMem( This->pTypes );
452 DeleteCriticalSection( &This->cs );
455 HRESULT QUARTZ_CreateEnumMediaTypes(
456 IEnumMediaTypes** ppobj,
457 const AM_MEDIA_TYPE* pTypes, ULONG cTypes )
459 CEnumMediaTypes* penum;
460 AM_MEDIA_TYPE* pTypesDup = NULL;
464 TRACE("(%p,%p,%lu)\n",ppobj,pTypes,cTypes);
468 pTypesDup = (AM_MEDIA_TYPE*)QUARTZ_AllocMem(
469 sizeof( AM_MEDIA_TYPE ) * cTypes );
470 if ( pTypesDup == NULL )
471 return E_OUTOFMEMORY;
476 hr = QUARTZ_MediaType_Copy( &pTypesDup[i], &pTypes[i] );
482 QUARTZ_MediaType_Free( &pTypesDup[i] );
484 QUARTZ_FreeMem( pTypesDup );
492 penum = (CEnumMediaTypes*)QUARTZ_AllocObj( sizeof(CEnumMediaTypes) );
495 return E_OUTOFMEMORY;
497 penum->pTypes = pTypesDup;
498 penum->cTypes = cTypes;
501 QUARTZ_IUnkInit( &penum->unk, NULL );
502 ICOM_VTBL(&penum->enummtype) = &ienummtype;
504 penum->unk.pEntries = IFEntries;
505 penum->unk.dwEntries = sizeof(IFEntries)/sizeof(IFEntries[0]);
506 penum->unk.pOnFinalRelease = QUARTZ_DestroyEnumMediaTypes;
508 InitializeCriticalSection( &penum->cs );
510 *ppobj = (IEnumMediaTypes*)(&penum->enummtype);