Merge pull request #3453 from cudawarped:cudacodec_add_reconfigure_decoder

`cudacodec::VideoReader` add reconfigure decoder functionality
pull/3486/head
Alexander Smorkalov 2 years ago committed by GitHub
commit 353e37e91f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      modules/cudacodec/include/opencv2/cudacodec.hpp
  2. 28
      modules/cudacodec/src/frame_queue.cpp
  3. 9
      modules/cudacodec/src/frame_queue.hpp
  4. 57
      modules/cudacodec/src/video_decoder.cpp
  5. 6
      modules/cudacodec/src/video_decoder.hpp
  6. 116
      modules/cudacodec/src/video_parser.cpp
  7. 2
      modules/cudacodec/src/video_parser.hpp
  8. 129
      modules/cudacodec/test/test_video.cpp

@ -309,12 +309,13 @@ enum DeinterlaceMode
*/
struct CV_EXPORTS_W_SIMPLE FormatInfo
{
CV_WRAP FormatInfo() : nBitDepthMinus8(-1), ulWidth(0), ulHeight(0), width(0), height(0), ulMaxWidth(0), ulMaxHeight(0), valid(false),
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_PROP_RW Codec codec;
CV_PROP_RW ChromaFormat chromaFormat;
CV_PROP_RW int nBitDepthMinus8;
CV_PROP_RW int nBitDepthChromaMinus8;
CV_PROP_RW int ulWidth;//!< Coded sequence width in pixels.
CV_PROP_RW int ulHeight;//!< Coded sequence height in pixels.
CV_PROP_RW int width;//!< Width of the decoded frame returned by nextFrame(frame).

@ -55,14 +55,29 @@ cv::cudacodec::detail::FrameQueue::~FrameQueue() {
void cv::cudacodec::detail::FrameQueue::init(const int _maxSz) {
AutoLock autoLock(mtx_);
if (isFrameInUse_)
return;
if (isFrameInUse_) return;
maxSz = _maxSz;
displayQueue_ = std::vector<CUVIDPARSERDISPINFO>(maxSz, CUVIDPARSERDISPINFO());
isFrameInUse_ = new volatile int[maxSz];
std::memset((void*)isFrameInUse_, 0, sizeof(*isFrameInUse_) * maxSz);
}
void cv::cudacodec::detail::FrameQueue::resize(const int newSz) {
if (newSz == maxSz) return;
if (!isFrameInUse_) return init(newSz);
AutoLock autoLock(mtx_);
const int maxSzOld = maxSz; maxSz = newSz;
const auto displayQueueOld = displayQueue_;
displayQueue_ = std::vector<CUVIDPARSERDISPINFO>(maxSz, CUVIDPARSERDISPINFO());
for (int i = readPosition_; i < readPosition_ + framesInQueue_; i++)
displayQueue_.at(i % displayQueue_.size()) = displayQueueOld.at(i % displayQueueOld.size());
const volatile int* const isFrameInUseOld = isFrameInUse_;
isFrameInUse_ = new volatile int[maxSz];
std::memset((void*)isFrameInUse_, 0, sizeof(*isFrameInUse_) * maxSz);
std::memcpy((void*)isFrameInUse_, (void*)isFrameInUseOld, sizeof(*isFrameInUseOld) * min(maxSz,maxSzOld));
delete[] isFrameInUseOld;
}
bool cv::cudacodec::detail::FrameQueue::waitUntilFrameAvailable(int pictureIndex, const bool allowFrameDrop)
{
while (isInUse(pictureIndex))
@ -79,6 +94,15 @@ bool cv::cudacodec::detail::FrameQueue::waitUntilFrameAvailable(int pictureIndex
return true;
}
bool cv::cudacodec::detail::FrameQueue::waitUntilEmpty() {
while (framesInQueue_) {
Thread::sleep(1);
if (isEndOfDecode())
return false;
}
return true;
}
void cv::cudacodec::detail::FrameQueue::enqueue(const CUVIDPARSERDISPINFO* picParams, const std::vector<RawPacket> rawPackets)
{
// Mark the frame as 'in-use' so we don't re-use it for decoding until it is no longer needed

@ -66,6 +66,12 @@ public:
~FrameQueue();
void init(const int _maxSz);
// Resize the current frame queue keeping any existing queued values - must only
// be called in the same thread as enqueue.
// Parameters:
// newSz - new size of the frame queue.
void resize(const int newSz);
void endDecode() { endOfDecode_ = true; }
bool isEndOfDecode() const { return endOfDecode_ != 0;}
@ -77,6 +83,8 @@ public:
// to ensure a frame is available.
bool waitUntilFrameAvailable(int pictureIndex, const bool allowFrameDrop = false);
bool waitUntilEmpty();
void enqueue(const CUVIDPARSERDISPINFO* picParams, const std::vector<RawPacket> rawPackets);
// Deque the next frame.
@ -97,6 +105,7 @@ public:
bool dequeueUntil(const int pictureIndex);
void releaseFrame(const CUVIDPARSERDISPINFO& picParams) { isFrameInUse_[picParams.picture_index] = 0; }
int getMaxSz() { return maxSz; }
private:
bool isInUse(int pictureIndex) const { return isFrameInUse_[pictureIndex] != 0; }

@ -124,8 +124,8 @@ void cv::cudacodec::detail::VideoDecoder::create(const FormatInfo& videoFormat)
cuSafeCall(cuvidGetDecoderCaps(&decodeCaps));
cuSafeCall(cuCtxPopCurrent(NULL));
if (!(decodeCaps.bIsSupported && (decodeCaps.nOutputFormatMask & (1 << cudaVideoSurfaceFormat_NV12)))){
CV_Error(Error::StsUnsupportedFormat, "Video source is not supported by hardware video decoder");
CV_LOG_ERROR(NULL, "Video source is not supported by hardware video decoder.");
CV_Error(Error::StsUnsupportedFormat, "Video source is not supported by hardware video decoder");
}
CV_Assert(videoFormat.ulWidth >= decodeCaps.nMinWidth &&
videoFormat.ulHeight >= decodeCaps.nMinHeight &&
@ -162,6 +162,61 @@ void cv::cudacodec::detail::VideoDecoder::create(const FormatInfo& videoFormat)
cuSafeCall(cuCtxPushCurrent(ctx_));
cuSafeCall(cuvidCreateDecoder(&decoder_, &createInfo_));
cuSafeCall(cuCtxPopCurrent(NULL));
inited_ = true;
}
int cv::cudacodec::detail::VideoDecoder::reconfigure(const FormatInfo& videoFormat) {
if (videoFormat.nBitDepthMinus8 != videoFormat_.nBitDepthMinus8 || videoFormat.nBitDepthChromaMinus8 != videoFormat_.nBitDepthChromaMinus8) {
CV_LOG_ERROR(NULL, "Reconfigure Not supported for bit depth change");
CV_Error(Error::StsUnsupportedFormat, "Reconfigure Not supported for bit depth change");
}
if (videoFormat.chromaFormat != videoFormat_.chromaFormat) {
CV_LOG_ERROR(NULL, "Reconfigure Not supported for chroma format change");
CV_Error(Error::StsUnsupportedFormat, "Reconfigure Not supported for chroma format change");
}
const bool decodeResChange = !(videoFormat.ulWidth == videoFormat_.ulWidth && videoFormat.ulHeight == videoFormat_.ulHeight);
if ((videoFormat.ulWidth > videoFormat_.ulMaxWidth) || (videoFormat.ulHeight > videoFormat_.ulMaxHeight)) {
// For VP9, let driver handle the change if new width/height > maxwidth/maxheight
if (videoFormat.codec != Codec::VP9) {
CV_LOG_ERROR(NULL, "Reconfigure Not supported when width/height > maxwidth/maxheight");
CV_Error(Error::StsUnsupportedFormat, "Reconfigure Not supported when width/height > maxwidth/maxheight");
}
}
if (!decodeResChange)
return 1;
{
AutoLock autoLock(mtx_);
videoFormat_.ulNumDecodeSurfaces = videoFormat.ulNumDecodeSurfaces;
videoFormat_.ulWidth = videoFormat.ulWidth;
videoFormat_.ulHeight = videoFormat.ulHeight;
videoFormat_.targetRoi = videoFormat.targetRoi;
}
CUVIDRECONFIGUREDECODERINFO reconfigParams = { 0 };
reconfigParams.ulWidth = videoFormat_.ulWidth;
reconfigParams.ulHeight = videoFormat_.ulHeight;
reconfigParams.display_area.left = videoFormat_.displayArea.x;
reconfigParams.display_area.right = videoFormat_.displayArea.x + videoFormat_.displayArea.width;
reconfigParams.display_area.top = videoFormat_.displayArea.y;
reconfigParams.display_area.bottom = videoFormat_.displayArea.y + videoFormat_.displayArea.height;
reconfigParams.ulTargetWidth = videoFormat_.width;
reconfigParams.ulTargetHeight = videoFormat_.height;
reconfigParams.target_rect.left = videoFormat_.targetRoi.x;
reconfigParams.target_rect.right = videoFormat_.targetRoi.x + videoFormat_.targetRoi.width;
reconfigParams.target_rect.top = videoFormat_.targetRoi.y;
reconfigParams.target_rect.bottom = videoFormat_.targetRoi.y + videoFormat_.targetRoi.height;
reconfigParams.ulNumDecodeSurfaces = videoFormat_.ulNumDecodeSurfaces;
cuSafeCall(cuCtxPushCurrent(ctx_));
cuSafeCall(cuvidReconfigureDecoder(decoder_, &reconfigParams));
cuSafeCall(cuCtxPopCurrent(NULL));
CV_LOG_INFO(NULL, "Reconfiguring Decoder");
return videoFormat_.ulNumDecodeSurfaces;
}
void cv::cudacodec::detail::VideoDecoder::release()

@ -68,9 +68,10 @@ public:
}
void create(const FormatInfo& videoFormat);
int reconfigure(const FormatInfo& videoFormat);
void release();
// Get the code-type currently used.
// Get the codec-type currently used.
cudaVideoCodec codec() const { return static_cast<cudaVideoCodec>(videoFormat_.codec); }
int nDecodeSurfaces() const { return videoFormat_.ulNumDecodeSurfaces; }
cv::Size getTargetSz() const { return videoFormat_.targetSz; }
@ -84,6 +85,8 @@ public:
unsigned long targetWidth() { return videoFormat_.width; }
unsigned long targetHeight() { return videoFormat_.height; }
bool inited() { return inited_; }
cudaVideoChromaFormat chromaFormat() const { return static_cast<cudaVideoChromaFormat>(videoFormat_.chromaFormat); }
int nBitDepthMinus8() const { return videoFormat_.nBitDepthMinus8; }
@ -114,6 +117,7 @@ private:
CUvideodecoder decoder_ = 0;
FormatInfo videoFormat_ = {};
Mutex mtx_;
bool inited_ = false;
};
}}}

