From 82e2792ab5cfaafc7d0c2ca7c22cecd56dba1c67 Mon Sep 17 00:00:00 2001 From: cudawarped <12133430+cudawarped@users.noreply.github.com> Date: Mon, 6 Mar 2023 12:19:05 +0200 Subject: [PATCH] cudacodec: ensure output frame resolution is display not coded size --- modules/cudacodec/src/video_parser.cpp | 8 +++--- modules/cudacodec/test/test_video.cpp | 37 ++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/modules/cudacodec/src/video_parser.cpp b/modules/cudacodec/src/video_parser.cpp index 8bccd065a8d..e9ce56339bc 100644 --- a/modules/cudacodec/src/video_parser.cpp +++ b/modules/cudacodec/src/video_parser.cpp @@ -122,16 +122,16 @@ int CUDAAPI cv::cudacodec::detail::VideoParser::HandleVideoSequence(void* userDa newFormat.ulHeight = format->coded_height; newFormat.fps = format->frame_rate.numerator / static_cast(format->frame_rate.denominator); newFormat.targetSz = thiz->videoDecoder_->getTargetSz(); - newFormat.width = newFormat.targetSz.width ? newFormat.targetSz.width : format->coded_width; - newFormat.height = newFormat.targetSz.height ? newFormat.targetSz.height : format->coded_height; newFormat.srcRoi = thiz->videoDecoder_->getSrcRoi(); if (newFormat.srcRoi.empty()) { - format->display_area.right = format->coded_width; - format->display_area.bottom = format->coded_height; 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(format->min_num_decode_surfaces)) : format->min_num_decode_surfaces * 2, 32); diff --git a/modules/cudacodec/test/test_video.cpp b/modules/cudacodec/test/test_video.cpp index b9b4e9f25c6..52105536225 100644 --- a/modules/cudacodec/test/test_video.cpp +++ b/modules/cudacodec/test/test_video.cpp @@ -58,6 +58,10 @@ PARAM_TEST_CASE(Scaling, cv::cuda::DeviceInfo, std::string, Size2f, Rect2f, Rect { }; +struct DisplayResolution : testing::TestWithParam +{ +}; + PARAM_TEST_CASE(Video, cv::cuda::DeviceInfo, std::string) { }; @@ -223,6 +227,37 @@ CUDA_TEST_P(Scaling, Reader) ASSERT_LT(mae, 2.35); } +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; + + { + // verify the output frame is the diplay size (1920x1080) and not the coded size (1920x1088) + cv::Ptr reader = cv::cudacodec::createVideoReader(inputFile); + reader->set(cudacodec::ColorFormat::GRAY); + ASSERT_TRUE(reader->nextFrame(frame)); + const cudacodec::FormatInfo format = reader->format(); + ASSERT_TRUE(format.displayArea == displayArea); + ASSERT_TRUE(frame.size() == displayArea.size() && frame.size() == format.targetSz); + } + + { + // extra check to verify display frame has not been post-processed and is just a cropped version of the coded sized frame + cudacodec::VideoReaderInitParams params; + params.srcRoi = Rect(0, 0, 1920, 1088); + cv::Ptr readerCodedSz = cv::cudacodec::createVideoReader(inputFile, {}, params); + readerCodedSz->set(cudacodec::ColorFormat::GRAY); + GpuMat frameCodedSz; + ASSERT_TRUE(readerCodedSz->nextFrame(frameCodedSz)); + const cudacodec::FormatInfo formatCodedSz = readerCodedSz->format(); + const double err = cv::cuda::norm(frame, frameCodedSz(displayArea), NORM_INF); + ASSERT_TRUE(err == 0); + } +} + CUDA_TEST_P(Video, Reader) { cv::cuda::setDevice(GET_PARAM(0).deviceID()); @@ -664,6 +699,8 @@ INSTANTIATE_TEST_CASE_P(CUDA_Codec, CheckSet, testing::Combine( INSTANTIATE_TEST_CASE_P(CUDA_Codec, Scaling, testing::Combine( ALL_DEVICES, testing::Values(VIDEO_SRC_SCALING), testing::Values(TARGET_SZ), testing::Values(SRC_ROI), testing::Values(TARGET_ROI))); +INSTANTIATE_TEST_CASE_P(CUDA_Codec, DisplayResolution, ALL_DEVICES); + #define VIDEO_SRC_R "highgui/video/big_buck_bunny.mp4", "cv/video/768x576.avi", "cv/video/1920x1080.avi", "highgui/video/big_buck_bunny.avi", \ "highgui/video/big_buck_bunny.h264", "highgui/video/big_buck_bunny.h265", "highgui/video/big_buck_bunny.mpg", \ "highgui/video/sample_322x242_15frames.yuv420p.libvpx-vp9.mp4", "highgui/video/sample_322x242_15frames.yuv420p.libaom-av1.mp4", \