blob: f33a106ca4ab4c79734bcafee9ab6804cd74a14c [file] [log] [blame]
/*
* Copyright (C) 2012 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 "Camera2Client"
#define ATRACE_TAG ATRACE_TAG_CAMERA
//#define LOG_NDEBUG 0
#include <utils/Log.h>
#include <utils/Trace.h>
#include <cutils/properties.h>
#include <gui/SurfaceTextureClient.h>
#include <gui/Surface.h>
#include <math.h>
#include "Camera2Client.h"
namespace android {
#define ALOG1(...) ALOGD_IF(gLogLevel >= 1, __VA_ARGS__);
#define ALOG2(...) ALOGD_IF(gLogLevel >= 2, __VA_ARGS__);
static int getCallingPid() {
return IPCThreadState::self()->getCallingPid();
}
static int getCallingUid() {
return IPCThreadState::self()->getCallingUid();
}
// Interface used by CameraService
Camera2Client::Camera2Client(const sp<CameraService>& cameraService,
const sp<ICameraClient>& cameraClient,
int cameraId,
int cameraFacing,
int clientPid):
Client(cameraService, cameraClient,
cameraId, cameraFacing, clientPid),
mState(NOT_INITIALIZED),
mPreviewStreamId(NO_PREVIEW_STREAM),
mPreviewRequest(NULL)
{
ATRACE_CALL();
mDevice = new Camera2Device(cameraId);
}
status_t Camera2Client::initialize(camera_module_t *module)
{
ATRACE_CALL();
status_t res;
res = mDevice->initialize(module);
if (res != OK) {
ALOGE("%s: Camera %d: unable to initialize device: %s (%d)",
__FUNCTION__, mCameraId, strerror(-res), res);
return NO_INIT;
}
res = buildDefaultParameters();
if (res != OK) {
ALOGE("%s: Camera %d: unable to build defaults: %s (%d)",
__FUNCTION__, mCameraId, strerror(-res), res);
return NO_INIT;
}
if (gLogLevel >= 1) {
ALOGD("%s: Default parameters converted from camera %d:", __FUNCTION__,
mCameraId);
ALOGD("%s", mParamsFlattened.string());
}
mState = STOPPED;
return OK;
}
Camera2Client::~Camera2Client() {
ATRACE_CALL();
mDestructionStarted = true;
disconnect();
}
status_t Camera2Client::dump(int fd, const Vector<String16>& args) {
String8 result;
result.appendFormat("Client2[%d] (%p) PID: %d:\n",
mCameraId,
getCameraClient()->asBinder().get(),
mClientPid);
write(fd, result.string(), result.size());
return NO_ERROR;
}
// ICamera interface
void Camera2Client::disconnect() {
ATRACE_CALL();
if (mDevice == 0) return;
stopPreview();
if (mPreviewStreamId != NO_PREVIEW_STREAM) {
mDevice->deleteStream(mPreviewStreamId);
mPreviewStreamId = NO_PREVIEW_STREAM;
}
CameraService::Client::disconnect();
}
status_t Camera2Client::connect(const sp<ICameraClient>& client) {
ATRACE_CALL();
return BAD_VALUE;
}
status_t Camera2Client::lock() {
ATRACE_CALL();
return BAD_VALUE;
}
status_t Camera2Client::unlock() {
ATRACE_CALL();
return BAD_VALUE;
}
status_t Camera2Client::setPreviewDisplay(
const sp<Surface>& surface) {
ATRACE_CALL();
if (mState == PREVIEW) return INVALID_OPERATION;
sp<IBinder> binder;
sp<ANativeWindow> window;
if (surface != 0) {
binder = surface->asBinder();
window = surface;
}
return setPreviewWindow(binder,window);
}
status_t Camera2Client::setPreviewTexture(
const sp<ISurfaceTexture>& surfaceTexture) {
ATRACE_CALL();
if (mState == PREVIEW) return INVALID_OPERATION;
sp<IBinder> binder;
sp<ANativeWindow> window;
if (surfaceTexture != 0) {
binder = surfaceTexture->asBinder();
window = new SurfaceTextureClient(surfaceTexture);
}
return setPreviewWindow(binder, window);
}
status_t Camera2Client::setPreviewWindow(const sp<IBinder>& binder,
const sp<ANativeWindow>& window) {
ATRACE_CALL();
status_t res;
if (binder == mPreviewSurface) {
return NO_ERROR;
}
if (mPreviewStreamId != NO_PREVIEW_STREAM) {
res = mDevice->deleteStream(mPreviewStreamId);
if (res != OK) {
return res;
}
}
res = mDevice->createStream(window,
mParameters.previewWidth, mParameters.previewHeight,
CAMERA2_HAL_PIXEL_FORMAT_OPAQUE,
&mPreviewStreamId);
if (res != OK) {
return res;
}
if (mState == WAITING_FOR_PREVIEW_WINDOW) {
return startPreview();
}
return OK;
}
void Camera2Client::setPreviewCallbackFlag(int flag) {
ATRACE_CALL();
}
status_t Camera2Client::startPreview() {
ATRACE_CALL();
status_t res;
if (mState == PREVIEW) return INVALID_OPERATION;
if (mPreviewStreamId == NO_PREVIEW_STREAM) {
mState = WAITING_FOR_PREVIEW_WINDOW;
return OK;
}
if (mPreviewRequest == NULL) {
updatePreviewRequest();
}
uint8_t outputStream = mPreviewStreamId;
camera_metadata_entry_t outputStreams;
res = find_camera_metadata_entry(mPreviewRequest,
ANDROID_REQUEST_OUTPUT_STREAMS,
&outputStreams);
if (res == NAME_NOT_FOUND) {
res = add_camera_metadata_entry(mPreviewRequest,
ANDROID_REQUEST_OUTPUT_STREAMS,
&outputStream, 1);
} else if (res == OK) {
res = update_camera_metadata_entry(mPreviewRequest,
outputStreams.index, &outputStream, 1, NULL);
}
if (res != OK) {
ALOGE("%s: Camera %d: Unable to set up preview request: %s (%d)",
__FUNCTION__, mCameraId, strerror(-res), res);
mState = STOPPED;
return res;
}
res = mDevice->setStreamingRequest(mPreviewRequest);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to set preview request to start preview: %s (%d)",
__FUNCTION__, mCameraId, strerror(-res), res);
mState = STOPPED;
return res;
}
mState = PREVIEW;
return OK;
}
void Camera2Client::stopPreview() {
ATRACE_CALL();
if (mState != PREVIEW) return;
mDevice->setStreamingRequest(NULL);
mState = STOPPED;
}
bool Camera2Client::previewEnabled() {
ATRACE_CALL();
return mState == PREVIEW;
}
status_t Camera2Client::storeMetaDataInBuffers(bool enabled) {
ATRACE_CALL();
return BAD_VALUE;
}
status_t Camera2Client::startRecording() {
ATRACE_CALL();
return BAD_VALUE;
}
void Camera2Client::stopRecording() {
ATRACE_CALL();
}
bool Camera2Client::recordingEnabled() {
ATRACE_CALL();
return BAD_VALUE;
}
void Camera2Client::releaseRecordingFrame(const sp<IMemory>& mem) {
ATRACE_CALL();
}
status_t Camera2Client::autoFocus() {
ATRACE_CALL();
return OK;
}
status_t Camera2Client::cancelAutoFocus() {
ATRACE_CALL();
return OK;
}
status_t Camera2Client::takePicture(int msgType) {
ATRACE_CALL();
return BAD_VALUE;
}
status_t Camera2Client::setParameters(const String8& params) {
ATRACE_CALL();
return OK;
}
String8 Camera2Client::getParameters() const {
ATRACE_CALL();
// TODO: Deal with focus distances
return mParamsFlattened;
}
status_t Camera2Client::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) {
ATRACE_CALL();
return OK;
}
/** Device-related methods */
camera_metadata_entry_t Camera2Client::staticInfo(uint32_t tag,
size_t minCount, size_t maxCount) {
status_t res;
camera_metadata_entry_t entry;
res = find_camera_metadata_entry(mDevice->info(),
tag,
&entry);
if (CC_UNLIKELY( res != OK )) {
const char* tagSection = get_camera_metadata_section_name(tag);
if (tagSection == NULL) tagSection = "<unknown>";
const char* tagName = get_camera_metadata_tag_name(tag);
if (tagName == NULL) tagName = "<unknown>";
ALOGE("Error finding static metadata entry '%s.%s' (%x): %s (%d)",
tagSection, tagName, tag, strerror(-res), res);
entry.count = 0;
entry.data.u8 = NULL;
} else if (CC_UNLIKELY(
(minCount != 0 && entry.count < minCount) ||
(maxCount != 0 && entry.count > maxCount) ) ) {
const char* tagSection = get_camera_metadata_section_name(tag);
if (tagSection == NULL) tagSection = "<unknown>";
const char* tagName = get_camera_metadata_tag_name(tag);
if (tagName == NULL) tagName = "<unknown>";
ALOGE("Malformed static metadata entry '%s.%s' (%x):"
"Expected between %d and %d values, but got %d values",
tagSection, tagName, tag, minCount, maxCount, entry.count);
entry.count = 0;
entry.data.u8 = NULL;
}
return entry;
}
/** Utility methods */
status_t Camera2Client::buildDefaultParameters() {
ATRACE_CALL();
status_t res;
CameraParameters params;
camera_metadata_entry_t availableProcessedSizes =
staticInfo(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES, 2);
if (!availableProcessedSizes.count) return NO_INIT;
// TODO: Pick more intelligently
mParameters.previewWidth = availableProcessedSizes.data.i32[0];
mParameters.previewHeight = availableProcessedSizes.data.i32[1];
mParameters.videoWidth = mParameters.previewWidth;
mParameters.videoHeight = mParameters.previewHeight;
params.setPreviewSize(mParameters.previewWidth, mParameters.previewHeight);
params.setVideoSize(mParameters.videoWidth, mParameters.videoHeight);
params.set(CameraParameters::KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO,
String8::format("%dx%d",
mParameters.previewWidth, mParameters.previewHeight));
{
String8 supportedPreviewSizes;
for (size_t i=0; i < availableProcessedSizes.count; i += 2) {
if (i != 0) supportedPreviewSizes += ",";
supportedPreviewSizes += String8::format("%dx%d",
availableProcessedSizes.data.i32[i],
availableProcessedSizes.data.i32[i+1]);
}
params.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES,
supportedPreviewSizes);
params.set(CameraParameters::KEY_SUPPORTED_VIDEO_SIZES,
supportedPreviewSizes);
}
camera_metadata_entry_t availableFpsRanges =
staticInfo(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, 2);
if (!availableFpsRanges.count) return NO_INIT;
mParameters.previewFpsRangeMin = availableFpsRanges.data.i32[0];
mParameters.previewFpsRangeMax = availableFpsRanges.data.i32[1];
params.set(CameraParameters::KEY_PREVIEW_FPS_RANGE,
String8::format("%d,%d",
mParameters.previewFpsRangeMin,
mParameters.previewFpsRangeMax));
{
String8 supportedPreviewFpsRange;
for (size_t i=0; i < availableFpsRanges.count; i += 2) {
if (i != 0) supportedPreviewFpsRange += ",";
supportedPreviewFpsRange += String8::format("(%d,%d)",
availableFpsRanges.data.i32[i],
availableFpsRanges.data.i32[i+1]);
}
params.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE,
supportedPreviewFpsRange);
}
mParameters.previewFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP;
params.set(CameraParameters::KEY_PREVIEW_FORMAT,
formatEnumToString(mParameters.previewFormat)); // NV21
camera_metadata_entry_t availableFormats =
staticInfo(ANDROID_SCALER_AVAILABLE_FORMATS);
{
String8 supportedPreviewFormats;
bool addComma = false;
for (size_t i=0; i < availableFormats.count; i++) {
if (addComma) supportedPreviewFormats += ",";
addComma = true;
switch (availableFormats.data.i32[i]) {
case HAL_PIXEL_FORMAT_YCbCr_422_SP:
supportedPreviewFormats += "yuv422sp";
break;
case HAL_PIXEL_FORMAT_YCrCb_420_SP:
supportedPreviewFormats += "yuv420sp";
break;
case HAL_PIXEL_FORMAT_YCbCr_422_I:
supportedPreviewFormats += "yuv422i-yuyv";
break;
case HAL_PIXEL_FORMAT_YV12:
supportedPreviewFormats += "yuv420p";
break;
case HAL_PIXEL_FORMAT_RGB_565:
supportedPreviewFormats += "rgb565";
break;
// Not advertizing JPEG, RAW_SENSOR, etc, for preview formats
case HAL_PIXEL_FORMAT_RAW_SENSOR:
addComma = false;
break;
default:
ALOGW("%s: Camera %d: Unknown preview format: %x",
__FUNCTION__, mCameraId, availableFormats.data.i32[i]);
addComma = false;
break;
}
}
params.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS,
supportedPreviewFormats);
}
// PREVIEW_FRAME_RATE / SUPPORTED_PREVIEW_FRAME_RATES are deprecated, but
// still have to do something sane for them
params.set(CameraParameters::KEY_PREVIEW_FRAME_RATE,
mParameters.previewFpsRangeMin);
{
String8 supportedPreviewFrameRates;
for (size_t i=0; i < availableFpsRanges.count; i += 2) {
if (i != 0) supportedPreviewFrameRates += ",";
supportedPreviewFrameRates += String8::format("%d",
availableFpsRanges.data.i32[i]);
}
params.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES,
supportedPreviewFrameRates);
}
camera_metadata_entry_t availableJpegSizes =
staticInfo(ANDROID_SCALER_AVAILABLE_JPEG_SIZES, 2);
if (!availableJpegSizes.count) return NO_INIT;
// TODO: Pick maximum
mParameters.pictureWidth = availableJpegSizes.data.i32[0];
mParameters.pictureHeight = availableJpegSizes.data.i32[1];
params.setPictureSize(mParameters.pictureWidth,
mParameters.pictureHeight);
{
String8 supportedPictureSizes;
for (size_t i=0; i < availableJpegSizes.count; i += 2) {
if (i != 0) supportedPictureSizes += ",";
supportedPictureSizes += String8::format("%dx%d",
availableJpegSizes.data.i32[i],
availableJpegSizes.data.i32[i+1]);
}
params.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES,
supportedPictureSizes);
}
params.setPictureFormat(CameraParameters::PIXEL_FORMAT_JPEG);
params.set(CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS,
CameraParameters::PIXEL_FORMAT_JPEG);
camera_metadata_entry_t availableJpegThumbnailSizes =
staticInfo(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES, 2);
if (!availableJpegThumbnailSizes.count) return NO_INIT;
// TODO: Pick default thumbnail size sensibly
mParameters.jpegThumbWidth = availableJpegThumbnailSizes.data.i32[0];
mParameters.jpegThumbHeight = availableJpegThumbnailSizes.data.i32[1];
params.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH,
mParameters.jpegThumbWidth);
params.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT,
mParameters.jpegThumbHeight);
{
String8 supportedJpegThumbSizes;
for (size_t i=0; i < availableJpegThumbnailSizes.count; i += 2) {
if (i != 0) supportedJpegThumbSizes += ",";
supportedJpegThumbSizes += String8::format("%dx%d",
availableJpegThumbnailSizes.data.i32[i],
availableJpegThumbnailSizes.data.i32[i+1]);
}
params.set(CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES,
supportedJpegThumbSizes);
}
mParameters.jpegThumbQuality = 90;
params.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY,
mParameters.jpegThumbQuality);
mParameters.jpegQuality = 90;
params.set(CameraParameters::KEY_JPEG_QUALITY,
mParameters.jpegQuality);
mParameters.jpegRotation = 0;
params.set(CameraParameters::KEY_ROTATION,
mParameters.jpegRotation);
mParameters.gpsEnabled = false;
mParameters.gpsProcessingMethod = "unknown";
// GPS fields in CameraParameters are not set by implementation
mParameters.wbMode = ANDROID_CONTROL_AWB_AUTO;
params.set(CameraParameters::KEY_WHITE_BALANCE,
CameraParameters::WHITE_BALANCE_AUTO);
camera_metadata_entry_t availableWhiteBalanceModes =
staticInfo(ANDROID_CONTROL_AWB_AVAILABLE_MODES);
{
String8 supportedWhiteBalance;
bool addComma = false;
for (size_t i=0; i < availableWhiteBalanceModes.count; i++) {
if (addComma) supportedWhiteBalance += ",";
addComma = true;
switch (availableWhiteBalanceModes.data.u8[i]) {
case ANDROID_CONTROL_AWB_AUTO:
supportedWhiteBalance += "auto";
break;
case ANDROID_CONTROL_AWB_INCANDESCENT:
supportedWhiteBalance += "incandescent";
break;
case ANDROID_CONTROL_AWB_FLUORESCENT:
supportedWhiteBalance += "fluorescent";
break;
case ANDROID_CONTROL_AWB_WARM_FLUORESCENT:
supportedWhiteBalance += "warm-fluorescent";
break;
case ANDROID_CONTROL_AWB_DAYLIGHT:
supportedWhiteBalance += "daylight";
break;
case ANDROID_CONTROL_AWB_CLOUDY_DAYLIGHT:
supportedWhiteBalance += "cloudy-daylight";
break;
case ANDROID_CONTROL_AWB_TWILIGHT:
supportedWhiteBalance += "twilight";
break;
case ANDROID_CONTROL_AWB_SHADE:
supportedWhiteBalance += "shade";
break;
// Skipping values not mappable to v1 API
case ANDROID_CONTROL_AWB_OFF:
addComma = false;
break;
default:
ALOGW("%s: Camera %d: Unknown white balance value: %d",
__FUNCTION__, mCameraId,
availableWhiteBalanceModes.data.u8[i]);
addComma = false;
break;
}
}
params.set(CameraParameters::KEY_SUPPORTED_WHITE_BALANCE,
supportedWhiteBalance);
}
mParameters.effectMode = ANDROID_CONTROL_EFFECT_OFF;
params.set(CameraParameters::KEY_EFFECT,
CameraParameters::EFFECT_NONE);
camera_metadata_entry_t availableEffects =
staticInfo(ANDROID_CONTROL_AVAILABLE_EFFECTS);
if (!availableEffects.count) return NO_INIT;
{
String8 supportedEffects;
bool addComma = false;
for (size_t i=0; i < availableEffects.count; i++) {
if (addComma) supportedEffects += ",";
addComma = true;
switch (availableEffects.data.u8[i]) {
case ANDROID_CONTROL_EFFECT_OFF:
supportedEffects += "none";
break;
case ANDROID_CONTROL_EFFECT_MONO:
supportedEffects += "mono";
case ANDROID_CONTROL_EFFECT_NEGATIVE:
supportedEffects += "negative";
break;
case ANDROID_CONTROL_EFFECT_SOLARIZE:
supportedEffects += "solarize";
break;
case ANDROID_CONTROL_EFFECT_SEPIA:
supportedEffects += "sepia";
break;
case ANDROID_CONTROL_EFFECT_POSTERIZE:
supportedEffects += "posterize";
break;
case ANDROID_CONTROL_EFFECT_WHITEBOARD:
supportedEffects += "whiteboard";
break;
case ANDROID_CONTROL_EFFECT_BLACKBOARD:
supportedEffects += "blackboard";
break;
case ANDROID_CONTROL_EFFECT_AQUA:
supportedEffects += "aqua";
break;
default:
ALOGW("%s: Camera %d: Unknown effect value: %d",
__FUNCTION__, mCameraId, availableEffects.data.u8[i]);
addComma = false;
break;
}
}
params.set(CameraParameters::KEY_SUPPORTED_EFFECTS, supportedEffects);
}
mParameters.antibandingMode = ANDROID_CONTROL_AE_ANTIBANDING_AUTO;
params.set(CameraParameters::KEY_ANTIBANDING,
CameraParameters::ANTIBANDING_AUTO);
camera_metadata_entry_t availableAntibandingModes =
staticInfo(ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES);
if (!availableAntibandingModes.count) return NO_INIT;
{
String8 supportedAntibanding;
bool addComma = false;
for (size_t i=0; i < availableAntibandingModes.count; i++) {
if (addComma) supportedAntibanding += ",";
addComma = true;
switch (availableAntibandingModes.data.u8[i]) {
case ANDROID_CONTROL_AE_ANTIBANDING_OFF:
supportedAntibanding += "off";
break;
case ANDROID_CONTROL_AE_ANTIBANDING_50HZ:
supportedAntibanding += "50hz";
break;
case ANDROID_CONTROL_AE_ANTIBANDING_60HZ:
supportedAntibanding += "60hz";
break;
case ANDROID_CONTROL_AE_ANTIBANDING_AUTO:
supportedAntibanding += "auto";
break;
default:
ALOGW("%s: Camera %d: Unknown antibanding value: %d",
__FUNCTION__, mCameraId,
availableAntibandingModes.data.u8[i]);
addComma = false;
break;
}
}
params.set(CameraParameters::KEY_SUPPORTED_ANTIBANDING,
supportedAntibanding);
}
mParameters.sceneMode = ANDROID_CONTROL_OFF;
params.set(CameraParameters::KEY_SCENE_MODE,
CameraParameters::SCENE_MODE_AUTO);
camera_metadata_entry_t availableSceneModes =
staticInfo(ANDROID_CONTROL_AVAILABLE_SCENE_MODES);
if (!availableSceneModes.count) return NO_INIT;
{
String8 supportedSceneModes("auto");
bool addComma = true;
bool noSceneModes = false;
for (size_t i=0; i < availableSceneModes.count; i++) {
if (addComma) supportedSceneModes += ",";
addComma = true;
switch (availableSceneModes.data.u8[i]) {
case ANDROID_CONTROL_SCENE_MODE_UNSUPPORTED:
noSceneModes = true;
break;
case ANDROID_CONTROL_SCENE_MODE_FACE_PRIORITY:
// Not in old API
addComma = false;
break;
case ANDROID_CONTROL_SCENE_MODE_ACTION:
supportedSceneModes += "action";
break;
case ANDROID_CONTROL_SCENE_MODE_PORTRAIT:
supportedSceneModes += "portrait";
break;
case ANDROID_CONTROL_SCENE_MODE_LANDSCAPE:
supportedSceneModes += "landscape";
break;
case ANDROID_CONTROL_SCENE_MODE_NIGHT:
supportedSceneModes += "night";
break;
case ANDROID_CONTROL_SCENE_MODE_NIGHT_PORTRAIT:
supportedSceneModes += "night-portrait";
break;
case ANDROID_CONTROL_SCENE_MODE_THEATRE:
supportedSceneModes += "theatre";
break;
case ANDROID_CONTROL_SCENE_MODE_BEACH:
supportedSceneModes += "beach";
break;
case ANDROID_CONTROL_SCENE_MODE_SNOW:
supportedSceneModes += "snow";
break;
case ANDROID_CONTROL_SCENE_MODE_SUNSET:
supportedSceneModes += "sunset";
break;
case ANDROID_CONTROL_SCENE_MODE_STEADYPHOTO:
supportedSceneModes += "steadyphoto";
break;
case ANDROID_CONTROL_SCENE_MODE_FIREWORKS:
supportedSceneModes += "fireworks";
break;
case ANDROID_CONTROL_SCENE_MODE_SPORTS:
supportedSceneModes += "sports";
break;
case ANDROID_CONTROL_SCENE_MODE_PARTY:
supportedSceneModes += "party";
break;
case ANDROID_CONTROL_SCENE_MODE_CANDLELIGHT:
supportedSceneModes += "candlelight";
break;
case ANDROID_CONTROL_SCENE_MODE_BARCODE:
supportedSceneModes += "barcode";
break;
default:
ALOGW("%s: Camera %d: Unknown scene mode value: %d",
__FUNCTION__, mCameraId, availableSceneModes.data.u8[i]);
addComma = false;
break;
}
}
if (!noSceneModes) {
params.set(CameraParameters::KEY_SUPPORTED_SCENE_MODES,
supportedSceneModes);
}
}
camera_metadata_entry_t flashAvailable =
staticInfo(ANDROID_FLASH_AVAILABLE, 1, 1);
if (!flashAvailable.count) return NO_INIT;
camera_metadata_entry_t availableAeModes =
staticInfo(ANDROID_CONTROL_AE_AVAILABLE_MODES);
if (!availableAeModes.count) return NO_INIT;
if (flashAvailable.data.u8[0]) {
mParameters.flashMode = Parameters::FLASH_MODE_AUTO;
params.set(CameraParameters::KEY_FLASH_MODE,
CameraParameters::FLASH_MODE_AUTO);
String8 supportedFlashModes(CameraParameters::FLASH_MODE_OFF);
supportedFlashModes = supportedFlashModes +
"," + CameraParameters::FLASH_MODE_AUTO +
"," + CameraParameters::FLASH_MODE_ON +
"," + CameraParameters::FLASH_MODE_TORCH;
for (size_t i=0; i < availableAeModes.count; i++) {
if (availableAeModes.data.u8[i] ==
ANDROID_CONTROL_AE_ON_AUTO_FLASH_REDEYE) {
supportedFlashModes = supportedFlashModes + "," +
CameraParameters::FLASH_MODE_RED_EYE;
break;
}
}
params.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES,
supportedFlashModes);
} else {
mParameters.flashMode = Parameters::FLASH_MODE_OFF;
params.set(CameraParameters::KEY_FLASH_MODE,
CameraParameters::FLASH_MODE_OFF);
params.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES,
CameraParameters::FLASH_MODE_OFF);
}
camera_metadata_entry_t minFocusDistance =
staticInfo(ANDROID_LENS_MINIMUM_FOCUS_DISTANCE, 1, 1);
if (!minFocusDistance.count) return NO_INIT;
camera_metadata_entry_t availableAfModes =
staticInfo(ANDROID_CONTROL_AF_AVAILABLE_MODES);
if (!availableAfModes.count) return NO_INIT;
if (minFocusDistance.data.f[0] == 0) {
// Fixed-focus lens
mParameters.focusMode = Parameters::FOCUS_MODE_FIXED;
params.set(CameraParameters::KEY_FOCUS_MODE,
CameraParameters::FOCUS_MODE_FIXED);
params.set(CameraParameters::KEY_SUPPORTED_FOCUS_MODES,
CameraParameters::FOCUS_MODE_FIXED);
} else {
mParameters.focusMode = Parameters::FOCUS_MODE_AUTO;
params.set(CameraParameters::KEY_FOCUS_MODE,
CameraParameters::FOCUS_MODE_AUTO);
String8 supportedFocusModes(CameraParameters::FOCUS_MODE_FIXED);
supportedFocusModes = supportedFocusModes + "," +
CameraParameters::FOCUS_MODE_INFINITY;
bool addComma = true;
for (size_t i=0; i < availableAfModes.count; i++) {
if (addComma) supportedFocusModes += ",";
addComma = true;
switch (availableAfModes.data.u8[i]) {
case ANDROID_CONTROL_AF_AUTO:
supportedFocusModes += "auto";
break;
case ANDROID_CONTROL_AF_MACRO:
supportedFocusModes += "macro";
break;
case ANDROID_CONTROL_AF_CONTINUOUS_VIDEO:
supportedFocusModes += "continuous-video";
break;
case ANDROID_CONTROL_AF_CONTINUOUS_PICTURE:
supportedFocusModes += "continuous-picture";
break;
case ANDROID_CONTROL_AF_EDOF:
supportedFocusModes += "edof";
break;
// Not supported in v1 API
case ANDROID_CONTROL_AF_OFF:
addComma = false;
break;
default:
ALOGW("%s: Camera %d: Unknown AF mode value: %d",
__FUNCTION__, mCameraId, availableAfModes.data.u8[i]);
addComma = false;
break;
}
}
params.set(CameraParameters::KEY_SUPPORTED_FOCUS_MODES,
supportedFocusModes);
}
camera_metadata_entry_t max3aRegions =
staticInfo(ANDROID_CONTROL_MAX_REGIONS, 1, 1);
if (!max3aRegions.count) return NO_INIT;
params.set(CameraParameters::KEY_MAX_NUM_FOCUS_AREAS,
max3aRegions.data.i32[0]);
params.set(CameraParameters::KEY_FOCUS_AREAS,
"(0,0,0,0,0)");
mParameters.focusingAreas.clear();
mParameters.focusingAreas.add(Parameters::Area(0,0,0,0,0));
camera_metadata_entry_t availableFocalLengths =
staticInfo(ANDROID_LENS_AVAILABLE_FOCAL_LENGTHS);
if (!availableFocalLengths.count) return NO_INIT;
float minFocalLength = availableFocalLengths.data.f[0];
params.setFloat(CameraParameters::KEY_FOCAL_LENGTH, minFocalLength);
camera_metadata_entry_t sensorSize =
staticInfo(ANDROID_SENSOR_PHYSICAL_SIZE, 2, 2);
if (!sensorSize.count) return NO_INIT;
// The fields of view here assume infinity focus, maximum wide angle
float horizFov = 180 / M_PI *
2 * atanf(sensorSize.data.f[0] / (2 * minFocalLength));
float vertFov = 180 / M_PI *
2 * atanf(sensorSize.data.f[1] / (2 * minFocalLength));
params.setFloat(CameraParameters::KEY_HORIZONTAL_VIEW_ANGLE, horizFov);
params.setFloat(CameraParameters::KEY_VERTICAL_VIEW_ANGLE, vertFov);
mParameters.exposureCompensation = 0;
params.set(CameraParameters::KEY_EXPOSURE_COMPENSATION,
mParameters.exposureCompensation);
camera_metadata_entry_t exposureCompensationRange =
staticInfo(ANDROID_CONTROL_AE_EXP_COMPENSATION_RANGE, 2, 2);
if (!exposureCompensationRange.count) return NO_INIT;
params.set(CameraParameters::KEY_MAX_EXPOSURE_COMPENSATION,
exposureCompensationRange.data.i32[1]);
params.set(CameraParameters::KEY_MIN_EXPOSURE_COMPENSATION,
exposureCompensationRange.data.i32[0]);
camera_metadata_entry_t exposureCompensationStep =
staticInfo(ANDROID_CONTROL_AE_EXP_COMPENSATION_STEP, 1, 1);
if (!exposureCompensationStep.count) return NO_INIT;
params.setFloat(CameraParameters::KEY_EXPOSURE_COMPENSATION_STEP,
exposureCompensationStep.data.r[0].numerator /
exposureCompensationStep.data.r[0].denominator);
mParameters.autoExposureLock = false;
params.set(CameraParameters::KEY_AUTO_EXPOSURE_LOCK,
CameraParameters::FALSE);
params.set(CameraParameters::KEY_AUTO_EXPOSURE_LOCK_SUPPORTED,
CameraParameters::TRUE);
mParameters.autoWhiteBalanceLock = false;
params.set(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK,
CameraParameters::FALSE);
params.set(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK_SUPPORTED,
CameraParameters::TRUE);
mParameters.meteringAreas.add(Parameters::Area(0, 0, 0, 0, 0));
params.set(CameraParameters::KEY_MAX_NUM_METERING_AREAS,
max3aRegions.data.i32[0]);
params.set(CameraParameters::KEY_METERING_AREAS,
"(0,0,0,0,0)");
mParameters.zoom = 0;
params.set(CameraParameters::KEY_ZOOM, mParameters.zoom);
params.set(CameraParameters::KEY_MAX_ZOOM, NUM_ZOOM_STEPS - 1);
camera_metadata_entry_t maxDigitalZoom =
staticInfo(ANDROID_SCALER_AVAILABLE_MAX_ZOOM, 1, 1);
if (!maxDigitalZoom.count) return NO_INIT;
{
String8 zoomRatios;
float zoom = 1.f;
float zoomIncrement = (maxDigitalZoom.data.f[0] - zoom) /
(NUM_ZOOM_STEPS-1);
bool addComma = false;
for (size_t i=0; i < NUM_ZOOM_STEPS; i++) {
if (addComma) zoomRatios += ",";
addComma = true;
zoomRatios += String8::format("%d", static_cast<int>(zoom * 100));
zoom += zoomIncrement;
}
params.set(CameraParameters::KEY_ZOOM_RATIOS, zoomRatios);
}
params.set(CameraParameters::KEY_ZOOM_SUPPORTED,
CameraParameters::TRUE);
params.set(CameraParameters::KEY_SMOOTH_ZOOM_SUPPORTED,
CameraParameters::TRUE);
params.set(CameraParameters::KEY_FOCUS_DISTANCES,
"Infinity,Infinity,Infinity");
camera_metadata_entry_t maxFacesDetected =
staticInfo(ANDROID_STATS_MAX_FACE_COUNT, 1, 1);
params.set(CameraParameters::KEY_MAX_NUM_DETECTED_FACES_HW,
maxFacesDetected.data.i32[0]);
params.set(CameraParameters::KEY_MAX_NUM_DETECTED_FACES_SW,
0);
params.set(CameraParameters::KEY_VIDEO_FRAME_FORMAT,
formatEnumToString(HAL_PIXEL_FORMAT_YCrCb_420_SP));
params.set(CameraParameters::KEY_RECORDING_HINT,
CameraParameters::FALSE);
params.set(CameraParameters::KEY_VIDEO_SNAPSHOT_SUPPORTED,
CameraParameters::TRUE);
params.set(CameraParameters::KEY_VIDEO_STABILIZATION,
CameraParameters::FALSE);
camera_metadata_entry_t availableVideoStabilizationModes =
staticInfo(ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES);
if (!availableVideoStabilizationModes.count) return NO_INIT;
if (availableVideoStabilizationModes.count > 1) {
params.set(CameraParameters::KEY_VIDEO_STABILIZATION_SUPPORTED,
CameraParameters::TRUE);
} else {
params.set(CameraParameters::KEY_VIDEO_STABILIZATION_SUPPORTED,
CameraParameters::FALSE);
}
mParamsFlattened = params.flatten();
return OK;
}
status_t Camera2Client::updatePreviewRequest() {
ATRACE_CALL();
status_t res;
if (mPreviewRequest == NULL) {
res = mDevice->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
&mPreviewRequest);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to create default preview request: "
"%s (%d)", __FUNCTION__, mCameraId, strerror(-res), res);
return res;
}
}
// TODO: Adjust for params changes
return OK;
}
const char* Camera2Client::formatEnumToString(int format) {
const char *fmt;
switch(format) {
case HAL_PIXEL_FORMAT_YCbCr_422_SP: // NV16
fmt = CameraParameters::PIXEL_FORMAT_YUV422SP;
break;
case HAL_PIXEL_FORMAT_YCrCb_420_SP: // NV21
fmt = CameraParameters::PIXEL_FORMAT_YUV420SP;
break;
case HAL_PIXEL_FORMAT_YCbCr_422_I: // YUY2
fmt = CameraParameters::PIXEL_FORMAT_YUV422I;
break;
case HAL_PIXEL_FORMAT_YV12: // YV12
fmt = CameraParameters::PIXEL_FORMAT_YUV420P;
break;
case HAL_PIXEL_FORMAT_RGB_565: // RGB565
fmt = CameraParameters::PIXEL_FORMAT_RGB565;
break;
case HAL_PIXEL_FORMAT_RGBA_8888: // RGBA8888
fmt = CameraParameters::PIXEL_FORMAT_RGBA8888;
break;
case HAL_PIXEL_FORMAT_RAW_SENSOR:
ALOGW("Raw sensor preview format requested.");
fmt = CameraParameters::PIXEL_FORMAT_BAYER_RGGB;
break;
default:
ALOGE("%s: Unknown preview format: %x",
__FUNCTION__, format);
fmt = NULL;
break;
}
return fmt;
}
} // namespace android