2 * arch-tag: Implementation gmencoder engine
4 * Copyright (C) 2007 INdT - Renato Filho <renato.filho@indt.org.br>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
32 #include <sys/types.h>
33 #include <sys/socket.h>
34 #include <libgnomevfs/gnome-vfs.h>
35 #include <gst/interfaces/tuner.h>
37 #include "gmencoder.h"
39 #define G_MENCODER_GET_PRIVATE(obj) \
40 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), G_TYPE_MENCODER, GMencoderPrivate))
42 #define USE_MANUAL_SINK
43 #define GMENCODER_TIMEOUT 10000
45 typedef struct _GMencoderPrivate GMencoderPrivate;
46 typedef struct _SetupInfo SetupInfo;
51 gchar **video_encode_prop;
57 gchar **audio_encode_prop;
62 struct _GMencoderPrivate {
69 GnomeVFSHandle *handle;
78 gboolean send_chunked;
97 static void g_mencoder_class_init(GMencoderClass * klass);
98 static void g_mencoder_init(GMencoder * object);
99 static void g_mencoder_dispose(GObject * object);
100 static void g_mencoder_finalize(GObject * object);
101 static GstElement *_create_audio_bin(const gchar * encode,
102 gchar ** encode_prop, gint rate);
103 static GstElement *_create_video_bin(const gchar * encode,
104 gchar ** encode_prop,
106 gint rate, guint width, guint height,
107 gboolean use_deinterlace);
110 _pipeline_bus_cb(GstBus * bus, GstMessage * msg, gpointer user_data);
112 static void _decodebin_new_pad_cb(GstElement * object,
114 gboolean flag, gpointer user_data);
116 static void _decodebin_unknown_type_cb(GstElement * object,
121 static void _close_output(GMencoder * self);
122 static gboolean _open_output(GMencoder * self, const gchar * uri);
124 static GstElement *_create_source(GMencoder *self, const gchar * uri);
125 static GstElement *_create_pipeline(GMencoder * self,
126 const gchar * video_encode,
127 const gchar * mux_name,
128 gchar ** video_encode_prop,
133 const gchar * audio_encode,
134 gchar ** audio_encode_prop,
136 gboolean deinterlace);
137 static gboolean _process_timeout_cb (gpointer user_data);
138 #ifdef USE_MANUAL_SINK
139 static void _flush_queue (GMencoder *self);
140 static void _buffer_arrive_cb (GstElement* object,
147 static gboolean _tick_cb(gpointer data);
149 static guint g_mencoder_signals[LAST_SIGNAL] = { 0 };
151 G_DEFINE_TYPE(GMencoder, g_mencoder, G_TYPE_OBJECT)
153 static void g_mencoder_class_init(GMencoderClass * klass)
155 GObjectClass *object_class;
156 object_class = (GObjectClass *) klass;
157 g_type_class_add_private(klass, sizeof(GMencoderPrivate));
159 object_class->dispose = g_mencoder_dispose;
160 object_class->finalize = g_mencoder_finalize;
162 g_mencoder_signals[PAUSED] =
163 g_signal_new("paused",
164 G_OBJECT_CLASS_TYPE(object_class),
167 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
169 g_mencoder_signals[PLAYING] =
170 g_signal_new("playing",
171 G_OBJECT_CLASS_TYPE(object_class),
174 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
176 g_mencoder_signals[STOPED] =
177 g_signal_new("stoped",
178 G_OBJECT_CLASS_TYPE(object_class),
181 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
183 g_mencoder_signals[EOS] =
185 G_OBJECT_CLASS_TYPE(object_class),
188 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
190 g_mencoder_signals[ERROR] =
191 g_signal_new("error",
192 G_OBJECT_CLASS_TYPE(object_class),
195 g_cclosure_marshal_VOID__STRING,
196 G_TYPE_NONE, 1, G_TYPE_STRING);
200 g_mencoder_init(GMencoder * self)
202 GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE(self);
203 priv->info = g_new0(SetupInfo, 1);
207 g_mencoder_dispose(GObject * object)
212 g_mencoder_finalize(GObject * object)
214 GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE(object);
217 g_mencoder_close_stream(G_MENCODER(object));
224 return g_object_new(G_TYPE_MENCODER, NULL);
229 _obj_set_prop(GObject * obj, const gchar * prop_name,
230 const gchar * prop_val)
234 GParamSpec *s = NULL;
235 GObjectClass *k = G_OBJECT_GET_CLASS(obj);
238 g_value_init(&v, G_TYPE_STRING);
239 g_value_set_string(&v, prop_val);
241 s = g_object_class_find_property(k, prop_name);
243 g_print("Invalid property name: %s\n", prop_name);
247 g_value_init(&p, s->value_type);
248 switch (s->value_type) {
250 g_value_set_int(&p, atoi(prop_val));
253 g_value_set_uint (&p, (guint) atoi(prop_val));
256 g_value_set_ulong (&p, atol(prop_val));
259 g_value_set_string(&p, prop_val);
262 g_value_set_boolean(&p, (gboolean) atoi (prop_val));
265 g_value_set_double(&p, atof (prop_val));
268 g_value_set_float(&p, (float) atof (prop_val));
271 g_value_set_enum(&p, atoi(prop_val));
272 g_warning ("Property %s of type %s. Not supported using default enum",
273 prop_name, g_type_name (s->value_type));
277 g_object_set_property(obj, prop_name, &p);
283 _create_element_with_prop(const gchar * factory_name,
284 const gchar * element_name, gchar ** prop)
289 ret = gst_element_factory_make(factory_name, element_name);
294 for (i = 0; i < g_strv_length(prop); i++) {
295 if (prop[i] != NULL) {
296 char **v = g_strsplit(prop[i], "=", 2);
297 if (g_strv_length(v) == 2) {
298 _obj_set_prop(G_OBJECT(ret), v[0], v[1]);
310 _create_audio_bin(const gchar * encode, gchar ** encode_prop, gint rate)
312 GstElement *abin = NULL;
313 GstElement *aqueue = NULL;
314 GstElement *aconvert = NULL;
315 GstElement *aencode = NULL;
316 GstElement *aqueue_src = NULL;
319 // audio/x-raw-int ! queue ! audioconvert ! faac ! rtpmp4gpay !
320 // udpsink name=upd_audio host=224.0.0.1 port=5002
321 abin = gst_bin_new("abin");
322 aqueue = gst_element_factory_make("queue", "aqueue");
323 aconvert = gst_element_factory_make("audioconvert", "aconvert");
325 _create_element_with_prop((encode ? encode : "lame"), "aencode",
327 aqueue_src = gst_element_factory_make("queue", "aqueue_src");
329 if ((abin == NULL) || (aqueue == NULL) || (aconvert == NULL)
330 || (aencode == NULL) || (aqueue_src == NULL)) {
331 g_warning("Audio elements not found");
337 gst_bin_add_many(GST_BIN(abin), aqueue, aconvert, aencode, aqueue_src,
340 if (!gst_element_link (aqueue, aconvert))
342 g_warning("Not Link audio elements");
349 caps = gst_caps_new_simple ("audio/x-raw-int",
350 "rate", G_TYPE_INT, rate, NULL);
351 if (!gst_element_link_filtered (aconvert, aencode, caps))
353 gst_caps_unref (caps);
354 g_warning("Not link rate filter");
358 gst_caps_unref (caps);
362 if (!gst_element_link (aconvert, aencode))
364 g_warning ("Fail to link audio elements");
370 if (!gst_element_link (aencode, aqueue_src))
372 g_warning("Not Link audio elements");
375 // TODO: apply audio rate
377 // ghost pad the audio bin
378 apad = gst_element_get_pad(aqueue, "sink");
379 gst_element_add_pad(abin, gst_ghost_pad_new("sink", apad));
380 gst_object_unref(apad);
382 apad = gst_element_get_pad(aqueue_src, "src");
383 gst_element_add_pad(abin, gst_ghost_pad_new("src", apad));
384 gst_object_unref(apad);
389 gst_object_unref(abin);
392 gst_object_unref(aqueue);
394 if (aconvert != NULL)
395 gst_object_unref(aconvert);
398 gst_object_unref(aencode);
400 if (aqueue_src != NULL)
401 gst_object_unref(aqueue_src);
404 gst_object_unref(apad);
412 // queue ! videoscale ! video/x-raw-yuv,width=240,height=144 ! colorspace
413 // ! rate ! encode ! queue
415 _create_video_bin(const gchar * encode,
416 gchar ** encode_prop,
417 gdouble fps, gint rate, guint width, guint height,
418 gboolean use_deinterlace)
420 GstElement *vbin = NULL;
421 GstElement *vqueue = NULL;
422 GstElement *vqueue_src = NULL;
423 GstElement *vcolorspace = NULL;
424 GstElement *vencode = NULL;
425 GstElement *vrate = NULL;
426 GstElement *deinterlace = NULL;
427 GstElement *walk = NULL;
430 vbin = gst_bin_new("vbin");
431 vqueue = gst_element_factory_make("queue", "vqueue");
433 gst_element_factory_make("ffmpegcolorspace", "colorspace");
435 if (use_deinterlace) {
436 deinterlace = gst_element_factory_make ("ffdeinterlace", "deinterlace");
437 if (deinterlace == NULL) {
438 g_warning ("Fail to create deinterlace element: Continue without deinterlace.");
443 vencode = _create_element_with_prop((encode !=
445 "ffenc_mpeg1video"), "vencode",
447 vqueue_src = gst_element_factory_make("queue", "queue_src");
449 if ((vbin == NULL) || (vqueue == NULL) || (vcolorspace == NULL)
450 || (vencode == NULL) || (vqueue_src == NULL)) {
451 g_warning("Video elements not found");
455 gst_bin_add_many(GST_BIN(vbin), vqueue, vcolorspace, vencode,
458 if (deinterlace != NULL) {
459 gst_bin_add(GST_BIN(vbin), deinterlace);
460 gst_element_link (vqueue, deinterlace);
466 if ((width > 0) && (height > 0)) {
471 vscale = gst_element_factory_make("videoscale", "vscale");
472 g_object_set (G_OBJECT (vscale), "method", 1, NULL);
473 gst_bin_add(GST_BIN(vbin), vscale);
475 vcaps = gst_caps_new_simple("video/x-raw-yuv",
476 "width", G_TYPE_INT, width,
477 "height", G_TYPE_INT, height, NULL);
479 gst_element_link(walk, vscale);
481 if (gst_element_link_filtered(vscale, vcolorspace, vcaps) == FALSE) {
482 g_warning("Fail to resize video");
483 gst_object_unref(vcaps);
484 gst_object_unref(vscale);
487 gst_caps_unref(vcaps);
489 gst_element_link(walk, vcolorspace);
493 // Changing the video fps
494 g_debug ("Changing FPS TO : %5.2f", fps);
496 vrate = gst_element_factory_make("videorate", "vrate");
498 gst_bin_add(GST_BIN(vbin), vrate);
500 if (gst_element_link(vcolorspace, vrate) == FALSE) {
501 g_warning("Fail to link video elements");
505 vcaps = gst_caps_new_simple("video/x-raw-yuv",
506 "framerate", GST_TYPE_FRACTION,
510 if (gst_element_link_filtered(vrate, vencode, vcaps) == FALSE) {
511 g_warning("Fail to link vrate with vencode.");
514 gst_caps_unref(vcaps);
516 if (gst_element_link(vcolorspace, vencode) == FALSE) {
517 g_warning("Fail to link colorspace and video encode element.");
522 gst_element_link(vencode, vqueue_src);
524 // ghost pad the video bin
525 vpad = gst_element_get_pad(vqueue, "sink");
526 gst_element_add_pad(vbin, gst_ghost_pad_new("sink", vpad));
527 gst_object_unref(vpad);
529 vpad = gst_element_get_pad(vqueue_src, "src");
530 gst_element_add_pad(vbin, gst_ghost_pad_new("src", vpad));
531 gst_object_unref(vpad);
537 gst_object_unref(vpad);
540 gst_object_unref(vbin);
543 gst_object_unref(vqueue);
546 gst_object_unref(vencode);
548 if (vqueue_src != NULL)
549 gst_object_unref(vqueue_src);
551 if (vcolorspace != NULL)
552 gst_object_unref(vcolorspace);
560 g_mencoder_setup_stream(GMencoder * self,
562 gboolean deinterlace,
563 const gchar * mux_name,
564 const gchar * video_encode,
565 gchar ** video_encode_prop,
570 const gchar * audio_encode,
571 gchar ** audio_encode_prop,
572 guint audio_rate, const gchar * out_uri)
574 GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE(self);
575 if (priv->ready == TRUE) {
577 ("Stream already configured. You need close stream first.");
582 if (_open_output(self, out_uri) == FALSE) {
587 priv->send_chunked = chunked;
588 priv->pipe = _create_pipeline(self,
596 audio_encode, audio_encode_prop,
600 return (priv->pipe != NULL);
605 g_mencoder_append_uri(GMencoder * self, const gchar * uri)
610 GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE(self);
611 gboolean ret = FALSE;
612 GstElement *ap = NULL;
613 GstElement *vp = NULL;
616 g_return_val_if_fail(priv->pipe != NULL, FALSE);
617 g_return_val_if_fail(priv->ready == FALSE, FALSE);
619 src = _create_source(self, uri);
623 priv->src = gst_bin_get_by_name(GST_BIN(src), "src");
625 gst_bin_add(GST_BIN(priv->pipe), src);
627 ap = gst_bin_get_by_name(GST_BIN(priv->pipe), "abin");
628 vp = gst_bin_get_by_name(GST_BIN(priv->pipe), "vbin");
630 if ((vp == NULL) || (ap == NULL)) {
631 g_warning("Fail to get output bin");
635 pad_src = gst_element_get_pad(src, "src_audio");
636 pad_sink = gst_element_get_compatible_pad(ap,
638 gst_pad_get_caps(pad_src));
640 if ((pad_sink == NULL) || (pad_src == NULL))
643 GstPadLinkReturn lret = gst_pad_link(pad_src, pad_sink);
644 if (lret != GST_PAD_LINK_OK)
647 gst_object_unref(pad_src);
648 gst_object_unref(pad_sink);
650 pad_src = gst_element_get_pad(src, "src_video");
651 pad_sink = gst_element_get_compatible_pad(vp,
653 gst_pad_get_caps(pad_src));
655 if ((pad_src == NULL) || (pad_sink == NULL))
658 if (gst_pad_link(pad_src, pad_sink) != GST_PAD_LINK_OK) {
659 g_warning("invalid source. video");
667 if ((src != NULL) && (ret == FALSE)) {
668 gst_bin_remove(GST_BIN(priv->pipe), src);
669 gst_object_unref(src);
673 gst_object_unref(ap);
676 gst_object_unref(vp);
679 gst_object_unref(pad_src);
681 if (pad_sink != NULL)
682 gst_object_unref(pad_sink);
690 g_mencoder_remove_uri(GMencoder * self, const gchar * uri)
692 // GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
697 g_mencoder_play_stream(GMencoder * self)
699 GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE(self);
700 g_return_if_fail(priv->ready == FALSE);
702 gst_element_set_state(priv->pipe, GST_STATE_PLAYING);
703 if (priv->tick_id != 0) {
704 g_source_remove (priv->tick_id);
706 priv->tick_id = g_timeout_add(500, _tick_cb, self);
708 if (priv->timeout_id != 0) {
709 g_source_remove (priv->timeout_id);
711 priv->timeout_id = g_timeout_add(GMENCODER_TIMEOUT, _process_timeout_cb, self);
715 g_mencoder_pause_stream(GMencoder * self)
717 GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE(self);
718 g_return_if_fail(priv->ready == TRUE);
719 gst_element_set_state(priv->pipe, GST_STATE_PAUSED);
723 g_mencoder_close_stream(GMencoder * self)
726 GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE(self);
727 if (priv->tick_id != 0) {
728 g_source_remove(priv->tick_id);
732 if (priv->timeout_id != 0) {
733 g_source_remove (priv->timeout_id);
734 priv->timeout_id = 0;
737 if (priv->pipe != NULL) {
738 // TODO: fixe pipeline dispose
739 //gst_element_set_state (priv->pipe, GST_STATE_NULL);
740 // g_debug ("SETING STATE TO NULL: OK");
741 // gst_element_set_state (priv->pipe, GST_STATE_NULL);
742 //gst_object_unref (priv->pipe);
743 //gst_object_unref(priv->src);
754 _create_pipeline(GMencoder * self,
755 const gchar * video_encode,
756 const gchar * mux_name,
757 gchar ** video_encode_prop,
762 const gchar * audio_encode,
763 gchar ** audio_encode_prop, guint audio_rate,
764 gboolean deinterlace)
767 GstElement *pipe = NULL;
768 GstElement *sink = NULL;
769 GstElement *mux = NULL;
770 GstElement *abin = NULL;
771 GstElement *vbin = NULL;
772 GstElement *queue = NULL;
773 GstPad *aux_pad = NULL;
774 GstPad *mux_pad = NULL;
776 pipe = gst_pipeline_new("pipe");
779 gst_element_factory_make((mux_name ? mux_name : "ffmux_mpeg"),
784 queue = gst_element_factory_make("queue", "queueu_sink");
787 sink = gst_element_factory_make("fakesink", "sink");
788 g_object_set (G_OBJECT (sink), "signal-handoffs", TRUE, NULL);
789 g_signal_connect (G_OBJECT (sink),
791 G_CALLBACK (_buffer_arrive_cb),
794 abin = _create_audio_bin(audio_encode, audio_encode_prop, audio_rate);
799 _create_video_bin(video_encode, video_encode_prop, video_fps,
800 video_rate, video_width, video_height, deinterlace);
805 gst_bin_add_many(GST_BIN(pipe), abin, vbin, mux, queue, sink, NULL);
808 // Link bins with mux
809 aux_pad = gst_element_get_pad(abin, "src");
811 gst_element_get_compatible_pad(mux, aux_pad,
812 GST_PAD_CAPS(aux_pad));
813 if (mux_pad == NULL) {
814 g_warning("Mux element no have audio PAD");
817 GstPadLinkReturn ret = gst_pad_link(aux_pad, mux_pad);
818 if (ret != GST_PAD_LINK_OK) {
819 g_warning("Fail link audio and mux: %d", ret);
823 gst_object_unref(aux_pad);
824 gst_object_unref(mux_pad);
826 aux_pad = gst_element_get_pad(vbin, "src");
828 gst_element_get_compatible_pad(mux, aux_pad,
829 GST_PAD_CAPS(aux_pad));
830 if (mux_pad == NULL) {
831 g_warning("Mux element no have video PAD");
834 ret = gst_pad_link(aux_pad, mux_pad);
835 if (ret != GST_PAD_LINK_OK) {
836 g_warning("Fail link video and mux: %d", ret);
839 gst_object_unref(aux_pad);
840 gst_object_unref(mux_pad);
844 // Link mux with sink
845 gst_element_link_many(mux, queue, sink, NULL);
847 bus = gst_pipeline_get_bus(GST_PIPELINE(pipe));
848 gst_bus_add_watch(bus, _pipeline_bus_cb, self);
849 gst_object_unref(bus);
853 g_warning("Invalid uri");
856 gst_object_unref(pipe);
861 gst_object_unref(mux);
864 if (mux_pad != NULL) {
865 gst_object_unref(mux_pad);
868 if (aux_pad != NULL) {
869 gst_object_unref(mux_pad);
873 gst_object_unref(sink);
877 gst_object_unref(abin);
881 gst_object_unref(vbin);
889 _close_output(GMencoder * self)
894 _create_v4l_source (GMencoder *self, const gchar * uri)
897 GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE(self);
900 info = g_strsplit (uri+6, ":", 3);
901 if (g_strv_length (info) != 3) {
905 priv->v4lsrc = gst_element_factory_make ("v4l2src", "src");
906 g_debug ("channel %s, norm %s, frequ %s", info[0], info[1], info[2]);
907 g_object_set (G_OBJECT (priv->v4lsrc),
910 "frequency", atoi (info[2]),
917 _create_source(GMencoder *self, const gchar * uri)
920 GstElement *bsrc = NULL;
921 GstElement *src = NULL;
922 GstElement *aqueue = NULL;
923 GstElement *vqueue = NULL;
924 GstElement *decode = NULL;
925 GstPad *src_pad = NULL;
928 bsrc = gst_bin_new(NULL);
930 // src = gst_element_factory_make ("gnomevfssrc", "src");
931 // g_object_set (G_OBJECT (src), "location", uri, NULL);
932 if (strncmp (uri, "v4l://", 6) == 0) {
934 src = _create_v4l_source (self, uri);
937 src = gst_element_make_from_uri(GST_URI_SRC, uri, "src");
944 if (g_getenv ("USE_DECODEBIN1"))
945 decode = gst_element_factory_make("decodebin", "decode");
947 decode = gst_element_factory_make("decodebin2", "decode");
951 aqueue = gst_element_factory_make("queue", "aqueue");
955 vqueue = gst_element_factory_make("queue", "vqueue");
959 gst_bin_add_many(GST_BIN(bsrc), src, decode, aqueue, vqueue,
961 gst_element_link (src, decode);
963 g_signal_connect(G_OBJECT(decode),
965 G_CALLBACK(_decodebin_new_pad_cb), bsrc);
967 g_signal_connect(G_OBJECT(decode),
969 G_CALLBACK(_decodebin_unknown_type_cb), pipe);
971 src_pad = gst_element_get_pad(aqueue, "src");
972 gst_element_add_pad(bsrc, gst_ghost_pad_new("src_audio", src_pad));
973 gst_object_unref(src_pad);
975 src_pad = gst_element_get_pad(vqueue, "src");
976 gst_element_add_pad(bsrc, gst_ghost_pad_new("src_video", src_pad));
977 gst_object_unref(src_pad);
982 g_debug ("Fail to create source element");
984 gst_object_unref(src);
987 if (decode != NULL) {
988 gst_object_unref(decode);
991 if (aqueue != NULL) {
992 gst_object_unref(aqueue);
995 if (vqueue != NULL) {
996 gst_object_unref(vqueue);
1003 _open_output(GMencoder * self, const gchar * uri)
1006 GnomeVFSResult result;
1007 GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE(self);
1009 i = g_strsplit(uri, "://", 0);
1010 if (strcmp(i[0], "fd") == 0) {
1011 result = gnome_vfs_open_fd (&priv->handle, atoi(i[1]));
1013 if (g_file_test (i[1], G_FILE_TEST_EXISTS) == FALSE) {
1014 result = gnome_vfs_create (&priv->handle, uri, GNOME_VFS_OPEN_WRITE, FALSE,
1015 GNOME_VFS_PERM_USER_WRITE | GNOME_VFS_PERM_USER_READ | GNOME_VFS_PERM_GROUP_READ);
1017 result = gnome_vfs_open (&priv->handle, uri,
1018 GNOME_VFS_OPEN_WRITE | GNOME_VFS_OPEN_TRUNCATE);
1023 return (result == GNOME_VFS_OK);
1027 _pipeline_bus_cb(GstBus * bus, GstMessage * msg, gpointer user_data)
1029 GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE(user_data);
1031 switch (GST_MESSAGE_TYPE(msg)) {
1033 case GST_MESSAGE_STATE_CHANGED:
1037 GstState pendingstate;
1040 gst_message_parse_state_changed(msg, &oldstate,
1041 &newstate, &pendingstate);
1043 if (pendingstate != GST_STATE_VOID_PENDING)
1046 if ((oldstate == GST_STATE_READY)
1047 && (newstate == GST_STATE_PAUSED)) {
1049 g_signal_emit(user_data, g_mencoder_signals[PAUSED],
1051 } else if ((oldstate == GST_STATE_PAUSED)
1052 && (newstate == GST_STATE_PLAYING)) {
1053 g_signal_emit(user_data, g_mencoder_signals[PLAYING], 0);
1054 } else if ((oldstate == GST_STATE_READY) &&
1055 (newstate == GST_STATE_NULL)) {
1056 g_signal_emit(user_data, g_mencoder_signals[STOPED], 0);
1061 case GST_MESSAGE_ERROR:
1067 if (priv->timeout_id != 0) {
1068 g_source_remove (priv->timeout_id);
1069 priv->timeout_id = 0;
1072 if (priv->tick_id != 0) {
1073 g_source_remove(priv->tick_id);
1077 gst_message_parse_error(msg, &error, &debug);
1078 err_str = g_strdup_printf("Error [%d] %s (%s)", error->code,
1079 error->message, debug);
1080 priv->ready = FALSE;
1082 g_signal_emit(user_data, g_mencoder_signals[ERROR], 0,
1086 g_clear_error(&error);
1091 case GST_MESSAGE_EOS:
1092 priv->ready = FALSE;
1093 #ifdef USE_MANUAL_SINK
1094 _flush_queue (G_MENCODER (user_data));
1096 g_signal_emit(user_data, g_mencoder_signals[EOS], 0);
1099 case GST_MESSAGE_DURATION:
1103 gst_message_parse_duration(msg, &format, &duration);
1104 if (format == GST_FORMAT_BYTES)
1105 priv->duration = duration;
1119 _decodebin_new_pad_cb(GstElement * object,
1120 GstPad * pad, gboolean flag, gpointer user_data)
1123 gchar *str_caps = NULL;
1124 GstElement *sink_element;
1127 caps = gst_pad_get_caps(pad);
1128 str_caps = gst_caps_to_string(caps);
1129 if (strstr(str_caps, "audio") != NULL) {
1130 sink_element = gst_bin_get_by_name(GST_BIN(user_data), "aqueue");
1131 } else if (strstr(str_caps, "video") != NULL) {
1132 sink_element = gst_bin_get_by_name(GST_BIN(user_data), "vqueue");
1134 g_warning("invalid caps %s", str_caps);
1137 sink_pad = gst_element_get_pad(sink_element, "sink");
1138 if (!gst_pad_is_linked (sink_pad))
1139 gst_pad_link(pad, sink_pad);
1141 gst_object_unref(sink_element);
1142 gst_object_unref(sink_pad);
1144 gst_caps_unref(caps);
1148 _decodebin_unknown_type_cb(GstElement * object,
1149 GstPad * pad, GstCaps * caps,
1152 g_warning("Unknown Type");
1153 // priv->ready = FALSE;
1157 _tick_cb(gpointer user_data)
1159 GstFormat format = GST_FORMAT_BYTES;
1162 GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE(user_data);
1164 if (priv->duration == 0) {
1166 if (gst_element_query_duration(priv->src, &format, &d))
1170 if (priv->duration != 0) {
1171 gst_element_query_position(priv->src, &format, &cur);
1172 g_print("PROGRESS:%lli\n", (99 * cur) / priv->duration);
1179 _process_timeout_cb (gpointer user_data)
1181 GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE(user_data);
1183 g_signal_emit(user_data, g_mencoder_signals[ERROR], 0, "timeout");
1184 priv->timeout_id = 0;
1189 #ifdef USE_MANUAL_SINK
1191 _send_buffer (GnomeVFSHandle *handle, gpointer buff, gint size)
1195 GnomeVFSResult result;
1196 GnomeVFSFileSize bytes_written;
1198 b_send = g_byte_array_new ();
1199 msg = g_strdup_printf ("%x\r\n", size);
1200 b_send = g_byte_array_append (b_send, (const guint8*) msg, strlen (msg) * sizeof (gchar));
1203 b_send = g_byte_array_append (b_send, buff, size);
1205 msg = g_strdup ("\r\n");
1206 b_send = g_byte_array_append (b_send, (const guint8*) msg, strlen (msg) * sizeof (gchar));
1209 result = gnome_vfs_write (handle, b_send->data, b_send->len, &bytes_written);
1210 g_byte_array_free (b_send, TRUE);
1212 return (result == GNOME_VFS_OK);
1216 _flush_queue (GMencoder *self)
1218 GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE(self);
1220 if (priv->send_chunked) {
1221 GnomeVFSFileSize bytes_written;
1223 end_msg = g_strdup ("0\r\n\r\n");
1224 gnome_vfs_write (priv->handle,
1225 (const guint8*) end_msg,
1226 strlen(end_msg) * sizeof(gchar),
1233 _buffer_arrive_cb (GstElement* object,
1238 GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE(user_data);
1240 if (priv->timeout_id != 0) {
1241 g_source_remove (priv->timeout_id);
1242 priv->timeout_id = 0;
1245 priv->timeout_id = g_timeout_add(GMENCODER_TIMEOUT, _process_timeout_cb, user_data);
1247 if (priv->send_chunked) {
1248 if (_send_buffer (priv->handle, GST_BUFFER_DATA (buff), GST_BUFFER_SIZE (buff)) == FALSE)
1251 GnomeVFSResult result;
1252 GnomeVFSFileSize bytes_written;
1254 result = gnome_vfs_write (priv->handle,
1255 GST_BUFFER_DATA (buff),
1256 GST_BUFFER_SIZE (buff),
1259 if (result != GNOME_VFS_OK)
1266 if (priv->tick_id != 0) {
1267 g_source_remove(priv->tick_id);
1270 g_signal_emit(user_data, g_mencoder_signals[ERROR], 0, "Fail to write on socket");
1271 gst_element_set_state (priv->pipe, GST_STATE_PAUSED);