Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 40 additions & 2 deletions modules/cudacodec/include/opencv2/cudacodec.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,8 @@ struct CV_EXPORTS_W_SIMPLE FormatInfo
*/
class CV_EXPORTS_W NVSurfaceToColorConverter {
public:
virtual ~NVSurfaceToColorConverter() {}

/** @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.
Expand Down Expand Up @@ -550,8 +552,7 @@ class CV_EXPORTS_W VideoReader
- 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;
CV_WRAP_AS(getVideoReaderProps) virtual bool get(const VideoReaderProps propertyId, CV_OUT size_t& propertyVal) const = 0;

/** @brief Retrieves the specified property used by the VideoSource.

Expand All @@ -562,6 +563,43 @@ class CV_EXPORTS_W VideoReader
@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 Determine whether the raw package at \a idx contains encoded data for a key frame.

@param idx Index of the encoded package to check.

@returns `true` if the raw package at \a idx contains encoded data for a key frame and `false` otherwise.

@note A typical use case is deciding to archive live video after streaming has been initialized. In this scenario you would not want to write any encoded frames before a key frame. This is simulated in the example below where VideoReader is initialized without enabling raw mode
```
VideoReaderInitParams params;
params.rawMode = false;
Ptr<VideoReader> reader = createVideoReader(rtspUrl, {}, params);
```
and then at some point in the future raw mode is enabled to enable the footage to be archived
```
reader->set(VideoReaderProps::PROP_RAW_MODE, true);
```
Because raw mode has been enabled mid stream the first raw package retrieved now is not guaranteed to contain a key frame. To locate the next raw package containing a key frame rawPackageHasKeyFrame() can then be used as shown below.
```
double iRawPacketBase = -1;
reader->get(VideoReaderProps::PROP_RAW_PACKAGES_BASE_INDEX, iRawPacketBase);
GpuMat frame;
while (reader->nextFrame(frame)) {
double nRawPackets = -1;
reader->get(VideoReaderProps::PROP_NUMBER_OF_RAW_PACKAGES_SINCE_LAST_GRAB, nRawPackets);
for (int iRawPacketToWrite = static_cast<int>(iRawPacketBase); iRawPacketToWrite < static_cast<int>(iRawPacketBase + nRawPackets); iRawPacketToWrite++) {
if (reader->rawPackageHasKeyFrame(iRawPacketToWrite)) {
Mat packageToWrite;
reader->retrieve(packageToWrite, iRawPacketToWrite);
...
}
}
}
```
\sa retrieve
*/
CV_WRAP virtual bool rawPackageHasKeyFrame(const size_t idx) const = 0;
};

/** @brief Interface for video demultiplexing. :
Expand Down
18 changes: 8 additions & 10 deletions modules/cudacodec/src/NvEncoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,9 @@ void NvEncoder::CreateDefaultEncoderParams(NV_ENC_INITIALIZE_PARAMS* pIntializeP
#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
NV_ENC_PRESET_CONFIG presetConfig = {};
presetConfig.version = NV_ENC_PRESET_CONFIG_VER;
presetConfig.presetCfg.version = NV_ENC_CONFIG_VER;
m_nvenc.nvEncGetEncodePresetConfigEx(m_hEncoder, codecGuid, presetGuid, tuningInfo, &presetConfig);
memcpy(pIntializeParams->encodeConfig, &presetConfig.presetCfg, sizeof(NV_ENC_CONFIG));

Expand Down Expand Up @@ -205,11 +203,9 @@ void NvEncoder::CreateEncoder(const NV_ENC_INITIALIZE_PARAMS* pEncoderParams)
}
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
NV_ENC_PRESET_CONFIG presetConfig = {};
presetConfig.version = NV_ENC_PRESET_CONFIG_VER;
presetConfig.presetCfg.version = NV_ENC_CONFIG_VER;
m_nvenc.nvEncGetEncodePresetConfigEx(m_hEncoder, pEncoderParams->encodeGUID, pEncoderParams->presetGUID, pEncoderParams->tuningInfo, &presetConfig);
memcpy(&m_encodeConfig, &presetConfig.presetCfg, sizeof(NV_ENC_CONFIG));
}
Expand Down Expand Up @@ -570,6 +566,8 @@ void NvEncoder::WaitForCompletionEvent(int iEvent)
NVENC_THROW_ERROR("Failed to encode frame", NV_ENC_ERR_GENERIC);
}
#endif
#else
CV_UNUSED(iEvent);
#endif
}

Expand Down
5 changes: 4 additions & 1 deletion modules/cudacodec/src/NvEncoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,10 @@ class NvEncoder
/**
* @brief This function returns the completion event.
*/
void* GetCompletionEvent(uint32_t eventIdx) { return (m_vpCompletionEvent.size() == m_nEncoderBuffer) ? m_vpCompletionEvent[eventIdx] : nullptr; }
void* GetCompletionEvent(uint32_t eventIdx) {
CV_Assert(m_nEncoderBuffer >= 0);
return (m_vpCompletionEvent.size() == static_cast<size_t>(m_nEncoderBuffer)) ? m_vpCompletionEvent[eventIdx] : nullptr;
}

