Merge pull request #22615 from cudawarped:nvcuvenc
authorcudawarped <12133430+cudawarped@users.noreply.github.com>
Fri, 28 Oct 2022 08:03:51 +0000 (11:03 +0300)
committerGitHub <noreply@github.com>
Fri, 28 Oct 2022 08:03:51 +0000 (11:03 +0300)
Update CMake rules to include Nvidia Video Codec SDK encoding libs

CMakeLists.txt
cmake/FindCUDA.cmake
cmake/OpenCVDetectCUDA.cmake
cmake/templates/OpenCVConfig-CUDA.cmake.in
samples/gpu/video_reader.cpp
samples/gpu/video_writer.cpp

index dbbb10ac9f496f410543f840280c4aff368d76d4..aba65ba23f1ddc382172088ba01b7a3b184589ed 100644 (file)
@@ -266,6 +266,9 @@ OCV_OPTION(WITH_CUDNN "Include NVIDIA CUDA Deep Neural Network (cuDNN) library s
 OCV_OPTION(WITH_NVCUVID "Include NVidia Video Decoding library support" OFF  # disabled, details: https://github.com/opencv/opencv/issues/14850
   VISIBLE_IF WITH_CUDA
   VERIFY HAVE_NVCUVID)
+OCV_OPTION(WITH_NVCUVENC "Include NVidia Video Encoding library support" OFF
+  VISIBLE_IF WITH_CUDA
+  VERIFY HAVE_NVCUVENC)
 OCV_OPTION(WITH_EIGEN "Include Eigen2/Eigen3 support" (NOT CV_DISABLE_OPTIMIZATION AND NOT CMAKE_CROSSCOMPILING)
   VISIBLE_IF NOT WINRT
   VERIFY HAVE_EIGEN)
@@ -1661,6 +1664,7 @@ if(WITH_CUDA OR HAVE_CUDA)
     IF HAVE_CUFFT THEN "CUFFT"
     IF HAVE_CUBLAS THEN "CUBLAS"
     IF HAVE_NVCUVID THEN "NVCUVID"
+    IF HAVE_NVCUVENC THEN "NVCUVENC"
     IF CUDA_FAST_MATH THEN "FAST_MATH"
     ELSE "no extra features")
   status("")
index 37d557a792e1b1dc13dbba497e761171c2d81f14..ca04bb4a4ead7e0d9cc2d06a8bc3b64a36904d6e 100644 (file)
 #                            Only available for CUDA version 5.5+.
 #   CUDA_npps_LIBRARY     -- NVIDIA Performance Primitives lib (signal processing).
 #                            Only available for CUDA version 5.5+.
-#   CUDA_nvcuvenc_LIBRARY -- CUDA Video Encoder library.
+#   CUDA_nvencodeapi_LIBRARY -- CUDA Video Encoder library.
 #                            Only available for CUDA version 3.2+.
 #                            Windows only.
 #   CUDA_nvcuvid_LIBRARY  -- CUDA Video Decoder library.
@@ -530,7 +530,7 @@ macro(cuda_unset_include_and_libraries)
   unset(CUDA_nppc_LIBRARY CACHE)
   unset(CUDA_nppi_LIBRARY CACHE)
   unset(CUDA_npps_LIBRARY CACHE)
-  unset(CUDA_nvcuvenc_LIBRARY CACHE)
+  unset(CUDA_nvencodeapi_LIBRARY CACHE)
   unset(CUDA_nvcuvid_LIBRARY CACHE)
 endmacro()
 
@@ -790,7 +790,7 @@ if(NOT CUDA_VERSION VERSION_LESS "3.2")
   find_cuda_helper_libs(cusparse)
   find_cuda_helper_libs(curand)
   if (WIN32)
-    find_cuda_helper_libs(nvcuvenc)
+    find_cuda_helper_libs(nvencodeapi)
     find_cuda_helper_libs(nvcuvid)
   endif()
 endif()
index acc101396c651aa92ebc57fb54c318333d5283ea..69d0455cc844f1d9395a443c86b5647e6943b60a 100644 (file)
@@ -28,6 +28,7 @@ else()
 endif()
 
 if(CUDA_FOUND)
+  unset(CUDA_nvcuvenc_LIBRARY CACHE)
   set(HAVE_CUDA 1)
   if(NOT CUDA_VERSION VERSION_LESS 11.0)
     # CUDA 11.0 removes nppicom
