Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/winegstreamer/gst_private.h | 2 ++ dlls/winegstreamer/gstdemux.c | 35 +++++++++++++++++++------------- dlls/winegstreamer/wg_parser.c | 7 +++++++ 3 files changed, 30 insertions(+), 14 deletions(-)
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index 0a37e10c840..d95f58dc607 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -217,6 +217,8 @@ struct unix_funcs
uint32_t (CDECL *wg_parser_get_stream_count)(struct wg_parser *parser); struct wg_parser_stream *(CDECL *wg_parser_get_stream)(struct wg_parser *parser, uint32_t index); + + void (CDECL *wg_parser_stream_get_preferred_format)(struct wg_parser_stream *stream, struct wg_format *format); };
extern const struct unix_funcs *unix_funcs; diff --git a/dlls/winegstreamer/gstdemux.c b/dlls/winegstreamer/gstdemux.c index be1c59453d5..95e55a55f22 100644 --- a/dlls/winegstreamer/gstdemux.c +++ b/dlls/winegstreamer/gstdemux.c @@ -1064,8 +1064,7 @@ static HRESULT decodebin_parser_source_query_accept(struct parser_source *pin, c static HRESULT decodebin_parser_source_get_media_type(struct parser_source *pin, unsigned int index, AM_MEDIA_TYPE *mt) { - struct wg_parser_stream *stream = pin->wg_stream; - struct wg_format format = stream->preferred_format; + struct wg_format format;
static const enum wg_video_format video_formats[] = { @@ -1086,6 +1085,8 @@ static HRESULT decodebin_parser_source_get_media_type(struct parser_source *pin, WG_VIDEO_FORMAT_RGB15, };
+ unix_funcs->wg_parser_stream_get_preferred_format(pin->wg_stream, &format); + memset(mt, 0, sizeof(AM_MEDIA_TYPE));
if (amt_from_wg_format(mt, &format)) @@ -1673,11 +1674,12 @@ static BOOL wave_parser_filter_init_gst(struct parser *filter)
static HRESULT wave_parser_source_query_accept(struct parser_source *pin, const AM_MEDIA_TYPE *mt) { - struct wg_parser_stream *stream = pin->wg_stream; + struct wg_format format; AM_MEDIA_TYPE pad_mt; HRESULT hr;
- if (!amt_from_wg_format(&pad_mt, &stream->preferred_format)) + unix_funcs->wg_parser_stream_get_preferred_format(pin->wg_stream, &format); + if (!amt_from_wg_format(&pad_mt, &format)) return E_OUTOFMEMORY; hr = compare_media_types(mt, &pad_mt) ? S_OK : S_FALSE; FreeMediaType(&pad_mt); @@ -1687,11 +1689,12 @@ static HRESULT wave_parser_source_query_accept(struct parser_source *pin, const static HRESULT wave_parser_source_get_media_type(struct parser_source *pin, unsigned int index, AM_MEDIA_TYPE *mt) { - struct wg_parser_stream *stream = pin->wg_stream; + struct wg_format format;
if (index > 0) return VFW_S_NO_MORE_ITEMS; - if (!amt_from_wg_format(mt, &stream->preferred_format)) + unix_funcs->wg_parser_stream_get_preferred_format(pin->wg_stream, &format); + if (!amt_from_wg_format(mt, &format)) return E_OUTOFMEMORY; return S_OK; } @@ -1761,11 +1764,12 @@ static BOOL avi_splitter_filter_init_gst(struct parser *filter)
static HRESULT avi_splitter_source_query_accept(struct parser_source *pin, const AM_MEDIA_TYPE *mt) { - struct wg_parser_stream *stream = pin->wg_stream; + struct wg_format format; AM_MEDIA_TYPE pad_mt; HRESULT hr;
- if (!amt_from_wg_format(&pad_mt, &stream->preferred_format)) + unix_funcs->wg_parser_stream_get_preferred_format(pin->wg_stream, &format); + if (!amt_from_wg_format(&pad_mt, &format)) return E_OUTOFMEMORY; hr = compare_media_types(mt, &pad_mt) ? S_OK : S_FALSE; FreeMediaType(&pad_mt); @@ -1775,11 +1779,12 @@ static HRESULT avi_splitter_source_query_accept(struct parser_source *pin, const static HRESULT avi_splitter_source_get_media_type(struct parser_source *pin, unsigned int index, AM_MEDIA_TYPE *mt) { - struct wg_parser_stream *stream = pin->wg_stream; + struct wg_format format;
if (index > 0) return VFW_S_NO_MORE_ITEMS; - if (!amt_from_wg_format(mt, &stream->preferred_format)) + unix_funcs->wg_parser_stream_get_preferred_format(pin->wg_stream, &format); + if (!amt_from_wg_format(mt, &format)) return E_OUTOFMEMORY; return S_OK; } @@ -1847,11 +1852,12 @@ static BOOL mpeg_splitter_filter_init_gst(struct parser *filter)
static HRESULT mpeg_splitter_source_query_accept(struct parser_source *pin, const AM_MEDIA_TYPE *mt) { - struct wg_parser_stream *stream = pin->wg_stream; + struct wg_format format; AM_MEDIA_TYPE pad_mt; HRESULT hr;
- if (!amt_from_wg_format(&pad_mt, &stream->preferred_format)) + unix_funcs->wg_parser_stream_get_preferred_format(pin->wg_stream, &format); + if (!amt_from_wg_format(&pad_mt, &format)) return E_OUTOFMEMORY; hr = compare_media_types(mt, &pad_mt) ? S_OK : S_FALSE; FreeMediaType(&pad_mt); @@ -1861,11 +1867,12 @@ static HRESULT mpeg_splitter_source_query_accept(struct parser_source *pin, cons static HRESULT mpeg_splitter_source_get_media_type(struct parser_source *pin, unsigned int index, AM_MEDIA_TYPE *mt) { - struct wg_parser_stream *stream = pin->wg_stream; + struct wg_format format;
if (index > 0) return VFW_S_NO_MORE_ITEMS; - if (!amt_from_wg_format(mt, &stream->preferred_format)) + unix_funcs->wg_parser_stream_get_preferred_format(pin->wg_stream, &format); + if (!amt_from_wg_format(mt, &format)) return E_OUTOFMEMORY; return S_OK; } diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c index 1cbe123ca2f..208abc59a9b 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c @@ -327,6 +327,11 @@ static struct wg_parser_stream * CDECL wg_parser_get_stream(struct wg_parser *pa return parser->streams[index]; }
+static void CDECL wg_parser_stream_get_preferred_format(struct wg_parser_stream *stream, struct wg_format *format) +{ + *format = stream->preferred_format; +} + static GstAutoplugSelectResult autoplug_blacklist(GstElement *bin, GstPad *pad, GstCaps *caps, GstElementFactory *fact, gpointer user) { const char *name = gst_element_factory_get_longname(fact); @@ -1480,6 +1485,8 @@ static const struct unix_funcs funcs =
wg_parser_get_stream_count, wg_parser_get_stream, + + wg_parser_stream_get_preferred_format, };
NTSTATUS CDECL __wine_init_unix_lib(HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out)
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/winegstreamer/gst_private.h | 2 ++ dlls/winegstreamer/gstdemux.c | 9 ++++----- dlls/winegstreamer/wg_parser.c | 14 ++++++++++++++ 3 files changed, 20 insertions(+), 5 deletions(-)
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index d95f58dc607..15c62fa29c5 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -219,6 +219,8 @@ struct unix_funcs struct wg_parser_stream *(CDECL *wg_parser_get_stream)(struct wg_parser *parser, uint32_t index);
void (CDECL *wg_parser_stream_get_preferred_format)(struct wg_parser_stream *stream, struct wg_format *format); + void (CDECL *wg_parser_stream_enable)(struct wg_parser_stream *stream, const struct wg_format *format); + void (CDECL *wg_parser_stream_disable)(struct wg_parser_stream *stream); };
extern const struct unix_funcs *unix_funcs; diff --git a/dlls/winegstreamer/gstdemux.c b/dlls/winegstreamer/gstdemux.c index 95e55a55f22..1f80a8fec8c 100644 --- a/dlls/winegstreamer/gstdemux.c +++ b/dlls/winegstreamer/gstdemux.c @@ -1507,6 +1507,7 @@ static HRESULT WINAPI GSTOutPin_DecideBufferSize(struct strmbase_source *iface, struct wg_parser_stream *stream = pin->wg_stream; unsigned int buffer_size = 16384; ALLOCATOR_PROPERTIES ret_props; + struct wg_format format; bool ret;
if (IsEqualGUID(&pin->pin.pin.mt.formattype, &FORMAT_VideoInfo)) @@ -1526,11 +1527,10 @@ static HRESULT WINAPI GSTOutPin_DecideBufferSize(struct strmbase_source *iface, buffer_size = format->nAvgBytesPerSec; }
- ret = amt_to_wg_format(&pin->pin.pin.mt, &stream->current_format); + ret = amt_to_wg_format(&pin->pin.pin.mt, &format); assert(ret); - stream->enabled = true; + unix_funcs->wg_parser_stream_enable(pin->wg_stream, &format);
- gst_pad_push_event(stream->my_sink, gst_event_new_reconfigure()); /* We do need to drop any buffers that might have been sent with the old * caps, but this will be handled in parser_init_stream(). */
@@ -1543,9 +1543,8 @@ static HRESULT WINAPI GSTOutPin_DecideBufferSize(struct strmbase_source *iface, static void source_disconnect(struct strmbase_source *iface) { struct parser_source *pin = impl_source_from_IPin(&iface->pin.IPin_iface); - struct wg_parser_stream *stream = pin->wg_stream;
- stream->enabled = false; + unix_funcs->wg_parser_stream_disable(pin->wg_stream); }
static void free_source_pin(struct parser_source *pin) diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c index 208abc59a9b..107dfdd1a7f 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c @@ -332,6 +332,18 @@ static void CDECL wg_parser_stream_get_preferred_format(struct wg_parser_stream *format = stream->preferred_format; }
+static void CDECL wg_parser_stream_enable(struct wg_parser_stream *stream, const struct wg_format *format) +{ + stream->current_format = *format; + stream->enabled = true; + gst_pad_push_event(stream->my_sink, gst_event_new_reconfigure()); +} + +static void CDECL wg_parser_stream_disable(struct wg_parser_stream *stream) +{ + stream->enabled = false; +} + static GstAutoplugSelectResult autoplug_blacklist(GstElement *bin, GstPad *pad, GstCaps *caps, GstElementFactory *fact, gpointer user) { const char *name = gst_element_factory_get_longname(fact); @@ -1487,6 +1499,8 @@ static const struct unix_funcs funcs = wg_parser_get_stream,
wg_parser_stream_get_preferred_format, + wg_parser_stream_enable, + wg_parser_stream_disable, };
NTSTATUS CDECL __wine_init_unix_lib(HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out)
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/winegstreamer/gst_private.h | 2 ++ dlls/winegstreamer/gstdemux.c | 29 +---------------------------- dlls/winegstreamer/wg_parser.c | 27 +++++++++++++++++++++++++++ 3 files changed, 30 insertions(+), 28 deletions(-)
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index 15c62fa29c5..08ff6ee21f0 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -221,6 +221,8 @@ struct unix_funcs void (CDECL *wg_parser_stream_get_preferred_format)(struct wg_parser_stream *stream, struct wg_format *format); void (CDECL *wg_parser_stream_enable)(struct wg_parser_stream *stream, const struct wg_format *format); void (CDECL *wg_parser_stream_disable)(struct wg_parser_stream *stream); + + bool (CDECL *wg_parser_stream_get_event)(struct wg_parser_stream *stream, struct wg_parser_event *event); };
extern const struct unix_funcs *unix_funcs; diff --git a/dlls/winegstreamer/gstdemux.c b/dlls/winegstreamer/gstdemux.c index 1f80a8fec8c..d4614ca5a65 100644 --- a/dlls/winegstreamer/gstdemux.c +++ b/dlls/winegstreamer/gstdemux.c @@ -686,33 +686,6 @@ static void send_buffer(struct parser_source *pin, GstBuffer *buf) gst_buffer_unref(buf); }
-static bool get_stream_event(struct parser_source *pin, struct wg_parser_event *event) -{ - struct parser *filter = impl_from_strmbase_filter(pin->pin.pin.filter); - struct wg_parser_stream *stream = pin->wg_stream; - struct wg_parser *parser = filter->wg_parser; - - pthread_mutex_lock(&parser->mutex); - - while (!parser->flushing && stream->event.type == WG_PARSER_EVENT_NONE) - pthread_cond_wait(&stream->event_cond, &parser->mutex); - - if (parser->flushing) - { - pthread_mutex_unlock(&parser->mutex); - TRACE("Filter is flushing.\n"); - return false; - } - - *event = stream->event; - stream->event.type = WG_PARSER_EVENT_NONE; - - pthread_mutex_unlock(&parser->mutex); - pthread_cond_signal(&stream->event_empty_cond); - - return true; -} - static DWORD CALLBACK stream_thread(void *arg) { struct parser_source *pin = arg; @@ -726,7 +699,7 @@ static DWORD CALLBACK stream_thread(void *arg)
EnterCriticalSection(&pin->flushing_cs);
- if (!get_stream_event(pin, &event)) + if (!unix_funcs->wg_parser_stream_get_event(pin->wg_stream, &event)) { LeaveCriticalSection(&pin->flushing_cs); continue; diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c index 107dfdd1a7f..b3f8eff43ad 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c @@ -344,6 +344,31 @@ static void CDECL wg_parser_stream_disable(struct wg_parser_stream *stream) stream->enabled = false; }
+static bool CDECL wg_parser_stream_get_event(struct wg_parser_stream *stream, struct wg_parser_event *event) +{ + struct wg_parser *parser = stream->parser; + + pthread_mutex_lock(&parser->mutex); + + while (!parser->flushing && stream->event.type == WG_PARSER_EVENT_NONE) + pthread_cond_wait(&stream->event_cond, &parser->mutex); + + if (parser->flushing) + { + pthread_mutex_unlock(&parser->mutex); + TRACE("Filter is flushing.\n"); + return false; + } + + *event = stream->event; + stream->event.type = WG_PARSER_EVENT_NONE; + + pthread_mutex_unlock(&parser->mutex); + pthread_cond_signal(&stream->event_empty_cond); + + return true; +} + static GstAutoplugSelectResult autoplug_blacklist(GstElement *bin, GstPad *pad, GstCaps *caps, GstElementFactory *fact, gpointer user) { const char *name = gst_element_factory_get_longname(fact); @@ -1501,6 +1526,8 @@ static const struct unix_funcs funcs = wg_parser_stream_get_preferred_format, wg_parser_stream_enable, wg_parser_stream_disable, + + wg_parser_stream_get_event, };
NTSTATUS CDECL __wine_init_unix_lib(HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out)
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/winegstreamer/gst_private.h | 3 +++ dlls/winegstreamer/gstdemux.c | 28 ++++------------------------ dlls/winegstreamer/wg_parser.c | 25 +++++++++++++++++++++++++ 3 files changed, 32 insertions(+), 24 deletions(-)
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index 08ff6ee21f0..ee698bdf32f 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -215,6 +215,9 @@ struct unix_funcs HRESULT (CDECL *wg_parser_connect)(struct wg_parser *parser, uint64_t file_size); void (CDECL *wg_parser_disconnect)(struct wg_parser *parser);
+ void (CDECL *wg_parser_begin_flush)(struct wg_parser *parser); + void (CDECL *wg_parser_end_flush)(struct wg_parser *parser); + uint32_t (CDECL *wg_parser_get_stream_count)(struct wg_parser *parser); struct wg_parser_stream *(CDECL *wg_parser_get_stream)(struct wg_parser *parser, uint32_t index);
diff --git a/dlls/winegstreamer/gstdemux.c b/dlls/winegstreamer/gstdemux.c index d4614ca5a65..63368febc5c 100644 --- a/dlls/winegstreamer/gstdemux.c +++ b/dlls/winegstreamer/gstdemux.c @@ -856,9 +856,7 @@ static HRESULT parser_init_stream(struct strmbase_filter *iface) return S_OK;
filter->streaming = true; - pthread_mutex_lock(&parser->mutex); - parser->flushing = false; - pthread_mutex_unlock(&parser->mutex); + unix_funcs->wg_parser_end_flush(filter->wg_parser);
/* DirectShow retains the old seek positions, but resets to them every time * it transitions from stopped -> paused. */ @@ -899,17 +897,7 @@ static HRESULT parser_cleanup_stream(struct strmbase_filter *iface) return S_OK;
filter->streaming = false; - pthread_mutex_lock(&parser->mutex); - parser->flushing = true; - pthread_mutex_unlock(&parser->mutex); - - for (i = 0; i < parser->stream_count; ++i) - { - struct wg_parser_stream *stream = parser->streams[i]; - - if (stream->enabled) - pthread_cond_signal(&stream->event_cond); - } + unix_funcs->wg_parser_begin_flush(filter->wg_parser);
for (i = 0; i < filter->source_count; ++i) { @@ -1228,7 +1216,6 @@ static HRESULT WINAPI GST_Seeking_SetPositions(IMediaSeeking *iface, struct parser_source *pin = impl_from_IMediaSeeking(iface); struct wg_parser_stream *stream = pin->wg_stream; struct parser *filter = impl_from_strmbase_filter(pin->pin.pin.filter); - struct wg_parser *parser = filter->wg_parser; GstSeekFlags flags = 0; HRESULT hr = S_OK; int i; @@ -1247,17 +1234,12 @@ static HRESULT WINAPI GST_Seeking_SetPositions(IMediaSeeking *iface,
if (!(current_flags & AM_SEEKING_NoFlush)) { - pthread_mutex_lock(&parser->mutex); - parser->flushing = true; - pthread_mutex_unlock(&parser->mutex); + unix_funcs->wg_parser_begin_flush(filter->wg_parser);
for (i = 0; i < filter->source_count; ++i) { if (filter->sources[i]->pin.pin.peer) - { - pthread_cond_signal(&stream->event_cond); IPin_BeginFlush(filter->sources[i]->pin.pin.peer); - } }
if (filter->reader) @@ -1296,9 +1278,7 @@ static HRESULT WINAPI GST_Seeking_SetPositions(IMediaSeeking *iface,
if (!(current_flags & AM_SEEKING_NoFlush)) { - pthread_mutex_lock(&parser->mutex); - parser->flushing = false; - pthread_mutex_unlock(&parser->mutex); + unix_funcs->wg_parser_end_flush(filter->wg_parser);
for (i = 0; i < filter->source_count; ++i) { diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c index b3f8eff43ad..bb1d6188a8b 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c @@ -327,6 +327,28 @@ static struct wg_parser_stream * CDECL wg_parser_get_stream(struct wg_parser *pa return parser->streams[index]; }
+static void CDECL wg_parser_begin_flush(struct wg_parser *parser) +{ + unsigned int i; + + pthread_mutex_lock(&parser->mutex); + parser->flushing = true; + pthread_mutex_unlock(&parser->mutex); + + for (i = 0; i < parser->stream_count; ++i) + { + if (parser->streams[i]->enabled) + pthread_cond_signal(&parser->streams[i]->event_cond); + } +} + +static void CDECL wg_parser_end_flush(struct wg_parser *parser) +{ + pthread_mutex_lock(&parser->mutex); + parser->flushing = false; + pthread_mutex_unlock(&parser->mutex); +} + static void CDECL wg_parser_stream_get_preferred_format(struct wg_parser_stream *stream, struct wg_format *format) { *format = stream->preferred_format; @@ -1520,6 +1542,9 @@ static const struct unix_funcs funcs = wg_parser_connect, wg_parser_disconnect,
+ wg_parser_begin_flush, + wg_parser_end_flush, + wg_parser_get_stream_count, wg_parser_get_stream,
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/winegstreamer/gst_private.h | 2 ++ dlls/winegstreamer/gstdemux.c | 28 ++++++++++------------------ dlls/winegstreamer/wg_parser.c | 12 ++++++++++++ 3 files changed, 24 insertions(+), 18 deletions(-)
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index ee698bdf32f..3c6d1147477 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -226,6 +226,8 @@ struct unix_funcs void (CDECL *wg_parser_stream_disable)(struct wg_parser_stream *stream);
bool (CDECL *wg_parser_stream_get_event)(struct wg_parser_stream *stream, struct wg_parser_event *event); + void (CDECL *wg_parser_stream_notify_qos)(struct wg_parser_stream *stream, + bool underflow, double proportion, int64_t diff, uint64_t timestamp); };
extern const struct unix_funcs *unix_funcs; diff --git a/dlls/winegstreamer/gstdemux.c b/dlls/winegstreamer/gstdemux.c index 63368febc5c..da294c31e01 100644 --- a/dlls/winegstreamer/gstdemux.c +++ b/dlls/winegstreamer/gstdemux.c @@ -1350,11 +1350,8 @@ static ULONG WINAPI GST_QualityControl_Release(IQualityControl *iface) static HRESULT WINAPI GST_QualityControl_Notify(IQualityControl *iface, IBaseFilter *sender, Quality q) { struct parser_source *pin = impl_from_IQualityControl(iface); - struct wg_parser_stream *stream = pin->wg_stream; - GstQOSType type = GST_QOS_TYPE_OVERFLOW; - GstClockTime timestamp; - GstClockTimeDiff diff; - GstEvent *event; + uint64_t timestamp; + int64_t diff;
TRACE("pin %p, sender %p, type %s, proportion %u, late %s, timestamp %s.\n", pin, sender, q.Type == Famine ? "Famine" : "Flood", q.Proportion, @@ -1362,20 +1359,14 @@ static HRESULT WINAPI GST_QualityControl_Notify(IQualityControl *iface, IBaseFil
mark_wine_thread();
- /* GST_QOS_TYPE_OVERFLOW is also used for buffers that arrive on time, but - * DirectShow filters might use Famine, so check that there actually is an - * underrun. */ - if (q.Type == Famine && q.Proportion < 1000) - type = GST_QOS_TYPE_UNDERFLOW; - /* DirectShow filters sometimes pass negative timestamps (Audiosurf uses the * current time instead of the time of the last buffer). GstClockTime is * unsigned, so clamp it to 0. */ - timestamp = max(q.TimeStamp * 100, 0); + timestamp = max(q.TimeStamp, 0);
/* The documentation specifies that timestamp + diff must be nonnegative. */ - diff = q.Late * 100; - if (diff < 0 && timestamp < (GstClockTime)-diff) + diff = q.Late; + if (diff < 0 && timestamp < (uint64_t)-diff) diff = -timestamp;
/* DirectShow "Proportion" describes what percentage of buffers the upstream @@ -1395,10 +1386,11 @@ static HRESULT WINAPI GST_QualityControl_Notify(IQualityControl *iface, IBaseFil return S_OK; }
- if (!(event = gst_event_new_qos(type, 1000.0 / q.Proportion, diff, timestamp))) - ERR("Failed to create QOS event.\n"); - - gst_pad_push_event(stream->my_sink, event); + /* GST_QOS_TYPE_OVERFLOW is also used for buffers that arrive on time, but + * DirectShow filters might use Famine, so check that there actually is an + * underrun. */ + unix_funcs->wg_parser_stream_notify_qos(pin->wg_stream, q.Type == Famine && q.Proportion < 1000, + 1000.0 / q.Proportion, diff, timestamp);
return S_OK; } diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c index bb1d6188a8b..79fa45eadca 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c @@ -391,6 +391,17 @@ static bool CDECL wg_parser_stream_get_event(struct wg_parser_stream *stream, st return true; }
+static void CDECL wg_parser_stream_notify_qos(struct wg_parser_stream *stream, + bool underflow, double proportion, int64_t diff, uint64_t timestamp) +{ + GstEvent *event; + + if (!(event = gst_event_new_qos(underflow ? GST_QOS_TYPE_UNDERFLOW : GST_QOS_TYPE_OVERFLOW, + 1000.0 / proportion, diff * 100, timestamp * 100))) + ERR("Failed to create QOS event.\n"); + gst_pad_push_event(stream->my_sink, event); +} + static GstAutoplugSelectResult autoplug_blacklist(GstElement *bin, GstPad *pad, GstCaps *caps, GstElementFactory *fact, gpointer user) { const char *name = gst_element_factory_get_longname(fact); @@ -1553,6 +1564,7 @@ static const struct unix_funcs funcs = wg_parser_stream_disable,
wg_parser_stream_get_event, + wg_parser_stream_notify_qos, };
NTSTATUS CDECL __wine_init_unix_lib(HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out)