From f64d046117903b25a5545f0683aec4b8a3ed7a03 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Fri, 30 Oct 2020 16:50:45 +0300 Subject: [PATCH] mf/copier: Move sample copier to its own file. Signed-off-by: Nikolay Sivov Signed-off-by: Alexandre Julliard --- dlls/mf/Makefile.in | 1 + dlls/mf/copier.c | 593 ++++++++++++++++++++++++++++++++++++++++++++ dlls/mf/main.c | 565 ----------------------------------------- 3 files changed, 594 insertions(+), 565 deletions(-) create mode 100644 dlls/mf/copier.c diff --git a/dlls/mf/Makefile.in b/dlls/mf/Makefile.in index f1d0571d143..cd50a849b7c 100644 --- a/dlls/mf/Makefile.in +++ b/dlls/mf/Makefile.in @@ -6,6 +6,7 @@ DELAYIMPORTS = evr EXTRADLLFLAGS = -mno-cygwin C_SRCS = \ + copier.c \ evr.c \ main.c \ samplegrabber.c \ diff --git a/dlls/mf/copier.c b/dlls/mf/copier.c new file mode 100644 index 00000000000..ba8e316f7e9 --- /dev/null +++ b/dlls/mf/copier.c @@ -0,0 +1,593 @@ +/* + * Copyright 2020 Nikolay Sivov for CodeWeavers + * + * 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 "mfapi.h" +#include "mfidl.h" +#include "mf_private.h" + +#include "wine/debug.h" +#include "wine/heap.h" + +WINE_DEFAULT_DEBUG_CHANNEL(mfplat); + +enum sample_copier_flags +{ + SAMPLE_COPIER_INPUT_TYPE_SET = 0x1, + SAMPLE_COPIER_OUTPUT_TYPE_SET = 0x2 +}; + +struct sample_copier +{ + IMFTransform IMFTransform_iface; + LONG refcount; + + IMFAttributes *attributes; + IMFMediaType *buffer_type; + DWORD buffer_size; + IMFSample *sample; + DWORD flags; + CRITICAL_SECTION cs; +}; + +static struct sample_copier *impl_from_IMFTransform(IMFTransform *iface) +{ + return CONTAINING_RECORD(iface, struct sample_copier, IMFTransform_iface); +} + +static HRESULT WINAPI sample_copier_transform_QueryInterface(IMFTransform *iface, REFIID riid, void **obj) +{ + TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj); + + if (IsEqualIID(riid, &IID_IMFTransform) || + IsEqualIID(riid, &IID_IUnknown)) + { + *obj = iface; + IMFTransform_AddRef(iface); + return S_OK; + } + + WARN("Unsupported interface %s.\n", debugstr_guid(riid)); + *obj = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI sample_copier_transform_AddRef(IMFTransform *iface) +{ + struct sample_copier *transform = impl_from_IMFTransform(iface); + ULONG refcount = InterlockedIncrement(&transform->refcount); + + TRACE("%p, refcount %u.\n", iface, refcount); + + return refcount; +} + +static ULONG WINAPI sample_copier_transform_Release(IMFTransform *iface) +{ + struct sample_copier *transform = impl_from_IMFTransform(iface); + ULONG refcount = InterlockedDecrement(&transform->refcount); + + TRACE("%p, refcount %u.\n", iface, refcount); + + if (!refcount) + { + if (transform->attributes) + IMFAttributes_Release(transform->attributes); + if (transform->buffer_type) + IMFMediaType_Release(transform->buffer_type); + DeleteCriticalSection(&transform->cs); + heap_free(transform); + } + + return refcount; +} + +static HRESULT WINAPI sample_copier_transform_GetStreamLimits(IMFTransform *iface, DWORD *input_minimum, + DWORD *input_maximum, DWORD *output_minimum, DWORD *output_maximum) +{ + TRACE("%p, %p, %p, %p, %p.\n", iface, input_minimum, input_maximum, output_minimum, output_maximum); + + *input_minimum = *input_maximum = *output_minimum = *output_maximum = 1; + + return S_OK; +} + +static HRESULT WINAPI sample_copier_transform_GetStreamCount(IMFTransform *iface, DWORD *inputs, DWORD *outputs) +{ + TRACE("%p, %p, %p.\n", iface, inputs, outputs); + + *inputs = 1; + *outputs = 1; + + return S_OK; +} + +static HRESULT WINAPI sample_copier_transform_GetStreamIDs(IMFTransform *iface, DWORD input_size, DWORD *inputs, + DWORD output_size, DWORD *outputs) +{ + TRACE("%p, %u, %p, %u, %p.\n", iface, input_size, inputs, output_size, outputs); + + return E_NOTIMPL; +} + +static HRESULT WINAPI sample_copier_transform_GetInputStreamInfo(IMFTransform *iface, DWORD id, MFT_INPUT_STREAM_INFO *info) +{ + struct sample_copier *transform = impl_from_IMFTransform(iface); + + TRACE("%p, %u, %p.\n", iface, id, info); + + memset(info, 0, sizeof(*info)); + + EnterCriticalSection(&transform->cs); + info->cbSize = transform->buffer_size; + LeaveCriticalSection(&transform->cs); + + return S_OK; +} + +static HRESULT WINAPI sample_copier_transform_GetOutputStreamInfo(IMFTransform *iface, DWORD id, + MFT_OUTPUT_STREAM_INFO *info) +{ + struct sample_copier *transform = impl_from_IMFTransform(iface); + + TRACE("%p, %u, %p.\n", iface, id, info); + + memset(info, 0, sizeof(*info)); + + EnterCriticalSection(&transform->cs); + info->cbSize = transform->buffer_size; + LeaveCriticalSection(&transform->cs); + + return S_OK; +} + +static HRESULT WINAPI sample_copier_transform_GetAttributes(IMFTransform *iface, IMFAttributes **attributes) +{ + struct sample_copier *transform = impl_from_IMFTransform(iface); + + TRACE("%p, %p.\n", iface, attributes); + + *attributes = transform->attributes; + IMFAttributes_AddRef(*attributes); + + return S_OK; +} + +static HRESULT WINAPI sample_copier_transform_GetInputStreamAttributes(IMFTransform *iface, DWORD id, + IMFAttributes **attributes) +{ + TRACE("%p, %u, %p.\n", iface, id, attributes); + + return E_NOTIMPL; +} + +static HRESULT WINAPI sample_copier_transform_GetOutputStreamAttributes(IMFTransform *iface, DWORD id, + IMFAttributes **attributes) +{ + TRACE("%p, %u, %p.\n", iface, id, attributes); + + return E_NOTIMPL; +} + +static HRESULT WINAPI sample_copier_transform_DeleteInputStream(IMFTransform *iface, DWORD id) +{ + TRACE("%p, %u.\n", iface, id); + + return E_NOTIMPL; +} + +static HRESULT WINAPI sample_copier_transform_AddInputStreams(IMFTransform *iface, DWORD streams, DWORD *ids) +{ + TRACE("%p, %u, %p.\n", iface, streams, ids); + + return E_NOTIMPL; +} + +static HRESULT WINAPI sample_copier_transform_GetInputAvailableType(IMFTransform *iface, DWORD id, DWORD index, + IMFMediaType **type) +{ + static const GUID *types[] = { &MFMediaType_Video, &MFMediaType_Audio }; + HRESULT hr; + + TRACE("%p, %u, %u, %p.\n", iface, id, index, type); + + if (id) + return MF_E_INVALIDSTREAMNUMBER; + + if (index > ARRAY_SIZE(types) - 1) + return MF_E_NO_MORE_TYPES; + + if (SUCCEEDED(hr = MFCreateMediaType(type))) + hr = IMFMediaType_SetGUID(*type, &MF_MT_MAJOR_TYPE, types[index]); + + return hr; +} + +static HRESULT WINAPI sample_copier_transform_GetOutputAvailableType(IMFTransform *iface, DWORD id, DWORD index, + IMFMediaType **type) +{ + struct sample_copier *transform = impl_from_IMFTransform(iface); + IMFMediaType *cloned_type = NULL; + HRESULT hr = S_OK; + + TRACE("%p, %u, %u, %p.\n", iface, id, index, type); + + EnterCriticalSection(&transform->cs); + if (transform->buffer_type) + { + if (SUCCEEDED(hr = MFCreateMediaType(&cloned_type))) + hr = IMFMediaType_CopyAllItems(transform->buffer_type, (IMFAttributes *)cloned_type); + } + else if (id) + hr = MF_E_INVALIDSTREAMNUMBER; + else + hr = MF_E_NO_MORE_TYPES; + LeaveCriticalSection(&transform->cs); + + if (SUCCEEDED(hr)) + *type = cloned_type; + else if (cloned_type) + IMFMediaType_Release(cloned_type); + + return hr; +} + +static HRESULT sample_copier_get_buffer_size(IMFMediaType *type, DWORD *size) +{ + GUID major, subtype; + UINT64 frame_size; + HRESULT hr; + + *size = 0; + + if (FAILED(hr = IMFMediaType_GetMajorType(type, &major))) + return hr; + + if (IsEqualGUID(&major, &MFMediaType_Video)) + { + if (SUCCEEDED(hr = IMFMediaType_GetGUID(type, &MF_MT_SUBTYPE, &subtype))) + { + if (SUCCEEDED(hr = IMFMediaType_GetUINT64(type, &MF_MT_FRAME_SIZE, &frame_size))) + { + if (FAILED(hr = MFCalculateImageSize(&subtype, (UINT32)(frame_size >> 32), (UINT32)frame_size, size))) + WARN("Failed to get image size for video format %s.\n", debugstr_guid(&subtype)); + } + } + } + else if (IsEqualGUID(&major, &MFMediaType_Audio)) + { + FIXME("Audio formats are not handled.\n"); + hr = E_NOTIMPL; + } + + return hr; +} + +static HRESULT sample_copier_set_media_type(struct sample_copier *transform, BOOL input, DWORD id, IMFMediaType *type, + DWORD flags) +{ + DWORD buffer_size; + HRESULT hr = S_OK; + + if (id) + return MF_E_INVALIDSTREAMNUMBER; + + EnterCriticalSection(&transform->cs); + if (type) + { + hr = sample_copier_get_buffer_size(type, &buffer_size); + if (!(flags & MFT_SET_TYPE_TEST_ONLY) && SUCCEEDED(hr)) + { + if (!transform->buffer_type) + hr = MFCreateMediaType(&transform->buffer_type); + if (SUCCEEDED(hr)) + hr = IMFMediaType_CopyAllItems(type, (IMFAttributes *)transform->buffer_type); + if (SUCCEEDED(hr)) + transform->buffer_size = buffer_size; + + if (SUCCEEDED(hr)) + { + if (input) + { + transform->flags |= SAMPLE_COPIER_INPUT_TYPE_SET; + transform->flags &= ~SAMPLE_COPIER_OUTPUT_TYPE_SET; + } + else + transform->flags |= SAMPLE_COPIER_OUTPUT_TYPE_SET; + } + } + } + else if (transform->buffer_type) + { + IMFMediaType_Release(transform->buffer_type); + transform->buffer_type = NULL; + } + LeaveCriticalSection(&transform->cs); + + return hr; +} + +static HRESULT WINAPI sample_copier_transform_SetInputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags) +{ + struct sample_copier *transform = impl_from_IMFTransform(iface); + + TRACE("%p, %u, %p, %#x.\n", iface, id, type, flags); + + return sample_copier_set_media_type(transform, TRUE, id, type, flags); +} + +static HRESULT WINAPI sample_copier_transform_SetOutputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags) +{ + struct sample_copier *transform = impl_from_IMFTransform(iface); + + TRACE("%p, %u, %p, %#x.\n", iface, id, type, flags); + + return sample_copier_set_media_type(transform, FALSE, id, type, flags); +} + +static HRESULT sample_copier_get_current_type(struct sample_copier *transform, DWORD id, DWORD flags, + IMFMediaType **ret) +{ + IMFMediaType *cloned_type = NULL; + HRESULT hr; + + if (id) + return MF_E_INVALIDSTREAMNUMBER; + + EnterCriticalSection(&transform->cs); + if (transform->flags & flags) + { + if (SUCCEEDED(hr = MFCreateMediaType(&cloned_type))) + hr = IMFMediaType_CopyAllItems(transform->buffer_type, (IMFAttributes *)cloned_type); + } + else + hr = MF_E_TRANSFORM_TYPE_NOT_SET; + LeaveCriticalSection(&transform->cs); + + if (SUCCEEDED(hr)) + *ret = cloned_type; + else if (cloned_type) + IMFMediaType_Release(cloned_type); + + return hr; +} + +static HRESULT WINAPI sample_copier_transform_GetInputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type) +{ + struct sample_copier *transform = impl_from_IMFTransform(iface); + + TRACE("%p, %u, %p.\n", iface, id, type); + + return sample_copier_get_current_type(transform, id, SAMPLE_COPIER_INPUT_TYPE_SET, type); +} + +static HRESULT WINAPI sample_copier_transform_GetOutputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type) +{ + struct sample_copier *transform = impl_from_IMFTransform(iface); + + TRACE("%p, %u, %p.\n", iface, id, type); + + return sample_copier_get_current_type(transform, id, SAMPLE_COPIER_OUTPUT_TYPE_SET, type); +} + +static HRESULT WINAPI sample_copier_transform_GetInputStatus(IMFTransform *iface, DWORD id, DWORD *flags) +{ + struct sample_copier *transform = impl_from_IMFTransform(iface); + HRESULT hr = S_OK; + + TRACE("%p, %u, %p.\n", iface, id, flags); + + if (id) + return MF_E_INVALIDSTREAMNUMBER; + + EnterCriticalSection(&transform->cs); + if (!(transform->flags & SAMPLE_COPIER_INPUT_TYPE_SET)) + hr = MF_E_TRANSFORM_TYPE_NOT_SET; + else + *flags = transform->sample ? 0 : MFT_INPUT_STATUS_ACCEPT_DATA; + LeaveCriticalSection(&transform->cs); + + return hr; +} + +static HRESULT WINAPI sample_copier_transform_GetOutputStatus(IMFTransform *iface, DWORD *flags) +{ + struct sample_copier *transform = impl_from_IMFTransform(iface); + HRESULT hr = S_OK; + + TRACE("%p, %p.\n", iface, flags); + + EnterCriticalSection(&transform->cs); + if (!(transform->flags & SAMPLE_COPIER_OUTPUT_TYPE_SET)) + hr = MF_E_TRANSFORM_TYPE_NOT_SET; + else + *flags = transform->sample ? MFT_OUTPUT_STATUS_SAMPLE_READY : 0; + LeaveCriticalSection(&transform->cs); + + return hr; +} + +static HRESULT WINAPI sample_copier_transform_SetOutputBounds(IMFTransform *iface, LONGLONG lower, LONGLONG upper) +{ + TRACE("%p, %s, %s.\n", iface, debugstr_time(lower), debugstr_time(upper)); + + return E_NOTIMPL; +} + +static HRESULT WINAPI sample_copier_transform_ProcessEvent(IMFTransform *iface, DWORD id, IMFMediaEvent *event) +{ + FIXME("%p, %u, %p.\n", iface, id, event); + + return E_NOTIMPL; +} + +static HRESULT WINAPI sample_copier_transform_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_TYPE message, ULONG_PTR param) +{ + struct sample_copier *transform = impl_from_IMFTransform(iface); + + TRACE("%p, %#x, %p.\n", iface, message, (void *)param); + + EnterCriticalSection(&transform->cs); + + if (message == MFT_MESSAGE_COMMAND_FLUSH) + { + if (transform->sample) + { + IMFSample_Release(transform->sample); + transform->sample = NULL; + } + } + + LeaveCriticalSection(&transform->cs); + + return S_OK; +} + +static HRESULT WINAPI sample_copier_transform_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags) +{ + struct sample_copier *transform = impl_from_IMFTransform(iface); + HRESULT hr = S_OK; + + TRACE("%p, %u, %p, %#x.\n", iface, id, sample, flags); + + if (id) + return MF_E_INVALIDSTREAMNUMBER; + + EnterCriticalSection(&transform->cs); + if (!transform->buffer_type) + hr = MF_E_TRANSFORM_TYPE_NOT_SET; + else if (transform->sample) + hr = MF_E_NOTACCEPTING; + else + { + transform->sample = sample; + IMFSample_AddRef(transform->sample); + } + LeaveCriticalSection(&transform->cs); + + return hr; +} + +static HRESULT WINAPI sample_copier_transform_ProcessOutput(IMFTransform *iface, DWORD flags, DWORD count, + MFT_OUTPUT_DATA_BUFFER *buffers, DWORD *status) +{ + struct sample_copier *transform = impl_from_IMFTransform(iface); + IMFMediaBuffer *buffer; + DWORD sample_flags; + HRESULT hr = S_OK; + LONGLONG time; + + TRACE("%p, %#x, %u, %p, %p.\n", iface, flags, count, buffers, status); + + EnterCriticalSection(&transform->cs); + if (!(transform->flags & SAMPLE_COPIER_OUTPUT_TYPE_SET)) + hr = MF_E_TRANSFORM_TYPE_NOT_SET; + else if (!transform->sample) + hr = MF_E_TRANSFORM_NEED_MORE_INPUT; + else + { + IMFSample_CopyAllItems(transform->sample, (IMFAttributes *)buffers->pSample); + + if (SUCCEEDED(IMFSample_GetSampleDuration(transform->sample, &time))) + IMFSample_SetSampleDuration(buffers->pSample, time); + + if (SUCCEEDED(IMFSample_GetSampleTime(transform->sample, &time))) + IMFSample_SetSampleTime(buffers->pSample, time); + + if (SUCCEEDED(IMFSample_GetSampleFlags(transform->sample, &sample_flags))) + IMFSample_SetSampleFlags(buffers->pSample, sample_flags); + + if (SUCCEEDED(IMFSample_ConvertToContiguousBuffer(transform->sample, NULL))) + { + if (SUCCEEDED(IMFSample_GetBufferByIndex(buffers->pSample, 0, &buffer))) + { + if (FAILED(IMFSample_CopyToBuffer(transform->sample, buffer))) + hr = MF_E_UNEXPECTED; + IMFMediaBuffer_Release(buffer); + } + } + + IMFSample_Release(transform->sample); + transform->sample = NULL; + } + LeaveCriticalSection(&transform->cs); + + return hr; +} + +static const IMFTransformVtbl sample_copier_transform_vtbl = +{ + sample_copier_transform_QueryInterface, + sample_copier_transform_AddRef, + sample_copier_transform_Release, + sample_copier_transform_GetStreamLimits, + sample_copier_transform_GetStreamCount, + sample_copier_transform_GetStreamIDs, + sample_copier_transform_GetInputStreamInfo, + sample_copier_transform_GetOutputStreamInfo, + sample_copier_transform_GetAttributes, + sample_copier_transform_GetInputStreamAttributes, + sample_copier_transform_GetOutputStreamAttributes, + sample_copier_transform_DeleteInputStream, + sample_copier_transform_AddInputStreams, + sample_copier_transform_GetInputAvailableType, + sample_copier_transform_GetOutputAvailableType, + sample_copier_transform_SetInputType, + sample_copier_transform_SetOutputType, + sample_copier_transform_GetInputCurrentType, + sample_copier_transform_GetOutputCurrentType, + sample_copier_transform_GetInputStatus, + sample_copier_transform_GetOutputStatus, + sample_copier_transform_SetOutputBounds, + sample_copier_transform_ProcessEvent, + sample_copier_transform_ProcessMessage, + sample_copier_transform_ProcessInput, + sample_copier_transform_ProcessOutput, +}; + +HRESULT WINAPI MFCreateSampleCopierMFT(IMFTransform **transform) +{ + struct sample_copier *object; + HRESULT hr; + + TRACE("%p.\n", transform); + + object = heap_alloc_zero(sizeof(*object)); + if (!object) + return E_OUTOFMEMORY; + + object->IMFTransform_iface.lpVtbl = &sample_copier_transform_vtbl; + object->refcount = 1; + InitializeCriticalSection(&object->cs); + + if (FAILED(hr = MFCreateAttributes(&object->attributes, 0))) + goto failed; + + IMFAttributes_SetUINT32(object->attributes, &MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE, 1); + + *transform = &object->IMFTransform_iface; + + return S_OK; + +failed: + + IMFTransform_Release(&object->IMFTransform_iface); + + return hr; +} diff --git a/dlls/mf/main.c b/dlls/mf/main.c index c48fc81a1d2..2caf50c54e0 100644 --- a/dlls/mf/main.c +++ b/dlls/mf/main.c @@ -1462,568 +1462,3 @@ HRESULT WINAPI MFCreateSimpleTypeHandler(IMFMediaTypeHandler **handler) return S_OK; } - -enum sample_copier_flags -{ - SAMPLE_COPIER_INPUT_TYPE_SET = 0x1, - SAMPLE_COPIER_OUTPUT_TYPE_SET = 0x2 -}; - -struct sample_copier -{ - IMFTransform IMFTransform_iface; - LONG refcount; - - IMFAttributes *attributes; - IMFMediaType *buffer_type; - DWORD buffer_size; - IMFSample *sample; - DWORD flags; - CRITICAL_SECTION cs; -}; - -static struct sample_copier *impl_copier_from_IMFTransform(IMFTransform *iface) -{ - return CONTAINING_RECORD(iface, struct sample_copier, IMFTransform_iface); -} - -static HRESULT WINAPI sample_copier_transform_QueryInterface(IMFTransform *iface, REFIID riid, void **obj) -{ - TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj); - - if (IsEqualIID(riid, &IID_IMFTransform) || - IsEqualIID(riid, &IID_IUnknown)) - { - *obj = iface; - IMFTransform_AddRef(iface); - return S_OK; - } - - WARN("Unsupported interface %s.\n", debugstr_guid(riid)); - *obj = NULL; - return E_NOINTERFACE; -} - -static ULONG WINAPI sample_copier_transform_AddRef(IMFTransform *iface) -{ - struct sample_copier *transform = impl_copier_from_IMFTransform(iface); - ULONG refcount = InterlockedIncrement(&transform->refcount); - - TRACE("%p, refcount %u.\n", iface, refcount); - - return refcount; -} - -static ULONG WINAPI sample_copier_transform_Release(IMFTransform *iface) -{ - struct sample_copier *transform = impl_copier_from_IMFTransform(iface); - ULONG refcount = InterlockedDecrement(&transform->refcount); - - TRACE("%p, refcount %u.\n", iface, refcount); - - if (!refcount) - { - if (transform->attributes) - IMFAttributes_Release(transform->attributes); - if (transform->buffer_type) - IMFMediaType_Release(transform->buffer_type); - DeleteCriticalSection(&transform->cs); - heap_free(transform); - } - - return refcount; -} - -static HRESULT WINAPI sample_copier_transform_GetStreamLimits(IMFTransform *iface, DWORD *input_minimum, - DWORD *input_maximum, DWORD *output_minimum, DWORD *output_maximum) -{ - TRACE("%p, %p, %p, %p, %p.\n", iface, input_minimum, input_maximum, output_minimum, output_maximum); - - *input_minimum = *input_maximum = *output_minimum = *output_maximum = 1; - - return S_OK; -} - -static HRESULT WINAPI sample_copier_transform_GetStreamCount(IMFTransform *iface, DWORD *inputs, DWORD *outputs) -{ - TRACE("%p, %p, %p.\n", iface, inputs, outputs); - - *inputs = 1; - *outputs = 1; - - return S_OK; -} - -static HRESULT WINAPI sample_copier_transform_GetStreamIDs(IMFTransform *iface, DWORD input_size, DWORD *inputs, - DWORD output_size, DWORD *outputs) -{ - TRACE("%p, %u, %p, %u, %p.\n", iface, input_size, inputs, output_size, outputs); - - return E_NOTIMPL; -} - -static HRESULT WINAPI sample_copier_transform_GetInputStreamInfo(IMFTransform *iface, DWORD id, MFT_INPUT_STREAM_INFO *info) -{ - struct sample_copier *transform = impl_copier_from_IMFTransform(iface); - - TRACE("%p, %u, %p.\n", iface, id, info); - - memset(info, 0, sizeof(*info)); - - EnterCriticalSection(&transform->cs); - info->cbSize = transform->buffer_size; - LeaveCriticalSection(&transform->cs); - - return S_OK; -} - -static HRESULT WINAPI sample_copier_transform_GetOutputStreamInfo(IMFTransform *iface, DWORD id, - MFT_OUTPUT_STREAM_INFO *info) -{ - struct sample_copier *transform = impl_copier_from_IMFTransform(iface); - - TRACE("%p, %u, %p.\n", iface, id, info); - - memset(info, 0, sizeof(*info)); - - EnterCriticalSection(&transform->cs); - info->cbSize = transform->buffer_size; - LeaveCriticalSection(&transform->cs); - - return S_OK; -} - -static HRESULT WINAPI sample_copier_transform_GetAttributes(IMFTransform *iface, IMFAttributes **attributes) -{ - struct sample_copier *transform = impl_copier_from_IMFTransform(iface); - - TRACE("%p, %p.\n", iface, attributes); - - *attributes = transform->attributes; - IMFAttributes_AddRef(*attributes); - - return S_OK; -} - -static HRESULT WINAPI sample_copier_transform_GetInputStreamAttributes(IMFTransform *iface, DWORD id, - IMFAttributes **attributes) -{ - TRACE("%p, %u, %p.\n", iface, id, attributes); - - return E_NOTIMPL; -} - -static HRESULT WINAPI sample_copier_transform_GetOutputStreamAttributes(IMFTransform *iface, DWORD id, - IMFAttributes **attributes) -{ - TRACE("%p, %u, %p.\n", iface, id, attributes); - - return E_NOTIMPL; -} - -static HRESULT WINAPI sample_copier_transform_DeleteInputStream(IMFTransform *iface, DWORD id) -{ - TRACE("%p, %u.\n", iface, id); - - return E_NOTIMPL; -} - -static HRESULT WINAPI sample_copier_transform_AddInputStreams(IMFTransform *iface, DWORD streams, DWORD *ids) -{ - TRACE("%p, %u, %p.\n", iface, streams, ids); - - return E_NOTIMPL; -} - -static HRESULT WINAPI sample_copier_transform_GetInputAvailableType(IMFTransform *iface, DWORD id, DWORD index, - IMFMediaType **type) -{ - static const GUID *types[] = { &MFMediaType_Video, &MFMediaType_Audio }; - HRESULT hr; - - TRACE("%p, %u, %u, %p.\n", iface, id, index, type); - - if (id) - return MF_E_INVALIDSTREAMNUMBER; - - if (index > ARRAY_SIZE(types) - 1) - return MF_E_NO_MORE_TYPES; - - if (SUCCEEDED(hr = MFCreateMediaType(type))) - hr = IMFMediaType_SetGUID(*type, &MF_MT_MAJOR_TYPE, types[index]); - - return hr; -} - -static HRESULT WINAPI sample_copier_transform_GetOutputAvailableType(IMFTransform *iface, DWORD id, DWORD index, - IMFMediaType **type) -{ - struct sample_copier *transform = impl_copier_from_IMFTransform(iface); - IMFMediaType *cloned_type = NULL; - HRESULT hr = S_OK; - - TRACE("%p, %u, %u, %p.\n", iface, id, index, type); - - EnterCriticalSection(&transform->cs); - if (transform->buffer_type) - { - if (SUCCEEDED(hr = MFCreateMediaType(&cloned_type))) - hr = IMFMediaType_CopyAllItems(transform->buffer_type, (IMFAttributes *)cloned_type); - } - else if (id) - hr = MF_E_INVALIDSTREAMNUMBER; - else - hr = MF_E_NO_MORE_TYPES; - LeaveCriticalSection(&transform->cs); - - if (SUCCEEDED(hr)) - *type = cloned_type; - else if (cloned_type) - IMFMediaType_Release(cloned_type); - - return hr; -} - -static HRESULT sample_copier_get_buffer_size(IMFMediaType *type, DWORD *size) -{ - GUID major, subtype; - UINT64 frame_size; - HRESULT hr; - - *size = 0; - - if (FAILED(hr = IMFMediaType_GetMajorType(type, &major))) - return hr; - - if (IsEqualGUID(&major, &MFMediaType_Video)) - { - if (SUCCEEDED(hr = IMFMediaType_GetGUID(type, &MF_MT_SUBTYPE, &subtype))) - { - if (SUCCEEDED(hr = IMFMediaType_GetUINT64(type, &MF_MT_FRAME_SIZE, &frame_size))) - { - if (FAILED(hr = MFCalculateImageSize(&subtype, (UINT32)(frame_size >> 32), (UINT32)frame_size, size))) - WARN("Failed to get image size for video format %s.\n", debugstr_guid(&subtype)); - } - } - } - else if (IsEqualGUID(&major, &MFMediaType_Audio)) - { - FIXME("Audio formats are not handled.\n"); - hr = E_NOTIMPL; - } - - return hr; -} - -static HRESULT sample_copier_set_media_type(struct sample_copier *transform, BOOL input, DWORD id, IMFMediaType *type, - DWORD flags) -{ - DWORD buffer_size; - HRESULT hr = S_OK; - - if (id) - return MF_E_INVALIDSTREAMNUMBER; - - EnterCriticalSection(&transform->cs); - if (type) - { - hr = sample_copier_get_buffer_size(type, &buffer_size); - if (!(flags & MFT_SET_TYPE_TEST_ONLY) && SUCCEEDED(hr)) - { - if (!transform->buffer_type) - hr = MFCreateMediaType(&transform->buffer_type); - if (SUCCEEDED(hr)) - hr = IMFMediaType_CopyAllItems(type, (IMFAttributes *)transform->buffer_type); - if (SUCCEEDED(hr)) - transform->buffer_size = buffer_size; - - if (SUCCEEDED(hr)) - { - if (input) - { - transform->flags |= SAMPLE_COPIER_INPUT_TYPE_SET; - transform->flags &= ~SAMPLE_COPIER_OUTPUT_TYPE_SET; - } - else - transform->flags |= SAMPLE_COPIER_OUTPUT_TYPE_SET; - } - } - } - else if (transform->buffer_type) - { - IMFMediaType_Release(transform->buffer_type); - transform->buffer_type = NULL; - } - LeaveCriticalSection(&transform->cs); - - return hr; -} - -static HRESULT WINAPI sample_copier_transform_SetInputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags) -{ - struct sample_copier *transform = impl_copier_from_IMFTransform(iface); - - TRACE("%p, %u, %p, %#x.\n", iface, id, type, flags); - - return sample_copier_set_media_type(transform, TRUE, id, type, flags); -} - -static HRESULT WINAPI sample_copier_transform_SetOutputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags) -{ - struct sample_copier *transform = impl_copier_from_IMFTransform(iface); - - TRACE("%p, %u, %p, %#x.\n", iface, id, type, flags); - - return sample_copier_set_media_type(transform, FALSE, id, type, flags); -} - -static HRESULT sample_copier_get_current_type(struct sample_copier *transform, DWORD id, DWORD flags, - IMFMediaType **ret) -{ - IMFMediaType *cloned_type = NULL; - HRESULT hr; - - if (id) - return MF_E_INVALIDSTREAMNUMBER; - - EnterCriticalSection(&transform->cs); - if (transform->flags & flags) - { - if (SUCCEEDED(hr = MFCreateMediaType(&cloned_type))) - hr = IMFMediaType_CopyAllItems(transform->buffer_type, (IMFAttributes *)cloned_type); - } - else - hr = MF_E_TRANSFORM_TYPE_NOT_SET; - LeaveCriticalSection(&transform->cs); - - if (SUCCEEDED(hr)) - *ret = cloned_type; - else if (cloned_type) - IMFMediaType_Release(cloned_type); - - return hr; -} - -static HRESULT WINAPI sample_copier_transform_GetInputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type) -{ - struct sample_copier *transform = impl_copier_from_IMFTransform(iface); - - TRACE("%p, %u, %p.\n", iface, id, type); - - return sample_copier_get_current_type(transform, id, SAMPLE_COPIER_INPUT_TYPE_SET, type); -} - -static HRESULT WINAPI sample_copier_transform_GetOutputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type) -{ - struct sample_copier *transform = impl_copier_from_IMFTransform(iface); - - TRACE("%p, %u, %p.\n", iface, id, type); - - return sample_copier_get_current_type(transform, id, SAMPLE_COPIER_OUTPUT_TYPE_SET, type); -} - -static HRESULT WINAPI sample_copier_transform_GetInputStatus(IMFTransform *iface, DWORD id, DWORD *flags) -{ - struct sample_copier *transform = impl_copier_from_IMFTransform(iface); - HRESULT hr = S_OK; - - TRACE("%p, %u, %p.\n", iface, id, flags); - - if (id) - return MF_E_INVALIDSTREAMNUMBER; - - EnterCriticalSection(&transform->cs); - if (!(transform->flags & SAMPLE_COPIER_INPUT_TYPE_SET)) - hr = MF_E_TRANSFORM_TYPE_NOT_SET; - else - *flags = transform->sample ? 0 : MFT_INPUT_STATUS_ACCEPT_DATA; - LeaveCriticalSection(&transform->cs); - - return hr; -} - -static HRESULT WINAPI sample_copier_transform_GetOutputStatus(IMFTransform *iface, DWORD *flags) -{ - struct sample_copier *transform = impl_copier_from_IMFTransform(iface); - HRESULT hr = S_OK; - - TRACE("%p, %p.\n", iface, flags); - - EnterCriticalSection(&transform->cs); - if (!(transform->flags & SAMPLE_COPIER_OUTPUT_TYPE_SET)) - hr = MF_E_TRANSFORM_TYPE_NOT_SET; - else - *flags = transform->sample ? MFT_OUTPUT_STATUS_SAMPLE_READY : 0; - LeaveCriticalSection(&transform->cs); - - return hr; -} - -static HRESULT WINAPI sample_copier_transform_SetOutputBounds(IMFTransform *iface, LONGLONG lower, LONGLONG upper) -{ - TRACE("%p, %s, %s.\n", iface, debugstr_time(lower), debugstr_time(upper)); - - return E_NOTIMPL; -} - -static HRESULT WINAPI sample_copier_transform_ProcessEvent(IMFTransform *iface, DWORD id, IMFMediaEvent *event) -{ - FIXME("%p, %u, %p.\n", iface, id, event); - - return E_NOTIMPL; -} - -static HRESULT WINAPI sample_copier_transform_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_TYPE message, ULONG_PTR param) -{ - struct sample_copier *transform = impl_copier_from_IMFTransform(iface); - - TRACE("%p, %#x, %p.\n", iface, message, (void *)param); - - EnterCriticalSection(&transform->cs); - - if (message == MFT_MESSAGE_COMMAND_FLUSH) - { - if (transform->sample) - { - IMFSample_Release(transform->sample); - transform->sample = NULL; - } - } - - LeaveCriticalSection(&transform->cs); - - return S_OK; -} - -static HRESULT WINAPI sample_copier_transform_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags) -{ - struct sample_copier *transform = impl_copier_from_IMFTransform(iface); - HRESULT hr = S_OK; - - TRACE("%p, %u, %p, %#x.\n", iface, id, sample, flags); - - if (id) - return MF_E_INVALIDSTREAMNUMBER; - - EnterCriticalSection(&transform->cs); - if (!transform->buffer_type) - hr = MF_E_TRANSFORM_TYPE_NOT_SET; - else if (transform->sample) - hr = MF_E_NOTACCEPTING; - else - { - transform->sample = sample; - IMFSample_AddRef(transform->sample); - } - LeaveCriticalSection(&transform->cs); - - return hr; -} - -static HRESULT WINAPI sample_copier_transform_ProcessOutput(IMFTransform *iface, DWORD flags, DWORD count, - MFT_OUTPUT_DATA_BUFFER *buffers, DWORD *status) -{ - struct sample_copier *transform = impl_copier_from_IMFTransform(iface); - IMFMediaBuffer *buffer; - DWORD sample_flags; - HRESULT hr = S_OK; - LONGLONG time; - - TRACE("%p, %#x, %u, %p, %p.\n", iface, flags, count, buffers, status); - - EnterCriticalSection(&transform->cs); - if (!(transform->flags & SAMPLE_COPIER_OUTPUT_TYPE_SET)) - hr = MF_E_TRANSFORM_TYPE_NOT_SET; - else if (!transform->sample) - hr = MF_E_TRANSFORM_NEED_MORE_INPUT; - else - { - IMFSample_CopyAllItems(transform->sample, (IMFAttributes *)buffers->pSample); - - if (SUCCEEDED(IMFSample_GetSampleDuration(transform->sample, &time))) - IMFSample_SetSampleDuration(buffers->pSample, time); - - if (SUCCEEDED(IMFSample_GetSampleTime(transform->sample, &time))) - IMFSample_SetSampleTime(buffers->pSample, time); - - if (SUCCEEDED(IMFSample_GetSampleFlags(transform->sample, &sample_flags))) - IMFSample_SetSampleFlags(buffers->pSample, sample_flags); - - if (SUCCEEDED(IMFSample_ConvertToContiguousBuffer(transform->sample, NULL))) - { - if (SUCCEEDED(IMFSample_GetBufferByIndex(buffers->pSample, 0, &buffer))) - { - if (FAILED(IMFSample_CopyToBuffer(transform->sample, buffer))) - hr = MF_E_UNEXPECTED; - IMFMediaBuffer_Release(buffer); - } - } - - IMFSample_Release(transform->sample); - transform->sample = NULL; - } - LeaveCriticalSection(&transform->cs); - - return hr; -} - -static const IMFTransformVtbl sample_copier_transform_vtbl = -{ - sample_copier_transform_QueryInterface, - sample_copier_transform_AddRef, - sample_copier_transform_Release, - sample_copier_transform_GetStreamLimits, - sample_copier_transform_GetStreamCount, - sample_copier_transform_GetStreamIDs, - sample_copier_transform_GetInputStreamInfo, - sample_copier_transform_GetOutputStreamInfo, - sample_copier_transform_GetAttributes, - sample_copier_transform_GetInputStreamAttributes, - sample_copier_transform_GetOutputStreamAttributes, - sample_copier_transform_DeleteInputStream, - sample_copier_transform_AddInputStreams, - sample_copier_transform_GetInputAvailableType, - sample_copier_transform_GetOutputAvailableType, - sample_copier_transform_SetInputType, - sample_copier_transform_SetOutputType, - sample_copier_transform_GetInputCurrentType, - sample_copier_transform_GetOutputCurrentType, - sample_copier_transform_GetInputStatus, - sample_copier_transform_GetOutputStatus, - sample_copier_transform_SetOutputBounds, - sample_copier_transform_ProcessEvent, - sample_copier_transform_ProcessMessage, - sample_copier_transform_ProcessInput, - sample_copier_transform_ProcessOutput, -}; - -HRESULT WINAPI MFCreateSampleCopierMFT(IMFTransform **transform) -{ - struct sample_copier *object; - HRESULT hr; - - TRACE("%p.\n", transform); - - object = heap_alloc_zero(sizeof(*object)); - if (!object) - return E_OUTOFMEMORY; - - object->IMFTransform_iface.lpVtbl = &sample_copier_transform_vtbl; - object->refcount = 1; - InitializeCriticalSection(&object->cs); - - if (FAILED(hr = MFCreateAttributes(&object->attributes, 0))) - goto failed; - - IMFAttributes_SetUINT32(object->attributes, &MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE, 1); - - *transform = &object->IMFTransform_iface; - - return S_OK; - -failed: - - IMFTransform_Release(&object->IMFTransform_iface); - - return hr; -}