/*
* Copyright (C) Texas Instruments - http://www.ti.com/
*
* 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.
*/
/**
* @file CameraHal.cpp
*
* This file maps the Camera Hardware Interface to V4L2.
*
*/
#include "CameraHal.h"
#include "ANativeWindowDisplayAdapter.h"
#include "BufferSourceAdapter.h"
#include "TICameraParameters.h"
#include "CameraProperties.h"
#include <cutils/properties.h>
#include <poll.h>
#include <math.h>
namespace Ti {
namespace Camera {
extern "C" CameraAdapter* OMXCameraAdapter_Factory(size_t);
extern "C" CameraAdapter* V4LCameraAdapter_Factory(size_t);
/*****************************************************************************/
////Constant definitions and declarations
////@todo Have a CameraProperties class to store these parameters as constants for every camera
//// Currently, they are hard-coded
const int CameraHal::NO_BUFFERS_PREVIEW = MAX_CAMERA_BUFFERS;
const int CameraHal::NO_BUFFERS_IMAGE_CAPTURE = 5;
const int CameraHal::SW_SCALING_FPS_LIMIT = 15;
const uint32_t MessageNotifier::EVENT_BIT_FIELD_POSITION = 16;
const uint32_t MessageNotifier::FRAME_BIT_FIELD_POSITION = 0;
// TODO(XXX): Temporarily increase number of buffers we can allocate from ANW
// until faux-NPA mode is implemented
const int CameraHal::NO_BUFFERS_IMAGE_CAPTURE_SYSTEM_HEAP = 15;
#ifdef CAMERAHAL_USE_RAW_IMAGE_SAVING
// HACK: Default path to directory where RAW images coming from video port will be saved to.
// If directory not exists the saving is skipped and video port frame is ignored.
// The directory name is choosed in so weird way to enable RAW images saving only when
// directory has been created explicitly by user.
extern const char * const kRawImagesOutputDirPath = "/data/misc/camera/RaW_PiCtUrEs";
extern const char * const kYuvImagesOutputDirPath = "/data/misc/camera/YuV_PiCtUrEs";
#endif
/******************************************************************************/
#ifdef OMAP_ENHANCEMENT_CPCAM
static int dummy_update_and_get_buffer(preview_stream_ops_t*, buffer_handle_t**, int*) {
return INVALID_OPERATION;
}
static int dummy_get_buffer_dimension(preview_stream_ops_t*, int*, int*) {
return INVALID_OPERATION;
}
static int dummy_get_buffer_format(preview_stream_ops_t*, int*) {
return INVALID_OPERATION;
}
static int dummy_set_metadata(preview_stream_ops_t*, const camera_memory_t*) {
return INVALID_OPERATION;
}
static int dummy_get_id(preview_stream_ops_t*, char *data, unsigned int dataSize) {
return INVALID_OPERATION;
}
static int dummy_get_buffer_count(preview_stream_ops_t*, int *count) {
return INVALID_OPERATION;
}
static int dummy_get_crop(preview_stream_ops_t*,
int *, int *, int *, int *) {
return INVALID_OPERATION;
}
static int dummy_get_current_size(preview_stream_ops_t*,
int *, int *) {
return INVALID_OPERATION;
}
#endif
#ifdef OMAP_ENHANCEMENT
static preview_stream_extended_ops_t dummyPreviewStreamExtendedOps = {
#ifdef OMAP_ENHANCEMENT_CPCAM
dummy_update_and_get_buffer,
dummy_get_buffer_dimension,
dummy_get_buffer_format,
dummy_set_metadata,
dummy_get_id,
dummy_get_buffer_count,
dummy_get_crop,
dummy_get_current_size,
#endif
};
#endif
DisplayAdapter::DisplayAdapter()
{
#ifdef OMAP_ENHANCEMENT
mExtendedOps = &dummyPreviewStreamExtendedOps;
#endif
}
#ifdef OMAP_ENHANCEMENT
void DisplayAdapter::setExtendedOps(preview_stream_extended_ops_t * extendedOps) {
mExtendedOps = extendedOps ? extendedOps : &dummyPreviewStreamExtendedOps;
}
#endif
#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
struct timeval CameraHal::mStartPreview;
struct timeval CameraHal::mStartFocus;
struct timeval CameraHal::mStartCapture;
#endif
static void orientation_cb(uint32_t orientation, uint32_t tilt, void* cookie) {
CameraHal *camera = NULL;
if (cookie) {
camera = (CameraHal*) cookie;
camera->onOrientationEvent(orientation, tilt);
}
}
/*-------------Camera Hal Interface Method definitions STARTS here--------------------*/
/**
Callback function to receive orientation events from SensorListener
*/
void CameraHal::onOrientationEvent(uint32_t orientation, uint32_t tilt) {
LOG_FUNCTION_NAME;
if ( NULL != mCameraAdapter ) {
mCameraAdapter->onOrientationEvent(orientation, tilt);
}
LOG_FUNCTION_NAME_EXIT;
}
/**
@brief Set the notification and data callbacks
@param[in] notify_cb Notify callback for notifying the app about events and errors
@param[in] data_cb Buffer callback for sending the preview/raw frames to the app
@param[in] data_cb_timestamp Buffer callback for sending the video frames w/ timestamp
@param[in] user Callback cookie
@return none
*/
void CameraHal::setCallbacks(camera_notify_callback notify_cb,
camera_data_callback data_cb,
camera_data_timestamp_callback data_cb_timestamp,
camera_request_memory get_memory,
void *user)
{
LOG_FUNCTION_NAME;
if ( NULL != mAppCallbackNotifier.get() )
{
mAppCallbackNotifier->setCallbacks(this,
notify_cb,
data_cb,
data_cb_timestamp,
get_memory,
user);
}
if ( NULL != mCameraAdapter ) {
mCameraAdapter->setSharedAllocator(get_memory);
}
LOG_FUNCTION_NAME_EXIT;
}
/**
@brief Enable a message, or set of messages.
@param[in] msgtype Bitmask of the messages to enable (defined in include/ui/Camera.h)
@return none
*/
void CameraHal::enableMsgType(int32_t msgType)
{
LOG_FUNCTION_NAME;
if ( ( msgType & CAMERA_MSG_SHUTTER ) && ( !mShutterEnabled ) )
{
msgType &= ~CAMERA_MSG_SHUTTER;
}
// ignoring enable focus message from camera service
// we will enable internally in autoFocus call
msgType &= ~CAMERA_MSG_FOCUS;
#ifdef ANDROID_API_JB_OR_LATER
msgType &= ~CAMERA_MSG_FOCUS_MOVE;
#endif
{
android::AutoMutex lock(mLock);
mMsgEnabled |= msgType;
}
if(mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)
{
if(mDisplayPaused)
{
CAMHAL_LOGDA("Preview currently paused...will enable preview callback when restarted");
msgType &= ~CAMERA_MSG_PREVIEW_FRAME;
}else
{
CAMHAL_LOGDA("Enabling Preview Callback");
}
}
else
{
CAMHAL_LOGDB("Preview callback not enabled %x", msgType);
}
///Configure app callback notifier with the message callback required
mAppCallbackNotifier->enableMsgType (msgType);
LOG_FUNCTION_NAME_EXIT;
}
/**
@brief Disable a message, or set of messages.
@param[in] msgtype Bitmask of the messages to disable (defined in include/ui/Camera.h)
@return none
*/
void CameraHal::disableMsgType(int32_t msgType)
{
LOG_FUNCTION_NAME;
{
android::AutoMutex lock(mLock);
mMsgEnabled &= ~msgType;
}
if( msgType & CAMERA_MSG_PREVIEW_FRAME)
{
CAMHAL_LOGDA("Disabling Preview Callback");
}
///Configure app callback notifier
mAppCallbackNotifier->disableMsgType (msgType);
LOG_FUNCTION_NAME_EXIT;
}
/**
@brief Query whether a message, or a set of messages, is enabled.
Note that this is operates as an AND, if any of the messages queried are off, this will
return false.
@param[in] msgtype Bitmask of the messages to query (defined in include/ui/Camera.h)
@return true If all message types are enabled
false If any message type
*/
int CameraHal::msgTypeEnabled(int32_t msgType)
{
int32_t msgEnabled = 0;
LOG_FUNCTION_NAME;
android::AutoMutex lock(mLock);
msgEnabled = mMsgEnabled;
if (!previewEnabled() && !mPreviewInitializationDone) {
msgEnabled &= ~(CAMERA_MSG_PREVIEW_FRAME | CAMERA_MSG_PREVIEW_METADATA);
}
LOG_FUNCTION_NAME_EXIT;
return (msgEnabled & msgType);
}
/**
@brief Set the camera parameters.
@param[in] params Camera parameters to configure the camera
@return NO_ERROR
@todo Define error codes
*/
int CameraHal::setParameters(const char* parameters)
{
LOG_FUNCTION_NAME;
android::CameraParameters params;
android::String8 str_params(parameters);
params.unflatten(str_params);
LOG_FUNCTION_NAME_EXIT;
return setParameters(params);
}
/**
@brief Set the camera parameters.
@param[in] params Camera parameters to configure the camera
@return NO_ERROR
@todo Define error codes
*/
int CameraHal::setParameters(const android::CameraParameters& params)
{
LOG_FUNCTION_NAME;
int w, h;
int framerate;
int maxFPS, minFPS;
const char *valstr = NULL;
int varint = 0;
status_t ret = NO_ERROR;
// Needed for KEY_RECORDING_HINT
bool restartPreviewRequired = false;
bool updateRequired = false;
android::CameraParameters oldParams = mParameters;
#ifdef V4L_CAMERA_ADAPTER
if (strcmp (V4L_CAMERA_NAME_USB, mCameraProperties->get(CameraProperties::CAMERA_NAME)) == 0 ) {
updateRequired = true;
}
#endif
{
android::AutoMutex lock(mLock);
///Ensure that preview is not enabled when the below parameters are changed.
if(!previewEnabled())
{
if ((valstr = params.getPreviewFormat()) != NULL) {
if ( isParameterValid(valstr, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_FORMATS))) {
mParameters.setPreviewFormat(valstr);
CAMHAL_LOGDB("PreviewFormat set %s", valstr);
} else {
CAMHAL_LOGEB("Invalid preview format: %s. Supported: %s", valstr,
mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_FORMATS));
return BAD_VALUE;
}
}
if ((valstr = params.get(TICameraParameters::KEY_VNF)) != NULL) {
if (strcmp(mCameraProperties->get(CameraProperties::VNF_SUPPORTED),
android::CameraParameters::TRUE) == 0) {
CAMHAL_LOGDB("VNF %s", valstr);
mParameters.set(TICameraParameters::KEY_VNF, valstr);
} else if (strcmp(valstr, android::CameraParameters::TRUE) == 0) {
CAMHAL_LOGEB("ERROR: Invalid VNF: %s", valstr);
return BAD_VALUE;
} else {
mParameters.set(TICameraParameters::KEY_VNF,
android::CameraParameters::FALSE);
}
}
if ((valstr = params.get(android::CameraParameters::KEY_VIDEO_STABILIZATION)) != NULL) {
// make sure we support vstab...if we don't and application is trying to set
// vstab then return an error
if (strcmp(mCameraProperties->get(CameraProperties::VSTAB_SUPPORTED),
android::CameraParameters::TRUE) == 0) {
CAMHAL_LOGDB("VSTAB %s", valstr);
mParameters.set(android::CameraParameters::KEY_VIDEO_STABILIZATION, valstr);
} else if (strcmp(valstr, android::CameraParameters::TRUE) == 0) {
CAMHAL_LOGEB("ERROR: Invalid VSTAB: %s", valstr);
return BAD_VALUE;
} else {
mParameters.set(android::CameraParameters::KEY_VIDEO_STABILIZATION,
android::CameraParameters::FALSE);
}
}
if( (valstr = params.get(TICameraParameters::KEY_CAP_MODE)) != NULL) {
if (strcmp(TICameraParameters::VIDEO_MODE, valstr)) {
mCapModeBackup = valstr;
}
CAMHAL_LOGDB("Capture mode set %s", valstr);
const char *currentMode = mParameters.get(TICameraParameters::KEY_CAP_MODE);
if ( NULL != currentMode ) {
if ( strcmp(currentMode, valstr) != 0 ) {
updateRequired = true;
}
} else {
updateRequired = true;
}
mParameters.set(TICameraParameters::KEY_CAP_MODE, valstr);
} else if (!mCapModeBackup.isEmpty()) {
// Restore previous capture mode after stopPreview()
mParameters.set(TICameraParameters::KEY_CAP_MODE,
mCapModeBackup.string());
updateRequired = true;
}
#ifdef OMAP_ENHANCEMENT_VTC
if ((valstr = params.get(TICameraParameters::KEY_VTC_HINT)) != NULL ) {
mParameters.set(TICameraParameters::KEY_VTC_HINT, valstr);
if (strcmp(valstr, android::CameraParameters::TRUE) == 0) {
mVTCUseCase = true;
} else {
mVTCUseCase = false;
}
CAMHAL_LOGDB("VTC Hint = %d", mVTCUseCase);
}
if (mVTCUseCase) {
if ((valstr = params.get(TICameraParameters::KEY_VIDEO_ENCODER_HANDLE)) != NULL ) {
mParameters.set(TICameraParameters::KEY_VIDEO_ENCODER_HANDLE, valstr);
}
if ((valstr = params.get(TICameraParameters::KEY_VIDEO_ENCODER_SLICE_HEIGHT)) != NULL ) {
mParameters.set(TICameraParameters::KEY_VIDEO_ENCODER_SLICE_HEIGHT, valstr);
}
}
#endif
}
if ((valstr = params.get(TICameraParameters::KEY_IPP)) != NULL) {
if (isParameterValid(valstr,mCameraProperties->get(CameraProperties::SUPPORTED_IPP_MODES))) {
if ((mParameters.get(TICameraParameters::KEY_IPP) == NULL) ||
(strcmp(valstr, mParameters.get(TICameraParameters::KEY_IPP)))) {
CAMHAL_LOGDB("IPP mode set %s", params.get(TICameraParameters::KEY_IPP));
mParameters.set(TICameraParameters::KEY_IPP, valstr);
restartPreviewRequired = true;
}
} else {
CAMHAL_LOGEB("ERROR: Invalid IPP mode: %s", valstr);
return BAD_VALUE;
}
}
if ( (valstr = params.get(TICameraParameters::KEY_S3D_PRV_FRAME_LAYOUT)) != NULL )
{
if (strcmp(valstr, mParameters.get(TICameraParameters::KEY_S3D_PRV_FRAME_LAYOUT)))
{
CAMHAL_LOGDB("Stereo 3D preview image layout is %s", valstr);
mParameters.set(TICameraParameters::KEY_S3D_PRV_FRAME_LAYOUT, valstr);
restartPreviewRequired = true;
}
}
#ifdef OMAP_ENHANCEMENT
int orientation =0;
if((valstr = params.get(TICameraParameters::KEY_SENSOR_ORIENTATION)) != NULL)
{
doesSetParameterNeedUpdate(valstr,
mParameters.get(TICameraParameters::KEY_SENSOR_ORIENTATION),
updateRequired);
orientation = params.getInt(TICameraParameters::KEY_SENSOR_ORIENTATION);
if ( orientation < 0 || orientation >= 360 || (orientation%90) != 0 ) {
CAMHAL_LOGE("Invalid sensor orientation: %s. Value must be one of: [0, 90, 180, 270]", valstr);
return BAD_VALUE;
}
CAMHAL_LOGD("Sensor Orientation is set to %d", orientation);
mParameters.set(TICameraParameters::KEY_SENSOR_ORIENTATION, valstr);
}
#endif
params.getPreviewSize(&w, &h);
if (w == -1 && h == -1) {
CAMHAL_LOGEA("Unable to get preview size");
return BAD_VALUE;
}
mVideoWidth = w;
mVideoHeight = h;
// Handle RECORDING_HINT to Set/Reset Video Mode Parameters
valstr = params.get(android::CameraParameters::KEY_RECORDING_HINT);
if(valstr != NULL)
{
CAMHAL_LOGDB("Recording Hint is set to %s", valstr);
if(strcmp(valstr, android::CameraParameters::TRUE) == 0)
{
CAMHAL_LOGVB("Video Resolution: %d x %d", mVideoWidth, mVideoHeight);
#ifdef OMAP_ENHANCEMENT_VTC
if (!mVTCUseCase)
#endif
{
int maxFPS, minFPS;
params.getPreviewFpsRange(&minFPS, &maxFPS);
maxFPS /= CameraHal::VFR_SCALE;
if ( ( maxFPS <= SW_SCALING_FPS_LIMIT ) ) {
getPreferredPreviewRes(&w, &h);
}
}
mParameters.set(android::CameraParameters::KEY_RECORDING_HINT, valstr);
restartPreviewRequired |= setVideoModeParameters(params);
}
else if(strcmp(valstr, android::CameraParameters::FALSE) == 0)
{
mParameters.set(android::CameraParameters::KEY_RECORDING_HINT, valstr);
restartPreviewRequired |= resetVideoModeParameters();
}
else
{
CAMHAL_LOGEA("Invalid RECORDING_HINT");
return BAD_VALUE;
}
}
else
{
// This check is required in following case.
// If VideoRecording activity sets KEY_RECORDING_HINT to TRUE and
// ImageCapture activity doesnot set KEY_RECORDING_HINT to FALSE (i.e. simply NULL),
// then Video Mode parameters may remain present in ImageCapture activity as well.
CAMHAL_LOGDA("Recording Hint is set to NULL");
mParameters.set(android::CameraParameters::KEY_RECORDING_HINT, "");
restartPreviewRequired |= resetVideoModeParameters();
}
if ( (!isResolutionValid(w, h, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_SIZES)))
&& (!isResolutionValid(w, h, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_SUBSAMPLED_SIZES)))
&& (!isResolutionValid(w, h, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_SIDEBYSIDE_SIZES)))
&& (!isResolutionValid(w, h, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_TOPBOTTOM_SIZES))) ) {
CAMHAL_LOGEB("Invalid preview resolution %d x %d", w, h);
return BAD_VALUE;
}
int oldWidth, oldHeight;
mParameters.getPreviewSize(&oldWidth, &oldHeight);
if ( ( oldWidth != w ) || ( oldHeight != h ) )
{
mParameters.setPreviewSize(w, h);
restartPreviewRequired = true;
}
CAMHAL_LOGDB("Preview Resolution: %d x %d", w, h);
if ((valstr = params.get(android::CameraParameters::KEY_FOCUS_MODE)) != NULL) {
if (isParameterValid(valstr, mCameraProperties->get(CameraProperties::SUPPORTED_FOCUS_MODES))) {
CAMHAL_LOGDB("Focus mode set %s", valstr);
// we need to take a decision on the capture mode based on whether CAF picture or
// video is chosen so the behavior of each is consistent to the application
if(strcmp(valstr, android::CameraParameters::FOCUS_MODE_CONTINUOUS_PICTURE) == 0){
restartPreviewRequired |= resetVideoModeParameters();
} else if (strcmp(valstr, android::CameraParameters::FOCUS_MODE_CONTINUOUS_VIDEO) == 0){
restartPreviewRequired |= setVideoModeParameters(params);
}
mParameters.set(android::CameraParameters::KEY_FOCUS_MODE, valstr);
} else {
CAMHAL_LOGEB("ERROR: Invalid FOCUS mode = %s", valstr);
return BAD_VALUE;
}
}
mRawCapture = false;
#ifdef CAMERAHAL_USE_RAW_IMAGE_SAVING
valstr = params.get(TICameraParameters::KEY_CAP_MODE);
if ( (!valstr || strcmp(valstr, TICameraParameters::HIGH_QUALITY_MODE) == 0) &&
access(kRawImagesOutputDirPath, F_OK) != -1 ) {
mRawCapture = true;
}
#endif
if ( (valstr = params.get(TICameraParameters::KEY_S3D_CAP_FRAME_LAYOUT)) != NULL )
{
CAMHAL_LOGDB("Stereo 3D capture image layout is %s", valstr);
mParameters.set(TICameraParameters::KEY_S3D_CAP_FRAME_LAYOUT, valstr);
}
params.getPictureSize(&w, &h);
if ( (isResolutionValid(w, h, mCameraProperties->get(CameraProperties::SUPPORTED_PICTURE_SIZES)))
|| (isResolutionValid(w, h, mCameraProperties->get(CameraProperties::SUPPORTED_PICTURE_SUBSAMPLED_SIZES)))
|| (isResolutionValid(w, h, mCameraProperties->get(CameraProperties::SUPPORTED_PICTURE_TOPBOTTOM_SIZES)))
|| (isResolutionValid(w, h, mCameraProperties->get(CameraProperties::SUPPORTED_PICTURE_SIDEBYSIDE_SIZES))) ) {
mParameters.setPictureSize(w, h);
} else {
CAMHAL_LOGEB("ERROR: Invalid picture resolution %d x %d", w, h);
return BAD_VALUE;
}
CAMHAL_LOGDB("Picture Size by App %d x %d", w, h);
if ( (valstr = params.getPictureFormat()) != NULL ) {
if (isParameterValid(valstr,mCameraProperties->get(CameraProperties::SUPPORTED_PICTURE_FORMATS))) {
if ((strcmp(valstr, android::CameraParameters::PIXEL_FORMAT_BAYER_RGGB) == 0) &&
mCameraProperties->get(CameraProperties::MAX_PICTURE_WIDTH) &&
mCameraProperties->get(CameraProperties::MAX_PICTURE_HEIGHT)) {
unsigned int width = 0, height = 0;
// Set picture size to full frame for raw bayer capture
width = atoi(mCameraProperties->get(CameraProperties::MAX_PICTURE_WIDTH));
height = atoi(mCameraProperties->get(CameraProperties::MAX_PICTURE_HEIGHT));
mParameters.setPictureSize(width,height);
}
mParameters.setPictureFormat(valstr);
} else {
CAMHAL_LOGEB("ERROR: Invalid picture format: %s",valstr);
ret = BAD_VALUE;
}
}
#ifdef OMAP_ENHANCEMENT_BURST_CAPTURE
if ((valstr = params.get(TICameraParameters::KEY_BURST)) != NULL) {
if (params.getInt(TICameraParameters::KEY_BURST) >=0) {
CAMHAL_LOGDB("Burst set %s", valstr);
mParameters.set(TICameraParameters::KEY_BURST, valstr);
} else {
CAMHAL_LOGEB("ERROR: Invalid Burst value: %s",valstr);
return BAD_VALUE;
}
}
#endif
// Variable framerate ranges have higher priority over
// deprecated constant FPS. "KEY_PREVIEW_FPS_RANGE" should
// be cleared by the client in order for constant FPS to get
// applied.
// If Port FPS needs to be used for configuring, then FPS RANGE should not be set by the APP.
valstr = params.get(android::CameraParameters::KEY_PREVIEW_FPS_RANGE);
if (valstr != NULL && strlen(valstr)) {
int curMaxFPS = 0;
int curMinFPS = 0;
// APP wants to set FPS range
// Set framerate = MAXFPS
CAMHAL_LOGDA("APP IS CHANGING FRAME RATE RANGE");
mParameters.getPreviewFpsRange(&curMinFPS, &curMaxFPS);
CAMHAL_LOGDB("## current minFPS = %d; maxFPS=%d",curMinFPS, curMaxFPS);
params.getPreviewFpsRange(&minFPS, &maxFPS);
CAMHAL_LOGDB("## requested minFPS = %d; maxFPS=%d",minFPS, maxFPS);
// Validate VFR
if (!isFpsRangeValid(minFPS, maxFPS, params.get(android::CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE)) &&
!isFpsRangeValid(minFPS, maxFPS, params.get(TICameraParameters::KEY_FRAMERATE_RANGES_EXT_SUPPORTED))) {
CAMHAL_LOGEA("Invalid FPS Range");
return BAD_VALUE;
} else {
framerate = maxFPS / CameraHal::VFR_SCALE;
mParameters.setPreviewFrameRate(framerate);
CAMHAL_LOGDB("SET FRAMERATE %d", framerate);
mParameters.set(android::CameraParameters::KEY_PREVIEW_FPS_RANGE, valstr);
CAMHAL_LOGDB("FPS Range = %s", valstr);
if ( curMaxFPS == (FRAME_RATE_HIGH_HD * CameraHal::VFR_SCALE) &&
maxFPS < (FRAME_RATE_HIGH_HD * CameraHal::VFR_SCALE) ) {
restartPreviewRequired = true;
}
}
} else {
framerate = params.getPreviewFrameRate();
if (!isParameterValid(framerate, params.get(android::CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES)) &&
!isParameterValid(framerate, params.get(TICameraParameters::KEY_FRAMERATES_EXT_SUPPORTED))) {
CAMHAL_LOGEA("Invalid frame rate");
return BAD_VALUE;
}
char tmpBuffer[MAX_PROP_VALUE_LENGTH];
sprintf(tmpBuffer, "%d,%d", framerate * CameraHal::VFR_SCALE, framerate * CameraHal::VFR_SCALE);
mParameters.setPreviewFrameRate(framerate);
CAMHAL_LOGDB("SET FRAMERATE %d", framerate);
mParameters.set(android::CameraParameters::KEY_PREVIEW_FPS_RANGE, tmpBuffer);
CAMHAL_LOGDB("FPS Range = %s", tmpBuffer);
}
if ((valstr = params.get(TICameraParameters::KEY_GBCE)) != NULL) {
if (strcmp(mCameraProperties->get(CameraProperties::SUPPORTED_GBCE),
android::CameraParameters::TRUE) == 0) {
CAMHAL_LOGDB("GBCE %s", valstr);
mParameters.set(TICameraParameters::KEY_GBCE, valstr);
} else if (strcmp(valstr, android::CameraParameters::TRUE) == 0) {
CAMHAL_LOGEB("ERROR: Invalid GBCE: %s", valstr);
return BAD_VALUE;
} else {
mParameters.set(TICameraParameters::KEY_GBCE, android::CameraParameters::FALSE);
}
} else {
mParameters.set(TICameraParameters::KEY_GBCE, android::CameraParameters::FALSE);
}
if ((valstr = params.get(TICameraParameters::KEY_GLBCE)) != NULL) {
if (strcmp(mCameraProperties->get(CameraProperties::SUPPORTED_GLBCE),
android::CameraParameters::TRUE) == 0) {
CAMHAL_LOGDB("GLBCE %s", valstr);
mParameters.set(TICameraParameters::KEY_GLBCE, valstr);
} else if (strcmp(valstr, android::CameraParameters::TRUE) == 0) {
CAMHAL_LOGEB("ERROR: Invalid GLBCE: %s", valstr);
return BAD_VALUE;
} else {
mParameters.set(TICameraParameters::KEY_GLBCE, android::CameraParameters::FALSE);
}
} else {
mParameters.set(TICameraParameters::KEY_GLBCE, android::CameraParameters::FALSE);
}
#ifdef OMAP_ENHANCEMENT_S3D
///Update the current parameter set
if ( (valstr = params.get(TICameraParameters::KEY_AUTOCONVERGENCE_MODE)) != NULL ) {
CAMHAL_LOGDB("AutoConvergence mode set = %s", valstr);
mParameters.set(TICameraParameters::KEY_AUTOCONVERGENCE_MODE, valstr);
}
if ( (valstr = params.get(TICameraParameters::KEY_MANUAL_CONVERGENCE)) != NULL ) {
int manualConvergence = (int)strtol(valstr, 0, 0);
if ( ( manualConvergence < strtol(mCameraProperties->get(CameraProperties::SUPPORTED_MANUAL_CONVERGENCE_MIN), 0, 0) ) ||
( manualConvergence > strtol(mCameraProperties->get(CameraProperties::SUPPORTED_MANUAL_CONVERGENCE_MAX), 0, 0) ) ) {
CAMHAL_LOGEB("ERROR: Invalid Manual Convergence = %d", manualConvergence);
return BAD_VALUE;
} else {
CAMHAL_LOGDB("ManualConvergence Value = %d", manualConvergence);
mParameters.set(TICameraParameters::KEY_MANUAL_CONVERGENCE, valstr);
}
}
if((valstr = params.get(TICameraParameters::KEY_MECHANICAL_MISALIGNMENT_CORRECTION)) != NULL) {
if ( strcmp(mCameraProperties->get(CameraProperties::MECHANICAL_MISALIGNMENT_CORRECTION_SUPPORTED),
android::CameraParameters::TRUE) == 0 ) {
CAMHAL_LOGDB("Mechanical Mialignment Correction is %s", valstr);
mParameters.set(TICameraParameters::KEY_MECHANICAL_MISALIGNMENT_CORRECTION, valstr);
} else {
mParameters.remove(TICameraParameters::KEY_MECHANICAL_MISALIGNMENT_CORRECTION);
}
}
if ((valstr = params.get(TICameraParameters::KEY_EXPOSURE_MODE)) != NULL) {
if (isParameterValid(valstr, mCameraProperties->get(CameraProperties::SUPPORTED_EXPOSURE_MODES))) {
CAMHAL_LOGDB("Exposure mode set = %s", valstr);
mParameters.set(TICameraParameters::KEY_EXPOSURE_MODE, valstr);
if (!strcmp(valstr, TICameraParameters::EXPOSURE_MODE_MANUAL)) {
int manualVal;
if ((valstr = params.get(TICameraParameters::KEY_MANUAL_EXPOSURE)) != NULL) {
manualVal = params.getInt(TICameraParameters::KEY_MANUAL_EXPOSURE);
if (manualVal < mParameters.getInt(TICameraParameters::KEY_SUPPORTED_MANUAL_EXPOSURE_MIN) ||
manualVal > mParameters.getInt(TICameraParameters::KEY_SUPPORTED_MANUAL_EXPOSURE_MAX)) {
CAMHAL_LOGEB("ERROR: Manual Exposure = %s is out of range - "
"setting minimum supported value", valstr);
valstr = mParameters.get(TICameraParameters::KEY_SUPPORTED_MANUAL_EXPOSURE_MIN);
}
CAMHAL_LOGDB("Manual Exposure = %s", valstr);
mParameters.set(TICameraParameters::KEY_MANUAL_EXPOSURE, valstr);
}
if ((valstr = params.get(TICameraParameters::KEY_MANUAL_EXPOSURE_RIGHT)) != NULL) {
manualVal = params.getInt(TICameraParameters::KEY_MANUAL_EXPOSURE_RIGHT);
if (manualVal < mParameters.getInt(TICameraParameters::KEY_SUPPORTED_MANUAL_EXPOSURE_MIN) ||
manualVal > mParameters.getInt(TICameraParameters::KEY_SUPPORTED_MANUAL_EXPOSURE_MAX)) {
CAMHAL_LOGEB("ERROR: Manual Exposure right = %s is out of range - "
"setting minimum supported value", valstr);
valstr = mParameters.get(TICameraParameters::KEY_SUPPORTED_MANUAL_EXPOSURE_MIN);
}
CAMHAL_LOGDB("Manual Exposure right = %s", valstr);
mParameters.set(TICameraParameters::KEY_MANUAL_EXPOSURE_RIGHT, valstr);
}
if ((valstr = params.get(TICameraParameters::KEY_MANUAL_GAIN_ISO)) != NULL) {
manualVal = params.getInt(TICameraParameters::KEY_MANUAL_GAIN_ISO);
if (manualVal < mParameters.getInt(TICameraParameters::KEY_SUPPORTED_MANUAL_GAIN_ISO_MIN) ||
manualVal > mParameters.getInt(TICameraParameters::KEY_SUPPORTED_MANUAL_GAIN_ISO_MAX)) {
CAMHAL_LOGEB("ERROR: Manual Gain = %s is out of range - "
"setting minimum supported value", valstr);
valstr = mParameters.get(TICameraParameters::KEY_SUPPORTED_MANUAL_GAIN_ISO_MIN);
}
CAMHAL_LOGDB("Manual Gain = %s", valstr);
mParameters.set(TICameraParameters::KEY_MANUAL_GAIN_ISO, valstr);
}
if ((valstr = params.get(TICameraParameters::KEY_MANUAL_GAIN_ISO_RIGHT)) != NULL) {
manualVal = params.getInt(TICameraParameters::KEY_MANUAL_GAIN_ISO_RIGHT);
if (manualVal < mParameters.getInt(TICameraParameters::KEY_SUPPORTED_MANUAL_GAIN_ISO_MIN) ||
manualVal > mParameters.getInt(TICameraParameters::KEY_SUPPORTED_MANUAL_GAIN_ISO_MAX)) {
CAMHAL_LOGEB("ERROR: Manual Gain right = %s is out of range - "
"setting minimum supported value", valstr);
valstr = mParameters.get(TICameraParameters::KEY_SUPPORTED_MANUAL_GAIN_ISO_MIN);
}
CAMHAL_LOGDB("Manual Gain right = %s", valstr);
mParameters.set(TICameraParameters::KEY_MANUAL_GAIN_ISO_RIGHT, valstr);
}
}
} else {
CAMHAL_LOGEB("ERROR: Invalid Exposure mode = %s", valstr);
return BAD_VALUE;
}
}
#endif
if ((valstr = params.get(android::CameraParameters::KEY_WHITE_BALANCE)) != NULL) {
if ( isParameterValid(valstr, mCameraProperties->get(CameraProperties::SUPPORTED_WHITE_BALANCE))) {
CAMHAL_LOGDB("White balance set %s", valstr);
mParameters.set(android::CameraParameters::KEY_WHITE_BALANCE, valstr);
} else {
CAMHAL_LOGEB("ERROR: Invalid white balance = %s", valstr);
return BAD_VALUE;
}
}
#ifdef OMAP_ENHANCEMENT
if ((valstr = params.get(TICameraParameters::KEY_CONTRAST)) != NULL) {
if (params.getInt(TICameraParameters::KEY_CONTRAST) >= 0 ) {
CAMHAL_LOGDB("Contrast set %s", valstr);
mParameters.set(TICameraParameters::KEY_CONTRAST, valstr);
} else {
CAMHAL_LOGEB("ERROR: Invalid Contrast = %s", valstr);
return BAD_VALUE;
}
}
if ((valstr =params.get(TICameraParameters::KEY_SHARPNESS)) != NULL) {
if (params.getInt(TICameraParameters::KEY_SHARPNESS) >= 0 ) {
CAMHAL_LOGDB("Sharpness set %s", valstr);
mParameters.set(TICameraParameters::KEY_SHARPNESS, valstr);
} else {
CAMHAL_LOGEB("ERROR: Invalid Sharpness = %s", valstr);
return BAD_VALUE;
}
}
if ((valstr = params.get(TICameraParameters::KEY_SATURATION)) != NULL) {
if (params.getInt(TICameraParameters::KEY_SATURATION) >= 0 ) {
CAMHAL_LOGDB("Saturation set %s", valstr);
mParameters.set(TICameraParameters::KEY_SATURATION, valstr);
} else {
CAMHAL_LOGEB("ERROR: Invalid Saturation = %s", valstr);
return BAD_VALUE;
}
}
if ((valstr = params.get(TICameraParameters::KEY_BRIGHTNESS)) != NULL) {
if (params.getInt(TICameraParameters::KEY_BRIGHTNESS) >= 0 ) {
CAMHAL_LOGDB("Brightness set %s", valstr);
mParameters.set(TICameraParameters::KEY_BRIGHTNESS, valstr);
} else {
CAMHAL_LOGEB("ERROR: Invalid Brightness = %s", valstr);
return BAD_VALUE;
}
}
#endif
if ((valstr = params.get(android::CameraParameters::KEY_ANTIBANDING)) != NULL) {
if (isParameterValid(valstr, mCameraProperties->get(CameraProperties::SUPPORTED_ANTIBANDING))) {
CAMHAL_LOGDB("Antibanding set %s", valstr);
mParameters.set(android::CameraParameters::KEY_ANTIBANDING, valstr);
} else {
CAMHAL_LOGEB("ERROR: Invalid Antibanding = %s", valstr);
return BAD_VALUE;
}
}
#ifdef OMAP_ENHANCEMENT
if ((valstr = params.get(TICameraParameters::KEY_ISO)) != NULL) {
if (isParameterValid(valstr, mCameraProperties->get(CameraProperties::SUPPORTED_ISO_VALUES))) {
CAMHAL_LOGDB("ISO set %s", valstr);
mParameters.set(TICameraParameters::KEY_ISO, valstr);
} else {
CAMHAL_LOGEB("ERROR: Invalid ISO = %s", valstr);
return BAD_VALUE;
}
}
#endif
if( (valstr = params.get(android::CameraParameters::KEY_FOCUS_AREAS)) != NULL )
{
CAMHAL_LOGDB("Focus areas position set %s", params.get(android::CameraParameters::KEY_FOCUS_AREAS));
mParameters.set(android::CameraParameters::KEY_FOCUS_AREAS, valstr);
}
#ifdef OMAP_ENHANCEMENT
if( (valstr = params.get(TICameraParameters::KEY_MEASUREMENT_ENABLE)) != NULL )
{
CAMHAL_LOGDB("Measurements set to %s", valstr);
mParameters.set(TICameraParameters::KEY_MEASUREMENT_ENABLE, valstr);
if (strcmp(valstr, android::CameraParameters::TRUE) == 0)
{
mMeasurementEnabled = true;
}
else if (strcmp(valstr, android::CameraParameters::FALSE) == 0)
{
mMeasurementEnabled = false;
}
else
{
mMeasurementEnabled = false;
}
}
#endif
if( (valstr = params.get(android::CameraParameters::KEY_EXPOSURE_COMPENSATION)) != NULL)
{
CAMHAL_LOGDB("Exposure compensation set %s", params.get(android::CameraParameters::KEY_EXPOSURE_COMPENSATION));
mParameters.set(android::CameraParameters::KEY_EXPOSURE_COMPENSATION, valstr);
}
if ((valstr = params.get(android::CameraParameters::KEY_SCENE_MODE)) != NULL) {
if (isParameterValid(valstr, mCameraProperties->get(CameraProperties::SUPPORTED_SCENE_MODES))) {
CAMHAL_LOGDB("Scene mode set %s", valstr);
doesSetParameterNeedUpdate(valstr,
mParameters.get(android::CameraParameters::KEY_SCENE_MODE),
updateRequired);
mParameters.set(android::CameraParameters::KEY_SCENE_MODE, valstr);
} else {
CAMHAL_LOGEB("ERROR: Invalid Scene mode = %s", valstr);
return BAD_VALUE;
}
}
if ((valstr = params.get(android::CameraParameters::KEY_FLASH_MODE)) != NULL) {
if (isParameterValid(valstr, mCameraProperties->get(CameraProperties::SUPPORTED_FLASH_MODES))) {
CAMHAL_LOGDB("Flash mode set %s", valstr);
mParameters.set(android::CameraParameters::KEY_FLASH_MODE, valstr);
} else {
CAMHAL_LOGEB("ERROR: Invalid Flash mode = %s", valstr);
return BAD_VALUE;
}
}
if ((valstr = params.get(android::CameraParameters::KEY_EFFECT)) != NULL) {
if (isParameterValid(valstr, mCameraProperties->get(CameraProperties::SUPPORTED_EFFECTS))) {
CAMHAL_LOGDB("Effect set %s", valstr);
mParameters.set(android::CameraParameters::KEY_EFFECT, valstr);
} else {
CAMHAL_LOGEB("ERROR: Invalid Effect = %s", valstr);
return BAD_VALUE;
}
}
varint = params.getInt(android::CameraParameters::KEY_ROTATION);
if ( varint >= 0 ) {
CAMHAL_LOGDB("Rotation set %d", varint);
mParameters.set(android::CameraParameters::KEY_ROTATION, varint);
}
varint = params.getInt(android::CameraParameters::KEY_JPEG_QUALITY);
if ( varint >= 0 ) {
CAMHAL_LOGDB("Jpeg quality set %d", varint);
mParameters.set(android::CameraParameters::KEY_JPEG_QUALITY, varint);
}
varint = params.getInt(android::CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH);
if ( varint >= 0 ) {
CAMHAL_LOGDB("Thumbnail width set %d", varint);
mParameters.set(android::CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, varint);
}
varint = params.getInt(android::CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT);
if ( varint >= 0 ) {
CAMHAL_LOGDB("Thumbnail width set %d", varint);
mParameters.set(android::CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, varint);
}
varint = params.getInt(android::CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY);
if ( varint >= 0 ) {
CAMHAL_LOGDB("Thumbnail quality set %d", varint);
mParameters.set(android::CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, varint);
}
if( (valstr = params.get(android::CameraParameters::KEY_GPS_LATITUDE)) != NULL )
{
CAMHAL_LOGDB("GPS latitude set %s", params.get(android::CameraParameters::KEY_GPS_LATITUDE));
mParameters.set(android::CameraParameters::KEY_GPS_LATITUDE, valstr);
}else{
mParameters.remove(android::CameraParameters::KEY_GPS_LATITUDE);
}
if( (valstr = params.get(android::CameraParameters::KEY_GPS_LONGITUDE)) != NULL )
{
CAMHAL_LOGDB("GPS longitude set %s", params.get(android::CameraParameters::KEY_GPS_LONGITUDE));
mParameters.set(android::CameraParameters::KEY_GPS_LONGITUDE, valstr);
}else{
mParameters.remove(android::CameraParameters::KEY_GPS_LONGITUDE);
}
if( (valstr = params.get(android::CameraParameters::KEY_GPS_ALTITUDE)) != NULL )
{
CAMHAL_LOGDB("GPS altitude set %s", params.get(android::CameraParameters::KEY_GPS_ALTITUDE));
mParameters.set(android::CameraParameters::KEY_GPS_ALTITUDE, valstr);
}else{
mParameters.remove(android::CameraParameters::KEY_GPS_ALTITUDE);
}
if( (valstr = params.get(android::CameraParameters::KEY_GPS_TIMESTAMP)) != NULL )
{
CAMHAL_LOGDB("GPS timestamp set %s", params.get(android::CameraParameters::KEY_GPS_TIMESTAMP));
mParameters.set(android::CameraParameters::KEY_GPS_TIMESTAMP, valstr);
}else{
mParameters.remove(android::CameraParameters::KEY_GPS_TIMESTAMP);
}
if( (valstr = params.get(TICameraParameters::KEY_GPS_DATESTAMP)) != NULL )
{
CAMHAL_LOGDB("GPS datestamp set %s", valstr);
mParameters.set(TICameraParameters::KEY_GPS_DATESTAMP, valstr);
}else{
mParameters.remove(TICameraParameters::KEY_GPS_DATESTAMP);
}
if( (valstr = params.get(android::CameraParameters::KEY_GPS_PROCESSING_METHOD)) != NULL )
{
CAMHAL_LOGDB("GPS processing method set %s", params.get(android::CameraParameters::KEY_GPS_PROCESSING_METHOD));
mParameters.set(android::CameraParameters::KEY_GPS_PROCESSING_METHOD, valstr);
}else{
mParameters.remove(android::CameraParameters::KEY_GPS_PROCESSING_METHOD);
}
if( (valstr = params.get(TICameraParameters::KEY_GPS_MAPDATUM )) != NULL )
{
CAMHAL_LOGDB("GPS MAPDATUM set %s", valstr);
mParameters.set(TICameraParameters::KEY_GPS_MAPDATUM, valstr);
}else{
mParameters.remove(TICameraParameters::KEY_GPS_MAPDATUM);
}
if( (valstr = params.get(TICameraParameters::KEY_GPS_VERSION)) != NULL )
{
CAMHAL_LOGDB("GPS MAPDATUM set %s", valstr);
mParameters.set(TICameraParameters::KEY_GPS_VERSION, valstr);
}else{
mParameters.remove(TICameraParameters::KEY_GPS_VERSION);
}
if( (valstr = params.get(TICameraParameters::KEY_EXIF_MODEL)) != NULL )
{
CAMHAL_LOGDB("EXIF Model set %s", valstr);
mParameters.set(TICameraParameters::KEY_EXIF_MODEL, valstr);
}
if( (valstr = params.get(TICameraParameters::KEY_EXIF_MAKE)) != NULL )
{
CAMHAL_LOGDB("EXIF Make set %s", valstr);
mParameters.set(TICameraParameters::KEY_EXIF_MAKE, valstr);
}
#ifdef OMAP_ENHANCEMENT
if( (valstr = params.get(TICameraParameters::KEY_EXP_BRACKETING_RANGE)) != NULL )
{
CAMHAL_LOGDB("Exposure Bracketing set %s", params.get(TICameraParameters::KEY_EXP_BRACKETING_RANGE));
mParameters.set(TICameraParameters::KEY_EXP_BRACKETING_RANGE, valstr);
mParameters.remove(TICameraParameters::KEY_EXP_GAIN_BRACKETING_RANGE);
}
else if ((valstr = params.get(TICameraParameters::KEY_EXP_GAIN_BRACKETING_RANGE)) != NULL) {
CAMHAL_LOGDB("ABS Exposure+Gain Bracketing set %s", params.get(TICameraParameters::KEY_EXP_GAIN_BRACKETING_RANGE));
mParameters.set(TICameraParameters::KEY_EXP_GAIN_BRACKETING_RANGE, valstr);
mParameters.remove(TICameraParameters::KEY_EXP_BRACKETING_RANGE);
} else
{
mParameters.remove(TICameraParameters::KEY_EXP_BRACKETING_RANGE);
}
if( (valstr = params.get(TICameraParameters::KEY_ZOOM_BRACKETING_RANGE)) != NULL ) {
CAMHAL_LOGDB("Zoom Bracketing range %s", valstr);
mParameters.set(TICameraParameters::KEY_ZOOM_BRACKETING_RANGE, valstr);
} else {
mParameters.remove(TICameraParameters::KEY_ZOOM_BRACKETING_RANGE);
}
#endif
if ((valstr = params.get(android::CameraParameters::KEY_ZOOM)) != NULL ) {
varint = atoi(valstr);
if ( varint >= 0 && varint <= mMaxZoomSupported ) {
CAMHAL_LOGDB("Zoom set %d", varint);
doesSetParameterNeedUpdate(valstr,
mParameters.get(android::CameraParameters::KEY_ZOOM),
updateRequired);
mParameters.set(android::CameraParameters::KEY_ZOOM, valstr);
} else {
CAMHAL_LOGEB("ERROR: Invalid Zoom: %s", valstr);
return BAD_VALUE;
}
}
if( (valstr = params.get(android::CameraParameters::KEY_AUTO_EXPOSURE_LOCK)) != NULL )
{
CAMHAL_LOGDB("Auto Exposure Lock set %s", valstr);
doesSetParameterNeedUpdate(valstr,
mParameters.get(android::CameraParameters::KEY_AUTO_EXPOSURE_LOCK),
updateRequired);
mParameters.set(android::CameraParameters::KEY_AUTO_EXPOSURE_LOCK, valstr);
}
if( (valstr = params.get(android::CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK)) != NULL )
{
CAMHAL_LOGDB("Auto WhiteBalance Lock set %s", valstr);
doesSetParameterNeedUpdate(valstr,
mParameters.get(android::CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK),
updateRequired);
mParameters.set(android::CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK, valstr);
}
if( (valstr = params.get(android::CameraParameters::KEY_METERING_AREAS)) != NULL )
{
CAMHAL_LOGDB("Metering areas position set %s", params.get(android::CameraParameters::KEY_METERING_AREAS));
mParameters.set(android::CameraParameters::KEY_METERING_AREAS, valstr);
}
if( (valstr = params.get(TICameraParameters::RAW_WIDTH)) != NULL ) {
CAMHAL_LOGDB("Raw image width set %s", params.get(TICameraParameters::RAW_WIDTH));
mParameters.set(TICameraParameters::RAW_WIDTH, valstr);
}
if( (valstr = params.get(TICameraParameters::RAW_HEIGHT)) != NULL ) {
CAMHAL_LOGDB("Raw image height set %s", params.get(TICameraParameters::RAW_HEIGHT));
mParameters.set(TICameraParameters::RAW_HEIGHT, valstr);
}
//TI extensions for enable/disable algos
if( (valstr = params.get(TICameraParameters::KEY_ALGO_EXTERNAL_GAMMA)) != NULL )
{
CAMHAL_LOGDB("External Gamma set %s", valstr);
mParameters.set(TICameraParameters::KEY_ALGO_EXTERNAL_GAMMA, valstr);
}
if( (valstr = params.get(TICameraParameters::KEY_ALGO_NSF1)) != NULL )
{
CAMHAL_LOGDB("NSF1 set %s", valstr);
mParameters.set(TICameraParameters::KEY_ALGO_NSF1, valstr);
}
if( (valstr = params.get(TICameraParameters::KEY_ALGO_NSF2)) != NULL )
{
CAMHAL_LOGDB("NSF2 set %s", valstr);
mParameters.set(TICameraParameters::KEY_ALGO_NSF2, valstr);
}
if( (valstr = params.get(TICameraParameters::KEY_ALGO_SHARPENING)) != NULL )
{
CAMHAL_LOGDB("Sharpening set %s", valstr);
mParameters.set(TICameraParameters::KEY_ALGO_SHARPENING, valstr);
}
if( (valstr = params.get(TICameraParameters::KEY_ALGO_THREELINCOLORMAP)) != NULL )
{
CAMHAL_LOGDB("Color Conversion set %s", valstr);
mParameters.set(TICameraParameters::KEY_ALGO_THREELINCOLORMAP, valstr);
}
if( (valstr = params.get(TICameraParameters::KEY_ALGO_GIC)) != NULL )
{
CAMHAL_LOGDB("Green Inballance Correction set %s", valstr);
mParameters.set(TICameraParameters::KEY_ALGO_GIC, valstr);
}
if( (valstr = params.get(TICameraParameters::KEY_GAMMA_TABLE)) != NULL )
{
CAMHAL_LOGDB("Manual gamma table set %s", valstr);
mParameters.set(TICameraParameters::KEY_GAMMA_TABLE, valstr);
}
android::CameraParameters adapterParams = mParameters;
#ifdef OMAP_ENHANCEMENT
if( NULL != params.get(TICameraParameters::KEY_TEMP_BRACKETING_RANGE_POS) )
{
int posBracketRange = params.getInt(TICameraParameters::KEY_TEMP_BRACKETING_RANGE_POS);
if ( 0 < posBracketRange )
{
mBracketRangePositive = posBracketRange;
}
}
CAMHAL_LOGDB("Positive bracketing range %d", mBracketRangePositive);
if( NULL != params.get(TICameraParameters::KEY_TEMP_BRACKETING_RANGE_NEG) )
{
int negBracketRange = params.getInt(TICameraParameters::KEY_TEMP_BRACKETING_RANGE_NEG);
if ( 0 < negBracketRange )
{
mBracketRangeNegative = negBracketRange;
}
}
CAMHAL_LOGDB("Negative bracketing range %d", mBracketRangeNegative);
if( ( (valstr = params.get(TICameraParameters::KEY_TEMP_BRACKETING)) != NULL) &&
( strcmp(valstr, android::CameraParameters::TRUE) == 0 )) {
if ( !mBracketingEnabled ) {
CAMHAL_LOGDA("Enabling bracketing");
mBracketingEnabled = true;
} else {
CAMHAL_LOGDA("Bracketing already enabled");
}
adapterParams.set(TICameraParameters::KEY_TEMP_BRACKETING, valstr);
mParameters.set(TICameraParameters::KEY_TEMP_BRACKETING, valstr);
} else if ( ( (valstr = params.get(TICameraParameters::KEY_TEMP_BRACKETING)) != NULL ) &&
( strcmp(valstr, android::CameraParameters::FALSE) == 0 )) {
CAMHAL_LOGDA("Disabling bracketing");
adapterParams.set(TICameraParameters::KEY_TEMP_BRACKETING, valstr);
mParameters.set(TICameraParameters::KEY_TEMP_BRACKETING, valstr);
mBracketingEnabled = false;
if ( mBracketingRunning ) {
stopImageBracketing();
}
} else {
adapterParams.remove(TICameraParameters::KEY_TEMP_BRACKETING);
mParameters.remove(TICameraParameters::KEY_TEMP_BRACKETING);
}
#endif
#ifdef OMAP_ENHANCEMENT_VTC
if (mVTCUseCase && !mTunnelSetup && (mCameraAdapter != NULL) &&
((mParameters.get(TICameraParameters::KEY_VIDEO_ENCODER_HANDLE)) != NULL )&&
((mParameters.get(TICameraParameters::KEY_VIDEO_ENCODER_SLICE_HEIGHT)) != NULL )) {
uint32_t sliceHeight = mParameters.getInt(TICameraParameters::KEY_VIDEO_ENCODER_SLICE_HEIGHT);
uint32_t encoderHandle = mParameters.getInt(TICameraParameters::KEY_VIDEO_ENCODER_HANDLE);
int w, h;
mParameters.getPreviewSize(&w, &h);
status_t done = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_SETUP_TUNNEL, sliceHeight, encoderHandle, w, h);
if (done == NO_ERROR) mTunnelSetup = true;
ret |= done;
}
#endif
// Only send parameters to adapter if preview is already
// enabled or doesSetParameterNeedUpdate says so. Initial setParameters to camera adapter,
// will be called in startPreview()
// TODO(XXX): Need to identify other parameters that need update from camera adapter
if ( (NULL != mCameraAdapter) &&
(mPreviewEnabled || updateRequired) &&
(!(mPreviewEnabled && restartPreviewRequired)) ) {
ret |= mCameraAdapter->setParameters(adapterParams);
}
#ifdef OMAP_ENHANCEMENT
if( ( (valstr = params.get(TICameraParameters::KEY_SHUTTER_ENABLE)) != NULL ) &&
( strcmp(valstr, android::CameraParameters::TRUE) == 0 ))
{
CAMHAL_LOGDA("Enabling shutter sound");
mShutterEnabled = true;
mMsgEnabled |= CAMERA_MSG_SHUTTER;
mParameters.set(TICameraParameters::KEY_SHUTTER_ENABLE, valstr);
}
else if ( ( (valstr = params.get(TICameraParameters::KEY_SHUTTER_ENABLE)) != NULL ) &&
( strcmp(valstr, android::CameraParameters::FALSE) == 0 ))
{
CAMHAL_LOGDA("Disabling shutter sound");
mShutterEnabled = false;
mMsgEnabled &= ~CAMERA_MSG_SHUTTER;
mParameters.set(TICameraParameters::KEY_SHUTTER_ENABLE, valstr);
}
#endif
}
//On fail restore old parameters
if ( NO_ERROR != ret ) {
mParameters = oldParams;
}
// Restart Preview if needed by KEY_RECODING_HINT only if preview is already running.
// If preview is not started yet, Video Mode parameters will take effect on next startPreview()
if (restartPreviewRequired && previewEnabled() && !mRecordingEnabled) {
CAMHAL_LOGDA("Restarting Preview");
ret = restartPreview();
} else if (restartPreviewRequired && !previewEnabled() &&
mDisplayPaused && !mRecordingEnabled) {
CAMHAL_LOGDA("Restarting preview in paused mode");
ret = restartPreview();
// TODO(XXX): If there is some delay between the restartPreview call and the code
// below, then the user could see some preview frames and callbacks. Let's find
// a better place to put this later...
if (ret == NO_ERROR) {
mDisplayPaused = true;
mPreviewEnabled = false;
ret = mDisplayAdapter->pauseDisplay(mDisplayPaused);
}
}
if ( !mBracketingRunning && mBracketingEnabled ) {
startImageBracketing();
}
if (ret != NO_ERROR)
{
CAMHAL_LOGEA("Failed to restart Preview");
return ret;
}
LOG_FUNCTION_NAME_EXIT;
return ret;
}
status_t CameraHal::allocPreviewBufs(int width, int height, const char* previewFormat,
unsigned int buffercount, unsigned int &max_queueable)
{
status_t ret = NO_ERROR;
LOG_FUNCTION_NAME;
if(mDisplayAdapter.get() == NULL)
{
// Memory allocation of preview buffers is now placed in gralloc
// CameraHal should not allocate preview buffers without DisplayAdapter
return NO_MEMORY;
}
if(!mPreviewBuffers)
{
mPreviewLength = 0;
mPreviewBuffers = mDisplayAdapter->allocateBufferList(width, height,
previewFormat,
mPreviewLength,
buffercount);
if (NULL == mPreviewBuffers ) {
CAMHAL_LOGEA("Couldn't allocate preview buffers");
return NO_MEMORY;
}
mPreviewOffsets = (uint32_t *) mDisplayAdapter->getOffsets();
if ( NULL == mPreviewOffsets ) {
CAMHAL_LOGEA("Buffer mapping failed");
return BAD_VALUE;
}
mBufProvider = (BufferProvider*) mDisplayAdapter.get();
ret = mDisplayAdapter->maxQueueableBuffers(max_queueable);
if (ret != NO_ERROR) {
return ret;
}
}
LOG_FUNCTION_NAME_EXIT;
return ret;
}
status_t CameraHal::freePreviewBufs()
{
status_t ret = NO_ERROR;
LOG_FUNCTION_NAME;
CAMHAL_LOGDB("mPreviewBuffers = %p", mPreviewBuffers);
if(mPreviewBuffers)
{
ret = mBufProvider->freeBufferList(mPreviewBuffers);
mPreviewBuffers = NULL;
LOG_FUNCTION_NAME_EXIT;
return ret;
}
LOG_FUNCTION_NAME_EXIT;
return ret;
}
status_t CameraHal::allocPreviewDataBufs(size_t size, size_t bufferCount)
{
status_t ret = NO_ERROR;
int bytes;
LOG_FUNCTION_NAME;
bytes = size;
if ( NO_ERROR == ret )
{
if( NULL != mPreviewDataBuffers )
{
ret = freePreviewDataBufs();
}
}
if ( NO_ERROR == ret )
{
bytes = ((bytes+4095)/4096)*4096;
mPreviewDataBuffers = mMemoryManager->allocateBufferList(0, 0, NULL, bytes, bufferCount);
CAMHAL_LOGDB("Size of Preview data buffer = %d", bytes);
if( NULL == mPreviewDataBuffers )
{
CAMHAL_LOGEA("Couldn't allocate image buffers using memory manager");
ret = -NO_MEMORY;
}
else
{
bytes = size;
}
}
if ( NO_ERROR == ret )
{
mPreviewDataFd = mMemoryManager->getFd();
mPreviewDataLength = bytes;
mPreviewDataOffsets = mMemoryManager->getOffsets();
}
else
{
mPreviewDataFd = -1;
mPreviewDataLength = 0;
mPreviewDataOffsets = NULL;
}
LOG_FUNCTION_NAME_EXIT;
return ret;
}
status_t CameraHal::freePreviewDataBufs()
{
status_t ret = NO_ERROR;
LOG_FUNCTION_NAME;
if ( NO_ERROR == ret )
{
if( NULL != mPreviewDataBuffers )
{
ret = mMemoryManager->freeBufferList(mPreviewDataBuffers);
mPreviewDataBuffers = NULL;
}
}
LOG_FUNCTION_NAME_EXIT;
return ret;
}
status_t CameraHal::allocImageBufs(unsigned int width, unsigned int height, size_t size,
const char* previewFormat, unsigned int bufferCount)
{
status_t ret = NO_ERROR;
int bytes = size;
LOG_FUNCTION_NAME;
// allocate image buffers only if not already allocated
if(NULL != mImageBuffers) {
return NO_ERROR;
}
if ( NO_ERROR == ret ) {
bytes = ((bytes+4095)/4096)*4096;
mImageBuffers = mMemoryManager->allocateBufferList(0, 0, previewFormat, bytes, bufferCount);
CAMHAL_LOGDB("Size of Image cap buffer = %d", bytes);
if( NULL == mImageBuffers ) {
CAMHAL_LOGEA("Couldn't allocate image buffers using memory manager");
ret = -NO_MEMORY;
} else {
bytes = size;
}
}
if ( NO_ERROR == ret ) {
mImageFd = mMemoryManager->getFd();
mImageLength = bytes;
mImageOffsets = mMemoryManager->getOffsets();
mImageCount = bufferCount;
} else {
mImageFd = -1;
mImageLength = 0;
mImageOffsets = NULL;
mImageCount = 0;
}
LOG_FUNCTION_NAME_EXIT;
return ret;
}
status_t CameraHal::allocVideoBufs(uint32_t width, uint32_t height, uint32_t bufferCount)
{
status_t ret = NO_ERROR;
LOG_FUNCTION_NAME;
if( NULL != mVideoBuffers ){
ret = freeVideoBufs(mVideoBuffers);
mVideoBuffers = NULL;
}
if ( NO_ERROR == ret ){
int32_t stride;
CameraBuffer *buffers = new CameraBuffer [bufferCount];
memset (buffers, 0, sizeof(CameraBuffer) * bufferCount);
if (buffers != NULL){
for (unsigned int i = 0; i< bufferCount; i++){
android::GraphicBufferAllocator &GrallocAlloc = android::GraphicBufferAllocator::get();
buffer_handle_t handle;
ret = GrallocAlloc.alloc(width, height, HAL_PIXEL_FORMAT_NV12, CAMHAL_GRALLOC_USAGE, &handle, &stride);
if (ret != NO_ERROR){
CAMHAL_LOGEA("Couldn't allocate video buffers using Gralloc");
ret = -NO_MEMORY;
for (unsigned int j=0; j< i; j++){
CAMHAL_LOGEB("Freeing Gralloc Buffer %p", buffers[i].opaque);
GrallocAlloc.free((buffer_handle_t)buffers[i].opaque);
}
delete [] buffers;
goto exit;
}
buffers[i].type = CAMERA_BUFFER_GRALLOC;
buffers[i].opaque = (void *)handle;
CAMHAL_LOGVB("*** Gralloc Handle =0x%x ***", handle);
}
mVideoBuffers = buffers;
}
else{
CAMHAL_LOGEA("Couldn't allocate video buffers ");
ret = -NO_MEMORY;
}
}
exit:
LOG_FUNCTION_NAME_EXIT;
return ret;
}
status_t CameraHal::allocRawBufs(int width, int height, const char* previewFormat, int bufferCount)
{
status_t ret = NO_ERROR;
LOG_FUNCTION_NAME
///@todo Enhance this method allocImageBufs() to take in a flag for burst capture
///Always allocate the buffers for image capture using MemoryManager
if (NO_ERROR == ret) {
if(( NULL != mVideoBuffers )) {
// Re-use the buffer for raw capture.
return ret;
}
}
if ( NO_ERROR == ret ) {
mVideoLength = 0;
mVideoLength = (((width * height * 2) + 4095)/4096)*4096;
mVideoBuffers = mMemoryManager->allocateBufferList(width, height, previewFormat,
mVideoLength, bufferCount);
CAMHAL_LOGDB("Size of Video cap buffer (used for RAW capture) %d", mVideoLength);
if( NULL == mVideoBuffers ) {
CAMHAL_LOGEA("Couldn't allocate Video buffers using memory manager");
ret = -NO_MEMORY;
}
}
if ( NO_ERROR == ret ) {
mVideoFd = mMemoryManager->getFd();
mVideoOffsets = mMemoryManager->getOffsets();
} else {
mVideoFd = -1;
mVideoOffsets = NULL;
}
LOG_FUNCTION_NAME_EXIT;
return ret;
}
void endImageCapture( void *userData)
{
LOG_FUNCTION_NAME;
if ( NULL != userData )
{
CameraHal *c = reinterpret_cast<CameraHal *>(userData);
c->signalEndImageCapture();
}
LOG_FUNCTION_NAME_EXIT;
}
void releaseImageBuffers(void *userData)
{
LOG_FUNCTION_NAME;
if (NULL != userData) {
CameraHal *c = reinterpret_cast<CameraHal *>(userData);
c->freeImageBufs();
}
LOG_FUNCTION_NAME_EXIT;
}
status_t CameraHal::signalEndImageCapture()
{
status_t ret = NO_ERROR;
int w,h;
android::AutoMutex lock(mLock);
LOG_FUNCTION_NAME;
if (mBufferSourceAdapter_Out.get()) {
mBufferSourceAdapter_Out->disableDisplay();
}
if (mBufferSourceAdapter_In.get()) {
mBufferSourceAdapter_In->disableDisplay();
}
if ( mBracketingRunning ) {
stopImageBracketing();
} else {
mCameraAdapter->sendCommand(CameraAdapter::CAMERA_STOP_IMAGE_CAPTURE);
}
LOG_FUNCTION_NAME_EXIT;
return ret;
}
status_t CameraHal::freeImageBufs()
{
status_t ret = NO_ERROR;
LOG_FUNCTION_NAME;
if (NULL == mImageBuffers) {
return -EINVAL;
}
if (mBufferSourceAdapter_Out.get()) {
mBufferSourceAdapter_Out = 0;
} else {
ret = mMemoryManager->freeBufferList(mImageBuffers);
}
mImageBuffers = NULL;
LOG_FUNCTION_NAME_EXIT;
return ret;
}
status_t CameraHal::freeVideoBufs(CameraBuffer *bufs)
{
status_t ret = NO_ERROR;
LOG_FUNCTION_NAME;
int count = atoi(mCameraProperties->get(CameraProperties::REQUIRED_PREVIEW_BUFS));
if(bufs == NULL)
{
CAMHAL_LOGEA("NULL pointer passed to freeVideoBuffer");
LOG_FUNCTION_NAME_EXIT;
return BAD_VALUE;
}
android::GraphicBufferAllocator &GrallocAlloc = android::GraphicBufferAllocator::get();
for(int i = 0; i < count; i++){
CAMHAL_LOGVB("Free Video Gralloc Handle 0x%x", bufs[i].opaque);
GrallocAlloc.free((buffer_handle_t)bufs[i].opaque);
}
LOG_FUNCTION_NAME_EXIT;
return ret;
}
status_t CameraHal::freeRawBufs()
{
status_t ret = NO_ERROR;
LOG_FUNCTION_NAME
if ( NO_ERROR == ret ) {
if( NULL != mVideoBuffers ) {
///@todo Pluralise the name of this method to freeBuffers
ret = mMemoryManager->freeBufferList(mVideoBuffers);
mVideoBuffers = NULL;
} else {
ret = -EINVAL;
}
}
LOG_FUNCTION_NAME_EXIT
return ret;
}
/**
@brief Start preview mode.
@param none
@return NO_ERROR Camera switched to VF mode
@todo Update function header with the different errors that are possible
*/
status_t CameraHal::startPreview() {
LOG_FUNCTION_NAME;
// When tunneling is enabled during VTC, startPreview happens in 2 steps:
// When the application sends the command CAMERA_CMD_PREVIEW_INITIALIZATION,
// cameraPreviewInitialization() is called, which in turn causes the CameraAdapter
// to move from loaded to idle state. And when the application calls startPreview,
// the CameraAdapter moves from idle to executing state.
//
// If the application calls startPreview() without sending the command
// CAMERA_CMD_PREVIEW_INITIALIZATION, then the function cameraPreviewInitialization()
// AND startPreview() are executed. In other words, if the application calls
// startPreview() without sending the command CAMERA_CMD_PREVIEW_INITIALIZATION,
// then the CameraAdapter moves from loaded to idle to executing state in one shot.
status_t ret = cameraPreviewInitialization();
// The flag mPreviewInitializationDone is set to true at the end of the function
// cameraPreviewInitialization(). Therefore, if everything goes alright, then the
// flag will be set. Sometimes, the function cameraPreviewInitialization() may
// return prematurely if all the resources are not available for starting preview.
// For example, if the preview window is not set, then it would return NO_ERROR.
// Under such circumstances, one should return from startPreview as well and should
// not continue execution. That is why, we check the flag and not the return value.
if (!mPreviewInitializationDone) return ret;
// Once startPreview is called, there is no need to continue to remember whether
// the function cameraPreviewInitialization() was called earlier or not. And so
// the flag mPreviewInitializationDone is reset here. Plus, this preserves the
// current behavior of startPreview under the circumstances where the application
// calls startPreview twice or more.
mPreviewInitializationDone = false;
///Enable the display adapter if present, actual overlay enable happens when we post the buffer
if(mDisplayAdapter.get() != NULL) {
CAMHAL_LOGDA("Enabling display");
int width, height;
mParameters.getPreviewSize(&width, &height);
#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
ret = mDisplayAdapter->enableDisplay(width, height, &mStartPreview);
#else
ret = mDisplayAdapter->enableDisplay(width, height, NULL);
#endif
if ( ret != NO_ERROR ) {
CAMHAL_LOGEA("Couldn't enable display");
// FIXME: At this stage mStateSwitchLock is locked and unlock is supposed to be called
// only from mCameraAdapter->sendCommand(CameraAdapter::CAMERA_START_PREVIEW)
// below. But this will never happen because of goto error. Thus at next
// startPreview() call CameraHAL will be deadlocked.
// Need to revisit mStateSwitch lock, for now just abort the process.
CAMHAL_ASSERT_X(false,
"At this stage mCameraAdapter->mStateSwitchLock is still locked, "
"deadlock is guaranteed");
goto error;
}
}
///Send START_PREVIEW command to adapter
CAMHAL_LOGDA("Starting CameraAdapter preview mode");
ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_START_PREVIEW);
if(ret!=NO_ERROR) {
CAMHAL_LOGEA("Couldn't start preview w/ CameraAdapter");
goto error;
}
CAMHAL_LOGDA("Started preview");
mPreviewEnabled = true;
mPreviewStartInProgress = false;
return ret;
error:
CAMHAL_LOGEA("Performing cleanup after error");
//Do all the cleanup
freePreviewBufs();
mCameraAdapter->sendCommand(CameraAdapter::CAMERA_STOP_PREVIEW);
if(mDisplayAdapter.get() != NULL) {
mDisplayAdapter->disableDisplay(false);
}
mAppCallbackNotifier->stop();
mPreviewStartInProgress = false;
mPreviewEnabled = false;
LOG_FUNCTION_NAME_EXIT;
return ret;
}
////////////
/**
@brief Set preview mode related initialization
-> Camera Adapter set params
-> Allocate buffers
-> Set use buffers for preview
@param none
@return NO_ERROR
@todo Update function header with the different errors that are possible
*/
status_t CameraHal::cameraPreviewInitialization()
{
status_t ret = NO_ERROR;
CameraAdapter::BuffersDescriptor desc;
CameraFrame frame;
unsigned int required_buffer_count;
unsigned int max_queueble_buffers;
#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
gettimeofday(&mStartPreview, NULL);
#endif
LOG_FUNCTION_NAME;
if (mPreviewInitializationDone) {
return NO_ERROR;
}
if ( mPreviewEnabled ){
CAMHAL_LOGDA("Preview already running");
LOG_FUNCTION_NAME_EXIT;
return ALREADY_EXISTS;
}
if ( NULL != mCameraAdapter ) {
ret = mCameraAdapter->setParameters(mParameters);
}
if ((mPreviewStartInProgress == false) && (mDisplayPaused == false)){
ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_QUERY_RESOLUTION_PREVIEW,( int ) &frame);
if ( NO_ERROR != ret ){
CAMHAL_LOGEB("Error: CAMERA_QUERY_RESOLUTION_PREVIEW %d", ret);
return ret;
}
///Update the current preview width and height
mPreviewWidth = frame.mWidth;
mPreviewHeight = frame.mHeight;
}
///If we don't have the preview callback enabled and display adapter,
if(!mSetPreviewWindowCalled || (mDisplayAdapter.get() == NULL)){
CAMHAL_LOGD("Preview not started. Preview in progress flag set");
mPreviewStartInProgress = true;
ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_SWITCH_TO_EXECUTING);
if ( NO_ERROR != ret ){
CAMHAL_LOGEB("Error: CAMERA_SWITCH_TO_EXECUTING %d", ret);
return ret;
}
return NO_ERROR;
}
if( (mDisplayAdapter.get() != NULL) && ( !mPreviewEnabled ) && ( mDisplayPaused ) )
{
CAMHAL_LOGDA("Preview is in paused state");
mDisplayPaused = false;
mPreviewEnabled = true;
if ( NO_ERROR == ret )
{
ret = mDisplayAdapter->pauseDisplay(mDisplayPaused);
if ( NO_ERROR != ret )
{
CAMHAL_LOGEB("Display adapter resume failed %x", ret);
}
}
//restart preview callbacks
if(mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)
{
mAppCallbackNotifier->enableMsgType (CAMERA_MSG_PREVIEW_FRAME);
}
signalEndImageCapture();
return ret;
}
required_buffer_count = atoi(mCameraProperties->get(CameraProperties::REQUIRED_PREVIEW_BUFS));
///Allocate the preview buffers
ret = allocPreviewBufs(mPreviewWidth, mPreviewHeight, mParameters.getPreviewFormat(), required_buffer_count, max_queueble_buffers);
if ( NO_ERROR != ret )
{
CAMHAL_LOGEA("Couldn't allocate buffers for Preview");
goto error;
}
if ( mMeasurementEnabled )
{
ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_QUERY_BUFFER_SIZE_PREVIEW_DATA,
( int ) &frame,
required_buffer_count);
if ( NO_ERROR != ret )
{
return ret;
}
///Allocate the preview data buffers
ret = allocPreviewDataBufs(frame.mLength, required_buffer_count);
if ( NO_ERROR != ret ) {
CAMHAL_LOGEA("Couldn't allocate preview data buffers");
goto error;
}
if ( NO_ERROR == ret )
{
desc.mBuffers = mPreviewDataBuffers;
desc.mOffsets = mPreviewDataOffsets;
desc.mFd = mPreviewDataFd;
desc.mLength = mPreviewDataLength;
desc.mCount = ( size_t ) required_buffer_count;
desc.mMaxQueueable = (size_t) required_buffer_count;
mCameraAdapter->sendCommand(CameraAdapter::CAMERA_USE_BUFFERS_PREVIEW_DATA,
( int ) &desc);
}
}
///Pass the buffers to Camera Adapter
desc.mBuffers = mPreviewBuffers;
desc.mOffsets = mPreviewOffsets;
desc.mFd = mPreviewFd;
desc.mLength = mPreviewLength;
desc.mCount = ( size_t ) required_buffer_count;
desc.mMaxQueueable = (size_t) max_queueble_buffers;
ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_USE_BUFFERS_PREVIEW,
( int ) &desc);
if ( NO_ERROR != ret )
{
CAMHAL_LOGEB("Failed to register preview buffers: 0x%x", ret);
freePreviewBufs();
return ret;
}
///Start the callback notifier
ret = mAppCallbackNotifier->start();
if( ALREADY_EXISTS == ret )
{
//Already running, do nothing
CAMHAL_LOGDA("AppCallbackNotifier already running");
ret = NO_ERROR;
}
else if ( NO_ERROR == ret ) {
CAMHAL_LOGDA("Started AppCallbackNotifier..");
mAppCallbackNotifier->setMeasurements(mMeasurementEnabled);
}
else
{
CAMHAL_LOGDA("Couldn't start AppCallbackNotifier");
goto error;
}
if (ret == NO_ERROR) mPreviewInitializationDone = true;
mAppCallbackNotifier->startPreviewCallbacks(mParameters, mPreviewBuffers, mPreviewOffsets, mPreviewFd, mPreviewLength, required_buffer_count);
return ret;
error:
CAMHAL_LOGEA("Performing cleanup after error");
//Do all the cleanup
freePreviewBufs();
mCameraAdapter->sendCommand(CameraAdapter::CAMERA_STOP_PREVIEW);
if(mDisplayAdapter.get() != NULL)
{
mDisplayAdapter->disableDisplay(false);
}
mAppCallbackNotifier->stop();
mPreviewStartInProgress = false;
mPreviewEnabled = false;
LOG_FUNCTION_NAME_EXIT;
return ret;
}
/**
@brief Sets ANativeWindow object.
Preview buffers provided to CameraHal via this object. DisplayAdapter will be interfacing with it
to render buffers to display.
@param[in] window The ANativeWindow object created by Surface flinger
@return NO_ERROR If the ANativeWindow object passes validation criteria
@todo Define validation criteria for ANativeWindow object. Define error codes for scenarios
*/
status_t CameraHal::setPreviewWindow(struct preview_stream_ops *window)
{
status_t ret = NO_ERROR;
CameraAdapter::BuffersDescriptor desc;
LOG_FUNCTION_NAME;
mSetPreviewWindowCalled = true;
///If the Camera service passes a null window, we destroy existing window and free the DisplayAdapter
if(!window)
{
if(mDisplayAdapter.get() != NULL)
{
///NULL window passed, destroy the display adapter if present
CAMHAL_LOGD("NULL window passed, destroying display adapter");
mDisplayAdapter.clear();
///@remarks If there was a window previously existing, we usually expect another valid window to be passed by the client
///@remarks so, we will wait until it passes a valid window to begin the preview again
mSetPreviewWindowCalled = false;
}
CAMHAL_LOGD("NULL ANativeWindow passed to setPreviewWindow");
return NO_ERROR;
}else if(mDisplayAdapter.get() == NULL)
{
// Need to create the display adapter since it has not been created
// Create display adapter
mDisplayAdapter = new ANativeWindowDisplayAdapter();
#ifdef OMAP_ENHANCEMENT
mDisplayAdapter->setExtendedOps(mExtendedPreviewStreamOps);
#endif
ret = NO_ERROR;
if(!mDisplayAdapter.get() || ((ret=mDisplayAdapter->initialize())!=NO_ERROR))
{
if(ret!=NO_ERROR)
{
mDisplayAdapter.clear();
CAMHAL_LOGEA("DisplayAdapter initialize failed");
LOG_FUNCTION_NAME_EXIT;
return ret;
}
else
{
CAMHAL_LOGEA("Couldn't create DisplayAdapter");
LOG_FUNCTION_NAME_EXIT;
return NO_MEMORY;
}
}
// DisplayAdapter needs to know where to get the CameraFrames from inorder to display
// Since CameraAdapter is the one that provides the frames, set it as the frame provider for DisplayAdapter
mDisplayAdapter->setFrameProvider(mCameraAdapter);
// Any dynamic errors that happen during the camera use case has to be propagated back to the application
// via CAMERA_MSG_ERROR. AppCallbackNotifier is the class that notifies such errors to the application
// Set it as the error handler for the DisplayAdapter
mDisplayAdapter->setErrorHandler(mAppCallbackNotifier.get());
// Update the display adapter with the new window that is passed from CameraService
ret = mDisplayAdapter->setPreviewWindow(window);
if(ret!=NO_ERROR)
{
CAMHAL_LOGEB("DisplayAdapter setPreviewWindow returned error %d", ret);
}
if(mPreviewStartInProgress)
{
CAMHAL_LOGDA("setPreviewWindow called when preview running");
// Start the preview since the window is now available
ret = startPreview();
}
} else {
// Update the display adapter with the new window that is passed from CameraService
ret = mDisplayAdapter->setPreviewWindow(window);
if ( (NO_ERROR == ret) && previewEnabled() ) {
restartPreview();
} else if (ret == ALREADY_EXISTS) {
// ALREADY_EXISTS should be treated as a noop in this case
ret = NO_ERROR;
}
}
LOG_FUNCTION_NAME_EXIT;
return ret;
}
#ifdef OMAP_ENHANCEMENT_CPCAM
void CameraHal::setExtendedPreviewStreamOps(preview_stream_extended_ops_t *ops)
{
mExtendedPreviewStreamOps = ops;
}
/**
@brief Sets Tapout Surfaces.
Buffers provided to CameraHal via this object for tap-out
functionality.
@param[in] window The ANativeWindow object created by Surface flinger
@return NO_ERROR If the ANativeWindow object passes validation criteria
@todo Define validation criteria for ANativeWindow object. Define error codes for scenarios
*/
status_t CameraHal::setTapoutLocked(struct preview_stream_ops *tapout)
{
status_t ret = NO_ERROR;
int index = -1;
LOG_FUNCTION_NAME;
if (!tapout) {
CAMHAL_LOGD("Missing argument");
LOG_FUNCTION_NAME_EXIT;
return NO_ERROR;
}
// Set tapout point
// 1. Check name of tap-out
// 2. If not already set, then create a new one
// 3. Allocate buffers. If user is re-setting the surface, free buffers first and re-allocate
// in case dimensions have changed
for (unsigned int i = 0; i < mOutAdapters.size(); i++) {
android::sp<DisplayAdapter> out;
out = mOutAdapters.itemAt(i);
ret = out->setPreviewWindow(tapout);
if (ret == ALREADY_EXISTS) {
CAMHAL_LOGD("Tap Out already set at index = %d", i);
index = i;
ret = NO_ERROR;
}
}
if (index < 0) {
android::sp<DisplayAdapter> out = new BufferSourceAdapter();
ret = out->initialize();
if (ret != NO_ERROR) {
out.clear();
CAMHAL_LOGEA("DisplayAdapter initialize failed");
goto exit;
}
// BufferSourceAdapter will be handler of the extended OPS
out->setExtendedOps(mExtendedPreviewStreamOps);
// CameraAdapter will be the frame provider for BufferSourceAdapter
out->setFrameProvider(mCameraAdapter);
// BufferSourceAdapter will use ErrorHandler to send errors back to
// the application
out->setErrorHandler(mAppCallbackNotifier.get());
// Update the display adapter with the new window that is passed from CameraService
ret = out->setPreviewWindow(tapout);
if(ret != NO_ERROR) {
CAMHAL_LOGEB("DisplayAdapter setPreviewWindow returned error %d", ret);
goto exit;
}
if (NULL != mCameraAdapter) {
unsigned int bufferCount, max_queueable;
CameraFrame frame;
bufferCount = out->getBufferCount();
if (bufferCount < 1) bufferCount = NO_BUFFERS_IMAGE_CAPTURE_SYSTEM_HEAP;
ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_QUERY_BUFFER_SIZE_IMAGE_CAPTURE,
( int ) &frame,
bufferCount);
if (NO_ERROR != ret) {
CAMHAL_LOGEB("CAMERA_QUERY_BUFFER_SIZE_IMAGE_CAPTURE returned error 0x%x", ret);
}
if (NO_ERROR == ret) {
CameraBuffer *bufs = NULL;
unsigned int stride;
unsigned int height = frame.mHeight;
int size = frame.mLength;
stride = frame.mAlignment / getBPP(mParameters.getPictureFormat());
bufs = out->allocateBufferList(stride,
height,
mParameters.getPictureFormat(),
size,
bufferCount);
if (bufs == NULL){
CAMHAL_LOGEB("error allocating buffer list");
goto exit;
}
}
}
mOutAdapters.add(out);
}
exit:
LOG_FUNCTION_NAME_EXIT;
return ret;
}
/**
@brief Releases Tapout Surfaces.
@param[in] window The ANativeWindow object created by Surface flinger
@return NO_ERROR If the ANativeWindow object passes validation criteria
@todo Define validation criteria for ANativeWindow object. Define error codes for scenarios
*/
status_t CameraHal::releaseTapoutLocked(struct preview_stream_ops *tapout)
{
status_t ret = NO_ERROR;
char id[OP_STR_SIZE];
LOG_FUNCTION_NAME;
if (!tapout) {
CAMHAL_LOGD("Missing argument");
LOG_FUNCTION_NAME_EXIT;
return NO_ERROR;
}
// Get the name of tapout
ret = mExtendedPreviewStreamOps->get_id(tapout, id, sizeof(id));
if (NO_ERROR != ret) {
CAMHAL_LOGEB("get_id OPS returned error %d", ret);
return ret;
}
// 1. Check name of tap-out
// 2. If exist, then free buffers and then remove it
if (mBufferSourceAdapter_Out.get() && mBufferSourceAdapter_Out->match(id)) {
CAMHAL_LOGD("REMOVE tap out %p previously set as current", tapout);
mBufferSourceAdapter_Out.clear();
}
for (unsigned int i = 0; i < mOutAdapters.size(); i++) {
android::sp<DisplayAdapter> out;
out = mOutAdapters.itemAt(i);
if (out->match(id)) {
CAMHAL_LOGD("REMOVE tap out %p \"%s\" at position %d", tapout, id, i);
mOutAdapters.removeAt(i);
break;
}
}
LOG_FUNCTION_NAME_EXIT;
return ret;
}
/**
@brief Sets Tapin Surfaces.
Buffers provided to CameraHal via this object for tap-in
functionality.
@param[in] window The ANativeWindow object created by Surface flinger
@return NO_ERROR If the ANativeWindow object passes validation criteria
@todo Define validation criteria for ANativeWindow object. Define error codes for scenarios
*/
status_t CameraHal::setTapinLocked(struct preview_stream_ops *tapin)
{
status_t ret = NO_ERROR;
int index = -1;
LOG_FUNCTION_NAME;
if (!tapin) {
CAMHAL_LOGD("Missing argument");
LOG_FUNCTION_NAME_EXIT;
return NO_ERROR;
}
// 1. Set tapin point
// 1. Check name of tap-in
// 2. If not already set, then create a new one
// 3. Allocate buffers. If user is re-setting the surface, free buffers first and re-allocate
// in case dimensions have changed
for (unsigned int i = 0; i < mInAdapters.size(); i++) {
android::sp<DisplayAdapter> in;
in = mInAdapters.itemAt(i);
ret = in->setPreviewWindow(tapin);
if (ret == ALREADY_EXISTS) {
CAMHAL_LOGD("Tap In already set at index = %d", i);
index = i;
ret = NO_ERROR;
}
}
if (index < 0) {
android::sp<DisplayAdapter> in = new BufferSourceAdapter();
ret = in->initialize();
if (ret != NO_ERROR) {
in.clear();
CAMHAL_LOGEA("DisplayAdapter initialize failed");
goto exit;
}
// BufferSourceAdapter will be handler of the extended OPS
in->setExtendedOps(mExtendedPreviewStreamOps);
// CameraAdapter will be the frame provider for BufferSourceAdapter
in->setFrameProvider(mCameraAdapter);
// BufferSourceAdapter will use ErrorHandler to send errors back to
// the application
in->setErrorHandler(mAppCallbackNotifier.get());
// Update the display adapter with the new window that is passed from CameraService
ret = in->setPreviewWindow(tapin);
if(ret != NO_ERROR) {
CAMHAL_LOGEB("DisplayAdapter setPreviewWindow returned error %d", ret);
goto exit;
}
mInAdapters.add(in);
}
exit:
LOG_FUNCTION_NAME_EXIT;
return ret;
}
/**
@brief Releases Tapin Surfaces.
@param[in] window The ANativeWindow object created by Surface flinger
@return NO_ERROR If the ANativeWindow object passes validation criteria
@todo Define validation criteria for ANativeWindow object. Define error codes for scenarios
*/
status_t CameraHal::releaseTapinLocked(struct preview_stream_ops *tapin)
{
status_t ret = NO_ERROR;
char id[OP_STR_SIZE];
LOG_FUNCTION_NAME;
if (!tapin) {
CAMHAL_LOGD("Missing argument");
LOG_FUNCTION_NAME_EXIT;
return NO_ERROR;
}
// Get the name of tapin
ret = mExtendedPreviewStreamOps->get_id(tapin, id, sizeof(id));
if (NO_ERROR != ret) {
CAMHAL_LOGEB("get_id OPS returned error %d", ret);
return ret;
}
// 1. Check name of tap-in
// 2. If exist, then free buffers and then remove it
if (mBufferSourceAdapter_In.get() && mBufferSourceAdapter_In->match(id)) {
CAMHAL_LOGD("REMOVE tap in %p previously set as current", tapin);
mBufferSourceAdapter_In.clear();
}
for (unsigned int i = 0; i < mInAdapters.size(); i++) {
android::sp<DisplayAdapter> in;
in = mInAdapters.itemAt(i);
if (in->match(id)) {
CAMHAL_LOGD("REMOVE tap in %p \"%s\" at position %d", tapin, id, i);
mInAdapters.removeAt(i);
break;
}
}
LOG_FUNCTION_NAME_EXIT;
return ret;
}
/**
@brief Sets ANativeWindow object.
Buffers provided to CameraHal via this object for tap-in/tap-out
functionality.
TODO(XXX): this is just going to use preview_stream_ops for now, but we
most likely need to extend it when we want more functionality
@param[in] window The ANativeWindow object created by Surface flinger
@return NO_ERROR If the ANativeWindow object passes validation criteria
@todo Define validation criteria for ANativeWindow object. Define error codes for scenarios
*/
status_t CameraHal::setBufferSource(struct preview_stream_ops *tapin, struct preview_stream_ops *tapout)
{
status_t ret = NO_ERROR;
int index = -1;
LOG_FUNCTION_NAME;
android::AutoMutex lock(mLock);
CAMHAL_LOGD ("setBufferSource(%p, %p)", tapin, tapout);
ret = setTapoutLocked(tapout);
if (ret != NO_ERROR) {
CAMHAL_LOGE("setTapoutLocked returned error 0x%x", ret);
goto exit;
}
ret = setTapinLocked(tapin);
if (ret != NO_ERROR) {
CAMHAL_LOGE("setTapinLocked returned error 0x%x", ret);
goto exit;
}
exit:
LOG_FUNCTION_NAME_EXIT;
return ret;
}
/**
@brief Releases ANativeWindow object.
Release Buffers previously released with setBufferSource()
TODO(XXX): this is just going to use preview_stream_ops for now, but we
most likely need to extend it when we want more functionality
@param[in] window The ANativeWindow object created by Surface flinger
@return NO_ERROR If the ANativeWindow object passes validation criteria
@todo Define validation criteria for ANativeWindow object. Define error codes for scenarios
*/
status_t CameraHal::releaseBufferSource(struct preview_stream_ops *tapin, struct preview_stream_ops *tapout)
{
status_t ret = NO_ERROR;
int index = -1;
LOG_FUNCTION_NAME;
android::AutoMutex lock(mLock);
CAMHAL_LOGD ("releaseBufferSource(%p, %p)", tapin, tapout);
if (tapout) {
ret |= releaseTapoutLocked(tapout);
if (ret != NO_ERROR) {
CAMHAL_LOGE("Error %d to release tap out", ret);
}
}
if (tapin) {
ret |= releaseTapinLocked(tapin);
if (ret != NO_ERROR) {
CAMHAL_LOGE("Error %d to release tap in", ret);
}
}
exit:
LOG_FUNCTION_NAME_EXIT;
return ret;
}
#endif
/**
@brief Stop a previously started preview.
@param none
@return none
*/
void CameraHal::stopPreview()
{
LOG_FUNCTION_NAME;
if( (!previewEnabled() && !mDisplayPaused) || mRecordingEnabled)
{
LOG_FUNCTION_NAME_EXIT;
return;
}
bool imageCaptureRunning = (mCameraAdapter->getState() & CameraAdapter::CAPTURE_STATE) &&
(mCameraAdapter->getNextState() != CameraAdapter::PREVIEW_STATE);
if(mDisplayPaused && !imageCaptureRunning)
{
// Display is paused, which essentially means there is no preview active.
// Note: this is done so that when stopPreview is called by client after
// an image capture, we do not de-initialize the camera adapter and
// restart over again.
return;
}
forceStopPreview();
// Reset Capture-Mode to default, so that when we switch from VideoRecording
// to ImageCapture, CAPTURE_MODE is not left to VIDEO_MODE.
CAMHAL_LOGDA("Resetting Capture-Mode to default");
mParameters.set(TICameraParameters::KEY_CAP_MODE, "");
LOG_FUNCTION_NAME_EXIT;
}
/**
@brief Returns true if preview is enabled
@param none
@return true If preview is running currently
false If preview has been stopped
*/
bool CameraHal::previewEnabled()
{
LOG_FUNCTION_NAME;
return (mPreviewEnabled || mPreviewStartInProgress);
}
/**
@brief Start record mode.
When a record image is available a CAMERA_MSG_VIDEO_FRAME message is sent with
the corresponding frame. Every record frame must be released by calling
releaseRecordingFrame().
@param none
@return NO_ERROR If recording could be started without any issues
@todo Update the header with possible error values in failure scenarios
*/
status_t CameraHal::startRecording( )
{
int w, h;
const char *valstr = NULL;
bool restartPreviewRequired = false;
status_t ret = NO_ERROR;
LOG_FUNCTION_NAME;
#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
gettimeofday(&mStartPreview, NULL);
#endif
if(!previewEnabled())
{
return NO_INIT;
}
// set internal recording hint in case camera adapter needs to make some
// decisions....(will only be sent to camera adapter if camera restart is required)
mParameters.set(TICameraParameters::KEY_RECORDING_HINT, android::CameraParameters::TRUE);
// if application starts recording in continuous focus picture mode...
// then we need to force default capture mode (as opposed to video mode)
if ( ((valstr = mParameters.get(android::CameraParameters::KEY_FOCUS_MODE)) != NULL) &&
(strcmp(valstr, android::CameraParameters::FOCUS_MODE_CONTINUOUS_PICTURE) == 0) ){
restartPreviewRequired = resetVideoModeParameters();
}
// only need to check recording hint if preview restart is not already needed
valstr = mParameters.get(android::CameraParameters::KEY_RECORDING_HINT);
if ( !restartPreviewRequired &&
(!valstr || (valstr && (strcmp(valstr, android::CameraParameters::TRUE) != 0))) ) {
restartPreviewRequired = setVideoModeParameters(mParameters);
}
if (restartPreviewRequired) {
{
android::AutoMutex lock(mLock);
mCapModeBackup = mParameters.get(TICameraParameters::KEY_CAP_MODE);
}
ret = restartPreview();
}
if ( NO_ERROR == ret )
{
int count = atoi(mCameraProperties->get(CameraProperties::REQUIRED_PREVIEW_BUFS));
mParameters.getPreviewSize(&w, &h);
CAMHAL_LOGDB("%s Video Width=%d Height=%d", __FUNCTION__, mVideoWidth, mVideoHeight);
if ((w != mVideoWidth) && (h != mVideoHeight))
{
ret = allocVideoBufs(mVideoWidth, mVideoHeight, count);
if ( NO_ERROR != ret )
{
CAMHAL_LOGEB("allocImageBufs returned error 0x%x", ret);
mParameters.remove(TICameraParameters::KEY_RECORDING_HINT);
return ret;
}
mAppCallbackNotifier->useVideoBuffers(true);
mAppCallbackNotifier->setVideoRes(mVideoWidth, mVideoHeight);
ret = mAppCallbackNotifier->initSharedVideoBuffers(mPreviewBuffers, mPreviewOffsets, mPreviewFd, mPreviewLength, count, mVideoBuffers);
}
else
{
mAppCallbackNotifier->useVideoBuffers(false);
mAppCallbackNotifier->setVideoRes(mPreviewWidth, mPreviewHeight);
ret = mAppCallbackNotifier->initSharedVideoBuffers(mPreviewBuffers, mPreviewOffsets, mPreviewFd, mPreviewLength, count, NULL);
}
}
if ( NO_ERROR == ret )
{
ret = mAppCallbackNotifier->startRecording();
}
if ( NO_ERROR == ret )
{
///Buffers for video capture (if different from preview) are expected to be allocated within CameraAdapter
ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_START_VIDEO);
}
if ( NO_ERROR == ret )
{
mRecordingEnabled = true;
}
LOG_FUNCTION_NAME_EXIT;
return ret;
}
/**
@brief Set the camera parameters specific to Video Recording.
This function checks for the camera parameters which have to be set for recording.
Video Recording needs CAPTURE_MODE to be VIDEO_MODE. This function sets it.
This function also enables Video Recording specific functions like VSTAB & VNF.
@param none
@return true if preview needs to be restarted for VIDEO_MODE parameters to take effect.
@todo Modify the policies for enabling VSTAB & VNF usecase based later.
*/
bool CameraHal::setVideoModeParameters(const android::CameraParameters& params)
{
const char *valstr = NULL;
const char *valstrRemote = NULL;
bool restartPreviewRequired = false;
LOG_FUNCTION_NAME;
// Set CAPTURE_MODE to VIDEO_MODE, if not set already and Restart Preview
valstr = mParameters.get(TICameraParameters::KEY_CAP_MODE);
if ( (valstr == NULL) ||
( (valstr != NULL) && ( (strcmp(valstr, (const char *) TICameraParameters::VIDEO_MODE) != 0) &&
(strcmp(valstr, (const char *) TICameraParameters::VIDEO_MODE_HQ ) != 0) ) ) ) {
CAMHAL_LOGDA("Set CAPTURE_MODE to VIDEO_MODE");
mParameters.set(TICameraParameters::KEY_CAP_MODE, (const char *) TICameraParameters::VIDEO_MODE);
restartPreviewRequired = true;
}
// set VSTAB. restart is required if vstab value has changed
if ( (valstrRemote = params.get(android::CameraParameters::KEY_VIDEO_STABILIZATION)) != NULL ) {
// make sure we support vstab
if (strcmp(mCameraProperties->get(CameraProperties::VSTAB_SUPPORTED),
android::CameraParameters::TRUE) == 0) {
valstr = mParameters.get(android::CameraParameters::KEY_VIDEO_STABILIZATION);
// vstab value has changed
if ((valstr != NULL) &&
strcmp(valstr, valstrRemote) != 0) {
restartPreviewRequired = true;
}
mParameters.set(android::CameraParameters::KEY_VIDEO_STABILIZATION,
valstrRemote);
}
} else if (mParameters.get(android::CameraParameters::KEY_VIDEO_STABILIZATION)) {
// vstab was configured but now unset
restartPreviewRequired = true;
mParameters.remove(android::CameraParameters::KEY_VIDEO_STABILIZATION);
}
// Set VNF
if ((valstrRemote = params.get(TICameraParameters::KEY_VNF)) == NULL) {
CAMHAL_LOGDA("Enable VNF");
mParameters.set(TICameraParameters::KEY_VNF, android::CameraParameters::TRUE);
restartPreviewRequired = true;
} else {
valstr = mParameters.get(TICameraParameters::KEY_VNF);
if (valstr && strcmp(valstr, valstrRemote) != 0) {
restartPreviewRequired = true;
}
mParameters.set(TICameraParameters::KEY_VNF, valstrRemote);
}
#if !defined(OMAP_ENHANCEMENT) && !defined(ENHANCED_DOMX)
// For VSTAB alone for 1080p resolution, padded width goes > 2048, which cannot be rendered by GPU.
// In such case, there is support in Ducati for combination of VSTAB & VNF requiring padded width < 2048.
// So we are forcefully enabling VNF, if VSTAB is enabled for 1080p resolution.
int w, h;
params.getPreviewSize(&w, &h);
valstr = mParameters.get(android::CameraParameters::KEY_VIDEO_STABILIZATION);
if (valstr && (strcmp(valstr, android::CameraParameters::TRUE) == 0) && (w == 1920)) {
CAMHAL_LOGDA("Force Enable VNF for 1080p");
const char *valKeyVnf = mParameters.get(TICameraParameters::KEY_VNF);
if(!valKeyVnf || (strcmp(valKeyVnf, android::CameraParameters::TRUE) != 0)) {
mParameters.set(TICameraParameters::KEY_VNF, android::CameraParameters::TRUE);
restartPreviewRequired = true;
}
}
#endif
LOG_FUNCTION_NAME_EXIT;
return restartPreviewRequired;
}
/**
@brief Reset the camera parameters specific to Video Recording.
This function resets CAPTURE_MODE and disables Recording specific functions like VSTAB & VNF.
@param none
@return true if preview needs to be restarted for VIDEO_MODE parameters to take effect.
*/
bool CameraHal::resetVideoModeParameters()
{
const char *valstr = NULL;
bool restartPreviewRequired = false;
status_t ret = NO_ERROR;
LOG_FUNCTION_NAME;
// ignore this if we are already recording
if (mRecordingEnabled) {
return false;
}
// Set CAPTURE_MODE to VIDEO_MODE, if not set already and Restart Preview
valstr = mParameters.get(TICameraParameters::KEY_CAP_MODE);
if ((valstr != NULL) && (strcmp(valstr, TICameraParameters::VIDEO_MODE) == 0)) {
CAMHAL_LOGDA("Reset Capture-Mode to default");
mParameters.set(TICameraParameters::KEY_CAP_MODE, "");
restartPreviewRequired = true;
}
LOG_FUNCTION_NAME_EXIT;
return restartPreviewRequired;
}
/**
@brief Restart the preview with setParameter.
This function restarts preview, for some VIDEO_MODE parameters to take effect.
@param none
@return NO_ERROR If recording parameters could be set without any issues
*/
status_t CameraHal::restartPreview()
{
status_t ret = NO_ERROR;
LOG_FUNCTION_NAME;
// Retain CAPTURE_MODE before calling stopPreview(), since it is reset in stopPreview().
forceStopPreview();
{
android::AutoMutex lock(mLock);
if (!mCapModeBackup.isEmpty()) {
mParameters.set(TICameraParameters::KEY_CAP_MODE, mCapModeBackup.string());
mCapModeBackup = "";
} else {
mParameters.set(TICameraParameters::KEY_CAP_MODE, "");
}
mCameraAdapter->setParameters(mParameters);
}
ret = startPreview();
LOG_FUNCTION_NAME_EXIT;
return ret;
}
/**
@brief Stop a previously started recording.
@param none
@return none
*/
void CameraHal::stopRecording()
{
CameraAdapter::AdapterState currentState;
LOG_FUNCTION_NAME;
android::AutoMutex lock(mLock);
if (!mRecordingEnabled )
{
return;
}
currentState = mCameraAdapter->getState();
if (currentState == CameraAdapter::VIDEO_CAPTURE_STATE) {
mCameraAdapter->sendCommand(CameraAdapter::CAMERA_STOP_IMAGE_CAPTURE);
}
mAppCallbackNotifier->stopRecording();
mCameraAdapter->sendCommand(CameraAdapter::CAMERA_STOP_VIDEO);
mRecordingEnabled = false;
if ( mAppCallbackNotifier->getUesVideoBuffers() ){
freeVideoBufs(mVideoBuffers);
if (mVideoBuffers){
CAMHAL_LOGVB(" FREEING mVideoBuffers %p", mVideoBuffers);
delete [] mVideoBuffers;
}
mVideoBuffers = NULL;
}
// reset internal recording hint in case camera adapter needs to make some
// decisions....(will only be sent to camera adapter if camera restart is required)
mParameters.remove(TICameraParameters::KEY_RECORDING_HINT);
LOG_FUNCTION_NAME_EXIT;
}
/**
@brief Returns true if recording is enabled.
@param none
@return true If recording is currently running
false If recording has been stopped
*/
int CameraHal::recordingEnabled()
{
LOG_FUNCTION_NAME;
LOG_FUNCTION_NAME_EXIT;
return mRecordingEnabled;
}
/**
@brief Release a record frame previously returned by CAMERA_MSG_VIDEO_FRAME.
@param[in] mem MemoryBase pointer to the frame being released. Must be one of the buffers
previously given by CameraHal
@return none
*/
void CameraHal::releaseRecordingFrame(const void* mem)
{
LOG_FUNCTION_NAME;
//CAMHAL_LOGDB(" 0x%x", mem->pointer());
if ( ( mRecordingEnabled ) && mem != NULL)
{
mAppCallbackNotifier->releaseRecordingFrame(mem);
}
LOG_FUNCTION_NAME_EXIT;
return;
}
/**
@brief Start auto focus
This call asynchronous.
The notification callback routine is called with CAMERA_MSG_FOCUS once when
focusing is complete. autoFocus() will be called again if another auto focus is
needed.
@param none
@return NO_ERROR
@todo Define the error codes if the focus is not locked
*/
status_t CameraHal::autoFocus()
{
status_t ret = NO_ERROR;
#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
gettimeofday(&mStartFocus, NULL);
#endif
LOG_FUNCTION_NAME;
android::AutoMutex lock(mLock);
mMsgEnabled |= CAMERA_MSG_FOCUS;
if ( NULL == mCameraAdapter )
{
ret = -1;
goto EXIT;
}
CameraAdapter::AdapterState state;
ret = mCameraAdapter->getState(state);
if (ret != NO_ERROR)
{
goto EXIT;
}
if (state == CameraAdapter::AF_STATE)
{
CAMHAL_LOGI("Ignoring start-AF (already in progress)");
goto EXIT;
}
#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
//pass the autoFocus timestamp along with the command to camera adapter
ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_PERFORM_AUTOFOCUS, ( int ) &mStartFocus);
#else
ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_PERFORM_AUTOFOCUS);
#endif
EXIT:
LOG_FUNCTION_NAME_EXIT;
return ret;
}
/**
@brief Cancels auto-focus function.
If the auto-focus is still in progress, this function will cancel it.
Whether the auto-focus is in progress or not, this function will return the
focus position to the default. If the camera does not support auto-focus, this is a no-op.
@param none
@return NO_ERROR If the cancel succeeded
@todo Define error codes if cancel didnt succeed
*/
status_t CameraHal::cancelAutoFocus()
{
LOG_FUNCTION_NAME;
android::AutoMutex lock(mLock);
android::CameraParameters adapterParams = mParameters;
mMsgEnabled &= ~CAMERA_MSG_FOCUS;
if( NULL != mCameraAdapter )
{
adapterParams.set(TICameraParameters::KEY_AUTO_FOCUS_LOCK, android::CameraParameters::FALSE);
mCameraAdapter->setParameters(adapterParams);
mCameraAdapter->sendCommand(CameraAdapter::CAMERA_CANCEL_AUTOFOCUS);
mAppCallbackNotifier->flushEventQueue();
}
LOG_FUNCTION_NAME_EXIT;
return NO_ERROR;
}
void CameraHal::setEventProvider(int32_t eventMask, MessageNotifier * eventNotifier)
{
LOG_FUNCTION_NAME;
if ( NULL != mEventProvider )
{
mEventProvider->disableEventNotification(CameraHalEvent::ALL_EVENTS);
delete mEventProvider;
mEventProvider = NULL;
}
mEventProvider = new EventProvider(eventNotifier, this, eventCallbackRelay);
if ( NULL == mEventProvider )
{
CAMHAL_LOGEA("Error in creating EventProvider");
}
else
{
mEventProvider->enableEventNotification(eventMask);
}
LOG_FUNCTION_NAME_EXIT;
}
void CameraHal::eventCallbackRelay(CameraHalEvent* event)
{
LOG_FUNCTION_NAME;
CameraHal *appcbn = ( CameraHal * ) (event->mCookie);
appcbn->eventCallback(event );
LOG_FUNCTION_NAME_EXIT;
}
void CameraHal::eventCallback(CameraHalEvent* event)
{
LOG_FUNCTION_NAME;
LOG_FUNCTION_NAME_EXIT;
}
status_t CameraHal::startImageBracketing()
{
status_t ret = NO_ERROR;
CameraFrame frame;
CameraAdapter::BuffersDescriptor desc;
unsigned int max_queueable = 0;
#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
gettimeofday(&mStartCapture, NULL);
#endif
LOG_FUNCTION_NAME;
if(!previewEnabled() && !mDisplayPaused)
{
LOG_FUNCTION_NAME_EXIT;
return NO_INIT;
}
if ( !mBracketingEnabled )
{
return ret;
}
if ( NO_ERROR == ret )
{
mBracketingRunning = true;
}
if ( (NO_ERROR == ret) && ( NULL != mCameraAdapter ) )
{
ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_QUERY_BUFFER_SIZE_IMAGE_CAPTURE,
( int ) &frame,
( mBracketRangeNegative + 1 ));
if ( NO_ERROR != ret )
{
CAMHAL_LOGEB("CAMERA_QUERY_BUFFER_SIZE_IMAGE_CAPTURE returned error 0x%x", ret);
}
}
if ( NO_ERROR == ret )
{
if ( NULL != mAppCallbackNotifier.get() )
{
mAppCallbackNotifier->setBurst(true);
}
}
if ( NO_ERROR == ret )
{
mParameters.getPictureSize(( int * ) &frame.mWidth,
( int * ) &frame.mHeight);
ret = allocImageBufs(frame.mWidth,
frame.mHeight,
frame.mLength,
mParameters.getPictureFormat(),
( mBracketRangeNegative + 1 ));
if ( NO_ERROR != ret )
{
CAMHAL_LOGEB("allocImageBufs returned error 0x%x", ret);
}
}
if ( (NO_ERROR == ret) && ( NULL != mCameraAdapter ) )
{
desc.mBuffers = mImageBuffers;
desc.mOffsets = mImageOffsets;
desc.mFd = mImageFd;
desc.mLength = mImageLength;
desc.mCount = ( size_t ) ( mBracketRangeNegative + 1 );
desc.mMaxQueueable = ( size_t ) ( mBracketRangeNegative + 1 );
ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_USE_BUFFERS_IMAGE_CAPTURE,
( int ) &desc);
if ( NO_ERROR == ret )
{
#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
//pass capture timestamp along with the camera adapter command
ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_START_BRACKET_CAPTURE, ( mBracketRangePositive + 1 ), (int) &mStartCapture);
#else
ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_START_BRACKET_CAPTURE, ( mBracketRangePositive + 1 ));
#endif
}
}
return ret;
}
status_t CameraHal::stopImageBracketing()
{
status_t ret = NO_ERROR;
LOG_FUNCTION_NAME;
if( !previewEnabled() )
{
return NO_INIT;
}
mBracketingRunning = false;
ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_STOP_BRACKET_CAPTURE);
LOG_FUNCTION_NAME_EXIT;
return ret;
}
/**
@brief Take a picture.
@param none
@return NO_ERROR If able to switch to image capture
@todo Define error codes if unable to switch to image capture
*/
status_t CameraHal::takePicture(const char *params)
{
android::AutoMutex lock(mLock);
return __takePicture(params);
}
/**
@brief Internal function for getting a captured image.
shared by takePicture and reprocess.
@param none
@return NO_ERROR If able to switch to image capture
@todo Define error codes if unable to switch to image capture
*/
status_t CameraHal::__takePicture(const char *params, struct timeval *captureStart)
{
// cancel AF state if needed (before any operation and mutex lock)
if (mCameraAdapter->getState() == CameraAdapter::AF_STATE) {
cancelAutoFocus();
}
status_t ret = NO_ERROR;
CameraFrame frame;
CameraAdapter::BuffersDescriptor desc;
int burst = -1;
const char *valstr = NULL;
unsigned int bufferCount = 1;
unsigned int max_queueable = 0;
unsigned int rawBufferCount = 1;
bool isCPCamMode = false;
android::sp<DisplayAdapter> outAdapter = 0;
bool reuseTapout = false;
#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
if ( NULL == captureStart ) {
gettimeofday(&mStartCapture, NULL);
} else {
memcpy(&mStartCapture, captureStart, sizeof(struct timeval));
}
#endif
LOG_FUNCTION_NAME;
if(!previewEnabled() && !mDisplayPaused)
{
LOG_FUNCTION_NAME_EXIT;
CAMHAL_LOGEA("Preview not started...");
return NO_INIT;
}
valstr = mParameters.get(TICameraParameters::KEY_CAP_MODE);
isCPCamMode = valstr && !strcmp(valstr, TICameraParameters::CP_CAM_MODE);
// return error if we are already capturing
// however, we can queue a capture when in cpcam mode
if ( ((mCameraAdapter->getState() == CameraAdapter::CAPTURE_STATE &&
mCameraAdapter->getNextState() != CameraAdapter::PREVIEW_STATE) ||
(mCameraAdapter->getState() == CameraAdapter::VIDEO_CAPTURE_STATE &&
mCameraAdapter->getNextState() != CameraAdapter::VIDEO_STATE)) &&
!isCPCamMode) {
CAMHAL_LOGEA("Already capturing an image...");
return NO_INIT;
}
// we only support video snapshot if we are in video mode (recording hint is set)
if ( (mCameraAdapter->getState() == CameraAdapter::VIDEO_STATE) &&
(valstr && ( strcmp(valstr, TICameraParameters::VIDEO_MODE) &&
strcmp(valstr, TICameraParameters::VIDEO_MODE_HQ ) ) ) ) {
CAMHAL_LOGEA("Trying to capture while recording without recording hint set...");
return INVALID_OPERATION;
}
#ifdef OMAP_ENHANCEMENT_CPCAM
// check if camera application is using shots parameters
// api. parameters set here override anything set using setParameters
// TODO(XXX): Just going to use legacy TI parameters for now. Need
// add new APIs in CameraHal to utilize android::ShotParameters later, so
// we don't have to parse through the whole set of parameters
// in camera adapter
if (strlen(params) > 0) {
android::ShotParameters shotParams;
const char *valStr;
const char *valExpComp, *valExpGain;
int valNum;
android::String8 shotParams8(params);
shotParams.unflatten(shotParams8);
mParameters.remove(TICameraParameters::KEY_EXP_GAIN_BRACKETING_RANGE);
mParameters.remove(TICameraParameters::KEY_EXP_BRACKETING_RANGE);
valExpGain = shotParams.get(android::ShotParameters::KEY_EXP_GAIN_PAIRS);
valExpComp = shotParams.get(android::ShotParameters::KEY_EXP_COMPENSATION);
if (NULL != valExpComp) {
mParameters.set(TICameraParameters::KEY_EXP_BRACKETING_RANGE, valExpComp);
} else if (NULL != valExpGain) {
mParameters.set(TICameraParameters::KEY_EXP_GAIN_BRACKETING_RANGE, valExpGain);
}
valNum = shotParams.getInt(android::ShotParameters::KEY_BURST);
if (valNum >= 0) {
mParameters.set(TICameraParameters::KEY_BURST, valNum);
burst = valNum;
}
valStr = shotParams.get(android::ShotParameters::KEY_FLUSH_CONFIG);
if (valStr!= NULL) {
if ( 0 == strcmp(valStr, android::ShotParameters::TRUE) ) {
mParameters.set(TICameraParameters::KEY_FLUSH_SHOT_CONFIG_QUEUE,
android::CameraParameters::TRUE);
} else if ( 0 == strcmp(valStr, android::ShotParameters::FALSE) ) {
mParameters.set(TICameraParameters::KEY_FLUSH_SHOT_CONFIG_QUEUE,
android::CameraParameters::FALSE);
}
}
valStr = shotParams.get(android::ShotParameters::KEY_CURRENT_TAP_OUT);
if (valStr != NULL) {
int index = -1;
for (unsigned int i = 0; i < mOutAdapters.size(); i++) {
if(mOutAdapters.itemAt(i)->match(valStr)) {
index = i;
break;
}
}
if (index < 0) {
CAMHAL_LOGE("Invalid tap out surface passed to camerahal");
return BAD_VALUE;
}
CAMHAL_LOGD("Found matching out adapter at %d", index);
outAdapter = mOutAdapters.itemAt(index);
if ( outAdapter == mBufferSourceAdapter_Out ) {
reuseTapout = true;
}
}
mCameraAdapter->setParameters(mParameters);
} else
#endif
{
// TODO(XXX): Should probably reset burst and bracketing params
// when we remove legacy TI parameters implementation
}
#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
CameraHal::PPM("Takepicture parameters set: ", &mStartCapture);
#endif
// if we are already in the middle of a capture and using the same
// tapout ST...then we just need setParameters and start image
// capture to queue more shots
if (((mCameraAdapter->getState() & CameraAdapter::CAPTURE_STATE) ==
CameraAdapter::CAPTURE_STATE) &&
(mCameraAdapter->getNextState() != CameraAdapter::PREVIEW_STATE) &&
(reuseTapout) ) {
#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
//pass capture timestamp along with the camera adapter command
ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_START_IMAGE_CAPTURE,
(int) &mStartCapture);
#else
ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_START_IMAGE_CAPTURE);
#endif
return ret;
}
if ( !mBracketingRunning )
{
// if application didn't set burst through android::ShotParameters
// then query from TICameraParameters
if ((burst == -1) && (NO_ERROR == ret)) {
burst = mParameters.getInt(TICameraParameters::KEY_BURST);
}
//Allocate all buffers only in burst capture case
if ( burst > 0 ) {
// For CPCam mode...allocate for worst case burst
bufferCount = isCPCamMode || (burst > CameraHal::NO_BUFFERS_IMAGE_CAPTURE) ?
CameraHal::NO_BUFFERS_IMAGE_CAPTURE : burst;
if (outAdapter.get()) {
if ( reuseTapout ) {
bufferCount = mImageCount;
} else {
bufferCount = outAdapter->getBufferCount();
if (bufferCount < 1) {
bufferCount = NO_BUFFERS_IMAGE_CAPTURE_SYSTEM_HEAP;
}
}
}
if ( NULL != mAppCallbackNotifier.get() ) {
mAppCallbackNotifier->setBurst(true);
}
} else if ( mBracketingEnabled ) {
bufferCount = mBracketRangeNegative + 1;
if ( NULL != mAppCallbackNotifier.get() ) {
mAppCallbackNotifier->setBurst(false);
}
} else {
if ( NULL != mAppCallbackNotifier.get() ) {
mAppCallbackNotifier->setBurst(false);
}
}
// pause preview during normal image capture
// do not pause preview if recording (video state)
if ( (NO_ERROR == ret) && (NULL != mDisplayAdapter.get()) ) {
if (mCameraAdapter->getState() != CameraAdapter::VIDEO_STATE) {
mDisplayPaused = true;
mPreviewEnabled = false;
ret = mDisplayAdapter->pauseDisplay(mDisplayPaused);
// since preview is paused we should stop sending preview frames too
if(mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME) {
mAppCallbackNotifier->disableMsgType (CAMERA_MSG_PREVIEW_FRAME);
}
}
#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
mDisplayAdapter->setSnapshotTimeRef(&mStartCapture);
#endif
}
// if we taking video snapshot...
if ((NO_ERROR == ret) && (mCameraAdapter->getState() == CameraAdapter::VIDEO_STATE)) {
// enable post view frames if not already enabled so we can internally
// save snapshot frames for generating thumbnail
if((mMsgEnabled & CAMERA_MSG_POSTVIEW_FRAME) == 0) {
mAppCallbackNotifier->enableMsgType(CAMERA_MSG_POSTVIEW_FRAME);
}
}
if ( (NO_ERROR == ret) && (NULL != mCameraAdapter) )
{
if ( NO_ERROR == ret )
ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_QUERY_BUFFER_SIZE_IMAGE_CAPTURE,
( int ) &frame,
bufferCount);
if ( NO_ERROR != ret )
{
CAMHAL_LOGEB("CAMERA_QUERY_BUFFER_SIZE_IMAGE_CAPTURE returned error 0x%x", ret);
}
}
#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
CameraHal::PPM("Takepicture buffer size queried: ", &mStartCapture);
#endif
if (outAdapter.get()) {
// Avoid locking the tapout again when reusing it
if (!reuseTapout) {
// Need to reset buffers if we are switching adapters since we don't know
// the state of the new buffer list
ret = outAdapter->maxQueueableBuffers(max_queueable);
if (NO_ERROR != ret) {
CAMHAL_LOGE("Couldn't get max queuable");
return ret;
}
mImageBuffers = outAdapter->getBuffers(true);
mImageOffsets = outAdapter->getOffsets();
mImageFd = outAdapter->getFd();
mImageLength = outAdapter->getSize();
mImageCount = bufferCount;
mBufferSourceAdapter_Out = outAdapter;
}
} else {
mBufferSourceAdapter_Out.clear();
// allocImageBufs will only allocate new buffers if mImageBuffers is NULL
if ( NO_ERROR == ret ) {
max_queueable = bufferCount;
ret = allocImageBufs(frame.mAlignment / getBPP(mParameters.getPictureFormat()),
frame.mHeight,
frame.mLength,
mParameters.getPictureFormat(),
bufferCount);
if ( NO_ERROR != ret ) {
CAMHAL_LOGEB("allocImageBufs returned error 0x%x", ret);
}
}
}
#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
CameraHal::PPM("Takepicture buffers allocated: ", &mStartCapture);
memcpy(&mImageBuffers->ppmStamp, &mStartCapture, sizeof(struct timeval));
#endif
if ( (NO_ERROR == ret) && ( NULL != mCameraAdapter ) )
{
desc.mBuffers = mImageBuffers;
desc.mOffsets = mImageOffsets;
desc.mFd = mImageFd;
desc.mLength = mImageLength;
desc.mCount = ( size_t ) bufferCount;
desc.mMaxQueueable = ( size_t ) max_queueable;
ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_USE_BUFFERS_IMAGE_CAPTURE,
( int ) &desc);
}
if (mRawCapture) {
if ( NO_ERROR == ret ) {
CAMHAL_LOGDB("Raw capture buffers setup - %s", mParameters.getPictureFormat());
ret = allocRawBufs(mParameters.getInt(TICameraParameters::RAW_WIDTH),
mParameters.getInt(TICameraParameters::RAW_HEIGHT),
android::CameraParameters::PIXEL_FORMAT_BAYER_RGGB,
rawBufferCount);
if ( NO_ERROR != ret ) {
CAMHAL_LOGEB("allocRawBufs (for RAW capture) returned error 0x%x", ret);
}
}
if ((NO_ERROR == ret) && ( NULL != mCameraAdapter )) {
desc.mBuffers = mVideoBuffers;
desc.mOffsets = mVideoOffsets;
desc.mFd = mVideoFd;
desc.mLength = mVideoLength;
desc.mCount = ( size_t ) rawBufferCount;
desc.mMaxQueueable = ( size_t ) rawBufferCount;
ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_USE_BUFFERS_VIDEO_CAPTURE,
( int ) &desc);
}
}
}
#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
CameraHal::PPM("Takepicture buffers registered: ", &mStartCapture);
#endif
if ((ret == NO_ERROR) && mBufferSourceAdapter_Out.get()) {
mBufferSourceAdapter_Out->enableDisplay(0, 0, NULL);
}
if ((NO_ERROR == ret) && (NULL != mCameraAdapter)) {
#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
//pass capture timestamp along with the camera adapter command
ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_START_IMAGE_CAPTURE, (int) &mStartCapture);
CameraHal::PPM("Takepicture capture started: ", &mStartCapture);
#else
ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_START_IMAGE_CAPTURE);
#endif
}
return ret;
}
/**
@brief Cancel a picture that was started with takePicture.
Calling this method when no picture is being taken is a no-op.
@param none
@return NO_ERROR If cancel succeeded. Cancel can succeed if image callback is not sent
@todo Define error codes
*/
status_t CameraHal::cancelPicture( )
{
LOG_FUNCTION_NAME;
status_t ret = NO_ERROR;
ret = signalEndImageCapture();
return NO_ERROR;
}
/**
@brief Return the camera parameters.
@param none
@return Currently configured camera parameters
*/
char* CameraHal::getParameters()
{
android::String8 params_str8;
char* params_string;
const char * valstr = NULL;
LOG_FUNCTION_NAME;
if( NULL != mCameraAdapter )
{
mCameraAdapter->getParameters(mParameters);
}
if ( (valstr = mParameters.get(TICameraParameters::KEY_S3D_CAP_FRAME_LAYOUT)) != NULL ) {
if (!strcmp(TICameraParameters::S3D_TB_FULL, valstr)) {
mParameters.set(android::CameraParameters::KEY_SUPPORTED_PICTURE_SIZES, mParameters.get(TICameraParameters::KEY_SUPPORTED_PICTURE_TOPBOTTOM_SIZES));
} else if (!strcmp(TICameraParameters::S3D_SS_FULL, valstr)) {
mParameters.set(android::CameraParameters::KEY_SUPPORTED_PICTURE_SIZES, mParameters.get(TICameraParameters::KEY_SUPPORTED_PICTURE_SIDEBYSIDE_SIZES));
} else if ((!strcmp(TICameraParameters::S3D_TB_SUBSAMPLED, valstr))
|| (!strcmp(TICameraParameters::S3D_SS_SUBSAMPLED, valstr))) {
mParameters.set(android::CameraParameters::KEY_SUPPORTED_PICTURE_SIZES, mParameters.get(TICameraParameters::KEY_SUPPORTED_PICTURE_SUBSAMPLED_SIZES));
}
}
if ( (valstr = mParameters.get(TICameraParameters::KEY_S3D_PRV_FRAME_LAYOUT)) != NULL ) {
if (!strcmp(TICameraParameters::S3D_TB_FULL, valstr)) {
mParameters.set(android::CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES, mParameters.get(TICameraParameters::KEY_SUPPORTED_PREVIEW_TOPBOTTOM_SIZES));
} else if (!strcmp(TICameraParameters::S3D_SS_FULL, valstr)) {
mParameters.set(android::CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES, mParameters.get(TICameraParameters::KEY_SUPPORTED_PREVIEW_SIDEBYSIDE_SIZES));
} else if ((!strcmp(TICameraParameters::S3D_TB_SUBSAMPLED, valstr))
|| (!strcmp(TICameraParameters::S3D_SS_SUBSAMPLED, valstr))) {
mParameters.set(android::CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES, mParameters.get(TICameraParameters::KEY_SUPPORTED_PREVIEW_SUBSAMPLED_SIZES));
}
}
android::CameraParameters mParams = mParameters;
// Handle RECORDING_HINT to Set/Reset Video Mode Parameters
valstr = mParameters.get(android::CameraParameters::KEY_RECORDING_HINT);
if(valstr != NULL)
{
if(strcmp(valstr, android::CameraParameters::TRUE) == 0)
{
//HACK FOR MMS MODE
resetPreviewRes(&mParams);
}
}
// do not send internal parameters to upper layers
mParams.remove(TICameraParameters::KEY_RECORDING_HINT);
mParams.remove(TICameraParameters::KEY_AUTO_FOCUS_LOCK);
params_str8 = mParams.flatten();
// camera service frees this string...
params_string = (char*) malloc(sizeof(char) * (params_str8.length()+1));
strcpy(params_string, params_str8.string());
LOG_FUNCTION_NAME_EXIT;
///Return the current set of parameters
return params_string;
}
#ifdef OMAP_ENHANCEMENT_CPCAM
/**
@brief Starts reprocessing operation.
*/
status_t CameraHal::reprocess(const char *params)
{
status_t ret = NO_ERROR;
int bufferCount = 0;
CameraAdapter::BuffersDescriptor desc;
CameraBuffer *reprocBuffers = NULL;
android::ShotParameters shotParams;
const char *valStr = NULL;
struct timeval startReprocess;
android::AutoMutex lock(mLock);
LOG_FUNCTION_NAME;
#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
gettimeofday(&startReprocess, NULL);
#endif
// 0. Get tap in surface
if (strlen(params) > 0) {
android::String8 shotParams8(params);
shotParams.unflatten(shotParams8);
}
valStr = shotParams.get(android::ShotParameters::KEY_CURRENT_TAP_IN);
if (valStr != NULL) {
int index = -1;
for (unsigned int i = 0; i < mInAdapters.size(); i++) {
if(mInAdapters.itemAt(i)->match(valStr)) {
index = i;
break;
}
}
if (index < 0) {
CAMHAL_LOGE("Invalid tap in surface passed to camerahal");
return BAD_VALUE;
}
CAMHAL_LOGD("Found matching in adapter at %d", index);
mBufferSourceAdapter_In = mInAdapters.itemAt(index);
} else {
CAMHAL_LOGE("No tap in surface sent with shot config!");
return BAD_VALUE;
}
// 1. Get buffers
if (mBufferSourceAdapter_In.get()) {
reprocBuffers = mBufferSourceAdapter_In->getBufferList(&bufferCount);
}
if (!reprocBuffers) {
CAMHAL_LOGE("Error: couldn't get input buffers for reprocess()");
goto exit;
}
#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
CameraHal::PPM("Got reprocess buffers: ", &startReprocess);
#endif
// 2. Get buffer information and parse parameters
{
shotParams.setBurst(bufferCount);
}
#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
memcpy(&reprocBuffers->ppmStamp, &startReprocess, sizeof(struct timeval));
#endif
// 3. Give buffer to camera adapter
desc.mBuffers = reprocBuffers;
desc.mOffsets = 0;
desc.mFd = 0;
desc.mLength = 0;
desc.mCount = (size_t) bufferCount;
desc.mMaxQueueable = (size_t) bufferCount;
ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_USE_BUFFERS_REPROCESS, (int) &desc);
if (ret != NO_ERROR) {
CAMHAL_LOGE("Error calling camera use buffers");
goto exit;
}
#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
CameraHal::PPM("Reprocess buffers registered: ", &startReprocess);
#endif
// 4. Start reprocessing
ret = mBufferSourceAdapter_In->enableDisplay(0, 0, NULL);
if (ret != NO_ERROR) {
CAMHAL_LOGE("Error enabling tap in point");
goto exit;
}
// 5. Start capturing
ret = __takePicture(shotParams.flatten().string(), &startReprocess);
exit:
return ret;
}
/**
@brief Cancels current reprocessing operation
*/
status_t CameraHal::cancel_reprocess( )
{
LOG_FUNCTION_NAME;
status_t ret = NO_ERROR;
ret = signalEndImageCapture();
return NO_ERROR;
}
#endif
void CameraHal::putParameters(char *parms)
{
free(parms);
}
/**
@brief Send command to camera driver.
@param none
@return NO_ERROR If the command succeeds
@todo Define the error codes that this function can return
*/
status_t CameraHal::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2)
{
status_t ret = NO_ERROR;
LOG_FUNCTION_NAME;
if ( ( NO_ERROR == ret ) && ( NULL == mCameraAdapter ) )
{
CAMHAL_LOGEA("No CameraAdapter instance");
return -EINVAL;
}
///////////////////////////////////////////////////////
// Following commands do NOT need preview to be started
///////////////////////////////////////////////////////
switch ( cmd ) {
#ifdef ANDROID_API_JB_OR_LATER
case CAMERA_CMD_ENABLE_FOCUS_MOVE_MSG:
{
const bool enable = static_cast<bool>(arg1);
android::AutoMutex lock(mLock);
if ( enable ) {
mMsgEnabled |= CAMERA_MSG_FOCUS_MOVE;
} else {
mMsgEnabled &= ~CAMERA_MSG_FOCUS_MOVE;
}
}
return OK;
#endif
}
if ( ret == OK && !previewEnabled()
#ifdef OMAP_ENHANCEMENT_VTC
&& (cmd != CAMERA_CMD_PREVIEW_INITIALIZATION)
#endif
) {
CAMHAL_LOGEA("Preview is not running");
ret = -EINVAL;
}
///////////////////////////////////////////////////////
// Following commands NEED preview to be started
///////////////////////////////////////////////////////
if ( NO_ERROR == ret )
{
switch(cmd)
{
case CAMERA_CMD_START_SMOOTH_ZOOM:
ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_START_SMOOTH_ZOOM, arg1);
break;
case CAMERA_CMD_STOP_SMOOTH_ZOOM:
ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_STOP_SMOOTH_ZOOM);
break;
case CAMERA_CMD_START_FACE_DETECTION:
ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_START_FD);
break;
case CAMERA_CMD_STOP_FACE_DETECTION:
ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_STOP_FD);
break;
#ifdef OMAP_ENHANCEMENT_VTC
case CAMERA_CMD_PREVIEW_DEINITIALIZATION:
if(mDisplayAdapter.get() != NULL) {
///Stop the buffer display first
mDisplayAdapter->disableDisplay();
}
if(mAppCallbackNotifier.get() != NULL) {
//Stop the callback sending
mAppCallbackNotifier->stop();
mAppCallbackNotifier->flushAndReturnFrames();
mAppCallbackNotifier->stopPreviewCallbacks();
}
ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_DESTROY_TUNNEL);
mTunnelSetup = false;
break;
case CAMERA_CMD_PREVIEW_INITIALIZATION:
ret = cameraPreviewInitialization();
break;
#endif
default:
break;
};
}
LOG_FUNCTION_NAME_EXIT;
return ret;
}
/**
@brief Release the hardware resources owned by this object.
Note that this is *not* done in the destructor.
@param none
@return none
*/
void CameraHal::release()
{
LOG_FUNCTION_NAME;
///@todo Investigate on how release is used by CameraService. Vaguely remember that this is called
///just before CameraHal object destruction
deinitialize();
LOG_FUNCTION_NAME_EXIT;
}
/**
@brief Dump state of the camera hardware
@param[in] fd File descriptor
@param[in] args Arguments
@return NO_ERROR Dump succeeded
@todo Error codes for dump fail
*/
status_t CameraHal::dump(int fd) const
{
LOG_FUNCTION_NAME;
///Implement this method when the h/w dump function is supported on Ducati side
return NO_ERROR;
}
/*-------------Camera Hal Interface Method definitions ENDS here--------------------*/
/*-------------Camera Hal Internal Method definitions STARTS here--------------------*/
/**
@brief Constructor of CameraHal
Member variables are initialized here. No allocations should be done here as we
don't use c++ exceptions in the code.
*/
CameraHal::CameraHal(int cameraId)
{
LOG_FUNCTION_NAME;
///Initialize all the member variables to their defaults
mPreviewEnabled = false;
mPreviewBuffers = NULL;
mImageBuffers = NULL;
mBufProvider = NULL;
mPreviewStartInProgress = false;
mVideoBuffers = NULL;
mVideoBufProvider = NULL;
mRecordingEnabled = false;
mDisplayPaused = false;
mSetPreviewWindowCalled = false;
mMsgEnabled = 0;
mAppCallbackNotifier = NULL;
mMemoryManager = NULL;
mCameraAdapter = NULL;
mBracketingEnabled = false;
mBracketingRunning = false;
mEventProvider = NULL;
mBracketRangePositive = 1;
mBracketRangeNegative = 1;
mMaxZoomSupported = 0;
mShutterEnabled = true;
mMeasurementEnabled = false;
mPreviewDataBuffers = NULL;
mCameraProperties = NULL;
mCurrentTime = 0;
mFalsePreview = 0;
mImageOffsets = NULL;
mImageLength = 0;
mImageFd = 0;
mImageCount = 0;
mVideoOffsets = NULL;
mVideoFd = 0;
mVideoLength = 0;
mPreviewDataOffsets = NULL;
mPreviewDataFd = 0;
mPreviewDataLength = 0;
mPreviewFd = 0;
mPreviewWidth = 0;
mPreviewHeight = 0;
mPreviewLength = 0;
mPreviewOffsets = NULL;
mPreviewRunning = 0;
mPreviewStateOld = 0;
mRecordingEnabled = 0;
mRecordEnabled = 0;
mSensorListener = NULL;
mVideoWidth = 0;
mVideoHeight = 0;
#ifdef OMAP_ENHANCEMENT_VTC
mVTCUseCase = false;
mTunnelSetup = false;
#endif
mPreviewInitializationDone = false;
#ifdef OMAP_ENHANCEMENT_CPCAM
mExtendedPreviewStreamOps = 0;
#endif
//These values depends on the sensor characteristics
mRawCapture = false;
#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
//Initialize the CameraHAL constructor timestamp, which is used in the
// PPM() method as time reference if the user does not supply one.
gettimeofday(&ppm_start, NULL);
#endif
mCameraIndex = cameraId;
LOG_FUNCTION_NAME_EXIT;
}
/**
@brief Destructor of CameraHal
This function simply calls deinitialize() to free up memory allocate during construct
phase
*/
CameraHal::~CameraHal()
{
LOG_FUNCTION_NAME;
///Call de-initialize here once more - it is the last chance for us to relinquish all the h/w and s/w resources
deinitialize();
if ( NULL != mEventProvider )
{
mEventProvider->disableEventNotification(CameraHalEvent::ALL_EVENTS);
delete mEventProvider;
mEventProvider = NULL;
}
/// Free the callback notifier
mAppCallbackNotifier.clear();
/// Free the display adapter
mDisplayAdapter.clear();
if ( NULL != mCameraAdapter ) {
int strongCount = mCameraAdapter->getStrongCount();
mCameraAdapter->decStrong(mCameraAdapter);
mCameraAdapter = NULL;
}
freeImageBufs();
freeRawBufs();
/// Free the memory manager
mMemoryManager.clear();
LOG_FUNCTION_NAME_EXIT;
}
/**
@brief Initialize the Camera HAL
Creates CameraAdapter, AppCallbackNotifier, DisplayAdapter and MemoryManager
@param None
@return NO_ERROR - On success
NO_MEMORY - On failure to allocate memory for any of the objects
@remarks Camera Hal internal function
*/
status_t CameraHal::initialize(CameraProperties::Properties* properties)
{
LOG_FUNCTION_NAME;
int sensor_index = 0;
const char* sensor_name = NULL;
///Initialize the event mask used for registering an event provider for AppCallbackNotifier
///Currently, registering all events as to be coming from CameraAdapter
int32_t eventMask = CameraHalEvent::ALL_EVENTS;
// Get my camera properties
mCameraProperties = properties;
if(!mCameraProperties)
{
goto fail_loop;
}
// Dump the properties of this Camera
// will only print if DEBUG macro is defined
mCameraProperties->dump();
if (strcmp(CameraProperties::DEFAULT_VALUE, mCameraProperties->get(CameraProperties::CAMERA_SENSOR_INDEX)) != 0 )
{
sensor_index = atoi(mCameraProperties->get(CameraProperties::CAMERA_SENSOR_INDEX));
}
if (strcmp(CameraProperties::DEFAULT_VALUE, mCameraProperties->get(CameraProperties::CAMERA_NAME)) != 0 ) {
sensor_name = mCameraProperties->get(CameraProperties::CAMERA_NAME);
}
CAMHAL_LOGDB("Sensor index= %d; Sensor name= %s", sensor_index, sensor_name);
if (strcmp(sensor_name, V4L_CAMERA_NAME_USB) == 0) {
#ifdef V4L_CAMERA_ADAPTER
mCameraAdapter = V4LCameraAdapter_Factory(sensor_index);
#endif
}
else {
#ifdef OMX_CAMERA_ADAPTER
mCameraAdapter = OMXCameraAdapter_Factory(sensor_index);
#endif
}
if ( ( NULL == mCameraAdapter ) || (mCameraAdapter->initialize(properties)!=NO_ERROR))
{
CAMHAL_LOGEA("Unable to create or initialize CameraAdapter");
mCameraAdapter = NULL;
goto fail_loop;
}
mCameraAdapter->incStrong(mCameraAdapter);
mCameraAdapter->registerImageReleaseCallback(releaseImageBuffers, (void *) this);
mCameraAdapter->registerEndCaptureCallback(endImageCapture, (void *)this);
if(!mAppCallbackNotifier.get())
{
/// Create the callback notifier
mAppCallbackNotifier = new AppCallbackNotifier();
if( ( NULL == mAppCallbackNotifier.get() ) || ( mAppCallbackNotifier->initialize() != NO_ERROR))
{
CAMHAL_LOGEA("Unable to create or initialize AppCallbackNotifier");
goto fail_loop;
}
}
if(!mMemoryManager.get())
{
/// Create Memory Manager
mMemoryManager = new MemoryManager();
if( ( NULL == mMemoryManager.get() ) || ( mMemoryManager->initialize() != NO_ERROR))
{
CAMHAL_LOGEA("Unable to create or initialize MemoryManager");
goto fail_loop;
}
}
///Setup the class dependencies...
///AppCallbackNotifier has to know where to get the Camera frames and the events like auto focus lock etc from.
///CameraAdapter is the one which provides those events
///Set it as the frame and event providers for AppCallbackNotifier
///@remarks setEventProvider API takes in a bit mask of events for registering a provider for the different events
/// That way, if events can come from DisplayAdapter in future, we will be able to add it as provider
/// for any event
mAppCallbackNotifier->setEventProvider(eventMask, mCameraAdapter);
mAppCallbackNotifier->setFrameProvider(mCameraAdapter);
///Any dynamic errors that happen during the camera use case has to be propagated back to the application
///via CAMERA_MSG_ERROR. AppCallbackNotifier is the class that notifies such errors to the application
///Set it as the error handler for CameraAdapter
mCameraAdapter->setErrorHandler(mAppCallbackNotifier.get());
///Start the callback notifier
if(mAppCallbackNotifier->start() != NO_ERROR)
{
CAMHAL_LOGEA("Couldn't start AppCallbackNotifier");
goto fail_loop;
}
CAMHAL_LOGDA("Started AppCallbackNotifier..");
mAppCallbackNotifier->setMeasurements(mMeasurementEnabled);
///Initialize default parameters
initDefaultParameters();
if ( setParameters(mParameters) != NO_ERROR )
{
CAMHAL_LOGEA("Failed to set default parameters?!");
}
// register for sensor events
mSensorListener = new SensorListener();
if (mSensorListener.get()) {
if (mSensorListener->initialize() == NO_ERROR) {
mSensorListener->setCallbacks(orientation_cb, this);
mSensorListener->enableSensor(SensorListener::SENSOR_ORIENTATION);
} else {
CAMHAL_LOGEA("Error initializing SensorListener. not fatal, continuing");
mSensorListener.clear();
mSensorListener = NULL;
}
}
LOG_FUNCTION_NAME_EXIT;
return NO_ERROR;
fail_loop:
///Free up the resources because we failed somewhere up
deinitialize();
LOG_FUNCTION_NAME_EXIT;
return NO_MEMORY;
}
bool CameraHal::isResolutionValid(unsigned int width, unsigned int height, const char *supportedResolutions)
{
bool ret = false;
status_t status = NO_ERROR;
char tmpBuffer[MAX_PROP_VALUE_LENGTH];
char *pos = NULL;
LOG_FUNCTION_NAME;
if (NULL == supportedResolutions) {
CAMHAL_LOGEA("Invalid supported resolutions string");
goto exit;
}
status = snprintf(tmpBuffer, MAX_PROP_VALUE_LENGTH - 1, "%dx%d", width, height);
if (0 > status) {
CAMHAL_LOGEA("Error encountered while generating validation string");
goto exit;
}
ret = isParameterValid(tmpBuffer, supportedResolutions);
exit:
LOG_FUNCTION_NAME_EXIT;
return ret;
}
bool CameraHal::isFpsRangeValid(int fpsMin, int fpsMax, const char *supportedFpsRanges)
{
bool ret = false;
char supported[MAX_PROP_VALUE_LENGTH];
char *pos;
int suppFpsRangeArray[2];
int i = 0;
LOG_FUNCTION_NAME;
if ( NULL == supportedFpsRanges ) {
CAMHAL_LOGEA("Invalid supported FPS ranges string");
return false;
}
if (fpsMin <= 0 || fpsMax <= 0 || fpsMin > fpsMax) {
return false;
}
strncpy(supported, supportedFpsRanges, MAX_PROP_VALUE_LENGTH);
pos = strtok(supported, " (,)");
while (pos != NULL) {
suppFpsRangeArray[i] = atoi(pos);
if (i++) {
if (fpsMin >= suppFpsRangeArray[0] && fpsMax <= suppFpsRangeArray[1]) {
ret = true;
break;
}
i = 0;
}
pos = strtok(NULL, " (,)");
}
LOG_FUNCTION_NAME_EXIT;
return ret;
}
bool CameraHal::isParameterValid(const char *param, const char *supportedParams)
{
bool ret = false;
char *pos;
char supported[MAX_PROP_VALUE_LENGTH];
LOG_FUNCTION_NAME;
if (NULL == supportedParams) {
CAMHAL_LOGEA("Invalid supported parameters string");
goto exit;
}
if (NULL == param) {
CAMHAL_LOGEA("Invalid parameter string");
goto exit;
}
strncpy(supported, supportedParams, MAX_PROP_VALUE_LENGTH - 1);
pos = strtok(supported, ",");
while (pos != NULL) {
if (!strcmp(pos, param)) {
ret = true;
break;
}
pos = strtok(NULL, ",");
}
exit:
LOG_FUNCTION_NAME_EXIT;
return ret;
}
bool CameraHal::isParameterValid(int param, const char *supportedParams)
{
bool ret = false;
status_t status;
char tmpBuffer[MAX_PROP_VALUE_LENGTH];
LOG_FUNCTION_NAME;
if (NULL == supportedParams) {
CAMHAL_LOGEA("Invalid supported parameters string");
goto exit;
}
status = snprintf(tmpBuffer, MAX_PROP_VALUE_LENGTH - 1, "%d", param);
if (0 > status) {
CAMHAL_LOGEA("Error encountered while generating validation string");
goto exit;
}
ret = isParameterValid(tmpBuffer, supportedParams);
exit:
LOG_FUNCTION_NAME_EXIT;
return ret;
}
status_t CameraHal::doesSetParameterNeedUpdate(const char* new_param, const char* old_param, bool& update) {
if (!new_param || !old_param) {
return -EINVAL;
}
// if params mismatch we should update parameters for camera adapter
if ((strcmp(new_param, old_param) != 0)) {
update = true;
}
return NO_ERROR;
}
status_t CameraHal::parseResolution(const char *resStr, int &width, int &height)
{
status_t ret = NO_ERROR;
char *ctx, *pWidth, *pHeight;
const char *sep = "x";
LOG_FUNCTION_NAME;
if ( NULL == resStr )
{
return -EINVAL;
}
//This fixes "Invalid input resolution"
char *resStr_copy = (char *)malloc(strlen(resStr) + 1);
if ( NULL != resStr_copy )
{
strcpy(resStr_copy, resStr);
pWidth = strtok_r(resStr_copy, sep, &ctx);
if ( NULL != pWidth )
{
width = atoi(pWidth);
}
else
{
CAMHAL_LOGEB("Invalid input resolution %s", resStr);
ret = -EINVAL;
}
}
if ( NO_ERROR == ret )
{
pHeight = strtok_r(NULL, sep, &ctx);
if ( NULL != pHeight )
{
height = atoi(pHeight);
}
else
{
CAMHAL_LOGEB("Invalid input resolution %s", resStr);
ret = -EINVAL;
}
}
free(resStr_copy);
resStr_copy = NULL;
LOG_FUNCTION_NAME_EXIT;
return ret;
}
void CameraHal::insertSupportedParams()
{
LOG_FUNCTION_NAME;
android::CameraParameters &p = mParameters;
///Set the name of the camera
p.set(TICameraParameters::KEY_CAMERA_NAME, mCameraProperties->get(CameraProperties::CAMERA_NAME));
mMaxZoomSupported = atoi(mCameraProperties->get(CameraProperties::SUPPORTED_ZOOM_STAGES));
p.set(android::CameraParameters::KEY_SUPPORTED_PICTURE_SIZES, mCameraProperties->get(CameraProperties::SUPPORTED_PICTURE_SIZES));
p.set(android::CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS, mCameraProperties->get(CameraProperties::SUPPORTED_PICTURE_FORMATS));
p.set(android::CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_SIZES));
p.set(android::CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_FORMATS));
p.set(TICameraParameters::KEY_SUPPORTED_PICTURE_SUBSAMPLED_SIZES, mCameraProperties->get(CameraProperties::SUPPORTED_PICTURE_SUBSAMPLED_SIZES));
p.set(TICameraParameters::KEY_SUPPORTED_PICTURE_SIDEBYSIDE_SIZES, mCameraProperties->get(CameraProperties::SUPPORTED_PICTURE_SIDEBYSIDE_SIZES));
p.set(TICameraParameters::KEY_SUPPORTED_PICTURE_TOPBOTTOM_SIZES, mCameraProperties->get(CameraProperties::SUPPORTED_PICTURE_TOPBOTTOM_SIZES));
p.set(TICameraParameters::KEY_SUPPORTED_PREVIEW_SUBSAMPLED_SIZES, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_SUBSAMPLED_SIZES));
p.set(TICameraParameters::KEY_SUPPORTED_PREVIEW_SIDEBYSIDE_SIZES, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_SIDEBYSIDE_SIZES));
p.set(TICameraParameters::KEY_SUPPORTED_PREVIEW_TOPBOTTOM_SIZES, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_TOPBOTTOM_SIZES));
p.set(android::CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_FRAME_RATES));
p.set(TICameraParameters::KEY_FRAMERATES_EXT_SUPPORTED, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_FRAME_RATES_EXT));
p.set(android::CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE, mCameraProperties->get(CameraProperties::FRAMERATE_RANGE_SUPPORTED));
p.set(TICameraParameters::KEY_FRAMERATE_RANGES_EXT_SUPPORTED, mCameraProperties->get(CameraProperties::FRAMERATE_RANGE_EXT_SUPPORTED));
p.set(android::CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES, mCameraProperties->get(CameraProperties::SUPPORTED_THUMBNAIL_SIZES));
p.set(android::CameraParameters::KEY_SUPPORTED_WHITE_BALANCE, mCameraProperties->get(CameraProperties::SUPPORTED_WHITE_BALANCE));
p.set(android::CameraParameters::KEY_SUPPORTED_EFFECTS, mCameraProperties->get(CameraProperties::SUPPORTED_EFFECTS));
p.set(android::CameraParameters::KEY_SUPPORTED_SCENE_MODES, mCameraProperties->get(CameraProperties::SUPPORTED_SCENE_MODES));
p.set(android::CameraParameters::KEY_SUPPORTED_FLASH_MODES, mCameraProperties->get(CameraProperties::SUPPORTED_FLASH_MODES));
p.set(android::CameraParameters::KEY_SUPPORTED_FOCUS_MODES, mCameraProperties->get(CameraProperties::SUPPORTED_FOCUS_MODES));
p.set(android::CameraParameters::KEY_SUPPORTED_ANTIBANDING, mCameraProperties->get(CameraProperties::SUPPORTED_ANTIBANDING));
p.set(android::CameraParameters::KEY_MAX_EXPOSURE_COMPENSATION, mCameraProperties->get(CameraProperties::SUPPORTED_EV_MAX));
p.set(android::CameraParameters::KEY_MIN_EXPOSURE_COMPENSATION, mCameraProperties->get(CameraProperties::SUPPORTED_EV_MIN));
p.set(android::CameraParameters::KEY_EXPOSURE_COMPENSATION_STEP, mCameraProperties->get(CameraProperties::SUPPORTED_EV_STEP));
p.set(TICameraParameters::KEY_SUPPORTED_EXPOSURE, mCameraProperties->get(CameraProperties::SUPPORTED_EXPOSURE_MODES));
p.set(TICameraParameters::KEY_SUPPORTED_MANUAL_EXPOSURE_MIN, mCameraProperties->get(CameraProperties::SUPPORTED_MANUAL_EXPOSURE_MIN));
p.set(TICameraParameters::KEY_SUPPORTED_MANUAL_EXPOSURE_MAX, mCameraProperties->get(CameraProperties::SUPPORTED_MANUAL_EXPOSURE_MAX));
p.set(TICameraParameters::KEY_SUPPORTED_MANUAL_EXPOSURE_STEP, mCameraProperties->get(CameraProperties::SUPPORTED_MANUAL_EXPOSURE_STEP));
p.set(TICameraParameters::KEY_SUPPORTED_MANUAL_GAIN_ISO_MIN, mCameraProperties->get(CameraProperties::SUPPORTED_MANUAL_GAIN_ISO_MIN));
p.set(TICameraParameters::KEY_SUPPORTED_MANUAL_GAIN_ISO_MAX, mCameraProperties->get(CameraProperties::SUPPORTED_MANUAL_GAIN_ISO_MAX));
p.set(TICameraParameters::KEY_SUPPORTED_MANUAL_GAIN_ISO_STEP, mCameraProperties->get(CameraProperties::SUPPORTED_MANUAL_GAIN_ISO_STEP));
p.set(TICameraParameters::KEY_SUPPORTED_ISO_VALUES, mCameraProperties->get(CameraProperties::SUPPORTED_ISO_VALUES));
p.set(android::CameraParameters::KEY_ZOOM_RATIOS, mCameraProperties->get(CameraProperties::SUPPORTED_ZOOM_RATIOS));
p.set(android::CameraParameters::KEY_MAX_ZOOM, mCameraProperties->get(CameraProperties::SUPPORTED_ZOOM_STAGES));
p.set(android::CameraParameters::KEY_ZOOM_SUPPORTED, mCameraProperties->get(CameraProperties::ZOOM_SUPPORTED));
p.set(android::CameraParameters::KEY_SMOOTH_ZOOM_SUPPORTED, mCameraProperties->get(CameraProperties::SMOOTH_ZOOM_SUPPORTED));
p.set(TICameraParameters::KEY_SUPPORTED_IPP, mCameraProperties->get(CameraProperties::SUPPORTED_IPP_MODES));
p.set(TICameraParameters::KEY_S3D_PRV_FRAME_LAYOUT_VALUES, mCameraProperties->get(CameraProperties::S3D_PRV_FRAME_LAYOUT_VALUES));
p.set(TICameraParameters::KEY_S3D_CAP_FRAME_LAYOUT_VALUES, mCameraProperties->get(CameraProperties::S3D_CAP_FRAME_LAYOUT_VALUES));
p.set(TICameraParameters::KEY_AUTOCONVERGENCE_MODE_VALUES, mCameraProperties->get(CameraProperties::AUTOCONVERGENCE_MODE_VALUES));
p.set(TICameraParameters::KEY_SUPPORTED_MANUAL_CONVERGENCE_MIN, mCameraProperties->get(CameraProperties::SUPPORTED_MANUAL_CONVERGENCE_MIN));
p.set(TICameraParameters::KEY_SUPPORTED_MANUAL_CONVERGENCE_MAX, mCameraProperties->get(CameraProperties::SUPPORTED_MANUAL_CONVERGENCE_MAX));
p.set(TICameraParameters::KEY_SUPPORTED_MANUAL_CONVERGENCE_STEP, mCameraProperties->get(CameraProperties::SUPPORTED_MANUAL_CONVERGENCE_STEP));
p.set(android::CameraParameters::KEY_VIDEO_STABILIZATION_SUPPORTED, mCameraProperties->get(CameraProperties::VSTAB_SUPPORTED));
p.set(TICameraParameters::KEY_VNF_SUPPORTED, mCameraProperties->get(CameraProperties::VNF_SUPPORTED));
p.set(android::CameraParameters::KEY_AUTO_EXPOSURE_LOCK_SUPPORTED, mCameraProperties->get(CameraProperties::AUTO_EXPOSURE_LOCK_SUPPORTED));
p.set(android::CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK_SUPPORTED, mCameraProperties->get(CameraProperties::AUTO_WHITEBALANCE_LOCK_SUPPORTED));
p.set(android::CameraParameters::KEY_VIDEO_SNAPSHOT_SUPPORTED, mCameraProperties->get(CameraProperties::VIDEO_SNAPSHOT_SUPPORTED));
p.set(TICameraParameters::KEY_MECHANICAL_MISALIGNMENT_CORRECTION_SUPPORTED, mCameraProperties->get(CameraProperties::MECHANICAL_MISALIGNMENT_CORRECTION_SUPPORTED));
p.set(TICameraParameters::KEY_CAP_MODE_VALUES, mCameraProperties->get(CameraProperties::CAP_MODE_VALUES));
LOG_FUNCTION_NAME_EXIT;
}
void CameraHal::initDefaultParameters()
{
//Purpose of this function is to initialize the default current and supported parameters for the currently
//selected camera.
android::CameraParameters &p = mParameters;
int currentRevision, adapterRevision;
status_t ret = NO_ERROR;
int width, height;
const char *valstr;
LOG_FUNCTION_NAME;
insertSupportedParams();
ret = parseResolution(mCameraProperties->get(CameraProperties::PREVIEW_SIZE), width, height);
if ( NO_ERROR == ret )
{
p.setPreviewSize(width, height);
}
else
{
p.setPreviewSize(MIN_WIDTH, MIN_HEIGHT);
}
ret = parseResolution(mCameraProperties->get(CameraProperties::PICTURE_SIZE), width, height);
if ( NO_ERROR == ret )
{
p.setPictureSize(width, height);
}
else
{
p.setPictureSize(PICTURE_WIDTH, PICTURE_HEIGHT);
}
ret = parseResolution(mCameraProperties->get(CameraProperties::JPEG_THUMBNAIL_SIZE), width, height);
if ( NO_ERROR == ret )
{
p.set(android::CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, width);
p.set(android::CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, height);
}
else
{
p.set(android::CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, MIN_WIDTH);
p.set(android::CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, MIN_HEIGHT);
}
//Insert default values
p.setPreviewFrameRate(atoi(mCameraProperties->get(CameraProperties::PREVIEW_FRAME_RATE)));
p.set(android::CameraParameters::KEY_PREVIEW_FPS_RANGE, mCameraProperties->get(CameraProperties::FRAMERATE_RANGE));
p.setPreviewFormat(mCameraProperties->get(CameraProperties::PREVIEW_FORMAT));
p.setPictureFormat(mCameraProperties->get(CameraProperties::PICTURE_FORMAT));
p.set(android::CameraParameters::KEY_JPEG_QUALITY, mCameraProperties->get(CameraProperties::JPEG_QUALITY));
p.set(android::CameraParameters::KEY_WHITE_BALANCE, mCameraProperties->get(CameraProperties::WHITEBALANCE));
p.set(android::CameraParameters::KEY_EFFECT, mCameraProperties->get(CameraProperties::EFFECT));
p.set(android::CameraParameters::KEY_ANTIBANDING, mCameraProperties->get(CameraProperties::ANTIBANDING));
p.set(android::CameraParameters::KEY_FLASH_MODE, mCameraProperties->get(CameraProperties::FLASH_MODE));
p.set(android::CameraParameters::KEY_FOCUS_MODE, mCameraProperties->get(CameraProperties::FOCUS_MODE));
p.set(android::CameraParameters::KEY_EXPOSURE_COMPENSATION, mCameraProperties->get(CameraProperties::EV_COMPENSATION));
p.set(android::CameraParameters::KEY_SCENE_MODE, mCameraProperties->get(CameraProperties::SCENE_MODE));
p.set(android::CameraParameters::KEY_ZOOM, mCameraProperties->get(CameraProperties::ZOOM));
p.set(TICameraParameters::KEY_CONTRAST, mCameraProperties->get(CameraProperties::CONTRAST));
p.set(TICameraParameters::KEY_SATURATION, mCameraProperties->get(CameraProperties::SATURATION));
p.set(TICameraParameters::KEY_BRIGHTNESS, mCameraProperties->get(CameraProperties::BRIGHTNESS));
p.set(TICameraParameters::KEY_SHARPNESS, mCameraProperties->get(CameraProperties::SHARPNESS));
p.set(TICameraParameters::KEY_EXPOSURE_MODE, mCameraProperties->get(CameraProperties::EXPOSURE_MODE));
p.set(TICameraParameters::KEY_MANUAL_EXPOSURE, mCameraProperties->get(CameraProperties::SUPPORTED_MANUAL_EXPOSURE_MIN));
p.set(TICameraParameters::KEY_MANUAL_EXPOSURE_RIGHT, mCameraProperties->get(CameraProperties::SUPPORTED_MANUAL_EXPOSURE_MIN));
p.set(TICameraParameters::KEY_MANUAL_GAIN_ISO, mCameraProperties->get(CameraProperties::SUPPORTED_MANUAL_GAIN_ISO_MIN));
p.set(TICameraParameters::KEY_MANUAL_GAIN_ISO_RIGHT, mCameraProperties->get(CameraProperties::SUPPORTED_MANUAL_GAIN_ISO_MIN));
p.set(TICameraParameters::KEY_ISO, mCameraProperties->get(CameraProperties::ISO_MODE));
p.set(TICameraParameters::KEY_IPP, mCameraProperties->get(CameraProperties::IPP));
p.set(TICameraParameters::KEY_GBCE, mCameraProperties->get(CameraProperties::GBCE));
p.set(TICameraParameters::KEY_GBCE_SUPPORTED, mCameraProperties->get(CameraProperties::SUPPORTED_GBCE));
p.set(TICameraParameters::KEY_GLBCE, mCameraProperties->get(CameraProperties::GLBCE));
p.set(TICameraParameters::KEY_GLBCE_SUPPORTED, mCameraProperties->get(CameraProperties::SUPPORTED_GLBCE));
p.set(TICameraParameters::KEY_S3D_PRV_FRAME_LAYOUT, mCameraProperties->get(CameraProperties::S3D_PRV_FRAME_LAYOUT));
p.set(TICameraParameters::KEY_S3D_CAP_FRAME_LAYOUT, mCameraProperties->get(CameraProperties::S3D_CAP_FRAME_LAYOUT));
p.set(TICameraParameters::KEY_AUTOCONVERGENCE_MODE, mCameraProperties->get(CameraProperties::AUTOCONVERGENCE_MODE));
p.set(TICameraParameters::KEY_MANUAL_CONVERGENCE, mCameraProperties->get(CameraProperties::MANUAL_CONVERGENCE));
p.set(android::CameraParameters::KEY_VIDEO_STABILIZATION, mCameraProperties->get(CameraProperties::VSTAB));
p.set(TICameraParameters::KEY_VNF, mCameraProperties->get(CameraProperties::VNF));
p.set(android::CameraParameters::KEY_FOCAL_LENGTH, mCameraProperties->get(CameraProperties::FOCAL_LENGTH));
p.set(android::CameraParameters::KEY_HORIZONTAL_VIEW_ANGLE, mCameraProperties->get(CameraProperties::HOR_ANGLE));
p.set(android::CameraParameters::KEY_VERTICAL_VIEW_ANGLE, mCameraProperties->get(CameraProperties::VER_ANGLE));
p.set(TICameraParameters::KEY_SENSOR_ORIENTATION, mCameraProperties->get(CameraProperties::SENSOR_ORIENTATION));
p.set(TICameraParameters::KEY_EXIF_MAKE, mCameraProperties->get(CameraProperties::EXIF_MAKE));
p.set(TICameraParameters::KEY_EXIF_MODEL, mCameraProperties->get(CameraProperties::EXIF_MODEL));
p.set(android::CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, mCameraProperties->get(CameraProperties::JPEG_THUMBNAIL_QUALITY));
p.set(android::CameraParameters::KEY_VIDEO_FRAME_FORMAT, "OMX_TI_COLOR_FormatYUV420PackedSemiPlanar");
p.set(android::CameraParameters::KEY_MAX_NUM_DETECTED_FACES_HW, mCameraProperties->get(CameraProperties::MAX_FD_HW_FACES));
p.set(android::CameraParameters::KEY_MAX_NUM_DETECTED_FACES_SW, mCameraProperties->get(CameraProperties::MAX_FD_SW_FACES));
p.set(TICameraParameters::KEY_MECHANICAL_MISALIGNMENT_CORRECTION, mCameraProperties->get(CameraProperties::MECHANICAL_MISALIGNMENT_CORRECTION));
// Only one area a.k.a Touch AF for now.
// TODO: Add support for multiple focus areas.
p.set(android::CameraParameters::KEY_MAX_NUM_FOCUS_AREAS, mCameraProperties->get(CameraProperties::MAX_FOCUS_AREAS));
p.set(android::CameraParameters::KEY_AUTO_EXPOSURE_LOCK, mCameraProperties->get(CameraProperties::AUTO_EXPOSURE_LOCK));
p.set(android::CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK, mCameraProperties->get(CameraProperties::AUTO_WHITEBALANCE_LOCK));
p.set(android::CameraParameters::KEY_MAX_NUM_METERING_AREAS, mCameraProperties->get(CameraProperties::MAX_NUM_METERING_AREAS));
p.set(TICameraParameters::RAW_WIDTH, mCameraProperties->get(CameraProperties::RAW_WIDTH));
p.set(TICameraParameters::RAW_HEIGHT,mCameraProperties->get(CameraProperties::RAW_HEIGHT));
// TI extensions for enable/disable algos
// Hadcoded for now
p.set(TICameraParameters::KEY_ALGO_EXTERNAL_GAMMA, android::CameraParameters::FALSE);
p.set(TICameraParameters::KEY_ALGO_NSF1, android::CameraParameters::TRUE);
p.set(TICameraParameters::KEY_ALGO_NSF2, android::CameraParameters::TRUE);
p.set(TICameraParameters::KEY_ALGO_SHARPENING, android::CameraParameters::TRUE);
p.set(TICameraParameters::KEY_ALGO_THREELINCOLORMAP, android::CameraParameters::TRUE);
p.set(TICameraParameters::KEY_ALGO_GIC, android::CameraParameters::TRUE);
LOG_FUNCTION_NAME_EXIT;
}
/**
@brief Stop a previously started preview.
@param none
@return none
*/
void CameraHal::forceStopPreview()
{
LOG_FUNCTION_NAME;
// stop bracketing if it is running
if ( mBracketingRunning ) {
stopImageBracketing();
}
if(mDisplayAdapter.get() != NULL) {
///Stop the buffer display first
mDisplayAdapter->disableDisplay();
}
if(mAppCallbackNotifier.get() != NULL) {
//Stop the callback sending
mAppCallbackNotifier->stop();
mAppCallbackNotifier->flushAndReturnFrames();
mAppCallbackNotifier->stopPreviewCallbacks();
}
if ( NULL != mCameraAdapter ) {
// only need to send these control commands to state machine if we are
// passed the LOADED_PREVIEW_STATE
if (mCameraAdapter->getState() > CameraAdapter::LOADED_PREVIEW_STATE) {
// according to javadoc...FD should be stopped in stopPreview
// and application needs to call startFaceDection again
// to restart FD
mCameraAdapter->sendCommand(CameraAdapter::CAMERA_STOP_FD);
}
mCameraAdapter->rollbackToInitializedState();
}
freePreviewBufs();
freePreviewDataBufs();
mPreviewEnabled = false;
mDisplayPaused = false;
mPreviewStartInProgress = false;
LOG_FUNCTION_NAME_EXIT;
}
/**
@brief Deallocates memory for all the resources held by Camera HAL.
Frees the following objects- CameraAdapter, AppCallbackNotifier, DisplayAdapter,
and Memory Manager
@param none
@return none
*/
void CameraHal::deinitialize()
{
LOG_FUNCTION_NAME;
if ( mPreviewEnabled || mDisplayPaused ) {
forceStopPreview();
}
mSetPreviewWindowCalled = false;
if (mSensorListener.get()) {
mSensorListener->disableSensor(SensorListener::SENSOR_ORIENTATION);
mSensorListener.clear();
mSensorListener = NULL;
}
mBufferSourceAdapter_Out.clear();
mBufferSourceAdapter_In.clear();
mOutAdapters.clear();
mInAdapters.clear();
LOG_FUNCTION_NAME_EXIT;
}
status_t CameraHal::storeMetaDataInBuffers(bool enable)
{
LOG_FUNCTION_NAME;
return mAppCallbackNotifier->useMetaDataBufferMode(enable);
LOG_FUNCTION_NAME_EXIT;
}
void CameraHal::getPreferredPreviewRes(int *width, int *height)
{
LOG_FUNCTION_NAME;
// We request Ducati for a higher resolution so preview looks better and then downscale the frame before the callback.
// TODO: This should be moved to configuration constants and boolean flag whether to provide such optimization
// Also consider providing this configurability of the desired display resolution from the application
if ( ( *width == 320 ) && ( *height == 240 ) ) {
*width = 640;
*height = 480;
} else if ( ( *width == 176 ) && ( *height == 144 ) ) {
*width = 704;
*height = 576;
}
LOG_FUNCTION_NAME_EXIT;
}
void CameraHal::resetPreviewRes(android::CameraParameters *params)
{
LOG_FUNCTION_NAME;
if ( (mVideoWidth <= 320) && (mVideoHeight <= 240)){
params->setPreviewSize(mVideoWidth, mVideoHeight);
}
LOG_FUNCTION_NAME_EXIT;
}
void *
camera_buffer_get_omx_ptr (CameraBuffer *buffer)
{
CAMHAL_LOGV("buffer_type %d opaque %p", buffer->type, buffer->opaque);
if (buffer->type == CAMERA_BUFFER_ANW) {
buffer_handle_t *handle = (buffer_handle_t *)buffer->opaque;
CAMHAL_LOGV("anw %08x", *handle);
return (void *)*handle;
} else if (buffer->type == CAMERA_BUFFER_ION) {
return (void *)buffer->fd;
} else {
CAMHAL_LOGV("other %08x", buffer->opaque);
return (void *)buffer->opaque;
}
}
} // namespace Camera
} // namespace Ti