From 6fab6a3e2feb3f24d772aa151c5f43d447ec2010 Mon Sep 17 00:00:00 2001 From: RashmiShinde21 Date: Tue, 14 Oct 2025 09:57:01 +0530 Subject: [PATCH 1/9] changes for creating the EGLImage from the DMA buffer, addded some logs, arguscamera->DMAtoHostCopy->VirtualCamera works with no errors --- base/CMakeLists.txt | 43 ++++---- base/include/DMAUtils.h | 25 ++++- base/src/DMAFDWrapper.cpp | 178 +++++++++++++++--------------- base/src/DMAUtils.cpp | 124 +++++++++++---------- base/src/NvArgusCamera.cpp | 7 +- base/src/NvArgusCameraHelper.cpp | 65 ++++++++++- base/test/nvarguscamera_tests.cpp | 42 ++++--- base/vcpkg-configuration.json | 2 +- base/vcpkg.json | 2 +- 9 files changed, 289 insertions(+), 199 deletions(-) diff --git a/base/CMakeLists.txt b/base/CMakeLists.txt index 46ef22106..106c0d1a1 100755 --- a/base/CMakeLists.txt +++ b/base/CMakeLists.txt @@ -54,7 +54,7 @@ find_package(LibLZMA REQUIRED) find_package(FFMPEG REQUIRED) find_package(ZXing CONFIG REQUIRED) find_package(bigint CONFIG REQUIRED) -find_package(SFML COMPONENTS system window audio graphics CONFIG REQUIRED) +find_package(SFML COMPONENTS System Window Audio Graphics CONFIG REQUIRED) find_package(whisper CONFIG REQUIRED) @@ -188,15 +188,15 @@ SET(CORE_FILES src/Split.cpp src/Utils.cpp src/FIndexStrategy.cpp - src/AudioCaptureSrc.cpp + #src/AudioCaptureSrc.cpp src/QRReader.cpp - src/Mp4WriterSink.cpp + #src/Mp4WriterSink.cpp src/Mp4WriterSinkUtils.cpp src/MultimediaQueueXform.cpp src/Mp4ReaderSource.cpp src/RTSPClientSrc.cpp src/RTSPClientSrc.cpp - src/MotionVectorExtractor.cpp + #src/MotionVectorExtractor.cpp src/OverlayModule.cpp src/OrderedCacheOfFiles.cpp src/SimpleControlModule.cpp @@ -409,24 +409,24 @@ SET(CUDA_IP_FILES IF(ENABLE_ARM64) SET(CUDA_IP_FILES ${CUDA_IP_FILES} - # src/JPEGDecoderL4TM.cpp - # src/JPEGDecoderL4TMHelper.cpp + src/JPEGDecoderL4TM.cpp + src/JPEGDecoderL4TMHelper.cpp src/JPEGEncoderL4TM.cpp src/JPEGEncoderL4TMHelper.cpp src/AV4L2Buffer.cpp src/AV4L2ElementPlane.cpp - # src/H264EncoderV4L2Helper.cpp - # src/V4L2CUYUV420Converter.cpp - # src/H264EncoderV4L2.cpp + src/H264EncoderV4L2Helper.cpp + src/V4L2CUYUV420Converter.cpp + src/H264EncoderV4L2.cpp src/DMAFDWrapper.cpp - # src/NvArgusCameraHelper.cpp - # src/NvArgusCamera.cpp + src/NvArgusCameraHelper.cpp + src/NvArgusCamera.cpp # src/NvV4L2Camera.cpp # src/NvV4L2CameraHelper.cpp # src/EglRenderer.cpp # src/NvEglRenderer.cpp src/DMAUtils.cpp - # src/NvTransform.cpp + src/NvTransform.cpp src/ApraEGLDisplay.cpp src/DMAFDToHostCopy.cpp src/H264DecoderV4L2Helper.cpp @@ -531,16 +531,16 @@ target_include_directories ( aprapipes PRIVATE IF (ENABLE_ARM64) SET(ARM64_UT_FILES - # test/jpegencoderl4tm_tests.cpp - # test/jpegdecoderl4tm_tests.cpp + test/jpegencoderl4tm_tests.cpp + 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/opencvresize_tests.cpp # test/h264encoderv4l2_tests.cpp - # test/nvarguscamerahelper_tests.cpp - # test/nvarguscamera_tests.cpp + #test/nvarguscamerahelper_tests.cpp + test/nvarguscamera_tests.cpp # test/nvv4l2camera_test.cpp # test/nvv4l2camerahelper_test.cpp - # test/nvtransform_tests.cpp + test/nvtransform_tests.cpp # test/eglrenderer_test.cpp # test/cuda_arm_tests.cpp # test/apraegldisplay_tests.cpp @@ -577,7 +577,7 @@ ENDIF(ENABLE_CUDA) SET(UT_FILES test/utmain.cpp test/unit_tests.cpp - test/cv_memory_leaks_tests.cpp + #test/cv_memory_leaks_tests.cpp-- test/module_tests.cpp # test/calchistogramcv_tests.cpp # test/filenamestrategy_tests.cpp @@ -692,7 +692,10 @@ target_link_libraries(aprapipesut ZLIB::ZLIB LibLZMA::LibLZMA bigint::bigint - sfml-audio + SFML::Audio + SFML::System + SFML::Window + SFML::Graphics whisper::whisper /usr/lib/aarch64-linux-gnu/libEGL.so.1.1.0 diff --git a/base/include/DMAUtils.h b/base/include/DMAUtils.h index f7991ee8d..58ec6cb7b 100644 --- a/base/include/DMAUtils.h +++ b/base/include/DMAUtils.h @@ -1,14 +1,27 @@ #pragma once - #include "EGL/egl.h" #include "cudaEGL.h" - +#include // Include the new header for NvBufSurface class Frame; class DMAUtils { public: - static uint8_t* getCudaPtrForFD(int fd, EGLImageKHR eglImage, CUgraphicsResource *pResource, CUeglFrame eglFrame, EGLDisplay eglDisplay); - static uint8_t* getCudaPtr(EGLImageKHR eglImage, CUgraphicsResource *pResource, CUeglFrame eglFrame, EGLDisplay eglDisplay); - static void freeCudaPtr(EGLImageKHR eglImage, CUgraphicsResource *pResource, EGLDisplay eglDisplay); -}; \ No newline at end of file + /** + * @brief Registers an EGLImage as a CUDA resource and maps it to a CUeglFrame. + * @param eglImage The EGL image handle. + * @param pResource Pointer to the CUgraphicsResource handle. + * @param pEglFrame Pointer to the CUeglFrame structure to fill. + * @return A pointer to the CUDA mapped buffer, or nullptr on failure. + */ + static uint8_t* getCudaPtr(EGLImageKHR eglImage, CUgraphicsResource *pResource, CUeglFrame *pEglFrame); + + /** + * @brief Unregisters a CUDA resource, unmaps the EGLImage, and destroys the NvBufSurface. + * @param eglImage The EGL image handle (no longer needed, but kept for legacy reference). + * @param pResource Pointer to the CUgraphicsResource handle. + * @param surf Pointer to the NvBufSurface. + * @param eglDisplay The EGL display handle. + */ + static void freeCudaPtr(EGLImageKHR eglImage, CUgraphicsResource *pResource, NvBufSurface *surf, EGLDisplay eglDisplay); +}; diff --git a/base/src/DMAFDWrapper.cpp b/base/src/DMAFDWrapper.cpp index 9c1912184..ab4acd93c 100644 --- a/base/src/DMAFDWrapper.cpp +++ b/base/src/DMAFDWrapper.cpp @@ -7,12 +7,12 @@ #include "cuda_runtime.h" DMAFDWrapper *DMAFDWrapper::create(int index, int width, int height, - NvBufSurfaceColorFormat colorFormat, - NvBufSurfaceLayout layout, EGLDisplay eglDisplay) +NvBufSurfaceColorFormat colorFormat, +NvBufSurfaceLayout layout, EGLDisplay eglDisplay) { DMAFDWrapper *buffer = new DMAFDWrapper(index, eglDisplay); if (!buffer) - { + { return nullptr; } @@ -46,6 +46,7 @@ DMAFDWrapper *DMAFDWrapper::create(int index, int width, int height, // JP5: Set hostPtr to mapped address for plane 0 buffer->hostPtr = buffer->m_surf->surfaceList[0].mappedAddr.addr[0]; + if (colorFormat == NVBUF_COLOR_FORMAT_NV12 || colorFormat == NVBUF_COLOR_FORMAT_YUV420) { @@ -93,147 +94,142 @@ DMAFDWrapper *DMAFDWrapper::create(int index, int width, int height, buffer->hostPtrV = buffer->m_surf->surfaceList[0].mappedAddr.addr[2]; } + + // if (colorFormat != NvBufferColorFormat_UYVY) + //{ + // buffer->eglImage = NvEGLImageFromFd(eglDisplay, buffer->m_fd); + // if (buffer->eglImage == EGL_NO_IMAGE_KHR) + // { + // LOG_ERROR << "Failed to create eglImage"; + // delete buffer; + // return nullptr; + // } + if (NvBufSurfaceMapEglImage(buffer->m_surf, 0) != 0) { - // buffer->eglImage = NvEGLImageFromFd(eglDisplay, buffer->m_fd); - // if (buffer->eglImage == EGL_NO_IMAGE_KHR) - // { - // LOG_ERROR << "Failed to create eglImage"; - // delete buffer; - // return nullptr; - // } - - // cudaFree(0); - // buffer->cudaPtr = DMAUtils::getCudaPtr(buffer->eglImage, &buffer->pResource, buffer->eglFrame, eglDisplay); + LOG_ERROR << "NvBufSurfaceMapEglImage Error"; + // Clean up resources before exiting. + NvBufSurfaceDestroy(buffer->m_surf); + delete buffer; + return nullptr; } + buffer->eglImage = buffer->m_surf->surfaceList[0].mappedAddr.eglImage; + if (buffer->eglImage == EGL_NO_IMAGE_KHR) + { + LOG_ERROR << "Failed to create eglImage from NvBufSurface"; + NvBufSurfaceUnMapEglImage(buffer->m_surf, 0); // Unmap the EGL image. + NvBufSurfaceDestroy(buffer->m_surf); + delete buffer; + return nullptr; + } + // cudaFree(0); + // buffer->cudaPtr = DMAUtils::getCudaPtr(buffer->eglImage, &buffer->pResource, buffer->eglFrame, eglDisplay); + cudaFree(0); + buffer->cudaPtr = DMAUtils::getCudaPtr(buffer->eglImage, &buffer->pResource, &buffer->eglFrame); - return buffer; + + return buffer; } DMAFDWrapper::DMAFDWrapper(int _index, EGLDisplay _eglDisplay) : eglImage(EGL_NO_IMAGE_KHR), - m_fd(-1), - m_surf(nullptr), - index(_index), - eglDisplay(_eglDisplay), - hostPtr(nullptr), - hostPtrU(nullptr), - hostPtrV(nullptr), - cudaPtr(nullptr) +m_fd(-1), +m_surf(nullptr), +index(_index), +eglDisplay(_eglDisplay), +hostPtr(nullptr), +hostPtrU(nullptr), +hostPtrV(nullptr), +cudaPtr(nullptr) { } DMAFDWrapper::~DMAFDWrapper() { - if (eglImage != EGL_NO_IMAGE_KHR) - { - // cudaFree(0); - // DMAUtils::freeCudaPtr(eglImage, &pResource, eglDisplay); - } +if (eglImage != EGL_NO_IMAGE_KHR) +{ +// cudaFree(0); +// DMAUtils::freeCudaPtr(eglImage, &pResource, eglDisplay); +} - if (hostPtr) - { - auto res = NvBufSurfaceUnMap(getNvBufSurface(), 0, 0); - if (res) - { - LOG_ERROR << "NvBufSurfaceUnMap Error<>" << res; - } - } +if (hostPtr) +{ +auto res = NvBufSurfaceUnMap(getNvBufSurface(), 0, 0); +if (res) +{ +LOG_ERROR << "NvBufSurfaceUnMap Error<>" << res; +} +} - if (hostPtrU) - { - auto res = NvBufSurfaceUnMap(getNvBufSurface(), 0, 1); - if (res) - { - LOG_ERROR << "NvBufSurfaceUnMap Error<>" << res; - } - } +if (hostPtrU) +{ +auto res = NvBufSurfaceUnMap(getNvBufSurface(), 0, 1); +if (res) +{ +LOG_ERROR << "NvBufSurfaceUnMap Error<>" << res; +} +} - if (hostPtrV) - { - auto res = NvBufSurfaceUnMap(getNvBufSurface(), 0, 2); - if (res) - { - LOG_ERROR << "NvBufSurfaceUnMap Error<>" << res; - } - } +if (hostPtrV) +{ +auto res = NvBufSurfaceUnMap(getNvBufSurface(), 0, 2); +if (res) +{ +LOG_ERROR << "NvBufSurfaceUnMap Error<>" << res; +} +} - if (m_surf) - { - NvBufSurfaceDestroy(m_surf); - m_surf = nullptr; - m_fd = -1; - } +if (m_surf) +{ +NvBufSurfaceDestroy(m_surf); +m_surf = nullptr; +m_fd = -1; +} } void *DMAFDWrapper::getHostPtr() { - return hostPtr; +return hostPtr; } void *DMAFDWrapper::getHostPtrY() { - return getHostPtr(); +return getHostPtr(); } void *DMAFDWrapper::getHostPtrU() { - return hostPtrU; +return hostPtrU; } void *DMAFDWrapper::getHostPtrV() { - return hostPtrV; +return hostPtrV; } void *DMAFDWrapper::getHostPtrUV() { - return getHostPtrU(); +return getHostPtrU(); } void *DMAFDWrapper::getCudaPtr() const { - return cudaPtr; +return cudaPtr; } int DMAFDWrapper::getIndex() const { - return index; +return index; } const void *DMAFDWrapper::getClientData() const { - return clientData; +return clientData; } void DMAFDWrapper::setClientData(const void *_clientData) { - clientData = _clientData; -} -void DMAFDWrapper::refreshHostPointers() -{ - if (m_surf) { - hostPtr = m_surf->surfaceList[0].mappedAddr.addr[0]; - - // For NV12, use the actual mapped address for UV - if (m_surf->surfaceList[0].colorFormat == NVBUF_COLOR_FORMAT_NV12) { - hostPtrU = m_surf->surfaceList[0].mappedAddr.addr[1]; - if (hostPtrU == nullptr) { - // Fallback to calculated offset if addr[1] is NULL - uint32_t yPitch = m_surf->surfaceList[0].planeParams.pitch[0]; - uint32_t yHeight = m_surf->surfaceList[0].planeParams.height[0]; - hostPtrU = (uint8_t*)hostPtr + (yPitch * yHeight); - } - } else { - if (m_surf->surfaceList[0].planeParams.num_planes > 1) { - hostPtrU = m_surf->surfaceList[0].mappedAddr.addr[1]; - } - } - - if (m_surf->surfaceList[0].planeParams.num_planes > 2) { - hostPtrV = m_surf->surfaceList[0].mappedAddr.addr[2]; - } - } +clientData = _clientData; } diff --git a/base/src/DMAUtils.cpp b/base/src/DMAUtils.cpp index 61abfb2ab..b520efb81 100644 --- a/base/src/DMAUtils.cpp +++ b/base/src/DMAUtils.cpp @@ -1,60 +1,70 @@ #include "DMAUtils.h" #include "Logger.h" +#include +#include -// uint8_t* DMAUtils::getCudaPtrForFD(int fd, EGLImageKHR eglImage, CUgraphicsResource *pResource, CUeglFrame eglFrame, EGLDisplay eglDisplay){ -// eglImage = NvEGLImageFromFd(eglDisplay, fd); -// if (eglImage == NULL) -// { -// LOG_ERROR << "DID not find eglImage for File Descriptor"; -// return nullptr; -// } -// return getCudaPtr(eglImage, pResource, eglFrame, eglDisplay); -// } -// uint8_t* DMAUtils::getCudaPtr(EGLImageKHR eglImage, CUgraphicsResource *pResource, CUeglFrame eglFrame, EGLDisplay eglDisplay) -// { -// auto status = cuGraphicsEGLRegisterImage(pResource, eglImage, CU_GRAPHICS_MAP_RESOURCE_FLAGS_NONE); -// if (status != CUDA_SUCCESS) -// { -// LOG_ERROR << "cuGraphicsEGLRegisterImage failed: " << status << " cuda process stop"; -// return NULL; -// } - -// status = cuGraphicsResourceGetMappedEglFrame(&eglFrame, *pResource, 0, 0); -// if (status != CUDA_SUCCESS) -// { -// LOG_ERROR << "cuGraphicsSubResourceGetMappedArray failed status<" << status << ">"; -// return NULL; -// } - -// status = cuCtxSynchronize(); -// if (status != CUDA_SUCCESS) -// { -// LOG_ERROR << "cuCtxSynchronize failed status<" << status << ">"; -// return NULL; -// } - -// return static_cast(eglFrame.frame.pPitch[0]); -// } - -// void DMAUtils::freeCudaPtr(EGLImageKHR eglImage, CUgraphicsResource *pResource, EGLDisplay eglDisplay) -// { -// auto status = cuCtxSynchronize(); -// if (status != CUDA_SUCCESS) -// { -// LOG_ERROR << "cuCtxSynchronize failed after cc status<" << status << ">"; -// return; -// } - -// status = cuGraphicsUnregisterResource(*pResource); -// if (status != CUDA_SUCCESS) -// { -// LOG_ERROR << "cuGraphicsEGLUnRegisterResource failed: " << status; -// return; -// } - -// auto res = NvDestroyEGLImage(eglDisplay, eglImage); -// if (res) -// { -// LOG_ERROR << "NvDestroyEGLImage Error<>" << res; -// } -// } \ No newline at end of file +// Forward declaration of NvBufSurface to avoid header dependencies if possible +//struct _NvBufSurface; +//typedef struct _NvBufSurface NvBufSurface; + +// This function is the equivalent of the old getCudaPtr. +// It directly uses the EGLImageKHR, which is created externally now. +uint8_t* DMAUtils::getCudaPtr(EGLImageKHR eglImage, CUgraphicsResource *pResource, CUeglFrame *pEglFrame) +{ + // Register the EGL image as a CUDA graphics resource + auto status = cuGraphicsEGLRegisterImage(pResource, eglImage, CU_GRAPHICS_MAP_RESOURCE_FLAGS_NONE); + if (status != CUDA_SUCCESS) + { + LOG_ERROR << "cuGraphicsEGLRegisterImage failed: " << status << " cuda process stop"; + return NULL; + } + + // Get the mapped CUeglFrame from the resource + status = cuGraphicsResourceGetMappedEglFrame(pEglFrame, *pResource, 0, 0); + if (status != CUDA_SUCCESS) + { + LOG_ERROR << "cuGraphicsResourceGetMappedEglFrame failed status<" << status << ">"; + return NULL; + } + + status = cuCtxSynchronize(); + if (status != CUDA_SUCCESS) + { + LOG_ERROR << "cuCtxSynchronize failed status<" << status << ">"; + return NULL; + } + + return static_cast(pEglFrame->frame.pPitch[0]); +} + +// Updated freeCudaPtr function to handle cleanup for JetPack 6 +void DMAUtils::freeCudaPtr(EGLImageKHR eglImage, CUgraphicsResource *pResource, NvBufSurface *surf, EGLDisplay eglDisplay) +{ + auto status = cuCtxSynchronize(); + if (status != CUDA_SUCCESS) + { + LOG_ERROR << "cuCtxSynchronize failed after cc status<" << status << ">"; + // Continue cleanup even if sync fails + } + + status = cuGraphicsUnregisterResource(*pResource); + if (status != CUDA_SUCCESS) + { + LOG_ERROR << "cuGraphicsUnregisterResource failed: " << status; + // Continue cleanup even if unregister fails + } + + // Unmap the EGLImage + auto res_unmap_egl = NvBufSurfaceUnMapEglImage(surf, 0); + if (res_unmap_egl) + { + LOG_ERROR << "NvBufSurfaceUnMapEglImage Error: " << res_unmap_egl; + } + + // Destroy the NvBufSurface + auto res_destroy = NvBufSurfaceDestroy(surf); + if (res_destroy) + { + LOG_ERROR << "NvBufSurfaceDestroy Error: " << res_destroy; + } +} diff --git a/base/src/NvArgusCamera.cpp b/base/src/NvArgusCamera.cpp index 33e2a6574..938d36e5a 100755 --- a/base/src/NvArgusCamera.cpp +++ b/base/src/NvArgusCamera.cpp @@ -35,7 +35,12 @@ bool NvArgusCamera::init() frame_container frames; frames.insert(make_pair(mOutputPinId, frame)); send(frames); }, [&]() -> frame_sp { return makeFrame(); }); - mHelper->start(mProps.width, mProps.height, static_cast(mProps.fps), mProps.cameraId); + + if (!mHelper->start(mProps.width, mProps.height, static_cast(mProps.fps), mProps.cameraId)) + { + LOG_ERROR << "Failed to start camera helper"; + return false; + } return true; } diff --git a/base/src/NvArgusCameraHelper.cpp b/base/src/NvArgusCameraHelper.cpp index 969678c69..bfc543316 100644 --- a/base/src/NvArgusCameraHelper.cpp +++ b/base/src/NvArgusCameraHelper.cpp @@ -33,10 +33,29 @@ void NvArgusCameraHelper::sendFrame(Argus::Buffer *buffer) { Argus::IBuffer *iBuffer = Argus::interface_cast(buffer); auto ptr = const_cast(iBuffer->getClientData()); - auto frame = mQueuedFrames[ptr]; + + // DEBUG: Track frame lookup + LOG_INFO << "sendFrame: looking up dmaFDWrapper=" << ptr; + + auto frameIt = mQueuedFrames.find(ptr); + if (frameIt == mQueuedFrames.end()) { + LOG_ERROR << "sendFrame: FRAME NOT FOUND in mQueuedFrames! ptr=" << ptr + << " map_size=" << mQueuedFrames.size(); + return; + } + + auto frame = frameIt->second; + LOG_INFO << "sendFrame: found frame=" << frame.get() + << " use_count=" << frame.use_count() + << " before sending"; + mSendFrame(frame); + + LOG_INFO << "sendFrame: after mSendFrame, use_count=" << frame.use_count(); + std::lock_guard lock(mQueuedFramesMutex); - mQueuedFrames.erase(ptr); + auto erased = mQueuedFrames.erase(ptr); + LOG_INFO << "sendFrame: erased " << erased << " entries, remaining=" << mQueuedFrames.size(); } void NvArgusCameraHelper::operator()() @@ -53,7 +72,7 @@ void NvArgusCameraHelper::operator()() /* Timeout or error happen, exit */ break; } - + LOG_INFO << "AT operator to acquireBuffer to capture camera frames"<(frame->data()); + + // DEBUG: Track frame lifecycle + LOG_INFO << "queueFrameToCamera: frame.get()=" << frame.get() + << " dmaFDWrapper=" << dmaFDWrapper + << " use_count=" << frame.use_count() + << " clientData=" << dmaFDWrapper->getClientData(); Argus::IBufferOutputStream *stream = Argus::interface_cast(outputStream); auto status = stream->releaseBuffer(static_cast(const_cast(dmaFDWrapper->getClientData()))); @@ -76,7 +101,21 @@ bool NvArgusCameraHelper::queueFrameToCamera() } std::lock_guard lock(mQueuedFramesMutex); + + // DEBUG: Check if this wrapper is already in the map + auto existing = mQueuedFrames.find(dmaFDWrapper); + if (existing != mQueuedFrames.end()) { + LOG_ERROR << "DOUBLE MAP ENTRY! dmaFDWrapper=" << dmaFDWrapper + << " existing_frame=" << existing->second.get() + << " existing_use_count=" << existing->second.use_count() + << " new_frame=" << frame.get() + << " new_use_count=" << frame.use_count(); + } + mQueuedFrames[dmaFDWrapper] = frame; + LOG_INFO << "queueFrameToCamera: stored in map, total entries=" << mQueuedFrames.size(); + + return true; } boost::shared_ptr NvArgusCameraUtils::instance; @@ -157,6 +196,11 @@ bool NvArgusCameraHelper::start(uint32_t width, uint32_t height, uint32_t fps, i /* Create the OutputStream */ outputStream.reset(iCaptureSession->createOutputStream(streamSettings.get())); Argus::IBufferOutputStream *iBufferOutputStream = Argus::interface_cast(outputStream); + if (!iBufferOutputStream) + { + LOG_ERROR << "Failed to get Argus::IBufferOutputStream interface"; + return false; + } /* Create the Argus::BufferSettings object to configure Argus::Buffer creation */ Argus::UniqueObj bufferSettings(iBufferOutputStream->createBufferSettings()); @@ -180,8 +224,19 @@ bool NvArgusCameraHelper::start(uint32_t width, uint32_t height, uint32_t fps, i auto dmaFDWrapper = static_cast(frame->data()); - iBufferSettings->setEGLImage(dmaFDWrapper->getEGLImage()); - iBufferSettings->setEGLDisplay(dmaFDWrapper->getEGLDisplay()); + // Debug: Check EGL image validity + EGLImageKHR eglImg = dmaFDWrapper->getEGLImage(); + EGLDisplay eglDisp = dmaFDWrapper->getEGLDisplay(); + LOG_INFO<< "Buffer[" << i << "] EGLImage: " << eglImg << " (EGL_NO_IMAGE_KHR=" << EGL_NO_IMAGE_KHR << ")"; + LOG_INFO<< "Buffer[" << i << "] EGLDisplay: " << eglDisp; + LOG_INFO << "Buffer[" << i << "] DMA FD: " << dmaFDWrapper->getFd(); + + if (eglImg == EGL_NO_IMAGE_KHR) { + LOG_ERROR << "Buffer[" << i << "] EGLImage is EGL_NO_IMAGE_KHR - this will cause Argus createBuffer to fail"; + } + + iBufferSettings->setEGLImage(eglImg); + iBufferSettings->setEGLDisplay(eglDisp); buffers[i].reset(iBufferOutputStream->createBuffer(bufferSettings.get())); Argus::IBuffer *iBuffer = Argus::interface_cast(buffers[i]); if (!Argus::interface_cast(buffers[i])) diff --git a/base/test/nvarguscamera_tests.cpp b/base/test/nvarguscamera_tests.cpp index 6c999c1d5..27f744788 100755 --- a/base/test/nvarguscamera_tests.cpp +++ b/base/test/nvarguscamera_tests.cpp @@ -14,7 +14,7 @@ BOOST_AUTO_TEST_SUITE(nvarguscamera_tests) -BOOST_AUTO_TEST_CASE(basic, *boost::unit_test::disabled()) +/*BOOST_AUTO_TEST_CASE(basic, *boost::unit_test::disabled()) { auto argValue = Test_Utils::getArgValue("n", "1"); auto n_cams = atoi(argValue.c_str()); @@ -70,10 +70,14 @@ BOOST_AUTO_TEST_CASE(basic, *boost::unit_test::disabled()) p.term(); p.wait_for_all(); -} +}*/ -BOOST_AUTO_TEST_CASE(vcam_nv12, *boost::unit_test::disabled()) +BOOST_AUTO_TEST_CASE(vcam_nv12) { + LoggerProps logProps; + logProps.enableConsoleLog = true; + Logger::initLogger(logProps); + Logger::setLogLevel(boost::log::trivial::severity_level::trace); NvArgusCameraProps sourceProps(1280, 720); sourceProps.maxConcurrentFrames = 10; sourceProps.fps = 30; @@ -95,12 +99,12 @@ BOOST_AUTO_TEST_CASE(vcam_nv12, *boost::unit_test::disabled()) p.appendModule(source); BOOST_TEST(p.init()); - Logger::setLogLevel(boost::log::trivial::severity_level::info); + //Logger::setLogLevel(boost::log::trivial::severity_level::info); p.run_all_threaded(); - boost::this_thread::sleep_for(boost::chrono::seconds(1000)); - Logger::setLogLevel(boost::log::trivial::severity_level::error); + boost::this_thread::sleep_for(boost::chrono::seconds(10)); + ///Logger::setLogLevel(boost::log::trivial::severity_level::error); p.stop(); p.term(); @@ -108,15 +112,19 @@ BOOST_AUTO_TEST_CASE(vcam_nv12, *boost::unit_test::disabled()) p.wait_for_all(); } -BOOST_AUTO_TEST_CASE(vcam_yuv420, *boost::unit_test::disabled()) +BOOST_AUTO_TEST_CASE(vcam_yuv420) { + LoggerProps logProps; + logProps.enableConsoleLog = true; + Logger::initLogger(logProps); + Logger::setLogLevel(boost::log::trivial::severity_level::trace); NvArgusCameraProps sourceProps(1280, 720); sourceProps.maxConcurrentFrames = 10; sourceProps.fps = 30; auto source = boost::shared_ptr(new NvArgusCamera(sourceProps)); - auto copySource = boost::shared_ptr(new DMAFDToHostCopy); - source->setNext(copySource); + //auto copySource = boost::shared_ptr(new DMAFDToHostCopy); + //source->setNext(copySource); auto transform = boost::shared_ptr(new NvTransform(NvTransformProps(ImageMetadata::YUV420))); source->setNext(transform); @@ -139,12 +147,12 @@ BOOST_AUTO_TEST_CASE(vcam_yuv420, *boost::unit_test::disabled()) p.appendModule(source); BOOST_TEST(p.init()); - Logger::setLogLevel(boost::log::trivial::severity_level::info); + //Logger::setLogLevel(boost::log::trivial::severity_level::info); p.run_all_threaded(); - boost::this_thread::sleep_for(boost::chrono::seconds(100)); - Logger::setLogLevel(boost::log::trivial::severity_level::error); + boost::this_thread::sleep_for(boost::chrono::seconds(10)); + //Logger::setLogLevel(boost::log::trivial::severity_level::error); p.stop(); p.term(); @@ -152,7 +160,7 @@ BOOST_AUTO_TEST_CASE(vcam_yuv420, *boost::unit_test::disabled()) p.wait_for_all(); } -BOOST_AUTO_TEST_CASE(vcam, *boost::unit_test::disabled()) +BOOST_AUTO_TEST_CASE(vcam) { NvArgusCameraProps sourceProps(1280, 720); sourceProps.maxConcurrentFrames = 10; @@ -162,7 +170,7 @@ BOOST_AUTO_TEST_CASE(vcam, *boost::unit_test::disabled()) auto copySource = boost::shared_ptr(new DMAFDToHostCopy); source->setNext(copySource); - auto transform = boost::shared_ptr(new NvTransform(NvTransformProps(ImageMetadata::BGRA))); + auto transform = boost::shared_ptr(new NvTransform(NvTransformProps(ImageMetadata::RGBA))); source->setNext(transform); auto copy = boost::shared_ptr(new DMAFDToHostCopy); @@ -187,7 +195,7 @@ BOOST_AUTO_TEST_CASE(vcam, *boost::unit_test::disabled()) p.run_all_threaded(); - boost::this_thread::sleep_for(boost::chrono::seconds(100)); + boost::this_thread::sleep_for(boost::chrono::seconds(10)); Logger::setLogLevel(boost::log::trivial::severity_level::error); p.stop(); @@ -195,7 +203,7 @@ BOOST_AUTO_TEST_CASE(vcam, *boost::unit_test::disabled()) p.wait_for_all(); } - +/* BOOST_AUTO_TEST_CASE(encoder, *boost::unit_test::disabled()) { NvArgusCameraProps sourceProps(800, 800); @@ -274,6 +282,6 @@ BOOST_AUTO_TEST_CASE(encoderrtsppush, *boost::unit_test::disabled()) p.term(); p.wait_for_all(); -} +}*/ BOOST_AUTO_TEST_SUITE_END() diff --git a/base/vcpkg-configuration.json b/base/vcpkg-configuration.json index 5f8f8c262..a1fcd893b 100644 --- a/base/vcpkg-configuration.json +++ b/base/vcpkg-configuration.json @@ -6,7 +6,7 @@ "default-registry": { "kind": "git", "repository": "https://github.com/Apra-Labs/vcpkg.git", - "baseline": "a1c6d4f053281b8e961c24a0035903f5f9d66329" + "baseline": "6ba64191f73b82b71ffa5263b26189f7b2b82f92" }, "registries": [ { diff --git a/base/vcpkg.json b/base/vcpkg.json index 5750a984b..46b3e3591 100644 --- a/base/vcpkg.json +++ b/base/vcpkg.json @@ -2,7 +2,7 @@ "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg/master/scripts/vcpkg.schema.json", "name": "apra-pipes-cuda", "version": "0.0.1", - "builtin-baseline": "4658624c5f19c1b468b62fe13ed202514dfd463e", + "builtin-baseline": "6ba64191f73b82b71ffa5263b26189f7b2b82f92", "overrides": [ { "name": "ffmpeg", From 6341040fcf73c93d07c1a67406ed9efd2b92f76a Mon Sep 17 00:00:00 2001 From: RashmiShinde21 Date: Thu, 6 Nov 2025 09:38:07 +0530 Subject: [PATCH 2/9] added timeout to the select() call in the camera event loop. This presevnts indefinite blocking in case no camera events occur --- base/src/NvV4L2CameraHelper.cpp | 43 ++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/base/src/NvV4L2CameraHelper.cpp b/base/src/NvV4L2CameraHelper.cpp index 3911d84d9..f894f07f3 100644 --- a/base/src/NvV4L2CameraHelper.cpp +++ b/base/src/NvV4L2CameraHelper.cpp @@ -2,15 +2,19 @@ #include "DMAFDWrapper.h" #include "NvEglRenderer.h" #include "NvUtils.h" -#include "nvbuf_utils.h" #include "Logger.h" +#include +#include +#include +#include +#include NvV4L2CameraHelper::NvV4L2CameraHelper(SendFrame sendFrame,std::function _makeFrame) { // hardcoded device name and pixfmt which is fine for now mCamDevname = "/dev/video0"; mCamFD = -1; - mCamPixFmt = V4L2_PIX_FMT_UYVY; + mCamPixFmt = V4L2_PIX_FMT_YUYV; mRunning = false; mSendFrame = sendFrame; @@ -72,7 +76,7 @@ bool NvV4L2CameraHelper::cameraInitialize(bool isMirror) fmt.fmt.pix.height != mCamHeight || fmt.fmt.pix.pixelformat != mCamPixFmt) { - LOG_ERROR << "The desired format is not supported"; + LOG_ERROR << "The desired format is not supported"< 0 && mRunning) + /* Wait for camera event with timeout = 10 sec */ + while (select(fds + 1, &rset, NULL, NULL, &timeout) > 0 && mRunning) { - if (FD_ISSET(fds, &rset)) - { - struct v4l2_buffer v4l2_buf; + if (FD_ISSET(fds, &rset)) + { + struct v4l2_buffer v4l2_buf; /* Dequeue a camera buff */ memset(&v4l2_buf, 0, sizeof(v4l2_buf)); @@ -134,22 +142,28 @@ void NvV4L2CameraHelper::operator()() v4l2_buf.memory = V4L2_MEMORY_DMABUF; if (ioctl(mCamFD, VIDIOC_DQBUF, &v4l2_buf) < 0) { - LOG_ERROR << "Failed to dequeue camera buff"; + LOG_ERROR << "Failed to dequeue camera buffer"; break; } // lock std::lock_guard lock(mBufferFDMutex); - auto frameItr = mBufferFD.find(v4l2_buf.m.fd); - if(frameItr == mBufferFD.end()) + auto frameItr = mBufferFD.find(v4l2_buf.m.fd); + if (frameItr == mBufferFD.end()) { - LOG_FATAL << " mBufferFD failed. fd<" << v4l2_buf.m.fd << "> size<" << mBufferFD.size() << ">"; + LOG_FATAL << "mBufferFD failed. fd<" << v4l2_buf.m.fd << "> size<" << mBufferFD.size() << ">"; } mSendFrame(frameItr->second); mBufferFD.erase(frameItr); - } } + else + { + LOG_INFO<<"fd not set"; + } +} } + + bool NvV4L2CameraHelper::queueBufferToCamera() { @@ -157,6 +171,7 @@ bool NvV4L2CameraHelper::queueBufferToCamera() { auto frame = mMakeFrame(); if(!frame.get()){ + LOG_INFO<<"cannot create frames"; break; } auto dmaFDWrapper = static_cast(frame->data()); @@ -180,7 +195,7 @@ bool NvV4L2CameraHelper::queueBufferToCamera() std::lock_guard lock(mBufferFDMutex); mBufferFD.insert(make_pair(buf.m.fd, frame)); } - + if (ioctl(mCamFD, VIDIOC_QBUF, &buf) < 0){ LOG_ERROR << "Failed to enqueue buffers"; return false; From 2c425534561b33fe0248b0e522ea4f3a0e053b9a Mon Sep 17 00:00:00 2001 From: RashmiShinde21 Date: Thu, 6 Nov 2025 10:08:14 +0530 Subject: [PATCH 3/9] added capture and vcam_crop tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Added capture test to validate NvV4L2Camera → DMAFDToHostCopy → VirtualCameraSink pipeline - Added vcam_crop test with NvTransform cropping --- base/test/nvv4l2camera_test.cpp | 99 ++++++++++++++++++++------- base/test/nvv4l2camerahelper_test.cpp | 22 +++--- 2 files changed, 87 insertions(+), 34 deletions(-) diff --git a/base/test/nvv4l2camera_test.cpp b/base/test/nvv4l2camera_test.cpp index 8c8c1a339..23fe79e4d 100644 --- a/base/test/nvv4l2camera_test.cpp +++ b/base/test/nvv4l2camera_test.cpp @@ -14,7 +14,6 @@ BOOST_AUTO_TEST_SUITE(nvv4l2camera_tests) BOOST_AUTO_TEST_CASE(basic, *boost::unit_test::disabled()) { Logger::setLogLevel(boost::log::trivial::severity_level::info); - auto source = boost::shared_ptr(new NvV4L2Camera(NvV4L2CameraProps(640, 480, 10))); StatSinkProps sinkProps; @@ -36,12 +35,12 @@ BOOST_AUTO_TEST_CASE(basic, *boost::unit_test::disabled()) BOOST_AUTO_TEST_CASE(save, *boost::unit_test::disabled()) { - auto source = boost::shared_ptr(new NvV4L2Camera(NvV4L2CameraProps(1920, 1080, 10))); + auto source = boost::shared_ptr(new NvV4L2Camera(NvV4L2CameraProps(640, 480, 10))); auto copySource = boost::shared_ptr(new DMAFDToHostCopy); source->setNext(copySource); - - auto fileWriter = boost::shared_ptr(new FileWriterModule(FileWriterModuleProps("./data/testOutput/nvv4l2/frame_????.raw"))); + + auto fileWriter = boost::shared_ptr(new FileWriterModule(FileWriterModuleProps("./data/testOutput/nvv4l2/framenv4l2.raw",true))); copySource->setNext(fileWriter); PipeLine p("test"); @@ -61,41 +60,26 @@ BOOST_AUTO_TEST_CASE(save, *boost::unit_test::disabled()) p.wait_for_all(); } -BOOST_AUTO_TEST_CASE(vcam, *boost::unit_test::disabled()) +BOOST_AUTO_TEST_CASE(nvv4l2_transform, *boost::unit_test::disabled()) { Logger::setLogLevel(boost::log::trivial::severity_level::info); - auto source = boost::shared_ptr(new NvV4L2Camera(NvV4L2CameraProps(1280, 720, 10))); + auto source = boost::shared_ptr(new NvV4L2Camera(NvV4L2CameraProps(640, 480, 10))); auto copySource = boost::shared_ptr(new DMAFDToHostCopy); source->setNext(copySource); - auto transform = boost::shared_ptr(new NvTransform(NvTransformProps(ImageMetadata::YUV420))); + auto transform = boost::shared_ptr(new NvTransform(NvTransformProps(ImageMetadata::RGBA))); source->setNext(transform); auto copy = boost::shared_ptr(new DMAFDToHostCopy); transform->setNext(copy); - auto transform2 = boost::shared_ptr(new NvTransform(NvTransformProps(ImageMetadata::NV12))); - source->setNext(transform2); - - auto copy2 = boost::shared_ptr(new DMAFDToHostCopy); - transform2->setNext(copy2); - - // VirtualCameraSinkProps sinkProps("/dev/video10"); - // sinkProps.logHealth = true; - // sinkProps.logHealthFrequency = 100; - // auto sink = boost::shared_ptr(new VirtualCameraSink(sinkProps)); - // copy->setNext(sink); - - auto fileWriter1 = boost::shared_ptr(new FileWriterModule(FileWriterModuleProps("./data/testOutput/nvv4l2/uyvy_????.raw"))); + auto fileWriter1 = boost::shared_ptr(new FileWriterModule(FileWriterModuleProps("./data/testOutput/nvv4l2/uyvy.raw",true))); copySource->setNext(fileWriter1); - auto fileWriter2 = boost::shared_ptr(new FileWriterModule(FileWriterModuleProps("./data/testOutput/nvv4l2/yuv420_????.raw"))); + auto fileWriter2 = boost::shared_ptr(new FileWriterModule(FileWriterModuleProps("./data/testOutput/nvv4l2/rgba.raw",true))); copy->setNext(fileWriter2); - // auto sink = boost::shared_ptr(new EglRenderer(EglRendererProps(0, 0))); - // transform->setNext(sink); - PipeLine p("test"); p.appendModule(source); BOOST_TEST(p.init()); @@ -112,4 +96,71 @@ BOOST_AUTO_TEST_CASE(vcam, *boost::unit_test::disabled()) p.wait_for_all(); } +BOOST_AUTO_TEST_CASE(vcam_crop) +{ + LoggerProps logProps; + logProps.enableConsoleLog = true; + Logger::initLogger(logProps); + Logger::setLogLevel(boost::log::trivial::severity_level::trace); + auto source = boost::shared_ptr(new NvV4L2Camera(NvV4L2CameraProps(640, 480, 10))); + + auto transform = boost::shared_ptr(new NvTransform(NvTransformProps(ImageMetadata::RGBA,360,360,0,0))); + source->setNext(transform); + + auto copy = boost::shared_ptr(new DMAFDToHostCopy); + transform->setNext(copy); + + VirtualCameraSinkProps sinkProps("/dev/video10"); + sinkProps.logHealth = true; + sinkProps.logHealthFrequency = 100; + auto sink = boost::shared_ptr(new VirtualCameraSink(sinkProps)); + + auto fileWriter2 = boost::shared_ptr(new FileWriterModule(FileWriterModuleProps("./data/testOutput/nvv4l2/crop_640_360.raw", true))); + copy->setNext(fileWriter2); + fileWriter2->setNext(sink); + + PipeLine p("test"); + p.appendModule(source); + BOOST_TEST(p.init()); + + p.run_all_threaded(); + + boost::this_thread::sleep_for(boost::chrono::seconds(10)); + + p.stop(); + p.term(); + + p.wait_for_all(); +} + +BOOST_AUTO_TEST_CASE(capture) +{ + LoggerProps logProps; + logProps.enableConsoleLog = true; + Logger::initLogger(logProps); + Logger::setLogLevel(boost::log::trivial::severity_level::trace); + auto source = boost::shared_ptr(new NvV4L2Camera(NvV4L2CameraProps(3280, 2464, 10))); + + auto copy = boost::shared_ptr(new DMAFDToHostCopy); + VirtualCameraSinkProps sinkProps("/dev/video10"); + sinkProps.logHealth = true; + sinkProps.logHealthFrequency = 100; + auto sink = boost::shared_ptr(new VirtualCameraSink(sinkProps)); + + source->setNext(copy); + copy->setNext(sink); + + PipeLine p("test"); + p.appendModule(source); + BOOST_TEST(p.init()); + p.run_all_threaded(); + + boost::this_thread::sleep_for(boost::chrono::seconds(30)); + + p.stop(); + p.term(); + + p.wait_for_all(); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/base/test/nvv4l2camerahelper_test.cpp b/base/test/nvv4l2camerahelper_test.cpp index bacc0e360..8caf08f22 100644 --- a/base/test/nvv4l2camerahelper_test.cpp +++ b/base/test/nvv4l2camerahelper_test.cpp @@ -3,6 +3,7 @@ #include "Module.h" #include "DMAFDWrapper.h" #include "NvV4L2CameraHelper.h" +#include "DMAAllocator.h" #include "test_utils.h" #include "Logger.h" @@ -12,15 +13,16 @@ BOOST_AUTO_TEST_SUITE(nvv4l2camerahelper_tests) BOOST_AUTO_TEST_CASE(basic, *boost::unit_test::disabled()) { - uint32_t width = 640; - uint32_t height = 480; + uint32_t width = 3280; + uint32_t height = 2464; - auto framemetadata = framemetadata_sp(new RawImageMetadata(width, height, ImageMetadata::ImageType::UYVY, CV_8UC3, size_t(0), CV_8U, FrameMetadata::MemType::DMABUF)); + auto framemetadata = framemetadata_sp(new RawImageMetadata(FrameMetadata::MemType::DMABUF)); + DMAAllocator::setMetadata(framemetadata, width, height, ImageMetadata::ImageType::UYVY); framefactory_sp framefactory(new FrameFactory(framemetadata, 10)); auto helper = std::make_shared([](frame_sp &frame) -> void { if(!frame.get()) - { + { LOG_ERROR << "RECEIVED NULLPTR FRAME"; return; } @@ -41,9 +43,8 @@ BOOST_AUTO_TEST_CASE(basic, *boost::unit_test::disabled()) } ); - BOOST_TEST(helper->start(width, height, 10, false)); - - boost::this_thread::sleep_for(boost::chrono::seconds(1)); + helper->start(width, height, 10, false); + boost::this_thread::sleep_for(boost::chrono::seconds(100)); BOOST_TEST(helper->stop()); helper.reset(); @@ -55,10 +56,11 @@ BOOST_AUTO_TEST_CASE(cache, *boost::unit_test::disabled()) { frame_sp cacheFrame; { - uint32_t width = 640; - uint32_t height = 480; + uint32_t width = 3280; + uint32_t height = 2464; - auto framemetadata = framemetadata_sp(new RawImageMetadata(width, height, ImageMetadata::ImageType::UYVY, CV_8UC3, size_t(0), CV_8U, FrameMetadata::MemType::DMABUF)); + auto framemetadata = framemetadata_sp(new RawImageMetadata(FrameMetadata::MemType::DMABUF)); + DMAAllocator::setMetadata(framemetadata, width, height, ImageMetadata::ImageType::UYVY); framefactory_sp framefactory(new FrameFactory(framemetadata,10)); auto helper = std::make_shared([&](frame_sp &frame) -> void { From d85c627b72e1f6bc900a41cd01e1807b3e1897a4 Mon Sep 17 00:00:00 2001 From: RashmiShinde21 Date: Thu, 6 Nov 2025 11:01:30 +0530 Subject: [PATCH 4/9] -fix for the nvtransform error -3 NvBufSurfTransformError_InvalidParams - disabled tests related to argus camera --- base/src/DMAFDWrapper.cpp | 6 ++-- base/test/nvarguscamera_tests.cpp | 58 +++++++++++++++---------------- 2 files changed, 31 insertions(+), 33 deletions(-) diff --git a/base/src/DMAFDWrapper.cpp b/base/src/DMAFDWrapper.cpp index ab4acd93c..72262620a 100644 --- a/base/src/DMAFDWrapper.cpp +++ b/base/src/DMAFDWrapper.cpp @@ -31,7 +31,7 @@ NvBufSurfaceLayout layout, EGLDisplay eglDisplay) delete buffer; return nullptr; } - + buffer->m_surf->numFilled = 1; buffer->m_fd = buffer->m_surf->surfaceList[0].bufferDesc; // Use NvBufferMemMapEx @@ -147,8 +147,8 @@ DMAFDWrapper::~DMAFDWrapper() { if (eglImage != EGL_NO_IMAGE_KHR) { -// cudaFree(0); -// DMAUtils::freeCudaPtr(eglImage, &pResource, eglDisplay); + //cudaFree(0); + //DMAUtils::freeCudaPtr(eglImage, &pResource, m_surf, eglDisplay); } if (hostPtr) diff --git a/base/test/nvarguscamera_tests.cpp b/base/test/nvarguscamera_tests.cpp index 27f744788..f39bb0ed2 100755 --- a/base/test/nvarguscamera_tests.cpp +++ b/base/test/nvarguscamera_tests.cpp @@ -13,8 +13,8 @@ #include "test_utils.h" BOOST_AUTO_TEST_SUITE(nvarguscamera_tests) - -/*BOOST_AUTO_TEST_CASE(basic, *boost::unit_test::disabled()) +/* +BOOST_AUTO_TEST_CASE(basic, *boost::unit_test::disabled()) { auto argValue = Test_Utils::getArgValue("n", "1"); auto n_cams = atoi(argValue.c_str()); @@ -72,7 +72,7 @@ BOOST_AUTO_TEST_SUITE(nvarguscamera_tests) p.wait_for_all(); }*/ -BOOST_AUTO_TEST_CASE(vcam_nv12) +BOOST_AUTO_TEST_CASE(vcam_nv12, *boost::unit_test::disabled()) { LoggerProps logProps; logProps.enableConsoleLog = true; @@ -91,20 +91,14 @@ BOOST_AUTO_TEST_CASE(vcam_nv12) sinkProps.logHealthFrequency = 100; auto sink = boost::shared_ptr(new VirtualCameraSink(sinkProps)); copySource->setNext(sink); - - // auto fileWriter = boost::shared_ptr(new FileWriterModule(FileWriterModuleProps("./data/testOutput/nvargus/nv12_????.raw"))); - // source->setNext(fileWriter); - PipeLine p("test"); p.appendModule(source); BOOST_TEST(p.init()); - //Logger::setLogLevel(boost::log::trivial::severity_level::info); p.run_all_threaded(); boost::this_thread::sleep_for(boost::chrono::seconds(10)); - ///Logger::setLogLevel(boost::log::trivial::severity_level::error); p.stop(); p.term(); @@ -123,10 +117,14 @@ BOOST_AUTO_TEST_CASE(vcam_yuv420) sourceProps.fps = 30; auto source = boost::shared_ptr(new NvArgusCamera(sourceProps)); - //auto copySource = boost::shared_ptr(new DMAFDToHostCopy); - //source->setNext(copySource); + auto copySource = boost::shared_ptr(new DMAFDToHostCopy); + source->setNext(copySource); - auto transform = boost::shared_ptr(new NvTransform(NvTransformProps(ImageMetadata::YUV420))); + auto fileWriter = boost::shared_ptr(new FileWriterModule(FileWriterModuleProps("./data/testOutput/nvargus/nv12.raw", true))); + copySource->setNext(fileWriter); + + + auto transform = boost::shared_ptr(new NvTransform(NvTransformProps(ImageMetadata::YUV420,640,360,0,0))); source->setNext(transform); auto copy = boost::shared_ptr(new DMAFDToHostCopy); @@ -138,21 +136,17 @@ BOOST_AUTO_TEST_CASE(vcam_yuv420) auto sink = boost::shared_ptr(new VirtualCameraSink(sinkProps)); copy->setNext(sink); - // auto fileWriter = boost::shared_ptr(new FileWriterModule(FileWriterModuleProps("./data/testOutput/nvargus/yuv420_????.raw"))); - // copy->setNext(fileWriter); - // auto fileWriter2 = boost::shared_ptr(new FileWriterModule(FileWriterModuleProps("./data/testOutput/nvargus/nv12_????.raw"))); - // copySource->setNext(fileWriter2); + auto fileWriter2 = boost::shared_ptr(new FileWriterModule(FileWriterModuleProps("./data/testOutput/nvargus/yuv420-640x360.raw", true))); + copy->setNext(fileWriter2); + PipeLine p("test"); p.appendModule(source); BOOST_TEST(p.init()); - //Logger::setLogLevel(boost::log::trivial::severity_level::info); - p.run_all_threaded(); boost::this_thread::sleep_for(boost::chrono::seconds(10)); - //Logger::setLogLevel(boost::log::trivial::severity_level::error); p.stop(); p.term(); @@ -160,7 +154,7 @@ BOOST_AUTO_TEST_CASE(vcam_yuv420) p.wait_for_all(); } -BOOST_AUTO_TEST_CASE(vcam) +BOOST_AUTO_TEST_CASE(crop, *boost::unit_test::disabled()) { NvArgusCameraProps sourceProps(1280, 720); sourceProps.maxConcurrentFrames = 10; @@ -170,7 +164,7 @@ BOOST_AUTO_TEST_CASE(vcam) auto copySource = boost::shared_ptr(new DMAFDToHostCopy); source->setNext(copySource); - auto transform = boost::shared_ptr(new NvTransform(NvTransformProps(ImageMetadata::RGBA))); + auto transform = boost::shared_ptr(new NvTransform(NvTransformProps(ImageMetadata::RGBA,480,360,0,0))); source->setNext(transform); auto copy = boost::shared_ptr(new DMAFDToHostCopy); @@ -184,7 +178,7 @@ BOOST_AUTO_TEST_CASE(vcam) // auto fileWriter = boost::shared_ptr(new FileWriterModule(FileWriterModuleProps("./data/testOutput/nvargus/bgra_????.raw"))); // copy->setNext(fileWriter); - // auto fileWriter2 = boost::shared_ptr(new FileWriterModule(FileWriterModuleProps("./data/testOutput/nvargus/nv12_????.raw"))); + //auto fileWriter2 = boost::shared_ptr(new FileWriterModule(FileWriterModuleProps("./data/testOutput/nvargus/nv12_????.raw"))); // copySource->setNext(fileWriter2); PipeLine p("test"); @@ -203,7 +197,6 @@ BOOST_AUTO_TEST_CASE(vcam) p.wait_for_all(); } -/* BOOST_AUTO_TEST_CASE(encoder, *boost::unit_test::disabled()) { NvArgusCameraProps sourceProps(800, 800); @@ -233,7 +226,7 @@ BOOST_AUTO_TEST_CASE(encoder, *boost::unit_test::disabled()) p.run_all_threaded(); - boost::this_thread::sleep_for(boost::chrono::seconds(100)); + boost::this_thread::sleep_for(boost::chrono::seconds(10)); Logger::setLogLevel(boost::log::trivial::severity_level::error); p.stop(); @@ -241,9 +234,14 @@ BOOST_AUTO_TEST_CASE(encoder, *boost::unit_test::disabled()) p.wait_for_all(); } - -BOOST_AUTO_TEST_CASE(encoderrtsppush, *boost::unit_test::disabled()) +/* +BOOST_AUTO_TEST_CASE(encoderrtsppush) { + + LoggerProps logProps; + logProps.enableConsoleLog = true; + Logger::initLogger(logProps); + Logger::setLogLevel(boost::log::trivial::severity_level::trace); NvArgusCameraProps sourceProps(1280, 720); sourceProps.maxConcurrentFrames = 10; sourceProps.fps = 30; @@ -254,10 +252,10 @@ BOOST_AUTO_TEST_CASE(encoderrtsppush, *boost::unit_test::disabled()) auto encoder = boost::shared_ptr(new H264EncoderV4L2(encoderProps)); source->setNext(encoder); - // auto fileWriter = boost::shared_ptr(new FileWriterModule(FileWriterModuleProps("./data/testOutput/ArgusCamera_1280x720.h264", true))); - // encoder->setNext(fileWriter); + auto fileWriter = boost::shared_ptr(new FileWriterModule(FileWriterModuleProps("./data/testOutput/ArgusCamera_1280x720.h264", true))); + encoder->setNext(fileWriter); - RTSPPusherProps rtspPusherProps("rtsp://10.102.10.129:5544", "aprapipes_h264"); + RTSPPusherProps rtspPusherProps("rtsp://10.102.10.102:5544", "aprapipes_h264"); auto rtspPusher = boost::shared_ptr(new RTSPPusher(rtspPusherProps)); encoder->setNext(rtspPusher); @@ -275,7 +273,7 @@ BOOST_AUTO_TEST_CASE(encoderrtsppush, *boost::unit_test::disabled()) p.run_all_threaded(); - boost::this_thread::sleep_for(boost::chrono::seconds(100000)); + boost::this_thread::sleep_for(boost::chrono::seconds(10)); Logger::setLogLevel(boost::log::trivial::severity_level::error); p.stop(); From 1106990a62e5a73806352d8c29df01239cd3c9a2 Mon Sep 17 00:00:00 2001 From: RashmiShinde21 Date: Thu, 6 Nov 2025 11:14:59 +0530 Subject: [PATCH 5/9] -made changes for jpeg encoding using file descriptor of the DMABUF --- base/include/JPEGEncoderL4TMHelper.h | 10 +++ base/src/JPEGEncoderL4TM.cpp | 109 +++++++++++++++++++-------- base/src/JPEGEncoderL4TMHelper.cpp | 72 ++++++++++++++++-- 3 files changed, 152 insertions(+), 39 deletions(-) diff --git a/base/include/JPEGEncoderL4TMHelper.h b/base/include/JPEGEncoderL4TMHelper.h index 5feff099e..f12668e4b 100755 --- a/base/include/JPEGEncoderL4TMHelper.h +++ b/base/include/JPEGEncoderL4TMHelper.h @@ -1,5 +1,12 @@ #ifndef __NV_JPEG_ENCODER_H__ #define __NV_JPEG_ENCODER_H__ +#ifndef TEGRA_ACCELERATE +/** + * @c TEGRA_ACCELERATE must be defined to enable hardware acceleration of + * JPEG encoding. + */ +#define TEGRA_ACCELERATE +#endif #include #include @@ -13,6 +20,9 @@ class JPEGEncoderL4TMHelper bool init(uint32_t width, uint32_t height, uint32_t stride, J_COLOR_SPACE color_space, double scale); int encode(const unsigned char* in_buf, unsigned char **out_buf, unsigned long &out_buf_size); + int encodeFromFd(int fd, J_COLOR_SPACE color_space, + unsigned char **out_buf, unsigned long &out_buf_size, + int quality); private: struct jpeg_compress_struct cinfo; diff --git a/base/src/JPEGEncoderL4TM.cpp b/base/src/JPEGEncoderL4TM.cpp index d847eaee0..7dae73890 100755 --- a/base/src/JPEGEncoderL4TM.cpp +++ b/base/src/JPEGEncoderL4TM.cpp @@ -7,6 +7,7 @@ #include #include "Utils.h" #include "AIPExceptions.h" +#include "DMAFDWrapper.h" #define MSDK_ALIGN16(value) (((value + 15) >> 4) << 4) // round up to a multiple of 16 #define MSDK_ALIGN32(X) (((uint32_t)((X)+31)) & (~ (uint32_t)31)) @@ -43,37 +44,80 @@ class JPEGEncoderL4TM::Detail void copyYUV420PlanarToContiguous(const unsigned char* base, unsigned char* dst, RawImagePlanarMetadata* rim) { - // const int width = rim->getWidth(0); - // const int height = rim->getHeight(0); - // const size_t stepY = rim->getStep(0); - // const size_t stepU = rim->getStep(1); - // const size_t stepV = rim->getStep(2); - // const size_t offY = rim->getNextPtrOffset(0); - // const size_t offU = rim->getNextPtrOffset(1); - // const size_t offV = rim->getNextPtrOffset(2); - // const unsigned char* srcY = base + offY; - // const unsigned char* srcU = base + offU; - // const unsigned char* srcV = base + offV; - // unsigned char* dstY = dst; - // unsigned char* dstU = dst + width * height; - // unsigned char* dstV = dstU + (width * height) / 4; - // // Y - // for (int r = 0; r < height; r++) - // { - // memcpy(dstY + r * width, srcY + r * stepY, width); - // } - // // U and V are half resolution - // const int uvWidth = width / 2; - // const int uvHeight = height / 2; - // for (int r = 0; r < uvHeight; r++) - // { - // memcpy(dstU + r * uvWidth, srcU + r * stepU, uvWidth); - // memcpy(dstV + r * uvWidth, srcV + r * stepV, uvWidth); - // } + const int width = rim->getWidth(0); + const int height = rim->getHeight(0); + + const size_t stepY = rim->getStep(0); + const size_t stepU = rim->getStep(1); + const size_t stepV = rim->getStep(2); + + const size_t offY = rim->getNextPtrOffset(0); + const size_t offU = rim->getNextPtrOffset(1); + const size_t offV = rim->getNextPtrOffset(2); + + const unsigned char* srcY = base + offY; + const unsigned char* srcU = base + offU; + const unsigned char* srcV = base + offV; + + unsigned char* dstY = dst; + unsigned char* dstU = dst + width * height; + unsigned char* dstV = dstU + (width * height) / 4; + + // Copy Y plane row-by-row (handle stride) + for (int r = 0; r < height; r++) + { + memcpy(dstY + r * width, srcY + r * stepY, width); + } + + // Copy U and V planes (half resolution) + const int uvWidth = width / 2; + const int uvHeight = height / 2; + + for (int r = 0; r < uvHeight; r++) + { + memcpy(dstU + r * uvWidth, srcU + r * stepU, uvWidth); + memcpy(dstV + r * uvWidth, srcV + r * stepV, uvWidth); + } } - size_t compute(frame_sp& inFrame, frame_sp& frame) - { +size_t compute(frame_sp& inFrame, frame_sp& frame) + { + auto inMeta = inFrame->getMetadata(); + + // If input is DMABUF planar YUV420 or NV12, use encodeFromFd + if (inMeta->getMemType() == FrameMetadata::DMABUF && (inMeta->getFrameType() == FrameMetadata::RAW_IMAGE_PLANAR || inMeta->getFrameType() == FrameMetadata::RAW_IMAGE)) + { + // Extract fd + auto dma = static_cast(inFrame->data()); + int fd = dma->getFd(); + if (fd <= 0) { + LOG_ERROR << "Invalid DMABUF fd"; + return 0; + } + + // Choose color space – I420/NV12 are both YCbCr for the encoder + //J_COLOR_SPACE cs = JCS_YCbCr; + + + + // Setup output buffer + auto out_ptr = static_cast(frame->data()); + unsigned char* out_buf = out_ptr; + unsigned long out_len = static_cast(frame->size()); + + // Call NvJPEGEncoder::encodeFromFd(fd, ...) + // Assuming you have a member nvEnc of type NvJPEGEncoder* already setup in init() + int ret = encHelper->encodeFromFd(fd, color_space, &out_buf, out_len, mProps.quality); + if (ret < 0) { + LOG_ERROR << "encodeFromFd failed"; + return 0; + } + + // out_len now has the actual size; return it + return static_cast(out_len); + } + else{ + auto in_buf = static_cast(inFrame->data()); if(color_space == JCS_YCbCr) @@ -107,7 +151,7 @@ class JPEGEncoderL4TM::Detail } else if (rim->getImageType() == ImageMetadata::YUV420) { - // copyYUV420PlanarToContiguous((unsigned char*)inFrame->data(), (unsigned char*)dummyBuffer.get(), rim); + copyYUV420PlanarToContiguous((unsigned char*)inFrame->data(), (unsigned char*)dummyBuffer.get(), rim); in_buf = dummyBuffer.get(); } else @@ -132,6 +176,7 @@ class JPEGEncoderL4TM::Detail return outLength; } + } size_t getDataSize() { @@ -271,7 +316,7 @@ class JPEGEncoderL4TM::Detail } else if(rawImageMetadata->getImageType() == ImageMetadata::RGBA) { - color_space = JCS_EXT_RGBA; + color_space = JCS_RGBA_8888; } else if(rawImageMetadata->getImageType() == ImageMetadata::NV12 || rawImageMetadata->getImageType() == ImageMetadata::YUV420) { @@ -300,7 +345,7 @@ class JPEGEncoderL4TM::Detail } else if(rim->getImageType() == ImageMetadata::RGBA) { - color_space = JCS_EXT_RGBA; + color_space = JCS_RGBA_8888; } else if(rim->getImageType() == ImageMetadata::NV12 || rim->getImageType() == ImageMetadata::YUV420) { diff --git a/base/src/JPEGEncoderL4TMHelper.cpp b/base/src/JPEGEncoderL4TMHelper.cpp index 3250f169c..24580bad3 100755 --- a/base/src/JPEGEncoderL4TMHelper.cpp +++ b/base/src/JPEGEncoderL4TMHelper.cpp @@ -2,6 +2,7 @@ #include "JPEGEncoderL4TMHelper.h" #include #include +#include // https://dev.w3.org/Amaya/libjpeg/example.c @@ -40,7 +41,7 @@ JPEGEncoderL4TMHelper::~JPEGEncoderL4TMHelper() bool JPEGEncoderL4TMHelper::init(uint32_t width, uint32_t height, uint32_t _stride, J_COLOR_SPACE color_space, double scale) { - if (color_space == JCS_RGB || color_space == JCS_EXT_RGBA) + if (color_space == JCS_RGB || color_space == JCS_RGBA_8888) { planes = 1; } @@ -78,7 +79,7 @@ bool JPEGEncoderL4TMHelper::init(uint32_t width, uint32_t height, uint32_t _stri cinfo.image_width = width; cinfo.image_height = height; - if(color_space == JCS_EXT_RGBA) + if(color_space == JCS_RGBA_8888) { cinfo.input_components = 4; // RGBA } @@ -90,7 +91,7 @@ bool JPEGEncoderL4TMHelper::init(uint32_t width, uint32_t height, uint32_t _stri // Scaling functionality removed - not available in standard libjpeg // if (scale != 1) { ... } - jpeg_set_defaults(&cinfo); +jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo, quality, TRUE); if (planes == 3) @@ -110,7 +111,7 @@ bool JPEGEncoderL4TMHelper::init(uint32_t width, uint32_t height, uint32_t _stri int JPEGEncoderL4TMHelper::encode(const unsigned char *in_buf, unsigned char **out_buf, unsigned long &out_buf_size) { - if(cinfo.in_color_space == JCS_RGB || cinfo.in_color_space == JCS_EXT_RGBA) + if(cinfo.in_color_space == JCS_RGB || cinfo.in_color_space == JCS_RGBA_8888) { // Store original color space before destroying J_COLOR_SPACE orig_color_space = cinfo.in_color_space; @@ -128,10 +129,10 @@ int JPEGEncoderL4TMHelper::encode(const unsigned char *in_buf, unsigned char **o cinfo.image_height = comp_height[0]; // Restore correct components based on original color space - if(orig_color_space == JCS_EXT_RGBA) + if(orig_color_space == JCS_RGBA_8888) { cinfo.input_components = 4; // RGBA - cinfo.in_color_space = JCS_EXT_RGBA; + cinfo.in_color_space = JCS_RGBA_8888; } else { @@ -144,7 +145,7 @@ int JPEGEncoderL4TMHelper::encode(const unsigned char *in_buf, unsigned char **o jpeg_mem_dest(&cinfo, out_buf, &out_buf_size); - // jpeg_set_hardware_acceleration_parameters_enc(&cinfo, TRUE, out_buf_size, 0, 0); + jpeg_set_hardware_acceleration_parameters_enc(&cinfo, TRUE, out_buf_size, 0, 0); unsigned char *base[planes], *end[planes]; @@ -198,3 +199,60 @@ int JPEGEncoderL4TMHelper::encode(const unsigned char *in_buf, unsigned char **o return 0; } + + +int JPEGEncoderL4TMHelper::encodeFromFd(int fd, J_COLOR_SPACE color_space, + unsigned char **out_buf, unsigned long &out_buf_size, + int quality) +{ + uint32_t buffer_id; + + if (fd == -1) + { + LOG_INFO<<"Not encoding because fd = -1"; + return -1; + } + + + + jpeg_mem_dest(&cinfo, out_buf, &out_buf_size); + + cinfo.fd = fd; + cinfo.IsVendorbuf = TRUE; + switch (color_space) + { + case JCS_YCbCr: + cinfo.in_color_space = JCS_YCbCr; + break; + case JCS_RGBA_8888: + cinfo.in_color_space = JCS_RGBA_8888; + default: + + LOG_INFO<<"Color format " << color_space << " not supported\n"; + return -1; + } + cinfo.raw_data_in = TRUE; + jpeg_set_defaults(&cinfo); + jpeg_set_quality(&cinfo, quality, TRUE); + jpeg_set_hardware_acceleration_parameters_enc(&cinfo, TRUE, out_buf_size, 0, 0); + + + + jpeg_start_compress (&cinfo, 0); + + if (cinfo.err->msg_code) + { + char err_string[256]; + cinfo.err->format_message((j_common_ptr) &cinfo, err_string); + LOG_INFO<<"Error in jpeg_start_compress: " << err_string; + return -1; + } + + jpeg_write_raw_data (&cinfo, NULL, 0); + jpeg_finish_compress(&cinfo); + + LOG_INFO<<"Succesfully encoded Buffer fd=" << fd; + + + return 0; +} \ No newline at end of file From 20f6b799ca7e5c86e1c0f2e0724e42c7fccb3b33 Mon Sep 17 00:00:00 2001 From: RashmiShinde21 Date: Thu, 6 Nov 2025 11:25:27 +0530 Subject: [PATCH 6/9] -added test cases for jpeg encoding using dmabuf -jpeg encoding of nv12 , yuv420 images, -encoding of frames through argus camera --- base/test/jpegencoderl4tm_tests.cpp | 200 +++++++++++++++++++++++++++- 1 file changed, 199 insertions(+), 1 deletion(-) diff --git a/base/test/jpegencoderl4tm_tests.cpp b/base/test/jpegencoderl4tm_tests.cpp index d62d66e72..9ff0bc891 100755 --- a/base/test/jpegencoderl4tm_tests.cpp +++ b/base/test/jpegencoderl4tm_tests.cpp @@ -1,7 +1,7 @@ #include "stdafx.h" #include #include - +#include "MemTypeConversion.h" #include "ExternalSourceModule.h" #include "ExternalSinkModule.h" #include "FrameMetadata.h" @@ -15,9 +15,207 @@ #include "PipeLine.h" #include "test_utils.h" #include +#include "NvV4L2Camera.h" +#include "DMAFDToHostCopy.h" +#include "FileWriterModule.h" +#include "DMAFDWrapper.h" +#include "DMAAllocator.h" +#include "nvbufsurface.h" + +#include "NvArgusCamera.h" BOOST_AUTO_TEST_SUITE(jpegencoderl4tm_tests) +BOOST_AUTO_TEST_CASE(argus_jpeg, * boost::unit_test::disabled()) +{ + LoggerProps logProps; + logProps.enableConsoleLog = true; + Logger::initLogger(logProps); + Logger::setLogLevel(boost::log::trivial::severity_level::trace); + NvArgusCameraProps sourceProps(1280, 720); + sourceProps.maxConcurrentFrames = 10; + sourceProps.fps = 30; + auto source = boost::shared_ptr(new NvArgusCamera(sourceProps)); + + auto copySource = boost::shared_ptr(new DMAFDToHostCopy); + source->setNext(copySource); + + auto fileWriter = boost::shared_ptr(new FileWriterModule(FileWriterModuleProps("./data/testOutput/nvargus/nv12-argus.raw", true))); + copySource->setNext(fileWriter); + + + auto jencode = boost::shared_ptr(new JPEGEncoderL4TM()); + auto encodedImageMetadata = framemetadata_sp(new FrameMetadata(FrameMetadata::ENCODED_IMAGE)); + auto encodedImagePin = jencode->addOutputPin(encodedImageMetadata); + source->setNext(jencode); + + + auto fileWriter2 = boost::shared_ptr(new FileWriterModule(FileWriterModuleProps("./data/testOutput/nvargus/frame_argus.jpg", true))); + jencode->setNext(fileWriter2); + PipeLine p("test"); + p.appendModule(source); + BOOST_TEST(p.init()); + p.run_all_threaded(); + + boost::this_thread::sleep_for(boost::chrono::seconds(10)); + + p.stop(); + p.term(); + + p.wait_for_all(); +} + + + +BOOST_AUTO_TEST_CASE(jpegencoder_dmabuf_fd_nv12, * boost::unit_test::disabled()) +{ + LoggerProps logProps; logProps.enableConsoleLog = true; + Logger::initLogger(logProps); + Logger::setLogLevel(boost::log::trivial::severity_level::trace); + + const int width = 704, height = 576; + const std::string inputYuvPath = "./data/nv12-704x576.raw"; + + // Source + auto m1 = boost::shared_ptr(new ExternalSourceModule()); + + // Create DMABUF metadata with actual pitches from NvBufSurface + auto meta = framemetadata_sp(new RawImagePlanarMetadata(FrameMetadata::DMABUF)); + DMAAllocator::setMetadata(meta, width, height, ImageMetadata::NV12); + auto rawPin = m1->addOutputPin(meta); + + // NVJPEG encoder module + auto enc = boost::shared_ptr(new JPEGEncoderL4TM()); // ensure this module exists/linked + m1->setNext(enc); + auto encMeta = framemetadata_sp(new FrameMetadata(FrameMetadata::ENCODED_IMAGE)); + auto encPin = enc->addOutputPin(encMeta); + + // Sink + auto sink = boost::shared_ptr(new ExternalSinkModule()); + enc->setNext(sink); + + BOOST_TEST(m1->init()); + BOOST_TEST(enc->init()); + BOOST_TEST(sink->init()); + + // Allocate DMABUF frame and fill with I420 data (row-wise using NvBufSurface params) + auto frame = m1->makeFrame(meta->getDataSize(), rawPin); + { + auto dma = static_cast(frame->data()); + NvBufSurface* surf = dma->getNvBufSurface(); + + std::ifstream in(inputYuvPath, std::ios::binary); + BOOST_TEST(in.good()); + + // planes: 0=Y,1=U,2=V + for (int p = 0; p < 3; ++p) { + NvBufSurfaceMap(surf, 0, p, NVBUF_MAP_READ_WRITE); + NvBufSurfaceSyncForCpu(surf, 0, p); + auto dst = static_cast(surf->surfaceList[0].mappedAddr.addr[p]); + auto rows = surf->surfaceList[0].planeParams.height[p]; + auto pitch = surf->surfaceList[0].planeParams.pitch[p]; + auto rowB = surf->surfaceList[0].planeParams.width[p] * + surf->surfaceList[0].planeParams.bytesPerPix[p]; + + std::vector row(rowB); + for (uint32_t r = 0; r < rows; ++r) { + in.read(reinterpret_cast(row.data()), rowB); + BOOST_TEST(static_cast(in.gcount()) == rowB); + memcpy(dst + r * pitch, row.data(), rowB); + } + NvBufSurfaceSyncForDevice(surf, 0, p); + NvBufSurfaceUnMap(surf, 0, p); + } + } + + frame_container fc; fc.insert({ rawPin, frame }); + m1->send(fc); + enc->step(); + + auto out = sink->pop(); + BOOST_TEST((out.find(encPin) != out.end())); + auto outFrame = out[encPin]; + BOOST_TEST(outFrame->size() > 0); + + Test_Utils::saveOrCompare("./data/testOutput/jenc_dmabuf_nv12.jpg", + (const uint8_t*)outFrame->data(), outFrame->size(), 0); +} + + +BOOST_AUTO_TEST_CASE(jpegencoder_dmabuf_fd_yuv420, * boost::unit_test::disabled()) +{ + LoggerProps logProps; logProps.enableConsoleLog = true; + Logger::initLogger(logProps); + Logger::setLogLevel(boost::log::trivial::severity_level::trace); + + const int width = 3840, height = 2160; + const std::string inputYuvPath = "./data/4k.yuv"; + + // Source + auto m1 = boost::shared_ptr(new ExternalSourceModule()); + + // Create DMABUF metadata with actual pitches from NvBufSurface + auto meta = framemetadata_sp(new RawImagePlanarMetadata(FrameMetadata::DMABUF)); + DMAAllocator::setMetadata(meta, width, height, ImageMetadata::YUV420); + auto rawPin = m1->addOutputPin(meta); + + // NVJPEG encoder module + auto enc = boost::shared_ptr(new JPEGEncoderL4TM()); // ensure this module exists/linked + m1->setNext(enc); + auto encMeta = framemetadata_sp(new FrameMetadata(FrameMetadata::ENCODED_IMAGE)); + auto encPin = enc->addOutputPin(encMeta); + + // Sink + auto sink = boost::shared_ptr(new ExternalSinkModule()); + enc->setNext(sink); + + BOOST_TEST(m1->init()); + BOOST_TEST(enc->init()); + BOOST_TEST(sink->init()); + + // Allocate DMABUF frame and fill with I420 data (row-wise using NvBufSurface params) + auto frame = m1->makeFrame(meta->getDataSize(), rawPin); + { + auto dma = static_cast(frame->data()); + NvBufSurface* surf = dma->getNvBufSurface(); + + std::ifstream in(inputYuvPath, std::ios::binary); + BOOST_TEST(in.good()); + + // planes: 0=Y,1=U,2=V + for (int p = 0; p < 3; ++p) { + NvBufSurfaceMap(surf, 0, p, NVBUF_MAP_READ_WRITE); + NvBufSurfaceSyncForCpu(surf, 0, p); + auto dst = static_cast(surf->surfaceList[0].mappedAddr.addr[p]); + auto rows = surf->surfaceList[0].planeParams.height[p]; + auto pitch = surf->surfaceList[0].planeParams.pitch[p]; + auto rowB = surf->surfaceList[0].planeParams.width[p] * + surf->surfaceList[0].planeParams.bytesPerPix[p]; + + std::vector row(rowB); + for (uint32_t r = 0; r < rows; ++r) { + in.read(reinterpret_cast(row.data()), rowB); + BOOST_TEST(static_cast(in.gcount()) == rowB); + memcpy(dst + r * pitch, row.data(), rowB); + } + NvBufSurfaceSyncForDevice(surf, 0, p); + NvBufSurfaceUnMap(surf, 0, p); + } + } + + frame_container fc; fc.insert({ rawPin, frame }); + m1->send(fc); + enc->step(); + + auto out = sink->pop(); + BOOST_TEST((out.find(encPin) != out.end())); + auto outFrame = out[encPin]; + BOOST_TEST(outFrame->size() > 0); + + Test_Utils::saveOrCompare("./data/testOutput/jenc_dmabuf_yuv420.jpg", + (const uint8_t*)outFrame->data(), outFrame->size(), 0); +} + BOOST_AUTO_TEST_CASE(jpegencoderl4tm_basic, * boost::unit_test::disabled()) { // metadata is known From 8f0dd5ee6b7c7b098bf4e6079315ac56c5aebeb4 Mon Sep 17 00:00:00 2001 From: RashmiShinde21 Date: Mon, 10 Nov 2025 16:05:11 +0530 Subject: [PATCH 7/9] -made changes for jpeg decoding using fd -added testcase for encoding of an jpg image to yuv using fd --- base/src/JPEGDecoderL4TM.cpp | 82 +++++++++++++------ base/src/JPEGDecoderL4TMHelper.cpp | 121 +++++++++++++++++++++++++++- base/test/jpegdecoderl4tm_tests.cpp | 56 ++++++++++++- 3 files changed, 231 insertions(+), 28 deletions(-) diff --git a/base/src/JPEGDecoderL4TM.cpp b/base/src/JPEGDecoderL4TM.cpp index f176ebfca..b41c32700 100755 --- a/base/src/JPEGDecoderL4TM.cpp +++ b/base/src/JPEGDecoderL4TM.cpp @@ -7,15 +7,17 @@ #include #include "Utils.h" #include "AIPExceptions.h" - +#include "DMAFDWrapper.h" +#include "DMAAllocator.h" class JPEGDecoderL4TM::Detail { public: - Detail() : mDataSize(0), + Detail(JPEGDecoderL4TMProps& props) : mDataSize(0), mWidth2(0), mHeight2(0), - mActualFrameSize(0) + mActualFrameSize(0), + mProps(props) { decHelper.reset(new JPEGDecoderL4TMHelper()); } @@ -32,16 +34,23 @@ class JPEGDecoderL4TM::Detail throw AIPException(AIP_FATAL, "init:: decHelper->init Failed"); } - // This is a cheating - // Actual output is NV12 - // width and height are aligned by 32 bits - setting stride - // passing frame->data() to cheat opencv to no allocate any buffer inside - cv::Mat img(mHeight2, mWidth2, CV_8UC1, frame->data(), mWidth2); - mDataSize = (mWidth2 * mHeight2 * 3) >> 1; - mActualFrameSize = mWidth2 * mHeight2; - - FrameMetadataFactory::downcast(metadata)->setData(img); - mMetadata = metadata; + if(mProps.decodeToFd) + { + // For decodeToFd, set DMABUF metadata with dimensions + auto planarMeta = FrameMetadataFactory::downcast(metadata); + DMAAllocator::setMetadata(metadata, mWidth2, mHeight2, ImageMetadata::YUV420); + mDataSize = (mWidth2 * mHeight2 * 3) >> 1; // YUV420 size + mActualFrameSize = mWidth2 * mHeight2; + } + else + { + cv::Mat img(mHeight2, mWidth2, CV_8UC1, frame->data(), mWidth2); + mDataSize = (mWidth2 * mHeight2 * 3) >> 1; + mActualFrameSize = mWidth2 * mHeight2; + FrameMetadataFactory::downcast(metadata)->setData(img); + } + + mMetadata = metadata; } framemetadata_sp getMetadata() @@ -51,8 +60,24 @@ class JPEGDecoderL4TM::Detail size_t compute(frame_sp &inFrame, frame_sp &frame) { - decHelper->decode((unsigned char *)inFrame->data(), inFrame->size(), (unsigned char *)frame->data()); - return mActualFrameSize; + int fd=0; + if(mProps.decodeToFd) + { + auto dmaWrapper = static_cast(frame->data()); + int fd = dmaWrapper->getFd(); + int ret=decHelper->decodeToFd(fd,(unsigned char *)inFrame->data(), inFrame->size()); + if (ret < 0) { + LOG_ERROR << "decodeToFd failed"; + return false; + } + } + else + { + decHelper->decode((unsigned char *)inFrame->data(), inFrame->size(), (unsigned char *)frame->data()); + + } + return mActualFrameSize; + } size_t getDataSize() @@ -69,11 +94,12 @@ class JPEGDecoderL4TM::Detail size_t mActualFrameSize; int mWidth2; int mHeight2; + JPEGDecoderL4TMProps mProps; }; JPEGDecoderL4TM::JPEGDecoderL4TM(JPEGDecoderL4TMProps _props) : Module(TRANSFORM, "JPEGDecoderL4TM", _props) { - mDetail.reset(new Detail()); + mDetail.reset(new Detail(_props)); } JPEGDecoderL4TM::~JPEGDecoderL4TM() {} @@ -107,9 +133,9 @@ bool JPEGDecoderL4TM::validateOutputPins() framemetadata_sp metadata = getFirstOutputMetadata(); FrameMetadata::FrameType frameType = metadata->getFrameType(); - if (frameType != FrameMetadata::RAW_IMAGE) + if ((frameType != FrameMetadata::RAW_IMAGE) &&(frameType != FrameMetadata::RAW_IMAGE_PLANAR)) { - LOG_ERROR << "<" << getId() << ">::validateOutputPins input frameType is expected to be RAW_IMAGE. Actual<" << frameType << ">"; + LOG_ERROR << "<" << getId() << ">::validateOutputPins frameType is expected to be RAW_IMAGE or RAW_IMAGE_PLANAR. Actual<" << frameType << ">"; return false; } @@ -128,7 +154,17 @@ bool JPEGDecoderL4TM::init() { throw AIPException(AIP_NOTSET, string("JPEGDecoderL4TM Output Frame Metadata parameters will be automatically set. Kindly remove.")); } - mDetail->outputPinId = getOutputPinIdByType(FrameMetadata::RAW_IMAGE); + + if(metadata->getFrameType()==FrameMetadata::RAW_IMAGE) + { + mDetail->outputPinId = getOutputPinIdByType(FrameMetadata::RAW_IMAGE); + } + else + { + mDetail->outputPinId = getOutputPinIdByType(FrameMetadata::RAW_IMAGE_PLANAR); + } + + return true; } @@ -147,20 +183,18 @@ bool JPEGDecoderL4TM::process(frame_container &frames) } auto metadata = mDetail->getMetadata(); - auto bufferFrame = makeFrame(mDetail->getDataSize()); + auto bufferFrame = makeFrame(mDetail->getDataSize(), mDetail->outputPinId); auto frameLength = mDetail->compute(frame, bufferFrame); - - auto outFrame = makeFrame(bufferFrame, frameLength,mDetail->outputPinId); - frames.insert(make_pair(mDetail->outputPinId, outFrame)); + frames.insert(make_pair(mDetail->outputPinId, bufferFrame)); send(frames); return true; } bool JPEGDecoderL4TM::processSOS(frame_sp &frame) { - auto outMetadata = getOutputMetadataByType(FrameMetadata::RAW_IMAGE); + auto outMetadata = getFirstOutputMetadata(); mDetail->initMetadata(frame, outMetadata); return true; } \ No newline at end of file diff --git a/base/src/JPEGDecoderL4TMHelper.cpp b/base/src/JPEGDecoderL4TMHelper.cpp index 5f419c2ac..6515a39dd 100755 --- a/base/src/JPEGDecoderL4TMHelper.cpp +++ b/base/src/JPEGDecoderL4TMHelper.cpp @@ -4,6 +4,9 @@ #include #include #include "Logger.h" +#include "nvbufsurface.h" +#include "jpegint.h" +#include JPEGDecoderL4TMHelper::JPEGDecoderL4TMHelper() { @@ -63,7 +66,7 @@ bool JPEGDecoderL4TMHelper::init(const unsigned char *in_buf, unsigned long in_b } } - jpeg_finish_decompress(&cinfo); + jpeg_finish_decompress(&cinfo); width = cinfo.image_width; height = cinfo.image_height; @@ -88,6 +91,122 @@ bool JPEGDecoderL4TMHelper::init(const unsigned char *in_buf, unsigned long in_b return true; } + + +int JPEGDecoderL4TMHelper::decodeToFd(int &fd, unsigned char * in_buf, + unsigned long in_buf_size) +{ + uint32_t pixel_format = 0; + uint32_t buffer_id; + NvBufSurface surface; + + if (in_buf == NULL || in_buf_size == 0) + { + LOG_INFO<<"Not decoding because input buffer = NULL or size = 0"; + return -1; + } + + + cinfo.out_color_space = JCS_YCbCr; + + jpeg_mem_src(&cinfo, in_buf, in_buf_size); + + cinfo.out_color_space = JCS_YCbCr; + + + (void) jpeg_read_header(&cinfo, TRUE); + + cinfo.out_color_space = JCS_YCbCr; + cinfo.IsVendorbuf = TRUE; + cinfo.pVendor_buf = (unsigned char*)&surface; + + if (cinfo.comp_info[0].h_samp_factor == 2) + { + if (cinfo.comp_info[0].v_samp_factor == 2) + { + pixel_format = V4L2_PIX_FMT_YUV420M; + } + else + { + pixel_format = V4L2_PIX_FMT_YUV422M; + } + } + else + { + if (cinfo.comp_info[0].v_samp_factor == 1) + { + pixel_format = V4L2_PIX_FMT_YUV444M; + } + else + { + pixel_format = V4L2_PIX_FMT_YUV422M; + } + } + + jpeg_start_decompress (&cinfo); + + if (cinfo.global_state != DSTATE_READY) { + LOG_INFO<<"JPEG format is not supported by libnvjpeg"; + return -1; + } + + jpeg_read_raw_data (&cinfo, NULL, cinfo.comp_info[0].v_samp_factor * DCTSIZE); + jpeg_finish_decompress(&cinfo); + + // Image width and height should be even + uint32_t width = (cinfo.image_width % 2 == 1) ? cinfo.image_width + 1 : cinfo.image_width; + uint32_t height = (cinfo.image_height % 2 == 1) ? cinfo.image_height + 1 : cinfo.image_height; + uint32_t pixfmt = pixel_format; + int fd1= cinfo.fd; + + LOG_INFO<<"Succesfully decoded Buffer fd=" << fd; + LOG_INFO<<"Succesfully decoded Buffer fd1=" << fd1; + + + NvBufSurfTransformRect src_rect, dst_rect; + src_rect.top = 0; + src_rect.left = 0; + src_rect.width = width; + src_rect.height = height; + dst_rect.top = 0; + dst_rect.left = 0; + dst_rect.width = width; + dst_rect.height = height; + + // Set up transform parameters + NvBufSurfTransformParams transform_params; + memset(&transform_params, 0, sizeof(transform_params)); + transform_params.transform_flag = NVBUFSURF_TRANSFORM_FILTER; + transform_params.transform_flip = NvBufSurfTransform_None; + transform_params.transform_filter = NvBufSurfTransformInter_Nearest; + transform_params.src_rect = &src_rect; + transform_params.dst_rect = &dst_rect; + + // auto dmaFDWrapper = static_cast(frame->data()); + NvBufSurface *in_surf = nullptr; + NvBufSurface *out_surf = nullptr; + + if (NvBufSurfaceFromFd(cinfo.fd, (void**)&in_surf) != 0) { + LOG_INFO << "Failed to create input surface"; + return false; + } + + if (NvBufSurfaceFromFd(fd, (void**)&out_surf) != 0) { + LOG_INFO << "Failed to create output surface"; + return false; + } + + NvBufSurfTransform_Error err = NvBufSurfTransform(in_surf, out_surf, &transform_params); + + if (err != NvBufSurfTransformError_Success) { + LOG_INFO << "Transform failed============================================>>>>>>>>>>>>>>>>>>>>>>>>>>>error:" < #include - +#include "DMAFDToHostCopy.h" +#include "FileWriterModule.h" #include "ExternalSourceModule.h" #include "ExternalSinkModule.h" #include "FrameMetadata.h" @@ -10,6 +11,7 @@ #include "AIPExceptions.h" #include "JPEGDecoderL4TM.h" #include "test_utils.h" +#include "PipeLine.h" BOOST_AUTO_TEST_SUITE(jpegdecoderl4tm_tests) @@ -66,8 +68,56 @@ BOOST_AUTO_TEST_CASE(jpegdecoderl4tm_basic, * boost::unit_test::disabled()) delete[] pReadData; } -BOOST_AUTO_TEST_CASE(jpegdecoderl4tm_rgb, * boost::unit_test::disabled()) -{ +BOOST_AUTO_TEST_CASE(jpegdecoderl4tm_fd_yuv420) +{ + LoggerProps logProps; + logProps.enableConsoleLog = true; + Logger::initLogger(logProps); + Logger::setLogLevel(boost::log::trivial::severity_level::trace); + const uint8_t* pReadData = nullptr; + unsigned int readDataSize = 0U; + BOOST_TEST(Test_Utils::readFile("./data/faces.jpg", pReadData, readDataSize)); + + auto m1 = boost::shared_ptr(new ExternalSourceModule()); + auto metadata = framemetadata_sp(new FrameMetadata(FrameMetadata::ENCODED_IMAGE)); + auto encodedImagePin = m1->addOutputPin(metadata); + + JPEGDecoderL4TMProps props; + props.decodeToFd = true; + + auto m2 = boost::shared_ptr(new JPEGDecoderL4TM(props)); + m1->setNext(m2); + auto decoderMetadata = framemetadata_sp(new RawImagePlanarMetadata(FrameMetadata::MemType::DMABUF)); + auto rawImagePin = m2->addOutputPin(decoderMetadata); + + + auto m3 = boost::shared_ptr(new DMAFDToHostCopy); + m2->setNext(m3); + + auto m4 = boost::shared_ptr(new FileWriterModule(FileWriterModuleProps("./data/testOutput/faces-dma.yuv", true))); + m3->setNext(m4); + + + BOOST_TEST(m1->init()); + BOOST_TEST(m2->init()); + BOOST_TEST(m3->init()); + BOOST_TEST(m4->init()); + + auto encodedImageFrame = m1->makeFrame(readDataSize, encodedImagePin); + memcpy(encodedImageFrame->data(), pReadData, readDataSize); + + frame_container frames; + frames.insert(make_pair(encodedImagePin, encodedImageFrame)); + + m1->send(frames); + m2->step(); + m3->step(); + m4->step(); + +} + +BOOST_AUTO_TEST_CASE(jpegdecoderl4tm_rgb) +{ const uint8_t* pReadData = nullptr; unsigned int readDataSize = 0U; BOOST_TEST(Test_Utils::readFile("./data/frame.jpg", pReadData, readDataSize)); From 7d726989df0cba64cde2b20f74aea2110aa25f57 Mon Sep 17 00:00:00 2001 From: RashmiShinde21 Date: Mon, 10 Nov 2025 17:32:52 +0530 Subject: [PATCH 8/9] changes in header files for decoding using fd --- base/include/JPEGDecoderL4TM.h | 3 ++- base/include/JPEGDecoderL4TMHelper.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/base/include/JPEGDecoderL4TM.h b/base/include/JPEGDecoderL4TM.h index 759f04317..0ff4eeee1 100755 --- a/base/include/JPEGDecoderL4TM.h +++ b/base/include/JPEGDecoderL4TM.h @@ -7,8 +7,9 @@ class JPEGDecoderL4TMProps : public ModuleProps public: JPEGDecoderL4TMProps() : ModuleProps() { - + decodeToFd=false; } + bool decodeToFd; }; class JPEGDecoderL4TM : public Module diff --git a/base/include/JPEGDecoderL4TMHelper.h b/base/include/JPEGDecoderL4TMHelper.h index 73a4c98ae..987c7a185 100755 --- a/base/include/JPEGDecoderL4TMHelper.h +++ b/base/include/JPEGDecoderL4TMHelper.h @@ -13,6 +13,7 @@ class JPEGDecoderL4TMHelper bool init(const unsigned char* in_buf, unsigned long in_buf_size, int& width, int& height); int decode(const unsigned char* in_buf, unsigned long in_buf_size, unsigned char *out_buf); + int decodeToFd(int &fd, unsigned char * in_buf,unsigned long in_buf_size); private: From d6a7e825082218c37147af831fd23ed8a3537451 Mon Sep 17 00:00:00 2001 From: RashmiShinde21 Date: Thu, 13 Nov 2025 12:21:05 +0530 Subject: [PATCH 9/9] fix for the color issue in YUV and NV12 frames --- base/include/DMAFrameUtils.h | 1 + 1 file changed, 1 insertion(+) diff --git a/base/include/DMAFrameUtils.h b/base/include/DMAFrameUtils.h index 366190084..8d1353df0 100644 --- a/base/include/DMAFrameUtils.h +++ b/base/include/DMAFrameUtils.h @@ -82,6 +82,7 @@ class DMAFrameUtils { width[i] = rawMetadata->getWidth(i); height[i] = rawMetadata->getHeight(i); + pitch[i]=rawMetadata->getStep(i); } auto metadata = framemetadata_sp(new RawImagePlanarMetadata(width[0], height[0], imageType, size_t(0), CV_8U, FrameMetadata::MemType::DMABUF)); DMAAllocator::setMetadata(metadata, width[0], height[0], imageType, pitch, offset);