'Tegra_multimedia_api / samples / 00_video_decode' problem

I’m testing the samples of the MultiMedia API.
Because I hope that in my program, I can create a decode thread many times and then destroy the decode thread, but I found that gstreamer in the set_state for READY, nveglglessink module called gst_eglglessink_stop (), will occur Xlib error, which lead to segment errors, I’m going to try MultiMediaAPI.

I changed the decode sample
Mainly the process does not exit the case, the cycle to create, destroy the decoding module.

After running, after more than 20 times to create, destroy the process, the process will be created every time when the leak about 40M memory, about 80 cycles will be run off the system kill.

I have tried the following command, a memory leak occurs

./video_decode ../../data/video/sample_outdoor_car_1080p_10fps.h264 H264 -wx 0 -wy 540 -ww 960 -wh 540

sudo -E ./video_decode test2.h264 H264 -wx 0 -wy 540 -ww 960 -wh 540 --stats

./video_decode test.h264 H264 -wx 0 -wy 540 -ww 960 -wh 540 --disable-rendering

My code is as follows, only changed the main function of the front and the last, an increase of a loop

please help.

int
main(int argc, char *argv[])
{
    context_t ctx;
    int ret = 0;
    int error = 0;
    uint32_t i;
    bool eos = false;
    char *nalu_parse_buffer = NULL;
    NvApplicationProfiler &profiler = NvApplicationProfiler::getProfilerInstance();

/* I changed here !!!!!!!!!!!!!! */
while(1)
{
	ret = 0;
	error = 0;
	eos = false;
	nalu_parse_buffer = NULL;
    
	set_defaults(&ctx);
	

    if (parse_csv_args(&ctx, argc, argv))
    {
        fprintf(stderr, "Error parsing commandline arguments\n");
        return -1;
    }

    ctx.dec = NvVideoDecoder::createVideoDecoder("dec0");
    TEST_ERROR(!ctx.dec, "Could not create decoder", cleanup);

    if (ctx.stats)
    {
        profiler.start(NvApplicationProfiler::DefaultSamplingInterval);
        ctx.dec->enableProfiling();
    }

    // Subscribe to Resolution change event
    ret = ctx.dec->subscribeEvent(V4L2_EVENT_RESOLUTION_CHANGE, 0, 0);
    TEST_ERROR(ret < 0, "Could not subscribe to V4L2_EVENT_RESOLUTION_CHANGE",
               cleanup);

    if (ctx.input_nalu)
    {
        nalu_parse_buffer = new char[CHUNK_SIZE];
    }
    else
    {
        // Set V4L2_CID_MPEG_VIDEO_DISABLE_COMPLETE_FRAME_INPUT control to false
        // so that application can send chunks of encoded data instead of forming
        // complete frames. This needs to be done before setting format on the
        // output plane.
        ret = ctx.dec->disableCompleteFrameInputBuffer();
        TEST_ERROR(ret < 0,
                "Error in decoder disableCompleteFrameInputBuffer", cleanup);
    }

    // Set format on the output plane
    ret = ctx.dec->setOutputPlaneFormat(ctx.decoder_pixfmt, CHUNK_SIZE);
    TEST_ERROR(ret < 0, "Could not set output plane format", cleanup);

    // V4L2_CID_MPEG_VIDEO_DISABLE_DPB should be set after output plane
    // set format
    if (ctx.disable_dpb)
    {
        ret = ctx.dec->disableDPB();
        TEST_ERROR(ret < 0, "Error in decoder disableDPB", cleanup);
    }

    if (ctx.enable_metadata)
    {
        ret = ctx.dec->enableMetadataReporting();
        TEST_ERROR(ret < 0, "Error while enabling metadata reporting", cleanup);
    }

    if (ctx.skip_frames)
    {
        ret = ctx.dec->setSkipFrames(ctx.skip_frames);
        TEST_ERROR(ret < 0, "Error while setting skip frames param", cleanup);
    }

    // Query, Export and Map the output plane buffers so that we can read
    // encoded data into the buffers
    ret = ctx.dec->output_plane.setupPlane(V4L2_MEMORY_MMAP, 10, true, false);
    TEST_ERROR(ret < 0, "Error while setting up output plane", cleanup);

    ctx.in_file = new ifstream(ctx.in_file_path);
    TEST_ERROR(!ctx.in_file->is_open(), "Error opening input file", cleanup);

    if (ctx.out_file_path)
    {
	printf("%s,%d\n",__func__, __LINE__);
        ctx.out_file = new ofstream(ctx.out_file_path);
        TEST_ERROR(!ctx.out_file->is_open(), "Error opening output file",
                   cleanup);
    }

    if (ctx.out_file || (!ctx.disable_rendering && !ctx.stats))
    {
        // Create converter to convert from BL to PL for writing raw video
        // to file
        ctx.conv = NvVideoConverter::createVideoConverter("conv0");
        TEST_ERROR(!ctx.conv, "Could not create video converter", cleanup);
        ctx.conv->output_plane.
            setDQThreadCallback(conv0_output_dqbuf_thread_callback);
        ctx.conv->capture_plane.
            setDQThreadCallback(conv0_capture_dqbuf_thread_callback);

        if (ctx.stats)
        {
            ctx.conv->enableProfiling();
        }
    }

    ret = ctx.dec->output_plane.setStreamStatus(true);
    TEST_ERROR(ret < 0, "Error in output plane stream on", cleanup);

    pthread_create(&ctx.dec_capture_loop, NULL, dec_capture_loop_fcn, &ctx);

    // Read encoded data and enqueue all the output plane buffers.
    // Exit loop in case file read is complete.
    i = 0;
    while (!eos && !ctx.got_error && !ctx.dec->isInError() &&
           i < ctx.dec->output_plane.getNumBuffers())
    {
        struct v4l2_buffer v4l2_buf;
        struct v4l2_plane planes[MAX_PLANES];
        NvBuffer *buffer;

        memset(&v4l2_buf, 0, sizeof(v4l2_buf));
        memset(planes, 0, sizeof(planes));

        buffer = ctx.dec->output_plane.getNthBuffer(i);
        if (ctx.input_nalu)
        {
            read_decoder_input_nalu(ctx.in_file, buffer, nalu_parse_buffer,
                    CHUNK_SIZE);
        }
        else
        {
            read_decoder_input_chunk(ctx.in_file, buffer);
        }

        v4l2_buf.index = i;
        v4l2_buf.m.planes = planes;
        v4l2_buf.m.planes[0].bytesused = buffer->planes[0].bytesused;

        // It is necessary to queue an empty buffer to signal EOS to the decoder
        // i.e. set v4l2_buf.m.planes[0].bytesused = 0 and queue the buffer
        ret = ctx.dec->output_plane.qBuffer(v4l2_buf, NULL);
        if (ret < 0)
        {
            cerr << "Error Qing buffer at output plane" << endl;
            abort(&ctx);
            break;
        }
        if (v4l2_buf.m.planes[0].bytesused == 0)
        {
            eos = true;
            cout << "Input file read complete" << endl;
            break;
        }
        i++;
    }
	printf("%s,%d\n",__func__, __LINE__);

    // Since all the output plane buffers have been queued, we first need to
    // dequeue a buffer from output plane before we can read new data into it
    // and queue it again.
    while (!eos && !ctx.got_error && !ctx.dec->isInError())
    {
        struct v4l2_buffer v4l2_buf;
        struct v4l2_plane planes[MAX_PLANES];
        NvBuffer *buffer;

        memset(&v4l2_buf, 0, sizeof(v4l2_buf));
        memset(planes, 0, sizeof(planes));

        v4l2_buf.m.planes = planes;

        ret = ctx.dec->output_plane.dqBuffer(v4l2_buf, &buffer, NULL, -1);
        if (ret < 0)
        {
            cerr << "Error DQing buffer at output plane" << endl;
            abort(&ctx);
            break;
        }

        if (ctx.input_nalu)
        {
            read_decoder_input_nalu(ctx.in_file, buffer, nalu_parse_buffer,
                    CHUNK_SIZE);
        }
        else
        {
            read_decoder_input_chunk(ctx.in_file, buffer);
        }
        v4l2_buf.m.planes[0].bytesused = buffer->planes[0].bytesused;
        ret = ctx.dec->output_plane.qBuffer(v4l2_buf, NULL);
        if (ret < 0)
        {
            cerr << "Error Qing buffer at output plane" << endl;
            abort(&ctx);
            break;
        }
        if (v4l2_buf.m.planes[0].bytesused == 0)
        {
            eos = true;
            cout << "Input file read complete" << endl;
            break;
        }
    }

    // After sending EOS, all the buffers from output plane should be dequeued.
    // and after that capture plane loop should be signalled to stop.
    while (ctx.dec->output_plane.getNumQueuedBuffers() > 0 &&
           !ctx.got_error && !ctx.dec->isInError())
    {
        struct v4l2_buffer v4l2_buf;
        struct v4l2_plane planes[MAX_PLANES];

        memset(&v4l2_buf, 0, sizeof(v4l2_buf));
        memset(planes, 0, sizeof(planes));

        v4l2_buf.m.planes = planes;
        ret = ctx.dec->output_plane.dqBuffer(v4l2_buf, NULL, NULL, -1);
        if (ret < 0)
        {
            cerr << "Error DQing buffer at output plane" << endl;
            abort(&ctx);
            break;
        }
    }

    // Signal EOS to the decoder capture loop
    ctx.got_eos = true;

    if (ctx.conv)
    {
        ctx.conv->capture_plane.waitForDQThread(-1);
    }

    if (ctx.stats)
    {
        profiler.stop();
        ctx.dec->printProfilingStats(cout);
        if (ctx.conv)
        {
            ctx.conv->printProfilingStats(cout);
        }
        if (ctx.renderer)
        {
            ctx.renderer->printProfilingStats(cout);
        }
        profiler.printProfilerData(cout);
    }

cleanup:
    if (ctx.dec_capture_loop)
    {
        pthread_join(ctx.dec_capture_loop, NULL);
    }

    if (ctx.conv && ctx.conv->isInError())
    {
        cerr << "Converter is in error" << endl;
        error = 1;
    }

    if (ctx.dec && ctx.dec->isInError())
    {
        cerr << "Decoder is in error" << endl;
        error = 1;
    }

    if (ctx.got_error)
    {
        error = 1;
    }

    // The decoder destructor does all the cleanup i.e set streamoff on output and capture planes,
    // unmap buffers, tell decoder to deallocate buffer (reqbufs ioctl with counnt = 0),
    // and finally call v4l2_close on the fd.
    delete ctx.dec;
    delete ctx.conv;

    // Similarly, EglRenderer destructor does all the cleanup
    delete ctx.renderer;
    delete ctx.in_file;
    delete ctx.out_file;
    delete ctx.conv_output_plane_buf_queue;
    delete[] nalu_parse_buffer;

/* I changed here !!!!!!!!!!!!!! */
	sleep (4);
}

    free(ctx.in_file_path);
    free(ctx.out_file_path);

    if (error)
    {
        cout << "App run failed" << endl;
    }
    else
    {
        cout << "App run was successful" << endl;
    }

    return -error;
}

