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
);