You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
422 lines
17 KiB
422 lines
17 KiB
/*
|
|
* Copyright (C) 2016 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_HARDWARE_CAMERA_DEVICE_V3_2_CAMERADEVICE3SESSION_H
|
|
#define ANDROID_HARDWARE_CAMERA_DEVICE_V3_2_CAMERADEVICE3SESSION_H
|
|
|
|
#include <android/hardware/camera/device/3.2/ICameraDevice.h>
|
|
#include <android/hardware/camera/device/3.2/ICameraDeviceSession.h>
|
|
#include <fmq/MessageQueue.h>
|
|
#include <hidl/MQDescriptor.h>
|
|
#include <hidl/Status.h>
|
|
#include <include/convert.h>
|
|
#include <deque>
|
|
#include <map>
|
|
#include <unordered_map>
|
|
#include "CameraMetadata.h"
|
|
#include "HandleImporter.h"
|
|
#include "hardware/camera3.h"
|
|
#include "hardware/camera_common.h"
|
|
#include "utils/Mutex.h"
|
|
|
|
namespace android {
|
|
namespace hardware {
|
|
namespace camera {
|
|
namespace device {
|
|
namespace V3_2 {
|
|
namespace implementation {
|
|
|
|
using ::android::hardware::camera::device::V3_2::CaptureRequest;
|
|
using ::android::hardware::camera::device::V3_2::HalStreamConfiguration;
|
|
using ::android::hardware::camera::device::V3_2::StreamConfiguration;
|
|
using ::android::hardware::camera::device::V3_2::ICameraDeviceSession;
|
|
using ::android::hardware::camera::common::V1_0::Status;
|
|
using ::android::hardware::camera::common::V1_0::helper::HandleImporter;
|
|
using ::android::hardware::kSynchronizedReadWrite;
|
|
using ::android::hardware::MessageQueue;
|
|
using ::android::hardware::MQDescriptorSync;
|
|
using ::android::hardware::Return;
|
|
using ::android::hardware::Void;
|
|
using ::android::hardware::hidl_vec;
|
|
using ::android::hardware::hidl_string;
|
|
using ::android::sp;
|
|
using ::android::Mutex;
|
|
|
|
struct Camera3Stream;
|
|
|
|
/**
|
|
* Function pointer types with C calling convention to
|
|
* use for HAL callback functions.
|
|
*/
|
|
extern "C" {
|
|
typedef void (callbacks_process_capture_result_t)(
|
|
const struct camera3_callback_ops *,
|
|
const camera3_capture_result_t *);
|
|
|
|
typedef void (callbacks_notify_t)(
|
|
const struct camera3_callback_ops *,
|
|
const camera3_notify_msg_t *);
|
|
}
|
|
|
|
struct CameraDeviceSession : public virtual RefBase, protected camera3_callback_ops {
|
|
|
|
CameraDeviceSession(camera3_device_t*,
|
|
const camera_metadata_t* deviceInfo,
|
|
const sp<ICameraDeviceCallback>&);
|
|
virtual ~CameraDeviceSession();
|
|
// Call by CameraDevice to dump active device states
|
|
void dumpState(const native_handle_t* fd);
|
|
// Caller must use this method to check if CameraDeviceSession ctor failed
|
|
bool isInitFailed() { return mInitFail; }
|
|
// Used by CameraDevice to signal external camera disconnected
|
|
void disconnect();
|
|
bool isClosed();
|
|
|
|
// Retrieve the HIDL interface, split into its own class to avoid inheritance issues when
|
|
// dealing with minor version revs and simultaneous implementation and interface inheritance
|
|
virtual sp<ICameraDeviceSession> getInterface() {
|
|
return new TrampolineSessionInterface_3_2(this);
|
|
}
|
|
|
|
protected:
|
|
|
|
// Methods from ::android::hardware::camera::device::V3_2::ICameraDeviceSession follow
|
|
|
|
Return<void> constructDefaultRequestSettings(
|
|
RequestTemplate type,
|
|
ICameraDeviceSession::constructDefaultRequestSettings_cb _hidl_cb);
|
|
Return<void> configureStreams(
|
|
const StreamConfiguration& requestedConfiguration,
|
|
ICameraDeviceSession::configureStreams_cb _hidl_cb);
|
|
Return<void> getCaptureRequestMetadataQueue(
|
|
ICameraDeviceSession::getCaptureRequestMetadataQueue_cb _hidl_cb);
|
|
Return<void> getCaptureResultMetadataQueue(
|
|
ICameraDeviceSession::getCaptureResultMetadataQueue_cb _hidl_cb);
|
|
Return<void> processCaptureRequest(
|
|
const hidl_vec<CaptureRequest>& requests,
|
|
const hidl_vec<BufferCache>& cachesToRemove,
|
|
ICameraDeviceSession::processCaptureRequest_cb _hidl_cb);
|
|
Return<Status> flush();
|
|
Return<void> close();
|
|
|
|
// Helper methods
|
|
Status constructDefaultRequestSettingsRaw(int type, CameraMetadata *outMetadata);
|
|
|
|
bool preProcessConfigurationLocked(const StreamConfiguration& requestedConfiguration,
|
|
camera3_stream_configuration_t *stream_list /*out*/,
|
|
hidl_vec<camera3_stream_t*> *streams /*out*/);
|
|
void postProcessConfigurationLocked(const StreamConfiguration& requestedConfiguration);
|
|
|
|
void postProcessConfigurationFailureLocked(const StreamConfiguration& requestedConfiguration);
|
|
|
|
protected:
|
|
|
|
// protecting mClosed/mDisconnected/mInitFail
|
|
mutable Mutex mStateLock;
|
|
// device is closed either
|
|
// - closed by user
|
|
// - init failed
|
|
// - camera disconnected
|
|
bool mClosed = false;
|
|
|
|
// Set by CameraDevice (when external camera is disconnected)
|
|
bool mDisconnected = false;
|
|
|
|
struct AETriggerCancelOverride {
|
|
bool applyAeLock;
|
|
uint8_t aeLock;
|
|
bool applyAePrecaptureTrigger;
|
|
uint8_t aePrecaptureTrigger;
|
|
};
|
|
|
|
camera3_device_t* mDevice;
|
|
const uint32_t mDeviceVersion;
|
|
const bool mFreeBufEarly;
|
|
bool mIsAELockAvailable;
|
|
bool mDerivePostRawSensKey;
|
|
uint32_t mNumPartialResults;
|
|
// Stream ID -> Camera3Stream cache
|
|
std::map<int, Camera3Stream> mStreamMap;
|
|
|
|
mutable Mutex mInflightLock; // protecting mInflightBuffers and mCirculatingBuffers
|
|
// (streamID, frameNumber) -> inflight buffer cache
|
|
std::map<std::pair<int, uint32_t>, camera3_stream_buffer_t> mInflightBuffers;
|
|
|
|
// (frameNumber, AETriggerOverride) -> inflight request AETriggerOverrides
|
|
std::map<uint32_t, AETriggerCancelOverride> mInflightAETriggerOverrides;
|
|
::android::hardware::camera::common::V1_0::helper::CameraMetadata mOverridenResult;
|
|
std::map<uint32_t, bool> mInflightRawBoostPresent;
|
|
::android::hardware::camera::common::V1_0::helper::CameraMetadata mOverridenRequest;
|
|
|
|
static const uint64_t BUFFER_ID_NO_BUFFER = 0;
|
|
// buffers currently ciculating between HAL and camera service
|
|
// key: bufferId sent via HIDL interface
|
|
// value: imported buffer_handle_t
|
|
// Buffer will be imported during process_capture_request and will be freed
|
|
// when the its stream is deleted or camera device session is closed
|
|
typedef std::unordered_map<uint64_t, buffer_handle_t> CirculatingBuffers;
|
|
// Stream ID -> circulating buffers map
|
|
std::map<int, CirculatingBuffers> mCirculatingBuffers;
|
|
|
|
static HandleImporter sHandleImporter;
|
|
static buffer_handle_t sEmptyBuffer;
|
|
|
|
bool mInitFail;
|
|
bool mFirstRequest = false;
|
|
|
|
common::V1_0::helper::CameraMetadata mDeviceInfo;
|
|
|
|
using RequestMetadataQueue = MessageQueue<uint8_t, kSynchronizedReadWrite>;
|
|
std::unique_ptr<RequestMetadataQueue> mRequestMetadataQueue;
|
|
using ResultMetadataQueue = MessageQueue<uint8_t, kSynchronizedReadWrite>;
|
|
std::shared_ptr<ResultMetadataQueue> mResultMetadataQueue;
|
|
|
|
class ResultBatcher {
|
|
public:
|
|
ResultBatcher(const sp<ICameraDeviceCallback>& callback);
|
|
void setNumPartialResults(uint32_t n);
|
|
void setBatchedStreams(const std::vector<int>& streamsToBatch);
|
|
void setResultMetadataQueue(std::shared_ptr<ResultMetadataQueue> q);
|
|
|
|
void registerBatch(uint32_t frameNumber, uint32_t batchSize);
|
|
void notify(NotifyMsg& msg);
|
|
void processCaptureResult(CaptureResult& result);
|
|
|
|
protected:
|
|
struct InflightBatch {
|
|
// Protect access to entire struct. Acquire this lock before read/write any data or
|
|
// calling any methods. processCaptureResult and notify will compete for this lock
|
|
// HIDL IPCs might be issued while the lock is held
|
|
Mutex mLock;
|
|
|
|
bool allDelivered() const;
|
|
|
|
uint32_t mFirstFrame;
|
|
uint32_t mLastFrame;
|
|
uint32_t mBatchSize;
|
|
|
|
bool mShutterDelivered = false;
|
|
std::vector<NotifyMsg> mShutterMsgs;
|
|
|
|
struct BufferBatch {
|
|
BufferBatch(uint32_t batchSize) {
|
|
mBuffers.reserve(batchSize);
|
|
}
|
|
bool mDelivered = false;
|
|
// This currently assumes every batched request will output to the batched stream
|
|
// and since HAL must always send buffers in order, no frameNumber tracking is
|
|
// needed
|
|
std::vector<StreamBuffer> mBuffers;
|
|
};
|
|
// Stream ID -> VideoBatch
|
|
std::unordered_map<int, BufferBatch> mBatchBufs;
|
|
|
|
struct MetadataBatch {
|
|
// (frameNumber, metadata)
|
|
std::vector<std::pair<uint32_t, CameraMetadata>> mMds;
|
|
};
|
|
// Partial result IDs that has been delivered to framework
|
|
uint32_t mNumPartialResults;
|
|
uint32_t mPartialResultProgress = 0;
|
|
// partialResult -> MetadataBatch
|
|
std::map<uint32_t, MetadataBatch> mResultMds;
|
|
|
|
// Set to true when batch is removed from mInflightBatches
|
|
// processCaptureResult and notify must check this flag after acquiring mLock to make
|
|
// sure this batch isn't removed while waiting for mLock
|
|
bool mRemoved = false;
|
|
};
|
|
|
|
|
|
// Get the batch index and pointer to InflightBatch (nullptrt if the frame is not batched)
|
|
// Caller must acquire the InflightBatch::mLock before accessing the InflightBatch
|
|
// It's possible that the InflightBatch is removed from mInflightBatches before the
|
|
// InflightBatch::mLock is acquired (most likely caused by an error notification), so
|
|
// caller must check InflightBatch::mRemoved flag after the lock is acquried.
|
|
// This method will hold ResultBatcher::mLock briefly
|
|
std::pair<int, std::shared_ptr<InflightBatch>> getBatch(uint32_t frameNumber);
|
|
|
|
static const int NOT_BATCHED = -1;
|
|
|
|
// move/push function avoids "hidl_handle& operator=(hidl_handle&)", which clones native
|
|
// handle
|
|
void moveStreamBuffer(StreamBuffer&& src, StreamBuffer& dst);
|
|
void pushStreamBuffer(StreamBuffer&& src, std::vector<StreamBuffer>& dst);
|
|
|
|
void sendBatchMetadataLocked(
|
|
std::shared_ptr<InflightBatch> batch, uint32_t lastPartialResultIdx);
|
|
|
|
// Check if the first batch in mInflightBatches is ready to be removed, and remove it if so
|
|
// This method will hold ResultBatcher::mLock briefly
|
|
void checkAndRemoveFirstBatch();
|
|
|
|
// The following sendXXXX methods must be called while the InflightBatch::mLock is locked
|
|
// HIDL IPC methods will be called during these methods.
|
|
void sendBatchShutterCbsLocked(std::shared_ptr<InflightBatch> batch);
|
|
// send buffers for all batched streams
|
|
void sendBatchBuffersLocked(std::shared_ptr<InflightBatch> batch);
|
|
// send buffers for specified streams
|
|
void sendBatchBuffersLocked(
|
|
std::shared_ptr<InflightBatch> batch, const std::vector<int>& streams);
|
|
// End of sendXXXX methods
|
|
|
|
// helper methods
|
|
void freeReleaseFences(hidl_vec<CaptureResult>&);
|
|
void notifySingleMsg(NotifyMsg& msg);
|
|
void processOneCaptureResult(CaptureResult& result);
|
|
void invokeProcessCaptureResultCallback(hidl_vec<CaptureResult> &results, bool tryWriteFmq);
|
|
|
|
// Protect access to mInflightBatches, mNumPartialResults and mStreamsToBatch
|
|
// processCaptureRequest, processCaptureResult, notify will compete for this lock
|
|
// Do NOT issue HIDL IPCs while holding this lock (except when HAL reports error)
|
|
mutable Mutex mLock;
|
|
std::deque<std::shared_ptr<InflightBatch>> mInflightBatches;
|
|
uint32_t mNumPartialResults;
|
|
std::vector<int> mStreamsToBatch;
|
|
const sp<ICameraDeviceCallback> mCallback;
|
|
std::shared_ptr<ResultMetadataQueue> mResultMetadataQueue;
|
|
|
|
// Protect against invokeProcessCaptureResultCallback()
|
|
Mutex mProcessCaptureResultLock;
|
|
|
|
} mResultBatcher;
|
|
|
|
std::vector<int> mVideoStreamIds;
|
|
|
|
bool initialize();
|
|
|
|
static bool shouldFreeBufEarly();
|
|
|
|
Status initStatus() const;
|
|
|
|
// Validate and import request's input buffer and acquire fence
|
|
virtual Status importRequest(
|
|
const CaptureRequest& request,
|
|
hidl_vec<buffer_handle_t*>& allBufPtrs,
|
|
hidl_vec<int>& allFences);
|
|
|
|
Status importRequestImpl(
|
|
const CaptureRequest& request,
|
|
hidl_vec<buffer_handle_t*>& allBufPtrs,
|
|
hidl_vec<int>& allFences,
|
|
// Optional argument for ICameraDeviceSession@3.5 impl
|
|
bool allowEmptyBuf = false);
|
|
|
|
Status importBuffer(int32_t streamId,
|
|
uint64_t bufId, buffer_handle_t buf,
|
|
/*out*/buffer_handle_t** outBufPtr,
|
|
bool allowEmptyBuf);
|
|
|
|
static void cleanupInflightFences(
|
|
hidl_vec<int>& allFences, size_t numFences);
|
|
|
|
void cleanupBuffersLocked(int id);
|
|
|
|
void updateBufferCaches(const hidl_vec<BufferCache>& cachesToRemove);
|
|
|
|
android_dataspace mapToLegacyDataspace(
|
|
android_dataspace dataSpace) const;
|
|
|
|
bool handleAePrecaptureCancelRequestLocked(
|
|
const camera3_capture_request_t &halRequest,
|
|
android::hardware::camera::common::V1_0::helper::CameraMetadata *settings /*out*/,
|
|
AETriggerCancelOverride *override /*out*/);
|
|
|
|
void overrideResultForPrecaptureCancelLocked(
|
|
const AETriggerCancelOverride &aeTriggerCancelOverride,
|
|
::android::hardware::camera::common::V1_0::helper::CameraMetadata *settings /*out*/);
|
|
|
|
Status processOneCaptureRequest(const CaptureRequest& request);
|
|
/**
|
|
* Static callback forwarding methods from HAL to instance
|
|
*/
|
|
static callbacks_process_capture_result_t sProcessCaptureResult;
|
|
static callbacks_notify_t sNotify;
|
|
|
|
// By default camera service uses frameNumber/streamId pair to retrieve the buffer that
|
|
// was sent to HAL. Override this implementation if HAL is using buffers from buffer management
|
|
// APIs to send output buffer.
|
|
virtual uint64_t getCapResultBufferId(const buffer_handle_t& buf, int streamId);
|
|
|
|
status_t constructCaptureResult(CaptureResult& result,
|
|
const camera3_capture_result *hal_result);
|
|
|
|
// Static helper method to copy/shrink capture result metadata sent by HAL
|
|
// Temporarily allocated metadata copy will be hold in mds
|
|
static void sShrinkCaptureResult(
|
|
camera3_capture_result* dst, const camera3_capture_result* src,
|
|
std::vector<::android::hardware::camera::common::V1_0::helper::CameraMetadata>* mds,
|
|
std::vector<const camera_metadata_t*>* physCamMdArray,
|
|
bool handlePhysCam);
|
|
static bool sShouldShrink(const camera_metadata_t* md);
|
|
static camera_metadata_t* sCreateCompactCopy(const camera_metadata_t* src);
|
|
|
|
private:
|
|
|
|
struct TrampolineSessionInterface_3_2 : public ICameraDeviceSession {
|
|
TrampolineSessionInterface_3_2(sp<CameraDeviceSession> parent) :
|
|
mParent(parent) {}
|
|
|
|
virtual Return<void> constructDefaultRequestSettings(
|
|
V3_2::RequestTemplate type,
|
|
V3_2::ICameraDeviceSession::constructDefaultRequestSettings_cb _hidl_cb) override {
|
|
return mParent->constructDefaultRequestSettings(type, _hidl_cb);
|
|
}
|
|
|
|
virtual Return<void> configureStreams(
|
|
const V3_2::StreamConfiguration& requestedConfiguration,
|
|
V3_2::ICameraDeviceSession::configureStreams_cb _hidl_cb) override {
|
|
return mParent->configureStreams(requestedConfiguration, _hidl_cb);
|
|
}
|
|
|
|
virtual Return<void> processCaptureRequest(const hidl_vec<V3_2::CaptureRequest>& requests,
|
|
const hidl_vec<V3_2::BufferCache>& cachesToRemove,
|
|
V3_2::ICameraDeviceSession::processCaptureRequest_cb _hidl_cb) override {
|
|
return mParent->processCaptureRequest(requests, cachesToRemove, _hidl_cb);
|
|
}
|
|
|
|
virtual Return<void> getCaptureRequestMetadataQueue(
|
|
V3_2::ICameraDeviceSession::getCaptureRequestMetadataQueue_cb _hidl_cb) override {
|
|
return mParent->getCaptureRequestMetadataQueue(_hidl_cb);
|
|
}
|
|
|
|
virtual Return<void> getCaptureResultMetadataQueue(
|
|
V3_2::ICameraDeviceSession::getCaptureResultMetadataQueue_cb _hidl_cb) override {
|
|
return mParent->getCaptureResultMetadataQueue(_hidl_cb);
|
|
}
|
|
|
|
virtual Return<Status> flush() override {
|
|
return mParent->flush();
|
|
}
|
|
|
|
virtual Return<void> close() override {
|
|
return mParent->close();
|
|
}
|
|
|
|
private:
|
|
sp<CameraDeviceSession> mParent;
|
|
};
|
|
};
|
|
|
|
} // namespace implementation
|
|
} // namespace V3_2
|
|
} // namespace device
|
|
} // namespace camera
|
|
} // namespace hardware
|
|
} // namespace android
|
|
|
|
#endif // ANDROID_HARDWARE_CAMERA_DEVICE_V3_2_CAMERADEVICE3SESSION_H
|