Skip to content

Commit

Permalink
cudacodec::VideoReader - ensure FormatInfo is valid before returning …
Browse files Browse the repository at this point in the history
…from createVideoReader
  • Loading branch information
cudawarped committed Jun 16, 2023
1 parent 7a4c0df commit d4b55f7
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 38 deletions.
6 changes: 4 additions & 2 deletions modules/cudacodec/src/video_decoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,9 +160,11 @@ void cv::cudacodec::detail::VideoDecoder::create(const FormatInfo& videoFormat)
createInfo_.ulCreationFlags = videoCreateFlags;
createInfo_.vidLock = lock_;
cuSafeCall(cuCtxPushCurrent(ctx_));
cuSafeCall(cuvidCreateDecoder(&decoder_, &createInfo_));
{
AutoLock autoLock(mtx_);
cuSafeCall(cuvidCreateDecoder(&decoder_, &createInfo_));
}
cuSafeCall(cuCtxPopCurrent(NULL));
inited_ = true;
}

int cv::cudacodec::detail::VideoDecoder::reconfigure(const FormatInfo& videoFormat) {
Expand Down
6 changes: 2 additions & 4 deletions modules/cudacodec/src/video_decoder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ class VideoDecoder
void create(const FormatInfo& videoFormat);
int reconfigure(const FormatInfo& videoFormat);
void release();
bool inited() { AutoLock autoLock(mtx_); return decoder_; }

// Get the codec-type currently used.
cudaVideoCodec codec() const { return static_cast<cudaVideoCodec>(videoFormat_.codec); }
Expand All @@ -85,8 +86,6 @@ class VideoDecoder
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; }

