Remove autotools build
[platform/upstream/gstreamer.git] / tests / examples / test-roi.c
1 /*
2  *  test-roi.c - Testsuite for Region of Interest
3  *
4  *  Copyright (C) 2017 Intel Corporation
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Lesser General Public License
8  *  as published by the Free Software Foundation; either version 2.1
9  *  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  *  Lesser General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Lesser General Public
17  *  License along with this library; if not, write to the Free
18  *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  *  Boston, MA 02110-1301 USA
20  */
21
22 #include <stdio.h>
23 #include <gst/gst.h>
24 #include <gst/video/navigation.h>
25 #include <gst/video/gstvideometa.h>
26
27 typedef struct _CustomData
28 {
29   GstElement *pipeline;
30   GMainLoop *loop;
31   gboolean roi_enabled;
32 } AppData;
33
34 static void
35 send_eos_event (AppData * data)
36 {
37   gst_element_send_event (data->pipeline, gst_event_new_eos ());
38 }
39
40 static void
41 dispatch_keystroke (AppData * app, const gchar * str)
42 {
43   switch (g_ascii_tolower (str[0])) {
44     case 'r':
45       app->roi_enabled = !app->roi_enabled;
46       gst_println ("ROI %s", app->roi_enabled ? "enabled" : "disabled");
47       break;
48     case 'q':
49       send_eos_event (app);
50       break;
51     default:
52       break;
53   }
54
55   return;
56 }
57
58 static void
59 cb_msg (GstBus * bus, GstMessage * msg, gpointer data)
60 {
61   AppData *app = data;
62   GstNavigationMessageType mtype = gst_navigation_message_get_type (msg);
63   GstEvent *ev = NULL;
64   GstNavigationEventType type;
65   const gchar *key;
66
67   if (mtype != GST_NAVIGATION_MESSAGE_EVENT)
68     return;
69   if (!gst_navigation_message_parse_event (msg, &ev))
70     goto bail;
71
72   type = gst_navigation_event_get_type (ev);
73   if (type != GST_NAVIGATION_EVENT_KEY_PRESS)
74     goto bail;
75   if (!gst_navigation_event_parse_key_event (ev, &key))
76     goto bail;
77
78   dispatch_keystroke (app, key);
79
80 bail:
81   if (ev)
82     gst_event_unref (ev);
83 }
84
85 static void
86 cb_msg_eos (GstBus * bus, GstMessage * msg, gpointer data)
87 {
88   AppData *app = data;
89   g_main_loop_quit (app->loop);
90 }
91
92
93 static void
94 cb_msg_error (GstBus * bus, GstMessage * msg, gpointer data)
95 {
96   AppData *app = data;
97   gchar *debug = NULL;
98   GError *err = NULL;
99
100   gst_message_parse_error (msg, &err, &debug);
101
102   g_print ("Error: %s\n", err->message);
103   g_error_free (err);
104
105   if (debug) {
106     g_print ("Debug details: %s\n", debug);
107     g_free (debug);
108   }
109
110   g_main_loop_quit (app->loop);
111 }
112
113 static GstPadProbeReturn
114 cb_add_roi (GstPad * pad, GstPadProbeInfo * info, gpointer data)
115 {
116   AppData *app = data;
117   GstVideoRegionOfInterestMeta *rmeta;
118   GstBuffer *buf = GST_PAD_PROBE_INFO_BUFFER (info);
119   GstStructure *s;
120
121   if (!app->roi_enabled)
122     return GST_PAD_PROBE_OK;
123
124   buf = gst_buffer_make_writable (buf);
125   if (!buf)
126     return GST_PAD_PROBE_OK;
127
128   rmeta =
129       gst_buffer_add_video_region_of_interest_meta (buf, "test", 0, 0, 320,
130       240);
131   if (!rmeta)
132     return GST_PAD_PROBE_OK;
133
134   s = gst_structure_new ("roi/vaapi", "delta-qp", G_TYPE_INT, -10, NULL);
135   gst_video_region_of_interest_meta_add_param (rmeta, s);
136
137   GST_PAD_PROBE_INFO_DATA (info) = buf;
138   return GST_PAD_PROBE_OK;
139 }
140
141 /* Process keyboard input */
142 static gboolean
143 handle_keyboard (GIOChannel * source, GIOCondition cond, gpointer data)
144 {
145   AppData *app = data;
146   gchar *str = NULL;
147
148   if (g_io_channel_read_line (source, &str, NULL, NULL,
149           NULL) != G_IO_STATUS_NORMAL) {
150     return TRUE;
151   }
152
153   dispatch_keystroke (app, str);
154
155   g_free (str);
156   return TRUE;
157 }
158
159 /*
160  * This is an example pipeline to recognize difference between ROI and non-ROI.
161  * 1. Produce snow pattern with 320p
162  * 2. Encode and decode the raw data with 2 pipelines at same time.
163  *    2.1. Insert GstVideoRegionOfInterestMeta to the 2nd pipeline buffers to enable ROI.
164  * 3. Mix both streams in videomixer.
165  * 5. Output the result in one window.
166  *
167  * Note that the higher definition of original raw data, the easier we
168  * recognize.  So you can replace videotestsrc with your
169  * high-definition camera or other src elements.
170  */
171
172 /*
173 .----------.  .---.     .--------.  .---.  .---.  .---.  .--------.  .----------.  .-----.
174 | videosrc |->|tee|->Q->|txtovrly|->|enc|->|dec|->|vpp|->|videobox|->|videomixer|->|vsink|
175 '----------'  '---'     '--------'  '---'  '---'  '---'  '--------'  '----------'  '-----'
176                 ^                                                    ^
177                 |                                                    |
178                 |       .--------.  .---.  .---.  .---.  .--------.  |
179                 '--->Q->|txtovrly|->|enc|->|dec|->|vpp|->|videobox|->'
180                      ^  '--------'  '---'  '---'  '---'  '--------'
181                      |
182                      '-- Insert GstVideoRegionOfInterestMeta width roit/vaapi params on buffers
183 */
184
185 int
186 main (int argc, char *argv[])
187 {
188   AppData data = { 0, };
189   GstStateChangeReturn ret;
190   GstElement *el;
191   GstPad *pad;
192   GError *err = NULL;
193   GIOChannel *io_stdin;
194   GstBus *bus;
195
196   data.roi_enabled = TRUE;
197
198   /* Initialize GStreamer */
199   gst_init (&argc, &argv);
200
201   /* Print usage map */
202   g_print ("USAGE: 'r' to enable/disable ROI && 'q' to quit\n");
203
204 #define SRC "videotestsrc pattern=snow ! " \
205             "video/x-raw, format=NV12, width=320, framerate=5/1"
206 #define ENCDEC "vaapih265enc rate-control=cbr bitrate=2000 ! vaapih265dec ! " \
207                "vaapipostproc ! video/x-raw, width=640"
208 #define TEXT "textoverlay font-desc=\"Arial Bold 48\" "
209
210   data.pipeline =
211       gst_parse_launch
212       ("videomixer name=mix ! vaapipostproc ! vaapisink sync=false "
213       SRC " ! tee name=t ! queue ! " TEXT " text=\"non-ROI\" ! " ENCDEC
214       " ! videobox left=-640 ! mix. "
215       " t. ! queue name=roi ! " TEXT " text=\"ROI\" ! " ENCDEC
216       " ! videobox ! mix.", &err);
217
218   if (err) {
219     g_printerr ("failed to parse pipeline: %s\n", err->message);
220     g_error_free (err);
221     return -1;
222   }
223
224   bus = gst_pipeline_get_bus (GST_PIPELINE (data.pipeline));
225   gst_bus_add_signal_watch_full (bus, G_PRIORITY_HIGH);
226   gst_bus_enable_sync_message_emission (bus);
227   g_signal_connect (bus, "message::error", G_CALLBACK (cb_msg_error), &data);
228   g_signal_connect (bus, "message::eos", G_CALLBACK (cb_msg_eos), &data);
229   g_signal_connect (bus, "message::element", G_CALLBACK (cb_msg), &data);
230   gst_object_unref (bus);
231
232   el = gst_bin_get_by_name (GST_BIN (data.pipeline), "roi");
233   pad = gst_element_get_static_pad (el, "src");
234   gst_object_unref (el);
235   gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER, cb_add_roi, &data, NULL);
236   gst_object_unref (pad);
237
238   /* Add a keyboard watch so we get notified of keystrokes */
239   io_stdin = g_io_channel_unix_new (fileno (stdin));
240   g_io_add_watch (io_stdin, G_IO_IN, handle_keyboard, &data);
241
242   /* Start playing */
243   ret = gst_element_set_state (data.pipeline, GST_STATE_PLAYING);
244   if (ret == GST_STATE_CHANGE_FAILURE) {
245     g_printerr ("Unable to set the pipeline to the playing state.\n");
246     gst_object_unref (data.pipeline);
247     return -1;
248   }
249
250   /* Create a GLib Main Loop and set it to run */
251   data.loop = g_main_loop_new (NULL, FALSE);
252   g_main_loop_run (data.loop);
253
254   /* Free resources */
255   g_main_loop_unref (data.loop);
256   gst_element_set_state (data.pipeline, GST_STATE_NULL);
257   gst_object_unref (data.pipeline);
258   g_io_channel_unref (io_stdin);
259
260   return 0;
261 }