gmyth-stream/gmemcoder/src/gmencoder.c
author rosfran
Wed May 16 19:46:20 2007 +0100 (2007-05-16)
branchtrunk
changeset 675 4c7f6a9bfded
parent 654 76b9c97faada
child 678 89bdaa9e72bf
permissions -rw-r--r--
[svn r681] Added configuration file parser (name/value pair list).
     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_FIRST,
   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             char** v = g_strsplit(prop[i], "=", 2);
   250             if (g_strv_length (v) == 2) {
   251                 _obj_set_prop (G_OBJECT (ret), v[0], v[1]);
   252             }
   253             g_strfreev (v);
   254         }
   255     }
   256 
   257     return ret;
   258 
   259 }
   260 
   261 static GstElement*
   262 _create_audio_bin (const gchar* encode,
   263                    gchar** encode_prop,
   264                    gint rate)
   265 {
   266     GstElement *abin = NULL;
   267     GstElement *aqueue = NULL;
   268     GstElement *aconvert = NULL;
   269     GstElement *aencode = NULL;
   270     GstElement *aqueue_src = NULL;
   271     GstPad *apad = NULL;
   272 
   273     //audio/x-raw-int ! queue ! audioconvert ! faac ! rtpmp4gpay !  udpsink name=upd_audio host=224.0.0.1 port=5002	
   274 	abin 	= gst_bin_new ("abin");
   275 	aqueue	= gst_element_factory_make ("queue", "aqueue");
   276 	aconvert= gst_element_factory_make ("audioconvert", "aconvert");
   277 	aencode = _create_element_with_prop ((encode ? encode : "lame"), "aencode", encode_prop);
   278 	aqueue_src= gst_element_factory_make ("queue", "aqueue_src");	
   279 
   280 	if ((abin == NULL) || (aqueue == NULL) || (aconvert == NULL) 
   281 		|| (aencode == NULL) || (aqueue_src == NULL)) {
   282 		g_warning ("Audio elements not found");
   283 		goto error;
   284 	}
   285 
   286     g_object_set (G_OBJECT (aencode), "bitrate", 32, NULL);
   287     /*
   288     if (rate > 0) {
   289         g_object_set (G_OBJECT (aencode), "bitrate", 32, NULL);
   290     }
   291     */
   292 
   293 	gst_bin_add_many (GST_BIN (abin), aqueue, aconvert, aencode, aqueue_src, NULL);
   294 	if (gst_element_link_many (aqueue, aconvert, aencode, aqueue_src, NULL) == FALSE) {
   295         g_warning ("Not Link audio elements");
   296     }
   297 
   298     //TODO: apply audio rate 
   299 
   300 	// ghost pad the audio bin
   301    	apad = gst_element_get_pad (aqueue, "sink");
   302    	gst_element_add_pad (abin, gst_ghost_pad_new("sink", apad));
   303 	gst_object_unref (apad);
   304 	
   305    	apad = gst_element_get_pad (aqueue_src, "src");
   306    	gst_element_add_pad (abin, gst_ghost_pad_new("src", apad));
   307     gst_object_unref (apad);
   308 
   309     return abin;
   310 error:
   311    	if (abin != NULL)
   312 		gst_object_unref (abin);
   313 
   314 	if (aqueue != NULL)
   315 		gst_object_unref (aqueue);
   316 
   317 	if (aconvert != NULL)
   318 		gst_object_unref (aconvert);
   319 
   320 	if (aencode != NULL)
   321 		gst_object_unref (aencode);
   322 
   323 	if (aqueue_src != NULL)
   324 		gst_object_unref (aqueue_src);
   325 
   326     if (apad != NULL)
   327         gst_object_unref (apad);
   328 
   329     return NULL;
   330 }
   331 
   332 
   333 
   334 
   335 //queue ! videoscale ! video/x-raw-yuv,width=240,height=144 ! colorspace ! rate ! encode ! queue
   336 static GstElement*
   337 _create_video_bin (const gchar* encode,
   338                     gchar** encode_prop,
   339                     gdouble fps,
   340                     gint rate,
   341                     guint width, 
   342                     guint height)
   343 {
   344     GstElement *vbin = NULL;
   345     GstElement *vqueue = NULL;
   346     GstElement* vqueue_src = NULL;
   347     GstElement *vcolorspace = NULL;
   348     GstElement *vencode = NULL;
   349     GstElement *vrate = NULL;
   350     GstPad *vpad = NULL;
   351 
   352 	vbin    = gst_bin_new ("vbin");
   353 	vqueue	= gst_element_factory_make ("queue", "vqueue");
   354 	vcolorspace = gst_element_factory_make ("ffmpegcolorspace", "colorspace");
   355 
   356 	vencode = _create_element_with_prop (
   357             (encode != NULL ? encode : "ffenc_mpeg1video"), 
   358             "vencode", encode_prop);
   359 	vqueue_src = gst_element_factory_make ("queue", "queue_src");
   360 
   361 	if ((vbin == NULL) || (vqueue == NULL) || (vcolorspace == NULL) 
   362 		|| (vencode == NULL) || (vqueue_src == NULL)) {
   363 		g_warning ("Video elements not found");
   364 		goto error;
   365 	}
   366 		
   367 	gst_bin_add_many (GST_BIN (vbin), vqueue, vcolorspace, vencode, vqueue_src, NULL);
   368 
   369 	
   370     if ((width > 0) && (height > 0)) {        
   371         //Scalling video
   372         GstCaps *vcaps;
   373 	    GstElement *vscale  = gst_element_factory_make ("videoscale", "vscale");
   374 
   375         gst_bin_add (GST_BIN (vbin), vscale);
   376 
   377         vcaps = gst_caps_new_simple ("video/x-raw-yuv",
   378                            "width", G_TYPE_INT, width,
   379                            "height", G_TYPE_INT, height,                           
   380                            NULL);
   381 
   382         gst_element_link (vqueue, vscale);
   383 					   	
   384         if (gst_element_link_filtered (vscale, vcolorspace, vcaps) == FALSE) {
   385             g_warning ("Fail to resize video");
   386             gst_object_unref (vcaps);
   387             gst_object_unref (vscale);
   388             goto error;
   389         }
   390         gst_caps_unref (vcaps);
   391     } else {
   392         gst_element_link (vqueue, vcolorspace);
   393     }
   394     
   395 
   396     if (fps > 0) {
   397         //Changing the video fps
   398         GstCaps *vcaps;
   399         vrate   = gst_element_factory_make ("videorate", "vrate");
   400 
   401         g_debug ("Setting FPS: %.2f", fps);
   402         gst_bin_add (GST_BIN (vbin), vrate);
   403 
   404     	if (gst_element_link (vcolorspace, vrate) == FALSE) {
   405 	        g_warning ("Fail to link video elements");
   406 	        goto error;
   407     	}
   408 
   409     	vcaps = gst_caps_new_simple ("video/x-raw-yuv",
   410 					   "framerate", GST_TYPE_FRACTION,  (int) (fps * 1000), 1000, NULL);
   411 
   412         if (gst_element_link_filtered (vrate, vencode, vcaps) == FALSE) { 
   413            g_warning ("Fail to link vrate with vencode.");
   414            goto error;
   415         }
   416         gst_caps_unref (vcaps);
   417     } else {
   418         if (gst_element_link (vcolorspace, vencode) == FALSE) {
   419             g_warning ("Fail to link colorspace and video encode element.");
   420             goto error;
   421         }
   422     }
   423     
   424     gst_element_link (vencode, vqueue_src);
   425 
   426 	// ghost pad the video  bin
   427    	vpad = gst_element_get_pad (vqueue, "sink");
   428    	gst_element_add_pad (vbin, gst_ghost_pad_new ("sink", vpad));	
   429 	gst_object_unref (vpad);
   430 	
   431    	vpad = gst_element_get_pad (vqueue_src, "src");
   432    	gst_element_add_pad (vbin, gst_ghost_pad_new ("src", vpad));	
   433 	gst_object_unref (vpad);
   434 
   435     return vbin;
   436 
   437 error:
   438     if (vpad != NULL)
   439         gst_object_unref (vpad);
   440 
   441 	if (vbin != NULL)
   442 		gst_object_unref (vbin);
   443 
   444 	if (vqueue != NULL)
   445 		gst_object_unref (vqueue);
   446 
   447 	if (vencode != NULL)
   448 		gst_object_unref (vencode);
   449 
   450 	if (vqueue_src != NULL)
   451 		gst_object_unref (vqueue_src);
   452 
   453     if (vcolorspace != NULL)
   454         gst_object_unref (vcolorspace);
   455 
   456     return NULL;
   457 }
   458 
   459 
   460 
   461 void
   462 g_mencoder_setup_stream (GMencoder *self, 
   463                          const gchar* mux_name,
   464                          const gchar* video_encode,
   465                          gchar** video_encode_prop,
   466                          gdouble video_fps,
   467                          gdouble video_rate,
   468                          guint video_width, 
   469                          guint video_height,                         
   470                          const gchar* audio_encode,
   471                          gchar** audio_encode_prop,
   472                          guint audio_rate,
   473                          const gchar* out_uri)
   474 {
   475     GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
   476     if (priv->ready == TRUE) {
   477         g_warning ("Stream already configured. You need close stream first.");
   478         return;
   479     }
   480 
   481     _close_output (self);
   482     _open_output (self, out_uri);
   483 
   484 	priv->sources = 0;
   485     priv->pipe = _create_pipeline (self,
   486             video_encode,
   487             mux_name,
   488             video_encode_prop,
   489             video_fps,
   490             video_rate,
   491             video_width,
   492             video_height,
   493             audio_encode,
   494             audio_encode_prop,
   495             audio_rate);
   496 
   497 }
   498 
   499 
   500 gboolean
   501 g_mencoder_append_uri (GMencoder *self,
   502                      const gchar* uri)
   503 {
   504     GstPad *pad_src;
   505     GstPad *pad_sink;
   506     GstElement *src;
   507     GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
   508     gboolean ret = FALSE;
   509     GstElement *ap = NULL;
   510     GstElement *vp = NULL;
   511 
   512 
   513     g_return_val_if_fail (priv->pipe != NULL, FALSE);
   514     g_return_val_if_fail (priv->ready == FALSE, FALSE);
   515 
   516 #ifndef SUPPORT_MULT_INPUT
   517 	g_return_val_if_fail (priv->sources < 1, FALSE);
   518 #endif
   519 
   520     src = _create_source (uri);
   521     if (src == NULL) 
   522         return FALSE;
   523 
   524 	priv->src = gst_bin_get_by_name (GST_BIN (src), "src");
   525 
   526     gst_bin_add (GST_BIN (priv->pipe), src);
   527 
   528 #ifdef SUPPORT_MULT_INPUT
   529     ap = gst_bin_get_by_name (GST_BIN (priv->pipe), "ap");
   530     vp = gst_bin_get_by_name (GST_BIN (priv->pipe), "vp");
   531 #else
   532     ap = gst_bin_get_by_name (GST_BIN (priv->pipe), "abin");
   533     vp = gst_bin_get_by_name (GST_BIN (priv->pipe), "vbin");
   534 #endif
   535 
   536     if ((vp == NULL)  || (ap == NULL)) {
   537 		g_warning  ("Fail to get output bin");
   538         goto error;
   539 	}
   540 
   541     pad_src = gst_element_get_pad (src, "src_audio");
   542     pad_sink = gst_element_get_compatible_pad (ap, 
   543             pad_src, 
   544             gst_pad_get_caps (pad_src));
   545 
   546     if ((pad_sink == NULL) || (pad_src == NULL))
   547         goto error;
   548 
   549     GstPadLinkReturn lret = gst_pad_link (pad_src, pad_sink);
   550     if (lret != GST_PAD_LINK_OK)
   551         goto error;
   552 
   553     gst_object_unref (pad_src);
   554     gst_object_unref (pad_sink);
   555 
   556     pad_src = gst_element_get_pad (src, "src_video");
   557     pad_sink = gst_element_get_compatible_pad (vp, 
   558             pad_src, 
   559             gst_pad_get_caps (pad_src));
   560 
   561     if ((pad_src == NULL) || (pad_sink == NULL))
   562         goto error;
   563 
   564     if (gst_pad_link (pad_src, pad_sink) != GST_PAD_LINK_OK) {
   565         g_warning ("invalid source. video");
   566         goto error;
   567     }
   568 
   569 	priv->sources++;
   570     ret = TRUE;
   571 	g_debug ("Uri: [%s] OK ", uri);
   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 	g_debug ("g_mencoder_close_stream");
   632 	if (priv->tick_id != 0) {			
   633 		g_source_remove (priv->tick_id);
   634 		priv->tick_id = 0;
   635 	}
   636 
   637     if (priv->pipe != NULL) { 
   638         gst_element_set_state (priv->pipe, GST_STATE_NULL);
   639         gst_object_unref (priv->pipe);
   640         priv->pipe = NULL;
   641         priv->abin = NULL;
   642         priv->vbin = NULL;
   643         priv->sink = NULL;
   644     }
   645     priv->ready = FALSE;
   646 
   647 
   648 }
   649 
   650 static GstElement*
   651 _create_pipeline (GMencoder *self,
   652                   const gchar* video_encode,
   653                   const gchar* mux_name,
   654                   gchar** video_encode_prop,
   655                   gdouble video_fps,
   656                   gdouble video_rate,
   657                   guint video_width, 
   658                   guint video_height,                         
   659                   const gchar* audio_encode,
   660                   gchar** audio_encode_prop,
   661                   guint audio_rate)
   662 {
   663 	GstBus *bus = NULL;
   664 	GstElement *pipe = NULL;
   665 	GstElement *sink = NULL;
   666     GstElement *mux = NULL;
   667     GstElement *abin = NULL;
   668     GstElement *vbin = NULL;    
   669     GstPad *aux_pad = NULL;
   670     GstPad *mux_pad = NULL;
   671 #ifdef SUPPORT_MULT_INPUT
   672     GstElement *ap = NULL;
   673     GstElement *vp = NULL;    
   674 #endif
   675     GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
   676 
   677 	pipe = gst_pipeline_new ("pipe");
   678 
   679 #ifdef SUPPORT_MULT_INPUT			
   680 	ap = gst_element_factory_make ("concatmux", "ap");
   681     vp = gst_element_factory_make ("concatmux", "vp");
   682 	gst_bin_add_many (GST_BIN (pipe), ap, vp, NULL);
   683 #endif
   684 
   685     mux = gst_element_factory_make ((mux_name ? mux_name : "ffmux_mpeg"), "mux");
   686     if (mux == NULL)
   687         goto error;
   688 
   689 
   690     sink = gst_element_factory_make ("fdsink", "sink");
   691     if (sink == NULL)
   692         goto error;
   693 
   694     g_object_set (G_OBJECT(sink), 
   695 			"fd", priv->fd,
   696             NULL);
   697 
   698     abin = _create_audio_bin (audio_encode, audio_encode_prop, audio_rate);
   699     if (abin == NULL)
   700         goto error;
   701 
   702     vbin = _create_video_bin (video_encode, video_encode_prop, video_fps, video_rate, video_width, video_height);
   703     if (vbin == NULL)
   704         goto error;
   705 
   706 	// Finish Pipe
   707     gst_bin_add_many (GST_BIN (pipe), abin, vbin, mux, sink, NULL);
   708 
   709 
   710 #ifdef SUPPORT_MULT_INPUT	
   711 	if (gst_element_link (ap, abin) == FALSE) {
   712 		g_warning ("Fail to link concat and abin");
   713 		goto error;
   714 	}
   715 
   716 	if (gst_element_link (vp, vbin) == FALSE) {
   717 		g_warning ("Fail to link concat and vbin");
   718 	}
   719 #endif	
   720 
   721     //Link bins with mux
   722     aux_pad = gst_element_get_pad (abin, "src");
   723     mux_pad = gst_element_get_compatible_pad (mux, aux_pad, GST_PAD_CAPS (aux_pad));
   724     if (mux_pad == NULL) {
   725         g_warning ("Mux element no have audio PAD");
   726         goto error;
   727     }
   728     GstPadLinkReturn ret = gst_pad_link (aux_pad, mux_pad);
   729     if (ret != GST_PAD_LINK_OK) {
   730         g_warning ("Fail link audio and mux: %d", ret);
   731         goto error;
   732    
   733     }
   734 	gst_object_unref (aux_pad);
   735     gst_object_unref (mux_pad);
   736 
   737     aux_pad = gst_element_get_pad (vbin, "src");
   738     mux_pad = gst_element_get_compatible_pad (mux, aux_pad, GST_PAD_CAPS (aux_pad));
   739     if (mux_pad == NULL) {
   740         g_warning ("Mux element no have video PAD");
   741         goto error;
   742     }
   743     ret = gst_pad_link (aux_pad, mux_pad);
   744     if (ret != GST_PAD_LINK_OK) {
   745         g_warning ("Fail link video and mux: %d", ret);
   746         goto error;
   747     }
   748     gst_object_unref (aux_pad);
   749     gst_object_unref (mux_pad);
   750     aux_pad = NULL;
   751     mux_pad = NULL;
   752 
   753     //Link mux with sink
   754     gst_element_link (mux, sink);
   755 
   756 	bus = gst_pipeline_get_bus (GST_PIPELINE (pipe));
   757 	gst_bus_add_watch (bus, _pipeline_bus_cb, self);
   758 	gst_object_unref (bus);
   759     return pipe;
   760 	
   761 error:
   762 	g_warning ("Invalid uri");
   763 
   764 	if (pipe != NULL) {
   765 		gst_object_unref (pipe);
   766     }
   767 
   768 
   769     if (mux != NULL) {
   770         gst_object_unref (mux);
   771     }
   772 
   773     if (mux_pad != NULL) {
   774         gst_object_unref (mux_pad);
   775     }
   776 
   777     if (aux_pad != NULL) {
   778         gst_object_unref (mux_pad);
   779     }
   780 
   781 	if (sink != NULL) {
   782 		gst_object_unref (sink);
   783     }
   784 
   785     if (abin != NULL) {
   786         gst_object_unref (abin);
   787     }
   788 
   789     if (vbin != NULL) {
   790         gst_object_unref (vbin);
   791     }
   792 
   793 	return FALSE;
   794 }
   795 
   796 
   797 static void
   798 _close_output (GMencoder *self)
   799 {
   800     
   801 }
   802 
   803 static GstElement*
   804 _create_source (const gchar* uri)
   805 {
   806 
   807     GstElement *bsrc = NULL;
   808     GstElement *src = NULL;
   809     GstElement *aqueue = NULL;
   810     GstElement *vqueue = NULL;
   811     GstElement *decode = NULL;
   812     GstPad *src_pad = NULL;
   813 
   814 
   815     bsrc = gst_bin_new (NULL);
   816 
   817 	//src = gst_element_factory_make ("gnomevfssrc", "src");
   818     //g_object_set (G_OBJECT (src), "location", uri, NULL);
   819 	src = gst_element_make_from_uri (GST_URI_SRC, uri, "src");
   820 	if (src == NULL) 
   821 		goto error;
   822 
   823 	decode = gst_element_factory_make ("decodebin2", "decode");
   824 	if (decode == NULL) 
   825 		goto error;
   826 
   827     aqueue = gst_element_factory_make ("queue", "aqueue");
   828     if (aqueue == NULL)
   829         goto error;
   830 
   831     vqueue = gst_element_factory_make ("queue", "vqueue");
   832     if (vqueue == NULL)
   833         goto error;
   834 
   835     gst_bin_add_many (GST_BIN (bsrc), src, decode, aqueue, vqueue, NULL);
   836     gst_element_link (src, decode);
   837 
   838 	g_signal_connect (G_OBJECT (decode), 
   839 				"new-decoded-pad",
   840 				G_CALLBACK (_decodebin_new_pad_cb),
   841 				bsrc);
   842 
   843 	g_signal_connect (G_OBJECT (decode),
   844 				"unknown-type",
   845 				G_CALLBACK (_decodebin_unknown_type_cb),
   846 				pipe);
   847 
   848     src_pad = gst_element_get_pad (aqueue, "src");
   849    	gst_element_add_pad (bsrc, gst_ghost_pad_new("src_audio", src_pad));
   850     gst_object_unref (src_pad);
   851 
   852     src_pad = gst_element_get_pad (vqueue, "src");
   853    	gst_element_add_pad (bsrc, gst_ghost_pad_new("src_video", src_pad));
   854     gst_object_unref (src_pad);
   855 
   856     return bsrc;
   857 
   858 error:
   859 	if (src != NULL) {
   860 		gst_object_unref (src);
   861     }
   862 
   863 	if (decode != NULL) {
   864 		gst_object_unref (decode);
   865     }
   866 
   867 	if (aqueue != NULL) {
   868 		gst_object_unref (aqueue);
   869     }
   870 
   871 	if (vqueue != NULL) {
   872 		gst_object_unref (vqueue);
   873     }
   874 
   875     return NULL;
   876 }
   877 
   878 static void
   879 _open_output (GMencoder *self, 
   880               const gchar* uri)
   881 {
   882     gchar** i;
   883     GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
   884 
   885     i = g_strsplit (uri, "://", 0);
   886     if (strcmp (i[0], "fd") == 0) {
   887         priv->fd = atoi (i[1]);
   888     } else if (strcmp (i[0], "file") == 0) {
   889         priv->fd = open (i[1], O_WRONLY | O_CREAT | O_TRUNC);
   890     } else {
   891         g_warning ("Output uri not supported");
   892     }
   893 
   894     g_strfreev (i);
   895 }
   896 
   897 static gboolean
   898 _pipeline_bus_cb (GstBus     *bus,
   899 		  GstMessage *msg,
   900 		  gpointer    user_data)
   901 {
   902 	GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (user_data);
   903 
   904 	switch (GST_MESSAGE_TYPE (msg)) 
   905 	{
   906 		case GST_MESSAGE_STATE_CHANGED:
   907 		{
   908 			GstState oldstate;
   909 			GstState newstate;
   910 			GstState pendingstate;
   911 
   912 
   913 			gst_message_parse_state_changed (msg, &oldstate,
   914 				&newstate, &pendingstate);
   915 
   916             if (pendingstate != GST_STATE_VOID_PENDING)
   917                 break;
   918 
   919             if ((oldstate == GST_STATE_READY) && 
   920                 (newstate == GST_STATE_PAUSED)) {
   921                     if (priv->ready) 
   922                         g_signal_emit (user_data, g_mencoder_signals[PAUSED], 0);
   923             } else if ((oldstate == GST_STATE_PAUSED) &&
   924                        (newstate == GST_STATE_PLAYING)) {
   925                         g_signal_emit (user_data, g_mencoder_signals[PLAYING], 0);
   926             } else if ((oldstate == GST_STATE_READY) &&
   927                        (newstate == GST_STATE_NULL)) {
   928                         g_signal_emit (user_data, g_mencoder_signals[STOPED], 0);
   929             }			
   930             break;
   931 		}
   932 		case GST_MESSAGE_ERROR: 
   933 		{
   934 		    GError *error;
   935 		    gchar *debug;
   936 		    gchar *err_str;
   937 		    
   938 		    gst_message_parse_error (msg, &error, &debug);
   939 		    err_str = g_strdup_printf ("Error [%d] %s (%s)", error->code,
   940 		        error->message,
   941 		        debug);
   942 		    g_signal_emit (user_data, g_mencoder_signals[ERROR], 0, err_str);
   943             priv->ready = FALSE;
   944 		    g_free (err_str);
   945 		    g_clear_error (&error);
   946 		    g_free (debug);
   947 		    break;
   948 		}
   949 		
   950 		case GST_MESSAGE_EOS:
   951             priv->ready = FALSE;
   952 		    g_signal_emit (user_data, g_mencoder_signals[EOS], 0);
   953 		    break;		
   954 		case GST_MESSAGE_DURATION:
   955 		{
   956 			GstFormat format;
   957 			gint64 duration;
   958 			gst_message_parse_duration (msg, &format, &duration);
   959 			if (format == GST_FORMAT_BYTES)
   960 				priv->duration = duration;
   961 			break;
   962 		}
   963 		default:
   964 		{
   965 			break;
   966 		}
   967 	}
   968 	return TRUE;
   969 }
   970 
   971 
   972 
   973 static void 
   974 _decodebin_new_pad_cb (GstElement* object,
   975                        GstPad* pad,
   976                        gboolean flag,
   977                        gpointer user_data)
   978 {
   979 	GstCaps *caps;
   980 	gchar *str_caps = NULL;
   981     GstElement *sink_element;
   982     GstPad *sink_pad;
   983 
   984 	caps = gst_pad_get_caps (pad);
   985 	str_caps = gst_caps_to_string (caps);
   986 	g_debug ("New pad : %s", str_caps);
   987 	if (strstr (str_caps, "audio") != NULL) {
   988         sink_element = gst_bin_get_by_name (GST_BIN (user_data), "aqueue");
   989 	} else if (strstr (str_caps, "video") != NULL) {
   990         sink_element = gst_bin_get_by_name (GST_BIN (user_data), "vqueue");
   991 	} else {
   992 		g_warning ("invalid caps %s", str_caps);
   993 	}
   994 
   995     sink_pad = gst_element_get_pad (sink_element, "sink");
   996 	gst_pad_link (pad, sink_pad);
   997 
   998     gst_object_unref (sink_element);
   999 	gst_object_unref (sink_pad);
  1000 	g_free (str_caps);
  1001 	gst_caps_unref (caps);
  1002 }
  1003 
  1004 static void 
  1005 _decodebin_unknown_type_cb (GstElement* object,
  1006                             GstPad* pad,
  1007                             GstCaps* caps,
  1008                             gpointer user_data)
  1009 {
  1010     g_warning  ("Unknown Type");
  1011     //priv->ready = FALSE;
  1012 }
  1013 
  1014 static gboolean
  1015 _tick_cb (gpointer user_data)
  1016 {
  1017 	GstFormat format = GST_FORMAT_BYTES;
  1018 	gint64 cur = 0;
  1019 
  1020 	GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (user_data);
  1021 
  1022 	if (priv->duration == 0) {
  1023 		gint64 d = 0;
  1024 		if (gst_element_query_duration (priv->src, &format, &d))
  1025 			priv->duration = d;
  1026 	}			
  1027 
  1028 	if (priv->duration != 0) {
  1029 		gst_element_query_position (priv->src, &format, &cur);
  1030 		g_print ("PROGRESS:%lli\n", (99 * cur) / priv->duration); 
  1031 	}
  1032 
  1033 	return TRUE;
  1034 }