Missing Bin Class in Deepstream Service Maker C++ APIs

Please provide complete information as applicable to your setup.

• Hardware Platform (Jetson / GPU) GPU
• DeepStream Version 7.0 (docker image: nvcr.io/nvidia/deepstream:7.0-sample-multiarch)
• NVIDIA GPU Driver Version (valid for GPU only) 535.171.04

Hi,

I am currently working with the Deepstream Service Maker C++ APIs and have noticed that there isn’t a Bin class available, which is a fundamental and useful component in GStreamer.

I am interested in understanding why the Bin class is missing from the Service Maker library.
Additionally, how can I work around the absence of a Bin class?
Is it recommended to implement a Bin C++ class that inherits from the Element class provided by the Service Maker library, or is there an alternative approach I should consider?

If implementing the Bin class is the best course of action, could someone provide guidance or examples on how to achieve this?

Thank you!

Why do need “Bin” class? Do you want to develop your own bin with Service Maker APIs?

I need the Bin class to create higher-level abstraction elements, which would allow me to manage groups of elements more easily and link these groups to other elements via GstGhostPad.

In the source code at /opt/nvidia/deepstream/deepstream/sources/apps/apps-common that uses the C API, GstBin is extensively used, such as in the creation of the Primary or Secondary GIE Bins and the Multi Source Bin. I would like to achieve similar functionality using the Service Maker APIs.

Additionally, I aim to develop an application similar to the deepstream_parallel_inference_app , but using the Service Maker APIs. In this context, the Bin is very useful for structuring and managing the elements involved.

I believe one option might be to develop my own Bin class using the Service Maker APIs, could you provide guidance or examples on how to achieve this?

Thanks.

You can develop normal GstBin element and the usage can be the same as “uridecodebin” with Service Maker.

I believe it would greatly enhance the Service Maker library to include a Bin class directly within its framework. This would streamline the process of constructing Bins without the need for intermediary GstBin steps, allowing for the direct addition and linking of deepstream::Elements rather than GstElements.

Currently, I am working on implementing an additional Bin class within Service Maker that derives from deepstream::Element. This class aims to replicate functionalities similar to those in deepstream::Pipeline, such as adding deepstream::Elements to the Bin and establishing links between them.

I am encountering challenges in implementing the destructor for the Bin class. I would like to understand how the destructor of deepstream::Pipeline is implemented, particularly how it manages the destruction of deepstream::Elements added to the pipeline. Could you provide insights into this?

Nothing special in deepstream::Pipeline destruction. Just set the GStreamer pipeline to NULL state.

This is my Bin class:

namespace deepstream
{
    class Bin : public Element
    {
    public:
        Bin(const std::string& name)
            : Element("bin", name) {}

        ~Bin()
        {
            gst_element_set_state(GST_ELEMENT(this->getGObject()), GST_STATE_NULL);
        }

        Bin& add(Element element)
        {
            auto res = elements.insert({ element.getName(), element });

            if (!res.second)
                throw std::runtime_error("Failed to insert Element " + element.getName());

            if (!gst_bin_add(GST_BIN(this->getGObject()), GST_ELEMENT(res.first->second.getGObject())))
            {
                elements.erase(res.first);
            }

            std::cout << "Add Element ... " << element.getName() << " to Bin " << this->getName() << std::endl;
            return *this;
        };

    private:
        std::map<std::string, Element> elements; ///< Map of element instances.
    };

} // namespace deepstream   

And this is my main.cpp:

int main()
{
    Pipeline pipeline("test_pipeline");
    {
        Bin bin("test_bin");
        Element elem("queue", "queue");
        std::cout << "Before add Element ref counter: " << GST_OBJECT_REFCOUNT_VALUE(elem.getGObject()) << std::endl;
        bin.add(elem);
        std::cout << "After add Element ref counter: " << GST_OBJECT_REFCOUNT_VALUE(elem.getGObject()) << std::endl;
    }
    return 0;
}

