From 736fe2aa246e81269cbcab6688ebc0a532a85288 Mon Sep 17 00:00:00 2001 From: James Bowley Date: Tue, 11 Jun 2019 09:57:20 +0100 Subject: [PATCH 1/5] Add missing codecs to cudacodec which uses Nvidia Video Codec SDK including checks to ensure codec used in input video file is supported on the current device. --- .../cudacodec/include/opencv2/cudacodec.hpp | 4 ++ modules/cudacodec/src/cuvid_video_source.cpp | 1 + modules/cudacodec/src/video_decoder.cpp | 41 ++++++++++++++----- 3 files changed, 35 insertions(+), 11 deletions(-) diff --git a/modules/cudacodec/include/opencv2/cudacodec.hpp b/modules/cudacodec/include/opencv2/cudacodec.hpp index e404a48ce9..dd8ae20007 100644 --- a/modules/cudacodec/include/opencv2/cudacodec.hpp +++ b/modules/cudacodec/include/opencv2/cudacodec.hpp @@ -250,6 +250,9 @@ enum Codec JPEG, H264_SVC, H264_MVC, + HEVC, + VP8, + VP9, Uncompressed_YUV420 = (('I'<<24)|('Y'<<16)|('U'<<8)|('V')), //!< Y,U,V (4:2:0) Uncompressed_YV12 = (('Y'<<24)|('V'<<16)|('1'<<8)|('2')), //!< Y,V,U (4:2:0) @@ -274,6 +277,7 @@ struct FormatInfo { Codec codec; ChromaFormat chromaFormat; + int nBitDepthMinus8; int width; int height; }; diff --git a/modules/cudacodec/src/cuvid_video_source.cpp b/modules/cudacodec/src/cuvid_video_source.cpp index fd6eac72de..75366a0f7a 100644 --- a/modules/cudacodec/src/cuvid_video_source.cpp +++ b/modules/cudacodec/src/cuvid_video_source.cpp @@ -70,6 +70,7 @@ cv::cudacodec::detail::CuvidVideoSource::CuvidVideoSource(const String& fname) format_.codec = static_cast(vidfmt.codec); format_.chromaFormat = static_cast(vidfmt.chroma_format); + format_.nBitDepthMinus8 = vidfmt.bit_depth_luma_minus8; format_.width = vidfmt.coded_width; format_.height = vidfmt.coded_height; } diff --git a/modules/cudacodec/src/video_decoder.cpp b/modules/cudacodec/src/video_decoder.cpp index 35919c3f56..ec508eac00 100644 --- a/modules/cudacodec/src/video_decoder.cpp +++ b/modules/cudacodec/src/video_decoder.cpp @@ -57,23 +57,42 @@ void cv::cudacodec::detail::VideoDecoder::create(const FormatInfo& videoFormat) cudaVideoCreate_PreferCUVID; // Validate video format. These are the currently supported formats via NVCUVID - CV_Assert(cudaVideoCodec_MPEG1 == _codec || - cudaVideoCodec_MPEG2 == _codec || - cudaVideoCodec_MPEG4 == _codec || - cudaVideoCodec_VC1 == _codec || - cudaVideoCodec_H264 == _codec || - cudaVideoCodec_JPEG == _codec || - cudaVideoCodec_YUV420== _codec || - cudaVideoCodec_YV12 == _codec || - cudaVideoCodec_NV12 == _codec || - cudaVideoCodec_YUYV == _codec || - cudaVideoCodec_UYVY == _codec ); + CV_Assert( cudaVideoCodec_MPEG1 == _codec || + cudaVideoCodec_MPEG2 == _codec || + cudaVideoCodec_MPEG4 == _codec || + cudaVideoCodec_VC1 == _codec || + cudaVideoCodec_H264 == _codec || + cudaVideoCodec_JPEG == _codec || + cudaVideoCodec_H264_SVC == _codec || + cudaVideoCodec_H264_MVC == _codec || + cudaVideoCodec_HEVC == _codec || + cudaVideoCodec_VP8 == _codec || + cudaVideoCodec_VP9 == _codec || + cudaVideoCodec_YUV420 == _codec || + cudaVideoCodec_YV12 == _codec || + cudaVideoCodec_NV12 == _codec || + cudaVideoCodec_YUYV == _codec || + cudaVideoCodec_UYVY == _codec); CV_Assert(cudaVideoChromaFormat_Monochrome == _chromaFormat || cudaVideoChromaFormat_420 == _chromaFormat || cudaVideoChromaFormat_422 == _chromaFormat || cudaVideoChromaFormat_444 == _chromaFormat); + // Check video format is supported by GPU's hardware video decoder + CUVIDDECODECAPS decodeCaps = {}; + decodeCaps.eCodecType = _codec; + decodeCaps.eChromaFormat = _chromaFormat; + decodeCaps.nBitDepthMinus8 = videoFormat.nBitDepthMinus8; + cuSafeCall(cuvidGetDecoderCaps(&decodeCaps)); + if (!decodeCaps.bIsSupported) + CV_Error(Error::StsUnsupportedFormat, "Video source is not supported by hardware video decoder"); + + CV_Assert(videoFormat.width >= decodeCaps.nMinWidth && + videoFormat.height >= decodeCaps.nMinHeight && + videoFormat.width <= decodeCaps.nMaxWidth && + videoFormat.height <= decodeCaps.nMaxHeight); + // Fill the decoder-create-info struct from the given video-format struct. std::memset(&createInfo_, 0, sizeof(CUVIDDECODECREATEINFO)); From ea2a4f715f956237a18d70394986fb954e84c62d Mon Sep 17 00:00:00 2001 From: cudawarped Date: Fri, 24 Dec 2021 11:20:39 +0000 Subject: [PATCH 2/5] Allow VideoCaptureProperties to be passed to VideoCapture on initialization. Include test for VideoReader but not for VideoCapture, assume pass through successful. Use propertyId instead of c++ keyword property. Remove unecessary error checks (parsers error is dependant on source) and output more informative exception. --- .../cudacodec/include/opencv2/cudacodec.hpp | 24 +++++- modules/cudacodec/src/ffmpeg_video_source.cpp | 16 +++- modules/cudacodec/src/ffmpeg_video_source.hpp | 5 +- modules/cudacodec/src/video_reader.cpp | 30 ++++--- modules/cudacodec/src/video_source.cpp | 5 ++ modules/cudacodec/src/video_source.hpp | 2 + modules/cudacodec/test/test_video.cpp | 78 ++++++++++++------- 7 files changed, 113 insertions(+), 47 deletions(-) diff --git a/modules/cudacodec/include/opencv2/cudacodec.hpp b/modules/cudacodec/include/opencv2/cudacodec.hpp index 7b8678df81..829153d00b 100644 --- a/modules/cudacodec/include/opencv2/cudacodec.hpp +++ b/modules/cudacodec/include/opencv2/cudacodec.hpp @@ -373,7 +373,7 @@ class CV_EXPORTS_W VideoReader @param propertyVal Value of the property. @return `true` if the property has been set. */ - CV_WRAP virtual bool set(const VideoReaderProps property, const double propertyVal) = 0; + CV_WRAP virtual bool set(const VideoReaderProps propertyId, const double propertyVal) = 0; /** @brief Returns the specified VideoReader property @@ -381,7 +381,16 @@ class CV_EXPORTS_W VideoReader @param propertyVal Optional value for the property. @return Value for the specified property. Value -1 is returned when querying a property that is not supported. */ - CV_WRAP virtual int get(const VideoReaderProps property, const int propertyVal = -1) const = 0; + CV_WRAP virtual int get(const VideoReaderProps propertyId, const int propertyVal = -1) const = 0; + + /** @brief Returns the specified property used by the VideoSource. + + @param propId Property identifier from cv::VideoCaptureProperties (eg. cv::CAP_PROP_POS_MSEC, cv::CAP_PROP_POS_FRAMES, ...) + or one from @ref videoio_flags_others + @return Value for the specified property. Value 0 is returned when querying a property that is + not supported. + */ + CV_WRAP virtual double get(const int propertyId) const = 0; }; /** @brief Interface for video demultiplexing. : @@ -417,6 +426,15 @@ class CV_EXPORTS_W RawVideoSource @param extraData 1D cv::Mat containing the extra data if it exists. */ virtual void getExtraData(cv::Mat& extraData) const = 0; + + /** @brief Returns the specified property used by the VideoSource. + + @param propId Property identifier from cv::VideoCaptureProperties (eg. cv::CAP_PROP_POS_MSEC, cv::CAP_PROP_POS_FRAMES, ...) + or one from @ref videoio_flags_others + @return Value for the specified property. Value 0 is returned when querying a property that is + not supported. + */ + virtual double get(const int propId) const = 0; }; /** @brief Creates video reader. @@ -426,7 +444,7 @@ class CV_EXPORTS_W RawVideoSource FFMPEG is used to read videos. User can implement own demultiplexing with cudacodec::RawVideoSource */ -CV_EXPORTS_W Ptr createVideoReader(const String& filename, const bool rawMode = false); +CV_EXPORTS_W Ptr createVideoReader(const String& filename, const std::vector& params = {}, const bool rawMode = false); /** @overload @param source RAW video source implemented by user. diff --git a/modules/cudacodec/src/ffmpeg_video_source.cpp b/modules/cudacodec/src/ffmpeg_video_source.cpp index 4efbe775a0..96574fa451 100644 --- a/modules/cudacodec/src/ffmpeg_video_source.cpp +++ b/modules/cudacodec/src/ffmpeg_video_source.cpp @@ -113,6 +113,7 @@ void FourccToChromaFormat(const int pixelFormat, ChromaFormat &chromaFormat, int } } +static int StartCodeLen(unsigned char* data, const int sz) { if (sz >= 3 && data[0] == 0 && data[1] == 0 && data[2] == 1) return 3; @@ -129,12 +130,13 @@ bool ParamSetsExist(unsigned char* parameterSets, const int szParameterSets, uns return paramSetStartCodeLen != 0 && packetStartCodeLen != 0 && parameterSets[paramSetStartCodeLen] == data[packetStartCodeLen]; } -cv::cudacodec::detail::FFmpegVideoSource::FFmpegVideoSource(const String& fname) +cv::cudacodec::detail::FFmpegVideoSource::FFmpegVideoSource(const String& fname, const std::vector& _videoCaptureParams) + : videoCaptureParams(_videoCaptureParams) { if (!videoio_registry::hasBackend(CAP_FFMPEG)) CV_Error(Error::StsNotImplemented, "FFmpeg backend not found"); - cap.open(fname, CAP_FFMPEG); + cap.open(fname, CAP_FFMPEG, videoCaptureParams); if (!cap.isOpened()) CV_Error(Error::StsUnsupportedFormat, "Unsupported video source"); @@ -176,6 +178,16 @@ void cv::cudacodec::detail::FFmpegVideoSource::updateFormat(const FormatInfo& vi format_.valid = true; } +double cv::cudacodec::detail::FFmpegVideoSource::get(const int propId) const +{ + if (videoCaptureParams.size() % 2 != 0) return 0; + for (std::size_t i = 0; i < videoCaptureParams.size(); i += 2) { + if (videoCaptureParams.at(i) == propId) + return videoCaptureParams.at(i + 1); + } + return 0; +} + bool cv::cudacodec::detail::FFmpegVideoSource::getNextPacket(unsigned char** data, size_t* size) { cap >> rawFrame; diff --git a/modules/cudacodec/src/ffmpeg_video_source.hpp b/modules/cudacodec/src/ffmpeg_video_source.hpp index e8346331e4..a5a46d96f5 100644 --- a/modules/cudacodec/src/ffmpeg_video_source.hpp +++ b/modules/cudacodec/src/ffmpeg_video_source.hpp @@ -51,7 +51,7 @@ namespace cv { namespace cudacodec { namespace detail { class FFmpegVideoSource : public RawVideoSource { public: - FFmpegVideoSource(const String& fname); + FFmpegVideoSource(const String& fname, const std::vector& params); ~FFmpegVideoSource(); bool getNextPacket(unsigned char** data, size_t* size) CV_OVERRIDE; @@ -64,11 +64,14 @@ class FFmpegVideoSource : public RawVideoSource void getExtraData(cv::Mat& _extraData) const CV_OVERRIDE { _extraData = extraData; } + double get(const int propId) const; + private: FormatInfo format_; VideoCapture cap; Mat rawFrame, extraData, dataWithHeader; int iFrame = 0; + std::vector videoCaptureParams; }; }}} diff --git a/modules/cudacodec/src/video_reader.cpp b/modules/cudacodec/src/video_reader.cpp index 49884f17b2..3f068da17e 100644 --- a/modules/cudacodec/src/video_reader.cpp +++ b/modules/cudacodec/src/video_reader.cpp @@ -73,9 +73,11 @@ namespace bool retrieve(OutputArray frame, const size_t idx) const CV_OVERRIDE; - bool set(const VideoReaderProps property, const double propertyVal) CV_OVERRIDE; + bool set(const VideoReaderProps propertyId, const double propertyVal) CV_OVERRIDE; - int get(const VideoReaderProps property, const int propertyVal) const CV_OVERRIDE; + int get(const VideoReaderProps propertyId, const int propertyVal) const CV_OVERRIDE; + + double get(const int propertyId) const CV_OVERRIDE; private: bool internalGrab(GpuMat& frame, Stream& stream); @@ -136,8 +138,8 @@ namespace }; bool VideoReaderImpl::internalGrab(GpuMat& frame, Stream& stream) { - if (videoSource_->hasError() || videoParser_->hasError()) - CV_Error(Error::StsUnsupportedFormat, "Unsupported video source"); + if (videoParser_->hasError()) + CV_Error(Error::StsError, "Parsing/Decoding video source failed, check GPU memory is available and GPU supports hardware decoding."); if (frames_.empty()) { @@ -148,8 +150,8 @@ namespace if (frameQueue_->dequeue(displayInfo, rawPackets)) break; - if (videoSource_->hasError() || videoParser_->hasError()) - CV_Error(Error::StsUnsupportedFormat, "Unsupported video source"); + if (videoParser_->hasError()) + CV_Error(Error::StsError, "Parsing/Decoding video source failed, check GPU memory is available and GPU supports hardware decoding."); if (frameQueue_->isEndOfDecode()) return false; @@ -231,8 +233,8 @@ namespace return !frame.empty(); } - bool VideoReaderImpl::set(const VideoReaderProps property, const double propertyVal) { - switch (property) { + bool VideoReaderImpl::set(const VideoReaderProps propertyId, const double propertyVal) { + switch (propertyId) { case VideoReaderProps::PROP_RAW_MODE : videoSource_->SetRawMode(static_cast(propertyVal)); break; @@ -240,8 +242,8 @@ namespace return true; } - int VideoReaderImpl::get(const VideoReaderProps property, const int propertyVal) const { - switch (property) + int VideoReaderImpl::get(const VideoReaderProps propertyId, const int propertyVal) const { + switch (propertyId) { case VideoReaderProps::PROP_DECODED_FRAME_IDX: return decodedFrameIdx; @@ -269,6 +271,10 @@ namespace return -1; } + double VideoReaderImpl::get(const int propertyId) const { + return videoSource_->get(propertyId); + } + bool VideoReaderImpl::nextFrame(GpuMat& frame, Stream& stream) { if (!internalGrab(frame, stream)) @@ -277,7 +283,7 @@ namespace } } -Ptr cv::cudacodec::createVideoReader(const String& filename, const bool rawMode) +Ptr cv::cudacodec::createVideoReader(const String& filename, const std::vector& params, const bool rawMode) { CV_Assert(!filename.empty()); @@ -286,7 +292,7 @@ Ptr cv::cudacodec::createVideoReader(const String& filename, const try { // prefer ffmpeg to cuvidGetSourceVideoFormat() which doesn't always return the corrct raw pixel format - Ptr source(new FFmpegVideoSource(filename)); + Ptr source(new FFmpegVideoSource(filename, params)); videoSource.reset(new RawVideoSourceWrapper(source, rawMode)); } catch (...) diff --git a/modules/cudacodec/src/video_source.cpp b/modules/cudacodec/src/video_source.cpp index ab549fbd8e..0eac8f93e3 100644 --- a/modules/cudacodec/src/video_source.cpp +++ b/modules/cudacodec/src/video_source.cpp @@ -71,6 +71,11 @@ void cv::cudacodec::detail::RawVideoSourceWrapper::updateFormat(const FormatInfo source_->updateFormat(videoFormat); } +double cv::cudacodec::detail::RawVideoSourceWrapper::get(const int propId) const +{ + return source_->get(propId); +} + void cv::cudacodec::detail::RawVideoSourceWrapper::start() { stop_ = false; diff --git a/modules/cudacodec/src/video_source.hpp b/modules/cudacodec/src/video_source.hpp index ebaa3ba301..d7a62a8d37 100644 --- a/modules/cudacodec/src/video_source.hpp +++ b/modules/cudacodec/src/video_source.hpp @@ -57,6 +57,7 @@ class VideoSource virtual FormatInfo format() const = 0; virtual void updateFormat(const FormatInfo& videoFormat) = 0; + virtual double get(const int propId) const { return 0; } virtual void start() = 0; virtual void stop() = 0; virtual bool isStarted() const = 0; @@ -89,6 +90,7 @@ class RawVideoSourceWrapper : public VideoSource FormatInfo format() const CV_OVERRIDE; void updateFormat(const FormatInfo& videoFormat) CV_OVERRIDE; + double get(const int propId) const CV_OVERRIDE; void start() CV_OVERRIDE; void stop() CV_OVERRIDE; bool isStarted() const CV_OVERRIDE; diff --git a/modules/cudacodec/test/test_video.cpp b/modules/cudacodec/test/test_video.cpp index f23360dceb..bd39afbde3 100644 --- a/modules/cudacodec/test/test_video.cpp +++ b/modules/cudacodec/test/test_video.cpp @@ -49,6 +49,11 @@ PARAM_TEST_CASE(CheckSet, cv::cuda::DeviceInfo, std::string) { }; +typedef tuple check_extra_data_params_t; +PARAM_TEST_CASE(CheckExtraData, cv::cuda::DeviceInfo, check_extra_data_params_t) +{ +}; + PARAM_TEST_CASE(Video, cv::cuda::DeviceInfo, std::string) { }; @@ -61,6 +66,18 @@ PARAM_TEST_CASE(CheckKeyFrame, cv::cuda::DeviceInfo, std::string) { }; +struct CheckParams : testing::TestWithParam +{ + cv::cuda::DeviceInfo devInfo; + + virtual void SetUp() + { + devInfo = GetParam(); + + cv::cuda::setDevice(devInfo.deviceID()); + } +}; + #if defined(HAVE_NVCUVID) ////////////////////////////////////////////////////// // VideoReader @@ -89,31 +106,25 @@ CUDA_TEST_P(CheckSet, Reader) ASSERT_TRUE(rawPacketsAvailable); } -typedef tuple check_extra_data_params_t; -typedef testing::TestWithParam< check_extra_data_params_t > CheckExtraData; - CUDA_TEST_P(CheckExtraData, Reader) { // RTSP streaming is only supported by the FFmpeg back end if (!videoio_registry::hasBackend(CAP_FFMPEG)) throw SkipTestException("FFmpeg backend not found"); - const std::vector devices = cvtest::DeviceManager::instance().values(); - for (const auto& device : devices) { - cv::cuda::setDevice(device.deviceID()); - const string path = GET_PARAM(0); - const int sz = GET_PARAM(1); - std::string inputFile = std::string(cvtest::TS::ptr()->get_data_path()) + "../" + path; - cv::Ptr reader = cv::cudacodec::createVideoReader(inputFile, true); - ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_RAW_MODE)); - const int extraDataIdx = reader->get(cv::cudacodec::VideoReaderProps::PROP_EXTRA_DATA_INDEX); - ASSERT_EQ(extraDataIdx, 1 ); - ASSERT_TRUE(reader->grab()); - cv::Mat extraData; - const bool newData = reader->retrieve(extraData, extraDataIdx); - ASSERT_TRUE(newData && sz || !newData && !sz); - ASSERT_EQ(extraData.total(), sz); - } + cv::cuda::setDevice(GET_PARAM(0).deviceID()); + const string path = get<0>(GET_PARAM(1)); + const int sz = get<1>(GET_PARAM(1)); + std::string inputFile = std::string(cvtest::TS::ptr()->get_data_path()) + "../" + path; + cv::Ptr reader = cv::cudacodec::createVideoReader(inputFile, {}, true); + ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_RAW_MODE)); + const int extraDataIdx = reader->get(cv::cudacodec::VideoReaderProps::PROP_EXTRA_DATA_INDEX); + ASSERT_EQ(extraDataIdx, 1 ); + ASSERT_TRUE(reader->grab()); + cv::Mat extraData; + const bool newData = reader->retrieve(extraData, extraDataIdx); + ASSERT_TRUE(newData && sz || !newData && !sz); + ASSERT_EQ(extraData.total(), sz); } CUDA_TEST_P(CheckKeyFrame, Reader) @@ -126,7 +137,7 @@ CUDA_TEST_P(CheckKeyFrame, Reader) const string path = GET_PARAM(1); std::string inputFile = std::string(cvtest::TS::ptr()->get_data_path()) + "../" + path; - cv::Ptr reader = cv::cudacodec::createVideoReader(inputFile, true); + cv::Ptr reader = cv::cudacodec::createVideoReader(inputFile, {}, true); ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_RAW_MODE)); const int rawIdxBase = reader->get(cv::cudacodec::VideoReaderProps::PROP_RAW_PACKAGES_BASE_INDEX); ASSERT_EQ(rawIdxBase, 2); @@ -180,7 +191,7 @@ CUDA_TEST_P(VideoReadRaw, Reader) { std::ofstream file(fileNameOut, std::ios::binary); ASSERT_TRUE(file.is_open()); - cv::Ptr reader = cv::cudacodec::createVideoReader(inputFile,true); + cv::Ptr reader = cv::cudacodec::createVideoReader(inputFile, {}, true); ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_RAW_MODE)); const int rawIdxBase = reader->get(cv::cudacodec::VideoReaderProps::PROP_RAW_PACKAGES_BASE_INDEX); ASSERT_EQ(rawIdxBase, 2); @@ -204,7 +215,7 @@ CUDA_TEST_P(VideoReadRaw, Reader) { cv::Ptr readerReference = cv::cudacodec::createVideoReader(inputFile); - cv::Ptr readerActual = cv::cudacodec::createVideoReader(fileNameOut,true); + cv::Ptr readerActual = cv::cudacodec::createVideoReader(fileNameOut, {}, true); const int decodedFrameIdx = readerActual->get(cv::cudacodec::VideoReaderProps::PROP_DECODED_FRAME_IDX); ASSERT_EQ(decodedFrameIdx, 0); cv::cuda::GpuMat reference, actual; @@ -222,6 +233,18 @@ CUDA_TEST_P(VideoReadRaw, Reader) ASSERT_EQ(0, remove(fileNameOut.c_str())); } + +CUDA_TEST_P(CheckParams, Reader) +{ + { + constexpr int msReference = 3333; + std::string inputFile = std::string(cvtest::TS::ptr()->get_data_path()) + "../highgui/video/big_buck_bunny.mp4"; + cv::Ptr reader = cv::cudacodec::createVideoReader(inputFile, { + cv::VideoCaptureProperties::CAP_PROP_OPEN_TIMEOUT_MSEC, msReference }); + const double msActual = reader->get(cv::VideoCaptureProperties::CAP_PROP_OPEN_TIMEOUT_MSEC); + ASSERT_EQ(msActual, msReference); + } +} #endif // HAVE_NVCUVID #if defined(_WIN32) && defined(HAVE_NVCUVENC) @@ -290,23 +313,20 @@ INSTANTIATE_TEST_CASE_P(CUDA_Codec, VideoReadRaw, testing::Combine( const check_extra_data_params_t check_extra_data_params[] = { - check_extra_data_params_t("cv/video/768x576.avi", 44), - check_extra_data_params_t("cv/video/1920x1080.avi", 47), - check_extra_data_params_t("highgui/video/big_buck_bunny.h264", 38), - check_extra_data_params_t("highgui/video/big_buck_bunny.h265", 84), check_extra_data_params_t("highgui/video/big_buck_bunny.mp4", 45), - check_extra_data_params_t("highgui/video/big_buck_bunny.avi", 58), - check_extra_data_params_t("highgui/video/big_buck_bunny.mpg", 12), check_extra_data_params_t("highgui/video/big_buck_bunny.mov", 45), check_extra_data_params_t("highgui/video/big_buck_bunny.mjpg.avi", 0) }; -INSTANTIATE_TEST_CASE_P(CUDA_Codec, CheckExtraData, testing::ValuesIn(check_extra_data_params)); +INSTANTIATE_TEST_CASE_P(CUDA_Codec, CheckExtraData, testing::Combine( + ALL_DEVICES, + testing::ValuesIn(check_extra_data_params))); INSTANTIATE_TEST_CASE_P(CUDA_Codec, CheckKeyFrame, testing::Combine( ALL_DEVICES, testing::Values(VIDEO_SRC_R))); +INSTANTIATE_TEST_CASE_P(CUDA_Codec, CheckParams, ALL_DEVICES); #endif // HAVE_NVCUVID || HAVE_NVCUVENC }} // namespace From e126d5baa3361c8b26f036af6b844fc9837400a4 Mon Sep 17 00:00:00 2001 From: cudawarped Date: Fri, 24 Dec 2021 13:12:46 +0000 Subject: [PATCH 3/5] Prevent, fall back to CuvidVideoSource if VideoCapture params are passed and initialization fails and add test for this. --- modules/cudacodec/src/video_reader.cpp | 1 + modules/cudacodec/test/test_video.cpp | 25 ++++++++++++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/modules/cudacodec/src/video_reader.cpp b/modules/cudacodec/src/video_reader.cpp index 3f068da17e..ccbffe904b 100644 --- a/modules/cudacodec/src/video_reader.cpp +++ b/modules/cudacodec/src/video_reader.cpp @@ -297,6 +297,7 @@ Ptr cv::cudacodec::createVideoReader(const String& filename, const } catch (...) { + if (params.size()) throw; videoSource.reset(new CuvidVideoSource(filename)); } diff --git a/modules/cudacodec/test/test_video.cpp b/modules/cudacodec/test/test_video.cpp index bd39afbde3..ebfed2cdbc 100644 --- a/modules/cudacodec/test/test_video.cpp +++ b/modules/cudacodec/test/test_video.cpp @@ -236,14 +236,37 @@ CUDA_TEST_P(VideoReadRaw, Reader) CUDA_TEST_P(CheckParams, Reader) { + std::string inputFile = std::string(cvtest::TS::ptr()->get_data_path()) + "../highgui/video/big_buck_bunny.mp4"; + { + cv::Ptr reader = cv::cudacodec::createVideoReader(inputFile); + const double msActual = reader->get(cv::VideoCaptureProperties::CAP_PROP_OPEN_TIMEOUT_MSEC); + ASSERT_EQ(msActual, 0); + } + { constexpr int msReference = 3333; - std::string inputFile = std::string(cvtest::TS::ptr()->get_data_path()) + "../highgui/video/big_buck_bunny.mp4"; cv::Ptr reader = cv::cudacodec::createVideoReader(inputFile, { cv::VideoCaptureProperties::CAP_PROP_OPEN_TIMEOUT_MSEC, msReference }); const double msActual = reader->get(cv::VideoCaptureProperties::CAP_PROP_OPEN_TIMEOUT_MSEC); ASSERT_EQ(msActual, msReference); } + + { + std::vector exceptionsThrown = { false,true }; + std::vector capPropFormats = { -1,0 }; + for (int i = 0; i < capPropFormats.size(); i++) { + bool exceptionThrown = false; + try { + cv::Ptr reader = cv::cudacodec::createVideoReader(inputFile, { + cv::VideoCaptureProperties::CAP_PROP_FORMAT, capPropFormats.at(i) }); + } + catch (cv::Exception ex) { + if (ex.code == Error::StsUnsupportedFormat) + exceptionThrown = true; + } + ASSERT_EQ(exceptionThrown, exceptionsThrown.at(i)); + } + } } #endif // HAVE_NVCUVID From 1832b5b99d10ee459eec1d63e4e34cb20e9061f2 Mon Sep 17 00:00:00 2001 From: cudawarped Date: Sat, 25 Dec 2021 17:58:00 +0000 Subject: [PATCH 4/5] Remove magic number from get methods, and make the types consistent with VideoCapture::get Fix documentation. --- .../cudacodec/include/opencv2/cudacodec.hpp | 44 +++++++++------ modules/cudacodec/src/ffmpeg_video_source.cpp | 12 +++-- modules/cudacodec/src/ffmpeg_video_source.hpp | 2 +- modules/cudacodec/src/video_reader.cpp | 38 +++++++------ modules/cudacodec/src/video_source.cpp | 4 +- modules/cudacodec/src/video_source.hpp | 4 +- modules/cudacodec/test/test_video.cpp | 53 +++++++++++++------ 7 files changed, 99 insertions(+), 58 deletions(-) diff --git a/modules/cudacodec/include/opencv2/cudacodec.hpp b/modules/cudacodec/include/opencv2/cudacodec.hpp index 829153d00b..7eddc57162 100644 --- a/modules/cudacodec/include/opencv2/cudacodec.hpp +++ b/modules/cudacodec/include/opencv2/cudacodec.hpp @@ -316,7 +316,10 @@ enum class VideoReaderProps { PROP_RAW_PACKAGES_BASE_INDEX = 2, //!< Base index for retrieving raw encoded data using retrieve(). PROP_NUMBER_OF_RAW_PACKAGES_SINCE_LAST_GRAB = 3, //!< Number of raw packages recieved since the last call to grab(). PROP_RAW_MODE = 4, //!< Status of raw mode. - PROP_LRF_HAS_KEY_FRAME = 5 //!< FFmpeg source only - Indicates whether the Last Raw Frame (LRF), output from VideoReader::retrieve() when VideoReader is initialized in raw mode, contains encoded data for a key frame. + PROP_LRF_HAS_KEY_FRAME = 5, //!< FFmpeg source only - Indicates whether the Last Raw Frame (LRF), output from VideoReader::retrieve() when VideoReader is initialized in raw mode, contains encoded data for a key frame. +#ifndef CV_DOXYGEN + PROP_NOT_SUPPORTED +#endif }; /** @brief Video reader interface. @@ -369,7 +372,7 @@ class CV_EXPORTS_W VideoReader /** @brief Sets a property in the VideoReader. - @param property Property identifier from cv::cudacodec::VideoReaderProps (eg. cv::cudacodec::PROP_DECODED_FRAME_IDX, cv::cudacodec::PROP_EXTRA_DATA_INDEX, ...) + @param propertyId Property identifier from cv::cudacodec::VideoReaderProps (eg. cv::cudacodec::PROP_DECODED_FRAME_IDX, cv::cudacodec::PROP_EXTRA_DATA_INDEX, ...). @param propertyVal Value of the property. @return `true` if the property has been set. */ @@ -377,20 +380,22 @@ class CV_EXPORTS_W VideoReader /** @brief Returns the specified VideoReader property - @param property Property identifier from cv::cudacodec::VideoReaderProps (eg. cv::cudacodec::PROP_DECODED_FRAME_IDX, cv::cudacodec::PROP_EXTRA_DATA_INDEX, ...) + @param propertyId Property identifier from cv::cudacodec::VideoReaderProps (eg. cv::cudacodec::PROP_DECODED_FRAME_IDX, cv::cudacodec::PROP_EXTRA_DATA_INDEX, ...). + @param propertyValOut Value for the specified property. @param propertyVal Optional value for the property. - @return Value for the specified property. Value -1 is returned when querying a property that is not supported. + @return `true` unless the property is not supported. */ - CV_WRAP virtual int get(const VideoReaderProps propertyId, const int propertyVal = -1) const = 0; + CV_WRAP virtual bool get(const VideoReaderProps propertyId, double& propertyValOut, const int propertyVal = -1) const = 0; + + /** @brief Retrieves the specified property used by the VideoSource. - /** @brief Returns the specified property used by the VideoSource. + @param propertyId Property identifier from cv::VideoCaptureProperties (eg. cv::CAP_PROP_POS_MSEC, cv::CAP_PROP_POS_FRAMES, ...) + or one from @ref videoio_flags_others. + @param propertyVal Value for the specified property. - @param propId Property identifier from cv::VideoCaptureProperties (eg. cv::CAP_PROP_POS_MSEC, cv::CAP_PROP_POS_FRAMES, ...) - or one from @ref videoio_flags_others - @return Value for the specified property. Value 0 is returned when querying a property that is - not supported. + @return `true` unless the property is unset set or not supported. */ - CV_WRAP virtual double get(const int propertyId) const = 0; + CV_WRAP virtual bool get(const int propertyId, double& propertyVal) const = 0; }; /** @brief Interface for video demultiplexing. : @@ -427,19 +432,24 @@ class CV_EXPORTS_W RawVideoSource */ virtual void getExtraData(cv::Mat& extraData) const = 0; - /** @brief Returns the specified property used by the VideoSource. + /** @brief Retrieves the specified property used by the VideoSource. + + @param propertyId Property identifier from cv::VideoCaptureProperties (eg. cv::CAP_PROP_POS_MSEC, cv::CAP_PROP_POS_FRAMES, ...) + or one from @ref videoio_flags_others. + @param propertyVal Value for the specified property. - @param propId Property identifier from cv::VideoCaptureProperties (eg. cv::CAP_PROP_POS_MSEC, cv::CAP_PROP_POS_FRAMES, ...) - or one from @ref videoio_flags_others - @return Value for the specified property. Value 0 is returned when querying a property that is - not supported. + @return `true` unless the property is unset set or not supported. */ - virtual double get(const int propId) const = 0; + virtual bool get(const int propertyId, double& propertyVal) const = 0; }; /** @brief Creates video reader. @param filename Name of the input video file. +@param params Pass through parameters for VideoCapure. VideoCapture with the FFMpeg back end (CAP_FFMPEG) is used to parse the video input. +The `params` parameter allows to specify extra parameters encoded as pairs `(paramId_1, paramValue_1, paramId_2, paramValue_2, ...)`. + See cv::VideoCaptureProperties +e.g. when streaming from an RTSP source CAP_PROP_OPEN_TIMEOUT_MSEC may need to be set. @param rawMode Allow the raw encoded data which has been read up until the last call to grab() to be retrieved by calling retrieve(rawData,RAW_DATA_IDX). FFMPEG is used to read videos. User can implement own demultiplexing with cudacodec::RawVideoSource diff --git a/modules/cudacodec/src/ffmpeg_video_source.cpp b/modules/cudacodec/src/ffmpeg_video_source.cpp index 96574fa451..436a18eb39 100644 --- a/modules/cudacodec/src/ffmpeg_video_source.cpp +++ b/modules/cudacodec/src/ffmpeg_video_source.cpp @@ -178,14 +178,16 @@ void cv::cudacodec::detail::FFmpegVideoSource::updateFormat(const FormatInfo& vi format_.valid = true; } -double cv::cudacodec::detail::FFmpegVideoSource::get(const int propId) const +bool cv::cudacodec::detail::FFmpegVideoSource::get(const int propertyId, double& propertyVal) const { - if (videoCaptureParams.size() % 2 != 0) return 0; + CV_Assert(videoCaptureParams.size() % 2 == 0); for (std::size_t i = 0; i < videoCaptureParams.size(); i += 2) { - if (videoCaptureParams.at(i) == propId) - return videoCaptureParams.at(i + 1); + if (videoCaptureParams.at(i) == propertyId) { + propertyVal = videoCaptureParams.at(i + 1); + return true; + } } - return 0; + return false; } bool cv::cudacodec::detail::FFmpegVideoSource::getNextPacket(unsigned char** data, size_t* size) diff --git a/modules/cudacodec/src/ffmpeg_video_source.hpp b/modules/cudacodec/src/ffmpeg_video_source.hpp index a5a46d96f5..ce8582f650 100644 --- a/modules/cudacodec/src/ffmpeg_video_source.hpp +++ b/modules/cudacodec/src/ffmpeg_video_source.hpp @@ -64,7 +64,7 @@ class FFmpegVideoSource : public RawVideoSource void getExtraData(cv::Mat& _extraData) const CV_OVERRIDE { _extraData = extraData; } - double get(const int propId) const; + bool get(const int propertyId, double& propertyVal) const; private: FormatInfo format_; diff --git a/modules/cudacodec/src/video_reader.cpp b/modules/cudacodec/src/video_reader.cpp index ccbffe904b..6b78d56582 100644 --- a/modules/cudacodec/src/video_reader.cpp +++ b/modules/cudacodec/src/video_reader.cpp @@ -48,7 +48,7 @@ using namespace cv::cudacodec; #ifndef HAVE_NVCUVID -Ptr cv::cudacodec::createVideoReader(const String&, const bool) { throw_no_cuda(); return Ptr(); } +Ptr cv::cudacodec::createVideoReader(const String&, const std::vector&, const bool) { throw_no_cuda(); return Ptr(); } Ptr cv::cudacodec::createVideoReader(const Ptr&, const bool) { throw_no_cuda(); return Ptr(); } #else // HAVE_NVCUVID @@ -75,9 +75,9 @@ namespace bool set(const VideoReaderProps propertyId, const double propertyVal) CV_OVERRIDE; - int get(const VideoReaderProps propertyId, const int propertyVal) const CV_OVERRIDE; + bool get(const VideoReaderProps propertyId, double& propertyValOut, const int propertyVal) const CV_OVERRIDE; - double get(const int propertyId) const CV_OVERRIDE; + bool get(const int propertyId, double& propertyVal) const CV_OVERRIDE; private: bool internalGrab(GpuMat& frame, Stream& stream); @@ -242,37 +242,45 @@ namespace return true; } - int VideoReaderImpl::get(const VideoReaderProps propertyId, const int propertyVal) const { + bool VideoReaderImpl::get(const VideoReaderProps propertyId, double& propertyValOut, const int propertyVal) const { switch (propertyId) { case VideoReaderProps::PROP_DECODED_FRAME_IDX: - return decodedFrameIdx; + propertyValOut = decodedFrameIdx; + return true; case VideoReaderProps::PROP_EXTRA_DATA_INDEX: - return extraDataIdx; + propertyValOut = extraDataIdx; + return true; case VideoReaderProps::PROP_RAW_PACKAGES_BASE_INDEX: - if (videoSource_->RawModeEnabled()) - return rawPacketsBaseIdx; + if (videoSource_->RawModeEnabled()) { + propertyValOut = rawPacketsBaseIdx; + return true; + } else break; case VideoReaderProps::PROP_NUMBER_OF_RAW_PACKAGES_SINCE_LAST_GRAB: - return rawPackets.size(); + propertyValOut = rawPackets.size(); + return true; case::VideoReaderProps::PROP_RAW_MODE: - return videoSource_->RawModeEnabled(); + propertyValOut = videoSource_->RawModeEnabled(); + return true; case::VideoReaderProps::PROP_LRF_HAS_KEY_FRAME: { const int iPacket = propertyVal - rawPacketsBaseIdx; - if (videoSource_->RawModeEnabled() && iPacket >= 0 && iPacket < rawPackets.size()) - return rawPackets.at(iPacket).containsKeyFrame; + if (videoSource_->RawModeEnabled() && iPacket >= 0 && iPacket < rawPackets.size()) { + propertyValOut = rawPackets.at(iPacket).containsKeyFrame; + return true; + } else break; } default: break; } - return -1; + return false; } - double VideoReaderImpl::get(const int propertyId) const { - return videoSource_->get(propertyId); + bool VideoReaderImpl::get(const int propertyId, double& propertyVal) const { + return videoSource_->get(propertyId, propertyVal); } bool VideoReaderImpl::nextFrame(GpuMat& frame, Stream& stream) diff --git a/modules/cudacodec/src/video_source.cpp b/modules/cudacodec/src/video_source.cpp index 0eac8f93e3..b58d753f74 100644 --- a/modules/cudacodec/src/video_source.cpp +++ b/modules/cudacodec/src/video_source.cpp @@ -71,9 +71,9 @@ void cv::cudacodec::detail::RawVideoSourceWrapper::updateFormat(const FormatInfo source_->updateFormat(videoFormat); } -double cv::cudacodec::detail::RawVideoSourceWrapper::get(const int propId) const +bool cv::cudacodec::detail::RawVideoSourceWrapper::get(const int propertyId, double& propertyVal) const { - return source_->get(propId); + return source_->get(propertyId, propertyVal); } void cv::cudacodec::detail::RawVideoSourceWrapper::start() diff --git a/modules/cudacodec/src/video_source.hpp b/modules/cudacodec/src/video_source.hpp index d7a62a8d37..8c96a34f2d 100644 --- a/modules/cudacodec/src/video_source.hpp +++ b/modules/cudacodec/src/video_source.hpp @@ -57,7 +57,7 @@ class VideoSource virtual FormatInfo format() const = 0; virtual void updateFormat(const FormatInfo& videoFormat) = 0; - virtual double get(const int propId) const { return 0; } + virtual bool get(const int propertyId, double& propertyVal) const { return false; } virtual void start() = 0; virtual void stop() = 0; virtual bool isStarted() const = 0; @@ -90,7 +90,7 @@ class RawVideoSourceWrapper : public VideoSource FormatInfo format() const CV_OVERRIDE; void updateFormat(const FormatInfo& videoFormat) CV_OVERRIDE; - double get(const int propId) const CV_OVERRIDE; + bool get(const int propertyId, double& propertyVal) const CV_OVERRIDE; void start() CV_OVERRIDE; void stop() CV_OVERRIDE; bool isStarted() const CV_OVERRIDE; diff --git a/modules/cudacodec/test/test_video.cpp b/modules/cudacodec/test/test_video.cpp index ebfed2cdbc..320f043d9a 100644 --- a/modules/cudacodec/test/test_video.cpp +++ b/modules/cudacodec/test/test_video.cpp @@ -93,12 +93,19 @@ CUDA_TEST_P(CheckSet, Reader) std::string inputFile = std::string(cvtest::TS::ptr()->get_data_path()) + +"../" + GET_PARAM(1); cv::Ptr reader = cv::cudacodec::createVideoReader(inputFile); - ASSERT_FALSE(reader->get(cv::cudacodec::VideoReaderProps::PROP_RAW_MODE)); + double unsupportedVal = -1; + ASSERT_FALSE(reader->get(cv::cudacodec::VideoReaderProps::PROP_NOT_SUPPORTED, unsupportedVal)); + double rawModeVal = -1; + ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_RAW_MODE, rawModeVal)); + ASSERT_FALSE(rawModeVal); ASSERT_TRUE(reader->set(cv::cudacodec::VideoReaderProps::PROP_RAW_MODE,true)); - ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_RAW_MODE)); + ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_RAW_MODE, rawModeVal)); + ASSERT_TRUE(rawModeVal); bool rawPacketsAvailable = false; while (reader->grab()) { - if (reader->get(cv::cudacodec::VideoReaderProps::PROP_NUMBER_OF_RAW_PACKAGES_SINCE_LAST_GRAB) > 0) { + double nRawPackages = -1; + ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_NUMBER_OF_RAW_PACKAGES_SINCE_LAST_GRAB, nRawPackages)); + if (nRawPackages > 0) { rawPacketsAvailable = true; break; } @@ -117,8 +124,11 @@ CUDA_TEST_P(CheckExtraData, Reader) const int sz = get<1>(GET_PARAM(1)); std::string inputFile = std::string(cvtest::TS::ptr()->get_data_path()) + "../" + path; cv::Ptr reader = cv::cudacodec::createVideoReader(inputFile, {}, true); - ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_RAW_MODE)); - const int extraDataIdx = reader->get(cv::cudacodec::VideoReaderProps::PROP_EXTRA_DATA_INDEX); + double rawModeVal = -1; + ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_RAW_MODE, rawModeVal)); + ASSERT_TRUE(rawModeVal); + double extraDataIdx = -1; + ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_EXTRA_DATA_INDEX, extraDataIdx)); ASSERT_EQ(extraDataIdx, 1 ); ASSERT_TRUE(reader->grab()); cv::Mat extraData; @@ -138,17 +148,22 @@ CUDA_TEST_P(CheckKeyFrame, Reader) const string path = GET_PARAM(1); std::string inputFile = std::string(cvtest::TS::ptr()->get_data_path()) + "../" + path; cv::Ptr reader = cv::cudacodec::createVideoReader(inputFile, {}, true); - ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_RAW_MODE)); - const int rawIdxBase = reader->get(cv::cudacodec::VideoReaderProps::PROP_RAW_PACKAGES_BASE_INDEX); + double rawModeVal = -1; + ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_RAW_MODE, rawModeVal)); + ASSERT_TRUE(rawModeVal); + double rawIdxBase = -1; + ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_RAW_PACKAGES_BASE_INDEX, rawIdxBase)); ASSERT_EQ(rawIdxBase, 2); constexpr int maxNPackagesToCheck = 2; int nPackages = 0; while (nPackages < maxNPackagesToCheck) { ASSERT_TRUE(reader->grab()); - const int N = reader->get(cv::cudacodec::VideoReaderProps::PROP_NUMBER_OF_RAW_PACKAGES_SINCE_LAST_GRAB); + double N = -1; + ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_NUMBER_OF_RAW_PACKAGES_SINCE_LAST_GRAB,N)); for (int i = rawIdxBase; i < N + rawIdxBase; i++) { nPackages++; - const bool containsKeyFrame = reader->get(cv::cudacodec::VideoReaderProps::PROP_LRF_HAS_KEY_FRAME, i); + double containsKeyFrame = -1; + ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_LRF_HAS_KEY_FRAME, containsKeyFrame, i)); ASSERT_TRUE(nPackages == 1 && containsKeyFrame || nPackages == 2 && !containsKeyFrame) << "nPackage: " << i; if (nPackages >= maxNPackagesToCheck) break; @@ -192,8 +207,11 @@ CUDA_TEST_P(VideoReadRaw, Reader) std::ofstream file(fileNameOut, std::ios::binary); ASSERT_TRUE(file.is_open()); cv::Ptr reader = cv::cudacodec::createVideoReader(inputFile, {}, true); - ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_RAW_MODE)); - const int rawIdxBase = reader->get(cv::cudacodec::VideoReaderProps::PROP_RAW_PACKAGES_BASE_INDEX); + double rawModeVal = -1; + ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_RAW_MODE, rawModeVal)); + ASSERT_TRUE(rawModeVal); + double rawIdxBase = -1; + ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_RAW_PACKAGES_BASE_INDEX, rawIdxBase)); ASSERT_EQ(rawIdxBase, 2); cv::cuda::GpuMat frame; for (int i = 0; i < 100; i++) @@ -201,7 +219,8 @@ CUDA_TEST_P(VideoReadRaw, Reader) ASSERT_TRUE(reader->grab()); ASSERT_TRUE(reader->retrieve(frame)); ASSERT_FALSE(frame.empty()); - const int N = reader->get(cv::cudacodec::VideoReaderProps::PROP_NUMBER_OF_RAW_PACKAGES_SINCE_LAST_GRAB); + double N = -1; + ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_NUMBER_OF_RAW_PACKAGES_SINCE_LAST_GRAB,N)); ASSERT_TRUE(N >= 0) << N << " < 0"; for (int i = rawIdxBase; i <= N + rawIdxBase; i++) { Mat rawPackets; @@ -216,7 +235,8 @@ CUDA_TEST_P(VideoReadRaw, Reader) { cv::Ptr readerReference = cv::cudacodec::createVideoReader(inputFile); cv::Ptr readerActual = cv::cudacodec::createVideoReader(fileNameOut, {}, true); - const int decodedFrameIdx = readerActual->get(cv::cudacodec::VideoReaderProps::PROP_DECODED_FRAME_IDX); + double decodedFrameIdx = -1; + ASSERT_TRUE(readerActual->get(cv::cudacodec::VideoReaderProps::PROP_DECODED_FRAME_IDX, decodedFrameIdx)); ASSERT_EQ(decodedFrameIdx, 0); cv::cuda::GpuMat reference, actual; cv::Mat referenceHost, actualHost; @@ -239,15 +259,16 @@ CUDA_TEST_P(CheckParams, Reader) std::string inputFile = std::string(cvtest::TS::ptr()->get_data_path()) + "../highgui/video/big_buck_bunny.mp4"; { cv::Ptr reader = cv::cudacodec::createVideoReader(inputFile); - const double msActual = reader->get(cv::VideoCaptureProperties::CAP_PROP_OPEN_TIMEOUT_MSEC); - ASSERT_EQ(msActual, 0); + double msActual = -1; + ASSERT_FALSE(reader->get(cv::VideoCaptureProperties::CAP_PROP_OPEN_TIMEOUT_MSEC, msActual)); } { constexpr int msReference = 3333; cv::Ptr reader = cv::cudacodec::createVideoReader(inputFile, { cv::VideoCaptureProperties::CAP_PROP_OPEN_TIMEOUT_MSEC, msReference }); - const double msActual = reader->get(cv::VideoCaptureProperties::CAP_PROP_OPEN_TIMEOUT_MSEC); + double msActual = -1; + ASSERT_TRUE(reader->get(cv::VideoCaptureProperties::CAP_PROP_OPEN_TIMEOUT_MSEC, msActual)); ASSERT_EQ(msActual, msReference); } From 45751f8170670808332df050073685706483b9a2 Mon Sep 17 00:00:00 2001 From: cudawarped Date: Tue, 28 Dec 2021 15:13:08 +0000 Subject: [PATCH 5/5] Add wrapper macro's and remove unecessary parameter from get(). --- modules/cudacodec/include/opencv2/cudacodec.hpp | 15 +++++++++------ modules/cudacodec/src/video_reader.cpp | 16 ++++++++-------- modules/cudacodec/test/test_video.cpp | 4 ++-- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/modules/cudacodec/include/opencv2/cudacodec.hpp b/modules/cudacodec/include/opencv2/cudacodec.hpp index 7eddc57162..e76d3cfb8b 100644 --- a/modules/cudacodec/include/opencv2/cudacodec.hpp +++ b/modules/cudacodec/include/opencv2/cudacodec.hpp @@ -372,7 +372,8 @@ class CV_EXPORTS_W VideoReader /** @brief Sets a property in the VideoReader. - @param propertyId Property identifier from cv::cudacodec::VideoReaderProps (eg. cv::cudacodec::PROP_DECODED_FRAME_IDX, cv::cudacodec::PROP_EXTRA_DATA_INDEX, ...). + @param propertyId Property identifier from cv::cudacodec::VideoReaderProps (eg. cv::cudacodec::VideoReaderProps::PROP_DECODED_FRAME_IDX, + cv::cudacodec::VideoReaderProps::PROP_EXTRA_DATA_INDEX, ...). @param propertyVal Value of the property. @return `true` if the property has been set. */ @@ -380,12 +381,14 @@ class CV_EXPORTS_W VideoReader /** @brief Returns the specified VideoReader property - @param propertyId Property identifier from cv::cudacodec::VideoReaderProps (eg. cv::cudacodec::PROP_DECODED_FRAME_IDX, cv::cudacodec::PROP_EXTRA_DATA_INDEX, ...). - @param propertyValOut Value for the specified property. - @param propertyVal Optional value for the property. + @param propertyId Property identifier from cv::cudacodec::VideoReaderProps (eg. cv::cudacodec::VideoReaderProps::PROP_DECODED_FRAME_IDX, + cv::cudacodec::VideoReaderProps::PROP_EXTRA_DATA_INDEX, ...). + @param propertyVal + In - Optional value required for querying specific propertyId's, e.g. the index of the raw package to be checked for a key frame (cv::cudacodec::VideoReaderProps::PROP_LRF_HAS_KEY_FRAME). + Out - Value of the property. @return `true` unless the property is not supported. */ - CV_WRAP virtual bool get(const VideoReaderProps propertyId, double& propertyValOut, const int propertyVal = -1) const = 0; + CV_WRAP virtual bool get(const VideoReaderProps propertyId, CV_IN_OUT double& propertyVal) const = 0; /** @brief Retrieves the specified property used by the VideoSource. @@ -395,7 +398,7 @@ class CV_EXPORTS_W VideoReader @return `true` unless the property is unset set or not supported. */ - CV_WRAP virtual bool get(const int propertyId, double& propertyVal) const = 0; + CV_WRAP virtual bool get(const int propertyId, CV_OUT double& propertyVal) const = 0; }; /** @brief Interface for video demultiplexing. : diff --git a/modules/cudacodec/src/video_reader.cpp b/modules/cudacodec/src/video_reader.cpp index 6b78d56582..b1cbe70f4c 100644 --- a/modules/cudacodec/src/video_reader.cpp +++ b/modules/cudacodec/src/video_reader.cpp @@ -75,7 +75,7 @@ namespace bool set(const VideoReaderProps propertyId, const double propertyVal) CV_OVERRIDE; - bool get(const VideoReaderProps propertyId, double& propertyValOut, const int propertyVal) const CV_OVERRIDE; + bool get(const VideoReaderProps propertyId, double& propertyVal) const CV_OVERRIDE; bool get(const int propertyId, double& propertyVal) const CV_OVERRIDE; @@ -242,32 +242,32 @@ namespace return true; } - bool VideoReaderImpl::get(const VideoReaderProps propertyId, double& propertyValOut, const int propertyVal) const { + bool VideoReaderImpl::get(const VideoReaderProps propertyId, double& propertyVal) const { switch (propertyId) { case VideoReaderProps::PROP_DECODED_FRAME_IDX: - propertyValOut = decodedFrameIdx; + propertyVal = decodedFrameIdx; return true; case VideoReaderProps::PROP_EXTRA_DATA_INDEX: - propertyValOut = extraDataIdx; + propertyVal = extraDataIdx; return true; case VideoReaderProps::PROP_RAW_PACKAGES_BASE_INDEX: if (videoSource_->RawModeEnabled()) { - propertyValOut = rawPacketsBaseIdx; + propertyVal = rawPacketsBaseIdx; return true; } else break; case VideoReaderProps::PROP_NUMBER_OF_RAW_PACKAGES_SINCE_LAST_GRAB: - propertyValOut = rawPackets.size(); + propertyVal = rawPackets.size(); return true; case::VideoReaderProps::PROP_RAW_MODE: - propertyValOut = videoSource_->RawModeEnabled(); + propertyVal = videoSource_->RawModeEnabled(); return true; case::VideoReaderProps::PROP_LRF_HAS_KEY_FRAME: { const int iPacket = propertyVal - rawPacketsBaseIdx; if (videoSource_->RawModeEnabled() && iPacket >= 0 && iPacket < rawPackets.size()) { - propertyValOut = rawPackets.at(iPacket).containsKeyFrame; + propertyVal = rawPackets.at(iPacket).containsKeyFrame; return true; } else diff --git a/modules/cudacodec/test/test_video.cpp b/modules/cudacodec/test/test_video.cpp index 320f043d9a..8dca084125 100644 --- a/modules/cudacodec/test/test_video.cpp +++ b/modules/cudacodec/test/test_video.cpp @@ -162,8 +162,8 @@ CUDA_TEST_P(CheckKeyFrame, Reader) ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_NUMBER_OF_RAW_PACKAGES_SINCE_LAST_GRAB,N)); for (int i = rawIdxBase; i < N + rawIdxBase; i++) { nPackages++; - double containsKeyFrame = -1; - ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_LRF_HAS_KEY_FRAME, containsKeyFrame, i)); + double containsKeyFrame = i; + ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_LRF_HAS_KEY_FRAME, containsKeyFrame)); ASSERT_TRUE(nPackages == 1 && containsKeyFrame || nPackages == 2 && !containsKeyFrame) << "nPackage: " << i; if (nPackages >= maxNPackagesToCheck) break;