[PATCH 4/5] winegstreamer: Create a winegstreamer parser object in wm_reader_open_stream().
Zebediah Figura
zfigura at codeweavers.com
Mon Oct 25 10:55:00 CDT 2021
Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---
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;
+ }
+
+ 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;
--
2.33.0
More information about the wine-devel
mailing list