Hi Li Lin,
please replace /usr/lib/aarch64-linux-gnu/tegra/libtegrav4l2.so and give it a try.
libtegrav4l2.so.txt (131 KB)

Thanks a lot!
I tested this .so, no memory leaks happend, but after 1003 times the cycle, the program error, and then quit.

command is

./video_decode test2.h264 H264 -wx 960 -wy 0 -ww 960 -wh 540

I tested three times and the results were exactly the same, each time after running 1003 cycles
The following is the print message, do I need to re-open a topic?

Exiting decoder capture loop thread
delete decoder
TVMR: TVMRFrameStatusReporting: 6067: Closing TVMR Frame Status Thread -------------
TVMR: TVMRVPRFloorSizeSettingThread: 5885: Closing TVMRVPRFloorSizeSettingThread -------------
TVMR: TVMRFrameDelivery: 5917: Closing TVMR Frame Delivery Thread -------------
TVMR: NvMMLiteTVMRDecBlockClose: 7740: Done 
!!!!!! loop_cnt = 1003
Failed to query video capabilities: Bad address
NvMMLiteOpen : Block : BlockType = 261 
TVMR: NvMMLiteTVMRDecBlockOpen: 7580: NvMMLiteBlockOpen 
NvMMLiteBlockCreate : Block : BlockType = 261 
Failed to query video capabilities: Bad address
Starting decoder capture loop thread
TVMR: cbBeginSequence: 1166: BeginSequence  1920x1088, bVPR = 0, fFrameRate = 0.000000
TVMR: LowCorner Frequency = 0 
TVMR: cbBeginSequence: 1545: DecodeBuffers = 14, pnvsi->eCodec = 4, codec = 0 
TVMR: NvMMLiteTVMRDecDoWork: 6466: NVMMLITE_TVMR: EOS detected
Input file read complete
TVMR: cbBeginSequence: 1606: Display Resolution : (1920x1080) 
TVMR: cbBeginSequence: 1607: Display Aspect Ratio : (1920x1080) 
TVMR: cbBeginSequence: 1649: ColorFormat : 5 
TVMR: cbBeginSequence:1660 ColorSpace = NvColorSpace_YCbCr709
TVMR: cbBeginSequence: 1790: SurfaceLayout = 3
TVMR: cbBeginSequence: 1868: NumOfSurfaces = 15, InteraceStream = 0, InterlaceEnabled = 0, bSecure = 0, MVC = 0 Semiplanar = 1, bReinit = 1, BitDepthForSurface = 8 LumaBitDepth = 8, ChromaBitDepth = 8, ChromaFormat = 5
Video Resolution: 1920x1080
libv4l2_nvvidconv (0):(765) (INFO) : Allocating (10) OUTPUT PLANE BUFFERS Layout=1
libv4l2_nvvidconv (0):(775) (INFO) : Allocating (10) CAPTURE PLANE BUFFERS Layout=0
Query and set capture successful
Opening channel /dev/nvhost-vic failed
libv4l2_nvvidconv (0):(1525) (ERROR) : BLIT FAILED err=196626
libv4l2_nvvidconv (0):(1543) (ERROR) : NVVIDCONV ERROR 196626
NvEglHandle: Unfreed handle upon egl deinit: type=2 refcnt=2
NvEglHandle: Unfreed handle upon egl deinit: type=1 refcnt=1

