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