Zebediah Figura : winegstreamer: Implement IWMReaderAdvanced::SetAllocateForOutput().

Alexandre Julliard julliard at winehq.org
Thu Nov 11 16:01:28 CST 2021


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

Author: Zebediah Figura <zfigura at codeweavers.com>
Date:   Wed Nov 10 19:05:46 2021 -0600

winegstreamer: Implement IWMReaderAdvanced::SetAllocateForOutput().

Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/winegstreamer/gst_private.h    |  8 +++-
 dlls/winegstreamer/wm_asyncreader.c | 17 ++++++--
 dlls/winegstreamer/wm_reader.c      | 84 +++++++++++++++++++++++++++++++------
 3 files changed, 91 insertions(+), 18 deletions(-)

diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index e1dec7b755c..f1862515ebc 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -120,10 +120,11 @@ struct wm_stream
 {
     struct wm_reader *reader;
     struct wg_parser_stream *wg_stream;
-    WORD index;
-    bool eos;
     struct wg_format format;
     WMT_STREAM_SELECTION selection;
+    WORD index;
+    bool eos;
+    bool allocate_output;
 };
 
 struct wm_reader
@@ -148,6 +149,8 @@ struct wm_reader
     struct wm_stream *streams;
     WORD stream_count;
 
+    IWMReaderCallbackAdvanced *callback_advanced;
+
     const struct wm_reader_ops *ops;
 };
 
