From eceae4e5f7932f829143b16cbd3f86f56b5692b2 Mon Sep 17 00:00:00 2001 From: "jy1210.jung" Date: Fri, 13 Jul 2018 16:49:41 +0900 Subject: [PATCH] [Sink/Example] change sink caps / property 1. change sink pad caps (any > other/tensor) 2. change property type and name (signal-rate) 3. remove unnecessary functions and params 4. add testcase for caps nego failed **Self evaluation:** 1. Build test: [*]Passed [ ]Failed [ ]Skipped 2. Run test: [*]Passed [ ]Failed [ ]Skipped Signed-off-by: Jaeyun Jung --- gst/tensor_sink/tensor_sink.c | 116 ++++++-------- gst/tensor_sink/tensor_sink.h | 12 +- .../example_cam/nnstreamer_example_cam.c | 22 +-- .../example_sink/nnstreamer_sink_example.c | 164 ++++++++++--------- .../example_sink/nnstreamer_sink_example_play.c | 174 ++++++++++----------- tests/nnstreamer_sink/unittest_sink.cpp | 169 +++++++++----------- 6 files changed, 326 insertions(+), 331 deletions(-) diff --git a/gst/tensor_sink/tensor_sink.c b/gst/tensor_sink/tensor_sink.c index aad7c27..e96a0cc 100644 --- a/gst/tensor_sink/tensor_sink.c +++ b/gst/tensor_sink/tensor_sink.c @@ -1,8 +1,8 @@ -/* +/** * GStreamer * Copyright (C) 2005 Thomas Vander Stichele * Copyright (C) 2005 Ronald S. Bultje - * Copyright (C) 2018 nnstreamer + * Copyright (C) 2018 Samsung Electronics Co., Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -13,7 +13,6 @@ * 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. - * */ /** @@ -24,7 +23,7 @@ * @file tensor_sink.c * @date 15 June 2018 * @brief GStreamer plugin to handle tensor stream - * @see http://github.com/TO-BE-DETERMINED-SOON + * @see http://github.com/nnsuite/nnstreamer * @see https://github.sec.samsung.net/STAR/nnstreamer * @author Jaeyun Jung * @bug No known bugs except for NYI items @@ -50,7 +49,7 @@ GST_DEBUG_CATEGORY_STATIC (gst_tensor_sink_debug); #define GST_CAT_DEFAULT gst_tensor_sink_debug -/* signals and args */ +/** signals and args */ enum { SIGNAL_NEW_DATA, @@ -62,7 +61,7 @@ enum enum { PROP_0, - PROP_RENDER_RATE, + PROP_SIGNAL_RATE, PROP_EMIT_SIGNAL, PROP_SILENT }; @@ -73,9 +72,9 @@ enum #define DEFAULT_EMIT_SIGNAL TRUE /** - * @brief Buffers rendered per second. + * @brief New data signals per second. */ -#define DEFAULT_RENDER_RATE 0 +#define DEFAULT_SIGNAL_RATE 0 /** * @brief Flag to print minimized log. @@ -110,14 +109,14 @@ enum static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, - GST_STATIC_CAPS_ANY); + GST_STATIC_CAPS (GST_TENSOR_CAP_DEFAULT)); /** * @brief Variable for signal ids. */ static guint _tensor_sink_signals[LAST_SIGNAL] = { 0 }; -/* GObject method implementation */ +/** GObject method implementation */ static void gst_tensor_sink_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); static void gst_tensor_sink_get_property (GObject * object, guint prop_id, @@ -125,7 +124,7 @@ static void gst_tensor_sink_get_property (GObject * object, guint prop_id, static void gst_tensor_sink_dispose (GObject * object); static void gst_tensor_sink_finalize (GObject * object); -/* GstBaseSink method implementation */ +/** GstBaseSink method implementation */ static gboolean gst_tensor_sink_start (GstBaseSink * sink); static gboolean gst_tensor_sink_stop (GstBaseSink * sink); static gboolean gst_tensor_sink_event (GstBaseSink * sink, GstEvent * event); @@ -137,26 +136,24 @@ static GstFlowReturn gst_tensor_sink_render_list (GstBaseSink * sink, static gboolean gst_tensor_sink_set_caps (GstBaseSink * sink, GstCaps * caps); static GstCaps *gst_tensor_sink_get_caps (GstBaseSink * sink, GstCaps * filter); -/* internal functions */ +/** internal functions */ static void _tensor_sink_render_buffer (GstTensorSink * self, GstBuffer * buffer); static void _tensor_sink_set_last_render_time (GstTensorSink * self, GstClockTime now); static GstClockTime _tensor_sink_get_last_render_time (GstTensorSink * self); -static void _tensor_sink_set_render_rate (GstTensorSink * self, guint64 rate); -static guint64 _tensor_sink_get_render_rate (GstTensorSink * self); +static void _tensor_sink_set_signal_rate (GstTensorSink * self, guint rate); +static guint _tensor_sink_get_signal_rate (GstTensorSink * self); static void _tensor_sink_set_emit_signal (GstTensorSink * self, gboolean emit); static gboolean _tensor_sink_get_emit_signal (GstTensorSink * self); static void _tensor_sink_set_silent (GstTensorSink * self, gboolean silent); static gboolean _tensor_sink_get_silent (GstTensorSink * self); -/* functions to initialize */ -static void _tensor_sink_do_init (GType type); +/** functions to initialize */ static gboolean _tensor_sink_plugin_init (GstPlugin * plugin); #define gst_tensor_sink_parent_class parent_class -G_DEFINE_TYPE_WITH_CODE (GstTensorSink, gst_tensor_sink, GST_TYPE_BASE_SINK, - _tensor_sink_do_init (g_define_type_id)); +G_DEFINE_TYPE (GstTensorSink, gst_tensor_sink, GST_TYPE_BASE_SINK); /** * @brief Initialize tensor_sink class. @@ -172,17 +169,17 @@ gst_tensor_sink_class_init (GstTensorSinkClass * klass) element_class = GST_ELEMENT_CLASS (klass); bsink_class = GST_BASE_SINK_CLASS (klass); - /* GObject methods */ + /** GObject methods */ gobject_class->set_property = gst_tensor_sink_set_property; gobject_class->get_property = gst_tensor_sink_get_property; gobject_class->dispose = gst_tensor_sink_dispose; gobject_class->finalize = gst_tensor_sink_finalize; - /* properties */ - g_object_class_install_property (gobject_class, PROP_RENDER_RATE, - g_param_spec_uint64 ("render-rate", "Render rate", - "Buffers rendered per second (0 for unlimited, max 500)", 0, 500, - DEFAULT_RENDER_RATE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** properties */ + g_object_class_install_property (gobject_class, PROP_SIGNAL_RATE, + g_param_spec_uint ("signal-rate", "Signal rate", + "New data signals per second (0 for unlimited, max 500)", 0, 500, + DEFAULT_SIGNAL_RATE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (gobject_class, PROP_EMIT_SIGNAL, g_param_spec_boolean ("emit-signal", "Emit signal", @@ -193,7 +190,7 @@ gst_tensor_sink_class_init (GstTensorSinkClass * klass) g_param_spec_boolean ("silent", "Silent", "Produce verbose output", DEFAULT_SILENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - /* signals */ + /** signals */ _tensor_sink_signals[SIGNAL_NEW_DATA] = g_signal_new ("new-data", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstTensorSinkClass, new_data), NULL, NULL, NULL, @@ -212,11 +209,11 @@ gst_tensor_sink_class_init (GstTensorSinkClass * klass) gst_element_class_set_static_metadata (element_class, "Tensor_Sink", "Sink/Tensor", - "Sink element to handle tensor stream", "nnstreamer "); + "Sink element to handle tensor stream", "Samsung Electronics Co., Ltd."); gst_element_class_add_static_pad_template (element_class, &sinktemplate); - /* GstBaseSink methods */ + /** GstBaseSink methods */ bsink_class->start = GST_DEBUG_FUNCPTR (gst_tensor_sink_start); bsink_class->stop = GST_DEBUG_FUNCPTR (gst_tensor_sink_stop); bsink_class->event = GST_DEBUG_FUNCPTR (gst_tensor_sink_event); @@ -239,14 +236,14 @@ gst_tensor_sink_init (GstTensorSink * self) g_mutex_init (&self->mutex); - /* init properties */ + /** init properties */ self->silent = DEFAULT_SILENT; self->emit_signal = DEFAULT_EMIT_SIGNAL; - self->render_rate = DEFAULT_RENDER_RATE; + self->signal_rate = DEFAULT_SIGNAL_RATE; self->last_render_time = GST_CLOCK_TIME_NONE; self->in_caps = NULL; - /* enable qos event */ + /** enable qos event */ gst_base_sink_set_sync (bsink, DEFAULT_SYNC); gst_base_sink_set_max_lateness (bsink, DEFAULT_LATENESS); gst_base_sink_set_qos_enabled (bsink, DEFAULT_QOS); @@ -266,8 +263,8 @@ gst_tensor_sink_set_property (GObject * object, guint prop_id, self = GST_TENSOR_SINK (object); switch (prop_id) { - case PROP_RENDER_RATE: - _tensor_sink_set_render_rate (self, g_value_get_uint64 (value)); + case PROP_SIGNAL_RATE: + _tensor_sink_set_signal_rate (self, g_value_get_uint (value)); break; case PROP_EMIT_SIGNAL: @@ -298,8 +295,8 @@ gst_tensor_sink_get_property (GObject * object, guint prop_id, self = GST_TENSOR_SINK (object); switch (prop_id) { - case PROP_RENDER_RATE: - g_value_set_uint64 (value, _tensor_sink_get_render_rate (self)); + case PROP_SIGNAL_RATE: + g_value_set_uint (value, _tensor_sink_get_signal_rate (self)); break; case PROP_EMIT_SIGNAL: @@ -360,7 +357,7 @@ gst_tensor_sink_finalize (GObject * object) static gboolean gst_tensor_sink_start (GstBaseSink * sink) { - /* load and init resources */ + /** load and init resources */ return TRUE; } @@ -372,7 +369,7 @@ gst_tensor_sink_start (GstBaseSink * sink) static gboolean gst_tensor_sink_stop (GstBaseSink * sink) { - /* free resources */ + /** free resources */ return TRUE; } @@ -431,7 +428,7 @@ gst_tensor_sink_query (GstBaseSink * sink, GstQuery * query) switch (type) { case GST_QUERY_SEEKING: DLOG ("query SEEKING"); - /* tensor sink does not support seeking */ + /** tensor sink does not support seeking */ gst_query_parse_seeking (query, &format, NULL, NULL, NULL); gst_query_set_seeking (query, format, FALSE, 0, -1); return TRUE; @@ -556,14 +553,14 @@ static void _tensor_sink_render_buffer (GstTensorSink * self, GstBuffer * buffer) { GstClockTime now = GST_CLOCK_TIME_NONE; - guint64 render_rate; + guint signal_rate; gboolean notify = FALSE; g_return_if_fail (GST_IS_TENSOR_SINK (self)); - render_rate = _tensor_sink_get_render_rate (self); + signal_rate = _tensor_sink_get_signal_rate (self); - if (render_rate) { + if (signal_rate) { GstClock *clock; GstClockTime render_time; GstClockTime last_render_time; @@ -574,19 +571,19 @@ _tensor_sink_render_buffer (GstTensorSink * self, GstBuffer * buffer) now = gst_clock_get_time (clock); last_render_time = _tensor_sink_get_last_render_time (self); - /* time for next render */ - render_time = (1000 / render_rate) * GST_MSECOND + last_render_time; + /** time for next signal */ + render_time = (1000 / signal_rate) * GST_MSECOND + last_render_time; if (!GST_CLOCK_TIME_IS_VALID (last_render_time) || GST_CLOCK_DIFF (now, render_time) <= 0) { - /* send data after render time, or firstly received buffer */ + /** send data after render time, or firstly received buffer */ notify = TRUE; } gst_object_unref (clock); } } else { - /* send data if render rate is 0 */ + /** send data if signal rate is 0 */ notify = TRUE; } @@ -594,8 +591,8 @@ _tensor_sink_render_buffer (GstTensorSink * self, GstBuffer * buffer) _tensor_sink_set_last_render_time (self, now); if (_tensor_sink_get_emit_signal (self)) { - DLOG ("signal for new data [%" GST_TIME_FORMAT "], rate [%ld]", - GST_TIME_ARGS (now), render_rate); + DLOG ("signal for new data [%" GST_TIME_FORMAT "], rate [%d]", + GST_TIME_ARGS (now), signal_rate); g_signal_emit (self, _tensor_sink_signals[SIGNAL_NEW_DATA], 0, buffer); } } @@ -632,31 +629,31 @@ _tensor_sink_get_last_render_time (GstTensorSink * self) } /** - * @brief Setter for value render_rate. + * @brief Setter for value signal_rate. */ static void -_tensor_sink_set_render_rate (GstTensorSink * self, guint64 rate) +_tensor_sink_set_signal_rate (GstTensorSink * self, guint rate) { g_return_if_fail (GST_IS_TENSOR_SINK (self)); - DLOG ("set render_rate to %ld", rate); + DLOG ("set signal_rate to %d", rate); g_mutex_lock (&self->mutex); - self->render_rate = rate; + self->signal_rate = rate; g_mutex_unlock (&self->mutex); } /** - * @brief Getter for value render_rate. + * @brief Getter for value signal_rate. */ -static guint64 -_tensor_sink_get_render_rate (GstTensorSink * self) +static guint +_tensor_sink_get_signal_rate (GstTensorSink * self) { - guint64 rate; + guint rate; g_return_val_if_fail (GST_IS_TENSOR_SINK (self), 0); g_mutex_lock (&self->mutex); - rate = self->render_rate; + rate = self->signal_rate; g_mutex_unlock (&self->mutex); return rate; @@ -717,15 +714,6 @@ _tensor_sink_get_silent (GstTensorSink * self) } /** - * @brief Function used in type implementation. - */ -static void -_tensor_sink_do_init (GType type) -{ - /* add interface */ -} - -/** * @brief Function to initialize the plugin. * * See GstPluginInitFunc() for more details. diff --git a/gst/tensor_sink/tensor_sink.h b/gst/tensor_sink/tensor_sink.h index 80cd2df..5b0551a 100644 --- a/gst/tensor_sink/tensor_sink.h +++ b/gst/tensor_sink/tensor_sink.h @@ -2,7 +2,7 @@ * GStreamer * Copyright (C) 2005 Thomas Vander Stichele * Copyright (C) 2005 Ronald S. Bultje - * Copyright (C) 2018 nnstreamer + * Copyright (C) 2018 Samsung Electronics Co., Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -13,13 +13,13 @@ * 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. - * */ + /** * @file tensor_sink.h * @date 15 June 2018 * @brief GStreamer plugin to handle tensor stream - * @see http://github.com/TO-BE-DETERMINED-SOON + * @see http://github.com/nnsuite/nnstreamer * @see https://github.sec.samsung.net/STAR/nnstreamer * @author Jaeyun Jung * @bug No known bugs except for NYI items @@ -60,7 +60,7 @@ struct _GstTensorSink GMutex mutex; /**< mutex for processing */ gboolean silent; /**< true to print minimized log */ gboolean emit_signal; /**< true to emit signal for new data, eos */ - guint64 render_rate; /**< buffers rendered per second */ + guint signal_rate; /**< new data signals per second */ GstClockTime last_render_time; /**< buffer rendered time */ GstCaps *in_caps; /**< received caps */ }; @@ -74,7 +74,7 @@ struct _GstTensorSinkClass { GstBaseSinkClass parent_class; /**< parent class */ - /* signals */ + /** signals */ void (*new_data) (GstElement * element, GstBuffer * buffer); /**< signal when new data received */ void (*stream_start) (GstElement * element); /**< signal when stream started */ void (*eos) (GstElement * element); /**< signal when end of stream reached */ @@ -87,4 +87,4 @@ GType gst_tensor_sink_get_type (void); G_END_DECLS -#endif /* __GST_TENSOR_SINK_H__ */ +#endif /** __GST_TENSOR_SINK_H__ */ diff --git a/nnstreamer_example/example_cam/nnstreamer_example_cam.c b/nnstreamer_example/example_cam/nnstreamer_example_cam.c index d499fbe..a570786 100644 --- a/nnstreamer_example/example_cam/nnstreamer_example_cam.c +++ b/nnstreamer_example/example_cam/nnstreamer_example_cam.c @@ -85,6 +85,8 @@ _parse_err_message (GstMessage * message) gchar *debug; GError *error; + g_return_if_fail (message != NULL); + switch (GST_MESSAGE_TYPE (message)) { case GST_MESSAGE_ERROR: gst_message_parse_error (message, &error, &debug); @@ -188,17 +190,17 @@ main (int argc, char **argv) _print_log ("start app.."); - /* check cam */ + /** check cam */ _check_cond_err (_check_cam_device (cam_dev)); - /* init gstreamer */ + /** init gstreamer */ gst_init (&argc, &argv); - /* main loop */ + /** main loop */ g_app.loop = g_main_loop_new (NULL, FALSE); _check_cond_err (g_app.loop != NULL); - /* init data pipeline */ + /** init data pipeline */ str_pipeline = g_strdup_printf ("v4l2src name=cam_src ! " @@ -215,7 +217,7 @@ main (int argc, char **argv) g_free (str_pipeline); _check_cond_err (g_app.pipeline != NULL); - /* data message callback */ + /** data message callback */ g_app.bus = gst_element_get_bus (g_app.pipeline); _check_cond_err (g_app.bus != NULL); @@ -224,10 +226,10 @@ main (int argc, char **argv) (GCallback) _message_cb, NULL); _check_cond_err (handle_id > 0); - /* start pipeline */ + /** start pipeline */ gst_element_set_state (g_app.pipeline, GST_STATE_PLAYING); - /* set window title */ + /** set window title */ element = gst_bin_get_by_name (GST_BIN (g_app.pipeline), "img_mixed"); _set_window_title (element, "Mixed"); gst_object_unref (element); @@ -236,13 +238,13 @@ main (int argc, char **argv) _set_window_title (element, "Original"); gst_object_unref (element); - /* run main loop */ + /** run main loop */ g_main_loop_run (g_app.loop); + /** quit when received eos or error message */ - /* cam source element */ + /** cam source element */ element = gst_bin_get_by_name (GST_BIN (g_app.pipeline), "cam_src"); - /* quit when received eos or error message */ gst_element_set_state (element, GST_STATE_READY); gst_element_set_state (g_app.pipeline, GST_STATE_READY); diff --git a/nnstreamer_example/example_sink/nnstreamer_sink_example.c b/nnstreamer_example/example_sink/nnstreamer_sink_example.c index cdb41ff..e7ef6ac 100644 --- a/nnstreamer_example/example_sink/nnstreamer_sink_example.c +++ b/nnstreamer_example/example_sink/nnstreamer_sink_example.c @@ -43,7 +43,6 @@ typedef struct GMainLoop *loop; /**< main event loop */ GstElement *pipeline; /**< gst pipeline for test */ GstBus *bus; /**< gst bus for test */ - GstElement *sink; /**< tensor sink element */ guint received; /**< received buffer count */ } AppData; @@ -51,7 +50,7 @@ typedef struct /** * @brief Data for pipeline and result. */ -static AppData g_app_data; +static AppData g_app; /** * @brief Free resources in app data. @@ -59,25 +58,20 @@ static AppData g_app_data; static void _free_app_data (void) { - if (g_app_data.loop) { - g_main_loop_unref (g_app_data.loop); - g_app_data.loop = NULL; + if (g_app.loop) { + g_main_loop_unref (g_app.loop); + g_app.loop = NULL; } - if (g_app_data.bus) { - gst_bus_remove_signal_watch (g_app_data.bus); - gst_object_unref (g_app_data.bus); - g_app_data.bus = NULL; + if (g_app.bus) { + gst_bus_remove_signal_watch (g_app.bus); + gst_object_unref (g_app.bus); + g_app.bus = NULL; } - if (g_app_data.sink) { - gst_object_unref (g_app_data.sink); - g_app_data.sink = NULL; - } - - if (g_app_data.pipeline) { - gst_object_unref (g_app_data.pipeline); - g_app_data.pipeline = NULL; + if (g_app.pipeline) { + gst_object_unref (g_app.pipeline); + g_app.pipeline = NULL; } } @@ -90,6 +84,8 @@ _parse_err_message (GstMessage * message) gchar *debug; GError *error; + g_return_if_fail (message != NULL); + switch (GST_MESSAGE_TYPE (message)) { case GST_MESSAGE_ERROR: gst_message_parse_error (message, &error, &debug); @@ -109,6 +105,27 @@ _parse_err_message (GstMessage * message) } /** + * @brief Function to print caps. + */ +static void +_parse_caps (GstCaps * caps) +{ + guint caps_size, i; + + g_return_if_fail (caps != NULL); + + caps_size = gst_caps_get_size (caps); + + for (i = 0; i < caps_size; i++) { + GstStructure *structure = gst_caps_get_structure (caps, i); + gchar *str = gst_structure_to_string (structure); + + _print_log ("[%d] %s", i, str); + g_free (str); + } +} + +/** * @brief Callback for message. */ static void @@ -117,13 +134,13 @@ _message_cb (GstBus * bus, GstMessage * message, gpointer user_data) switch (GST_MESSAGE_TYPE (message)) { case GST_MESSAGE_EOS: _print_log ("received eos message"); - g_main_loop_quit (g_app_data.loop); + g_main_loop_quit (g_app.loop); break; case GST_MESSAGE_ERROR: _print_log ("received error message"); _parse_err_message (message); - g_main_loop_quit (g_app_data.loop); + g_main_loop_quit (g_app.loop); break; case GST_MESSAGE_WARNING: @@ -146,11 +163,13 @@ _message_cb (GstBus * bus, GstMessage * message, gpointer user_data) static void _new_data_cb (GstElement * element, GstBuffer * buffer, gpointer user_data) { - g_app_data.received++; - _print_log ("new data callback [%d]", g_app_data.received); + g_app.received++; + if (g_app.received % 150 == 0) { + _print_log ("receiving new data [%d]", g_app.received); + } - /* example to get data */ - if (DBG) { + /** example to get data */ + { GstMemory *mem; GstMapInfo info; guint i; @@ -161,7 +180,7 @@ _new_data_cb (GstElement * element, GstBuffer * buffer, gpointer user_data) mem = gst_buffer_peek_memory (buffer, i); if (gst_memory_map (mem, &info, GST_MAP_READ)) { - /* check data (info.data, info.size) */ + /** check data (info.data, info.size) */ _print_log ("received %zd", info.size); gst_memory_unmap (mem, &info); @@ -169,30 +188,27 @@ _new_data_cb (GstElement * element, GstBuffer * buffer, gpointer user_data) } } - /* example to get negotiated caps */ - if (DBG) { + /** example to get caps */ + { GstPad *sink_pad; GstCaps *caps; - sink_pad = gst_element_get_static_pad (g_app_data.sink, "sink"); + sink_pad = gst_element_get_static_pad (element, "sink"); if (sink_pad) { + /** negotiated */ caps = gst_pad_get_current_caps (sink_pad); if (caps) { - guint caps_size, i; - - caps_size = gst_caps_get_size (caps); - _print_log ("caps size is %d", caps_size); - - for (i = 0; i < caps_size; i++) { - GstStructure *structure = gst_caps_get_structure (caps, i); - gchar *str = gst_structure_to_string (structure); + _parse_caps (caps); + gst_caps_unref (caps); + } - _print_log ("[%d] %s", i, str); - g_free (str); - } + /** template */ + caps = gst_pad_get_pad_template_caps (sink_pad); + if (caps) { + _parse_caps (caps); gst_caps_unref (caps); } @@ -232,75 +248,77 @@ main (int argc, char **argv) gchar *str_pipeline; gulong handle_id; GstStateChangeReturn state_ret; + GstElement *element; - /* init gstreamer */ + /** init gstreamer */ gst_init (&argc, &argv); - /* init app variable */ - g_app_data.received = 0; + /** init app variable */ + g_app.received = 0; - /* main loop and pipeline */ - g_app_data.loop = g_main_loop_new (NULL, FALSE); - _check_cond_err (g_app_data.loop != NULL); + /** main loop and pipeline */ + g_app.loop = g_main_loop_new (NULL, FALSE); + _check_cond_err (g_app.loop != NULL); - /* 640x480 30fps for test */ + /** 640x480 30fps for test */ str_pipeline = g_strdup_printf ("videotestsrc num-buffers=%d ! video/x-raw,format=RGB,width=%d,height=%d ! " "tensor_converter ! tensor_sink name=tensor_sink", num_buffers, width, height); - g_app_data.pipeline = gst_parse_launch (str_pipeline, NULL); + g_app.pipeline = gst_parse_launch (str_pipeline, NULL); g_free (str_pipeline); - _check_cond_err (g_app_data.pipeline != NULL); + _check_cond_err (g_app.pipeline != NULL); - /* message callback */ - g_app_data.bus = gst_element_get_bus (g_app_data.pipeline); - _check_cond_err (g_app_data.bus != NULL); + /** message callback */ + g_app.bus = gst_element_get_bus (g_app.pipeline); + _check_cond_err (g_app.bus != NULL); - gst_bus_add_signal_watch (g_app_data.bus); - handle_id = g_signal_connect (g_app_data.bus, "message", + gst_bus_add_signal_watch (g_app.bus); + handle_id = g_signal_connect (g_app.bus, "message", (GCallback) _message_cb, NULL); _check_cond_err (handle_id > 0); - /* get tensor sink element using name */ - g_app_data.sink = - gst_bin_get_by_name (GST_BIN (g_app_data.pipeline), "tensor_sink"); - _check_cond_err (g_app_data.sink != NULL); + /** get tensor sink element using name */ + element = gst_bin_get_by_name (GST_BIN (g_app.pipeline), "tensor_sink"); + _check_cond_err (element != NULL); if (DBG) { - /* print logs, default TRUE */ - g_object_set (g_app_data.sink, "silent", (gboolean) FALSE, NULL); + /** print logs, default TRUE */ + g_object_set (element, "silent", (gboolean) FALSE, NULL); } - /* enable emit-signal, default TRUE */ - g_object_set (g_app_data.sink, "emit-signal", (gboolean) TRUE, NULL); + /** enable emit-signal, default TRUE */ + g_object_set (element, "emit-signal", (gboolean) TRUE, NULL); - /* tensor sink signal : new data callback */ - handle_id = g_signal_connect (g_app_data.sink, "new-data", + /** tensor sink signal : new data callback */ + handle_id = g_signal_connect (element, "new-data", (GCallback) _new_data_cb, NULL); _check_cond_err (handle_id > 0); - /* tensor sink signal : stream-start callback, optional */ - handle_id = g_signal_connect (g_app_data.sink, "stream-start", + /** tensor sink signal : stream-start callback, optional */ + handle_id = g_signal_connect (element, "stream-start", (GCallback) _stream_start_cb, NULL); _check_cond_err (handle_id > 0); - /* tensor sink signal : eos callback, optional */ - handle_id = g_signal_connect (g_app_data.sink, "eos", - (GCallback) _eos_cb, NULL); + /** tensor sink signal : eos callback, optional */ + handle_id = g_signal_connect (element, "eos", (GCallback) _eos_cb, NULL); _check_cond_err (handle_id > 0); - /* start pipeline */ - state_ret = gst_element_set_state (g_app_data.pipeline, GST_STATE_PLAYING); + gst_object_unref (element); + + /** start pipeline */ + state_ret = gst_element_set_state (g_app.pipeline, GST_STATE_PLAYING); _check_cond_err (state_ret != GST_STATE_CHANGE_FAILURE); - g_main_loop_run (g_app_data.loop); + /** run main loop */ + g_main_loop_run (g_app.loop); + /** quit when received eos message */ - /* quit when received eos message */ - state_ret = gst_element_set_state (g_app_data.pipeline, GST_STATE_NULL); + state_ret = gst_element_set_state (g_app.pipeline, GST_STATE_NULL); _check_cond_err (state_ret != GST_STATE_CHANGE_FAILURE); - _print_log ("total received %d", g_app_data.received); + _print_log ("total received %d", g_app.received); error: _free_app_data (); diff --git a/nnstreamer_example/example_sink/nnstreamer_sink_example_play.c b/nnstreamer_example/example_sink/nnstreamer_sink_example_play.c index 3d11506..3aec001 100644 --- a/nnstreamer_example/example_sink/nnstreamer_sink_example_play.c +++ b/nnstreamer_example/example_sink/nnstreamer_sink_example_play.c @@ -50,17 +50,15 @@ typedef struct GstBus *data_bus; /**< gst bus for data pipeline */ GstElement *player_pipeline; /**< gst pipeline for player */ GstBus *player_bus; /**< gst bus for player pipeline */ - GstElement *tensor_sink; /**< tensor sink element */ - GstElement *player_src; /**< player source element */ - guint received; /**< received buffer count */ gboolean set_caps; /**< caps passed to player pipeline */ + guint received; /**< received buffer count */ } AppData; /** * @brief Data for pipeline and result. */ -static AppData g_app_data; +static AppData g_app; /** * @brief Free resources in app data. @@ -68,41 +66,31 @@ static AppData g_app_data; static void _free_app_data (void) { - if (g_app_data.loop) { - g_main_loop_unref (g_app_data.loop); - g_app_data.loop = NULL; - } - - if (g_app_data.data_bus) { - gst_bus_remove_signal_watch (g_app_data.data_bus); - gst_object_unref (g_app_data.data_bus); - g_app_data.data_bus = NULL; + if (g_app.loop) { + g_main_loop_unref (g_app.loop); + g_app.loop = NULL; } - if (g_app_data.player_bus) { - gst_bus_remove_signal_watch (g_app_data.player_bus); - gst_object_unref (g_app_data.player_bus); - g_app_data.player_bus = NULL; + if (g_app.data_bus) { + gst_bus_remove_signal_watch (g_app.data_bus); + gst_object_unref (g_app.data_bus); + g_app.data_bus = NULL; } - if (g_app_data.tensor_sink) { - gst_object_unref (g_app_data.tensor_sink); - g_app_data.tensor_sink = NULL; + if (g_app.player_bus) { + gst_bus_remove_signal_watch (g_app.player_bus); + gst_object_unref (g_app.player_bus); + g_app.player_bus = NULL; } - if (g_app_data.player_src) { - gst_object_unref (g_app_data.player_src); - g_app_data.player_src = NULL; + if (g_app.data_pipeline) { + gst_object_unref (g_app.data_pipeline); + g_app.data_pipeline = NULL; } - if (g_app_data.data_pipeline) { - gst_object_unref (g_app_data.data_pipeline); - g_app_data.data_pipeline = NULL; - } - - if (g_app_data.player_pipeline) { - gst_object_unref (g_app_data.player_pipeline); - g_app_data.player_pipeline = NULL; + if (g_app.player_pipeline) { + gst_object_unref (g_app.player_pipeline); + g_app.player_pipeline = NULL; } } @@ -115,6 +103,8 @@ _parse_err_message (GstMessage * message) gchar *debug; GError *error; + g_return_if_fail (message != NULL); + switch (GST_MESSAGE_TYPE (message)) { case GST_MESSAGE_ERROR: gst_message_parse_error (message, &error, &debug); @@ -139,16 +129,21 @@ _parse_err_message (GstMessage * message) static void _data_message_cb (GstBus * bus, GstMessage * message, gpointer user_data) { + GstElement *player_src; + switch (GST_MESSAGE_TYPE (message)) { case GST_MESSAGE_EOS: _print_log ("[data] received eos message"); - gst_app_src_end_of_stream (GST_APP_SRC (g_app_data.player_src)); + player_src = gst_bin_get_by_name (GST_BIN (g_app.player_pipeline), + "player_src"); + gst_app_src_end_of_stream (GST_APP_SRC (player_src)); + gst_object_unref (player_src); break; case GST_MESSAGE_ERROR: _print_log ("[data] received error message"); _parse_err_message (message); - g_main_loop_quit (g_app_data.loop); + g_main_loop_quit (g_app.loop); break; case GST_MESSAGE_WARNING: @@ -174,13 +169,13 @@ _player_message_cb (GstBus * bus, GstMessage * message, gpointer user_data) switch (GST_MESSAGE_TYPE (message)) { case GST_MESSAGE_EOS: _print_log ("[player] received eos message"); - g_main_loop_quit (g_app_data.loop); + g_main_loop_quit (g_app.loop); break; case GST_MESSAGE_ERROR: _print_log ("[player] received error message"); _parse_err_message (message); - g_main_loop_quit (g_app_data.loop); + g_main_loop_quit (g_app.loop); break; case GST_MESSAGE_WARNING: @@ -203,31 +198,38 @@ _player_message_cb (GstBus * bus, GstMessage * message, gpointer user_data) static void _new_data_cb (GstElement * element, GstBuffer * buffer, gpointer user_data) { - g_app_data.received++; - _print_log ("new data callback [%d]", g_app_data.received); + GstElement *player_src; + + g_app.received++; + if (g_app.received % 150 == 0) { + _print_log ("receiving new data [%d]", g_app.received); + } - if (!g_app_data.set_caps) { + player_src = + gst_bin_get_by_name (GST_BIN (g_app.player_pipeline), "player_src"); + + if (!g_app.set_caps) { GstPad *sink_pad; GstCaps *caps; - sink_pad = gst_element_get_static_pad (g_app_data.tensor_sink, "sink"); + sink_pad = gst_element_get_static_pad (element, "sink"); if (sink_pad) { caps = gst_pad_get_current_caps (sink_pad); if (caps) { - gst_app_src_set_caps (GST_APP_SRC (g_app_data.player_src), caps); + gst_app_src_set_caps (GST_APP_SRC (player_src), caps); gst_caps_unref (caps); - g_app_data.set_caps = TRUE; + g_app.set_caps = TRUE; } gst_object_unref (sink_pad); } } - gst_app_src_push_buffer (GST_APP_SRC (g_app_data.player_src), - gst_buffer_copy (buffer)); + gst_app_src_push_buffer (GST_APP_SRC (player_src), gst_buffer_copy (buffer)); + gst_object_unref (player_src); } /** @@ -241,84 +243,82 @@ main (int argc, char **argv) gchar *str_pipeline; gulong handle_id; + GstElement *element; - /* init gstreamer */ + /** init gstreamer */ gst_init (&argc, &argv); - /* init app variable */ - g_app_data.received = 0; - g_app_data.set_caps = FALSE; + /** init app variable */ + g_app.set_caps = FALSE; + g_app.received = 0; - /* main loop and pipeline */ - g_app_data.loop = g_main_loop_new (NULL, FALSE); - _check_cond_err (g_app_data.loop != NULL); + /** main loop and pipeline */ + g_app.loop = g_main_loop_new (NULL, FALSE); + _check_cond_err (g_app.loop != NULL); str_pipeline = g_strdup_printf ("videotestsrc is-live=TRUE ! video/x-raw,format=RGB,width=%d,height=%d ! " "tensor_converter ! tensor_sink name=tensor_sink", width, height); - g_app_data.data_pipeline = gst_parse_launch (str_pipeline, NULL); + g_app.data_pipeline = gst_parse_launch (str_pipeline, NULL); g_free (str_pipeline); - _check_cond_err (g_app_data.data_pipeline != NULL); + _check_cond_err (g_app.data_pipeline != NULL); - /* data message callback */ - g_app_data.data_bus = gst_element_get_bus (g_app_data.data_pipeline); - _check_cond_err (g_app_data.data_bus != NULL); + /** data message callback */ + g_app.data_bus = gst_element_get_bus (g_app.data_pipeline); + _check_cond_err (g_app.data_bus != NULL); - gst_bus_add_signal_watch (g_app_data.data_bus); - handle_id = g_signal_connect (g_app_data.data_bus, "message", + gst_bus_add_signal_watch (g_app.data_bus); + handle_id = g_signal_connect (g_app.data_bus, "message", (GCallback) _data_message_cb, NULL); _check_cond_err (handle_id > 0); - /* get tensor sink element using name */ - g_app_data.tensor_sink = - gst_bin_get_by_name (GST_BIN (g_app_data.data_pipeline), "tensor_sink"); - _check_cond_err (g_app_data.tensor_sink != NULL); + /** get tensor sink element using name */ + element = gst_bin_get_by_name (GST_BIN (g_app.data_pipeline), "tensor_sink"); + _check_cond_err (element != NULL); if (DBG) { - /* print logs, default TRUE */ - g_object_set (g_app_data.tensor_sink, "silent", (gboolean) FALSE, NULL); + /** print logs, default TRUE */ + g_object_set (element, "silent", (gboolean) FALSE, NULL); } - /* enable emit-signal, default TRUE */ - g_object_set (g_app_data.tensor_sink, "emit-signal", (gboolean) TRUE, NULL); + /** enable emit-signal, default TRUE */ + g_object_set (element, "emit-signal", (gboolean) TRUE, NULL); - /* tensor sink signal : new data callback */ - handle_id = g_signal_connect (g_app_data.tensor_sink, "new-data", + /** tensor sink signal : new data callback */ + handle_id = g_signal_connect (element, "new-data", (GCallback) _new_data_cb, NULL); _check_cond_err (handle_id > 0); - /* init player pipeline */ + gst_object_unref (element); + + /** init player pipeline */ str_pipeline = g_strdup_printf ("appsrc name=player_src ! tensordec ! videoconvert ! xvimagesink"); - g_app_data.player_pipeline = gst_parse_launch (str_pipeline, NULL); + g_app.player_pipeline = gst_parse_launch (str_pipeline, NULL); g_free (str_pipeline); - _check_cond_err (g_app_data.player_pipeline != NULL); + _check_cond_err (g_app.player_pipeline != NULL); - /* player message callback */ - g_app_data.player_bus = gst_element_get_bus (g_app_data.player_pipeline); - _check_cond_err (g_app_data.player_bus != NULL); + /** player message callback */ + g_app.player_bus = gst_element_get_bus (g_app.player_pipeline); + _check_cond_err (g_app.player_bus != NULL); - gst_bus_add_signal_watch (g_app_data.player_bus); - handle_id = g_signal_connect (g_app_data.player_bus, "message", + gst_bus_add_signal_watch (g_app.player_bus); + handle_id = g_signal_connect (g_app.player_bus, "message", (GCallback) _player_message_cb, NULL); _check_cond_err (handle_id > 0); - /* player source element */ - g_app_data.player_src = - gst_bin_get_by_name (GST_BIN (g_app_data.player_pipeline), "player_src"); - _check_cond_err (g_app_data.player_src != NULL); - - /* start pipeline */ - gst_element_set_state (g_app_data.data_pipeline, GST_STATE_PLAYING); - gst_element_set_state (g_app_data.player_pipeline, GST_STATE_PLAYING); + /** start pipeline */ + gst_element_set_state (g_app.data_pipeline, GST_STATE_PLAYING); + gst_element_set_state (g_app.player_pipeline, GST_STATE_PLAYING); - g_main_loop_run (g_app_data.loop); + /** run main loop */ + g_main_loop_run (g_app.loop); + /** quit when received eos message */ - /* quit when received eos message */ - gst_element_set_state (g_app_data.data_pipeline, GST_STATE_NULL); - gst_element_set_state (g_app_data.player_pipeline, GST_STATE_NULL); + gst_element_set_state (g_app.data_pipeline, GST_STATE_NULL); + gst_element_set_state (g_app.player_pipeline, GST_STATE_NULL); error: _free_app_data (); diff --git a/tests/nnstreamer_sink/unittest_sink.cpp b/tests/nnstreamer_sink/unittest_sink.cpp index 206d4f6..6e16fef 100644 --- a/tests/nnstreamer_sink/unittest_sink.cpp +++ b/tests/nnstreamer_sink/unittest_sink.cpp @@ -5,6 +5,7 @@ * @see http://github.com/TO-BE-DETERMINED-SOON * @see https://github.sec.samsung.net/STAR/nnstreamer * @author Jaeyun Jung + * @bug No known bugs. */ #include @@ -127,57 +128,6 @@ _new_data_cb (GstElement * element, GstBuffer * buffer, gpointer user_data) { g_test_data.received++; _print_log ("new data callback [%d]", g_test_data.received); - - /* example to get data */ - if (DBG) { - GstMemory *mem; - GstMapInfo info; - guint i; - guint num_mems; - - num_mems = gst_buffer_n_memory (buffer); - for (i = 0; i < num_mems; i++) { - mem = gst_buffer_peek_memory (buffer, i); - - if (gst_memory_map (mem, &info, GST_MAP_READ)) { - /* check data (info.data, info.size) */ - _print_log ("received %zd", info.size); - - gst_memory_unmap (mem, &info); - } - } - } - - /* example to get negotiated caps */ - if (DBG) { - GstPad *sink_pad; - GstCaps *caps; - - sink_pad = gst_element_get_static_pad (g_test_data.sink, "sink"); - - if (sink_pad) { - g_object_get (sink_pad, "caps", &caps, NULL); - - if (caps) { - guint caps_size, i; - - caps_size = gst_caps_get_size (caps); - _print_log ("caps size is %d", caps_size); - - for (i = 0; i < caps_size; i++) { - GstStructure *structure = gst_caps_get_structure (caps, i); - gchar *str = gst_structure_to_string (structure); - - _print_log ("[%d] %s", i, str); - g_free (str); - } - - gst_caps_unref (caps); - } - - gst_object_unref (sink_pad); - } - } } /** @@ -219,8 +169,8 @@ _setup_pipeline (const guint num_buffers) str_pipeline = g_strdup_printf - ("videotestsrc num-buffers=%d ! video/x-raw,width=640,height=480,framerate=(fraction)30/1 ! videoconvert ! video/x-raw,format=RGB ! tensor_converter ! tensor_sink name=test_sink", - num_buffers); + ("videotestsrc num-buffers=%d ! video/x-raw,width=160,height=120,format=RGB,framerate=(fraction)30/1 ! " + "tensor_converter ! tensor_sink name=test_sink", num_buffers); g_test_data.pipeline = gst_parse_launch (str_pipeline, NULL); g_free (str_pipeline); _check_cond_err (g_test_data.pipeline != NULL); @@ -250,7 +200,7 @@ error: */ TEST (tensor_sink_test, properties) { - guint64 rate, res_rate; + guint rate, res_rate; gint64 lateness, res_lateness; gboolean silent, res_silent; gboolean emit, res_emit; @@ -259,15 +209,15 @@ TEST (tensor_sink_test, properties) ASSERT_TRUE (_setup_pipeline (1)); - /* default render-rate is 0 */ - g_object_get (g_test_data.sink, "render-rate", &rate, NULL); + /** default signal-rate is 0 */ + g_object_get (g_test_data.sink, "signal-rate", &rate, NULL); EXPECT_EQ (rate, 0); - g_object_set (g_test_data.sink, "render-rate", (rate + 10), NULL); - g_object_get (g_test_data.sink, "render-rate", &res_rate, NULL); + g_object_set (g_test_data.sink, "signal-rate", (rate + 10), NULL); + g_object_get (g_test_data.sink, "signal-rate", &res_rate, NULL); EXPECT_EQ (res_rate, (rate + 10)); - /* default emit-signal is TRUE */ + /** default emit-signal is TRUE */ g_object_get (g_test_data.sink, "emit-signal", &emit, NULL); EXPECT_EQ (emit, TRUE); @@ -275,7 +225,7 @@ TEST (tensor_sink_test, properties) g_object_get (g_test_data.sink, "emit-signal", &res_emit, NULL); EXPECT_EQ (res_emit, !emit); - /* default silent is TRUE */ + /** default silent is TRUE */ g_object_get (g_test_data.sink, "silent", &silent, NULL); EXPECT_EQ (silent, TRUE); @@ -283,7 +233,7 @@ TEST (tensor_sink_test, properties) g_object_get (g_test_data.sink, "silent", &res_silent, NULL); EXPECT_EQ (res_silent, !silent); - /* GstBaseSink:sync TRUE */ + /** GstBaseSink:sync TRUE */ g_object_get (g_test_data.sink, "sync", &sync, NULL); EXPECT_EQ (sync, TRUE); @@ -291,16 +241,16 @@ TEST (tensor_sink_test, properties) g_object_get (g_test_data.sink, "sync", &res_sync, NULL); EXPECT_EQ (res_sync, !sync); - /* GstBaseSink:max-lateness 30ms */ + /** GstBaseSink:max-lateness 30ms */ g_object_get (g_test_data.sink, "max-lateness", &lateness, NULL); EXPECT_EQ (lateness, (30 * GST_MSECOND)); - /* -1 means unlimited time */ + /** -1 means unlimited time */ g_object_set (g_test_data.sink, "max-lateness", (gint64) (-1), NULL); g_object_get (g_test_data.sink, "max-lateness", &res_lateness, NULL); EXPECT_EQ (res_lateness, -1); - /* GstBaseSink:qos TRUE */ + /** GstBaseSink:qos TRUE */ g_object_get (g_test_data.sink, "qos", &qos, NULL); EXPECT_EQ (qos, TRUE); @@ -322,14 +272,11 @@ TEST (tensor_sink_test, signals) ASSERT_TRUE (_setup_pipeline (num_buffers)); if (DBG) { - /* print logs */ - g_object_set (g_test_data.sink, "silent", FALSE, NULL); + /** print logs */ + g_object_set (g_test_data.sink, "silent", (gboolean) FALSE, NULL); } - /* enable emit-signal */ - g_object_set (g_test_data.sink, "emit-signal", TRUE, NULL); - - /* tensor sink signals */ + /** tensor sink signals */ handle_id = g_signal_connect (g_test_data.sink, "new-data", (GCallback) _new_data_cb, NULL); EXPECT_TRUE (handle_id > 0); @@ -347,10 +294,10 @@ TEST (tensor_sink_test, signals) g_main_loop_run (g_test_data.loop); gst_element_set_state (g_test_data.pipeline, GST_STATE_NULL); - /* check eos message */ + /** check eos message */ EXPECT_EQ (g_test_data.status, TEST_EOS); - /* check received buffers and signals */ + /** check received buffers and signals */ EXPECT_EQ (g_test_data.received, num_buffers); EXPECT_EQ (g_test_data.start, TRUE); EXPECT_EQ (g_test_data.end, TRUE); @@ -359,9 +306,9 @@ TEST (tensor_sink_test, signals) } /** - * @brief Test for tensor sink render-rate. + * @brief Test for tensor sink signal-rate. */ -TEST (tensor_sink_test, render_rate) +TEST (tensor_sink_test, signal_rate) { const guint num_buffers = 10; gulong handle_id; @@ -369,30 +316,27 @@ TEST (tensor_sink_test, render_rate) ASSERT_TRUE (_setup_pipeline (num_buffers)); if (DBG) { - /* print logs */ - g_object_set (g_test_data.sink, "silent", FALSE, NULL); + /** print logs */ + g_object_set (g_test_data.sink, "silent", (gboolean) FALSE, NULL); } - /* enable emit-signal */ - g_object_set (g_test_data.sink, "emit-signal", TRUE, NULL); + /** set signal-rate */ + g_object_set (g_test_data.sink, "signal-rate", (guint) 15, NULL); - /* set render-rate */ - g_object_set (g_test_data.sink, "render-rate", (guint64) 15, NULL); - - /* signal for new data */ + /** signal for new data */ handle_id = g_signal_connect (g_test_data.sink, "new-data", (GCallback) _new_data_cb, NULL); EXPECT_TRUE (handle_id > 0); - _print_log ("start pipeline for render-rate test"); + _print_log ("start pipeline for signal-rate test"); gst_element_set_state (g_test_data.pipeline, GST_STATE_PLAYING); g_main_loop_run (g_test_data.loop); gst_element_set_state (g_test_data.pipeline, GST_STATE_NULL); - /* check eos message */ + /** check eos message */ EXPECT_EQ (g_test_data.status, TEST_EOS); - /* check received buffers */ + /** check received buffers */ EXPECT_TRUE (g_test_data.received < num_buffers); _free_test_data (); @@ -410,16 +354,16 @@ TEST (tensor_sink_test, unknown_case) ASSERT_TRUE (_setup_pipeline (num_buffers)); if (DBG) { - /* print logs */ - g_object_set (g_test_data.sink, "silent", FALSE, NULL); + /** print logs */ + g_object_set (g_test_data.sink, "silent", (gboolean) FALSE, NULL); } - /* try to set/get unknown property */ + /** try to set/get unknown property */ g_object_set (g_test_data.sink, "unknown-prop", 1, NULL); g_object_get (g_test_data.sink, "unknown-prop", &unknown, NULL); EXPECT_EQ (unknown, -1); - /* unknown signal */ + /** unknown signal */ handle_id = g_signal_connect (g_test_data.sink, "unknown-sig", (GCallback) _new_data_cb, NULL); EXPECT_EQ (handle_id, 0); @@ -429,10 +373,53 @@ TEST (tensor_sink_test, unknown_case) g_main_loop_run (g_test_data.loop); gst_element_set_state (g_test_data.pipeline, GST_STATE_NULL); - /* check eos message */ + /** check eos message */ EXPECT_EQ (g_test_data.status, TEST_EOS); - /* check received buffers */ + /** check received buffers */ + EXPECT_EQ (g_test_data.received, 0); + + _free_test_data (); +} + +/** + * @brief Test for caps negotiation failed. + */ +TEST (tensor_sink_test, caps_error) +{ + const guint num_buffers = 10; + gchar *str_pipeline; + + g_test_data.received = 0; + g_test_data.loop = g_main_loop_new (NULL, FALSE); + + /** cannot link videoconvert and tensor_sink */ + str_pipeline = + g_strdup_printf + ("videotestsrc num-buffers=%d ! video/x-raw,width=160,height=120,format=RGB,framerate=(fraction)30/1 ! " + "videoconvert ! tensor_sink name=test_sink", num_buffers); + g_test_data.pipeline = gst_parse_launch (str_pipeline, NULL); + g_free (str_pipeline); + + g_test_data.bus = gst_element_get_bus (g_test_data.pipeline); + gst_bus_add_signal_watch (g_test_data.bus); + g_signal_connect (g_test_data.bus, "message", (GCallback) _message_cb, NULL); + + g_test_data.sink = + gst_bin_get_by_name (GST_BIN (g_test_data.pipeline), "test_sink"); + + g_signal_connect (g_test_data.sink, "new-data", (GCallback) _new_data_cb, + NULL); + + _print_log ("start pipeline for caps error test"); + gst_element_set_state (g_test_data.pipeline, GST_STATE_PLAYING); + g_main_loop_run (g_test_data.loop); + gst_element_set_state (g_test_data.pipeline, GST_STATE_NULL); + + /** check error message */ + EXPECT_EQ (g_test_data.status, TEST_ERR_MESSAGE); + + /** check received buffers */ EXPECT_EQ (g_test_data.received, 0); _free_test_data (); -- 2.7.4