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 )
66 memcpy( pmtDst->pbFormat, pmtSrc->pbFormat, pmtSrc->cbFormat );
69 if ( pmtSrc->pUnk != NULL )
71 pmtDst->pUnk = pmtSrc->pUnk;
72 IUnknown_AddRef( pmtSrc->pUnk );
78 void QUARTZ_MediaType_Free(
81 if ( pmt->pUnk != NULL )
83 IUnknown_Release( pmt->pUnk );
86 if ( pmt->pbFormat != NULL )
88 CoTaskMemFree( pmt->pbFormat );
94 AM_MEDIA_TYPE* QUARTZ_MediaType_Duplicate(
95 const AM_MEDIA_TYPE* pmtSrc )
97 AM_MEDIA_TYPE* pmtDup;
99 pmtDup = (AM_MEDIA_TYPE*)CoTaskMemAlloc( sizeof(AM_MEDIA_TYPE) );
100 if ( pmtDup == NULL )
102 if ( QUARTZ_MediaType_Copy( pmtDup, pmtSrc ) != S_OK )
104 CoTaskMemFree( pmtDup );
111 void QUARTZ_MediaType_Destroy(
114 QUARTZ_MediaType_Free( pmt );
115 CoTaskMemFree( pmt );
118 void QUARTZ_MediaSubType_FromFourCC(
119 GUID* psubtype, DWORD dwFourCC )
121 TRACE( "FourCC %c%c%c%c\n",
122 (int)(dwFourCC>> 0)&0xff,
123 (int)(dwFourCC>> 8)&0xff,
124 (int)(dwFourCC>>16)&0xff,
125 (int)(dwFourCC>>24)&0xff );
126 memcpy( psubtype, &MEDIASUBTYPE_PCM, sizeof(GUID) );
127 psubtype->Data1 = dwFourCC;
130 BOOL QUARTZ_MediaSubType_IsFourCC(
131 const GUID* psubtype )
135 QUARTZ_MediaSubType_FromFourCC(
136 &guidTemp, psubtype->Data1 );
137 return IsEqualGUID( psubtype, &guidTemp );
140 HRESULT QUARTZ_MediaSubType_FromBitmap(
141 GUID* psubtype, const BITMAPINFOHEADER* pbi )
146 if ( (pbi->biCompression & 0xffff0000) != 0 )
149 if ( pbi->biWidth <= 0 || pbi->biHeight == 0 )
153 switch ( pbi->biCompression )
156 if ( pbi->biPlanes != 1 )
158 switch ( pbi->biBitCount )
161 memcpy( psubtype, &MEDIASUBTYPE_RGB1, sizeof(GUID) );
165 memcpy( psubtype, &MEDIASUBTYPE_RGB4, sizeof(GUID) );
169 memcpy( psubtype, &MEDIASUBTYPE_RGB8, sizeof(GUID) );
173 memcpy( psubtype, &MEDIASUBTYPE_RGB555, sizeof(GUID) );
177 memcpy( psubtype, &MEDIASUBTYPE_RGB24, sizeof(GUID) );
181 memcpy( psubtype, &MEDIASUBTYPE_RGB32, sizeof(GUID) );
187 if ( pbi->biPlanes == 1 && pbi->biHeight > 0 &&
188 pbi->biBitCount == 8 )
190 QUARTZ_MediaSubType_FromFourCC( psubtype, 1 );
195 if ( pbi->biPlanes == 1 && pbi->biHeight > 0 &&
196 pbi->biBitCount == 4 )
198 QUARTZ_MediaSubType_FromFourCC( psubtype, 2 );
203 if ( pbi->biPlanes != 1 )
205 pdwBitf = (DWORD*)( (BYTE*)pbi + sizeof(BITMAPINFOHEADER) );
206 switch ( pbi->biBitCount )
209 if ( pdwBitf[0] == 0x7c00 &&
210 pdwBitf[1] == 0x03e0 &&
211 pdwBitf[2] == 0x001f )
213 memcpy( psubtype, &MEDIASUBTYPE_RGB555, sizeof(GUID) );
216 if ( pdwBitf[0] == 0xf800 &&
217 pdwBitf[1] == 0x07e0 &&
218 pdwBitf[2] == 0x001f )
220 memcpy( psubtype, &MEDIASUBTYPE_RGB565, sizeof(GUID) );
225 if ( pdwBitf[0] == 0x00ff0000 &&
226 pdwBitf[1] == 0x0000ff00 &&
227 pdwBitf[2] == 0x000000ff )
229 memcpy( psubtype, &MEDIASUBTYPE_RGB32, sizeof(GUID) );
240 void QUARTZ_PatchBitmapInfoHeader( BITMAPINFOHEADER* pbi )
242 switch ( pbi->biCompression )
244 case mmioFOURCC('R','G','B',' '):
245 pbi->biCompression = 0;
247 case mmioFOURCC('R','L','E',' '):
248 case mmioFOURCC('M','R','L','E'):
249 case mmioFOURCC('R','L','E','8'):
250 case mmioFOURCC('R','L','E','4'):
251 if ( pbi->biBitCount == 4 )
252 pbi->biCompression = 2;
254 pbi->biCompression = 1;
259 BOOL QUARTZ_BitmapHasFixedSample( const BITMAPINFOHEADER* pbi )
261 switch ( pbi->biCompression )
265 case mmioFOURCC('I','4','2','0'):
266 case mmioFOURCC('I','Y','U','V'):
267 case mmioFOURCC('Y','U','Y','V'):
268 case mmioFOURCC('Y','V','U','9'):
269 case mmioFOURCC('Y','4','1','1'):
270 case mmioFOURCC('Y','4','1','P'):
271 case mmioFOURCC('Y','U','Y','2'):
272 case mmioFOURCC('Y','V','Y','U'):
273 case mmioFOURCC('U','Y','V','Y'):
274 case mmioFOURCC('Y','2','1','1'):
275 case mmioFOURCC('Y','V','1','2'):
283 /****************************************************************************/
285 typedef struct IEnumMediaTypesImpl
287 ICOM_VFIELD(IEnumMediaTypes);
288 } IEnumMediaTypesImpl;
293 IEnumMediaTypesImpl enummtype;
294 struct QUARTZ_IFEntry IFEntries[1];
296 AM_MEDIA_TYPE* pTypes;
301 #define CEnumMediaTypes_THIS(iface,member) CEnumMediaTypes* This = ((CEnumMediaTypes*)(((char*)iface)-offsetof(CEnumMediaTypes,member)))
305 static HRESULT WINAPI
306 IEnumMediaTypes_fnQueryInterface(IEnumMediaTypes* iface,REFIID riid,void** ppobj)
308 CEnumMediaTypes_THIS(iface,enummtype);
310 TRACE("(%p)->()\n",This);
312 return IUnknown_QueryInterface(This->unk.punkControl,riid,ppobj);
316 IEnumMediaTypes_fnAddRef(IEnumMediaTypes* iface)
318 CEnumMediaTypes_THIS(iface,enummtype);
320 TRACE("(%p)->()\n",This);
322 return IUnknown_AddRef(This->unk.punkControl);
326 IEnumMediaTypes_fnRelease(IEnumMediaTypes* iface)
328 CEnumMediaTypes_THIS(iface,enummtype);
330 TRACE("(%p)->()\n",This);
332 return IUnknown_Release(This->unk.punkControl);
335 static HRESULT WINAPI
336 IEnumMediaTypes_fnNext(IEnumMediaTypes* iface,ULONG cReq,AM_MEDIA_TYPE** ppmtype,ULONG* pcFetched)
338 CEnumMediaTypes_THIS(iface,enummtype);
342 TRACE("(%p)->(%lu,%p,%p)\n",This,cReq,ppmtype,pcFetched);
344 if ( pcFetched == NULL && cReq > 1 )
346 if ( ppmtype == NULL )
349 EnterCriticalSection( &This->cs );
355 if ( This->cCur >= This->cTypes )
360 ppmtype[ cFetched ] =
361 QUARTZ_MediaType_Duplicate( &This->pTypes[ This->cCur ] );
362 if ( ppmtype[ cFetched ] == NULL )
365 while ( cFetched > 0 )
368 QUARTZ_MediaType_Destroy( ppmtype[ cFetched ] );
379 LeaveCriticalSection( &This->cs );
381 if ( pcFetched != NULL )
382 *pcFetched = cFetched;
387 static HRESULT WINAPI
388 IEnumMediaTypes_fnSkip(IEnumMediaTypes* iface,ULONG cSkip)
390 CEnumMediaTypes_THIS(iface,enummtype);
393 TRACE("(%p)->()\n",This);
395 EnterCriticalSection( &This->cs );
400 if ( This->cCur >= This->cTypes )
409 LeaveCriticalSection( &This->cs );
414 static HRESULT WINAPI
415 IEnumMediaTypes_fnReset(IEnumMediaTypes* iface)
417 CEnumMediaTypes_THIS(iface,enummtype);
419 TRACE("(%p)->()\n",This);
421 EnterCriticalSection( &This->cs );
425 LeaveCriticalSection( &This->cs );
430 static HRESULT WINAPI
431 IEnumMediaTypes_fnClone(IEnumMediaTypes* iface,IEnumMediaTypes** ppobj)
433 CEnumMediaTypes_THIS(iface,enummtype);
436 TRACE("(%p)->()\n",This);
441 EnterCriticalSection( &This->cs );
443 hr = QUARTZ_CreateEnumMediaTypes(
445 This->pTypes, This->cTypes );
447 IEnumMediaTypes_Skip( *ppobj, This->cCur );
449 LeaveCriticalSection( &This->cs );
455 static ICOM_VTABLE(IEnumMediaTypes) ienummtype =
457 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
458 /* IUnknown fields */
459 IEnumMediaTypes_fnQueryInterface,
460 IEnumMediaTypes_fnAddRef,
461 IEnumMediaTypes_fnRelease,
462 /* IEnumMediaTypes fields */
463 IEnumMediaTypes_fnNext,
464 IEnumMediaTypes_fnSkip,
465 IEnumMediaTypes_fnReset,
466 IEnumMediaTypes_fnClone,
470 /* can I use offsetof safely? - FIXME? */
471 static QUARTZ_IFEntry IFEntries[] =
473 { &IID_IEnumMediaTypes, offsetof(CEnumMediaTypes,enummtype)-offsetof(CEnumMediaTypes,unk) },
477 void QUARTZ_DestroyEnumMediaTypes(IUnknown* punk)
479 CEnumMediaTypes_THIS(punk,unk);
482 if ( This->pTypes != NULL )
484 for ( i = 0; i < This->cTypes; i++ )
485 QUARTZ_MediaType_Free( &This->pTypes[i] );
486 QUARTZ_FreeMem( This->pTypes );
489 DeleteCriticalSection( &This->cs );
492 HRESULT QUARTZ_CreateEnumMediaTypes(
493 IEnumMediaTypes** ppobj,
494 const AM_MEDIA_TYPE* pTypes, ULONG cTypes )
496 CEnumMediaTypes* penum;
497 AM_MEDIA_TYPE* pTypesDup = NULL;
501 TRACE("(%p,%p,%lu)\n",ppobj,pTypes,cTypes);
505 pTypesDup = (AM_MEDIA_TYPE*)QUARTZ_AllocMem(
506 sizeof( AM_MEDIA_TYPE ) * cTypes );
507 if ( pTypesDup == NULL )
508 return E_OUTOFMEMORY;
513 hr = QUARTZ_MediaType_Copy( &pTypesDup[i], &pTypes[i] );
519 QUARTZ_MediaType_Free( &pTypesDup[i] );
521 QUARTZ_FreeMem( pTypesDup );
529 penum = (CEnumMediaTypes*)QUARTZ_AllocObj( sizeof(CEnumMediaTypes) );
532 return E_OUTOFMEMORY;
534 penum->pTypes = pTypesDup;
535 penum->cTypes = cTypes;
538 QUARTZ_IUnkInit( &penum->unk, NULL );
539 ICOM_VTBL(&penum->enummtype) = &ienummtype;
541 penum->unk.pEntries = IFEntries;
542 penum->unk.dwEntries = sizeof(IFEntries)/sizeof(IFEntries[0]);
543 penum->unk.pOnFinalRelease = QUARTZ_DestroyEnumMediaTypes;
545 InitializeCriticalSection( &penum->cs );
547 *ppobj = (IEnumMediaTypes*)(&penum->enummtype);