For mp3 audio streams, continuously call gst_pad_query_duration until the duration arrives. Fixes issue of incorrect song duration in Fallout: New Vegas.
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/winegstreamer/wg_parser.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-)
diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c index 1653701506c..1dae3bfb922 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c @@ -1504,13 +1504,22 @@ static gboolean src_event_cb(GstPad *pad, GstObject *parent, GstEvent *event) return ret; }
-static LONGLONG query_duration(GstPad *pad) +static LONGLONG query_duration(GstPad *pad, gboolean query_duration) { gint64 duration, byte_length;
if (gst_pad_query_duration(pad, GST_FORMAT_TIME, &duration)) return duration / 100;
+ if (query_duration) + { + for (;;) + { + if (gst_pad_query_duration(pad, GST_FORMAT_TIME, &duration)) + return duration / 100; + } + } + WARN("Failed to query time duration; trying to convert from byte length.\n");
/* To accurately get a duration for the stream, we want to only consider the @@ -1569,6 +1578,7 @@ static HRESULT CDECL wg_parser_connect(struct wg_parser *parser, uint64_t file_s for (i = 0; i < parser->stream_count; ++i) { struct wg_parser_stream *stream = parser->streams[i]; + gboolean duration_wait = FALSE;
while (!stream->has_caps && !parser->error) pthread_cond_wait(&parser->init_cond, &parser->mutex); @@ -1577,12 +1587,25 @@ static HRESULT CDECL wg_parser_connect(struct wg_parser *parser, uint64_t file_s pthread_mutex_unlock(&parser->mutex); return E_FAIL; } + + /* + * On MP3 audio streams, sometimes the duration value takes time to be + * set. In this case, we need to continuously call query_duration + * until we get it. + */ + if (input_format.major_type == WG_MAJOR_TYPE_AUDIO && + input_format.u.audio.format >= WG_AUDIO_FORMAT_MPEG1_LAYER1 && + input_format.u.audio.format <= WG_AUDIO_FORMAT_MPEG1_LAYER3) + { + duration_wait = TRUE; + } + /* GStreamer doesn't actually provide any guarantees about when duration * is available, even for seekable streams. However, many elements (e.g. * avidemux, wavparse, qtdemux) in practice record duration before * fixing caps, so as a heuristic, wait until we get caps before trying * to query for duration. */ - stream->duration = query_duration(stream->their_src); + stream->duration = query_duration(stream->their_src, duration_wait); }
pthread_mutex_unlock(&parser->mutex);