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