From 85df2c6b1ba427635dc46966a0f8f4a7c973412a Mon Sep 17 00:00:00 2001 From: zaki Date: Thu, 22 Jun 2023 13:20:50 +0530 Subject: [PATCH 1/6] 1. Added motion vector frame as 2nd output from the module. 2. Added Props to enable or disable motion vectors. 3. Added tests for it --- base/CMakeLists.txt | 1 - base/include/H264EncoderV4L2.h | 10 +- base/include/H264EncoderV4L2Helper.h | 33 +++-- base/src/H264EncoderV4L2.cpp | 32 ++--- base/src/H264EncoderV4L2Helper.cpp | 140 +++++++++++++++++++-- base/test/h264encoderv4l2_tests.cpp | 142 ++++++++++++++++++++-- base/test/h264encoderv4l2helper_tests.cpp | 136 --------------------- 7 files changed, 309 insertions(+), 185 deletions(-) delete mode 100755 base/test/h264encoderv4l2helper_tests.cpp diff --git a/base/CMakeLists.txt b/base/CMakeLists.txt index 8019945ff..f9d14b705 100755 --- a/base/CMakeLists.txt +++ b/base/CMakeLists.txt @@ -467,7 +467,6 @@ IF (ENABLE_ARM64) test/jpegdecoderl4tm_tests.cpp # test/l4tm_dec_enc_1_tests.cpp #todo this test needs to be improved to add to jetson suite test/opencvresize_tests.cpp - test/h264encoderv4l2helper_tests.cpp test/h264encoderv4l2_tests.cpp test/nvarguscamerahelper_tests.cpp test/nvarguscamera_tests.cpp diff --git a/base/include/H264EncoderV4L2.h b/base/include/H264EncoderV4L2.h index 8b5db5f8f..19c0319a7 100644 --- a/base/include/H264EncoderV4L2.h +++ b/base/include/H264EncoderV4L2.h @@ -7,12 +7,15 @@ class H264EncoderV4L2Helper; class H264EncoderV4L2Props : public ModuleProps { public: - H264EncoderV4L2Props(): targetKbps(1024) + H264EncoderV4L2Props(bool _enableMotionVectors = false, int _motionVectorThreshold = 5): targetKbps(1024) { - + enableMotionVectors = _enableMotionVectors; + motionVectorThreshold = _motionVectorThreshold; } uint32_t targetKbps; + bool enableMotionVectors = false; + int motionVectorThreshold = 5; }; class H264EncoderV4L2 : public Module @@ -37,5 +40,6 @@ class H264EncoderV4L2 : public Module H264EncoderV4L2Props mProps; framemetadata_sp mOutputMetadata; - std::string mOutputPinId; + std::string motionVectorFramePinId; + std::string h264FrameOutputPinId; }; diff --git a/base/include/H264EncoderV4L2Helper.h b/base/include/H264EncoderV4L2Helper.h index 6f0c120f6..d1d1ef776 100644 --- a/base/include/H264EncoderV4L2Helper.h +++ b/base/include/H264EncoderV4L2Helper.h @@ -1,19 +1,18 @@ #pragma once +#include +#include "ExtFrame.h" #include "AV4L2ElementPlane.h" #include "V4L2CUYUV420Converter.h" - -#include "ExtFrame.h" -#include +#include "v4l2_nv_extensions.h" class H264EncoderV4L2Helper { public: - typedef std::function SendFrame; + typedef std::function SendFrameContainer; + static std::shared_ptr create(enum v4l2_memory memType, uint32_t pixelFormat, uint32_t width, uint32_t height, uint32_t step, uint32_t bitrate, bool enableMotionVectors, int motionVectorThreshold, uint32_t fps, std::string h264FrameOutputPinId, std::string motionVectorFramePinId, framemetadata_sp h264Metadata, std::function makeFrame, std::function makeFrameTrim, SendFrameContainer sendFrameContainer); - static std::shared_ptr create(enum v4l2_memory memType, uint32_t pixelFormat, uint32_t width, uint32_t height, uint32_t step, uint32_t bitrate, uint32_t fps, SendFrame sendFrame); - - H264EncoderV4L2Helper(enum v4l2_memory memType, uint32_t pixelFormat, uint32_t width, uint32_t height, uint32_t step, uint32_t bitrate, uint32_t fps, SendFrame sendFrame); + H264EncoderV4L2Helper(enum v4l2_memory memType, uint32_t pixelFormat, uint32_t width, uint32_t height, uint32_t step, uint32_t bitrate, bool enableMotionVectors, int motionVectorThreshold, uint32_t fps,std::string h264FrameOutputPinId, std::string motionVectorFramePinId, framemetadata_sp h264Metadata, std::function makeFrame, std::function makeFrameTrim, SendFrameContainer sendFrameContainer); ~H264EncoderV4L2Helper(); void stop(); @@ -32,6 +31,8 @@ class H264EncoderV4L2Helper void setLevel(); void setFrameRate(uint32_t framerate_num, uint32_t framerate_den); + int setExtControlsMV(v4l2_ext_controls &ctl); + int enableMotionVectorReporting(); void initEncoderParams(uint32_t bitrate, uint32_t fps); int setExtControls(v4l2_ext_control &control); @@ -39,15 +40,25 @@ class H264EncoderV4L2Helper void reuseCatureBuffer(ExtFrame *pointer, uint32_t index, std::shared_ptr self); bool processEOS(); - + int getExtControls(v4l2_ext_controls &ctl); + int getMotionVectors(uint32_t buffer_index, + v4l2_ctrl_videoenc_outputbuf_metadata_MV &enc_mv_metadata); + void serializeMotionVectors(v4l2_ctrl_videoenc_outputbuf_metadata_MV enc_mv_metadata, frame_container &frames); private: std::shared_ptr mSelf; int mFD; std::unique_ptr mOutputPlane; std::unique_ptr mCapturePlane; - boost::object_pool frame_opool; - SendFrame mSendFrame; - + SendFrameContainer mSendFrameContainer; + int mWidth = 0; + int mHeight = 0; + bool enableMotionVectors; + int motionVectorThreshold; + std::string h264FrameOutputPinId; + std::string motionVectorFramePinId; + framemetadata_sp h264Metadata; + std::function makeFrame; + std::function makeFrameTrim; std::unique_ptr mConverter; }; \ No newline at end of file diff --git a/base/src/H264EncoderV4L2.cpp b/base/src/H264EncoderV4L2.cpp index 4f3eefa3a..d2b941cd1 100644 --- a/base/src/H264EncoderV4L2.cpp +++ b/base/src/H264EncoderV4L2.cpp @@ -5,12 +5,15 @@ #include "Frame.h" #include "Logger.h" #include "Utils.h" +#include "H264Metadata.h" #include "AIPExceptions.h" H264EncoderV4L2::H264EncoderV4L2(H264EncoderV4L2Props props) : Module(TRANSFORM, "H264EncoderV4L2", props), mProps(props) { - mOutputMetadata = framemetadata_sp(new FrameMetadata(FrameMetadata::H264_DATA)); - mOutputPinId = addOutputPin(mOutputMetadata); + mOutputMetadata = framemetadata_sp(new H264Metadata(0, 0)); + auto motionVectorOutputMetadata = framemetadata_sp(new FrameMetadata(FrameMetadata::OVERLAY_INFO_IMAGE)); + h264FrameOutputPinId = addOutputPin(mOutputMetadata); + motionVectorFramePinId = addOutputPin(motionVectorOutputMetadata); } H264EncoderV4L2::~H264EncoderV4L2() @@ -55,15 +58,10 @@ bool H264EncoderV4L2::validateInputPins() bool H264EncoderV4L2::validateOutputPins() { - if (getNumberOfOutputPins() != 1) - { - LOG_ERROR << "<" << getId() << ">::validateOutputPins size is expected to be 1. Actual<" << getNumberOfOutputPins() << ">"; - return false; - } framemetadata_sp metadata = getFirstOutputMetadata(); FrameMetadata::FrameType frameType = metadata->getFrameType(); - if (frameType != FrameMetadata::H264_DATA) + if (frameType != FrameMetadata::H264_DATA && frameType != FrameMetadata::OVERLAY_INFO_IMAGE) { LOG_ERROR << "<" << getId() << ">::validateOutputPins input frameType is expected to be H264_DATA. Actual<" << frameType << ">"; return false; @@ -144,12 +142,18 @@ bool H264EncoderV4L2::processSOS(frame_sp &frame) v4l2MemType = V4L2_MEMORY_DMABUF; } - mHelper = H264EncoderV4L2Helper::create(v4l2MemType, pixelFormat, width, height, step, 1024 * mProps.targetKbps, 30, [&](frame_sp &frame) -> void { - frame->setMetadata(mOutputMetadata); - - frame_container frames; - frames.insert(make_pair(mOutputPinId, frame)); - send(frames); + auto h264OutMetadata = framemetadata_sp(new H264Metadata(width, height)); + auto h264Metadata = FrameMetadataFactory::downcast(h264OutMetadata); + h264Metadata->setData(*h264Metadata); + Module::setMetadata(h264FrameOutputPinId, h264OutMetadata); + + mHelper = H264EncoderV4L2Helper::create(v4l2MemType, pixelFormat, width, height, step, 1024 * mProps.targetKbps, mProps.enableMotionVectors, mProps.motionVectorThreshold, 30,h264FrameOutputPinId, motionVectorFramePinId, h264OutMetadata, + [&](size_t size, string& pinId) + { return makeFrame(size, pinId); }, + [&](frame_sp& frame, size_t& size, string& pinId) + { return makeFrame(frame, size, pinId); }, + [&](frame_container &frameContainer) -> void { + send(frameContainer); }); return true; diff --git a/base/src/H264EncoderV4L2Helper.cpp b/base/src/H264EncoderV4L2Helper.cpp index 693148840..cf682a929 100644 --- a/base/src/H264EncoderV4L2Helper.cpp +++ b/base/src/H264EncoderV4L2Helper.cpp @@ -1,9 +1,10 @@ -#include "H264EncoderV4L2Helper.h" -#include "v4l2_nv_extensions.h" - +#include +#include "Overlay.h" #include "Logger.h" #include "AIPExceptions.h" +#include "H264EncoderV4L2Helper.h" + inline bool checkv4l2(int ret, int iLine, const char *szFile, std::string message, bool raiseException) { if (ret < 0) @@ -23,9 +24,9 @@ inline bool checkv4l2(int ret, int iLine, const char *szFile, std::string messag #define CHECKV4L2(call, message, raiseException) checkv4l2(call, __LINE__, __FILE__, message, raiseException) -std::shared_ptr H264EncoderV4L2Helper::create(enum v4l2_memory memType, uint32_t pixelFormat, uint32_t width, uint32_t height, uint32_t step, uint32_t bitrate, uint32_t fps, SendFrame sendFrame) +std::shared_ptr H264EncoderV4L2Helper::create(enum v4l2_memory memType, uint32_t pixelFormat, uint32_t width, uint32_t height, uint32_t step, uint32_t bitrate, bool enableMotionVectors, int motionVectorThreshold, uint32_t fps, std::string h264FrameOutputPinId, std::string motionVectorFramePinId, framemetadata_sp h264Metadata, std::function makeFrame, std::function makeFrameTrim, SendFrameContainer sendFrameContainer) { - auto instance = std::make_shared(memType, pixelFormat, width, height, step, bitrate, fps, sendFrame); + auto instance = std::make_shared(memType, pixelFormat, width, height, step, bitrate, enableMotionVectors, motionVectorThreshold, fps,h264FrameOutputPinId, motionVectorFramePinId, h264Metadata, makeFrame, makeFrameTrim, sendFrameContainer); instance->setSelf(instance); return instance; @@ -36,7 +37,7 @@ void H264EncoderV4L2Helper::setSelf(std::shared_ptr &self mSelf = self; } -H264EncoderV4L2Helper::H264EncoderV4L2Helper(enum v4l2_memory memType, uint32_t pixelFormat, uint32_t width, uint32_t height, uint32_t step, uint32_t bitrate, uint32_t fps, SendFrame sendFrame) : mSendFrame(sendFrame), mFD(-1) +H264EncoderV4L2Helper::H264EncoderV4L2Helper(enum v4l2_memory memType, uint32_t pixelFormat, uint32_t width, uint32_t height, uint32_t step, uint32_t bitrate, bool _enableMotionVectors, int _motionVectorThreshold, uint32_t fps, std::string _h264FrameOutputPinId, std::string _motionVectorFramePinId, framemetadata_sp _h264Metadata, std::function _makeFrame, std::function _makeFrameTrim, SendFrameContainer sendFrameContainer) : mSendFrameContainer(sendFrameContainer), mFD(-1), mWidth(width), mHeight(height), enableMotionVectors(_enableMotionVectors), motionVectorThreshold(_motionVectorThreshold), h264FrameOutputPinId(_h264FrameOutputPinId), motionVectorFramePinId(_motionVectorFramePinId), h264Metadata(_h264Metadata), makeFrame(_makeFrame), makeFrameTrim(_makeFrameTrim) { initV4L2(); @@ -124,12 +125,47 @@ void H264EncoderV4L2Helper::initV4L2() } } + +int +H264EncoderV4L2Helper::setExtControlsMV(v4l2_ext_controls &ctl) +{ + int ret; + + ret = v4l2_ioctl(mFD, VIDIOC_S_EXT_CTRLS, &ctl); + + return ret; +} + + +int +H264EncoderV4L2Helper::enableMotionVectorReporting() +{ + struct v4l2_ext_control control; + struct v4l2_ext_controls ctrls; + + memset(&control, 0, sizeof(control)); + memset(&ctrls, 0, sizeof(ctrls)); + + ctrls.count = 1; + ctrls.controls = &control; + ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG; + + control.id = V4L2_CID_MPEG_VIDEOENC_ENABLE_METADATA_MV; + control.value = 1; + + setExtControlsMV(ctrls); +} + void H264EncoderV4L2Helper::initEncoderParams(uint32_t bitrate, uint32_t fps) { setBitrate(bitrate); setProfile(); setLevel(); setFrameRate(fps, 1); + if(enableMotionVectors) + { + enableMotionVectorReporting(); + } } void H264EncoderV4L2Helper::setBitrate(uint32_t bitrate) @@ -200,10 +236,100 @@ int H264EncoderV4L2Helper::setExtControls(v4l2_ext_control &control) return v4l2_ioctl(mFD, VIDIOC_S_EXT_CTRLS, &ctrls); } +int +H264EncoderV4L2Helper::getExtControls(v4l2_ext_controls &ctl) +{ + int ret; + + ret = v4l2_ioctl(mFD, VIDIOC_G_EXT_CTRLS, &ctl); + + return ret; +} + +int +H264EncoderV4L2Helper::getMotionVectors(uint32_t buffer_index, + v4l2_ctrl_videoenc_outputbuf_metadata_MV &enc_mv_metadata) +{ + v4l2_ctrl_video_metadata metadata; + struct v4l2_ext_control control; + struct v4l2_ext_controls ctrls; + + ctrls.count = 1; + ctrls.controls = &control; + ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG; + + metadata.buffer_index = buffer_index; + metadata.VideoEncMetadataMV = &enc_mv_metadata; + + control.id = V4L2_CID_MPEG_VIDEOENC_METADATA_MV; + control.string = (char *)&metadata; + + getExtControls(ctrls); +} + +void H264EncoderV4L2Helper::serializeMotionVectors(v4l2_ctrl_videoenc_outputbuf_metadata_MV enc_mv_metadata, frame_container &frames) +{ + uint32_t numMVs = enc_mv_metadata.bufSize / sizeof(MVInfo); + MVInfo *pInfo = enc_mv_metadata.pMVInfo; + + std::vector circleOverlays; + CompositeOverlay compositeOverlay; + + int totalMacroblockInRow = floor(mWidth / 16); + auto motionVectorFrame = makeFrame(1024 * 1024 * 3, motionVectorFramePinId); + uint32_t *frameBuffer = reinterpret_cast(motionVectorFrame->data()); + size_t mCount = 0; + for (uint32_t i = 0; i < numMVs; i++, pInfo++) + { + + if (abs(pInfo->mv_x) > motionVectorThreshold || abs(pInfo->mv_y) > motionVectorThreshold) + { + auto tempY = floor(i / totalMacroblockInRow); + auto y = tempY * 16 + 8; + auto tempX = floor(i % totalMacroblockInRow); + auto x = tempX * 16 + 8; + CircleOverlay circleOverlay; + circleOverlay.x1 = x; + circleOverlay.y1 = y; + circleOverlay.radius = 1; + frameBuffer[mCount] = static_cast(x); + frameBuffer[mCount + 1] = static_cast(y); + frameBuffer[mCount + 2] = 1; + circleOverlays.push_back(circleOverlay); + } + } + + for (auto &circleOverlay : circleOverlays) + { + compositeOverlay.add(&circleOverlay); + } + + if (circleOverlays.size()) + { + DrawingOverlay drawingOverlay; + drawingOverlay.add(&compositeOverlay); + auto getSerializeSize = drawingOverlay.mGetSerializeSize(); + getSerializeSize += 100; + auto trimmedMotionVectorFrame = makeFrameTrim(motionVectorFrame, getSerializeSize, motionVectorFramePinId); + drawingOverlay.serialize(trimmedMotionVectorFrame); + frames.insert(make_pair(motionVectorFramePinId, trimmedMotionVectorFrame)); + } +} void H264EncoderV4L2Helper::capturePlaneDQCallback(AV4L2Buffer *buffer) { auto frame = frame_sp(frame_opool.construct(buffer->planesInfo[0].data, buffer->v4l2_buf.m.planes[0].bytesused), std::bind(&H264EncoderV4L2Helper::reuseCatureBuffer, this, std::placeholders::_1, buffer->getIndex(), mSelf)); - mSendFrame(frame); + frame->setMetadata(h264Metadata); + frame_container frames; + frames.insert(make_pair(h264FrameOutputPinId, frame)); + + if (enableMotionVectors) + { + v4l2_ctrl_videoenc_outputbuf_metadata_MV enc_mv_metadata; + getMotionVectors(buffer->v4l2_buf.index, enc_mv_metadata); + serializeMotionVectors(enc_mv_metadata, frames); + } + + mSendFrameContainer(frames); mConverter->releaseFrame(); } diff --git a/base/test/h264encoderv4l2_tests.cpp b/base/test/h264encoderv4l2_tests.cpp index 0b4a882cf..8b36d4bd1 100755 --- a/base/test/h264encoderv4l2_tests.cpp +++ b/base/test/h264encoderv4l2_tests.cpp @@ -3,13 +3,17 @@ #include "PipeLine.h" #include "H264EncoderV4L2.h" #include "FileReaderModule.h" -#include "FileWriterModule.h" #include "FrameMetadata.h" #include "Frame.h" #include "Logger.h" #include "StatSink.h" #include "CudaMemCopy.h" +#include "ExternalSinkModule.h" #include "RTSPPusher.h" +#include "Overlay.h" +#include "OverlayModule.h" +#include "H264Metadata.h" +#include "FramesMuxer.h" #include "test_utils.h" @@ -30,12 +34,12 @@ BOOST_AUTO_TEST_CASE(yuv420_640x360) auto encoder = boost::shared_ptr(new H264EncoderV4L2(encoderProps)); fileReader->setNext(encoder); - auto fileWriter = boost::shared_ptr(new FileWriterModule(FileWriterModuleProps("./data/testOutput/Raw_YUV420_640x360.h264", true))); - encoder->setNext(fileWriter); + auto sink = boost::shared_ptr(new ExternalSinkModule()); + encoder->setNext(sink); BOOST_TEST(fileReader->init()); BOOST_TEST(encoder->init()); - BOOST_TEST(fileWriter->init()); + BOOST_TEST(sink->init()); fileReader->play(true); @@ -44,10 +48,11 @@ BOOST_AUTO_TEST_CASE(yuv420_640x360) { fileReader->step(); encoder->step(); - fileWriter->step(); + auto frames = sink->pop(); + auto outputFrame = frames.begin()->second; + std::string fileName = "/data/testOutput/h264EncoderV4l2/Raw_YUV420_640x360_" + to_string(i) + ".h264"; + Test_Utils::saveOrCompare(fileName.c_str(), const_cast(static_cast(outputFrame->data())), outputFrame->size(), 0); } - - Test_Utils::saveOrCompare("./data/testOutput/Raw_YUV420_640x360.h264", 0); } BOOST_AUTO_TEST_CASE(rgb24_1280x720, *boost::unit_test::disabled()) @@ -71,13 +76,13 @@ BOOST_AUTO_TEST_CASE(rgb24_1280x720, *boost::unit_test::disabled()) auto encoder = boost::shared_ptr(new H264EncoderV4L2(encoderProps)); copy->setNext(encoder); - auto fileWriter = boost::shared_ptr(new FileWriterModule(FileWriterModuleProps("./data/testOutput/Raw_RGB24_1280x720.h264", true))); - encoder->setNext(fileWriter); + auto sink = boost::shared_ptr(new ExternalSinkModule()); + encoder->setNext(sink); BOOST_TEST(fileReader->init()); BOOST_TEST(copy->init()); BOOST_TEST(encoder->init()); - BOOST_TEST(fileWriter->init()); + BOOST_TEST(sink->init()); fileReader->play(true); @@ -87,10 +92,11 @@ BOOST_AUTO_TEST_CASE(rgb24_1280x720, *boost::unit_test::disabled()) fileReader->step(); copy->step(); encoder->step(); - fileWriter->step(); + auto frames = sink->pop(); + auto outputFrame = frames.begin()->second; + Test_Utils::saveOrCompare("./data/testOutput/Raw_RGB24_1280x720.h264", const_cast(static_cast(outputFrame->data())), outputFrame->size(), 0); } - - Test_Utils::saveOrCompare("./data/testOutput/Raw_RGB24_1280x720.h264", 0); + } BOOST_AUTO_TEST_CASE(yuv420_640x360_profiling, *boost::unit_test::disabled()) @@ -212,4 +218,114 @@ BOOST_AUTO_TEST_CASE(encodepush, *boost::unit_test::disabled()) LOG_INFO << "TEST DONE"; } +BOOST_AUTO_TEST_CASE(encode_and_extract_motion_vectors) +{ + // metadata is known + auto width = 640; + auto height = 360; + + auto fileReader = boost::shared_ptr(new FileReaderModule(FileReaderModuleProps("./data/Raw_YUV420_640x360/Image???_YUV420.raw"))); + auto metadata = framemetadata_sp(new RawImagePlanarMetadata(width, height, ImageMetadata::ImageType::YUV420, size_t(0), CV_8U)); + auto rawImagePin = fileReader->addOutputPin(metadata); + + H264EncoderV4L2Props encoderProps; + encoderProps.targetKbps = 1024; + encoderProps.enableMotionVectors = true; + auto encoder = boost::shared_ptr(new H264EncoderV4L2(encoderProps)); + fileReader->setNext(encoder); + + auto sink = boost::shared_ptr(new ExternalSinkModule()); + encoder->setNext(sink); + + BOOST_TEST(fileReader->init()); + BOOST_TEST(encoder->init()); + BOOST_TEST(sink->init()); + + fileReader->play(true); + + for (auto i = 0; i < 40; i++) + { + fileReader->step(); + encoder->step(); + auto frames = sink->pop(); + for (auto it = frames.cbegin(); it != frames.cend(); it++) + { + auto metadata = it->second->getMetadata(); + auto frameType = metadata->getFrameType(); + auto outputFrame = it->second; + if (frameType == FrameMetadata::H264_DATA) + { + std::string fileName = "./data/testOutput/h264EncoderH264Frames/frame_640x360" + to_string(i) + ".h264"; + Test_Utils::saveOrCompare(fileName.c_str(), const_cast(static_cast(outputFrame->data())), outputFrame->size(), 0); + } + else if(frameType == FrameMetadata::OVERLAY_INFO_IMAGE) + { + DrawingOverlay drawOverlay; + drawOverlay.deserialize(outputFrame); + auto list = drawOverlay.getList(); + + for (auto primitive1 : list) + { + if (primitive1->primitiveType == Primitive::COMPOSITE) + { + CompositeOverlay *mCompositeOverlay1 = static_cast(primitive1); + + auto compositeList1 = mCompositeOverlay1->getList(); + + for (auto primitive2 : compositeList1) + { + BOOST_TEST(primitive2->primitiveType == Primitive::CIRCLE); + } + } + } + } + } + } +} + +BOOST_AUTO_TEST_CASE(encode_and_extract_motion_vector_overlay, , *boost::unit_test::disabled()) +{ + // metadata is known + auto width = 640; + auto height = 360; + + auto fileReader = boost::shared_ptr(new FileReaderModule(FileReaderModuleProps("./data/Raw_YUV420_640x360/Image???_YUV420.raw"))); + auto metadata = framemetadata_sp(new RawImagePlanarMetadata(width, height, ImageMetadata::ImageType::YUV420, size_t(0), CV_8U)); + auto rawImagePin = fileReader->addOutputPin(metadata); + + H264EncoderV4L2Props encoderProps; + encoderProps.targetKbps = 1024; + encoderProps.enableMotionVectors = true; + auto encoder = boost::shared_ptr(new H264EncoderV4L2(encoderProps)); + fileReader->setNext(encoder); + + auto muxer = boost::shared_ptr(new FramesMuxer()); + fileReader->setNext(muxer); + encoder->setNext(muxer); + + auto overlay = boost::shared_ptr(new OverlayModule(OverlayModuleProps())); + muxer->setNext(overlay) + + auto sink = boost::shared_ptr(new ExternalSinkModule()); + overlay->setNext(sink); + + BOOST_TEST(fileReader->init()); + BOOST_TEST(encoder->init()); + BOOST_TEST(muxer->init()); + BOOST_TEST(overlay->init()); + BOOST_TEST(sink->init()); + + fileReader->play(true); + + for (auto i = 0; i < 40; i++) + { + fileReader->step(); + encoder->step(); + muxer->step(); + muxer->step(); + overlay->step(); + auto frames = sink->pop(); + } +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/base/test/h264encoderv4l2helper_tests.cpp b/base/test/h264encoderv4l2helper_tests.cpp deleted file mode 100755 index 8c9b248f9..000000000 --- a/base/test/h264encoderv4l2helper_tests.cpp +++ /dev/null @@ -1,136 +0,0 @@ -#include - -#include "RawImagePlanarMetadata.h" -#include "H264EncoderV4L2Helper.h" -#include "FrameFactory.h" -#include "Frame.h" -#include "Logger.h" - -#include "test_utils.h" - -#include "nvbuf_utils.h" - -BOOST_AUTO_TEST_SUITE(h264encoderv4l2helper_tests) - -BOOST_AUTO_TEST_CASE(yuv420_black) -{ - auto width = 1280; - auto height = 720; - auto imageSizeY = width * height; - auto imageSize = (imageSizeY * 3) >> 1; - - auto data = new uint8_t[imageSize]; - memset(data, 0, imageSizeY); - memset(data + imageSizeY, 128, imageSizeY >> 1); - - auto inputFrame = boost::shared_ptr(new ExtFrame(data, imageSize)); - - auto helper = H264EncoderV4L2Helper::create(V4L2_MEMORY_MMAP, V4L2_PIX_FMT_YUV420M, width, height, width, 4*1024*1024, 30, [](frame_sp& frame) -> void { - LOG_INFO << frame->size(); - } ); - - for (auto i = 0; i < 100; i++) - { - helper->process(inputFrame); - } - - boost::this_thread::sleep_for(boost::chrono::seconds(5)); - helper->stop(); - helper.reset(); - - delete[] data; -} - -BOOST_AUTO_TEST_CASE(yuv420_black_dmabuf) -{ - auto width = 1280; - auto height = 720; - - auto imageSize = (width * height * 3) >> 1; - - auto metadata = framemetadata_sp(new RawImagePlanarMetadata(width, height, ImageMetadata::ImageType::YUV420, size_t(0), CV_8U, FrameMetadata::MemType::DMABUF)); - auto frameFactory = framefactory_sp(new FrameFactory(metadata, 10)); - - auto inputFrame = frameFactory->create(imageSize, frameFactory); - - auto helper = H264EncoderV4L2Helper::create(V4L2_MEMORY_DMABUF, V4L2_PIX_FMT_YUV420M, width, height, width, 4*1024*1024, 30, [](frame_sp& frame) -> void { - LOG_DEBUG << frame->size(); - } ); - - for (auto i = 0; i < 100; i++) - { - helper->process(inputFrame); - } - - boost::this_thread::sleep_for(boost::chrono::seconds(5)); - helper->stop(); - helper.reset(); -} - -BOOST_AUTO_TEST_CASE(rgb24_black) -{ - auto width = 1280; - auto height = 720; - auto step = width * 3; - auto imageSize = step * height; - - uint8_t* data; - cudaMalloc(&data, imageSize); - cudaMemset(data, 0, imageSize); - cudaDeviceSynchronize(); - - auto inputFrame = boost::shared_ptr(new ExtFrame(data, imageSize)); - - auto helper = H264EncoderV4L2Helper::create(V4L2_MEMORY_MMAP, V4L2_PIX_FMT_RGB24, width, height, step, 4*1024*1024, 30, [](frame_sp& frame) -> void { - LOG_INFO << frame->size(); - } ); - - for (auto i = 0; i < 100; i++) - { - helper->process(inputFrame); - } - - boost::this_thread::sleep_for(boost::chrono::seconds(5)); - helper->stop(); - helper.reset(); - - cudaFree(data); -} - -BOOST_AUTO_TEST_CASE(memory_cache_free_test) -{ - frame_sp cacheFrame; - - { - auto width = 1280; - auto height = 720; - auto imageSizeY = width * height; - auto imageSize = (imageSizeY * 3) >> 1; - - auto data = new uint8_t[imageSize]; - memset(data, 0, imageSizeY); - memset(data + imageSizeY, 128, imageSizeY >> 1); - - auto inputFrame = boost::shared_ptr(new ExtFrame(data, imageSize)); - - auto helper = H264EncoderV4L2Helper::create(V4L2_MEMORY_MMAP, V4L2_PIX_FMT_YUV420M, width, height, width, 4 * 1024 * 1024, 30, [&](frame_sp &frame) -> void { - cacheFrame = frame; - }); - - for (auto i = 0; i < 10; i++) - { - helper->process(inputFrame); - } - - boost::this_thread::sleep_for(boost::chrono::seconds(1)); - helper->stop(); - helper.reset(); - - delete[] data; - } - - LOG_DEBUG << cacheFrame->data() << "<>" << cacheFrame->size(); - cacheFrame.reset(); -} - -BOOST_AUTO_TEST_SUITE_END() From cbdb83cf685473bea27d4d1620587747e987540b Mon Sep 17 00:00:00 2001 From: zaki Date: Thu, 22 Jun 2023 15:00:49 +0530 Subject: [PATCH 2/6] removed comma --- base/test/h264encoderv4l2_tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/test/h264encoderv4l2_tests.cpp b/base/test/h264encoderv4l2_tests.cpp index 8b36d4bd1..26621f4d6 100755 --- a/base/test/h264encoderv4l2_tests.cpp +++ b/base/test/h264encoderv4l2_tests.cpp @@ -283,7 +283,7 @@ BOOST_AUTO_TEST_CASE(encode_and_extract_motion_vectors) } } -BOOST_AUTO_TEST_CASE(encode_and_extract_motion_vector_overlay, , *boost::unit_test::disabled()) +BOOST_AUTO_TEST_CASE(encode_and_extract_motion_vector_overlay,*boost::unit_test::disabled()) { // metadata is known auto width = 640; From 339a85f96869291fa18af32948990afa5e8110bb Mon Sep 17 00:00:00 2001 From: zaki Date: Thu, 22 Jun 2023 18:37:56 +0530 Subject: [PATCH 3/6] added semicolom --- base/test/h264encoderv4l2_tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/test/h264encoderv4l2_tests.cpp b/base/test/h264encoderv4l2_tests.cpp index 26621f4d6..8ad4242f3 100755 --- a/base/test/h264encoderv4l2_tests.cpp +++ b/base/test/h264encoderv4l2_tests.cpp @@ -304,7 +304,7 @@ BOOST_AUTO_TEST_CASE(encode_and_extract_motion_vector_overlay,*boost::unit_test: encoder->setNext(muxer); auto overlay = boost::shared_ptr(new OverlayModule(OverlayModuleProps())); - muxer->setNext(overlay) + muxer->setNext(overlay); auto sink = boost::shared_ptr(new ExternalSinkModule()); overlay->setNext(sink); From 913de10ef1240a941d963763d1e8a63524fa17a4 Mon Sep 17 00:00:00 2001 From: zaki kochargi <97148049+mohammedzakikochargi@users.noreply.github.com> Date: Fri, 11 Aug 2023 16:00:17 +0530 Subject: [PATCH 4/6] update the the testOutput path --- base/test/h264encoderv4l2_tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/test/h264encoderv4l2_tests.cpp b/base/test/h264encoderv4l2_tests.cpp index 8ad4242f3..1698d5292 100755 --- a/base/test/h264encoderv4l2_tests.cpp +++ b/base/test/h264encoderv4l2_tests.cpp @@ -50,7 +50,7 @@ BOOST_AUTO_TEST_CASE(yuv420_640x360) encoder->step(); auto frames = sink->pop(); auto outputFrame = frames.begin()->second; - std::string fileName = "/data/testOutput/h264EncoderV4l2/Raw_YUV420_640x360_" + to_string(i) + ".h264"; + std::string fileName = "./data/testOutput/h264EncoderV4l2/Raw_YUV420_640x360_" + to_string(i) + ".h264"; Test_Utils::saveOrCompare(fileName.c_str(), const_cast(static_cast(outputFrame->data())), outputFrame->size(), 0); } } From 36e852001a3a45ce46009e99c76a87304cfd262a Mon Sep 17 00:00:00 2001 From: zaki Date: Mon, 21 Aug 2023 14:45:11 +0530 Subject: [PATCH 5/6] Addressed PR comments --- base/include/H264EncoderV4L2.h | 1 - base/include/H264EncoderV4L2Helper.h | 2 +- base/src/H264EncoderV4L2.cpp | 4 +-- base/src/H264EncoderV4L2Helper.cpp | 11 +++---- base/test/h264encoderv4l2_tests.cpp | 46 ---------------------------- 5 files changed, 6 insertions(+), 58 deletions(-) diff --git a/base/include/H264EncoderV4L2.h b/base/include/H264EncoderV4L2.h index 19c0319a7..694dcad1c 100644 --- a/base/include/H264EncoderV4L2.h +++ b/base/include/H264EncoderV4L2.h @@ -39,7 +39,6 @@ class H264EncoderV4L2 : public Module std::shared_ptr mHelper; H264EncoderV4L2Props mProps; - framemetadata_sp mOutputMetadata; std::string motionVectorFramePinId; std::string h264FrameOutputPinId; }; diff --git a/base/include/H264EncoderV4L2Helper.h b/base/include/H264EncoderV4L2Helper.h index d1d1ef776..71aa96868 100644 --- a/base/include/H264EncoderV4L2Helper.h +++ b/base/include/H264EncoderV4L2Helper.h @@ -4,7 +4,7 @@ #include "ExtFrame.h" #include "AV4L2ElementPlane.h" #include "V4L2CUYUV420Converter.h" -#include "v4l2_nv_extensions.h" +#include class H264EncoderV4L2Helper { diff --git a/base/src/H264EncoderV4L2.cpp b/base/src/H264EncoderV4L2.cpp index d2b941cd1..e22a248ca 100644 --- a/base/src/H264EncoderV4L2.cpp +++ b/base/src/H264EncoderV4L2.cpp @@ -10,7 +10,7 @@ H264EncoderV4L2::H264EncoderV4L2(H264EncoderV4L2Props props) : Module(TRANSFORM, "H264EncoderV4L2", props), mProps(props) { - mOutputMetadata = framemetadata_sp(new H264Metadata(0, 0)); + auto mOutputMetadata = framemetadata_sp(new H264Metadata(0, 0)); auto motionVectorOutputMetadata = framemetadata_sp(new FrameMetadata(FrameMetadata::OVERLAY_INFO_IMAGE)); h264FrameOutputPinId = addOutputPin(mOutputMetadata); motionVectorFramePinId = addOutputPin(motionVectorOutputMetadata); @@ -143,8 +143,6 @@ bool H264EncoderV4L2::processSOS(frame_sp &frame) } auto h264OutMetadata = framemetadata_sp(new H264Metadata(width, height)); - auto h264Metadata = FrameMetadataFactory::downcast(h264OutMetadata); - h264Metadata->setData(*h264Metadata); Module::setMetadata(h264FrameOutputPinId, h264OutMetadata); mHelper = H264EncoderV4L2Helper::create(v4l2MemType, pixelFormat, width, height, step, 1024 * mProps.targetKbps, mProps.enableMotionVectors, mProps.motionVectorThreshold, 30,h264FrameOutputPinId, motionVectorFramePinId, h264OutMetadata, diff --git a/base/src/H264EncoderV4L2Helper.cpp b/base/src/H264EncoderV4L2Helper.cpp index cf682a929..8be1256ab 100644 --- a/base/src/H264EncoderV4L2Helper.cpp +++ b/base/src/H264EncoderV4L2Helper.cpp @@ -275,26 +275,23 @@ void H264EncoderV4L2Helper::serializeMotionVectors(v4l2_ctrl_videoenc_outputbuf_ std::vector circleOverlays; CompositeOverlay compositeOverlay; - int totalMacroblockInRow = floor(mWidth / 16); + int totalMacroblockInRow = floor(mWidth / 16); // Tells about the total number of macro blocks in each row. auto motionVectorFrame = makeFrame(1024 * 1024 * 3, motionVectorFramePinId); uint32_t *frameBuffer = reinterpret_cast(motionVectorFrame->data()); size_t mCount = 0; - for (uint32_t i = 0; i < numMVs; i++, pInfo++) + for (uint32_t i = 0; i < numMVs; i++, pInfo++) // numMVs is the total macroblock in the frame. { if (abs(pInfo->mv_x) > motionVectorThreshold || abs(pInfo->mv_y) > motionVectorThreshold) { - auto tempY = floor(i / totalMacroblockInRow); - auto y = tempY * 16 + 8; + auto tempY = floor(i / totalMacroblockInRow); // i represents current macroblock , To get the y offset of macroblock the current macroblock is divided by macroblock across width. + auto y = tempY * 16 + 8; // Here every macroblock is of 16x16 , So multiply it by 16. To get to the centre of the macroblock add it by 8. auto tempX = floor(i % totalMacroblockInRow); auto x = tempX * 16 + 8; CircleOverlay circleOverlay; circleOverlay.x1 = x; circleOverlay.y1 = y; circleOverlay.radius = 1; - frameBuffer[mCount] = static_cast(x); - frameBuffer[mCount + 1] = static_cast(y); - frameBuffer[mCount + 2] = 1; circleOverlays.push_back(circleOverlay); } } diff --git a/base/test/h264encoderv4l2_tests.cpp b/base/test/h264encoderv4l2_tests.cpp index 1698d5292..c0c609825 100755 --- a/base/test/h264encoderv4l2_tests.cpp +++ b/base/test/h264encoderv4l2_tests.cpp @@ -282,50 +282,4 @@ BOOST_AUTO_TEST_CASE(encode_and_extract_motion_vectors) } } } - -BOOST_AUTO_TEST_CASE(encode_and_extract_motion_vector_overlay,*boost::unit_test::disabled()) -{ - // metadata is known - auto width = 640; - auto height = 360; - - auto fileReader = boost::shared_ptr(new FileReaderModule(FileReaderModuleProps("./data/Raw_YUV420_640x360/Image???_YUV420.raw"))); - auto metadata = framemetadata_sp(new RawImagePlanarMetadata(width, height, ImageMetadata::ImageType::YUV420, size_t(0), CV_8U)); - auto rawImagePin = fileReader->addOutputPin(metadata); - - H264EncoderV4L2Props encoderProps; - encoderProps.targetKbps = 1024; - encoderProps.enableMotionVectors = true; - auto encoder = boost::shared_ptr(new H264EncoderV4L2(encoderProps)); - fileReader->setNext(encoder); - - auto muxer = boost::shared_ptr(new FramesMuxer()); - fileReader->setNext(muxer); - encoder->setNext(muxer); - - auto overlay = boost::shared_ptr(new OverlayModule(OverlayModuleProps())); - muxer->setNext(overlay); - - auto sink = boost::shared_ptr(new ExternalSinkModule()); - overlay->setNext(sink); - - BOOST_TEST(fileReader->init()); - BOOST_TEST(encoder->init()); - BOOST_TEST(muxer->init()); - BOOST_TEST(overlay->init()); - BOOST_TEST(sink->init()); - - fileReader->play(true); - - for (auto i = 0; i < 40; i++) - { - fileReader->step(); - encoder->step(); - muxer->step(); - muxer->step(); - overlay->step(); - auto frames = sink->pop(); - } -} - BOOST_AUTO_TEST_SUITE_END() From d39ede2920042273a20d41d81530dff059517a19 Mon Sep 17 00:00:00 2001 From: zaki Date: Wed, 23 Aug 2023 18:08:32 +0530 Subject: [PATCH 6/6] Addressed PR commnets --- base/include/H264EncoderV4L2Helper.h | 5 ++--- base/src/H264EncoderV4L2.cpp | 2 -- base/src/H264EncoderV4L2Helper.cpp | 19 ++++++++----------- base/test/h264encoderv4l2_tests.cpp | 4 +++- 4 files changed, 13 insertions(+), 17 deletions(-) diff --git a/base/include/H264EncoderV4L2Helper.h b/base/include/H264EncoderV4L2Helper.h index 71aa96868..43e4fdd10 100644 --- a/base/include/H264EncoderV4L2Helper.h +++ b/base/include/H264EncoderV4L2Helper.h @@ -10,9 +10,9 @@ class H264EncoderV4L2Helper { public: typedef std::function SendFrameContainer; - static std::shared_ptr create(enum v4l2_memory memType, uint32_t pixelFormat, uint32_t width, uint32_t height, uint32_t step, uint32_t bitrate, bool enableMotionVectors, int motionVectorThreshold, uint32_t fps, std::string h264FrameOutputPinId, std::string motionVectorFramePinId, framemetadata_sp h264Metadata, std::function makeFrame, std::function makeFrameTrim, SendFrameContainer sendFrameContainer); + static std::shared_ptr create(enum v4l2_memory memType, uint32_t pixelFormat, uint32_t width, uint32_t height, uint32_t step, uint32_t bitrate, bool enableMotionVectors, int motionVectorThreshold, uint32_t fps, std::string h264FrameOutputPinId, std::string motionVectorFramePinId, framemetadata_sp h264Metadata, std::function makeFrame, SendFrameContainer sendFrameContainer); - H264EncoderV4L2Helper(enum v4l2_memory memType, uint32_t pixelFormat, uint32_t width, uint32_t height, uint32_t step, uint32_t bitrate, bool enableMotionVectors, int motionVectorThreshold, uint32_t fps,std::string h264FrameOutputPinId, std::string motionVectorFramePinId, framemetadata_sp h264Metadata, std::function makeFrame, std::function makeFrameTrim, SendFrameContainer sendFrameContainer); + H264EncoderV4L2Helper(enum v4l2_memory memType, uint32_t pixelFormat, uint32_t width, uint32_t height, uint32_t step, uint32_t bitrate, bool enableMotionVectors, int motionVectorThreshold, uint32_t fps,std::string h264FrameOutputPinId, std::string motionVectorFramePinId, framemetadata_sp h264Metadata, std::function makeFrame, SendFrameContainer sendFrameContainer); ~H264EncoderV4L2Helper(); void stop(); @@ -59,6 +59,5 @@ class H264EncoderV4L2Helper std::string motionVectorFramePinId; framemetadata_sp h264Metadata; std::function makeFrame; - std::function makeFrameTrim; std::unique_ptr mConverter; }; \ No newline at end of file diff --git a/base/src/H264EncoderV4L2.cpp b/base/src/H264EncoderV4L2.cpp index e22a248ca..75f3d542c 100644 --- a/base/src/H264EncoderV4L2.cpp +++ b/base/src/H264EncoderV4L2.cpp @@ -148,8 +148,6 @@ bool H264EncoderV4L2::processSOS(frame_sp &frame) mHelper = H264EncoderV4L2Helper::create(v4l2MemType, pixelFormat, width, height, step, 1024 * mProps.targetKbps, mProps.enableMotionVectors, mProps.motionVectorThreshold, 30,h264FrameOutputPinId, motionVectorFramePinId, h264OutMetadata, [&](size_t size, string& pinId) { return makeFrame(size, pinId); }, - [&](frame_sp& frame, size_t& size, string& pinId) - { return makeFrame(frame, size, pinId); }, [&](frame_container &frameContainer) -> void { send(frameContainer); }); diff --git a/base/src/H264EncoderV4L2Helper.cpp b/base/src/H264EncoderV4L2Helper.cpp index 8be1256ab..2103ca238 100644 --- a/base/src/H264EncoderV4L2Helper.cpp +++ b/base/src/H264EncoderV4L2Helper.cpp @@ -24,9 +24,9 @@ inline bool checkv4l2(int ret, int iLine, const char *szFile, std::string messag #define CHECKV4L2(call, message, raiseException) checkv4l2(call, __LINE__, __FILE__, message, raiseException) -std::shared_ptr H264EncoderV4L2Helper::create(enum v4l2_memory memType, uint32_t pixelFormat, uint32_t width, uint32_t height, uint32_t step, uint32_t bitrate, bool enableMotionVectors, int motionVectorThreshold, uint32_t fps, std::string h264FrameOutputPinId, std::string motionVectorFramePinId, framemetadata_sp h264Metadata, std::function makeFrame, std::function makeFrameTrim, SendFrameContainer sendFrameContainer) +std::shared_ptr H264EncoderV4L2Helper::create(enum v4l2_memory memType, uint32_t pixelFormat, uint32_t width, uint32_t height, uint32_t step, uint32_t bitrate, bool enableMotionVectors, int motionVectorThreshold, uint32_t fps, std::string h264FrameOutputPinId, std::string motionVectorFramePinId, framemetadata_sp h264Metadata, std::function makeFrame, SendFrameContainer sendFrameContainer) { - auto instance = std::make_shared(memType, pixelFormat, width, height, step, bitrate, enableMotionVectors, motionVectorThreshold, fps,h264FrameOutputPinId, motionVectorFramePinId, h264Metadata, makeFrame, makeFrameTrim, sendFrameContainer); + auto instance = std::make_shared(memType, pixelFormat, width, height, step, bitrate, enableMotionVectors, motionVectorThreshold, fps,h264FrameOutputPinId, motionVectorFramePinId, h264Metadata, makeFrame, sendFrameContainer); instance->setSelf(instance); return instance; @@ -37,7 +37,7 @@ void H264EncoderV4L2Helper::setSelf(std::shared_ptr &self mSelf = self; } -H264EncoderV4L2Helper::H264EncoderV4L2Helper(enum v4l2_memory memType, uint32_t pixelFormat, uint32_t width, uint32_t height, uint32_t step, uint32_t bitrate, bool _enableMotionVectors, int _motionVectorThreshold, uint32_t fps, std::string _h264FrameOutputPinId, std::string _motionVectorFramePinId, framemetadata_sp _h264Metadata, std::function _makeFrame, std::function _makeFrameTrim, SendFrameContainer sendFrameContainer) : mSendFrameContainer(sendFrameContainer), mFD(-1), mWidth(width), mHeight(height), enableMotionVectors(_enableMotionVectors), motionVectorThreshold(_motionVectorThreshold), h264FrameOutputPinId(_h264FrameOutputPinId), motionVectorFramePinId(_motionVectorFramePinId), h264Metadata(_h264Metadata), makeFrame(_makeFrame), makeFrameTrim(_makeFrameTrim) +H264EncoderV4L2Helper::H264EncoderV4L2Helper(enum v4l2_memory memType, uint32_t pixelFormat, uint32_t width, uint32_t height, uint32_t step, uint32_t bitrate, bool _enableMotionVectors, int _motionVectorThreshold, uint32_t fps, std::string _h264FrameOutputPinId, std::string _motionVectorFramePinId, framemetadata_sp _h264Metadata, std::function _makeFrame, SendFrameContainer sendFrameContainer) : mSendFrameContainer(sendFrameContainer), mFD(-1), mWidth(width), mHeight(height), enableMotionVectors(_enableMotionVectors), motionVectorThreshold(_motionVectorThreshold), h264FrameOutputPinId(_h264FrameOutputPinId), motionVectorFramePinId(_motionVectorFramePinId), h264Metadata(_h264Metadata), makeFrame(_makeFrame) { initV4L2(); @@ -276,9 +276,6 @@ void H264EncoderV4L2Helper::serializeMotionVectors(v4l2_ctrl_videoenc_outputbuf_ CompositeOverlay compositeOverlay; int totalMacroblockInRow = floor(mWidth / 16); // Tells about the total number of macro blocks in each row. - auto motionVectorFrame = makeFrame(1024 * 1024 * 3, motionVectorFramePinId); - uint32_t *frameBuffer = reinterpret_cast(motionVectorFrame->data()); - size_t mCount = 0; for (uint32_t i = 0; i < numMVs; i++, pInfo++) // numMVs is the total macroblock in the frame. { @@ -305,11 +302,11 @@ void H264EncoderV4L2Helper::serializeMotionVectors(v4l2_ctrl_videoenc_outputbuf_ { DrawingOverlay drawingOverlay; drawingOverlay.add(&compositeOverlay); - auto getSerializeSize = drawingOverlay.mGetSerializeSize(); - getSerializeSize += 100; - auto trimmedMotionVectorFrame = makeFrameTrim(motionVectorFrame, getSerializeSize, motionVectorFramePinId); - drawingOverlay.serialize(trimmedMotionVectorFrame); - frames.insert(make_pair(motionVectorFramePinId, trimmedMotionVectorFrame)); + auto serializeSize = drawingOverlay.mGetSerializeSize(); + serializeSize += 100; + auto motionVectorFrame = makeFrame(serializeSize, motionVectorFramePinId); + drawingOverlay.serialize(motionVectorFrame); + frames.insert(make_pair(motionVectorFramePinId, motionVectorFrame)); } } void H264EncoderV4L2Helper::capturePlaneDQCallback(AV4L2Buffer *buffer) diff --git a/base/test/h264encoderv4l2_tests.cpp b/base/test/h264encoderv4l2_tests.cpp index c0c609825..01a9e19be 100755 --- a/base/test/h264encoderv4l2_tests.cpp +++ b/base/test/h264encoderv4l2_tests.cpp @@ -243,6 +243,7 @@ BOOST_AUTO_TEST_CASE(encode_and_extract_motion_vectors) fileReader->play(true); + int motionVectorFramesCount = 0; for (auto i = 0; i < 40; i++) { fileReader->step(); @@ -263,7 +264,7 @@ BOOST_AUTO_TEST_CASE(encode_and_extract_motion_vectors) DrawingOverlay drawOverlay; drawOverlay.deserialize(outputFrame); auto list = drawOverlay.getList(); - + motionVectorFramesCount++; for (auto primitive1 : list) { if (primitive1->primitiveType == Primitive::COMPOSITE) @@ -281,5 +282,6 @@ BOOST_AUTO_TEST_CASE(encode_and_extract_motion_vectors) } } } + BOOST_TEST(motionVectorFramesCount == 32); } BOOST_AUTO_TEST_SUITE_END()