@@ -174,6 +177,7 @@ void wm_reader_init(struct wm_reader *reader, const struct wm_reader_ops *ops);
 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_output_props(struct wm_reader *reader, DWORD output,
         IWMOutputMediaProps *props);
 HRESULT wm_reader_set_streams_selected(struct wm_reader *reader, WORD count,
diff --git a/dlls/winegstreamer/wm_asyncreader.c b/dlls/winegstreamer/wm_asyncreader.c
index 35ed8221aa0..e0547dfda60 100644
--- a/dlls/winegstreamer/wm_asyncreader.c
+++ b/dlls/winegstreamer/wm_asyncreader.c
@@ -57,10 +57,16 @@ static REFERENCE_TIME get_current_time(const struct async_reader *reader)
 static void open_stream(struct async_reader *reader, IWMReaderCallback *callback, void *context)
 {
     static const DWORD zero;
+    HRESULT hr;
 
     IWMReaderCallback_AddRef(reader->callback = callback);
     reader->context = context;
     IWMReaderCallback_OnStatus(callback, WMT_OPENED, S_OK, WMT_TYPE_DWORD, (BYTE *)&zero, context);
+
+    if (FAILED(hr = IWMReaderCallback_QueryInterface(callback,
+            &IID_IWMReaderCallbackAdvanced, (void **)&reader->reader.callback_advanced)))
+        reader->reader.callback_advanced = NULL;
+    TRACE("Querying for IWMReaderCallbackAdvanced returned %#x.\n", hr);
 }
 
 static DWORD WINAPI stream_thread(void *arg)
@@ -497,11 +503,14 @@ static HRESULT WINAPI WMReaderAdvanced_GetReceiveStreamSamples(IWMReaderAdvanced
     return E_NOTIMPL;
 }
 
-static HRESULT WINAPI WMReaderAdvanced_SetAllocateForOutput(IWMReaderAdvanced6 *iface, DWORD output_num, BOOL allocate)
+static HRESULT WINAPI WMReaderAdvanced_SetAllocateForOutput(IWMReaderAdvanced6 *iface,
+        DWORD output, 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, output %u, allocate %d.\n", reader, output, allocate);
+
+    return wm_reader_set_allocate_for_output(&reader->reader, output, allocate);
 }
 
 static HRESULT WINAPI WMReaderAdvanced_GetAllocateForOutput(IWMReaderAdvanced6 *iface, DWORD output_num, BOOL *allocate)
diff --git a/dlls/winegstreamer/wm_reader.c b/dlls/winegstreamer/wm_reader.c
index 0e0c639d504..810a800f016 100644
--- a/dlls/winegstreamer/wm_reader.c
+++ b/dlls/winegstreamer/wm_reader.c
@@ -1532,6 +1532,10 @@ HRESULT wm_reader_close(struct wm_reader *reader)
     CloseHandle(reader->read_thread);
     reader->read_thread = NULL;
 
+    if (reader->callback_advanced)
+        IWMReaderCallbackAdvanced_Release(reader->callback_advanced);
+    reader->callback_advanced = NULL;
+
     wg_parser_destroy(reader->wg_parser);
     reader->wg_parser = NULL;
 
@@ -1736,9 +1740,9 @@ static const char *get_major_type_string(enum wg_major_type type)
 HRESULT wm_reader_get_stream_sample(struct wm_stream *stream,
         INSSBuffer **ret_sample, QWORD *pts, QWORD *duration, DWORD *flags)
 {
+    IWMReaderCallbackAdvanced *callback_advanced = stream->reader->callback_advanced;
     struct wg_parser_stream *wg_stream = stream->wg_stream;
     struct wg_parser_event event;
-    struct buffer *object;
 
     if (stream->selection == WMT_OFF)
         return NS_E_INVALID_REQUEST;
@@ -1746,6 +1750,9 @@ HRESULT wm_reader_get_stream_sample(struct wm_stream *stream,
     if (stream->eos)
         return NS_E_NO_MORE_SAMPLES;
 
+    if (!stream->allocate_output)
+        callback_advanced = NULL;
+
     for (;;)
     {
         if (!wg_parser_stream_get_event(wg_stream, &event))
@@ -1760,24 +1767,59 @@ HRESULT wm_reader_get_stream_sample(struct wm_stream *stream,
         switch (event.type)
         {
             case WG_PARSER_EVENT_BUFFER:
-                /* FIXME: Should these be pooled? */
-                if (!(object = calloc(1, offsetof(struct buffer, data[event.u.buffer.size]))))
+            {
+                DWORD size, capacity;
+                INSSBuffer *sample;
+                HRESULT hr;
+                BYTE *data;
+
+                if (callback_advanced)
                 {
-                    wg_parser_stream_release_buffer(wg_stream);
-                    return E_OUTOFMEMORY;
+                    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);
+                        wg_parser_stream_release_buffer(wg_stream);
+                        return hr;
+                    }
+                }
+                else
+                {
+                    struct buffer *object;
+
+                    /* FIXME: Should these be pooled? */
+                    if (!(object = calloc(1, offsetof(struct buffer, data[event.u.buffer.size]))))
+                    {
+                        wg_parser_stream_release_buffer(wg_stream);
+                        return E_OUTOFMEMORY;
+                    }
+
+                    object->INSSBuffer_iface.lpVtbl = &buffer_vtbl;
+                    object->refcount = 1;
+                    object->capacity = event.u.buffer.size;
+
+                    TRACE("Created buffer %p.\n", object);
+                    sample = &object->INSSBuffer_iface;
                 }
 
-                object->INSSBuffer_iface.lpVtbl = &buffer_vtbl;
-                object->refcount = 1;
-                object->capacity = object->size = event.u.buffer.size;
+                if (FAILED(hr = INSSBuffer_GetBufferAndLength(sample, &data, &size)))
+                    ERR("Failed to get data pointer, hr %#x.\n", hr);
+                if (FAILED(hr = INSSBuffer_GetMaxLength(sample, &capacity)))
+                    ERR("Failed to get capacity, hr %#x.\n", hr);
+                if (event.u.buffer.size > capacity)
+                    ERR("Returned capacity %u is less than requested capacity %u.\n",
+                            capacity, event.u.buffer.size);
 
-                if (!wg_parser_stream_copy_buffer(wg_stream, object->data, 0, object->size))
+                if (!wg_parser_stream_copy_buffer(wg_stream, data, 0, event.u.buffer.size))
                 {
                     /* The GStreamer pin has been flushed. */
-                    free(object);
+                    INSSBuffer_Release(sample);
                     break;
                 }
 
+                if (FAILED(hr = INSSBuffer_SetLength(sample, event.u.buffer.size)))
+                    ERR("Failed to set size %u, hr %#x.\n", event.u.buffer.size, hr);
+
                 wg_parser_stream_release_buffer(wg_stream);
 
                 if (!event.u.buffer.has_pts)
@@ -1793,9 +1835,9 @@ HRESULT wm_reader_get_stream_sample(struct wm_stream *stream,
                 if (!event.u.buffer.delta)
                     *flags |= WM_SF_CLEANPOINT;
 
-                TRACE("Created buffer %p.\n", object);
-                *ret_sample = &object->INSSBuffer_iface;
+                *ret_sample = sample;
                 return S_OK;
+            }
 
             case WG_PARSER_EVENT_EOS:
                 stream->eos = true;
@@ -1891,6 +1933,24 @@ HRESULT wm_reader_get_stream_selection(struct wm_reader *reader,
     return S_OK;
 }
 
+HRESULT wm_reader_set_allocate_for_output(struct wm_reader *reader, DWORD output, BOOL allocate)
+{
+    struct wm_stream *stream;
+
+    EnterCriticalSection(&reader->cs);
+
+    if (!(stream = get_stream_by_output_number(reader, output)))
+    {
+        LeaveCriticalSection(&reader->cs);
+        return E_INVALIDARG;
+    }
+
+    stream->allocate_output = !!allocate;
+
+    LeaveCriticalSection(&reader->cs);
+    return S_OK;
+}
+
 void wm_reader_init(struct wm_reader *reader, const struct wm_reader_ops *ops)
 {
     reader->IWMHeaderInfo3_iface.lpVtbl = &header_info_vtbl;




More information about the wine-cvs mailing list