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