1
//------------------------------------------------------------------------------
4
// Desc: DirectShow base classes - implements a class that holds and
5
// manages media type information.
7
// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
8
//------------------------------------------------------------------------------
10
#include <pjmedia-videodev/config.h>
12
#if defined(PJMEDIA_VIDEO_DEV_HAS_DSHOW) && PJMEDIA_VIDEO_DEV_HAS_DSHOW != 0
14
// helper class that derived pin objects can use to compare media
15
// types etc. Has same data members as the struct AM_MEDIA_TYPE defined
16
// in the streams IDL file, but also has (non-virtual) functions
21
CMediaType::~CMediaType(){
26
CMediaType::CMediaType()
32
CMediaType::CMediaType(const GUID * type)
39
// copy constructor does a deep copy of the format block
41
CMediaType::CMediaType(const AM_MEDIA_TYPE& rt, __out_opt HRESULT* phr)
43
HRESULT hr = CopyMediaType(this, &rt);
44
if (FAILED(hr) && (NULL != phr)) {
50
CMediaType::CMediaType(const CMediaType& rt, __out_opt HRESULT* phr)
52
HRESULT hr = CopyMediaType(this, &rt);
53
if (FAILED(hr) && (NULL != phr)) {
59
// this class inherits publicly from AM_MEDIA_TYPE so the compiler could generate
60
// the following assignment operator itself, however it could introduce some
61
// memory conflicts and leaks in the process because the structure contains
62
// a dynamically allocated block (pbFormat) which it will not copy correctly
65
CMediaType::operator=(const AM_MEDIA_TYPE& rt)
72
CMediaType::operator=(const CMediaType& rt)
74
*this = (AM_MEDIA_TYPE &) rt;
79
CMediaType::operator == (const CMediaType& rt) const
81
// I don't believe we need to check sample size or
82
// temporal compression flags, since I think these must
83
// be represented in the type, subtype and format somehow. They
84
// are pulled out as separate flags so that people who don't understand
85
// the particular format representation can still see them, but
86
// they should duplicate information in the format block.
88
return ((IsEqualGUID(majortype,rt.majortype) == TRUE) &&
89
(IsEqualGUID(subtype,rt.subtype) == TRUE) &&
90
(IsEqualGUID(formattype,rt.formattype) == TRUE) &&
91
(cbFormat == rt.cbFormat) &&
93
pbFormat != NULL && rt.pbFormat != NULL &&
94
(memcmp(pbFormat, rt.pbFormat, cbFormat) == 0)));
99
CMediaType::operator != (const CMediaType& rt) const
101
/* Check to see if they are equal */
111
CMediaType::Set(const CMediaType& rt)
113
return Set((AM_MEDIA_TYPE &) rt);
118
CMediaType::Set(const AM_MEDIA_TYPE& rt)
121
FreeMediaType(*this);
122
HRESULT hr = CopyMediaType(this, &rt);
124
return E_OUTOFMEMORY;
133
CMediaType::IsValid() const
135
return (!IsEqualGUID(majortype,GUID_NULL));
140
CMediaType::SetType(const GUID* ptype)
147
CMediaType::SetSubtype(const GUID* ptype)
154
CMediaType::GetSampleSize() const {
164
CMediaType::SetSampleSize(ULONG sz) {
168
bFixedSizeSamples = TRUE;
175
CMediaType::SetVariableSize() {
176
bFixedSizeSamples = FALSE;
181
CMediaType::SetTemporalCompression(BOOL bCompressed) {
182
bTemporalCompression = bCompressed;
186
CMediaType::SetFormat(__in_bcount(cb) BYTE * pformat, ULONG cb)
188
if (NULL == AllocFormatBuffer(cb))
192
memcpy(pbFormat, pformat, cb);
197
// set the type of the media type format block, this type defines what you
198
// will actually find in the format pointer. For example FORMAT_VideoInfo or
199
// FORMAT_WaveFormatEx. In the future this may be an interface pointer to a
200
// property set. Before sending out media types this should be filled in.
203
CMediaType::SetFormatType(const GUID *pformattype)
205
formattype = *pformattype;
209
// reset the format buffer
211
void CMediaType::ResetFormatBuffer()
214
CoTaskMemFree((PVOID)pbFormat);
221
// allocate length bytes for the format and return a read/write pointer
222
// If we cannot allocate the new block of memory we return NULL leaving
223
// the original block of memory untouched (as does ReallocFormatBuffer)
226
CMediaType::AllocFormatBuffer(ULONG length)
230
// do the types have the same buffer size
232
if (cbFormat == length) {
236
// allocate the new format buffer
238
BYTE *pNewFormat = (PBYTE)CoTaskMemAlloc(length);
239
if (pNewFormat == NULL) {
240
if (length <= cbFormat) return pbFormat; //reuse the old block anyway.
244
// delete the old format
248
CoTaskMemFree((PVOID)pbFormat);
252
pbFormat = pNewFormat;
257
// reallocate length bytes for the format and return a read/write pointer
258
// to it. We keep as much information as we can given the new buffer size
259
// if this fails the original format buffer is left untouched. The caller
260
// is responsible for ensuring the size of memory required is non zero
263
CMediaType::ReallocFormatBuffer(ULONG length)
267
// do the types have the same buffer size
269
if (cbFormat == length) {
273
// allocate the new format buffer
275
BYTE *pNewFormat = (PBYTE)CoTaskMemAlloc(length);
276
if (pNewFormat == NULL) {
277
if (length <= cbFormat) return pbFormat; //reuse the old block anyway.
281
// copy any previous format (or part of if new is smaller)
282
// delete the old format and replace with the new one
286
memcpy(pNewFormat,pbFormat,min(length,cbFormat));
287
CoTaskMemFree((PVOID)pbFormat);
291
pbFormat = pNewFormat;
295
// initialise a media type structure
297
void CMediaType::InitMediaType()
299
ZeroMemory((PVOID)this, sizeof(*this));
301
bFixedSizeSamples = TRUE;
305
// a partially specified media type can be passed to IPin::Connect
306
// as a constraint on the media type used in the connection.
307
// the type, subtype or format type can be null.
309
CMediaType::IsPartiallySpecified(void) const
311
if ((majortype == GUID_NULL) ||
312
(formattype == GUID_NULL)) {
320
CMediaType::MatchesPartial(const CMediaType* ppartial) const
322
if ((ppartial->majortype != GUID_NULL) &&
323
(majortype != ppartial->majortype)) {
326
if ((ppartial->subtype != GUID_NULL) &&
327
(subtype != ppartial->subtype)) {
331
if (ppartial->formattype != GUID_NULL) {
332
// if the format block is specified then it must match exactly
333
if (formattype != ppartial->formattype) {
336
if (cbFormat != ppartial->cbFormat) {
339
if ((cbFormat != 0) &&
340
(memcmp(pbFormat, ppartial->pbFormat, cbFormat) != 0)) {
351
// general purpose function to delete a heap allocated AM_MEDIA_TYPE structure
352
// which is useful when calling IEnumMediaTypes::Next as the interface
353
// implementation allocates the structures which you must later delete
354
// the format block may also be a pointer to an interface to release
356
void WINAPI DeleteMediaType(__inout_opt AM_MEDIA_TYPE *pmt)
358
// allow NULL pointers for coding simplicity
365
CoTaskMemFree((PVOID)pmt);
369
// this also comes in useful when using the IEnumMediaTypes interface so
370
// that you can copy a media type, you can do nearly the same by creating
371
// a CMediaType object but as soon as it goes out of scope the destructor
372
// will delete the memory it allocated (this takes a copy of the memory)
374
AM_MEDIA_TYPE * WINAPI CreateMediaType(AM_MEDIA_TYPE const *pSrc)
378
// Allocate a block of memory for the media type
380
AM_MEDIA_TYPE *pMediaType =
381
(AM_MEDIA_TYPE *)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
383
if (pMediaType == NULL) {
386
// Copy the variable length format block
388
HRESULT hr = CopyMediaType(pMediaType,pSrc);
390
CoTaskMemFree((PVOID)pMediaType);
398
// Copy 1 media type to another
400
HRESULT WINAPI CopyMediaType(__out AM_MEDIA_TYPE *pmtTarget, const AM_MEDIA_TYPE *pmtSource)
402
// We'll leak if we copy onto one that already exists - there's one
403
// case we can check like that - copying to itself.
404
ASSERT(pmtSource != pmtTarget);
405
*pmtTarget = *pmtSource;
406
if (pmtSource->cbFormat != 0) {
407
ASSERT(pmtSource->pbFormat != NULL);
408
pmtTarget->pbFormat = (PBYTE)CoTaskMemAlloc(pmtSource->cbFormat);
409
if (pmtTarget->pbFormat == NULL) {
410
pmtTarget->cbFormat = 0;
411
return E_OUTOFMEMORY;
413
CopyMemory((PVOID)pmtTarget->pbFormat, (PVOID)pmtSource->pbFormat,
414
pmtTarget->cbFormat);
417
if (pmtTarget->pUnk != NULL) {
418
pmtTarget->pUnk->AddRef();
424
// Free an existing media type (ie free resources it holds)
426
void WINAPI FreeMediaType(__inout AM_MEDIA_TYPE& mt)
428
if (mt.cbFormat != 0) {
429
CoTaskMemFree((PVOID)mt.pbFormat);
431
// Strictly unnecessary but tidier
435
if (mt.pUnk != NULL) {
441
// Initialize a media type from a WAVEFORMATEX
443
STDAPI CreateAudioMediaType(
444
const WAVEFORMATEX *pwfx,
445
__out AM_MEDIA_TYPE *pmt,
449
pmt->majortype = MEDIATYPE_Audio;
450
if (pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
451
pmt->subtype = ((PWAVEFORMATEXTENSIBLE)pwfx)->SubFormat;
453
pmt->subtype = FOURCCMap(pwfx->wFormatTag);
455
pmt->formattype = FORMAT_WaveFormatEx;
456
pmt->bFixedSizeSamples = TRUE;
457
pmt->bTemporalCompression = FALSE;
458
pmt->lSampleSize = pwfx->nBlockAlign;
461
if (pwfx->wFormatTag == WAVE_FORMAT_PCM) {
462
pmt->cbFormat = sizeof(WAVEFORMATEX);
464
pmt->cbFormat = sizeof(WAVEFORMATEX) + pwfx->cbSize;
466
pmt->pbFormat = (PBYTE)CoTaskMemAlloc(pmt->cbFormat);
467
if (pmt->pbFormat == NULL) {
468
return E_OUTOFMEMORY;
470
if (pwfx->wFormatTag == WAVE_FORMAT_PCM) {
471
CopyMemory(pmt->pbFormat, pwfx, sizeof(PCMWAVEFORMAT));
472
((WAVEFORMATEX *)pmt->pbFormat)->cbSize = 0;
474
CopyMemory(pmt->pbFormat, pwfx, pmt->cbFormat);
480
// eliminate very many spurious warnings from MS compiler
481
#pragma warning(disable:4514)
483
#endif /* PJMEDIA_VIDEO_DEV_HAS_DSHOW */