From 4e8ad583022671c54369d3b4f064757f794e48ad Mon Sep 17 00:00:00 2001 From: Nicolas Dufresne Date: Fri, 27 Feb 2015 13:03:42 -0300 Subject: [PATCH] examples: v4l2: add example for v4l2src renegotiation Based on work from Thiago Santos https://bugzilla.gnome.org/show_bug.cgi?id=682770 --- tests/examples/v4l2/Makefile.am | 6 +- tests/examples/v4l2/meson.build | 6 + tests/examples/v4l2/v4l2src-renegotiate.c | 169 ++++++++++++++++++++++ 3 files changed, 180 insertions(+), 1 deletion(-) create mode 100644 tests/examples/v4l2/v4l2src-renegotiate.c diff --git a/tests/examples/v4l2/Makefile.am b/tests/examples/v4l2/Makefile.am index 3f80c9e3c0..1fb4165d0f 100644 --- a/tests/examples/v4l2/Makefile.am +++ b/tests/examples/v4l2/Makefile.am @@ -1,5 +1,9 @@ -noinst_PROGRAMS = camctrl +noinst_PROGRAMS = camctrl v4l2src-renegotiate camctrl_SOURCES = camctrl.c camctrl_CFLAGS = $(GST_BASE_CFLAGS) $(GST_CONTROLLER_CFLAGS) $(GST_CFLAGS) camctrl_LDADD = $(GST_BASE_LIBS) $(GST_CONTROLLER_LIBS) $(GST_LIBS) + +v4l2src_renegotiate_SOURCES = v4l2src-renegotiate.c +v4l2src_renegotiate_CFLAGS = $(GST_BASE_CFLAGS) $(GST_CFLAGS) +v4l2src_renegotiate_LDADD = $(GST_BASE_LIBS) $(GST_LIBS) diff --git a/tests/examples/v4l2/meson.build b/tests/examples/v4l2/meson.build index 5507d86761..d59d000e3e 100644 --- a/tests/examples/v4l2/meson.build +++ b/tests/examples/v4l2/meson.build @@ -3,3 +3,9 @@ executable('camctrl', 'camctrl.c', c_args : gst_plugins_good_args, include_directories : [configinc], install: false) + +executable('v4l2src-renegotiate', 'v4l2src-renegotiate.c', + dependencies: [gst_dep], + c_args : gst_plugins_good_args, + include_directories : [configinc], + install: false) diff --git a/tests/examples/v4l2/v4l2src-renegotiate.c b/tests/examples/v4l2/v4l2src-renegotiate.c new file mode 100644 index 0000000000..c56dde8cba --- /dev/null +++ b/tests/examples/v4l2/v4l2src-renegotiate.c @@ -0,0 +1,169 @@ +/* GStreamer + * + * Copyright (C) 2015 Samsung Electronics. All rights reserved. + * Author: Thiago Santos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +/* demo for showing v4l2src renegotiating */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +/* Options */ +static gchar *device = "/dev/video0"; +static gchar *videosink = "autovideosink"; +static gboolean enable_dmabuf = FALSE; +static gchar *def_resolutions[] = { + "320x240", + "1280x720", + "640x480", + NULL +}; + +static gchar **resolutions = def_resolutions; + +static GOptionEntry entries[] = { + {"device", 'd', 0, G_OPTION_ARG_STRING, &device, "V4L2 Camera Device", + NULL}, + {"videosink", 's', 0, G_OPTION_ARG_STRING, &videosink, "Video Sink to use", + NULL}, + {"enable-dmabuf", 'z', 0, G_OPTION_ARG_NONE, &enable_dmabuf, + "Enable DMABuf", NULL}, + {"resolution", 'r', 0, G_OPTION_ARG_STRING_ARRAY, &resolutions, + "Add a resolution to the list", NULL}, + {NULL} +}; + +static GMainLoop *loop; +static GstElement *pipeline; +static GstElement *src, *capsfilter; +static gint index = 0; + +static gboolean +bus_callback (GstBus * bus, GstMessage * message, gpointer data) +{ + switch (message->type) { + case GST_MESSAGE_EOS: + g_main_loop_quit (loop); + break; + case GST_MESSAGE_ERROR:{ + GError *gerror; + gchar *debug; + + gst_message_parse_error (message, &gerror, &debug); + gst_object_default_error (GST_MESSAGE_SRC (message), gerror, debug); + g_error_free (gerror); + g_free (debug); + g_main_loop_quit (loop); + break; + } + default: + break; + } + + return TRUE; +} + +static gboolean +change_caps (gpointer data) +{ + GstCaps *caps; + GStrv res; + gchar *caps_str; + + if (!resolutions[index]) { + gst_element_send_event (pipeline, gst_event_new_eos ()); + return FALSE; + } + + g_print ("Setting resolution to '%s'\n", resolutions[index]); + + res = g_strsplit (resolutions[index++], "x", 2); + if (!res[0] || !res[1]) { + g_warning ("Can't parse resolution: %s", resolutions[index - 1]); + g_strfreev (res); + return TRUE; + } + + caps_str = g_strdup_printf ("video/x-raw,width=%s,height=%s", res[0], res[1]); + caps = gst_caps_from_string (caps_str); + g_object_set (capsfilter, "caps", caps, NULL); + + g_strfreev (res); + g_free (caps_str); + gst_caps_unref (caps); + + return TRUE; +} + +gint +main (gint argc, gchar ** argv) +{ + GstBus *bus; + GError *error = NULL; + GOptionContext *context; + gchar *desc; + + context = g_option_context_new ("- test v4l2src live renegotition"); + g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE); + g_option_context_add_group (context, gst_init_get_option_group ()); + if (!g_option_context_parse (context, &argc, &argv, &error)) { + g_print ("option parsing failed: %s\n", error->message); + g_error_free (error); + return 1; + } + + loop = g_main_loop_new (NULL, FALSE); + + desc = g_strdup_printf ("v4l2src name=src device=\"%s\" io-mode=\"%s\" " + "! capsfilter name=cf ! %s", device, enable_dmabuf ? "dmabuf" : "mmap", + videosink); + pipeline = gst_parse_launch (desc, &error); + if (!pipeline) { + g_print ("failed to create pipeline: %s", error->message); + g_error_free (error); + return 1; + } + + src = gst_bin_get_by_name (GST_BIN (pipeline), "src"); + capsfilter = gst_bin_get_by_name (GST_BIN (pipeline), "cf"); + + bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); + gst_bus_add_watch (bus, bus_callback, NULL); + gst_object_unref (bus); + + change_caps (NULL); + + /* play and wait */ + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + g_timeout_add_seconds (3, change_caps, NULL); + + /* mainloop and wait for eos */ + g_main_loop_run (loop); + + /* stop and cleanup */ + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (src); + gst_object_unref (capsfilter); + gst_object_unref (GST_OBJECT (pipeline)); + g_main_loop_unref (loop); + return 0; +}