Loading services/camera/virtualcamera/VirtualCameraRenderThread.cc +40 −10 Original line number Diff line number Diff line Loading @@ -14,7 +14,6 @@ * limitations under the License. */ #include "hardware/gralloc.h" #define LOG_TAG "VirtualCameraRenderThread" #include "VirtualCameraRenderThread.h" Loading Loading @@ -45,6 +44,7 @@ #include "android-base/thread_annotations.h" #include "android/binder_auto_utils.h" #include "android/hardware_buffer.h" #include "hardware/gralloc.h" #include "system/camera_metadata.h" #include "ui/GraphicBuffer.h" #include "ui/Rect.h" Loading Loading @@ -422,9 +422,47 @@ void VirtualCameraRenderThread::threadLoop() { void VirtualCameraRenderThread::processCaptureRequest( const ProcessCaptureRequestTask& request) { const std::chrono::nanoseconds timestamp = if (mTestMode) { // In test mode let's just render something to the Surface ourselves. renderTestPatternYCbCr420(mEglSurfaceTexture->getSurface(), request.getFrameNumber()); } std::chrono::nanoseconds timestamp = std::chrono::duration_cast<std::chrono::nanoseconds>( std::chrono::steady_clock::now().time_since_epoch()); std::chrono::nanoseconds lastAcquisitionTimestamp( mLastAcquisitionTimestampNanoseconds.exchange(timestamp.count(), std::memory_order_relaxed)); if (request.getRequestSettings().fpsRange) { const int maxFps = std::max(1, request.getRequestSettings().fpsRange->maxFps); const std::chrono::nanoseconds minFrameDuration( static_cast<uint64_t>(1e9 / maxFps)); const std::chrono::nanoseconds frameDuration = timestamp - lastAcquisitionTimestamp; if (frameDuration < minFrameDuration) { // We're too fast for the configured maxFps, let's wait a bit. const std::chrono::nanoseconds sleepTime = minFrameDuration - frameDuration; ALOGV("Current frame duration would be %" PRIu64 " ns corresponding to, " "sleeping for %" PRIu64 " ns before updating texture to match maxFps %d", static_cast<uint64_t>(frameDuration.count()), static_cast<uint64_t>(sleepTime.count()), maxFps); std::this_thread::sleep_for(sleepTime); timestamp = std::chrono::duration_cast<std::chrono::nanoseconds>( std::chrono::steady_clock::now().time_since_epoch()); mLastAcquisitionTimestampNanoseconds.store(timestamp.count(), std::memory_order_relaxed); } } // Acquire new (most recent) image from the Surface. mEglSurfaceTexture->updateTexture(); CaptureResult captureResult; captureResult.fmqResultSize = 0; Loading @@ -439,14 +477,6 @@ void VirtualCameraRenderThread::processCaptureRequest( const std::vector<CaptureRequestBuffer>& buffers = request.getBuffers(); captureResult.outputBuffers.resize(buffers.size()); if (mTestMode) { // In test mode let's just render something to the Surface ourselves. renderTestPatternYCbCr420(mEglSurfaceTexture->getSurface(), request.getFrameNumber()); } mEglSurfaceTexture->updateTexture(); for (int i = 0; i < buffers.size(); ++i) { const CaptureRequestBuffer& reqBuffer = buffers[i]; StreamBuffer& resBuffer = captureResult.outputBuffers[i]; Loading services/camera/virtualcamera/VirtualCameraRenderThread.h +4 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #ifndef ANDROID_COMPANION_VIRTUALCAMERA_VIRTUALCAMERARENDERTHREAD_H #define ANDROID_COMPANION_VIRTUALCAMERA_VIRTUALCAMERARENDERTHREAD_H #include <atomic> #include <cstdint> #include <deque> #include <future> Loading Loading @@ -195,6 +196,9 @@ class VirtualCameraRenderThread { std::condition_variable mCondVar; volatile bool mPendingExit GUARDED_BY(mLock); // Acquisition timestamp of last frame. std::atomic<uint64_t> mLastAcquisitionTimestampNanoseconds; // EGL helpers - constructed and accessed only from rendering thread. std::unique_ptr<EglDisplayContext> mEglDisplayContext; std::unique_ptr<EglTextureProgram> mEglTextureYuvProgram; Loading Loading
services/camera/virtualcamera/VirtualCameraRenderThread.cc +40 −10 Original line number Diff line number Diff line Loading @@ -14,7 +14,6 @@ * limitations under the License. */ #include "hardware/gralloc.h" #define LOG_TAG "VirtualCameraRenderThread" #include "VirtualCameraRenderThread.h" Loading Loading @@ -45,6 +44,7 @@ #include "android-base/thread_annotations.h" #include "android/binder_auto_utils.h" #include "android/hardware_buffer.h" #include "hardware/gralloc.h" #include "system/camera_metadata.h" #include "ui/GraphicBuffer.h" #include "ui/Rect.h" Loading Loading @@ -422,9 +422,47 @@ void VirtualCameraRenderThread::threadLoop() { void VirtualCameraRenderThread::processCaptureRequest( const ProcessCaptureRequestTask& request) { const std::chrono::nanoseconds timestamp = if (mTestMode) { // In test mode let's just render something to the Surface ourselves. renderTestPatternYCbCr420(mEglSurfaceTexture->getSurface(), request.getFrameNumber()); } std::chrono::nanoseconds timestamp = std::chrono::duration_cast<std::chrono::nanoseconds>( std::chrono::steady_clock::now().time_since_epoch()); std::chrono::nanoseconds lastAcquisitionTimestamp( mLastAcquisitionTimestampNanoseconds.exchange(timestamp.count(), std::memory_order_relaxed)); if (request.getRequestSettings().fpsRange) { const int maxFps = std::max(1, request.getRequestSettings().fpsRange->maxFps); const std::chrono::nanoseconds minFrameDuration( static_cast<uint64_t>(1e9 / maxFps)); const std::chrono::nanoseconds frameDuration = timestamp - lastAcquisitionTimestamp; if (frameDuration < minFrameDuration) { // We're too fast for the configured maxFps, let's wait a bit. const std::chrono::nanoseconds sleepTime = minFrameDuration - frameDuration; ALOGV("Current frame duration would be %" PRIu64 " ns corresponding to, " "sleeping for %" PRIu64 " ns before updating texture to match maxFps %d", static_cast<uint64_t>(frameDuration.count()), static_cast<uint64_t>(sleepTime.count()), maxFps); std::this_thread::sleep_for(sleepTime); timestamp = std::chrono::duration_cast<std::chrono::nanoseconds>( std::chrono::steady_clock::now().time_since_epoch()); mLastAcquisitionTimestampNanoseconds.store(timestamp.count(), std::memory_order_relaxed); } } // Acquire new (most recent) image from the Surface. mEglSurfaceTexture->updateTexture(); CaptureResult captureResult; captureResult.fmqResultSize = 0; Loading @@ -439,14 +477,6 @@ void VirtualCameraRenderThread::processCaptureRequest( const std::vector<CaptureRequestBuffer>& buffers = request.getBuffers(); captureResult.outputBuffers.resize(buffers.size()); if (mTestMode) { // In test mode let's just render something to the Surface ourselves. renderTestPatternYCbCr420(mEglSurfaceTexture->getSurface(), request.getFrameNumber()); } mEglSurfaceTexture->updateTexture(); for (int i = 0; i < buffers.size(); ++i) { const CaptureRequestBuffer& reqBuffer = buffers[i]; StreamBuffer& resBuffer = captureResult.outputBuffers[i]; Loading
services/camera/virtualcamera/VirtualCameraRenderThread.h +4 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #ifndef ANDROID_COMPANION_VIRTUALCAMERA_VIRTUALCAMERARENDERTHREAD_H #define ANDROID_COMPANION_VIRTUALCAMERA_VIRTUALCAMERARENDERTHREAD_H #include <atomic> #include <cstdint> #include <deque> #include <future> Loading Loading @@ -195,6 +196,9 @@ class VirtualCameraRenderThread { std::condition_variable mCondVar; volatile bool mPendingExit GUARDED_BY(mLock); // Acquisition timestamp of last frame. std::atomic<uint64_t> mLastAcquisitionTimestampNanoseconds; // EGL helpers - constructed and accessed only from rendering thread. std::unique_ptr<EglDisplayContext> mEglDisplayContext; std::unique_ptr<EglTextureProgram> mEglTextureYuvProgram; Loading