Skip to content

Commit 813967b

Browse files
authored
Merge pull request #3486 from cudawarped:cudacodec_force_valid_format
`cudacodec::VideoReader` - ensure `FormatInfo.valid == true` on return from constructor
2 parents 7a4c0df + d4b55f7 commit 813967b

File tree

4 files changed

+36
-38
lines changed

4 files changed

+36
-38
lines changed

modules/cudacodec/src/video_decoder.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,9 +160,11 @@ void cv::cudacodec::detail::VideoDecoder::create(const FormatInfo& videoFormat)
160160
createInfo_.ulCreationFlags = videoCreateFlags;
161161
createInfo_.vidLock = lock_;
162162
cuSafeCall(cuCtxPushCurrent(ctx_));
163-
cuSafeCall(cuvidCreateDecoder(&decoder_, &createInfo_));
163+
{
164+
AutoLock autoLock(mtx_);
165+
cuSafeCall(cuvidCreateDecoder(&decoder_, &createInfo_));
166+
}
164167
cuSafeCall(cuCtxPopCurrent(NULL));
165-
inited_ = true;
166168
}
167169

168170
int cv::cudacodec::detail::VideoDecoder::reconfigure(const FormatInfo& videoFormat) {

modules/cudacodec/src/video_decoder.hpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ class VideoDecoder
7070
void create(const FormatInfo& videoFormat);
7171
int reconfigure(const FormatInfo& videoFormat);
7272
void release();
73+
bool inited() { AutoLock autoLock(mtx_); return decoder_; }
7374

7475
// Get the codec-type currently used.
7576
cudaVideoCodec codec() const { return static_cast<cudaVideoCodec>(videoFormat_.codec); }
@@ -85,8 +86,6 @@ class VideoDecoder
8586
unsigned long targetWidth() { return videoFormat_.width; }
8687
unsigned long targetHeight() { return videoFormat_.height; }
8788

88-
bool inited() { return inited_; }
89-
9089
cudaVideoChromaFormat chromaFormat() const { return static_cast<cudaVideoChromaFormat>(videoFormat_.chromaFormat); }
9190
int nBitDepthMinus8() const { return videoFormat_.nBitDepthMinus8; }
9291

@@ -114,10 +113,9 @@ class VideoDecoder
114113
private:
115114
CUcontext ctx_ = 0;
116115
CUvideoctxlock lock_;
117-
CUvideodecoder decoder_ = 0;
116+
CUvideodecoder decoder_ = 0;
118117
FormatInfo videoFormat_ = {};
119118
Mutex mtx_;
120-
bool inited_ = false;
121119
};
122120

123121
}}}

