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