gmyth-stream/gmemcoder/src/gmencoder.c
author melunko
Thu Apr 26 19:50:02 2007 +0100 (2007-04-26)
branchtrunk
changeset 599 5555b47e102b
child 600 7da2a5e32fa6
permissions -rw-r--r--
[svn r605] added livetv support to gmyth-cat
renatofilho@588
     1
#ifdef HAVE_CONFIG_H
renatofilho@588
     2
#include "config.h"
renatofilho@588
     3
#endif
renatofilho@588
     4
renatofilho@588
     5
#include <glib.h>
renatofilho@588
     6
#include <gst/gst.h>
renatofilho@588
     7
#include <string.h>
renatofilho@588
     8
renatofilho@588
     9
#include "gmencoder.h"
renatofilho@588
    10
renatofilho@588
    11
#define G_MENCODER_GET_PRIVATE(obj) \
renatofilho@588
    12
    (G_TYPE_INSTANCE_GET_PRIVATE ((obj), G_TYPE_MENCODER, GMencoderPrivate))
renatofilho@588
    13
renatofilho@588
    14
renatofilho@588
    15
typedef struct _GMencoderPrivate GMencoderPrivate;
renatofilho@588
    16
renatofilho@588
    17
struct _GMencoderPrivate
renatofilho@588
    18
{    
renatofilho@588
    19
	GstElement *pipe;
renatofilho@588
    20
	GstElement *abin;
renatofilho@588
    21
	GstElement *vbin;
renatofilho@588
    22
	GstElement *sink;
renatofilho@588
    23
	gboolean ready;
renatofilho@588
    24
};
renatofilho@588
    25
renatofilho@588
    26
enum {
renatofilho@588
    27
  READY,
renatofilho@588
    28
  PAUSED,
renatofilho@588
    29
  PLAYING,
renatofilho@588
    30
  STOPED,
renatofilho@588
    31
  EOS,
renatofilho@588
    32
  ERROR,
renatofilho@588
    33
  LAST_SIGNAL
renatofilho@588
    34
};
renatofilho@588
    35
renatofilho@588
    36
static void g_mencoder_class_init       (GMencoderClass *klass);
renatofilho@588
    37
static void g_mencoder_init             (GMencoder *object);
renatofilho@588
    38
static void g_mencoder_dispose  	    (GObject *object);
renatofilho@588
    39
static void g_mencoder_finalize 	    (GObject *object);
renatofilho@588
    40
static GstElement*
renatofilho@588
    41
            _create_audio_bin           (GMencoder *self,
renatofilho@588
    42
                                        const gchar* encode,
renatofilho@588
    43
                                        gchar** encode_prop,
renatofilho@588
    44
                                        gint rate);
renatofilho@588
    45
static GstElement*
renatofilho@588
    46
            _create_video_bin           (GMencoder* self, 
renatofilho@588
    47
                                        const gchar* encode,
renatofilho@588
    48
                                        gchar** encode_prop,
renatofilho@588
    49
                                        gdouble fps,
renatofilho@588
    50
                                        gint rate,
renatofilho@588
    51
                                        guint width, 
renatofilho@588
    52
                                        guint height);
renatofilho@588
    53
renatofilho@588
    54
static gboolean 
renatofilho@588
    55
            _pipeline_bus_cb            (GstBus     *bus,
renatofilho@588
    56
		                                 GstMessage *msg,
renatofilho@588
    57
		                                 gpointer    user_data);
renatofilho@588
    58
static void _decodebin_new_pad_cb 		(GstElement* object,
renatofilho@588
    59
				                         GstPad* pad,
renatofilho@588
    60
				                         gboolean flag,
renatofilho@588
    61
				                         gpointer user_data);
renatofilho@588
    62
static void  _decodebin_unknown_type_cb (GstElement* object,
renatofilho@588
    63
		                         	     GstPad* pad,
renatofilho@588
    64
                                         GstCaps* caps,
renatofilho@588
    65
                                         gpointer user_data);
renatofilho@588
    66
renatofilho@588
    67
renatofilho@588
    68
static guint g_mencoder_signals[LAST_SIGNAL] = { 0 };
renatofilho@588
    69
renatofilho@588
    70
G_DEFINE_TYPE(GMencoder, g_mencoder, G_TYPE_OBJECT)
renatofilho@588
    71
renatofilho@588
    72
static void
renatofilho@588
    73
