mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 11:36:00 +00:00
Camera: Add external camera provider
Bug: 64874137 63873538 Change-Id: I4309874a7dedd3dd71d4bd0c2004d460421db679
This commit is contained in:
@@ -134,6 +134,65 @@ void HandleImporter::closeFence(int fd) const {
|
||||
}
|
||||
}
|
||||
|
||||
YCbCrLayout HandleImporter::lockYCbCr(
|
||||
buffer_handle_t& buf, uint64_t cpuUsage,
|
||||
const IMapper::Rect& accessRegion) {
|
||||
Mutex::Autolock lock(mLock);
|
||||
YCbCrLayout layout = {};
|
||||
|
||||
if (!mInitialized) {
|
||||
initializeLocked();
|
||||
}
|
||||
|
||||
if (mMapper == nullptr) {
|
||||
ALOGE("%s: mMapper is null!", __FUNCTION__);
|
||||
return layout;
|
||||
}
|
||||
|
||||
hidl_handle acquireFenceHandle;
|
||||
auto buffer = const_cast<native_handle_t*>(buf);
|
||||
mMapper->lockYCbCr(buffer, cpuUsage, accessRegion, acquireFenceHandle,
|
||||
[&](const auto& tmpError, const auto& tmpLayout) {
|
||||
if (tmpError == MapperError::NONE) {
|
||||
layout = tmpLayout;
|
||||
} else {
|
||||
ALOGE("%s: failed to lockYCbCr error %d!", __FUNCTION__, tmpError);
|
||||
}
|
||||
});
|
||||
|
||||
ALOGV("%s: layout y %p cb %p cr %p y_str %d c_str %d c_step %d",
|
||||
__FUNCTION__, layout.y, layout.cb, layout.cr,
|
||||
layout.yStride, layout.cStride, layout.chromaStep);
|
||||
return layout;
|
||||
}
|
||||
|
||||
int HandleImporter::unlock(buffer_handle_t& buf) {
|
||||
int releaseFence = -1;
|
||||
auto buffer = const_cast<native_handle_t*>(buf);
|
||||
mMapper->unlock(
|
||||
buffer, [&](const auto& tmpError, const auto& tmpReleaseFence) {
|
||||
if (tmpError == MapperError::NONE) {
|
||||
auto fenceHandle = tmpReleaseFence.getNativeHandle();
|
||||
if (fenceHandle) {
|
||||
if (fenceHandle->numInts != 0 || fenceHandle->numFds != 1) {
|
||||
ALOGE("%s: bad release fence numInts %d numFds %d",
|
||||
__FUNCTION__, fenceHandle->numInts, fenceHandle->numFds);
|
||||
return;
|
||||
}
|
||||
releaseFence = dup(fenceHandle->data[0]);
|
||||
if (releaseFence <= 0) {
|
||||
ALOGE("%s: bad release fence FD %d",
|
||||
__FUNCTION__, releaseFence);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ALOGE("%s: failed to unlock error %d!", __FUNCTION__, tmpError);
|
||||
}
|
||||
});
|
||||
|
||||
return releaseFence;
|
||||
}
|
||||
|
||||
} // namespace helper
|
||||
} // namespace V1_0
|
||||
} // namespace common
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <cutils/native_handle.h>
|
||||
|
||||
using android::hardware::graphics::mapper::V2_0::IMapper;
|
||||
using android::hardware::graphics::mapper::V2_0::YCbCrLayout;
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
@@ -43,6 +44,12 @@ public:
|
||||
bool importFence(const native_handle_t* handle, int& fd) const;
|
||||
void closeFence(int fd) const;
|
||||
|
||||
// Assume caller has done waiting for acquire fences
|
||||
YCbCrLayout lockYCbCr(buffer_handle_t& buf, uint64_t cpuUsage,
|
||||
const IMapper::Rect& accessRegion);
|
||||
|
||||
int unlock(buffer_handle_t& buf); // returns release fence
|
||||
|
||||
private:
|
||||
void initializeLocked();
|
||||
void cleanup();
|
||||
@@ -60,4 +67,4 @@ private:
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
#endif // CAMERA_COMMON_1_0_HANDLEIMPORTED_H
|
||||
#endif // CAMERA_COMMON_1_0_HANDLEIMPORTED_H
|
||||
|
||||
@@ -17,7 +17,13 @@
|
||||
cc_library_headers {
|
||||
name: "camera.device@3.4-impl_headers",
|
||||
vendor: true,
|
||||
export_include_dirs: ["include/device_v3_4_impl"],
|
||||
export_include_dirs: ["include/device_v3_4_impl"]
|
||||
}
|
||||
|
||||
cc_library_headers {
|
||||
name: "camera.device@3.4-external-impl_headers",
|
||||
vendor: true,
|
||||
export_include_dirs: ["include/ext_device_v3_4_impl"]
|
||||
}
|
||||
|
||||
cc_library_shared {
|
||||
@@ -55,3 +61,40 @@ cc_library_shared {
|
||||
"libfmq",
|
||||
],
|
||||
}
|
||||
|
||||
cc_library_shared {
|
||||
name: "camera.device@3.4-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",
|
||||
"android.hardware.camera.device@3.2",
|
||||
"android.hardware.camera.device@3.3",
|
||||
"android.hardware.camera.device@3.4",
|
||||
"android.hardware.camera.provider@2.4",
|
||||
"android.hardware.graphics.mapper@2.0",
|
||||
"liblog",
|
||||
"libhardware",
|
||||
"libcamera_metadata",
|
||||
"libfmq",
|
||||
"libsync",
|
||||
"libyuv",
|
||||
],
|
||||
static_libs: [
|
||||
"android.hardware.camera.common@1.0-helper",
|
||||
],
|
||||
local_include_dirs: ["include/ext_device_v3_4_impl"],
|
||||
export_shared_lib_headers: [
|
||||
"libfmq",
|
||||
],
|
||||
}
|
||||
|
||||
793
camera/device/3.4/default/ExternalCameraDevice.cpp
Normal file
793
camera/device/3.4/default/ExternalCameraDevice.cpp
Normal file
@@ -0,0 +1,793 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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 "ExtCamDev@3.4"
|
||||
#define LOG_NDEBUG 0
|
||||
#include <log/log.h>
|
||||
|
||||
#include <array>
|
||||
#include <linux/videodev2.h>
|
||||
#include "android-base/macros.h"
|
||||
#include "CameraMetadata.h"
|
||||
#include "../../3.2/default/include/convert.h"
|
||||
#include "ExternalCameraDevice_3_4.h"
|
||||
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace camera {
|
||||
namespace device {
|
||||
namespace V3_4 {
|
||||
namespace implementation {
|
||||
|
||||
namespace {
|
||||
// Only support MJPEG for now as it seems to be the one supports higher fps
|
||||
// Other formats to consider in the future:
|
||||
// * V4L2_PIX_FMT_YVU420 (== YV12)
|
||||
// * V4L2_PIX_FMT_YVYU (YVYU: can be converted to YV12 or other YUV420_888 formats)
|
||||
const std::array<uint32_t, /*size*/1> kSupportedFourCCs {{
|
||||
V4L2_PIX_FMT_MJPEG
|
||||
}}; // double braces required in C++11
|
||||
|
||||
// TODO: b/72261897
|
||||
// Define max size/fps this Android device can advertise (and streaming at reasonable speed)
|
||||
// Also make sure that can be done without editing source code
|
||||
|
||||
// TODO: b/72261675: make it dynamic since this affects memory usage
|
||||
const int kMaxJpegSize = {13 * 1024 * 1024}; // 13MB
|
||||
} // anonymous namespace
|
||||
|
||||
ExternalCameraDevice::ExternalCameraDevice(const std::string& cameraId) :
|
||||
mCameraId(cameraId) {
|
||||
status_t ret = initCameraCharacteristics();
|
||||
if (ret != OK) {
|
||||
ALOGE("%s: init camera characteristics failed: errorno %d", __FUNCTION__, ret);
|
||||
mInitFailed = true;
|
||||
}
|
||||
}
|
||||
|
||||
ExternalCameraDevice::~ExternalCameraDevice() {}
|
||||
|
||||
bool ExternalCameraDevice::isInitFailed() {
|
||||
return mInitFailed;
|
||||
}
|
||||
|
||||
Return<void> ExternalCameraDevice::getResourceCost(getResourceCost_cb _hidl_cb) {
|
||||
CameraResourceCost resCost;
|
||||
resCost.resourceCost = 100;
|
||||
_hidl_cb(Status::OK, resCost);
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> ExternalCameraDevice::getCameraCharacteristics(
|
||||
getCameraCharacteristics_cb _hidl_cb) {
|
||||
Mutex::Autolock _l(mLock);
|
||||
V3_2::CameraMetadata hidlChars;
|
||||
|
||||
if (isInitFailed()) {
|
||||
_hidl_cb(Status::INTERNAL_ERROR, hidlChars);
|
||||
return Void();
|
||||
}
|
||||
|
||||
const camera_metadata_t* rawMetadata = mCameraCharacteristics.getAndLock();
|
||||
V3_2::implementation::convertToHidl(rawMetadata, &hidlChars);
|
||||
_hidl_cb(Status::OK, hidlChars);
|
||||
mCameraCharacteristics.unlock(rawMetadata);
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<Status> ExternalCameraDevice::setTorchMode(TorchMode) {
|
||||
return Status::METHOD_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
Return<void> ExternalCameraDevice::open(
|
||||
const sp<ICameraDeviceCallback>& callback, open_cb _hidl_cb) {
|
||||
Status status = Status::OK;
|
||||
sp<ExternalCameraDeviceSession> session = nullptr;
|
||||
|
||||
if (callback == nullptr) {
|
||||
ALOGE("%s: cannot open camera %s. callback is null!",
|
||||
__FUNCTION__, mCameraId.c_str());
|
||||
_hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
|
||||
return Void();
|
||||
}
|
||||
|
||||
if (isInitFailed()) {
|
||||
ALOGE("%s: cannot open camera %s. camera init failed!",
|
||||
__FUNCTION__, mCameraId.c_str());
|
||||
_hidl_cb(Status::INTERNAL_ERROR, nullptr);
|
||||
return Void();
|
||||
}
|
||||
|
||||
mLock.lock();
|
||||
|
||||
ALOGV("%s: Initializing device for camera %s", __FUNCTION__, mCameraId.c_str());
|
||||
session = mSession.promote();
|
||||
if (session != nullptr && !session->isClosed()) {
|
||||
ALOGE("%s: cannot open an already opened camera!", __FUNCTION__);
|
||||
mLock.unlock();
|
||||
_hidl_cb(Status::CAMERA_IN_USE, nullptr);
|
||||
return Void();
|
||||
}
|
||||
|
||||
unique_fd fd(::open(mCameraId.c_str(), O_RDWR));
|
||||
if (fd.get() < 0) {
|
||||
ALOGE("%s: v4l2 device open %s failed: %s",
|
||||
__FUNCTION__, mCameraId.c_str(), strerror(errno));
|
||||
mLock.unlock();
|
||||
_hidl_cb(Status::INTERNAL_ERROR, nullptr);
|
||||
return Void();
|
||||
}
|
||||
|
||||
session = new ExternalCameraDeviceSession(
|
||||
callback, mSupportedFormats, mCameraCharacteristics, std::move(fd));
|
||||
if (session == nullptr) {
|
||||
ALOGE("%s: camera device session allocation failed", __FUNCTION__);
|
||||
mLock.unlock();
|
||||
_hidl_cb(Status::INTERNAL_ERROR, nullptr);
|
||||
return Void();
|
||||
}
|
||||
if (session->isInitFailed()) {
|
||||
ALOGE("%s: camera device session init failed", __FUNCTION__);
|
||||
session = nullptr;
|
||||
mLock.unlock();
|
||||
_hidl_cb(Status::INTERNAL_ERROR, nullptr);
|
||||
return Void();
|
||||
}
|
||||
mSession = session;
|
||||
|
||||
mLock.unlock();
|
||||
|
||||
_hidl_cb(status, session->getInterface());
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> ExternalCameraDevice::dumpState(const ::android::hardware::hidl_handle& handle) {
|
||||
Mutex::Autolock _l(mLock);
|
||||
if (handle.getNativeHandle() == nullptr) {
|
||||
ALOGE("%s: handle must not be null", __FUNCTION__);
|
||||
return Void();
|
||||
}
|
||||
if (handle->numFds != 1 || handle->numInts != 0) {
|
||||
ALOGE("%s: handle must contain 1 FD and 0 integers! Got %d FDs and %d ints",
|
||||
__FUNCTION__, handle->numFds, handle->numInts);
|
||||
return Void();
|
||||
}
|
||||
int fd = handle->data[0];
|
||||
if (mSession == nullptr) {
|
||||
dprintf(fd, "No active camera device session instance\n");
|
||||
return Void();
|
||||
}
|
||||
auto session = mSession.promote();
|
||||
if (session == nullptr) {
|
||||
dprintf(fd, "No active camera device session instance\n");
|
||||
return Void();
|
||||
}
|
||||
// Call into active session to dump states
|
||||
session->dumpState(handle);
|
||||
return Void();
|
||||
}
|
||||
|
||||
|
||||
status_t ExternalCameraDevice::initCameraCharacteristics() {
|
||||
if (mCameraCharacteristics.isEmpty()) {
|
||||
// init camera characteristics
|
||||
unique_fd fd(::open(mCameraId.c_str(), O_RDWR));
|
||||
if (fd.get() < 0) {
|
||||
ALOGE("%s: v4l2 device open %s failed", __FUNCTION__, mCameraId.c_str());
|
||||
return DEAD_OBJECT;
|
||||
}
|
||||
|
||||
status_t ret;
|
||||
ret = initDefaultCharsKeys(&mCameraCharacteristics);
|
||||
if (ret != OK) {
|
||||
ALOGE("%s: init default characteristics key failed: errorno %d", __FUNCTION__, ret);
|
||||
mCameraCharacteristics.clear();
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = initCameraControlsCharsKeys(fd.get(), &mCameraCharacteristics);
|
||||
if (ret != OK) {
|
||||
ALOGE("%s: init camera control characteristics key failed: errorno %d", __FUNCTION__, ret);
|
||||
mCameraCharacteristics.clear();
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = initOutputCharsKeys(fd.get(), &mCameraCharacteristics);
|
||||
if (ret != OK) {
|
||||
ALOGE("%s: init output characteristics key failed: errorno %d", __FUNCTION__, ret);
|
||||
mCameraCharacteristics.clear();
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
|
||||
#define UPDATE(tag, data, size) \
|
||||
do { \
|
||||
if (metadata->update((tag), (data), (size))) { \
|
||||
ALOGE("Update " #tag " failed!"); \
|
||||
return -EINVAL; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
status_t ExternalCameraDevice::initDefaultCharsKeys(
|
||||
::android::hardware::camera::common::V1_0::helper::CameraMetadata* metadata) {
|
||||
// TODO: changed to HARDWARELEVEL_EXTERNAL later
|
||||
const uint8_t hardware_level = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED;
|
||||
UPDATE(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL, &hardware_level, 1);
|
||||
|
||||
// android.colorCorrection
|
||||
const uint8_t availableAberrationModes[] = {
|
||||
ANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF};
|
||||
UPDATE(ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
|
||||
availableAberrationModes, ARRAY_SIZE(availableAberrationModes));
|
||||
|
||||
// android.control
|
||||
const uint8_t antibandingMode =
|
||||
ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO;
|
||||
UPDATE(ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,
|
||||
&antibandingMode, 1);
|
||||
|
||||
const int32_t controlMaxRegions[] = {/*AE*/ 0, /*AWB*/ 0, /*AF*/ 0};
|
||||
UPDATE(ANDROID_CONTROL_MAX_REGIONS, controlMaxRegions,
|
||||
ARRAY_SIZE(controlMaxRegions));
|
||||
|
||||
const uint8_t videoStabilizationMode =
|
||||
ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF;
|
||||
UPDATE(ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,
|
||||
&videoStabilizationMode, 1);
|
||||
|
||||
const uint8_t awbAvailableMode = ANDROID_CONTROL_AWB_MODE_AUTO;
|
||||
UPDATE(ANDROID_CONTROL_AWB_AVAILABLE_MODES, &awbAvailableMode, 1);
|
||||
|
||||
const uint8_t aeAvailableMode = ANDROID_CONTROL_AE_MODE_ON;
|
||||
UPDATE(ANDROID_CONTROL_AE_AVAILABLE_MODES, &aeAvailableMode, 1);
|
||||
|
||||
const uint8_t availableFffect = ANDROID_CONTROL_EFFECT_MODE_OFF;
|
||||
UPDATE(ANDROID_CONTROL_AVAILABLE_EFFECTS, &availableFffect, 1);
|
||||
|
||||
const uint8_t controlAvailableModes[] = {ANDROID_CONTROL_MODE_OFF,
|
||||
ANDROID_CONTROL_MODE_AUTO};
|
||||
UPDATE(ANDROID_CONTROL_AVAILABLE_MODES, controlAvailableModes,
|
||||
ARRAY_SIZE(controlAvailableModes));
|
||||
|
||||
// android.edge
|
||||
const uint8_t edgeMode = ANDROID_EDGE_MODE_OFF;
|
||||
UPDATE(ANDROID_EDGE_AVAILABLE_EDGE_MODES, &edgeMode, 1);
|
||||
|
||||
// android.flash
|
||||
const uint8_t flashInfo = ANDROID_FLASH_INFO_AVAILABLE_FALSE;
|
||||
UPDATE(ANDROID_FLASH_INFO_AVAILABLE, &flashInfo, 1);
|
||||
|
||||
// android.hotPixel
|
||||
const uint8_t hotPixelMode = ANDROID_HOT_PIXEL_MODE_OFF;
|
||||
UPDATE(ANDROID_HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES, &hotPixelMode, 1);
|
||||
|
||||
// android.jpeg
|
||||
// TODO: b/72261675 See if we can provide thumbnail size for all jpeg aspect ratios
|
||||
const int32_t jpegAvailableThumbnailSizes[] = {0, 0, 240, 180};
|
||||
UPDATE(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES, jpegAvailableThumbnailSizes,
|
||||
ARRAY_SIZE(jpegAvailableThumbnailSizes));
|
||||
|
||||
const int32_t jpegMaxSize = kMaxJpegSize;
|
||||
UPDATE(ANDROID_JPEG_MAX_SIZE, &jpegMaxSize, 1);
|
||||
|
||||
const uint8_t jpegQuality = 90;
|
||||
UPDATE(ANDROID_JPEG_QUALITY, &jpegQuality, 1);
|
||||
UPDATE(ANDROID_JPEG_THUMBNAIL_QUALITY, &jpegQuality, 1);
|
||||
|
||||
const int32_t jpegOrientation = 0;
|
||||
UPDATE(ANDROID_JPEG_ORIENTATION, &jpegOrientation, 1);
|
||||
|
||||
// android.lens
|
||||
const uint8_t focusDistanceCalibration =
|
||||
ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION_UNCALIBRATED;
|
||||
UPDATE(ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION, &focusDistanceCalibration, 1);
|
||||
|
||||
const uint8_t opticalStabilizationMode =
|
||||
ANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF;
|
||||
UPDATE(ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,
|
||||
&opticalStabilizationMode, 1);
|
||||
|
||||
const uint8_t facing = ANDROID_LENS_FACING_EXTERNAL;
|
||||
UPDATE(ANDROID_LENS_FACING, &facing, 1);
|
||||
|
||||
// android.noiseReduction
|
||||
const uint8_t noiseReductionMode = ANDROID_NOISE_REDUCTION_MODE_OFF;
|
||||
UPDATE(ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,
|
||||
&noiseReductionMode, 1);
|
||||
UPDATE(ANDROID_NOISE_REDUCTION_MODE, &noiseReductionMode, 1);
|
||||
|
||||
// android.request
|
||||
const uint8_t availableCapabilities[] = {
|
||||
ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE};
|
||||
UPDATE(ANDROID_REQUEST_AVAILABLE_CAPABILITIES, availableCapabilities,
|
||||
ARRAY_SIZE(availableCapabilities));
|
||||
|
||||
const int32_t partialResultCount = 1;
|
||||
UPDATE(ANDROID_REQUEST_PARTIAL_RESULT_COUNT, &partialResultCount, 1);
|
||||
|
||||
// This means pipeline latency of X frame intervals. The maximum number is 4.
|
||||
const uint8_t requestPipelineMaxDepth = 4;
|
||||
UPDATE(ANDROID_REQUEST_PIPELINE_MAX_DEPTH, &requestPipelineMaxDepth, 1);
|
||||
UPDATE(ANDROID_REQUEST_PIPELINE_DEPTH, &requestPipelineMaxDepth, 1);
|
||||
|
||||
// Three numbers represent the maximum numbers of different types of output
|
||||
// streams simultaneously. The types are raw sensor, processed (but not
|
||||
// stalling), and processed (but stalling). For usb limited mode, raw sensor
|
||||
// is not supported. Stalling stream is JPEG. Non-stalling streams are
|
||||
// YUV_420_888 or YV12.
|
||||
const int32_t requestMaxNumOutputStreams[] = {
|
||||
/*RAW*/0,
|
||||
/*Processed*/ExternalCameraDeviceSession::kMaxProcessedStream,
|
||||
/*Stall*/ExternalCameraDeviceSession::kMaxStallStream};
|
||||
UPDATE(ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS, requestMaxNumOutputStreams,
|
||||
ARRAY_SIZE(requestMaxNumOutputStreams));
|
||||
|
||||
// Limited mode doesn't support reprocessing.
|
||||
const int32_t requestMaxNumInputStreams = 0;
|
||||
UPDATE(ANDROID_REQUEST_MAX_NUM_INPUT_STREAMS, &requestMaxNumInputStreams,
|
||||
1);
|
||||
|
||||
// android.scaler
|
||||
// TODO: b/72263447 V4L2_CID_ZOOM_*
|
||||
const float scalerAvailableMaxDigitalZoom[] = {1};
|
||||
UPDATE(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
|
||||
scalerAvailableMaxDigitalZoom,
|
||||
ARRAY_SIZE(scalerAvailableMaxDigitalZoom));
|
||||
|
||||
const uint8_t croppingType = ANDROID_SCALER_CROPPING_TYPE_CENTER_ONLY;
|
||||
UPDATE(ANDROID_SCALER_CROPPING_TYPE, &croppingType, 1);
|
||||
|
||||
const int32_t testPatternModes[] = {
|
||||
ANDROID_SENSOR_TEST_PATTERN_MODE_OFF};
|
||||
UPDATE(ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES, testPatternModes,
|
||||
ARRAY_SIZE(testPatternModes));
|
||||
UPDATE(ANDROID_SENSOR_TEST_PATTERN_MODE, &testPatternModes[0], 1);
|
||||
|
||||
const uint8_t timestampSource = ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN;
|
||||
UPDATE(ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE, ×tampSource, 1);
|
||||
|
||||
// Orientation probably isn't useful for external facing camera?
|
||||
const int32_t orientation = 0;
|
||||
UPDATE(ANDROID_SENSOR_ORIENTATION, &orientation, 1);
|
||||
|
||||
// android.shading
|
||||
const uint8_t availabeMode = ANDROID_SHADING_MODE_OFF;
|
||||
UPDATE(ANDROID_SHADING_AVAILABLE_MODES, &availabeMode, 1);
|
||||
|
||||
// android.statistics
|
||||
const uint8_t faceDetectMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;
|
||||
UPDATE(ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES, &faceDetectMode,
|
||||
1);
|
||||
|
||||
const int32_t maxFaceCount = 0;
|
||||
UPDATE(ANDROID_STATISTICS_INFO_MAX_FACE_COUNT, &maxFaceCount, 1);
|
||||
|
||||
const uint8_t availableHotpixelMode =
|
||||
ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE_OFF;
|
||||
UPDATE(ANDROID_STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES,
|
||||
&availableHotpixelMode, 1);
|
||||
|
||||
const uint8_t lensShadingMapMode =
|
||||
ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF;
|
||||
UPDATE(ANDROID_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES,
|
||||
&lensShadingMapMode, 1);
|
||||
|
||||
// android.sync
|
||||
const int32_t maxLatency = ANDROID_SYNC_MAX_LATENCY_UNKNOWN;
|
||||
UPDATE(ANDROID_SYNC_MAX_LATENCY, &maxLatency, 1);
|
||||
|
||||
/* Other sensor/RAW realted keys:
|
||||
* android.sensor.info.colorFilterArrangement -> no need if we don't do RAW
|
||||
* android.sensor.info.physicalSize -> not available
|
||||
* android.sensor.info.whiteLevel -> not available/not needed
|
||||
* android.sensor.info.lensShadingApplied -> not needed
|
||||
* android.sensor.info.preCorrectionActiveArraySize -> not available/not needed
|
||||
* android.sensor.blackLevelPattern -> not available/not needed
|
||||
*/
|
||||
|
||||
const int32_t availableRequestKeys[] = {
|
||||
ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
|
||||
ANDROID_CONTROL_AE_ANTIBANDING_MODE,
|
||||
ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
|
||||
ANDROID_CONTROL_AE_LOCK,
|
||||
ANDROID_CONTROL_AE_MODE,
|
||||
ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
|
||||
ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
|
||||
ANDROID_CONTROL_AF_MODE,
|
||||
ANDROID_CONTROL_AF_TRIGGER,
|
||||
ANDROID_CONTROL_AWB_LOCK,
|
||||
ANDROID_CONTROL_AWB_MODE,
|
||||
ANDROID_CONTROL_CAPTURE_INTENT,
|
||||
ANDROID_CONTROL_EFFECT_MODE,
|
||||
ANDROID_CONTROL_MODE,
|
||||
ANDROID_CONTROL_SCENE_MODE,
|
||||
ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
|
||||
ANDROID_FLASH_MODE,
|
||||
ANDROID_JPEG_ORIENTATION,
|
||||
ANDROID_JPEG_QUALITY,
|
||||
ANDROID_JPEG_THUMBNAIL_QUALITY,
|
||||
ANDROID_JPEG_THUMBNAIL_SIZE,
|
||||
ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
|
||||
ANDROID_NOISE_REDUCTION_MODE,
|
||||
ANDROID_SCALER_CROP_REGION,
|
||||
ANDROID_SENSOR_TEST_PATTERN_MODE,
|
||||
ANDROID_STATISTICS_FACE_DETECT_MODE,
|
||||
ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE};
|
||||
UPDATE(ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS, availableRequestKeys,
|
||||
ARRAY_SIZE(availableRequestKeys));
|
||||
|
||||
const int32_t availableResultKeys[] = {
|
||||
ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
|
||||
ANDROID_CONTROL_AE_ANTIBANDING_MODE,
|
||||
ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
|
||||
ANDROID_CONTROL_AE_LOCK,
|
||||
ANDROID_CONTROL_AE_MODE,
|
||||
ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
|
||||
ANDROID_CONTROL_AE_STATE,
|
||||
ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
|
||||
ANDROID_CONTROL_AF_MODE,
|
||||
ANDROID_CONTROL_AF_STATE,
|
||||
ANDROID_CONTROL_AF_TRIGGER,
|
||||
ANDROID_CONTROL_AWB_LOCK,
|
||||
ANDROID_CONTROL_AWB_MODE,
|
||||
ANDROID_CONTROL_AWB_STATE,
|
||||
ANDROID_CONTROL_CAPTURE_INTENT,
|
||||
ANDROID_CONTROL_EFFECT_MODE,
|
||||
ANDROID_CONTROL_MODE,
|
||||
ANDROID_CONTROL_SCENE_MODE,
|
||||
ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
|
||||
ANDROID_FLASH_MODE,
|
||||
ANDROID_FLASH_STATE,
|
||||
ANDROID_JPEG_ORIENTATION,
|
||||
ANDROID_JPEG_QUALITY,
|
||||
ANDROID_JPEG_THUMBNAIL_QUALITY,
|
||||
ANDROID_JPEG_THUMBNAIL_SIZE,
|
||||
ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
|
||||
ANDROID_NOISE_REDUCTION_MODE,
|
||||
ANDROID_REQUEST_PIPELINE_DEPTH,
|
||||
ANDROID_SCALER_CROP_REGION,
|
||||
ANDROID_SENSOR_TIMESTAMP,
|
||||
ANDROID_STATISTICS_FACE_DETECT_MODE,
|
||||
ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE,
|
||||
ANDROID_STATISTICS_LENS_SHADING_MAP_MODE,
|
||||
ANDROID_STATISTICS_SCENE_FLICKER};
|
||||
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));
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
status_t ExternalCameraDevice::initCameraControlsCharsKeys(int,
|
||||
::android::hardware::camera::common::V1_0::helper::CameraMetadata* metadata) {
|
||||
/**
|
||||
* android.sensor.info.sensitivityRange -> V4L2_CID_ISO_SENSITIVITY
|
||||
* android.sensor.info.exposureTimeRange -> V4L2_CID_EXPOSURE_ABSOLUTE
|
||||
* android.sensor.info.maxFrameDuration -> TBD
|
||||
* android.lens.info.minimumFocusDistance -> V4L2_CID_FOCUS_ABSOLUTE
|
||||
* android.lens.info.hyperfocalDistance
|
||||
* android.lens.info.availableFocalLengths -> not available?
|
||||
*/
|
||||
|
||||
// android.control
|
||||
// No AE compensation support for now.
|
||||
// TODO: V4L2_CID_EXPOSURE_BIAS
|
||||
const int32_t controlAeCompensationRange[] = {0, 0};
|
||||
UPDATE(ANDROID_CONTROL_AE_COMPENSATION_RANGE, controlAeCompensationRange,
|
||||
ARRAY_SIZE(controlAeCompensationRange));
|
||||
const camera_metadata_rational_t controlAeCompensationStep[] = {{0, 1}};
|
||||
UPDATE(ANDROID_CONTROL_AE_COMPENSATION_STEP, controlAeCompensationStep,
|
||||
ARRAY_SIZE(controlAeCompensationStep));
|
||||
|
||||
|
||||
// TODO: Check V4L2_CID_AUTO_FOCUS_*.
|
||||
const uint8_t afAvailableModes[] = {ANDROID_CONTROL_AF_MODE_AUTO,
|
||||
ANDROID_CONTROL_AF_MODE_OFF};
|
||||
UPDATE(ANDROID_CONTROL_AF_AVAILABLE_MODES, afAvailableModes,
|
||||
ARRAY_SIZE(afAvailableModes));
|
||||
|
||||
// TODO: V4L2_CID_SCENE_MODE
|
||||
const uint8_t availableSceneMode = ANDROID_CONTROL_SCENE_MODE_DISABLED;
|
||||
UPDATE(ANDROID_CONTROL_AVAILABLE_SCENE_MODES, &availableSceneMode, 1);
|
||||
|
||||
// TODO: V4L2_CID_3A_LOCK
|
||||
const uint8_t aeLockAvailable = ANDROID_CONTROL_AE_LOCK_AVAILABLE_FALSE;
|
||||
UPDATE(ANDROID_CONTROL_AE_LOCK_AVAILABLE, &aeLockAvailable, 1);
|
||||
const uint8_t awbLockAvailable = ANDROID_CONTROL_AWB_LOCK_AVAILABLE_FALSE;
|
||||
UPDATE(ANDROID_CONTROL_AWB_LOCK_AVAILABLE, &awbLockAvailable, 1);
|
||||
|
||||
// TODO: V4L2_CID_ZOOM_*
|
||||
const float scalerAvailableMaxDigitalZoom[] = {1};
|
||||
UPDATE(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
|
||||
scalerAvailableMaxDigitalZoom,
|
||||
ARRAY_SIZE(scalerAvailableMaxDigitalZoom));
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
status_t ExternalCameraDevice::initOutputCharsKeys(int fd,
|
||||
::android::hardware::camera::common::V1_0::helper::CameraMetadata* metadata) {
|
||||
initSupportedFormatsLocked(fd);
|
||||
if (mSupportedFormats.empty()) {
|
||||
ALOGE("%s: Init supported format list failed", __FUNCTION__);
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
std::vector<int32_t> streamConfigurations;
|
||||
std::vector<int64_t> minFrameDurations;
|
||||
std::vector<int64_t> stallDurations;
|
||||
int64_t maxFrameDuration = 0;
|
||||
int32_t maxFps = std::numeric_limits<int32_t>::min();
|
||||
int32_t minFps = std::numeric_limits<int32_t>::max();
|
||||
std::set<int32_t> framerates;
|
||||
|
||||
std::array<int, /*size*/3> halFormats{{
|
||||
HAL_PIXEL_FORMAT_BLOB,
|
||||
HAL_PIXEL_FORMAT_YCbCr_420_888,
|
||||
HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED}};
|
||||
|
||||
for (const auto& supportedFormat : mSupportedFormats) {
|
||||
for (const auto& format : halFormats) {
|
||||
streamConfigurations.push_back(format);
|
||||
streamConfigurations.push_back(supportedFormat.width);
|
||||
streamConfigurations.push_back(supportedFormat.height);
|
||||
streamConfigurations.push_back(
|
||||
ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT);
|
||||
}
|
||||
|
||||
int64_t min_frame_duration = std::numeric_limits<int64_t>::max();
|
||||
for (const auto& frameRate : supportedFormat.frameRates) {
|
||||
int64_t frame_duration = 1000000000LL / frameRate;
|
||||
if (frame_duration < min_frame_duration) {
|
||||
min_frame_duration = frame_duration;
|
||||
}
|
||||
if (frame_duration > maxFrameDuration) {
|
||||
maxFrameDuration = frame_duration;
|
||||
}
|
||||
int32_t frameRateInt = static_cast<int32_t>(frameRate);
|
||||
if (minFps > frameRateInt) {
|
||||
minFps = frameRateInt;
|
||||
}
|
||||
if (maxFps < frameRateInt) {
|
||||
maxFps = frameRateInt;
|
||||
}
|
||||
framerates.insert(frameRateInt);
|
||||
}
|
||||
|
||||
for (const auto& format : halFormats) {
|
||||
minFrameDurations.push_back(format);
|
||||
minFrameDurations.push_back(supportedFormat.width);
|
||||
minFrameDurations.push_back(supportedFormat.height);
|
||||
minFrameDurations.push_back(min_frame_duration);
|
||||
}
|
||||
|
||||
// The stall duration is 0 for non-jpeg formats. For JPEG format, stall
|
||||
// duration can be 0 if JPEG is small. Here we choose 1 sec for JPEG.
|
||||
// TODO: b/72261675. Maybe set this dynamically
|
||||
for (const auto& format : halFormats) {
|
||||
const int64_t NS_TO_SECOND = 1000000000;
|
||||
int64_t stall_duration =
|
||||
(format == HAL_PIXEL_FORMAT_BLOB) ? NS_TO_SECOND : 0;
|
||||
stallDurations.push_back(format);
|
||||
stallDurations.push_back(supportedFormat.width);
|
||||
stallDurations.push_back(supportedFormat.height);
|
||||
stallDurations.push_back(stall_duration);
|
||||
}
|
||||
}
|
||||
|
||||
// The document in aeAvailableTargetFpsRanges section says the minFps should
|
||||
// not be larger than 15.
|
||||
// We cannot support fixed 30fps but Android requires (min, max) and
|
||||
// (max, max) ranges.
|
||||
// TODO: populate more, right now this does not support 30,30 if the device
|
||||
// has higher than 30 fps modes
|
||||
std::vector<int32_t> fpsRanges;
|
||||
// Variable range
|
||||
fpsRanges.push_back(minFps);
|
||||
fpsRanges.push_back(maxFps);
|
||||
// Fixed ranges
|
||||
for (const auto& framerate : framerates) {
|
||||
fpsRanges.push_back(framerate);
|
||||
fpsRanges.push_back(framerate);
|
||||
}
|
||||
UPDATE(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, fpsRanges.data(),
|
||||
fpsRanges.size());
|
||||
|
||||
UPDATE(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
|
||||
streamConfigurations.data(), streamConfigurations.size());
|
||||
|
||||
UPDATE(ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,
|
||||
minFrameDurations.data(), minFrameDurations.size());
|
||||
|
||||
UPDATE(ANDROID_SCALER_AVAILABLE_STALL_DURATIONS, stallDurations.data(),
|
||||
stallDurations.size());
|
||||
|
||||
UPDATE(ANDROID_SENSOR_INFO_MAX_FRAME_DURATION, &maxFrameDuration, 1);
|
||||
|
||||
SupportedV4L2Format maximumFormat {.width = 0, .height = 0};
|
||||
for (const auto& supportedFormat : mSupportedFormats) {
|
||||
if (supportedFormat.width >= maximumFormat.width &&
|
||||
supportedFormat.height >= maximumFormat.height) {
|
||||
maximumFormat = supportedFormat;
|
||||
}
|
||||
}
|
||||
int32_t activeArraySize[] = {0, 0,
|
||||
static_cast<int32_t>(maximumFormat.width),
|
||||
static_cast<int32_t>(maximumFormat.height)};
|
||||
UPDATE(ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE,
|
||||
activeArraySize, ARRAY_SIZE(activeArraySize));
|
||||
UPDATE(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE, activeArraySize,
|
||||
ARRAY_SIZE(activeArraySize));
|
||||
|
||||
int32_t pixelArraySize[] = {static_cast<int32_t>(maximumFormat.width),
|
||||
static_cast<int32_t>(maximumFormat.height)};
|
||||
UPDATE(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE, pixelArraySize,
|
||||
ARRAY_SIZE(pixelArraySize));
|
||||
return OK;
|
||||
}
|
||||
|
||||
#undef ARRAY_SIZE
|
||||
#undef UPDATE
|
||||
|
||||
void ExternalCameraDevice::getFrameRateList(
|
||||
int fd, SupportedV4L2Format* format) {
|
||||
format->frameRates.clear();
|
||||
|
||||
v4l2_frmivalenum frameInterval {
|
||||
.pixel_format = format->fourcc,
|
||||
.width = format->width,
|
||||
.height = format->height,
|
||||
.index = 0
|
||||
};
|
||||
|
||||
for (frameInterval.index = 0;
|
||||
TEMP_FAILURE_RETRY(ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &frameInterval)) == 0;
|
||||
++frameInterval.index) {
|
||||
if (frameInterval.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
|
||||
if (frameInterval.discrete.numerator != 0) {
|
||||
float framerate = frameInterval.discrete.denominator /
|
||||
static_cast<float>(frameInterval.discrete.numerator);
|
||||
ALOGV("index:%d, format:%c%c%c%c, w %d, h %d, framerate %f",
|
||||
frameInterval.index,
|
||||
frameInterval.pixel_format & 0xFF,
|
||||
(frameInterval.pixel_format >> 8) & 0xFF,
|
||||
(frameInterval.pixel_format >> 16) & 0xFF,
|
||||
(frameInterval.pixel_format >> 24) & 0xFF,
|
||||
frameInterval.width, frameInterval.height, framerate);
|
||||
format->frameRates.push_back(framerate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (format->frameRates.empty()) {
|
||||
ALOGE("%s: failed to get supported frame rates for format:%c%c%c%c w %d h %d",
|
||||
__FUNCTION__,
|
||||
frameInterval.pixel_format & 0xFF,
|
||||
(frameInterval.pixel_format >> 8) & 0xFF,
|
||||
(frameInterval.pixel_format >> 16) & 0xFF,
|
||||
(frameInterval.pixel_format >> 24) & 0xFF,
|
||||
frameInterval.width, frameInterval.height);
|
||||
}
|
||||
}
|
||||
|
||||
void ExternalCameraDevice::initSupportedFormatsLocked(int fd) {
|
||||
struct v4l2_fmtdesc fmtdesc {
|
||||
.index = 0,
|
||||
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE};
|
||||
int ret = 0;
|
||||
while (ret == 0) {
|
||||
ret = TEMP_FAILURE_RETRY(ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc));
|
||||
ALOGD("index:%d,ret:%d, format:%c%c%c%c", fmtdesc.index, ret,
|
||||
fmtdesc.pixelformat & 0xFF,
|
||||
(fmtdesc.pixelformat >> 8) & 0xFF,
|
||||
(fmtdesc.pixelformat >> 16) & 0xFF,
|
||||
(fmtdesc.pixelformat >> 24) & 0xFF);
|
||||
if (ret == 0 && !(fmtdesc.flags & V4L2_FMT_FLAG_EMULATED)) {
|
||||
auto it = std::find (
|
||||
kSupportedFourCCs.begin(), kSupportedFourCCs.end(), fmtdesc.pixelformat);
|
||||
if (it != kSupportedFourCCs.end()) {
|
||||
// Found supported format
|
||||
v4l2_frmsizeenum frameSize {
|
||||
.index = 0,
|
||||
.pixel_format = fmtdesc.pixelformat};
|
||||
for (; TEMP_FAILURE_RETRY(ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &frameSize)) == 0;
|
||||
++frameSize.index) {
|
||||
if (frameSize.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
|
||||
ALOGD("index:%d, format:%c%c%c%c, w %d, h %d", frameSize.index,
|
||||
fmtdesc.pixelformat & 0xFF,
|
||||
(fmtdesc.pixelformat >> 8) & 0xFF,
|
||||
(fmtdesc.pixelformat >> 16) & 0xFF,
|
||||
(fmtdesc.pixelformat >> 24) & 0xFF,
|
||||
frameSize.discrete.width, frameSize.discrete.height);
|
||||
// Disregard h > w formats so all aspect ratio (h/w) <= 1.0
|
||||
// This will simplify the crop/scaling logic down the road
|
||||
if (frameSize.discrete.height > frameSize.discrete.width) {
|
||||
continue;
|
||||
}
|
||||
SupportedV4L2Format format {
|
||||
.width = frameSize.discrete.width,
|
||||
.height = frameSize.discrete.height,
|
||||
.fourcc = fmtdesc.pixelformat
|
||||
};
|
||||
getFrameRateList(fd, &format);
|
||||
if (!format.frameRates.empty()) {
|
||||
mSupportedFormats.push_back(format);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fmtdesc.index++;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V3_4
|
||||
} // namespace device
|
||||
} // namespace camera
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
1990
camera/device/3.4/default/ExternalCameraDeviceSession.cpp
Normal file
1990
camera/device/3.4/default/ExternalCameraDeviceSession.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,441 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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_4_EXTCAMERADEVICE3SESSION_H
|
||||
#define ANDROID_HARDWARE_CAMERA_DEVICE_V3_4_EXTCAMERADEVICE3SESSION_H
|
||||
|
||||
#include <android/hardware/camera/device/3.2/ICameraDevice.h>
|
||||
#include <android/hardware/camera/device/3.4/ICameraDeviceSession.h>
|
||||
#include <fmq/MessageQueue.h>
|
||||
#include <hidl/MQDescriptor.h>
|
||||
#include <hidl/Status.h>
|
||||
#include <include/convert.h>
|
||||
#include <chrono>
|
||||
#include <condition_variable>
|
||||
#include <list>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include "CameraMetadata.h"
|
||||
#include "HandleImporter.h"
|
||||
#include "utils/KeyedVector.h"
|
||||
#include "utils/Mutex.h"
|
||||
#include "utils/Thread.h"
|
||||
#include "android-base/unique_fd.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace camera {
|
||||
namespace device {
|
||||
namespace V3_4 {
|
||||
namespace implementation {
|
||||
|
||||
using ::android::hardware::camera::device::V3_2::BufferCache;
|
||||
using ::android::hardware::camera::device::V3_2::BufferStatus;
|
||||
using ::android::hardware::camera::device::V3_2::CameraMetadata;
|
||||
using ::android::hardware::camera::device::V3_2::CaptureRequest;
|
||||
using ::android::hardware::camera::device::V3_2::CaptureResult;
|
||||
using ::android::hardware::camera::device::V3_2::ErrorCode;
|
||||
using ::android::hardware::camera::device::V3_2::ICameraDeviceCallback;
|
||||
using ::android::hardware::camera::device::V3_2::MsgType;
|
||||
using ::android::hardware::camera::device::V3_2::NotifyMsg;
|
||||
using ::android::hardware::camera::device::V3_2::RequestTemplate;
|
||||
using ::android::hardware::camera::device::V3_2::Stream;
|
||||
using ::android::hardware::camera::device::V3_4::StreamConfiguration;
|
||||
using ::android::hardware::camera::device::V3_2::StreamConfigurationMode;
|
||||
using ::android::hardware::camera::device::V3_2::StreamRotation;
|
||||
using ::android::hardware::camera::device::V3_2::StreamType;
|
||||
using ::android::hardware::camera::device::V3_2::DataspaceFlags;
|
||||
using ::android::hardware::camera::device::V3_4::HalStreamConfiguration;
|
||||
using ::android::hardware::camera::device::V3_4::ICameraDeviceSession;
|
||||
using ::android::hardware::camera::common::V1_0::Status;
|
||||
using ::android::hardware::camera::common::V1_0::helper::HandleImporter;
|
||||
using ::android::hardware::graphics::common::V1_0::BufferUsage;
|
||||
using ::android::hardware::graphics::common::V1_0::Dataspace;
|
||||
using ::android::hardware::graphics::common::V1_0::PixelFormat;
|
||||
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;
|
||||
using ::android::base::unique_fd;
|
||||
|
||||
// TODO: put V4L2 related structs into separate header?
|
||||
struct SupportedV4L2Format {
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t fourcc;
|
||||
// All supported frame rate for this w/h/fourcc combination
|
||||
std::vector<float> frameRates;
|
||||
};
|
||||
|
||||
// A class provide access to a dequeued V4L2 frame buffer (mostly in MJPG format)
|
||||
// Also contains necessary information to enqueue the buffer back to V4L2 buffer queue
|
||||
class V4L2Frame : public virtual VirtualLightRefBase {
|
||||
public:
|
||||
V4L2Frame(uint32_t w, uint32_t h, uint32_t fourcc, int bufIdx, int fd, uint32_t dataSize);
|
||||
~V4L2Frame() override;
|
||||
const uint32_t mWidth;
|
||||
const uint32_t mHeight;
|
||||
const uint32_t mFourcc;
|
||||
const int mBufferIndex; // for later enqueue
|
||||
int map(uint8_t** data, size_t* dataSize);
|
||||
int unmap();
|
||||
private:
|
||||
Mutex mLock;
|
||||
const int mFd; // used for mmap but doesn't claim ownership
|
||||
const size_t mDataSize;
|
||||
uint8_t* mData = nullptr;
|
||||
bool mMapped = false;
|
||||
};
|
||||
|
||||
// A RAII class representing a CPU allocated YUV frame used as intermeidate buffers
|
||||
// when generating output images.
|
||||
class AllocatedFrame : public virtual VirtualLightRefBase {
|
||||
public:
|
||||
AllocatedFrame(uint32_t w, uint32_t h); // TODO: use Size?
|
||||
~AllocatedFrame() override;
|
||||
const uint32_t mWidth;
|
||||
const uint32_t mHeight;
|
||||
const uint32_t mFourcc; // Only support YU12 format for now
|
||||
int allocate(YCbCrLayout* out = nullptr);
|
||||
int getLayout(YCbCrLayout* out);
|
||||
int getCroppedLayout(const IMapper::Rect&, YCbCrLayout* out); // return non-zero for bad input
|
||||
private:
|
||||
Mutex mLock;
|
||||
std::vector<uint8_t> mData;
|
||||
};
|
||||
|
||||
struct Size {
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
|
||||
bool operator==(const Size& other) const {
|
||||
return (width == other.width && height == other.height);
|
||||
}
|
||||
};
|
||||
|
||||
struct SizeHasher {
|
||||
size_t operator()(const Size& sz) const {
|
||||
size_t result = 1;
|
||||
result = 31 * result + sz.width;
|
||||
result = 31 * result + sz.height;
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
enum CroppingType {
|
||||
HORIZONTAL = 0,
|
||||
VERTICAL = 1
|
||||
};
|
||||
|
||||
struct ExternalCameraDeviceSession : public virtual RefBase {
|
||||
|
||||
ExternalCameraDeviceSession(const sp<ICameraDeviceCallback>&,
|
||||
const std::vector<SupportedV4L2Format>& supportedFormats,
|
||||
const common::V1_0::helper::CameraMetadata& chars,
|
||||
unique_fd v4l2Fd);
|
||||
virtual ~ExternalCameraDeviceSession();
|
||||
// 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 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_4(this);
|
||||
}
|
||||
|
||||
static const int kMaxProcessedStream = 2;
|
||||
static const int kMaxStallStream = 1;
|
||||
|
||||
protected:
|
||||
|
||||
// Methods from ::android::hardware::camera::device::V3_2::ICameraDeviceSession follow
|
||||
|
||||
Return<void> constructDefaultRequestSettings(
|
||||
RequestTemplate,
|
||||
ICameraDeviceSession::constructDefaultRequestSettings_cb _hidl_cb);
|
||||
|
||||
Return<void> configureStreams(
|
||||
const V3_2::StreamConfiguration&,
|
||||
ICameraDeviceSession::configureStreams_cb);
|
||||
|
||||
Return<void> getCaptureRequestMetadataQueue(
|
||||
ICameraDeviceSession::getCaptureRequestMetadataQueue_cb);
|
||||
|
||||
Return<void> getCaptureResultMetadataQueue(
|
||||
ICameraDeviceSession::getCaptureResultMetadataQueue_cb);
|
||||
|
||||
Return<void> processCaptureRequest(
|
||||
const hidl_vec<CaptureRequest>&,
|
||||
const hidl_vec<BufferCache>&,
|
||||
ICameraDeviceSession::processCaptureRequest_cb);
|
||||
|
||||
Return<Status> flush();
|
||||
Return<void> close();
|
||||
|
||||
Return<void> configureStreams_3_3(
|
||||
const V3_2::StreamConfiguration&,
|
||||
ICameraDeviceSession::configureStreams_3_3_cb);
|
||||
|
||||
Return<void> configureStreams_3_4(
|
||||
const V3_4::StreamConfiguration& requestedConfiguration,
|
||||
ICameraDeviceSession::configureStreams_3_4_cb _hidl_cb);
|
||||
|
||||
Return<void> processCaptureRequest_3_4(
|
||||
const hidl_vec<V3_4::CaptureRequest>& requests,
|
||||
const hidl_vec<V3_2::BufferCache>& cachesToRemove,
|
||||
ICameraDeviceSession::processCaptureRequest_3_4_cb _hidl_cb);
|
||||
|
||||
protected:
|
||||
struct HalStreamBuffer {
|
||||
int32_t streamId;
|
||||
uint64_t bufferId;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
PixelFormat format;
|
||||
V3_2::BufferUsageFlags usage;
|
||||
buffer_handle_t* bufPtr;
|
||||
int acquireFence;
|
||||
bool fenceTimeout;
|
||||
};
|
||||
|
||||
struct HalRequest {
|
||||
uint32_t frameNumber;
|
||||
common::V1_0::helper::CameraMetadata setting;
|
||||
sp<V4L2Frame> frameIn;
|
||||
nsecs_t shutterTs;
|
||||
std::vector<HalStreamBuffer> buffers;
|
||||
};
|
||||
|
||||
static std::vector<SupportedV4L2Format> sortFormats(
|
||||
const std::vector<SupportedV4L2Format>&);
|
||||
static CroppingType initCroppingType(const std::vector<SupportedV4L2Format>&);
|
||||
bool initialize();
|
||||
Status initStatus() const;
|
||||
status_t initDefaultRequests();
|
||||
status_t fillCaptureResult(common::V1_0::helper::CameraMetadata& md, nsecs_t timestamp);
|
||||
Status configureStreams(const V3_2::StreamConfiguration&, V3_3::HalStreamConfiguration* out);
|
||||
int configureV4l2StreamLocked(const SupportedV4L2Format& fmt);
|
||||
int v4l2StreamOffLocked();
|
||||
|
||||
// TODO: change to unique_ptr for better tracking
|
||||
sp<V4L2Frame> dequeueV4l2FrameLocked(); // Called with mLock hold
|
||||
void enqueueV4l2Frame(const sp<V4L2Frame>&);
|
||||
|
||||
// Check if input Stream is one of supported stream setting on this device
|
||||
bool isSupported(const Stream&);
|
||||
|
||||
// Validate and import request's output buffers and acquire fence
|
||||
Status importRequest(
|
||||
const CaptureRequest& request,
|
||||
hidl_vec<buffer_handle_t*>& allBufPtrs,
|
||||
hidl_vec<int>& allFences);
|
||||
static void cleanupInflightFences(
|
||||
hidl_vec<int>& allFences, size_t numFences);
|
||||
void cleanupBuffersLocked(int id);
|
||||
void updateBufferCaches(const hidl_vec<BufferCache>& cachesToRemove);
|
||||
|
||||
Status processOneCaptureRequest(const CaptureRequest& request);
|
||||
|
||||
Status processCaptureResult(HalRequest&);
|
||||
Status processCaptureRequestError(HalRequest&);
|
||||
void notifyShutter(uint32_t frameNumber, nsecs_t shutterTs);
|
||||
void notifyError(uint32_t frameNumber, int32_t streamId, ErrorCode ec);
|
||||
void invokeProcessCaptureResultCallback(
|
||||
hidl_vec<CaptureResult> &results, bool tryWriteFmq);
|
||||
static void freeReleaseFences(hidl_vec<CaptureResult>&);
|
||||
|
||||
class OutputThread : public android::Thread {
|
||||
public:
|
||||
OutputThread(wp<ExternalCameraDeviceSession> parent, CroppingType);
|
||||
~OutputThread();
|
||||
|
||||
Status allocateIntermediateBuffers(
|
||||
const Size& v4lSize, const hidl_vec<Stream>& streams);
|
||||
Status submitRequest(const HalRequest&);
|
||||
void flush();
|
||||
virtual bool threadLoop() override;
|
||||
|
||||
private:
|
||||
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;
|
||||
// returns FLEX_YUV_GENERIC for formats other than YV12/YU12/NV12/NV21
|
||||
static uint32_t getFourCcFromLayout(const YCbCrLayout&);
|
||||
static int getCropRect(
|
||||
CroppingType ct, const Size& inSize, const Size& outSize, IMapper::Rect* out);
|
||||
|
||||
static const int kReqWaitTimeoutSec = 3;
|
||||
|
||||
void waitForNextRequest(HalRequest* out);
|
||||
int cropAndScaleLocked(
|
||||
sp<AllocatedFrame>& in, const HalStreamBuffer& halBuf,
|
||||
YCbCrLayout* out);
|
||||
|
||||
int formatConvertLocked(const YCbCrLayout& in, const YCbCrLayout& out,
|
||||
Size sz, uint32_t format);
|
||||
|
||||
mutable std::mutex mLock;
|
||||
std::condition_variable mRequestCond;
|
||||
wp<ExternalCameraDeviceSession> mParent;
|
||||
CroppingType mCroppingType;
|
||||
std::list<HalRequest> mRequestList;
|
||||
// V4L2 frameIn
|
||||
// (MJPG decode)-> mYu12Frame
|
||||
// (Scale)-> mScaledYu12Frames
|
||||
// (Format convert) -> output gralloc frames
|
||||
sp<AllocatedFrame> mYu12Frame;
|
||||
std::unordered_map<Size, sp<AllocatedFrame>, SizeHasher> mIntermediateBuffers;
|
||||
std::unordered_map<Size, sp<AllocatedFrame>, SizeHasher> mScaledYu12Frames;
|
||||
YCbCrLayout mYu12FrameLayout;
|
||||
};
|
||||
|
||||
// Protect (most of) HIDL interface methods from synchronized-entering
|
||||
mutable Mutex mInterfaceLock;
|
||||
|
||||
mutable Mutex mLock; // Protect all private members except otherwise noted
|
||||
const sp<ICameraDeviceCallback> mCallback;
|
||||
const common::V1_0::helper::CameraMetadata mCameraCharacteristics;
|
||||
unique_fd mV4l2Fd;
|
||||
// device is closed either
|
||||
// - closed by user
|
||||
// - init failed
|
||||
// - camera disconnected
|
||||
bool mClosed = false;
|
||||
bool mInitFail = false;
|
||||
bool mFirstRequest = false;
|
||||
common::V1_0::helper::CameraMetadata mLatestReqSetting;
|
||||
|
||||
bool mV4l2Streaming = false;
|
||||
SupportedV4L2Format mV4l2StreamingFmt;
|
||||
std::vector<unique_fd> mV4l2Buffers;
|
||||
|
||||
static const int kBufferWaitTimeoutSec = 3; // TODO: handle long exposure (or not allowing)
|
||||
std::mutex mV4l2BufferLock; // protect the buffer count and condition below
|
||||
std::condition_variable mV4L2BufferReturned;
|
||||
size_t mNumDequeuedV4l2Buffers = 0;
|
||||
|
||||
const std::vector<SupportedV4L2Format> mSupportedFormats;
|
||||
const CroppingType mCroppingType;
|
||||
sp<OutputThread> mOutputThread;
|
||||
|
||||
// Stream ID -> Camera3Stream cache
|
||||
std::unordered_map<int, Stream> mStreamMap;
|
||||
std::unordered_set<uint32_t> mInflightFrames;
|
||||
|
||||
// buffers currently circulating between HAL and camera service
|
||||
// key: bufferId sent via HIDL interface
|
||||
// value: imported buffer_handle_t
|
||||
// Buffer will be imported during processCaptureRequest 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;
|
||||
|
||||
/* Beginning of members not changed after initialize() */
|
||||
using RequestMetadataQueue = MessageQueue<uint8_t, kSynchronizedReadWrite>;
|
||||
std::unique_ptr<RequestMetadataQueue> mRequestMetadataQueue;
|
||||
using ResultMetadataQueue = MessageQueue<uint8_t, kSynchronizedReadWrite>;
|
||||
std::shared_ptr<ResultMetadataQueue> mResultMetadataQueue;
|
||||
|
||||
// Protect against invokeProcessCaptureResultCallback()
|
||||
Mutex mProcessCaptureResultLock;
|
||||
|
||||
std::unordered_map<int, CameraMetadata> mDefaultRequests;
|
||||
/* End of members not changed after initialize() */
|
||||
|
||||
private:
|
||||
|
||||
struct TrampolineSessionInterface_3_4 : public ICameraDeviceSession {
|
||||
TrampolineSessionInterface_3_4(sp<ExternalCameraDeviceSession> parent) :
|
||||
mParent(parent) {}
|
||||
|
||||
virtual Return<void> constructDefaultRequestSettings(
|
||||
V3_2::RequestTemplate type,
|
||||
V3_3::ICameraDeviceSession::constructDefaultRequestSettings_cb _hidl_cb) override {
|
||||
return mParent->constructDefaultRequestSettings(type, _hidl_cb);
|
||||
}
|
||||
|
||||
virtual Return<void> configureStreams(
|
||||
const V3_2::StreamConfiguration& requestedConfiguration,
|
||||
V3_3::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_3::ICameraDeviceSession::processCaptureRequest_cb _hidl_cb) override {
|
||||
return mParent->processCaptureRequest(requests, cachesToRemove, _hidl_cb);
|
||||
}
|
||||
|
||||
virtual Return<void> getCaptureRequestMetadataQueue(
|
||||
V3_3::ICameraDeviceSession::getCaptureRequestMetadataQueue_cb _hidl_cb) override {
|
||||
return mParent->getCaptureRequestMetadataQueue(_hidl_cb);
|
||||
}
|
||||
|
||||
virtual Return<void> getCaptureResultMetadataQueue(
|
||||
V3_3::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();
|
||||
}
|
||||
|
||||
virtual Return<void> configureStreams_3_3(
|
||||
const V3_2::StreamConfiguration& requestedConfiguration,
|
||||
configureStreams_3_3_cb _hidl_cb) override {
|
||||
return mParent->configureStreams_3_3(requestedConfiguration, _hidl_cb);
|
||||
}
|
||||
|
||||
virtual Return<void> configureStreams_3_4(
|
||||
const V3_4::StreamConfiguration& requestedConfiguration,
|
||||
configureStreams_3_4_cb _hidl_cb) override {
|
||||
return mParent->configureStreams_3_4(requestedConfiguration, _hidl_cb);
|
||||
}
|
||||
|
||||
virtual Return<void> processCaptureRequest_3_4(const hidl_vec<V3_4::CaptureRequest>& requests,
|
||||
const hidl_vec<V3_2::BufferCache>& cachesToRemove,
|
||||
ICameraDeviceSession::processCaptureRequest_3_4_cb _hidl_cb) override {
|
||||
return mParent->processCaptureRequest_3_4(requests, cachesToRemove, _hidl_cb);
|
||||
}
|
||||
|
||||
private:
|
||||
sp<ExternalCameraDeviceSession> mParent;
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V3_4
|
||||
} // namespace device
|
||||
} // namespace camera
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
#endif // ANDROID_HARDWARE_CAMERA_DEVICE_V3_4_EXTCAMERADEVICE3SESSION_H
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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_4_EXTCAMERADEVICE_H
|
||||
#define ANDROID_HARDWARE_CAMERA_DEVICE_V3_4_EXTCAMERADEVICE_H
|
||||
|
||||
#include "utils/Mutex.h"
|
||||
#include "CameraMetadata.h"
|
||||
|
||||
#include <android/hardware/camera/device/3.2/ICameraDevice.h>
|
||||
#include <hidl/Status.h>
|
||||
#include <hidl/MQDescriptor.h>
|
||||
#include "ExternalCameraDeviceSession.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace camera {
|
||||
namespace device {
|
||||
namespace V3_4 {
|
||||
namespace implementation {
|
||||
|
||||
using namespace ::android::hardware::camera::device;
|
||||
using ::android::hardware::camera::device::V3_2::ICameraDevice;
|
||||
using ::android::hardware::camera::device::V3_2::ICameraDeviceCallback;
|
||||
using ::android::hardware::camera::common::V1_0::CameraResourceCost;
|
||||
using ::android::hardware::camera::common::V1_0::TorchMode;
|
||||
using ::android::hardware::camera::common::V1_0::Status;
|
||||
using ::android::hardware::Return;
|
||||
using ::android::hardware::Void;
|
||||
using ::android::hardware::hidl_vec;
|
||||
using ::android::hardware::hidl_string;
|
||||
using ::android::sp;
|
||||
|
||||
/*
|
||||
* The camera device HAL implementation is opened lazily (via the open call)
|
||||
*/
|
||||
struct ExternalCameraDevice : public ICameraDevice {
|
||||
|
||||
// Called by external camera provider HAL.
|
||||
// Provider HAL must ensure the uniqueness of CameraDevice object per cameraId, or there could
|
||||
// be multiple CameraDevice trying to access the same physical camera. Also, provider will have
|
||||
// to keep track of all CameraDevice objects in order to notify CameraDevice when the underlying
|
||||
// camera is detached.
|
||||
ExternalCameraDevice(const std::string& cameraId);
|
||||
~ExternalCameraDevice();
|
||||
|
||||
// Caller must use this method to check if CameraDevice ctor failed
|
||||
bool isInitFailed();
|
||||
|
||||
/* Methods from ::android::hardware::camera::device::V3_2::ICameraDevice follow. */
|
||||
// The following method can be called without opening the actual camera device
|
||||
Return<void> getResourceCost(getResourceCost_cb _hidl_cb) override;
|
||||
|
||||
Return<void> getCameraCharacteristics(getCameraCharacteristics_cb _hidl_cb) override;
|
||||
|
||||
Return<Status> setTorchMode(TorchMode) override;
|
||||
|
||||
// Open the device HAL and also return a default capture session
|
||||
Return<void> open(const sp<ICameraDeviceCallback>&, open_cb) override;
|
||||
|
||||
// Forward the dump call to the opened session, or do nothing
|
||||
Return<void> dumpState(const ::android::hardware::hidl_handle&) override;
|
||||
/* End of Methods from ::android::hardware::camera::device::V3_2::ICameraDevice */
|
||||
|
||||
protected:
|
||||
void getFrameRateList(int fd, SupportedV4L2Format* format);
|
||||
// Init supported w/h/format/fps in mSupportedFormats. Caller still owns fd
|
||||
void initSupportedFormatsLocked(int fd);
|
||||
|
||||
status_t initCameraCharacteristics();
|
||||
// Init non-device dependent keys
|
||||
status_t initDefaultCharsKeys(::android::hardware::camera::common::V1_0::helper::CameraMetadata*);
|
||||
// Init camera control chars keys. Caller still owns fd
|
||||
status_t initCameraControlsCharsKeys(int fd,
|
||||
::android::hardware::camera::common::V1_0::helper::CameraMetadata*);
|
||||
// Init camera output configuration related keys. Caller still owns fd
|
||||
status_t initOutputCharsKeys(int fd,
|
||||
::android::hardware::camera::common::V1_0::helper::CameraMetadata*);
|
||||
|
||||
Mutex mLock;
|
||||
bool mInitFailed = false;
|
||||
std::string mCameraId;
|
||||
std::vector<SupportedV4L2Format> mSupportedFormats;
|
||||
|
||||
wp<ExternalCameraDeviceSession> mSession = nullptr;
|
||||
|
||||
::android::hardware::camera::common::V1_0::helper::CameraMetadata mCameraCharacteristics;
|
||||
};
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V3_4
|
||||
} // namespace device
|
||||
} // namespace camera
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
#endif // ANDROID_HARDWARE_CAMERA_DEVICE_V3_4_EXTCAMERADEVICE_H
|
||||
@@ -3,7 +3,8 @@ cc_library_shared {
|
||||
defaults: ["hidl_defaults"],
|
||||
proprietary: true,
|
||||
relative_install_path: "hw",
|
||||
srcs: ["CameraProvider.cpp"],
|
||||
srcs: ["CameraProvider.cpp",
|
||||
"ExternalCameraProvider.cpp"],
|
||||
shared_libs: [
|
||||
"libhidlbase",
|
||||
"libhidltransport",
|
||||
@@ -17,6 +18,7 @@ cc_library_shared {
|
||||
"camera.device@3.2-impl",
|
||||
"camera.device@3.3-impl",
|
||||
"camera.device@3.4-impl",
|
||||
"camera.device@3.4-external-impl",
|
||||
"android.hardware.camera.provider@2.4",
|
||||
"android.hardware.camera.common@1.0",
|
||||
"android.hardware.graphics.mapper@2.0",
|
||||
@@ -28,6 +30,7 @@ cc_library_shared {
|
||||
],
|
||||
header_libs: [
|
||||
"camera.device@3.4-impl_headers",
|
||||
"camera.device@3.4-external-impl_headers"
|
||||
],
|
||||
static_libs: [
|
||||
"android.hardware.camera.common@1.0-helper",
|
||||
@@ -56,3 +59,25 @@ cc_binary {
|
||||
"android.hardware.camera.common@1.0",
|
||||
],
|
||||
}
|
||||
|
||||
cc_binary {
|
||||
name: "android.hardware.camera.provider@2.4-external-service",
|
||||
defaults: ["hidl_defaults"],
|
||||
proprietary: true,
|
||||
relative_install_path: "hw",
|
||||
srcs: ["external-service.cpp"],
|
||||
compile_multilib: "32",
|
||||
init_rc: ["android.hardware.camera.provider@2.4-external-service.rc"],
|
||||
shared_libs: [
|
||||
"libhidlbase",
|
||||
"libhidltransport",
|
||||
"libbinder",
|
||||
"liblog",
|
||||
"libutils",
|
||||
"android.hardware.camera.device@1.0",
|
||||
"android.hardware.camera.device@3.2",
|
||||
"android.hardware.camera.device@3.3",
|
||||
"android.hardware.camera.provider@2.4",
|
||||
"android.hardware.camera.common@1.0",
|
||||
],
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <android/log.h>
|
||||
|
||||
#include "CameraProvider.h"
|
||||
#include "ExternalCameraProvider.h"
|
||||
#include "CameraDevice_1_0.h"
|
||||
#include "CameraDevice_3_3.h"
|
||||
#include "CameraDevice_3_4.h"
|
||||
@@ -36,6 +37,7 @@ namespace implementation {
|
||||
|
||||
namespace {
|
||||
const char *kLegacyProviderName = "legacy/0";
|
||||
const char *kExternalProviderName = "external/0";
|
||||
// "device@<version>/legacy/<id>"
|
||||
const std::regex kDeviceNameRE("device@([0-9]+\\.[0-9]+)/legacy/(.+)");
|
||||
const char *kHAL3_2 = "3.2";
|
||||
@@ -571,20 +573,24 @@ Return<void> CameraProvider::getCameraDeviceInterface_V3_x(
|
||||
}
|
||||
|
||||
ICameraProvider* HIDL_FETCH_ICameraProvider(const char* name) {
|
||||
if (strcmp(name, kLegacyProviderName) != 0) {
|
||||
return nullptr;
|
||||
if (strcmp(name, kLegacyProviderName) == 0) {
|
||||
CameraProvider* provider = new CameraProvider();
|
||||
if (provider == nullptr) {
|
||||
ALOGE("%s: cannot allocate camera provider!", __FUNCTION__);
|
||||
return nullptr;
|
||||
}
|
||||
if (provider->isInitFailed()) {
|
||||
ALOGE("%s: camera provider init failed!", __FUNCTION__);
|
||||
delete provider;
|
||||
return nullptr;
|
||||
}
|
||||
return provider;
|
||||
} else if (strcmp(name, kExternalProviderName) == 0) {
|
||||
ExternalCameraProvider* provider = new ExternalCameraProvider();
|
||||
return provider;
|
||||
}
|
||||
CameraProvider* provider = new CameraProvider();
|
||||
if (provider == nullptr) {
|
||||
ALOGE("%s: cannot allocate camera provider!", __FUNCTION__);
|
||||
return nullptr;
|
||||
}
|
||||
if (provider->isInitFailed()) {
|
||||
ALOGE("%s: camera provider init failed!", __FUNCTION__);
|
||||
delete provider;
|
||||
return nullptr;
|
||||
}
|
||||
return provider;
|
||||
ALOGE("%s: unknown instance name: %s", __FUNCTION__, name);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace implementation
|
||||
|
||||
276
camera/provider/2.4/default/ExternalCameraProvider.cpp
Normal file
276
camera/provider/2.4/default/ExternalCameraProvider.cpp
Normal file
@@ -0,0 +1,276 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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 "CamPvdr@2.4-external"
|
||||
//#define LOG_NDEBUG 0
|
||||
#include <log/log.h>
|
||||
|
||||
#include <regex>
|
||||
#include <sys/inotify.h>
|
||||
#include <errno.h>
|
||||
#include <linux/videodev2.h>
|
||||
#include "ExternalCameraProvider.h"
|
||||
#include "ExternalCameraDevice_3_4.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace camera {
|
||||
namespace provider {
|
||||
namespace V2_4 {
|
||||
namespace implementation {
|
||||
|
||||
namespace {
|
||||
// "device@<version>/external/<id>"
|
||||
const std::regex kDeviceNameRE("device@([0-9]+\\.[0-9]+)/external/(.+)");
|
||||
const int kMaxDevicePathLen = 256;
|
||||
const char* kDevicePath = "/dev/";
|
||||
|
||||
bool matchDeviceName(const hidl_string& deviceName, std::string* deviceVersion,
|
||||
std::string* cameraId) {
|
||||
std::string deviceNameStd(deviceName.c_str());
|
||||
std::smatch sm;
|
||||
if (std::regex_match(deviceNameStd, sm, kDeviceNameRE)) {
|
||||
if (deviceVersion != nullptr) {
|
||||
*deviceVersion = sm[1];
|
||||
}
|
||||
if (cameraId != nullptr) {
|
||||
*cameraId = sm[2];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
ExternalCameraProvider::ExternalCameraProvider() : mHotPlugThread(this) {
|
||||
mHotPlugThread.run("ExtCamHotPlug", PRIORITY_BACKGROUND);
|
||||
}
|
||||
|
||||
ExternalCameraProvider::~ExternalCameraProvider() {
|
||||
mHotPlugThread.requestExit();
|
||||
}
|
||||
|
||||
|
||||
Return<Status> ExternalCameraProvider::setCallback(
|
||||
const sp<ICameraProviderCallback>& callback) {
|
||||
Mutex::Autolock _l(mLock);
|
||||
mCallbacks = callback;
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
Return<void> ExternalCameraProvider::getVendorTags(getVendorTags_cb _hidl_cb) {
|
||||
// No vendor tag support for USB camera
|
||||
hidl_vec<VendorTagSection> zeroSections;
|
||||
_hidl_cb(Status::OK, zeroSections);
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> ExternalCameraProvider::getCameraIdList(getCameraIdList_cb _hidl_cb) {
|
||||
std::vector<hidl_string> deviceNameList;
|
||||
for (auto const& kvPair : mCameraStatusMap) {
|
||||
if (kvPair.second == CameraDeviceStatus::PRESENT) {
|
||||
deviceNameList.push_back(kvPair.first);
|
||||
}
|
||||
}
|
||||
hidl_vec<hidl_string> hidlDeviceNameList(deviceNameList);
|
||||
ALOGV("ExtCam: number of cameras is %zu", deviceNameList.size());
|
||||
_hidl_cb(Status::OK, hidlDeviceNameList);
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> ExternalCameraProvider::isSetTorchModeSupported(
|
||||
isSetTorchModeSupported_cb _hidl_cb) {
|
||||
// No torch mode support for USB camera
|
||||
_hidl_cb (Status::OK, false);
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> ExternalCameraProvider::getCameraDeviceInterface_V1_x(
|
||||
const hidl_string&,
|
||||
getCameraDeviceInterface_V1_x_cb _hidl_cb) {
|
||||
// External Camera HAL does not support HAL1
|
||||
_hidl_cb(Status::OPERATION_NOT_SUPPORTED, nullptr);
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> ExternalCameraProvider::getCameraDeviceInterface_V3_x(
|
||||
const hidl_string& cameraDeviceName,
|
||||
getCameraDeviceInterface_V3_x_cb _hidl_cb) {
|
||||
|
||||
std::string cameraId, deviceVersion;
|
||||
bool match = matchDeviceName(cameraDeviceName, &deviceVersion, &cameraId);
|
||||
if (!match) {
|
||||
_hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
|
||||
return Void();
|
||||
}
|
||||
|
||||
if (mCameraStatusMap.count(cameraDeviceName) == 0 ||
|
||||
mCameraStatusMap[cameraDeviceName] != CameraDeviceStatus::PRESENT) {
|
||||
_hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
|
||||
return Void();
|
||||
}
|
||||
|
||||
ALOGV("Constructing v3.4 external camera device");
|
||||
sp<device::V3_2::ICameraDevice> device;
|
||||
sp<device::V3_4::implementation::ExternalCameraDevice> deviceImpl =
|
||||
new device::V3_4::implementation::ExternalCameraDevice(
|
||||
cameraId);
|
||||
if (deviceImpl == nullptr || deviceImpl->isInitFailed()) {
|
||||
ALOGE("%s: camera device %s init failed!", __FUNCTION__, cameraId.c_str());
|
||||
device = nullptr;
|
||||
_hidl_cb(Status::INTERNAL_ERROR, nullptr);
|
||||
return Void();
|
||||
}
|
||||
device = deviceImpl;
|
||||
|
||||
_hidl_cb (Status::OK, device);
|
||||
|
||||
return Void();
|
||||
}
|
||||
|
||||
void ExternalCameraProvider::addExternalCamera(const char* devName) {
|
||||
ALOGE("ExtCam: adding %s to External Camera HAL!", devName);
|
||||
Mutex::Autolock _l(mLock);
|
||||
std::string deviceName = std::string("device@3.4/external/") + devName;
|
||||
mCameraStatusMap[deviceName] = CameraDeviceStatus::PRESENT;
|
||||
if (mCallbacks != nullptr) {
|
||||
mCallbacks->cameraDeviceStatusChange(deviceName, CameraDeviceStatus::PRESENT);
|
||||
}
|
||||
}
|
||||
|
||||
void ExternalCameraProvider::deviceAdded(const char* devName) {
|
||||
int fd = -1;
|
||||
if ((fd = ::open(devName, O_RDWR)) < 0) {
|
||||
ALOGE("%s open v4l2 device %s failed:%s", __FUNCTION__, devName, strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
struct v4l2_capability capability;
|
||||
int ret = ioctl(fd, VIDIOC_QUERYCAP, &capability);
|
||||
if (ret < 0) {
|
||||
ALOGE("%s v4l2 QUERYCAP %s failed", __FUNCTION__, devName);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(capability.device_caps & V4L2_CAP_VIDEO_CAPTURE)) {
|
||||
ALOGW("%s device %s does not support VIDEO_CAPTURE", __FUNCTION__, devName);
|
||||
break;
|
||||
}
|
||||
|
||||
addExternalCamera(devName);
|
||||
} while (0);
|
||||
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
void ExternalCameraProvider::deviceRemoved(const char* devName) {
|
||||
Mutex::Autolock _l(mLock);
|
||||
std::string deviceName = std::string("device@3.4/external/") + devName;
|
||||
if (mCameraStatusMap.find(deviceName) != mCameraStatusMap.end()) {
|
||||
mCameraStatusMap.erase(deviceName);
|
||||
if (mCallbacks != nullptr) {
|
||||
mCallbacks->cameraDeviceStatusChange(deviceName, CameraDeviceStatus::NOT_PRESENT);
|
||||
}
|
||||
} else {
|
||||
ALOGE("%s: cannot find camera device %s", __FUNCTION__, devName);
|
||||
}
|
||||
}
|
||||
|
||||
ExternalCameraProvider::HotplugThread::HotplugThread(ExternalCameraProvider* parent) :
|
||||
Thread(/*canCallJava*/false), mParent(parent) {}
|
||||
|
||||
ExternalCameraProvider::HotplugThread::~HotplugThread() {}
|
||||
|
||||
bool ExternalCameraProvider::HotplugThread::threadLoop() {
|
||||
// Find existing /dev/video* devices
|
||||
DIR* devdir = opendir(kDevicePath);
|
||||
if(devdir == 0) {
|
||||
ALOGE("%s: cannot open %s! Exiting threadloop", __FUNCTION__, kDevicePath);
|
||||
return false;
|
||||
}
|
||||
|
||||
struct dirent* de;
|
||||
// This list is device dependent. TODO: b/72261897 allow setting it from setprop/device boot
|
||||
std::string internalDevices = "0,1";
|
||||
while ((de = readdir(devdir)) != 0) {
|
||||
// Find external v4l devices that's existing before we start watching and add them
|
||||
if (!strncmp("video", de->d_name, 5)) {
|
||||
// TODO: This might reject some valid devices. Ex: internal is 33 and a device named 3
|
||||
// is added.
|
||||
if (internalDevices.find(de->d_name + 5) == std::string::npos) {
|
||||
ALOGV("Non-internal v4l device %s found", de->d_name);
|
||||
char v4l2DevicePath[kMaxDevicePathLen];
|
||||
snprintf(v4l2DevicePath, kMaxDevicePathLen,
|
||||
"%s%s", kDevicePath, de->d_name);
|
||||
mParent->deviceAdded(v4l2DevicePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir(devdir);
|
||||
|
||||
// Watch new video devices
|
||||
mINotifyFD = inotify_init();
|
||||
if (mINotifyFD < 0) {
|
||||
ALOGE("%s: inotify init failed! Exiting threadloop", __FUNCTION__);
|
||||
return true;
|
||||
}
|
||||
|
||||
mWd = inotify_add_watch(mINotifyFD, kDevicePath, IN_CREATE | IN_DELETE);
|
||||
if (mWd < 0) {
|
||||
ALOGE("%s: inotify add watch failed! Exiting threadloop", __FUNCTION__);
|
||||
return true;
|
||||
}
|
||||
|
||||
ALOGI("%s start monitoring new V4L2 devices", __FUNCTION__);
|
||||
|
||||
bool done = false;
|
||||
char eventBuf[512];
|
||||
while (!done) {
|
||||
int offset = 0;
|
||||
int ret = read(mINotifyFD, eventBuf, sizeof(eventBuf));
|
||||
if (ret >= (int)sizeof(struct inotify_event)) {
|
||||
while (offset < ret) {
|
||||
struct inotify_event* event = (struct inotify_event*)&eventBuf[offset];
|
||||
if (event->wd == mWd) {
|
||||
if (!strncmp("video", event->name, 5)) {
|
||||
char v4l2DevicePath[kMaxDevicePathLen];
|
||||
snprintf(v4l2DevicePath, kMaxDevicePathLen,
|
||||
"%s%s", kDevicePath, event->name);
|
||||
if (event->mask & IN_CREATE) {
|
||||
mParent->deviceAdded(v4l2DevicePath);
|
||||
}
|
||||
if (event->mask & IN_DELETE) {
|
||||
mParent->deviceRemoved(v4l2DevicePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
offset += sizeof(struct inotify_event) + event->len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V2_4
|
||||
} // namespace provider
|
||||
} // namespace camera
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
102
camera/provider/2.4/default/ExternalCameraProvider.h
Normal file
102
camera/provider/2.4/default/ExternalCameraProvider.h
Normal file
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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_PROVIDER_V2_4_EXTCAMERAPROVIDER_H
|
||||
#define ANDROID_HARDWARE_CAMERA_PROVIDER_V2_4_EXTCAMERAPROVIDER_H
|
||||
|
||||
#include <unordered_map>
|
||||
#include "utils/Mutex.h"
|
||||
#include "utils/Thread.h"
|
||||
#include <android/hardware/camera/provider/2.4/ICameraProvider.h>
|
||||
#include <hidl/Status.h>
|
||||
#include <hidl/MQDescriptor.h>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace camera {
|
||||
namespace provider {
|
||||
namespace V2_4 {
|
||||
namespace implementation {
|
||||
|
||||
using ::android::hardware::camera::common::V1_0::CameraDeviceStatus;
|
||||
using ::android::hardware::camera::common::V1_0::Status;
|
||||
using ::android::hardware::camera::common::V1_0::VendorTagSection;
|
||||
using ::android::hardware::camera::provider::V2_4::ICameraProvider;
|
||||
using ::android::hardware::camera::provider::V2_4::ICameraProviderCallback;
|
||||
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 ExternalCameraProvider : public ICameraProvider {
|
||||
ExternalCameraProvider();
|
||||
~ExternalCameraProvider();
|
||||
|
||||
// Methods from ::android::hardware::camera::provider::V2_4::ICameraProvider follow.
|
||||
Return<Status> setCallback(const sp<ICameraProviderCallback>& callback) override;
|
||||
|
||||
Return<void> getVendorTags(getVendorTags_cb _hidl_cb) override;
|
||||
|
||||
Return<void> getCameraIdList(getCameraIdList_cb _hidl_cb) override;
|
||||
|
||||
Return<void> isSetTorchModeSupported(isSetTorchModeSupported_cb _hidl_cb) override;
|
||||
|
||||
Return<void> getCameraDeviceInterface_V1_x(
|
||||
const hidl_string&,
|
||||
getCameraDeviceInterface_V1_x_cb) override;
|
||||
Return<void> getCameraDeviceInterface_V3_x(
|
||||
const hidl_string&,
|
||||
getCameraDeviceInterface_V3_x_cb) override;
|
||||
|
||||
private:
|
||||
|
||||
void addExternalCamera(const char* devName);
|
||||
|
||||
void deviceAdded(const char* devName);
|
||||
|
||||
void deviceRemoved(const char* devName);
|
||||
|
||||
class HotplugThread : public android::Thread {
|
||||
public:
|
||||
HotplugThread(ExternalCameraProvider* parent);
|
||||
~HotplugThread();
|
||||
|
||||
virtual bool threadLoop() override;
|
||||
|
||||
private:
|
||||
ExternalCameraProvider* mParent = nullptr;
|
||||
|
||||
int mINotifyFD = -1;
|
||||
int mWd = -1;
|
||||
} mHotPlugThread;
|
||||
|
||||
Mutex mLock;
|
||||
sp<ICameraProviderCallback> mCallbacks = nullptr;
|
||||
std::unordered_map<std::string, CameraDeviceStatus> mCameraStatusMap; // camera id -> status
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V2_4
|
||||
} // namespace provider
|
||||
} // namespace camera
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
#endif // ANDROID_HARDWARE_CAMERA_PROVIDER_V2_4_EXTCAMERAPROVIDER_H
|
||||
@@ -0,0 +1,7 @@
|
||||
service vendor.camera-provider-2-4-ext /vendor/bin/hw/android.hardware.camera.provider@2.4-external-service
|
||||
class hal
|
||||
user cameraserver
|
||||
group audio camera input drmrpc usb
|
||||
ioprio rt 4
|
||||
capabilities SYS_NICE
|
||||
writepid /dev/cpuset/camera-daemon/tasks /dev/stune/top-app/tasks
|
||||
34
camera/provider/2.4/default/external-service.cpp
Normal file
34
camera/provider/2.4/default/external-service.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2018 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 "android.hardware.camera.provider@2.4-external-service"
|
||||
|
||||
#include <android/hardware/camera/provider/2.4/ICameraProvider.h>
|
||||
#include <hidl/LegacySupport.h>
|
||||
|
||||
#include <binder/ProcessState.h>
|
||||
|
||||
using android::hardware::camera::provider::V2_4::ICameraProvider;
|
||||
using android::hardware::defaultPassthroughServiceImplementation;
|
||||
|
||||
int main()
|
||||
{
|
||||
ALOGI("External camera provider service is starting.");
|
||||
// The camera HAL may communicate to other vendor components via
|
||||
// /dev/vndbinder
|
||||
android::ProcessState::initWithDriver("/dev/vndbinder");
|
||||
return defaultPassthroughServiceImplementation<ICameraProvider>("external/0", /*maxThreads*/ 6);
|
||||
}
|
||||
Reference in New Issue
Block a user