modules/cudacodec/src/video_reader.cpp

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,14 +67,11 @@ void cvtFromNv12(const GpuMat& decodedFrame, GpuMat& outFrame, int width, int he
6767
outFrame.create(height, width, CV_8UC3);
6868
Npp8u* pSrc[2] = { decodedFrame.data, &decodedFrame.data[decodedFrame.step * height] };
6969
NppiSize oSizeROI = { width,height };
70-
#if (CUDART_VERSION < 9200)
71-
CV_Error(Error::StsUnsupportedFormat, "ColorFormat::BGR is not supported until CUDA 9.2, use default ColorFormat::BGRA.");
72-
#elif (CUDART_VERSION < 10100)
70+
#if (CUDART_VERSION < 10100)
7371
cv::cuda::NppStreamHandler h(stream);
7472
if (videoFullRangeFlag)
7573
nppSafeCall(nppiNV12ToBGR_709HDTV_8u_P2C3R(pSrc, decodedFrame.step, outFrame.data, outFrame.step, oSizeROI));
7674
else {
77-
CV_LOG_DEBUG(NULL, "Color reproduction may be inaccurate due CUDA version <= 11.0, for better results upgrade CUDA runtime or try ColorFormat::BGRA.");
7875
nppSafeCall(nppiNV12ToBGR_8u_P2C3R(pSrc, decodedFrame.step, outFrame.data, outFrame.step, oSizeROI));
7976
}
8077
#elif (CUDART_VERSION >= 10100)
@@ -85,7 +82,6 @@ void cvtFromNv12(const GpuMat& decodedFrame, GpuMat& outFrame, int width, int he
8582
nppSafeCall(nppiNV12ToBGR_709HDTV_8u_P2C3R_Ctx(pSrc, decodedFrame.step, outFrame.data, outFrame.step, oSizeROI, nppStreamCtx));
8683
else {
8784
#if (CUDART_VERSION < 11000)
88-
CV_LOG_DEBUG(NULL, "Color reproduction may be inaccurate due CUDA version <= 11.0, for better results upgrade CUDA runtime or try ColorFormat::BGRA.");
8985
nppSafeCall(nppiNV12ToBGR_8u_P2C3R_Ctx(pSrc, decodedFrame.step, outFrame.data, outFrame.step, oSizeROI, nppStreamCtx));
9086
#else
9187
nppSafeCall(nppiNV12ToBGR_709CSC_8u_P2C3R_Ctx(pSrc, decodedFrame.step, outFrame.data, outFrame.step, oSizeROI, nppStreamCtx));
@@ -137,6 +133,7 @@ namespace
137133

138134
private:
139135
bool internalGrab(GpuMat& frame, Stream& stream);
136+
void waitForDecoderInit();
140137

141138
Ptr<VideoSource> videoSource_;
142139

@@ -160,6 +157,15 @@ namespace
160157
return videoSource_->format();
161158
}
162159

160+
void VideoReaderImpl::waitForDecoderInit() {
161+
for (;;) {
162+
if (videoDecoder_->inited()) break;
163+
if (videoParser_->hasError() || frameQueue_->isEndOfDecode())
164+
CV_Error(Error::StsError, "Parsing/Decoding video source failed, check GPU memory is available and GPU supports hardware decoding.");
165+
Thread::sleep(1);
166+
}
167+
}
168+
163169
VideoReaderImpl::VideoReaderImpl(const Ptr<VideoSource>& source, const int minNumDecodeSurfaces, const bool allowFrameDrop, const bool udpSource,
164170
const Size targetSz, const Rect srcRoi, const Rect targetRoi) :
165171
videoSource_(source),
@@ -177,6 +183,8 @@ namespace
177183
videoParser_.reset(new VideoParser(videoDecoder_, frameQueue_, allowFrameDrop, udpSource));
178184
videoSource_->setVideoParser(videoParser_);
179185
videoSource_->start();
186+
waitForDecoderInit();
187+
videoSource_->updateFormat(videoDecoder_->format());
180188
}
181189

182190
VideoReaderImpl::~VideoReaderImpl()
@@ -307,6 +315,15 @@ namespace
307315

308316
bool VideoReaderImpl::set(const ColorFormat colorFormat_) {
309317
if (!ValidColorFormat(colorFormat_)) return false;
318+
if (colorFormat_ == ColorFormat::BGR) {
319+
#if (CUDART_VERSION < 9200)
320+
CV_LOG_DEBUG(NULL, "ColorFormat::BGR is not supported until CUDA 9.2, use default ColorFormat::BGRA.");
321+
return false;
322+
#elif (CUDART_VERSION < 11000)
323+
if (!videoDecoder_->format().videoFullRangeFlag)
324+
CV_LOG_INFO(NULL, "Color reproduction may be inaccurate due CUDA version <= 11.0, for better results upgrade CUDA runtime or try ColorFormat::BGRA.");
325+
#endif
326+
}
310327
colorFormat = colorFormat_;
311328
return true;
312329
}

modules/cudacodec/test/test_video.cpp

Lines changed: 8 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -230,14 +230,15 @@ CUDA_TEST_P(Scaling, Reader)
230230
static_cast<int>(params.targetSz.width * targetRoiIn.width), static_cast<int>(params.targetSz.height * targetRoiIn.height));
231231