I tried other commands, after 1009 cycles, the video rendered failed and no decoded video was shown

./video_decode test2.h264 H264 -wx 0 -wy 0 --stats --dbg-level 3

Do not use conv, will also be wrong, the wrong location here

egl_status = eglInitialize(renderer->egl_display, 0, 0);
    if (!egl_status)
    {
        COMP_ERROR_MSG("Unable to initialize egl library");
        goto error;
    }

The following is the printed information

TVMR: TVMRFrameStatusReporting: 6067: Closing TVMR Frame Status Thread -------------
TVMR: TVMRVPRFloorSizeSettingThread: 5885: Closing TVMRVPRFloorSizeSettingThread -------------
TVMR: TVMRFrameDelivery: 5917: Closing TVMR Frame Delivery Thread -------------
TVMR: NvMMLiteTVMRDecBlockClose: 7740: Done 
[LOG_LEVEL_DEBUG] (NvV4l2Element.cpp:87) <V4l2Element> Device closed, fd = 5
!!!!!! loop_cnt = 1009
Failed to query video capabilities: Bad address
[LOG_LEVEL_DEBUG] (NvV4l2Element.cpp:62) <dec0> :Opened, fd = 5
Set governor to performance before enabling profiler
[LOG_LEVEL_DEBUG] (NvV4l2Element.cpp:215) <dec0> :Successfully subscribed to event 5
[LOG_LEVEL_DEBUG] (NvV4l2Element.cpp:177) <dec0> :Set controls
[LOG_LEVEL_DEBUG] (NvVideoDecoder.cpp:182) <dec0> :Disabling decoder complete frame input buffer: success
NvMMLiteOpen : Block : BlockType = 261 
TVMR: NvMMLiteTVMRDecBlockOpen: 7580: NvMMLiteBlockOpen 
NvMMLiteBlockCreate : Block : BlockType = 261 
[LOG_LEVEL_DEBUG] (NvV4l2ElementPlane.cpp:290) <dec0> :Output Plane:VIDIOC_S_FMT at capture plane successful
[LOG_LEVEL_DEBUG] (NvV4l2ElementPlane.cpp:433) <dec0> :Output Plane:Reqbuf returned 10 buffers
[LOG_LEVEL_DEBUG] (NvV4l2ElementPlane.cpp:542) <dec0> :Output Plane:QueryBuf for 0th buffer successful
[LOG_LEVEL_DEBUG] (NvV4l2ElementPlane.cpp:580) <dec0> :Output Plane:ExportBuf successful for Buffer 0, Plane 0, fd = 1024
[LOG_LEVEL_DEBUG] (NvBuffer.cpp:175) <Buffer> Mapped buffer 0, plane 0 to 
[LOG_LEVEL_DEBUG] (NvV4l2ElementPlane.cpp:542) <dec0> :Output Plane:QueryBuf for 1th buffer successful
[LOG_LEVEL_DEBUG] (NvV4l2ElementPlane.cpp:580) <dec0> :Output Plane:ExportBuf successful for Buffer 1, Plane 0, fd = 1025
[LOG_LEVEL_DEBUG] (NvBuffer.cpp:175) <Buffer> Mapped buffer 1, plane 0 to 
[LOG_LEVEL_DEBUG] (NvV4l2ElementPlane.cpp:542) <dec0> :Output Plane:QueryBuf for 2th buffer successful
[LOG_LEVEL_DEBUG] (NvV4l2ElementPlane.cpp:580) <dec0> :Output Plane:ExportBuf successful for Buffer 2, Plane 0, fd = 1026
[LOG_LEVEL_DEBUG] (NvBuffer.cpp:175) <Buffer> Mapped buffer 2, plane 0 to 
[LOG_LEVEL_DEBUG] (NvV4l2ElementPlane.cpp:542) <dec0> :Output Plane:QueryBuf for 3th buffer successful
[LOG_LEVEL_DEBUG] (NvV4l2ElementPlane.cpp:580) <dec0> :Output Plane:ExportBuf successful for Buffer 3, Plane 0, fd = 1027
[LOG_LEVEL_DEBUG] (NvBuffer.cpp:175) <Buffer> Mapped buffer 3, plane 0 to 
[LOG_LEVEL_DEBUG] (NvV4l2ElementPlane.cpp:542) <dec0> :Output Plane:QueryBuf for 4th buffer successful
[LOG_LEVEL_DEBUG] (NvV4l2ElementPlane.cpp:580) <dec0> :Output Plane:ExportBuf successful for Buffer 4, Plane 0, fd = 1028
[LOG_LEVEL_DEBUG] (NvBuffer.cpp:175) <Buffer> Mapped buffer 4, plane 0 to 
[LOG_LEVEL_DEBUG] (NvV4l2ElementPlane.cpp:542) <dec0> :Output Plane:QueryBuf for 5th buffer successful
[LOG_LEVEL_DEBUG] (NvV4l2ElementPlane.cpp:580) <dec0> :Output Plane:ExportBuf successful for Buffer 5, Plane 0, fd = 1029
[LOG_LEVEL_DEBUG] (NvBuffer.cpp:175) <Buffer> Mapped buffer 5, plane 0 to 
[LOG_LEVEL_DEBUG] (NvV4l2ElementPlane.cpp:542) <dec0> :Output Plane:QueryBuf for 6th buffer successful
[LOG_LEVEL_DEBUG] (NvV4l2ElementPlane.cpp:580) <dec0> :Output Plane:ExportBuf successful for Buffer 6, Plane 0, fd = 1030
[LOG_LEVEL_DEBUG] (NvBuffer.cpp:175) <Buffer> Mapped buffer 6, plane 0 to 
[LOG_LEVEL_DEBUG] (NvV4l2ElementPlane.cpp:542) <dec0> :Output Plane:QueryBuf for 7th buffer successful
[LOG_LEVEL_DEBUG] (NvV4l2ElementPlane.cpp:580) <dec0> :Output Plane:ExportBuf successful for Buffer 7, Plane 0, fd = 1031
[LOG_LEVEL_DEBUG] (NvBuffer.cpp:175) <Buffer> Mapped buffer 7, plane 0 to 
[LOG_LEVEL_DEBUG] (NvV4l2ElementPlane.cpp:542) <dec0> :Output Plane:QueryBuf for 8th buffer successful
[LOG_LEVEL_DEBUG] (NvV4l2ElementPlane.cpp:580) <dec0> :Output Plane:ExportBuf successful for Buffer 8, Plane 0, fd = 1032
[LOG_LEVEL_DEBUG] (NvBuffer.cpp:175) <Buffer> Mapped buffer 8, plane 0 to 
[LOG_LEVEL_DEBUG] (NvV4l2ElementPlane.cpp:542) <dec0> :Output Plane:QueryBuf for 9th buffer successful
[LOG_LEVEL_DEBUG] (NvV4l2ElementPlane.cpp:580) <dec0> :Output Plane:ExportBuf successful for Buffer 9, Plane 0, fd = 1033
[LOG_LEVEL_DEBUG] (NvBuffer.cpp:175) <Buffer> Mapped buffer 9, plane 0 to 
[LOG_LEVEL_DEBUG] (NvV4l2ElementPlane.cpp:467) <dec0> :Output Plane:STREAMON successful
Starting decoder capture loop thread
[LOG_LEVEL_DEBUG] (NvV4l2ElementPlane.cpp:257) <dec0> :Output Plane:Qed buffer 0
TVMR: NvMMLiteTVMRDecDoWork: 6466: NVMMLITE_TVMR: EOS detected
[LOG_LEVEL_DEBUG] (NvV4l2ElementPlane.cpp:257) <dec0> :Output Plane:Qed buffer 1
Input file read complete
TVMR: cbBeginSequence: 1166: BeginSequence  1920x1088, bVPR = 0, fFrameRate = 0.000000
TVMR: LowCorner Frequency = 0 
TVMR: cbBeginSequence: 1545: DecodeBuffers = 14, pnvsi->eCodec = 4, codec = 0 
TVMR: cbBeginSequence: 1606: Display Resolution : (1920x1080) 
TVMR: cbBeginSequence: 1607: Display Aspect Ratio : (1920x1080) 
TVMR: cbBeginSequence: 1649: ColorFormat : 5 
TVMR: cbBeginSequence:1660 ColorSpace = NvColorSpace_YCbCr709
TVMR: cbBeginSequence: 1790: SurfaceLayout = 3
TVMR: cbBeginSequence: 1868: NumOfSurfaces = 15, InteraceStream = 0, InterlaceEnabled = 0, bSecure = 0, MVC = 0 Semiplanar = 1, bReinit = 1, BitDepthForSurface = 8 LumaBitDepth = 8, ChromaBitDepth = 8, ChromaFormat = 5
[LOG_LEVEL_DEBUG] (NvV4l2Element.cpp:102) <dec0> :DQed event 5
[LOG_LEVEL_DEBUG] (NvV4l2ElementPlane.cpp:272) <dec0> :Capture Plane:Getting format: success
[LOG_LEVEL_DEBUG] (NvV4l2ElementPlane.cpp:308) <dec0> :Capture Plane:Getting crop params: success
Video Resolution: 1920x1080
[LOG_LEVEL_ERROR] (NvEglRenderer.cpp:109) <renderer0> Setting Screen width 1920 height 1080
[LOG_LEVEL_DEBUG] (NvEglRenderer.cpp:111) <renderer0> :Display opened successfully 548145233648
[LOG_LEVEL_DEBUG] (NvEglRenderer.cpp:199) <renderer0> :Egl Got display 5
[LOG_LEVEL_ERROR] (NvEglRenderer.cpp:204) <renderer0> Unable to initialize egl library
[LOG_LEVEL_ERROR] (NvEglRenderer.cpp:152) <renderer0> Got ERROR closing display
Error in setting up renderer. Check if X is running or run with --disable-rendering
TVMR: cbDisplayPicture: 3753: Retunred NULL Frame Buffer 
TVMR: cbDisplayPicture: 3753: Retunred NULL Frame Buffer 
TVMR: cbDisplayPicture: 3753: Retunred NULL Frame Buffer 
TVMR: cbDisplayPicture: 3753: Retunred NULL Frame Buffer 
TVMR: cbDisplayPicture: 3753: Retunred NULL Frame Buffer 
TVMR: cbDisplayPicture: 3753: Retunred NULL Frame Buffer 
TVMR: cbDisplayPicture: 3753: Retunred NULL Frame Buffer 
TVMR: cbDisplayPicture: 3753: Retunred NULL Frame Buffer 
TVMR: cbDisplayPicture: 3753: Retunred NULL Frame Buffer 
TVMR: cbDisplayPicture: 3753: Retunred NULL Frame Buffer 
TVMR: cbDisplayPicture: 3753: Retunred NULL Frame Buffer 
TVMR: cbDisplayPicture: 3753: Retunred NULL Frame Buffer 
TVMR: cbDisplayPicture: 3753: Retunred NULL Frame Buffer 
TVMR: cbDisplayPicture: 3753: Retunred NULL Frame Buffer 
TVMR: TVMRBufferProcessing: 4955: Consume the extra signalling for EOS 
TVMR: cbDisplayPicture: 3753: Retunred NULL Frame Buffer 
[LOG_LEVEL_DEBUG] (NvV4l2ElementPlane.cpp:467) <dec0> :Output Plane:STREAMOFF successful
[LOG_LEVEL_DEBUG] (NvV4l2ElementPlane.cpp:446) <dec0> :Capture Plane:Already in STREAMOFF
Error in query_and_set_capture
Exiting decoder capture loop thread
Error DQing buffer at output plane
[LOG_LEVEL_DEBUG] (NvV4l2ElementPlane.cpp:446) <dec0> :Output Plane:Already in STREAMOFF
[LOG_LEVEL_DEBUG] (NvV4l2ElementPlane.cpp:446) <dec0> :Capture Plane:Already in STREAMOFF
----------- Element = dec0 -----------
Total Profiling time = 0
Average FPS = 0
Total units processed = 0
-------------------------------------
************************************
Total Profiling Time = 0 sec
************************************
delete decoder
[LOG_LEVEL_DEBUG] (NvV4l2ElementPlane.cpp:446) <dec0> :Output Plane:Already in STREAMOFF
[LOG_LEVEL_DEBUG] (NvV4l2ElementPlane.cpp:831) <dec0> :Output Plane:Stopped DQ Thread
[LOG_LEVEL_DEBUG] (NvBuffer.cpp:201) <Buffer> Buffer 0 unmapped 
[LOG_LEVEL_DEBUG] (NvBuffer.cpp:201) <Buffer> Buffer 1 unmapped 
[LOG_LEVEL_DEBUG] (NvBuffer.cpp:201) <Buffer> Buffer 2 unmapped 
[LOG_LEVEL_DEBUG] (NvBuffer.cpp:201) <Buffer> Buffer 3 unmapped 
[LOG_LEVEL_DEBUG] (NvBuffer.cpp:201) <Buffer> Buffer 4 unmapped 
[LOG_LEVEL_DEBUG] (NvBuffer.cpp:201) <Buffer> Buffer 5 unmapped 
[LOG_LEVEL_DEBUG] (NvBuffer.cpp:201) <Buffer> Buffer 6 unmapped 
[LOG_LEVEL_DEBUG] (NvBuffer.cpp:201) <Buffer> Buffer 7 unmapped 
[LOG_LEVEL_DEBUG] (NvBuffer.cpp:201) <Buffer> Buffer 8 unmapped 
[LOG_LEVEL_DEBUG] (NvBuffer.cpp:201) <Buffer> Buffer 9 unmapped 
[LOG_LEVEL_DEBUG] (NvV4l2ElementPlane.cpp:433) <dec0> :Output Plane:Reqbuf returned 0 buffers
[LOG_LEVEL_DEBUG] (NvV4l2ElementPlane.cpp:372) <dec0> :Output Plane:deinit successful
[LOG_LEVEL_DEBUG] (NvV4l2ElementPlane.cpp:446) <dec0> :Capture Plane:Already in STREAMOFF
[LOG_LEVEL_DEBUG] (NvV4l2ElementPlane.cpp:831) <dec0> :Capture Plane:Stopped DQ Thread
[LOG_LEVEL_DEBUG] (NvV4l2ElementPlane.cpp:433) <dec0> :Capture Plane:Reqbuf returned 0 buffers
[LOG_LEVEL_DEBUG] (NvV4l2ElementPlane.cpp:372) <dec0> :Capture Plane:deinit successful
TVMR: TVMRFrameStatusReporting: 6067: Closing TVMR Frame Status Thread -------------
TVMR: TVMRVPRFloorSizeSettingThread: 5885: Closing TVMRVPRFloorSizeSettingThread -------------
TVMR: TVMRFrameDelivery: 5917: Closing TVMR Frame Delivery Thread -------------
TVMR: NvMMLiteTVMRDecBlockClose: 7740: Done 
[LOG_LEVEL_DEBUG] (NvV4l2Element.cpp:87) <V4l2Element> Device closed, fd = 5

