gmyth-stream/gmemcoder/src/gmencoder.c
author melunko
Wed May 16 13:21:24 2007 +0100 (2007-05-16)
branchtrunk
changeset 662 9d602fc9a799
parent 634 43f66895cc86
child 671 a05b421242e4
permissions -rw-r--r--
[svn r668] Fixed but to release hostname string when the local machine does not have hostname set
     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 	gboolean ready;
    44     SetupInfo *info;
    45     GstClockTime videot;
    46     GstClockTime audiot;
    47     gint fd;
    48 	gint sources;
    49 	gint tick_id;
    50 };
    51 
    52 enum {
    53   PAUSED,
    54   PLAYING,
    55   STOPED,
    56   EOS,
    57   ERROR,
    58   LAST_SIGNAL
    59 };
    60 
    61 static void g_mencoder_class_init       (GMencoderClass *klass);
    62 static void g_mencoder_init             (GMencoder *object);
    63 static void g_mencoder_dispose  	    (GObject *object);
    64 static void g_mencoder_finalize 	    (GObject *object);
    65 static GstElement*
    66             _create_audio_bin           (const gchar* encode,
    67                                          gchar** encode_prop,
    68                                          gint rate);
    69 static GstElement*
    70             _create_video_bin           (const gchar* encode,
    71                                         gchar** encode_prop,
    72                                         gdouble fps,
    73                                         gint rate,
    74                                         guint width, 
    75                                         guint height);
    76 
    77 static gboolean 
    78             _pipeline_bus_cb            (GstBus     *bus,
    79 		                                 GstMessage *msg,
    80 		                                 gpointer    user_data);
    81 static void _decodebin_new_pad_cb 		(GstElement* object,
    82 				                         GstPad* pad,
    83 				                         gboolean flag,
    84 				                         gpointer user_data);
    85 static void  _decodebin_unknown_type_cb (GstElement* object,
    86 		                         	     GstPad* pad,
    87                                          GstCaps* caps,
    88                                          gpointer user_data);
    89 static void _close_output              (GMencoder *self);
    90 static void _open_output               (GMencoder *self,
    91                                          const gchar* uri);
    92 static GstElement* _create_source       (const gchar* uri);
    93 static GstElement*_create_pipeline      (GMencoder *self,
    94                                           const gchar* video_encode,
    95                                           const gchar* mux_name,
    96                                           gchar** video_encode_prop,
    97                                           gdouble video_fps,
    98                                           gdouble video_rate,
    99                                           guint video_width, 
   100                                           guint video_height,                         
   101                                           const gchar* audio_encode,
   102                                           gchar** audio_encode_prop,
   103                                           guint audio_rate);
   104 static gboolean _tick_cb 				 (gpointer data);
   105 
   106 
   107 
   108 
   109 
   110 
   111 static guint g_mencoder_signals[LAST_SIGNAL] = { 0 };
   112 
   113 G_DEFINE_TYPE(GMencoder, g_mencoder, G_TYPE_OBJECT)
   114 
   115 static void
   116 g_mencoder_class_init (GMencoderClass *klass)
   117 {   
   118 	GObjectClass *object_class;
   119 
   120 	object_class = (GObjectClass *) klass;
   121 
   122 	g_type_class_add_private (klass, sizeof (GMencoderPrivate));
   123         
   124 	object_class->dispose  = g_mencoder_dispose;
   125 	object_class->finalize = g_mencoder_finalize;	
   126 	
   127     g_mencoder_signals[PAUSED] =
   128         g_signal_new ("paused",
   129     		  G_OBJECT_CLASS_TYPE (object_class),
   130     		  G_SIGNAL_RUN_FIRST,
   131     		  0, NULL, NULL,
   132     		  g_cclosure_marshal_VOID__VOID,
   133     		  G_TYPE_NONE, 0);
   134     		  
   135     g_mencoder_signals[PLAYING] =
   136         g_signal_new ("playing",
   137     		  G_OBJECT_CLASS_TYPE (object_class),
   138     		  G_SIGNAL_RUN_FIRST,
   139     		  0, NULL, NULL,
   140               g_cclosure_marshal_VOID__VOID,
   141     		  G_TYPE_NONE, 0);
   142 
   143     g_mencoder_signals[STOPED] =
   144         g_signal_new ("stoped",
   145     		  G_OBJECT_CLASS_TYPE (object_class),
   146     		  G_SIGNAL_RUN_FIRST,
   147     		  0, NULL, NULL,
   148     		  g_cclosure_marshal_VOID__VOID,
   149     		  G_TYPE_NONE, 0);
   150 
   151     g_mencoder_signals[EOS] =
   152         g_signal_new ("eos",
   153     		  G_OBJECT_CLASS_TYPE (object_class),
   154     		  G_SIGNAL_RUN_FIRST,
   155     		  0, NULL, NULL,
   156     		  g_cclosure_marshal_VOID__VOID,
   157     		  G_TYPE_NONE, 0);
   158     		  
   159     		  
   160     g_mencoder_signals[ERROR] =
   161         g_signal_new ("error",
   162     		  G_OBJECT_CLASS_TYPE (object_class),
   163     		  G_SIGNAL_RUN_FIRST,
   164     		  0, NULL, NULL,
   165     		  g_cclosure_marshal_VOID__STRING,
   166     		  G_TYPE_NONE, 1, G_TYPE_STRING);	
   167 }
   168 
   169 static void
   170 g_mencoder_init (GMencoder *self)
   171 {
   172 	GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
   173     priv->info = g_new0 (SetupInfo, 1);
   174 }
   175 
   176 static void 
   177 g_mencoder_dispose (GObject *object)
   178 {
   179 }
   180 
   181 static void 
   182 g_mencoder_finalize (GObject *object)
   183 {
   184     //TODO: clear vars
   185 	g_mencoder_close_stream (G_MENCODER (object));
   186 }
   187 
   188 GMencoder*  
   189 g_mencoder_new (void)
   190 {
   191     return g_object_new (G_TYPE_MENCODER, NULL);
   192 }
   193 
   194 
   195 static void
   196 _obj_set_prop (GObject *obj, 
   197                 const gchar *prop_name,
   198                 const gchar *prop_val)
   199 {
   200     GValue p = {0};
   201     GValue v = {0};
   202     GParamSpec *s = NULL;
   203     GObjectClass *k = G_OBJECT_GET_CLASS (obj);
   204 
   205 
   206     g_value_init (&v, G_TYPE_STRING);
   207     g_value_set_string (&v, prop_val);
   208 
   209     s = g_object_class_find_property (k, prop_name);
   210     if (s == NULL) {
   211         g_print ("Invalid property name: %s\n", prop_name);
   212         return;
   213     }
   214 
   215     g_value_init (&p, s->value_type);
   216     switch (s->value_type) 
   217     {
   218         case G_TYPE_INT:
   219             g_value_set_int (&p, atoi (prop_val));
   220             break;
   221         case G_TYPE_STRING:
   222             g_value_set_string (&p, prop_val);
   223             break;
   224         default:
   225             return;
   226     }
   227        
   228     g_object_set_property (obj, prop_name, &p);
   229     g_value_unset (&v);
   230     g_value_unset (&p);
   231 }
   232 
   233 static GstElement*
   234 _create_element_with_prop (const gchar* factory_name,
   235                             const gchar* element_name,
   236                             gchar** prop)
   237 {
   238     GstElement *ret;
   239     int i;
   240 
   241     g_debug ("Creating element: %s", factory_name);
   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     gst_bin_add (GST_BIN (priv->pipe), src);
   525 
   526 #ifdef SUPPORT_MULT_INPUT
   527     ap = gst_bin_get_by_name (GST_BIN (priv->pipe), "ap");
   528     vp = gst_bin_get_by_name (GST_BIN (priv->pipe), "vp");
   529 #else
   530     ap = gst_bin_get_by_name (GST_BIN (priv->pipe), "abin");
   531     vp = gst_bin_get_by_name (GST_BIN (priv->pipe), "vbin");
   532 #endif
   533 
   534     if ((vp == NULL)  || (ap == NULL)) {
   535 		g_warning  ("Fail to get output bin");
   536         goto error;
   537 	}
   538 
   539     pad_src = gst_element_get_pad (src, "src_audio");
   540     pad_sink = gst_element_get_compatible_pad (ap, 
   541             pad_src, 
   542             gst_pad_get_caps (pad_src));
   543 
   544     if ((pad_sink == NULL) || (pad_src == NULL))
   545         goto error;
   546 
   547     GstPadLinkReturn lret = gst_pad_link (pad_src, pad_sink);
   548     if (lret != GST_PAD_LINK_OK)
   549         goto error;
   550 
   551     gst_object_unref (pad_src);
   552     gst_object_unref (pad_sink);
   553 
   554     pad_src = gst_element_get_pad (src, "src_video");
   555     pad_sink = gst_element_get_compatible_pad (vp, 
   556             pad_src, 
   557             gst_pad_get_caps (pad_src));
   558 
   559     if ((pad_src == NULL) || (pad_sink == NULL))
   560         goto error;
   561 
   562     if (gst_pad_link (pad_src, pad_sink) != GST_PAD_LINK_OK) {
   563         g_warning ("invalid source. video");
   564         goto error;
   565     }
   566 
   567 	priv->sources++;
   568     ret = TRUE;
   569 	g_debug ("Uri: [%s] OK ", uri);
   570 error:
   571 
   572     if ((src != NULL) && (ret == FALSE)) {
   573         gst_bin_remove (GST_BIN (priv->pipe), src);
   574         gst_object_unref (src);
   575     }
   576 
   577     if (ap != NULL) 
   578         gst_object_unref (ap);
   579 
   580     if (vp != NULL)
   581         gst_object_unref (vp);
   582 
   583     if (pad_src != NULL)
   584         gst_object_unref (pad_src);
   585 
   586     if (pad_sink != NULL)
   587         gst_object_unref (pad_sink);
   588 
   589     return ret;
   590 }
   591 
   592 
   593 
   594 void        
   595 g_mencoder_remove_uri (GMencoder *self,
   596                         const gchar* uri)
   597 {
   598     // GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
   599     //TODO: remove src
   600 }
   601 
   602 void
   603 g_mencoder_play_stream (GMencoder *self)
   604 {
   605     GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
   606 
   607     g_return_if_fail (priv->ready == FALSE);
   608     priv->ready = TRUE;
   609     gst_element_set_state (priv->pipe, GST_STATE_PLAYING);
   610 
   611 	priv->tick_id = g_timeout_add (500, _tick_cb, self);
   612 }
   613 
   614 void
   615 g_mencoder_pause_stream (GMencoder *self)
   616 {
   617     GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
   618 
   619     g_return_if_fail (priv->ready == TRUE);
   620     gst_element_set_state (priv->pipe, GST_STATE_PAUSED);
   621 }
   622 
   623 void
   624 g_mencoder_close_stream (GMencoder *self)
   625 {
   626 
   627     GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
   628 
   629 	g_debug ("g_mencoder_close_stream");
   630 	if (priv->tick_id != 0) {			
   631 		g_source_remove (priv->tick_id);
   632 		priv->tick_id = 0;
   633 	}
   634 
   635     if (priv->pipe != NULL) { 
   636         gst_element_set_state (priv->pipe, GST_STATE_NULL);
   637         gst_object_unref (priv->pipe);
   638         priv->pipe = NULL;
   639         priv->abin = NULL;
   640         priv->vbin = NULL;
   641         priv->sink = NULL;
   642     }
   643     priv->ready = FALSE;
   644 
   645 
   646 }
   647 
   648 static GstElement*
   649 _create_pipeline (GMencoder *self,
   650                   const gchar* video_encode,
   651                   const gchar* mux_name,
   652                   gchar** video_encode_prop,
   653                   gdouble video_fps,
   654                   gdouble video_rate,
   655                   guint video_width, 
   656                   guint video_height,                         
   657                   const gchar* audio_encode,
   658                   gchar** audio_encode_prop,
   659                   guint audio_rate)
   660 {
   661 	GstBus *bus = NULL;
   662 	GstElement *pipe = NULL;
   663 	GstElement *sink = NULL;
   664     GstElement *mux = NULL;
   665     GstElement *abin = NULL;
   666     GstElement *vbin = NULL;    
   667     GstPad *aux_pad = NULL;
   668     GstPad *mux_pad = NULL;
   669 #ifdef SUPPORT_MULT_INPUT
   670     GstElement *ap = NULL;
   671     GstElement *vp = NULL;    
   672 #endif
   673     GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
   674 
   675 	pipe = gst_pipeline_new ("pipe");
   676 
   677 #ifdef SUPPORT_MULT_INPUT			
   678 	ap = gst_element_factory_make ("concatmux", "ap");
   679     vp = gst_element_factory_make ("concatmux", "vp");
   680 	gst_bin_add_many (GST_BIN (pipe), ap, vp, NULL);
   681 #endif
   682 
   683     mux = gst_element_factory_make ((mux_name ? mux_name : "ffmux_mpeg"), "mux");
   684     if (mux == NULL)
   685         goto error;
   686 
   687 
   688     sink = gst_element_factory_make ("fdsink", "sink");
   689     if (sink == NULL)
   690         goto error;
   691 
   692     g_object_set (G_OBJECT(sink), 
   693 			"fd", priv->fd,
   694             NULL);
   695 
   696     abin = _create_audio_bin (audio_encode, audio_encode_prop, audio_rate);
   697     if (abin == NULL)
   698         goto error;
   699 
   700     vbin = _create_video_bin (video_encode, video_encode_prop, video_fps, video_rate, video_width, video_height);
   701     if (vbin == NULL)
   702         goto error;
   703 
   704 	// Finish Pipe
   705     gst_bin_add_many (GST_BIN (pipe), abin, vbin, mux, sink, NULL);
   706 
   707 
   708 #ifdef SUPPORT_MULT_INPUT	
   709 	if (gst_element_link (ap, abin) == FALSE) {
   710 		g_warning ("Fail to link concat and abin");
   711 		goto error;
   712 	}
   713 
   714 	if (gst_element_link (vp, vbin) == FALSE) {
   715 		g_warning ("Fail to link concat and vbin");
   716 	}
   717 #endif	
   718 
   719     //Link bins with mux
   720     aux_pad = gst_element_get_pad (abin, "src");
   721     mux_pad = gst_element_get_compatible_pad (mux, aux_pad, GST_PAD_CAPS (aux_pad));
   722     if (mux_pad == NULL) {
   723         g_warning ("Mux element no have audio PAD");
   724         goto error;
   725     }
   726     GstPadLinkReturn ret = gst_pad_link (aux_pad, mux_pad);
   727     if (ret != GST_PAD_LINK_OK) {
   728         g_warning ("Fail link audio and mux: %d", ret);
   729         goto error;
   730    
   731     }
   732 	gst_object_unref (aux_pad);
   733     gst_object_unref (mux_pad);
   734 
   735     aux_pad = gst_element_get_pad (vbin, "src");
   736     mux_pad = gst_element_get_compatible_pad (mux, aux_pad, GST_PAD_CAPS (aux_pad));
   737     if (mux_pad == NULL) {
   738         g_warning ("Mux element no have video PAD");
   739         goto error;
   740     }
   741     ret = gst_pad_link (aux_pad, mux_pad);
   742     if (ret != GST_PAD_LINK_OK) {
   743         g_warning ("Fail link video and mux: %d", ret);
   744         goto error;
   745     }
   746     gst_object_unref (aux_pad);
   747     gst_object_unref (mux_pad);
   748     aux_pad = NULL;
   749     mux_pad = NULL;
   750 
   751     //Link mux with sink
   752     gst_element_link (mux, sink);
   753 
   754 	bus = gst_pipeline_get_bus (GST_PIPELINE (pipe));
   755 	gst_bus_add_watch (bus, _pipeline_bus_cb, self);
   756 	gst_object_unref (bus);
   757     return pipe;
   758 	
   759 error:
   760 	g_warning ("Invalid uri");
   761 
   762 	if (pipe != NULL) {
   763 		gst_object_unref (pipe);
   764     }
   765 
   766 
   767     if (mux != NULL) {
   768         gst_object_unref (mux);
   769     }
   770 
   771     if (mux_pad != NULL) {
   772         gst_object_unref (mux_pad);
   773     }
   774 
   775     if (aux_pad != NULL) {
   776         gst_object_unref (mux_pad);
   777     }
   778 
   779 	if (sink != NULL) {
   780 		gst_object_unref (sink);
   781     }
   782 
   783     if (abin != NULL) {
   784         gst_object_unref (abin);
   785     }
   786 
   787     if (vbin != NULL) {
   788         gst_object_unref (vbin);
   789     }
   790 
   791 	return FALSE;
   792 }
   793 
   794 
   795 static void
   796 _close_output (GMencoder *self)
   797 {
   798     
   799 }
   800 
   801 static GstElement*
   802 _create_source (const gchar* uri)
   803 {
   804 
   805     GstElement *bsrc;
   806     GstElement *src;
   807     GstElement *aqueue;
   808     GstElement *vqueue;
   809     GstElement *decode;
   810     GstPad *src_pad;
   811 
   812 
   813     bsrc = gst_bin_new (NULL);
   814 
   815 	//src = gst_element_factory_make ("gnomevfssrc", "src");
   816     //g_object_set (G_OBJECT (src), "location", uri, NULL);
   817 	src = gst_element_make_from_uri (GST_URI_SRC, uri, "src");
   818 	if (src == NULL) 
   819 		goto error;
   820 
   821 	decode = gst_element_factory_make ("decodebin2", "decode");
   822 	if (decode == NULL) 
   823 		goto error;
   824 
   825     aqueue = gst_element_factory_make ("queue", "aqueue");
   826     if (aqueue == NULL)
   827         goto error;
   828 
   829     vqueue = gst_element_factory_make ("queue", "vqueue");
   830     if (vqueue == NULL)
   831         goto error;
   832 
   833     gst_bin_add_many (GST_BIN (bsrc), src, decode, aqueue, vqueue, NULL);
   834     gst_element_link (src, decode);
   835 
   836 	g_signal_connect (G_OBJECT (decode), 
   837 				"new-decoded-pad",
   838 				G_CALLBACK (_decodebin_new_pad_cb),
   839 				bsrc);
   840 
   841 	g_signal_connect (G_OBJECT (decode),
   842 				"unknown-type",
   843 				G_CALLBACK (_decodebin_unknown_type_cb),
   844 				pipe);
   845 
   846     src_pad = gst_element_get_pad (aqueue, "src");
   847    	gst_element_add_pad (bsrc, gst_ghost_pad_new("src_audio", src_pad));
   848     gst_object_unref (src_pad);
   849 
   850     src_pad = gst_element_get_pad (vqueue, "src");
   851    	gst_element_add_pad (bsrc, gst_ghost_pad_new("src_video", src_pad));
   852     gst_object_unref (src_pad);
   853 
   854     return bsrc;
   855 
   856 error:
   857 	if (src != NULL) {
   858 		gst_object_unref (src);
   859     }
   860 
   861 	if (decode != NULL) {
   862 		gst_object_unref (decode);
   863     }
   864 
   865 	if (aqueue != NULL) {
   866 		gst_object_unref (aqueue);
   867     }
   868 
   869 	if (vqueue != NULL) {
   870 		gst_object_unref (vqueue);
   871     }
   872 
   873     return NULL;
   874 }
   875 
   876 static void
   877 _open_output (GMencoder *self, 
   878               const gchar* uri)
   879 {
   880     gchar** i;
   881     GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
   882 
   883     i = g_strsplit (uri, "://", 0);
   884     if (strcmp (i[0], "fd") == 0) {
   885         priv->fd = atoi (i[1]);
   886     } else if (strcmp (i[0], "file") == 0) {
   887         priv->fd = open (i[1], O_WRONLY | O_CREAT | O_TRUNC);
   888     } else {
   889         g_warning ("Output uri not supported");
   890     }
   891 
   892     g_strfreev (i);
   893 }
   894 
   895 static gboolean
   896 _pipeline_bus_cb (GstBus     *bus,
   897 		  GstMessage *msg,
   898 		  gpointer    user_data)
   899 {
   900 	GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (user_data);
   901 
   902 	switch (GST_MESSAGE_TYPE (msg)) 
   903 	{
   904 		case GST_MESSAGE_STATE_CHANGED:
   905 		{
   906 			GstState oldstate;
   907 			GstState newstate;
   908 			GstState pendingstate;
   909 
   910 
   911 			gst_message_parse_state_changed (msg, &oldstate,
   912 				&newstate, &pendingstate);
   913 
   914             if (pendingstate != GST_STATE_VOID_PENDING)
   915                 break;
   916 
   917             if ((oldstate == GST_STATE_READY) && 
   918                 (newstate == GST_STATE_PAUSED)) {
   919                     if (priv->ready) 
   920                         g_signal_emit (user_data, g_mencoder_signals[PAUSED], 0);
   921             } else if ((oldstate == GST_STATE_PAUSED) &&
   922                        (newstate == GST_STATE_PLAYING)) {
   923                         g_signal_emit (user_data, g_mencoder_signals[PLAYING], 0);
   924             } else if ((oldstate == GST_STATE_READY) &&
   925                        (newstate == GST_STATE_NULL)) {
   926                         g_signal_emit (user_data, g_mencoder_signals[STOPED], 0);
   927             }			
   928             break;
   929 		}
   930 		case GST_MESSAGE_ERROR: 
   931 		{
   932 		    GError *error;
   933 		    gchar *debug;
   934 		    gchar *err_str;
   935 		    
   936 		    gst_message_parse_error (msg, &error, &debug);
   937 		    err_str = g_strdup_printf ("Error [%d] %s (%s)", error->code,
   938 		        error->message,
   939 		        debug);
   940 		    g_signal_emit (user_data, g_mencoder_signals[ERROR], 0, err_str);
   941             priv->ready = FALSE;
   942 		    g_free (err_str);
   943 		    g_clear_error (&error);
   944 		    g_free (debug);
   945 		    break;
   946 		}
   947 		
   948 		case GST_MESSAGE_EOS:
   949             priv->ready = FALSE;
   950 		    g_signal_emit (user_data, g_mencoder_signals[EOS], 0);
   951 		    break;		
   952 
   953 		default:
   954 		{
   955 			break;
   956 		}
   957 	}
   958 	return TRUE;
   959 }
   960 
   961 
   962 
   963 static void 
   964 _decodebin_new_pad_cb (GstElement* object,
   965                        GstPad* pad,
   966                        gboolean flag,
   967                        gpointer user_data)
   968 {
   969 	GstCaps *caps;
   970 	gchar *str_caps = NULL;
   971     GstElement *sink_element;
   972     GstPad *sink_pad;
   973 
   974 	caps = gst_pad_get_caps (pad);
   975 	str_caps = gst_caps_to_string (caps);
   976 	g_debug ("New pad : %s", str_caps);
   977 	if (strstr (str_caps, "audio") != NULL) {
   978         sink_element = gst_bin_get_by_name (GST_BIN (user_data), "aqueue");
   979 	} else if (strstr (str_caps, "video") != NULL) {
   980         sink_element = gst_bin_get_by_name (GST_BIN (user_data), "vqueue");
   981 	} else {
   982 		g_warning ("invalid caps %s", str_caps);
   983 	}
   984 
   985     sink_pad = gst_element_get_pad (sink_element, "sink");
   986 	gst_pad_link (pad, sink_pad);
   987 
   988     gst_object_unref (sink_element);
   989 	gst_object_unref (sink_pad);
   990 	g_free (str_caps);
   991 	gst_caps_unref (caps);
   992 }
   993 
   994 static void 
   995 _decodebin_unknown_type_cb (GstElement* object,
   996                             GstPad* pad,
   997                             GstCaps* caps,
   998                             gpointer user_data)
   999 {
  1000     g_warning  ("Unknown Type");
  1001     //priv->ready = FALSE;
  1002 }
  1003 
  1004 static gboolean
  1005 _tick_cb (gpointer user_data)
  1006 {
  1007 	GstFormat format = GST_FORMAT_TIME;
  1008 	gint64 cur = 0;
  1009 	gint64 duration = 0;
  1010 
  1011 	GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (user_data);
  1012 
  1013 	if (gst_element_query_duration (priv->pipe, &format, &duration)) {
  1014 		gst_element_query_position (priv->pipe, &format, &cur);
  1015 		g_print ("PROGRESS:%lli%\n", (100 * cur) / duration); 
  1016 	}
  1017 
  1018 	return TRUE;
  1019 }