blob: 388adb2e7d378f72f336873fd27946b9f4b91185 [file] [log] [blame]
/*
* 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.
*
*/
#define LOG_TAG "CameraHAL"
#include "CameraHal.h"
#include "ANativeWindowDisplayAdapter.h"
#include "TICameraParameters.h"
#include "CameraProperties.h"
#include <cutils/properties.h>
#include <poll.h>
#include <math.h>
namespace android {
extern "C" CameraAdapter* CameraAdapter_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 = 2;
const uint32_t MessageNotifier::EVENT_BIT_FIELD_POSITION = 0;
const uint32_t MessageNotifier::FRAME_BIT_FIELD_POSITION = 0;
/******************************************************************************/
#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);
}
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 | CAMERA_MSG_FOCUS_MOVE);
{
Mutex::Autolock 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;
{
Mutex::Autolock 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)
{
LOG_FUNCTION_NAME;
Mutex::Autolock lock(mLock);
LOG_FUNCTION_NAME_EXIT;
return (mMsgEnabled & 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;
CameraParameters params;
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 CameraParameters& params)
{
LOG_FUNCTION_NAME;
int w, h;
int w_orig, h_orig;
int framerate,minframerate;
int maxFPS, minFPS;
int error;
int base;
const char *valstr = NULL;
const char *prevFormat;
char *af_coord;
TIUTILS::Message msg;
status_t ret = NO_ERROR;
// Needed for KEY_RECORDING_HINT
bool restartPreviewRequired = false;
bool updateRequired = false;
CameraParameters oldParams(mParameters.flatten());
bool videoMode = false;
char range[MAX_PROP_VALUE_LENGTH];
{
Mutex::Autolock lock(mLock);
///Ensure that preview is not enabled when the below parameters are changed.
if(!previewEnabled())
{
CAMHAL_LOGDB("PreviewFormat %s", params.getPreviewFormat());
if ((valstr = params.getPreviewFormat()) != NULL) {
if ( isParameterValid(valstr, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_FORMATS))) {
mParameters.setPreviewFormat(valstr);
} else {
CAMHAL_LOGEB("Invalid preview format.Supported: %s", mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_FORMATS));
return -EINVAL;
}
}
if ((valstr = params.get(TICameraParameters::KEY_VNF)) != NULL) {
if ( (params.getInt(TICameraParameters::KEY_VNF)==0) || (params.getInt(TICameraParameters::KEY_VNF)==1) ) {
CAMHAL_LOGDB("VNF set %s", params.get(TICameraParameters::KEY_VNF));
mParameters.set(TICameraParameters::KEY_VNF, valstr);
} else {
CAMHAL_LOGEB("ERROR: Invalid VNF: %s", valstr);
ret = -EINVAL;
}
}
if ((valstr = params.get(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),
CameraParameters::TRUE) == 0) {
CAMHAL_LOGDB("VSTAB %s",
params.get(CameraParameters::KEY_VIDEO_STABILIZATION));
mParameters.set(CameraParameters::KEY_VIDEO_STABILIZATION,
params.get(CameraParameters::KEY_VIDEO_STABILIZATION));
} else if (strcmp(valstr, CameraParameters::TRUE) == 0) {
CAMHAL_LOGEB("ERROR: Invalid VSTAB: %s", valstr);
ret = -EINVAL;
} else {
mParameters.set(CameraParameters::KEY_VIDEO_STABILIZATION,
CameraParameters::FALSE);
}
}
if( (valstr = params.get(TICameraParameters::KEY_CAP_MODE)) != NULL)
{
CAMHAL_LOGDB("Capture mode set %s", params.get(TICameraParameters::KEY_CAP_MODE));
mParameters.set(TICameraParameters::KEY_CAP_MODE, valstr);
}
if ((valstr = params.get(TICameraParameters::KEY_IPP)) != NULL) {
if (isParameterValid(valstr,mCameraProperties->get(CameraProperties::SUPPORTED_IPP_MODES))) {
CAMHAL_LOGDB("IPP mode set %s", params.get(TICameraParameters::KEY_IPP));
mParameters.set(TICameraParameters::KEY_IPP, valstr);
} else {
CAMHAL_LOGEB("ERROR: Invalid IPP mode: %s", valstr);
ret = -EINVAL;
}
}
if((valstr = params.get(TICameraParameters::KEY_S3D2D_PREVIEW)) != NULL)
{
CAMHAL_LOGDB("Stereo 3D->2D Preview mode is %s", params.get(TICameraParameters::KEY_S3D2D_PREVIEW));
mParameters.set(TICameraParameters::KEY_S3D2D_PREVIEW, valstr);
}
if((valstr = params.get(TICameraParameters::KEY_AUTOCONVERGENCE)) != NULL)
{
CAMHAL_LOGDB("AutoConvergence mode is %s", params.get(TICameraParameters::KEY_AUTOCONVERGENCE));
mParameters.set(TICameraParameters::KEY_AUTOCONVERGENCE, valstr);
}
}
params.getPreviewSize(&w, &h);
if (w == -1 && h == -1) {
CAMHAL_LOGEA("Unable to get preview size");
return -EINVAL;
}
int oldWidth, oldHeight;
mParameters.getPreviewSize(&oldWidth, &oldHeight);
int orientation =0;
if((valstr = params.get(TICameraParameters::KEY_SENSOR_ORIENTATION)) != NULL)
{
CAMHAL_LOGDB("Sensor Orientation is set to %s", params.get(TICameraParameters::KEY_SENSOR_ORIENTATION));
mParameters.set(TICameraParameters::KEY_SENSOR_ORIENTATION, valstr);
orientation = params.getInt(TICameraParameters::KEY_SENSOR_ORIENTATION);
}
if(orientation ==90 || orientation ==270)
{
if ( !isResolutionValid(h,w, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_SIZES)))
{
CAMHAL_LOGEB("Invalid preview resolution %d x %d", w, h);
return -EINVAL;
}
else
{
mParameters.setPreviewSize(w, h);
mVideoWidth = w;
mVideoHeight = h;
}
}
else
{
if ( !isResolutionValid(w, h, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_SIZES)))
{
CAMHAL_LOGEB("Invalid preview resolution %d x %d", w, h);
return -EINVAL;
}
else
{
mParameters.setPreviewSize(w, h);
}
}
if ( ( oldWidth != w ) || ( oldHeight != h ) )
{
restartPreviewRequired |= true;
}
CAMHAL_LOGDB("PreviewResolution by App %d x %d", w, h);
// Handle RECORDING_HINT to Set/Reset Video Mode Parameters
valstr = params.get(CameraParameters::KEY_RECORDING_HINT);
if(valstr != NULL)
{
if(strcmp(valstr, CameraParameters::TRUE) == 0)
{
CAMHAL_LOGDB("Recording Hint is set to %s", valstr);
mParameters.set(CameraParameters::KEY_RECORDING_HINT, valstr);
videoMode = true;
int w, h;
params.getPreviewSize(&w, &h);
CAMHAL_LOGVB("%s Preview Width=%d Height=%d\n", __FUNCTION__, w, h);
//HACK FOR MMS
mVideoWidth = w;
mVideoHeight = h;
CAMHAL_LOGVB("%s Video Width=%d Height=%d\n", __FUNCTION__, mVideoWidth, mVideoHeight);
setPreferredPreviewRes(w, h);
mParameters.getPreviewSize(&w, &h);
CAMHAL_LOGVB("%s Preview Width=%d Height=%d\n", __FUNCTION__, w, h);
//Avoid restarting preview for MMS HACK
if ((w != mVideoWidth) && (h != mVideoHeight))
{
restartPreviewRequired = false;
}
restartPreviewRequired |= setVideoModeParameters(params);
}
else if(strcmp(valstr, CameraParameters::FALSE) == 0)
{
CAMHAL_LOGDB("Recording Hint is set to %s", valstr);
mParameters.set(CameraParameters::KEY_RECORDING_HINT, valstr);
restartPreviewRequired |= resetVideoModeParameters();
params.getPreviewSize(&mVideoWidth, &mVideoHeight);
}
else
{
CAMHAL_LOGEA("Invalid RECORDING_HINT");
return -EINVAL;
}
}
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(CameraParameters::KEY_RECORDING_HINT, "");
restartPreviewRequired |= resetVideoModeParameters();
params.getPreviewSize(&mVideoWidth, &mVideoHeight);
}
if ((valstr = params.get(CameraParameters::KEY_FOCUS_MODE)) != NULL) {
if (isParameterValid(valstr, mCameraProperties->get(CameraProperties::SUPPORTED_FOCUS_MODES))) {
CAMHAL_LOGDB("Focus mode set %s", params.get(CameraParameters::KEY_FOCUS_MODE));
// 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, CameraParameters::FOCUS_MODE_CONTINUOUS_PICTURE) == 0){
restartPreviewRequired |= resetVideoModeParameters();
} else if (strcmp(valstr, CameraParameters::FOCUS_MODE_CONTINUOUS_VIDEO) == 0){
restartPreviewRequired |= setVideoModeParameters(params);
}
mParameters.set(CameraParameters::KEY_FOCUS_MODE, valstr);
} else {
CAMHAL_LOGEB("ERROR: Invalid FOCUS mode = %s", valstr);
ret = -EINVAL;
}
}
///Below parameters can be changed when the preview is running
if ( (valstr = params.getPictureFormat()) != NULL ) {
if (isParameterValid(params.getPictureFormat(),mCameraProperties->get(CameraProperties::SUPPORTED_PICTURE_FORMATS))) {
mParameters.setPictureFormat(valstr);
} else {
CAMHAL_LOGEB("ERROR: Invalid picture format: %s",valstr);
ret = -EINVAL;
}
}
params.getPictureSize(&w, &h);
if ( isResolutionValid(w, h, mCameraProperties->get(CameraProperties::SUPPORTED_PICTURE_SIZES))) {
mParameters.setPictureSize(w, h);
} else {
CAMHAL_LOGEB("ERROR: Invalid picture resolution %dx%d", w, h);
ret = -EINVAL;
}
CAMHAL_LOGDB("Picture Size by App %d x %d", w, h);
if ((valstr = params.get(TICameraParameters::KEY_BURST)) != NULL) {
if (params.getInt(TICameraParameters::KEY_BURST) >=0) {
CAMHAL_LOGDB("Burst set %s", params.get(TICameraParameters::KEY_BURST));
mParameters.set(TICameraParameters::KEY_BURST, valstr);
} else {
CAMHAL_LOGEB("ERROR: Invalid Burst value: %s",valstr);
ret = -EINVAL;
}
}
framerate = params.getPreviewFrameRate();
valstr = params.get(CameraParameters::KEY_PREVIEW_FPS_RANGE);
CAMHAL_LOGDB("FRAMERATE %d", framerate);
CAMHAL_LOGVB("Passed FRR: %s, Supported FRR %s", valstr
, mCameraProperties->get(CameraProperties::FRAMERATE_RANGE_SUPPORTED));
CAMHAL_LOGVB("Passed FR: %d, Supported FR %s", framerate
, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_FRAME_RATES));
//Perform parameter validation
if(!isParameterValid(valstr
, mCameraProperties->get(CameraProperties::FRAMERATE_RANGE_SUPPORTED))
|| !isParameterValid(framerate,
mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_FRAME_RATES)))
{
CAMHAL_LOGEA("Invalid frame rate range or frame rate");
return -EINVAL;
}
// 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 ( strcmp(valstr, mCameraProperties->get(CameraProperties::FRAMERATE_RANGE)) != 0)
{
// APP wants to set FPS range
//Set framerate = MAXFPS
CAMHAL_LOGDA("APP IS CHANGING FRAME RATE RANGE");
params.getPreviewFpsRange(&minFPS, &maxFPS);
if ( ( 0 > minFPS ) || ( 0 > maxFPS ) )
{
CAMHAL_LOGEA("ERROR: FPS Range is negative!");
return -EINVAL;
}
framerate = maxFPS /CameraHal::VFR_SCALE;
}
else
{
if ( framerate != atoi(mCameraProperties->get(CameraProperties::PREVIEW_FRAME_RATE)) )
{
selectFPSRange(framerate, &minFPS, &maxFPS);
CAMHAL_LOGDB("Select FPS Range %d %d", minFPS, maxFPS);
}
else
{
if (videoMode) {
valstr = mCameraProperties->get(CameraProperties::FRAMERATE_RANGE_VIDEO);
CameraParameters temp;
temp.set(CameraParameters::KEY_PREVIEW_FPS_RANGE, valstr);
temp.getPreviewFpsRange(&minFPS, &maxFPS);
}
else {
valstr = mCameraProperties->get(CameraProperties::FRAMERATE_RANGE_IMAGE);
CameraParameters temp;
temp.set(CameraParameters::KEY_PREVIEW_FPS_RANGE, valstr);
temp.getPreviewFpsRange(&minFPS, &maxFPS);
}
framerate = maxFPS / CameraHal::VFR_SCALE;
}
}
CAMHAL_LOGDB("FPS Range = %s", valstr);
CAMHAL_LOGDB("DEFAULT FPS Range = %s", mCameraProperties->get(CameraProperties::FRAMERATE_RANGE));
minFPS /= CameraHal::VFR_SCALE;
maxFPS /= CameraHal::VFR_SCALE;
if ( ( 0 == minFPS ) || ( 0 == maxFPS ) )
{
CAMHAL_LOGEA("ERROR: FPS Range is invalid!");
ret = -EINVAL;
}
if ( maxFPS < minFPS )
{
CAMHAL_LOGEA("ERROR: Max FPS is smaller than Min FPS!");
ret = -EINVAL;
}
CAMHAL_LOGDB("SET FRAMERATE %d", framerate);
mParameters.setPreviewFrameRate(framerate);
mParameters.set(CameraParameters::KEY_PREVIEW_FPS_RANGE, params.get(CameraParameters::KEY_PREVIEW_FPS_RANGE));
CAMHAL_LOGDB("FPS Range [%d, %d]", minFPS, maxFPS);
mParameters.set(TICameraParameters::KEY_MINFRAMERATE, minFPS);
mParameters.set(TICameraParameters::KEY_MAXFRAMERATE, maxFPS);
if( ( valstr = params.get(TICameraParameters::KEY_GBCE) ) != NULL )
{
CAMHAL_LOGDB("GBCE Value = %s", valstr);
mParameters.set(TICameraParameters::KEY_GBCE, valstr);
}
if( ( valstr = params.get(TICameraParameters::KEY_GLBCE) ) != NULL )
{
CAMHAL_LOGDB("GLBCE Value = %s", valstr);
mParameters.set(TICameraParameters::KEY_GLBCE, valstr);
}
///Update the current parameter set
if( (valstr = params.get(TICameraParameters::KEY_AUTOCONVERGENCE)) != NULL)
{
CAMHAL_LOGDB("AutoConvergence Mode is set = %s", params.get(TICameraParameters::KEY_AUTOCONVERGENCE));
mParameters.set(TICameraParameters::KEY_AUTOCONVERGENCE, valstr);
}
if( (valstr = params.get(TICameraParameters::KEY_MANUALCONVERGENCE_VALUES)) !=NULL )
{
CAMHAL_LOGDB("ManualConvergence Value = %s", params.get(TICameraParameters::KEY_MANUALCONVERGENCE_VALUES));
mParameters.set(TICameraParameters::KEY_MANUALCONVERGENCE_VALUES, valstr);
}
if ((valstr = params.get(TICameraParameters::KEY_EXPOSURE_MODE)) != NULL) {
if (isParameterValid(valstr, mCameraProperties->get(CameraProperties::SUPPORTED_EXPOSURE_MODES))) {
CAMHAL_LOGDB("Exposure set = %s", valstr);
mParameters.set(TICameraParameters::KEY_EXPOSURE_MODE, valstr);
} else {
CAMHAL_LOGEB("ERROR: Invalid Exposure = %s", valstr);
ret = -EINVAL;
}
}
if ((valstr = params.get(CameraParameters::KEY_WHITE_BALANCE)) != NULL) {
if ( isParameterValid(valstr, mCameraProperties->get(CameraProperties::SUPPORTED_WHITE_BALANCE))) {
CAMHAL_LOGDB("White balance set %s", valstr);
mParameters.set(CameraParameters::KEY_WHITE_BALANCE, valstr);
} else {
CAMHAL_LOGEB("ERROR: Invalid white balance = %s", valstr);
ret = -EINVAL;
}
}
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);
ret = -EINVAL;
}
}
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);
ret = -EINVAL;
}
}
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);
ret = -EINVAL;
}
}
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);
ret = -EINVAL;
}
}
if ((valstr = params.get(CameraParameters::KEY_ANTIBANDING)) != NULL) {
if (isParameterValid(valstr, mCameraProperties->get(CameraProperties::SUPPORTED_ANTIBANDING))) {
CAMHAL_LOGDB("Antibanding set %s", valstr);
mParameters.set(CameraParameters::KEY_ANTIBANDING, valstr);
} else {
CAMHAL_LOGEB("ERROR: Invalid Antibanding = %s", valstr);
ret = -EINVAL;
}
}
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);
ret = -EINVAL;
}
}
if( (valstr = params.get(CameraParameters::KEY_FOCUS_AREAS)) != NULL )
{
CAMHAL_LOGDB("Focus areas position set %s", params.get(CameraParameters::KEY_FOCUS_AREAS));
mParameters.set(CameraParameters::KEY_FOCUS_AREAS, valstr);
}
if( (valstr = params.get(TICameraParameters::KEY_MEASUREMENT_ENABLE)) != NULL )
{
CAMHAL_LOGDB("Measurements set to %s", params.get(TICameraParameters::KEY_MEASUREMENT_ENABLE));
mParameters.set(TICameraParameters::KEY_MEASUREMENT_ENABLE, valstr);
if (strcmp(valstr, (const char *) TICameraParameters::MEASUREMENT_ENABLE) == 0)
{
mMeasurementEnabled = true;
}
else if (strcmp(valstr, (const char *) TICameraParameters::MEASUREMENT_DISABLE) == 0)
{
mMeasurementEnabled = false;
}
else
{
mMeasurementEnabled = false;
}
}
if( (valstr = params.get(CameraParameters::KEY_EXPOSURE_COMPENSATION)) != NULL)
{
CAMHAL_LOGDB("Exposure compensation set %s", params.get(CameraParameters::KEY_EXPOSURE_COMPENSATION));
mParameters.set(CameraParameters::KEY_EXPOSURE_COMPENSATION, valstr);
}
if ((valstr = params.get(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(CameraParameters::KEY_SCENE_MODE),
updateRequired);
mParameters.set(CameraParameters::KEY_SCENE_MODE, valstr);
} else {
CAMHAL_LOGEB("ERROR: Invalid Scene mode = %s", valstr);
ret = -EINVAL;
}
}
if ((valstr = params.get(CameraParameters::KEY_FLASH_MODE)) != NULL) {
if (isParameterValid(valstr, mCameraProperties->get(CameraProperties::SUPPORTED_FLASH_MODES))) {
CAMHAL_LOGDB("Flash mode set %s", valstr);
mParameters.set(CameraParameters::KEY_FLASH_MODE, valstr);
} else {
CAMHAL_LOGEB("ERROR: Invalid Flash mode = %s", valstr);
ret = -EINVAL;
}
}
if ((valstr = params.get(CameraParameters::KEY_EFFECT)) != NULL) {
if (isParameterValid(valstr, mCameraProperties->get(CameraProperties::SUPPORTED_EFFECTS))) {
CAMHAL_LOGDB("Effect set %s", valstr);
mParameters.set(CameraParameters::KEY_EFFECT, valstr);
} else {
CAMHAL_LOGEB("ERROR: Invalid Effect = %s", valstr);
ret = -EINVAL;
}
}
if(( (valstr = params.get(CameraParameters::KEY_ROTATION)) != NULL)
&& (params.getInt(CameraParameters::KEY_ROTATION) >=0))
{
CAMHAL_LOGDB("Rotation set %s", params.get(CameraParameters::KEY_ROTATION));
mParameters.set(CameraParameters::KEY_ROTATION, valstr);
}
if(( (valstr = params.get(CameraParameters::KEY_JPEG_QUALITY)) != NULL)
&& (params.getInt(CameraParameters::KEY_JPEG_QUALITY) >=0))
{
CAMHAL_LOGDB("Jpeg quality set %s", params.get(CameraParameters::KEY_JPEG_QUALITY));
mParameters.set(CameraParameters::KEY_JPEG_QUALITY, valstr);
}
if(( (valstr = params.get(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH)) != NULL)
&& (params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH) >=0))
{
CAMHAL_LOGDB("Thumbnail width set %s", params.get(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH));
mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, valstr);
}
if(( (valstr = params.get(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT)) != NULL)
&& (params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT) >=0))
{
CAMHAL_LOGDB("Thumbnail width set %s", params.get(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT));
mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, valstr);
}
if(( (valstr = params.get(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY)) != NULL )
&& (params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY) >=0))
{
CAMHAL_LOGDB("Thumbnail quality set %s", params.get(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY));
mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, valstr);
}
if( (valstr = params.get(CameraParameters::KEY_GPS_LATITUDE)) != NULL )
{
CAMHAL_LOGDB("GPS latitude set %s", params.get(CameraParameters::KEY_GPS_LATITUDE));
mParameters.set(CameraParameters::KEY_GPS_LATITUDE, valstr);
}else{
mParameters.remove(CameraParameters::KEY_GPS_LATITUDE);
}
if( (valstr = params.get(CameraParameters::KEY_GPS_LONGITUDE)) != NULL )
{
CAMHAL_LOGDB("GPS longitude set %s", params.get(CameraParameters::KEY_GPS_LONGITUDE));
mParameters.set(CameraParameters::KEY_GPS_LONGITUDE, valstr);
}else{
mParameters.remove(CameraParameters::KEY_GPS_LONGITUDE);
}
if( (valstr = params.get(CameraParameters::KEY_GPS_ALTITUDE)) != NULL )
{
CAMHAL_LOGDB("GPS altitude set %s", params.get(CameraParameters::KEY_GPS_ALTITUDE));
mParameters.set(CameraParameters::KEY_GPS_ALTITUDE, valstr);
}else{
mParameters.remove(CameraParameters::KEY_GPS_ALTITUDE);
}
if( (valstr = params.get(CameraParameters::KEY_GPS_TIMESTAMP)) != NULL )
{
CAMHAL_LOGDB("GPS timestamp set %s", params.get(CameraParameters::KEY_GPS_TIMESTAMP));
mParameters.set(CameraParameters::KEY_GPS_TIMESTAMP, valstr);
}else{
mParameters.remove(CameraParameters::KEY_GPS_TIMESTAMP);
}
if( (valstr = params.get(TICameraParameters::KEY_GPS_DATESTAMP)) != NULL )
{
CAMHAL_LOGDB("GPS datestamp set %s", params.get(TICameraParameters::KEY_GPS_DATESTAMP));
mParameters.set(TICameraParameters::KEY_GPS_DATESTAMP, valstr);
}else{
mParameters.remove(TICameraParameters::KEY_GPS_DATESTAMP);
}
if( (valstr = params.get(CameraParameters::KEY_GPS_PROCESSING_METHOD)) != NULL )
{
CAMHAL_LOGDB("GPS processing method set %s", params.get(CameraParameters::KEY_GPS_PROCESSING_METHOD));
mParameters.set(CameraParameters::KEY_GPS_PROCESSING_METHOD, valstr);
}else{
mParameters.remove(CameraParameters::KEY_GPS_PROCESSING_METHOD);
}
if( (valstr = params.get(TICameraParameters::KEY_GPS_MAPDATUM )) != NULL )
{
CAMHAL_LOGDB("GPS MAPDATUM set %s", params.get(TICameraParameters::KEY_GPS_MAPDATUM));
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", params.get(TICameraParameters::KEY_GPS_VERSION));
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", params.get(TICameraParameters::KEY_EXIF_MODEL));
mParameters.set(TICameraParameters::KEY_EXIF_MODEL, valstr);
}
if( (valstr = params.get(TICameraParameters::KEY_EXIF_MAKE)) != NULL )
{
CAMHAL_LOGDB("EXIF Make set %s", params.get(TICameraParameters::KEY_EXIF_MAKE));
mParameters.set(TICameraParameters::KEY_EXIF_MAKE, valstr);
}
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);
}
else
{
mParameters.remove(TICameraParameters::KEY_EXP_BRACKETING_RANGE);
}
if ((valstr = params.get(CameraParameters::KEY_ZOOM)) != NULL ) {
if ((params.getInt(CameraParameters::KEY_ZOOM) >= 0 ) &&
(params.getInt(CameraParameters::KEY_ZOOM) <= mMaxZoomSupported )) {
CAMHAL_LOGDB("Zoom set %s", valstr);
doesSetParameterNeedUpdate(valstr,
mParameters.get(CameraParameters::KEY_ZOOM),
updateRequired);
mParameters.set(CameraParameters::KEY_ZOOM, valstr);
} else {
CAMHAL_LOGEB("ERROR: Invalid Zoom: %s", valstr);
ret = -EINVAL;
}
}
if( (valstr = params.get(CameraParameters::KEY_AUTO_EXPOSURE_LOCK)) != NULL )
{
CAMHAL_LOGDB("Auto Exposure Lock set %s", params.get(CameraParameters::KEY_AUTO_EXPOSURE_LOCK));
doesSetParameterNeedUpdate(valstr,
mParameters.get(CameraParameters::KEY_AUTO_EXPOSURE_LOCK),
updateRequired);
mParameters.set(CameraParameters::KEY_AUTO_EXPOSURE_LOCK, valstr);
}
if( (valstr = params.get(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK)) != NULL )
{
CAMHAL_LOGDB("Auto WhiteBalance Lock set %s", params.get(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK));
doesSetParameterNeedUpdate(valstr,
mParameters.get(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK),
updateRequired);
mParameters.set(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK, valstr);
}
if( (valstr = params.get(CameraParameters::KEY_METERING_AREAS)) != NULL )
{
CAMHAL_LOGDB("Metering areas position set %s", params.get(CameraParameters::KEY_METERING_AREAS));
mParameters.set(CameraParameters::KEY_METERING_AREAS, valstr);
}
CameraParameters adapterParams = mParameters;
// 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) ) {
ret |= mCameraAdapter->setParameters(adapterParams);
}
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, TICameraParameters::BRACKET_ENABLE) == 0 ))
{
if ( !mBracketingEnabled )
{
CAMHAL_LOGDA("Enabling bracketing");
mBracketingEnabled = true;
//Wait for AF events to enable bracketing
if ( NULL != mCameraAdapter )
{
setEventProvider( CameraHalEvent::ALL_EVENTS, mCameraAdapter );
}
}
else
{
CAMHAL_LOGDA("Bracketing already enabled");
}
}
else if ( ( (valstr = params.get(TICameraParameters::KEY_TEMP_BRACKETING)) != NULL ) &&
( strcmp(valstr, TICameraParameters::BRACKET_DISABLE) == 0 ))
{
CAMHAL_LOGDA("Disabling bracketing");
mBracketingEnabled = false;
stopImageBracketing();
//Remove AF events subscription
if ( NULL != mEventProvider )
{
mEventProvider->disableEventNotification( CameraHalEvent::ALL_EVENTS );
delete mEventProvider;
mEventProvider = NULL;
}
}
if( ( (valstr = params.get(TICameraParameters::KEY_SHUTTER_ENABLE)) != NULL ) &&
( strcmp(valstr, TICameraParameters::SHUTTER_ENABLE) == 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, TICameraParameters::SHUTTER_DISABLE) == 0 ))
{
CAMHAL_LOGDA("Disabling shutter sound");
mShutterEnabled = false;
mMsgEnabled &= ~CAMERA_MSG_SHUTTER;
mParameters.set(TICameraParameters::KEY_SHUTTER_ENABLE, valstr);
}
}
//On fail restore old parameters
if ( NO_ERROR != ret ) {
mParameters.unflatten(oldParams.flatten());
}
// 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("Stopping Preview");
forceStopPreview();
}
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(!mPreviewBufs)
{
///@todo Pluralise the name of this method to allocateBuffers
mPreviewLength = 0;
mPreviewBufs = (int32_t *) mDisplayAdapter->allocateBuffer(width, height,
previewFormat,
mPreviewLength,
buffercount);
if (NULL == mPreviewBufs ) {
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;
}
mPreviewFd = mDisplayAdapter->getFd();
if ( -1 == mPreviewFd ) {
CAMHAL_LOGEA("Invalid handle");
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("mPreviewBufs = 0x%x", (unsigned int)mPreviewBufs);
if(mPreviewBufs)
{
///@todo Pluralise the name of this method to freeBuffers
ret = mBufProvider->freeBuffer(mPreviewBufs);
mPreviewBufs = 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 != mPreviewDataBufs )
{
ret = freePreviewDataBufs();
}
}
if ( NO_ERROR == ret )
{
bytes = ((bytes+4095)/4096)*4096;
mPreviewDataBufs = (int32_t *)mMemoryManager->allocateBuffer(0, 0, NULL, bytes, bufferCount);
CAMHAL_LOGDB("Size of Preview data buffer = %d", bytes);
if( NULL == mPreviewDataBufs )
{
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;
return ret;
}
status_t CameraHal::freePreviewDataBufs()
{
status_t ret = NO_ERROR;
LOG_FUNCTION_NAME;
if ( NO_ERROR == ret )
{
if( NULL != mPreviewDataBufs )
{
///@todo Pluralise the name of this method to freeBuffers
ret = mMemoryManager->freeBuffer(mPreviewDataBufs);
mPreviewDataBufs = 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;
LOG_FUNCTION_NAME;
bytes = size;
// allocate image buffers only if not already allocated
if(NULL != mImageBufs) {
return NO_ERROR;
}
if ( NO_ERROR == ret )
{
bytes = ((bytes+4095)/4096)*4096;
mImageBufs = (int32_t *)mMemoryManager->allocateBuffer(0, 0, previewFormat, bytes, bufferCount);
CAMHAL_LOGDB("Size of Image cap buffer = %d", bytes);
if( NULL == mImageBufs )
{
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();
}
else
{
mImageFd = -1;
mImageLength = 0;
mImageOffsets = NULL;
}
LOG_FUNCTION_NAME;
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 != mVideoBufs ){
ret = freeVideoBufs(mVideoBufs);
mVideoBufs = NULL;
}
if ( NO_ERROR == ret ){
int32_t stride;
buffer_handle_t *bufsArr = new buffer_handle_t [bufferCount];
if (bufsArr != NULL){
for (int i = 0; i< bufferCount; i++){
GraphicBufferAllocator &GrallocAlloc = GraphicBufferAllocator::get();
buffer_handle_t buf;
ret = GrallocAlloc.alloc(width, height, HAL_PIXEL_FORMAT_NV12, CAMHAL_GRALLOC_USAGE, &buf, &stride);
if (ret != NO_ERROR){
CAMHAL_LOGEA("Couldn't allocate video buffers using Gralloc");
ret = -NO_MEMORY;
for (int j=0; j< i; j++){
buf = (buffer_handle_t)bufsArr[j];
CAMHAL_LOGEB("Freeing Gralloc Buffer 0x%x", buf);
GrallocAlloc.free(buf);
}
delete [] bufsArr;
goto exit;
}
bufsArr[i] = buf;
CAMHAL_LOGVB("*** Gralloc Handle =0x%x ***", buf);
}
mVideoBufs = (int32_t *)bufsArr;
}
else{
CAMHAL_LOGEA("Couldn't allocate video buffers ");
ret = -NO_MEMORY;
}
}
exit:
LOG_FUNCTION_NAME;
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;
CameraParameters adapterParams = mParameters;
Mutex::Autolock lock(mLock);
LOG_FUNCTION_NAME;
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 ( NO_ERROR == ret )
{
if( NULL != mImageBufs )
{
///@todo Pluralise the name of this method to freeBuffers
ret = mMemoryManager->freeBuffer(mImageBufs);
mImageBufs = NULL;
}
else
{
ret = -EINVAL;
}
}
LOG_FUNCTION_NAME_EXIT;
return ret;
}
status_t CameraHal::freeVideoBufs(void *bufs)
{
status_t ret = NO_ERROR;
LOG_FUNCTION_NAME;
buffer_handle_t *pBuf = (buffer_handle_t*)bufs;
int count = atoi(mCameraProperties->get(CameraProperties::REQUIRED_PREVIEW_BUFS));
if(pBuf == NULL)
{
CAMHAL_LOGEA("NULL pointer passed to freeVideoBuffer");
LOG_FUNCTION_NAME_EXIT;
return BAD_VALUE;
}
GraphicBufferAllocator &GrallocAlloc = GraphicBufferAllocator::get();
for(int i = 0; i < count; i++){
buffer_handle_t ptr = *pBuf++;
CAMHAL_LOGVB("Free Video Gralloc Handle 0x%x", ptr);
GrallocAlloc.free(ptr);
}
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()
{
status_t ret = NO_ERROR;
CameraAdapter::BuffersDescriptor desc;
CameraFrame frame;
const char *valstr = NULL;
unsigned int required_buffer_count;
unsigned int max_queueble_buffers;
#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
gettimeofday(&mStartPreview, NULL);
#endif
LOG_FUNCTION_NAME;
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;
//Update the padded width and height - required for VNF and VSTAB
mParameters.set(TICameraParameters::KEY_PADDED_WIDTH, mPreviewWidth);
mParameters.set(TICameraParameters::KEY_PADDED_HEIGHT, mPreviewHeight);
}
///If we don't have the preview callback enabled and display adapter,
if(!mSetPreviewWindowCalled || (mDisplayAdapter.get() == NULL)){
CAMHAL_LOGDA("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);
}
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 = mPreviewDataBufs;
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 = mPreviewBufs;
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;
}
mAppCallbackNotifier->startPreviewCallbacks(mParameters, mPreviewBufs, mPreviewOffsets, mPreviewFd, mPreviewLength, required_buffer_count);
///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;
}
///Enable the display adapter if present, actual overlay enable happens when we post the buffer
if(mDisplayAdapter.get() != NULL)
{
CAMHAL_LOGDA("Enabling display");
bool isS3d = false;
DisplayAdapter::S3DParameters s3dParams;
int width, height;
mParameters.getPreviewSize(&width, &height);
#if 0 //TODO: s3d is not part of bringup...will reenable
if ( (valstr = mParameters.get(TICameraParameters::KEY_S3D_SUPPORTED)) != NULL) {
isS3d = (strcmp(valstr, "true") == 0);
}
if ( (valstr = mParameters.get(TICameraParameters::KEY_S3D2D_PREVIEW)) != NULL) {
if (strcmp(valstr, "off") == 0)
{
CAMHAL_LOGEA("STEREO 3D->2D PREVIEW MODE IS OFF");
//TODO: obtain the frame packing configuration from camera or user settings
//once side by side configuration is supported
s3dParams.mode = OVERLAY_S3D_MODE_ON;
s3dParams.framePacking = OVERLAY_S3D_FORMAT_OVERUNDER;
s3dParams.order = OVERLAY_S3D_ORDER_LF;
s3dParams.subSampling = OVERLAY_S3D_SS_NONE;
}
else
{
CAMHAL_LOGEA("STEREO 3D->2D PREVIEW MODE IS ON");
s3dParams.mode = OVERLAY_S3D_MODE_OFF;
s3dParams.framePacking = OVERLAY_S3D_FORMAT_OVERUNDER;
s3dParams.order = OVERLAY_S3D_ORDER_LF;
s3dParams.subSampling = OVERLAY_S3D_SS_NONE;
}
}
#endif //if 0
#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
ret = mDisplayAdapter->enableDisplay(width, height, &mStartPreview, isS3d ? &s3dParams : NULL);
#else
ret = mDisplayAdapter->enableDisplay(width, height, NULL, isS3d ? &s3dParams : NULL);
#endif
if ( ret != NO_ERROR )
{
CAMHAL_LOGEA("Couldn't enable display");
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 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_LOGDA("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_LOGDA("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();
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;
}
/**
@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, 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(CameraParameters::KEY_FOCUS_MODE)) != NULL) &&
(strcmp(valstr, CameraParameters::FOCUS_MODE_CONTINUOUS_PICTURE) == 0) ){
restartPreviewRequired = resetVideoModeParameters();
}
// only need to check recording hint if preview restart is not already needed
valstr = mParameters.get(CameraParameters::KEY_RECORDING_HINT);
if ( !restartPreviewRequired &&
(!valstr || (valstr && (strcmp(valstr, CameraParameters::TRUE) != 0))) ) {
restartPreviewRequired = setVideoModeParameters(mParameters);
}
if (restartPreviewRequired) {
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(mPreviewBufs, mPreviewOffsets, mPreviewFd, mPreviewLength, count, mVideoBufs);
}
else
{
mAppCallbackNotifier->useVideoBuffers(false);
mAppCallbackNotifier->setVideoRes(mPreviewWidth, mPreviewHeight);
ret = mAppCallbackNotifier->initSharedVideoBuffers(mPreviewBufs, 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 CameraParameters& params)
{
const char *valstr = NULL;
bool restartPreviewRequired = false;
status_t ret = NO_ERROR;
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) ) )
{
CAMHAL_LOGDA("Set CAPTURE_MODE to VIDEO_MODE");
mParameters.set(TICameraParameters::KEY_CAP_MODE, (const char *) TICameraParameters::VIDEO_MODE);
restartPreviewRequired = true;
}
// Check if CAPTURE_MODE is VIDEO_MODE, since VSTAB & VNF work only in VIDEO_MODE.
valstr = mParameters.get(TICameraParameters::KEY_CAP_MODE);
if (strcmp(valstr, (const char *) TICameraParameters::VIDEO_MODE) == 0) {
// set VSTAB. restart is required if vstab value has changed
if (params.get(CameraParameters::KEY_VIDEO_STABILIZATION) != NULL) {
// make sure we support vstab
if (strcmp(mCameraProperties->get(CameraProperties::VSTAB_SUPPORTED),
CameraParameters::TRUE) == 0) {
valstr = mParameters.get(CameraParameters::KEY_VIDEO_STABILIZATION);
// vstab value has changed
if ((valstr != NULL) &&
strcmp(valstr, params.get(CameraParameters::KEY_VIDEO_STABILIZATION)) != 0) {
restartPreviewRequired = true;
}
mParameters.set(CameraParameters::KEY_VIDEO_STABILIZATION,
params.get(CameraParameters::KEY_VIDEO_STABILIZATION));
}
} else if (mParameters.get(CameraParameters::KEY_VIDEO_STABILIZATION)) {
// vstab was configured but now unset
restartPreviewRequired = true;
mParameters.remove(CameraParameters::KEY_VIDEO_STABILIZATION);
}
// Set VNF
if (params.get(TICameraParameters::KEY_VNF) == NULL) {
CAMHAL_LOGDA("Enable VNF");
mParameters.set(TICameraParameters::KEY_VNF, "1");
restartPreviewRequired = true;
} else {
valstr = mParameters.get(TICameraParameters::KEY_VNF);
if (valstr && strcmp(valstr, params.get(TICameraParameters::KEY_VNF)) != 0) {
restartPreviewRequired = true;
}
mParameters.set(TICameraParameters::KEY_VNF, params.get(TICameraParameters::KEY_VNF));
}
// 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.
valstr = mParameters.get(CameraParameters::KEY_VIDEO_STABILIZATION);
if (valstr && (strcmp(valstr, CameraParameters::TRUE) == 0) && (mPreviewWidth == 1920)) {
CAMHAL_LOGDA("Force Enable VNF for 1080p");
mParameters.set(TICameraParameters::KEY_VNF, "1");
restartPreviewRequired = true;
}
}
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()
{
const char *valstr = NULL;
char tmpvalstr[30];
status_t ret = NO_ERROR;
LOG_FUNCTION_NAME;
// Retain CAPTURE_MODE before calling stopPreview(), since it is reset in stopPreview().
tmpvalstr[0] = 0;
valstr = mParameters.get(TICameraParameters::KEY_CAP_MODE);
if(valstr != NULL)
{
if(sizeof(tmpvalstr) < (strlen(valstr)+1))
{
return -EINVAL;
}
strncpy(tmpvalstr, valstr, sizeof(tmpvalstr));
tmpvalstr[sizeof(tmpvalstr)-1] = 0;
}
forceStopPreview();
{
Mutex::Autolock lock(mLock);
mParameters.set(TICameraParameters::KEY_CAP_MODE, tmpvalstr);
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;
Mutex::Autolock 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(mVideoBufs);
if (mVideoBufs){
CAMHAL_LOGVB(" FREEING mVideoBufs 0x%x", mVideoBufs);
delete [] mVideoBufs;
}
mVideoBufs = 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;
Mutex::Autolock 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;
Mutex::Autolock lock(mLock);
CameraParameters adapterParams = mParameters;
mMsgEnabled &= ~CAMERA_MSG_FOCUS;
if( NULL != mCameraAdapter )
{
adapterParams.set(TICameraParameters::KEY_AUTO_FOCUS_LOCK, 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;
if ( NULL != event )
{
switch( event->mEventType )
{
case CameraHalEvent::EVENT_FOCUS_LOCKED:
case CameraHalEvent::EVENT_FOCUS_ERROR:
{
if ( mBracketingEnabled )
{
startImageBracketing();
}
break;
}
default:
{
break;
}
};
}
LOG_FUNCTION_NAME_EXIT;
}
status_t CameraHal::startImageBracketing()
{
status_t ret = NO_ERROR;
CameraFrame frame;
CameraAdapter::BuffersDescriptor desc;
#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 = mImageBufs;
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( )
{
status_t ret = NO_ERROR;
CameraFrame frame;
CameraAdapter::BuffersDescriptor desc;
int burst;
const char *valstr = NULL;
unsigned int bufferCount = 1;
Mutex::Autolock lock(mLock);
#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
gettimeofday(&mStartCapture, NULL);
#endif
LOG_FUNCTION_NAME;
if(!previewEnabled() && !mDisplayPaused)
{
LOG_FUNCTION_NAME_EXIT;
CAMHAL_LOGEA("Preview not started...");
return NO_INIT;
}
// return error if we are already capturing
if ( (mCameraAdapter->getState() == CameraAdapter::CAPTURE_STATE &&
mCameraAdapter->getNextState() != CameraAdapter::PREVIEW_STATE) ||
(mCameraAdapter->getState() == CameraAdapter::VIDEO_CAPTURE_STATE &&
mCameraAdapter->getNextState() != CameraAdapter::VIDEO_STATE) ) {
CAMHAL_LOGEA("Already capturing an image...");
return NO_INIT;
}
// we only support video snapshot if we are in video mode (recording hint is set)
valstr = mParameters.get(TICameraParameters::KEY_CAP_MODE);
if ( (mCameraAdapter->getState() == CameraAdapter::VIDEO_STATE) &&
(valstr && strcmp(valstr, TICameraParameters::VIDEO_MODE)) ) {
CAMHAL_LOGEA("Trying to capture while recording without recording hint set...");
return INVALID_OPERATION;
}
if ( !mBracketingRunning )
{
if ( NO_ERROR == ret )
{
burst = mParameters.getInt(TICameraParameters::KEY_BURST);
}
//Allocate all buffers only in burst capture case
if ( burst > 1 )
{
bufferCount = CameraHal::NO_BUFFERS_IMAGE_CAPTURE;
if ( NULL != mAppCallbackNotifier.get() )
{
mAppCallbackNotifier->setBurst(true);
}
}
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() &&
burst < 1) {
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 ( NO_ERROR == ret )
{
mParameters.getPictureSize(( int * ) &frame.mWidth,
( int * ) &frame.mHeight);
ret = allocImageBufs(frame.mWidth,
frame.mHeight,
frame.mLength,
mParameters.getPictureFormat(),
bufferCount);
if ( NO_ERROR != ret )
{
CAMHAL_LOGEB("allocImageBufs returned error 0x%x", ret);
}
}
if ( (NO_ERROR == ret) && ( NULL != mCameraAdapter ) )
{
desc.mBuffers = mImageBufs;
desc.mOffsets = mImageOffsets;
desc.mFd = mImageFd;
desc.mLength = mImageLength;
desc.mCount = ( size_t ) bufferCount;
desc.mMaxQueueable = ( size_t ) bufferCount;
ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_USE_BUFFERS_IMAGE_CAPTURE,
( int ) &desc);
}
}
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);
#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;
Mutex::Autolock lock(mLock);
mCameraAdapter->sendCommand(CameraAdapter::CAMERA_STOP_IMAGE_CAPTURE);
return NO_ERROR;
}
/**
@brief Return the camera parameters.
@param none
@return Currently configured camera parameters
*/
char* CameraHal::getParameters()
{
String8 params_str8;
char* params_string;
const char * valstr = NULL;
LOG_FUNCTION_NAME;
if( NULL != mCameraAdapter )
{
mCameraAdapter->getParameters(mParameters);
}
CameraParameters mParams = mParameters;
// Handle RECORDING_HINT to Set/Reset Video Mode Parameters
valstr = mParameters.get(CameraParameters::KEY_RECORDING_HINT);
if(valstr != NULL)
{
if(strcmp(valstr, CameraParameters::TRUE) == 0)
{
//HACK FOR MMS MODE
resetPreviewRes(&mParams, mVideoWidth, mVideoHeight);
}
}
// 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;
}
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) {
case CAMERA_CMD_ENABLE_FOCUS_MOVE_MSG:
bool enable = static_cast<bool>(arg1);
Mutex::Autolock lock(mLock);
if (enable) {
mMsgEnabled |= CAMERA_MSG_FOCUS_MOVE;
} else {
mMsgEnabled &= ~CAMERA_MSG_FOCUS_MOVE;
}
return NO_ERROR;
break;
}
if ( ( NO_ERROR == ret ) && ( !previewEnabled() ))
{
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);
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;
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;
mPreviewBufs = NULL;
mImageBufs = NULL;
mBufProvider = NULL;
mPreviewStartInProgress = false;
mVideoBufs = 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;
mPreviewDataBufs = NULL;
mCameraProperties = NULL;
mCurrentTime = 0;
mFalsePreview = 0;
mImageOffsets = NULL;
mImageLength = 0;
mImageFd = 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;
#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();
/// 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;
///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));
}
CAMHAL_LOGDB("Sensor index %d", sensor_index);
mCameraAdapter = CameraAdapter_Factory(sensor_index);
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 = true;
status_t status = NO_ERROR;
char tmpBuffer[PARAM_BUFFER + 1];
char *pos = NULL;
LOG_FUNCTION_NAME;
if ( NULL == supportedResolutions )
{
CAMHAL_LOGEA("Invalid supported resolutions string");
ret = false;
goto exit;
}
status = snprintf(tmpBuffer, PARAM_BUFFER, "%dx%d", width, height);
if ( 0 > status )
{
CAMHAL_LOGEA("Error encountered while generating validation string");
ret = false;
goto exit;
}
pos = strstr(supportedResolutions, tmpBuffer);
if ( NULL == pos )
{
ret = false;
}
else
{
ret = true;
}
exit:
LOG_FUNCTION_NAME_EXIT;
return ret;
}
bool CameraHal::isParameterValid(const char *param, const char *supportedParams)
{
bool ret = true;
char *pos = NULL;
LOG_FUNCTION_NAME;
if ( NULL == supportedParams )
{
CAMHAL_LOGEA("Invalid supported parameters string");
ret = false;
goto exit;
}
if ( NULL == param )
{
CAMHAL_LOGEA("Invalid parameter string");
ret = false;
goto exit;
}
pos = strstr(supportedParams, param);
if ( NULL == pos )
{
ret = false;
}
else
{
ret = true;
}
exit:
LOG_FUNCTION_NAME_EXIT;
return ret;
}
bool CameraHal::isParameterValid(int param, const char *supportedParams)
{
bool ret = true;
char *pos = NULL;
status_t status;
char tmpBuffer[PARAM_BUFFER + 1];
LOG_FUNCTION_NAME;
if ( NULL == supportedParams )
{
CAMHAL_LOGEA("Invalid supported parameters string");
ret = false;
goto exit;
}
status = snprintf(tmpBuffer, PARAM_BUFFER, "%d", param);
if ( 0 > status )
{
CAMHAL_LOGEA("Error encountered while generating validation string");
ret = false;
goto exit;
}
pos = strstr(supportedParams, tmpBuffer);
if ( NULL == pos )
{
ret = false;
}
else
{
ret = true;
}
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";
char *tmp = NULL;
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 ) {
if ( NO_ERROR == ret )
{
strcpy(resStr_copy, resStr);
pWidth = strtok_r( (char *) 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()
{
char tmpBuffer[PARAM_BUFFER + 1];
LOG_FUNCTION_NAME;
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(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES, mCameraProperties->get(CameraProperties::SUPPORTED_PICTURE_SIZES));
p.set(CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS, mCameraProperties->get(CameraProperties::SUPPORTED_PICTURE_FORMATS));
p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_SIZES));
p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_FORMATS));
p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_FRAME_RATES));
p.set(CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES, mCameraProperties->get(CameraProperties::SUPPORTED_THUMBNAIL_SIZES));
p.set(CameraParameters::KEY_SUPPORTED_WHITE_BALANCE, mCameraProperties->get(CameraProperties::SUPPORTED_WHITE_BALANCE));
p.set(CameraParameters::KEY_SUPPORTED_EFFECTS, mCameraProperties->get(CameraProperties::SUPPORTED_EFFECTS));
p.set(CameraParameters::KEY_SUPPORTED_SCENE_MODES, mCameraProperties->get(CameraProperties::SUPPORTED_SCENE_MODES));
p.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES, mCameraProperties->get(CameraProperties::SUPPORTED_FLASH_MODES));
p.set(CameraParameters::KEY_SUPPORTED_FOCUS_MODES, mCameraProperties->get(CameraProperties::SUPPORTED_FOCUS_MODES));
p.set(CameraParameters::KEY_SUPPORTED_ANTIBANDING, mCameraProperties->get(CameraProperties::SUPPORTED_ANTIBANDING));
p.set(CameraParameters::KEY_MAX_EXPOSURE_COMPENSATION, mCameraProperties->get(CameraProperties::SUPPORTED_EV_MAX));
p.set(CameraParameters::KEY_MIN_EXPOSURE_COMPENSATION, mCameraProperties->get(CameraProperties::SUPPORTED_EV_MIN));
p.set(CameraParameters::KEY_EXPOSURE_COMPENSATION_STEP, mCameraProperties->get(CameraProperties::SUPPORTED_EV_STEP));
p.set(CameraParameters::KEY_SUPPORTED_SCENE_MODES, mCameraProperties->get(CameraProperties::SUPPORTED_SCENE_MODES));
p.set(TICameraParameters::KEY_SUPPORTED_EXPOSURE, mCameraProperties->get(CameraProperties::SUPPORTED_EXPOSURE_MODES));
p.set(TICameraParameters::KEY_SUPPORTED_ISO_VALUES, mCameraProperties->get(CameraProperties::SUPPORTED_ISO_VALUES));
p.set(CameraParameters::KEY_ZOOM_RATIOS, mCameraProperties->get(CameraProperties::SUPPORTED_ZOOM_RATIOS));
p.set(CameraParameters::KEY_MAX_ZOOM, mCameraProperties->get(CameraProperties::SUPPORTED_ZOOM_STAGES));
p.set(CameraParameters::KEY_ZOOM_SUPPORTED, mCameraProperties->get(CameraProperties::ZOOM_SUPPORTED));
p.set(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_SUPPORTED,mCameraProperties->get(CameraProperties::S3D_SUPPORTED));
p.set(TICameraParameters::KEY_S3D2D_PREVIEW_MODE,mCameraProperties->get(CameraProperties::S3D2D_PREVIEW_MODES));
p.set(TICameraParameters::KEY_AUTOCONVERGENCE_MODE, mCameraProperties->get(CameraProperties::AUTOCONVERGENCE_MODE));
p.set(TICameraParameters::KEY_MANUALCONVERGENCE_VALUES, mCameraProperties->get(CameraProperties::MANUALCONVERGENCE_VALUES));
p.set(CameraParameters::KEY_VIDEO_STABILIZATION_SUPPORTED, mCameraProperties->get(CameraProperties::VSTAB_SUPPORTED));
p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE, mCameraProperties->get(CameraProperties::FRAMERATE_RANGE_SUPPORTED));
p.set(TICameraParameters::KEY_SENSOR_ORIENTATION, mCameraProperties->get(CameraProperties::SENSOR_ORIENTATION));
p.set(TICameraParameters::KEY_SENSOR_ORIENTATION_VALUES, mCameraProperties->get(CameraProperties::SENSOR_ORIENTATION_VALUES));
p.set(CameraParameters::KEY_AUTO_EXPOSURE_LOCK_SUPPORTED, mCameraProperties->get(CameraProperties::AUTO_EXPOSURE_LOCK_SUPPORTED));
p.set(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK_SUPPORTED, mCameraProperties->get(CameraProperties::AUTO_WHITEBALANCE_LOCK_SUPPORTED));
p.set(CameraParameters::KEY_VIDEO_SNAPSHOT_SUPPORTED, mCameraProperties->get(CameraProperties::VIDEO_SNAPSHOT_SUPPORTED));
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.
CameraParameters &p = mParameters;
int currentRevision, adapterRevision;
status_t ret = NO_ERROR;
int width, height;
LOG_FUNCTION_NAME;
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(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, width);
p.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, height);
}
else
{
p.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, MIN_WIDTH);
p.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, MIN_HEIGHT);
}
insertSupportedParams();
//Insert default values
p.setPreviewFrameRate(atoi(mCameraProperties->get(CameraProperties::PREVIEW_FRAME_RATE)));
p.setPreviewFormat(mCameraProperties->get(CameraProperties::PREVIEW_FORMAT));
p.setPictureFormat(mCameraProperties->get(CameraProperties::PICTURE_FORMAT));
p.set(CameraParameters::KEY_JPEG_QUALITY, mCameraProperties->get(CameraProperties::JPEG_QUALITY));
p.set(CameraParameters::KEY_WHITE_BALANCE, mCameraProperties->get(CameraProperties::WHITEBALANCE));
p.set(CameraParameters::KEY_EFFECT, mCameraProperties->get(CameraProperties::EFFECT));
p.set(CameraParameters::KEY_ANTIBANDING, mCameraProperties->get(CameraProperties::ANTIBANDING));
p.set(CameraParameters::KEY_FLASH_MODE, mCameraProperties->get(CameraProperties::FLASH_MODE));
p.set(CameraParameters::KEY_FOCUS_MODE, mCameraProperties->get(CameraProperties::FOCUS_MODE));
p.set(CameraParameters::KEY_EXPOSURE_COMPENSATION, mCameraProperties->get(CameraProperties::EV_COMPENSATION));
p.set(CameraParameters::KEY_SCENE_MODE, mCameraProperties->get(CameraProperties::SCENE_MODE));
p.set(CameraParameters::KEY_FLASH_MODE, mCameraProperties->get(CameraProperties::FLASH_MODE));
p.set(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_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_S3D2D_PREVIEW, mCameraProperties->get(CameraProperties::S3D2D_PREVIEW));
p.set(TICameraParameters::KEY_AUTOCONVERGENCE, mCameraProperties->get(CameraProperties::AUTOCONVERGENCE));
p.set(TICameraParameters::KEY_MANUALCONVERGENCE_VALUES, mCameraProperties->get(CameraProperties::MANUALCONVERGENCE_VALUES));
p.set(CameraParameters::KEY_VIDEO_STABILIZATION, mCameraProperties->get(CameraProperties::VSTAB));
p.set(CameraParameters::KEY_FOCAL_LENGTH, mCameraProperties->get(CameraProperties::FOCAL_LENGTH));
p.set(CameraParameters::KEY_HORIZONTAL_VIEW_ANGLE, mCameraProperties->get(CameraProperties::HOR_ANGLE));
p.set(CameraParameters::KEY_VERTICAL_VIEW_ANGLE, mCameraProperties->get(CameraProperties::VER_ANGLE));
p.set(CameraParameters::KEY_PREVIEW_FPS_RANGE,mCameraProperties->get(CameraProperties::FRAMERATE_RANGE));
p.set(TICameraParameters::KEY_SENSOR_ORIENTATION, mCameraProperties->get(CameraProperties::SENSOR_ORIENTATION));
p.set(TICameraParameters::KEY_SENSOR_ORIENTATION_VALUES, mCameraProperties->get(CameraProperties::SENSOR_ORIENTATION_VALUES));
p.set(TICameraParameters::KEY_EXIF_MAKE, mCameraProperties->get(CameraProperties::EXIF_MAKE));
p.set(TICameraParameters::KEY_EXIF_MODEL, mCameraProperties->get(CameraProperties::EXIF_MODEL));
p.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, mCameraProperties->get(CameraProperties::JPEG_THUMBNAIL_QUALITY));
p.set(CameraParameters::KEY_VIDEO_FRAME_FORMAT, "OMX_TI_COLOR_FormatYUV420PackedSemiPlanar");
p.set(CameraParameters::KEY_MAX_NUM_DETECTED_FACES_HW, mCameraProperties->get(CameraProperties::MAX_FD_HW_FACES));
p.set(CameraParameters::KEY_MAX_NUM_DETECTED_FACES_SW, mCameraProperties->get(CameraProperties::MAX_FD_SW_FACES));
// Only one area a.k.a Touch AF for now.
// TODO: Add support for multiple focus areas.
p.set(CameraParameters::KEY_MAX_NUM_FOCUS_AREAS, mCameraProperties->get(CameraProperties::MAX_FOCUS_AREAS));
p.set(CameraParameters::KEY_AUTO_EXPOSURE_LOCK, mCameraProperties->get(CameraProperties::AUTO_EXPOSURE_LOCK));
p.set(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK, mCameraProperties->get(CameraProperties::AUTO_WHITEBALANCE_LOCK));
p.set(CameraParameters::KEY_MAX_NUM_METERING_AREAS, mCameraProperties->get(CameraProperties::MAX_NUM_METERING_AREAS));
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
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;
}
LOG_FUNCTION_NAME_EXIT;
}
status_t CameraHal::storeMetaDataInBuffers(bool enable)
{
LOG_FUNCTION_NAME;
return mAppCallbackNotifier->useMetaDataBufferMode(enable);
LOG_FUNCTION_NAME_EXIT;
}
void CameraHal::selectFPSRange(int framerate, int *min_fps, int *max_fps)
{
char * ptr;
char supported[MAX_PROP_VALUE_LENGTH];
int fpsrangeArray[2];
int i = 0;
LOG_FUNCTION_NAME;
size_t size = strlen(mCameraProperties->get(CameraProperties::FRAMERATE_RANGE_SUPPORTED))+1;
strncpy(supported, mCameraProperties->get(CameraProperties::FRAMERATE_RANGE_SUPPORTED), size);
ptr = strtok (supported," (,)");
while (ptr != NULL)
{
fpsrangeArray[i]= atoi(ptr)/CameraHal::VFR_SCALE;
if (i == 1)
{
if (framerate == fpsrangeArray[i])
{
CAMHAL_LOGDB("SETTING FPS RANGE min = %d max = %d \n", fpsrangeArray[0], fpsrangeArray[1]);
*min_fps = fpsrangeArray[0]*CameraHal::VFR_SCALE;
*max_fps = fpsrangeArray[1]*CameraHal::VFR_SCALE;
break;
}
}
ptr = strtok (NULL, " (,)");
i++;
i%=2;
}
LOG_FUNCTION_NAME_EXIT;
}
void CameraHal::setPreferredPreviewRes(int width, int height)
{
LOG_FUNCTION_NAME;
if ( (width == 320) && (height == 240)){
mParameters.setPreviewSize(640,480);
}
if ( (width == 176) && (height == 144)){
mParameters.setPreviewSize(704,576);
}
LOG_FUNCTION_NAME_EXIT;
}
void CameraHal::resetPreviewRes(CameraParameters *mParams, int width, int height)
{
LOG_FUNCTION_NAME;
if ( (width <= 320) && (height <= 240)){
mParams->setPreviewSize(mVideoWidth, mVideoHeight);
}
LOG_FUNCTION_NAME_EXIT;
}
};