Search code examples
gstreamerkurento

Kurento: unable to apply GStreamer "audiocheblimit" + "cutter"


the following is my code block using which I am trying to remove noise from the incoming mediapipeline.

VADCustomFilterImpl::VADCustomFilterImpl(const boost::property_tree::ptree & config,std::shared_ptr <MediaPipeline > mediaPipeline) :FilterImpl (config,std::dynamic_pointer_cast <MediaObjectImpl> (mediaPipeline))
        {
            /* audio cheb limit - to remove noise */
            //GST_WARNING("------------------------audiocheblimit");
            g_object_set(element, "filter-factory", "audiocheblimit", NULL);
            g_object_get(G_OBJECT(element), "filter", &audiocheblimitfilter, NULL);

            if (audiocheblimitfilter == NULL) {
            throw KurentoException(MEDIA_OBJECT_NOT_FOUND, "MediaObject not found: audiocheblimitfilter");
            }

            g_object_set(G_OBJECT(audiocheblimitfilter), "mode", "low-pass", NULL);
            g_object_set(G_OBJECT(audiocheblimitfilter),"cutoff", 700, NULL);

            //GST_WARNING("----------------cutter");
            /*Cutter*/
            g_object_set(element, "filter-factory", "cutter", NULL);
            g_object_get(G_OBJECT(element), "filter", &cutterfilter, NULL);

            if (cutterfilter == NULL) {
                throw KurentoException(MEDIA_OBJECT_NOT_FOUND, "MediaObject not found: cutterfilter");
            }

            g_object_set(G_OBJECT(cutterfilter), "threshold-dB", -40.0, NULL);
            g_object_set(G_OBJECT(cutterfilter), "run-length", 500000000, NULL);

            //GST_WARNING("~~~~~~~~~~~~~~~~~~~~audiocheblimit+cutter");
            bus_handler_id = 0;

            g_object_unref(audiocheblimitfilter);
            g_object_unref(cutterfilter);
        }

in kurento logs only ------------------------audiocheblimit is getting printed, after which there is no log and in my java server console am getting Websocket disconnected by WebSocket Read EOF (status code 1006)

Is there any specific reason why this is crashing ? Can we apply two GStreamer plugins one after another in kurento?

Or Do we need to create multiple kurento custom filters which will use one single GStreamer plugin in it??

Edit 1:

as pointed by @santoscadenas, I have looked into faceoverlay project and made changes accordingly in my code,

#include "gstvadcustomfilter.h"
#include <gst/gst.h>
#include <glib/gstdio.h>
#include <gst/audio/audio.h>
#include <opencv2/opencv.hpp>
#include <cv.h>
#include <memory>

GST_DEBUG_CATEGORY_STATIC (gst_v_a_d_custom_filter_debug_category);
#define GST_CAT_DEFAULT gst_v_a_d_custom_filter_debug_category

#define PLUGIN_NAME "voicedetector"

#define GST_V_A_D_CUSTOM_FILTER_GET_PRIVATE(obj) (    \
    G_TYPE_INSTANCE_GET_PRIVATE (               \
        (obj),                                  \
        GST_TYPE_V_A_D_CUSTOM_FILTER,                 \
        GstVADCustomFilterPrivate                  \
                                )               \
                                           )

/* pad templates */

#define AUDIO_SRC_CAPS \
  GST_AUDIO_CAPS_MAKE("{ S16LE }")

#define AUDIO_SINK_CAPS \
  GST_AUDIO_CAPS_MAKE("{ S16LE }")

/* class initialization */
struct _GstVADCustomFilterPrivate
{
GstElement *audiocheb_limit;
GstElement *cutter_filter;
GstPad *src, *sink;
}priv;

//GstPad *tempsrc , *cuttersrcpad, *audiocheblimitsinkpad;

