Added LGPL standard comment, and copyright notices where necessary.
[wine/multimedia.git] / dlls / quartz / mtype.c
blobf2942751af3600dd525a539996009ffb9a6865f5
1 /*
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
21 #include "config.h"
23 #include "windef.h"
24 #include "winbase.h"
25 #include "wingdi.h"
26 #include "winuser.h"
27 #include "winerror.h"
28 #include "mmsystem.h"
29 #include "strmif.h"
30 #include "vfwmsgs.h"
31 #include "uuids.h"
33 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
36 #include "quartz_private.h"
37 #include "mtype.h"
38 #include "iunk.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) );
55 pmtDst->pUnk = NULL;
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 );
65 return E_OUTOFMEMORY;
67 memcpy( pmtDst->pbFormat, pmtSrc->pbFormat, pmtSrc->cbFormat );
70 if ( pmtSrc->pUnk != NULL )
72 pmtDst->pUnk = pmtSrc->pUnk;
73 IUnknown_AddRef( pmtSrc->pUnk );
76 return S_OK;
79 void QUARTZ_MediaType_Free(
80 AM_MEDIA_TYPE* pmt )
82 if ( pmt->pUnk != NULL )
84 IUnknown_Release( pmt->pUnk );
85 pmt->pUnk = NULL;
87 if ( pmt->pbFormat != NULL )
89 CoTaskMemFree( pmt->pbFormat );
90 pmt->cbFormat = 0;
91 pmt->pbFormat = NULL;
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 )
102 return NULL;
103 if ( QUARTZ_MediaType_Copy( pmtDup, pmtSrc ) != S_OK )
105 CoTaskMemFree( pmtDup );
106 return NULL;
109 return pmtDup;
112 void QUARTZ_MediaType_Destroy(
113 AM_MEDIA_TYPE* pmt )
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 )
134 GUID guidTemp;
136 QUARTZ_MediaSubType_FromFourCC(
137 &guidTemp, psubtype->Data1 );
138 return IsEqualGUID( psubtype, &guidTemp );
141 HRESULT QUARTZ_MediaSubType_FromBitmap(
142 GUID* psubtype, const BITMAPINFOHEADER* pbi )
144 HRESULT hr;
145 DWORD* pdwBitf;
147 if ( (pbi->biCompression & 0xffff0000) != 0 )
148 return S_FALSE;
150 if ( pbi->biWidth <= 0 || pbi->biHeight == 0 )
151 return E_FAIL;
153 hr = E_FAIL;
154 switch ( pbi->biCompression )
156 case 0:
157 if ( pbi->biPlanes != 1 )
158 break;
159 switch ( pbi->biBitCount )
161 case 1:
162 memcpy( psubtype, &MEDIASUBTYPE_RGB1, sizeof(GUID) );
163 hr = S_OK;
164 break;
165 case 4:
166 memcpy( psubtype, &MEDIASUBTYPE_RGB4, sizeof(GUID) );
167 hr = S_OK;
168 break;
169 case 8:
170 memcpy( psubtype, &MEDIASUBTYPE_RGB8, sizeof(GUID) );
171 hr = S_OK;
172 break;
173 case 16:
174 memcpy( psubtype, &MEDIASUBTYPE_RGB555, sizeof(GUID) );
175 hr = S_OK;
176 break;
177 case 24:
178 memcpy( psubtype, &MEDIASUBTYPE_RGB24, sizeof(GUID) );
179 hr = S_OK;
180 break;
181 case 32:
182 memcpy( psubtype, &MEDIASUBTYPE_RGB32, sizeof(GUID) );
183 hr = S_OK;
184 break;
186 break;
187 case 1:
188 if ( pbi->biPlanes == 1 && pbi->biHeight > 0 &&
189 pbi->biBitCount == 8 )
191 QUARTZ_MediaSubType_FromFourCC( psubtype, 1 );
192 hr = S_OK;
194 break;
195 case 2:
196 if ( pbi->biPlanes == 1 && pbi->biHeight > 0 &&
197 pbi->biBitCount == 4 )
199 QUARTZ_MediaSubType_FromFourCC( psubtype, 2 );
200 hr = S_OK;
202 break;
203 case 3:
204 if ( pbi->biPlanes != 1 )
205 break;
206 pdwBitf = (DWORD*)( (BYTE*)pbi + sizeof(BITMAPINFOHEADER) );
207 switch ( pbi->biBitCount )
209 case 16:
210 if ( pdwBitf[0] == 0x7c00 &&
211 pdwBitf[1] == 0x03e0 &&
212 pdwBitf[2] == 0x001f )
214 memcpy( psubtype, &MEDIASUBTYPE_RGB555, sizeof(GUID) );
215 hr = S_OK;
217 if ( pdwBitf[0] == 0xf800 &&
218 pdwBitf[1] == 0x07e0 &&
219 pdwBitf[2] == 0x001f )
221 memcpy( psubtype, &MEDIASUBTYPE_RGB565, sizeof(GUID) );
222 hr = S_OK;
224 break;
225 case 32:
226 if ( pdwBitf[0] == 0x00ff0000 &&
227 pdwBitf[1] == 0x0000ff00 &&
228 pdwBitf[2] == 0x000000ff )
230 memcpy( psubtype, &MEDIASUBTYPE_RGB32, sizeof(GUID) );
231 hr = S_OK;
233 break;
235 break;
238 return hr;
241 void QUARTZ_PatchBitmapInfoHeader( BITMAPINFOHEADER* pbi )
243 switch ( pbi->biCompression )
245 case mmioFOURCC('R','G','B',' '):
246 pbi->biCompression = 0;
247 break;
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;
254 else
255 pbi->biCompression = 1;
256 break;
260 BOOL QUARTZ_BitmapHasFixedSample( const BITMAPINFOHEADER* pbi )
262 switch ( pbi->biCompression )
264 case 0:
265 case 3:
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'):
277 return TRUE;
280 return FALSE;
284 /****************************************************************************/
286 typedef struct IEnumMediaTypesImpl
288 ICOM_VFIELD(IEnumMediaTypes);
289 } IEnumMediaTypesImpl;
291 typedef struct
293 QUARTZ_IUnkImpl unk;
294 IEnumMediaTypesImpl enummtype;
295 struct QUARTZ_IFEntry IFEntries[1];
296 CRITICAL_SECTION cs;
297 AM_MEDIA_TYPE* pTypes;
298 ULONG cTypes;
299 ULONG cCur;
300 } CEnumMediaTypes;
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);
316 static ULONG WINAPI
317 IEnumMediaTypes_fnAddRef(IEnumMediaTypes* iface)
319 CEnumMediaTypes_THIS(iface,enummtype);
321 TRACE("(%p)->()\n",This);
323 return IUnknown_AddRef(This->unk.punkControl);
326 static ULONG WINAPI
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);
340 HRESULT hr;
341 ULONG cFetched;
343 TRACE("(%p)->(%lu,%p,%p)\n",This,cReq,ppmtype,pcFetched);
345 if ( pcFetched == NULL && cReq > 1 )
346 return E_INVALIDARG;
347 if ( ppmtype == NULL )
348 return E_POINTER;
350 EnterCriticalSection( &This->cs );
352 hr = NOERROR;
353 cFetched = 0;
354 while ( cReq > 0 )
356 if ( This->cCur >= This->cTypes )
358 hr = S_FALSE;
359 break;
361 ppmtype[ cFetched ] =
362 QUARTZ_MediaType_Duplicate( &This->pTypes[ This->cCur ] );
363 if ( ppmtype[ cFetched ] == NULL )
365 hr = E_OUTOFMEMORY;
366 while ( cFetched > 0 )
368 cFetched --;
369 QUARTZ_MediaType_Destroy( ppmtype[ cFetched ] );
371 break;
374 cFetched ++;
376 This->cCur ++;
377 cReq --;
380 LeaveCriticalSection( &This->cs );
382 if ( pcFetched != NULL )
383 *pcFetched = cFetched;
385 return hr;
388 static HRESULT WINAPI
389 IEnumMediaTypes_fnSkip(IEnumMediaTypes* iface,ULONG cSkip)
391 CEnumMediaTypes_THIS(iface,enummtype);
392 HRESULT hr;
394 TRACE("(%p)->()\n",This);
396 EnterCriticalSection( &This->cs );
398 hr = NOERROR;
399 while ( cSkip > 0 )
401 if ( This->cCur >= This->cTypes )
403 hr = S_FALSE;
404 break;
406 This->cCur ++;
407 cSkip --;
410 LeaveCriticalSection( &This->cs );
412 return hr;
415 static HRESULT WINAPI
416 IEnumMediaTypes_fnReset(IEnumMediaTypes* iface)
418 CEnumMediaTypes_THIS(iface,enummtype);
420 TRACE("(%p)->()\n",This);
422 EnterCriticalSection( &This->cs );
424 This->cCur = 0;
426 LeaveCriticalSection( &This->cs );
428 return NOERROR;
431 static HRESULT WINAPI
432 IEnumMediaTypes_fnClone(IEnumMediaTypes* iface,IEnumMediaTypes** ppobj)
434 CEnumMediaTypes_THIS(iface,enummtype);
435 HRESULT hr;
437 TRACE("(%p)->()\n",This);
439 if ( ppobj == NULL )
440 return E_POINTER;
442 EnterCriticalSection( &This->cs );
444 hr = QUARTZ_CreateEnumMediaTypes(
445 ppobj,
446 This->pTypes, This->cTypes );
447 if ( SUCCEEDED(hr) )
448 IEnumMediaTypes_Skip( *ppobj, This->cCur );
450 LeaveCriticalSection( &This->cs );
452 return hr;
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);
481 ULONG i;
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;
499 ULONG i;
500 HRESULT hr;
502 TRACE("(%p,%p,%lu)\n",ppobj,pTypes,cTypes);
504 if ( cTypes > 0 )
506 pTypesDup = (AM_MEDIA_TYPE*)QUARTZ_AllocMem(
507 sizeof( AM_MEDIA_TYPE ) * cTypes );
508 if ( pTypesDup == NULL )
509 return E_OUTOFMEMORY;
511 i = 0;
512 while ( i < cTypes )
514 hr = QUARTZ_MediaType_Copy( &pTypesDup[i], &pTypes[i] );
515 if ( FAILED(hr) )
517 while ( i > 0 )
519 i --;
520 QUARTZ_MediaType_Free( &pTypesDup[i] );
522 QUARTZ_FreeMem( pTypesDup );
523 return hr;
526 i ++;
530 penum = (CEnumMediaTypes*)QUARTZ_AllocObj( sizeof(CEnumMediaTypes) );
531 if ( penum == NULL )
533 return E_OUTOFMEMORY;
535 penum->pTypes = pTypesDup;
536 penum->cTypes = cTypes;
537 penum->cCur = 0;
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);
550 return S_OK;