uri-source: Respect stream-id even on streams muxed in raw

The issue is that we rely on `decodebin::autoplug-select` to `SKIP`
unwanted pads, that signal was first provided to select factories during
autoplugin, not totally thought to avoid exposing pads. For streams
muxed directly in raw, decodebin has nothing to plug after the demuxer
and the pad is exposed right away, meaning that we do not have any
chance to avoid that pad to be exposed. This patch takes that limitation
into account and checks the stream ID of the pads exposed by decodebin
before exposing them itself, so we end up using the right pad even if
more are uselessly exposed by decodebin.

Fixes https://gitlab.freedesktop.org/gstreamer/gst-editing-services/-/issues/126

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-editing-services/-/merge_requests/222>
This commit is contained in:
Thibault Saunier 2020-12-13 22:54:37 -03:00 committed by GStreamer Merge Bot
parent 8e9e95b90a
commit 0d95d9258b
6 changed files with 77 additions and 14 deletions

View file

@ -136,7 +136,8 @@ ges_audio_uri_source_class_init (GESAudioUriSourceClass * klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GESTimelineElementClass *element_class = GES_TIMELINE_ELEMENT_CLASS (klass);
GESAudioSourceClass *source_class = GES_AUDIO_SOURCE_CLASS (klass);
GESSourceClass *src_class = GES_SOURCE_CLASS (klass);
GESAudioSourceClass *audio_src_class = GES_AUDIO_SOURCE_CLASS (klass);
object_class->get_property = ges_audio_uri_source_get_property;
object_class->set_property = ges_audio_uri_source_set_property;
@ -153,7 +154,8 @@ ges_audio_uri_source_class_init (GESAudioUriSourceClass * klass)
element_class->get_natural_framerate = _get_natural_framerate;
source_class->create_source = ges_audio_uri_source_create_source;
src_class->select_pad = ges_uri_source_select_pad;
audio_src_class->create_source = ges_audio_uri_source_create_source;
}
static void

View file

@ -82,8 +82,15 @@ _set_ghost_pad_target (GESSource * self, GstPad * srcpad, GstElement * element)
{
GstPadLinkReturn link_return;
GESSourcePrivate *priv = self->priv;
GESSourceClass *source_klass = GES_SOURCE_GET_CLASS (self);
gboolean use_converter = ! !priv->first_converter;
if (source_klass->select_pad && !source_klass->select_pad (self, srcpad)) {
GST_INFO_OBJECT (self, "Ignoring pad %" GST_PTR_FORMAT, srcpad);
return;
}
if (use_converter && priv->is_rendering_smartly) {
GstPad *pad = gst_element_get_static_pad (priv->first_converter, "sink");
use_converter = gst_pad_can_link (srcpad, pad);

View file

@ -55,9 +55,21 @@ struct _GESSourceClass {
/*< private >*/
GESTrackElementClass parent_class;
/*< private >*/
/**
* GESSourceClass::select_pad:
* @source: The @source for which to check if @pad should be used or not
* @pad: The pad to check
*
* Check whether @pad should be exposed/used.
*
* Returns: %TRUE if @pad should be used %FALSE otherwise.
*
* Since: 1.20
*/
gboolean (*select_pad)(GESSource *source, GstPad *pad);
/* Padding for API extension */
gpointer _ges_reserved[GES_PADDING];
gpointer _ges_reserved[GES_PADDING - 1];
};
G_END_DECLS

View file

@ -71,13 +71,17 @@ autoplug_select_cb (GstElement * bin, GstPad * pad, GstCaps * caps,
(ges_extractable_get_asset (GES_EXTRACTABLE (self->element)))));
gboolean wanted = !g_strcmp0 (stream_id, wanted_id);
if (!ges_source_get_rendering_smartly (GES_SOURCE (self->element))) {
if (!wanted && are_raw_caps (caps)) {
GST_DEBUG_OBJECT (self->element, "Totally skipping %s", stream_id);
if (!are_raw_caps (caps))
goto done;
if (!wanted) {
GST_INFO_OBJECT (self->element, "Not matching stream id: %s -> SKIPPING",
stream_id);
res = GST_AUTOPLUG_SELECT_SKIP;
} else {
GST_INFO_OBJECT (self->element, "Using stream %s", stream_id);
}
GST_LOG_OBJECT (self->element, "Not being smart here");
goto done;
}
@ -183,3 +187,37 @@ ges_uri_source_init (GESTrackElement * element, GESUriSource * self)
g_signal_connect (element, "notify::track",
G_CALLBACK (ges_uri_source_track_set_cb), self);
}
gboolean
ges_uri_source_select_pad (GESSource * self, GstPad * pad)
{
gboolean res = TRUE;
gboolean is_nested_timeline;
GESUriSourceAsset *asset =
GES_URI_SOURCE_ASSET (ges_extractable_get_asset (GES_EXTRACTABLE (self)));
const GESUriClipAsset *clip_asset =
ges_uri_source_asset_get_filesource_asset (asset);
const gchar *wanted_stream_id = ges_asset_get_id (GES_ASSET (asset));
gchar *stream_id;
if (clip_asset) {
g_object_get (G_OBJECT (clip_asset), "is-nested-timeline",
&is_nested_timeline, NULL);
if (is_nested_timeline) {
GST_DEBUG_OBJECT (self, "Nested timeline track selection is handled"
" by the timeline SELECT_STREAM events handling.");
return TRUE;
}
}
stream_id = gst_pad_get_stream_id (pad);
res = !g_strcmp0 (stream_id, wanted_stream_id);
GST_INFO_OBJECT (self, "%s pad with stream id: %s as %s wanted",
res ? "Using" : "Ignoring", stream_id, wanted_stream_id);
g_free (stream_id);
return res;
}

View file

@ -35,6 +35,7 @@ struct _GESUriSource
GESTrackElement *element;
};
G_GNUC_INTERNAL gboolean ges_uri_source_select_pad (GESSource *self, GstPad *pad);
G_GNUC_INTERNAL GstElement *ges_uri_source_create_source (GESUriSource *self);
G_GNUC_INTERNAL void ges_uri_source_init (GESTrackElement *element, GESUriSource *self);

View file

@ -297,7 +297,8 @@ static void
ges_video_uri_source_class_init (GESVideoUriSourceClass * klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GESVideoSourceClass *source_class = GES_VIDEO_SOURCE_CLASS (klass);
GESSourceClass *src_class = GES_SOURCE_CLASS (klass);
GESVideoSourceClass *video_src_class = GES_VIDEO_SOURCE_CLASS (klass);
object_class->get_property = ges_video_uri_source_get_property;
object_class->set_property = ges_video_uri_source_set_property;
@ -312,12 +313,14 @@ ges_video_uri_source_class_init (GESVideoUriSourceClass * klass)
g_param_spec_string ("uri", "URI", "uri of the resource",
NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
source_class->create_source = ges_video_uri_source_create_source;
source_class->ABI.abi.needs_converters =
src_class->select_pad = ges_uri_source_select_pad;
video_src_class->create_source = ges_video_uri_source_create_source;
video_src_class->ABI.abi.needs_converters =
ges_video_uri_source_needs_converters;
source_class->ABI.abi.get_natural_size =
video_src_class->ABI.abi.get_natural_size =
ges_video_uri_source_get_natural_size;
source_class->ABI.abi.create_filters = ges_video_uri_source_create_filters;
video_src_class->ABI.abi.create_filters = ges_video_uri_source_create_filters;
}
static void