Expand Down Expand Up @@ -114,10 +113,9 @@ class VideoDecoder
private:
CUcontext ctx_ = 0;
CUvideoctxlock lock_;
CUvideodecoder decoder_ = 0;
CUvideodecoder decoder_ = 0;
FormatInfo videoFormat_ = {};
Mutex mtx_;
bool inited_ = false;
};

}}}
Expand Down
27 changes: 22 additions & 5 deletions modules/cudacodec/src/video_reader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,11 @@ void cvtFromNv12(const GpuMat& decodedFrame, GpuMat& outFrame, int width, int he
outFrame.create(height, width, CV_8UC3);
Npp8u* pSrc[2] = { decodedFrame.data, &decodedFrame.data[decodedFrame.step * height] };
NppiSize oSizeROI = { width,height };
#if (CUDART_VERSION < 9200)
CV_Error(Error::StsUnsupportedFormat, "ColorFormat::BGR is not supported until CUDA 9.2, use default ColorFormat::BGRA.");
#elif (CUDART_VERSION < 10100)
#if (CUDART_VERSION < 10100)
cv::cuda::NppStreamHandler h(stream);
if (videoFullRangeFlag)
nppSafeCall(nppiNV12ToBGR_709HDTV_8u_P2C3R(pSrc, decodedFrame.step, outFrame.data, outFrame.step, oSizeROI));
else {
CV_LOG_DEBUG(NULL, "Color reproduction may be inaccurate due CUDA version <= 11.0, for better results upgrade CUDA runtime or try ColorFormat::BGRA.");
nppSafeCall(nppiNV12ToBGR_8u_P2C3R(pSrc, decodedFrame.step, outFrame.data, outFrame.step, oSizeROI));
}
#elif (CUDART_VERSION >= 10100)
Expand All @@ -85,7 +82,6 @@ void cvtFromNv12(const GpuMat& decodedFrame, GpuMat& outFrame, int width, int he
nppSafeCall(nppiNV12ToBGR_709HDTV_8u_P2C3R_Ctx(pSrc, decodedFrame.step, outFrame.data, outFrame.step, oSizeROI, nppStreamCtx));
else {
#if (CUDART_VERSION < 11000)
CV_LOG_DEBUG(NULL, "Color reproduction may be inaccurate due CUDA version <= 11.0, for better results upgrade CUDA runtime or try ColorFormat::BGRA.");
nppSafeCall(nppiNV12ToBGR_8u_P2C3R_Ctx(pSrc, decodedFrame.step, outFrame.data, outFrame.step, oSizeROI, nppStreamCtx));
#else
nppSafeCall(nppiNV12ToBGR_709CSC_8u_P2C3R_Ctx(pSrc, decodedFrame.step, outFrame.data, outFrame.step, oSizeROI, nppStreamCtx));
Expand Down Expand Up @@ -137,6 +133,7 @@ namespace

private:
bool internalGrab(GpuMat& frame, Stream& stream);
void waitForDecoderInit();

Ptr<VideoSource> videoSource_;

Expand All @@ -160,6 +157,15 @@ namespace
return videoSource_->format();
}

void VideoReaderImpl::waitForDecoderInit() {
for (;;) {
if (videoDecoder_->inited()) break;
if (videoParser_->hasError() || frameQueue_->isEndOfDecode())
CV_Error(Error::StsError, "Parsing/Decoding video source failed, check GPU memory is available and GPU supports hardware decoding.");
Thread::sleep(1);
}
}

VideoReaderImpl::VideoReaderImpl(const Ptr<VideoSource>& source, const int minNumDecodeSurfaces, const bool allowFrameDrop, const bool udpSource,
const Size targetSz, const Rect srcRoi, const Rect targetRoi) :
videoSource_(source),
Expand All @@ -177,6 +183,8 @@ namespace
videoParser_.reset(new VideoParser(videoDecoder_, frameQueue_, allowFrameDrop, udpSource));
videoSource_->setVideoParser(videoParser_);
videoSource_->start();
waitForDecoderInit();
videoSource_->updateFormat(videoDecoder_->format());
}

VideoReaderImpl::~VideoReaderImpl()
Expand Down Expand Up @@ -307,6 +315,15 @@ namespace

bool VideoReaderImpl::set(const ColorFormat colorFormat_) {
if (!ValidColorFormat(colorFormat_)) return false;
if (colorFormat_ == ColorFormat::BGR) {
#if (CUDART_VERSION < 9200)
CV_LOG_DEBUG(NULL, "ColorFormat::BGR is not supported until CUDA 9.2, use default ColorFormat::BGRA.");
return false;
#elif (CUDART_VERSION < 11000)
if (!videoDecoder_->format().videoFullRangeFlag)
CV_LOG_INFO(NULL, "Color reproduction may be inaccurate due CUDA version <= 11.0, for better results upgrade CUDA runtime or try ColorFormat::BGRA.");
#endif
}
colorFormat = colorFormat_;
return true;
}
Expand Down
35 changes: 8 additions & 27 deletions modules/cudacodec/test/test_video.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -230,14 +230,15 @@ CUDA_TEST_P(Scaling, Reader)
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);
const cudacodec::FormatInfo format = reader->format();
ASSERT_TRUE(format.valid);
ASSERT_TRUE(reader->set(cudacodec::ColorFormat::GRAY));
GpuMat frame;
ASSERT_TRUE(reader->nextFrame(frame));
const cudacodec::FormatInfo format = reader->format();
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(format.targetSz == targetSzOut && format.srcRoi == srcRoiOut && format.targetRoi == targetRoiOut);
ASSERT_TRUE(frame.size() == targetSzOut);
GpuMat frameGs;
cv::cuda::resize(frameOr(srcRoiOut), frameGs, targetRoiOut.size(), 0, 0, INTER_AREA);
Expand Down Expand Up @@ -310,8 +311,6 @@ CUDA_TEST_P(Video, Reader)
double colorFormat;
ASSERT_TRUE(reader->get(cudacodec::VideoReaderProps::PROP_COLOR_FORMAT, colorFormat) && static_cast<cudacodec::ColorFormat>(colorFormat) == formatToChannels.first);
ASSERT_TRUE(reader->nextFrame(frame));
if(!fmt.valid)
fmt = reader->format();
const int height = formatToChannels.first == cudacodec::ColorFormat::NV_NV12 ? static_cast<int>(1.5 * fmt.height) : fmt.height;
ASSERT_TRUE(frame.cols == fmt.width && frame.rows == height);
ASSERT_FALSE(frame.empty());
Expand All @@ -326,6 +325,7 @@ CUDA_TEST_P(ColorConversion, Reader)
const std::string inputFile = std::string(cvtest::TS::ptr()->get_data_path()) + "../" + get<0>(GET_PARAM(2));
const bool videoFullRangeFlag = get<1>(GET_PARAM(2));
cv::Ptr<cv::cudacodec::VideoReader> reader = cv::cudacodec::createVideoReader(inputFile);
cv::cudacodec::FormatInfo fmt = reader->format();
reader->set(colorFormat);
cv::VideoCapture cap(inputFile);

