gmyth-stream/gmemcoder/src/gmencoder.c
author melunko
Thu May 24 21:14:40 2007 +0100 (2007-05-24)
branchtrunk
changeset 708 eaa6e1c5fab2
parent 692 d9c6cce2b167
child 712 8d28bf09d12f
permissions -rw-r--r--
[svn r714] version increased to 0.3. test binary removed from debian package
     1 #ifdef HAVE_CONFIG_H
     2 #include "config.h"
     3 #endif
     4 
     5 #include <sys/stat.h>
     6 #include <fcntl.h>
     7 #include <unistd.h>
     8 #include <glib.h>
     9 #include <gst/gst.h>
    10 #include <string.h>
    11 
    12 #include "gmencoder.h"
    13 
    14 #define G_MENCODER_GET_PRIVATE(obj) \
    15     (G_TYPE_INSTANCE_GET_PRIVATE ((obj), G_TYPE_MENCODER, GMencoderPrivate))
    16 
    17 //#define SUPPORT_MULT_INPUT  0
    18 
    19 typedef struct _GMencoderPrivate GMencoderPrivate;
    20 typedef struct _SetupInfo SetupInfo;
    21 
    22 struct _SetupInfo
    23 {
    24     gchar* video_encode;
    25     gchar* mux_name;
    26     gchar** video_encode_prop;
    27     gdouble video_fps;
    28     gdouble video_rate;
    29     guint video_width;
    30     guint video_height;                        
    31     gchar* audio_encode;
    32     gchar** audio_encode_prop;
    33     guint audio_rate;
    34 };
    35 
    36 
    37 struct _GMencoderPrivate
    38 {    
    39 	GstElement *pipe;
    40 	GstElement *abin;
    41 	GstElement *vbin;
    42 	GstElement *sink;
    43 	GstElement *src;
    44 	gboolean ready;
    45     SetupInfo *info;
    46     GstClockTime videot;
    47     GstClockTime audiot;
    48     gint fd;
    49 	gint sources;
    50 	gint tick_id;
    51 	gint64 duration;
    52 };
    53 
    54 enum {
    55   PAUSED,
    56   PLAYING,
    57   STOPED,
    58   EOS,
    59   ERROR,
    60   LAST_SIGNAL
    61 };
    62 
    63 static void g_mencoder_class_init       (GMencoderClass *klass);
    64 static void g_mencoder_init             (GMencoder *object);
    65 static void g_mencoder_dispose  	    (GObject *object);
    66 static void g_mencoder_finalize 	    (GObject *object);
    67 static GstElement*
    68             _create_audio_bin           (const gchar* encode,
    69                                          gchar** encode_prop,
    70                                          gint rate);
    71 static GstElement*
    72             _create_video_bin           (const gchar* encode,
    73                                         gchar** encode_prop,
    74                                         gdouble fps,
    75                                         gint rate,
    76                                         guint width, 
    77                                         guint height);
    78 
    79 static gboolean 
    80             _pipeline_bus_cb            (GstBus     *bus,
    81 		                                 GstMessage *msg,
    82 		                                 gpointer    user_data);
    83 static void _decodebin_new_pad_cb 		(GstElement* object,
    84 				                         GstPad* pad,
    85 				                         gboolean flag,
    86 				                         gpointer user_data);
    87 static void  _decodebin_unknown_type_cb (GstElement* object,
    88 		                         	     GstPad* pad,
    89                                          GstCaps* caps,
    90                                          gpointer user_data);
    91 static void _close_output              (GMencoder *self);
    92 static void _open_output               (GMencoder *self,
    93                                          const gchar* uri);
    94 static GstElement* _create_source       (const gchar* uri);
    95 static GstElement*_create_pipeline      (GMencoder *self,
    96                                           const gchar* video_encode,
    97                                           const gchar* mux_name,
    98                                           gchar** video_encode_prop,
    99                                           gdouble video_fps,
   100                                           gdouble video_rate,
   101                                           guint video_width, 
   102                                           guint video_height,                         
   103                                           const gchar* audio_encode,
   104                                           gchar** audio_encode_prop,
   105                                           guint audio_rate);
   106 static gboolean _tick_cb 				 (gpointer data);
   107 
   108 
   109 
   110 
   111 
   112 
   113 static guint g_mencoder_signals[LAST_SIGNAL] = { 0 };
   114 
   115 G_DEFINE_TYPE(GMencoder, g_mencoder, G_TYPE_OBJECT)
   116 
   117 static void
   118 g_mencoder_class_init (GMencoderClass *klass)
   119 {   
   120 	GObjectClass *object_class;
   121 
   122 	object_class = (GObjectClass *) klass;
   123 
   124 	g_type_class_add_private (klass, sizeof (GMencoderPrivate));
   125         
   126 	object_class->dispose  = g_mencoder_dispose;
   127 	object_class->finalize = g_mencoder_finalize;	
   128 	
   129     g_mencoder_signals[PAUSED] =
   130         g_signal_new ("paused",
   131     		  G_OBJECT_CLASS_TYPE (object_class),
   132     		  G_SIGNAL_RUN_FIRST,
   133     		  0, NULL, NULL,
   134     		  g_cclosure_marshal_VOID__VOID,
   135     		  G_TYPE_NONE, 0);
   136     		  
   137     g_mencoder_signals[PLAYING] =
   138         g_signal_new ("playing",
   139     		  G_OBJECT_CLASS_TYPE (object_class),
   140     		  G_SIGNAL_RUN_FIRST,
   141     		  0, NULL, NULL,
   142               g_cclosure_marshal_VOID__VOID,
   143     		  G_TYPE_NONE, 0);
   144 
   145     g_mencoder_signals[STOPED] =
   146         g_signal_new ("stoped",
   147     		  G_OBJECT_CLASS_TYPE (object_class),
   148     		  G_SIGNAL_RUN_FIRST,
   149     		  0, NULL, NULL,
   150     		  g_cclosure_marshal_VOID__VOID,
   151     		  G_TYPE_NONE, 0);
   152 
   153     g_mencoder_signals[EOS] =
   154         g_signal_new ("eos",
   155     		  G_OBJECT_CLASS_TYPE (object_class),
   156     		  G_SIGNAL_RUN_FIRST,
   157     		  0, NULL, NULL,
   158     		  g_cclosure_marshal_VOID__VOID,
   159     		  G_TYPE_NONE, 0);
   160     		  
   161     		  
   162     g_mencoder_signals[ERROR] =
   163         g_signal_new ("error",
   164     		  G_OBJECT_CLASS_TYPE (object_class),
   165     		  G_SIGNAL_RUN_LAST,
   166     		  0, NULL, NULL,
   167     		  g_cclosure_marshal_VOID__STRING,
   168     		  G_TYPE_NONE, 1, G_TYPE_STRING);	
   169 }
   170 
   171 static void
   172 g_mencoder_init (GMencoder *self)
   173 {
   174 	GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
   175     priv->info = g_new0 (SetupInfo, 1);
   176 }
   177 
   178 static void 
   179 g_mencoder_dispose (GObject *object)
   180 {
   181 }
   182 
   183 static void 
   184 g_mencoder_finalize (GObject *object)
   185 {
   186     //TODO: clear vars
   187 	g_mencoder_close_stream (G_MENCODER (object));
   188 }
   189 
   190 GMencoder*  
   191 g_mencoder_new (void)
   192 {
   193     return g_object_new (G_TYPE_MENCODER, NULL);
   194 }
   195 
   196 
   197 static void
   198 _obj_set_prop (GObject *obj, 
   199                 const gchar *prop_name,
   200                 const gchar *prop_val)
   201 {
   202     GValue p = {0};
   203     GValue v = {0};
   204     GParamSpec *s = NULL;
   205     GObjectClass *k = G_OBJECT_GET_CLASS (obj);
   206 
   207 
   208     g_value_init (&v, G_TYPE_STRING);
   209     g_value_set_string (&v, prop_val);
   210 
   211     s = g_object_class_find_property (k, prop_name);
   212     if (s == NULL) {
   213         g_print ("Invalid property name: %s\n", prop_name);
   214         return;
   215     }
   216 
   217     g_value_init (&p, s->value_type);
   218     switch (s->value_type) 
   219     {
   220         case G_TYPE_INT:
   221             g_value_set_int (&p, atoi (prop_val));
   222             break;
   223         case G_TYPE_STRING:
   224             g_value_set_string (&p, prop_val);
   225             break;
   226         default:
   227             return;
   228     }
   229        
   230     g_object_set_property (obj, prop_name, &p);
   231     g_value_unset (&v);
   232     g_value_unset (&p);
   233 }
   234 
   235 static GstElement*
   236 _create_element_with_prop (const gchar* factory_name,
   237                             const gchar* element_name,
   238                             gchar** prop)
   239 {
   240     GstElement *ret;
   241     int i;
   242 
   243     ret = gst_element_factory_make (factory_name, element_name);
   244     if (ret == NULL)
   245         return NULL;
   246 
   247     if (prop != NULL) {
   248         for (i=0; i < g_strv_length (prop); i++) {
   249 			if (prop[i] != NULL) {
   250             	char** v = g_strsplit(prop[i], "=", 2);
   251             	if (g_strv_length (v) == 2) {
   252                 	_obj_set_prop (G_OBJECT (ret), v[0], v[1]);
   253             	}	
   254             	g_strfreev (v);
   255 			}
   256         }
   257     }
   258 
   259     return ret;
   260 
   261 }
   262 
   263 static GstElement*
   264 _create_audio_bin (const gchar* encode,
   265                    gchar** encode_prop,
   266                    gint rate)
   267 {
   268     GstElement *abin = NULL;
   269     GstElement *aqueue = NULL;
   270     GstElement *aconvert = NULL;
   271     GstElement *aencode = NULL;
   272     GstElement *aqueue_src = NULL;
   273     GstPad *apad = NULL;
   274 
   275     //audio/x-raw-int ! queue ! audioconvert ! faac ! rtpmp4gpay !  udpsink name=upd_audio host=224.0.0.1 port=5002	
   276 	abin 	= gst_bin_new ("abin");
   277 	aqueue	= gst_element_factory_make ("queue", "aqueue");
   278 	aconvert= gst_element_factory_make ("audioconvert", "aconvert");
   279 	aencode = _create_element_with_prop ((encode ? encode : "lame"), "aencode", encode_prop);
   280 	aqueue_src= gst_element_factory_make ("queue", "aqueue_src");	
   281 
   282 	if ((abin == NULL) || (aqueue == NULL) || (aconvert == NULL) 
   283 		|| (aencode == NULL) || (aqueue_src == NULL)) {
   284 		g_warning ("Audio elements not found");
   285 		goto error;
   286 	}
   287 
   288     g_object_set (G_OBJECT (aencode), "bitrate", 32, NULL);
   289     /*
   290     if (rate > 0) {
   291         g_object_set (G_OBJECT (aencode), "bitrate", 32, NULL);
   292     }
   293     */
   294 
   295 	gst_bin_add_many (GST_BIN (abin), aqueue, aconvert, aencode, aqueue_src, NULL);
   296 	if (gst_element_link_many (aqueue, aconvert, aencode, aqueue_src, NULL) == FALSE) {
   297         g_warning ("Not Link audio elements");
   298     }
   299 
   300     //TODO: apply audio rate 
   301 
   302 	// ghost pad the audio bin
   303    	apad = gst_element_get_pad (aqueue, "sink");
   304    	gst_element_add_pad (abin, gst_ghost_pad_new("sink", apad));
   305 	gst_object_unref (apad);
   306 	
   307    	apad = gst_element_get_pad (aqueue_src, "src");
   308    	gst_element_add_pad (abin, gst_ghost_pad_new("src", apad));
   309     gst_object_unref (apad);
   310 
   311     return abin;
   312 error:
   313    	if (abin != NULL)
   314 		gst_object_unref (abin);
   315 
   316 	if (aqueue != NULL)
   317 		gst_object_unref (aqueue);
   318 
   319 	if (aconvert != NULL)
   320 		gst_object_unref (aconvert);
   321 
   322 	if (aencode != NULL)
   323 		gst_object_unref (aencode);
   324 
   325 	if (aqueue_src != NULL)
   326 		gst_object_unref (aqueue_src);
   327 
   328     if (apad != NULL)
   329         gst_object_unref (apad);
   330 
   331     return NULL;
   332 }
   333 
   334 
   335 
   336 
   337 //queue ! videoscale ! video/x-raw-yuv,width=240,height=144 ! colorspace ! rate ! encode ! queue
   338 static GstElement*
   339 _create_video_bin (const gchar* encode,
   340                     gchar** encode_prop,
   341                     gdouble fps,
   342                     gint rate,
   343                     guint width, 
   344                     guint height)
   345 {
   346     GstElement *vbin = NULL;
   347     GstElement *vqueue = NULL;
   348     GstElement* vqueue_src = NULL;
   349     GstElement *vcolorspace = NULL;
   350     GstElement *vencode = NULL;
   351     GstElement *vrate = NULL;
   352     GstPad *vpad = NULL;
   353 
   354 	vbin    = gst_bin_new ("vbin");
   355 	vqueue	= gst_element_factory_make ("queue", "vqueue");
   356 	vcolorspace = gst_element_factory_make ("ffmpegcolorspace", "colorspace");
   357 
   358 	vencode = _create_element_with_prop (
   359             (encode != NULL ? encode : "ffenc_mpeg1video"), 
   360             "vencode", encode_prop);
   361 	vqueue_src = gst_element_factory_make ("queue", "queue_src");
   362 
   363 	if ((vbin == NULL) || (vqueue == NULL) || (vcolorspace == NULL) 
   364 		|| (vencode == NULL) || (vqueue_src == NULL)) {
   365 		g_warning ("Video elements not found");
   366 		goto error;
   367 	}
   368 		
   369 	gst_bin_add_many (GST_BIN (vbin), vqueue, vcolorspace, vencode, vqueue_src, NULL);
   370 
   371 	
   372     if ((width > 0) && (height > 0)) {        
   373         //Scalling video
   374         GstCaps *vcaps;
   375 	    GstElement *vscale  = gst_element_factory_make ("videoscale", "vscale");
   376 
   377         gst_bin_add (GST_BIN (vbin), vscale);
   378 
   379         vcaps = gst_caps_new_simple ("video/x-raw-yuv",
   380                            "width", G_TYPE_INT, width,
   381                            "height", G_TYPE_INT, height,                           
   382                            NULL);
   383 
   384         gst_element_link (vqueue, vscale);
   385 					   	
   386         if (gst_element_link_filtered (vscale, vcolorspace, vcaps) == FALSE) {
   387             g_warning ("Fail to resize video");
   388             gst_object_unref (vcaps);
   389             gst_object_unref (vscale);
   390             goto error;
   391         }
   392         gst_caps_unref (vcaps);
   393     } else {
   394         gst_element_link (vqueue, vcolorspace);
   395     }
   396     
   397 
   398     if (fps > 0) {
   399         //Changing the video fps
   400         GstCaps *vcaps;
   401         vrate   = gst_element_factory_make ("videorate", "vrate");
   402 
   403         gst_bin_add (GST_BIN (vbin), vrate);
   404 
   405     	if (gst_element_link (vcolorspace, vrate) == FALSE) {
   406 	        g_warning ("Fail to link video elements");
   407 	        goto error;
   408     	}
   409 
   410     	vcaps = gst_caps_new_simple ("video/x-raw-yuv",
   411 					   "framerate", GST_TYPE_FRACTION,  (int) (fps * 1000), 1000, NULL);
   412 
   413         if (gst_element_link_filtered (vrate, vencode, vcaps) == FALSE) { 
   414            g_warning ("Fail to link vrate with vencode.");
   415            goto error;
   416         }
   417         gst_caps_unref (vcaps);
   418     } else {
   419         if (gst_element_link (vcolorspace, vencode) == FALSE) {
   420             g_warning ("Fail to link colorspace and video encode element.");
   421             goto error;
   422         }
   423     }
   424     
   425     gst_element_link (vencode, vqueue_src);
   426 
   427 	// ghost pad the video  bin
   428    	vpad = gst_element_get_pad (vqueue, "sink");
   429    	gst_element_add_pad (vbin, gst_ghost_pad_new ("sink", vpad));	
   430 	gst_object_unref (vpad);
   431 	
   432    	vpad = gst_element_get_pad (vqueue_src, "src");
   433    	gst_element_add_pad (vbin, gst_ghost_pad_new ("src", vpad));	
   434 	gst_object_unref (vpad);
   435 
   436     return vbin;
   437 
   438 error:
   439     if (vpad != NULL)
   440         gst_object_unref (vpad);
   441 
   442 	if (vbin != NULL)
   443 		gst_object_unref (vbin);
   444 
   445 	if (vqueue != NULL)
   446 		gst_object_unref (vqueue);
   447 
   448 	if (vencode != NULL)
   449 		gst_object_unref (vencode);
   450 
   451 	if (vqueue_src != NULL)
   452 		gst_object_unref (vqueue_src);
   453 
   454     if (vcolorspace != NULL)
   455         gst_object_unref (vcolorspace);
   456 
   457     return NULL;
   458 }
   459 
   460 
   461 
   462 void
   463 g_mencoder_setup_stream (GMencoder *self, 
   464                          const gchar* mux_name,
   465                          const gchar* video_encode,
   466                          gchar** video_encode_prop,
   467                          gdouble video_fps,
   468                          gdouble video_rate,
   469                          guint video_width, 
   470                          guint video_height,                         
   471                          const gchar* audio_encode,
   472                          gchar** audio_encode_prop,
   473                          guint audio_rate,
   474                          const gchar* out_uri)
   475 {
   476     GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
   477     if (priv->ready == TRUE) {
   478         g_warning ("Stream already configured. You need close stream first.");
   479         return;
   480     }
   481 
   482     _close_output (self);
   483     _open_output (self, out_uri);
   484 
   485 	priv->sources = 0;
   486     priv->pipe = _create_pipeline (self,
   487             video_encode,
   488             mux_name,
   489             video_encode_prop,
   490             video_fps,
   491             video_rate,
   492             video_width,
   493             video_height,
   494             audio_encode,
   495             audio_encode_prop,
   496             audio_rate);
   497 
   498 }
   499 
   500 
   501 gboolean
   502 g_mencoder_append_uri (GMencoder *self,
   503                      const gchar* uri)
   504 {
   505     GstPad *pad_src;
   506     GstPad *pad_sink;
   507     GstElement *src;
   508     GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
   509     gboolean ret = FALSE;
   510     GstElement *ap = NULL;
   511     GstElement *vp = NULL;
   512 
   513 
   514     g_return_val_if_fail (priv->pipe != NULL, FALSE);
   515     g_return_val_if_fail (priv->ready == FALSE, FALSE);
   516 
   517 #ifndef SUPPORT_MULT_INPUT
   518 	g_return_val_if_fail (priv->sources < 1, FALSE);
   519 #endif
   520 
   521     src = _create_source (uri);
   522     if (src == NULL) 
   523         return FALSE;
   524 
   525 	priv->src = gst_bin_get_by_name (GST_BIN (src), "src");
   526 
   527     gst_bin_add (GST_BIN (priv->pipe), src);
   528 
   529 #ifdef SUPPORT_MULT_INPUT
   530     ap = gst_bin_get_by_name (GST_BIN (priv->pipe), "ap");
   531     vp = gst_bin_get_by_name (GST_BIN (priv->pipe), "vp");
   532 #else
   533     ap = gst_bin_get_by_name (GST_BIN (priv->pipe), "abin");
   534     vp = gst_bin_get_by_name (GST_BIN (priv->pipe), "vbin");
   535 #endif
   536 
   537     if ((vp == NULL)  || (ap == NULL)) {
   538 		g_warning  ("Fail to get output bin");
   539         goto error;
   540 	}
   541 
   542     pad_src = gst_element_get_pad (src, "src_audio");
   543     pad_sink = gst_element_get_compatible_pad (ap, 
   544             pad_src, 
   545             gst_pad_get_caps (pad_src));
   546 
   547     if ((pad_sink == NULL) || (pad_src == NULL))
   548         goto error;
   549 
   550     GstPadLinkReturn lret = gst_pad_link (pad_src, pad_sink);
   551     if (lret != GST_PAD_LINK_OK)
   552         goto error;
   553 
   554     gst_object_unref (pad_src);
   555     gst_object_unref (pad_sink);
   556 
   557     pad_src = gst_element_get_pad (src, "src_video");
   558     pad_sink = gst_element_get_compatible_pad (vp, 
   559             pad_src, 
   560             gst_pad_get_caps (pad_src));
   561 
   562     if ((pad_src == NULL) || (pad_sink == NULL))
   563         goto error;
   564 
   565     if (gst_pad_link (pad_src, pad_sink) != GST_PAD_LINK_OK) {
   566         g_warning ("invalid source. video");
   567         goto error;
   568     }
   569 
   570 	priv->sources++;
   571     ret = TRUE;
   572 error:
   573 
   574     if ((src != NULL) && (ret == FALSE)) {
   575         gst_bin_remove (GST_BIN (priv->pipe), src);
   576         gst_object_unref (src);
   577     }
   578 
   579     if (ap != NULL) 
   580         gst_object_unref (ap);
   581 
   582     if (vp != NULL)
   583         gst_object_unref (vp);
   584 
   585     if (pad_src != NULL)
   586         gst_object_unref (pad_src);
   587 
   588     if (pad_sink != NULL)
   589         gst_object_unref (pad_sink);
   590 
   591     return ret;
   592 }
   593 
   594 
   595 
   596 void        
   597 g_mencoder_remove_uri (GMencoder *self,
   598                         const gchar* uri)
   599 {
   600     // GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
   601     //TODO: remove src
   602 }
   603 
   604 void
   605 g_mencoder_play_stream (GMencoder *self)
   606 {
   607     GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
   608 
   609     g_return_if_fail (priv->ready == FALSE);
   610     priv->ready = TRUE;
   611     gst_element_set_state (priv->pipe, GST_STATE_PLAYING);
   612 
   613 	priv->tick_id = g_timeout_add (500, _tick_cb, self);
   614 }
   615 
   616 void
   617 g_mencoder_pause_stream (GMencoder *self)
   618 {
   619     GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
   620 
   621     g_return_if_fail (priv->ready == TRUE);
   622     gst_element_set_state (priv->pipe, GST_STATE_PAUSED);
   623 }
   624 
   625 void
   626 g_mencoder_close_stream (GMencoder *self)
   627 {
   628 
   629     GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
   630 
   631 	if (priv->tick_id != 0) {			
   632 		g_source_remove (priv->tick_id);
   633 		priv->tick_id = 0;
   634 	}
   635 
   636     if (priv->pipe != NULL) { 
   637 		//TODO: fixe pipeline dispose
   638 		g_debug ("SETING STATE TO NULL");
   639         //gst_element_set_state (priv->pipe, GST_STATE_NULL);
   640 		g_debug ("SETING STATE TO NULL: OK");
   641         //gst_object_unref (priv->pipe);
   642         gst_object_unref (priv->src);
   643 		priv->src = NULL;
   644         priv->pipe = NULL;
   645         priv->abin = NULL;
   646         priv->vbin = NULL;
   647         priv->sink = NULL;
   648     }
   649     priv->ready = FALSE;
   650 }
   651 
   652 static GstElement*
   653 _create_pipeline (GMencoder *self,
   654                   const gchar* video_encode,
   655                   const gchar* mux_name,
   656                   gchar** video_encode_prop,
   657                   gdouble video_fps,
   658                   gdouble video_rate,
   659                   guint video_width, 
   660                   guint video_height,                         
   661                   const gchar* audio_encode,
   662                   gchar** audio_encode_prop,
   663                   guint audio_rate)
   664 {
   665 	GstBus *bus = NULL;
   666 	GstElement *pipe = NULL;
   667 	GstElement *sink = NULL;
   668     GstElement *mux = NULL;
   669     GstElement *abin = NULL;
   670     GstElement *vbin = NULL;    
   671     GstPad *aux_pad = NULL;
   672     GstPad *mux_pad = NULL;
   673 #ifdef SUPPORT_MULT_INPUT
   674     GstElement *ap = NULL;
   675     GstElement *vp = NULL;    
   676 #endif
   677     GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
   678 
   679 	pipe = gst_pipeline_new ("pipe");
   680 
   681 #ifdef SUPPORT_MULT_INPUT			
   682 	ap = gst_element_factory_make ("concatmux", "ap");
   683     vp = gst_element_factory_make ("concatmux", "vp");
   684 	gst_bin_add_many (GST_BIN (pipe), ap, vp, NULL);
   685 #endif
   686 
   687     mux = gst_element_factory_make ((mux_name ? mux_name : "ffmux_mpeg"), "mux");
   688     if (mux == NULL)
   689         goto error;
   690 
   691 
   692     sink = gst_element_factory_make ("fdsink", "sink");
   693     if (sink == NULL)
   694         goto error;
   695 
   696     g_object_set (G_OBJECT(sink), 
   697 			"fd", priv->fd,
   698             NULL);
   699 
   700     abin = _create_audio_bin (audio_encode, audio_encode_prop, audio_rate);
   701     if (abin == NULL)
   702         goto error;
   703 
   704     vbin = _create_video_bin (video_encode, video_encode_prop, video_fps, video_rate, video_width, video_height);
   705     if (vbin == NULL)
   706         goto error;
   707 
   708 	// Finish Pipe
   709     gst_bin_add_many (GST_BIN (pipe), abin, vbin, mux, sink, NULL);
   710 
   711 
   712 #ifdef SUPPORT_MULT_INPUT	
   713 	if (gst_element_link (ap, abin) == FALSE) {
   714 		g_warning ("Fail to link concat and abin");
   715 		goto error;
   716 	}
   717 
   718 	if (gst_element_link (vp, vbin) == FALSE) {
   719 		g_warning ("Fail to link concat and vbin");
   720 	}
   721 #endif	
   722 
   723     //Link bins with mux
   724     aux_pad = gst_element_get_pad (abin, "src");
   725     mux_pad = gst_element_get_compatible_pad (mux, aux_pad, GST_PAD_CAPS (aux_pad));
   726     if (mux_pad == NULL) {
   727         g_warning ("Mux element no have audio PAD");
   728         goto error;
   729     }
   730     GstPadLinkReturn ret = gst_pad_link (aux_pad, mux_pad);
   731     if (ret != GST_PAD_LINK_OK) {
   732         g_warning ("Fail link audio and mux: %d", ret);
   733         goto error;
   734    
   735     }
   736 	gst_object_unref (aux_pad);
   737     gst_object_unref (mux_pad);
   738 
   739     aux_pad = gst_element_get_pad (vbin, "src");
   740     mux_pad = gst_element_get_compatible_pad (mux, aux_pad, GST_PAD_CAPS (aux_pad));
   741     if (mux_pad == NULL) {
   742         g_warning ("Mux element no have video PAD");
   743         goto error;
   744     }
   745     ret = gst_pad_link (aux_pad, mux_pad);
   746     if (ret != GST_PAD_LINK_OK) {
   747         g_warning ("Fail link video and mux: %d", ret);
   748         goto error;
   749     }
   750     gst_object_unref (aux_pad);
   751     gst_object_unref (mux_pad);
   752     aux_pad = NULL;
   753     mux_pad = NULL;
   754 
   755     //Link mux with sink
   756     gst_element_link (mux, sink);
   757 
   758 	bus = gst_pipeline_get_bus (GST_PIPELINE (pipe));
   759 	gst_bus_add_watch (bus, _pipeline_bus_cb, self);
   760 	gst_object_unref (bus);
   761     return pipe;
   762 	
   763 error:
   764 	g_warning ("Invalid uri");
   765 
   766 	if (pipe != NULL) {
   767 		gst_object_unref (pipe);
   768     }
   769 
   770 
   771     if (mux != NULL) {
   772         gst_object_unref (mux);
   773     }
   774 
   775     if (mux_pad != NULL) {
   776         gst_object_unref (mux_pad);
   777     }
   778 
   779     if (aux_pad != NULL) {
   780         gst_object_unref (mux_pad);
   781     }
   782 
   783 	if (sink != NULL) {
   784 		gst_object_unref (sink);
   785     }
   786 
   787     if (abin != NULL) {
   788         gst_object_unref (abin);
   789     }
   790 
   791     if (vbin != NULL) {
   792         gst_object_unref (vbin);
   793     }
   794 
   795 	return FALSE;
   796 }
   797 
   798 
   799 static void
   800 _close_output (GMencoder *self)
   801 {
   802     
   803 }
   804 
   805 static GstElement*
   806 _create_source (const gchar* uri)
   807 {
   808 
   809     GstElement *bsrc = NULL;
   810     GstElement *src = NULL;
   811     GstElement *aqueue = NULL;
   812     GstElement *vqueue = NULL;
   813     GstElement *decode = NULL;
   814     GstPad *src_pad = NULL;
   815 
   816 
   817     bsrc = gst_bin_new (NULL);
   818 
   819 	//src = gst_element_factory_make ("gnomevfssrc", "src");
   820     //g_object_set (G_OBJECT (src), "location", uri, NULL);
   821 	src = gst_element_make_from_uri (GST_URI_SRC, uri, "src");
   822 	if (src == NULL) 
   823 		goto error;
   824 
   825 	decode = gst_element_factory_make ("decodebin2", "decode");
   826 	if (decode == NULL) 
   827 		goto error;
   828 
   829     aqueue = gst_element_factory_make ("queue", "aqueue");
   830     if (aqueue == NULL)
   831         goto error;
   832 
   833     vqueue = gst_element_factory_make ("queue", "vqueue");
   834     if (vqueue == NULL)
   835         goto error;
   836 
   837     gst_bin_add_many (GST_BIN (bsrc), src, decode, aqueue, vqueue, NULL);
   838     gst_element_link (src, decode);
   839 
   840 	g_signal_connect (G_OBJECT (decode), 
   841 				"new-decoded-pad",
   842 				G_CALLBACK (_decodebin_new_pad_cb),
   843 				bsrc);
   844 
   845 	g_signal_connect (G_OBJECT (decode),
   846 				"unknown-type",
   847 				G_CALLBACK (_decodebin_unknown_type_cb),
   848 				pipe);
   849 
   850     src_pad = gst_element_get_pad (aqueue, "src");
   851    	gst_element_add_pad (bsrc, gst_ghost_pad_new("src_audio", src_pad));
   852     gst_object_unref (src_pad);
   853 
   854     src_pad = gst_element_get_pad (vqueue, "src");
   855    	gst_element_add_pad (bsrc, gst_ghost_pad_new("src_video", src_pad));
   856     gst_object_unref (src_pad);
   857 
   858     return bsrc;
   859 
   860 error:
   861 	if (src != NULL) {
   862 		gst_object_unref (src);
   863     }
   864 
   865 	if (decode != NULL) {
   866 		gst_object_unref (decode);
   867     }
   868 
   869 	if (aqueue != NULL) {
   870 		gst_object_unref (aqueue);
   871     }
   872 
   873 	if (vqueue != NULL) {
   874 		gst_object_unref (vqueue);
   875     }
   876 
   877     return NULL;
   878 }
   879 
   880 static void
   881 _open_output (GMencoder *self, 
   882               const gchar* uri)
   883 {
   884     gchar** i;
   885     GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
   886 
   887     i = g_strsplit (uri, "://", 0);
   888     if (strcmp (i[0], "fd") == 0) {
   889         priv->fd = atoi (i[1]);
   890     } else if (strcmp (i[0], "file") == 0) {
   891         priv->fd = open (i[1], O_WRONLY | O_CREAT | O_TRUNC);
   892     } else {
   893         g_warning ("Output uri not supported");
   894     }
   895 
   896     g_strfreev (i);
   897 }
   898 
   899 static gboolean
   900 _pipeline_bus_cb (GstBus     *bus,
   901 		  GstMessage *msg,
   902 		  gpointer    user_data)
   903 {
   904 	GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (user_data);
   905 
   906 	switch (GST_MESSAGE_TYPE (msg)) 
   907 	{
   908 		case GST_MESSAGE_STATE_CHANGED:
   909 		{
   910 			GstState oldstate;
   911 			GstState newstate;
   912 			GstState pendingstate;
   913 
   914 
   915 			gst_message_parse_state_changed (msg, &oldstate,
   916 				&newstate, &pendingstate);
   917 
   918             if (pendingstate != GST_STATE_VOID_PENDING)
   919                 break;
   920 
   921             if ((oldstate == GST_STATE_READY) && 
   922                 (newstate == GST_STATE_PAUSED)) {
   923                     if (priv->ready) 
   924                         g_signal_emit (user_data, g_mencoder_signals[PAUSED], 0);
   925             } else if ((oldstate == GST_STATE_PAUSED) &&
   926                        (newstate == GST_STATE_PLAYING)) {
   927                         g_signal_emit (user_data, g_mencoder_signals[PLAYING], 0);
   928             } else if ((oldstate == GST_STATE_READY) &&
   929                        (newstate == GST_STATE_NULL)) {
   930                         g_signal_emit (user_data, g_mencoder_signals[STOPED], 0);
   931             }			
   932             break;
   933 		}
   934 		case GST_MESSAGE_ERROR: 
   935 		{
   936 		    GError *error;
   937 		    gchar *debug;
   938 		    gchar *err_str;
   939 
   940 			if (priv->tick_id != 0) {			
   941 				g_source_remove (priv->tick_id);
   942 				priv->tick_id = 0;
   943 			}
   944 		    
   945 		    gst_message_parse_error (msg, &error, &debug);
   946 		    err_str = g_strdup_printf ("Error [%d] %s (%s)", error->code,
   947 		        error->message,
   948 		        debug);
   949             priv->ready = FALSE;
   950 		    g_signal_emit (user_data, g_mencoder_signals[ERROR], 0, err_str);
   951 		    g_free (err_str);
   952 		    g_clear_error (&error);
   953 		    g_free (debug);
   954 		    break;
   955 		}
   956 		
   957 		case GST_MESSAGE_EOS:
   958             priv->ready = FALSE;
   959 		    g_signal_emit (user_data, g_mencoder_signals[EOS], 0);
   960 		    break;		
   961 		case GST_MESSAGE_DURATION:
   962 		{
   963 			GstFormat format;
   964 			gint64 duration;
   965 			gst_message_parse_duration (msg, &format, &duration);
   966 			if (format == GST_FORMAT_BYTES)
   967 				priv->duration = duration;
   968 			break;
   969 		}
   970 		default:
   971 		{
   972 			break;
   973 		}
   974 	}
   975 	return TRUE;
   976 }
   977 
   978 
   979 
   980 static void 
   981 _decodebin_new_pad_cb (GstElement* object,
   982                        GstPad* pad,
   983                        gboolean flag,
   984                        gpointer user_data)
   985 {
   986 	GstCaps *caps;
   987 	gchar *str_caps = NULL;
   988     GstElement *sink_element;
   989     GstPad *sink_pad;
   990 
   991 	caps = gst_pad_get_caps (pad);
   992 	str_caps = gst_caps_to_string (caps);
   993 	if (strstr (str_caps, "audio") != NULL) {
   994         sink_element = gst_bin_get_by_name (GST_BIN (user_data), "aqueue");
   995 	} else if (strstr (str_caps, "video") != NULL) {
   996         sink_element = gst_bin_get_by_name (GST_BIN (user_data), "vqueue");
   997 	} else {
   998 		g_warning ("invalid caps %s", str_caps);
   999 	}
  1000 
  1001     sink_pad = gst_element_get_pad (sink_element, "sink");
  1002 	gst_pad_link (pad, sink_pad);
  1003 
  1004     gst_object_unref (sink_element);
  1005 	gst_object_unref (sink_pad);
  1006 	g_free (str_caps);
  1007 	gst_caps_unref (caps);
  1008 }
  1009 
  1010 static void 
  1011 _decodebin_unknown_type_cb (GstElement* object,
  1012                             GstPad* pad,
  1013                             GstCaps* caps,
  1014                             gpointer user_data)
  1015 {
  1016     g_warning  ("Unknown Type");
  1017     //priv->ready = FALSE;
  1018 }
  1019 
  1020 static gboolean
  1021 _tick_cb (gpointer user_data)
  1022 {
  1023 	GstFormat format = GST_FORMAT_BYTES;
  1024 	gint64 cur = 0;
  1025 
  1026 	GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (user_data);
  1027 
  1028 	if (priv->duration == 0) {
  1029 		gint64 d = 0;
  1030 		if (gst_element_query_duration (priv->src, &format, &d))
  1031 			priv->duration = d;
  1032 	}			
  1033 
  1034 	if (priv->duration != 0) {
  1035 		gst_element_query_position (priv->src, &format, &cur);
  1036 		g_print ("PROGRESS:%lli\n", (99 * cur) / priv->duration); 
  1037 	}
  1038 
  1039 	return TRUE;
  1040 }