Camera: fill in Camera3Device offline processing impl

Move shared method implementations to Camera3OutputUtils.cpp/h
Defined interfaces to handle Camera3Device/Camera3OfflineSession
behavior differences in Camera3OutputInterface.h.

Bug: 135142453
Test: N/A (not enough implementation yet)
Change-Id: I57476ca5a1edf69c02a22241ad776d6f02636033
gugelfrei
Yin-Chia Yeh 5 years ago
parent 56d98ba800
commit 5fd603ea87

@ -46,6 +46,7 @@ cc_library_shared {
"api2/HeicEncoderInfoManager.cpp",
"api2/HeicCompositeStream.cpp",
"device1/CameraHardwareInterface.cpp",
"device3/BufferUtils.cpp",
"device3/Camera3Device.cpp",
"device3/Camera3OfflineSession.cpp",
"device3/Camera3Stream.cpp",
@ -60,6 +61,8 @@ cc_library_shared {
"device3/CoordinateMapper.cpp",
"device3/DistortionMapper.cpp",
"device3/ZoomRatioMapper.cpp",
"device3/Camera3OutputStreamInterface.cpp",
"device3/Camera3OutputUtils.cpp",
"gui/RingBufferConsumer.cpp",
"utils/CameraThreadState.cpp",
"hidl/AidlCameraDeviceCallbacks.cpp",

@ -111,7 +111,7 @@ status_t Camera2ClientBase<TClientBase>::initializeImpl(TProviderPtr providerPtr
return res;
}
wp<CameraDeviceBase::NotificationListener> weakThis(this);
wp<NotificationListener> weakThis(this);
res = mDevice->setNotifyCallback(weakThis);
return OK;

@ -29,7 +29,7 @@ class CameraService;
template <typename TClientBase>
class Camera2ClientBase :
public TClientBase,
public CameraDeviceBase::NotificationListener
public NotificationListener
{
public:
typedef typename TClientBase::TCamCallbacks TCamCallbacks;
@ -61,7 +61,7 @@ public:
virtual status_t dumpClient(int fd, const Vector<String16>& args);
/**
* CameraDeviceBase::NotificationListener implementation
* NotificationListener implementation
*/
virtual void notifyError(int32_t errorCode,

@ -24,7 +24,4 @@ namespace android {
CameraDeviceBase::~CameraDeviceBase() {
}
CameraDeviceBase::NotificationListener::~NotificationListener() {
}
} // namespace android

@ -258,35 +258,6 @@ class CameraDeviceBase : public virtual RefBase {
*/
virtual ssize_t getJpegBufferSize(uint32_t width, uint32_t height) const = 0;
/**
* Abstract class for HAL notification listeners
*/
class NotificationListener : public virtual RefBase {
public:
// The set of notifications is a merge of the notifications required for
// API1 and API2.
// Required for API 1 and 2
virtual void notifyError(int32_t errorCode,
const CaptureResultExtras &resultExtras) = 0;
// Required only for API2
virtual void notifyIdle() = 0;
virtual void notifyShutter(const CaptureResultExtras &resultExtras,
nsecs_t timestamp) = 0;
virtual void notifyPrepared(int streamId) = 0;
virtual void notifyRequestQueueEmpty() = 0;
// Required only for API1
virtual void notifyAutoFocus(uint8_t newState, int triggerId) = 0;
virtual void notifyAutoExposure(uint8_t newState, int triggerId) = 0;
virtual void notifyAutoWhitebalance(uint8_t newState,
int triggerId) = 0;
virtual void notifyRepeatingRequestError(long lastFrameNumber) = 0;
protected:
virtual ~NotificationListener();
};
/**
* Connect HAL notifications to a listener. Overwrites previous
* listener. Set to NULL to stop receiving notifications.

@ -25,10 +25,42 @@
namespace android {
/**
* Abstract class for HAL notification listeners
*/
class NotificationListener : public virtual RefBase {
public:
// The set of notifications is a merge of the notifications required for
// API1 and API2.
// Required for API 1 and 2
virtual void notifyError(int32_t errorCode,
const CaptureResultExtras &resultExtras) = 0;
// Required only for API2
virtual void notifyIdle() = 0;
virtual void notifyShutter(const CaptureResultExtras &resultExtras,
nsecs_t timestamp) = 0;
virtual void notifyPrepared(int streamId) = 0;
virtual void notifyRequestQueueEmpty() = 0;
// Required only for API1
virtual void notifyAutoFocus(uint8_t newState, int triggerId) = 0;
virtual void notifyAutoExposure(uint8_t newState, int triggerId) = 0;
virtual void notifyAutoWhitebalance(uint8_t newState,
int triggerId) = 0;
virtual void notifyRepeatingRequestError(long lastFrameNumber) = 0;
protected:
virtual ~NotificationListener() {}
};
class CameraOfflineSessionBase : public virtual RefBase {
public:
virtual ~CameraOfflineSessionBase();
virtual status_t initialize(
wp<NotificationListener> listener) = 0;
// The session's original camera ID
virtual const String8& getId() const = 0;
@ -36,8 +68,6 @@ class CameraOfflineSessionBase : public virtual RefBase {
virtual status_t dump(int fd) = 0;
virtual status_t abort() = 0;
/**
* Capture result passing
*/

@ -0,0 +1,277 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "Camera3-BufUtils"
#define ATRACE_TAG ATRACE_TAG_CAMERA
//#define LOG_NDEBUG 0
//#define LOG_NNDEBUG 0 // Per-frame verbose logging
#include <inttypes.h>
#include <utils/Log.h>
#include "device3/BufferUtils.h"
namespace android {
namespace camera3 {
camera3_buffer_status_t mapHidlBufferStatus(hardware::camera::device::V3_2::BufferStatus status) {
using hardware::camera::device::V3_2::BufferStatus;
switch (status) {
case BufferStatus::OK: return CAMERA3_BUFFER_STATUS_OK;
case BufferStatus::ERROR: return CAMERA3_BUFFER_STATUS_ERROR;
}
return CAMERA3_BUFFER_STATUS_ERROR;
}
void BufferRecords::takeInflightBufferMap(BufferRecords& other) {
std::lock_guard<std::mutex> oLock(other.mInflightLock);
std::lock_guard<std::mutex> lock(mInflightLock);
if (mInflightBufferMap.size() > 0) {
ALOGE("%s: inflight map is set in non-empty state!", __FUNCTION__);
}
mInflightBufferMap = std::move(other.mInflightBufferMap);
other.mInflightBufferMap.clear();
}
void BufferRecords::takeRequestedBufferMap(BufferRecords& other) {
std::lock_guard<std::mutex> oLock(other.mRequestedBuffersLock);
std::lock_guard<std::mutex> lock(mRequestedBuffersLock);
if (mRequestedBufferMap.size() > 0) {
ALOGE("%s: requested buffer map is set in non-empty state!", __FUNCTION__);
}
mRequestedBufferMap = std::move(other.mRequestedBufferMap);
other.mRequestedBufferMap.clear();
}
void BufferRecords::takeBufferCaches(BufferRecords& other, const std::vector<int32_t>& streams) {
std::lock_guard<std::mutex> oLock(other.mBufferIdMapLock);
std::lock_guard<std::mutex> lock(mBufferIdMapLock);
if (mBufferIdMaps.size() > 0) {
ALOGE("%s: buffer ID map is set in non-empty state!", __FUNCTION__);
}
for (auto streamId : streams) {
mBufferIdMaps.insert({streamId, std::move(other.mBufferIdMaps.at(streamId))});
}
other.mBufferIdMaps.clear();
}
std::pair<bool, uint64_t> BufferRecords::getBufferId(
const buffer_handle_t& buf, int streamId) {
std::lock_guard<std::mutex> lock(mBufferIdMapLock);
BufferIdMap& bIdMap = mBufferIdMaps.at(streamId);
auto it = bIdMap.find(buf);
if (it == bIdMap.end()) {
bIdMap[buf] = mNextBufferId++;
ALOGV("stream %d now have %zu buffer caches, buf %p",
streamId, bIdMap.size(), buf);
return std::make_pair(true, mNextBufferId - 1);
} else {
return std::make_pair(false, it->second);
}
}
void BufferRecords::tryCreateBufferCache(int streamId) {
std::lock_guard<std::mutex> lock(mBufferIdMapLock);
if (mBufferIdMaps.count(streamId) == 0) {
mBufferIdMaps.emplace(streamId, BufferIdMap{});
}
}
void BufferRecords::removeInactiveBufferCaches(const std::set<int32_t>& activeStreams) {
std::lock_guard<std::mutex> lock(mBufferIdMapLock);
for(auto it = mBufferIdMaps.begin(); it != mBufferIdMaps.end();) {
int streamId = it->first;
bool active = activeStreams.count(streamId) > 0;
if (!active) {
it = mBufferIdMaps.erase(it);
} else {
++it;
}
}
}
uint64_t BufferRecords::removeOneBufferCache(int streamId, const native_handle_t* handle) {
std::lock_guard<std::mutex> lock(mBufferIdMapLock);
uint64_t bufferId = BUFFER_ID_NO_BUFFER;
auto mapIt = mBufferIdMaps.find(streamId);
if (mapIt == mBufferIdMaps.end()) {
// streamId might be from a deleted stream here
ALOGI("%s: stream %d has been removed",
__FUNCTION__, streamId);
return BUFFER_ID_NO_BUFFER;
}
BufferIdMap& bIdMap = mapIt->second;
auto it = bIdMap.find(handle);
if (it == bIdMap.end()) {
ALOGW("%s: cannot find buffer %p in stream %d",
__FUNCTION__, handle, streamId);
return BUFFER_ID_NO_BUFFER;
} else {
bufferId = it->second;
bIdMap.erase(it);
ALOGV("%s: stream %d now have %zu buffer caches after removing buf %p",
__FUNCTION__, streamId, bIdMap.size(), handle);
}
return bufferId;
}
std::vector<uint64_t> BufferRecords::clearBufferCaches(int streamId) {
std::lock_guard<std::mutex> lock(mBufferIdMapLock);
std::vector<uint64_t> ret;
auto mapIt = mBufferIdMaps.find(streamId);
if (mapIt == mBufferIdMaps.end()) {
ALOGE("%s: streamId %d not found!", __FUNCTION__, streamId);
return ret;
}
BufferIdMap& bIdMap = mapIt->second;
ret.reserve(bIdMap.size());
for (const auto& it : bIdMap) {
ret.push_back(it.second);
}
bIdMap.clear();
return ret;
}
bool BufferRecords::isStreamCached(int streamId) {
std::lock_guard<std::mutex> lock(mBufferIdMapLock);
return mBufferIdMaps.find(streamId) != mBufferIdMaps.end();
}
bool BufferRecords::verifyBufferIds(
int32_t streamId, std::vector<uint64_t>& bufIds) {
std::lock_guard<std::mutex> lock(mBufferIdMapLock);
camera3::BufferIdMap& bIdMap = mBufferIdMaps.at(streamId);
if (bIdMap.size() != bufIds.size()) {
ALOGE("%s: stream ID %d buffer cache number mismatch: %zu/%zu (service/HAL)",
__FUNCTION__, streamId, bIdMap.size(), bufIds.size());
return false;
}
std::vector<uint64_t> internalBufIds;
internalBufIds.reserve(bIdMap.size());
for (const auto& pair : bIdMap) {
internalBufIds.push_back(pair.second);
}
std::sort(bufIds.begin(), bufIds.end());
std::sort(internalBufIds.begin(), internalBufIds.end());
for (size_t i = 0; i < bufIds.size(); i++) {
if (bufIds[i] != internalBufIds[i]) {
ALOGE("%s: buffer cache mismatch! Service %" PRIu64 ", HAL %" PRIu64,
__FUNCTION__, internalBufIds[i], bufIds[i]);
return false;
}
}
return true;
}
void BufferRecords::getInflightBufferKeys(
std::vector<std::pair<int32_t, int32_t>>* out) {
std::lock_guard<std::mutex> lock(mInflightLock);
out->clear();
out->reserve(mInflightBufferMap.size());
for (auto& pair : mInflightBufferMap) {
uint64_t key = pair.first;
int32_t streamId = key & 0xFFFFFFFF;
int32_t frameNumber = (key >> 32) & 0xFFFFFFFF;
out->push_back(std::make_pair(frameNumber, streamId));
}
return;
}
status_t BufferRecords::pushInflightBuffer(
int32_t frameNumber, int32_t streamId, buffer_handle_t *buffer) {
std::lock_guard<std::mutex> lock(mInflightLock);
uint64_t key = static_cast<uint64_t>(frameNumber) << 32 | static_cast<uint64_t>(streamId);
mInflightBufferMap[key] = buffer;
return OK;
}
status_t BufferRecords::popInflightBuffer(
int32_t frameNumber, int32_t streamId,
/*out*/ buffer_handle_t **buffer) {
std::lock_guard<std::mutex> lock(mInflightLock);
uint64_t key = static_cast<uint64_t>(frameNumber) << 32 | static_cast<uint64_t>(streamId);
auto it = mInflightBufferMap.find(key);
if (it == mInflightBufferMap.end()) return NAME_NOT_FOUND;
if (buffer != nullptr) {
*buffer = it->second;
}
mInflightBufferMap.erase(it);
return OK;
}
void BufferRecords::popInflightBuffers(
const std::vector<std::pair<int32_t, int32_t>>& buffers) {
for (const auto& pair : buffers) {
int32_t frameNumber = pair.first;
int32_t streamId = pair.second;
popInflightBuffer(frameNumber, streamId, nullptr);
}
}
status_t BufferRecords::pushInflightRequestBuffer(
uint64_t bufferId, buffer_handle_t* buf, int32_t streamId) {
std::lock_guard<std::mutex> lock(mRequestedBuffersLock);
auto pair = mRequestedBufferMap.insert({bufferId, {streamId, buf}});
if (!pair.second) {
ALOGE("%s: bufId %" PRIu64 " is already inflight!",
__FUNCTION__, bufferId);
return BAD_VALUE;
}
return OK;
}
// Find and pop a buffer_handle_t based on bufferId
status_t BufferRecords::popInflightRequestBuffer(
uint64_t bufferId,
/*out*/ buffer_handle_t** buffer,
/*optional out*/ int32_t* streamId) {
if (buffer == nullptr) {
ALOGE("%s: buffer (%p) must not be null", __FUNCTION__, buffer);
return BAD_VALUE;
}
std::lock_guard<std::mutex> lock(mRequestedBuffersLock);
auto it = mRequestedBufferMap.find(bufferId);
if (it == mRequestedBufferMap.end()) {
ALOGE("%s: bufId %" PRIu64 " is not inflight!",
__FUNCTION__, bufferId);
return BAD_VALUE;
}
*buffer = it->second.second;
if (streamId != nullptr) {
*streamId = it->second.first;
}
mRequestedBufferMap.erase(it);
return OK;
}
void BufferRecords::getInflightRequestBufferKeys(
std::vector<uint64_t>* out) {
std::lock_guard<std::mutex> lock(mRequestedBuffersLock);
out->clear();
out->reserve(mRequestedBufferMap.size());
for (auto& pair : mRequestedBufferMap) {
out->push_back(pair.first);
}
return;
}
} // camera3
} // namespace android

@ -0,0 +1,167 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_SERVERS_CAMERA3_BUFFER_UTILS_H
#define ANDROID_SERVERS_CAMERA3_BUFFER_UTILS_H
#include <unordered_map>
#include <mutex>
#include <set>
#include <cutils/native_handle.h>
#include <android/hardware/camera/device/3.2/ICameraDevice.h>
// TODO: remove legacy camera3.h references
#include "hardware/camera3.h"
#include <device3/Camera3OutputInterface.h>
namespace android {
namespace camera3 {
struct BufferHasher {
size_t operator()(const buffer_handle_t& buf) const {
if (buf == nullptr)
return 0;
size_t result = 1;
result = 31 * result + buf->numFds;
for (int i = 0; i < buf->numFds; i++) {
result = 31 * result + buf->data[i];
}
return result;
}
};
struct BufferComparator {
bool operator()(const buffer_handle_t& buf1, const buffer_handle_t& buf2) const {
if (buf1->numFds == buf2->numFds) {
for (int i = 0; i < buf1->numFds; i++) {
if (buf1->data[i] != buf2->data[i]) {
return false;
}
}
return true;
}
return false;
}
};
// Per stream buffer native handle -> bufId map
typedef std::unordered_map<const buffer_handle_t, uint64_t,
BufferHasher, BufferComparator> BufferIdMap;
// streamId -> BufferIdMap
typedef std::unordered_map<int, BufferIdMap> BufferIdMaps;
// Map of inflight buffers sent along in capture requests.
// Key is composed by (frameNumber << 32 | streamId)
typedef std::unordered_map<uint64_t, buffer_handle_t*> InflightBufferMap;
// Map of inflight buffers dealt by requestStreamBuffers API
typedef std::unordered_map<uint64_t, std::pair<int32_t, buffer_handle_t*>> RequestedBufferMap;
// A struct containing all buffer tracking information like inflight buffers
// and buffer ID caches
class BufferRecords : public BufferRecordsInterface {
public:
BufferRecords() {}
BufferRecords(BufferRecords&& other) :
mBufferIdMaps(other.mBufferIdMaps),
mNextBufferId(other.mNextBufferId),
mInflightBufferMap(other.mInflightBufferMap),
mRequestedBufferMap(other.mRequestedBufferMap) {}
virtual ~BufferRecords() {}
// Helper methods to help moving buffer records
void takeInflightBufferMap(BufferRecords& other);
void takeRequestedBufferMap(BufferRecords& other);
void takeBufferCaches(BufferRecords& other, const std::vector<int32_t>& streams);
// method to extract buffer's unique ID
// return pair of (newlySeenBuffer?, bufferId)
virtual std::pair<bool, uint64_t> getBufferId(
const buffer_handle_t& buf, int streamId) override;
void tryCreateBufferCache(int streamId);
void removeInactiveBufferCaches(const std::set<int32_t>& activeStreams);
// Return the removed buffer ID if input cache is found.
// Otherwise return BUFFER_ID_NO_BUFFER
uint64_t removeOneBufferCache(int streamId, const native_handle_t* handle);
// Clear all caches for input stream, but do not remove the stream
// Removed buffers' ID are returned
std::vector<uint64_t> clearBufferCaches(int streamId);
bool isStreamCached(int streamId);
// Return true if the input caches match what we have; otherwise false
bool verifyBufferIds(int32_t streamId, std::vector<uint64_t>& inBufIds);
// Get a vector of (frameNumber, streamId) pair of currently inflight
// buffers
void getInflightBufferKeys(std::vector<std::pair<int32_t, int32_t>>* out);
status_t pushInflightBuffer(int32_t frameNumber, int32_t streamId,
buffer_handle_t *buffer);
// Find a buffer_handle_t based on frame number and stream ID
virtual status_t popInflightBuffer(int32_t frameNumber, int32_t streamId,
/*out*/ buffer_handle_t **buffer) override;
// Pop inflight buffers based on pairs of (frameNumber,streamId)
void popInflightBuffers(const std::vector<std::pair<int32_t, int32_t>>& buffers);
// Get a vector of bufferId of currently inflight buffers
void getInflightRequestBufferKeys(std::vector<uint64_t>* out);
// Register a bufId (streamId, buffer_handle_t) to inflight request buffer
virtual status_t pushInflightRequestBuffer(
uint64_t bufferId, buffer_handle_t* buf, int32_t streamId) override;
// Find a buffer_handle_t based on bufferId
virtual status_t popInflightRequestBuffer(uint64_t bufferId,
/*out*/ buffer_handle_t** buffer,
/*optional out*/ int32_t* streamId = nullptr) override;
private:
std::mutex mBufferIdMapLock;
BufferIdMaps mBufferIdMaps;
uint64_t mNextBufferId = 1; // 0 means no buffer
std::mutex mInflightLock;
InflightBufferMap mInflightBufferMap;
std::mutex mRequestedBuffersLock;
RequestedBufferMap mRequestedBufferMap;
}; // class BufferRecords
static const uint64_t BUFFER_ID_NO_BUFFER = 0;
camera3_buffer_status_t mapHidlBufferStatus(
hardware::camera::device::V3_2::BufferStatus status);
} // namespace camera3
} // namespace android
#endif

File diff suppressed because it is too large Load Diff

@ -43,10 +43,14 @@
#include <camera/CaptureResult.h>
#include "common/CameraDeviceBase.h"
#include "device3/BufferUtils.h"
#include "device3/StatusTracker.h"
#include "device3/Camera3BufferManager.h"
#include "device3/DistortionMapper.h"
#include "device3/ZoomRatioMapper.h"
#include "device3/InFlightRequest.h"
#include "device3/Camera3OutputInterface.h"
#include "device3/Camera3OfflineSession.h"
#include "utils/TagMonitor.h"
#include "utils/LatencyHistogram.h"
#include <camera_metadata_hidden.h>
@ -69,7 +73,11 @@ class Camera3StreamInterface;
*/
class Camera3Device :
public CameraDeviceBase,
virtual public hardware::camera::device::V3_5::ICameraDeviceCallback {
virtual public hardware::camera::device::V3_5::ICameraDeviceCallback,
public camera3::SetErrorInterface,
public camera3::InflightRequestUpdateInterface,
public camera3::RequestBufferInterface,
public camera3::FlushBufferInterface {
public:
explicit Camera3Device(const String8& id);
@ -201,6 +209,16 @@ class Camera3Device :
status_t switchToOffline(const std::vector<int32_t>& streamsToKeep,
/*out*/ sp<CameraOfflineSessionBase>* session) override;
// RequestBufferInterface
bool startRequestBuffer() override;
void endRequestBuffer() override;
nsecs_t getWaitDuration() override;
// FlushBufferInterface
void getInflightBufferKeys(std::vector<std::pair<int32_t, int32_t>>* out) override;
void getInflightRequestBufferKeys(std::vector<uint64_t>* out) override;
std::vector<sp<camera3::Camera3StreamInterface>> getAllStreams() override;
/**
* Helper functions to map between framework and HIDL values
*/
@ -213,8 +231,6 @@ class Camera3Device :
// Returns a negative error code if the passed-in operation mode is not valid.
static status_t mapToStreamConfigurationMode(camera3_stream_configuration_mode_t operationMode,
/*out*/ hardware::camera::device::V3_2::StreamConfigurationMode *mode);
static camera3_buffer_status_t mapHidlBufferStatus(
hardware::camera::device::V3_2::BufferStatus status);
static int mapToFrameworkFormat(hardware::graphics::common::V1_0::PixelFormat pixelFormat);
static android_dataspace mapToFrameworkDataspace(
hardware::camera::device::V3_2::DataspaceFlags);
@ -229,7 +245,6 @@ class Camera3Device :
// internal typedefs
using RequestMetadataQueue = hardware::MessageQueue<uint8_t, hardware::kSynchronizedReadWrite>;
using ResultMetadataQueue = hardware::MessageQueue<uint8_t, hardware::kSynchronizedReadWrite>;
static const size_t kDumpLockAttempts = 10;
static const size_t kDumpSleepDuration = 100000; // 0.10 sec
@ -283,7 +298,8 @@ class Camera3Device :
* Adapter for legacy HAL / HIDL HAL interface calls; calls either into legacy HALv3 or the
* HIDL HALv3 interfaces.
*/
class HalInterface : public camera3::Camera3StreamBufferFreedListener {
class HalInterface : public camera3::Camera3StreamBufferFreedListener,
public camera3::BufferRecordsInterface {
public:
HalInterface(sp<hardware::camera::device::V3_2::ICameraDeviceSession> &session,
std::shared_ptr<RequestMetadataQueue> queue,
@ -321,27 +337,31 @@ class Camera3Device :
bool isReconfigurationRequired(CameraMetadata& oldSessionParams,
CameraMetadata& newSessionParams);
// Upon successful return, HalInterface will return buffer maps needed for offline
// processing, and clear all its internal buffer maps.
status_t switchToOffline(
const std::vector<int32_t>& streamsToKeep,
/*out*/hardware::camera::device::V3_6::CameraOfflineSessionInfo* offlineSessionInfo,
/*out*/sp<hardware::camera::device::V3_6::ICameraOfflineSession>* offlineSession);
/*out*/sp<hardware::camera::device::V3_6::ICameraOfflineSession>* offlineSession,
/*out*/camera3::BufferRecords* bufferRecords);
/////////////////////////////////////////////////////////////////////
// Implements BufferRecordsInterface
// method to extract buffer's unique ID
// return pair of (newlySeenBuffer?, bufferId)
std::pair<bool, uint64_t> getBufferId(const buffer_handle_t& buf, int streamId);
std::pair<bool, uint64_t> getBufferId(
const buffer_handle_t& buf, int streamId) override;
// Find a buffer_handle_t based on frame number and stream ID
status_t popInflightBuffer(int32_t frameNumber, int32_t streamId,
/*out*/ buffer_handle_t **buffer);
/*out*/ buffer_handle_t **buffer) override;
// Register a bufId (streamId, buffer_handle_t) to inflight request buffer
status_t pushInflightRequestBuffer(
uint64_t bufferId, buffer_handle_t* buf, int32_t streamId);
uint64_t bufferId, buffer_handle_t* buf, int32_t streamId) override;
// Find a buffer_handle_t based on bufferId
status_t popInflightRequestBuffer(uint64_t bufferId,
/*out*/ buffer_handle_t** buffer,
/*optional out*/ int32_t* streamId = nullptr);
/*optional out*/ int32_t* streamId = nullptr) override;
/////////////////////////////////////////////////////////////////////
// Get a vector of (frameNumber, streamId) pair of currently inflight
// buffers
@ -352,7 +372,6 @@ class Camera3Device :
void onStreamReConfigured(int streamId);
static const uint64_t BUFFER_ID_NO_BUFFER = 0;
private:
// Always valid
sp<hardware::camera::device::V3_2::ICameraDeviceSession> mHidlSession;
@ -367,8 +386,6 @@ class Camera3Device :
std::shared_ptr<RequestMetadataQueue> mRequestMetadataQueue;
std::mutex mInflightLock;
// The output HIDL request still depends on input camera3_capture_request_t
// Do not free input camera3_capture_request_t before output HIDL request
status_t wrapAsHidlRequest(camera3_capture_request_t* in,
@ -382,55 +399,20 @@ class Camera3Device :
// Pop inflight buffers based on pairs of (frameNumber,streamId)
void popInflightBuffers(const std::vector<std::pair<int32_t, int32_t>>& buffers);
// Cache of buffer handles keyed off (frameNumber << 32 | streamId)
std::unordered_map<uint64_t, buffer_handle_t*> mInflightBufferMap;
// Return true if the input caches match what we have; otherwise false
bool verifyBufferIds(int32_t streamId, std::vector<uint64_t>& inBufIds);
// Delete and optionally close native handles and clear the input vector afterward
static void cleanupNativeHandles(
std::vector<native_handle_t*> *handles, bool closeFd = false);
struct BufferHasher {
size_t operator()(const buffer_handle_t& buf) const {
if (buf == nullptr)
return 0;
size_t result = 1;
result = 31 * result + buf->numFds;
for (int i = 0; i < buf->numFds; i++) {
result = 31 * result + buf->data[i];
}
return result;
}
};
struct BufferComparator {
bool operator()(const buffer_handle_t& buf1, const buffer_handle_t& buf2) const {
if (buf1->numFds == buf2->numFds) {
for (int i = 0; i < buf1->numFds; i++) {
if (buf1->data[i] != buf2->data[i]) {
return false;
}
}
return true;
}
return false;
}
};
std::mutex mBufferIdMapLock; // protecting mBufferIdMaps and mNextBufferId
typedef std::unordered_map<const buffer_handle_t, uint64_t,
BufferHasher, BufferComparator> BufferIdMap;
// stream ID -> per stream buffer ID map
std::unordered_map<int, BufferIdMap> mBufferIdMaps;
uint64_t mNextBufferId = 1; // 0 means no buffer
virtual void onBufferFreed(int streamId, const native_handle_t* handle) override;
std::mutex mFreedBuffersLock;
std::vector<std::pair<int, uint64_t>> mFreedBuffers;
// Buffers given to HAL through requestStreamBuffer API
std::mutex mRequestedBuffersLock;
std::unordered_map<uint64_t, std::pair<int32_t, buffer_handle_t*>> mRequestedBuffers;
// Keep track of buffer cache and inflight buffer records
camera3::BufferRecords mBufferRecords;
uint32_t mNextStreamConfigCounter = 1;
@ -473,24 +455,7 @@ class Camera3Device :
// Tracking cause of fatal errors when in STATUS_ERROR
String8 mErrorCause;
// Synchronized mapping of stream IDs to stream instances
class StreamSet {
public:
status_t add(int streamId, sp<camera3::Camera3OutputStreamInterface>);
ssize_t remove(int streamId);
sp<camera3::Camera3OutputStreamInterface> get(int streamId);
// get by (underlying) vector index
sp<camera3::Camera3OutputStreamInterface> operator[] (size_t index);
size_t size() const;
std::vector<int> getStreamIds();
void clear();
private:
mutable std::mutex mLock;
KeyedVector<int, sp<camera3::Camera3OutputStreamInterface>> mData;
};
StreamSet mOutputStreams;
camera3::StreamSet mOutputStreams;
sp<camera3::Camera3Stream> mInputStream;
int mNextStreamId;
bool mNeedConfig;
@ -579,15 +544,6 @@ class Camera3Device :
const hardware::hidl_vec<
hardware::camera::device::V3_2::StreamBuffer>& buffers) override;
// Handle one capture result. Assume that mProcessCaptureResultLock is held.
void processOneCaptureResultLocked(
const hardware::camera::device::V3_2::CaptureResult& result,
const hardware::hidl_vec<
hardware::camera::device::V3_4::PhysicalCameraMetadata> physicalCameraMetadata);
status_t readOneCameraMetadataLocked(uint64_t fmqResultSize,
hardware::camera::device::V3_2::CameraMetadata& resultMetadata,
const hardware::camera::device::V3_2::CameraMetadata& result);
// Handle one notify message
void notify(const hardware::camera::device::V3_2::NotifyMsg& msg);
@ -710,23 +666,26 @@ class Camera3Device :
* error message to indicate why. Only the first call's message will be
* used. The message is also sent to the log.
*/
void setErrorState(const char *fmt, ...);
void setErrorState(const char *fmt, ...) override;
void setErrorStateLocked(const char *fmt, ...) override;
void setErrorStateV(const char *fmt, va_list args);
void setErrorStateLocked(const char *fmt, ...);
void setErrorStateLockedV(const char *fmt, va_list args);
/////////////////////////////////////////////////////////////////////
// Implements InflightRequestUpdateInterface
void onInflightEntryRemovedLocked(nsecs_t duration) override;
void checkInflightMapLengthLocked() override;
void onInflightMapFlushedLocked() override;
/////////////////////////////////////////////////////////////////////
/**
* Debugging trylock/spin method
* Try to acquire a lock a few times with sleeps between before giving up.
*/
bool tryLockSpinRightRound(Mutex& lock);
/**
* Helper function to determine if an input size for implementation defined
* format is supported.
*/
bool isOpaqueInputSizeSupported(uint32_t width, uint32_t height);
/**
* Helper function to get the largest Jpeg resolution (in area)
* Return Size(0, 0) if static metatdata is invalid
@ -860,7 +819,8 @@ class Camera3Device :
status_t switchToOffline(
const std::vector<int32_t>& streamsToKeep,
/*out*/hardware::camera::device::V3_6::CameraOfflineSessionInfo* offlineSessionInfo,
/*out*/sp<hardware::camera::device::V3_6::ICameraOfflineSession>* offlineSession);
/*out*/sp<hardware::camera::device::V3_6::ICameraOfflineSession>* offlineSession,
/*out*/camera3::BufferRecords* bufferRecords);
protected:
@ -1021,119 +981,12 @@ class Camera3Device :
/**
* In-flight queue for tracking completion of capture requests.
*/
std::mutex mInFlightLock;
camera3::InFlightRequestMap mInFlightMap;
nsecs_t mExpectedInflightDuration = 0;
// End of mInFlightLock protection scope
struct InFlightRequest {
// Set by notify() SHUTTER call.
nsecs_t shutterTimestamp;
// Set by process_capture_result().
nsecs_t sensorTimestamp;
int requestStatus;
// Set by process_capture_result call with valid metadata
bool haveResultMetadata;
// Decremented by calls to process_capture_result with valid output
// and input buffers
int numBuffersLeft;
CaptureResultExtras resultExtras;
// If this request has any input buffer
bool hasInputBuffer;
// The last metadata that framework receives from HAL and
// not yet send out because the shutter event hasn't arrived.
// It's added by process_capture_result and sent when framework
// receives the shutter event.
CameraMetadata pendingMetadata;
// The metadata of the partial results that framework receives from HAL so far
// and has sent out.
CameraMetadata collectedPartialResult;
// Buffers are added by process_capture_result when output buffers
// return from HAL but framework has not yet received the shutter
// event. They will be returned to the streams when framework receives
// the shutter event.
Vector<camera3_stream_buffer_t> pendingOutputBuffers;
// Whether this inflight request's shutter and result callback are to be
// called. The policy is that if the request is the last one in the constrained
// high speed recording request list, this flag will be true. If the request list
// is not for constrained high speed recording, this flag will also be true.
bool hasCallback;
// Maximum expected frame duration for this request.
// For manual captures, equal to the max of requested exposure time and frame duration
// For auto-exposure modes, equal to 1/(lower end of target FPS range)
nsecs_t maxExpectedDuration;
// Whether the result metadata for this request is to be skipped. The
// result metadata should be skipped in the case of
// REQUEST/RESULT error.
bool skipResultMetadata;
// The physical camera ids being requested.
std::set<String8> physicalCameraIds;
// Map of physicalCameraId <-> Metadata
std::vector<PhysicalCaptureResultInfo> physicalMetadatas;
// Indicates a still capture request.
bool stillCapture;
// Indicates a ZSL capture request
bool zslCapture;
// Requested camera ids (both logical and physical) with zoomRatio != 1.0f
std::set<std::string> cameraIdsWithZoom;
// What shared surfaces an output should go to
SurfaceMap outputSurfaces;
// Default constructor needed by KeyedVector
InFlightRequest() :
shutterTimestamp(0),
sensorTimestamp(0),
requestStatus(OK),
haveResultMetadata(false),
numBuffersLeft(0),
hasInputBuffer(false),
hasCallback(true),
maxExpectedDuration(kDefaultExpectedDuration),
skipResultMetadata(false),
stillCapture(false),
zslCapture(false) {
}
InFlightRequest(int numBuffers, CaptureResultExtras extras, bool hasInput,
bool hasAppCallback, nsecs_t maxDuration,
const std::set<String8>& physicalCameraIdSet, bool isStillCapture,
bool isZslCapture, const std::set<std::string>& idsWithZoom,
const SurfaceMap& outSurfaces = SurfaceMap{}) :
shutterTimestamp(0),
sensorTimestamp(0),
requestStatus(OK),
haveResultMetadata(false),
numBuffersLeft(numBuffers),
resultExtras(extras),
hasInputBuffer(hasInput),
hasCallback(hasAppCallback),
maxExpectedDuration(maxDuration),
skipResultMetadata(false),
physicalCameraIds(physicalCameraIdSet),
stillCapture(isStillCapture),
zslCapture(isZslCapture),
cameraIdsWithZoom(idsWithZoom),
outputSurfaces(outSurfaces) {
}
};
// Map from frame number to the in-flight request state
typedef KeyedVector<uint32_t, InFlightRequest> InFlightMap;
Mutex mInFlightLock; // Protects mInFlightMap and
// mExpectedInflightDuration
InFlightMap mInFlightMap;
nsecs_t mExpectedInflightDuration = 0;
int mInFlightStatusId;
int mInFlightStatusId; // const after initialize
status_t registerInFlight(uint32_t frameNumber,
int32_t numBuffers, CaptureResultExtras resultExtras, bool hasInput,
@ -1211,7 +1064,7 @@ class Camera3Device :
*/
// Lock for output side of device
Mutex mOutputLock;
std::mutex mOutputLock;
/**** Scope for mOutputLock ****/
// the minimal frame number of the next non-reprocess result
@ -1226,61 +1079,18 @@ class Camera3Device :
uint32_t mNextReprocessShutterFrameNumber;
// the minimal frame number of the next ZSL still capture shutter
uint32_t mNextZslStillShutterFrameNumber;
List<CaptureResult> mResultQueue;
Condition mResultSignal;
wp<NotificationListener> mListener;
List<CaptureResult> mResultQueue;
std::condition_variable mResultSignal;
wp<NotificationListener> mListener;
/**** End scope for mOutputLock ****/
/**
* Callback functions from HAL device
*/
void processCaptureResult(const camera3_capture_result *result);
void notify(const camera3_notify_msg *msg);
// Specific notify handlers
void notifyError(const camera3_error_msg_t &msg,
sp<NotificationListener> listener);
void notifyShutter(const camera3_shutter_msg_t &msg,
sp<NotificationListener> listener);
// helper function to return the output buffers to the streams.
void returnOutputBuffers(const camera3_stream_buffer_t *outputBuffers,
size_t numBuffers, nsecs_t timestamp, bool timestampIncreasing = true,
// The following arguments are only meant for surface sharing use case
const SurfaceMap& outputSurfaces = SurfaceMap{},
// Used to send buffer error callback when failing to return buffer
const CaptureResultExtras &resultExtras = CaptureResultExtras{});
// Send a partial capture result.
void sendPartialCaptureResult(const camera_metadata_t * partialResult,
const CaptureResultExtras &resultExtras, uint32_t frameNumber);
// Send a total capture result given the pending metadata and result extras,
// partial results, and the frame number to the result queue.
void sendCaptureResult(CameraMetadata &pendingMetadata,
CaptureResultExtras &resultExtras,
CameraMetadata &collectedPartialResult, uint32_t frameNumber,
bool reprocess, bool zslStillCapture,
const std::set<std::string>& cameraIdsWithZoom,
const std::vector<PhysicalCaptureResultInfo>& physicalMetadatas);
bool isLastFullResult(const InFlightRequest& inFlightRequest);
// Insert the result to the result queue after updating frame number and overriding AE
// trigger cancel.
// mOutputLock must be held when calling this function.
void insertResultLocked(CaptureResult *result, uint32_t frameNumber);
/**** Scope for mInFlightLock ****/
// Remove the in-flight map entry of the given index from mInFlightMap.
// It must only be called with mInFlightLock held.
void removeInFlightMapEntryLocked(int idx);
// Remove the in-flight request of the given index from mInFlightMap
// if it's no longer needed. It must only be called with mInFlightLock held.
void removeInFlightRequestIfReadyLocked(int idx);
// Remove all in-flight requests and return all buffers.
// This is used after HAL interface is closed to cleanup any request/buffers
// not returned by HAL.
@ -1378,6 +1188,10 @@ class Camera3Device :
void onSubmittingRequest();
void onRequestThreadPaused();
// Events triggered by successful switchToOffline call
// Return true is there is no ongoing requestBuffer call.
bool onSwitchToOfflineSuccess();
private:
void notifyTrackerLocked(bool active);
@ -1391,6 +1205,7 @@ class Camera3Device :
bool mRequestThreadPaused = true;
bool mInflightMapEmpty = true;
bool mRequestBufferOngoing = false;
bool mSwitchedToOffline = false;
wp<camera3::StatusTracker> mStatusTracker;
int mRequestBufferStatusId;
@ -1398,7 +1213,6 @@ class Camera3Device :
// Fix up result metadata for monochrome camera.
bool mNeedFixupMonochromeTags;
status_t fixupMonochromeTags(const CameraMetadata& deviceInfo, CameraMetadata& resultMetadata);
// Whether HAL supports offline processing capability.
bool mSupportOfflineProcessing = false;

@ -29,90 +29,435 @@
#include <utils/Trace.h>
#include <android/hardware/camera2/ICameraDeviceCallbacks.h>
#include "device3/Camera3OfflineSession.h"
#include "device3/Camera3OutputStream.h"
#include "device3/Camera3InputStream.h"
#include "device3/Camera3SharedOutputStream.h"
#include "utils/CameraTraces.h"
using namespace android::camera3;
using namespace android::hardware::camera;
namespace android {
Camera3OfflineSession::Camera3OfflineSession(const String8 &id):
mId(id)
{
Camera3OfflineSession::Camera3OfflineSession(const String8 &id,
const sp<camera3::Camera3Stream>& inputStream,
const camera3::StreamSet& offlineStreamSet,
camera3::BufferRecords&& bufferRecords,
const camera3::InFlightRequestMap& offlineReqs,
const Camera3OfflineStates& offlineStates,
sp<hardware::camera::device::V3_6::ICameraOfflineSession> offlineSession) :
mId(id),
mInputStream(inputStream),
mOutputStreams(offlineStreamSet),
mBufferRecords(std::move(bufferRecords)),
mOfflineReqs(offlineReqs),
mSession(offlineSession),
mTagMonitor(offlineStates.mTagMonitor),
mVendorTagId(offlineStates.mVendorTagId),
mUseHalBufManager(offlineStates.mUseHalBufManager),
mNeedFixupMonochromeTags(offlineStates.mNeedFixupMonochromeTags),
mUsePartialResult(offlineStates.mUsePartialResult),
mNumPartialResults(offlineStates.mNumPartialResults),
mNextResultFrameNumber(offlineStates.mNextResultFrameNumber),
mNextReprocessResultFrameNumber(offlineStates.mNextReprocessResultFrameNumber),
mNextZslStillResultFrameNumber(offlineStates.mNextZslStillResultFrameNumber),
mNextShutterFrameNumber(offlineStates.mNextShutterFrameNumber),
mNextReprocessShutterFrameNumber(offlineStates.mNextReprocessShutterFrameNumber),
mNextZslStillShutterFrameNumber(offlineStates.mNextZslStillShutterFrameNumber),
mDeviceInfo(offlineStates.mDeviceInfo),
mPhysicalDeviceInfoMap(offlineStates.mPhysicalDeviceInfoMap),
mDistortionMappers(offlineStates.mDistortionMappers),
mZoomRatioMappers(offlineStates.mZoomRatioMappers),
mStatus(STATUS_UNINITIALIZED) {
ATRACE_CALL();
ALOGV("%s: Created offline session for camera %s", __FUNCTION__, mId.string());
}
Camera3OfflineSession::~Camera3OfflineSession()
{
Camera3OfflineSession::~Camera3OfflineSession() {
ATRACE_CALL();
ALOGV("%s: Tearing down offline session for camera id %s", __FUNCTION__, mId.string());
disconnectImpl();
}
const String8& Camera3OfflineSession::getId() const {
return mId;
}
status_t Camera3OfflineSession::initialize(
sp<hardware::camera::device::V3_6::ICameraOfflineSession> /*hidlSession*/) {
status_t Camera3OfflineSession::initialize(wp<NotificationListener> listener) {
ATRACE_CALL();
if (mSession == nullptr) {
ALOGE("%s: HIDL session is null!", __FUNCTION__);
return DEAD_OBJECT;
}
{
std::lock_guard<std::mutex> lock(mLock);
mListener = listener;
// setup result FMQ
std::unique_ptr<ResultMetadataQueue>& resQueue = mResultMetadataQueue;
auto resultQueueRet = mSession->getCaptureResultMetadataQueue(
[&resQueue](const auto& descriptor) {
resQueue = std::make_unique<ResultMetadataQueue>(descriptor);
if (!resQueue->isValid() || resQueue->availableToWrite() <= 0) {
ALOGE("HAL returns empty result metadata fmq, not use it");
resQueue = nullptr;
// Don't use resQueue onwards.
}
});
if (!resultQueueRet.isOk()) {
ALOGE("Transaction error when getting result metadata queue from camera session: %s",
resultQueueRet.description().c_str());
return DEAD_OBJECT;
}
mStatus = STATUS_ACTIVE;
}
mSession->setCallback(this);
return OK;
}
status_t Camera3OfflineSession::dump(int /*fd*/) {
ATRACE_CALL();
std::lock_guard<std::mutex> il(mInterfaceLock);
return OK;
}
status_t Camera3OfflineSession::abort() {
status_t Camera3OfflineSession::disconnect() {
ATRACE_CALL();
return OK;
return disconnectImpl();
}
status_t Camera3OfflineSession::disconnect() {
status_t Camera3OfflineSession::disconnectImpl() {
ATRACE_CALL();
std::lock_guard<std::mutex> il(mInterfaceLock);
sp<NotificationListener> listener;
{
std::lock_guard<std::mutex> lock(mLock);
if (mStatus == STATUS_CLOSED) {
return OK; // don't close twice
} else if (mStatus == STATUS_ERROR) {
ALOGE("%s: offline session %s shutting down in error state",
__FUNCTION__, mId.string());
}
listener = mListener.promote();
}
ALOGV("%s: E", __FUNCTION__);
{
std::lock_guard<std::mutex> lock(mRequestBufferInterfaceLock);
mAllowRequestBuffer = false;
}
std::vector<wp<Camera3StreamInterface>> streams;
streams.reserve(mOutputStreams.size() + (mInputStream != nullptr ? 1 : 0));
for (size_t i = 0; i < mOutputStreams.size(); i++) {
streams.push_back(mOutputStreams[i]);
}
if (mInputStream != nullptr) {
streams.push_back(mInputStream);
}
mSession->close();
FlushInflightReqStates states {
mId, mOfflineReqsLock, mOfflineReqs, mUseHalBufManager,
listener, *this, mBufferRecords, *this};
camera3::flushInflightRequests(states);
{
std::lock_guard<std::mutex> lock(mLock);
mSession.clear();
mOutputStreams.clear();
mInputStream.clear();
mStatus = STATUS_CLOSED;
}
for (auto& weakStream : streams) {
sp<Camera3StreamInterface> stream = weakStream.promote();
if (stream != nullptr) {
ALOGE("%s: Stream %d leaked! strong reference (%d)!",
__FUNCTION__, stream->getId(), stream->getStrongCount() - 1);
}
}
ALOGV("%s: X", __FUNCTION__);
return OK;
}
status_t Camera3OfflineSession::waitForNextFrame(nsecs_t /*timeout*/) {
status_t Camera3OfflineSession::waitForNextFrame(nsecs_t timeout) {
ATRACE_CALL();
std::unique_lock<std::mutex> lk(mOutputLock);
while (mResultQueue.empty()) {
auto st = mResultSignal.wait_for(lk, std::chrono::nanoseconds(timeout));
if (st == std::cv_status::timeout) {
return TIMED_OUT;
}
}
return OK;
}
status_t Camera3OfflineSession::getNextResult(CaptureResult* /*frame*/) {
status_t Camera3OfflineSession::getNextResult(CaptureResult* frame) {
ATRACE_CALL();
std::lock_guard<std::mutex> l(mOutputLock);
if (mResultQueue.empty()) {
return NOT_ENOUGH_DATA;
}
if (frame == nullptr) {
ALOGE("%s: argument cannot be NULL", __FUNCTION__);
return BAD_VALUE;
}
CaptureResult &result = *(mResultQueue.begin());
frame->mResultExtras = result.mResultExtras;
frame->mMetadata.acquire(result.mMetadata);
frame->mPhysicalMetadatas = std::move(result.mPhysicalMetadatas);
mResultQueue.erase(mResultQueue.begin());
return OK;
}
hardware::Return<void> Camera3OfflineSession::processCaptureResult_3_4(
const hardware::hidl_vec<
hardware::camera::device::V3_4::CaptureResult>& /*results*/) {
hardware::camera::device::V3_4::CaptureResult>& results) {
sp<NotificationListener> listener;
{
std::lock_guard<std::mutex> lock(mLock);
if (mStatus != STATUS_ACTIVE) {
ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus);
return hardware::Void();
}
listener = mListener.promote();
}
CaptureOutputStates states {
mId,
mOfflineReqsLock, mOfflineReqs,
mOutputLock, mResultQueue, mResultSignal,
mNextShutterFrameNumber,
mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
mNextResultFrameNumber,
mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
mResultMetadataQueue, mDistortionMappers, mZoomRatioMappers, mTagMonitor,
mInputStream, mOutputStreams, listener, *this, *this, mBufferRecords
};
std::lock_guard<std::mutex> lock(mProcessCaptureResultLock);
for (const auto& result : results) {
processOneCaptureResultLocked(states, result.v3_2, result.physicalCameraMetadata);
}
return hardware::Void();
}
hardware::Return<void> Camera3OfflineSession::processCaptureResult(
const hardware::hidl_vec<
hardware::camera::device::V3_2::CaptureResult>& /*results*/) {
hardware::camera::device::V3_2::CaptureResult>& results) {
// TODO: changed impl to call into processCaptureResult_3_4 instead?
// might need to figure how to reduce copy though.
sp<NotificationListener> listener;
{
std::lock_guard<std::mutex> lock(mLock);
if (mStatus != STATUS_ACTIVE) {
ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus);
return hardware::Void();
}
listener = mListener.promote();
}
hardware::hidl_vec<hardware::camera::device::V3_4::PhysicalCameraMetadata> noPhysMetadata;
CaptureOutputStates states {
mId,
mOfflineReqsLock, mOfflineReqs,
mOutputLock, mResultQueue, mResultSignal,
mNextShutterFrameNumber,
mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
mNextResultFrameNumber,
mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
mResultMetadataQueue, mDistortionMappers, mZoomRatioMappers, mTagMonitor,
mInputStream, mOutputStreams, listener, *this, *this, mBufferRecords
};
std::lock_guard<std::mutex> lock(mProcessCaptureResultLock);
for (const auto& result : results) {
processOneCaptureResultLocked(states, result, noPhysMetadata);
}
return hardware::Void();
}
hardware::Return<void> Camera3OfflineSession::notify(
const hardware::hidl_vec<hardware::camera::device::V3_2::NotifyMsg>& /*msgs*/) {
const hardware::hidl_vec<hardware::camera::device::V3_2::NotifyMsg>& msgs) {
sp<NotificationListener> listener;
{
std::lock_guard<std::mutex> lock(mLock);
if (mStatus != STATUS_ACTIVE) {
ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus);
return hardware::Void();
}
listener = mListener.promote();
}
CaptureOutputStates states {
mId,
mOfflineReqsLock, mOfflineReqs,
mOutputLock, mResultQueue, mResultSignal,
mNextShutterFrameNumber,
mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
mNextResultFrameNumber,
mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
mResultMetadataQueue, mDistortionMappers, mZoomRatioMappers, mTagMonitor,
mInputStream, mOutputStreams, listener, *this, *this, mBufferRecords
};
for (const auto& msg : msgs) {
camera3::notify(states, msg);
}
return hardware::Void();
}
hardware::Return<void> Camera3OfflineSession::requestStreamBuffers(
const hardware::hidl_vec<hardware::camera::device::V3_5::BufferRequest>& /*bufReqs*/,
requestStreamBuffers_cb /*_hidl_cb*/) {
const hardware::hidl_vec<hardware::camera::device::V3_5::BufferRequest>& bufReqs,
requestStreamBuffers_cb _hidl_cb) {
{
std::lock_guard<std::mutex> lock(mLock);
if (mStatus != STATUS_ACTIVE) {
ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus);
return hardware::Void();
}
}
RequestBufferStates states {
mId, mRequestBufferInterfaceLock, mUseHalBufManager, mOutputStreams,
*this, mBufferRecords, *this};
camera3::requestStreamBuffers(states, bufReqs, _hidl_cb);
return hardware::Void();
}
hardware::Return<void> Camera3OfflineSession::returnStreamBuffers(
const hardware::hidl_vec<hardware::camera::device::V3_2::StreamBuffer>& /*buffers*/) {
const hardware::hidl_vec<hardware::camera::device::V3_2::StreamBuffer>& buffers) {
{
std::lock_guard<std::mutex> lock(mLock);
if (mStatus != STATUS_ACTIVE) {
ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus);
return hardware::Void();
}
}
ReturnBufferStates states {
mId, mUseHalBufManager, mOutputStreams, mBufferRecords};
camera3::returnStreamBuffers(states, buffers);
return hardware::Void();
}
void Camera3OfflineSession::setErrorState(const char *fmt, ...) {
ATRACE_CALL();
std::lock_guard<std::mutex> lock(mLock);
va_list args;
va_start(args, fmt);
setErrorStateLockedV(fmt, args);
va_end(args);
//FIXME: automatically disconnect here?
}
void Camera3OfflineSession::setErrorStateLocked(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
setErrorStateLockedV(fmt, args);
va_end(args);
}
void Camera3OfflineSession::setErrorStateLockedV(const char *fmt, va_list args) {
// Print out all error messages to log
String8 errorCause = String8::formatV(fmt, args);
ALOGE("Camera %s: %s", mId.string(), errorCause.string());
// But only do error state transition steps for the first error
if (mStatus == STATUS_ERROR || mStatus == STATUS_UNINITIALIZED) return;
mErrorCause = errorCause;
mStatus = STATUS_ERROR;
// Notify upstream about a device error
sp<NotificationListener> listener = mListener.promote();
if (listener != NULL) {
listener->notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE,
CaptureResultExtras());
}
// Save stack trace. View by dumping it later.
CameraTraces::saveTrace();
}
void Camera3OfflineSession::onInflightEntryRemovedLocked(nsecs_t /*duration*/) {
if (mOfflineReqs.size() == 0) {
std::lock_guard<std::mutex> lock(mRequestBufferInterfaceLock);
mAllowRequestBuffer = false;
}
}
void Camera3OfflineSession::checkInflightMapLengthLocked() {
// Intentional empty impl.
}
void Camera3OfflineSession::onInflightMapFlushedLocked() {
// Intentional empty impl.
}
bool Camera3OfflineSession::startRequestBuffer() {
return mAllowRequestBuffer;
}
void Camera3OfflineSession::endRequestBuffer() {
// Intentional empty impl.
}
nsecs_t Camera3OfflineSession::getWaitDuration() {
const nsecs_t kBaseGetBufferWait = 3000000000; // 3 sec.
return kBaseGetBufferWait;
}
void Camera3OfflineSession::getInflightBufferKeys(std::vector<std::pair<int32_t, int32_t>>* out) {
mBufferRecords.getInflightBufferKeys(out);
}
void Camera3OfflineSession::getInflightRequestBufferKeys(std::vector<uint64_t>* out) {
mBufferRecords.getInflightRequestBufferKeys(out);
}
std::vector<sp<Camera3StreamInterface>> Camera3OfflineSession::getAllStreams() {
std::vector<sp<Camera3StreamInterface>> ret;
bool hasInputStream = mInputStream != nullptr;
ret.reserve(mOutputStreams.size() + ((hasInputStream) ? 1 : 0));
if (hasInputStream) {
ret.push_back(mInputStream);
}
for (size_t i = 0; i < mOutputStreams.size(); i++) {
ret.push_back(mOutputStreams[i]);
}
return ret;
}
}; // namespace android

@ -17,16 +17,23 @@
#ifndef ANDROID_SERVERS_CAMERA3OFFLINESESSION_H
#define ANDROID_SERVERS_CAMERA3OFFLINESESSION_H
#include <memory>
#include <mutex>
#include <utils/String8.h>
#include <utils/String16.h>
#include <android/hardware/camera/device/3.6/ICameraOfflineSession.h>
#include <fmq/MessageQueue.h>
#include "common/CameraOfflineSessionBase.h"
#include "device3/Camera3BufferManager.h"
#include "device3/DistortionMapper.h"
#include "device3/InFlightRequest.h"
#include "device3/Camera3OutputUtils.h"
#include "device3/ZoomRatioMapper.h"
#include "utils/TagMonitor.h"
#include "utils/LatencyHistogram.h"
#include <camera_metadata_hidden.h>
@ -41,26 +48,90 @@ class Camera3StreamInterface;
} // namespace camera3
// An immutable struct containing general states that will be copied from Camera3Device to
// Camera3OfflineSession
struct Camera3OfflineStates {
Camera3OfflineStates(
const TagMonitor& tagMonitor, const metadata_vendor_id_t vendorTagId,
const bool useHalBufManager, const bool needFixupMonochromeTags,
const bool usePartialResult, const uint32_t numPartialResults,
const uint32_t nextResultFN, const uint32_t nextReprocResultFN,
const uint32_t nextZslResultFN, const uint32_t nextShutterFN,
const uint32_t nextReprocShutterFN, const uint32_t nextZslShutterFN,
const CameraMetadata& deviceInfo,
const std::unordered_map<std::string, CameraMetadata>& physicalDeviceInfoMap,
const std::unordered_map<std::string, camera3::DistortionMapper>& distortionMappers,
const std::unordered_map<std::string, camera3::ZoomRatioMapper>& zoomRatioMappers) :
mTagMonitor(tagMonitor), mVendorTagId(vendorTagId),
mUseHalBufManager(useHalBufManager), mNeedFixupMonochromeTags(needFixupMonochromeTags),
mUsePartialResult(usePartialResult), mNumPartialResults(numPartialResults),
mNextResultFrameNumber(nextResultFN),
mNextReprocessResultFrameNumber(nextReprocResultFN),
mNextZslStillResultFrameNumber(nextZslResultFN),
mNextShutterFrameNumber(nextShutterFN),
mNextReprocessShutterFrameNumber(nextReprocShutterFN),
mNextZslStillShutterFrameNumber(nextZslShutterFN),
mDeviceInfo(deviceInfo),
mPhysicalDeviceInfoMap(physicalDeviceInfoMap),
mDistortionMappers(distortionMappers),
mZoomRatioMappers(zoomRatioMappers) {}
const TagMonitor& mTagMonitor;
const metadata_vendor_id_t mVendorTagId;
const bool mUseHalBufManager;
const bool mNeedFixupMonochromeTags;
const bool mUsePartialResult;
const uint32_t mNumPartialResults;
// the minimal frame number of the next non-reprocess result
const uint32_t mNextResultFrameNumber;
// the minimal frame number of the next reprocess result
const uint32_t mNextReprocessResultFrameNumber;
// the minimal frame number of the next ZSL still capture result
const uint32_t mNextZslStillResultFrameNumber;
// the minimal frame number of the next non-reprocess shutter
const uint32_t mNextShutterFrameNumber;
// the minimal frame number of the next reprocess shutter
const uint32_t mNextReprocessShutterFrameNumber;
// the minimal frame number of the next ZSL still capture shutter
const uint32_t mNextZslStillShutterFrameNumber;
const CameraMetadata& mDeviceInfo;
const std::unordered_map<std::string, CameraMetadata>& mPhysicalDeviceInfoMap;
const std::unordered_map<std::string, camera3::DistortionMapper>& mDistortionMappers;
const std::unordered_map<std::string, camera3::ZoomRatioMapper>& mZoomRatioMappers;
};
/**
* Camera3OfflineSession for offline session defined in HIDL ICameraOfflineSession@3.6 or higher
*/
class Camera3OfflineSession :
public CameraOfflineSessionBase,
virtual public hardware::camera::device::V3_5::ICameraDeviceCallback {
virtual public hardware::camera::device::V3_5::ICameraDeviceCallback,
public camera3::SetErrorInterface,
public camera3::InflightRequestUpdateInterface,
public camera3::RequestBufferInterface,
public camera3::FlushBufferInterface {
public:
// initialize by Camera3Device. Camera3Device must send all info in separate argument.
// monitored tags
// mUseHalBufManager
// mUsePartialResult
// mNumPartialResults
explicit Camera3OfflineSession(const String8& id);
// initialize by Camera3Device.
explicit Camera3OfflineSession(const String8& id,
const sp<camera3::Camera3Stream>& inputStream,
const camera3::StreamSet& offlineStreamSet,
camera3::BufferRecords&& bufferRecords,
const camera3::InFlightRequestMap& offlineReqs,
const Camera3OfflineStates& offlineStates,
sp<hardware::camera::device::V3_6::ICameraOfflineSession> offlineSession);
virtual ~Camera3OfflineSession();
status_t initialize(
sp<hardware::camera::device::V3_6::ICameraOfflineSession> hidlSession);
virtual status_t initialize(wp<NotificationListener> listener) override;
/**
* CameraOfflineSessionBase interface
@ -71,8 +142,6 @@ class Camera3OfflineSession :
status_t dump(int fd) override;
status_t abort() override;
// methods for capture result passing
status_t waitForNextFrame(nsecs_t timeout) override;
status_t getNextResult(CaptureResult *frame) override;
@ -115,10 +184,99 @@ class Camera3OfflineSession :
*/
private:
// Camera device ID
const String8 mId;
sp<camera3::Camera3Stream> mInputStream;
camera3::StreamSet mOutputStreams;
camera3::BufferRecords mBufferRecords;
std::mutex mOfflineReqsLock;
camera3::InFlightRequestMap mOfflineReqs;
sp<hardware::camera::device::V3_6::ICameraOfflineSession> mSession;
TagMonitor mTagMonitor;
const metadata_vendor_id_t mVendorTagId;
const bool mUseHalBufManager;
const bool mNeedFixupMonochromeTags;
const bool mUsePartialResult;
const uint32_t mNumPartialResults;
std::mutex mOutputLock;
List<CaptureResult> mResultQueue;
std::condition_variable mResultSignal;
// the minimal frame number of the next non-reprocess result
uint32_t mNextResultFrameNumber;
// the minimal frame number of the next reprocess result
uint32_t mNextReprocessResultFrameNumber;
// the minimal frame number of the next ZSL still capture result
uint32_t mNextZslStillResultFrameNumber;
// the minimal frame number of the next non-reprocess shutter
uint32_t mNextShutterFrameNumber;
// the minimal frame number of the next reprocess shutter
uint32_t mNextReprocessShutterFrameNumber;
// the minimal frame number of the next ZSL still capture shutter
uint32_t mNextZslStillShutterFrameNumber;
// End of mOutputLock scope
const CameraMetadata mDeviceInfo;
std::unordered_map<std::string, CameraMetadata> mPhysicalDeviceInfoMap;
std::unordered_map<std::string, camera3::DistortionMapper> mDistortionMappers;
std::unordered_map<std::string, camera3::ZoomRatioMapper> mZoomRatioMappers;
mutable std::mutex mLock;
enum Status {
STATUS_UNINITIALIZED = 0,
STATUS_ACTIVE,
STATUS_ERROR,
STATUS_CLOSED
} mStatus;
wp<NotificationListener> mListener;
// End of mLock protect scope
std::mutex mProcessCaptureResultLock;
// FMQ to write result on. Must be guarded by mProcessCaptureResultLock.
std::unique_ptr<ResultMetadataQueue> mResultMetadataQueue;
// Tracking cause of fatal errors when in STATUS_ERROR
String8 mErrorCause;
// Lock to ensure requestStreamBuffers() callbacks are serialized
std::mutex mRequestBufferInterfaceLock;
// allow request buffer until all requests are processed or disconnectImpl is called
bool mAllowRequestBuffer = true;
// For client methods such as disconnect/dump
std::mutex mInterfaceLock;
// SetErrorInterface
void setErrorState(const char *fmt, ...) override;
void setErrorStateLocked(const char *fmt, ...) override;
// InflightRequestUpdateInterface
void onInflightEntryRemovedLocked(nsecs_t duration) override;
void checkInflightMapLengthLocked() override;
void onInflightMapFlushedLocked() override;
// RequestBufferInterface
bool startRequestBuffer() override;
void endRequestBuffer() override;
nsecs_t getWaitDuration() override;
// FlushBufferInterface
void getInflightBufferKeys(std::vector<std::pair<int32_t, int32_t>>* out) override;
void getInflightRequestBufferKeys(std::vector<uint64_t>* out) override;
std::vector<sp<camera3::Camera3StreamInterface>> getAllStreams() override;
void setErrorStateLockedV(const char *fmt, va_list args);
status_t disconnectImpl();
}; // class Camera3OfflineSession
}; // namespace android

@ -0,0 +1,111 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_SERVERS_CAMERA3_OUTPUT_INTERFACE_H
#define ANDROID_SERVERS_CAMERA3_OUTPUT_INTERFACE_H
#include <memory>
#include <cutils/native_handle.h>
#include <utils/Timers.h>
#include "device3/Camera3StreamInterface.h"
namespace android {
namespace camera3 {
/**
* Interfaces used by result/notification path shared between Camera3Device and
* Camera3OfflineSession
*/
class SetErrorInterface {
public:
// Switch device into error state and send a ERROR_DEVICE notification
virtual void setErrorState(const char *fmt, ...) = 0;
// Same as setErrorState except this method assumes callers holds the main object lock
virtual void setErrorStateLocked(const char *fmt, ...) = 0;
virtual ~SetErrorInterface() {}
};
// Interface used by callback path to update buffer records
class BufferRecordsInterface {
public:
// method to extract buffer's unique ID
// return pair of (newlySeenBuffer?, bufferId)
virtual std::pair<bool, uint64_t> getBufferId(const buffer_handle_t& buf, int streamId) = 0;
// Find a buffer_handle_t based on frame number and stream ID
virtual status_t popInflightBuffer(int32_t frameNumber, int32_t streamId,
/*out*/ buffer_handle_t **buffer) = 0;
// Register a bufId (streamId, buffer_handle_t) to inflight request buffer
virtual status_t pushInflightRequestBuffer(
uint64_t bufferId, buffer_handle_t* buf, int32_t streamId) = 0;
// Find a buffer_handle_t based on bufferId
virtual status_t popInflightRequestBuffer(uint64_t bufferId,
/*out*/ buffer_handle_t** buffer,
/*optional out*/ int32_t* streamId = nullptr) = 0;
virtual ~BufferRecordsInterface() {}
};
class InflightRequestUpdateInterface {
public:
// Caller must hold the lock proctecting InflightRequestMap
// duration: the maxExpectedDuration of the removed entry
virtual void onInflightEntryRemovedLocked(nsecs_t duration) = 0;
virtual void checkInflightMapLengthLocked() = 0;
virtual void onInflightMapFlushedLocked() = 0;
virtual ~InflightRequestUpdateInterface() {}
};
class RequestBufferInterface {
public:
// Return if the state machine currently allows for requestBuffers.
// If this returns true, caller must call endRequestBuffer() later to signal end of a
// request buffer transaction.
virtual bool startRequestBuffer() = 0;
virtual void endRequestBuffer() = 0;
// Returns how long should implementation wait for a buffer returned
virtual nsecs_t getWaitDuration() = 0;
virtual ~RequestBufferInterface() {}
};
class FlushBufferInterface {
public:
virtual void getInflightBufferKeys(std::vector<std::pair<int32_t, int32_t>>* out) = 0;
virtual void getInflightRequestBufferKeys(std::vector<uint64_t>* out) = 0;
virtual std::vector<sp<Camera3StreamInterface>> getAllStreams() = 0;
virtual ~FlushBufferInterface() {}
};
} // namespace camera3
} // namespace android
#endif

@ -0,0 +1,84 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "Camera3-OutStrmIntf"
#define ATRACE_TAG ATRACE_TAG_CAMERA
//#define LOG_NDEBUG 0
//#define LOG_NNDEBUG 0 // Per-frame verbose logging
#include "Camera3OutputStreamInterface.h"
namespace android {
namespace camera3 {
status_t StreamSet::add(
int streamId, sp<camera3::Camera3OutputStreamInterface> stream) {
if (stream == nullptr) {
ALOGE("%s: cannot add null stream", __FUNCTION__);
return BAD_VALUE;
}
std::lock_guard<std::mutex> lock(mLock);
return mData.add(streamId, stream);
}
ssize_t StreamSet::remove(int streamId) {
std::lock_guard<std::mutex> lock(mLock);
return mData.removeItem(streamId);
}
sp<camera3::Camera3OutputStreamInterface> StreamSet::get(int streamId) {
std::lock_guard<std::mutex> lock(mLock);
ssize_t idx = mData.indexOfKey(streamId);
if (idx == NAME_NOT_FOUND) {
return nullptr;
}
return mData.editValueAt(idx);
}
sp<camera3::Camera3OutputStreamInterface> StreamSet::operator[] (size_t index) {
std::lock_guard<std::mutex> lock(mLock);
return mData.editValueAt(index);
}
size_t StreamSet::size() const {
std::lock_guard<std::mutex> lock(mLock);
return mData.size();
}
void StreamSet::clear() {
std::lock_guard<std::mutex> lock(mLock);
return mData.clear();
}
std::vector<int> StreamSet::getStreamIds() {
std::lock_guard<std::mutex> lock(mLock);
std::vector<int> streamIds(mData.size());
for (size_t i = 0; i < mData.size(); i++) {
streamIds[i] = mData.keyAt(i);
}
return streamIds;
}
StreamSet::StreamSet(const StreamSet& other) {
std::lock_guard<std::mutex> lock(other.mLock);
mData = other.mData;
}
} // namespace camera3
} // namespace android

@ -97,6 +97,26 @@ class Camera3OutputStreamInterface : public virtual Camera3StreamInterface {
virtual const String8& getPhysicalCameraId() const = 0;
};
// Helper class to organize a synchronized mapping of stream IDs to stream instances
class StreamSet {
public:
status_t add(int streamId, sp<camera3::Camera3OutputStreamInterface>);
ssize_t remove(int streamId);
sp<camera3::Camera3OutputStreamInterface> get(int streamId);
// get by (underlying) vector index
sp<camera3::Camera3OutputStreamInterface> operator[] (size_t index);
size_t size() const;
std::vector<int> getStreamIds();
void clear();
StreamSet() {};
StreamSet(const StreamSet& other);
private:
mutable std::mutex mLock;
KeyedVector<int, sp<camera3::Camera3OutputStreamInterface>> mData;
};
} // namespace camera3
} // namespace android

@ -0,0 +1,143 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_SERVERS_CAMERA3_OUTPUT_UTILS_H
#define ANDROID_SERVERS_CAMERA3_OUTPUT_UTILS_H
#include <memory>
#include <mutex>
#include <cutils/native_handle.h>
#include <fmq/MessageQueue.h>
#include <common/CameraDeviceBase.h>
#include "device3/BufferUtils.h"
#include "device3/DistortionMapper.h"
#include "device3/ZoomRatioMapper.h"
#include "device3/InFlightRequest.h"
#include "device3/Camera3Stream.h"
#include "device3/Camera3OutputStreamInterface.h"
#include "utils/TagMonitor.h"
namespace android {
using ResultMetadataQueue = hardware::MessageQueue<uint8_t, hardware::kSynchronizedReadWrite>;
namespace camera3 {
/**
* Helper methods shared between Camera3Device/Camera3OfflineSession for HAL callbacks
*/
// helper function to return the output buffers to output streams.
void returnOutputBuffers(
bool useHalBufManager,
sp<NotificationListener> listener, // Only needed when outputSurfaces is not empty
const camera3_stream_buffer_t *outputBuffers,
size_t numBuffers, nsecs_t timestamp, bool timestampIncreasing = true,
// The following arguments are only meant for surface sharing use case
const SurfaceMap& outputSurfaces = SurfaceMap{},
// Used to send buffer error callback when failing to return buffer
const CaptureResultExtras &resultExtras = CaptureResultExtras{});
// Camera3Device/Camera3OfflineSession internal states used in notify/processCaptureResult
// callbacks
struct CaptureOutputStates {
const String8& cameraId;
std::mutex& inflightLock;
InFlightRequestMap& inflightMap; // end of inflightLock scope
std::mutex& outputLock;
List<CaptureResult>& resultQueue;
std::condition_variable& resultSignal;
uint32_t& nextShutterFrameNum;
uint32_t& nextReprocShutterFrameNum;
uint32_t& nextZslShutterFrameNum;
uint32_t& nextResultFrameNum;
uint32_t& nextReprocResultFrameNum;
uint32_t& nextZslResultFrameNum; // end of outputLock scope
const bool useHalBufManager;
const bool usePartialResult;
const bool needFixupMonoChrome;
const uint32_t numPartialResults;
const metadata_vendor_id_t vendorTagId;
const CameraMetadata& deviceInfo;
const std::unordered_map<std::string, CameraMetadata>& physicalDeviceInfoMap;
std::unique_ptr<ResultMetadataQueue>& fmq;
std::unordered_map<std::string, camera3::DistortionMapper>& distortionMappers;
std::unordered_map<std::string, camera3::ZoomRatioMapper>& zoomRatioMappers;
TagMonitor& tagMonitor;
sp<Camera3Stream> inputStream;
StreamSet& outputStreams;
sp<NotificationListener> listener;
SetErrorInterface& setErrIntf;
InflightRequestUpdateInterface& inflightIntf;
BufferRecordsInterface& bufferRecordsIntf;
};
// Handle one capture result. Assume callers hold the lock to serialize all
// processCaptureResult calls
void processOneCaptureResultLocked(
CaptureOutputStates& states,
const hardware::camera::device::V3_2::CaptureResult& result,
const hardware::hidl_vec<
hardware::camera::device::V3_4::PhysicalCameraMetadata> physicalCameraMetadata);
// Handle one notify message
void notify(CaptureOutputStates& states,
const hardware::camera::device::V3_2::NotifyMsg& msg);
struct RequestBufferStates {
const String8& cameraId;
std::mutex& reqBufferLock; // lock to serialize request buffer calls
const bool useHalBufManager;
StreamSet& outputStreams;
SetErrorInterface& setErrIntf;
BufferRecordsInterface& bufferRecordsIntf;
RequestBufferInterface& reqBufferIntf;
};
void requestStreamBuffers(RequestBufferStates& states,
const hardware::hidl_vec<hardware::camera::device::V3_5::BufferRequest>& bufReqs,
hardware::camera::device::V3_5::ICameraDeviceCallback::requestStreamBuffers_cb _hidl_cb);
struct ReturnBufferStates {
const String8& cameraId;
const bool useHalBufManager;
StreamSet& outputStreams;
BufferRecordsInterface& bufferRecordsIntf;
};
void returnStreamBuffers(ReturnBufferStates& states,
const hardware::hidl_vec<hardware::camera::device::V3_2::StreamBuffer>& buffers);
struct FlushInflightReqStates {
const String8& cameraId;
std::mutex& inflightLock;
InFlightRequestMap& inflightMap; // end of inflightLock scope
const bool useHalBufManager;
sp<NotificationListener> listener;
InflightRequestUpdateInterface& inflightIntf;
BufferRecordsInterface& bufferRecordsIntf;
FlushBufferInterface& flushBufferIntf;
};
void flushInflightRequests(FlushInflightReqStates& states);
} // namespace camera3
} // namespace android
#endif

@ -151,6 +151,14 @@ const String8& Camera3Stream::physicalCameraId() const {
return mPhysicalCameraId;
}
void Camera3Stream::setOfflineProcessingSupport(bool support) {
mSupportOfflineProcessing = support;
}
bool Camera3Stream::getOfflineProcessingSupport() const {
return mSupportOfflineProcessing;
}
status_t Camera3Stream::forceToIdle() {
ATRACE_CALL();
Mutex::Autolock l(mLock);

@ -167,6 +167,9 @@ class Camera3Stream :
android_dataspace getOriginalDataSpace() const;
const String8& physicalCameraId() const;
void setOfflineProcessingSupport(bool) override;
bool getOfflineProcessingSupport() const override;
camera3_stream* asHalStream() override {
return this;
}
@ -592,6 +595,8 @@ class Camera3Stream :
String8 mPhysicalCameraId;
nsecs_t mLastTimestamp;
bool mSupportOfflineProcessing = false;
}; // class Camera3Stream
}; // namespace camera3

@ -23,6 +23,7 @@
#include "Camera3StreamBufferListener.h"
#include "Camera3StreamBufferFreedListener.h"
struct camera3_stream;
struct camera3_stream_buffer;
namespace android {
@ -98,6 +99,12 @@ class Camera3StreamInterface : public virtual RefBase {
virtual bool isDataSpaceOverridden() const = 0;
virtual android_dataspace getOriginalDataSpace() const = 0;
/**
* Offline processing
*/
virtual void setOfflineProcessingSupport(bool support) = 0;
virtual bool getOfflineProcessingSupport() const = 0;
/**
* Get a HAL3 handle for the stream, without starting stream configuration.
*/

@ -36,6 +36,15 @@ class DistortionMapper : private CoordinateMapper {
public:
DistortionMapper();
DistortionMapper(const DistortionMapper& other) :
mValidMapping(other.mValidMapping), mValidGrids(other.mValidGrids),
mFx(other.mFx), mFy(other.mFy), mCx(other.mCx), mCy(other.mCy), mS(other.mS),
mInvFx(other.mInvFx), mInvFy(other.mInvFy), mK(other.mK),
mArrayWidth(other.mArrayWidth), mArrayHeight(other.mArrayHeight),
mActiveWidth(other.mActiveWidth), mActiveHeight(other.mActiveHeight),
mArrayDiffX(other.mArrayDiffX), mArrayDiffY(other.mArrayDiffY),
mCorrectedGrid(other.mCorrectedGrid), mDistortedGrid(other.mDistortedGrid) {}
/**
* Check whether distortion correction is supported by the camera HAL
*/
@ -173,7 +182,7 @@ class DistortionMapper : private CoordinateMapper {
// pre-calculated inverses for speed
float mInvFx, mInvFy;
// radial/tangential distortion parameters
float mK[5];
std::array<float, 5> mK;
// pre-correction active array dimensions
float mArrayWidth, mArrayHeight;

@ -0,0 +1,148 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ANDROID_SERVERS_CAMERA3_INFLIGHT_REQUEST_H
#define ANDROID_SERVERS_CAMERA3_INFLIGHT_REQUEST_H
#include <set>
#include <camera/CaptureResult.h>
#include <camera/CameraMetadata.h>
#include <utils/String8.h>
#include <utils/Timers.h>
#include "hardware/camera3.h"
#include "common/CameraDeviceBase.h"
namespace android {
namespace camera3 {
struct InFlightRequest {
// Set by notify() SHUTTER call.
nsecs_t shutterTimestamp;
// Set by process_capture_result().
nsecs_t sensorTimestamp;
int requestStatus;
// Set by process_capture_result call with valid metadata
bool haveResultMetadata;
// Decremented by calls to process_capture_result with valid output
// and input buffers
int numBuffersLeft;
CaptureResultExtras resultExtras;
// If this request has any input buffer
bool hasInputBuffer;
// The last metadata that framework receives from HAL and
// not yet send out because the shutter event hasn't arrived.
// It's added by process_capture_result and sent when framework
// receives the shutter event.
CameraMetadata pendingMetadata;
// The metadata of the partial results that framework receives from HAL so far
// and has sent out.
CameraMetadata collectedPartialResult;
// Buffers are added by process_capture_result when output buffers
// return from HAL but framework has not yet received the shutter
// event. They will be returned to the streams when framework receives
// the shutter event.
Vector<camera3_stream_buffer_t> pendingOutputBuffers;
// Whether this inflight request's shutter and result callback are to be
// called. The policy is that if the request is the last one in the constrained
// high speed recording request list, this flag will be true. If the request list
// is not for constrained high speed recording, this flag will also be true.
bool hasCallback;
// Maximum expected frame duration for this request.
// For manual captures, equal to the max of requested exposure time and frame duration
// For auto-exposure modes, equal to 1/(lower end of target FPS range)
nsecs_t maxExpectedDuration;
// Whether the result metadata for this request is to be skipped. The
// result metadata should be skipped in the case of
// REQUEST/RESULT error.
bool skipResultMetadata;
// The physical camera ids being requested.
std::set<String8> physicalCameraIds;
// Map of physicalCameraId <-> Metadata
std::vector<PhysicalCaptureResultInfo> physicalMetadatas;
// Indicates a still capture request.
bool stillCapture;
// Indicates a ZSL capture request
bool zslCapture;
// Requested camera ids (both logical and physical) with zoomRatio != 1.0f
std::set<std::string> cameraIdsWithZoom;
// What shared surfaces an output should go to
SurfaceMap outputSurfaces;
// TODO: dedupe
static const nsecs_t kDefaultExpectedDuration = 100000000; // 100 ms
// Default constructor needed by KeyedVector
InFlightRequest() :
shutterTimestamp(0),
sensorTimestamp(0),
requestStatus(OK),
haveResultMetadata(false),
numBuffersLeft(0),
hasInputBuffer(false),
hasCallback(true),
maxExpectedDuration(kDefaultExpectedDuration),
skipResultMetadata(false),
stillCapture(false),
zslCapture(false) {
}
InFlightRequest(int numBuffers, CaptureResultExtras extras, bool hasInput,
bool hasAppCallback, nsecs_t maxDuration,
const std::set<String8>& physicalCameraIdSet, bool isStillCapture,
bool isZslCapture, const std::set<std::string>& idsWithZoom,
const SurfaceMap& outSurfaces = SurfaceMap{}) :
shutterTimestamp(0),
sensorTimestamp(0),
requestStatus(OK),
haveResultMetadata(false),
numBuffersLeft(numBuffers),
resultExtras(extras),
hasInputBuffer(hasInput),
hasCallback(hasAppCallback),
maxExpectedDuration(maxDuration),
skipResultMetadata(false),
physicalCameraIds(physicalCameraIdSet),
stillCapture(isStillCapture),
zslCapture(isZslCapture),
cameraIdsWithZoom(idsWithZoom),
outputSurfaces(outSurfaces) {
}
};
// Map from frame number to the in-flight request state
typedef KeyedVector<uint32_t, InFlightRequest> InFlightRequestMap;
} // namespace camera3
} // namespace android
#endif

@ -33,6 +33,16 @@ TagMonitor::TagMonitor():
mVendorTagId(CAMERA_METADATA_INVALID_VENDOR_ID)
{}
TagMonitor::TagMonitor(const TagMonitor& other):
mMonitoringEnabled(other.mMonitoringEnabled.load()),
mMonitoredTagList(other.mMonitoredTagList),
mLastMonitoredRequestValues(other.mLastMonitoredRequestValues),
mLastMonitoredResultValues(other.mLastMonitoredResultValues),
mLastMonitoredPhysicalRequestKeys(other.mLastMonitoredPhysicalRequestKeys),
mLastMonitoredPhysicalResultKeys(other.mLastMonitoredPhysicalResultKeys),
mMonitoringEvents(other.mMonitoringEvents),
mVendorTagId(other.mVendorTagId) {}
const String16 TagMonitor::kMonitorOption = String16("-m");
const char* TagMonitor::k3aTags =

@ -50,6 +50,8 @@ class TagMonitor {
TagMonitor();
TagMonitor(const TagMonitor& other);
void initialize(metadata_vendor_id_t id) { mVendorTagId = id; }
// Parse tag name list (comma-separated) and if valid, enable monitoring

Loading…
Cancel
Save