renatofilho@588: #ifdef HAVE_CONFIG_H
renatofilho@588: #include "config.h"
renatofilho@588: #endif
renatofilho@588: 
renatofilho@600: #include <sys/stat.h>
renatofilho@600: #include <fcntl.h>
renatofilho@600: #include <unistd.h>
renatofilho@588: #include <glib.h>
renatofilho@588: #include <gst/gst.h>
renatofilho@588: #include <string.h>
renatofilho@588: 
renatofilho@588: #include "gmencoder.h"
renatofilho@588: 
renatofilho@588: #define G_MENCODER_GET_PRIVATE(obj) \
renatofilho@588:     (G_TYPE_INSTANCE_GET_PRIVATE ((obj), G_TYPE_MENCODER, GMencoderPrivate))
renatofilho@588: 
renatofilho@634: //#define SUPPORT_MULT_INPUT  0
renatofilho@588: 
renatofilho@588: typedef struct _GMencoderPrivate GMencoderPrivate;
renatofilho@600: typedef struct _SetupInfo SetupInfo;
renatofilho@600: 
renatofilho@600: struct _SetupInfo
renatofilho@600: {
renatofilho@600:     gchar* video_encode;
renatofilho@600:     gchar* mux_name;
renatofilho@600:     gchar** video_encode_prop;
renatofilho@600:     gdouble video_fps;
renatofilho@600:     gdouble video_rate;
renatofilho@600:     guint video_width;
renatofilho@600:     guint video_height;                        
renatofilho@600:     gchar* audio_encode;
renatofilho@600:     gchar** audio_encode_prop;
renatofilho@600:     guint audio_rate;
renatofilho@600: };
renatofilho@600: 
renatofilho@588: 
renatofilho@588: struct _GMencoderPrivate
renatofilho@588: {    
renatofilho@588: 	GstElement *pipe;
renatofilho@588: 	GstElement *abin;
renatofilho@588: 	GstElement *vbin;
renatofilho@588: 	GstElement *sink;
renatofilho@671: 	GstElement *src;
renatofilho@588: 	gboolean ready;
renatofilho@600:     SetupInfo *info;
renatofilho@600:     GstClockTime videot;
renatofilho@600:     GstClockTime audiot;
renatofilho@600:     gint fd;
renatofilho@634: 	gint sources;
renatofilho@654: 	gint tick_id;
renatofilho@671: 	gint64 duration;
renatofilho@588: };
renatofilho@588: 
renatofilho@588: enum {
renatofilho@588:   PAUSED,
renatofilho@588:   PLAYING,
renatofilho@588:   STOPED,
renatofilho@588:   EOS,
renatofilho@588:   ERROR,
renatofilho@588:   LAST_SIGNAL
renatofilho@588: };
renatofilho@588: 
renatofilho@588: static void g_mencoder_class_init       (GMencoderClass *klass);
renatofilho@588: static void g_mencoder_init             (GMencoder *object);
renatofilho@588: static void g_mencoder_dispose  	    (GObject *object);
renatofilho@588: static void g_mencoder_finalize 	    (GObject *object);
renatofilho@588: static GstElement*
renatofilho@600:             _create_audio_bin           (const gchar* encode,
renatofilho@600:                                          gchar** encode_prop,
renatofilho@600:                                          gint rate);
renatofilho@588: static GstElement*
renatofilho@600:             _create_video_bin           (const gchar* encode,
renatofilho@588:                                         gchar** encode_prop,
renatofilho@588:                                         gdouble fps,
renatofilho@588:                                         gint rate,
renatofilho@588:                                         guint width, 
renatofilho@588:                                         guint height);
renatofilho@588: 
renatofilho@588: static gboolean 
renatofilho@588:             _pipeline_bus_cb            (GstBus     *bus,
renatofilho@588: 		                                 GstMessage *msg,
renatofilho@588: 		                                 gpointer    user_data);
renatofilho@588: static void _decodebin_new_pad_cb 		(GstElement* object,
renatofilho@588: 				                         GstPad* pad,
renatofilho@588: 				                         gboolean flag,
renatofilho@588: 				                         gpointer user_data);
renatofilho@588: static void  _decodebin_unknown_type_cb (GstElement* object,
renatofilho@588: 		                         	     GstPad* pad,
renatofilho@588:                                          GstCaps* caps,
renatofilho@588:                                          gpointer user_data);
renatofilho@600: static void _close_output              (GMencoder *self);
renatofilho@600: static void _open_output               (GMencoder *self,
renatofilho@600:                                          const gchar* uri);
renatofilho@600: static GstElement* _create_source       (const gchar* uri);
renatofilho@600: static GstElement*_create_pipeline      (GMencoder *self,
renatofilho@600:                                           const gchar* video_encode,
renatofilho@600:                                           const gchar* mux_name,
renatofilho@600:                                           gchar** video_encode_prop,
renatofilho@600:                                           gdouble video_fps,
renatofilho@600:                                           gdouble video_rate,
renatofilho@600:                                           guint video_width, 
renatofilho@600:                                           guint video_height,                         
renatofilho@600:                                           const gchar* audio_encode,
renatofilho@600:                                           gchar** audio_encode_prop,
renatofilho@600:                                           guint audio_rate);
renatofilho@654: static gboolean _tick_cb 				 (gpointer data);
renatofilho@654: 
renatofilho@600: 
renatofilho@600: 
renatofilho@600: 
renatofilho@588: 
renatofilho@588: 
renatofilho@588: static guint g_mencoder_signals[LAST_SIGNAL] = { 0 };
renatofilho@588: 
renatofilho@588: G_DEFINE_TYPE(GMencoder, g_mencoder, G_TYPE_OBJECT)
renatofilho@588: 
renatofilho@588: static void
renatofilho@588: g_mencoder_class_init (GMencoderClass *klass)
renatofilho@588: {   
renatofilho@588: 	GObjectClass *object_class;
renatofilho@588: 
renatofilho@588: 	object_class = (GObjectClass *) klass;
renatofilho@588: 
renatofilho@588: 	g_type_class_add_private (klass, sizeof (GMencoderPrivate));
renatofilho@588:         
renatofilho@588: 	object_class->dispose  = g_mencoder_dispose;
renatofilho@588: 	object_class->finalize = g_mencoder_finalize;	
renatofilho@588: 	
renatofilho@588:     g_mencoder_signals[PAUSED] =
renatofilho@588:         g_signal_new ("paused",
renatofilho@588:     		  G_OBJECT_CLASS_TYPE (object_class),
renatofilho@588:     		  G_SIGNAL_RUN_FIRST,
renatofilho@588:     		  0, NULL, NULL,
renatofilho@588:     		  g_cclosure_marshal_VOID__VOID,
renatofilho@588:     		  G_TYPE_NONE, 0);
renatofilho@588:     		  
renatofilho@588:     g_mencoder_signals[PLAYING] =
renatofilho@588:         g_signal_new ("playing",
renatofilho@588:     		  G_OBJECT_CLASS_TYPE (object_class),
renatofilho@588:     		  G_SIGNAL_RUN_FIRST,
renatofilho@588:     		  0, NULL, NULL,
renatofilho@588:               g_cclosure_marshal_VOID__VOID,
renatofilho@588:     		  G_TYPE_NONE, 0);
renatofilho@588: 
renatofilho@588:     g_mencoder_signals[STOPED] =
renatofilho@588:         g_signal_new ("stoped",
renatofilho@588:     		  G_OBJECT_CLASS_TYPE (object_class),
renatofilho@588:     		  G_SIGNAL_RUN_FIRST,
renatofilho@588:     		  0, NULL, NULL,
renatofilho@588:     		  g_cclosure_marshal_VOID__VOID,
renatofilho@588:     		  G_TYPE_NONE, 0);
renatofilho@588: 
renatofilho@588:     g_mencoder_signals[EOS] =
renatofilho@588:         g_signal_new ("eos",
renatofilho@588:     		  G_OBJECT_CLASS_TYPE (object_class),
renatofilho@588:     		  G_SIGNAL_RUN_FIRST,
renatofilho@588:     		  0, NULL, NULL,
renatofilho@588:     		  g_cclosure_marshal_VOID__VOID,
renatofilho@588:     		  G_TYPE_NONE, 0);
renatofilho@588:     		  
renatofilho@588:     		  
renatofilho@588:     g_mencoder_signals[ERROR] =
renatofilho@588:         g_signal_new ("error",
renatofilho@588:     		  G_OBJECT_CLASS_TYPE (object_class),
renatofilho@678:     		  G_SIGNAL_RUN_LAST,
renatofilho@588:     		  0, NULL, NULL,
renatofilho@588:     		  g_cclosure_marshal_VOID__STRING,
renatofilho@588:     		  G_TYPE_NONE, 1, G_TYPE_STRING);	
renatofilho@588: }
renatofilho@588: 
renatofilho@588: static void
renatofilho@588: g_mencoder_init (GMencoder *self)
renatofilho@588: {
renatofilho@600: 	GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
renatofilho@600:     priv->info = g_new0 (SetupInfo, 1);
renatofilho@588: }
renatofilho@588: 
renatofilho@588: static void 
renatofilho@588: g_mencoder_dispose (GObject *object)
renatofilho@588: {
renatofilho@588: }
renatofilho@588: 
renatofilho@588: static void 
renatofilho@588: g_mencoder_finalize (GObject *object)
renatofilho@588: {
renatofilho@600:     //TODO: clear vars
renatofilho@588: 	g_mencoder_close_stream (G_MENCODER (object));
renatofilho@588: }
renatofilho@588: 
renatofilho@588: GMencoder*  
renatofilho@588: g_mencoder_new (void)
renatofilho@588: {
renatofilho@588:     return g_object_new (G_TYPE_MENCODER, NULL);
renatofilho@588: }
renatofilho@588: 
renatofilho@600: 
renatofilho@588: static void
renatofilho@588: _obj_set_prop (GObject *obj, 
renatofilho@588:                 const gchar *prop_name,
renatofilho@588:                 const gchar *prop_val)
renatofilho@588: {
renatofilho@588:     GValue p = {0};
renatofilho@588:     GValue v = {0};
renatofilho@588:     GParamSpec *s = NULL;
renatofilho@588:     GObjectClass *k = G_OBJECT_GET_CLASS (obj);
renatofilho@588: 
renatofilho@588: 
renatofilho@588:     g_value_init (&v, G_TYPE_STRING);
renatofilho@588:     g_value_set_string (&v, prop_val);
renatofilho@588: 
renatofilho@588:     s = g_object_class_find_property (k, prop_name);
renatofilho@588:     if (s == NULL) {
renatofilho@588:         g_print ("Invalid property name: %s\n", prop_name);
renatofilho@588:         return;
renatofilho@588:     }
renatofilho@588: 
renatofilho@588:     g_value_init (&p, s->value_type);
renatofilho@588:     switch (s->value_type) 
renatofilho@588:     {
renatofilho@588:         case G_TYPE_INT:
renatofilho@588:             g_value_set_int (&p, atoi (prop_val));
renatofilho@588:             break;
renatofilho@588:         case G_TYPE_STRING:
renatofilho@588:             g_value_set_string (&p, prop_val);
renatofilho@588:             break;
renatofilho@588:         default:
renatofilho@588:             return;
renatofilho@588:     }
renatofilho@588:        
renatofilho@588:     g_object_set_property (obj, prop_name, &p);
renatofilho@588:     g_value_unset (&v);
renatofilho@588:     g_value_unset (&p);
renatofilho@588: }
renatofilho@588: 
renatofilho@588: static GstElement*
renatofilho@588: _create_element_with_prop (const gchar* factory_name,
renatofilho@588:                             const gchar* element_name,
renatofilho@588:                             gchar** prop)
renatofilho@588: {
renatofilho@588:     GstElement *ret;
renatofilho@588:     int i;
renatofilho@588: 
renatofilho@588:     ret = gst_element_factory_make (factory_name, element_name);
renatofilho@588:     if (ret == NULL)
renatofilho@588:         return NULL;
renatofilho@588: 
renatofilho@588:     if (prop != NULL) {
renatofilho@588:         for (i=0; i < g_strv_length (prop); i++) {
renatofilho@678: 			if (prop[i] != NULL) {
renatofilho@678:             	char** v = g_strsplit(prop[i], "=", 2);
renatofilho@678:             	if (g_strv_length (v) == 2) {
renatofilho@678:                 	_obj_set_prop (G_OBJECT (ret), v[0], v[1]);
renatofilho@678:             	}	
renatofilho@678:             	g_strfreev (v);
renatofilho@678: 			}
renatofilho@588:         }
renatofilho@588:     }
renatofilho@588: 
renatofilho@588:     return ret;
renatofilho@588: 
renatofilho@588: }
renatofilho@588: 
renatofilho@588: static GstElement*
renatofilho@600: _create_audio_bin (const gchar* encode,
renatofilho@600:                    gchar** encode_prop,
renatofilho@600:                    gint rate)
renatofilho@588: {
renatofilho@588:     GstElement *abin = NULL;
renatofilho@588:     GstElement *aqueue = NULL;
renatofilho@588:     GstElement *aconvert = NULL;
renatofilho@588:     GstElement *aencode = NULL;
renatofilho@588:     GstElement *aqueue_src = NULL;
renatofilho@588:     GstPad *apad = NULL;
renatofilho@588: 
renatofilho@588:     //audio/x-raw-int ! queue ! audioconvert ! faac ! rtpmp4gpay !  udpsink name=upd_audio host=224.0.0.1 port=5002	
renatofilho@588: 	abin 	= gst_bin_new ("abin");
renatofilho@588: 	aqueue	= gst_element_factory_make ("queue", "aqueue");
renatofilho@588: 	aconvert= gst_element_factory_make ("audioconvert", "aconvert");
renatofilho@588: 	aencode = _create_element_with_prop ((encode ? encode : "lame"), "aencode", encode_prop);
renatofilho@588: 	aqueue_src= gst_element_factory_make ("queue", "aqueue_src");	
renatofilho@588: 
renatofilho@588: 	if ((abin == NULL) || (aqueue == NULL) || (aconvert == NULL) 
renatofilho@588: 		|| (aencode == NULL) || (aqueue_src == NULL)) {
renatofilho@588: 		g_warning ("Audio elements not found");
renatofilho@588: 		goto error;
renatofilho@588: 	}
renatofilho@588: 
renatofilho@600:     g_object_set (G_OBJECT (aencode), "bitrate", 32, NULL);
renatofilho@600:     /*
renatofilho@600:     if (rate > 0) {
renatofilho@600:         g_object_set (G_OBJECT (aencode), "bitrate", 32, NULL);
renatofilho@600:     }
renatofilho@600:     */
renatofilho@600: 
renatofilho@588: 	gst_bin_add_many (GST_BIN (abin), aqueue, aconvert, aencode, aqueue_src, NULL);
renatofilho@600: 	if (gst_element_link_many (aqueue, aconvert, aencode, aqueue_src, NULL) == FALSE) {
renatofilho@600:         g_warning ("Not Link audio elements");
renatofilho@600:     }
renatofilho@588: 
renatofilho@588:     //TODO: apply audio rate 
renatofilho@588: 
renatofilho@588: 	// ghost pad the audio bin
renatofilho@588:    	apad = gst_element_get_pad (aqueue, "sink");
renatofilho@588:    	gst_element_add_pad (abin, gst_ghost_pad_new("sink", apad));
renatofilho@588: 	gst_object_unref (apad);
renatofilho@588: 	
renatofilho@588:    	apad = gst_element_get_pad (aqueue_src, "src");
renatofilho@588:    	gst_element_add_pad (abin, gst_ghost_pad_new("src", apad));
renatofilho@588:     gst_object_unref (apad);
renatofilho@588: 
renatofilho@588:     return abin;
renatofilho@588: error:
renatofilho@588:    	if (abin != NULL)
renatofilho@588: 		gst_object_unref (abin);
renatofilho@588: 
renatofilho@588: 	if (aqueue != NULL)
renatofilho@588: 		gst_object_unref (aqueue);
renatofilho@588: 
renatofilho@588: 	if (aconvert != NULL)
renatofilho@588: 		gst_object_unref (aconvert);
renatofilho@588: 
renatofilho@588: 	if (aencode != NULL)
renatofilho@588: 		gst_object_unref (aencode);
renatofilho@588: 
renatofilho@588: 	if (aqueue_src != NULL)
renatofilho@588: 		gst_object_unref (aqueue_src);
renatofilho@588: 
renatofilho@588:     if (apad != NULL)
renatofilho@588:         gst_object_unref (apad);
renatofilho@588: 
renatofilho@588:     return NULL;
renatofilho@588: }
renatofilho@588: 
renatofilho@588: 
renatofilho@588: 
renatofilho@588: 
renatofilho@588: //queue ! videoscale ! video/x-raw-yuv,width=240,height=144 ! colorspace ! rate ! encode ! queue
renatofilho@588: static GstElement*
renatofilho@600: _create_video_bin (const gchar* encode,
renatofilho@588:                     gchar** encode_prop,
renatofilho@588:                     gdouble fps,
renatofilho@588:                     gint rate,
renatofilho@588:                     guint width, 
renatofilho@588:                     guint height)
renatofilho@588: {
renatofilho@588:     GstElement *vbin = NULL;
renatofilho@588:     GstElement *vqueue = NULL;
renatofilho@588:     GstElement* vqueue_src = NULL;
renatofilho@588:     GstElement *vcolorspace = NULL;
renatofilho@588:     GstElement *vencode = NULL;
renatofilho@588:     GstElement *vrate = NULL;
renatofilho@588:     GstPad *vpad = NULL;
renatofilho@588: 
renatofilho@588: 	vbin    = gst_bin_new ("vbin");
renatofilho@588: 	vqueue	= gst_element_factory_make ("queue", "vqueue");
renatofilho@588: 	vcolorspace = gst_element_factory_make ("ffmpegcolorspace", "colorspace");
renatofilho@616: 
renatofilho@616: 	vencode = _create_element_with_prop (
renatofilho@616:             (encode != NULL ? encode : "ffenc_mpeg1video"), 
renatofilho@616:             "vencode", encode_prop);
renatofilho@588: 	vqueue_src = gst_element_factory_make ("queue", "queue_src");
renatofilho@588: 
renatofilho@588: 	if ((vbin == NULL) || (vqueue == NULL) || (vcolorspace == NULL) 
renatofilho@588: 		|| (vencode == NULL) || (vqueue_src == NULL)) {
renatofilho@588: 		g_warning ("Video elements not found");
renatofilho@588: 		goto error;
renatofilho@588: 	}
renatofilho@588: 		
renatofilho@588: 	gst_bin_add_many (GST_BIN (vbin), vqueue, vcolorspace, vencode, vqueue_src, NULL);
renatofilho@588: 
renatofilho@588: 	
renatofilho@588:     if ((width > 0) && (height > 0)) {        
renatofilho@588:         //Scalling video
renatofilho@588:         GstCaps *vcaps;
renatofilho@588: 	    GstElement *vscale  = gst_element_factory_make ("videoscale", "vscale");
renatofilho@588: 
renatofilho@588:         gst_bin_add (GST_BIN (vbin), vscale);
renatofilho@588: 
renatofilho@588:         vcaps = gst_caps_new_simple ("video/x-raw-yuv",
renatofilho@588:                            "width", G_TYPE_INT, width,
renatofilho@588:                            "height", G_TYPE_INT, height,                           
renatofilho@588:                            NULL);
renatofilho@588: 
renatofilho@588:         gst_element_link (vqueue, vscale);
renatofilho@588: 					   	
renatofilho@588:         if (gst_element_link_filtered (vscale, vcolorspace, vcaps) == FALSE) {
renatofilho@588:             g_warning ("Fail to resize video");
renatofilho@588:             gst_object_unref (vcaps);
renatofilho@588:             gst_object_unref (vscale);
renatofilho@588:             goto error;
renatofilho@588:         }
renatofilho@588:         gst_caps_unref (vcaps);
renatofilho@588:     } else {
renatofilho@588:         gst_element_link (vqueue, vcolorspace);
renatofilho@588:     }
renatofilho@600:     
renatofilho@588: 
renatofilho@588:     if (fps > 0) {
renatofilho@588:         //Changing the video fps
renatofilho@588:         GstCaps *vcaps;
renatofilho@616:         vrate   = gst_element_factory_make ("videorate", "vrate");
renatofilho@588: 
renatofilho@588:         gst_bin_add (GST_BIN (vbin), vrate);
renatofilho@588: 
renatofilho@588:     	if (gst_element_link (vcolorspace, vrate) == FALSE) {
renatofilho@588: 	        g_warning ("Fail to link video elements");
renatofilho@588: 	        goto error;
renatofilho@588:     	}
renatofilho@588: 
renatofilho@588:     	vcaps = gst_caps_new_simple ("video/x-raw-yuv",
renatofilho@616: 					   "framerate", GST_TYPE_FRACTION,  (int) (fps * 1000), 1000, NULL);
renatofilho@588: 
renatofilho@588:         if (gst_element_link_filtered (vrate, vencode, vcaps) == FALSE) { 
renatofilho@588:            g_warning ("Fail to link vrate with vencode.");
renatofilho@588:            goto error;
renatofilho@588:         }
renatofilho@588:         gst_caps_unref (vcaps);
renatofilho@588:     } else {
renatofilho@588:         if (gst_element_link (vcolorspace, vencode) == FALSE) {
renatofilho@588:             g_warning ("Fail to link colorspace and video encode element.");
renatofilho@588:             goto error;
renatofilho@588:         }
renatofilho@588:     }
renatofilho@588:     
renatofilho@588:     gst_element_link (vencode, vqueue_src);
renatofilho@588: 
renatofilho@588: 	// ghost pad the video  bin
renatofilho@588:    	vpad = gst_element_get_pad (vqueue, "sink");
renatofilho@588:    	gst_element_add_pad (vbin, gst_ghost_pad_new ("sink", vpad));	
renatofilho@588: 	gst_object_unref (vpad);
renatofilho@588: 	
renatofilho@588:    	vpad = gst_element_get_pad (vqueue_src, "src");
renatofilho@588:    	gst_element_add_pad (vbin, gst_ghost_pad_new ("src", vpad));	
renatofilho@588: 	gst_object_unref (vpad);
renatofilho@588: 
renatofilho@588:     return vbin;
renatofilho@588: 
renatofilho@588: error:
renatofilho@588:     if (vpad != NULL)
renatofilho@588:         gst_object_unref (vpad);
renatofilho@588: 
renatofilho@588: 	if (vbin != NULL)
renatofilho@588: 		gst_object_unref (vbin);
renatofilho@588: 
renatofilho@588: 	if (vqueue != NULL)
renatofilho@588: 		gst_object_unref (vqueue);
renatofilho@588: 
renatofilho@588: 	if (vencode != NULL)
renatofilho@588: 		gst_object_unref (vencode);
renatofilho@588: 
renatofilho@588: 	if (vqueue_src != NULL)
renatofilho@588: 		gst_object_unref (vqueue_src);
renatofilho@588: 
renatofilho@588:     if (vcolorspace != NULL)
renatofilho@588:         gst_object_unref (vcolorspace);
renatofilho@588: 
renatofilho@588:     return NULL;
renatofilho@588: }
renatofilho@588: 
renatofilho@588: 
renatofilho@600: 
renatofilho@600: void
renatofilho@588: g_mencoder_setup_stream (GMencoder *self, 
renatofilho@616:                          const gchar* mux_name,
renatofilho@588:                          const gchar* video_encode,
renatofilho@588:                          gchar** video_encode_prop,
renatofilho@588:                          gdouble video_fps,
renatofilho@588:                          gdouble video_rate,
renatofilho@588:                          guint video_width, 
renatofilho@600:                          guint video_height,                         
renatofilho@588:                          const gchar* audio_encode,
renatofilho@588:                          gchar** audio_encode_prop,
renatofilho@588:                          guint audio_rate,
renatofilho@600:                          const gchar* out_uri)
renatofilho@600: {
renatofilho@600:     GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
renatofilho@600:     if (priv->ready == TRUE) {
renatofilho@600:         g_warning ("Stream already configured. You need close stream first.");
renatofilho@600:         return;
renatofilho@600:     }
renatofilho@600: 
renatofilho@634:     _close_output (self);
renatofilho@634:     _open_output (self, out_uri);
renatofilho@634: 
renatofilho@634: 	priv->sources = 0;
renatofilho@600:     priv->pipe = _create_pipeline (self,
renatofilho@600:             video_encode,
renatofilho@600:             mux_name,
renatofilho@600:             video_encode_prop,
renatofilho@600:             video_fps,
renatofilho@600:             video_rate,
renatofilho@600:             video_width,
renatofilho@600:             video_height,
renatofilho@600:             audio_encode,
renatofilho@600:             audio_encode_prop,
renatofilho@600:             audio_rate);
renatofilho@600: 
renatofilho@600: }
renatofilho@600: 
renatofilho@600: 
renatofilho@600: gboolean
renatofilho@600: g_mencoder_append_uri (GMencoder *self,
renatofilho@600:                      const gchar* uri)
renatofilho@600: {
renatofilho@600:     GstPad *pad_src;
renatofilho@600:     GstPad *pad_sink;
renatofilho@600:     GstElement *src;
renatofilho@600:     GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
renatofilho@600:     gboolean ret = FALSE;
renatofilho@634:     GstElement *ap = NULL;
renatofilho@634:     GstElement *vp = NULL;
renatofilho@634: 
renatofilho@600: 
renatofilho@600:     g_return_val_if_fail (priv->pipe != NULL, FALSE);
renatofilho@600:     g_return_val_if_fail (priv->ready == FALSE, FALSE);
renatofilho@600: 
renatofilho@634: #ifndef SUPPORT_MULT_INPUT
renatofilho@634: 	g_return_val_if_fail (priv->sources < 1, FALSE);
renatofilho@634: #endif
renatofilho@634: 
renatofilho@600:     src = _create_source (uri);
renatofilho@600:     if (src == NULL) 
renatofilho@600:         return FALSE;
renatofilho@600: 
renatofilho@671: 	priv->src = gst_bin_get_by_name (GST_BIN (src), "src");
renatofilho@671: 
renatofilho@600:     gst_bin_add (GST_BIN (priv->pipe), src);
renatofilho@600: 
renatofilho@634: #ifdef SUPPORT_MULT_INPUT
renatofilho@600:     ap = gst_bin_get_by_name (GST_BIN (priv->pipe), "ap");
renatofilho@600:     vp = gst_bin_get_by_name (GST_BIN (priv->pipe), "vp");
renatofilho@634: #else
renatofilho@634:     ap = gst_bin_get_by_name (GST_BIN (priv->pipe), "abin");
renatofilho@634:     vp = gst_bin_get_by_name (GST_BIN (priv->pipe), "vbin");
renatofilho@634: #endif
renatofilho@634: 
renatofilho@634:     if ((vp == NULL)  || (ap == NULL)) {
renatofilho@634: 		g_warning  ("Fail to get output bin");
renatofilho@600:         goto error;
renatofilho@634: 	}
renatofilho@600: 
renatofilho@600:     pad_src = gst_element_get_pad (src, "src_audio");
renatofilho@600:     pad_sink = gst_element_get_compatible_pad (ap, 
renatofilho@600:             pad_src, 
renatofilho@600:             gst_pad_get_caps (pad_src));
renatofilho@600: 
renatofilho@600:     if ((pad_sink == NULL) || (pad_src == NULL))
renatofilho@600:         goto error;
renatofilho@600: 
renatofilho@600:     GstPadLinkReturn lret = gst_pad_link (pad_src, pad_sink);
renatofilho@600:     if (lret != GST_PAD_LINK_OK)
renatofilho@600:         goto error;
renatofilho@600: 
renatofilho@600:     gst_object_unref (pad_src);
renatofilho@600:     gst_object_unref (pad_sink);
renatofilho@600: 
renatofilho@600:     pad_src = gst_element_get_pad (src, "src_video");
renatofilho@600:     pad_sink = gst_element_get_compatible_pad (vp, 
renatofilho@600:             pad_src, 
renatofilho@600:             gst_pad_get_caps (pad_src));
renatofilho@600: 
renatofilho@600:     if ((pad_src == NULL) || (pad_sink == NULL))
renatofilho@600:         goto error;
renatofilho@600: 
renatofilho@600:     if (gst_pad_link (pad_src, pad_sink) != GST_PAD_LINK_OK) {
renatofilho@600:         g_warning ("invalid source. video");
renatofilho@600:         goto error;
renatofilho@600:     }
renatofilho@600: 
renatofilho@634: 	priv->sources++;
renatofilho@600:     ret = TRUE;
renatofilho@600: error:
renatofilho@600: 
renatofilho@600:     if ((src != NULL) && (ret == FALSE)) {
renatofilho@600:         gst_bin_remove (GST_BIN (priv->pipe), src);
renatofilho@600:         gst_object_unref (src);
renatofilho@600:     }
renatofilho@600: 
renatofilho@600:     if (ap != NULL) 
renatofilho@600:         gst_object_unref (ap);
renatofilho@600: 
renatofilho@600:     if (vp != NULL)
renatofilho@600:         gst_object_unref (vp);
renatofilho@600: 
renatofilho@600:     if (pad_src != NULL)
renatofilho@600:         gst_object_unref (pad_src);
renatofilho@600: 
renatofilho@600:     if (pad_sink != NULL)
renatofilho@600:         gst_object_unref (pad_sink);
renatofilho@600: 
renatofilho@600:     return ret;
renatofilho@600: }
renatofilho@600: 
renatofilho@600: 
renatofilho@600: 
renatofilho@600: void        
renatofilho@600: g_mencoder_remove_uri (GMencoder *self,
renatofilho@600:                         const gchar* uri)
renatofilho@600: {
renatofilho@600:     // GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
renatofilho@600:     //TODO: remove src
renatofilho@600: }
renatofilho@600: 
renatofilho@600: void
renatofilho@600: g_mencoder_play_stream (GMencoder *self)
renatofilho@600: {
renatofilho@600:     GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
renatofilho@600: 
renatofilho@600:     g_return_if_fail (priv->ready == FALSE);
renatofilho@600:     priv->ready = TRUE;
renatofilho@600:     gst_element_set_state (priv->pipe, GST_STATE_PLAYING);
renatofilho@654: 
renatofilho@654: 	priv->tick_id = g_timeout_add (500, _tick_cb, self);
renatofilho@600: }
renatofilho@600: 
renatofilho@600: void
renatofilho@600: g_mencoder_pause_stream (GMencoder *self)
renatofilho@600: {
renatofilho@600:     GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
renatofilho@600: 
renatofilho@600:     g_return_if_fail (priv->ready == TRUE);
renatofilho@600:     gst_element_set_state (priv->pipe, GST_STATE_PAUSED);
renatofilho@600: }
renatofilho@600: 
renatofilho@600: void
renatofilho@600: g_mencoder_close_stream (GMencoder *self)
renatofilho@600: {
renatofilho@600: 
renatofilho@600:     GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
renatofilho@600: 
renatofilho@654: 	if (priv->tick_id != 0) {			
renatofilho@654: 		g_source_remove (priv->tick_id);
renatofilho@654: 		priv->tick_id = 0;
renatofilho@654: 	}
renatofilho@654: 
renatofilho@600:     if (priv->pipe != NULL) { 
renatofilho@691: 		//TODO: fixe pipeline dispose
renatofilho@692: 		g_debug ("SETING STATE TO NULL");
melunko@703:         //gst_element_set_state (priv->pipe, GST_STATE_NULL);
renatofilho@692: 		g_debug ("SETING STATE TO NULL: OK");
renatofilho@678:         //gst_object_unref (priv->pipe);
renatofilho@678:         gst_object_unref (priv->src);
renatofilho@678: 		priv->src = NULL;
renatofilho@600:         priv->pipe = NULL;
renatofilho@600:         priv->abin = NULL;
renatofilho@600:         priv->vbin = NULL;
renatofilho@600:         priv->sink = NULL;
renatofilho@600:     }
renatofilho@600:     priv->ready = FALSE;
renatofilho@600: }
renatofilho@600: 
renatofilho@600: static GstElement*
renatofilho@600: _create_pipeline (GMencoder *self,
renatofilho@600:                   const gchar* video_encode,
renatofilho@600:                   const gchar* mux_name,
renatofilho@600:                   gchar** video_encode_prop,
renatofilho@600:                   gdouble video_fps,
renatofilho@600:                   gdouble video_rate,
renatofilho@600:                   guint video_width, 
renatofilho@600:                   guint video_height,                         
renatofilho@600:                   const gchar* audio_encode,
renatofilho@600:                   gchar** audio_encode_prop,
renatofilho@600:                   guint audio_rate)
renatofilho@588: {
renatofilho@712:     GstBus *bus = NULL;
renatofilho@712:     GstElement *pipe = NULL;
renatofilho@712:     GstElement *sink = NULL;
renatofilho@588:     GstElement *mux = NULL;
renatofilho@588:     GstElement *abin = NULL;
renatofilho@600:     GstElement *vbin = NULL;    
renatofilho@712:     GstElement *queue= NULL;
renatofilho@634:     GstPad *aux_pad = NULL;
renatofilho@634:     GstPad *mux_pad = NULL;
renatofilho@634: #ifdef SUPPORT_MULT_INPUT
renatofilho@600:     GstElement *ap = NULL;
renatofilho@600:     GstElement *vp = NULL;    
renatofilho@634: #endif
renatofilho@634:     GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
renatofilho@588: 
renatofilho@600: 	pipe = gst_pipeline_new ("pipe");
renatofilho@588: 
renatofilho@634: #ifdef SUPPORT_MULT_INPUT			
renatofilho@634: 	ap = gst_element_factory_make ("concatmux", "ap");
renatofilho@614:     vp = gst_element_factory_make ("concatmux", "vp");
renatofilho@634: 	gst_bin_add_many (GST_BIN (pipe), ap, vp, NULL);
renatofilho@634: #endif
renatofilho@588: 
renatofilho@600:     mux = gst_element_factory_make ((mux_name ? mux_name : "ffmux_mpeg"), "mux");
renatofilho@588:     if (mux == NULL)
renatofilho@588:         goto error;
renatofilho@588: 
renatofilho@712:     queue = gst_element_factory_make ("queue", "queueu_sink");
renatofilho@712: 
renatofilho@634: 
renatofilho@634:     sink = gst_element_factory_make ("fdsink", "sink");
renatofilho@600:     if (sink == NULL)
renatofilho@588:         goto error;
renatofilho@588: 
renatofilho@600:     g_object_set (G_OBJECT(sink), 
renatofilho@634: 			"fd", priv->fd,
renatofilho@712: 			"sync", FALSE,
renatofilho@634:             NULL);
renatofilho@600: 
renatofilho@600:     abin = _create_audio_bin (audio_encode, audio_encode_prop, audio_rate);
renatofilho@588:     if (abin == NULL)
renatofilho@588:         goto error;
renatofilho@588: 
renatofilho@600:     vbin = _create_video_bin (video_encode, video_encode_prop, video_fps, video_rate, video_width, video_height);
renatofilho@588:     if (vbin == NULL)
renatofilho@588:         goto error;
renatofilho@588: 
renatofilho@588: 	// Finish Pipe
renatofilho@712:     gst_bin_add_many (GST_BIN (pipe), abin, vbin, mux, queue, sink, NULL);
renatofilho@600: 
renatofilho@600: 
renatofilho@634: #ifdef SUPPORT_MULT_INPUT	
renatofilho@634: 	if (gst_element_link (ap, abin) == FALSE) {
renatofilho@634: 		g_warning ("Fail to link concat and abin");
renatofilho@634: 		goto error;
renatofilho@634: 	}
renatofilho@634: 
renatofilho@634: 	if (gst_element_link (vp, vbin) == FALSE) {
renatofilho@634: 		g_warning ("Fail to link concat and vbin");
renatofilho@634: 	}
renatofilho@634: #endif	
renatofilho@588: 
renatofilho@588:     //Link bins with mux
renatofilho@588:     aux_pad = gst_element_get_pad (abin, "src");
renatofilho@617:     mux_pad = gst_element_get_compatible_pad (mux, aux_pad, GST_PAD_CAPS (aux_pad));
renatofilho@600:     if (mux_pad == NULL) {
renatofilho@617:         g_warning ("Mux element no have audio PAD");
renatofilho@600:         goto error;
renatofilho@600:     }
renatofilho@588:     GstPadLinkReturn ret = gst_pad_link (aux_pad, mux_pad);
renatofilho@588:     if (ret != GST_PAD_LINK_OK) {
renatofilho@588:         g_warning ("Fail link audio and mux: %d", ret);
renatofilho@588:         goto error;
renatofilho@588:    
renatofilho@588:     }
renatofilho@588: 	gst_object_unref (aux_pad);
renatofilho@588:     gst_object_unref (mux_pad);
renatofilho@588: 
renatofilho@588:     aux_pad = gst_element_get_pad (vbin, "src");
renatofilho@617:     mux_pad = gst_element_get_compatible_pad (mux, aux_pad, GST_PAD_CAPS (aux_pad));
renatofilho@600:     if (mux_pad == NULL) {
renatofilho@617:         g_warning ("Mux element no have video PAD");
renatofilho@600:         goto error;
renatofilho@600:     }
renatofilho@588:     ret = gst_pad_link (aux_pad, mux_pad);
renatofilho@588:     if (ret != GST_PAD_LINK_OK) {
renatofilho@588:         g_warning ("Fail link video and mux: %d", ret);
renatofilho@588:         goto error;
renatofilho@588:     }
renatofilho@588:     gst_object_unref (aux_pad);
renatofilho@588:     gst_object_unref (mux_pad);
renatofilho@588:     aux_pad = NULL;
renatofilho@588:     mux_pad = NULL;
renatofilho@588: 
renatofilho@588:     //Link mux with sink
renatofilho@712:     gst_element_link_many (mux, queue, sink, NULL);
renatofilho@588: 
renatofilho@588: 	bus = gst_pipeline_get_bus (GST_PIPELINE (pipe));
renatofilho@588: 	gst_bus_add_watch (bus, _pipeline_bus_cb, self);
renatofilho@588: 	gst_object_unref (bus);
renatofilho@600:     return pipe;
renatofilho@588: 	
renatofilho@588: error:
renatofilho@588: 	g_warning ("Invalid uri");
renatofilho@588: 
renatofilho@588: 	if (pipe != NULL) {
renatofilho@588: 		gst_object_unref (pipe);
renatofilho@588:     }
renatofilho@588: 
renatofilho@588: 
renatofilho@588:     if (mux != NULL) {
renatofilho@588:         gst_object_unref (mux);
renatofilho@588:     }
renatofilho@588: 
renatofilho@588:     if (mux_pad != NULL) {
renatofilho@588:         gst_object_unref (mux_pad);
renatofilho@588:     }
renatofilho@588: 
renatofilho@588:     if (aux_pad != NULL) {
renatofilho@588:         gst_object_unref (mux_pad);
renatofilho@588:     }
renatofilho@588: 
renatofilho@600: 	if (sink != NULL) {
renatofilho@600: 		gst_object_unref (sink);
renatofilho@588:     }
renatofilho@588: 
renatofilho@588:     if (abin != NULL) {
renatofilho@588:         gst_object_unref (abin);
renatofilho@588:     }
renatofilho@588: 
renatofilho@588:     if (vbin != NULL) {
renatofilho@588:         gst_object_unref (vbin);
renatofilho@588:     }
renatofilho@588: 
renatofilho@588: 	return FALSE;
renatofilho@588: }
renatofilho@588: 
renatofilho@600: 
renatofilho@600: static void
renatofilho@600: _close_output (GMencoder *self)
renatofilho@588: {
renatofilho@600:     
renatofilho@600: }
renatofilho@600: 
renatofilho@600: static GstElement*
renatofilho@600: _create_source (const gchar* uri)
renatofilho@600: {
renatofilho@600: 
renatofilho@671:     GstElement *bsrc = NULL;
renatofilho@671:     GstElement *src = NULL;
renatofilho@712:     GstElement *queue = NULL;
renatofilho@671:     GstElement *aqueue = NULL;
renatofilho@671:     GstElement *vqueue = NULL;
renatofilho@671:     GstElement *decode = NULL;
renatofilho@671:     GstPad *src_pad = NULL;
renatofilho@600: 
renatofilho@600: 
renatofilho@600:     bsrc = gst_bin_new (NULL);
renatofilho@600: 
renatofilho@634: 	//src = gst_element_factory_make ("gnomevfssrc", "src");
renatofilho@634:     //g_object_set (G_OBJECT (src), "location", uri, NULL);
renatofilho@634: 	src = gst_element_make_from_uri (GST_URI_SRC, uri, "src");
renatofilho@600: 	if (src == NULL) 
renatofilho@600: 		goto error;
renatofilho@600: 
renatofilho@712: 	decode = gst_element_factory_make ("decodebin", "decode");
renatofilho@600: 	if (decode == NULL) 
renatofilho@600: 		goto error;
renatofilho@600: 
renatofilho@712:     queue = gst_element_factory_make ("queue", "queue_src");
renatofilho@600:     aqueue = gst_element_factory_make ("queue", "aqueue");
renatofilho@600:     if (aqueue == NULL)
renatofilho@600:         goto error;
renatofilho@600: 
renatofilho@600:     vqueue = gst_element_factory_make ("queue", "vqueue");
renatofilho@600:     if (vqueue == NULL)
renatofilho@600:         goto error;
renatofilho@600: 
renatofilho@712:     gst_bin_add_many (GST_BIN (bsrc), src, queue, decode, aqueue, vqueue, NULL);
renatofilho@712:     gst_element_link_many (src, queue, decode, NULL);
renatofilho@600: 
renatofilho@600: 	g_signal_connect (G_OBJECT (decode), 
renatofilho@600: 				"new-decoded-pad",
renatofilho@600: 				G_CALLBACK (_decodebin_new_pad_cb),
renatofilho@600: 				bsrc);
renatofilho@600: 
renatofilho@600: 	g_signal_connect (G_OBJECT (decode),
renatofilho@600: 				"unknown-type",
renatofilho@600: 				G_CALLBACK (_decodebin_unknown_type_cb),
renatofilho@600: 				pipe);
renatofilho@600: 
renatofilho@600:     src_pad = gst_element_get_pad (aqueue, "src");
renatofilho@600:    	gst_element_add_pad (bsrc, gst_ghost_pad_new("src_audio", src_pad));
renatofilho@600:     gst_object_unref (src_pad);
renatofilho@600: 
renatofilho@600:     src_pad = gst_element_get_pad (vqueue, "src");
renatofilho@600:    	gst_element_add_pad (bsrc, gst_ghost_pad_new("src_video", src_pad));
renatofilho@600:     gst_object_unref (src_pad);
renatofilho@600: 
renatofilho@600:     return bsrc;
renatofilho@600: 
renatofilho@600: error:
renatofilho@600: 	if (src != NULL) {
renatofilho@600: 		gst_object_unref (src);
renatofilho@600:     }
renatofilho@600: 
renatofilho@600: 	if (decode != NULL) {
renatofilho@600: 		gst_object_unref (decode);
renatofilho@600:     }
renatofilho@600: 
renatofilho@600: 	if (aqueue != NULL) {
renatofilho@600: 		gst_object_unref (aqueue);
renatofilho@600:     }
renatofilho@600: 
renatofilho@600: 	if (vqueue != NULL) {
renatofilho@600: 		gst_object_unref (vqueue);
renatofilho@600:     }
renatofilho@600: 
renatofilho@600:     return NULL;
renatofilho@600: }
renatofilho@600: 
renatofilho@600: static void
renatofilho@600: _open_output (GMencoder *self, 
renatofilho@600:               const gchar* uri)
renatofilho@600: {
renatofilho@600:     gchar** i;
renatofilho@588:     GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
renatofilho@588: 
renatofilho@600:     i = g_strsplit (uri, "://", 0);
renatofilho@600:     if (strcmp (i[0], "fd") == 0) {
renatofilho@600:         priv->fd = atoi (i[1]);
renatofilho@600:     } else if (strcmp (i[0], "file") == 0) {
renatofilho@600:         priv->fd = open (i[1], O_WRONLY | O_CREAT | O_TRUNC);
renatofilho@600:     } else {
renatofilho@600:         g_warning ("Output uri not supported");
renatofilho@600:     }
renatofilho@588: 
renatofilho@600:     g_strfreev (i);
renatofilho@588: }
renatofilho@588: 
renatofilho@588: static gboolean
renatofilho@588: _pipeline_bus_cb (GstBus     *bus,
renatofilho@588: 		  GstMessage *msg,
renatofilho@588: 		  gpointer    user_data)
renatofilho@588: {
renatofilho@600: 	GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (user_data);
renatofilho@600: 
renatofilho@588: 	switch (GST_MESSAGE_TYPE (msg)) 
renatofilho@588: 	{
renatofilho@588: 		case GST_MESSAGE_STATE_CHANGED:
renatofilho@588: 		{
renatofilho@588: 			GstState oldstate;
renatofilho@588: 			GstState newstate;
renatofilho@588: 			GstState pendingstate;
renatofilho@588: 
renatofilho@588: 
renatofilho@588: 			gst_message_parse_state_changed (msg, &oldstate,
renatofilho@588: 				&newstate, &pendingstate);
renatofilho@588: 
renatofilho@588:             if (pendingstate != GST_STATE_VOID_PENDING)
renatofilho@588:                 break;
renatofilho@588: 
renatofilho@588:             if ((oldstate == GST_STATE_READY) && 
renatofilho@588:                 (newstate == GST_STATE_PAUSED)) {
renatofilho@588:                     if (priv->ready) 
renatofilho@588:                         g_signal_emit (user_data, g_mencoder_signals[PAUSED], 0);
renatofilho@588:             } else if ((oldstate == GST_STATE_PAUSED) &&
renatofilho@588:                        (newstate == GST_STATE_PLAYING)) {
renatofilho@588:                         g_signal_emit (user_data, g_mencoder_signals[PLAYING], 0);
renatofilho@588:             } else if ((oldstate == GST_STATE_READY) &&
renatofilho@588:                        (newstate == GST_STATE_NULL)) {
renatofilho@588:                         g_signal_emit (user_data, g_mencoder_signals[STOPED], 0);
renatofilho@588:             }			
renatofilho@588:             break;
renatofilho@588: 		}
renatofilho@588: 		case GST_MESSAGE_ERROR: 
renatofilho@588: 		{
renatofilho@588: 		    GError *error;
renatofilho@588: 		    gchar *debug;
renatofilho@588: 		    gchar *err_str;
renatofilho@678: 
renatofilho@678: 			if (priv->tick_id != 0) {			
renatofilho@678: 				g_source_remove (priv->tick_id);
renatofilho@678: 				priv->tick_id = 0;
renatofilho@678: 			}
renatofilho@588: 		    
renatofilho@588: 		    gst_message_parse_error (msg, &error, &debug);
renatofilho@588: 		    err_str = g_strdup_printf ("Error [%d] %s (%s)", error->code,
renatofilho@588: 		        error->message,
renatofilho@588: 		        debug);
renatofilho@678:             priv->ready = FALSE;
renatofilho@588: 		    g_signal_emit (user_data, g_mencoder_signals[ERROR], 0, err_str);
renatofilho@588: 		    g_free (err_str);
renatofilho@588: 		    g_clear_error (&error);
renatofilho@588: 		    g_free (debug);
renatofilho@588: 		    break;
renatofilho@588: 		}
renatofilho@588: 		
renatofilho@588: 		case GST_MESSAGE_EOS:
renatofilho@600:             priv->ready = FALSE;
renatofilho@588: 		    g_signal_emit (user_data, g_mencoder_signals[EOS], 0);
renatofilho@588: 		    break;		
renatofilho@671: 		case GST_MESSAGE_DURATION:
renatofilho@671: 		{
renatofilho@671: 			GstFormat format;
renatofilho@671: 			gint64 duration;
renatofilho@671: 			gst_message_parse_duration (msg, &format, &duration);
renatofilho@671: 			if (format == GST_FORMAT_BYTES)
renatofilho@671: 				priv->duration = duration;
renatofilho@671: 			break;
renatofilho@671: 		}
renatofilho@588: 		default:
renatofilho@654: 		{
renatofilho@588: 			break;
renatofilho@654: 		}
renatofilho@588: 	}
renatofilho@588: 	return TRUE;
renatofilho@588: }
renatofilho@588: 
renatofilho@600: 
renatofilho@600: 
renatofilho@588: static void 
renatofilho@588: _decodebin_new_pad_cb (GstElement* object,
renatofilho@588:                        GstPad* pad,
renatofilho@588:                        gboolean flag,
renatofilho@588:                        gpointer user_data)
renatofilho@588: {
renatofilho@588: 	GstCaps *caps;
renatofilho@588: 	gchar *str_caps = NULL;
renatofilho@600:     GstElement *sink_element;
renatofilho@600:     GstPad *sink_pad;
renatofilho@588: 
renatofilho@588: 	caps = gst_pad_get_caps (pad);
renatofilho@588: 	str_caps = gst_caps_to_string (caps);
renatofilho@588: 	if (strstr (str_caps, "audio") != NULL) {
renatofilho@600:         sink_element = gst_bin_get_by_name (GST_BIN (user_data), "aqueue");
renatofilho@588: 	} else if (strstr (str_caps, "video") != NULL) {
renatofilho@600:         sink_element = gst_bin_get_by_name (GST_BIN (user_data), "vqueue");
renatofilho@588: 	} else {
renatofilho@588: 		g_warning ("invalid caps %s", str_caps);
renatofilho@588: 	}
renatofilho@588: 
renatofilho@600:     sink_pad = gst_element_get_pad (sink_element, "sink");
renatofilho@600: 	gst_pad_link (pad, sink_pad);
renatofilho@600: 
renatofilho@600:     gst_object_unref (sink_element);
renatofilho@600: 	gst_object_unref (sink_pad);
renatofilho@588: 	g_free (str_caps);
renatofilho@588: 	gst_caps_unref (caps);
renatofilho@588: }
renatofilho@588: 
renatofilho@588: static void 
renatofilho@588: _decodebin_unknown_type_cb (GstElement* object,
renatofilho@588:                             GstPad* pad,
renatofilho@588:                             GstCaps* caps,
renatofilho@588:                             gpointer user_data)
renatofilho@588: {
renatofilho@588:     g_warning  ("Unknown Type");
renatofilho@600:     //priv->ready = FALSE;
renatofilho@588: }
renatofilho@654: 
renatofilho@654: static gboolean
renatofilho@654: _tick_cb (gpointer user_data)
renatofilho@654: {
renatofilho@671: 	GstFormat format = GST_FORMAT_BYTES;
renatofilho@654: 	gint64 cur = 0;
renatofilho@654: 
renatofilho@654: 	GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (user_data);
renatofilho@654: 
renatofilho@671: 	if (priv->duration == 0) {
renatofilho@671: 		gint64 d = 0;
renatofilho@671: 		if (gst_element_query_duration (priv->src, &format, &d))
renatofilho@671: 			priv->duration = d;
renatofilho@671: 	}			
renatofilho@671: 
renatofilho@671: 	if (priv->duration != 0) {
renatofilho@671: 		gst_element_query_position (priv->src, &format, &cur);
renatofilho@671: 		g_print ("PROGRESS:%lli\n", (99 * cur) / priv->duration); 
renatofilho@654: 	}
renatofilho@654: 
renatofilho@654: 	return TRUE;
renatofilho@654: }