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