g_mencoder_class_init (GMencoderClass *klass)
renatofilho@588
    74
{   
renatofilho@588
    75
	GObjectClass *object_class;
renatofilho@588
    76
renatofilho@588
    77
	object_class = (GObjectClass *) klass;
renatofilho@588
    78
renatofilho@588
    79
	g_type_class_add_private (klass, sizeof (GMencoderPrivate));
renatofilho@588
    80
        
renatofilho@588
    81
	object_class->dispose  = g_mencoder_dispose;
renatofilho@588
    82
	object_class->finalize = g_mencoder_finalize;	
renatofilho@588
    83
	
renatofilho@588
    84
    g_mencoder_signals[READY] =
renatofilho@588
    85
        g_signal_new ("ready",
renatofilho@588
    86
    		  G_OBJECT_CLASS_TYPE (object_class),
renatofilho@588
    87
    		  G_SIGNAL_RUN_FIRST,
renatofilho@588
    88
    		  0, NULL, NULL,
renatofilho@588
    89
    		  g_cclosure_marshal_VOID__VOID,
renatofilho@588
    90
    		  G_TYPE_NONE, 0);
renatofilho@588
    91
renatofilho@588
    92
    g_mencoder_signals[PAUSED] =
renatofilho@588
    93
        g_signal_new ("paused",
renatofilho@588
    94
    		  G_OBJECT_CLASS_TYPE (object_class),
renatofilho@588
    95
    		  G_SIGNAL_RUN_FIRST,
renatofilho@588
    96
    		  0, NULL, NULL,
renatofilho@588
    97
    		  g_cclosure_marshal_VOID__VOID,
renatofilho@588
    98
    		  G_TYPE_NONE, 0);
renatofilho@588
    99
    		  
renatofilho@588
   100
    g_mencoder_signals[PLAYING] =
renatofilho@588
   101
        g_signal_new ("playing",
renatofilho@588
   102
    		  G_OBJECT_CLASS_TYPE (object_class),
renatofilho@588
   103
    		  G_SIGNAL_RUN_FIRST,
renatofilho@588
   104
    		  0, NULL, NULL,
renatofilho@588
   105
              g_cclosure_marshal_VOID__VOID,
renatofilho@588
   106
    		  G_TYPE_NONE, 0);
renatofilho@588
   107
renatofilho@588
   108
    g_mencoder_signals[STOPED] =
renatofilho@588
   109
        g_signal_new ("stoped",
renatofilho@588
   110
    		  G_OBJECT_CLASS_TYPE (object_class),
renatofilho@588
   111
    		  G_SIGNAL_RUN_FIRST,
renatofilho@588
   112
    		  0, NULL, NULL,
renatofilho@588
   113
    		  g_cclosure_marshal_VOID__VOID,
renatofilho@588
   114
    		  G_TYPE_NONE, 0);
renatofilho@588
   115
renatofilho@588
   116
    g_mencoder_signals[EOS] =
renatofilho@588
   117
        g_signal_new ("eos",
renatofilho@588
   118
    		  G_OBJECT_CLASS_TYPE (object_class),
renatofilho@588
   119
    		  G_SIGNAL_RUN_FIRST,
renatofilho@588
   120
    		  0, NULL, NULL,
renatofilho@588
   121
    		  g_cclosure_marshal_VOID__VOID,
renatofilho@588
   122
    		  G_TYPE_NONE, 0);
renatofilho@588
   123
    		  
renatofilho@588
   124
    		  
renatofilho@588
   125
    g_mencoder_signals[ERROR] =
renatofilho@588
   126
        g_signal_new ("error",
renatofilho@588
   127
    		  G_OBJECT_CLASS_TYPE (object_class),
renatofilho@588
   128
    		  G_SIGNAL_RUN_FIRST,
renatofilho@588
   129
    		  0, NULL, NULL,
renatofilho@588
   130
    		  g_cclosure_marshal_VOID__STRING,
renatofilho@588
   131
    		  G_TYPE_NONE, 1, G_TYPE_STRING);	
renatofilho@588
   132
}
renatofilho@588
   133
renatofilho@588
   134
static void
renatofilho@588
   135
g_mencoder_init (GMencoder *self)
renatofilho@588
   136
{
renatofilho@588
   137
}
renatofilho@588
   138
renatofilho@588
   139
static void 
renatofilho@588
   140
g_mencoder_dispose (GObject *object)
renatofilho@588
   141
{
renatofilho@588
   142
}
renatofilho@588
   143
renatofilho@588
   144
static void 
renatofilho@588
   145
g_mencoder_finalize (GObject *object)
renatofilho@588
   146
{
renatofilho@588
   147
	g_mencoder_close_stream (G_MENCODER (object));
renatofilho@588
   148
}
renatofilho@588
   149
renatofilho@588
   150
GMencoder*  
renatofilho@588
   151
g_mencoder_new (void)
renatofilho@588
   152
{
renatofilho@588
   153
    return g_object_new (G_TYPE_MENCODER, NULL);
renatofilho@588
   154
}
renatofilho@588
   155
renatofilho@588
   156
static void
renatofilho@588
   157
_obj_set_prop (GObject *obj, 
renatofilho@588
   158
                const gchar *prop_name,
renatofilho@588
   159
                const gchar *prop_val)
