Now all the exe-examples are migrated to nnstreamer-example repository.
TODO : we have to set up the app-test with the example repo.
Signed-off-by: Jaeyun Jung <jy1210.jung@samsung.com>
ADD_SUBDIRECTORY(custom_example_opencv)
ADD_SUBDIRECTORY(custom_example_RNN)
ADD_SUBDIRECTORY(custom_example_LSTM)
-ADD_SUBDIRECTORY(example_cam)
-ADD_SUBDIRECTORY(example_sink)
-ADD_SUBDIRECTORY(example_filter)
+++ /dev/null
-pkg_check_modules(app_ex_cam_pkgs gstreamer-1.0 glib-2.0 REQUIRED)
-
-ADD_EXECUTABLE(nnstreamer_example_cam nnstreamer_example_cam.c)
-
-TARGET_LINK_LIBRARIES(nnstreamer_example_cam ${app_ex_cam_pkgs_LIBRARIES})
-TARGET_INCLUDE_DIRECTORIES(nnstreamer_example_cam PUBLIC ${app_ex_cam_pkgs_INCLUDE_DIRS})
-TARGET_COMPILE_OPTIONS(nnstreamer_example_cam PUBLIC ${app_ex_cam_pkgs_CFLAGS_OTHER})
-
-IF (INSTALL_EXAMPLE_APP)
- INSTALL(TARGETS nnstreamer_example_cam RUNTIME DESTINATION ${EXAMPLE_EXEC_PREFIX})
-ENDIF (INSTALL_EXAMPLE_APP)
+++ /dev/null
-nnstreamer_example_cam = executable('nnstreamer_example_cam',
- 'nnstreamer_example_cam.c',
- dependencies: [glib_dep, gst_dep],
- install: get_option('install-example'),
- install_dir: examples_install_dir
-)
+++ /dev/null
-/**
- * @file nnstreamer_example_cam.c
- * @date 10 July 2018
- * @brief Tensor stream example
- * @author Jaeyun Jung <jy1210.jung@samsung.com>
- * @bug No known bugs.
- *
- * Sample code for tensor stream, this app shows video frame.
- *
- * Run example :
- * Before running this example, GST_PLUGIN_PATH should be updated for nnstreamer plug-in.
- * $ export GST_PLUGIN_PATH=$GST_PLUGIN_PATH:<nnstreamer plugin path>
- * $ ./nnstreamer_example_cam
- */
-
-#include <fcntl.h>
-#include <unistd.h>
-
-#include <gst/gst.h>
-
-/**
- * @brief Macro for debug mode.
- */
-#ifndef DBG
-#define DBG FALSE
-#endif
-
-/**
- * @brief Macro for debug message.
- */
-#define _print_log(...) if (DBG) g_message (__VA_ARGS__)
-
-/**
- * @brief Macro to check error case.
- */
-#define _check_cond_err(cond) \
- if (!(cond)) { \
- _print_log ("app failed! [line : %d]", __LINE__); \
- goto error; \
- }
-
-/**
- * @brief Data structure for app.
- */
-typedef struct
-{
- GMainLoop *loop; /**< main event loop */
- GstElement *pipeline; /**< gst pipeline for data stream */
- GstBus *bus; /**< gst bus for data pipeline */
-} AppData;
-
-/**
- * @brief Data for pipeline and result.
- */
-static AppData g_app;
-
-/**
- * @brief Free resources in app data.
- */
-static void
-_free_app_data (void)
-{
- if (g_app.loop) {
- g_main_loop_unref (g_app.loop);
- g_app.loop = 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.pipeline) {
- gst_object_unref (g_app.pipeline);
- g_app.pipeline = NULL;
- }
-}
-
-/**
- * @brief Function to print error message.
- */
-static void
-_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);
- break;
-
- case GST_MESSAGE_WARNING:
- gst_message_parse_warning (message, &error, &debug);
- break;
-
- default:
- return;
- }
-
- gst_object_default_error (GST_MESSAGE_SRC (message), error, debug);
- g_error_free (error);
- g_free (debug);
-}
-
-/**
- * @brief Callback for message.
- */
-static void
-_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.loop);
- break;
-
- case GST_MESSAGE_ERROR:
- _print_log ("received error message");
- _parse_err_message (message);
- g_main_loop_quit (g_app.loop);
- break;
-
- case GST_MESSAGE_WARNING:
- _print_log ("received warning message");
- _parse_err_message (message);
- break;
-
- case GST_MESSAGE_STREAM_START:
- _print_log ("received start message");
- break;
-
- default:
- break;
- }
-}
-
-/**
- * @brief Set window title.
- * @param name GstXImageSink element name
- * @param title window title
- */
-static void
-_set_window_title (const gchar * name, const gchar * title)
-{
- GstTagList *tags;
- GstPad *sink_pad;
- GstElement *element;
-
- element = gst_bin_get_by_name (GST_BIN (g_app.pipeline), name);
-
- g_return_if_fail (element != NULL);
-
- sink_pad = gst_element_get_static_pad (element, "sink");
-
- if (sink_pad) {
- tags = gst_tag_list_new (GST_TAG_TITLE, title, NULL);
- gst_pad_send_event (sink_pad, gst_event_new_tag (tags));
- gst_object_unref (sink_pad);
- }
-
- gst_object_unref (element);
-}
-
-/**
- * @brief Main function.
- */
-int
-main (int argc, char **argv)
-{
- const guint width = 640;
- const guint height = 480;
-
- gchar *str_pipeline;
- gulong handle_id;
- GstElement *element;
-
- _print_log ("start app..");
-
- /** init gstreamer */
- gst_init (&argc, &argv);
-
- /** main loop */
- g_app.loop = g_main_loop_new (NULL, FALSE);
- _check_cond_err (g_app.loop != NULL);
-
- /** init pipeline */
- str_pipeline =
- g_strdup_printf
- ("v4l2src name=cam_src ! videoscale ! "
- "video/x-raw,width=%d,height=%d,format=RGB ! tee name=t_raw "
- "videomixer name=mix "
- "sink_0::xpos=0 sink_0::ypos=0 sink_0::zorder=0 "
- "sink_1::xpos=0 sink_1::ypos=0 sink_1::zorder=1 sink_1::alpha=0.7 ! "
- "videoconvert ! ximagesink name=img_mixed "
- "t_raw. ! queue ! mix.sink_0 "
- "t_raw. ! queue ! tensor_converter ! tensor_decoder mode=direct_video ! videoscale ! video/x-raw,width=%d,height=%d ! mix.sink_1 "
- "t_raw. ! queue ! videoconvert ! ximagesink name=img_origin",
- width, height, width / 2, height / 2);
- g_app.pipeline = gst_parse_launch (str_pipeline, NULL);
- g_free (str_pipeline);
- _check_cond_err (g_app.pipeline != NULL);
-
- /** bus and 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.bus);
- handle_id = g_signal_connect (g_app.bus, "message",
- (GCallback) _message_cb, NULL);
- _check_cond_err (handle_id > 0);
-
- /** start pipeline */
- gst_element_set_state (g_app.pipeline, GST_STATE_PLAYING);
-
- /** set window title */
- _set_window_title ("img_mixed", "Mixed");
- _set_window_title ("img_origin", "Original");
-
- /** run main loop */
- g_main_loop_run (g_app.loop);
- /** quit when received eos or error message */
-
- /** cam source element */
- element = gst_bin_get_by_name (GST_BIN (g_app.pipeline), "cam_src");
-
- gst_element_set_state (element, GST_STATE_READY);
- gst_element_set_state (g_app.pipeline, GST_STATE_READY);
-
- g_usleep (200 * 1000);
-
- gst_element_set_state (element, GST_STATE_NULL);
- gst_element_set_state (g_app.pipeline, GST_STATE_NULL);
-
- g_usleep (200 * 1000);
- gst_object_unref (element);
-
-error:
- _print_log ("close app..");
- _free_app_data ();
- return 0;
-}
+++ /dev/null
-pkg_check_modules(app_ex_filter_pkgs gstreamer-1.0 glib-2.0 REQUIRED)
-
-ADD_EXECUTABLE(nnstreamer_example_filter nnstreamer_example_filter.c)
-
-TARGET_LINK_LIBRARIES(nnstreamer_example_filter ${app_ex_filter_pkgs_LIBRARIES})
-TARGET_INCLUDE_DIRECTORIES(nnstreamer_example_filter PUBLIC ${app_ex_filter_pkgs_INCLUDE_DIRS})
-TARGET_COMPILE_OPTIONS(nnstreamer_example_filter PUBLIC ${app_ex_filter_pkgs_CFLAGS_OTHER})
-
-IF (INSTALL_EXAMPLE_APP)
- INSTALL(TARGETS nnstreamer_example_filter RUNTIME DESTINATION ${EXAMPLE_EXEC_PREFIX})
-ENDIF (INSTALL_EXAMPLE_APP)
+++ /dev/null
-nnstreamer_example_filter = executable('nnstreamer_example_filter',
- 'nnstreamer_example_filter.c',
- dependencies: [glib_dep, gst_dep],
- install: get_option('install-example'),
- install_dir: examples_install_dir
-)
-
-if get_option('install-example')
- install_data('nnstreamer_example_filter.py',
- install_dir: examples_install_dir
- )
-endif
+++ /dev/null
-/**
- * @file nnstreamer_example_filter.c
- * @date 13 July 2018
- * @brief Tensor stream example with filter
- * @author Jaeyun Jung <jy1210.jung@samsung.com>
- * @bug No known bugs.
- *
- * NNStreamer example for image recognition.
- *
- * Pipeline :
- * v4l2src -- tee -- textoverlay -- videoconvert -- ximagesink
- * |
- * --- videoscale -- tensor_converter -- tensor_filter -- tensor_sink
- *
- * This app displays video sink.
- *
- * 'tensor_filter' for image recognition.
- * Download tflite moel 'Mobilenet_1.0_224_quant' from below link,
- * https://github.com/nnsuite/testcases/tree/master/DeepLearningModels/tensorflow-lite/Mobilenet_v1_1.0_224_quant
- *
- * 'tensor_sink' updates recognition result to display in textoverlay.
- *
- * Run example :
- * Before running this example, GST_PLUGIN_PATH should be updated for nnstreamer plug-in.
- * $ export GST_PLUGIN_PATH=$GST_PLUGIN_PATH:<nnstreamer plugin path>
- * $ ./nnstreamer_example_filter
- */
-
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <glib.h>
-#include <gst/gst.h>
-
-/**
- * @brief Macro for debug mode.
- */
-#ifndef DBG
-#define DBG FALSE
-#endif
-
-/**
- * @brief Macro for debug message.
- */
-#define _print_log(...) if (DBG) g_message (__VA_ARGS__)
-
-/**
- * @brief Macro to check error case.
- */
-#define _check_cond_err(cond) \
- if (!(cond)) { \
- _print_log ("app failed! [line : %d]", __LINE__); \
- goto error; \
- }
-
-/**
- * @brief Data structure for tflite model info.
- */
-typedef struct
-{
- gchar *model_path; /**< tflite model file path */
- gchar *label_path; /**< label file path */
- GList *labels; /**< list of loaded labels */
- guint total_labels; /**< count of labels */
-} tflite_info_s;
-
-/**
- * @brief Data structure for app.
- */
-typedef struct
-{
- GMainLoop *loop; /**< main event loop */
- GstElement *pipeline; /**< gst pipeline for data stream */
- GstBus *bus; /**< gst bus for data pipeline */
-
- gboolean running; /**< true when app is running */
- guint received; /**< received buffer count */
- gint current_label_index; /**< current label index */
- gint new_label_index; /**< new label index */
- tflite_info_s tflite_info; /**< tflite model info */
-} AppData;
-
-/**
- * @brief Data for pipeline and result.
- */
-static AppData g_app;
-
-/**
- * @brief Free data in tflite info structure.
- */
-static void
-_tflite_free_info (tflite_info_s * tflite_info)
-{
- g_return_if_fail (tflite_info != NULL);
-
- if (tflite_info->model_path) {
- g_free (tflite_info->model_path);
- tflite_info->model_path = NULL;
- }
-
- if (tflite_info->label_path) {
- g_free (tflite_info->label_path);
- tflite_info->label_path = NULL;
- }
-
- if (tflite_info->labels) {
- g_list_free_full (tflite_info->labels, g_free);
- tflite_info->labels = NULL;
- }
-}
-
-/**
- * @brief Check tflite model and load labels.
- *
- * This example uses 'Mobilenet_1.0_224_quant' for image classification.
- */
-static gboolean
-_tflite_init_info (tflite_info_s * tflite_info, const gchar * path)
-{
- const gchar tflite_model[] = "mobilenet_v1_1.0_224_quant.tflite";
- const gchar tflite_label[] = "labels.txt";
-
- FILE *fp;
-
- g_return_val_if_fail (tflite_info != NULL, FALSE);
-
- tflite_info->model_path = NULL;
- tflite_info->label_path = NULL;
- tflite_info->labels = NULL;
-
- /** check model file exists */
- tflite_info->model_path = g_strdup_printf ("%s/%s", path, tflite_model);
-
- if (access (tflite_info->model_path, F_OK) != 0) {
- _print_log ("cannot find tflite model [%s]", tflite_info->model_path);
- return FALSE;
- }
-
- /** load labels */
- tflite_info->label_path = g_strdup_printf ("%s/%s", path, tflite_label);
-
- if ((fp = fopen (tflite_info->label_path, "r")) != NULL) {
- char *line = NULL;
- size_t len = 0;
- ssize_t read;
- gchar *label;
-
- while ((read = getline (&line, &len, fp)) != -1) {
- label = g_strdup ((gchar *) line);
- tflite_info->labels = g_list_append (tflite_info->labels, label);
- }
-
- if (line) {
- free (line);
- }
-
- fclose (fp);
- } else {
- _print_log ("cannot find tflite label [%s]", tflite_info->label_path);
- return FALSE;
- }
-
- tflite_info->total_labels = g_list_length (tflite_info->labels);
- _print_log ("finished to load labels, total %d", tflite_info->total_labels);
- return TRUE;
-}
-
-/**
- * @brief Get label string with given index.
- */
-static gchar *
-_tflite_get_label (tflite_info_s * tflite_info, gint index)
-{
- guint length;
-
- g_return_val_if_fail (tflite_info != NULL, NULL);
- g_return_val_if_fail (tflite_info->labels != NULL, NULL);
-
- length = g_list_length (tflite_info->labels);
- g_return_val_if_fail (index >= 0 && index < length, NULL);
-
- return (gchar *) g_list_nth_data (tflite_info->labels, index);
-}
-
-/**
- * @brief Update tflite label index with max score.
- * @param scores array of scores
- * @param len array length
- * @return None
- */
-static void
-_update_top_label_index (guint8 * scores, guint len)
-{
- gint i;
- gint index = -1;
- guint8 max_score = 0;
-
- /** -1 if failed to get max score index */
- g_app.new_label_index = -1;
-
- g_return_if_fail (scores != NULL);
- g_return_if_fail (len == g_app.tflite_info.total_labels);
-
- for (i = 0; i < len; i++) {
- if (scores[i] > 0 && scores[i] > max_score) {
- index = i;
- max_score = scores[i];
- }
- }
-
- g_app.new_label_index = index;
-}
-
-/**
- * @brief Free resources in app data.
- */
-static void
-_free_app_data (void)
-{
- if (g_app.loop) {
- g_main_loop_unref (g_app.loop);
- g_app.loop = 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.pipeline) {
- gst_object_unref (g_app.pipeline);
- g_app.pipeline = NULL;
- }
-
- _tflite_free_info (&g_app.tflite_info);
-}
-
-/**
- * @brief Function to print error message.
- */
-static void
-_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);
- break;
-
- case GST_MESSAGE_WARNING:
- gst_message_parse_warning (message, &error, &debug);
- break;
-
- default:
- return;
- }
-
- gst_object_default_error (GST_MESSAGE_SRC (message), error, debug);
- g_error_free (error);
- g_free (debug);
-}
-
-/**
- * @brief Function to print qos message.
- */
-static void
-_parse_qos_message (GstMessage * message)
-{
- GstFormat format;
- guint64 processed;
- guint64 dropped;
-
- gst_message_parse_qos_stats (message, &format, &processed, &dropped);
- _print_log ("format[%d] processed[%" G_GUINT64_FORMAT "] dropped[%"
- G_GUINT64_FORMAT "]", format, processed, dropped);
-}
-
-/**
- * @brief Callback for message.
- */
-static void
-_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.loop);
- break;
-
- case GST_MESSAGE_ERROR:
- _print_log ("received error message");
- _parse_err_message (message);
- g_main_loop_quit (g_app.loop);
- break;
-
- case GST_MESSAGE_WARNING:
- _print_log ("received warning message");
- _parse_err_message (message);
- break;
-
- case GST_MESSAGE_STREAM_START:
- _print_log ("received start message");
- break;
-
- case GST_MESSAGE_QOS:
- _parse_qos_message (message);
- break;
-
- default:
- break;
- }
-}
-
-/**
- * @brief Callback for tensor sink signal.
- */
-static void
-_new_data_cb (GstElement * element, GstBuffer * buffer, gpointer user_data)
-{
- /** print progress */
- g_app.received++;
- _print_log ("receiving new data [%d]", g_app.received);
-
- if (g_app.running) {
- 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)) {
- /** update label index with max score */
- _update_top_label_index (info.data, (guint) info.size);
-
- gst_memory_unmap (mem, &info);
- }
- }
- }
-}
-
-/**
- * @brief Set window title.
- * @param name GstXImageSink element name
- * @param title window title
- */
-static void
-_set_window_title (const gchar * name, const gchar * title)
-{
- GstTagList *tags;
- GstPad *sink_pad;
- GstElement *element;
-
- element = gst_bin_get_by_name (GST_BIN (g_app.pipeline), name);
-
- g_return_if_fail (element != NULL);
-
- sink_pad = gst_element_get_static_pad (element, "sink");
-
- if (sink_pad) {
- tags = gst_tag_list_new (GST_TAG_TITLE, title, NULL);
- gst_pad_send_event (sink_pad, gst_event_new_tag (tags));
- gst_object_unref (sink_pad);
- }
-
- gst_object_unref (element);
-}
-
-/**
- * @brief Timer callback for textoverlay.
- * @return True to ensure the timer continues
- */
-static gboolean
-_timer_update_result_cb (gpointer user_data)
-{
- if (g_app.running) {
- GstElement *overlay;
- gchar *label = NULL;
-
- if (g_app.current_label_index != g_app.new_label_index) {
- g_app.current_label_index = g_app.new_label_index;
-
- overlay = gst_bin_get_by_name (GST_BIN (g_app.pipeline), "tensor_res");
-
- label = _tflite_get_label (&g_app.tflite_info, g_app.current_label_index);
- g_object_set (overlay, "text", (label != NULL) ? label : "", NULL);
-
- gst_object_unref (overlay);
- }
- }
-
- return TRUE;
-}
-
-/**
- * @brief Main function.
- */
-int
-main (int argc, char **argv)
-{
- const gchar tflite_model_path[] = "./tflite_model";
-
- gchar *str_pipeline;
- gulong handle_id;
- guint timer_id = 0;
- GstElement *element;
-
- _print_log ("start app..");
-
- /** init app variable */
- g_app.running = FALSE;
- g_app.received = 0;
- g_app.current_label_index = -1;
- g_app.new_label_index = -1;
-
- _check_cond_err (_tflite_init_info (&g_app.tflite_info, tflite_model_path));
-
- /** init gstreamer */
- gst_init (&argc, &argv);
-
- /** main loop */
- g_app.loop = g_main_loop_new (NULL, FALSE);
- _check_cond_err (g_app.loop != NULL);
-
- /** init pipeline */
- str_pipeline =
- g_strdup_printf
- ("v4l2src name=cam_src ! videoscale ! "
- "video/x-raw,width=640,height=480,format=RGB ! tee name=t_raw "
- "t_raw. ! queue ! textoverlay name=tensor_res font-desc=Sans,24 ! "
- "videoconvert ! ximagesink name=img_tensor "
- "t_raw. ! queue leaky=2 max-size-buffers=2 ! videoscale ! tensor_converter ! "
- "tensor_filter framework=tensorflow-lite model=%s ! "
- "tensor_sink name=tensor_sink",
- g_app.tflite_info.model_path);
- g_app.pipeline = gst_parse_launch (str_pipeline, NULL);
- g_free (str_pipeline);
- _check_cond_err (g_app.pipeline != NULL);
-
- /** bus and 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.bus);
- handle_id = g_signal_connect (g_app.bus, "message",
- (GCallback) _message_cb, NULL);
- _check_cond_err (handle_id > 0);
-
- /** tensor sink signal : new data callback */
- element = gst_bin_get_by_name (GST_BIN (g_app.pipeline), "tensor_sink");
- handle_id = g_signal_connect (element, "new-data",
- (GCallback) _new_data_cb, NULL);
- gst_object_unref (element);
- _check_cond_err (handle_id > 0);
-
- /** timer to update result */
- timer_id = g_timeout_add (500, _timer_update_result_cb, NULL);
- _check_cond_err (timer_id > 0);
-
- /** start pipeline */
- gst_element_set_state (g_app.pipeline, GST_STATE_PLAYING);
-
- g_app.running = TRUE;
-
- /** set window title */
- _set_window_title ("img_tensor", "NNStreamer Example");
-
- /** run main loop */
- g_main_loop_run (g_app.loop);
- /** quit when received eos or error message */
- g_app.running = FALSE;
-
- /** cam source element */
- element = gst_bin_get_by_name (GST_BIN (g_app.pipeline), "cam_src");
-
- gst_element_set_state (element, GST_STATE_READY);
- gst_element_set_state (g_app.pipeline, GST_STATE_READY);
-
- g_usleep (200 * 1000);
-
- gst_element_set_state (element, GST_STATE_NULL);
- gst_element_set_state (g_app.pipeline, GST_STATE_NULL);
-
- g_usleep (200 * 1000);
- gst_object_unref (element);
-
-error:
- _print_log ("close app..");
-
- if (timer_id > 0) {
- g_source_remove (timer_id);
- }
-
- _free_app_data ();
- return 0;
-}
+++ /dev/null
-# !/usr/bin/env python
-
-"""
-@file nnstreamer_example_filter.py
-@date 18 July 2018
-@brief Tensor stream example with filter
-@see https://github.com/nnsuite/nnstreamer
-@author Jaeyun Jung <jy1210.jung@samsung.com>
-@bug No known bugs.
-
-NNStreamer example for image recognition.
-
-Pipeline :
-v4l2src -- tee -- textoverlay -- videoconvert -- ximagesink
- |
- --- videoscale -- tensor_converter -- tensor_filter -- tensor_sink
-
-This app displays video sink.
-
-'tensor_filter' for image recognition.
-Download tflite moel 'Mobilenet_1.0_224_quant' from below link,
-https://github.com/nnsuite/testcases/tree/master/DeepLearningModels/tensorflow-lite/Mobilenet_v1_1.0_224_quant
-
-'tensor_sink' updates recognition result to display in textoverlay.
-
-Run example :
-Before running this example, GST_PLUGIN_PATH should be updated for nnstreamer plugin.
-$ export GST_PLUGIN_PATH=$GST_PLUGIN_PATH:<nnstreamer plugin path>
-$ python nnstreamer_example_filter.py
-
-See https://lazka.github.io/pgi-docs/#Gst-1.0 for Gst API details.
-"""
-
-import os
-import sys
-import logging
-import gi
-
-gi.require_version('Gst', '1.0')
-from gi.repository import Gst, GObject
-
-
-class NNStreamerExample:
- """NNStreamer example for image recognition."""
-
- def __init__(self, argv=None):
- self.loop = None
- self.pipeline = None
- self.running = False
- self.current_label_index = -1
- self.new_label_index = -1
- self.tflite_model = ''
- self.tflite_labels = []
-
- if not self.tflite_init():
- raise Exception
-
- GObject.threads_init()
- Gst.init(argv)
-
- def run_example(self):
- """Init pipeline and run example.
-
- :return: None
- """
- # main loop
- self.loop = GObject.MainLoop()
-
- # init pipeline
- self.pipeline = Gst.parse_launch(
- 'v4l2src name=cam_src ! videoscale ! '
- 'video/x-raw,width=640,height=480,format=RGB ! tee name=t_raw '
- 't_raw. ! queue ! textoverlay name=tensor_res font-desc=Sans,24 ! '
- 'videoconvert ! ximagesink name=img_tensor '
- 't_raw. ! queue leaky=2 max-size-buffers=2 ! videoscale ! tensor_converter ! '
- 'tensor_filter framework=tensorflow-lite model=' + self.tflite_model + ' ! '
- 'tensor_sink name=tensor_sink'
- )
-
- # bus and message callback
- bus = self.pipeline.get_bus()
- bus.add_signal_watch()
- bus.connect('message', self.on_bus_message)
-
- # tensor sink signal : new data callback
- tensor_sink = self.pipeline.get_by_name('tensor_sink')
- tensor_sink.connect('new-data', self.on_new_data)
-
- # timer to update result
- GObject.timeout_add(500, self.on_timer_update_result)
-
- # start pipeline
- self.pipeline.set_state(Gst.State.PLAYING)
- self.running = True
-
- # set window title
- self.set_window_title('img_tensor', 'NNStreamer Example')
-
- # run main loop
- self.loop.run()
- # quit when received eos or error message
-
- self.running = False
- self.pipeline.set_state(Gst.State.NULL)
-
- bus.remove_signal_watch()
-
- def on_bus_message(self, bus, message):
- """Callback for message.
-
- :param bus: pipeline bus
- :param message: message from pipeline
- :return: None
- """
- if message.type == Gst.MessageType.EOS:
- logging.info('received eos message')
- self.loop.quit()
- elif message.type == Gst.MessageType.ERROR:
- error, debug = message.parse_error()
- logging.warning('[error] %s : %s', error.message, debug)
- self.loop.quit()
- elif message.type == Gst.MessageType.WARNING:
- error, debug = message.parse_warning()
- logging.warning('[warning] %s : %s', error.message, debug)
- elif message.type == Gst.MessageType.STREAM_START:
- logging.info('received start message')
- elif message.type == Gst.MessageType.QOS:
- data_format, processed, dropped = message.parse_qos_stats()
- format_str = Gst.Format.get_name(data_format)
- logging.debug('[qos] format[%s] processed[%d] dropped[%d]', format_str, processed, dropped)
-
- def on_new_data(self, sink, buffer):
- """Callback for tensor sink signal.
-
- :param sink: tensor sink element
- :param buffer: buffer from element
- :return: None
- """
- if self.running:
- for idx in range(buffer.n_memory()):
- mem = buffer.peek_memory(idx)
- result, mapinfo = mem.map(Gst.MapFlags.READ)
- if result:
- # update label index with max score
- self.update_top_label_index(mapinfo.data, mapinfo.size)
- mem.unmap(mapinfo)
-
- def on_timer_update_result(self):
- """Timer callback for textoverlay.
-
- :return: True to ensure the timer continues
- """
- if self.running:
- if self.current_label_index != self.new_label_index:
- # update textoverlay
- self.current_label_index = self.new_label_index
- label = self.tflite_get_label(self.current_label_index)
- textoverlay = self.pipeline.get_by_name('tensor_res')
- textoverlay.set_property('text', label)
- return True
-
- def set_window_title(self, name, title):
- """Set window title.
-
- :param name: GstXImageSink element name
- :param title: window title
- :return: None
- """
- element = self.pipeline.get_by_name(name)
- if element is not None:
- pad = element.get_static_pad('sink')
- if pad is not None:
- tags = Gst.TagList.new_empty()
- tags.add_value(Gst.TagMergeMode.APPEND, 'title', title)
- pad.send_event(Gst.Event.new_tag(tags))
-
- def tflite_init(self):
- """Check tflite model and load labels.
-
- :return: True if successfully initialized
- """
- tflite_model = 'mobilenet_v1_1.0_224_quant.tflite'
- tflite_label = 'labels.txt'
- current_folder = os.path.dirname(os.path.abspath(__file__))
- model_folder = os.path.join(current_folder, 'tflite_model')
-
- # check model file exists
- self.tflite_model = os.path.join(model_folder, tflite_model)
- if not os.path.exists(self.tflite_model):
- logging.error('cannot find tflite model [%s]', self.tflite_model)
- return False
-
- # load labels
- label_path = os.path.join(model_folder, tflite_label)
- try:
- with open(label_path, 'r') as label_file:
- for line in label_file.readlines():
- self.tflite_labels.append(line)
- except FileNotFoundError:
- logging.error('cannot find tflite label [%s]', label_path)
- return False
-
- logging.info('finished to load labels, total [%d]', len(self.tflite_labels))
- return True
-
- def tflite_get_label(self, index):
- """Get label string with given index.
-
- :param index: index for label
- :return: label string
- """
- try:
- label = self.tflite_labels[index]
- except IndexError:
- label = ''
- return label
-
- def update_top_label_index(self, data, data_size):
- """Update tflite label index with max score.
-
- :param data: array of scores
- :param data_size: data size
- :return: None
- """
- # -1 if failed to get max score index
- self.new_label_index = -1
-
- if data_size == len(self.tflite_labels):
- scores = [data[i] for i in range(data_size)]
- max_score = max(scores)
- if max_score > 0:
- self.new_label_index = scores.index(max_score)
- else:
- logging.error('unexpected data size [%d]', data_size)
-
-
-if __name__ == '__main__':
- example = NNStreamerExample(sys.argv[1:])
- example.run_example()
+++ /dev/null
-pkg_check_modules(app_ex_sink_pkgs gstreamer-1.0 gstreamer-app-1.0 glib-2.0 REQUIRED)
-
-# example 1
-ADD_EXECUTABLE(nnstreamer_sink_example nnstreamer_sink_example.c)
-
-TARGET_LINK_LIBRARIES(nnstreamer_sink_example ${app_ex_sink_pkgs_LIBRARIES})
-TARGET_INCLUDE_DIRECTORIES(nnstreamer_sink_example PUBLIC ${app_ex_sink_pkgs_INCLUDE_DIRS})
-TARGET_COMPILE_OPTIONS(nnstreamer_sink_example PUBLIC ${app_ex_sink_pkgs_CFLAGS_OTHER})
-
-# example 2
-ADD_EXECUTABLE(nnstreamer_sink_example_play nnstreamer_sink_example_play.c)
-
-TARGET_LINK_LIBRARIES(nnstreamer_sink_example_play ${app_ex_sink_pkgs_LIBRARIES})
-TARGET_INCLUDE_DIRECTORIES(nnstreamer_sink_example_play PUBLIC ${app_ex_sink_pkgs_INCLUDE_DIRS})
-TARGET_COMPILE_OPTIONS(nnstreamer_sink_example_play PUBLIC ${app_ex_sink_pkgs_CFLAGS_OTHER})
-
-IF (INSTALL_EXAMPLE_APP)
- INSTALL(TARGETS nnstreamer_sink_example nnstreamer_sink_example_play RUNTIME DESTINATION ${EXAMPLE_EXEC_PREFIX})
-ENDIF (INSTALL_EXAMPLE_APP)
+++ /dev/null
-nnstreamer_sink_example = executable('nnstreamer_sink_example',
- 'nnstreamer_sink_example.c',
- dependencies: [glib_dep, gst_dep, gst_app_dep],
- install: get_option('install-example'),
- install_dir: examples_install_dir
-)
-
-nnstreamer_sink_example_play = executable('nnstreamer_sink_example_play',
- 'nnstreamer_sink_example_play.c',
- dependencies: [glib_dep, gst_dep, gst_app_dep],
- install: get_option('install-example'),
- install_dir: examples_install_dir
-)
+++ /dev/null
-/**
- * @file nnstreamer_sink_example.c
- * @date 3 July 2018
- * @brief Sample code for tensor sink plugin
- * @see https://github.com/nnsuite/nnstreamer
- * @author Jaeyun Jung <jy1210.jung@samsung.com>
- * @bug No known bugs.
- *
- * Simple example to init tensor sink element and get data.
- *
- * Run example :
- * Before running this example, GST_PLUGIN_PATH should be updated for nnstreamer plug-in.
- * $ export GST_PLUGIN_PATH=$GST_PLUGIN_PATH:<nnstreamer plugin path>
- * $ ./nnstreamer_sink_example
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <gst/gst.h>
-#include <gst/app/gstappsrc.h>
-
-/**
- * @brief Macro for debug mode.
- */
-#ifndef DBG
-#define DBG FALSE
-#endif
-
-/**
- * @brief Macro for debug message.
- */
-#define _print_log(...) if (DBG) g_message (__VA_ARGS__)
-
-/**
- * @brief Macro to check error case.
- */
-#define _check_cond_err(cond) \
- if (!(cond)) { \
- _print_log ("app failed! [line : %d]", __LINE__); \
- goto error; \
- }
-
-/**
- * @brief Test media type.
- */
-typedef enum
-{
- TEST_TYPE_VIDEO,
- TEST_TYPE_AUDIO,
- TEST_TYPE_TEXT
-} test_media_type;
-
-/**
- * @brief Data structure for app.
- */
-typedef struct
-{
- GMainLoop *loop; /**< main event loop */
- GstElement *pipeline; /**< gst pipeline for test */
- GstBus *bus; /**< gst bus for test */
-
- guint received; /**< received buffer count */
- test_media_type media_type; /**< test media type */
-} AppData;
-
-/**
- * @brief Data for pipeline and result.
- */
-static AppData g_app;
-
-/**
- * @brief Free resources in app data.
- */
-static void
-_free_app_data (void)
-{
- if (g_app.loop) {
- if (g_main_loop_is_running (g_app.loop)) {
- g_main_loop_quit (g_app.loop);
- }
-
- g_main_loop_unref (g_app.loop);
- g_app.loop = 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.pipeline) {
- gst_object_unref (g_app.pipeline);
- g_app.pipeline = NULL;
- }
-}
-
-/**
- * @brief Function to print error message.
- */
-static void
-_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);
- break;
-
- case GST_MESSAGE_WARNING:
- gst_message_parse_warning (message, &error, &debug);
- break;
-
- default:
- return;
- }
-
- gst_object_default_error (GST_MESSAGE_SRC (message), error, debug);
- g_error_free (error);
- g_free (debug);
-}
-
-/**
- * @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
-_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.loop);
- break;
-
- case GST_MESSAGE_ERROR:
- _print_log ("received error message");
- _parse_err_message (message);
- g_main_loop_quit (g_app.loop);
- break;
-
- case GST_MESSAGE_WARNING:
- _print_log ("received warning message");
- _parse_err_message (message);
- break;
-
- case GST_MESSAGE_STREAM_START:
- _print_log ("received start message");
- break;
-
- default:
- break;
- }
-}
-
-/**
- * @brief Callback for signal new-data.
- */
-static void
-_new_data_cb (GstElement * element, GstBuffer * buffer, gpointer user_data)
-{
- g_app.received++;
- if (g_app.received % 150 == 0) {
- _print_log ("receiving new data [%d]", g_app.received);
- }
-
- /** example to get data */
- {
- 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) */
- if (g_app.media_type == TEST_TYPE_TEXT) {
- _print_log ("received %zd [%s]", info.size, (gchar *) info.data);
- } else {
- _print_log ("received %zd", info.size);
- }
-
- gst_memory_unmap (mem, &info);
- }
- }
- }
-
- /** example to get caps */
- {
- GstPad *sink_pad;
- GstCaps *caps;
-
- sink_pad = gst_element_get_static_pad (element, "sink");
-
- if (sink_pad) {
- /** negotiated */
- caps = gst_pad_get_current_caps (sink_pad);
-
- if (caps) {
- _parse_caps (caps);
- gst_caps_unref (caps);
- }
-
- /** template */
- caps = gst_pad_get_pad_template_caps (sink_pad);
-
- if (caps) {
- _parse_caps (caps);
- gst_caps_unref (caps);
- }
-
- gst_object_unref (sink_pad);
- }
- }
-}
-
-/**
- * @brief Callback for signal stream-start.
- */
-static void
-_stream_start_cb (GstElement * element, gpointer user_data)
-{
- _print_log ("stream start callback");
-}
-
-/**
- * @brief Callback for signal eos.
- */
-static void
-_eos_cb (GstElement * element, gpointer user_data)
-{
- _print_log ("eos callback");
-}
-
-/**
- * @brief Timer callback to push buffer.
- * @return True to ensure the timer continues
- */
-static gboolean
-_test_src_timer_cb (gpointer user_data)
-{
- GstElement *appsrc;
- GstBuffer *buf;
- guint buffer_index;
-
- buffer_index = g_app.received + 1;
- appsrc = gst_bin_get_by_name (GST_BIN (g_app.pipeline), "appsrc");
-
- switch (g_app.media_type) {
- case TEST_TYPE_TEXT:
- {
- gchar *text_data;
-
- /** send 20 text buffers */
- if (buffer_index > 20) {
- if (gst_app_src_end_of_stream (GST_APP_SRC (appsrc)) != GST_FLOW_OK) {
- _print_log ("failed to indicate eos");
- }
- return FALSE;
- }
-
- text_data = g_strdup_printf ("example for text [%d/20]", buffer_index);
- buf = gst_buffer_new_wrapped (text_data, strlen (text_data));
-
- GST_BUFFER_PTS (buf) = 20 * GST_MSECOND * buffer_index;
- GST_BUFFER_DURATION (buf) = 20 * GST_MSECOND;
-
- if (gst_app_src_push_buffer (GST_APP_SRC (appsrc), buf) != GST_FLOW_OK) {
- _print_log ("failed to push buffer [%d]", buffer_index);
- }
-
- break;
- }
- default:
- /** nothing to do */
- return FALSE;
- }
-
- return TRUE;
-}
-
-/**
- * @brief Test pipeline for given type.
- * @param type test media type
- */
-static gchar *
-_test_pipeline (test_media_type type)
-{
- gchar *str_pipeline;
-
- switch (type) {
- case TEST_TYPE_VIDEO:
- /** video 640x480 30fps 100 buffers */
- str_pipeline =
- g_strdup_printf
- ("videotestsrc num-buffers=100 ! video/x-raw,format=RGB,width=640,height=480 ! "
- "tensor_converter ! tensor_sink name=tensor_sink");
- break;
-
- case TEST_TYPE_AUDIO:
- /** audio sample rate 16000 (16 bits, signed, little endian) 30 buffers */
- str_pipeline =
- g_strdup_printf
- ("audiotestsrc num-buffers=30 ! audio/x-raw,format=S16LE,rate=16000 ! "
- "tensor_converter ! tensor_sink name=tensor_sink");
- break;
-
- case TEST_TYPE_TEXT:
- /** text 20 buffers */
- str_pipeline =
- g_strdup_printf
- ("appsrc name=appsrc caps=text/x-raw,format=utf8 ! "
- "tensor_converter ! tensor_sink name=tensor_sink");
- break;
-
- default:
- return NULL;
- }
-
- return str_pipeline;
-}
-
-/**
- * @brief Main function.
- */
-int
-main (int argc, char **argv)
-{
- test_media_type test_type = TEST_TYPE_VIDEO;
- gchar *str_pipeline;
- gulong handle_id;
- GstStateChangeReturn state_ret;
- GstElement *element;
-
- if (argc > 1) {
- test_type = atoi (argv[1]);
- }
-
- /** init gstreamer */
- gst_init (&argc, &argv);
-
- /** init app variable */
- g_app.received = 0;
- g_app.media_type = test_type;
-
- /** main loop and pipeline */
- g_app.loop = g_main_loop_new (NULL, FALSE);
- _check_cond_err (g_app.loop != NULL);
-
- str_pipeline = _test_pipeline (test_type);
- g_app.pipeline = gst_parse_launch (str_pipeline, NULL);
- g_free (str_pipeline);
- _check_cond_err (g_app.pipeline != 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.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 */
- 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 (element, "silent", (gboolean) FALSE, 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 (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 (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 (element, "eos", (GCallback) _eos_cb, NULL);
- _check_cond_err (handle_id > 0);
-
- 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);
-
- _check_cond_err (g_timeout_add (20, _test_src_timer_cb, NULL) > 0);
-
- /** run main loop */
- g_main_loop_run (g_app.loop);
- /** quit when received eos message */
-
- 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.received);
-
-error:
- _free_app_data ();
- return 0;
-}
+++ /dev/null
-/**
- * @file nnstreamer_sink_example_play.c
- * @date 5 July 2018
- * @brief Sample code for tensor sink plugin
- * @author Jaeyun Jung <jy1210.jung@samsung.com>
- * @bug No known bugs.
- *
- * This sample app shows video frame using two pipelines.
- *
- * [1st pipeline : videotestsrc-tensor_converter-tensor_sink]
- * push buffer to appsrc
- * [2nd pipeline : appsrc-tensor_decoder-videoconvert-ximagesink]
- *
- * Run example :
- * Before running this example, GST_PLUGIN_PATH should be updated for nnstreamer plug-in.
- * $ export GST_PLUGIN_PATH=$GST_PLUGIN_PATH:<nnstreamer plugin path>
- * $ ./nnstreamer_sink_example_play
- */
-
-#include <gst/gst.h>
-#include <gst/app/gstappsrc.h>
-
-/**
- * @brief Macro for debug mode.
- */
-#ifndef DBG
-#define DBG FALSE
-#endif
-
-/**
- * @brief Macro for debug message.
- */
-#define _print_log(...) if (DBG) g_message (__VA_ARGS__)
-
-/**
- * @brief Macro to check error case.
- */
-#define _check_cond_err(cond) \
- if (!(cond)) { \
- _print_log ("app failed! [line : %d]", __LINE__); \
- goto error; \
- }
-
-/**
- * @brief Data structure for app.
- */
-typedef struct
-{
- GMainLoop *loop; /**< main event loop */
- GstElement *data_pipeline; /**< gst pipeline for data stream */
- GstBus *data_bus; /**< gst bus for data pipeline */
- GstElement *player_pipeline; /**< gst pipeline for player */
- GstBus *player_bus; /**< gst bus for player pipeline */
-
- gboolean set_caps; /**< caps passed to player pipeline */
- guint received; /**< received buffer count */
-} AppData;
-
-/**
- * @brief Data for pipeline and result.
- */
-static AppData g_app;
-
-/**
- * @brief Free resources in app data.
- */
-static void
-_free_app_data (void)
-{
- 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.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_pipeline) {
- gst_object_unref (g_app.data_pipeline);
- g_app.data_pipeline = NULL;
- }
-
- if (g_app.player_pipeline) {
- gst_object_unref (g_app.player_pipeline);
- g_app.player_pipeline = NULL;
- }
-}
-
-/**
- * @brief Function to print error message.
- */
-static void
-_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);
- break;
-
- case GST_MESSAGE_WARNING:
- gst_message_parse_warning (message, &error, &debug);
- break;
-
- default:
- return;
- }
-
- gst_object_default_error (GST_MESSAGE_SRC (message), error, debug);
- g_error_free (error);
- g_free (debug);
-}
-
-/**
- * @brief Callback for 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");
- 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.loop);
- break;
-
- case GST_MESSAGE_WARNING:
- _print_log ("[data] received warning message");
- _parse_err_message (message);
- break;
-
- case GST_MESSAGE_STREAM_START:
- _print_log ("[data] received start message");
- break;
-
- default:
- break;
- }
-}
-
-/**
- * @brief Callback for message.
- */
-static void
-_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.loop);
- break;
-
- case GST_MESSAGE_ERROR:
- _print_log ("[player] received error message");
- _parse_err_message (message);
- g_main_loop_quit (g_app.loop);
- break;
-
- case GST_MESSAGE_WARNING:
- _print_log ("[player] received warning message");
- _parse_err_message (message);
- break;
-
- case GST_MESSAGE_STREAM_START:
- _print_log ("[player] received start message");
- break;
-
- default:
- break;
- }
-}
-
-/**
- * @brief Callback for signal new-data.
- */
-static void
-_new_data_cb (GstElement * element, GstBuffer * buffer, gpointer user_data)
-{
- GstElement *player_src;
-
- g_app.received++;
- if (g_app.received % 150 == 0) {
- _print_log ("receiving new data [%d]", g_app.received);
- }
-
- 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 (element, "sink");
-
- if (sink_pad) {
- caps = gst_pad_get_current_caps (sink_pad);
-
- if (caps) {
- gst_app_src_set_caps (GST_APP_SRC (player_src), caps);
-
- gst_caps_unref (caps);
- g_app.set_caps = TRUE;
- }
-
- gst_object_unref (sink_pad);
- }
- }
-
- gst_app_src_push_buffer (GST_APP_SRC (player_src), gst_buffer_copy (buffer));
- gst_object_unref (player_src);
-}
-
-/**
- * @brief Main function.
- */
-int
-main (int argc, char **argv)
-{
- const guint width = 640;
- const guint height = 480;
-
- gchar *str_pipeline;
- gulong handle_id;
- GstElement *element;
-
- /** init gstreamer */
- gst_init (&argc, &argv);
-
- /** init app variable */
- g_app.set_caps = FALSE;
- g_app.received = 0;
-
- /** 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_pipeline = gst_parse_launch (str_pipeline, NULL);
- g_free (str_pipeline);
- _check_cond_err (g_app.data_pipeline != 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_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 */
- 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 (element, "silent", (gboolean) FALSE, 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 (element, "new-data",
- (GCallback) _new_data_cb, NULL);
- _check_cond_err (handle_id > 0);
-
- gst_object_unref (element);
-
- /** init player pipeline */
- str_pipeline =
- g_strdup_printf
- ("appsrc name=player_src ! tensor_decoder mode=direct_video ! videoconvert ! ximagesink");
- g_app.player_pipeline = gst_parse_launch (str_pipeline, NULL);
- g_free (str_pipeline);
- _check_cond_err (g_app.player_pipeline != 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.player_bus);
- handle_id = g_signal_connect (g_app.player_bus, "message",
- (GCallback) _player_message_cb, NULL);
- _check_cond_err (handle_id > 0);
-
- /** start pipeline */
- gst_element_set_state (g_app.data_pipeline, GST_STATE_PLAYING);
- gst_element_set_state (g_app.player_pipeline, GST_STATE_PLAYING);
-
- /** run main loop */
- g_main_loop_run (g_app.loop);
- /** quit when received eos message */
-
- 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 ();
- return 0;
-}
subdir('custom_example_opencv')
subdir('custom_example_RNN')
subdir('custom_example_LSTM')
-subdir('example_cam')
-subdir('example_sink')
-subdir('example_filter')
Development package for custom tensor operator developers (tensor_filter/custom).
This contains corresponding header files and .pc pkgconfig file.
-%package example
+%package custom-filter-example
Summary: NNStreamer example custom plugins and test plugins
Requires: nnstreamer = %{version}-%{release}
-%description example
+%description custom-filter-example
Example custom tensor_filter subplugins and
plugins created for test purpose.
%{_datadir}/nnstreamer/unittest/*
%endif
-%files example
+%files custom-filter-example
%manifest nnstreamer.manifest
%defattr(-,root,root,-)
%license LICENSE
%{_libdir}/*.so
-%{nnstexampledir}/*
%exclude %{_libdir}/libtensor_filter_tflitecore.so
%ifarch x86_64 aarch64
%exclude %{_libdir}/libtensor_filter_tfcore.so