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