From 22f3702ff785a725c4456fb8048bbf8d1ac41caf Mon Sep 17 00:00:00 2001 From: Matthew Date: Mon, 17 Mar 2025 11:18:36 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=B9=E4=B8=BA=E5=8D=95=E4=B8=AA=E8=AF=B7?= =?UTF-8?q?=E6=B1=82=E8=BF=9E=E6=8B=8D4=E5=B8=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/cpp/camera2/ndkcamera.cpp | 100 +++++++++++++++++++++++-- app/src/main/cpp/camera2/ndkcamera.h | 6 +- 2 files changed, 98 insertions(+), 8 deletions(-) diff --git a/app/src/main/cpp/camera2/ndkcamera.cpp b/app/src/main/cpp/camera2/ndkcamera.cpp index 4ddfc9b9..7e896d36 100644 --- a/app/src/main/cpp/camera2/ndkcamera.cpp +++ b/app/src/main/cpp/camera2/ndkcamera.cpp @@ -1182,6 +1182,7 @@ void NdkCamera::close() */ mCaptureFrames.clear(); + mCaptureResultMap.clear(); if ((ACameraManager *)camera_manager != NULL) { @@ -1469,13 +1470,40 @@ void NdkCamera::onImageAvailable(AImageReader* reader) } } - ConvertYUV21ToMat(nv21, width, height,mWidth, mHeight, camera_orientation, - camera_facing == ACAMERA_LENS_FACING_FRONT, m_params.orientation, mOneFrame); + int64_t frameTs = 0; + mstatus = AImage_getTimestamp(image, &frameTs); + AImage_delete(image); - delete[] nv21; + bool captureCompleted = false; + bool captureDispatchable = false; + m_locker.lock(); + if (!frame.empty()) + { + mOneFrame.push_back(std::make_pair<>(frameTs, frame)); } - } - m_photoTaken = true; + if (mOneFrame.size() >= expectedTimes) + { + bool allExisted = true; + for (auto itFrame = mOneFrame.cbegin(); itFrame != mOneFrame.cend(); ++itFrame) + { + if (mCaptureResultMap.find(itFrame->first) == mCaptureResultMap.cend()) + { + allExisted = false; + break; + } + } + if (allExisted) + { + captureCompleted = true; + } + } + + if (captureCompleted && !mCaptureDispatched) + { + mCaptureDispatched = true; + captureDispatchable = true; + } + m_locker.unlock(); AImage_delete(image); @@ -1931,12 +1959,32 @@ void NdkCamera::onCaptureCompleted(ACameraCaptureSession* session, ACaptureReque bool captureDispatchable = false; size_t expectedTimes = mCaptureRequests.size() - 1; + int64_t resultTimestamp = GetTimestamp(result); std::shared_ptr captureResult(pCopy, ACameraMetadata_free); - if (expectedTimes == 1) + + if (m_params.burstRawCapture == 0) { m_locker.lock(); mCaptureResults.push_back(captureResult); - captureCompleted = !mOneFrame.empty(); + mCaptureResultMap[resultTimestamp] = captureResult; + + if (mOneFrame.size() >= expectedTimes) + { + bool allExisted = true; + for (auto itFrame = mOneFrame.cbegin(); itFrame != mOneFrame.cend(); ++itFrame) + { + if (mCaptureResultMap.find(itFrame->first) == mCaptureResultMap.cend()) + { + allExisted = false; + break; + } + } + if (allExisted) + { + captureCompleted = true; + } + } + if (captureCompleted && !mCaptureDispatched) { mCaptureDispatched = true; @@ -1970,6 +2018,44 @@ void NdkCamera::onCaptureCompleted(ACameraCaptureSession* session, ACaptureReque } } +int64_t NdkCamera::GetTimestamp(const ACameraMetadata* result) +{ + ACameraMetadata_const_entry entry; + camera_status_t status = ACameraMetadata_getConstEntry(result, ACAMERA_SENSOR_TIMESTAMP, &entry); + + if (status == ACAMERA_OK && entry.count > 0) { + return entry.data.i64[0]; + } + + return 0; +} + +void NdkCamera::FireOneCapture(uint64_t ts) +{ +#ifdef OUTPUT_DBG_INFO + if (mWidth == 1920 && mOneFrame.size() > 1) + { + std::string dt = FormatLocalDateTime("%d%02d%02d%02d%02d%02d", ts / 1000); + std::vector params; + params.push_back(cv::IMWRITE_JPEG_QUALITY); + params.push_back(50); + + for (auto it = mOneFrame.cbegin(); it != mOneFrame.cend(); ++it) + { + std::string fileName = "/sdcard/com.xypower.mpapp/tmp/" + dt; + size_t idx = std::distance(mOneFrame.cbegin(), it); + std::shared_ptr result = mCaptureResults[idx]; + CAPTURE_RESULT captureResult = { 0 }; + EnumCameraResult(result.get(), captureResult); + + fileName += "_" + mCameraId + "_" + std::to_string(captureResult.aeState) + "_" + std::to_string(idx) + ".jpg"; + cv::imwrite(fileName, it->second, params); + } + } +#endif + onOneCapture(mCharacteristics, mCaptureResults.back(), mFinalLdr, ts - m_startTime, mOneFrame.back().second); +} + void NdkCamera::FireBurstCapture() { unsigned long long ts = GetMicroTimeStamp(); diff --git a/app/src/main/cpp/camera2/ndkcamera.h b/app/src/main/cpp/camera2/ndkcamera.h index 71ccfae5..7e6a21ba 100644 --- a/app/src/main/cpp/camera2/ndkcamera.h +++ b/app/src/main/cpp/camera2/ndkcamera.h @@ -23,6 +23,7 @@ #include #include "Camera2Helper.h" #include +#include #include /** @@ -192,6 +193,7 @@ public: } bool IsCameraAvailable(const std::string& cameraId); + int64_t GetTimestamp(const ACameraMetadata* result); static bool convertAImageToNv21(AImage* image, uint8_t** nv21, int32_t& width, int32_t& height); static void EnumCameraResult(ACameraMetadata* result, CAPTURE_RESULT& captureResult); @@ -266,13 +268,15 @@ protected: std::shared_ptr mPreviewResults; std::vector > mCaptureResults; + std::map > mCaptureResultMap; uint32_t mLdr; uint32_t mFinalLdr; uint32_t mFinalBurstCaptures; int32_t mFinalOutputFormat; std::vector > mCaptureFrames; - cv::Mat mOneFrame; + // cv::Mat mOneFrame; + std::vector > mOneFrame; std::vector > mRawFrames; ACameraCaptureSession* capture_session;