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