Sweden-Number/dlls/mfplat/mediatype.c

2092 lines
67 KiB
C

/*
* Copyright 2017 Alistair Leslie-Hughes
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define COBJMACROS
#include "mfplat_private.h"
#include "initguid.h"
#include "ks.h"
#include "ksmedia.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
DEFINE_MEDIATYPE_GUID(MFVideoFormat_IMC1, MAKEFOURCC('I','M','C','1'));
DEFINE_MEDIATYPE_GUID(MFVideoFormat_IMC2, MAKEFOURCC('I','M','C','2'));
DEFINE_MEDIATYPE_GUID(MFVideoFormat_IMC3, MAKEFOURCC('I','M','C','3'));
DEFINE_MEDIATYPE_GUID(MFVideoFormat_IMC4, MAKEFOURCC('I','M','C','4'));
struct media_type
{
struct attributes attributes;
IMFMediaType IMFMediaType_iface;
};
struct stream_desc
{
struct attributes attributes;
IMFStreamDescriptor IMFStreamDescriptor_iface;
IMFMediaTypeHandler IMFMediaTypeHandler_iface;
DWORD identifier;
IMFMediaType **media_types;
unsigned int media_types_count;
IMFMediaType *current_type;
};
struct presentation_desc_entry
{
IMFStreamDescriptor *descriptor;
BOOL selected;
};
struct presentation_desc
{
struct attributes attributes;
IMFPresentationDescriptor IMFPresentationDescriptor_iface;
struct presentation_desc_entry *descriptors;
unsigned int count;
};
static HRESULT presentation_descriptor_init(struct presentation_desc *object, DWORD count);
static inline struct media_type *impl_from_IMFMediaType(IMFMediaType *iface)
{
return CONTAINING_RECORD(iface, struct media_type, IMFMediaType_iface);
}
static inline struct stream_desc *impl_from_IMFStreamDescriptor(IMFStreamDescriptor *iface)
{
return CONTAINING_RECORD(iface, struct stream_desc, IMFStreamDescriptor_iface);
}
static struct stream_desc *impl_from_IMFMediaTypeHandler(IMFMediaTypeHandler *iface)
{
return CONTAINING_RECORD(iface, struct stream_desc, IMFMediaTypeHandler_iface);
}
static struct presentation_desc *impl_from_IMFPresentationDescriptor(IMFPresentationDescriptor *iface)
{
return CONTAINING_RECORD(iface, struct presentation_desc, IMFPresentationDescriptor_iface);
}
static HRESULT WINAPI mediatype_QueryInterface(IMFMediaType *iface, REFIID riid, void **out)
{
TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
if (IsEqualIID(riid, &IID_IMFMediaType) ||
IsEqualIID(riid, &IID_IMFAttributes) ||
IsEqualIID(riid, &IID_IUnknown))
{
*out = iface;
IMFMediaType_AddRef(iface);
return S_OK;
}
WARN("Unsupported %s.\n", debugstr_guid(riid));
*out = NULL;
return E_NOINTERFACE;
}
static ULONG WINAPI mediatype_AddRef(IMFMediaType *iface)
{
struct media_type *media_type = impl_from_IMFMediaType(iface);
ULONG refcount = InterlockedIncrement(&media_type->attributes.ref);
TRACE("%p, refcount %u.\n", iface, refcount);
return refcount;
}
static ULONG WINAPI mediatype_Release(IMFMediaType *iface)
{
struct media_type *media_type = impl_from_IMFMediaType(iface);
ULONG refcount = InterlockedDecrement(&media_type->attributes.ref);
TRACE("%p, refcount %u.\n", iface, refcount);
if (!refcount)
{
clear_attributes_object(&media_type->attributes);
heap_free(media_type);
}
return refcount;
}
static HRESULT WINAPI mediatype_GetItem(IMFMediaType *iface, REFGUID key, PROPVARIANT *value)
{
struct media_type *media_type = impl_from_IMFMediaType(iface);
TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
return attributes_GetItem(&media_type->attributes, key, value);
}
static HRESULT WINAPI mediatype_GetItemType(IMFMediaType *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
{
struct media_type *media_type = impl_from_IMFMediaType(iface);
TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), type);
return attributes_GetItemType(&media_type->attributes, key, type);
}
static HRESULT WINAPI mediatype_CompareItem(IMFMediaType *iface, REFGUID key, REFPROPVARIANT value, BOOL *result)
{
struct media_type *media_type = impl_from_IMFMediaType(iface);
TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_propvar(value), result);
return attributes_CompareItem(&media_type->attributes, key, value, result);
}
static HRESULT WINAPI mediatype_Compare(IMFMediaType *iface, IMFAttributes *attrs, MF_ATTRIBUTES_MATCH_TYPE type,
BOOL *result)
{
struct media_type *media_type = impl_from_IMFMediaType(iface);
TRACE("%p, %p, %d, %p.\n", iface, attrs, type, result);
return attributes_Compare(&media_type->attributes, attrs, type, result);
}
static HRESULT WINAPI mediatype_GetUINT32(IMFMediaType *iface, REFGUID key, UINT32 *value)
{
struct media_type *media_type = impl_from_IMFMediaType(iface);
TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
return attributes_GetUINT32(&media_type->attributes, key, value);
}
static HRESULT WINAPI mediatype_GetUINT64(IMFMediaType *iface, REFGUID key, UINT64 *value)
{
struct media_type *media_type = impl_from_IMFMediaType(iface);
TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
return attributes_GetUINT64(&media_type->attributes, key, value);
}
static HRESULT WINAPI mediatype_GetDouble(IMFMediaType *iface, REFGUID key, double *value)
{
struct media_type *media_type = impl_from_IMFMediaType(iface);
TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
return attributes_GetDouble(&media_type->attributes, key, value);
}
static HRESULT WINAPI mediatype_GetGUID(IMFMediaType *iface, REFGUID key, GUID *value)
{
struct media_type *media_type = impl_from_IMFMediaType(iface);
TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
return attributes_GetGUID(&media_type->attributes, key, value);
}
static HRESULT WINAPI mediatype_GetStringLength(IMFMediaType *iface, REFGUID key, UINT32 *length)
{
struct media_type *media_type = impl_from_IMFMediaType(iface);
TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), length);
return attributes_GetStringLength(&media_type->attributes, key, length);
}
static HRESULT WINAPI mediatype_GetString(IMFMediaType *iface, REFGUID key, WCHAR *value,
UINT32 size, UINT32 *length)
{
struct media_type *media_type = impl_from_IMFMediaType(iface);
TRACE("%p, %s, %p, %u, %p.\n", iface, debugstr_attr(key), value, size, length);
return attributes_GetString(&media_type->attributes, key, value, size, length);
}
static HRESULT WINAPI mediatype_GetAllocatedString(IMFMediaType *iface, REFGUID key,
WCHAR **value, UINT32 *length)
{
struct media_type *media_type = impl_from_IMFMediaType(iface);
TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), value, length);
return attributes_GetAllocatedString(&media_type->attributes, key, value, length);
}
static HRESULT WINAPI mediatype_GetBlobSize(IMFMediaType *iface, REFGUID key, UINT32 *size)
{
struct media_type *media_type = impl_from_IMFMediaType(iface);
TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), size);
return attributes_GetBlobSize(&media_type->attributes, key, size);
}
static HRESULT WINAPI mediatype_GetBlob(IMFMediaType *iface, REFGUID key, UINT8 *buf,
UINT32 bufsize, UINT32 *blobsize)
{
struct media_type *media_type = impl_from_IMFMediaType(iface);
TRACE("%p, %s, %p, %u, %p.\n", iface, debugstr_attr(key), buf, bufsize, blobsize);
return attributes_GetBlob(&media_type->attributes, key, buf, bufsize, blobsize);
}
static HRESULT WINAPI mediatype_GetAllocatedBlob(IMFMediaType *iface, REFGUID key, UINT8 **buf, UINT32 *size)
{
struct media_type *media_type = impl_from_IMFMediaType(iface);
TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), buf, size);
return attributes_GetAllocatedBlob(&media_type->attributes, key, buf, size);
}
static HRESULT WINAPI mediatype_GetUnknown(IMFMediaType *iface, REFGUID key, REFIID riid, void **obj)
{
struct media_type *media_type = impl_from_IMFMediaType(iface);
TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_guid(riid), obj);
return attributes_GetUnknown(&media_type->attributes, key, riid, obj);
}
static HRESULT WINAPI mediatype_SetItem(IMFMediaType *iface, REFGUID key, REFPROPVARIANT value)
{
struct media_type *media_type = impl_from_IMFMediaType(iface);
TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_propvar(value));
return attributes_SetItem(&media_type->attributes, key, value);
}
static HRESULT WINAPI mediatype_DeleteItem(IMFMediaType *iface, REFGUID key)
{
struct media_type *media_type = impl_from_IMFMediaType(iface);
TRACE("%p, %s.\n", iface, debugstr_attr(key));
return attributes_DeleteItem(&media_type->attributes, key);
}
static HRESULT WINAPI mediatype_DeleteAllItems(IMFMediaType *iface)
{
struct media_type *media_type = impl_from_IMFMediaType(iface);
TRACE("%p.\n", iface);
return attributes_DeleteAllItems(&media_type->attributes);
}
static HRESULT WINAPI mediatype_SetUINT32(IMFMediaType *iface, REFGUID key, UINT32 value)
{
struct media_type *media_type = impl_from_IMFMediaType(iface);
TRACE("%p, %s, %u.\n", iface, debugstr_attr(key), value);
return attributes_SetUINT32(&media_type->attributes, key, value);
}
static HRESULT WINAPI mediatype_SetUINT64(IMFMediaType *iface, REFGUID key, UINT64 value)
{
struct media_type *media_type = impl_from_IMFMediaType(iface);
TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), wine_dbgstr_longlong(value));
return attributes_SetUINT64(&media_type->attributes, key, value);
}
static HRESULT WINAPI mediatype_SetDouble(IMFMediaType *iface, REFGUID key, double value)
{
struct media_type *media_type = impl_from_IMFMediaType(iface);
TRACE("%p, %s, %f.\n", iface, debugstr_attr(key), value);
return attributes_SetDouble(&media_type->attributes, key, value);
}
static HRESULT WINAPI mediatype_SetGUID(IMFMediaType *iface, REFGUID key, REFGUID value)
{
struct media_type *media_type = impl_from_IMFMediaType(iface);
TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_mf_guid(value));
return attributes_SetGUID(&media_type->attributes, key, value);
}
static HRESULT WINAPI mediatype_SetString(IMFMediaType *iface, REFGUID key, const WCHAR *value)
{
struct media_type *media_type = impl_from_IMFMediaType(iface);
TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_w(value));
return attributes_SetString(&media_type->attributes, key, value);
}
static HRESULT WINAPI mediatype_SetBlob(IMFMediaType *iface, REFGUID key, const UINT8 *buf, UINT32 size)
{
struct media_type *media_type = impl_from_IMFMediaType(iface);
TRACE("%p, %s, %p, %u.\n", iface, debugstr_attr(key), buf, size);
return attributes_SetBlob(&media_type->attributes, key, buf, size);
}
static HRESULT WINAPI mediatype_SetUnknown(IMFMediaType *iface, REFGUID key, IUnknown *unknown)
{
struct media_type *media_type = impl_from_IMFMediaType(iface);
TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), unknown);
return attributes_SetUnknown(&media_type->attributes, key, unknown);
}
static HRESULT WINAPI mediatype_LockStore(IMFMediaType *iface)
{
struct media_type *media_type = impl_from_IMFMediaType(iface);
TRACE("%p.\n", iface);
return attributes_LockStore(&media_type->attributes);
}
static HRESULT WINAPI mediatype_UnlockStore(IMFMediaType *iface)
{
struct media_type *media_type = impl_from_IMFMediaType(iface);
TRACE("%p.\n", iface);
return attributes_UnlockStore(&media_type->attributes);
}
static HRESULT WINAPI mediatype_GetCount(IMFMediaType *iface, UINT32 *count)
{
struct media_type *media_type = impl_from_IMFMediaType(iface);
TRACE("%p, %p.\n", iface, count);
return attributes_GetCount(&media_type->attributes, count);
}
static HRESULT WINAPI mediatype_GetItemByIndex(IMFMediaType *iface, UINT32 index, GUID *key, PROPVARIANT *value)
{
struct media_type *media_type = impl_from_IMFMediaType(iface);
TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
return attributes_GetItemByIndex(&media_type->attributes, index, key, value);
}
static HRESULT WINAPI mediatype_CopyAllItems(IMFMediaType *iface, IMFAttributes *dest)
{
struct media_type *media_type = impl_from_IMFMediaType(iface);
TRACE("%p, %p.\n", iface, dest);
return attributes_CopyAllItems(&media_type->attributes, dest);
}
static HRESULT WINAPI mediatype_GetMajorType(IMFMediaType *iface, GUID *guid)
{
struct media_type *media_type = impl_from_IMFMediaType(iface);
TRACE("%p, %p.\n", iface, guid);
return attributes_GetGUID(&media_type->attributes, &MF_MT_MAJOR_TYPE, guid);
}
static HRESULT WINAPI mediatype_IsCompressedFormat(IMFMediaType *iface, BOOL *compressed)
{
struct media_type *media_type = impl_from_IMFMediaType(iface);
UINT32 value;
TRACE("%p, %p.\n", iface, compressed);
if (FAILED(attributes_GetUINT32(&media_type->attributes, &MF_MT_ALL_SAMPLES_INDEPENDENT, &value)))
{
value = 0;
}
*compressed = !value;
return S_OK;
}
static HRESULT WINAPI mediatype_IsEqual(IMFMediaType *iface, IMFMediaType *type, DWORD *flags)
{
const DWORD full_equality_flags = MF_MEDIATYPE_EQUAL_MAJOR_TYPES | MF_MEDIATYPE_EQUAL_FORMAT_TYPES |
MF_MEDIATYPE_EQUAL_FORMAT_DATA | MF_MEDIATYPE_EQUAL_FORMAT_USER_DATA;
struct media_type *media_type = impl_from_IMFMediaType(iface);
struct comparand
{
IMFAttributes *type;
PROPVARIANT value;
UINT32 count;
GUID guid;
HRESULT hr;
} left, right, swp;
unsigned int i;
BOOL result;
TRACE("%p, %p, %p.\n", iface, type, flags);
*flags = 0;
left.type = &media_type->attributes.IMFAttributes_iface;
right.type = (IMFAttributes *)type;
if (FAILED(IMFAttributes_GetGUID(left.type, &MF_MT_MAJOR_TYPE, &left.guid)))
return E_INVALIDARG;
if (FAILED(IMFAttributes_GetGUID(right.type, &MF_MT_MAJOR_TYPE, &right.guid)))
return E_INVALIDARG;
if (IsEqualGUID(&left.guid, &right.guid))
*flags |= MF_MEDIATYPE_EQUAL_MAJOR_TYPES;
/* Subtypes equal or both missing. */
left.hr = IMFAttributes_GetGUID(left.type, &MF_MT_SUBTYPE, &left.guid);
right.hr = IMFAttributes_GetGUID(right.type, &MF_MT_SUBTYPE, &right.guid);
if ((SUCCEEDED(left.hr) && SUCCEEDED(right.hr) && IsEqualGUID(&left.guid, &right.guid)) ||
(FAILED(left.hr) && FAILED(right.hr)))
{
*flags |= MF_MEDIATYPE_EQUAL_FORMAT_TYPES;
}
/* Format data */
IMFAttributes_GetCount(left.type, &left.count);
IMFAttributes_GetCount(right.type, &right.count);
if (right.count < left.count)
{
swp = left;
left = right;
right = swp;
}
*flags |= MF_MEDIATYPE_EQUAL_FORMAT_DATA;
for (i = 0; i < left.count; ++i)
{
PROPVARIANT value;
GUID key;
if (SUCCEEDED(IMFAttributes_GetItemByIndex(left.type, i, &key, &value)))
{
if (IsEqualGUID(&key, &MF_MT_USER_DATA) ||
IsEqualGUID(&key, &MF_MT_FRAME_RATE_RANGE_MIN) ||
IsEqualGUID(&key, &MF_MT_FRAME_RATE_RANGE_MAX))
{
PropVariantClear(&value);
continue;
}
result = FALSE;
IMFAttributes_CompareItem(right.type, &key, &value, &result);
PropVariantClear(&value);
if (!result)
{
*flags &= ~MF_MEDIATYPE_EQUAL_FORMAT_DATA;
break;
}
}
}
/* User data */
PropVariantInit(&left.value);
left.hr = IMFAttributes_GetItem(left.type, &MF_MT_USER_DATA, &left.value);
PropVariantInit(&right.value);
right.hr = IMFAttributes_GetItem(right.type, &MF_MT_USER_DATA, &right.value);
/* Compare user data if both types have it, otherwise simply check if both don't. */
if (SUCCEEDED(left.hr) && SUCCEEDED(right.hr))
{
result = FALSE;
IMFAttributes_CompareItem(left.type, &MF_MT_USER_DATA, &left.value, &result);
}
else
result = FAILED(left.hr) && FAILED(right.hr);
PropVariantClear(&left.value);
PropVariantClear(&right.value);
if (result)
*flags |= MF_MEDIATYPE_EQUAL_FORMAT_USER_DATA;
return *flags == full_equality_flags ? S_OK : S_FALSE;
}
static HRESULT WINAPI mediatype_GetRepresentation(IMFMediaType *iface, GUID guid, void **representation)
{
FIXME("%p, %s, %p.\n", iface, debugstr_guid(&guid), representation);
return E_NOTIMPL;
}
static HRESULT WINAPI mediatype_FreeRepresentation(IMFMediaType *iface, GUID guid, void *representation)
{
FIXME("%p, %s, %p.\n", iface, debugstr_guid(&guid), representation);
return E_NOTIMPL;
}
static const IMFMediaTypeVtbl mediatypevtbl =
{
mediatype_QueryInterface,
mediatype_AddRef,
mediatype_Release,
mediatype_GetItem,
mediatype_GetItemType,
mediatype_CompareItem,
mediatype_Compare,
mediatype_GetUINT32,
mediatype_GetUINT64,
mediatype_GetDouble,
mediatype_GetGUID,
mediatype_GetStringLength,
mediatype_GetString,
mediatype_GetAllocatedString,
mediatype_GetBlobSize,
mediatype_GetBlob,
mediatype_GetAllocatedBlob,
mediatype_GetUnknown,
mediatype_SetItem,
mediatype_DeleteItem,
mediatype_DeleteAllItems,
mediatype_SetUINT32,
mediatype_SetUINT64,
mediatype_SetDouble,
mediatype_SetGUID,
mediatype_SetString,
mediatype_SetBlob,
mediatype_SetUnknown,
mediatype_LockStore,
mediatype_UnlockStore,
mediatype_GetCount,
mediatype_GetItemByIndex,
mediatype_CopyAllItems,
mediatype_GetMajorType,
mediatype_IsCompressedFormat,
mediatype_IsEqual,
mediatype_GetRepresentation,
mediatype_FreeRepresentation
};
/***********************************************************************
* MFCreateMediaType (mfplat.@)
*/
HRESULT WINAPI MFCreateMediaType(IMFMediaType **media_type)
{
struct media_type *object;
HRESULT hr;
TRACE("%p.\n", media_type);
if (!media_type)
return E_INVALIDARG;
object = heap_alloc(sizeof(*object));
if (!object)
return E_OUTOFMEMORY;
if (FAILED(hr = init_attributes_object(&object->attributes, 0)))
{
heap_free(object);
return hr;
}
object->IMFMediaType_iface.lpVtbl = &mediatypevtbl;
*media_type = &object->IMFMediaType_iface;
TRACE("Created media type %p.\n", *media_type);
return S_OK;
}
static HRESULT WINAPI stream_descriptor_QueryInterface(IMFStreamDescriptor *iface, REFIID riid, void **out)
{
TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
if (IsEqualIID(riid, &IID_IMFStreamDescriptor) ||
IsEqualIID(riid, &IID_IMFAttributes) ||
IsEqualIID(riid, &IID_IUnknown))
{
*out = iface;
IMFStreamDescriptor_AddRef(iface);
return S_OK;
}
WARN("Unsupported %s.\n", debugstr_guid(riid));
*out = NULL;
return E_NOINTERFACE;
}
static ULONG WINAPI stream_descriptor_AddRef(IMFStreamDescriptor *iface)
{
struct stream_desc *stream_desc = impl_from_IMFStreamDescriptor(iface);
ULONG refcount = InterlockedIncrement(&stream_desc->attributes.ref);
TRACE("%p, refcount %u.\n", iface, refcount);
return refcount;
}
static ULONG WINAPI stream_descriptor_Release(IMFStreamDescriptor *iface)
{
struct stream_desc *stream_desc = impl_from_IMFStreamDescriptor(iface);
ULONG refcount = InterlockedDecrement(&stream_desc->attributes.ref);
unsigned int i;
TRACE("%p, refcount %u.\n", iface, refcount);
if (!refcount)
{
for (i = 0; i < stream_desc->media_types_count; ++i)
{
if (stream_desc->media_types[i])
IMFMediaType_Release(stream_desc->media_types[i]);
}
heap_free(stream_desc->media_types);
if (stream_desc->current_type)
IMFMediaType_Release(stream_desc->current_type);
clear_attributes_object(&stream_desc->attributes);
heap_free(stream_desc);
}
return refcount;
}
static HRESULT WINAPI stream_descriptor_GetItem(IMFStreamDescriptor *iface, REFGUID key, PROPVARIANT *value)
{
struct stream_desc *stream_desc = impl_from_IMFStreamDescriptor(iface);
TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
return attributes_GetItem(&stream_desc->attributes, key, value);
}
static HRESULT WINAPI stream_descriptor_GetItemType(IMFStreamDescriptor *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
{
struct stream_desc *stream_desc = impl_from_IMFStreamDescriptor(iface);
TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), type);
return attributes_GetItemType(&stream_desc->attributes, key, type);
}
static HRESULT WINAPI stream_descriptor_CompareItem(IMFStreamDescriptor *iface, REFGUID key, REFPROPVARIANT value,
BOOL *result)
{
struct stream_desc *stream_desc = impl_from_IMFStreamDescriptor(iface);
TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_propvar(value), result);
return attributes_CompareItem(&stream_desc->attributes, key, value, result);
}
static HRESULT WINAPI stream_descriptor_Compare(IMFStreamDescriptor *iface, IMFAttributes *theirs,
MF_ATTRIBUTES_MATCH_TYPE type, BOOL *result)
{
struct stream_desc *stream_desc = impl_from_IMFStreamDescriptor(iface);
TRACE("%p, %p, %d, %p.\n", iface, theirs, type, result);
return attributes_Compare(&stream_desc->attributes, theirs, type, result);
}
static HRESULT WINAPI stream_descriptor_GetUINT32(IMFStreamDescriptor *iface, REFGUID key, UINT32 *value)
{
struct stream_desc *stream_desc = impl_from_IMFStreamDescriptor(iface);
TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
return attributes_GetUINT32(&stream_desc->attributes, key, value);
}
static HRESULT WINAPI stream_descriptor_GetUINT64(IMFStreamDescriptor *iface, REFGUID key, UINT64 *value)
{
struct stream_desc *stream_desc = impl_from_IMFStreamDescriptor(iface);
TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
return attributes_GetUINT64(&stream_desc->attributes, key, value);
}
static HRESULT WINAPI stream_descriptor_GetDouble(IMFStreamDescriptor *iface, REFGUID key, double *value)
{
struct stream_desc *stream_desc = impl_from_IMFStreamDescriptor(iface);
TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
return attributes_GetDouble(&stream_desc->attributes, key, value);
}
static HRESULT WINAPI stream_descriptor_GetGUID(IMFStreamDescriptor *iface, REFGUID key, GUID *value)
{
struct stream_desc *stream_desc = impl_from_IMFStreamDescriptor(iface);
TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
return attributes_GetGUID(&stream_desc->attributes, key, value);
}
static HRESULT WINAPI stream_descriptor_GetStringLength(IMFStreamDescriptor *iface, REFGUID key, UINT32 *length)
{
struct stream_desc *stream_desc = impl_from_IMFStreamDescriptor(iface);
TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), length);
return attributes_GetStringLength(&stream_desc->attributes, key, length);
}
static HRESULT WINAPI stream_descriptor_GetString(IMFStreamDescriptor *iface, REFGUID key, WCHAR *value,
UINT32 size, UINT32 *length)
{
struct stream_desc *stream_desc = impl_from_IMFStreamDescriptor(iface);
TRACE("%p, %s, %p, %u, %p.\n", iface, debugstr_attr(key), value, size, length);
return attributes_GetString(&stream_desc->attributes, key, value, size, length);
}
static HRESULT WINAPI stream_descriptor_GetAllocatedString(IMFStreamDescriptor *iface, REFGUID key,
WCHAR **value, UINT32 *length)
{
struct stream_desc *stream_desc = impl_from_IMFStreamDescriptor(iface);
TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), value, length);
return attributes_GetAllocatedString(&stream_desc->attributes, key, value, length);
}
static HRESULT WINAPI stream_descriptor_GetBlobSize(IMFStreamDescriptor *iface, REFGUID key, UINT32 *size)
{
struct stream_desc *stream_desc = impl_from_IMFStreamDescriptor(iface);
TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), size);
return attributes_GetBlobSize(&stream_desc->attributes, key, size);
}
static HRESULT WINAPI stream_descriptor_GetBlob(IMFStreamDescriptor *iface, REFGUID key, UINT8 *buf,
UINT32 bufsize, UINT32 *blobsize)
{
struct stream_desc *stream_desc = impl_from_IMFStreamDescriptor(iface);
TRACE("%p, %s, %p, %u, %p.\n", iface, debugstr_attr(key), buf, bufsize, blobsize);
return attributes_GetBlob(&stream_desc->attributes, key, buf, bufsize, blobsize);
}
static HRESULT WINAPI stream_descriptor_GetAllocatedBlob(IMFStreamDescriptor *iface, REFGUID key, UINT8 **buf,
UINT32 *size)
{
struct stream_desc *stream_desc = impl_from_IMFStreamDescriptor(iface);
TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), buf, size);
return attributes_GetAllocatedBlob(&stream_desc->attributes, key, buf, size);
}
static HRESULT WINAPI stream_descriptor_GetUnknown(IMFStreamDescriptor *iface, REFGUID key, REFIID riid, void **out)
{
struct stream_desc *stream_desc = impl_from_IMFStreamDescriptor(iface);
TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_guid(riid), out);
return attributes_GetUnknown(&stream_desc->attributes, key, riid, out);
}
static HRESULT WINAPI stream_descriptor_SetItem(IMFStreamDescriptor *iface, REFGUID key, REFPROPVARIANT value)
{
struct stream_desc *stream_desc = impl_from_IMFStreamDescriptor(iface);
TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_propvar(value));
return attributes_SetItem(&stream_desc->attributes, key, value);
}
static HRESULT WINAPI stream_descriptor_DeleteItem(IMFStreamDescriptor *iface, REFGUID key)
{
struct stream_desc *stream_desc = impl_from_IMFStreamDescriptor(iface);
TRACE("%p, %s.\n", iface, debugstr_attr(key));
return attributes_DeleteItem(&stream_desc->attributes, key);
}
static HRESULT WINAPI stream_descriptor_DeleteAllItems(IMFStreamDescriptor *iface)
{
struct stream_desc *stream_desc = impl_from_IMFStreamDescriptor(iface);
TRACE("%p.\n", iface);
return attributes_DeleteAllItems(&stream_desc->attributes);
}
static HRESULT WINAPI stream_descriptor_SetUINT32(IMFStreamDescriptor *iface, REFGUID key, UINT32 value)
{
struct stream_desc *stream_desc = impl_from_IMFStreamDescriptor(iface);
TRACE("%p, %s, %u.\n", iface, debugstr_attr(key), value);
return attributes_SetUINT32(&stream_desc->attributes, key, value);
}
static HRESULT WINAPI stream_descriptor_SetUINT64(IMFStreamDescriptor *iface, REFGUID key, UINT64 value)
{
struct stream_desc *stream_desc = impl_from_IMFStreamDescriptor(iface);
TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), wine_dbgstr_longlong(value));
return attributes_SetUINT64(&stream_desc->attributes, key, value);
}
static HRESULT WINAPI stream_descriptor_SetDouble(IMFStreamDescriptor *iface, REFGUID key, double value)
{
struct stream_desc *stream_desc = impl_from_IMFStreamDescriptor(iface);
TRACE("%p, %s, %f.\n", iface, debugstr_attr(key), value);
return attributes_SetDouble(&stream_desc->attributes, key, value);
}
static HRESULT WINAPI stream_descriptor_SetGUID(IMFStreamDescriptor *iface, REFGUID key, REFGUID value)
{
struct stream_desc *stream_desc = impl_from_IMFStreamDescriptor(iface);
TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_mf_guid(value));
return attributes_SetGUID(&stream_desc->attributes, key, value);
}
static HRESULT WINAPI stream_descriptor_SetString(IMFStreamDescriptor *iface, REFGUID key, const WCHAR *value)
{
struct stream_desc *stream_desc = impl_from_IMFStreamDescriptor(iface);
TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_w(value));
return attributes_SetString(&stream_desc->attributes, key, value);
}
static HRESULT WINAPI stream_descriptor_SetBlob(IMFStreamDescriptor *iface, REFGUID key, const UINT8 *buf, UINT32 size)
{
struct stream_desc *stream_desc = impl_from_IMFStreamDescriptor(iface);
TRACE("%p, %s, %p, %u.\n", iface, debugstr_attr(key), buf, size);
return attributes_SetBlob(&stream_desc->attributes, key, buf, size);
}
static HRESULT WINAPI stream_descriptor_SetUnknown(IMFStreamDescriptor *iface, REFGUID key, IUnknown *unknown)
{
struct stream_desc *stream_desc = impl_from_IMFStreamDescriptor(iface);
TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), unknown);
return attributes_SetUnknown(&stream_desc->attributes, key, unknown);
}
static HRESULT WINAPI stream_descriptor_LockStore(IMFStreamDescriptor *iface)
{
struct stream_desc *stream_desc = impl_from_IMFStreamDescriptor(iface);
TRACE("%p.\n", iface);
return attributes_LockStore(&stream_desc->attributes);
}
static HRESULT WINAPI stream_descriptor_UnlockStore(IMFStreamDescriptor *iface)
{
struct stream_desc *stream_desc = impl_from_IMFStreamDescriptor(iface);
TRACE("%p.\n", iface);
return attributes_UnlockStore(&stream_desc->attributes);
}
static HRESULT WINAPI stream_descriptor_GetCount(IMFStreamDescriptor *iface, UINT32 *count)
{
struct stream_desc *stream_desc = impl_from_IMFStreamDescriptor(iface);
TRACE("%p, %p.\n", iface, count);
return attributes_GetCount(&stream_desc->attributes, count);
}
static HRESULT WINAPI stream_descriptor_GetItemByIndex(IMFStreamDescriptor *iface, UINT32 index, GUID *key,
PROPVARIANT *value)
{
struct stream_desc *stream_desc = impl_from_IMFStreamDescriptor(iface);
TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
return attributes_GetItemByIndex(&stream_desc->attributes, index, key, value);
}
static HRESULT WINAPI stream_descriptor_CopyAllItems(IMFStreamDescriptor *iface, IMFAttributes *dest)
{
struct stream_desc *stream_desc = impl_from_IMFStreamDescriptor(iface);
TRACE("%p, %p.\n", iface, dest);
return attributes_CopyAllItems(&stream_desc->attributes, dest);
}
static HRESULT WINAPI stream_descriptor_GetStreamIdentifier(IMFStreamDescriptor *iface, DWORD *identifier)
{
struct stream_desc *stream_desc = impl_from_IMFStreamDescriptor(iface);
TRACE("%p, %p.\n", iface, identifier);
*identifier = stream_desc->identifier;
return S_OK;
}
static HRESULT WINAPI stream_descriptor_GetMediaTypeHandler(IMFStreamDescriptor *iface, IMFMediaTypeHandler **handler)
{
struct stream_desc *stream_desc = impl_from_IMFStreamDescriptor(iface);
TRACE("%p, %p.\n", iface, handler);
*handler = &stream_desc->IMFMediaTypeHandler_iface;
IMFMediaTypeHandler_AddRef(*handler);
return S_OK;
}
static const IMFStreamDescriptorVtbl streamdescriptorvtbl =
{
stream_descriptor_QueryInterface,
stream_descriptor_AddRef,
stream_descriptor_Release,
stream_descriptor_GetItem,
stream_descriptor_GetItemType,
stream_descriptor_CompareItem,
stream_descriptor_Compare,
stream_descriptor_GetUINT32,
stream_descriptor_GetUINT64,
stream_descriptor_GetDouble,
stream_descriptor_GetGUID,
stream_descriptor_GetStringLength,
stream_descriptor_GetString,
stream_descriptor_GetAllocatedString,
stream_descriptor_GetBlobSize,
stream_descriptor_GetBlob,
stream_descriptor_GetAllocatedBlob,
stream_descriptor_GetUnknown,
stream_descriptor_SetItem,
stream_descriptor_DeleteItem,
stream_descriptor_DeleteAllItems,
stream_descriptor_SetUINT32,
stream_descriptor_SetUINT64,
stream_descriptor_SetDouble,
stream_descriptor_SetGUID,
stream_descriptor_SetString,
stream_descriptor_SetBlob,
stream_descriptor_SetUnknown,
stream_descriptor_LockStore,
stream_descriptor_UnlockStore,
stream_descriptor_GetCount,
stream_descriptor_GetItemByIndex,
stream_descriptor_CopyAllItems,
stream_descriptor_GetStreamIdentifier,
stream_descriptor_GetMediaTypeHandler
};
static HRESULT WINAPI mediatype_handler_QueryInterface(IMFMediaTypeHandler *iface, REFIID riid, void **obj)
{
TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
if (IsEqualIID(riid, &IID_IMFMediaTypeHandler) ||
IsEqualIID(riid, &IID_IUnknown))
{
*obj = iface;
IMFMediaTypeHandler_AddRef(iface);
return S_OK;
}
WARN("Unsupported %s.\n", debugstr_guid(riid));
*obj = NULL;
return E_NOINTERFACE;
}
static ULONG WINAPI mediatype_handler_AddRef(IMFMediaTypeHandler *iface)
{
struct stream_desc *stream_desc = impl_from_IMFMediaTypeHandler(iface);
return IMFStreamDescriptor_AddRef(&stream_desc->IMFStreamDescriptor_iface);
}
static ULONG WINAPI mediatype_handler_Release(IMFMediaTypeHandler *iface)
{
struct stream_desc *stream_desc = impl_from_IMFMediaTypeHandler(iface);
return IMFStreamDescriptor_Release(&stream_desc->IMFStreamDescriptor_iface);
}
static BOOL stream_descriptor_is_mediatype_supported(IMFMediaType *media_type, IMFMediaType *candidate)
{
DWORD flags = 0;
if (FAILED(IMFMediaType_IsEqual(media_type, candidate, &flags)))
return FALSE;
return (flags & (MF_MEDIATYPE_EQUAL_MAJOR_TYPES | MF_MEDIATYPE_EQUAL_FORMAT_TYPES)) ==
(MF_MEDIATYPE_EQUAL_MAJOR_TYPES | MF_MEDIATYPE_EQUAL_FORMAT_TYPES);
}
static HRESULT WINAPI mediatype_handler_IsMediaTypeSupported(IMFMediaTypeHandler *iface, IMFMediaType *in_type,
IMFMediaType **out_type)
{
struct stream_desc *stream_desc = impl_from_IMFMediaTypeHandler(iface);
BOOL supported = FALSE;
unsigned int i;
TRACE("%p, %p, %p.\n", iface, in_type, out_type);
if (!in_type)
return E_POINTER;
if (out_type)
*out_type = NULL;
EnterCriticalSection(&stream_desc->attributes.cs);
supported = stream_desc->current_type && stream_descriptor_is_mediatype_supported(stream_desc->current_type, in_type);
if (!supported)
{
for (i = 0; i < stream_desc->media_types_count; ++i)
{
if ((supported = stream_descriptor_is_mediatype_supported(stream_desc->media_types[i], in_type)))
break;
}
}
LeaveCriticalSection(&stream_desc->attributes.cs);
return supported ? S_OK : MF_E_INVALIDMEDIATYPE;
}
static HRESULT WINAPI mediatype_handler_GetMediaTypeCount(IMFMediaTypeHandler *iface, DWORD *count)
{
struct stream_desc *stream_desc = impl_from_IMFMediaTypeHandler(iface);
TRACE("%p, %p.\n", iface, count);
*count = stream_desc->media_types_count;
return S_OK;
}
static HRESULT WINAPI mediatype_handler_GetMediaTypeByIndex(IMFMediaTypeHandler *iface, DWORD index,
IMFMediaType **type)
{
struct stream_desc *stream_desc = impl_from_IMFMediaTypeHandler(iface);
TRACE("%p, %u, %p.\n", iface, index, type);
if (index >= stream_desc->media_types_count)
return MF_E_NO_MORE_TYPES;
if (stream_desc->media_types[index])
{
*type = stream_desc->media_types[index];
IMFMediaType_AddRef(*type);
}
return stream_desc->media_types[index] ? S_OK : E_FAIL;
}
static HRESULT WINAPI mediatype_handler_SetCurrentMediaType(IMFMediaTypeHandler *iface, IMFMediaType *type)
{
struct stream_desc *stream_desc = impl_from_IMFMediaTypeHandler(iface);
TRACE("%p, %p.\n", iface, type);
if (!type)
return E_POINTER;
EnterCriticalSection(&stream_desc->attributes.cs);
if (stream_desc->current_type)
IMFMediaType_Release(stream_desc->current_type);
stream_desc->current_type = type;
IMFMediaType_AddRef(stream_desc->current_type);
LeaveCriticalSection(&stream_desc->attributes.cs);
return S_OK;
}
static HRESULT WINAPI mediatype_handler_GetCurrentMediaType(IMFMediaTypeHandler *iface, IMFMediaType **type)
{
struct stream_desc *stream_desc = impl_from_IMFMediaTypeHandler(iface);
HRESULT hr = S_OK;
TRACE("%p, %p.\n", iface, type);
EnterCriticalSection(&stream_desc->attributes.cs);
if (stream_desc->current_type)
{
*type = stream_desc->current_type;
IMFMediaType_AddRef(*type);
}
else
hr = MF_E_NOT_INITIALIZED;
LeaveCriticalSection(&stream_desc->attributes.cs);
return hr;
}
static HRESULT WINAPI mediatype_handler_GetMajorType(IMFMediaTypeHandler *iface, GUID *type)
{
struct stream_desc *stream_desc = impl_from_IMFMediaTypeHandler(iface);
HRESULT hr;
TRACE("%p, %p.\n", iface, type);
EnterCriticalSection(&stream_desc->attributes.cs);
if (stream_desc->current_type)
hr = IMFMediaType_GetGUID(stream_desc->current_type, &MF_MT_MAJOR_TYPE, type);
else
hr = MF_E_ATTRIBUTENOTFOUND;
LeaveCriticalSection(&stream_desc->attributes.cs);
return hr;
}
static const IMFMediaTypeHandlerVtbl mediatypehandlervtbl =
{
mediatype_handler_QueryInterface,
mediatype_handler_AddRef,
mediatype_handler_Release,
mediatype_handler_IsMediaTypeSupported,
mediatype_handler_GetMediaTypeCount,
mediatype_handler_GetMediaTypeByIndex,
mediatype_handler_SetCurrentMediaType,
mediatype_handler_GetCurrentMediaType,
mediatype_handler_GetMajorType,
};
/***********************************************************************
* MFCreateStreamDescriptor (mfplat.@)
*/
HRESULT WINAPI MFCreateStreamDescriptor(DWORD identifier, DWORD count,
IMFMediaType **types, IMFStreamDescriptor **descriptor)
{
struct stream_desc *object;
unsigned int i;
HRESULT hr;
TRACE("%d, %d, %p, %p.\n", identifier, count, types, descriptor);
if (!count)
return E_INVALIDARG;
object = heap_alloc_zero(sizeof(*object));
if (!object)
return E_OUTOFMEMORY;
if (FAILED(hr = init_attributes_object(&object->attributes, 0)))
{
heap_free(object);
return hr;
}
object->IMFStreamDescriptor_iface.lpVtbl = &streamdescriptorvtbl;
object->IMFMediaTypeHandler_iface.lpVtbl = &mediatypehandlervtbl;
object->identifier = identifier;
object->media_types = heap_alloc(count * sizeof(*object->media_types));
if (!object->media_types)
{
IMFStreamDescriptor_Release(&object->IMFStreamDescriptor_iface);
return E_OUTOFMEMORY;
}
for (i = 0; i < count; ++i)
{
object->media_types[i] = types[i];
if (object->media_types[i])
IMFMediaType_AddRef(object->media_types[i]);
}
object->media_types_count = count;
*descriptor = &object->IMFStreamDescriptor_iface;
return S_OK;
}
static HRESULT WINAPI presentation_descriptor_QueryInterface(IMFPresentationDescriptor *iface, REFIID riid, void **out)
{
TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
if (IsEqualIID(riid, &IID_IMFPresentationDescriptor) ||
IsEqualIID(riid, &IID_IMFAttributes) ||
IsEqualIID(riid, &IID_IUnknown))
{
*out = iface;
IMFPresentationDescriptor_AddRef(iface);
return S_OK;
}
WARN("Unsupported %s.\n", debugstr_guid(riid));
*out = NULL;
return E_NOINTERFACE;
}
static ULONG WINAPI presentation_descriptor_AddRef(IMFPresentationDescriptor *iface)
{
struct presentation_desc *presentation_desc = impl_from_IMFPresentationDescriptor(iface);
ULONG refcount = InterlockedIncrement(&presentation_desc->attributes.ref);
TRACE("%p, refcount %u.\n", iface, refcount);
return refcount;
}
static ULONG WINAPI presentation_descriptor_Release(IMFPresentationDescriptor *iface)
{
struct presentation_desc *presentation_desc = impl_from_IMFPresentationDescriptor(iface);
ULONG refcount = InterlockedDecrement(&presentation_desc->attributes.ref);
unsigned int i;
TRACE("%p, refcount %u.\n", iface, refcount);
if (!refcount)
{
for (i = 0; i < presentation_desc->count; ++i)
{
if (presentation_desc->descriptors[i].descriptor)
IMFStreamDescriptor_Release(presentation_desc->descriptors[i].descriptor);
}
clear_attributes_object(&presentation_desc->attributes);
heap_free(presentation_desc->descriptors);
heap_free(presentation_desc);
}
return refcount;
}
static HRESULT WINAPI presentation_descriptor_GetItem(IMFPresentationDescriptor *iface, REFGUID key,
PROPVARIANT *value)
{
struct presentation_desc *presentation_desc = impl_from_IMFPresentationDescriptor(iface);
TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
return attributes_GetItem(&presentation_desc->attributes, key, value);
}
static HRESULT WINAPI presentation_descriptor_GetItemType(IMFPresentationDescriptor *iface, REFGUID key,
MF_ATTRIBUTE_TYPE *type)
{
struct presentation_desc *presentation_desc = impl_from_IMFPresentationDescriptor(iface);
TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), type);
return attributes_GetItemType(&presentation_desc->attributes, key, type);
}
static HRESULT WINAPI presentation_descriptor_CompareItem(IMFPresentationDescriptor *iface, REFGUID key,
REFPROPVARIANT value, BOOL *result)
{
struct presentation_desc *presentation_desc = impl_from_IMFPresentationDescriptor(iface);
TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_propvar(value), result);
return attributes_CompareItem(&presentation_desc->attributes, key, value, result);
}
static HRESULT WINAPI presentation_descriptor_Compare(IMFPresentationDescriptor *iface, IMFAttributes *attrs,
MF_ATTRIBUTES_MATCH_TYPE type, BOOL *result)
{
struct presentation_desc *presentation_desc = impl_from_IMFPresentationDescriptor(iface);
TRACE("%p, %p, %d, %p.\n", iface, attrs, type, result);
return attributes_Compare(&presentation_desc->attributes, attrs, type, result);
}
static HRESULT WINAPI presentation_descriptor_GetUINT32(IMFPresentationDescriptor *iface, REFGUID key, UINT32 *value)
{
struct presentation_desc *presentation_desc = impl_from_IMFPresentationDescriptor(iface);
TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
return attributes_GetUINT32(&presentation_desc->attributes, key, value);
}
static HRESULT WINAPI presentation_descriptor_GetUINT64(IMFPresentationDescriptor *iface, REFGUID key, UINT64 *value)
{
struct presentation_desc *presentation_desc = impl_from_IMFPresentationDescriptor(iface);
TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
return attributes_GetUINT64(&presentation_desc->attributes, key, value);
}
static HRESULT WINAPI presentation_descriptor_GetDouble(IMFPresentationDescriptor *iface, REFGUID key, double *value)
{
struct presentation_desc *presentation_desc = impl_from_IMFPresentationDescriptor(iface);
TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
return attributes_GetDouble(&presentation_desc->attributes, key, value);
}
static HRESULT WINAPI presentation_descriptor_GetGUID(IMFPresentationDescriptor *iface, REFGUID key, GUID *value)
{
struct presentation_desc *presentation_desc = impl_from_IMFPresentationDescriptor(iface);
TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
return attributes_GetGUID(&presentation_desc->attributes, key, value);
}
static HRESULT WINAPI presentation_descriptor_GetStringLength(IMFPresentationDescriptor *iface, REFGUID key,
UINT32 *length)
{
struct presentation_desc *presentation_desc = impl_from_IMFPresentationDescriptor(iface);
TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), length);
return attributes_GetStringLength(&presentation_desc->attributes, key, length);
}
static HRESULT WINAPI presentation_descriptor_GetString(IMFPresentationDescriptor *iface, REFGUID key, WCHAR *value,
UINT32 size, UINT32 *length)
{
struct presentation_desc *presentation_desc = impl_from_IMFPresentationDescriptor(iface);
TRACE("%p, %s, %p, %u, %p.\n", iface, debugstr_attr(key), value, size, length);
return attributes_GetString(&presentation_desc->attributes, key, value, size, length);
}
static HRESULT WINAPI presentation_descriptor_GetAllocatedString(IMFPresentationDescriptor *iface, REFGUID key,
WCHAR **value, UINT32 *length)
{
struct presentation_desc *presentation_desc = impl_from_IMFPresentationDescriptor(iface);
TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), value, length);
return attributes_GetAllocatedString(&presentation_desc->attributes, key, value, length);
}
static HRESULT WINAPI presentation_descriptor_GetBlobSize(IMFPresentationDescriptor *iface, REFGUID key, UINT32 *size)
{
struct presentation_desc *presentation_desc = impl_from_IMFPresentationDescriptor(iface);
TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), size);
return attributes_GetBlobSize(&presentation_desc->attributes, key, size);
}
static HRESULT WINAPI presentation_descriptor_GetBlob(IMFPresentationDescriptor *iface, REFGUID key, UINT8 *buf,
UINT32 bufsize, UINT32 *blobsize)
{
struct presentation_desc *presentation_desc = impl_from_IMFPresentationDescriptor(iface);
TRACE("%p, %s, %p, %u, %p.\n", iface, debugstr_attr(key), buf, bufsize, blobsize);
return attributes_GetBlob(&presentation_desc->attributes, key, buf, bufsize, blobsize);
}
static HRESULT WINAPI presentation_descriptor_GetAllocatedBlob(IMFPresentationDescriptor *iface, REFGUID key,
UINT8 **buf, UINT32 *size)
{
struct presentation_desc *presentation_desc = impl_from_IMFPresentationDescriptor(iface);
TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), buf, size);
return attributes_GetAllocatedBlob(&presentation_desc->attributes, key, buf, size);
}
static HRESULT WINAPI presentation_descriptor_GetUnknown(IMFPresentationDescriptor *iface, REFGUID key,
REFIID riid, void **out)
{
struct presentation_desc *presentation_desc = impl_from_IMFPresentationDescriptor(iface);
TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_guid(riid), out);
return attributes_GetUnknown(&presentation_desc->attributes, key, riid, out);
}
static HRESULT WINAPI presentation_descriptor_SetItem(IMFPresentationDescriptor *iface, REFGUID key,
REFPROPVARIANT value)
{
struct presentation_desc *presentation_desc = impl_from_IMFPresentationDescriptor(iface);
TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_propvar(value));
return attributes_SetItem(&presentation_desc->attributes, key, value);
}
static HRESULT WINAPI presentation_descriptor_DeleteItem(IMFPresentationDescriptor *iface, REFGUID key)
{
struct presentation_desc *presentation_desc = impl_from_IMFPresentationDescriptor(iface);
TRACE("%p, %s.\n", iface, debugstr_attr(key));
return attributes_DeleteItem(&presentation_desc->attributes, key);
}
static HRESULT WINAPI presentation_descriptor_DeleteAllItems(IMFPresentationDescriptor *iface)
{
struct presentation_desc *presentation_desc = impl_from_IMFPresentationDescriptor(iface);
TRACE("%p.\n", iface);
return attributes_DeleteAllItems(&presentation_desc->attributes);
}
static HRESULT WINAPI presentation_descriptor_SetUINT32(IMFPresentationDescriptor *iface, REFGUID key, UINT32 value)
{
struct presentation_desc *presentation_desc = impl_from_IMFPresentationDescriptor(iface);
TRACE("%p, %s, %u.\n", iface, debugstr_attr(key), value);
return attributes_SetUINT32(&presentation_desc->attributes, key, value);
}
static HRESULT WINAPI presentation_descriptor_SetUINT64(IMFPresentationDescriptor *iface, REFGUID key, UINT64 value)
{
struct presentation_desc *presentation_desc = impl_from_IMFPresentationDescriptor(iface);
TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), wine_dbgstr_longlong(value));
return attributes_SetUINT64(&presentation_desc->attributes, key, value);
}
static HRESULT WINAPI presentation_descriptor_SetDouble(IMFPresentationDescriptor *iface, REFGUID key, double value)
{
struct presentation_desc *presentation_desc = impl_from_IMFPresentationDescriptor(iface);
TRACE("%p, %s, %f.\n", iface, debugstr_attr(key), value);
return attributes_SetDouble(&presentation_desc->attributes, key, value);
}
static HRESULT WINAPI presentation_descriptor_SetGUID(IMFPresentationDescriptor *iface, REFGUID key, REFGUID value)
{
struct presentation_desc *presentation_desc = impl_from_IMFPresentationDescriptor(iface);
TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_mf_guid(value));
return attributes_SetGUID(&presentation_desc->attributes, key, value);
}
static HRESULT WINAPI presentation_descriptor_SetString(IMFPresentationDescriptor *iface, REFGUID key,
const WCHAR *value)
{
struct presentation_desc *presentation_desc = impl_from_IMFPresentationDescriptor(iface);
TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_w(value));
return attributes_SetString(&presentation_desc->attributes, key, value);
}
static HRESULT WINAPI presentation_descriptor_SetBlob(IMFPresentationDescriptor *iface, REFGUID key, const UINT8 *buf,
UINT32 size)
{
struct presentation_desc *presentation_desc = impl_from_IMFPresentationDescriptor(iface);
TRACE("%p, %s, %p, %u.\n", iface, debugstr_attr(key), buf, size);
return attributes_SetBlob(&presentation_desc->attributes, key, buf, size);
}
static HRESULT WINAPI presentation_descriptor_SetUnknown(IMFPresentationDescriptor *iface, REFGUID key,
IUnknown *unknown)
{
struct presentation_desc *presentation_desc = impl_from_IMFPresentationDescriptor(iface);
TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), unknown);
return attributes_SetUnknown(&presentation_desc->attributes, key, unknown);
}
static HRESULT WINAPI presentation_descriptor_LockStore(IMFPresentationDescriptor *iface)
{
struct presentation_desc *presentation_desc = impl_from_IMFPresentationDescriptor(iface);
TRACE("%p.\n", iface);
return attributes_LockStore(&presentation_desc->attributes);
}
static HRESULT WINAPI presentation_descriptor_UnlockStore(IMFPresentationDescriptor *iface)
{
struct presentation_desc *presentation_desc = impl_from_IMFPresentationDescriptor(iface);
TRACE("%p.\n", iface);
return attributes_UnlockStore(&presentation_desc->attributes);
}
static HRESULT WINAPI presentation_descriptor_GetCount(IMFPresentationDescriptor *iface, UINT32 *count)
{
struct presentation_desc *presentation_desc = impl_from_IMFPresentationDescriptor(iface);
TRACE("%p, %p.\n", iface, count);
return attributes_GetCount(&presentation_desc->attributes, count);
}
static HRESULT WINAPI presentation_descriptor_GetItemByIndex(IMFPresentationDescriptor *iface, UINT32 index, GUID *key,
PROPVARIANT *value)
{
struct presentation_desc *presentation_desc = impl_from_IMFPresentationDescriptor(iface);
TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
return attributes_GetItemByIndex(&presentation_desc->attributes, index, key, value);
}
static HRESULT WINAPI presentation_descriptor_CopyAllItems(IMFPresentationDescriptor *iface, IMFAttributes *dest)
{
struct presentation_desc *presentation_desc = impl_from_IMFPresentationDescriptor(iface);
TRACE("%p, %p.\n", iface, dest);
return attributes_CopyAllItems(&presentation_desc->attributes, dest);
}
static HRESULT WINAPI presentation_descriptor_GetStreamDescriptorCount(IMFPresentationDescriptor *iface, DWORD *count)
{
struct presentation_desc *presentation_desc = impl_from_IMFPresentationDescriptor(iface);
TRACE("%p, %p.\n", iface, count);
*count = presentation_desc->count;
return S_OK;
}
static HRESULT WINAPI presentation_descriptor_GetStreamDescriptorByIndex(IMFPresentationDescriptor *iface, DWORD index,
BOOL *selected, IMFStreamDescriptor **descriptor)
{
struct presentation_desc *presentation_desc = impl_from_IMFPresentationDescriptor(iface);
TRACE("%p, %u, %p, %p.\n", iface, index, selected, descriptor);
if (index >= presentation_desc->count)
return E_INVALIDARG;
EnterCriticalSection(&presentation_desc->attributes.cs);
*selected = presentation_desc->descriptors[index].selected;
LeaveCriticalSection(&presentation_desc->attributes.cs);
*descriptor = presentation_desc->descriptors[index].descriptor;
IMFStreamDescriptor_AddRef(*descriptor);
return S_OK;
}
static HRESULT WINAPI presentation_descriptor_SelectStream(IMFPresentationDescriptor *iface, DWORD index)
{
struct presentation_desc *presentation_desc = impl_from_IMFPresentationDescriptor(iface);
TRACE("%p, %u.\n", iface, index);
if (index >= presentation_desc->count)
return E_INVALIDARG;
EnterCriticalSection(&presentation_desc->attributes.cs);
presentation_desc->descriptors[index].selected = TRUE;
LeaveCriticalSection(&presentation_desc->attributes.cs);
return S_OK;
}
static HRESULT WINAPI presentation_descriptor_DeselectStream(IMFPresentationDescriptor *iface, DWORD index)
{
struct presentation_desc *presentation_desc = impl_from_IMFPresentationDescriptor(iface);
TRACE("%p, %u.\n", iface, index);
if (index >= presentation_desc->count)
return E_INVALIDARG;
EnterCriticalSection(&presentation_desc->attributes.cs);
presentation_desc->descriptors[index].selected = FALSE;
LeaveCriticalSection(&presentation_desc->attributes.cs);
return S_OK;
}
static HRESULT WINAPI presentation_descriptor_Clone(IMFPresentationDescriptor *iface,
IMFPresentationDescriptor **descriptor)
{
struct presentation_desc *presentation_desc = impl_from_IMFPresentationDescriptor(iface);
struct presentation_desc *object;
unsigned int i;
TRACE("%p, %p.\n", iface, descriptor);
object = heap_alloc_zero(sizeof(*object));
if (!object)
return E_OUTOFMEMORY;
presentation_descriptor_init(object, presentation_desc->count);
EnterCriticalSection(&presentation_desc->attributes.cs);
for (i = 0; i < presentation_desc->count; ++i)
{
object->descriptors[i] = presentation_desc->descriptors[i];
IMFStreamDescriptor_AddRef(object->descriptors[i].descriptor);
}
attributes_CopyAllItems(&presentation_desc->attributes, (IMFAttributes *)&object->IMFPresentationDescriptor_iface);
LeaveCriticalSection(&presentation_desc->attributes.cs);
*descriptor = &object->IMFPresentationDescriptor_iface;
return S_OK;
}
static const IMFPresentationDescriptorVtbl presentationdescriptorvtbl =
{
presentation_descriptor_QueryInterface,
presentation_descriptor_AddRef,
presentation_descriptor_Release,
presentation_descriptor_GetItem,
presentation_descriptor_GetItemType,
presentation_descriptor_CompareItem,
presentation_descriptor_Compare,
presentation_descriptor_GetUINT32,
presentation_descriptor_GetUINT64,
presentation_descriptor_GetDouble,
presentation_descriptor_GetGUID,
presentation_descriptor_GetStringLength,
presentation_descriptor_GetString,
presentation_descriptor_GetAllocatedString,
presentation_descriptor_GetBlobSize,
presentation_descriptor_GetBlob,
presentation_descriptor_GetAllocatedBlob,
presentation_descriptor_GetUnknown,
presentation_descriptor_SetItem,
presentation_descriptor_DeleteItem,
presentation_descriptor_DeleteAllItems,
presentation_descriptor_SetUINT32,
presentation_descriptor_SetUINT64,
presentation_descriptor_SetDouble,
presentation_descriptor_SetGUID,
presentation_descriptor_SetString,
presentation_descriptor_SetBlob,
presentation_descriptor_SetUnknown,
presentation_descriptor_LockStore,
presentation_descriptor_UnlockStore,
presentation_descriptor_GetCount,
presentation_descriptor_GetItemByIndex,
presentation_descriptor_CopyAllItems,
presentation_descriptor_GetStreamDescriptorCount,
presentation_descriptor_GetStreamDescriptorByIndex,
presentation_descriptor_SelectStream,
presentation_descriptor_DeselectStream,
presentation_descriptor_Clone,
};
static HRESULT presentation_descriptor_init(struct presentation_desc *object, DWORD count)
{
HRESULT hr;
if (FAILED(hr = init_attributes_object(&object->attributes, 0)))
return hr;
object->IMFPresentationDescriptor_iface.lpVtbl = &presentationdescriptorvtbl;
object->descriptors = heap_alloc_zero(count * sizeof(*object->descriptors));
if (!object->descriptors)
{
IMFPresentationDescriptor_Release(&object->IMFPresentationDescriptor_iface);
return E_OUTOFMEMORY;
}
object->count = count;
return S_OK;
}
/***********************************************************************
* MFCreatePresentationDescriptor (mfplat.@)
*/
HRESULT WINAPI MFCreatePresentationDescriptor(DWORD count, IMFStreamDescriptor **descriptors,
IMFPresentationDescriptor **out)
{
struct presentation_desc *object;
unsigned int i;
HRESULT hr;
TRACE("%u, %p, %p.\n", count, descriptors, out);
if (!count)
return E_INVALIDARG;
for (i = 0; i < count; ++i)
{
if (!descriptors[i])
return E_INVALIDARG;
}
object = heap_alloc_zero(sizeof(*object));
if (!object)
return E_OUTOFMEMORY;
if (FAILED(hr = presentation_descriptor_init(object, count)))
{
heap_free(object);
return hr;
}
for (i = 0; i < count; ++i)
{
object->descriptors[i].descriptor = descriptors[i];
IMFStreamDescriptor_AddRef(object->descriptors[i].descriptor);
}
*out = &object->IMFPresentationDescriptor_iface;
return S_OK;
}
struct uncompressed_video_format
{
const GUID *subtype;
unsigned char bytes_per_pixel;
unsigned char alignment;
unsigned char bottom_up;
unsigned char yuv;
};
static int __cdecl uncompressed_video_format_compare(const void *a, const void *b)
{
const GUID *guid = a;
const struct uncompressed_video_format *format = b;
return memcmp(guid, format->subtype, sizeof(*guid));
}
static const struct uncompressed_video_format video_formats[] =
{
{ &MFVideoFormat_RGB24, 4, 3, 1, 0 },
{ &MFVideoFormat_ARGB32, 4, 3, 1, 0 },
{ &MFVideoFormat_RGB32, 4, 3, 1, 0 },
{ &MFVideoFormat_RGB565, 2, 3, 1, 0 },
{ &MFVideoFormat_RGB555, 2, 3, 1, 0 },
{ &MFVideoFormat_A2R10G10B10, 4, 3, 1, 0 },
{ &MFVideoFormat_RGB8, 1, 3, 1, 0 },
{ &MFVideoFormat_L8, 1, 3, 1, 0 },
{ &MFVideoFormat_AYUV, 4, 3, 0, 1 },
{ &MFVideoFormat_IMC1, 2, 3, 0, 1 },
{ &MFVideoFormat_IMC2, 1, 0, 0, 1 },
{ &MFVideoFormat_IMC3, 2, 3, 0, 1 },
{ &MFVideoFormat_IMC4, 1, 0, 0, 1 },
{ &MFVideoFormat_NV12, 1, 0, 0, 1 },
{ &MFVideoFormat_D16, 2, 3, 0, 0 },
{ &MFVideoFormat_L16, 2, 3, 0, 0 },
{ &MFVideoFormat_UYVY, 2, 0, 0, 1 },
{ &MFVideoFormat_YUY2, 2, 0, 0, 1 },
{ &MFVideoFormat_YV12, 1, 0, 0, 1 },
{ &MFVideoFormat_A16B16G16R16F, 8, 3, 1, 0 },
};
static struct uncompressed_video_format *mf_get_video_format(const GUID *subtype)
{
return bsearch(subtype, video_formats, ARRAY_SIZE(video_formats), sizeof(*video_formats),
uncompressed_video_format_compare);
}
static unsigned int mf_get_stride_for_format(const struct uncompressed_video_format *format, unsigned int width)
{
return (width * format->bytes_per_pixel + format->alignment) & ~format->alignment;
}
unsigned int mf_format_get_stride(const GUID *subtype, unsigned int width, BOOL *is_yuv)
{
struct uncompressed_video_format *format = mf_get_video_format(subtype);
if (format)
{
*is_yuv = format->yuv;
return mf_get_stride_for_format(format, width);
}
return 0;
}
/***********************************************************************
* MFGetStrideForBitmapInfoHeader (mfplat.@)
*/
HRESULT WINAPI MFGetStrideForBitmapInfoHeader(DWORD fourcc, DWORD width, LONG *stride)
{
struct uncompressed_video_format *format;
GUID subtype;
TRACE("%s, %u, %p.\n", debugstr_fourcc(fourcc), width, stride);
memcpy(&subtype, &MFVideoFormat_Base, sizeof(subtype));
subtype.Data1 = fourcc;
if (!(format = mf_get_video_format(&subtype)))
{
*stride = 0;
return MF_E_INVALIDMEDIATYPE;
}
*stride = mf_get_stride_for_format(format, width);
if (format->bottom_up)
*stride *= -1;
return S_OK;
}
/***********************************************************************
* MFCalculateImageSize (mfplat.@)
*/
HRESULT WINAPI MFCalculateImageSize(REFGUID subtype, UINT32 width, UINT32 height, UINT32 *size)
{
struct uncompressed_video_format *format;
unsigned int stride;
TRACE("%s, %u, %u, %p.\n", debugstr_mf_guid(subtype), width, height, size);
if (!(format = mf_get_video_format(subtype)))
{
*size = 0;
return E_INVALIDARG;
}
switch (subtype->Data1)
{
case MAKEFOURCC('I','M','C','2'):
case MAKEFOURCC('I','M','C','4'):
case MAKEFOURCC('N','V','1','2'):
case MAKEFOURCC('Y','V','1','2'):
/* 2 x 2 block, interleaving UV for half the height */
*size = ((width + 1) & ~1) * height * 3 / 2;
break;
case D3DFMT_L8:
case D3DFMT_L16:
case D3DFMT_D16:
*size = width * format->bytes_per_pixel * height;
break;
default:
stride = mf_get_stride_for_format(format, width);
*size = stride * height;
}
return S_OK;
}
/***********************************************************************
* MFGetPlaneSize (mfplat.@)
*/
HRESULT WINAPI MFGetPlaneSize(DWORD fourcc, DWORD width, DWORD height, DWORD *size)
{
struct uncompressed_video_format *format;
unsigned int stride;
GUID subtype;
TRACE("%s, %u, %u, %p.\n", debugstr_fourcc(fourcc), width, height, size);
memcpy(&subtype, &MFVideoFormat_Base, sizeof(subtype));
subtype.Data1 = fourcc;
if (!(format = mf_get_video_format(&subtype)))
return MF_E_INVALIDMEDIATYPE;
stride = mf_get_stride_for_format(format, width);
switch (fourcc)
{
case MAKEFOURCC('I','M','C','2'):
case MAKEFOURCC('I','M','C','4'):
case MAKEFOURCC('N','V','1','2'):
case MAKEFOURCC('Y','V','1','2'):
*size = stride * height * 3 / 2;
break;
default:
*size = stride * height;
}
return S_OK;
}
/***********************************************************************
* MFCompareFullToPartialMediaType (mfplat.@)
*/
BOOL WINAPI MFCompareFullToPartialMediaType(IMFMediaType *full_type, IMFMediaType *partial_type)
{
BOOL result;
GUID major;
TRACE("%p, %p.\n", full_type, partial_type);
if (FAILED(IMFMediaType_GetMajorType(partial_type, &major)))
return FALSE;
if (FAILED(IMFMediaType_Compare(partial_type, (IMFAttributes *)full_type, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &result)))
return FALSE;
return result;
}
/***********************************************************************
* MFWrapMediaType (mfplat.@)
*/
HRESULT WINAPI MFWrapMediaType(IMFMediaType *original, REFGUID major, REFGUID subtype, IMFMediaType **ret)
{
IMFMediaType *mediatype;
UINT8 *buffer;
UINT32 size;
HRESULT hr;
TRACE("%p, %s, %s, %p.\n", original, debugstr_guid(major), debugstr_guid(subtype), ret);
if (FAILED(hr = MFGetAttributesAsBlobSize((IMFAttributes *)original, &size)))
return hr;
if (!(buffer = heap_alloc(size)))
return E_OUTOFMEMORY;
if (FAILED(hr = MFGetAttributesAsBlob((IMFAttributes *)original, buffer, size)))
goto failed;
if (FAILED(hr = MFCreateMediaType(&mediatype)))
goto failed;
if (FAILED(hr = IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, major)))
goto failed;
if (FAILED(hr = IMFMediaType_SetGUID(mediatype, &MF_MT_SUBTYPE, subtype)))
goto failed;
if (FAILED(hr = IMFMediaType_SetBlob(mediatype, &MF_MT_WRAPPED_TYPE, buffer, size)))
goto failed;
*ret = mediatype;
failed:
heap_free(buffer);
return hr;
}
/***********************************************************************
* MFUnwrapMediaType (mfplat.@)
*/
HRESULT WINAPI MFUnwrapMediaType(IMFMediaType *wrapper, IMFMediaType **ret)
{
IMFMediaType *mediatype;
UINT8 *buffer;
UINT32 size;
HRESULT hr;
TRACE("%p, %p.\n", wrapper, ret);
if (FAILED(hr = MFCreateMediaType(&mediatype)))
return hr;
if (FAILED(hr = IMFMediaType_GetAllocatedBlob(wrapper, &MF_MT_WRAPPED_TYPE, &buffer, &size)))
{
IMFMediaType_Release(mediatype);
return hr;
}
hr = MFInitAttributesFromBlob((IMFAttributes *)mediatype, buffer, size);
CoTaskMemFree(buffer);
if (FAILED(hr))
return hr;
*ret = mediatype;
return S_OK;
}
/***********************************************************************
* MFCreateWaveFormatExFromMFMediaType (mfplat.@)
*/
HRESULT WINAPI MFCreateWaveFormatExFromMFMediaType(IMFMediaType *mediatype, WAVEFORMATEX **ret_format,
UINT32 *size, UINT32 flags)
{
WAVEFORMATEXTENSIBLE *format_ext = NULL;
WAVEFORMATEX *format;
GUID major, subtype;
UINT32 value;
HRESULT hr;
TRACE("%p, %p, %p, %#x.\n", mediatype, ret_format, size, flags);
if (FAILED(hr = IMFMediaType_GetGUID(mediatype, &MF_MT_MAJOR_TYPE, &major)))
return hr;
if (FAILED(hr = IMFMediaType_GetGUID(mediatype, &MF_MT_SUBTYPE, &subtype)))
return hr;
if (!IsEqualGUID(&major, &MFMediaType_Audio))
return E_INVALIDARG;
if (!IsEqualGUID(&subtype, &MFAudioFormat_PCM))
{
FIXME("Unsupported audio format %s.\n", debugstr_guid(&subtype));
return E_NOTIMPL;
}
/* FIXME: probably WAVE_FORMAT_MPEG/WAVE_FORMAT_MPEGLAYER3 should be handled separately. */
if (flags == MFWaveFormatExConvertFlag_ForceExtensible)
{
format_ext = CoTaskMemAlloc(sizeof(*format_ext));
*size = sizeof(*format_ext);
format = (WAVEFORMATEX *)format_ext;
}
else
{
format = CoTaskMemAlloc(sizeof(*format));
*size = sizeof(*format);
}
if (!format)
return E_OUTOFMEMORY;
memset(format, 0, *size);
format->wFormatTag = format_ext ? WAVE_FORMAT_EXTENSIBLE : WAVE_FORMAT_PCM;
if (SUCCEEDED(IMFMediaType_GetUINT32(mediatype, &MF_MT_AUDIO_NUM_CHANNELS, &value)))
format->nChannels = value;
IMFMediaType_GetUINT32(mediatype, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &format->nSamplesPerSec);
IMFMediaType_GetUINT32(mediatype, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, &format->nAvgBytesPerSec);
if (SUCCEEDED(IMFMediaType_GetUINT32(mediatype, &MF_MT_AUDIO_BLOCK_ALIGNMENT, &value)))
format->nBlockAlign = value;
if (SUCCEEDED(IMFMediaType_GetUINT32(mediatype, &MF_MT_AUDIO_BITS_PER_SAMPLE, &value)))
format->wBitsPerSample = value;
if (format_ext)
{
format->cbSize = sizeof(*format_ext) - sizeof(*format);
if (SUCCEEDED(IMFMediaType_GetUINT32(mediatype, &MF_MT_AUDIO_VALID_BITS_PER_SAMPLE, &value)))
format_ext->Samples.wSamplesPerBlock = value;
IMFMediaType_GetUINT32(mediatype, &MF_MT_AUDIO_CHANNEL_MASK, &format_ext->dwChannelMask);
memcpy(&format_ext->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM, sizeof(format_ext->SubFormat));
}
*ret_format = format;
return S_OK;
}