/**
* @brief This function returns the current pixel format.
Expand Down
5 changes: 5 additions & 0 deletions modules/cudacodec/src/cuda/ColorSpace.cu
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@

namespace cv { namespace cuda { namespace device {

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);

template<class T>
__device__ static T Clamp(T x, T lower, T upper) {
return x < lower ? lower : (x > upper ? upper : x);
Expand Down
2 changes: 1 addition & 1 deletion modules/cudacodec/src/cuvid_video_source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ cv::cudacodec::detail::CuvidVideoSource::CuvidVideoSource(const String& fname)
CUVIDEOFORMAT vidfmt;
cuSafeCall( cuvidGetSourceVideoFormat(videoSource_, &vidfmt, 0) );

CV_Assert(Codec::NumCodecs == cudaVideoCodec::cudaVideoCodec_NumCodecs);
CV_Assert(static_cast<int>(Codec::NumCodecs) == static_cast<int>(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;
Expand Down
1 change: 1 addition & 0 deletions modules/cudacodec/src/cuvid_video_source.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ class CuvidVideoSource : public VideoSource

FormatInfo format() const CV_OVERRIDE;
void updateFormat(const FormatInfo& videoFormat) CV_OVERRIDE;
bool get(const int, double&) const { return false; }
void start() CV_OVERRIDE;
void stop() CV_OVERRIDE;
bool isStarted() const CV_OVERRIDE;
Expand Down
12 changes: 7 additions & 5 deletions modules/cudacodec/src/ffmpeg_video_source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ Codec FourccToCodec(int codec)
}

static
int StartCodeLen(unsigned char* data, const int sz) {
int StartCodeLen(unsigned char* data, const size_t 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)
Expand All @@ -99,7 +99,8 @@ int StartCodeLen(unsigned char* data, const int sz) {
return 0;
}

bool ParamSetsExist(unsigned char* parameterSets, const int szParameterSets, unsigned char* data, const int szData) {
static
bool ParamSetsExist(unsigned char* parameterSets, const size_t szParameterSets, unsigned char* data, const size_t 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
Expand Down Expand Up @@ -129,8 +130,8 @@ cv::cudacodec::detail::FFmpegVideoSource::FFmpegVideoSource(const String& fname,

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_.height = static_cast<int>(cap.get(CAP_PROP_FRAME_HEIGHT));
format_.width = static_cast<int>(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);
Expand Down Expand Up @@ -181,7 +182,8 @@ bool cv::cudacodec::detail::FFmpegVideoSource::getNextPacket(unsigned char** dat
{
const size_t nBytesToTrimFromData = format_.codec == Codec::MPEG4 ? 3 : 0;
const size_t newSz = extraData.total() + *size - nBytesToTrimFromData;
dataWithHeader = Mat(1, newSz, CV_8UC1);
CV_Assert(newSz <= std::numeric_limits<int>::max());
dataWithHeader = Mat(1, static_cast<int>(newSz), CV_8UC1);
memcpy(dataWithHeader.data, extraData.data, extraData.total());
memcpy(dataWithHeader.data + extraData.total(), (*data) + nBytesToTrimFromData, *size - nBytesToTrimFromData);
*data = dataWithHeader.data;
Expand Down
48 changes: 24 additions & 24 deletions modules/cudacodec/src/video_decoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ static const char* GetVideoCodecString(cudaVideoCodec eCodec) {
}
for (int i = cudaVideoCodec_NumCodecs + 1; i < sizeof(aCodecName) / sizeof(aCodecName[0]); i++) {
if (eCodec == aCodecName[i].eCodec) {
return aCodecName[eCodec].name;
return aCodecName[i].name;
}
}
return "Unknown";
Expand Down Expand Up @@ -158,7 +158,7 @@ void cv::cudacodec::detail::VideoDecoder::create(const FormatInfo& videoFormat)
codecSupported |= cudaVideoCodec_VP8 == _codec || cudaVideoCodec_VP9 == _codec;
#endif
#if (CUDART_VERSION >= 9000)
codecSupported |= cudaVideoCodec_AV1;
codecSupported |= cudaVideoCodec_AV1 == _codec;
#endif
CV_Assert(codecSupported);
CV_Assert( cudaVideoChromaFormat_Monochrome == _chromaFormat ||
Expand Down Expand Up @@ -211,12 +211,12 @@ void cv::cudacodec::detail::VideoDecoder::create(const FormatInfo& videoFormat)
}
}

CV_Assert(videoFormat.ulWidth >= decodeCaps.nMinWidth &&
videoFormat.ulHeight >= decodeCaps.nMinHeight &&
videoFormat.ulWidth <= decodeCaps.nMaxWidth &&
videoFormat.ulHeight <= decodeCaps.nMaxHeight);
CV_Assert(videoFormat.ulWidth >= static_cast<int>(decodeCaps.nMinWidth) &&
videoFormat.ulHeight >= static_cast<int>(decodeCaps.nMinHeight) &&
videoFormat.ulWidth <= static_cast<int>(decodeCaps.nMaxWidth) &&
videoFormat.ulHeight <= static_cast<int>(decodeCaps.nMaxHeight));

CV_Assert((videoFormat.width >> 4) * (videoFormat.height >> 4) <= decodeCaps.nMaxMBCount);
CV_Assert((static_cast<unsigned int>(videoFormat.width) >> 4) * (static_cast<unsigned int>(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.");
Expand All @@ -240,14 +240,14 @@ void cv::cudacodec::detail::VideoDecoder::create(const FormatInfo& videoFormat)
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_.display_area.left = static_cast<short>(videoFormat.displayArea.x);
createInfo_.display_area.right = static_cast<short>(videoFormat.displayArea.x + videoFormat.displayArea.width);
createInfo_.display_area.top = static_cast<short>(videoFormat.displayArea.y);
createInfo_.display_area.bottom = static_cast<short>(videoFormat.displayArea.y + videoFormat.displayArea.height);
createInfo_.target_rect.left = static_cast<short>(videoFormat.targetRoi.x);
createInfo_.target_rect.right = static_cast<short>(videoFormat.targetRoi.x + videoFormat.targetRoi.width);
createInfo_.target_rect.top = static_cast<short>(videoFormat.targetRoi.y);
createInfo_.target_rect.bottom = static_cast<short>(videoFormat.targetRoi.y + videoFormat.targetRoi.height);
createInfo_.ulNumOutputSurfaces = 2;
createInfo_.ulCreationFlags = videoCreateFlags;
createInfo_.vidLock = lock_;
Expand Down Expand Up @@ -288,19 +288,19 @@ int cv::cudacodec::detail::VideoDecoder::reconfigure(const FormatInfo& videoForm
videoFormat_.targetRoi = videoFormat.targetRoi;
}

CUVIDRECONFIGUREDECODERINFO reconfigParams = { 0 };
CUVIDRECONFIGUREDECODERINFO reconfigParams = {};
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.display_area.left = static_cast<short>(videoFormat_.displayArea.x);
reconfigParams.display_area.right = static_cast<short>(videoFormat_.displayArea.x + videoFormat_.displayArea.width);
reconfigParams.display_area.top = static_cast<short>(videoFormat_.displayArea.y);
reconfigParams.display_area.bottom = static_cast<short>(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.target_rect.left = static_cast<short>(videoFormat_.targetRoi.x);
reconfigParams.target_rect.right = static_cast<short>(videoFormat_.targetRoi.x + videoFormat_.targetRoi.width);
reconfigParams.target_rect.top = static_cast<short>(videoFormat_.targetRoi.y);
reconfigParams.target_rect.bottom = static_cast<short>(videoFormat_.targetRoi.y + videoFormat_.targetRoi.height);
reconfigParams.ulNumDecodeSurfaces = videoFormat_.ulNumDecodeSurfaces;

cuSafeCall(cuCtxPushCurrent(ctx_));
Expand Down
Loading
Loading