1 /* GStreamer Editing Services
2 * Copyright (C) 2020 Ubicast S.A
3 * Author: Thibault Saunier <tsaunier@igalia.com>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
25 #include "ges-internal.h"
26 #include "ges-uri-source.h"
28 GST_DEBUG_CATEGORY_STATIC (uri_source_debug);
29 #undef GST_CAT_DEFAULT
30 #define GST_CAT_DEFAULT uri_source_debug
32 #define DEFAULT_RAW_CAPS \
36 "subpicture/x-dvd; " \
39 static GstStaticCaps default_raw_caps = GST_STATIC_CAPS (DEFAULT_RAW_CAPS);
41 static inline gboolean
42 are_raw_caps (const GstCaps * caps)
44 GstCaps *raw = gst_static_caps_get (&default_raw_caps);
45 gboolean res = gst_caps_can_intersect (caps, raw);
53 GST_AUTOPLUG_SELECT_TRY,
54 GST_AUTOPLUG_SELECT_EXPOSE,
55 GST_AUTOPLUG_SELECT_SKIP,
56 } GstAutoplugSelectResult;
59 autoplug_select_cb (GstElement * bin, GstPad * pad, GstCaps * caps,
60 GstElementFactory * factory, GESUriSource * self)
63 GstCaps *downstream_caps;
64 GstQuery *segment_query = NULL;
65 GstFormat segment_format;
66 GstAutoplugSelectResult res = GST_AUTOPLUG_SELECT_TRY;
67 gchar *stream_id = gst_pad_get_stream_id (pad);
68 const gchar *wanted_id =
69 gst_discoverer_stream_info_get_stream_id
70 (ges_uri_source_asset_get_stream_info (GES_URI_SOURCE_ASSET
71 (ges_extractable_get_asset (GES_EXTRACTABLE (self->element)))));
72 gboolean wanted = !g_strcmp0 (stream_id, wanted_id);
74 if (!ges_source_get_rendering_smartly (GES_SOURCE (self->element))) {
75 if (!are_raw_caps (caps))
79 GST_INFO_OBJECT (self->element, "Not matching stream id: %s -> SKIPPING",
81 res = GST_AUTOPLUG_SELECT_SKIP;
83 GST_INFO_OBJECT (self->element, "Using stream %s", stream_id);
88 segment_query = gst_query_new_segment (GST_FORMAT_TIME);
89 if (!gst_pad_query (pad, segment_query)) {
90 GST_DEBUG_OBJECT (pad, "Could not query segment");
95 gst_query_parse_segment (segment_query, NULL, &segment_format, NULL, NULL);
96 if (segment_format != GST_FORMAT_TIME) {
97 GST_DEBUG_OBJECT (pad,
98 "Segment not in %s != time for %" GST_PTR_FORMAT
99 "... continue plugin elements", gst_format_get_name (segment_format),
105 nlesrc = ges_track_element_get_nleobject (self->element);
106 downstream_caps = gst_pad_peer_query_caps (nlesrc->srcpads->data, NULL);
107 if (downstream_caps && gst_caps_can_intersect (downstream_caps, caps)) {
109 res = GST_AUTOPLUG_SELECT_EXPOSE;
110 GST_INFO_OBJECT (self, "Exposing %" GST_PTR_FORMAT " with stream id: %s",
113 res = GST_AUTOPLUG_SELECT_SKIP;
114 GST_DEBUG_OBJECT (self->element, "Totally skipping %s", stream_id);
117 gst_clear_caps (&downstream_caps);
121 gst_clear_query (&segment_query);
127 ges_uri_source_create_source (GESUriSource * self)
130 GstElement *decodebin;
131 const GstCaps *caps = NULL;
133 track = ges_track_element_get_track (self->element);
135 self->decodebin = decodebin = gst_element_factory_make ("uridecodebin", NULL);
136 GST_DEBUG_OBJECT (self->element,
137 "%" GST_PTR_FORMAT " - Track! %" GST_PTR_FORMAT, self->decodebin, track);
140 caps = ges_track_get_caps (track);
142 g_object_set (decodebin, "caps", caps,
143 "expose-all-streams", FALSE, "uri", self->uri, NULL);
144 g_signal_connect (decodebin, "autoplug-select",
145 G_CALLBACK (autoplug_select_cb), self);
152 ges_uri_source_track_set_cb (GESTrackElement * element,
153 GParamSpec * arg G_GNUC_UNUSED, GESUriSource * self)
156 const GstCaps *caps = NULL;
158 if (!self->decodebin)
161 track = ges_track_element_get_track (GES_TRACK_ELEMENT (element));
165 caps = ges_track_get_caps (track);
167 GST_INFO_OBJECT (element,
168 "Setting %" GST_PTR_FORMAT "caps to: %" GST_PTR_FORMAT, self->decodebin,
170 g_object_set (self->decodebin, "caps", caps, NULL);
176 ges_uri_source_init (GESTrackElement * element, GESUriSource * self)
178 static gsize once = 0;
180 if (g_once_init_enter (&once)) {
181 GST_DEBUG_CATEGORY_INIT (uri_source_debug, "gesurisource", 0,
183 g_once_init_leave (&once, 1);
186 self->element = element;
187 g_signal_connect (element, "notify::track",
188 G_CALLBACK (ges_uri_source_track_set_cb), self);
192 ges_uri_source_select_pad (GESSource * self, GstPad * pad)
195 gboolean is_nested_timeline;
196 GESUriSourceAsset *asset =
197 GES_URI_SOURCE_ASSET (ges_extractable_get_asset (GES_EXTRACTABLE (self)));
198 const GESUriClipAsset *clip_asset =
199 ges_uri_source_asset_get_filesource_asset (asset);
200 const gchar *wanted_stream_id = ges_asset_get_id (GES_ASSET (asset));
204 g_object_get (G_OBJECT (clip_asset), "is-nested-timeline",
205 &is_nested_timeline, NULL);
207 if (is_nested_timeline) {
208 GST_DEBUG_OBJECT (self, "Nested timeline track selection is handled"
209 " by the timeline SELECT_STREAM events handling.");
215 stream_id = gst_pad_get_stream_id (pad);
216 res = !g_strcmp0 (stream_id, wanted_stream_id);
218 GST_INFO_OBJECT (self, "%s pad with stream id: %s as %s wanted",
219 res ? "Using" : "Ignoring", stream_id, wanted_stream_id);