Skip to content

Commit 758c1a9

Browse files
authored
Merge pull request #3139 from cudawarped:pass_videocapture_params_to_videoreader
Pass cv::VideoCaptureProperties to VideoReader FFmpeg source * 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. * 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. * Prevent, fall back to CuvidVideoSource if VideoCapture params are passed and initialization fails and add test for this. * Remove magic number from get methods, and make the types consistent with VideoCapture::get Fix documentation. * Add wrapper macro's and remove unecessary parameter from get().
1 parent 49e8f12 commit 758c1a9

File tree

7 files changed

+207
-73
lines changed

7 files changed

+207
-73
lines changed

modules/cudacodec/include/opencv2/cudacodec.hpp

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,10 @@ enum class VideoReaderProps {
316316
PROP_RAW_PACKAGES_BASE_INDEX = 2, //!< Base index for retrieving raw encoded data using retrieve().
317317
PROP_NUMBER_OF_RAW_PACKAGES_SINCE_LAST_GRAB = 3, //!< Number of raw packages recieved since the last call to grab().
318318
PROP_RAW_MODE = 4, //!< Status of raw mode.
319-
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.
319+
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.
320+
#ifndef CV_DOXYGEN
321+
PROP_NOT_SUPPORTED
322+
#endif
320323
};
321324

322325
/** @brief Video reader interface.
@@ -369,19 +372,33 @@ class CV_EXPORTS_W VideoReader
369372

370373
/** @brief Sets a property in the VideoReader.
371374
372-
@param property Property identifier from cv::cudacodec::VideoReaderProps (eg. cv::cudacodec::PROP_DECODED_FRAME_IDX, cv::cudacodec::PROP_EXTRA_DATA_INDEX, ...)
375+
@param propertyId Property identifier from cv::cudacodec::VideoReaderProps (eg. cv::cudacodec::VideoReaderProps::PROP_DECODED_FRAME_IDX,
376+
cv::cudacodec::VideoReaderProps::PROP_EXTRA_DATA_INDEX, ...).
373377
@param propertyVal Value of the property.
374378
@return `true` if the property has been set.
375379
*/
376-
CV_WRAP virtual bool set(const VideoReaderProps property, const double propertyVal) = 0;
380+
CV_WRAP virtual bool set(const VideoReaderProps propertyId, const double propertyVal) = 0;
377381

378382
/** @brief Returns the specified VideoReader property
379383
380-
@param property Property identifier from cv::cudacodec::VideoReaderProps (eg. cv::cudacodec::PROP_DECODED_FRAME_IDX, cv::cudacodec::PROP_EXTRA_DATA_INDEX, ...)
381-
@param propertyVal Optional value for the property.
382-
@return Value for the specified property. Value -1 is returned when querying a property that is not supported.
384+
@param propertyId Property identifier from cv::cudacodec::VideoReaderProps (eg. cv::cudacodec::VideoReaderProps::PROP_DECODED_FRAME_IDX,
385+
cv::cudacodec::VideoReaderProps::PROP_EXTRA_DATA_INDEX, ...).
386+
@param propertyVal
387+
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).
388+
Out - Value of the property.
389+
@return `true` unless the property is not supported.
383390
*/
384-
CV_WRAP virtual int get(const VideoReaderProps property, const int propertyVal = -1) const = 0;
391+
CV_WRAP virtual bool get(const VideoReaderProps propertyId, CV_IN_OUT double& propertyVal) const = 0;
392+
393+
/** @brief Retrieves the specified property used by the VideoSource.
394+
395+
@param propertyId Property identifier from cv::VideoCaptureProperties (eg. cv::CAP_PROP_POS_MSEC, cv::CAP_PROP_POS_FRAMES, ...)
396+
or one from @ref videoio_flags_others.
397+
@param propertyVal Value for the specified property.
398+
399+
@return `true` unless the property is unset set or not supported.
400+
*/
401+
CV_WRAP virtual bool get(const int propertyId, CV_OUT double& propertyVal) const = 0;
385402
};
386403

