diff options
-rw-r--r-- | tests/elements/test-roi.c | 200 |
1 files changed, 137 insertions, 63 deletions
diff --git a/tests/elements/test-roi.c b/tests/elements/test-roi.c index 2818a10e..2ce614ef 100644 --- a/tests/elements/test-roi.c +++ b/tests/elements/test-roi.c @@ -20,55 +20,129 @@ */ #include <stdio.h> -#include <string.h> #include <gst/gst.h> +#include <gst/video/navigation.h> +#include <gst/video/gstvideometa.h> typedef struct _CustomData { GstElement *pipeline; - GstPad *src_pad; GMainLoop *loop; + gboolean roi_enabled; } AppData; static void -send_roi_event (AppData * data) +send_eos_event (AppData * data) { - gboolean res = FALSE; - GstEvent *event; - gint value[2] = { 4, 0 }; - static gint counter = 0; - - event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM_OOB, - gst_structure_new ("GstVaapiEncoderRegionOfInterest", - "roi-x", G_TYPE_UINT, 0, - "roi-y", G_TYPE_UINT, 0, - "roi-width", G_TYPE_UINT, 320, - "roi-height", G_TYPE_UINT, 240, - "roi-value", G_TYPE_INT, value[counter++ % 2], NULL)); - - /* Send the event */ - res = gst_pad_push_event (data->src_pad, event); - g_print ("Sending event %p done: %d\n", event, res); + gst_element_send_event (data->pipeline, gst_event_new_eos ()); } static void -send_eos_event (AppData * data) +dispatch_keystroke (AppData * app, const gchar * str) { - GstBus *bus; - GstMessage *msg; + switch (g_ascii_tolower (str[0])) { + case 'r': + app->roi_enabled = !app->roi_enabled; + gst_println ("ROI %s", app->roi_enabled ? "enabled" : "disabled"); + break; + case 'q': + send_eos_event (app); + break; + default: + break; + } - bus = gst_element_get_bus (data->pipeline); - gst_element_send_event (data->pipeline, gst_event_new_eos ()); - msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_EOS); + return; +} - gst_message_unref (msg); - gst_object_unref (bus); +static void +cb_msg (GstBus * bus, GstMessage * msg, gpointer data) +{ + AppData *app = data; + GstNavigationMessageType mtype = gst_navigation_message_get_type (msg); + GstEvent *ev = NULL; + GstNavigationEventType type; + const gchar *key; + + if (mtype != GST_NAVIGATION_MESSAGE_EVENT) + return; + if (!gst_navigation_message_parse_event (msg, &ev)) + goto bail; + + type = gst_navigation_event_get_type (ev); + if (type != GST_NAVIGATION_EVENT_KEY_PRESS) + goto bail; + if (!gst_navigation_event_parse_key_event (ev, &key)) + goto bail; + + dispatch_keystroke (app, key); + +bail: + if (ev) + gst_event_unref (ev); +} + +static void +cb_msg_eos (GstBus * bus, GstMessage * msg, gpointer data) +{ + AppData *app = data; + g_main_loop_quit (app->loop); +} + + +static void +cb_msg_error (GstBus * bus, GstMessage * msg, gpointer data) +{ + AppData *app = data; + gchar *debug = NULL; + GError *err = NULL; + + gst_message_parse_error (msg, &err, &debug); + + g_print ("Error: %s\n", err->message); + g_error_free (err); + + if (debug) { + g_print ("Debug details: %s\n", debug); + g_free (debug); + } + + g_main_loop_quit (app->loop); +} + +static GstPadProbeReturn +cb_add_roi (GstPad * pad, GstPadProbeInfo * info, gpointer data) +{ + AppData *app = data; + GstVideoRegionOfInterestMeta *rmeta; + GstBuffer *buf = GST_PAD_PROBE_INFO_BUFFER (info); + GstStructure *s; + + if (!app->roi_enabled) + return GST_PAD_PROBE_OK; + + buf = gst_buffer_make_writable (buf); + if (!buf) + return GST_PAD_PROBE_OK; + + rmeta = + gst_buffer_add_video_region_of_interest_meta (buf, "test", 0, 0, 320, + 240); + if (!rmeta) + return GST_PAD_PROBE_OK; + + s = gst_structure_new ("roi/vaapi", "delta-qp", G_TYPE_INT, -10, NULL); + gst_video_region_of_interest_meta_add_param (rmeta, s); + + GST_PAD_PROBE_INFO_DATA (info) = buf; + return GST_PAD_PROBE_OK; } /* Process keyboard input */ static gboolean -handle_keyboard (GIOChannel * source, GIOCondition cond, AppData * data) +handle_keyboard (GIOChannel * source, GIOCondition cond, gpointer data) { + AppData *app = data; gchar *str = NULL; if (g_io_channel_read_line (source, &str, NULL, NULL, @@ -76,20 +150,9 @@ handle_keyboard (GIOChannel * source, GIOCondition cond, AppData * data) return TRUE; } - switch (g_ascii_tolower (str[0])) { - case 'r': - send_roi_event (data); - break; - case 'q': - send_eos_event (data); - g_main_loop_quit (data->loop); - break; - default: - break; - } + dispatch_keystroke (app, str); g_free (str); - return TRUE; } @@ -97,7 +160,7 @@ handle_keyboard (GIOChannel * source, GIOCondition cond, AppData * data) * This is an example pipeline to recognize difference between ROI and non-ROI. * 1. Produce snow pattern with 320p * 2. Encode and decode the raw data with 2 pipelines at same time. - * 2.1. Inject a GstCustomEvent to the 2nd pipeline to enable ROI. + * 2.1. Insert GstVideoRegionOfInterestMeta to the 2nd pipeline buffers to enable ROI. * 3. Mix both streams in videomixer. * 5. Output the result in one window. * @@ -116,37 +179,41 @@ handle_keyboard (GIOChannel * source, GIOCondition cond, AppData * data) '--->Q->|txtovrly|->|enc|->|dec|->|vpp|->|videobox|->' ^ '--------' '---' '---' '---' '--------' | - '-- Injection of GstCustomEvent "GstVaapiEncoderRegionOfInterest" + '-- Insert GstVideoRegionOfInterestMeta width roit/vaapi params on buffers */ int main (int argc, char *argv[]) { - AppData data; + AppData data = { 0, }; GstStateChangeReturn ret; - GstElement *q; - GIOChannel *io_stdin; + GstElement *el; + GstPad *pad; GError *err = NULL; + GIOChannel *io_stdin; + GstBus *bus; + + data.roi_enabled = TRUE; /* Initialize GStreamer */ gst_init (&argc, &argv); /* Print usage map */ - g_print ("USAGE: Choose one of the following options, then press enter:\n" - " 'r' to send ROI event \n" " 'q' to quit\n"); + g_print ("USAGE: 'r' to enable/disable ROI && 'q' to quit\n"); -#define ENCDEC "vaapih264enc rate-control=cbr bitrate=2000 ! vaapih264dec ! vaapipostproc width=640 " -#define TEXT "textoverlay font-desc=\"Arial Bold 48\" text=" +#define SRC "videotestsrc pattern=snow ! " \ + "video/x-raw, format=NV12, width=320, framerate=5/1" +#define ENCDEC "vaapih265enc rate-control=cbr bitrate=2000 ! vaapih265dec ! " \ + "vaapipostproc ! video/x-raw, width=640" +#define TEXT "textoverlay font-desc=\"Arial Bold 48\" " data.pipeline = gst_parse_launch ("videomixer name=mix ! vaapipostproc ! vaapisink sync=false " - "videotestsrc pattern=snow ! video/x-raw, width=320, framerate=5/1 " - "! tee name=t " - "t. ! queue ! " TEXT "\"non-ROI\" ! " ENCDEC - "! videobox left=-640 ! mix. " - "t. ! queue name=roi ! " TEXT "\"ROI\" ! " ENCDEC - "! videobox ! mix.", &err); + SRC " ! tee name=t ! queue ! " TEXT " text=\"non-ROI\" ! " ENCDEC + " ! videobox left=-640 ! mix. " + " t. ! queue name=roi ! " TEXT " text=\"ROI\" ! " ENCDEC + " ! videobox ! mix.", &err); if (err) { g_printerr ("failed to parse pipeline: %s\n", err->message); @@ -154,13 +221,23 @@ main (int argc, char *argv[]) return -1; } - q = gst_bin_get_by_name (GST_BIN (data.pipeline), "roi"); - data.src_pad = gst_element_get_static_pad (q, "src"); - gst_object_unref (q); + bus = gst_pipeline_get_bus (GST_PIPELINE (data.pipeline)); + gst_bus_add_signal_watch_full (bus, G_PRIORITY_HIGH); + gst_bus_enable_sync_message_emission (bus); + g_signal_connect (bus, "message::error", G_CALLBACK (cb_msg_error), &data); + g_signal_connect (bus, "message::eos", G_CALLBACK (cb_msg_eos), &data); + g_signal_connect (bus, "message::element", G_CALLBACK (cb_msg), &data); + gst_object_unref (bus); + + el = gst_bin_get_by_name (GST_BIN (data.pipeline), "roi"); + pad = gst_element_get_static_pad (el, "src"); + gst_object_unref (el); + gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER, cb_add_roi, &data, NULL); + gst_object_unref (pad); /* Add a keyboard watch so we get notified of keystrokes */ io_stdin = g_io_channel_unix_new (fileno (stdin)); - g_io_add_watch (io_stdin, G_IO_IN, (GIOFunc) handle_keyboard, &data); + g_io_add_watch (io_stdin, G_IO_IN, handle_keyboard, &data); /* Start playing */ ret = gst_element_set_state (data.pipeline, GST_STATE_PLAYING); @@ -176,12 +253,9 @@ main (int argc, char *argv[]) /* Free resources */ g_main_loop_unref (data.loop); - g_io_channel_unref (io_stdin); gst_element_set_state (data.pipeline, GST_STATE_NULL); - - if (data.src_pad) - gst_object_unref (data.src_pad); gst_object_unref (data.pipeline); + g_io_channel_unref (io_stdin); return 0; } |