* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include "config.h"
#include <stdio.h>
#include <stdlib.h>
+#ifdef HAVE_GST1
+#include <gst/video/colorbalance.h>
+#else
#include <gst/interfaces/colorbalance.h>
+#endif
#define DEBUG_FLAG EMPATHY_DEBUG_VOIP
#include <libempathy/empathy-debug.h>
GstElement *src;
/* Element implementing a ColorBalance interface */
GstElement *balance;
+ /* Elements for resolution and framerate adjustment */
+ GstElement *capsfilter;
+ GstElement *videorate;
+ guint width;
+ guint height;
+ guint framerate;
};
#define EMPATHY_GST_VIDEO_SRC_GET_PRIVATE(o) \
return NULL;
}
+#ifdef HAVE_GST1
+static GstPadProbeReturn
+empathy_video_src_drop_eos (GstPad *pad,
+ GstPadProbeInfo *info,
+ gpointer user_data)
+{
+ if (GST_EVENT_TYPE (GST_PAD_PROBE_INFO_EVENT (info)) == GST_EVENT_EOS)
+ return GST_PAD_PROBE_DROP;
+
+ return GST_PAD_PROBE_OK;
+}
+#else
+static gboolean
+empathy_video_src_drop_eos (GstPad *pad, GstEvent *event, gpointer user_data)
+{
+ return GST_EVENT_TYPE (event) != GST_EVENT_EOS;
+}
+#endif
static void
empathy_video_src_init (EmpathyGstVideoSrc *obj)
gchar *str;
/* allocate caps here, so we can update it by optional elements */
+#ifdef HAVE_GST1
+ caps = gst_caps_new_simple ("video/x-raw",
+#else
caps = gst_caps_new_simple ("video/x-raw-yuv",
+#endif
"width", G_TYPE_INT, 320,
"height", G_TYPE_INT, 240,
NULL);
/* we need to save our source to priv->src */
priv->src = element;
- /* videomaxrate is optional as it's part of gst-plugins-bad. So don't
- * fail if it doesn't exist. */
+ /* Drop EOS events, so that our sinks don't get confused when we restart the
+ * source (triggering an EOS) */
+ src = gst_element_get_static_pad (element, "src");
+
+#ifdef HAVE_GST1
+ gst_pad_add_probe (src, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM,
+ empathy_video_src_drop_eos, NULL, NULL);
+#else
+ gst_pad_add_event_probe (src, G_CALLBACK (empathy_video_src_drop_eos), NULL);
+#endif
+
+ gst_object_unref (src);
+
+ /* videorate with the required properties optional as it needs a currently
+ * unreleased gst-plugins-base 0.10.36 */
element_back = element;
- if ((element = empathy_gst_add_to_bin (GST_BIN (obj),
- element, "videomaxrate")) == NULL)
+ element = empathy_gst_add_to_bin (GST_BIN (obj), element, "videorate");
+
+ if (element != NULL && g_object_class_find_property (
+ G_OBJECT_GET_CLASS (element), "max-rate") != NULL)
{
- g_message ("Couldn't add \"videomaxrate\" (gst-plugins-bad missing?)");
- element = element_back;
+ priv->videorate = element;
+ g_object_set (G_OBJECT (element),
+ "drop-only", TRUE,
+ "average-period", GST_SECOND/2,
+ NULL);
}
else
{
- gst_caps_set_simple (caps,
- "framerate", GST_TYPE_FRACTION, 15, 1,
- NULL);
+ g_message ("videorate missing or doesn't have max-rate property, not"
+ "doing dynamic framerate changes (Needs gst-plugins-base >= 0.10.36)");
+ /* Refcount owned by the bin */
+ gst_bin_remove (GST_BIN (obj), element);
+ element = element_back;
}
+ gst_caps_set_simple (caps,
+ "framerate", GST_TYPE_FRACTION_RANGE, 1, 1, 30, 1,
+ NULL);
+
str = gst_caps_to_string (caps);
DEBUG ("Current video src caps are : %s", str);
g_free (str);
+#ifdef HAVE_GST1
+ if ((element = empathy_gst_add_to_bin (GST_BIN (obj),
+ element, "videoconvert")) == NULL)
+ g_error ("Failed to add \"videoconvert\" (gst-plugins-base missing?)");
+#else
if ((element = empathy_gst_add_to_bin (GST_BIN (obj),
element, "ffmpegcolorspace")) == NULL)
g_error ("Failed to add \"ffmpegcolorspace\" (gst-plugins-base missing?)");
+#endif
if ((element = empathy_gst_add_to_bin (GST_BIN (obj),
element, "videoscale")) == NULL)
g_error (
"Failed to add \"capsfilter\" (gstreamer core elements missing?)");
+ priv->capsfilter = element;
g_object_set (G_OBJECT (element), "caps", caps, NULL);
return device;
}
+
+void
+empathy_video_src_set_framerate (GstElement *src,
+ guint framerate)
+{
+ EmpathyGstVideoSrcPrivate *priv = EMPATHY_GST_VIDEO_SRC_GET_PRIVATE (src);
+
+ if (priv->videorate)
+ {
+ g_object_set (G_OBJECT (priv->videorate), "max-rate", framerate, NULL);
+ }
+}
+
+void
+empathy_video_src_set_resolution (GstElement *src,
+ guint width,
+ guint height)
+{
+ EmpathyGstVideoSrcPrivate *priv = EMPATHY_GST_VIDEO_SRC_GET_PRIVATE (src);
+ GstCaps *caps;
+ GstPad *srcpad, *peer;
+
+ g_return_if_fail (priv->capsfilter != NULL);
+
+ gst_element_set_locked_state (priv->src, TRUE);
+ gst_element_set_state (priv->src, GST_STATE_NULL);
+
+ srcpad = gst_element_get_static_pad (priv->src, "src");
+ peer = gst_pad_get_peer (srcpad);
+
+ /* Keep a ref as removing it from the bin will loose our reference */
+ gst_object_ref (priv->src);
+ gst_bin_remove (GST_BIN (src), priv->src);
+
+ g_object_get (priv->capsfilter, "caps", &caps, NULL);
+ caps = gst_caps_make_writable (caps);
+
+ gst_caps_set_simple (caps,
+ "width", G_TYPE_INT, width,
+ "height", G_TYPE_INT, height,
+ NULL);
+
+ g_object_set (priv->capsfilter, "caps", caps, NULL);
+ gst_caps_unref (caps);
+
+ gst_bin_add (GST_BIN (src), priv->src);
+ /* We as the bin own the source again, so drop the temporary ref */
+ gst_object_unref (priv->src);
+
+ gst_pad_link (srcpad, peer);
+
+ gst_element_set_locked_state (priv->src, FALSE);
+ gst_element_sync_state_with_parent (priv->src);
+
+ gst_object_unref (srcpad);
+ gst_object_unref (peer);
+}