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