gmyth-stream/gmemcoder/src/gmencoder.c
author morphbr
Thu May 31 19:55:43 2007 +0100 (2007-05-31)
branchtrunk
changeset 729 8ef808220720
parent 703 bfc97f675c60
child 748 bf9dac4bdc5d
permissions -rw-r--r--
[svn r735] * GMyth-Streamer
- bug fix in log
     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     GstElement *queue= NULL;
   672     GstPad *aux_pad = NULL;
   673     GstPad *mux_pad = NULL;
   674 #ifdef SUPPORT_MULT_INPUT
   675     GstElement *ap = NULL;
   676     GstElement *vp = NULL;    
   677 #endif
   678     GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
   679 
   680 	pipe = gst_pipeline_new ("pipe");
   681 
   682 #ifdef SUPPORT_MULT_INPUT			
   683 	ap = gst_element_factory_make ("concatmux", "ap");
   684     vp = gst_element_factory_make ("concatmux", "vp");
   685 	gst_bin_add_many (GST_BIN (pipe), ap, vp, NULL);
   686 #endif
   687 
   688     mux = gst_element_factory_make ((mux_name ? mux_name : "ffmux_mpeg"), "mux");
   689     if (mux == NULL)
   690         goto error;
   691 
   692     queue = gst_element_factory_make ("queue", "queueu_sink");
   693 
   694 
   695     sink = gst_element_factory_make ("fdsink", "sink");
   696     if (sink == NULL)
   697         goto error;
   698 
   699     g_object_set (G_OBJECT(sink), 
   700 			"fd", priv->fd,
   701 			"sync", FALSE,
   702             NULL);
   703 
   704     abin = _create_audio_bin (audio_encode, audio_encode_prop, audio_rate);
   705     if (abin == NULL)
   706         goto error;
   707 
   708     vbin = _create_video_bin (video_encode, video_encode_prop, video_fps, video_rate, video_width, video_height);
   709     if (vbin == NULL)
   710         goto error;
   711 
   712 	// Finish Pipe
   713     gst_bin_add_many (GST_BIN (pipe), abin, vbin, mux, queue, sink, NULL);
   714 
   715 
   716 #ifdef SUPPORT_MULT_INPUT	
   717 	if (gst_element_link (ap, abin) == FALSE) {
   718 		g_warning ("Fail to link concat and abin");
   719 		goto error;
   720 	}
   721 
   722 	if (gst_element_link (vp, vbin) == FALSE) {
   723 		g_warning ("Fail to link concat and vbin");
   724 	}
   725 #endif	
   726 
   727     //Link bins with mux
   728     aux_pad = gst_element_get_pad (abin, "src");
   729     mux_pad = gst_element_get_compatible_pad (mux, aux_pad, GST_PAD_CAPS (aux_pad));
   730     if (mux_pad == NULL) {
   731         g_warning ("Mux element no have audio PAD");
   732         goto error;
   733     }
   734     GstPadLinkReturn ret = gst_pad_link (aux_pad, mux_pad);
   735     if (ret != GST_PAD_LINK_OK) {
   736         g_warning ("Fail link audio and mux: %d", ret);
   737         goto error;
   738    
   739     }
   740 	gst_object_unref (aux_pad);
   741     gst_object_unref (mux_pad);
   742 
   743     aux_pad = gst_element_get_pad (vbin, "src");
   744     mux_pad = gst_element_get_compatible_pad (mux, aux_pad, GST_PAD_CAPS (aux_pad));
   745     if (mux_pad == NULL) {
   746         g_warning ("Mux element no have video PAD");
   747         goto error;
   748     }
   749     ret = gst_pad_link (aux_pad, mux_pad);
   750     if (ret != GST_PAD_LINK_OK) {
   751         g_warning ("Fail link video and mux: %d", ret);
   752         goto error;
   753     }
   754     gst_object_unref (aux_pad);
   755     gst_object_unref (mux_pad);
   756     aux_pad = NULL;
   757     mux_pad = NULL;
   758 
   759     //Link mux with sink
   760     gst_element_link_many (mux, queue, sink, NULL);
   761 
   762 	bus = gst_pipeline_get_bus (GST_PIPELINE (pipe));
   763 	gst_bus_add_watch (bus, _pipeline_bus_cb, self);
   764 	gst_object_unref (bus);
   765     return pipe;
   766 	
   767 error:
   768 	g_warning ("Invalid uri");
   769 
   770 	if (pipe != NULL) {
   771 		gst_object_unref (pipe);
   772     }
   773 
   774 
   775     if (mux != NULL) {
   776         gst_object_unref (mux);
   777     }
   778 
   779     if (mux_pad != NULL) {
   780         gst_object_unref (mux_pad);
   781     }
   782 
   783     if (aux_pad != NULL) {
   784         gst_object_unref (mux_pad);
   785     }
   786 
   787 	if (sink != NULL) {
   788 		gst_object_unref (sink);
   789     }
   790 
   791     if (abin != NULL) {
   792         gst_object_unref (abin);
   793     }
   794 
   795     if (vbin != NULL) {
   796         gst_object_unref (vbin);
   797     }
   798 
   799 	return FALSE;
   800 }
   801 
   802 
   803 static void
   804 _close_output (GMencoder *self)
   805 {
   806     
   807 }
   808 
   809 static GstElement*
   810 _create_source (const gchar* uri)
   811 {
   812 
   813     GstElement *bsrc = NULL;
   814     GstElement *src = NULL;
   815     GstElement *queue = NULL;
   816     GstElement *aqueue = NULL;
   817     GstElement *vqueue = NULL;
   818     GstElement *decode = NULL;
   819     GstPad *src_pad = NULL;
   820 
   821 
   822     bsrc = gst_bin_new (NULL);
   823 
   824 	//src = gst_element_factory_make ("gnomevfssrc", "src");
   825     //g_object_set (G_OBJECT (src), "location", uri, NULL);
   826 	src = gst_element_make_from_uri (GST_URI_SRC, uri, "src");
   827 	if (src == NULL) 
   828 		goto error;
   829 
   830 	decode = gst_element_factory_make ("decodebin", "decode");
   831 	if (decode == NULL) 
   832 		goto error;
   833 
   834     queue = gst_element_factory_make ("queue", "queue_src");
   835     aqueue = gst_element_factory_make ("queue", "aqueue");
   836     if (aqueue == NULL)
   837         goto error;
   838 
   839     vqueue = gst_element_factory_make ("queue", "vqueue");
   840     if (vqueue == NULL)
   841         goto error;
   842 
   843     gst_bin_add_many (GST_BIN (bsrc), src, queue, decode, aqueue, vqueue, NULL);
   844     gst_element_link_many (src, queue, decode, NULL);
   845 
   846 	g_signal_connect (G_OBJECT (decode), 
   847 				"new-decoded-pad",
   848 				G_CALLBACK (_decodebin_new_pad_cb),
   849 				bsrc);
   850 
   851 	g_signal_connect (G_OBJECT (decode),
   852 				"unknown-type",
   853 				G_CALLBACK (_decodebin_unknown_type_cb),
   854 				pipe);
   855 
   856     src_pad = gst_element_get_pad (aqueue, "src");
   857    	gst_element_add_pad (bsrc, gst_ghost_pad_new("src_audio", src_pad));
   858     gst_object_unref (src_pad);
   859 
   860     src_pad = gst_element_get_pad (vqueue, "src");
   861    	gst_element_add_pad (bsrc, gst_ghost_pad_new("src_video", src_pad));
   862     gst_object_unref (src_pad);
   863 
   864     return bsrc;
   865 
   866 error:
   867 	if (src != NULL) {
   868 		gst_object_unref (src);
   869     }
   870 
   871 	if (decode != NULL) {
   872 		gst_object_unref (decode);
   873     }
   874 
   875 	if (aqueue != NULL) {
   876 		gst_object_unref (aqueue);
   877     }
   878 
   879 	if (vqueue != NULL) {
   880 		gst_object_unref (vqueue);
   881     }
   882 
   883     return NULL;
   884 }
   885 
   886 static void
   887 _open_output (GMencoder *self, 
   888               const gchar* uri)
   889 {
   890     gchar** i;
   891     GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
   892 
   893     i = g_strsplit (uri, "://", 0);
   894     if (strcmp (i[0], "fd") == 0) {
   895         priv->fd = atoi (i[1]);
   896     } else if (strcmp (i[0], "file") == 0) {
   897         priv->fd = open (i[1], O_WRONLY | O_CREAT | O_TRUNC);
   898     } else {
   899         g_warning ("Output uri not supported");
   900     }
   901 
   902     g_strfreev (i);
   903 }
   904 
   905 static gboolean
   906 _pipeline_bus_cb (GstBus     *bus,
   907 		  GstMessage *msg,
   908 		  gpointer    user_data)
   909 {
   910 	GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (user_data);
   911 
   912 	switch (GST_MESSAGE_TYPE (msg)) 
   913 	{
   914 		case GST_MESSAGE_STATE_CHANGED:
   915 		{
   916 			GstState oldstate;
   917 			GstState newstate;
   918 			GstState pendingstate;
   919 
   920 
   921 			gst_message_parse_state_changed (msg, &oldstate,
   922 				&newstate, &pendingstate);
   923 
   924             if (pendingstate != GST_STATE_VOID_PENDING)
   925                 break;
   926 
   927             if ((oldstate == GST_STATE_READY) && 
   928                 (newstate == GST_STATE_PAUSED)) {
   929                     if (priv->ready) 
   930                         g_signal_emit (user_data, g_mencoder_signals[PAUSED], 0);
   931             } else if ((oldstate == GST_STATE_PAUSED) &&
   932                        (newstate == GST_STATE_PLAYING)) {
   933                         g_signal_emit (user_data, g_mencoder_signals[PLAYING], 0);
   934             } else if ((oldstate == GST_STATE_READY) &&
   935                        (newstate == GST_STATE_NULL)) {
   936                         g_signal_emit (user_data, g_mencoder_signals[STOPED], 0);
   937             }			
   938             break;
   939 		}
   940 		case GST_MESSAGE_ERROR: 
   941 		{
   942 		    GError *error;
   943 		    gchar *debug;
   944 		    gchar *err_str;
   945 
   946 			if (priv->tick_id != 0) {			
   947 				g_source_remove (priv->tick_id);
   948 				priv->tick_id = 0;
   949 			}
   950 		    
   951 		    gst_message_parse_error (msg, &error, &debug);
   952 		    err_str = g_strdup_printf ("Error [%d] %s (%s)", error->code,
   953 		        error->message,
   954 		        debug);
   955             priv->ready = FALSE;
   956 		    g_signal_emit (user_data, g_mencoder_signals[ERROR], 0, err_str);
   957 		    g_free (err_str);
   958 		    g_clear_error (&error);
   959 		    g_free (debug);
   960 		    break;
   961 		}
   962 		
   963 		case GST_MESSAGE_EOS:
   964             priv->ready = FALSE;
   965 		    g_signal_emit (user_data, g_mencoder_signals[EOS], 0);
   966 		    break;		
   967 		case GST_MESSAGE_DURATION:
   968 		{
   969 			GstFormat format;
   970 			gint64 duration;
   971 			gst_message_parse_duration (msg, &format, &duration);
   972 			if (format == GST_FORMAT_BYTES)
   973 				priv->duration = duration;
   974 			break;
   975 		}
   976 		default:
   977 		{
   978 			break;
   979 		}
   980 	}
   981 	return TRUE;
   982 }
   983 
   984 
   985 
   986 static void 
   987 _decodebin_new_pad_cb (GstElement* object,
   988                        GstPad* pad,
   989                        gboolean flag,
   990                        gpointer user_data)
   991 {
   992 	GstCaps *caps;
   993 	gchar *str_caps = NULL;
   994     GstElement *sink_element;
   995     GstPad *sink_pad;
   996 
   997 	caps = gst_pad_get_caps (pad);
   998 	str_caps = gst_caps_to_string (caps);
   999 	if (strstr (str_caps, "audio") != NULL) {
  1000         sink_element = gst_bin_get_by_name (GST_BIN (user_data), "aqueue");
  1001 	} else if (strstr (str_caps, "video") != NULL) {
  1002         sink_element = gst_bin_get_by_name (GST_BIN (user_data), "vqueue");
  1003 	} else {
  1004 		g_warning ("invalid caps %s", str_caps);
  1005 	}
  1006 
  1007     sink_pad = gst_element_get_pad (sink_element, "sink");
  1008 	gst_pad_link (pad, sink_pad);
  1009 
  1010     gst_object_unref (sink_element);
  1011 	gst_object_unref (sink_pad);
  1012 	g_free (str_caps);
  1013 	gst_caps_unref (caps);
  1014 }
  1015 
  1016 static void 
  1017 _decodebin_unknown_type_cb (GstElement* object,
  1018                             GstPad* pad,
  1019                             GstCaps* caps,
  1020                             gpointer user_data)
  1021 {
  1022     g_warning  ("Unknown Type");
  1023     //priv->ready = FALSE;
  1024 }
  1025 
  1026 static gboolean
  1027 _tick_cb (gpointer user_data)
  1028 {
  1029 	GstFormat format = GST_FORMAT_BYTES;
  1030 	gint64 cur = 0;
  1031 
  1032 	GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (user_data);
  1033 
  1034 	if (priv->duration == 0) {
  1035 		gint64 d = 0;
  1036 		if (gst_element_query_duration (priv->src, &format, &d))
  1037 			priv->duration = d;
  1038 	}			
  1039 
  1040 	if (priv->duration != 0) {
  1041 		gst_element_query_position (priv->src, &format, &cur);
  1042 		g_print ("PROGRESS:%lli\n", (99 * cur) / priv->duration); 
  1043 	}
  1044 
  1045 	return TRUE;
  1046 }