test_video.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. /*M///////////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
  4. //
  5. // By downloading, copying, installing or using the software you agree to this license.
  6. // If you do not agree to this license, do not download, install,
  7. // copy or use the software.
  8. //
  9. //
  10. // License Agreement
  11. // For Open Source Computer Vision Library
  12. //
  13. // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
  14. // Copyright (C) 2009, Willow Garage Inc., all rights reserved.
  15. // Third party copyrights are property of their respective owners.
  16. //
  17. // Redistribution and use in source and binary forms, with or without modification,
  18. // are permitted provided that the following conditions are met:
  19. //
  20. // * Redistribution's of source code must retain the above copyright notice,
  21. // this list of conditions and the following disclaimer.
  22. //
  23. // * Redistribution's in binary form must reproduce the above copyright notice,
  24. // this list of conditions and the following disclaimer in the documentation
  25. // and/or other materials provided with the distribution.
  26. //
  27. // * The name of the copyright holders may not be used to endorse or promote products
  28. // derived from this software without specific prior written permission.
  29. //
  30. // This software is provided by the copyright holders and contributors "as is" and
  31. // any express or implied warranties, including, but not limited to, the implied
  32. // warranties of merchantability and fitness for a particular purpose are disclaimed.
  33. // In no event shall the Intel Corporation or contributors be liable for any direct,
  34. // indirect, incidental, special, exemplary, or consequential damages
  35. // (including, but not limited to, procurement of substitute goods or services;
  36. // loss of use, data, or profits; or business interruption) however caused
  37. // and on any theory of liability, whether in contract, strict liability,
  38. // or tort (including negligence or otherwise) arising in any way out of
  39. // the use of this software, even if advised of the possibility of such damage.
  40. //
  41. //M*/
  42. #include "test_precomp.hpp"
  43. namespace opencv_test {
  44. namespace {
  45. #if defined(HAVE_NVCUVID) || defined(HAVE_NVCUVENC)
  46. PARAM_TEST_CASE(CheckSet, cv::cuda::DeviceInfo, std::string)
  47. {
  48. };
  49. typedef tuple<std::string, int> check_extra_data_params_t;
  50. PARAM_TEST_CASE(CheckExtraData, cv::cuda::DeviceInfo, check_extra_data_params_t)
  51. {
  52. };
  53. PARAM_TEST_CASE(Video, cv::cuda::DeviceInfo, std::string)
  54. {
  55. };
  56. PARAM_TEST_CASE(VideoReadRaw, cv::cuda::DeviceInfo, std::string)
  57. {
  58. };
  59. PARAM_TEST_CASE(CheckKeyFrame, cv::cuda::DeviceInfo, std::string)
  60. {
  61. };
  62. struct CheckParams : testing::TestWithParam<cv::cuda::DeviceInfo>
  63. {
  64. cv::cuda::DeviceInfo devInfo;
  65. virtual void SetUp()
  66. {
  67. devInfo = GetParam();
  68. cv::cuda::setDevice(devInfo.deviceID());
  69. }
  70. };
  71. #if defined(HAVE_NVCUVID)
  72. //////////////////////////////////////////////////////
  73. // VideoReader
  74. //==========================================================================
  75. CUDA_TEST_P(CheckSet, Reader)
  76. {
  77. cv::cuda::setDevice(GET_PARAM(0).deviceID());
  78. if (!videoio_registry::hasBackend(CAP_FFMPEG))
  79. throw SkipTestException("FFmpeg backend was not found");
  80. std::string inputFile = std::string(cvtest::TS::ptr()->get_data_path()) + +"../" + GET_PARAM(1);
  81. cv::Ptr<cv::cudacodec::VideoReader> reader = cv::cudacodec::createVideoReader(inputFile);
  82. double unsupportedVal = -1;
  83. ASSERT_FALSE(reader->get(cv::cudacodec::VideoReaderProps::PROP_NOT_SUPPORTED, unsupportedVal));
  84. double rawModeVal = -1;
  85. ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_RAW_MODE, rawModeVal));
  86. ASSERT_FALSE(rawModeVal);
  87. ASSERT_TRUE(reader->set(cv::cudacodec::VideoReaderProps::PROP_RAW_MODE,true));
  88. ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_RAW_MODE, rawModeVal));
  89. ASSERT_TRUE(rawModeVal);
  90. bool rawPacketsAvailable = false;
  91. while (reader->grab()) {
  92. double nRawPackages = -1;
  93. ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_NUMBER_OF_RAW_PACKAGES_SINCE_LAST_GRAB, nRawPackages));
  94. if (nRawPackages > 0) {
  95. rawPacketsAvailable = true;
  96. break;
  97. }
  98. }
  99. ASSERT_TRUE(rawPacketsAvailable);
  100. }
  101. CUDA_TEST_P(CheckExtraData, Reader)
  102. {
  103. // RTSP streaming is only supported by the FFmpeg back end
  104. if (!videoio_registry::hasBackend(CAP_FFMPEG))
  105. throw SkipTestException("FFmpeg backend not found");
  106. cv::cuda::setDevice(GET_PARAM(0).deviceID());
  107. const string path = get<0>(GET_PARAM(1));
  108. const int sz = get<1>(GET_PARAM(1));
  109. std::string inputFile = std::string(cvtest::TS::ptr()->get_data_path()) + "../" + path;
  110. cv::Ptr<cv::cudacodec::VideoReader> reader = cv::cudacodec::createVideoReader(inputFile, {}, true);
  111. double rawModeVal = -1;
  112. ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_RAW_MODE, rawModeVal));
  113. ASSERT_TRUE(rawModeVal);
  114. double extraDataIdx = -1;
  115. ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_EXTRA_DATA_INDEX, extraDataIdx));
  116. ASSERT_EQ(extraDataIdx, 1 );
  117. ASSERT_TRUE(reader->grab());
  118. cv::Mat extraData;
  119. const bool newData = reader->retrieve(extraData, extraDataIdx);
  120. ASSERT_TRUE(newData && sz || !newData && !sz);
  121. ASSERT_EQ(extraData.total(), sz);
  122. }
  123. CUDA_TEST_P(CheckKeyFrame, Reader)
  124. {
  125. cv::cuda::setDevice(GET_PARAM(0).deviceID());
  126. // RTSP streaming is only supported by the FFmpeg back end
  127. if (!videoio_registry::hasBackend(CAP_FFMPEG))
  128. throw SkipTestException("FFmpeg backend not found");
  129. const string path = GET_PARAM(1);
  130. std::string inputFile = std::string(cvtest::TS::ptr()->get_data_path()) + "../" + path;
  131. cv::Ptr<cv::cudacodec::VideoReader> reader = cv::cudacodec::createVideoReader(inputFile, {}, true);
  132. double rawModeVal = -1;
  133. ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_RAW_MODE, rawModeVal));
  134. ASSERT_TRUE(rawModeVal);
  135. double rawIdxBase = -1;
  136. ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_RAW_PACKAGES_BASE_INDEX, rawIdxBase));
  137. ASSERT_EQ(rawIdxBase, 2);
  138. constexpr int maxNPackagesToCheck = 2;
  139. int nPackages = 0;
  140. while (nPackages < maxNPackagesToCheck) {
  141. ASSERT_TRUE(reader->grab());
  142. double N = -1;
  143. ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_NUMBER_OF_RAW_PACKAGES_SINCE_LAST_GRAB,N));
  144. for (int i = rawIdxBase; i < N + rawIdxBase; i++) {
  145. nPackages++;
  146. double containsKeyFrame = i;
  147. ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_LRF_HAS_KEY_FRAME, containsKeyFrame));
  148. ASSERT_TRUE(nPackages == 1 && containsKeyFrame || nPackages == 2 && !containsKeyFrame) << "nPackage: " << i;
  149. if (nPackages >= maxNPackagesToCheck)
  150. break;
  151. }
  152. }
  153. }
  154. CUDA_TEST_P(Video, Reader)
  155. {
  156. cv::cuda::setDevice(GET_PARAM(0).deviceID());
  157. // CUDA demuxer has to fall back to ffmpeg to process "cv/video/768x576.avi"
  158. if (GET_PARAM(1) == "cv/video/768x576.avi" && !videoio_registry::hasBackend(CAP_FFMPEG))
  159. throw SkipTestException("FFmpeg backend not found");
  160. std::string inputFile = std::string(cvtest::TS::ptr()->get_data_path()) + "../" + GET_PARAM(1);
  161. cv::Ptr<cv::cudacodec::VideoReader> reader = cv::cudacodec::createVideoReader(inputFile);
  162. cv::cudacodec::FormatInfo fmt = reader->format();
  163. cv::cuda::GpuMat frame;
  164. for (int i = 0; i < 100; i++)
  165. {
  166. ASSERT_TRUE(reader->nextFrame(frame));
  167. if(!fmt.valid)
  168. fmt = reader->format();
  169. ASSERT_TRUE(frame.cols == fmt.width && frame.rows == fmt.height);
  170. ASSERT_FALSE(frame.empty());
  171. }
  172. }
  173. CUDA_TEST_P(VideoReadRaw, Reader)
  174. {
  175. cv::cuda::setDevice(GET_PARAM(0).deviceID());
  176. // RTSP streaming is only supported by the FFmpeg back end
  177. if (!videoio_registry::hasBackend(CAP_FFMPEG))
  178. throw SkipTestException("FFmpeg backend not found");
  179. std::string inputFile = std::string(cvtest::TS::ptr()->get_data_path()) + "../" + GET_PARAM(1);
  180. const string fileNameOut = tempfile("test_container_stream");
  181. {
  182. std::ofstream file(fileNameOut, std::ios::binary);
  183. ASSERT_TRUE(file.is_open());
  184. cv::Ptr<cv::cudacodec::VideoReader> reader = cv::cudacodec::createVideoReader(inputFile, {}, true);
  185. double rawModeVal = -1;
  186. ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_RAW_MODE, rawModeVal));
  187. ASSERT_TRUE(rawModeVal);
  188. double rawIdxBase = -1;
  189. ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_RAW_PACKAGES_BASE_INDEX, rawIdxBase));
  190. ASSERT_EQ(rawIdxBase, 2);
  191. cv::cuda::GpuMat frame;
  192. for (int i = 0; i < 100; i++)
  193. {
  194. ASSERT_TRUE(reader->grab());
  195. ASSERT_TRUE(reader->retrieve(frame));
  196. ASSERT_FALSE(frame.empty());
  197. double N = -1;
  198. ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_NUMBER_OF_RAW_PACKAGES_SINCE_LAST_GRAB,N));
  199. ASSERT_TRUE(N >= 0) << N << " < 0";
  200. for (int i = rawIdxBase; i <= N + rawIdxBase; i++) {
  201. Mat rawPackets;
  202. reader->retrieve(rawPackets, i);
  203. file.write((char*)rawPackets.data, rawPackets.total());
  204. }
  205. }
  206. }
  207. std::cout << "Checking written video stream: " << fileNameOut << std::endl;
  208. {
  209. cv::Ptr<cv::cudacodec::VideoReader> readerReference = cv::cudacodec::createVideoReader(inputFile);
  210. cv::Ptr<cv::cudacodec::VideoReader> readerActual = cv::cudacodec::createVideoReader(fileNameOut, {}, true);
  211. double decodedFrameIdx = -1;
  212. ASSERT_TRUE(readerActual->get(cv::cudacodec::VideoReaderProps::PROP_DECODED_FRAME_IDX, decodedFrameIdx));
  213. ASSERT_EQ(decodedFrameIdx, 0);
  214. cv::cuda::GpuMat reference, actual;
  215. cv::Mat referenceHost, actualHost;
  216. for (int i = 0; i < 100; i++)
  217. {
  218. ASSERT_TRUE(readerReference->nextFrame(reference));
  219. ASSERT_TRUE(readerActual->grab());
  220. ASSERT_TRUE(readerActual->retrieve(actual, decodedFrameIdx));
  221. actual.download(actualHost);
  222. reference.download(referenceHost);
  223. ASSERT_TRUE(cvtest::norm(actualHost, referenceHost, NORM_INF) == 0);
  224. }
  225. }
  226. ASSERT_EQ(0, remove(fileNameOut.c_str()));
  227. }
  228. CUDA_TEST_P(CheckParams, Reader)
  229. {
  230. std::string inputFile = std::string(cvtest::TS::ptr()->get_data_path()) + "../highgui/video/big_buck_bunny.mp4";
  231. {
  232. cv::Ptr<cv::cudacodec::VideoReader> reader = cv::cudacodec::createVideoReader(inputFile);
  233. double msActual = -1;
  234. ASSERT_FALSE(reader->get(cv::VideoCaptureProperties::CAP_PROP_OPEN_TIMEOUT_MSEC, msActual));
  235. }
  236. {
  237. constexpr int msReference = 3333;
  238. cv::Ptr<cv::cudacodec::VideoReader> reader = cv::cudacodec::createVideoReader(inputFile, {
  239. cv::VideoCaptureProperties::CAP_PROP_OPEN_TIMEOUT_MSEC, msReference });
  240. double msActual = -1;
  241. ASSERT_TRUE(reader->get(cv::VideoCaptureProperties::CAP_PROP_OPEN_TIMEOUT_MSEC, msActual));
  242. ASSERT_EQ(msActual, msReference);
  243. }
  244. {
  245. std::vector<bool> exceptionsThrown = { false,true };
  246. std::vector<int> capPropFormats = { -1,0 };
  247. for (int i = 0; i < capPropFormats.size(); i++) {
  248. bool exceptionThrown = false;
  249. try {
  250. cv::Ptr<cv::cudacodec::VideoReader> reader = cv::cudacodec::createVideoReader(inputFile, {
  251. cv::VideoCaptureProperties::CAP_PROP_FORMAT, capPropFormats.at(i) });
  252. }
  253. catch (cv::Exception ex) {
  254. if (ex.code == Error::StsUnsupportedFormat)
  255. exceptionThrown = true;
  256. }
  257. ASSERT_EQ(exceptionThrown, exceptionsThrown.at(i));
  258. }
  259. }
  260. }
  261. #endif // HAVE_NVCUVID
  262. #if defined(_WIN32) && defined(HAVE_NVCUVENC)
  263. //////////////////////////////////////////////////////
  264. // VideoWriter
  265. CUDA_TEST_P(Video, Writer)
  266. {
  267. cv::cuda::setDevice(GET_PARAM(0).deviceID());
  268. const std::string inputFile = std::string(cvtest::TS::ptr()->get_data_path()) + "video/" + GET_PARAM(1);
  269. std::string outputFile = cv::tempfile(".avi");
  270. const double FPS = 25.0;
  271. cv::VideoCapture reader(inputFile);
  272. ASSERT_TRUE(reader.isOpened());
  273. cv::Ptr<cv::cudacodec::VideoWriter> d_writer;
  274. cv::Mat frame;
  275. cv::cuda::GpuMat d_frame;
  276. for (int i = 0; i < 10; ++i)
  277. {
  278. reader >> frame;
  279. ASSERT_FALSE(frame.empty());
  280. d_frame.upload(frame);
  281. if (d_writer.empty())
  282. d_writer = cv::cudacodec::createVideoWriter(outputFile, frame.size(), FPS);
  283. d_writer->write(d_frame);
  284. }
  285. reader.release();
  286. d_writer.release();
  287. reader.open(outputFile);
  288. ASSERT_TRUE(reader.isOpened());
  289. for (int i = 0; i < 5; ++i)
  290. {
  291. reader >> frame;
  292. ASSERT_FALSE(frame.empty());
  293. }
  294. }
  295. #endif // _WIN32, HAVE_NVCUVENC
  296. INSTANTIATE_TEST_CASE_P(CUDA_Codec, CheckSet, testing::Combine(
  297. ALL_DEVICES,
  298. testing::Values("highgui/video/big_buck_bunny.mp4")));
  299. #define VIDEO_SRC_R "highgui/video/big_buck_bunny.mp4", "cv/video/768x576.avi", "cv/video/1920x1080.avi", "highgui/video/big_buck_bunny.avi", \
  300. "highgui/video/big_buck_bunny.h264", "highgui/video/big_buck_bunny.h265", "highgui/video/big_buck_bunny.mpg"
  301. INSTANTIATE_TEST_CASE_P(CUDA_Codec, Video, testing::Combine(
  302. ALL_DEVICES,
  303. testing::Values(VIDEO_SRC_R)));
  304. #define VIDEO_SRC_RW "highgui/video/big_buck_bunny.h264", "highgui/video/big_buck_bunny.h265"
  305. INSTANTIATE_TEST_CASE_P(CUDA_Codec, VideoReadRaw, testing::Combine(
  306. ALL_DEVICES,
  307. testing::Values(VIDEO_SRC_RW)));
  308. const check_extra_data_params_t check_extra_data_params[] =
  309. {
  310. check_extra_data_params_t("highgui/video/big_buck_bunny.mp4", 45),
  311. check_extra_data_params_t("highgui/video/big_buck_bunny.mov", 45),
  312. check_extra_data_params_t("highgui/video/big_buck_bunny.mjpg.avi", 0)
  313. };
  314. INSTANTIATE_TEST_CASE_P(CUDA_Codec, CheckExtraData, testing::Combine(
  315. ALL_DEVICES,
  316. testing::ValuesIn(check_extra_data_params)));
  317. INSTANTIATE_TEST_CASE_P(CUDA_Codec, CheckKeyFrame, testing::Combine(
  318. ALL_DEVICES,
  319. testing::Values(VIDEO_SRC_R)));
  320. INSTANTIATE_TEST_CASE_P(CUDA_Codec, CheckParams, ALL_DEVICES);
  321. #endif // HAVE_NVCUVID || HAVE_NVCUVENC
  322. }} // namespace