/* the capabilities of the inputs and outputs. */
GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
    GST_PAD_SINK,
    GST_PAD_ALWAYS,
    GST_STATIC_CAPS (        // the capabilities of the padtemplate
        AUDIO_SINK_CAPS
      )
    );

GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
    GST_PAD_SRC,
    GST_PAD_REQUEST,
    GST_STATIC_CAPS (        // the capabilities of the padtemplate
        AUDIO_SRC_CAPS
      )
    );

//G_DEFINE_TYPE (GstVADCustomFilter, gst_v_a_d_custom_filter, GST_TYPE_BIN);

G_DEFINE_TYPE_WITH_CODE (GstVADCustomFilter, gst_v_a_d_custom_filter,
                         GST_TYPE_BIN,
                         GST_DEBUG_CATEGORY_INIT (gst_v_a_d_custom_filter_debug_category,
                             PLUGIN_NAME, 0,
                             "debug category for v_a_d_custom_filter element") );


/*static GstFlowReturn
gst_v_a_d_custom_filter_transform_frame_ip (GstVideoFilter *filter,
                                      GstVideoFrame *frame)
{
GST_WARNING("gst_v_a_d_custom_filter_transform_frame_ip");
  return GST_FLOW_OK;
}*/

static void
gst_v_a_d_custom_filter_finalize (GObject *object)
{
GST_WARNING("Inside gst_v_a_d_custom_filter_finalize");
}

static void
gst_v_a_d_custom_filter_init (GstVADCustomFilter *v_a_d_custom_filter)
{
    GstPadTemplate *templ;
    GstPad *target;
    GST_ERROR("Inside gst_v_a_d_custom_filter_init");

    v_a_d_custom_filter->priv = GST_V_A_D_CUSTOM_FILTER_GET_PRIVATE (v_a_d_custom_filter);
    GST_ERROR("audio cheb limit");
    v_a_d_custom_filter->priv->audiocheb_limit =
    gst_element_factory_make ("audiocheblimit", NULL);

    g_object_set (v_a_d_custom_filter->priv->audiocheb_limit, "cutoff",700.0, NULL);

    gst_bin_add (GST_BIN (v_a_d_custom_filter), v_a_d_custom_filter->priv->audiocheb_limit);
    GST_ERROR("cutter");
    /*cutter*/
    v_a_d_custom_filter->priv->cutter_filter =
    gst_element_factory_make ("cutter", NULL);

    g_object_set (v_a_d_custom_filter->priv->cutter_filter, "threshold-dB",-40.0, NULL);
    g_object_set (v_a_d_custom_filter->priv->cutter_filter, "run-length",500000000, NULL);

    gst_bin_add (GST_BIN (v_a_d_custom_filter), v_a_d_custom_filter->priv->cutter_filter);
    GST_ERROR("cutter added to the bus");

    target = gst_element_get_static_pad (v_a_d_custom_filter->priv->audiocheb_limit, "sink");

    GST_ERROR("sink factory");
    templ = gst_static_pad_template_get (&sink_factory);
    GST_ERROR("sink , target, templ");

    v_a_d_custom_filter->priv->sink =
    gst_ghost_pad_new_from_template ("sink", target, templ);
    GST_ERROR("g_object_unref");
    g_object_unref (templ);
    g_object_unref (target);
    GST_ERROR("GST_ELEMENT (v_a_d_custom_filter), v_a_d_custom_filter->priv->sink");
    gst_element_add_pad (GST_ELEMENT (v_a_d_custom_filter), v_a_d_custom_filter->priv->sink);

    target = gst_element_get_static_pad (v_a_d_custom_filter->priv->cutter_filter, "src");
    GST_ERROR("src factory");
    templ = gst_static_pad_template_get (&src_factory);

    v_a_d_custom_filter->priv->src = gst_ghost_pad_new_from_template ("src", target, templ);
    g_object_unref (templ);
    g_object_unref (target);

    gst_element_add_pad (GST_ELEMENT (v_a_d_custom_filter), v_a_d_custom_filter->priv->src);
    gst_element_link (v_a_d_custom_filter->priv->audiocheb_limit, v_a_d_custom_filter->priv->cutter_filter);
}

