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