1 ///////////////////////////////////////////////////////////////////////////////
2 // $Source: x:/prj/tech/libsrc/actmovie/RCS/amalloc.cpp $
4 // $Date: 1996/09/18 11:32:28 $
23 ///////////////////////////////////////////////////////////////////////////////
25 // @Note (toml 09-06-96): The following are HACKS to get this file to compiler
28 // @TBD (toml 09-06-96): Thse macros are placeholders for things in mtype.*, which needs to be imported (?)
29 #define DeleteMediaType(p)
30 #define CreateMediaType(p) (p)
32 // @TBD (toml 09-06-96): these are things from wxutil
33 #define ValidateReadPtr(p,cb)
34 #define ValidateWritePtr(p,cb)
35 #define ValidateReadWritePtr(p,cb)
36 #define ValidateStringPtr(p)
37 #define ValidateStringPtrA(p)
38 #define ValidateStringPtrW(p)
40 // @TBD (toml 09-06-96): From wxdebug
41 #define CheckPointer(p,ret) {if((p)==NULL) return (ret);}
48 ///////////////////////////////////////////////////////////////////////////////
50 // CLASS: cMediaSample
52 // Memory allocation class, implements cMediaSample
55 ///////////////////////////////////////
57 // Pre-fab COM implementations
60 IMPLEMENT_UNAGGREGATABLE(cMediaSample
, IMediaSample
);
62 ///////////////////////////////////////
64 #pragma off(unreferenced)
65 cMediaSample::cMediaSample(char *pName
,
66 cBaseAllocator
* pAllocator
,
70 : m_pBuffer(pBuffer
), // Initialise the buffer
71 m_cbBuffer(length
), // And it's length
72 m_lActual(length
), // By default, actual = length
73 m_pMediaType(NULL
), // No media type change
74 m_dwFlags(0) // Nothing set
76 /* We must have an owner and it must also be derived from class cBaseAllocator BUT we do not hold a reference count on it */
77 m_pAllocator
= pAllocator
;
80 if (pAllocator
== NULL
)
82 *phr
= VFW_E_NEED_OWNER
;
85 #pragma on(unreferenced)
88 ///////////////////////////////////////
90 cMediaSample::~cMediaSample()
94 DeleteMediaType(m_pMediaType
);
100 ///////////////////////////////////////
102 // On final release of this sample buffer it is not deleted but
103 // returned to the freelist of the owning memory allocator
105 // The allocator may be waiting for the last buffer to be placed on the free
106 // list in order to decommit all the memory, so the ReleaseBuffer() call may
107 // result in this sample being deleted. We also need to hold a refcount on
108 // the allocator to stop that going away until we have finished with this.
109 // However, we cannot release the allocator before the ReleaseBuffer, as the
110 // release may cause us to be deleted. Similarly we can't do it afterwards.
112 // Thus we must leave it to the allocator to hold an addref on our behalf.
113 // When he issues us in GetBuffer, he addref's himself. When ReleaseBuffer
114 // is called, he releases himself, possibly causing us and him to be deleted.
116 void cMediaSample::OnFinalRelease()
118 /* Free all resources */
122 /* This may cause us to be deleted */
123 // Our refcount is reliably 0 thus no-one will mess with us
124 m_pAllocator
->ReleaseBuffer(this);
128 ///////////////////////////////////////
130 // set the buffer pointer and length. Used by allocators that
131 // want variable sized pointers or pointers into already-read data.
132 // This is only available through a cMediaSample* not an IMediaSample*
133 // and so cannot be changed by clients.
136 HRESULT
cMediaSample::SetPointer(BYTE
* ptr
, long cBytes
)
138 m_pBuffer
= ptr
; // new buffer area (could be null)
139 m_cbBuffer
= cBytes
; // length of buffer
140 m_lActual
= cBytes
; // length of data in buffer (assume full)
146 ///////////////////////////////////////
148 // get me a read/write pointer to this buffer's memory. I will actually
149 // want to use sizeUsed bytes.
152 STDMETHODIMP
cMediaSample::GetPointer(BYTE
** ppBuffer
)
154 CheckPointer(ppBuffer
, E_POINTER
);
155 ValidateReadWritePtr(ppBuffer
, sizeof(BYTE
*));
157 // creator must have set pointer either during
158 // constructor or by SetPointer
162 return VFW_E_BUFFER_NOTSET
;
165 *ppBuffer
= m_pBuffer
;
170 ///////////////////////////////////////
172 // return the size in bytes of this buffer
175 STDMETHODIMP_(long) cMediaSample::GetSize(void)
181 ///////////////////////////////////////
183 // get the stream time at which this sample should start and finish.
186 STDMETHODIMP
cMediaSample::GetTime(REFERENCE_TIME
* pTimeStart
, // put time here
187 REFERENCE_TIME
* pTimeEnd
)
189 CheckPointer(pTimeStart
, E_POINTER
);
190 CheckPointer(pTimeEnd
, E_POINTER
);
191 ValidateReadWritePtr(pTimeStart
, sizeof(REFERENCE_TIME
));
192 ValidateReadWritePtr(pTimeEnd
, sizeof(REFERENCE_TIME
));
194 if (!(m_dwFlags
& Sample_TimeValid
))
196 return VFW_E_SAMPLE_TIME_NOT_SET
;
199 *pTimeStart
= m_Start
;
205 ///////////////////////////////////////
207 // Set the stream time at which this sample should start and finish.
209 STDMETHODIMP
cMediaSample::SetTime(REFERENCE_TIME
* pTimeStart
,
210 REFERENCE_TIME
* pTimeEnd
)
212 if (!pTimeStart
|| !pTimeEnd
)
214 if (!pTimeStart
&& !pTimeEnd
)
216 m_dwFlags
&= ~Sample_TimeValid
;
220 CheckPointer(pTimeStart
, E_POINTER
);
221 CheckPointer(pTimeEnd
, E_POINTER
);
226 ValidateReadPtr(pTimeStart
, sizeof(REFERENCE_TIME
));
227 ValidateReadPtr(pTimeEnd
, sizeof(REFERENCE_TIME
));
228 Assert_(*pTimeEnd
>= *pTimeStart
);
230 m_Start
= *pTimeStart
;
232 m_dwFlags
|= Sample_TimeValid
;
238 ///////////////////////////////////////
240 // get the media times (eg bytes) for this sample
243 STDMETHODIMP
cMediaSample::GetMediaTime(LONGLONG
* pTimeStart
,
246 CheckPointer(pTimeStart
, E_POINTER
);
247 CheckPointer(pTimeEnd
, E_POINTER
);
248 ValidateReadWritePtr(pTimeStart
, sizeof(LONGLONG
));
249 ValidateReadWritePtr(pTimeEnd
, sizeof(LONGLONG
));
251 if (!(m_dwFlags
& Sample_MediaTimeValid
))
253 return VFW_E_MEDIA_TIME_NOT_SET
;
256 *pTimeStart
= m_MediaStart
;
257 *pTimeEnd
= (m_MediaStart
+ m_MediaEnd
);
262 ///////////////////////////////////////
264 // Set the media times for this sample
267 STDMETHODIMP
cMediaSample::SetMediaTime(LONGLONG
* pTimeStart
,
270 if (!pTimeStart
&& !pTimeEnd
)
272 m_dwFlags
&= ~Sample_MediaTimeValid
;
276 CheckPointer(pTimeStart
, E_POINTER
);
277 CheckPointer(pTimeEnd
, E_POINTER
);
278 ValidateReadPtr(pTimeStart
, sizeof(LONGLONG
));
279 ValidateReadPtr(pTimeEnd
, sizeof(LONGLONG
));
280 Assert_(*pTimeEnd
>= *pTimeStart
);
282 m_MediaStart
= *pTimeStart
;
283 m_MediaEnd
= (long) (*pTimeEnd
- *pTimeStart
);
284 m_dwFlags
|= Sample_MediaTimeValid
;
290 ///////////////////////////////////////
292 STDMETHODIMP
cMediaSample::IsSyncPoint(void)
294 if (m_dwFlags
& Sample_SyncPoint
)
305 ///////////////////////////////////////
307 STDMETHODIMP
cMediaSample::SetSyncPoint(BOOL bIsSyncPoint
)
311 m_dwFlags
|= Sample_SyncPoint
;
315 m_dwFlags
&= ~Sample_SyncPoint
;
320 ///////////////////////////////////////
322 // returns S_OK if there is a discontinuity in the data (this same is
323 // not a continuation of the previous stream of data
324 // - there has been a seek).
327 STDMETHODIMP
cMediaSample::IsDiscontinuity(void)
329 if (m_dwFlags
& Sample_Discontinuity
)
339 ///////////////////////////////////////
341 // set the discontinuity property - TRUE if this sample is not a
342 // continuation, but a new sample after a seek.
345 STDMETHODIMP
cMediaSample::SetDiscontinuity(BOOL bDiscont
)
347 // should be TRUE or FALSE
350 m_dwFlags
|= Sample_Discontinuity
;
354 m_dwFlags
&= ~Sample_Discontinuity
;
359 ///////////////////////////////////////
361 STDMETHODIMP
cMediaSample::IsPreroll(void)
363 if (m_dwFlags
& Sample_Preroll
)
374 ///////////////////////////////////////
376 STDMETHODIMP
cMediaSample::SetPreroll(BOOL bIsPreroll
)
380 m_dwFlags
|= Sample_Preroll
;
384 m_dwFlags
&= ~Sample_Preroll
;
389 ///////////////////////////////////////
391 STDMETHODIMP_(long) cMediaSample::GetActualDataLength(void)
397 ///////////////////////////////////////
399 STDMETHODIMP
cMediaSample::SetActualDataLength(long lActual
)
401 if (lActual
> GetSize())
403 Assert_(lActual
<= GetSize());
404 return VFW_E_BUFFER_OVERFLOW
;
411 ///////////////////////////////////////
413 STDMETHODIMP
cMediaSample::GetMediaType(AM_MEDIA_TYPE
** ppMediaType
)
415 CheckPointer(ppMediaType
, E_POINTER
);
416 ValidateReadWritePtr(ppMediaType
, sizeof(AM_MEDIA_TYPE
*));
417 Assert_(ppMediaType
);
419 /* Do we have a new media type for them */
421 if (!(m_dwFlags
& Sample_TypeChanged
))
423 Assert_(m_pMediaType
== NULL
);
428 Assert_(m_pMediaType
);
430 /* Create a copy of our media type */
432 *ppMediaType
= CreateMediaType(m_pMediaType
);
433 if (*ppMediaType
== NULL
)
435 return E_OUTOFMEMORY
;
441 ///////////////////////////////////////
443 STDMETHODIMP
cMediaSample::SetMediaType(AM_MEDIA_TYPE
* pMediaType
)
445 /* Delete the current media type */
449 DeleteMediaType(m_pMediaType
);
453 /* Mechanism for resetting the format type */
455 if (pMediaType
== NULL
)
457 m_dwFlags
&= ~Sample_TypeChanged
;
462 ValidateReadPtr(pMediaType
, sizeof(AM_MEDIA_TYPE
));
464 /* Take a copy of the media type */
466 m_pMediaType
= CreateMediaType(pMediaType
);
467 if (m_pMediaType
== NULL
)
469 m_dwFlags
&= ~Sample_TypeChanged
;
470 return E_OUTOFMEMORY
;
473 m_dwFlags
|= Sample_TypeChanged
;
477 ///////////////////////////////////////////////////////////////////////////////
479 // CLASS: cBaseAllocator
482 ///////////////////////////////////////
484 // Pre-fab COM implementations
487 IMPLEMENT_UNAGGREGATABLE_SELF_DELETE(cBaseAllocator
, IMemAllocator
);
489 ///////////////////////////////////////
491 #pragma off(unreferenced)
492 cBaseAllocator::cBaseAllocator(char *pName
, LPUNKNOWN pUnk
, HRESULT
* phr
, BOOL bEvent
)
496 m_bDecommitInProgress(FALSE
),
504 AssertMsg(!pUnk
, "Aggregation of cBaseAllocator not implemented!");
507 m_hSem
= CreateSemaphore(NULL
, 0, 0x7FFFFFFF, NULL
);
510 *phr
= E_OUTOFMEMORY
;
515 #pragma on(unreferenced)
518 ///////////////////////////////////////
520 cBaseAllocator::~cBaseAllocator()
522 // we can't call Decommit here since that would mean a call to a
523 // pure virtual in destructor.
524 // We must assume that the derived class has gone into decommit state in
526 Assert_(!m_bCommitted
);
529 Verify(CloseHandle(m_hSem
));
534 ///////////////////////////////////////
536 /* This sets the size and count of the required samples. The memory isn't
537 actually allocated until Commit() is called, if memory has already been
538 allocated then assuming no samples are outstanding the user may call us
539 to change the buffering, the memory will be released in Commit() */
541 STDMETHODIMP
cBaseAllocator::SetProperties(ALLOCATOR_PROPERTIES
* pRequest
,
542 ALLOCATOR_PROPERTIES
* pActual
)
544 CheckPointer(pRequest
, E_POINTER
);
545 CheckPointer(pActual
, E_POINTER
);
546 ValidateReadWritePtr(pActual
, sizeof(ALLOCATOR_PROPERTIES
));
547 cAutoLock
lock(m_Lock
);
548 ZeroMemory(pActual
, sizeof(ALLOCATOR_PROPERTIES
));
550 Assert_(pRequest
->cbBuffer
> 0);
552 /* Check the alignment requested */
553 if (pRequest
->cbAlign
!= 1)
555 DbgLog((LOG_ERROR
, 2, TEXT("Alignment requested was 0x%x, not 1"),
557 return VFW_E_BADALIGN
;
560 /* Can't do this if already committed, there is an argument that says we should not reject the SetProperties call if there
561 are buffers still active. However this is called by the source filter, which is the same person who is holding the
562 samples. Therefore it is not unreasonable for them to free all their samples before changing the requirements */
566 return VFW_E_ALREADY_COMMITTED
;
569 /* Must be no outstanding buffers */
571 if (m_lAllocated
!= m_lFree
.GetCount())
573 return VFW_E_BUFFERS_OUTSTANDING
;
576 /* There isn't any real need to check the parameters as they will just be rejected when the user finally calls Commit */
578 pActual
->cbBuffer
= m_lSize
= pRequest
->cbBuffer
;
579 pActual
->cBuffers
= m_lCount
= pRequest
->cBuffers
;
580 pActual
->cbAlign
= m_lAlignment
= pRequest
->cbAlign
;
581 pActual
->cbPrefix
= m_lPrefix
= pRequest
->cbPrefix
;
587 ///////////////////////////////////////
589 STDMETHODIMP
cBaseAllocator::GetProperties(ALLOCATOR_PROPERTIES
* pActual
)
591 CheckPointer(pActual
, E_POINTER
);
592 ValidateReadWritePtr(pActual
, sizeof(ALLOCATOR_PROPERTIES
));
594 cAutoLock
lock(m_Lock
);
595 pActual
->cbBuffer
= m_lSize
;
596 pActual
->cBuffers
= m_lCount
;
597 pActual
->cbAlign
= m_lAlignment
;
598 pActual
->cbPrefix
= m_lPrefix
;
602 ///////////////////////////////////////
603 // get container for a sample. Blocking, synchronous call to get the
604 // next free buffer (as represented by an IMediaSample interface).
605 // on return, the time etc properties will be invalid, but the buffer
606 // pointer and size will be correct.
608 HRESULT
cBaseAllocator::GetBuffer(IMediaSample
** ppBuffer
,
609 REFERENCE_TIME
* /* pStartTime */,
610 REFERENCE_TIME
* /*pEndTime */,
613 cMediaSample
*pSample
;
618 cAutoLock
lock(m_Lock
);
619 /* Check we are committed */
622 return VFW_E_NOT_COMMITTED
;
624 pSample
= (cMediaSample
*) m_lFree
.RemoveHead();
631 /* If we didn't get a sample then wait for the list to signal */
637 Assert_(m_hSem
!= NULL
);
638 WaitForSingleObject(m_hSem
, INFINITE
);
641 /* This QueryInterface should addref the buffer up to one. On release back to zero instead of being deleted, it will
642 requeue itself by calling the ReleaseBuffer member function. NOTE the owner of a media sample must always be derived
643 from cBaseAllocator */
645 HRESULT hr
= pSample
->QueryInterface(IID_IMediaSample
, (void **) ppBuffer
);
646 /* For each sample outstanding, we need to AddRef ourselves on his behalf he cannot do it, as there is no correct ordering
647 of his release and his call to ReleaseBuffer as both could destroy him. We release this count in ReleaseBuffer, called
648 when the sample's count drops to zero */
655 ///////////////////////////////////////
657 /* Final release of a cMediaSample will call this */
659 STDMETHODIMP
cBaseAllocator::ReleaseBuffer(IMediaSample
* pSample
)
661 CheckPointer(pSample
, E_POINTER
);
662 ValidateReadPtr(pSample
, sizeof(IMediaSample
));
664 cAutoLock
lock(m_Lock
);
665 /* Put back on the free list */
667 m_lFree
.Add((cMediaSample
*) pSample
);
670 // if there is a pending Decommit, then we need to complete it by
671 // calling Free() when the last buffer is placed on the free list
673 long l1
= m_lFree
.GetCount();
674 if (m_bDecommitInProgress
&& (l1
== m_lAllocated
))
677 m_bDecommitInProgress
= FALSE
;
681 /* For each buffer there is one AddRef, made in GetBuffer and released here. This may cause the allocator and all samples
688 ///////////////////////////////////////
690 void cBaseAllocator::NotifySample()
694 Assert_(m_hSem
!= NULL
);
695 ReleaseSemaphore(m_hSem
, m_lWaiting
, 0);
700 ///////////////////////////////////////
702 STDMETHODIMP
cBaseAllocator::Commit()
704 /* Check we are not decommitted */
705 cAutoLock
lock(m_Lock
);
706 // cannot need to alloc or re-alloc if we are committed
712 /* Allow GetBuffer calls */
716 // is there a pending decommit ? if so, just cancel it
717 if (m_bDecommitInProgress
)
719 m_bDecommitInProgress
= FALSE
;
721 // don't call Alloc at this point. He cannot allow SetProperties
722 // between Decommit and the last free, so the buffer size cannot have
723 // changed. And because some of the buffers are not free yet, he
724 // cannot re-alloc anyway.
728 DbgLog((LOG_MEMORY
, 1, TEXT("Allocating: %ldx%ld"), m_lCount
, m_lSize
));
730 // actually need to allocate the samples
731 HRESULT hr
= Alloc();
734 m_bCommitted
= FALSE
;
741 ///////////////////////////////////////
743 STDMETHODIMP
cBaseAllocator::Decommit()
745 /* Check we are not already decommitted */
746 cAutoLock
lock(m_Lock
);
747 if (m_bCommitted
== FALSE
)
749 if (m_bDecommitInProgress
== FALSE
)
755 /* No more GetBuffer calls will succeed */
756 m_bCommitted
= FALSE
;
758 // are any buffers outstanding?
759 if (m_lFree
.GetCount() < m_lAllocated
)
761 // please complete the decommit when last buffer is freed
762 m_bDecommitInProgress
= TRUE
;
766 m_bDecommitInProgress
= FALSE
;
768 // need to complete the decommit here as there are no
769 // outstanding buffers
774 // Tell anyone whose waiting that they can go now so we can
782 ///////////////////////////////////////
784 /* Base definition of allocation which checks we are ok to go ahead and do
785 the full allocation. We return S_FALSE if the requirements are the same */
787 HRESULT
cBaseAllocator::Alloc(void)
789 /* Error if he hasn't set the size yet */
790 if (m_lCount
<= 0 || m_lSize
<= 0 || m_lAlignment
<= 0)
792 return VFW_E_SIZENOTSET
;
795 /* should never get here while buffers outstanding */
796 Assert_(m_lFree
.GetCount() == m_lAllocated
);
798 /* If the requirements haven't changed then don't reallocate */
799 if (m_bChanged
== FALSE
)
807 ///////////////////////////////////////
809 /* Implement cBaseAllocator::cSampleList::Remove(pSample)
810 Removes pSample from the list
812 void cBaseAllocator::cSampleList::Remove(cMediaSample
* pSample
)
814 cMediaSample
**pSearch
;
815 for (pSearch
= &m_List
;
817 pSearch
= &(cBaseAllocator::NextSample(*pSearch
)))
819 if (*pSearch
== pSample
)
821 *pSearch
= cBaseAllocator::NextSample(pSample
);
822 cBaseAllocator::NextSample(pSample
) = NULL
;
828 CriticalMsg("Couldn't find sample in list");
831 ///////////////////////////////////////////////////////////////////////////////
833 // CLASS: cMemAllocator
837 cMemAllocator::cMemAllocator(char *pName
,
840 : cBaseAllocator(pName
, pUnk
, phr
),
845 ///////////////////////////////////////
847 /* This sets the size and count of the required samples. The memory isn't
848 actually allocated until Commit() is called, if memory has already been
849 allocated then assuming no samples are outstanding the user may call us
850 to change the buffering, the memory will be released in Commit() */
851 STDMETHODIMP
cMemAllocator::SetProperties(ALLOCATOR_PROPERTIES
* pRequest
,
852 ALLOCATOR_PROPERTIES
* pActual
)
854 CheckPointer(pActual
, E_POINTER
);
855 ValidateReadWritePtr(pActual
, sizeof(ALLOCATOR_PROPERTIES
));
856 cAutoLock
lock(m_Lock
);
857 ZeroMemory(pActual
, sizeof(ALLOCATOR_PROPERTIES
));
859 Assert_(pRequest
->cbBuffer
> 0);
862 GetSystemInfo(&SysInfo
);
864 /* Check the alignment request is a power of 2 */
865 if ((-pRequest
->cbAlign
& pRequest
->cbAlign
) != pRequest
->cbAlign
)
867 DbgLog((LOG_ERROR
, 1, TEXT("Alignment requested 0x%x not a power of 2!"),
870 /* Check the alignment requested */
871 if (pRequest
->cbAlign
== 0 ||
872 SysInfo
.dwAllocationGranularity
& (pRequest
->cbAlign
- 1) != 0)
874 DbgLog((LOG_ERROR
, 1, TEXT("Invalid alignment 0x%x requested - granularity = 0x%x"),
875 pRequest
->cbAlign
, SysInfo
.dwAllocationGranularity
));
876 return VFW_E_BADALIGN
;
879 /* Can't do this if already committed, there is an argument that says we should not reject the SetProperties call if there
880 are buffers still active. However this is called by the source filter, which is the same person who is holding the
881 samples. Therefore it is not unreasonable for them to free all their samples before changing the requirements */
883 if (m_bCommitted
== TRUE
)
885 return VFW_E_ALREADY_COMMITTED
;
888 /* Must be no outstanding buffers */
890 if (m_lFree
.GetCount() < m_lAllocated
)
892 return VFW_E_BUFFERS_OUTSTANDING
;
895 /* There isn't any real need to check the parameters as they will just be rejected when the user finally calls Commit */
897 // round length up to alignment - remember that prefix is included in
899 long lSize
= pRequest
->cbBuffer
+ pRequest
->cbPrefix
;
900 long lRemainder
= lSize
% pRequest
->cbAlign
;
903 lSize
= lSize
- lRemainder
+ pRequest
->cbAlign
;
905 pActual
->cbBuffer
= m_lSize
= (lSize
- pRequest
->cbPrefix
);
907 pActual
->cBuffers
= m_lCount
= pRequest
->cBuffers
;
908 pActual
->cbAlign
= m_lAlignment
= pRequest
->cbAlign
;
909 pActual
->cbPrefix
= m_lPrefix
= pRequest
->cbPrefix
;
915 ///////////////////////////////////////
916 // override this to allocate our resources when Commit is called.
918 // note that our resources may be already allocated when this is called,
919 // since we don't free them on Decommit. We will only be called when in
920 // decommit state with all buffers free.
922 // object locked by caller
924 HRESULT
cMemAllocator::Alloc(void)
926 cAutoLock
lock(m_Lock
);
927 /* Check he has called SetProperties */
928 HRESULT hr
= cBaseAllocator::Alloc();
934 /* If the requirements haven't changed then don't reallocate */
940 Assert_(hr
== S_OK
); // we use this fact in the loop below
942 /* Free the old resources */
948 /* Create the contiguous memory block for the samples making sure it's properly aligned (64K should be enough!) */
949 Assert_(m_lAlignment
!= 0 &&
950 (m_lSize
+ m_lPrefix
) % m_lAlignment
== 0);
952 m_pBuffer
= (PBYTE
) VirtualAlloc(NULL
,
953 m_lCount
* (m_lSize
+ m_lPrefix
),
957 if (m_pBuffer
== NULL
)
959 return E_OUTOFMEMORY
;
962 BYTE
*pNext
= m_pBuffer
;
963 cMediaSample
*pSample
;
964 Assert_(m_lAllocated
== 0);
966 // Create the new samples - we have allocated m_lSize bytes for each sample
967 // plus m_lPrefix bytes per sample as a prefix. We set the pointer to
968 // the memory after the prefix - so that GetPointer() will return a pointer
970 for (; m_lAllocated
< m_lCount
; m_lAllocated
++, pNext
+= (m_lSize
+ m_lPrefix
))
974 pSample
= new cMediaSample(NAME("Default memory media sample"),
977 pNext
+ m_lPrefix
, // GetPointer() value
978 m_lSize
); // not including prefix
980 if (FAILED(hr
) || pSample
== NULL
)
983 return E_OUTOFMEMORY
;
987 // m_lFree.Add(pSample);
988 // Our new results in a 1 reference count not zero, so we start by releasing the sample
989 // (which decrements the reference count and then adds it to the free list anyway).
990 // This should fix things so that media samples are actually released when we're finished with them.
999 ///////////////////////////////////////
1000 // override this to free up any resources we have allocated.
1001 // called from the base class on Decommit when all buffers have been
1002 // returned to the free list.
1004 // caller has already locked the object.
1006 // in our case, we keep the memory until we are deleted, so
1007 // we do nothing here. The memory is deleted in the destructor by
1008 // calling ReallyFree()
1010 void cMemAllocator::Free(void)
1016 ///////////////////////////////////////
1017 // called from the destructor (and from Alloc if changing size/count) to
1018 // actually free up the memory
1020 void cMemAllocator::ReallyFree(void)
1022 /* Should never be deleting this unless all buffers are freed */
1024 Assert_(m_lAllocated
== m_lFree
.GetCount());
1026 /* Free up all the cMediaSamples */
1028 cMediaSample
*pSample
;
1031 pSample
= m_lFree
.RemoveHead();
1032 if (pSample
!= NULL
)
1044 // free the block of buffer memory
1047 Verify(VirtualFree(m_pBuffer
, 0, MEM_RELEASE
));
1053 ///////////////////////////////////////
1055 /* Destructor frees our memory resources */
1057 cMemAllocator::~cMemAllocator()
1063 ///////////////////////////////////////////////////////////////////////////////
1065 #pragma off(unreferenced)
1066 cDDSample::cDDSample(
1068 cBaseAllocator
*pAllocator
,
1070 LPDIRECTDRAWSURFACE pDDSurface
,
1071 IDirectDrawSurface
*pIDDSurface
,
1072 LPDDSURFACEDESC pDDSurfaceDesc
,
1074 cMediaSample(pName
, pAllocator
, phr
, (BYTE
*)pDDSurfaceDesc
->lpSurface
, length
),
1075 m_pDDSurface(pDDSurface
),
1076 m_pDDSurfaceDesc(pDDSurfaceDesc
),
1077 m_pIDDSurface(pIDDSurface
)
1081 #pragma on(unreferenced)
1083 LPDIRECTDRAWSURFACE
cDDSample::GetDDSurface()
1085 return m_pDDSurface
;
1088 IDirectDrawSurface
*cDDSample::GetIDDSurface()
1090 return m_pIDDSurface
;
1093 LPDDSURFACEDESC
cDDSample::GetDDSurfaceDesc()
1095 return m_pDDSurfaceDesc
;
1098 #pragma off(unreferenced)
1099 cBitmapSample::cBitmapSample(
1101 cBaseAllocator
*pAllocator
,
1103 grs_bitmap
*pBitmap
,
1105 cMediaSample(pName
, pAllocator
, phr
, (BYTE
*)pBitmap
->bits
, length
),
1109 #pragma on(unreferenced)
1111 grs_bitmap
*cBitmapSample::GetBitmap()