From 66aba496f176bca320442e50205a1b00f445bb8f Mon Sep 17 00:00:00 2001 From: James Bowley Date: Tue, 11 Jun 2019 09:57:20 +0100 Subject: [PATCH] Add missing codecs to cudacodec which uses Nvidia Video Codec SDK including checks to ensure codec used in input video file is supported on the current device. Re-enable cudacodec performance test. --- .../cudacodec/include/opencv2/cudacodec.hpp | 4 ++ modules/cudacodec/perf/perf_video.cpp | 2 +- modules/cudacodec/src/cuvid_video_source.cpp | 1 + modules/cudacodec/src/ffmpeg_video_source.cpp | 1 + modules/cudacodec/src/video_decoder.cpp | 63 ++++++++++++++----- 5 files changed, 54 insertions(+), 17 deletions(-) diff --git a/modules/cudacodec/include/opencv2/cudacodec.hpp b/modules/cudacodec/include/opencv2/cudacodec.hpp index e404a48ce..dd8ae2000 100644 --- a/modules/cudacodec/include/opencv2/cudacodec.hpp +++ b/modules/cudacodec/include/opencv2/cudacodec.hpp @@ -250,6 +250,9 @@ enum Codec JPEG, H264_SVC, H264_MVC, + HEVC, + VP8, + VP9, Uncompressed_YUV420 = (('I'<<24)|('Y'<<16)|('U'<<8)|('V')), //!< Y,U,V (4:2:0) Uncompressed_YV12 = (('Y'<<24)|('V'<<16)|('1'<<8)|('2')), //!< Y,V,U (4:2:0) @@ -274,6 +277,7 @@ struct FormatInfo { Codec codec; ChromaFormat chromaFormat; + int nBitDepthMinus8; int width; int height; }; diff --git a/modules/cudacodec/perf/perf_video.cpp b/modules/cudacodec/perf/perf_video.cpp index 731f72c44..46f9c3bfb 100644 --- a/modules/cudacodec/perf/perf_video.cpp +++ b/modules/cudacodec/perf/perf_video.cpp @@ -51,7 +51,7 @@ DEF_PARAM_TEST_1(FileName, string); ////////////////////////////////////////////////////// // VideoReader -#if defined(HAVE_NVCUVID) && defined(HAVE_VIDEO_INPUT) +#if defined(HAVE_NVCUVID) PERF_TEST_P(FileName, VideoReader, Values("gpu/video/768x576.avi", "gpu/video/1920x1080.avi")) { diff --git a/modules/cudacodec/src/cuvid_video_source.cpp b/modules/cudacodec/src/cuvid_video_source.cpp index fd6eac72d..75366a0f7 100644 --- a/modules/cudacodec/src/cuvid_video_source.cpp +++ b/modules/cudacodec/src/cuvid_video_source.cpp @@ -70,6 +70,7 @@ cv::cudacodec::detail::CuvidVideoSource::CuvidVideoSource(const String& fname) format_.codec = static_cast(vidfmt.codec); format_.chromaFormat = static_cast(vidfmt.chroma_format); + format_.nBitDepthMinus8 = vidfmt.bit_depth_luma_minus8; format_.width = vidfmt.coded_width; format_.height = vidfmt.coded_height; } diff --git a/modules/cudacodec/src/ffmpeg_video_source.cpp b/modules/cudacodec/src/ffmpeg_video_source.cpp index 1978e7860..41c006e1c 100644 --- a/modules/cudacodec/src/ffmpeg_video_source.cpp +++ b/modules/cudacodec/src/ffmpeg_video_source.cpp @@ -111,6 +111,7 @@ cv::cudacodec::detail::FFmpegVideoSource::FFmpegVideoSource(const String& fname) format_.codec = static_cast(codec); format_.chromaFormat = static_cast(chroma_format); + format_.nBitDepthMinus8 = -1; format_.width = width; format_.height = height; } diff --git a/modules/cudacodec/src/video_decoder.cpp b/modules/cudacodec/src/video_decoder.cpp index 35919c3f5..c0a746784 100644 --- a/modules/cudacodec/src/video_decoder.cpp +++ b/modules/cudacodec/src/video_decoder.cpp @@ -57,22 +57,53 @@ void cv::cudacodec::detail::VideoDecoder::create(const FormatInfo& videoFormat) cudaVideoCreate_PreferCUVID; // Validate video format. These are the currently supported formats via NVCUVID - CV_Assert(cudaVideoCodec_MPEG1 == _codec || - cudaVideoCodec_MPEG2 == _codec || - cudaVideoCodec_MPEG4 == _codec || - cudaVideoCodec_VC1 == _codec || - cudaVideoCodec_H264 == _codec || - cudaVideoCodec_JPEG == _codec || - cudaVideoCodec_YUV420== _codec || - cudaVideoCodec_YV12 == _codec || - cudaVideoCodec_NV12 == _codec || - cudaVideoCodec_YUYV == _codec || - cudaVideoCodec_UYVY == _codec ); - - CV_Assert(cudaVideoChromaFormat_Monochrome == _chromaFormat || - cudaVideoChromaFormat_420 == _chromaFormat || - cudaVideoChromaFormat_422 == _chromaFormat || - cudaVideoChromaFormat_444 == _chromaFormat); + bool codecSupported = cudaVideoCodec_MPEG1 == _codec || + cudaVideoCodec_MPEG2 == _codec || + cudaVideoCodec_MPEG4 == _codec || + cudaVideoCodec_VC1 == _codec || + cudaVideoCodec_H264 == _codec || + cudaVideoCodec_JPEG == _codec || + cudaVideoCodec_H264_SVC == _codec || + cudaVideoCodec_H264_MVC == _codec || + cudaVideoCodec_YV12 == _codec || + cudaVideoCodec_NV12 == _codec || + cudaVideoCodec_YUYV == _codec || + cudaVideoCodec_UYVY == _codec; + +#if defined (HAVE_CUDA) +#if (CUDART_VERSION >= 6500) + codecSupported |= cudaVideoCodec_HEVC == _codec; +#endif +#if ((CUDART_VERSION == 7500) || (CUDART_VERSION >= 9000)) + codecSupported |= cudaVideoCodec_VP8 == _codec || + cudaVideoCodec_VP9 == _codec || + cudaVideoCodec_YUV420 == _codec; +#endif +#endif + + CV_Assert(codecSupported); + CV_Assert( cudaVideoChromaFormat_Monochrome == _chromaFormat || + cudaVideoChromaFormat_420 == _chromaFormat || + cudaVideoChromaFormat_422 == _chromaFormat || + cudaVideoChromaFormat_444 == _chromaFormat); + +#if (CUDART_VERSION >= 9000) + // Check video format is supported by GPU's hardware video decoder + if (videoFormat.nBitDepthMinus8 != -1) { // info not available call to create CuvidVideoSource() failed + CUVIDDECODECAPS decodeCaps = {}; + decodeCaps.eCodecType = _codec; + decodeCaps.eChromaFormat = _chromaFormat; + decodeCaps.nBitDepthMinus8 = videoFormat.nBitDepthMinus8; + cuSafeCall(cuvidGetDecoderCaps(&decodeCaps)); + if (!decodeCaps.bIsSupported) + CV_Error(Error::StsUnsupportedFormat, "Video source is not supported by hardware video decoder"); + + CV_Assert(videoFormat.width >= decodeCaps.nMinWidth && + videoFormat.height >= decodeCaps.nMinHeight && + videoFormat.width <= decodeCaps.nMaxWidth && + videoFormat.height <= decodeCaps.nMaxHeight); + } +#endif // Fill the decoder-create-info struct from the given video-format struct. std::memset(&createInfo_, 0, sizeof(CUVIDDECODECREATEINFO));