# HG changeset patch # User renatofilho # Date 1177358721 -3600 # Node ID 3219eb5401c0d0c095f812b2dd72301d59caa617 # Parent 747b409e4f014745c9eebda2d140de7815481e70 [svn r594] bug fixed diff -r 747b409e4f01 -r 3219eb5401c0 gmyth-stream/gmemcoder/src/Makefile.am --- a/gmyth-stream/gmemcoder/src/Makefile.am Mon Apr 23 19:16:24 2007 +0100 +++ b/gmyth-stream/gmemcoder/src/Makefile.am Mon Apr 23 21:05:21 2007 +0100 @@ -3,8 +3,8 @@ gmencoder_SOURCES = \ main.c \ - gmemcoder.c \ - gmemcoder.h + gmencoder.c \ + gmencoder.h gmencoder_LDADD = \ $(GLIB_LIBS) \ diff -r 747b409e4f01 -r 3219eb5401c0 gmyth-stream/gmemcoder/src/gmemcoder.c --- a/gmyth-stream/gmemcoder/src/gmemcoder.c Mon Apr 23 19:16:24 2007 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,551 +0,0 @@ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include - -#include "gmemcoder.h" - -#define G_MENCODER_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), G_TYPE_MENCODER, GMencoderPrivate)) - - -typedef struct _GMencoderPrivate GMencoderPrivate; - -struct _GMencoderPrivate -{ - GstElement *pipe; - GstElement *abin; - GstElement *vbin; - GstElement *sink; - gboolean ready; -}; - -enum { - READY, - PAUSED, - PLAYING, - STOPED, - EOS, - ERROR, - LAST_SIGNAL -}; - -static void g_mencoder_class_init (GMencoderClass *klass); -static void g_mencoder_init (GMencoder *object); -static void g_mencoder_dispose (GObject *object); -static void g_mencoder_finalize (GObject *object); -static gboolean - _pipeline_bus_cb (GstBus *bus, - GstMessage *msg, - gpointer user_data); - -static void _decodebin_new_pad_cb (GstElement* object, - GstPad* pad, - gboolean flag, - gpointer user_data); -static void _decodebin_unknown_type_cb (GstElement* object, - GstPad* pad, - GstCaps* caps, - gpointer user_data); - -static guint g_mencoder_signals[LAST_SIGNAL] = { 0 }; - -G_DEFINE_TYPE(GMencoder, g_mencoder, G_TYPE_OBJECT) - -static void -g_mencoder_class_init (GMencoderClass *klass) -{ - GObjectClass *object_class; - - object_class = (GObjectClass *) klass; - - g_type_class_add_private (klass, sizeof (GMencoderPrivate)); - - object_class->dispose = g_mencoder_dispose; - object_class->finalize = g_mencoder_finalize; - - g_mencoder_signals[READY] = - g_signal_new ("ready", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - g_mencoder_signals[PAUSED] = - g_signal_new ("paused", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - g_mencoder_signals[PLAYING] = - g_signal_new ("playing", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - g_mencoder_signals[STOPED] = - g_signal_new ("stoped", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - g_mencoder_signals[EOS] = - g_signal_new ("eos", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - - g_mencoder_signals[ERROR] = - g_signal_new ("error", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, G_TYPE_STRING); -} - -static void -g_mencoder_init (GMencoder *self) -{ -} - -static void -g_mencoder_dispose (GObject *object) -{ -} - -static void -g_mencoder_finalize (GObject *object) -{ - g_mencoder_close_stream (G_MENCODER (object)); -} - -GMencoder* -g_mencoder_new (void) -{ - return g_object_new (G_TYPE_MENCODER, NULL); -} - - -gboolean -g_mencoder_setup_stream (GMencoder *self, - const gchar* uri, - guint width, guint height, - gint out_fd) -{ - GstBus *bus = NULL; - GstElement *pipe = NULL; - GstElement *decode = NULL; - GstElement *fdsink = NULL; - GstElement *mux = NULL; - - GstCaps *vscale_caps = NULL; - GstPad *asinkpad = NULL; - GstPad *vsinkpad = NULL; - GstPad *video_src_pad = NULL; - GstPad *audio_src_pad = NULL; - GstPad *mux_pad = NULL; - GstElement *src = NULL; - GstElement *vbin, *vqueue, *vcolorspace, *vscale, *vrate, *vencode, *vqueue_src; - GstElement *abin, *aqueue, *aconvert, *aencode, *aqueue_src; - GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self); - - vbin = vqueue = vscale = vrate = vencode = vqueue_src = NULL; - abin = aqueue = aconvert = aencode = aqueue_src = NULL; - - pipe = gst_pipeline_new ("pipe"); - src = gst_element_make_from_uri (GST_URI_SRC, uri, "src"); - if (src == NULL) - goto error; - - decode = gst_element_factory_make ("decodebin", "decode"); - if (decode == NULL) - goto error; - - mux = gst_element_factory_make ("ffmux_mpeg", "mux"); - if (mux == NULL) - goto error; - - fdsink = gst_element_factory_make ("fdsink", "sink"); - if (fdsink == NULL) - goto error; - - g_debug ("Setting fd to %d", out_fd); - g_object_set (G_OBJECT (fdsink), "fd", out_fd, NULL); - - //queue ! videoscale ! video/x-raw-yuv,width=240,height=144 ! videorate ! ffenc_h263p bitrate=256000 me-method=2 ! rtph263ppay ! udpsink host=224.0.0.1 port=5000 - - vbin = gst_bin_new ("vbin"); - vqueue = gst_element_factory_make ("queue", "vqueue"); - vscale = gst_element_factory_make ("videoscale", "vscale"); - vcolorspace = gst_element_factory_make ("ffmpegcolorspace", "colorspace"); - vrate = gst_element_factory_make ("videorate", "vrate"); - vencode = gst_element_factory_make ("ffenc_mpeg1video", "vencode"); - vqueue_src = gst_element_factory_make ("queue", "queue_src"); - - - if ((vbin == NULL) || (vqueue == NULL) || (vcolorspace == NULL) - || (vscale == NULL) || (vrate == NULL) - || (vencode == NULL) || (vqueue_src == NULL)) { - g_warning ("Video elements not found"); - goto error; - } - - g_object_set (G_OBJECT (vencode), "bitrate", 200, "pass", 2, "quantizer", 5, NULL); - - gst_bin_add_many (GST_BIN (vbin), vqueue, vscale, vcolorspace, vrate, vencode, vqueue_src, NULL); - gst_element_link (vqueue, vscale); - - - vscale_caps = gst_caps_new_simple ("video/x-raw-yuv", - "width", G_TYPE_INT, 320, - "height", G_TYPE_INT, 288, - NULL); - - if (gst_element_link_filtered (vscale, vcolorspace, vscale_caps) == FALSE) { - g_warning ("Fail to resize video"); - goto error; - } - - if (gst_element_link (vcolorspace, vrate) == FALSE) { - g_warning ("Fail to link video elements"); - goto error; - } - - gst_caps_unref (vscale_caps); - - vscale_caps = gst_caps_new_simple ("video/x-raw-yuv", - "framerate", GST_TYPE_FRACTION, 10, 1, NULL); - - if (gst_element_link_filtered (vrate, vencode, vscale_caps) == FALSE) { - g_warning ("Fail to link vrate with vencode."); - goto error; - - } - - gst_element_link (vencode, vqueue_src); - - // ghost pad the video bin - vsinkpad = gst_element_get_pad (vqueue, "sink"); - gst_element_add_pad (vbin, gst_ghost_pad_new ("sink", vsinkpad)); - gst_object_unref (vsinkpad); - - video_src_pad = gst_element_get_pad (vqueue_src, "src"); - gst_element_add_pad (vbin, gst_ghost_pad_new ("src", video_src_pad)); - gst_object_unref (video_src_pad); - - - //audio/x-raw-int ! queue ! audioconvert ! faac ! rtpmp4gpay ! udpsink name=upd_audio host=224.0.0.1 port=5002 - abin = gst_bin_new ("abin"); - aqueue = gst_element_factory_make ("queue", "aqueue"); - aconvert= gst_element_factory_make ("audioconvert", "aconvert"); - aencode = gst_element_factory_make ("lame", "aencode"); - aqueue_src= gst_element_factory_make ("queue", "aqueue_src"); - - if ((abin == NULL) || (aqueue == NULL) || (aconvert == NULL) - || (aencode == NULL) || (aqueue_src == NULL)) { - g_warning ("Audio elements not found"); - goto error; - } - - gst_bin_add_many (GST_BIN (abin), aqueue, aconvert, aencode, aqueue_src, NULL); - gst_element_link_many (aqueue, aconvert, aencode, aqueue_src, NULL); - - - // ghost pad the audio bin - asinkpad = gst_element_get_pad (aqueue, "sink"); - gst_element_add_pad (abin, gst_ghost_pad_new("sink", asinkpad)); - gst_object_unref (asinkpad); - - audio_src_pad = gst_element_get_pad (aqueue_src, "src"); - gst_element_add_pad (abin, gst_ghost_pad_new("src", audio_src_pad)); - gst_object_unref (audio_src_pad); - - - // Finish Pipe - gst_bin_add_many (GST_BIN (pipe), src, decode, abin, vbin, mux, fdsink, NULL); - gst_element_link (src, decode); - - //Link bins with mux - audio_src_pad = gst_element_get_pad (abin, "src"); - mux_pad = gst_element_get_pad (mux, "audio_0"); - if (gst_pad_link (audio_src_pad, mux_pad) != GST_PAD_LINK_OK) { - g_warning ("Fail link audio and mux"); - goto error; - - } - gst_object_unref (audio_src_pad); - gst_object_unref (mux_pad); - audio_src_pad = NULL; - mux_pad = NULL; - - video_src_pad = gst_element_get_pad (vbin, "src"); - mux_pad = gst_element_get_pad (mux, "video_0"); - if (gst_pad_link (video_src_pad, mux_pad) != GST_PAD_LINK_OK) { - g_warning ("Fail link video and mux"); - goto error; - } - gst_object_unref (video_src_pad); - gst_object_unref (mux_pad); - video_src_pad = NULL; - mux_pad = NULL; - - //Link mux with sink - gst_element_link (mux, fdsink); - - bus = gst_pipeline_get_bus (GST_PIPELINE (pipe)); - gst_bus_add_watch (bus, _pipeline_bus_cb, self); - gst_object_unref (bus); - - g_signal_connect (G_OBJECT (decode), - "new-decoded-pad", - G_CALLBACK (_decodebin_new_pad_cb), - self); - - g_signal_connect (G_OBJECT (decode), - "unknown-type", - G_CALLBACK (_decodebin_unknown_type_cb), - self); - - g_debug ("Setting pipe to PAUSE"); - - priv->pipe = pipe; - priv->abin = abin; - priv->vbin = vbin; - priv->sink = fdsink; - priv->ready = FALSE; - - gst_element_set_state (pipe, GST_STATE_PAUSED); - g_debug ("End SETUP"); - return TRUE; - -error: - g_warning ("Invalid uri"); - - if (pipe != NULL) - gst_object_unref (pipe); - - if (src != NULL) - gst_object_unref (src); - - if (decode != NULL) - gst_object_unref (decode); - - if (vscale_caps != NULL) - gst_caps_unref (vscale_caps); - - if (vbin != NULL) - gst_object_unref (vbin); - - if (vqueue != NULL) - gst_object_unref (vqueue); - - if (vrate != NULL) - gst_object_unref (vrate); - - if (vencode != NULL) - gst_object_unref (vencode); - - if (vqueue_src != NULL) - gst_object_unref (vqueue_src); - - if (abin != NULL) - gst_object_unref (abin); - - if (aqueue != NULL) - gst_object_unref (aqueue); - - if (aconvert != NULL) - gst_object_unref (aconvert); - - if (aencode != NULL) - gst_object_unref (aencode); - - if (aqueue_src != NULL) - gst_object_unref (aqueue_src); - - if (video_src_pad != NULL) { - gst_object_unref (video_src_pad); - } - - if (audio_src_pad != NULL) { - gst_object_unref (audio_src_pad); - } - - if (mux != NULL) { - gst_object_unref (mux); - } - - if (mux_pad != NULL) { - gst_object_unref (mux_pad); - } - - if (fdsink != NULL) - gst_object_unref (fdsink); - - return FALSE; -} - -gboolean -g_mencoder_play_stream (GMencoder *self) -{ - GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self); - - g_return_val_if_fail (priv->ready == TRUE, FALSE); - - if (gst_element_set_state (priv->pipe, GST_STATE_PLAYING) != GST_STATE_CHANGE_FAILURE) { - g_debug ("PLAYING"); - return TRUE; - } - return FALSE; -} - -gboolean -g_mencoder_pause_stream (GMencoder *self) -{ - GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self); - - g_return_val_if_fail (priv->ready == TRUE, FALSE); - - if (gst_element_set_state (priv->pipe, GST_STATE_PAUSED) != GST_STATE_CHANGE_FAILURE) { - g_debug ("PAUSED"); - return TRUE; - } - return FALSE; -} - -void -g_mencoder_close_stream (GMencoder *self) -{ - - GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self); - - g_return_if_fail (priv->ready == TRUE); - - gst_element_set_state (priv->pipe, GST_STATE_NULL); - gst_object_unref (priv->pipe); - priv->pipe = NULL; - priv->abin = NULL; - priv->vbin = NULL; - priv->sink = NULL; - priv->ready = FALSE; -} - -static gboolean -_pipeline_bus_cb (GstBus *bus, - GstMessage *msg, - gpointer user_data) -{ - switch (GST_MESSAGE_TYPE (msg)) - { - case GST_MESSAGE_STATE_CHANGED: - { - GstState oldstate; - GstState newstate; - GstState pendingstate; - - GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (user_data); - - gst_message_parse_state_changed (msg, &oldstate, - &newstate, &pendingstate); - - if (pendingstate != GST_STATE_VOID_PENDING) - break; - - if ((oldstate == GST_STATE_READY) && - (newstate == GST_STATE_PAUSED)) { - if (priv->ready) - g_signal_emit (user_data, g_mencoder_signals[PAUSED], 0); - else { - priv->ready = TRUE; - g_signal_emit (user_data, g_mencoder_signals[READY], 0); - } - } else if ((oldstate == GST_STATE_PAUSED) && - (newstate == GST_STATE_PLAYING)) { - g_signal_emit (user_data, g_mencoder_signals[PLAYING], 0); - } else if ((oldstate == GST_STATE_READY) && - (newstate == GST_STATE_NULL)) { - g_signal_emit (user_data, g_mencoder_signals[STOPED], 0); - } - break; - } - case GST_MESSAGE_ERROR: - { - GError *error; - gchar *debug; - gchar *err_str; - - gst_message_parse_error (msg, &error, &debug); - err_str = g_strdup_printf ("Error [%d] %s (%s)", error->code, - error->message, - debug); - g_signal_emit (user_data, g_mencoder_signals[ERROR], 0, err_str); - g_free (err_str); - g_clear_error (&error); - g_free (debug); - break; - } - - case GST_MESSAGE_EOS: - g_signal_emit (user_data, g_mencoder_signals[EOS], 0); - break; - default: - break; - } - return TRUE; -} - -static void -_decodebin_new_pad_cb (GstElement* object, - GstPad* pad, - gboolean flag, - gpointer user_data) -{ - GstCaps *caps; - gchar *str_caps = NULL; - GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (user_data); - - caps = gst_pad_get_caps (pad); - str_caps = gst_caps_to_string (caps); - g_debug ("CAPS : %s", str_caps); - - if (strstr (str_caps, "audio") != NULL) { - GstPad *apad = gst_element_get_pad (priv->abin, "sink"); - g_debug ("Linked with Audio"); - gst_pad_link (pad, apad); - gst_object_unref (apad); - } else if (strstr (str_caps, "video") != NULL) { - GstPad *vpad = gst_element_get_pad (priv->vbin, "sink"); - g_debug ("Linked with Video"); - gst_pad_link (pad, vpad); - gst_object_unref (vpad); - } else { - g_warning ("invalid caps %s", str_caps); - } - - g_free (str_caps); - gst_caps_unref (caps); - g_debug ("OK"); -} - -static void -_decodebin_unknown_type_cb (GstElement* object, - GstPad* pad, - GstCaps* caps, - gpointer user_data) -{ - g_warning ("Unknown Type"); -} diff -r 747b409e4f01 -r 3219eb5401c0 gmyth-stream/gmemcoder/src/gmemcoder.h --- a/gmyth-stream/gmemcoder/src/gmemcoder.h Mon Apr 23 19:16:24 2007 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -#ifndef __G_MENCODER_H__ -#define __G_MENCODER_H__ - -#include - -G_BEGIN_DECLS - -typedef struct _GMencoder GMencoder; -typedef struct _GMencoderClass GMencoderClass; - -struct _GMencoderClass { - GObjectClass parent_class; -}; - -struct _GMencoder { - GObject parent; -}; - -/* TYPE MACROS */ -#define G_TYPE_MENCODER \ - (g_mencoder_get_type()) -#define G_MENCODER(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_MENCODER, GMencoder)) -#define G_MENCODER_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_MENCODER, GMencoderClass)) -#define G_IS_MENCODER(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_MENCODER)) -#define G_IS_MENCODER_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_MENCODER)) -#define G_MENCODER_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), G_TYPE_MENCODER, GMencoderClass)) - - -GType g_mencoder_get_type (void); -GMencoder* g_mencoder_new (void); -gboolean g_mencoder_setup_stream (GMencoder *self, - const gchar* uri, - guint width, guint height, - gint out_fd); -gboolean g_mencoder_play_stream (GMencoder *self); -gboolean g_mencoder_pause_stream (GMencoder *self); -void g_mencoder_close_stream (GMencoder *self); - -G_END_DECLS - -#endif diff -r 747b409e4f01 -r 3219eb5401c0 gmyth-stream/gmemcoder/src/gmencoder.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth-stream/gmemcoder/src/gmencoder.c Mon Apr 23 21:05:21 2007 +0100 @@ -0,0 +1,705 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include "gmencoder.h" + +#define G_MENCODER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), G_TYPE_MENCODER, GMencoderPrivate)) + + +typedef struct _GMencoderPrivate GMencoderPrivate; + +struct _GMencoderPrivate +{ + GstElement *pipe; + GstElement *abin; + GstElement *vbin; + GstElement *sink; + gboolean ready; +}; + +enum { + READY, + PAUSED, + PLAYING, + STOPED, + EOS, + ERROR, + LAST_SIGNAL +}; + +static void g_mencoder_class_init (GMencoderClass *klass); +static void g_mencoder_init (GMencoder *object); +static void g_mencoder_dispose (GObject *object); +static void g_mencoder_finalize (GObject *object); +static GstElement* + _create_audio_bin (GMencoder *self, + const gchar* encode, + gchar** encode_prop, + gint rate); +static GstElement* + _create_video_bin (GMencoder* self, + const gchar* encode, + gchar** encode_prop, + gdouble fps, + gint rate, + guint width, + guint height); + +static gboolean + _pipeline_bus_cb (GstBus *bus, + GstMessage *msg, + gpointer user_data); +static void _decodebin_new_pad_cb (GstElement* object, + GstPad* pad, + gboolean flag, + gpointer user_data); +static void _decodebin_unknown_type_cb (GstElement* object, + GstPad* pad, + GstCaps* caps, + gpointer user_data); + + +static guint g_mencoder_signals[LAST_SIGNAL] = { 0 }; + +G_DEFINE_TYPE(GMencoder, g_mencoder, G_TYPE_OBJECT) + +static void +g_mencoder_class_init (GMencoderClass *klass) +{ + GObjectClass *object_class; + + object_class = (GObjectClass *) klass; + + g_type_class_add_private (klass, sizeof (GMencoderPrivate)); + + object_class->dispose = g_mencoder_dispose; + object_class->finalize = g_mencoder_finalize; + + g_mencoder_signals[READY] = + g_signal_new ("ready", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + g_mencoder_signals[PAUSED] = + g_signal_new ("paused", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + g_mencoder_signals[PLAYING] = + g_signal_new ("playing", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + g_mencoder_signals[STOPED] = + g_signal_new ("stoped", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + g_mencoder_signals[EOS] = + g_signal_new ("eos", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + + g_mencoder_signals[ERROR] = + g_signal_new ("error", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, G_TYPE_STRING); +} + +static void +g_mencoder_init (GMencoder *self) +{ +} + +static void +g_mencoder_dispose (GObject *object) +{ +} + +static void +g_mencoder_finalize (GObject *object) +{ + g_mencoder_close_stream (G_MENCODER (object)); +} + +GMencoder* +g_mencoder_new (void) +{ + return g_object_new (G_TYPE_MENCODER, NULL); +} + +static void +_obj_set_prop (GObject *obj, + const gchar *prop_name, + const gchar *prop_val) +{ + GValue p = {0}; + GValue v = {0}; + GParamSpec *s = NULL; + GObjectClass *k = G_OBJECT_GET_CLASS (obj); + + + g_value_init (&v, G_TYPE_STRING); + g_value_set_string (&v, prop_val); + + g_debug ("PROP [%s] VAL [%s]", prop_name, prop_val); + + s = g_object_class_find_property (k, prop_name); + if (s == NULL) { + g_print ("Invalid property name: %s\n", prop_name); + return; + } + + g_value_init (&p, s->value_type); + switch (s->value_type) + { + case G_TYPE_INT: + g_value_set_int (&p, atoi (prop_val)); + break; + case G_TYPE_STRING: + g_value_set_string (&p, prop_val); + break; + default: + return; + } + + g_object_set_property (obj, prop_name, &p); + g_value_unset (&v); + g_value_unset (&p); +} + +static GstElement* +_create_element_with_prop (const gchar* factory_name, + const gchar* element_name, + gchar** prop) +{ + GstElement *ret; + int i; + + + g_debug ("SET OBJ [%s]", factory_name); + ret = gst_element_factory_make (factory_name, element_name); + if (ret == NULL) + return NULL; + + if (prop != NULL) { + for (i=0; i < g_strv_length (prop); i++) { + char** v = g_strsplit(prop[i], "=", 2); + if (g_strv_length (v) == 2) { + _obj_set_prop (G_OBJECT (ret), v[0], v[1]); + } + g_strfreev (v); + } + } + + return ret; + +} + +static GstElement* +_create_audio_bin (GMencoder* self, + const gchar* encode, + gchar** encode_prop, + gint rate) +{ + GstElement *abin = NULL; + GstElement *aqueue = NULL; + GstElement *aconvert = NULL; + GstElement *aencode = NULL; + GstElement *aqueue_src = NULL; + GstPad *apad = NULL; + + //audio/x-raw-int ! queue ! audioconvert ! faac ! rtpmp4gpay ! udpsink name=upd_audio host=224.0.0.1 port=5002 + abin = gst_bin_new ("abin"); + aqueue = gst_element_factory_make ("queue", "aqueue"); + aconvert= gst_element_factory_make ("audioconvert", "aconvert"); + aencode = _create_element_with_prop ((encode ? encode : "lame"), "aencode", encode_prop); + aqueue_src= gst_element_factory_make ("queue", "aqueue_src"); + + if ((abin == NULL) || (aqueue == NULL) || (aconvert == NULL) + || (aencode == NULL) || (aqueue_src == NULL)) { + g_warning ("Audio elements not found"); + goto error; + } + + gst_bin_add_many (GST_BIN (abin), aqueue, aconvert, aencode, aqueue_src, NULL); + gst_element_link_many (aqueue, aconvert, aencode, aqueue_src, NULL); + + //TODO: apply audio rate + + // ghost pad the audio bin + apad = gst_element_get_pad (aqueue, "sink"); + gst_element_add_pad (abin, gst_ghost_pad_new("sink", apad)); + gst_object_unref (apad); + + apad = gst_element_get_pad (aqueue_src, "src"); + gst_element_add_pad (abin, gst_ghost_pad_new("src", apad)); + gst_object_unref (apad); + + return abin; +error: + if (abin != NULL) + gst_object_unref (abin); + + if (aqueue != NULL) + gst_object_unref (aqueue); + + if (aconvert != NULL) + gst_object_unref (aconvert); + + if (aencode != NULL) + gst_object_unref (aencode); + + if (aqueue_src != NULL) + gst_object_unref (aqueue_src); + + if (apad != NULL) + gst_object_unref (apad); + + return NULL; +} + + + + +//queue ! videoscale ! video/x-raw-yuv,width=240,height=144 ! colorspace ! rate ! encode ! queue +static GstElement* +_create_video_bin (GMencoder* self, + const gchar* encode, + gchar** encode_prop, + gdouble fps, + gint rate, + guint width, + guint height) +{ + GstElement *vbin = NULL; + GstElement *vqueue = NULL; + GstElement* vqueue_src = NULL; + GstElement *vcolorspace = NULL; + GstElement *vencode = NULL; + GstElement *vrate = NULL; + GstPad *vpad = NULL; + + vbin = gst_bin_new ("vbin"); + vqueue = gst_element_factory_make ("queue", "vqueue"); + vcolorspace = gst_element_factory_make ("ffmpegcolorspace", "colorspace"); + vencode = _create_element_with_prop ((encode ? encode : "ffenc_mpeg1video"), "vencode", encode_prop); + vrate = gst_element_factory_make ("videorate", "vrate"); + vqueue_src = gst_element_factory_make ("queue", "queue_src"); + + if ((vbin == NULL) || (vqueue == NULL) || (vcolorspace == NULL) + || (vencode == NULL) || (vqueue_src == NULL)) { + g_warning ("Video elements not found"); + goto error; + } + + gst_bin_add_many (GST_BIN (vbin), vqueue, vcolorspace, vencode, vqueue_src, NULL); + + + if ((width > 0) && (height > 0)) { + //Scalling video + GstCaps *vcaps; + GstElement *vscale = gst_element_factory_make ("videoscale", "vscale"); + + gst_bin_add (GST_BIN (vbin), vscale); + + vcaps = gst_caps_new_simple ("video/x-raw-yuv", + "width", G_TYPE_INT, width, + "height", G_TYPE_INT, height, + NULL); + + gst_element_link (vqueue, vscale); + + if (gst_element_link_filtered (vscale, vcolorspace, vcaps) == FALSE) { + g_warning ("Fail to resize video"); + gst_object_unref (vcaps); + gst_object_unref (vscale); + goto error; + } + gst_caps_unref (vcaps); + } else { + gst_element_link (vqueue, vcolorspace); + } + + if (fps > 0) { + //Changing the video fps + GstCaps *vcaps; + + gst_bin_add (GST_BIN (vbin), vrate); + + if (gst_element_link (vcolorspace, vrate) == FALSE) { + g_warning ("Fail to link video elements"); + goto error; + } + + vcaps = gst_caps_new_simple ("video/x-raw-yuv", + "framerate", GST_TYPE_FRACTION, (int) (fps * 1000), 1000, NULL); + + if (gst_element_link_filtered (vrate, vencode, vcaps) == FALSE) { + g_warning ("Fail to link vrate with vencode."); + goto error; + } + gst_caps_unref (vcaps); + } else { + if (gst_element_link (vcolorspace, vencode) == FALSE) { + g_warning ("Fail to link colorspace and video encode element."); + goto error; + } + } + + + gst_element_link (vencode, vqueue_src); + + // ghost pad the video bin + vpad = gst_element_get_pad (vqueue, "sink"); + gst_element_add_pad (vbin, gst_ghost_pad_new ("sink", vpad)); + gst_object_unref (vpad); + + vpad = gst_element_get_pad (vqueue_src, "src"); + gst_element_add_pad (vbin, gst_ghost_pad_new ("src", vpad)); + gst_object_unref (vpad); + + return vbin; + +error: + if (vpad != NULL) + gst_object_unref (vpad); + + if (vbin != NULL) + gst_object_unref (vbin); + + if (vqueue != NULL) + gst_object_unref (vqueue); + + if (vencode != NULL) + gst_object_unref (vencode); + + if (vqueue_src != NULL) + gst_object_unref (vqueue_src); + + if (vcolorspace != NULL) + gst_object_unref (vcolorspace); + + return NULL; +} + + +gboolean +g_mencoder_setup_stream (GMencoder *self, + const gchar* uri, + const gchar* video_encode, + gchar** video_encode_prop, + gdouble video_fps, + gdouble video_rate, + guint video_width, + guint video_height, + const gchar* audio_encode, + gchar** audio_encode_prop, + guint audio_rate, + const gchar* sink_name, + gchar** sink_prop) +{ + GstBus *bus = NULL; + GstElement *pipe = NULL; + GstElement *fdsink = NULL; + GstElement *mux = NULL; + GstElement *decode = NULL; + GstElement *src = NULL; + GstElement *abin = NULL; + GstElement *vbin = NULL; + GstPad *aux_pad = NULL; + GstPad *mux_pad = NULL; + + GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self); + + pipe = gst_pipeline_new ("pipe"); + src = gst_element_make_from_uri (GST_URI_SRC, uri, "src"); + if (src == NULL) + goto error; + + decode = gst_element_factory_make ("decodebin2", "decode"); + if (decode == NULL) + goto error; + + mux = gst_element_factory_make ("ffmux_mpeg", "mux"); + if (mux == NULL) + goto error; + + fdsink = _create_element_with_prop (sink_name, "sink", sink_prop); + if (fdsink == NULL) + goto error; + + abin = _create_audio_bin (self, audio_encode, audio_encode_prop, audio_rate); + if (abin == NULL) + goto error; + + vbin = _create_video_bin (self, video_encode, video_encode_prop, video_fps, video_rate, video_width, video_height); + if (vbin == NULL) + goto error; + + // Finish Pipe + gst_bin_add_many (GST_BIN (pipe), src, decode, abin, vbin, mux, fdsink, NULL); + gst_element_link (src, decode); + + //Link bins with mux + aux_pad = gst_element_get_pad (abin, "src"); + mux_pad = gst_element_get_pad (mux, "audio_0"); + GstPadLinkReturn ret = gst_pad_link (aux_pad, mux_pad); + if (ret != GST_PAD_LINK_OK) { + g_warning ("Fail link audio and mux: %d", ret); + goto error; + + } + gst_object_unref (aux_pad); + gst_object_unref (mux_pad); + + aux_pad = gst_element_get_pad (vbin, "src"); + mux_pad = gst_element_get_pad (mux, "video_0"); + ret = gst_pad_link (aux_pad, mux_pad); + if (ret != GST_PAD_LINK_OK) { + g_warning ("Fail link video and mux: %d", ret); + goto error; + } + gst_object_unref (aux_pad); + gst_object_unref (mux_pad); + aux_pad = NULL; + mux_pad = NULL; + + //Link mux with sink + gst_element_link (mux, fdsink); + + g_signal_connect (G_OBJECT (decode), + "new-decoded-pad", + G_CALLBACK (_decodebin_new_pad_cb), + self); + + g_signal_connect (G_OBJECT (decode), + "unknown-type", + G_CALLBACK (_decodebin_unknown_type_cb), + self); + + + bus = gst_pipeline_get_bus (GST_PIPELINE (pipe)); + gst_bus_add_watch (bus, _pipeline_bus_cb, self); + gst_object_unref (bus); + + + priv->pipe = pipe; + priv->abin = abin; + priv->vbin = vbin; + priv->sink = fdsink; + priv->ready = FALSE; + + gst_element_set_state (pipe, GST_STATE_PAUSED); + return TRUE; + +error: + g_warning ("Invalid uri"); + + if (pipe != NULL) { + gst_object_unref (pipe); + } + + if (src != NULL) { + gst_object_unref (src); + } + + if (mux != NULL) { + gst_object_unref (mux); + } + + if (mux_pad != NULL) { + gst_object_unref (mux_pad); + } + + if (aux_pad != NULL) { + gst_object_unref (mux_pad); + } + + if (fdsink != NULL) { + gst_object_unref (fdsink); + } + + if (abin != NULL) { + gst_object_unref (abin); + } + + if (vbin != NULL) { + gst_object_unref (vbin); + } + + return FALSE; +} + +gboolean +g_mencoder_play_stream (GMencoder *self) +{ + GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self); + + g_return_val_if_fail (priv->ready == TRUE, FALSE); + + if (gst_element_set_state (priv->pipe, GST_STATE_PLAYING) != GST_STATE_CHANGE_FAILURE) { + g_debug ("PLAYING"); + return TRUE; + } + return FALSE; +} + +gboolean +g_mencoder_pause_stream (GMencoder *self) +{ + GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self); + + g_return_val_if_fail (priv->ready == TRUE, FALSE); + + if (gst_element_set_state (priv->pipe, GST_STATE_PAUSED) != GST_STATE_CHANGE_FAILURE) { + g_debug ("PAUSED"); + return TRUE; + } + return FALSE; +} + +void +g_mencoder_close_stream (GMencoder *self) +{ + + GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (self); + + g_return_if_fail (priv->ready == TRUE); + + gst_element_set_state (priv->pipe, GST_STATE_NULL); + gst_object_unref (priv->pipe); + priv->pipe = NULL; + priv->abin = NULL; + priv->vbin = NULL; + priv->sink = NULL; + priv->ready = FALSE; +} + +static gboolean +_pipeline_bus_cb (GstBus *bus, + GstMessage *msg, + gpointer user_data) +{ + switch (GST_MESSAGE_TYPE (msg)) + { + case GST_MESSAGE_STATE_CHANGED: + { + GstState oldstate; + GstState newstate; + GstState pendingstate; + + GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (user_data); + + gst_message_parse_state_changed (msg, &oldstate, + &newstate, &pendingstate); + + if (pendingstate != GST_STATE_VOID_PENDING) + break; + + if ((oldstate == GST_STATE_READY) && + (newstate == GST_STATE_PAUSED)) { + if (priv->ready) + g_signal_emit (user_data, g_mencoder_signals[PAUSED], 0); + else { + priv->ready = TRUE; + g_signal_emit (user_data, g_mencoder_signals[READY], 0); + } + } else if ((oldstate == GST_STATE_PAUSED) && + (newstate == GST_STATE_PLAYING)) { + g_signal_emit (user_data, g_mencoder_signals[PLAYING], 0); + } else if ((oldstate == GST_STATE_READY) && + (newstate == GST_STATE_NULL)) { + g_signal_emit (user_data, g_mencoder_signals[STOPED], 0); + } + break; + } + case GST_MESSAGE_ERROR: + { + GError *error; + gchar *debug; + gchar *err_str; + + gst_message_parse_error (msg, &error, &debug); + err_str = g_strdup_printf ("Error [%d] %s (%s)", error->code, + error->message, + debug); + g_signal_emit (user_data, g_mencoder_signals[ERROR], 0, err_str); + g_free (err_str); + g_clear_error (&error); + g_free (debug); + break; + } + + case GST_MESSAGE_EOS: + g_signal_emit (user_data, g_mencoder_signals[EOS], 0); + break; + default: + break; + } + return TRUE; +} + +static void +_decodebin_new_pad_cb (GstElement* object, + GstPad* pad, + gboolean flag, + gpointer user_data) +{ + GstCaps *caps; + gchar *str_caps = NULL; + GMencoderPrivate *priv = G_MENCODER_GET_PRIVATE (user_data); + + caps = gst_pad_get_caps (pad); + str_caps = gst_caps_to_string (caps); + g_debug ("CAPS : %s", str_caps); + + if (strstr (str_caps, "audio") != NULL) { + GstPad *apad = gst_element_get_pad (priv->abin, "sink"); + gst_pad_link (pad, apad); + gst_object_unref (apad); + } else if (strstr (str_caps, "video") != NULL) { + GstPad *vpad = gst_element_get_pad (priv->vbin, "sink"); + gst_pad_link (pad, vpad); + gst_object_unref (vpad); + } else { + g_warning ("invalid caps %s", str_caps); + } + + g_free (str_caps); + gst_caps_unref (caps); +} + +static void +_decodebin_unknown_type_cb (GstElement* object, + GstPad* pad, + GstCaps* caps, + gpointer user_data) +{ + g_warning ("Unknown Type"); +} diff -r 747b409e4f01 -r 3219eb5401c0 gmyth-stream/gmemcoder/src/gmencoder.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth-stream/gmemcoder/src/gmencoder.h Mon Apr 23 21:05:21 2007 +0100 @@ -0,0 +1,55 @@ +#ifndef __G_MENCODER_H__ +#define __G_MENCODER_H__ + +#include + +G_BEGIN_DECLS + +typedef struct _GMencoder GMencoder; +typedef struct _GMencoderClass GMencoderClass; + +struct _GMencoderClass { + GObjectClass parent_class; +}; + +struct _GMencoder { + GObject parent; +}; + +/* TYPE MACROS */ +#define G_TYPE_MENCODER \ + (g_mencoder_get_type()) +#define G_MENCODER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_MENCODER, GMencoder)) +#define G_MENCODER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_MENCODER, GMencoderClass)) +#define G_IS_MENCODER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_MENCODER)) +#define G_IS_MENCODER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_MENCODER)) +#define G_MENCODER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), G_TYPE_MENCODER, GMencoderClass)) + + +GType g_mencoder_get_type (void); +GMencoder* g_mencoder_new (void); +gboolean g_mencoder_setup_stream (GMencoder *self, + const gchar* uri, + const gchar* video_encode, + gchar** video_encode_prop, + gdouble video_fps, + gdouble video_rate, + guint video_width, + guint video_height, + const gchar* audio_encode, + gchar** audio_encode_prop, + guint audio_rate, + const gchar* output_element, + gchar** output_prop); +gboolean g_mencoder_play_stream (GMencoder *self); +gboolean g_mencoder_pause_stream (GMencoder *self); +void g_mencoder_close_stream (GMencoder *self); + +G_END_DECLS + +#endif diff -r 747b409e4f01 -r 3219eb5401c0 gmyth-stream/gmemcoder/src/main.c --- a/gmyth-stream/gmemcoder/src/main.c Mon Apr 23 19:16:24 2007 +0100 +++ b/gmyth-stream/gmemcoder/src/main.c Mon Apr 23 21:05:21 2007 +0100 @@ -6,11 +6,24 @@ #include #include -#include "gmemcoder.h" +#include "gmencoder.h" -//#define FILE_OUT 1 +#define FILE_OUT 1 static GMainLoop *mainloop = NULL; +/* Options */ +static gchar* input_file = NULL; +static gchar* video_encode = NULL; +static gchar* video_opts = NULL; +static gdouble video_fps = 0.0; +static gint video_rate = 0; +static gint video_width = 0; +static gint video_height = 0; +static gchar* audio_encode = NULL; +static gchar* audio_opts = NULL; +static double audio_rate = 0.0; +static gchar* output_element = NULL; +static gchar* output_opts = NULL; static void _mencoder_ready_cb (GMencoder *mencoder, gpointer data) @@ -59,22 +72,64 @@ { GMencoder *coder; GIOChannel *ch; + gchar **oopts; + gchar **vopts; + gchar **aopts; + + GOptionContext *context; + static const GOptionEntry options [] = { + {"input-file", 'i', 0, G_OPTION_ARG_STRING, &input_file, "Input File", NULL}, + {"video-encode", 0, 0, G_OPTION_ARG_STRING, &video_encode, "GstElementName for used to video encode", NULL}, + {"video-opts", 0, 0, G_OPTION_ARG_STRING, &video_opts, "Properties to set on video element", NULL}, + {"video-fps", 0, 0, G_OPTION_ARG_DOUBLE, &video_fps, "Video FPS", NULL}, + {"video-rate", 0, 0, G_OPTION_ARG_INT, &video_rate, "Video rate", NULL}, + {"video-width", 0, 0, G_OPTION_ARG_INT, &video_width, "Video width", NULL}, + {"video-height", 0, 0, G_OPTION_ARG_INT, &video_height, "Video height", NULL}, + {"audio-encode", 0, 0, G_OPTION_ARG_STRING, &audio_encode, "GstElementName for use to audio encode", NULL}, + {"audio-opts", 0, 0, G_OPTION_ARG_STRING, &audio_opts, "Properties to set on audio element", NULL}, + {"audio-rate", 0, 0, G_OPTION_ARG_INT, &audio_rate, "Audio rate", NULL}, + {"output-element", 0, 0, G_OPTION_ARG_STRING, &output_element,"GstElementName for use to output", NULL}, + {"output-opts", 0, 0, G_OPTION_ARG_STRING, &output_opts, "Properties to set on output element", NULL}, + { NULL } + }; g_type_init (); + g_thread_init (NULL); + + //g_set_prgname ("gmemcoder"); + context = g_option_context_new (NULL); + g_option_context_set_help_enabled (context, TRUE); + g_option_context_add_main_entries (context, options, NULL); + g_option_context_add_group (context, gst_init_get_option_group ()); + g_option_context_parse (context, &argc, &argv, NULL); + gst_init (&argc, &argv); - g_set_prgname ("gmemcoder"); + if (output_element == NULL) { + g_print ("You need specify output-element name.\nTry --help for more information.\n"); + return 1; + } + + if (input_file == NULL) { + g_print ("You need specify input file\nTry --help for more information.\n"); + } coder = g_mencoder_new (); ch = g_io_channel_unix_new (0); -#ifdef FILE_OUT - int fd = open (argv[2], O_WRONLY | O_CREAT | O_TRUNC); - g_debug ("FD %d", fd); - g_mencoder_setup_stream (coder, argv[1], 320, 288, fd); -#else - g_mencoder_setup_stream (coder, argv[1], 320, 288, atoi (argv[2])); -#endif + aopts = g_strsplit (audio_opts, ",", 0); + vopts = g_strsplit (video_opts, ",", 0); + oopts = g_strsplit (output_opts, ",", 0); + + g_mencoder_setup_stream (coder, + input_file, + video_encode, vopts, video_fps, video_rate, video_width, video_height, + audio_encode, aopts, audio_rate, + output_element, oopts); + + g_strfreev (aopts); + g_strfreev (vopts); + g_strfreev (oopts); mainloop = g_main_loop_new (NULL, FALSE); g_io_add_watch (ch, G_IO_IN, _io_channel_cb, coder); @@ -97,9 +152,5 @@ g_main_loop_run (mainloop); -#if FILE_OUT - close (fd); -#endif - return 0; }