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