2 * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
7 #include "emotion_private.h"
8 #include "emotion_gstreamer.h"
9 #include "emotion_gstreamer_pipeline.h"
13 emotion_pipeline_pause(GstElement *pipeline)
15 GstStateChangeReturn res;
17 res = gst_element_set_state((pipeline), GST_STATE_PAUSED);
18 if (res == GST_STATE_CHANGE_FAILURE)
20 g_print("Emotion-Gstreamer ERROR: could not pause\n");
24 res = gst_element_get_state((pipeline), NULL, NULL, GST_CLOCK_TIME_NONE);
25 if (res != GST_STATE_CHANGE_SUCCESS)
27 g_print("Emotion-Gstreamer ERROR: could not complete pause\n");
34 /* Send the video frame to the evas object */
36 cb_handoff(GstElement *fakesrc,
44 Emotion_Gstreamer_Video *ev = (Emotion_Gstreamer_Video *)user_data;
51 ev->obj_data = malloc(GST_BUFFER_SIZE(buffer) * sizeof(void));
53 memcpy(ev->obj_data, GST_BUFFER_DATA(buffer), GST_BUFFER_SIZE(buffer));
54 buf[0] = GST_BUFFER_DATA(buffer);
56 ecore_pipe_write(ev->pipe, buf, sizeof(buf));
60 Emotion_Audio_Sink *asink;
61 asink = (Emotion_Audio_Sink *)eina_list_nth(ev->audio_sinks, ev->audio_sink_nbr);
62 _emotion_video_pos_update(ev->obj, ev->position, asink->length_time);
65 query = gst_query_new_position(GST_FORMAT_TIME);
66 if (gst_pad_query(gst_pad_get_peer(pad), query))
70 gst_query_parse_position(query, NULL, &position);
71 ev->position = (double)position / (double)GST_SECOND;
73 gst_query_unref(query);
77 file_new_decoded_pad_cb(GstElement *decodebin,
82 Emotion_Gstreamer_Video *ev;
87 ev = (Emotion_Gstreamer_Video *)user_data;
88 caps = gst_pad_get_caps(new_pad);
89 str = gst_caps_to_string(caps);
91 if (g_str_has_prefix(str, "video/"))
93 Emotion_Video_Sink *vsink;
97 vsink = (Emotion_Video_Sink *)calloc(1, sizeof(Emotion_Video_Sink));
99 ev->video_sinks = eina_list_append(ev->video_sinks, vsink);
100 if (!eina_list_data_find(ev->video_sinks, vsink))
106 queue = gst_element_factory_make("queue", NULL);
107 vsink->sink = gst_element_factory_make("fakesink", "videosink");
108 gst_bin_add_many(GST_BIN(ev->pipeline), queue, vsink->sink, NULL);
109 gst_element_link(queue, vsink->sink);
110 videopad = gst_element_get_pad(queue, "sink");
111 gst_pad_link(new_pad, videopad);
112 gst_object_unref(videopad);
113 if (eina_list_count(ev->video_sinks) == 1)
115 ev->ratio = (double)vsink->width / (double)vsink->height;
117 gst_element_set_state(queue, GST_STATE_PAUSED);
118 gst_element_set_state(vsink->sink, GST_STATE_PAUSED);
121 else if (g_str_has_prefix(str, "audio/"))
123 Emotion_Audio_Sink *asink;
126 asink = (Emotion_Audio_Sink *)calloc(1, sizeof(Emotion_Audio_Sink));
128 ev->audio_sinks = eina_list_append(ev->audio_sinks, asink);
129 if (!eina_list_data_find(ev->audio_sinks, asink))
135 for (index = 0; asink != eina_list_nth(ev->audio_sinks, index); index++)
137 asink->sink = emotion_audio_sink_create(ev, index);
138 gst_bin_add(GST_BIN(ev->pipeline), asink->sink);
139 audiopad = gst_element_get_pad(asink->sink, "sink");
140 gst_pad_link(new_pad, audiopad);
141 gst_element_set_state(asink->sink, GST_STATE_PAUSED);
148 emotion_video_sink_new(Emotion_Gstreamer_Video *ev)
150 Emotion_Video_Sink *vsink;
152 if (!ev) return NULL;
154 vsink = (Emotion_Video_Sink *)calloc(1, sizeof(Emotion_Video_Sink));
155 if (!vsink) return NULL;
157 ev->video_sinks = eina_list_append(ev->video_sinks, vsink);
158 if (!eina_list_data_find(ev->video_sinks, vsink))
167 emotion_video_sink_free(Emotion_Gstreamer_Video *ev, Emotion_Video_Sink *vsink)
169 if (!ev || !vsink) return;
171 ev->video_sinks = eina_list_remove(ev->video_sinks, vsink);
176 emotion_visualization_sink_create(Emotion_Gstreamer_Video *ev, Emotion_Audio_Sink *asink)
178 Emotion_Video_Sink *vsink;
180 if (!ev) return NULL;
182 vsink = emotion_video_sink_new(ev);
183 if (!vsink) return NULL;
185 vsink->sink = gst_bin_get_by_name(GST_BIN(asink->sink), "vissink1");
188 emotion_video_sink_free(ev, vsink);
193 ev->ratio = (double)vsink->width / (double)vsink->height;
196 vsink->fourcc = GST_MAKE_FOURCC('A', 'R', 'G', 'B');
197 vsink->length_time = asink->length_time;
199 g_object_set(G_OBJECT(vsink->sink), "sync", TRUE, NULL);
200 g_object_set(G_OBJECT(vsink->sink), "signal-handoffs", TRUE, NULL);
201 g_signal_connect(G_OBJECT(vsink->sink),
203 G_CALLBACK(cb_handoff), ev);
208 emotion_pipeline_cdda_track_count_get(void *video)
210 Emotion_Gstreamer_Video *ev;
212 guint tracks_count = 0;
215 ev = (Emotion_Gstreamer_Video *)video;
216 if (!ev) return tracks_count;
219 bus = gst_element_get_bus(ev->pipeline);
220 if (!bus) return tracks_count;
226 message = gst_bus_pop(bus);
228 /* All messages read, we're done */
231 switch (GST_MESSAGE_TYPE(message))
233 case GST_MESSAGE_TAG:
237 gst_message_parse_tag(message, &tags);
239 gst_tag_list_get_uint(tags, GST_TAG_TRACK_COUNT, &tracks_count);
240 if (tracks_count) done = TRUE;
243 case GST_MESSAGE_ERROR:
247 gst_message_unref(message);
250 gst_object_unref(GST_OBJECT(bus));
256 emotion_visualization_element_name_get(Emotion_Vis visualisation)
258 switch (visualisation)
260 case EMOTION_VIS_NONE:
262 case EMOTION_VIS_GOOM:
264 case EMOTION_VIS_LIBVISUAL_BUMPSCOPE:
265 return "libvisual_bumpscope";
266 case EMOTION_VIS_LIBVISUAL_CORONA:
267 return "libvisual_corona";
268 case EMOTION_VIS_LIBVISUAL_DANCING_PARTICLES:
269 return "libvisual_dancingparticles";
270 case EMOTION_VIS_LIBVISUAL_GDKPIXBUF:
271 return "libvisual_gdkpixbuf";
272 case EMOTION_VIS_LIBVISUAL_G_FORCE:
273 return "libvisual_G-Force";
274 case EMOTION_VIS_LIBVISUAL_GOOM:
275 return "libvisual_goom";
276 case EMOTION_VIS_LIBVISUAL_INFINITE:
277 return "libvisual_infinite";
278 case EMOTION_VIS_LIBVISUAL_JAKDAW:
279 return "libvisual_jakdaw";
280 case EMOTION_VIS_LIBVISUAL_JESS:
281 return "libvisual_jess";
282 case EMOTION_VIS_LIBVISUAL_LV_ANALYSER:
283 return "libvisual_lv_analyzer";
284 case EMOTION_VIS_LIBVISUAL_LV_FLOWER:
285 return "libvisual_lv_flower";
286 case EMOTION_VIS_LIBVISUAL_LV_GLTEST:
287 return "libvisual_lv_gltest";
288 case EMOTION_VIS_LIBVISUAL_LV_SCOPE:
289 return "libvisual_lv_scope";
290 case EMOTION_VIS_LIBVISUAL_MADSPIN:
291 return "libvisual_madspin";
292 case EMOTION_VIS_LIBVISUAL_NEBULUS:
293 return "libvisual_nebulus";
294 case EMOTION_VIS_LIBVISUAL_OINKSIE:
295 return "libvisual_oinksie";
296 case EMOTION_VIS_LIBVISUAL_PLASMA:
297 return "libvisual_plazma";
304 emotion_visualization_bin_create(Emotion_Gstreamer_Video *ev, int index)
306 const char *vis_name;
308 GstElement *vis, *visbin, *queue, *conv, *cspace, *sink;
312 if (ev->vis == EMOTION_VIS_NONE)
315 vis_name = emotion_visualization_element_name_get(ev->vis);
319 g_snprintf(buf, sizeof(buf), "vis%d", index);
320 vis = gst_element_factory_make(vis_name, buf);
324 g_snprintf(buf, sizeof(buf), "visbin%d", index);
325 visbin = gst_bin_new(buf);
327 queue = gst_element_factory_make("queue", NULL);
328 conv = gst_element_factory_make("audioconvert", NULL);
329 cspace = gst_element_factory_make("ffmpegcolorspace", NULL);
330 g_snprintf(buf, sizeof(buf), "vissink%d", index);
331 sink = gst_element_factory_make("fakesink", buf);
333 if ((!visbin) || (!queue) || (!conv) || (!cspace) || (!sink))
336 gst_bin_add_many(GST_BIN(visbin), queue, conv, vis, cspace, sink, NULL);
337 gst_element_link_many(queue, conv, vis, cspace, NULL);
338 caps = gst_caps_new_simple("video/x-raw-rgb",
339 "bpp", G_TYPE_INT, 32,
340 "width", G_TYPE_INT, 320,
341 "height", G_TYPE_INT, 200,
343 gst_element_link_filtered(cspace, sink, caps);
345 vispad = gst_element_get_pad(queue, "sink");
346 gst_element_add_pad(visbin, gst_ghost_pad_new("sink", vispad));
347 gst_object_unref(vispad);
353 gst_object_unref(vis);
355 gst_object_unref(visbin);
357 gst_object_unref(queue);
359 gst_object_unref(conv);
361 gst_object_unref(cspace);
363 gst_object_unref(sink);
369 emotion_audio_bin_create(Emotion_Gstreamer_Video *ev, int index)
371 GstElement *audiobin, *queue, *conv, *resample, *volume, *sink;
375 audiobin = gst_bin_new(NULL);
376 queue = gst_element_factory_make("queue", NULL);
377 conv = gst_element_factory_make("audioconvert", NULL);
378 resample = gst_element_factory_make("audioresample", NULL);
379 volume = gst_element_factory_make("volume", "volume");
382 sink = gst_element_factory_make("autoaudiosink", NULL);
384 /* XXX hack: use a proper mixer element here */
385 sink = gst_element_factory_make("fakesink", NULL);
387 if ((!audiobin) || (!queue) || (!conv) || (!resample) || (!volume) || (!sink))
390 g_object_get(volume, "volume", &vol, NULL);
393 gst_bin_add_many(GST_BIN(audiobin),
394 queue, conv, resample, volume, sink, NULL);
395 gst_element_link_many(queue, conv, resample, volume, sink, NULL);
397 audiopad = gst_element_get_pad(queue, "sink");
398 gst_element_add_pad(audiobin, gst_ghost_pad_new("sink", audiopad));
399 gst_object_unref(audiopad);
405 gst_object_unref(audiobin);
407 gst_object_unref(queue);
409 gst_object_unref(conv);
411 gst_object_unref(resample);
413 gst_object_unref(volume);
415 gst_object_unref(sink);
422 emotion_audio_sink_create(Emotion_Gstreamer_Video *ev, int index)
426 GstElement *audiobin;
427 GstElement *visbin = NULL;
432 audiobin = emotion_audio_bin_create(ev, index);
436 bin = gst_bin_new(NULL);
439 gst_object_unref(audiobin);
443 g_snprintf(buf, 128, "tee%d", index);
444 tee = gst_element_factory_make("tee", buf);
446 visbin = emotion_visualization_bin_create(ev, index);
448 gst_bin_add_many(GST_BIN(bin), tee, audiobin, visbin, NULL);
450 binpad = gst_element_get_pad(audiobin, "sink");
451 teepad = gst_element_get_request_pad(tee, "src%d");
452 gst_pad_link(teepad, binpad);
453 gst_object_unref(teepad);
454 gst_object_unref(binpad);
458 binpad = gst_element_get_pad(visbin, "sink");
459 teepad = gst_element_get_request_pad(tee, "src%d");
460 gst_pad_link(teepad, binpad);
461 gst_object_unref(teepad);
462 gst_object_unref(binpad);
465 teepad = gst_element_get_pad(tee, "sink");
466 gst_element_add_pad(bin, gst_ghost_pad_new("sink", teepad));
467 gst_object_unref(teepad);
473 emotion_streams_sinks_get(Emotion_Gstreamer_Video *ev, GstElement *decoder)
480 alist = ev->audio_sinks;
481 vlist = ev->video_sinks;
483 it = gst_element_iterate_src_pads(decoder);
484 while (gst_iterator_next(it, &data) == GST_ITERATOR_OK)
492 caps = gst_pad_get_caps(pad);
493 str = gst_caps_to_string(caps);
494 g_print("caps !! %s\n", str);
497 if (g_str_has_prefix(str, "video/"))
499 Emotion_Video_Sink *vsink;
501 vsink = (Emotion_Video_Sink *)eina_list_data_get(vlist);
502 vlist = eina_list_next(vlist);
504 emotion_video_sink_fill(vsink, pad, caps);
507 else if (g_str_has_prefix(str, "audio/"))
509 Emotion_Audio_Sink *asink;
512 asink = (Emotion_Audio_Sink *)eina_list_data_get(alist);
513 alist = eina_list_next(alist);
515 emotion_audio_sink_fill(asink, pad, caps);
517 for (index = 0; asink != eina_list_nth(ev->audio_sinks, index) ; index++)
520 if (eina_list_count(ev->video_sinks) == 0)
524 Emotion_Video_Sink *vsink;
526 vsink = emotion_visualization_sink_create(ev, asink);
527 if (!vsink) goto finalize;
535 g_snprintf(buf, 128, "visbin%d", index);
536 visbin = gst_bin_get_by_name(GST_BIN(ev->pipeline), buf);
542 sinkpad = gst_element_get_pad(visbin, "sink");
543 srcpad = gst_pad_get_peer(sinkpad);
544 gst_pad_unlink(srcpad, sinkpad);
546 gst_object_unref(srcpad);
547 gst_object_unref(sinkpad);
552 gst_caps_unref(caps);
554 gst_object_unref(pad);
556 gst_iterator_free(it);
560 emotion_video_sink_fill(Emotion_Video_Sink *vsink, GstPad *pad, GstCaps *caps)
562 GstStructure *structure;
567 structure = gst_caps_get_structure(caps, 0);
568 str = gst_caps_to_string(caps);
570 gst_structure_get_int(structure, "width", &vsink->width);
571 gst_structure_get_int(structure, "height", &vsink->height);
575 val = gst_structure_get_value(structure, "framerate");
578 vsink->fps_num = gst_value_get_fraction_numerator(val);
579 vsink->fps_den = gst_value_get_fraction_denominator(val);
581 if (g_str_has_prefix(str, "video/x-raw-yuv"))
583 val = gst_structure_get_value(structure, "format");
584 vsink->fourcc = gst_value_get_fourcc(val);
586 else if (g_str_has_prefix(str, "video/x-raw-rgb"))
587 vsink->fourcc = GST_MAKE_FOURCC('A', 'R', 'G', 'B');
591 query = gst_query_new_duration(GST_FORMAT_TIME);
592 if (gst_pad_query(pad, query))
596 gst_query_parse_duration(query, NULL, &time);
597 vsink->length_time = (double)time / (double)GST_SECOND;
600 gst_query_unref(query);
604 emotion_audio_sink_fill(Emotion_Audio_Sink *asink, GstPad *pad, GstCaps *caps)
606 GstStructure *structure;
609 structure = gst_caps_get_structure(caps, 0);
611 gst_structure_get_int(structure, "channels", &asink->channels);
612 gst_structure_get_int(structure, "rate", &asink->samplerate);
614 query = gst_query_new_duration(GST_FORMAT_TIME);
615 if (gst_pad_query(pad, query))
619 gst_query_parse_duration(query, NULL, &time);
620 asink->length_time = (double)time / (double)GST_SECOND;
622 gst_query_unref(query);