renatofilho@588
   160
{
renatofilho@588
   161
    GValue p = {0};
renatofilho@588
   162
    GValue v = {0};
renatofilho@588
   163
    GParamSpec *s = NULL;
renatofilho@588
   164
    GObjectClass *k = G_OBJECT_GET_CLASS (obj);
renatofilho@588
   165
renatofilho@588
   166
renatofilho@588
   167
    g_value_init (&v, G_TYPE_STRING);
renatofilho@588
   168
    g_value_set_string (&v, prop_val);
renatofilho@588
   169
renatofilho@588
   170
    g_debug ("PROP [%s] VAL [%s]", prop_name, prop_val);
renatofilho@588
   171
renatofilho@588
   172
    s = g_object_class_find_property (k, prop_name);
renatofilho@588
   173
    if (s == NULL) {
renatofilho@588
   174
        g_print ("Invalid property name: %s\n", prop_name);
renatofilho@588
   175
        return;
renatofilho@588
   176
    }
renatofilho@588
   177
renatofilho@588
   178
    g_value_init (&p, s->value_type);
renatofilho@588
   179
    switch (s->value_type) 
renatofilho@588
   180
    {
renatofilho@588
   181
        case G_TYPE_INT:
renatofilho@588
   182
            g_value_set_int (&p, atoi (prop_val));
renatofilho@588
   183
            break;
renatofilho@588
   184
        case G_TYPE_STRING:
renatofilho@588
   185
            g_value_set_string (&p, prop_val);
renatofilho@588
   186
            break;
renatofilho@588
   187
        default:
renatofilho@588
   188
            return;
renatofilho@588
   189
    }
renatofilho@588
   190
       
renatofilho@588
   191
    g_object_set_property (obj, prop_name, &p);
renatofilho@588
   192
    g_value_unset (&v);
renatofilho@588
   193
    g_value_unset (&p);
renatofilho@588
   194
}
renatofilho@588
   195
renatofilho@588
   196
static GstElement*
renatofilho@588
   197
_create_element_with_prop (const gchar* factory_name,
renatofilho@588
   198
                            const gchar* element_name,
renatofilho@588
   199
                            gchar** prop)
renatofilho@588
   200
{
renatofilho@588
   201
    GstElement *ret;
renatofilho@588
   202
    int i;
renatofilho@588
   203
renatofilho@588
   204
renatofilho@588
   205
    g_debug ("SET OBJ [%s]", factory_name);
renatofilho@588
   206
    ret = gst_element_factory_make (factory_name, element_name);
renatofilho@588
   207
    if (ret == NULL)
renatofilho@588
   208
        return NULL;
renatofilho@588
   209
renatofilho@588
   210
    if (prop != NULL) {
renatofilho@588
   211
        for (i=0; i < g_strv_length (prop); i++) {
renatofilho@588
   212
            char** v = g_strsplit(prop[i], "=", 2);
renatofilho@588
   213
            if (g_strv_length (v) == 2) {
renatofilho@588
   214
                _obj_set_prop (G_OBJECT (ret), v[0], v[1]);
renatofilho@588
   215
            }
renatofilho@588
   216
            g_strfreev (v);
renatofilho@588
   217
        }
renatofilho@588
   218
    }
renatofilho@588
   219
renatofilho@588
   220
    return ret;
renatofilho@588
   221
renatofilho@588
   222
}
renatofilho@588
   223
renatofilho@588
   224
static GstElement*
renatofilho@588
   225
_create_audio_bin (GMencoder* self,
renatofilho@588
   226
                    const gchar* encode,
renatofilho@588
   227
                    gchar** encode_prop,
renatofilho@588
   228
                    gint rate)
renatofilho@588
   229
{
renatofilho@588
   230
    GstElement *abin = NULL;
renatofilho@588
   231
    GstElement *aqueue = NULL;
renatofilho@588
   232
    GstElement *aconvert = NULL;
renatofilho@588
   233
    GstElement *aencode = NULL;
renatofilho@588
   234
    GstElement *aqueue_src = NULL;
renatofilho@588
   235
    GstPad *apad = NULL;
renatofilho@588
   236
renatofilho@588
   237
    //audio/x-raw-int ! queue ! audioconvert ! faac ! rtpmp4gpay !  udpsink name=upd_audio host=224.0.0.1 port=5002	
renatofilho@588
   238
	abin 	= gst_bin_new ("abin");
renatofilho@588
   239
	aqueue	= gst_element_factory_make ("queue", "aqueue");
renatofilho@588
   240
	aconvert= gst_element_factory_make ("audioconvert", "aconvert");
renatofilho@588
   241
	aencode = _create_element_with_prop ((encode ? encode : "lame"), "aencode", encode_prop);
renatofilho@588
   242
	aqueue_src= gst_element_factory_make ("queue", "aqueue_src");	
renatofilho@588
   243
renatofilho@588
   244
	if ((abin == NULL) || (aqueue == NULL) || (aconvert == NULL) 
renatofilho@588
   245
		|| (aencode == NULL) || (aqueue_src == NULL)) {
renatofilho@588
   246
		g_warning ("Audio elements not found");
renatofilho@588
   247
		goto error;
renatofilho@588
   248
	}
renatofilho@588
   249
renatofilho@588
   250
	gst_bin_add_many (GST_BIN (abin), aqueue, aconvert, aencode, aqueue_src, NULL);
renatofilho@588
   251
	gst_element_link_many (aqueue, aconvert, aencode, aqueue_src, NULL);
renatofilho@588
   252
renatofilho@588
   253
    //TODO: apply audio rate 
renatofilho@588
   254
renatofilho@588
   255
	// ghost pad the audio bin
renatofilho@588
   256
   	apad = gst_element_get_pad (aqueue, "sink");
renatofilho@588
   257
   	gst_element_add_pad (abin, gst_ghost_pad_new("sink", apad));
renatofilho@588
   258
	gst_object_unref (apad);
renatofilho@588
   259
	
renatofilho@588
   260
   	apad = gst_element_get_pad (aqueue_src, "src");
renatofilho@588
   261
   	gst_element_add_pad (abin, gst_ghost_pad_new("src", apad));
renatofilho@588
   262
    gst_object_unref (apad);
renatofilho@588
   263
renatofilho@588
   264
    return abin;
renatofilho@588
   265
error:
renatofilho@588
   266
   	if (abin != NULL)
renatofilho@588
   267
		gst_object_unref (abin);
renatofilho@588
   268
renatofilho@588
   269
	if (aqueue != NULL)
renatofilho@588
   270
		gst_object_unref (aqueue);
renatofilho@588
   271
renatofilho@588
   272
	if (aconvert != NULL)
renatofilho@588
   273
		gst_object_unref (aconvert);
renatofilho@588
   274
renatofilho@588
   275
	if (aencode != NULL)
renatofilho@588
   276
		gst_object_unref (aencode);
renatofilho@588
   277
renatofilho@588
   278
	if (aqueue_src != NULL)
renatofilho@588
   279
		gst_object_unref (aqueue_src);
renatofilho@588
   280
renatofilho@588
   281
    if (apad != NULL)
renatofilho@588
   282
        gst_object_unref (apad);
renatofilho@588
   283
renatofilho@588
   284
    return NULL;
renatofilho@588
   285
}
renatofilho@588
   286
