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