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