Nikolay Sivov : evr/sample: Add a surface buffer on sample creation.

Alexandre Julliard julliard at winehq.org
Wed Oct 14 15:37:21 CDT 2020


Module: wine
Branch: master
Commit: 208520f8d956dc2ea88c3461c6c6e57001b4b648
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=208520f8d956dc2ea88c3461c6c6e57001b4b648

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Wed Oct 14 16:03:11 2020 +0300

evr/sample: Add a surface buffer on sample creation.

Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/evr/sample.c    | 190 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 dlls/evr/tests/evr.c |  20 ++++--
 2 files changed, 202 insertions(+), 8 deletions(-)

diff --git a/dlls/evr/sample.c b/dlls/evr/sample.c
index 5427833a2c..668e675da2 100644
--- a/dlls/evr/sample.c
+++ b/dlls/evr/sample.c
@@ -48,6 +48,16 @@ static const char *debugstr_time(LONGLONG time)
     return wine_dbg_sprintf("%s", rev);
 }
 
+struct surface_buffer
+{
+    IMFMediaBuffer IMFMediaBuffer_iface;
+    IMFGetService IMFGetService_iface;
+    LONG refcount;
+
+    IUnknown *surface;
+    ULONG length;
+};
+
 struct video_sample
 {
     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);
 }
 
+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
 {
     IMFVideoSampleAllocator IMFVideoSampleAllocator_iface;
@@ -929,16 +949,171 @@ static const IMFDesiredSampleVtbl desired_video_sample_vtbl =
     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)
 {
     struct video_sample *object;
+    IMFMediaBuffer *buffer = NULL;
     HRESULT hr;
 
     TRACE("%p, %p.\n", surface, sample);
 
-    if (surface)
-        FIXME("Create surface buffer.\n");
-
     if (!(object = heap_alloc_zero(sizeof(*object))))
         return E_OUTOFMEMORY;
 
@@ -953,6 +1128,15 @@ HRESULT WINAPI MFCreateVideoSampleFromSurface(IUnknown *surface, IMFSample **sam
         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;
 
     return S_OK;
diff --git a/dlls/evr/tests/evr.c b/dlls/evr/tests/evr.c
index b924ac2d9b..69ee2d3d96 100644
--- a/dlls/evr/tests/evr.c
+++ b/dlls/evr/tests/evr.c
@@ -750,6 +750,10 @@ static void test_surface_sample(void)
 
     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);
     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;
     hr = IMFSample_GetBufferCount(sample, &count);
     ok(hr == S_OK, "Failed to get buffer count, hr %#x.\n", hr);
-todo_wine
     ok(count == 1, "Unexpected attribute count.\n");
 
     hr = IMFSample_GetTotalLength(sample, &length);
@@ -822,11 +825,8 @@ todo_wine
     ok(hr == MF_E_NO_SAMPLE_TIMESTAMP, "Unexpected hr %#x.\n", hr);
 
     hr = IMFSample_GetBufferByIndex(sample, 0, &buffer);
-todo_wine
     ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
 
-if (SUCCEEDED(hr))
-{
     hr = IMFMediaBuffer_GetMaxLength(buffer, &length);
     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(!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);
     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);
     ok(hr == E_NOINTERFACE, "Unexpected hr %#x.\n", hr);
 
@@ -861,7 +871,7 @@ if (SUCCEEDED(hr))
     ok(!count, "Unexpected attribute count.\n");
 
     IMFMediaBuffer_Release(buffer);
-}
+
     hr = IMFSample_GetSampleFlags(sample, &flags);
     ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
 




More information about the wine-cvs mailing list