[svn r653] Some new tests: stringlist and LiveTV Monitor Handler.
12 #include "gmencoder.h"
14 #define G_MENCODER_GET_PRIVATE(obj) \
15 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), G_TYPE_MENCODER, GMencoderPrivate))
17 //#define SUPPORT_MULT_INPUT 0
19 typedef struct _GMencoderPrivate GMencoderPrivate;
20 typedef struct _SetupInfo SetupInfo;
26 gchar** video_encode_prop;
32 gchar** audio_encode_prop;
37 struct _GMencoderPrivate
60 static void g_mencoder_class_init (GMencoderClass *klass);
61 static void g_mencoder_init (GMencoder *object);
62 static void g_mencoder_dispose (GObject *object);
63 static void g_mencoder_finalize (GObject *object);
65 _create_audio_bin (const gchar* encode,
69 _create_video_bin (const gchar* encode,
77 _pipeline_bus_cb (GstBus *bus,
80 static void _decodebin_new_pad_cb (GstElement* object,
84 static void _decodebin_unknown_type_cb (GstElement* object,
88 static void _close_output (GMencoder *self);
89 static void _open_output (GMencoder *self,
91 static GstElement* _create_source (const gchar* uri);
92 static GstElement*_create_pipeline (GMencoder *self,
93 const gchar* video_encode,
94 const gchar* mux_name,
95 gchar** video_encode_prop,
100 const gchar* audio_encode,
101 gchar** audio_encode_prop,
108 static guint g_mencoder_signals[LAST_SIGNAL] = { 0 };
110 G_DEFINE_TYPE(GMencoder, g_mencoder, G_TYPE_OBJECT)
113 g_mencoder_class_init (GMencoderClass *klass)
115 GObjectClass *object_class;
117 object_class = (GObjectClass *) klass;
119 g_type_class_add_private (klass, sizeof (GMencoderPrivate));
121 object_class->dispose = g_mencoder_dispose;
122 object_class->finalize = g_mencoder_finalize;
124 g_mencoder_signals[PAUSED] =
125 g_signal_new ("paused",
126 G_OBJECT_CLASS_TYPE (object_class),
129 g_cclosure_marshal_VOID__VOID,
132 g_mencoder_signals[PLAYING] =
133 g_signal_new ("playing",
134 G_OBJECT_CLASS_TYPE (object_class),
137 g_cclosure_marshal_VOID__VOID,
140 g_mencoder_signals[STOPED] =
141 g_signal_new ("stoped",
142 G_OBJECT_CLASS_TYPE (object_class),
145 g_cclosure_marshal_VOID__VOID,
148 g_mencoder_signals[EOS] =
150 G_OBJECT_CLASS_TYPE (object_class),
153 g_cclosure_marshal_VOID__VOID,
157 g_mencoder_signals[ERROR] =
158 g_signal_new ("error",
159 G_OBJECT_CLASS_TYPE (object_class),
162 g_cclosure_marshal_VOID__STRING,
163 G_TYPE_NONE, 1, G_TYPE_STRING);
167 g_mencoder_init (GMencoder *self)
169 GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
170 priv->info = g_new0 (SetupInfo, 1);
174 g_mencoder_dispose (GObject *object)
179 g_mencoder_finalize (GObject *object)
182 g_mencoder_close_stream (G_MENCODER (object));
186 g_mencoder_new (void)
188 return g_object_new (G_TYPE_MENCODER, NULL);
193 _obj_set_prop (GObject *obj,
194 const gchar *prop_name,
195 const gchar *prop_val)
199 GParamSpec *s = NULL;
200 GObjectClass *k = G_OBJECT_GET_CLASS (obj);
203 g_value_init (&v, G_TYPE_STRING);
204 g_value_set_string (&v, prop_val);
206 s = g_object_class_find_property (k, prop_name);
208 g_print ("Invalid property name: %s\n", prop_name);
212 g_value_init (&p, s->value_type);
213 switch (s->value_type)
216 g_value_set_int (&p, atoi (prop_val));
219 g_value_set_string (&p, prop_val);
225 g_object_set_property (obj, prop_name, &p);
231 _create_element_with_prop (const gchar* factory_name,
232 const gchar* element_name,
238 g_debug ("Creating element: %s", factory_name);
240 ret = gst_element_factory_make (factory_name, element_name);
245 for (i=0; i < g_strv_length (prop); i++) {
246 char** v = g_strsplit(prop[i], "=", 2);
247 if (g_strv_length (v) == 2) {
248 _obj_set_prop (G_OBJECT (ret), v[0], v[1]);
259 _create_audio_bin (const gchar* encode,
263 GstElement *abin = NULL;
264 GstElement *aqueue = NULL;
265 GstElement *aconvert = NULL;
266 GstElement *aencode = NULL;
267 GstElement *aqueue_src = NULL;
270 //audio/x-raw-int ! queue ! audioconvert ! faac ! rtpmp4gpay ! udpsink name=upd_audio host=224.0.0.1 port=5002
271 abin = gst_bin_new ("abin");
272 aqueue = gst_element_factory_make ("queue", "aqueue");
273 aconvert= gst_element_factory_make ("audioconvert", "aconvert");
274 aencode = _create_element_with_prop ((encode ? encode : "lame"), "aencode", encode_prop);
275 aqueue_src= gst_element_factory_make ("queue", "aqueue_src");
277 if ((abin == NULL) || (aqueue == NULL) || (aconvert == NULL)
278 || (aencode == NULL) || (aqueue_src == NULL)) {
279 g_warning ("Audio elements not found");
283 g_object_set (G_OBJECT (aencode), "bitrate", 32, NULL);
286 g_object_set (G_OBJECT (aencode), "bitrate", 32, NULL);
290 gst_bin_add_many (GST_BIN (abin), aqueue, aconvert, aencode, aqueue_src, NULL);
291 if (gst_element_link_many (aqueue, aconvert, aencode, aqueue_src, NULL) == FALSE) {
292 g_warning ("Not Link audio elements");
295 //TODO: apply audio rate
297 // ghost pad the audio bin
298 apad = gst_element_get_pad (aqueue, "sink");
299 gst_element_add_pad (abin, gst_ghost_pad_new("sink", apad));
300 gst_object_unref (apad);
302 apad = gst_element_get_pad (aqueue_src, "src");
303 gst_element_add_pad (abin, gst_ghost_pad_new("src", apad));
304 gst_object_unref (apad);
309 gst_object_unref (abin);
312 gst_object_unref (aqueue);
314 if (aconvert != NULL)
315 gst_object_unref (aconvert);
318 gst_object_unref (aencode);
320 if (aqueue_src != NULL)
321 gst_object_unref (aqueue_src);
324 gst_object_unref (apad);
332 //queue ! videoscale ! video/x-raw-yuv,width=240,height=144 ! colorspace ! rate ! encode ! queue
334 _create_video_bin (const gchar* encode,
341 GstElement *vbin = NULL;
342 GstElement *vqueue = NULL;
343 GstElement* vqueue_src = NULL;
344 GstElement *vcolorspace = NULL;
345 GstElement *vencode = NULL;
346 GstElement *vrate = NULL;
349 vbin = gst_bin_new ("vbin");
350 vqueue = gst_element_factory_make ("queue", "vqueue");
351 vcolorspace = gst_element_factory_make ("ffmpegcolorspace", "colorspace");
353 vencode = _create_element_with_prop (
354 (encode != NULL ? encode : "ffenc_mpeg1video"),
355 "vencode", encode_prop);
356 vqueue_src = gst_element_factory_make ("queue", "queue_src");
358 if ((vbin == NULL) || (vqueue == NULL) || (vcolorspace == NULL)
359 || (vencode == NULL) || (vqueue_src == NULL)) {
360 g_warning ("Video elements not found");
364 gst_bin_add_many (GST_BIN (vbin), vqueue, vcolorspace, vencode, vqueue_src, NULL);
367 if ((width > 0) && (height > 0)) {
370 GstElement *vscale = gst_element_factory_make ("videoscale", "vscale");
372 gst_bin_add (GST_BIN (vbin), vscale);
374 vcaps = gst_caps_new_simple ("video/x-raw-yuv",
375 "width", G_TYPE_INT, width,
376 "height", G_TYPE_INT, height,
379 gst_element_link (vqueue, vscale);
381 if (gst_element_link_filtered (vscale, vcolorspace, vcaps) == FALSE) {
382 g_warning ("Fail to resize video");
383 gst_object_unref (vcaps);
384 gst_object_unref (vscale);
387 gst_caps_unref (vcaps);
389 gst_element_link (vqueue, vcolorspace);
394 //Changing the video fps
396 vrate = gst_element_factory_make ("videorate", "vrate");
398 g_debug ("Setting FPS: %.2f", fps);
399 gst_bin_add (GST_BIN (vbin), vrate);
401 if (gst_element_link (vcolorspace, vrate) == FALSE) {
402 g_warning ("Fail to link video elements");
406 vcaps = gst_caps_new_simple ("video/x-raw-yuv",
407 "framerate", GST_TYPE_FRACTION, (int) (fps * 1000), 1000, NULL);
409 if (gst_element_link_filtered (vrate, vencode, vcaps) == FALSE) {
410 g_warning ("Fail to link vrate with vencode.");
413 gst_caps_unref (vcaps);
415 if (gst_element_link (vcolorspace, vencode) == FALSE) {
416 g_warning ("Fail to link colorspace and video encode element.");
421 gst_element_link (vencode, vqueue_src);
423 // ghost pad the video bin
424 vpad = gst_element_get_pad (vqueue, "sink");
425 gst_element_add_pad (vbin, gst_ghost_pad_new ("sink", vpad));
426 gst_object_unref (vpad);
428 vpad = gst_element_get_pad (vqueue_src, "src");
429 gst_element_add_pad (vbin, gst_ghost_pad_new ("src", vpad));
430 gst_object_unref (vpad);
436 gst_object_unref (vpad);
439 gst_object_unref (vbin);
442 gst_object_unref (vqueue);
445 gst_object_unref (vencode);
447 if (vqueue_src != NULL)
448 gst_object_unref (vqueue_src);
450 if (vcolorspace != NULL)
451 gst_object_unref (vcolorspace);
459 g_mencoder_setup_stream (GMencoder *self,
460 const gchar* mux_name,
461 const gchar* video_encode,
462 gchar** video_encode_prop,
467 const gchar* audio_encode,
468 gchar** audio_encode_prop,
470 const gchar* out_uri)
472 GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
473 if (priv->ready == TRUE) {
474 g_warning ("Stream already configured. You need close stream first.");
478 _close_output (self);
479 _open_output (self, out_uri);
482 priv->pipe = _create_pipeline (self,
498 g_mencoder_append_uri (GMencoder *self,
504 GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
505 gboolean ret = FALSE;
506 GstElement *ap = NULL;
507 GstElement *vp = NULL;
510 g_return_val_if_fail (priv->pipe != NULL, FALSE);
511 g_return_val_if_fail (priv->ready == FALSE, FALSE);
513 #ifndef SUPPORT_MULT_INPUT
514 g_return_val_if_fail (priv->sources < 1, FALSE);
517 src = _create_source (uri);
521 gst_bin_add (GST_BIN (priv->pipe), src);
523 #ifdef SUPPORT_MULT_INPUT
524 ap = gst_bin_get_by_name (GST_BIN (priv->pipe), "ap");
525 vp = gst_bin_get_by_name (GST_BIN (priv->pipe), "vp");
527 ap = gst_bin_get_by_name (GST_BIN (priv->pipe), "abin");
528 vp = gst_bin_get_by_name (GST_BIN (priv->pipe), "vbin");
531 if ((vp == NULL) || (ap == NULL)) {
532 g_warning ("Fail to get output bin");
536 pad_src = gst_element_get_pad (src, "src_audio");
537 pad_sink = gst_element_get_compatible_pad (ap,
539 gst_pad_get_caps (pad_src));
541 if ((pad_sink == NULL) || (pad_src == NULL))
544 GstPadLinkReturn lret = gst_pad_link (pad_src, pad_sink);
545 if (lret != GST_PAD_LINK_OK)
548 gst_object_unref (pad_src);
549 gst_object_unref (pad_sink);
551 pad_src = gst_element_get_pad (src, "src_video");
552 pad_sink = gst_element_get_compatible_pad (vp,
554 gst_pad_get_caps (pad_src));
556 if ((pad_src == NULL) || (pad_sink == NULL))
559 if (gst_pad_link (pad_src, pad_sink) != GST_PAD_LINK_OK) {
560 g_warning ("invalid source. video");
566 g_debug ("Uri: [%s] OK ", uri);
569 if ((src != NULL) && (ret == FALSE)) {
570 gst_bin_remove (GST_BIN (priv->pipe), src);
571 gst_object_unref (src);
575 gst_object_unref (ap);
578 gst_object_unref (vp);
581 gst_object_unref (pad_src);
583 if (pad_sink != NULL)
584 gst_object_unref (pad_sink);
592 g_mencoder_remove_uri (GMencoder *self,
595 // GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
600 g_mencoder_play_stream (GMencoder *self)
602 GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
604 g_return_if_fail (priv->ready == FALSE);
606 gst_element_set_state (priv->pipe, GST_STATE_PLAYING);
610 g_mencoder_pause_stream (GMencoder *self)
612 GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
614 g_return_if_fail (priv->ready == TRUE);
615 gst_element_set_state (priv->pipe, GST_STATE_PAUSED);
619 g_mencoder_close_stream (GMencoder *self)
622 GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
624 g_debug ("g_mencoder_close_stream");
625 if (priv->pipe != NULL) {
626 gst_element_set_state (priv->pipe, GST_STATE_NULL);
627 gst_object_unref (priv->pipe);
637 _create_pipeline (GMencoder *self,
638 const gchar* video_encode,
639 const gchar* mux_name,
640 gchar** video_encode_prop,
645 const gchar* audio_encode,
646 gchar** audio_encode_prop,
650 GstElement *pipe = NULL;
651 GstElement *sink = NULL;
652 GstElement *mux = NULL;
653 GstElement *abin = NULL;
654 GstElement *vbin = NULL;
655 GstPad *aux_pad = NULL;
656 GstPad *mux_pad = NULL;
657 #ifdef SUPPORT_MULT_INPUT
658 GstElement *ap = NULL;
659 GstElement *vp = NULL;
661 GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
663 pipe = gst_pipeline_new ("pipe");
665 #ifdef SUPPORT_MULT_INPUT
666 ap = gst_element_factory_make ("concatmux", "ap");
667 vp = gst_element_factory_make ("concatmux", "vp");
668 gst_bin_add_many (GST_BIN (pipe), ap, vp, NULL);
671 mux = gst_element_factory_make ((mux_name ? mux_name : "ffmux_mpeg"), "mux");
676 sink = gst_element_factory_make ("fdsink", "sink");
680 g_object_set (G_OBJECT(sink),
684 abin = _create_audio_bin (audio_encode, audio_encode_prop, audio_rate);
688 vbin = _create_video_bin (video_encode, video_encode_prop, video_fps, video_rate, video_width, video_height);
693 gst_bin_add_many (GST_BIN (pipe), abin, vbin, mux, sink, NULL);
696 #ifdef SUPPORT_MULT_INPUT
697 if (gst_element_link (ap, abin) == FALSE) {
698 g_warning ("Fail to link concat and abin");
702 if (gst_element_link (vp, vbin) == FALSE) {
703 g_warning ("Fail to link concat and vbin");
708 aux_pad = gst_element_get_pad (abin, "src");
709 mux_pad = gst_element_get_compatible_pad (mux, aux_pad, GST_PAD_CAPS (aux_pad));
710 if (mux_pad == NULL) {
711 g_warning ("Mux element no have audio PAD");
714 GstPadLinkReturn ret = gst_pad_link (aux_pad, mux_pad);
715 if (ret != GST_PAD_LINK_OK) {
716 g_warning ("Fail link audio and mux: %d", ret);
720 gst_object_unref (aux_pad);
721 gst_object_unref (mux_pad);
723 aux_pad = gst_element_get_pad (vbin, "src");
724 mux_pad = gst_element_get_compatible_pad (mux, aux_pad, GST_PAD_CAPS (aux_pad));
725 if (mux_pad == NULL) {
726 g_warning ("Mux element no have video PAD");
729 ret = gst_pad_link (aux_pad, mux_pad);
730 if (ret != GST_PAD_LINK_OK) {
731 g_warning ("Fail link video and mux: %d", ret);
734 gst_object_unref (aux_pad);
735 gst_object_unref (mux_pad);
740 gst_element_link (mux, sink);
742 bus = gst_pipeline_get_bus (GST_PIPELINE (pipe));
743 gst_bus_add_watch (bus, _pipeline_bus_cb, self);
744 gst_object_unref (bus);
748 g_warning ("Invalid uri");
751 gst_object_unref (pipe);
756 gst_object_unref (mux);
759 if (mux_pad != NULL) {
760 gst_object_unref (mux_pad);
763 if (aux_pad != NULL) {
764 gst_object_unref (mux_pad);
768 gst_object_unref (sink);
772 gst_object_unref (abin);
776 gst_object_unref (vbin);
784 _close_output (GMencoder *self)
790 _create_source (const gchar* uri)
801 bsrc = gst_bin_new (NULL);
803 //src = gst_element_factory_make ("gnomevfssrc", "src");
804 //g_object_set (G_OBJECT (src), "location", uri, NULL);
805 src = gst_element_make_from_uri (GST_URI_SRC, uri, "src");
809 decode = gst_element_factory_make ("decodebin2", "decode");
813 aqueue = gst_element_factory_make ("queue", "aqueue");
817 vqueue = gst_element_factory_make ("queue", "vqueue");
821 gst_bin_add_many (GST_BIN (bsrc), src, decode, aqueue, vqueue, NULL);
822 gst_element_link (src, decode);
824 g_signal_connect (G_OBJECT (decode),
826 G_CALLBACK (_decodebin_new_pad_cb),
829 g_signal_connect (G_OBJECT (decode),
831 G_CALLBACK (_decodebin_unknown_type_cb),
834 src_pad = gst_element_get_pad (aqueue, "src");
835 gst_element_add_pad (bsrc, gst_ghost_pad_new("src_audio", src_pad));
836 gst_object_unref (src_pad);
838 src_pad = gst_element_get_pad (vqueue, "src");
839 gst_element_add_pad (bsrc, gst_ghost_pad_new("src_video", src_pad));
840 gst_object_unref (src_pad);
846 gst_object_unref (src);
849 if (decode != NULL) {
850 gst_object_unref (decode);
853 if (aqueue != NULL) {
854 gst_object_unref (aqueue);
857 if (vqueue != NULL) {
858 gst_object_unref (vqueue);
865 _open_output (GMencoder *self,
869 GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
871 i = g_strsplit (uri, "://", 0);
872 if (strcmp (i[0], "fd") == 0) {
873 priv->fd = atoi (i[1]);
874 } else if (strcmp (i[0], "file") == 0) {
875 priv->fd = open (i[1], O_WRONLY | O_CREAT | O_TRUNC);
877 g_warning ("Output uri not supported");
884 _pipeline_bus_cb (GstBus *bus,
888 GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (user_data);
890 switch (GST_MESSAGE_TYPE (msg))
892 case GST_MESSAGE_STATE_CHANGED:
896 GstState pendingstate;
899 gst_message_parse_state_changed (msg, &oldstate,
900 &newstate, &pendingstate);
902 if (pendingstate != GST_STATE_VOID_PENDING)
905 if ((oldstate == GST_STATE_READY) &&
906 (newstate == GST_STATE_PAUSED)) {
908 g_signal_emit (user_data, g_mencoder_signals[PAUSED], 0);
909 } else if ((oldstate == GST_STATE_PAUSED) &&
910 (newstate == GST_STATE_PLAYING)) {
911 g_signal_emit (user_data, g_mencoder_signals[PLAYING], 0);
912 } else if ((oldstate == GST_STATE_READY) &&
913 (newstate == GST_STATE_NULL)) {
914 g_signal_emit (user_data, g_mencoder_signals[STOPED], 0);
918 case GST_MESSAGE_ERROR:
924 gst_message_parse_error (msg, &error, &debug);
925 err_str = g_strdup_printf ("Error [%d] %s (%s)", error->code,
928 g_signal_emit (user_data, g_mencoder_signals[ERROR], 0, err_str);
931 g_clear_error (&error);
936 case GST_MESSAGE_EOS:
938 g_signal_emit (user_data, g_mencoder_signals[EOS], 0);
949 _decodebin_new_pad_cb (GstElement* object,
955 gchar *str_caps = NULL;
956 GstElement *sink_element;
959 caps = gst_pad_get_caps (pad);
960 str_caps = gst_caps_to_string (caps);
961 g_debug ("New pad : %s", str_caps);
962 if (strstr (str_caps, "audio") != NULL) {
963 sink_element = gst_bin_get_by_name (GST_BIN (user_data), "aqueue");
964 } else if (strstr (str_caps, "video") != NULL) {
965 sink_element = gst_bin_get_by_name (GST_BIN (user_data), "vqueue");
967 g_warning ("invalid caps %s", str_caps);
970 sink_pad = gst_element_get_pad (sink_element, "sink");
971 gst_pad_link (pad, sink_pad);
973 gst_object_unref (sink_element);
974 gst_object_unref (sink_pad);
976 gst_caps_unref (caps);
980 _decodebin_unknown_type_cb (GstElement* object,
985 g_warning ("Unknown Type");
986 //priv->ready = FALSE;