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