vendor: OpenCV 5.0.0 snapshot at 755e50675d97db9b7d449d8bd6b09888646f6c6e

This commit is contained in:
Gitea Mirror Bot
2026-08-22 00:11:13 +08:00
commit 12022378a3
3872 changed files with 2513409 additions and 0 deletions
+52
View File
@@ -0,0 +1,52 @@
if(IOS OR APPLE OR WINRT OR (NOT HAVE_CUDA AND NOT BUILD_CUDA_STUBS))
ocv_module_disable(cudacodec)
endif()
set(the_description "CUDA-accelerated Video Encoding/Decoding")
if(WIN32)
ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4127 /wd4324 /wd4512)
else()
ocv_warnings_disable(CMAKE_CXX_FLAGS -Wundef -Wshadow -Wsign-compare -Wenum-compare)
endif()
set(required_dependencies opencv_core opencv_videoio opencv_cudaarithm opencv_cudawarping)
if(HAVE_NVCUVENC)
list(APPEND required_dependencies opencv_cudaimgproc)
endif()
ocv_add_module(cudacodec ${required_dependencies} OPTIONAL opencv_cudev WRAP python)
ocv_module_include_directories()
ocv_glob_module_sources()
set(extra_libs "")
if(WITH_NVCUVID AND NOT HAVE_NVCUVID)
message(WARNING "cudacodec::VideoReader requires Nvidia Video Codec SDK. Please resolve dependency or disable WITH_NVCUVID=OFF")
endif()
if(WITH_NVCUVENC AND NOT HAVE_NVCUVENC)
message(WARNING "cudacodec::VideoWriter requires Nvidia Video Codec SDK. Please resolve dependency or disable WITH_NVCUVENC=OFF")
endif()
if(ENABLE_CUDA_FIRST_CLASS_LANGUAGE)
list(APPEND extra_libs CUDA::cuda_driver CUDA::cudart${CUDA_LIB_EXT})
else()
list(APPEND extra_libs ${CUDA_CUDA_LIBRARY})
endif()
if(HAVE_NVCUVID)
list(APPEND extra_libs ${CUDA_nvcuvid_LIBRARY})
endif()
if(HAVE_NVCUVENC)
if(WIN32)
list(APPEND extra_libs ${CUDA_nvencodeapi_LIBRARY})
else()
list(APPEND extra_libs ${CUDA_nvidia-encode_LIBRARY})
endif()
endif()
ocv_create_module(${extra_libs})
ocv_add_accuracy_tests()
ocv_add_perf_tests()
@@ -0,0 +1,674 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef OPENCV_CUDACODEC_HPP
#define OPENCV_CUDACODEC_HPP
#ifndef __cplusplus
# error cudacodec.hpp header must be compiled as C++
#endif
#include "opencv2/core/cuda.hpp"
/**
@addtogroup cuda
@{
@defgroup cudacodec Video Encoding/Decoding
@}
*/
namespace cv { namespace cudacodec {
//! @addtogroup cudacodec
//! @{
////////////////////////////////// Video Encoding //////////////////////////////////
/** @brief Video codecs supported by cudacodec::VideoReader and cudacodec::VideoWriter.
@note
- Support will depend on your hardware, refer to the Nvidia Video Codec SDK Video Encode and Decode GPU Support Matrix for details.
*/
enum Codec
{
MPEG1 = 0,
MPEG2,
MPEG4,
VC1,
H264,
JPEG,
H264_SVC,
H264_MVC,
HEVC,
VP8,
VP9,
AV1,
NumCodecs,
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)
Uncompressed_NV12 = (('N' << 24) | ('V' << 16) | ('1' << 8) | ('2')), //!< Y,UV (4:2:0)
Uncompressed_YUYV = (('Y' << 24) | ('U' << 16) | ('Y' << 8) | ('V')), //!< YUYV/YUY2 (4:2:2)
Uncompressed_UYVY = (('U' << 24) | ('Y' << 16) | ('V' << 8) | ('Y')) //!< UYVY (4:2:2)
};
/** @brief ColorFormat for the frame returned by VideoReader::nextFrame() and VideoReader::retrieve() or used to initialize a VideoWriter.
*/
enum ColorFormat {
UNDEFINED = 0,
BGRA = 1, //!< OpenCV color format. VideoReader and VideoWriter.
BGR = 2, //!< OpenCV color format. VideoReader and VideoWriter.
GRAY = 3, //!< OpenCV color format. VideoReader and VideoWriter.
RGB = 5, //!< OpenCV color format. VideoReader and VideoWriter.
RGBA = 6, //!< OpenCV color format. VideoReader and VideoWriter.
NV_YUV_SURFACE_FORMAT = 7, //!< Nvidia YUV Surface Format output by the Nvidia decoder, see @ref SurfaceFormat. VideoReader only.
NV_NV12 = 4, //!< Nvidia Buffer Format - Semi-Planar YUV [Y plane followed by interleaved UV plane]. VideoWriter only. @deprecated Deprecated for use with VideoReader, use @ref NV_YUV_SURFACE_FORMAT instead.
NV_YV12 = 8, //!< Nvidia Buffer Format - Planar YUV [Y plane followed by V and U planes]. VideoWriter only.
NV_IYUV = 9, //!< Nvidia Buffer Format - Planar YUV [Y plane followed by U and V planes]. VideoWriter only.
NV_YUV444 = 10, //!< Nvidia Buffer Format - Planar YUV [Y plane followed by U and V planes]. VideoWriter only.
NV_AYUV = 11, //!< Nvidia Buffer Format - 8 bit Packed A8Y8U8V8. This is a word-ordered format where a pixel is represented by a 32-bit word with V in the lowest 8 bits, U in the next 8 bits, Y in the 8 bits after that and A in the highest 8 bits. VideoWriter only.
NV_YUV420_10BIT = 12, //!< Nvidia Buffer Format - 10 bit Semi-Planar YUV [Y plane followed by interleaved UV plane]. Each pixel of size 2 bytes. Most Significant 10 bits contain pixel data. VideoWriter only.
NV_YUV444_10BIT = 13, //!< Nvidia Buffer Format - 10 bit Planar YUV444 [Y plane followed by U and V planes]. Each pixel of size 2 bytes. Most Significant 10 bits contain pixel data. VideoWriter only.
#ifndef CV_DOXYGEN
PROP_NOT_SUPPORTED
#endif
};
/** @brief Rate Control Modes.
*/
enum EncodeParamsRcMode {
ENC_PARAMS_RC_CONSTQP = 0x0, //!< Constant QP mode.
ENC_PARAMS_RC_VBR = 0x1, //!< Variable bitrate mode.
ENC_PARAMS_RC_CBR = 0x2 //!< Constant bitrate mode.
};
/** @brief Multi Pass Encoding.
*/
enum EncodeMultiPass
{
ENC_MULTI_PASS_DISABLED = 0x0, //!< Single Pass.
ENC_TWO_PASS_QUARTER_RESOLUTION = 0x1, //!< Two Pass encoding is enabled where first Pass is quarter resolution.
ENC_TWO_PASS_FULL_RESOLUTION = 0x2, //!< Two Pass encoding is enabled where first Pass is full resolution.
};
/** @brief Supported Encoder Profiles.
*/
enum EncodeProfile {
ENC_CODEC_PROFILE_AUTOSELECT = 0,
ENC_H264_PROFILE_BASELINE = 1,
ENC_H264_PROFILE_MAIN = 2,
ENC_H264_PROFILE_HIGH = 3,
ENC_H264_PROFILE_HIGH_444 = 4,
ENC_H264_PROFILE_STEREO = 5,
ENC_H264_PROFILE_PROGRESSIVE_HIGH = 6,
ENC_H264_PROFILE_CONSTRAINED_HIGH = 7,
ENC_HEVC_PROFILE_MAIN = 8,
ENC_HEVC_PROFILE_MAIN10 = 9,
ENC_HEVC_PROFILE_FREXT = 10
};
/** @brief Nvidia Encoding Presets. Performance degrades and quality improves as we move from P1 to P7.
*/
enum EncodePreset {
ENC_PRESET_P1 = 1,
ENC_PRESET_P2 = 2,
ENC_PRESET_P3 = 3,
ENC_PRESET_P4 = 4,
ENC_PRESET_P5 = 5,
ENC_PRESET_P6 = 6,
ENC_PRESET_P7 = 7
};
/** @brief Tuning information.
*/
enum EncodeTuningInfo {
ENC_TUNING_INFO_UNDEFINED = 0, //!< Undefined tuningInfo. Invalid value for encoding.
ENC_TUNING_INFO_HIGH_QUALITY = 1, //!< Tune presets for latency tolerant encoding.
ENC_TUNING_INFO_LOW_LATENCY = 2, //!< Tune presets for low latency streaming.
ENC_TUNING_INFO_ULTRA_LOW_LATENCY = 3, //!< Tune presets for ultra low latency streaming.
ENC_TUNING_INFO_LOSSLESS = 4, //!< Tune presets for lossless encoding.
ENC_TUNING_INFO_COUNT
};
/** Quantization Parameter for each type of frame when using ENC_PARAMS_RC_MODE::ENC_PARAMS_RC_CONSTQP.
*/
struct CV_EXPORTS_W_SIMPLE EncodeQp
{
CV_PROP_RW uint32_t qpInterP; //!< Specifies QP value for P-frame.
CV_PROP_RW uint32_t qpInterB; //!< Specifies QP value for B-frame.
CV_PROP_RW uint32_t qpIntra; //!< Specifies QP value for Intra Frame.
};
/** @brief Different parameters for CUDA video encoder.
*/
struct CV_EXPORTS_W_SIMPLE EncoderParams
{
public:
CV_WRAP EncoderParams() : nvPreset(ENC_PRESET_P3), tuningInfo(ENC_TUNING_INFO_HIGH_QUALITY), encodingProfile(ENC_CODEC_PROFILE_AUTOSELECT),
rateControlMode(ENC_PARAMS_RC_VBR), multiPassEncoding(ENC_MULTI_PASS_DISABLED), constQp({ 0,0,0 }), averageBitRate(0), maxBitRate(0),
targetQuality(30), gopLength(250), idrPeriod(250), videoFullRangeFlag(false){};
CV_PROP_RW EncodePreset nvPreset;
CV_PROP_RW EncodeTuningInfo tuningInfo;
CV_PROP_RW EncodeProfile encodingProfile;
CV_PROP_RW EncodeParamsRcMode rateControlMode;
CV_PROP_RW EncodeMultiPass multiPassEncoding;
CV_PROP_RW EncodeQp constQp; //!< QP's for \ref ENC_PARAMS_RC_CONSTQP.
CV_PROP_RW int averageBitRate; //!< target bitrate for \ref ENC_PARAMS_RC_VBR and \ref ENC_PARAMS_RC_CBR.
CV_PROP_RW int maxBitRate; //!< upper bound on bitrate for \ref ENC_PARAMS_RC_VBR and \ref ENC_PARAMS_RC_CONSTQP.
CV_PROP_RW uint8_t targetQuality; //!< value 0 - 51 where video quality decreases as targetQuality increases, used with \ref ENC_PARAMS_RC_VBR.
CV_PROP_RW int gopLength; //!< the number of pictures in one GOP, ensuring \ref idrPeriod >= \ref gopLength.
CV_PROP_RW int idrPeriod; //!< IDR interval, ensuring \ref idrPeriod >= \ref gopLength.
CV_PROP_RW bool videoFullRangeFlag;//!< Indicates if the black level, luma and chroma of the source are represented using the full or limited range (AKA TV or "analogue" range) of values as defined in Annex E of the ITU-T Specification.
};
CV_EXPORTS bool operator==(const EncoderParams& lhs, const EncoderParams& rhs);
/** @brief Interface for encoder callbacks.
User can implement own multiplexing by implementing this interface.
*/
class CV_EXPORTS_W EncoderCallback {
public:
/** @brief Callback function to signal that the encoded bitstream for one or more frames is ready.
@param vPacket The raw bitstream for one or more frames.
@param pts Presentation timestamps for each frame in vPacket using the FPS time base. e.g. fps = 25, pts = 3, presentation time = 3/25 seconds.
*/
virtual void onEncoded(const std::vector<std::vector<uint8_t>>& vPacket, const std::vector<uint64_t>& pts) = 0;
/** @brief Set the GOP pattern used by the encoder.
@param frameIntervalP Specify the GOP pattern as follows : \p frameIntervalP = 0: I, 1 : IPP, 2 : IBP, 3 : IBBP.
*/
virtual bool setFrameIntervalP(const int frameIntervalP) = 0;
/** @brief Callback function to that the encoding has finished.
* */
virtual void onEncodingFinished() = 0;
virtual ~EncoderCallback() {}
};
/** @brief Video writer interface, see createVideoWriter().
Available if Nvidia's Video Codec SDK is installed.
Only Codec::H264 and Codec::HEVC are supported with encoding support dependent on the GPU, refer to the Nvidia Video Codec SDK Video Encode and Decode GPU Support Matrix for details.
@note
- An example on how to use the VideoWriter class can be found at
opencv_source_code/samples/gpu/video_writer.cpp
*/
class CV_EXPORTS_W VideoWriter
{
public:
virtual ~VideoWriter() {}
/** @brief Writes the next video frame.
@param frame The framet to be written.
The method encodes the specified image to a video stream. The image must have the same size and the same
surface format as has been specified when opening the video writer.
*/
CV_WRAP virtual void write(InputArray frame) = 0;
/** @brief Retrieve the encoding parameters.
*/
CV_WRAP virtual EncoderParams getEncoderParams() const = 0;
/** @brief Waits until the encoding process has finished before calling EncoderCallback::onEncodingFinished().
*/
CV_WRAP virtual void release() = 0;
};
/** @brief Creates video writer.
@param fileName Name of the output video file.
@param frameSize Size of the input video frames.
@param codec Supports Codec::H264 and Codec::HEVC.
@param fps Framerate of the created video stream.
@param colorFormat OpenCv color format of the frames to be encoded.
@param encoderCallback Callbacks for video encoder. See cudacodec::EncoderCallback. Required for working with the encoded video stream.
@param stream Stream for frame pre-processing.
*/
CV_EXPORTS_W Ptr<cudacodec::VideoWriter> createVideoWriter(const String& fileName, const Size frameSize, const Codec codec = Codec::H264, const double fps = 25.0,
const ColorFormat colorFormat = ColorFormat::BGR, Ptr<EncoderCallback> encoderCallback = 0, const cuda::Stream& stream = cuda::Stream::Null());
/** @brief Creates video writer.
@param fileName Name of the output video file.
@param frameSize Size of the input video frames.
@param codec Supports Codec::H264 and Codec::HEVC.
@param fps Framerate of the created video stream.
@param colorFormat OpenCv color format of the frames to be encoded.
@param params Additional encoding parameters.
@param encoderCallback Callbacks for video encoder. See cudacodec::EncoderCallback. Required for working with the encoded video stream.
@param stream Stream for frame pre-processing.
*/
CV_EXPORTS_W Ptr<cudacodec::VideoWriter> createVideoWriter(const String& fileName, const Size frameSize, const Codec codec, const double fps, const ColorFormat colorFormat,
const EncoderParams& params, Ptr<EncoderCallback> encoderCallback = 0, const cuda::Stream& stream = cuda::Stream::Null());
////////////////////////////////// Video Decoding //////////////////////////////////////////
/** @brief Chroma formats supported by cudacodec::VideoReader.
*/
enum ChromaFormat
{
Monochrome = 0,
YUV420,
YUV422,
YUV444,
NumFormats
};
/** @brief Deinterlacing mode used by decoder. */
enum DeinterlaceMode
{
Weave = 0, //!< Weave both fields(no deinterlacing).For progressive content and for content that doesn't need deinterlacing.
Bob = 1, //!< Drop one field.
Adaptive = 2 //!< Adaptive deinterlacing needs more video memory than other deinterlacing modes.
};
/** @brief Video Signal Description Color Primaries of the VideoReader source (section E.2.1 VUI parameters semantics of H265 spec file) */
enum class ColorSpaceStandard {
BT709 = 1, //!< ITU-R BT.709 standard for high-definition television.
Unspecified = 2, //!< Unspecified color space standard.
Reserved = 3, //!< Reserved for future use.
FCC = 4, //!< FCC color space standard.
BT470 = 5, //!< ITU - R BT.470, used for older analog television systems.
BT601 = 6, //!< ITU - R BT.601, used for standard definition television.
SMPTE240M = 7, //!< SMPTE 240M, used for early HDTV systems.
YCgCo = 8, //!< YCgCo color space, used in some video compression algorithms.
BT2020 = 9, //!< ITU - R BT.2020, used for ultra-high-definition television.
BT2020C = 10 //!< ITU - R BT.2020 Constant Luminance, used for ultra-high-definition television.
};
/** @brief Video surface formats output by the decoder */
enum SurfaceFormat {
SF_NV12 = 0, //!< Semi-Planar YUV [Y plane followed by interleaved UV plane]
SF_P016 = 1, //!< 16 bit Semi-Planar YUV [Y plane followed by interleaved UV plane]. Can be used for 10 bit(6LSB bits 0), 12 bit (4LSB bits 0)
SF_YUV444 = 2, //!< Planar YUV [Y plane followed by U and V planes]
SF_YUV444_16Bit = 3 //!< 16 bit Planar YUV [Y plane followed by U and V planes]. Can be used for 10 bit(6LSB bits 0), 12 bit (4LSB bits 0)
};
/** @brief Bit depth of the frame returned by VideoReader::nextFrame() and VideoReader::retrieve() */
enum BitDepth {
EIGHT = 0, //!< 8 bit depth.
SIXTEEN = 1, //!< 16 bit depth.
UNCHANGED = 2 //!< Use source bit depth.
};
/** @brief Utility function demonstrating how to map the luma histogram when FormatInfo::videoFullRangeFlag == false
@param hist Luma histogram \a hist returned from VideoReader::nextFrame(GpuMat& frame, GpuMat& hist, Stream& stream).
@param histFull Host histogram equivelent to downloading \a hist after calling cuda::calcHist(InputArray frame, OutputArray hist, Stream& stream).
@note
- This function demonstrates how to map the luma histogram back so that it is equivalent to the result obtained from cuda::calcHist()
if the returned frame was ColorFormat::GRAY.
*/
CV_EXPORTS_W void MapHist(const cuda::GpuMat& hist, CV_OUT Mat& histFull);
/** @brief Struct providing information about video file format. :
*/
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),
fps(0), ulNumDecodeSurfaces(0), videoFullRangeFlag(false), colorSpaceStandard(ColorSpaceStandard::BT601), enableHistogram(false), nCounterBitDepth(0), nMaxHistogramBins(0){};
CV_PROP_RW Codec codec;
CV_PROP_RW ChromaFormat chromaFormat;
CV_PROP_RW SurfaceFormat surfaceFormat; //!< Surface format of the decoded frame.
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).
CV_PROP_RW int height;//!< Height of the decoded frame returned by nextFrame(frame).
int ulMaxWidth;
int ulMaxHeight;
CV_PROP_RW Rect displayArea;//!< ROI inside the decoded frame returned by nextFrame(frame), containing the useable video frame.
CV_PROP_RW bool valid;
CV_PROP_RW double fps;
CV_PROP_RW int ulNumDecodeSurfaces;//!< Maximum number of internal decode surfaces.
CV_PROP_RW DeinterlaceMode deinterlaceMode;
CV_PROP_RW cv::Size targetSz;//!< Post-processed size of the output frame.
CV_PROP_RW cv::Rect srcRoi;//!< Region of interest decoded from video source.
CV_PROP_RW cv::Rect targetRoi;//!< Region of interest in the output frame containing the decoded frame.
CV_PROP_RW bool videoFullRangeFlag;//!< Output value indicating if the black level, luma and chroma of the source are represented using the full or limited range (AKA TV or "analogue" range) of values as defined in Annex E of the ITU-T Specification.
CV_PROP_RW ColorSpaceStandard colorSpaceStandard; //!< Video Signal Description Color Primaries of the VideoReader source (section E.2.1 VUI parameters semantics of H265 spec file)
CV_PROP_RW bool enableHistogram;//!< Flag requesting histogram output if supported. Exception will be thrown when requested but not supported.
CV_PROP_RW int nCounterBitDepth;//!< Bit depth of histogram bins if histogram output is requested and supported.
CV_PROP_RW int nMaxHistogramBins;//!< Max number of histogram bins if histogram output is requested and supported.
};
/** @brief Class for converting the raw YUV Surface output from VideoReader if output color format is set to ColorFormat::NV_YUV_SURFACE_FORMAT (VideoReader::set(ColorFormat::NV_YUV_SURFACE_FORMAT)) to the requested @ref ColorFormat.
*/
class CV_EXPORTS_W NVSurfaceToColorConverter {
public:
/** @brief Performs the conversion from the raw YUV Surface output from VideoReader to the requested color format. Use this function when you want to convert the raw YUV Surface output from VideoReader to more than one color format or you want both the raw Surface output in addition to a color frame.
* @param yuv The raw YUV Surface output from VideoReader see @ref SurfaceFormat.
* @param color The converted frame.
* @param surfaceFormat The surface format of the input YUV data.
* @param outputFormat The requested output color format.
* @param bitDepth The requested bit depth of the output frame.
* @param planar Request seperate planes for each color plane.
* @param stream Stream for the asynchronous version.
*/
CV_WRAP virtual bool convert(InputArray yuv, OutputArray color, const SurfaceFormat surfaceFormat, const ColorFormat outputFormat, const BitDepth bitDepth = BitDepth::UNCHANGED, const bool planar = false, cuda::Stream& stream = cuda::Stream::Null()) = 0;
virtual ~NVSurfaceToColorConverter() {};
};
/** @brief Creates a NVSurfaceToColorConverter.
* @param colorSpace The requested @ref ColorSpaceStandard for the converter.
* @param videoFullRangeFlag Indicates if the black level, luma and chroma of the source are represented using the full or limited range (AKA TV or "analogue" range) of values as defined in Annex E of the ITU-T Specification.
*/
CV_EXPORTS_W Ptr<NVSurfaceToColorConverter> createNVSurfaceToColorConverter(const ColorSpaceStandard colorSpace, const bool videoFullRangeFlag = false);
/** @brief cv::cudacodec::VideoReader generic properties identifier.
*/
enum class VideoReaderProps {
PROP_DECODED_FRAME_IDX = 0, //!< Index for retrieving the decoded frame using retrieve().
PROP_EXTRA_DATA_INDEX = 1, //!< Index for retrieving the extra data associated with a video source using retrieve().
PROP_RAW_PACKAGES_BASE_INDEX = 2, //!< Base index for retrieving raw encoded data using retrieve().
PROP_NUMBER_OF_RAW_PACKAGES_SINCE_LAST_GRAB = 3, //!< Number of raw packages recieved since the last call to grab().
PROP_RAW_MODE = 4, //!< Status of raw mode.
PROP_LRF_HAS_KEY_FRAME = 5, //!< FFmpeg source only - Indicates whether the Last Raw Frame (LRF), output from VideoReader::retrieve() when VideoReader is initialized in raw mode, contains encoded data for a key frame.
PROP_COLOR_FORMAT = 6, //!< ColorFormat of the decoded frame. This can be changed before every call to nextFrame() and retrieve().
PROP_UDP_SOURCE = 7, //!< Status of VideoReaderInitParams::udpSource initialization.
PROP_ALLOW_FRAME_DROP = 8, //!< Status of VideoReaderInitParams::allowFrameDrop initialization.
PROP_BIT_DEPTH = 9, //!< Bit depth of the decoded frame. This can be changed before every call to nextFrame() and retrieve().
PROP_PLANAR = 10, //!< Planar when true, packed when false. This can be changed before every call to nextFrame() and retrieve().
#ifndef CV_DOXYGEN
PROP_NOT_SUPPORTED
#endif
};
/** @brief Video reader interface, see createVideoReader().
Available if Nvidia's Video Codec SDK is installed.
Decoding support is dependent on the GPU, refer to the Nvidia Video Codec SDK Video Encode and Decode GPU Support Matrix for details.
@note
- An example on how to use the VideoReader interface can be found at
opencv_source_code/samples/gpu/video_reader.cpp
*/
class CV_EXPORTS_W VideoReader
{
public:
virtual ~VideoReader() {}
/** @brief Grabs, decodes and returns the next video frame.
@param [out] frame The video frame.
@param stream Stream for the asynchronous version.
@return `false` if no frames have been grabbed.
If no frames have been grabbed (there are no more frames in video file), the methods return false.
The method throws an Exception if error occurs.
*/
CV_WRAP virtual bool nextFrame(CV_OUT cuda::GpuMat& frame, cuda::Stream &stream = cuda::Stream::Null()) = 0;
/** @brief Grabs, decodes and returns the next video frame and frame luma histogram.
@param [out] frame The video frame.
@param [out] histogram Histogram of the luma component of the encoded frame, see note.
@param stream Stream for the asynchronous version.
@return `false` if no frames have been grabbed.
If no frames have been grabbed (there are no more frames in video file), the methods return false.
The method throws an Exception if error occurs.
@note Histogram data is collected by NVDEC during the decoding process resulting in zero performance penalty. NVDEC computes the histogram data for only the luma component of decoded output, not on post-processed frame(i.e. when scaling, cropping, etc. applied). If the source is encoded using a limited range of luma values (FormatInfo::videoFullRangeFlag == false) then the histogram bin values will correspond to to this limited range of values and will need to be mapped to contain the same output as cuda::calcHist(). The MapHist() utility function can be used to perform this mapping on the host if required.
*/
CV_WRAP_AS(nextFrameWithHist) virtual bool nextFrame(CV_OUT cuda::GpuMat& frame, CV_OUT cuda::GpuMat& histogram, cuda::Stream& stream = cuda::Stream::Null()) = 0;
/** @brief Returns information about video file format.
*/
CV_WRAP virtual FormatInfo format() const = 0;
/** @brief Grabs the next frame from the video source.
@param stream Stream for the asynchronous version.
@return `true` (non-zero) in the case of success.
The method/function grabs the next frame from video file or camera and returns true (non-zero) in
the case of success.
The primary use of the function is for reading both the encoded and decoded video data when rawMode is enabled. With rawMode enabled
retrieve() can be called following grab() to retrieve all the data associated with the current video source since the last call to grab() or the creation of the VideoReader.
*/
CV_WRAP virtual bool grab(cuda::Stream& stream = cuda::Stream::Null()) = 0;
/** @brief Returns previously grabbed video data.
@param [out] frame The returned data which depends on the provided idx.
@param idx Determines the returned data inside image. The returned data can be the:
- Decoded frame, idx = get(PROP_DECODED_FRAME_IDX).
- Extra data if available, idx = get(PROP_EXTRA_DATA_INDEX).
- Raw encoded data package. To retrieve package i, idx = get(PROP_RAW_PACKAGES_BASE_INDEX) + i with i < get(PROP_NUMBER_OF_RAW_PACKAGES_SINCE_LAST_GRAB)
@return `false` if no frames have been grabbed
The method returns data associated with the current video source since the last call to grab() or the creation of the VideoReader. If no data is present
the method returns false and the function returns an empty image.
*/
virtual bool retrieve(OutputArray frame, const size_t idx = static_cast<size_t>(VideoReaderProps::PROP_DECODED_FRAME_IDX)) const = 0;
/** @brief Returns previously grabbed encoded video data.
@param [out] frame The encoded video data.
@param idx Determines the returned data inside image. The returned data can be the:
- Extra data if available, idx = get(PROP_EXTRA_DATA_INDEX).
- Raw encoded data package. To retrieve package i, idx = get(PROP_RAW_PACKAGES_BASE_INDEX) + i with i < get(PROP_NUMBER_OF_RAW_PACKAGES_SINCE_LAST_GRAB)
@return `false` if no frames have been grabbed
The method returns data associated with the current video source since the last call to grab() or the creation of the VideoReader. If no data is present
the method returns false and the function returns an empty image.
*/
CV_WRAP inline bool retrieve(CV_OUT Mat& frame, const size_t idx) const {
return retrieve(OutputArray(frame), idx);
}
/** @brief Returns the next video frame.
@param [out] frame The video frame. If grab() has not been called then this will be empty().
@return `false` if no frames have been grabbed
The method returns data associated with the current video source since the last call to grab(). If no data is present
the method returns false and the function returns an empty image.
*/
CV_WRAP inline bool retrieve(CV_OUT cuda::GpuMat& frame) const {
return retrieve(OutputArray(frame));
}
/** @brief Sets a property in the VideoReader.
@param propertyId Property identifier from cv::cudacodec::VideoReaderProps (eg. cv::cudacodec::VideoReaderProps::PROP_DECODED_FRAME_IDX,
cv::cudacodec::VideoReaderProps::PROP_EXTRA_DATA_INDEX, ...).
@param propertyVal Value of the property.
@return `true` if the property has been set.
*/
virtual bool set(const VideoReaderProps propertyId, const double propertyVal) = 0;
CV_WRAP inline bool setVideoReaderProps(const VideoReaderProps propertyId, double propertyVal) {
return set(propertyId, propertyVal);
}
/** @brief Set the desired ColorFormat for the frame returned by nextFrame()/retrieve().
@param colorFormat Value of the ColorFormat.
@param bitDepth Requested bit depth of the frame.
@param planar Set to true for planar and false for packed color format.
@return `true` unless the colorFormat is not supported.
*/
CV_WRAP virtual bool set(const ColorFormat colorFormat, const BitDepth bitDepth = BitDepth::UNCHANGED, const bool planar = false) = 0;
/** @brief Returns the specified VideoReader property
@param propertyId Property identifier from cv::cudacodec::VideoReaderProps (eg. cv::cudacodec::VideoReaderProps::PROP_DECODED_FRAME_IDX,
cv::cudacodec::VideoReaderProps::PROP_EXTRA_DATA_INDEX, ...).
@param propertyVal
- In: Optional value required for querying specific propertyId's, e.g. the index of the raw package to be checked for a key frame (cv::cudacodec::VideoReaderProps::PROP_LRF_HAS_KEY_FRAME).
- Out: Value of the property.
@return `true` unless the property is not supported.
*/
virtual bool get(const VideoReaderProps propertyId, double& propertyVal) const = 0;
CV_WRAP virtual bool getVideoReaderProps(const VideoReaderProps propertyId, CV_OUT double& propertyValOut, double propertyValIn = 0) const = 0;
/** @brief Retrieves the specified property used by the VideoSource.
@param propertyId Property identifier from cv::VideoCaptureProperties (eg. cv::CAP_PROP_POS_MSEC, cv::CAP_PROP_POS_FRAMES, ...)
or one from @ref videoio_flags_others.
@param propertyVal Value for the specified property.
@return `true` unless the property is unset set or not supported.
*/
CV_WRAP virtual bool get(const int propertyId, CV_OUT double& propertyVal) const = 0;
};
/** @brief Interface for video demultiplexing. :
User can implement own demultiplexing by implementing this interface.
*/
class CV_EXPORTS_W RawVideoSource
{
public:
virtual ~RawVideoSource() {}
/** @brief Returns next packet with RAW video frame.
@param data Pointer to frame data.
@param size Size in bytes of current frame.
*/
virtual bool getNextPacket(unsigned char** data, size_t* size) = 0;
/** @brief Returns true if the last packet contained a key frame.
*/
virtual bool lastPacketContainsKeyFrame() const { return false; }
/** @brief Returns information about video file format.
*/
virtual FormatInfo format() const = 0;
/** @brief Updates the coded width and height inside format.
*/
virtual void updateFormat(const FormatInfo& videoFormat) = 0;
/** @brief Returns any extra data associated with the video source.
@param extraData 1D cv::Mat containing the extra data if it exists.
*/
virtual void getExtraData(cv::Mat& extraData) const = 0;
/** @brief Retrieves the specified property used by the VideoSource.
@param propertyId Property identifier from cv::VideoCaptureProperties (eg. cv::CAP_PROP_POS_MSEC, cv::CAP_PROP_POS_FRAMES, ...)
or one from @ref videoio_flags_others.
@param propertyVal Value for the specified property.
@return `true` unless the property is unset set or not supported.
*/
virtual bool get(const int propertyId, double& propertyVal) const = 0;
/** @brief Retrieve the index of the first frame that will returned after construction.
@return index of the index of the first frame that will returned after construction.
@note To reduce the decoding overhead when initializing VideoReader to start its decoding from frame N, RawVideoSource should seek to the first valid key frame less than or equal to N and return that index here.
*/
virtual int getFirstFrameIdx() const = 0;
};
/** @brief VideoReader initialization parameters
@param udpSource Remove validation which can cause VideoReader() to throw exceptions when reading from a UDP source.
@param allowFrameDrop Allow frames to be dropped when ingesting from a live capture source to prevent delay and eventual disconnection
when calls to nextFrame()/grab() cannot keep up with the source's fps. Only use if delay and disconnection are a problem, i.e. not when decoding from
video files where setting this flag will cause frames to be unnecessarily discarded.
@param minNumDecodeSurfaces Minimum number of internal decode surfaces used by the hardware decoder. NVDEC will automatically determine the minimum number of
surfaces it requires for correct functionality and optimal video memory usage but not necessarily for best performance, which depends on the design of the
overall application. The optimal number of decode surfaces (in terms of performance and memory utilization) should be decided by experimentation for each application,
but it cannot go below the number determined by NVDEC.
@param rawMode Allow the raw encoded data which has been read up until the last call to grab() to be retrieved by calling retrieve(rawData,RAW_DATA_IDX).
@param targetSz Post-processed size (width/height should be multiples of 2) of the output frame, defaults to the size of the encoded video source.
@param srcRoi Region of interest (x/width should be multiples of 4 and y/height multiples of 2) decoded from video source, defaults to the full frame.
@param targetRoi Region of interest (x/width should be multiples of 4 and y/height multiples of 2) within the output frame to copy and resize the decoded frame to,
defaults to the full frame.
@param enableHistogram Request output of decoded luma histogram \a hist from VideoReader::nextFrame(GpuMat& frame, GpuMat& hist, Stream& stream), if hardware supported.
@param firstFrameIdx Index of the first frame to seek to on initialization of the VideoReader.
*/
struct CV_EXPORTS_W_SIMPLE VideoReaderInitParams {
CV_WRAP VideoReaderInitParams() : udpSource(false), allowFrameDrop(false), minNumDecodeSurfaces(0), rawMode(0), enableHistogram(false), firstFrameIdx(0){};
CV_PROP_RW bool udpSource;
CV_PROP_RW bool allowFrameDrop;
CV_PROP_RW int minNumDecodeSurfaces;
CV_PROP_RW bool rawMode;
CV_PROP_RW cv::Size targetSz;
CV_PROP_RW cv::Rect srcRoi;
CV_PROP_RW cv::Rect targetRoi;
CV_PROP_RW bool enableHistogram;
CV_PROP_RW int firstFrameIdx;
};
/** @brief Creates video reader.
@param filename Name of the input video file.
@param sourceParams Pass through parameters for VideoCapure. VideoCapture with the FFMpeg back end (CAP_FFMPEG) is used to parse the video input.
The `sourceParams` parameter allows to specify extra parameters encoded as pairs `(paramId_1, paramValue_1, paramId_2, paramValue_2, ...)`.
See cv::VideoCaptureProperties
e.g. when streaming from an RTSP source CAP_PROP_OPEN_TIMEOUT_MSEC may need to be set.
@param params Initializaton parameters. See cv::cudacodec::VideoReaderInitParams.
FFMPEG is used to read videos. User can implement own demultiplexing with cudacodec::RawVideoSource
*/
CV_EXPORTS_W Ptr<VideoReader> createVideoReader(const String& filename, const std::vector<int>& sourceParams = {}, const VideoReaderInitParams params = VideoReaderInitParams());
/** @overload
@param source RAW video source implemented by user.
@param params Initializaton parameters. See cv::cudacodec::VideoReaderInitParams.
*/
CV_EXPORTS_W Ptr<VideoReader> createVideoReader(const Ptr<RawVideoSource>& source, const VideoReaderInitParams params = VideoReaderInitParams());
//! @}
}} // namespace cv { namespace cudacodec {
#endif /* OPENCV_CUDACODEC_HPP */
@@ -0,0 +1,137 @@
#!/usr/bin/env python
import os
import cv2 as cv
import numpy as np
import tempfile
from tests_common import NewOpenCVTests, unittest
class cudacodec_test(NewOpenCVTests):
def setUp(self):
super(cudacodec_test, self).setUp()
if not cv.cuda.getCudaEnabledDeviceCount():
self.skipTest("No CUDA-capable device is detected")
@unittest.skipIf('OPENCV_TEST_DATA_PATH' not in os.environ,
"OPENCV_TEST_DATA_PATH is not defined")
def test_reader(self):
# Test the functionality but not the results of the VideoReader
vid_path = os.environ['OPENCV_TEST_DATA_PATH'] + '/highgui/video/big_buck_bunny.h264'
try:
reader = cv.cudacodec.createVideoReader(vid_path)
format_info = reader.format()
ret, gpu_mat = reader.nextFrame()
self.assertTrue(ret)
self.assertTrue(isinstance(gpu_mat, cv.cuda.GpuMat), msg=type(gpu_mat))
#TODO: print(cv.utils.dumpInputArray(gpu_mat)) # - no support for GpuMat
# Retrieve format info
if(not format_info.valid):
format_info = reader.format()
sz = gpu_mat.size()
self.assertTrue(sz[0] == format_info.width and sz[1] == format_info.height)
# not checking output, therefore sepearate tests for different signatures is unecessary
ret, gpu_mat_ = reader.nextFrame(gpu_mat)
self.assertTrue(ret and gpu_mat_.cudaPtr() == gpu_mat.cudaPtr())
# Pass VideoReaderInitParams to the decoder and initialization params to the source (cv::VideoCapture)
params = cv.cudacodec.VideoReaderInitParams()
params.rawMode = True
params.enableHistogram = False
ms_gs = 1234
post_processed_sz = (gpu_mat.size()[0]*2, gpu_mat.size()[1]*2)
params.targetSz = post_processed_sz
reader = cv.cudacodec.createVideoReader(vid_path,[cv.CAP_PROP_OPEN_TIMEOUT_MSEC, ms_gs], params)
ret, ms = reader.get(cv.CAP_PROP_OPEN_TIMEOUT_MSEC)
self.assertTrue(ret and ms == ms_gs)
ret, raw_mode = reader.getVideoReaderProps(cv.cudacodec.VideoReaderProps_PROP_RAW_MODE)
self.assertTrue(ret and raw_mode)
# Retrieve image histogram. Not all GPUs support histogram. Just check the method is called correctly
ret, gpu_mat, hist = reader.nextFrameWithHist()
self.assertTrue(ret and not gpu_mat.empty())
ret, gpu_mat_, hist_ = reader.nextFrameWithHist(gpu_mat, hist)
self.assertTrue(ret and not gpu_mat.empty())
self.assertTrue(gpu_mat_.cudaPtr() == gpu_mat.cudaPtr())
# Check post processing applied
self.assertTrue(gpu_mat.size() == post_processed_sz)
# Change color format
ret, colour_code = reader.getVideoReaderProps(cv.cudacodec.VideoReaderProps_PROP_COLOR_FORMAT)
self.assertTrue(ret and colour_code == cv.cudacodec.BGRA)
colour_code_gs = cv.cudacodec.GRAY
reader.set(colour_code_gs)
ret, colour_code = reader.getVideoReaderProps(cv.cudacodec.VideoReaderProps_PROP_COLOR_FORMAT)
self.assertTrue(ret and colour_code == colour_code_gs)
# Read raw encoded bitstream
ret, i_base = reader.getVideoReaderProps(cv.cudacodec.VideoReaderProps_PROP_RAW_PACKAGES_BASE_INDEX)
self.assertTrue(ret and i_base == 2.0)
self.assertTrue(reader.grab())
ret, gpu_mat3 = reader.retrieve()
self.assertTrue(ret and isinstance(gpu_mat3,cv.cuda.GpuMat) and not gpu_mat3.empty())
ret = reader.retrieve(gpu_mat3)
self.assertTrue(ret and isinstance(gpu_mat3,cv.cuda.GpuMat) and not gpu_mat3.empty())
ret, n_raw_packages_since_last_grab = reader.getVideoReaderProps(cv.cudacodec.VideoReaderProps_PROP_NUMBER_OF_RAW_PACKAGES_SINCE_LAST_GRAB)
self.assertTrue(ret and n_raw_packages_since_last_grab > 0)
ret, raw_data = reader.retrieve(int(i_base))
self.assertTrue(ret and isinstance(raw_data,np.ndarray) and np.any(raw_data))
except cv.error as e:
notSupported = (e.code == cv.Error.StsNotImplemented or e.code == cv.Error.StsUnsupportedFormat or e.code == cv.Error.GPU_API_CALL_ERROR)
self.assertTrue(notSupported)
if e.code == cv.Error.StsNotImplemented:
self.skipTest("NVCUVID is not installed")
elif e.code == cv.Error.StsUnsupportedFormat:
self.skipTest("GPU hardware video decoder missing or video format not supported")
elif e.code == cv.Error.GPU_API_CALL_ERRROR:
self.skipTest("GPU hardware video decoder is missing")
else:
self.skipTest(e.err)
def test_NVSurfaceToColorConverter(self):
converter = cv.cudacodec.createNVSurfaceToColorConverter(cv.cudacodec.ColorSpaceStandard_BT601,False)
bgr_sz = (1920,1080)
nv12_sz = (1920, int(1.5*1080))
blank_nv12_frame = cv.cuda.GpuMat(nv12_sz,cv.CV_8U)
ret, bgr = converter.convert(blank_nv12_frame, cv.cudacodec.SF_NV12, cv.cudacodec.BGR)
self.assertTrue(ret == True and bgr.size() == bgr_sz)
def test_map_histogram(self):
hist = cv.cuda_GpuMat((1,256), cv.CV_8UC1)
hist.setTo(1)
hist_host = cv.cudacodec.MapHist(hist)
self.assertTrue(hist_host.shape == (256, 1) and isinstance(hist_host, np.ndarray))
def test_writer(self):
# Test the functionality but not the results of the VideoWriter
try:
fd, fname = tempfile.mkstemp(suffix=".h264")
os.close(fd)
encoder_params_in = cv.cudacodec.EncoderParams()
encoder_params_in.gopLength = 10
stream = cv.cuda.Stream()
sz = (1920,1080)
writer = cv.cudacodec.createVideoWriter(fname, sz, cv.cudacodec.H264, 30, cv.cudacodec.BGR,
encoder_params_in, stream=stream)
blankFrameIn = cv.cuda.GpuMat(sz,cv.CV_8UC3)
writer.write(blankFrameIn)
writer.release()
encoder_params_out = writer.getEncoderParams()
self.assertTrue(encoder_params_in.gopLength == encoder_params_out.gopLength)
cap = cv.VideoCapture(fname,cv.CAP_FFMPEG)
self.assertTrue(cap.isOpened())
ret, blankFrameOut = cap.read()
self.assertTrue(ret and blankFrameOut.shape == blankFrameIn.download().shape)
cap.release()
except cv.error as e:
self.assertEqual(e.code, cv.Error.StsNotImplemented)
self.skipTest("Either NVCUVENC or a GPU hardware encoder is missing or the encoding profile is not supported.")
os.remove(fname)
if __name__ == '__main__':
NewOpenCVTests.bootstrap()
+47
View File
@@ -0,0 +1,47 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "perf_precomp.hpp"
using namespace perf;
CV_PERF_TEST_CUDA_MAIN(cudacodec)
+54
View File
@@ -0,0 +1,54 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef OPENCV_PERF_PRECOMP_HPP
#define OPENCV_PERF_PRECOMP_HPP
#include "opencv2/ts.hpp"
#include "opencv2/ts/cuda_perf.hpp"
#include "opencv2/cudacodec.hpp"
namespace opencv_test {
using namespace perf;
}
#endif
+191
View File
@@ -0,0 +1,191 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "perf_precomp.hpp"
#include "opencv2/videoio.hpp"
namespace opencv_test { namespace {
#if defined(HAVE_NVCUVID) || defined(HAVE_NVCUVENC)
#if defined(HAVE_FFMPEG_WRAPPER) // should this be set in preprocessor or in cvconfig.h
#define VIDEO_SRC Values("cv/video/768x576.avi", "cv/video/1920x1080.avi")
#else
// CUDA demuxer has to fall back to ffmpeg to process "cv/video/768x576.avi"
#define VIDEO_SRC Values( "cv/video/1920x1080.avi")
#endif
#if defined(HAVE_NVCUVID)
DEF_PARAM_TEST_1(FileName, string);
//////////////////////////////////////////////////////
// VideoReader
PERF_TEST_P(FileName, VideoReader, VIDEO_SRC)
{
declare.time(20);
const string inputFile = perf::TestBase::getDataPath(GetParam());
if (PERF_RUN_CUDA())
{
cv::Ptr<cv::cudacodec::VideoReader> d_reader = cv::cudacodec::createVideoReader(inputFile);
cv::cuda::GpuMat frame;
TEST_CYCLE_N(10) d_reader->nextFrame(frame);
CUDA_SANITY_CHECK(frame);
}
else
{
cv::VideoCapture reader(inputFile);
ASSERT_TRUE( reader.isOpened() );
cv::Mat frame;
TEST_CYCLE_N(10) reader >> frame;
CPU_SANITY_CHECK(frame);
}
}
#endif
//////////////////////////////////////////////////////
// VideoWriter
#if defined(HAVE_NVCUVENC)
DEF_PARAM_TEST(WriteToFile, string, cv::cudacodec::ColorFormat, cv::cudacodec::Codec);
#define COLOR_FORMAT Values(cv::cudacodec::ColorFormat::BGR, cv::cudacodec::ColorFormat::RGB, cv::cudacodec::ColorFormat::BGRA, \
cv::cudacodec::ColorFormat::RGBA, cv::cudacodec::ColorFormat::GRAY)
#define CODEC Values(cv::cudacodec::Codec::H264, cv::cudacodec::Codec::HEVC)
PERF_TEST_P(WriteToFile, VideoWriter, Combine(VIDEO_SRC, COLOR_FORMAT, CODEC))
{
declare.time(30);
const string inputFile = perf::TestBase::getDataPath(GET_PARAM(0));
const cv::cudacodec::ColorFormat surfaceFormat = GET_PARAM(1);
const cudacodec::Codec codec = GET_PARAM(2);
const double fps = 25;
const int nFrames = 20;
cv::VideoCapture reader(inputFile);
ASSERT_TRUE(reader.isOpened());
Mat frameBgr;
if (PERF_RUN_CUDA()) {
const std::string ext = codec == cudacodec::Codec::H264 ? ".h264" : ".hevc";
const string outputFile = cv::tempfile(ext.c_str());
std::vector<GpuMat> frames;
cv::Mat frameNewSf;
cuda::Stream stream;
ColorConversionCodes conversionCode = COLOR_COLORCVT_MAX;
switch (surfaceFormat) {
case cudacodec::ColorFormat::RGB:
conversionCode = COLOR_BGR2RGB;
break;
case cudacodec::ColorFormat::BGRA:
conversionCode = COLOR_BGR2BGRA;
break;
case cudacodec::ColorFormat::RGBA:
conversionCode = COLOR_BGR2RGBA;
break;
case cudacodec::ColorFormat::GRAY:
conversionCode = COLOR_BGR2GRAY;
default:
break;
}
for (int i = 0; i < nFrames; i++) {
reader >> frameBgr;
ASSERT_FALSE(frameBgr.empty());
if (conversionCode == COLOR_COLORCVT_MAX)
frameNewSf = frameBgr;
else
cv::cvtColor(frameBgr, frameNewSf, conversionCode);
GpuMat frame; frame.upload(frameNewSf, stream);
frames.push_back(frame);
}
stream.waitForCompletion();
cv::Ptr<cv::cudacodec::VideoWriter> d_writer = cv::cudacodec::createVideoWriter(outputFile, frameBgr.size(), codec, fps, surfaceFormat, 0, stream);
for (int i = 0; i < nFrames - 1; ++i) {
startTimer();
d_writer->write(frames[i]);
stopTimer();
}
startTimer();
d_writer->write(frames[nFrames - 1]);
d_writer->release();
stopTimer();
ASSERT_EQ(0, remove(outputFile.c_str()));
}
else {
if (surfaceFormat != cv::cudacodec::ColorFormat::BGR || codec != cv::cudacodec::Codec::H264)
throw PerfSkipTestException();
cv::VideoWriter writer;
const string outputFile = cv::tempfile(".avi");
for (int i = 0; i < nFrames-1; ++i) {
reader >> frameBgr;
ASSERT_FALSE(frameBgr.empty());
if (!writer.isOpened())
writer.open(outputFile, VideoWriter::fourcc('X', 'V', 'I', 'D'), fps, frameBgr.size());
startTimer();
writer.write(frameBgr);
stopTimer();
}
reader >> frameBgr;
ASSERT_FALSE(frameBgr.empty());
startTimer();
writer.write(frameBgr);
writer.release();
stopTimer();
ASSERT_EQ(0, remove(outputFile.c_str()));
}
SANITY_CHECK(frameBgr);
}
#endif
#endif
}} // namespace
+799
View File
@@ -0,0 +1,799 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#include "precomp.hpp"
#if defined(HAVE_NVCUVENC)
#include "NvEncoder.h"
namespace cv { namespace cudacodec {
NvEncoder::NvEncoder(NV_ENC_DEVICE_TYPE eDeviceType, void* pDevice, uint32_t nWidth, uint32_t nHeight, NV_ENC_BUFFER_FORMAT eBufferFormat,
uint32_t nExtraOutputDelay) :
m_hEncoder(nullptr),
m_pDevice(pDevice),
m_eDeviceType(eDeviceType),
m_nWidth(nWidth),
m_nHeight(nHeight),
m_nMaxEncodeWidth(nWidth),
m_nMaxEncodeHeight(nHeight),
m_eBufferFormat(eBufferFormat),
m_nExtraOutputDelay(nExtraOutputDelay)
{
LoadNvEncApi();
if (!m_nvenc.nvEncOpenEncodeSession)
{
m_nEncoderBuffer = 0;
NVENC_THROW_ERROR("EncodeAPI not found", NV_ENC_ERR_NO_ENCODE_DEVICE);
}
NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS encodeSessionExParams = {};
encodeSessionExParams.version = NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS_VER;
encodeSessionExParams.device = m_pDevice;
encodeSessionExParams.deviceType = m_eDeviceType;
encodeSessionExParams.apiVersion = NVENCAPI_VERSION;
void* hEncoder = NULL;
NVENC_API_CALL(m_nvenc.nvEncOpenEncodeSessionEx(&encodeSessionExParams, &hEncoder));
m_hEncoder = hEncoder;
}
void NvEncoder::LoadNvEncApi()
{
uint32_t version = 0;
uint32_t currentVersion = (NVENCAPI_MAJOR_VERSION << 4) | NVENCAPI_MINOR_VERSION;
NVENC_API_CALL(NvEncodeAPIGetMaxSupportedVersion(&version));
if (currentVersion > version)
{
NVENC_THROW_ERROR("Current Driver Version does not support this NvEncodeAPI version, please upgrade driver", NV_ENC_ERR_INVALID_VERSION);
}
m_nvenc = {};
m_nvenc.version = NV_ENCODE_API_FUNCTION_LIST_VER;
NVENC_API_CALL(NvEncodeAPICreateInstance(&m_nvenc));
}
NvEncoder::~NvEncoder()
{
DestroyHWEncoder();
}
void NvEncoder::CreateDefaultEncoderParams(NV_ENC_INITIALIZE_PARAMS* pIntializeParams, GUID codecGuid, GUID presetGuid, NV_ENC_TUNING_INFO tuningInfo)
{
if (!m_hEncoder)
{
NVENC_THROW_ERROR("Encoder Initialization failed", NV_ENC_ERR_NO_ENCODE_DEVICE);
return;
}
if (pIntializeParams == nullptr || pIntializeParams->encodeConfig == nullptr)
{
NVENC_THROW_ERROR("pInitializeParams and pInitializeParams->encodeConfig can't be NULL", NV_ENC_ERR_INVALID_PTR);
}
memset(pIntializeParams->encodeConfig, 0, sizeof(NV_ENC_CONFIG));
auto pEncodeConfig = pIntializeParams->encodeConfig;
memset(pIntializeParams, 0, sizeof(NV_ENC_INITIALIZE_PARAMS));
pIntializeParams->encodeConfig = pEncodeConfig;
pIntializeParams->encodeConfig->version = NV_ENC_CONFIG_VER;
pIntializeParams->version = NV_ENC_INITIALIZE_PARAMS_VER;
pIntializeParams->encodeGUID = codecGuid;
pIntializeParams->presetGUID = presetGuid;
pIntializeParams->encodeWidth = m_nWidth;
pIntializeParams->encodeHeight = m_nHeight;
pIntializeParams->darWidth = m_nWidth;
pIntializeParams->darHeight = m_nHeight;
pIntializeParams->frameRateNum = 30;
pIntializeParams->frameRateDen = 1;
pIntializeParams->enablePTD = 1;
pIntializeParams->reportSliceOffsets = 0;
pIntializeParams->enableSubFrameWrite = 0;
pIntializeParams->maxEncodeWidth = m_nWidth;
pIntializeParams->maxEncodeHeight = m_nHeight;
pIntializeParams->enableMEOnlyMode = false;
pIntializeParams->enableOutputInVidmem = false;
#if defined(_WIN32)
pIntializeParams->enableEncodeAsync = GetCapabilityValue(codecGuid, NV_ENC_CAPS_ASYNC_ENCODE_SUPPORT);
#endif
pIntializeParams->tuningInfo = tuningInfo;
pIntializeParams->encodeConfig->rcParams.rateControlMode = NV_ENC_PARAMS_RC_CONSTQP;
#if ((NVENCAPI_MAJOR_VERSION == 12 && NVENCAPI_MINOR_VERSION >= 2) || NVENCAPI_MAJOR_VERSION > 12)
NV_ENC_PRESET_CONFIG presetConfig = { NV_ENC_PRESET_CONFIG_VER, 0, { NV_ENC_CONFIG_VER } };
#else
NV_ENC_PRESET_CONFIG presetConfig = { NV_ENC_PRESET_CONFIG_VER, { NV_ENC_CONFIG_VER } };
#endif
m_nvenc.nvEncGetEncodePresetConfigEx(m_hEncoder, codecGuid, presetGuid, tuningInfo, &presetConfig);
memcpy(pIntializeParams->encodeConfig, &presetConfig.presetCfg, sizeof(NV_ENC_CONFIG));
if (pIntializeParams->encodeGUID == NV_ENC_CODEC_H264_GUID)
{
if (m_eBufferFormat == NV_ENC_BUFFER_FORMAT_YUV444 || m_eBufferFormat == NV_ENC_BUFFER_FORMAT_YUV444_10BIT)
{
pIntializeParams->encodeConfig->encodeCodecConfig.h264Config.chromaFormatIDC = 3;
}
pIntializeParams->encodeConfig->encodeCodecConfig.h264Config.idrPeriod = pIntializeParams->encodeConfig->gopLength;
}
else if (pIntializeParams->encodeGUID == NV_ENC_CODEC_HEVC_GUID)
{
#if ((NVENCAPI_MAJOR_VERSION == 12 && NVENCAPI_MINOR_VERSION >= 2) || NVENCAPI_MAJOR_VERSION > 12)
pIntializeParams->encodeConfig->encodeCodecConfig.hevcConfig.inputBitDepth = pIntializeParams->encodeConfig->encodeCodecConfig.hevcConfig.outputBitDepth =
(m_eBufferFormat == NV_ENC_BUFFER_FORMAT_YUV420_10BIT || m_eBufferFormat == NV_ENC_BUFFER_FORMAT_YUV444_10BIT) ? NV_ENC_BIT_DEPTH_10 : NV_ENC_BIT_DEPTH_8;
#else
pIntializeParams->encodeConfig->encodeCodecConfig.hevcConfig.pixelBitDepthMinus8 =
(m_eBufferFormat == NV_ENC_BUFFER_FORMAT_YUV420_10BIT || m_eBufferFormat == NV_ENC_BUFFER_FORMAT_YUV444_10BIT) ? 2 : 0;
#endif
if (m_eBufferFormat == NV_ENC_BUFFER_FORMAT_YUV444 || m_eBufferFormat == NV_ENC_BUFFER_FORMAT_YUV444_10BIT)
{
pIntializeParams->encodeConfig->encodeCodecConfig.hevcConfig.chromaFormatIDC = 3;
}
pIntializeParams->encodeConfig->encodeCodecConfig.hevcConfig.idrPeriod = pIntializeParams->encodeConfig->gopLength;
}
return;
}
void NvEncoder::CreateEncoder(const NV_ENC_INITIALIZE_PARAMS* pEncoderParams)
{
if (!m_hEncoder)
{
NVENC_THROW_ERROR("Encoder Initialization failed", NV_ENC_ERR_NO_ENCODE_DEVICE);
}
if (!pEncoderParams)
{
NVENC_THROW_ERROR("Invalid NV_ENC_INITIALIZE_PARAMS ptr", NV_ENC_ERR_INVALID_PTR);
}
if (pEncoderParams->encodeWidth == 0 || pEncoderParams->encodeHeight == 0)
{
NVENC_THROW_ERROR("Invalid encoder width and height", NV_ENC_ERR_INVALID_PARAM);
}
if (pEncoderParams->encodeGUID != NV_ENC_CODEC_H264_GUID && pEncoderParams->encodeGUID != NV_ENC_CODEC_HEVC_GUID)
{
NVENC_THROW_ERROR("Invalid codec guid", NV_ENC_ERR_INVALID_PARAM);
}
if (pEncoderParams->encodeGUID == NV_ENC_CODEC_H264_GUID)
{
if (m_eBufferFormat == NV_ENC_BUFFER_FORMAT_YUV420_10BIT || m_eBufferFormat == NV_ENC_BUFFER_FORMAT_YUV444_10BIT)
{
NVENC_THROW_ERROR("10-bit format isn't supported by H264 encoder", NV_ENC_ERR_INVALID_PARAM);
}
}
// set other necessary params if not set yet
if (pEncoderParams->encodeGUID == NV_ENC_CODEC_H264_GUID)
{
if ((m_eBufferFormat == NV_ENC_BUFFER_FORMAT_YUV444) &&
(pEncoderParams->encodeConfig->encodeCodecConfig.h264Config.chromaFormatIDC != 3))
{
NVENC_THROW_ERROR("Invalid ChromaFormatIDC", NV_ENC_ERR_INVALID_PARAM);
}
}
if (pEncoderParams->encodeGUID == NV_ENC_CODEC_HEVC_GUID)
{
bool yuv10BitFormat = (m_eBufferFormat == NV_ENC_BUFFER_FORMAT_YUV420_10BIT || m_eBufferFormat == NV_ENC_BUFFER_FORMAT_YUV444_10BIT) ? true : false;
#if ((NVENCAPI_MAJOR_VERSION == 12 && NVENCAPI_MINOR_VERSION >= 2) || NVENCAPI_MAJOR_VERSION > 12)
if (yuv10BitFormat && pEncoderParams->encodeConfig->encodeCodecConfig.hevcConfig.inputBitDepth != NV_ENC_BIT_DEPTH_10)
#else
if (yuv10BitFormat && pEncoderParams->encodeConfig->encodeCodecConfig.hevcConfig.pixelBitDepthMinus8 != 2)
#endif
{
NVENC_THROW_ERROR("Invalid PixelBitdepth", NV_ENC_ERR_INVALID_PARAM);
}
if ((m_eBufferFormat == NV_ENC_BUFFER_FORMAT_YUV444 || m_eBufferFormat == NV_ENC_BUFFER_FORMAT_YUV444_10BIT) &&
(pEncoderParams->encodeConfig->encodeCodecConfig.hevcConfig.chromaFormatIDC != 3))
{
NVENC_THROW_ERROR("Invalid ChromaFormatIDC", NV_ENC_ERR_INVALID_PARAM);
}
}
memcpy(&m_initializeParams, pEncoderParams, sizeof(m_initializeParams));
m_initializeParams.version = NV_ENC_INITIALIZE_PARAMS_VER;
if (pEncoderParams->encodeConfig)
{
memcpy(&m_encodeConfig, pEncoderParams->encodeConfig, sizeof(m_encodeConfig));
m_encodeConfig.version = NV_ENC_CONFIG_VER;
}
else
{
#if ((NVENCAPI_MAJOR_VERSION == 12 && NVENCAPI_MINOR_VERSION >= 2) || NVENCAPI_MAJOR_VERSION > 12)
NV_ENC_PRESET_CONFIG presetConfig = { NV_ENC_PRESET_CONFIG_VER, 0, { NV_ENC_CONFIG_VER } };
#else
NV_ENC_PRESET_CONFIG presetConfig = { NV_ENC_PRESET_CONFIG_VER, { NV_ENC_CONFIG_VER } };
#endif
m_nvenc.nvEncGetEncodePresetConfigEx(m_hEncoder, pEncoderParams->encodeGUID, pEncoderParams->presetGUID, pEncoderParams->tuningInfo, &presetConfig);
memcpy(&m_encodeConfig, &presetConfig.presetCfg, sizeof(NV_ENC_CONFIG));
}
if (((uint32_t)m_encodeConfig.frameIntervalP) > m_encodeConfig.gopLength)
{
m_encodeConfig.frameIntervalP = m_encodeConfig.gopLength;
}
m_initializeParams.encodeConfig = &m_encodeConfig;
NVENC_API_CALL(m_nvenc.nvEncInitializeEncoder(m_hEncoder, &m_initializeParams));
m_bEncoderInitialized = true;
m_nWidth = m_initializeParams.encodeWidth;
m_nHeight = m_initializeParams.encodeHeight;
m_nMaxEncodeWidth = m_initializeParams.maxEncodeWidth;
m_nMaxEncodeHeight = m_initializeParams.maxEncodeHeight;
m_nEncoderBuffer = m_encodeConfig.frameIntervalP + m_encodeConfig.rcParams.lookaheadDepth + m_nExtraOutputDelay;
m_nOutputDelay = m_nEncoderBuffer - 1;
m_vpCompletionEvent.resize(m_nEncoderBuffer, nullptr);
#if defined(_WIN32)
for (uint32_t i = 0; i < m_vpCompletionEvent.size(); i++)
{
m_vpCompletionEvent[i] = CreateEvent(NULL, FALSE, FALSE, NULL);
NV_ENC_EVENT_PARAMS eventParams = { NV_ENC_EVENT_PARAMS_VER };
eventParams.completionEvent = m_vpCompletionEvent[i];
m_nvenc.nvEncRegisterAsyncEvent(m_hEncoder, &eventParams);
}
#endif
m_vMappedInputBuffers.resize(m_nEncoderBuffer, nullptr);
m_vBitstreamOutputBuffer.resize(m_nEncoderBuffer, nullptr);
InitializeBitstreamBuffer();
AllocateInputBuffers(m_nEncoderBuffer);
}
void NvEncoder::DestroyEncoder()
{
if (!m_hEncoder)
{
return;
}
ReleaseInputBuffers();
DestroyHWEncoder();
}
void NvEncoder::DestroyHWEncoder()
{
if (!m_hEncoder)
{
return;
}
#if defined(_WIN32)
for (uint32_t i = 0; i < m_vpCompletionEvent.size(); i++)
{
if (m_vpCompletionEvent[i])
{
NV_ENC_EVENT_PARAMS eventParams = { NV_ENC_EVENT_PARAMS_VER };
eventParams.completionEvent = m_vpCompletionEvent[i];
m_nvenc.nvEncUnregisterAsyncEvent(m_hEncoder, &eventParams);
CloseHandle(m_vpCompletionEvent[i]);
}
}
m_vpCompletionEvent.clear();
#endif
DestroyBitstreamBuffer();
m_nvenc.nvEncDestroyEncoder(m_hEncoder);
m_hEncoder = nullptr;
m_bEncoderInitialized = false;
}
const NvEncInputFrame* NvEncoder::GetNextInputFrame()
{
int i = m_iToSend % m_nEncoderBuffer;
return &m_vInputFrames[i];
}
void NvEncoder::MapResources(uint32_t bfrIdx)
{
NV_ENC_MAP_INPUT_RESOURCE mapInputResource = {};
mapInputResource.version = NV_ENC_MAP_INPUT_RESOURCE_VER;
mapInputResource.registeredResource = m_vRegisteredResources[bfrIdx];
NVENC_API_CALL(m_nvenc.nvEncMapInputResource(m_hEncoder, &mapInputResource));
m_vMappedInputBuffers[bfrIdx] = mapInputResource.mappedResource;
}
void NvEncoder::EncodeFrame(std::vector<std::vector<uint8_t>>& vPacket, std::vector<uint64_t>& outputTimeStamps, NV_ENC_PIC_PARAMS* pPicParams)
{
vPacket.clear();
outputTimeStamps.clear();
if (!IsHWEncoderInitialized())
{
NVENC_THROW_ERROR("Encoder device not found", NV_ENC_ERR_NO_ENCODE_DEVICE);
}
int bfrIdx = m_iToSend % m_nEncoderBuffer;
MapResources(bfrIdx);
NVENCSTATUS nvStatus = DoEncode(m_vMappedInputBuffers[bfrIdx], m_vBitstreamOutputBuffer[bfrIdx], pPicParams);
if (nvStatus == NV_ENC_SUCCESS || nvStatus == NV_ENC_ERR_NEED_MORE_INPUT)
{
m_iToSend++;
GetEncodedPacket(m_vBitstreamOutputBuffer, vPacket, outputTimeStamps, true);
}
else
{
NVENC_THROW_ERROR("nvEncEncodePicture API failed", nvStatus);
}
}
void NvEncoder::GetSequenceParams(std::vector<uint8_t>& seqParams)
{
uint8_t spsppsData[1024]; // Assume maximum spspps data is 1KB or less
memset(spsppsData, 0, sizeof(spsppsData));
NV_ENC_SEQUENCE_PARAM_PAYLOAD payload = {};
payload.version = NV_ENC_SEQUENCE_PARAM_PAYLOAD_VER;
uint32_t spsppsSize = 0;
payload.spsppsBuffer = spsppsData;
payload.inBufferSize = sizeof(spsppsData);
payload.outSPSPPSPayloadSize = &spsppsSize;
NVENC_API_CALL(m_nvenc.nvEncGetSequenceParams(m_hEncoder, &payload));
seqParams.clear();
seqParams.insert(seqParams.end(), &spsppsData[0], &spsppsData[spsppsSize]);
}
NVENCSTATUS NvEncoder::DoEncode(NV_ENC_INPUT_PTR inputBuffer, NV_ENC_OUTPUT_PTR outputBuffer, NV_ENC_PIC_PARAMS* pPicParams)
{
NV_ENC_PIC_PARAMS picParams = {};
if (pPicParams)
{
picParams = *pPicParams;
}
picParams.inputTimeStamp = m_iInputFrame++;
picParams.version = NV_ENC_PIC_PARAMS_VER;
picParams.pictureStruct = NV_ENC_PIC_STRUCT_FRAME;
picParams.inputBuffer = inputBuffer;
picParams.bufferFmt = GetPixelFormat();
picParams.inputWidth = GetEncodeWidth();
picParams.inputHeight = GetEncodeHeight();
picParams.outputBitstream = outputBuffer;
picParams.completionEvent = GetCompletionEvent(m_iToSend % m_nEncoderBuffer);
NVENCSTATUS nvStatus = m_nvenc.nvEncEncodePicture(m_hEncoder, &picParams);
return nvStatus;
}
void NvEncoder::SendEOS()
{
NV_ENC_PIC_PARAMS picParams = {};
picParams.version = NV_ENC_PIC_PARAMS_VER;
picParams.encodePicFlags = NV_ENC_PIC_FLAG_EOS;
picParams.completionEvent = GetCompletionEvent(m_iToSend % m_nEncoderBuffer);
NVENC_API_CALL(m_nvenc.nvEncEncodePicture(m_hEncoder, &picParams));
}
void NvEncoder::EndEncode(std::vector<std::vector<uint8_t>>& vPacket, std::vector<uint64_t>& outputTimeStamps)
{
vPacket.clear();
if (!IsHWEncoderInitialized())
{
NVENC_THROW_ERROR("Encoder device not initialized", NV_ENC_ERR_ENCODER_NOT_INITIALIZED);
}
SendEOS();
GetEncodedPacket(m_vBitstreamOutputBuffer, vPacket, outputTimeStamps, false);
}
void NvEncoder::GetEncodedPacket(std::vector<NV_ENC_OUTPUT_PTR>& vOutputBuffer, std::vector<std::vector<uint8_t>>& vPacket, std::vector<uint64_t>& outputTimeStamps, bool bOutputDelay)
{
unsigned i = 0;
int iEnd = bOutputDelay ? m_iToSend - m_nOutputDelay : m_iToSend;
for (; m_iGot < iEnd; m_iGot++)
{
WaitForCompletionEvent(m_iGot % m_nEncoderBuffer);
NV_ENC_LOCK_BITSTREAM lockBitstreamData = {};
lockBitstreamData.version = NV_ENC_LOCK_BITSTREAM_VER;
lockBitstreamData.outputBitstream = vOutputBuffer[m_iGot % m_nEncoderBuffer];
lockBitstreamData.doNotWait = false;
NVENC_API_CALL(m_nvenc.nvEncLockBitstream(m_hEncoder, &lockBitstreamData));
outputTimeStamps.push_back(lockBitstreamData.outputTimeStamp);
uint8_t* pData = (uint8_t*)lockBitstreamData.bitstreamBufferPtr;
if (vPacket.size() < i + 1)
{
vPacket.push_back(std::vector<uint8_t>());
}
vPacket[i].clear();
vPacket[i].insert(vPacket[i].end(), &pData[0], &pData[lockBitstreamData.bitstreamSizeInBytes]);
i++;
NVENC_API_CALL(m_nvenc.nvEncUnlockBitstream(m_hEncoder, lockBitstreamData.outputBitstream));
if (m_vMappedInputBuffers[m_iGot % m_nEncoderBuffer])
{
NVENC_API_CALL(m_nvenc.nvEncUnmapInputResource(m_hEncoder, m_vMappedInputBuffers[m_iGot % m_nEncoderBuffer]));
m_vMappedInputBuffers[m_iGot % m_nEncoderBuffer] = nullptr;
}
}
}
bool NvEncoder::Reconfigure(const NV_ENC_RECONFIGURE_PARAMS* pReconfigureParams)
{
NVENC_API_CALL(m_nvenc.nvEncReconfigureEncoder(m_hEncoder, const_cast<NV_ENC_RECONFIGURE_PARAMS*>(pReconfigureParams)));
memcpy(&m_initializeParams, &(pReconfigureParams->reInitEncodeParams), sizeof(m_initializeParams));
if (pReconfigureParams->reInitEncodeParams.encodeConfig)
{
memcpy(&m_encodeConfig, pReconfigureParams->reInitEncodeParams.encodeConfig, sizeof(m_encodeConfig));
}
m_nWidth = m_initializeParams.encodeWidth;
m_nHeight = m_initializeParams.encodeHeight;
m_nMaxEncodeWidth = m_initializeParams.maxEncodeWidth;
m_nMaxEncodeHeight = m_initializeParams.maxEncodeHeight;
return true;
}
NV_ENC_REGISTERED_PTR NvEncoder::RegisterResource(void* pBuffer, NV_ENC_INPUT_RESOURCE_TYPE eResourceType,
int width, int height, int pitch, NV_ENC_BUFFER_FORMAT bufferFormat, NV_ENC_BUFFER_USAGE bufferUsage,
NV_ENC_FENCE_POINT_D3D12* pInputFencePoint)
{
NV_ENC_REGISTER_RESOURCE registerResource = {};
registerResource.version = NV_ENC_REGISTER_RESOURCE_VER;
registerResource.resourceType = eResourceType;
registerResource.resourceToRegister = pBuffer;
registerResource.width = width;
registerResource.height = height;
registerResource.pitch = pitch;
registerResource.bufferFormat = bufferFormat;
registerResource.bufferUsage = bufferUsage;
registerResource.pInputFencePoint = pInputFencePoint;
NVENC_API_CALL(m_nvenc.nvEncRegisterResource(m_hEncoder, &registerResource));
return registerResource.registeredResource;
}
void NvEncoder::RegisterInputResources(std::vector<void*> inputframes, NV_ENC_INPUT_RESOURCE_TYPE eResourceType,
int width, int height, int pitch, NV_ENC_BUFFER_FORMAT bufferFormat, bool bReferenceFrame)
{
for (uint32_t i = 0; i < inputframes.size(); ++i)
{
NV_ENC_REGISTERED_PTR registeredPtr = RegisterResource(inputframes[i], eResourceType, width, height, pitch, bufferFormat, NV_ENC_INPUT_IMAGE);
std::vector<uint32_t> _chromaOffsets;
NvEncoder::GetChromaSubPlaneOffsets(bufferFormat, pitch, height, _chromaOffsets);
NvEncInputFrame inputframe = {};
inputframe.inputPtr = (void*)inputframes[i];
inputframe.chromaOffsets[0] = 0;
inputframe.chromaOffsets[1] = 0;
for (uint32_t ch = 0; ch < _chromaOffsets.size(); ch++)
{
inputframe.chromaOffsets[ch] = _chromaOffsets[ch];
}
inputframe.numChromaPlanes = NvEncoder::GetNumChromaPlanes(bufferFormat);
inputframe.pitch = pitch;
inputframe.chromaPitch = NvEncoder::GetChromaPitch(bufferFormat, pitch);
inputframe.bufferFormat = bufferFormat;
inputframe.resourceType = eResourceType;
if (bReferenceFrame)
{
m_vRegisteredResourcesForReference.push_back(registeredPtr);
m_vReferenceFrames.push_back(inputframe);
}
else
{
m_vRegisteredResources.push_back(registeredPtr);
m_vInputFrames.push_back(inputframe);
}
}
}
void NvEncoder::FlushEncoder()
{
try
{
std::vector<std::vector<uint8_t>> vPacket;
std::vector<uint64_t> outputTimeStamps;
EndEncode(vPacket, outputTimeStamps);
}
catch (...)
{
}
}
void NvEncoder::UnregisterInputResources()
{
FlushEncoder();
m_vMappedRefBuffers.clear();
for (uint32_t i = 0; i < m_vMappedInputBuffers.size(); ++i)
{
if (m_vMappedInputBuffers[i])
{
m_nvenc.nvEncUnmapInputResource(m_hEncoder, m_vMappedInputBuffers[i]);
}
}
m_vMappedInputBuffers.clear();
for (uint32_t i = 0; i < m_vRegisteredResources.size(); ++i)
{
if (m_vRegisteredResources[i])
{
m_nvenc.nvEncUnregisterResource(m_hEncoder, m_vRegisteredResources[i]);
}
}
m_vRegisteredResources.clear();
for (uint32_t i = 0; i < m_vRegisteredResourcesForReference.size(); ++i)
{
if (m_vRegisteredResourcesForReference[i])
{
m_nvenc.nvEncUnregisterResource(m_hEncoder, m_vRegisteredResourcesForReference[i]);
}
}
m_vRegisteredResourcesForReference.clear();
}
void NvEncoder::WaitForCompletionEvent(int iEvent)
{
#if defined(_WIN32)
// Check if we are in async mode. If not, don't wait for event;
NV_ENC_CONFIG sEncodeConfig = { 0 };
NV_ENC_INITIALIZE_PARAMS sInitializeParams = { 0 };
sInitializeParams.encodeConfig = &sEncodeConfig;
GetInitializeParams(&sInitializeParams);
if (0U == sInitializeParams.enableEncodeAsync)
{
return;
}
#ifdef DEBUG
WaitForSingleObject(m_vpCompletionEvent[iEvent], INFINITE);
#else
// wait for 20s which is infinite on terms of gpu time
if (WaitForSingleObject(m_vpCompletionEvent[iEvent], 20000) == WAIT_FAILED)
{
NVENC_THROW_ERROR("Failed to encode frame", NV_ENC_ERR_GENERIC);
}
#endif
#endif
}
uint32_t NvEncoder::GetWidthInBytes(const NV_ENC_BUFFER_FORMAT bufferFormat, const uint32_t width)
{
switch (bufferFormat) {
case NV_ENC_BUFFER_FORMAT_NV12:
case NV_ENC_BUFFER_FORMAT_YV12:
case NV_ENC_BUFFER_FORMAT_IYUV:
case NV_ENC_BUFFER_FORMAT_YUV444:
return width;
case NV_ENC_BUFFER_FORMAT_YUV420_10BIT:
case NV_ENC_BUFFER_FORMAT_YUV444_10BIT:
return width * 2;
case NV_ENC_BUFFER_FORMAT_ARGB:
case NV_ENC_BUFFER_FORMAT_ARGB10:
case NV_ENC_BUFFER_FORMAT_AYUV:
case NV_ENC_BUFFER_FORMAT_ABGR:
case NV_ENC_BUFFER_FORMAT_ABGR10:
return width * 4;
default:
NVENC_THROW_ERROR("Invalid Buffer format", NV_ENC_ERR_INVALID_PARAM);
}
}
uint32_t NvEncoder::GetNumChromaPlanes(const NV_ENC_BUFFER_FORMAT bufferFormat)
{
switch (bufferFormat)
{
case NV_ENC_BUFFER_FORMAT_NV12:
case NV_ENC_BUFFER_FORMAT_YUV420_10BIT:
return 1;
case NV_ENC_BUFFER_FORMAT_YV12:
case NV_ENC_BUFFER_FORMAT_IYUV:
case NV_ENC_BUFFER_FORMAT_YUV444:
case NV_ENC_BUFFER_FORMAT_YUV444_10BIT:
return 2;
case NV_ENC_BUFFER_FORMAT_ARGB:
case NV_ENC_BUFFER_FORMAT_ARGB10:
case NV_ENC_BUFFER_FORMAT_AYUV:
case NV_ENC_BUFFER_FORMAT_ABGR:
case NV_ENC_BUFFER_FORMAT_ABGR10:
return 0;
default:
NVENC_THROW_ERROR("Invalid Buffer format", NV_ENC_ERR_INVALID_PARAM);
}
}
uint32_t NvEncoder::GetChromaPitch(const NV_ENC_BUFFER_FORMAT bufferFormat, const uint32_t lumaPitch)
{
switch (bufferFormat)
{
case NV_ENC_BUFFER_FORMAT_NV12:
case NV_ENC_BUFFER_FORMAT_YUV420_10BIT:
case NV_ENC_BUFFER_FORMAT_YUV444:
case NV_ENC_BUFFER_FORMAT_YUV444_10BIT:
return lumaPitch;
case NV_ENC_BUFFER_FORMAT_YV12:
case NV_ENC_BUFFER_FORMAT_IYUV:
return (lumaPitch + 1) / 2;
case NV_ENC_BUFFER_FORMAT_ARGB:
case NV_ENC_BUFFER_FORMAT_ARGB10:
case NV_ENC_BUFFER_FORMAT_AYUV:
case NV_ENC_BUFFER_FORMAT_ABGR:
case NV_ENC_BUFFER_FORMAT_ABGR10:
return 0;
default:
NVENC_THROW_ERROR("Invalid Buffer format", NV_ENC_ERR_INVALID_PARAM);
}
}
void NvEncoder::GetChromaSubPlaneOffsets(const NV_ENC_BUFFER_FORMAT bufferFormat, const uint32_t pitch, const uint32_t height, std::vector<uint32_t>& chromaOffsets)
{
chromaOffsets.clear();
switch (bufferFormat)
{
case NV_ENC_BUFFER_FORMAT_NV12:
case NV_ENC_BUFFER_FORMAT_YUV420_10BIT:
chromaOffsets.push_back(pitch * height);
return;
case NV_ENC_BUFFER_FORMAT_YV12:
case NV_ENC_BUFFER_FORMAT_IYUV:
chromaOffsets.push_back(pitch * height);
chromaOffsets.push_back(chromaOffsets[0] + (NvEncoder::GetChromaPitch(bufferFormat, pitch) * GetChromaHeight(bufferFormat, height)));
return;
case NV_ENC_BUFFER_FORMAT_YUV444:
case NV_ENC_BUFFER_FORMAT_YUV444_10BIT:
chromaOffsets.push_back(pitch * height);
chromaOffsets.push_back(chromaOffsets[0] + (pitch * height));
return;
case NV_ENC_BUFFER_FORMAT_ARGB:
case NV_ENC_BUFFER_FORMAT_ARGB10:
case NV_ENC_BUFFER_FORMAT_AYUV:
case NV_ENC_BUFFER_FORMAT_ABGR:
case NV_ENC_BUFFER_FORMAT_ABGR10:
return;
default:
NVENC_THROW_ERROR("Invalid Buffer format", NV_ENC_ERR_INVALID_PARAM);
}
}
uint32_t NvEncoder::GetChromaHeight(const NV_ENC_BUFFER_FORMAT bufferFormat, const uint32_t lumaHeight)
{
switch (bufferFormat)
{
case NV_ENC_BUFFER_FORMAT_YV12:
case NV_ENC_BUFFER_FORMAT_IYUV:
case NV_ENC_BUFFER_FORMAT_NV12:
case NV_ENC_BUFFER_FORMAT_YUV420_10BIT:
return (lumaHeight + 1) / 2;
case NV_ENC_BUFFER_FORMAT_YUV444:
case NV_ENC_BUFFER_FORMAT_YUV444_10BIT:
return lumaHeight;
case NV_ENC_BUFFER_FORMAT_ARGB:
case NV_ENC_BUFFER_FORMAT_ARGB10:
case NV_ENC_BUFFER_FORMAT_AYUV:
case NV_ENC_BUFFER_FORMAT_ABGR:
case NV_ENC_BUFFER_FORMAT_ABGR10:
return 0;
default:
NVENC_THROW_ERROR("Invalid Buffer format", NV_ENC_ERR_INVALID_PARAM);
}
}
uint32_t NvEncoder::GetChromaWidthInBytes(const NV_ENC_BUFFER_FORMAT bufferFormat, const uint32_t lumaWidth)
{
switch (bufferFormat)
{
case NV_ENC_BUFFER_FORMAT_YV12:
case NV_ENC_BUFFER_FORMAT_IYUV:
return (lumaWidth + 1) / 2;
case NV_ENC_BUFFER_FORMAT_NV12:
return lumaWidth;
case NV_ENC_BUFFER_FORMAT_YUV420_10BIT:
return 2 * lumaWidth;
case NV_ENC_BUFFER_FORMAT_YUV444:
return lumaWidth;
case NV_ENC_BUFFER_FORMAT_YUV444_10BIT:
return 2 * lumaWidth;
case NV_ENC_BUFFER_FORMAT_ARGB:
case NV_ENC_BUFFER_FORMAT_ARGB10:
case NV_ENC_BUFFER_FORMAT_AYUV:
case NV_ENC_BUFFER_FORMAT_ABGR:
case NV_ENC_BUFFER_FORMAT_ABGR10:
return 0;
default:
NVENC_THROW_ERROR("Invalid Buffer format", NV_ENC_ERR_INVALID_PARAM);
}
}
int NvEncoder::GetCapabilityValue(GUID guidCodec, NV_ENC_CAPS capsToQuery)
{
if (!m_hEncoder)
{
return 0;
}
NV_ENC_CAPS_PARAM capsParam = {};
capsParam.version = NV_ENC_CAPS_PARAM_VER;
capsParam.capsToQuery = capsToQuery;
int v;
m_nvenc.nvEncGetEncodeCaps(m_hEncoder, guidCodec, &capsParam, &v);
return v;
}
int NvEncoder::GetFrameSize() const
{
switch (GetPixelFormat())
{
case NV_ENC_BUFFER_FORMAT_YV12:
case NV_ENC_BUFFER_FORMAT_IYUV:
case NV_ENC_BUFFER_FORMAT_NV12:
return GetEncodeWidth() * (GetEncodeHeight() + (GetEncodeHeight() + 1) / 2);
case NV_ENC_BUFFER_FORMAT_YUV420_10BIT:
return 2 * GetEncodeWidth() * (GetEncodeHeight() + (GetEncodeHeight() + 1) / 2);
case NV_ENC_BUFFER_FORMAT_YUV444:
return GetEncodeWidth() * GetEncodeHeight() * 3;
case NV_ENC_BUFFER_FORMAT_YUV444_10BIT:
return 2 * GetEncodeWidth() * GetEncodeHeight() * 3;
case NV_ENC_BUFFER_FORMAT_ARGB:
case NV_ENC_BUFFER_FORMAT_ARGB10:
case NV_ENC_BUFFER_FORMAT_AYUV:
case NV_ENC_BUFFER_FORMAT_ABGR:
case NV_ENC_BUFFER_FORMAT_ABGR10:
return 4 * GetEncodeWidth() * GetEncodeHeight();
default:
NVENC_THROW_ERROR("Invalid Buffer format", NV_ENC_ERR_INVALID_PARAM);
}
}
void NvEncoder::GetInitializeParams(NV_ENC_INITIALIZE_PARAMS* pInitializeParams)
{
if (!pInitializeParams || !pInitializeParams->encodeConfig)
{
NVENC_THROW_ERROR("Both pInitializeParams and pInitializeParams->encodeConfig can't be NULL", NV_ENC_ERR_INVALID_PTR);
}
NV_ENC_CONFIG* pEncodeConfig = pInitializeParams->encodeConfig;
*pEncodeConfig = m_encodeConfig;
*pInitializeParams = m_initializeParams;
pInitializeParams->encodeConfig = pEncodeConfig;
}
void NvEncoder::InitializeBitstreamBuffer()
{
for (int i = 0; i < m_nEncoderBuffer; i++)
{
NV_ENC_CREATE_BITSTREAM_BUFFER createBitstreamBuffer = {};
createBitstreamBuffer.version = NV_ENC_CREATE_BITSTREAM_BUFFER_VER;
NVENC_API_CALL(m_nvenc.nvEncCreateBitstreamBuffer(m_hEncoder, &createBitstreamBuffer));
m_vBitstreamOutputBuffer[i] = createBitstreamBuffer.bitstreamBuffer;
}
}
void NvEncoder::DestroyBitstreamBuffer()
{
for (uint32_t i = 0; i < m_vBitstreamOutputBuffer.size(); i++)
{
if (m_vBitstreamOutputBuffer[i])
{
m_nvenc.nvEncDestroyBitstreamBuffer(m_hEncoder, m_vBitstreamOutputBuffer[i]);
}
}
m_vBitstreamOutputBuffer.clear();
}
}}
#endif
+389
View File
@@ -0,0 +1,389 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#ifndef OPENCV_NVENCODER_HPP
#define OPENCV_NVENCODER_HPP
#include <vector>
#include "nvEncodeAPI.h"
#include <stdint.h>
#include <mutex>
#include <string>
#include <iostream>
#include <sstream>
#include <string.h>
namespace cv { namespace cudacodec {
#ifndef _WIN32
#include <cstring>
static inline bool operator==(const GUID& guid1, const GUID& guid2) {
return !memcmp(&guid1, &guid2, sizeof(GUID));
}
static inline bool operator!=(const GUID& guid1, const GUID& guid2) {
return !(guid1 == guid2);
}
#endif
#define NVENC_THROW_ERROR( errorStr, errorCode ) \
do \
{ \
cv::String msg = cv::format("%s [Code = %d]", errorStr, errorCode); \
cv::error(cv::Error::GpuApiCallError, msg, __FUNCTION__, __FILE__, __LINE__); \
} while (0)
#define NVENC_API_CALL( nvencAPI ) \
do \
{ \
NVENCSTATUS errorCode = nvencAPI; \
if( errorCode != NV_ENC_SUCCESS) \
{ \
cv::String msg = cv::format("NVENC returned error [Code = %d]", errorCode); \
cv::error(cv::Error::GpuApiCallError, msg, __FUNCTION__, __FILE__, __LINE__); \
} \
} while (0)
struct NvEncInputFrame
{
void* inputPtr = nullptr;
uint32_t chromaOffsets[2];
uint32_t numChromaPlanes;
uint32_t pitch;
uint32_t chromaPitch;
NV_ENC_BUFFER_FORMAT bufferFormat;
NV_ENC_INPUT_RESOURCE_TYPE resourceType;
};
/**
* @brief Shared base class for different encoder interfaces.
*/
class NvEncoder
{
public:
/**
* @brief This function is used to initialize the encoder session.
* Application must call this function to initialize the encoder, before
* starting to encode any frames.
*/
virtual void CreateEncoder(const NV_ENC_INITIALIZE_PARAMS* pEncodeParams);
/**
* @brief This function is used to destroy the encoder session.
* Application must call this function to destroy the encoder session and
* clean up any allocated resources. The application must call EndEncode()
* function to get any queued encoded frames before calling DestroyEncoder().
*/
virtual void DestroyEncoder();
/**
* @brief This function is used to reconfigure an existing encoder session.
* Application can use this function to dynamically change the bitrate,
* resolution and other QOS parameters. If the application changes the
* resolution, it must set NV_ENC_RECONFIGURE_PARAMS::forceIDR.
*/
bool Reconfigure(const NV_ENC_RECONFIGURE_PARAMS* pReconfigureParams);
/**
* @brief This function is used to get the next available input buffer.
* Applications must call this function to obtain a pointer to the next
* input buffer. The application must copy the uncompressed data to the
* input buffer and then call EncodeFrame() function to encode it.
*/
const NvEncInputFrame* GetNextInputFrame();
/**
* @brief This function is used to encode a frame.
* Applications must call EncodeFrame() function to encode the uncompressed
* data, which has been copied to an input buffer obtained from the
* GetNextInputFrame() function.
*/
virtual void EncodeFrame(std::vector<std::vector<uint8_t>>& vPacket, std::vector<uint64_t>& outputTimeStamps, NV_ENC_PIC_PARAMS* pPicParams = nullptr);
/**
* @brief This function to flush the encoder queue.
* The encoder might be queuing frames for B picture encoding or lookahead;
* the application must call EndEncode() to get all the queued encoded frames
* from the encoder. The application must call this function before destroying
* an encoder session.
*/
virtual void EndEncode(std::vector<std::vector<uint8_t>>& vPacket, std::vector<uint64_t>& outputTimeStamps);
/**
* @brief This function is used to query hardware encoder capabilities.
* Applications can call this function to query capabilities like maximum encode
* dimensions, support for lookahead or the ME-only mode etc.
*/
int GetCapabilityValue(GUID guidCodec, NV_ENC_CAPS capsToQuery);
/**
* @brief This function is used to get the current device on which encoder is running.
*/
void* GetDevice() const { return m_pDevice; }
/**
* @brief This function is used to get the current device type which encoder is running.
*/
NV_ENC_DEVICE_TYPE GetDeviceType() const { return m_eDeviceType; }
/**
* @brief This function is used to get the current encode width.
* The encode width can be modified by Reconfigure() function.
*/
int GetEncodeWidth() const { return m_nWidth; }
/**
* @brief This function is used to get the current encode height.
* The encode height can be modified by Reconfigure() function.
*/
int GetEncodeHeight() const { return m_nHeight; }
/**
* @brief This function is used to get the current frame size based on pixel format.
*/
int GetFrameSize() const;
/**
* @brief This function is used to initialize config parameters based on
* given codec and preset guids.
* The application can call this function to get the default configuration
* for a certain preset. The application can either use these parameters
* directly or override them with application-specific settings before
* using them in CreateEncoder() function.
*/
void CreateDefaultEncoderParams(NV_ENC_INITIALIZE_PARAMS* pIntializeParams, GUID codecGuid, GUID presetGuid, NV_ENC_TUNING_INFO tuningInfo = NV_ENC_TUNING_INFO_UNDEFINED);
/**
* @brief This function is used to get the current initialization parameters,
* which had been used to configure the encoder session.
* The initialization parameters are modified if the application calls
* Reconfigure() function.
*/
void GetInitializeParams(NV_ENC_INITIALIZE_PARAMS* pInitializeParams);
/**
* @brief This function is used to get sequence and picture parameter headers.
* Application can call this function after encoder is initialized to get SPS and PPS
* nalus for the current encoder instance. The sequence header data might change when
* application calls Reconfigure() function.
*/
void GetSequenceParams(std::vector<uint8_t>& seqParams);
/**
* @brief NvEncoder class virtual destructor.
*/
virtual ~NvEncoder();
public:
/**
* @brief This a static function to get chroma offsets for YUV planar formats.
*/
static void GetChromaSubPlaneOffsets(const NV_ENC_BUFFER_FORMAT bufferFormat, const uint32_t pitch,
const uint32_t height, std::vector<uint32_t>& chromaOffsets);
/**
* @brief This a static function to get the chroma plane pitch for YUV planar formats.
*/
static uint32_t GetChromaPitch(const NV_ENC_BUFFER_FORMAT bufferFormat, const uint32_t lumaPitch);
/**
* @brief This a static function to get the number of chroma planes for YUV planar formats.
*/
static uint32_t GetNumChromaPlanes(const NV_ENC_BUFFER_FORMAT bufferFormat);
/**
* @brief This a static function to get the chroma plane width in bytes for YUV planar formats.
*/
static uint32_t GetChromaWidthInBytes(const NV_ENC_BUFFER_FORMAT bufferFormat, const uint32_t lumaWidth);
/**
* @brief This a static function to get the chroma planes height in bytes for YUV planar formats.
*/
static uint32_t GetChromaHeight(const NV_ENC_BUFFER_FORMAT bufferFormat, const uint32_t lumaHeight);
/**
* @brief This a static function to get the width in bytes for the frame.
* For YUV planar format this is the width in bytes of the luma plane.
*/
static uint32_t GetWidthInBytes(const NV_ENC_BUFFER_FORMAT bufferFormat, const uint32_t width);
/**
* @brief This function returns the number of allocated buffers.
*/
uint32_t GetEncoderBufferCount() const { return m_nEncoderBuffer; }
protected:
/**
* @brief NvEncoder class constructor.
* NvEncoder class constructor cannot be called directly by the application.
*/
NvEncoder(NV_ENC_DEVICE_TYPE eDeviceType, void* pDevice, uint32_t nWidth, uint32_t nHeight,
NV_ENC_BUFFER_FORMAT eBufferFormat, uint32_t nOutputDelay);
/**
* @brief This function is used to check if hardware encoder is properly initialized.
*/
bool IsHWEncoderInitialized() const { return m_hEncoder != NULL && m_bEncoderInitialized; }
/**
* @brief This function is used to register CUDA, D3D or OpenGL input buffers with NvEncodeAPI.
* This is non public function and is called by derived class for allocating
* and registering input buffers.
*/
void RegisterInputResources(std::vector<void*> inputframes, NV_ENC_INPUT_RESOURCE_TYPE eResourceType,
int width, int height, int pitch, NV_ENC_BUFFER_FORMAT bufferFormat, bool bReferenceFrame = false);
/**
* @brief This function is used to unregister resources which had been previously registered for encoding
* using RegisterInputResources() function.
*/
void UnregisterInputResources();
/**
* @brief This function is used to register CUDA, D3D or OpenGL input or output buffers with NvEncodeAPI.
*/
NV_ENC_REGISTERED_PTR RegisterResource(void* pBuffer, NV_ENC_INPUT_RESOURCE_TYPE eResourceType,
int width, int height, int pitch, NV_ENC_BUFFER_FORMAT bufferFormat, NV_ENC_BUFFER_USAGE bufferUsage = NV_ENC_INPUT_IMAGE,
NV_ENC_FENCE_POINT_D3D12* pInputFencePoint = NULL);
/**
* @brief This function returns maximum width used to open the encoder session.
* All encode input buffers are allocated using maximum dimensions.
*/
uint32_t GetMaxEncodeWidth() const { return m_nMaxEncodeWidth; }
/**
* @brief This function returns maximum height used to open the encoder session.
* All encode input buffers are allocated using maximum dimensions.
*/
uint32_t GetMaxEncodeHeight() const { return m_nMaxEncodeHeight; }
/**
* @brief This function returns the completion event.
*/
void* GetCompletionEvent(uint32_t eventIdx) { return (m_vpCompletionEvent.size() == m_nEncoderBuffer) ? m_vpCompletionEvent[eventIdx] : nullptr; }
/**
* @brief This function returns the current pixel format.
*/
NV_ENC_BUFFER_FORMAT GetPixelFormat() const { return m_eBufferFormat; }
/**
* @brief This function is used to submit the encode commands to the
* NVENC hardware.
*/
NVENCSTATUS DoEncode(NV_ENC_INPUT_PTR inputBuffer, NV_ENC_OUTPUT_PTR outputBuffer, NV_ENC_PIC_PARAMS* pPicParams);
/**
* @brief This function is used to submit the encode commands to the
* NVENC hardware for ME only mode.
*/
//NVENCSTATUS DoMotionEstimation(NV_ENC_INPUT_PTR inputBuffer, NV_ENC_INPUT_PTR inputBufferForReference, NV_ENC_OUTPUT_PTR outputBuffer);
/**
* @brief This function is used to map the input buffers to NvEncodeAPI.
*/
void MapResources(uint32_t bfrIdx);
/**
* @brief This function is used to wait for completion of encode command.
*/
void WaitForCompletionEvent(int iEvent);
/**
* @brief This function is used to send EOS to HW encoder.
*/
void SendEOS();
private:
/**
* @brief This is a private function which is used to check if there is any
buffering done by encoder.
* The encoder generally buffers data to encode B frames or for lookahead
* or pipelining.
*/
bool IsZeroDelay() { return m_nOutputDelay == 0; }
/**
* @brief This is a private function which is used to load the encode api shared library.
*/
void LoadNvEncApi();
/**
* @brief This is a private function which is used to get the output packets
* from the encoder HW.
* This is called by DoEncode() function. If there is buffering enabled,
* this may return without any output data.
*/
void GetEncodedPacket(std::vector<NV_ENC_OUTPUT_PTR>& vOutputBuffer, std::vector<std::vector<uint8_t>>& vPacket, std::vector<uint64_t>& outputTimeStamps, bool bOutputDelay);
/**
* @brief This is a private function which is used to initialize the bitstream buffers.
* This is only used in the encoding mode.
*/
void InitializeBitstreamBuffer();
/**
* @brief This is a private function which is used to destroy the bitstream buffers.
* This is only used in the encoding mode.
*/
void DestroyBitstreamBuffer();
/**
* @brief This is a private function which is used to destroy HW encoder.
*/
void DestroyHWEncoder();
/**
* @brief This function is used to flush the encoder queue.
*/
void FlushEncoder();
private:
/**
* @brief This is a pure virtual function which is used to allocate input buffers.
* The derived classes must implement this function.
*/
virtual void AllocateInputBuffers(int32_t numInputBuffers) = 0;
/**
* @brief This is a pure virtual function which is used to destroy input buffers.
* The derived classes must implement this function.
*/
virtual void ReleaseInputBuffers() = 0;
protected:
void* m_hEncoder = nullptr;
NV_ENCODE_API_FUNCTION_LIST m_nvenc;
std::vector<NvEncInputFrame> m_vInputFrames;
std::vector<NV_ENC_REGISTERED_PTR> m_vRegisteredResources;
std::vector<NvEncInputFrame> m_vReferenceFrames;
std::vector<NV_ENC_REGISTERED_PTR> m_vRegisteredResourcesForReference;
std::vector<NV_ENC_INPUT_PTR> m_vMappedInputBuffers;
std::vector<NV_ENC_INPUT_PTR> m_vMappedRefBuffers;
std::vector<void*> m_vpCompletionEvent;
int32_t m_iToSend = 0;
int32_t m_iGot = 0;
int32_t m_nEncoderBuffer = 0;
int32_t m_nOutputDelay = 0;
int32_t m_iInputFrame = 0;
private:
void* m_pDevice;
NV_ENC_DEVICE_TYPE m_eDeviceType;
uint32_t m_nWidth;
uint32_t m_nHeight;
uint32_t m_nMaxEncodeWidth = 0;
uint32_t m_nMaxEncodeHeight = 0;
NV_ENC_BUFFER_FORMAT m_eBufferFormat;
NV_ENC_INITIALIZE_PARAMS m_initializeParams = {};
NV_ENC_CONFIG m_encodeConfig = {};
bool m_bEncoderInitialized = false;
uint32_t m_nExtraOutputDelay = 3; // To ensure encode and graphics can work in parallel, m_nExtraOutputDelay should be set to at least 1
std::vector<NV_ENC_OUTPUT_PTR> m_vBitstreamOutputBuffer;
};
}}
#endif
+196
View File
@@ -0,0 +1,196 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#include "precomp.hpp"
#if defined(HAVE_NVCUVENC)
#include "NvEncoderCuda.h"
namespace cv { namespace cudacodec {
NvEncoderCuda::NvEncoderCuda(CUcontext cuContext, uint32_t nWidth, uint32_t nHeight, NV_ENC_BUFFER_FORMAT eBufferFormat,
uint32_t nExtraOutputDelay) :
NvEncoder(NV_ENC_DEVICE_TYPE_CUDA, cuContext, nWidth, nHeight, eBufferFormat, nExtraOutputDelay),
m_cuContext(cuContext)
{
if (!m_hEncoder)
{
NVENC_THROW_ERROR("Encoder Initialization failed", NV_ENC_ERR_INVALID_DEVICE);
}
if (!m_cuContext)
{
NVENC_THROW_ERROR("Invalid Cuda Context", NV_ENC_ERR_INVALID_DEVICE);
}
}
NvEncoderCuda::~NvEncoderCuda()
{
ReleaseCudaResources();
}
void NvEncoderCuda::AllocateInputBuffers(int32_t numInputBuffers)
{
if (!IsHWEncoderInitialized())
{
NVENC_THROW_ERROR("Encoder intialization failed", NV_ENC_ERR_ENCODER_NOT_INITIALIZED);
}
cuSafeCall(cuCtxPushCurrent(m_cuContext));
std::vector<void*> inputFrames;
for (int i = 0; i < numInputBuffers; i++)
{
CUdeviceptr pDeviceFrame;
uint32_t chromaHeight = GetNumChromaPlanes(GetPixelFormat()) * GetChromaHeight(GetPixelFormat(), GetMaxEncodeHeight());
if (GetPixelFormat() == NV_ENC_BUFFER_FORMAT_YV12 || GetPixelFormat() == NV_ENC_BUFFER_FORMAT_IYUV)
chromaHeight = GetChromaHeight(GetPixelFormat(), GetMaxEncodeHeight());
cuSafeCall(cuMemAllocPitch((CUdeviceptr*)&pDeviceFrame,
&m_cudaPitch,
GetWidthInBytes(GetPixelFormat(), GetMaxEncodeWidth()),
GetMaxEncodeHeight() + chromaHeight, 16));
inputFrames.push_back((void*)pDeviceFrame);
}
cuSafeCall(cuCtxPopCurrent(NULL));
RegisterInputResources(inputFrames,
NV_ENC_INPUT_RESOURCE_TYPE_CUDADEVICEPTR,
GetMaxEncodeWidth(),
GetMaxEncodeHeight(),
(int)m_cudaPitch,
GetPixelFormat(),
false);
}
void NvEncoderCuda::SetIOCudaStreams(NV_ENC_CUSTREAM_PTR inputStream, NV_ENC_CUSTREAM_PTR outputStream)
{
NVENC_API_CALL(m_nvenc.nvEncSetIOCudaStreams(m_hEncoder, inputStream, outputStream));
}
void NvEncoderCuda::ReleaseInputBuffers()
{
ReleaseCudaResources();
}
void NvEncoderCuda::ReleaseCudaResources()
{
if (!m_hEncoder)
{
return;
}
if (!m_cuContext)
{
return;
}
UnregisterInputResources();
cuCtxPushCurrent(m_cuContext);
for (uint32_t i = 0; i < m_vInputFrames.size(); ++i)
{
if (m_vInputFrames[i].inputPtr)
{
cuMemFree(reinterpret_cast<CUdeviceptr>(m_vInputFrames[i].inputPtr));
}
}
m_vInputFrames.clear();
for (uint32_t i = 0; i < m_vReferenceFrames.size(); ++i)
{
if (m_vReferenceFrames[i].inputPtr)
{
cuMemFree(reinterpret_cast<CUdeviceptr>(m_vReferenceFrames[i].inputPtr));
}
}
m_vReferenceFrames.clear();
cuCtxPopCurrent(NULL);
m_cuContext = nullptr;
}
void NvEncoderCuda::CopyToDeviceFrame(CUcontext device,
void* pSrcFrame,
uint32_t nSrcPitch,
CUdeviceptr pDstFrame,
uint32_t dstPitch,
int width,
int height,
CUmemorytype srcMemoryType,
NV_ENC_BUFFER_FORMAT pixelFormat,
const uint32_t dstChromaOffsets[],
uint32_t numChromaPlanes,
bool bUnAlignedDeviceCopy,
CUstream stream)
{
if (srcMemoryType != CU_MEMORYTYPE_HOST && srcMemoryType != CU_MEMORYTYPE_DEVICE)
{
NVENC_THROW_ERROR("Invalid source memory type for copy", NV_ENC_ERR_INVALID_PARAM);
}
cuSafeCall(cuCtxPushCurrent(device));
uint32_t srcPitch = nSrcPitch ? nSrcPitch : NvEncoder::GetWidthInBytes(pixelFormat, width);
CUDA_MEMCPY2D m = {};
m.srcMemoryType = srcMemoryType;
if (srcMemoryType == CU_MEMORYTYPE_HOST)
{
m.srcHost = pSrcFrame;
}
else
{
m.srcDevice = (CUdeviceptr)pSrcFrame;
}
m.srcPitch = srcPitch;
m.dstMemoryType = CU_MEMORYTYPE_DEVICE;
m.dstDevice = pDstFrame;
m.dstPitch = dstPitch;
m.WidthInBytes = NvEncoder::GetWidthInBytes(pixelFormat, width);
m.Height = height;
if (bUnAlignedDeviceCopy && srcMemoryType == CU_MEMORYTYPE_DEVICE)
{
cuSafeCall(cuMemcpy2DUnaligned(&m));
}
else
{
cuSafeCall(stream == NULL ? cuMemcpy2D(&m) : cuMemcpy2DAsync(&m, stream));
}
std::vector<uint32_t> srcChromaOffsets;
NvEncoder::GetChromaSubPlaneOffsets(pixelFormat, srcPitch, height, srcChromaOffsets);
uint32_t chromaHeight = NvEncoder::GetChromaHeight(pixelFormat, height);
uint32_t destChromaPitch = NvEncoder::GetChromaPitch(pixelFormat, dstPitch);
uint32_t srcChromaPitch = NvEncoder::GetChromaPitch(pixelFormat, srcPitch);
uint32_t chromaWidthInBytes = NvEncoder::GetChromaWidthInBytes(pixelFormat, width);
for (uint32_t i = 0; i < numChromaPlanes; ++i)
{
if (chromaHeight)
{
if (srcMemoryType == CU_MEMORYTYPE_HOST)
{
m.srcHost = ((uint8_t*)pSrcFrame + srcChromaOffsets[i]);
}
else
{
m.srcDevice = (CUdeviceptr)((uint8_t*)pSrcFrame + srcChromaOffsets[i]);
}
m.srcPitch = srcChromaPitch;
m.dstDevice = (CUdeviceptr)((uint8_t*)pDstFrame + dstChromaOffsets[i]);
m.dstPitch = destChromaPitch;
m.WidthInBytes = chromaWidthInBytes;
m.Height = chromaHeight;
if (bUnAlignedDeviceCopy && srcMemoryType == CU_MEMORYTYPE_DEVICE)
{
cuSafeCall(cuMemcpy2DUnaligned(&m));
}
else
{
cuSafeCall(stream == NULL ? cuMemcpy2D(&m) : cuMemcpy2DAsync(&m, stream));
}
}
}
cuSafeCall(cuCtxPopCurrent(NULL));
}
}}
#endif
+75
View File
@@ -0,0 +1,75 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#ifndef OPENCV_NVENCODERCUDA_HPP
#define OPENCV_NVENCODERCUDA_HPP
#include <vector>
#include <stdint.h>
#include <mutex>
#include <cuda.h>
#include "NvEncoder.h"
namespace cv { namespace cudacodec {
/**
* @brief Encoder for CUDA device memory.
*/
class NvEncoderCuda : public NvEncoder
{
public:
NvEncoderCuda(CUcontext cuContext, uint32_t nWidth, uint32_t nHeight, NV_ENC_BUFFER_FORMAT eBufferFormat,
uint32_t nExtraOutputDelay = 3);
virtual ~NvEncoderCuda();
/**
* @brief This is a static function to copy input data from host memory to device memory.
* This function assumes YUV plane is a single contiguous memory segment.
*/
static void CopyToDeviceFrame(CUcontext device,
void* pSrcFrame,
uint32_t nSrcPitch,
CUdeviceptr pDstFrame,
uint32_t dstPitch,
int width,
int height,
CUmemorytype srcMemoryType,
NV_ENC_BUFFER_FORMAT pixelFormat,
const uint32_t dstChromaOffsets[],
uint32_t numChromaPlanes,
bool bUnAlignedDeviceCopy = false,
CUstream stream = NULL);
/**
* @brief This function sets input and output CUDA streams
*/
void SetIOCudaStreams(NV_ENC_CUSTREAM_PTR inputStream, NV_ENC_CUSTREAM_PTR outputStream);
protected:
/**
* @brief This function is used to release the input buffers allocated for encoding.
* This function is an override of virtual function NvEncoder::ReleaseInputBuffers().
*/
virtual void ReleaseInputBuffers() override;
private:
/**
* @brief This function is used to allocate input buffers for encoding.
* This function is an override of virtual function NvEncoder::AllocateInputBuffers().
*/
virtual void AllocateInputBuffers(int32_t numInputBuffers) override;
private:
/**
* @brief This is a private function to release CUDA device memory used for encoding.
*/
void ReleaseCudaResources();
protected:
CUcontext m_cuContext;
private:
size_t m_cudaPitch = 0;
};
}}
#endif
+699
View File
@@ -0,0 +1,699 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#include "ColorSpace.h"
#include <opencv2/cudacodec.hpp>
#include <opencv2/core/cuda/common.hpp>
namespace cv { namespace cuda { namespace device {
template<class T>
__device__ static T Clamp(T x, T lower, T upper) {
return x < lower ? lower : (x > upper ? upper : x);
}
template<class Gray, class YuvUnit>
__device__ inline Gray YToGrayForPixel(YuvUnit y, float lumaCoeff, bool videoFullRangeFlag) {
const int low = videoFullRangeFlag ? 0 : 1 << (sizeof(YuvUnit) * 8 - 4);
float fy = (int)y - low;
const float maxf = (1 << sizeof(YuvUnit) * 8) - 1.0f;
YuvUnit g = (YuvUnit)Clamp(lumaCoeff * fy, 0.0f, maxf);
const int nShift = abs((int)sizeof(YuvUnit) - (int)sizeof(Gray)) * 8;
Gray gray{};
if (sizeof(YuvUnit) >= sizeof(Gray))
gray = g >> nShift;
else
gray = g << nShift;
return gray;
}
template<class Color, class YuvUnit>
__device__ inline Color YuvToColorForPixel(YuvUnit y, YuvUnit u, YuvUnit v, ColorMatrix matYuv2Color, bool videoFullRangeFlag) {
const int
low = videoFullRangeFlag ? 0 : 1 << (sizeof(YuvUnit) * 8 - 4),
mid = 1 << (sizeof(YuvUnit) * 8 - 1);
float fy = (int)y - low, fu = (int)u - mid, fv = (int)v - mid;
const float maxf = (1 << sizeof(YuvUnit) * 8) - 1.0f;
YuvUnit
r = (YuvUnit)Clamp(matYuv2Color.m[0][0] * fy + matYuv2Color.m[0][1] * fu + matYuv2Color.m[0][2] * fv, 0.0f, maxf),
g = (YuvUnit)Clamp(matYuv2Color.m[1][0] * fy + matYuv2Color.m[1][1] * fu + matYuv2Color.m[1][2] * fv, 0.0f, maxf),
b = (YuvUnit)Clamp(matYuv2Color.m[2][0] * fy + matYuv2Color.m[2][1] * fu + matYuv2Color.m[2][2] * fv, 0.0f, maxf);
Color color{};
const int nShift = abs((int)sizeof(YuvUnit) - (int)sizeof(color.c.r)) * 8;
if (sizeof(YuvUnit) >= sizeof(color.c.r)) {
color.c.r = r >> nShift;
color.c.g = g >> nShift;
color.c.b = b >> nShift;
}
else {
color.c.r = r << nShift;
color.c.g = g << nShift;
color.c.b = b << nShift;
}
return color;
}
template<class Color, class YuvUnit>
__device__ inline Color YuvToColoraForPixel(YuvUnit y, YuvUnit u, YuvUnit v, ColorMatrix matYuv2Color, bool videoFullRangeFlag) {
Color color = YuvToColorForPixel<Color>(y, u, v, matYuv2Color, videoFullRangeFlag);
const float maxf = (1 << sizeof(color.c.r) * 8) - 1.0f;
color.c.a = maxf;
return color;
}
template<class Yuvx2, class Gray, class Grayx2>
__global__ static void YToGrayKernel(uint8_t* pYuv, int nYuvPitch, uint8_t* pGray, int nGrayPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag) {
int x = (threadIdx.x + blockIdx.x * blockDim.x) * 2;
int y = (threadIdx.y + blockIdx.y * blockDim.y);
if (x + 1 >= nWidth || y >= nHeight) {
return;
}
uint8_t* pSrc = pYuv + x * sizeof(Yuvx2) / 2 + y * nYuvPitch;
uint8_t* pDst = pGray + x * sizeof(Gray) + y * nGrayPitch;
Yuvx2 l0 = *(Yuvx2*)pSrc;
*(Grayx2*)pDst = Grayx2{
YToGrayForPixel<Gray>(l0.x, matYuv2Color.m[0][0], videoFullRangeFlag),
YToGrayForPixel<Gray>(l0.y, matYuv2Color.m[0][0], videoFullRangeFlag),
};
}
template<class Yuvx2, class Color, class Colorx2>
__global__ static void YuvToColorKernel(uint8_t* pYuv, int nYuvPitch, uint8_t* pColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag) {
int x = (threadIdx.x + blockIdx.x * blockDim.x) * 2;
int y = (threadIdx.y + blockIdx.y * blockDim.y) * 2;
if (x + 1 >= nWidth || y + 1 >= nHeight) {
return;
}
uint8_t* pSrc = pYuv + x * sizeof(Yuvx2) / 2 + y * nYuvPitch;
uint8_t* pDst = pColor + x * sizeof(Color) + y * nColorPitch;
Yuvx2 l0 = *(Yuvx2*)pSrc;
Yuvx2 l1 = *(Yuvx2*)(pSrc + nYuvPitch);
Yuvx2 ch = *(Yuvx2*)(pSrc + (nHeight - y / 2) * nYuvPitch);
union ColorOutx2 {
Colorx2 d;
Color color[2];
};
ColorOutx2 l1Out;
l1Out.color[0] = YuvToColorForPixel<Color>(l0.x, ch.x, ch.y, matYuv2Color, videoFullRangeFlag);
l1Out.color[1] = YuvToColorForPixel<Color>(l0.y, ch.x, ch.y, matYuv2Color, videoFullRangeFlag);
*(Colorx2*)pDst = l1Out.d;
ColorOutx2 l2Out;
l2Out.color[0] = YuvToColorForPixel<Color>(l1.x, ch.x, ch.y, matYuv2Color, videoFullRangeFlag);
l2Out.color[1] = YuvToColorForPixel<Color>(l1.y, ch.x, ch.y, matYuv2Color, videoFullRangeFlag);
*(Colorx2*)(pDst + nColorPitch) = l2Out.d;
}
template<class YuvUnitx2, class Color, class ColorIntx2>
__global__ static void YuvToColoraKernel(uint8_t* pYuv, int nYuvPitch, uint8_t* pColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag) {
int x = (threadIdx.x + blockIdx.x * blockDim.x) * 2;
int y = (threadIdx.y + blockIdx.y * blockDim.y) * 2;
if (x + 1 >= nWidth || y + 1 >= nHeight) {
return;
}
uint8_t* pSrc = pYuv + x * sizeof(YuvUnitx2) / 2 + y * nYuvPitch;
uint8_t* pDst = pColor + x * sizeof(Color) + y * nColorPitch;
YuvUnitx2 l0 = *(YuvUnitx2*)pSrc;
YuvUnitx2 l1 = *(YuvUnitx2*)(pSrc + nYuvPitch);
YuvUnitx2 ch = *(YuvUnitx2*)(pSrc + (nHeight - y / 2) * nYuvPitch);
*(ColorIntx2*)pDst = ColorIntx2{
YuvToColoraForPixel<Color>(l0.x, ch.x, ch.y, matYuv2Color, videoFullRangeFlag).d,
YuvToColoraForPixel<Color>(l0.y, ch.x, ch.y, matYuv2Color, videoFullRangeFlag).d,
};
*(ColorIntx2*)(pDst + nColorPitch) = ColorIntx2{
YuvToColoraForPixel<Color>(l1.x, ch.x, ch.y, matYuv2Color, videoFullRangeFlag).d,
YuvToColoraForPixel<Color>(l1.y, ch.x, ch.y, matYuv2Color, videoFullRangeFlag).d,
};
}
template<class YuvUnitx2, class Color, class Colorx2>
__global__ static void Yuv444ToColorKernel(uint8_t* pYuv, int nYuvPitch, uint8_t* pColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag) {
int x = (threadIdx.x + blockIdx.x * blockDim.x) * 2;
int y = (threadIdx.y + blockIdx.y * blockDim.y);
if (x + 1 >= nWidth || y >= nHeight) {
return;
}
uint8_t* pSrc = pYuv + x * sizeof(YuvUnitx2) / 2 + y * nYuvPitch;
uint8_t* pDst = pColor + x * sizeof(Color) + y * nColorPitch;
YuvUnitx2 l0 = *(YuvUnitx2*)pSrc;
YuvUnitx2 ch1 = *(YuvUnitx2*)(pSrc + (nHeight * nYuvPitch));
YuvUnitx2 ch2 = *(YuvUnitx2*)(pSrc + (2 * nHeight * nYuvPitch));
union ColorOutx2 {
Colorx2 d;
Color color[2];
};
ColorOutx2 out;
out.color[0] = YuvToColorForPixel<Color>(l0.x, ch1.x, ch2.x, matYuv2Color, videoFullRangeFlag);
out.color[1] = YuvToColorForPixel<Color>(l0.y, ch1.y, ch2.y, matYuv2Color, videoFullRangeFlag);
*(Colorx2*)pDst = out.d;
}
template<class YuvUnitx2, class Color, class ColorIntx2>
__global__ static void Yuv444ToColoraKernel(uint8_t* pYuv, int nYuvPitch, uint8_t* pColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag) {
int x = (threadIdx.x + blockIdx.x * blockDim.x) * 2;
int y = (threadIdx.y + blockIdx.y * blockDim.y);
if (x + 1 >= nWidth || y >= nHeight) {
return;
}
uint8_t* pSrc = pYuv + x * sizeof(YuvUnitx2) / 2 + y * nYuvPitch;
uint8_t* pDst = pColor + x * sizeof(Color) + y * nColorPitch;
YuvUnitx2 l0 = *(YuvUnitx2*)pSrc;
YuvUnitx2 ch1 = *(YuvUnitx2*)(pSrc + (nHeight * nYuvPitch));
YuvUnitx2 ch2 = *(YuvUnitx2*)(pSrc + (2 * nHeight * nYuvPitch));
*(ColorIntx2*)pDst = ColorIntx2{
YuvToColoraForPixel<Color>(l0.x, ch1.x, ch2.x, matYuv2Color, videoFullRangeFlag).d,
YuvToColoraForPixel<Color>(l0.y, ch1.y, ch2.y, matYuv2Color, videoFullRangeFlag).d,
};
}
template<class YuvUnitx2, class Color, class ColorUnitx2>
__global__ static void YuvToColorPlanarKernel(uint8_t* pYuv, int nYuvPitch, uint8_t* pColorp, int nColorpPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag) {
int x = (threadIdx.x + blockIdx.x * blockDim.x) * 2;
int y = (threadIdx.y + blockIdx.y * blockDim.y) * 2;
if (x + 1 >= nWidth || y + 1 >= nHeight) {
return;
}
uint8_t* pSrc = pYuv + x * sizeof(YuvUnitx2) / 2 + y * nYuvPitch;
YuvUnitx2 l0 = *(YuvUnitx2*)pSrc;
YuvUnitx2 l1 = *(YuvUnitx2*)(pSrc + nYuvPitch);
YuvUnitx2 ch = *(YuvUnitx2*)(pSrc + (nHeight - y / 2) * nYuvPitch);
Color color0 = YuvToColorForPixel<Color>(l0.x, ch.x, ch.y, matYuv2Color, videoFullRangeFlag),
color1 = YuvToColorForPixel<Color>(l0.y, ch.x, ch.y, matYuv2Color, videoFullRangeFlag),
color2 = YuvToColorForPixel<Color>(l1.x, ch.x, ch.y, matYuv2Color, videoFullRangeFlag),
color3 = YuvToColorForPixel<Color>(l1.y, ch.x, ch.y, matYuv2Color, videoFullRangeFlag);
uint8_t* pDst = pColorp + x * sizeof(ColorUnitx2) / 2 + y * nColorpPitch;
*(ColorUnitx2*)pDst = ColorUnitx2{ color0.v.x, color1.v.x };
*(ColorUnitx2*)(pDst + nColorpPitch) = ColorUnitx2{ color2.v.x, color3.v.x };
pDst += nColorpPitch * nHeight;
*(ColorUnitx2*)pDst = ColorUnitx2{ color0.v.y, color1.v.y };
*(ColorUnitx2*)(pDst + nColorpPitch) = ColorUnitx2{ color2.v.y, color3.v.y };
pDst += nColorpPitch * nHeight;
*(ColorUnitx2*)pDst = ColorUnitx2{ color0.v.z, color1.v.z };
*(ColorUnitx2*)(pDst + nColorpPitch) = ColorUnitx2{ color2.v.z, color3.v.z };
}
template<class YuvUnitx2, class Color, class ColorUnitx2>
__global__ static void YuvToColoraPlanarKernel(uint8_t* pYuv, int nYuvPitch, uint8_t* pColorp, int nColorpPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag) {
int x = (threadIdx.x + blockIdx.x * blockDim.x) * 2;
int y = (threadIdx.y + blockIdx.y * blockDim.y) * 2;
if (x + 1 >= nWidth || y + 1 >= nHeight) {
return;
}
uint8_t* pSrc = pYuv + x * sizeof(YuvUnitx2) / 2 + y * nYuvPitch;
YuvUnitx2 l0 = *(YuvUnitx2*)pSrc;
YuvUnitx2 l1 = *(YuvUnitx2*)(pSrc + nYuvPitch);
YuvUnitx2 ch = *(YuvUnitx2*)(pSrc + (nHeight - y / 2) * nYuvPitch);
Color color0 = YuvToColoraForPixel<Color>(l0.x, ch.x, ch.y, matYuv2Color, videoFullRangeFlag),
color1 = YuvToColoraForPixel<Color>(l0.y, ch.x, ch.y, matYuv2Color, videoFullRangeFlag),
color2 = YuvToColoraForPixel<Color>(l1.x, ch.x, ch.y, matYuv2Color, videoFullRangeFlag),
color3 = YuvToColoraForPixel<Color>(l1.y, ch.x, ch.y, matYuv2Color, videoFullRangeFlag);
uint8_t* pDst = pColorp + x * sizeof(ColorUnitx2) / 2 + y * nColorpPitch;
*(ColorUnitx2*)pDst = ColorUnitx2{ color0.v.x, color1.v.x };
*(ColorUnitx2*)(pDst + nColorpPitch) = ColorUnitx2{ color2.v.x, color3.v.x };
pDst += nColorpPitch * nHeight;
*(ColorUnitx2*)pDst = ColorUnitx2{ color0.v.y, color1.v.y };
*(ColorUnitx2*)(pDst + nColorpPitch) = ColorUnitx2{ color2.v.y, color3.v.y };
pDst += nColorpPitch * nHeight;
*(ColorUnitx2*)pDst = ColorUnitx2{ color0.v.z, color1.v.z };
*(ColorUnitx2*)(pDst + nColorpPitch) = ColorUnitx2{ color2.v.z, color3.v.z };
pDst += nColorpPitch * nHeight;
*(ColorUnitx2*)pDst = ColorUnitx2{ color0.v.w, color1.v.w };
*(ColorUnitx2*)(pDst + nColorpPitch) = ColorUnitx2{ color2.v.w, color3.v.w };
}
template<class YuvUnitx2, class Color, class ColorUnitx2>
__global__ static void Yuv444ToColorPlanarKernel(uint8_t* pYuv, int nYuvPitch, uint8_t* pColorp, int nColorpPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag) {
int x = (threadIdx.x + blockIdx.x * blockDim.x) * 2;
int y = (threadIdx.y + blockIdx.y * blockDim.y);
if (x + 1 >= nWidth || y >= nHeight) {
return;
}
uint8_t* pSrc = pYuv + x * sizeof(YuvUnitx2) / 2 + y * nYuvPitch;
YuvUnitx2 l0 = *(YuvUnitx2*)pSrc;
YuvUnitx2 ch1 = *(YuvUnitx2*)(pSrc + (nHeight * nYuvPitch));
YuvUnitx2 ch2 = *(YuvUnitx2*)(pSrc + (2 * nHeight * nYuvPitch));
Color color0 = YuvToColorForPixel<Color>(l0.x, ch1.x, ch2.x, matYuv2Color, videoFullRangeFlag),
color1 = YuvToColorForPixel<Color>(l0.y, ch1.y, ch2.y, matYuv2Color, videoFullRangeFlag);
uint8_t* pDst = pColorp + x * sizeof(ColorUnitx2) / 2 + y * nColorpPitch;
*(ColorUnitx2*)pDst = ColorUnitx2{ color0.v.x, color1.v.x };
pDst += nColorpPitch * nHeight;
*(ColorUnitx2*)pDst = ColorUnitx2{ color0.v.y, color1.v.y };
pDst += nColorpPitch * nHeight;
*(ColorUnitx2*)pDst = ColorUnitx2{ color0.v.z, color1.v.z };
}
template<class YuvUnitx2, class Color, class ColorUnitx2>
__global__ static void Yuv444ToColoraPlanarKernel(uint8_t* pYuv, int nYuvPitch, uint8_t* pColorp, int nColorpPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag) {
int x = (threadIdx.x + blockIdx.x * blockDim.x) * 2;
int y = (threadIdx.y + blockIdx.y * blockDim.y);
if (x + 1 >= nWidth || y >= nHeight) {
return;
}
uint8_t* pSrc = pYuv + x * sizeof(YuvUnitx2) / 2 + y * nYuvPitch;
YuvUnitx2 l0 = *(YuvUnitx2*)pSrc;
YuvUnitx2 ch1 = *(YuvUnitx2*)(pSrc + (nHeight * nYuvPitch));
YuvUnitx2 ch2 = *(YuvUnitx2*)(pSrc + (2 * nHeight * nYuvPitch));
Color color0 = YuvToColoraForPixel<Color>(l0.x, ch1.x, ch2.x, matYuv2Color, videoFullRangeFlag),
color1 = YuvToColoraForPixel<Color>(l0.y, ch1.y, ch2.y, matYuv2Color, videoFullRangeFlag);
uint8_t* pDst = pColorp + x * sizeof(ColorUnitx2) / 2 + y * nColorpPitch;
*(ColorUnitx2*)pDst = ColorUnitx2{ color0.v.x, color1.v.x };
pDst += nColorpPitch * nHeight;
*(ColorUnitx2*)pDst = ColorUnitx2{ color0.v.y, color1.v.y };
pDst += nColorpPitch * nHeight;
*(ColorUnitx2*)pDst = ColorUnitx2{ color0.v.z, color1.v.z };
pDst += nColorpPitch * nHeight;
*(ColorUnitx2*)pDst = ColorUnitx2{ color0.v.w, color1.v.w };
}
#define BLOCKSIZE_X 32
#define BLOCKSIZE_Y 8
void Y8ToGray8(uint8_t* dpY8, int nY8Pitch, uint8_t* dpGray, int nGrayPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream) {
YToGrayKernel<uchar2, unsigned char, uchar2>
<<<dim3(divUp(nWidth, 2 * BLOCKSIZE_X), divUp(nHeight, BLOCKSIZE_Y)), dim3(BLOCKSIZE_X, BLOCKSIZE_Y), 0, stream>>>
(dpY8, nY8Pitch, dpGray, nGrayPitch, nWidth, nHeight, matYuv2Color, videoFullRangeFlag);
if (stream == 0)
cudaSafeCall(cudaStreamSynchronize(stream));
}
void Y8ToGray16(uint8_t* dpY8, int nY8Pitch, uint8_t* dpGray, int nGrayPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream) {
YToGrayKernel<uchar2, unsigned short, ushort2>
<<<dim3(divUp(nWidth, 2 * BLOCKSIZE_X), divUp(nHeight, BLOCKSIZE_Y)), dim3(BLOCKSIZE_X, BLOCKSIZE_Y), 0, stream>>>
(dpY8, nY8Pitch, dpGray, nGrayPitch, nWidth, nHeight, matYuv2Color, videoFullRangeFlag);
if (stream == 0)
cudaSafeCall(cudaStreamSynchronize(stream));
}
void Y16ToGray8(uint8_t* dpY16, int nY16Pitch, uint8_t* dpGray, int nGrayPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream) {
YToGrayKernel<ushort2, unsigned char, uchar2>
<<<dim3(divUp(nWidth, 2 * BLOCKSIZE_X), divUp(nHeight, BLOCKSIZE_Y)), dim3(BLOCKSIZE_X, BLOCKSIZE_Y), 0, stream>>>
(dpY16, nY16Pitch, dpGray, nGrayPitch, nWidth, nHeight, matYuv2Color, videoFullRangeFlag);
if (stream == 0)
cudaSafeCall(cudaStreamSynchronize(stream));
}
void Y16ToGray16(uint8_t* dpY16, int nY16Pitch, uint8_t* dpGray, int nGrayPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream) {
YToGrayKernel<ushort2, unsigned short, ushort2>
<<<dim3(divUp(nWidth, 2 * BLOCKSIZE_X), divUp(nHeight, BLOCKSIZE_Y)), dim3(BLOCKSIZE_X, BLOCKSIZE_Y), 0, stream>>>
(dpY16, nY16Pitch, dpGray, nGrayPitch, nWidth, nHeight, matYuv2Color, videoFullRangeFlag);
if (stream == 0)
cudaSafeCall(cudaStreamSynchronize(stream));
}
template <class COLOR24>
void Nv12ToColor24(uint8_t* dpNv12, int nNv12Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream) {
YuvToColorKernel<uchar2, COLOR24, ushort3>
<<<dim3(divUp(nWidth, 2 * BLOCKSIZE_X), divUp(nHeight, 2* BLOCKSIZE_Y)), dim3(BLOCKSIZE_X, BLOCKSIZE_Y), 0, stream>>>
(dpNv12, nNv12Pitch, dpColor, nColorPitch, nWidth, nHeight, matYuv2Color, videoFullRangeFlag);
if (stream == 0)
cudaSafeCall(cudaStreamSynchronize(stream));
}
template <class COLOR32>
void Nv12ToColor32(uint8_t* dpNv12, int nNv12Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream) {
YuvToColoraKernel<uchar2, COLOR32, uint2>
<<<dim3(divUp(nWidth, 2 * BLOCKSIZE_X), divUp(nHeight, 2* BLOCKSIZE_Y)), dim3(BLOCKSIZE_X, BLOCKSIZE_Y), 0, stream>>>
(dpNv12, nNv12Pitch, dpColor, nColorPitch, nWidth, nHeight, matYuv2Color, videoFullRangeFlag);
if (stream == 0)
cudaSafeCall(cudaStreamSynchronize(stream));
}
template <class COLOR48>
void Nv12ToColor48(uint8_t* dpNv12, int nNv12Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream) {
YuvToColorKernel<uchar2, COLOR48, uint3>
<<<dim3(divUp(nWidth, 2 * BLOCKSIZE_X), divUp(nHeight, 2* BLOCKSIZE_Y)), dim3(BLOCKSIZE_X, BLOCKSIZE_Y), 0, stream>>>
(dpNv12, nNv12Pitch, dpColor, nColorPitch, nWidth, nHeight, matYuv2Color, videoFullRangeFlag);
if (stream == 0)
cudaSafeCall(cudaStreamSynchronize(stream));
}
template <class COLOR64>
void Nv12ToColor64(uint8_t* dpNv12, int nNv12Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream) {
YuvToColoraKernel<uchar2, COLOR64, ulonglong2>
<<<dim3(divUp(nWidth, 2 * BLOCKSIZE_X), divUp(nHeight, 2* BLOCKSIZE_Y)), dim3(BLOCKSIZE_X, BLOCKSIZE_Y), 0, stream>>>
(dpNv12, nNv12Pitch, dpColor, nColorPitch, nWidth, nHeight, matYuv2Color, videoFullRangeFlag);
if (stream == 0)
cudaSafeCall(cudaStreamSynchronize(stream));
}
template <class COLOR24>
void YUV444ToColor24(uint8_t* dpYUV444, int nPitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream) {
Yuv444ToColorKernel<uchar2, COLOR24, ushort3>
<<<dim3(divUp(nWidth, 2 * BLOCKSIZE_X), divUp(nHeight, BLOCKSIZE_Y)), dim3(BLOCKSIZE_X, BLOCKSIZE_Y), 0, stream>>>
(dpYUV444, nPitch, dpColor, nColorPitch, nWidth, nHeight, matYuv2Color, videoFullRangeFlag);
if (stream == 0)
cudaSafeCall(cudaStreamSynchronize(stream));
}
template <class COLOR32>
void YUV444ToColor32(uint8_t* dpYUV444, int nPitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream) {
Yuv444ToColoraKernel<uchar2, COLOR32, uint2>
<<<dim3(divUp(nWidth, 2 * BLOCKSIZE_X), divUp(nHeight, BLOCKSIZE_Y)), dim3(BLOCKSIZE_X, BLOCKSIZE_Y), 0, stream>>>
(dpYUV444, nPitch, dpColor, nColorPitch, nWidth, nHeight, matYuv2Color, videoFullRangeFlag);
if (stream == 0)
cudaSafeCall(cudaStreamSynchronize(stream));
}
template <class COLOR48>
void YUV444ToColor48(uint8_t* dpYUV444, int nPitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream) {
Yuv444ToColorKernel<uchar2, COLOR48, uint3>
<<<dim3(divUp(nWidth, 2 * BLOCKSIZE_X), divUp(nHeight, BLOCKSIZE_Y)), dim3(BLOCKSIZE_X, BLOCKSIZE_Y), 0, stream>>>
(dpYUV444, nPitch, dpColor, nColorPitch, nWidth, nHeight, matYuv2Color, videoFullRangeFlag);
if (stream == 0)
cudaSafeCall(cudaStreamSynchronize(stream));
}
template <class COLOR64>
void YUV444ToColor64(uint8_t* dpYUV444, int nPitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream) {
Yuv444ToColoraKernel<uchar2, COLOR64, ulonglong2>
<<<dim3(divUp(nWidth, 2 * BLOCKSIZE_X), divUp(nHeight, BLOCKSIZE_Y)), dim3(BLOCKSIZE_X, BLOCKSIZE_Y), 0, stream>>>
(dpYUV444, nPitch, dpColor, nColorPitch, nWidth, nHeight, matYuv2Color, videoFullRangeFlag);
if (stream == 0)
cudaSafeCall(cudaStreamSynchronize(stream));
}
template <class COLOR24>
void P016ToColor24(uint8_t* dpP016, int nP016Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream) {
YuvToColorKernel<ushort2, COLOR24, ushort3>
<<<dim3(divUp(nWidth, 2 * BLOCKSIZE_X), divUp(nHeight, 2 * BLOCKSIZE_Y)), dim3(BLOCKSIZE_X, BLOCKSIZE_Y), 0, stream>>>
(dpP016, nP016Pitch, dpColor, nColorPitch, nWidth, nHeight, matYuv2Color, videoFullRangeFlag);
if (stream == 0)
cudaSafeCall(cudaStreamSynchronize(stream));
}
template <class COLOR32>
void P016ToColor32(uint8_t* dpP016, int nP016Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream) {
YuvToColoraKernel<ushort2, COLOR32, uint2>
<<<dim3(divUp(nWidth, 2 * BLOCKSIZE_X), divUp(nHeight, 2 * BLOCKSIZE_Y)), dim3(BLOCKSIZE_X, BLOCKSIZE_Y), 0, stream>>>
(dpP016, nP016Pitch, dpColor, nColorPitch, nWidth, nHeight, matYuv2Color, videoFullRangeFlag);
if (stream == 0)
cudaSafeCall(cudaStreamSynchronize(stream));
}
template <class COLOR48>
void P016ToColor48(uint8_t* dpP016, int nP016Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream) {
YuvToColorKernel<ushort2, COLOR48, uint3>
<<<dim3(divUp(nWidth, 2 * BLOCKSIZE_X), divUp(nHeight, 2 * BLOCKSIZE_Y)), dim3(BLOCKSIZE_X, BLOCKSIZE_Y), 0, stream>>>
(dpP016, nP016Pitch, dpColor, nColorPitch, nWidth, nHeight, matYuv2Color, videoFullRangeFlag);
if (stream == 0)
cudaSafeCall(cudaStreamSynchronize(stream));
}
template <class COLOR64>
void P016ToColor64(uint8_t* dpP016, int nP016Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream) {
YuvToColoraKernel<ushort2, COLOR64, ulonglong2>
<<<dim3(divUp(nWidth, 2 * BLOCKSIZE_X), divUp(nHeight, 2 * BLOCKSIZE_Y)), dim3(BLOCKSIZE_X, BLOCKSIZE_Y), 0, stream>>>
(dpP016, nP016Pitch, dpColor, nColorPitch, nWidth, nHeight, matYuv2Color, videoFullRangeFlag);
if (stream == 0)
cudaSafeCall(cudaStreamSynchronize(stream));
}
template <class COLOR24>
void YUV444P16ToColor24(uint8_t* dpYUV444, int nPitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream) {
Yuv444ToColorKernel<ushort2, COLOR24, ushort3>
<<<dim3(divUp(nWidth, 2 * BLOCKSIZE_X), divUp(nHeight, BLOCKSIZE_Y)), dim3(BLOCKSIZE_X, BLOCKSIZE_Y), 0, stream>>>
(dpYUV444, nPitch, dpColor, nColorPitch, nWidth, nHeight, matYuv2Color, videoFullRangeFlag);
if (stream == 0)
cudaSafeCall(cudaStreamSynchronize(stream));
}
template <class COLOR32>
void YUV444P16ToColor32(uint8_t* dpYUV444, int nPitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream) {
Yuv444ToColoraKernel<ushort2, COLOR32, uint2>
<<<dim3(divUp(nWidth, 2 * BLOCKSIZE_X), divUp(nHeight, BLOCKSIZE_Y)), dim3(BLOCKSIZE_X, BLOCKSIZE_Y), 0, stream>>>
(dpYUV444, nPitch, dpColor, nColorPitch, nWidth, nHeight, matYuv2Color, videoFullRangeFlag);
if (stream == 0)
cudaSafeCall(cudaStreamSynchronize(stream));
}
template <class COLOR48>
void YUV444P16ToColor48(uint8_t* dpYUV444, int nPitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream) {
Yuv444ToColorKernel<ushort2, COLOR48, uint3>
<<<dim3(divUp(nWidth, 2 * BLOCKSIZE_X), divUp(nHeight, BLOCKSIZE_Y)), dim3(BLOCKSIZE_X, BLOCKSIZE_Y), 0, stream>>>
(dpYUV444, nPitch, dpColor, nColorPitch, nWidth, nHeight, matYuv2Color, videoFullRangeFlag);
if (stream == 0)
cudaSafeCall(cudaStreamSynchronize(stream));
}
template <class COLOR64>
void YUV444P16ToColor64(uint8_t* dpYUV444, int nPitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream) {
Yuv444ToColoraKernel<ushort2, COLOR64, ulonglong2>
<<<dim3(divUp(nWidth, 2 * BLOCKSIZE_X), divUp(nHeight, BLOCKSIZE_Y)), dim3(BLOCKSIZE_X, BLOCKSIZE_Y), 0, stream>>>
(dpYUV444, nPitch, dpColor, nColorPitch, nWidth, nHeight, matYuv2Color, videoFullRangeFlag);
if (stream == 0)
cudaSafeCall(cudaStreamSynchronize(stream));
}
template <class COLOR24>
void Nv12ToColorPlanar24(uint8_t* dpNv12, int nNv12Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream) {
YuvToColorPlanarKernel<uchar2, COLOR24, uchar2>
<<<dim3(divUp(nWidth, 2 * BLOCKSIZE_X), divUp(nHeight, 2 * BLOCKSIZE_Y)), dim3(BLOCKSIZE_X, BLOCKSIZE_Y), 0, stream>>>
(dpNv12, nNv12Pitch, dpColor, nColorPitch, nWidth, nHeight, matYuv2Color, videoFullRangeFlag);
if (stream == 0)
cudaSafeCall(cudaStreamSynchronize(stream));
}
template <class COLOR32>
void Nv12ToColorPlanar32(uint8_t* dpNv12, int nNv12Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream) {
YuvToColoraPlanarKernel<uchar2, COLOR32, uchar2>
<<<dim3(divUp(nWidth, 2 * BLOCKSIZE_X), divUp(nHeight, 2 * BLOCKSIZE_Y)), dim3(BLOCKSIZE_X, BLOCKSIZE_Y), 0, stream>>>
(dpNv12, nNv12Pitch, dpColor, nColorPitch, nWidth, nHeight, matYuv2Color, videoFullRangeFlag);
if (stream == 0)
cudaSafeCall(cudaStreamSynchronize(stream));
}
template <class COLOR48>
void Nv12ToColorPlanar48(uint8_t* dpNv12, int nNv12Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream) {
YuvToColorPlanarKernel<uchar2, COLOR48, ushort2>
<<<dim3(divUp(nWidth, 2 * BLOCKSIZE_X), divUp(nHeight, 2 * BLOCKSIZE_Y)), dim3(BLOCKSIZE_X, BLOCKSIZE_Y), 0, stream>>>
(dpNv12, nNv12Pitch, dpColor, nColorPitch, nWidth, nHeight, matYuv2Color, videoFullRangeFlag);
if (stream == 0)
cudaSafeCall(cudaStreamSynchronize(stream));
}
template <class COLOR64>
void Nv12ToColorPlanar64(uint8_t* dpNv12, int nNv12Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream) {
YuvToColoraPlanarKernel<uchar2, COLOR64, ushort2>
<<<dim3(divUp(nWidth, 2 * BLOCKSIZE_X), divUp(nHeight, 2 * BLOCKSIZE_Y)), dim3(BLOCKSIZE_X, BLOCKSIZE_Y), 0, stream>>>
(dpNv12, nNv12Pitch, dpColor, nColorPitch, nWidth, nHeight, matYuv2Color, videoFullRangeFlag);
if (stream == 0)
cudaSafeCall(cudaStreamSynchronize(stream));
}
template <class COLOR24>
void P016ToColorPlanar24(uint8_t* dpP016, int nP016Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream) {
YuvToColorPlanarKernel<ushort2, COLOR24, uchar2>
<<<dim3(divUp(nWidth, 2 * BLOCKSIZE_X), divUp(nHeight, 2 * BLOCKSIZE_Y)), dim3(BLOCKSIZE_X, BLOCKSIZE_Y), 0, stream>>>
(dpP016, nP016Pitch, dpColor, nColorPitch, nWidth, nHeight, matYuv2Color, videoFullRangeFlag);
if (stream == 0)
cudaSafeCall(cudaStreamSynchronize(stream));
}
template <class COLOR32>
void P016ToColorPlanar32(uint8_t* dpP016, int nP016Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream) {
YuvToColoraPlanarKernel<ushort2, COLOR32, uchar2>
<<<dim3(divUp(nWidth, 2 * BLOCKSIZE_X), divUp(nHeight, 2 * BLOCKSIZE_Y)), dim3(BLOCKSIZE_X, BLOCKSIZE_Y), 0, stream>>>
(dpP016, nP016Pitch, dpColor, nColorPitch, nWidth, nHeight, matYuv2Color, videoFullRangeFlag);
if (stream == 0)
cudaSafeCall(cudaStreamSynchronize(stream));
}
template <class COLOR48>
void P016ToColorPlanar48(uint8_t* dpP016, int nP016Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream) {
YuvToColorPlanarKernel<ushort2, COLOR48, ushort2>
<<<dim3(divUp(nWidth, 2 * BLOCKSIZE_X), divUp(nHeight, 2 * BLOCKSIZE_Y)), dim3(BLOCKSIZE_X, BLOCKSIZE_Y), 0, stream>>>
(dpP016, nP016Pitch, dpColor, nColorPitch, nWidth, nHeight, matYuv2Color, videoFullRangeFlag);
if (stream == 0)
cudaSafeCall(cudaStreamSynchronize(stream));
}
template <class COLOR64>
void P016ToColorPlanar64(uint8_t* dpP016, int nP016Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream) {
YuvToColoraPlanarKernel<ushort2, COLOR64, ushort2>
<<<dim3(divUp(nWidth, 2 * BLOCKSIZE_X), divUp(nHeight, 2 * BLOCKSIZE_Y)), dim3(BLOCKSIZE_X, BLOCKSIZE_Y), 0, stream>>>
(dpP016, nP016Pitch, dpColor, nColorPitch, nWidth, nHeight, matYuv2Color, videoFullRangeFlag);
if (stream == 0)
cudaSafeCall(cudaStreamSynchronize(stream));
}
template <class COLOR24>
void YUV444ToColorPlanar24(uint8_t* dpYUV444, int nPitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream) {
Yuv444ToColorPlanarKernel<uchar2, COLOR24, uchar2>
<<<dim3(divUp(nWidth, 2 * BLOCKSIZE_X), divUp(nHeight, BLOCKSIZE_Y)), dim3(BLOCKSIZE_X, BLOCKSIZE_Y), 0, stream>>>
(dpYUV444, nPitch, dpColor, nColorPitch, nWidth, nHeight, matYuv2Color, videoFullRangeFlag);
if (stream == 0)
cudaSafeCall(cudaStreamSynchronize(stream));
}
template <class COLOR32>
void YUV444ToColorPlanar32(uint8_t* dpYUV444, int nPitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream) {
Yuv444ToColoraPlanarKernel<uchar2, COLOR32, uchar2>
<<<dim3(divUp(nWidth, 2 * BLOCKSIZE_X), divUp(nHeight, BLOCKSIZE_Y)), dim3(BLOCKSIZE_X, BLOCKSIZE_Y), 0, stream>>>
(dpYUV444, nPitch, dpColor, nColorPitch, nWidth, nHeight, matYuv2Color, videoFullRangeFlag);
if (stream == 0)
cudaSafeCall(cudaStreamSynchronize(stream));
}
template <class COLOR48>
void YUV444ToColorPlanar48(uint8_t* dpYUV444, int nPitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream) {
Yuv444ToColorPlanarKernel<uchar2, COLOR48, ushort2>
<<<dim3(divUp(nWidth, 2 * BLOCKSIZE_X), divUp(nHeight, BLOCKSIZE_Y)), dim3(BLOCKSIZE_X, BLOCKSIZE_Y), 0, stream>>>
(dpYUV444, nPitch, dpColor, nColorPitch, nWidth, nHeight, matYuv2Color, videoFullRangeFlag);
if (stream == 0)
cudaSafeCall(cudaStreamSynchronize(stream));
}
template <class COLOR64>
void YUV444ToColorPlanar64(uint8_t* dpYUV444, int nPitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream) {
Yuv444ToColoraPlanarKernel<uchar2, COLOR64, ushort2>
<<<dim3(divUp(nWidth, 2 * BLOCKSIZE_X), divUp(nHeight, BLOCKSIZE_Y)), dim3(BLOCKSIZE_X, BLOCKSIZE_Y), 0, stream>>>
(dpYUV444, nPitch, dpColor, nColorPitch, nWidth, nHeight, matYuv2Color, videoFullRangeFlag);
if (stream == 0)
cudaSafeCall(cudaStreamSynchronize(stream));
}
template <class COLOR24>
void YUV444P16ToColorPlanar24(uint8_t* dpYUV444, int nPitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream) {
Yuv444ToColorPlanarKernel<ushort2, COLOR24, uchar2>
<<<dim3(divUp(nWidth, 2 * BLOCKSIZE_X), divUp(nHeight, BLOCKSIZE_Y)), dim3(BLOCKSIZE_X, BLOCKSIZE_Y), 0, stream>>>
(dpYUV444, nPitch, dpColor, nColorPitch, nWidth, nHeight, matYuv2Color, videoFullRangeFlag);
if (stream == 0)
cudaSafeCall(cudaStreamSynchronize(stream));
}
template <class COLOR32>
void YUV444P16ToColorPlanar32(uint8_t* dpYUV444, int nPitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream) {
Yuv444ToColoraPlanarKernel<ushort2, COLOR32, uchar2>
<<<dim3(divUp(nWidth, 2 * BLOCKSIZE_X), divUp(nHeight, BLOCKSIZE_Y)), dim3(BLOCKSIZE_X, BLOCKSIZE_Y), 0, stream>>>
(dpYUV444, nPitch, dpColor, nColorPitch, nWidth, nHeight, matYuv2Color, videoFullRangeFlag);
if (stream == 0)
cudaSafeCall(cudaStreamSynchronize(stream));
}
template <class COLOR48>
void YUV444P16ToColorPlanar48(uint8_t* dpYUV444, int nPitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream) {
Yuv444ToColorPlanarKernel<ushort2, COLOR48, ushort2>
<<<dim3(divUp(nWidth, 2 * BLOCKSIZE_X), divUp(nHeight, BLOCKSIZE_Y)), dim3(BLOCKSIZE_X, BLOCKSIZE_Y), 0, stream>>>
(dpYUV444, nPitch, dpColor, nColorPitch, nWidth, nHeight, matYuv2Color, videoFullRangeFlag);
if (stream == 0)
cudaSafeCall(cudaStreamSynchronize(stream));
}
template <class COLOR64>
void YUV444P16ToColorPlanar64(uint8_t* dpYUV444, int nPitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream) {
Yuv444ToColoraPlanarKernel<ushort2, COLOR64, ushort2>
<<<dim3(divUp(nWidth, 2 * BLOCKSIZE_X), divUp(nHeight, BLOCKSIZE_Y)), dim3(BLOCKSIZE_X, BLOCKSIZE_Y), 0, stream>>>
(dpYUV444, nPitch, dpColor, nColorPitch, nWidth, nHeight, matYuv2Color, videoFullRangeFlag);
if (stream == 0)
cudaSafeCall(cudaStreamSynchronize(stream));
}
template void Nv12ToColor24<BGR24>(uint8_t* dpNv12, int nNv12Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void Nv12ToColor24<RGB24>(uint8_t* dpNv12, int nNv12Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void Nv12ToColor32<BGRA32>(uint8_t* dpNv12, int nNv12Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void Nv12ToColor32<RGBA32>(uint8_t* dpNv12, int nNv12Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void Nv12ToColor48<BGR48>(uint8_t* dpNv12, int nNv12Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void Nv12ToColor48<RGB48>(uint8_t* dpNv12, int nNv12Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void Nv12ToColor64<BGRA64>(uint8_t* dpNv12, int nNv12Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void Nv12ToColor64<RGBA64>(uint8_t* dpNv12, int nNv12Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void Nv12ToColorPlanar24<BGR24>(uint8_t* dpNv12, int nNv12Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void Nv12ToColorPlanar24<RGB24>(uint8_t* dpNv12, int nNv12Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void Nv12ToColorPlanar32<BGRA32>(uint8_t* dpNv12, int nNv12Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void Nv12ToColorPlanar32<RGBA32>(uint8_t* dpNv12, int nNv12Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void Nv12ToColorPlanar48<BGR48>(uint8_t* dpNv12, int nNv12Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void Nv12ToColorPlanar48<RGB48>(uint8_t* dpNv12, int nNv12Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void Nv12ToColorPlanar64<BGRA64>(uint8_t* dpNv12, int nNv12Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void Nv12ToColorPlanar64<RGBA64>(uint8_t* dpNv12, int nNv12Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void P016ToColor24<BGR24>(uint8_t* dpP016, int nP016Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void P016ToColor24<RGB24>(uint8_t* dpP016, int nP016Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void P016ToColor32<BGRA32>(uint8_t* dpP016, int nP016Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void P016ToColor32<RGBA32>(uint8_t* dpP016, int nP016Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void P016ToColor48<BGR48>(uint8_t* dpP016, int nP016Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void P016ToColor48<RGB48>(uint8_t* dpP016, int nP016Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void P016ToColor64<BGRA64>(uint8_t* dpP016, int nP016Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void P016ToColor64<RGBA64>(uint8_t* dpP016, int nP016Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void P016ToColorPlanar24<BGR24>(uint8_t* dpP016, int nP016Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void P016ToColorPlanar24<RGB24>(uint8_t* dpP016, int nP016Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void P016ToColorPlanar32<BGRA32>(uint8_t* dpP016, int nP016Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void P016ToColorPlanar32<RGBA32>(uint8_t* dpP016, int nP016Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void P016ToColorPlanar48<BGR48>(uint8_t* dpP016, int nP016Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void P016ToColorPlanar48<RGB48>(uint8_t* dpP016, int nP016Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void P016ToColorPlanar64<BGRA64>(uint8_t* dpP016, int nP016Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void P016ToColorPlanar64<RGBA64>(uint8_t* dpP016, int nP016Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void YUV444ToColor24<BGR24>(uint8_t* dpYUV444, int nPitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void YUV444ToColor24<RGB24>(uint8_t* dpYUV444, int nPitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void YUV444ToColor32<BGRA32>(uint8_t* dpYUV444, int nPitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void YUV444ToColor32<RGBA32>(uint8_t* dpYUV444, int nPitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void YUV444ToColor48<BGR48>(uint8_t* dpYUV444, int nPitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void YUV444ToColor48<RGB48>(uint8_t* dpYUV444, int nPitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void YUV444ToColor64<BGRA64>(uint8_t* dpYUV444, int nPitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void YUV444ToColor64<RGBA64>(uint8_t* dpYUV444, int nPitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void YUV444ToColorPlanar24<BGR24>(uint8_t* dpYUV444, int nPitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void YUV444ToColorPlanar24<RGB24>(uint8_t* dpYUV444, int nPitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void YUV444ToColorPlanar32<BGRA32>(uint8_t* dpYUV444, int nPitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void YUV444ToColorPlanar32<RGBA32>(uint8_t* dpYUV444, int nPitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void YUV444ToColorPlanar48<BGR48>(uint8_t* dpYUV444, int nPitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void YUV444ToColorPlanar48<RGB48>(uint8_t* dpYUV444, int nPitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void YUV444ToColorPlanar64<BGRA64>(uint8_t* dpYUV444, int nPitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void YUV444ToColorPlanar64<RGBA64>(uint8_t* dpYUV444, int nPitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void YUV444P16ToColor24<BGR24>(uint8_t* dpYUV444, int nPitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void YUV444P16ToColor24<RGB24>(uint8_t* dpYUV444, int nPitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void YUV444P16ToColor32<BGRA32>(uint8_t* dpYUV444, int nPitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void YUV444P16ToColor32<RGBA32>(uint8_t* dpYUV444, int nPitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void YUV444P16ToColor48<BGR48>(uint8_t* dpYUV444, int nPitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void YUV444P16ToColor48<RGB48>(uint8_t* dpYUV444, int nPitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void YUV444P16ToColor64<BGRA64>(uint8_t* dpYUV444, int nPitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void YUV444P16ToColor64<RGBA64>(uint8_t* dpYUV444, int nPitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void YUV444P16ToColorPlanar24<BGR24>(uint8_t* dpYUV444, int nPitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void YUV444P16ToColorPlanar24<RGB24>(uint8_t* dpYUV444, int nPitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void YUV444P16ToColorPlanar32<BGRA32>(uint8_t* dpYUV444, int nPitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void YUV444P16ToColorPlanar32<RGBA32>(uint8_t* dpYUV444, int nPitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void YUV444P16ToColorPlanar48<BGR48>(uint8_t* dpYUV444, int nPitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void YUV444P16ToColorPlanar48<RGB48>(uint8_t* dpYUV444, int nPitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void YUV444P16ToColorPlanar64<BGRA64>(uint8_t* dpYUV444, int nPitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template void YUV444P16ToColorPlanar64<RGBA64>(uint8_t* dpYUV444, int nPitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
}}}
+73
View File
@@ -0,0 +1,73 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#pragma once
#include <stdint.h>
#include <cuda_runtime.h>
namespace cv { namespace cuda { namespace device {
struct ColorMatrix {
float m[3][3];
};
union BGR24 {
uchar3 v;
struct {
uint8_t b, g, r;
} c;
};
union RGB24 {
uchar3 v;
struct {
uint8_t r, g, b;
} c;
};
union BGRA32 {
uint32_t d;
uchar4 v;
struct {
uint8_t b, g, r, a;
} c;
};
union RGBA32 {
uint32_t d;
uchar4 v;
struct {
uint8_t r, g, b, a;
} c;
};
union BGR48 {
ushort3 v;
struct {
uint16_t b, g, r;
} c;
};
union RGB48 {
ushort3 v;
struct {
uint16_t r, g, b;
} c;
};
union BGRA64 {
uint64_t d;
ushort4 v;
struct {
uint16_t b, g, r, a;
} c;
};
union RGBA64 {
uint64_t d;
ushort4 v;
struct {
uint16_t r, g, b, a;
} c;
};
}}}
@@ -0,0 +1,126 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "precomp.hpp"
#ifdef HAVE_NVCUVID
using namespace cv;
using namespace cv::cudacodec;
using namespace cv::cudacodec::detail;
cv::cudacodec::detail::CuvidVideoSource::CuvidVideoSource(const String& fname)
{
CUVIDSOURCEPARAMS params;
std::memset(&params, 0, sizeof(CUVIDSOURCEPARAMS));
// Fill parameter struct
params.pUserData = this; // will be passed to data handlers
params.pfnVideoDataHandler = HandleVideoData; // our local video-handler callback
params.pfnAudioDataHandler = 0;
// now create the actual source
CUresult cuRes = cuvidCreateVideoSource(&videoSource_, fname.c_str(), &params);
if (cuRes == CUDA_ERROR_INVALID_SOURCE)
CV_Error(Error::StsUnsupportedFormat, "Unsupported video source");
cuSafeCall( cuRes );
CUVIDEOFORMAT vidfmt;
cuSafeCall( cuvidGetSourceVideoFormat(videoSource_, &vidfmt, 0) );
CV_Assert(Codec::NumCodecs == cudaVideoCodec::cudaVideoCodec_NumCodecs);
format_.codec = static_cast<Codec>(vidfmt.codec);
format_.chromaFormat = static_cast<ChromaFormat>(vidfmt.chroma_format);
format_.nBitDepthMinus8 = vidfmt.bit_depth_luma_minus8;
format_.width = vidfmt.coded_width;
format_.height = vidfmt.coded_height;
format_.displayArea = Rect(Point(vidfmt.display_area.left, vidfmt.display_area.top), Point(vidfmt.display_area.right, vidfmt.display_area.bottom));
format_.valid = true;
if (vidfmt.frame_rate.numerator != 0 && vidfmt.frame_rate.denominator != 0)
format_.fps = vidfmt.frame_rate.numerator / (double)vidfmt.frame_rate.denominator;
}
cv::cudacodec::detail::CuvidVideoSource::~CuvidVideoSource()
{
cuvidDestroyVideoSource(videoSource_);
}
FormatInfo cv::cudacodec::detail::CuvidVideoSource::format() const
{
return format_;
}
void cv::cudacodec::detail::CuvidVideoSource::updateFormat(const FormatInfo& videoFormat)
{
format_ = videoFormat;
format_.valid = true;
}
void cv::cudacodec::detail::CuvidVideoSource::start()
{
cuSafeCall( cuvidSetVideoSourceState(videoSource_, cudaVideoState_Started) );
}
void cv::cudacodec::detail::CuvidVideoSource::stop()
{
cuSafeCall( cuvidSetVideoSourceState(videoSource_, cudaVideoState_Stopped) );
}
bool cv::cudacodec::detail::CuvidVideoSource::isStarted() const
{
return (cuvidGetVideoSourceState(videoSource_) == cudaVideoState_Started);
}
bool cv::cudacodec::detail::CuvidVideoSource::hasError() const
{
return (cuvidGetVideoSourceState(videoSource_) == cudaVideoState_Error);
}
int CUDAAPI cv::cudacodec::detail::CuvidVideoSource::HandleVideoData(void* userData, CUVIDSOURCEDATAPACKET* packet)
{
CuvidVideoSource* thiz = static_cast<CuvidVideoSource*>(userData);
return thiz->parseVideoData(packet->payload, packet->payload_size, thiz->RawModeEnabled(), false, (packet->flags & CUVID_PKT_ENDOFSTREAM) != 0);
}
#endif // HAVE_NVCUVID
@@ -0,0 +1,83 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef __CUVID_VIDEO_SOURCE_HPP__
#define __CUVID_VIDEO_SOURCE_HPP__
#include "video_source.hpp"
namespace cv { namespace cudacodec { namespace detail {
class CuvidVideoSource : public VideoSource
{
public:
explicit CuvidVideoSource(const String& fname);
~CuvidVideoSource();
FormatInfo format() const CV_OVERRIDE;
void updateFormat(const FormatInfo& videoFormat) CV_OVERRIDE;
void start() CV_OVERRIDE;
void stop() CV_OVERRIDE;
bool isStarted() const CV_OVERRIDE;
bool hasError() const CV_OVERRIDE;
private:
// Callback for handling packages of demuxed video data.
//
// Parameters:
// pUserData - Pointer to user data. We must pass a pointer to a
// VideoSourceData struct here, that contains a valid CUvideoparser
// and FrameQueue.
// pPacket - video-source data packet.
//
// NOTE: called from a different thread that doesn't not have a cuda context
//
static int CUDAAPI HandleVideoData(void* pUserData, CUVIDSOURCEDATAPACKET* pPacket);
CUvideosource videoSource_;
FormatInfo format_;
};
}}}
#endif // __CUVID_VIDEO_SOURCE_HPP__
@@ -0,0 +1,196 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "precomp.hpp"
#ifdef HAVE_NVCUVID
using namespace cv;
using namespace cv::cudacodec;
using namespace cv::cudacodec::detail;
#ifndef CV_FOURCC_MACRO
#define CV_FOURCC_MACRO(c1, c2, c3, c4) (((c1) & 255) + (((c2) & 255) << 8) + (((c3) & 255) << 16) + (((c4) & 255) << 24))
#endif
static std::string fourccToString(int fourcc)
{
char str[5] = {'\0', '\0', '\0', '\0'};
for (int i = 0; i < 4; i++) {
char c = (char)(fourcc >> i*8);
str[i] = ' ' <= c && c < 128 ? c : '?';
}
return std::string(str);
}
static
Codec FourccToCodec(int codec)
{
switch (codec)
{
case CV_FOURCC_MACRO('m', 'p', 'g', '1'): return MPEG1;
case CV_FOURCC_MACRO('m', 'p', 'g', '2'): return MPEG2;
case CV_FOURCC_MACRO('F', 'M', 'P', '4'): return MPEG4;
case CV_FOURCC_MACRO('W', 'V', 'C', '1'): return VC1;
case CV_FOURCC_MACRO('h', '2', '6', '4'): return H264;
case CV_FOURCC_MACRO('h', 'e', 'v', 'c'): return HEVC;
case CV_FOURCC_MACRO('M', 'J', 'P', 'G'): return JPEG;
case CV_FOURCC_MACRO('V', 'P', '8', '0'): return VP8;
case CV_FOURCC_MACRO('V', 'P', '9', '0'): return VP9;
case CV_FOURCC_MACRO('A', 'V', '0', '1'): return AV1;
default:
break;
}
std::string msg = cv::format("Unknown codec FOURCC: 0x%08X (%s)", codec, fourccToString(codec).c_str());
CV_LOG_WARNING(NULL, msg);
CV_Error(Error::StsUnsupportedFormat, msg);
}
static
int StartCodeLen(unsigned char* data, const int sz) {
if (sz >= 3 && data[0] == 0 && data[1] == 0 && data[2] == 1)
return 3;
else if (sz >= 4 && data[0] == 0 && data[1] == 0 && data[2] == 0 && data[3] == 1)
return 4;
else
return 0;
}
bool ParamSetsExist(unsigned char* parameterSets, const int szParameterSets, unsigned char* data, const int szData) {
const int paramSetStartCodeLen = StartCodeLen(parameterSets, szParameterSets);
const int packetStartCodeLen = StartCodeLen(data, szData);
// weak test to see if the parameter set has already been included in the RTP stream
return paramSetStartCodeLen != 0 && packetStartCodeLen != 0 && parameterSets[paramSetStartCodeLen] == data[packetStartCodeLen];
}
cv::cudacodec::detail::FFmpegVideoSource::FFmpegVideoSource(const String& fname, const std::vector<int>& _videoCaptureParams, const int iMaxStartFrame)
: videoCaptureParams(_videoCaptureParams)
{
if (!videoio_registry::hasBackend(CAP_FFMPEG))
CV_Error(Error::StsNotImplemented, "FFmpeg backend not found");
videoCaptureParams.push_back(CAP_PROP_FORMAT);
videoCaptureParams.push_back(-1);
if (!cap.open(fname, CAP_FFMPEG, videoCaptureParams))
CV_Error(Error::StsUnsupportedFormat, "Unsupported video source");
CV_Assert(cap.get(CAP_PROP_FORMAT) == -1);
if (iMaxStartFrame) {
CV_Assert(cap.set(CAP_PROP_POS_FRAMES, iMaxStartFrame));
firstFrameIdx = static_cast<int>(cap.get(CAP_PROP_POS_FRAMES));
}
const int codecExtradataIndex = static_cast<int>(cap.get(CAP_PROP_CODEC_EXTRADATA_INDEX));
Mat tmpExtraData;
if (cap.retrieve(tmpExtraData, codecExtradataIndex) && tmpExtraData.total())
extraData = tmpExtraData.clone();
int codec = (int)cap.get(CAP_PROP_FOURCC);
format_.codec = FourccToCodec(codec);
format_.height = cap.get(CAP_PROP_FRAME_HEIGHT);
format_.width = cap.get(CAP_PROP_FRAME_WIDTH);
format_.displayArea = Rect(0, 0, format_.width, format_.height);
format_.valid = false;
format_.fps = cap.get(CAP_PROP_FPS);
}
cv::cudacodec::detail::FFmpegVideoSource::~FFmpegVideoSource()
{
if (cap.isOpened())
cap.release();
}
FormatInfo cv::cudacodec::detail::FFmpegVideoSource::format() const
{
return format_;
}
void cv::cudacodec::detail::FFmpegVideoSource::updateFormat(const FormatInfo& videoFormat)
{
format_ = videoFormat;
format_.valid = true;
}
bool cv::cudacodec::detail::FFmpegVideoSource::get(const int propertyId, double& propertyVal) const
{
propertyVal = cap.get(propertyId);
if (propertyVal != CAP_PROP_UNKNOWN)
return true;
CV_Assert(videoCaptureParams.size() % 2 == 0);
for (std::size_t i = 0; i < videoCaptureParams.size(); i += 2) {
if (videoCaptureParams.at(i) == propertyId) {
propertyVal = videoCaptureParams.at(i + 1);
return true;
}
}
return false;
}
bool cv::cudacodec::detail::FFmpegVideoSource::getNextPacket(unsigned char** data, size_t* size)
{
cap >> rawFrame;
*data = rawFrame.data;
*size = rawFrame.total();
if (iFrame++ == 0 && extraData.total()) {
if (format_.codec == Codec::MPEG4 ||
((format_.codec == Codec::H264 || format_.codec == Codec::HEVC) && !ParamSetsExist(extraData.data, extraData.total(), *data, *size)))
{
const size_t nBytesToTrimFromData = format_.codec == Codec::MPEG4 ? 3 : 0;
const size_t newSz = extraData.total() + *size - nBytesToTrimFromData;
dataWithHeader = Mat(1, newSz, CV_8UC1);
memcpy(dataWithHeader.data, extraData.data, extraData.total());
memcpy(dataWithHeader.data + extraData.total(), (*data) + nBytesToTrimFromData, *size - nBytesToTrimFromData);
*data = dataWithHeader.data;
*size = newSz;
}
}
return *size != 0;
}
bool cv::cudacodec::detail::FFmpegVideoSource::lastPacketContainsKeyFrame() const
{
return cap.get(CAP_PROP_LRF_HAS_KEY_FRAME);
}
#endif // HAVE_CUDA
@@ -0,0 +1,82 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef __FFMPEG_VIDEO_SOURCE_HPP__
#define __FFMPEG_VIDEO_SOURCE_HPP__
#include "opencv2/cudacodec.hpp"
namespace cv { namespace cudacodec { namespace detail {
class FFmpegVideoSource : public RawVideoSource
{
public:
FFmpegVideoSource(const String& fname, const std::vector<int>& params, const int iMaxStartFrame);
~FFmpegVideoSource();
bool getNextPacket(unsigned char** data, size_t* size) CV_OVERRIDE;
bool lastPacketContainsKeyFrame() const;
FormatInfo format() const CV_OVERRIDE;
void updateFormat(const FormatInfo& videoFormat) CV_OVERRIDE;
void getExtraData(cv::Mat& _extraData) const CV_OVERRIDE { _extraData = extraData; }
bool get(const int propertyId, double& propertyVal) const;
int getFirstFrameIdx() const { return firstFrameIdx; }
private:
FormatInfo format_;
VideoCapture cap;
Mat rawFrame, extraData, dataWithHeader;
int iFrame = 0;
std::vector<int> videoCaptureParams;
int firstFrameIdx = 0;
};
}}}
#endif // __FFMPEG_VIDEO_SOURCE_HPP__
+174
View File
@@ -0,0 +1,174 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "precomp.hpp"
#ifdef HAVE_NVCUVID
RawPacket::RawPacket(const unsigned char* data_, const size_t size, const bool containsKeyFrame_) :
data(data_,data_ + size), containsKeyFrame(containsKeyFrame_) {};
cv::cudacodec::detail::FrameQueue::~FrameQueue() {
if (isFrameInUse_)
delete[] isFrameInUse_;
}
void cv::cudacodec::detail::FrameQueue::init(const int _maxSz) {
AutoLock autoLock(mtx_);
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))
{
if (allowFrameDrop && dequeueUntil(pictureIndex))
break;
// Decoder is getting too far ahead from display
Thread::sleep(1);
if (isEndOfDecode())
return false;
}
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
// for display
isFrameInUse_[picParams->picture_index] = true;
// Wait until we have a free entry in the display queue (should never block if we have enough entries)
do
{
bool isFramePlaced = false;
{
AutoLock autoLock(mtx_);
if (framesInQueue_ < maxSz)
{
const int writePosition = (readPosition_ + framesInQueue_) % maxSz;
displayQueue_.at(writePosition) = *picParams;
for (const auto& rawPacket : rawPackets)
rawPacketQueue.push(rawPacket);
framesInQueue_++;
isFramePlaced = true;
}
}
if (isFramePlaced) // Done
break;
// Wait a bit
Thread::sleep(1);
} while (!isEndOfDecode());
}
bool cv::cudacodec::detail::FrameQueue::dequeueUntil(const int pictureIndex) {
AutoLock autoLock(mtx_);
if (isFrameInUse_[pictureIndex] != 1)
return false;
for (int i = 0; i < framesInQueue_; i++) {
const bool found = displayQueue_.at(readPosition_).picture_index == pictureIndex;
isFrameInUse_[displayQueue_.at(readPosition_).picture_index] = 0;
framesInQueue_--;
readPosition_ = (readPosition_ + 1) % maxSz;
if (found) return true;
}
return false;
}
bool cv::cudacodec::detail::FrameQueue::dequeue(CUVIDPARSERDISPINFO& displayInfo, std::vector<RawPacket>& rawPackets)
{
AutoLock autoLock(mtx_);
if (framesInQueue_ > 0)
{
int entry = readPosition_;
displayInfo = displayQueue_.at(entry);
while (!rawPacketQueue.empty()) {
rawPackets.push_back(rawPacketQueue.front());
rawPacketQueue.pop();
}
readPosition_ = (entry + 1) % maxSz;
framesInQueue_--;
isFrameInUse_[displayInfo.picture_index] = 2;
return true;
}
return false;
}
#endif // HAVE_NVCUVID
+124
View File
@@ -0,0 +1,124 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef __FRAME_QUEUE_HPP__
#define __FRAME_QUEUE_HPP__
#include <queue>
#include "opencv2/core/utility.hpp"
class RawPacket {
public:
RawPacket(const unsigned char* _data, const size_t _size = 0, const bool _containsKeyFrame = false);
const unsigned char* Data() const noexcept { return data.data(); }
size_t Size() const noexcept { return data.size(); }
bool ContainsKeyFrame() const noexcept { return containsKeyFrame; }
private:
std::vector<unsigned char> data;
bool containsKeyFrame = false;
};
namespace cv { namespace cudacodec { namespace detail {
class FrameQueue
{
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;}
// Spins until frame becomes available or decoding gets canceled.
// If the requested frame is available the method returns true.
// If decoding was interrupted before the requested frame becomes
// available, the method returns false.
// If allowFrameDrop == true, spin is disabled and n > 0 frames are discarded
// 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.
// Parameters:
// displayInfo - New frame info gets placed into this object.
// Returns:
// true, if a new frame was returned,
// false, if the queue was empty and no new frame could be returned.
bool dequeue(CUVIDPARSERDISPINFO& displayInfo, std::vector<RawPacket>& rawPackets);
// Deque all frames up to and including the frame with index pictureIndex - must only
// be called in the same thread as enqueue.
// Parameters:
// pictureIndex - Display index of the frame.
// Returns:
// true, if successful,
// false, if no frames are dequed.
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; }
Mutex mtx_;
volatile int* isFrameInUse_ = 0;
volatile int endOfDecode_ = 0;
int framesInQueue_ = 0;
int readPosition_ = 0;
std::vector< CUVIDPARSERDISPINFO> displayQueue_;
int maxSz = 0;
std::queue<RawPacket> rawPacketQueue;
};
}}}
#endif // __FRAME_QUEUE_HPP__
@@ -0,0 +1,354 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#include "precomp.hpp"
using namespace cv;
using namespace cv::cuda;
using namespace cv::cudacodec;
#if !defined (HAVE_CUDA)
Ptr<NVSurfaceToColorConverter> cv::cudacodec::createNVSurfaceToColorConverter(const ColorSpaceStandard, const bool){ throw_no_cuda(); }
#else
#include "cuda/ColorSpace.h"
namespace cv { namespace cuda { namespace device {
template<class BGR24> void Nv12ToColor24(uint8_t* dpNv12, int nNv12Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class RGB24> void Nv12ToColor24(uint8_t* dpNv12, int nNv12Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class BGRA32> void Nv12ToColor32(uint8_t* dpNv12, int nNv12Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class RGBA32> void Nv12ToColor32(uint8_t* dpNv12, int nNv12Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class BGR48> void Nv12ToColor48(uint8_t* dpNv12, int nNv12Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class RGB48> void Nv12ToColor48(uint8_t* dpNv12, int nNv12Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class BGRA64> void Nv12ToColor64(uint8_t* dpNv12, int nNv12Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class RGBA64> void Nv12ToColor64(uint8_t* dpNv12, int nNv12Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class BGR24> void Nv12ToColorPlanar24(uint8_t* dpNv12, int nNv12Pitch, uint8_t* dpBgrp, int nBgrpPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class RGB24> void Nv12ToColorPlanar24(uint8_t* dpNv12, int nNv12Pitch, uint8_t* dpBgrp, int nBgrpPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class BGRA32> void Nv12ToColorPlanar32(uint8_t* dpNv12, int nNv12Pitch, uint8_t* dpBgrp, int nBgrpPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class RGBA32> void Nv12ToColorPlanar32(uint8_t* dpNv12, int nNv12Pitch, uint8_t* dpBgrp, int nBgrpPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class BGR48> void Nv12ToColorPlanar48(uint8_t* dpNv12, int nNv12Pitch, uint8_t* dpBgrp, int nBgrpPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class RGB48> void Nv12ToColorPlanar48(uint8_t* dpNv12, int nNv12Pitch, uint8_t* dpBgrp, int nBgrpPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class BGRA64> void Nv12ToColorPlanar64(uint8_t* dpNv12, int nNv12Pitch, uint8_t* dpBgrp, int nBgrpPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class RGBA64> void Nv12ToColorPlanar64(uint8_t* dpNv12, int nNv12Pitch, uint8_t* dpBgrp, int nBgrpPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class BGR24> void P016ToColor24(uint8_t* dpP016, int nP016Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class RGB24> void P016ToColor24(uint8_t* dpP016, int nP016Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class BGRA32> void P016ToColor32(uint8_t* dpP016, int nP016Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class RGBA32> void P016ToColor32(uint8_t* dpP016, int nP016Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class BGR48> void P016ToColor48(uint8_t* dpP016, int nP016Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class RGB48> void P016ToColor48(uint8_t* dpP016, int nP016Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class BGRA64> void P016ToColor64(uint8_t* dpP016, int nP016Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class RGBA64> void P016ToColor64(uint8_t* dpP016, int nP016Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class BGR24> void P016ToColorPlanar24(uint8_t* dpP016, int nP016Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class RGB24> void P016ToColorPlanar24(uint8_t* dpP016, int nP016Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class BGRA32> void P016ToColorPlanar32(uint8_t* dpP016, int nP016Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class RGBA32> void P016ToColorPlanar32(uint8_t* dpP016, int nP016Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag);
template<class BGR48> void P016ToColorPlanar48(uint8_t* dpP016, int nP016Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class RGB48> void P016ToColorPlanar48(uint8_t* dpP016, int nP016Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class BGRA64> void P016ToColorPlanar64(uint8_t* dpP016, int nP016Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class RGBA64> void P016ToColorPlanar64(uint8_t* dpP016, int nP016Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class BGR24> void YUV444ToColor24(uint8_t* dpYuv444, int nYuv444Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class RGB24> void YUV444ToColor24(uint8_t* dpYuv444, int nYuv444Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class BGRA32> void YUV444ToColor32(uint8_t* dpYuv444, int nYuv444Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class RGBA32> void YUV444ToColor32(uint8_t* dpYuv444, int nYuv444Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class BGR48> void YUV444ToColor48(uint8_t* dpYuv444, int nYuv444Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class RGB48> void YUV444ToColor48(uint8_t* dpYuv444, int nYuv444Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class BGRA64> void YUV444ToColor64(uint8_t* dpYuv444, int nYuv444Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class RGBA64> void YUV444ToColor64(uint8_t* dpYuv444, int nYuv444Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class BGR24> void YUV444ToColorPlanar24(uint8_t* dpYuv444, int nYuv444Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class RGB24> void YUV444ToColorPlanar24(uint8_t* dpYuv444, int nYuv444Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class BGRA32> void YUV444ToColorPlanar32(uint8_t* dpYuv444, int nYuv444Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class RGBA32> void YUV444ToColorPlanar32(uint8_t* dpYuv444, int nYuv444Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class BGR48> void YUV444ToColorPlanar48(uint8_t* dpYuv444, int nYuv444Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class RGB48> void YUV444ToColorPlanar48(uint8_t* dpYuv444, int nYuv444Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class BGRA64> void YUV444ToColorPlanar64(uint8_t* dpYuv444, int nYuv444Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class RGBA64> void YUV444ToColorPlanar64(uint8_t* dpYuv444, int nYuv444Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class BGR24> void YUV444P16ToColor24(uint8_t* dpYuv444, int nYuv444Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class RGB24> void YUV444P16ToColor24(uint8_t* dpYuv444, int nYuv444Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class BGRA32> void YUV444P16ToColor32(uint8_t* dpYuv444, int nYuv444Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class RGBA32> void YUV444P16ToColor32(uint8_t* dpYuv444, int nYuv444Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class BGR48> void YUV444P16ToColor48(uint8_t* dpYuv444, int nYuv444Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class RGB48> void YUV444P16ToColor48(uint8_t* dpYuv444, int nYuv444Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class BGRA64> void YUV444P16ToColor64(uint8_t* dpYuv444, int nYuv444Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class RGBA64> void YUV444P16ToColor64(uint8_t* dpYuv444, int nYuv444Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class BGR24> void YUV444P16ToColorPlanar24(uint8_t* dpYuv444, int nYuv444Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class RGB24> void YUV444P16ToColorPlanar24(uint8_t* dpYuv444, int nYuv444Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class BGRA32> void YUV444P16ToColorPlanar32(uint8_t* dpYuv444, int nYuv444Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class RGBA32> void YUV444P16ToColorPlanar32(uint8_t* dpYuv444, int nYuv444Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class BGR48> void YUV444P16ToColorPlanar48(uint8_t* dpYuv444, int nYuv444Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class RGB48> void YUV444P16ToColorPlanar48(uint8_t* dpYuv444, int nYuv444Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class BGRA64> void YUV444P16ToColorPlanar64(uint8_t* dpYuv444, int nYuv444Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
template<class RGBA64> void YUV444P16ToColorPlanar64(uint8_t* dpYuv444, int nYuv444Pitch, uint8_t* dpColor, int nColorPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
void Y8ToGray8(uint8_t* dpY8, int nY8Pitch, uint8_t* dpGray, int nGrayPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
void Y8ToGray16(uint8_t* dpY8, int nY8Pitch, uint8_t* dpGray, int nGrayPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
void Y16ToGray8(uint8_t* dpY16, int nY16Pitch, uint8_t* dpGray, int nGrayPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
void Y16ToGray16(uint8_t* dpY16, int nY16Pitch, uint8_t* dpGray, int nGrayPitch, int nWidth, int nHeight, ColorMatrix matYuv2Color, bool videoFullRangeFlag, const cudaStream_t stream);
}}}
using namespace cuda::device;
namespace {
void GetConstants(int iMatrix, float& wr, float& wb, int& black, int& white, int& uvWhite, int& max, bool fullRange = false) {
if (fullRange) {
black = 0; white = 255; uvWhite = 255;
}
else {
black = 16; white = 235; uvWhite = 240;
}
max = 255;
switch (static_cast<cv::cudacodec::ColorSpaceStandard>(iMatrix))
{
case cv::cudacodec::ColorSpaceStandard::BT709:
default:
wr = 0.2126f; wb = 0.0722f;
break;
case cv::cudacodec::ColorSpaceStandard::FCC:
wr = 0.30f; wb = 0.11f;
break;
case cv::cudacodec::ColorSpaceStandard::BT470:
case cv::cudacodec::ColorSpaceStandard::BT601:
wr = 0.2990f; wb = 0.1140f;
break;
case cv::cudacodec::ColorSpaceStandard::SMPTE240M:
wr = 0.212f; wb = 0.087f;
break;
case cv::cudacodec::ColorSpaceStandard::BT2020:
case cv::cudacodec::ColorSpaceStandard::BT2020C:
wr = 0.2627f; wb = 0.0593f;
// 10-bit only
black <<= 8;
white <<= 8;
uvWhite <<= 8;
max = (1 << 16) - 1;
break;
}
}
void SetMatYuv2Rgb(int iMatrix, ColorMatrix& matYuv2Color, bool fullRange = false) {
float wr, wb;
int black, white, max, uvWhite;
GetConstants(iMatrix, wr, wb, black, white, uvWhite, max, fullRange);
float mat[3][3] = {
1.0f, 0.0f, (1.0f - wr) / 0.5f,
1.0f, -wb * (1.0f - wb) / 0.5f / (1 - wb - wr), -wr * (1 - wr) / 0.5f / (1 - wb - wr),
1.0f, (1.0f - wb) / 0.5f, 0.0f,
};
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (j == 0)
matYuv2Color.m[i][j] = (float)(1.0 * max / (white - black) * mat[i][j]);
else
matYuv2Color.m[i][j] = (float)(1.0 * max / (uvWhite - black) * mat[i][j]);
}
}
}
}
class NVSurfaceToColorConverterImpl : public NVSurfaceToColorConverter {
public:
NVSurfaceToColorConverterImpl(ColorSpaceStandard colorSpace, bool fullColorRange = false) :
videoFullRangeFlag(fullColorRange)
{
SetMatYuv2Rgb(static_cast<int>(colorSpace), matYuv2Color, fullColorRange);
}
int OutputColorFormatIdx(const cudacodec::ColorFormat format) {
switch (format) {
case cudacodec::ColorFormat::BGR: return 0;
case cudacodec::ColorFormat::RGB: return 1;
case cudacodec::ColorFormat::BGRA: return 2;
case cudacodec::ColorFormat::RGBA: return 3;
case cudacodec::ColorFormat::GRAY: return 4;
default: return -1;
}
}
int NumChannels(const cudacodec::ColorFormat format) {
switch (format) {
case cudacodec::ColorFormat::BGR:
case cudacodec::ColorFormat::RGB: return 3;
case cudacodec::ColorFormat::BGRA:
case cudacodec::ColorFormat::RGBA: return 4;
case cudacodec::ColorFormat::GRAY: return 1;
default: return -1;
}
}
BitDepth GetBitDepthOut(const BitDepth bitDepth, const int nBitsIn) {
switch (bitDepth) {
case BitDepth::EIGHT:
case BitDepth::SIXTEEN:
return bitDepth;
case BitDepth::UNCHANGED:
default:
if (nBitsIn == CV_8U)
return BitDepth::EIGHT;
else
return BitDepth::SIXTEEN;
}
}
bool convert(const InputArray yuv, const OutputArray out, const SurfaceFormat surfaceFormat, const ColorFormat outputFormat, const BitDepth bitDepth, const bool planar, cuda::Stream& stream) {
CV_Assert(outputFormat == ColorFormat::BGR || outputFormat == ColorFormat::BGRA || outputFormat == ColorFormat::RGB || outputFormat == ColorFormat::RGBA || outputFormat == ColorFormat::GRAY);
CV_Assert(yuv.depth() == CV_8U || yuv.depth() == CV_16U);
const bool yuv420 = surfaceFormat == SurfaceFormat::SF_NV12 || surfaceFormat == SurfaceFormat::SF_P016;
CV_Assert(yuv.cols() % 2 == 0);
using func_t = void (*)(uint8_t* yuv, int yuvPitch, uint8_t* color, int colorPitch, int width, int height, ColorMatrix matYuv2Color, bool videoFullRangeFlag, cudaStream_t stream);
static const func_t funcsNV12[5][2][2] =
{
{
{ Nv12ToColor24<BGR24>, Nv12ToColorPlanar24<BGR24> },
{ Nv12ToColor48<BGR48>, Nv12ToColorPlanar48<BGR48> }
},
{
{ Nv12ToColor24<RGB24>, Nv12ToColorPlanar24<RGB24> },
{ Nv12ToColor48<RGB48>, Nv12ToColorPlanar48<RGB48> }
},
{
{ Nv12ToColor32<BGRA32>, Nv12ToColorPlanar32<BGRA32> },
{ Nv12ToColor64<BGRA64>, Nv12ToColorPlanar64<BGRA64> }
},
{
{ Nv12ToColor32<RGBA32>, Nv12ToColorPlanar32<RGBA32> },
{ Nv12ToColor64<RGBA64>, Nv12ToColorPlanar64<RGBA64> }
},
{
{ Y8ToGray8, Y8ToGray8 },
{ Y8ToGray16, Y8ToGray16 }
}
};
static const func_t funcsP016[5][2][2] =
{
{
{ P016ToColor24<BGR24>, P016ToColorPlanar24<BGR24> },
{ P016ToColor48<BGR48>, P016ToColorPlanar48<BGR48> }
},
{
{ P016ToColor24<RGB24>, P016ToColorPlanar24<RGB24> },
{ P016ToColor48<RGB48>, P016ToColorPlanar48<RGB48> }
},
{
{ P016ToColor32<BGRA32>, P016ToColorPlanar32<BGRA32> },
{ P016ToColor64<BGRA64>, P016ToColorPlanar64<BGRA64> }
},
{
{ P016ToColor32<RGBA32>, P016ToColorPlanar32<RGBA32> },
{ P016ToColor64<RGBA64>, P016ToColorPlanar64<RGBA64> }
},
{
{ Y16ToGray8, Y16ToGray8 },
{ Y16ToGray16, Y16ToGray16 }
}
};
static const func_t funcsYUV444[5][2][2] =
{
{
{ YUV444ToColor24<BGR24>, YUV444ToColorPlanar24<BGR24> },
{ YUV444ToColor48<BGR48>, YUV444ToColorPlanar48<BGR48> }
},
{
{ YUV444ToColor24<RGB24>, YUV444ToColorPlanar24<RGB24> },
{ YUV444ToColor48<RGB48>, YUV444ToColorPlanar48<RGB48> }
},
{
{ YUV444ToColor32<BGRA32>, YUV444ToColorPlanar32<BGRA32> },
{ YUV444ToColor64<BGRA64>, YUV444ToColorPlanar64<BGRA64> }
},
{
{ YUV444ToColor32<RGBA32>, YUV444ToColorPlanar32<RGBA32> },
{ YUV444ToColor64<RGBA64>, YUV444ToColorPlanar64<RGBA64> }
},
{
{ Y8ToGray8, Y8ToGray8 },
{ Y8ToGray16, Y8ToGray16 }
}
};
static const func_t funcsYUV444P16[5][2][2] =
{
{
{ YUV444P16ToColor24<BGR24>, YUV444P16ToColorPlanar24<BGR24> },
{ YUV444P16ToColor48<BGR48>, YUV444P16ToColorPlanar48<BGR48> }
},
{
{ YUV444P16ToColor24<RGB24>, YUV444P16ToColorPlanar24<RGB24> },
{ YUV444P16ToColor48<RGB48>, YUV444P16ToColorPlanar48<RGB48> }
},
{
{ YUV444P16ToColor32<BGRA32>, YUV444P16ToColorPlanar32<BGRA32> },
{ YUV444P16ToColor64<BGRA64>, YUV444P16ToColorPlanar64<BGRA64> }
},
{
{ YUV444P16ToColor32<RGBA32>, YUV444P16ToColorPlanar32<RGBA32> },
{ YUV444P16ToColor64<RGBA64>, YUV444P16ToColorPlanar64<RGBA64> }
},
{
{ Y16ToGray8, Y16ToGray8 },
{ Y16ToGray16, Y16ToGray16 }
}
};
GpuMat yuv_ = getInputMat(yuv, stream);
CV_Assert(yuv_.step <= static_cast<size_t>(std::numeric_limits<int>::max()));
const int nRows = static_cast<int>(yuv.rows() / (yuv420 ? 1.5f : 3.0f));
CV_Assert(!yuv420 || nRows % 2 == 0);
const int nChannels = NumChannels(outputFormat);
const int nRowsOut = nRows * (planar ? nChannels : 1);
const BitDepth bitDepth_ = GetBitDepthOut(bitDepth, yuv.depth());
const int iBitDepth = bitDepth_ == BitDepth::EIGHT ? 0 : 1;
const int typeOut = CV_MAKE_TYPE(bitDepth_ == BitDepth::EIGHT ? CV_8U : CV_16U, planar ? 1 : nChannels);
GpuMat out_ = getOutputMat(out, nRowsOut, yuv.cols(), typeOut, stream);
const int iSurfaceFormat = static_cast<int>(surfaceFormat);
const int iPlanar = planar ? 1 : 0;
const int iOutputFormat = OutputColorFormatIdx(outputFormat);
func_t func = nullptr;
switch (iSurfaceFormat)
{
case 0:
func = funcsNV12[iOutputFormat][iBitDepth][iPlanar];
break;
case 1:
func = funcsP016[iOutputFormat][iBitDepth][iPlanar];
break;
case 2:
func = funcsYUV444[iOutputFormat][iBitDepth][iPlanar];
break;
case 3:
func = funcsYUV444P16[iOutputFormat][iBitDepth][iPlanar];
break;
}
if (!func)
CV_Error(Error::StsUnsupportedFormat, "Unsupported combination of source and destination types");
CV_Assert(out_.step <= static_cast<size_t>(std::numeric_limits<int>::max()));
func((uint8_t*)yuv_.ptr(0), static_cast<int>(yuv_.step), (uint8_t*)out_.ptr(0), static_cast<int>(out_.step), out_.cols, nRows, matYuv2Color, videoFullRangeFlag, StreamAccessor::getStream(stream));
return true;
}
private:
ColorMatrix matYuv2Color;
bool videoFullRangeFlag;
};
Ptr<NVSurfaceToColorConverter> cv::cudacodec::createNVSurfaceToColorConverter(const ColorSpaceStandard colorSpace, const bool videoFullRangeFlag) {
return makePtr<NVSurfaceToColorConverterImpl>(colorSpace, videoFullRangeFlag);
}
#endif
+94
View File
@@ -0,0 +1,94 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef OPENCV_PRECOMP_H
#define OPENCV_PRECOMP_H
#include <cstdlib>
#include <cstring>
#include <deque>
#include <utility>
#include <stdexcept>
#include <iostream>
#include "opencv2/cudacodec.hpp"
#include "opencv2/videoio.hpp"
#include "opencv2/videoio/registry.hpp"
#include "opencv2/core/private.cuda.hpp"
#include <opencv2/core/utils/logger.hpp>
#if defined(HAVE_NVCUVID) || defined(HAVE_NVCUVENC)
#if _WIN32
#define NOMINMAX
#endif
#if defined(HAVE_NVCUVID)
#if defined(HAVE_DYNLINK_NVCUVID_HEADER)
#include <dynlink_nvcuvid.h>
#elif defined(HAVE_NVCUVID_HEADER)
#include <nvcuvid.h>
#endif
#ifdef _WIN32
#include <windows.h>
#else
#include <pthread.h>
#include <unistd.h>
#endif
#include "thread.hpp"
#include "video_source.hpp"
#include "ffmpeg_video_source.hpp"
#include "cuvid_video_source.hpp"
#include "frame_queue.hpp"
#include "video_decoder.hpp"
#include "video_parser.hpp"
#endif
#if defined(HAVE_NVCUVENC)
#include <fstream>
#include <nvEncodeAPI.h>
#include "NvEncoderCuda.h"
#include <opencv2/cudaimgproc.hpp>
#endif
#endif
#endif /* OPENCV_PRECOMP_H */
+170
View File
@@ -0,0 +1,170 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "precomp.hpp"
#ifdef HAVE_NVCUVID
using namespace cv::cudacodec::detail;
#ifdef _WIN32
namespace
{
struct UserData
{
Thread::Func func;
void* param;
};
DWORD WINAPI WinThreadFunction(LPVOID lpParam)
{
UserData* userData = static_cast<UserData*>(lpParam);
userData->func(userData->param);
return 0;
}
}
class cv::cudacodec::detail::Thread::Impl
{
public:
Impl(Thread::Func func, void* userData)
{
userData_.func = func;
userData_.param = userData;
thread_ = CreateThread(
NULL, // default security attributes
0, // use default stack size
WinThreadFunction, // thread function name
&userData_, // argument to thread function
0, // use default creation flags
&threadId_); // returns the thread identifier
}
~Impl()
{
CloseHandle(thread_);
}
void wait()
{
WaitForSingleObject(thread_, INFINITE);
}
private:
UserData userData_;
HANDLE thread_;
DWORD threadId_;
};
#else
namespace
{
struct UserData
{
Thread::Func func;
void* param;
};
void* PThreadFunction(void* lpParam)
{
UserData* userData = static_cast<UserData*>(lpParam);
userData->func(userData->param);
return 0;
}
}
class cv::cudacodec::detail::Thread::Impl
{
public:
Impl(Thread::Func func, void* userData)
{
userData_.func = func;
userData_.param = userData;
pthread_create(&thread_, NULL, PThreadFunction, &userData_);
}
~Impl()
{
pthread_detach(thread_);
}
void wait()
{
pthread_join(thread_, NULL);
}
private:
pthread_t thread_;
UserData userData_;
};
#endif
cv::cudacodec::detail::Thread::Thread(Func func, void* userData) :
impl_(new Impl(func, userData))
{
}
void cv::cudacodec::detail::Thread::wait()
{
impl_->wait();
}
void cv::cudacodec::detail::Thread::sleep(int ms)
{
#ifdef _WIN32
::Sleep(ms);
#else
::usleep(ms * 1000);
#endif
}
#endif // HAVE_NVCUVID
+70
View File
@@ -0,0 +1,70 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef __THREAD_WRAPPERS_HPP__
#define __THREAD_WRAPPERS_HPP__
#include "opencv2/core.hpp"
namespace cv { namespace cudacodec { namespace detail {
class Thread
{
public:
typedef void (*Func)(void* userData);
explicit Thread(Func func, void* userData = 0);
void wait();
static void sleep(int ms);
class Impl;
private:
cv::Ptr<Impl> impl_;
};
}}}
#endif // __THREAD_WRAPPERS_HPP__
+322
View File
@@ -0,0 +1,322 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "precomp.hpp"
#ifdef HAVE_NVCUVID
#if (CUDART_VERSION >= 9000)
static const char* GetVideoCodecString(cudaVideoCodec eCodec) {
static struct {
cudaVideoCodec eCodec;
const char* name;
} aCodecName[] = {
{ cudaVideoCodec_MPEG1, "MPEG-1" },
{ cudaVideoCodec_MPEG2, "MPEG-2" },
{ cudaVideoCodec_MPEG4, "MPEG-4 (ASP)" },
{ cudaVideoCodec_VC1, "VC-1/WMV" },
{ cudaVideoCodec_H264, "AVC/H.264" },
{ cudaVideoCodec_JPEG, "M-JPEG" },
{ cudaVideoCodec_H264_SVC, "H.264/SVC" },
{ cudaVideoCodec_H264_MVC, "H.264/MVC" },
{ cudaVideoCodec_HEVC, "H.265/HEVC" },
{ cudaVideoCodec_VP8, "VP8" },
{ cudaVideoCodec_VP9, "VP9" },
{ cudaVideoCodec_AV1, "AV1" },
{ cudaVideoCodec_NumCodecs, "Invalid" },
{ cudaVideoCodec_YUV420, "YUV 4:2:0" },
{ cudaVideoCodec_YV12, "YV12 4:2:0" },
{ cudaVideoCodec_NV12, "NV12 4:2:0" },
{ cudaVideoCodec_YUYV, "YUYV 4:2:2" },
{ cudaVideoCodec_UYVY, "UYVY 4:2:2" },
};
if (eCodec >= 0 && eCodec <= cudaVideoCodec_NumCodecs) {
return aCodecName[eCodec].name;
}
for (int i = cudaVideoCodec_NumCodecs + 1; i < sizeof(aCodecName) / sizeof(aCodecName[0]); i++) {
if (eCodec == aCodecName[i].eCodec) {
return aCodecName[eCodec].name;
}
}
return "Unknown";
}
#endif
static const char* GetVideoChromaFormatString(cudaVideoChromaFormat eChromaFormat) {
static struct {
cudaVideoChromaFormat eChromaFormat;
const char* name;
} aChromaFormatName[] = {
{ cudaVideoChromaFormat_Monochrome, "YUV 400 (Monochrome)" },
{ cudaVideoChromaFormat_420, "YUV 420" },
{ cudaVideoChromaFormat_422, "YUV 422" },
{ cudaVideoChromaFormat_444, "YUV 444" },
};
if (eChromaFormat >= 0 && eChromaFormat < sizeof(aChromaFormatName) / sizeof(aChromaFormatName[0])) {
return aChromaFormatName[eChromaFormat].name;
}
return "Unknown";
}
void cv::cudacodec::detail::VideoDecoder::create(const FormatInfo& videoFormat)
{
{
AutoLock autoLock(mtx_);
videoFormat_ = videoFormat;
}
const cudaVideoCodec _codec = static_cast<cudaVideoCodec>(videoFormat_.codec);
const cudaVideoChromaFormat _chromaFormat = static_cast<cudaVideoChromaFormat>(videoFormat_.chromaFormat);
cudaVideoSurfaceFormat surfaceFormat = cudaVideoSurfaceFormat_NV12;
#if (CUDART_VERSION < 9000)
if (videoFormat.nBitDepthMinus8 > 0) {
std::ostringstream warning;
warning << "NV12 (8 bit luma, 4 bit chroma) is currently the only supported decoder output format. Video input is " << videoFormat.nBitDepthMinus8 + 8 << " bit " \
<< std::string(GetVideoChromaFormatString(_chromaFormat)) << ". Truncating luma to 8 bits";
if (videoFormat.chromaFormat != YUV420)
warning << " and chroma to 4 bits";
CV_LOG_WARNING(NULL, warning.str());
}
#else
if (_chromaFormat == cudaVideoChromaFormat_420 || cudaVideoChromaFormat_Monochrome)
surfaceFormat = videoFormat_.nBitDepthMinus8 ? cudaVideoSurfaceFormat_P016 : cudaVideoSurfaceFormat_NV12;
else if (_chromaFormat == cudaVideoChromaFormat_444)
surfaceFormat = videoFormat_.nBitDepthMinus8 ? cudaVideoSurfaceFormat_YUV444_16Bit : cudaVideoSurfaceFormat_YUV444;
else if (_chromaFormat == cudaVideoChromaFormat_422) {
surfaceFormat = videoFormat_.nBitDepthMinus8 ? cudaVideoSurfaceFormat_P016 : cudaVideoSurfaceFormat_NV12;
CV_LOG_WARNING(NULL, "YUV 4:2:2 is not currently supported, falling back to YUV 4:2:0.");
}
#endif
const cudaVideoCreateFlags videoCreateFlags = (_codec == cudaVideoCodec_JPEG || _codec == cudaVideoCodec_MPEG2) ?
cudaVideoCreate_PreferCUDA :
cudaVideoCreate_PreferCUVID;
// Validate video format. These are the currently supported formats via NVCUVID
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 (CUDART_VERSION >= 6050)
codecSupported |= cudaVideoCodec_HEVC == _codec;
#endif
#if (CUDART_VERSION >= 7050)
codecSupported |= cudaVideoCodec_YUV420 == _codec;
#endif
#if ((CUDART_VERSION == 7050) || (CUDART_VERSION >= 9000))
codecSupported |= cudaVideoCodec_VP8 == _codec || cudaVideoCodec_VP9 == _codec;
#endif
#if (CUDART_VERSION >= 9000)
codecSupported |= cudaVideoCodec_AV1;
#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
CUVIDDECODECAPS decodeCaps = {};
decodeCaps.eCodecType = _codec;
decodeCaps.eChromaFormat = _chromaFormat;
decodeCaps.nBitDepthMinus8 = videoFormat.nBitDepthMinus8;
cuSafeCall(cuCtxPushCurrent(ctx_));
cuSafeCall(cuvidGetDecoderCaps(&decodeCaps));
cuSafeCall(cuCtxPopCurrent(NULL));
if (!decodeCaps.bIsSupported) {
CV_Error(Error::StsUnsupportedFormat, std::to_string(decodeCaps.nBitDepthMinus8 + 8) + " bit " + GetVideoCodecString(_codec) + " with " + GetVideoChromaFormatString(_chromaFormat) + " chroma format is not supported by this GPU hardware video decoder. Please refer to Nvidia's GPU Support Matrix to confirm your GPU supports hardware decoding of this video source.");
}
if (!(decodeCaps.nOutputFormatMask & (1 << surfaceFormat)))
{
if (decodeCaps.nOutputFormatMask & (1 << cudaVideoSurfaceFormat_NV12))
surfaceFormat = cudaVideoSurfaceFormat_NV12;
else if (decodeCaps.nOutputFormatMask & (1 << cudaVideoSurfaceFormat_P016))
surfaceFormat = cudaVideoSurfaceFormat_P016;
else if (decodeCaps.nOutputFormatMask & (1 << cudaVideoSurfaceFormat_YUV444))
surfaceFormat = cudaVideoSurfaceFormat_YUV444;
else if (decodeCaps.nOutputFormatMask & (1 << cudaVideoSurfaceFormat_YUV444_16Bit))
surfaceFormat = cudaVideoSurfaceFormat_YUV444_16Bit;
else
CV_Error(Error::StsUnsupportedFormat, "No supported output format found");
}
videoFormat_.surfaceFormat = static_cast<SurfaceFormat>(surfaceFormat);
if (videoFormat.enableHistogram) {
if (!decodeCaps.bIsHistogramSupported) {
CV_Error(Error::StsBadArg, "Luma histogram output is not supported for current codec and/or on current device.");
}
if (decodeCaps.nCounterBitDepth != 32) {
std::ostringstream error;
error << "Luma histogram output disabled due to current device using " << decodeCaps.nCounterBitDepth << " bit bins. Histogram output only supports 32 bit bins.";
CV_Error(Error::StsBadArg, error.str());
}
else {
videoFormat_.nCounterBitDepth = decodeCaps.nCounterBitDepth;
videoFormat_.nMaxHistogramBins = decodeCaps.nMaxHistogramBins;
}
}
CV_Assert(videoFormat.ulWidth >= decodeCaps.nMinWidth &&
videoFormat.ulHeight >= decodeCaps.nMinHeight &&
videoFormat.ulWidth <= decodeCaps.nMaxWidth &&
videoFormat.ulHeight <= decodeCaps.nMaxHeight);
CV_Assert((videoFormat.width >> 4) * (videoFormat.height >> 4) <= decodeCaps.nMaxMBCount);
#else
if (videoFormat.enableHistogram) {
CV_Error(Error::StsBadArg, "Luma histogram output is not supported when CUDA Toolkit version <= 9.0.");
}
#endif
// Create video decoder
CUVIDDECODECREATEINFO createInfo_ = {};
#if (CUDART_VERSION >= 9000)
createInfo_.enableHistogram = videoFormat.enableHistogram;
createInfo_.bitDepthMinus8 = videoFormat.nBitDepthMinus8;
createInfo_.ulMaxWidth = videoFormat.ulMaxWidth;
createInfo_.ulMaxHeight = videoFormat.ulMaxHeight;
#endif
createInfo_.CodecType = _codec;
createInfo_.ulWidth = videoFormat.ulWidth;
createInfo_.ulHeight = videoFormat.ulHeight;
createInfo_.ulNumDecodeSurfaces = videoFormat.ulNumDecodeSurfaces;
createInfo_.ChromaFormat = _chromaFormat;
createInfo_.OutputFormat = surfaceFormat;
createInfo_.DeinterlaceMode = static_cast<cudaVideoDeinterlaceMode>(videoFormat.deinterlaceMode);
createInfo_.ulTargetWidth = videoFormat.width;
createInfo_.ulTargetHeight = videoFormat.height;
createInfo_.display_area.left = videoFormat.displayArea.x;
createInfo_.display_area.right = videoFormat.displayArea.x + videoFormat.displayArea.width;
createInfo_.display_area.top = videoFormat.displayArea.y;
createInfo_.display_area.bottom = videoFormat.displayArea.y + videoFormat.displayArea.height;
createInfo_.target_rect.left = videoFormat.targetRoi.x;
createInfo_.target_rect.right = videoFormat.targetRoi.x + videoFormat.targetRoi.width;
createInfo_.target_rect.top = videoFormat.targetRoi.y;
createInfo_.target_rect.bottom = videoFormat.targetRoi.y + videoFormat.targetRoi.height;
createInfo_.ulNumOutputSurfaces = 2;
createInfo_.ulCreationFlags = videoCreateFlags;
createInfo_.vidLock = lock_;
cuSafeCall(cuCtxPushCurrent(ctx_));
{
AutoLock autoLock(mtx_);
cuSafeCall(cuvidCreateDecoder(&decoder_, &createInfo_));
}
cuSafeCall(cuCtxPopCurrent(NULL));
}
int cv::cudacodec::detail::VideoDecoder::reconfigure(const FormatInfo& videoFormat) {
if (videoFormat.nBitDepthMinus8 != videoFormat_.nBitDepthMinus8 || videoFormat.nBitDepthChromaMinus8 != videoFormat_.nBitDepthChromaMinus8) {
CV_Error(Error::StsUnsupportedFormat, "Reconfigure Not supported for bit depth change");
}
if (videoFormat.chromaFormat != videoFormat_.chromaFormat) {
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_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()
{
if (decoder_)
{
cuvidDestroyDecoder(decoder_);
decoder_ = 0;
}
}
#endif // HAVE_NVCUVID
+127
View File
@@ -0,0 +1,127 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef __VIDEO_DECODER_HPP__
#define __VIDEO_DECODER_HPP__
namespace cv { namespace cudacodec { namespace detail {
class VideoDecoder
{
public:
VideoDecoder(const Codec& codec, const int minNumDecodeSurfaces, cv::Size targetSz, cv::Rect srcRoi, cv::Rect targetRoi, const bool enableHistogram, CUcontext ctx, CUvideoctxlock lock) :
ctx_(ctx), lock_(lock), decoder_(0)
{
videoFormat_.codec = codec;
videoFormat_.ulNumDecodeSurfaces = minNumDecodeSurfaces;
videoFormat_.enableHistogram = enableHistogram;
// alignment enforced by nvcuvid, likely due to chroma subsampling
videoFormat_.targetSz.width = targetSz.width - targetSz.width % 2; videoFormat_.targetSz.height = targetSz.height - targetSz.height % 2;
videoFormat_.srcRoi.x = srcRoi.x - srcRoi.x % 4; videoFormat_.srcRoi.width = srcRoi.width - srcRoi.width % 4;
videoFormat_.srcRoi.y = srcRoi.y - srcRoi.y % 2; videoFormat_.srcRoi.height = srcRoi.height - srcRoi.height % 2;
videoFormat_.targetRoi.x = targetRoi.x - targetRoi.x % 4; videoFormat_.targetRoi.width = targetRoi.width - targetRoi.width % 4;
videoFormat_.targetRoi.y = targetRoi.y - targetRoi.y % 2; videoFormat_.targetRoi.height = targetRoi.height - targetRoi.height % 2;
}
~VideoDecoder()
{
release();
}
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); }
int nDecodeSurfaces() const { return videoFormat_.ulNumDecodeSurfaces; }
cv::Size getTargetSz() const { return videoFormat_.targetSz; }
cv::Rect getSrcRoi() const { return videoFormat_.srcRoi; }
cv::Rect getTargetRoi() const { return videoFormat_.targetRoi; }
unsigned long frameWidth() const { return videoFormat_.ulWidth; }
unsigned long frameHeight() const { return videoFormat_.ulHeight; }
FormatInfo format() { AutoLock autoLock(mtx_); return videoFormat_;}
unsigned long targetWidth() { return videoFormat_.width; }
unsigned long targetHeight() { return videoFormat_.height; }
cudaVideoChromaFormat chromaFormat() const { return static_cast<cudaVideoChromaFormat>(videoFormat_.chromaFormat); }
int nBitDepthMinus8() const { return videoFormat_.nBitDepthMinus8; }
bool enableHistogram() const { return videoFormat_.enableHistogram; }
bool decodePicture(CUVIDPICPARAMS* picParams)
{
return cuvidDecodePicture(decoder_, picParams) == CUDA_SUCCESS;
}
cuda::GpuMat mapFrame(int picIdx, CUVIDPROCPARAMS& videoProcParams)
{
CUdeviceptr ptr;
unsigned int pitch;
cuSafeCall( cuvidMapVideoFrame(decoder_, picIdx, &ptr, &pitch, &videoProcParams) );
const int height = (videoFormat_.surfaceFormat == cudaVideoSurfaceFormat_NV12 || videoFormat_.surfaceFormat == cudaVideoSurfaceFormat_P016) ? targetHeight() * 3 / 2 : targetHeight() * 3;
const int type = (videoFormat_.surfaceFormat == cudaVideoSurfaceFormat_NV12 || videoFormat_.surfaceFormat == cudaVideoSurfaceFormat_YUV444) ? CV_8U : CV_16U;
return cuda::GpuMat(height, targetWidth(), type, (void*) ptr, pitch);
}
void unmapFrame(cuda::GpuMat& frame)
{
cuSafeCall( cuvidUnmapVideoFrame(decoder_, (CUdeviceptr) frame.data) );
frame.release();
}
private:
CUcontext ctx_ = 0;
CUvideoctxlock lock_;
CUvideodecoder decoder_ = 0;
FormatInfo videoFormat_ = {};
Mutex mtx_;
};
}}}
#endif // __VIDEO_DECODER_HPP__
+209
View File
@@ -0,0 +1,209 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "precomp.hpp"
#ifdef HAVE_NVCUVID
cv::cudacodec::detail::VideoParser::VideoParser(VideoDecoder* videoDecoder, FrameQueue* frameQueue, const bool allowFrameDrop, const bool udpSource) :
videoDecoder_(videoDecoder), frameQueue_(frameQueue), allowFrameDrop_(allowFrameDrop)
{
if (udpSource) maxUnparsedPackets_ = 0;
CUVIDPARSERPARAMS params;
std::memset(&params, 0, sizeof(CUVIDPARSERPARAMS));
params.CodecType = videoDecoder->codec();
params.ulMaxNumDecodeSurfaces = 1;
params.ulMaxDisplayDelay = 1; // this flag is needed so the parser will push frames out to the decoder as quickly as it can
params.pUserData = this;
params.pfnSequenceCallback = HandleVideoSequence; // Called before decoding frames and/or whenever there is a format change
params.pfnDecodePicture = HandlePictureDecode; // Called when a picture is ready to be decoded (decode order)
params.pfnDisplayPicture = HandlePictureDisplay; // Called whenever a picture is ready to be displayed (display order)
cuSafeCall( cuvidCreateVideoParser(&parser_, &params) );
}
bool cv::cudacodec::detail::VideoParser::parseVideoData(const unsigned char* data, size_t size, const bool rawMode, const bool containsKeyFrame, bool endOfStream)
{
CUVIDSOURCEDATAPACKET packet;
std::memset(&packet, 0, sizeof(CUVIDSOURCEDATAPACKET));
packet.flags = CUVID_PKT_TIMESTAMP;
if (endOfStream)
packet.flags |= CUVID_PKT_ENDOFSTREAM;
packet.payload_size = static_cast<unsigned long>(size);
packet.payload = data;
if (rawMode)
currentFramePackets.push_back(RawPacket(data, size, containsKeyFrame));
CUresult retVal = CUDA_SUCCESS;
try {
retVal = cuvidParseVideoData(parser_, &packet);
}
catch(const cv::Exception& e) {
CV_LOG_ERROR(NULL, e.msg);
hasError_ = true;
frameQueue_->endDecode();
return false;
}
if (retVal != CUDA_SUCCESS) {
hasError_ = true;
frameQueue_->endDecode();
return false;
}
++unparsedPackets_;
if (maxUnparsedPackets_ && unparsedPackets_ > maxUnparsedPackets_)
{
CV_LOG_ERROR(NULL, "Maxium number of packets (" << maxUnparsedPackets_ << ") parsed without decoding a frame or reconfiguring the decoder, if reading from \
a live source consider initializing with VideoReaderInitParams::udpSource == true.");
hasError_ = true;
frameQueue_->endDecode();
return false;
}
if (endOfStream)
frameQueue_->endDecode();
return !frameQueue_->isEndOfDecode();
}
int CUDAAPI cv::cudacodec::detail::VideoParser::HandleVideoSequence(void* userData, CUVIDEOFORMAT* format)
{
VideoParser* thiz = static_cast<VideoParser*>(userData);
thiz->unparsedPackets_ = 0;
FormatInfo newFormat;
newFormat.videoFullRangeFlag = format->video_signal_description.video_full_range_flag;
newFormat.colorSpaceStandard = static_cast<ColorSpaceStandard>(format->video_signal_description.matrix_coefficients);
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)
{
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;
newFormat.enableHistogram = thiz->videoDecoder_->enableHistogram();
thiz->frameQueue_->waitUntilEmpty();
int retVal = newFormat.ulNumDecodeSurfaces;
if (thiz->videoDecoder_->inited()) {
retVal = thiz->videoDecoder_->reconfigure(newFormat);
if (retVal > 1 && newFormat.ulNumDecodeSurfaces != thiz->frameQueue_->getMaxSz())
thiz->frameQueue_->resize(newFormat.ulNumDecodeSurfaces);
}
else {
thiz->frameQueue_->init(newFormat.ulNumDecodeSurfaces);
thiz->videoDecoder_->create(newFormat);
}
return retVal;
}
int CUDAAPI cv::cudacodec::detail::VideoParser::HandlePictureDecode(void* userData, CUVIDPICPARAMS* picParams)
{
VideoParser* thiz = static_cast<VideoParser*>(userData);
thiz->unparsedPackets_ = 0;
bool isFrameAvailable = thiz->frameQueue_->waitUntilFrameAvailable(picParams->CurrPicIdx, thiz->allowFrameDrop_);
if (!isFrameAvailable)
return false;
if (!thiz->videoDecoder_->decodePicture(picParams))
{
CV_LOG_ERROR(NULL, "Decoding failed!");
thiz->hasError_ = true;
return false;
}
return true;
}
int CUDAAPI cv::cudacodec::detail::VideoParser::HandlePictureDisplay(void* userData, CUVIDPARSERDISPINFO* picParams)
{
VideoParser* thiz = static_cast<VideoParser*>(userData);
thiz->unparsedPackets_ = 0;
thiz->frameQueue_->enqueue(picParams, thiz->currentFramePackets);
thiz->currentFramePackets.clear();
return true;
}
#endif // HAVE_NVCUVID
+95
View File
@@ -0,0 +1,95 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef __VIDEO_PARSER_HPP__
#define __VIDEO_PARSER_HPP__
#include "frame_queue.hpp"
#include "video_decoder.hpp"
namespace cv { namespace cudacodec { namespace detail {
class VideoParser
{
public:
VideoParser(VideoDecoder* videoDecoder, FrameQueue* frameQueue, const bool allowFrameDrop = false, const bool udpSource = false);
~VideoParser()
{
cuvidDestroyVideoParser(parser_);
}
bool parseVideoData(const unsigned char* data, size_t size, const bool rawMode, const bool containsKeyFrame, bool endOfStream);
bool hasError() const { return hasError_; }
bool udpSource() const { return maxUnparsedPackets_ == 0; }
bool allowFrameDrops() const { return allowFrameDrop_; }
private:
VideoDecoder* videoDecoder_ = 0;
FrameQueue* frameQueue_ = 0;
CUvideoparser parser_;
int unparsedPackets_ = 0;
int maxUnparsedPackets_ = 20;
std::vector<RawPacket> currentFramePackets;
volatile bool hasError_ = false;
bool allowFrameDrop_ = false;
// Called when the decoder encounters a video format change (or initial sequence header)
static int CUDAAPI HandleVideoSequence(void* pUserData, CUVIDEOFORMAT* pFormat);
// Called by the video parser to decode a single picture
// Since the parser will deliver data as fast as it can, we need to make sure that the picture
// index we're attempting to use for decode is no longer used for display
static int CUDAAPI HandlePictureDecode(void* pUserData, CUVIDPICPARAMS* pPicParams);
// Called by the video parser to display a video frame (in the case of field pictures, there may be
// 2 decode calls per 1 display call, since two fields make up one frame)
static int CUDAAPI HandlePictureDisplay(void* pUserData, CUVIDPARSERDISPINFO* pPicParams);
};
}}}
#endif // __VIDEO_PARSER_HPP__
+466
View File
@@ -0,0 +1,466 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "precomp.hpp"
using namespace cv;
using namespace cv::cuda;
using namespace cv::cudacodec;
#ifndef HAVE_NVCUVID
Ptr<VideoReader> cv::cudacodec::createVideoReader(const String&, const std::vector<int>&, const VideoReaderInitParams) { throw_no_cuda(); return Ptr<VideoReader>(); }
Ptr<VideoReader> cv::cudacodec::createVideoReader(const Ptr<RawVideoSource>&, const VideoReaderInitParams) { throw_no_cuda(); return Ptr<VideoReader>(); }
void cv::cudacodec::MapHist(const GpuMat&, Mat&) { throw_no_cuda(); }
#else // HAVE_NVCUVID
void nv12ToBgra(const GpuMat& decodedFrame, GpuMat& outFrame, int width, int height, const bool videoFullRangeFlag, cudaStream_t stream);
using namespace cv::cudacodec::detail;
namespace
{
class VideoReaderImpl : public VideoReader
{
public:
explicit VideoReaderImpl(const Ptr<VideoSource>& source, const int minNumDecodeSurfaces, const bool allowFrameDrop = false , const bool udpSource = false,
const Size targetSz = Size(), const Rect srcRoi = Rect(), const Rect targetRoi = Rect(), const bool enableHistogram = false, const int firstFrameIdx = 0);
~VideoReaderImpl();
bool nextFrame(GpuMat& frame, Stream& stream) CV_OVERRIDE;
bool nextFrame(GpuMat& frame, GpuMat& histogram, Stream& stream) CV_OVERRIDE;
FormatInfo format() const CV_OVERRIDE;
bool grab(Stream& stream) CV_OVERRIDE;
bool retrieve(OutputArray frame, const size_t idx) const CV_OVERRIDE;
bool set(const VideoReaderProps propertyId, const double propertyVal) CV_OVERRIDE;
bool set(const ColorFormat colorFormat, const BitDepth bitDepth = BitDepth::UNCHANGED, const bool planar = false) CV_OVERRIDE;
bool get(const VideoReaderProps propertyId, double& propertyVal) const CV_OVERRIDE;
bool getVideoReaderProps(const VideoReaderProps propertyId, double& propertyValOut, double propertyValIn) const CV_OVERRIDE;
bool get(const int propertyId, double& propertyVal) const CV_OVERRIDE;
private:
bool skipFrame();
bool aquireFrameInfo(std::pair<CUVIDPARSERDISPINFO, CUVIDPROCPARAMS>& frameInfo, Stream& stream = Stream::Null());
void releaseFrameInfo(const std::pair<CUVIDPARSERDISPINFO, CUVIDPROCPARAMS>& frameInfo);
bool internalGrab(GpuMat & frame, GpuMat & histogram, Stream & stream);
void waitForDecoderInit();
void cvtFromYuv(const GpuMat& decodedFrame, GpuMat& outFrame, const SurfaceFormat surfaceFormat, Stream& stream);
Ptr<VideoSource> videoSource_;
Ptr<FrameQueue> frameQueue_ = 0;
Ptr<VideoDecoder> videoDecoder_ = 0;
Ptr<VideoParser> videoParser_ = 0;
CUvideoctxlock lock_;
std::deque< std::pair<CUVIDPARSERDISPINFO, CUVIDPROCPARAMS> > frames_;
std::vector<RawPacket> rawPackets;
GpuMat lastFrame, lastHistogram;
static const int decodedFrameIdx = 0;
static const int extraDataIdx = 1;
static const int rawPacketsBaseIdx = 2;
Ptr<NVSurfaceToColorConverter> yuvConverter = 0;
ColorFormat colorFormat = ColorFormat::BGRA;
BitDepth bitDepth = BitDepth::UNCHANGED;
bool planar = false;
static const String errorMsg;
int iFrame = 0;
};
const String VideoReaderImpl::errorMsg = "Parsing/Decoding video source failed, check GPU memory is available and GPU supports requested functionality.";
FormatInfo VideoReaderImpl::format() const
{
return videoSource_->format();
}
void VideoReaderImpl::waitForDecoderInit() {
for (;;) {
if (videoDecoder_->inited()) break;
if (videoParser_->hasError() || frameQueue_->isEndOfDecode())
CV_Error(Error::StsError, errorMsg);
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, const bool enableHistogram, const int firstFrameIdx) :
videoSource_(source),
lock_(0)
{
// init context
GpuMat temp(1, 1, CV_8UC1);
temp.release();
CUcontext ctx;
cuSafeCall( cuCtxGetCurrent(&ctx) );
cuSafeCall( cuvidCtxLockCreate(&lock_, ctx) );
frameQueue_.reset(new FrameQueue());
videoDecoder_.reset(new VideoDecoder(videoSource_->format().codec, minNumDecodeSurfaces, targetSz, srcRoi, targetRoi, enableHistogram, ctx, lock_));
videoParser_.reset(new VideoParser(videoDecoder_, frameQueue_, allowFrameDrop, udpSource));
videoSource_->setVideoParser(videoParser_);
videoSource_->start();
waitForDecoderInit();
FormatInfo format = videoDecoder_->format();
if (format.colorSpaceStandard == ColorSpaceStandard::Unspecified) {
if (format.width > 1280 || format.height > 720)
format.colorSpaceStandard = ColorSpaceStandard::BT709;
else
format.colorSpaceStandard = ColorSpaceStandard::BT601;
}
yuvConverter = createNVSurfaceToColorConverter(format.colorSpaceStandard, format.videoFullRangeFlag);
for(iFrame = videoSource_->getFirstFrameIdx(); iFrame < firstFrameIdx; iFrame++)
CV_Assert(skipFrame());
videoSource_->updateFormat(format);
}
VideoReaderImpl::~VideoReaderImpl()
{
frameQueue_->endDecode();
videoSource_->stop();
}
class VideoCtxAutoLock
{
public:
VideoCtxAutoLock(CUvideoctxlock lock) : m_lock(lock) { cuSafeCall( cuvidCtxLock(m_lock, 0) ); }
~VideoCtxAutoLock() { cuvidCtxUnlock(m_lock, 0); }
private:
CUvideoctxlock m_lock;
};
bool VideoReaderImpl::aquireFrameInfo(std::pair<CUVIDPARSERDISPINFO, CUVIDPROCPARAMS>& frameInfo, Stream& stream) {
if (frames_.empty())
{
CUVIDPARSERDISPINFO displayInfo;
rawPackets.clear();
for (;;)
{
if (frameQueue_->dequeue(displayInfo, rawPackets))
break;
if (videoParser_->hasError())
CV_Error(Error::StsError, errorMsg);
if (frameQueue_->isEndOfDecode())
return false;
// Wait a bit
Thread::sleep(1);
}
bool isProgressive = displayInfo.progressive_frame != 0;
const int num_fields = isProgressive ? 1 : 2 + displayInfo.repeat_first_field;
for (int active_field = 0; active_field < num_fields; ++active_field)
{
CUVIDPROCPARAMS videoProcParams;
std::memset(&videoProcParams, 0, sizeof(CUVIDPROCPARAMS));
videoProcParams.progressive_frame = displayInfo.progressive_frame;
videoProcParams.second_field = active_field;
videoProcParams.top_field_first = displayInfo.top_field_first;
videoProcParams.unpaired_field = (num_fields == 1);
videoProcParams.output_stream = StreamAccessor::getStream(stream);
frames_.push_back(std::make_pair(displayInfo, videoProcParams));
}
}
else {
for (auto& frame : frames_)
frame.second.output_stream = StreamAccessor::getStream(stream);
}
if (frames_.empty())
return false;
frameInfo = frames_.front();
frames_.pop_front();
return true;
}
void VideoReaderImpl::releaseFrameInfo(const std::pair<CUVIDPARSERDISPINFO, CUVIDPROCPARAMS>& frameInfo) {
// release the frame, so it can be re-used in decoder
if (frames_.empty())
frameQueue_->releaseFrame(frameInfo.first);
}
bool VideoReaderImpl::internalGrab(GpuMat& frame, GpuMat& histogram, Stream& stream) {
if (videoParser_->hasError())
CV_Error(Error::StsError, errorMsg);
std::pair<CUVIDPARSERDISPINFO, CUVIDPROCPARAMS> frameInfo;
if (!aquireFrameInfo(frameInfo, stream))
return false;
{
VideoCtxAutoLock autoLock(lock_);
unsigned long long cuHistogramPtr = 0;
const cudacodec::FormatInfo fmt = videoDecoder_->format();
if (fmt.enableHistogram)
frameInfo.second.histogram_dptr = &cuHistogramPtr;
// map decoded video frame to CUDA surface
GpuMat decodedFrame = videoDecoder_->mapFrame(frameInfo.first.picture_index, frameInfo.second);
if (fmt.enableHistogram) {
const size_t histogramSz = 4 * fmt.nMaxHistogramBins;
histogram.create(1, fmt.nMaxHistogramBins, CV_32S);
cuSafeCall(cuMemcpyDtoDAsync((CUdeviceptr)(histogram.data), cuHistogramPtr, histogramSz, StreamAccessor::getStream(stream)));
}
cvtFromYuv(decodedFrame, frame, videoDecoder_->format().surfaceFormat, stream);
// unmap video frame
// unmapFrame() synchronizes with the VideoDecode API (ensures the frame has finished decoding)
videoDecoder_->unmapFrame(decodedFrame);
}
releaseFrameInfo(frameInfo);
iFrame++;
return true;
}
bool VideoReaderImpl::skipFrame() {
std::pair<CUVIDPARSERDISPINFO, CUVIDPROCPARAMS> frameInfo;
if (!aquireFrameInfo(frameInfo))
return false;
releaseFrameInfo(frameInfo);
return true;
}
bool VideoReaderImpl::grab(Stream& stream) {
return internalGrab(lastFrame, lastHistogram, stream);
}
bool VideoReaderImpl::retrieve(OutputArray frame, const size_t idx) const {
if (idx == decodedFrameIdx) {
if (!frame.isGpuMat())
CV_Error(Error::StsUnsupportedFormat, "Decoded frame is stored on the device and must be retrieved using a cv::cuda::GpuMat");
frame.getGpuMatRef() = lastFrame;
}
else if (idx == extraDataIdx) {
if (!frame.isMat())
CV_Error(Error::StsUnsupportedFormat, "Extra data is stored on the host and must be retrieved using a cv::Mat");
videoSource_->getExtraData(frame.getMatRef());
}
else{
if (idx >= rawPacketsBaseIdx && idx < rawPacketsBaseIdx + rawPackets.size()) {
if (!frame.isMat())
CV_Error(Error::StsUnsupportedFormat, "Raw data is stored on the host and must be retrieved using a cv::Mat");
const size_t i = idx - rawPacketsBaseIdx;
Mat tmp(1, rawPackets.at(i).Size(), CV_8UC1, const_cast<unsigned char*>(rawPackets.at(i).Data()), rawPackets.at(i).Size());
frame.getMatRef() = tmp;
}
}
return !frame.empty();
}
bool VideoReaderImpl::set(const VideoReaderProps propertyId, const double propertyVal) {
switch (propertyId) {
case VideoReaderProps::PROP_RAW_MODE :
videoSource_->SetRawMode(static_cast<bool>(propertyVal));
return true;
}
return false;
}
bool ValidColorFormat(const ColorFormat colorFormat) {
if (colorFormat == ColorFormat::BGRA || colorFormat == ColorFormat::BGR || colorFormat == ColorFormat::RGB || colorFormat == ColorFormat::RGBA || colorFormat == ColorFormat::GRAY || colorFormat == ColorFormat::NV_YUV_SURFACE_FORMAT || colorFormat == ColorFormat::NV_YUV444)
return true;
return false;
}
bool VideoReaderImpl::set(const ColorFormat colorFormat_, const BitDepth bitDepth_, const bool planar_) {
ColorFormat tmpFormat = colorFormat_;
if (tmpFormat == ColorFormat::NV_NV12) {
CV_LOG_WARNING(NULL, "ColorFormat::NV_NV12 is depreciated forcing ColorFormat::NV_YUV_SURFACE_FORMAT instead.");
tmpFormat = ColorFormat::NV_YUV_SURFACE_FORMAT;
}
if (!ValidColorFormat(tmpFormat)) return false;
colorFormat = tmpFormat;
bitDepth = bitDepth_;
planar = planar_;
return true;
}
bool VideoReaderImpl::get(const VideoReaderProps propertyId, double& propertyVal) const {
switch (propertyId)
{
case VideoReaderProps::PROP_DECODED_FRAME_IDX:
propertyVal = decodedFrameIdx;
return true;
case VideoReaderProps::PROP_EXTRA_DATA_INDEX:
propertyVal = extraDataIdx;
return true;
case VideoReaderProps::PROP_RAW_PACKAGES_BASE_INDEX:
if (videoSource_->RawModeEnabled()) {
propertyVal = rawPacketsBaseIdx;
return true;
}
else
break;
case VideoReaderProps::PROP_NUMBER_OF_RAW_PACKAGES_SINCE_LAST_GRAB:
propertyVal = rawPackets.size();
return true;
case VideoReaderProps::PROP_RAW_MODE:
propertyVal = videoSource_->RawModeEnabled();
return true;
case VideoReaderProps::PROP_LRF_HAS_KEY_FRAME: {
const int iPacket = propertyVal - rawPacketsBaseIdx;
if (videoSource_->RawModeEnabled() && iPacket >= 0 && iPacket < rawPackets.size()) {
propertyVal = rawPackets.at(iPacket).ContainsKeyFrame();
return true;
}
else
break;
}
case VideoReaderProps::PROP_ALLOW_FRAME_DROP:
propertyVal = videoParser_->allowFrameDrops();
return true;
case VideoReaderProps::PROP_UDP_SOURCE:
propertyVal = videoParser_->udpSource();
return true;
case VideoReaderProps::PROP_COLOR_FORMAT:
propertyVal = static_cast<double>(colorFormat);
return true;
case VideoReaderProps::PROP_BIT_DEPTH:
propertyVal = static_cast<double>(bitDepth);
return true;
case VideoReaderProps::PROP_PLANAR:
propertyVal = static_cast<double>(planar);
return true;
default:
break;
}
return false;
}
bool VideoReaderImpl::getVideoReaderProps(const VideoReaderProps propertyId, double& propertyValOut, double propertyValIn) const {
double propertyValInOut = propertyValIn;
const bool ret = get(propertyId, propertyValInOut);
propertyValOut = propertyValInOut;
return ret;
}
bool VideoReaderImpl::get(const int propertyId, double& propertyVal) const {
if (propertyId == cv::VideoCaptureProperties::CAP_PROP_POS_FRAMES) {
propertyVal = static_cast<double>(iFrame);
return true;
}
return videoSource_->get(propertyId, propertyVal);
}
bool VideoReaderImpl::nextFrame(GpuMat& frame, Stream& stream)
{
GpuMat tmp;
return nextFrame(frame, tmp, stream);
}
bool VideoReaderImpl::nextFrame(GpuMat& frame, GpuMat& histogram, Stream& stream)
{
if (!internalGrab(frame, histogram, stream))
return false;
return true;
}
void VideoReaderImpl::cvtFromYuv(const GpuMat& decodedFrame, GpuMat& outFrame, const SurfaceFormat surfaceFormat, Stream& stream)
{
if (colorFormat == ColorFormat::NV_YUV_SURFACE_FORMAT) {
decodedFrame.copyTo(outFrame, stream);
return;
}
yuvConverter->convert(decodedFrame, outFrame, surfaceFormat, colorFormat, bitDepth, planar, stream);
}
}
Ptr<VideoReader> cv::cudacodec::createVideoReader(const String& filename, const std::vector<int>& sourceParams, const VideoReaderInitParams params)
{
CV_Assert(!filename.empty());
Ptr<VideoSource> videoSource;
try
{
// prefer ffmpeg to cuvidGetSourceVideoFormat() which doesn't always return the corrct raw pixel format
Ptr<RawVideoSource> source(new FFmpegVideoSource(filename, sourceParams, params.firstFrameIdx));
videoSource.reset(new RawVideoSourceWrapper(source, params.rawMode));
}
catch (...)
{
if (sourceParams.size()) throw;
videoSource.reset(new CuvidVideoSource(filename));
}
return makePtr<VideoReaderImpl>(videoSource, params.minNumDecodeSurfaces, params.allowFrameDrop, params.udpSource, params.targetSz,
params.srcRoi, params.targetRoi, params.enableHistogram, params.firstFrameIdx);
}
Ptr<VideoReader> cv::cudacodec::createVideoReader(const Ptr<RawVideoSource>& source, const VideoReaderInitParams params)
{
Ptr<VideoSource> videoSource(new RawVideoSourceWrapper(source, params.rawMode));
return makePtr<VideoReaderImpl>(videoSource, params.minNumDecodeSurfaces, params.allowFrameDrop, params.udpSource, params.targetSz,
params.srcRoi, params.targetRoi, params.enableHistogram, params.firstFrameIdx);
}
void cv::cudacodec::MapHist(const GpuMat& hist, Mat& histFull) {
Mat histHost; hist.download(histHost);
histFull.create(histHost.size(), histHost.type());
histFull = 0;
const float scale = 255.0f / 219.0f;
const int offset = 16;
for (int iScaled = 0; iScaled < histHost.cols; iScaled++) {
const int iHistFull = std::min(std::max(0, static_cast<int>(std::round((iScaled - offset) * scale))), static_cast<int>(histFull.total()) - 1);
histFull.at<int>(iHistFull) += histHost.at<int>(iScaled);
}
}
#endif // HAVE_NVCUVID
+148
View File
@@ -0,0 +1,148 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "precomp.hpp"
#ifdef HAVE_NVCUVID
using namespace cv;
using namespace cv::cudacodec;
using namespace cv::cudacodec::detail;
bool cv::cudacodec::detail::VideoSource::parseVideoData(const unsigned char* data, size_t size, const bool rawMode, const bool containsKeyFrame, bool endOfStream)
{
return videoParser_->parseVideoData(data, size, rawMode, containsKeyFrame, endOfStream);
}
cv::cudacodec::detail::RawVideoSourceWrapper::RawVideoSourceWrapper(const Ptr<RawVideoSource>& source, const bool rawMode) :
source_(source)
{
SetRawMode(rawMode);
CV_Assert( !source_.empty() );
}
cv::cudacodec::FormatInfo cv::cudacodec::detail::RawVideoSourceWrapper::format() const
{
return source_->format();
}
void cv::cudacodec::detail::RawVideoSourceWrapper::updateFormat(const FormatInfo& videoFormat)
{
source_->updateFormat(videoFormat);
}
bool cv::cudacodec::detail::RawVideoSourceWrapper::get(const int propertyId, double& propertyVal) const
{
return source_->get(propertyId, propertyVal);
}
int cv::cudacodec::detail::RawVideoSourceWrapper::getFirstFrameIdx() const {
return source_->getFirstFrameIdx();
}
void cv::cudacodec::detail::RawVideoSourceWrapper::start()
{
stop_ = false;
hasError_ = false;
thread_.reset(new Thread(readLoop, this));
}
void cv::cudacodec::detail::RawVideoSourceWrapper::stop()
{
stop_ = true;
thread_->wait();
thread_.release();
}
bool cv::cudacodec::detail::RawVideoSourceWrapper::isStarted() const
{
return !stop_;
}
bool cv::cudacodec::detail::RawVideoSourceWrapper::hasError() const
{
return hasError_;
}
void cv::cudacodec::detail::RawVideoSourceWrapper::readLoop(void* userData)
{
RawVideoSourceWrapper* thiz = static_cast<RawVideoSourceWrapper*>(userData);
for (;;)
{
unsigned char* data;
size_t size;
if (!thiz->source_->getNextPacket(&data, &size))
{
thiz->hasError_ = false;
break;
}
bool containsKeyFrame = false;
if (thiz->RawModeEnabled()) {
containsKeyFrame = thiz->source_->lastPacketContainsKeyFrame();
if (!thiz->extraDataQueried) {
thiz->extraDataQueried = true;
Mat extraData;
thiz->source_->getExtraData(extraData);
if(!extraData.empty())
thiz->setExtraData(extraData);
}
}
if (!thiz->parseVideoData(data, size, thiz->RawModeEnabled(), containsKeyFrame))
{
thiz->hasError_ = true;
break;
}
if (thiz->stop_)
break;
}
if(!thiz->hasError_)
thiz->parseVideoData(0, 0, false, false, true);
}
#endif // HAVE_NVCUVID
+110
View File
@@ -0,0 +1,110 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef __CUDACODEC_VIDEO_SOURCE_H__
#define __CUDACODEC_VIDEO_SOURCE_H__
#include "thread.hpp"
namespace cv { namespace cudacodec { namespace detail {
class VideoParser;
class VideoSource
{
public:
virtual ~VideoSource() {}
virtual FormatInfo format() const = 0;
virtual void updateFormat(const FormatInfo& videoFormat) = 0;
virtual bool get(const int, double&) const { return false; }
virtual int getFirstFrameIdx() const { return 0; }
virtual void start() = 0;
virtual void stop() = 0;
virtual bool isStarted() const = 0;
virtual bool hasError() const = 0;
void setVideoParser(detail::VideoParser* videoParser) { videoParser_ = videoParser; }
void setExtraData(const cv::Mat _extraData) {
AutoLock autoLock(mtx_);
extraData = _extraData.clone();
}
void getExtraData(cv::Mat& _extraData) {
AutoLock autoLock(mtx_);
_extraData = extraData.clone();
}
void SetRawMode(const bool enabled) { rawMode_ = enabled; }
bool RawModeEnabled() const { return rawMode_; }
protected:
bool parseVideoData(const uchar* data, size_t size, const bool rawMode, const bool containsKeyFrame, bool endOfStream = false);
bool extraDataQueried = false;
private:
detail::VideoParser* videoParser_ = 0;
cv::Mat extraData;
bool rawMode_ = false;
Mutex mtx_;
};
class RawVideoSourceWrapper : public VideoSource
{
public:
RawVideoSourceWrapper(const Ptr<RawVideoSource>& source, const bool rawMode);
FormatInfo format() const CV_OVERRIDE;
void updateFormat(const FormatInfo& videoFormat) CV_OVERRIDE;
bool get(const int propertyId, double& propertyVal) const CV_OVERRIDE;
int getFirstFrameIdx() const CV_OVERRIDE;
void start() CV_OVERRIDE;
void stop() CV_OVERRIDE;
bool isStarted() const CV_OVERRIDE;
bool hasError() const CV_OVERRIDE;
private:
static void readLoop(void* userData);
Ptr<RawVideoSource> source_ = 0;
Ptr<Thread> thread_ = 0;
volatile bool stop_;
volatile bool hasError_;
};
}}}
#endif // __CUDACODEC_VIDEO_SOURCE_H__
+460
View File
@@ -0,0 +1,460 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "precomp.hpp"
namespace cv { namespace cudacodec {
using namespace cv::cuda;
#if !defined(HAVE_NVCUVENC)
Ptr<cudacodec::VideoWriter> createVideoWriter(const String&, const Size, const Codec, const double, const ColorFormat, const Ptr<EncoderCallback>, const cv::cuda::Stream&) { throw_no_cuda(); return Ptr<cv::cudacodec::VideoWriter>(); }
Ptr<cudacodec::VideoWriter> createVideoWriter(const String&, const Size, const Codec, const double, const ColorFormat, const EncoderParams&, const Ptr<EncoderCallback>, const cv::cuda::Stream&) { throw_no_cuda(); return Ptr<cv::cudacodec::VideoWriter>(); }
#else // !defined HAVE_NVCUVENC
NV_ENC_BUFFER_FORMAT EncBufferFormat(const ColorFormat colorFormat);
int NChannels(const ColorFormat colorFormat);
GUID CodecGuid(const Codec codec);
void FrameRate(const double fps, uint32_t& frameRateNum, uint32_t& frameRateDen);
GUID EncodingProfileGuid(const EncodeProfile encodingProfile);
GUID EncodingPresetGuid(const EncodePreset nvPreset);
bool operator==(const EncoderParams& lhs, const EncoderParams& rhs)
{
return std::tie(lhs.nvPreset, lhs.tuningInfo, lhs.encodingProfile, lhs.rateControlMode, lhs.multiPassEncoding, lhs.constQp.qpInterB, lhs.constQp.qpInterP, lhs.constQp.qpIntra,
lhs.averageBitRate, lhs.maxBitRate, lhs.targetQuality, lhs.gopLength) == std::tie(rhs.nvPreset, rhs.tuningInfo, rhs.encodingProfile, rhs.rateControlMode, rhs.multiPassEncoding, rhs.constQp.qpInterB, rhs.constQp.qpInterP, rhs.constQp.qpIntra,
rhs.averageBitRate, rhs.maxBitRate, rhs.targetQuality, rhs.gopLength);
};
class FFmpegVideoWriter : public EncoderCallback
{
public:
FFmpegVideoWriter(const String& fileName, const Codec codec, const int fps, const Size sz, const int idrPeriod);
~FFmpegVideoWriter();
void onEncoded(const std::vector<std::vector<uint8_t>>& vPacket, const std::vector<uint64_t>& pts);
void onEncodingFinished();
bool setFrameIntervalP(const int frameIntervalP);
private:
cv::VideoWriter writer;
};
FFmpegVideoWriter::FFmpegVideoWriter(const String& fileName, const Codec codec, const int fps, const Size sz, const int idrPeriod) {
if (!videoio_registry::hasBackend(CAP_FFMPEG))
CV_Error(Error::StsNotImplemented, "FFmpeg backend not found");
const int fourcc = codec == Codec::H264 ? cv::VideoWriter::fourcc('a', 'v', 'c', '1') : cv::VideoWriter::fourcc('h', 'v', 'c', '1');
writer.open(fileName, fourcc, fps, sz, { VideoWriterProperties::VIDEOWRITER_PROP_RAW_VIDEO, 1, VideoWriterProperties::VIDEOWRITER_PROP_KEY_INTERVAL, idrPeriod });
if (!writer.isOpened())
CV_Error(Error::StsUnsupportedFormat, "Unsupported video sink");
}
void FFmpegVideoWriter::onEncodingFinished() {
writer.release();
}
FFmpegVideoWriter::~FFmpegVideoWriter() {
onEncodingFinished();
}
void FFmpegVideoWriter::onEncoded(const std::vector<std::vector<uint8_t>>& vPacket, const std::vector<uint64_t>& pts) {
CV_Assert(vPacket.size() == pts.size());
for (int i = 0; i < vPacket.size(); i++){
std::vector<uint8_t> packet = vPacket.at(i);
Mat wrappedPacket(1, packet.size(), CV_8UC1, (void*)packet.data());
const double ptsDouble = static_cast<double>(pts.at(i));
CV_Assert(static_cast<uint64_t>(ptsDouble) == pts.at(i));
CV_Assert(writer.set(VIDEOWRITER_PROP_PTS, ptsDouble));
writer.write(wrappedPacket);
}
}
bool FFmpegVideoWriter::setFrameIntervalP(const int frameIntervalP) {
return writer.set(VIDEOWRITER_PROP_DTS_DELAY, static_cast<double>(frameIntervalP - 1));
}
class RawVideoWriter : public EncoderCallback
{
public:
RawVideoWriter(const String fileName);
~RawVideoWriter();
void onEncoded(const std::vector<std::vector<uint8_t>>& vPacket, const std::vector<uint64_t>& pts);
void onEncodingFinished();
bool setFrameIntervalP(const int) { return false;}
private:
std::ofstream fpOut;
};
RawVideoWriter::RawVideoWriter(String fileName) {
fpOut = std::ofstream(fileName, std::ios::out | std::ios::binary);
if (!fpOut)
CV_Error(Error::StsError, "Failed to open video file " + fileName + " for writing!");
}
void RawVideoWriter::onEncodingFinished() {
fpOut.close();
}
RawVideoWriter::~RawVideoWriter() {
onEncodingFinished();
}
void RawVideoWriter::onEncoded(const std::vector<std::vector<uint8_t>>& vPacket, const std::vector<uint64_t>&) {
for (auto& packet : vPacket)
fpOut.write(reinterpret_cast<const char*>(packet.data()), packet.size());
}
class VideoWriterImpl : public VideoWriter
{
public:
VideoWriterImpl(const Ptr<EncoderCallback>& videoWriter, const Size frameSize, const Codec codec, const double fps,
const ColorFormat colorFormat, const Stream& stream = Stream::Null());
VideoWriterImpl(const Ptr<EncoderCallback>& videoWriter, const Size frameSize, const Codec codec, const double fps,
const ColorFormat colorFormat, const EncoderParams& encoderParams, const Stream& stream = Stream::Null());
~VideoWriterImpl();
void write(InputArray frame);
EncoderParams getEncoderParams() const;
void release();
private:
void Init(const Codec codec, const double fps, const Size frameSz);
void InitializeEncoder(const GUID codec, const double fps);
void CopyToNvSurface(const InputArray src);
Ptr<EncoderCallback> encoderCallback;
ColorFormat colorFormat = ColorFormat::UNDEFINED;
NV_ENC_BUFFER_FORMAT surfaceFormat = NV_ENC_BUFFER_FORMAT::NV_ENC_BUFFER_FORMAT_UNDEFINED;
EncoderParams encoderParams;
Stream stream = Stream::Null();
Ptr<NvEncoderCuda> pEnc;
std::vector<std::vector<uint8_t>> vPacket;
int nSrcChannels = 0;
CUcontext cuContext;
};
NV_ENC_BUFFER_FORMAT EncBufferFormat(const ColorFormat colorFormat) {
switch (colorFormat) {
case ColorFormat::BGR: return NV_ENC_BUFFER_FORMAT_ARGB;
case ColorFormat::RGB: return NV_ENC_BUFFER_FORMAT_ABGR;
case ColorFormat::BGRA: return NV_ENC_BUFFER_FORMAT_ARGB;
case ColorFormat::RGBA: return NV_ENC_BUFFER_FORMAT_ABGR;
case ColorFormat::GRAY:
case ColorFormat::NV_NV12: return NV_ENC_BUFFER_FORMAT_NV12;
case ColorFormat::NV_YV12: return NV_ENC_BUFFER_FORMAT_YV12;
case ColorFormat::NV_IYUV: return NV_ENC_BUFFER_FORMAT_IYUV;
case ColorFormat::NV_YUV444: return NV_ENC_BUFFER_FORMAT_YUV444;
case ColorFormat::NV_AYUV: return NV_ENC_BUFFER_FORMAT_AYUV;
case ColorFormat::NV_YUV420_10BIT: return NV_ENC_BUFFER_FORMAT_YUV420_10BIT;
case ColorFormat::NV_YUV444_10BIT: return NV_ENC_BUFFER_FORMAT_YUV444_10BIT;
default: return NV_ENC_BUFFER_FORMAT_UNDEFINED;
}
}
int NChannels(const ColorFormat colorFormat) {
switch (colorFormat) {
case ColorFormat::BGR:
case ColorFormat::RGB: return 3;
case ColorFormat::RGBA:
case ColorFormat::BGRA:
case ColorFormat::NV_AYUV: return 4;
case ColorFormat::GRAY:
case ColorFormat::NV_NV12:
case ColorFormat::NV_IYUV:
case ColorFormat::NV_YV12:
case ColorFormat::NV_YUV420_10BIT:
case ColorFormat::NV_YUV444:
case ColorFormat::NV_YUV444_10BIT: return 1;
default: return 0;
}
}
VideoWriterImpl::VideoWriterImpl(const Ptr<EncoderCallback>& encoderCallBack_, const Size frameSz, const Codec codec, const double fps,
const ColorFormat colorFormat_, const EncoderParams& encoderParams_, const Stream& stream_) :
encoderCallback(encoderCallBack_), colorFormat(colorFormat_), encoderParams(encoderParams_), stream(stream_)
{
CV_Assert(colorFormat != ColorFormat::UNDEFINED);
surfaceFormat = EncBufferFormat(colorFormat);
if (surfaceFormat == NV_ENC_BUFFER_FORMAT_UNDEFINED) {
String msg = cv::format("Unsupported input surface format: %i", colorFormat);
CV_LOG_WARNING(NULL, msg);
CV_Error(Error::StsUnsupportedFormat, msg);
}
nSrcChannels = NChannels(colorFormat);
Init(codec, fps, frameSz);
}
void VideoWriterImpl::release() {
std::vector<uint64_t> pts;
pEnc->EndEncode(vPacket, pts);
encoderCallback->onEncoded(vPacket, pts);
encoderCallback->onEncodingFinished();
}
VideoWriterImpl::~VideoWriterImpl() {
release();
}
GUID CodecGuid(const Codec codec) {
switch (codec) {
case Codec::H264: return NV_ENC_CODEC_H264_GUID;
case Codec::HEVC: return NV_ENC_CODEC_HEVC_GUID;
default: break;
}
std::string msg = "Unknown codec: cudacodec::VideoWriter only supports CODEC_VW::H264 and CODEC_VW::HEVC";
CV_LOG_WARNING(NULL, msg);
CV_Error(Error::StsUnsupportedFormat, msg);
}
void VideoWriterImpl::Init(const Codec codec, const double fps, const Size frameSz) {
// init context
GpuMat temp(1, 1, CV_8UC1);
temp.release();
cuSafeCall(cuCtxGetCurrent(&cuContext));
CV_Assert(nSrcChannels != 0);
const GUID codecGuid = CodecGuid(codec);
try {
pEnc = new NvEncoderCuda(cuContext, frameSz.width, frameSz.height, surfaceFormat);
InitializeEncoder(codecGuid, fps);
const cudaStream_t cudaStream = cuda::StreamAccessor::getStream(stream);
pEnc->SetIOCudaStreams((NV_ENC_CUSTREAM_PTR)&cudaStream, (NV_ENC_CUSTREAM_PTR)&cudaStream);
}
catch (cv::Exception& e)
{
String msg = String("Error initializing Nvidia Encoder. Refer to Nvidia's GPU Support Matrix to confirm your GPU supports hardware encoding, ") +
String("codec and surface format and check the encoder documentation to verify your choice of encoding paramaters are supported.") +
e.msg;
CV_Error(Error::GpuApiCallError, msg);
}
const Size encoderFrameSz(pEnc->GetEncodeWidth(), pEnc->GetEncodeHeight());
CV_Assert(frameSz == encoderFrameSz);
}
void FrameRate(const double fps, uint32_t& frameRateNum, uint32_t& frameRateDen) {
CV_Assert(fps >= 0);
int frame_rate = (int)(fps + 0.5);
int frame_rate_base = 1;
while (fabs(((double)frame_rate / frame_rate_base) - fps) > 0.001) {
frame_rate_base *= 10;
frame_rate = (int)(fps * frame_rate_base + 0.5);
}
frameRateNum = frame_rate;
frameRateDen = frame_rate_base;
}
GUID EncodingProfileGuid(const EncodeProfile encodingProfile) {
switch (encodingProfile) {
case(ENC_CODEC_PROFILE_AUTOSELECT): return NV_ENC_CODEC_PROFILE_AUTOSELECT_GUID;
case(ENC_H264_PROFILE_BASELINE): return NV_ENC_H264_PROFILE_BASELINE_GUID;
case(ENC_H264_PROFILE_MAIN): return NV_ENC_H264_PROFILE_MAIN_GUID;
case(ENC_H264_PROFILE_HIGH): return NV_ENC_H264_PROFILE_HIGH_GUID;
case(ENC_H264_PROFILE_HIGH_444): return NV_ENC_H264_PROFILE_HIGH_444_GUID;
case(ENC_H264_PROFILE_STEREO): return NV_ENC_H264_PROFILE_STEREO_GUID;
case(ENC_H264_PROFILE_PROGRESSIVE_HIGH): return NV_ENC_H264_PROFILE_PROGRESSIVE_HIGH_GUID;
case(ENC_H264_PROFILE_CONSTRAINED_HIGH): return NV_ENC_H264_PROFILE_CONSTRAINED_HIGH_GUID;
case(ENC_HEVC_PROFILE_MAIN): return NV_ENC_HEVC_PROFILE_MAIN_GUID;
case(ENC_HEVC_PROFILE_MAIN10): return NV_ENC_HEVC_PROFILE_MAIN10_GUID;
case(ENC_HEVC_PROFILE_FREXT): return NV_ENC_HEVC_PROFILE_FREXT_GUID;
default: break;
}
std::string msg = "Unknown Encoding Profile.";
CV_LOG_WARNING(NULL, msg);
CV_Error(Error::StsUnsupportedFormat, msg);
}
GUID EncodingPresetGuid(const EncodePreset nvPreset) {
switch (nvPreset) {
case ENC_PRESET_P1: return NV_ENC_PRESET_P1_GUID;
case ENC_PRESET_P2: return NV_ENC_PRESET_P2_GUID;
case ENC_PRESET_P3: return NV_ENC_PRESET_P3_GUID;
case ENC_PRESET_P4: return NV_ENC_PRESET_P4_GUID;
case ENC_PRESET_P5: return NV_ENC_PRESET_P5_GUID;
case ENC_PRESET_P6: return NV_ENC_PRESET_P6_GUID;
case ENC_PRESET_P7: return NV_ENC_PRESET_P7_GUID;
default: break;
}
std::string msg = "Unknown Nvidia Encoding Preset.";
CV_LOG_WARNING(NULL, msg);
CV_Error(Error::StsUnsupportedFormat, msg);
}
std::string GetVideoCodecString(const GUID codec) {
if (codec == NV_ENC_CODEC_H264_GUID) return "AVC/H.264";
else if (codec == NV_ENC_CODEC_HEVC_GUID) return "H.265/HEVC";
#if (NVENCAPI_MAJOR_VERSION >= 12)
else if (codec == NV_ENC_CODEC_AV1_GUID) return "AV1";
#endif
else return "Unknown";
}
void VideoWriterImpl::InitializeEncoder(const GUID codec, const double fps)
{
NV_ENC_INITIALIZE_PARAMS initializeParams = {};
initializeParams.version = NV_ENC_INITIALIZE_PARAMS_VER;
NV_ENC_CONFIG encodeConfig = {};
encodeConfig.version = NV_ENC_CONFIG_VER;
initializeParams.encodeConfig = &encodeConfig;
pEnc->CreateDefaultEncoderParams(&initializeParams, codec, EncodingPresetGuid(encoderParams.nvPreset), (NV_ENC_TUNING_INFO)encoderParams.tuningInfo);
FrameRate(fps, initializeParams.frameRateNum, initializeParams.frameRateDen);
initializeParams.encodeConfig->profileGUID = EncodingProfileGuid(encoderParams.encodingProfile);
initializeParams.encodeConfig->rcParams.rateControlMode = (NV_ENC_PARAMS_RC_MODE)(encoderParams.rateControlMode + encoderParams.multiPassEncoding);
initializeParams.encodeConfig->rcParams.constQP = { encoderParams.constQp.qpInterB, encoderParams.constQp.qpInterB,encoderParams.constQp.qpInterB };
initializeParams.encodeConfig->rcParams.averageBitRate = encoderParams.averageBitRate;
initializeParams.encodeConfig->rcParams.maxBitRate = encoderParams.maxBitRate;
initializeParams.encodeConfig->rcParams.targetQuality = encoderParams.targetQuality;
initializeParams.encodeConfig->gopLength = encoderParams.gopLength;
if (initializeParams.encodeConfig->frameIntervalP > 1) {
CV_Assert(encoderCallback->setFrameIntervalP(initializeParams.encodeConfig->frameIntervalP));
}
if (codec == NV_ENC_CODEC_H264_GUID) {
initializeParams.encodeConfig->encodeCodecConfig.h264Config.idrPeriod = encoderParams.idrPeriod;
if (encoderParams.videoFullRangeFlag) {
initializeParams.encodeConfig->encodeCodecConfig.h264Config.h264VUIParameters.videoFullRangeFlag = 1;
initializeParams.encodeConfig->encodeCodecConfig.h264Config.h264VUIParameters.videoSignalTypePresentFlag = 1;
}
}
else if (codec == NV_ENC_CODEC_HEVC_GUID) {
initializeParams.encodeConfig->encodeCodecConfig.hevcConfig.idrPeriod = encoderParams.idrPeriod;
if (encoderParams.videoFullRangeFlag) {
initializeParams.encodeConfig->encodeCodecConfig.hevcConfig.hevcVUIParameters.videoFullRangeFlag = 1;
initializeParams.encodeConfig->encodeCodecConfig.hevcConfig.hevcVUIParameters.videoSignalTypePresentFlag = 1;
}
}
else {
std::string msg = "videoFullRangeFlag is not supported by codec: " + GetVideoCodecString(codec);
CV_LOG_WARNING(NULL, msg);
}
pEnc->CreateEncoder(&initializeParams);
}
inline bool CvFormat(const ColorFormat cf) {
if (cf == ColorFormat::BGR || cf == ColorFormat::RGB || cf == ColorFormat::BGRA || cf == ColorFormat::RGBA || cf == ColorFormat::GRAY)
return true;
return false;
}
void VideoWriterImpl::CopyToNvSurface(const InputArray src)
{
const NvEncInputFrame* encoderInputFrame = pEnc->GetNextInputFrame();
CV_Assert(src.isGpuMat() || src.isMat());
if (CvFormat(colorFormat))
CV_Assert(src.size() == Size(pEnc->GetEncodeWidth(), pEnc->GetEncodeHeight()));
Npp8u* dst = (Npp8u*)encoderInputFrame->inputPtr;
if (colorFormat == ColorFormat::BGR || colorFormat == ColorFormat::RGB) {
GpuMat srcDevice;
if (src.isGpuMat())
srcDevice = src.getGpuMat();
else {
if (stream)
srcDevice.upload(src, stream);
else
srcDevice.upload(src);
}
if (colorFormat == ColorFormat::BGR) {
GpuMat dstGpuMat(pEnc->GetEncodeHeight(), pEnc->GetEncodeWidth(), CV_8UC4, dst, encoderInputFrame->pitch);
cuda::cvtColor(srcDevice, dstGpuMat, COLOR_BGR2BGRA, 0, stream);
}
else {
GpuMat dstGpuMat(pEnc->GetEncodeHeight(), pEnc->GetEncodeWidth(), CV_8UC4, dst, encoderInputFrame->pitch);
cuda::cvtColor(srcDevice, dstGpuMat, COLOR_RGB2RGBA, 0, stream);
}
}
else if (colorFormat == ColorFormat::GRAY) {
const cudaMemcpyKind memcpyKind = src.isGpuMat() ? cudaMemcpyDeviceToDevice : cudaMemcpyHostToDevice;
const void* srcPtr = src.isGpuMat() ? src.getGpuMat().data : src.getMat().data;
const size_t srcPitch = src.isGpuMat() ? src.getGpuMat().step : src.getMat().step;
const uint32_t chromaHeight = NvEncoder::GetChromaHeight(NV_ENC_BUFFER_FORMAT_NV12, pEnc->GetEncodeHeight());
if (stream) {
cudaMemcpy2DAsync(dst, encoderInputFrame->pitch, srcPtr, srcPitch, pEnc->GetEncodeWidth(), pEnc->GetEncodeHeight(), memcpyKind,
cuda::StreamAccessor::getStream(stream));
cudaMemset2DAsync(&dst[encoderInputFrame->pitch * pEnc->GetEncodeHeight()], encoderInputFrame->pitch, 128, pEnc->GetEncodeWidth(), chromaHeight,
cuda::StreamAccessor::getStream(stream));
}
else {
cudaMemcpy2D(dst, encoderInputFrame->pitch, srcPtr, srcPitch, pEnc->GetEncodeWidth(), pEnc->GetEncodeHeight(), memcpyKind);
cudaMemset2D(&dst[encoderInputFrame->pitch * pEnc->GetEncodeHeight()], encoderInputFrame->pitch, 128, pEnc->GetEncodeWidth(), chromaHeight);
}
}
else {
void* srcPtr = src.isGpuMat() ? src.getGpuMat().data : src.getMat().data;
const CUmemorytype cuMemoryType = src.isGpuMat() ? CU_MEMORYTYPE_DEVICE : CU_MEMORYTYPE_HOST;
NvEncoderCuda::CopyToDeviceFrame(cuContext, srcPtr, static_cast<unsigned>(src.step()), (CUdeviceptr)encoderInputFrame->inputPtr, (int)encoderInputFrame->pitch, pEnc->GetEncodeWidth(),
pEnc->GetEncodeHeight(), cuMemoryType, encoderInputFrame->bufferFormat, encoderInputFrame->chromaOffsets, encoderInputFrame->numChromaPlanes,
false, cuda::StreamAccessor::getStream(stream));
}
}
void VideoWriterImpl::write(const InputArray frame) {
CV_Assert(frame.channels() == nSrcChannels);
CopyToNvSurface(frame);
std::vector<uint64_t> pts;
pEnc->EncodeFrame(vPacket, pts);
encoderCallback->onEncoded(vPacket, pts);
};
EncoderParams VideoWriterImpl::getEncoderParams() const {
return encoderParams;
};
Ptr<VideoWriter> createVideoWriter(const String& fileName, const Size frameSize, const Codec codec, const double fps, const ColorFormat colorFormat,
Ptr<EncoderCallback> encoderCallback, const Stream& stream)
{
return createVideoWriter(fileName, frameSize, codec, fps, colorFormat, EncoderParams(), encoderCallback, stream);
}
Ptr<VideoWriter> createVideoWriter(const String& fileName, const Size frameSize, const Codec codec, const double fps, const ColorFormat colorFormat,
const EncoderParams& params, Ptr<EncoderCallback> encoderCallback, const Stream& stream)
{
CV_Assert(params.idrPeriod >= params.gopLength);
if (!encoderCallback) {
try {
encoderCallback = new FFmpegVideoWriter(fileName, codec, fps, frameSize, params.idrPeriod);
}
catch (...)
{
encoderCallback = new RawVideoWriter(fileName);
}
}
return makePtr<VideoWriterImpl>(encoderCallback, frameSize, codec, fps, colorFormat, params, stream);
}
#endif // !defined HAVE_NVCUVENC
}}
+45
View File
@@ -0,0 +1,45 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "test_precomp.hpp"
CV_CUDA_TEST_MAIN("gpu")
+55
View File
@@ -0,0 +1,55 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef OPENCV_TEST_PRECOMP_HPP
#define OPENCV_TEST_PRECOMP_HPP
#include "opencv2/ts.hpp"
#include "opencv2/videoio/registry.hpp"
#include "opencv2/ts/cuda_test.hpp"
#include "opencv2/cudacodec.hpp"
#include "opencv2/cudawarping.hpp"
#include "opencv2/cudaarithm.hpp"
#include "cvconfig.h"
#endif
File diff suppressed because it is too large Load Diff