Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

442 lines
15 KiB

  1. // Copyright (c) 1992 - 1997 Microsoft Corporation. All Rights Reserved.
  2. // Media type stuff
  3. void WINAPI DeleteMediaType(AM_MEDIA_TYPE *pmt);
  4. void WINAPI CopyMediaType(AM_MEDIA_TYPE *pmtTarget, const AM_MEDIA_TYPE *pmtSource);
  5. void WINAPI FreeMediaType(AM_MEDIA_TYPE& mt);
  6. void WINAPI InitMediaType(AM_MEDIA_TYPE *mt);
  7. /* Base class objects for ActiveMovie in ATL */
  8. /* Allocators */
  9. //=====================================================================
  10. //=====================================================================
  11. // Memory allocators
  12. //
  13. // the shared memory transport between pins requires the input pin
  14. // to provide a memory allocator that can provide sample objects. A
  15. // sample object supports the IMediaSample interface.
  16. //
  17. // CAMBaseAllocator handles the management of free and busy samples. It
  18. // allocates CAMMediaSample objects. CAMBaseAllocator is an abstract class:
  19. // in particular it has no method of initializing the list of free
  20. // samples. CAMMemAllocator is derived from CAMBaseAllocator and initializes
  21. // the list of samples using memory from the standard IMalloc interface.
  22. //
  23. // If you want your buffers to live in some special area of memory,
  24. // derive your allocator object from CAMBaseAllocator. If you derive your
  25. // IMemInputPin interface object from CAMBaseMemInputPin, you will get
  26. // CAMMemAllocator-based allocation etc for free and will just need to
  27. // supply the Receive handling, and media type / format negotiation.
  28. //=====================================================================
  29. //=====================================================================
  30. //
  31. // The inhertiance tree for allocators and samples looks like
  32. //
  33. // CAMImplMediaSample<_S, _A>
  34. //
  35. // CAMImplMediaSample< CMediaSample< _A >, _A >
  36. // |
  37. // V
  38. // CAMMediaSample<_A>
  39. //
  40. //
  41. // CAMBaseAllocator<_A, _S>
  42. //
  43. // CAMBaseAllocator< CAMMemAllocator, CAMMediaSample< CAMMemAllocator > > >
  44. // |
  45. // V
  46. // CAMMemAllocator
  47. //=====================================================================
  48. //=====================================================================
  49. // Defines CAMMediaSample
  50. //
  51. // an object of this class supports IMediaSample and represents a buffer
  52. // for media data with some associated properties. Releasing it returns
  53. // it to a freelist managed by a CAMBaseAllocator derived object.
  54. //=====================================================================
  55. //=====================================================================
  56. template <class _S, class _A>
  57. class CAMMediaSampleImpl : public IMediaSample2 // The interface we support
  58. {
  59. protected:
  60. friend class _A;
  61. /* Values for dwFlags - these are used for backward compatiblity
  62. only now - use AM_SAMPLE_xxx
  63. */
  64. enum { Sample_SyncPoint = 0x01, /* Is this a sync point */
  65. Sample_Preroll = 0x02, /* Is this a preroll sample */
  66. Sample_Discontinuity = 0x04, /* Set if start of new segment */
  67. Sample_TypeChanged = 0x08, /* Has the type changed */
  68. Sample_TimeValid = 0x10, /* Set if time is valid */
  69. Sample_MediaTimeValid = 0x20, /* Is the media time valid */
  70. Sample_TimeDiscontinuity = 0x40, /* Time discontinuity */
  71. Sample_StopValid = 0x100, /* Stop time valid */
  72. Sample_ValidFlags = 0x1FF
  73. };
  74. /* Properties, the media sample class can be a container for a format
  75. change in which case we take a copy of a type through the SetMediaType
  76. interface function and then return it when GetMediaType is called. As
  77. we do no internal processing on it we leave it as a pointer */
  78. DWORD m_dwFlags; /* Flags for this sample */
  79. /* Type specific flags are packed
  80. into the top word
  81. */
  82. DWORD m_dwTypeSpecificFlags; /* Media type specific flags */
  83. LPBYTE m_pBuffer; /* Pointer to the complete buffer */
  84. LONG m_lActual; /* Length of data in this sample */
  85. LONG m_cbBuffer; /* Size of the buffer */
  86. _A *m_pAllocator; /* The allocator who owns us */
  87. REFERENCE_TIME m_Start; /* Start sample time */
  88. REFERENCE_TIME m_End; /* End sample time */
  89. LONGLONG m_MediaStart; /* Real media start position */
  90. LONG m_MediaEnd; /* A difference to get the end */
  91. AM_MEDIA_TYPE *m_pMediaType; /* Media type change data */
  92. public:
  93. LONG m_cRef; /* Reference count */
  94. _S *m_pNext; /* Chaining in free list */
  95. public:
  96. CAMMediaSampleImpl();
  97. ~CAMMediaSampleImpl()
  98. {
  99. if (m_pMediaType) {
  100. DeleteMediaType(m_pMediaType);
  101. }
  102. }
  103. /* Note the media sample does not delegate to its owner */
  104. STDMETHODIMP QueryInterface(REFIID riid, void **ppv);
  105. STDMETHODIMP_(ULONG) AddRef();
  106. STDMETHODIMP_(ULONG) Release();
  107. void Init(_A *pAllocator)
  108. {
  109. m_pAllocator = pAllocator;
  110. }
  111. // set the buffer pointer and length. Used by allocators that
  112. // want variable sized pointers or pointers into already-read data.
  113. // This is only available through a CAMMediaSampleImpl* not an IMediaSample*
  114. // and so cannot be changed by clients.
  115. HRESULT SetPointer(BYTE * ptr, LONG cBytes)
  116. {
  117. m_pBuffer = ptr; // new buffer area (could be null)
  118. m_cbBuffer = cBytes; // length of buffer
  119. m_lActual = cBytes; // length of data in buffer (assume full)
  120. return S_OK;
  121. }
  122. // Get me a read/write pointer to this buffer's memory.
  123. STDMETHODIMP GetPointer(BYTE ** ppBuffer);
  124. STDMETHODIMP_(LONG) GetSize(void);
  125. // get the stream time at which this sample should start and finish.
  126. STDMETHODIMP GetTime(
  127. REFERENCE_TIME * pTimeStart, // put time here
  128. REFERENCE_TIME * pTimeEnd
  129. );
  130. // Set the stream time at which this sample should start and finish.
  131. STDMETHODIMP SetTime(
  132. REFERENCE_TIME * pTimeStart, // put time here
  133. REFERENCE_TIME * pTimeEnd
  134. );
  135. STDMETHODIMP IsSyncPoint(void);
  136. STDMETHODIMP SetSyncPoint(BOOL bIsSyncPoint);
  137. STDMETHODIMP IsPreroll(void);
  138. STDMETHODIMP SetPreroll(BOOL bIsPreroll);
  139. STDMETHODIMP_(LONG) GetActualDataLength(void);
  140. STDMETHODIMP SetActualDataLength(LONG lActual);
  141. // these allow for limited format changes in band
  142. STDMETHODIMP GetMediaType(AM_MEDIA_TYPE **ppMediaType);
  143. STDMETHODIMP SetMediaType(AM_MEDIA_TYPE *pMediaType);
  144. // returns S_OK if there is a discontinuity in the data (this same is
  145. // not a continuation of the previous stream of data
  146. // - there has been a seek).
  147. STDMETHODIMP IsDiscontinuity(void);
  148. // set the discontinuity property - TRUE if this sample is not a
  149. // continuation, but a new sample after a seek.
  150. STDMETHODIMP SetDiscontinuity(BOOL bDiscontinuity);
  151. // get the media times for this sample
  152. STDMETHODIMP GetMediaTime(
  153. LONGLONG * pTimeStart,
  154. LONGLONG * pTimeEnd
  155. );
  156. // Set the media times for this sample
  157. STDMETHODIMP SetMediaTime(
  158. LONGLONG * pTimeStart,
  159. LONGLONG * pTimeEnd
  160. );
  161. // Set and get properties (IMediaSample2)
  162. STDMETHODIMP GetProperties(
  163. DWORD cbProperties,
  164. BYTE * pbProperties
  165. );
  166. STDMETHODIMP SetProperties(
  167. DWORD cbProperties,
  168. const BYTE * pbProperties
  169. );
  170. };
  171. //=====================================================================
  172. //=====================================================================
  173. // Defines CAMBaseAllocator
  174. //
  175. // Abstract base class that manages a list of media samples
  176. //
  177. // This class provides support for getting buffers from the free list,
  178. // including handling of commit and (asynchronous) decommit.
  179. //
  180. // Derive from this class and override the Alloc and Free functions to
  181. // allocate your CAMMediaSampleImpl (or derived) objects and add them to the
  182. // free list, preparing them as necessary.
  183. //=====================================================================
  184. //=====================================================================
  185. template <class _A, class _S>
  186. class CAMBaseAllocator :
  187. public CComObjectRoot,
  188. public IMemAllocator // The interface we support
  189. {
  190. protected:
  191. CCritSec m_Lock;
  192. friend class _A;
  193. typedef CAMBaseAllocator<_A, _S> _BaseAllocator;
  194. class CSampleList;
  195. friend class CSampleList;
  196. /* Hack to get at protected member in _S */
  197. static _S *
  198. &NextSample(_S *pSample)
  199. {
  200. return pSample->m_pNext;
  201. }
  202. /* Mini list class for the free list */
  203. class CSampleList
  204. {
  205. public:
  206. CSampleList() : m_List(NULL), m_nOnList(0) {};
  207. #ifdef DEBUG
  208. ~CSampleList()
  209. {
  210. _ASSERTE(m_nOnList == 0);
  211. };
  212. #endif
  213. _S *Head() const { return m_List; };
  214. _S *Next(_S *pSample) const { return NextSample(pSample); };
  215. int GetCount() const { return m_nOnList; };
  216. void Add(_S *pSample)
  217. {
  218. _ASSERTE(pSample != NULL);
  219. NextSample(pSample) = m_List;
  220. m_List = pSample;
  221. m_nOnList++;
  222. };
  223. _S *RemoveHead()
  224. {
  225. _S *pSample = m_List;
  226. if (pSample != NULL) {
  227. m_List = NextSample(m_List);
  228. m_nOnList--;
  229. }
  230. return pSample;
  231. };
  232. void Remove(_S *pSample);
  233. public:
  234. _S *m_List;
  235. int m_nOnList;
  236. };
  237. protected:
  238. CSampleList m_lFree; // Free list
  239. /* Note to overriders of CAMBaseAllocator.
  240. We use a lazy signalling mechanism for waiting for samples.
  241. This means we don't call the OS if no waits occur.
  242. In order to implement this:
  243. 1. When a new sample is added to m_lFree call NotifySample() which
  244. calls ReleaseSemaphore on m_hSem with a count of m_lWaiting and
  245. sets m_lWaiting to 0.
  246. This must all be done holding the allocator's critical section.
  247. 2. When waiting for a sample call SetWaiting() which increments
  248. m_lWaiting BEFORE leaving the allocator's critical section.
  249. 3. Actually wait by calling WaitForSingleObject(m_hSem, INFINITE)
  250. having left the allocator's critical section. The effect of
  251. this is to remove 1 from the semaphore's count. You MUST call
  252. this once having incremented m_lWaiting.
  253. The following are then true when the critical section is not held :
  254. (let nWaiting = number about to wait or waiting)
  255. (1) if (m_lFree.GetCount() != 0) then (m_lWaiting == 0)
  256. (2) m_lWaiting + Semaphore count == nWaiting
  257. We would deadlock if
  258. nWaiting != 0 &&
  259. m_lFree.GetCount() != 0 &&
  260. Semaphore count == 0
  261. But from (1) if m_lFree.GetCount() != 0 then m_lWaiting == 0 so
  262. from (2) Semaphore count == nWaiting (which is non-0) so the
  263. deadlock can't happen.
  264. */
  265. HANDLE m_hSem; // For signalling
  266. long m_lWaiting; // Waiting for a free element
  267. long m_lCount; // how many buffers we have agreed to provide
  268. long m_lAllocated; // how many buffers are currently allocated
  269. long m_lSize; // agreed size of each buffer
  270. long m_lAlignment; // agreed alignment
  271. long m_lPrefix; // agreed prefix (preceeds GetPointer() value)
  272. BOOL m_bChanged; // Have the buffer requirements changed
  273. // if true, we are decommitted and can't allocate memory
  274. BOOL m_bCommitted;
  275. // if true, the decommit has happened, but we haven't called Free yet
  276. // as there are still outstanding buffers
  277. BOOL m_bDecommitInProgress;
  278. // override to free the memory when decommit completes
  279. // - we actually do nothing, and save the memory until deletion.
  280. virtual void Free(void) = 0;
  281. // override to allocate the memory when commit called
  282. virtual HRESULT Alloc(void);
  283. public:
  284. CAMBaseAllocator();
  285. ~CAMBaseAllocator();
  286. HRESULT FinalConstruct();
  287. BEGIN_COM_MAP(CAMBaseAllocator)
  288. COM_INTERFACE_ENTRY(IMemAllocator)
  289. END_COM_MAP()
  290. STDMETHODIMP SetProperties(
  291. ALLOCATOR_PROPERTIES* pRequest,
  292. ALLOCATOR_PROPERTIES* pActual);
  293. // return the properties actually being used on this allocator
  294. STDMETHODIMP GetProperties(
  295. ALLOCATOR_PROPERTIES* pProps);
  296. // override Commit to allocate memory. We handle the GetBuffer
  297. //state changes
  298. STDMETHODIMP Commit();
  299. // override this to handle the memory freeing. We handle any outstanding
  300. // GetBuffer calls
  301. STDMETHODIMP Decommit();
  302. // get container for a sample. Blocking, synchronous call to get the
  303. // next free buffer (as represented by an IMediaSample interface).
  304. // on return, the time etc properties will be invalid, but the buffer
  305. // pointer and size will be correct. The two time parameters are
  306. // optional and either may be NULL, they may alternatively be set to
  307. // the start and end times the sample will have attached to it
  308. // bPrevFramesSkipped is not used (used only by the video renderer's
  309. // allocator where it affects quality management in direct draw).
  310. STDMETHODIMP GetBuffer(IMediaSample **ppBuffer,
  311. REFERENCE_TIME * pStartTime,
  312. REFERENCE_TIME * pEndTime,
  313. DWORD dwFlags);
  314. // final release of a _SampleClass will call this
  315. STDMETHODIMP ReleaseBuffer(IMediaSample *pBuffer);
  316. // obsolete:: virtual void PutOnFreeList(_SampleClass * pSample);
  317. // Notify that a sample is available
  318. void NotifySample();
  319. // Notify that we're waiting for a sample
  320. void SetWaiting() { m_lWaiting++; };
  321. };
  322. template < class _A >
  323. class CAMMediaSample : public CAMMediaSampleImpl< CAMMediaSample<_A>, _A >
  324. {
  325. public:
  326. CAMMediaSample() {}
  327. };
  328. //=====================================================================
  329. //=====================================================================
  330. // Defines CAMMemAllocator
  331. //
  332. // this is an allocator based on CAMBaseAllocator that allocates sample
  333. // buffers in main memory (from 'new'). You must call SetProperties
  334. // before calling Commit.
  335. //
  336. // we don't free the memory when going into Decommit state. The simplest
  337. // way to implement this without complicating CAMBaseAllocator is to
  338. // have a Free() function, called to go into decommit state, that does
  339. // nothing and a ReallyFree function called from our destructor that
  340. // actually frees the memory.
  341. //=====================================================================
  342. //=====================================================================
  343. class CAMMemAllocator :
  344. public CAMBaseAllocator< CAMMemAllocator,
  345. CAMMediaSample<CAMMemAllocator> >
  346. {
  347. protected:
  348. LPBYTE m_pBuffer; // combined memory for all buffers
  349. // override to free the memory when decommit completes
  350. // - we actually do nothing, and save the memory until deletion.
  351. void Free(void);
  352. // called from the destructor (and from Alloc if changing size/count) to
  353. // actually free up the memory
  354. void ReallyFree(void);
  355. // overriden to allocate the memory when commit called
  356. HRESULT Alloc(void);
  357. public:
  358. STDMETHODIMP SetProperties(
  359. ALLOCATOR_PROPERTIES* pRequest,
  360. ALLOCATOR_PROPERTIES* pActual);
  361. CAMMemAllocator();
  362. ~CAMMemAllocator();
  363. };