2 * test-roi.c - Testsuite for Region of Interest
4 * Copyright (C) 2017 Intel Corporation
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.
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.
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
24 #include <gst/video/navigation.h>
25 #include <gst/video/gstvideometa.h>
27 typedef struct _CustomData
35 send_eos_event (AppData * data)
37 gst_element_send_event (data->pipeline, gst_event_new_eos ());
41 dispatch_keystroke (AppData * app, const gchar * str)
43 switch (g_ascii_tolower (str[0])) {
45 app->roi_enabled = !app->roi_enabled;
46 gst_println ("ROI %s", app->roi_enabled ? "enabled" : "disabled");
59 cb_msg (GstBus * bus, GstMessage * msg, gpointer data)
62 GstNavigationMessageType mtype = gst_navigation_message_get_type (msg);
64 GstNavigationEventType type;
67 if (mtype != GST_NAVIGATION_MESSAGE_EVENT)
69 if (!gst_navigation_message_parse_event (msg, &ev))
72 type = gst_navigation_event_get_type (ev);
73 if (type != GST_NAVIGATION_EVENT_KEY_PRESS)
75 if (!gst_navigation_event_parse_key_event (ev, &key))
78 dispatch_keystroke (app, key);
86 cb_msg_eos (GstBus * bus, GstMessage * msg, gpointer data)
89 g_main_loop_quit (app->loop);
94 cb_msg_error (GstBus * bus, GstMessage * msg, gpointer data)
100 gst_message_parse_error (msg, &err, &debug);
102 g_print ("Error: %s\n", err->message);
106 g_print ("Debug details: %s\n", debug);
110 g_main_loop_quit (app->loop);
113 static GstPadProbeReturn
114 cb_add_roi (GstPad * pad, GstPadProbeInfo * info, gpointer data)
117 GstVideoRegionOfInterestMeta *rmeta;
118 GstBuffer *buf = GST_PAD_PROBE_INFO_BUFFER (info);
121 if (!app->roi_enabled)
122 return GST_PAD_PROBE_OK;
124 buf = gst_buffer_make_writable (buf);
126 return GST_PAD_PROBE_OK;
129 gst_buffer_add_video_region_of_interest_meta (buf, "test", 0, 0, 320,
132 return GST_PAD_PROBE_OK;
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);
137 GST_PAD_PROBE_INFO_DATA (info) = buf;
138 return GST_PAD_PROBE_OK;
141 /* Process keyboard input */
143 handle_keyboard (GIOChannel * source, GIOCondition cond, gpointer data)
148 if (g_io_channel_read_line (source, &str, NULL, NULL,
149 NULL) != G_IO_STATUS_NORMAL) {
153 dispatch_keystroke (app, str);
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.
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.
173 .----------. .---. .--------. .---. .---. .---. .--------. .----------. .-----.
174 | videosrc |->|tee|->Q->|txtovrly|->|enc|->|dec|->|vpp|->|videobox|->|videomixer|->|vsink|
175 '----------' '---' '--------' '---' '---' '---' '--------' '----------' '-----'
178 | .--------. .---. .---. .---. .--------. |
179 '--->Q->|txtovrly|->|enc|->|dec|->|vpp|->|videobox|->'
180 ^ '--------' '---' '---' '---' '--------'
182 '-- Insert GstVideoRegionOfInterestMeta width roit/vaapi params on buffers
186 main (int argc, char *argv[])
188 AppData data = { 0, };
189 GstStateChangeReturn ret;
193 GIOChannel *io_stdin;
196 data.roi_enabled = TRUE;
198 /* Initialize GStreamer */
199 gst_init (&argc, &argv);
201 /* Print usage map */
202 g_print ("USAGE: 'r' to enable/disable ROI && 'q' to quit\n");
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\" "
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);
219 g_printerr ("failed to parse pipeline: %s\n", err->message);
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);
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);
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);
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);
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);
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);