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