diff --git a/modules/cudacodec/include/opencv2/cudacodec.hpp b/modules/cudacodec/include/opencv2/cudacodec.hpp index 35f5b28cc83..b62a87f4ca1 100644 --- a/modules/cudacodec/include/opencv2/cudacodec.hpp +++ b/modules/cudacodec/include/opencv2/cudacodec.hpp @@ -385,6 +385,8 @@ struct CV_EXPORTS_W_SIMPLE FormatInfo */ class CV_EXPORTS_W NVSurfaceToColorConverter { public: + virtual ~NVSurfaceToColorConverter() {} + /** @brief Performs the conversion from the raw YUV Surface output from VideoReader to the requested color format. Use this function when you want to convert the raw YUV Surface output from VideoReader to more than one color format or you want both the raw Surface output in addition to a color frame. * @param yuv The raw YUV Surface output from VideoReader see @ref SurfaceFormat. * @param color The converted frame. @@ -551,8 +553,7 @@ class CV_EXPORTS_W VideoReader - Out: Value of the property. @return `true` unless the property is not supported. */ - virtual bool get(const VideoReaderProps propertyId, double& propertyVal) const = 0; - CV_WRAP virtual bool getVideoReaderProps(const VideoReaderProps propertyId, CV_OUT double& propertyValOut, double propertyValIn = 0) const = 0; + CV_WRAP_AS(getVideoReaderProps) virtual bool get(const VideoReaderProps propertyId, CV_OUT size_t& propertyVal) const = 0; /** @brief Retrieves the specified property used by the VideoSource. @@ -563,6 +564,43 @@ class CV_EXPORTS_W VideoReader @return `true` unless the property is unset set or not supported. */ CV_WRAP virtual bool get(const int propertyId, CV_OUT double& propertyVal) const = 0; + + /** @brief Determine whether the raw package at \a idx contains encoded data for a key frame. + + @param idx Index of the encoded package to check. + + @returns `true` if the raw package at \a idx contains encoded data for a key frame and `false` otherwise. + + @note A typical use case is deciding to archive live video after streaming has been initialized. In this scenario you would not want to write any encoded frames before a key frame. This is simulated in the example below where VideoReader is initialized without enabling raw mode + ``` + VideoReaderInitParams params; + params.rawMode = false; + Ptr reader = createVideoReader(rtspUrl, {}, params); + ``` + and then at some point in the future raw mode is enabled to enable the footage to be archived + ``` + reader->set(VideoReaderProps::PROP_RAW_MODE, true); + ``` + Because raw mode has been enabled mid stream the first raw package retrieved now is not guaranteed to contain a key frame. To locate the next raw package containing a key frame rawPackageHasKeyFrame() can then be used as shown below. + ``` + double iRawPacketBase = -1; + reader->get(VideoReaderProps::PROP_RAW_PACKAGES_BASE_INDEX, iRawPacketBase); + GpuMat frame; + while (reader->nextFrame(frame)) { + double nRawPackets = -1; + reader->get(VideoReaderProps::PROP_NUMBER_OF_RAW_PACKAGES_SINCE_LAST_GRAB, nRawPackets); + for (int iRawPacketToWrite = static_cast(iRawPacketBase); iRawPacketToWrite < static_cast(iRawPacketBase + nRawPackets); iRawPacketToWrite++) { + if (reader->rawPackageHasKeyFrame(iRawPacketToWrite)) { + Mat packageToWrite; + reader->retrieve(packageToWrite, iRawPacketToWrite); + ... + } + } + } + ``` + \sa retrieve + */ + CV_WRAP virtual bool rawPackageHasKeyFrame(const size_t idx) const = 0; }; /** @brief Interface for video demultiplexing. : diff --git a/modules/cudacodec/misc/python/test/test_cudacodec.py b/modules/cudacodec/misc/python/test/test_cudacodec.py index cf20daeb181..021d3148358 100644 --- a/modules/cudacodec/misc/python/test/test_cudacodec.py +++ b/modules/cudacodec/misc/python/test/test_cudacodec.py @@ -48,37 +48,37 @@ def test_reader(self): ret, raw_mode = reader.getVideoReaderProps(cv.cudacodec.VideoReaderProps_PROP_RAW_MODE) self.assertTrue(ret and raw_mode) - # Retrieve image histogram. Not all GPUs support histogram. Just check the method is called correctly - ret, gpu_mat, hist = reader.nextFrameWithHist() - self.assertTrue(ret and not gpu_mat.empty()) - ret, gpu_mat_, hist_ = reader.nextFrameWithHist(gpu_mat, hist) - self.assertTrue(ret and not gpu_mat.empty()) - self.assertTrue(gpu_mat_.cudaPtr() == gpu_mat.cudaPtr()) + # Read raw encoded bitstream + ret, i_base = reader.getVideoReaderProps(cv.cudacodec.VideoReaderProps_PROP_RAW_PACKAGES_BASE_INDEX) + self.assertTrue(ret and i_base == 2.0) + ret, gpu_mat_2 = reader.nextFrame() + self.assertTrue(ret and isinstance(gpu_mat_2,cv.cuda.GpuMat) and not gpu_mat_2.empty()) + ret = reader.retrieve(gpu_mat_2) + self.assertTrue(ret and isinstance(gpu_mat_2,cv.cuda.GpuMat) and not gpu_mat_2.empty()) + ret, n_raw_packages_since_last_grab = reader.getVideoReaderProps(cv.cudacodec.VideoReaderProps_PROP_NUMBER_OF_RAW_PACKAGES_SINCE_LAST_GRAB) + self.assertTrue(ret and n_raw_packages_since_last_grab > 0) + self.assertTrue(reader.rawPackageHasKeyFrame(int(i_base))) + ret, raw_data = reader.retrieve(int(i_base)) + self.assertTrue(ret and isinstance(raw_data,np.ndarray) and np.any(raw_data)) # Check post processing applied - self.assertTrue(gpu_mat.size() == post_processed_sz) + self.assertTrue(gpu_mat_2.size() == post_processed_sz) + + # Retrieve image histogram. Not all GPUs support histogram. Just check the method is called correctly + ret, gpu_mat_3, hist = reader.nextFrameWithHist() + self.assertTrue(ret and not gpu_mat_3.empty()) + ret, gpu_mat_3_, hist_ = reader.nextFrameWithHist(gpu_mat_3, hist) + self.assertTrue(ret and not gpu_mat_3.empty()) + self.assertTrue(gpu_mat_3_.cudaPtr() == gpu_mat_3.cudaPtr()) # Change color format ret, colour_code = reader.getVideoReaderProps(cv.cudacodec.VideoReaderProps_PROP_COLOR_FORMAT) - self.assertTrue(ret and colour_code == cv.cudacodec.ColorFormat_BGRA) - colour_code_gs = cv.cudacodec.ColorFormat_GRAY + self.assertTrue(ret and colour_code == cv.cudacodec.BGRA) + colour_code_gs = cv.cudacodec.GRAY reader.set(colour_code_gs) ret, colour_code = reader.getVideoReaderProps(cv.cudacodec.VideoReaderProps_PROP_COLOR_FORMAT) self.assertTrue(ret and colour_code == colour_code_gs) - # Read raw encoded bitstream - ret, i_base = reader.getVideoReaderProps(cv.cudacodec.VideoReaderProps_PROP_RAW_PACKAGES_BASE_INDEX) - self.assertTrue(ret and i_base == 2.0) - self.assertTrue(reader.grab()) - ret, gpu_mat3 = reader.retrieve() - self.assertTrue(ret and isinstance(gpu_mat3,cv.cuda.GpuMat) and not gpu_mat3.empty()) - ret = reader.retrieve(gpu_mat3) - self.assertTrue(ret and isinstance(gpu_mat3,cv.cuda.GpuMat) and not gpu_mat3.empty()) - ret, n_raw_packages_since_last_grab = reader.getVideoReaderProps(cv.cudacodec.VideoReaderProps_PROP_NUMBER_OF_RAW_PACKAGES_SINCE_LAST_GRAB) - self.assertTrue(ret and n_raw_packages_since_last_grab > 0) - ret, raw_data = reader.retrieve(int(i_base)) - self.assertTrue(ret and isinstance(raw_data,np.ndarray) and np.any(raw_data)) - except cv.error as e: notSupported = (e.code == cv.Error.StsNotImplemented or e.code == cv.Error.StsUnsupportedFormat or e.code == cv.Error.GPU_API_CALL_ERROR) self.assertTrue(notSupported) @@ -107,7 +107,7 @@ def test_writer(self): encoder_params_in.gopLength = 10 stream = cv.cuda.Stream() sz = (1920,1080) - writer = cv.cudacodec.createVideoWriter(fname, sz, cv.cudacodec.H264, 30, cv.cudacodec.ColorFormat_BGR, + writer = cv.cudacodec.createVideoWriter(fname, sz, cv.cudacodec.H264, 30, cv.cudacodec.BGR, encoder_params_in, stream=stream) blankFrameIn = cv.cuda.GpuMat(sz,cv.CV_8UC3) writer.write(blankFrameIn) diff --git a/modules/cudacodec/src/NvEncoder.cpp b/modules/cudacodec/src/NvEncoder.cpp index 3beb09514b8..d606f569df8 100644 --- a/modules/cudacodec/src/NvEncoder.cpp +++ b/modules/cudacodec/src/NvEncoder.cpp @@ -101,11 +101,9 @@ void NvEncoder::CreateDefaultEncoderParams(NV_ENC_INITIALIZE_PARAMS* pIntializeP #endif pIntializeParams->tuningInfo = tuningInfo; pIntializeParams->encodeConfig->rcParams.rateControlMode = NV_ENC_PARAMS_RC_CONSTQP; -#if ((NVENCAPI_MAJOR_VERSION == 12 && NVENCAPI_MINOR_VERSION >= 2) || NVENCAPI_MAJOR_VERSION > 12) - NV_ENC_PRESET_CONFIG presetConfig = { NV_ENC_PRESET_CONFIG_VER, 0, { NV_ENC_CONFIG_VER } }; -#else - NV_ENC_PRESET_CONFIG presetConfig = { NV_ENC_PRESET_CONFIG_VER, { NV_ENC_CONFIG_VER } }; -#endif + NV_ENC_PRESET_CONFIG presetConfig = {}; + presetConfig.version = NV_ENC_PRESET_CONFIG_VER; + presetConfig.presetCfg.version = NV_ENC_CONFIG_VER; m_nvenc.nvEncGetEncodePresetConfigEx(m_hEncoder, codecGuid, presetGuid, tuningInfo, &presetConfig); memcpy(pIntializeParams->encodeConfig, &presetConfig.presetCfg, sizeof(NV_ENC_CONFIG)); @@ -205,11 +203,9 @@ void NvEncoder::CreateEncoder(const NV_ENC_INITIALIZE_PARAMS* pEncoderParams) } else { -#if ((NVENCAPI_MAJOR_VERSION == 12 && NVENCAPI_MINOR_VERSION >= 2) || NVENCAPI_MAJOR_VERSION > 12) - NV_ENC_PRESET_CONFIG presetConfig = { NV_ENC_PRESET_CONFIG_VER, 0, { NV_ENC_CONFIG_VER } }; -#else - NV_ENC_PRESET_CONFIG presetConfig = { NV_ENC_PRESET_CONFIG_VER, { NV_ENC_CONFIG_VER } }; -#endif + NV_ENC_PRESET_CONFIG presetConfig = {}; + presetConfig.version = NV_ENC_PRESET_CONFIG_VER; + presetConfig.presetCfg.version = NV_ENC_CONFIG_VER; m_nvenc.nvEncGetEncodePresetConfigEx(m_hEncoder, pEncoderParams->encodeGUID, pEncoderParams->presetGUID, pEncoderParams->tuningInfo, &presetConfig); memcpy(&m_encodeConfig, &presetConfig.presetCfg, sizeof(NV_ENC_CONFIG)); } @@ -570,6 +566,8 @@ void NvEncoder::WaitForCompletionEvent(int iEvent) NVENC_THROW_ERROR("Failed to encode frame", NV_ENC_ERR_GENERIC); } #endif +#else + CV_UNUSED(iEvent); #endif } diff --git a/modules/cudacodec/src/NvEncoder.h b/modules/cudacodec/src/NvEncoder.h index 83fb6fc69ec..04430c9e0f9 100644 --- a/modules/cudacodec/src/NvEncoder.h +++ b/modules/cudacodec/src/NvEncoder.h @@ -263,7 +263,10 @@ class NvEncoder /** * @brief This function returns the completion event. */ - void* GetCompletionEvent(uint32_t eventIdx) { return (m_vpCompletionEvent.size() == m_nEncoderBuffer) ? m_vpCompletionEvent[eventIdx] : nullptr; } + void* GetCompletionEvent(uint32_t eventIdx) { + CV_Assert(m_nEncoderBuffer >= 0); + return (m_vpCompletionEvent.size() == static_cast(m_nEncoderBuffer)) ? m_vpCompletionEvent[eventIdx] : nullptr; + } /** * @brief This function returns the current pixel format. diff --git a/modules/cudacodec/src/cuda/ColorSpace.cu b/modules/cudacodec/src/cuda/ColorSpace.cu index 137805af392..2d3db5876b6 100644 --- a/modules/cudacodec/src/cuda/ColorSpace.cu +++ b/modules/cudacodec/src/cuda/ColorSpace.cu @@ -8,6 +8,11 @@ namespace cv { namespace cuda { namespace device { +void SetMatYuv2Rgb(int iMatrix, bool fullRange = false); +void Y8ToGray8(uint8_t* dpY8, int nY8Pitch, uint8_t* dpGray, int nGrayPitch, int nWidth, int nHeight, bool videoFullRangeFlag, const cudaStream_t stream); +void Y8ToGray16(uint8_t* dpY8, int nY8Pitch, uint8_t* dpGray, int nGrayPitch, int nWidth, int nHeight, bool videoFullRangeFlag, const cudaStream_t stream); +void Y16ToGray8(uint8_t* dpY16, int nY16Pitch, uint8_t* dpGray, int nGrayPitch, int nWidth, int nHeight, bool videoFullRangeFlag, const cudaStream_t stream); +void Y16ToGray16(uint8_t* dpY16, int nY16Pitch, uint8_t* dpGray, int nGrayPitch, int nWidth, int nHeight, bool videoFullRangeFlag, const cudaStream_t stream); __constant__ float matYuv2Color[3][3]; void inline GetConstants(int iMatrix, float& wr, float& wb, int& black, int& white, int& uvWhite, int& max, bool fullRange = false) { @@ -49,7 +54,7 @@ void inline GetConstants(int iMatrix, float& wr, float& wb, int& black, int& whi } } -void SetMatYuv2Rgb(int iMatrix, bool fullRange = false) { +void SetMatYuv2Rgb(int iMatrix, bool fullRange) { float wr, wb; int black, white, max, uvWhite; GetConstants(iMatrix, wr, wb, black, white, uvWhite, max, fullRange); @@ -160,15 +165,15 @@ __global__ static void YuvToColorKernel(uint8_t* pYuv, int nYuvPitch, uint8_t* p union ColorOutx2 { Colorx2 d; - Color Color[2]; + Color color[2]; }; ColorOutx2 l1Out; - l1Out.Color[0] = YuvToColorForPixel(l0.x, ch.x, ch.y, videoFullRangeFlag); - l1Out.Color[1] = YuvToColorForPixel(l0.y, ch.x, ch.y, videoFullRangeFlag); + l1Out.color[0] = YuvToColorForPixel(l0.x, ch.x, ch.y, videoFullRangeFlag); + l1Out.color[1] = YuvToColorForPixel(l0.y, ch.x, ch.y, videoFullRangeFlag); *(Colorx2*)pDst = l1Out.d; ColorOutx2 l2Out; - l2Out.Color[0] = YuvToColorForPixel(l1.x, ch.x, ch.y, videoFullRangeFlag); - l2Out.Color[1] = YuvToColorForPixel(l1.y, ch.x, ch.y, videoFullRangeFlag); + l2Out.color[0] = YuvToColorForPixel(l1.x, ch.x, ch.y, videoFullRangeFlag); + l2Out.color[1] = YuvToColorForPixel(l1.y, ch.x, ch.y, videoFullRangeFlag); *(Colorx2*)(pDst + nColorPitch) = l2Out.d; } @@ -214,11 +219,11 @@ __global__ static void Yuv444ToColorKernel(uint8_t* pYuv, int nYuvPitch, uint8_t union ColorOutx2 { Colorx2 d; - Color Color[2]; + Color color[2]; }; ColorOutx2 out; - out.Color[0] = YuvToColorForPixel(l0.x, ch1.x, ch2.x, videoFullRangeFlag); - out.Color[1] = YuvToColorForPixel(l0.y, ch1.y, ch2.y, videoFullRangeFlag); + out.color[0] = YuvToColorForPixel(l0.x, ch1.x, ch2.x, videoFullRangeFlag); + out.color[1] = YuvToColorForPixel(l0.y, ch1.y, ch2.y, videoFullRangeFlag); *(Colorx2*)pDst = out.d; } diff --git a/modules/cudacodec/src/cuvid_video_source.cpp b/modules/cudacodec/src/cuvid_video_source.cpp index 3d7bbbb8c05..5c78288f9b6 100644 --- a/modules/cudacodec/src/cuvid_video_source.cpp +++ b/modules/cudacodec/src/cuvid_video_source.cpp @@ -68,7 +68,7 @@ cv::cudacodec::detail::CuvidVideoSource::CuvidVideoSource(const String& fname) CUVIDEOFORMAT vidfmt; cuSafeCall( cuvidGetSourceVideoFormat(videoSource_, &vidfmt, 0) ); - CV_Assert(Codec::NumCodecs == cudaVideoCodec::cudaVideoCodec_NumCodecs); + CV_Assert(static_cast(Codec::NumCodecs) == static_cast(cudaVideoCodec::cudaVideoCodec_NumCodecs)); format_.codec = static_cast(vidfmt.codec); format_.chromaFormat = static_cast(vidfmt.chroma_format); format_.nBitDepthMinus8 = vidfmt.bit_depth_luma_minus8; diff --git a/modules/cudacodec/src/cuvid_video_source.hpp b/modules/cudacodec/src/cuvid_video_source.hpp index 21b28980a20..5c1099ee4d8 100644 --- a/modules/cudacodec/src/cuvid_video_source.hpp +++ b/modules/cudacodec/src/cuvid_video_source.hpp @@ -56,6 +56,7 @@ class CuvidVideoSource : public VideoSource FormatInfo format() const CV_OVERRIDE; void updateFormat(const FormatInfo& videoFormat) CV_OVERRIDE; + bool get(const int, double&) const { return false; } void start() CV_OVERRIDE; void stop() CV_OVERRIDE; bool isStarted() const CV_OVERRIDE; diff --git a/modules/cudacodec/src/ffmpeg_video_source.cpp b/modules/cudacodec/src/ffmpeg_video_source.cpp index aa92889d55e..25bbc836eed 100644 --- a/modules/cudacodec/src/ffmpeg_video_source.cpp +++ b/modules/cudacodec/src/ffmpeg_video_source.cpp @@ -90,7 +90,7 @@ Codec FourccToCodec(int codec) } static -int StartCodeLen(unsigned char* data, const int sz) { +int StartCodeLen(unsigned char* data, const size_t sz) { if (sz >= 3 && data[0] == 0 && data[1] == 0 && data[2] == 1) return 3; else if (sz >= 4 && data[0] == 0 && data[1] == 0 && data[2] == 0 && data[3] == 1) @@ -99,7 +99,8 @@ int StartCodeLen(unsigned char* data, const int sz) { return 0; } -bool ParamSetsExist(unsigned char* parameterSets, const int szParameterSets, unsigned char* data, const int szData) { +static +bool ParamSetsExist(unsigned char* parameterSets, const size_t szParameterSets, unsigned char* data, const size_t szData) { const int paramSetStartCodeLen = StartCodeLen(parameterSets, szParameterSets); const int packetStartCodeLen = StartCodeLen(data, szData); // weak test to see if the parameter set has already been included in the RTP stream @@ -129,8 +130,8 @@ cv::cudacodec::detail::FFmpegVideoSource::FFmpegVideoSource(const String& fname, int codec = (int)cap.get(CAP_PROP_FOURCC); format_.codec = FourccToCodec(codec); - format_.height = cap.get(CAP_PROP_FRAME_HEIGHT); - format_.width = cap.get(CAP_PROP_FRAME_WIDTH); + format_.height = static_cast(cap.get(CAP_PROP_FRAME_HEIGHT)); + format_.width = static_cast(cap.get(CAP_PROP_FRAME_WIDTH)); format_.displayArea = Rect(0, 0, format_.width, format_.height); format_.valid = false; format_.fps = cap.get(CAP_PROP_FPS); @@ -181,7 +182,8 @@ bool cv::cudacodec::detail::FFmpegVideoSource::getNextPacket(unsigned char** dat { const size_t nBytesToTrimFromData = format_.codec == Codec::MPEG4 ? 3 : 0; const size_t newSz = extraData.total() + *size - nBytesToTrimFromData; - dataWithHeader = Mat(1, newSz, CV_8UC1); + CV_Assert(newSz <= std::numeric_limits::max()); + dataWithHeader = Mat(1, static_cast(newSz), CV_8UC1); memcpy(dataWithHeader.data, extraData.data, extraData.total()); memcpy(dataWithHeader.data + extraData.total(), (*data) + nBytesToTrimFromData, *size - nBytesToTrimFromData); *data = dataWithHeader.data; diff --git a/modules/cudacodec/src/video_decoder.cpp b/modules/cudacodec/src/video_decoder.cpp index 0377767f025..c392956d3e2 100644 --- a/modules/cudacodec/src/video_decoder.cpp +++ b/modules/cudacodec/src/video_decoder.cpp @@ -158,7 +158,7 @@ void cv::cudacodec::detail::VideoDecoder::create(const FormatInfo& videoFormat) codecSupported |= cudaVideoCodec_VP8 == _codec || cudaVideoCodec_VP9 == _codec; #endif #if (CUDART_VERSION >= 9000) - codecSupported |= cudaVideoCodec_AV1; + codecSupported |= cudaVideoCodec_AV1 == _codec; #endif CV_Assert(codecSupported); CV_Assert( cudaVideoChromaFormat_Monochrome == _chromaFormat || @@ -211,12 +211,12 @@ void cv::cudacodec::detail::VideoDecoder::create(const FormatInfo& videoFormat) } } - CV_Assert(videoFormat.ulWidth >= decodeCaps.nMinWidth && - videoFormat.ulHeight >= decodeCaps.nMinHeight && - videoFormat.ulWidth <= decodeCaps.nMaxWidth && - videoFormat.ulHeight <= decodeCaps.nMaxHeight); + CV_Assert(videoFormat.ulWidth >= static_cast(decodeCaps.nMinWidth) && + videoFormat.ulHeight >= static_cast(decodeCaps.nMinHeight) && + videoFormat.ulWidth <= static_cast(decodeCaps.nMaxWidth) && + videoFormat.ulHeight <= static_cast(decodeCaps.nMaxHeight)); - CV_Assert((videoFormat.width >> 4) * (videoFormat.height >> 4) <= decodeCaps.nMaxMBCount); + CV_Assert((static_cast(videoFormat.width) >> 4) * (static_cast(videoFormat.height) >> 4) <= decodeCaps.nMaxMBCount); #else if (videoFormat.enableHistogram) { CV_Error(Error::StsBadArg, "Luma histogram output is not supported when CUDA Toolkit version <= 9.0."); @@ -240,14 +240,14 @@ void cv::cudacodec::detail::VideoDecoder::create(const FormatInfo& videoFormat) createInfo_.DeinterlaceMode = static_cast(videoFormat.deinterlaceMode); createInfo_.ulTargetWidth = videoFormat.width; createInfo_.ulTargetHeight = videoFormat.height; - createInfo_.display_area.left = videoFormat.displayArea.x; - createInfo_.display_area.right = videoFormat.displayArea.x + videoFormat.displayArea.width; - createInfo_.display_area.top = videoFormat.displayArea.y; - createInfo_.display_area.bottom = videoFormat.displayArea.y + videoFormat.displayArea.height; - createInfo_.target_rect.left = videoFormat.targetRoi.x; - createInfo_.target_rect.right = videoFormat.targetRoi.x + videoFormat.targetRoi.width; - createInfo_.target_rect.top = videoFormat.targetRoi.y; - createInfo_.target_rect.bottom = videoFormat.targetRoi.y + videoFormat.targetRoi.height; + createInfo_.display_area.left = static_cast(videoFormat.displayArea.x); + createInfo_.display_area.right = static_cast(videoFormat.displayArea.x + videoFormat.displayArea.width); + createInfo_.display_area.top = static_cast(videoFormat.displayArea.y); + createInfo_.display_area.bottom = static_cast(videoFormat.displayArea.y + videoFormat.displayArea.height); + createInfo_.target_rect.left = static_cast(videoFormat.targetRoi.x); + createInfo_.target_rect.right = static_cast(videoFormat.targetRoi.x + videoFormat.targetRoi.width); + createInfo_.target_rect.top = static_cast(videoFormat.targetRoi.y); + createInfo_.target_rect.bottom = static_cast(videoFormat.targetRoi.y + videoFormat.targetRoi.height); createInfo_.ulNumOutputSurfaces = 2; createInfo_.ulCreationFlags = videoCreateFlags; createInfo_.vidLock = lock_; @@ -288,19 +288,19 @@ int cv::cudacodec::detail::VideoDecoder::reconfigure(const FormatInfo& videoForm videoFormat_.targetRoi = videoFormat.targetRoi; } - CUVIDRECONFIGUREDECODERINFO reconfigParams = { 0 }; + CUVIDRECONFIGUREDECODERINFO reconfigParams = {}; reconfigParams.ulWidth = videoFormat_.ulWidth; reconfigParams.ulHeight = videoFormat_.ulHeight; - reconfigParams.display_area.left = videoFormat_.displayArea.x; - reconfigParams.display_area.right = videoFormat_.displayArea.x + videoFormat_.displayArea.width; - reconfigParams.display_area.top = videoFormat_.displayArea.y; - reconfigParams.display_area.bottom = videoFormat_.displayArea.y + videoFormat_.displayArea.height; + reconfigParams.display_area.left = static_cast(videoFormat_.displayArea.x); + reconfigParams.display_area.right = static_cast(videoFormat_.displayArea.x + videoFormat_.displayArea.width); + reconfigParams.display_area.top = static_cast(videoFormat_.displayArea.y); + reconfigParams.display_area.bottom = static_cast(videoFormat_.displayArea.y + videoFormat_.displayArea.height); reconfigParams.ulTargetWidth = videoFormat_.width; reconfigParams.ulTargetHeight = videoFormat_.height; - reconfigParams.target_rect.left = videoFormat_.targetRoi.x; - reconfigParams.target_rect.right = videoFormat_.targetRoi.x + videoFormat_.targetRoi.width; - reconfigParams.target_rect.top = videoFormat_.targetRoi.y; - reconfigParams.target_rect.bottom = videoFormat_.targetRoi.y + videoFormat_.targetRoi.height; + reconfigParams.target_rect.left = static_cast(videoFormat_.targetRoi.x); + reconfigParams.target_rect.right = static_cast(videoFormat_.targetRoi.x + videoFormat_.targetRoi.width); + reconfigParams.target_rect.top = static_cast(videoFormat_.targetRoi.y); + reconfigParams.target_rect.bottom = static_cast(videoFormat_.targetRoi.y + videoFormat_.targetRoi.height); reconfigParams.ulNumDecodeSurfaces = videoFormat_.ulNumDecodeSurfaces; cuSafeCall(cuCtxPushCurrent(ctx_)); diff --git a/modules/cudacodec/src/video_reader.cpp b/modules/cudacodec/src/video_reader.cpp index 28bbc113163..9e12df6c5c7 100644 --- a/modules/cudacodec/src/video_reader.cpp +++ b/modules/cudacodec/src/video_reader.cpp @@ -54,7 +54,7 @@ void cv::cudacodec::MapHist(const GpuMat&, Mat&) { throw_no_cuda(); } #else // HAVE_NVCUVID -void nv12ToBgra(const GpuMat& decodedFrame, GpuMat& outFrame, int width, int height, const bool videoFullRangeFlag, cudaStream_t stream); +//void nv12ToBgra(const GpuMat& decodedFrame, GpuMat& outFrame, int width, int height, const bool videoFullRangeFlag, cudaStream_t stream); using namespace cv::cudacodec::detail; @@ -81,11 +81,12 @@ namespace bool set(const ColorFormat colorFormat, const BitDepth bitDepth = BitDepth::UNCHANGED, const bool planar = false) CV_OVERRIDE; - bool get(const VideoReaderProps propertyId, double& propertyVal) const CV_OVERRIDE; - bool getVideoReaderProps(const VideoReaderProps propertyId, double& propertyValOut, double propertyValIn) const CV_OVERRIDE; + bool get(const VideoReaderProps propertyId, size_t& propertyVal) const CV_OVERRIDE; bool get(const int propertyId, double& propertyVal) const CV_OVERRIDE; + bool rawPackageHasKeyFrame(const size_t idx) const CV_OVERRIDE; + private: bool skipFrame(); bool aquireFrameInfo(std::pair& frameInfo, Stream& stream = Stream::Null()); @@ -298,8 +299,9 @@ namespace if (idx >= rawPacketsBaseIdx && idx < rawPacketsBaseIdx + rawPackets.size()) { if (!frame.isMat()) CV_Error(Error::StsUnsupportedFormat, "Raw data is stored on the host and must be retrieved using a cv::Mat"); - const size_t i = idx - rawPacketsBaseIdx; - Mat tmp(1, rawPackets.at(i).Size(), CV_8UC1, const_cast(rawPackets.at(i).Data()), rawPackets.at(i).Size()); + const size_t i = idx - static_cast(rawPacketsBaseIdx); + CV_Assert(rawPackets.at(i).Size() <= std::numeric_limits::max()); + Mat tmp(1, static_cast(rawPackets.at(i).Size()), CV_8UC1, const_cast(rawPackets.at(i).Data()), rawPackets.at(i).Size()); frame.getMatRef() = tmp; } } @@ -311,6 +313,8 @@ namespace case VideoReaderProps::PROP_RAW_MODE : videoSource_->SetRawMode(static_cast(propertyVal)); return true; + default: + break; } return false; } @@ -334,7 +338,7 @@ namespace return true; } - bool VideoReaderImpl::get(const VideoReaderProps propertyId, double& propertyVal) const { + bool VideoReaderImpl::get(const VideoReaderProps propertyId, size_t& propertyVal) const { switch (propertyId) { case VideoReaderProps::PROP_DECODED_FRAME_IDX: @@ -356,15 +360,6 @@ namespace case VideoReaderProps::PROP_RAW_MODE: 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()) { - propertyVal = rawPackets.at(iPacket).ContainsKeyFrame(); - return true; - } - else - break; - } case VideoReaderProps::PROP_ALLOW_FRAME_DROP: propertyVal = videoParser_->allowFrameDrops(); return true; @@ -372,13 +367,13 @@ namespace propertyVal = videoParser_->udpSource(); return true; case VideoReaderProps::PROP_COLOR_FORMAT: - propertyVal = static_cast(colorFormat); + propertyVal = static_cast(colorFormat); return true; case VideoReaderProps::PROP_BIT_DEPTH: - propertyVal = static_cast(bitDepth); + propertyVal = static_cast(bitDepth); return true; case VideoReaderProps::PROP_PLANAR: - propertyVal = static_cast(planar); + propertyVal = static_cast(planar); return true; default: break; @@ -386,11 +381,13 @@ namespace return false; } - bool VideoReaderImpl::getVideoReaderProps(const VideoReaderProps propertyId, double& propertyValOut, double propertyValIn) const { - double propertyValInOut = propertyValIn; - const bool ret = get(propertyId, propertyValInOut); - propertyValOut = propertyValInOut; - return ret; + bool VideoReaderImpl::rawPackageHasKeyFrame(const size_t idx) const { + if (idx < rawPacketsBaseIdx) return false; + const size_t iPacket = idx - rawPacketsBaseIdx; + if (videoSource_->RawModeEnabled() && iPacket < rawPackets.size()) + return rawPackets.at(iPacket).ContainsKeyFrame(); + else + return false; } bool VideoReaderImpl::get(const int propertyId, double& propertyVal) const { diff --git a/modules/cudacodec/src/video_source.hpp b/modules/cudacodec/src/video_source.hpp index f7e4c0bd15b..0d851c154fa 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 bool get(const int propertyId, double& propertyVal) const { return false; } + virtual bool get(const int, double&) const = 0; virtual int getFirstFrameIdx() const { return 0; } virtual void start() = 0; virtual void stop() = 0; diff --git a/modules/cudacodec/src/video_writer.cpp b/modules/cudacodec/src/video_writer.cpp index 9b36febda45..13c109ff6bd 100644 --- a/modules/cudacodec/src/video_writer.cpp +++ b/modules/cudacodec/src/video_writer.cpp @@ -59,6 +59,7 @@ GUID CodecGuid(const Codec codec); void FrameRate(const double fps, uint32_t& frameRateNum, uint32_t& frameRateDen); GUID EncodingProfileGuid(const EncodeProfile encodingProfile); GUID EncodingPresetGuid(const EncodePreset nvPreset); +std::string GetVideoCodecString(const GUID codec); bool operator==(const EncoderParams& lhs, const EncoderParams& rhs) { @@ -70,7 +71,7 @@ bool operator==(const EncoderParams& lhs, const EncoderParams& rhs) class FFmpegVideoWriter : public EncoderCallback { public: - FFmpegVideoWriter(const String& fileName, const Codec codec, const int fps, const Size sz, const int idrPeriod); + FFmpegVideoWriter(const String& fileName, const Codec codec, const double fps, const Size sz, const int idrPeriod); ~FFmpegVideoWriter(); void onEncoded(const std::vector>& vPacket, const std::vector& pts); void onEncodingFinished(); @@ -79,7 +80,7 @@ class FFmpegVideoWriter : public EncoderCallback cv::VideoWriter writer; }; -FFmpegVideoWriter::FFmpegVideoWriter(const String& fileName, const Codec codec, const int fps, const Size sz, const int idrPeriod) { +FFmpegVideoWriter::FFmpegVideoWriter(const String& fileName, const Codec codec, const double fps, const Size sz, const int idrPeriod) { if (!videoio_registry::hasBackend(CAP_FFMPEG)) CV_Error(Error::StsNotImplemented, "FFmpeg backend not found"); const int fourcc = codec == Codec::H264 ? cv::VideoWriter::fourcc('a', 'v', 'c', '1') : cv::VideoWriter::fourcc('h', 'v', 'c', '1'); @@ -100,7 +101,8 @@ void FFmpegVideoWriter::onEncoded(const std::vector>& vPack CV_Assert(vPacket.size() == pts.size()); for (int i = 0; i < vPacket.size(); i++){ std::vector packet = vPacket.at(i); - Mat wrappedPacket(1, packet.size(), CV_8UC1, (void*)packet.data()); + CV_Assert(packet.size() <= std::numeric_limits::max()); + Mat wrappedPacket(1, static_cast(packet.size()), CV_8UC1, (void*)packet.data()); const double ptsDouble = static_cast(pts.at(i)); CV_Assert(static_cast(ptsDouble) == pts.at(i)); CV_Assert(writer.set(VIDEOWRITER_PROP_PTS, ptsDouble)); @@ -213,7 +215,7 @@ VideoWriterImpl::VideoWriterImpl(const Ptr& encoderCallBack_, c CV_Assert(colorFormat != ColorFormat::UNDEFINED); surfaceFormat = EncBufferFormat(colorFormat); if (surfaceFormat == NV_ENC_BUFFER_FORMAT_UNDEFINED) { - String msg = cv::format("Unsupported input surface format: %i", colorFormat); + String msg = cv::format("Unsupported input surface format: %i", static_cast(colorFormat)); CV_LOG_WARNING(NULL, msg); CV_Error(Error::StsUnsupportedFormat, msg); } diff --git a/modules/cudacodec/test/test_video.cpp b/modules/cudacodec/test/test_video.cpp index deb75aafb5b..a9d171b282b 100644 --- a/modules/cudacodec/test/test_video.cpp +++ b/modules/cudacodec/test/test_video.cpp @@ -152,9 +152,9 @@ 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); - double unsupportedVal = -1; + size_t unsupportedVal = 0; ASSERT_FALSE(reader->get(cv::cudacodec::VideoReaderProps::PROP_NOT_SUPPORTED, unsupportedVal)); - double rawModeVal = -1; + size_t rawModeVal = 0; 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)); @@ -162,7 +162,7 @@ CUDA_TEST_P(CheckSet, Reader) ASSERT_TRUE(rawModeVal); bool rawPacketsAvailable = false; while (reader->grab()) { - double nRawPackages = -1; + size_t nRawPackages = 0; ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_NUMBER_OF_RAW_PACKAGES_SINCE_LAST_GRAB, nRawPackages)); if (nRawPackages > 0) { rawPacketsAvailable = true; @@ -180,17 +180,17 @@ CUDA_TEST_P(CheckExtraData, Reader) cv::cuda::setDevice(GET_PARAM(0).deviceID()); const string path = get<0>(GET_PARAM(1)); - const int sz = get<1>(GET_PARAM(1)); + const size_t sz = get<1>(GET_PARAM(1)); std::string inputFile = std::string(cvtest::TS::ptr()->get_data_path()) + "../" + path; cv::cudacodec::VideoReaderInitParams params; params.rawMode = true; cv::Ptr reader = cv::cudacodec::createVideoReader(inputFile, {}, params); - double extraDataIdx = -1; + size_t extraDataIdx = 0; ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_EXTRA_DATA_INDEX, extraDataIdx)); - ASSERT_EQ(extraDataIdx, 1 ); + ASSERT_EQ(extraDataIdx, static_cast(1) ); ASSERT_TRUE(reader->grab()); cv::Mat extraData; - const bool newData = reader->retrieve(extraData, static_cast(extraDataIdx)); + const bool newData = reader->retrieve(extraData, extraDataIdx); ASSERT_TRUE((newData && sz) || (!newData && !sz)); ASSERT_EQ(extraData.total(), sz); } @@ -208,19 +208,18 @@ CUDA_TEST_P(CheckKeyFrame, Reader) cv::cudacodec::VideoReaderInitParams params; params.rawMode = true; cv::Ptr reader = cv::cudacodec::createVideoReader(inputFile, {}, params); - double rawIdxBase = -1; + size_t rawIdxBase = 0; ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_RAW_PACKAGES_BASE_INDEX, rawIdxBase)); - ASSERT_EQ(rawIdxBase, 2); + ASSERT_EQ(rawIdxBase, static_cast(2)); constexpr int maxNPackagesToCheck = 2; int nPackages = 0; while (nPackages < maxNPackagesToCheck) { ASSERT_TRUE(reader->grab()); - double N = -1; + size_t N = 0; ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_NUMBER_OF_RAW_PACKAGES_SINCE_LAST_GRAB,N)); - for (int i = static_cast(rawIdxBase); i < static_cast(N + rawIdxBase); i++) { + for (size_t i = rawIdxBase; i < N + rawIdxBase; i++) { nPackages++; - double containsKeyFrame = i; - ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_LRF_HAS_KEY_FRAME, containsKeyFrame)); + const bool containsKeyFrame = reader->rawPackageHasKeyFrame(i); ASSERT_TRUE((nPackages == 1 && containsKeyFrame) || (nPackages == 2 && !containsKeyFrame)) << "nPackage: " << i; if (nPackages >= maxNPackagesToCheck) break; @@ -301,9 +300,7 @@ CUDA_TEST_P(DisplayResolution, Reader) readerCodedSz->set(cudacodec::ColorFormat::GRAY); GpuMat frameCodedSz; ASSERT_TRUE(readerCodedSz->nextFrame(frameCodedSz)); - const cudacodec::FormatInfo formatCodedSz = readerCodedSz->format(); - const double err = cv::cuda::norm(frame, frameCodedSz(displayArea), NORM_INF); - ASSERT_TRUE(err == 0); + ASSERT_EQ(cv::cuda::norm(frame, frameCodedSz(displayArea), NORM_INF), 0); } } @@ -331,7 +328,7 @@ CUDA_TEST_P(Video, Reader) { const std::pair< cudacodec::ColorFormat, int>& formatToChannels = formatsToChannels[i % formatsToChannels.size()]; ASSERT_TRUE(reader->set(formatToChannels.first)); - double colorFormat; + size_t colorFormat; ASSERT_TRUE(reader->get(cudacodec::VideoReaderProps::PROP_COLOR_FORMAT, colorFormat) && static_cast(colorFormat) == formatToChannels.first); ASSERT_TRUE(reader->nextFrame(frame)); const int height = formatToChannels.first == cudacodec::ColorFormat::NV_YUV_SURFACE_FORMAT ? static_cast(1.5 * fmt.height) : fmt.height; @@ -371,7 +368,7 @@ CUDA_TEST_P(ColorConversionFormat, Reader) cv::cuda::setDevice(GET_PARAM(0).deviceID()); const cudacodec::ColorFormat colorFormat = static_cast(static_cast(GET_PARAM(1))); cv::Ptr reader = cv::cudacodec::createVideoReader(inputFile); - double colorFormatGetVal; + size_t colorFormatGetVal; ASSERT_TRUE(reader->get(cudacodec::VideoReaderProps::PROP_COLOR_FORMAT, colorFormatGetVal)); ASSERT_EQ(cudacodec::ColorFormat::BGRA, static_cast(colorFormatGetVal)); reader->set(colorFormat); @@ -414,7 +411,7 @@ CUDA_TEST_P(ColorConversionPlanar, Reader) { const std::string inputFile = std::string(cvtest::TS::ptr()->get_data_path()) + "../highgui/video/big_buck_bunny.h264"; cv::Ptr reader = cv::cudacodec::createVideoReader(inputFile); - double planarGetVal; + size_t planarGetVal; ASSERT_TRUE(reader->get(cudacodec::VideoReaderProps::PROP_PLANAR, planarGetVal)); ASSERT_FALSE(static_cast(planarGetVal)); reader->set(cudacodec::ColorFormat::BGR, cudacodec::BitDepth::UNCHANGED, true); @@ -446,7 +443,7 @@ CUDA_TEST_P(ColorConversionBitdepth, Reader) cv::cuda::setDevice(GET_PARAM(0).deviceID()); const cudacodec::BitDepth bitDepth = static_cast(static_cast(GET_PARAM(1))); cv::Ptr reader = cv::cudacodec::createVideoReader(inputFile); - double bitDepthGetVal; + size_t bitDepthGetVal; ASSERT_TRUE(reader->get(cudacodec::VideoReaderProps::PROP_BIT_DEPTH, bitDepthGetVal)); ASSERT_EQ(cudacodec::BitDepth::UNCHANGED, static_cast(bitDepthGetVal)); reader->set(cudacodec::ColorFormat::BGR, bitDepth); @@ -547,8 +544,9 @@ CUDA_TEST_P(ReconfigureDecoder, Reader) ASSERT_TRUE(frame.size() == initialSize); ASSERT_TRUE(fmt.srcRoi.empty()); const bool resChanged = (initialCodedSize.width != fmt.ulWidth) || (initialCodedSize.height != fmt.ulHeight); - if (resChanged) + if (resChanged) { ASSERT_TRUE(fmt.targetRoi.empty()); + } } ASSERT_TRUE(nFrames == 40); } @@ -569,19 +567,18 @@ CUDA_TEST_P(VideoReadRaw, Reader) cv::cudacodec::VideoReaderInitParams params; params.rawMode = true; cv::Ptr reader = cv::cudacodec::createVideoReader(inputFile, {}, params); - double rawIdxBase = -1; + size_t rawIdxBase = 0; ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_RAW_PACKAGES_BASE_INDEX, rawIdxBase)); - ASSERT_EQ(rawIdxBase, 2); + ASSERT_EQ(rawIdxBase, static_cast(2)); cv::cuda::GpuMat frame; for (int i = 0; i < 100; i++) { ASSERT_TRUE(reader->grab()); ASSERT_TRUE(reader->retrieve(frame)); ASSERT_FALSE(frame.empty()); - 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 j = static_cast(rawIdxBase); j <= static_cast(N + rawIdxBase); j++) { + size_t N = 0; + ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_NUMBER_OF_RAW_PACKAGES_SINCE_LAST_GRAB, N)); + for (size_t j = rawIdxBase; j <= N + rawIdxBase; j++) { Mat rawPackets; reader->retrieve(rawPackets, j); file.write((char*)rawPackets.data, rawPackets.total()); @@ -596,9 +593,9 @@ CUDA_TEST_P(VideoReadRaw, Reader) cv::cudacodec::VideoReaderInitParams params; params.rawMode = true; cv::Ptr readerActual = cv::cudacodec::createVideoReader(fileNameOut, {}, params); - double decodedFrameIdx = -1; + size_t decodedFrameIdx = 0; ASSERT_TRUE(readerActual->get(cv::cudacodec::VideoReaderProps::PROP_DECODED_FRAME_IDX, decodedFrameIdx)); - ASSERT_EQ(decodedFrameIdx, 0); + ASSERT_EQ(decodedFrameIdx, static_cast(0)); cv::cuda::GpuMat reference, actual; cv::Mat referenceHost, actualHost; for (int i = 0; i < 100; i++) @@ -728,7 +725,7 @@ CUDA_TEST_P(CheckInitParams, Reader) params.udpSource = GET_PARAM(2); params.allowFrameDrop = GET_PARAM(3); params.rawMode = GET_PARAM(4); - double udpSource = 0, allowFrameDrop = 0, rawMode = 0; + size_t udpSource = 0, allowFrameDrop = 0, rawMode = 0; cv::Ptr reader = cv::cudacodec::createVideoReader(inputFile, {}, params); ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_UDP_SOURCE, udpSource) && static_cast(udpSource) == params.udpSource); ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_ALLOW_FRAME_DROP, allowFrameDrop) && static_cast(allowFrameDrop) == params.allowFrameDrop); @@ -961,6 +958,8 @@ void generateTestImages(Mat bgrIn, Mat& testImg, Mat& out, const cudacodec::Surf imgOut8 = imgOutFromYuv; break; } + default: + return; } Mat imgOutBitDepthOut;