Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pass cv::VideoCaptureProperties to VideoReader FFmpeg source #3139

Merged
merged 12 commits into from
Dec 28, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
44 changes: 27 additions & 17 deletions modules/cudacodec/include/opencv2/cudacodec.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,10 @@ enum class VideoReaderProps {
PROP_RAW_PACKAGES_BASE_INDEX = 2, //!< Base index for retrieving raw encoded data using retrieve().
PROP_NUMBER_OF_RAW_PACKAGES_SINCE_LAST_GRAB = 3, //!< Number of raw packages recieved since the last call to grab().
PROP_RAW_MODE = 4, //!< Status of raw mode.
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.
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.
#ifndef CV_DOXYGEN
PROP_NOT_SUPPORTED
#endif
};

/** @brief Video reader interface.
Expand Down Expand Up @@ -369,28 +372,30 @@ class CV_EXPORTS_W VideoReader

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

@param property Property identifier from cv::cudacodec::VideoReaderProps (eg. cv::cudacodec::PROP_DECODED_FRAME_IDX, cv::cudacodec::PROP_EXTRA_DATA_INDEX, ...)
@param propertyId Property identifier from cv::cudacodec::VideoReaderProps (eg. cv::cudacodec::PROP_DECODED_FRAME_IDX, cv::cudacodec::PROP_EXTRA_DATA_INDEX, ...).
@param propertyVal Value of the property.
@return `true` if the property has been set.
*/
CV_WRAP virtual bool set(const VideoReaderProps propertyId, const double propertyVal) = 0;

/** @brief Returns the specified VideoReader property

@param property Property identifier from cv::cudacodec::VideoReaderProps (eg. cv::cudacodec::PROP_DECODED_FRAME_IDX, cv::cudacodec::PROP_EXTRA_DATA_INDEX, ...)
@param propertyId Property identifier from cv::cudacodec::VideoReaderProps (eg. cv::cudacodec::PROP_DECODED_FRAME_IDX, cv::cudacodec::PROP_EXTRA_DATA_INDEX, ...).
@param propertyValOut Value for the specified property.
@param propertyVal Optional value for the property.
@return Value for the specified property. Value -1 is returned when querying a property that is not supported.
@return `true` unless the property is not supported.
*/
CV_WRAP virtual int get(const VideoReaderProps propertyId, const int propertyVal = -1) const = 0;
CV_WRAP virtual bool get(const VideoReaderProps propertyId, double& propertyValOut, const int propertyVal = -1) const = 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CV_WRAP

It needs to add CV_OUT specifier:

CV_OUT double& propertyValOut

const int propertyVal = -1

Perhaps we don't need this anymore.


/** @brief Retrieves the specified property used by the VideoSource.

/** @brief Returns the specified property used by the VideoSource.
@param propertyId Property identifier from cv::VideoCaptureProperties (eg. cv::CAP_PROP_POS_MSEC, cv::CAP_PROP_POS_FRAMES, ...)
or one from @ref videoio_flags_others.
@param propertyVal Value for the specified property.

@param propId Property identifier from cv::VideoCaptureProperties (eg. cv::CAP_PROP_POS_MSEC, cv::CAP_PROP_POS_FRAMES, ...)
or one from @ref videoio_flags_others
@return Value for the specified property. Value 0 is returned when querying a property that is
not supported.
@return `true` unless the property is unset set or not supported.
*/
CV_WRAP virtual double get(const int propertyId) const = 0;
CV_WRAP virtual bool get(const int propertyId, double& propertyVal) const = 0;
};

/** @brief Interface for video demultiplexing. :
Expand Down Expand Up @@ -427,19 +432,24 @@ class CV_EXPORTS_W RawVideoSource
*/
virtual void getExtraData(cv::Mat& extraData) const = 0;

/** @brief Returns the specified property used by the VideoSource.
/** @brief Retrieves the specified property used by the VideoSource.

@param propertyId Property identifier from cv::VideoCaptureProperties (eg. cv::CAP_PROP_POS_MSEC, cv::CAP_PROP_POS_FRAMES, ...)
or one from @ref videoio_flags_others.
@param propertyVal Value for the specified property.

@param propId Property identifier from cv::VideoCaptureProperties (eg. cv::CAP_PROP_POS_MSEC, cv::CAP_PROP_POS_FRAMES, ...)
or one from @ref videoio_flags_others
@return Value for the specified property. Value 0 is returned when querying a property that is
not supported.
@return `true` unless the property is unset set or not supported.
*/
virtual double get(const int propId) const = 0;
virtual bool get(const int propertyId, double& propertyVal) const = 0;
};