387404
/** @brief Interface for video demultiplexing. :
@@ -417,16 +434,30 @@ class CV_EXPORTS_W RawVideoSource
417434
@param extraData 1D cv::Mat containing the extra data if it exists.
418435
*/
419436
virtual void getExtraData(cv::Mat& extraData) const = 0;
437+
438+
/** @brief Retrieves the specified property used by the VideoSource.
439+
440+
@param propertyId Property identifier from cv::VideoCaptureProperties (eg. cv::CAP_PROP_POS_MSEC, cv::CAP_PROP_POS_FRAMES, ...)
441+
or one from @ref videoio_flags_others.
442+
@param propertyVal Value for the specified property.
443+
444+
@return `true` unless the property is unset set or not supported.
445+
*/
446+
virtual bool get(const int propertyId, double& propertyVal) const = 0;
420447
};
421448

422449
/** @brief Creates video reader.
423450
424451
@param filename Name of the input video file.
452+
@param params Pass through parameters for VideoCapure. VideoCapture with the FFMpeg back end (CAP_FFMPEG) is used to parse the video input.
453+
The `params` parameter allows to specify extra parameters encoded as pairs `(paramId_1, paramValue_1, paramId_2, paramValue_2, ...)`.
454+
See cv::VideoCaptureProperties
455+
e.g. when streaming from an RTSP source CAP_PROP_OPEN_TIMEOUT_MSEC may need to be set.
425456
@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).
426457
427458
FFMPEG is used to read videos. User can implement own demultiplexing with cudacodec::RawVideoSource
428459
*/
429-
CV_EXPORTS_W Ptr<VideoReader> createVideoReader(const String& filename, const bool rawMode = false);
460+
CV_EXPORTS_W Ptr<VideoReader> createVideoReader(const String& filename, const std::vector<int>& params = {}, const bool rawMode = false);
430461