@ -68,6 +68,7 @@ bool cv::cudacodec::detail::VideoParser::parseVideoData(const unsigned char* dat
CUVIDSOURCEDATAPACKET packet;
std::memset(&packet, 0, sizeof(CUVIDSOURCEDATAPACKET));
packet.flags = CUVID_PKT_TIMESTAMP;
if (endOfStream)
packet.flags |= CUVID_PKT_ENDOFSTREAM;
@ -107,68 +108,69 @@ int CUDAAPI cv::cudacodec::detail::VideoParser::HandleVideoSequence(void* userDa
thiz->unparsedPackets_ = 0;
if (format->codec != thiz->videoDecoder_->codec() ||
format->coded_width != thiz->videoDecoder_->frameWidth() ||
format->coded_height != thiz->videoDecoder_->frameHeight() ||
format->chroma_format != thiz->videoDecoder_->chromaFormat()||
format->bit_depth_luma_minus8 != thiz->videoDecoder_->nBitDepthMinus8() ||
format->min_num_decode_surfaces != thiz->videoDecoder_->nDecodeSurfaces())
FormatInfo newFormat;
newFormat.videoFullRangeFlag = format->video_signal_description.video_full_range_flag;
newFormat.codec = static_cast<Codec>(format->codec);
newFormat.chromaFormat = static_cast<ChromaFormat>(format->chroma_format);
newFormat.nBitDepthMinus8 = format->bit_depth_luma_minus8;
newFormat.nBitDepthChromaMinus8 = format->bit_depth_chroma_minus8;
newFormat.ulWidth = format->coded_width;
newFormat.ulHeight = format->coded_height;
newFormat.fps = format->frame_rate.numerator / static_cast<float>(format->frame_rate.denominator);
newFormat.targetSz = thiz->videoDecoder_->getTargetSz();
newFormat.srcRoi = thiz->videoDecoder_->getSrcRoi();
if (newFormat.srcRoi.empty()) {
newFormat.displayArea = Rect(Point(format->display_area.left, format->display_area.top), Point(format->display_area.right, format->display_area.bottom));
if (newFormat.targetSz.empty())
newFormat.targetSz = Size((format->display_area.right - format->display_area.left), (format->display_area.bottom - format->display_area.top));
}
else
newFormat.displayArea = newFormat.srcRoi;
newFormat.width = newFormat.targetSz.width ? newFormat.targetSz.width : format->coded_width;
newFormat.height = newFormat.targetSz.height ? newFormat.targetSz.height : format->coded_height;
newFormat.targetRoi = thiz->videoDecoder_->getTargetRoi();
newFormat.ulNumDecodeSurfaces = min(!thiz->allowFrameDrop_ ? max(thiz->videoDecoder_->nDecodeSurfaces(), static_cast<int>(format->min_num_decode_surfaces)) :
format->min_num_decode_surfaces * 2, 32);
if (format->progressive_sequence)
newFormat.deinterlaceMode = Weave;
else
newFormat.deinterlaceMode = Adaptive;
int maxW = 0, maxH = 0;
// AV1 has max width/height of sequence in sequence header
if (format->codec == cudaVideoCodec_AV1 && format->seqhdr_data_length > 0)
{
FormatInfo newFormat;
newFormat.videoFullRangeFlag = format->video_signal_description.video_full_range_flag;
newFormat.codec = static_cast<Codec>(format->codec);
newFormat.chromaFormat = static_cast<ChromaFormat>(format->chroma_format);
newFormat.nBitDepthMinus8 = format->bit_depth_luma_minus8;
newFormat.ulWidth = format->coded_width;
newFormat.ulHeight = format->coded_height;
newFormat.fps = format->frame_rate.numerator / static_cast<float>(format->frame_rate.denominator);
newFormat.targetSz = thiz->videoDecoder_->getTargetSz();
newFormat.srcRoi = thiz->videoDecoder_->getSrcRoi();
if (newFormat.srcRoi.empty()) {
newFormat.displayArea = Rect(Point(format->display_area.left, format->display_area.top), Point(format->display_area.right, format->display_area.bottom));
if (newFormat.targetSz.empty())
newFormat.targetSz = Size((format->display_area.right - format->display_area.left), (format->display_area.bottom - format->display_area.top));
}
else
newFormat.displayArea = newFormat.srcRoi;
newFormat.width = newFormat.targetSz.width ? newFormat.targetSz.width : format->coded_width;
newFormat.height = newFormat.targetSz.height ? newFormat.targetSz.height : format->coded_height;
newFormat.targetRoi = thiz->videoDecoder_->getTargetRoi();
newFormat.ulNumDecodeSurfaces = min(!thiz->allowFrameDrop_ ? max(thiz->videoDecoder_->nDecodeSurfaces(), static_cast<int>(format->min_num_decode_surfaces)) :
format->min_num_decode_surfaces * 2, 32);
if (format->progressive_sequence)
newFormat.deinterlaceMode = Weave;
else
newFormat.deinterlaceMode = Adaptive;
int maxW = 0, maxH = 0;
// AV1 has max width/height of sequence in sequence header
if (format->codec == cudaVideoCodec_AV1 && format->seqhdr_data_length > 0)
{
CUVIDEOFORMATEX* vidFormatEx = (CUVIDEOFORMATEX*)format;
maxW = vidFormatEx->av1.max_width;
maxH = vidFormatEx->av1.max_height;
CUVIDEOFORMATEX* vidFormatEx = (CUVIDEOFORMATEX*)format;
maxW = vidFormatEx->av1.max_width;
maxH = vidFormatEx->av1.max_height;
}
if (maxW < (int)format->coded_width)
maxW = format->coded_width;
if (maxH < (int)format->coded_height)
maxH = format->coded_height;
newFormat.ulMaxWidth = maxW;
newFormat.ulMaxHeight = maxH;
thiz->frameQueue_->waitUntilEmpty();
int retVal = newFormat.ulNumDecodeSurfaces;
try
{
if (thiz->videoDecoder_->inited()) {
retVal = thiz->videoDecoder_->reconfigure(newFormat);
if (retVal > 1 && newFormat.ulNumDecodeSurfaces != thiz->frameQueue_->getMaxSz())
thiz->frameQueue_->resize(newFormat.ulNumDecodeSurfaces);
}
if (maxW < (int)format->coded_width)
maxW = format->coded_width;
if (maxH < (int)format->coded_height)
maxH = format->coded_height;
newFormat.ulMaxWidth = maxW;
newFormat.ulMaxHeight = maxH;
thiz->frameQueue_->init(newFormat.ulNumDecodeSurfaces);
try
{
thiz->videoDecoder_->release();
else {
thiz->frameQueue_->init(newFormat.ulNumDecodeSurfaces);
thiz->videoDecoder_->create(newFormat);
}
catch (const cv::Exception&)
{
CV_LOG_ERROR(NULL, "Attempt to reconfigure Nvidia decoder failed!");
thiz->hasError_ = true;
return false;
}
}
return thiz->videoDecoder_->nDecodeSurfaces();
catch (const cv::Exception&)
{
CV_LOG_ERROR(NULL, "Attempt to configure Nvidia decoder failed!");
thiz->hasError_ = true;
retVal = 0;
}
return retVal;
}
int CUDAAPI cv::cudacodec::detail::VideoParser::HandlePictureDecode(void* userData, CUVIDPICPARAMS* picParams)

@ -78,8 +78,6 @@ private:
bool allowFrameDrop_ = false;
// Called when the decoder encounters a video format change (or initial sequence header)
// This particular implementation of the callback returns 0 in case the video format changes
// to something different than the original format. Returning 0 causes a stop of the app.
static int CUDAAPI HandleVideoSequence(void* pUserData, CUVIDEOFORMAT* pFormat);
// Called by the video parser to decode a single picture

@ -45,6 +45,15 @@ namespace opencv_test {
namespace {
#if defined(HAVE_NVCUVID) || defined(HAVE_NVCUVENC)
struct SetDevice : testing::TestWithParam<cv::cuda::DeviceInfo>
{
cv::cuda::DeviceInfo devInfo;
virtual void SetUp(){
devInfo = GetParam();
cv::cuda::setDevice(devInfo.deviceID());
}
};
PARAM_TEST_CASE(CheckSet, cv::cuda::DeviceInfo, std::string)
{
};
@ -71,6 +80,14 @@ PARAM_TEST_CASE(ColorConversion, cv::cuda::DeviceInfo, cv::cudacodec::ColorForma
{
};
struct ReconfigureDecoderWithScaling : SetDevice
{
};
PARAM_TEST_CASE(ReconfigureDecoder, cv::cuda::DeviceInfo, int)
{
};
PARAM_TEST_CASE(VideoReadRaw, cv::cuda::DeviceInfo, std::string)
{
};
@ -87,16 +104,8 @@ PARAM_TEST_CASE(CheckInitParams, cv::cuda::DeviceInfo, std::string, bool, bool,
{
};
struct CheckParams : testing::TestWithParam<cv::cuda::DeviceInfo>
struct CheckParams : SetDevice
{
cv::cuda::DeviceInfo devInfo;
virtual void SetUp()
{
devInfo = GetParam();
cv::cuda::setDevice(devInfo.deviceID());
}
};
#if defined(HAVE_NVCUVID)
@ -190,6 +199,14 @@ CUDA_TEST_P(CheckKeyFrame, Reader)
}
}
void ForceAlignment(Rect& srcRoi, Rect& targetRoi, Size& targetSz) {
targetSz.width = targetSz.width - targetSz.width % 2; targetSz.height = targetSz.height - targetSz.height % 2;
srcRoi.x = srcRoi.x - srcRoi.x % 4; srcRoi.width = srcRoi.width - srcRoi.width % 4;
srcRoi.y = srcRoi.y - srcRoi.y % 2; srcRoi.height = srcRoi.height - srcRoi.height % 2;
targetRoi.x = targetRoi.x - targetRoi.x % 4; targetRoi.width = targetRoi.width - targetRoi.width % 4;
targetRoi.y = targetRoi.y - targetRoi.y % 2; targetRoi.height = targetRoi.height - targetRoi.height % 2;
}
CUDA_TEST_P(Scaling, Reader)
{
cv::cuda::setDevice(GET_PARAM(0).deviceID());
@ -211,18 +228,15 @@ CUDA_TEST_P(Scaling, Reader)
static_cast<int>(frameOr.rows * srcRoiIn.height));
params.targetRoi = Rect(static_cast<int>(params.targetSz.width * targetRoiIn.x), static_cast<int>(params.targetSz.height * targetRoiIn.y),
static_cast<int>(params.targetSz.width * targetRoiIn.width), static_cast<int>(params.targetSz.height * targetRoiIn.height));
cv::Ptr<cv::cudacodec::VideoReader> reader = cv::cudacodec::createVideoReader(inputFile, {}, params);
ASSERT_TRUE(reader->set(cudacodec::ColorFormat::GRAY));
GpuMat frame;
ASSERT_TRUE(reader->nextFrame(frame));
const cudacodec::FormatInfo format = reader->format();
Size targetSzOut;
targetSzOut.width = params.targetSz.width - params.targetSz.width % 2; targetSzOut.height = params.targetSz.height - params.targetSz.height % 2;
Rect srcRoiOut, targetRoiOut;
srcRoiOut.x = params.srcRoi.x - params.srcRoi.x % 4; srcRoiOut.width = params.srcRoi.width - params.srcRoi.width % 4;
srcRoiOut.y = params.srcRoi.y - params.srcRoi.y % 2; srcRoiOut.height = params.srcRoi.height - params.srcRoi.height % 2;
targetRoiOut.x = params.targetRoi.x - params.targetRoi.x % 4; targetRoiOut.width = params.targetRoi.width - params.targetRoi.width % 4;
targetRoiOut.y = params.targetRoi.y - params.targetRoi.y % 2; targetRoiOut.height = params.targetRoi.height - params.targetRoi.height % 2;
Size targetSzOut = params.targetSz;
Rect srcRoiOut = params.srcRoi, targetRoiOut = params.targetRoi;
ForceAlignment(srcRoiOut, targetRoiOut, targetSzOut);
ASSERT_TRUE(format.valid && format.targetSz == targetSzOut && format.srcRoi == srcRoiOut && format.targetRoi == targetRoiOut);
ASSERT_TRUE(frame.size() == targetSzOut);
GpuMat frameGs;
@ -237,8 +251,8 @@ CUDA_TEST_P(DisplayResolution, Reader)
cv::cuda::setDevice(GetParam().deviceID());
std::string inputFile = std::string(cvtest::TS::ptr()->get_data_path()) + "../cv/video/1920x1080.avi";
const Rect displayArea(0, 0, 1920, 1080);
GpuMat frame;
GpuMat frame;
{
// verify the output frame is the diplay size (1920x1080) and not the coded size (1920x1088)
cv::Ptr<cv::cudacodec::VideoReader> reader = cv::cudacodec::createVideoReader(inputFile);
@ -332,6 +346,82 @@ CUDA_TEST_P(ColorConversion, Reader)
}
}
CUDA_TEST_P(ReconfigureDecoderWithScaling, Reader)
{
const std::string inputFile = std::string(cvtest::TS::ptr()->get_data_path()) + "../highgui/video/big_buck_bunny_multi_res.h264";
GpuMat frameOr;
{
cv::Ptr<cv::cudacodec::VideoReader> readerGs = cv::cudacodec::createVideoReader(inputFile);
ASSERT_TRUE(readerGs->nextFrame(frameOr));
}
cv::cudacodec::VideoReaderInitParams params;
const Size2f targetSzNew(0.8f, 0.9f);
const Rect2f srcRoiNew(0.25f, 0.25f, 0.5f, 0.5f);
const Rect2f targetRoiNew(0.2f, 0.3f, 0.6f, 0.7f);
params.targetSz = Size(static_cast<int>(frameOr.cols * targetSzNew.width), static_cast<int>(frameOr.rows * targetSzNew.height));
params.srcRoi = Rect(static_cast<int>(frameOr.cols * srcRoiNew.x), static_cast<int>(frameOr.rows * srcRoiNew.y), static_cast<int>(frameOr.cols * srcRoiNew.width),
static_cast<int>(frameOr.rows * srcRoiNew.height));
params.targetRoi = Rect(static_cast<int>(params.targetSz.width * targetRoiNew.x), static_cast<int>(params.targetSz.height * targetRoiNew.y),
static_cast<int>(params.targetSz.width * targetRoiNew.width), static_cast<int>(params.targetSz.height * targetRoiNew.height));
Size targetSzOut = params.targetSz;
Rect srcRoiOut = params.srcRoi, targetRoiOut = params.targetRoi;
ForceAlignment(srcRoiOut, targetRoiOut, targetSzOut);
GpuMat mask(targetSzOut, CV_8U, Scalar(255));
mask(targetRoiOut).setTo(0);
cv::Ptr<cv::cudacodec::VideoReader> reader = cv::cudacodec::createVideoReader(inputFile, {}, params);
reader->set(cudacodec::ColorFormat::GRAY);
cv::cudacodec::FormatInfo fmt;
cv::cuda::GpuMat frame;
int nFrames = 0;
Size initialSize;
while (reader->nextFrame(frame))
{
ASSERT_TRUE(!frame.empty());
if (nFrames++ == 0)
initialSize = frame.size();
fmt = reader->format();
ASSERT_TRUE(fmt.valid && (frame.size() == initialSize));
ASSERT_TRUE((frame.size() == targetSzOut) && (fmt.targetSz == targetSzOut) && (fmt.srcRoi == srcRoiOut) && (fmt.targetRoi == targetRoiOut));
// simple check - zero borders, non zero contents
ASSERT_TRUE(!cuda::absSum(frame, mask)[0] && cuda::sum(frame)[0]);
}
ASSERT_TRUE(nFrames == 40);
}
CUDA_TEST_P(ReconfigureDecoder, Reader)
{
const std::string inputFile = std::string(cvtest::TS::ptr()->get_data_path()) + "../highgui/video/big_buck_bunny_multi_res.h264";
cv::cuda::setDevice(GET_PARAM(0).deviceID());
const int minNumDecodeSurfaces = GET_PARAM(1);
cv::cudacodec::VideoReaderInitParams params;
params.minNumDecodeSurfaces = minNumDecodeSurfaces;
cv::Ptr<cv::cudacodec::VideoReader> reader = cv::cudacodec::createVideoReader(inputFile, {}, params);
reader->set(cudacodec::ColorFormat::GRAY);
cv::cudacodec::FormatInfo fmt;
cv::cuda::GpuMat frame, mask;
int nFrames = 0;
Size initialSize, initialCodedSize;
while(reader->nextFrame(frame))
{
ASSERT_TRUE(!frame.empty());
fmt = reader->format();
if (nFrames++ == 0) {
initialSize = frame.size();
initialCodedSize = Size(fmt.ulWidth, fmt.ulHeight);
}
ASSERT_TRUE(fmt.valid && (frame.size() == initialSize));
ASSERT_TRUE(fmt.srcRoi.empty());
const bool resChanged = (initialCodedSize.width != fmt.ulWidth) || (initialCodedSize.height != fmt.ulHeight);
if (resChanged)
ASSERT_TRUE(fmt.targetRoi.empty());
}
ASSERT_TRUE(nFrames == 40);
}
CUDA_TEST_P(VideoReadRaw, Reader)
{
cv::cuda::setDevice(GET_PARAM(0).deviceID());
@ -767,6 +857,11 @@ INSTANTIATE_TEST_CASE_P(CUDA_Codec, ColorConversion, testing::Combine(
testing::Values(VIDEO_COLOR_OUTPUTS),
testing::ValuesIn(color_conversion_params)));
INSTANTIATE_TEST_CASE_P(CUDA_Codec, ReconfigureDecoderWithScaling, ALL_DEVICES);
#define N_DECODE_SURFACES testing::Values(0, 10)
INSTANTIATE_TEST_CASE_P(CUDA_Codec, ReconfigureDecoder, testing::Combine(ALL_DEVICES, N_DECODE_SURFACES));
#define VIDEO_SRC_RW "highgui/video/big_buck_bunny.h264", "highgui/video/big_buck_bunny.h265"
INSTANTIATE_TEST_CASE_P(CUDA_Codec, VideoReadRaw, testing::Combine(
ALL_DEVICES,

Loading…
Cancel
Save