Kurento: невозможно применить GStreamer audiocheblimit + cutter

Ниже приведен мой блок кода, с помощью которого я пытаюсь удалить шум из входящего медиаконвейера.

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);
        }

в журналах kurento печатается только ------------------------audiocheblimit, после чего журнала нет, а в консоли моего java-сервера я получаю Websocket disconnected by WebSocket Read EOF (status code 1006)

Есть ли какая-то конкретная причина, почему это падает? Можем ли мы применить два плагина GStreamer один за другим в kurento?

Или нам нужно создать несколько пользовательских фильтров kurento, которые будут использовать в нем один плагин GStreamer ??

Редактировать 1:

как указал @santoscadenas, я изучил проект faceoverlay и внес соответствующие изменения в свой код,

#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);
}

лог сервера:

(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)

person Sagar Pilkhwal    schedule 16.03.2016    source источник


Ответы (1)


Проблема в том, что filter-factory можно установить только один раз. Установка его дважды не сработает, это то, что мы не тестировали, и это может привести к ошибкам (как кажется, это происходит).

Если вам нужно применить более одного элемента gstreamer, создайте оболочку (GstBin), которая содержит оба элемента и предлагает тот же интерфейс площадок, что и один простой фильтр (один приемник и один src). Внутри GstBin вы можете подключить столько элементов, сколько захотите.

Изменить

Вы можете получить пример GstBin, инкапсулирующего различные элементы здесь

Изменить 2

Проблема в этой строке:

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

"mode" является перечислением и может передаваться как строка, но как целочисленное значение.

Изменить 3

Кажется, вы не правильно указываете свой элемент в файле .h, который вам нужен:

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

И в вашем файле .c:

 G_DEFINE_TYPE (GstVADCustomFilter, gst_v_a_d_custom_filter, GST_TYPE_BIN);
