2

I am trying to apply some GStreamer plugins on the kurento mediapipeline, here I expect that the Gstreamer code which is working fine in a standalone program to send callback messages related to cutter.

The following is my code:

namespace kurento
{
    namespace module
    {
        namespace vadcustomfilter
        {
            std::string Id = "";

            void VADCustomFilterImpl::busMessage(GstMessage * message)
            {
                GST_ERROR("***In BusMessage***");

                if (message->type == GST_MESSAGE_EOS)
                {
                    g_object_set(G_OBJECT(valve), "drop", FALSE, NULL);
                }

                const GstStructure *s = gst_message_get_structure(message);
                const gchar *name = gst_structure_get_name(s);
                GST_INFO("Name: %s\n", name);

                if (message->type == GST_MESSAGE_ELEMENT)
                {
                    if (strcmp(name, "cutter") == 0)
                    {
                        GstClockTime time = 0;
                        GstClockTime prevsilencetime = 0;

                        if (!gst_structure_get_boolean(s, "above", &above))
                        {
                            GST_ERROR("could not parse above");
                        }

                        GST_INFO("above: %d", above);

                        if (above)
                        {
                            if (isSpeaking == 0)
                            {
                                revsilencetime = time;                              
                                g_object_set(G_OBJECT(valve), "drop", FALSE, NULL);
                            }
                            /*Send Voice Detected Event */                          
                            try
                            {
                                GST_ERROR("Sending Event: VoiceDetected");
                                VoiceDetected event(shared_from_this(), "voice-detected", Id.c_str());
                                signalVoiceDetected(event);
                                GST_ERROR("Sent Event: VoiceDetected");
                            }
                            catch (std::bad_weak_ptr & e)
                            {
                                GST_ERROR("EXCEPTION: Voice activity detected ");
                            }
                            isSpeaking = 1;
                        }
                        else
                        {
                            if (isSpeaking == 1)
                            {
                                g_object_set(G_OBJECT(valve), "drop", TRUE, NULL);
                            }
                            isSpeaking = 0;
                        }
                    }
                }
            }


            VADCustomFilterImpl::VADCustomFilterImpl(const boost::property_tree::
                ptree & config,
                std::shared_ptr <
                MediaPipeline > mediaPipeline,
                const std::string &pipelineId) :FilterImpl
                (config,
                std::dynamic_pointer_cast <MediaObjectImpl> (mediaPipeline))
            {
-->Edit Start       

                g_object_set (element, "filter-factory", "audioconvert", NULL);
                g_object_get (G_OBJECT (element), "filter", &audioconvertfilter, NULL);

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

                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", -39.0, NULL);
                g_object_set (G_OBJECT (cutterfilter), "run-length", 400000000, NULL);


                g_object_set (element, "filter-factory", "vadcustomfilter", NULL);

                g_object_get (G_OBJECT (element), "filter", &vadCustomFilter, NULL);

                bus_handler_id = 0;
                GST_ERROR("PipelineId: constructor %s",pipelineId.c_str());
                Id = pipelineId;
    -->Edit End

            }


            void VADCustomFilterImpl::postConstructor()
            {
                GstBus *bus;

                std::shared_ptr < MediaPipelineImpl > pipe;

                FilterImpl::postConstructor();

                pipe =
                    std::dynamic_pointer_cast <MediaPipelineImpl>
                    (getMediaPipeline());
                g_assert(pipe);

                /* #1. Add cutter filter here */
                create_gst_cutter_filter(pipe);


                bus = gst_pipeline_get_bus(GST_PIPELINE(pipe->getPipeline()));
                g_assert(bus);
                bus_handler_id = register_signal_handler(G_OBJECT(bus),
                    "message",
                    std::function <
                    void(GstElement *,
                    GstMessage *) >
                    (std::bind
                    (&VADCustomFilterImpl::
                    busMessage, this,
                    std::placeholders::_2)),
                    std::dynamic_pointer_cast <
                    VADCustomFilterImpl>
                    (shared_from_this()));


                GST_ERROR("busMessage added successfully.");

                g_object_unref(bus);
            }

            VADCustomFilterImpl::~VADCustomFilterImpl()
            {
                std::shared_ptr < MediaPipelineImpl > pipe;

                if (bus_handler_id > 0)
                {
                    pipe =
                        std::dynamic_pointer_cast <MediaPipelineImpl>
                        (getMediaPipeline());
                    GstBus *bus =
                        gst_pipeline_get_bus(GST_PIPELINE(pipe->getPipeline()));
                    unregister_signal_handler(bus, bus_handler_id);
                    g_object_unref(bus);
                }
            }

            MediaObjectImpl *VADCustomFilterImplFactory::createObject(const boost::
                property_tree::
                ptree &
                config,
                std::
                shared_ptr <
                MediaPipeline
                >
                mediaPipeline,
                const std::string &pipelineId)
                const
            {
                GST_ERROR("Pipeline Id createObject %s", pipelineId.c_str());
                return new VADCustomFilterImpl(config, mediaPipeline, pipelineId.c_str());
            }




            VADCustomFilterImpl::StaticConstructor VADCustomFilterImpl::
                staticConstructor;

            VADCustomFilterImpl::StaticConstructor::StaticConstructor()
            {
                GST_DEBUG_CATEGORY_INIT(GST_CAT_DEFAULT, GST_DEFAULT_NAME, 0,
                    GST_DEFAULT_NAME);
            }
        }/* vadcustomfilter */
    }/* module */
}/* kurento */

