1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/gmyth-stream/gmemcoder/src/gmencoder.c Wed Apr 25 15:53:19 2007 +0100
1.3 @@ -0,0 +1,705 @@
1.4 +#ifdef HAVE_CONFIG_H
1.5 +#include "config.h"
1.6 +#endif
1.7 +
1.8 +#include <glib.h>
1.9 +#include <gst/gst.h>
1.10 +#include <string.h>
1.11 +
1.12 +#include "gmencoder.h"
1.13 +
1.14 +#define G_MENCODER_GET_PRIVATE(obj) \
1.15 + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), G_TYPE_MENCODER, GMencoderPrivate))
1.16 +
1.17 +
1.18 +typedef struct _GMencoderPrivate GMencoderPrivate;
1.19 +
1.20 +struct _GMencoderPrivate
1.21 +{
1.22 + GstElement *pipe;
1.23 + GstElement *abin;
1.24 + GstElement *vbin;
1.25 + GstElement *sink;
1.26 + gboolean ready;
1.27 +};
1.28 +
1.29 +enum {
1.30 + READY,
1.31 + PAUSED,
1.32 + PLAYING,
1.33 + STOPED,
1.34 + EOS,
1.35 + ERROR,
1.36 + LAST_SIGNAL
1.37 +};
1.38 +
1.39 +static void g_mencoder_class_init (GMencoderClass *klass);
1.40 +static void g_mencoder_init (GMencoder *object);
1.41 +static void g_mencoder_dispose (GObject *object);
1.42 +static void g_mencoder_finalize (GObject *object);
1.43 +static GstElement*
1.44 + _create_audio_bin (GMencoder *self,
1.45 + const gchar* encode,
1.46 + gchar** encode_prop,
1.47 + gint rate);
1.48 +static GstElement*
1.49 + _create_video_bin (GMencoder* self,
1.50 + const gchar* encode,
1.51 + gchar** encode_prop,
1.52 + gdouble fps,
1.53 + gint rate,
1.54 + guint width,
1.55 + guint height);
1.56 +
1.57 +static gboolean
1.58 + _pipeline_bus_cb (GstBus *bus,
1.59 + GstMessage *msg,
1.60 + gpointer user_data);
1.61 +static void _decodebin_new_pad_cb (GstElement* object,
1.62 + GstPad* pad,
1.63 + gboolean flag,
1.64 + gpointer user_data);
1.65 +static void _decodebin_unknown_type_cb (GstElement* object,
1.66 + GstPad* pad,
1.67 + GstCaps* caps,
1.68 + gpointer user_data);
1.69 +
1.70 +
1.71 +static guint g_mencoder_signals[LAST_SIGNAL] = { 0 };
1.72 +
1.73 +G_DEFINE_TYPE(GMencoder, g_mencoder, G_TYPE_OBJECT)
1.74 +
1.75 +static void
1.76 +g_mencoder_class_init (GMencoderClass *klass)
1.77 +{
1.78 + GObjectClass *object_class;
1.79 +
1.80 + object_class = (GObjectClass *) klass;
1.81 +
1.82 + g_type_class_add_private (klass, sizeof (GMencoderPrivate));
1.83 +
1.84 + object_class->dispose = g_mencoder_dispose;
1.85 + object_class->finalize = g_mencoder_finalize;
1.86 +
1.87 + g_mencoder_signals[READY] =
1.88 + g_signal_new ("ready",
1.89 + G_OBJECT_CLASS_TYPE (object_class),
1.90 + G_SIGNAL_RUN_FIRST,
1.91 + 0, NULL, NULL,
1.92 + g_cclosure_marshal_VOID__VOID,
1.93 + G_TYPE_NONE, 0);
1.94 +
1.95 + g_mencoder_signals[PAUSED] =
1.96 + g_signal_new ("paused",
1.97 + G_OBJECT_CLASS_TYPE (object_class),
1.98 + G_SIGNAL_RUN_FIRST,
1.99 + 0, NULL, NULL,
1.100 + g_cclosure_marshal_VOID__VOID,
1.101 + G_TYPE_NONE, 0);
1.102 +
1.103 + g_mencoder_signals[PLAYING] =
1.104 + g_signal_new ("playing",
1.105 + G_OBJECT_CLASS_TYPE (object_class),
1.106 + G_SIGNAL_RUN_FIRST,
1.107 + 0, NULL, NULL,
1.108 + g_cclosure_marshal_VOID__VOID,
1.109 + G_TYPE_NONE, 0);
1.110 +
1.111 + g_mencoder_signals[STOPED] =
1.112 + g_signal_new ("stoped",
1.113 + G_OBJECT_CLASS_TYPE (object_class),
1.114 + G_SIGNAL_RUN_FIRST,
1.115 + 0, NULL, NULL,
1.116 + g_cclosure_marshal_VOID__VOID,
1.117 + G_TYPE_NONE, 0);
1.118 +
1.119 + g_mencoder_signals[EOS] =
1.120 + g_signal_new ("eos",
1.121 + G_OBJECT_CLASS_TYPE (object_class),
1.122 + G_SIGNAL_RUN_FIRST,
1.123 + 0, NULL, NULL,
1.124 + g_cclosure_marshal_VOID__VOID,
1.125 + G_TYPE_NONE, 0);
1.126 +
1.127 +
1.128 + g_mencoder_signals[ERROR] =
1.129 + g_signal_new ("error",
1.130 + G_OBJECT_CLASS_TYPE (object_class),
1.131 + G_SIGNAL_RUN_FIRST,
1.132 + 0, NULL, NULL,
1.133 + g_cclosure_marshal_VOID__STRING,
1.134 + G_TYPE_NONE, 1, G_TYPE_STRING);
1.135 +}
1.136 +
1.137 +static void
1.138 +g_mencoder_init (GMencoder *self)
1.139 +{
1.140 +}
1.141 +
1.142 +static void
1.143 +g_mencoder_dispose (GObject *object)
1.144 +{
1.145 +}
1.146 +
1.147 +static void
1.148 +g_mencoder_finalize (GObject *object)
1.149 +{
1.150 + g_mencoder_close_stream (G_MENCODER (object));
1.151 +}
1.152 +
1.153 +GMencoder*
1.154 +g_mencoder_new (void)
1.155 +{
1.156 + return g_object_new (G_TYPE_MENCODER, NULL);
1.157 +}
1.158 +
1.159 +static void
1.160 +_obj_set_prop (GObject *obj,
1.161 + const gchar *prop_name,
1.162 + const gchar *prop_val)
1.163 +{
1.164 + GValue p = {0};
1.165 + GValue v = {0};
1.166 + GParamSpec *s = NULL;
1.167 + GObjectClass *k = G_OBJECT_GET_CLASS (obj);
1.168 +
1.169 +
1.170 + g_value_init (&v, G_TYPE_STRING);
1.171 + g_value_set_string (&v, prop_val);
1.172 +
1.173 + g_debug ("PROP [%s] VAL [%s]", prop_name, prop_val);
1.174 +
1.175 + s = g_object_class_find_property (k, prop_name);
1.176 + if (s == NULL) {
1.177 + g_print ("Invalid property name: %s\n", prop_name);
1.178 + return;
1.179 + }
1.180 +
1.181 + g_value_init (&p, s->value_type);
1.182 + switch (s->value_type)
1.183 + {
1.184 + case G_TYPE_INT:
1.185 + g_value_set_int (&p, atoi (prop_val));
1.186 + break;
1.187 + case G_TYPE_STRING:
1.188 + g_value_set_string (&p, prop_val);
1.189 + break;
1.190 + default:
1.191 + return;
1.192 + }
1.193 +
1.194 + g_object_set_property (obj, prop_name, &p);
1.195 + g_value_unset (&v);
1.196 + g_value_unset (&p);
1.197 +}
1.198 +
1.199 +static GstElement*
1.200 +_create_element_with_prop (const gchar* factory_name,
1.201 + const gchar* element_name,
1.202 + gchar** prop)
1.203 +{
1.204 + GstElement *ret;
1.205 + int i;
1.206 +
1.207 +
1.208 + g_debug ("SET OBJ [%s]", factory_name);
1.209 + ret = gst_element_factory_make (factory_name, element_name);
1.210 + if (ret == NULL)
1.211 + return NULL;
1.212 +
1.213 + if (prop != NULL) {
1.214 + for (i=0; i < g_strv_length (prop); i++) {
1.215 + char** v = g_strsplit(prop[i], "=", 2);
1.216 + if (g_strv_length (v) == 2) {
1.217 + _obj_set_prop (G_OBJECT (ret), v[0], v[1]);
1.218 + }
1.219 + g_strfreev (v);
1.220 + }
1.221 + }
1.222 +
1.223 + return ret;
1.224 +
1.225 +}
1.226 +
1.227 +static GstElement*
1.228 +_create_audio_bin (GMencoder* self,
1.229 + const gchar* encode,
1.230 + gchar** encode_prop,
1.231 + gint rate)
1.232 +{
1.233 + GstElement *abin = NULL;
1.234 + GstElement *aqueue = NULL;
1.235 + GstElement *aconvert = NULL;
1.236 + GstElement *aencode = NULL;
1.237 + GstElement *aqueue_src = NULL;
1.238 + GstPad *apad = NULL;
1.239 +
1.240 + //audio/x-raw-int ! queue ! audioconvert ! faac ! rtpmp4gpay ! udpsink name=upd_audio host=224.0.0.1 port=5002
1.241 + abin = gst_bin_new ("abin");
1.242 + aqueue = gst_element_factory_make ("queue", "aqueue");
1.243 + aconvert= gst_element_factory_make ("audioconvert", "aconvert");
1.244 + aencode = _create_element_with_prop ((encode ? encode : "lame"), "aencode", encode_prop);
1.245 + aqueue_src= gst_element_factory_make ("queue", "aqueue_src");
1.246 +
1.247 + if ((abin == NULL) || (aqueue == NULL) || (aconvert == NULL)
1.248 + || (aencode == NULL) || (aqueue_src == NULL)) {
1.249 + g_warning ("Audio elements not found");
1.250 + goto error;
1.251 + }
1.252 +
1.253 + gst_bin_add_many (GST_BIN (abin), aqueue, aconvert, aencode, aqueue_src, NULL);
1.254 + gst_element_link_many (aqueue, aconvert, aencode, aqueue_src, NULL);
1.255 +
1.256 + //TODO: apply audio rate
1.257 +
1.258 + // ghost pad the audio bin
1.259 + apad = gst_element_get_pad (aqueue, "sink");
1.260 + gst_element_add_pad (abin, gst_ghost_pad_new("sink", apad));
1.261 + gst_object_unref (apad);
1.262 +
1.263 + apad = gst_element_get_pad (aqueue_src, "src");
1.264 + gst_element_add_pad (abin, gst_ghost_pad_new("src", apad));
1.265 + gst_object_unref (apad);
1.266 +
1.267 + return abin;
1.268 +error:
1.269 + if (abin != NULL)
1.270 + gst_object_unref (abin);
1.271 +
1.272 + if (aqueue != NULL)
1.273 + gst_object_unref (aqueue);
1.274 +
1.275 + if (aconvert != NULL)
1.276 + gst_object_unref (aconvert);
1.277 +
1.278 + if (aencode != NULL)
1.279 + gst_object_unref (aencode);
1.280 +
1.281 + if (aqueue_src != NULL)
1.282 + gst_object_unref (aqueue_src);
1.283 +
1.284 + if (apad != NULL)
1.285 + gst_object_unref (apad);
1.286 +
1.287 + return NULL;
1.288 +}
1.289 +
1.290 +
1.291 +
1.292 +
1.293 +//queue ! videoscale ! video/x-raw-yuv,width=240,height=144 ! colorspace ! rate ! encode ! queue
1.294 +static GstElement*
1.295 +_create_video_bin (GMencoder* self,
1.296 + const gchar* encode,
1.297 + gchar** encode_prop,
1.298 + gdouble fps,
1.299 + gint rate,
1.300 + guint width,
1.301 + guint height)
1.302 +{
1.303 + GstElement *vbin = NULL;
1.304 + GstElement *vqueue = NULL;
1.305 + GstElement* vqueue_src = NULL;
1.306 + GstElement *vcolorspace = NULL;
1.307 + GstElement *vencode = NULL;
1.308 + GstElement *vrate = NULL;
1.309 + GstPad *vpad = NULL;
1.310 +
1.311 + vbin = gst_bin_new ("vbin");
1.312 + vqueue = gst_element_factory_make ("queue", "vqueue");
1.313 + vcolorspace = gst_element_factory_make ("ffmpegcolorspace", "colorspace");
1.314 + vencode = _create_element_with_prop ((encode ? encode : "ffenc_mpeg1video"), "vencode", encode_prop);
1.315 + vrate = gst_element_factory_make ("videorate", "vrate");
1.316 + vqueue_src = gst_element_factory_make ("queue", "queue_src");
1.317 +
1.318 + if ((vbin == NULL) || (vqueue == NULL) || (vcolorspace == NULL)
1.319 + || (vencode == NULL) || (vqueue_src == NULL)) {
1.320 + g_warning ("Video elements not found");
1.321 + goto error;
1.322 + }
1.323 +
1.324 + gst_bin_add_many (GST_BIN (vbin), vqueue, vcolorspace, vencode, vqueue_src, NULL);
1.325 +
1.326 +
1.327 + if ((width > 0) && (height > 0)) {
1.328 + //Scalling video
1.329 + GstCaps *vcaps;
1.330 + GstElement *vscale = gst_element_factory_make ("videoscale", "vscale");
1.331 +
1.332 + gst_bin_add (GST_BIN (vbin), vscale);
1.333 +
1.334 + vcaps = gst_caps_new_simple ("video/x-raw-yuv",
1.335 + "width", G_TYPE_INT, width,
1.336 + "height", G_TYPE_INT, height,
1.337 + NULL);
1.338 +
1.339 + gst_element_link (vqueue, vscale);
1.340 +
1.341 + if (gst_element_link_filtered (vscale, vcolorspace, vcaps) == FALSE) {
1.342 + g_warning ("Fail to resize video");
1.343 + gst_object_unref (vcaps);
1.344 + gst_object_unref (vscale);
1.345 + goto error;
1.346 + }
1.347 + gst_caps_unref (vcaps);
1.348 + } else {
1.349 + gst_element_link (vqueue, vcolorspace);
1.350 + }
1.351 +
1.352 + if (fps > 0) {
1.353 + //Changing the video fps
1.354 + GstCaps *vcaps;
1.355 +
1.356 + gst_bin_add (GST_BIN (vbin), vrate);
1.357 +
1.358 + if (gst_element_link (vcolorspace, vrate) == FALSE) {
1.359 + g_warning ("Fail to link video elements");
1.360 + goto error;
1.361 + }
1.362 +
1.363 + vcaps = gst_caps_new_simple ("video/x-raw-yuv",
1.364 + "framerate", GST_TYPE_FRACTION, (int) (fps * 1000), 1000, NULL);
1.365 +
1.366 + if (gst_element_link_filtered (vrate, vencode, vcaps) == FALSE) {
1.367 + g_warning ("Fail to link vrate with vencode.");
1.368 + goto error;
1.369 + }
1.370 + gst_caps_unref (vcaps);
1.371 + } else {
1.372 + if (gst_element_link (vcolorspace, vencode) == FALSE) {
1.373 + g_warning ("Fail to link colorspace and video encode element.");
1.374 + goto error;
1.375 + }
1.376 + }
1.377 +
1.378 +
1.379 + gst_element_link (vencode, vqueue_src);
1.380 +
1.381 + // ghost pad the video bin
1.382 + vpad = gst_element_get_pad (vqueue, "sink");
1.383 + gst_element_add_pad (vbin, gst_ghost_pad_new ("sink", vpad));
1.384 + gst_object_unref (vpad);
1.385 +
1.386 + vpad = gst_element_get_pad (vqueue_src, "src");
1.387 + gst_element_add_pad (vbin, gst_ghost_pad_new ("src", vpad));
1.388 + gst_object_unref (vpad);
1.389 +
1.390 + return vbin;
1.391 +
1.392 +error:
1.393 + if (vpad != NULL)
1.394 + gst_object_unref (vpad);
1.395 +
1.396 + if (vbin != NULL)
1.397 + gst_object_unref (vbin);
1.398 +
1.399 + if (vqueue != NULL)
1.400 + gst_object_unref (vqueue);
1.401 +
1.402 + if (vencode != NULL)
1.403 + gst_object_unref (vencode);
1.404 +
1.405 + if (vqueue_src != NULL)
1.406 + gst_object_unref (vqueue_src);
1.407 +
1.408 + if (vcolorspace != NULL)
1.409 + gst_object_unref (vcolorspace);
1.410 +
1.411 + return NULL;
1.412 +}
1.413 +
1.414 +
1.415 +gboolean
1.416 +g_mencoder_setup_stream (GMencoder *self,
1.417 + const gchar* uri,
1.418 + const gchar* video_encode,
1.419 + gchar** video_encode_prop,
1.420 + gdouble video_fps,
1.421 + gdouble video_rate,
1.422 + guint video_width,
1.423 + guint video_height,
1.424 + const gchar* audio_encode,
1.425 + gchar** audio_encode_prop,
1.426 + guint audio_rate,
1.427 + const gchar* sink_name,
1.428 + gchar** sink_prop)
1.429 +{
1.430 + GstBus *bus = NULL;
1.431 + GstElement *pipe = NULL;
1.432 + GstElement *fdsink = NULL;
1.433 + GstElement *mux = NULL;
1.434 + GstElement *decode = NULL;
1.435 + GstElement *src = NULL;
1.436 + GstElement *abin = NULL;
1.437 + GstElement *vbin = NULL;
1.438 + GstPad *aux_pad = NULL;
1.439 + GstPad *mux_pad = NULL;
1.440 +
1.441 + GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
1.442 +
1.443 + pipe = gst_pipeline_new ("pipe");
1.444 + src = gst_element_make_from_uri (GST_URI_SRC, uri, "src");
1.445 + if (src == NULL)
1.446 + goto error;
1.447 +
1.448 + decode = gst_element_factory_make ("decodebin2", "decode");
1.449 + if (decode == NULL)
1.450 + goto error;
1.451 +
1.452 + mux = gst_element_factory_make ("ffmux_mpeg", "mux");
1.453 + if (mux == NULL)
1.454 + goto error;
1.455 +
1.456 + fdsink = _create_element_with_prop (sink_name, "sink", sink_prop);
1.457 + if (fdsink == NULL)
1.458 + goto error;
1.459 +
1.460 + abin = _create_audio_bin (self, audio_encode, audio_encode_prop, audio_rate);
1.461 + if (abin == NULL)
1.462 + goto error;
1.463 +
1.464 + vbin = _create_video_bin (self, video_encode, video_encode_prop, video_fps, video_rate, video_width, video_height);
1.465 + if (vbin == NULL)
1.466 + goto error;
1.467 +
1.468 + // Finish Pipe
1.469 + gst_bin_add_many (GST_BIN (pipe), src, decode, abin, vbin, mux, fdsink, NULL);
1.470 + gst_element_link (src, decode);
1.471 +
1.472 + //Link bins with mux
1.473 + aux_pad = gst_element_get_pad (abin, "src");
1.474 + mux_pad = gst_element_get_pad (mux, "audio_0");
1.475 + GstPadLinkReturn ret = gst_pad_link (aux_pad, mux_pad);
1.476 + if (ret != GST_PAD_LINK_OK) {
1.477 + g_warning ("Fail link audio and mux: %d", ret);
1.478 + goto error;
1.479 +
1.480 + }
1.481 + gst_object_unref (aux_pad);
1.482 + gst_object_unref (mux_pad);
1.483 +
1.484 + aux_pad = gst_element_get_pad (vbin, "src");
1.485 + mux_pad = gst_element_get_pad (mux, "video_0");
1.486 + ret = gst_pad_link (aux_pad, mux_pad);
1.487 + if (ret != GST_PAD_LINK_OK) {
1.488 + g_warning ("Fail link video and mux: %d", ret);
1.489 + goto error;
1.490 + }
1.491 + gst_object_unref (aux_pad);
1.492 + gst_object_unref (mux_pad);
1.493 + aux_pad = NULL;
1.494 + mux_pad = NULL;
1.495 +
1.496 + //Link mux with sink
1.497 + gst_element_link (mux, fdsink);
1.498 +
1.499 + g_signal_connect (G_OBJECT (decode),
1.500 + "new-decoded-pad",
1.501 + G_CALLBACK (_decodebin_new_pad_cb),
1.502 + self);
1.503 +
1.504 + g_signal_connect (G_OBJECT (decode),
1.505 + "unknown-type",
1.506 + G_CALLBACK (_decodebin_unknown_type_cb),
1.507 + self);
1.508 +
1.509 +
1.510 + bus = gst_pipeline_get_bus (GST_PIPELINE (pipe));
1.511 + gst_bus_add_watch (bus, _pipeline_bus_cb, self);
1.512 + gst_object_unref (bus);
1.513 +
1.514 +
1.515 + priv->pipe = pipe;
1.516 + priv->abin = abin;
1.517 + priv->vbin = vbin;
1.518 + priv->sink = fdsink;
1.519 + priv->ready = FALSE;
1.520 +
1.521 + gst_element_set_state (pipe, GST_STATE_PAUSED);
1.522 + return TRUE;
1.523 +
1.524 +error:
1.525 + g_warning ("Invalid uri");
1.526 +
1.527 + if (pipe != NULL) {
1.528 + gst_object_unref (pipe);
1.529 + }
1.530 +
1.531 + if (src != NULL) {
1.532 + gst_object_unref (src);
1.533 + }
1.534 +
1.535 + if (mux != NULL) {
1.536 + gst_object_unref (mux);
1.537 + }
1.538 +
1.539 + if (mux_pad != NULL) {
1.540 + gst_object_unref (mux_pad);
1.541 + }
1.542 +
1.543 + if (aux_pad != NULL) {
1.544 + gst_object_unref (mux_pad);
1.545 + }
1.546 +
1.547 + if (fdsink != NULL) {
1.548 + gst_object_unref (fdsink);
1.549 + }
1.550 +
1.551 + if (abin != NULL) {
1.552 + gst_object_unref (abin);
1.553 + }
1.554 +
1.555 + if (vbin != NULL) {
1.556 + gst_object_unref (vbin);
1.557 + }
1.558 +
1.559 + return FALSE;
1.560 +}
1.561 +
1.562 +gboolean
1.563 +g_mencoder_play_stream (GMencoder *self)
1.564 +{
1.565 + GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
1.566 +
1.567 + g_return_val_if_fail (priv->ready == TRUE, FALSE);
1.568 +
1.569 + if (gst_element_set_state (priv->pipe, GST_STATE_PLAYING) != GST_STATE_CHANGE_FAILURE) {
1.570 + g_debug ("PLAYING");
1.571 + return TRUE;
1.572 + }
1.573 + return FALSE;
1.574 +}
1.575 +
1.576 +gboolean
1.577 +g_mencoder_pause_stream (GMencoder *self)
1.578 +{
1.579 + GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
1.580 +
1.581 + g_return_val_if_fail (priv->ready == TRUE, FALSE);
1.582 +
1.583 + if (gst_element_set_state (priv->pipe, GST_STATE_PAUSED) != GST_STATE_CHANGE_FAILURE) {
1.584 + g_debug ("PAUSED");
1.585 + return TRUE;
1.586 + }
1.587 + return FALSE;
1.588 +}
1.589 +
1.590 +void
1.591 +g_mencoder_close_stream (GMencoder *self)
1.592 +{
1.593 +
1.594 + GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
1.595 +
1.596 + g_return_if_fail (priv->ready == TRUE);
1.597 +
1.598 + gst_element_set_state (priv->pipe, GST_STATE_NULL);
1.599 + gst_object_unref (priv->pipe);
1.600 + priv->pipe = NULL;
1.601 + priv->abin = NULL;
1.602 + priv->vbin = NULL;
1.603 + priv->sink = NULL;
1.604 + priv->ready = FALSE;
1.605 +}
1.606 +
1.607 +static gboolean
1.608 +_pipeline_bus_cb (GstBus *bus,
1.609 + GstMessage *msg,
1.610 + gpointer user_data)
1.611 +{
1.612 + switch (GST_MESSAGE_TYPE (msg))
1.613 + {
1.614 + case GST_MESSAGE_STATE_CHANGED:
1.615 + {
1.616 + GstState oldstate;
1.617 + GstState newstate;
1.618 + GstState pendingstate;
1.619 +
1.620 + GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (user_data);
1.621 +
1.622 + gst_message_parse_state_changed (msg, &oldstate,
1.623 + &newstate, &pendingstate);
1.624 +
1.625 + if (pendingstate != GST_STATE_VOID_PENDING)
1.626 + break;
1.627 +
1.628 + if ((oldstate == GST_STATE_READY) &&
1.629 + (newstate == GST_STATE_PAUSED)) {
1.630 + if (priv->ready)
1.631 + g_signal_emit (user_data, g_mencoder_signals[PAUSED], 0);
1.632 + else {
1.633 + priv->ready = TRUE;
1.634 + g_signal_emit (user_data, g_mencoder_signals[READY], 0);
1.635 + }
1.636 + } else if ((oldstate == GST_STATE_PAUSED) &&
1.637 + (newstate == GST_STATE_PLAYING)) {
1.638 + g_signal_emit (user_data, g_mencoder_signals[PLAYING], 0);
1.639 + } else if ((oldstate == GST_STATE_READY) &&
1.640 + (newstate == GST_STATE_NULL)) {
1.641 + g_signal_emit (user_data, g_mencoder_signals[STOPED], 0);
1.642 + }
1.643 + break;
1.644 + }
1.645 + case GST_MESSAGE_ERROR:
1.646 + {
1.647 + GError *error;
1.648 + gchar *debug;
1.649 + gchar *err_str;
1.650 +
1.651 + gst_message_parse_error (msg, &error, &debug);
1.652 + err_str = g_strdup_printf ("Error [%d] %s (%s)", error->code,
1.653 + error->message,
1.654 + debug);
1.655 + g_signal_emit (user_data, g_mencoder_signals[ERROR], 0, err_str);
1.656 + g_free (err_str);
1.657 + g_clear_error (&error);
1.658 + g_free (debug);
1.659 + break;
1.660 + }
1.661 +
1.662 + case GST_MESSAGE_EOS:
1.663 + g_signal_emit (user_data, g_mencoder_signals[EOS], 0);
1.664 + break;
1.665 + default:
1.666 + break;
1.667 + }
1.668 + return TRUE;
1.669 +}
1.670 +
1.671 +static void
1.672 +_decodebin_new_pad_cb (GstElement* object,
1.673 + GstPad* pad,
1.674 + gboolean flag,
1.675 + gpointer user_data)
1.676 +{
1.677 + GstCaps *caps;
1.678 + gchar *str_caps = NULL;
1.679 + GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (user_data);
1.680 +
1.681 + caps = gst_pad_get_caps (pad);
1.682 + str_caps = gst_caps_to_string (caps);
1.683 + g_debug ("CAPS : %s", str_caps);
1.684 +
1.685 + if (strstr (str_caps, "audio") != NULL) {
1.686 + GstPad *apad = gst_element_get_pad (priv->abin, "sink");
1.687 + gst_pad_link (pad, apad);
1.688 + gst_object_unref (apad);
1.689 + } else if (strstr (str_caps, "video") != NULL) {
1.690 + GstPad *vpad = gst_element_get_pad (priv->vbin, "sink");
1.691 + gst_pad_link (pad, vpad);
1.692 + gst_object_unref (vpad);
1.693 + } else {
1.694 + g_warning ("invalid caps %s", str_caps);
1.695 + }
1.696 +
1.697 + g_free (str_caps);
1.698 + gst_caps_unref (caps);
1.699 +}
1.700 +
1.701 +static void
1.702 +_decodebin_unknown_type_cb (GstElement* object,
1.703 + GstPad* pad,
1.704 + GstCaps* caps,
1.705 + gpointer user_data)
1.706 +{
1.707 + g_warning ("Unknown Type");
1.708 +}