Add $X_LIBS path while searching for libfreetype.
[wine/gsoc_dplay.git] / dlls / quartz / mtype.c
blob00dcfad9409b3b5bfb41d36e329bb0ca84f48604
1 /*
2 * Implements IEnumMediaTypes and helper functions. (internal)
4 * hidenori@a2.ctktv.ne.jp
5 */
7 #include "config.h"
9 #include "windef.h"
10 #include "winbase.h"
11 #include "wingdi.h"
12 #include "winuser.h"
13 #include "winerror.h"
14 #include "mmsystem.h"
15 #include "strmif.h"
16 #include "vfwmsgs.h"
17 #include "uuids.h"
19 #include "debugtools.h"
20 DEFAULT_DEBUG_CHANNEL(quartz);
22 #include "quartz_private.h"
23 #include "mtype.h"
24 #include "iunk.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) );
41 pmtDst->pUnk = NULL;
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 );
51 return E_OUTOFMEMORY;
53 memcpy( pmtDst->pbFormat, pmtSrc->pbFormat, pmtSrc->cbFormat );
56 if ( pmtSrc->pUnk != NULL )
58 pmtDst->pUnk = pmtSrc->pUnk;
59 IUnknown_AddRef( pmtSrc->pUnk );
62 return S_OK;
65 void QUARTZ_MediaType_Free(
66 AM_MEDIA_TYPE* pmt )
68 if ( pmt->pUnk != NULL )
70 IUnknown_Release( pmt->pUnk );
71 pmt->pUnk = NULL;
73 if ( pmt->pbFormat != NULL )
75 CoTaskMemFree( pmt->pbFormat );
76 pmt->cbFormat = 0;
77 pmt->pbFormat = NULL;
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) );
87 if ( pmtDup == NULL )
88 return NULL;
89 if ( QUARTZ_MediaType_Copy( pmtDup, pmtSrc ) != S_OK )
91 CoTaskMemFree( pmtDup );
92 return NULL;
95 return pmtDup;
98 void QUARTZ_MediaType_Destroy(
99 AM_MEDIA_TYPE* pmt )
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 )
120 GUID guidTemp;
122 QUARTZ_MediaSubType_FromFourCC(
123 &guidTemp, psubtype->Data1 );
124 return IsEqualGUID( psubtype, &guidTemp );
127 HRESULT QUARTZ_MediaSubType_FromBitmap(
128 GUID* psubtype, const BITMAPINFOHEADER* pbi )
130 HRESULT hr;
131 DWORD* pdwBitf;
133 if ( (pbi->biCompression & 0xffff0000) != 0 )
134 return S_FALSE;
136 if ( pbi->biWidth <= 0 || pbi->biHeight == 0 )
137 return E_FAIL;
139 hr = E_FAIL;
140 switch ( pbi->biCompression )
142 case 0:
143 if ( pbi->biPlanes != 1 )
144 break;
145 switch ( pbi->biBitCount )
147 case 1:
148 memcpy( psubtype, &MEDIASUBTYPE_RGB1, sizeof(GUID) );
149 hr = S_OK;
150 break;
151 case 4:
152 memcpy( psubtype, &MEDIASUBTYPE_RGB4, sizeof(GUID) );
153 hr = S_OK;
154 break;
155 case 8:
156 memcpy( psubtype, &MEDIASUBTYPE_RGB8, sizeof(GUID) );
157 hr = S_OK;
158 break;
159 case 16:
160 memcpy( psubtype, &MEDIASUBTYPE_RGB555, sizeof(GUID) );
161 hr = S_OK;
162 break;
163 case 24:
164 memcpy( psubtype, &MEDIASUBTYPE_RGB24, sizeof(GUID) );
165 hr = S_OK;
166 break;
167 case 32:
168 memcpy( psubtype, &MEDIASUBTYPE_RGB32, sizeof(GUID) );
169 hr = S_OK;
170 break;
172 break;
173 case 1:
174 if ( pbi->biPlanes == 1 && pbi->biHeight > 0 &&
175 pbi->biBitCount == 8 )
177 QUARTZ_MediaSubType_FromFourCC( psubtype, mmioFOURCC('M','R','L','E') );
178 hr = S_OK;
180 break;
181 case 2:
182 if ( pbi->biPlanes == 1 && pbi->biHeight > 0 &&
183 pbi->biBitCount == 4 )
185 QUARTZ_MediaSubType_FromFourCC( psubtype, mmioFOURCC('M','R','L','E') );
186 hr = S_OK;
188 break;
189 case 3:
190 if ( pbi->biPlanes != 1 )
191 break;
192 pdwBitf = (DWORD*)( (BYTE*)pbi + sizeof(BITMAPINFOHEADER) );
193 switch ( pbi->biBitCount )
195 case 16:
196 if ( pdwBitf[0] == 0x7c00 &&
197 pdwBitf[1] == 0x03e0 &&
198 pdwBitf[2] == 0x001f )
200 memcpy( psubtype, &MEDIASUBTYPE_RGB555, sizeof(GUID) );
201 hr = S_OK;
203 if ( pdwBitf[0] == 0xf800 &&
204 pdwBitf[1] == 0x07e0 &&
205 pdwBitf[2] == 0x001f )
207 memcpy( psubtype, &MEDIASUBTYPE_RGB565, sizeof(GUID) );
208 hr = S_OK;
210 break;
211 case 32:
212 if ( pdwBitf[0] == 0x00ff0000 &&
213 pdwBitf[1] == 0x0000ff00 &&
214 pdwBitf[2] == 0x000000ff )
216 memcpy( psubtype, &MEDIASUBTYPE_RGB32, sizeof(GUID) );
217 hr = S_OK;
219 break;
221 break;
224 return hr;
227 void QUARTZ_PatchBitmapInfoHeader( BITMAPINFOHEADER* pbi )
229 switch ( pbi->biCompression )
231 case mmioFOURCC('R','G','B',' '):
232 pbi->biCompression = 0;
233 break;
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;
240 else
241 pbi->biCompression = 1;
242 break;
246 BOOL QUARTZ_BitmapHasFixedSample( const BITMAPINFOHEADER* pbi )
248 switch ( pbi->biCompression )
250 case 0:
251 case 3:
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'):
263 return TRUE;
266 return FALSE;
270 /****************************************************************************/
272 typedef struct IEnumMediaTypesImpl
274 ICOM_VFIELD(IEnumMediaTypes);
275 } IEnumMediaTypesImpl;
277 typedef struct
279 QUARTZ_IUnkImpl unk;
280 IEnumMediaTypesImpl enummtype;
281 struct QUARTZ_IFEntry IFEntries[1];
282 CRITICAL_SECTION cs;
283 AM_MEDIA_TYPE* pTypes;
284 ULONG cTypes;
285 ULONG cCur;
286 } CEnumMediaTypes;
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);
302 static ULONG WINAPI
303 IEnumMediaTypes_fnAddRef(IEnumMediaTypes* iface)
305 CEnumMediaTypes_THIS(iface,enummtype);
307 TRACE("(%p)->()\n",This);
309 return IUnknown_AddRef(This->unk.punkControl);
312 static ULONG WINAPI
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);
326 HRESULT hr;
327 ULONG cFetched;
329 TRACE("(%p)->(%lu,%p,%p)\n",This,cReq,ppmtype,pcFetched);
331 if ( pcFetched == NULL && cReq > 1 )
332 return E_INVALIDARG;
333 if ( ppmtype == NULL )
334 return E_POINTER;
336 EnterCriticalSection( &This->cs );
338 hr = NOERROR;
339 cFetched = 0;
340 while ( cReq > 0 )
342 if ( This->cCur >= This->cTypes )
344 hr = S_FALSE;
345 break;
347 ppmtype[ cFetched ] =
348 QUARTZ_MediaType_Duplicate( &This->pTypes[ This->cCur ] );
349 if ( ppmtype[ cFetched ] == NULL )
351 hr = E_OUTOFMEMORY;
352 while ( cFetched > 0 )
354 cFetched --;
355 QUARTZ_MediaType_Destroy( ppmtype[ cFetched ] );
357 break;
360 cFetched ++;
362 This->cCur ++;
363 cReq --;
366 LeaveCriticalSection( &This->cs );
368 if ( pcFetched != NULL )
369 *pcFetched = cFetched;
371 return hr;
374 static HRESULT WINAPI
375 IEnumMediaTypes_fnSkip(IEnumMediaTypes* iface,ULONG cSkip)
377 CEnumMediaTypes_THIS(iface,enummtype);
378 HRESULT hr;
380 TRACE("(%p)->()\n",This);
382 EnterCriticalSection( &This->cs );
384 hr = NOERROR;
385 while ( cSkip > 0 )
387 if ( This->cCur >= This->cTypes )
389 hr = S_FALSE;
390 break;
392 This->cCur ++;
393 cSkip --;
396 LeaveCriticalSection( &This->cs );
398 return hr;
401 static HRESULT WINAPI
402 IEnumMediaTypes_fnReset(IEnumMediaTypes* iface)
404 CEnumMediaTypes_THIS(iface,enummtype);
406 TRACE("(%p)->()\n",This);
408 EnterCriticalSection( &This->cs );
410 This->cCur = 0;
412 LeaveCriticalSection( &This->cs );
414 return NOERROR;
417 static HRESULT WINAPI
418 IEnumMediaTypes_fnClone(IEnumMediaTypes* iface,IEnumMediaTypes** ppobj)
420 CEnumMediaTypes_THIS(iface,enummtype);
421 HRESULT hr;
423 TRACE("(%p)->()\n",This);
425 if ( ppobj == NULL )
426 return E_POINTER;
428 EnterCriticalSection( &This->cs );
430 hr = QUARTZ_CreateEnumMediaTypes(
431 ppobj,
432 This->pTypes, This->cTypes );
433 if ( SUCCEEDED(hr) )
434 IEnumMediaTypes_Skip( *ppobj, This->cCur );
436 LeaveCriticalSection( &This->cs );
438 return hr;
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);
467 ULONG i;
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;
485 ULONG i;
486 HRESULT hr;
488 TRACE("(%p,%p,%lu)\n",ppobj,pTypes,cTypes);
490 if ( cTypes > 0 )
492 pTypesDup = (AM_MEDIA_TYPE*)QUARTZ_AllocMem(
493 sizeof( AM_MEDIA_TYPE ) * cTypes );
494 if ( pTypesDup == NULL )
495 return E_OUTOFMEMORY;
497 i = 0;
498 while ( i < cTypes )
500 hr = QUARTZ_MediaType_Copy( &pTypesDup[i], &pTypes[i] );
501 if ( FAILED(hr) )
503 while ( i > 0 )
505 i --;
506 QUARTZ_MediaType_Free( &pTypesDup[i] );
508 QUARTZ_FreeMem( pTypesDup );
509 return hr;
512 i ++;
516 penum = (CEnumMediaTypes*)QUARTZ_AllocObj( sizeof(CEnumMediaTypes) );
517 if ( penum == NULL )
519 return E_OUTOFMEMORY;
521 penum->pTypes = pTypesDup;
522 penum->cTypes = cTypes;
523 penum->cCur = 0;
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);
536 return S_OK;