From: Zebediah Figura Subject: [PATCH 2/2] winegstreamer: Convert timestamps to running time in wg_parser_stream_notify_qos(). Message-Id: <20210316210632.18047-2-z.figura12@gmail.com> Date: Tue, 16 Mar 2021 16:06:32 -0500 In-Reply-To: <20210316210632.18047-1-z.figura12@gmail.com> References: <20210316210632.18047-1-z.figura12@gmail.com> Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50733 Signed-off-by: Zebediah Figura --- dlls/winegstreamer/wg_parser.c | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c index 801fc096302..cfcce2e1de1 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c @@ -79,6 +79,7 @@ struct wg_parser_stream GstPad *their_src, *post_sink, *post_src, *my_sink; GstElement *flip; + GstSegment segment; struct wg_format preferred_format, current_format; pthread_cond_t event_cond, event_empty_cond; @@ -691,10 +692,24 @@ static bool CDECL wg_parser_stream_seek(struct wg_parser_stream *stream, double static void CDECL wg_parser_stream_notify_qos(struct wg_parser_stream *stream, bool underflow, double proportion, int64_t diff, uint64_t timestamp) { + GstClockTime stream_time; GstEvent *event; + /* We return timestamps in stream time, i.e. relative to the start of the + * file (or other medium), but gst_event_new_qos() expects the timestamp in + * running time. */ + stream_time = gst_segment_to_running_time(&stream->segment, GST_FORMAT_TIME, timestamp * 100); + if (stream_time == -1) + { + /* This can happen legitimately if the sample falls outside of the + * segment bounds. GStreamer elements shouldn't present the sample in + * that case, but DirectShow doesn't care. */ + TRACE("Ignoring QoS event.\n"); + return; + } + if (!(event = gst_event_new_qos(underflow ? GST_QOS_TYPE_UNDERFLOW : GST_QOS_TYPE_OVERFLOW, - proportion, diff * 100, timestamp * 100))) + proportion, diff * 100, stream_time))) ERR("Failed to create QOS event.\n"); gst_pad_push_event(stream->my_sink, event); } @@ -792,6 +807,8 @@ static gboolean sink_event_cb(GstPad *pad, GstObject *parent, GstEvent *event) break; } + gst_segment_copy_into(segment, &stream->segment); + stream_event.type = WG_PARSER_EVENT_SEGMENT; stream_event.u.segment.position = segment->position / 100; stream_event.u.segment.stop = segment->stop / 100; @@ -838,6 +855,14 @@ static gboolean sink_event_cb(GstPad *pad, GstObject *parent, GstEvent *event) break; case GST_EVENT_FLUSH_STOP: + { + gboolean reset_time; + + gst_event_parse_flush_stop(event, &reset_time); + + if (reset_time) + gst_segment_init(&stream->segment, GST_FORMAT_UNDEFINED); + if (stream->enabled) { pthread_mutex_lock(&parser->mutex); @@ -845,6 +870,7 @@ static gboolean sink_event_cb(GstPad *pad, GstObject *parent, GstEvent *event) pthread_mutex_unlock(&parser->mutex); } break; + } case GST_EVENT_CAPS: { @@ -882,6 +908,10 @@ static GstFlowReturn sink_chain_cb(GstPad *pad, GstObject *parent, GstBuffer *bu stream_event.type = WG_PARSER_EVENT_BUFFER; + /* FIXME: Should we use gst_segment_to_stream_time_full()? Under what + * circumstances is the stream time not equal to the buffer PTS? Note that + * this will need modification to wg_parser_stream_notify_qos() as well. */ + if ((stream_event.u.buffer.has_pts = GST_BUFFER_PTS_IS_VALID(buffer))) stream_event.u.buffer.pts = GST_BUFFER_PTS(buffer) / 100; if ((stream_event.u.buffer.has_duration = GST_BUFFER_DURATION_IS_VALID(buffer))) @@ -972,6 +1002,8 @@ static struct wg_parser_stream *create_stream(struct wg_parser *parser) if (!(stream = calloc(1, sizeof(*stream)))) return NULL; + gst_segment_init(&stream->segment, GST_FORMAT_UNDEFINED); + stream->parser = parser; pthread_cond_init(&stream->event_cond, NULL); pthread_cond_init(&stream->event_empty_cond, NULL); -- 2.20.1