/** @brief Creates video reader.

@param filename Name of the input video file.
@param params Pass through parameters for VideoCapure. VideoCapture with the FFMpeg back end (CAP_FFMPEG) is used to parse the video input.
The `params` parameter allows to specify extra parameters encoded as pairs `(paramId_1, paramValue_1, paramId_2, paramValue_2, ...)`.
See cv::VideoCaptureProperties
e.g. when streaming from an RTSP source CAP_PROP_OPEN_TIMEOUT_MSEC may need to be set.
@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).

FFMPEG is used to read videos. User can implement own demultiplexing with cudacodec::RawVideoSource
Expand Down
12 changes: 7 additions & 5 deletions modules/cudacodec/src/ffmpeg_video_source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,14 +178,16 @@ void cv::cudacodec::detail::FFmpegVideoSource::updateFormat(const FormatInfo& vi
format_.valid = true;
}

double cv::cudacodec::detail::FFmpegVideoSource::get(const int propId) const
bool cv::cudacodec::detail::FFmpegVideoSource::get(const int propertyId, double& propertyVal) const
{
if (videoCaptureParams.size() % 2 != 0) return 0;
CV_Assert(videoCaptureParams.size() % 2 == 0);
for (std::size_t i = 0; i < videoCaptureParams.size(); i += 2) {
if (videoCaptureParams.at(i) == propId)
return videoCaptureParams.at(i + 1);
if (videoCaptureParams.at(i) == propertyId) {
propertyVal = videoCaptureParams.at(i + 1);
return true;
}
}
return 0;
return false;
}

bool cv::cudacodec::detail::FFmpegVideoSource::getNextPacket(unsigned char** data, size_t* size)
Expand Down
2 changes: 1 addition & 1 deletion modules/cudacodec/src/ffmpeg_video_source.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ class FFmpegVideoSource : public RawVideoSource

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

double get(const int propId) const;
bool get(const int propertyId, double& propertyVal) const;

private:
FormatInfo format_;
Expand Down
38 changes: 23 additions & 15 deletions modules/cudacodec/src/video_reader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ using namespace cv::cudacodec;

#ifndef HAVE_NVCUVID

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

#else // HAVE_NVCUVID
Expand All @@ -75,9 +75,9 @@ namespace

bool set(const VideoReaderProps propertyId, const double propertyVal) CV_OVERRIDE;

int get(const VideoReaderProps propertyId, const int propertyVal) const CV_OVERRIDE;
bool get(const VideoReaderProps propertyId, double& propertyValOut, const int propertyVal) const CV_OVERRIDE;

double get(const int propertyId) const CV_OVERRIDE;
bool get(const int propertyId, double& propertyVal) const CV_OVERRIDE;

private:
bool internalGrab(GpuMat& frame, Stream& stream);
Expand Down Expand Up @@ -242,37 +242,45 @@ namespace
return true;
}

int VideoReaderImpl::get(const VideoReaderProps propertyId, const int propertyVal) const {
bool VideoReaderImpl::get(const VideoReaderProps propertyId, double& propertyValOut, const int propertyVal) const {
switch (propertyId)
{
case VideoReaderProps::PROP_DECODED_FRAME_IDX:
return decodedFrameIdx;
propertyValOut = decodedFrameIdx;
return true;
case VideoReaderProps::PROP_EXTRA_DATA_INDEX:
return extraDataIdx;
propertyValOut = extraDataIdx;
return true;
case VideoReaderProps::PROP_RAW_PACKAGES_BASE_INDEX:
if (videoSource_->RawModeEnabled())
return rawPacketsBaseIdx;
if (videoSource_->RawModeEnabled()) {
propertyValOut = rawPacketsBaseIdx;
return true;
}
else
break;
case VideoReaderProps::PROP_NUMBER_OF_RAW_PACKAGES_SINCE_LAST_GRAB:
return rawPackets.size();
propertyValOut = rawPackets.size();
return true;
case::VideoReaderProps::PROP_RAW_MODE:
return videoSource_->RawModeEnabled();
propertyValOut = videoSource_->RawModeEnabled();
return true;
case::VideoReaderProps::PROP_LRF_HAS_KEY_FRAME: {
const int iPacket = propertyVal - rawPacketsBaseIdx;
if (videoSource_->RawModeEnabled() && iPacket >= 0 && iPacket < rawPackets.size())
return rawPackets.at(iPacket).containsKeyFrame;
if (videoSource_->RawModeEnabled() && iPacket >= 0 && iPacket < rawPackets.size()) {
propertyValOut = rawPackets.at(iPacket).containsKeyFrame;
return true;
}
else
break;
}
default:
break;
}
return -1;
return false;
}

double VideoReaderImpl::get(const int propertyId) const {
return videoSource_->get(propertyId);
bool VideoReaderImpl::get(const int propertyId, double& propertyVal) const {
return videoSource_->get(propertyId, propertyVal);
}

bool VideoReaderImpl::nextFrame(GpuMat& frame, Stream& stream)
Expand Down
4 changes: 2 additions & 2 deletions modules/cudacodec/src/video_source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,9 @@ void cv::cudacodec::detail::RawVideoSourceWrapper::updateFormat(const FormatInfo
source_->updateFormat(videoFormat);
}

double cv::cudacodec::detail::RawVideoSourceWrapper::get(const int propId) const
bool cv::cudacodec::detail::RawVideoSourceWrapper::get(const int propertyId, double& propertyVal) const
{
return source_->get(propId);
return source_->get(propertyId, propertyVal);
}

void cv::cudacodec::detail::RawVideoSourceWrapper::start()
Expand Down
4 changes: 2 additions & 2 deletions modules/cudacodec/src/video_source.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class VideoSource

virtual FormatInfo format() const = 0;
virtual void updateFormat(const FormatInfo& videoFormat) = 0;
virtual double get(const int propId) const { return 0; }
virtual bool get(const int propertyId, double& propertyVal) const { return false; }
virtual void start() = 0;
virtual void stop() = 0;
virtual bool isStarted() const = 0;
Expand Down Expand Up @@ -90,7 +90,7 @@ class RawVideoSourceWrapper : public VideoSource

FormatInfo format() const CV_OVERRIDE;
void updateFormat(const FormatInfo& videoFormat) CV_OVERRIDE;
double get(const int propId) const CV_OVERRIDE;
bool get(const int propertyId, double& propertyVal) const CV_OVERRIDE;
void start() CV_OVERRIDE;
void stop() CV_OVERRIDE;
bool isStarted() const CV_OVERRIDE;
Expand Down
53 changes: 37 additions & 16 deletions modules/cudacodec/test/test_video.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,12 +93,19 @@ CUDA_TEST_P(CheckSet, Reader)

std::string inputFile = std::string(cvtest::TS::ptr()->get_data_path()) + +"../" + GET_PARAM(1);
cv::Ptr<cv::cudacodec::VideoReader> reader = cv::cudacodec::createVideoReader(inputFile);
ASSERT_FALSE(reader->get(cv::cudacodec::VideoReaderProps::PROP_RAW_MODE));
double unsupportedVal = -1;
ASSERT_FALSE(reader->get(cv::cudacodec::VideoReaderProps::PROP_NOT_SUPPORTED, unsupportedVal));
double rawModeVal = -1;
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));
ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_RAW_MODE));
ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_RAW_MODE, rawModeVal));
ASSERT_TRUE(rawModeVal);
bool rawPacketsAvailable = false;
while (reader->grab()) {
if (reader->get(cv::cudacodec::VideoReaderProps::PROP_NUMBER_OF_RAW_PACKAGES_SINCE_LAST_GRAB) > 0) {
double nRawPackages = -1;
ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_NUMBER_OF_RAW_PACKAGES_SINCE_LAST_GRAB, nRawPackages));
if (nRawPackages > 0) {
rawPacketsAvailable = true;
break;
}
Expand All @@ -117,8 +124,11 @@ CUDA_TEST_P(CheckExtraData, Reader)
const int sz = get<1>(GET_PARAM(1));
std::string inputFile = std::string(cvtest::TS::ptr()->get_data_path()) + "../" + path;
cv::Ptr<cv::cudacodec::VideoReader> reader = cv::cudacodec::createVideoReader(inputFile, {}, true);
ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_RAW_MODE));
const int extraDataIdx = reader->get(cv::cudacodec::VideoReaderProps::PROP_EXTRA_DATA_INDEX);
double rawModeVal = -1;
ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_RAW_MODE, rawModeVal));
ASSERT_TRUE(rawModeVal);
double extraDataIdx = -1;
ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_EXTRA_DATA_INDEX, extraDataIdx));
ASSERT_EQ(extraDataIdx, 1 );
ASSERT_TRUE(reader->grab());
cv::Mat extraData;
Expand All @@ -138,17 +148,22 @@ CUDA_TEST_P(CheckKeyFrame, Reader)
const string path = GET_PARAM(1);
std::string inputFile = std::string(cvtest::TS::ptr()->get_data_path()) + "../" + path;
cv::Ptr<cv::cudacodec::VideoReader> reader = cv::cudacodec::createVideoReader(inputFile, {}, true);
ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_RAW_MODE));
const int rawIdxBase = reader->get(cv::cudacodec::VideoReaderProps::PROP_RAW_PACKAGES_BASE_INDEX);
double rawModeVal = -1;
ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_RAW_MODE, rawModeVal));
ASSERT_TRUE(rawModeVal);
double rawIdxBase = -1;
ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_RAW_PACKAGES_BASE_INDEX, rawIdxBase));
ASSERT_EQ(rawIdxBase, 2);
constexpr int maxNPackagesToCheck = 2;
int nPackages = 0;
while (nPackages < maxNPackagesToCheck) {
ASSERT_TRUE(reader->grab());
const int N = reader->get(cv::cudacodec::VideoReaderProps::PROP_NUMBER_OF_RAW_PACKAGES_SINCE_LAST_GRAB);
double N = -1;
ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_NUMBER_OF_RAW_PACKAGES_SINCE_LAST_GRAB,N));
for (int i = rawIdxBase; i < N + rawIdxBase; i++) {
nPackages++;
const bool containsKeyFrame = reader->get(cv::cudacodec::VideoReaderProps::PROP_LRF_HAS_KEY_FRAME, i);
double containsKeyFrame = -1;
ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_LRF_HAS_KEY_FRAME, containsKeyFrame, i));
ASSERT_TRUE(nPackages == 1 && containsKeyFrame || nPackages == 2 && !containsKeyFrame) << "nPackage: " << i;
if (nPackages >= maxNPackagesToCheck)
break;
Expand Down Expand Up @@ -192,16 +207,20 @@ CUDA_TEST_P(VideoReadRaw, Reader)
std::ofstream file(fileNameOut, std::ios::binary);
ASSERT_TRUE(file.is_open());
cv::Ptr<cv::cudacodec::VideoReader> reader = cv::cudacodec::createVideoReader(inputFile, {}, true);
ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_RAW_MODE));
const int rawIdxBase = reader->get(cv::cudacodec::VideoReaderProps::PROP_RAW_PACKAGES_BASE_INDEX);
double rawModeVal = -1;
ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_RAW_MODE, rawModeVal));
ASSERT_TRUE(rawModeVal);
double rawIdxBase = -1;
ASSERT_TRUE(reader->get(cv::cudacodec::VideoReaderProps::PROP_RAW_PACKAGES_BASE_INDEX, rawIdxBase));
ASSERT_EQ(rawIdxBase, 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());
const int N = reader->get(cv::cudacodec::VideoReaderProps::PROP_NUMBER_OF_RAW_PACKAGES_SINCE_LAST_GRAB);
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 i = rawIdxBase; i <= N + rawIdxBase; i++) {
Mat rawPackets;
Expand All @@ -216,7 +235,8 @@ CUDA_TEST_P(VideoReadRaw, Reader)
{
cv::Ptr<cv::cudacodec::VideoReader> readerReference = cv::cudacodec::createVideoReader(inputFile);
cv::Ptr<cv::cudacodec::VideoReader> readerActual = cv::cudacodec::createVideoReader(fileNameOut, {}, true);
const int decodedFrameIdx = readerActual->get(cv::cudacodec::VideoReaderProps::PROP_DECODED_FRAME_IDX);
double decodedFrameIdx = -1;
ASSERT_TRUE(readerActual->get(cv::cudacodec::VideoReaderProps::PROP_DECODED_FRAME_IDX, decodedFrameIdx));
ASSERT_EQ(decodedFrameIdx, 0);
cv::cuda::GpuMat reference, actual;
cv::Mat referenceHost, actualHost;
Expand All @@ -239,15 +259,16 @@ CUDA_TEST_P(CheckParams, Reader)
std::string inputFile = std::string(cvtest::TS::ptr()->get_data_path()) + "../highgui/video/big_buck_bunny.mp4";
{
cv::Ptr<cv::cudacodec::VideoReader> reader = cv::cudacodec::createVideoReader(inputFile);
const double msActual = reader->get(cv::VideoCaptureProperties::CAP_PROP_OPEN_TIMEOUT_MSEC);
ASSERT_EQ(msActual, 0);
double msActual = -1;
ASSERT_FALSE(reader->get(cv::VideoCaptureProperties::CAP_PROP_OPEN_TIMEOUT_MSEC, msActual));
}

{
constexpr int msReference = 3333;
cv::Ptr<cv::cudacodec::VideoReader> reader = cv::cudacodec::createVideoReader(inputFile, {
cv::VideoCaptureProperties::CAP_PROP_OPEN_TIMEOUT_MSEC, msReference });
const double msActual = reader->get(cv::VideoCaptureProperties::CAP_PROP_OPEN_TIMEOUT_MSEC);
double msActual = -1;
ASSERT_TRUE(reader->get(cv::VideoCaptureProperties::CAP_PROP_OPEN_TIMEOUT_MSEC, msActual));
ASSERT_EQ(msActual, msReference);
}

Expand Down