person santoscadenas    schedule 16.03.2016
comment
Вероятно, вам может понадобиться определить фабрику для корзины. Или хотя бы прокладки, иначе фильтр его забракует. - person santoscadenas; 16.03.2016
comment
Это что-то похожее на github.com/Kurento/kms- фильтры/дерево/мастер/src/gst-plugins/. Я также отредактировал ответ с этой информацией - person santoscadenas; 16.03.2016
comment
Я просмотрел пример faceoverlay и отредактировал свой вопрос. - person Sagar Pilkhwal; 16.03.2016
comment
Вероятно, в /var/log/kurento-media-server/media-server_error.log будет трассировка стека. Не могли бы вы дать нам последний? - person santoscadenas; 16.03.2016
comment
(kurento-media-server:20099): GLib-GObject-WARNING **: value "((GstAudioChebLimitMode) -1913471257)" of type 'GstAudioChebLimitMode' is invalid or out of range for property 'mode' of type 'GstAudioChebLimitMode' [31;1mSegmentation fault[0m (thread [33;1m140198495102720[0m, pid [33;1m20099[0m) Я использовал audiocheblimit mode=low-pass Я удалил mode=low-pass по умолчанию, проверьте мой вопрос для редактирования трассировки стека, которую я получаю сейчас - person Sagar Pilkhwal; 16.03.2016
comment
Кажется, вы неправильно передаете значение свойства. Вы не можете передавать имена перечислений в виде строк таким образом. Вы должны преобразовать их (сложно) или использовать числовое значение (намного проще). - person santoscadenas; 16.03.2016
comment
Эта трассировка стека без символов отладки не очень полезна, почему в вашей библиотеке нет символов отладки? - person santoscadenas; 16.03.2016
comment
Это зависит от того, как вы загружаете библиотеку на сервер. - person santoscadenas; 16.03.2016
comment
привет, проблема заключалась в том, что g_object_set (G_OBJECT (audiocheblimit), "cutoff", 700, NULL); изменил 700 на 700.0, но как теперь применить этот бин к объекту mediapipeline или element? g_object_set(element, "filter-factory", "my_bin", NULL); потребуется, чтобы я определил новый filter fatory g_object_get(G_OBJECT(element), "filter", &binfilter, NULL); - person Sagar Pilkhwal; 17.03.2016
comment
Вам нужно зарегистрировать фабрику для вашего элемента, потому что фабрика требуется внутри. - person santoscadenas; 17.03.2016
comment
также мне придется обрабатывать sink_event как в faceoverlay примере kms_image_overlay_class_init () - person Sagar Pilkhwal; 17.03.2016
comment
Нет, просто соедините элементы и позвольте им автоматически обрабатывать события - person santoscadenas; 17.03.2016
comment
отлично, не могли бы вы проверить мое редактирование, я получаю ошибку сегментации на сервере и множественную ошибку g_assert в журнале сервера - person Sagar Pilkhwal; 17.03.2016
comment
Первая строка дает вам подсказку: (kurento-media-server:23094): GLib-GObject-WARNING **: invalid cast from 'GstVADCustomFilter' to 'GstBin' Вы используете другие типы, чем ожидалось. Проверьте свой код. - person santoscadenas; 17.03.2016
comment
я вызываю GST_BIN() для переменной, которую я получаю от gst_v_a_d_custom_filter_init (GstVADCustomFilter *v_a_d_custom_filter), т.е. v_a_d_custom_filter, так же, как в примере сfaceetector. - person Sagar Pilkhwal; 17.03.2016
comment
Тот что у вас не правильный. Проверьте еще раз: struct GstVADCustomFilter {GstBin parent;....}. И GST_TYPE_BIN вместо GST_TYPE_VIDEO_FILTER. - person santoscadenas; 17.03.2016
comment
У вас есть это, потому что автоматически созданные файлы предназначены для другой цели, чем то, что вы делаете. С этой частью все в порядке, но G_DEFINE_TYPE в файле .c также следует изменить. - person santoscadenas; 17.03.2016
comment
да, у меня изменения GST_TYPE_VIDEO_FILTER --›GST_TYPE_BIN, но теперь я получаю GLib-GObject-WARNING **: invalid class cast from 'GstVADCustomFilter' to 'GstVideoFilter' :( - person Sagar Pilkhwal; 17.03.2016
comment
GstVideoFilter base; это должно быть удалено из определения структуры - person santoscadenas; 17.03.2016
comment
Попробуйте проверить значения, возвращаемые такими функциями, как gst_ghost_pad_new_from_template, прежде чем использовать их, чтобы получить более конкретные данные о том, что используется неправильно. - person santoscadenas; 18.03.2016
comment
Это вызвано тем, что ограничения, которые вы устанавливаете для своей корзины, не предназначены для аудио или видео, а фильтрующий элемент не может определяться автоматически. Если вы установите фильтр для видео или аудио, используя свойство "type" для аудио (1), это должно быть исправлено. - person santoscadenas; 18.03.2016
comment
Мы слишком долго растягиваем эту ветку, не становясь полезными для других, кроме вас. Не возражаете ли вы, чтобы ваши вопросы были короткими и лаконичными, чтобы их можно было задать более чем одному пользователю? Спасибо. - person santoscadenas; 18.03.2016
comment
извините за это, есть ли какой-либо документ, на который я/пользователи могут ссылаться, чтобы создать собственный фильтр для kurento? потому что для новичка много неизвестного ... Также есть ли созданный вами плагин для обработки звука, доступный на github? - person Sagar Pilkhwal; 18.03.2016
comment
Это руководство мы использовали для обучения разработке модулей GStreamer gstreamer. freedesktop.org/data/doc/gstreamer/head/pwg/html разработка модулей GStreamer требует некоторого времени, чтобы иметь хорошие базовые знания, чтобы быть продуктивной, пожалуйста, наберитесь терпения. - person santoscadenas; 18.03.2016
comment
Привет, не могли бы вы рассказать, как получить сообщения, отправленные элементом cutter, при использовании внутри gst-плагина. Я не могу получить доступ к bus, на котором я могу добавить отслеживание сообщений. У меня просто есть bin object. Is there any way I can attatch callback listener on the bin` для сообщений его дочерних элементов - person Sagar Pilkhwal; 21.03.2016
comment
Вам нужно дождаться, пока элемент будет добавлен в конвейер, затем вы можете рекурсивно получить родительский элемент, пока не получите нуль, тогда это конвейер. - person santoscadenas; 22.03.2016
comment
Хорошо, есть ли какой-нибудь пример, на который я могу взглянуть? любой gst-плагин, который может делать что-то, как вы сказали? - person Sagar Pilkhwal; 22.03.2016
comment
Нет, что я могу вспомнить сейчас. Вероятно, самым близким из них является фильтр zbar, но он немного отличается. - person santoscadenas; 22.03.2016
comment
привет, в kms 6.5 мы можем применить несколько gst-плагинов в file-factory пользовательского модуля kurento? Раньше мы получали ошибки сегментации в KMS 6.4. - person Sagar Pilkhwal; 08.06.2016
comment
Нет, это невозможно даже в 6.5. Извиняюсь - person santoscadenas; 08.06.2016