Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/winegstreamer/wg_parser.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c index 72dfab8f3d6..9a382cb724c 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c @@ -1272,7 +1272,7 @@ static GstFlowReturn src_getrange_cb(GstPad *pad, GstObject *parent, GstMapInfo map_info; bool ret;
- GST_LOG("pad %p, offset %" G_GINT64_MODIFIER "u, length %u, buffer %p.", pad, offset, size, *buffer); + GST_LOG("pad %p, offset %" G_GINT64_MODIFIER "u, size %u, buffer %p.", pad, offset, size, *buffer);
if (offset == GST_BUFFER_OFFSET_NONE) offset = parser->next_pull_offset; @@ -1281,6 +1281,16 @@ static GstFlowReturn src_getrange_cb(GstPad *pad, GstObject *parent, if (!*buffer) *buffer = new_buffer = gst_buffer_new_and_alloc(size);
+ if (!size) + { + /* asfreader occasionally asks for zero bytes. gst_buffer_map() will + * return NULL in this case. Avoid confusing the read thread by asking + * it for zero bytes. */ + gst_buffer_set_size(*buffer, 0); + GST_LOG("Returning empty buffer."); + return GST_FLOW_OK; + } + gst_buffer_map(*buffer, &map_info, GST_MAP_WRITE);
pthread_mutex_lock(&parser->mutex);
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/winegstreamer/gst_private.h | 2 ++ dlls/winegstreamer/main.c | 27 +++++++++++++++++++++++++++ dlls/winegstreamer/media_source.c | 8 ++++---- dlls/winegstreamer/quartz_parser.c | 8 ++++---- 4 files changed, 37 insertions(+), 8 deletions(-)
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index ebe0bf6f50d..986c8ca695d 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -38,6 +38,8 @@
#include "unixlib.h"
+bool array_reserve(void **elements, size_t *capacity, size_t count, size_t size) DECLSPEC_HIDDEN; + static inline const char *debugstr_time(REFERENCE_TIME time) { ULONGLONG abstime = time >= 0 ? time : -time; diff --git a/dlls/winegstreamer/main.c b/dlls/winegstreamer/main.c index c799aa06d1b..d6f19fb4ad1 100644 --- a/dlls/winegstreamer/main.c +++ b/dlls/winegstreamer/main.c @@ -31,6 +31,33 @@ static unixlib_handle_t unix_handle;
WINE_DEFAULT_DEBUG_CHANNEL(quartz);
+bool array_reserve(void **elements, size_t *capacity, size_t count, size_t size) +{ + unsigned int new_capacity, max_capacity; + void *new_elements; + + if (count <= *capacity) + return TRUE; + + max_capacity = ~(SIZE_T)0 / size; + if (count > max_capacity) + return FALSE; + + new_capacity = max(4, *capacity); + while (new_capacity < count && new_capacity <= max_capacity / 2) + new_capacity *= 2; + if (new_capacity < count) + new_capacity = max_capacity; + + if (!(new_elements = realloc(*elements, new_capacity * size))) + return FALSE; + + *elements = new_elements; + *capacity = new_capacity; + + return TRUE; +} + struct wg_parser *wg_parser_create(enum wg_parser_type type, bool unlimited_buffering) { struct wg_parser_create_params params = diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c index da898f20f66..703bdd7c57d 100644 --- a/dlls/winegstreamer/media_source.c +++ b/dlls/winegstreamer/media_source.c @@ -613,7 +613,7 @@ static DWORD CALLBACK read_thread(void *arg) { struct media_source *source = arg; IMFByteStream *byte_stream = source->byte_stream; - uint32_t buffer_size = 0; + size_t buffer_size = 0; uint64_t file_size; void *data = NULL;
@@ -636,10 +636,10 @@ static DWORD CALLBACK read_thread(void *arg) else if (offset + size >= file_size) size = file_size - offset;
- if (size > buffer_size) + if (!array_reserve(&data, &buffer_size, size, 1)) { - buffer_size = size; - data = realloc(data, size); + free(data); + return 0; }
ret_size = 0; diff --git a/dlls/winegstreamer/quartz_parser.c b/dlls/winegstreamer/quartz_parser.c index 6ae1a99a14a..b6655d5da3c 100644 --- a/dlls/winegstreamer/quartz_parser.c +++ b/dlls/winegstreamer/quartz_parser.c @@ -786,7 +786,7 @@ static DWORD CALLBACK read_thread(void *arg) { struct parser *filter = arg; LONGLONG file_size, unused; - uint32_t buffer_size = 0; + size_t buffer_size = 0; void *data = NULL;
IAsyncReader_Length(filter->reader, &file_size, &unused); @@ -807,10 +807,10 @@ static DWORD CALLBACK read_thread(void *arg) else if (offset + size >= file_size) size = file_size - offset;
- if (size > buffer_size) + if (!array_reserve(&data, &buffer_size, size, 1)) { - buffer_size = size; - data = realloc(data, size); + free(data); + return 0; }
hr = IAsyncReader_SyncRead(filter->reader, offset, size, data);
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/winegstreamer/media_source.c | 7 +++++-- dlls/winegstreamer/quartz_parser.c | 5 ++++- 2 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c index 703bdd7c57d..dab85e4689d 100644 --- a/dlls/winegstreamer/media_source.c +++ b/dlls/winegstreamer/media_source.c @@ -613,9 +613,12 @@ static DWORD CALLBACK read_thread(void *arg) { struct media_source *source = arg; IMFByteStream *byte_stream = source->byte_stream; - size_t buffer_size = 0; + size_t buffer_size = 4096; uint64_t file_size; - void *data = NULL; + void *data; + + if (!(data = malloc(buffer_size))) + return 0;
IMFByteStream_GetLength(byte_stream, &file_size);
diff --git a/dlls/winegstreamer/quartz_parser.c b/dlls/winegstreamer/quartz_parser.c index b6655d5da3c..6d79d2ef129 100644 --- a/dlls/winegstreamer/quartz_parser.c +++ b/dlls/winegstreamer/quartz_parser.c @@ -786,9 +786,12 @@ static DWORD CALLBACK read_thread(void *arg) { struct parser *filter = arg; LONGLONG file_size, unused; - size_t buffer_size = 0; + size_t buffer_size = 4096; void *data = NULL;
+ if (!(data = malloc(buffer_size))) + return 0; + IAsyncReader_Length(filter->reader, &file_size, &unused);
TRACE("Starting read thread for filter %p.\n", filter);
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51837 Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/winegstreamer/media_source.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c index dab85e4689d..c8b8be50c8c 100644 --- a/dlls/winegstreamer/media_source.c +++ b/dlls/winegstreamer/media_source.c @@ -639,6 +639,11 @@ static DWORD CALLBACK read_thread(void *arg) else if (offset + size >= file_size) size = file_size - offset;
+ /* Some IMFByteStreams (including the standard file-based stream) return + * an error when reading past the file size. */ + if (!size) + wg_parser_push_data(source->wg_parser, data, 0); + if (!array_reserve(&data, &buffer_size, size, 1)) { free(data);
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- This has come in handy when debugging several times.
dlls/winegstreamer/wg_parser.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c index 9a382cb724c..0c23ae6d351 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c @@ -1006,6 +1006,7 @@ static gboolean sink_query_cb(GstPad *pad, GstObject *parent, GstQuery *query) case GST_QUERY_CAPS: { GstCaps *caps, *filter, *temp; + gchar *str;
gst_query_parse_caps(query, &filter);
@@ -1016,6 +1017,10 @@ static gboolean sink_query_cb(GstPad *pad, GstObject *parent, GstQuery *query) if (!caps) return FALSE;
+ str = gst_caps_to_string(caps); + GST_LOG("Stream caps are "%s".", str); + g_free(str); + if (filter) { temp = gst_caps_intersect(caps, filter);