renatofilho@588
   287
renatofilho@588
   288
renatofilho@588
   289
renatofilho@588
   290
//queue ! videoscale ! video/x-raw-yuv,width=240,height=144 ! colorspace ! rate ! encode ! queue
renatofilho@588
   291
static GstElement*
renatofilho@588
   292
_create_video_bin (GMencoder* self, 
renatofilho@588
   293
                    const gchar* encode,
renatofilho@588
   294
                    gchar** encode_prop,
renatofilho@588
   295
                    gdouble fps,
renatofilho@588
   296
                    gint rate,
renatofilho@588
   297
                    guint width, 
renatofilho@588
   298
                    guint height)
renatofilho@588
   299
{
renatofilho@588
   300
    GstElement *vbin = NULL;
renatofilho@588
   301
    GstElement *vqueue = NULL;
renatofilho@588
   302
    GstElement* vqueue_src = NULL;
renatofilho@588
   303
    GstElement *vcolorspace = NULL;
renatofilho@588
   304
    GstElement *vencode = NULL;
renatofilho@588
   305
    GstElement *vrate = NULL;
renatofilho@588
   306
    GstPad *vpad = NULL;
renatofilho@588
   307
renatofilho@588
   308
	vbin    = gst_bin_new ("vbin");
renatofilho@588
   309
	vqueue	= gst_element_factory_make ("queue", "vqueue");
renatofilho@588
   310
	vcolorspace = gst_element_factory_make ("ffmpegcolorspace", "colorspace");
renatofilho@588
   311
	vencode = _create_element_with_prop ((encode ? encode : "ffenc_mpeg1video"), "vencode", encode_prop);
renatofilho@588
   312
    vrate   = gst_element_factory_make ("videorate", "vrate");
renatofilho@588
   313
	vqueue_src = gst_element_factory_make ("queue", "queue_src");
renatofilho@588
   314
renatofilho@588
   315
	if ((vbin == NULL) || (vqueue == NULL) || (vcolorspace == NULL) 
renatofilho@588
   316
		|| (vencode == NULL) || (vqueue_src == NULL)) {
renatofilho@588
   317
		g_warning ("Video elements not found");
renatofilho@588
   318
		goto error;
renatofilho@588
   319
	}
renatofilho@588
   320
		
renatofilho@588
   321
	gst_bin_add_many (GST_BIN (vbin), vqueue, vcolorspace, vencode, vqueue_src, NULL);
renatofilho@588
   322
renatofilho@588
   323
	
renatofilho@588
   324
    if ((width > 0) && (height > 0)) {        
renatofilho@588
   325
        //Scalling video
renatofilho@588
   326
        GstCaps *vcaps;
renatofilho@588
   327
	    GstElement *vscale  = gst_element_factory_make ("videoscale", "vscale");
renatofilho@588
   328
renatofilho@588
   329
        gst_bin_add (GST_BIN (vbin), vscale);
renatofilho@588
   330
renatofilho@588
   331
        vcaps = gst_caps_new_simple ("video/x-raw-yuv",
renatofilho@588
   332
                           "width", G_TYPE_INT, width,
renatofilho@588
   333
                           "height", G_TYPE_INT, height,                           
renatofilho@588
   334
                           NULL);
renatofilho@588
   335
renatofilho@588
   336
        gst_element_link (vqueue, vscale);
renatofilho@588
   337
					   	
renatofilho@588
   338
        if (gst_element_link_filtered (vscale, vcolorspace, vcaps) == FALSE) {
renatofilho@588
   339
            g_warning ("Fail to resize video");
renatofilho@588
   340
            gst_object_unref (vcaps);
renatofilho@588
   341
            gst_object_unref (vscale);
renatofilho@588
   342
            goto error;
renatofilho@588
   343
        }
renatofilho@588
   344
        gst_caps_unref (vcaps);
renatofilho@588
   345
    } else {
renatofilho@588
   346
        gst_element_link (vqueue, vcolorspace);
renatofilho@588
   347
    }
renatofilho@588
   348
renatofilho@588
   349
    if (fps > 0) {
renatofilho@588
   350
        //Changing the video fps
renatofilho@588
   351
        GstCaps *vcaps;
renatofilho@588
   352
renatofilho@588
   353
        gst_bin_add (GST_BIN (vbin), vrate);
renatofilho@588
   354
renatofilho@588
   355
    	if (gst_element_link (vcolorspace, vrate) == FALSE) {
renatofilho@588
   356
	        g_warning ("Fail to link video elements");
renatofilho@588
   357
	        goto error;
renatofilho@588
   358
    	}
renatofilho@588
   359
renatofilho@588
   360
    	vcaps = gst_caps_new_simple ("video/x-raw-yuv",
renatofilho@588
   361
					   "framerate", GST_TYPE_FRACTION, (int) (fps * 1000), 1000, NULL);
renatofilho@588
   362
renatofilho@588
   363
        if (gst_element_link_filtered (vrate, vencode, vcaps) == FALSE) { 
renatofilho@588
   364
           g_warning ("Fail to link vrate with vencode.");
renatofilho@588
   365
           goto error;
renatofilho@588
   366
        }
renatofilho@588
   367
        gst_caps_unref (vcaps);
renatofilho@588
   368
    } else {
renatofilho@588
   369
        if (gst_element_link (vcolorspace, vencode) == FALSE) {
renatofilho@588
   370
            g_warning ("Fail to link colorspace and video encode element.");
renatofilho@588
   371
            goto error;
renatofilho@588
   372
        }
renatofilho@588
   373
    }
renatofilho@588
   374
renatofilho@588
   375
    
renatofilho@588
   376
    gst_element_link (vencode, vqueue_src);
renatofilho@588
   377
renatofilho@588
   378
	// ghost pad the video  bin
renatofilho@588
   379
   	vpad = gst_element_get_pad (vqueue, "sink");
renatofilho@588
   380
   	gst_element_add_pad (vbin, gst_ghost_pad_new ("sink", vpad));	
renatofilho@588
   381
	gst_object_unref (vpad);
renatofilho@588
   382
	
renatofilho@588
   383
   	vpad = gst_element_get_pad (vqueue_src, "src");
renatofilho@588
   384
   	gst_element_add_pad (vbin, gst_ghost_pad_new ("src", vpad));	
renatofilho@588
   385
	gst_object_unref (vpad);
renatofilho@588
   386
renatofilho@588
   387
    return vbin;
renatofilho@588
   388
renatofilho@588
   389
error:
renatofilho@588
   390
    if (vpad != NULL)
renatofilho@588
   391
        gst_object_unref (vpad);
renatofilho@588
   392
renatofilho@588
   393
	if (vbin != NULL)
renatofilho@588
   394
		gst_object_unref (vbin);
renatofilho@588
   395
renatofilho@588
   396
	if (vqueue != NULL)
renatofilho@588
   397
		gst_object_unref (vqueue);
renatofilho@588
   398
renatofilho@588
   399
	if (vencode != NULL)
renatofilho@588
   400
		gst_object_unref (vencode);
renatofilho@588
   401
renatofilho@588
   402
	if (vqueue_src != NULL)
renatofilho@588
   403
		gst_object_unref (vqueue_src);
renatofilho@588
   404
renatofilho@588
   405
    if (vcolorspace != NULL)
renatofilho@588
   406
        gst_object_unref (vcolorspace);
renatofilho@588
   407
renatofilho@588
   408
    return NULL;
renatofilho@588
   409
}
renatofilho@588
   410
