From f552db23d9dbf4e05e6626c691d0a35e566a5074 Mon Sep 17 00:00:00 2001 From: cudawarped <12133430+cudawarped@users.noreply.github.com> Date: Tue, 21 Oct 2025 17:11:09 +0300 Subject: [PATCH] Expose NVSurfaceToColorConverter::convert to python and remove unecessary videoFullRangeFlag argument. --- modules/cudacodec/include/opencv2/cudacodec.hpp | 3 +-- .../cudacodec/misc/python/test/test_cudacodec.py | 14 +++++++++++--- .../nvidia_surface_format_to_color_converter.cpp | 7 +++++-- modules/cudacodec/src/video_reader.cpp | 8 ++++---- modules/cudacodec/test/test_video.cpp | 2 +- 5 files changed, 22 insertions(+), 12 deletions(-) diff --git a/modules/cudacodec/include/opencv2/cudacodec.hpp b/modules/cudacodec/include/opencv2/cudacodec.hpp index 35f5b28cc83..1a83c57d6d5 100644 --- a/modules/cudacodec/include/opencv2/cudacodec.hpp +++ b/modules/cudacodec/include/opencv2/cudacodec.hpp @@ -392,10 +392,9 @@ class CV_EXPORTS_W NVSurfaceToColorConverter { * @param outputFormat The requested output color format. * @param bitDepth The requested bit depth of the output frame. * @param planar Request seperate planes for each color plane. - * @param videoFullRangeFlag Indicates if the black level, luma and chroma of the source are represented using the full or limited range (AKA TV or "analogue" range) of values as defined in Annex E of the ITU-T Specification. * @param stream Stream for the asynchronous version. */ - virtual bool convert(InputArray yuv, OutputArray color, const SurfaceFormat surfaceFormat, const ColorFormat outputFormat, const BitDepth bitDepth = BitDepth::UNCHANGED, const bool planar = false, const bool videoFullRangeFlag = false, cuda::Stream& stream = cuda::Stream::Null()) = 0; + CV_WRAP virtual bool convert(InputArray yuv, OutputArray color, const SurfaceFormat surfaceFormat, const ColorFormat outputFormat, const BitDepth bitDepth = BitDepth::UNCHANGED, const bool planar = false, cuda::Stream& stream = cuda::Stream::Null()) = 0; }; /** @brief Creates a NVSurfaceToColorConverter. diff --git a/modules/cudacodec/misc/python/test/test_cudacodec.py b/modules/cudacodec/misc/python/test/test_cudacodec.py index cf20daeb181..6c22b57251b 100644 --- a/modules/cudacodec/misc/python/test/test_cudacodec.py +++ b/modules/cudacodec/misc/python/test/test_cudacodec.py @@ -60,8 +60,8 @@ def test_reader(self): # 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) @@ -91,6 +91,14 @@ def test_reader(self): else: self.skipTest(e.err) + def test_NVSurfaceToColorConverter(self): + converter = cv.cudacodec.createNVSurfaceToColorConverter(cv.cudacodec.ColorSpaceStandard_BT601,False) + bgr_sz = (1920,1080) + nv12_sz = (1920, int(1.5*1080)) + blank_nv12_frame = cv.cuda.GpuMat(nv12_sz,cv.CV_8U) + ret, bgr = converter.convert(blank_nv12_frame, cv.cudacodec.SF_NV12, cv.cudacodec.BGR) + self.assertTrue(ret == True and bgr.size() == bgr_sz) + def test_map_histogram(self): hist = cv.cuda_GpuMat((1,256), cv.CV_8UC1) hist.setTo(1) @@ -107,7 +115,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/nvidia_surface_format_to_color_converter.cpp b/modules/cudacodec/src/nvidia_surface_format_to_color_converter.cpp index ae5805094f1..c04b22b8a7e 100644 --- a/modules/cudacodec/src/nvidia_surface_format_to_color_converter.cpp +++ b/modules/cudacodec/src/nvidia_surface_format_to_color_converter.cpp @@ -154,7 +154,9 @@ void SetMatYuv2Rgb(int iMatrix, ColorMatrix& matYuv2Color, bool fullRange = fals class NVSurfaceToColorConverterImpl : public NVSurfaceToColorConverter { public: - NVSurfaceToColorConverterImpl(ColorSpaceStandard colorSpace, bool fullColorRange = false) { + NVSurfaceToColorConverterImpl(ColorSpaceStandard colorSpace, bool fullColorRange = false) : + videoFullRangeFlag(fullColorRange) + { SetMatYuv2Rgb(static_cast(colorSpace), matYuv2Color, fullColorRange); } @@ -194,7 +196,7 @@ class NVSurfaceToColorConverterImpl : public NVSurfaceToColorConverter { } } - bool convert(const InputArray yuv, const OutputArray out, const SurfaceFormat surfaceFormat, const ColorFormat outputFormat, const BitDepth bitDepth, const bool planar, const bool videoFullRangeFlag, cuda::Stream& stream) { + bool convert(const InputArray yuv, const OutputArray out, const SurfaceFormat surfaceFormat, const ColorFormat outputFormat, const BitDepth bitDepth, const bool planar, cuda::Stream& stream) { CV_Assert(outputFormat == ColorFormat::BGR || outputFormat == ColorFormat::BGRA || outputFormat == ColorFormat::RGB || outputFormat == ColorFormat::RGBA || outputFormat == ColorFormat::GRAY); CV_Assert(yuv.depth() == CV_8U || yuv.depth() == CV_16U); const bool yuv420 = surfaceFormat == SurfaceFormat::SF_NV12 || surfaceFormat == SurfaceFormat::SF_P016; @@ -341,6 +343,7 @@ class NVSurfaceToColorConverterImpl : public NVSurfaceToColorConverter { private: ColorMatrix matYuv2Color; + bool videoFullRangeFlag; }; Ptr cv::cudacodec::createNVSurfaceToColorConverter(const ColorSpaceStandard colorSpace, const bool videoFullRangeFlag) { diff --git a/modules/cudacodec/src/video_reader.cpp b/modules/cudacodec/src/video_reader.cpp index 28bbc113163..d4465eb49a7 100644 --- a/modules/cudacodec/src/video_reader.cpp +++ b/modules/cudacodec/src/video_reader.cpp @@ -92,7 +92,7 @@ namespace void releaseFrameInfo(const std::pair& frameInfo); bool internalGrab(GpuMat & frame, GpuMat & histogram, Stream & stream); void waitForDecoderInit(); - void cvtFromYuv(const GpuMat& decodedFrame, GpuMat& outFrame, const SurfaceFormat surfaceFormat, const bool videoFullRangeFlag, Stream& stream); + void cvtFromYuv(const GpuMat& decodedFrame, GpuMat& outFrame, const SurfaceFormat surfaceFormat, Stream& stream); Ptr videoSource_; @@ -260,7 +260,7 @@ namespace cuSafeCall(cuMemcpyDtoDAsync((CUdeviceptr)(histogram.data), cuHistogramPtr, histogramSz, StreamAccessor::getStream(stream))); } - cvtFromYuv(decodedFrame, frame, videoDecoder_->format().surfaceFormat, videoDecoder_->format().videoFullRangeFlag, stream); + cvtFromYuv(decodedFrame, frame, videoDecoder_->format().surfaceFormat, stream); // unmap video frame // unmapFrame() synchronizes with the VideoDecode API (ensures the frame has finished decoding) videoDecoder_->unmapFrame(decodedFrame); @@ -414,13 +414,13 @@ namespace return true; } - void VideoReaderImpl::cvtFromYuv(const GpuMat& decodedFrame, GpuMat& outFrame, const SurfaceFormat surfaceFormat, const bool videoFullRangeFlag, Stream& stream) + void VideoReaderImpl::cvtFromYuv(const GpuMat& decodedFrame, GpuMat& outFrame, const SurfaceFormat surfaceFormat, Stream& stream) { if (colorFormat == ColorFormat::NV_YUV_SURFACE_FORMAT) { decodedFrame.copyTo(outFrame, stream); return; } - yuvConverter->convert(decodedFrame, outFrame, surfaceFormat, colorFormat, bitDepth, planar, videoFullRangeFlag, stream); + yuvConverter->convert(decodedFrame, outFrame, surfaceFormat, colorFormat, bitDepth, planar, stream); } } diff --git a/modules/cudacodec/test/test_video.cpp b/modules/cudacodec/test/test_video.cpp index 791be89d7ae..aba3526db2f 100644 --- a/modules/cudacodec/test/test_video.cpp +++ b/modules/cudacodec/test/test_video.cpp @@ -998,7 +998,7 @@ CUDA_TEST_P(YuvConverter, Reader) Mat nv12Interleaved, bgrFromYuv; generateTestImages(bgr, nv12Interleaved, bgrFromYuv, surfaceFormat, outputFormat, bitDepth, planar, fullRange); GpuMat nv12Device(nv12Interleaved), bgrDevice(bgrFromYuv.size(), bgrFromYuv.type()); - yuvConverter->convert(nv12Device, bgrDevice, surfaceFormat, outputFormat, bitDepth, planar, fullRange); + yuvConverter->convert(nv12Device, bgrDevice, surfaceFormat, outputFormat, bitDepth, planar); bgrDevice.download(bgrHost); EXPECT_MAT_NEAR(bgrFromYuv, bgrHost, bitDepth == cudacodec::BitDepth::EIGHT ? 2 :512); }