Commit 0e7836c0 authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

mfplat/allocator: Add initial implementation of sample allocator.

parent 3bf48966
......@@ -20,10 +20,10 @@
#include "mfplat_private.h"
#include "dxva2api.h"
#include "initguid.h"
#include "ks.h"
#include "ksmedia.h"
#include "dxva2api.h"
#include "wine/debug.h"
......
......@@ -82,6 +82,7 @@
@ stdcall MFCreateVideoMediaTypeFromSubtype(ptr ptr)
@ stub MFCreateVideoMediaTypeFromVideoInfoHeader2
@ stub MFCreateVideoMediaTypeFromVideoInfoHeader
@ stdcall MFCreateVideoSampleAllocatorEx(ptr ptr)
@ stdcall MFCreateWaveFormatExFromMFMediaType(ptr ptr ptr long)
@ stub MFDeserializeAttributesFromStream
@ stub MFDeserializeEvent
......
......@@ -20,8 +20,13 @@
#include "mfplat_private.h"
#include "rtworkq.h"
#include "d3d9.h"
#include "d3d11.h"
#include "initguid.h"
#include "dxva2api.h"
#include "wine/debug.h"
#include "wine/list.h"
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
......@@ -50,6 +55,54 @@ struct sample
LONG tracked_refcount;
};
struct sample_allocator
{
IMFVideoSampleAllocatorEx IMFVideoSampleAllocatorEx_iface;
IMFVideoSampleAllocatorCallback IMFVideoSampleAllocatorCallback_iface;
IMFAsyncCallback tracking_callback;
LONG refcount;
IMFVideoSampleAllocatorNotify *callback;
IDirect3DDeviceManager9 *d3d9_device_manager;
IMFDXGIDeviceManager *dxgi_device_manager;
struct
{
unsigned int width;
unsigned int height;
D3DFORMAT d3d9_format;
DXGI_FORMAT dxgi_format;
unsigned int buffer_count;
} frame_desc;
unsigned int free_sample_count;
unsigned int cold_sample_count;
struct list free_samples;
struct list used_samples;
CRITICAL_SECTION cs;
};
struct queued_sample
{
struct list entry;
IMFSample *sample;
};
static struct sample_allocator *impl_from_IMFVideoSampleAllocatorEx(IMFVideoSampleAllocatorEx *iface)
{
return CONTAINING_RECORD(iface, struct sample_allocator, IMFVideoSampleAllocatorEx_iface);
}
static struct sample_allocator *impl_from_IMFVideoSampleAllocatorCallback(IMFVideoSampleAllocatorCallback *iface)
{
return CONTAINING_RECORD(iface, struct sample_allocator, IMFVideoSampleAllocatorCallback_iface);
}
static struct sample_allocator *impl_from_IMFAsyncCallback(IMFAsyncCallback *iface)
{
return CONTAINING_RECORD(iface, struct sample_allocator, tracking_callback);
}
static struct sample *impl_from_IMFSample(IMFSample *iface)
{
return CONTAINING_RECORD(iface, struct sample, IMFSample_iface);
......@@ -1005,3 +1058,621 @@ HRESULT WINAPI MFCreateTrackedSample(IMFTrackedSample **sample)
return S_OK;
}
static HRESULT WINAPI sample_allocator_QueryInterface(IMFVideoSampleAllocatorEx *iface, REFIID riid, void **obj)
{
struct sample_allocator *allocator = impl_from_IMFVideoSampleAllocatorEx(iface);
TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
if (IsEqualIID(riid, &IID_IMFVideoSampleAllocatorEx) ||
IsEqualIID(riid, &IID_IMFVideoSampleAllocator) ||
IsEqualIID(riid, &IID_IUnknown))
{
*obj = &allocator->IMFVideoSampleAllocatorEx_iface;
}
else if (IsEqualIID(riid, &IID_IMFVideoSampleAllocatorCallback))
{
*obj = &allocator->IMFVideoSampleAllocatorCallback_iface;
}
else
{
WARN("Unsupported interface %s.\n", debugstr_guid(riid));
*obj = NULL;
return E_NOINTERFACE;
}
IUnknown_AddRef((IUnknown *)*obj);
return S_OK;
}
static ULONG WINAPI sample_allocator_AddRef(IMFVideoSampleAllocatorEx *iface)
{
struct sample_allocator *allocator = impl_from_IMFVideoSampleAllocatorEx(iface);
ULONG refcount = InterlockedIncrement(&allocator->refcount);
TRACE("%p, refcount %u.\n", iface, refcount);
return refcount;
}
static void sample_allocator_release_samples(struct sample_allocator *allocator)
{
struct queued_sample *iter, *iter2;
LIST_FOR_EACH_ENTRY_SAFE(iter, iter2, &allocator->free_samples, struct queued_sample, entry)
{
list_remove(&iter->entry);
IMFSample_Release(iter->sample);
heap_free(iter);
}
LIST_FOR_EACH_ENTRY_SAFE(iter, iter2, &allocator->used_samples, struct queued_sample, entry)
{
list_remove(&iter->entry);
heap_free(iter);
}
}
static ULONG WINAPI sample_allocator_Release(IMFVideoSampleAllocatorEx *iface)
{
struct sample_allocator *allocator = impl_from_IMFVideoSampleAllocatorEx(iface);
ULONG refcount = InterlockedDecrement(&allocator->refcount);
TRACE("%p, refcount %u.\n", iface, refcount);
if (!refcount)
{
if (allocator->callback)
IMFVideoSampleAllocatorNotify_Release(allocator->callback);
if (allocator->d3d9_device_manager)
IDirect3DDeviceManager9_Release(allocator->d3d9_device_manager);
if (allocator->dxgi_device_manager)
IMFDXGIDeviceManager_Release(allocator->dxgi_device_manager);
sample_allocator_release_samples(allocator);
DeleteCriticalSection(&allocator->cs);
heap_free(allocator);
}
return refcount;
}
static HRESULT WINAPI sample_allocator_SetDirectXManager(IMFVideoSampleAllocatorEx *iface,
IUnknown *manager)
{
struct sample_allocator *allocator = impl_from_IMFVideoSampleAllocatorEx(iface);
IDirect3DDeviceManager9 *d3d9_device_manager = NULL;
IMFDXGIDeviceManager *dxgi_device_manager = NULL;
HRESULT hr;
TRACE("%p, %p.\n", iface, manager);
if (manager)
{
if (FAILED(hr = IUnknown_QueryInterface(manager, &IID_IMFDXGIDeviceManager, (void **)&dxgi_device_manager)))
{
hr = IUnknown_QueryInterface(manager, &IID_IDirect3DDeviceManager9, (void **)&d3d9_device_manager);
}
if (FAILED(hr))
return hr;
}
EnterCriticalSection(&allocator->cs);
if (allocator->d3d9_device_manager)
IDirect3DDeviceManager9_Release(allocator->d3d9_device_manager);
if (allocator->dxgi_device_manager)
IMFDXGIDeviceManager_Release(allocator->dxgi_device_manager);
allocator->d3d9_device_manager = NULL;
allocator->dxgi_device_manager = NULL;
if (dxgi_device_manager)
allocator->dxgi_device_manager = dxgi_device_manager;
else if (d3d9_device_manager)
allocator->d3d9_device_manager = d3d9_device_manager;
LeaveCriticalSection(&allocator->cs);
return S_OK;
}
static HRESULT WINAPI sample_allocator_UninitializeSampleAllocator(IMFVideoSampleAllocatorEx *iface)
{
struct sample_allocator *allocator = impl_from_IMFVideoSampleAllocatorEx(iface);
TRACE("%p.\n", iface);
EnterCriticalSection(&allocator->cs);
sample_allocator_release_samples(allocator);
allocator->free_sample_count = 0;
LeaveCriticalSection(&allocator->cs);
return S_OK;
}
struct surface_service
{
IDirectXVideoProcessorService *dxva_service;
ID3D11Device *d3d11_device;
HANDLE hdevice;
};
static HRESULT sample_allocator_get_surface_service(struct sample_allocator *allocator, struct surface_service *service)
{
HRESULT hr = S_OK;
memset(service, 0, sizeof(*service));
if (allocator->d3d9_device_manager)
{
if (SUCCEEDED(hr = IDirect3DDeviceManager9_OpenDeviceHandle(allocator->d3d9_device_manager, &service->hdevice)))
{
if (FAILED(hr = IDirect3DDeviceManager9_GetVideoService(allocator->d3d9_device_manager, service->hdevice,
&IID_IDirectXVideoProcessorService, (void **)&service->dxva_service)))
{
WARN("Failed to get DXVA processor service, hr %#x.\n", hr);
IDirect3DDeviceManager9_CloseDeviceHandle(allocator->d3d9_device_manager, service->hdevice);
}
}
}
else if (allocator->dxgi_device_manager)
{
if (SUCCEEDED(hr = IMFDXGIDeviceManager_OpenDeviceHandle(allocator->dxgi_device_manager, &service->hdevice)))
{
if (FAILED(hr = IMFDXGIDeviceManager_GetVideoService(allocator->dxgi_device_manager, service->hdevice,
&IID_ID3D11Device, (void **)&service->d3d11_device)))
{
WARN("Failed to get D3D11 device, hr %#x.\n", hr);
IMFDXGIDeviceManager_CloseDeviceHandle(allocator->dxgi_device_manager, service->hdevice);
}
}
}
if (FAILED(hr))
memset(service, 0, sizeof(*service));
return hr;
}
static void sample_allocator_release_surface_service(struct sample_allocator *allocator,
struct surface_service *service)
{
if (service->dxva_service)
IDirectXVideoProcessorService_Release(service->dxva_service);
if (service->d3d11_device)
ID3D11Device_Release(service->d3d11_device);
if (allocator->d3d9_device_manager)
IDirect3DDeviceManager9_CloseDeviceHandle(allocator->d3d9_device_manager, service->hdevice);
else if (allocator->dxgi_device_manager)
IMFDXGIDeviceManager_CloseDeviceHandle(allocator->dxgi_device_manager, service->hdevice);
}
static HRESULT sample_allocator_allocate_sample(struct sample_allocator *allocator, const struct surface_service *service,
IMFSample **sample)
{
struct queued_sample *queued_sample = heap_alloc(sizeof(*queued_sample));
IMFTrackedSample *tracked_sample;
IMFMediaBuffer *buffer;
unsigned int i;
HRESULT hr;
if (FAILED(hr = MFCreateTrackedSample(&tracked_sample)))
{
return hr;
}
IMFTrackedSample_QueryInterface(tracked_sample, &IID_IMFSample, (void **)sample);
IMFTrackedSample_Release(tracked_sample);
for (i = 0; i < allocator->frame_desc.buffer_count; ++i)
{
if (service->dxva_service)
{
IDirect3DSurface9 *surface;
if (SUCCEEDED(hr = IDirectXVideoProcessorService_CreateSurface(service->dxva_service, allocator->frame_desc.width,
allocator->frame_desc.height, 0, allocator->frame_desc.d3d9_format, D3DPOOL_DEFAULT, 0,
DXVA2_VideoProcessorRenderTarget, &surface, NULL)))
{
hr = MFCreateDXSurfaceBuffer(&IID_IDirect3DSurface9, (IUnknown *)surface, FALSE, &buffer);
IDirect3DSurface9_Release(surface);
}
}
else if (service->d3d11_device)
{
D3D11_TEXTURE2D_DESC desc = { 0 };
ID3D11Texture2D *texture;
desc.Width = allocator->frame_desc.width;
desc.Height = allocator->frame_desc.height;
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.Format = allocator->frame_desc.dxgi_format;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.Usage = 0;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
if (SUCCEEDED(hr = ID3D11Device_CreateTexture2D(service->d3d11_device, &desc, NULL, &texture)))
{
hr = MFCreateDXGISurfaceBuffer(&IID_ID3D11Texture2D, (IUnknown *)texture, 0, FALSE, &buffer);
ID3D11Texture2D_Release(texture);
}
}
else
{
hr = MFCreate2DMediaBuffer(allocator->frame_desc.width, allocator->frame_desc.height,
allocator->frame_desc.d3d9_format, FALSE, &buffer);
}
if (SUCCEEDED(hr))
{
hr = IMFSample_AddBuffer(*sample, buffer);
IMFMediaBuffer_Release(buffer);
}
}
return hr;
}
static HRESULT sample_allocator_initialize(struct sample_allocator *allocator, unsigned int sample_count,
unsigned int max_sample_count, IMFAttributes *attributes, IMFMediaType *media_type)
{
struct surface_service service;
unsigned int i;
GUID major, subtype;
UINT64 frame_size;
IMFSample *sample;
HRESULT hr;
if (FAILED(hr = IMFMediaType_GetMajorType(media_type, &major)))
return hr;
if (!IsEqualGUID(&major, &MFMediaType_Video))
return MF_E_INVALIDMEDIATYPE;
if (FAILED(hr = IMFMediaType_GetUINT64(media_type, &MF_MT_FRAME_SIZE, &frame_size)))
return hr;
if (FAILED(hr = IMFMediaType_GetGUID(media_type, &MF_MT_SUBTYPE, &subtype)))
return hr;
if (sample_count > max_sample_count)
return E_INVALIDARG;
sample_count = max(1, sample_count);
max_sample_count = max(1, max_sample_count);
if (attributes)
FIXME("Initialization attributes ignored.\n");
allocator->frame_desc.d3d9_format = subtype.Data1;
allocator->frame_desc.dxgi_format = MFMapDX9FormatToDXGIFormat(allocator->frame_desc.d3d9_format);
allocator->frame_desc.width = frame_size >> 32;
allocator->frame_desc.height = frame_size;
if (FAILED(hr = sample_allocator_get_surface_service(allocator, &service)))
return hr;
sample_allocator_release_samples(allocator);
for (i = 0; i < sample_count; ++i)
{
struct queued_sample *queued_sample;
if (SUCCEEDED(hr = sample_allocator_allocate_sample(allocator, &service, &sample)))
{
queued_sample = heap_alloc(sizeof(*queued_sample));
queued_sample->sample = sample;
list_add_tail(&allocator->free_samples, &queued_sample->entry);
allocator->free_sample_count++;
}
}
allocator->cold_sample_count = max_sample_count - allocator->free_sample_count;
sample_allocator_release_surface_service(allocator, &service);
return hr;
}
static HRESULT WINAPI sample_allocator_InitializeSampleAllocator(IMFVideoSampleAllocatorEx *iface,
DWORD sample_count, IMFMediaType *media_type)
{
struct sample_allocator *allocator = impl_from_IMFVideoSampleAllocatorEx(iface);
HRESULT hr;
TRACE("%p, %u, %p.\n", iface, sample_count, media_type);
if (!sample_count)
return E_INVALIDARG;
EnterCriticalSection(&allocator->cs);
hr = sample_allocator_initialize(allocator, sample_count, sample_count, NULL, media_type);
LeaveCriticalSection(&allocator->cs);
return hr;
}
static HRESULT sample_allocator_track_sample(struct sample_allocator *allocator, IMFSample *sample)
{
IMFTrackedSample *tracked_sample;
HRESULT hr;
if (SUCCEEDED(hr = IMFSample_QueryInterface(sample, &IID_IMFTrackedSample, (void **)&tracked_sample)))
{
hr = IMFTrackedSample_SetAllocator(tracked_sample, &allocator->tracking_callback, NULL);
IMFTrackedSample_Release(tracked_sample);
}
return hr;
}
static HRESULT WINAPI sample_allocator_AllocateSample(IMFVideoSampleAllocatorEx *iface, IMFSample **out)
{
struct sample_allocator *allocator = impl_from_IMFVideoSampleAllocatorEx(iface);
IMFSample *sample;
HRESULT hr;
TRACE("%p, %p.\n", iface, out);
EnterCriticalSection(&allocator->cs);
if (list_empty(&allocator->free_samples) && list_empty(&allocator->used_samples))
hr = MF_E_NOT_INITIALIZED;
else if (list_empty(&allocator->free_samples) && !allocator->cold_sample_count)
hr = MF_E_SAMPLEALLOCATOR_EMPTY;
else if (!list_empty(&allocator->free_samples))
{
struct list *head = list_head(&allocator->free_samples);
sample = LIST_ENTRY(head, struct queued_sample, entry)->sample;
if (SUCCEEDED(hr = sample_allocator_track_sample(allocator, sample)))
{
list_remove(head);
list_add_tail(&allocator->used_samples, head);
allocator->free_sample_count--;
/* Reference counter is not increased when sample is returned, so next release could trigger
tracking condition. This is balanced by incremented reference counter when sample is returned
back to the free list. */
*out = sample;
}
}
else /* allocator->cold_sample_count != 0 */
{
struct surface_service service;
if (SUCCEEDED(hr = sample_allocator_get_surface_service(allocator, &service)))
{
if (SUCCEEDED(hr = sample_allocator_allocate_sample(allocator, &service, &sample)))
{
if (SUCCEEDED(hr = sample_allocator_track_sample(allocator, sample)))
{
struct queued_sample *queued_sample = heap_alloc(sizeof(*queued_sample));
queued_sample->sample = sample;
list_add_tail(&allocator->used_samples, &queued_sample->entry);
allocator->cold_sample_count--;
*out = queued_sample->sample;
}
}
sample_allocator_release_surface_service(allocator, &service);
}
}
LeaveCriticalSection(&allocator->cs);
return hr;
}
static HRESULT WINAPI sample_allocator_InitializeSampleAllocatorEx(IMFVideoSampleAllocatorEx *iface, DWORD initial_sample_count,
DWORD max_sample_count, IMFAttributes *attributes, IMFMediaType *media_type)
{
struct sample_allocator *allocator = impl_from_IMFVideoSampleAllocatorEx(iface);
HRESULT hr;
TRACE("%p, %u, %u, %p, %p.\n", iface, initial_sample_count, max_sample_count, attributes, media_type);
EnterCriticalSection(&allocator->cs);
hr = sample_allocator_initialize(allocator, initial_sample_count, max_sample_count, attributes, media_type);
LeaveCriticalSection(&allocator->cs);
return hr;
}
static const IMFVideoSampleAllocatorExVtbl sample_allocator_vtbl =
{
sample_allocator_QueryInterface,
sample_allocator_AddRef,
sample_allocator_Release,
sample_allocator_SetDirectXManager,
sample_allocator_UninitializeSampleAllocator,
sample_allocator_InitializeSampleAllocator,
sample_allocator_AllocateSample,
sample_allocator_InitializeSampleAllocatorEx,
};
static HRESULT WINAPI sample_allocator_callback_QueryInterface(IMFVideoSampleAllocatorCallback *iface,
REFIID riid, void **obj)
{
struct sample_allocator *allocator = impl_from_IMFVideoSampleAllocatorCallback(iface);
return IMFVideoSampleAllocatorEx_QueryInterface(&allocator->IMFVideoSampleAllocatorEx_iface, riid, obj);
}
static ULONG WINAPI sample_allocator_callback_AddRef(IMFVideoSampleAllocatorCallback *iface)
{
struct sample_allocator *allocator = impl_from_IMFVideoSampleAllocatorCallback(iface);
return IMFVideoSampleAllocatorEx_AddRef(&allocator->IMFVideoSampleAllocatorEx_iface);
}
static ULONG WINAPI sample_allocator_callback_Release(IMFVideoSampleAllocatorCallback *iface)
{
struct sample_allocator *allocator = impl_from_IMFVideoSampleAllocatorCallback(iface);
return IMFVideoSampleAllocatorEx_Release(&allocator->IMFVideoSampleAllocatorEx_iface);
}
static HRESULT WINAPI sample_allocator_callback_SetCallback(IMFVideoSampleAllocatorCallback *iface,
IMFVideoSampleAllocatorNotify *callback)
{
struct sample_allocator *allocator = impl_from_IMFVideoSampleAllocatorCallback(iface);
TRACE("%p, %p.\n", iface, callback);
EnterCriticalSection(&allocator->cs);
if (allocator->callback)
IMFVideoSampleAllocatorNotify_Release(allocator->callback);
allocator->callback = callback;
if (allocator->callback)
IMFVideoSampleAllocatorNotify_AddRef(allocator->callback);
LeaveCriticalSection(&allocator->cs);
return S_OK;
}
static HRESULT WINAPI sample_allocator_callback_GetFreeSampleCount(IMFVideoSampleAllocatorCallback *iface,
LONG *count)
{
struct sample_allocator *allocator = impl_from_IMFVideoSampleAllocatorCallback(iface);
TRACE("%p, %p.\n", iface, count);
if (!count)
return E_POINTER;
EnterCriticalSection(&allocator->cs);
*count = allocator->free_sample_count;
LeaveCriticalSection(&allocator->cs);
return S_OK;
}
static const IMFVideoSampleAllocatorCallbackVtbl sample_allocator_callback_vtbl =
{
sample_allocator_callback_QueryInterface,
sample_allocator_callback_AddRef,
sample_allocator_callback_Release,
sample_allocator_callback_SetCallback,
sample_allocator_callback_GetFreeSampleCount,
};
static HRESULT WINAPI sample_allocator_tracking_callback_QueryInterface(IMFAsyncCallback *iface,
REFIID riid, void **obj)
{
if (IsEqualIID(riid, &IID_IMFAsyncCallback) ||
IsEqualIID(riid, &IID_IUnknown))
{
*obj = iface;
IMFAsyncCallback_AddRef(iface);
return S_OK;
}
WARN("Unsupported interface %s.\n", debugstr_guid(riid));
*obj = NULL;
return E_NOINTERFACE;
}
static ULONG WINAPI sample_allocator_tracking_callback_AddRef(IMFAsyncCallback *iface)
{
struct sample_allocator *allocator = impl_from_IMFAsyncCallback(iface);
return IMFVideoSampleAllocatorEx_AddRef(&allocator->IMFVideoSampleAllocatorEx_iface);
}
static ULONG WINAPI sample_allocator_tracking_callback_Release(IMFAsyncCallback *iface)
{
struct sample_allocator *allocator = impl_from_IMFAsyncCallback(iface);
return IMFVideoSampleAllocatorEx_Release(&allocator->IMFVideoSampleAllocatorEx_iface);
}
static HRESULT WINAPI sample_allocator_tracking_callback_GetParameters(IMFAsyncCallback *iface,
DWORD *flags, DWORD *queue)
{
return E_NOTIMPL;
}
static HRESULT WINAPI sample_allocator_tracking_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result)
{
struct sample_allocator *allocator = impl_from_IMFAsyncCallback(iface);
struct queued_sample *iter;
IUnknown *object = NULL;
IMFSample *sample = NULL;
HRESULT hr;
if (FAILED(IMFAsyncResult_GetObject(result, &object)))
return E_UNEXPECTED;
hr = IUnknown_QueryInterface(object, &IID_IMFSample, (void **)&sample);
IUnknown_Release(object);
if (FAILED(hr))
return E_UNEXPECTED;
EnterCriticalSection(&allocator->cs);
LIST_FOR_EACH_ENTRY(iter, &allocator->used_samples, struct queued_sample, entry)
{
if (sample == iter->sample)
{
list_remove(&iter->entry);
list_add_tail(&allocator->free_samples, &iter->entry);
IMFSample_AddRef(iter->sample);
allocator->free_sample_count++;
break;
}
}
IMFSample_Release(sample);
if (allocator->callback)
IMFVideoSampleAllocatorNotify_NotifyRelease(allocator->callback);
LeaveCriticalSection(&allocator->cs);
return S_OK;
}
static const IMFAsyncCallbackVtbl sample_allocator_tracking_callback_vtbl =
{
sample_allocator_tracking_callback_QueryInterface,
sample_allocator_tracking_callback_AddRef,
sample_allocator_tracking_callback_Release,
sample_allocator_tracking_callback_GetParameters,
sample_allocator_tracking_callback_Invoke,
};
/***********************************************************************
* MFCreateVideoSampleAllocatorEx (mfplat.@)
*/
HRESULT WINAPI MFCreateVideoSampleAllocatorEx(REFIID riid, void **obj)
{
struct sample_allocator *object;
HRESULT hr;
TRACE("%s, %p.\n", debugstr_guid(riid), obj);
if (!(object = heap_alloc_zero(sizeof(*object))))
return E_OUTOFMEMORY;
object->IMFVideoSampleAllocatorEx_iface.lpVtbl = &sample_allocator_vtbl;
object->IMFVideoSampleAllocatorCallback_iface.lpVtbl = &sample_allocator_callback_vtbl;
object->tracking_callback.lpVtbl = &sample_allocator_tracking_callback_vtbl;
object->refcount = 1;
object->frame_desc.buffer_count = 1;
list_init(&object->used_samples);
list_init(&object->free_samples);
InitializeCriticalSection(&object->cs);
hr = IMFVideoSampleAllocatorEx_QueryInterface(&object->IMFVideoSampleAllocatorEx_iface, riid, obj);
IMFVideoSampleAllocatorEx_Release(&object->IMFVideoSampleAllocatorEx_iface);
return hr;
}
......@@ -6302,7 +6302,7 @@ static void test_sample_allocator(void)
if (!pMFCreateVideoSampleAllocatorEx)
{
skip("MFCreateVideoSampleAllocatorEx() is not available.\n");
win_skip("MFCreateVideoSampleAllocatorEx() is not available.\n");
return;
}
......@@ -6392,6 +6392,7 @@ static void test_sample_allocator(void)
hr = IMFVideoSampleAllocatorCallback_GetFreeSampleCount(allocator_cb, &count);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
todo_wine
ok(!count, "Unexpected count %d.\n", count);
check_interface(sample, &IID_IMFTrackedSample, TRUE);
......@@ -6500,9 +6501,11 @@ static void test_sample_allocator(void)
IMFDXGIBuffer_Release(dxgi_buffer);
hr = IMFMediaBuffer_Lock(buffer, &data, NULL, NULL);
todo_wine
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
hr = IMFMediaBuffer_Unlock(buffer);
todo_wine
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
IMFSample_Release(sample);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment