Zebediah Figura : winegstreamer: Create a winegstreamer parser object in wm_reader_open_stream().

Alexandre Julliard julliard at winehq.org
Tue Oct 26 16:19:18 CDT 2021


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

Author: Zebediah Figura <zfigura at codeweavers.com>
Date:   Mon Oct 25 18:52:12 2021 -0500

winegstreamer: Create a winegstreamer parser object in wm_reader_open_stream().

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

---

 dlls/winegstreamer/gst_private.h |   3 ++
 dlls/winegstreamer/wm_reader.c   | 113 ++++++++++++++++++++++++++++++++++++++-
 2 files changed, 115 insertions(+), 1 deletion(-)

diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index a07195a4a1e..caa449956bf 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -125,6 +125,9 @@ struct wm_reader
     CRITICAL_SECTION cs;
 
     IStream *source_stream;
+    HANDLE read_thread;
+    bool read_thread_shutdown;
+    struct wg_parser *wg_parser;
 
     const struct wm_reader_ops *ops;
 };
diff --git a/dlls/winegstreamer/wm_reader.c b/dlls/winegstreamer/wm_reader.c
index e5c2d2a9789..163eebf8c55 100644
--- a/dlls/winegstreamer/wm_reader.c
+++ b/dlls/winegstreamer/wm_reader.c
@@ -20,6 +20,68 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(wmvcore);
 
+static DWORD CALLBACK read_thread(void *arg)
+{
+    struct wm_reader *reader = arg;
+    IStream *stream = reader->source_stream;
+    size_t buffer_size = 4096;
+    uint64_t file_size;
+    STATSTG stat;
+    void *data;
+
+    if (!(data = malloc(buffer_size)))
+        return 0;
+
+    IStream_Stat(stream, &stat, STATFLAG_NONAME);
+    file_size = stat.cbSize.QuadPart;
+
+    TRACE("Starting read thread for reader %p.\n", reader);
+
+    while (!reader->read_thread_shutdown)
+    {
+        LARGE_INTEGER stream_offset;
+        uint64_t offset;
+        ULONG ret_size;
+        uint32_t size;
+        HRESULT hr;
+
+        if (!wg_parser_get_next_read_offset(reader->wg_parser, &offset, &size))
+            continue;
+
+        if (offset >= file_size)
+            size = 0;
+        else if (offset + size >= file_size)
+            size = file_size - offset;
+
+        if (!size)
+        {
+            wg_parser_push_data(reader->wg_parser, data, 0);
+            continue;
+        }
+
+        if (!array_reserve(&data, &buffer_size, size, 1))
+        {
+            free(data);
+            return 0;
+        }
+
+        ret_size = 0;
+
+        stream_offset.QuadPart = offset;
+        if (SUCCEEDED(hr = IStream_Seek(stream, stream_offset, STREAM_SEEK_SET, NULL)))
+            hr = IStream_Read(stream, data, size, &ret_size);
+        if (FAILED(hr))
+            ERR("Failed to read %u bytes at offset %I64u, hr %#x.\n", size, offset, hr);
+        else if (ret_size != size)
+            ERR("Unexpected short read: requested %u bytes, got %u.\n", size, ret_size);
+        wg_parser_push_data(reader->wg_parser, SUCCEEDED(hr) ? data : NULL, ret_size);
+    }
+
+    free(data);
+    TRACE("Reader is shutting down; exiting.\n");
+    return 0;
+}
+
 static struct wm_reader *impl_from_IWMProfile3(IWMProfile3 *iface)
 {
     return CONTAINING_RECORD(iface, struct wm_reader, IWMProfile3_iface);
@@ -761,13 +823,53 @@ static const IWMReaderTimecodeVtbl timecode_vtbl =
 
 HRESULT wm_reader_open_stream(struct wm_reader *reader, IStream *stream)
 {
+    struct wg_parser *wg_parser;
+    STATSTG stat;
+    HRESULT hr;
+
+    if (FAILED(hr = IStream_Stat(stream, &stat, STATFLAG_NONAME)))
+    {
+        ERR("Failed to stat stream, hr %#x.\n", hr);
+        return hr;
+    }
+
+    if (!(wg_parser = wg_parser_create(WG_PARSER_DECODEBIN, false)))
+        return E_OUTOFMEMORY;
+
     EnterCriticalSection(&reader->cs);
 
+    reader->wg_parser = wg_parser;
     IStream_AddRef(reader->source_stream = stream);
+    reader->read_thread_shutdown = false;
+    if (!(reader->read_thread = CreateThread(NULL, 0, read_thread, reader, 0, NULL)))
+    {
+        hr = E_OUTOFMEMORY;
+        goto out_destroy_parser;
+    }
 
-    LeaveCriticalSection(&reader->cs);
+    if (FAILED(hr = wg_parser_connect(reader->wg_parser, stat.cbSize.QuadPart)))
+    {
+        ERR("Failed to connect parser, hr %#x.\n", hr);
+        goto out_shutdown_thread;
+    }
 
+    LeaveCriticalSection(&reader->cs);
     return S_OK;
+
+out_shutdown_thread:
+    reader->read_thread_shutdown = true;
+    WaitForSingleObject(reader->read_thread, INFINITE);
+    CloseHandle(reader->read_thread);
+    reader->read_thread = NULL;
+
+out_destroy_parser:
+    wg_parser_destroy(reader->wg_parser);
+    reader->wg_parser = NULL;
+    IStream_Release(reader->source_stream);
+    reader->source_stream = NULL;
+
+    LeaveCriticalSection(&reader->cs);
+    return hr;
 }
 
 HRESULT wm_reader_close(struct wm_reader *reader)
@@ -780,6 +882,15 @@ HRESULT wm_reader_close(struct wm_reader *reader)
         return NS_E_INVALID_REQUEST;
     }
 
+    wg_parser_disconnect(reader->wg_parser);
+
+    reader->read_thread_shutdown = true;
+    WaitForSingleObject(reader->read_thread, INFINITE);
+    CloseHandle(reader->read_thread);
+    reader->read_thread = NULL;
+
+    wg_parser_destroy(reader->wg_parser);
+    reader->wg_parser = NULL;
     IStream_Release(reader->source_stream);
     reader->source_stream = NULL;
 




More information about the wine-cvs mailing list