Implemented CLSID_AudioRender.
[wine/multimedia.git] / dlls / quartz / sample.c
blob03a8f0e30c34307285daa86d6b23d8dbceafa13d
1 /*
2 * Implements IMediaSample2 for CMemMediaSample.
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 "wine/obj_base.h"
15 #include "strmif.h"
16 #include "vfwmsgs.h"
18 #include "debugtools.h"
19 DEFAULT_DEBUG_CHANNEL(quartz);
21 #include "quartz_private.h"
22 #include "sample.h"
23 #include "mtype.h"
26 /***************************************************************************
28 * CMemMediaSample::IMediaSample2
32 static HRESULT WINAPI
33 IMediaSample2_fnQueryInterface(IMediaSample2* iface,REFIID riid,void** ppobj)
35 ICOM_THIS(CMemMediaSample,iface);
37 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
39 if ( ppobj == NULL )
40 return E_POINTER;
42 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
43 IsEqualGUID( riid, &IID_IMediaSample ) ||
44 IsEqualGUID( riid, &IID_IMediaSample2 ) )
46 *ppobj = iface;
47 IMediaSample2_AddRef(iface);
48 return NOERROR;
51 return E_NOINTERFACE;
54 static ULONG WINAPI
55 IMediaSample2_fnAddRef(IMediaSample2* iface)
57 ICOM_THIS(CMemMediaSample,iface);
59 TRACE("(%p)->()\n",This);
61 return InterlockedExchangeAdd(&(This->ref),1) + 1;
64 static ULONG WINAPI
65 IMediaSample2_fnRelease(IMediaSample2* iface)
67 ICOM_THIS(CMemMediaSample,iface);
68 LONG ref;
70 TRACE("(%p)->()\n",This);
72 ref = InterlockedExchangeAdd(&(This->ref),-1) - 1;
73 if ( ref > 0 )
74 return (ULONG)ref;
76 /* this class would be reused.. */
77 if ( This->prop.pMediaType != NULL )
79 QUARTZ_MediaType_Destroy( This->prop.pMediaType );
80 This->prop.pMediaType = NULL;
82 This->prop.dwTypeSpecificFlags = 0;
83 This->prop.dwSampleFlags = 0;
84 This->prop.lActual = This->prop.cbBuffer;
86 IMemAllocator_ReleaseBuffer(This->pOwner,(IMediaSample*)iface);
88 return 0;
93 static HRESULT WINAPI
94 IMediaSample2_fnGetPointer(IMediaSample2* iface,BYTE** ppData)
96 ICOM_THIS(CMemMediaSample,iface);
98 TRACE("(%p)->()\n",This);
100 if ( ppData == NULL )
101 return E_POINTER;
103 *ppData = This->prop.pbBuffer;
104 return NOERROR;
107 static long WINAPI
108 IMediaSample2_fnGetSize(IMediaSample2* iface)
110 ICOM_THIS(CMemMediaSample,iface);
112 TRACE("(%p)->()\n",This);
114 return This->prop.cbBuffer;
117 static HRESULT WINAPI
118 IMediaSample2_fnGetTime(IMediaSample2* iface,REFERENCE_TIME* prtStart,REFERENCE_TIME* prtEnd)
120 ICOM_THIS(CMemMediaSample,iface);
122 TRACE("(%p)->(%p,%p)\n",This,prtStart,prtEnd);
124 if ( prtStart == NULL || prtEnd == NULL )
125 return E_POINTER;
127 if ( ( This->prop.dwSampleFlags & AM_SAMPLE_TIMEVALID ) &&
128 ( This->prop.dwSampleFlags & AM_SAMPLE_STOPVALID ) )
130 *prtStart = This->prop.tStart;
131 *prtEnd = This->prop.tStop;
132 return NOERROR;
135 return VFW_E_MEDIA_TIME_NOT_SET;
138 static HRESULT WINAPI
139 IMediaSample2_fnSetTime(IMediaSample2* iface,REFERENCE_TIME* prtStart,REFERENCE_TIME* prtEnd)
141 ICOM_THIS(CMemMediaSample,iface);
143 TRACE("(%p)->(%p,%p) stub!\n",This,prtStart,prtEnd);
145 This->prop.dwSampleFlags &= ~(AM_SAMPLE_TIMEVALID|AM_SAMPLE_STOPVALID);
146 if ( prtStart != NULL )
148 This->prop.dwSampleFlags |= AM_SAMPLE_TIMEVALID;
149 This->prop.tStart = *prtStart;
151 if ( prtEnd != NULL )
153 This->prop.dwSampleFlags |= AM_SAMPLE_STOPVALID;
154 This->prop.tStop = *prtEnd;
157 return NOERROR;
160 static HRESULT WINAPI
161 IMediaSample2_fnIsSyncPoint(IMediaSample2* iface)
163 ICOM_THIS(CMemMediaSample,iface);
165 TRACE("(%p)->()\n",This);
167 return ( This->prop.dwSampleFlags & AM_SAMPLE_SPLICEPOINT ) ?
168 S_OK : S_FALSE;
171 static HRESULT WINAPI
172 IMediaSample2_fnSetSyncPoint(IMediaSample2* iface,BOOL bSync)
174 ICOM_THIS(CMemMediaSample,iface);
176 TRACE("(%p)->(%d)\n",This,bSync);
178 if ( bSync )
179 This->prop.dwSampleFlags |= AM_SAMPLE_SPLICEPOINT;
180 else
181 This->prop.dwSampleFlags &= ~AM_SAMPLE_SPLICEPOINT;
183 return NOERROR;
186 static HRESULT WINAPI
187 IMediaSample2_fnIsPreroll(IMediaSample2* iface)
189 ICOM_THIS(CMemMediaSample,iface);
191 TRACE("(%p)->()\n",This);
193 return ( This->prop.dwSampleFlags & AM_SAMPLE_PREROLL ) ?
194 S_OK : S_FALSE;
197 static HRESULT WINAPI
198 IMediaSample2_fnSetPreroll(IMediaSample2* iface,BOOL bPreroll)
200 ICOM_THIS(CMemMediaSample,iface);
202 TRACE("(%p)->(%d)\n",This,bPreroll);
204 if ( bPreroll )
205 This->prop.dwSampleFlags |= AM_SAMPLE_PREROLL;
206 else
207 This->prop.dwSampleFlags &= ~AM_SAMPLE_PREROLL;
209 return NOERROR;
212 static long WINAPI
213 IMediaSample2_fnGetActualDataLength(IMediaSample2* iface)
215 ICOM_THIS(CMemMediaSample,iface);
217 TRACE("(%p)->()\n",This);
219 return This->prop.lActual;
222 static HRESULT WINAPI
223 IMediaSample2_fnSetActualDataLength(IMediaSample2* iface,long lLength)
225 ICOM_THIS(CMemMediaSample,iface);
227 TRACE("(%p)->(%ld)\n",This,lLength);
229 if ( This->prop.cbBuffer > lLength )
230 return E_INVALIDARG;
232 This->prop.lActual = lLength;
233 return NOERROR;
236 static HRESULT WINAPI
237 IMediaSample2_fnGetMediaType(IMediaSample2* iface,AM_MEDIA_TYPE** ppmt)
239 ICOM_THIS(CMemMediaSample,iface);
241 TRACE("(%p)->(%p)\n",This,ppmt);
243 if ( ppmt == NULL )
244 return E_POINTER;
245 *ppmt = NULL;
246 if ( !(This->prop.dwSampleFlags & AM_SAMPLE_TYPECHANGED) )
247 return S_FALSE;
249 *ppmt = QUARTZ_MediaType_Duplicate( This->prop.pMediaType );
250 if ( *ppmt == NULL )
251 return E_OUTOFMEMORY;
253 return NOERROR;
256 static HRESULT WINAPI
257 IMediaSample2_fnSetMediaType(IMediaSample2* iface,AM_MEDIA_TYPE* pmt)
259 ICOM_THIS(CMemMediaSample,iface);
260 AM_MEDIA_TYPE* pmtDup;
262 TRACE("(%p)->(%p)\n",This,pmt);
264 if ( pmt == NULL )
266 /* FIXME? */
267 if ( This->prop.pMediaType != NULL )
269 QUARTZ_MediaType_Destroy( This->prop.pMediaType );
270 This->prop.pMediaType = NULL;
272 This->prop.dwSampleFlags &= ~AM_SAMPLE_TYPECHANGED;
273 return NOERROR;
276 pmtDup = QUARTZ_MediaType_Duplicate( pmt );
277 if ( pmtDup == NULL )
278 return E_OUTOFMEMORY;
280 if ( This->prop.pMediaType != NULL )
281 QUARTZ_MediaType_Destroy( This->prop.pMediaType );
282 This->prop.dwSampleFlags |= AM_SAMPLE_TYPECHANGED;
283 This->prop.pMediaType = pmtDup;
285 return NOERROR;
288 static HRESULT WINAPI
289 IMediaSample2_fnIsDiscontinuity(IMediaSample2* iface)
291 ICOM_THIS(CMemMediaSample,iface);
293 TRACE("(%p)->()\n",This);
295 return ( This->prop.dwSampleFlags & AM_SAMPLE_DATADISCONTINUITY ) ?
296 S_OK : S_FALSE;
299 static HRESULT WINAPI
300 IMediaSample2_fnSetDiscontinuity(IMediaSample2* iface,BOOL bDiscontinuity)
302 ICOM_THIS(CMemMediaSample,iface);
304 TRACE("(%p)->(%d)\n",This,bDiscontinuity);
306 if ( bDiscontinuity )
307 This->prop.dwSampleFlags |= AM_SAMPLE_DATADISCONTINUITY;
308 else
309 This->prop.dwSampleFlags &= ~AM_SAMPLE_DATADISCONTINUITY;
311 return NOERROR;
314 static HRESULT WINAPI
315 IMediaSample2_fnGetMediaTime(IMediaSample2* iface,LONGLONG* pTimeStart,LONGLONG* pTimeEnd)
317 ICOM_THIS(CMemMediaSample,iface);
319 TRACE("(%p)->(%p,%p)\n",This,pTimeStart,pTimeEnd);
321 if ( pTimeStart == NULL || pTimeEnd == NULL )
322 return E_POINTER;
324 if ( !This->fMediaTimeIsValid )
325 return VFW_E_MEDIA_TIME_NOT_SET;
327 *pTimeStart = This->llMediaTimeStart;
328 *pTimeEnd = This->llMediaTimeEnd;
330 return NOERROR;
332 return E_NOTIMPL;
335 static HRESULT WINAPI
336 IMediaSample2_fnSetMediaTime(IMediaSample2* iface,LONGLONG* pTimeStart,LONGLONG* pTimeEnd)
338 ICOM_THIS(CMemMediaSample,iface);
340 TRACE("(%p)->()\n",This);
341 if ( pTimeStart == NULL || pTimeEnd == NULL )
343 This->fMediaTimeIsValid = FALSE;
345 else
347 This->fMediaTimeIsValid = TRUE;
348 This->llMediaTimeStart = *pTimeStart;
349 This->llMediaTimeEnd = *pTimeEnd;
352 return NOERROR;
356 static HRESULT WINAPI
357 IMediaSample2_fnGetProperties(IMediaSample2* iface,DWORD cbProp,BYTE* pbProp)
359 ICOM_THIS(CMemMediaSample,iface);
361 TRACE("(%p)->(%lu,%p)\n",This,cbProp,pbProp);
363 if ( cbProp < 0 || cbProp > sizeof(AM_SAMPLE2_PROPERTIES) )
364 return E_FAIL;
365 memcpy( pbProp, &This->prop, cbProp );
367 return NOERROR;
370 static HRESULT WINAPI
371 IMediaSample2_fnSetProperties(IMediaSample2* iface,DWORD cbProp,const BYTE* pbProp)
373 ICOM_THIS(CMemMediaSample,iface);
374 const AM_SAMPLE2_PROPERTIES* pProp;
375 AM_SAMPLE2_PROPERTIES propNew;
376 AM_MEDIA_TYPE* pmtDup = NULL;
377 HRESULT hr = E_INVALIDARG;
379 TRACE("(%p)->(%lu,%p)\n",This,cbProp,pbProp);
381 if ( pbProp == NULL )
382 return E_POINTER;
383 pProp = (const AM_SAMPLE2_PROPERTIES*)pbProp;
384 if ( cbProp != sizeof(AM_SAMPLE2_PROPERTIES) )
385 goto err;
387 CopyMemory( &propNew, pProp, sizeof(AM_SAMPLE2_PROPERTIES) );
388 if ( propNew.cbData != sizeof(AM_SAMPLE2_PROPERTIES) )
389 goto err;
391 if ( This->prop.cbBuffer < propNew.lActual )
392 goto err;
394 if ( propNew.dwSampleFlags & AM_SAMPLE_TYPECHANGED )
396 pmtDup = QUARTZ_MediaType_Duplicate( propNew.pMediaType );
397 if ( pmtDup == NULL )
399 hr = E_OUTOFMEMORY;
400 goto err;
404 if ( propNew.pbBuffer != NULL && propNew.pbBuffer != This->prop.pbBuffer )
405 goto err;
406 if ( propNew.cbBuffer != 0 && propNew.cbBuffer != This->prop.cbBuffer )
407 goto err;
409 if ( This->prop.pMediaType != NULL )
410 QUARTZ_MediaType_Destroy( This->prop.pMediaType );
411 CopyMemory( &This->prop, &propNew, sizeof(AM_SAMPLE2_PROPERTIES) );
412 This->prop.pMediaType = pmtDup;
413 pmtDup = NULL;
415 hr= NOERROR;
416 err:
417 if ( pmtDup != NULL )
418 QUARTZ_MediaType_Destroy( pmtDup );
420 return hr;
424 static ICOM_VTABLE(IMediaSample2) imediasample2 =
426 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
427 /* IUnknown fields */
428 IMediaSample2_fnQueryInterface,
429 IMediaSample2_fnAddRef,
430 IMediaSample2_fnRelease,
431 /* IMediaSample fields */
432 IMediaSample2_fnGetPointer,
433 IMediaSample2_fnGetSize,
434 IMediaSample2_fnGetTime,
435 IMediaSample2_fnSetTime,
436 IMediaSample2_fnIsSyncPoint,
437 IMediaSample2_fnSetSyncPoint,
438 IMediaSample2_fnIsPreroll,
439 IMediaSample2_fnSetPreroll,
440 IMediaSample2_fnGetActualDataLength,
441 IMediaSample2_fnSetActualDataLength,
442 IMediaSample2_fnGetMediaType,
443 IMediaSample2_fnSetMediaType,
444 IMediaSample2_fnIsDiscontinuity,
445 IMediaSample2_fnSetDiscontinuity,
446 IMediaSample2_fnGetMediaTime,
447 IMediaSample2_fnSetMediaTime,
448 /* IMediaSample2 fields */
449 IMediaSample2_fnGetProperties,
450 IMediaSample2_fnSetProperties,
454 /***************************************************************************
456 * new/delete for CMemMediaSample
460 HRESULT QUARTZ_CreateMemMediaSample(
461 BYTE* pbData, DWORD dwDataLength,
462 IMemAllocator* pOwner,
463 CMemMediaSample** ppSample )
465 CMemMediaSample* pms;
467 TRACE("(%p,%08lx,%p,%p)\n",pbData,dwDataLength,pOwner,ppSample);
468 pms = (CMemMediaSample*)QUARTZ_AllocObj( sizeof(CMemMediaSample) );
469 if ( pms == NULL )
470 return E_OUTOFMEMORY;
472 ICOM_VTBL(pms) = &imediasample2;
473 pms->ref = 0;
474 pms->pOwner = pOwner;
475 pms->fMediaTimeIsValid = FALSE;
476 pms->llMediaTimeStart = 0;
477 pms->llMediaTimeEnd = 0;
478 ZeroMemory( &(pms->prop), sizeof(pms->prop) );
479 pms->prop.cbData = sizeof(pms->prop);
480 pms->prop.dwTypeSpecificFlags = 0;
481 pms->prop.dwSampleFlags = 0;
482 pms->prop.pbBuffer = pbData;
483 pms->prop.cbBuffer = (LONG)dwDataLength;
484 pms->prop.lActual = (LONG)dwDataLength;
486 *ppSample = pms;
488 return S_OK;
491 void QUARTZ_DestroyMemMediaSample(
492 CMemMediaSample* pSample )
494 TRACE("(%p)\n",pSample);
496 QUARTZ_FreeObj( pSample );