| /* |
| * Copyright (C) Texas Instruments - http://www.ti.com/ |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2.1 of the License, or (at your option) any later version. |
| * |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| /** |
| * @file CameraHal.cpp |
| * |
| * This file maps the Camera Hardware Interface to V4L2. |
| * |
| */ |
| |
| #define LOG_TAG "CameraHal" |
| |
| #include "CameraHal.h" |
| #include <poll.h> |
| #include "zoom_step.inc" |
| |
| #include <math.h> |
| |
| #include <cutils/properties.h> |
| #define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) |
| static int mDebugFps = 0; |
| |
| #define RES_720P 1280 |
| |
| namespace android { |
| /*****************************************************************************/ |
| |
| /* |
| * This is the overlay_t object, it is returned to the user and represents |
| * an overlay. here we use a subclass, where we can store our own state. |
| * This handles will be passed across processes and possibly given to other |
| * HAL modules (for instance video decode modules). |
| */ |
| struct overlay_true_handle_t : public native_handle { |
| /* add the data fields we need here, for instance: */ |
| int ctl_fd; |
| int shared_fd; |
| int width; |
| int height; |
| int format; |
| int num_buffers; |
| int shared_size; |
| }; |
| |
| /* Defined in liboverlay */ |
| typedef struct { |
| int fd; |
| size_t length; |
| uint32_t offset; |
| void *ptr; |
| } mapping_data_t; |
| |
| int CameraHal::camera_device = 0; |
| wp<CameraHardwareInterface> CameraHal::singleton; |
| const char CameraHal::supportedPictureSizes [] = "3264x2448,2560x2048,2048x1536,1600x1200,1280x1024,1152x968,1280x960,800x600,640x480,320x240"; |
| const char CameraHal::supportedPreviewSizes [] = "1280x720,992x560,864x480,800x480,720x576,720x480,768x576,640x480,320x240,352x288,240x160,176x144,128x96"; |
| const char CameraHal::supportedFPS [] = "33,30,25,24,20,15,10"; |
| const char CameraHal::supportedThumbnailSizes []= "512x384,320x240,80x60,0x0"; |
| const char CameraHal::PARAMS_DELIMITER []= ","; |
| |
| const supported_resolution CameraHal::supportedPictureRes[] = { {3264, 2448} , {2560, 2048} , |
| {2048, 1536} , {1600, 1200} , |
| {1280, 1024} , {1152, 968} , |
| {1280, 960} , {800, 600}, |
| {640, 480} , {320, 240} }; |
| |
| const supported_resolution CameraHal::supportedPreviewRes[] = { {1280, 720}, {800, 480}, |
| {720, 576}, {720, 480}, |
| {992, 560}, {864, 480}, {848, 480}, |
| {768, 576}, {640, 480}, |
| {320, 240}, {352, 288}, {240, 160}, |
| {176, 144}, {128, 96}}; |
| |
| int camerahal_strcat(char *dst, const char *src, size_t size) |
| { |
| size_t actual_size; |
| |
| actual_size = strlcat(dst, src, size); |
| if(actual_size > size) |
| { |
| LOGE("Unexpected truncation from camerahal_strcat dst=%s src=%s", dst, src); |
| return actual_size; |
| } |
| |
| return 0; |
| } |
| |
| CameraHal::CameraHal() |
| :mParameters(), |
| mOverlay(NULL), |
| mPreviewRunning(0), |
| mRecordingFrameSize(0), |
| mVideoBufferCount(0), |
| nOverlayBuffersQueued(0), |
| nCameraBuffersQueued(0), |
| mfirstTime(0), |
| pictureNumber(0), |
| #ifdef FW3A |
| fobj(NULL), |
| #endif |
| file_index(0), |
| mflash(2), |
| mcapture_mode(1), |
| mcaf(0), |
| j(0) |
| { |
| #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS |
| gettimeofday(&ppm_start, NULL); |
| #endif |
| |
| isStart_FW3A = false; |
| isStart_FW3A_AF = false; |
| isStart_FW3A_CAF = false; |
| isStart_FW3A_AEWB = false; |
| isStart_VPP = false; |
| isStart_JPEG = false; |
| mPictureHeap = NULL; |
| mIPPInitAlgoState = false; |
| mIPPToEnable = false; |
| mRecordEnabled = 0; |
| mNotifyCb = 0; |
| mDataCb = 0; |
| mDataCbTimestamp = 0; |
| mCallbackCookie = 0; |
| mMsgEnabled = 0 ; |
| mFalsePreview = false; //Eclair HAL |
| mZoomSpeed = 1; |
| mZoomTargetIdx = 0; |
| mZoomCurrentIdx = 0; |
| mSmoothZoomStatus = SMOOTH_STOP; |
| rotation = 0; |
| |
| #ifdef HARDWARE_OMX |
| |
| gpsLocation = NULL; |
| |
| #endif |
| |
| mShutterEnable = true; |
| sStart_FW3A_CAF:mCAFafterPreview = false; |
| ancillary_len = 8092; |
| |
| #ifdef IMAGE_PROCESSING_PIPELINE |
| |
| pIPP.hIPP = NULL; |
| |
| #endif |
| |
| int i = 0; |
| for(i = 0; i < VIDEO_FRAME_COUNT_MAX; i++) |
| { |
| mVideoBuffer[i] = 0; |
| buffers_queued_to_dss[i] = 0; |
| } |
| |
| CameraCreate(); |
| |
| initDefaultParameters(); |
| |
| /* Avoiding duplicate call of cameraconfigure(). It is now called in previewstart() */ |
| //CameraConfigure(); |
| |
| #ifdef FW3A |
| FW3A_Create(); |
| FW3A_Init(); |
| #endif |
| |
| ICaptureCreate(); |
| |
| mPreviewThread = new PreviewThread(this); |
| mPreviewThread->run("CameraPreviewThread", PRIORITY_URGENT_DISPLAY); |
| |
| if( pipe(procPipe) != 0 ){ |
| LOGE("Failed creating pipe"); |
| } |
| |
| if( pipe(shutterPipe) != 0 ){ |
| LOGE("Failed creating pipe"); |
| } |
| |
| if( pipe(rawPipe) != 0 ){ |
| LOGE("Failed creating pipe"); |
| } |
| |
| if( pipe(snapshotPipe) != 0 ){ |
| LOGE("Failed creating pipe"); |
| } |
| |
| if( pipe(snapshotReadyPipe) != 0 ){ |
| LOGE("Failed creating pipe"); |
| } |
| |
| mPROCThread = new PROCThread(this); |
| mPROCThread->run("CameraPROCThread", PRIORITY_URGENT_DISPLAY); |
| LOGD("STARTING PROC THREAD \n"); |
| |
| mShutterThread = new ShutterThread(this); |
| mShutterThread->run("CameraShutterThread", PRIORITY_URGENT_DISPLAY); |
| LOGD("STARTING Shutter THREAD \n"); |
| |
| mRawThread = new RawThread(this); |
| mRawThread->run("CameraRawThread", PRIORITY_URGENT_DISPLAY); |
| LOGD("STARTING Raw THREAD \n"); |
| |
| mSnapshotThread = new SnapshotThread(this); |
| mSnapshotThread->run("CameraSnapshotThread", PRIORITY_URGENT_DISPLAY); |
| LOGD("STARTING Snapshot THREAD \n"); |
| |
| char value[PROPERTY_VALUE_MAX]; |
| property_get("debug.image.showfps", value, "0"); |
| mDebugFps = atoi(value); |
| LOGD_IF(mDebugFps, "showfps enabled"); |
| |
| |
| } |
| |
| bool CameraHal::validateSize(size_t width, size_t height, const supported_resolution *supRes, size_t count) |
| { |
| bool ret = false; |
| status_t stat = NO_ERROR; |
| unsigned int size; |
| |
| LOG_FUNCTION_NAME |
| |
| if ( NULL == supRes ) { |
| LOGE("Invalid resolutions array passed"); |
| stat = -EINVAL; |
| } |
| |
| if ( NO_ERROR == stat ) { |
| for ( unsigned int i = 0 ; i < count; i++ ) { |
| LOGD( "Validating %d, %d and %d, %d", supRes[i].width, width, supRes[i].height, height); |
| if ( ( supRes[i].width == width ) && ( supRes[i].height == height ) ) { |
| ret = true; |
| break; |
| } |
| } |
| } |
| |
| LOG_FUNCTION_NAME_EXIT |
| |
| return ret; |
| } |
| |
| void CameraHal::initDefaultParameters() |
| { |
| CameraParameters p; |
| char tmpBuffer[PARAM_BUFFER], zoomStageBuffer[PARAM_BUFFER]; |
| unsigned int zoomStage; |
| |
| LOG_FUNCTION_NAME |
| |
| p.setPreviewSize(MIN_WIDTH, MIN_HEIGHT); |
| p.setPreviewFrameRate(30); |
| p.setPreviewFormat(CameraParameters::PIXEL_FORMAT_YUV422I); |
| |
| p.setPictureSize(PICTURE_WIDTH, PICTURE_HEIGHT); |
| p.setPictureFormat(CameraParameters::PIXEL_FORMAT_JPEG); |
| p.set(CameraParameters::KEY_JPEG_QUALITY, 100); |
| |
| //extended parameters |
| |
| memset(tmpBuffer, '\0', PARAM_BUFFER); |
| for ( int i = 0 ; i < ZOOM_STAGES ; i++ ) { |
| zoomStage = (unsigned int ) ( zoom_step[i]*PARM_ZOOM_SCALE ); |
| snprintf(zoomStageBuffer, PARAM_BUFFER, "%d", zoomStage); |
| |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) zoomStageBuffer, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) PARAMS_DELIMITER, PARAM_BUFFER)) return; |
| } |
| p.set(CameraParameters::KEY_ZOOM_RATIOS, tmpBuffer); |
| p.set(CameraParameters::KEY_ZOOM_SUPPORTED, "true"); |
| p.set(CameraParameters::KEY_SMOOTH_ZOOM_SUPPORTED, "true"); |
| // zoom goes from 0..MAX_ZOOM so send array size minus one |
| p.set(CameraParameters::KEY_MAX_ZOOM, ZOOM_STAGES-1); |
| p.set(CameraParameters::KEY_ZOOM, 0); |
| |
| p.set(CameraParameters::KEY_MAX_EXPOSURE_COMPENSATION, COMPENSATION_MAX); |
| p.set(CameraParameters::KEY_MIN_EXPOSURE_COMPENSATION, COMPENSATION_MIN); |
| p.set(CameraParameters::KEY_EXPOSURE_COMPENSATION_STEP, COMPENSATION_STEP); |
| p.set(CameraParameters::KEY_EXPOSURE_COMPENSATION, 0); |
| |
| p.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES, CameraHal::supportedPictureSizes); |
| p.set(CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS, CameraParameters::PIXEL_FORMAT_JPEG); |
| p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES, CameraHal::supportedPreviewSizes); |
| p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS, CameraParameters::PIXEL_FORMAT_YUV422I); |
| p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES, CameraHal::supportedFPS); |
| p.set(CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES, CameraHal::supportedThumbnailSizes); |
| p.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, STRINGIZE(DEFAULT_THUMB_WIDTH)); |
| p.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, STRINGIZE(DEFAULT_THUMB_HEIGHT)); |
| |
| p.set(CameraParameters::KEY_FOCAL_LENGTH, STRINGIZE(IMX046_FOCALLENGTH)); |
| p.set(CameraParameters::KEY_HORIZONTAL_VIEW_ANGLE, STRINGIZE(IMX046_HORZANGLE)); |
| p.set(CameraParameters::KEY_VERTICAL_VIEW_ANGLE, STRINGIZE(IMX046_VERTANGLE)); |
| |
| memset(tmpBuffer, '\0', PARAM_BUFFER); |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) CameraParameters::WHITE_BALANCE_AUTO, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) PARAMS_DELIMITER, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) CameraParameters::WHITE_BALANCE_INCANDESCENT, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) PARAMS_DELIMITER, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) CameraParameters::WHITE_BALANCE_FLUORESCENT, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) PARAMS_DELIMITER, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) CameraParameters::WHITE_BALANCE_DAYLIGHT, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) PARAMS_DELIMITER, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) CameraParameters::WHITE_BALANCE_SHADE, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) PARAMS_DELIMITER, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) CameraParameters::WHITE_BALANCE_CLOUDY_DAYLIGHT, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) PARAMS_DELIMITER, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) WHITE_BALANCE_HORIZON, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) PARAMS_DELIMITER, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) WHITE_BALANCE_TUNGSTEN, PARAM_BUFFER)) return; |
| p.set(CameraParameters::KEY_SUPPORTED_WHITE_BALANCE, tmpBuffer); |
| p.set(CameraParameters::KEY_WHITE_BALANCE, CameraParameters::WHITE_BALANCE_AUTO); |
| |
| memset(tmpBuffer, '\0', sizeof(*tmpBuffer)); |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) CameraParameters::EFFECT_NONE, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) PARAMS_DELIMITER, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) CameraParameters::EFFECT_MONO, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) PARAMS_DELIMITER, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) CameraParameters::EFFECT_NEGATIVE, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) PARAMS_DELIMITER, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) CameraParameters::EFFECT_SOLARIZE, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) PARAMS_DELIMITER, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) CameraParameters::EFFECT_SEPIA, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) PARAMS_DELIMITER, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) CameraParameters::EFFECT_WHITEBOARD, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) PARAMS_DELIMITER, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) CameraParameters::EFFECT_BLACKBOARD, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) PARAMS_DELIMITER, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) EFFECT_COOL, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) PARAMS_DELIMITER, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) EFFECT_EMBOSS, PARAM_BUFFER)) return; |
| p.set(CameraParameters::KEY_SUPPORTED_EFFECTS, tmpBuffer); |
| p.set(CameraParameters::KEY_EFFECT, CameraParameters::EFFECT_NONE); |
| |
| memset(tmpBuffer, '\0', sizeof(*tmpBuffer)); |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) CameraParameters::SCENE_MODE_AUTO, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) PARAMS_DELIMITER, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) CameraParameters::SCENE_MODE_PORTRAIT, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) PARAMS_DELIMITER, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) CameraParameters::SCENE_MODE_LANDSCAPE, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) PARAMS_DELIMITER, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) CameraParameters::SCENE_MODE_ACTION, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) PARAMS_DELIMITER, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) CameraParameters::SCENE_MODE_NIGHT_PORTRAIT, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) PARAMS_DELIMITER, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) CameraParameters::SCENE_MODE_FIREWORKS, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) PARAMS_DELIMITER, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) CameraParameters::SCENE_MODE_NIGHT, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) PARAMS_DELIMITER, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) CameraParameters::SCENE_MODE_SNOW, PARAM_BUFFER)) return; |
| p.set(CameraParameters::KEY_SUPPORTED_SCENE_MODES, tmpBuffer); |
| p.set(CameraParameters::KEY_SCENE_MODE, CameraParameters::SCENE_MODE_AUTO); |
| |
| memset(tmpBuffer, '\0', sizeof(*tmpBuffer)); |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) CameraParameters::FOCUS_MODE_AUTO, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) PARAMS_DELIMITER, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) CameraParameters::FOCUS_MODE_INFINITY, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) PARAMS_DELIMITER, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) CameraParameters::FOCUS_MODE_MACRO, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) PARAMS_DELIMITER, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) CameraParameters::FOCUS_MODE_FIXED, PARAM_BUFFER)) return; |
| p.set(CameraParameters::KEY_SUPPORTED_FOCUS_MODES, tmpBuffer); |
| p.set(CameraParameters::KEY_FOCUS_MODE, CameraParameters::FOCUS_MODE_AUTO); |
| |
| memset(tmpBuffer, '\0', sizeof(*tmpBuffer)); |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) CameraParameters::ANTIBANDING_50HZ, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) PARAMS_DELIMITER, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) CameraParameters::ANTIBANDING_60HZ, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) PARAMS_DELIMITER, PARAM_BUFFER)) return; |
| if(camerahal_strcat((char*) tmpBuffer, (const char*) CameraParameters::ANTIBANDING_OFF, PARAM_BUFFER)) return; |
| p.set(CameraParameters::KEY_SUPPORTED_ANTIBANDING, tmpBuffer); |
| p.set(CameraParameters::KEY_ANTIBANDING, CameraParameters::ANTIBANDING_OFF); |
| |
| p.set(CameraParameters::KEY_ROTATION, 0); |
| p.set(KEY_ROTATION_TYPE, ROTATION_PHYSICAL); |
| |
| if (setParameters(p) != NO_ERROR) { |
| LOGE("Failed to set default parameters?!"); |
| } |
| |
| LOG_FUNCTION_NAME_EXIT |
| |
| } |
| |
| |
| CameraHal::~CameraHal() |
| { |
| int err = 0; |
| int procMessage [1]; |
| sp<PROCThread> procThread; |
| sp<RawThread> rawThread; |
| sp<ShutterThread> shutterThread; |
| sp<SnapshotThread> snapshotThread; |
| |
| LOG_FUNCTION_NAME |
| |
| |
| if(mPreviewThread != NULL) { |
| Message msg; |
| msg.command = PREVIEW_KILL; |
| previewThreadCommandQ.put(&msg); |
| previewThreadAckQ.get(&msg); |
| } |
| |
| sp<PreviewThread> previewThread; |
| |
| { // scope for the lock |
| Mutex::Autolock lock(mLock); |
| previewThread = mPreviewThread; |
| } |
| |
| // don't hold the lock while waiting for the thread to quit |
| if (previewThread != 0) { |
| previewThread->requestExitAndWait(); |
| } |
| |
| { // scope for the lock |
| Mutex::Autolock lock(mLock); |
| mPreviewThread.clear(); |
| } |
| |
| procMessage[0] = PROC_THREAD_EXIT; |
| write(procPipe[1], procMessage, sizeof(unsigned int)); |
| |
| { // scope for the lock |
| Mutex::Autolock lock(mLock); |
| procThread = mPROCThread; |
| } |
| |
| // don't hold the lock while waiting for the thread to quit |
| if (procThread != 0) { |
| procThread->requestExitAndWait(); |
| } |
| |
| { // scope for the lock |
| Mutex::Autolock lock(mLock); |
| mPROCThread.clear(); |
| close(procPipe[0]); |
| close(procPipe[1]); |
| } |
| |
| procMessage[0] = SHUTTER_THREAD_EXIT; |
| write(shutterPipe[1], procMessage, sizeof(unsigned int)); |
| |
| { // scope for the lock |
| Mutex::Autolock lock(mLock); |
| shutterThread = mShutterThread; |
| } |
| |
| // don't hold the lock while waiting for the thread to quit |
| if (shutterThread != 0) { |
| shutterThread->requestExitAndWait(); |
| } |
| |
| { // scope for the lock |
| Mutex::Autolock lock(mLock); |
| mShutterThread.clear(); |
| close(shutterPipe[0]); |
| close(shutterPipe[1]); |
| } |
| |
| procMessage[0] = RAW_THREAD_EXIT; |
| write(rawPipe[1], procMessage, sizeof(unsigned int)); |
| |
| { // scope for the lock |
| Mutex::Autolock lock(mLock); |
| rawThread = mRawThread; |
| } |
| |
| // don't hold the lock while waiting for the thread to quit |
| if (rawThread != 0) { |
| rawThread->requestExitAndWait(); |
| } |
| |
| { // scope for the lock |
| Mutex::Autolock lock(mLock); |
| mRawThread.clear(); |
| close(rawPipe[0]); |
| close(rawPipe[1]); |
| } |
| |
| procMessage[0] = SNAPSHOT_THREAD_EXIT; |
| write(snapshotPipe[1], procMessage, sizeof(unsigned int)); |
| |
| { |
| Mutex::Autolock lock(mLock); |
| snapshotThread = mSnapshotThread; |
| } |
| |
| if (snapshotThread != 0 ) { |
| snapshotThread->requestExitAndWait(); |
| } |
| |
| { |
| Mutex::Autolock lock(mLock); |
| mSnapshotThread.clear(); |
| close(snapshotPipe[0]); |
| close(snapshotPipe[1]); |
| close(snapshotReadyPipe[0]); |
| close(snapshotReadyPipe[1]); |
| } |
| |
| ICaptureDestroy(); |
| |
| #ifdef FW3A |
| FW3A_Release(); |
| FW3A_Destroy(); |
| #endif |
| |
| CameraDestroy(true); |
| |
| |
| #ifdef IMAGE_PROCESSING_PIPELINE |
| |
| if(pIPP.hIPP != NULL){ |
| err = DeInitIPP(mippMode); |
| if( err ) |
| LOGE("ERROR DeInitIPP() failed"); |
| |
| pIPP.hIPP = NULL; |
| } |
| |
| #endif |
| |
| if ( mOverlay.get() != NULL ) |
| { |
| LOGD("Destroying current overlay"); |
| mOverlay->destroy(); |
| } |
| |
| singleton.clear(); |
| |
| LOGD("<<< Release"); |
| } |
| |
| void CameraHal::previewThread() |
| { |
| Message msg; |
| int parm; |
| bool shouldLive = true; |
| bool has_message; |
| int err; |
| struct pollfd pfd[2]; |
| |
| LOG_FUNCTION_NAME |
| |
| while(shouldLive) { |
| |
| has_message = false; |
| |
| if( mPreviewRunning ) |
| { |
| |
| pfd[0].fd = previewThreadCommandQ.getInFd(); |
| pfd[0].events = POLLIN; |
| pfd[1].fd = camera_device; |
| pfd[1].events = POLLIN; |
| |
| if (poll(pfd, 2, 1000) == 0) { |
| continue; |
| } |
| |
| if (pfd[0].revents & POLLIN) { |
| previewThreadCommandQ.get(&msg); |
| has_message = true; |
| } |
| |
| if (pfd[1].revents & POLLIN) { |
| nextPreview(); |
| } |
| |
| #ifdef FW3A |
| |
| if ( isStart_FW3A_AF ) { |
| err = ICam_ReadStatus(fobj->hnd, &fobj->status); |
| if ( (err == 0) && ( ICAM_AF_STATUS_RUNNING != fobj->status.af.status ) ) { |
| |
| #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS |
| |
| PPM("AF Completed in ",&focus_before); |
| |
| #endif |
| |
| ICam_ReadMakerNote(fobj->hnd, &fobj->mnote); |
| |
| if (FW3A_Stop_AF() < 0){ |
| LOGE("ERROR FW3A_Stop_AF()"); |
| } |
| |
| bool focus_flag; |
| if ( fobj->status.af.status == ICAM_AF_STATUS_SUCCESS ) { |
| focus_flag = true; |
| LOGE("AF Success"); |
| } else { |
| focus_flag = false; |
| LOGE("AF Fail"); |
| } |
| |
| if( msgTypeEnabled(CAMERA_MSG_FOCUS) ) |
| mNotifyCb(CAMERA_MSG_FOCUS, focus_flag, 0, mCallbackCookie); |
| } |
| } |
| #endif |
| |
| } |
| else |
| { |
| //block for message |
| previewThreadCommandQ.get(&msg); |
| has_message = true; |
| } |
| |
| if( !has_message ) |
| continue; |
| |
| switch(msg.command) |
| { |
| case PREVIEW_START: |
| { |
| LOGD("Receive Command: PREVIEW_START"); |
| err = 0; |
| |
| if( ! mPreviewRunning ) { |
| |
| if( CameraCreate() < 0){ |
| LOGE("ERROR CameraCreate()"); |
| err = -1; |
| } |
| |
| PPM("CONFIGURING CAMERA TO RESTART PREVIEW"); |
| if (CameraConfigure() < 0){ |
| LOGE("ERROR CameraConfigure()"); |
| err = -1; |
| } |
| |
| #ifdef FW3A |
| |
| if (FW3A_Start() < 0){ |
| LOGE("ERROR FW3A_Start()"); |
| err = -1; |
| } |
| |
| if (FW3A_SetSettings() < 0){ |
| LOGE("ERROR FW3A_SetSettings()"); |
| err = -1; |
| } |
| |
| #endif |
| |
| if ( CorrectPreview() < 0 ) |
| LOGE("Error during CorrectPreview()"); |
| |
| if ( CameraStart() < 0 ) { |
| LOGE("ERROR CameraStart()"); |
| err = -1; |
| } |
| |
| #ifdef FW3A |
| if ( mCAFafterPreview ) { |
| mCAFafterPreview = false; |
| if( FW3A_Start_CAF() < 0 ) |
| LOGE("Error while starting CAF"); |
| } |
| #endif |
| |
| if(!mfirstTime){ |
| PPM("Standby to first shot"); |
| mfirstTime++; |
| } else { |
| |
| #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS |
| PPM("Shot to Shot", &ppm_receiveCmdToTakePicture); |
| |
| #endif |
| |
| } |
| } else { |
| err = -1; |
| } |
| |
| LOGD("PREVIEW_START %s", err ? "NACK" : "ACK"); |
| msg.command = err ? PREVIEW_NACK : PREVIEW_ACK; |
| |
| if ( !err ) { |
| LOGD("Preview Started!"); |
| mPreviewRunning = true; |
| } |
| |
| previewThreadAckQ.put(&msg); |
| } |
| break; |
| |
| case PREVIEW_STOP: |
| { |
| LOGD("Receive Command: PREVIEW_STOP"); |
| err = 0; |
| if( mPreviewRunning ) { |
| |
| #ifdef FW3A |
| |
| if( FW3A_Stop_AF() < 0){ |
| LOGE("ERROR FW3A_Stop_AF()"); |
| err= -1; |
| } |
| if( FW3A_Stop_CAF() < 0){ |
| LOGE("ERROR FW3A_Stop_CAF()"); |
| err= -1; |
| } else { |
| mcaf = 0; |
| } |
| if( FW3A_Stop() < 0){ |
| LOGE("ERROR FW3A_Stop()"); |
| err= -1; |
| } |
| if( FW3A_GetSettings() < 0){ |
| LOGE("ERROR FW3A_GetSettings()"); |
| err= -1; |
| } |
| |
| #endif |
| |
| if( CameraStop() < 0){ |
| LOGE("ERROR CameraStop()"); |
| err= -1; |
| } |
| |
| if( CameraDestroy(false) < 0){ |
| LOGE("ERROR CameraDestroy()"); |
| err= -1; |
| } |
| |
| if (err) { |
| LOGE("ERROR Cannot deinit preview."); |
| } |
| |
| LOGD("PREVIEW_STOP %s", err ? "NACK" : "ACK"); |
| msg.command = err ? PREVIEW_NACK : PREVIEW_ACK; |
| } |
| else |
| { |
| msg.command = PREVIEW_NACK; |
| } |
| |
| mPreviewRunning = false; |
| |
| previewThreadAckQ.put(&msg); |
| } |
| break; |
| |
| case START_SMOOTH_ZOOM: |
| |
| parm = ( int ) msg.arg1; |
| |
| LOGD("Receive Command: START_SMOOTH_ZOOM %d", parm); |
| |
| if ( ( parm >= 0 ) && ( parm < ZOOM_STAGES) ) { |
| mZoomTargetIdx = parm; |
| mZoomSpeed = 1; |
| mSmoothZoomStatus = SMOOTH_START; |
| msg.command = PREVIEW_ACK; |
| } else { |
| msg.command = PREVIEW_NACK; |
| } |
| |
| previewThreadAckQ.put(&msg); |
| |
| break; |
| |
| case STOP_SMOOTH_ZOOM: |
| |
| LOGD("Receive Command: STOP_SMOOTH_ZOOM"); |
| if(mSmoothZoomStatus == SMOOTH_START) |
| { |
| mSmoothZoomStatus = SMOOTH_NOTIFY_AND_STOP; |
| } |
| msg.command = PREVIEW_ACK; |
| |
| previewThreadAckQ.put(&msg); |
| |
| break; |
| |
| case PREVIEW_AF_START: |
| { |
| LOGD("Receive Command: PREVIEW_AF_START"); |
| err = 0; |
| |
| if( !mPreviewRunning ){ |
| LOGD("WARNING PREVIEW NOT RUNNING!"); |
| msg.command = PREVIEW_NACK; |
| } else { |
| |
| #ifdef FW3A |
| |
| if (isStart_FW3A_CAF!= 0){ |
| if( FW3A_Stop_CAF() < 0){ |
| LOGE("ERROR FW3A_Stop_CAF();"); |
| err = -1; |
| } |
| } |
| |
| #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS |
| |
| gettimeofday(&focus_before, NULL); |
| |
| #endif |
| if (isStart_FW3A){ |
| if (isStart_FW3A_AF == 0){ |
| if( FW3A_Start_AF() < 0){ |
| LOGE("ERROR FW3A_Start_AF()"); |
| err = -1; |
| } |
| |
| } |
| } else { |
| if(msgTypeEnabled(CAMERA_MSG_FOCUS)) |
| mNotifyCb(CAMERA_MSG_FOCUS, true, 0, mCallbackCookie); |
| } |
| |
| msg.command = err ? PREVIEW_NACK : PREVIEW_ACK; |
| |
| #else |
| |
| if( msgTypeEnabled(CAMERA_MSG_FOCUS) ) |
| mNotifyCb(CAMERA_MSG_FOCUS, true, 0, mCallbackCookie); |
| |
| msg.command = PREVIEW_ACK; |
| |
| #endif |
| |
| } |
| LOGD("Receive Command: PREVIEW_AF_START %s", msg.command == PREVIEW_NACK ? "NACK" : "ACK"); |
| previewThreadAckQ.put(&msg); |
| } |
| break; |
| |
| case PREVIEW_CAF_START: |
| { |
| LOGD("Receive Command: PREVIEW_CAF_START"); |
| err=0; |
| |
| if( !mPreviewRunning ) { |
| msg.command = PREVIEW_ACK; |
| mCAFafterPreview = true; |
| } |
| else |
| { |
| #ifdef FW3A |
| if (isStart_FW3A_CAF == 0){ |
| if( FW3A_Start_CAF() < 0){ |
| LOGE("ERROR FW3A_Start_CAF()"); |
| err = -1; |
| } |
| } |
| #endif |
| msg.command = err ? PREVIEW_NACK : PREVIEW_ACK; |
| } |
| LOGD("Receive Command: PREVIEW_CAF_START %s", msg.command == PREVIEW_NACK ? "NACK" : "ACK"); |
| previewThreadAckQ.put(&msg); |
| } |
| break; |
| |
| case PREVIEW_CAF_STOP: |
| { |
| LOGD("Receive Command: PREVIEW_CAF_STOP"); |
| err = 0; |
| |
| if( !mPreviewRunning ) |
| msg.command = PREVIEW_ACK; |
| else |
| { |
| #ifdef FW3A |
| if( FW3A_Stop_CAF() < 0){ |
| LOGE("ERROR FW3A_Stop_CAF()"); |
| err = -1; |
| } |
| #endif |
| msg.command = err ? PREVIEW_NACK : PREVIEW_ACK; |
| } |
| LOGD("Receive Command: PREVIEW_CAF_STOP %s", msg.command == PREVIEW_NACK ? "NACK" : "ACK"); |
| previewThreadAckQ.put(&msg); |
| } |
| break; |
| |
| case PREVIEW_CAPTURE: |
| { |
| int flg_AF = 0; |
| int flg_CAF = 0; |
| err = 0; |
| |
| #ifdef DEBUG_LOG |
| |
| LOGD("ENTER OPTION PREVIEW_CAPTURE"); |
| |
| PPM("RECEIVED COMMAND TO TAKE A PICTURE"); |
| |
| #endif |
| |
| #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS |
| gettimeofday(&ppm_receiveCmdToTakePicture, NULL); |
| #endif |
| |
| // Boost DSP OPP to highest level |
| SetDSPHz(DSP3630_HZ_MAX); |
| |
| if( mPreviewRunning ) { |
| if( CameraStop() < 0){ |
| LOGE("ERROR CameraStop()"); |
| err = -1; |
| } |
| |
| #ifdef FW3A |
| if( (flg_AF = FW3A_Stop_AF()) < 0){ |
| LOGE("ERROR FW3A_Stop_AF()"); |
| err = -1; |
| } |
| if( (flg_CAF = FW3A_Stop_CAF()) < 0){ |
| LOGE("ERROR FW3A_Stop_CAF()"); |
| err = -1; |
| } else { |
| mcaf = 0; |
| } |
| |
| if ( ICam_ReadStatus(fobj->hnd, &fobj->status) < 0 ) { |
| LOGE("ICam_ReadStatus failed"); |
| err = -1; |
| } |
| |
| if ( ICam_ReadMakerNote(fobj->hnd, &fobj->mnote) < 0 ) { |
| LOGE("ICam_ReadMakerNote failed"); |
| err = -1; |
| } |
| |
| if( FW3A_Stop() < 0){ |
| LOGE("ERROR FW3A_Stop()"); |
| err = -1; |
| } |
| #endif |
| |
| mPreviewRunning = false; |
| |
| } |
| #ifdef FW3A |
| if( FW3A_GetSettings() < 0){ |
| LOGE("ERROR FW3A_GetSettings()"); |
| err = -1; |
| } |
| #endif |
| |
| #ifdef DEBUG_LOG |
| |
| PPM("STOPPED PREVIEW"); |
| |
| #endif |
| |
| if( ICapturePerform() < 0){ |
| LOGE("ERROR ICapturePerform()"); |
| err = -1; |
| } |
| |
| if( err ) |
| LOGE("Capture failed."); |
| |
| //restart the preview |
| #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS |
| gettimeofday(&ppm_restartPreview, NULL); |
| #endif |
| |
| #ifdef DEBUG_LOG |
| |
| PPM("CONFIGURING CAMERA TO RESTART PREVIEW"); |
| |
| #endif |
| |
| if (CameraConfigure() < 0) |
| LOGE("ERROR CameraConfigure()"); |
| |
| #ifdef FW3A |
| |
| if (FW3A_Start() < 0) |
| LOGE("ERROR FW3A_Start()"); |
| |
| #endif |
| |
| if ( CorrectPreview() < 0 ) |
| LOGE("Error during CorrectPreview()"); |
| |
| if (CameraStart() < 0) |
| LOGE("ERROR CameraStart()"); |
| |
| #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS |
| |
| PPM("Capture mode switch", &ppm_restartPreview); |
| PPM("Shot to Shot", &ppm_receiveCmdToTakePicture); |
| |
| #endif |
| |
| #ifdef FW3A |
| |
| if ( flg_CAF ) { |
| if( FW3A_Start_CAF() < 0 ) |
| LOGE("Error while starting CAF"); |
| } |
| |
| #endif |
| |
| mPreviewRunning = true; |
| |
| msg.command = PREVIEW_ACK; |
| previewThreadAckQ.put(&msg); |
| LOGD("EXIT OPTION PREVIEW_CAPTURE"); |
| } |
| break; |
| |
| case PREVIEW_CAPTURE_CANCEL: |
| { |
| LOGD("Receive Command: PREVIEW_CAPTURE_CANCEL"); |
| msg.command = PREVIEW_NACK; |
| previewThreadAckQ.put(&msg); |
| } |
| break; |
| |
| case PREVIEW_KILL: |
| { |
| LOGD("Receive Command: PREVIEW_KILL"); |
| err = 0; |
| |
| if (mPreviewRunning) { |
| #ifdef FW3A |
| if( FW3A_Stop_AF() < 0){ |
| LOGE("ERROR FW3A_Stop_AF()"); |
| err = -1; |
| } |
| if( FW3A_Stop_CAF() < 0){ |
| LOGE("ERROR FW3A_Stop_CAF()"); |
| err = -1; |
| } |
| if( FW3A_Stop() < 0){ |
| LOGE("ERROR FW3A_Stop()"); |
| err = -1; |
| } |
| #endif |
| if( CameraStop() < 0){ |
| LOGE("ERROR FW3A_Stop()"); |
| err = -1; |
| } |
| mPreviewRunning = false; |
| } |
| |
| msg.command = err ? PREVIEW_NACK : PREVIEW_ACK; |
| LOGD("Receive Command: PREVIEW_CAF_STOP %s", msg.command == PREVIEW_NACK ? "NACK" : "ACK"); |
| |
| previewThreadAckQ.put(&msg); |
| shouldLive = false; |
| } |
| break; |
| } |
| } |
| |
| LOG_FUNCTION_NAME_EXIT |
| } |
| |
| int CameraHal::CameraCreate() |
| { |
| int err = 0; |
| |
| LOG_FUNCTION_NAME |
| |
| camera_device = open(VIDEO_DEVICE, O_RDWR); |
| if (camera_device < 0) { |
| LOGE ("Could not open the camera device: %s", strerror(errno) ); |
| goto exit; |
| } |
| |
| LOG_FUNCTION_NAME_EXIT |
| return 0; |
| |
| exit: |
| return err; |
| } |
| |
| |
| int CameraHal::CameraDestroy(bool destroyOverlay) |
| { |
| int err, buffer_count; |
| |
| LOG_FUNCTION_NAME |
| |
| close(camera_device); |
| camera_device = -1; |
| |
| if ((mOverlay != NULL) && (destroyOverlay)) { |
| buffer_count = mOverlay->getBufferCount(); |
| |
| for ( int i = 0 ; i < buffer_count ; i++ ) |
| { |
| // need to free buffers and heaps mapped using overlay fd before it is destroyed |
| // otherwise we could create a resource leak |
| // a segfault could occur if we try to free pointers after overlay is destroyed |
| mPreviewBuffers[i].clear(); |
| mPreviewHeaps[i].clear(); |
| mVideoBuffer[i].clear(); |
| mVideoHeaps[i].clear(); |
| buffers_queued_to_dss[i] = 0; |
| } |
| mOverlay->destroy(); |
| mOverlay = NULL; |
| nOverlayBuffersQueued = 0; |
| |
| } |
| |
| LOG_FUNCTION_NAME_EXIT |
| return 0; |
| } |
| |
| int CameraHal::CameraConfigure() |
| { |
| int w, h, framerate; |
| int image_width, image_height; |
| int err; |
| struct v4l2_format format; |
| enum v4l2_buf_type type; |
| struct v4l2_control vc; |
| struct v4l2_streamparm parm; |
| |
| LOG_FUNCTION_NAME |
| |
| mParameters.getPreviewSize(&w, &h); |
| |
| /* Set preview format */ |
| format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
| format.fmt.pix.width = w; |
| format.fmt.pix.height = h; |
| format.fmt.pix.pixelformat = PIXEL_FORMAT; |
| |
| err = ioctl(camera_device, VIDIOC_S_FMT, &format); |
| if ( err < 0 ){ |
| LOGE ("Failed to set VIDIOC_S_FMT."); |
| goto s_fmt_fail; |
| } |
| |
| LOGI("CameraConfigure PreviewFormat: w=%d h=%d", format.fmt.pix.width, format.fmt.pix.height); |
| |
| framerate = mParameters.getPreviewFrameRate(); |
| |
| LOGD("CameraConfigure: framerate to set = %d",framerate); |
| |
| parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
| err = ioctl(camera_device, VIDIOC_G_PARM, &parm); |
| if(err != 0) { |
| LOGD("VIDIOC_G_PARM "); |
| return -1; |
| } |
| |
| LOGD("CameraConfigure: Old frame rate is %d/%d fps", |
| parm.parm.capture.timeperframe.denominator, |
| parm.parm.capture.timeperframe.numerator); |
| |
| parm.parm.capture.timeperframe.numerator = 1; |
| //Framerate 0 does not make sense in kernel context |
| if ( framerate!=0 ) parm.parm.capture.timeperframe.denominator = framerate; |
| else ( parm.parm.capture.timeperframe.denominator ) = 30; |
| err = ioctl(camera_device, VIDIOC_S_PARM, &parm); |
| if(err != 0) { |
| LOGE("VIDIOC_S_PARM "); |
| return -1; |
| } |
| |
| LOGI("CameraConfigure: New frame rate is %d/%d fps",parm.parm.capture.timeperframe.denominator,parm.parm.capture.timeperframe.numerator); |
| |
| LOG_FUNCTION_NAME_EXIT |
| return 0; |
| |
| s_fmt_fail: |
| return -1; |
| } |
| |
| int CameraHal::CameraStart() |
| { |
| int w, h; |
| int err; |
| int nSizeBytes; |
| int buffer_count; |
| struct v4l2_format format; |
| enum v4l2_buf_type type; |
| struct v4l2_requestbuffers creqbuf; |
| |
| LOG_FUNCTION_NAME |
| |
| nCameraBuffersQueued = 0; |
| |
| mParameters.getPreviewSize(&w, &h); |
| LOGD("**CaptureQBuffers: preview size=%dx%d", w, h); |
| |
| mPreviewFrameSize = w * h * 2; |
| if (mPreviewFrameSize & 0xfff) |
| { |
| mPreviewFrameSize = (mPreviewFrameSize & 0xfffff000) + 0x1000; |
| } |
| LOGD("mPreviewFrameSize = 0x%x = %d", mPreviewFrameSize, mPreviewFrameSize); |
| |
| buffer_count = mOverlay->getBufferCount(); |
| LOGD("number of buffers = %d\n", buffer_count); |
| |
| creqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
| creqbuf.memory = V4L2_MEMORY_USERPTR; |
| creqbuf.count = buffer_count ; |
| if (ioctl(camera_device, VIDIOC_REQBUFS, &creqbuf) < 0) { |
| LOGE ("VIDIOC_REQBUFS Failed. %s", strerror(errno)); |
| goto fail_reqbufs; |
| } |
| |
| for (int i = 0; i < (int)creqbuf.count; i++) { |
| |
| v4l2_cam_buffer[i].type = creqbuf.type; |
| v4l2_cam_buffer[i].memory = creqbuf.memory; |
| v4l2_cam_buffer[i].index = i; |
| |
| if (ioctl(camera_device, VIDIOC_QUERYBUF, &v4l2_cam_buffer[i]) < 0) { |
| LOGE("VIDIOC_QUERYBUF Failed"); |
| goto fail_loop; |
| } |
| |
| mapping_data_t* data = (mapping_data_t*) mOverlay->getBufferAddress((void*)i); |
| if ( data == NULL ) { |
| LOGE(" getBufferAddress returned NULL"); |
| goto fail_loop; |
| } |
| |
| v4l2_cam_buffer[i].m.userptr = (unsigned long) data->ptr; |
| v4l2_cam_buffer[i].length = data->length; |
| |
| strcpy((char *)v4l2_cam_buffer[i].m.userptr, "hello"); |
| if (strcmp((char *)v4l2_cam_buffer[i].m.userptr, "hello")) { |
| LOGI("problem with buffer\n"); |
| goto fail_loop; |
| } |
| |
| LOGD("User Buffer [%d].start = %p length = %d\n", i, |
| (void*)v4l2_cam_buffer[i].m.userptr, v4l2_cam_buffer[i].length); |
| |
| if (buffers_queued_to_dss[i] == 0) |
| { |
| if (ioctl(camera_device, VIDIOC_QBUF, &v4l2_cam_buffer[i]) < 0) { |
| LOGE("CameraStart VIDIOC_QBUF Failed: %s", strerror(errno) ); |
| goto fail_loop; |
| }else{ |
| nCameraBuffersQueued++; |
| } |
| } |
| else LOGI("CameraStart::Could not queue buffer %d to Camera because it is being held by Overlay", i); |
| |
| // ensure we release any stale ref's to sp |
| mPreviewBuffers[i].clear(); |
| mPreviewHeaps[i].clear(); |
| |
| mPreviewHeaps[i] = new MemoryHeapBase(data->fd,mPreviewFrameSize, 0, data->offset); |
| mPreviewBuffers[i] = new MemoryBase(mPreviewHeaps[i], 0, mPreviewFrameSize); |
| |
| } |
| |
| type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
| err = ioctl(camera_device, VIDIOC_STREAMON, &type); |
| if ( err < 0) { |
| LOGE("VIDIOC_STREAMON Failed"); |
| goto fail_loop; |
| } |
| |
| if( ioctl(camera_device, VIDIOC_G_CROP, &mInitialCrop) < 0 ){ |
| LOGE("[%s]: ERROR VIDIOC_G_CROP failed", strerror(errno)); |
| return -1; |
| } |
| |
| LOGE("Initial Crop: crop_top = %d, crop_left = %d, crop_width = %d, crop_height = %d", mInitialCrop.c.top, mInitialCrop.c.left, mInitialCrop.c.width, mInitialCrop.c.height); |
| |
| if ( mZoomTargetIdx != mZoomCurrentIdx ) { |
| |
| if( ZoomPerform(zoom_step[mZoomTargetIdx]) < 0 ) |
| LOGE("Error while applying zoom"); |
| |
| mZoomCurrentIdx = mZoomTargetIdx; |
| mParameters.set("zoom", (int) mZoomCurrentIdx); |
| mNotifyCb(CAMERA_MSG_ZOOM, (int) mZoomCurrentIdx, 1, mCallbackCookie); |
| } |
| |
| LOG_FUNCTION_NAME_EXIT |
| |
| return 0; |
| |
| fail_bufalloc: |
| fail_loop: |
| fail_reqbufs: |
| |
| return -1; |
| } |
| |
| int CameraHal::CameraStop() |
| { |
| |
| #ifdef DEBUG_LOG |
| |
| LOG_FUNCTION_NAME |
| |
| #endif |
| |
| int ret; |
| struct v4l2_requestbuffers creqbuf; |
| struct v4l2_buffer cfilledbuffer; |
| cfilledbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
| cfilledbuffer.memory = V4L2_MEMORY_USERPTR; |
| |
| while(nCameraBuffersQueued){ |
| nCameraBuffersQueued--; |
| } |
| |
| #ifdef DEBUG_LOG |
| |
| LOGD("Done dequeuing from Camera!"); |
| |
| #endif |
| |
| creqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
| if (ioctl(camera_device, VIDIOC_STREAMOFF, &creqbuf.type) == -1) { |
| LOGE("VIDIOC_STREAMOFF Failed"); |
| goto fail_streamoff; |
| } |
| |
| //Force the zoom to be updated next time preview is started. |
| mZoomCurrentIdx = 0; |
| |
| #ifdef DEBUG_LOG |
| |
| LOG_FUNCTION_NAME_EXIT |
| |
| #endif |
| |
| return 0; |
| |
| fail_streamoff: |
| |
| return -1; |
| } |
| |
| static void debugShowFPS() |
| { |
| static int mFrameCount = 0; |
| static int mLastFrameCount = 0; |
| static nsecs_t mLastFpsTime = 0; |
| static float mFps = 0; |
| mFrameCount++; |
| if (!(mFrameCount & 0x1F)) { |
| nsecs_t now = systemTime(); |
| nsecs_t diff = now - mLastFpsTime; |
| mFps = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff; |
| mLastFpsTime = now; |
| mLastFrameCount = mFrameCount; |
| LOGD("####### [%d] Frames, %f FPS", mFrameCount, mFps); |
| } |
| } |
| |
| void CameraHal::queueToOverlay(int index) |
| { |
| int nBuffers_queued_to_dss = mOverlay->queueBuffer((void*)index); |
| if (nBuffers_queued_to_dss < 0) |
| { |
| if (ioctl(camera_device, VIDIOC_QBUF, &v4l2_cam_buffer[index]) < 0) { |
| LOGE("VIDIOC_QBUF Failed, line=%d",__LINE__); |
| } |
| else nCameraBuffersQueued++; |
| } |
| else |
| { |
| nOverlayBuffersQueued++; |
| buffers_queued_to_dss[index] = 1; //queued |
| if (nBuffers_queued_to_dss != nOverlayBuffersQueued) |
| { |
| LOGD("nBuffers_queued_to_dss = %d, nOverlayBuffersQueued = %d", nBuffers_queued_to_dss, nOverlayBuffersQueued); |
| LOGD("buffers in DSS \n %d %d %d %d %d %d", buffers_queued_to_dss[0], buffers_queued_to_dss[1], |
| buffers_queued_to_dss[2], buffers_queued_to_dss[3], buffers_queued_to_dss[4], buffers_queued_to_dss[5]); |
| //Queue all the buffers that were discarded by DSS upon STREAM OFF, back to camera. |
| for(int k = 0; k < MAX_CAMERA_BUFFERS; k++) |
| { |
| if ((buffers_queued_to_dss[k] == 1) && (k != index)) |
| { |
| buffers_queued_to_dss[k] = 0; |
| nOverlayBuffersQueued--; |
| if (ioctl(camera_device, VIDIOC_QBUF, &v4l2_cam_buffer[k]) < 0) { |
| LOGE("VIDIOC_QBUF Failed, line=%d. Buffer lost forever.",__LINE__); |
| }else{ |
| nCameraBuffersQueued++; |
| LOGD("Reclaiming buffer [%d] from Overlay", k); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| int CameraHal::dequeueFromOverlay() |
| { |
| overlay_buffer_t overlaybuffer;// contains the index of the buffer dque |
| |
| int dequeue_from_dss_failed = mOverlay->dequeueBuffer(&overlaybuffer); |
| if(!dequeue_from_dss_failed){ |
| nOverlayBuffersQueued--; |
| buffers_queued_to_dss[(int)overlaybuffer] = 0; |
| lastOverlayBufferDQ = (int)overlaybuffer; |
| return (int)overlaybuffer; |
| } |
| return -1; |
| } |
| |
| void CameraHal::nextPreview() |
| { |
| struct v4l2_buffer cfilledbuffer; |
| cfilledbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
| cfilledbuffer.memory = V4L2_MEMORY_USERPTR; |
| int w, h, ret; |
| static int frame_count = 0; |
| int zoom_inc, err; |
| struct timeval lowLightTime; |
| int overlaybufferindex = -1; //contains the last buffer dque or -1 if dque failed |
| |
| mParameters.getPreviewSize(&w, &h); |
| |
| //Zoom |
| frame_count++; |
| if( mZoomCurrentIdx != mZoomTargetIdx){ |
| |
| if( mZoomCurrentIdx < mZoomTargetIdx) |
| zoom_inc = 1; |
| else |
| zoom_inc = -1; |
| |
| if ( mZoomSpeed > 0 ){ |
| if( (frame_count % mZoomSpeed) == 0){ |
| mZoomCurrentIdx += zoom_inc; |
| } |
| } else { |
| mZoomCurrentIdx = mZoomTargetIdx; |
| } |
| |
| ZoomPerform(zoom_step[mZoomCurrentIdx]); |
| mParameters.set("zoom", mZoomCurrentIdx); |
| |
| // Immediate zoom should not generate callbacks. |
| if ( mSmoothZoomStatus == SMOOTH_START || mSmoothZoomStatus == SMOOTH_NOTIFY_AND_STOP) { |
| if(mSmoothZoomStatus == SMOOTH_NOTIFY_AND_STOP) |
| { |
| mZoomTargetIdx = mZoomCurrentIdx; |
| mSmoothZoomStatus = SMOOTH_STOP; |
| } |
| if( mZoomCurrentIdx == mZoomTargetIdx ) |
| mNotifyCb(CAMERA_MSG_ZOOM, mZoomCurrentIdx, 1, mCallbackCookie); |
| else |
| mNotifyCb(CAMERA_MSG_ZOOM, mZoomCurrentIdx, 0, mCallbackCookie); |
| } |
| } |
| |
| #ifdef FW3A |
| if (isStart_FW3A != 0){ |
| //Low light notification |
| if( ( fobj->settings.ae.framerate == 0 ) && ( ( frame_count % 10) == 0 ) ) { |
| #if ( PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS ) && DEBUG_LOG |
| |
| gettimeofday(&lowLightTime, NULL); |
| |
| #endif |
| err = ICam_ReadStatus(fobj->hnd, &fobj->status); |
| if (err == 0) { |
| if (fobj->status.ae.camera_shake == ICAM_SHAKE_HIGH_RISK2) { |
| mParameters.set("low-light", "1"); |
| } else { |
| mParameters.set("low-light", "0"); |
| } |
| } |
| |
| #if ( PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS ) && DEBUG_LOG |
| |
| PPM("Low-light delay", &lowLightTime); |
| |
| #endif |
| |
| } |
| } |
| #endif |
| |
| if (ioctl(camera_device, VIDIOC_DQBUF, &cfilledbuffer) < 0) { |
| LOGE("VIDIOC_DQBUF Failed!!!"); |
| goto EXIT; |
| }else{ |
| nCameraBuffersQueued--; |
| } |
| mCurrentTime[cfilledbuffer.index] = s2ns(cfilledbuffer.timestamp.tv_sec) + us2ns(cfilledbuffer.timestamp.tv_usec); |
| |
| //SaveFile(NULL, (char*)"yuv", (void *)cfilledbuffer.m.userptr, mPreviewFrameSize); |
| |
| if( msgTypeEnabled(CAMERA_MSG_PREVIEW_FRAME) ) |
| mDataCb(CAMERA_MSG_PREVIEW_FRAME, mPreviewBuffers[cfilledbuffer.index], mCallbackCookie); |
| |
| queueToOverlay(cfilledbuffer.index); |
| overlaybufferindex = dequeueFromOverlay(); |
| |
| mRecordingLock.lock(); |
| |
| if(mRecordEnabled) |
| { |
| if(overlaybufferindex != -1) // dequeued a valid buffer from overlay |
| { |
| if (nCameraBuffersQueued == 0) |
| { |
| /* Drop the frame. Camera is starving. */ |
| if (ioctl(camera_device, VIDIOC_QBUF, &v4l2_cam_buffer[overlaybufferindex]) < 0) { |
| LOGE("VIDIOC_QBUF Failed, line=%d",__LINE__); |
| } |
| else nCameraBuffersQueued++; |
| LOGD("Didnt queue this buffer to VE."); |
| if (mPrevTime < mCurrentTime[overlaybufferindex]) |
| mPrevTime = mCurrentTime[overlaybufferindex]; |
| else |
| mPrevTime += frameInterval; |
| } |
| else |
| { |
| buffers_queued_to_ve[overlaybufferindex] = 1; |
| if (mPrevTime > mCurrentTime[overlaybufferindex]) |
| { |
| //LOGW("Had to adjust the timestamp. Clock went back in time. mCurrentTime = %lld, mPrevTime = %llu", mCurrentTime[overlaybufferindex], mPrevTime); |
| mCurrentTime[overlaybufferindex] = mPrevTime + frameInterval; |
| } |
| #ifdef OMAP_ENHANCEMENT |
| mDataCbTimestamp(mCurrentTime[overlaybufferindex], CAMERA_MSG_VIDEO_FRAME, mVideoBuffer[overlaybufferindex], mCallbackCookie, 0, 0); |
| #else |
| mDataCbTimestamp(mCurrentTime[overlaybufferindex], CAMERA_MSG_VIDEO_FRAME, mVideoBuffer[overlaybufferindex], mCallbackCookie); |
| #endif |
| mPrevTime = mCurrentTime[overlaybufferindex]; |
| } |
| } |
| } |
| else |
| { |
| if (overlaybufferindex != -1) { // dequeued a valid buffer from overlay |
| if (ioctl(camera_device, VIDIOC_QBUF, &v4l2_cam_buffer[overlaybufferindex]) < 0) { |
| LOGE("VIDIOC_QBUF Failed. line=%d",__LINE__); |
| }else{ |
| nCameraBuffersQueued++; |
| } |
| } |
| } |
| |
| mRecordingLock.unlock(); |
| |
| |
| if (UNLIKELY(mDebugFps)) { |
| debugShowFPS(); |
| } |
| |
| EXIT: |
| |
| return ; |
| } |
| |
| #ifdef ICAP |
| |
| int CameraHal::ICapturePerform() |
| { |
| |
| int err; |
| int status = 0; |
| int jpegSize; |
| uint32_t fixedZoom; |
| void *outBuffer; |
| unsigned long base, offset, jpeg_offset; |
| unsigned int preview_width, preview_height; |
| icap_buffer_t snapshotBuffer; |
| unsigned int image_width, image_height, thumb_width, thumb_height; |
| SICap_ManualParameters manual_config; |
| SICam_Settings config; |
| icap_tuning_params_t cap_tuning; |
| icap_resolution_cap_t spec_res; |
| icap_buffer_t capture_buffer; |
| icap_process_mode_e mode; |
| unsigned int procMessage[PROC_THREAD_NUM_ARGS], |
| shutterMessage[SHUTTER_THREAD_NUM_ARGS], |
| rawMessage[RAW_THREAD_NUM_ARGS]; |
| int pixelFormat; |
| exif_buffer *exif_buf; |
| mode = ICAP_PROCESS_MODE_CONTINUOUS; |
| |
| #ifdef DEBUG_LOG |
| |
| LOG_FUNCTION_NAME |
| |
| PPM("START OF ICapturePerform"); |
| |
| #endif |
| |
| mParameters.getPictureSize((int *) &image_width, (int *) &image_height); |
| mParameters.getPreviewSize((int *) &preview_width,(int *) &preview_height); |
| thumb_width = mParameters.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH); |
| thumb_height = mParameters.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT); |
| |
| #ifdef DEBUG_LOG |
| |
| LOGD("ICapturePerform image_width=%d image_height=%d",image_width,image_height); |
| |
| #endif |
| |
| memset(&manual_config, 0 ,sizeof(manual_config)); |
| memset(&iobj->cfg, 0, sizeof(icap_configure_t)); |
| |
| #ifdef DEBUG_LOG |
| |
| LOGD("MakerNote 0x%x, size %d", ( unsigned int ) fobj->mnote.buffer,fobj->mnote.filled_size); |
| |
| LOGD("shutter_cap = %d ; again_cap = %d ; awb_index = %d; %d %d %d %d\n", |
| (int)fobj->status.ae.shutter_cap, (int)fobj->status.ae.again_cap, |
| (int)fobj->status.awb.awb_index, (int)fobj->status.awb.gain_Gr, |
| (int)fobj->status.awb.gain_R, (int)fobj->status.awb.gain_B, |
| (int)fobj->status.awb.gain_Gb); |
| |
| #endif |
| |
| snapshotBuffer.buffer = NULL; |
| snapshotBuffer.alloc_size = 0; |
| LOGE("mBurstShots %d", mBurstShots); |
| if ( 1 >= mBurstShots ) { |
| if ( mcapture_mode == 1 ) { |
| spec_res.capture_mode = ICAP_CAPTURE_MODE_HP; |
| iobj->cfg.capture_mode = ICAP_CAPTURE_MODE_HP; |
| iobj->cfg.notify.cb_capture = onSnapshot; |
| iobj->cfg.notify.cb_snapshot_crop = onCrop; |
| fixedZoom = (uint32_t) (zoom_step[0]*ZOOM_SCALE); |
| |
| iobj->cfg.zoom.enable = ICAP_ENABLE; |
| iobj->cfg.zoom.vertical = fixedZoom; |
| iobj->cfg.zoom.horizontal = fixedZoom; |
| } else { |
| snapshotBuffer.buffer = getLastOverlayAddress(); |
| snapshotBuffer.alloc_size = getLastOverlayLength(); |
| spec_res.capture_mode = ICAP_CAPTURE_MODE_HQ; |
| iobj->cfg.capture_mode = ICAP_CAPTURE_MODE_HQ; |
| iobj->cfg.notify.cb_snapshot = onGeneratedSnapshot; |
| iobj->cfg.snapshot_width = preview_width; |
| iobj->cfg.snapshot_height = preview_height; |
| fixedZoom = (uint32_t) (zoom_step[mZoomTargetIdx]*ZOOM_SCALE); |
| |
| iobj->cfg.zoom.enable = ICAP_ENABLE; |
| iobj->cfg.zoom.vertical = fixedZoom; |
| iobj->cfg.zoom.horizontal = fixedZoom; |
| } |
| iobj->cfg.notify.cb_mknote = onMakernote; |
| iobj->cfg.notify.cb_ipp = onIPP; |
| } else { |
| spec_res.capture_mode = ICAP_CAPTURE_MODE_HP; |
| iobj->cfg.capture_mode = ICAP_CAPTURE_MODE_HP; |
| iobj->cfg.notify.cb_capture = onSnapshot; |
| iobj->cfg.notify.cb_snapshot_crop = onCrop; |
| fixedZoom = (uint32_t) (zoom_step[0]*ZOOM_SCALE); |
| |
| iobj->cfg.zoom.enable = ICAP_ENABLE; |
| iobj->cfg.zoom.vertical = fixedZoom; |
| iobj->cfg.zoom.horizontal = fixedZoom; |
| } |
| iobj->cfg.notify.cb_shutter = onShutter; |
| spec_res.res.width = image_width; |
| spec_res.res.height = image_height; |
| spec_res.capture_format = ICAP_CAPTURE_FORMAT_UYVY; |
| |
| status = icap_query_resolution(iobj->lib_private, 0, &spec_res); |
| |
| if( ICAP_STATUS_FAIL == status){ |
| LOGE ("First icapture query resolution failed"); |
| |
| int tmp_width, tmp_height; |
| tmp_width = image_width; |
| tmp_height = image_height; |
| status = icap_query_enumerate(iobj->lib_private, 0, &spec_res); |
| if ( ICAP_STATUS_FAIL == status ) { |
| LOGE("icapture enumerate failed"); |
| goto fail_config; |
| } |
| |
| if ( image_width < spec_res.res_range.width_min ) |
| tmp_width = spec_res.res_range.width_min; |
| |
| if ( image_height < spec_res.res_range.height_min ) |
| tmp_height = spec_res.res_range.height_min; |
| |
| if ( image_width > spec_res.res_range.width_max ) |
| tmp_width = spec_res.res_range.width_max; |
| |
| if ( image_height > spec_res.res_range.height_max ) |
| tmp_height = spec_res.res_range.height_max; |
| |
| spec_res.res.width = tmp_width; |
| spec_res.res.height = tmp_height; |
| status = icap_query_resolution(iobj->lib_private, 0, &spec_res); |
| if ( ICAP_STATUS_FAIL == status ) { |
| LOGE("icapture query failed again, giving up"); |
| goto fail_config; |
| } |
| } |
| |
| iobj->cfg.notify.priv = this; |
| |
| iobj->cfg.crop.enable = ICAP_ENABLE; |
| iobj->cfg.crop.top = fobj->status.preview.top; |
| iobj->cfg.crop.left = fobj->status.preview.left; |
| iobj->cfg.crop.width = fobj->status.preview.width; |
| iobj->cfg.crop.height = fobj->status.preview.height; |
| |
| iobj->cfg.capture_format = ICAP_CAPTURE_FORMAT_UYVY; |
| iobj->cfg.width = spec_res.res.width; |
| iobj->cfg.height = spec_res.res.height; |
| mImageCropTop = 0; |
| mImageCropLeft = 0; |
| mImageCropWidth = spec_res.res.width; |
| mImageCropHeight = spec_res.res.height; |
| |
| iobj->cfg.notify.cb_h3a = NULL; //onSaveH3A; |
| iobj->cfg.notify.cb_lsc = NULL; //onSaveLSC; |
| iobj->cfg.notify.cb_raw = NULL; //onSaveRAW; |
| |
| #if DEBUG_LOG |
| |
| PPM("Before ICapture Config"); |
| |
| #endif |
| |
| LOGE("Zoom set to %d", fixedZoom); |
| |
| status = icap_config_common(iobj->lib_private, &iobj->cfg); |
| |
| if( ICAP_STATUS_FAIL == status){ |
| LOGE ("ICapture Config function failed"); |
| goto fail_config; |
| } |
| |
| #if DEBUG_LOG |
| |
| PPM("ICapture config OK"); |
| |
| LOGD("iobj->cfg.image_width = %d = 0x%x iobj->cfg.image_height=%d = 0x%x , iobj->cfg.sizeof_img_buf = %d", (int)iobj->cfg.width, (int)iobj->cfg.width, (int)iobj->cfg.height, (int)iobj->cfg.height, (int) spec_res.buffer_size); |
| |
| #endif |
| |
| cap_tuning.icam_makernote = ( void * ) &fobj->mnote; |
| cap_tuning.icam_settings = ( void * ) &fobj->settings; |
| cap_tuning.icam_status = ( void * ) &fobj->status; |
| |
| #ifdef DEBUG_LOG |
| |
| PPM("SETUP SOME 3A STUFF"); |
| |
| #endif |
| |
| status = icap_config_tuning(iobj->lib_private, &cap_tuning); |
| if( ICAP_STATUS_FAIL == status){ |
| LOGE ("ICapture tuning function failed"); |
| goto fail_config; |
| } |
| |
| allocatePictureBuffer(spec_res.buffer_size, mBurstShots); |
| |
| for ( int i = 0; i < mBurstShots; i++ ) { |
| capture_buffer.buffer = mYuvBuffer[i]; |
| capture_buffer.alloc_size = spec_res.buffer_size; |
| |
| LOGE ("ICapture push buffer 0x%x, len %d", ( unsigned int ) mYuvBuffer[i], spec_res.buffer_size); |
| status = icap_push_buffer(iobj->lib_private, &capture_buffer, &snapshotBuffer); |
| if( ICAP_STATUS_FAIL == status){ |
| LOGE ("ICapture push buffer function failed"); |
| goto fail_config; |
| } |
| |
| } |
| |
| for ( int i = 0; i < mBurstShots; i++ ) { |
| |
| #if DEBUG_LOG |
| |
| PPM("BEFORE ICapture Process"); |
| |
| #endif |
| |
| status = icap_process(iobj->lib_private, mode, NULL); |
| |
| if( ICAP_STATUS_FAIL == status ) { |
| LOGE("ICapture Process failed"); |
| goto fail_process; |
| } |
| |
| #if DEBUG_LOG |
| |
| else { |
| PPM("ICapture process OK"); |
| } |
| |
| LOGD("iobj->proc.out_img_w = %d = 0x%x iobj->proc.out_img_h=%u = 0x%x", (int) iobj->cfg.width,(int) iobj->cfg.width, (int) iobj->cfg.height,(int)iobj->cfg.height); |
| |
| #endif |
| |
| pixelFormat = PIX_YUV422I; |
| |
| //block until snapshot is ready |
| fd_set descriptorSet; |
| int max_fd; |
| unsigned int snapshotReadyMessage; |
| |
| max_fd = snapshotReadyPipe[0] + 1; |
| |
| FD_ZERO(&descriptorSet); |
| FD_SET(snapshotReadyPipe[0], &descriptorSet); |
| |
| #ifdef DEBUG_LOG |
| |
| LOGD("Waiting on SnapshotThread ready message"); |
| |
| #endif |
| |
| err = select(max_fd, &descriptorSet, NULL, NULL, NULL); |
| if (err < 1) { |
| LOGE("Error in select"); |
| } |
| |
| if(FD_ISSET(snapshotReadyPipe[0], &descriptorSet)) |
| read(snapshotReadyPipe[0], &snapshotReadyMessage, sizeof(snapshotReadyMessage)); |
| |
| } |
| |
| for ( int i = 0; i < mBurstShots; i++ ) { |
| |
| #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS |
| |
| PPM("SENDING MESSAGE TO PROCESSING THREAD"); |
| |
| #endif |
| |
| mExifParams.exposure = fobj->status.ae.shutter_cap; |
| mExifParams.zoom = zoom_step[mZoomTargetIdx]; |
| exif_buf = get_exif_buffer(&mExifParams, gpsLocation); |
| |
| if( NULL != gpsLocation ) { |
| free(gpsLocation); |
| gpsLocation = NULL; |
| } |
| |
| procMessage[0] = PROC_THREAD_PROCESS; |
| procMessage[1] = iobj->cfg.width; |
| procMessage[2] = iobj->cfg.height; |
| procMessage[3] = image_width; |
| procMessage[4] = image_height; |
| procMessage[5] = pixelFormat; |
| |
| #ifdef IMAGE_PROCESSING_PIPELINE |
| |
| procMessage[6] = mIPPParams.EdgeEnhancementStrength; |
| procMessage[7] = mIPPParams.WeakEdgeThreshold; |
| procMessage[8] = mIPPParams.StrongEdgeThreshold; |
| procMessage[9] = mIPPParams.LowFreqLumaNoiseFilterStrength; |
| procMessage[10] = mIPPParams.MidFreqLumaNoiseFilterStrength; |
| procMessage[11] = mIPPParams.HighFreqLumaNoiseFilterStrength; |
| procMessage[12] = mIPPParams.LowFreqCbNoiseFilterStrength; |
| procMessage[13] = mIPPParams.MidFreqCbNoiseFilterStrength; |
| procMessage[14] = mIPPParams.HighFreqCbNoiseFilterStrength; |
| procMessage[15] = mIPPParams.LowFreqCrNoiseFilterStrength; |
| procMessage[16] = mIPPParams.MidFreqCrNoiseFilterStrength; |
| procMessage[17] = mIPPParams.HighFreqCrNoiseFilterStrength; |
| procMessage[18] = mIPPParams.shadingVertParam1; |
| procMessage[19] = mIPPParams.shadingVertParam2; |
| procMessage[20] = mIPPParams.shadingHorzParam1; |
| procMessage[21] = mIPPParams.shadingHorzParam2; |
| procMessage[22] = mIPPParams.shadingGainScale; |
| procMessage[23] = mIPPParams.shadingGainOffset; |
| procMessage[24] = mIPPParams.shadingGainMaxValue; |
| procMessage[25] = mIPPParams.ratioDownsampleCbCr; |
| |
| #endif |
| |
| procMessage[26] = (unsigned int) mYuvBuffer[i]; |
| procMessage[27] = mPictureOffset[i]; |
| procMessage[28] = mPictureLength[i]; |
| procMessage[29] = rotation; |
| |
| if ( mcapture_mode == 1 ) { |
| procMessage[30] = mZoomTargetIdx; |
| } else { |
| procMessage[30] = 0; |
| } |
| |
| procMessage[31] = mippMode; |
| procMessage[32] = mIPPToEnable; |
| procMessage[33] = quality; |
| procMessage[34] = (unsigned int) mDataCb; |
| procMessage[35] = 0; |
| procMessage[36] = (unsigned int) mCallbackCookie; |
| procMessage[37] = 0; |
| procMessage[38] = 0; |
| procMessage[39] = iobj->cfg.width; |
| procMessage[40] = iobj->cfg.height; |
| procMessage[41] = thumb_width; |
| procMessage[42] = thumb_height; |
| |
| procMessage[43] = (unsigned int) exif_buf; |
| |
| write(procPipe[1], &procMessage, sizeof(procMessage)); |
| |
| mIPPToEnable = false; // reset ipp enable after sending to proc thread |
| |
| #ifdef DEBUG_LOG |
| |
| LOGD("\n\n\n PICTURE NUMBER =%d\n\n\n",++pictureNumber); |
| |
| PPM("IMAGE CAPTURED"); |
| |
| #endif |
| |
| if( msgTypeEnabled(CAMERA_MSG_RAW_IMAGE) ) { |
| |
| #ifdef DEBUG_LOG |
| |
| PPM("SENDING MESSAGE TO RAW THREAD"); |
| |
| #endif |
| |
| rawMessage[0] = RAW_THREAD_CALL; |
| rawMessage[1] = (unsigned int) mDataCb; |
| rawMessage[2] = (unsigned int) mCallbackCookie; |
| rawMessage[3] = (unsigned int) NULL; |
| write(rawPipe[1], &rawMessage, sizeof(rawMessage)); |
| } |
| } |
| #ifdef DEBUG_LOG |
| |
| LOG_FUNCTION_NAME_EXIT |
| |
| #endif |
| |
| return 0; |
| |
| fail_config : |
| fail_process: |
| |
| return -1; |
| } |
| |
| #else |
| |
| //TODO: Update the normal in according the PPM Changes |
| int CameraHal::ICapturePerform(){ |
| |
| int image_width, image_height; |
| int image_rotation; |
| double image_zoom; |
| int preview_width, preview_height; |
| unsigned long base, offset; |
| struct v4l2_buffer buffer; |
| struct v4l2_format format; |
| struct v4l2_buffer cfilledbuffer; |
| struct v4l2_requestbuffers creqbuf; |
| sp<MemoryBase> mPictureBuffer; |
| sp<MemoryBase> memBase; |
| int jpegSize; |
| void * outBuffer; |
| sp<MemoryHeapBase> mJPEGPictureHeap; |
| sp<MemoryBase> mJPEGPictureMemBase; |
| unsigned int vppMessage[3]; |
| int err, i; |
| int snapshot_buffer_index; |
| void* snapshot_buffer; |
| int ipp_reconfigure=0; |
| int ippTempConfigMode; |
| int jpegFormat = PIX_YUV422I; |
| v4l2_streamparm parm; |
| |
| LOG_FUNCTION_NAME |
| |
| LOGD("\n\n\n PICTURE NUMBER =%d\n\n\n",++pictureNumber); |
| |
| if( ( msgTypeEnabled(CAMERA_MSG_SHUTTER) ) && mShutterEnable) |
| mNotifyCb(CAMERA_MSG_SHUTTER, 0, 0, mCallbackCookie); |
| |
| mParameters.getPictureSize(&image_width, &image_height); |
| mParameters.getPreviewSize(&preview_width, &preview_height); |
| |
| LOGD("Picture Size: Width = %d \tHeight = %d", image_width, image_height); |
| |
| image_rotation = rotation; |
| image_zoom = zoom_step[mZoomTargetIdx]; |
| |
| format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
| format.fmt.pix.width = image_width; |
| format.fmt.pix.height = image_height; |
| format.fmt.pix.pixelformat = PIXEL_FORMAT; |
| |
| /* set size & format of the video image */ |
| if (ioctl(camera_device, VIDIOC_S_FMT, &format) < 0){ |
| LOGE ("Failed to set VIDIOC_S_FMT."); |
| return -1; |
| } |
| |
| //Set 10 fps for 8MP case |
| if( ( image_height == CAPTURE_8MP_HEIGHT ) && ( image_width == CAPTURE_8MP_WIDTH ) ) { |
| LOGE("8MP Capture setting framerate to 10"); |
| parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
| err = ioctl(camera_device, VIDIOC_G_PARM, &parm); |
| if(err != 0) { |
| LOGD("VIDIOC_G_PARM "); |
| return -1; |
| } |
| |
| parm.parm.capture.timeperframe.numerator = 1; |
| parm.parm.capture.timeperframe.denominator = 10; |
| err = ioctl(camera_device, VIDIOC_S_PARM, &parm); |
| if(err != 0) { |
| LOGE("VIDIOC_S_PARM "); |
| return -1; |
| } |
| } |
| |
| /* Check if the camera driver can accept 1 buffer */ |
| creqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
| creqbuf.memory = V4L2_MEMORY_USERPTR; |
| creqbuf.count = 1; |
| if (ioctl(camera_device, VIDIOC_REQBUFS, &creqbuf) < 0){ |
| LOGE ("VIDIOC_REQBUFS Failed. errno = %d", errno); |
| return -1; |
| } |
| |
| yuv_len = image_width * image_height * 2; |
| if (yuv_len & 0xfff) |
| { |
| yuv_len = (yuv_len & 0xfffff000) + 0x1000; |
| } |
| LOGD("pictureFrameSize = 0x%x = %d", yuv_len, yuv_len); |
| #define ALIGMENT 1 |
| #if ALIGMENT |
| mPictureHeap = new MemoryHeapBase(yuv_len); |
| #else |
| // Make a new mmap'ed heap that can be shared across processes. |
| mPictureHeap = new MemoryHeapBase(yuv_len + 0x20 + 256); |
| #endif |
| |
| base = (unsigned long)mPictureHeap->getBase(); |
| |
| #if ALIGMENT |
| base = (base + 0xfff) & 0xfffff000; |
| #else |
| /*Align buffer to 32 byte boundary */ |
| while ((base & 0x1f) != 0) |
| { |
| base++; |
| } |
| /* Buffer pointer shifted to avoid DSP cache issues */ |
| base += 128; |
| #endif |
| |
| offset = base - (unsigned long)mPictureHeap->getBase(); |
| |
| buffer.type = creqbuf.type; |
| buffer.memory = creqbuf.memory; |
| buffer.index = 0; |
| |
| if (ioctl(camera_device, VIDIOC_QUERYBUF, &buffer) < 0) { |
| LOGE("VIDIOC_QUERYBUF Failed"); |
| return -1; |
| } |
| |
| yuv_len = buffer.length; |
| |
| buffer.m.userptr = base; |
| mPictureBuffer = new MemoryBase(mPictureHeap, offset, yuv_len); |
| LOGD("Picture Buffer: Base = %p Offset = 0x%x", (void *)base, (unsigned int)offset); |
| |
| if (ioctl(camera_device, VIDIOC_QBUF, &buffer) < 0) { |
| LOGE("CAMERA VIDIOC_QBUF Failed"); |
| return -1; |
| } |
| |
| /* turn on streaming */ |
| creqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
| if (ioctl(camera_device, VIDIOC_STREAMON, &creqbuf.type) < 0) { |
| LOGE("VIDIOC_STREAMON Failed"); |
| return -1; |
| } |
| |
| LOGD("De-queue the next avaliable buffer"); |
| |
| /* De-queue the next avaliable buffer */ |
| cfilledbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
| |
| #if ALIGMENT |
| cfilledbuffer.memory = creqbuf.memory; |
| #else |
| cfilledbuffer.memory = V4L2_MEMORY_USERPTR; |
| #endif |
| while (ioctl(camera_device, VIDIOC_DQBUF, &cfilledbuffer) < 0) { |
| LOGE("VIDIOC_DQBUF Failed"); |
| } |
| |
| PPM("AFTER CAPTURE YUV IMAGE"); |
| |
| /* turn off streaming */ |
| creqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
| if (ioctl(camera_device, VIDIOC_STREAMOFF, &creqbuf.type) < 0) { |
| LOGE("VIDIOC_STREAMON Failed"); |
| return -1; |
| } |
| |
| if( msgTypeEnabled(CAMERA_MSG_RAW_IMAGE) ){ |
| mDataCb(CAMERA_MSG_RAW_IMAGE, mPictureBuffer,mCallbackCookie); |
| } |
| |
| yuv_buffer = (uint8_t*)buffer.m.userptr; |
| LOGD("PictureThread: generated a picture, yuv_buffer=%p yuv_len=%d",yuv_buffer,yuv_len); |
| |
| #ifdef HARDWARE_OMX |
| #if VPP |
| #if VPP_THREAD |
| |
| LOGD("SENDING MESSAGE TO VPP THREAD \n"); |
| vpp_buffer = yuv_buffer; |
| vppMessage[0] = VPP_THREAD_PROCESS; |
| vppMessage[1] = image_width; |
| vppMessage[2] = image_height; |
| |
| write(vppPipe[1],&vppMessage,sizeof(vppMessage)); |
| |
| #else |
| |
| mapping_data_t* data = (mapping_data_t*) mOverlay->getBufferAddress( (void*) (lastOverlayBufferDQ) ); |
| if ( data == NULL ) { |
| LOGE(" getBufferAddress returned NULL skipping snapshot"); |
| } else{ |
| snapshot_buffer = data->ptr; |
| |
| scale_init(image_width, image_height, preview_width, preview_height, PIX_YUV422I, PIX_YUV422I); |
| |
| err = scale_process(yuv_buffer, image_width, image_height, |
| snapshot_buffer, preview_width, preview_height, 0, PIX_YUV422I, zoom_step[/*mZoomTargetIdx*/ 0], 0, 0, image_width, image_height); |
| |
| #ifdef DEBUG_LOG |
| PPM("After vpp downscales:"); |
| if( err ) |
| LOGE("scale_process() failed"); |
| else |
| LOGD("scale_process() OK"); |
| #endif |
| |
| #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS |
| PPM("Shot to Snapshot", &ppm_receiveCmdToTakePicture); |
| #endif |
| scale_deinit(); |
| |
| queueToOverlay(lastOverlayBufferDQ); |
| dequeueFromOverlay(); |
| } |
| #endif |
| #endif |
| #endif |
| |
| #ifdef IMAGE_PROCESSING_PIPELINE |
| #if 1 |
| |
| if(mippMode ==-1 ){ |
| mippMode=IPP_EdgeEnhancement_Mode; |
| } |
| |
| #else |
| |
| if(mippMode ==-1){ |
| mippMode=IPP_CromaSupression_Mode; |
| } |
| if(mippMode == IPP_CromaSupression_Mode){ |
| mippMode=IPP_EdgeEnhancement_Mode; |
| } |
| else if(mippMode == IPP_EdgeEnhancement_Mode){ |
| mippMode=IPP_CromaSupression_Mode; |
| } |
| |
| #endif |
| |
| LOGD("IPPmode=%d",mippMode); |
| if(mippMode == IPP_CromaSupression_Mode){ |
| LOGD("IPP_CromaSupression_Mode"); |
| } |
| else if(mippMode == IPP_EdgeEnhancement_Mode){ |
| LOGD("IPP_EdgeEnhancement_Mode"); |
| } |
| else if(mippMode == IPP_Disabled_Mode){ |
| LOGD("IPP_Disabled_Mode"); |
| } |
| |
| if(mippMode){ |
| |
| if(mippMode != IPP_CromaSupression_Mode && mippMode != IPP_EdgeEnhancement_Mode){ |
| LOGE("ERROR ippMode unsupported"); |
| return -1; |
| } |
| PPM("Before init IPP"); |
| |
| if(mIPPToEnable) |
| { |
| err = InitIPP(image_width,image_height, jpegFormat, mippMode); |
| if( err ) { |
| LOGE("ERROR InitIPP() failed"); |
| return -1; |
| } |
| PPM("After IPP Init"); |
| mIPPToEnable = false; |
| } |
| |
| err = PopulateArgsIPP(image_width,image_height, jpegFormat, mippMode); |
| if( err ) { |
| LOGE("ERROR PopulateArgsIPP() failed"); |
| return -1; |
| } |
| PPM("BEFORE IPP Process Buffer"); |
| |
| LOGD("Calling ProcessBufferIPP(buffer=%p , len=0x%x)", yuv_buffer, yuv_len); |
| err = ProcessBufferIPP(yuv_buffer, yuv_len, |
| jpegFormat, |
| mippMode, |
| -1, // EdgeEnhancementStrength |
| -1, // WeakEdgeThreshold |
| -1, // StrongEdgeThreshold |
| -1, // LowFreqLumaNoiseFilterStrength |
| -1, // MidFreqLumaNoiseFilterStrength |
| -1, // HighFreqLumaNoiseFilterStrength |
| -1, // LowFreqCbNoiseFilterStrength |
| -1, // MidFreqCbNoiseFilterStrength |
| -1, // HighFreqCbNoiseFilterStrength |
| -1, // LowFreqCrNoiseFilterStrength |
| -1, // MidFreqCrNoiseFilterStrength |
| -1, // HighFreqCrNoiseFilterStrength |
| -1, // shadingVertParam1 |
| -1, // shadingVertParam2 |
| -1, // shadingHorzParam1 |
| -1, // shadingHorzParam2 |
| -1, // shadingGainScale |
| -1, // shadingGainOffset |
| -1, // shadingGainMaxValue |
| -1); // ratioDownsampleCbCr |
| if( err ) { |
| LOGE("ERROR ProcessBufferIPP() failed"); |
| return -1; |
| } |
| PPM("AFTER IPP Process Buffer"); |
| |
| if(!(pIPP.ippconfig.isINPLACE)){ |
| yuv_buffer = pIPP.pIppOutputBuffer; |
| } |
| |
| #if ( IPP_YUV422P || IPP_YUV420P_OUTPUT_YUV422I ) |
| jpegFormat = PIX_YUV422I; |
| LOGD("YUV422 !!!!"); |
| #else |
| yuv_len= ((image_width * image_height *3)/2); |
| jpegFormat = PIX_YUV420P; |
| LOGD("YUV420 !!!!"); |
| #endif |
| |
| } |
| //SaveFile(NULL, (char*)"yuv", yuv_buffer, yuv_len); |
| |
| #endif |
| |
| if ( msgTypeEnabled(CAMERA_MSG_COMPRESSED_IMAGE) ) |
| { |
| |
| #ifdef HARDWARE_OMX |
| #if JPEG |
| int jpegSize = (image_width * image_height) + 12288; |
| mJPEGPictureHeap = new MemoryHeapBase(jpegSize+ 256); |
| outBuffer = (void *)((unsigned long)(mJPEGPictureHeap->getBase()) + 128); |
| |
| exif_buffer *exif_buf = get_exif_buffer(&mExifParams, gpsLocation); |
| |
| PPM("BEFORE JPEG Encode Image"); |
| LOGE(" outbuffer = 0x%x, jpegSize = %d, yuv_buffer = 0x%x, yuv_len = %d, image_width = %d, image_height = %d, quality = %d, mippMode =%d", outBuffer , jpegSize, yuv_buffer, yuv_len, image_width, image_height, quality,mippMode); |
| jpegEncoder->encodeImage((uint8_t *)outBuffer , jpegSize, yuv_buffer, yuv_len, |
| image_width, image_height, quality, exif_buf, jpegFormat, DEFAULT_THUMB_WIDTH, DEFAULT_THUMB_HEIGHT, image_width, image_height, |
| image_rotation, image_zoom, 0, 0, image_width, image_height); |
| PPM("AFTER JPEG Encode Image"); |
| |
| mJPEGPictureMemBase = new MemoryBase(mJPEGPictureHeap, 128, jpegEncoder->jpegSize); |
| |
| if ( msgTypeEnabled(CAMERA_MSG_COMPRESSED_IMAGE) ){ |
| mDataCb(CAMERA_MSG_COMPRESSED_IMAGE,mJPEGPictureMemBase,mCallbackCookie); |
| } |
| |
| |
| PPM("Shot to Save", &ppm_receiveCmdToTakePicture); |
| if((exif_buf != NULL) && (exif_buf->data != NULL)) |
| exif_buf_free (exif_buf); |
| |
| if( NULL != gpsLocation ) { |
| free(gpsLocation); |
| gpsLocation = NULL; |
| } |
| mJPEGPictureMemBase.clear(); |
| mJPEGPictureHeap.clear(); |
| |
| #else |
| |
| if ( msgTypeEnabled(CAMERA_MSG_COMPRESSED_IMAGE) ) |
| mDataCb(CAMERA_MSG_COMPRESSED_IMAGE,NULL,mCallbackCookie); |
| |
| #endif |
| |
| #endif |
| |
| } |
| |
| // Release constraint to DSP OPP by setting lowest Hz |
| SetDSPHz(DSP3630_HZ_MIN); |
| |
| mPictureBuffer.clear(); |
| mPictureHeap.clear(); |
| |
| #ifdef HARDWARE_OMX |
| #if VPP_THREAD |
| LOGD("CameraHal thread before waiting increment in semaphore\n"); |
| sem_wait(&mIppVppSem); |
| LOGD("CameraHal thread after waiting increment in semaphore\n"); |
| #endif |
| #endif |
| |
| PPM("END OF ICapturePerform"); |
| LOG_FUNCTION_NAME_EXIT |
| |
| return NO_ERROR; |
| |
| } |
| |
| #endif |
| |
| void *CameraHal::getLastOverlayAddress() |
| { |
| void *res = NULL; |
| |
| mapping_data_t* data = (mapping_data_t*) mOverlay->getBufferAddress( (void*) (lastOverlayBufferDQ) ); |
| if ( data == NULL ) { |
| LOGE(" getBufferAddress returned NULL"); |
| } else { |
| res = data->ptr; |
| } |
| |
| LOG_FUNCTION_NAME_EXIT |
| |
| return res; |
| } |
| |
| size_t CameraHal::getLastOverlayLength() |
| { |
| size_t res = 0; |
| |
| mapping_data_t* data = (mapping_data_t*) mOverlay->getBufferAddress( (void*) (lastOverlayBufferDQ) ); |
| if ( data == NULL ) { |
| LOGE(" getBufferAddress returned NULL"); |
| } else { |
| res = data->length; |
| } |
| |
| LOG_FUNCTION_NAME_EXIT |
| |
| return res; |
| } |
| |
| void CameraHal::snapshotThread() |
| { |
| fd_set descriptorSet; |
| int max_fd; |
| int err, status; |
| unsigned int snapshotMessage[9], snapshotReadyMessage; |
| int image_width, image_height, pixelFormat, preview_width, preview_height; |
| int crop_top, crop_left, crop_width, crop_height; |
| void *yuv_buffer, *snapshot_buffer; |
| double ZoomTarget; |
| |
| LOG_FUNCTION_NAME |
| |
| pixelFormat = PIX_YUV422I; |
| max_fd = snapshotPipe[0] + 1; |
| |
| FD_ZERO(&descriptorSet); |
| FD_SET(snapshotPipe[0], &descriptorSet); |
| |
| while(1) { |
| err = select(max_fd, &descriptorSet, NULL, NULL, NULL); |
| |
| #ifdef DEBUG_LOG |
| |
| LOGD("SNAPSHOT THREAD SELECT RECEIVED A MESSAGE\n"); |
| |
| #endif |
| |
| if (err < 1) { |
| LOGE("Snapshot: Error in select"); |
| } |
| |
| if(FD_ISSET(snapshotPipe[0], &descriptorSet)){ |
| |
| read(snapshotPipe[0], &snapshotMessage, sizeof(snapshotMessage)); |
| |
| if(snapshotMessage[0] == SNAPSHOT_THREAD_START){ |
| |
| #ifdef DEBUG_LOG |
| |
| LOGD("SNAPSHOT_THREAD_START RECEIVED\n"); |
| |
| #endif |
| |
| yuv_buffer = (void *) snapshotMessage[1]; |
| image_width = snapshotMessage[2]; |
| image_height = snapshotMessage[3]; |
| ZoomTarget = zoom_step[snapshotMessage[4]]; |
| crop_left = snapshotMessage[5]; |
| crop_top = snapshotMessage[6]; |
| crop_width = snapshotMessage[7]; |
| crop_height = snapshotMessage[8]; |
| |
| mParameters.getPreviewSize(&preview_width, &preview_height); |
| |
| #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS |
| |
| PPM("Before vpp downscales:"); |
| |
| #endif |
| |
| snapshot_buffer = getLastOverlayAddress(); |
| if ( NULL == snapshot_buffer ) |
| continue; |
| |
| LOGE("Snapshot buffer 0x%x, yuv_buffer = 0x%x, zoomTarget = %5.2f", ( unsigned int ) snapshot_buffer, ( unsigned int ) yuv_buffer, ZoomTarget); |
| |
| status = scale_init(image_width, image_height, preview_width, preview_height, PIX_YUV422I, PIX_YUV422I); |
| |
| if ( status < 0 ) { |
| LOGE("VPP init failed"); |
| goto EXIT; |
| } |
| |
| status = scale_process(yuv_buffer, image_width, image_height, |
| snapshot_buffer, preview_width, preview_height, 0, PIX_YUV422I, zoom_step[0], crop_top, crop_left, crop_width, crop_height); |
| |
| #ifdef DEBUG_LOG |
| |
| PPM("After vpp downscales:"); |
| |
| if( status ) |
| LOGE("scale_process() failed"); |
| else |
| LOGD("scale_process() OK"); |
| |
| #endif |
| |
| #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS |
| |
| PPM("Shot to Snapshot", &ppm_receiveCmdToTakePicture); |
| |
| #endif |
| |
| scale_deinit(); |
| |
| queueToOverlay(lastOverlayBufferDQ); |
| dequeueFromOverlay(); |
| |
| EXIT: |
| |
| write(snapshotReadyPipe[1], &snapshotReadyMessage, sizeof(snapshotReadyMessage)); |
| } else if (snapshotMessage[0] == SNAPSHOT_THREAD_START_GEN) { |
| |
| queueToOverlay(lastOverlayBufferDQ); |
| mParameters.getPreviewSize(&preview_width, &preview_height); |
| |
| #ifdef DUMP_SNAPSHOT |
| SaveFile(NULL, (char*)"snp", getLastOverlayAddress(), preview_width*preview_height*2); |
| #endif |
| |
| #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS |
| |
| PPM("Shot to Snapshot", &ppm_receiveCmdToTakePicture); |
| |
| #endif |
| dequeueFromOverlay(); |
| write(snapshotReadyPipe[1], &snapshotReadyMessage, sizeof(snapshotReadyMessage)); |
| |
| } else if (snapshotMessage[0] == SNAPSHOT_THREAD_EXIT) { |
| LOGD("SNAPSHOT_THREAD_EXIT RECEIVED"); |
| |
| break; |
| } |
| } |
| } |
| |
| LOG_FUNCTION_NAME_EXIT |
| } |
| |
| void CameraHal::rawThread() |
| { |
| LOG_FUNCTION_NAME |
| |
| fd_set descriptorSet; |
| int max_fd; |
| int err; |
| unsigned int rawMessage[RAW_THREAD_NUM_ARGS]; |
| data_callback RawCallback; |
| void *PictureCallbackCookie; |
| sp<MemoryBase> rawData; |
| |
| max_fd = rawPipe[0] + 1; |
| |
| FD_ZERO(&descriptorSet); |
| FD_SET(rawPipe[0], &descriptorSet); |
| |
| while(1) { |
| err = select(max_fd, &descriptorSet, NULL, NULL, NULL); |
| |
| #ifdef DEBUG_LOG |
| |
| LOGD("RAW THREAD SELECT RECEIVED A MESSAGE\n"); |
| |
| #endif |
| |
| if (err < 1) { |
| LOGE("Raw: Error in select"); |
| } |
| |
| if(FD_ISSET(rawPipe[0], &descriptorSet)){ |
| |
| read(rawPipe[0], &rawMessage, sizeof(rawMessage)); |
| |
| if(rawMessage[0] == RAW_THREAD_CALL){ |
| |
| #ifdef DEBUG_LOG |
| |
| LOGD("RAW_THREAD_CALL RECEIVED\n"); |
| |
| #endif |
| |
| RawCallback = (data_callback) rawMessage[1]; |
| PictureCallbackCookie = (void *) rawMessage[2]; |
| rawData = (MemoryBase *) rawMessage[3]; |
| |
| RawCallback(CAMERA_MSG_RAW_IMAGE, rawData, PictureCallbackCookie); |
| |
| #ifdef DEBUG_LOG |
| |
| PPM("RAW CALLBACK CALLED"); |
| |
| #endif |
| |
| } else if (rawMessage[0] == RAW_THREAD_EXIT) { |
| LOGD("RAW_THREAD_EXIT RECEIVED"); |
| |
| break; |
| } |
| } |
| } |
| |
| LOG_FUNCTION_NAME_EXIT |
| } |
| |
| void CameraHal::shutterThread() |
| { |
| LOG_FUNCTION_NAME |
| |
| fd_set descriptorSet; |
| int max_fd; |
| int err; |
| unsigned int shutterMessage[SHUTTER_THREAD_NUM_ARGS]; |
| notify_callback ShutterCallback; |
| void *PictureCallbackCookie; |
| |
| max_fd = shutterPipe[0] + 1; |
| |
| FD_ZERO(&descriptorSet); |
| FD_SET(shutterPipe[0], &descriptorSet); |
| |
| while(1) { |
| err = select(max_fd, &descriptorSet, NULL, NULL, NULL); |
| |
| #ifdef DEBUG_LOG |
| |
| LOGD("SHUTTER THREAD SELECT RECEIVED A MESSAGE\n"); |
| |
| #endif |
| |
| if (err < 1) { |
| LOGE("Shutter: Error in select"); |
| } |
| |
| if(FD_ISSET(shutterPipe[0], &descriptorSet)){ |
| |
| read(shutterPipe[0], &shutterMessage, sizeof(shutterMessage)); |
| |
| if(shutterMessage[0] == SHUTTER_THREAD_CALL){ |
| |
| #ifdef DEBUG_LOG |
| |
| LOGD("SHUTTER_THREAD_CALL_RECEIVED\n"); |
| |
| #endif |
| |
| ShutterCallback = (notify_callback) shutterMessage[1]; |
| PictureCallbackCookie = (void *) shutterMessage[2]; |
| |
| ShutterCallback(CAMERA_MSG_SHUTTER, 0, 0, PictureCallbackCookie); |
| |
| #ifdef DEBUG_LOG |
| |
| PPM("CALLED SHUTTER CALLBACK"); |
| |
| #endif |
| |
| } else if (shutterMessage[0] == SHUTTER_THREAD_EXIT) { |
| LOGD("SHUTTER_THREAD_EXIT RECEIVED"); |
| |
| break; |
| } |
| } |
| } |
| |
| LOG_FUNCTION_NAME_EXIT |
| } |
| |
| void CameraHal::procThread() |
| { |
| LOG_FUNCTION_NAME |
| |
| int status; |
| int capture_width, capture_height, image_width, image_height; |
| fd_set descriptorSet; |
| int max_fd; |
| int err; |
| int pixelFormat; |
| unsigned int procMessage [PROC_THREAD_NUM_ARGS]; |
| unsigned int jpegQuality, jpegSize, size, base, tmpBase, offset, yuv_offset, yuv_len, image_rotation, ippMode; |
| unsigned int crop_top, crop_left, crop_width, crop_height; |
| double image_zoom; |
| bool ipp_to_enable; |
| sp<MemoryHeapBase> JPEGPictureHeap; |
| sp<MemoryBase> JPEGPictureMemBase; |
| data_callback RawPictureCallback; |
| data_callback JpegPictureCallback; |
| void *yuv_buffer, *outBuffer, *PictureCallbackCookie; |
| int thumb_width, thumb_height; |
| |
| #ifdef HARDWARE_OMX |
| |
| exif_buffer *exif_buf; |
| |
| #endif |
| |
| unsigned short EdgeEnhancementStrength, WeakEdgeThreshold, StrongEdgeThreshold, |
| LowFreqLumaNoiseFilterStrength, MidFreqLumaNoiseFilterStrength, HighFreqLumaNoiseFilterStrength, |
| LowFreqCbNoiseFilterStrength, MidFreqCbNoiseFilterStrength, HighFreqCbNoiseFilterStrength, |
| LowFreqCrNoiseFilterStrength, MidFreqCrNoiseFilterStrength, HighFreqCrNoiseFilterStrength, |
| shadingVertParam1, shadingVertParam2, shadingHorzParam1, shadingHorzParam2, shadingGainScale, |
| shadingGainOffset, shadingGainMaxValue, ratioDownsampleCbCr; |
| |
| void* input_buffer; |
| unsigned int input_length; |
| |
| max_fd = procPipe[0] + 1; |
| |
| FD_ZERO(&descriptorSet); |
| FD_SET(procPipe[0], &descriptorSet); |
| |
| mJPEGLength = MAX_THUMB_WIDTH*MAX_THUMB_HEIGHT + PICTURE_WIDTH*PICTURE_HEIGHT + ((2*PAGE) - 1); |
| mJPEGLength &= ~((2*PAGE) - 1); |
| mJPEGLength += 2*PAGE; |
| JPEGPictureHeap = new MemoryHeapBase(mJPEGLength); |
| |
| while(1){ |
| |
| err = select(max_fd, &descriptorSet, NULL, NULL, NULL); |
| |
| #ifdef DEBUG_LOG |
| |
| LOGD("PROCESSING THREAD SELECT RECEIVED A MESSAGE\n"); |
| |
| #endif |
| |
| if (err < 1) { |
| LOGE("Proc: Error in select"); |
| } |
| |
| if(FD_ISSET(procPipe[0], &descriptorSet)){ |
| |
| read(procPipe[0], &procMessage, sizeof(procMessage)); |
| |
| if(procMessage[0] == PROC_THREAD_PROCESS){ |
| |
| #ifdef DEBUG_LOG |
| |
| LOGD("PROC_THREAD_PROCESS_RECEIVED\n"); |
| |
| #endif |
| |
| capture_width = procMessage[1]; |
| capture_height = procMessage[2]; |
| image_width = procMessage[3]; |
| image_height = procMessage[4]; |
| pixelFormat = procMessage[5]; |
| EdgeEnhancementStrength = procMessage[6]; |
| WeakEdgeThreshold = procMessage[7]; |
| StrongEdgeThreshold = procMessage[8]; |
| LowFreqLumaNoiseFilterStrength = procMessage[9]; |
| MidFreqLumaNoiseFilterStrength = procMessage[10]; |
| HighFreqLumaNoiseFilterStrength = procMessage[11]; |
| LowFreqCbNoiseFilterStrength = procMessage[12]; |
| MidFreqCbNoiseFilterStrength = procMessage[13]; |
| HighFreqCbNoiseFilterStrength = procMessage[14]; |
| LowFreqCrNoiseFilterStrength = procMessage[15]; |
| MidFreqCrNoiseFilterStrength = procMessage[16]; |
| HighFreqCrNoiseFilterStrength = procMessage[17]; |
| shadingVertParam1 = procMessage[18]; |
| shadingVertParam2 = procMessage[19]; |
| shadingHorzParam1 = procMessage[20]; |
| shadingHorzParam2 = procMessage[21]; |
| shadingGainScale = procMessage[22]; |
| shadingGainOffset = procMessage[23]; |
| shadingGainMaxValue = procMessage[24]; |
| ratioDownsampleCbCr = procMessage[25]; |
| yuv_buffer = (void *) procMessage[26]; |
| yuv_offset = procMessage[27]; |
| yuv_len = procMessage[28]; |
| image_rotation = procMessage[29]; |
| image_zoom = zoom_step[procMessage[30]]; |
| ippMode = procMessage[31]; |
| ipp_to_enable = procMessage[32]; |
| jpegQuality = procMessage[33]; |
| JpegPictureCallback = (data_callback) procMessage[34]; |
| RawPictureCallback = (data_callback) procMessage[35]; |
| PictureCallbackCookie = (void *) procMessage[36]; |
| crop_left = procMessage[37]; |
| crop_top = procMessage[38]; |
| crop_width = procMessage[39]; |
| crop_height = procMessage[40]; |
| thumb_width = procMessage[41]; |
| thumb_height = procMessage[42]; |
| |
| #ifdef HARDWARE_OMX |
| |
| exif_buf = (exif_buffer *) procMessage[43]; |
| |
| #endif |
| |
| LOGD("JPEGPictureHeap->getStrongCount() = %d, base = 0x%x", JPEGPictureHeap->getStrongCount(), ( unsigned int ) JPEGPictureHeap->getBase()); |
| jpegSize = mJPEGLength; |
| |
| if(JPEGPictureHeap->getStrongCount() > 1 ) |
| { |
| JPEGPictureHeap.clear(); |
| JPEGPictureHeap = new MemoryHeapBase(jpegSize); |
| } |
| |
| base = (unsigned long) JPEGPictureHeap->getBase(); |
| base = (base + 0xfff) & 0xfffff000; |
| offset = base - (unsigned long) JPEGPictureHeap->getBase(); |
| outBuffer = (void *) base; |
| |
| pixelFormat = PIX_YUV422I; |
| |
| input_buffer = yuv_buffer; |
| input_length = yuv_len; |
| |
| #ifdef IMAGE_PROCESSING_PIPELINE |
| |
| #ifdef DEBUG_LOG |
| |
| LOGD("IPPmode=%d",ippMode); |
| if(ippMode == IPP_CromaSupression_Mode){ |
| LOGD("IPP_CromaSupression_Mode"); |
| } |
| else if(ippMode == IPP_EdgeEnhancement_Mode){ |
| LOGD("IPP_EdgeEnhancement_Mode"); |
| } |
| else if(ippMode == IPP_Disabled_Mode){ |
| LOGD("IPP_Disabled_Mode"); |
| } |
| |
| #endif |
| |
| if( (ippMode == IPP_CromaSupression_Mode) || (ippMode == IPP_EdgeEnhancement_Mode) ){ |
| |
| if(ipp_to_enable) { |
| |
| #ifdef DEBUG_LOG |
| |
| PPM("Before init IPP"); |
| |
| #endif |
| |
| err = InitIPP(capture_width, capture_height, pixelFormat, ippMode); |
| if( err ) |
| LOGE("ERROR InitIPP() failed"); |
| |
| #ifdef DEBUG_LOG |
| PPM("After IPP Init"); |
| #endif |
| |
| } |
| |
| err = PopulateArgsIPP(capture_width, capture_height, pixelFormat, ippMode); |
| if( err ) |
| LOGE("ERROR PopulateArgsIPP() failed"); |
| |
| #ifdef DEBUG_LOG |
| PPM("BEFORE IPP Process Buffer"); |
| LOGD("Calling ProcessBufferIPP(buffer=%p , len=0x%x)", yuv_buffer, yuv_len); |
| #endif |
| // TODO: Need to add support for new EENF 1.9 parameters from proc messages |
| err = ProcessBufferIPP(input_buffer, input_length, |
| pixelFormat, |
| ippMode, |
| EdgeEnhancementStrength, |
| WeakEdgeThreshold, |
| StrongEdgeThreshold, |
| LowFreqLumaNoiseFilterStrength, |
| MidFreqLumaNoiseFilterStrength, |
| HighFreqLumaNoiseFilterStrength, |
| LowFreqCbNoiseFilterStrength, |
| MidFreqCbNoiseFilterStrength, |
| HighFreqCbNoiseFilterStrength, |
| LowFreqCrNoiseFilterStrength, |
| MidFreqCrNoiseFilterStrength, |
| HighFreqCrNoiseFilterStrength, |
| shadingVertParam1, |
| shadingVertParam2, |
| shadingHorzParam1, |
| shadingHorzParam2, |
| shadingGainScale, |
| shadingGainOffset, |
| shadingGainMaxValue, |
| ratioDownsampleCbCr); |
| if( err ) |
| LOGE("ERROR ProcessBufferIPP() failed"); |
| |
| #ifdef DEBUG_LOG |
| PPM("AFTER IPP Process Buffer"); |
| #endif |
| pixelFormat = PIX_YUV422I; //output of IPP is always 422I |
| if(!(pIPP.ippconfig.isINPLACE)){ |
| input_buffer = pIPP.pIppOutputBuffer; |
| input_length = pIPP.outputBufferSize; |
| } |
| } |
| #endif |
| |
| #if JPEG |
| err = 0; |
| |
| #ifdef DEBUG_LOG |
| LOGD(" outbuffer = %p, jpegSize = %d, input_buffer = %p, yuv_len = %d, image_width = %d, image_height = %d, quality = %d, ippMode =%d", outBuffer , jpegSize, input_buffer/*yuv_buffer*/, input_length/*yuv_len*/, image_width, image_height, jpegQuality, ippMode); |
| #endif |
| //workaround for thumbnail size - it should be smaller than captured image |
| if ((image_width<thumb_width) || (image_height<thumb_width) || |
| (image_width<thumb_height) || (image_height<thumb_height)) { |
| thumb_width = MIN_THUMB_WIDTH; |
| thumb_height = MIN_THUMB_HEIGHT; |
| } |
| |
| #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS |
| PPM("BEFORE JPEG Encode Image"); |
| #endif |
| if (!( jpegEncoder->encodeImage((uint8_t *)outBuffer , jpegSize, input_buffer, input_length, |
| capture_width, capture_height, jpegQuality, exif_buf, pixelFormat, thumb_width, thumb_height, image_width, image_height, |
| image_rotation, image_zoom, crop_top, crop_left, crop_width, crop_height))) |
| { |
| err = -1; |
| LOGE("JPEG Encoding failed"); |
| } |
| #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS |
| PPM("AFTER JPEG Encode Image"); |
| if ( 0 != image_rotation ) |
| PPM("Shot to JPEG with %d deg rotation", &ppm_receiveCmdToTakePicture, image_rotation); |
| else |
| PPM("Shot to JPEG", &ppm_receiveCmdToTakePicture); |
| #endif |
| |
| JPEGPictureMemBase = new MemoryBase(JPEGPictureHeap, offset, jpegEncoder->jpegSize); |
| #endif |
| /* Disable the jpeg message enabled check for now */ |
| if(/*JpegPictureCallback*/ true) { |
| |
| #if JPEG |
| |
| JpegPictureCallback(CAMERA_MSG_COMPRESSED_IMAGE, JPEGPictureMemBase, PictureCallbackCookie); |
| |
| #else |
| |
| JpegPictureCallback(CAMERA_MSG_COMPRESSED_IMAGE, NULL, PictureCallbackCookie); |
| |
| #endif |
| |
| } |
| |
| #ifdef DEBUG_LOG |
| |
| LOGD("jpegEncoder->jpegSize=%d jpegSize=%d", jpegEncoder->jpegSize, jpegSize); |
| |
| #endif |
| |
| #ifdef HARDWARE_OMX |
| |
| if((exif_buf != NULL) && (exif_buf->data != NULL)) |
| exif_buf_free(exif_buf); |
| |
| #endif |
| |
| JPEGPictureMemBase.clear(); |
| free((void *) ( ((unsigned int) yuv_buffer) - yuv_offset) ); |
| |
| // Release constraint to DSP OPP by setting lowest Hz |
| SetDSPHz(DSP3630_HZ_MIN); |
| |
| } else if( procMessage[0] == PROC_THREAD_EXIT ) { |
| LOGD("PROC_THREAD_EXIT_RECEIVED"); |
| JPEGPictureHeap.clear(); |
| break; |
| } |
| } |
| } |
| |
| JPEGPictureHeap.clear(); |
| |
| LOG_FUNCTION_NAME_EXIT |
| } |
| |
| #ifdef ICAP_EXPERIMENTAL |
| |
| int CameraHal::allocatePictureBuffer(size_t length, int burstCount) |
| { |
| unsigned int base, tmpBase; |
| |
| length += ((2*PAGE) - 1) + 10*PAGE; |
| length &= ~((2*PAGE) - 1); |
| length += 2*PAGE; |
| |
| //allocate new buffers |
| for ( int i = 0; i < burstCount; i++) { |
| base = (unsigned int) malloc(length); |
| if ( ((void *) base ) == NULL ) |
| return -1; |
| |
| tmpBase = base; |
| base = (base + 0xfff) & 0xfffff000; |
| mPictureOffset[i] = base - tmpBase; |
| mYuvBuffer[i] = (uint8_t *) base; |
| mPictureLength[i] = length - mPictureOffset[i]; |
| } |
| |
| return NO_ERROR; |
| } |
| |
| #else |
| |
| int CameraHal::allocatePictureBuffer(int width, int height, int burstCount) |
| { |
| unsigned int base, tmpBase, length; |
| |
| length = width*height*2 + ((2*PAGE) - 1) + 10*PAGE; |
| length &= ~((2*PAGE) - 1); |
| length += 2*PAGE; |
| |
| //allocate new buffers |
| for ( int i = 0; i < burstCount; i++) { |
| base = (unsigned int) malloc(length); |
| if ( ((void *) base ) == NULL ) |
| return -1; |
| |
| tmpBase = base; |
| base = (base + 0xfff) & 0xfffff000; |
| mPictureOffset[i] = base - tmpBase; |
| mYuvBuffer[i] = (uint8_t *) base; |
| mPictureLength[i] = length - mPictureOffset[i]; |
| } |
| |
| return NO_ERROR; |
| } |
| |
| #endif |
| |
| int CameraHal::ICaptureCreate(void) |
| { |
| int res; |
| |
| #ifdef DEBUG_LOG |
| |
| LOG_FUNCTION_NAME |
| |
| #endif |
| |
| res = 0; |
| |
| #ifdef ICAP |
| |
| iobj = (libtest_obj *) malloc( sizeof( *iobj)); |
| if( NULL == iobj) { |
| LOGE("libtest_obj malloc failed"); |
| goto exit; |
| } |
| |
| memset(iobj, 0 , sizeof(*iobj)); |
| |
| res = icap_create(&iobj->lib_private); |
| if ( ICAP_STATUS_FAIL == res) { |
| LOGE("ICapture Create function failed"); |
| goto fail_icapture; |
| } |
| |
| LOGD("ICapture create OK"); |
| |
| #endif |
| |
| #ifdef HARDWARE_OMX |
| #ifdef IMAGE_PROCESSING_PIPELINE |
| |
| mippMode = IPP_Disabled_Mode; |
| |
| #endif |
| |
| #if JPEG |
| |
| jpegEncoder = new JpegEncoder; |
| |
| if( NULL != jpegEncoder ) |
| isStart_JPEG = true; |
| |
| #endif |
| #endif |
| |
| LOG_FUNCTION_NAME_EXIT |
| return res; |
| |
| fail_jpeg_buffer: |
| fail_yuv_buffer: |
| fail_init: |
| |
| #ifdef HARDWARE_OMX |
| #if JPEG |
| |
| delete jpegEncoder; |
| |
| #endif |
| #endif |
| |
| #ifdef ICAP |
| |
| icap_destroy(iobj->lib_private); |
| |
| #endif |
| |
| fail_icapture: |
| exit: |
| return -1; |
| } |
| |
| int CameraHal::ICaptureDestroy(void) |
| { |
| int err; |
| |
| #ifdef HARDWARE_OMX |
| #if JPEG |
| |
| if( isStart_JPEG ) |
| { |
| isStart_JPEG = false; |
| delete jpegEncoder; |
| jpegEncoder = NULL; |
| } |
| #endif |
| #endif |
| |
| #ifdef ICAP |
| if(iobj != NULL) |
| { |
| err = icap_destroy(iobj->lib_private); |
| if ( ICAP_STATUS_FAIL == err ) |
| LOGE("ICapture Delete failed"); |
| else |
| LOGD("ICapture delete OK"); |
| |
| free(iobj); |
| iobj = NULL; |
| } |
| |
| #endif |
| |
| return 0; |
| } |
| |
| status_t CameraHal::setOverlay(const sp<Overlay> &overlay) |
| { |
| Mutex::Autolock lock(mLock); |
| int w,h; |
| |
| LOGD("CameraHal setOverlay/1/%08lx/%08lx", (long unsigned int)overlay.get(), (long unsigned int)mOverlay.get()); |
| // De-alloc any stale data |
| if ( mOverlay.get() != NULL ) |
| { |
| LOGD("Destroying current overlay"); |
| |
| int buffer_count = mOverlay->getBufferCount(); |
| for(int i =0; i < buffer_count ; i++){ |
| // need to free buffers and heaps mapped using overlay fd before it is destroyed |
| // otherwise we could create a resource leak |
| // a segfault could occur if we try to free pointers after overlay is destroyed |
| mPreviewBuffers[i].clear(); |
| mPreviewHeaps[i].clear(); |
| mVideoBuffer[i].clear(); |
| mVideoHeaps[i].clear(); |
| buffers_queued_to_dss[i] = 0; |
| } |
| |
| mOverlay->destroy(); |
| nOverlayBuffersQueued = 0; |
| } |
| |
| mOverlay = overlay; |
| if (mOverlay == NULL) |
| { |
| LOGE("Trying to set overlay, but overlay is null!, line:%d",__LINE__); |
| return NO_ERROR; |
| } |
| |
| mParameters.getPreviewSize(&w, &h); |
| if ((w == RES_720P) || (h == RES_720P)) |
| { |
| mOverlay->setParameter(CACHEABLE_BUFFERS, 1); |
| mOverlay->setParameter(MAINTAIN_COHERENCY, 0); |
| mOverlay->resizeInput(w, h); |
| } |
| |
| if (mFalsePreview) // Eclair HAL |
| { |
| // Restart the preview (Only for Overlay Case) |
| //LOGD("In else overlay"); |
| mPreviewRunning = false; |
| Message msg; |
| msg.command = PREVIEW_START; |
| previewThreadCommandQ.put(&msg); |
| previewThreadAckQ.get(&msg); |
| } // Eclair HAL |
| |
| LOG_FUNCTION_NAME_EXIT |
| |
| return NO_ERROR; |
| } |
| |
| status_t CameraHal::startPreview() |
| { |
| LOG_FUNCTION_NAME |
| |
| if(mOverlay == NULL) //Eclair HAL |
| { |
| LOGD("Return from camera Start Preview"); |
| mPreviewRunning = true; |
| mFalsePreview = true; |
| return NO_ERROR; |
| } //Eclair HAL |
| |
| mFalsePreview = false; //Eclair HAL |
| |
| Message msg; |
| msg.command = PREVIEW_START; |
| previewThreadCommandQ.put(&msg); |
| previewThreadAckQ.get(&msg); |
| |
| LOG_FUNCTION_NAME_EXIT |
| return msg.command == PREVIEW_ACK ? NO_ERROR : INVALID_OPERATION; |
| } |
| |
| void CameraHal::stopPreview() |
| { |
| LOG_FUNCTION_NAME |
| |
| mFalsePreview = false; //Eclair HAL |
| Message msg; |
| msg.command = PREVIEW_STOP; |
| previewThreadCommandQ.put(&msg); |
| previewThreadAckQ.get(&msg); |
| } |
| |
| |
| status_t CameraHal::autoFocus() |
| { |
| LOG_FUNCTION_NAME |
| |
| Message msg; |
| msg.command = PREVIEW_AF_START; |
| previewThreadCommandQ.put(&msg); |
| previewThreadAckQ.get(&msg); |
| |
| LOG_FUNCTION_NAME_EXIT |
| return msg.command == PREVIEW_ACK ? NO_ERROR : INVALID_OPERATION; |
| } |
| |
| bool CameraHal::previewEnabled() |
| { |
| return mPreviewRunning; |
| } |
| |
| |
| status_t CameraHal::startRecording( ) |
| { |
| LOG_FUNCTION_NAME |
| int w,h; |
| int i = 0; |
| |
| mPrevTime = systemTime(SYSTEM_TIME_MONOTONIC); |
| int framerate = mParameters.getPreviewFrameRate(); |
| frameInterval = 1000000000LL / framerate ; |
| mParameters.getPreviewSize(&w, &h); |
| mRecordingFrameSize = w * h * 2; |
| overlay_handle_t overlayhandle = mOverlay->getHandleRef(); |
| overlay_true_handle_t true_handle; |
| if ( overlayhandle == NULL ) { |
| LOGD("overlayhandle is received as NULL. "); |
| return UNKNOWN_ERROR; |
| } |
| |
| memcpy(&true_handle,overlayhandle,sizeof(overlay_true_handle_t)); |
| int overlayfd = true_handle.ctl_fd; |
| LOGD("#Overlay driver FD:%d ",overlayfd); |
| |
| mVideoBufferCount = mOverlay->getBufferCount(); |
| |
| if (mVideoBufferCount > VIDEO_FRAME_COUNT_MAX) |
| { |
| LOGD("Error: mVideoBufferCount > VIDEO_FRAME_COUNT_MAX"); |
| return UNKNOWN_ERROR; |
| } |
| |
| mRecordingLock.lock(); |
| |
| for(i = 0; i < mVideoBufferCount; i++) |
| { |
| mVideoHeaps[i].clear(); |
| mVideoBuffer[i].clear(); |
| buffers_queued_to_ve[i] = 0; |
| } |
| |
| for(i = 0; i < mVideoBufferCount; i++) |
| { |
| mapping_data_t* data = (mapping_data_t*) mOverlay->getBufferAddress((void*)i); |
| // make sure data if valid, if not clear all previously allocated memory and return |
| if(data != NULL) |
| { |
| mVideoHeaps[i] = new MemoryHeapBase(data->fd,mPreviewFrameSize, 0, data->offset); |
| mVideoBuffer[i] = new MemoryBase(mVideoHeaps[i], 0, mRecordingFrameSize); |
| LOGV("mVideoHeaps[%d]: ID:%d,Base:[%p],size:%d", i, mVideoHeaps[i]->getHeapID(), mVideoHeaps[i]->getBase() ,mVideoHeaps[i]->getSize()); |
| LOGV("mVideoBuffer[%d]: Pointer[%p]", i, mVideoBuffer[i]->pointer()); |
| } else{ |
| for(int j = 0; j < i+1; j++) |
| { |
| mVideoHeaps[j].clear(); |
| mVideoBuffer[j].clear(); |
| buffers_queued_to_ve[j] = 0; |
| } |
| LOGD("Error: data from overlay returned null"); |
| return UNKNOWN_ERROR; |
| } |
| } |
| |
| mRecordEnabled =true; |
| mRecordingLock.unlock(); |
| return NO_ERROR; |
| } |
| |
| void CameraHal::stopRecording() |
| { |
| LOG_FUNCTION_NAME |
| mRecordingLock.lock(); |
| mRecordEnabled = false; |
| |
| for(int i = 0; i < MAX_CAMERA_BUFFERS; i ++) |
| { |
| if (buffers_queued_to_ve[i] == 1) |
| { |
| if (ioctl(camera_device, VIDIOC_QBUF, &v4l2_cam_buffer[i]) < 0) { |
| LOGE("VIDIOC_QBUF Failed. line=%d",__LINE__); |
| } |
| else nCameraBuffersQueued++; |
| buffers_queued_to_ve[i] = 0; |
| LOGD("Buffer #%d was not returned by VE. Reclaiming it !!!!!!!!!!!!!!!!!!!!!!!!", i); |
| } |
| } |
| |
| mRecordingLock.unlock(); |
| } |
| |
| bool CameraHal::recordingEnabled() |
| { |
| LOG_FUNCTION_NAME |
| return (mRecordEnabled); |
| } |
| void CameraHal::releaseRecordingFrame(const sp<IMemory>& mem) |
| { |
| //LOG_FUNCTION_NAME |
| int index; |
| |
| for(index = 0; index <mVideoBufferCount; index ++){ |
| if(mem->pointer() == mVideoBuffer[index]->pointer()) { |
| break; |
| } |
| } |
| |
| if (index == mVideoBufferCount) |
| { |
| LOGD("Encoder returned wrong buffer address"); |
| return; |
| } |
| |
| debugShowFPS(); |
| |
| if (ioctl(camera_device, VIDIOC_QBUF, &v4l2_cam_buffer[index]) < 0) |
| { |
| LOGE("VIDIOC_QBUF Failed, index [%d] line=%d",index,__LINE__); |
| } |
| else |
| { |
| nCameraBuffersQueued++; |
| } |
| |
| return; |
| } |
| |
| sp<IMemoryHeap> CameraHal::getRawHeap() const |
| { |
| return mPictureHeap; |
| } |
| |
| |
| status_t CameraHal::takePicture( ) |
| { |
| LOG_FUNCTION_NAME |
| |
| Message msg; |
| msg.command = PREVIEW_CAPTURE; |
| previewThreadCommandQ.put(&msg); |
| previewThreadAckQ.get(&msg); |
| |
| #ifdef DEBUG_LOG |
| |
| LOG_FUNCTION_NAME_EXIT |
| |
| #endif |
| |
| return NO_ERROR; |
| } |
| |
| status_t CameraHal::cancelPicture( ) |
| { |
| LOG_FUNCTION_NAME |
| disableMsgType(CAMERA_MSG_RAW_IMAGE); |
| disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE); |
| // mCallbackCookie = NULL; // done in destructor |
| |
| LOGE("Callbacks set to null"); |
| return -1; |
| } |
| |
| status_t CameraHal::convertGPSCoord(double coord, int *deg, int *min, int *sec) |
| { |
| double tmp; |
| |
| LOG_FUNCTION_NAME |
| |
| if ( coord == 0 ) { |
| |
| LOGE("Invalid GPS coordinate"); |
| |
| return EINVAL; |
| } |
| |
| *deg = (int) floor(coord); |
| tmp = ( coord - floor(coord) )*60; |
| *min = (int) floor(tmp); |
| tmp = ( tmp - floor(tmp) )*60; |
| *sec = (int) floor(tmp); |
| |
| if( *sec >= 60 ) { |
| *sec = 0; |
| *min += 1; |
| } |
| |
| if( *min >= 60 ) { |
| *min = 0; |
| *deg += 1; |
| } |
| |
| LOG_FUNCTION_NAME_EXIT |
| |
| return NO_ERROR; |
| } |
| |
| status_t CameraHal::setParameters(const CameraParameters ¶ms) |
| { |
| LOG_FUNCTION_NAME |
| |
| int w, h; |
| int w_orig, h_orig, rot_orig; |
| int framerate; |
| int zoom, compensation, saturation, sharpness; |
| int zoom_save; |
| int contrast, brightness, caf; |
| int error; |
| int base; |
| const char *valstr; |
| char *af_coord; |
| Message msg; |
| |
| Mutex::Autolock lock(mLock); |
| |
| LOGD("PreviewFormat %s", params.getPreviewFormat()); |
| |
| if ( params.getPreviewFormat() != NULL ) { |
| if (strcmp(params.getPreviewFormat(), (const char *) CameraParameters::PIXEL_FORMAT_YUV422I) != 0) { |
| LOGE("Only yuv422i preview is supported"); |
| return -EINVAL; |
| } |
| } |
| |
| LOGD("PictureFormat %s", params.getPictureFormat()); |
| if ( params.getPictureFormat() != NULL ) { |
| if (strcmp(params.getPictureFormat(), (const char *) CameraParameters::PIXEL_FORMAT_JPEG) != 0) { |
| LOGE("Only jpeg still pictures are supported"); |
| return -EINVAL; |
| } |
| } |
| |
| params.getPreviewSize(&w, &h); |
| if ( validateSize(w, h, supportedPreviewRes, ARRAY_SIZE(supportedPreviewRes)) == false ) { |
| LOGE("Preview size not supported"); |
| return -EINVAL; |
| } |
| LOGD("PreviewResolution by App %d x %d", w, h); |
| |
| params.getPictureSize(&w, &h); |
| if (validateSize(w, h, supportedPictureRes, ARRAY_SIZE(supportedPictureRes)) == false ) { |
| LOGE("Picture size not supported"); |
| return -EINVAL; |
| } |
| LOGD("Picture Size by App %d x %d", w, h); |
| |
| #ifdef HARDWARE_OMX |
| |
| mExifParams.width = w; |
| mExifParams.height = h; |
| |
| #endif |
| |
| framerate = params.getPreviewFrameRate(); |
| LOGD("FRAMERATE %d", framerate); |
| |
| rot_orig = rotation; |
| rotation = params.getInt(CameraParameters::KEY_ROTATION); |
| |
| mParameters.getPictureSize(&w_orig, &h_orig); |
| zoom_save = mParameters.getInt(CameraParameters::KEY_ZOOM); |
| mParameters = params; |
| |
| #ifdef IMAGE_PROCESSING_PIPELINE |
| |
| if((mippMode != mParameters.getInt(KEY_IPP)) || (w != w_orig) || (h != h_orig) || |
| ((rot_orig != 180) && (rotation == 180)) || |
| ((rot_orig == 180) && (rotation != 180))) // in the current setup, IPP uses a different setup when rotation is 180 degrees |
| { |
| if(pIPP.hIPP != NULL){ |
| LOGD("pIPP.hIPP=%p", pIPP.hIPP); |
| if(DeInitIPP(mippMode)) // deinit here to save time |
| LOGE("ERROR DeInitIPP() failed"); |
| pIPP.hIPP = NULL; |
| } |
| |
| mippMode = mParameters.getInt(KEY_IPP); |
| LOGD("mippMode=%d", mippMode); |
| |
| mIPPToEnable = true; |
| } |
| |
| #endif |
| |
| mParameters.getPictureSize(&w, &h); |
| LOGD("Picture Size by CamHal %d x %d", w, h); |
| |
| mParameters.getPreviewSize(&w, &h); |
| LOGD("Preview Resolution by CamHal %d x %d", w, h); |
| |
| quality = params.getInt(CameraParameters::KEY_JPEG_QUALITY); |
| if ( ( quality < 0 ) || (quality > 100) ){ |
| quality = 100; |
| } |
| |
| zoom = mParameters.getInt(CameraParameters::KEY_ZOOM); |
| if( (zoom >= 0) && ( zoom < ZOOM_STAGES) ){ |
| // immediate zoom |
| mZoomSpeed = 0; |
| mZoomTargetIdx = zoom; |
| } else if(zoom>= ZOOM_STAGES){ |
| mParameters.set(CameraParameters::KEY_ZOOM, zoom_save); |
| return -EINVAL; |
| } else { |
| mZoomTargetIdx = 0; |
| } |
| LOGD("Zoom by App %d", zoom); |
| |
| #ifdef HARDWARE_OMX |
| |
| mExifParams.zoom = zoom; |
| |
| #endif |
| |
| if ( ( params.get(CameraParameters::KEY_GPS_LATITUDE) != NULL ) && ( params.get(CameraParameters::KEY_GPS_LONGITUDE) != NULL ) && ( params.get(CameraParameters::KEY_GPS_ALTITUDE) != NULL )) { |
| |
| double gpsCoord; |
| struct tm* timeinfo; |
| |
| #ifdef HARDWARE_OMX |
| |
| if( NULL == gpsLocation ) |
| gpsLocation = (gps_data *) malloc( sizeof(gps_data)); |
| |
| if( NULL != gpsLocation ) { |
| LOGE("initializing gps_data structure"); |
| |
| memset(gpsLocation, 0, sizeof(gps_data)); |
| gpsLocation->datestamp[0] = '\0'; |
| |
| gpsCoord = strtod( params.get(CameraParameters::KEY_GPS_LATITUDE), NULL); |
| convertGPSCoord(gpsCoord, &gpsLocation->latDeg, &gpsLocation->latMin, &gpsLocation->latSec); |
| gpsLocation->latRef = (gpsCoord < 0) ? (char*) "S" : (char*) "N"; |
| |
| gpsCoord = strtod( params.get(CameraParameters::KEY_GPS_LONGITUDE), NULL); |
| convertGPSCoord(gpsCoord, &gpsLocation->longDeg, &gpsLocation->longMin, &gpsLocation->longSec); |
| gpsLocation->longRef = (gpsCoord < 0) ? (char*) "W" : (char*) "E"; |
| |
| gpsCoord = strtod( params.get(CameraParameters::KEY_GPS_ALTITUDE), NULL); |
| gpsLocation->altitude = gpsCoord; |
| |
| if ( NULL != params.get(CameraParameters::KEY_GPS_TIMESTAMP) ){ |
| gpsLocation->timestamp = strtol( params.get(CameraParameters::KEY_GPS_TIMESTAMP), NULL, 10); |
| timeinfo = localtime((time_t*)&(gpsLocation->timestamp)); |
| if(timeinfo != NULL) |
| strftime(gpsLocation->datestamp, 11, "%Y:%m:%d", timeinfo); |
| } |
| |
| gpsLocation->altitudeRef = params.getInt(KEY_GPS_ALTITUDE_REF); |
| gpsLocation->mapdatum = (char *) params.get(KEY_GPS_MAPDATUM); |
| gpsLocation->versionId = (char *) params.get(KEY_GPS_VERSION); |
| gpsLocation->procMethod = (char *) params.get(CameraParameters::KEY_GPS_PROCESSING_METHOD); |
| |
| } else { |
| LOGE("Not enough memory to allocate gps_data structure"); |
| } |
| |
| #endif |
| |
| } |
| |
| if ( params.get(KEY_SHUTTER_ENABLE) != NULL ) { |
| if ( strcmp(params.get(KEY_SHUTTER_ENABLE), (const char *) "true") == 0 ) |
| mShutterEnable = true; |
| else if ( strcmp(params.get(KEY_SHUTTER_ENABLE), (const char *) "false") == 0 ) |
| mShutterEnable = false; |
| } |
| |
| #ifdef FW3A |
| |
| if ( params.get(KEY_CAPTURE_MODE) != NULL ) { |
| if (strcmp(params.get(KEY_CAPTURE_MODE), (const char *) HIGH_QUALITY) == 0) { |
| mcapture_mode = 2; |
| } else if (strcmp(params.get(KEY_CAPTURE_MODE), (const char *) HIGH_PERFORMANCE) == 0) { |
| mcapture_mode = 1; |
| } else { |
| mcapture_mode = 1; |
| } |
| } else { |
| mcapture_mode = 1; |
| } |
| |
| int burst_capture = params.getInt(KEY_BURST); |
| if ( ( 0 >= burst_capture ) ){ |
| mBurstShots = 1; |
| } else { |
| // hardcoded in HP mode |
| mcapture_mode = 1; |
| mBurstShots = burst_capture; |
| } |
| |
| LOGD("Capture Mode set %d, Burst Shots set %d", mcapture_mode, burst_capture); |
| LOGD("mBurstShots %d", mBurstShots); |
| |
| if ( NULL != fobj ){ |
| |
| if ( params.get(KEY_METER_MODE) != NULL ) { |
| if (strcmp(params.get(KEY_METER_MODE), (const char *) METER_MODE_CENTER) == 0) { |
| fobj->settings.af.spot_weighting = ICAM_FOCUS_SPOT_SINGLE_CENTER; |
| fobj->settings.ae.spot_weighting = ICAM_EXPOSURE_SPOT_CENTER; |
| |
| #ifdef HARDWARE_OMX |
| |
| mExifParams.metering_mode = EXIF_CENTER; |
| |
| #endif |
| |
| } else if (strcmp(params.get(KEY_METER_MODE), (const char *) METER_MODE_AVERAGE) == 0) { |
| fobj->settings.af.spot_weighting = ICAM_FOCUS_SPOT_MULTI_AVERAGE; |
| fobj->settings.ae.spot_weighting = ICAM_EXPOSURE_SPOT_NORMAL; |
| |
| #ifdef HARDWARE_OMX |
| |
| mExifParams.metering_mode = EXIF_AVERAGE; |
| |
| #endif |
| |
| } |
| } |
| |
| //Set 3A config to disable variable fps |
| fobj->settings.ae.framerate = framerate; |
| fobj->settings.general.view_finder_mode = ICAM_VFMODE_VIDEO_RECORD; |
| |
| if ( params.get(KEY_CAPTURE) != NULL ) { |
| if (strcmp(params.get(KEY_CAPTURE), (const char *) CAPTURE_STILL) == 0) { |
| //Set 3A config to enable variable fps |
| fobj->settings.ae.framerate = 0; |
| fobj->settings.general.view_finder_mode = ICAM_VFMODE_STILL_CAPTURE; |
| } |
| } |
| |
| if ( params.get(CameraParameters::KEY_SCENE_MODE) != NULL ) { |
| if (strcmp(params.get(CameraParameters::KEY_SCENE_MODE), (const char *) CameraParameters::SCENE_MODE_AUTO) == 0) { |
| fobj->settings.general.scene = ICAM_SCENE_MODE_MANUAL; |
| |
| } else if (strcmp(params.get(CameraParameters::KEY_SCENE_MODE), (const char *) CameraParameters::SCENE_MODE_PORTRAIT) == 0) { |
| |
| fobj->settings.general.scene = ICAM_SCENE_MODE_PORTRAIT; |
| |
| } else if (strcmp(params.get(CameraParameters::KEY_SCENE_MODE), (const char *) CameraParameters::SCENE_MODE_LANDSCAPE) == 0) { |
| |
| fobj->settings.general.scene = ICAM_SCENE_MODE_LANDSCAPE; |
| |
| } else if (strcmp(params.get(CameraParameters::KEY_SCENE_MODE), (const char *) CameraParameters::SCENE_MODE_NIGHT) == 0) { |
| |
| fobj->settings.general.scene = ICAM_SCENE_MODE_NIGHT; |
| |
| } else if (strcmp(params.get(CameraParameters::KEY_SCENE_MODE), (const char *) CameraParameters::SCENE_MODE_NIGHT_PORTRAIT) == 0) { |
| |
| fobj->settings.general.scene = ICAM_SCENE_MODE_NIGHT_PORTRAIT; |
| |
| } else if (strcmp(params.get(CameraParameters::KEY_SCENE_MODE), (const char *) CameraParameters::SCENE_MODE_FIREWORKS) == 0) { |
| |
| fobj->settings.general.scene = ICAM_SCENE_MODE_FIREWORKS; |
| |
| } else if (strcmp(params.get(CameraParameters::KEY_SCENE_MODE), (const char *) CameraParameters::SCENE_MODE_ACTION) == 0) { |
| |
| fobj->settings.general.scene = ICAM_SCENE_MODE_SPORT; |
| |
| } |
| else if (strcmp(params.get(CameraParameters::KEY_SCENE_MODE), (const char *) CameraParameters::SCENE_MODE_SNOW) == 0) { |
| |
| fobj->settings.general.scene = ICAM_SCENE_MODE_SNOW_BEACH; |
| |
| } |
| } |
| |
| if ( params.get(CameraParameters::KEY_WHITE_BALANCE) != NULL ) { |
| if (strcmp(params.get(CameraParameters::KEY_WHITE_BALANCE), (const char *) CameraParameters::WHITE_BALANCE_AUTO ) == 0) { |
| |
| fobj->settings.awb.mode = ICAM_WHITE_BALANCE_MODE_WB_AUTO; |
| |
| #ifdef HARDWARE_OMX |
| |
| mExifParams.wb = EXIF_WB_AUTO; |
| |
| #endif |
| |
| } else if (strcmp(params.get(CameraParameters::KEY_WHITE_BALANCE), (const char *) CameraParameters::WHITE_BALANCE_INCANDESCENT) == 0) { |
| |
| fobj->settings.awb.mode = ICAM_WHITE_BALANCE_MODE_WB_INCANDESCENT; |
| |
| #ifdef HARDWARE_OMX |
| |
| mExifParams.wb = EXIF_WB_MANUAL; |
| |
| #endif |
| |
| } else if (strcmp(params.get(CameraParameters::KEY_WHITE_BALANCE), (const char *) CameraParameters::WHITE_BALANCE_FLUORESCENT) == 0) { |
| |
| fobj->settings.awb.mode = ICAM_WHITE_BALANCE_MODE_WB_FLUORESCENT; |
| |
| #ifdef HARDWARE_OMX |
| |
| mExifParams.wb = EXIF_WB_MANUAL; |
| |
| #endif |
| |
| } else if (strcmp(params.get(CameraParameters::KEY_WHITE_BALANCE), (const char *) CameraParameters::WHITE_BALANCE_DAYLIGHT) == 0) { |
| |
| fobj->settings.awb.mode = ICAM_WHITE_BALANCE_MODE_WB_DAYLIGHT; |
| |
| #ifdef HARDWARE_OMX |
| |
| mExifParams.wb = EXIF_WB_MANUAL; |
| |
| #endif |
| |
| } else if (strcmp(params.get(CameraParameters::KEY_WHITE_BALANCE), (const char *) CameraParameters::WHITE_BALANCE_CLOUDY_DAYLIGHT) == 0) { |
| |
| fobj->settings.awb.mode = ICAM_WHITE_BALANCE_MODE_WB_CLOUDY; |
| |
| #ifdef HARDWARE_OMX |
| |
| mExifParams.wb = EXIF_WB_MANUAL; |
| |
| #endif |
| |
| } else if (strcmp(params.get(CameraParameters::KEY_WHITE_BALANCE), (const char *) CameraParameters::WHITE_BALANCE_SHADE) == 0) { |
| |
| fobj->settings.awb.mode = ICAM_WHITE_BALANCE_MODE_WB_SHADOW; |
| |
| #ifdef HARDWARE_OMX |
| |
| mExifParams.wb = EXIF_WB_MANUAL; |
| |
| #endif |
| |
| } else if (strcmp(params.get(CameraParameters::KEY_WHITE_BALANCE), (const char *) WHITE_BALANCE_HORIZON) == 0) { |
| |
| fobj->settings.awb.mode = ICAM_WHITE_BALANCE_MODE_WB_HORIZON; |
| |
| #ifdef HARDWARE_OMX |
| |
| mExifParams.wb = EXIF_WB_MANUAL; |
| |
| #endif |
| } else if (strcmp(params.get(CameraParameters::KEY_WHITE_BALANCE), (const char *) WHITE_BALANCE_TUNGSTEN) == 0) { |
| |
| fobj->settings.awb.mode = ICAM_WHITE_BALANCE_MODE_WB_TUNGSTEN; |
| |
| #ifdef HARDWARE_OMX |
| |
| mExifParams.wb = EXIF_WB_MANUAL; |
| |
| #endif |
| } |
| |
| } |
| |
| if ( params.get(CameraParameters::KEY_EFFECT) != NULL ) { |
| if (strcmp(params.get(CameraParameters::KEY_EFFECT), (const char *) CameraParameters::EFFECT_NONE ) == 0) { |
| |
| fobj->settings.general.effects = ICAM_EFFECT_NORMAL; |
| |
| } else if (strcmp(params.get(CameraParameters::KEY_EFFECT), (const char *) CameraParameters::EFFECT_MONO) == 0) { |
| |
| fobj->settings.general.effects = ICAM_EFFECT_GRAYSCALE; |
| |
| } else if (strcmp(params.get(CameraParameters::KEY_EFFECT), (const char *) CameraParameters::EFFECT_NEGATIVE) == 0) { |
| |
| fobj->settings.general.effects = ICAM_EFFECT_NEGATIVE; |
| |
| } else if (strcmp(params.get(CameraParameters::KEY_EFFECT), (const char *) CameraParameters::EFFECT_SOLARIZE) == 0) { |
| |
| fobj->settings.general.effects = ICAM_EFFECT_SOLARIZE; |
| |
| } else if (strcmp(params.get(CameraParameters::KEY_EFFECT), (const char *) CameraParameters::EFFECT_SEPIA) == 0) { |
| |
| fobj->settings.general.effects = ICAM_EFFECT_SEPIA; |
| |
| } else if (strcmp(params.get(CameraParameters::KEY_EFFECT), (const char *) CameraParameters::EFFECT_WHITEBOARD) == 0) { |
| |
| fobj->settings.general.effects = ICAM_EFFECT_WHITEBOARD; |
| |
| } else if (strcmp(params.get(CameraParameters::KEY_EFFECT), (const char *) CameraParameters::EFFECT_BLACKBOARD) == 0) { |
| |
| fobj->settings.general.effects = ICAM_EFFECT_BLACKBOARD; |
| |
| } else if (strcmp(params.get(CameraParameters::KEY_EFFECT), (const char *) EFFECT_COOL) == 0) { |
| |
| fobj->settings.general.effects = ICAM_EFFECT_COOL; |
| |
| } else if (strcmp(params.get(CameraParameters::KEY_EFFECT), (const char *) EFFECT_EMBOSS) == 0) { |
| |
| fobj->settings.general.effects = ICAM_EFFECT_EMBOSS; |
| |
| } |
| } |
| |
| if ( params.get(CameraParameters::KEY_ANTIBANDING) != NULL ) { |
| if (strcmp(params.get(CameraParameters::KEY_ANTIBANDING), (const char *) CameraParameters::ANTIBANDING_50HZ ) == 0) { |
| |
| fobj->settings.general.flicker_avoidance = ICAM_FLICKER_AVOIDANCE_50HZ; |
| |
| } else if (strcmp(params.get(CameraParameters::KEY_ANTIBANDING), (const char *) CameraParameters::ANTIBANDING_60HZ) == 0) { |
| |
| fobj->settings.general.flicker_avoidance = ICAM_FLICKER_AVOIDANCE_60HZ; |
| |
| } else if (strcmp(params.get(CameraParameters::KEY_ANTIBANDING), (const char *) CameraParameters::ANTIBANDING_OFF) == 0) { |
| |
| fobj->settings.general.flicker_avoidance = ICAM_FLICKER_AVOIDANCE_NO; |
| |
| } |
| } |
| |
| if ( params.get(CameraParameters::KEY_FOCUS_MODE) != NULL ) { |
| if (strcmp(params.get(CameraParameters::KEY_FOCUS_MODE), (const char *) CameraParameters::FOCUS_MODE_AUTO ) == 0) { |
| |
| fobj->settings.af.focus_mode = ICAM_FOCUS_MODE_AF_AUTO; |
| |
| } else if (strcmp(params.get(CameraParameters::KEY_FOCUS_MODE), (const char *) CameraParameters::FOCUS_MODE_INFINITY) == 0) { |
| |
| fobj->settings.af.focus_mode = ICAM_FOCUS_MODE_AF_INFINY; |
| |
| } else if (strcmp(params.get(CameraParameters::KEY_FOCUS_MODE), (const char *) CameraParameters::FOCUS_MODE_MACRO) == 0) { |
| |
| fobj->settings.af.focus_mode = ICAM_FOCUS_MODE_AF_MACRO; |
| |
| } else if (strcmp(params.get(CameraParameters::KEY_FOCUS_MODE), (const char *) CameraParameters::FOCUS_MODE_FIXED) == 0) { |
| |
| fobj->settings.af.focus_mode = ICAM_FOCUS_MODE_AF_MANUAL; |
| |
| } |
| } |
| |
| valstr = mParameters.get(KEY_TOUCH_FOCUS); |
| if(NULL != valstr) { |
| char *valstr_copy = (char *)malloc(ARRAY_SIZE(valstr) + 1); |
| if(NULL != valstr_copy){ |
| if ( strcmp(valstr, (const char *) TOUCH_FOCUS_DISABLED) != 0) { |
| |
| //make a copy of valstr, because strtok() overrides the whole mParameters structure |
| strcpy(valstr_copy, valstr); |
| int af_x = 0; |
| int af_y = 0; |
| |
| af_coord = strtok((char *) valstr_copy, PARAMS_DELIMITER); |
| |
| if( NULL != af_coord){ |
| af_x = atoi(af_coord); |
| } |
| |
| af_coord = strtok(NULL, PARAMS_DELIMITER); |
| |
| if( NULL != af_coord){ |
| af_y = atoi(af_coord); |
| } |
| |
| fobj->settings.general.face_tracking.enable = 1; |
| fobj->settings.general.face_tracking.count = 1; |
| fobj->settings.general.face_tracking.update = 1; |
| fobj->settings.general.face_tracking.faces[0].top = af_y; |
| fobj->settings.general.face_tracking.faces[0].left = af_x; |
| fobj->settings.af.focus_mode = ICAM_FOCUS_MODE_AF_EXTENDED; |
| |
| LOGD("NEW PARAMS: af_x = %d, af_y = %d", af_x, af_y); |
| } |
| free(valstr_copy); |
| valstr_copy = NULL; |
| } |
| } |
| |
| if ( params.get(KEY_ISO) != NULL ) { |
| if (strcmp(params.get(KEY_ISO), (const char *) ISO_AUTO ) == 0) { |
| |
| fobj->settings.ae.iso = ICAM_EXPOSURE_ISO_AUTO; |
| |
| #ifdef HARDWARE_OMX |
| |
| mExifParams.iso = EXIF_ISO_AUTO; |
| |
| #endif |
| |
| } else if (strcmp(params.get(KEY_ISO), (const char *) ISO_100 ) == 0) { |
| |
| fobj->settings.ae.iso = ICAM_EXPOSURE_ISO_100; |
| |
| #ifdef HARDWARE_OMX |
| |
| mExifParams.iso = EXIF_ISO_100; |
| |
| #endif |
| |
| } else if (strcmp(params.get(KEY_ISO), (const char *) ISO_200 ) == 0) { |
| |
| fobj->settings.ae.iso = ICAM_EXPOSURE_ISO_200; |
| |
| #ifdef HARDWARE_OMX |
| |
| mExifParams.iso = EXIF_ISO_200; |
| |
| #endif |
| |
| } else if (strcmp(params.get(KEY_ISO), (const char *) ISO_400 ) == 0) { |
| |
| fobj->settings.ae.iso = ICAM_EXPOSURE_ISO_400; |
| |
| #ifdef HARDWARE_OMX |
| |
| mExifParams.iso = EXIF_ISO_400; |
| |
| #endif |
| |
| } else if (strcmp(params.get(KEY_ISO), (const char *) ISO_800 ) == 0) { |
| |
| fobj->settings.ae.iso = ICAM_EXPOSURE_ISO_800; |
| |
| #ifdef HARDWARE_OMX |
| |
| mExifParams.iso = EXIF_ISO_800; |
| |
| #endif |
| |
| } else if (strcmp(params.get(KEY_ISO), (const char *) ISO_1000 ) == 0) { |
| |
| fobj->settings.ae.iso = ICAM_EXPOSURE_ISO_1000; |
| |
| #ifdef HARDWARE_OMX |
| |
| mExifParams.iso = EXIF_ISO_1000; |
| |
| #endif |
| |
| } else if (strcmp(params.get(KEY_ISO), (const char *) ISO_1200 ) == 0) { |
| |
| fobj->settings.ae.iso = ICAM_EXPOSURE_ISO_1600; |
| |
| #ifdef HARDWARE_OMX |
| |
| mExifParams.iso = EXIF_ISO_1200; |
| |
| #endif |
| |
| } else if (strcmp(params.get(KEY_ISO), (const char *) ISO_1600 ) == 0) { |
| |
| fobj->settings.ae.iso = ICAM_EXPOSURE_ISO_1600; |
| |
| #ifdef HARDWARE_OMX |
| |
| mExifParams.iso = EXIF_ISO_1600; |
| |
| #endif |
| |
| } else { |
| |
| fobj->settings.ae.iso = ICAM_EXPOSURE_ISO_AUTO; |
| |
| #ifdef HARDWARE_OMX |
| |
| mExifParams.iso = EXIF_ISO_AUTO; |
| |
| #endif |
| |
| } |
| } else { |
| |
| fobj->settings.ae.iso = ICAM_EXPOSURE_ISO_AUTO; |
| |
| #ifdef HARDWARE_OMX |
| |
| mExifParams.iso = EXIF_ISO_AUTO; |
| |
| #endif |
| |
| } |
| |
| if ( params.get(KEY_EXPOSURE_MODE) != NULL ) { |
| if (strcmp(params.get(KEY_EXPOSURE_MODE), (const char *) EXPOSURE_AUTO ) == 0) { |
| |
| fobj->settings.ae.mode = ICAM_EXPOSURE_MODE_EXP_AUTO; |
| |
| } else if (strcmp(params.get(KEY_EXPOSURE_MODE), (const char *) EXPOSURE_MACRO ) == 0) { |
| |
| fobj->settings.ae.mode = ICAM_EXPOSURE_MODE_EXP_MACRO; |
| |
| } else if (strcmp(params.get(KEY_EXPOSURE_MODE), (const char *) EXPOSURE_PORTRAIT ) == 0) { |
| |
| fobj->settings.ae.mode = ICAM_EXPOSURE_MODE_EXP_PORTRAIT; |
| |
| } else if (strcmp(params.get(KEY_EXPOSURE_MODE), (const char *) EXPOSURE_LANDSCAPE ) == 0) { |
| |
| fobj->settings.ae.mode = ICAM_EXPOSURE_MODE_EXP_LANDSCAPE; |
| |
| } else if (strcmp(params.get(KEY_EXPOSURE_MODE), (const char *) EXPOSURE_SPORTS ) == 0) { |
| |
| fobj->settings.ae.mode = ICAM_EXPOSURE_MODE_EXP_SPORTS; |
| |
| } else if (strcmp(params.get(KEY_EXPOSURE_MODE), (const char *) EXPOSURE_NIGHT ) == 0) { |
| |
| fobj->settings.ae.mode = ICAM_EXPOSURE_MODE_EXP_NIGHT; |
| |
| } else if (strcmp(params.get(KEY_EXPOSURE_MODE), (const char *) EXPOSURE_NIGHT_PORTRAIT ) == 0) { |
| |
| fobj->settings.ae.mode = ICAM_EXPOSURE_MODE_EXP_NIGHT_PORTRAIT; |
| |
| } else if (strcmp(params.get(KEY_EXPOSURE_MODE), (const char *) EXPOSURE_BACKLIGHTING ) == 0) { |
| |
| fobj->settings.ae.mode = ICAM_EXPOSURE_MODE_EXP_BACKLIGHTING; |
| |
| } else if (strcmp(params.get(KEY_EXPOSURE_MODE), (const char *) EXPOSURE_MANUAL ) == 0) { |
| |
| fobj->settings.ae.mode = ICAM_EXPOSURE_MODE_EXP_MANUAL; |
| |
| } else if (strcmp(params.get(KEY_EXPOSURE_MODE), (const char *) EXPOSURE_VERYLONG ) == 0) { |
| |
| fobj->settings.ae.mode = ICAM_EXPOSURE_MODE_EXP_VERYLONG; |
| |
| } else { |
| |
| fobj->settings.ae.mode = ICAM_EXPOSURE_MODE_EXP_AUTO; |
| |
| } |
| } else { |
| |
| fobj->settings.ae.mode = ICAM_EXPOSURE_MODE_EXP_AUTO; |
| |
| } |
| |
| compensation = mParameters.getInt(CameraParameters::KEY_EXPOSURE_COMPENSATION); |
| saturation = mParameters.getInt(KEY_SATURATION); |
| sharpness = mParameters.getInt(KEY_SHARPNESS); |
| contrast = mParameters.getInt(KEY_CONTRAST); |
| brightness = mParameters.getInt(KEY_BRIGHTNESS); |
| caf = mParameters.getInt(KEY_CAF); |
| |
| if(contrast != -1) { |
| contrast -= CONTRAST_OFFSET; |
| fobj->settings.general.contrast = contrast; |
| } |
| |
| if(brightness != -1) { |
| brightness -= BRIGHTNESS_OFFSET; |
| fobj->settings.general.brightness = brightness; |
| LOGE("Brightness passed to 3A %d", brightness); |
| } |
| |
| if(saturation!= -1) { |
| saturation -= SATURATION_OFFSET; |
| fobj->settings.general.saturation = saturation; |
| LOGE("Saturation passed to 3A %d", saturation); |
| } |
| if(sharpness != -1) |
| fobj->settings.general.sharpness = sharpness; |
| |
| fobj->settings.ae.compensation = compensation; |
| |
| FW3A_SetSettings(); |
| |
| if(mParameters.getInt(KEY_ROTATION_TYPE) == ROTATION_EXIF) { |
| mExifParams.rotation = rotation; |
| rotation = 0; // reset rotation so encoder doesn't not perform any rotation |
| } else { |
| mExifParams.rotation = -1; |
| } |
| |
| if ((caf != -1) && (mcaf != caf)){ |
| mcaf = caf; |
| Message msg; |
| msg.command = mcaf ? PREVIEW_CAF_START : PREVIEW_CAF_STOP; |
| previewThreadCommandQ.put(&msg); |
| //unlock in order to read the message correctly |
| mLock.unlock(); |
| previewThreadAckQ.get(&msg); |
| return msg.command == PREVIEW_ACK ? NO_ERROR : INVALID_OPERATION; |
| } |
| } |
| |
| #endif |
| |
| LOG_FUNCTION_NAME_EXIT |
| return NO_ERROR; |
| } |
| |
| CameraParameters CameraHal::getParameters() const |
| { |
| CameraParameters params; |
| |
| LOG_FUNCTION_NAME |
| |
| { |
| Mutex::Autolock lock(mLock); |
| params = mParameters; |
| } |
| |
| #ifdef FW3A |
| |
| //check if fobj is created in order to get settings from 3AFW |
| if ( NULL != fobj ) { |
| |
| if( FW3A_GetSettings() < 0 ) { |
| LOGE("ERROR FW3A_GetSettings()"); |
| goto exit; |
| } |
| |
| switch ( fobj->settings.general.scene ) { |
| case ICAM_SCENE_MODE_MANUAL: |
| params.set(CameraParameters::KEY_SCENE_MODE, CameraParameters::SCENE_MODE_AUTO); |
| break; |
| case ICAM_SCENE_MODE_PORTRAIT: |
| params.set(CameraParameters::KEY_SCENE_MODE, CameraParameters::SCENE_MODE_PORTRAIT); |
| break; |
| case ICAM_SCENE_MODE_LANDSCAPE: |
| params.set(CameraParameters::KEY_SCENE_MODE, CameraParameters::SCENE_MODE_LANDSCAPE); |
| break; |
| case ICAM_SCENE_MODE_NIGHT: |
| params.set(CameraParameters::KEY_SCENE_MODE, CameraParameters::SCENE_MODE_NIGHT); |
| break; |
| case ICAM_SCENE_MODE_FIREWORKS: |
| params.set(CameraParameters::KEY_SCENE_MODE, CameraParameters::SCENE_MODE_FIREWORKS); |
| break; |
| case ICAM_SCENE_MODE_SPORT: |
| params.set(CameraParameters::KEY_SCENE_MODE, CameraParameters::SCENE_MODE_ACTION); |
| break; |
| //TODO: Extend support for those |
| case ICAM_SCENE_MODE_CLOSEUP: |
| break; |
| case ICAM_SCENE_MODE_UNDERWATER: |
| break; |
| case ICAM_SCENE_MODE_SNOW_BEACH: |
| params.set(CameraParameters::KEY_SCENE_MODE, CameraParameters::SCENE_MODE_SNOW); |
| break; |
| case ICAM_SCENE_MODE_MOOD: |
| break; |
| case ICAM_SCENE_MODE_NIGHT_INDOOR: |
| break; |
| case ICAM_SCENE_MODE_NIGHT_PORTRAIT: |
| params.set(CameraParameters::KEY_SCENE_MODE, CameraParameters::SCENE_MODE_NIGHT_PORTRAIT); |
| break; |
| case ICAM_SCENE_MODE_INDOOR: |
| break; |
| case ICAM_SCENE_MODE_AUTO: |
| break; |
| }; |
| |
| switch ( fobj->settings.ae.mode ) { |
| case ICAM_EXPOSURE_MODE_EXP_AUTO: |
| params.set(KEY_EXPOSURE_MODE, EXPOSURE_AUTO); |
| break; |
| case ICAM_EXPOSURE_MODE_EXP_MACRO: |
| params.set(KEY_EXPOSURE_MODE, EXPOSURE_MACRO); |
| break; |
| case ICAM_EXPOSURE_MODE_EXP_PORTRAIT: |
| params.set(KEY_EXPOSURE_MODE, EXPOSURE_PORTRAIT); |
| break; |
| case ICAM_EXPOSURE_MODE_EXP_LANDSCAPE: |
| params.set(KEY_EXPOSURE_MODE, EXPOSURE_LANDSCAPE); |
| break; |
| case ICAM_EXPOSURE_MODE_EXP_SPORTS: |
| params.set(KEY_EXPOSURE_MODE, EXPOSURE_SPORTS); |
| break; |
| case ICAM_EXPOSURE_MODE_EXP_NIGHT: |
| params.set(KEY_EXPOSURE_MODE, EXPOSURE_NIGHT); |
| break; |
| case ICAM_EXPOSURE_MODE_EXP_NIGHT_PORTRAIT: |
| params.set(KEY_EXPOSURE_MODE, EXPOSURE_NIGHT_PORTRAIT); |
| break; |
| case ICAM_EXPOSURE_MODE_EXP_BACKLIGHTING: |
| params.set(KEY_EXPOSURE_MODE, EXPOSURE_BACKLIGHTING); |
| break; |
| case ICAM_EXPOSURE_MODE_EXP_MANUAL: |
| params.set(KEY_EXPOSURE_MODE, EXPOSURE_MANUAL); |
| break; |
| case ICAM_EXPOSURE_MODE_EXP_VERYLONG: |
| params.set(KEY_EXPOSURE_MODE, EXPOSURE_VERYLONG); |
| break; |
| }; |
| |
| switch ( fobj->settings.ae.iso ) { |
| case ICAM_EXPOSURE_ISO_AUTO: |
| params.set(KEY_ISO, ISO_AUTO); |
| break; |
| case ICAM_EXPOSURE_ISO_100: |
| params.set(KEY_ISO, ISO_100); |
| break; |
| case ICAM_EXPOSURE_ISO_200: |
| params.set(KEY_ISO, ISO_200); |
| break; |
| case ICAM_EXPOSURE_ISO_400: |
| params.set(KEY_ISO, ISO_400); |
| break; |
| case ICAM_EXPOSURE_ISO_800: |
| params.set(KEY_ISO, ISO_800); |
| break; |
| case ICAM_EXPOSURE_ISO_1000: |
| params.set(KEY_ISO, ISO_1000); |
| break; |
| case ICAM_EXPOSURE_ISO_1200: |
| params.set(KEY_ISO, ISO_1200); |
| break; |
| case ICAM_EXPOSURE_ISO_1600: |
| params.set(KEY_ISO, ISO_1600); |
| break; |
| }; |
| |
| switch ( fobj->settings.af.focus_mode ) { |
| case ICAM_FOCUS_MODE_AF_AUTO: |
| params.set(CameraParameters::KEY_FOCUS_MODE, CameraParameters::FOCUS_MODE_AUTO); |
| break; |
| case ICAM_FOCUS_MODE_AF_INFINY: |
| params.set(CameraParameters::KEY_FOCUS_MODE, CameraParameters::FOCUS_MODE_INFINITY); |
| break; |
| case ICAM_FOCUS_MODE_AF_MACRO: |
| params.set(CameraParameters::KEY_FOCUS_MODE, CameraParameters::FOCUS_MODE_MACRO); |
| break; |
| case ICAM_FOCUS_MODE_AF_MANUAL: |
| params.set(CameraParameters::KEY_FOCUS_MODE, CameraParameters::FOCUS_MODE_FIXED); |
| break; |
| //TODO: Extend support for those |
| case ICAM_FOCUS_MODE_AF_CONTINUOUS: |
| break; |
| case ICAM_FOCUS_MODE_AF_CONTINUOUS_NORMAL: |
| break; |
| case ICAM_FOCUS_MODE_AF_PORTRAIT: |
| break; |
| case ICAM_FOCUS_MODE_AF_HYPERFOCAL: |
| break; |
| case ICAM_FOCUS_MODE_AF_EXTENDED: |
| break; |
| case ICAM_FOCUS_MODE_AF_CONTINUOUS_EXTENDED: |
| break; |
| }; |
| |
| switch ( fobj->settings.general.flicker_avoidance ) { |
| case ICAM_FLICKER_AVOIDANCE_50HZ: |
| params.set(CameraParameters::KEY_ANTIBANDING, CameraParameters::ANTIBANDING_50HZ); |
| break; |
| case ICAM_FLICKER_AVOIDANCE_60HZ: |
| params.set(CameraParameters::KEY_ANTIBANDING, CameraParameters::ANTIBANDING_60HZ); |
| break; |
| case ICAM_FLICKER_AVOIDANCE_NO: |
| params.set(CameraParameters::KEY_ANTIBANDING, CameraParameters::ANTIBANDING_OFF); |
| break; |
| }; |
| |
| switch ( fobj->settings.general.effects ) { |
| case ICAM_EFFECT_EMBOSS: |
| params.set(CameraParameters::KEY_EFFECT, EFFECT_EMBOSS); |
| break; |
| case ICAM_EFFECT_COOL: |
| params.set(CameraParameters::KEY_EFFECT, EFFECT_COOL); |
| break; |
| case ICAM_EFFECT_BLACKBOARD: |
| params.set(CameraParameters::KEY_EFFECT, CameraParameters::EFFECT_BLACKBOARD); |
| break; |
| case ICAM_EFFECT_WHITEBOARD: |
| params.set(CameraParameters::KEY_EFFECT, CameraParameters::EFFECT_WHITEBOARD); |
| break; |
| case ICAM_EFFECT_SEPIA: |
| params.set(CameraParameters::KEY_EFFECT, CameraParameters::EFFECT_SEPIA); |
| break; |
| case ICAM_EFFECT_SOLARIZE: |
| params.set(CameraParameters::KEY_EFFECT, CameraParameters::EFFECT_SOLARIZE); |
| break; |
| case ICAM_EFFECT_NEGATIVE: |
| params.set(CameraParameters::KEY_EFFECT, CameraParameters::EFFECT_NEGATIVE); |
| break; |
| case ICAM_EFFECT_GRAYSCALE: |
| params.set(CameraParameters::KEY_EFFECT, CameraParameters::EFFECT_MONO); |
| break; |
| case ICAM_EFFECT_NORMAL: |
| params.set(CameraParameters::KEY_EFFECT, CameraParameters::EFFECT_NONE); |
| break; |
| //TODO: Add support for those |
| case ICAM_EFFECT_NATURAL: |
| break; |
| case ICAM_EFFECT_VIVID: |
| break; |
| case ICAM_EFFECT_COLORSWAP: |
| break; |
| case ICAM_EFFECT_OUT_OF_FOCUS: |
| break; |
| case ICAM_EFFECT_NEGATIVE_SEPIA: |
| break; |
| }; |
| |
| switch ( fobj->settings.awb.mode ) { |
| case ICAM_WHITE_BALANCE_MODE_WB_SHADOW: |
| params.set(CameraParameters::KEY_WHITE_BALANCE, CameraParameters::WHITE_BALANCE_SHADE); |
| break; |
| case ICAM_WHITE_BALANCE_MODE_WB_CLOUDY: |
| params.set(CameraParameters::KEY_WHITE_BALANCE, CameraParameters::WHITE_BALANCE_CLOUDY_DAYLIGHT); |
| break; |
| case ICAM_WHITE_BALANCE_MODE_WB_DAYLIGHT: |
| params.set(CameraParameters::KEY_WHITE_BALANCE, CameraParameters::WHITE_BALANCE_DAYLIGHT); |
| break; |
| case ICAM_WHITE_BALANCE_MODE_WB_FLUORESCENT: |
| params.set(CameraParameters::KEY_WHITE_BALANCE, CameraParameters::WHITE_BALANCE_FLUORESCENT); |
| break; |
| case ICAM_WHITE_BALANCE_MODE_WB_INCANDESCENT: |
| params.set(CameraParameters::KEY_WHITE_BALANCE, CameraParameters::WHITE_BALANCE_INCANDESCENT); |
| break; |
| case ICAM_WHITE_BALANCE_MODE_WB_AUTO: |
| params.set(CameraParameters::KEY_WHITE_BALANCE, CameraParameters::WHITE_BALANCE_AUTO); |
| break; |
| case ICAM_WHITE_BALANCE_MODE_WB_HORIZON: |
| params.set(CameraParameters::KEY_WHITE_BALANCE, WHITE_BALANCE_HORIZON); |
| break; |
| //TODO: Extend support for those |
| case ICAM_WHITE_BALANCE_MODE_WB_MANUAL: |
| break; |
| case ICAM_WHITE_BALANCE_MODE_WB_TUNGSTEN: |
| params.set(CameraParameters::KEY_WHITE_BALANCE, WHITE_BALANCE_TUNGSTEN); |
| break; |
| case ICAM_WHITE_BALANCE_MODE_WB_OFFICE: |
| break; |
| case ICAM_WHITE_BALANCE_MODE_WB_FLASH: |
| break; |
| }; |
| |
| switch ( fobj->settings.ae.spot_weighting ) { |
| case ICAM_EXPOSURE_SPOT_NORMAL: |
| params.set(KEY_METER_MODE, METER_MODE_AVERAGE); |
| break; |
| case ICAM_EXPOSURE_SPOT_CENTER: |
| params.set(KEY_METER_MODE, METER_MODE_CENTER); |
| break; |
| //TODO: support this also |
| case ICAM_EXPOSURE_SPOT_WIDE: |
| break; |
| }; |
| |
| params.set(CameraParameters::KEY_EXPOSURE_COMPENSATION, fobj->settings.ae.compensation); |
| params.set(KEY_SATURATION, ( fobj->settings.general.saturation + SATURATION_OFFSET )); |
| params.set(KEY_SHARPNESS, fobj->settings.general.sharpness); |
| params.set(KEY_CONTRAST, ( fobj->settings.general.contrast + CONTRAST_OFFSET )); |
| params.set(KEY_BRIGHTNESS, ( fobj->settings.general.brightness + BRIGHTNESS_OFFSET )); |
| params.setPreviewFrameRate(fobj->settings.ae.framerate); |
| } |
| #endif |
| |
| exit: |
| |
| LOG_FUNCTION_NAME_EXIT |
| |
| return params; |
| } |
| |
| status_t CameraHal::dump(int fd, const Vector<String16>& args) const |
| { |
| return 0; |
| } |
| |
| void CameraHal::dumpFrame(void *buffer, int size, char *path) |
| { |
| FILE* fIn = NULL; |
| |
| fIn = fopen(path, "w"); |
| if ( fIn == NULL ) { |
| LOGE("\n\n\n\nError: failed to open the file %s for writing\n\n\n\n", path); |
| return; |
| } |
| |
| fwrite((void *)buffer, 1, size, fIn); |
| fclose(fIn); |
| |
| } |
| |
| void CameraHal::release() |
| { |
| } |
| |
| #ifdef FW3A |
| |
| void CameraHal::onIPP(void *priv, icap_ipp_parameters_t *ipp_params) |
| { |
| CameraHal* camHal = reinterpret_cast<CameraHal*>(priv); |
| |
| LOG_FUNCTION_NAME |
| |
| #ifdef IMAGE_PROCESSING_PIPELINE |
| |
| if ( ipp_params->type == ICAP_IPP_PARAMETERS_VER1_9 ) { |
| camHal->mIPPParams.EdgeEnhancementStrength = ipp_params->ipp19.EdgeEnhancementStrength; |
| camHal->mIPPParams.WeakEdgeThreshold = ipp_params->ipp19.WeakEdgeThreshold; |
| camHal->mIPPParams.StrongEdgeThreshold = ipp_params->ipp19.StrongEdgeThreshold; |
| camHal->mIPPParams.LowFreqLumaNoiseFilterStrength = ipp_params->ipp19.LowFreqLumaNoiseFilterStrength; |
| camHal->mIPPParams.MidFreqLumaNoiseFilterStrength = ipp_params->ipp19.MidFreqLumaNoiseFilterStrength; |
| camHal->mIPPParams.HighFreqLumaNoiseFilterStrength = ipp_params->ipp19.HighFreqLumaNoiseFilterStrength; |
| camHal->mIPPParams.LowFreqCbNoiseFilterStrength = ipp_params->ipp19.LowFreqCbNoiseFilterStrength; |
| camHal->mIPPParams.MidFreqCbNoiseFilterStrength = ipp_params->ipp19.MidFreqCbNoiseFilterStrength; |
| camHal->mIPPParams.HighFreqCbNoiseFilterStrength = ipp_params->ipp19.HighFreqCbNoiseFilterStrength; |
| camHal->mIPPParams.LowFreqCrNoiseFilterStrength = ipp_params->ipp19.LowFreqCrNoiseFilterStrength; |
| camHal->mIPPParams.MidFreqCrNoiseFilterStrength = ipp_params->ipp19.MidFreqCrNoiseFilterStrength; |
| camHal->mIPPParams.HighFreqCrNoiseFilterStrength = ipp_params->ipp19.HighFreqCrNoiseFilterStrength; |
| camHal->mIPPParams.shadingVertParam1 = ipp_params->ipp19.shadingVertParam1; |
| camHal->mIPPParams.shadingVertParam2 = ipp_params->ipp19.shadingVertParam2; |
| camHal->mIPPParams.shadingHorzParam1 = ipp_params->ipp19.shadingHorzParam1; |
| camHal->mIPPParams.shadingHorzParam2 = ipp_params->ipp19.shadingHorzParam2; |
| camHal->mIPPParams.shadingGainScale = ipp_params->ipp19.shadingGainScale; |
| camHal->mIPPParams.shadingGainOffset = ipp_params->ipp19.shadingGainOffset; |
| camHal->mIPPParams.shadingGainMaxValue = ipp_params->ipp19.shadingGainMaxValue; |
| camHal->mIPPParams.ratioDownsampleCbCr = ipp_params->ipp19.ratioDownsampleCbCr; |
| } else if ( ipp_params->type == ICAP_IPP_PARAMETERS_VER1_8 ) { |
| camHal->mIPPParams.EdgeEnhancementStrength = ipp_params->ipp18.ee_q; |
| camHal->mIPPParams.WeakEdgeThreshold = ipp_params->ipp18.ew_ts; |
| camHal->mIPPParams.StrongEdgeThreshold = ipp_params->ipp18.es_ts; |
| camHal->mIPPParams.LowFreqLumaNoiseFilterStrength = ipp_params->ipp18.luma_nf; |
| camHal->mIPPParams.MidFreqLumaNoiseFilterStrength = ipp_params->ipp18.luma_nf; |
| camHal->mIPPParams.HighFreqLumaNoiseFilterStrength = ipp_params->ipp18.luma_nf; |
| camHal->mIPPParams.LowFreqCbNoiseFilterStrength = ipp_params->ipp18.chroma_nf; |
| camHal->mIPPParams.MidFreqCbNoiseFilterStrength = ipp_params->ipp18.chroma_nf; |
| camHal->mIPPParams.HighFreqCbNoiseFilterStrength = ipp_params->ipp18.chroma_nf; |
| camHal->mIPPParams.LowFreqCrNoiseFilterStrength = ipp_params->ipp18.chroma_nf; |
| camHal->mIPPParams.MidFreqCrNoiseFilterStrength = ipp_params->ipp18.chroma_nf; |
| camHal->mIPPParams.HighFreqCrNoiseFilterStrength = ipp_params->ipp18.chroma_nf; |
| camHal->mIPPParams.shadingVertParam1 = -1; |
| camHal->mIPPParams.shadingVertParam2 = -1; |
| camHal->mIPPParams.shadingHorzParam1 = -1; |
| camHal->mIPPParams.shadingHorzParam2 = -1; |
| camHal->mIPPParams.shadingGainScale = -1; |
| camHal->mIPPParams.shadingGainOffset = -1; |
| camHal->mIPPParams.shadingGainMaxValue = -1; |
| camHal->mIPPParams.ratioDownsampleCbCr = -1; |
| } else { |
| camHal->mIPPParams.EdgeEnhancementStrength = 220; |
| camHal->mIPPParams.WeakEdgeThreshold = 8; |
| camHal->mIPPParams.StrongEdgeThreshold = 200; |
| camHal->mIPPParams.LowFreqLumaNoiseFilterStrength = 5; |
| camHal->mIPPParams.MidFreqLumaNoiseFilterStrength = 10; |
| camHal->mIPPParams.HighFreqLumaNoiseFilterStrength = 15; |
| camHal->mIPPParams.LowFreqCbNoiseFilterStrength = 20; |
| camHal->mIPPParams.MidFreqCbNoiseFilterStrength = 30; |
| camHal->mIPPParams.HighFreqCbNoiseFilterStrength = 10; |
| camHal->mIPPParams.LowFreqCrNoiseFilterStrength = 10; |
| camHal->mIPPParams.MidFreqCrNoiseFilterStrength = 25; |
| camHal->mIPPParams.HighFreqCrNoiseFilterStrength = 15; |
| camHal->mIPPParams.shadingVertParam1 = 10; |
| camHal->mIPPParams.shadingVertParam2 = 400; |
| camHal->mIPPParams.shadingHorzParam1 = 10; |
| camHal->mIPPParams.shadingHorzParam2 = 400; |
| camHal->mIPPParams.shadingGainScale = 128; |
| camHal->mIPPParams.shadingGainOffset = 2048; |
| camHal->mIPPParams.shadingGainMaxValue = 16384; |
| camHal->mIPPParams.ratioDownsampleCbCr = 1; |
| } |
| |
| #endif |
| |
| LOG_FUNCTION_NAME_EXIT |
| } |
| |
| void CameraHal::onGeneratedSnapshot(void *priv, icap_image_buffer_t *buf) |
| { |
| unsigned int snapshotMessage[1]; |
| |
| CameraHal* camHal = reinterpret_cast<CameraHal*>(priv); |
| |
| LOG_FUNCTION_NAME |
| |
| snapshotMessage[0] = SNAPSHOT_THREAD_START_GEN; |
| write(camHal->snapshotPipe[1], &snapshotMessage, sizeof(snapshotMessage)); |
| |
| LOG_FUNCTION_NAME_EXIT |
| } |
| |
| void CameraHal::onSnapshot(void *priv, icap_image_buffer_t *buf) |
| { |
| unsigned int snapshotMessage[9]; |
| |
| CameraHal* camHal = reinterpret_cast<CameraHal*>(priv); |
| |
| LOG_FUNCTION_NAME |
| |
| snapshotMessage[0] = SNAPSHOT_THREAD_START; |
| snapshotMessage[1] = (unsigned int) buf->buffer.buffer; |
| snapshotMessage[2] = buf->width; |
| snapshotMessage[3] = buf->height; |
| snapshotMessage[4] = camHal->mZoomTargetIdx; |
| snapshotMessage[5] = camHal->mImageCropLeft; |
| snapshotMessage[6] = camHal->mImageCropTop; |
| snapshotMessage[7] = camHal->mImageCropWidth; |
| snapshotMessage[8] = camHal->mImageCropHeight; |
| |
| write(camHal->snapshotPipe[1], &snapshotMessage, sizeof(snapshotMessage)); |
| |
| LOG_FUNCTION_NAME_EXIT |
| } |
| |
| void CameraHal::onShutter(void *priv, icap_image_buffer_t *image_buf) |
| { |
| LOG_FUNCTION_NAME |
| |
| unsigned int shutterMessage[3]; |
| |
| CameraHal* camHal = reinterpret_cast<CameraHal*>(priv); |
| |
| if( ( camHal->msgTypeEnabled(CAMERA_MSG_SHUTTER) ) && (camHal->mShutterEnable) ) { |
| |
| #ifdef DEBUG_LOG |
| |
| camHal->PPM("SENDING MESSAGE TO SHUTTER THREAD"); |
| |
| #endif |
| |
| shutterMessage[0] = SHUTTER_THREAD_CALL; |
| shutterMessage[1] = (unsigned int) camHal->mNotifyCb; |
| shutterMessage[2] = (unsigned int) camHal->mCallbackCookie; |
| write(camHal->shutterPipe[1], &shutterMessage, sizeof(shutterMessage)); |
| } |
| |
| LOG_FUNCTION_NAME_EXIT |
| } |
| |
| void CameraHal::onCrop(void *priv, icap_crop_rect_t *crop_rect) |
| { |
| LOG_FUNCTION_NAME |
| |
| CameraHal *camHal = reinterpret_cast<CameraHal *> (priv); |
| |
| camHal->mImageCropTop = crop_rect->top; |
| camHal->mImageCropLeft = crop_rect->left; |
| camHal->mImageCropWidth = crop_rect->width; |
| camHal->mImageCropHeight = crop_rect->height; |
| |
| LOG_FUNCTION_NAME_EXIT |
| } |
| |
| void CameraHal::onMakernote(void *priv, void *mknote_ptr) |
| { |
| LOG_FUNCTION_NAME |
| |
| CameraHal *camHal = reinterpret_cast<CameraHal *>(priv); |
| SICam_MakerNote *makerNote = reinterpret_cast<SICam_MakerNote *>(mknote_ptr); |
| |
| #ifdef DUMP_MAKERNOTE |
| |
| camHal->SaveFile(NULL, (char*)"mnt", makerNote->buffer, makerNote->filled_size); |
| |
| #endif |
| |
| LOG_FUNCTION_NAME_EXIT |
| } |
| |
| void CameraHal::onSaveH3A(void *priv, icap_image_buffer_t *buf) |
| { |
| CameraHal* camHal = reinterpret_cast<CameraHal*>(priv); |
| |
| LOGD("Observer onSaveH3A\n"); |
| camHal->SaveFile(NULL, (char*)"h3a", buf->buffer.buffer, buf->buffer.filled_size); |
| } |
| |
| void CameraHal::onSaveLSC(void *priv, icap_image_buffer_t *buf) |
| { |
| CameraHal* camHal = reinterpret_cast<CameraHal*>(priv); |
| |
| LOGD("Observer onSaveLSC\n"); |
| camHal->SaveFile(NULL, (char*)"lsc", buf->buffer.buffer, buf->buffer.filled_size); |
| } |
| |
| void CameraHal::onSaveRAW(void *priv, icap_image_buffer_t *buf) |
| { |
| CameraHal* camHal = reinterpret_cast<CameraHal*>(priv); |
| |
| LOGD("Observer onSaveRAW\n"); |
| camHal->SaveFile(NULL, (char*)"raw", buf->buffer.buffer, buf->buffer.filled_size); |
| } |
| |
| #endif |
| |
| int CameraHal::SaveFile(char *filename, char *ext, void *buffer, int size) |
| { |
| LOG_FUNCTION_NAME |
| //Store image |
| char fn [512]; |
| |
| if (filename) { |
| strcpy(fn,filename); |
| } else { |
| if (ext==NULL) ext = (char*)"tmp"; |
| sprintf(fn, PHOTO_PATH, file_index, ext); |
| } |
| file_index++; |
| LOGD("Writing to file: %s", fn); |
| int fd = open(fn, O_RDWR | O_CREAT | O_SYNC); |
| if (fd < 0) { |
| LOGE("Cannot open file %s : %s", fn, strerror(errno)); |
| return -1; |
| } else { |
| |
| int written = 0; |
| int page_block, page = 0; |
| int cnt = 0; |
| int nw; |
| char *wr_buff = (char*)buffer; |
| LOGD("Jpeg size %d buffer 0x%x", size, ( unsigned int ) buffer); |
| page_block = size / 20; |
| while (written < size ) { |
| nw = size - written; |
| nw = (nw>512*1024)?8*1024:nw; |
| |
| nw = ::write(fd, wr_buff, nw); |
| if (nw<0) { |
| LOGD("write fail nw=%d, %s", nw, strerror(errno)); |
| break; |
| } |
| wr_buff += nw; |
| written += nw; |
| cnt++; |
| |
| page += nw; |
| if (page>=page_block){ |
| page = 0; |
| LOGD("Percent %6.2f, wn=%5d, total=%8d, jpeg_size=%8d", |
| ((float)written)/size, nw, written, size); |
| } |
| } |
| |
| close(fd); |
| |
| return 0; |
| } |
| } |
| |
| |
| sp<IMemoryHeap> CameraHal::getPreviewHeap() const |
| { |
| LOG_FUNCTION_NAME |
| return 0; |
| } |
| |
| sp<CameraHardwareInterface> CameraHal::createInstance() |
| { |
| LOG_FUNCTION_NAME |
| |
| if (singleton != 0) { |
| sp<CameraHardwareInterface> hardware = singleton.promote(); |
| if (hardware != 0) { |
| return hardware; |
| } |
| } |
| |
| sp<CameraHardwareInterface> hardware(new CameraHal()); |
| |
| singleton = hardware; |
| return hardware; |
| } |
| |
| /*--------------------Eclair HAL---------------------------------------*/ |
| void CameraHal::setCallbacks(notify_callback notify_cb, |
| data_callback data_cb, |
| data_callback_timestamp data_cb_timestamp, |
| void* user) |
| { |
| Mutex::Autolock lock(mLock); |
| mNotifyCb = notify_cb; |
| mDataCb = data_cb; |
| mDataCbTimestamp = data_cb_timestamp; |
| mCallbackCookie = user; |
| } |
| |
| void CameraHal::enableMsgType(int32_t msgType) |
| { |
| Mutex::Autolock lock(mLock); |
| mMsgEnabled |= msgType; |
| } |
| |
| void CameraHal::disableMsgType(int32_t msgType) |
| { |
| Mutex::Autolock lock(mLock); |
| mMsgEnabled &= ~msgType; |
| } |
| |
| bool CameraHal::msgTypeEnabled(int32_t msgType) |
| { |
| Mutex::Autolock lock(mLock); |
| return (mMsgEnabled & msgType); |
| } |
| |
| status_t CameraHal::cancelAutoFocus() |
| { |
| return NO_ERROR; |
| } |
| |
| /*--------------------Eclair HAL---------------------------------------*/ |
| |
| status_t CameraHal::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) |
| { |
| Message msg; |
| status_t ret = NO_ERROR; |
| |
| LOG_FUNCTION_NAME |
| |
| switch(cmd) { |
| case CAMERA_CMD_START_SMOOTH_ZOOM: |
| msg.command = START_SMOOTH_ZOOM; |
| msg.arg1 = ( void * ) arg1; |
| previewThreadCommandQ.put(&msg); |
| previewThreadAckQ.get(&msg); |
| |
| if ( PREVIEW_ACK != msg.command ) { |
| ret = -EINVAL; |
| } |
| |
| break; |
| case CAMERA_CMD_STOP_SMOOTH_ZOOM: |
| msg.command = STOP_SMOOTH_ZOOM; |
| previewThreadCommandQ.put(&msg); |
| previewThreadAckQ.get(&msg); |
| |
| if ( PREVIEW_ACK != msg.command ) { |
| ret = -EINVAL; |
| } |
| |
| break; |
| default: |
| break; |
| }; |
| |
| LOG_FUNCTION_NAME_EXIT |
| |
| return ret; |
| } |
| |
| |
| extern "C" sp<CameraHardwareInterface> openCameraHardware() |
| { |
| LOGD("opening ti camera hal\n"); |
| return CameraHal::createInstance(); |
| } |
| |
| |
| }; // namespace android |
| |