232232
cv::Ptr<cv::cudacodec::VideoReader> reader = cv::cudacodec::createVideoReader(inputFile, {}, params);
233+
const cudacodec::FormatInfo format = reader->format();
234+
ASSERT_TRUE(format.valid);
233235
ASSERT_TRUE(reader->set(cudacodec::ColorFormat::GRAY));
234236
GpuMat frame;
235237
ASSERT_TRUE(reader->nextFrame(frame));
236-
const cudacodec::FormatInfo format = reader->format();
237238
Size targetSzOut = params.targetSz;
238239
Rect srcRoiOut = params.srcRoi, targetRoiOut = params.targetRoi;
239240
ForceAlignment(srcRoiOut, targetRoiOut, targetSzOut);
240-
ASSERT_TRUE(format.valid && format.targetSz == targetSzOut && format.srcRoi == srcRoiOut && format.targetRoi == targetRoiOut);
241+
ASSERT_TRUE(format.targetSz == targetSzOut && format.srcRoi == srcRoiOut && format.targetRoi == targetRoiOut);
241242
ASSERT_TRUE(frame.size() == targetSzOut);
242243
GpuMat frameGs;
243244
cv::cuda::resize(frameOr(srcRoiOut), frameGs, targetRoiOut.size(), 0, 0, INTER_AREA);
@@ -310,8 +311,6 @@ CUDA_TEST_P(Video, Reader)
310311
double colorFormat;
311312
ASSERT_TRUE(reader->get(cudacodec::VideoReaderProps::PROP_COLOR_FORMAT, colorFormat) && static_cast<cudacodec::ColorFormat>(colorFormat) == formatToChannels.first);
312313
ASSERT_TRUE(reader->nextFrame(frame));
313-
if(!fmt.valid)
314-
fmt = reader->format();
315314
const int height = formatToChannels.first == cudacodec::ColorFormat::NV_NV12 ? static_cast<int>(1.5 * fmt.height) : fmt.height;
316315
ASSERT_TRUE(frame.cols == fmt.width && frame.rows == height);
317316
ASSERT_FALSE(frame.empty());
@@ -326,6 +325,7 @@ CUDA_TEST_P(ColorConversion, Reader)
326325
const std::string inputFile = std::string(cvtest::TS::ptr()->get_data_path()) + "../" + get<0>(GET_PARAM(2));
327326
const bool videoFullRangeFlag = get<1>(GET_PARAM(2));
328327
cv::Ptr<cv::cudacodec::VideoReader> reader = cv::cudacodec::createVideoReader(inputFile);
328+
cv::cudacodec::FormatInfo fmt = reader->format();
329329
reader->set(colorFormat);
330330
cv::VideoCapture cap(inputFile);
331331