renatofilho@588
   411
renatofilho@588
   412
gboolean
renatofilho@588
   413
g_mencoder_setup_stream (GMencoder *self, 
renatofilho@588
   414
                         const gchar* uri, 
renatofilho@588
   415
                         const gchar* video_encode,
renatofilho@588
   416
                         gchar** video_encode_prop,
renatofilho@588
   417
                         gdouble video_fps,
renatofilho@588
   418
                         gdouble video_rate,
renatofilho@588
   419
                         guint video_width, 
renatofilho@588
   420
                         guint video_height,
renatofilho@588
   421
                         const gchar* audio_encode,
renatofilho@588
   422
                         gchar** audio_encode_prop,
renatofilho@588
   423
                         guint audio_rate,
renatofilho@588
   424
                         const gchar* sink_name,
renatofilho@588
   425
                         gchar** sink_prop)
renatofilho@588
   426
{
renatofilho@588
   427
	GstBus *bus = NULL;
renatofilho@588
   428
	GstElement *pipe = NULL;
renatofilho@588
   429
	GstElement *fdsink = NULL;
renatofilho@588
   430
    GstElement *mux = NULL;
renatofilho@588
   431
    GstElement *decode = NULL;
renatofilho@588
   432
	GstElement *src = NULL;
renatofilho@588
   433
    GstElement *abin = NULL;
renatofilho@588
   434
    GstElement *vbin = NULL;
renatofilho@588
   435
    GstPad *aux_pad = NULL;
renatofilho@588
   436
    GstPad *mux_pad = NULL;
renatofilho@588
   437
renatofilho@588
   438
	GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
renatofilho@588
   439
renatofilho@588
   440
	pipe = gst_pipeline_new ("pipe");
renatofilho@588
   441
	src = gst_element_make_from_uri (GST_URI_SRC, uri, "src");
renatofilho@588
   442
	if (src == NULL) 
renatofilho@588
   443
		goto error;
renatofilho@588
   444
renatofilho@588
   445
	decode = gst_element_factory_make ("decodebin2", "decode");
renatofilho@588
   446
	if (decode == NULL) 
renatofilho@588
   447
		goto error;
renatofilho@588
   448
renatofilho@588
   449
    mux = gst_element_factory_make ("ffmux_mpeg", "mux");
renatofilho@588
   450
    if (mux == NULL)
renatofilho@588
   451
        goto error;
renatofilho@588
   452
renatofilho@588
   453
    fdsink = _create_element_with_prop (sink_name, "sink", sink_prop);
renatofilho@588
   454
    if (fdsink == NULL)
renatofilho@588
   455
        goto error;
renatofilho@588
   456
renatofilho@588
   457
    abin = _create_audio_bin (self, audio_encode, audio_encode_prop, audio_rate);
renatofilho@588
   458
    if (abin == NULL)
renatofilho@588
   459
        goto error;
renatofilho@588
   460
renatofilho@588
   461
    vbin = _create_video_bin (self, video_encode, video_encode_prop, video_fps, video_rate, video_width, video_height);
renatofilho@588
   462
    if (vbin == NULL)
renatofilho@588
   463
        goto error;
renatofilho@588
   464
renatofilho@588
   465
	// Finish Pipe
renatofilho@588
   466
    gst_bin_add_many (GST_BIN (pipe), src, decode, abin, vbin, mux, fdsink, NULL);
renatofilho@588
   467
	gst_element_link (src, decode);
renatofilho@588
   468
renatofilho@588
   469
    //Link bins with mux
renatofilho@588
   470
    aux_pad = gst_element_get_pad (abin, "src");
renatofilho@588
   471
    mux_pad = gst_element_get_pad (mux, "audio_0");
renatofilho@588
   472
    GstPadLinkReturn ret = gst_pad_link (aux_pad, mux_pad);
renatofilho@588
   473
    if (ret != GST_PAD_LINK_OK) {
renatofilho@588
   474
        g_warning ("Fail link audio and mux: %d", ret);
renatofilho@588
   475
        goto error;
renatofilho@588
   476
   
renatofilho@588
   477
    }
renatofilho@588
   478
	gst_object_unref (aux_pad);
renatofilho@588
   479
    gst_object_unref (mux_pad);
renatofilho@588
   480
renatofilho@588
   481
    aux_pad = gst_element_get_pad (vbin, "src");
renatofilho@588
   482
    mux_pad = gst_element_get_pad (mux, "video_0");
renatofilho@588
   483
    ret = gst_pad_link (aux_pad, mux_pad);
renatofilho@588
   484
    if (ret != GST_PAD_LINK_OK) {
renatofilho@588
   485
        g_warning ("Fail link video and mux: %d", ret);
renatofilho@588
   486
        goto error;
renatofilho@588
   487
    }
renatofilho@588
   488
    gst_object_unref (aux_pad);
renatofilho@588
   489
    gst_object_unref (mux_pad);
renatofilho@588
   490
    aux_pad = NULL;
renatofilho@588
   491
    mux_pad = NULL;
renatofilho@588
   492
renatofilho@588
   493
    //Link mux with sink
renatofilho@588
   494
    gst_element_link (mux, fdsink);
renatofilho@588
   495
renatofilho@588
   496
	g_signal_connect (G_OBJECT (decode), 
renatofilho@588
   497
				"new-decoded-pad",
renatofilho@588
   498
				G_CALLBACK (_decodebin_new_pad_cb),
renatofilho@588
   499
				self);
renatofilho@588
   500
	
renatofilho@588
   501
	g_signal_connect (G_OBJECT (decode),
renatofilho@588
   502
				"unknown-type",
renatofilho@588
   503
				G_CALLBACK (_decodebin_unknown_type_cb),
renatofilho@588
   504
				self);
renatofilho@588
   505
renatofilho@588
   506
renatofilho@588
   507
	bus = gst_pipeline_get_bus (GST_PIPELINE (pipe));
renatofilho@588
   508
	gst_bus_add_watch (bus, _pipeline_bus_cb, self);
renatofilho@588
   509
	gst_object_unref (bus);
renatofilho@588
   510
renatofilho@588
   511
renatofilho@588
   512
	priv->pipe = pipe;
renatofilho@588
   513
	priv->abin = abin;
renatofilho@588
   514
	priv->vbin = vbin;
renatofilho@588
   515
	priv->sink = fdsink;
renatofilho@588
   516
	priv->ready = FALSE;
renatofilho@588
   517
	
renatofilho@588
   518
	gst_element_set_state (pipe, GST_STATE_PAUSED);	   	
renatofilho@588
   519
	return  TRUE;
renatofilho@588
   520
	
renatofilho@588
   521
error:
renatofilho@588
   522
	g_warning ("Invalid uri");
renatofilho@588
   523
renatofilho@588
   524
	if (pipe != NULL) {
renatofilho@588
   525
		gst_object_unref (pipe);
renatofilho@588
   526
    }
renatofilho@588
   527
renatofilho@588
   528
	if (src != NULL) {
renatofilho@588
   529
		gst_object_unref (src);
renatofilho@588
   530
    }
renatofilho@588
   531
renatofilho@588
   532
    if (mux != NULL) {
renatofilho@588
   533
        gst_object_unref (mux);
renatofilho@588
   534
    }
renatofilho@588
   535
renatofilho@588
   536
    if (mux_pad != NULL) {
renatofilho@588
   537
        gst_object_unref (mux_pad);
renatofilho@588
   538
    }
renatofilho@588
   539
renatofilho@588
   540
    if (aux_pad != NULL) {
renatofilho@588
   541
        gst_object_unref (mux_pad);
renatofilho@588
   542
    }
renatofilho@588
   543
renatofilho@588
   544
	if (fdsink != NULL) {
renatofilho@588
   545
		gst_object_unref (fdsink);
renatofilho@588
   546
    }
renatofilho@588
   547
renatofilho@588
   548
    if (abin != NULL) {
renatofilho@588
   549
        gst_object_unref (abin);
renatofilho@588
   550
    }
renatofilho@588
   551
renatofilho@588
   552
    if (vbin != NULL) {
renatofilho@588
   553
        gst_object_unref (vbin);
renatofilho@588
   554
    }
renatofilho@588
   555
renatofilho@588
   556
	return FALSE;
renatofilho@588
   557
}
renatofilho@588
   558
