468b94b94ac0662bf005d351bdfa54b47083a1de
[platform/upstream/gst-editing-services.git] / ges / ges-video-uri-source.c
1 /* GStreamer Editing Services
2  * Copyright (C) 2009 Edward Hervey <edward.hervey@collabora.co.uk>
3  *               2009 Nokia Corporation
4  *
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.
9  *
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.
14  *
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.
19  */
20
21 /**
22  * SECTION:gesvideourisource
23  * @title: GESVideoUriSource
24  * @short_description: outputs a single video stream from a given file
25  */
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #include <gst/pbutils/missing-plugins.h>
31
32 #include "ges-utils.h"
33 #include "ges-internal.h"
34 #include "ges-track-element.h"
35 #include "ges-video-uri-source.h"
36 #include "ges-uri-asset.h"
37 #include "ges-extractable.h"
38
39 struct _GESVideoUriSourcePrivate
40 {
41   GstElement *decodebin;        /* Reference owned by parent class */
42 };
43
44 enum
45 {
46   PROP_0,
47   PROP_URI
48 };
49
50 static void
51 ges_video_uri_source_track_set_cb (GESVideoUriSource * self,
52     GParamSpec * arg G_GNUC_UNUSED, gpointer nothing)
53 {
54   GESTrack *track;
55   const GstCaps *caps = NULL;
56
57   if (!self->priv->decodebin)
58     return;
59
60   track = ges_track_element_get_track (GES_TRACK_ELEMENT (self));
61   if (!track)
62     return;
63
64   caps = ges_track_get_caps (track);
65
66   GST_INFO_OBJECT (self, "Setting caps to: %" GST_PTR_FORMAT, caps);
67   g_object_set (self->priv->decodebin, "caps", caps, NULL);
68 }
69
70 /* GESSource VMethod */
71 static GstElement *
72 ges_video_uri_source_create_source (GESTrackElement * trksrc)
73 {
74   GESVideoUriSource *self;
75   GESTrack *track;
76   GstElement *decodebin;
77   const GstCaps *caps = NULL;
78
79   self = (GESVideoUriSource *) trksrc;
80
81   track = ges_track_element_get_track (trksrc);
82   if (track)
83     caps = ges_track_get_caps (track);
84
85   decodebin = self->priv->decodebin = gst_element_factory_make ("uridecodebin",
86       NULL);
87
88   g_object_set (decodebin, "caps", caps,
89       "expose-all-streams", FALSE, "uri", self->uri, NULL);
90
91   return decodebin;
92 }
93
94 static gboolean
95 ges_video_uri_source_needs_converters (GESVideoSource * source)
96 {
97   GESTrack *track = ges_track_element_get_track (GES_TRACK_ELEMENT (source));
98
99   if (!track || ges_track_get_mixing (track)) {
100     GESAsset *asset = ges_asset_request (GES_TYPE_URI_CLIP,
101         GES_VIDEO_URI_SOURCE (source)->uri, NULL);
102     gboolean is_nested = FALSE;
103
104     g_assert (asset);
105
106     g_object_get (asset, "is-nested-timeline", &is_nested, NULL);
107     gst_object_unref (asset);
108
109     return !is_nested;
110   }
111
112
113   return FALSE;
114 }
115
116 /* Extractable interface implementation */
117
118 static gchar *
119 ges_extractable_check_id (GType type, const gchar * id, GError ** error)
120 {
121   return g_strdup (id);
122 }
123
124 static void
125 extractable_set_asset (GESExtractable * extractable, GESAsset * asset)
126 {
127   /* FIXME That should go into #GESTrackElement, but
128    * some work is needed to make sure it works properly */
129
130   if (ges_track_element_get_track_type (GES_TRACK_ELEMENT (extractable)) ==
131       GES_TRACK_TYPE_UNKNOWN) {
132     ges_track_element_set_track_type (GES_TRACK_ELEMENT (extractable),
133         ges_track_element_asset_get_track_type (GES_TRACK_ELEMENT_ASSET
134             (asset)));
135   }
136 }
137
138 static void
139 ges_extractable_interface_init (GESExtractableInterface * iface)
140 {
141   iface->asset_type = GES_TYPE_URI_SOURCE_ASSET;
142   iface->check_id = ges_extractable_check_id;
143   iface->set_asset = extractable_set_asset;
144 }
145
146 G_DEFINE_TYPE_WITH_CODE (GESVideoUriSource, ges_video_uri_source,
147     GES_TYPE_VIDEO_SOURCE, G_ADD_PRIVATE (GESVideoUriSource)
148     G_IMPLEMENT_INTERFACE (GES_TYPE_EXTRACTABLE,
149         ges_extractable_interface_init));
150
151
152 /* GObject VMethods */
153
154 static void
155 ges_video_uri_source_get_property (GObject * object, guint property_id,
156     GValue * value, GParamSpec * pspec)
157 {
158   GESVideoUriSource *uriclip = GES_VIDEO_URI_SOURCE (object);
159
160   switch (property_id) {
161     case PROP_URI:
162       g_value_set_string (value, uriclip->uri);
163       break;
164     default:
165       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
166   }
167 }
168
169 static void
170 ges_video_uri_source_set_property (GObject * object, guint property_id,
171     const GValue * value, GParamSpec * pspec)
172 {
173   GESVideoUriSource *uriclip = GES_VIDEO_URI_SOURCE (object);
174
175   switch (property_id) {
176     case PROP_URI:
177       if (uriclip->uri) {
178         GST_WARNING_OBJECT (object, "Uri already set to %s", uriclip->uri);
179         return;
180       }
181       uriclip->uri = g_value_dup_string (value);
182       break;
183     default:
184       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
185   }
186 }
187
188 static void
189 ges_video_uri_source_dispose (GObject * object)
190 {
191   GESVideoUriSource *uriclip = GES_VIDEO_URI_SOURCE (object);
192
193   if (uriclip->uri)
194     g_free (uriclip->uri);
195
196   G_OBJECT_CLASS (ges_video_uri_source_parent_class)->dispose (object);
197 }
198
199 static void
200 ges_video_uri_source_class_init (GESVideoUriSourceClass * klass)
201 {
202   GObjectClass *object_class = G_OBJECT_CLASS (klass);
203   GESVideoSourceClass *source_class = GES_VIDEO_SOURCE_CLASS (klass);
204
205   object_class->get_property = ges_video_uri_source_get_property;
206   object_class->set_property = ges_video_uri_source_set_property;
207   object_class->dispose = ges_video_uri_source_dispose;
208
209   /**
210    * GESVideoUriSource:uri:
211    *
212    * The location of the file/resource to use.
213    */
214   g_object_class_install_property (object_class, PROP_URI,
215       g_param_spec_string ("uri", "URI", "uri of the resource",
216           NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
217
218   source_class->create_source = ges_video_uri_source_create_source;
219   source_class->ABI.abi.needs_converters =
220       ges_video_uri_source_needs_converters;
221 }
222
223 static void
224 ges_video_uri_source_init (GESVideoUriSource * self)
225 {
226   self->priv = ges_video_uri_source_get_instance_private (self);
227
228   g_signal_connect (self, "notify::track",
229       G_CALLBACK (ges_video_uri_source_track_set_cb), NULL);
230 }
231
232 /**
233  * ges_video_uri_source_new:
234  * @uri: the URI the source should control
235  *
236  * Creates a new #GESVideoUriSource for the provided @uri.
237  *
238  * Returns: (transfer floating) (nullable): The newly created #GESVideoUriSource,
239  * or %NULL if there was an error.
240  */
241 GESVideoUriSource *
242 ges_video_uri_source_new (gchar * uri)
243 {
244   return g_object_new (GES_TYPE_VIDEO_URI_SOURCE, "uri", uri, NULL);
245 }