@@ -336,8 +336,8 @@ CUDA_TEST_P(ColorConversion, Reader)
336336
reader->nextFrame(frame);
337337
frame.download(frameFromDevice);
338338
cap.read(frameHost);
339-
const cv::cudacodec::FormatInfo fmt = reader->format();
340-
ASSERT_TRUE(fmt.valid && fmt.videoFullRangeFlag == videoFullRangeFlag);
339+
fmt = reader->format();
340+
ASSERT_TRUE(fmt.videoFullRangeFlag == videoFullRangeFlag);
341341
if (colorFormat == cv::cudacodec::ColorFormat::BGRA)
342342
cv::cvtColor(frameHost, frameHostGs, COLOR_BGR2BGRA);
343343
else
@@ -384,7 +384,7 @@ CUDA_TEST_P(ReconfigureDecoderWithScaling, Reader)
384384
if (nFrames++ == 0)
385385
initialSize = frame.size();
386386
fmt = reader->format();
387-
ASSERT_TRUE(fmt.valid && (frame.size() == initialSize));
387+
ASSERT_TRUE(frame.size() == initialSize);
388388
ASSERT_TRUE((frame.size() == targetSzOut) && (fmt.targetSz == targetSzOut) && (fmt.srcRoi == srcRoiOut) && (fmt.targetRoi == targetRoiOut));
389389
// simple check - zero borders, non zero contents
390390
ASSERT_TRUE(!cuda::absSum(frame, mask)[0] && cuda::sum(frame)[0]);
@@ -413,7 +413,7 @@ CUDA_TEST_P(ReconfigureDecoder, Reader)
413413
initialSize = frame.size();
414414
initialCodedSize = Size(fmt.ulWidth, fmt.ulHeight);
415415
}
416-
ASSERT_TRUE(fmt.valid && (frame.size() == initialSize));
416+
ASSERT_TRUE(frame.size() == initialSize);
417417
ASSERT_TRUE(fmt.srcRoi.empty());
418418
const bool resChanged = (initialCodedSize.width != fmt.ulWidth) || (initialCodedSize.height != fmt.ulHeight);
419419
if (resChanged)
@@ -541,11 +541,6 @@ CUDA_TEST_P(CheckDecodeSurfaces, Reader)
541541
{
542542
cv::Ptr<cv::cudacodec::VideoReader> reader = cv::cudacodec::createVideoReader(inputFile);
543543
cv::cudacodec::FormatInfo fmt = reader->format();
544-
if (!fmt.valid) {
545-
reader->grab();
546-
fmt = reader->format();
547-
ASSERT_TRUE(fmt.valid);
548-
}
549544
ulNumDecodeSurfaces = fmt.ulNumDecodeSurfaces;
550545
}
551546

@@ -554,11 +549,6 @@ CUDA_TEST_P(CheckDecodeSurfaces, Reader)
554549
params.minNumDecodeSurfaces = ulNumDecodeSurfaces - 1;
555550
cv::Ptr<cv::cudacodec::VideoReader> reader = cv::cudacodec::createVideoReader(inputFile, {}, params);
556551
cv::cudacodec::FormatInfo fmt = reader->format();
557-
if (!fmt.valid) {
558-
reader->grab();
559-
fmt = reader->format();
560-
ASSERT_TRUE(fmt.valid);
561-
}
562552
ASSERT_TRUE(fmt.ulNumDecodeSurfaces == ulNumDecodeSurfaces);
563553
for (int i = 0; i < 100; i++) ASSERT_TRUE(reader->grab());
564554
}
@@ -568,11 +558,6 @@ CUDA_TEST_P(CheckDecodeSurfaces, Reader)
568558
params.minNumDecodeSurfaces = ulNumDecodeSurfaces + 1;
569559
cv::Ptr<cv::cudacodec::VideoReader> reader = cv::cudacodec::createVideoReader(inputFile, {}, params);
570560
cv::cudacodec::FormatInfo fmt = reader->format();
571-
if (!fmt.valid) {
572-
reader->grab();
573-
fmt = reader->format();
574-
ASSERT_TRUE(fmt.valid);
575-
}
576561
ASSERT_TRUE(fmt.ulNumDecodeSurfaces == ulNumDecodeSurfaces + 1);
577562
for (int i = 0; i < 100; i++) ASSERT_TRUE(reader->grab());
578563
}
@@ -626,10 +611,6 @@ CUDA_TEST_P(TransCode, H264ToH265)
626611
cv::cuda::Stream stream;
627612
for (int i = 0; i < nFrames; ++i) {
628613
ASSERT_TRUE(reader->nextFrame(frame, stream));
629-
if (!fmt.valid) {
630-
fmt = reader->format();
631-
ASSERT_TRUE(fmt.valid);
632-
}
633614
ASSERT_FALSE(frame.empty());
634615
Mat tst; frame.download(tst);
635616
if (writer.empty()) {

0 commit comments

Comments
 (0)