Hi Li Lin,
We have confirmed it is an X11 fd leakage issue. The fix will be in next release.

Hi DaneLLL,

I am getting “Failed to query video capabilities: Bad address” when I run other samples as well. Kindly check out this post by me :

https://devtalk.nvidia.com/default/topic/1021843/10_camera_recording-sample-not-working/#5200199

Has this been fixed in the latest release ?

Thanks.

It is a warning message and harmless.

Hi li_lin and DaneLLL,
I am following up this topic. Now I have 28.2 on TX2, and I do the same modification to 00_video_decode as li_lin.
The code is here: (add a while loop to wrap everything and change the return statement)

int
main(int argc, char *argv[])
{
while(1) { /* I changed here !!!!!!!!!!!!!! */
    context_t ctx;
    int ret = 0;
    int error = 0;
    uint32_t current_file = 0;
    uint32_t i;
    bool eos = false;
    char *nalu_parse_buffer = NULL;
    NvApplicationProfiler &profiler = NvApplicationProfiler::getProfilerInstance();

    set_defaults(&ctx);

    if (parse_csv_args(&ctx, argc, argv))
    {
        fprintf(stderr, "Error parsing commandline arguments\n");
        return -1;
    }

    ctx.dec = NvVideoDecoder::createVideoDecoder("dec0");
    TEST_ERROR(!ctx.dec, "Could not create decoder", cleanup);

    if (ctx.stats)
    {
        profiler.start(NvApplicationProfiler::DefaultSamplingInterval);
        ctx.dec->enableProfiling();
    }

    // Subscribe to Resolution change event
    ret = ctx.dec->subscribeEvent(V4L2_EVENT_RESOLUTION_CHANGE, 0, 0);
    TEST_ERROR(ret < 0, "Could not subscribe to V4L2_EVENT_RESOLUTION_CHANGE",
               cleanup);

    if (ctx.input_nalu)
    {
        nalu_parse_buffer = new char[CHUNK_SIZE];
    }
    else
    {
        // Set V4L2_CID_MPEG_VIDEO_DISABLE_COMPLETE_FRAME_INPUT control to false
        // so that application can send chunks of encoded data instead of forming
        // complete frames. This needs to be done before setting format on the
        // output plane.
        ret = ctx.dec->disableCompleteFrameInputBuffer();
        TEST_ERROR(ret < 0,
                "Error in decoder disableCompleteFrameInputBuffer", cleanup);
    }

    // Set format on the output plane
    ret = ctx.dec->setOutputPlaneFormat(ctx.decoder_pixfmt, CHUNK_SIZE);
    TEST_ERROR(ret < 0, "Could not set output plane format", cleanup);

    // V4L2_CID_MPEG_VIDEO_DISABLE_DPB should be set after output plane
    // set format
    if (ctx.disable_dpb)
    {
        ret = ctx.dec->disableDPB();
        TEST_ERROR(ret < 0, "Error in decoder disableDPB", cleanup);
    }

    if (ctx.enable_metadata || ctx.enable_input_metadata)
    {
        ret = ctx.dec->enableMetadataReporting();
        TEST_ERROR(ret < 0, "Error while enabling metadata reporting", cleanup);
    }

    if (ctx.skip_frames)
    {
        ret = ctx.dec->setSkipFrames(ctx.skip_frames);
        TEST_ERROR(ret < 0, "Error while setting skip frames param", cleanup);
    }

    // Query, Export and Map the output plane buffers so that we can read
    // encoded data into the buffers
    if (ctx.memory_type == V4L2_MEMORY_MMAP)
        ret = ctx.dec->output_plane.setupPlane(V4L2_MEMORY_MMAP, 10, true, false);
    else if (ctx.memory_type == V4L2_MEMORY_USERPTR)
        ret = ctx.dec->output_plane.setupPlane(V4L2_MEMORY_USERPTR, 10, false, true);

    TEST_ERROR(ret < 0, "Error while setting up output plane", cleanup);

    ctx.in_file = (std::ifstream **)malloc(sizeof(std::ifstream *)*ctx.file_count);
    for (uint32_t i = 0 ; i < ctx.file_count ; i++)
    {
        ctx.in_file[i] = new ifstream(ctx.in_file_path[i]);
        TEST_ERROR(!ctx.in_file[i]->is_open(), "Error opening input file", cleanup);
    }

    if (ctx.out_file_path)
    {
        ctx.out_file = new ofstream(ctx.out_file_path);
        TEST_ERROR(!ctx.out_file->is_open(), "Error opening output file",
                   cleanup);
    }

#ifndef USE_NVBUF_TRANSFORM_API
    if (ctx.out_file || (!ctx.disable_rendering && !ctx.stats))
    {
        // Create converter to convert from BL to PL for writing raw video
        // to file
        ctx.conv = NvVideoConverter::createVideoConverter("conv0");
        TEST_ERROR(!ctx.conv, "Could not create video converter", cleanup);
        ctx.conv->output_plane.
            setDQThreadCallback(conv0_output_dqbuf_thread_callback);
        ctx.conv->capture_plane.
            setDQThreadCallback(conv0_capture_dqbuf_thread_callback);

        if (ctx.stats)
        {
            ctx.conv->enableProfiling();
        }
    }
#endif

    ret = ctx.dec->output_plane.setStreamStatus(true);
    TEST_ERROR(ret < 0, "Error in output plane stream on", cleanup);

    pthread_create(&ctx.dec_capture_loop, NULL, dec_capture_loop_fcn, &ctx);

    if (ctx.copy_timestamp && ctx.input_nalu) {
      ctx.timestamp = (ctx.start_ts * MICROSECOND_UNIT);
      ctx.timestampincr = (MICROSECOND_UNIT * 16) / ((uint32_t) (ctx.dec_fps * 16));
    }

    // Read encoded data and enqueue all the output plane buffers.
    // Exit loop in case file read is complete.
    i = 0;
    while (!eos && !ctx.got_error && !ctx.dec->isInError() &&
           i < ctx.dec->output_plane.getNumBuffers())
    {
        struct v4l2_buffer v4l2_buf;
        struct v4l2_plane planes[MAX_PLANES];
        NvBuffer *buffer;

        memset(&v4l2_buf, 0, sizeof(v4l2_buf));
        memset(planes, 0, sizeof(planes));

        buffer = ctx.dec->output_plane.getNthBuffer(i);
        if ((ctx.decoder_pixfmt == V4L2_PIX_FMT_H264) ||
                (ctx.decoder_pixfmt == V4L2_PIX_FMT_H265))
        {
            if (ctx.input_nalu)
            {
                read_decoder_input_nalu(ctx.in_file[current_file], buffer, nalu_parse_buffer,
                        CHUNK_SIZE, &ctx);
            }
            else
            {
                read_decoder_input_chunk(ctx.in_file[current_file], buffer);
            }
        }
        if (ctx.decoder_pixfmt == V4L2_PIX_FMT_VP9)
        {
            ret = read_vp9_decoder_input_chunk(&ctx, buffer);
            if (ret != 0)
                cerr << "Couldn't read VP9 chunk" << endl;
        }
        v4l2_buf.index = i;
        v4l2_buf.m.planes = planes;
        v4l2_buf.m.planes[0].bytesused = buffer->planes[0].bytesused;

        if (ctx.input_nalu && ctx.copy_timestamp && ctx.flag_copyts)
        {
          v4l2_buf.flags |= V4L2_BUF_FLAG_TIMESTAMP_COPY;
          ctx.timestamp += ctx.timestampincr;
          v4l2_buf.timestamp.tv_sec = ctx.timestamp / (MICROSECOND_UNIT);
          v4l2_buf.timestamp.tv_usec = ctx.timestamp % (MICROSECOND_UNIT);
        }

        if (v4l2_buf.m.planes[0].bytesused == 0)
        {
            if (ctx.bQueue)
            {
                current_file++;
                if(current_file != ctx.file_count)
                {
                    continue;
                }
            }
            if(ctx.bLoop)
            {
                current_file = current_file % ctx.file_count;
                continue;
            }
        }
        // It is necessary to queue an empty buffer to signal EOS to the decoder
        // i.e. set v4l2_buf.m.planes[0].bytesused = 0 and queue the buffer
        ret = ctx.dec->output_plane.qBuffer(v4l2_buf, NULL);
        if (ret < 0)
        {
            cerr << "Error Qing buffer at output plane" << endl;
            abort(&ctx);
            break;
        }
        if (v4l2_buf.m.planes[0].bytesused == 0)
        {
            eos = true;
            cout << "Input file read complete" << endl;
            break;
        }
        i++;
    }

    // Since all the output plane buffers have been queued, we first need to
    // dequeue a buffer from output plane before we can read new data into it
    // and queue it again.
    while (!eos && !ctx.got_error && !ctx.dec->isInError())
    {
        struct v4l2_buffer v4l2_buf;
        struct v4l2_plane planes[MAX_PLANES];
        NvBuffer *buffer;

        memset(&v4l2_buf, 0, sizeof(v4l2_buf));
        memset(planes, 0, sizeof(planes));

        v4l2_buf.m.planes = planes;

        ret = ctx.dec->output_plane.dqBuffer(v4l2_buf, &buffer, NULL, -1);
        if (ret < 0)
        {
            cerr << "Error DQing buffer at output plane" << endl;
            abort(&ctx);
            break;
        }

        if ((v4l2_buf.flags & V4L2_BUF_FLAG_ERROR) && ctx.enable_input_metadata)
        {
            v4l2_ctrl_videodec_inputbuf_metadata dec_input_metadata;

            ret = ctx.dec->getInputMetadata(v4l2_buf.index, dec_input_metadata);
            if (ret == 0)
            {
                ret = report_input_metadata(&ctx, &dec_input_metadata);
                if (ret == -1)
                {
                  cerr << "Error with input stream header parsing" << endl;
                }
            }
        }

        if ((ctx.decoder_pixfmt == V4L2_PIX_FMT_H264) ||
                (ctx.decoder_pixfmt == V4L2_PIX_FMT_H265))
        {
            if (ctx.input_nalu)
            {
                read_decoder_input_nalu(ctx.in_file[current_file], buffer, nalu_parse_buffer,
                        CHUNK_SIZE, &ctx);
            }
            else
            {
                read_decoder_input_chunk(ctx.in_file[current_file], buffer);
            }
        }
        if (ctx.decoder_pixfmt == V4L2_PIX_FMT_VP9)
        {
            ret = read_vp9_decoder_input_chunk(&ctx, buffer);
            if (ret != 0)
                cerr << "Couldn't read VP9 chunk" << endl;
        }
        v4l2_buf.m.planes[0].bytesused = buffer->planes[0].bytesused;

        if (ctx.input_nalu && ctx.copy_timestamp && ctx.flag_copyts)
        {
          v4l2_buf.flags |= V4L2_BUF_FLAG_TIMESTAMP_COPY;
          ctx.timestamp += ctx.timestampincr;
          v4l2_buf.timestamp.tv_sec = ctx.timestamp / (MICROSECOND_UNIT);
          v4l2_buf.timestamp.tv_usec = ctx.timestamp % (MICROSECOND_UNIT);
        }

        if (v4l2_buf.m.planes[0].bytesused == 0)
        {
            if (ctx.bQueue)
            {
                current_file++;
                if(current_file != ctx.file_count)
                {
                    continue;
                }
            }
            if(ctx.bLoop)
            {
                current_file = current_file % ctx.file_count;
                continue;
            }
        }
        ret = ctx.dec->output_plane.qBuffer(v4l2_buf, NULL);
        if (ret < 0)
        {
            cerr << "Error Qing buffer at output plane" << endl;
            abort(&ctx);
            break;
        }
        if (v4l2_buf.m.planes[0].bytesused == 0)
        {
            eos = true;
            cout << "Input file read complete" << endl;
            break;
        }
    }

    // After sending EOS, all the buffers from output plane should be dequeued.
    // and after that capture plane loop should be signalled to stop.
    while (ctx.dec->output_plane.getNumQueuedBuffers() > 0 &&
           !ctx.got_error && !ctx.dec->isInError())
    {
        struct v4l2_buffer v4l2_buf;
        struct v4l2_plane planes[MAX_PLANES];

        memset(&v4l2_buf, 0, sizeof(v4l2_buf));
        memset(planes, 0, sizeof(planes));

        v4l2_buf.m.planes = planes;
        ret = ctx.dec->output_plane.dqBuffer(v4l2_buf, NULL, NULL, -1);
        if (ret < 0)
        {
            cerr << "Error DQing buffer at output plane" << endl;
            abort(&ctx);
            break;
        }

        if ((v4l2_buf.flags & V4L2_BUF_FLAG_ERROR) && ctx.enable_input_metadata)
        {
            v4l2_ctrl_videodec_inputbuf_metadata dec_input_metadata;

            ret = ctx.dec->getInputMetadata(v4l2_buf.index, dec_input_metadata);
            if (ret == 0)
            {
                ret = report_input_metadata(&ctx, &dec_input_metadata);
                if (ret == -1)
                {
                  cerr << "Error with input stream header parsing" << endl;
                  abort(&ctx);
                  break;
                }
            }
        }
    }

    // Signal EOS to the decoder capture loop
    ctx.got_eos = true;
#ifndef USE_NVBUF_TRANSFORM_API
    if (ctx.conv)
    {
        ctx.conv->capture_plane.waitForDQThread(-1);
    }
#endif

    if (ctx.stats)
    {
        profiler.stop();
        ctx.dec->printProfilingStats(cout);
#ifndef USE_NVBUF_TRANSFORM_API
        if (ctx.conv)
        {
            ctx.conv->printProfilingStats(cout);
        }
#endif
        if (ctx.renderer)
        {
            ctx.renderer->printProfilingStats(cout);
        }
        profiler.printProfilerData(cout);
    }

cleanup:
    if (ctx.dec_capture_loop)
    {
        pthread_join(ctx.dec_capture_loop, NULL);
    }
#ifndef USE_NVBUF_TRANSFORM_API
    if (ctx.conv && ctx.conv->isInError())
    {
        cerr << "Converter is in error" << endl;
        error = 1;
    }
#endif
    if (ctx.dec && ctx.dec->isInError())
    {
        cerr << "Decoder is in error" << endl;
        error = 1;
    }

    if (ctx.got_error)
    {
        error = 1;
    }

    // The decoder destructor does all the cleanup i.e set streamoff on output and capture planes,
    // unmap buffers, tell decoder to deallocate buffer (reqbufs ioctl with counnt = 0),
    // and finally call v4l2_close on the fd.
    delete ctx.dec;
#ifndef USE_NVBUF_TRANSFORM_API
    delete ctx.conv;
#endif
    // Similarly, EglRenderer destructor does all the cleanup
    delete ctx.renderer;
    for (uint32_t i = 0 ; i < ctx.file_count ; i++)
      delete ctx.in_file[i];
    delete ctx.out_file;
#ifndef USE_NVBUF_TRANSFORM_API
    delete ctx.conv_output_plane_buf_queue;
#else
    if(ctx.dst_dma_fd != -1)
    {
        NvBufferDestroy(ctx.dst_dma_fd);
        ctx.dst_dma_fd = -1;
    }
#endif
    delete[] nalu_parse_buffer;
    free (ctx.in_file);
    for (uint32_t i = 0 ; i < ctx.file_count ; i++)
      free (ctx.in_file_path[i]);
    free (ctx.in_file_path);
    free(ctx.out_file_path);
    if (error)
    {
        cout << "App run failed" << endl;
    }
    else
    {
        cout << "App run was successful" << endl;
    }
} /* I changed here !!!!!!!!!!!!!! */
    return 0; /* I changed here !!!!!!!!!!!!!! */
}

