Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
10e29b2
cuda: fix bug in histogram kernels when source memory is not aligned …
cudawarped Apr 19, 2023
72080b8
cudacodec::VideoReader - amend FFmpeg codec resolution
cudawarped Apr 25, 2023
cc5c276
cudacodec::VideoReader - fix cudart defines
cudawarped Jun 22, 2023
9c10a6d
Merge pull request #3488 from cudawarped:fix_cudacodec_codec_resolution
asmorkalov Jun 22, 2023
b677ac8
FFmpeg/4.x: update FFmpeg wrapper 2023.6
asmorkalov Jun 22, 2023
3d242a6
Merge pull request #3513 from cudawarped:fix_cudacodec_cudart_defines
asmorkalov Jun 22, 2023
70f8706
Merge pull request #3514 from asmorkalov:as/ffmpeg_update_4.x
asmorkalov Jun 22, 2023
4f66f86
Merge pull request #3475 from cudawarped:cuda_fix_unaligned_hist
asmorkalov Jun 27, 2023
d545bab
Fixed memory leak in EllipseDetector and Mat addressing.
asmorkalov Jun 27, 2023
f10c84d
Merge pull request #3515 from asmorkalov:as/find_ellipses_memory
asmorkalov Jun 28, 2023
e963ec2
Wstringop-overflow warning fix in bio inspired module.
asmorkalov Jul 10, 2023
cfa540e
Merge pull request #3522 from asmorkalov:as/gcc_11_warning_fix
asmorkalov Jul 11, 2023
c944ec5
Add Ubuntu 22.04 to CI.
asmorkalov Jul 11, 2023
d89b2b9
Merge pull request #3524 from asmorkalov:as/ci-ubuntu-2204
asmorkalov Jul 11, 2023
0fe30d8
Added Java bindings for dnn_superres module.
asmorkalov Jul 17, 2023
c49a420
cudacodec: return luma hist from VideoReader::nextFrame if requested
cudawarped Jun 10, 2023
9dfe233
Merge pull request #3477 from cudawarped:cudacodec_add_luma_hist
asmorkalov Jul 19, 2023
a06aece
Fixed several test failures in Python tests for CUDA modules.
asmorkalov Jul 20, 2023
4899bee
Merge pull request #3535 from asmorkalov:as/cuda_pytest_stabilization
asmorkalov Jul 20, 2023
68c708d
fix: remove using namespace cuda from public header
VadimLevin Jul 19, 2023
179021f
Merge pull request #3534 from VadimLevin:dev/vlevin/remove-using-name…
asmorkalov Jul 26, 2023
daaf645
Merge pull request #3533 from asmorkalov:as/dnn_superres_java
asmorkalov Jul 27, 2023
a9d5b85
Merge branch 4.x
asmorkalov Jul 27, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions modules/bioinspired/src/transientareassegmentationmodule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ class TransientAreasSegmentationModuleImpl : protected BasicRetinaFilter
/**
* @return the current parameters setup
*/
struct SegmentationParameters getParameters();
SegmentationParameters getParameters();

/**
* parameters setup display method
Expand Down Expand Up @@ -202,7 +202,7 @@ class TransientAreasSegmentationModuleImpl : protected BasicRetinaFilter
*/
inline const std::valarray<float> &getMotionContextPicture() const {return _contextMotionEnergy;}

struct cv::bioinspired::SegmentationParameters _segmentationParameters;
cv::bioinspired::SegmentationParameters _segmentationParameters;
// template buffers and related acess pointers
std::valarray<float> _inputToSegment;
std::valarray<float> _contextMotionEnergy;
Expand Down Expand Up @@ -233,7 +233,7 @@ class TransientAreasSegmentationModuleImpl_: public TransientAreasSegmentationM
inline virtual void setup(cv::FileStorage &fs, const bool applyDefaultSetupOnFailure) CV_OVERRIDE { _segmTool.setup(fs, applyDefaultSetupOnFailure); }
inline virtual void setup(SegmentationParameters newParameters) CV_OVERRIDE { _segmTool.setup(newParameters); }
inline virtual String printSetup() CV_OVERRIDE { return _segmTool.printSetup(); }
inline virtual struct SegmentationParameters getParameters() CV_OVERRIDE { return _segmTool.getParameters(); }
inline virtual SegmentationParameters getParameters() CV_OVERRIDE { return _segmTool.getParameters(); }
inline virtual void write( String fs ) const CV_OVERRIDE { _segmTool.write(fs); }
inline virtual void run(InputArray inputToSegment, const int channelIndex) CV_OVERRIDE { _segmTool.run(inputToSegment, channelIndex); }
inline virtual void getSegmentationPicture(OutputArray transientAreas) CV_OVERRIDE { return _segmTool.getSegmentationPicture(transientAreas); }
Expand Down Expand Up @@ -285,7 +285,7 @@ void TransientAreasSegmentationModuleImpl::clearAllBuffers()
_segmentedAreas=0;
}

