@@ -59,7 +59,6 @@ GUID CodecGuid(const Codec codec);
5959void FrameRate (const double fps, uint32_t & frameRateNum, uint32_t & frameRateDen);
6060GUID EncodingProfileGuid (const EncodeProfile encodingProfile);
6161GUID EncodingPresetGuid (const EncodePreset nvPreset);
62- bool Equal (const GUID& g1, const GUID& g2);
6362
6463bool operator ==(const EncoderParams& lhs, const EncoderParams& rhs)
6564{
@@ -68,12 +67,48 @@ bool operator==(const EncoderParams& lhs, const EncoderParams& rhs)
6867 rhs.averageBitRate , rhs.maxBitRate , rhs.targetQuality , rhs.gopLength );
6968};
7069
70+ class FFmpegVideoWriter : public EncoderCallback
71+ {
72+ public:
73+ FFmpegVideoWriter (const String& fileName, const Codec codec, const int fps, const Size sz, const int idrPeriod);
74+ ~FFmpegVideoWriter ();
75+ void onEncoded (const std::vector<std::vector<uint8_t >>& vPacket);
76+ void onEncodingFinished ();
77+ private:
78+ cv::VideoWriter writer;
79+ };
80+
81+ FFmpegVideoWriter::FFmpegVideoWriter (const String& fileName, const Codec codec, const int fps, const Size sz, const int idrPeriod) {
82+ if (!videoio_registry::hasBackend (CAP_FFMPEG))
83+ CV_Error (Error::StsNotImplemented, " FFmpeg backend not found" );
84+ const int fourcc = codec == Codec::H264 ? cv::VideoWriter::fourcc (' a' , ' v' , ' c' , ' 1' ) : cv::VideoWriter::fourcc (' h' , ' e' , ' v' , ' 1' );
85+ writer.open (fileName, fourcc, fps, sz, { VideoWriterProperties::VIDEOWRITER_PROP_RAW_VIDEO, 1 , VideoWriterProperties::VIDEOWRITER_PROP_KEY_INTERVAL, idrPeriod });
86+ if (!writer.isOpened ())
87+ CV_Error (Error::StsUnsupportedFormat, " Unsupported video sink" );
88+ }
89+
90+ void FFmpegVideoWriter::onEncodingFinished () {
91+ writer.release ();
92+ }
93+
94+ FFmpegVideoWriter::~FFmpegVideoWriter () {
95+ onEncodingFinished ();
96+ }
97+
98+ void FFmpegVideoWriter::onEncoded (const std::vector<std::vector<uint8_t >>& vPacket) {
99+ for (auto & packet : vPacket) {
100+ Mat wrappedPacket (1 , packet.size (), CV_8UC1, (void *)packet.data ());
101+ writer.write (wrappedPacket);
102+ }
103+ }
104+
105+
71106class RawVideoWriter : public EncoderCallback
72107{
73108public:
74- RawVideoWriter (String fileName);
109+ RawVideoWriter (const String fileName);
75110 ~RawVideoWriter ();
76- void onEncoded (std::vector<std::vector<uint8_t >> vPacket);
111+ void onEncoded (const std::vector<std::vector<uint8_t >>& vPacket);
77112 void onEncodingFinished ();
78113private:
79114 std::ofstream fpOut;
@@ -93,9 +128,9 @@ RawVideoWriter::~RawVideoWriter() {
93128 onEncodingFinished ();
94129}
95130
96- void RawVideoWriter::onEncoded (std::vector<std::vector<uint8_t >> vPacket) {
131+ void RawVideoWriter::onEncoded (const std::vector<std::vector<uint8_t >>& vPacket) {
97132 for (auto & packet : vPacket)
98- fpOut.write (reinterpret_cast <char *>(packet.data ()), packet.size ());
133+ fpOut.write (reinterpret_cast <const char *>(packet.data ()), packet.size ());
99134}
100135
101136class VideoWriterImpl : public VideoWriter
@@ -172,12 +207,6 @@ VideoWriterImpl::VideoWriterImpl(const Ptr<EncoderCallback>& encoderCallBack_, c
172207 Init (codec, fps, frameSz);
173208}
174209
175- VideoWriterImpl::VideoWriterImpl (const Ptr<EncoderCallback>& encoderCallback, const Size frameSz, const Codec codec, const double fps,
176- const ColorFormat colorFormat, const Stream& stream) :
177- VideoWriterImpl(encoderCallback, frameSz, codec, fps, colorFormat, EncoderParams(), stream)
178- {
179- }
180-
181210void VideoWriterImpl::release () {
182211 pEnc->EndEncode (vPacket);
183212 encoderCallback->onEncoded (vPacket);
@@ -271,12 +300,6 @@ GUID EncodingPresetGuid(const EncodePreset nvPreset) {
271300 CV_Error (Error::StsUnsupportedFormat, msg);
272301}
273302
274- bool Equal (const GUID& g1, const GUID& g2) {
275- if (std::tie (g1.Data1 , g1.Data2 , g1.Data3 , g1.Data4 ) == std::tie (g2.Data1 , g2.Data2 , g2.Data3 , g2.Data4 ))
276- return true ;
277- return false ;
278- }
279-
280303void VideoWriterImpl::InitializeEncoder (const GUID codec, const double fps)
281304{
282305 NV_ENC_INITIALIZE_PARAMS initializeParams = {};
@@ -293,10 +316,10 @@ void VideoWriterImpl::InitializeEncoder(const GUID codec, const double fps)
293316 initializeParams.encodeConfig ->rcParams .maxBitRate = encoderParams.maxBitRate ;
294317 initializeParams.encodeConfig ->rcParams .targetQuality = encoderParams.targetQuality ;
295318 initializeParams.encodeConfig ->gopLength = encoderParams.gopLength ;
296- if (Equal ( codec, NV_ENC_CODEC_H264_GUID) )
297- initializeParams.encodeConfig ->encodeCodecConfig .h264Config .idrPeriod = encoderParams.gopLength ;
298- else if (Equal ( codec, NV_ENC_CODEC_HEVC_GUID) )
299- initializeParams.encodeConfig ->encodeCodecConfig .hevcConfig .idrPeriod = encoderParams.gopLength ;
319+ if (codec == NV_ENC_CODEC_H264_GUID)
320+ initializeParams.encodeConfig ->encodeCodecConfig .h264Config .idrPeriod = encoderParams.idrPeriod ;
321+ else if (codec == NV_ENC_CODEC_HEVC_GUID)
322+ initializeParams.encodeConfig ->encodeCodecConfig .hevcConfig .idrPeriod = encoderParams.idrPeriod ;
300323 pEnc->CreateEncoder (&initializeParams);
301324}
302325
@@ -371,14 +394,25 @@ EncoderParams VideoWriterImpl::getEncoderParams() const {
371394Ptr<VideoWriter> createVideoWriter (const String& fileName, const Size frameSize, const Codec codec, const double fps, const ColorFormat colorFormat,
372395 Ptr<EncoderCallback> encoderCallback, const Stream& stream)
373396{
374- encoderCallback = encoderCallback ? encoderCallback : new RawVideoWriter (fileName);
375- return makePtr<VideoWriterImpl>(encoderCallback, frameSize, codec, fps, colorFormat, stream);
397+ return createVideoWriter (fileName, frameSize, codec, fps, colorFormat, EncoderParams (), encoderCallback, stream);
376398}
377399
378400Ptr<VideoWriter> createVideoWriter (const String& fileName, const Size frameSize, const Codec codec, const double fps, const ColorFormat colorFormat,
379401 const EncoderParams& params, Ptr<EncoderCallback> encoderCallback, const Stream& stream)
380402{
381- encoderCallback = encoderCallback ? encoderCallback : new RawVideoWriter (fileName);
403+ CV_Assert (params.idrPeriod >= params.gopLength );
404+ if (!encoderCallback) {
405+ // required until PR for raw video encapsulation is merged and windows dll is updated
406+ #ifndef WIN32 // remove #define and keep code once merged
407+ try {
408+ encoderCallback = new FFmpegVideoWriter (fileName, codec, fps, frameSize, params.idrPeriod );
409+ }
410+ catch (...)
411+ #endif
412+ {
413+ encoderCallback = new RawVideoWriter (fileName);
414+ }
415+ }
382416 return makePtr<VideoWriterImpl>(encoderCallback, frameSize, codec, fps, colorFormat, params, stream);
383417}
384418
0 commit comments