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