From 6233f9752f0ed46c74761a9665451e8fc1e3ec51 Mon Sep 17 00:00:00 2001 From: Jimena Salas Date: Fri, 26 Mar 2021 09:50:49 -0600 Subject: [PATCH] Remove embedding overlay related files --- ext/opencv/gstembeddingoverlay.cc | 352 ------------- ext/opencv/gstembeddingoverlay.h | 34 -- ext/r2inference/gstfacenetv1.c | 298 ----------- ext/r2inference/gstfacenetv1.h | 34 -- tests/examples/embedding/README.md | 27 - tests/examples/embedding/customlogic.cc | 65 --- tests/examples/embedding/customlogic.h | 45 -- .../embedding/embeddings/embeddings.txt | 1 - .../examples/embedding/embeddings/labels.txt | 1 - tests/examples/embedding/gstembedding.c | 463 ------------------ .../embedding/images/Barack_Obama.jpg | Bin 17201 -> 0 bytes .../embedding/images/Chuck_Norris.jpg | Bin 34367 -> 0 bytes tests/examples/embedding/meson.build | 10 - 13 files changed, 1330 deletions(-) delete mode 100644 ext/opencv/gstembeddingoverlay.cc delete mode 100644 ext/opencv/gstembeddingoverlay.h delete mode 100644 ext/r2inference/gstfacenetv1.c delete mode 100644 ext/r2inference/gstfacenetv1.h delete mode 100644 tests/examples/embedding/README.md delete mode 100644 tests/examples/embedding/customlogic.cc delete mode 100644 tests/examples/embedding/customlogic.h delete mode 100644 tests/examples/embedding/embeddings/embeddings.txt delete mode 100644 tests/examples/embedding/embeddings/labels.txt delete mode 100644 tests/examples/embedding/gstembedding.c delete mode 100644 tests/examples/embedding/images/Barack_Obama.jpg delete mode 100644 tests/examples/embedding/images/Chuck_Norris.jpg delete mode 100644 tests/examples/embedding/meson.build diff --git a/ext/opencv/gstembeddingoverlay.cc b/ext/opencv/gstembeddingoverlay.cc deleted file mode 100644 index ab5c1291..00000000 --- a/ext/opencv/gstembeddingoverlay.cc +++ /dev/null @@ -1,352 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2018-2020 RidgeRun - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * 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. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "gstembeddingoverlay.h" - -#include "gst/r2inference/gstinferencemeta.h" - -#define DEFAULT_EMBEDDINGS NULL -#define DEFAULT_NUM_EMBEDDINGS 0 -#define MIN_LIKENESS_THRESH 0.0 -#define MAX_LIKENESS_THRESH G_MAXDOUBLE -#define DEFAULT_LIKENESS_THRESH 1.0 - -/* *INDENT-OFF* */ -static const cv::Scalar forest_green = cv::Scalar (11, 102, 35); -static const cv::Scalar chilli_red = cv::Scalar (194, 24, 7); -static const cv::Scalar white = cv::Scalar (255, 255, 255, 255); -/* *INDENT-ON* */ - -GST_DEBUG_CATEGORY_STATIC (gst_embedding_overlay_debug_category); -#define GST_CAT_DEFAULT gst_embedding_overlay_debug_category - -/* prototypes */ -static void gst_embedding_overlay_set_property (GObject * object, - guint property_id, const GValue * value, GParamSpec * pspec); -static void gst_embedding_overlay_get_property (GObject * object, - guint property_id, GValue * value, GParamSpec * pspec); -static void gst_embedding_overlay_finalize (GObject * object); -static GstFlowReturn gst_embedding_overlay_process_meta (GstInferenceBaseOverlay - * inference_overlay, cv::Mat & cv_mat, GstVideoFrame * frame, - GstMeta * meta, gdouble font_scale, gint thickness, gchar ** labels_list, - gint num_labels, LineStyleBoundingBox style, gdouble alpha_overlay); -static gboolean gst_embedding_overlay_set_embeddings (GstEmbeddingOverlay * - embedding_overlay, const GValue * value); - -enum -{ - PROP_0, - PROP_EMBEDDINGS, - PROP_LIKENESS_THRESH -}; - -struct _GstEmbeddingOverlay -{ - GstInferenceBaseOverlay parent; - gchar *embeddings; - gchar **embeddings_list; - gint num_embeddings; - gint embedding_size; - gdouble likeness_thresh; -}; - -struct _GstClassificationOverlayClass -{ - GstInferenceBaseOverlay parent; -}; - -/* class initialization */ - -G_DEFINE_TYPE_WITH_CODE (GstEmbeddingOverlay, gst_embedding_overlay, - GST_TYPE_INFERENCE_BASE_OVERLAY, - GST_DEBUG_CATEGORY_INIT (gst_embedding_overlay_debug_category, - "embeddingoverlay", 0, "debug category for embedding_overlay element")); - -static void -gst_embedding_overlay_class_init (GstEmbeddingOverlayClass * klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - GstInferenceBaseOverlayClass *io_class = - GST_INFERENCE_BASE_OVERLAY_CLASS (klass); - - gobject_class->set_property = gst_embedding_overlay_set_property; - gobject_class->get_property = gst_embedding_overlay_get_property; - gobject_class->finalize = gst_embedding_overlay_finalize; - - g_object_class_install_property (gobject_class, PROP_EMBEDDINGS, - g_param_spec_string ("embeddings", "embeddings", - "String containing the embeddings. Consecutive values are \n\t\t\t" - "separated with a space and embedding with a semicolon.", - DEFAULT_EMBEDDINGS, G_PARAM_READWRITE)); - g_object_class_install_property (gobject_class, PROP_LIKENESS_THRESH, - g_param_spec_double ("likeness-threshold", "likeness-thresh", - "Likeness threshold to compare distance between embeddings.\n\t\t\t" - "For lower values the algorithm is stricter. 1.0 is recommended.", - MIN_LIKENESS_THRESH, MAX_LIKENESS_THRESH, DEFAULT_LIKENESS_THRESH, - G_PARAM_READWRITE)); - - gst_element_class_set_static_metadata (GST_ELEMENT_CLASS (klass), - "embeddingoverlay", "Filter", - "Overlays classification metadata on input buffer", - "Carlos Rodriguez \n\t\t\t" - " Jose Jimenez \n\t\t\t" - " Michael Gruner \n\t\t\t" - " Carlos Aguero \n\t\t\t" - " Miguel Taylor \n\t\t\t" - " Greivin Fallas "); - - io_class->process_meta = - GST_DEBUG_FUNCPTR (gst_embedding_overlay_process_meta); - io_class->meta_type = GST_CLASSIFICATION_META_API_TYPE; -} - -static void -gst_embedding_overlay_init (GstEmbeddingOverlay * embedding_overlay) -{ - embedding_overlay->embeddings = DEFAULT_EMBEDDINGS; - embedding_overlay->embeddings_list = DEFAULT_EMBEDDINGS; - embedding_overlay->num_embeddings = DEFAULT_NUM_EMBEDDINGS; - embedding_overlay->likeness_thresh = DEFAULT_LIKENESS_THRESH; -} - -void -gst_embedding_overlay_set_property (GObject * object, guint property_id, - const GValue * value, GParamSpec * pspec) -{ - GstEmbeddingOverlay *embedding_overlay = GST_EMBEDDING_OVERLAY (object); - - GST_DEBUG_OBJECT (embedding_overlay, "set_property"); - - switch (property_id) { - case PROP_EMBEDDINGS: - if (gst_embedding_overlay_set_embeddings (embedding_overlay, value)) { - GST_DEBUG_OBJECT (embedding_overlay, "Changed inference labels %s", - embedding_overlay->embeddings); - } else { - GST_ERROR_OBJECT (embedding_overlay, "Failed setting embeddings"); - } - break; - case PROP_LIKENESS_THRESH: - GST_OBJECT_LOCK (embedding_overlay); - embedding_overlay->likeness_thresh = g_value_get_double (value); - GST_DEBUG_OBJECT (embedding_overlay, - "Changed likeness threshold to %lf", - embedding_overlay->likeness_thresh); - GST_OBJECT_UNLOCK (embedding_overlay); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -void -gst_embedding_overlay_get_property (GObject * object, guint property_id, - GValue * value, GParamSpec * pspec) -{ - GstEmbeddingOverlay *embedding_overlay = GST_EMBEDDING_OVERLAY (object); - - GST_DEBUG_OBJECT (embedding_overlay, "get_property"); - - switch (property_id) { - case PROP_EMBEDDINGS: - GST_OBJECT_LOCK (embedding_overlay); - g_value_set_string (value, embedding_overlay->embeddings); - GST_OBJECT_UNLOCK (embedding_overlay); - break; - case PROP_LIKENESS_THRESH: - GST_OBJECT_LOCK (embedding_overlay); - g_value_set_double (value, embedding_overlay->likeness_thresh); - GST_OBJECT_UNLOCK (embedding_overlay); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -void -gst_embedding_overlay_finalize (GObject * object) -{ - GstEmbeddingOverlay *embedding_overlay = GST_EMBEDDING_OVERLAY (object); - - GST_DEBUG_OBJECT (embedding_overlay, "finalize"); - - /* clean up as possible. may be called multiple times */ - if (embedding_overlay->embeddings != NULL) { - g_free (embedding_overlay->embeddings); - } - if (embedding_overlay->embeddings_list != NULL) { - g_strfreev (embedding_overlay->embeddings_list); - } - - G_OBJECT_CLASS (gst_embedding_overlay_parent_class)->finalize (object); -} - -static GstFlowReturn -gst_embedding_overlay_process_meta (GstInferenceBaseOverlay * inference_overlay, - cv::Mat & cv_mat, GstVideoFrame * frame, GstMeta * meta, gdouble font_scale, - gint thickness, gchar ** labels_list, gint num_labels, - LineStyleBoundingBox, gdouble alpha_overlay ) -{ - GstEmbeddingOverlay *embedding_overlay = - GST_EMBEDDING_OVERLAY (inference_overlay); - GstClassificationMeta *class_meta; - gint i, j, width, height; - gdouble current, diff; - cv::String str; - cv::Size size; - cv::Scalar tmp_color; - cv::Scalar color = cv::Scalar (0, 0, 0, 0); - - gchar **embeddings_list; - gint num_embeddings; - gint embedding_size; - gdouble likeness_thresh; - - GST_OBJECT_LOCK (embedding_overlay); - embeddings_list = g_strdupv (embedding_overlay->embeddings_list); - num_embeddings = embedding_overlay->num_embeddings; - embedding_size = embedding_overlay->embedding_size; - likeness_thresh = embedding_overlay->likeness_thresh; - GST_OBJECT_UNLOCK (embedding_overlay); - - if (num_embeddings == 0) { - GST_WARNING_OBJECT (embedding_overlay, - "Please set at least one valid embedding using the 'embeddings'" - "property"); - goto end; - } - - class_meta = (GstClassificationMeta *) meta; - - if (class_meta->num_labels != embedding_size) { - GST_WARNING_OBJECT (embedding_overlay, - "Provided embeddings and inference output have different sizes"); - goto end; - } - - str = cv::format ("Fail"); - tmp_color[0] = chilli_red[0]; - tmp_color[1] = chilli_red[1]; - tmp_color[2] = chilli_red[2]; - for (i = 0; i < num_embeddings; ++i) { - diff = 0.0; - for (j = 0; j < embedding_size; ++j) { - current = class_meta->label_probs[j]; - current -= atof (embeddings_list[i * embedding_size + j]); - current = current * current; - diff = diff + current; - } - if (diff < likeness_thresh) { - if (num_labels > i) { - str = cv::format ("Pass: %s", labels_list[i]); - } else { - str = cv::format ("Pass"); - } - tmp_color[0] = forest_green[0]; - tmp_color[1] = forest_green[1]; - tmp_color[2] = forest_green[2]; - break; - } - } - - /* Convert color according to colorspace */ - switch (GST_VIDEO_FRAME_FORMAT (frame)) { - case GST_VIDEO_FORMAT_BGR: - case GST_VIDEO_FORMAT_BGRx: - case GST_VIDEO_FORMAT_BGRA: - color[0] = tmp_color[2]; - color[1] = tmp_color[1]; - color[2] = tmp_color[0]; - break; - case GST_VIDEO_FORMAT_xRGB: - case GST_VIDEO_FORMAT_ARGB: - color[1] = tmp_color[0]; - color[2] = tmp_color[1]; - color[3] = tmp_color[2]; - break; - case GST_VIDEO_FORMAT_xBGR: - case GST_VIDEO_FORMAT_ABGR: - color[1] = tmp_color[2]; - color[2] = tmp_color[1]; - color[3] = tmp_color[0]; - break; - default: - color = tmp_color; - break; - } - - width = cv_mat.cols; - height = cv_mat.rows; - - /* Put string on screen - * 10*font_scale+16 aproximates text's rendered size on screen as a - * lineal function to avoid using cv::getTextSize. - * 5*thickness adds the border offset - */ - cv::putText (cv_mat, str, cv::Point (5 * thickness, - 5 * thickness + 10 * font_scale + 16), cv::FONT_HERSHEY_PLAIN, - font_scale, white, thickness + (thickness * 0.5)); - cv::putText (cv_mat, str, cv::Point (5 * thickness, - 5 * thickness + 10 * font_scale + 16), cv::FONT_HERSHEY_PLAIN, - font_scale, color, thickness); - cv::rectangle (cv_mat, cv::Point (0, 0), cv::Point (width, height), color, - 10 * thickness); - -end: - g_strfreev (embeddings_list); - return GST_FLOW_OK; -} - -gboolean -gst_embedding_overlay_set_embeddings (GstEmbeddingOverlay * embedding_overlay, - const GValue * value) -{ - g_return_val_if_fail (embedding_overlay, FALSE); - g_return_val_if_fail (value, FALSE); - - GST_OBJECT_LOCK (embedding_overlay); - if (embedding_overlay->embeddings != NULL) { - g_free (embedding_overlay->embeddings); - } - if (embedding_overlay->embeddings_list != NULL) { - g_strfreev (embedding_overlay->embeddings_list); - } - embedding_overlay->embeddings = g_value_dup_string (value); - embedding_overlay->embeddings_list = - g_strsplit (g_value_get_string (value), ";", 0); - embedding_overlay->num_embeddings = - g_strv_length (embedding_overlay->embeddings_list); - g_strfreev (embedding_overlay->embeddings_list); - embedding_overlay->embeddings_list = - g_strsplit_set (g_value_get_string (value), "; ", 0); - embedding_overlay->embedding_size = - g_strv_length (embedding_overlay->embeddings_list) / - embedding_overlay->num_embeddings; - GST_OBJECT_UNLOCK (embedding_overlay); - - return TRUE; -} diff --git a/ext/opencv/gstembeddingoverlay.h b/ext/opencv/gstembeddingoverlay.h deleted file mode 100644 index 3a2b503e..00000000 --- a/ext/opencv/gstembeddingoverlay.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2018-2020 RidgeRun - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * 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. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#ifndef _GST_EMBEDDING_OVERLAY_H_ -#define _GST_EMBEDDING_OVERLAY_H_ - -#include - -G_BEGIN_DECLS - -#define GST_TYPE_EMBEDDING_OVERLAY (gst_embedding_overlay_get_type()) -G_DECLARE_FINAL_TYPE (GstEmbeddingOverlay, gst_embedding_overlay, GST, EMBEDDING_OVERLAY, GstInferenceBaseOverlay) - -G_END_DECLS - -#endif diff --git a/ext/r2inference/gstfacenetv1.c b/ext/r2inference/gstfacenetv1.c deleted file mode 100644 index 7e004e13..00000000 --- a/ext/r2inference/gstfacenetv1.c +++ /dev/null @@ -1,298 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2018-2020 RidgeRun - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * 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. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -/** - * SECTION:element-gstfacenetv1 - * - * The facenetv1 element allows the user to infer/execute a pretrained model - * based on the FaceNetV1 architecture on incoming image frames. - * - * - * Example launch line - * |[ - * gst-launch-1.0 -v videotestsrc ! facenetv1 ! xvimagesink - * ]| - * Process video frames from the camera using a FaceNet V1 model. - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "gstfacenetv1.h" -#include "gst/r2inference/gstinferencemeta.h" -#include -#include -#include "gst/r2inference/gstinferencepreprocess.h" -#include "gst/r2inference/gstinferencepostprocess.h" -#include "gst/r2inference/gstinferencedebug.h" - -GST_DEBUG_CATEGORY_STATIC (gst_facenetv1_debug_category); -#define GST_CAT_DEFAULT gst_facenetv1_debug_category - -#define MODEL_CHANNELS 3 - -/* prototypes */ -static void gst_facenetv1_set_property (GObject * object, - guint property_id, const GValue * value, GParamSpec * pspec); -static void gst_facenetv1_get_property (GObject * object, - guint property_id, GValue * value, GParamSpec * pspec); -static void gst_facenetv1_dispose (GObject * object); -static void gst_facenetv1_finalize (GObject * object); - -static gboolean gst_facenetv1_preprocess (GstVideoInference * vi, - GstVideoFrame * inframe, GstVideoFrame * outframe); -static gboolean gst_facenetv1_postprocess (GstVideoInference * vi, - const gpointer prediction, gsize predsize, GstMeta * meta_model[2], - GstVideoInfo * info_model, gboolean * valid_prediction, - gchar ** labels_list, gint num_labels); -static gboolean gst_facenetv1_postprocess_old (GstVideoInference * vi, - const gpointer prediction, gsize predsize, GstMeta * meta_model, - GstVideoInfo * info_model, gboolean * valid_prediction); -static gboolean gst_facenetv1_postprocess_new (GstVideoInference * vi, - const gpointer prediction, gsize predsize, GstMeta * meta_model, - GstVideoInfo * info_model, gboolean * valid_prediction, - gchar ** labels_list, gint num_labels); -static gboolean gst_facenetv1_start (GstVideoInference * vi); -static gboolean gst_facenetv1_stop (GstVideoInference * vi); - -enum -{ - PROP_0 -}; - -/* pad templates */ - -#define CAPS "video/x-raw,format=RGB,width=160,height=160" - -static GstStaticPadTemplate sink_model_factory = -GST_STATIC_PAD_TEMPLATE ("sink_model", - GST_PAD_SINK, - GST_PAD_REQUEST, - GST_STATIC_CAPS (CAPS) - ); - -static GstStaticPadTemplate src_model_factory = -GST_STATIC_PAD_TEMPLATE ("src_model", - GST_PAD_SRC, - GST_PAD_REQUEST, - GST_STATIC_CAPS (CAPS) - ); - -struct _GstFacenetv1 -{ - GstVideoInference parent; -}; - -struct _GstFacenetv1Class -{ - GstVideoInferenceClass parent; -}; - -/* class initialization */ - -G_DEFINE_TYPE_WITH_CODE (GstFacenetv1, gst_facenetv1, - GST_TYPE_VIDEO_INFERENCE, - GST_DEBUG_CATEGORY_INIT (gst_facenetv1_debug_category, "facenetv1", 0, - "debug category for facenetv1 element")); - -static void -gst_facenetv1_class_init (GstFacenetv1Class * klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - GstElementClass *element_class = GST_ELEMENT_CLASS (klass); - GstVideoInferenceClass *vi_class = GST_VIDEO_INFERENCE_CLASS (klass); - - gst_element_class_add_static_pad_template (element_class, - &sink_model_factory); - gst_element_class_add_static_pad_template (element_class, &src_model_factory); - - gst_element_class_set_static_metadata (GST_ELEMENT_CLASS (klass), - "facenetv1", "Filter", - "Infers incoming image frames using a pretrained FaceNet model", - "Carlos Rodriguez \n\t\t\t" - " Jose Jimenez \n\t\t\t" - " Michael Gruner "); - - gobject_class->set_property = gst_facenetv1_set_property; - gobject_class->get_property = gst_facenetv1_get_property; - gobject_class->dispose = gst_facenetv1_dispose; - gobject_class->finalize = gst_facenetv1_finalize; - - vi_class->start = GST_DEBUG_FUNCPTR (gst_facenetv1_start); - vi_class->stop = GST_DEBUG_FUNCPTR (gst_facenetv1_stop); - vi_class->preprocess = GST_DEBUG_FUNCPTR (gst_facenetv1_preprocess); - vi_class->postprocess = GST_DEBUG_FUNCPTR (gst_facenetv1_postprocess); - vi_class->inference_meta_info = gst_classification_meta_get_info (); -} - -static void -gst_facenetv1_init (GstFacenetv1 * facenetv1) -{ -} - -void -gst_facenetv1_set_property (GObject * object, guint property_id, - const GValue * value, GParamSpec * pspec) -{ - GstFacenetv1 *facenetv1 = GST_FACENETV1 (object); - - GST_DEBUG_OBJECT (facenetv1, "set_property"); - - switch (property_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -void -gst_facenetv1_get_property (GObject * object, guint property_id, - GValue * value, GParamSpec * pspec) -{ - GstFacenetv1 *facenetv1 = GST_FACENETV1 (object); - - GST_DEBUG_OBJECT (facenetv1, "get_property"); - - switch (property_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -void -gst_facenetv1_dispose (GObject * object) -{ - GstFacenetv1 *facenetv1 = GST_FACENETV1 (object); - - GST_DEBUG_OBJECT (facenetv1, "dispose"); - - /* clean up as possible. may be called multiple times */ - - G_OBJECT_CLASS (gst_facenetv1_parent_class)->dispose (object); -} - -void -gst_facenetv1_finalize (GObject * object) -{ - GstFacenetv1 *facenetv1 = GST_FACENETV1 (object); - - GST_DEBUG_OBJECT (facenetv1, "finalize"); - - /* clean up object here */ - - G_OBJECT_CLASS (gst_facenetv1_parent_class)->finalize (object); -} - -static gboolean -gst_facenetv1_preprocess (GstVideoInference * vi, - GstVideoFrame * inframe, GstVideoFrame * outframe) -{ - GST_LOG_OBJECT (vi, "Preprocess"); - return gst_normalize_face (inframe, outframe, MODEL_CHANNELS); -} - -static gboolean -gst_facenetv1_postprocess_old (GstVideoInference * vi, - const gpointer prediction, gsize predsize, GstMeta * meta_model, - GstVideoInfo * info_model, gboolean * valid_prediction) -{ - GstClassificationMeta *class_meta = (GstClassificationMeta *) meta_model; - GstDebugLevel gst_debug_level = GST_LEVEL_LOG; - - GST_LOG_OBJECT (vi, "Postprocess"); - - gst_fill_classification_meta (class_meta, prediction, predsize); - - gst_inference_print_highest_probability (vi, gst_facenetv1_debug_category, - class_meta, prediction, gst_debug_level); - - *valid_prediction = TRUE; - return TRUE; -} - -static gboolean -gst_facenetv1_postprocess_new (GstVideoInference * vi, - const gpointer prediction, gsize predsize, GstMeta * meta_model, - GstVideoInfo * info_model, gboolean * valid_prediction, - gchar ** labels_list, gint num_labels) -{ - GstInferenceMeta *imeta = NULL; - GstInferenceClassification *c = NULL; - GstInferencePrediction *root = NULL; - - g_return_val_if_fail (vi != NULL, FALSE); - g_return_val_if_fail (meta_model != NULL, FALSE); - g_return_val_if_fail (info_model != NULL, FALSE); - - GST_LOG_OBJECT (vi, "Postprocess Meta"); - - imeta = (GstInferenceMeta *) meta_model; - - root = imeta->prediction; - if (!root) { - GST_ERROR_OBJECT (vi, "Prediction is not part of the Inference Meta"); - return FALSE; - } - - c = gst_create_class_from_prediction (vi, prediction, predsize, labels_list, - num_labels); - gst_inference_prediction_append_classification (root, c); - gst_inference_print_predictions (vi, gst_facenetv1_debug_category, imeta); - - *valid_prediction = TRUE; - return TRUE; -} - -static gboolean -gst_facenetv1_postprocess (GstVideoInference * vi, const gpointer prediction, - gsize predsize, GstMeta * meta_model[2], GstVideoInfo * info_model, - gboolean * valid_prediction, gchar ** labels_list, gint num_labels) -{ - gboolean ret = TRUE; - - ret &= - gst_facenetv1_postprocess_old (vi, prediction, predsize, meta_model[0], - info_model, valid_prediction); - ret &= - gst_facenetv1_postprocess_new (vi, prediction, predsize, meta_model[1], - info_model, valid_prediction, labels_list, num_labels); - - return ret; -} - -static gboolean -gst_facenetv1_start (GstVideoInference * vi) -{ - GST_INFO_OBJECT (vi, "Starting Facenet v1"); - - return TRUE; -} - -static gboolean -gst_facenetv1_stop (GstVideoInference * vi) -{ - GST_INFO_OBJECT (vi, "Stopping Facenet v1"); - - return TRUE; -} diff --git a/ext/r2inference/gstfacenetv1.h b/ext/r2inference/gstfacenetv1.h deleted file mode 100644 index c91989b8..00000000 --- a/ext/r2inference/gstfacenetv1.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2018-2020 RidgeRun - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * 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. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#ifndef _GST_FACENETV1_H_ -#define _GST_FACENETV1_H_ - -#include - -G_BEGIN_DECLS - -#define GST_TYPE_FACENETV1 gst_facenetv1_get_type () -G_DECLARE_FINAL_TYPE (GstFacenetv1, gst_facenetv1, GST, FACENETV1, GstVideoInference) - -G_END_DECLS - -#endif diff --git a/tests/examples/embedding/README.md b/tests/examples/embedding/README.md deleted file mode 100644 index 5c3da9a8..00000000 --- a/tests/examples/embedding/README.md +++ /dev/null @@ -1,27 +0,0 @@ -# Embedding Example -This example receives video file, images or camera stream as input and process each frame to detect if a face is among the accepted set of faces. For each processed frame the application captures the signal emitted by GstInference, forwarding the prediction to a placeholder for external logic which computes if the metadata belongs to a valid face. Simultaneously, the pipeline displays the captured frames with the associated label in a window in case of valid face, otherwise a fail label will be displayed. - -# Parameters -* -m|--model -Mandatory. Path to the InceptionV4 trained model -* -f|--file -Optional. Path to the video file to be used. -If it is not set, a camera stream will be used. -* -b|--backend -Mandatory. Name of the backed to be used. See Supported Backends for a list of possible options. -* -e|--embeddings -Mandatory. Path to the text file with embeddings data containing valid faces -* -l|--labels -Mandatory. Path to the text file with labels associated to the embeddings file -* -v -Optional. Run verbosely, Can be used to obtain encoded metadata from custom images. -* -h|--help -Displays usage and parameters description - -# Usage -The embeddings and labels files provided for this demo can be found at 'embeddings' folder, those files provide the metadata from the 'images' folder. -``` -./embedding -m -f -b -e -l [-v] -``` -# More information -Please check our [developers](https://developer.ridgerun.com/wiki/index.php?title=GstInference/Example_Applications/Embedding) page for this example. diff --git a/tests/examples/embedding/customlogic.cc b/tests/examples/embedding/customlogic.cc deleted file mode 100644 index a26f7302..00000000 --- a/tests/examples/embedding/customlogic.cc +++ /dev/null @@ -1,65 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2018-2020 RidgeRun - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * 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. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#include "customlogic.h" -#include -#include - -void -handle_prediction (unsigned char *image, - int width, int height, unsigned int size, - double *embeddings, int num_dimensions, - int verbose, char **embeddings_list, char **labels, - int num_embeddings) -{ - /* FILLME: - * Put here your custom logic, you may use C++ here. - */ - - int i, j; - double current, diff; - double likeness_thresh = 0.9; - - for (i = 0; i < num_embeddings; ++i) { - diff = 0.0; - for (j = 0; j < num_dimensions; ++j) { - current = embeddings[j] - - atof (embeddings_list[i * num_dimensions + j]); - current = current * current; - diff = diff + current; - } - - if (diff < likeness_thresh) { - std::cout << "Authorized: " << labels[i] << std::endl; - break; - } - } - - if (verbose) { - std::cout << "Displaying embeddings from current frame" << std::endl; - - for (int i = 0; i < num_dimensions; ++i) { - std::cout << embeddings[i] << " "; - } - - std::cout << std::endl; - } -} diff --git a/tests/examples/embedding/customlogic.h b/tests/examples/embedding/customlogic.h deleted file mode 100644 index 17b4a189..00000000 --- a/tests/examples/embedding/customlogic.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2018-2020 RidgeRun - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * 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. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#ifndef __EMBEDDING_CUSTOM_LOGIC__ -#define __EMBEDDING_CUSTOM_LOGIC__ - -#ifdef __cplusplus -extern "C" { -#endif - -void -handle_prediction (unsigned char *image, - int width, - int height, - unsigned int size, - double *embeddings, - int num_dimensions, - int verbose, - char **embeddings_list, - char **labels, - int num_embeddings); - -#ifdef __cplusplus -} -#endif - -#endif //__EMBEDDING_CUSTOM_LOGIC__ diff --git a/tests/examples/embedding/embeddings/embeddings.txt b/tests/examples/embedding/embeddings/embeddings.txt deleted file mode 100644 index 866b24a1..00000000 --- a/tests/examples/embedding/embeddings/embeddings.txt +++ /dev/null @@ -1 +0,0 @@ --0.0145593 -0.0584495 0.0371784 -0.0912583 0.0490291 -0.0138151 -0.0323807 -0.0655067 0.0632302 -0.108694 0.13243 -0.0735193 0.00284548 -0.136761 -0.0199185 0.0698619 0.126645 0.1193 0.0110647 -0.111995 0.0158512 0.00433643 -0.0758559 0.0262919 0.0479901 0.0946619 0.0865307 0.117623 -0.0716868 -0.00987446 0.02357 0.153645 -0.0515243 0.0114069 0.0752071 -0.0052865 0.0569346 0.185266 0.13548 0.0183175 0.0196599 -0.0376986 0.125624 -0.163115 -0.081066 -0.0181404 0.0306145 -0.161885 0.0324361 -0.025209 0.0890772 0.0985957 0.169964 -0.0656467 0.132334 0.197022 -0.130948 -0.128935 0.0770448 -0.0759822 0.0719929 0.041964 -0.0149276 0.100265 0.0512894 0.0797284 0.0842571 0.00714669 -0.0802012 0.126848 0.102854 -0.0279055 0.0943478 -0.141276 -0.0672122 0.0512549 -0.0887869 0.00805435 -0.138771 -0.154171 0.0184849 -0.00798414 -0.0382218 0.262642 0.0620274 0.0160168 0.131385 -0.173691 -0.0936234 -0.0327744 -0.00891561 -0.0502745 -0.0983856 -0.0451589 0.0597074 -0.0466168 0.0568609 -0.0749385 0.0241126 -0.0180538 0.0295493 0.0973359 0.0317965 -0.121993 -0.000457776 0.162942 -0.127862 0.033625 -0.0521476 -0.022432 0.068894 0.0548606 0.0497928 0.0185768 0.0157577 0.0550619 -0.143579 0.0650198 -0.135888 -0.0184038 0.010344 -0.0246181 0.183069 0.0519738 0.00459688 -0.0259964 0.111819 -0.0981886;-0.0242322 0.00290796 -0.162734 0.0286987 0.0642769 -0.0359746 -0.0148205 -0.0628836 -0.116573 0.0260048 0.0582735 0.0380352 0.028675 -0.105973 0.0646818 0.0244191 0.0484146 -0.0989158 -0.0378393 0.135033 0.141195 -0.105727 -0.00524461 0.0412349 -0.0236515 -0.00295492 0.0143279 0.0563888 0.0473259 0.0471952 0.0906711 0.0400181 -0.0451043 0.04677 -0.141052 -0.156074 0.102902 -0.139874 -0.0758197 -0.0876225 0.0337217 0.0562246 0.047203 0.0574563 -0.0346048 0.0272441 0.1464 -0.11729 -0.0192566 0.0500386 -0.20818 0.00922727 -0.0418217 -0.0439746 -0.0460908 -0.0146872 0.128959 0.145776 -0.010307 -0.0502751 -0.0336426 0.0830565 0.151228 0.144064 -0.21205 0.0717333 0.0502196 -0.0608728 0.108237 -0.0956707 0.120978 -0.178943 -0.0360214 0.0257333 0.0886595 0.0511544 0.0311828 0.0356794 -0.00302341 -0.0439167 -0.0331555 -0.0353495 -0.0187001 -0.100847 0.0497707 0.179336 -0.164382 0.10775 0.00772931 -0.0325079 0.0483728 -0.195318 0.0763725 0.0769976 0.162546 0.0145742 -0.029331 -0.0993435 -0.148174 -0.0178964 -0.0752645 0.081258 0.128173 -0.0234716 0.0159863 -0.119493 0.0897941 0.0113501 -0.0650295 0.112933 -0.14094 0.12612 0.0619066 0.0242797 -0.106637 -0.0690303 -0.142767 -0.0396135 -0.0697015 -0.0323864 0.0244745 0.0639094 0.124145 -0.130794 0.0173324 -0.11673 0.116843 0.0512073 diff --git a/tests/examples/embedding/embeddings/labels.txt b/tests/examples/embedding/embeddings/labels.txt deleted file mode 100644 index 723b67a2..00000000 --- a/tests/examples/embedding/embeddings/labels.txt +++ /dev/null @@ -1 +0,0 @@ -Barack_Obama;Chuck_Norris diff --git a/tests/examples/embedding/gstembedding.c b/tests/examples/embedding/gstembedding.c deleted file mode 100644 index dbb9ff8c..00000000 --- a/tests/examples/embedding/gstembedding.c +++ /dev/null @@ -1,463 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2018-2020 RidgeRun - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * 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. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include -#include -#include -#include - -#include "customlogic.h" -#include "gst/r2inference/gstinferencemeta.h" - -#define GETTEXT_PACKAGE "GstInference" - -typedef struct _GstEmbedding GstEmbedding; -struct _GstEmbedding -{ - GstElement *pipeline; - GMainLoop *main_loop; - GstElement *inference_element; - gchar **embeddings_list; - gchar **labels_list; - int num_embeddings; -}; - -GstEmbedding *gst_embedding_new (void); -void gst_embedding_free (GstEmbedding * embedding); -void gst_embedding_create_pipeline (GstEmbedding * embedding); -void gst_embedding_start (GstEmbedding * embedding); -void gst_embedding_stop (GstEmbedding * embedding); -static void gst_embedding_process_inference (GstElement * element, - GstEmbeddingMeta * model_meta, GstVideoFrame * model_frame, - GstEmbeddingMeta * bypass_meta, GstVideoFrame * bypass_frame, - gpointer user_data); -static gboolean gst_embedding_exit_handler (gpointer user_data); -static gboolean gst_embedding_handle_message (GstBus * bus, - GstMessage * message, gpointer data); -gboolean verbose; -static gchar *gst_embedding_read_file (const gchar * file); - -static const gchar *model_path = NULL; -static const gchar *file_path = NULL; -static const gchar *embeddings_path = NULL; -static const gchar *labels_path = NULL; -static const gchar *backend = NULL; - -static GOptionEntry entries[] = { - {"verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Be verbose", NULL}, - {"model", 'm', 0, G_OPTION_ARG_STRING, &model_path, "Model path", NULL}, - {"embeddings", 'e', 0, G_OPTION_ARG_STRING, &embeddings_path, - "Path to file with encoded valid faces", NULL}, - {"labels", 'l', 0, G_OPTION_ARG_STRING, &labels_path, - "Path to labels from valid faces", NULL}, - {"file", 'f', 0, G_OPTION_ARG_STRING, &file_path, - "File path (or camera, if omitted)", NULL}, - {"backend", 'b', 0, G_OPTION_ARG_STRING, &backend, - "Backend used for inference, example: tensorflow", NULL}, - {NULL} -}; - -int -main (int argc, char *argv[]) -{ - GError *error = NULL; - GOptionContext *context; - GstEmbedding *embedding; - GMainLoop *main_loop; - - context = g_option_context_new (" - GstInference Embedding Example"); - g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE); - g_option_context_add_group (context, gst_init_get_option_group ()); - if (!g_option_context_parse (context, &argc, &argv, &error)) { - g_printerr ("option parsing failed: %s\n", error->message); - g_clear_error (&error); - g_option_context_free (context); - exit (1); - } - g_option_context_free (context); - - if (verbose) { - g_print ("Model Path: %s \n", model_path); - g_print ("File path: %s \n", file_path ? file_path : "camera"); - g_print ("Backend: %s \n", backend); - g_print ("Embeddings Path: %s \n", embeddings_path); - g_print ("Labels Path: %s \n", labels_path); - } - - if (!backend) { - g_printerr ("Backend is required for inference (-b ) \n"); - exit (1); - } - - if (!model_path) { - g_printerr ("Model path is required (-m ) \n"); - exit (1); - } - - if (!embeddings_path) { - g_printerr ("Embeddings path is required (-e ) \n"); - exit (1); - } - - if (!labels_path) { - g_printerr ("Labels path is required (-l ) \n"); - exit (1); - } - - embedding = gst_embedding_new (); - gst_embedding_create_pipeline (embedding); - - g_unix_signal_add (SIGINT, gst_embedding_exit_handler, embedding); - embedding->inference_element = - gst_bin_get_by_name (GST_BIN (embedding->pipeline), "net"); - - g_signal_connect (embedding->inference_element, "new-prediction", - G_CALLBACK (gst_embedding_process_inference), embedding); - - gst_embedding_start (embedding); - - main_loop = g_main_loop_new (NULL, TRUE); - embedding->main_loop = main_loop; - - g_main_loop_run (main_loop); - - gst_embedding_stop (embedding); - gst_embedding_free (embedding); - - exit (0); -} - -static gboolean -gst_embedding_exit_handler (gpointer data) -{ - GstEmbedding *embedding; - - g_return_val_if_fail (data, FALSE); - - embedding = (GstEmbedding *) data; - g_main_loop_quit (embedding->main_loop); - - return TRUE; -} - -static gchar * -gst_embedding_read_file (const gchar * file) -{ - - FILE *infile; - glong numbytes; - gchar *buffer; - size_t bytes_read; - - g_return_val_if_fail (file, NULL); - - infile = fopen (file, "r"); - if (infile == NULL) { - g_printerr ("The file does not exist \n"); - return NULL; - } - - fseek (infile, 0L, SEEK_END); - numbytes = ftell (infile); - fseek (infile, 0L, SEEK_SET); - - buffer = (gchar *) calloc (numbytes, sizeof (gchar)); - bytes_read = fread (buffer, sizeof (gchar), numbytes - 1, infile); - if (bytes_read == 0) { - g_printerr ("The file was not copied \n"); - return NULL; - } - - fclose (infile); - - return buffer; -} - -GstEmbedding * -gst_embedding_new (void) -{ - GstEmbedding *embedding; - - embedding = g_new0 (GstEmbedding, 1); - - return embedding; -} - -void -gst_embedding_free (GstEmbedding * embedding) -{ - - g_return_if_fail (embedding); - - if (embedding->inference_element) { - gst_object_unref (embedding->inference_element); - embedding->inference_element = NULL; - } - - if (embedding->pipeline) { - gst_element_set_state (embedding->pipeline, GST_STATE_NULL); - gst_object_unref (embedding->pipeline); - embedding->pipeline = NULL; - } - if (embedding->main_loop) { - g_main_loop_unref (embedding->main_loop); - embedding->main_loop = NULL; - } - - if (embedding->embeddings_list) { - g_strfreev (embedding->embeddings_list); - embedding->embeddings_list = NULL; - } - - if (embedding->labels_list) { - g_strfreev (embedding->labels_list); - embedding->labels_list = NULL; - } - - g_free (embedding); -} - -static void -gst_embedding_process_inference (GstElement * element, - GstEmbeddingMeta * model_meta, GstVideoFrame * model_frame, - GstEmbeddingMeta * bypass_meta, GstVideoFrame * bypass_frame, - gpointer user_data) -{ - GstEmbedding *embedding; - - g_return_if_fail (element); - g_return_if_fail (model_meta); - g_return_if_fail (model_frame); - g_return_if_fail (bypass_meta); - g_return_if_fail (bypass_frame); - g_return_if_fail (user_data); - - embedding = (GstEmbedding *) user_data; - - handle_prediction (bypass_frame->data[0], bypass_frame->info.width, - bypass_frame->info.height, bypass_frame->info.size, - bypass_meta->embedding, bypass_meta->num_dimensions, verbose, - embedding->embeddings_list, embedding->labels_list, - embedding->num_embeddings); -} - -void -gst_embedding_create_pipeline (GstEmbedding * embedding) -{ - GString *pipe_desc; - GstElement *pipeline; - GError *error = NULL; - GstBus *bus; - gchar *embeddings; - gchar *labels; - - g_return_if_fail (embedding); - - embeddings = gst_embedding_read_file (embeddings_path); - if (embeddings == NULL) { - g_printerr ("Error reading embeddings file \n"); - return; - } - - embedding->embeddings_list = g_strsplit (embeddings, ";", 0); - embedding->num_embeddings = g_strv_length (embedding->embeddings_list); - g_strfreev (embedding->embeddings_list); - embedding->embeddings_list = g_strsplit_set (embeddings, "; ", 0); - - labels = gst_embedding_read_file (labels_path); - if (labels == NULL) { - g_printerr ("Error reading labels file \n"); - return; - } - embedding->labels_list = g_strsplit (labels, ";", 0); - pipe_desc = g_string_new (""); - - if (file_path) { - g_string_append (pipe_desc, " filesrc location="); - g_string_append (pipe_desc, file_path); - g_string_append (pipe_desc, " ! decodebin ! "); - } else { - g_string_append (pipe_desc, " autovideosrc ! "); - } - - g_string_append (pipe_desc, " tee name=t t. ! queue ! videoconvert ! "); - g_string_append (pipe_desc, " videoscale ! net.sink_model t. ! "); - g_string_append (pipe_desc, " queue ! videoconvert ! net.sink_bypass "); - g_string_append (pipe_desc, " facenetv1 name=net backend="); - g_string_append (pipe_desc, backend); - g_string_append (pipe_desc, " model-location="); - g_string_append (pipe_desc, model_path); - if (!strcmp (backend, "tensorflow")) { - g_string_append (pipe_desc, " backend::input-layer=input "); - g_string_append (pipe_desc, " backend::output-layer=output "); - } - - g_string_append (pipe_desc, " net.src_bypass ! videoconvert ! "); - g_string_append (pipe_desc, " embeddingoverlay embeddings='"); - g_string_append (pipe_desc, embeddings); - g_string_append (pipe_desc, "' labels='"); - g_string_append (pipe_desc, labels); - g_string_append (pipe_desc, "' font-scale=1 likeness-threshold=0.9 "); - g_string_append (pipe_desc, " ! videoconvert ! queue ! "); - g_string_append (pipe_desc, " autovideosink sync=false"); - - g_free (embeddings); - g_free (labels); - - if (verbose) - g_print ("pipeline: %s\n", pipe_desc->str); - - pipeline = GST_ELEMENT (gst_parse_launch (pipe_desc->str, &error)); - g_string_free (pipe_desc, TRUE); - - if (error) { - g_print ("pipeline parsing error: %s\n", error->message); - g_clear_error (&error); - gst_object_unref (pipeline); - return; - } - - embedding->pipeline = pipeline; - - gst_pipeline_set_auto_flush_bus (GST_PIPELINE (pipeline), FALSE); - bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); - gst_bus_add_watch (bus, gst_embedding_handle_message, embedding); - gst_object_unref (bus); -} - -void -gst_embedding_start (GstEmbedding * embedding) -{ - g_return_if_fail (embedding); - - gst_element_set_state (embedding->pipeline, GST_STATE_PLAYING); -} - -void -gst_embedding_stop (GstEmbedding * embedding) -{ - g_return_if_fail (embedding); - - gst_element_set_state (embedding->pipeline, GST_STATE_NULL); -} - -static void -gst_embedding_handle_eos (GstEmbedding * embedding) -{ - g_return_if_fail (embedding); - - g_main_loop_quit (embedding->main_loop); -} - -static void -gst_embedding_handle_error (GstEmbedding * embedding, - GError * error, const char *debug) -{ - g_return_if_fail (embedding); - g_return_if_fail (error); - g_return_if_fail (debug); - - g_printerr ("error: %s\n", error->message); - g_main_loop_quit (embedding->main_loop); -} - -static void -gst_embedding_handle_warning (GstEmbedding * embedding, - GError * error, const char *debug) -{ - g_return_if_fail (embedding); - g_return_if_fail (error); - g_return_if_fail (debug); - - g_printerr ("warning: %s\n", error->message); -} - -static void -gst_embedding_handle_info (GstEmbedding * embedding, - GError * error, const char *debug) -{ - g_return_if_fail (embedding); - g_return_if_fail (error); - g_return_if_fail (debug); - - g_print ("info: %s\n", error->message); -} - -static gboolean -gst_embedding_handle_message (GstBus * bus, GstMessage * message, gpointer data) -{ - GstEmbedding *embedding; - - g_return_val_if_fail (bus, FALSE); - g_return_val_if_fail (message, FALSE); - g_return_val_if_fail (data, FALSE); - - embedding = (GstEmbedding *) data; - - switch (GST_MESSAGE_TYPE (message)) { - case GST_MESSAGE_EOS: - gst_embedding_handle_eos (embedding); - break; - case GST_MESSAGE_ERROR: - { - GError *error = NULL; - gchar *debug; - - gst_message_parse_error (message, &error, &debug); - gst_embedding_handle_error (embedding, error, debug); - g_clear_error (&error); - } - break; - case GST_MESSAGE_WARNING: - { - GError *error = NULL; - gchar *debug; - - gst_message_parse_warning (message, &error, &debug); - gst_embedding_handle_warning (embedding, error, debug); - g_clear_error (&error); - } - break; - case GST_MESSAGE_INFO: - { - GError *error = NULL; - gchar *debug; - - gst_message_parse_info (message, &error, &debug); - gst_embedding_handle_info (embedding, error, debug); - g_clear_error (&error); - } - break; - default: - if (verbose) { - g_print ("message: %s\n", GST_MESSAGE_TYPE_NAME (message)); - } - break; - } - - return TRUE; -} diff --git a/tests/examples/embedding/images/Barack_Obama.jpg b/tests/examples/embedding/images/Barack_Obama.jpg deleted file mode 100644 index e3e185ab77297a78f2c47a721cc63bb050180cc0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17201 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
w 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 diff --git a/tests/examples/embedding/images/Chuck_Norris.jpg b/tests/examples/embedding/images/Chuck_Norris.jpg deleted file mode 100644 index cf13617b1d2e0e4ff2b37ad590f51d7740f3f049..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 34367 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