Repository: opencv
Issue: opencv4.4   decode video with gpu    /opencv-4.4.0/modules/core/src/cuda/gpu_mat.cu:121: error: (-217:Gpu API call) all CUDA-capable devices are busy or unavailable in function 'allocate'
Labels: category: gpu/cuda (contrib),incomplete,needs investigation

System information (version)
OpenCV = 4.4.0 
Operating System / Platform = ubuntu 18.04
Compiler = gcc/g++ 7.5
cuda = 10.0
Video_Codec_SDK_9.1.23

I have build my opencv 4.4.0 using Cmak with CUDA 10.0 to speedup decoding videos. I tested code1.cpp , code2.cpp and 
 code3.cpp.   Results are below.

**1. code1.cpp             sucess
2. code2.cpp                failure
3. code3.cpp                sucess**


In code2.cpp ,  I just comment  all code related to display and get error information **(terminate called after throwing an instance of 'cv::Exception'
  what():  OpenCV(4.4.0) /home/py/Downloads/opencv-4.4.0/modules/core/src/cuda/gpu_mat.cu:121: error: (-217:Gpu API call) all CUDA-capable devices are busy or unavailable in function 'allocate'**

In code3.cpp,  I uncomment "cv::namedWindow("GPU", cv::WINDOW_OPENGL);" ,  it can work. I do not know the impact of "cv::namedWindow("GPU", cv::WINDOW_OPENGL);", .

 the output of gdb code2.cpp is 
```
GNU gdb (Ubuntu 8.1.1-0ubuntu1) 8.1.1
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from build/main...(no debugging symbols found)...done.
(gdb) r
Starting program: /home/py/testcase-10/gpu-decode/build/main
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7fffd9813700 (LWP 6993)]
gpus=1
1
[New Thread 0x7fffd9012700 (LWP 6994)]
[New Thread 0x7fffd8811700 (LWP 6995)]
[New Thread 0x7fffd3fff700 (LWP 6996)]
[New Thread 0x7fffd37fe700 (LWP 6997)]
[New Thread 0x7fffd2ffd700 (LWP 6998)]
[New Thread 0x7fffd27fc700 (LWP 6999)]
[New Thread 0x7fffd1ffb700 (LWP 7000)]
[New Thread 0x7fffd17fa700 (LWP 7001)]
[New Thread 0x7fffd0ff9700 (LWP 7002)]
[New Thread 0x7fffbffff700 (LWP 7003)]
[New Thread 0x7fffbf7fe700 (LWP 7004)]
[New Thread 0x7fffbeffd700 (LWP 7005)]
[New Thread 0x7fffbe7fc700 (LWP 7006)]
[New Thread 0x7fffbdffb700 (LWP 7007)]
[New Thread 0x7fffbd7fa700 (LWP 7008)]
[New Thread 0x7fffbcff9700 (LWP 7009)]
2
[New Thread 0x7fffbc7f8700 (LWP 7010)]
[New Thread 0x7fffbbff7700 (LWP 7011)]
[New Thread 0x7fffbb7f6700 (LWP 7012)]
[New Thread 0x7fffbaff5700 (LWP 7014)]
[New Thread 0x7fffba7f4700 (LWP 7015)]
[New Thread 0x7fffb9ff3700 (LWP 7016)]
[New Thread 0x7fffb97f2700 (LWP 7017)]
[New Thread 0x7fffb8ff1700 (LWP 7018)]
[New Thread 0x7fffb87f0700 (LWP 7019)]
[New Thread 0x7fffb7fef700 (LWP 7020)]
[New Thread 0x7fffb77ee700 (LWP 7021)]
[New Thread 0x7fffb6fed700 (LWP 7022)]
[New Thread 0x7fffb67ec700 (LWP 7023)]
[New Thread 0x7fffb5feb700 (LWP 7024)]
[New Thread 0x7fffb57ea700 (LWP 7025)]
[New Thread 0x7fffb4fe9700 (LWP 7026)]
terminate called after throwing an instance of 'cv::Exception'
  what():  OpenCV(4.4.0) /home/py/Downloads/opencv-4.4.0/modules/core/src/cuda/gpu_mat.cu:121: error: (-217:Gpu API call) all CUDA-capable devices are busy or unavailable in function 'allocate'


Thread 1 "main" received signal SIGABRT, Aborted.
__GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
51      ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) bt
#0  0x00007ffff1291fb7 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#1  0x00007ffff1293921 in __GI_abort () at abort.c:79
#2  0x00007ffff1c86957 in  () at /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3  0x00007ffff1c8cae6 in  () at /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#4  0x00007ffff1c8cb21 in  () at /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#5  0x00007ffff1c8cd54 in  () at /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#6  0x00005555556d6aa2 in cv::error(cv::Exception const&) ()
#7  0x00005555556d8182 in cv::error(int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*, char const*, int) ()
#8  0x0000555555750f0f in cv::cuda::GpuMat::create(int, int, int) ()
#9  0x00005555559dcd38 in (anonymous namespace)::VideoReaderImpl::VideoReaderImpl(cv::Ptr<cv::cudacodec::detail::VideoSource> const&) ()
#10 0x00005555559ddf13 in cv::cudacodec::createVideoReader(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) ()
#11 0x0000555555637436 in main ()
```
all test code are showed  below.
**//-----------code1.cpp--------------------**
```
**//-----------code1.cpp--------------------**
#include <iostream>
#include "opencv2/opencv_modules.hpp"
#if defined(HAVE_OPENCV_CUDACODEC)
#include <string>
#include <vector>
#include <algorithm>
#include <numeric>
#include <opencv2/core.hpp>
#include <opencv2/core/opengl.hpp>
#include <opencv2/cudacodec.hpp>
#include <opencv2/highgui.hpp>
int main(int argc, const char* argv[])
{
    const std::string fname = "./ch01_20191121144300.mp4";

    cv::namedWindow("CPU", cv::WINDOW_NORMAL);
    
    cv::namedWindow("GPU", cv::WINDOW_OPENGL);
    std::cout << "gpus=" << cv::cuda::getCudaEnabledDeviceCount() << std::endl;
    cv::cuda::setGlDevice();

    cv::Mat frame;
    cv::VideoCapture reader(fname);

    cv::cuda::GpuMat d_frame;
    cv::Ptr<cv::cudacodec::VideoReader> d_reader = cv::cudacodec::createVideoReader(fname);

    cv::TickMeter tm;
    std::vector<double> cpu_times;
    std::vector<double> gpu_times;

    int gpu_frame_count=0, cpu_frame_count=0;

    for (;;)
    {
        tm.reset(); tm.start();
        if (!reader.read(frame))
            break;
        tm.stop();
        cpu_times.push_back(tm.getTimeMilli());
        cpu_frame_count++;

        cv::imshow("CPU", frame);

        if (cv::waitKey(3) > 0)
            break;
    }

    for (;;)
    {
        tm.reset(); tm.start();
        if (!d_reader->nextFrame(d_frame))
            break;
        tm.stop();
        gpu_times.push_back(tm.getTimeMilli());
        gpu_frame_count++;

        cv::imshow("GPU", d_frame);

        if (cv::waitKey(3) > 0)
            break;
    }

    if (!cpu_times.empty() && !gpu_times.empty())
    {
        std::cout << std::endl << "Results:" << std::endl;

        std::sort(cpu_times.begin(), cpu_times.end());
        std::sort(gpu_times.begin(), gpu_times.end());

        double cpu_avg = std::accumulate(cpu_times.begin(), cpu_times.end(), 0.0) / cpu_times.size();
        double gpu_avg = std::accumulate(gpu_times.begin(), gpu_times.end(), 0.0) / gpu_times.size();

        std::cout << "CPU : Avg : " << cpu_avg << " ms FPS : " << 1000.0 / cpu_avg << " Frames " << cpu_frame_count << std::endl;
        std::cout << "GPU : Avg : " << gpu_avg << " ms FPS : " << 1000.0 / gpu_avg << " Frames " << gpu_frame_count << std::endl;
    }

    return 0;
}

#else

int main()
{
    std::cout << "OpenCV was built without CUDA Video decoding support\n" << std::endl;
    return 0;
}

#endif
```
**//-----------code2.cpp--------------------**
```
**//-----------code2.cpp--------------------**
#include <iostream>

#include "opencv2/opencv_modules.hpp"

#if defined(HAVE_OPENCV_CUDACODEC)

#include <string>
#include <vector>
#include <algorithm>
#include <numeric>
#include <opencv2/core.hpp>
#include <opencv2/core/opengl.hpp>
#include <opencv2/cudacodec.hpp>
#include <opencv2/highgui.hpp>

int main(int argc, const char* argv[])
{
    const std::string fname = "./ch01_20191121144300.mp4";

    // cv::namedWindow("CPU", cv::WINDOW_NORMAL);
    
    // cv::namedWindow("GPU", cv::WINDOW_OPENGL);
    std::cout << "gpus=" << cv::cuda::getCudaEnabledDeviceCount() << std::endl;
    cv::cuda::setGlDevice();
    std::cout << "1" << std::endl;

    cv::Mat frame;
    cv::VideoCapture reader(fname);
    std::cout << "2" << std::endl;

    cv::cuda::GpuMat d_frame;
    cv::Ptr<cv::cudacodec::VideoReader> d_reader = cv::cudacodec::createVideoReader(fname);
    std::cout << "3" << std::endl;
    cv::TickMeter tm;
    std::vector<double> cpu_times;
    std::vector<double> gpu_times;

    int gpu_frame_count=0, cpu_frame_count=0;

    for (;;)
    {
        tm.reset(); tm.start();
        if (!reader.read(frame))
            break;
        tm.stop();
        cpu_times.push_back(tm.getTimeMilli());
        cpu_frame_count++;

        // cv::imshow("CPU", frame);

        // if (cv::waitKey(3) > 0)
        //     break;
    }

    for (;;)
    {
        tm.reset(); tm.start();
        if (!d_reader->nextFrame(d_frame))
            break;
        tm.stop();
        gpu_times.push_back(tm.getTimeMilli());
        gpu_frame_count++;

        // cv::imshow("GPU", d_frame);

        // if (cv::waitKey(3) > 0)
        //     break;
    }

    if (!cpu_times.empty() && !gpu_times.empty())
    {
        std::cout << std::endl << "Results:" << std::endl;

        std::sort(cpu_times.begin(), cpu_times.end());
        std::sort(gpu_times.begin(), gpu_times.end());

        double cpu_avg = std::accumulate(cpu_times.begin(), cpu_times.end(), 0.0) / cpu_times.size();
        double gpu_avg = std::accumulate(gpu_times.begin(), gpu_times.end(), 0.0) / gpu_times.size();

        std::cout << "CPU : Avg : " << cpu_avg << " ms FPS : " << 1000.0 / cpu_avg << " Frames " << cpu_frame_count << std::endl;
        std::cout << "GPU : Avg : " << gpu_avg << " ms FPS : " << 1000.0 / gpu_avg << " Frames " << gpu_frame_count << std::endl;
    }

    return 0;
}

#else

int main()
{
    std::cout << "OpenCV was built without CUDA Video decoding support\n" << std::endl;
    return 0;
}

#endif
```
**//-----------code3.cpp--------------------**
```
**//-----------code3.cpp--------------------**
#include <iostream>

#include "opencv2/opencv_modules.hpp"

#if defined(HAVE_OPENCV_CUDACODEC)

#include <string>
#include <vector>
#include <algorithm>
#include <numeric>
#include <opencv2/core.hpp>
#include <opencv2/core/opengl.hpp>
#include <opencv2/cudacodec.hpp>
#include <opencv2/highgui.hpp>

int main(int argc, const char* argv[])
{
    const std::string fname = "./ch01_20191121144300.mp4";

    // cv::namedWindow("CPU", cv::WINDOW_NORMAL);
    
    cv::namedWindow("GPU", cv::WINDOW_OPENGL);
    std::cout << "gpus=" << cv::cuda::getCudaEnabledDeviceCount() << std::endl;
    cv::cuda::setGlDevice();
    std::cout << "1" << std::endl;

    cv::Mat frame;
    cv::VideoCapture reader(fname);
    std::cout << "2" << std::endl;

    cv::cuda::GpuMat d_frame;
    cv::Ptr<cv::cudacodec::VideoReader> d_reader = cv::cudacodec::createVideoReader(fname);
    std::cout << "3" << std::endl;
    cv::TickMeter tm;
    std::vector<double> cpu_times;
    std::vector<double> gpu_times;

    int gpu_frame_count=0, cpu_frame_count=0;

    for (;;)
    {
        tm.reset(); tm.start();
        if (!reader.read(frame))
            break;
        tm.stop();
        cpu_times.push_back(tm.getTimeMilli());
        cpu_frame_count++;

        // cv::imshow("CPU", frame);

        // if (cv::waitKey(3) > 0)
        //     break;
    }

    for (;;)
    {
        tm.reset(); tm.start();
        if (!d_reader->nextFrame(d_frame))
            break;
        tm.stop();
        gpu_times.push_back(tm.getTimeMilli());
        gpu_frame_count++;

        // cv::imshow("GPU", d_frame);

        // if (cv::waitKey(3) > 0)
        //     break;
    }

    if (!cpu_times.empty() && !gpu_times.empty())
    {
        std::cout << std::endl << "Results:" << std::endl;

        std::sort(cpu_times.begin(), cpu_times.end());
        std::sort(gpu_times.begin(), gpu_times.end());

        double cpu_avg = std::accumulate(cpu_times.begin(), cpu_times.end(), 0.0) / cpu_times.size();
        double gpu_avg = std::accumulate(gpu_times.begin(), gpu_times.end(), 0.0) / gpu_times.size();

        std::cout << "CPU : Avg : " << cpu_avg << " ms FPS : " << 1000.0 / cpu_avg << " Frames " << cpu_frame_count << std::endl;
        std::cout << "GPU : Avg : " << gpu_avg << " ms FPS : " << 1000.0 / gpu_avg << " Frames " << gpu_frame_count << std::endl;
    }

    return 0;
}

#else

int main()
{
    std::cout << "OpenCV was built without CUDA Video decoding support\n" << std::endl;
    return 0;
}

#endif
```