* changes: Camera: Propagate all offline stream ids to clients Camera: Add initial offline client listener logic Camera: Initial support for composite streams in offline mode Camera: Initial offline session client Camera: fill in Camera3Device offline processing implgugelfrei
commit
f0b35a84d6
@ -0,0 +1,287 @@
|
||||
/*
|
||||
* 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 "CameraOfflineClient"
|
||||
#define ATRACE_TAG ATRACE_TAG_CAMERA
|
||||
//#define LOG_NDEBUG 0
|
||||
|
||||
#include "CameraOfflineSessionClient.h"
|
||||
#include "utils/CameraThreadState.h"
|
||||
#include <utils/Trace.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
using binder::Status;
|
||||
|
||||
status_t CameraOfflineSessionClient::initialize(sp<CameraProviderManager>, const String8&) {
|
||||
ATRACE_CALL();
|
||||
|
||||
// Verify ops permissions
|
||||
auto res = startCameraOps();
|
||||
if (res != OK) {
|
||||
return res;
|
||||
}
|
||||
|
||||
if (mOfflineSession.get() == nullptr) {
|
||||
ALOGE("%s: Camera %s: No valid offline session",
|
||||
__FUNCTION__, mCameraIdStr.string());
|
||||
return NO_INIT;
|
||||
}
|
||||
|
||||
wp<NotificationListener> weakThis(this);
|
||||
res = mOfflineSession->initialize(weakThis);
|
||||
if (res != OK) {
|
||||
ALOGE("%s: Camera %s: unable to initialize device: %s (%d)",
|
||||
__FUNCTION__, mCameraIdStr.string(), strerror(-res), res);
|
||||
return res;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
status_t CameraOfflineSessionClient::dump(int fd, const Vector<String16>& args) {
|
||||
return BasicClient::dump(fd, args);
|
||||
}
|
||||
|
||||
status_t CameraOfflineSessionClient::dumpClient(int fd, const Vector<String16>& /*args*/) {
|
||||
String8 result;
|
||||
|
||||
result = " Offline session dump:\n";
|
||||
write(fd, result.string(), result.size());
|
||||
|
||||
if (mOfflineSession.get() == nullptr) {
|
||||
result = " *** Offline session is detached\n";
|
||||
write(fd, result.string(), result.size());
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
auto res = mOfflineSession->dump(fd);
|
||||
if (res != OK) {
|
||||
result = String8::format(" Error dumping offline session: %s (%d)",
|
||||
strerror(-res), res);
|
||||
write(fd, result.string(), result.size());
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
binder::Status CameraOfflineSessionClient::disconnect() {
|
||||
Mutex::Autolock icl(mBinderSerializationLock);
|
||||
|
||||
binder::Status res = Status::ok();
|
||||
if (mDisconnected) {
|
||||
return res;
|
||||
}
|
||||
// Allow both client and the media server to disconnect at all times
|
||||
int callingPid = CameraThreadState::getCallingPid();
|
||||
if (callingPid != mClientPid &&
|
||||
callingPid != mServicePid) {
|
||||
return res;
|
||||
}
|
||||
|
||||
mDisconnected = true;
|
||||
|
||||
sCameraService->removeByClient(this);
|
||||
sCameraService->logDisconnectedOffline(mCameraIdStr, mClientPid, String8(mClientPackageName));
|
||||
|
||||
sp<IBinder> remote = getRemote();
|
||||
if (remote != nullptr) {
|
||||
remote->unlinkToDeath(sCameraService);
|
||||
}
|
||||
|
||||
finishCameraOps();
|
||||
ALOGI("%s: Disconnected client for offline camera %s for PID %d", __FUNCTION__,
|
||||
mCameraIdStr.string(), mClientPid);
|
||||
|
||||
// client shouldn't be able to call into us anymore
|
||||
mClientPid = 0;
|
||||
|
||||
if (mOfflineSession.get() != nullptr) {
|
||||
auto ret = mOfflineSession->disconnect();
|
||||
if (ret != OK) {
|
||||
ALOGE("%s: Failed disconnecting from offline session %s (%d)", __FUNCTION__,
|
||||
strerror(-ret), ret);
|
||||
}
|
||||
mOfflineSession = nullptr;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < mCompositeStreamMap.size(); i++) {
|
||||
auto ret = mCompositeStreamMap.valueAt(i)->deleteInternalStreams();
|
||||
if (ret != OK) {
|
||||
ALOGE("%s: Failed removing composite stream %s (%d)", __FUNCTION__,
|
||||
strerror(-ret), ret);
|
||||
}
|
||||
}
|
||||
mCompositeStreamMap.clear();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void CameraOfflineSessionClient::notifyError(int32_t errorCode,
|
||||
const CaptureResultExtras& resultExtras) {
|
||||
// Thread safe. Don't bother locking.
|
||||
// Composites can have multiple internal streams. Error notifications coming from such internal
|
||||
// streams may need to remain within camera service.
|
||||
bool skipClientNotification = false;
|
||||
for (size_t i = 0; i < mCompositeStreamMap.size(); i++) {
|
||||
skipClientNotification |= mCompositeStreamMap.valueAt(i)->onError(errorCode, resultExtras);
|
||||
}
|
||||
|
||||
if ((mRemoteCallback.get() != nullptr) && (!skipClientNotification)) {
|
||||
mRemoteCallback->onDeviceError(errorCode, resultExtras);
|
||||
}
|
||||
}
|
||||
|
||||
status_t CameraOfflineSessionClient::startCameraOps() {
|
||||
ATRACE_CALL();
|
||||
{
|
||||
ALOGV("%s: Start camera ops, package name = %s, client UID = %d",
|
||||
__FUNCTION__, String8(mClientPackageName).string(), mClientUid);
|
||||
}
|
||||
|
||||
if (mAppOpsManager != nullptr) {
|
||||
// Notify app ops that the camera is not available
|
||||
mOpsCallback = new OpsCallback(this);
|
||||
int32_t res;
|
||||
// TODO : possibly change this to OP_OFFLINE_CAMERA_SESSION
|
||||
mAppOpsManager->startWatchingMode(AppOpsManager::OP_CAMERA,
|
||||
mClientPackageName, mOpsCallback);
|
||||
// TODO : possibly change this to OP_OFFLINE_CAMERA_SESSION
|
||||
res = mAppOpsManager->startOpNoThrow(AppOpsManager::OP_CAMERA,
|
||||
mClientUid, mClientPackageName, /*startIfModeDefault*/ false);
|
||||
|
||||
if (res == AppOpsManager::MODE_ERRORED) {
|
||||
ALOGI("Offline Camera %s: Access for \"%s\" has been revoked",
|
||||
mCameraIdStr.string(), String8(mClientPackageName).string());
|
||||
return PERMISSION_DENIED;
|
||||
}
|
||||
|
||||
if (res == AppOpsManager::MODE_IGNORED) {
|
||||
ALOGI("Offline Camera %s: Access for \"%s\" has been restricted",
|
||||
mCameraIdStr.string(), String8(mClientPackageName).string());
|
||||
// Return the same error as for device policy manager rejection
|
||||
return -EACCES;
|
||||
}
|
||||
}
|
||||
|
||||
mOpsActive = true;
|
||||
|
||||
// Transition device state to OPEN
|
||||
sCameraService->mUidPolicy->registerMonitorUid(mClientUid);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
status_t CameraOfflineSessionClient::finishCameraOps() {
|
||||
ATRACE_CALL();
|
||||
|
||||
// Check if startCameraOps succeeded, and if so, finish the camera op
|
||||
if (mOpsActive) {
|
||||
// Notify app ops that the camera is available again
|
||||
if (mAppOpsManager != nullptr) {
|
||||
// TODO : possibly change this to OP_OFFLINE_CAMERA_SESSION
|
||||
mAppOpsManager->finishOp(AppOpsManager::OP_CAMERA, mClientUid,
|
||||
mClientPackageName);
|
||||
mOpsActive = false;
|
||||
}
|
||||
}
|
||||
// Always stop watching, even if no camera op is active
|
||||
if (mOpsCallback != nullptr && mAppOpsManager != nullptr) {
|
||||
mAppOpsManager->stopWatchingMode(mOpsCallback);
|
||||
}
|
||||
mOpsCallback.clear();
|
||||
|
||||
sCameraService->mUidPolicy->unregisterMonitorUid(mClientUid);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
void CameraOfflineSessionClient::onResultAvailable(const CaptureResult& result) {
|
||||
ATRACE_CALL();
|
||||
ALOGV("%s", __FUNCTION__);
|
||||
|
||||
if (mRemoteCallback.get() != NULL) {
|
||||
mRemoteCallback->onResultReceived(result.mMetadata, result.mResultExtras,
|
||||
result.mPhysicalMetadatas);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < mCompositeStreamMap.size(); i++) {
|
||||
mCompositeStreamMap.valueAt(i)->onResultAvailable(result);
|
||||
}
|
||||
}
|
||||
|
||||
void CameraOfflineSessionClient::notifyShutter(const CaptureResultExtras& resultExtras,
|
||||
nsecs_t timestamp) {
|
||||
|
||||
if (mRemoteCallback.get() != nullptr) {
|
||||
mRemoteCallback->onCaptureStarted(resultExtras, timestamp);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < mCompositeStreamMap.size(); i++) {
|
||||
mCompositeStreamMap.valueAt(i)->onShutter(resultExtras, timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
void CameraOfflineSessionClient::notifyIdle() {
|
||||
if (mRemoteCallback.get() != nullptr) {
|
||||
mRemoteCallback->onDeviceIdle();
|
||||
}
|
||||
}
|
||||
|
||||
void CameraOfflineSessionClient::notifyAutoFocus(uint8_t newState, int triggerId) {
|
||||
(void)newState;
|
||||
(void)triggerId;
|
||||
|
||||
ALOGV("%s: Autofocus state now %d, last trigger %d",
|
||||
__FUNCTION__, newState, triggerId);
|
||||
}
|
||||
|
||||
void CameraOfflineSessionClient::notifyAutoExposure(uint8_t newState, int triggerId) {
|
||||
(void)newState;
|
||||
(void)triggerId;
|
||||
|
||||
ALOGV("%s: Autoexposure state now %d, last trigger %d",
|
||||
__FUNCTION__, newState, triggerId);
|
||||
}
|
||||
|
||||
void CameraOfflineSessionClient::notifyAutoWhitebalance(uint8_t newState, int triggerId) {
|
||||
(void)newState;
|
||||
(void)triggerId;
|
||||
|
||||
ALOGV("%s: Auto-whitebalance state now %d, last trigger %d", __FUNCTION__, newState,
|
||||
triggerId);
|
||||
}
|
||||
|
||||
void CameraOfflineSessionClient::notifyPrepared(int /*streamId*/) {
|
||||
ALOGE("%s: Unexpected stream prepare notification in offline mode!", __FUNCTION__);
|
||||
notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE,
|
||||
CaptureResultExtras());
|
||||
}
|
||||
|
||||
void CameraOfflineSessionClient::notifyRequestQueueEmpty() {
|
||||
if (mRemoteCallback.get() != nullptr) {
|
||||
mRemoteCallback->onRequestQueueEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
void CameraOfflineSessionClient::notifyRepeatingRequestError(long /*lastFrameNumber*/) {
|
||||
ALOGE("%s: Unexpected repeating request error in offline mode!", __FUNCTION__);
|
||||
notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE,
|
||||
CaptureResultExtras());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
}; // namespace android
|
@ -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
@ -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
|
File diff suppressed because it is too large
Load Diff
@ -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
|
@ -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
|
Loading…
Reference in new issue