Repository: opencv
Issue: After setting the decoder to hevc_cuvid, VideoCapture reads video more slowly
Labels: category: videoio,needs investigation

<!--
If you have a question rather than reporting a bug please go to https://forum.opencv.org where you get much faster responses.
If you need further assistance please read [How To Contribute](https://github.com/opencv/opencv/wiki/How_to_contribute).

This is a template helping you to create an issue which can be processed as quickly as possible. This is the bug reporting section for the OpenCV library.
-->

##### System information (version)
<!-- Example
- OpenCV => 4.2
- Operating System / Platform => Windows 64 Bit
- Compiler => Visual Studio 2017
-->

- OpenCV => 4.5.4
- Operating System / Platform => Ubuntu 20.04.3 LTS
- Compiler => gcc version 9.4.0

##### Detailed description

<!-- your description -->
I have a code that tests how long VideoCapture takes to read a video.
```cpp
uint64_t get_timestamp() {
    using namespace std::chrono;
    return duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
}

int main(int argc, char** argv)
{
    auto start = get_timestamp();
    cv::VideoCapture cap("base.ts", cv::CAP_FFMPEG
        // , { cv::CAP_PROP_HW_ACCELERATION, cv::VIDEO_ACCELERATION_ANY }
    );
    if (!cap.isOpened())
    {
        std::cerr << "Open file fails" << std::endl;
        return -1;
    }
    cv::Mat frame;
    while (true) {
        cap >> frame;
        if (frame.empty()) {
            break;
        }
    }
    auto end = get_timestamp();
    std::cout << (end - start) << std::endl;
}
```
The build information for my ffmpeg is as follows:
```shell
ffmpeg version 4.2.4-1ubuntu0.1 Copyright (c) 2000-2020 the FFmpeg developers
built with gcc 9 (Ubuntu 9.3.0-10ubuntu2)
configuration: --prefix=/usr --extra-version=1ubuntu0.1 --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --arch=amd64 --enable-gpl --disable-stripping --enable-avresample --disable-filter=resample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libcodec2 --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libjack --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librsvg --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-lv2 --enable-omx --enable-openal --enable-opencl --enable-opengl --enable-sdl2 --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-nvenc --enable-chromaprint --enable-frei0r --enable-libx264 --enable-shared
libavutil      56. 31.100 / 56. 31.100
libavcodec     58. 54.100 / 58. 54.100
libavformat    58. 29.100 / 58. 29.100
libavdevice    58.  8.100 / 58.  8.100
libavfilter     7. 57.100 /  7. 57.100
libavresample   4.  0.  0 /  4.  0.  0
libswscale      5.  5.100 /  5.  5.100
libswresample   3.  5.100 /  3.  5.100
libpostproc    55.  5.100 / 55.  5.100
```
And ffmpeg has a hevc_cuvid decoder:
```shell
ffmpeg -decoders|grep hevc
 VFS..D hevc                 HEVC (High Efficiency Video Coding)
 V..... hevc_v4l2m2m         V4L2 mem2mem HEVC decoder wrapper (codec hevc)
 V..... hevc_cuvid           Nvidia CUVID HEVC decoder (codec hevc)
```
I use "base.ts"(same as mentioned in the cpp code ) to test ffmpeg's hevc_cuvid decoder:
```shell
time ffmpeg -vcodec hevc_cuvid -i base.ts -f null /dev/null
frame= 6132 fps=2191 q=-0.0 Lsize=N/A time=00:06:01.05 bitrate=N/A speed= 129x

real	0m1.560s
user	0m0.740s
sys	0m0.216s

--------------------------------------------------------------

time ffmpeg -i base.ts -f null /dev/null
frame= 6132 fps=2191 q=-0.0 Lsize=N/A time=00:06:01.05 bitrate=N/A speed= 129x

real	0m2.840s
user	0m10.606s
sys	0m0.175s
```
So It looks like ffmpeg's hardware decoding acceleration is working.

I build OpenCV with the following configuration：
```shell
cmake \
  -DCMAKE_BUILD_TYPE=Release \
  -DOPENCV_GENERATE_PKGCONFIG=ON \
  -DBUILD_TESTS=OFF \
  -DBUILD_PERF_TESTS=OFF \
  -DBUILD_EXAMPLES=OFF \
  -DWITH_CUDA=OFF \
  -DWITH_FFMPEG=ON \
  -DDCMAKE_INSTALL_PREFIX=/usr/local \
  -DBUILD_opencv_python2=OFF \
  -DBUILD_opencv_python3=ON \
  ..
```
First I export OPENCV_FFMPEG_CAPTURE_OPTIONS then execute the cpp code, the execution duration is as follows
```shell
export OPENCV_FFMPEG_CAPTURE_OPTIONS="video_codec;hevc_cuvid"

real    0m5.395s
user    0m5.404s
sys     0m0.220s
```
nvidia-smi info:
```shell
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 510.60.02    Driver Version: 510.60.02    CUDA Version: 11.6     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  NVIDIA GeForce ...  Off  | 00000000:01:00.0  On |                  N/A |
|  0%   47C    P2    61W / 260W |    309MiB / 11264MiB |      5%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+
                                                                               
+-----------------------------------------------------------------------------+
| Processes:                                                                  |
|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
|        ID   ID                                                   Usage      |
|=============================================================================|
|    0   N/A  N/A      1100      G   /usr/lib/xorg/Xorg                 35MiB |
|    0   N/A  N/A      1828      G   /usr/lib/xorg/Xorg                 80MiB |
|    0   N/A  N/A      1955      G   /usr/bin/gnome-shell               20MiB |
|    0   N/A  N/A     58130      C   ...enchmark/OpenCV_benchmark      157MiB |
+-----------------------------------------------------------------------------+
```
PID: 58130 is my executable. So OpenCV does use GPU resources.

Then I unset OPENCV_FFMPEG_CAPTURE_OPTIONS and re-execute the code:
```shell
unset OPENCV_FFMPEG_CAPTURE_OPTIONS

real    0m3.035s
user    0m13.068s
sys     0m0.122s
```
nvidia-smi info:
```shell
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 510.60.02    Driver Version: 510.60.02    CUDA Version: 11.6     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  NVIDIA GeForce ...  Off  | 00000000:01:00.0  On |                  N/A |
|  0%   43C    P8    12W / 260W |    149MiB / 11264MiB |      0%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+
                                                                               
+-----------------------------------------------------------------------------+
| Processes:                                                                  |
|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
|        ID   ID                                                   Usage      |
|=============================================================================|
|    0   N/A  N/A      1100      G   /usr/lib/xorg/Xorg                 35MiB |
|    0   N/A  N/A      1828      G   /usr/lib/xorg/Xorg                 80MiB |
|    0   N/A  N/A      1955      G   /usr/bin/gnome-shell               20MiB |
+-----------------------------------------------------------------------------+
```
The process of my executable is not shown in the results, and the CPU usage is higher than before.

So my question is: when execute the cpp code, why hevc_cuvid decoders is slower than cpu. Thanks.
##### Steps to reproduce

<!-- to add code example fence it with triple backticks and optional file extension
    ```.cpp
    // C++ code example
    ```
 or attach as .txt or .zip file
-->

##### Issue submission checklist

 - [ ] I report the issue, it's not a question
   <!--
   OpenCV team works with forum.opencv.org, Stack Overflow and other communities
   to discuss problems. Tickets with questions without a real issue statement will be
   closed.
   -->
 - [x] I checked the problem with documentation, FAQ, open issues,
       forum.opencv.org, Stack Overflow, etc and have not found any solution
   <!--
   Places to check:
   * OpenCV documentation: https://docs.opencv.org
   * FAQ page: https://github.com/opencv/opencv/wiki/FAQ
   * OpenCV forum: https://forum.opencv.org
   * OpenCV issue tracker: https://github.com/opencv/opencv/issues?q=is%3Aissue
   * Stack Overflow branch: https://stackoverflow.com/questions/tagged/opencv
   -->
 - [x] I updated to the latest OpenCV version and the issue is still there
   <!--
   master branch for OpenCV 4.x and 3.4 branch for OpenCV 3.x releases.
   OpenCV team supports only the latest release for each branch.
   The ticket is closed if the problem is not reproduced with the modern version.
   -->
 - [x] There is reproducer code and related data files: videos, images, onnx, etc
   <!--
   The best reproducer -- test case for OpenCV that we can add to the library.
   Recommendations for media files and binary files:
   * Try to reproduce the issue with images and videos in opencv_extra repository
     to reduce attachment size
   * Use PNG for images, if you report some CV related bug, but not image reader
     issue
   * Attach the image as an archive to the ticket, if you report some reader issue.
     Image hosting services compress images and it breaks the repro code.
   * Provide ONNX file for some public model or ONNX file with random weights,
     if you report ONNX parsing or handling issue. Architecture details diagram
     from netron tool can be very useful too. See https://lutzroeder.github.io/netron/
   -->