summaryrefslogtreecommitdiff
path: root/third_party/BaseClasses/mtype.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/BaseClasses/mtype.cpp')
-rw-r--r--third_party/BaseClasses/mtype.cpp478
1 files changed, 478 insertions, 0 deletions
diff --git a/third_party/BaseClasses/mtype.cpp b/third_party/BaseClasses/mtype.cpp
new file mode 100644
index 00000000..fffbcf79
--- /dev/null
+++ b/third_party/BaseClasses/mtype.cpp
@@ -0,0 +1,478 @@
+//------------------------------------------------------------------------------
+// File: MType.cpp
+//
+// Desc: DirectShow base classes - implements a class that holds and
+// manages media type information.
+//
+// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
+//------------------------------------------------------------------------------
+
+
+// helper class that derived pin objects can use to compare media
+// types etc. Has same data members as the struct AM_MEDIA_TYPE defined
+// in the streams IDL file, but also has (non-virtual) functions
+
+#include <streams.h>
+#include <mmreg.h>
+
+CMediaType::~CMediaType(){
+ FreeMediaType(*this);
+}
+
+
+CMediaType::CMediaType()
+{
+ InitMediaType();
+}
+
+
+CMediaType::CMediaType(const GUID * type)
+{
+ InitMediaType();
+ majortype = *type;
+}
+
+
+// copy constructor does a deep copy of the format block
+
+CMediaType::CMediaType(const AM_MEDIA_TYPE& rt, __out_opt HRESULT* phr)
+{
+ HRESULT hr = CopyMediaType(this, &rt);
+ if (FAILED(hr) && (NULL != phr)) {
+ *phr = hr;
+ }
+}
+
+
+CMediaType::CMediaType(const CMediaType& rt, __out_opt HRESULT* phr)
+{
+ HRESULT hr = CopyMediaType(this, &rt);
+ if (FAILED(hr) && (NULL != phr)) {
+ *phr = hr;
+ }
+}
+
+
+// this class inherits publicly from AM_MEDIA_TYPE so the compiler could generate
+// the following assignment operator itself, however it could introduce some
+// memory conflicts and leaks in the process because the structure contains
+// a dynamically allocated block (pbFormat) which it will not copy correctly
+
+CMediaType&
+CMediaType::operator=(const AM_MEDIA_TYPE& rt)
+{
+ Set(rt);
+ return *this;
+}
+
+CMediaType&
+CMediaType::operator=(const CMediaType& rt)
+{
+ *this = (AM_MEDIA_TYPE &) rt;
+ return *this;
+}
+
+BOOL
+CMediaType::operator == (const CMediaType& rt) const
+{
+ // I don't believe we need to check sample size or
+ // temporal compression flags, since I think these must
+ // be represented in the type, subtype and format somehow. They
+ // are pulled out as separate flags so that people who don't understand
+ // the particular format representation can still see them, but
+ // they should duplicate information in the format block.
+
+ return ((IsEqualGUID(majortype,rt.majortype) == TRUE) &&
+ (IsEqualGUID(subtype,rt.subtype) == TRUE) &&
+ (IsEqualGUID(formattype,rt.formattype) == TRUE) &&
+ (cbFormat == rt.cbFormat) &&
+ ( (cbFormat == 0) ||
+ pbFormat != NULL && rt.pbFormat != NULL &&
+ (memcmp(pbFormat, rt.pbFormat, cbFormat) == 0)));
+}
+
+
+BOOL
+CMediaType::operator != (const CMediaType& rt) const
+{
+ /* Check to see if they are equal */
+
+ if (*this == rt) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+HRESULT
+CMediaType::Set(const CMediaType& rt)
+{
+ return Set((AM_MEDIA_TYPE &) rt);
+}
+
+
+HRESULT
+CMediaType::Set(const AM_MEDIA_TYPE& rt)
+{
+ if (&rt != this) {
+ FreeMediaType(*this);
+ HRESULT hr = CopyMediaType(this, &rt);
+ if (FAILED(hr)) {
+ return E_OUTOFMEMORY;
+ }
+ }
+
+ return S_OK;
+}
+
+
+BOOL
+CMediaType::IsValid() const
+{
+ return (!IsEqualGUID(majortype,GUID_NULL));
+}
+
+
+void
+CMediaType::SetType(const GUID* ptype)
+{
+ majortype = *ptype;
+}
+
+
+void
+CMediaType::SetSubtype(const GUID* ptype)
+{
+ subtype = *ptype;
+}
+
+
+ULONG
+CMediaType::GetSampleSize() const {
+ if (IsFixedSize()) {
+ return lSampleSize;
+ } else {
+ return 0;
+ }
+}
+
+
+void
+CMediaType::SetSampleSize(ULONG sz) {
+ if (sz == 0) {
+ SetVariableSize();
+ } else {
+ bFixedSizeSamples = TRUE;
+ lSampleSize = sz;
+ }
+}
+
+
+void
+CMediaType::SetVariableSize() {
+ bFixedSizeSamples = FALSE;
+}
+
+
+void
+CMediaType::SetTemporalCompression(BOOL bCompressed) {
+ bTemporalCompression = bCompressed;
+}
+
+BOOL
+CMediaType::SetFormat(__in_bcount(cb) BYTE * pformat, ULONG cb)
+{
+ if (NULL == AllocFormatBuffer(cb))
+ return(FALSE);
+
+ ASSERT(pbFormat);
+ memcpy(pbFormat, pformat, cb);
+ return(TRUE);
+}
+
+
+// set the type of the media type format block, this type defines what you
+// will actually find in the format pointer. For example FORMAT_VideoInfo or
+// FORMAT_WaveFormatEx. In the future this may be an interface pointer to a
+// property set. Before sending out media types this should be filled in.
+
+void
+CMediaType::SetFormatType(const GUID *pformattype)
+{
+ formattype = *pformattype;
+}
+
+
+// reset the format buffer
+
+void CMediaType::ResetFormatBuffer()
+{
+ if (cbFormat) {
+ CoTaskMemFree((PVOID)pbFormat);
+ }
+ cbFormat = 0;
+ pbFormat = NULL;
+}
+
+
+// allocate length bytes for the format and return a read/write pointer
+// If we cannot allocate the new block of memory we return NULL leaving
+// the original block of memory untouched (as does ReallocFormatBuffer)
+
+BYTE*
+CMediaType::AllocFormatBuffer(ULONG length)
+{
+ ASSERT(length);
+
+ // do the types have the same buffer size
+
+ if (cbFormat == length) {
+ return pbFormat;
+ }
+
+ // allocate the new format buffer
+
+ BYTE *pNewFormat = (PBYTE)CoTaskMemAlloc(length);
+ if (pNewFormat == NULL) {
+ if (length <= cbFormat) return pbFormat; //reuse the old block anyway.
+ return NULL;
+ }
+
+ // delete the old format
+
+ if (cbFormat != 0) {
+ ASSERT(pbFormat);
+ CoTaskMemFree((PVOID)pbFormat);
+ }
+
+ cbFormat = length;
+ pbFormat = pNewFormat;
+ return pbFormat;
+}
+
+
+// reallocate length bytes for the format and return a read/write pointer
+// to it. We keep as much information as we can given the new buffer size
+// if this fails the original format buffer is left untouched. The caller
+// is responsible for ensuring the size of memory required is non zero
+
+BYTE*
+CMediaType::ReallocFormatBuffer(ULONG length)
+{
+ ASSERT(length);
+
+ // do the types have the same buffer size
+
+ if (cbFormat == length) {
+ return pbFormat;
+ }
+
+ // allocate the new format buffer
+
+ BYTE *pNewFormat = (PBYTE)CoTaskMemAlloc(length);
+ if (pNewFormat == NULL) {
+ if (length <= cbFormat) return pbFormat; //reuse the old block anyway.
+ return NULL;
+ }
+
+ // copy any previous format (or part of if new is smaller)
+ // delete the old format and replace with the new one
+
+ if (cbFormat != 0) {
+ ASSERT(pbFormat);
+ memcpy(pNewFormat,pbFormat,min(length,cbFormat));
+ CoTaskMemFree((PVOID)pbFormat);
+ }
+
+ cbFormat = length;
+ pbFormat = pNewFormat;
+ return pNewFormat;
+}
+
+// initialise a media type structure
+
+void CMediaType::InitMediaType()
+{
+ ZeroMemory((PVOID)this, sizeof(*this));
+ lSampleSize = 1;
+ bFixedSizeSamples = TRUE;
+}
+
+
+// a partially specified media type can be passed to IPin::Connect
+// as a constraint on the media type used in the connection.
+// the type, subtype or format type can be null.
+BOOL
+CMediaType::IsPartiallySpecified(void) const
+{
+ if ((majortype == GUID_NULL) ||
+ (formattype == GUID_NULL)) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+BOOL
+CMediaType::MatchesPartial(const CMediaType* ppartial) const
+{
+ if ((ppartial->majortype != GUID_NULL) &&
+ (majortype != ppartial->majortype)) {
+ return FALSE;
+ }
+ if ((ppartial->subtype != GUID_NULL) &&
+ (subtype != ppartial->subtype)) {
+ return FALSE;
+ }
+
+ if (ppartial->formattype != GUID_NULL) {
+ // if the format block is specified then it must match exactly
+ if (formattype != ppartial->formattype) {
+ return FALSE;
+ }
+ if (cbFormat != ppartial->cbFormat) {
+ return FALSE;
+ }
+ if ((cbFormat != 0) &&
+ (memcmp(pbFormat, ppartial->pbFormat, cbFormat) != 0)) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+
+}
+
+
+
+// general purpose function to delete a heap allocated AM_MEDIA_TYPE structure
+// which is useful when calling IEnumMediaTypes::Next as the interface
+// implementation allocates the structures which you must later delete
+// the format block may also be a pointer to an interface to release
+
+void WINAPI DeleteMediaType(__inout_opt AM_MEDIA_TYPE *pmt)
+{
+ // allow NULL pointers for coding simplicity
+
+ if (pmt == NULL) {
+ return;
+ }
+
+ FreeMediaType(*pmt);
+ CoTaskMemFree((PVOID)pmt);
+}
+
+
+// this also comes in useful when using the IEnumMediaTypes interface so
+// that you can copy a media type, you can do nearly the same by creating
+// a CMediaType object but as soon as it goes out of scope the destructor
+// will delete the memory it allocated (this takes a copy of the memory)
+
+AM_MEDIA_TYPE * WINAPI CreateMediaType(AM_MEDIA_TYPE const *pSrc)
+{
+ ASSERT(pSrc);
+
+ // Allocate a block of memory for the media type
+
+ AM_MEDIA_TYPE *pMediaType =
+ (AM_MEDIA_TYPE *)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
+
+ if (pMediaType == NULL) {
+ return NULL;
+ }
+ // Copy the variable length format block
+
+ HRESULT hr = CopyMediaType(pMediaType,pSrc);
+ if (FAILED(hr)) {
+ CoTaskMemFree((PVOID)pMediaType);
+ return NULL;
+ }
+
+ return pMediaType;
+}
+
+
+// Copy 1 media type to another
+
+HRESULT WINAPI CopyMediaType(__out AM_MEDIA_TYPE *pmtTarget, const AM_MEDIA_TYPE *pmtSource)
+{
+ // We'll leak if we copy onto one that already exists - there's one
+ // case we can check like that - copying to itself.
+ ASSERT(pmtSource != pmtTarget);
+ *pmtTarget = *pmtSource;
+ if (pmtSource->cbFormat != 0) {
+ ASSERT(pmtSource->pbFormat != NULL);
+ pmtTarget->pbFormat = (PBYTE)CoTaskMemAlloc(pmtSource->cbFormat);
+ if (pmtTarget->pbFormat == NULL) {
+ pmtTarget->cbFormat = 0;
+ return E_OUTOFMEMORY;
+ } else {
+ CopyMemory((PVOID)pmtTarget->pbFormat, (PVOID)pmtSource->pbFormat,
+ pmtTarget->cbFormat);
+ }
+ }
+ if (pmtTarget->pUnk != NULL) {
+ pmtTarget->pUnk->AddRef();
+ }
+
+ return S_OK;
+}
+
+// Free an existing media type (ie free resources it holds)
+
+void WINAPI FreeMediaType(__inout AM_MEDIA_TYPE& mt)
+{
+ if (mt.cbFormat != 0) {
+ CoTaskMemFree((PVOID)mt.pbFormat);
+
+ // Strictly unnecessary but tidier
+ mt.cbFormat = 0;
+ mt.pbFormat = NULL;
+ }
+ if (mt.pUnk != NULL) {
+ mt.pUnk->Release();
+ mt.pUnk = NULL;
+ }
+}
+
+// Initialize a media type from a WAVEFORMATEX
+
+STDAPI CreateAudioMediaType(
+ const WAVEFORMATEX *pwfx,
+ __out AM_MEDIA_TYPE *pmt,
+ BOOL bSetFormat
+)
+{
+ pmt->majortype = MEDIATYPE_Audio;
+ if (pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
+ pmt->subtype = ((PWAVEFORMATEXTENSIBLE)pwfx)->SubFormat;
+ } else {
+ pmt->subtype = FOURCCMap(pwfx->wFormatTag);
+ }
+ pmt->formattype = FORMAT_WaveFormatEx;
+ pmt->bFixedSizeSamples = TRUE;
+ pmt->bTemporalCompression = FALSE;
+ pmt->lSampleSize = pwfx->nBlockAlign;
+ pmt->pUnk = NULL;
+ if (bSetFormat) {
+ if (pwfx->wFormatTag == WAVE_FORMAT_PCM) {
+ pmt->cbFormat = sizeof(WAVEFORMATEX);
+ } else {
+ pmt->cbFormat = sizeof(WAVEFORMATEX) + pwfx->cbSize;
+ }
+ pmt->pbFormat = (PBYTE)CoTaskMemAlloc(pmt->cbFormat);
+ if (pmt->pbFormat == NULL) {
+ return E_OUTOFMEMORY;
+ }
+ if (pwfx->wFormatTag == WAVE_FORMAT_PCM) {
+ CopyMemory(pmt->pbFormat, pwfx, sizeof(PCMWAVEFORMAT));
+ ((WAVEFORMATEX *)pmt->pbFormat)->cbSize = 0;
+ } else {
+ CopyMemory(pmt->pbFormat, pwfx, pmt->cbFormat);
+ }
+ }
+ return S_OK;
+}
+
+// eliminate very many spurious warnings from MS compiler
+#pragma warning(disable:4514)