[svn r603] Uses Valgrind and Mudflap, to create cover tests, and make performance reports.
11 #define G_MENCODER_GET_PRIVATE(obj) \
12 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), G_TYPE_MENCODER, GMencoderPrivate))
15 typedef struct _GMencoderPrivate GMencoderPrivate;
17 struct _GMencoderPrivate
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);
41 _create_audio_bin (GMencoder *self,
46 _create_video_bin (GMencoder* self,
55 _pipeline_bus_cb (GstBus *bus,
58 static void _decodebin_new_pad_cb (GstElement* object,
62 static void _decodebin_unknown_type_cb (GstElement* object,
68 static guint g_mencoder_signals[LAST_SIGNAL] = { 0 };
70 G_DEFINE_TYPE(GMencoder, g_mencoder, G_TYPE_OBJECT)
73 g_mencoder_class_init (GMencoderClass *klass)
75 GObjectClass *object_class;
77 object_class = (GObjectClass *) klass;
79 g_type_class_add_private (klass, sizeof (GMencoderPrivate));
81 object_class->dispose = g_mencoder_dispose;
82 object_class->finalize = g_mencoder_finalize;
84 g_mencoder_signals[READY] =
85 g_signal_new ("ready",
86 G_OBJECT_CLASS_TYPE (object_class),
89 g_cclosure_marshal_VOID__VOID,
92 g_mencoder_signals[PAUSED] =
93 g_signal_new ("paused",
94 G_OBJECT_CLASS_TYPE (object_class),
97 g_cclosure_marshal_VOID__VOID,
100 g_mencoder_signals[PLAYING] =
101 g_signal_new ("playing",
102 G_OBJECT_CLASS_TYPE (object_class),
105 g_cclosure_marshal_VOID__VOID,
108 g_mencoder_signals[STOPED] =
109 g_signal_new ("stoped",
110 G_OBJECT_CLASS_TYPE (object_class),
113 g_cclosure_marshal_VOID__VOID,
116 g_mencoder_signals[EOS] =
118 G_OBJECT_CLASS_TYPE (object_class),
121 g_cclosure_marshal_VOID__VOID,
125 g_mencoder_signals[ERROR] =
126 g_signal_new ("error",
127 G_OBJECT_CLASS_TYPE (object_class),
130 g_cclosure_marshal_VOID__STRING,
131 G_TYPE_NONE, 1, G_TYPE_STRING);
135 g_mencoder_init (GMencoder *self)
140 g_mencoder_dispose (GObject *object)
145 g_mencoder_finalize (GObject *object)
147 g_mencoder_close_stream (G_MENCODER (object));
151 g_mencoder_new (void)
153 return g_object_new (G_TYPE_MENCODER, NULL);
157 _obj_set_prop (GObject *obj,
158 const gchar *prop_name,
159 const gchar *prop_val)
163 GParamSpec *s = NULL;
164 GObjectClass *k = G_OBJECT_GET_CLASS (obj);
167 g_value_init (&v, G_TYPE_STRING);
168 g_value_set_string (&v, prop_val);
170 g_debug ("PROP [%s] VAL [%s]", prop_name, prop_val);
172 s = g_object_class_find_property (k, prop_name);
174 g_print ("Invalid property name: %s\n", prop_name);
178 g_value_init (&p, s->value_type);
179 switch (s->value_type)
182 g_value_set_int (&p, atoi (prop_val));
185 g_value_set_string (&p, prop_val);
191 g_object_set_property (obj, prop_name, &p);
197 _create_element_with_prop (const gchar* factory_name,
198 const gchar* element_name,
205 g_debug ("SET OBJ [%s]", factory_name);
206 ret = gst_element_factory_make (factory_name, element_name);
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]);
225 _create_audio_bin (GMencoder* self,
230 GstElement *abin = NULL;
231 GstElement *aqueue = NULL;
232 GstElement *aconvert = NULL;
233 GstElement *aencode = NULL;
234 GstElement *aqueue_src = NULL;
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");
244 if ((abin == NULL) || (aqueue == NULL) || (aconvert == NULL)
245 || (aencode == NULL) || (aqueue_src == NULL)) {
246 g_warning ("Audio elements not found");
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);
253 //TODO: apply audio rate
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);
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);
267 gst_object_unref (abin);
270 gst_object_unref (aqueue);
272 if (aconvert != NULL)
273 gst_object_unref (aconvert);
276 gst_object_unref (aencode);
278 if (aqueue_src != NULL)
279 gst_object_unref (aqueue_src);
282 gst_object_unref (apad);
290 //queue ! videoscale ! video/x-raw-yuv,width=240,height=144 ! colorspace ! rate ! encode ! queue
292 _create_video_bin (GMencoder* self,
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;
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");
315 if ((vbin == NULL) || (vqueue == NULL) || (vcolorspace == NULL)
316 || (vencode == NULL) || (vqueue_src == NULL)) {
317 g_warning ("Video elements not found");
321 gst_bin_add_many (GST_BIN (vbin), vqueue, vcolorspace, vencode, vqueue_src, NULL);
324 if ((width > 0) && (height > 0)) {
327 GstElement *vscale = gst_element_factory_make ("videoscale", "vscale");
329 gst_bin_add (GST_BIN (vbin), vscale);
331 vcaps = gst_caps_new_simple ("video/x-raw-yuv",
332 "width", G_TYPE_INT, width,
333 "height", G_TYPE_INT, height,
336 gst_element_link (vqueue, vscale);
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);
344 gst_caps_unref (vcaps);
346 gst_element_link (vqueue, vcolorspace);
350 //Changing the video fps
353 gst_bin_add (GST_BIN (vbin), vrate);
355 if (gst_element_link (vcolorspace, vrate) == FALSE) {
356 g_warning ("Fail to link video elements");
360 vcaps = gst_caps_new_simple ("video/x-raw-yuv",
361 "framerate", GST_TYPE_FRACTION, (int) (fps * 1000), 1000, NULL);
363 if (gst_element_link_filtered (vrate, vencode, vcaps) == FALSE) {
364 g_warning ("Fail to link vrate with vencode.");
367 gst_caps_unref (vcaps);
369 if (gst_element_link (vcolorspace, vencode) == FALSE) {
370 g_warning ("Fail to link colorspace and video encode element.");
376 gst_element_link (vencode, vqueue_src);
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);
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);
391 gst_object_unref (vpad);
394 gst_object_unref (vbin);
397 gst_object_unref (vqueue);
400 gst_object_unref (vencode);
402 if (vqueue_src != NULL)
403 gst_object_unref (vqueue_src);
405 if (vcolorspace != NULL)
406 gst_object_unref (vcolorspace);
413 g_mencoder_setup_stream (GMencoder *self,
415 const gchar* video_encode,
416 gchar** video_encode_prop,
421 const gchar* audio_encode,
422 gchar** audio_encode_prop,
424 const gchar* sink_name,
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;
438 GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
440 pipe = gst_pipeline_new ("pipe");
441 src = gst_element_make_from_uri (GST_URI_SRC, uri, "src");
445 decode = gst_element_factory_make ("decodebin2", "decode");
449 mux = gst_element_factory_make ("ffmux_mpeg", "mux");
453 fdsink = _create_element_with_prop (sink_name, "sink", sink_prop);
457 abin = _create_audio_bin (self, audio_encode, audio_encode_prop, audio_rate);
461 vbin = _create_video_bin (self, video_encode, video_encode_prop, video_fps, video_rate, video_width, video_height);
466 gst_bin_add_many (GST_BIN (pipe), src, decode, abin, vbin, mux, fdsink, NULL);
467 gst_element_link (src, decode);
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);
478 gst_object_unref (aux_pad);
479 gst_object_unref (mux_pad);
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);
488 gst_object_unref (aux_pad);
489 gst_object_unref (mux_pad);
494 gst_element_link (mux, fdsink);
496 g_signal_connect (G_OBJECT (decode),
498 G_CALLBACK (_decodebin_new_pad_cb),
501 g_signal_connect (G_OBJECT (decode),
503 G_CALLBACK (_decodebin_unknown_type_cb),
507 bus = gst_pipeline_get_bus (GST_PIPELINE (pipe));
508 gst_bus_add_watch (bus, _pipeline_bus_cb, self);
509 gst_object_unref (bus);
518 gst_element_set_state (pipe, GST_STATE_PAUSED);
522 g_warning ("Invalid uri");
525 gst_object_unref (pipe);
529 gst_object_unref (src);
533 gst_object_unref (mux);
536 if (mux_pad != NULL) {
537 gst_object_unref (mux_pad);
540 if (aux_pad != NULL) {
541 gst_object_unref (mux_pad);
544 if (fdsink != NULL) {
545 gst_object_unref (fdsink);
549 gst_object_unref (abin);
553 gst_object_unref (vbin);
560 g_mencoder_play_stream (GMencoder *self)
562 GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
564 g_return_val_if_fail (priv->ready == TRUE, FALSE);
566 if (gst_element_set_state (priv->pipe, GST_STATE_PLAYING) != GST_STATE_CHANGE_FAILURE) {
574 g_mencoder_pause_stream (GMencoder *self)
576 GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
578 g_return_val_if_fail (priv->ready == TRUE, FALSE);
580 if (gst_element_set_state (priv->pipe, GST_STATE_PAUSED) != GST_STATE_CHANGE_FAILURE) {
588 g_mencoder_close_stream (GMencoder *self)
591 GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self);
593 g_return_if_fail (priv->ready == TRUE);
595 gst_element_set_state (priv->pipe, GST_STATE_NULL);
596 gst_object_unref (priv->pipe);
605 _pipeline_bus_cb (GstBus *bus,
609 switch (GST_MESSAGE_TYPE (msg))
611 case GST_MESSAGE_STATE_CHANGED:
615 GstState pendingstate;
617 GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (user_data);
619 gst_message_parse_state_changed (msg, &oldstate,
620 &newstate, &pendingstate);
622 if (pendingstate != GST_STATE_VOID_PENDING)
625 if ((oldstate == GST_STATE_READY) &&
626 (newstate == GST_STATE_PAUSED)) {
628 g_signal_emit (user_data, g_mencoder_signals[PAUSED], 0);
631 g_signal_emit (user_data, g_mencoder_signals[READY], 0);
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);
642 case GST_MESSAGE_ERROR:
648 gst_message_parse_error (msg, &error, &debug);
649 err_str = g_strdup_printf ("Error [%d] %s (%s)", error->code,
652 g_signal_emit (user_data, g_mencoder_signals[ERROR], 0, err_str);
654 g_clear_error (&error);
659 case GST_MESSAGE_EOS:
660 g_signal_emit (user_data, g_mencoder_signals[EOS], 0);
669 _decodebin_new_pad_cb (GstElement* object,
675 gchar *str_caps = NULL;
676 GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (user_data);
678 caps = gst_pad_get_caps (pad);
679 str_caps = gst_caps_to_string (caps);
680 g_debug ("CAPS : %s", str_caps);
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);
691 g_warning ("invalid caps %s", str_caps);
695 gst_caps_unref (caps);
699 _decodebin_unknown_type_cb (GstElement* object,
704 g_warning ("Unknown Type");