struct SegmentationParameters TransientAreasSegmentationModuleImpl::getParameters()
SegmentationParameters TransientAreasSegmentationModuleImpl::getParameters()
{
return _segmentationParameters;
}
Expand Down Expand Up @@ -343,7 +343,7 @@ void TransientAreasSegmentationModuleImpl::setup(cv::FileStorage &fs, const bool
std::cout<<"Retina::setup: resetting retina with default parameters"<<std::endl;
if (applyDefaultSetupOnFailure)
{
struct cv::bioinspired::SegmentationParameters defaults;
cv::bioinspired::SegmentationParameters defaults;
setup(defaults);
}
std::cout<<"SegmentationModule::setup: wrong/unappropriate xml parameter file : error report :`n=>"<<e.what()<<std::endl;
Expand All @@ -356,7 +356,7 @@ void TransientAreasSegmentationModuleImpl::setup(cv::bioinspired::SegmentationPa
{

// copy structure contents
memcpy(&_segmentationParameters, &newParameters, sizeof(cv::bioinspired::SegmentationParameters));
_segmentationParameters = newParameters;
// apply setup
// init local motion energy extraction low pass filter
BasicRetinaFilter::setLPfilterParameters(0, newParameters.localEnergy_temporalConstant, newParameters.localEnergy_spatialConstant);
Expand Down
49 changes: 38 additions & 11 deletions modules/cudacodec/include/opencv2/cudacodec.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,6 @@

namespace cv { namespace cudacodec {

using namespace cuda; // Stream

//! @addtogroup cudacodec
//! @{

Expand Down Expand Up @@ -264,7 +262,7 @@ class CV_EXPORTS_W VideoWriter
@param stream Stream for frame pre-processing.
*/
CV_EXPORTS_W Ptr<cudacodec::VideoWriter> createVideoWriter(const String& fileName, const Size frameSize, const Codec codec = Codec::H264, const double fps = 25.0,
const ColorFormat colorFormat = ColorFormat::BGR, Ptr<EncoderCallback> encoderCallback = 0, const Stream& stream = Stream::Null());
const ColorFormat colorFormat = ColorFormat::BGR, Ptr<EncoderCallback> encoderCallback = 0, const cuda::Stream& stream = cuda::Stream::Null());

/** @brief Creates video writer.

Expand All @@ -278,7 +276,7 @@ CV_EXPORTS_W Ptr<cudacodec::VideoWriter> createVideoWriter(const String& fileNam
@param stream Stream for frame pre-processing.
*/
CV_EXPORTS_W Ptr<cudacodec::VideoWriter> createVideoWriter(const String& fileName, const Size frameSize, const Codec codec, const double fps, const ColorFormat colorFormat,
const EncoderParams& params, Ptr<EncoderCallback> encoderCallback = 0, const Stream& stream = Stream::Null());
const EncoderParams& params, Ptr<EncoderCallback> encoderCallback = 0, const cuda::Stream& stream = cuda::Stream::Null());

////////////////////////////////// Video Decoding //////////////////////////////////////////

Expand All @@ -295,7 +293,7 @@ enum ChromaFormat

/** @brief Deinterlacing mode used by decoder.
* @param Weave Weave both fields (no deinterlacing). For progressive content and for content that doesn't need deinterlacing.
* Bob Drop one field.
* @param Bob Drop one field.
* @param Adaptive Adaptive deinterlacing needs more video memory than other deinterlacing modes.
* */
enum DeinterlaceMode
Expand All @@ -305,12 +303,22 @@ enum DeinterlaceMode
Adaptive = 2
};

/** @brief Utility function demonstrating how to map the luma histogram when FormatInfo::videoFullRangeFlag == false
@param hist Luma histogram \a hist returned from VideoReader::nextFrame(GpuMat& frame, GpuMat& hist, Stream& stream).
@param histFull Host histogram equivelent to downloading \a hist after calling cuda::calcHist(InputArray frame, OutputArray hist, Stream& stream).

@note
- This function demonstrates how to map the luma histogram back so that it is equivalent to the result obtained from cuda::calcHist()
if the returned frame was colorFormat::GRAY.
*/
CV_EXPORTS_W void MapHist(const cuda::GpuMat& hist, CV_OUT Mat& histFull);

/** @brief Struct providing information about video file format. :
*/
struct CV_EXPORTS_W_SIMPLE FormatInfo
{
CV_WRAP FormatInfo() : nBitDepthMinus8(-1), nBitDepthChromaMinus8(-1), ulWidth(0), ulHeight(0), width(0), height(0), ulMaxWidth(0), ulMaxHeight(0), valid(false),
fps(0), ulNumDecodeSurfaces(0), videoFullRangeFlag(false) {};
CV_WRAP FormatInfo() : nBitDepthMinus8(-1), ulWidth(0), ulHeight(0), width(0), height(0), ulMaxWidth(0), ulMaxHeight(0), valid(false),
fps(0), ulNumDecodeSurfaces(0), videoFullRangeFlag(false), enableHistogram(false), nCounterBitDepth(0), nMaxHistogramBins(0){};

CV_PROP_RW Codec codec;
CV_PROP_RW ChromaFormat chromaFormat;
Expand All @@ -331,6 +339,9 @@ struct CV_EXPORTS_W_SIMPLE FormatInfo
CV_PROP_RW cv::Rect srcRoi;//!< Region of interest decoded from video source.
CV_PROP_RW cv::Rect targetRoi;//!< Region of interest in the output frame containing the decoded frame.
CV_PROP_RW bool videoFullRangeFlag;//!< Output value indicating 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. Internally the conversion from NV12 to BGR obeys ITU 709.
CV_PROP_RW bool enableHistogram;//!< Flag requesting histogram output if supported. Exception will be thrown when requested but not supported.
CV_PROP_RW int nCounterBitDepth;//!< Bit depth of histogram bins if histogram output is requested and supported.
CV_PROP_RW int nMaxHistogramBins;//!< Max number of histogram bins if histogram output is requested and supported.
};

/** @brief cv::cudacodec::VideoReader generic properties identifier.
Expand Down Expand Up @@ -374,7 +385,21 @@ class CV_EXPORTS_W VideoReader
If no frames have been grabbed (there are no more frames in video file), the methods return false.
The method throws an Exception if error occurs.
*/
CV_WRAP virtual bool nextFrame(CV_OUT GpuMat& frame, Stream &stream = Stream::Null()) = 0;
CV_WRAP virtual bool nextFrame(CV_OUT cuda::GpuMat& frame, cuda::Stream &stream = cuda::Stream::Null()) = 0;

/** @brief Grabs, decodes and returns the next video frame and frame luma histogram.

@param [out] frame The video frame.
@param [out] histogram Histogram of the luma component of the encoded frame, see note.
@param stream Stream for the asynchronous version.
@return `false` if no frames have been grabbed.

If no frames have been grabbed (there are no more frames in video file), the methods return false.
The method throws an Exception if error occurs.

@note Histogram data is collected by NVDEC during the decoding process resulting in zero performance penalty. NVDEC computes the histogram data for only the luma component of decoded output, not on post-processed frame(i.e. when scaling, cropping, etc. applied). If the source is encoded using a limited range of luma values (FormatInfo::videoFullRangeFlag == false) then the histogram bin values will correspond to to this limited range of values and will need to be mapped to contain the same output as cuda::calcHist(). The MapHist() utility function can be used to perform this mapping on the host if required.
*/
CV_WRAP_AS(nextFrameWithHist) virtual bool nextFrame(CV_OUT cuda::GpuMat& frame, CV_OUT cuda::GpuMat& histogram, cuda::Stream& stream = cuda::Stream::Null()) = 0;

/** @brief Returns information about video file format.
*/
Expand All @@ -391,7 +416,7 @@ class CV_EXPORTS_W VideoReader
The primary use of the function is for reading both the encoded and decoded video data when rawMode is enabled. With rawMode enabled
retrieve() can be called following grab() to retrieve all the data associated with the current video source since the last call to grab() or the creation of the VideoReader.
*/
CV_WRAP virtual bool grab(Stream& stream = Stream::Null()) = 0;
CV_WRAP virtual bool grab(cuda::Stream& stream = cuda::Stream::Null()) = 0;

/** @brief Returns previously grabbed video data.

Expand Down Expand Up @@ -430,7 +455,7 @@ class CV_EXPORTS_W VideoReader
The method returns data associated with the current video source since the last call to grab(). If no data is present
the method returns false and the function returns an empty image.
*/
CV_WRAP inline bool retrieve(CV_OUT GpuMat& frame) const {
CV_WRAP inline bool retrieve(CV_OUT cuda::GpuMat& frame) const {
return retrieve(OutputArray(frame));
}

Expand Down Expand Up @@ -535,16 +560,18 @@ but it cannot go below the number determined by NVDEC.
@param srcRoi Region of interest (x/width should be multiples of 4 and y/height multiples of 2) decoded from video source, defaults to the full frame.
@param targetRoi Region of interest (x/width should be multiples of 4 and y/height multiples of 2) within the output frame to copy and resize the decoded frame to,
defaults to the full frame.
@param enableHistogram Request output of decoded luma histogram \a hist from VideoReader::nextFrame(GpuMat& frame, GpuMat& hist, Stream& stream), if hardware supported.
*/
struct CV_EXPORTS_W_SIMPLE VideoReaderInitParams {
CV_WRAP VideoReaderInitParams() : udpSource(false), allowFrameDrop(false), minNumDecodeSurfaces(0), rawMode(0) {};
CV_WRAP VideoReaderInitParams() : udpSource(false), allowFrameDrop(false), minNumDecodeSurfaces(0), rawMode(0), enableHistogram(false){};
CV_PROP_RW bool udpSource;
CV_PROP_RW bool allowFrameDrop;
CV_PROP_RW int minNumDecodeSurfaces;
CV_PROP_RW bool rawMode;
CV_PROP_RW cv::Size targetSz;
CV_PROP_RW cv::Rect srcRoi;
CV_PROP_RW cv::Rect targetRoi;
CV_PROP_RW bool enableHistogram;
};

/** @brief Creates video reader.
Expand Down
47 changes: 35 additions & 12 deletions modules/cudacodec/misc/python/test/test_cudacodec.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,43 +14,59 @@ def setUp(self):
@unittest.skipIf('OPENCV_TEST_DATA_PATH' not in os.environ,
"OPENCV_TEST_DATA_PATH is not defined")
def test_reader(self):
#Test the functionality but not the results of the video reader
# Test the functionality but not the results of the VideoReader

vid_path = os.environ['OPENCV_TEST_DATA_PATH'] + '/cv/video/1920x1080.avi'
vid_path = os.environ['OPENCV_TEST_DATA_PATH'] + '/highgui/video/big_buck_bunny.h264'
try:
reader = cv.cudacodec.createVideoReader(vid_path)
format_info = reader.format()
ret, gpu_mat = reader.nextFrame()
self.assertTrue(ret)
self.assertTrue('GpuMat' in str(type(gpu_mat)), msg=type(gpu_mat))
self.assertTrue(isinstance(gpu_mat, cv.cuda.GpuMat), msg=type(gpu_mat))
#TODO: print(cv.utils.dumpInputArray(gpu_mat)) # - no support for GpuMat

# Retrieve format info
if(not format_info.valid):
format_info = reader.format()
sz = gpu_mat.size()
self.assertTrue(sz[0] == format_info.width and sz[1] == format_info.height)

# not checking output, therefore sepearate tests for different signatures is unecessary
ret, _gpu_mat2 = reader.nextFrame(gpu_mat)
#TODO: self.assertTrue(gpu_mat == gpu_mat2)
self.assertTrue(ret)
ret, gpu_mat_ = reader.nextFrame(gpu_mat)
self.assertTrue(ret and gpu_mat_.cudaPtr() == gpu_mat.cudaPtr())

# Pass VideoReaderInitParams to the decoder and initialization params to the source (cv::VideoCapture)
params = cv.cudacodec.VideoReaderInitParams()
params.rawMode = True
params.enableHistogram = False
ms_gs = 1234
post_processed_sz = (gpu_mat.size()[0]*2, gpu_mat.size()[1]*2)
params.targetSz = post_processed_sz
reader = cv.cudacodec.createVideoReader(vid_path,[cv.CAP_PROP_OPEN_TIMEOUT_MSEC, ms_gs], params)
ret, ms = reader.get(cv.CAP_PROP_OPEN_TIMEOUT_MSEC)
self.assertTrue(ret and ms == ms_gs)
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())

# Check post processing applied
self.assertTrue(gpu_mat.size() == post_processed_sz)

# 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
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())
Expand All @@ -75,8 +91,14 @@ def test_reader(self):
else:
self.skipTest(e.err)

def test_writer_existence(self):
#Test at least the existence of wrapped functions for now
def test_map_histogram(self):
hist = cv.cuda_GpuMat((1,256), cv.CV_8UC1)
hist.setTo(1)
hist_host = cv.cudacodec.MapHist(hist)
self.assertTrue(hist_host.shape == (256, 1) and isinstance(hist_host, np.ndarray))

def test_writer(self):
# Test the functionality but not the results of the VideoWriter

try:
fd, fname = tempfile.mkstemp(suffix=".h264")
Expand All @@ -91,16 +113,17 @@ def test_writer_existence(self):
writer.write(blankFrameIn)
writer.release()
encoder_params_out = writer.getEncoderParams()
self.assert_true(encoder_params_in.gopLength == encoder_params_out.gopLength)
self.assertTrue(encoder_params_in.gopLength == encoder_params_out.gopLength)
cap = cv.VideoCapture(fname,cv.CAP_FFMPEG)
self.assert_true(cap.isOpened())
self.assertTrue(cap.isOpened())
ret, blankFrameOut = cap.read()
self.assert_true(ret and blankFrameOut.shape == blankFrameIn.download().shape)
self.assertTrue(ret and blankFrameOut.shape == blankFrameIn.download().shape)
cap.release()
except cv.error as e:
self.assertEqual(e.code, cv.Error.StsNotImplemented)
self.skipTest("Either NVCUVENC or a GPU hardware encoder is missing or the encoding profile is not supported.")

os.remove(fname)

if __name__ == '__main__':
NewOpenCVTests.bootstrap()
NewOpenCVTests.bootstrap()
32 changes: 29 additions & 3 deletions modules/cudacodec/src/ffmpeg_video_source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,10 @@ static std::string fourccToString(int fourcc)
(i32_c.c[3] >= ' ' && i32_c.c[3] < 128) ? i32_c.c[3] : '?');
}

// handle old FFmpeg backend - remove when windows shared library is updated
#ifdef _WIN32
static
Codec FourccToCodec(int codec)
Codec FourccToCodecWin32Old(int codec)
{
switch (codec)
{
Expand Down Expand Up @@ -100,9 +102,34 @@ Codec FourccToCodec(int codec)
case CV_FOURCC_MACRO('a', 'v', '0', '1'): // fallthru
case CV_FOURCC_MACRO('A', 'V', '0', '1'): return AV1;
default:
break;
return NumCodecs;
}
}
#endif

static
Codec FourccToCodec(int codec)
{
#ifdef _WIN32 // handle old FFmpeg backend - remove when windows shared library is updated
Codec win32OldCodec = FourccToCodecWin32Old(codec);
if(win32OldCodec != NumCodecs)
return win32OldCodec;
#endif
switch (codec)
{
case CV_FOURCC_MACRO('m', 'p', 'g', '1'): return MPEG1;
case CV_FOURCC_MACRO('m', 'p', 'g', '2'): return MPEG2;
case CV_FOURCC_MACRO('F', 'M', 'P', '4'): return MPEG4;
case CV_FOURCC_MACRO('W', 'V', 'C', '1'): return VC1;
case CV_FOURCC_MACRO('h', '2', '6', '4'): return H264;
case CV_FOURCC_MACRO('h', 'e', 'v', 'c'): return HEVC;
case CV_FOURCC_MACRO('M', 'J', 'P', 'G'): return JPEG;
case CV_FOURCC_MACRO('V', 'P', '8', '0'): return VP8;
case CV_FOURCC_MACRO('V', 'P', '9', '0'): return VP9;
case CV_FOURCC_MACRO('A', 'V', '0', '1'): return AV1;
default:
break;
}
std::string msg = cv::format("Unknown codec FOURCC: 0x%08X (%s)", codec, fourccToString(codec).c_str());
CV_LOG_WARNING(NULL, msg);
CV_Error(Error::StsUnsupportedFormat, msg);
Expand Down Expand Up @@ -163,7 +190,6 @@ cv::cudacodec::detail::FFmpegVideoSource::FFmpegVideoSource(const String& fname,

int codec = (int)cap.get(CAP_PROP_FOURCC);
int pixelFormat = (int)cap.get(CAP_PROP_CODEC_PIXEL_FORMAT);

format_.codec = FourccToCodec(codec);
format_.height = cap.get(CAP_PROP_FRAME_HEIGHT);
format_.width = cap.get(CAP_PROP_FRAME_WIDTH);
Expand Down
Loading