overall I have added comments for the questions which I have in the code.

I am getting callback for GstMessageTag which I have printed in the log using gst_structure_get_name(name) but i am not getting any callbacks for cutter

Is there anything missing/wrong in the flow of the code ?

Edit: Removed gstreamer way of adding plugin filters, tried adding audioconvert cutter on element

but I am getting error on addIceCandidate:

Req-> {"id":13,"method":"invoke","params":{"object":"ff394885-ff7b-4cd2-ac83-190ab58056c3_kurento.MediaPipeline/4911aa60-27e4-461e-86c0-10532bc30d4f_kurento.WebRtcEndpoint","operation":"addIceCandidate","operationParams":{"candidate":{"sdpMid":"audio","__module__":"kurento","sdpMLineIndex":0,"__type__":"IceCandidate","candidate":"candidate:1226269011 1 udp 2122260223 172.24.9.207 62808 typ host generation 0 ufrag nSC45+9JNTCJm+yr"}},"sessionId":"15daae09-de86-4293-a3de-28f33f2d0b16"},"jsonrpc":"2.0"}


Res {"id":13,"error":{"code":40401,"message":"Error adding candidate","data":{"type":"ICE_ADD_CANDIDATE_ERROR"}},"jsonrpc":"2.0"}
Sagar Pilkhwal
  • 3,998
  • 2
  • 25
  • 77

1 Answers1

2

It seems that the way that you are creating gstreamer elements is not the way that Kurento expects. Basically you are creating elements in the function create_gst_cutter_filter that are not linked correctly.

If you are creating a filter, all gstreamer stuff (create elements and connect them) should be done in gstreamer element that you call vadcustomfilter this element needs just one sink and one src pads.

If you want to create a different kind of element, as it seems because you are adding mulltifilesink, you need to extend from MediaElement and create a gstreamer element extending from KmsElement. You can see examples of this in kms-elements project.

Edit:

About the error returned by server. It seems not related to the problem here, but to a dependency problem. Check back this question and check if you have the same problem

Community
  • 1
  • 1
santoscadenas
  • 1,482
  • 9
  • 17
  • 1
    @SagarPilkhwal Yes, kms-elements is a huge proyect, but it's the only place where we have examples for plugins that are not filters. If you follow the instructions here for a gstreamer plugin you will get the base code of a project without opencv. http://doc-kurento.readthedocs.org/en/stable/mastering/develop_kurento_modules.html#how-to-develop-kurento-modules. But I think is what you already did. – santoscadenas Mar 11 '16 at 10:16
  • 1
    What is the objective you want with your plugin? Depending on it you should take one path or another. – santoscadenas Mar 11 '16 at 10:18
  • 1
    See how zbar filter is done. https://github.com/Kurento/kms-filters/blob/master/src/server/implementation/objects/ZBarFilterImpl.cpp – santoscadenas Mar 11 '16 at 10:29
  • 1
    Maybe you don't need `audioconvert`, agnosticbin can do this for you in most of the cases. – santoscadenas Mar 11 '16 at 11:01
  • @SagarPilkhwal Check the edit in my response to see is this is the problem – santoscadenas Mar 11 '16 at 11:25
  • Hi, I removed `audiofilter` element and now I am receiving callbacks for `cutter`. Also how to use `multifilesink` will there be any special scenario involved when using `multifilesink` – Sagar Pilkhwal Mar 11 '16 at 12:20
  • N, we do not have this scenario, most similar could be the recorder, but has its peculiarities, don't know if it is a good example. Why do you need it? – santoscadenas Mar 11 '16 at 12:25
  • I want to remove silence from the stream and save it to multiple files. I have a working gstreamer code which removes silence and saves into file. but I seems merging it into kurento will be a uphill task – Sagar Pilkhwal Mar 11 '16 at 12:34
  • Try using provided kurento elements this will speed up your development. Creating custom elements is always hard. Adding a kurento GStreamer filter with only the cutter element and connect it to a recorder could do the job for you without any custom plugin. – santoscadenas Mar 11 '16 at 12:51
  • okay, is there any specific kurento plugin which might help record the audio, because I have to rewind/seek back the pipeline some miliseconds when voice is detected. which I wont think will be possible. Thanks – Sagar Pilkhwal Mar 11 '16 at 14:02
  • 1
    You are right, kurento does not allow doing seek on the pipeline. You need a different hack for that, creating custom recorder or something like that, that is not an easy task. Other simpler option could be recording a file and then post process it remove silence with the program that you already have. – santoscadenas Mar 11 '16 at 14:25
  • Hi, In java group call application example, how can I get access to each user's `mediapipeline`. Is it possible to get a hold of individual pipeline? when I print the `Id` of evey connected user's mediapipeline I get the same output `user1: b524a269-cef8-4070-99d4-e8895b7e6fb8_kurento.MediaPipeline user2: b524a269-cef8-4070-99d4-e8895b7e6fb8_kurento.MediaPipeline` – Sagar Pilkhwal Mar 15 '16 at 10:57
  • You mean accessing gstreamer pipeline? or Kurento Pipeline? If you get access to the WebRtcEndpoint you can get its parent that is a MediaPipeline. – santoscadenas Mar 15 '16 at 11:07
  • 1
    I think this is a completely different question from the original one, let's move discussion to a new question. – santoscadenas Mar 15 '16 at 12:03