static void
gst_v_a_d_custom_filter_class_init (GstVADCustomFilterClass *klass)
{
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
  //GstVideoFilterClass *video_filter_class = GST_VIDEO_FILTER_CLASS (klass);

  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, PLUGIN_NAME, 0, PLUGIN_NAME);

  gst_element_class_add_pad_template (GST_ELEMENT_CLASS (klass),
                                      gst_pad_template_new ("src", GST_PAD_SRC,
                                          GST_PAD_ALWAYS,
                                          gst_caps_from_string (AUDIO_SRC_CAPS) ) );
  gst_element_class_add_pad_template (GST_ELEMENT_CLASS (klass),
                                      gst_pad_template_new ("sink", GST_PAD_SINK,
                                          GST_PAD_ALWAYS,
                                          gst_caps_from_string (AUDIO_SINK_CAPS) ) );

  gst_element_class_set_static_metadata (GST_ELEMENT_CLASS (klass),
                                      "Voice Activity Detector", "Audio/Filter",
                                      "Using GStreamer Cutter Element",
                                      "Author: Sagar Pilkhwal");

  gobject_class->finalize = gst_v_a_d_custom_filter_finalize;

  //video_filter_class->transform_frame_ip =    GST_DEBUG_FUNCPTR (gst_v_a_d_custom_filter_transform_frame_ip);

}

gboolean
gst_v_a_d_custom_filter_plugin_init (GstPlugin *plugin)
{
  GST_WARNING("Inside gst_v_a_d_custom_filter_plugin_init");
  return gst_element_register (plugin, PLUGIN_NAME, GST_RANK_NONE, GST_TYPE_V_A_D_CUSTOM_FILTER);
}

server log:

(kurento-media-server:27765): GLib-GObject-CRITICAL **: g_object_set: assertion 'G_IS_OBJECT (object)' failed
(kurento-media-server:27765): GStreamer-CRITICAL **: gst_bin_add: assertion 'GST_IS_ELEMENT (element)' failed
(kurento-media-server:27765): GStreamer-CRITICAL **: gst_element_get_static_pad: assertion 'GST_IS_ELEMENT (element)' failed
(kurento-media-server:27765): GStreamer-CRITICAL **: gst_ghost_pad_new_from_template: assertion 'GST_IS_PAD (target)' failed
(kurento-media-server:27765): GLib-GObject-CRITICAL **: g_object_unref: assertion 'G_IS_OBJECT (object)' failed
(kurento-media-server:27765): GStreamer-CRITICAL **: gst_element_add_pad: assertion 'GST_IS_PAD (pad)' failed
[31;1mSegmentation fault[0m (thread [33;1m140450597959424[0m, pid [33;1m27765[0m)

Solution

  • The problem is that filter-factory can be only set once. Setting it twice won't work, it something that we have not tested and that can segfaults (as it seems it is happening).

    If you need to apply more than just one gstreamer element, create a wrapper (GstBin) that contains both and offers the same pads interface as one simple filter (one sink and one src). Inside the GstBin you can connect as much elements as you want.

    Edit

    You can can have an example of a GstBin encapsulating various elements here

    Edit 2

    The problem is on this line:

    g_object_set (G_OBJECT (audiocheblimit), "mode", "low-pass", NULL);
    

    "mode" is an enum and can be passed as a string but as a integer value.

    Edit 3

    It seems that you are not declaring your element correclty on .h file you need:

     typedef _GstVADCustomFilter {
       GstBin parent;
       ...
     } GstVADCustomFilter;
    

    And on your .c file:

     G_DEFINE_TYPE (GstVADCustomFilter, gst_v_a_d_custom_filter, GST_TYPE_BIN);