Expand All @@ -336,8 +336,8 @@ CUDA_TEST_P(ColorConversion, Reader)
reader->nextFrame(frame);
frame.download(frameFromDevice);
cap.read(frameHost);
const cv::cudacodec::FormatInfo fmt = reader->format();
ASSERT_TRUE(fmt.valid && fmt.videoFullRangeFlag == videoFullRangeFlag);
fmt = reader->format();
ASSERT_TRUE(fmt.videoFullRangeFlag == videoFullRangeFlag);
if (colorFormat == cv::cudacodec::ColorFormat::BGRA)
cv::cvtColor(frameHost, frameHostGs, COLOR_BGR2BGRA);
else
Expand Down Expand Up @@ -384,7 +384,7 @@ CUDA_TEST_P(ReconfigureDecoderWithScaling, Reader)
if (nFrames++ == 0)
initialSize = frame.size();
fmt = reader->format();
ASSERT_TRUE(fmt.valid && (frame.size() == initialSize));
ASSERT_TRUE(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]);
Expand Down Expand Up @@ -413,7 +413,7 @@ CUDA_TEST_P(ReconfigureDecoder, Reader)
initialSize = frame.size();
initialCodedSize = Size(fmt.ulWidth, fmt.ulHeight);
}
ASSERT_TRUE(fmt.valid && (frame.size() == initialSize));
ASSERT_TRUE(frame.size() == initialSize);
ASSERT_TRUE(fmt.srcRoi.empty());
const bool resChanged = (initialCodedSize.width != fmt.ulWidth) || (initialCodedSize.height != fmt.ulHeight);
if (resChanged)
Expand Down Expand Up @@ -541,11 +541,6 @@ CUDA_TEST_P(CheckDecodeSurfaces, Reader)
{
cv::Ptr<cv::cudacodec::VideoReader> reader = cv::cudacodec::createVideoReader(inputFile);
cv::cudacodec::FormatInfo fmt = reader->format();
if (!fmt.valid) {
reader->grab();
fmt = reader->format();
ASSERT_TRUE(fmt.valid);
}
ulNumDecodeSurfaces = fmt.ulNumDecodeSurfaces;
}

Expand All @@ -554,11 +549,6 @@ CUDA_TEST_P(CheckDecodeSurfaces, Reader)
params.minNumDecodeSurfaces = ulNumDecodeSurfaces - 1;
cv::Ptr<cv::cudacodec::VideoReader> reader = cv::cudacodec::createVideoReader(inputFile, {}, params);
cv::cudacodec::FormatInfo fmt = reader->format();
if (!fmt.valid) {
reader->grab();
fmt = reader->format();
ASSERT_TRUE(fmt.valid);
}
ASSERT_TRUE(fmt.ulNumDecodeSurfaces == ulNumDecodeSurfaces);
for (int i = 0; i < 100; i++) ASSERT_TRUE(reader->grab());
}
Expand All @@ -568,11 +558,6 @@ CUDA_TEST_P(CheckDecodeSurfaces, Reader)
params.minNumDecodeSurfaces = ulNumDecodeSurfaces + 1;
cv::Ptr<cv::cudacodec::VideoReader> reader = cv::cudacodec::createVideoReader(inputFile, {}, params);
cv::cudacodec::FormatInfo fmt = reader->format();
if (!fmt.valid) {
reader->grab();
fmt = reader->format();
ASSERT_TRUE(fmt.valid);
}
ASSERT_TRUE(fmt.ulNumDecodeSurfaces == ulNumDecodeSurfaces + 1);
for (int i = 0; i < 100; i++) ASSERT_TRUE(reader->grab());
}
Expand Down Expand Up @@ -626,10 +611,6 @@ CUDA_TEST_P(TransCode, H264ToH265)
cv::cuda::Stream stream;
for (int i = 0; i < nFrames; ++i) {
ASSERT_TRUE(reader->nextFrame(frame, stream));
if (!fmt.valid) {
fmt = reader->format();
ASSERT_TRUE(fmt.valid);
}
ASSERT_FALSE(frame.empty());
Mat tst; frame.download(tst);
if (writer.empty()) {
Expand Down

0 comments on commit d4b55f7

Please sign in to comment.