Use DrawFrameControl instead of bitmaps in certain cases.
[wine] / dlls / quartz / sample.c
1 /*
2  * Implements IMediaSample2 for CMemMediaSample.
3  *
4  * hidenori@a2.ctktv.ne.jp
5  */
6
7 #include "config.h"
8
9 #include "windef.h"
10 #include "winbase.h"
11 #include "wingdi.h"
12 #include "winuser.h"
13 #include "winerror.h"
14 #include "strmif.h"
15 #include "vfwmsgs.h"
16
17 #include "debugtools.h"
18 DEFAULT_DEBUG_CHANNEL(quartz);
19
20 #include "quartz_private.h"
21 #include "sample.h"
22 #include "mtype.h"
23
24
25 /***************************************************************************
26  *
27  *      Helper functions
28  *
29  */
30
31 HRESULT QUARTZ_IMediaSample_GetProperties(
32         IMediaSample* pSample,
33         AM_SAMPLE2_PROPERTIES* pProp )
34 {
35         HRESULT hr;
36         AM_SAMPLE2_PROPERTIES   prop;
37         IMediaSample2*  pSample2 = NULL;
38
39         ZeroMemory( &prop, sizeof(AM_SAMPLE2_PROPERTIES) );
40
41 #if 0 /* not yet */
42         hr = IMediaSample_QueryInterface( pSample, &IID_IMediaSample2, (void**)&pSample2 );
43         if ( hr == S_OK )
44         {
45                 hr = IMediaSample2_GetProperties(pSample2,sizeof(AM_SAMPLE2_PROPERTIES),&prop);
46                 IMediaSample2_Release(pSample2);
47                 if ( hr == S_OK )
48                 {
49                         memcpy( pProp, &prop, sizeof(AM_SAMPLE2_PROPERTIES) );
50                         pProp->pMediaType =
51                                 QUARTZ_MediaType_Duplicate( &prop.pMediaType );
52
53                         return NOERROR;
54                 }
55         }
56 #endif
57
58         pProp->cbData = sizeof(AM_SAMPLE2_PROPERTIES);
59         pProp->dwTypeSpecificFlags = 0;
60         pProp->dwSampleFlags = 0;
61         if ( IMediaSample_IsSyncPoint(pSample) == S_OK )
62                 pProp->dwSampleFlags |= AM_SAMPLE_SPLICEPOINT;
63         if ( IMediaSample_IsPreroll(pSample) == S_OK )
64                 pProp->dwSampleFlags |= AM_SAMPLE_PREROLL;
65         if ( IMediaSample_IsDiscontinuity(pSample) == S_OK )
66                 pProp->dwSampleFlags |= AM_SAMPLE_DATADISCONTINUITY;
67         pProp->lActual = (LONG)IMediaSample_GetActualDataLength(pSample);
68         if ( IMediaSample_GetTime(pSample,&pProp->tStart,&pProp->tStop) == S_OK )
69                 pProp->dwSampleFlags |= AM_SAMPLE_TIMEVALID | AM_SAMPLE_STOPVALID;
70         pProp->dwStreamId = 0;
71         if ( IMediaSample_GetMediaType(pSample,&(pProp->pMediaType)) == S_OK )
72                 pProp->dwSampleFlags |= AM_SAMPLE_TYPECHANGED;
73         IMediaSample_GetPointer(pSample,&(pProp->pbBuffer));
74         pProp->cbBuffer = (LONG)IMediaSample_GetSize(pSample);
75
76         return NOERROR;
77 }
78
79 HRESULT QUARTZ_IMediaSample_SetProperties(
80         IMediaSample* pSample,
81         const AM_SAMPLE2_PROPERTIES* pProp )
82 {
83         HRESULT hr;
84         AM_SAMPLE2_PROPERTIES   prop;
85         IMediaSample2*  pSample2 = NULL;
86
87         memcpy( &prop, pProp, sizeof(AM_SAMPLE2_PROPERTIES) );
88         prop.cbData = sizeof(AM_SAMPLE2_PROPERTIES);
89         prop.pbBuffer = NULL;
90         prop.cbBuffer = 0;
91
92 #if 0 /* not yet */
93         hr = IMediaSample_QueryInterface( pSample, &IID_IMediaSample2, (void**)&pSample2 );
94         if ( hr == S_OK )
95         {
96                 hr = IMediaSample2_SetProperties(pSample2,sizeof(AM_SAMPLE2_PROPERTIES),&prop);
97                 IMediaSample2_Release(pSample2);
98                 if ( hr == S_OK )
99                         return NOERROR;
100         }
101 #endif
102
103         hr = S_OK;
104
105         if ( SUCCEEDED(hr) )
106                 hr = IMediaSample_SetSyncPoint(pSample,
107                         (prop.dwSampleFlags & AM_SAMPLE_SPLICEPOINT) ? TRUE : FALSE);
108         if ( SUCCEEDED(hr) )
109                 hr = IMediaSample_SetPreroll(pSample,
110                         (prop.dwSampleFlags & AM_SAMPLE_PREROLL) ? TRUE : FALSE);
111         if ( SUCCEEDED(hr) )
112                 hr = IMediaSample_SetDiscontinuity(pSample,
113                         (prop.dwSampleFlags & AM_SAMPLE_DATADISCONTINUITY) ? TRUE : FALSE);
114         if ( SUCCEEDED(hr) )
115         {
116                 TRACE("length = %ld/%ld\n",prop.lActual,pProp->cbBuffer);
117                 hr = IMediaSample_SetActualDataLength(pSample,prop.lActual);
118         }
119         if ( SUCCEEDED(hr) )
120         {
121                 if ( ( prop.dwSampleFlags & AM_SAMPLE_TIMEVALID) &&
122                      ( prop.dwSampleFlags & AM_SAMPLE_STOPVALID) )
123                         hr = IMediaSample_SetTime(pSample,&prop.tStart,&prop.tStop);
124                 else
125                         hr = IMediaSample_SetTime(pSample,NULL,NULL);
126         }
127         if ( SUCCEEDED(hr) )
128                 hr = IMediaSample_SetMediaType(pSample,
129                         (prop.dwSampleFlags & AM_SAMPLE_TYPECHANGED) ?
130                                 prop.pMediaType : NULL);
131
132         return hr;
133 }
134
135 HRESULT QUARTZ_IMediaSample_Copy(
136         IMediaSample* pDstSample,
137         IMediaSample* pSrcSample,
138         BOOL bCopyData )
139 {
140         HRESULT hr;
141         AM_SAMPLE2_PROPERTIES   prop;
142         BYTE* pDataSrc = NULL;
143         BYTE* pDataDst = NULL;
144
145         hr = QUARTZ_IMediaSample_GetProperties( pSrcSample, &prop );
146         if ( FAILED(hr) )
147                 return hr;
148         if ( !bCopyData )
149                 prop.lActual = 0;
150         hr = QUARTZ_IMediaSample_SetProperties( pDstSample, &prop );
151         if ( prop.pMediaType != NULL )
152                 QUARTZ_MediaType_Destroy( prop.pMediaType );
153
154         if ( SUCCEEDED(hr) && bCopyData )
155         {
156                 hr = IMediaSample_GetPointer(pSrcSample,&pDataSrc);
157                 if ( SUCCEEDED(hr) )
158                         hr = IMediaSample_GetPointer(pDstSample,&pDataDst);
159                 if ( SUCCEEDED(hr) )
160                 {
161                         if ( pDataSrc != NULL && pDataDst != NULL )
162                                 memcpy( pDataDst, pDataSrc, prop.lActual );
163                         else
164                                 hr = E_FAIL;
165                 }
166         }
167
168         return hr;
169 }
170
171 /***************************************************************************
172  *
173  *      CMemMediaSample::IMediaSample2
174  *
175  */
176
177 static HRESULT WINAPI
178 IMediaSample2_fnQueryInterface(IMediaSample2* iface,REFIID riid,void** ppobj)
179 {
180         ICOM_THIS(CMemMediaSample,iface);
181
182         TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
183
184         if ( ppobj == NULL )
185                 return E_POINTER;
186
187         if ( IsEqualGUID( riid, &IID_IUnknown ) ||
188              IsEqualGUID( riid, &IID_IMediaSample ) ||
189              IsEqualGUID( riid, &IID_IMediaSample2 ) )
190         {
191                 *ppobj = iface;
192                 IMediaSample2_AddRef(iface);
193                 return NOERROR;
194         }
195
196         return E_NOINTERFACE;
197 }
198
199 static ULONG WINAPI
200 IMediaSample2_fnAddRef(IMediaSample2* iface)
201 {
202         ICOM_THIS(CMemMediaSample,iface);
203
204         TRACE("(%p)->()\n",This);
205
206         return InterlockedExchangeAdd(&(This->ref),1) + 1;
207 }
208
209 static ULONG WINAPI
210 IMediaSample2_fnRelease(IMediaSample2* iface)
211 {
212         ICOM_THIS(CMemMediaSample,iface);
213         LONG    ref;
214
215         TRACE("(%p)->()\n",This);
216
217         if ( This->ref == 0 )
218         {
219                 ERR("(%p) - released sample!\n",This);
220                 return 0;
221         }
222
223         ref = InterlockedExchangeAdd(&(This->ref),-1) - 1;
224         if ( ref > 0 )
225                 return (ULONG)ref;
226
227         /* this class would be reused.. */
228         if ( This->prop.pMediaType != NULL )
229         {
230                 QUARTZ_MediaType_Destroy( This->prop.pMediaType );
231                 This->prop.pMediaType = NULL;
232         }
233         This->prop.dwTypeSpecificFlags = 0;
234         This->prop.dwSampleFlags = 0;
235         This->prop.lActual = This->prop.cbBuffer;
236
237         IMemAllocator_ReleaseBuffer(This->pOwner,(IMediaSample*)iface);
238
239         return 0;
240 }
241
242
243
244 static HRESULT WINAPI
245 IMediaSample2_fnGetPointer(IMediaSample2* iface,BYTE** ppData)
246 {
247         ICOM_THIS(CMemMediaSample,iface);
248
249         TRACE("(%p)->()\n",This);
250
251         if ( This->ref == 0 )
252         {
253                 ERR("(%p) - released sample!\n",This);
254                 return E_UNEXPECTED;
255         }
256
257         if ( ppData == NULL )
258                 return E_POINTER;
259
260         *ppData = This->prop.pbBuffer;
261         return NOERROR;
262 }
263
264 static long WINAPI
265 IMediaSample2_fnGetSize(IMediaSample2* iface)
266 {
267         ICOM_THIS(CMemMediaSample,iface);
268
269         TRACE("(%p)->()\n",This);
270
271         return This->prop.cbBuffer;
272 }
273
274 static HRESULT WINAPI
275 IMediaSample2_fnGetTime(IMediaSample2* iface,REFERENCE_TIME* prtStart,REFERENCE_TIME* prtEnd)
276 {
277         ICOM_THIS(CMemMediaSample,iface);
278
279         TRACE("(%p)->(%p,%p)\n",This,prtStart,prtEnd);
280
281         if ( This->ref == 0 )
282         {
283                 ERR("(%p) - released sample!\n",This);
284                 return E_UNEXPECTED;
285         }
286
287         if ( prtStart == NULL || prtEnd == NULL )
288                 return E_POINTER;
289
290         if ( ( This->prop.dwSampleFlags & AM_SAMPLE_TIMEVALID ) &&
291                  ( This->prop.dwSampleFlags & AM_SAMPLE_STOPVALID ) )
292         {
293                 *prtStart = This->prop.tStart;
294                 *prtEnd = This->prop.tStop;
295                 return NOERROR;
296         }
297
298         return VFW_E_MEDIA_TIME_NOT_SET;
299 }
300
301 static HRESULT WINAPI
302 IMediaSample2_fnSetTime(IMediaSample2* iface,REFERENCE_TIME* prtStart,REFERENCE_TIME* prtEnd)
303 {
304         ICOM_THIS(CMemMediaSample,iface);
305
306         TRACE("(%p)->(%p,%p) stub!\n",This,prtStart,prtEnd);
307
308         This->prop.dwSampleFlags &= ~(AM_SAMPLE_TIMEVALID|AM_SAMPLE_STOPVALID);
309         if ( prtStart != NULL )
310         {
311                 This->prop.dwSampleFlags |= AM_SAMPLE_TIMEVALID;
312                 This->prop.tStart = *prtStart;
313         }
314         if ( prtEnd != NULL )
315         {
316                 This->prop.dwSampleFlags |= AM_SAMPLE_STOPVALID;
317                 This->prop.tStop = *prtEnd;
318         }
319
320         return NOERROR;
321 }
322
323 static HRESULT WINAPI
324 IMediaSample2_fnIsSyncPoint(IMediaSample2* iface)
325 {
326         ICOM_THIS(CMemMediaSample,iface);
327
328         TRACE("(%p)->()\n",This);
329
330         return ( This->prop.dwSampleFlags & AM_SAMPLE_SPLICEPOINT ) ?
331                                                 S_OK : S_FALSE;
332 }
333
334 static HRESULT WINAPI
335 IMediaSample2_fnSetSyncPoint(IMediaSample2* iface,BOOL bSync)
336 {
337         ICOM_THIS(CMemMediaSample,iface);
338
339         TRACE("(%p)->(%d)\n",This,bSync);
340
341         if ( bSync )
342                 This->prop.dwSampleFlags |= AM_SAMPLE_SPLICEPOINT;
343         else
344                 This->prop.dwSampleFlags &= ~AM_SAMPLE_SPLICEPOINT;
345
346         return NOERROR;
347 }
348
349 static HRESULT WINAPI
350 IMediaSample2_fnIsPreroll(IMediaSample2* iface)
351 {
352         ICOM_THIS(CMemMediaSample,iface);
353
354         TRACE("(%p)->()\n",This);
355
356         return ( This->prop.dwSampleFlags & AM_SAMPLE_PREROLL ) ?
357                                                 S_OK : S_FALSE;
358 }
359
360 static HRESULT WINAPI
361 IMediaSample2_fnSetPreroll(IMediaSample2* iface,BOOL bPreroll)
362 {
363         ICOM_THIS(CMemMediaSample,iface);
364
365         TRACE("(%p)->(%d)\n",This,bPreroll);
366
367         if ( bPreroll )
368                 This->prop.dwSampleFlags |= AM_SAMPLE_PREROLL;
369         else
370                 This->prop.dwSampleFlags &= ~AM_SAMPLE_PREROLL;
371
372         return NOERROR;
373 }
374
375 static long WINAPI
376 IMediaSample2_fnGetActualDataLength(IMediaSample2* iface)
377 {
378         ICOM_THIS(CMemMediaSample,iface);
379
380         TRACE("(%p)->()\n",This);
381
382         return This->prop.lActual;
383 }
384
385 static HRESULT WINAPI
386 IMediaSample2_fnSetActualDataLength(IMediaSample2* iface,long lLength)
387 {
388         ICOM_THIS(CMemMediaSample,iface);
389
390         TRACE("(%p)->(%ld)\n",This,lLength);
391
392         if ( This->prop.cbBuffer < lLength )
393                 return E_INVALIDARG;
394
395         This->prop.lActual = lLength;
396         return NOERROR;
397 }
398
399 static HRESULT WINAPI
400 IMediaSample2_fnGetMediaType(IMediaSample2* iface,AM_MEDIA_TYPE** ppmt)
401 {
402         ICOM_THIS(CMemMediaSample,iface);
403
404         TRACE("(%p)->(%p)\n",This,ppmt);
405
406         if ( ppmt == NULL )
407                 return E_POINTER;
408         *ppmt = NULL;
409         if ( !(This->prop.dwSampleFlags & AM_SAMPLE_TYPECHANGED) )
410                 return S_FALSE;
411
412         *ppmt = QUARTZ_MediaType_Duplicate( This->prop.pMediaType );
413         if ( *ppmt == NULL )
414                 return E_OUTOFMEMORY;
415
416         return NOERROR;
417 }
418
419 static HRESULT WINAPI
420 IMediaSample2_fnSetMediaType(IMediaSample2* iface,AM_MEDIA_TYPE* pmt)
421 {
422         ICOM_THIS(CMemMediaSample,iface);
423         AM_MEDIA_TYPE* pmtDup;
424
425         TRACE("(%p)->(%p)\n",This,pmt);
426
427         if ( pmt == NULL )
428         {
429                 /* FIXME? */
430                 if ( This->prop.pMediaType != NULL )
431                 {
432                         QUARTZ_MediaType_Destroy( This->prop.pMediaType );
433                         This->prop.pMediaType = NULL;
434                 }
435                 This->prop.dwSampleFlags &= ~AM_SAMPLE_TYPECHANGED;
436                 return NOERROR;
437         }
438
439         pmtDup = QUARTZ_MediaType_Duplicate( pmt );
440         if ( pmtDup == NULL )
441                 return E_OUTOFMEMORY;
442
443         if ( This->prop.pMediaType != NULL )
444                 QUARTZ_MediaType_Destroy( This->prop.pMediaType );
445         This->prop.dwSampleFlags |= AM_SAMPLE_TYPECHANGED;
446         This->prop.pMediaType = pmtDup;
447
448         return NOERROR;
449 }
450
451 static HRESULT WINAPI
452 IMediaSample2_fnIsDiscontinuity(IMediaSample2* iface)
453 {
454         ICOM_THIS(CMemMediaSample,iface);
455
456         TRACE("(%p)->()\n",This);
457
458         return ( This->prop.dwSampleFlags & AM_SAMPLE_DATADISCONTINUITY ) ?
459                                                 S_OK : S_FALSE;
460 }
461
462 static HRESULT WINAPI
463 IMediaSample2_fnSetDiscontinuity(IMediaSample2* iface,BOOL bDiscontinuity)
464 {
465         ICOM_THIS(CMemMediaSample,iface);
466
467         TRACE("(%p)->(%d)\n",This,bDiscontinuity);
468
469         if ( bDiscontinuity )
470                 This->prop.dwSampleFlags |= AM_SAMPLE_DATADISCONTINUITY;
471         else
472                 This->prop.dwSampleFlags &= ~AM_SAMPLE_DATADISCONTINUITY;
473
474         return NOERROR;
475 }
476
477 static HRESULT WINAPI
478 IMediaSample2_fnGetMediaTime(IMediaSample2* iface,LONGLONG* pTimeStart,LONGLONG* pTimeEnd)
479 {
480         ICOM_THIS(CMemMediaSample,iface);
481
482         TRACE("(%p)->(%p,%p)\n",This,pTimeStart,pTimeEnd);
483
484         if ( pTimeStart == NULL || pTimeEnd == NULL )
485                 return E_POINTER;
486
487         if ( !This->fMediaTimeIsValid )
488                 return VFW_E_MEDIA_TIME_NOT_SET;
489
490         *pTimeStart = This->llMediaTimeStart;
491         *pTimeEnd = This->llMediaTimeEnd;
492
493         return NOERROR;
494
495         return E_NOTIMPL;
496 }
497
498 static HRESULT WINAPI
499 IMediaSample2_fnSetMediaTime(IMediaSample2* iface,LONGLONG* pTimeStart,LONGLONG* pTimeEnd)
500 {
501         ICOM_THIS(CMemMediaSample,iface);
502
503         TRACE("(%p)->()\n",This);
504         if ( pTimeStart == NULL || pTimeEnd == NULL )
505         {
506                 This->fMediaTimeIsValid = FALSE;
507         }
508         else
509         {
510                 This->fMediaTimeIsValid = TRUE;
511                 This->llMediaTimeStart = *pTimeStart;
512                 This->llMediaTimeEnd = *pTimeEnd;
513         }
514
515         return NOERROR;
516 }
517
518
519 static HRESULT WINAPI
520 IMediaSample2_fnGetProperties(IMediaSample2* iface,DWORD cbProp,BYTE* pbProp)
521 {
522         ICOM_THIS(CMemMediaSample,iface);
523
524         TRACE("(%p)->(%lu,%p)\n",This,cbProp,pbProp);
525
526         if ( cbProp < 0 || cbProp > sizeof(AM_SAMPLE2_PROPERTIES) )
527                 return E_FAIL;
528         memcpy( pbProp, &This->prop, cbProp );
529
530         return NOERROR;
531 }
532
533 static HRESULT WINAPI
534 IMediaSample2_fnSetProperties(IMediaSample2* iface,DWORD cbProp,const BYTE* pbProp)
535 {
536         ICOM_THIS(CMemMediaSample,iface);
537         const AM_SAMPLE2_PROPERTIES* pProp;
538         AM_SAMPLE2_PROPERTIES propNew;
539         AM_MEDIA_TYPE* pmtDup = NULL;
540         HRESULT hr = E_INVALIDARG;
541
542         TRACE("(%p)->(%lu,%p)\n",This,cbProp,pbProp);
543
544         if ( pbProp == NULL )
545                 return E_POINTER;
546         pProp = (const AM_SAMPLE2_PROPERTIES*)pbProp;
547         if ( cbProp != sizeof(AM_SAMPLE2_PROPERTIES) )
548                 goto err;
549
550         CopyMemory( &propNew, pProp, sizeof(AM_SAMPLE2_PROPERTIES) );
551         if ( propNew.cbData != sizeof(AM_SAMPLE2_PROPERTIES) )
552                 goto err;
553
554         if ( This->prop.cbBuffer < propNew.lActual )
555                 goto err;
556
557         if ( propNew.dwSampleFlags & AM_SAMPLE_TYPECHANGED )
558         {
559                 pmtDup = QUARTZ_MediaType_Duplicate( propNew.pMediaType );
560                 if ( pmtDup == NULL )
561                 {
562                         hr = E_OUTOFMEMORY;
563                         goto err;
564                 }
565         }
566
567         if ( propNew.pbBuffer != NULL && propNew.pbBuffer != This->prop.pbBuffer )
568                 goto err;
569         if ( propNew.cbBuffer != 0 && propNew.cbBuffer != This->prop.cbBuffer )
570                 goto err;
571
572         if ( This->prop.pMediaType != NULL )
573                 QUARTZ_MediaType_Destroy( This->prop.pMediaType );
574         CopyMemory( &This->prop, &propNew, sizeof(AM_SAMPLE2_PROPERTIES) );
575         This->prop.pMediaType = pmtDup;
576         pmtDup = NULL;
577
578         hr= NOERROR;
579 err:
580         if ( pmtDup != NULL )
581                 QUARTZ_MediaType_Destroy( pmtDup );
582
583         return hr;
584 }
585
586
587 static ICOM_VTABLE(IMediaSample2) imediasample2 =
588 {
589         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
590         /* IUnknown fields */
591         IMediaSample2_fnQueryInterface,
592         IMediaSample2_fnAddRef,
593         IMediaSample2_fnRelease,
594         /* IMediaSample fields */
595         IMediaSample2_fnGetPointer,
596         IMediaSample2_fnGetSize,
597         IMediaSample2_fnGetTime,
598         IMediaSample2_fnSetTime,
599         IMediaSample2_fnIsSyncPoint,
600         IMediaSample2_fnSetSyncPoint,
601         IMediaSample2_fnIsPreroll,
602         IMediaSample2_fnSetPreroll,
603         IMediaSample2_fnGetActualDataLength,
604         IMediaSample2_fnSetActualDataLength,
605         IMediaSample2_fnGetMediaType,
606         IMediaSample2_fnSetMediaType,
607         IMediaSample2_fnIsDiscontinuity,
608         IMediaSample2_fnSetDiscontinuity,
609         IMediaSample2_fnGetMediaTime,
610         IMediaSample2_fnSetMediaTime,
611         /* IMediaSample2 fields */
612         IMediaSample2_fnGetProperties,
613         IMediaSample2_fnSetProperties,
614 };
615
616
617 /***************************************************************************
618  *
619  *      new/delete for CMemMediaSample
620  *
621  */
622
623 HRESULT QUARTZ_CreateMemMediaSample(
624         BYTE* pbData, DWORD dwDataLength,
625         IMemAllocator* pOwner,
626         CMemMediaSample** ppSample )
627 {
628         CMemMediaSample*        pms;
629
630         TRACE("(%p,%08lx,%p,%p)\n",pbData,dwDataLength,pOwner,ppSample);
631         pms = (CMemMediaSample*)QUARTZ_AllocObj( sizeof(CMemMediaSample) );
632         if ( pms == NULL )
633                 return E_OUTOFMEMORY;
634
635         ICOM_VTBL(pms) = &imediasample2;
636         pms->ref = 0;
637         pms->pOwner = pOwner;
638         pms->fMediaTimeIsValid = FALSE;
639         pms->llMediaTimeStart = 0;
640         pms->llMediaTimeEnd = 0;
641         ZeroMemory( &(pms->prop), sizeof(pms->prop) );
642         pms->prop.cbData = sizeof(pms->prop);
643         pms->prop.dwTypeSpecificFlags = 0;
644         pms->prop.dwSampleFlags = 0;
645         pms->prop.pbBuffer = pbData;
646         pms->prop.cbBuffer = (LONG)dwDataLength;
647         pms->prop.lActual = (LONG)dwDataLength;
648
649         *ppSample = pms;
650
651         return S_OK;
652 }
653
654 void QUARTZ_DestroyMemMediaSample(
655         CMemMediaSample* pSample )
656 {
657         TRACE("(%p)\n",pSample);
658
659         QUARTZ_FreeObj( pSample );
660 }
661