mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-01-31 01:15:24 +01:00
Update it to the version found at https://github.com/Microsoft/Windows-classic-samples , which is in an MIT licensed repo, and add the LICENSE file (edited to remove the SIL Open Font LICENSE part since that doesn't apply). Some modifications have been made to reduce the diff/stop git complaining (not including any file that wasn't in the previous version and removing the related header includes in streams.h, and fixing some but not all of the whitespace issues).
479 lines
11 KiB
C++
479 lines
11 KiB
C++
//------------------------------------------------------------------------------
|
|
// 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)
|