Loading camera/device/3.4/default/ExternalCameraDevice.cpp +35 −59 Original line number Diff line number Diff line Loading @@ -50,22 +50,29 @@ constexpr int OPEN_RETRY_SLEEP_US = 100000; // 100ms * MAX_RETRY = 0.5 seconds ExternalCameraDevice::ExternalCameraDevice( const std::string& cameraId, const ExternalCameraConfig& cfg) : mCameraId(cameraId), mCfg(cfg) { mCfg(cfg) {} ExternalCameraDevice::~ExternalCameraDevice() {} bool ExternalCameraDevice::isInitFailed() { Mutex::Autolock _l(mLock); return isInitFailedLocked(); } bool ExternalCameraDevice::isInitFailedLocked() { if (!mInitialized) { status_t ret = initCameraCharacteristics(); if (ret != OK) { ALOGE("%s: init camera characteristics failed: errorno %d", __FUNCTION__, ret); mInitFailed = true; } mInitialized = true; } ExternalCameraDevice::~ExternalCameraDevice() {} bool ExternalCameraDevice::isInitFailed() { return mInitFailed; } Return<void> ExternalCameraDevice::getResourceCost(getResourceCost_cb _hidl_cb) { Return<void> ExternalCameraDevice::getResourceCost( ICameraDevice::getResourceCost_cb _hidl_cb) { CameraResourceCost resCost; resCost.resourceCost = 100; _hidl_cb(Status::OK, resCost); Loading @@ -73,11 +80,11 @@ Return<void> ExternalCameraDevice::getResourceCost(getResourceCost_cb _hidl_cb) } Return<void> ExternalCameraDevice::getCameraCharacteristics( getCameraCharacteristics_cb _hidl_cb) { ICameraDevice::getCameraCharacteristics_cb _hidl_cb) { Mutex::Autolock _l(mLock); V3_2::CameraMetadata hidlChars; if (isInitFailed()) { if (isInitFailedLocked()) { _hidl_cb(Status::INTERNAL_ERROR, hidlChars); return Void(); } Loading @@ -94,7 +101,7 @@ Return<Status> ExternalCameraDevice::setTorchMode(TorchMode) { } Return<void> ExternalCameraDevice::open( const sp<ICameraDeviceCallback>& callback, open_cb _hidl_cb) { const sp<ICameraDeviceCallback>& callback, ICameraDevice::open_cb _hidl_cb) { Status status = Status::OK; sp<ExternalCameraDeviceSession> session = nullptr; Loading Loading @@ -143,7 +150,7 @@ Return<void> ExternalCameraDevice::open( } } session = new ExternalCameraDeviceSession( session = createSession( callback, mCfg, mSupportedFormats, mCroppingType, mCameraCharacteristics, mCameraId, std::move(fd)); if (session == nullptr) { Loading Loading @@ -479,52 +486,9 @@ status_t ExternalCameraDevice::initDefaultCharsKeys( UPDATE(ANDROID_REQUEST_AVAILABLE_RESULT_KEYS, availableResultKeys, ARRAY_SIZE(availableResultKeys)); const int32_t availableCharacteristicsKeys[] = { ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES, ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES, ANDROID_CONTROL_AE_AVAILABLE_MODES, ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, ANDROID_CONTROL_AE_COMPENSATION_RANGE, ANDROID_CONTROL_AE_COMPENSATION_STEP, ANDROID_CONTROL_AE_LOCK_AVAILABLE, ANDROID_CONTROL_AF_AVAILABLE_MODES, ANDROID_CONTROL_AVAILABLE_EFFECTS, ANDROID_CONTROL_AVAILABLE_MODES, ANDROID_CONTROL_AVAILABLE_SCENE_MODES, ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES, ANDROID_CONTROL_AWB_AVAILABLE_MODES, ANDROID_CONTROL_AWB_LOCK_AVAILABLE, ANDROID_CONTROL_MAX_REGIONS, ANDROID_FLASH_INFO_AVAILABLE, ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL, ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES, ANDROID_LENS_FACING, ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION, ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION, ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES, ANDROID_REQUEST_AVAILABLE_CAPABILITIES, ANDROID_REQUEST_MAX_NUM_INPUT_STREAMS, ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS, ANDROID_REQUEST_PARTIAL_RESULT_COUNT, ANDROID_REQUEST_PIPELINE_MAX_DEPTH, ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, ANDROID_SCALER_CROPPING_TYPE, ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE, ANDROID_SENSOR_INFO_MAX_FRAME_DURATION, ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE, ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE, ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE, ANDROID_SENSOR_ORIENTATION, ANDROID_SHADING_AVAILABLE_MODES, ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES, ANDROID_STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES, ANDROID_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES, ANDROID_STATISTICS_INFO_MAX_FACE_COUNT, ANDROID_SYNC_MAX_LATENCY}; UPDATE(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS, availableCharacteristicsKeys, ARRAY_SIZE(availableCharacteristicsKeys)); AVAILABLE_CHARACTERISTICS_KEYS_3_4.data(), AVAILABLE_CHARACTERISTICS_KEYS_3_4.size()); return OK; } Loading Loading @@ -931,6 +895,18 @@ void ExternalCameraDevice::initSupportedFormatsLocked(int fd) { } } sp<ExternalCameraDeviceSession> ExternalCameraDevice::createSession( const sp<ICameraDeviceCallback>& cb, const ExternalCameraConfig& cfg, const std::vector<SupportedV4L2Format>& sortedFormats, const CroppingType& croppingType, const common::V1_0::helper::CameraMetadata& chars, const std::string& cameraId, unique_fd v4l2Fd) { return new ExternalCameraDeviceSession( cb, cfg, sortedFormats, croppingType, chars, cameraId, std::move(v4l2Fd)); } } // namespace implementation } // namespace V3_4 } // namespace device Loading camera/device/3.4/default/ExternalCameraDeviceSession.cpp +161 −59 Original line number Diff line number Diff line Loading @@ -81,6 +81,8 @@ bool tryLock(std::mutex& mutex) return locked; } buffer_handle_t sEmptyBuffer = nullptr; } // Anonymous namespace // Static instances Loading @@ -103,11 +105,8 @@ ExternalCameraDeviceSession::ExternalCameraDeviceSession( mCroppingType(croppingType), mCameraId(cameraId), mV4l2Fd(std::move(v4l2Fd)), mOutputThread(new OutputThread(this, mCroppingType)), mMaxThumbResolution(getMaxThumbResolution()), mMaxJpegResolution(getMaxJpegResolution()) { mInitFail = initialize(); } mMaxJpegResolution(getMaxJpegResolution()) {} bool ExternalCameraDeviceSession::initialize() { if (mV4l2Fd.get() < 0) { Loading Loading @@ -142,6 +141,12 @@ bool ExternalCameraDeviceSession::initialize() { model = card; } } initOutputThread(); if (mOutputThread == nullptr) { ALOGE("%s: init OutputThread failed!", __FUNCTION__); return true; } mOutputThread->setExifMakeModel(make, model); status_t status = initDefaultRequests(); Loading @@ -168,6 +173,32 @@ bool ExternalCameraDeviceSession::initialize() { return false; } bool ExternalCameraDeviceSession::isInitFailed() { Mutex::Autolock _l(mLock); if (!mInitialized) { mInitFail = initialize(); mInitialized = true; } return mInitFail; } void ExternalCameraDeviceSession::initOutputThread() { mOutputThread = new OutputThread(this, mCroppingType); } void ExternalCameraDeviceSession::closeOutputThread() { closeOutputThreadImpl(); } void ExternalCameraDeviceSession::closeOutputThreadImpl() { if (mOutputThread) { mOutputThread->flush(); mOutputThread->requestExit(); mOutputThread->join(); mOutputThread.clear(); } } Status ExternalCameraDeviceSession::initStatus() const { Mutex::Autolock _l(mLock); Status status = Status::OK; Loading @@ -181,7 +212,7 @@ Status ExternalCameraDeviceSession::initStatus() const { ExternalCameraDeviceSession::~ExternalCameraDeviceSession() { if (!isClosed()) { ALOGE("ExternalCameraDeviceSession deleted before close!"); close(); close(/*callerIsDtor*/true); } } Loading Loading @@ -442,19 +473,24 @@ Return<Status> ExternalCameraDeviceSession::flush() { return Status::OK; } Return<void> ExternalCameraDeviceSession::close() { Return<void> ExternalCameraDeviceSession::close(bool callerIsDtor) { Mutex::Autolock _il(mInterfaceLock); bool closed = isClosed(); if (!closed) { mOutputThread->flush(); mOutputThread->requestExit(); mOutputThread->join(); if (callerIsDtor) { closeOutputThreadImpl(); } else { closeOutputThread(); } Mutex::Autolock _l(mLock); // free all buffers { Mutex::Autolock _l(mCbsLock); for(auto pair : mStreamMap) { cleanupBuffersLocked(/*Stream ID*/pair.first); } } v4l2StreamOffLocked(); ALOGV("%s: closing V4L2 camera FD %d", __FUNCTION__, mV4l2Fd.get()); mV4l2Fd.reset(); Loading @@ -463,10 +499,61 @@ Return<void> ExternalCameraDeviceSession::close() { return Void(); } Status ExternalCameraDeviceSession::importRequest( Status ExternalCameraDeviceSession::importRequestLocked( const CaptureRequest& request, hidl_vec<buffer_handle_t*>& allBufPtrs, hidl_vec<int>& allFences) { return importRequestLockedImpl(request, allBufPtrs, allFences); } Status ExternalCameraDeviceSession::importBuffer(int32_t streamId, uint64_t bufId, buffer_handle_t buf, /*out*/buffer_handle_t** outBufPtr, bool allowEmptyBuf) { Mutex::Autolock _l(mCbsLock); return importBufferLocked(streamId, bufId, buf, outBufPtr, allowEmptyBuf); } Status ExternalCameraDeviceSession::importBufferLocked(int32_t streamId, uint64_t bufId, buffer_handle_t buf, /*out*/buffer_handle_t** outBufPtr, bool allowEmptyBuf) { if (buf == nullptr && bufId == BUFFER_ID_NO_BUFFER) { if (allowEmptyBuf) { *outBufPtr = &sEmptyBuffer; return Status::OK; } else { ALOGE("%s: bufferId %" PRIu64 " has null buffer handle!", __FUNCTION__, bufId); return Status::ILLEGAL_ARGUMENT; } } CirculatingBuffers& cbs = mCirculatingBuffers[streamId]; if (cbs.count(bufId) == 0) { if (buf == nullptr) { ALOGE("%s: bufferId %" PRIu64 " has null buffer handle!", __FUNCTION__, bufId); return Status::ILLEGAL_ARGUMENT; } // Register a newly seen buffer buffer_handle_t importedBuf = buf; sHandleImporter.importBuffer(importedBuf); if (importedBuf == nullptr) { ALOGE("%s: output buffer for stream %d is invalid!", __FUNCTION__, streamId); return Status::INTERNAL_ERROR; } else { cbs[bufId] = importedBuf; } } *outBufPtr = &cbs[bufId]; return Status::OK; } Status ExternalCameraDeviceSession::importRequestLockedImpl( const CaptureRequest& request, hidl_vec<buffer_handle_t*>& allBufPtrs, hidl_vec<int>& allFences, bool allowEmptyBuf) { size_t numOutputBufs = request.outputBuffers.size(); size_t numBufs = numOutputBufs; // Validate all I/O buffers Loading @@ -485,26 +572,17 @@ Status ExternalCameraDeviceSession::importRequest( streamIds[i] = request.outputBuffers[i].streamId; } { Mutex::Autolock _l(mCbsLock); for (size_t i = 0; i < numBufs; i++) { buffer_handle_t buf = allBufs[i]; uint64_t bufId = allBufIds[i]; CirculatingBuffers& cbs = mCirculatingBuffers[streamIds[i]]; if (cbs.count(bufId) == 0) { if (buf == nullptr) { ALOGE("%s: bufferId %" PRIu64 " has null buffer handle!", __FUNCTION__, bufId); return Status::ILLEGAL_ARGUMENT; } // Register a newly seen buffer buffer_handle_t importedBuf = buf; sHandleImporter.importBuffer(importedBuf); if (importedBuf == nullptr) { ALOGE("%s: output buffer %zu is invalid!", __FUNCTION__, i); return Status::INTERNAL_ERROR; } else { cbs[bufId] = importedBuf; Status st = importBufferLocked( streamIds[i], allBufIds[i], allBufs[i], &allBufPtrs[i], allowEmptyBuf); if (st != Status::OK) { // Detailed error logs printed in importBuffer return st; } } allBufPtrs[i] = &cbs[bufId]; } // All buffers are imported. Now validate output buffer acquire fences Loading Loading @@ -652,7 +730,7 @@ Status ExternalCameraDeviceSession::processOneCaptureRequest(const CaptureReques } } status = importRequest(request, allBufPtrs, allFences); status = importRequestLocked(request, allBufPtrs, allFences); if (status != Status::OK) { return status; } Loading Loading @@ -775,9 +853,11 @@ Status ExternalCameraDeviceSession::processCaptureResult(std::shared_ptr<HalRequ result.outputBuffers[i].bufferId = req->buffers[i].bufferId; if (req->buffers[i].fenceTimeout) { result.outputBuffers[i].status = BufferStatus::ERROR; if (req->buffers[i].acquireFence > 0) { native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0); handle->data[0] = req->buffers[i].acquireFence; result.outputBuffers[i].releaseFence.setTo(handle, /*shouldOwn*/false); } notifyError(req->frameNumber, req->buffers[i].streamId, ErrorCode::ERROR_BUFFER); } else { result.outputBuffers[i].status = BufferStatus::OK; Loading Loading @@ -1747,6 +1827,12 @@ bool ExternalCameraDeviceSession::OutputThread::threadLoop() { (req->frameIn->mFourcc >> 24) & 0xFF); } int res = requestBufferStart(req->buffers); if (res != 0) { ALOGE("%s: send BufferRequest failed! res %d", __FUNCTION__, res); return onDeviceError("%s: failed to send buffer request!", __FUNCTION__); } std::unique_lock<std::mutex> lk(mBufferLock); // Convert input V4L2 frame to YU12 of the same size // TODO: see if we can save some computation by converting to YV12 here Loading @@ -1759,7 +1845,7 @@ bool ExternalCameraDeviceSession::OutputThread::threadLoop() { // TODO: in some special case maybe we can decode jpg directly to gralloc output? ATRACE_BEGIN("MJPGtoI420"); int res = libyuv::MJPGToI420( res = libyuv::MJPGToI420( inData, inDataSize, static_cast<uint8_t*>(mYu12FrameLayout.y), mYu12FrameLayout.yStride, Loading @@ -1783,10 +1869,23 @@ bool ExternalCameraDeviceSession::OutputThread::threadLoop() { return true; } ATRACE_BEGIN("Wait for BufferRequest done"); res = waitForBufferRequestDone(&req->buffers); ATRACE_END(); if (res != 0) { ALOGE("%s: wait for BufferRequest done failed! res %d", __FUNCTION__, res); lk.unlock(); return onDeviceError("%s: failed to process buffer request error!", __FUNCTION__); } ALOGV("%s processing new request", __FUNCTION__); const int kSyncWaitTimeoutMs = 500; for (auto& halBuf : req->buffers) { if (halBuf.acquireFence != -1) { if (*(halBuf.bufPtr) == nullptr) { ALOGW("%s: buffer for stream %d missing", __FUNCTION__, halBuf.streamId); halBuf.fenceTimeout = true; } else if (halBuf.acquireFence != -1) { int ret = sync_wait(halBuf.acquireFence, kSyncWaitTimeoutMs); if (ret) { halBuf.fenceTimeout = true; Loading Loading @@ -2045,7 +2144,7 @@ void ExternalCameraDeviceSession::cleanupBuffersLocked(int id) { } void ExternalCameraDeviceSession::updateBufferCaches(const hidl_vec<BufferCache>& cachesToRemove) { Mutex::Autolock _l(mLock); Mutex::Autolock _l(mCbsLock); for (auto& cache : cachesToRemove) { auto cbsIt = mCirculatingBuffers.find(cache.streamId); if (cbsIt == mCirculatingBuffers.end()) { Loading Loading @@ -2499,6 +2598,8 @@ Status ExternalCameraDeviceSession::configureStreams( } Mutex::Autolock _l(mLock); { Mutex::Autolock _l(mCbsLock); // Add new streams for (const auto& stream : config.streams) { if (mStreamMap.count(stream.id) == 0) { Loading @@ -2525,6 +2626,7 @@ Status ExternalCameraDeviceSession::configureStreams( ++it; } } } // Now select a V4L2 format to produce all output streams float desiredAr = (mCroppingType == VERTICAL) ? kMaxAspectRatio : kMinAspectRatio; Loading camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h +40 −5 Original line number Diff line number Diff line Loading @@ -97,7 +97,7 @@ struct ExternalCameraDeviceSession : public virtual RefBase { // Call by CameraDevice to dump active device states void dumpState(const native_handle_t*); // Caller must use this method to check if CameraDeviceSession ctor failed bool isInitFailed() { return mInitFail; } bool isInitFailed(); bool isClosed(); // Retrieve the HIDL interface, split into its own class to avoid inheritance issues when Loading Loading @@ -134,7 +134,7 @@ protected: ICameraDeviceSession::processCaptureRequest_cb); Return<Status> flush(); Return<void> close(); Return<void> close(bool callerIsDtor = false); Return<void> configureStreams_3_3( const V3_2::StreamConfiguration&, Loading Loading @@ -170,10 +170,17 @@ protected: std::vector<HalStreamBuffer> buffers; }; static const uint64_t BUFFER_ID_NO_BUFFER = 0; Status constructDefaultRequestSettingsRaw(RequestTemplate type, V3_2::CameraMetadata *outMetadata); bool initialize(); // To init/close different version of output thread virtual void initOutputThread(); virtual void closeOutputThread(); void closeOutputThreadImpl(); Status initStatus() const; status_t initDefaultRequests(); status_t fillCaptureResult(common::V1_0::helper::CameraMetadata& md, nsecs_t timestamp); Loading @@ -195,10 +202,28 @@ protected: bool isSupported(const Stream&); // Validate and import request's output buffers and acquire fence Status importRequest( virtual Status importRequestLocked( const CaptureRequest& request, hidl_vec<buffer_handle_t*>& allBufPtrs, hidl_vec<int>& allFences); Status importRequestLockedImpl( 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); Status importBufferLocked(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); Loading @@ -224,7 +249,7 @@ protected: class OutputThread : public android::Thread { public: OutputThread(wp<ExternalCameraDeviceSession> parent, CroppingType); ~OutputThread(); virtual ~OutputThread(); Status allocateIntermediateBuffers( const Size& v4lSize, const Size& thumbSize, Loading @@ -236,7 +261,14 @@ protected: virtual bool threadLoop() override; void setExifMakeModel(const std::string& make, const std::string& model); private: protected: // Methods to request output buffer in parallel // No-op for device@3.4. Implemented in device@3.5 virtual int requestBufferStart(const std::vector<HalStreamBuffer>&) { return 0; } virtual int waitForBufferRequestDone( /*out*/std::vector<HalStreamBuffer>*) { return 0; } static const uint32_t FLEX_YUV_GENERIC = static_cast<uint32_t>('F') | static_cast<uint32_t>('L') << 8 | static_cast<uint32_t>('E') << 16 | static_cast<uint32_t>('X') << 24; Loading Loading @@ -319,6 +351,7 @@ protected: // - init failed // - camera disconnected bool mClosed = false; bool mInitialized = false; bool mInitFail = false; bool mFirstRequest = false; common::V1_0::helper::CameraMetadata mLatestReqSetting; Loading Loading @@ -351,6 +384,8 @@ protected: typedef std::unordered_map<uint64_t, buffer_handle_t> CirculatingBuffers; // Stream ID -> circulating buffers map std::map<int, CirculatingBuffers> mCirculatingBuffers; // Protect mCirculatingBuffers, must not lock mLock after acquiring this lock mutable Mutex mCbsLock; std::mutex mAfTriggerLock; // protect mAfTrigger bool mAfTrigger = false; Loading camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDevice_3_4.h +110 −8 File changed.Preview size limit exceeded, changes collapsed. Show changes camera/device/3.5/default/Android.bp +48 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,12 @@ cc_library_headers { export_include_dirs: ["include/device_v3_5_impl"] } cc_library_headers { name: "camera.device@3.5-external-impl_headers", vendor: true, export_include_dirs: ["include/ext_device_v3_5_impl"] } cc_library_shared { name: "camera.device@3.5-impl", defaults: ["hidl_defaults"], Loading Loading @@ -52,3 +58,45 @@ cc_library_shared { ], local_include_dirs: ["include/device_v3_5_impl"], } cc_library_shared { name: "camera.device@3.5-external-impl", defaults: ["hidl_defaults"], proprietary: true, vendor: true, srcs: [ "ExternalCameraDevice.cpp", "ExternalCameraDeviceSession.cpp", ], shared_libs: [ "libhidlbase", "libhidltransport", "libutils", "libcutils", "camera.device@3.2-impl", "camera.device@3.3-impl", "camera.device@3.4-external-impl", "android.hardware.camera.device@3.2", "android.hardware.camera.device@3.3", "android.hardware.camera.device@3.4", "android.hardware.camera.device@3.5", "android.hardware.camera.provider@2.4", "android.hardware.graphics.mapper@2.0", "liblog", "libhardware", "libcamera_metadata", "libfmq", "libsync", "libyuv", "libjpeg", "libexif", "libtinyxml2" ], static_libs: [ "android.hardware.camera.common@1.0-helper", ], local_include_dirs: ["include/ext_device_v3_5_impl"], export_shared_lib_headers: [ "libfmq", ], } Loading
camera/device/3.4/default/ExternalCameraDevice.cpp +35 −59 Original line number Diff line number Diff line Loading @@ -50,22 +50,29 @@ constexpr int OPEN_RETRY_SLEEP_US = 100000; // 100ms * MAX_RETRY = 0.5 seconds ExternalCameraDevice::ExternalCameraDevice( const std::string& cameraId, const ExternalCameraConfig& cfg) : mCameraId(cameraId), mCfg(cfg) { mCfg(cfg) {} ExternalCameraDevice::~ExternalCameraDevice() {} bool ExternalCameraDevice::isInitFailed() { Mutex::Autolock _l(mLock); return isInitFailedLocked(); } bool ExternalCameraDevice::isInitFailedLocked() { if (!mInitialized) { status_t ret = initCameraCharacteristics(); if (ret != OK) { ALOGE("%s: init camera characteristics failed: errorno %d", __FUNCTION__, ret); mInitFailed = true; } mInitialized = true; } ExternalCameraDevice::~ExternalCameraDevice() {} bool ExternalCameraDevice::isInitFailed() { return mInitFailed; } Return<void> ExternalCameraDevice::getResourceCost(getResourceCost_cb _hidl_cb) { Return<void> ExternalCameraDevice::getResourceCost( ICameraDevice::getResourceCost_cb _hidl_cb) { CameraResourceCost resCost; resCost.resourceCost = 100; _hidl_cb(Status::OK, resCost); Loading @@ -73,11 +80,11 @@ Return<void> ExternalCameraDevice::getResourceCost(getResourceCost_cb _hidl_cb) } Return<void> ExternalCameraDevice::getCameraCharacteristics( getCameraCharacteristics_cb _hidl_cb) { ICameraDevice::getCameraCharacteristics_cb _hidl_cb) { Mutex::Autolock _l(mLock); V3_2::CameraMetadata hidlChars; if (isInitFailed()) { if (isInitFailedLocked()) { _hidl_cb(Status::INTERNAL_ERROR, hidlChars); return Void(); } Loading @@ -94,7 +101,7 @@ Return<Status> ExternalCameraDevice::setTorchMode(TorchMode) { } Return<void> ExternalCameraDevice::open( const sp<ICameraDeviceCallback>& callback, open_cb _hidl_cb) { const sp<ICameraDeviceCallback>& callback, ICameraDevice::open_cb _hidl_cb) { Status status = Status::OK; sp<ExternalCameraDeviceSession> session = nullptr; Loading Loading @@ -143,7 +150,7 @@ Return<void> ExternalCameraDevice::open( } } session = new ExternalCameraDeviceSession( session = createSession( callback, mCfg, mSupportedFormats, mCroppingType, mCameraCharacteristics, mCameraId, std::move(fd)); if (session == nullptr) { Loading Loading @@ -479,52 +486,9 @@ status_t ExternalCameraDevice::initDefaultCharsKeys( UPDATE(ANDROID_REQUEST_AVAILABLE_RESULT_KEYS, availableResultKeys, ARRAY_SIZE(availableResultKeys)); const int32_t availableCharacteristicsKeys[] = { ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES, ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES, ANDROID_CONTROL_AE_AVAILABLE_MODES, ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, ANDROID_CONTROL_AE_COMPENSATION_RANGE, ANDROID_CONTROL_AE_COMPENSATION_STEP, ANDROID_CONTROL_AE_LOCK_AVAILABLE, ANDROID_CONTROL_AF_AVAILABLE_MODES, ANDROID_CONTROL_AVAILABLE_EFFECTS, ANDROID_CONTROL_AVAILABLE_MODES, ANDROID_CONTROL_AVAILABLE_SCENE_MODES, ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES, ANDROID_CONTROL_AWB_AVAILABLE_MODES, ANDROID_CONTROL_AWB_LOCK_AVAILABLE, ANDROID_CONTROL_MAX_REGIONS, ANDROID_FLASH_INFO_AVAILABLE, ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL, ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES, ANDROID_LENS_FACING, ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION, ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION, ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES, ANDROID_REQUEST_AVAILABLE_CAPABILITIES, ANDROID_REQUEST_MAX_NUM_INPUT_STREAMS, ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS, ANDROID_REQUEST_PARTIAL_RESULT_COUNT, ANDROID_REQUEST_PIPELINE_MAX_DEPTH, ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, ANDROID_SCALER_CROPPING_TYPE, ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE, ANDROID_SENSOR_INFO_MAX_FRAME_DURATION, ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE, ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE, ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE, ANDROID_SENSOR_ORIENTATION, ANDROID_SHADING_AVAILABLE_MODES, ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES, ANDROID_STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES, ANDROID_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES, ANDROID_STATISTICS_INFO_MAX_FACE_COUNT, ANDROID_SYNC_MAX_LATENCY}; UPDATE(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS, availableCharacteristicsKeys, ARRAY_SIZE(availableCharacteristicsKeys)); AVAILABLE_CHARACTERISTICS_KEYS_3_4.data(), AVAILABLE_CHARACTERISTICS_KEYS_3_4.size()); return OK; } Loading Loading @@ -931,6 +895,18 @@ void ExternalCameraDevice::initSupportedFormatsLocked(int fd) { } } sp<ExternalCameraDeviceSession> ExternalCameraDevice::createSession( const sp<ICameraDeviceCallback>& cb, const ExternalCameraConfig& cfg, const std::vector<SupportedV4L2Format>& sortedFormats, const CroppingType& croppingType, const common::V1_0::helper::CameraMetadata& chars, const std::string& cameraId, unique_fd v4l2Fd) { return new ExternalCameraDeviceSession( cb, cfg, sortedFormats, croppingType, chars, cameraId, std::move(v4l2Fd)); } } // namespace implementation } // namespace V3_4 } // namespace device Loading
camera/device/3.4/default/ExternalCameraDeviceSession.cpp +161 −59 Original line number Diff line number Diff line Loading @@ -81,6 +81,8 @@ bool tryLock(std::mutex& mutex) return locked; } buffer_handle_t sEmptyBuffer = nullptr; } // Anonymous namespace // Static instances Loading @@ -103,11 +105,8 @@ ExternalCameraDeviceSession::ExternalCameraDeviceSession( mCroppingType(croppingType), mCameraId(cameraId), mV4l2Fd(std::move(v4l2Fd)), mOutputThread(new OutputThread(this, mCroppingType)), mMaxThumbResolution(getMaxThumbResolution()), mMaxJpegResolution(getMaxJpegResolution()) { mInitFail = initialize(); } mMaxJpegResolution(getMaxJpegResolution()) {} bool ExternalCameraDeviceSession::initialize() { if (mV4l2Fd.get() < 0) { Loading Loading @@ -142,6 +141,12 @@ bool ExternalCameraDeviceSession::initialize() { model = card; } } initOutputThread(); if (mOutputThread == nullptr) { ALOGE("%s: init OutputThread failed!", __FUNCTION__); return true; } mOutputThread->setExifMakeModel(make, model); status_t status = initDefaultRequests(); Loading @@ -168,6 +173,32 @@ bool ExternalCameraDeviceSession::initialize() { return false; } bool ExternalCameraDeviceSession::isInitFailed() { Mutex::Autolock _l(mLock); if (!mInitialized) { mInitFail = initialize(); mInitialized = true; } return mInitFail; } void ExternalCameraDeviceSession::initOutputThread() { mOutputThread = new OutputThread(this, mCroppingType); } void ExternalCameraDeviceSession::closeOutputThread() { closeOutputThreadImpl(); } void ExternalCameraDeviceSession::closeOutputThreadImpl() { if (mOutputThread) { mOutputThread->flush(); mOutputThread->requestExit(); mOutputThread->join(); mOutputThread.clear(); } } Status ExternalCameraDeviceSession::initStatus() const { Mutex::Autolock _l(mLock); Status status = Status::OK; Loading @@ -181,7 +212,7 @@ Status ExternalCameraDeviceSession::initStatus() const { ExternalCameraDeviceSession::~ExternalCameraDeviceSession() { if (!isClosed()) { ALOGE("ExternalCameraDeviceSession deleted before close!"); close(); close(/*callerIsDtor*/true); } } Loading Loading @@ -442,19 +473,24 @@ Return<Status> ExternalCameraDeviceSession::flush() { return Status::OK; } Return<void> ExternalCameraDeviceSession::close() { Return<void> ExternalCameraDeviceSession::close(bool callerIsDtor) { Mutex::Autolock _il(mInterfaceLock); bool closed = isClosed(); if (!closed) { mOutputThread->flush(); mOutputThread->requestExit(); mOutputThread->join(); if (callerIsDtor) { closeOutputThreadImpl(); } else { closeOutputThread(); } Mutex::Autolock _l(mLock); // free all buffers { Mutex::Autolock _l(mCbsLock); for(auto pair : mStreamMap) { cleanupBuffersLocked(/*Stream ID*/pair.first); } } v4l2StreamOffLocked(); ALOGV("%s: closing V4L2 camera FD %d", __FUNCTION__, mV4l2Fd.get()); mV4l2Fd.reset(); Loading @@ -463,10 +499,61 @@ Return<void> ExternalCameraDeviceSession::close() { return Void(); } Status ExternalCameraDeviceSession::importRequest( Status ExternalCameraDeviceSession::importRequestLocked( const CaptureRequest& request, hidl_vec<buffer_handle_t*>& allBufPtrs, hidl_vec<int>& allFences) { return importRequestLockedImpl(request, allBufPtrs, allFences); } Status ExternalCameraDeviceSession::importBuffer(int32_t streamId, uint64_t bufId, buffer_handle_t buf, /*out*/buffer_handle_t** outBufPtr, bool allowEmptyBuf) { Mutex::Autolock _l(mCbsLock); return importBufferLocked(streamId, bufId, buf, outBufPtr, allowEmptyBuf); } Status ExternalCameraDeviceSession::importBufferLocked(int32_t streamId, uint64_t bufId, buffer_handle_t buf, /*out*/buffer_handle_t** outBufPtr, bool allowEmptyBuf) { if (buf == nullptr && bufId == BUFFER_ID_NO_BUFFER) { if (allowEmptyBuf) { *outBufPtr = &sEmptyBuffer; return Status::OK; } else { ALOGE("%s: bufferId %" PRIu64 " has null buffer handle!", __FUNCTION__, bufId); return Status::ILLEGAL_ARGUMENT; } } CirculatingBuffers& cbs = mCirculatingBuffers[streamId]; if (cbs.count(bufId) == 0) { if (buf == nullptr) { ALOGE("%s: bufferId %" PRIu64 " has null buffer handle!", __FUNCTION__, bufId); return Status::ILLEGAL_ARGUMENT; } // Register a newly seen buffer buffer_handle_t importedBuf = buf; sHandleImporter.importBuffer(importedBuf); if (importedBuf == nullptr) { ALOGE("%s: output buffer for stream %d is invalid!", __FUNCTION__, streamId); return Status::INTERNAL_ERROR; } else { cbs[bufId] = importedBuf; } } *outBufPtr = &cbs[bufId]; return Status::OK; } Status ExternalCameraDeviceSession::importRequestLockedImpl( const CaptureRequest& request, hidl_vec<buffer_handle_t*>& allBufPtrs, hidl_vec<int>& allFences, bool allowEmptyBuf) { size_t numOutputBufs = request.outputBuffers.size(); size_t numBufs = numOutputBufs; // Validate all I/O buffers Loading @@ -485,26 +572,17 @@ Status ExternalCameraDeviceSession::importRequest( streamIds[i] = request.outputBuffers[i].streamId; } { Mutex::Autolock _l(mCbsLock); for (size_t i = 0; i < numBufs; i++) { buffer_handle_t buf = allBufs[i]; uint64_t bufId = allBufIds[i]; CirculatingBuffers& cbs = mCirculatingBuffers[streamIds[i]]; if (cbs.count(bufId) == 0) { if (buf == nullptr) { ALOGE("%s: bufferId %" PRIu64 " has null buffer handle!", __FUNCTION__, bufId); return Status::ILLEGAL_ARGUMENT; } // Register a newly seen buffer buffer_handle_t importedBuf = buf; sHandleImporter.importBuffer(importedBuf); if (importedBuf == nullptr) { ALOGE("%s: output buffer %zu is invalid!", __FUNCTION__, i); return Status::INTERNAL_ERROR; } else { cbs[bufId] = importedBuf; Status st = importBufferLocked( streamIds[i], allBufIds[i], allBufs[i], &allBufPtrs[i], allowEmptyBuf); if (st != Status::OK) { // Detailed error logs printed in importBuffer return st; } } allBufPtrs[i] = &cbs[bufId]; } // All buffers are imported. Now validate output buffer acquire fences Loading Loading @@ -652,7 +730,7 @@ Status ExternalCameraDeviceSession::processOneCaptureRequest(const CaptureReques } } status = importRequest(request, allBufPtrs, allFences); status = importRequestLocked(request, allBufPtrs, allFences); if (status != Status::OK) { return status; } Loading Loading @@ -775,9 +853,11 @@ Status ExternalCameraDeviceSession::processCaptureResult(std::shared_ptr<HalRequ result.outputBuffers[i].bufferId = req->buffers[i].bufferId; if (req->buffers[i].fenceTimeout) { result.outputBuffers[i].status = BufferStatus::ERROR; if (req->buffers[i].acquireFence > 0) { native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0); handle->data[0] = req->buffers[i].acquireFence; result.outputBuffers[i].releaseFence.setTo(handle, /*shouldOwn*/false); } notifyError(req->frameNumber, req->buffers[i].streamId, ErrorCode::ERROR_BUFFER); } else { result.outputBuffers[i].status = BufferStatus::OK; Loading Loading @@ -1747,6 +1827,12 @@ bool ExternalCameraDeviceSession::OutputThread::threadLoop() { (req->frameIn->mFourcc >> 24) & 0xFF); } int res = requestBufferStart(req->buffers); if (res != 0) { ALOGE("%s: send BufferRequest failed! res %d", __FUNCTION__, res); return onDeviceError("%s: failed to send buffer request!", __FUNCTION__); } std::unique_lock<std::mutex> lk(mBufferLock); // Convert input V4L2 frame to YU12 of the same size // TODO: see if we can save some computation by converting to YV12 here Loading @@ -1759,7 +1845,7 @@ bool ExternalCameraDeviceSession::OutputThread::threadLoop() { // TODO: in some special case maybe we can decode jpg directly to gralloc output? ATRACE_BEGIN("MJPGtoI420"); int res = libyuv::MJPGToI420( res = libyuv::MJPGToI420( inData, inDataSize, static_cast<uint8_t*>(mYu12FrameLayout.y), mYu12FrameLayout.yStride, Loading @@ -1783,10 +1869,23 @@ bool ExternalCameraDeviceSession::OutputThread::threadLoop() { return true; } ATRACE_BEGIN("Wait for BufferRequest done"); res = waitForBufferRequestDone(&req->buffers); ATRACE_END(); if (res != 0) { ALOGE("%s: wait for BufferRequest done failed! res %d", __FUNCTION__, res); lk.unlock(); return onDeviceError("%s: failed to process buffer request error!", __FUNCTION__); } ALOGV("%s processing new request", __FUNCTION__); const int kSyncWaitTimeoutMs = 500; for (auto& halBuf : req->buffers) { if (halBuf.acquireFence != -1) { if (*(halBuf.bufPtr) == nullptr) { ALOGW("%s: buffer for stream %d missing", __FUNCTION__, halBuf.streamId); halBuf.fenceTimeout = true; } else if (halBuf.acquireFence != -1) { int ret = sync_wait(halBuf.acquireFence, kSyncWaitTimeoutMs); if (ret) { halBuf.fenceTimeout = true; Loading Loading @@ -2045,7 +2144,7 @@ void ExternalCameraDeviceSession::cleanupBuffersLocked(int id) { } void ExternalCameraDeviceSession::updateBufferCaches(const hidl_vec<BufferCache>& cachesToRemove) { Mutex::Autolock _l(mLock); Mutex::Autolock _l(mCbsLock); for (auto& cache : cachesToRemove) { auto cbsIt = mCirculatingBuffers.find(cache.streamId); if (cbsIt == mCirculatingBuffers.end()) { Loading Loading @@ -2499,6 +2598,8 @@ Status ExternalCameraDeviceSession::configureStreams( } Mutex::Autolock _l(mLock); { Mutex::Autolock _l(mCbsLock); // Add new streams for (const auto& stream : config.streams) { if (mStreamMap.count(stream.id) == 0) { Loading @@ -2525,6 +2626,7 @@ Status ExternalCameraDeviceSession::configureStreams( ++it; } } } // Now select a V4L2 format to produce all output streams float desiredAr = (mCroppingType == VERTICAL) ? kMaxAspectRatio : kMinAspectRatio; Loading
camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h +40 −5 Original line number Diff line number Diff line Loading @@ -97,7 +97,7 @@ struct ExternalCameraDeviceSession : public virtual RefBase { // Call by CameraDevice to dump active device states void dumpState(const native_handle_t*); // Caller must use this method to check if CameraDeviceSession ctor failed bool isInitFailed() { return mInitFail; } bool isInitFailed(); bool isClosed(); // Retrieve the HIDL interface, split into its own class to avoid inheritance issues when Loading Loading @@ -134,7 +134,7 @@ protected: ICameraDeviceSession::processCaptureRequest_cb); Return<Status> flush(); Return<void> close(); Return<void> close(bool callerIsDtor = false); Return<void> configureStreams_3_3( const V3_2::StreamConfiguration&, Loading Loading @@ -170,10 +170,17 @@ protected: std::vector<HalStreamBuffer> buffers; }; static const uint64_t BUFFER_ID_NO_BUFFER = 0; Status constructDefaultRequestSettingsRaw(RequestTemplate type, V3_2::CameraMetadata *outMetadata); bool initialize(); // To init/close different version of output thread virtual void initOutputThread(); virtual void closeOutputThread(); void closeOutputThreadImpl(); Status initStatus() const; status_t initDefaultRequests(); status_t fillCaptureResult(common::V1_0::helper::CameraMetadata& md, nsecs_t timestamp); Loading @@ -195,10 +202,28 @@ protected: bool isSupported(const Stream&); // Validate and import request's output buffers and acquire fence Status importRequest( virtual Status importRequestLocked( const CaptureRequest& request, hidl_vec<buffer_handle_t*>& allBufPtrs, hidl_vec<int>& allFences); Status importRequestLockedImpl( 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); Status importBufferLocked(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); Loading @@ -224,7 +249,7 @@ protected: class OutputThread : public android::Thread { public: OutputThread(wp<ExternalCameraDeviceSession> parent, CroppingType); ~OutputThread(); virtual ~OutputThread(); Status allocateIntermediateBuffers( const Size& v4lSize, const Size& thumbSize, Loading @@ -236,7 +261,14 @@ protected: virtual bool threadLoop() override; void setExifMakeModel(const std::string& make, const std::string& model); private: protected: // Methods to request output buffer in parallel // No-op for device@3.4. Implemented in device@3.5 virtual int requestBufferStart(const std::vector<HalStreamBuffer>&) { return 0; } virtual int waitForBufferRequestDone( /*out*/std::vector<HalStreamBuffer>*) { return 0; } static const uint32_t FLEX_YUV_GENERIC = static_cast<uint32_t>('F') | static_cast<uint32_t>('L') << 8 | static_cast<uint32_t>('E') << 16 | static_cast<uint32_t>('X') << 24; Loading Loading @@ -319,6 +351,7 @@ protected: // - init failed // - camera disconnected bool mClosed = false; bool mInitialized = false; bool mInitFail = false; bool mFirstRequest = false; common::V1_0::helper::CameraMetadata mLatestReqSetting; Loading Loading @@ -351,6 +384,8 @@ protected: typedef std::unordered_map<uint64_t, buffer_handle_t> CirculatingBuffers; // Stream ID -> circulating buffers map std::map<int, CirculatingBuffers> mCirculatingBuffers; // Protect mCirculatingBuffers, must not lock mLock after acquiring this lock mutable Mutex mCbsLock; std::mutex mAfTriggerLock; // protect mAfTrigger bool mAfTrigger = false; Loading
camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDevice_3_4.h +110 −8 File changed.Preview size limit exceeded, changes collapsed. Show changes
camera/device/3.5/default/Android.bp +48 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,12 @@ cc_library_headers { export_include_dirs: ["include/device_v3_5_impl"] } cc_library_headers { name: "camera.device@3.5-external-impl_headers", vendor: true, export_include_dirs: ["include/ext_device_v3_5_impl"] } cc_library_shared { name: "camera.device@3.5-impl", defaults: ["hidl_defaults"], Loading Loading @@ -52,3 +58,45 @@ cc_library_shared { ], local_include_dirs: ["include/device_v3_5_impl"], } cc_library_shared { name: "camera.device@3.5-external-impl", defaults: ["hidl_defaults"], proprietary: true, vendor: true, srcs: [ "ExternalCameraDevice.cpp", "ExternalCameraDeviceSession.cpp", ], shared_libs: [ "libhidlbase", "libhidltransport", "libutils", "libcutils", "camera.device@3.2-impl", "camera.device@3.3-impl", "camera.device@3.4-external-impl", "android.hardware.camera.device@3.2", "android.hardware.camera.device@3.3", "android.hardware.camera.device@3.4", "android.hardware.camera.device@3.5", "android.hardware.camera.provider@2.4", "android.hardware.graphics.mapper@2.0", "liblog", "libhardware", "libcamera_metadata", "libfmq", "libsync", "libyuv", "libjpeg", "libexif", "libtinyxml2" ], static_libs: [ "android.hardware.camera.common@1.0-helper", ], local_include_dirs: ["include/ext_device_v3_5_impl"], export_shared_lib_headers: [ "libfmq", ], }