renatofilho@588
   559
gboolean 
renatofilho@588
   560
g_mencoder_play_stream (GMencoder *self)
renatofilho@588
   561
{
renatofilho@588
   562
    GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
renatofilho@588
   563
renatofilho@588
   564
    g_return_val_if_fail (priv->ready == TRUE, FALSE);
renatofilho@588
   565
    
renatofilho@588
   566
    if (gst_element_set_state (priv->pipe, GST_STATE_PLAYING) != GST_STATE_CHANGE_FAILURE) {
renatofilho@588
   567
			g_debug ("PLAYING");
renatofilho@588
   568
			return TRUE;
renatofilho@588
   569
	}
renatofilho@588
   570
	return FALSE;
renatofilho@588
   571
}
renatofilho@588
   572
renatofilho@588
   573
gboolean
renatofilho@588
   574
g_mencoder_pause_stream (GMencoder *self)
renatofilho@588
   575
{
renatofilho@588
   576
    GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
renatofilho@588
   577
renatofilho@588
   578
    g_return_val_if_fail (priv->ready == TRUE, FALSE);
renatofilho@588
   579
    
renatofilho@588
   580
    if (gst_element_set_state (priv->pipe, GST_STATE_PAUSED) != GST_STATE_CHANGE_FAILURE) {
renatofilho@588
   581
			g_debug ("PAUSED");
renatofilho@588
   582
			return TRUE;
renatofilho@588
   583
	}
renatofilho@588
   584
	return FALSE;
renatofilho@588
   585
}
renatofilho@588
   586
