Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

5.x merge 4.x #3793

Merged
merged 8 commits into from
Sep 10, 2024
Merged
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
20 changes: 5 additions & 15 deletions modules/cudaarithm/src/cuda/polar_cart.cu
Original file line number Diff line number Diff line change
Expand Up @@ -159,25 +159,15 @@ void cv::cuda::cartToPolar(InputArray _xy, OutputArray _mag, OutputArray _angle,
GpuMat_<float> magc(mag);
GpuMat_<float> anglec(angle);

gridTransformUnary(globPtr<float2>(xy), globPtr<float>(magc), magnitude_interleaved_func<float2>(), stream);

if (angleInDegrees)
{
auto f1 = magnitude_interleaved_func<float2>();
auto f2 = direction_interleaved_func<float2, true>();
cv::cudev::tuple<decltype(f1), decltype(f2)> f12 = cv::cudev::make_tuple(f1, f2);
gridTransformTuple(globPtr<float2>(xy),
tie(magc, anglec),
f12,
stream);
gridTransformUnary(globPtr<float2>(xy), globPtr<float>(anglec), direction_interleaved_func<float2, true>(), stream);
}
else
{
auto f1 = magnitude_interleaved_func<float2>();
auto f2 = direction_interleaved_func<float2, false>();
cv::cudev::tuple<decltype(f1), decltype(f2)> f12 = cv::cudev::make_tuple(f1, f2);
gridTransformTuple(globPtr<float2>(xy),
tie(magc, anglec),
f12,
stream);
gridTransformUnary(globPtr<float2>(xy), globPtr<float>(anglec), direction_interleaved_func<float2, false>(), stream);
}

syncOutput(mag, _mag, stream);
Expand All @@ -191,7 +181,7 @@ void cv::cuda::cartToPolar(InputArray _xy, OutputArray _magAngle, bool angleInDe
CV_Assert( xy.type() == CV_32FC2 );

GpuMat magAngle = getOutputMat(_magAngle, xy.size(), CV_32FC2, stream);

if (angleInDegrees)
{
gridTransformUnary(globPtr<float2>(xy),
Expand Down
9 changes: 8 additions & 1 deletion modules/cudacodec/include/opencv2/cudacodec.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -208,8 +208,15 @@ class CV_EXPORTS_W EncoderCallback {
/** @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) = 0;
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.
* */
Expand Down
16 changes: 10 additions & 6 deletions modules/cudacodec/src/NvEncoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -305,9 +305,10 @@ void NvEncoder::MapResources(uint32_t bfrIdx)
m_vMappedInputBuffers[bfrIdx] = mapInputResource.mappedResource;
}

void NvEncoder::EncodeFrame(std::vector<std::vector<uint8_t>>& vPacket, NV_ENC_PIC_PARAMS* pPicParams)
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);
Expand All @@ -322,7 +323,7 @@ void NvEncoder::EncodeFrame(std::vector<std::vector<uint8_t>>& vPacket, NV_ENC_P
if (nvStatus == NV_ENC_SUCCESS || nvStatus == NV_ENC_ERR_NEED_MORE_INPUT)
{
m_iToSend++;
GetEncodedPacket(m_vBitstreamOutputBuffer, vPacket, true);
GetEncodedPacket(m_vBitstreamOutputBuffer, vPacket, outputTimeStamps, true);
}
else
{
Expand Down Expand Up @@ -353,6 +354,7 @@ NVENCSTATUS NvEncoder::DoEncode(NV_ENC_INPUT_PTR inputBuffer, NV_ENC_OUTPUT_PTR
{
picParams = *pPicParams;
}
picParams.inputTimeStamp = m_iInputFrame++;
picParams.version = NV_ENC_PIC_PARAMS_VER;
picParams.pictureStruct = NV_ENC_PIC_STRUCT_FRAME;
picParams.inputBuffer = inputBuffer;
Expand All @@ -376,7 +378,7 @@ void NvEncoder::SendEOS()
NVENC_API_CALL(m_nvenc.nvEncEncodePicture(m_hEncoder, &picParams));
}

void NvEncoder::EndEncode(std::vector<std::vector<uint8_t>>& vPacket)
void NvEncoder::EndEncode(std::vector<std::vector<uint8_t>>& vPacket, std::vector<uint64_t>& outputTimeStamps)
{
vPacket.clear();
if (!IsHWEncoderInitialized())
Expand All @@ -386,10 +388,10 @@ void NvEncoder::EndEncode(std::vector<std::vector<uint8_t>>& vPacket)

SendEOS();

GetEncodedPacket(m_vBitstreamOutputBuffer, vPacket, false);
GetEncodedPacket(m_vBitstreamOutputBuffer, vPacket, outputTimeStamps, false);
}

void NvEncoder::GetEncodedPacket(std::vector<NV_ENC_OUTPUT_PTR>& vOutputBuffer, std::vector<std::vector<uint8_t>>& vPacket, bool bOutputDelay)
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;
Expand All @@ -402,6 +404,7 @@ void NvEncoder::GetEncodedPacket(std::vector<NV_ENC_OUTPUT_PTR>& vOutputBuffer,
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)
{
Expand Down Expand Up @@ -499,7 +502,8 @@ void NvEncoder::FlushEncoder()
try
{
std::vector<std::vector<uint8_t>> vPacket;
EndEncode(vPacket);
std::vector<uint64_t> outputTimeStamps;
EndEncode(vPacket, outputTimeStamps);
}
catch (...)
{
Expand Down
7 changes: 4 additions & 3 deletions modules/cudacodec/src/NvEncoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ class NvEncoder
* data, which has been copied to an input buffer obtained from the
* GetNextInputFrame() function.
*/
virtual void EncodeFrame(std::vector<std::vector<uint8_t>>& vPacket, NV_ENC_PIC_PARAMS* pPicParams = nullptr);
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.
Expand All @@ -109,7 +109,7 @@ class NvEncoder
* from the encoder. The application must call this function before destroying
* an encoder session.
*/
virtual void EndEncode(std::vector<std::vector<uint8_t>>& vPacket);
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.
Expand Down Expand Up @@ -317,7 +317,7 @@ class NvEncoder
* 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, bool bOutputDelay);
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.
Expand Down Expand Up @@ -369,6 +369,7 @@ class NvEncoder
int32_t m_iGot = 0;
int32_t m_nEncoderBuffer = 0;
int32_t m_nOutputDelay = 0;
int32_t m_iInputFrame = 0;

private:
void* m_pDevice;
Expand Down
41 changes: 32 additions & 9 deletions modules/cudacodec/src/video_writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ Ptr<cudacodec::VideoWriter> createVideoWriter(const String&, const Size, const C

#else // !defined HAVE_NVCUVENC

#if defined(WIN32) // remove when FFmpeg wrapper includes PR25874
#define WIN32_WAIT_FOR_FFMPEG_WRAPPER_UPDATE
#endif

NV_ENC_BUFFER_FORMAT EncBufferFormat(const ColorFormat colorFormat);
int NChannels(const ColorFormat colorFormat);
GUID CodecGuid(const Codec codec);
Expand All @@ -72,8 +76,9 @@ 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);
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;
};
Expand All @@ -95,21 +100,32 @@ FFmpegVideoWriter::~FFmpegVideoWriter() {
onEncodingFinished();
}

void FFmpegVideoWriter::onEncoded(const std::vector<std::vector<uint8_t>>& vPacket) {
for (auto& packet : vPacket) {
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));
#if !defined(WIN32_WAIT_FOR_FFMPEG_WRAPPER_UPDATE)
CV_Assert(writer.set(VIDEOWRITER_PROP_PTS, ptsDouble));
#endif
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);
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;
};
Expand All @@ -128,7 +144,7 @@ RawVideoWriter::~RawVideoWriter() {
onEncodingFinished();
}

void RawVideoWriter::onEncoded(const std::vector<std::vector<uint8_t>>& vPacket) {
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());
}
Expand Down Expand Up @@ -208,8 +224,9 @@ VideoWriterImpl::VideoWriterImpl(const Ptr<EncoderCallback>& encoderCallBack_, c
}

void VideoWriterImpl::release() {
pEnc->EndEncode(vPacket);
encoderCallback->onEncoded(vPacket);
std::vector<uint64_t> pts;
pEnc->EndEncode(vPacket, pts);
encoderCallback->onEncoded(vPacket, pts);
encoderCallback->onEncodingFinished();
}

Expand Down Expand Up @@ -316,6 +333,11 @@ void VideoWriterImpl::InitializeEncoder(const GUID codec, const double fps)
initializeParams.encodeConfig->rcParams.maxBitRate = encoderParams.maxBitRate;
initializeParams.encodeConfig->rcParams.targetQuality = encoderParams.targetQuality;
initializeParams.encodeConfig->gopLength = encoderParams.gopLength;
#if !defined(WIN32_WAIT_FOR_FFMPEG_WRAPPER_UPDATE)
if (initializeParams.encodeConfig->frameIntervalP > 1) {
CV_Assert(encoderCallback->setFrameIntervalP(initializeParams.encodeConfig->frameIntervalP));
}
#endif
if (codec == NV_ENC_CODEC_H264_GUID)
initializeParams.encodeConfig->encodeCodecConfig.h264Config.idrPeriod = encoderParams.idrPeriod;
else if (codec == NV_ENC_CODEC_HEVC_GUID)
Expand Down Expand Up @@ -383,8 +405,9 @@ void VideoWriterImpl::CopyToNvSurface(const InputArray src)
void VideoWriterImpl::write(const InputArray frame) {
CV_Assert(frame.channels() == nSrcChannels);
CopyToNvSurface(frame);
pEnc->EncodeFrame(vPacket);
encoderCallback->onEncoded(vPacket);
std::vector<uint64_t> pts;
pEnc->EncodeFrame(vPacket, pts);
encoderCallback->onEncoded(vPacket, pts);
};

EncoderParams VideoWriterImpl::getEncoderParams() const {
Expand Down
15 changes: 15 additions & 0 deletions modules/cudacodec/test/test_video.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -650,6 +650,9 @@ struct TransCode : testing::TestWithParam<cv::cuda::DeviceInfo>
}
};

#if defined(WIN32) // remove when FFmpeg wrapper includes PR25874
#define WIN32_WAIT_FOR_FFMPEG_WRAPPER_UPDATE
#endif

CUDA_TEST_P(TransCode, H264ToH265)
{
Expand Down Expand Up @@ -691,6 +694,10 @@ CUDA_TEST_P(TransCode, H264ToH265)
for (int i = 0; i < nFrames; ++i) {
cap >> frame;
ASSERT_FALSE(frame.empty());
#if !defined(WIN32_WAIT_FOR_FFMPEG_WRAPPER_UPDATE)
const int pts = static_cast<int>(cap.get(CAP_PROP_PTS));
ASSERT_EQ(i, pts > 0 ? pts : 0); // FFmpeg back end returns dts if pts is zero.
#endif
}
}
ASSERT_EQ(0, remove(outputFile.c_str()));
Expand Down Expand Up @@ -773,6 +780,10 @@ CUDA_TEST_P(Write, Writer)
for (int i = 0; i < nFrames; ++i) {
cap >> frame;
ASSERT_FALSE(frame.empty());
#if !defined(WIN32_WAIT_FOR_FFMPEG_WRAPPER_UPDATE)
const int pts = static_cast<int>(cap.get(CAP_PROP_PTS));
ASSERT_EQ(i, pts > 0 ? pts : 0); // FFmpeg back end returns dts if pts is zero.
#endif
}
}
ASSERT_EQ(0, remove(outputFile.c_str()));
Expand Down Expand Up @@ -867,6 +878,10 @@ CUDA_TEST_P(EncoderParams, Writer)
const bool keyFrameActual = capRaw.get(CAP_PROP_LRF_HAS_KEY_FRAME) == 1.0;
const bool keyFrameReference = i % idrPeriod == 0;
ASSERT_EQ(keyFrameActual, keyFrameReference);
#if !defined(WIN32_WAIT_FOR_FFMPEG_WRAPPER_UPDATE)
const int pts = static_cast<int>(cap.get(CAP_PROP_PTS));
ASSERT_EQ(i, pts > 0 ? pts : 0); // FFmpeg back end returns dts if pts is zero.
#endif
}
}
}
Expand Down
5 changes: 3 additions & 2 deletions modules/wechat_qrcode/src/zxing/zxing.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#ifndef __ZXING_ZXING_HPP__
#define __ZXING_ZXING_HPP__

#include "opencv2/core/fast_math.hpp"

#define COUNTER_TYPE short

Expand Down Expand Up @@ -54,8 +55,8 @@ typedef unsigned char boolean;
#include <cmath>

namespace zxing {
inline bool isnan(float v) { return std::isnan(v); }
inline bool isnan(double v) { return std::isnan(v); }
inline bool isnan(float v) { return cvIsNaN(v) != 0; }
inline bool isnan(double v) { return cvIsNaN(v) != 0; }
inline float nan() { return std::numeric_limits<float>::quiet_NaN(); }
} // namespace zxing

Expand Down
Loading