2 * Copyright (C) 2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
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.
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.
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.
26 #include "gstfrei0r.h"
27 #include "gstfrei0rsrc.h"
29 GST_DEBUG_CATEGORY_EXTERN (frei0r_debug);
30 #define GST_CAT_DEFAULT frei0r_debug
34 f0r_plugin_info_t info;
35 GstFrei0rFuncTable ftable;
36 } GstFrei0rSrcClassData;
39 gst_frei0r_src_set_caps (GstBaseSrc * src, GstCaps * caps)
41 GstFrei0rSrc *self = GST_FREI0R_SRC (src);
43 gst_video_info_init (&self->info);
44 if (!gst_video_info_from_caps (&self->info, caps))
47 gst_base_src_set_blocksize (src, self->info.size);
53 gst_frei0r_src_fill (GstPushSrc * src, GstBuffer * buf)
55 GstFrei0rSrc *self = GST_FREI0R_SRC (src);
56 GstFrei0rSrcClass *klass = GST_FREI0R_SRC_GET_CLASS (src);
57 GstClockTime timestamp;
61 if (G_UNLIKELY (!self->f0r_instance)) {
63 gst_frei0r_instance_construct (klass->ftable, klass->properties,
64 klass->n_properties, self->property_cache, self->info.width,
67 if (G_UNLIKELY (!self->f0r_instance))
68 return GST_FLOW_ERROR;
72 gst_util_uint64_scale (self->n_frames, GST_SECOND * self->info.fps_d,
74 GST_BUFFER_PTS (buf) = GST_BUFFER_DTS (buf) = timestamp;
75 GST_BUFFER_OFFSET (buf) = self->n_frames;
77 GST_BUFFER_OFFSET_END (buf) = self->n_frames;
78 GST_BUFFER_DURATION (buf) =
79 gst_util_uint64_scale (self->n_frames, GST_SECOND * self->info.fps_d,
80 self->info.fps_n) - GST_BUFFER_TIMESTAMP (buf);
83 gst_segment_to_stream_time (&GST_BASE_SRC_CAST (self)->segment,
84 GST_FORMAT_TIME, timestamp);
86 GST_DEBUG_OBJECT (self, "sync to %" GST_TIME_FORMAT,
87 GST_TIME_ARGS (timestamp));
89 if (GST_CLOCK_TIME_IS_VALID (timestamp))
90 gst_object_sync_values (GST_OBJECT (self), timestamp);
92 time = ((gdouble) GST_BUFFER_TIMESTAMP (buf)) / GST_SECOND;
94 GST_OBJECT_LOCK (self);
96 if (!gst_buffer_map (buf, &map, GST_MAP_WRITE))
99 if (klass->ftable->update2)
100 klass->ftable->update2 (self->f0r_instance, time, NULL, NULL, NULL,
101 (guint32 *) map.data);
103 klass->ftable->update (self->f0r_instance, time, NULL,
104 (guint32 *) map.data);
106 gst_buffer_unmap (buf, &map);
108 GST_OBJECT_UNLOCK (self);
113 GST_OBJECT_UNLOCK (self);
114 GST_ELEMENT_ERROR (GST_ELEMENT (src), RESOURCE, WRITE, (NULL),
115 ("Could not map buffer for writing"));
116 return GST_FLOW_ERROR;
120 gst_frei0r_src_start (GstBaseSrc * basesrc)
122 GstFrei0rSrc *self = GST_FREI0R_SRC (basesrc);
130 gst_frei0r_src_stop (GstBaseSrc * basesrc)
132 GstFrei0rSrc *self = GST_FREI0R_SRC (basesrc);
133 GstFrei0rSrcClass *klass = GST_FREI0R_SRC_GET_CLASS (basesrc);
135 if (self->f0r_instance) {
136 klass->ftable->destruct (self->f0r_instance);
137 self->f0r_instance = NULL;
140 gst_video_info_init (&self->info);
147 gst_frei0r_src_is_seekable (GstBaseSrc * psrc)
153 gst_frei0r_src_do_seek (GstBaseSrc * bsrc, GstSegment * segment)
156 GstFrei0rSrc *self = GST_FREI0R_SRC (bsrc);
158 segment->time = segment->start;
159 time = segment->position;
161 /* now move to the time indicated */
162 if (self->info.fps_n) {
163 self->n_frames = gst_util_uint64_scale (time,
164 self->info.fps_n, self->info.fps_d * GST_SECOND);
173 gst_frei0r_src_query (GstBaseSrc * bsrc, GstQuery * query)
176 GstFrei0rSrc *self = GST_FREI0R_SRC (bsrc);
177 GstFrei0rSrcClass *klass = GST_FREI0R_SRC_GET_CLASS (self);
179 switch (GST_QUERY_TYPE (query)) {
180 case GST_QUERY_CONVERT:
182 GstFormat src_fmt, dest_fmt;
183 gint64 src_val, dest_val;
185 gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
186 if (src_fmt == dest_fmt) {
192 case GST_FORMAT_DEFAULT:
194 case GST_FORMAT_TIME:
196 if (self->info.fps_n) {
197 dest_val = gst_util_uint64_scale (src_val,
198 self->info.fps_d * GST_SECOND, self->info.fps_n);
207 case GST_FORMAT_TIME:
209 case GST_FORMAT_DEFAULT:
211 if (self->info.fps_n) {
212 dest_val = gst_util_uint64_scale (src_val,
213 self->info.fps_n, self->info.fps_d * GST_SECOND);
226 gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
232 GST_BASE_SRC_CLASS (g_type_class_peek_parent (klass))->query (bsrc,
240 GST_DEBUG_OBJECT (self, "query failed");
246 gst_frei0r_src_fixate (GstBaseSrc * src, GstCaps * caps)
248 GstStructure *structure;
250 caps = gst_caps_make_writable (caps);
252 structure = gst_caps_get_structure (caps, 0);
254 gst_structure_fixate_field_nearest_int (structure, "width", 320);
255 gst_structure_fixate_field_nearest_int (structure, "height", 240);
256 gst_structure_fixate_field_nearest_fraction (structure, "framerate", 30, 1);
262 gst_frei0r_src_finalize (GObject * object)
264 GstFrei0rSrc *self = GST_FREI0R_SRC (object);
265 GstFrei0rSrcClass *klass = GST_FREI0R_SRC_GET_CLASS (object);
267 if (self->f0r_instance) {
268 klass->ftable->destruct (self->f0r_instance);
269 self->f0r_instance = NULL;
272 if (self->property_cache)
273 gst_frei0r_property_cache_free (klass->properties, self->property_cache,
274 klass->n_properties);
275 self->property_cache = NULL;
277 G_OBJECT_CLASS (g_type_class_peek_parent (klass))->finalize (object);
281 gst_frei0r_src_get_property (GObject * object, guint prop_id, GValue * value,
284 GstFrei0rSrc *self = GST_FREI0R_SRC (object);
285 GstFrei0rSrcClass *klass = GST_FREI0R_SRC_GET_CLASS (object);
287 GST_OBJECT_LOCK (self);
288 if (!gst_frei0r_get_property (self->f0r_instance, klass->ftable,
289 klass->properties, klass->n_properties, self->property_cache, prop_id,
291 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
292 GST_OBJECT_UNLOCK (self);
296 gst_frei0r_src_set_property (GObject * object, guint prop_id,
297 const GValue * value, GParamSpec * pspec)
299 GstFrei0rSrc *self = GST_FREI0R_SRC (object);
300 GstFrei0rSrcClass *klass = GST_FREI0R_SRC_GET_CLASS (object);
302 GST_OBJECT_LOCK (self);
303 if (!gst_frei0r_set_property (self->f0r_instance, klass->ftable,
304 klass->properties, klass->n_properties, self->property_cache, prop_id,
306 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
307 GST_OBJECT_UNLOCK (self);
311 gst_frei0r_src_class_init (GstFrei0rSrcClass * klass,
312 GstFrei0rSrcClassData * class_data)
314 GObjectClass *gobject_class = (GObjectClass *) klass;
315 GstElementClass *gstelement_class = (GstElementClass *) klass;
316 GstPushSrcClass *gstpushsrc_class = (GstPushSrcClass *) klass;
317 GstBaseSrcClass *gstbasesrc_class = (GstBaseSrcClass *) klass;
318 GstPadTemplate *templ;
323 klass->ftable = &class_data->ftable;
324 klass->info = &class_data->info;
326 gobject_class->finalize = gst_frei0r_src_finalize;
327 gobject_class->set_property = gst_frei0r_src_set_property;
328 gobject_class->get_property = gst_frei0r_src_get_property;
330 klass->n_properties = klass->info->num_params;
331 klass->properties = g_new0 (GstFrei0rProperty, klass->n_properties);
333 gst_frei0r_klass_install_properties (gobject_class, klass->ftable,
334 klass->properties, klass->n_properties);
338 ("Sebastian Dröge <sebastian.droege@collabora.co.uk>, %s",
339 class_data->info.author);
340 desc = class_data->info.explanation;
341 if (desc == NULL || *desc == '\0')
343 gst_element_class_set_metadata (gstelement_class, class_data->info.name,
344 "Src/Video", desc, author);
347 caps = gst_frei0r_caps_from_color_model (class_data->info.color_model);
349 templ = gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, caps);
350 gst_element_class_add_pad_template (gstelement_class, templ);
351 gst_caps_unref (caps);
353 gstbasesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_frei0r_src_set_caps);
354 gstbasesrc_class->is_seekable =
355 GST_DEBUG_FUNCPTR (gst_frei0r_src_is_seekable);
356 gstbasesrc_class->do_seek = GST_DEBUG_FUNCPTR (gst_frei0r_src_do_seek);
357 gstbasesrc_class->query = GST_DEBUG_FUNCPTR (gst_frei0r_src_query);
358 gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_frei0r_src_start);
359 gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_frei0r_src_stop);
360 gstbasesrc_class->fixate = GST_DEBUG_FUNCPTR (gst_frei0r_src_fixate);
362 gstpushsrc_class->fill = GST_DEBUG_FUNCPTR (gst_frei0r_src_fill);
366 gst_frei0r_src_init (GstFrei0rSrc * self, GstFrei0rSrcClass * klass)
368 self->property_cache =
369 gst_frei0r_property_cache_init (klass->properties, klass->n_properties);
370 gst_video_info_init (&self->info);
371 gst_base_src_set_format (GST_BASE_SRC_CAST (self), GST_FORMAT_TIME);
374 GstFrei0rPluginRegisterReturn
375 gst_frei0r_src_register (GstPlugin * plugin, const gchar * vendor,
376 const f0r_plugin_info_t * info, const GstFrei0rFuncTable * ftable)
378 GTypeInfo typeinfo = {
379 sizeof (GstFrei0rSrcClass),
382 (GClassInitFunc) gst_frei0r_src_class_init,
385 sizeof (GstFrei0rSrc),
387 (GInstanceInitFunc) gst_frei0r_src_init
390 gchar *type_name, *tmp;
391 GstFrei0rSrcClassData *class_data;
392 GstFrei0rPluginRegisterReturn ret = GST_FREI0R_PLUGIN_REGISTER_RETURN_FAILED;
395 tmp = g_strdup_printf ("frei0r-src-%s-%s", vendor, info->name);
397 tmp = g_strdup_printf ("frei0r-src-%s", info->name);
398 type_name = g_ascii_strdown (tmp, -1);
400 g_strcanon (type_name, G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "-+", '-');
402 if (g_type_from_name (type_name)) {
403 GST_DEBUG ("Type '%s' already exists", type_name);
404 return GST_FREI0R_PLUGIN_REGISTER_RETURN_ALREADY_REGISTERED;
407 class_data = g_new0 (GstFrei0rSrcClassData, 1);
408 memcpy (&class_data->info, info, sizeof (f0r_plugin_info_t));
409 memcpy (&class_data->ftable, ftable, sizeof (GstFrei0rFuncTable));
410 typeinfo.class_data = class_data;
412 type = g_type_register_static (GST_TYPE_PUSH_SRC, type_name, &typeinfo, 0);
413 if (gst_element_register (plugin, type_name, GST_RANK_NONE, type))
414 ret = GST_FREI0R_PLUGIN_REGISTER_RETURN_OK;