When I run the code, I get this error when exiting the scope where the Bin is defined:

GStreamer-CRITICAL **: 10:15:12.559:
Trying to dispose object “queue”, but it still has a parent “test_bin”.
You need to let the parent manage the object instead of unreffing the object directly

Can you please explain how to fix this error?

Moreover, I noticed that if I print the reference counter value before and after adding the Element to the Bin, I get:

Before add Element ref counter: 1
Add Element … queue to Bin test_bin
After add Element ref counter: 2

While if I use the Pipeline like this:

int main()
{
    Pipeline pipeline("test_pipeline");
    {
        Element elem("queue", "queue");
        std::cout << "Before add Element ref counter: " << GST_OBJECT_REFCOUNT_VALUE(elem.getGObject()) << std::endl;
        pipeline.add(elem);
        std::cout << "After add Element ref counter: " << GST_OBJECT_REFCOUNT_VALUE(elem.getGObject()) << std::endl;
    }
    return 0;
}

I get:

Before add Element ref counter: 1
Add Element … queue
After add Element ref counter: 3

Could you explain why this is happening? Additionally, could you describe how elements are added to the Pipeline?

Thank you.

It is not reasonable to ask us to explain your code.

I apologize if my previous request was unclear.

Could you please describe how elements are added to the Pipeline and why the reference counter goes from 1 to 3 after adding an element to the Pipeline?

Your guidance would be greatly appreciated.

Thank you!

The Service Maker is not open source. I can’t tell you the details.

Thanks for the answer.

I am conducting further tests to implement a Bin class within Service Maker and have encountered an issue. The code below is an example to illustrate the issue, not production code. It is the smallest code snippet that replicates the issue:

using namespace deepstream;

int main()
{
    std::unique_ptr<Element> elem_ptr;
    {
        Pipeline pipeline("test_pipeline");
        elem_ptr = std::make_unique<Element>("queue", "queue");
        std::cout << "Created element" << std::endl;
        std::cout << "Element has reference counter: " << GST_OBJECT_REFCOUNT_VALUE(elem_ptr->getGObject())
            << " and is floating: " << g_object_is_floating(elem_ptr->getGObject()) << std::endl;
        gst_object_ref_sink(elem_ptr->getGObject());
        std::cout << "Called gst_object_ref_sink" << std::endl;
        std::cout << "Element has reference counter: " << GST_OBJECT_REFCOUNT_VALUE(elem_ptr->getGObject())
            << " and is floating: " << g_object_is_floating(elem_ptr->getGObject()) << std::endl;
        pipeline.add(*elem_ptr);
        std::cout << "Element has reference counter: " << GST_OBJECT_REFCOUNT_VALUE(elem_ptr->getGObject())
            << " and is floating: " << g_object_is_floating(elem_ptr->getGObject()) << std::endl;
    }
    std::cout << "Pipeline deleted" << std::endl;
    std::cout << "Element has reference counter: " << GST_OBJECT_REFCOUNT_VALUE(elem_ptr->getGObject())
        << " and is floating: " << g_object_is_floating(elem_ptr->getGObject()) << std::endl;
    
    return 0;
}

The output is:

Created element
Element has reference counter: 1 and is floating: 1
Called gst_object_ref_sink
Element has reference counter: 1 and is floating: 0
Add Element … queue
Element has reference counter: 4 and is floating: 0
Pipeline deleted
Element has reference counter: 2 and is floating: 0

After deleting the pipeline, I would expect the Element to be in the exact same state as before adding it to the pipeline, while this is not the case: the element’s reference counter is 2, whereas I would expect it to be 1.
Is this the expected behavior?

Thank you.

Sorry for response late.
The Service Maker APIs are developed for the application developers who are not familiar with GStreamer. So the Bin is not involved for the GstBin is already enough for the users who want to develop their own bin element.

Why do you ask for the Bin class in Service Maker?