renatofilho@588
   587
void
renatofilho@588
   588
g_mencoder_close_stream (GMencoder *self)
renatofilho@588
   589
{
renatofilho@588
   590
renatofilho@588
   591
    GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
renatofilho@588
   592
renatofilho@588
   593
    g_return_if_fail (priv->ready == TRUE);
renatofilho@588
   594
    
renatofilho@588
   595
    gst_element_set_state (priv->pipe, GST_STATE_NULL);
renatofilho@588
   596
    gst_object_unref (priv->pipe);
renatofilho@588
   597
    priv->pipe = NULL;
renatofilho@588
   598
    priv->abin = NULL;
renatofilho@588
   599
    priv->vbin = NULL;
renatofilho@588
   600
    priv->sink = NULL;
renatofilho@588
   601
    priv->ready = FALSE;
renatofilho@588
   602
}
renatofilho@588
   603
renatofilho@588
   604
static gboolean
renatofilho@588
   605
_pipeline_bus_cb (GstBus     *bus,
renatofilho@588
   606
		  GstMessage *msg,
renatofilho@588
   607
		  gpointer    user_data)
renatofilho@588
   608
{
renatofilho@588
   609
	switch (GST_MESSAGE_TYPE (msg)) 
renatofilho@588
   610
	{
renatofilho@588
   611
		case GST_MESSAGE_STATE_CHANGED:
renatofilho@588
   612
		{
renatofilho@588
   613
			GstState oldstate;
renatofilho@588
   614
			GstState newstate;
renatofilho@588
   615
			GstState pendingstate;
renatofilho@588
   616
renatofilho@588
   617
			GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (user_data);
renatofilho@588
   618
renatofilho@588
   619
			gst_message_parse_state_changed (msg, &oldstate,
renatofilho@588
   620
				&newstate, &pendingstate);
renatofilho@588
   621
renatofilho@588
   622
            if (pendingstate != GST_STATE_VOID_PENDING)
renatofilho@588
   623
                break;
renatofilho@588
   624
renatofilho@588
   625
            if ((oldstate == GST_STATE_READY) && 
renatofilho@588
   626
                (newstate == GST_STATE_PAUSED)) {
renatofilho@588
   627
                    if (priv->ready) 
renatofilho@588
   628
                        g_signal_emit (user_data, g_mencoder_signals[PAUSED], 0);
renatofilho@588
   629
                    else {
renatofilho@588
   630
                        priv->ready = TRUE;
renatofilho@588
   631
                        g_signal_emit (user_data, g_mencoder_signals[READY], 0);
renatofilho@588
   632
                    }
renatofilho@588
   633
            } else if ((oldstate == GST_STATE_PAUSED) &&
renatofilho@588
   634
                       (newstate == GST_STATE_PLAYING)) {
renatofilho@588
   635
                        g_signal_emit (user_data, g_mencoder_signals[PLAYING], 0);
renatofilho@588
   636
            } else if ((oldstate == GST_STATE_READY) &&
renatofilho@588
   637
                       (newstate == GST_STATE_NULL)) {
renatofilho@588
   638
                        g_signal_emit (user_data, g_mencoder_signals[STOPED], 0);
renatofilho@588
   639
            }			
renatofilho@588
   640
            break;
renatofilho@588
   641
		}
renatofilho@588
   642
		case GST_MESSAGE_ERROR: 
renatofilho@588
   643
		{
renatofilho@588
   644
		    GError *error;
renatofilho@588
   645
		    gchar *debug;
renatofilho@588
   646
		    gchar *err_str;
renatofilho@588
   647
		    
renatofilho@588
   648
		    gst_message_parse_error (msg, &error, &debug);
renatofilho@588
   649
		    err_str = g_strdup_printf ("Error [%d] %s (%s)", error->code,
renatofilho@588
   650
		        error->message,
renatofilho@588
   651
		        debug);
renatofilho@588
   652
		    g_signal_emit (user_data, g_mencoder_signals[ERROR], 0, err_str);
renatofilho@588
   653
		    g_free (err_str);
renatofilho@588
   654
		    g_clear_error (&error);
renatofilho@588
   655
		    g_free (debug);
renatofilho@588
   656
		    break;
renatofilho@588
   657
		}
renatofilho@588
   658
		
renatofilho@588
   659
		case GST_MESSAGE_EOS:
renatofilho@588
   660
		    g_signal_emit (user_data, g_mencoder_signals[EOS], 0);
renatofilho@588
   661
		    break;		
renatofilho@588
   662
		default:
renatofilho@588
   663
			break;
renatofilho@588
   664
	}
renatofilho@588
   665
	return TRUE;
renatofilho@588
   666
}
renatofilho@588
   667
