[PATCH 4/5] winegstreamer: Implement IWMReaderAdvanced::SetAllocateForStream().

Zebediah Figura zfigura at codeweavers.com
Wed Nov 10 19:05:49 CST 2021


Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---
 dlls/winegstreamer/gst_private.h    |   2 +
 dlls/winegstreamer/wm_asyncreader.c |  11 +--
 dlls/winegstreamer/wm_reader.c      |  32 ++++++++-
 dlls/wmvcore/tests/wmvcore.c        | 108 +++++++++++++++++++++++++---
 4 files changed, 136 insertions(+), 17 deletions(-)

diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index e31405a09ca..e0f8bdae4a6 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -125,6 +125,7 @@ struct wm_stream
     WORD index;
     bool eos;
     bool allocate_output;
+    bool allocate_stream;
     /* Note that we only pretend to read compressed samples, and instead output
      * uncompressed samples regardless of whether we are configured to read
      * compressed samples. Rather, the behaviour of the reader objects differs
@@ -183,6 +184,7 @@ HRESULT wm_reader_open_file(struct wm_reader *reader, const WCHAR *filename);
 HRESULT wm_reader_open_stream(struct wm_reader *reader, IStream *stream);
 void wm_reader_seek(struct wm_reader *reader, QWORD start, LONGLONG duration);
 HRESULT wm_reader_set_allocate_for_output(struct wm_reader *reader, DWORD output, BOOL allocate);
+HRESULT wm_reader_set_allocate_for_stream(struct wm_reader *reader, WORD stream_number, BOOL allocate);
 HRESULT wm_reader_set_output_props(struct wm_reader *reader, DWORD output,
         IWMOutputMediaProps *props);
 HRESULT wm_reader_set_read_compressed(struct wm_reader *reader,
diff --git a/dlls/winegstreamer/wm_asyncreader.c b/dlls/winegstreamer/wm_asyncreader.c
index 9cf8a73eb53..b3dd7d41873 100644
--- a/dlls/winegstreamer/wm_asyncreader.c
+++ b/dlls/winegstreamer/wm_asyncreader.c
@@ -528,11 +528,14 @@ static HRESULT WINAPI WMReaderAdvanced_GetAllocateForOutput(IWMReaderAdvanced6 *
     return E_NOTIMPL;
 }
 
-static HRESULT WINAPI WMReaderAdvanced_SetAllocateForStream(IWMReaderAdvanced6 *iface, WORD output_num, BOOL allocate)
+static HRESULT WINAPI WMReaderAdvanced_SetAllocateForStream(IWMReaderAdvanced6 *iface,
+        WORD stream_number, BOOL allocate)
 {
-    struct async_reader *This = impl_from_IWMReaderAdvanced6(iface);
-    FIXME("(%p)->(%d %x)\n", This, output_num, allocate);
-    return E_NOTIMPL;
+    struct async_reader *reader = impl_from_IWMReaderAdvanced6(iface);
+
+    TRACE("reader %p, stream_number %u, allocate %d.\n", reader, stream_number, allocate);
+
+    return wm_reader_set_allocate_for_stream(&reader->reader, stream_number, allocate);
 }
 
 static HRESULT WINAPI WMReaderAdvanced_GetAllocateForStream(IWMReaderAdvanced6 *iface, WORD output_num, BOOL *allocate)
diff --git a/dlls/winegstreamer/wm_reader.c b/dlls/winegstreamer/wm_reader.c
index c53fb8ea8ee..a6e73c2857e 100644
--- a/dlls/winegstreamer/wm_reader.c
+++ b/dlls/winegstreamer/wm_reader.c
@@ -1792,12 +1792,22 @@ HRESULT wm_reader_get_stream_sample(struct wm_stream *stream,
                 HRESULT hr;
                 BYTE *data;
 
-                if (callback_advanced && !stream->read_compressed && stream->allocate_output)
+                if (callback_advanced && stream->read_compressed && stream->allocate_stream)
+                {
+                    if (FAILED(hr = IWMReaderCallbackAdvanced_AllocateForStream(callback_advanced,
+                            stream->index + 1, event.u.buffer.size, &sample, NULL)))
+                    {
+                        ERR("Failed to allocate stream sample of %u bytes, hr %#x.\n", event.u.buffer.size, hr);
+                        wg_parser_stream_release_buffer(wg_stream);
+                        return hr;
+                    }
+                }
+                else if (callback_advanced && !stream->read_compressed && stream->allocate_output)
                 {
                     if (FAILED(hr = IWMReaderCallbackAdvanced_AllocateForOutput(callback_advanced,
                             stream->index, event.u.buffer.size, &sample, NULL)))
                     {
-                        ERR("Failed to allocate sample of %u bytes, hr %#x.\n", event.u.buffer.size, hr);
+                        ERR("Failed to allocate output sample of %u bytes, hr %#x.\n", event.u.buffer.size, hr);
                         wg_parser_stream_release_buffer(wg_stream);
                         return hr;
                     }
@@ -1970,6 +1980,24 @@ HRESULT wm_reader_set_allocate_for_output(struct wm_reader *reader, DWORD output
     return S_OK;
 }
 
+HRESULT wm_reader_set_allocate_for_stream(struct wm_reader *reader, WORD stream_number, BOOL allocate)
+{
+    struct wm_stream *stream;
+
+    EnterCriticalSection(&reader->cs);
+
+    if (!(stream = wm_reader_get_stream_by_stream_number(reader, stream_number)))
+    {
+        LeaveCriticalSection(&reader->cs);
+        return E_INVALIDARG;
+    }
+
+    stream->allocate_stream = !!allocate;
+
+    LeaveCriticalSection(&reader->cs);
+    return S_OK;
+}
+
 HRESULT wm_reader_set_read_compressed(struct wm_reader *reader, WORD stream_number, BOOL compressed)
 {
     struct wm_stream *stream;
diff --git a/dlls/wmvcore/tests/wmvcore.c b/dlls/wmvcore/tests/wmvcore.c
index eb6e45b30ce..8e10d9f5e89 100644
--- a/dlls/wmvcore/tests/wmvcore.c
+++ b/dlls/wmvcore/tests/wmvcore.c
@@ -356,8 +356,13 @@ static HRESULT WINAPI buffer_GetMaxLength(INSSBuffer *iface, DWORD *size)
 
 static HRESULT WINAPI buffer_GetBuffer(INSSBuffer *iface, BYTE **data)
 {
-    ok(0, "Unexpected call.\n");
-    return E_NOTIMPL;
+    struct buffer *buffer = impl_from_INSSBuffer(iface);
+
+    if (winetest_debug > 1)
+        trace("%04x: INSSBuffer::GetBuffer()\n", GetCurrentThreadId());
+
+    *data = buffer->data;
+    return S_OK;
 }
 
 static HRESULT WINAPI buffer_GetBufferAndLength(INSSBuffer *iface, BYTE **data, DWORD *size)
@@ -1618,8 +1623,32 @@ static HRESULT WINAPI callback_advanced_OnOutputPropsChanged(IWMReaderCallbackAd
 static HRESULT WINAPI callback_advanced_AllocateForStream(IWMReaderCallbackAdvanced *iface,
         WORD stream_number, DWORD size, INSSBuffer **sample, void *context)
 {
-    ok(0, "Unexpected call.\n");
-    return E_NOTIMPL;
+    struct callback *callback = impl_from_IWMReaderCallbackAdvanced(iface);
+    struct buffer *object;
+
+    if (winetest_debug > 1)
+        trace("%u: %04x: IWMReaderCallbackAdvanced::AllocateForStream(output %u, size %u)\n",
+                GetTickCount(), GetCurrentThreadId(), stream_number, size);
+
+    ok(callback->read_compressed, "AllocateForStream() should only be called when reading compressed samples.\n");
+    ok(callback->allocated_samples, "AllocateForStream() should only be called when using a custom allocator.\n");
+
+    if (!(object = malloc(offsetof(struct buffer, data[size]))))
+        return E_OUTOFMEMORY;
+
+    size = max(size, 65536);
+
+    object->INSSBuffer_iface.lpVtbl = &buffer_vtbl;
+    object->refcount = 1;
+    object->capacity = size;
+    /* Native seems to break if we set the size to zero. */
+    object->size = size;
+    *sample = &object->INSSBuffer_iface;
+
+    InterlockedIncrement(&outstanding_buffers);
+
+    ok(!context, "Got unexpected context %p.\n", context);
+    return S_OK;
 }
 
 static HRESULT WINAPI callback_advanced_AllocateForOutput(IWMReaderCallbackAdvanced *iface,
@@ -1632,7 +1661,15 @@ static HRESULT WINAPI callback_advanced_AllocateForOutput(IWMReaderCallbackAdvan
         trace("%u: %04x: IWMReaderCallbackAdvanced::AllocateForOutput(output %u, size %u)\n",
                 GetTickCount(), GetCurrentThreadId(), output, size);
 
-    ok(callback->allocated_samples, "AllocateForOutput() should only be called when using a custom allocator.\n");
+    if (!callback->read_compressed)
+    {
+        /* Actually AllocateForOutput() isn't called when reading compressed
+         * samples either, but native seems to have some sort of race that
+         * causes one call to this function to happen in
+         * test_async_reader_allocate_compressed(). */
+        ok(callback->allocated_samples,
+                "AllocateForOutput() should only be called when using a custom allocator.\n");
+    }
 
     if (!(object = malloc(offsetof(struct buffer, data[size]))))
         return E_OUTOFMEMORY;
@@ -1829,13 +1866,13 @@ static void test_async_reader_allocate(IWMReader *reader,
     ok(hr == S_OK, "Got hr %#x.\n", hr);
 
     hr = IWMReaderAdvanced2_SetAllocateForStream(advanced, 0, TRUE);
-    todo_wine ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+    ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
     hr = IWMReaderAdvanced2_SetAllocateForStream(advanced, 1, TRUE);
-    todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
     hr = IWMReaderAdvanced2_SetAllocateForStream(advanced, 2, TRUE);
-    todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
     hr = IWMReaderAdvanced2_SetAllocateForStream(advanced, 3, TRUE);
-    todo_wine ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+    ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
 
     hr = IWMReaderAdvanced2_GetAllocateForOutput(advanced, 0, &allocate);
     todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
@@ -1858,9 +1895,9 @@ static void test_async_reader_allocate(IWMReader *reader,
     run_async_reader(reader, advanced, callback);
 
     hr = IWMReaderAdvanced2_SetAllocateForStream(advanced, 1, FALSE);
-    todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
     hr = IWMReaderAdvanced2_SetAllocateForStream(advanced, 2, FALSE);
-    todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
 }
 
 static void test_async_reader_selection(IWMReader *reader,
@@ -1963,6 +2000,54 @@ static void test_async_reader_compressed(IWMReader *reader,
     ok(hr == S_OK, "Got hr %#x.\n", hr);
 }
 
+static void test_async_reader_allocate_compressed(IWMReader *reader,
+        IWMReaderAdvanced2 *advanced, struct callback *callback)
+{
+    HRESULT hr;
+
+    callback->read_compressed = true;
+
+    hr = IWMReaderAdvanced2_SetReceiveStreamSamples(advanced, 1, TRUE);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+    hr = IWMReaderAdvanced2_SetReceiveStreamSamples(advanced, 2, TRUE);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+    callback->allocated_samples = true;
+
+    hr = IWMReaderAdvanced2_SetAllocateForStream(advanced, 1, TRUE);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+    hr = IWMReaderAdvanced2_SetAllocateForStream(advanced, 2, TRUE);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+    run_async_reader(reader, advanced, callback);
+
+    hr = IWMReaderAdvanced2_SetAllocateForStream(advanced, 1, FALSE);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+    hr = IWMReaderAdvanced2_SetAllocateForStream(advanced, 2, FALSE);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+    hr = IWMReaderAdvanced2_SetAllocateForOutput(advanced, 0, TRUE);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+    hr = IWMReaderAdvanced2_SetAllocateForOutput(advanced, 1, TRUE);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+    callback->allocated_samples = false;
+
+    run_async_reader(reader, advanced, callback);
+
+    hr = IWMReaderAdvanced2_SetAllocateForOutput(advanced, 0, FALSE);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+    hr = IWMReaderAdvanced2_SetAllocateForOutput(advanced, 1, FALSE);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+    hr = IWMReaderAdvanced2_SetReceiveStreamSamples(advanced, 1, FALSE);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+    hr = IWMReaderAdvanced2_SetReceiveStreamSamples(advanced, 2, FALSE);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+    callback->read_compressed = false;
+}
+
 static void test_async_reader_streaming(void)
 {
     const WCHAR *filename = load_resource(L"test.wmv");
@@ -2056,6 +2141,7 @@ static void test_async_reader_streaming(void)
     test_async_reader_selection(reader, advanced, &callback);
     test_async_reader_allocate(reader, advanced, &callback);
     test_async_reader_compressed(reader, advanced, &callback);
+    test_async_reader_allocate_compressed(reader, advanced, &callback);
 
     hr = IWMReader_Close(reader);
     ok(hr == S_OK, "Got hr %#x.\n", hr);
-- 
2.33.0




More information about the wine-devel mailing list