And I run the program like:

./video_decode H264 /home/nvidia/Videos/car_1080p_10fps.h264

Basically, I want it to repeat decode and render one h264 file over and over again. But after 1 st iteration, it won’t work as intended and emit errors:

nvbuf_utils: nvbuffer Payload Type not supported
NvBufferGetParams failed for src_dmabuf_fd
nvbuffer_transform Failed
Transform failed
nvbuf_utils: nvbuffer Payload Type not supported
NvBufferGetParams failed for src_dmabuf_fd
nvbuffer_transform Failed
Transform failed
nvbuf_utils: nvbuffer Payload Type not supported
NvBufferGetParams failed for src_dmabuf_fd
nvbuffer_transform Failed
Transform failed
nvbuf_utils: nvbuffer Payload Type not supported
NvBufferGetParams failed for src_dmabuf_fd
nvbuffer_transform Failed
Transform failed
nvbuf_utils: nvbuffer Payload Type not supported
NvBufferGetParams failed for src_dmabuf_fd
nvbuffer_transform Failed
Transform failed
...

I have to ctrl+c it. So, what’s going wrong here?

And if I want to decode more than one h264 file, how can I work it out? Now I can think of 2 ways to do so, as a work around to the problem mentioned above:
Guess 1: I should put them in a list and then pass them one by one to the NvVideoDecoder just like this sample did, but never clean up decoder and converter. Right?
Guess 2: I can create multiple pairs of decoder and converter, each pair working on a separate thread, but this method won’t be able to work if we create more than 8 pairs of decoder and converter, which is because that 16 video devices is the default upper limit for MMAPI. Right?

Or, could you please kindly give comments on my guesses or give a hint? A big thx! :) :) :)

Hi fengxueem,
Your issue is not same as this thread. Please start a new post.

Hi DaneLLL,
Thx for your reply. Opening a new thread.