renatofilho@588
   668
static void 
renatofilho@588
   669
_decodebin_new_pad_cb (GstElement* object,
renatofilho@588
   670
                       GstPad* pad,
renatofilho@588
   671
                       gboolean flag,
renatofilho@588
   672
                       gpointer user_data)
renatofilho@588
   673
{
renatofilho@588
   674
	GstCaps *caps;
renatofilho@588
   675
	gchar *str_caps = NULL;
renatofilho@588
   676
    GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (user_data);
renatofilho@588
   677
renatofilho@588
   678
	caps = gst_pad_get_caps (pad);
renatofilho@588
   679
	str_caps = gst_caps_to_string (caps);
renatofilho@588
   680
    g_debug ("CAPS : %s", str_caps);
renatofilho@588
   681
renatofilho@588
   682
	if (strstr (str_caps, "audio") != NULL) {
renatofilho@588
   683
		GstPad *apad = gst_element_get_pad (priv->abin, "sink");
renatofilho@588
   684
		gst_pad_link (pad, apad);
renatofilho@588
   685
		gst_object_unref (apad);
renatofilho@588
   686
	} else if (strstr (str_caps, "video") != NULL) {
renatofilho@588
   687
		GstPad *vpad = gst_element_get_pad (priv->vbin, "sink");
renatofilho@588
   688
		gst_pad_link (pad, vpad);
renatofilho@588
   689
		gst_object_unref (vpad);
renatofilho@588
   690
	} else {
renatofilho@588
   691
		g_warning ("invalid caps %s", str_caps);
renatofilho@588
   692
	}
renatofilho@588
   693
renatofilho@588
   694
	g_free (str_caps);
renatofilho@588
   695
	gst_caps_unref (caps);
renatofilho@588
   696
}
renatofilho@588
   697
renatofilho@588
   698
static void 
renatofilho@588
   699
_decodebin_unknown_type_cb (GstElement* object,
renatofilho@588
   700
                            GstPad* pad,
renatofilho@588
   701
                            GstCaps* caps,
renatofilho@588
   702
                            gpointer user_data)
renatofilho@588
   703
{
renatofilho@588
   704
    g_warning  ("Unknown Type");
renatofilho@588
   705
}