command-line-formatter: Stop uselessly looping over options
[platform/upstream/gstreamer.git] / ges / ges-video-test-source.c
1 /* GStreamer Editing Services
2  * Copyright (C) 2010 Brandon Lewis <brandon.lewis@collabora.co.uk>
3  *               2010 Nokia Corporation
4  * Copyright (C) 2020 Igalia S.L
5  *     Author: 2020 Thibault Saunier <tsaunier@igalia.com>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22
23 /**
24  * SECTION:gesvideotestsource
25  * @title: GESVideoTestSource
26  * @short_description: produce solid colors and patterns, possibly with a time
27  * overlay.
28  */
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #include "ges-internal.h"
34 #include "ges-track-element.h"
35 #include "ges-video-test-source.h"
36
37 #define DEFAULT_VPATTERN GES_VIDEO_TEST_PATTERN_SMPTE
38
39 struct _GESVideoTestSourcePrivate
40 {
41   GESVideoTestPattern pattern;
42
43   GstElement *capsfilter;
44 };
45
46 static void
47 ges_extractable_interface_init (GESExtractableInterface * iface)
48 {
49   iface->check_id = ges_test_source_asset_check_id;
50   iface->asset_type = GES_TYPE_TRACK_ELEMENT_ASSET;
51 }
52
53 static GstStructure *
54 ges_video_test_source_asset_get_config (GESAsset * asset)
55 {
56   const gchar *id = ges_asset_get_id (asset);
57   if (g_strcmp0 (id, g_type_name (ges_asset_get_extractable_type (asset))))
58     return gst_structure_from_string (ges_asset_get_id (asset), NULL);
59
60   return NULL;
61 }
62
63 G_DEFINE_TYPE_WITH_CODE (GESVideoTestSource, ges_video_test_source,
64     GES_TYPE_VIDEO_SOURCE, G_ADD_PRIVATE (GESVideoTestSource)
65     G_IMPLEMENT_INTERFACE (GES_TYPE_EXTRACTABLE,
66         ges_extractable_interface_init));
67
68 static GstElement *ges_video_test_source_create_source (GESTrackElement * self);
69
70 static gboolean
71 get_natural_size (GESVideoSource * source, gint * width, gint * height)
72 {
73   gboolean res = FALSE;
74   GESTimelineElement *parent = GES_TIMELINE_ELEMENT_PARENT (source);
75
76   if (parent) {
77     GESAsset *asset = ges_extractable_get_asset (GES_EXTRACTABLE (parent));
78
79     if (asset)
80       res = ges_test_clip_asset_get_natural_size (asset, width, height);
81   }
82
83   if (!res) {
84     *width = DEFAULT_WIDTH;
85     *height = DEFAULT_HEIGHT;
86   }
87
88   return TRUE;
89 }
90
91 static gboolean
92 _set_parent (GESTimelineElement * element, GESTimelineElement * parent)
93 {
94   gint width, height, fps_n, fps_d;
95   GstCaps *caps;
96   GESVideoTestSource *self = GES_VIDEO_TEST_SOURCE (element);
97
98
99   if (!parent)
100     goto done;
101
102   g_assert (self->priv->capsfilter);
103   /* Setting the parent ourself as we need it to get the natural size */
104   element->parent = parent;
105   if (!ges_video_source_get_natural_size (GES_VIDEO_SOURCE (self), &width,
106           &height)) {
107     width = DEFAULT_WIDTH;
108     height = DEFAULT_HEIGHT;
109   }
110
111   if (!ges_timeline_element_get_natural_framerate (parent, &fps_n, &fps_d)) {
112     fps_n = DEFAULT_FRAMERATE_N;
113     fps_d = DEFAULT_FRAMERATE_D;
114   }
115
116   caps = gst_caps_new_simple ("video/x-raw",
117       "width", G_TYPE_INT, width,
118       "height", G_TYPE_INT, height,
119       "framerate", GST_TYPE_FRACTION, fps_n, fps_d, NULL);
120   g_object_set (self->priv->capsfilter, "caps", caps, NULL);
121   gst_caps_unref (caps);
122
123 done:
124   return
125       GES_TIMELINE_ELEMENT_CLASS
126       (ges_video_test_source_parent_class)->set_parent (element, parent);
127 }
128
129 static gboolean
130 _get_natural_framerate (GESTimelineElement * element, gint * fps_n,
131     gint * fps_d)
132 {
133   gboolean res = FALSE;
134   GESTimelineElement *parent = GES_TIMELINE_ELEMENT_PARENT (element);
135
136   if (parent) {
137     GESAsset *asset = ges_extractable_get_asset (GES_EXTRACTABLE (parent));
138
139     if (asset) {
140       res =
141           ges_clip_asset_get_natural_framerate (GES_CLIP_ASSET (asset), fps_n,
142           fps_d);
143     }
144   }
145
146   if (!res) {
147     *fps_n = DEFAULT_FRAMERATE_N;
148     *fps_d = DEFAULT_FRAMERATE_D;
149   }
150
151   return TRUE;
152 }
153
154 static void
155 dispose (GObject * object)
156 {
157   G_OBJECT_CLASS (ges_video_test_source_parent_class)->dispose (object);
158 }
159
160 static void
161 ges_video_test_source_class_init (GESVideoTestSourceClass * klass)
162 {
163   GObjectClass *object_class = G_OBJECT_CLASS (klass);
164   GESVideoSourceClass *source_class = GES_VIDEO_SOURCE_CLASS (klass);
165
166   source_class->create_source = ges_video_test_source_create_source;
167   source_class->ABI.abi.get_natural_size = get_natural_size;
168
169   object_class->dispose = dispose;
170
171   GES_TIMELINE_ELEMENT_CLASS (klass)->set_parent = _set_parent;
172   GES_TIMELINE_ELEMENT_CLASS (klass)->get_natural_framerate =
173       _get_natural_framerate;
174 }
175
176 static void
177 ges_video_test_source_init (GESVideoTestSource * self)
178 {
179   self->priv = ges_video_test_source_get_instance_private (self);
180
181   self->priv->pattern = DEFAULT_VPATTERN;
182 }
183
184 static GstStructure *
185 ges_video_test_source_get_config (GESVideoTestSource * self)
186 {
187   GESAsset *asset = ges_extractable_get_asset (GES_EXTRACTABLE (self));
188   if (asset)
189     return ges_video_test_source_asset_get_config (asset);
190
191   return NULL;
192 }
193
194 static GstElement *
195 ges_video_test_source_create_overlay (GESVideoTestSource * self)
196 {
197   const gchar *bindesc = NULL;
198   GstStructure *config = ges_video_test_source_get_config (self);
199
200   if (!config)
201     return NULL;
202
203   if (gst_structure_has_name (config, "time-overlay")) {
204     gboolean disable_timecodestamper;
205
206     if (gst_structure_get_boolean (config, "disable-timecodestamper",
207             &disable_timecodestamper))
208       bindesc = "timeoverlay";
209     else
210       bindesc = "timecodestamper ! timeoverlay";
211   }
212   gst_structure_free (config);
213
214   if (!bindesc)
215     return NULL;
216
217   return gst_parse_bin_from_description (bindesc, TRUE, NULL);
218 }
219
220 static GstElement *
221 ges_video_test_source_create_source (GESTrackElement * element)
222 {
223   GstCaps *caps;
224   gint pattern;
225   GstElement *testsrc, *res;
226   GstElement *overlay;
227   const gchar *props[] =
228       { "pattern", "background-color", "foreground-color", NULL };
229   GPtrArray *elements;
230   GESVideoTestSource *self = GES_VIDEO_TEST_SOURCE (element);
231
232   g_assert (!GES_TIMELINE_ELEMENT_PARENT (element));
233   testsrc = gst_element_factory_make ("videotestsrc", NULL);
234   self->priv->capsfilter = gst_element_factory_make ("capsfilter", NULL);
235   pattern = self->priv->pattern;
236
237   g_object_set (testsrc, "pattern", pattern, NULL);
238
239   elements = g_ptr_array_new ();
240   g_ptr_array_add (elements, self->priv->capsfilter);
241   caps = gst_caps_new_simple ("video/x-raw",
242       "width", G_TYPE_INT, DEFAULT_WIDTH,
243       "height", G_TYPE_INT, DEFAULT_HEIGHT,
244       "framerate", GST_TYPE_FRACTION, DEFAULT_FRAMERATE_N, DEFAULT_FRAMERATE_D,
245       NULL);
246   g_object_set (self->priv->capsfilter, "caps", caps, NULL);
247   gst_caps_unref (caps);
248
249   overlay = ges_video_test_source_create_overlay (self);
250   if (overlay) {
251     const gchar *overlay_props[] =
252         { "time-mode", "text-y", "text-x", "text-width", "test-height",
253       "halignment", "valignment", "font-desc", NULL
254     };
255
256     ges_track_element_add_children_props (element, overlay, NULL,
257         NULL, overlay_props);
258     g_ptr_array_add (elements, overlay);
259   }
260
261   ges_track_element_add_children_props (element, testsrc, NULL, NULL, props);
262
263   res = ges_source_create_topbin (GES_SOURCE (element), "videotestsrc", testsrc,
264       elements);
265
266   return res;
267 }
268
269 /**
270  * ges_video_test_source_set_pattern:
271  * @self: a #GESVideoTestSource
272  * @pattern: a #GESVideoTestPattern
273  *
274  * Sets the source to use the given @pattern.
275  */
276 void
277 ges_video_test_source_set_pattern (GESVideoTestSource
278     * self, GESVideoTestPattern pattern)
279 {
280   GstElement *element =
281       ges_track_element_get_element (GES_TRACK_ELEMENT (self));
282
283   self->priv->pattern = pattern;
284
285   if (element) {
286     GValue val = { 0 };
287
288     g_value_init (&val, GES_VIDEO_TEST_PATTERN_TYPE);
289     g_value_set_enum (&val, pattern);
290     ges_track_element_set_child_property (GES_TRACK_ELEMENT (self), "pattern",
291         &val);
292   }
293 }
294
295 /**
296  * ges_video_test_source_get_pattern:
297  * @source: a #GESVideoTestPattern
298  *
299  * Get the video pattern used by the @source.
300  *
301  * Returns: The video pattern used by the @source.
302  */
303 GESVideoTestPattern
304 ges_video_test_source_get_pattern (GESVideoTestSource * source)
305 {
306   GValue val = { 0 };
307
308   ges_track_element_get_child_property (GES_TRACK_ELEMENT (source), "pattern",
309       &val);
310   return g_value_get_enum (&val);
311 }
312
313 /**
314  * ges_video_test_source_new:
315  *
316  * Creates a new #GESVideoTestSource.
317  *
318  * Returns: (transfer floating) (nullable): The newly created
319  * #GESVideoTestSource, or %NULL if there was an error.
320  */
321 GESVideoTestSource *
322 ges_video_test_source_new (void)
323 {
324   GESVideoTestSource *res;
325   GESAsset *asset = ges_asset_request (GES_TYPE_VIDEO_TEST_SOURCE, NULL, NULL);
326
327   res = GES_VIDEO_TEST_SOURCE (ges_asset_extract (asset, NULL));
328   gst_object_unref (asset);
329
330   return res;
331 }