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