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