2 * Implements IEnumMediaTypes and helper functions. (internal)
4 * Copyright (C) Hidenori TAKESHIMA <hidenori@a2.ctktv.ne.jp>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
36 #include "quartz_private.h"
41 /****************************************************************************/
45 HRESULT QUARTZ_MediaType_Copy(
46 AM_MEDIA_TYPE* pmtDst,
47 const AM_MEDIA_TYPE* pmtSrc )
49 memcpy( &pmtDst->majortype, &pmtSrc->majortype, sizeof(GUID) );
50 memcpy( &pmtDst->subtype, &pmtSrc->subtype, sizeof(GUID) );
51 pmtDst->bFixedSizeSamples = pmtSrc->bFixedSizeSamples;
52 pmtDst->bTemporalCompression = pmtSrc->bTemporalCompression;
53 pmtDst->lSampleSize = pmtSrc->lSampleSize;
54 memcpy( &pmtDst->formattype, &pmtSrc->formattype, sizeof(GUID) );
56 pmtDst->cbFormat = pmtSrc->cbFormat;
57 pmtDst->pbFormat = NULL;
59 if ( pmtSrc->pbFormat != NULL && pmtSrc->cbFormat != 0 )
61 pmtDst->pbFormat = (BYTE*)CoTaskMemAlloc( pmtSrc->cbFormat );
62 if ( pmtDst->pbFormat == NULL )
64 CoTaskMemFree( pmtDst );
67 memcpy( pmtDst->pbFormat, pmtSrc->pbFormat, pmtSrc->cbFormat );
70 if ( pmtSrc->pUnk != NULL )
72 pmtDst->pUnk = pmtSrc->pUnk;
73 IUnknown_AddRef( pmtSrc->pUnk );
79 void QUARTZ_MediaType_Free(
82 if ( pmt->pUnk != NULL )
84 IUnknown_Release( pmt->pUnk );
87 if ( pmt->pbFormat != NULL )
89 CoTaskMemFree( pmt->pbFormat );
95 AM_MEDIA_TYPE* QUARTZ_MediaType_Duplicate(
96 const AM_MEDIA_TYPE* pmtSrc )
98 AM_MEDIA_TYPE* pmtDup;
100 pmtDup = (AM_MEDIA_TYPE*)CoTaskMemAlloc( sizeof(AM_MEDIA_TYPE) );
101 if ( pmtDup == NULL )
103 if ( QUARTZ_MediaType_Copy( pmtDup, pmtSrc ) != S_OK )
105 CoTaskMemFree( pmtDup );
112 void QUARTZ_MediaType_Destroy(
115 QUARTZ_MediaType_Free( pmt );
116 CoTaskMemFree( pmt );
119 void QUARTZ_MediaSubType_FromFourCC(
120 GUID* psubtype, DWORD dwFourCC )
122 TRACE( "FourCC %c%c%c%c\n",
123 (int)(dwFourCC>> 0)&0xff,
124 (int)(dwFourCC>> 8)&0xff,
125 (int)(dwFourCC>>16)&0xff,
126 (int)(dwFourCC>>24)&0xff );
127 memcpy( psubtype, &MEDIASUBTYPE_PCM, sizeof(GUID) );
128 psubtype->Data1 = dwFourCC;
131 BOOL QUARTZ_MediaSubType_IsFourCC(
132 const GUID* psubtype )
136 QUARTZ_MediaSubType_FromFourCC(
137 &guidTemp, psubtype->Data1 );
138 return IsEqualGUID( psubtype, &guidTemp );
141 HRESULT QUARTZ_MediaSubType_FromBitmap(
142 GUID* psubtype, const BITMAPINFOHEADER* pbi )
147 if ( (pbi->biCompression & 0xffff0000) != 0 )
150 if ( pbi->biWidth <= 0 || pbi->biHeight == 0 )
154 switch ( pbi->biCompression )
157 if ( pbi->biPlanes != 1 )
159 switch ( pbi->biBitCount )
162 memcpy( psubtype, &MEDIASUBTYPE_RGB1, sizeof(GUID) );
166 memcpy( psubtype, &MEDIASUBTYPE_RGB4, sizeof(GUID) );
170 memcpy( psubtype, &MEDIASUBTYPE_RGB8, sizeof(GUID) );
174 memcpy( psubtype, &MEDIASUBTYPE_RGB555, sizeof(GUID) );
178 memcpy( psubtype, &MEDIASUBTYPE_RGB24, sizeof(GUID) );
182 memcpy( psubtype, &MEDIASUBTYPE_RGB32, sizeof(GUID) );
188 if ( pbi->biPlanes == 1 && pbi->biHeight > 0 &&
189 pbi->biBitCount == 8 )
191 QUARTZ_MediaSubType_FromFourCC( psubtype, 1 );
196 if ( pbi->biPlanes == 1 && pbi->biHeight > 0 &&
197 pbi->biBitCount == 4 )
199 QUARTZ_MediaSubType_FromFourCC( psubtype, 2 );
204 if ( pbi->biPlanes != 1 )
206 pdwBitf = (DWORD*)( (BYTE*)pbi + sizeof(BITMAPINFOHEADER) );
207 switch ( pbi->biBitCount )
210 if ( pdwBitf[0] == 0x7c00 &&
211 pdwBitf[1] == 0x03e0 &&
212 pdwBitf[2] == 0x001f )
214 memcpy( psubtype, &MEDIASUBTYPE_RGB555, sizeof(GUID) );
217 if ( pdwBitf[0] == 0xf800 &&
218 pdwBitf[1] == 0x07e0 &&
219 pdwBitf[2] == 0x001f )
221 memcpy( psubtype, &MEDIASUBTYPE_RGB565, sizeof(GUID) );
226 if ( pdwBitf[0] == 0x00ff0000 &&
227 pdwBitf[1] == 0x0000ff00 &&
228 pdwBitf[2] == 0x000000ff )
230 memcpy( psubtype, &MEDIASUBTYPE_RGB32, sizeof(GUID) );
241 void QUARTZ_PatchBitmapInfoHeader( BITMAPINFOHEADER* pbi )
243 switch ( pbi->biCompression )
245 case mmioFOURCC('R','G','B',' '):
246 pbi->biCompression = 0;
248 case mmioFOURCC('R','L','E',' '):
249 case mmioFOURCC('M','R','L','E'):
250 case mmioFOURCC('R','L','E','8'):
251 case mmioFOURCC('R','L','E','4'):
252 if ( pbi->biBitCount == 4 )
253 pbi->biCompression = 2;
255 pbi->biCompression = 1;
260 BOOL QUARTZ_BitmapHasFixedSample( const BITMAPINFOHEADER* pbi )
262 switch ( pbi->biCompression )
266 case mmioFOURCC('I','4','2','0'):
267 case mmioFOURCC('I','Y','U','V'):
268 case mmioFOURCC('Y','U','Y','V'):
269 case mmioFOURCC('Y','V','U','9'):
270 case mmioFOURCC('Y','4','1','1'):
271 case mmioFOURCC('Y','4','1','P'):
272 case mmioFOURCC('Y','U','Y','2'):
273 case mmioFOURCC('Y','V','Y','U'):
274 case mmioFOURCC('U','Y','V','Y'):
275 case mmioFOURCC('Y','2','1','1'):
276 case mmioFOURCC('Y','V','1','2'):
284 /****************************************************************************/
286 typedef struct IEnumMediaTypesImpl
288 ICOM_VFIELD(IEnumMediaTypes);
289 } IEnumMediaTypesImpl;
294 IEnumMediaTypesImpl enummtype;
295 struct QUARTZ_IFEntry IFEntries[1];
297 AM_MEDIA_TYPE* pTypes;
302 #define CEnumMediaTypes_THIS(iface,member) CEnumMediaTypes* This = ((CEnumMediaTypes*)(((char*)iface)-offsetof(CEnumMediaTypes,member)))
306 static HRESULT WINAPI
307 IEnumMediaTypes_fnQueryInterface(IEnumMediaTypes* iface,REFIID riid,void** ppobj)
309 CEnumMediaTypes_THIS(iface,enummtype);
311 TRACE("(%p)->()\n",This);
313 return IUnknown_QueryInterface(This->unk.punkControl,riid,ppobj);
317 IEnumMediaTypes_fnAddRef(IEnumMediaTypes* iface)
319 CEnumMediaTypes_THIS(iface,enummtype);
321 TRACE("(%p)->()\n",This);
323 return IUnknown_AddRef(This->unk.punkControl);
327 IEnumMediaTypes_fnRelease(IEnumMediaTypes* iface)
329 CEnumMediaTypes_THIS(iface,enummtype);
331 TRACE("(%p)->()\n",This);
333 return IUnknown_Release(This->unk.punkControl);
336 static HRESULT WINAPI
337 IEnumMediaTypes_fnNext(IEnumMediaTypes* iface,ULONG cReq,AM_MEDIA_TYPE** ppmtype,ULONG* pcFetched)
339 CEnumMediaTypes_THIS(iface,enummtype);
343 TRACE("(%p)->(%lu,%p,%p)\n",This,cReq,ppmtype,pcFetched);
345 if ( pcFetched == NULL && cReq > 1 )
347 if ( ppmtype == NULL )
350 EnterCriticalSection( &This->cs );
356 if ( This->cCur >= This->cTypes )
361 ppmtype[ cFetched ] =
362 QUARTZ_MediaType_Duplicate( &This->pTypes[ This->cCur ] );
363 if ( ppmtype[ cFetched ] == NULL )
366 while ( cFetched > 0 )
369 QUARTZ_MediaType_Destroy( ppmtype[ cFetched ] );
380 LeaveCriticalSection( &This->cs );
382 if ( pcFetched != NULL )
383 *pcFetched = cFetched;
388 static HRESULT WINAPI
389 IEnumMediaTypes_fnSkip(IEnumMediaTypes* iface,ULONG cSkip)
391 CEnumMediaTypes_THIS(iface,enummtype);
394 TRACE("(%p)->()\n",This);
396 EnterCriticalSection( &This->cs );
401 if ( This->cCur >= This->cTypes )
410 LeaveCriticalSection( &This->cs );
415 static HRESULT WINAPI
416 IEnumMediaTypes_fnReset(IEnumMediaTypes* iface)
418 CEnumMediaTypes_THIS(iface,enummtype);
420 TRACE("(%p)->()\n",This);
422 EnterCriticalSection( &This->cs );
426 LeaveCriticalSection( &This->cs );
431 static HRESULT WINAPI
432 IEnumMediaTypes_fnClone(IEnumMediaTypes* iface,IEnumMediaTypes** ppobj)
434 CEnumMediaTypes_THIS(iface,enummtype);
437 TRACE("(%p)->()\n",This);
442 EnterCriticalSection( &This->cs );
444 hr = QUARTZ_CreateEnumMediaTypes(
446 This->pTypes, This->cTypes );
448 IEnumMediaTypes_Skip( *ppobj, This->cCur );
450 LeaveCriticalSection( &This->cs );
456 static ICOM_VTABLE(IEnumMediaTypes) ienummtype =
458 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
459 /* IUnknown fields */
460 IEnumMediaTypes_fnQueryInterface,
461 IEnumMediaTypes_fnAddRef,
462 IEnumMediaTypes_fnRelease,
463 /* IEnumMediaTypes fields */
464 IEnumMediaTypes_fnNext,
465 IEnumMediaTypes_fnSkip,
466 IEnumMediaTypes_fnReset,
467 IEnumMediaTypes_fnClone,
471 /* can I use offsetof safely? - FIXME? */
472 static QUARTZ_IFEntry IFEntries[] =
474 { &IID_IEnumMediaTypes, offsetof(CEnumMediaTypes,enummtype)-offsetof(CEnumMediaTypes,unk) },
478 void QUARTZ_DestroyEnumMediaTypes(IUnknown* punk)
480 CEnumMediaTypes_THIS(punk,unk);
483 if ( This->pTypes != NULL )
485 for ( i = 0; i < This->cTypes; i++ )
486 QUARTZ_MediaType_Free( &This->pTypes[i] );
487 QUARTZ_FreeMem( This->pTypes );
490 DeleteCriticalSection( &This->cs );
493 HRESULT QUARTZ_CreateEnumMediaTypes(
494 IEnumMediaTypes** ppobj,
495 const AM_MEDIA_TYPE* pTypes, ULONG cTypes )
497 CEnumMediaTypes* penum;
498 AM_MEDIA_TYPE* pTypesDup = NULL;
502 TRACE("(%p,%p,%lu)\n",ppobj,pTypes,cTypes);
506 pTypesDup = (AM_MEDIA_TYPE*)QUARTZ_AllocMem(
507 sizeof( AM_MEDIA_TYPE ) * cTypes );
508 if ( pTypesDup == NULL )
509 return E_OUTOFMEMORY;
514 hr = QUARTZ_MediaType_Copy( &pTypesDup[i], &pTypes[i] );
520 QUARTZ_MediaType_Free( &pTypesDup[i] );
522 QUARTZ_FreeMem( pTypesDup );
530 penum = (CEnumMediaTypes*)QUARTZ_AllocObj( sizeof(CEnumMediaTypes) );
533 return E_OUTOFMEMORY;
535 penum->pTypes = pTypesDup;
536 penum->cTypes = cTypes;
539 QUARTZ_IUnkInit( &penum->unk, NULL );
540 ICOM_VTBL(&penum->enummtype) = &ienummtype;
542 penum->unk.pEntries = IFEntries;
543 penum->unk.dwEntries = sizeof(IFEntries)/sizeof(IFEntries[0]);
544 penum->unk.pOnFinalRelease = QUARTZ_DestroyEnumMediaTypes;
546 InitializeCriticalSection( &penum->cs );
548 *ppobj = (IEnumMediaTypes*)(&penum->enummtype);