11 #include <sys/types.h>
12 #include <sys/socket.h>
14 #include "gmencoder.h"
16 #define G_MENCODER_GET_PRIVATE(obj) \
17 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), G_TYPE_MENCODER, GMencoderPrivate))
19 // #define SUPPORT_MULT_INPUT 0
20 #define USE_MANUAL_SINK
21 #define BUFFER_SIZE (1024 * 64)
23 typedef struct _GMencoderPrivate GMencoderPrivate;
24 typedef struct _SetupInfo SetupInfo;
29 gchar **video_encode_prop;
35 gchar **audio_encode_prop;
40 struct _GMencoderPrivate {
54 gboolean send_chunked;
55 #ifdef USE_MANUAL_SINK
69 static void g_mencoder_class_init(GMencoderClass * klass);
70 static void g_mencoder_init(GMencoder * object);
71 static void g_mencoder_dispose(GObject * object);
72 static void g_mencoder_finalize(GObject * object);
73 static GstElement *_create_audio_bin(const gchar * encode,
74 gchar ** encode_prop, gint rate);
75 static GstElement *_create_video_bin(const gchar * encode,
78 gint rate, guint width, guint height,
79 gboolean use_deinterlace);
82 _pipeline_bus_cb(GstBus * bus, GstMessage * msg, gpointer user_data);
84 static void _decodebin_new_pad_cb(GstElement * object,
86 gboolean flag, gpointer user_data);
88 static void _decodebin_unknown_type_cb(GstElement * object,
93 static void _close_output(GMencoder * self);
94 static gboolean _open_output(GMencoder * self, const gchar * uri);
96 static GstElement *_create_source(const gchar * uri);
97 static GstElement *_create_pipeline(GMencoder * self,
98 const gchar * video_encode,
99 const gchar * mux_name,
100 gchar ** video_encode_prop,
105 const gchar * audio_encode,
106 gchar ** audio_encode_prop,
108 gboolean deinterlace);
109 #ifdef USE_MANUAL_SINK
110 static void _flush_queue (GMencoder *self);
111 static void _buffer_arrive_cb (GstElement* object,
118 static gboolean _tick_cb(gpointer data);
120 static guint g_mencoder_signals[LAST_SIGNAL] = { 0 };
122 G_DEFINE_TYPE(GMencoder, g_mencoder, G_TYPE_OBJECT)
124 static void g_mencoder_class_init(GMencoderClass * klass)
126 GObjectClass *object_class;
127 object_class = (GObjectClass *) klass;
128 g_type_class_add_private(klass, sizeof(GMencoderPrivate));
130 object_class->dispose = g_mencoder_dispose;
131 object_class->finalize = g_mencoder_finalize;
133 g_mencoder_signals[PAUSED] =
134 g_signal_new("paused",
135 G_OBJECT_CLASS_TYPE(object_class),
138 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
140 g_mencoder_signals[PLAYING] =
141 g_signal_new("playing",
142 G_OBJECT_CLASS_TYPE(object_class),
145 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
147 g_mencoder_signals[STOPED] =
148 g_signal_new("stoped",
149 G_OBJECT_CLASS_TYPE(object_class),
152 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
154 g_mencoder_signals[EOS] =
156 G_OBJECT_CLASS_TYPE(object_class),
159 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
161 g_mencoder_signals[ERROR] =
162 g_signal_new("error",
163 G_OBJECT_CLASS_TYPE(object_class),
166 g_cclosure_marshal_VOID__STRING,
167 G_TYPE_NONE, 1, G_TYPE_STRING);
171 g_mencoder_init(GMencoder * self)
173 GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE(self);
174 priv->info = g_new0(SetupInfo, 1);
175 #ifdef USE_MANUAL_SINK
176 priv->queue = g_byte_array_new ();
181 g_mencoder_dispose(GObject * object)
186 g_mencoder_finalize(GObject * object)
188 GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE(object);
191 g_mencoder_close_stream(G_MENCODER(object));
193 #ifdef USE_MANUAL_SINK
194 g_byte_array_free (priv->queue, TRUE);
201 return g_object_new(G_TYPE_MENCODER, NULL);
206 _obj_set_prop(GObject * obj, const gchar * prop_name,
207 const gchar * prop_val)
211 GParamSpec *s = NULL;
212 GObjectClass *k = G_OBJECT_GET_CLASS(obj);
215 g_value_init(&v, G_TYPE_STRING);
216 g_value_set_string(&v, prop_val);
218 s = g_object_class_find_property(k, prop_name);
220 g_print("Invalid property name: %s\n", prop_name);
224 g_value_init(&p, s->value_type);
225 switch (s->value_type) {
227 g_value_set_int(&p, atoi(prop_val));
230 g_value_set_ulong (&p, atol(prop_val));
233 g_value_set_string(&p, prop_val);
236 g_value_set_boolean(&p, (gboolean) atoi (prop_val));
239 g_value_set_double(&p, atof (prop_val));
242 g_value_set_float(&p, (float) atof (prop_val));
245 g_value_set_enum(&p, atoi(prop_val));
246 g_warning ("Property %s of type %s. Not supported using default enum",
247 prop_name, g_type_name (s->value_type));
251 g_object_set_property(obj, prop_name, &p);
257 _create_element_with_prop(const gchar * factory_name,
258 const gchar * element_name, gchar ** prop)
263 ret = gst_element_factory_make(factory_name, element_name);
268 for (i = 0; i < g_strv_length(prop); i++) {
269 if (prop[i] != NULL) {
270 char **v = g_strsplit(prop[i], "=", 2);
271 if (g_strv_length(v) == 2) {
272 _obj_set_prop(G_OBJECT(ret), v[0], v[1]);
284 _create_audio_bin(const gchar * encode, gchar ** encode_prop, gint rate)
286 GstElement *abin = NULL;
287 GstElement *aqueue = NULL;
288 GstElement *aconvert = NULL;
289 GstElement *aencode = NULL;
290 GstElement *aqueue_src = NULL;
293 // audio/x-raw-int ! queue ! audioconvert ! faac ! rtpmp4gpay !
294 // udpsink name=upd_audio host=224.0.0.1 port=5002
295 abin = gst_bin_new("abin");
296 aqueue = gst_element_factory_make("queue", "aqueue");
297 aconvert = gst_element_factory_make("audioconvert", "aconvert");
299 _create_element_with_prop((encode ? encode : "lame"), "aencode",
301 aqueue_src = gst_element_factory_make("queue", "aqueue_src");
303 if ((abin == NULL) || (aqueue == NULL) || (aconvert == NULL)
304 || (aencode == NULL) || (aqueue_src == NULL)) {
305 g_warning("Audio elements not found");
309 g_object_set(G_OBJECT(aencode), "bitrate", 32, NULL);
311 * if (rate > 0) { g_object_set (G_OBJECT (aencode), "bitrate", 32,
315 gst_bin_add_many(GST_BIN(abin), aqueue, aconvert, aencode, aqueue_src,
317 if (gst_element_link_many(aqueue, aconvert, aencode, aqueue_src, NULL)
319 g_warning("Not Link audio elements");
321 // TODO: apply audio rate
323 // ghost pad the audio bin
324 apad = gst_element_get_pad(aqueue, "sink");
325 gst_element_add_pad(abin, gst_ghost_pad_new("sink", apad));
326 gst_object_unref(apad);
328 apad = gst_element_get_pad(aqueue_src, "src");
329 gst_element_add_pad(abin, gst_ghost_pad_new("src", apad));
330 gst_object_unref(apad);
335 gst_object_unref(abin);
338 gst_object_unref(aqueue);
340 if (aconvert != NULL)
341 gst_object_unref(aconvert);
344 gst_object_unref(aencode);
346 if (aqueue_src != NULL)
347 gst_object_unref(aqueue_src);
350 gst_object_unref(apad);
358 // queue ! videoscale ! video/x-raw-yuv,width=240,height=144 ! colorspace
359 // ! rate ! encode ! queue
361 _create_video_bin(const gchar * encode,
362 gchar ** encode_prop,
363 gdouble fps, gint rate, guint width, guint height,
364 gboolean use_deinterlace)
366 GstElement *vbin = NULL;
367 GstElement *vqueue = NULL;
368 GstElement *vqueue_src = NULL;
369 GstElement *vcolorspace = NULL;
370 GstElement *vencode = NULL;
371 GstElement *vrate = NULL;
372 GstElement *deinterlace = NULL;
373 GstElement *walk = NULL;
376 vbin = gst_bin_new("vbin");
377 vqueue = gst_element_factory_make("queue", "vqueue");
379 gst_element_factory_make("ffmpegcolorspace", "colorspace");
381 if (use_deinterlace) {
382 deinterlace = gst_element_factory_make ("ffdeinterlace", "deinterlace");
383 if (deinterlace == NULL) {
384 g_warning ("Fail to create deinterlace element: Continue without deinterlace.");
389 vencode = _create_element_with_prop((encode !=
391 "ffenc_mpeg1video"), "vencode",
393 vqueue_src = gst_element_factory_make("queue", "queue_src");
395 if ((vbin == NULL) || (vqueue == NULL) || (vcolorspace == NULL)
396 || (vencode == NULL) || (vqueue_src == NULL)) {
397 g_warning("Video elements not found");
401 gst_bin_add_many(GST_BIN(vbin), vqueue, vcolorspace, vencode,
404 if (deinterlace != NULL) {
405 gst_bin_add(GST_BIN(vbin), deinterlace);
406 gst_element_link (vqueue, deinterlace);
412 if ((width > 0) && (height > 0)) {
416 gst_element_factory_make("videoscale", "vscale");
418 g_object_set (G_OBJECT (vscale), "method", 1, NULL);
420 gst_bin_add(GST_BIN(vbin), vscale);
422 vcaps = gst_caps_new_simple("video/x-raw-yuv",
423 "width", G_TYPE_INT, width,
424 "height", G_TYPE_INT, height, NULL);
426 gst_element_link(walk, vscale);
428 if (gst_element_link_filtered(vscale, vcolorspace, vcaps) == FALSE) {
429 g_warning("Fail to resize video");
430 gst_object_unref(vcaps);
431 gst_object_unref(vscale);
434 gst_caps_unref(vcaps);
436 gst_element_link(walk, vcolorspace);
440 // Changing the video fps
442 vrate = gst_element_factory_make("videorate", "vrate");
444 gst_bin_add(GST_BIN(vbin), vrate);
446 if (gst_element_link(vcolorspace, vrate) == FALSE) {
447 g_warning("Fail to link video elements");
451 vcaps = gst_caps_new_simple("video/x-raw-yuv",
452 "framerate", GST_TYPE_FRACTION,
453 (int) (fps * 1000), 1000, NULL);
455 if (gst_element_link_filtered(vrate, vencode, vcaps) == FALSE) {
456 g_warning("Fail to link vrate with vencode.");
459 gst_caps_unref(vcaps);
461 if (gst_element_link(vcolorspace, vencode) == FALSE) {
462 g_warning("Fail to link colorspace and video encode element.");
467 gst_element_link(vencode, vqueue_src);
469 // ghost pad the video bin
470 vpad = gst_element_get_pad(vqueue, "sink");
471 gst_element_add_pad(vbin, gst_ghost_pad_new("sink", vpad));
472 gst_object_unref(vpad);
474 vpad = gst_element_get_pad(vqueue_src, "src");
475 gst_element_add_pad(vbin, gst_ghost_pad_new("src", vpad));
476 gst_object_unref(vpad);
482 gst_object_unref(vpad);
485 gst_object_unref(vbin);
488 gst_object_unref(vqueue);
491 gst_object_unref(vencode);
493 if (vqueue_src != NULL)
494 gst_object_unref(vqueue_src);
496 if (vcolorspace != NULL)
497 gst_object_unref(vcolorspace);
505 g_mencoder_setup_stream(GMencoder * self,
507 gboolean deinterlace,
508 const gchar * mux_name,
509 const gchar * video_encode,
510 gchar ** video_encode_prop,
515 const gchar * audio_encode,
516 gchar ** audio_encode_prop,
517 guint audio_rate, const gchar * out_uri)
519 GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE(self);
520 if (priv->ready == TRUE) {
522 ("Stream already configured. You need close stream first.");
527 if (_open_output(self, out_uri) == FALSE)
531 priv->send_chunked = chunked;
532 priv->pipe = _create_pipeline(self,
540 audio_encode, audio_encode_prop,
544 return (priv->pipe != NULL);
549 g_mencoder_append_uri(GMencoder * self, const gchar * uri)
554 GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE(self);
555 gboolean ret = FALSE;
556 GstElement *ap = NULL;
557 GstElement *vp = NULL;
560 g_return_val_if_fail(priv->pipe != NULL, FALSE);
561 g_return_val_if_fail(priv->ready == FALSE, FALSE);
563 #ifndef SUPPORT_MULT_INPUT
564 g_return_val_if_fail(priv->sources < 1, FALSE);
567 src = _create_source(uri);
571 priv->src = gst_bin_get_by_name(GST_BIN(src), "src");
573 gst_bin_add(GST_BIN(priv->pipe), src);
575 #ifdef SUPPORT_MULT_INPUT
576 ap = gst_bin_get_by_name(GST_BIN(priv->pipe), "ap");
577 vp = gst_bin_get_by_name(GST_BIN(priv->pipe), "vp");
579 ap = gst_bin_get_by_name(GST_BIN(priv->pipe), "abin");
580 vp = gst_bin_get_by_name(GST_BIN(priv->pipe), "vbin");
583 if ((vp == NULL) || (ap == NULL)) {
584 g_warning("Fail to get output bin");
588 pad_src = gst_element_get_pad(src, "src_audio");
589 pad_sink = gst_element_get_compatible_pad(ap,
591 gst_pad_get_caps(pad_src));
593 if ((pad_sink == NULL) || (pad_src == NULL))
596 GstPadLinkReturn lret = gst_pad_link(pad_src, pad_sink);
597 if (lret != GST_PAD_LINK_OK)
600 gst_object_unref(pad_src);
601 gst_object_unref(pad_sink);
603 pad_src = gst_element_get_pad(src, "src_video");
604 pad_sink = gst_element_get_compatible_pad(vp,
606 gst_pad_get_caps(pad_src));
608 if ((pad_src == NULL) || (pad_sink == NULL))
611 if (gst_pad_link(pad_src, pad_sink) != GST_PAD_LINK_OK) {
612 g_warning("invalid source. video");
620 if ((src != NULL) && (ret == FALSE)) {
621 gst_bin_remove(GST_BIN(priv->pipe), src);
622 gst_object_unref(src);
626 gst_object_unref(ap);
629 gst_object_unref(vp);
632 gst_object_unref(pad_src);
634 if (pad_sink != NULL)
635 gst_object_unref(pad_sink);
643 g_mencoder_remove_uri(GMencoder * self, const gchar * uri)
645 // GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
650 g_mencoder_play_stream(GMencoder * self)
652 GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE(self);
653 g_return_if_fail(priv->ready == FALSE);
655 gst_element_set_state(priv->pipe, GST_STATE_PLAYING);
656 priv->tick_id = g_timeout_add(500, _tick_cb, self);
660 g_mencoder_pause_stream(GMencoder * self)
662 GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE(self);
663 g_return_if_fail(priv->ready == TRUE);
664 gst_element_set_state(priv->pipe, GST_STATE_PAUSED);
668 g_mencoder_close_stream(GMencoder * self)
671 GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE(self);
672 if (priv->tick_id != 0) {
673 g_source_remove(priv->tick_id);
677 if (priv->pipe != NULL) {
678 // TODO: fixe pipeline dispose
679 gst_element_set_state (priv->pipe, GST_STATE_NULL);
680 // g_debug ("SETING STATE TO NULL: OK");
681 // gst_element_set_state (priv->pipe, GST_STATE_NULL);
682 gst_object_unref (priv->pipe);
683 //gst_object_unref(priv->src);
694 _create_pipeline(GMencoder * self,
695 const gchar * video_encode,
696 const gchar * mux_name,
697 gchar ** video_encode_prop,
702 const gchar * audio_encode,
703 gchar ** audio_encode_prop, guint audio_rate,
704 gboolean deinterlace)
707 GstElement *pipe = NULL;
708 GstElement *sink = NULL;
709 GstElement *mux = NULL;
710 GstElement *abin = NULL;
711 GstElement *vbin = NULL;
712 GstElement *queue = NULL;
713 GstPad *aux_pad = NULL;
714 GstPad *mux_pad = NULL;
715 #ifdef SUPPORT_MULT_INPUT
716 GstElement *ap = NULL;
717 GstElement *vp = NULL;
720 pipe = gst_pipeline_new("pipe");
722 #ifdef SUPPORT_MULT_INPUT
723 ap = gst_element_factory_make("concatmux", "ap");
724 vp = gst_element_factory_make("concatmux", "vp");
725 gst_bin_add_many(GST_BIN(pipe), ap, vp, NULL);
727 GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE(self);
730 gst_element_factory_make((mux_name ? mux_name : "ffmux_mpeg"),
735 queue = gst_element_factory_make("queue", "queueu_sink");
738 #ifdef USE_MANUAL_SINK
739 sink = gst_element_factory_make("fakesink", "sink");
740 g_object_set (G_OBJECT (sink), "signal-handoffs", TRUE, NULL);
741 g_signal_connect (G_OBJECT (sink),
743 G_CALLBACK (_buffer_arrive_cb),
746 sink = gst_element_factory_make("fdsink", "sink");
750 g_object_set(G_OBJECT(sink), "fd", priv->fd, "sync", FALSE, NULL);
753 abin = _create_audio_bin(audio_encode, audio_encode_prop, audio_rate);
758 _create_video_bin(video_encode, video_encode_prop, video_fps,
759 video_rate, video_width, video_height, deinterlace);
764 gst_bin_add_many(GST_BIN(pipe), abin, vbin, mux, queue, sink, NULL);
767 #ifdef SUPPORT_MULT_INPUT
768 if (gst_element_link(ap, abin) == FALSE) {
769 g_warning("Fail to link concat and abin");
773 if (gst_element_link(vp, vbin) == FALSE) {
774 g_warning("Fail to link concat and vbin");
778 // Link bins with mux
779 aux_pad = gst_element_get_pad(abin, "src");
781 gst_element_get_compatible_pad(mux, aux_pad,
782 GST_PAD_CAPS(aux_pad));
783 if (mux_pad == NULL) {
784 g_warning("Mux element no have audio PAD");
787 GstPadLinkReturn ret = gst_pad_link(aux_pad, mux_pad);
788 if (ret != GST_PAD_LINK_OK) {
789 g_warning("Fail link audio and mux: %d", ret);
793 gst_object_unref(aux_pad);
794 gst_object_unref(mux_pad);
796 aux_pad = gst_element_get_pad(vbin, "src");
798 gst_element_get_compatible_pad(mux, aux_pad,
799 GST_PAD_CAPS(aux_pad));
800 if (mux_pad == NULL) {
801 g_warning("Mux element no have video PAD");
804 ret = gst_pad_link(aux_pad, mux_pad);
805 if (ret != GST_PAD_LINK_OK) {
806 g_warning("Fail link video and mux: %d", ret);
809 gst_object_unref(aux_pad);
810 gst_object_unref(mux_pad);
814 // Link mux with sink
815 gst_element_link_many(mux, queue, sink, NULL);
817 bus = gst_pipeline_get_bus(GST_PIPELINE(pipe));
818 gst_bus_add_watch(bus, _pipeline_bus_cb, self);
819 gst_object_unref(bus);
823 g_warning("Invalid uri");
826 gst_object_unref(pipe);
831 gst_object_unref(mux);
834 if (mux_pad != NULL) {
835 gst_object_unref(mux_pad);
838 if (aux_pad != NULL) {
839 gst_object_unref(mux_pad);
843 gst_object_unref(sink);
847 gst_object_unref(abin);
851 gst_object_unref(vbin);
859 _close_output(GMencoder * self)
864 _create_source(const gchar * uri)
867 GstElement *bsrc = NULL;
868 GstElement *src = NULL;
869 GstElement *queue = NULL;
870 GstElement *aqueue = NULL;
871 GstElement *vqueue = NULL;
872 GstElement *decode = NULL;
873 GstPad *src_pad = NULL;
876 bsrc = gst_bin_new(NULL);
878 // src = gst_element_factory_make ("gnomevfssrc", "src");
879 // g_object_set (G_OBJECT (src), "location", uri, NULL);
880 src = gst_element_make_from_uri(GST_URI_SRC, uri, "src");
884 decode = gst_element_factory_make("decodebin", "decode");
888 queue = gst_element_factory_make("queue", "queue_src");
889 aqueue = gst_element_factory_make("queue", "aqueue");
893 vqueue = gst_element_factory_make("queue", "vqueue");
897 gst_bin_add_many(GST_BIN(bsrc), src, queue, decode, aqueue, vqueue,
899 gst_element_link_many(src, queue, decode, NULL);
901 g_signal_connect(G_OBJECT(decode),
903 G_CALLBACK(_decodebin_new_pad_cb), bsrc);
905 g_signal_connect(G_OBJECT(decode),
907 G_CALLBACK(_decodebin_unknown_type_cb), pipe);
909 src_pad = gst_element_get_pad(aqueue, "src");
910 gst_element_add_pad(bsrc, gst_ghost_pad_new("src_audio", src_pad));
911 gst_object_unref(src_pad);
913 src_pad = gst_element_get_pad(vqueue, "src");
914 gst_element_add_pad(bsrc, gst_ghost_pad_new("src_video", src_pad));
915 gst_object_unref(src_pad);
921 gst_object_unref(src);
924 if (decode != NULL) {
925 gst_object_unref(decode);
928 if (aqueue != NULL) {
929 gst_object_unref(aqueue);
932 if (vqueue != NULL) {
933 gst_object_unref(vqueue);
940 _open_output(GMencoder * self, const gchar * uri)
944 GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE(self);
946 i = g_strsplit(uri, "://", 0);
947 if (strcmp(i[0], "fd") == 0) {
948 priv->fd = atoi(i[1]);
949 if (priv->send_chunked)
950 fcntl (priv->fd, F_SETFL, O_ASYNC);
951 } else if (strcmp(i[0], "file") == 0) {
952 if (g_file_test (i[1], G_FILE_TEST_EXISTS)) {
953 if (unlink (i[1]) != 0) {
954 g_warning ("Fail to write in : %s", uri);
959 priv->fd = open(i[1], O_WRONLY | O_CREAT | O_TRUNC,
960 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
962 if (priv->fd == -1) {
963 g_warning ("Fail to open : %s", uri);
967 g_warning("Output uri not supported");
977 _pipeline_bus_cb(GstBus * bus, GstMessage * msg, gpointer user_data)
979 GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE(user_data);
981 switch (GST_MESSAGE_TYPE(msg)) {
983 case GST_MESSAGE_STATE_CHANGED:
987 GstState pendingstate;
990 gst_message_parse_state_changed(msg, &oldstate,
991 &newstate, &pendingstate);
993 if (pendingstate != GST_STATE_VOID_PENDING)
996 if ((oldstate == GST_STATE_READY)
997 && (newstate == GST_STATE_PAUSED)) {
999 g_signal_emit(user_data, g_mencoder_signals[PAUSED],
1001 } else if ((oldstate == GST_STATE_PAUSED)
1002 && (newstate == GST_STATE_PLAYING)) {
1003 g_signal_emit(user_data, g_mencoder_signals[PLAYING], 0);
1004 } else if ((oldstate == GST_STATE_READY) &&
1005 (newstate == GST_STATE_NULL)) {
1006 g_signal_emit(user_data, g_mencoder_signals[STOPED], 0);
1011 case GST_MESSAGE_ERROR:
1017 if (priv->tick_id != 0) {
1018 g_source_remove(priv->tick_id);
1022 gst_message_parse_error(msg, &error, &debug);
1023 err_str = g_strdup_printf("Error [%d] %s (%s)", error->code,
1024 error->message, debug);
1025 priv->ready = FALSE;
1026 g_signal_emit(user_data, g_mencoder_signals[ERROR], 0,
1029 g_clear_error(&error);
1034 case GST_MESSAGE_EOS:
1035 priv->ready = FALSE;
1036 #ifdef USE_MANUAL_SINK
1037 _flush_queue (G_MENCODER (user_data));
1039 g_signal_emit(user_data, g_mencoder_signals[EOS], 0);
1042 case GST_MESSAGE_DURATION:
1046 gst_message_parse_duration(msg, &format, &duration);
1047 if (format == GST_FORMAT_BYTES)
1048 priv->duration = duration;
1062 _decodebin_new_pad_cb(GstElement * object,
1063 GstPad * pad, gboolean flag, gpointer user_data)
1066 gchar *str_caps = NULL;
1067 GstElement *sink_element;
1070 caps = gst_pad_get_caps(pad);
1071 str_caps = gst_caps_to_string(caps);
1072 if (strstr(str_caps, "audio") != NULL) {
1073 sink_element = gst_bin_get_by_name(GST_BIN(user_data), "aqueue");
1074 } else if (strstr(str_caps, "video") != NULL) {
1075 sink_element = gst_bin_get_by_name(GST_BIN(user_data), "vqueue");
1077 g_warning("invalid caps %s", str_caps);
1080 sink_pad = gst_element_get_pad(sink_element, "sink");
1081 gst_pad_link(pad, sink_pad);
1083 gst_object_unref(sink_element);
1084 gst_object_unref(sink_pad);
1086 gst_caps_unref(caps);
1090 _decodebin_unknown_type_cb(GstElement * object,
1091 GstPad * pad, GstCaps * caps,
1094 g_warning("Unknown Type");
1095 // priv->ready = FALSE;
1099 _tick_cb(gpointer user_data)
1101 GstFormat format = GST_FORMAT_BYTES;
1104 GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE(user_data);
1106 if (priv->duration == 0) {
1108 if (gst_element_query_duration(priv->src, &format, &d))
1112 if (priv->duration != 0) {
1113 gst_element_query_position(priv->src, &format, &cur);
1114 g_print("PROGRESS:%lli\n", (99 * cur) / priv->duration);
1121 #ifdef USE_MANUAL_SINK
1123 _send_buffer (gint fd, gpointer buff, gint size)
1125 gboolean ret = TRUE;
1129 b_send = g_byte_array_new ();
1130 msg = g_strdup_printf ("%x\r\n", size);
1131 b_send = g_byte_array_append (b_send, (const guint8*) msg, strlen (msg) * sizeof (gchar));
1134 b_send = g_byte_array_append (b_send, buff, size);
1136 msg = g_strdup ("\r\n");
1137 b_send = g_byte_array_append (b_send, (const guint8*) msg, strlen (msg) * sizeof (gchar));
1140 if (send (fd, b_send->data, b_send->len, MSG_MORE) <= 0)
1142 g_byte_array_free (b_send, TRUE);
1148 _flush_queue (GMencoder *self)
1151 GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE(self);
1153 if (BUFFER_SIZE == 0)
1156 if (priv->queue->len > 0) {
1157 _send_buffer (priv->fd, priv->queue->data, priv->queue->len);
1158 priv->queue = g_byte_array_remove_range (priv->queue, 0, priv->queue->len);
1161 end_msg = g_strdup ("0\r\n\r\n");
1162 write (priv->fd, (const guint8*) end_msg, strlen(end_msg) * sizeof(gchar));
1167 _buffer_arrive_cb (GstElement* object,
1172 GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE(user_data);
1174 if (GST_BUFFER_SIZE (buff) == 0)
1177 if (BUFFER_SIZE == 0) {
1178 if (_send_buffer (priv->fd, GST_BUFFER_DATA (buff), GST_BUFFER_SIZE (buff)) == FALSE)
1183 priv->queue = g_byte_array_append (priv->queue, GST_BUFFER_DATA (buff), GST_BUFFER_SIZE (buff));
1184 while (priv->queue->len >= BUFFER_SIZE) {
1185 if (priv->send_chunked) {
1186 if (_send_buffer (priv->fd, priv->queue->data, BUFFER_SIZE) == FALSE)
1189 if (write (priv->fd, priv->queue->data, BUFFER_SIZE) == -1)
1192 priv->queue = g_byte_array_remove_range (priv->queue, 0, BUFFER_SIZE);
1197 if (priv->tick_id != 0) {
1198 g_source_remove(priv->tick_id);
1201 priv->queue = g_byte_array_remove_range (priv->queue, 0, priv->queue->len);
1202 g_signal_emit(user_data, g_mencoder_signals[ERROR], 0, "Error on socket");