[PATCH v2 4/6] winegstreamer: Move fetching of stream duration to the designated function.
Derek Lesho
dlesho at codeweavers.com
Fri Sep 17 14:58:56 CDT 2021
In push mode parsers, we won't want to retrieve the duration.
Signed-off-by: Derek Lesho <dlesho at codeweavers.com>
---
dlls/winegstreamer/wg_parser.c | 145 +++++++++++++++++++--------------
1 file changed, 86 insertions(+), 59 deletions(-)
diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c
index 98b7491998b..f751463a548 100644
--- a/dlls/winegstreamer/wg_parser.c
+++ b/dlls/winegstreamer/wg_parser.c
@@ -503,70 +503,14 @@ static bool wg_parser_initialize(struct wg_parser *parser)
for (i = 0; i < parser->stream_count; ++i)
{
struct wg_parser_stream *stream = parser->streams[i];
- gint64 duration;
while (!stream->has_caps && !parser->error)
pthread_cond_wait(&parser->state_cond, &parser->mutex);
- /* GStreamer doesn't actually provide any guarantees about when duration
- * is available, even for seekable streams. It's basically built for
- * applications that don't care, e.g. movie players that can display
- * a duration once it's available, and update it visually if a better
- * estimate is found. This doesn't really match well with DirectShow or
- * Media Foundation, which both expect duration to be available
- * immediately on connecting, so we have to use some complex heuristics
- * to try to actually get a usable duration.
- *
- * Some elements (avidemux, wavparse, qtdemux) record duration almost
- * immediately, before fixing caps. Such elements don't send
- * duration-changed messages. Therefore always try querying duration
- * after caps have been found.
- *
- * Some elements (mpegaudioparse) send duration-changed. In the case of
- * a mp3 stream without seek tables it will not be sent immediately, but
- * only after enough frames have been parsed to form an estimate. They
- * may send it multiple times with increasingly accurate estimates, but
- * unfortunately we have no way of knowing whether another estimate will
- * be sent, so we always take the first one. We assume that if the
- * duration is not immediately available then the element will always
- * send duration-changed.
- */
-
- for (;;)
+ if (parser->error)
{
- if (parser->error)
- {
- pthread_mutex_unlock(&parser->mutex);
- return 0;
- }
- if (gst_pad_query_duration(stream->their_src, GST_FORMAT_TIME, &duration))
- {
- stream->duration = duration / 100;
- break;
- }
-
- if (stream->eos)
- {
- stream->duration = 0;
- GST_WARNING("Failed to query duration.\n");
- break;
- }
-
- /* Elements based on GstBaseParse send duration-changed before
- * actually updating the duration in GStreamer versions prior
- * to 1.17.1. See <gstreamer.git:d28e0b4147fe7073b2>. So after
- * receiving duration-changed we have to continue polling until
- * the query succeeds. */
- if (parser->has_duration)
- {
- pthread_mutex_unlock(&parser->mutex);
- g_usleep(10000);
- pthread_mutex_lock(&parser->mutex);
- }
- else
- {
- pthread_cond_wait(&parser->state_cond, &parser->mutex);
- }
+ pthread_mutex_unlock(&parser->mutex);
+ return 0;
}
}
@@ -812,6 +756,87 @@ static void CDECL wg_parser_stream_release_buffer(struct wg_parser_stream *strea
static uint64_t CDECL wg_parser_stream_get_duration(struct wg_parser_stream *stream)
{
+ struct wg_parser *parser = stream->parser;
+ gint64 duration;
+
+ pthread_mutex_lock(&parser->mutex);
+
+ if (stream->duration != UINT64_MAX)
+ {
+ pthread_mutex_unlock(&parser->mutex);
+ return stream->duration;
+ }
+
+ if (!parser->flushing)
+ {
+ GST_WARNING("Parser must be flushing to retrieve duration.\n");
+ pthread_mutex_unlock(&parser->mutex);
+ return UINT64_MAX;
+ }
+
+ /* GStreamer doesn't actually provide any guarantees about when duration
+ * is available, even for seekable streams. It's basically built for
+ * applications that don't care, e.g. movie players that can display
+ * a duration once it's available, and update it visually if a better
+ * estimate is found. This doesn't really match well with DirectShow or
+ * Media Foundation, which both expect duration to be available
+ * immediately on connecting, so we have to use some complex heuristics
+ * to try to actually get a usable duration.
+ *
+ * Some elements (avidemux, wavparse, qtdemux) record duration almost
+ * immediately, before fixing caps. Such elements don't send
+ * duration-changed messages. Therefore always try querying duration
+ * after caps have been found.
+ *
+ * Some elements (mpegaudioparse) send duration-changed. In the case of
+ * a mp3 stream without seek tables it will not be sent immediately, but
+ * only after enough frames have been parsed to form an estimate. They
+ * may send it multiple times with increasingly accurate estimates, but
+ * unfortunately we have no way of knowing whether another estimate will
+ * be sent, so we always take the first one. We assume that if the
+ * duration is not immediately available then the element will always
+ * send duration-changed.
+ */
+
+ for (;;)
+ {
+ if (parser->error)
+ {
+ pthread_mutex_unlock(&parser->mutex);
+ return 0;
+ }
+ if (gst_pad_query_duration(stream->their_src, GST_FORMAT_TIME, &duration))
+ {
+ stream->duration = duration / 100;
+ break;
+ }
+
+ if (stream->eos)
+ {
+ stream->duration = 0;
+ GST_WARNING("Failed to query duration.\n");
+ break;
+ }
+
+ /* Elements based on GstBaseParse send duration-changed before
+ * actually updating the duration in GStreamer versions prior
+ * to 1.17.1. See <gstreamer.git:d28e0b4147fe7073b2>. So after
+ * receiving duration-changed we have to continue polling until
+ * the query succeeds. */
+ if (parser->has_duration)
+ {
+ pthread_mutex_unlock(&parser->mutex);
+ g_usleep(10000);
+ pthread_mutex_lock(&parser->mutex);
+ }
+ else
+ {
+ pthread_cond_wait(&parser->state_cond, &parser->mutex);
+ }
+ }
+
+ pthread_mutex_unlock(&parser->mutex);
+
return stream->duration;
}
@@ -1173,6 +1198,8 @@ static struct wg_parser_stream *create_stream(struct wg_parser *parser)
gst_pad_set_event_function(stream->my_sink, sink_event_cb);
gst_pad_set_query_function(stream->my_sink, sink_query_cb);
+ stream->duration = UINT64_MAX;
+
parser->streams[parser->stream_count++] = stream;
return stream;
}
--
2.33.0
More information about the wine-devel
mailing list