@@ -53,7 +54,7 @@ if(CUDA_FOUND)
       endif()
   endif()
 
-  if(WITH_NVCUVID)
+  if(WITH_NVCUVID OR WITH_NVCUVENC)
     macro(ocv_cuda_SEARCH_NVCUVID_HEADER _filename _result)
       # place header file under CUDA_TOOLKIT_TARGET_DIR or CUDA_TOOLKIT_ROOT_DIR
       find_path(_header_result
@@ -71,18 +72,25 @@ if(CUDA_FOUND)
       endif()
       unset(_header_result CACHE)
     endmacro()
-    ocv_cuda_SEARCH_NVCUVID_HEADER("nvcuvid.h" HAVE_NVCUVID_HEADER)
-    ocv_cuda_SEARCH_NVCUVID_HEADER("dynlink_nvcuvid.h" HAVE_DYNLINK_NVCUVID_HEADER)
-    find_cuda_helper_libs(nvcuvid)
-    if(WIN32)
-      find_cuda_helper_libs(nvcuvenc)
-    endif()
-    if(CUDA_nvcuvid_LIBRARY AND (${HAVE_NVCUVID_HEADER} OR ${HAVE_DYNLINK_NVCUVID_HEADER}))
-      # make sure to have both header and library before enabling
-      set(HAVE_NVCUVID 1)
+    if(WITH_NVCUVID)
+      ocv_cuda_SEARCH_NVCUVID_HEADER("nvcuvid.h" HAVE_NVCUVID_HEADER)
+      ocv_cuda_SEARCH_NVCUVID_HEADER("dynlink_nvcuvid.h" HAVE_DYNLINK_NVCUVID_HEADER)
+      find_cuda_helper_libs(nvcuvid)
+      if(CUDA_nvcuvid_LIBRARY AND (${HAVE_NVCUVID_HEADER} OR ${HAVE_DYNLINK_NVCUVID_HEADER}))
+        # make sure to have both header and library before enabling
+        set(HAVE_NVCUVID 1)
+      endif()
     endif()
-    if(CUDA_nvcuvenc_LIBRARY)
-      set(HAVE_NVCUVENC 1)
+    if(WITH_NVCUVENC)
+      ocv_cuda_SEARCH_NVCUVID_HEADER("nvEncodeAPI.h" HAVE_NVCUVENC_HEADER)
+      if(WIN32)
+        find_cuda_helper_libs(nvencodeapi)
+      else()
+        find_cuda_helper_libs(nvidia-encode)
+      endif()
+      if((CUDA_nvencodeapi_LIBRARY OR CUDA_nvidia-encode_LIBRARY) AND ${HAVE_NVCUVENC_HEADER})
+        set(HAVE_NVCUVENC 1)
+      endif()
     endif()
   endif()
 
index e71c9e2e31127cd7b450b42261a54bf442b1b52b..25a20556ec4a823b78647d96f6923373360e6202 100644 (file)
@@ -5,7 +5,7 @@ set(OpenCV_CUDA_VERSION "@CUDA_VERSION_STRING@")
 set(OpenCV_USE_CUBLAS   "@HAVE_CUBLAS@")
 set(OpenCV_USE_CUFFT    "@HAVE_CUFFT@")
 set(OpenCV_USE_NVCUVID  "@HAVE_NVCUVID@")
-
+set(OpenCV_USE_NVCUVENC "@HAVE_NVCUVENC@")
 set(OpenCV_CUDNN_VERSION    "@CUDNN_VERSION@")
 set(OpenCV_USE_CUDNN        "@HAVE_CUDNN@")
 
@@ -36,14 +36,6 @@ if(OpenCV_USE_CUFFT)
   list(APPEND OpenCV_CUDA_LIBS_ABSPATH ${CUDA_CUFFT_LIBRARIES})
 endif()
 
-if(OpenCV_USE_NVCUVID)
-  list(APPEND OpenCV_CUDA_LIBS_ABSPATH ${CUDA_nvcuvid_LIBRARIES})
-endif()
-
-if(WIN32)
-  list(APPEND OpenCV_CUDA_LIBS_ABSPATH ${CUDA_nvcuvenc_LIBRARIES})
-endif()
-
 set(OpenCV_CUDA_LIBS_RELPATH "")
 foreach(l ${OpenCV_CUDA_LIBS_ABSPATH})
   get_filename_component(_tmp ${l} PATH)
index ea141c3b1a5b69ce29f9f9deb70926c31fae813b..e8a738f905c347dcd08095479a8335d3ba7ff71d 100644 (file)
@@ -22,65 +22,41 @@ int main(int argc, const char* argv[])
     const std::string fname(argv[1]);
 
     cv::namedWindow("CPU", cv::WINDOW_NORMAL);
+#if defined(HAVE_OPENGL)
     cv::namedWindow("GPU", cv::WINDOW_OPENGL);
     cv::cuda::setGlDevice();
+#else
+    cv::namedWindow("GPU", cv::WINDOW_NORMAL);
+#endif
 
+    cv::TickMeter tm;
     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;
     }
 
