evr/sample: Add a surface buffer on sample creation.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
1cb37f7e80
commit
208520f8d9
|
@ -48,6 +48,16 @@ static const char *debugstr_time(LONGLONG time)
|
||||||
return wine_dbg_sprintf("%s", rev);
|
return wine_dbg_sprintf("%s", rev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct surface_buffer
|
||||||
|
{
|
||||||
|
IMFMediaBuffer IMFMediaBuffer_iface;
|
||||||
|
IMFGetService IMFGetService_iface;
|
||||||
|
LONG refcount;
|
||||||
|
|
||||||
|
IUnknown *surface;
|
||||||
|
ULONG length;
|
||||||
|
};
|
||||||
|
|
||||||
struct video_sample
|
struct video_sample
|
||||||
{
|
{
|
||||||
IMFSample IMFSample_iface;
|
IMFSample IMFSample_iface;
|
||||||
|
@ -80,6 +90,16 @@ static struct video_sample *impl_from_IMFDesiredSample(IMFDesiredSample *iface)
|
||||||
return CONTAINING_RECORD(iface, struct video_sample, IMFDesiredSample_iface);
|
return CONTAINING_RECORD(iface, struct video_sample, IMFDesiredSample_iface);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct surface_buffer *impl_from_IMFMediaBuffer(IMFMediaBuffer *iface)
|
||||||
|
{
|
||||||
|
return CONTAINING_RECORD(iface, struct surface_buffer, IMFMediaBuffer_iface);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct surface_buffer *impl_from_IMFGetService(IMFGetService *iface)
|
||||||
|
{
|
||||||
|
return CONTAINING_RECORD(iface, struct surface_buffer, IMFGetService_iface);
|
||||||
|
}
|
||||||
|
|
||||||
struct sample_allocator
|
struct sample_allocator
|
||||||
{
|
{
|
||||||
IMFVideoSampleAllocator IMFVideoSampleAllocator_iface;
|
IMFVideoSampleAllocator IMFVideoSampleAllocator_iface;
|
||||||
|
@ -929,16 +949,171 @@ static const IMFDesiredSampleVtbl desired_video_sample_vtbl =
|
||||||
desired_video_sample_Clear,
|
desired_video_sample_Clear,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static HRESULT WINAPI surface_buffer_QueryInterface(IMFMediaBuffer *iface, REFIID riid, void **obj)
|
||||||
|
{
|
||||||
|
struct surface_buffer *buffer = impl_from_IMFMediaBuffer(iface);
|
||||||
|
|
||||||
|
TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
|
||||||
|
|
||||||
|
if (IsEqualIID(riid, &IID_IMFMediaBuffer) || IsEqualIID(riid, &IID_IUnknown))
|
||||||
|
{
|
||||||
|
*obj = &buffer->IMFMediaBuffer_iface;
|
||||||
|
}
|
||||||
|
else if (IsEqualIID(riid, &IID_IMFGetService))
|
||||||
|
{
|
||||||
|
*obj = &buffer->IMFGetService_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 surface_buffer_AddRef(IMFMediaBuffer *iface)
|
||||||
|
{
|
||||||
|
struct surface_buffer *buffer = impl_from_IMFMediaBuffer(iface);
|
||||||
|
ULONG refcount = InterlockedIncrement(&buffer->refcount);
|
||||||
|
|
||||||
|
TRACE("%p, refcount %u.\n", iface, refcount);
|
||||||
|
|
||||||
|
return refcount;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ULONG WINAPI surface_buffer_Release(IMFMediaBuffer *iface)
|
||||||
|
{
|
||||||
|
struct surface_buffer *buffer = impl_from_IMFMediaBuffer(iface);
|
||||||
|
ULONG refcount = InterlockedDecrement(&buffer->refcount);
|
||||||
|
|
||||||
|
TRACE("%p, refcount %u.\n", iface, refcount);
|
||||||
|
|
||||||
|
if (!refcount)
|
||||||
|
{
|
||||||
|
IUnknown_Release(buffer->surface);
|
||||||
|
heap_free(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return refcount;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI surface_buffer_Lock(IMFMediaBuffer *iface, BYTE **data, DWORD *maxlength, DWORD *length)
|
||||||
|
{
|
||||||
|
TRACE("%p, %p, %p, %p.\n", iface, data, maxlength, length);
|
||||||
|
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI surface_buffer_Unlock(IMFMediaBuffer *iface)
|
||||||
|
{
|
||||||
|
TRACE("%p.\n", iface);
|
||||||
|
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI surface_buffer_GetCurrentLength(IMFMediaBuffer *iface, DWORD *length)
|
||||||
|
{
|
||||||
|
struct surface_buffer *buffer = impl_from_IMFMediaBuffer(iface);
|
||||||
|
|
||||||
|
TRACE("%p.\n", iface);
|
||||||
|
|
||||||
|
*length = buffer->length;
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI surface_buffer_SetCurrentLength(IMFMediaBuffer *iface, DWORD length)
|
||||||
|
{
|
||||||
|
struct surface_buffer *buffer = impl_from_IMFMediaBuffer(iface);
|
||||||
|
|
||||||
|
TRACE("%p.\n", iface);
|
||||||
|
|
||||||
|
buffer->length = length;
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI surface_buffer_GetMaxLength(IMFMediaBuffer *iface, DWORD *length)
|
||||||
|
{
|
||||||
|
TRACE("%p.\n", iface);
|
||||||
|
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const IMFMediaBufferVtbl surface_buffer_vtbl =
|
||||||
|
{
|
||||||
|
surface_buffer_QueryInterface,
|
||||||
|
surface_buffer_AddRef,
|
||||||
|
surface_buffer_Release,
|
||||||
|
surface_buffer_Lock,
|
||||||
|
surface_buffer_Unlock,
|
||||||
|
surface_buffer_GetCurrentLength,
|
||||||
|
surface_buffer_SetCurrentLength,
|
||||||
|
surface_buffer_GetMaxLength,
|
||||||
|
};
|
||||||
|
|
||||||
|
static HRESULT WINAPI surface_buffer_gs_QueryInterface(IMFGetService *iface, REFIID riid, void **obj)
|
||||||
|
{
|
||||||
|
struct surface_buffer *buffer = impl_from_IMFGetService(iface);
|
||||||
|
return IMFMediaBuffer_QueryInterface(&buffer->IMFMediaBuffer_iface, riid, obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ULONG WINAPI surface_buffer_gs_AddRef(IMFGetService *iface)
|
||||||
|
{
|
||||||
|
struct surface_buffer *buffer = impl_from_IMFGetService(iface);
|
||||||
|
return IMFMediaBuffer_AddRef(&buffer->IMFMediaBuffer_iface);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ULONG WINAPI surface_buffer_gs_Release(IMFGetService *iface)
|
||||||
|
{
|
||||||
|
struct surface_buffer *buffer = impl_from_IMFGetService(iface);
|
||||||
|
return IMFMediaBuffer_Release(&buffer->IMFMediaBuffer_iface);
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI surface_buffer_gs_GetService(IMFGetService *iface, REFGUID service, REFIID riid, void **obj)
|
||||||
|
{
|
||||||
|
FIXME("%p, %s, %s, %p.\n", iface, debugstr_guid(service), debugstr_guid(riid), obj);
|
||||||
|
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const IMFGetServiceVtbl surface_buffer_gs_vtbl =
|
||||||
|
{
|
||||||
|
surface_buffer_gs_QueryInterface,
|
||||||
|
surface_buffer_gs_AddRef,
|
||||||
|
surface_buffer_gs_Release,
|
||||||
|
surface_buffer_gs_GetService,
|
||||||
|
};
|
||||||
|
|
||||||
|
static HRESULT create_surface_buffer(IUnknown *surface, IMFMediaBuffer **buffer)
|
||||||
|
{
|
||||||
|
struct surface_buffer *object;
|
||||||
|
|
||||||
|
if (!(object = heap_alloc_zero(sizeof(*object))))
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
|
||||||
|
object->IMFMediaBuffer_iface.lpVtbl = &surface_buffer_vtbl;
|
||||||
|
object->IMFGetService_iface.lpVtbl = &surface_buffer_gs_vtbl;
|
||||||
|
object->refcount = 1;
|
||||||
|
object->surface = surface;
|
||||||
|
IUnknown_AddRef(object->surface);
|
||||||
|
|
||||||
|
*buffer = &object->IMFMediaBuffer_iface;
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
HRESULT WINAPI MFCreateVideoSampleFromSurface(IUnknown *surface, IMFSample **sample)
|
HRESULT WINAPI MFCreateVideoSampleFromSurface(IUnknown *surface, IMFSample **sample)
|
||||||
{
|
{
|
||||||
struct video_sample *object;
|
struct video_sample *object;
|
||||||
|
IMFMediaBuffer *buffer = NULL;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
TRACE("%p, %p.\n", surface, sample);
|
TRACE("%p, %p.\n", surface, sample);
|
||||||
|
|
||||||
if (surface)
|
|
||||||
FIXME("Create surface buffer.\n");
|
|
||||||
|
|
||||||
if (!(object = heap_alloc_zero(sizeof(*object))))
|
if (!(object = heap_alloc_zero(sizeof(*object))))
|
||||||
return E_OUTOFMEMORY;
|
return E_OUTOFMEMORY;
|
||||||
|
|
||||||
|
@ -953,6 +1128,15 @@ HRESULT WINAPI MFCreateVideoSampleFromSurface(IUnknown *surface, IMFSample **sam
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (surface && FAILED(hr = create_surface_buffer(surface, &buffer)))
|
||||||
|
{
|
||||||
|
IMFSample_Release(&object->IMFSample_iface);
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer)
|
||||||
|
IMFSample_AddBuffer(object->sample, buffer);
|
||||||
|
|
||||||
*sample = &object->IMFSample_iface;
|
*sample = &object->IMFSample_iface;
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
|
|
@ -750,6 +750,10 @@ static void test_surface_sample(void)
|
||||||
|
|
||||||
IDirect3DSwapChain9_Release(swapchain);
|
IDirect3DSwapChain9_Release(swapchain);
|
||||||
|
|
||||||
|
hr = MFCreateVideoSampleFromSurface(NULL, &sample);
|
||||||
|
ok(hr == S_OK, "Failed to create surface sample, hr %#x.\n", hr);
|
||||||
|
IMFSample_Release(sample);
|
||||||
|
|
||||||
hr = MFCreateVideoSampleFromSurface((IUnknown *)backbuffer, &sample);
|
hr = MFCreateVideoSampleFromSurface((IUnknown *)backbuffer, &sample);
|
||||||
ok(hr == S_OK, "Failed to create surface sample, hr %#x.\n", hr);
|
ok(hr == S_OK, "Failed to create surface sample, hr %#x.\n", hr);
|
||||||
|
|
||||||
|
@ -808,7 +812,6 @@ static void test_surface_sample(void)
|
||||||
count = 0;
|
count = 0;
|
||||||
hr = IMFSample_GetBufferCount(sample, &count);
|
hr = IMFSample_GetBufferCount(sample, &count);
|
||||||
ok(hr == S_OK, "Failed to get buffer count, hr %#x.\n", hr);
|
ok(hr == S_OK, "Failed to get buffer count, hr %#x.\n", hr);
|
||||||
todo_wine
|
|
||||||
ok(count == 1, "Unexpected attribute count.\n");
|
ok(count == 1, "Unexpected attribute count.\n");
|
||||||
|
|
||||||
hr = IMFSample_GetTotalLength(sample, &length);
|
hr = IMFSample_GetTotalLength(sample, &length);
|
||||||
|
@ -822,11 +825,8 @@ todo_wine
|
||||||
ok(hr == MF_E_NO_SAMPLE_TIMESTAMP, "Unexpected hr %#x.\n", hr);
|
ok(hr == MF_E_NO_SAMPLE_TIMESTAMP, "Unexpected hr %#x.\n", hr);
|
||||||
|
|
||||||
hr = IMFSample_GetBufferByIndex(sample, 0, &buffer);
|
hr = IMFSample_GetBufferByIndex(sample, 0, &buffer);
|
||||||
todo_wine
|
|
||||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
hr = IMFMediaBuffer_GetMaxLength(buffer, &length);
|
hr = IMFMediaBuffer_GetMaxLength(buffer, &length);
|
||||||
ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
|
ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
|
||||||
|
|
||||||
|
@ -834,9 +834,19 @@ if (SUCCEEDED(hr))
|
||||||
ok(hr == S_OK, "Failed to get length, hr %#x.\n", hr);
|
ok(hr == S_OK, "Failed to get length, hr %#x.\n", hr);
|
||||||
ok(!length, "Unexpected length %u.\n", length);
|
ok(!length, "Unexpected length %u.\n", length);
|
||||||
|
|
||||||
|
hr = IMFMediaBuffer_SetCurrentLength(buffer, 16);
|
||||||
|
ok(hr == S_OK, "Failed to get length, hr %#x.\n", hr);
|
||||||
|
|
||||||
|
hr = IMFMediaBuffer_GetCurrentLength(buffer, &length);
|
||||||
|
ok(hr == S_OK, "Failed to get length, hr %#x.\n", hr);
|
||||||
|
ok(length == 16, "Unexpected length %u.\n", length);
|
||||||
|
|
||||||
hr = IMFMediaBuffer_Lock(buffer, &data, NULL, NULL);
|
hr = IMFMediaBuffer_Lock(buffer, &data, NULL, NULL);
|
||||||
ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
|
ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
|
||||||
|
|
||||||
|
hr = IMFMediaBuffer_Unlock(buffer);
|
||||||
|
ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
|
||||||
|
|
||||||
hr = IMFMediaBuffer_QueryInterface(buffer, &IID_IMF2DBuffer, (void **)&unk);
|
hr = IMFMediaBuffer_QueryInterface(buffer, &IID_IMF2DBuffer, (void **)&unk);
|
||||||
ok(hr == E_NOINTERFACE, "Unexpected hr %#x.\n", hr);
|
ok(hr == E_NOINTERFACE, "Unexpected hr %#x.\n", hr);
|
||||||
|
|
||||||
|
@ -861,7 +871,7 @@ if (SUCCEEDED(hr))
|
||||||
ok(!count, "Unexpected attribute count.\n");
|
ok(!count, "Unexpected attribute count.\n");
|
||||||
|
|
||||||
IMFMediaBuffer_Release(buffer);
|
IMFMediaBuffer_Release(buffer);
|
||||||
}
|
|
||||||
hr = IMFSample_GetSampleFlags(sample, &flags);
|
hr = IMFSample_GetSampleFlags(sample, &flags);
|
||||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue