42ad2d824145e41d7da13a9584b0e0beb21fa6f0
[platform/upstream/gst-editing-services.git] / ges / ges-multi-file-source.c
1 /* GStreamer Editing Services
2  * Copyright (C) 2013 Lubosz Sarnecki <lubosz@gmail.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19
20 /**
21  * SECTION:gesmultifilesource
22  * @title: GESMultiFileSource
23  * @short_description: outputs the video stream from a sequence of images.
24  *
25  * Outputs the video stream from a given image sequence. The start frame chosen
26  * will be determined by the in-point property on the track element.
27  *
28  * This should not be used anymore, the `imagesequence://` protocol should be
29  * used instead. Check the #imagesequencesrc GStreamer element for more
30  * information.
31  *
32  * Deprecated: 1.18: Use #GESUriSource instead
33  */
34 #ifdef HAVE_CONFIG_H
35 #include "config.h"
36 #endif
37
38 #include <stdlib.h>
39 #include <string.h>
40 #include "ges-internal.h"
41 #include "ges-track-element.h"
42 #include "ges-multi-file-source.h"
43 #include "ges-extractable.h"
44 #include "ges-uri-asset.h"
45 #include "ges-internal.h"
46
47 /* Extractable interface implementation */
48
49 static gchar *
50 ges_extractable_check_id (GType type, const gchar * id, GError ** error)
51 {
52   return g_strdup (id);
53 }
54
55 static void
56 ges_extractable_interface_init (GESExtractableInterface * iface)
57 {
58   iface->check_id = ges_extractable_check_id;
59 }
60
61 struct _GESMultiFileSourcePrivate
62 {
63   /*  Dummy variable */
64   void *nothing;
65 };
66
67 enum
68 {
69   PROP_0,
70   PROP_URI
71 };
72
73 G_DEFINE_TYPE_WITH_CODE (GESMultiFileSource, ges_multi_file_source,
74     GES_TYPE_VIDEO_SOURCE, G_ADD_PRIVATE (GESMultiFileSource)
75     G_IMPLEMENT_INTERFACE (GES_TYPE_EXTRACTABLE,
76         ges_extractable_interface_init));
77
78 static void
79 ges_multi_file_source_get_property (GObject * object, guint property_id,
80     GValue * value, GParamSpec * pspec)
81 {
82   GESMultiFileSource *uriclip = GES_MULTI_FILE_SOURCE (object);
83
84   switch (property_id) {
85     case PROP_URI:
86       g_value_set_string (value, uriclip->uri);
87       break;
88     default:
89       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
90   }
91 }
92
93 static void
94 ges_multi_file_source_set_property (GObject * object, guint property_id,
95     const GValue * value, GParamSpec * pspec)
96 {
97   GESMultiFileSource *uriclip = GES_MULTI_FILE_SOURCE (object);
98
99   switch (property_id) {
100     case PROP_URI:
101       uriclip->uri = g_value_dup_string (value);
102       break;
103     default:
104       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
105   }
106 }
107
108 static void
109 ges_multi_file_source_dispose (GObject * object)
110 {
111   GESMultiFileSource *uriclip = GES_MULTI_FILE_SOURCE (object);
112
113   if (uriclip->uri)
114     g_free (uriclip->uri);
115
116   G_OBJECT_CLASS (ges_multi_file_source_parent_class)->dispose (object);
117 }
118
119 static void
120 pad_added_cb (GstElement * decodebin, GstPad * pad, GstElement * bin)
121 {
122   GstPad *srcpad;
123
124   srcpad = gst_ghost_pad_new ("src", pad);
125
126   gst_pad_set_active (srcpad, TRUE);
127   gst_element_add_pad (bin, srcpad);
128 }
129
130 /**
131   * ges_multi_file_uri_new: (skip)
132   *
133   * Reads start/stop index and location from a multifile uri.
134   *
135   */
136 GESMultiFileURI *
137 ges_multi_file_uri_new (const gchar * uri)
138 {
139   gchar *colon = NULL;
140   gchar *at = NULL;
141   gchar *indices;
142   int charpos;
143   GESMultiFileURI *uri_data;
144   const int prefix_size = strlen (GES_MULTI_FILE_URI_PREFIX);
145
146   uri_data = malloc (sizeof (GESMultiFileURI));
147
148   uri_data->start = 0;
149   uri_data->end = -1;
150
151   at = strchr (uri, '@');
152   if (at != NULL) {
153     charpos = (int) (at - uri);
154     indices = g_strdup_printf ("%.*s", charpos, uri);
155     indices = &indices[prefix_size];
156     colon = strchr (indices, ':');
157     if (colon != NULL) {
158       charpos = (int) (colon - indices);
159       uri_data->end = atoi (colon + 1);
160       uri_data->start = atoi (g_strdup_printf ("%.*s", charpos, indices));
161       GST_DEBUG ("indices start: %d end %d\n", uri_data->start, uri_data->end);
162     } else {
163       GST_ERROR
164           ("Malformated multifile uri. You are using '@' and are missing ':'");
165     }
166     uri_data->location = at + 1;
167   } else {
168     uri_data->location = g_strdup (&uri[prefix_size]);
169   }
170   GST_DEBUG ("location: %s\n", uri_data->location);
171
172   return uri_data;
173 }
174
175 static GstElement *
176 ges_multi_file_source_create_source (GESTrackElement * track_element)
177 {
178   GESMultiFileSource *self;
179   GstElement *bin, *src, *decodebin;
180   GstCaps *disc_caps;
181   GstDiscovererStreamInfo *stream_info;
182   GValue fps = G_VALUE_INIT;
183   GstCaps *caps;
184   GESUriSourceAsset *asset;
185   GESMultiFileURI *uri_data;
186
187   self = (GESMultiFileSource *) track_element;
188
189   asset =
190       GES_URI_SOURCE_ASSET (ges_extractable_get_asset (GES_EXTRACTABLE (self)));
191
192   if (asset != NULL) {
193     stream_info = ges_uri_source_asset_get_stream_info (asset);
194     g_assert (stream_info);
195     disc_caps = gst_discoverer_stream_info_get_caps (stream_info);
196     caps = gst_caps_copy (disc_caps);
197     GST_DEBUG_OBJECT (disc_caps, "Got some nice caps");
198     gst_object_unref (stream_info);
199     gst_caps_unref (disc_caps);
200   } else {
201     caps = gst_caps_new_empty ();
202     GST_WARNING ("Could not extract asset.");
203   }
204
205   g_value_init (&fps, GST_TYPE_FRACTION);
206   gst_value_set_fraction (&fps, 25, 1);
207   gst_caps_set_value (caps, "framerate", &fps);
208
209   bin = GST_ELEMENT (gst_bin_new ("multi-image-bin"));
210   src = gst_element_factory_make ("multifilesrc", NULL);
211
212   uri_data = ges_multi_file_uri_new (self->uri);
213   g_object_set (src, "start-index", uri_data->start, "stop-index",
214       uri_data->end, "caps", caps, "location", uri_data->location, NULL);
215   g_free (uri_data);
216
217   decodebin = gst_element_factory_make ("decodebin", NULL);
218
219   gst_bin_add_many (GST_BIN (bin), src, decodebin, NULL);
220   gst_element_link_pads_full (src, "src", decodebin, "sink",
221       GST_PAD_LINK_CHECK_NOTHING);
222
223   g_signal_connect (G_OBJECT (decodebin), "pad-added",
224       G_CALLBACK (pad_added_cb), bin);
225
226   return bin;
227 }
228
229 static void
230 ges_multi_file_source_class_init (GESMultiFileSourceClass * klass)
231 {
232   GObjectClass *object_class = G_OBJECT_CLASS (klass);
233   GESVideoSourceClass *source_class = GES_VIDEO_SOURCE_CLASS (klass);
234
235   object_class->get_property = ges_multi_file_source_get_property;
236   object_class->set_property = ges_multi_file_source_set_property;
237   object_class->dispose = ges_multi_file_source_dispose;
238
239   /**
240    * GESMultiFileSource:uri:
241    *
242    * The uri of the file/resource to use. You can set a start index,
243    * a stop index and a sequence pattern.
244    * The format is &lt;multifile://start:stop\@location-pattern&gt;.
245    * The pattern uses printf string formating.
246    *
247    * Example uris:
248    *
249    * multifile:///home/you/image\%03d.jpg
250    *
251    * multifile://20:50@/home/you/sequence/\%04d.png
252    *
253    */
254   g_object_class_install_property (object_class, PROP_URI,
255       g_param_spec_string ("uri", "URI", "multifile uri",
256           NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
257   source_class->create_source = ges_multi_file_source_create_source;
258 }
259
260 static void
261 ges_multi_file_source_init (GESMultiFileSource * self)
262 {
263   self->priv = ges_multi_file_source_get_instance_private (self);
264 }
265
266 /* @uri: the URI the source should control
267  *
268  * Creates a new #GESMultiFileSource for the provided @uri.
269  *
270  * Returns: (transfer floating): A new #GESMultiFileSource.
271  */
272 GESMultiFileSource *
273 ges_multi_file_source_new (gchar * uri)
274 {
275   GESMultiFileSource *res;
276   GESAsset *asset = ges_asset_request (GES_TYPE_MULTI_FILE_SOURCE, uri, NULL);
277
278   res = GES_MULTI_FILE_SOURCE (ges_asset_extract (asset, NULL));
279   res->uri = g_strdup (uri);
280   gst_object_unref (asset);
281
282   return res;
283 }