Skip to content

Commit d7c3402

Browse files
committed
wip
1 parent 2526e88 commit d7c3402

File tree

4 files changed

+82
-16
lines changed

4 files changed

+82
-16
lines changed

modules/cudacodec/include/opencv2/cudacodec.hpp

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,7 @@ struct CV_EXPORTS_W_SIMPLE FormatInfo
336336
/** @brief cv::cudacodec::VideoReader generic properties identifier.
337337
*/
338338
enum class VideoReaderProps {
339+
PROP_DECODED_FRAME_IDX = 0, //!< Index for retrieving the decoded frame using retrieve().
339340
PROP_EXTRA_DATA_INDEX = 1, //!< Index for retrieving the extra data associated with a video source using retrieve().
340341
PROP_RAW_PACKAGES_BASE_INDEX = 2, //!< Base index for retrieving raw encoded data using retrieve().
341342
PROP_NUMBER_OF_RAW_PACKAGES_SINCE_LAST_GRAB = 3, //!< Number of raw packages recieved since the last call to grab().
@@ -378,9 +379,36 @@ class CV_EXPORTS_W VideoReader
378379
*/
379380
CV_WRAP virtual FormatInfo format() const = 0;
380381

382+
/** @brief Grabs the next frame from the video source.
383+
384+
@param stream Stream for the asynchronous version.
385+
@return `true` (non-zero) in the case of success.
386+
387+
The method/function grabs the next frame from video file or camera and returns true (non-zero) in
388+
the case of success.
389+
390+
The primary use of the function is for reading both the encoded and decoded video data when rawMode is enabled. With rawMode enabled
391+
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.
392+
*/
393+
CV_WRAP virtual bool grab(Stream& stream = Stream::Null()) = 0;
394+
381395
/** @brief Returns previously grabbed video data.
382396
383397
@param [out] frame The returned data which depends on the provided idx.
398+
@param idx Determines the returned data inside image. The returned data can be the:
399+
- Decoded frame, idx = get(PROP_DECODED_FRAME_IDX).
400+
- Extra data if available, idx = get(PROP_EXTRA_DATA_INDEX).
401+
- Raw encoded data package. To retrieve package i, idx = get(PROP_RAW_PACKAGES_BASE_INDEX) + i with i < get(PROP_NUMBER_OF_RAW_PACKAGES_SINCE_LAST_GRAB)
402+
@return `false` if no frames have been grabbed
403+
404+
The method returns data associated with the current video source since the last call to grab() or the creation of the VideoReader. If no data is present
405+
the method returns false and the function returns an empty image.
406+
*/
407+
virtual bool retrieve(OutputArray frame, const size_t idx = static_cast<size_t>(VideoReaderProps::PROP_DECODED_FRAME_IDX)) const = 0;
408+
409+
/** @brief Returns previously grabbed encoded video data.
410+
411+
@param [out] frame The encoded video data.
384412
@param idx Determines the returned data inside image. The returned data can be the:
385413
- Extra data if available, idx = get(PROP_EXTRA_DATA_INDEX).
386414
- Raw encoded data package. To retrieve package i, idx = get(PROP_RAW_PACKAGES_BASE_INDEX) + i with i < get(PROP_NUMBER_OF_RAW_PACKAGES_SINCE_LAST_GRAB)
@@ -389,7 +417,21 @@ class CV_EXPORTS_W VideoReader
389417
The method returns data associated with the current video source since the last call to grab() or the creation of the VideoReader. If no data is present
390418
the method returns false and the function returns an empty image.
391419
*/
392-
CV_WRAP virtual bool retrieve(OutputArray frame, const size_t idx) const = 0;
420+
CV_WRAP inline bool retrieve(CV_OUT Mat& frame, const size_t idx) const {
421+
return retrieve(OutputArray(frame), idx);
422+
}
423+
424+
/** @brief Returns the next video frame.
425+
426+
@param [out] frame The video frame. If grab() has not been called then this will be empty().
427+
@return `false` if no frames have been grabbed
428+
429+
The method returns data associated with the current video source since the last call to grab(). If no data is present
430+
the method returns false and the function returns an empty image.
431+
*/
432+
CV_WRAP inline bool retrieve(CV_OUT GpuMat& frame) const {
433+
return retrieve(OutputArray(frame));
434+
}
393435

394436
/** @brief Sets a property in the VideoReader.
395437

modules/cudacodec/misc/python/test/test_cudacodec.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ def test_reader(self):
5555
self.assertTrue(ret and i_base == 2.0)
5656
ret, gpu_mat3 = reader.nextFrame()
5757
self.assertTrue(ret and isinstance(gpu_mat3,cv.cuda.GpuMat) and not gpu_mat3.empty())
58+
ret = reader.retrieve(gpu_mat3)
59+
self.assertTrue(ret and isinstance(gpu_mat3,cv.cuda.GpuMat) and not gpu_mat3.empty())
5860
ret, n_raw_packages_since_last_grab = reader.getVideoReaderProps(cv.cudacodec.VideoReaderProps_PROP_NUMBER_OF_RAW_PACKAGES_SINCE_LAST_GRAB)
5961
self.assertTrue(ret and n_raw_packages_since_last_grab > 0)
6062
self.assertTrue(reader.rawPackageHasKeyFrame(int(i_base)))

modules/cudacodec/src/video_reader.cpp

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,8 @@ namespace
121121

122122
FormatInfo format() const CV_OVERRIDE;
123123

124+
bool grab(Stream& stream) CV_OVERRIDE;
125+
124126
bool retrieve(OutputArray frame, const size_t idx) const CV_OVERRIDE;
125127

126128
bool set(const VideoReaderProps propertyId, const double propertyVal) CV_OVERRIDE;
@@ -134,6 +136,7 @@ namespace
134136
bool rawPackageHasKeyFrame(const size_t idx) const CV_OVERRIDE;
135137

136138
private:
139+
bool internalGrab(GpuMat& frame, Stream& stream);
137140
void waitForDecoderInit();
138141

139142
Ptr<VideoSource> videoSource_;
@@ -204,7 +207,7 @@ namespace
204207
CUvideoctxlock m_lock;
205208
};
206209

207-
bool VideoReaderImpl::nextFrame(GpuMat& frame, Stream& stream) {
210+
bool VideoReaderImpl::internalGrab(GpuMat& frame, Stream& stream) {
208211
if (videoParser_->hasError())
209212
CV_Error(Error::StsError, "Parsing/Decoding video source failed, check GPU memory is available and GPU supports hardware decoding.");
210213

@@ -272,8 +275,17 @@ namespace
272275
return true;
273276
}
274277

278+
bool VideoReaderImpl::grab(Stream& stream) {
279+
return internalGrab(lastFrame, stream);
280+
}
281+
275282
bool VideoReaderImpl::retrieve(OutputArray frame, const size_t idx) const {
276-
if (idx == extraDataIdx) {
283+
if (idx == decodedFrameIdx) {
284+
if (!frame.isGpuMat())
285+
CV_Error(Error::StsUnsupportedFormat, "Decoded frame is stored on the device and must be retrieved using a cv::cuda::GpuMat");
286+
frame.getGpuMatRef() = lastFrame;
287+
}
288+
else if (idx == extraDataIdx) {
277289
if (!frame.isMat())
278290
CV_Error(Error::StsUnsupportedFormat, "Extra data is stored on the host and must be retrieved using a cv::Mat");
279291
videoSource_->getExtraData(frame.getMatRef());
@@ -326,6 +338,9 @@ namespace
326338
bool VideoReaderImpl::get(const VideoReaderProps propertyId, size_t& propertyVal) const {
327339
switch (propertyId)
328340
{
341+
case VideoReaderProps::PROP_DECODED_FRAME_IDX:
342+
propertyVal = decodedFrameIdx;
343+
return true;
329344
case VideoReaderProps::PROP_EXTRA_DATA_INDEX:
330345
propertyVal = extraDataIdx;
331346
return true;
@@ -369,6 +384,13 @@ namespace
369384
bool VideoReaderImpl::get(const int propertyId, double& propertyVal) const {
370385
return videoSource_->get(propertyId, propertyVal);
371386
}
387+
388+
bool VideoReaderImpl::nextFrame(GpuMat& frame, Stream& stream)
389+
{
390+
if (!internalGrab(frame, stream))
391+
return false;
392+
return true;
393+
}
372394
}
373395

374396
Ptr<VideoReader> cv::cudacodec::createVideoReader(const String& filename, const std::vector<int>& sourceParams, const VideoReaderInitParams params)

modules/cudacodec/test/test_video.cpp

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -132,9 +132,8 @@ CUDA_TEST_P(CheckSet, Reader)
132132
ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_RAW_MODE, rawModeVal));
133133
ASSERT_TRUE(rawModeVal);
134134
bool rawPacketsAvailable = false;
135-
GpuMat frame;
136-
while (reader->nextFrame(frame)) {
137-
size_t nRawPackages = 0;
135+
while (reader->grab()) {
136+
double nRawPackages = -1;
138137
ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_NUMBER_OF_RAW_PACKAGES_SINCE_LAST_GRAB, nRawPackages));
139138
if (nRawPackages > 0) {
140139
rawPacketsAvailable = true;
@@ -160,8 +159,7 @@ CUDA_TEST_P(CheckExtraData, Reader)
160159
size_t extraDataIdx = 0;
161160
ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_EXTRA_DATA_INDEX, extraDataIdx));
162161
ASSERT_EQ(extraDataIdx, static_cast<size_t>(1) );
163-
GpuMat frame;
164-
ASSERT_TRUE(reader->nextFrame(frame));
162+
ASSERT_TRUE(reader->grab());
165163
cv::Mat extraData;
166164
const bool newData = reader->retrieve(extraData, extraDataIdx);
167165
ASSERT_TRUE((newData && sz) || (!newData && !sz));
@@ -186,9 +184,8 @@ CUDA_TEST_P(CheckKeyFrame, Reader)
186184
ASSERT_EQ(rawIdxBase, static_cast<size_t>(2));
187185
constexpr int maxNPackagesToCheck = 2;
188186
int nPackages = 0;
189-
GpuMat frame;
190187
while (nPackages < maxNPackagesToCheck) {
191-
ASSERT_TRUE(reader->nextFrame(frame));
188+
ASSERT_TRUE(reader->grab());
192189
size_t N = 0;
193190
ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_NUMBER_OF_RAW_PACKAGES_SINCE_LAST_GRAB,N));
194191
for (size_t i = rawIdxBase; i < N + rawIdxBase; i++) {
@@ -441,7 +438,8 @@ CUDA_TEST_P(VideoReadRaw, Reader)
441438
cv::cuda::GpuMat frame;
442439
for (int i = 0; i < 100; i++)
443440
{
444-
ASSERT_TRUE(reader->nextFrame(frame));
441+
ASSERT_TRUE(reader->grab());
442+
ASSERT_TRUE(reader->retrieve(frame));
445443
ASSERT_FALSE(frame.empty());
446444
size_t N = 0;
447445
ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_NUMBER_OF_RAW_PACKAGES_SINCE_LAST_GRAB, N));
@@ -460,12 +458,16 @@ CUDA_TEST_P(VideoReadRaw, Reader)
460458
cv::cudacodec::VideoReaderInitParams params;
461459
params.rawMode = true;
462460
cv::Ptr<cv::cudacodec::VideoReader> readerActual = cv::cudacodec::createVideoReader(fileNameOut, {}, params);
461+
double decodedFrameIdx = -1;
462+
ASSERT_TRUE(readerActual->get(cv::cudacodec::VideoReaderProps::PROP_DECODED_FRAME_IDX, decodedFrameIdx));
463+
ASSERT_EQ(decodedFrameIdx, 0);
463464
cv::cuda::GpuMat reference, actual;
464465
cv::Mat referenceHost, actualHost;
465466
for (int i = 0; i < 100; i++)
466467
{
467468
ASSERT_TRUE(readerReference->nextFrame(reference));
468-
ASSERT_TRUE(readerActual->nextFrame(actual));
469+
ASSERT_TRUE(readerActual->grab());
470+
ASSERT_TRUE(readerActual->retrieve(actual, static_cast<size_t>(decodedFrameIdx)));
469471
actual.download(actualHost);
470472
reference.download(referenceHost);
471473
ASSERT_TRUE(cvtest::norm(actualHost, referenceHost, NORM_INF) == 0);
@@ -541,8 +543,7 @@ CUDA_TEST_P(CheckDecodeSurfaces, Reader)
541543
cv::Ptr<cv::cudacodec::VideoReader> reader = cv::cudacodec::createVideoReader(inputFile, {}, params);
542544
cv::cudacodec::FormatInfo fmt = reader->format();
543545
ASSERT_TRUE(fmt.ulNumDecodeSurfaces == ulNumDecodeSurfaces);
544-
GpuMat frame;
545-
for (int i = 0; i < 100; i++) ASSERT_TRUE(reader->nextFrame(frame));
546+
for (int i = 0; i < 100; i++) ASSERT_TRUE(reader->grab());
546547
}
547548

548549
{
@@ -551,8 +552,7 @@ CUDA_TEST_P(CheckDecodeSurfaces, Reader)
551552
cv::Ptr<cv::cudacodec::VideoReader> reader = cv::cudacodec::createVideoReader(inputFile, {}, params);
552553
cv::cudacodec::FormatInfo fmt = reader->format();
553554
ASSERT_TRUE(fmt.ulNumDecodeSurfaces == ulNumDecodeSurfaces + 1);
554-
GpuMat frame;
555-
for (int i = 0; i < 100; i++) ASSERT_TRUE(reader->nextFrame(frame));
555+
for (int i = 0; i < 100; i++) ASSERT_TRUE(reader->grab());
556556
}
557557
}
558558

0 commit comments

Comments
 (0)