From 24c0dc96021b04d6def4685706b585822bf87b7f Mon Sep 17 00:00:00 2001 From: Edward Hervey Date: Wed, 10 Apr 2024 07:22:36 +0200 Subject: [PATCH] parsebin: Ensure non-time subtitle streams get "parsed" Since https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6153 , subtitle "decoders" (i.e. which decode to raw text) are no longer auto-plugged by parsebin. But if a given format does not have a parser at all, we would end up outputting non-time/non-parsed outputs. In order to mitigate the issue, until such parsers are available, we check if the subtitle stream is in TIME format or not (i.e. whether it comes from a parser or demuxer). If not, we attempt to plug in a subtitle "decoder". Fixes #3463 Part-of: --- .../gst/playback/gstparsebin.c | 37 ++++++++++++++++++- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/subprojects/gst-plugins-base/gst/playback/gstparsebin.c b/subprojects/gst-plugins-base/gst/playback/gstparsebin.c index defacb665f..57c539fc78 100644 --- a/subprojects/gst-plugins-base/gst/playback/gstparsebin.c +++ b/subprojects/gst-plugins-base/gst/playback/gstparsebin.c @@ -1765,10 +1765,41 @@ connect_pad (GstParseBin * parsebin, GstElement * src, GstParsePad * parsepad, { gboolean res = FALSE; GString *error_details = NULL; + GstFormat segment_format = GST_FORMAT_TIME; + GstPbUtilsCapsDescriptionFlags caps_flags = + gst_pb_utils_get_caps_description_flags (caps); g_return_val_if_fail (factories != NULL, FALSE); g_return_val_if_fail (factories->n_values > 0, FALSE); + /* For subtitles, which can come from standalone files, we need to ensure we + * output a timed/parsed stream. But not all formats have a parser, so we also + * want to try plugging in subtitle "decoders" like `subparse`. + * + * In order to ensure that, if the caps are subtitles, we query the stream + * format to check if it's in time or not. If it's not in time format, we will + * attempt to plugin in a "decoder" (if present). */ + if (caps_flags == GST_PBUTILS_CAPS_DESCRIPTION_FLAG_SUBTITLE) { + GstEvent *segment_event = + gst_pad_get_sticky_event (pad, GST_EVENT_SEGMENT, 0); + const GstSegment *segment = NULL; + + segment_format = GST_FORMAT_UNDEFINED; + if (segment_event) { + gst_event_parse_segment (segment_event, &segment); + if (segment) + segment_format = segment->format; + } + if (segment == GST_FORMAT_UNDEFINED) { + GstQuery *segment_query = gst_query_new_segment (GST_FORMAT_TIME); + if (gst_pad_query (pad, segment_query)) { + gst_query_parse_segment (segment_query, NULL, &segment_format, NULL, + NULL); + } + gst_query_unref (segment_query); + } + } + GST_DEBUG_OBJECT (parsebin, "pad %s:%s , chain:%p, %d factories, caps %" GST_PTR_FORMAT, GST_DEBUG_PAD_NAME (pad), chain, factories->n_values, caps); @@ -1888,9 +1919,11 @@ connect_pad (GstParseBin * parsebin, GstElement * src, GstParsePad * parsepad, } - /* Expose pads if the next factory is a decoder */ + /* Expose pads if the next factory is a decoder. segment_format might be not + * time for subtitle streams */ if (gst_element_factory_list_is_type (factory, - GST_ELEMENT_FACTORY_TYPE_DECODER)) { + GST_ELEMENT_FACTORY_TYPE_DECODER) + && segment_format == GST_FORMAT_TIME) { ret = GST_AUTOPLUG_SELECT_EXPOSE; } else { /* emit autoplug-select to see what we should do with it. */