+    cv::cuda::GpuMat d_frame;
+    cv::Ptr<cv::cudacodec::VideoReader> d_reader = cv::cudacodec::createVideoReader(fname);
     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 defined(HAVE_OPENGL)
+        cv::imshow("GPU", cv::ogl::Texture2D(d_frame));
+#else
+        d_frame.download(frame);
+        cv::imshow("GPU", frame);
+#endif
         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;
 }
 
index fa1d709c09a1fb6c188703287777e7dda19fbaf3..02b17700fc6e869278c3f68a0fd295cac468b74f 100644 (file)
@@ -2,7 +2,7 @@
 
 #include "opencv2/opencv_modules.hpp"
 
-#if defined(HAVE_OPENCV_CUDACODEC) && defined(_WIN32)
+#if defined(HAVE_OPENCV_CUDACODEC)
 
 #include <vector>
 #include <numeric>
@@ -20,7 +20,7 @@ int main(int argc, const char* argv[])
         return -1;
     }
 
-    const double FPS = 25.0;
+    constexpr double fps = 25.0;
 
     cv::VideoCapture reader(argv[1]);
 
@@ -37,17 +37,12 @@ int main(int argc, const char* argv[])
 
     cv::Mat frame;
     cv::cuda::GpuMat d_frame;
-
-    std::vector<double> cpu_times;
-    std::vector<double> gpu_times;
-    TickMeter tm;
+    cv::cuda::Stream stream;
 
     for (int i = 1;; ++i)
     {
         std::cout << "Read " << i << " frame" << std::endl;
-
         reader >> frame;
-
         if (frame.empty())
         {
             std::cout << "Stop" << std::endl;
@@ -57,47 +52,27 @@ int main(int argc, const char* argv[])
         if (!writer.isOpened())
         {
             std::cout << "Frame Size : " << frame.cols << "x" << frame.rows << std::endl;
-
             std::cout << "Open CPU Writer" << std::endl;
-
-            if (!writer.open("output_cpu.avi", cv::VideoWriter::fourcc('X', 'V', 'I', 'D'), FPS, frame.size()))
+            const String outputFilename = "output_cpu.avi";
+            if (!writer.open(outputFilename, cv::VideoWriter::fourcc('X', 'V', 'I', 'D'), fps, frame.size()))
                 return -1;
+            std::cout << "Writing to " << outputFilename << std::endl;
         }
 
         if (d_writer.empty())
         {
             std::cout << "Open CUDA Writer" << std::endl;
-
-            const cv::String outputFilename = "output_gpu.avi";
-            d_writer = cv::cudacodec::createVideoWriter(outputFilename, frame.size(), FPS);
+            const cv::String outputFilename = "output_gpu.h264";
+            d_writer = cv::cudacodec::createVideoWriter(outputFilename, frame.size(), cv::cudacodec::Codec::H264, fps, cv::cudacodec::ColorFormat::BGR, 0, stream);
+            std::cout << "Writing to " << outputFilename << std::endl;
         }
 
-        d_frame.upload(frame);
-
+        d_frame.upload(frame, stream);
         std::cout << "Write " << i << " frame" << std::endl;
-
-        tm.reset(); tm.start();
         writer.write(frame);
-        tm.stop();
-        cpu_times.push_back(tm.getTimeMilli());
-
-        tm.reset(); tm.start();
         d_writer->write(d_frame);
-        tm.stop();
-        gpu_times.push_back(tm.getTimeMilli());
     }
 
-    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 [XVID] : Avg : " << cpu_avg << " ms FPS : " << 1000.0 / cpu_avg << std::endl;
-    std::cout << "GPU [H264] : Avg : " << gpu_avg << " ms FPS : " << 1000.0 / gpu_avg << std::endl;
-
     return 0;
 }