How to deepcopy NvDsFrameMeta to another thread?deepstream-transfer-learning-app is too slowly!

Please provide complete information as applicable to your setup.

• Hardware Platform (Jetson / GPU)
RTX 2060
• DeepStream Version
ds 6.0
• JetPack Version (valid for Jetson only)
• TensorRT Version
tensorrt 8
• NVIDIA GPU Driver Version (valid for GPU only)
470.141.03
• Issue Type( questions, new requirements, bugs)

question
• How to reproduce the issue ? (This is for bugs. Including which sample app is using, the configuration files content, the command line used and other details for reproducing)

RUN deepstream-transfer-learning-app with set source=30

• Requirement details( This is for new requirement. Including the module name-for which plugin or for which sample application, the function description)

I want to save the images from the inference video to my disk. I used the example from deepstream-transfer-learning-app’ code . Its core code is as follows:

static void
after_pgie_image_meta_save(AppCtx *appCtx, GstBuffer *buf,
                           NvDsBatchMeta *batch_meta, guint index)
{

    
    GstMapInfo inmap = GST_MAP_INFO_INIT;
    if (!gst_buffer_map(buf, &inmap, GST_MAP_READ))
    {
        std::cerr << "input buffer mapinfo failed\n";
        return;
    }
    NvBufSurface *ip_surf = (NvBufSurface *)inmap.data;
    gst_buffer_unmap(buf, &inmap);

    bool isWrite = false;

    NvDsObjectMeta *obj_meta = NULL;
    NvDsMetaList *l_frame = NULL;
    NvDsMetaList *l_obj = NULL;
    if (!isInitEncContext)
    {
       
        obj_ctx_handle_ = nvds_obj_enc_create_context();
        isInitEncContext = true;
    }
    auto start_t = std::chrono::high_resolution_clock::now();

    /// Creating a special object meta in order to save a full frame
    if (picCount % 150 == 0)
    {
      
        for (NvDsMetaList *l_frame = batch_meta->frame_meta_list; l_frame != nullptr;
             l_frame = l_frame->next)
        {
            NvDsFrameMeta *frame_meta = (NvDsFrameMeta *)(l_frame->data);

            guint num_rects = 0;

            bool at_least_one_confidence_is_within_range = false;

            ...

            if (at_least_one_confidence_is_within_range)
            {

                unsigned dummy_counter = 0;

                isWrite = true;

                NvDsObjEncUsrArgs userData = {0};
                /* To be set by user */
                userData.saveImg = TRUE;
                userData.attachUsrMeta = FALSE;
                /* Set if Image scaling Required */
                userData.scaleImg = FALSE;
                userData.scaledWidth = 0;
                userData.scaledHeight = 0;
                std::stringstream ss;
                ss << "camera" << frame_meta->pad_index << "_" << (picCount / 150) << ".jpg";
                std::string path = ss.str();

                if (path.size() >= sizeof(userData.fileNameImg))
                {
                    std::cerr << "Folder path too long (path: " << path
                              << ", size: " << path.size() << ") could not save image.\n"
                              << "Should be less than " << sizeof(userData.fileNameImg) << " characters.";
                    return;
                }
                userData.saveImg = TRUE;
                userData.attachUsrMeta = FALSE;
                path.copy(userData.fileNameImg, path.size());
                userData.fileNameImg[path.size()] = '\0';
                userData.objNum = picCount;
                userData.quality = 80;

                NvDsObjectMeta dummy_obj_meta;
                dummy_obj_meta.rect_params.width = ip_surf->surfaceList[frame_meta->batch_id].width;
                dummy_obj_meta.rect_params.height = ip_surf->surfaceList[frame_meta->batch_id].height;
                dummy_obj_meta.rect_params.top = 0;
                dummy_obj_meta.rect_params.left = 0;

                
                nvds_obj_enc_process(obj_ctx_handle_, &userData, ip_surf, &dummy_obj_meta, frame_meta);
                std::cout << "camera :" << frame_meta->pad_index << " writed,frame :" << picCount << std::endl;
                

            }
        }

        if (isWrite)
        {

            auto over_t = std::chrono::high_resolution_clock::now();
            std::chrono::duration<double, std::milli> elapsed = over_t - start_t;
            std::cout << "total time:" << elapsed.count() << "ms!" << std::endl;

            nvds_obj_enc_finish(obj_ctx_handle_);
        }

    } // end of picCount %150

    picCount++;
}

The example of deepstream-transfer-learning-app has some problems, nvds_obj_enc_process is used in after_pgie_image_meta_save, if there are many images, it will still block the pipline. For example, 30 images might take 3 seconds.

So, I want to make a copy of NvDsFrameMeta and send it to the consumer thread. The question is: how should I deep copy the copied data structure of NvDsFrameMeta (do I also copy the data in the gpu?), can you give me some sample code? Thanks!

Do you mean you want to do “nvds_obj_enc_process” in another thread? It is better to copy the whole GstBuffer to new created GstBuffer

yes!I want to use “nvds_obj_enc_process” in another thread。but how to copy the whole GstBuffer to new created GstBuffer?could u give me some code for sample?

I User deepcopy for GstBuffer,But I got this error when gst_buffer_unref.

[NvTiler::Composite] ERROR: 360; NvBufSurfTransformComposite failed(-1)
ERROR from tiled_display_tiler: GstNvTiler: FATAL ERROR; NvTiler::Composite failed
Debug info: gstnvtiler.cpp(666): gst_nvmultistreamtiler_transform (): /GstPipeline:pipeline/GstBin:tiled_display_bin/GstNvMultiStreamTiler:tiled_display_tiler

And ,my code like this:

static void
after_pgie_image_meta_save(AppCtx *appCtx, GstBuffer *buf,
                           NvDsBatchMeta *batch_meta, guint index)
{
    if (g_img_meta_consumer.get_is_stopped())
    {
        std::cerr << "Could not save image and metadata: "
                  << "Consumer is stopped.\n";
        return;
    }
    GstBuffer *new_buf = gst_buffer_copy_deep(buf);
    GstMapInfo inmap = GST_MAP_INFO_INIT;
    if (!gst_buffer_map(new_buf, &inmap, GST_MAP_READ))
        {
            std::cerr << "input buffer mapinfo failed\n";
            return;
        }
    NvBufSurface *ip_surf = (NvBufSurface *)inmap.data;
    gst_buffer_unmap(new_buf, &inmap);
    gst_buffer_unref(new_buf);


hope u give me some help!

There is no update from you for a period, assuming this is not an issue anymore.
Hence we are closing this topic. If need further support, please open a new one.
Thanks

This is not copy. Please create NvBufSurface as the sample in nvdsexample /opt/nvidia/deepstream/deepdtream/sources/gst-plugins/gst-dsexample

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.