2 * Copyright (C) 2004 Benjamin Otte <otte@gnome.org>
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., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
25 #include <gst/base/gstadapter.h>
26 #include <gst/video/video.h>
27 #include <gst/audio/audio.h>
28 #include <libvisual/libvisual.h>
30 #define GST_TYPE_VISUAL (gst_visual_get_type())
31 #define GST_IS_VISUAL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VISUAL))
32 #define GST_VISUAL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VISUAL,GstVisual))
33 #define GST_IS_VISUAL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VISUAL))
34 #define GST_VISUAL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VISUAL,GstVisualClass))
35 #define GST_VISUAL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VISUAL, GstVisualClass))
37 typedef struct _GstVisual GstVisual;
38 typedef struct _GstVisualClass GstVisualClass;
40 GST_DEBUG_CATEGORY_STATIC (libvisual_debug);
41 #define GST_CAT_DEFAULT (libvisual_debug)
43 /* amounf of samples before we can feed libvisual */
44 #define VISUAL_SAMPLES 512
46 #define DEFAULT_WIDTH 320
47 #define DEFAULT_HEIGHT 240
48 #define DEFAULT_FPS_N 25
49 #define DEFAULT_FPS_D 1
65 /* audio/video state */
68 /* framerate numerator & denominator */
73 GstClockTime duration;
77 /* samples per frame based on caps */
84 /* QoS stuff *//* with LOCK */
86 GstClockTime earliest_time;
89 struct _GstVisualClass
91 GstElementClass parent_class;
96 GType gst_visual_get_type (void);
99 static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
102 GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE (" { "
103 #if G_BYTE_ORDER == G_BIG_ENDIAN
104 "\"xRGB\", " "\"RGB\", "
106 "\"BGRx\", " "\"BGR\", "
111 static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
114 GST_STATIC_CAPS ("audio/x-raw, "
115 "format = (string) " GST_AUDIO_NE (S16) ", "
116 "channels = (int) { 1, 2 }, "
117 #if defined(VISUAL_API_VERSION) && VISUAL_API_VERSION >= 4000 && VISUAL_API_VERSION < 5000
118 "rate = (int) { 8000, 11250, 22500, 32000, 44100, 48000, 96000 }"
120 "rate = (int) [ 1000, MAX ]"
126 static void gst_visual_class_init (gpointer g_class, gpointer class_data);
127 static void gst_visual_init (GstVisual * visual);
128 static void gst_visual_finalize (GObject * object);
130 static GstStateChangeReturn gst_visual_change_state (GstElement * element,
131 GstStateChange transition);
132 static GstFlowReturn gst_visual_chain (GstPad * pad, GstBuffer * buffer);
133 static gboolean gst_visual_sink_event (GstPad * pad, GstEvent * event);
134 static gboolean gst_visual_src_event (GstPad * pad, GstEvent * event);
136 static gboolean gst_visual_src_query (GstPad * pad, GstQuery * query);
138 static gboolean gst_visual_sink_setcaps (GstPad * pad, GstCaps * caps);
139 static GstCaps *gst_visual_getcaps (GstPad * pad, GstCaps * filter);
140 static void libvisual_log_handler (const char *message, const char *funcname,
143 static GstElementClass *parent_class = NULL;
146 gst_visual_get_type (void)
148 static GType type = 0;
150 if (G_UNLIKELY (type == 0)) {
151 static const GTypeInfo info = {
152 sizeof (GstVisualClass),
155 gst_visual_class_init,
160 (GInstanceInitFunc) gst_visual_init,
163 type = g_type_register_static (GST_TYPE_ELEMENT, "GstVisual", &info, 0);
169 libvisual_log_handler (const char *message, const char *funcname, void *priv)
171 GST_CAT_LEVEL_LOG (libvisual_debug, (GstDebugLevel) (priv), NULL, "%s - %s",
176 gst_visual_class_init (gpointer g_class, gpointer class_data)
178 GstVisualClass *klass = GST_VISUAL_CLASS (g_class);
179 GstElementClass *element = GST_ELEMENT_CLASS (g_class);
180 GObjectClass *object = G_OBJECT_CLASS (g_class);
182 klass->plugin = class_data;
184 element->change_state = gst_visual_change_state;
186 if (class_data == NULL) {
187 parent_class = g_type_class_peek_parent (g_class);
189 char *longname = g_strdup_printf ("libvisual %s plugin v.%s",
190 klass->plugin->info->name, klass->plugin->info->version);
192 /* FIXME: improve to only register what plugin supports? */
193 gst_element_class_add_pad_template (element,
194 gst_static_pad_template_get (&src_template));
195 gst_element_class_add_pad_template (element,
196 gst_static_pad_template_get (&sink_template));
198 gst_element_class_set_details_simple (element,
199 longname, "Visualization",
200 klass->plugin->info->about, "Benjamin Otte <otte@gnome.org>");
205 object->finalize = gst_visual_finalize;
209 gst_visual_init (GstVisual * visual)
211 /* create the sink and src pads */
212 visual->sinkpad = gst_pad_new_from_static_template (&sink_template, "sink");
213 gst_pad_set_chain_function (visual->sinkpad, gst_visual_chain);
214 gst_pad_set_event_function (visual->sinkpad, gst_visual_sink_event);
215 gst_element_add_pad (GST_ELEMENT (visual), visual->sinkpad);
217 visual->srcpad = gst_pad_new_from_static_template (&src_template, "src");
218 gst_pad_set_event_function (visual->srcpad, gst_visual_src_event);
219 gst_pad_set_query_function (visual->srcpad, gst_visual_src_query);
220 gst_element_add_pad (GST_ELEMENT (visual), visual->srcpad);
222 visual->adapter = gst_adapter_new ();
226 gst_visual_clear_actors (GstVisual * visual)
229 visual_object_unref (VISUAL_OBJECT (visual->actor));
230 visual->actor = NULL;
233 visual_object_unref (VISUAL_OBJECT (visual->video));
234 visual->video = NULL;
237 visual_object_unref (VISUAL_OBJECT (visual->audio));
238 visual->audio = NULL;
243 gst_visual_finalize (GObject * object)
245 GstVisual *visual = GST_VISUAL (object);
247 g_object_unref (visual->adapter);
249 gst_object_unref (visual->pool);
250 gst_visual_clear_actors (visual);
252 GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
256 gst_visual_reset (GstVisual * visual)
258 gst_adapter_clear (visual->adapter);
259 gst_segment_init (&visual->segment, GST_FORMAT_UNDEFINED);
261 GST_OBJECT_LOCK (visual);
262 visual->proportion = 1.0;
263 visual->earliest_time = -1;
264 GST_OBJECT_UNLOCK (visual);
268 gst_visual_getcaps (GstPad * pad, GstCaps * filter)
271 GstVisual *visual = GST_VISUAL (gst_pad_get_parent (pad));
274 if (!visual->actor) {
275 ret = gst_pad_get_pad_template_caps (visual->srcpad);
279 ret = gst_caps_new_empty ();
280 depths = visual_actor_get_supported_depth (visual->actor);
282 /* FIXME: set an error */
285 if (depths == VISUAL_VIDEO_DEPTH_GL) {
286 /* We can't handle GL only plugins */
290 GST_DEBUG_OBJECT (visual, "libvisual plugin supports depths %u (0x%04x)",
292 /* if (depths & VISUAL_VIDEO_DEPTH_32BIT) Always supports 32bit output */
293 #if G_BYTE_ORDER == G_BIG_ENDIAN
294 gst_caps_append (ret, gst_caps_from_string (GST_VIDEO_CAPS_MAKE ("xRGB")));
296 gst_caps_append (ret, gst_caps_from_string (GST_VIDEO_CAPS_MAKE ("BGRx")));
299 if (depths & VISUAL_VIDEO_DEPTH_24BIT) {
300 #if G_BYTE_ORDER == G_BIG_ENDIAN
301 gst_caps_append (ret, gst_caps_from_string (GST_VIDEO_CAPS_MAKE ("RGB")));
303 gst_caps_append (ret, gst_caps_from_string (GST_VIDEO_CAPS_MAKE ("BGR")));
306 if (depths & VISUAL_VIDEO_DEPTH_16BIT) {
307 gst_caps_append (ret, gst_caps_from_string (GST_VIDEO_CAPS_MAKE ("RGB16")));
313 GstCaps *intersection;
316 gst_caps_intersect_full (filter, ret, GST_CAPS_INTERSECT_FIRST);
317 gst_caps_unref (ret);
321 GST_DEBUG_OBJECT (visual, "returning caps %" GST_PTR_FORMAT, ret);
322 gst_object_unref (visual);
327 gst_visual_src_setcaps (GstVisual * visual, GstCaps * caps)
330 GstStructure *structure;
331 gint depth, pitch, rate;
334 structure = gst_caps_get_structure (caps, 0);
336 GST_DEBUG_OBJECT (visual, "src pad got caps %" GST_PTR_FORMAT, caps);
338 if (!gst_structure_get_int (structure, "width", &visual->width))
340 if (!gst_structure_get_int (structure, "height", &visual->height))
342 if (!(fmt = gst_structure_get_string (structure, "format")))
344 if (!gst_structure_get_fraction (structure, "framerate", &visual->fps_n,
348 if (!strcmp (fmt, "BGR") || !strcmp (fmt, "RGB"))
350 else if (!strcmp (fmt, "BGRx") || !strcmp (fmt, "xRGB"))
355 visual_video_set_depth (visual->video,
356 visual_video_depth_enum_from_value (depth));
357 visual_video_set_dimension (visual->video, visual->width, visual->height);
358 pitch = GST_ROUND_UP_4 (visual->width * visual->video->bpp);
359 visual_video_set_pitch (visual->video, pitch);
360 visual_actor_video_negotiate (visual->actor, 0, FALSE, FALSE);
362 rate = GST_AUDIO_INFO_RATE (&visual->info);
364 /* precalc some values */
365 visual->outsize = visual->video->height * pitch;
366 visual->spf = gst_util_uint64_scale_int (rate, visual->fps_d, visual->fps_n);
368 gst_util_uint64_scale_int (GST_SECOND, visual->fps_d, visual->fps_n);
370 res = gst_pad_push_event (visual->srcpad, gst_event_new_caps (caps));
377 GST_DEBUG_OBJECT (visual, "error parsing caps");
383 gst_visual_sink_setcaps (GstPad * pad, GstCaps * caps)
385 GstVisual *visual = GST_VISUAL (gst_pad_get_parent (pad));
389 if (!gst_audio_info_from_caps (&info, caps))
394 rate = GST_AUDIO_INFO_RATE (&info);
396 /* this is how many samples we need to fill one frame at the requested
398 if (visual->fps_n != 0) {
400 gst_util_uint64_scale_int (rate, visual->fps_d, visual->fps_n);
403 gst_object_unref (visual);
410 GST_ERROR_OBJECT (visual, "invalid caps received");
411 gst_object_unref (visual);
417 gst_vis_src_negotiate (GstVisual * visual)
419 GstCaps *othercaps, *target;
420 GstStructure *structure;
423 GstBufferPool *pool = NULL;
424 guint size, min, max, prefix, alignment;
426 caps = gst_pad_query_caps (visual->srcpad, NULL);
428 /* see what the peer can do */
429 othercaps = gst_pad_peer_get_caps (visual->srcpad, caps);
432 gst_caps_unref (caps);
434 if (gst_caps_is_empty (target))
437 target = gst_caps_make_writable (target);
438 gst_caps_truncate (target);
440 /* need a copy, we'll be modifying it when fixating */
441 target = gst_caps_copy (caps);
442 gst_caps_unref (caps);
444 GST_DEBUG_OBJECT (visual, "before fixate caps %" GST_PTR_FORMAT, target);
446 /* fixate in case something is not fixed. This does nothing if the value is
447 * already fixed. For video we always try to fixate to something like
448 * 320x240x25 by convention. */
449 structure = gst_caps_get_structure (target, 0);
450 gst_structure_fixate_field_nearest_int (structure, "width", DEFAULT_WIDTH);
451 gst_structure_fixate_field_nearest_int (structure, "height", DEFAULT_HEIGHT);
452 gst_structure_fixate_field_nearest_fraction (structure, "framerate",
453 DEFAULT_FPS_N, DEFAULT_FPS_D);
454 gst_caps_fixate (target);
456 GST_DEBUG_OBJECT (visual, "after fixate caps %" GST_PTR_FORMAT, target);
458 gst_visual_src_setcaps (visual, target);
460 /* try to get a bufferpool now */
461 /* find a pool for the negotiated caps now */
462 query = gst_query_new_allocation (target, TRUE);
464 if (gst_pad_peer_query (visual->srcpad, query)) {
465 /* we got configuration from our peer, parse them */
466 gst_query_parse_allocation_params (query, &size, &min, &max, &prefix,
469 size = visual->outsize;
476 GstStructure *config;
478 /* we did not get a pool, make one ourselves then */
479 pool = gst_buffer_pool_new ();
481 config = gst_buffer_pool_get_config (pool);
482 gst_buffer_pool_config_set (config, target, size, min, max, prefix,
484 gst_buffer_pool_set_config (pool, config);
488 gst_object_unref (visual->pool);
492 gst_buffer_pool_set_active (pool, TRUE);
494 gst_caps_unref (target);
501 GST_ELEMENT_ERROR (visual, STREAM, FORMAT, (NULL),
502 ("could not negotiate output format"));
503 gst_caps_unref (target);
509 gst_visual_sink_event (GstPad * pad, GstEvent * event)
514 visual = GST_VISUAL (gst_pad_get_parent (pad));
516 switch (GST_EVENT_TYPE (event)) {
517 case GST_EVENT_FLUSH_START:
518 res = gst_pad_push_event (visual->srcpad, event);
520 case GST_EVENT_FLUSH_STOP:
521 /* reset QoS and adapter. */
522 gst_visual_reset (visual);
523 res = gst_pad_push_event (visual->srcpad, event);
529 gst_event_parse_caps (event, &caps);
530 res = gst_visual_sink_setcaps (pad, caps);
531 gst_event_unref (event);
534 case GST_EVENT_SEGMENT:
536 /* the newsegment values are used to clip the input samples
537 * and to convert the incomming timestamps to running time so
539 gst_event_copy_segment (event, &visual->segment);
542 res = gst_pad_push_event (visual->srcpad, event);
546 res = gst_pad_event_default (pad, event);
550 gst_object_unref (visual);
555 gst_visual_src_event (GstPad * pad, GstEvent * event)
560 visual = GST_VISUAL (gst_pad_get_parent (pad));
562 switch (GST_EVENT_TYPE (event)) {
566 GstClockTimeDiff diff;
567 GstClockTime timestamp;
569 gst_event_parse_qos (event, NULL, &proportion, &diff, ×tamp);
571 /* save stuff for the _chain function */
572 GST_OBJECT_LOCK (visual);
573 visual->proportion = proportion;
575 /* we're late, this is a good estimate for next displayable
576 * frame (see part-qos.txt) */
577 visual->earliest_time = timestamp + 2 * diff + visual->duration;
579 visual->earliest_time = timestamp + diff;
581 GST_OBJECT_UNLOCK (visual);
583 res = gst_pad_push_event (visual->sinkpad, event);
586 case GST_EVENT_RECONFIGURE:
588 gst_event_unref (event);
592 res = gst_pad_event_default (pad, event);
596 gst_object_unref (visual);
601 gst_visual_src_query (GstPad * pad, GstQuery * query)
606 visual = GST_VISUAL (gst_pad_get_parent (pad));
608 switch (GST_QUERY_TYPE (query)) {
609 case GST_QUERY_LATENCY:
611 /* We need to send the query upstream and add the returned latency to our
613 GstClockTime min_latency, max_latency;
615 GstClockTime our_latency;
618 if ((res = gst_pad_peer_query (visual->sinkpad, query))) {
619 gst_query_parse_latency (query, &us_live, &min_latency, &max_latency);
621 GST_DEBUG_OBJECT (visual, "Peer latency: min %"
622 GST_TIME_FORMAT " max %" GST_TIME_FORMAT,
623 GST_TIME_ARGS (min_latency), GST_TIME_ARGS (max_latency));
625 /* the max samples we must buffer buffer */
626 max_samples = MAX (VISUAL_SAMPLES, visual->spf);
628 gst_util_uint64_scale_int (max_samples, GST_SECOND,
629 GST_AUDIO_INFO_RATE (&visual->info));
631 GST_DEBUG_OBJECT (visual, "Our latency: %" GST_TIME_FORMAT,
632 GST_TIME_ARGS (our_latency));
634 /* we add some latency but only if we need to buffer more than what
635 * upstream gives us */
636 min_latency += our_latency;
637 if (max_latency != -1)
638 max_latency += our_latency;
640 GST_DEBUG_OBJECT (visual, "Calculated total latency : min %"
641 GST_TIME_FORMAT " max %" GST_TIME_FORMAT,
642 GST_TIME_ARGS (min_latency), GST_TIME_ARGS (max_latency));
644 gst_query_set_latency (query, TRUE, min_latency, max_latency);
650 GstCaps *filter, *caps;
652 gst_query_parse_caps (query, &filter);
653 caps = gst_visual_getcaps (pad, filter);
654 gst_query_set_caps_result (query, caps);
655 gst_caps_unref (caps);
659 res = gst_pad_query_default (pad, query);
663 gst_object_unref (visual);
668 /* Make sure we are negotiated */
670 ensure_negotiated (GstVisual * visual)
672 gboolean reconfigure;
674 GST_OBJECT_LOCK (visual->srcpad);
675 reconfigure = GST_PAD_NEEDS_RECONFIGURE (visual->srcpad);
676 GST_OBJECT_FLAG_UNSET (visual->srcpad, GST_PAD_NEED_RECONFIGURE);
677 GST_OBJECT_UNLOCK (visual->srcpad);
679 /* we don't know an output format yet, pick one */
680 if (reconfigure || !gst_pad_has_current_caps (visual->srcpad)) {
681 if (!gst_vis_src_negotiate (visual))
682 return GST_FLOW_NOT_NEGOTIATED;
688 gst_visual_chain (GstPad * pad, GstBuffer * buffer)
690 GstBuffer *outbuf = NULL;
692 GstVisual *visual = GST_VISUAL (gst_pad_get_parent (pad));
693 GstFlowReturn ret = GST_FLOW_OK;
695 gint bpf, rate, channels;
697 GST_DEBUG_OBJECT (visual, "chain function called");
699 /* Make sure have an output format */
700 ret = ensure_negotiated (visual);
701 if (ret != GST_FLOW_OK) {
702 gst_buffer_unref (buffer);
706 /* resync on DISCONT */
707 if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT)) {
708 gst_adapter_clear (visual->adapter);
711 rate = GST_AUDIO_INFO_RATE (&visual->info);
712 bpf = GST_AUDIO_INFO_BPF (&visual->info);
713 channels = GST_AUDIO_INFO_CHANNELS (&visual->info);
715 GST_DEBUG_OBJECT (visual,
716 "Input buffer has %d samples, time=%" G_GUINT64_FORMAT,
717 gst_buffer_get_size (buffer) / bpf, GST_BUFFER_TIMESTAMP (buffer));
719 gst_adapter_push (visual->adapter, buffer);
724 guint64 dist, timestamp;
728 GST_DEBUG_OBJECT (visual, "processing buffer");
730 avail = gst_adapter_available (visual->adapter);
731 GST_DEBUG_OBJECT (visual, "avail now %u", avail);
733 /* we need at least VISUAL_SAMPLES samples */
734 if (avail < VISUAL_SAMPLES * bpf)
737 /* we need at least enough samples to make one frame */
738 if (avail < visual->spf * bpf)
741 /* get timestamp of the current adapter byte */
742 timestamp = gst_adapter_prev_timestamp (visual->adapter, &dist);
743 if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
744 /* convert bytes to time */
746 timestamp += gst_util_uint64_scale_int (dist, GST_SECOND, rate);
749 if (timestamp != -1) {
752 /* QoS is done on running time */
753 qostime = gst_segment_to_running_time (&visual->segment, GST_FORMAT_TIME,
755 qostime += visual->duration;
757 GST_OBJECT_LOCK (visual);
758 /* check for QoS, don't compute buffers that are known to be late */
759 need_skip = visual->earliest_time != -1 &&
760 qostime <= visual->earliest_time;
761 GST_OBJECT_UNLOCK (visual);
764 GST_WARNING_OBJECT (visual,
765 "QoS: skip ts: %" GST_TIME_FORMAT ", earliest: %" GST_TIME_FORMAT,
766 GST_TIME_ARGS (qostime), GST_TIME_ARGS (visual->earliest_time));
771 /* Read VISUAL_SAMPLES samples per channel */
773 (const guint16 *) gst_adapter_map (visual->adapter,
774 VISUAL_SAMPLES * bpf);
776 #if defined(VISUAL_API_VERSION) && VISUAL_API_VERSION >= 4000 && VISUAL_API_VERSION < 5000
778 VisBuffer *lbuf, *rbuf;
779 guint16 ldata[VISUAL_SAMPLES], rdata[VISUAL_SAMPLES];
780 VisAudioSampleRateType vrate;
782 lbuf = visual_buffer_new_with_buffer (ldata, sizeof (ldata), NULL);
783 rbuf = visual_buffer_new_with_buffer (rdata, sizeof (rdata), NULL);
786 for (i = 0; i < VISUAL_SAMPLES; i++) {
791 for (i = 0; i < VISUAL_SAMPLES; i++) {
799 vrate = VISUAL_AUDIO_SAMPLE_RATE_8000;
802 vrate = VISUAL_AUDIO_SAMPLE_RATE_11250;
805 vrate = VISUAL_AUDIO_SAMPLE_RATE_22500;
808 vrate = VISUAL_AUDIO_SAMPLE_RATE_32000;
811 vrate = VISUAL_AUDIO_SAMPLE_RATE_44100;
814 vrate = VISUAL_AUDIO_SAMPLE_RATE_48000;
817 vrate = VISUAL_AUDIO_SAMPLE_RATE_96000;
820 visual_object_unref (VISUAL_OBJECT (lbuf));
821 visual_object_unref (VISUAL_OBJECT (rbuf));
822 GST_ERROR_OBJECT (visual, "unsupported rate %d", rate);
823 ret = GST_FLOW_ERROR;
828 visual_audio_samplepool_input_channel (visual->audio->samplepool,
830 vrate, VISUAL_AUDIO_SAMPLE_FORMAT_S16,
831 (char *) VISUAL_AUDIO_CHANNEL_LEFT);
832 visual_audio_samplepool_input_channel (visual->audio->samplepool, rbuf,
833 vrate, VISUAL_AUDIO_SAMPLE_FORMAT_S16,
834 (char *) VISUAL_AUDIO_CHANNEL_RIGHT);
836 visual_object_unref (VISUAL_OBJECT (lbuf));
837 visual_object_unref (VISUAL_OBJECT (rbuf));
841 if (visual->channels == 2) {
842 for (i = 0; i < VISUAL_SAMPLES; i++) {
843 visual->audio->plugpcm[0][i] = *data++;
844 visual->audio->plugpcm[1][i] = *data++;
847 for (i = 0; i < VISUAL_SAMPLES; i++) {
848 visual->audio->plugpcm[0][i] = *data;
849 visual->audio->plugpcm[1][i] = *data++;
854 /* alloc a buffer if we don't have one yet, this happens
855 * when we pushed a buffer in this while loop before */
856 if (outbuf == NULL) {
857 GST_DEBUG_OBJECT (visual, "allocating output buffer");
858 ret = gst_buffer_pool_acquire_buffer (visual->pool, &outbuf, NULL);
859 if (ret != GST_FLOW_OK) {
860 gst_adapter_unmap (visual->adapter);
864 outdata = gst_buffer_map (outbuf, &outsize, NULL, GST_MAP_WRITE);
865 visual_video_set_buffer (visual->video, outdata);
866 visual_audio_analyze (visual->audio);
867 visual_actor_run (visual->actor, visual->audio);
868 visual_video_set_buffer (visual->video, NULL);
869 gst_buffer_unmap (outbuf, outdata, outsize);
870 GST_DEBUG_OBJECT (visual, "rendered one frame");
872 gst_adapter_unmap (visual->adapter);
874 GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
875 GST_BUFFER_DURATION (outbuf) = visual->duration;
877 ret = gst_pad_push (visual->srcpad, outbuf);
881 GST_DEBUG_OBJECT (visual, "finished frame, flushing %u samples from input",
884 /* Flush out the number of samples per frame */
885 gst_adapter_flush (visual->adapter, visual->spf * bpf);
887 /* quit the loop if something was wrong */
888 if (ret != GST_FLOW_OK)
895 gst_buffer_unref (outbuf);
897 gst_object_unref (visual);
902 static GstStateChangeReturn
903 gst_visual_change_state (GstElement * element, GstStateChange transition)
905 GstVisual *visual = GST_VISUAL (element);
906 GstStateChangeReturn ret;
908 switch (transition) {
909 case GST_STATE_CHANGE_NULL_TO_READY:
911 visual_actor_new (GST_VISUAL_GET_CLASS (visual)->plugin->info->
913 visual->video = visual_video_new ();
914 visual->audio = visual_audio_new ();
915 /* can't have a play without actors */
916 if (!visual->actor || !visual->video)
919 if (visual_actor_realize (visual->actor) != 0)
922 visual_actor_set_video (visual->actor, visual->video);
924 case GST_STATE_CHANGE_READY_TO_PAUSED:
925 gst_visual_reset (visual);
927 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
933 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
935 switch (transition) {
936 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
938 case GST_STATE_CHANGE_PAUSED_TO_READY:
940 gst_buffer_pool_set_active (visual->pool, FALSE);
941 gst_object_unref (visual->pool);
945 case GST_STATE_CHANGE_READY_TO_NULL:
946 gst_visual_clear_actors (visual);
957 GST_ELEMENT_ERROR (visual, LIBRARY, INIT, (NULL),
958 ("could not create actors"));
959 gst_visual_clear_actors (visual);
960 return GST_STATE_CHANGE_FAILURE;
964 GST_ELEMENT_ERROR (visual, LIBRARY, INIT, (NULL),
965 ("could not realize actor"));
966 gst_visual_clear_actors (visual);
967 return GST_STATE_CHANGE_FAILURE;
972 make_valid_name (char *name)
975 * Replace invalid chars with _ in the type name
977 static const gchar extra_chars[] = "-_+";
981 int valid = ((p[0] >= 'A' && p[0] <= 'Z') ||
982 (p[0] >= 'a' && p[0] <= 'z') ||
983 (p[0] >= '0' && p[0] <= '9') || strchr (extra_chars, p[0]));
990 gst_visual_actor_plugin_is_gl (VisObject * plugin, const gchar * name)
995 #if !defined(VISUAL_API_VERSION)
997 depth = VISUAL_PLUGIN_ACTOR (plugin)->depth;
998 is_gl = (depth == VISUAL_VIDEO_DEPTH_GL);
1000 #elif VISUAL_API_VERSION >= 4000 && VISUAL_API_VERSION < 5000
1002 depth = VISUAL_ACTOR_PLUGIN (plugin)->vidoptions.depth;
1003 /* FIXME: how to figure this out correctly in 0.4? */
1004 is_gl = (depth & VISUAL_VIDEO_DEPTH_GL) == VISUAL_VIDEO_DEPTH_GL;
1007 # error what libvisual version is this?
1011 GST_DEBUG ("plugin %s is not a GL plugin (%d), registering", name, depth);
1013 GST_DEBUG ("plugin %s is a GL plugin (%d), ignoring", name, depth);
1020 plugin_init (GstPlugin * plugin)
1025 GST_DEBUG_CATEGORY_INIT (libvisual_debug, "libvisual", 0,
1026 "libvisual audio visualisations");
1028 #ifdef LIBVISUAL_PLUGINSBASEDIR
1029 gst_plugin_add_dependency_simple (plugin, "HOME/.libvisual/actor",
1030 LIBVISUAL_PLUGINSBASEDIR "/actor", NULL, GST_PLUGIN_DEPENDENCY_FLAG_NONE);
1033 visual_log_set_verboseness (VISUAL_LOG_VERBOSENESS_LOW);
1034 visual_log_set_info_handler (libvisual_log_handler, (void *) GST_LEVEL_INFO);
1035 visual_log_set_warning_handler (libvisual_log_handler,
1036 (void *) GST_LEVEL_WARNING);
1037 visual_log_set_critical_handler (libvisual_log_handler,
1038 (void *) GST_LEVEL_ERROR);
1039 visual_log_set_error_handler (libvisual_log_handler,
1040 (void *) GST_LEVEL_ERROR);
1042 if (!visual_is_initialized ())
1043 if (visual_init (NULL, NULL) != 0)
1046 list = visual_actor_get_list ();
1048 #if !defined(VISUAL_API_VERSION)
1049 count = visual_list_count (list);
1050 #elif VISUAL_API_VERSION >= 4000 && VISUAL_API_VERSION < 5000
1051 count = visual_collection_size (VISUAL_COLLECTION (list));
1054 for (i = 0; i < count; i++) {
1055 VisPluginRef *ref = visual_list_get (list, i);
1056 VisPluginData *visplugin = NULL;
1057 gboolean skip = FALSE;
1061 sizeof (GstVisualClass),
1064 gst_visual_class_init,
1072 visplugin = visual_plugin_load (ref);
1074 if (ref->info->plugname == NULL)
1077 /* Blacklist some plugins */
1078 if (strcmp (ref->info->plugname, "gstreamer") == 0 ||
1079 strcmp (ref->info->plugname, "gdkpixbuf") == 0) {
1082 /* Ignore plugins that only support GL output for now */
1083 skip = gst_visual_actor_plugin_is_gl (visplugin->info->plugin,
1084 visplugin->info->plugname);
1087 visual_plugin_unload (visplugin);
1090 name = g_strdup_printf ("GstVisual%s", ref->info->plugname);
1091 make_valid_name (name);
1092 type = g_type_register_static (GST_TYPE_VISUAL, name, &info, 0);
1095 name = g_strdup_printf ("libvisual_%s", ref->info->plugname);
1096 make_valid_name (name);
1097 if (!gst_element_register (plugin, name, GST_RANK_NONE, type)) {
1108 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
1111 "libvisual visualization plugins",
1112 plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)