1 /* GStreamer
2  *
3  * Copyright (C) 2015 Samsung Electronics. All rights reserved.
4  *   Author: Thiago Santos <thiagoss@osg.samsung.com>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21 /* demo for showing v4l2src renegotiating */
22 
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26 
27 #include <gst/gst.h>
28 
29 /* Options */
30 static const gchar *device = "/dev/video0";
31 static const gchar *videosink = "autovideosink";
32 static const gchar *io_mode = "mmap";
33 static const gchar *def_resolutions[] = {
34   "320x240",
35   "1280x720",
36   "640x480",
37   NULL
38 };
39 
40 static const gchar **resolutions = def_resolutions;
41 
42 static GOptionEntry entries[] = {
43   {"device", 'd', 0, G_OPTION_ARG_STRING, &device, "V4L2 Camera Device",
44       NULL},
45   {"videosink", 's', 0, G_OPTION_ARG_STRING, &videosink, "Video Sink to use",
46       NULL},
47   {"io-mode", 'z', 0, G_OPTION_ARG_STRING, &io_mode,
48       "Configure the \"io-mode\" property on v4l2scr", NULL},
49   {"resolution", 'r', 0, G_OPTION_ARG_STRING_ARRAY, &resolutions,
50       "Add a resolution to the list", NULL},
51   {NULL}
52 };
53 
54 static GMainLoop *loop;
55 static GstElement *pipeline;
56 static GstElement *src, *capsfilter;
57 static gint resolution_index = 0;
58 
59 static gboolean
bus_callback(GstBus * bus,GstMessage * message,gpointer data)60 bus_callback (GstBus * bus, GstMessage * message, gpointer data)
61 {
62   switch (message->type) {
63     case GST_MESSAGE_EOS:
64       g_main_loop_quit (loop);
65       break;
66     case GST_MESSAGE_ERROR:{
67       GError *gerror;
68       gchar *debug;
69 
70       gst_message_parse_error (message, &gerror, &debug);
71       gst_object_default_error (GST_MESSAGE_SRC (message), gerror, debug);
72       g_error_free (gerror);
73       g_free (debug);
74       g_main_loop_quit (loop);
75       break;
76     }
77     default:
78       break;
79   }
80 
81   return TRUE;
82 }
83 
84 static gboolean
change_caps(gpointer data)85 change_caps (gpointer data)
86 {
87   GstCaps *caps;
88   GStrv res;
89   gchar *caps_str;
90 
91   if (!resolutions[resolution_index]) {
92     gst_element_send_event (pipeline, gst_event_new_eos ());
93     return FALSE;
94   }
95 
96   g_print ("Setting resolution to '%s'\n", resolutions[resolution_index]);
97 
98   res = g_strsplit (resolutions[resolution_index++], "x", 2);
99   if (!res[0] || !res[1]) {
100     g_warning ("Can't parse resolution: %s", resolutions[resolution_index - 1]);
101     g_strfreev (res);
102     return TRUE;
103   }
104 
105   caps_str = g_strdup_printf ("video/x-raw,width=%s,height=%s", res[0], res[1]);
106   caps = gst_caps_from_string (caps_str);
107   g_object_set (capsfilter, "caps", caps, NULL);
108 
109   g_strfreev (res);
110   g_free (caps_str);
111   gst_caps_unref (caps);
112 
113   return TRUE;
114 }
115 
116 gint
main(gint argc,gchar ** argv)117 main (gint argc, gchar ** argv)
118 {
119   GstBus *bus;
120   GError *error = NULL;
121   GOptionContext *context;
122   gchar *desc;
123   gboolean ret;
124 
125   context = g_option_context_new ("- test v4l2src live renegotition");
126   g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
127   g_option_context_add_group (context, gst_init_get_option_group ());
128   ret = g_option_context_parse (context, &argc, &argv, &error);
129   g_option_context_free (context);
130 
131   if (!ret) {
132     g_print ("option parsing failed: %s\n", error->message);
133     g_error_free (error);
134     return 1;
135   }
136 
137   loop = g_main_loop_new (NULL, FALSE);
138 
139   desc = g_strdup_printf ("v4l2src name=src device=\"%s\" io-mode=\"%s\" "
140       "! capsfilter name=cf ! %s", device, io_mode, videosink);
141   pipeline = gst_parse_launch (desc, &error);
142   g_free (desc);
143   if (!pipeline) {
144     g_print ("failed to create pipeline: %s", error->message);
145     g_error_free (error);
146     return 1;
147   }
148 
149   src = gst_bin_get_by_name (GST_BIN (pipeline), "src");
150   capsfilter = gst_bin_get_by_name (GST_BIN (pipeline), "cf");
151 
152   bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
153   gst_bus_add_watch (bus, bus_callback, NULL);
154   gst_object_unref (bus);
155 
156   change_caps (NULL);
157 
158   /* play and wait */
159   gst_element_set_state (pipeline, GST_STATE_PLAYING);
160 
161   g_timeout_add_seconds (3, change_caps, NULL);
162 
163   /* mainloop and wait for eos */
164   g_main_loop_run (loop);
165 
166   /* stop and cleanup */
167   gst_element_set_state (pipeline, GST_STATE_NULL);
168   gst_object_unref (src);
169   gst_object_unref (capsfilter);
170   gst_object_unref (GST_OBJECT (pipeline));
171   g_main_loop_unref (loop);
172   return 0;
173 }
174