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