PageRenderTime 40ms CodeModel.GetById 33ms RepoModel.GetById 1ms app.codeStats 0ms

/dependencies/include/cgv/media/video/ds/mtype.cpp

https://github.com/tomka/copo
C++ | 477 lines | 311 code | 101 blank | 65 comment | 90 complexity | df060aaf5c018cc6a96f2fb278f4bdaa MD5 | raw file
  1. //------------------------------------------------------------------------------
  2. // File: MType.cpp
  3. //
  4. // Desc: DirectShow base classes - implements a class that holds and
  5. // manages media type information.
  6. //
  7. // Copyright (c) Microsoft Corporation. All rights reserved.
  8. //------------------------------------------------------------------------------
  9. // helper class that derived pin objects can use to compare media
  10. // types etc. Has same data members as the struct AM_MEDIA_TYPE defined
  11. // in the streams IDL file, but also has (non-virtual) functions
  12. #include <streams.h>
  13. #include <mmreg.h>
  14. CMediaType::~CMediaType(){
  15. FreeMediaType(*this);
  16. }
  17. CMediaType::CMediaType()
  18. {
  19. InitMediaType();
  20. }
  21. CMediaType::CMediaType(const GUID * type)
  22. {
  23. InitMediaType();
  24. majortype = *type;
  25. }
  26. // copy constructor does a deep copy of the format block
  27. CMediaType::CMediaType(const AM_MEDIA_TYPE& rt, HRESULT* phr)
  28. {
  29. HRESULT hr = CopyMediaType(this, &rt);
  30. if (FAILED(hr) && (NULL != phr)) {
  31. *phr = hr;
  32. }
  33. }
  34. CMediaType::CMediaType(const CMediaType& rt, HRESULT* phr)
  35. {
  36. HRESULT hr = CopyMediaType(this, &rt);
  37. if (FAILED(hr) && (NULL != phr)) {
  38. *phr = hr;
  39. }
  40. }
  41. // this class inherits publicly from AM_MEDIA_TYPE so the compiler could generate
  42. // the following assignment operator itself, however it could introduce some
  43. // memory conflicts and leaks in the process because the structure contains
  44. // a dynamically allocated block (pbFormat) which it will not copy correctly
  45. CMediaType&
  46. CMediaType::operator=(const AM_MEDIA_TYPE& rt)
  47. {
  48. Set(rt);
  49. return *this;
  50. }
  51. CMediaType&
  52. CMediaType::operator=(const CMediaType& rt)
  53. {
  54. *this = (AM_MEDIA_TYPE &) rt;
  55. return *this;
  56. }
  57. BOOL
  58. CMediaType::operator == (const CMediaType& rt) const
  59. {
  60. // I don't believe we need to check sample size or
  61. // temporal compression flags, since I think these must
  62. // be represented in the type, subtype and format somehow. They
  63. // are pulled out as separate flags so that people who don't understand
  64. // the particular format representation can still see them, but
  65. // they should duplicate information in the format block.
  66. return ((IsEqualGUID(majortype,rt.majortype) == TRUE) &&
  67. (IsEqualGUID(subtype,rt.subtype) == TRUE) &&
  68. (IsEqualGUID(formattype,rt.formattype) == TRUE) &&
  69. (cbFormat == rt.cbFormat) &&
  70. ( (cbFormat == 0) ||
  71. (memcmp(pbFormat, rt.pbFormat, cbFormat) == 0)));
  72. }
  73. BOOL
  74. CMediaType::operator != (const CMediaType& rt) const
  75. {
  76. /* Check to see if they are equal */
  77. if (*this == rt) {
  78. return FALSE;
  79. }
  80. return TRUE;
  81. }
  82. HRESULT
  83. CMediaType::Set(const CMediaType& rt)
  84. {
  85. return Set((AM_MEDIA_TYPE &) rt);
  86. }
  87. HRESULT
  88. CMediaType::Set(const AM_MEDIA_TYPE& rt)
  89. {
  90. if (&rt != this) {
  91. FreeMediaType(*this);
  92. HRESULT hr = CopyMediaType(this, &rt);
  93. if (FAILED(hr)) {
  94. return E_OUTOFMEMORY;
  95. }
  96. }
  97. return S_OK;
  98. }
  99. BOOL
  100. CMediaType::IsValid() const
  101. {
  102. return (!IsEqualGUID(majortype,GUID_NULL));
  103. }
  104. void
  105. CMediaType::SetType(const GUID* ptype)
  106. {
  107. majortype = *ptype;
  108. }
  109. void
  110. CMediaType::SetSubtype(const GUID* ptype)
  111. {
  112. subtype = *ptype;
  113. }
  114. ULONG
  115. CMediaType::GetSampleSize() const {
  116. if (IsFixedSize()) {
  117. return lSampleSize;
  118. } else {
  119. return 0;
  120. }
  121. }
  122. void
  123. CMediaType::SetSampleSize(ULONG sz) {
  124. if (sz == 0) {
  125. SetVariableSize();
  126. } else {
  127. bFixedSizeSamples = TRUE;
  128. lSampleSize = sz;
  129. }
  130. }
  131. void
  132. CMediaType::SetVariableSize() {
  133. bFixedSizeSamples = FALSE;
  134. }
  135. void
  136. CMediaType::SetTemporalCompression(BOOL bCompressed) {
  137. bTemporalCompression = bCompressed;
  138. }
  139. BOOL
  140. CMediaType::SetFormat(BYTE * pformat, ULONG cb)
  141. {
  142. if (NULL == AllocFormatBuffer(cb))
  143. return(FALSE);
  144. ASSERT(pbFormat);
  145. memcpy(pbFormat, pformat, cb);
  146. return(TRUE);
  147. }
  148. // set the type of the media type format block, this type defines what you
  149. // will actually find in the format pointer. For example FORMAT_VideoInfo or
  150. // FORMAT_WaveFormatEx. In the future this may be an interface pointer to a
  151. // property set. Before sending out media types this should be filled in.
  152. void
  153. CMediaType::SetFormatType(const GUID *pformattype)
  154. {
  155. formattype = *pformattype;
  156. }
  157. // reset the format buffer
  158. void CMediaType::ResetFormatBuffer()
  159. {
  160. if (cbFormat) {
  161. CoTaskMemFree((PVOID)pbFormat);
  162. }
  163. cbFormat = 0;
  164. pbFormat = NULL;
  165. }
  166. // allocate length bytes for the format and return a read/write pointer
  167. // If we cannot allocate the new block of memory we return NULL leaving
  168. // the original block of memory untouched (as does ReallocFormatBuffer)
  169. BYTE*
  170. CMediaType::AllocFormatBuffer(ULONG length)
  171. {
  172. ASSERT(length);
  173. // do the types have the same buffer size
  174. if (cbFormat == length) {
  175. return pbFormat;
  176. }
  177. // allocate the new format buffer
  178. BYTE *pNewFormat = (PBYTE)CoTaskMemAlloc(length);
  179. if (pNewFormat == NULL) {
  180. if (length <= cbFormat) return pbFormat; //reuse the old block anyway.
  181. return NULL;
  182. }
  183. // delete the old format
  184. if (cbFormat != 0) {
  185. ASSERT(pbFormat);
  186. CoTaskMemFree((PVOID)pbFormat);
  187. }
  188. cbFormat = length;
  189. pbFormat = pNewFormat;
  190. return pbFormat;
  191. }
  192. // reallocate length bytes for the format and return a read/write pointer
  193. // to it. We keep as much information as we can given the new buffer size
  194. // if this fails the original format buffer is left untouched. The caller
  195. // is responsible for ensuring the size of memory required is non zero
  196. BYTE*
  197. CMediaType::ReallocFormatBuffer(ULONG length)
  198. {
  199. ASSERT(length);
  200. // do the types have the same buffer size
  201. if (cbFormat == length) {
  202. return pbFormat;
  203. }
  204. // allocate the new format buffer
  205. BYTE *pNewFormat = (PBYTE)CoTaskMemAlloc(length);
  206. if (pNewFormat == NULL) {
  207. if (length <= cbFormat) return pbFormat; //reuse the old block anyway.
  208. return NULL;
  209. }
  210. // copy any previous format (or part of if new is smaller)
  211. // delete the old format and replace with the new one
  212. if (cbFormat != 0) {
  213. ASSERT(pbFormat);
  214. memcpy(pNewFormat,pbFormat,min(length,cbFormat));
  215. CoTaskMemFree((PVOID)pbFormat);
  216. }
  217. cbFormat = length;
  218. pbFormat = pNewFormat;
  219. return pNewFormat;
  220. }
  221. // initialise a media type structure
  222. void CMediaType::InitMediaType()
  223. {
  224. ZeroMemory((PVOID)this, sizeof(*this));
  225. lSampleSize = 1;
  226. bFixedSizeSamples = TRUE;
  227. }
  228. // a partially specified media type can be passed to IPin::Connect
  229. // as a constraint on the media type used in the connection.
  230. // the type, subtype or format type can be null.
  231. BOOL
  232. CMediaType::IsPartiallySpecified(void) const
  233. {
  234. if ((majortype == GUID_NULL) ||
  235. (formattype == GUID_NULL)) {
  236. return TRUE;
  237. } else {
  238. return FALSE;
  239. }
  240. }
  241. BOOL
  242. CMediaType::MatchesPartial(const CMediaType* ppartial) const
  243. {
  244. if ((ppartial->majortype != GUID_NULL) &&
  245. (majortype != ppartial->majortype)) {
  246. return FALSE;
  247. }
  248. if ((ppartial->subtype != GUID_NULL) &&
  249. (subtype != ppartial->subtype)) {
  250. return FALSE;
  251. }
  252. if (ppartial->formattype != GUID_NULL) {
  253. // if the format block is specified then it must match exactly
  254. if (formattype != ppartial->formattype) {
  255. return FALSE;
  256. }
  257. if (cbFormat != ppartial->cbFormat) {
  258. return FALSE;
  259. }
  260. if ((cbFormat != 0) &&
  261. (memcmp(pbFormat, ppartial->pbFormat, cbFormat) != 0)) {
  262. return FALSE;
  263. }
  264. }
  265. return TRUE;
  266. }
  267. // general purpose function to delete a heap allocated AM_MEDIA_TYPE structure
  268. // which is useful when calling IEnumMediaTypes::Next as the interface
  269. // implementation allocates the structures which you must later delete
  270. // the format block may also be a pointer to an interface to release
  271. void WINAPI DeleteMediaType(AM_MEDIA_TYPE *pmt)
  272. {
  273. // allow NULL pointers for coding simplicity
  274. if (pmt == NULL) {
  275. return;
  276. }
  277. FreeMediaType(*pmt);
  278. CoTaskMemFree((PVOID)pmt);
  279. }
  280. // this also comes in useful when using the IEnumMediaTypes interface so
  281. // that you can copy a media type, you can do nearly the same by creating
  282. // a CMediaType object but as soon as it goes out of scope the destructor
  283. // will delete the memory it allocated (this takes a copy of the memory)
  284. AM_MEDIA_TYPE * WINAPI CreateMediaType(AM_MEDIA_TYPE const *pSrc)
  285. {
  286. ASSERT(pSrc);
  287. // Allocate a block of memory for the media type
  288. AM_MEDIA_TYPE *pMediaType =
  289. (AM_MEDIA_TYPE *)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
  290. if (pMediaType == NULL) {
  291. return NULL;
  292. }
  293. // Copy the variable length format block
  294. HRESULT hr = CopyMediaType(pMediaType,pSrc);
  295. if (FAILED(hr)) {
  296. CoTaskMemFree((PVOID)pMediaType);
  297. return NULL;
  298. }
  299. return pMediaType;
  300. }
  301. // Copy 1 media type to another
  302. HRESULT WINAPI CopyMediaType(AM_MEDIA_TYPE *pmtTarget, const AM_MEDIA_TYPE *pmtSource)
  303. {
  304. // We'll leak if we copy onto one that already exists - there's one
  305. // case we can check like that - copying to itself.
  306. ASSERT(pmtSource != pmtTarget);
  307. *pmtTarget = *pmtSource;
  308. if (pmtSource->cbFormat != 0) {
  309. ASSERT(pmtSource->pbFormat != NULL);
  310. pmtTarget->pbFormat = (PBYTE)CoTaskMemAlloc(pmtSource->cbFormat);
  311. if (pmtTarget->pbFormat == NULL) {
  312. pmtTarget->cbFormat = 0;
  313. return E_OUTOFMEMORY;
  314. } else {
  315. CopyMemory((PVOID)pmtTarget->pbFormat, (PVOID)pmtSource->pbFormat,
  316. pmtTarget->cbFormat);
  317. }
  318. }
  319. if (pmtTarget->pUnk != NULL) {
  320. pmtTarget->pUnk->AddRef();
  321. }
  322. return S_OK;
  323. }
  324. // Free an existing media type (ie free resources it holds)
  325. void WINAPI FreeMediaType(AM_MEDIA_TYPE& mt)
  326. {
  327. if (mt.cbFormat != 0) {
  328. CoTaskMemFree((PVOID)mt.pbFormat);
  329. // Strictly unnecessary but tidier
  330. mt.cbFormat = 0;
  331. mt.pbFormat = NULL;
  332. }
  333. if (mt.pUnk != NULL) {
  334. mt.pUnk->Release();
  335. mt.pUnk = NULL;
  336. }
  337. }
  338. // Initialize a media type from a WAVEFORMATEX
  339. STDAPI CreateAudioMediaType(
  340. const WAVEFORMATEX *pwfx,
  341. AM_MEDIA_TYPE *pmt,
  342. BOOL bSetFormat
  343. )
  344. {
  345. pmt->majortype = MEDIATYPE_Audio;
  346. if (pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
  347. pmt->subtype = ((PWAVEFORMATEXTENSIBLE)pwfx)->SubFormat;
  348. } else {
  349. pmt->subtype = FOURCCMap(pwfx->wFormatTag);
  350. }
  351. pmt->formattype = FORMAT_WaveFormatEx;
  352. pmt->bFixedSizeSamples = TRUE;
  353. pmt->bTemporalCompression = FALSE;
  354. pmt->lSampleSize = pwfx->nBlockAlign;
  355. pmt->pUnk = NULL;
  356. if (bSetFormat) {
  357. if (pwfx->wFormatTag == WAVE_FORMAT_PCM) {
  358. pmt->cbFormat = sizeof(WAVEFORMATEX);
  359. } else {
  360. pmt->cbFormat = sizeof(WAVEFORMATEX) + pwfx->cbSize;
  361. }
  362. pmt->pbFormat = (PBYTE)CoTaskMemAlloc(pmt->cbFormat);
  363. if (pmt->pbFormat == NULL) {
  364. return E_OUTOFMEMORY;
  365. }
  366. if (pwfx->wFormatTag == WAVE_FORMAT_PCM) {
  367. CopyMemory(pmt->pbFormat, pwfx, sizeof(PCMWAVEFORMAT));
  368. ((WAVEFORMATEX *)pmt->pbFormat)->cbSize = 0;
  369. } else {
  370. CopyMemory(pmt->pbFormat, pwfx, pmt->cbFormat);
  371. }
  372. }
  373. return S_OK;
  374. }
  375. // eliminate very many spurious warnings from MS compiler
  376. #pragma warning(disable:4514)