431462
/** @overload
432463
@param source RAW video source implemented by user.

modules/cudacodec/src/ffmpeg_video_source.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ void FourccToChromaFormat(const int pixelFormat, ChromaFormat &chromaFormat, int
113113
}
114114
}
115115

116+
static
116117
int StartCodeLen(unsigned char* data, const int sz) {
117118
if (sz >= 3 && data[0] == 0 && data[1] == 0 && data[2] == 1)
118119
return 3;
@@ -129,12 +130,13 @@ bool ParamSetsExist(unsigned char* parameterSets, const int szParameterSets, uns
129130
return paramSetStartCodeLen != 0 && packetStartCodeLen != 0 && parameterSets[paramSetStartCodeLen] == data[packetStartCodeLen];
130131
}
131132

132-
cv::cudacodec::detail::FFmpegVideoSource::FFmpegVideoSource(const String& fname)
133+
cv::cudacodec::detail::FFmpegVideoSource::FFmpegVideoSource(const String& fname, const std::vector<int>& _videoCaptureParams)
134+
: videoCaptureParams(_videoCaptureParams)
133135
{
134136
if (!videoio_registry::hasBackend(CAP_FFMPEG))
135137
CV_Error(Error::StsNotImplemented, "FFmpeg backend not found");
136138

137-
cap.open(fname, CAP_FFMPEG);
139+
cap.open(fname, CAP_FFMPEG, videoCaptureParams);
138140
if (!cap.isOpened())
139141
CV_Error(Error::StsUnsupportedFormat, "Unsupported video source");
140142

@@ -176,6 +178,18 @@ void cv::cudacodec::detail::FFmpegVideoSource::updateFormat(const FormatInfo& vi
176178
format_.valid = true;
177179
}
178180

181+
bool cv::cudacodec::detail::FFmpegVideoSource::get(const int propertyId, double& propertyVal) const
182+
{
183+
CV_Assert(videoCaptureParams.size() % 2 == 0);
184+
for (std::size_t i = 0; i < videoCaptureParams.size(); i += 2) {
185+
if (videoCaptureParams.at(i) == propertyId) {
186+
propertyVal = videoCaptureParams.at(i + 1);
187+
return true;
188+
}
189+
}
190+
return false;
191+
}
192+
179193
bool cv::cudacodec::detail::FFmpegVideoSource::getNextPacket(unsigned char** data, size_t* size)
180194
{
181195
cap >> rawFrame;

modules/cudacodec/src/ffmpeg_video_source.hpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ namespace cv { namespace cudacodec { namespace detail {
5151
class FFmpegVideoSource : public RawVideoSource
5252
{
5353
public:
54-
FFmpegVideoSource(const String& fname);
54+
FFmpegVideoSource(const String& fname, const std::vector<int>& params);
5555
~FFmpegVideoSource();
5656

5757
bool getNextPacket(unsigned char** data, size_t* size) CV_OVERRIDE;
@@ -64,11 +64,14 @@ class FFmpegVideoSource : public RawVideoSource
6464

6565
void getExtraData(cv::Mat& _extraData) const CV_OVERRIDE { _extraData = extraData; }
6666

67+
bool get(const int propertyId, double& propertyVal) const;
68+
6769
private:
6870
FormatInfo format_;
6971
VideoCapture cap;
7072
Mat rawFrame, extraData, dataWithHeader;
7173
int iFrame = 0;
74+
std::vector<int> videoCaptureParams;
7275
};
7376

7477
}}}

modules/cudacodec/src/video_reader.cpp

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ using namespace cv::cudacodec;
4848

4949
#ifndef HAVE_NVCUVID
5050

51-
Ptr<VideoReader> cv::cudacodec::createVideoReader(const String&, const bool) { throw_no_cuda(); return Ptr<VideoReader>(); }
51+
Ptr<VideoReader> cv::cudacodec::createVideoReader(const String&, const std::vector<int>&, const bool) { throw_no_cuda(); return Ptr<VideoReader>(); }
5252
Ptr<VideoReader> cv::cudacodec::createVideoReader(const Ptr<RawVideoSource>&, const bool) { throw_no_cuda(); return Ptr<VideoReader>(); }
5353

5454
#else // HAVE_NVCUVID
@@ -73,9 +73,11 @@ namespace
7373

7474
bool retrieve(OutputArray frame, const size_t idx) const CV_OVERRIDE;
7575

76-
bool set(const VideoReaderProps property, const double propertyVal) CV_OVERRIDE;
76+
bool set(const VideoReaderProps propertyId, const double propertyVal) CV_OVERRIDE;
7777

78-
int get(const VideoReaderProps property, const int propertyVal) const CV_OVERRIDE;
78+
bool get(const VideoReaderProps propertyId, double& propertyVal) const CV_OVERRIDE;
79+
80+
bool get(const int propertyId, double& propertyVal) const CV_OVERRIDE;
7981

8082
private:
8183
bool internalGrab(GpuMat& frame, Stream& stream);
@@ -136,8 +138,8 @@ namespace
136138
};
137139

138140
bool VideoReaderImpl::internalGrab(GpuMat& frame, Stream& stream) {
139-
if (videoSource_->hasError() || videoParser_->hasError())
140-
CV_Error(Error::StsUnsupportedFormat, "Unsupported video source");
141+
if (videoParser_->hasError())
142+
CV_Error(Error::StsError, "Parsing/Decoding video source failed, check GPU memory is available and GPU supports hardware decoding.");
141143

142144
if (frames_.empty())
143145
{
@@ -148,8 +150,8 @@ namespace
148150
if (frameQueue_->dequeue(displayInfo, rawPackets))
149151
break;
150152

151-
if (videoSource_->hasError() || videoParser_->hasError())
152-
CV_Error(Error::StsUnsupportedFormat, "Unsupported video source");
153+
if (videoParser_->hasError())
154+
CV_Error(Error::StsError, "Parsing/Decoding video source failed, check GPU memory is available and GPU supports hardware decoding.");
153155

154156
if (frameQueue_->isEndOfDecode())
155157
return false;
@@ -231,42 +233,54 @@ namespace
231233
return !frame.empty();
232234
}
233235

234-
bool VideoReaderImpl::set(const VideoReaderProps property, const double propertyVal) {
235-
switch (property) {
236+
bool VideoReaderImpl::set(const VideoReaderProps propertyId, const double propertyVal) {
237+
switch (propertyId) {
236238
case VideoReaderProps::PROP_RAW_MODE :
237239
videoSource_->SetRawMode(static_cast<bool>(propertyVal));
238240
break;
239241
}
240242
return true;
241243
}
242244

243-
int VideoReaderImpl::get(const VideoReaderProps property, const int propertyVal) const {
244-
switch (property)
245+
bool VideoReaderImpl::get(const VideoReaderProps propertyId, double& propertyVal) const {
246+
switch (propertyId)
245247
{
246248
case VideoReaderProps::PROP_DECODED_FRAME_IDX:
247-
return decodedFrameIdx;
249+
propertyVal = decodedFrameIdx;
250+
return true;
248251
case VideoReaderProps::PROP_EXTRA_DATA_INDEX:
249-
return extraDataIdx;
252+
propertyVal = extraDataIdx;
253+
return true;
250254
case VideoReaderProps::PROP_RAW_PACKAGES_BASE_INDEX:
251-
if (videoSource_->RawModeEnabled())
252-
return rawPacketsBaseIdx;
255+
if (videoSource_->RawModeEnabled()) {
256+
propertyVal = rawPacketsBaseIdx;
257+
return true;
258+
}
253259
else
254260
break;
255261
case VideoReaderProps::PROP_NUMBER_OF_RAW_PACKAGES_SINCE_LAST_GRAB:
256-
return rawPackets.size();
262+
propertyVal = rawPackets.size();
263+
return true;
257264
case::VideoReaderProps::PROP_RAW_MODE:
258-
return videoSource_->RawModeEnabled();
265+
propertyVal = videoSource_->RawModeEnabled();
266+
return true;
259267
case::VideoReaderProps::PROP_LRF_HAS_KEY_FRAME: {
260268
const int iPacket = propertyVal - rawPacketsBaseIdx;
261-
if (videoSource_->RawModeEnabled() && iPacket >= 0 && iPacket < rawPackets.size())
262-
return rawPackets.at(iPacket).containsKeyFrame;
269+
if (videoSource_->RawModeEnabled() && iPacket >= 0 && iPacket < rawPackets.size()) {
270+
propertyVal = rawPackets.at(iPacket).containsKeyFrame;
271+
return true;
272+
}
263273
else
264274
break;
265275
}
266276
default:
267277
break;
268278
}
269-
return -1;
279+
return false;
280+
}
281+
282+
bool VideoReaderImpl::get(const int propertyId, double& propertyVal) const {
283+
return videoSource_->get(propertyId, propertyVal);
270284
}
271285

272286
bool VideoReaderImpl::nextFrame(GpuMat& frame, Stream& stream)
@@ -277,7 +291,7 @@ namespace
277291
}
278292
}
279293

280-
Ptr<VideoReader> cv::cudacodec::createVideoReader(const String& filename, const bool rawMode)
294+
Ptr<VideoReader> cv::cudacodec::createVideoReader(const String& filename, const std::vector<int>& params, const bool rawMode)
281295
{
282296
CV_Assert(!filename.empty());
283297

@@ -286,11 +300,12 @@ Ptr<VideoReader> cv::cudacodec::createVideoReader(const String& filename, const
286300
try
287301
{
288302
// prefer ffmpeg to cuvidGetSourceVideoFormat() which doesn't always return the corrct raw pixel format
289-
Ptr<RawVideoSource> source(new FFmpegVideoSource(filename));
303+
Ptr<RawVideoSource> source(new FFmpegVideoSource(filename, params));
290304
videoSource.reset(new RawVideoSourceWrapper(source, rawMode));
291305
}
292306
catch (...)
293307
{
308+
if (params.size()) throw;
294309
videoSource.reset(new CuvidVideoSource(filename));
295310
}
296311

modules/cudacodec/src/video_source.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,11 @@ void cv::cudacodec::detail::RawVideoSourceWrapper::updateFormat(const FormatInfo
7171
source_->updateFormat(videoFormat);
7272
}
7373

74+
bool cv::cudacodec::detail::RawVideoSourceWrapper::get(const int propertyId, double& propertyVal) const
75+
{
76+
return source_->get(propertyId, propertyVal);
77+
}
78+
7479
void cv::cudacodec::detail::RawVideoSourceWrapper::start()
7580
{
7681
stop_ = false;

modules/cudacodec/src/video_source.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ class VideoSource
5757

5858
virtual FormatInfo format() const = 0;
5959
virtual void updateFormat(const FormatInfo& videoFormat) = 0;
60+
virtual bool get(const int propertyId, double& propertyVal) const { return false; }
6061
virtual void start() = 0;
6162
virtual void stop() = 0;
6263
virtual bool isStarted() const = 0;
@@ -89,6 +90,7 @@ class RawVideoSourceWrapper : public VideoSource
8990

9091
FormatInfo format() const CV_OVERRIDE;
9192
void updateFormat(const FormatInfo& videoFormat) CV_OVERRIDE;
93+
bool get(const int propertyId, double& propertyVal) const CV_OVERRIDE;
9294
void start() CV_OVERRIDE;
9395
void stop() CV_OVERRIDE;
9496
bool isStarted() const CV_OVERRIDE;

0 commit comments

Comments
 (0)