| |
| /* |
| ** Copyright 2008, Google Inc. |
| ** Copyright (c) 2011-2012 The Linux Foundation. All rights reserved. |
| ** |
| ** Licensed under the Apache License, Version 2.0 (the "License"); |
| ** you may not use this file except in compliance with the License. |
| ** You may obtain a copy of the License at |
| ** |
| ** http://www.apache.org/licenses/LICENSE-2.0 |
| ** |
| ** Unless required by applicable law or agreed to in writing, software |
| ** distributed under the License is distributed on an "AS IS" BASIS, |
| ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| ** See the License for the specific language governing permissions and |
| ** limitations under the License. |
| */ |
| |
| #define ALOG_NDEBUG 0 |
| #define ALOG_NIDEBUG 0 |
| #define LOG_TAG "QualcommCameraHardware" |
| #include <utils/Log.h> |
| #include "QualcommCameraHardware.h" |
| |
| #include <utils/Errors.h> |
| #include <utils/threads.h> |
| |
| #include <binder/MemoryHeapPmem.h> |
| #if 0 |
| #include <binder/MemoryHeapIon.h> |
| #endif |
| #include <camera/Camera.h> |
| #include <hardware/camera.h> |
| #include <utils/String16.h> |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| #include <unistd.h> |
| #include <fcntl.h> |
| #include <cutils/properties.h> |
| #include <math.h> |
| #include <linux/ioctl.h> |
| #include "QCameraParameters.h" |
| #include <media/mediarecorder.h> |
| #include <gralloc_priv.h> |
| #include <genlock.h> |
| |
| #include "linux/msm_mdp.h" |
| #include <linux/fb.h> |
| #define LIKELY(exp) __builtin_expect(!!(exp), 1) |
| #define UNLIKELY(exp) __builtin_expect(!!(exp), 0) |
| #define CAMERA_HAL_UNUSED(expr) do { (void)(expr); } while (0) |
| |
| extern "C" { |
| #include <fcntl.h> |
| #include <time.h> |
| #include <pthread.h> |
| #include <stdio.h> |
| #include <string.h> |
| #include <unistd.h> |
| #include <termios.h> |
| #include <assert.h> |
| #include <stdlib.h> |
| #include <ctype.h> |
| #include <signal.h> |
| #include <errno.h> |
| #include <sys/mman.h> |
| #include <sys/system_properties.h> |
| #include <sys/time.h> |
| #include <stdlib.h> |
| |
| |
| #include <camera.h> |
| #include <cam_fifo.h> |
| #include <liveshot.h> |
| #include <jpege.h> |
| #include <jpeg_encoder.h> |
| |
| #define DUMP_LIVESHOT_JPEG_FILE 0 |
| |
| #define DEFAULT_PICTURE_WIDTH 640 |
| #define DEFAULT_PICTURE_HEIGHT 480 |
| #define DEFAULT_PICTURE_WIDTH_3D 1920 |
| #define DEFAULT_PICTURE_HEIGHT_3D 1080 |
| #define INITIAL_PREVIEW_HEIGHT 144 |
| #define INITIAL_PREVIEW_WIDTH 176 |
| |
| #define THUMBNAIL_BUFFER_SIZE (THUMBNAIL_WIDTH * THUMBNAIL_HEIGHT * 3/2) |
| #define MAX_ZOOM_LEVEL 5 |
| #define NOT_FOUND -1 |
| // Number of video buffers held by kernal (initially 1,2 &3) |
| #define ACTIVE_VIDEO_BUFFERS 3 |
| #define ACTIVE_PREVIEW_BUFFERS 3 |
| #define ACTIVE_ZSL_BUFFERS 3 |
| #define APP_ORIENTATION 90 |
| #define HDR_HAL_FRAME 2 |
| |
| #define FLASH_AUTO 24 |
| #define FLASH_SNAP 32 |
| |
| #define DUMMY_CAMERA_STARTED 1; |
| #define DUMMY_CAMERA_STOPPED 0; |
| #define FLOOR16(X) ((X) & 0xFFF0) |
| #if DLOPEN_LIBMMCAMERA |
| #include <dlfcn.h> |
| |
| |
| // Conversion routines from YV420sp to YV12 format |
| int (*LINK_yuv_convert_ycrcb420sp_to_yv12_inplace) (yuv_image_type* yuvStructPtr); |
| int (*LINK_yuv_convert_ycrcb420sp_to_yv12) (yuv_image_type* yuvStructPtrin, yuv_image_type* yuvStructPtrout); |
| #define NUM_YV12_FRAMES 1 |
| #define FOCUS_AREA_INIT "(-1000,-1000,1000,1000,1000)" |
| |
| void *libmmcamera; |
| void* (*LINK_cam_conf)(void *data); |
| void* (*LINK_cam_frame)(void *data); |
| void* (*LINK_wait_cam_frame_thread_ready)(void); |
| void* (*LINK_cam_frame_set_exit_flag)(int flag); |
| bool (*LINK_jpeg_encoder_init)(); |
| void (*LINK_jpeg_encoder_join)(); |
| bool (*LINK_jpeg_encoder_encode)(const cam_ctrl_dimension_t *dimen, |
| const uint8_t *thumbnailbuf, int thumbnailfd, |
| const uint8_t *snapshotbuf, int snapshotfd, |
| common_crop_t *scaling_parms, exif_tags_info_t *exif_data, |
| int exif_table_numEntries, int jpegPadding, const int32_t cbcroffset,int zsl_enable); |
| void (*LINK_camframe_terminate)(void); |
| //for 720p |
| // Function pointer , called by camframe when a video frame is available. |
| void (**LINK_camframe_video_callback)(struct msm_frame * frame); |
| // Function to add a frame to free Q |
| void (*LINK_camframe_add_frame)(cam_frame_type_t type,struct msm_frame *frame); |
| |
| void (*LINK_camframe_release_all_frames)(cam_frame_type_t type); |
| |
| int8_t (*LINK_jpeg_encoder_setMainImageQuality)(uint32_t quality); |
| int8_t (*LINK_jpeg_encoder_setThumbnailQuality)(uint32_t quality); |
| int8_t (*LINK_jpeg_encoder_setRotation)(uint32_t rotation); |
| int8_t (*LINK_jpeg_encoder_get_buffer_offset)(uint32_t width, uint32_t height, |
| uint32_t* p_y_offset, |
| uint32_t* p_cbcr_offset, |
| uint32_t* p_buf_size); |
| int8_t (*LINK_jpeg_encoder_setLocation)(const camera_position_type *location); |
| void (*LINK_jpeg_encoder_set_3D_info)(cam_3d_frame_format_t format); |
| const struct camera_size_type *(*LINK_default_sensor_get_snapshot_sizes)(int *len); |
| int (*LINK_launch_cam_conf_thread)(void); |
| int (*LINK_release_cam_conf_thread)(void); |
| mm_camera_status_t (*LINK_mm_camera_init)(mm_camera_config *, mm_camera_notify*, mm_camera_ops*,uint8_t); |
| mm_camera_status_t (*LINK_mm_camera_deinit)(); |
| mm_camera_status_t (*LINK_mm_camera_destroy)(); |
| mm_camera_status_t (*LINK_mm_camera_exec)(); |
| mm_camera_status_t (*LINK_mm_camera_get_camera_info) (qcamera_info_t* p_cam_info, int* p_num_cameras); |
| |
| int8_t (*LINK_zoom_crop_upscale)(uint32_t width, uint32_t height, |
| uint32_t cropped_width, uint32_t cropped_height, uint8_t *img_buf); |
| |
| // callbacks |
| void (**LINK_mmcamera_shutter_callback)(common_crop_t *crop); |
| void (**LINK_cancel_liveshot)(void); |
| int8_t (*LINK_set_liveshot_params)(uint32_t a_width, uint32_t a_height, exif_tags_info_t *a_exif_data, |
| int a_exif_numEntries, uint8_t* a_out_buffer, uint32_t a_outbuffer_size); |
| void (*LINK_set_liveshot_frame)(struct msm_frame *liveshot_frame); |
| #else |
| #define LINK_cam_conf cam_conf |
| #define LINK_cam_frame cam_frame |
| #define LINK_wait_cam_frame_thread_ready wait_cam_frame_thread_ready |
| #define LINK_cam_frame cam_frame_set_exit_flag |
| #define LINK_jpeg_encoder_init jpeg_encoder_init |
| #define LINK_jpeg_encoder_join jpeg_encoder_join |
| #define LINK_jpeg_encoder_encode jpeg_encoder_encode |
| #define LINK_camframe_terminate camframe_terminate |
| #define LINK_jpeg_encoder_setMainImageQuality jpeg_encoder_setMainImageQuality |
| #define LINK_jpeg_encoder_setThumbnailQuality jpeg_encoder_setThumbnailQuality |
| #define LINK_jpeg_encoder_setRotation jpeg_encoder_setRotation |
| #define LINK_jpeg_encoder_get_buffer_offset jpeg_encoder_get_buffer_offset |
| #define LINK_jpeg_encoder_setLocation jpeg_encoder_setLocation |
| #define LINK_jpeg_encoder_set_3D_info jpeg_encoder_set_3D_info |
| #define LINK_default_sensor_get_snapshot_sizes default_sensor_get_snapshot_sizes |
| #define LINK_launch_cam_conf_thread launch_cam_conf_thread |
| #define LINK_release_cam_conf_thread release_cam_conf_thread |
| #define LINK_zoom_crop_upscale zoom_crop_upscale |
| #define LINK_mm_camera_init mm_camera_config_init |
| #define LINK_mm_camera_deinit mm_camera_config_deinit |
| #define LINK_mm_camera_destroy mm_camera_config_destroy |
| #define LINK_mm_camera_exec mm_camera_exec |
| #define LINK_camframe_add_frame camframe_add_frame |
| #define LINK_camframe_release_all_frames camframe_release_all_frames |
| #define LINK_mm_camera_get_camera_info mm_camera_get_camera_info |
| |
| extern void (*mmcamera_camframe_callback)(struct msm_frame *frame); |
| extern void (*mmcamera_camstats_callback)(camstats_type stype, camera_preview_histogram_info* histinfo); |
| extern void (*mmcamera_jpegfragment_callback)(uint8_t *buff_ptr, |
| uint32_t buff_size); |
| extern void (*mmcamera_jpeg_callback)(jpeg_event_t status); |
| extern void (*mmcamera_shutter_callback)(common_crop_t *crop); |
| extern void (*mmcamera_liveshot_callback)(liveshot_status status, uint32_t jpeg_size); |
| #define LINK_set_liveshot_params set_liveshot_params |
| #define LINK_set_liveshot_frame set_liveshot_frame |
| #endif |
| |
| } // extern "C" |
| |
| #ifndef HAVE_CAMERA_SIZE_TYPE |
| struct camera_size_type { |
| int width; |
| int height; |
| }; |
| #endif |
| #if 0 |
| typedef struct crop_info_struct { |
| int32_t x; |
| int32_t y; |
| int32_t w; |
| int32_t h; |
| } zoom_crop_info; |
| #endif |
| union zoomimage |
| { |
| char d[sizeof(struct mdp_blit_req_list) + sizeof(struct mdp_blit_req) * 1]; |
| struct mdp_blit_req_list list; |
| } zoomImage; |
| |
| //Default to VGA |
| #define DEFAULT_PREVIEW_WIDTH 640 |
| #define DEFAULT_PREVIEW_HEIGHT 480 |
| #define DEFAULT_PREVIEW_WIDTH_3D 1280 |
| #define DEFAULT_PREVIEW_HEIGHT_3D 720 |
| |
| //Default FPS |
| #define MINIMUM_FPS 5 |
| #define MAXIMUM_FPS 31 |
| #define DEFAULT_FPS MAXIMUM_FPS |
| #define DEFAULT_FIXED_FPS_VALUE 30 |
| /* |
| * Modifying preview size requires modification |
| * in bitmasks for boardproperties |
| */ |
| static uint32_t PREVIEW_SIZE_COUNT; |
| static uint32_t HFR_SIZE_COUNT; |
| |
| board_property boardProperties[] = { |
| {TARGET_MSM7625, 0x00000fff, false, false, false}, |
| {TARGET_MSM7625A, 0x00000fff, false, false, false}, |
| {TARGET_MSM7627, 0x000006ff, false, false, false}, |
| {TARGET_MSM7627A, 0x000006ff, false, false, false}, |
| {TARGET_MSM7630, 0x00000fff, true, true, false}, |
| {TARGET_MSM8660, 0x00001fff, true, true, false}, |
| {TARGET_QSD8250, 0x00000fff, false, false, false} |
| }; |
| |
| //static const camera_size_type* picture_sizes; |
| //static int PICTURE_SIZE_COUNT; |
| /* TODO |
| * Ideally this should be a populated by lower layers. |
| * But currently this is no API to do that at lower layer. |
| * Hence populating with default sizes for now. This needs |
| * to be changed once the API is supported. |
| */ |
| //sorted on column basis |
| static struct camera_size_type zsl_picture_sizes[] = { |
| { 1024, 768}, // 1MP XGA |
| { 800, 600}, //SVGA |
| { 800, 480}, // WVGA |
| { 640, 480}, // VGA |
| { 352, 288}, //CIF |
| { 320, 240}, // QVGA |
| { 176, 144} // QCIF |
| }; |
| |
| static struct camera_size_type for_3D_picture_sizes[] = { |
| { 1920, 1080}, |
| }; |
| |
| static int data_counter = 0; |
| static int sensor_rotation = 0; |
| static int record_flag = 0; |
| static camera_size_type* picture_sizes; |
| static camera_size_type* preview_sizes; |
| static camera_size_type* hfr_sizes; |
| static unsigned int PICTURE_SIZE_COUNT; |
| static const camera_size_type * picture_sizes_ptr; |
| static int supportedPictureSizesCount; |
| static liveshotState liveshot_state = LIVESHOT_DONE; |
| |
| #ifdef Q12 |
| #undef Q12 |
| #endif |
| |
| #define Q12 4096 |
| |
| static const target_map targetList [] = { |
| { "msm7625", TARGET_MSM7625 }, |
| { "msm7625a", TARGET_MSM7625A }, |
| { "msm7627", TARGET_MSM7627 }, |
| { "msm7627a", TARGET_MSM7627A }, |
| { "qsd8250", TARGET_QSD8250 }, |
| { "msm7630", TARGET_MSM7630 }, |
| { "msm8660", TARGET_MSM8660 } |
| |
| }; |
| static targetType mCurrentTarget = TARGET_MAX; |
| |
| typedef struct { |
| uint32_t aspect_ratio; |
| uint32_t width; |
| uint32_t height; |
| } thumbnail_size_type; |
| |
| static thumbnail_size_type thumbnail_sizes[] = { |
| { 7281, 512, 288 }, //1.777778 |
| { 6826, 480, 288 }, //1.666667 |
| { 6808, 256, 154 }, //1.662337 |
| { 6144, 432, 288 }, //1.5 |
| { 5461, 512, 384 }, //1.333333 |
| { 5006, 352, 288 }, //1.222222 |
| }; |
| #define THUMBNAIL_SIZE_COUNT (sizeof(thumbnail_sizes)/sizeof(thumbnail_size_type)) |
| #define DEFAULT_THUMBNAIL_SETTING 4 |
| #define THUMBNAIL_WIDTH_STR "512" |
| #define THUMBNAIL_HEIGHT_STR "384" |
| #define THUMBNAIL_SMALL_HEIGHT 144 |
| static camera_size_type jpeg_thumbnail_sizes[] = { |
| { 512, 288 }, |
| { 480, 288 }, |
| { 432, 288 }, |
| { 512, 384 }, |
| { 352, 288 }, |
| {0,0} |
| }; |
| //supported preview fps ranges should be added to this array in the form (minFps,maxFps) |
| static android::FPSRange FpsRangesSupported[] = {{MINIMUM_FPS*1000,MAXIMUM_FPS*1000}}; |
| |
| #define FPS_RANGES_SUPPORTED_COUNT (sizeof(FpsRangesSupported)/sizeof(FpsRangesSupported[0])) |
| |
| #define JPEG_THUMBNAIL_SIZE_COUNT (sizeof(jpeg_thumbnail_sizes)/sizeof(camera_size_type)) |
| static int attr_lookup(const str_map arr[], int len, const char *name) |
| { |
| if (name) { |
| for (int i = 0; i < len; i++) { |
| if (!strcmp(arr[i].desc, name)) |
| return arr[i].val; |
| } |
| } |
| return NOT_FOUND; |
| } |
| |
| // round to the next power of two |
| static inline unsigned clp2(unsigned x) |
| { |
| x = x - 1; |
| x = x | (x >> 1); |
| x = x | (x >> 2); |
| x = x | (x >> 4); |
| x = x | (x >> 8); |
| x = x | (x >>16); |
| return x + 1; |
| } |
| |
| static int exif_table_numEntries = 0; |
| #define MAX_EXIF_TABLE_ENTRIES 14 |
| exif_tags_info_t exif_data[MAX_EXIF_TABLE_ENTRIES]; |
| //static zoom_crop_info zoomCropInfo; |
| static android_native_rect_t zoomCropInfo; |
| static void *mLastQueuedFrame = NULL; |
| #define RECORD_BUFFERS 9 |
| #define RECORD_BUFFERS_8x50 8 |
| static int kRecordBufferCount; |
| /* controls whether VPE is avialable for the target |
| * under consideration. |
| * 1: VPE support is available |
| * 0: VPE support is not available (default) |
| */ |
| static bool mVpeEnabled; |
| static cam_frame_start_parms camframeParams; |
| |
| static int HAL_numOfCameras; |
| static qcamera_info_t HAL_cameraInfo[MSM_MAX_CAMERA_SENSORS]; |
| static int HAL_currentCameraId; |
| static int HAL_currentCameraMode; |
| static mm_camera_config mCfgControl; |
| static bool mCameraOpen; |
| |
| static int HAL_currentSnapshotMode; |
| static int previewWidthToNativeZoom; |
| static int previewHeightToNativeZoom; |
| #define CAMERA_SNAPSHOT_NONZSL 0x04 |
| #define CAMERA_SNAPSHOT_ZSL 0x08 |
| |
| namespace android { |
| extern void native_send_data_callback(int32_t msgType, |
| camera_memory_t * framebuffer, |
| void* user); |
| |
| extern camera_memory_t* get_mem(int fd,size_t buf_size, |
| unsigned int num_bufs, |
| void *user); |
| |
| static const int PICTURE_FORMAT_JPEG = 1; |
| static const int PICTURE_FORMAT_RAW = 2; |
| |
| // from aeecamera.h |
| static const str_map whitebalance[] = { |
| { QCameraParameters::WHITE_BALANCE_AUTO, CAMERA_WB_AUTO }, |
| { QCameraParameters::WHITE_BALANCE_INCANDESCENT, CAMERA_WB_INCANDESCENT }, |
| { QCameraParameters::WHITE_BALANCE_FLUORESCENT, CAMERA_WB_FLUORESCENT }, |
| { QCameraParameters::WHITE_BALANCE_DAYLIGHT, CAMERA_WB_DAYLIGHT }, |
| { QCameraParameters::WHITE_BALANCE_CLOUDY_DAYLIGHT, CAMERA_WB_CLOUDY_DAYLIGHT } |
| }; |
| |
| // from camera_effect_t. This list must match aeecamera.h |
| static const str_map effects[] = { |
| { QCameraParameters::EFFECT_NONE, CAMERA_EFFECT_OFF }, |
| { QCameraParameters::EFFECT_MONO, CAMERA_EFFECT_MONO }, |
| { QCameraParameters::EFFECT_NEGATIVE, CAMERA_EFFECT_NEGATIVE }, |
| { QCameraParameters::EFFECT_SOLARIZE, CAMERA_EFFECT_SOLARIZE }, |
| { QCameraParameters::EFFECT_SEPIA, CAMERA_EFFECT_SEPIA }, |
| { QCameraParameters::EFFECT_POSTERIZE, CAMERA_EFFECT_POSTERIZE }, |
| { QCameraParameters::EFFECT_WHITEBOARD, CAMERA_EFFECT_WHITEBOARD }, |
| { QCameraParameters::EFFECT_BLACKBOARD, CAMERA_EFFECT_BLACKBOARD }, |
| { QCameraParameters::EFFECT_AQUA, CAMERA_EFFECT_AQUA } |
| }; |
| |
| // from qcamera/common/camera.h |
| static const str_map autoexposure[] = { |
| { QCameraParameters::AUTO_EXPOSURE_FRAME_AVG, CAMERA_AEC_FRAME_AVERAGE }, |
| { QCameraParameters::AUTO_EXPOSURE_CENTER_WEIGHTED, CAMERA_AEC_CENTER_WEIGHTED }, |
| { QCameraParameters::AUTO_EXPOSURE_SPOT_METERING, CAMERA_AEC_SPOT_METERING } |
| }; |
| |
| // from qcamera/common/camera.h |
| static const str_map antibanding[] = { |
| { QCameraParameters::ANTIBANDING_OFF, CAMERA_ANTIBANDING_OFF }, |
| { QCameraParameters::ANTIBANDING_50HZ, CAMERA_ANTIBANDING_50HZ }, |
| { QCameraParameters::ANTIBANDING_60HZ, CAMERA_ANTIBANDING_60HZ }, |
| { QCameraParameters::ANTIBANDING_AUTO, CAMERA_ANTIBANDING_AUTO } |
| }; |
| |
| static const str_map antibanding_3D[] = { |
| { QCameraParameters::ANTIBANDING_OFF, CAMERA_ANTIBANDING_OFF }, |
| { QCameraParameters::ANTIBANDING_50HZ, CAMERA_ANTIBANDING_50HZ }, |
| { QCameraParameters::ANTIBANDING_60HZ, CAMERA_ANTIBANDING_60HZ } |
| }; |
| |
| /* Mapping from MCC to antibanding type */ |
| struct country_map { |
| uint32_t country_code; |
| camera_antibanding_type type; |
| }; |
| |
| #if 0 //not using this function. keeping this as this came from Google. |
| static struct country_map country_numeric[] = { |
| { 202, CAMERA_ANTIBANDING_50HZ }, // Greece |
| { 204, CAMERA_ANTIBANDING_50HZ }, // Netherlands |
| { 206, CAMERA_ANTIBANDING_50HZ }, // Belgium |
| { 208, CAMERA_ANTIBANDING_50HZ }, // France |
| { 212, CAMERA_ANTIBANDING_50HZ }, // Monaco |
| { 213, CAMERA_ANTIBANDING_50HZ }, // Andorra |
| { 214, CAMERA_ANTIBANDING_50HZ }, // Spain |
| { 216, CAMERA_ANTIBANDING_50HZ }, // Hungary |
| { 219, CAMERA_ANTIBANDING_50HZ }, // Croatia |
| { 220, CAMERA_ANTIBANDING_50HZ }, // Serbia |
| { 222, CAMERA_ANTIBANDING_50HZ }, // Italy |
| { 226, CAMERA_ANTIBANDING_50HZ }, // Romania |
| { 228, CAMERA_ANTIBANDING_50HZ }, // Switzerland |
| { 230, CAMERA_ANTIBANDING_50HZ }, // Czech Republic |
| { 231, CAMERA_ANTIBANDING_50HZ }, // Slovakia |
| { 232, CAMERA_ANTIBANDING_50HZ }, // Austria |
| { 234, CAMERA_ANTIBANDING_50HZ }, // United Kingdom |
| { 235, CAMERA_ANTIBANDING_50HZ }, // United Kingdom |
| { 238, CAMERA_ANTIBANDING_50HZ }, // Denmark |
| { 240, CAMERA_ANTIBANDING_50HZ }, // Sweden |
| { 242, CAMERA_ANTIBANDING_50HZ }, // Norway |
| { 244, CAMERA_ANTIBANDING_50HZ }, // Finland |
| { 246, CAMERA_ANTIBANDING_50HZ }, // Lithuania |
| { 247, CAMERA_ANTIBANDING_50HZ }, // Latvia |
| { 248, CAMERA_ANTIBANDING_50HZ }, // Estonia |
| { 250, CAMERA_ANTIBANDING_50HZ }, // Russian Federation |
| { 255, CAMERA_ANTIBANDING_50HZ }, // Ukraine |
| { 257, CAMERA_ANTIBANDING_50HZ }, // Belarus |
| { 259, CAMERA_ANTIBANDING_50HZ }, // Moldova |
| { 260, CAMERA_ANTIBANDING_50HZ }, // Poland |
| { 262, CAMERA_ANTIBANDING_50HZ }, // Germany |
| { 266, CAMERA_ANTIBANDING_50HZ }, // Gibraltar |
| { 268, CAMERA_ANTIBANDING_50HZ }, // Portugal |
| { 270, CAMERA_ANTIBANDING_50HZ }, // Luxembourg |
| { 272, CAMERA_ANTIBANDING_50HZ }, // Ireland |
| { 274, CAMERA_ANTIBANDING_50HZ }, // Iceland |
| { 276, CAMERA_ANTIBANDING_50HZ }, // Albania |
| { 278, CAMERA_ANTIBANDING_50HZ }, // Malta |
| { 280, CAMERA_ANTIBANDING_50HZ }, // Cyprus |
| { 282, CAMERA_ANTIBANDING_50HZ }, // Georgia |
| { 283, CAMERA_ANTIBANDING_50HZ }, // Armenia |
| { 284, CAMERA_ANTIBANDING_50HZ }, // Bulgaria |
| { 286, CAMERA_ANTIBANDING_50HZ }, // Turkey |
| { 288, CAMERA_ANTIBANDING_50HZ }, // Faroe Islands |
| { 290, CAMERA_ANTIBANDING_50HZ }, // Greenland |
| { 293, CAMERA_ANTIBANDING_50HZ }, // Slovenia |
| { 294, CAMERA_ANTIBANDING_50HZ }, // Macedonia |
| { 295, CAMERA_ANTIBANDING_50HZ }, // Liechtenstein |
| { 297, CAMERA_ANTIBANDING_50HZ }, // Montenegro |
| { 302, CAMERA_ANTIBANDING_60HZ }, // Canada |
| { 310, CAMERA_ANTIBANDING_60HZ }, // United States of America |
| { 311, CAMERA_ANTIBANDING_60HZ }, // United States of America |
| { 312, CAMERA_ANTIBANDING_60HZ }, // United States of America |
| { 313, CAMERA_ANTIBANDING_60HZ }, // United States of America |
| { 314, CAMERA_ANTIBANDING_60HZ }, // United States of America |
| { 315, CAMERA_ANTIBANDING_60HZ }, // United States of America |
| { 316, CAMERA_ANTIBANDING_60HZ }, // United States of America |
| { 330, CAMERA_ANTIBANDING_60HZ }, // Puerto Rico |
| { 334, CAMERA_ANTIBANDING_60HZ }, // Mexico |
| { 338, CAMERA_ANTIBANDING_50HZ }, // Jamaica |
| { 340, CAMERA_ANTIBANDING_50HZ }, // Martinique |
| { 342, CAMERA_ANTIBANDING_50HZ }, // Barbados |
| { 346, CAMERA_ANTIBANDING_60HZ }, // Cayman Islands |
| { 350, CAMERA_ANTIBANDING_60HZ }, // Bermuda |
| { 352, CAMERA_ANTIBANDING_50HZ }, // Grenada |
| { 354, CAMERA_ANTIBANDING_60HZ }, // Montserrat |
| { 362, CAMERA_ANTIBANDING_50HZ }, // Netherlands Antilles |
| { 363, CAMERA_ANTIBANDING_60HZ }, // Aruba |
| { 364, CAMERA_ANTIBANDING_60HZ }, // Bahamas |
| { 365, CAMERA_ANTIBANDING_60HZ }, // Anguilla |
| { 366, CAMERA_ANTIBANDING_50HZ }, // Dominica |
| { 368, CAMERA_ANTIBANDING_60HZ }, // Cuba |
| { 370, CAMERA_ANTIBANDING_60HZ }, // Dominican Republic |
| { 372, CAMERA_ANTIBANDING_60HZ }, // Haiti |
| { 401, CAMERA_ANTIBANDING_50HZ }, // Kazakhstan |
| { 402, CAMERA_ANTIBANDING_50HZ }, // Bhutan |
| { 404, CAMERA_ANTIBANDING_50HZ }, // India |
| { 405, CAMERA_ANTIBANDING_50HZ }, // India |
| { 410, CAMERA_ANTIBANDING_50HZ }, // Pakistan |
| { 413, CAMERA_ANTIBANDING_50HZ }, // Sri Lanka |
| { 414, CAMERA_ANTIBANDING_50HZ }, // Myanmar |
| { 415, CAMERA_ANTIBANDING_50HZ }, // Lebanon |
| { 416, CAMERA_ANTIBANDING_50HZ }, // Jordan |
| { 417, CAMERA_ANTIBANDING_50HZ }, // Syria |
| { 418, CAMERA_ANTIBANDING_50HZ }, // Iraq |
| { 419, CAMERA_ANTIBANDING_50HZ }, // Kuwait |
| { 420, CAMERA_ANTIBANDING_60HZ }, // Saudi Arabia |
| { 421, CAMERA_ANTIBANDING_50HZ }, // Yemen |
| { 422, CAMERA_ANTIBANDING_50HZ }, // Oman |
| { 424, CAMERA_ANTIBANDING_50HZ }, // United Arab Emirates |
| { 425, CAMERA_ANTIBANDING_50HZ }, // Israel |
| { 426, CAMERA_ANTIBANDING_50HZ }, // Bahrain |
| { 427, CAMERA_ANTIBANDING_50HZ }, // Qatar |
| { 428, CAMERA_ANTIBANDING_50HZ }, // Mongolia |
| { 429, CAMERA_ANTIBANDING_50HZ }, // Nepal |
| { 430, CAMERA_ANTIBANDING_50HZ }, // United Arab Emirates |
| { 431, CAMERA_ANTIBANDING_50HZ }, // United Arab Emirates |
| { 432, CAMERA_ANTIBANDING_50HZ }, // Iran |
| { 434, CAMERA_ANTIBANDING_50HZ }, // Uzbekistan |
| { 436, CAMERA_ANTIBANDING_50HZ }, // Tajikistan |
| { 437, CAMERA_ANTIBANDING_50HZ }, // Kyrgyz Rep |
| { 438, CAMERA_ANTIBANDING_50HZ }, // Turkmenistan |
| { 440, CAMERA_ANTIBANDING_60HZ }, // Japan |
| { 441, CAMERA_ANTIBANDING_60HZ }, // Japan |
| { 452, CAMERA_ANTIBANDING_50HZ }, // Vietnam |
| { 454, CAMERA_ANTIBANDING_50HZ }, // Hong Kong |
| { 455, CAMERA_ANTIBANDING_50HZ }, // Macao |
| { 456, CAMERA_ANTIBANDING_50HZ }, // Cambodia |
| { 457, CAMERA_ANTIBANDING_50HZ }, // Laos |
| { 460, CAMERA_ANTIBANDING_50HZ }, // China |
| { 466, CAMERA_ANTIBANDING_60HZ }, // Taiwan |
| { 470, CAMERA_ANTIBANDING_50HZ }, // Bangladesh |
| { 472, CAMERA_ANTIBANDING_50HZ }, // Maldives |
| { 502, CAMERA_ANTIBANDING_50HZ }, // Malaysia |
| { 505, CAMERA_ANTIBANDING_50HZ }, // Australia |
| { 510, CAMERA_ANTIBANDING_50HZ }, // Indonesia |
| { 514, CAMERA_ANTIBANDING_50HZ }, // East Timor |
| { 515, CAMERA_ANTIBANDING_60HZ }, // Philippines |
| { 520, CAMERA_ANTIBANDING_50HZ }, // Thailand |
| { 525, CAMERA_ANTIBANDING_50HZ }, // Singapore |
| { 530, CAMERA_ANTIBANDING_50HZ }, // New Zealand |
| { 535, CAMERA_ANTIBANDING_60HZ }, // Guam |
| { 536, CAMERA_ANTIBANDING_50HZ }, // Nauru |
| { 537, CAMERA_ANTIBANDING_50HZ }, // Papua New Guinea |
| { 539, CAMERA_ANTIBANDING_50HZ }, // Tonga |
| { 541, CAMERA_ANTIBANDING_50HZ }, // Vanuatu |
| { 542, CAMERA_ANTIBANDING_50HZ }, // Fiji |
| { 544, CAMERA_ANTIBANDING_60HZ }, // American Samoa |
| { 545, CAMERA_ANTIBANDING_50HZ }, // Kiribati |
| { 546, CAMERA_ANTIBANDING_50HZ }, // New Caledonia |
| { 548, CAMERA_ANTIBANDING_50HZ }, // Cook Islands |
| { 602, CAMERA_ANTIBANDING_50HZ }, // Egypt |
| { 603, CAMERA_ANTIBANDING_50HZ }, // Algeria |
| { 604, CAMERA_ANTIBANDING_50HZ }, // Morocco |
| { 605, CAMERA_ANTIBANDING_50HZ }, // Tunisia |
| { 606, CAMERA_ANTIBANDING_50HZ }, // Libya |
| { 607, CAMERA_ANTIBANDING_50HZ }, // Gambia |
| { 608, CAMERA_ANTIBANDING_50HZ }, // Senegal |
| { 609, CAMERA_ANTIBANDING_50HZ }, // Mauritania |
| { 610, CAMERA_ANTIBANDING_50HZ }, // Mali |
| { 611, CAMERA_ANTIBANDING_50HZ }, // Guinea |
| { 613, CAMERA_ANTIBANDING_50HZ }, // Burkina Faso |
| { 614, CAMERA_ANTIBANDING_50HZ }, // Niger |
| { 616, CAMERA_ANTIBANDING_50HZ }, // Benin |
| { 617, CAMERA_ANTIBANDING_50HZ }, // Mauritius |
| { 618, CAMERA_ANTIBANDING_50HZ }, // Liberia |
| { 619, CAMERA_ANTIBANDING_50HZ }, // Sierra Leone |
| { 620, CAMERA_ANTIBANDING_50HZ }, // Ghana |
| { 621, CAMERA_ANTIBANDING_50HZ }, // Nigeria |
| { 622, CAMERA_ANTIBANDING_50HZ }, // Chad |
| { 623, CAMERA_ANTIBANDING_50HZ }, // Central African Republic |
| { 624, CAMERA_ANTIBANDING_50HZ }, // Cameroon |
| { 625, CAMERA_ANTIBANDING_50HZ }, // Cape Verde |
| { 627, CAMERA_ANTIBANDING_50HZ }, // Equatorial Guinea |
| { 631, CAMERA_ANTIBANDING_50HZ }, // Angola |
| { 633, CAMERA_ANTIBANDING_50HZ }, // Seychelles |
| { 634, CAMERA_ANTIBANDING_50HZ }, // Sudan |
| { 636, CAMERA_ANTIBANDING_50HZ }, // Ethiopia |
| { 637, CAMERA_ANTIBANDING_50HZ }, // Somalia |
| { 638, CAMERA_ANTIBANDING_50HZ }, // Djibouti |
| { 639, CAMERA_ANTIBANDING_50HZ }, // Kenya |
| { 640, CAMERA_ANTIBANDING_50HZ }, // Tanzania |
| { 641, CAMERA_ANTIBANDING_50HZ }, // Uganda |
| { 642, CAMERA_ANTIBANDING_50HZ }, // Burundi |
| { 643, CAMERA_ANTIBANDING_50HZ }, // Mozambique |
| { 645, CAMERA_ANTIBANDING_50HZ }, // Zambia |
| { 646, CAMERA_ANTIBANDING_50HZ }, // Madagascar |
| { 647, CAMERA_ANTIBANDING_50HZ }, // France |
| { 648, CAMERA_ANTIBANDING_50HZ }, // Zimbabwe |
| { 649, CAMERA_ANTIBANDING_50HZ }, // Namibia |
| { 650, CAMERA_ANTIBANDING_50HZ }, // Malawi |
| { 651, CAMERA_ANTIBANDING_50HZ }, // Lesotho |
| { 652, CAMERA_ANTIBANDING_50HZ }, // Botswana |
| { 653, CAMERA_ANTIBANDING_50HZ }, // Swaziland |
| { 654, CAMERA_ANTIBANDING_50HZ }, // Comoros |
| { 655, CAMERA_ANTIBANDING_50HZ }, // South Africa |
| { 657, CAMERA_ANTIBANDING_50HZ }, // Eritrea |
| { 702, CAMERA_ANTIBANDING_60HZ }, // Belize |
| { 704, CAMERA_ANTIBANDING_60HZ }, // Guatemala |
| { 706, CAMERA_ANTIBANDING_60HZ }, // El Salvador |
| { 708, CAMERA_ANTIBANDING_60HZ }, // Honduras |
| { 710, CAMERA_ANTIBANDING_60HZ }, // Nicaragua |
| { 712, CAMERA_ANTIBANDING_60HZ }, // Costa Rica |
| { 714, CAMERA_ANTIBANDING_60HZ }, // Panama |
| { 722, CAMERA_ANTIBANDING_50HZ }, // Argentina |
| { 724, CAMERA_ANTIBANDING_60HZ }, // Brazil |
| { 730, CAMERA_ANTIBANDING_50HZ }, // Chile |
| { 732, CAMERA_ANTIBANDING_60HZ }, // Colombia |
| { 734, CAMERA_ANTIBANDING_60HZ }, // Venezuela |
| { 736, CAMERA_ANTIBANDING_50HZ }, // Bolivia |
| { 738, CAMERA_ANTIBANDING_60HZ }, // Guyana |
| { 740, CAMERA_ANTIBANDING_60HZ }, // Ecuador |
| { 742, CAMERA_ANTIBANDING_50HZ }, // French Guiana |
| { 744, CAMERA_ANTIBANDING_50HZ }, // Paraguay |
| { 746, CAMERA_ANTIBANDING_60HZ }, // Suriname |
| { 748, CAMERA_ANTIBANDING_50HZ }, // Uruguay |
| { 750, CAMERA_ANTIBANDING_50HZ }, // Falkland Islands |
| }; |
| #define country_number (sizeof(country_numeric) / sizeof(country_map)) |
| /* Look up pre-sorted antibanding_type table by current MCC. */ |
| static camera_antibanding_type camera_get_location(void) { |
| char value[PROP_VALUE_MAX]; |
| char country_value[PROP_VALUE_MAX]; |
| uint32_t country_code; |
| memset(value, 0x00, sizeof(value)); |
| memset(country_value, 0x00, sizeof(country_value)); |
| if (!__system_property_get("gsm.operator.numeric", value)) { |
| return CAMERA_ANTIBANDING_60HZ; |
| } |
| memcpy(country_value, value, 3); |
| country_code = atoi(country_value); |
| ALOGD("value:%s, country value:%s, country code:%d\n", |
| value, country_value, country_code); |
| int left = 0; |
| int right = country_number - 1; |
| while (left <= right) { |
| int index = (left + right) >> 1; |
| if (country_numeric[index].country_code == country_code) |
| return country_numeric[index].type; |
| else if (country_numeric[index].country_code > country_code) |
| right = index - 1; |
| else |
| left = index + 1; |
| } |
| return CAMERA_ANTIBANDING_60HZ; |
| } |
| #endif |
| |
| static const str_map scenemode[] = { |
| { QCameraParameters::SCENE_MODE_AUTO, CAMERA_BESTSHOT_OFF }, |
| { QCameraParameters::SCENE_MODE_ASD, CAMERA_BESTSHOT_AUTO }, |
| { QCameraParameters::SCENE_MODE_ACTION, CAMERA_BESTSHOT_ACTION }, |
| { QCameraParameters::SCENE_MODE_PORTRAIT, CAMERA_BESTSHOT_PORTRAIT }, |
| { QCameraParameters::SCENE_MODE_LANDSCAPE, CAMERA_BESTSHOT_LANDSCAPE }, |
| { QCameraParameters::SCENE_MODE_NIGHT, CAMERA_BESTSHOT_NIGHT }, |
| { QCameraParameters::SCENE_MODE_NIGHT_PORTRAIT, CAMERA_BESTSHOT_NIGHT_PORTRAIT }, |
| { QCameraParameters::SCENE_MODE_THEATRE, CAMERA_BESTSHOT_THEATRE }, |
| { QCameraParameters::SCENE_MODE_BEACH, CAMERA_BESTSHOT_BEACH }, |
| { QCameraParameters::SCENE_MODE_SNOW, CAMERA_BESTSHOT_SNOW }, |
| { QCameraParameters::SCENE_MODE_SUNSET, CAMERA_BESTSHOT_SUNSET }, |
| { QCameraParameters::SCENE_MODE_STEADYPHOTO, CAMERA_BESTSHOT_ANTISHAKE }, |
| { QCameraParameters::SCENE_MODE_FIREWORKS , CAMERA_BESTSHOT_FIREWORKS }, |
| { QCameraParameters::SCENE_MODE_SPORTS , CAMERA_BESTSHOT_SPORTS }, |
| { QCameraParameters::SCENE_MODE_PARTY, CAMERA_BESTSHOT_PARTY }, |
| { QCameraParameters::SCENE_MODE_CANDLELIGHT, CAMERA_BESTSHOT_CANDLELIGHT }, |
| { QCameraParameters::SCENE_MODE_BACKLIGHT, CAMERA_BESTSHOT_BACKLIGHT }, |
| { QCameraParameters::SCENE_MODE_FLOWERS, CAMERA_BESTSHOT_FLOWERS }, |
| { QCameraParameters::SCENE_MODE_AR, CAMERA_BESTSHOT_AR }, |
| }; |
| |
| static const str_map scenedetect[] = { |
| { QCameraParameters::SCENE_DETECT_OFF, FALSE }, |
| { QCameraParameters::SCENE_DETECT_ON, TRUE }, |
| }; |
| |
| // from camera.h, led_mode_t |
| static const str_map flash[] = { |
| { QCameraParameters::FLASH_MODE_OFF, LED_MODE_OFF }, |
| { QCameraParameters::FLASH_MODE_AUTO, LED_MODE_AUTO }, |
| { QCameraParameters::FLASH_MODE_ON, LED_MODE_ON }, |
| { QCameraParameters::FLASH_MODE_TORCH, LED_MODE_TORCH} |
| }; |
| |
| // from mm-camera/common/camera.h. |
| static const str_map iso[] = { |
| { QCameraParameters::ISO_AUTO, CAMERA_ISO_AUTO}, |
| { QCameraParameters::ISO_HJR, CAMERA_ISO_DEBLUR}, |
| { QCameraParameters::ISO_100, CAMERA_ISO_100}, |
| { QCameraParameters::ISO_200, CAMERA_ISO_200}, |
| { QCameraParameters::ISO_400, CAMERA_ISO_400}, |
| { QCameraParameters::ISO_800, CAMERA_ISO_800 }, |
| { QCameraParameters::ISO_1600, CAMERA_ISO_1600 } |
| }; |
| |
| static const str_map iso_3D[] = { |
| { QCameraParameters::ISO_AUTO, CAMERA_ISO_AUTO}, |
| { QCameraParameters::ISO_100, CAMERA_ISO_100}, |
| { QCameraParameters::ISO_200, CAMERA_ISO_200}, |
| { QCameraParameters::ISO_400, CAMERA_ISO_400}, |
| { QCameraParameters::ISO_800, CAMERA_ISO_800 }, |
| { QCameraParameters::ISO_1600, CAMERA_ISO_1600 } |
| }; |
| |
| |
| #define DONT_CARE AF_MODE_MAX |
| static const str_map focus_modes[] = { |
| { QCameraParameters::FOCUS_MODE_AUTO, AF_MODE_AUTO}, |
| { QCameraParameters::FOCUS_MODE_INFINITY, DONT_CARE }, |
| { QCameraParameters::FOCUS_MODE_NORMAL, AF_MODE_NORMAL }, |
| { QCameraParameters::FOCUS_MODE_MACRO, AF_MODE_MACRO }, |
| { QCameraParameters::FOCUS_MODE_CONTINUOUS_PICTURE, AF_MODE_CAF }, |
| { QCameraParameters::FOCUS_MODE_CONTINUOUS_VIDEO, DONT_CARE } |
| }; |
| |
| static const str_map lensshade[] = { |
| { QCameraParameters::LENSSHADE_ENABLE, TRUE }, |
| { QCameraParameters::LENSSHADE_DISABLE, FALSE } |
| }; |
| |
| static const str_map hfr[] = { |
| { QCameraParameters::VIDEO_HFR_OFF, CAMERA_HFR_MODE_OFF }, |
| { QCameraParameters::VIDEO_HFR_2X, CAMERA_HFR_MODE_60FPS }, |
| { QCameraParameters::VIDEO_HFR_3X, CAMERA_HFR_MODE_90FPS }, |
| { QCameraParameters::VIDEO_HFR_4X, CAMERA_HFR_MODE_120FPS }, |
| }; |
| |
| static const str_map mce[] = { |
| { QCameraParameters::MCE_ENABLE, TRUE }, |
| { QCameraParameters::MCE_DISABLE, FALSE } |
| }; |
| |
| static const str_map hdr[] = { |
| { QCameraParameters::HDR_ENABLE, TRUE }, |
| { QCameraParameters::HDR_DISABLE, FALSE } |
| }; |
| |
| static const str_map histogram[] = { |
| { QCameraParameters::HISTOGRAM_ENABLE, TRUE }, |
| { QCameraParameters::HISTOGRAM_DISABLE, FALSE } |
| }; |
| |
| static const str_map skinToneEnhancement[] = { |
| { QCameraParameters::SKIN_TONE_ENHANCEMENT_ENABLE, TRUE }, |
| { QCameraParameters::SKIN_TONE_ENHANCEMENT_DISABLE, FALSE } |
| }; |
| |
| static const str_map denoise[] = { |
| { QCameraParameters::DENOISE_OFF, FALSE }, |
| { QCameraParameters::DENOISE_ON, TRUE } |
| }; |
| |
| static const str_map selectable_zone_af[] = { |
| { QCameraParameters::SELECTABLE_ZONE_AF_AUTO, AUTO }, |
| { QCameraParameters::SELECTABLE_ZONE_AF_SPOT_METERING, SPOT }, |
| { QCameraParameters::SELECTABLE_ZONE_AF_CENTER_WEIGHTED, CENTER_WEIGHTED }, |
| { QCameraParameters::SELECTABLE_ZONE_AF_FRAME_AVERAGE, AVERAGE } |
| }; |
| |
| static const str_map facedetection[] = { |
| { QCameraParameters::FACE_DETECTION_OFF, FALSE }, |
| { QCameraParameters::FACE_DETECTION_ON, TRUE } |
| }; |
| |
| #define DONT_CARE_COORDINATE -1 |
| static const str_map touchafaec[] = { |
| { QCameraParameters::TOUCH_AF_AEC_OFF, FALSE }, |
| { QCameraParameters::TOUCH_AF_AEC_ON, TRUE } |
| }; |
| |
| static const str_map redeye_reduction[] = { |
| { QCameraParameters::REDEYE_REDUCTION_ENABLE, TRUE }, |
| { QCameraParameters::REDEYE_REDUCTION_DISABLE, FALSE } |
| }; |
| |
| static const str_map zsl_modes[] = { |
| { QCameraParameters::ZSL_OFF, FALSE }, |
| { QCameraParameters::ZSL_ON, TRUE }, |
| }; |
| |
| /* |
| * Values based on aec.c |
| */ |
| #define DONT_CARE_COORDINATE -1 |
| #define CAMERA_HISTOGRAM_ENABLE 1 |
| #define CAMERA_HISTOGRAM_DISABLE 0 |
| #define HISTOGRAM_STATS_SIZE 257 |
| |
| /* |
| * Values based on aec.c |
| */ |
| #define EXPOSURE_COMPENSATION_MAXIMUM_NUMERATOR 12 |
| #define EXPOSURE_COMPENSATION_MINIMUM_NUMERATOR -12 |
| #define EXPOSURE_COMPENSATION_DEFAULT_NUMERATOR 0 |
| #define EXPOSURE_COMPENSATION_DENOMINATOR 6 |
| #define EXPOSURE_COMPENSATION_STEP ((float (1))/EXPOSURE_COMPENSATION_DENOMINATOR) |
| |
| static const str_map picture_formats[] = { |
| {QCameraParameters::PIXEL_FORMAT_JPEG, PICTURE_FORMAT_JPEG}, |
| {QCameraParameters::PIXEL_FORMAT_RAW, PICTURE_FORMAT_RAW} |
| }; |
| |
| static const str_map recording_Hints[] = { |
| {"false", FALSE}, |
| {"true", TRUE} |
| }; |
| |
| static const str_map picture_formats_zsl[] = { |
| {QCameraParameters::PIXEL_FORMAT_JPEG, PICTURE_FORMAT_JPEG} |
| }; |
| |
| static const str_map frame_rate_modes[] = { |
| {QCameraParameters::KEY_PREVIEW_FRAME_RATE_AUTO_MODE, FPS_MODE_AUTO}, |
| {QCameraParameters::KEY_PREVIEW_FRAME_RATE_FIXED_MODE, FPS_MODE_FIXED} |
| }; |
| |
| static int mPreviewFormat; |
| static const str_map preview_formats[] = { |
| {QCameraParameters::PIXEL_FORMAT_YUV420SP, CAMERA_YUV_420_NV21}, |
| {QCameraParameters::PIXEL_FORMAT_YUV420SP_ADRENO, CAMERA_YUV_420_NV21_ADRENO}, |
| {QCameraParameters::PIXEL_FORMAT_YUV420P, CAMERA_YUV_420_YV12} |
| }; |
| static const str_map preview_formats1[] = { |
| {QCameraParameters::PIXEL_FORMAT_YUV420SP, CAMERA_YUV_420_NV21}, |
| {QCameraParameters::PIXEL_FORMAT_YUV420P, CAMERA_YUV_420_YV12} |
| }; |
| |
| static const str_map app_preview_formats[] = { |
| {QCameraParameters::PIXEL_FORMAT_YUV420SP, HAL_PIXEL_FORMAT_YCrCb_420_SP}, //nv21 |
| //{QCameraParameters::PIXEL_FORMAT_YUV420SP_ADRENO, HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO}, //nv21_adreno |
| {QCameraParameters::PIXEL_FORMAT_YUV420P, HAL_PIXEL_FORMAT_YV12}, //YV12 |
| }; |
| |
| |
| static bool parameter_string_initialized = false; |
| static String8 preview_size_values; |
| static String8 hfr_size_values; |
| static String8 picture_size_values; |
| static String8 fps_ranges_supported_values; |
| static String8 jpeg_thumbnail_size_values; |
| static String8 antibanding_values; |
| static String8 effect_values; |
| static String8 autoexposure_values; |
| static String8 whitebalance_values; |
| static String8 flash_values; |
| static String8 focus_mode_values; |
| static String8 iso_values; |
| static String8 lensshade_values; |
| static String8 mce_values; |
| static String8 hdr_values; |
| static String8 histogram_values; |
| static String8 skinToneEnhancement_values; |
| static String8 touchafaec_values; |
| static String8 picture_format_values; |
| static String8 scenemode_values; |
| static String8 denoise_values; |
| static String8 zoom_ratio_values; |
| static String8 preview_frame_rate_values; |
| static String8 frame_rate_mode_values; |
| static String8 scenedetect_values; |
| static String8 preview_format_values; |
| static String8 selectable_zone_af_values; |
| static String8 facedetection_values; |
| static String8 hfr_values; |
| static String8 redeye_reduction_values; |
| static String8 zsl_values; |
| |
| mm_camera_notify mCamNotify; |
| mm_camera_ops mCamOps; |
| static mm_camera_buffer_t mEncodeOutputBuffer[MAX_SNAPSHOT_BUFFERS]; |
| static encode_params_t mImageEncodeParms; |
| static capture_params_t mImageCaptureParms; |
| static raw_capture_params_t mRawCaptureParms; |
| static zsl_capture_params_t mZslCaptureParms; |
| static zsl_params_t mZslParms; |
| static yv12_format_parms_t myv12_params; |
| |
| static String8 create_sizes_str(const camera_size_type *sizes, int len) { |
| String8 str; |
| char buffer[32]; |
| |
| if (len > 0) { |
| sprintf(buffer, "%dx%d", sizes[0].width, sizes[0].height); |
| str.append(buffer); |
| } |
| for (int i = 1; i < len; i++) { |
| sprintf(buffer, ",%dx%d", sizes[i].width, sizes[i].height); |
| str.append(buffer); |
| } |
| return str; |
| } |
| |
| static String8 create_fps_str(const android:: FPSRange* fps, int len) { |
| String8 str; |
| char buffer[32]; |
| |
| if (len > 0) { |
| sprintf(buffer, "(%d,%d)", fps[0].minFPS, fps[0].maxFPS); |
| str.append(buffer); |
| } |
| for (int i = 1; i < len; i++) { |
| sprintf(buffer, ",(%d,%d)", fps[i].minFPS, fps[i].maxFPS); |
| str.append(buffer); |
| } |
| return str; |
| } |
| |
| static String8 create_values_str(const str_map *values, int len) { |
| String8 str; |
| |
| if (len > 0) { |
| str.append(values[0].desc); |
| } |
| for (int i = 1; i < len; i++) { |
| str.append(","); |
| str.append(values[i].desc); |
| } |
| return str; |
| } |
| |
| |
| static String8 create_str(int16_t *arr, int length){ |
| String8 str; |
| char buffer[32]; |
| |
| if(length > 0){ |
| snprintf(buffer, sizeof(buffer), "%d", arr[0]); |
| str.append(buffer); |
| } |
| |
| for (int i =1;i<length;i++){ |
| snprintf(buffer, sizeof(buffer), ",%d",arr[i]); |
| str.append(buffer); |
| } |
| return str; |
| } |
| |
| static String8 create_values_range_str(int min, int max){ |
| String8 str; |
| char buffer[32]; |
| |
| if(min <= max){ |
| snprintf(buffer, sizeof(buffer), "%d", min); |
| str.append(buffer); |
| |
| for (int i = min + 1; i <= max; i++) { |
| snprintf(buffer, sizeof(buffer), ",%d", i); |
| str.append(buffer); |
| } |
| } |
| return str; |
| } |
| |
| extern "C" { |
| //------------------------------------------------------------------------ |
| // : 720p busyQ funcitons |
| // -------------------------------------------------------------------- |
| static struct fifo_queue g_busy_frame_queue = |
| {0, 0, 0, PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, (char *)"video_busy_q"}; |
| }; |
| |
| static void cam_frame_wait_video (void) |
| { |
| ALOGV("cam_frame_wait_video E "); |
| if ((g_busy_frame_queue.num_of_frames) <=0){ |
| pthread_cond_wait(&(g_busy_frame_queue.wait), &(g_busy_frame_queue.mut)); |
| } |
| ALOGV("cam_frame_wait_video X"); |
| return; |
| } |
| |
| void cam_frame_flush_video (void) |
| { |
| ALOGV("cam_frame_flush_video: in n = %d\n", g_busy_frame_queue.num_of_frames); |
| pthread_mutex_lock(&(g_busy_frame_queue.mut)); |
| |
| while (g_busy_frame_queue.front) |
| { |
| //dequeue from the busy queue |
| struct fifo_node *node = dequeue (&g_busy_frame_queue); |
| if(node) |
| free(node); |
| |
| ALOGV("cam_frame_flush_video: node \n"); |
| } |
| pthread_mutex_unlock(&(g_busy_frame_queue.mut)); |
| ALOGV("cam_frame_flush_video: out n = %d\n", g_busy_frame_queue.num_of_frames); |
| return ; |
| } |
| |
| static struct msm_frame * cam_frame_get_video() |
| { |
| struct msm_frame *p = NULL; |
| ALOGV("cam_frame_get_video... in\n"); |
| ALOGV("cam_frame_get_video... got lock\n"); |
| if (g_busy_frame_queue.front) |
| { |
| //dequeue |
| struct fifo_node *node = dequeue (&g_busy_frame_queue); |
| if (node) |
| { |
| p = (struct msm_frame *)node->f; |
| free (node); |
| } |
| ALOGV("cam_frame_get_video... out = %x\n", p->buffer); |
| } |
| return p; |
| } |
| |
| // Parse string like "(1, 2, 3, 4, ..., N)" |
| // num is pointer to an allocated array of size N |
| static int parseNDimVector_HAL(const char *str, int *num, int N, char delim = ',') |
| { |
| char *start, *end; |
| if(num == NULL) { |
| ALOGE("Invalid output array (num == NULL)"); |
| return -1; |
| } |
| //check if string starts and ends with parantheses |
| if(str[0] != '(' || str[strlen(str)-1] != ')') { |
| ALOGE("Invalid format of string %s, valid format is (n1, n2, n3, n4 ...)", str); |
| return -1; |
| } |
| start = (char*) str; |
| start++; |
| for(int i=0; i<N; i++) { |
| *(num+i) = (int) strtol(start, &end, 10); |
| if(*end != delim && i < N-1) { |
| ALOGE("Cannot find delimeter '%c' in string \"%s\". end = %c", delim, str, *end); |
| return -1; |
| } |
| start = end+1; |
| } |
| return 0; |
| } |
| static int countChar(const char *str , char ch ) |
| { |
| int noOfChar = 0; |
| |
| for ( int i = 0; str[i] != '\0'; i++) { |
| if ( str[i] == ch ) |
| noOfChar = noOfChar + 1; |
| } |
| |
| return noOfChar; |
| } |
| int checkAreaParameters(const char *str) |
| { |
| int areaValues[6]; |
| int left, right, top, bottom, weight; |
| |
| if(countChar(str, ',') > 4) { |
| ALOGE("%s: No of area parameters exceeding the expected number %s", __FUNCTION__, str); |
| return -1; |
| } |
| |
| if(parseNDimVector_HAL(str, areaValues, 5) !=0) { |
| ALOGE("%s: Failed to parse the input string %s", __FUNCTION__, str); |
| return -1; |
| } |
| |
| ALOGV("%s: Area values are %d,%d,%d,%d,%d", __FUNCTION__, |
| areaValues[0], areaValues[1], areaValues[2], areaValues[3], areaValues[4]); |
| |
| left = areaValues[0]; |
| top = areaValues[1]; |
| right = areaValues[2]; |
| bottom = areaValues[3]; |
| weight = areaValues[4]; |
| |
| // left should >= -1000 |
| if (!(left >= -1000)) |
| return -1; |
| // top should >= -1000 |
| if(!(top >= -1000)) |
| return -1; |
| // right should <= 1000 |
| if(!(right <= 1000)) |
| return -1; |
| // bottom should <= 1000 |
| if(!(bottom <= 1000)) |
| return -1; |
| // weight should >= 1 |
| // weight should <= 1000 |
| if(!((1 <= weight) && (weight <= 1000))) |
| return -1; |
| // left should < right |
| if(!(left < right)) |
| return -1; |
| // top should < bottom |
| if(!(top < bottom)) |
| return -1; |
| |
| return 0; |
| } |
| |
| static void cam_frame_post_video (struct msm_frame *p) |
| { |
| if (!p) |
| { |
| ALOGE("post video , buffer is null"); |
| return; |
| } |
| ALOGV("cam_frame_post_video... in = %x\n", (unsigned int)(p->buffer)); |
| pthread_mutex_lock(&(g_busy_frame_queue.mut)); |
| ALOGV("post_video got lock. q count before enQ %d", g_busy_frame_queue.num_of_frames); |
| //enqueue to busy queue |
| struct fifo_node *node = (struct fifo_node *)malloc (sizeof (struct fifo_node)); |
| if (node) |
| { |
| ALOGV(" post video , enqueing in busy queue"); |
| node->f = p; |
| node->next = NULL; |
| enqueue (&g_busy_frame_queue, node); |
| ALOGV("post_video got lock. q count after enQ %d", g_busy_frame_queue.num_of_frames); |
| } |
| else |
| { |
| ALOGE("cam_frame_post_video error... out of memory\n"); |
| } |
| |
| pthread_mutex_unlock(&(g_busy_frame_queue.mut)); |
| pthread_cond_signal(&(g_busy_frame_queue.wait)); |
| |
| ALOGV("cam_frame_post_video... out = %x\n", p->buffer); |
| |
| return; |
| } |
| |
| QualcommCameraHardware::FrameQueue::FrameQueue(){ |
| mInitialized = false; |
| } |
| |
| QualcommCameraHardware::FrameQueue::~FrameQueue(){ |
| flush(); |
| } |
| |
| void QualcommCameraHardware::FrameQueue::init(){ |
| Mutex::Autolock l(&mQueueLock); |
| mInitialized = true; |
| mQueueWait.signal(); |
| } |
| |
| void QualcommCameraHardware::FrameQueue::deinit(){ |
| Mutex::Autolock l(&mQueueLock); |
| mInitialized = false; |
| mQueueWait.signal(); |
| } |
| |
| bool QualcommCameraHardware::FrameQueue::isInitialized(){ |
| Mutex::Autolock l(&mQueueLock); |
| return mInitialized; |
| } |
| |
| bool QualcommCameraHardware::FrameQueue::add( |
| struct msm_frame * element){ |
| Mutex::Autolock l(&mQueueLock); |
| if(mInitialized == false) |
| return false; |
| |
| mContainer.add(element); |
| mQueueWait.signal(); |
| return true; |
| } |
| |
| struct msm_frame * QualcommCameraHardware::FrameQueue::get(){ |
| |
| struct msm_frame *frame; |
| mQueueLock.lock(); |
| while(mInitialized && mContainer.isEmpty()){ |
| mQueueWait.wait(mQueueLock); |
| } |
| |
| if(!mInitialized){ |
| mQueueLock.unlock(); |
| return NULL; |
| } |
| |
| frame = mContainer.itemAt(0); |
| mContainer.removeAt(0); |
| mQueueLock.unlock(); |
| return frame; |
| } |
| |
| void QualcommCameraHardware::FrameQueue::flush(){ |
| Mutex::Autolock l(&mQueueLock); |
| mContainer.clear(); |
| |
| } |
| |
| |
| void QualcommCameraHardware::storeTargetType(void) { |
| char mDeviceName[PROPERTY_VALUE_MAX]; |
| property_get("ro.product.device",mDeviceName," "); |
| mCurrentTarget = TARGET_MAX; |
| for( int i = 0; i < TARGET_MAX ; i++) { |
| if( !strncmp(mDeviceName, targetList[i].targetStr, 7)) { |
| mCurrentTarget = targetList[i].targetEnum; |
| if(mCurrentTarget == TARGET_MSM7625) { |
| if(!strncmp(mDeviceName, "msm7625a" , 8)) |
| mCurrentTarget = TARGET_MSM7625A; |
| } |
| if(mCurrentTarget == TARGET_MSM7627) { |
| if(!strncmp(mDeviceName, "msm7627a" , 8)) |
| mCurrentTarget = TARGET_MSM7627A; |
| } |
| break; |
| } |
| } |
| ALOGV(" Storing the current target type as %d ", mCurrentTarget ); |
| return; |
| } |
| |
| void *openCamera(void *data) { |
| ALOGV(" openCamera : E"); |
| mCameraOpen = false; |
| |
| if (!libmmcamera) { |
| ALOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror()); |
| return false; |
| } |
| |
| *(void **)&LINK_mm_camera_init = |
| ::dlsym(libmmcamera, "mm_camera_init"); |
| |
| *(void **)&LINK_mm_camera_exec = |
| ::dlsym(libmmcamera, "mm_camera_exec"); |
| |
| *(void **)&LINK_mm_camera_deinit = |
| ::dlsym(libmmcamera, "mm_camera_deinit"); |
| |
| |
| if (MM_CAMERA_SUCCESS != LINK_mm_camera_init(&mCfgControl, &mCamNotify, &mCamOps, 0)) { |
| ALOGE("startCamera: mm_camera_init failed:"); |
| return false; |
| //pthread_exit((void*) ret_val); |
| } |
| |
| uint8_t camera_id8 = (uint8_t)HAL_currentCameraId; |
| if (MM_CAMERA_SUCCESS != mCfgControl.mm_camera_set_parm(CAMERA_PARM_CAMERA_ID, &camera_id8)) { |
| ALOGE("setting camera id failed"); |
| LINK_mm_camera_deinit(); |
| return false; |
| //pthread_exit((void*) ret_val); |
| } |
| |
| //camera_mode_t mode = (camera_mode_t)HAL_currentCameraMode; |
| camera_mode_t mode = CAMERA_MODE_2D; |
| if (MM_CAMERA_SUCCESS != mCfgControl.mm_camera_set_parm(CAMERA_PARM_MODE, &mode)) { |
| ALOGE("startCamera: CAMERA_PARM_MODE failed:"); |
| LINK_mm_camera_deinit(); |
| return false; |
| //pthread_exit((void*) ret_val); |
| } |
| |
| if (MM_CAMERA_SUCCESS != LINK_mm_camera_exec()) { |
| ALOGE("startCamera: mm_camera_exec failed:"); |
| return false; |
| //pthread_exit((void*) ret_val); |
| } |
| mCameraOpen = true; |
| ALOGV(" openCamera : X"); |
| if (CAMERA_MODE_3D == mode) { |
| camera_3d_frame_t snapshotFrame; |
| snapshotFrame.frame_type = CAM_SNAPSHOT_FRAME; |
| if(MM_CAMERA_SUCCESS != |
| mCfgControl.mm_camera_get_parm(CAMERA_PARM_3D_FRAME_FORMAT, |
| (void *)&snapshotFrame)){ |
| ALOGE("%s: get 3D format failed", __func__); |
| LINK_mm_camera_deinit(); |
| return false; |
| //pthread_exit((void*) ret_val); |
| } |
| QualcommCameraHardware* obj = QualcommCameraHardware::getInstance(); |
| if (obj != 0) { |
| obj->mSnapshot3DFormat = snapshotFrame.format; |
| ALOGI("%s: 3d format snapshot %d", __func__, obj->mSnapshot3DFormat); |
| } |
| } |
| |
| ALOGV("openCamera : X"); |
| // pthread_exit((void*) ret_val); |
| |
| return NULL; |
| } |
| //------------------------------------------------------------------------------------- |
| static Mutex singleton_lock; |
| static bool singleton_releasing; |
| static nsecs_t singleton_releasing_start_time; |
| static const nsecs_t SINGLETON_RELEASING_WAIT_TIME = seconds_to_nanoseconds(5); |
| static const nsecs_t SINGLETON_RELEASING_RECHECK_TIMEOUT = seconds_to_nanoseconds(1); |
| static Condition singleton_wait; |
| |
| static void receive_camframe_callback(struct msm_frame *frame); |
| static void receive_liveshot_callback(liveshot_status status, uint32_t jpeg_size); |
| static void receive_camstats_callback(camstats_type stype, camera_preview_histogram_info* histinfo); |
| static void receive_camframe_video_callback(struct msm_frame *frame); // 720p |
| static int8_t receive_event_callback(mm_camera_event* event); |
| static void receive_shutter_callback(common_crop_t *crop); |
| static void receive_camframe_error_callback(camera_error_type err); |
| static int fb_fd = -1; |
| static int32_t mMaxZoom = 0; |
| static bool zoomSupported = false; |
| static int dstOffset = 0; |
| |
| static int16_t * zoomRatios; |
| |
| |
| /* When using MDP zoom, double the preview buffers. The usage of these |
| * buffers is as follows: |
| * 1. As all the buffers comes under a single FD, and at initial registration, |
| * this FD will be passed to surface flinger, surface flinger can have access |
| * to all the buffers when needed. |
| * 2. Only "kPreviewBufferCount" buffers (SrcSet) will be registered with the |
| * camera driver to receive preview frames. The remaining buffers (DstSet), |
| * will be used at HAL and by surface flinger only when crop information |
| * is present in the frame. |
| * 3. When there is no crop information, there will be no call to MDP zoom, |
| * and the buffers in SrcSet will be passed to surface flinger to display. |
| * 4. With crop information present, MDP zoom will be called, and the final |
| * data will be placed in a buffer from DstSet, and this buffer will be given |
| * to surface flinger to display. |
| */ |
| #define NUM_MORE_BUFS 2 |
| |
| QualcommCameraHardware::QualcommCameraHardware() |
| : mParameters(), |
| mCameraRunning(false), |
| mPreviewInitialized(false), |
| mPreviewThreadRunning(false), |
| mHFRThreadRunning(false), |
| mFrameThreadRunning(false), |
| mVideoThreadRunning(false), |
| mSnapshotThreadRunning(false), |
| mJpegThreadRunning(false), |
| mSmoothzoomThreadRunning(false), |
| mSmoothzoomThreadExit(false), |
| mInSnapshotMode(false), |
| mEncodePending(false), |
| mBuffersInitialized(false), |
| mSnapshotFormat(0), |
| mFirstFrame(true), |
| mReleasedRecordingFrame(false), |
| mPreviewFrameSize(0), |
| mRawSize(0), |
| mCbCrOffsetRaw(0), |
| mYOffset(0), |
| mAutoFocusThreadRunning(false), |
| mInitialized(false), |
| mBrightness(0), |
| mSkinToneEnhancement(0), |
| mHJR(0), |
| mInPreviewCallback(false), |
| //mUseOverlay(0), |
| mIs3DModeOn(0), |
| //mOverlay(0), |
| mMsgEnabled(0), |
| mNotifyCallback(0), |
| mDataCallback(0), |
| mDataCallbackTimestamp(0), |
| mCallbackCookie(0), |
| mDebugFps(0), |
| mSnapshotDone(0), |
| maxSnapshotWidth(0), |
| maxSnapshotHeight(0), |
| mHasAutoFocusSupport(0), |
| mDisEnabled(0), |
| mRotation(0), |
| mResetWindowCrop(false), |
| mThumbnailWidth(0), |
| mThumbnailHeight(0), |
| strTexturesOn(false), |
| mPictureWidth(0), |
| mPictureHeight(0), |
| mPostviewWidth(0), |
| mPostviewHeight(0), |
| mPreviewWindow(NULL), |
| mTotalPreviewBufferCount(0), |
| mZslFlashEnable(false), |
| mZslPanorama(false), |
| mSnapshotCancel(false), |
| mHFRMode(false), |
| mActualPictWidth(0), |
| mActualPictHeight(0), |
| mDenoiseValue(0), |
| mPreviewStopping(false), |
| mInHFRThread(false), |
| mPrevHeapDeallocRunning(false), |
| mHdrMode(false ), |
| mExpBracketMode(false), |
| mZslEnable(false), |
| mStoreMetaDataInFrame(0), |
| mRecordingState(0) |
| { |
| ALOGI("QualcommCameraHardware constructor E"); |
| mMMCameraDLRef = MMCameraDL::getInstance(); |
| libmmcamera = mMMCameraDLRef->pointer(); |
| char value[PROPERTY_VALUE_MAX]; |
| mCameraOpen = false; |
| /*if(HAL_currentSnapshotMode == CAMERA_SNAPSHOT_ZSL) { |
| ALOGI("%s: this is ZSL mode", __FUNCTION__); |
| mZslEnable = true; |
| }*/ |
| |
| property_get("persist.camera.hal.multitouchaf", value, "0"); |
| mMultiTouch = atoi(value); |
| |
| storeTargetType(); |
| for(int i=0; i< MAX_SNAPSHOT_BUFFERS; i++) { |
| mRawMapped[i] = NULL; |
| mJpegMapped[i] = NULL; |
| mThumbnailMapped[i] = NULL; |
| } |
| mRawSnapshotMapped = NULL; |
| mJpegCopyMapped = NULL; |
| for(int i=0; i< RECORD_BUFFERS; i++) { |
| mRecordMapped[i] = NULL; |
| } |
| |
| for(int i=0; i<3; i++) |
| mStatsMapped[i] = NULL; |
| |
| mJpegLiveSnapMapped = NULL; |
| if(HAL_currentCameraMode == CAMERA_SUPPORT_MODE_3D){ |
| mIs3DModeOn = true; |
| } |
| /* TODO: Will remove this command line interface at end */ |
| property_get("persist.camera.hal.3dmode", value, "0"); |
| int mode = atoi(value); |
| if( mode == 1) { |
| mIs3DModeOn = true; |
| HAL_currentCameraMode = CAMERA_MODE_3D; |
| } |
| |
| if( (pthread_create(&mDeviceOpenThread, NULL, openCamera, NULL)) != 0) { |
| ALOGE(" openCamera thread creation failed "); |
| } |
| memset(&mDimension, 0, sizeof(mDimension)); |
| memset(&mCrop, 0, sizeof(mCrop)); |
| memset(&zoomCropInfo, 0, sizeof(android_native_rect_t)); |
| //storeTargetType(); |
| property_get("persist.debug.sf.showfps", value, "0"); |
| mDebugFps = atoi(value); |
| if( mCurrentTarget == TARGET_MSM7630 || mCurrentTarget == TARGET_MSM8660 ) { |
| kPreviewBufferCountActual = kPreviewBufferCount; |
| kRecordBufferCount = RECORD_BUFFERS; |
| recordframes = new msm_frame[kRecordBufferCount]; |
| record_buffers_tracking_flag = new bool[kRecordBufferCount]; |
| } |
| else { |
| kPreviewBufferCountActual = kPreviewBufferCount + NUM_MORE_BUFS; |
| if( mCurrentTarget == TARGET_QSD8250 ) { |
| kRecordBufferCount = RECORD_BUFFERS_8x50; |
| recordframes = new msm_frame[kRecordBufferCount]; |
| record_buffers_tracking_flag = new bool[kRecordBufferCount]; |
| } |
| } |
| mTotalPreviewBufferCount = kTotalPreviewBufferCount; |
| if((mCurrentTarget != TARGET_MSM7630 ) && (mCurrentTarget != TARGET_QSD8250) |
| && (mCurrentTarget != TARGET_MSM8660)) { |
| for (int i = 0; i < mTotalPreviewBufferCount; i++) |
| metadata_memory[i] = NULL; |
| } |
| else { |
| for (int i = 0; i < kRecordBufferCount; i++) |
| metadata_memory[i] = NULL; |
| } |
| switch(mCurrentTarget){ |
| case TARGET_MSM7627: |
| case TARGET_MSM7627A: |
| jpegPadding = 0; // to be checked. |
| break; |
| case TARGET_QSD8250: |
| case TARGET_MSM7630: |
| case TARGET_MSM8660: |
| jpegPadding = 0; |
| break; |
| default: |
| jpegPadding = 0; |
| break; |
| } |
| // Initialize with default format values. The format values can be |
| // overriden when application requests. |
| mDimension.prev_format = CAMERA_YUV_420_NV21; |
| mPreviewFormat = CAMERA_YUV_420_NV21; |
| mDimension.enc_format = CAMERA_YUV_420_NV21; |
| if((mCurrentTarget == TARGET_MSM7630) || (mCurrentTarget == TARGET_MSM8660)) |
| mDimension.enc_format = CAMERA_YUV_420_NV12; |
| mDimension.main_img_format = CAMERA_YUV_420_NV21; |
| mDimension.thumb_format = CAMERA_YUV_420_NV21; |
| |
| if( (mCurrentTarget == TARGET_MSM7630) || (mCurrentTarget == TARGET_MSM8660) ){ |
| /* DIS is disabled all the time in VPE support targets. |
| * No provision for the user to control this. |
| */ |
| mDisEnabled = 0; |
| /* Get the DIS value from properties, to check whether |
| * DIS is disabled or not. If the property is not found |
| * default to DIS disabled.*/ |
| property_get("persist.camera.hal.dis", value, "0"); |
| mDisEnabled = atoi(value); |
| mVpeEnabled = 1; |
| } |
| if(mIs3DModeOn) { |
| mDisEnabled = 0; |
| } |
| ALOGV("constructor EX"); |
| } |
| |
| void QualcommCameraHardware::hasAutoFocusSupport(){ |
| if( !mCamOps.mm_camera_is_supported(CAMERA_OPS_FOCUS)){ |
| ALOGI("AutoFocus is not supported"); |
| mHasAutoFocusSupport = false; |
| }else { |
| mHasAutoFocusSupport = true; |
| } |
| if(mZslEnable) |
| mHasAutoFocusSupport = false; |
| } |
| |
| //filter Picture sizes based on max width and height |
| void QualcommCameraHardware::filterPictureSizes(){ |
| unsigned int i; |
| if(PICTURE_SIZE_COUNT <= 0) |
| return; |
| maxSnapshotWidth = picture_sizes[0].width; |
| maxSnapshotHeight = picture_sizes[0].height; |
| // Iterate through all the width and height to find the max value |
| for(i =0; i<PICTURE_SIZE_COUNT;i++){ |
| if(((maxSnapshotWidth < picture_sizes[i].width) && |
| (maxSnapshotHeight <= picture_sizes[i].height))){ |
| maxSnapshotWidth = picture_sizes[i].width; |
| maxSnapshotHeight = picture_sizes[i].height; |
| } |
| } |
| if(mZslEnable){ |
| // due to lack of PMEM we restrict to lower resolution |
| picture_sizes_ptr = zsl_picture_sizes; |
| supportedPictureSizesCount = 7; |
| } |
| else if(mIs3DModeOn){ |
| // In 3D mode we only want 1080p picture size |
| picture_sizes_ptr = for_3D_picture_sizes; |
| supportedPictureSizesCount = 1; |
| } |
| else{ |
| picture_sizes_ptr = picture_sizes; |
| supportedPictureSizesCount = PICTURE_SIZE_COUNT; |
| } |
| } |
| |
| bool QualcommCameraHardware::supportsSceneDetection() { |
| unsigned int prop = 0; |
| for(prop=0; prop<sizeof(boardProperties)/sizeof(board_property); prop++) { |
| if((mCurrentTarget == boardProperties[prop].target) |
| && boardProperties[prop].hasSceneDetect == true) { |
| return true; |
| break; |
| } |
| } |
| return false; |
| } |
| |
| bool QualcommCameraHardware::supportsSelectableZoneAf() { |
| unsigned int prop = 0; |
| for(prop=0; prop<sizeof(boardProperties)/sizeof(board_property); prop++) { |
| if((mCurrentTarget == boardProperties[prop].target) |
| && boardProperties[prop].hasSelectableZoneAf == true) { |
| return true; |
| break; |
| } |
| } |
| return false; |
| } |
| |
| bool QualcommCameraHardware::supportsFaceDetection() { |
| unsigned int prop = 0; |
| for(prop=0; prop<sizeof(boardProperties)/sizeof(board_property); prop++) { |
| if((mCurrentTarget == boardProperties[prop].target) |
| && boardProperties[prop].hasFaceDetect == true) { |
| return true; |
| break; |
| } |
| } |
| return false; |
| } |
| |
| void QualcommCameraHardware::initDefaultParameters() |
| { |
| ALOGV("initDefaultParameters E"); |
| mDimension.picture_width = DEFAULT_PICTURE_WIDTH; |
| mDimension.picture_height = DEFAULT_PICTURE_HEIGHT; |
| mDimension.ui_thumbnail_width = |
| thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].width; |
| mDimension.ui_thumbnail_height = |
| thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height; |
| bool ret = native_set_parms(CAMERA_PARM_DIMENSION, |
| sizeof(cam_ctrl_dimension_t),(void *) &mDimension); |
| if(ret != true) { |
| ALOGE("CAMERA_PARM_DIMENSION failed!!!"); |
| return; |
| } |
| hasAutoFocusSupport(); |
| //Disable DIS for Web Camera |
| if( !mCfgControl.mm_camera_is_supported(CAMERA_PARM_VIDEO_DIS)){ |
| ALOGI("DISABLE DIS"); |
| mDisEnabled = 0; |
| }else { |
| ALOGI("Enable DIS"); |
| } |
| // Initialize constant parameter strings. This will happen only once in the |
| // lifetime of the mediaserver process. |
| if (!parameter_string_initialized) { |
| if(mIs3DModeOn){ |
| antibanding_values = create_values_str( |
| antibanding_3D, sizeof(antibanding_3D) / sizeof(str_map)); |
| } else{ |
| antibanding_values = create_values_str( |
| antibanding, sizeof(antibanding) / sizeof(str_map)); |
| } |
| effect_values = create_values_str( |
| effects, sizeof(effects) / sizeof(str_map)); |
| autoexposure_values = create_values_str( |
| autoexposure, sizeof(autoexposure) / sizeof(str_map)); |
| whitebalance_values = create_values_str( |
| whitebalance, sizeof(whitebalance) / sizeof(str_map)); |
| //filter picture sizes |
| filterPictureSizes(); |
| picture_size_values = create_sizes_str( |
| picture_sizes_ptr, supportedPictureSizesCount); |
| preview_size_values = create_sizes_str( |
| preview_sizes, PREVIEW_SIZE_COUNT); |
| mParameters.set(QCameraParameters::KEY_SUPPORTED_PREVIEW_SIZES, |
| preview_size_values.string()); |
| |
| mParameters.set(QCameraParameters::KEY_SUPPORTED_VIDEO_SIZES, |
| preview_size_values.string()); |
| |
| mParameters.set(QCameraParameters::KEY_SUPPORTED_PICTURE_SIZES, |
| picture_size_values.string()); |
| mParameters.set(QCameraParameters::KEY_VIDEO_SNAPSHOT_SUPPORTED, |
| "true"); |
| mParameters.set(QCameraParameters::KEY_SUPPORTED_FOCUS_MODES, |
| QCameraParameters::FOCUS_MODE_INFINITY); |
| mParameters.set(QCameraParameters::KEY_FOCUS_MODE, |
| QCameraParameters::FOCUS_MODE_INFINITY); |
| mParameters.set(QCameraParameters::KEY_MAX_NUM_FOCUS_AREAS, "1"); |
| |
| mParameters.set(QCameraParameters::KEY_FOCUS_AREAS, FOCUS_AREA_INIT); |
| mParameters.set(QCameraParameters::KEY_METERING_AREAS, FOCUS_AREA_INIT); |
| |
| if(!mIs3DModeOn){ |
| hfr_size_values = create_sizes_str( |
| hfr_sizes, HFR_SIZE_COUNT); |
| } |
| fps_ranges_supported_values = create_fps_str( |
| FpsRangesSupported,FPS_RANGES_SUPPORTED_COUNT ); |
| mParameters.set( |
| QCameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE, |
| fps_ranges_supported_values); |
| mParameters.setPreviewFpsRange(MINIMUM_FPS*1000,MAXIMUM_FPS*1000); |
| |
| flash_values = create_values_str( |
| flash, sizeof(flash) / sizeof(str_map)); |
| if(mHasAutoFocusSupport){ |
| focus_mode_values = create_values_str( |
| focus_modes, sizeof(focus_modes) / sizeof(str_map)); |
| } |
| if(mIs3DModeOn){ |
| iso_values = create_values_str( |
| iso_3D,sizeof(iso_3D)/sizeof(str_map)); |
| } else{ |
| iso_values = create_values_str( |
| iso,sizeof(iso)/sizeof(str_map)); |
| } |
| lensshade_values = create_values_str( |
| lensshade,sizeof(lensshade)/sizeof(str_map)); |
| mce_values = create_values_str( |
| mce,sizeof(mce)/sizeof(str_map)); |
| if(!mIs3DModeOn){ |
| hfr_values = create_values_str( |
| hfr,sizeof(hfr)/sizeof(str_map)); |
| } |
| if(mCurrentTarget == TARGET_MSM8660) |
| hdr_values = create_values_str( |
| hdr,sizeof(hdr)/sizeof(str_map)); |
| //Currently Enabling Histogram for 8x60 |
| if(mCurrentTarget == TARGET_MSM8660) { |
| histogram_values = create_values_str( |
| histogram,sizeof(histogram)/sizeof(str_map)); |
| } |
| //Currently Enabling Skin Tone Enhancement for 8x60 and 7630 |
| if((mCurrentTarget == TARGET_MSM8660)||(mCurrentTarget == TARGET_MSM7630)) { |
| skinToneEnhancement_values = create_values_str( |
| skinToneEnhancement,sizeof(skinToneEnhancement)/sizeof(str_map)); |
| } |
| if(mHasAutoFocusSupport){ |
| touchafaec_values = create_values_str( |
| touchafaec,sizeof(touchafaec)/sizeof(str_map)); |
| } |
| zsl_values = create_values_str( |
| zsl_modes,sizeof(zsl_modes)/sizeof(str_map)); |
| |
| if(mZslEnable){ |
| picture_format_values = create_values_str( |
| picture_formats_zsl, sizeof(picture_formats_zsl)/sizeof(str_map)); |
| } else{ |
| picture_format_values = create_values_str( |
| picture_formats, sizeof(picture_formats)/sizeof(str_map)); |
| } |
| if(mCurrentTarget == TARGET_MSM8660 || |
| (mCurrentTarget == TARGET_MSM7625A || |
| mCurrentTarget == TARGET_MSM7627A)) { |
| denoise_values = create_values_str( |
| denoise, sizeof(denoise) / sizeof(str_map)); |
| } |
| if(mCfgControl.mm_camera_query_parms(CAMERA_PARM_ZOOM_RATIO, |
| (void **)&zoomRatios, (uint32_t *) &mMaxZoom) == MM_CAMERA_SUCCESS) { |
| zoomSupported = true; |
| if( mMaxZoom >0) { |
| ALOGI("Maximum zoom value is %d", mMaxZoom); |
| if(zoomRatios != NULL) { |
| zoom_ratio_values = create_str(zoomRatios, mMaxZoom); |
| } else { |
| ALOGE("Failed to get zoomratios .."); |
| } |
| } else { |
| zoomSupported = false; |
| } |
| } else { |
| zoomSupported = false; |
| ALOGE("Failed to get maximum zoom value...setting max " |
| "zoom to zero"); |
| mMaxZoom = 0; |
| } |
| preview_frame_rate_values = create_values_range_str( |
| MINIMUM_FPS, MAXIMUM_FPS); |
| |
| scenemode_values = create_values_str( |
| scenemode, sizeof(scenemode) / sizeof(str_map)); |
| |
| if(supportsSceneDetection()) { |
| scenedetect_values = create_values_str( |
| scenedetect, sizeof(scenedetect) / sizeof(str_map)); |
| } |
| |
| if(mHasAutoFocusSupport && supportsSelectableZoneAf()){ |
| selectable_zone_af_values = create_values_str( |
| selectable_zone_af, sizeof(selectable_zone_af) / sizeof(str_map)); |
| } |
| |
| if(mHasAutoFocusSupport && supportsFaceDetection()) { |
| facedetection_values = create_values_str( |
| facedetection, sizeof(facedetection) / sizeof(str_map)); |
| } |
| |
| redeye_reduction_values = create_values_str( |
| redeye_reduction, sizeof(redeye_reduction) / sizeof(str_map)); |
| |
| parameter_string_initialized = true; |
| } |
| //set video size |
| if(( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250) || (mCurrentTarget == TARGET_MSM8660)) { |
| String8 vSize = create_sizes_str(preview_sizes, 1); |
| mParameters.set(QCameraParameters::KEY_VIDEO_SIZE, vSize.string()); |
| } |
| if(mIs3DModeOn){ |
| ALOGI("In initDefaultParameters - 3D mode on so set the default preview to 1280 x 720"); |
| mParameters.setPreviewSize(DEFAULT_PREVIEW_WIDTH_3D, DEFAULT_PREVIEW_HEIGHT_3D); |
| mDimension.display_width = DEFAULT_PREVIEW_WIDTH_3D; |
| mDimension.display_height = DEFAULT_PREVIEW_HEIGHT_3D; |
| } else{ |
| mParameters.setPreviewSize(DEFAULT_PREVIEW_WIDTH, DEFAULT_PREVIEW_HEIGHT); |
| mDimension.display_width = DEFAULT_PREVIEW_WIDTH; |
| mDimension.display_height = DEFAULT_PREVIEW_HEIGHT; |
| } |
| mParameters.setPreviewFrameRate(DEFAULT_FPS); |
| if( mCfgControl.mm_camera_is_supported(CAMERA_PARM_FPS)){ |
| mParameters.set( |
| QCameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES, |
| preview_frame_rate_values.string()); |
| } else { |
| mParameters.setPreviewFrameRate(DEFAULT_FIXED_FPS_VALUE); |
| mParameters.set( |
| QCameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES, |
| DEFAULT_FIXED_FPS_VALUE); |
| } |
| mParameters.setPreviewFrameRateMode("frame-rate-auto"); |
| mParameters.setPreviewFormat("yuv420sp"); // informative |
| mParameters.set("overlay-format", HAL_PIXEL_FORMAT_YCbCr_420_SP); |
| if(mIs3DModeOn){ |
| mParameters.setPictureSize(DEFAULT_PICTURE_WIDTH_3D, DEFAULT_PICTURE_HEIGHT_3D); |
| } else{ |
| mParameters.setPictureSize(DEFAULT_PICTURE_WIDTH, DEFAULT_PICTURE_HEIGHT); |
| } |
| mParameters.setPictureFormat("jpeg"); // informative |
| |
| mParameters.set(QCameraParameters::KEY_VIDEO_FRAME_FORMAT, "yuv420sp"); |
| |
| mParameters.set(QCameraParameters::KEY_JPEG_QUALITY, "85"); // max quality |
| |
| mParameters.set("power-mode-supported", "false"); |
| |
| mParameters.set(QCameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, |
| THUMBNAIL_WIDTH_STR); // informative |
| mParameters.set(QCameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, |
| THUMBNAIL_HEIGHT_STR); // informative |
| mDimension.ui_thumbnail_width = |
| thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].width; |
| mDimension.ui_thumbnail_height = |
| thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height; |
| mParameters.set(QCameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, "90"); |
| |
| String8 valuesStr = create_sizes_str(jpeg_thumbnail_sizes, JPEG_THUMBNAIL_SIZE_COUNT); |
| mParameters.set(QCameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES, |
| valuesStr.string()); |
| |
| // Define CAMERA_SMOOTH_ZOOM in Android.mk file , to enable smoothzoom |
| #ifdef CAMERA_SMOOTH_ZOOM |
| mParameters.set(QCameraParameters::KEY_SMOOTH_ZOOM_SUPPORTED, "true"); |
| #endif |
| |
| if(zoomSupported){ |
| mParameters.set(QCameraParameters::KEY_ZOOM_SUPPORTED, "true"); |
| ALOGI("max zoom is %d", mMaxZoom-1); |
| /* mMaxZoom value that the query interface returns is the size |
| * of zoom table. So the actual max zoom value will be one |
| * less than that value. |
| */ |
| mParameters.set("max-zoom",mMaxZoom-1); |
| mParameters.set(QCameraParameters::KEY_ZOOM_RATIOS, |
| zoom_ratio_values); |
| } else { |
| mParameters.set(QCameraParameters::KEY_ZOOM_SUPPORTED, "false"); |
| } |
| /* Enable zoom support for video application if VPE enabled */ |
| if(zoomSupported && mVpeEnabled) { |
| mParameters.set("video-zoom-support", "true"); |
| } else { |
| mParameters.set("video-zoom-support", "false"); |
| } |
| |
| mParameters.set(QCameraParameters::KEY_CAMERA_MODE,0); |
| |
| mParameters.set(QCameraParameters::KEY_ANTIBANDING, |
| QCameraParameters::ANTIBANDING_OFF); |
| mParameters.set(QCameraParameters::KEY_EFFECT, |
| QCameraParameters::EFFECT_NONE); |
| mParameters.set(QCameraParameters::KEY_AUTO_EXPOSURE, |
| QCameraParameters::AUTO_EXPOSURE_FRAME_AVG); |
| mParameters.set(QCameraParameters::KEY_WHITE_BALANCE, |
| QCameraParameters::WHITE_BALANCE_AUTO); |
| if( (mCurrentTarget != TARGET_MSM7630) |
| && (mCurrentTarget != TARGET_QSD8250) |
| && (mCurrentTarget != TARGET_MSM8660) |
| && (mCurrentTarget != TARGET_MSM7627A)) { |
| mParameters.set(QCameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS, |
| "yuv420sp"); |
| } else if(mCurrentTarget == TARGET_MSM7627A || mCurrentTarget == TARGET_MSM7627) { |
| preview_format_values = create_values_str( |
| preview_formats1, sizeof(preview_formats1) / sizeof(str_map)); |
| mParameters.set(QCameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS, |
| preview_format_values.string()); |
| } else { |
| preview_format_values = create_values_str( |
| preview_formats, sizeof(preview_formats) / sizeof(str_map)); |
| mParameters.set(QCameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS, |
| preview_format_values.string()); |
| } |
| |
| frame_rate_mode_values = create_values_str( |
| frame_rate_modes, sizeof(frame_rate_modes) / sizeof(str_map)); |
| if( mCfgControl.mm_camera_is_supported(CAMERA_PARM_FPS_MODE)){ |
| mParameters.set(QCameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATE_MODES, |
| frame_rate_mode_values.string()); |
| } |
| |
| mParameters.set(QCameraParameters::KEY_SUPPORTED_PREVIEW_SIZES, |
| preview_size_values.string()); |
| mParameters.set(QCameraParameters::KEY_SUPPORTED_PICTURE_SIZES, |
| picture_size_values.string()); |
| mParameters.set(QCameraParameters::KEY_SUPPORTED_ANTIBANDING, |
| antibanding_values); |
| mParameters.set(QCameraParameters::KEY_SUPPORTED_EFFECTS, effect_values); |
| mParameters.set(QCameraParameters::KEY_SUPPORTED_AUTO_EXPOSURE, autoexposure_values); |
| mParameters.set(QCameraParameters::KEY_SUPPORTED_WHITE_BALANCE, |
| whitebalance_values); |
| |
| if(mHasAutoFocusSupport){ |
| mParameters.set(QCameraParameters::KEY_SUPPORTED_FOCUS_MODES, |
| focus_mode_values); |
| mParameters.set(QCameraParameters::KEY_FOCUS_MODE, |
| QCameraParameters::FOCUS_MODE_AUTO); |
| } else { |
| mParameters.set(QCameraParameters::KEY_SUPPORTED_FOCUS_MODES, |
| QCameraParameters::FOCUS_MODE_INFINITY); |
| mParameters.set(QCameraParameters::KEY_FOCUS_MODE, |
| QCameraParameters::FOCUS_MODE_INFINITY); |
| } |
| |
| mParameters.set(QCameraParameters::KEY_SUPPORTED_PICTURE_FORMATS, |
| picture_format_values); |
| |
| if(mCfgControl.mm_camera_is_supported(CAMERA_PARM_LED_MODE)) { |
| mParameters.set(QCameraParameters::KEY_FLASH_MODE, |
| QCameraParameters::FLASH_MODE_OFF); |
| mParameters.set(QCameraParameters::KEY_SUPPORTED_FLASH_MODES, |
| flash_values); |
| } |
| |
| mParameters.set(QCameraParameters::KEY_MAX_SHARPNESS, |
| CAMERA_MAX_SHARPNESS); |
| mParameters.set(QCameraParameters::KEY_MAX_CONTRAST, |
| CAMERA_MAX_CONTRAST); |
| mParameters.set(QCameraParameters::KEY_MAX_SATURATION, |
| CAMERA_MAX_SATURATION); |
| |
| mParameters.set( |
| QCameraParameters::KEY_MAX_EXPOSURE_COMPENSATION, |
| EXPOSURE_COMPENSATION_MAXIMUM_NUMERATOR); |
| mParameters.set( |
| QCameraParameters::KEY_MIN_EXPOSURE_COMPENSATION, |
| EXPOSURE_COMPENSATION_MINIMUM_NUMERATOR); |
| mParameters.set( |
| QCameraParameters::KEY_EXPOSURE_COMPENSATION, |
| EXPOSURE_COMPENSATION_DEFAULT_NUMERATOR); |
| mParameters.setFloat( |
| QCameraParameters::KEY_EXPOSURE_COMPENSATION_STEP, |
| EXPOSURE_COMPENSATION_STEP); |
| |
| mParameters.set("luma-adaptation", "3"); |
| mParameters.set("skinToneEnhancement", "0"); |
| mParameters.set("zoom-supported", "true"); |
| mParameters.set("zoom", 0); |
| mParameters.set(QCameraParameters::KEY_PICTURE_FORMAT, |
| QCameraParameters::PIXEL_FORMAT_JPEG); |
| |
| mParameters.set(QCameraParameters::KEY_SHARPNESS, |
| CAMERA_DEF_SHARPNESS); |
| mParameters.set(QCameraParameters::KEY_CONTRAST, |
| CAMERA_DEF_CONTRAST); |
| mParameters.set(QCameraParameters::KEY_SATURATION, |
| CAMERA_DEF_SATURATION); |
| |
| mParameters.set(QCameraParameters::KEY_ISO_MODE, |
| QCameraParameters::ISO_AUTO); |
| mParameters.set(QCameraParameters::KEY_LENSSHADE, |
| QCameraParameters::LENSSHADE_ENABLE); |
| mParameters.set(QCameraParameters::KEY_SUPPORTED_ISO_MODES, |
| iso_values); |
| mParameters.set(QCameraParameters::KEY_SUPPORTED_LENSSHADE_MODES, |
| lensshade_values); |
| mParameters.set(QCameraParameters::KEY_MEMORY_COLOR_ENHANCEMENT, |
| QCameraParameters::MCE_ENABLE); |
| mParameters.set(QCameraParameters::KEY_SUPPORTED_MEM_COLOR_ENHANCE_MODES, |
| mce_values); |
| if(mCfgControl.mm_camera_is_supported(CAMERA_PARM_HFR) && !(mIs3DModeOn)) { |
| mParameters.set(QCameraParameters::KEY_VIDEO_HIGH_FRAME_RATE, |
| QCameraParameters::VIDEO_HFR_OFF); |
| mParameters.set(QCameraParameters::KEY_SUPPORTED_HFR_SIZES, |
| hfr_size_values.string()); |
| mParameters.set(QCameraParameters::KEY_SUPPORTED_VIDEO_HIGH_FRAME_RATE_MODES, |
| hfr_values); |
| } else |
| mParameters.set(QCameraParameters::KEY_SUPPORTED_HFR_SIZES,""); |
| |
| mParameters.set(QCameraParameters::KEY_HIGH_DYNAMIC_RANGE_IMAGING, |
| QCameraParameters::MCE_DISABLE); |
| mParameters.set(QCameraParameters::KEY_SUPPORTED_HDR_IMAGING_MODES, |
| hdr_values); |
| mParameters.set(QCameraParameters::KEY_HISTOGRAM, |
| QCameraParameters::HISTOGRAM_DISABLE); |
| mParameters.set(QCameraParameters::KEY_SUPPORTED_HISTOGRAM_MODES, |
| histogram_values); |
| mParameters.set(QCameraParameters::KEY_SKIN_TONE_ENHANCEMENT, |
| QCameraParameters::SKIN_TONE_ENHANCEMENT_DISABLE); |
| mParameters.set(QCameraParameters::KEY_SUPPORTED_SKIN_TONE_ENHANCEMENT_MODES, |
| skinToneEnhancement_values); |
| mParameters.set(QCameraParameters::KEY_SCENE_MODE, |
| QCameraParameters::SCENE_MODE_AUTO); |
| mParameters.set("strtextures", "OFF"); |
| |
| mParameters.set(QCameraParameters::KEY_SUPPORTED_SCENE_MODES, |
| scenemode_values); |
| mParameters.set(QCameraParameters::KEY_DENOISE, |
| QCameraParameters::DENOISE_OFF); |
| mParameters.set(QCameraParameters::KEY_SUPPORTED_DENOISE, |
| denoise_values); |
| |
| //touch af/aec parameters |
| mParameters.set(QCameraParameters::KEY_TOUCH_AF_AEC, |
| QCameraParameters::TOUCH_AF_AEC_OFF); |
| mParameters.set(QCameraParameters::KEY_SUPPORTED_TOUCH_AF_AEC, |
| touchafaec_values); |
| mParameters.set("touchAfAec-dx","100"); |
| mParameters.set("touchAfAec-dy","100"); |
| mParameters.set(QCameraParameters::KEY_MAX_NUM_FOCUS_AREAS, "1"); |
| mParameters.set(QCameraParameters::KEY_MAX_NUM_METERING_AREAS, "1"); |
| |
| mParameters.set(QCameraParameters::KEY_SCENE_DETECT, |
| QCameraParameters::SCENE_DETECT_OFF); |
| mParameters.set(QCameraParameters::KEY_SUPPORTED_SCENE_DETECT, |
| scenedetect_values); |
| mParameters.set(QCameraParameters::KEY_SELECTABLE_ZONE_AF, |
| QCameraParameters::SELECTABLE_ZONE_AF_AUTO); |
| mParameters.set(QCameraParameters::KEY_SUPPORTED_SELECTABLE_ZONE_AF, |
| selectable_zone_af_values); |
| mParameters.set(QCameraParameters::KEY_FACE_DETECTION, |
| QCameraParameters::FACE_DETECTION_OFF); |
| mParameters.set(QCameraParameters::KEY_SUPPORTED_FACE_DETECTION, |
| facedetection_values); |
| mParameters.set(QCameraParameters::KEY_REDEYE_REDUCTION, |
| QCameraParameters::REDEYE_REDUCTION_DISABLE); |
| mParameters.set(QCameraParameters::KEY_SUPPORTED_REDEYE_REDUCTION, |
| redeye_reduction_values); |
| mParameters.set(QCameraParameters::KEY_ZSL, |
| QCameraParameters::ZSL_OFF); |
| mParameters.set(QCameraParameters::KEY_SUPPORTED_ZSL_MODES, |
| zsl_values); |
| |
| float focalLength = 0.0f; |
| float horizontalViewAngle = 0.0f; |
| float verticalViewAngle = 0.0f; |
| |
| mCfgControl.mm_camera_get_parm(CAMERA_PARM_FOCAL_LENGTH, |
| (void *)&focalLength); |
| mParameters.setFloat(QCameraParameters::KEY_FOCAL_LENGTH, |
| focalLength); |
| mCfgControl.mm_camera_get_parm(CAMERA_PARM_HORIZONTAL_VIEW_ANGLE, |
| (void *)&horizontalViewAngle); |
| mParameters.setFloat(QCameraParameters::KEY_HORIZONTAL_VIEW_ANGLE, |
| horizontalViewAngle); |
| mCfgControl.mm_camera_get_parm(CAMERA_PARM_VERTICAL_VIEW_ANGLE, |
| (void *)&verticalViewAngle); |
| mParameters.setFloat(QCameraParameters::KEY_VERTICAL_VIEW_ANGLE, |
| verticalViewAngle); |
| numCapture = 1; |
| if(mZslEnable) { |
| int maxSnapshot = MAX_SNAPSHOT_BUFFERS - 2; |
| char value[5]; |
| property_get("persist.camera.hal.capture", value, "1"); |
| numCapture = atoi(value); |
| if(numCapture > maxSnapshot) |
| numCapture = maxSnapshot; |
| else if(numCapture < 1) |
| numCapture = 1; |
| mParameters.set("capture-burst-captures-values", maxSnapshot); |
| mParameters.set("capture-burst-interval-supported", "false"); |
| } |
| mParameters.set("num-snaps-per-shutter", numCapture); |
| ALOGI("%s: setting num-snaps-per-shutter to %d", __FUNCTION__, numCapture); |
| if(mIs3DModeOn) |
| mParameters.set("3d-frame-format", "left-right"); |
| |
| switch(mCurrentTarget){ |
| case TARGET_MSM7627: |
| case TARGET_QSD8250: |
| case TARGET_MSM7630: |
| mParameters.set(QCameraParameters::KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO, "800x480"); |
| break; |
| case TARGET_MSM7627A: |
| mParameters.set(QCameraParameters::KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO, "864x480"); |
| break; |
| case TARGET_MSM8660: |
| mParameters.set(QCameraParameters::KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO, "1920x1088"); |
| break; |
| default: |
| mParameters.set(QCameraParameters::KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO, "640x480"); |
| break; |
| } |
| if (setParameters(mParameters) != NO_ERROR) { |
| ALOGE("Failed to set default parameters?!"); |
| } |
| |
| /* Initialize the camframe_timeout_flag*/ |
| Mutex::Autolock l(&mCamframeTimeoutLock); |
| camframe_timeout_flag = FALSE; |
| mPostviewHeap = NULL; |
| mDisplayHeap = NULL; |
| mLastPreviewFrameHeap = NULL; |
| mThumbnailHeap = NULL; |
| |
| mInitialized = true; |
| strTexturesOn = false; |
| |
| ALOGV("initDefaultParameters X"); |
| } |
| |
| |
| #define ROUND_TO_PAGE(x) (((x)+0xfff)&~0xfff) |
| |
| bool QualcommCameraHardware::startCamera() |
| { |
| ALOGV("startCamera E"); |
| if( mCurrentTarget == TARGET_MAX ) { |
| ALOGE(" Unable to determine the target type. Camera will not work "); |
| return false; |
| } |
| #if DLOPEN_LIBMMCAMERA |
| |
| ALOGV("loading liboemcamera at %p", libmmcamera); |
| if (!libmmcamera) { |
| ALOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror()); |
| return false; |
| } |
| |
| *(void **)&LINK_cam_frame = |
| ::dlsym(libmmcamera, "cam_frame"); |
| *(void **)&LINK_wait_cam_frame_thread_ready = |
| ::dlsym(libmmcamera, "wait_cam_frame_thread_ready"); |
| *(void **)&LINK_cam_frame_set_exit_flag = |
| ::dlsym(libmmcamera, "cam_frame_set_exit_flag"); |
| *(void **)&LINK_camframe_terminate = |
| ::dlsym(libmmcamera, "camframe_terminate"); |
| |
| *(void **)&LINK_jpeg_encoder_init = |
| ::dlsym(libmmcamera, "jpeg_encoder_init"); |
| |
| *(void **)&LINK_jpeg_encoder_encode = |
| ::dlsym(libmmcamera, "jpeg_encoder_encode"); |
| |
| *(void **)&LINK_jpeg_encoder_join = |
| ::dlsym(libmmcamera, "jpeg_encoder_join"); |
| |
| mCamNotify.preview_frame_cb = &receive_camframe_callback; |
| |
| mCamNotify.camstats_cb = &receive_camstats_callback; |
| |
| mCamNotify.on_event = &receive_event_callback; |
| |
| mCamNotify.on_error_event = &receive_camframe_error_callback; |
| |
| // 720 p new recording functions |
| mCamNotify.video_frame_cb = &receive_camframe_video_callback; |
| // 720 p new recording functions |
| |
| *(void **)&LINK_camframe_add_frame = ::dlsym(libmmcamera, "camframe_add_frame"); |
| |
| *(void **)&LINK_camframe_release_all_frames = ::dlsym(libmmcamera, "camframe_release_all_frames"); |
| |
| *(void **)&LINK_mmcamera_shutter_callback = |
| ::dlsym(libmmcamera, "mmcamera_shutter_callback"); |
| |
| *LINK_mmcamera_shutter_callback = receive_shutter_callback; |
| |
| *(void**)&LINK_jpeg_encoder_setMainImageQuality = |
| ::dlsym(libmmcamera, "jpeg_encoder_setMainImageQuality"); |
| |
| *(void**)&LINK_jpeg_encoder_setThumbnailQuality = |
| ::dlsym(libmmcamera, "jpeg_encoder_setThumbnailQuality"); |
| |
| *(void**)&LINK_jpeg_encoder_setRotation = |
| ::dlsym(libmmcamera, "jpeg_encoder_setRotation"); |
| |
| *(void**)&LINK_jpeg_encoder_get_buffer_offset = |
| ::dlsym(libmmcamera, "jpeg_encoder_get_buffer_offset"); |
| |
| *(void**)&LINK_jpeg_encoder_set_3D_info = |
| ::dlsym(libmmcamera, "jpeg_encoder_set_3D_info"); |
| |
| /* Disabling until support is available. |
| *(void**)&LINK_jpeg_encoder_setLocation = |
| ::dlsym(libmmcamera, "jpeg_encoder_setLocation"); |
| */ |
| *(void **)&LINK_cam_conf = |
| ::dlsym(libmmcamera, "cam_conf"); |
| |
| /* Disabling until support is available. |
| *(void **)&LINK_default_sensor_get_snapshot_sizes = |
| ::dlsym(libmmcamera, "default_sensor_get_snapshot_sizes"); |
| */ |
| *(void **)&LINK_launch_cam_conf_thread = |
| ::dlsym(libmmcamera, "launch_cam_conf_thread"); |
| |
| *(void **)&LINK_release_cam_conf_thread = |
| ::dlsym(libmmcamera, "release_cam_conf_thread"); |
| |
| mCamNotify.on_liveshot_event = &receive_liveshot_callback; |
| |
| *(void **)&LINK_cancel_liveshot = |
| ::dlsym(libmmcamera, "cancel_liveshot"); |
| |
| *(void **)&LINK_set_liveshot_params = |
| ::dlsym(libmmcamera, "set_liveshot_params"); |
| |
| *(void **)&LINK_set_liveshot_frame = |
| ::dlsym(libmmcamera, "set_liveshot_frame"); |
| |
| *(void **)&LINK_mm_camera_destroy = |
| ::dlsym(libmmcamera, "mm_camera_destroy"); |
| |
| *(void **)&LINK_yuv_convert_ycrcb420sp_to_yv12_inplace = |
| ::dlsym(libmmcamera, "yuv_convert_ycrcb420sp_to_yv12"); |
| |
| *(void **)&LINK_yuv_convert_ycrcb420sp_to_yv12 = |
| ::dlsym(libmmcamera, "yuv_convert_ycrcb420sp_to_yv12_ver2"); |
| |
| /* Disabling until support is available.*/ |
| *(void **)&LINK_zoom_crop_upscale = |
| ::dlsym(libmmcamera, "zoom_crop_upscale"); |
| |
| |
| #else |
| mCamNotify.preview_frame_cb = &receive_camframe_callback; |
| mCamNotify.camstats_cb = &receive_camstats_callback; |
| mCamNotify.on_event = &receive_event_callback; |
| |
| mmcamera_shutter_callback = receive_shutter_callback; |
| mCamNotify.on_liveshot_event = &receive_liveshot_callback; |
| mCamNotify.video_frame_cb = &receive_camframe_video_callback; |
| |
| #endif // DLOPEN_LIBMMCAMERA |
| #if 0 //commenting this for now as not getting graphics permission |
| if((mCurrentTarget != TARGET_MSM7630) && (mCurrentTarget != TARGET_MSM8660)){ |
| fb_fd = open("/dev/graphics/fb0", O_RDWR); |
| if (fb_fd < 0) { |
| ALOGE("startCamera: fb0 open failed: %s!", strerror(errno)); |
| return FALSE; |
| } |
| } |
| #endif |
| int ret_val; |
| if (pthread_join(mDeviceOpenThread, (void**)&ret_val) != 0) { |
| ALOGE("openCamera thread exit failed"); |
| return false; |
| } |
| |
| if (!mCameraOpen) { |
| ALOGE("openCamera() failed"); |
| return false; |
| } |
| |
| |
| mCfgControl.mm_camera_query_parms(CAMERA_PARM_PICT_SIZE, (void **)&picture_sizes, &PICTURE_SIZE_COUNT); |
| if ((picture_sizes == NULL) || (!PICTURE_SIZE_COUNT)) { |
| ALOGE("startCamera X: could not get snapshot sizes"); |
| return false; |
| } |
| ALOGI("startCamera picture_sizes %p PICTURE_SIZE_COUNT %d", picture_sizes, PICTURE_SIZE_COUNT); |
| mCfgControl.mm_camera_query_parms(CAMERA_PARM_PREVIEW_SIZE, (void **)&preview_sizes, &PREVIEW_SIZE_COUNT); |
| if ((preview_sizes == NULL) || (!PREVIEW_SIZE_COUNT)) { |
| ALOGE("startCamera X: could not get preview sizes"); |
| return false; |
| } |
| ALOGI("startCamera preview_sizes %p previewSizeCount %d", preview_sizes, PREVIEW_SIZE_COUNT); |
| |
| mCfgControl.mm_camera_query_parms(CAMERA_PARM_HFR_SIZE, (void **)&hfr_sizes, &HFR_SIZE_COUNT); |
| if ((hfr_sizes == NULL) || (!HFR_SIZE_COUNT)) { |
| ALOGE("startCamera X: could not get hfr sizes"); |
| return false; |
| } |
| ALOGI("startCamera hfr_sizes %p hfrSizeCount %d", hfr_sizes, HFR_SIZE_COUNT); |
| |
| |
| ALOGV("startCamera X"); |
| return true; |
| } |
| |
| status_t QualcommCameraHardware::dump(int fd, |
| const Vector<String16>& args) const |
| { |
| const size_t SIZE = 256; |
| char buffer[SIZE]; |
| String8 result; |
| #if 0 |
| // Dump internal primitives. |
| result.append("QualcommCameraHardware::dump"); |
| snprintf(buffer, 255, "mMsgEnabled (%d)\n", mMsgEnabled); |
| result.append(buffer); |
| int width, height; |
| mParameters.getPreviewSize(&width, &height); |
| snprintf(buffer, 255, "preview width(%d) x height (%d)\n", width, height); |
| result.append(buffer); |
| mParameters.getPictureSize(&width, &height); |
| snprintf(buffer, 255, "raw width(%d) x height (%d)\n", width, height); |
| result.append(buffer); |
| snprintf(buffer, 255, |
| "preview frame size(%d), raw size (%d), jpeg size (%d) " |
| "and jpeg max size (%d)\n", mPreviewFrameSize, mRawSize, |
| mJpegSize, mJpegMaxSize); |
| result.append(buffer); |
| write(fd, result.string(), result.size()); |
| |
| // Dump internal objects. |
| if (mPreviewHeap[0] != 0) { |
| mPreviewHeap[0]->dump(fd, args); |
| } |
| if (mRawHeap != 0) { |
| mRawHeap->dump(fd, args); |
| } |
| if (mJpegHeap != 0) { |
| mJpegHeap->dump(fd, args); |
| } |
| mParameters.dump(fd, args); |
| #endif |
| return NO_ERROR; |
| } |
| |
| /* Issue ioctl calls related to starting Camera Operations*/ |
| bool static native_start_ops(mm_camera_ops_type_t type, void* value) |
| { |
| if(mCamOps.mm_camera_start(type, value,NULL) != MM_CAMERA_SUCCESS) { |
| ALOGE("native_start_ops: type %d error %s", |
| type,strerror(errno)); |
| return false; |
| } |
| return true; |
| } |
| |
| /* Issue ioctl calls related to stopping Camera Operations*/ |
| bool static native_stop_ops(mm_camera_ops_type_t type, void* value) |
| { |
| if(mCamOps.mm_camera_stop(type, value,NULL) != MM_CAMERA_SUCCESS) { |
| ALOGE("native_stop_ops: type %d error %s", |
| type,strerror(errno)); |
| return false; |
| } |
| return true; |
| } |
| /*==========================================================================*/ |
| |
| |
| #define GPS_PROCESSING_METHOD_SIZE 101 |
| #define FOCAL_LENGTH_DECIMAL_PRECISON 100 |
| |
| static const char ExifAsciiPrefix[] = { 0x41, 0x53, 0x43, 0x49, 0x49, 0x0, 0x0, 0x0 }; |
| #define EXIF_ASCII_PREFIX_SIZE (sizeof(ExifAsciiPrefix)) |
| |
| static rat_t latitude[3]; |
| static rat_t longitude[3]; |
| static char lonref[2]; |
| static char latref[2]; |
| static rat_t altitude; |
| static rat_t gpsTimestamp[3]; |
| static char gpsDatestamp[20]; |
| static char dateTime[20]; |
| static rat_t focalLength; |
| static uint16_t flashMode; |
| static int iso_arr[] = {0,1,100,200,400,800,1600}; |
| static uint16_t isoMode; |
| static char gpsProcessingMethod[EXIF_ASCII_PREFIX_SIZE + GPS_PROCESSING_METHOD_SIZE]; |
| static void addExifTag(exif_tag_id_t tagid, exif_tag_type_t type, |
| uint32_t count, uint8_t copy, void *data) { |
| |
| if(exif_table_numEntries == MAX_EXIF_TABLE_ENTRIES) { |
| ALOGE("Number of entries exceeded limit"); |
| return; |
| } |
| |
| int index = exif_table_numEntries; |
| exif_data[index].tag_id = tagid; |
| exif_data[index].tag_entry.type = type; |
| exif_data[index].tag_entry.count = count; |
| exif_data[index].tag_entry.copy = copy; |
| if((type == EXIF_RATIONAL) && (count > 1)) |
| exif_data[index].tag_entry.data._rats = (rat_t *)data; |
| if((type == EXIF_RATIONAL) && (count == 1)) |
| exif_data[index].tag_entry.data._rat = *(rat_t *)data; |
| else if(type == EXIF_ASCII) |
| exif_data[index].tag_entry.data._ascii = (char *)data; |
| else if(type == EXIF_BYTE) |
| exif_data[index].tag_entry.data._byte = *(uint8_t *)data; |
| else if((type == EXIF_SHORT) && (count > 1)) |
| exif_data[index].tag_entry.data._shorts = (uint16_t *)data; |
| else if((type == EXIF_SHORT) && (count == 1)) |
| exif_data[index].tag_entry.data._short = *(uint16_t *)data; |
| // Increase number of entries |
| exif_table_numEntries++; |
| } |
| |
| static void parseLatLong(const char *latlonString, int *pDegrees, |
| int *pMinutes, int *pSeconds ) { |
| |
| double value = atof(latlonString); |
| value = fabs(value); |
| int degrees = (int) value; |
| |
| double remainder = value - degrees; |
| int minutes = (int) (remainder * 60); |
| int seconds = (int) (((remainder * 60) - minutes) * 60 * 1000); |
| |
| *pDegrees = degrees; |
| *pMinutes = minutes; |
| *pSeconds = seconds; |
| } |
| |
| static void setLatLon(exif_tag_id_t tag, const char *latlonString) { |
| |
| int degrees, minutes, seconds; |
| |
| parseLatLong(latlonString, °rees, &minutes, &seconds); |
| |
| rat_t value[3] = { {degrees, 1}, |
| {minutes, 1}, |
| {seconds, 1000} }; |
| |
| if(tag == EXIFTAGID_GPS_LATITUDE) { |
| memcpy(latitude, value, sizeof(latitude)); |
| addExifTag(EXIFTAGID_GPS_LATITUDE, EXIF_RATIONAL, 3, |
| 1, (void *)latitude); |
| } else { |
| memcpy(longitude, value, sizeof(longitude)); |
| addExifTag(EXIFTAGID_GPS_LONGITUDE, EXIF_RATIONAL, 3, |
| 1, (void *)longitude); |
| } |
| } |
| |
| void QualcommCameraHardware::setGpsParameters() { |
| const char *str = NULL; |
| |
| str = mParameters.get(QCameraParameters::KEY_GPS_PROCESSING_METHOD); |
| |
| if(str!=NULL ){ |
| memcpy(gpsProcessingMethod, ExifAsciiPrefix, EXIF_ASCII_PREFIX_SIZE); |
| strncpy(gpsProcessingMethod + EXIF_ASCII_PREFIX_SIZE, str, |
| GPS_PROCESSING_METHOD_SIZE - 1); |
| gpsProcessingMethod[EXIF_ASCII_PREFIX_SIZE + GPS_PROCESSING_METHOD_SIZE-1] = '\0'; |
| addExifTag(EXIFTAGID_GPS_PROCESSINGMETHOD, EXIF_ASCII, |
| EXIF_ASCII_PREFIX_SIZE + strlen(gpsProcessingMethod + EXIF_ASCII_PREFIX_SIZE) + 1, |
| 1, (void *)gpsProcessingMethod); |
| } |
| |
| str = NULL; |
| |
| //Set Latitude |
| str = mParameters.get(QCameraParameters::KEY_GPS_LATITUDE); |
| if(str != NULL) { |
| setLatLon(EXIFTAGID_GPS_LATITUDE, str); |
| //set Latitude Ref |
| float latitudeValue = mParameters.getFloat(QCameraParameters::KEY_GPS_LATITUDE); |
| latref[0] = 'N'; |
| if(latitudeValue < 0 ){ |
| latref[0] = 'S'; |
| } |
| latref[1] = '\0'; |
| mParameters.set(QCameraParameters::KEY_GPS_LATITUDE_REF, latref); |
| addExifTag(EXIFTAGID_GPS_LATITUDE_REF, EXIF_ASCII, 2, |
| 1, (void *)latref); |
| } |
| |
| //set Longitude |
| str = NULL; |
| str = mParameters.get(QCameraParameters::KEY_GPS_LONGITUDE); |
| if(str != NULL) { |
| setLatLon(EXIFTAGID_GPS_LONGITUDE, str); |
| //set Longitude Ref |
| float longitudeValue = mParameters.getFloat(QCameraParameters::KEY_GPS_LONGITUDE); |
| lonref[0] = 'E'; |
| if(longitudeValue < 0){ |
| lonref[0] = 'W'; |
| } |
| lonref[1] = '\0'; |
| mParameters.set(QCameraParameters::KEY_GPS_LONGITUDE_REF, lonref); |
| addExifTag(EXIFTAGID_GPS_LONGITUDE_REF, EXIF_ASCII, 2, |
| 1, (void *)lonref); |
| } |
| |
| //set Altitude |
| str = NULL; |
| str = mParameters.get(QCameraParameters::KEY_GPS_ALTITUDE); |
| if(str != NULL) { |
| double value = atof(str); |
| int ref = 0; |
| if(value < 0){ |
| ref = 1; |
| value = -value; |
| } |
| uint32_t value_meter = value * 1000; |
| rat_t alt_value = {value_meter, 1000}; |
| memcpy(&altitude, &alt_value, sizeof(altitude)); |
| addExifTag(EXIFTAGID_GPS_ALTITUDE, EXIF_RATIONAL, 1, |
| 1, (void *)&altitude); |
| //set AltitudeRef |
| mParameters.set(QCameraParameters::KEY_GPS_ALTITUDE_REF, ref); |
| addExifTag(EXIFTAGID_GPS_ALTITUDE_REF, EXIF_BYTE, 1, |
| 1, (void *)&ref); |
| } |
| |
| //set Gps TimeStamp |
| str = NULL; |
| str = mParameters.get(QCameraParameters::KEY_GPS_TIMESTAMP); |
| if(str != NULL) { |
| |
| long value = atol(str); |
| time_t unixTime; |
| struct tm *UTCTimestamp; |
| |
| unixTime = (time_t)value; |
| UTCTimestamp = gmtime(&unixTime); |
| |
| strftime(gpsDatestamp, sizeof(gpsDatestamp), "%Y:%m:%d", UTCTimestamp); |
| addExifTag(EXIFTAGID_GPS_DATESTAMP, EXIF_ASCII, |
| strlen(gpsDatestamp)+1 , 1, (void *)&gpsDatestamp); |
| |
| rat_t time_value[3] = { {UTCTimestamp->tm_hour, 1}, |
| {UTCTimestamp->tm_min, 1}, |
| {UTCTimestamp->tm_sec, 1} }; |
| |
| |
| memcpy(&gpsTimestamp, &time_value, sizeof(gpsTimestamp)); |
| addExifTag(EXIFTAGID_GPS_TIMESTAMP, EXIF_RATIONAL, |
| 3, 1, (void *)&gpsTimestamp); |
| } |
| |
| } |
| |
| |
| bool QualcommCameraHardware::initZslParameter(void) |
| { ALOGV("%s: E", __FUNCTION__); |
| mParameters.getPictureSize(&mPictureWidth, &mPictureHeight); |
| ALOGI("initZslParamter E: picture size=%dx%d", mPictureWidth, mPictureHeight); |
| if (updatePictureDimension(mParameters, mPictureWidth, mPictureHeight)) { |
| mDimension.picture_width = mPictureWidth; |
| mDimension.picture_height = mPictureHeight; |
| } |
| |
| /* use the default thumbnail sizes */ |
| mZslParms.picture_width = mPictureWidth; |
| mZslParms.picture_height = mPictureHeight; |
| mZslParms.preview_width = mDimension.display_width; |
| mZslParms.preview_height = mDimension.display_height; |
| mZslParms.useExternalBuffers = TRUE; |
| /* fill main image size, thumbnail size, postview size into capture_params_t*/ |
| memset(&mZslCaptureParms, 0, sizeof(zsl_capture_params_t)); |
| mZslCaptureParms.thumbnail_height = mPostviewHeight; |
| mZslCaptureParms.thumbnail_width = mPostviewWidth; |
| ALOGI("Number of snapshot to capture: %d",numCapture); |
| mZslCaptureParms.num_captures = numCapture; |
| |
| return true; |
| } |
| |
| |
| bool QualcommCameraHardware::initImageEncodeParameters(int size) |
| { |
| ALOGV("%s: E", __FUNCTION__); |
| memset(&mImageEncodeParms, 0, sizeof(encode_params_t)); |
| int jpeg_quality = mParameters.getInt("jpeg-quality"); |
| bool ret; |
| if (jpeg_quality >= 0) { |
| ALOGI("initJpegParameters, current jpeg main img quality =%d", |
| jpeg_quality); |
| //Application can pass quality of zero |
| //when there is no back sensor connected. |
| //as jpeg quality of zero is not accepted at |
| //camera stack, pass default value. |
| if(jpeg_quality == 0) jpeg_quality = 85; |
| mImageEncodeParms.quality = jpeg_quality; |
| ret = native_set_parms(CAMERA_PARM_JPEG_MAINIMG_QUALITY, sizeof(int), &jpeg_quality); |
| if(!ret){ |
| ALOGE("initJpegParametersX: failed to set main image quality"); |
| return false; |
| } |
| } |
| |
| int thumbnail_quality = mParameters.getInt("jpeg-thumbnail-quality"); |
| if (thumbnail_quality >= 0) { |
| //Application can pass quality of zero |
| //when there is no back sensor connected. |
| //as quality of zero is not accepted at |
| //camera stack, pass default value. |
| if(thumbnail_quality == 0) thumbnail_quality = 85; |
| ALOGI("initJpegParameters, current jpeg thumbnail quality =%d", |
| thumbnail_quality); |
| /* TODO: check with mm-camera? */ |
| mImageEncodeParms.quality = thumbnail_quality; |
| ret = native_set_parms(CAMERA_PARM_JPEG_THUMB_QUALITY, sizeof(int), &thumbnail_quality); |
| if(!ret){ |
| ALOGE("initJpegParameters X: failed to set thumbnail quality"); |
| return false; |
| } |
| } |
| |
| int rotation = mParameters.getInt("rotation"); |
| char mDeviceName[PROPERTY_VALUE_MAX]; |
| property_get("ro.hw_plat", mDeviceName, ""); |
| if(!strcmp(mDeviceName,"7x25A")) |
| rotation = (rotation + 90)%360; |
| |
| if (mIs3DModeOn) |
| rotation = 0; |
| if (rotation >= 0) { |
| ALOGI("initJpegParameters, rotation = %d", rotation); |
| mImageEncodeParms.rotation = rotation; |
| } |
| |
| jpeg_set_location(); |
| |
| //set TimeStamp |
| const char *str = mParameters.get(QCameraParameters::KEY_EXIF_DATETIME); |
| if(str != NULL) { |
| strncpy(dateTime, str, 19); |
| dateTime[19] = '\0'; |
| addExifTag(EXIFTAGID_EXIF_DATE_TIME_ORIGINAL, EXIF_ASCII, |
| 20, 1, (void *)dateTime); |
| } |
| |
| int focalLengthValue = (int) (mParameters.getFloat( |
| QCameraParameters::KEY_FOCAL_LENGTH) * FOCAL_LENGTH_DECIMAL_PRECISON); |
| rat_t focalLengthRational = {focalLengthValue, FOCAL_LENGTH_DECIMAL_PRECISON}; |
| memcpy(&focalLength, &focalLengthRational, sizeof(focalLengthRational)); |
| addExifTag(EXIFTAGID_FOCAL_LENGTH, EXIF_RATIONAL, 1, |
| 1, (void *)&focalLength); |
| //Adding ExifTag for ISOSpeedRating |
| const char *iso_str = mParameters.get(QCameraParameters::KEY_ISO_MODE); |
| int iso_value = attr_lookup(iso, sizeof(iso) / sizeof(str_map), iso_str); |
| isoMode = iso_arr[iso_value]; |
| addExifTag(EXIFTAGID_ISO_SPEED_RATING,EXIF_SHORT,1,1,(void *)&isoMode); |
| |
| if (mUseJpegDownScaling) { |
| ALOGI("initImageEncodeParameters: update main image", __func__); |
| mImageEncodeParms.output_picture_width = mActualPictWidth; |
| mImageEncodeParms.output_picture_height = mActualPictHeight; |
| } |
| mImageEncodeParms.cbcr_offset = mCbCrOffsetRaw; |
| if(mPreviewFormat == CAMERA_YUV_420_NV21_ADRENO) |
| mImageEncodeParms.cbcr_offset = mCbCrOffsetRaw; |
| /* TODO: check this */ |
| mImageEncodeParms.y_offset = 0; |
| for(int i = 0; i < size; i++){ |
| memset(&mEncodeOutputBuffer[i], 0, sizeof(mm_camera_buffer_t)); |
| mEncodeOutputBuffer[i].ptr = (uint8_t *)mJpegMapped[i]->data; |
| mEncodeOutputBuffer[i].filled_size = mJpegMaxSize; |
| mEncodeOutputBuffer[i].size = mJpegMaxSize; |
| mEncodeOutputBuffer[i].fd = mJpegfd[i]; |
| mEncodeOutputBuffer[i].offset = 0; |
| } |
| mImageEncodeParms.p_output_buffer = mEncodeOutputBuffer; |
| mImageEncodeParms.exif_data = exif_data; |
| mImageEncodeParms.exif_numEntries = exif_table_numEntries; |
| |
| mImageEncodeParms.format3d = mIs3DModeOn; |
| return true; |
| } |
| |
| bool QualcommCameraHardware::native_set_parms( |
| camera_parm_type_t type, uint16_t length, void *value) |
| { |
| if(mCfgControl.mm_camera_set_parm(type,value) != MM_CAMERA_SUCCESS) { |
| ALOGE("native_set_parms failed: type %d length %d error %s", |
| type, length, strerror(errno)); |
| return false; |
| } |
| return true; |
| |
| } |
| bool QualcommCameraHardware::native_set_parms( |
| camera_parm_type_t type, uint16_t length, void *value, int *result) |
| { |
| mm_camera_status_t status; |
| status = mCfgControl.mm_camera_set_parm(type,value); |
| ALOGI("native_set_parms status = %d", status); |
| if( status == MM_CAMERA_SUCCESS || status == MM_CAMERA_ERR_INVALID_OPERATION){ |
| *result = status ; |
| return true; |
| } |
| ALOGE("%s: type %d length %d error %s, status %d", __FUNCTION__, |
| type, length, strerror(errno), status); |
| *result = status; |
| return false; |
| } |
| |
| void QualcommCameraHardware::jpeg_set_location() |
| { |
| bool encode_location = true; |
| camera_position_type pt; |
| |
| #define PARSE_LOCATION(what,type,fmt,desc) do { \ |
| pt.what = 0; \ |
| const char *what##_str = mParameters.get("gps-"#what); \ |
| ALOGI("GPS PARM %s --> [%s]", "gps-"#what, what##_str); \ |
| if (what##_str) { \ |
| type what = 0; \ |
| if (sscanf(what##_str, fmt, &what) == 1) \ |
| pt.what = what; \ |
| else { \ |
| ALOGE("GPS " #what " %s could not" \ |
| " be parsed as a " #desc, what##_str); \ |
| encode_location = false; \ |
| } \ |
| } \ |
| else { \ |
| ALOGI("GPS " #what " not specified: " \ |
| "defaulting to zero in EXIF header."); \ |
| encode_location = false; \ |
| } \ |
| } while(0) |
| |
| PARSE_LOCATION(timestamp, long, "%ld", "long"); |
| if (!pt.timestamp) pt.timestamp = time(NULL); |
| PARSE_LOCATION(altitude, short, "%hd", "short"); |
| PARSE_LOCATION(latitude, double, "%lf", "double float"); |
| PARSE_LOCATION(longitude, double, "%lf", "double float"); |
| |
| #undef PARSE_LOCATION |
| |
| if (encode_location) { |
| ALOGI("setting image location ALT %d LAT %lf LON %lf", |
| pt.altitude, pt.latitude, pt.longitude); |
| |
| setGpsParameters(); |
| /* Disabling until support is available. |
| if (!LINK_jpeg_encoder_setLocation(&pt)) { |
| ALOGE("jpeg_set_location: LINK_jpeg_encoder_setLocation failed."); |
| } |
| */ |
| } |
| else ALOGI("not setting image location"); |
| } |
| |
| static bool register_buf(int size, |
| int frame_size, |
| int cbcr_offset, |
| int yoffset, |
| int pmempreviewfd, |
| uint32_t offset, |
| uint8_t *buf, |
| int pmem_type, |
| bool vfe_can_write, |
| bool register_buffer, |
| bool use_all_chnls) |
| { |
| struct msm_pmem_info pmemBuf; |
| CAMERA_HAL_UNUSED(frame_size); |
| |
| memset(&pmemBuf, 0, sizeof(struct msm_pmem_info)); |
| pmemBuf.type = pmem_type; |
| pmemBuf.fd = pmempreviewfd; |
| pmemBuf.offset = offset; |
| pmemBuf.len = size; |
| pmemBuf.vaddr = buf; |
| pmemBuf.planar0_off = yoffset; |
| if(!use_all_chnls) { |
| ALOGI("use_all_chnls = %d\n", use_all_chnls); |
| pmemBuf.planar1_off = cbcr_offset; |
| pmemBuf.planar2_off = yoffset; |
| } else { |
| pmemBuf.planar1_off = myv12_params.CbOffset; |
| pmemBuf.planar2_off = myv12_params.CrOffset; |
| } |
| ALOGI("register_buf: CbOff = 0x%x CrOff = 0x%x", |
| pmemBuf.planar1_off, pmemBuf.planar2_off); |
| |
| pmemBuf.active = vfe_can_write; |
| |
| ALOGI("register_buf: reg = %d buffer = %p", |
| !register_buffer, buf); |
| if(native_start_ops(register_buffer ? CAMERA_OPS_REGISTER_BUFFER : |
| CAMERA_OPS_UNREGISTER_BUFFER ,(void *)&pmemBuf) < 0) { |
| ALOGE("register_buf: MSM_CAM_IOCTL_(UN)REGISTER_PMEM error %s", |
| strerror(errno)); |
| return false; |
| } |
| |
| return true; |
| |
| } |
| |
| static bool register_buf(int size, |
| int frame_size, |
| int cbcr_offset, |
| int yoffset, |
| int pmempreviewfd, |
| uint32_t offset, |
| uint8_t *buf, |
| int pmem_type, |
| bool vfe_can_write, |
| bool register_buffer = true, |
| bool use_all_chnls = false); |
| |
| void QualcommCameraHardware::runFrameThread(void *data) |
| { |
| ALOGV("runFrameThread E"); |
| int type; |
| int CbCrOffset = PAD_TO_WORD(previewWidth * previewHeight); |
| |
| if(libmmcamera) |
| { |
| LINK_cam_frame(data); |
| } |
| //waiting for preview thread to complete before clearing of the buffers |
| mPreviewThreadWaitLock.lock(); |
| while (mPreviewThreadRunning) { |
| ALOGI("runframethread: waiting for preview thread to complete."); |
| mPreviewThreadWait.wait(mPreviewThreadWaitLock); |
| ALOGI("initPreview: old preview thread completed."); |
| } |
| mPreviewThreadWaitLock.unlock(); |
| |
| // Cancelling previewBuffers and returning them to display before stopping preview |
| // This will ensure that all preview buffers are available for dequeing when |
| //startPreview is called again with the same ANativeWindow object (snapshot case). If the |
| //ANativeWindow is a new one(camera-camcorder switch case) because the app passed a new |
| //surface then buffers will be re-allocated and not returned from the old pool. |
| relinquishBuffers(); |
| mPreviewBusyQueue.flush(); |
| /* Flush the Free Q */ |
| LINK_camframe_release_all_frames(CAM_PREVIEW_FRAME); |
| |
| if(mIs3DModeOn != true) { |
| #if 0 |
| if(mInHFRThread == false) |
| { |
| mPmemWaitLock.lock(); |
| //mPreviewHeap.clear(); |
| // TODO do properly |
| mPrevHeapDeallocRunning = true; |
| mPmemWait.signal(); |
| mPmemWaitLock.unlock(); |
| |
| if(( mPreviewFormat == CAMERA_YUV_420_YV12 )&& |
| ( mCurrentTarget == TARGET_MSM7627A || mCurrentTarget == TARGET_MSM7627) && |
| previewWidth%32 != 0 ) |
| mYV12Heap.clear(); |
| |
| } |
| else |
| #endif |
| { |
| int mBufferSize = previewWidth * previewHeight * 3/2; |
| int mCbCrOffset = PAD_TO_WORD(previewWidth * previewHeight); |
| ALOGI("unregistering all preview buffers"); |
| //unregister preview buffers. we are not deallocating here. |
| for (int cnt = 0; cnt < mTotalPreviewBufferCount; ++cnt) { |
| register_buf(mBufferSize, |
| mBufferSize, |
| mCbCrOffset, |
| 0, |
| frames[cnt].fd, |
| 0, |
| (uint8_t *)frames[cnt].buffer, |
| MSM_PMEM_PREVIEW, |
| false, |
| false, |
| true); |
| //mPreviewHeap[cnt].clear(); |
| // TODO : clean properly |
| } |
| } |
| } |
| if(!mZslEnable) { |
| if(( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250) || (mCurrentTarget == TARGET_MSM8660)){ |
| if(mHFRMode != true) { |
| #if 0 |
| mRecordHeap.clear(); |
| mRecordHeap = NULL; |
| #endif |
| } else { |
| ALOGI("%s: unregister record buffers with camera driver", __FUNCTION__); |
| register_record_buffers(false); |
| } |
| int CbCrOffset = PAD_TO_2K(mDimension.video_width * mDimension.video_height); |
| for (int cnt = 0; cnt < kRecordBufferCount; cnt++) { |
| #if 0 |
| if (mRecordfd[cnt] > 0) { |
| ALOGE("Unregistering buffer %d with kernel",cnt); |
| register_buf(mRecordFrameSize, |
| mRecordFrameSize, CbCrOffset, 0, |
| mRecordfd[cnt], |
| 0, |
| (uint8_t *)recordframes[cnt].buffer, |
| MSM_PMEM_VIDEO, |
| false, false); |
| ALOGE("Came back from register call to kernel"); |
| } |
| #endif |
| type = MSM_PMEM_VIDEO; |
| ALOGI("%s: unregister record buffers[%d] with camera driver", __FUNCTION__, cnt); |
| if(recordframes) { |
| register_buf(mRecordFrameSize, |
| mRecordFrameSize, CbCrOffset, 0, |
| recordframes[cnt].fd, |
| 0, |
| (uint8_t *)recordframes[cnt].buffer, |
| type, |
| false,false); |
| if(mRecordMapped[cnt]) { |
| mRecordMapped[cnt]->release(mRecordMapped[cnt]); |
| mRecordMapped[cnt] = NULL; |
| close(mRecordfd[cnt]); |
| if(mStoreMetaDataInFrame && (metadata_memory[cnt] != NULL)){ |
| struct encoder_media_buffer_type * packet = |
| (struct encoder_media_buffer_type *)metadata_memory[cnt]->data; |
| native_handle_delete(const_cast<native_handle_t *>(packet->meta_handle)); |
| metadata_memory[cnt]->release(metadata_memory[cnt]); |
| metadata_memory[cnt] = NULL; |
| } |
| #ifdef USE_ION |
| deallocate_ion_memory(&record_main_ion_fd[cnt], &record_ion_info_fd[cnt]); |
| #endif |
| } |
| } |
| } |
| } |
| } |
| |
| mFrameThreadWaitLock.lock(); |
| mFrameThreadRunning = false; |
| mFrameThreadWait.signal(); |
| mFrameThreadWaitLock.unlock(); |
| |
| ALOGV("runFrameThread X"); |
| } |
| |
| |
| void QualcommCameraHardware::runPreviewThread(void *data) |
| { |
| static int hfr_count = 0; |
| msm_frame* frame = NULL; |
| status_t retVal = NO_ERROR; |
| CAMERA_HAL_UNUSED(data); |
| android_native_buffer_t *buffer; |
| buffer_handle_t *handle = NULL; |
| int bufferIndex = 0; |
| |
| while((frame = mPreviewBusyQueue.get()) != NULL) { |
| if (UNLIKELY(mDebugFps)) { |
| debugShowPreviewFPS(); |
| } |
| mCallbackLock.lock(); |
| int msgEnabled = mMsgEnabled; |
| camera_data_callback pcb = mDataCallback; |
| void *pdata = mCallbackCookie; |
| camera_data_timestamp_callback rcb = mDataCallbackTimestamp; |
| void *rdata = mCallbackCookie; |
| camera_data_callback mcb = mDataCallback; |
| void *mdata = mCallbackCookie; |
| mCallbackLock.unlock(); |
| |
| // signal smooth zoom thread , that a new preview frame is available |
| mSmoothzoomThreadWaitLock.lock(); |
| if(mSmoothzoomThreadRunning) { |
| mSmoothzoomThreadWait.signal(); |
| } |
| mSmoothzoomThreadWaitLock.unlock(); |
| |
| // Find the offset within the heap of the current buffer. |
| ssize_t offset_addr = 0; // TODO , use proper value |
| // (ssize_t)frame->buffer - (ssize_t)mPreviewHeap->mHeap->base(); |
| // ssize_t offset = offset_addr / mPreviewHeap->mAlignedBufferSize; |
| common_crop_t *crop = (common_crop_t *) (frame->cropinfo); |
| #ifdef DUMP_PREVIEW_FRAMES |
| static int frameCnt = 0; |
| int written; |
| if (frameCnt >= 0 && frameCnt <= 10 ) { |
| char buf[128]; |
| snprintf(buffer, sizeof(buf), "/data/%d_preview.yuv", frameCnt); |
| int file_fd = open(buf, O_RDWR | O_CREAT, 0777); |
| ALOGI("dumping preview frame %d", frameCnt); |
| if (file_fd < 0) { |
| ALOGE("cannot open file\n"); |
| } |
| else |
| { |
| ALOGI("dumping data"); |
| written = write(file_fd, (uint8_t *)frame->buffer, |
| mPreviewFrameSize ); |
| if(written < 0) |
| ALOGE("error in data write"); |
| } |
| close(file_fd); |
| } |
| frameCnt++; |
| #endif |
| mInPreviewCallback = true; |
| if (crop->in1_w != 0 && crop->in1_h != 0) { |
| zoomCropInfo.left = (crop->out1_w - crop->in1_w + 1) / 2 - 1; |
| zoomCropInfo.top = (crop->out1_h - crop->in1_h + 1) / 2 - 1; |
| /* There can be scenarios where the in1_wXin1_h and |
| * out1_wXout1_h are same. In those cases, reset the |
| * x and y to zero instead of negative for proper zooming |
| */ |
| if(zoomCropInfo.left < 0) zoomCropInfo.left = 0; |
| if(zoomCropInfo.top < 0) zoomCropInfo.top = 0; |
| zoomCropInfo.right = zoomCropInfo.left + crop->in1_w; |
| zoomCropInfo.bottom = zoomCropInfo.top + crop->in1_h; |
| mPreviewWindow-> set_crop (mPreviewWindow, |
| zoomCropInfo.left, |
| zoomCropInfo.top, |
| zoomCropInfo.right, |
| zoomCropInfo.bottom); |
| /* Set mResetOverlayCrop to true, so that when there is |
| * no crop information, setCrop will be called |
| * with zero crop values. |
| */ |
| mResetWindowCrop = true; |
| |
| } else { |
| // Reset zoomCropInfo variables. This will ensure that |
| // stale values wont be used for postview |
| zoomCropInfo.left = 0; |
| zoomCropInfo.top = 0; |
| zoomCropInfo.right = crop->in1_w; |
| zoomCropInfo.bottom = crop->in1_h; |
| /* This reset is required, if not, overlay driver continues |
| * to use the old crop information for these preview |
| * frames which is not the correct behavior. To avoid |
| * multiple calls, reset once. |
| */ |
| if(mResetWindowCrop == true){ |
| mPreviewWindow-> set_crop (mPreviewWindow, |
| zoomCropInfo.left, |
| zoomCropInfo.top, |
| zoomCropInfo.right, |
| zoomCropInfo.bottom); |
| mResetWindowCrop = false; |
| } |
| } |
| /* To overcome a timing case where we could be having the overlay refer to deallocated |
| mDisplayHeap(and showing corruption), the mDisplayHeap is not deallocated untill the |
| first preview frame is queued to the overlay in 8660. Also adding the condition |
| to check if snapshot is currently in progress ensures that the resources being |
| used by the snapshot thread are not incorrectly deallocated by preview thread*/ |
| if ((mCurrentTarget == TARGET_MSM8660)&&(mFirstFrame == true)) { |
| ALOGD(" receivePreviewFrame : first frame queued, display heap being deallocated"); |
| mThumbnailHeap.clear(); |
| mDisplayHeap.clear(); |
| if(!mZslEnable){ |
| mDisplayHeap.clear(); |
| mPostviewHeap.clear(); |
| } |
| mFirstFrame = false; |
| } |
| mLastQueuedFrame = (void *)frame->buffer; |
| bufferIndex = mapBuffer(frame); |
| |
| // if 7x27A && yv12 is set as preview format use convert routines to |
| // convert from YUV420sp to YV12 |
| yuv_image_type in_buf, out_buf; |
| int conversion_result = 0; |
| |
| if(( mPreviewFormat == CAMERA_YUV_420_YV12 ) && |
| ( mCurrentTarget == TARGET_MSM7627A || mCurrentTarget == TARGET_MSM7627 )){ |
| // if the width is not multiple of 32, |
| //we cannot do inplace conversion as sizes of 420sp and YV12 frames differ |
| if(previewWidth%32){ |
| #if 0 //TODO : |
| ALOGE("YV12::Doing not inplace conversion from 420sp to yv12"); |
| in_buf.imgPtr = (unsigned char*)mPreviewMapped[bufferIndex]->data; |
| in_buf.dx = out_buf.dx = previewWidth; |
| in_buf.dy = in_buf.dy = previewHeight; |
| conversion_result = LINK_yuv_convert_ycrcb420sp_to_yv12(&in_buf, &out_buf); |
| #endif |
| } else { |
| ALOGI("Doing inplace conversion from 420sp to yv12"); |
| in_buf.imgPtr = (unsigned char *)mPreviewMapped[bufferIndex]->data; |
| in_buf.dx = previewWidth; |
| in_buf.dy = previewHeight; |
| conversion_result = LINK_yuv_convert_ycrcb420sp_to_yv12_inplace(&in_buf); |
| } |
| } |
| |
| if(bufferIndex >= 0) { |
| //Need to encapsulate this in IMemory object and send |
| |
| if (pcb != NULL && (msgEnabled & CAMERA_MSG_PREVIEW_FRAME)) { |
| int previewBufSize; |
| /* for CTS : Forcing preview memory buffer lenth to be |
| 'previewWidth * previewHeight * 3/2'. Needed when gralloc allocated extra memory.*/ |
| if( mPreviewFormat == CAMERA_YUV_420_NV21 || mPreviewFormat == CAMERA_YUV_420_YV12) { |
| previewBufSize = previewWidth * previewHeight * 3/2; |
| camera_memory_t *previewMem = mGetMemory(frames[bufferIndex].fd, previewBufSize, |
| 1, mCallbackCookie); |
| if (!previewMem || !previewMem->data) { |
| ALOGE("%s: mGetMemory failed.\n", __func__); |
| } else { |
| pcb(CAMERA_MSG_PREVIEW_FRAME,previewMem,0,NULL,pdata); |
| previewMem->release(previewMem); |
| } |
| } else |
| pcb(CAMERA_MSG_PREVIEW_FRAME,(camera_memory_t *) mPreviewMapped[bufferIndex],0,NULL,pdata); |
| } |
| |
| // TODO : may have to reutn proper frame as pcb |
| mDisplayLock.lock(); |
| if( mPreviewWindow != NULL) { |
| if (BUFFER_LOCKED == frame_buffer[bufferIndex].lockState) { |
| if (GENLOCK_FAILURE == genlock_unlock_buffer( |
| (native_handle_t*)(*(frame_buffer[bufferIndex].buffer)))) { |
| ALOGE("%s: genlock_unlock_buffer failed", __FUNCTION__); |
| mDisplayLock.unlock(); |
| } else { |
| frame_buffer[bufferIndex].lockState = BUFFER_UNLOCKED; |
| } |
| } else { |
| ALOGI("%s: buffer to be enqueued is unlocked", __FUNCTION__); |
| mDisplayLock.unlock(); |
| } |
| const char *str = mParameters.get(QCameraParameters::KEY_VIDEO_HIGH_FRAME_RATE); |
| if(str != NULL){ |
| int is_hfr_off = 0; |
| hfr_count++; |
| if(!strcmp(str, QCameraParameters::VIDEO_HFR_OFF)) { |
| is_hfr_off = 1; |
| retVal = mPreviewWindow->enqueue_buffer(mPreviewWindow, |
| frame_buffer[bufferIndex].buffer); |
| } else if (!strcmp(str, QCameraParameters::VIDEO_HFR_2X)) { |
| hfr_count %= 2; |
| } else if (!strcmp(str, QCameraParameters::VIDEO_HFR_3X)) { |
| hfr_count %= 3; |
| } else if (!strcmp(str, QCameraParameters::VIDEO_HFR_4X)) { |
| hfr_count %= 4; |
| } |
| if(hfr_count == 0) |
| retVal = mPreviewWindow->enqueue_buffer(mPreviewWindow, |
| frame_buffer[bufferIndex].buffer); |
| else if(!is_hfr_off) |
| retVal = mPreviewWindow->cancel_buffer(mPreviewWindow, |
| frame_buffer[bufferIndex].buffer); |
| } else |
| retVal = mPreviewWindow->enqueue_buffer(mPreviewWindow, |
| frame_buffer[bufferIndex].buffer); |
| if( retVal != NO_ERROR) |
| ALOGE("%s: Failed while queueing buffer %d for display." |
| " Error = %d", __FUNCTION__, |
| frames[bufferIndex].fd, retVal); |
| int stride; |
| retVal = mPreviewWindow->dequeue_buffer(mPreviewWindow, |
| &(handle),&(stride)); |
| private_handle_t *bhandle = (private_handle_t *)(*handle); |
| if( retVal != NO_ERROR) { |
| ALOGE("%s: Failed while dequeueing buffer from display." |
| " Error = %d", __FUNCTION__, retVal); |
| } else { |
| retVal = mPreviewWindow->lock_buffer(mPreviewWindow,handle); |
| //yyan todo use handle to find out buffer |
| if(retVal != NO_ERROR) |
| ALOGE("%s: Failed while dequeueing buffer from" |
| "display. Error = %d", __FUNCTION__, retVal); |
| } |
| } |
| mDisplayLock.unlock(); |
| } else |
| ALOGE("Could not find the buffer"); |
| |
| // If output is NOT enabled (targets otherthan 7x30 , 8x50 and 8x60 currently..) |
| |
| nsecs_t timeStamp = nsecs_t(frame->ts.tv_sec)*1000000000LL + frame->ts.tv_nsec; |
| |
| if( (mCurrentTarget != TARGET_MSM7630 ) && (mCurrentTarget != TARGET_QSD8250) && (mCurrentTarget != TARGET_MSM8660)) { |
| int flagwait = 1; |
| if(rcb != NULL && (msgEnabled & CAMERA_MSG_VIDEO_FRAME) && (record_flag)) { |
| if(mStoreMetaDataInFrame){ |
| flagwait = 1; |
| if(metadata_memory[bufferIndex]!= NULL) |
| rcb(timeStamp, CAMERA_MSG_VIDEO_FRAME, metadata_memory[bufferIndex],0,rdata); |
| else flagwait = 0; |
| } else { |
| rcb(timeStamp, CAMERA_MSG_VIDEO_FRAME, mPreviewMapped[bufferIndex],0, rdata); |
| } |
| if(flagwait){ |
| Mutex::Autolock rLock(&mRecordFrameLock); |
| if (mReleasedRecordingFrame != true) { |
| mRecordWait.wait(mRecordFrameLock); |
| } |
| mReleasedRecordingFrame = false; |
| } |
| } |
| } |
| |
| if ( mCurrentTarget == TARGET_MSM8660 ) { |
| mMetaDataWaitLock.lock(); |
| if (mFaceDetectOn == true && mSendMetaData == true) { |
| mSendMetaData = false; |
| fd_roi_t *roi = (fd_roi_t *)(frame->roi_info.info); |
| |
| switch (roi->type) { |
| case FD_ROI_TYPE_HEADER: |
| { |
| mNumFDRcvd = 0; |
| memset(mFaceArray, -1, sizeof(mFaceArray)); |
| mFaceArray[0] = 0; //faces_detected * 4; |
| |
| mFacesDetected = roi->d.hdr.num_face_detected; |
| if(mFacesDetected > MAX_ROI) |
| mFacesDetected = MAX_ROI; |
| } |
| break; |
| case FD_ROI_TYPE_DATA: |
| { |
| int idx = roi->d.data.idx; |
| if (idx < mFacesDetected) { |
| mFaceArray[idx*4+1] = roi->d.data.face.face_boundary.x; |
| mFaceArray[idx*4+2] = roi->d.data.face.face_boundary.y; |
| mFaceArray[idx*4+3] = roi->d.data.face.face_boundary.x; |
| mFaceArray[idx*4+4] = roi->d.data.face.face_boundary.y; |
| mNumFDRcvd++; |
| if (mNumFDRcvd == mFacesDetected) { |
| mFaceArray[0] = mFacesDetected * 4; |
| if(mMetaDataHeap != NULL){ |
| ALOGV("runPreviewThread mMetaDataHEap is non-NULL"); |
| memcpy((uint32_t *)mMetaDataHeap->mHeap->base(), (uint32_t *)mFaceArray, sizeof(mFaceArray)); |
| } |
| } |
| } |
| } |
| break; |
| } |
| } |
| mMetaDataWaitLock.unlock(); |
| } |
| bufferIndex = mapFrame(handle); |
| if(bufferIndex >= 0) { |
| LINK_camframe_add_frame(CAM_PREVIEW_FRAME, &frames[bufferIndex]); |
| private_handle_t *bhandle = (private_handle_t *)(*handle); |
| if (GENLOCK_NO_ERROR != genlock_lock_buffer(bhandle, GENLOCK_WRITE_LOCK, GENLOCK_MAX_TIMEOUT)) { |
| ALOGE("%s: genlock_lock_buffer(WRITE) failed", __FUNCTION__); |
| frame_buffer[bufferIndex].lockState = BUFFER_UNLOCKED; |
| } else { |
| frame_buffer[bufferIndex].lockState = BUFFER_LOCKED; |
| } |
| } else { |
| ALOGE("Could not find the Frame"); |
| |
| // Special Case: Stoppreview is issued which causes thumbnail buffer |
| // to be cancelled. Frame thread has still not exited. In preview thread |
| // dequeue returns incorrect buffer id (previously cancelled thumbnail buffer) |
| // This will throw error "Could not find frame". We need to cancel the incorrectly |
| // dequeued buffer here to ensure that all buffers are available for the next |
| // startPreview call. |
| |
| mDisplayLock.lock(); |
| ALOGV(" error Cancelling preview buffers "); |
| retVal = mPreviewWindow->cancel_buffer(mPreviewWindow, |
| handle); |
| if(retVal != NO_ERROR) |
| ALOGE("%s: cancelBuffer failed for buffer", __FUNCTION__); |
| mDisplayLock.unlock(); |
| } |
| } |
| mPreviewThreadWaitLock.lock(); |
| mPreviewThreadRunning = false; |
| mPreviewThreadWait.signal(); |
| mPreviewThreadWaitLock.unlock(); |
| } |
| int QualcommCameraHardware::mapBuffer(struct msm_frame *frame) { |
| int ret = -1; |
| for (int cnt = 0; cnt < mTotalPreviewBufferCount; cnt++) { |
| if (frame_buffer[cnt].frame->buffer == frame->buffer) { |
| ret = cnt; |
| break; |
| } |
| } |
| return ret; |
| } |
| int QualcommCameraHardware::mapvideoBuffer(struct msm_frame *frame) |
| { |
| int ret = -1; |
| for (int cnt = 0; cnt < kRecordBufferCount; cnt++) { |
| if ((unsigned int)mRecordMapped[cnt]->data == (unsigned int)frame->buffer) { |
| ret = cnt; |
| ALOGI("found match returning %d", ret); |
| break; |
| } |
| } |
| return ret; |
| |
| } |
| int QualcommCameraHardware::mapRawBuffer(struct msm_frame *frame) |
| { |
| int ret = -1; |
| for (int cnt = 0; cnt < (mZslEnable? MAX_SNAPSHOT_BUFFERS : numCapture); cnt++) { |
| if ((unsigned int)mRawMapped[cnt]->data == (unsigned int)frame->buffer) { |
| ret = cnt; |
| ALOGI("found match returning %d", ret); |
| break; |
| } |
| } |
| return ret; |
| } |
| int QualcommCameraHardware::mapThumbnailBuffer(struct msm_frame *frame) |
| { |
| int ret = -1; |
| for (int cnt = 0; cnt < (mZslEnable? MAX_SNAPSHOT_BUFFERS : numCapture); cnt++) { |
| if ((unsigned int)(uint8_t *)mThumbnailMapped[cnt] == (unsigned int)frame->buffer) { |
| ret = cnt; |
| ALOGI("found match returning %d", ret); |
| break; |
| } |
| } |
| if(ret < 0) ALOGE("mapThumbnailBuffer, could not find match"); |
| return ret; |
| } |
| int QualcommCameraHardware::mapJpegBuffer(mm_camera_buffer_t *encode_buffer) |
| { |
| int ret = -1; |
| for (int cnt = 0; cnt < (mZslEnable? MAX_SNAPSHOT_BUFFERS : numCapture); cnt++) { |
| if ((unsigned int)mJpegMapped[cnt]->data == (unsigned int)encode_buffer->ptr) { |
| ret = cnt; |
| ALOGI("found match returning %d", ret); |
| break; |
| } |
| } |
| return ret; |
| } |
| int QualcommCameraHardware::mapFrame(buffer_handle_t *buffer) { |
| int ret = -1; |
| for (int cnt = 0; cnt < mTotalPreviewBufferCount; cnt++) { |
| if (frame_buffer[cnt].buffer == buffer) { |
| ret = cnt; |
| break; |
| } |
| } |
| return ret; |
| } |
| |
| void *preview_thread(void *user) |
| { |
| ALOGV("preview_thread E"); |
| QualcommCameraHardware *obj = QualcommCameraHardware::getInstance(); |
| if (obj != 0) { |
| obj->runPreviewThread(user); |
| } |
| else ALOGE("not starting preview thread: the object went away!"); |
| ALOGV("preview_thread X"); |
| return NULL; |
| } |
| |
| void *hfr_thread(void *user) |
| { |
| ALOGV("hfr_thread E"); |
| QualcommCameraHardware *obj = QualcommCameraHardware::getInstance(); |
| if (obj != 0) { |
| obj->runHFRThread(user); |
| } |
| else ALOGE("not starting hfr thread: the object went away!"); |
| ALOGV("hfr_thread X"); |
| return NULL; |
| } |
| |
| void QualcommCameraHardware::runHFRThread(void *data) |
| { |
| ALOGV("runHFRThread E"); |
| mInHFRThread = true; |
| CAMERA_HAL_UNUSED(data); |
| ALOGI("%s: stopping Preview", __FUNCTION__); |
| stopPreviewInternal(); |
| |
| // Release thumbnail Buffers |
| if( mPreviewWindow != NULL ) { |
| private_handle_t *handle; |
| for (int cnt = 0; cnt < (mZslEnable? (MAX_SNAPSHOT_BUFFERS-2) : numCapture); cnt++) { |
| if(mPreviewWindow != NULL && mThumbnailBuffer[cnt] != NULL) { |
| handle = (private_handle_t *)(*mThumbnailBuffer[cnt]); |
| ALOGV("%s: Cancelling postview buffer %d ", __FUNCTION__, handle->fd); |
| ALOGV("runHfrThread : display lock"); |
| mDisplayLock.lock(); |
| if (BUFFER_LOCKED == mThumbnailLockState[cnt]) { |
| if (GENLOCK_FAILURE == genlock_unlock_buffer(handle)) { |
| ALOGE("%s: genlock_unlock_buffer failed", __FUNCTION__); |
| mDisplayLock.unlock(); |
| continue; |
| } else { |
| mThumbnailLockState[cnt] = BUFFER_UNLOCKED; |
| } |
| } |
| status_t retVal = mPreviewWindow->cancel_buffer(mPreviewWindow, |
| mThumbnailBuffer[cnt]); |
| if(retVal != NO_ERROR) |
| ALOGE("%s: cancelBuffer failed for postview buffer %d", |
| __FUNCTION__, handle->fd); |
| // unregister , unmap and release as well |
| int mBufferSize = previewWidth * previewHeight * 3/2; |
| int mCbCrOffset = PAD_TO_WORD(previewWidth * previewHeight); |
| if(mThumbnailMapped[cnt] && (mSnapshotFormat == PICTURE_FORMAT_JPEG)) { |
| ALOGI("%s: Unregistering Thumbnail Buffer %d ", __FUNCTION__, handle->fd); |
| register_buf(mBufferSize, |
| mBufferSize, mCbCrOffset, 0, |
| handle->fd, |
| 0, |
| (uint8_t *)mThumbnailMapped[cnt], |
| MSM_PMEM_THUMBNAIL, |
| false, false); |
| if (munmap((void *)(mThumbnailMapped[cnt]),handle->size ) == -1) { |
| ALOGE("StopPreview : Error un-mmapping the thumbnail buffer %d", index); |
| } |
| mThumbnailBuffer[cnt] = NULL; |
| mThumbnailMapped[cnt] = NULL; |
| } |
| ALOGV("runHfrThread : display unlock"); |
| mDisplayLock.unlock(); |
| } |
| } |
| } |
| |
| ALOGV("%s: setting parameters", __FUNCTION__); |
| setParameters(mParameters); |
| ALOGV("%s: starting Preview", __FUNCTION__); |
| if( mPreviewWindow == NULL) |
| { |
| startPreviewInternal(); |
| } |
| else { |
| getBuffersAndStartPreview(); |
| } |
| |
| mHFRMode = false; |
| mInHFRThread = false; |
| } |
| |
| void QualcommCameraHardware::runVideoThread(void *data) |
| { |
| ALOGV("runVideoThread E"); |
| msm_frame* vframe = NULL; |
| CAMERA_HAL_UNUSED(data); |
| |
| while(true) { |
| pthread_mutex_lock(&(g_busy_frame_queue.mut)); |
| |
| // Exit the thread , in case of stop recording.. |
| mVideoThreadWaitLock.lock(); |
| if(mVideoThreadExit){ |
| ALOGV("Exiting video thread.."); |
| mVideoThreadWaitLock.unlock(); |
| pthread_mutex_unlock(&(g_busy_frame_queue.mut)); |
| break; |
| } |
| mVideoThreadWaitLock.unlock(); |
| |
| ALOGV("in video_thread : wait for video frame "); |
| // check if any frames are available in busyQ and give callback to |
| // services/video encoder |
| cam_frame_wait_video(); |
| ALOGV("video_thread, wait over.."); |
| |
| // Exit the thread , in case of stop recording.. |
| mVideoThreadWaitLock.lock(); |
| if(mVideoThreadExit){ |
| ALOGV("Exiting video thread.."); |
| mVideoThreadWaitLock.unlock(); |
| pthread_mutex_unlock(&(g_busy_frame_queue.mut)); |
| break; |
| } |
| mVideoThreadWaitLock.unlock(); |
| |
| // Get the video frame to be encoded |
| vframe = cam_frame_get_video (); |
| pthread_mutex_unlock(&(g_busy_frame_queue.mut)); |
| ALOGI("in video_thread : got video frame %x",vframe); |
| |
| /*if (UNLIKELY(mDebugFps)) { |
| debugShowVideoFPS(); |
| }*/ |
| |
| if(vframe != NULL) { |
| // Find the offset within the heap of the current buffer. |
| //ALOGV("Got video frame : buffer %d base %d ", vframe->buffer, |
| //(unsigned long int)mRecordHeap->mHeap->base()); |
| //ssize_t offset = |
| // (ssize_t)vframe->buffer - (ssize_t)mRecordHeap->mHeap->base(); |
| //ALOGV("offset = %d , alignsize = %d , new_offset = %d", (int)offset, mRecordHeap->mAlignedBufferSize, |
| // (int)(offset / mRecordHeap->mAlignedBufferSize)); |
| |
| //offset /= mRecordHeap->mAlignedBufferSize; |
| |
| //set the track flag to true for this video buffer |
| //record_buffers_tracking_flag[offset] = true; |
| |
| /* Extract the timestamp of this frame */ |
| nsecs_t timeStamp = nsecs_t(vframe->ts.tv_sec)*1000000000LL + vframe->ts.tv_nsec; |
| |
| // dump frames for test purpose |
| #if 0 |
| static int frameCnt = 0; |
| if (frameCnt >= 11 && frameCnt <= 13 ) { |
| char buf[128]; |
| sprintf(buf, "/data/%d_v.yuv", frameCnt); |
| int file_fd = open(buf, O_RDWR | O_CREAT, 0777); |
| ALOGV("dumping video frame %d", frameCnt); |
| if (file_fd < 0) { |
| ALOGE("cannot open file\n"); |
| } |
| else |
| { |
| write(file_fd, (const void *)vframe->buffer, |
| vframe->cbcr_off * 3 / 2); |
| } |
| close(file_fd); |
| } |
| frameCnt++; |
| #endif |
| #if 0 |
| if(mIs3DModeOn ) { |
| /* VPE will be taking care of zoom, so no need to |
| * use overlay's setCrop interface for zoom |
| * functionality. |
| */ |
| /* get the offset of current video buffer for rendering */ |
| ssize_t offset_addr = (ssize_t)vframe->buffer - |
| (ssize_t)mRecordHeap->mHeap->base(); |
| /* To overcome a timing case where we could be having the overlay refer to deallocated |
| mDisplayHeap(and showing corruption), the mDisplayHeap is not deallocated untill the |
| first preview frame is queued to the overlay in 8660 */ |
| if ((mCurrentTarget == TARGET_MSM8660)&&(mFirstFrame == true)) { |
| ALOGD(" receivePreviewFrame : first frame queued, display heap being deallocated"); |
| mThumbnailHeap.clear(); |
| mDisplayHeap.clear(); |
| mFirstFrame = false; |
| mPostviewHeap.clear(); |
| } |
| mLastQueuedFrame = (void *)vframe->buffer; |
| } |
| #endif |
| // Enable IF block to give frames to encoder , ELSE block for just simulation |
| #if 1 |
| ALOGV("in video_thread : got video frame, before if check giving frame to services/encoder"); |
| mCallbackLock.lock(); |
| int msgEnabled = mMsgEnabled; |
| camera_data_timestamp_callback rcb = mDataCallbackTimestamp; |
| void *rdata = mCallbackCookie; |
| mCallbackLock.unlock(); |
| |
| /* When 3D mode is ON, the video thread will be ON even in preview |
| * mode. We need to distinguish when recording is started. So, when |
| * 3D mode is ON, check for the recordingState (which will be set |
| * with start recording and reset in stop recording), before |
| * calling rcb. |
| */ |
| int index = mapvideoBuffer(vframe); |
| if(!mIs3DModeOn) { |
| record_buffers_tracking_flag[index] = true; |
| if(rcb != NULL && (msgEnabled & CAMERA_MSG_VIDEO_FRAME) ) { |
| ALOGV("in video_thread : got video frame, giving frame to services/encoder index = %d", index); |
| if(mStoreMetaDataInFrame){ |
| rcb(timeStamp, CAMERA_MSG_VIDEO_FRAME, metadata_memory[index],0,rdata); |
| } else { |
| rcb(timeStamp, CAMERA_MSG_VIDEO_FRAME, mRecordMapped[index],0,rdata); |
| } |
| } |
| } |
| #if 0 |
| else { |
| mCallbackLock.lock(); |
| msgEnabled = mMsgEnabled; |
| data_callback pcb = mDataCallback; |
| void *pdata = mCallbackCookie; |
| mCallbackLock.unlock(); |
| if (pcb != NULL) { |
| ALOGE("pcb is not null"); |
| static int count = 0; |
| //if(msgEnabled & CAMERA_MSG_PREVIEW_FRAME) { |
| if (!count) { |
| ALOGE("Giving first frame to app"); |
| pcb(CAMERA_MSG_PREVIEW_FRAME, mRecordHeap->mBuffers[offset], |
| pdata); |
| count++; |
| } |
| } |
| if(mRecordingState == 1) { |
| if(rcb != NULL && (msgEnabled & CAMERA_MSG_VIDEO_FRAME) ) { |
| ALOGV("in video_thread 3D mode : got video frame, giving frame to services/encoder"); |
| rcb(timeStamp, CAMERA_MSG_VIDEO_FRAME, mRecordHeap->mBuffers[offset], rdata); |
| } |
| } else { |
| /* When in preview mode, put the video buffer back into |
| * free Q, for next availability. |
| */ |
| ALOGV("in video_thread 3D mode : got video frame, putting frame to Free Q"); |
| record_buffers_tracking_flag[offset] = false; |
| LINK_camframe_add_frame(CAM_VIDEO_FRAME,vframe); |
| } |
| } |
| #endif |
| #else |
| // 720p output2 : simulate release frame here: |
| ALOGI("in video_thread simulation , releasing the video frame"); |
| LINK_camframe_add_frame(CAM_VIDEO_FRAME,vframe); |
| #endif |
| |
| } else ALOGE("in video_thread get frame returned null"); |
| |
| |
| } // end of while loop |
| |
| mVideoThreadWaitLock.lock(); |
| mVideoThreadRunning = false; |
| mVideoThreadWait.signal(); |
| mVideoThreadWaitLock.unlock(); |
| |
| ALOGV("runVideoThread X"); |
| } |
| |
| void *video_thread(void *user) |
| { |
| ALOGV("video_thread E"); |
| CAMERA_HAL_UNUSED(user); |
| |
| QualcommCameraHardware *obj = QualcommCameraHardware::getInstance(); |
| if (obj != 0) { |
| obj->runVideoThread(user); |
| } |
| else ALOGE("not starting video thread: the object went away!"); |
| ALOGV("video_thread X"); |
| return NULL; |
| } |
| |
| void *frame_thread(void *user) |
| { |
| ALOGD("frame_thread E"); |
| CAMERA_HAL_UNUSED(user); |
| QualcommCameraHardware *obj = QualcommCameraHardware::getInstance(); |
| if (obj != 0) { |
| obj->runFrameThread(user); |
| } |
| else ALOGW("not starting frame thread: the object went away!"); |
| ALOGD("frame_thread X"); |
| return NULL; |
| } |
| |
| static int parse_size(const char *str, int &width, int &height) |
| { |
| // Find the width. |
| char *end; |
| int w = (int)strtol(str, &end, 10); |
| // If an 'x' or 'X' does not immediately follow, give up. |
| if ( (*end != 'x') && (*end != 'X') ) |
| return -1; |
| |
| // Find the height, immediately after the 'x'. |
| int h = (int)strtol(end+1, 0, 10); |
| |
| width = w; |
| height = h; |
| |
| return 0; |
| } |
| QualcommCameraHardware* hardware; |
| |
| int QualcommCameraHardware::allocate_ion_memory(int *main_ion_fd, struct ion_allocation_data* alloc, |
| struct ion_fd_data* ion_info_fd, int ion_type, int size, int *memfd) |
| { |
| int rc = 0; |
| struct ion_handle_data handle_data; |
| |
| *main_ion_fd = open("/dev/ion", O_RDONLY | O_SYNC); |
| if (*main_ion_fd < 0) { |
| ALOGE("Ion dev open failed\n"); |
| ALOGE("Error is %s\n", strerror(errno)); |
| goto ION_OPEN_FAILED; |
| } |
| alloc->len = size; |
| /* to make it page size aligned */ |
| alloc->len = (alloc->len + 4095) & (~4095); |
| alloc->align = 4096; |
| alloc->flags = 0; |
| alloc->heap_id_mask = (0x1 << ion_type | 0x1 << ION_IOMMU_HEAP_ID); |
| |
| rc = ioctl(*main_ion_fd, ION_IOC_ALLOC, alloc); |
| if (rc < 0) { |
| ALOGE("ION allocation failed\n"); |
| goto ION_ALLOC_FAILED; |
| } |
| |
| ion_info_fd->handle = alloc->handle; |
| rc = ioctl(*main_ion_fd, ION_IOC_SHARE, ion_info_fd); |
| if (rc < 0) { |
| ALOGE("ION map failed %s\n", strerror(errno)); |
| goto ION_MAP_FAILED; |
| } |
| *memfd = ion_info_fd->fd; |
| return 0; |
| |
| ION_MAP_FAILED: |
| handle_data.handle = ion_info_fd->handle; |
| ioctl(*main_ion_fd, ION_IOC_FREE, &handle_data); |
| ION_ALLOC_FAILED: |
| close(*main_ion_fd); |
| ION_OPEN_FAILED: |
| return -1; |
| } |
| int QualcommCameraHardware::deallocate_ion_memory(int *main_ion_fd, struct ion_fd_data* ion_info_fd) |
| { |
| struct ion_handle_data handle_data; |
| int rc = 0; |
| |
| handle_data.handle = ion_info_fd->handle; |
| ioctl(*main_ion_fd, ION_IOC_FREE, &handle_data); |
| close(*main_ion_fd); |
| return rc; |
| } |
| |
| bool QualcommCameraHardware::initPreview() |
| { |
| const char * pmem_region; |
| int CbCrOffset = 0; |
| int ion_heap; |
| mParameters.getPreviewSize(&previewWidth, &previewHeight); |
| const char *recordSize = NULL; |
| recordSize = mParameters.get(QCameraParameters::KEY_VIDEO_SIZE); |
| ALOGI("%s Got preview dimension as %d x %d ", __func__, previewWidth, previewHeight); |
| if(!recordSize) { |
| //If application didn't set this parameter string, use the values from |
| //getPreviewSize() as video dimensions. |
| ALOGV("No Record Size requested, use the preview dimensions"); |
| videoWidth = previewWidth; |
| videoHeight = previewHeight; |
| } else { |
| //Extract the record witdh and height that application requested. |
| if(!parse_size(recordSize, videoWidth, videoHeight)) { |
| //VFE output1 shouldn't be greater than VFE output2. |
| if( (previewWidth > videoWidth) || (previewHeight > videoHeight)) { |
| //Set preview sizes as record sizes. |
| ALOGI("Preview size %dx%d is greater than record size %dx%d,\ |
| resetting preview size to record size",previewWidth,\ |
| previewHeight, videoWidth, videoHeight); |
| previewWidth = videoWidth; |
| previewHeight = videoHeight; |
| mParameters.setPreviewSize(previewWidth, previewHeight); |
| } |
| if( (mCurrentTarget != TARGET_MSM7630) |
| && (mCurrentTarget != TARGET_QSD8250) |
| && (mCurrentTarget != TARGET_MSM8660) ) { |
| //For Single VFE output targets, use record dimensions as preview dimensions. |
| previewWidth = videoWidth; |
| previewHeight = videoHeight; |
| mParameters.setPreviewSize(previewWidth, previewHeight); |
| } |
| } else { |
| ALOGE("initPreview X: failed to parse parameter record-size (%s)", recordSize); |
| return false; |
| } |
| } |
| |
| mDimension.display_width = previewWidth; |
| mDimension.display_height= previewHeight; |
| mDimension.ui_thumbnail_width = |
| thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].width; |
| mDimension.ui_thumbnail_height = |
| thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height; |
| |
| ALOGV("initPreview E: preview size=%dx%d videosize = %d x %d", previewWidth, previewHeight, videoWidth, videoHeight ); |
| |
| if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250) || (mCurrentTarget == TARGET_MSM8660)) { |
| mDimension.video_width = CEILING16(videoWidth); |
| /* Backup the video dimensions, as video dimensions in mDimension |
| * will be modified when DIS is supported. Need the actual values |
| * to pass ap part of VPE config |
| */ |
| videoWidth = mDimension.video_width; |
| mDimension.video_height = videoHeight; |
| ALOGV("initPreview : preview size=%dx%d videosize = %d x %d", previewWidth, previewHeight, |
| mDimension.video_width, mDimension.video_height); |
| } |
| |
| // See comments in deinitPreview() for why we have to wait for the frame |
| // thread here, and why we can't use pthread_join(). |
| mFrameThreadWaitLock.lock(); |
| while (mFrameThreadRunning) { |
| ALOGI("initPreview: waiting for old frame thread to complete."); |
| mFrameThreadWait.wait(mFrameThreadWaitLock); |
| ALOGI("initPreview: old frame thread completed."); |
| } |
| mFrameThreadWaitLock.unlock(); |
| |
| mInSnapshotModeWaitLock.lock(); |
| while (mInSnapshotMode) { |
| ALOGI("initPreview: waiting for snapshot mode to complete."); |
| mInSnapshotModeWait.wait(mInSnapshotModeWaitLock); |
| ALOGI("initPreview: snapshot mode completed."); |
| } |
| mInSnapshotModeWaitLock.unlock(); |
| |
| pmem_region = "/dev/pmem_adsp"; |
| ion_heap = ION_CAMERA_HEAP_ID; |
| |
| int cnt = 0; |
| |
| memset(&myv12_params, 0, sizeof(yv12_format_parms_t)); |
| mPreviewFrameSize = previewWidth * previewHeight * 3/2; |
| ALOGI("Width = %d Height = %d \n", previewWidth, previewHeight); |
| if(mPreviewFormat == CAMERA_YUV_420_YV12) { |
| myv12_params.CbOffset = PAD_TO_WORD(previewWidth * previewHeight); |
| myv12_params.CrOffset = myv12_params.CbOffset + PAD_TO_WORD((previewWidth * previewHeight)/4); |
| mDimension.prev_format = CAMERA_YUV_420_YV12; |
| ALOGI("CbOffset = 0x%x CrOffset = 0x%x \n",myv12_params.CbOffset, myv12_params.CrOffset); |
| } else { |
| CbCrOffset = PAD_TO_WORD(previewWidth * previewHeight); |
| } |
| |
| //Pass the yuv formats, display dimensions, |
| //so that vfe will be initialized accordingly. |
| mDimension.display_luma_width = previewWidth; |
| mDimension.display_luma_height = previewHeight; |
| mDimension.display_chroma_width = previewWidth; |
| mDimension.display_chroma_height = previewHeight; |
| if(mPreviewFormat == CAMERA_YUV_420_NV21_ADRENO) { |
| mPreviewFrameSize = PAD_TO_4K(CEILING32(previewWidth) * CEILING32(previewHeight)) + |
| 2 * (CEILING32(previewWidth/2) * CEILING32(previewHeight/2)); |
| CbCrOffset = PAD_TO_4K(CEILING32(previewWidth) * CEILING32(previewHeight)); |
| mDimension.prev_format = CAMERA_YUV_420_NV21_ADRENO; |
| mDimension.display_luma_width = CEILING32(previewWidth); |
| mDimension.display_luma_height = CEILING32(previewHeight); |
| mDimension.display_chroma_width = 2 * CEILING32(previewWidth/2); |
| //Chroma Height is not needed as of now. Just sending with other dimensions. |
| mDimension.display_chroma_height = CEILING32(previewHeight/2); |
| } |
| ALOGV("mDimension.prev_format = %d", mDimension.prev_format); |
| ALOGV("mDimension.display_luma_width = %d", mDimension.display_luma_width); |
| ALOGV("mDimension.display_luma_height = %d", mDimension.display_luma_height); |
| ALOGV("mDimension.display_chroma_width = %d", mDimension.display_chroma_width); |
| ALOGV("mDimension.display_chroma_height = %d", mDimension.display_chroma_height); |
| |
| dstOffset = 0; |
| //set DIS value to get the updated video width and height to calculate |
| //the required record buffer size |
| if(mVpeEnabled) { |
| bool status = setDIS(); |
| if(status) { |
| ALOGE("Failed to set DIS"); |
| return false; |
| } |
| } |
| |
| //Pass the original video width and height and get the required width |
| //and height for record buffer allocation |
| mDimension.orig_video_width = videoWidth; |
| mDimension.orig_video_height = videoHeight; |
| if(mZslEnable){ |
| //Limitation of ZSL where the thumbnail and display dimensions should be the same |
| mDimension.ui_thumbnail_width = mDimension.display_width; |
| mDimension.ui_thumbnail_height = mDimension.display_height; |
| mParameters.getPictureSize(&mPictureWidth, &mPictureHeight); |
| if (updatePictureDimension(mParameters, mPictureWidth, |
| mPictureHeight)) { |
| mDimension.picture_width = mPictureWidth; |
| mDimension.picture_height = mPictureHeight; |
| } |
| } |
| // mDimension will be filled with thumbnail_width, thumbnail_height, |
| // orig_picture_dx, and orig_picture_dy after this function call. We need to |
| // keep it for jpeg_encoder_encode. |
| bool ret = native_set_parms(CAMERA_PARM_DIMENSION, |
| sizeof(cam_ctrl_dimension_t), &mDimension); |
| #if 0 |
| if(mIs3DModeOn != true) { |
| if(mInHFRThread == false) |
| { |
| mPrevHeapDeallocRunning = false; |
| #ifdef USE_ION |
| mPreviewHeap = new IonPool(ion_heap, |
| MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING, |
| MSM_PMEM_PREVIEW, //MSM_PMEM_OUTPUT2, |
| mPreviewFrameSize, |
| kPreviewBufferCountActual, |
| mPreviewFrameSize, |
| CbCrOffset, |
| 0, |
| "preview"); |
| #else |
| mPreviewHeap = new PmemPool(pmem_region, |
| MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING, |
| MSM_PMEM_PREVIEW, //MSM_PMEM_OUTPUT2, |
| mPreviewFrameSize, |
| kPreviewBufferCountActual, |
| mPreviewFrameSize, |
| CbCrOffset, |
| 0, |
| "preview"); |
| #endif |
| if (!mPreviewHeap->initialized()) { |
| mPreviewHeap.clear(); |
| ALOGE("initPreview X: could not initialize Camera preview heap."); |
| return false; |
| } |
| } |
| else |
| { |
| for (int cnt = 0; cnt < kPreviewBufferCountActual; ++cnt) { |
| bool status; |
| int active = (cnt < ACTIVE_PREVIEW_BUFFERS); |
| status = register_buf(mPreviewFrameSize, |
| mPreviewFrameSize, |
| CbCrOffset, |
| 0, |
| mPreviewHeap->mHeap->getHeapID(), |
| mPreviewHeap->mAlignedBufferSize * cnt, |
| (uint8_t *)mPreviewHeap->mHeap->base() + mPreviewHeap->mAlignedBufferSize * cnt, |
| MSM_PMEM_PREVIEW, |
| active, |
| true); |
| if(status == false){ |
| ALOGE("Registring Preview Buffers failed for HFR mode"); |
| return false; |
| } |
| } |
| } |
| // if 7x27A , YV12 format is set as preview format , if width is not 32 |
| // bit aligned , we need seperate buffer to hold YV12 data |
| yv12framesize = (previewWidth*previewHeight) |
| + 2* ( CEILING16(previewWidth/2) * (previewHeight/2)) ; |
| if(( mPreviewFormat == CAMERA_YUV_420_YV12 ) && |
| ( mCurrentTarget == TARGET_MSM7627A || mCurrentTarget == TARGET_MSM7627 ) && |
| previewWidth%32 != 0 ){ |
| ALOGE("initpreview : creating YV12 heap as previewwidth %d not 32 aligned", previewWidth); |
| #ifdef USE_ION |
| mYV12Heap = new IonPool(ion_heap, |
| MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING, |
| MSM_PMEM_PREVIEW, |
| yv12framesize, |
| NUM_YV12_FRAMES, |
| yv12framesize, |
| CbCrOffset, |
| 0, |
| "postview"); |
| #else |
| mYV12Heap = new PmemPool(pmem_region, |
| MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING, |
| MSM_PMEM_PREVIEW, |
| yv12framesize, |
| NUM_YV12_FRAMES, |
| yv12framesize, |
| CbCrOffset, |
| 0, |
| "postview"); |
| #endif |
| if (!mYV12Heap->initialized()) { |
| mYV12Heap.clear(); |
| ALOGE("initPreview X: could not initialize YV12 Camera preview heap."); |
| return false; |
| } |
| } |
| } |
| #endif |
| |
| if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250) || (mCurrentTarget == TARGET_MSM8660)) { |
| |
| // Allocate video buffers after allocating preview buffers. |
| bool status = initRecord(); |
| if(status != true) { |
| ALOGE("Failed to allocate video bufers"); |
| return false; |
| } |
| } |
| |
| if (ret) { |
| if(mIs3DModeOn != true) { |
| for (cnt = 0; cnt < kPreviewBufferCount; cnt++) { |
| #if 0 |
| frames[cnt].fd = mPreviewHeap->mHeap->getHeapID(); |
| frames[cnt].buffer = |
| (uint32_t)mPreviewHeap->mHeap->base() + mPreviewHeap->mAlignedBufferSize * cnt; |
| frames[cnt].y_off = 0; |
| frames[cnt].cbcr_off = CbCrOffset; |
| frames[cnt].path = OUTPUT_TYPE_P; // MSM_FRAME_ENC; |
| #endif |
| } |
| |
| mPreviewBusyQueue.init(); |
| LINK_camframe_release_all_frames(CAM_PREVIEW_FRAME); |
| for(int i=ACTIVE_PREVIEW_BUFFERS ;i <kPreviewBufferCount; i++) |
| LINK_camframe_add_frame(CAM_PREVIEW_FRAME,&frames[i]); |
| |
| mPreviewThreadWaitLock.lock(); |
| pthread_attr_t pattr; |
| pthread_attr_init(&pattr); |
| pthread_attr_setdetachstate(&pattr, PTHREAD_CREATE_DETACHED); |
| |
| mPreviewThreadRunning = !pthread_create(&mPreviewThread, |
| &pattr, |
| preview_thread, |
| (void*)NULL); |
| ret = mPreviewThreadRunning; |
| mPreviewThreadWaitLock.unlock(); |
| |
| if(ret == false) |
| return ret; |
| } |
| |
| |
| mFrameThreadWaitLock.lock(); |
| pthread_attr_t attr; |
| pthread_attr_init(&attr); |
| pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); |
| camframeParams.cammode = CAMERA_MODE_2D; |
| |
| if (mIs3DModeOn) { |
| camframeParams.cammode = CAMERA_MODE_3D; |
| } else { |
| camframeParams.cammode = CAMERA_MODE_2D; |
| } |
| LINK_cam_frame_set_exit_flag(0); |
| |
| mFrameThreadRunning = !pthread_create(&mFrameThread, |
| &attr, |
| frame_thread, |
| &camframeParams); |
| ret = mFrameThreadRunning; |
| mFrameThreadWaitLock.unlock(); |
| LINK_wait_cam_frame_thread_ready(); |
| } |
| mFirstFrame = true; |
| |
| ALOGV("initPreview X: %d", ret); |
| return ret; |
| } |
| |
| void QualcommCameraHardware::deinitPreview(void) |
| { |
| ALOGV("deinitPreview E"); |
| |
| mPreviewBusyQueue.deinit(); |
| |
| // When we call deinitPreview(), we signal to the frame thread that it |
| // needs to exit, but we DO NOT WAIT for it to complete here. The problem |
| // is that deinitPreview is sometimes called from the frame-thread's |
| // callback, when the refcount on the Camera client reaches zero. If we |
| // called pthread_join(), we would deadlock. So, we just call |
| // LINK_camframe_terminate() in deinitPreview(), which makes sure that |
| // after the preview callback returns, the camframe thread will exit. We |
| // could call pthread_join() in initPreview() to join the last frame |
| // thread. However, we would also have to call pthread_join() in release |
| // as well, shortly before we destroy the object; this would cause the same |
| // deadlock, since release(), like deinitPreview(), may also be called from |
| // the frame-thread's callback. This we have to make the frame thread |
| // detached, and use a separate mechanism to wait for it to complete. |
| |
| LINK_camframe_terminate(); |
| ALOGV("deinitPreview X"); |
| } |
| |
| bool QualcommCameraHardware::initRawSnapshot() |
| { |
| ALOGV("initRawSnapshot E"); |
| const char * pmem_region; |
| |
| //get width and height from Dimension Object |
| bool ret = native_set_parms(CAMERA_PARM_DIMENSION, |
| sizeof(cam_ctrl_dimension_t), &mDimension); |
| |
| |
| if(!ret){ |
| ALOGE("initRawSnapshot X: failed to set dimension"); |
| return false; |
| } |
| int rawSnapshotSize = mDimension.raw_picture_height * |
| mDimension.raw_picture_width; |
| |
| ALOGI("raw_snapshot_buffer_size = %d, raw_picture_height = %d, "\ |
| "raw_picture_width = %d", |
| rawSnapshotSize, mDimension.raw_picture_height, |
| mDimension.raw_picture_width); |
| |
| // Create Memory for Raw Snapshot |
| if( createSnapshotMemory(numCapture, numCapture, false, PICTURE_FORMAT_RAW) == false ) // TODO : check if the numbers are correct |
| { |
| ALOGE("ERROR : initRawSnapshot , createSnapshotMemory failed"); |
| return false; |
| } |
| |
| mRawCaptureParms.num_captures = 1; |
| mRawCaptureParms.raw_picture_width = mDimension.raw_picture_width; |
| mRawCaptureParms.raw_picture_height = mDimension.raw_picture_height; |
| |
| ALOGV("initRawSnapshot X"); |
| return true; |
| |
| } |
| bool QualcommCameraHardware::initZslBuffers(bool initJpegHeap){ |
| ALOGV("Init ZSL buffers E"); |
| const char * pmem_region; |
| int ion_heap = ION_CP_MM_HEAP_ID; |
| int postViewBufferSize; |
| |
| mPostviewWidth = mDimension.display_width; |
| mPostviewHeight = mDimension.display_height; |
| |
| //postview buffer initialization |
| postViewBufferSize = mPostviewWidth * mPostviewHeight * 3 / 2; |
| int CbCrOffsetPostview = PAD_TO_WORD(mPostviewWidth * mPostviewHeight); |
| if(mPreviewFormat == CAMERA_YUV_420_NV21_ADRENO) { |
| postViewBufferSize = PAD_TO_4K(CEILING32(mPostviewWidth) * CEILING32(mPostviewHeight)) + |
| 2 * (CEILING32(mPostviewWidth/2) * CEILING32(mPostviewHeight/2)); |
| int CbCrOffsetPostview = PAD_TO_4K(CEILING32(mPostviewWidth) * CEILING32(mPostviewHeight)); |
| } |
| |
| //Snapshot buffer initialization |
| mRawSize = mPictureWidth * mPictureHeight * 3 / 2; |
| mCbCrOffsetRaw = PAD_TO_WORD(mPictureWidth * mPictureHeight); |
| if(mPreviewFormat == CAMERA_YUV_420_NV21_ADRENO) { |
| mRawSize = PAD_TO_4K(CEILING32(mPictureWidth) * CEILING32(mPictureHeight)) + |
| 2 * (CEILING32(mPictureWidth/2) * CEILING32(mPictureHeight/2)); |
| mCbCrOffsetRaw = PAD_TO_4K(CEILING32(mPictureWidth) * CEILING32(mPictureHeight)); |
| } |
| |
| //Jpeg buffer initialization |
| if( mCurrentTarget == TARGET_MSM7627 || |
| (mCurrentTarget == TARGET_MSM7625A || |
| mCurrentTarget == TARGET_MSM7627A)) |
| mJpegMaxSize = CEILING16(mPictureWidth) * CEILING16(mPictureHeight) * 3 / 2; |
| else { |
| mJpegMaxSize = mPictureWidth * mPictureHeight * 3 / 2; |
| if(mPreviewFormat == CAMERA_YUV_420_NV21_ADRENO){ |
| mJpegMaxSize = |
| PAD_TO_4K(CEILING32(mPictureWidth) * CEILING32(mPictureHeight)) + |
| 2 * (CEILING32(mPictureWidth/2) * CEILING32(mPictureHeight/2)); |
| } |
| } |
| |
| cam_buf_info_t buf_info; |
| int yOffset = 0; |
| buf_info.resolution.width = mPictureWidth; |
| buf_info.resolution.height = mPictureHeight; |
| if(mPreviewFormat != CAMERA_YUV_420_NV21_ADRENO) { |
| mCfgControl.mm_camera_get_parm(CAMERA_PARM_BUFFER_INFO, (void *)&buf_info); |
| mRawSize = buf_info.size; |
| mJpegMaxSize = mRawSize; |
| mCbCrOffsetRaw = buf_info.cbcr_offset; |
| yOffset = buf_info.yoffset; |
| } |
| |
| ALOGV("initZslBuffer: initializing mRawHeap."); |
| if(mCurrentTarget == TARGET_MSM8660) { |
| pmem_region = "/dev/pmem_smipool"; |
| } else { |
| pmem_region = "/dev/pmem_adsp"; |
| } |
| //Main Raw Image |
| #if 0 |
| #ifdef USE_ION |
| mRawHeap = |
| new IonPool( ion_heap, |
| MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING, |
| MSM_PMEM_MAINIMG, |
| mJpegMaxSize, |
| MAX_SNAPSHOT_BUFFERS, |
| mRawSize, |
| mCbCrOffsetRaw, |
| yOffset, |
| "snapshot camera"); |
| #else |
| mRawHeap = |
| new PmemPool(pmem_region, |
| MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING, |
| MSM_PMEM_MAINIMG, |
| mJpegMaxSize, |
| MAX_SNAPSHOT_BUFFERS, |
| mRawSize, |
| mCbCrOffsetRaw, |
| yOffset, |
| "snapshot camera"); |
| #endif |
| if (!mRawHeap->initialized()) { |
| ALOGE("initZslBuffer X failed "); |
| mRawHeap.clear(); |
| ALOGE("initRaw X: error initializing mRawHeap"); |
| return false; |
| } |
| |
| |
| // Jpeg |
| if (initJpegHeap) { |
| ALOGV("initZslRaw: initializing mJpegHeap."); |
| mJpegHeap = |
| new AshmemPool(mJpegMaxSize, |
| (MAX_SNAPSHOT_BUFFERS - 2), // It is the max number of snapshot supported. |
| 0, // we do not know how big the picture will be |
| "jpeg"); |
| |
| if (!mJpegHeap->initialized()) { |
| mJpegHeap.clear(); |
| mRawHeap.clear(); |
| ALOGE("initZslRaw X failed: error initializing mJpegHeap."); |
| return false; |
| } |
| } |
| |
| //PostView |
| pmem_region = "/dev/pmem_adsp"; |
| ion_heap = ION_HEAP_ADSP_ID; |
| #ifdef USE_ION |
| mPostviewHeap = |
| new IonPool(ion_heap, |
| MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING, |
| MSM_PMEM_THUMBNAIL, |
| postViewBufferSize, |
| MAX_SNAPSHOT_BUFFERS, |
| postViewBufferSize, |
| CbCrOffsetPostview, |
| 0, |
| "thumbnail"); |
| #else |
| mPostviewHeap = |
| new PmemPool(pmem_region, |
| MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING, |
| MSM_PMEM_THUMBNAIL, |
| postViewBufferSize, |
| MAX_SNAPSHOT_BUFFERS, |
| postViewBufferSize, |
| CbCrOffsetPostview, |
| 0, |
| "thumbnail"); |
| #endif |
| |
| if (!mPostviewHeap->initialized()) { |
| mPostviewHeap.clear(); |
| mJpegHeap.clear(); |
| mRawHeap.clear(); |
| ALOGE("initZslBuffer X failed: error initializing mPostviewHeap."); |
| return false; |
| } |
| #endif |
| if( createSnapshotMemory(MAX_SNAPSHOT_BUFFERS, MAX_SNAPSHOT_BUFFERS, initJpegHeap) == false ) // TODO : check if the numbers are correct |
| { |
| ALOGE("ERROR : initZslraw , createSnapshotMemory failed"); |
| return false; |
| } |
| /* frame all the exif and encode information into encode_params_t */ |
| initImageEncodeParameters(MAX_SNAPSHOT_BUFFERS); |
| |
| ALOGV("initZslRaw X"); |
| return true; |
| } |
| |
| bool QualcommCameraHardware::deinitZslBuffers() |
| { |
| ALOGV("deinitZslBuffers E"); |
| for (int cnt = 0; cnt < (mZslEnable? MAX_SNAPSHOT_BUFFERS : numCapture); cnt++) { |
| if(NULL != mRawMapped[cnt]) { |
| ALOGI("Unregister MAIN_IMG"); |
| register_buf(mJpegMaxSize, |
| mRawSize,mCbCrOffsetRaw,0, |
| mRawfd[cnt],0, |
| (uint8_t *)mRawMapped[cnt]->data, |
| MSM_PMEM_MAINIMG, |
| 0, 0); |
| mRawMapped[cnt]->release(mRawMapped[cnt]); |
| mRawMapped[cnt] = NULL; |
| close(mRawfd[cnt]); |
| #ifdef USE_ION |
| deallocate_ion_memory(&raw_main_ion_fd[cnt], &raw_ion_info_fd[cnt]); |
| #endif |
| } |
| } |
| for (int cnt = 0; cnt < (mZslEnable? (MAX_SNAPSHOT_BUFFERS) : numCapture); cnt++) { |
| if(mJpegMapped[cnt]) { |
| mJpegMapped[cnt]->release(mJpegMapped[cnt]); |
| mJpegMapped[cnt] = NULL; |
| } |
| } |
| ALOGV("deinitZslBuffers X"); |
| return true; |
| } |
| |
| bool QualcommCameraHardware::createSnapshotMemory (int numberOfRawBuffers, int numberOfJpegBuffers, |
| bool initJpegHeap, int snapshotFormat) |
| { |
| char * pmem_region; |
| int ret; |
| int ion_heap = ION_CP_MM_HEAP_ID; |
| if(mCurrentTarget == TARGET_MSM8660) { |
| pmem_region = "/dev/pmem_smipool"; |
| } else { |
| pmem_region = "/dev/pmem_adsp"; |
| } |
| if( snapshotFormat == PICTURE_FORMAT_JPEG) { |
| // Create Raw memory for snapshot |
| for(int cnt = 0; cnt < numberOfRawBuffers; cnt++) |
| { |
| #ifdef USE_ION |
| if (allocate_ion_memory(&raw_main_ion_fd[cnt], &raw_alloc[cnt], &raw_ion_info_fd[cnt], |
| ion_heap, mJpegMaxSize, &mRawfd[cnt]) < 0){ |
| ALOGE("do_mmap: Open device %s failed!\n",pmem_region); |
| return NULL; |
| } |
| #else |
| mRawfd[cnt] = open(pmem_region, O_RDWR|O_SYNC); |
| if (mRawfd[cnt] <= 0) { |
| ALOGE("%s: Open device %s failed!\n",__func__, pmem_region); |
| return false; |
| } |
| #endif |
| ALOGI("%s Raw memory index: %d , fd is %d ", __func__, cnt, mRawfd[cnt]); |
| mRawMapped[cnt]=mGetMemory(mRawfd[cnt], mJpegMaxSize,1,mCallbackCookie); |
| if(mRawMapped[cnt] == NULL) { |
| ALOGE("Failed to get camera memory for mRawMapped heap index: %d", cnt); |
| return false; |
| }else{ |
| ALOGI("Received following info for raw mapped data:%p,handle:%p, size:%d,release:%p", |
| mRawMapped[cnt]->data ,mRawMapped[cnt]->handle, mRawMapped[cnt]->size, mRawMapped[cnt]->release); |
| } |
| // Register Raw frames |
| ALOGI("Registering buffer %d with fd :%d with kernel",cnt,mRawfd[cnt]); |
| int active = (cnt < ACTIVE_ZSL_BUFFERS); // TODO check ? |
| register_buf(mJpegMaxSize, |
| mRawSize, |
| mCbCrOffsetRaw, |
| mYOffset, |
| mRawfd[cnt],0, |
| (uint8_t *)mRawMapped[cnt]->data, |
| MSM_PMEM_MAINIMG, |
| active); |
| } |
| // Create Jpeg memory for snapshot |
| if (initJpegHeap) |
| { |
| for(int cnt = 0; cnt < numberOfJpegBuffers; cnt++) |
| { |
| ALOGI("%s Jpeg memory index: %d , fd is %d ", __func__, cnt, mJpegfd[cnt]); |
| mJpegMapped[cnt]=mGetMemory(-1, mJpegMaxSize,1,mCallbackCookie); |
| if(mJpegMapped[cnt] == NULL) { |
| ALOGE("Failed to get camera memory for mJpegMapped heap index: %d", cnt); |
| return false; |
| }else{ |
| ALOGI("Received following info for jpeg mapped data:%p,handle:%p, size:%d,release:%p", |
| mJpegMapped[cnt]->data ,mJpegMapped[cnt]->handle, mJpegMapped[cnt]->size, mJpegMapped[cnt]->release); |
| } |
| } |
| } |
| // Lock Thumbnail buffers, and register them |
| ALOGI("Locking and registering Thumbnail buffer(s)"); |
| for(int cnt = 0; cnt < (mZslEnable? (MAX_SNAPSHOT_BUFFERS-2) : numCapture); cnt++) { |
| // TODO : change , lock all thumbnail buffers |
| if((mPreviewWindow != NULL) && (mThumbnailBuffer[cnt] != NULL)) { |
| ALOGI("createsnapshotbuffers : display lock"); |
| mDisplayLock.lock(); |
| /* Lock the postview buffer before use */ |
| ALOGI(" Locking thumbnail/postview buffer %d", cnt); |
| if( (ret = mPreviewWindow->lock_buffer(mPreviewWindow, |
| mThumbnailBuffer[cnt])) != NO_ERROR) { |
| ALOGE(" Error locking postview buffer. Error = %d ", ret); |
| ALOGE("createsnapshotbuffers : display unlock error"); |
| mDisplayLock.unlock(); |
| return false; |
| } |
| if (GENLOCK_NO_ERROR != genlock_lock_buffer((native_handle_t*)(*mThumbnailBuffer[cnt]), |
| GENLOCK_WRITE_LOCK, GENLOCK_MAX_TIMEOUT)) { |
| ALOGE("%s: genlock_lock_buffer(WRITE) failed", __FUNCTION__); |
| mDisplayLock.unlock(); |
| return -EINVAL; |
| } else { |
| mThumbnailLockState[cnt] = BUFFER_LOCKED; |
| } |
| mDisplayLock.unlock(); |
| ALOGE("createsnapshotbuffers : display unlock"); |
| } |
| |
| private_handle_t *thumbnailHandle; |
| int mBufferSize = previewWidth * previewHeight * 3/2; |
| int mCbCrOffset = PAD_TO_WORD(previewWidth * previewHeight); |
| |
| if(mThumbnailBuffer[cnt]) { |
| thumbnailHandle = (private_handle_t *)(*mThumbnailBuffer[cnt]); |
| ALOGI("fd thumbnailhandle fd %d size %d", thumbnailHandle->fd, thumbnailHandle->size); |
| mThumbnailMapped [cnt]= (unsigned int) mmap(0, thumbnailHandle->size, PROT_READ|PROT_WRITE, |
| MAP_SHARED, thumbnailHandle->fd, 0); |
| if((void *)mThumbnailMapped[cnt] == MAP_FAILED){ |
| ALOGE(" Couldnt map Thumbnail buffer %d", errno); |
| return false; |
| } |
| register_buf(mBufferSize, |
| mBufferSize, mCbCrOffset, 0, |
| thumbnailHandle->fd, |
| 0, |
| (uint8_t *)mThumbnailMapped[cnt], |
| MSM_PMEM_THUMBNAIL, |
| (cnt < ACTIVE_ZSL_BUFFERS)); |
| } |
| } // for loop locking and registering thumbnail buffers |
| } else { // End if Format is Jpeg , start if format is RAW |
| if(numberOfRawBuffers ==1) { |
| int rawSnapshotSize = mDimension.raw_picture_height * mDimension.raw_picture_width; |
| #ifdef USE_ION |
| if (allocate_ion_memory(&raw_snapshot_main_ion_fd, &raw_snapshot_alloc, &raw_snapshot_ion_info_fd, |
| ion_heap, rawSnapshotSize, &mRawSnapshotfd) < 0){ |
| ALOGE("do_mmap: Open device %s failed!\n",pmem_region); |
| return false; |
| } |
| #else |
| mRawSnapshotfd = open(pmem_region, O_RDWR|O_SYNC); |
| if (mRawSnapshotfd <= 0) { |
| ALOGE("%s: Open device %s failed for rawnspashot!\n",__func__, pmem_region); |
| return false; |
| } |
| #endif |
| ALOGI("%s Raw snapshot memory , fd is %d ", __func__, mRawSnapshotfd); |
| mRawSnapshotMapped=mGetMemory(mRawSnapshotfd, |
| rawSnapshotSize, |
| 1, |
| mCallbackCookie); |
| if(mRawSnapshotMapped == NULL) { |
| ALOGE("Failed to get camera memory for mRawSnapshotMapped "); |
| return false; |
| }else{ |
| ALOGI("Received following info for raw mapped data:%p,handle:%p, size:%d,release:%p", |
| mRawSnapshotMapped->data ,mRawSnapshotMapped->handle, mRawSnapshotMapped->size, mRawSnapshotMapped->release); |
| } |
| // Register Raw frames |
| ALOGI("Registering RawSnapshot buffer with fd :%d with kernel",mRawSnapshotfd); |
| int active = 1; // TODO check ? |
| register_buf( rawSnapshotSize, |
| rawSnapshotSize, |
| 0, |
| 0, |
| mRawSnapshotfd, |
| 0, |
| (uint8_t *)mRawSnapshotMapped->data, |
| MSM_PMEM_RAW_MAINIMG, |
| active); |
| } else { |
| ALOGE("Multiple raw snapshot capture not supported for now...."); |
| return false; |
| } |
| } // end else , if RAW format |
| return true; |
| } |
| bool QualcommCameraHardware::initRaw(bool initJpegHeap) |
| { |
| const char * pmem_region; |
| int ion_heap; |
| int postViewBufferSize; |
| uint32_t pictureAspectRatio; |
| uint32_t i; |
| mParameters.getPictureSize(&mPictureWidth, &mPictureHeight); |
| mActualPictWidth = mPictureWidth; |
| mActualPictHeight = mPictureHeight; |
| if (updatePictureDimension(mParameters, mPictureWidth, mPictureHeight)) { |
| mDimension.picture_width = mPictureWidth; |
| mDimension.picture_height = mPictureHeight; |
| } |
| ALOGV("initRaw E: picture size=%dx%d", mPictureWidth, mPictureHeight); |
| int w_scale_factor = (mIs3DModeOn && mSnapshot3DFormat == SIDE_BY_SIDE_FULL) ? 2 : 1; |
| |
| /* use the default thumbnail sizes */ |
| mThumbnailHeight = thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height; |
| mThumbnailWidth = (mThumbnailHeight * mPictureWidth)/ mPictureHeight; |
| /* see if we can get better thumbnail sizes (not mandatory?) */ |
| pictureAspectRatio = (uint32_t)((mPictureWidth * Q12) / mPictureHeight); |
| for(i = 0; i < THUMBNAIL_SIZE_COUNT; i++ ){ |
| if(thumbnail_sizes[i].aspect_ratio == pictureAspectRatio) |
| { |
| mThumbnailWidth = thumbnail_sizes[i].width; |
| mThumbnailHeight = thumbnail_sizes[i].height; |
| break; |
| } |
| } |
| /* calculate thumbnail aspect ratio */ |
| if(mCurrentTarget == TARGET_MSM7627 ) { |
| int thumbnail_aspect_ratio = |
| (uint32_t)((mThumbnailWidth * Q12) / mThumbnailHeight); |
| |
| if (thumbnail_aspect_ratio < pictureAspectRatio) { |
| |
| /* if thumbnail is narrower than main image, in other words wide mode |
| * snapshot then we want to adjust the height of the thumbnail to match |
| * the main image aspect ratio. */ |
| mThumbnailHeight = |
| (mThumbnailWidth * Q12) / pictureAspectRatio; |
| } else if (thumbnail_aspect_ratio != pictureAspectRatio) { |
| |
| /* if thumbnail is wider than main image we want to adjust width of the |
| * thumbnail to match main image aspect ratio */ |
| mThumbnailWidth = |
| (mThumbnailHeight * pictureAspectRatio) / Q12; |
| } |
| /* make the dimensions multiple of 16 - JPEG requirement */ |
| mThumbnailWidth = FLOOR16(mThumbnailWidth); |
| mThumbnailHeight = FLOOR16(mThumbnailHeight); |
| ALOGV("the thumbnail sizes are %dx%d",mThumbnailWidth,mThumbnailHeight); |
| } |
| |
| /* calculate postView size */ |
| mPostviewWidth = mThumbnailWidth; |
| mPostviewHeight = mThumbnailHeight; |
| /* Try to keep the postview dimensions near to preview for better |
| * performance and userexperience. If the postview and preview dimensions |
| * are same, then we can try to use the same overlay of preview for |
| * postview also. If not, we need to reset the overlay for postview. |
| * we will be getting the same dimensions for preview and postview |
| * in most of the cases. The only exception is for applications |
| * which won't use optimalPreviewSize based on picture size. |
| */ |
| if((mPictureHeight >= previewHeight) && |
| (mCurrentTarget != TARGET_MSM7627) && !mIs3DModeOn) { |
| mPostviewHeight = previewHeight; |
| mPostviewWidth = (previewHeight * mPictureWidth) / mPictureHeight; |
| }else if(mActualPictHeight < mThumbnailHeight){ |
| mPostviewHeight = THUMBNAIL_SMALL_HEIGHT; |
| mPostviewWidth = (THUMBNAIL_SMALL_HEIGHT * mActualPictWidth)/ mActualPictHeight; |
| mThumbnailWidth = mPostviewWidth; |
| mThumbnailHeight = mPostviewHeight; |
| } |
| |
| if(mPreviewFormat == CAMERA_YUV_420_NV21_ADRENO){ |
| mDimension.main_img_format = CAMERA_YUV_420_NV21_ADRENO; |
| mDimension.thumb_format = CAMERA_YUV_420_NV21_ADRENO; |
| } |
| |
| mDimension.ui_thumbnail_width = mPostviewWidth; |
| mDimension.ui_thumbnail_height = mPostviewHeight; |
| |
| // mDimension will be filled with thumbnail_width, thumbnail_height, |
| // orig_picture_dx, and orig_picture_dy after this function call. We need to |
| // keep it for jpeg_encoder_encode. |
| bool ret = native_set_parms(CAMERA_PARM_DIMENSION, |
| sizeof(cam_ctrl_dimension_t), &mDimension); |
| |
| if(!ret) { |
| ALOGE("initRaw X: failed to set dimension"); |
| return false; |
| } |
| #if 0 |
| if (mJpegHeap != NULL) { |
| ALOGV("initRaw: clearing old mJpegHeap."); |
| mJpegHeap.clear(); |
| } |
| #endif |
| //postview buffer initialization |
| postViewBufferSize = mPostviewWidth * w_scale_factor * mPostviewHeight * 3 / 2; |
| int CbCrOffsetPostview = PAD_TO_WORD(mPostviewWidth * w_scale_factor * mPostviewHeight); |
| |
| //Snapshot buffer initialization |
| mRawSize = mPictureWidth * w_scale_factor * mPictureHeight * 3 / 2; |
| mCbCrOffsetRaw = PAD_TO_WORD(mPictureWidth * w_scale_factor * mPictureHeight); |
| if(mPreviewFormat == CAMERA_YUV_420_NV21_ADRENO) { |
| mRawSize = PAD_TO_4K(CEILING32(mPictureWidth * w_scale_factor) * CEILING32(mPictureHeight)) + |
| 2 * (CEILING32(mPictureWidth * w_scale_factor/2) * CEILING32(mPictureHeight/2)); |
| mCbCrOffsetRaw = PAD_TO_4K(CEILING32(mPictureWidth * w_scale_factor) * CEILING32(mPictureHeight)); |
| } |
| |
| //Jpeg buffer initialization |
| if( mCurrentTarget == TARGET_MSM7627 || |
| (mCurrentTarget == TARGET_MSM7625A || |
| mCurrentTarget == TARGET_MSM7627A)) |
| mJpegMaxSize = CEILING16(mPictureWidth * w_scale_factor) * CEILING16(mPictureHeight) * 3 / 2; |
| else { |
| mJpegMaxSize = mPictureWidth * w_scale_factor * mPictureHeight * 3 / 2; |
| if(mPreviewFormat == CAMERA_YUV_420_NV21_ADRENO){ |
| mJpegMaxSize = |
| PAD_TO_4K(CEILING32(mPictureWidth * w_scale_factor) * CEILING32(mPictureHeight)) + |
| 2 * (CEILING32(mPictureWidth * w_scale_factor/2) * CEILING32(mPictureHeight/2)); |
| } |
| } |
| |
| int rotation = mParameters.getInt("rotation"); |
| char mDeviceName[PROPERTY_VALUE_MAX]; |
| property_get("ro.hw_plat", mDeviceName, ""); |
| if(!strcmp(mDeviceName,"7x25A")) |
| rotation = (rotation + 90)%360; |
| |
| if (mIs3DModeOn) |
| rotation = 0; |
| ret = native_set_parms(CAMERA_PARM_JPEG_ROTATION, sizeof(int), &rotation); |
| if(!ret){ |
| ALOGE("setting camera id failed"); |
| return false; |
| } |
| cam_buf_info_t buf_info; |
| if(mIs3DModeOn == false) |
| { |
| buf_info.resolution.width = mPictureWidth * w_scale_factor; |
| buf_info.resolution.height = mPictureHeight; |
| mCfgControl.mm_camera_get_parm(CAMERA_PARM_BUFFER_INFO, (void *)&buf_info); |
| mRawSize = buf_info.size; |
| mJpegMaxSize = mRawSize; |
| mCbCrOffsetRaw = buf_info.cbcr_offset; |
| mYOffset = buf_info.yoffset; |
| } |
| int mBufferSize; |
| int CbCrOffset; |
| if(mCurrentTarget != TARGET_MSM7627 && mCurrentTarget != TARGET_MSM7627A){ |
| mParameters.getPreviewSize(&previewWidth, &previewHeight); |
| mBufferSize = previewWidth * previewHeight * 3/2; |
| CbCrOffset = PAD_TO_WORD(previewWidth * previewHeight); |
| } |
| else { |
| mBufferSize = mPostviewWidth * mPostviewHeight * 3/2; |
| CbCrOffset = PAD_TO_WORD(mPostviewWidth * mPostviewHeight); |
| } |
| |
| ALOGV("initRaw: initializing mRawHeap."); |
| |
| //PostView |
| pmem_region = "/dev/pmem_adsp"; |
| ion_heap = ION_CAMERA_HEAP_ID; |
| // Create memory for Raw YUV frames and Jpeg images |
| if( createSnapshotMemory(numCapture, numCapture, initJpegHeap) == false ) |
| { |
| ALOGE("ERROR : initraw , createSnapshotMemory failed"); |
| return false; |
| } |
| /* frame all the exif and encode information into encode_params_t */ |
| |
| initImageEncodeParameters(numCapture); |
| /* fill main image size, thumbnail size, postview size into capture_params_t*/ |
| memset(&mImageCaptureParms, 0, sizeof(capture_params_t)); |
| mImageCaptureParms.num_captures = numCapture; |
| mImageCaptureParms.picture_width = mPictureWidth; |
| mImageCaptureParms.picture_height = mPictureHeight; |
| mImageCaptureParms.postview_width = mPostviewWidth; |
| mImageCaptureParms.postview_height = mPostviewHeight; |
| |
| int width = mParameters.getInt(QCameraParameters::KEY_JPEG_THUMBNAIL_WIDTH); |
| int height = mParameters.getInt(QCameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT); |
| if((width != 0) && (height != 0)) { |
| mImageCaptureParms.thumbnail_width = mThumbnailWidth; |
| mImageCaptureParms.thumbnail_height = mThumbnailHeight; |
| } else { |
| mImageCaptureParms.thumbnail_width = 0; |
| mImageCaptureParms.thumbnail_height = 0; |
| } |
| |
| ALOGI("%s: picture size=%dx%d",__FUNCTION__, |
| mImageCaptureParms.picture_width, mImageCaptureParms.picture_height); |
| ALOGI("%s: postview size=%dx%d",__FUNCTION__, |
| mImageCaptureParms.postview_width, mImageCaptureParms.postview_height); |
| ALOGI("%s: thumbnail size=%dx%d",__FUNCTION__, |
| mImageCaptureParms.thumbnail_width, mImageCaptureParms.thumbnail_height); |
| |
| ALOGV("initRaw X"); |
| return true; |
| } |
| |
| |
| void QualcommCameraHardware::deinitRawSnapshot() |
| { |
| ALOGV("deinitRawSnapshot E"); |
| |
| int rawSnapshotSize = mDimension.raw_picture_height * mDimension.raw_picture_width; |
| // Unregister and de allocated memory for Raw Snapshot |
| if(mRawSnapshotMapped) { |
| register_buf( rawSnapshotSize, |
| rawSnapshotSize, |
| 0, |
| 0, |
| mRawSnapshotfd, |
| 0, |
| (uint8_t *)mRawSnapshotMapped->data, |
| MSM_PMEM_RAW_MAINIMG, |
| false, |
| false); |
| mRawSnapshotMapped->release(mRawSnapshotMapped); |
| mRawSnapshotMapped = NULL; |
| close(mRawSnapshotfd); |
| #ifdef USE_ION |
| deallocate_ion_memory(&raw_snapshot_main_ion_fd, &raw_snapshot_ion_info_fd); |
| #endif |
| } |
| ALOGV("deinitRawSnapshot X"); |
| } |
| |
| void QualcommCameraHardware::deinitRaw() |
| { |
| ALOGV("deinitRaw E"); |
| ALOGV("deinitRaw , clearing raw memory and jpeg memory"); |
| for (int cnt = 0; cnt < (mZslEnable? MAX_SNAPSHOT_BUFFERS : numCapture); cnt++) { |
| if(NULL != mRawMapped[cnt]) { |
| ALOGI("Unregister MAIN_IMG"); |
| register_buf(mJpegMaxSize, |
| mRawSize,mCbCrOffsetRaw,0, |
| mRawfd[cnt],0, |
| (uint8_t *)mRawMapped[cnt]->data, |
| MSM_PMEM_MAINIMG, |
| 0, 0); |
| mRawMapped[cnt]->release(mRawMapped[cnt]); |
| mRawMapped[cnt] = NULL; |
| close(mRawfd[cnt]); |
| #ifdef USE_ION |
| deallocate_ion_memory(&raw_main_ion_fd[cnt], &raw_ion_info_fd[cnt]); |
| #endif |
| } |
| } |
| for (int cnt = 0; cnt < (mZslEnable? (MAX_SNAPSHOT_BUFFERS) : numCapture); cnt++) { |
| if(NULL != mJpegMapped[cnt]) { |
| mJpegMapped[cnt]->release(mJpegMapped[cnt]); |
| mJpegMapped[cnt] = NULL; |
| } |
| } |
| if( mPreviewWindow != NULL ) { |
| ALOGI("deinitRaw , clearing/cancelling thumbnail buffers:"); |
| private_handle_t *handle; |
| for (int cnt = 0; cnt < (mZslEnable? (MAX_SNAPSHOT_BUFFERS-2) : numCapture); cnt++) { |
| if(mPreviewWindow != NULL && mThumbnailBuffer[cnt] != NULL) { |
| handle = (private_handle_t *)(*mThumbnailBuffer[cnt]); |
| ALOGI("%s: Cancelling postview buffer %d ", __FUNCTION__, handle->fd); |
| ALOGI("deinitraw : display lock"); |
| mDisplayLock.lock(); |
| if (BUFFER_LOCKED == mThumbnailLockState[cnt]) { |
| if (GENLOCK_FAILURE == genlock_unlock_buffer(handle)) { |
| ALOGE("%s: genlock_unlock_buffer failed", __FUNCTION__); |
| } else { |
| mThumbnailLockState[cnt] = BUFFER_UNLOCKED; |
| } |
| } |
| status_t retVal = mPreviewWindow->cancel_buffer(mPreviewWindow, |
| mThumbnailBuffer[cnt]); |
| if(retVal != NO_ERROR) |
| ALOGE("%s: cancelBuffer failed for postview buffer %d", |
| __FUNCTION__, handle->fd); |
| if(mStoreMetaDataInFrame && (metadata_memory[cnt] != NULL)){ |
| struct encoder_media_buffer_type * packet = |
| (struct encoder_media_buffer_type *)metadata_memory[cnt]->data; |
| native_handle_delete(const_cast<native_handle_t *>(packet->meta_handle)); |
| metadata_memory[cnt]->release(metadata_memory[cnt]); |
| metadata_memory[cnt] = NULL; |
| } |
| // unregister , unmap and release as well |
| |
| int mBufferSize = previewWidth * previewHeight * 3/2; |
| int mCbCrOffset = PAD_TO_WORD(previewWidth * previewHeight); |
| if(mThumbnailMapped[cnt]) { |
| ALOGI("%s: Unregistering Thumbnail Buffer %d ", __FUNCTION__, handle->fd); |
| register_buf(mBufferSize, |
| mBufferSize, mCbCrOffset, 0, |
| handle->fd, |
| 0, |
| (uint8_t *)mThumbnailMapped[cnt], |
| MSM_PMEM_THUMBNAIL, |
| false, false); |
| if (munmap((void *)(mThumbnailMapped[cnt]),handle->size ) == -1) { |
| ALOGE("deinitraw : Error un-mmapping the thumbnail buffer %d", index); |
| } |
| mThumbnailBuffer[cnt] = NULL; |
| mThumbnailMapped[cnt] = NULL; |
| } |
| ALOGI("deinitraw : display unlock"); |
| mDisplayLock.unlock(); |
| } |
| } |
| } |
| ALOGV("deinitRaw X"); |
| } |
| |
| void QualcommCameraHardware::relinquishBuffers() |
| { |
| status_t retVal; |
| ALOGV("%s: E ", __FUNCTION__); |
| mDisplayLock.lock(); |
| if( mPreviewWindow != NULL) { |
| for(int cnt = 0; cnt < mTotalPreviewBufferCount; cnt++) { |
| if (BUFFER_LOCKED == frame_buffer[cnt].lockState) { |
| ALOGI(" Cancelling preview buffers %d ",frames[cnt].fd); |
| if (GENLOCK_FAILURE == genlock_unlock_buffer((native_handle_t *) |
| (*(frame_buffer[cnt].buffer)))) { |
| ALOGE("%s: genlock_unlock_buffer failed", __FUNCTION__); |
| } else { |
| frame_buffer[cnt].lockState = BUFFER_UNLOCKED; |
| } |
| } |
| retVal = mPreviewWindow->cancel_buffer(mPreviewWindow, |
| frame_buffer[cnt].buffer); |
| mPreviewMapped[cnt]->release(mPreviewMapped[cnt]); |
| if(mStoreMetaDataInFrame && (metadata_memory[cnt] != NULL)){ |
| struct encoder_media_buffer_type * packet = |
| (struct encoder_media_buffer_type *)metadata_memory[cnt]->data; |
| native_handle_delete(const_cast<native_handle_t *>(packet->meta_handle)); |
| metadata_memory[cnt]->release(metadata_memory[cnt]); |
| metadata_memory[cnt] = NULL; |
| } |
| ALOGI("release preview buffers"); |
| if(retVal != NO_ERROR) |
| ALOGE("%s: cancelBuffer failed for preview buffer %d ", |
| __FUNCTION__, frames[cnt].fd); |
| } |
| } else { |
| ALOGV(" PreviewWindow is null, will not cancelBuffers "); |
| } |
| mDisplayLock.unlock(); |
| ALOGV("%s: X ", __FUNCTION__); |
| } |
| status_t QualcommCameraHardware::set_PreviewWindow(void* param) |
| { |
| ALOGV(": set_preview_window"); |
| preview_stream_ops_t* window = (preview_stream_ops_t*)param; |
| return setPreviewWindow(window); |
| } |
| |
| status_t QualcommCameraHardware::setPreviewWindow(preview_stream_ops_t* window) |
| { |
| status_t retVal = NO_ERROR; |
| ALOGV(" %s: E ", __FUNCTION__); |
| if( window == NULL) { |
| ALOGW(" Setting NULL preview window "); |
| /* Current preview window will be invalidated. |
| * Release all the buffers back */ |
| //@TODO: We may need to this to avoid leak |
| /*if(mPreviewWindow!=NULL) |
| relinquishBuffers();*/ |
| } |
| ALOGI("Set preview window:: "); |
| mDisplayLock.lock(); |
| mPreviewWindow = window; |
| mDisplayLock.unlock(); |
| |
| if( (mPreviewWindow != NULL) && mCameraRunning) { |
| /* Initial preview in progress. Stop it and start |
| * the actual preview */ |
| stopInitialPreview(); |
| retVal = getBuffersAndStartPreview(); |
| } |
| ALOGV(" %s : X ", __FUNCTION__ ); |
| return retVal; |
| } |
| |
| status_t QualcommCameraHardware::getBuffersAndStartPreview() { |
| status_t retVal = NO_ERROR; |
| int stride; |
| bool all_chnls = false; |
| ALOGI(" %s : E ", __FUNCTION__); |
| mFrameThreadWaitLock.lock(); |
| while (mFrameThreadRunning) { |
| ALOGV("%s: waiting for old frame thread to complete.", __FUNCTION__); |
| mFrameThreadWait.wait(mFrameThreadWaitLock); |
| ALOGV("%s: old frame thread completed.",__FUNCTION__); |
| } |
| mFrameThreadWaitLock.unlock(); |
| |
| if( mPreviewWindow!= NULL) { |
| ALOGV("%s: Calling native_window_set_buffer", __FUNCTION__); |
| |
| android_native_buffer_t *mPreviewBuffer; |
| int32_t previewFormat; |
| const char *str = mParameters.getPreviewFormat(); |
| int numMinUndequeuedBufs = 0; |
| |
| int err = mPreviewWindow->get_min_undequeued_buffer_count(mPreviewWindow, |
| &numMinUndequeuedBufs); |
| |
| if (err != 0) { |
| ALOGW("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)", |
| strerror(-err), -err); |
| return err; |
| } |
| mTotalPreviewBufferCount = kPreviewBufferCount + numMinUndequeuedBufs; |
| |
| previewFormat = attr_lookup(app_preview_formats, |
| sizeof(app_preview_formats) / sizeof(str_map), str); |
| if (previewFormat == NOT_FOUND) { |
| previewFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP; |
| } |
| |
| retVal = mPreviewWindow->set_buffer_count(mPreviewWindow, |
| mTotalPreviewBufferCount + |
| (mZslEnable? (MAX_SNAPSHOT_BUFFERS-2) : numCapture) ); //1); |
| |
| if(retVal != NO_ERROR) { |
| ALOGE("%s: Error while setting buffer count to %d ", __FUNCTION__, kPreviewBufferCount + 1); |
| return retVal; |
| } |
| mParameters.getPreviewSize(&previewWidth, &previewHeight); |
| |
| retVal = mPreviewWindow->set_buffers_geometry(mPreviewWindow, |
| previewWidth, previewHeight, previewFormat); |
| |
| if(retVal != NO_ERROR) { |
| ALOGE("%s: Error while setting buffer geometry ", __FUNCTION__); |
| return retVal; |
| } |
| |
| #ifdef USE_ION |
| mPreviewWindow->set_usage (mPreviewWindow, |
| GRALLOC_USAGE_PRIVATE_CAMERA_HEAP | |
| GRALLOC_USAGE_PRIVATE_UNCACHED); |
| #else |
| mPreviewWindow->set_usage (mPreviewWindow, |
| GRALLOC_USAGE_PRIVATE_ADSP_HEAP | |
| GRALLOC_USAGE_PRIVATE_UNCACHED); |
| #endif |
| int CbCrOffset = PAD_TO_WORD(previewWidth * previewHeight); |
| int cnt = 0, active = 1; |
| int mBufferSize = previewWidth * previewHeight * 3/2; |
| for (cnt = 0; cnt < mTotalPreviewBufferCount; cnt++) { |
| //const native_handle *nh = (native_handle *)malloc (sizeof(native_handle)); |
| buffer_handle_t *bhandle =NULL;// &nh; ; |
| //buffer_handle_t *bh_handle=&handle; |
| retVal = mPreviewWindow->dequeue_buffer(mPreviewWindow, |
| &(bhandle), |
| &(stride)); |
| |
| if((retVal == NO_ERROR)) { |
| /* Acquire lock on the buffer if it was successfully |
| * dequeued from gralloc */ |
| ALOGV(" Locking buffer %d ", cnt); |
| retVal = mPreviewWindow->lock_buffer(mPreviewWindow, |
| bhandle); |
| // lock the buffer using genlock |
| if (GENLOCK_NO_ERROR != genlock_lock_buffer((native_handle_t *)(*bhandle), |
| GENLOCK_WRITE_LOCK, GENLOCK_MAX_TIMEOUT)) { |
| ALOGE("%s: genlock_lock_buffer(WRITE) failed", __FUNCTION__); |
| return -EINVAL; |
| } |
| ALOGI(" Locked buffer %d successfully", cnt); |
| //yyan todo use handle to find out mPreviewBuffer |
| |
| } else { |
| ALOGE("%s: dequeueBuffer failed for preview buffer. Error = %d", |
| __FUNCTION__, retVal); |
| return retVal; |
| } |
| if(retVal == NO_ERROR) { |
| private_handle_t *handle = (private_handle_t *)(*bhandle);//(private_handle_t *)mPreviewBuffer->handle; |
| ALOGI("Handle %p, Fd passed:%d, Base:%p, Size %p", |
| handle,handle->fd,handle->base,handle->size); |
| |
| if(handle) { |
| |
| //thumbnailHandle = (private_handle_t *)mThumbnailBuffer->handle; |
| ALOGV("fd mmap fd %d size %d", handle->fd, handle->size/*thumbnailHandle->size*/); |
| mPreviewMapped[cnt]= mGetMemory(handle->fd,handle->size,1,mCallbackCookie); |
| |
| if((void *)mPreviewMapped[cnt] == NULL){ |
| ALOGE(" Failed to get camera memory for Preview buffer %d ",cnt); |
| }else{ |
| ALOGI(" Mapped Preview buffer %d", cnt); |
| } |
| ALOGI("Got the following from get_mem data: %p, handle :%d, release : %p, size: %d", |
| mPreviewMapped[cnt]->data, |
| mPreviewMapped[cnt]->handle, |
| mPreviewMapped[cnt]->release, |
| mPreviewMapped[cnt]->size); |
| ALOGI(" getbuffersandrestartpreview deQ %d", handle->fd); |
| frames[cnt].fd = handle->fd; |
| frames[cnt].buffer = (unsigned int)mPreviewMapped[cnt]->data;//(unsigned int)mPreviewHeap[cnt]->mHeap->base(); |
| if(((void *)frames[cnt].buffer == MAP_FAILED) |
| || (frames[cnt].buffer == 0)) { |
| ALOGE("%s: Couldnt map preview buffers", __FUNCTION__); |
| return UNKNOWN_ERROR; |
| } |
| |
| if(mPreviewFormat == CAMERA_YUV_420_YV12 && mCurrentTarget != TARGET_MSM7627A) { |
| myv12_params.CbOffset = PAD_TO_WORD(previewWidth * previewHeight); |
| myv12_params.CrOffset = myv12_params.CbOffset + PAD_TO_WORD((previewWidth * previewHeight)/4); |
| ALOGI("CbOffset = 0x%x CrOffset = 0x%x \n",myv12_params.CbOffset, myv12_params.CrOffset); |
| frames[cnt].planar0_off = 0; |
| frames[cnt].planar1_off = myv12_params.CbOffset; |
| frames[cnt].planar2_off = myv12_params.CrOffset; |
| frames[cnt].path = OUTPUT_TYPE_P; // MSM_FRAME_ENC; |
| all_chnls = true; |
| }else{ |
| frames[cnt].planar0_off = 0; |
| frames[cnt].planar1_off= CbCrOffset; |
| frames[cnt].planar2_off = 0; |
| frames[cnt].path = OUTPUT_TYPE_P; // MSM_FRAME_ENC; |
| } |
| frame_buffer[cnt].frame = &frames[cnt]; |
| frame_buffer[cnt].buffer = bhandle; |
| frame_buffer[cnt].size = handle->size; |
| frame_buffer[cnt].lockState = BUFFER_LOCKED; |
| active = (cnt < ACTIVE_PREVIEW_BUFFERS); |
| |
| ALOGI("Registering buffer %d with fd :%d with kernel",cnt,handle->fd); |
| register_buf(mBufferSize, |
| mBufferSize, CbCrOffset, 0, |
| handle->fd, |
| 0, |
| (uint8_t *)frames[cnt].buffer/*(uint8_t *)mThumbnailMapped*/, |
| MSM_PMEM_PREVIEW, |
| active,true,all_chnls); |
| ALOGI("Came back from register call to kernel"); |
| } else |
| ALOGE("%s: setPreviewWindow: Could not get buffer handle", __FUNCTION__); |
| } else { |
| ALOGE("%s: lockBuffer failed for preview buffer. Error = %d", |
| __FUNCTION__, retVal); |
| return retVal; |
| } |
| } |
| |
| |
| // Dequeue Thumbnail/Postview Buffers here , Consider ZSL/Multishot cases |
| for (cnt = 0; cnt < (mZslEnable? (MAX_SNAPSHOT_BUFFERS-2) : numCapture); cnt++) { |
| |
| retVal = mPreviewWindow->dequeue_buffer(mPreviewWindow, |
| &mThumbnailBuffer[cnt], &(stride)); |
| private_handle_t* handle = (private_handle_t *)(*mThumbnailBuffer[cnt]); |
| ALOGI(" : dequeing thumbnail buffer fd %d", handle->fd); |
| if(retVal != NO_ERROR) { |
| ALOGE("%s: dequeueBuffer failed for postview buffer. Error = %d ", |
| __FUNCTION__, retVal); |
| return retVal; |
| } |
| } |
| |
| // Cancel minUndequeuedBufs. |
| for (cnt = kPreviewBufferCount; cnt < mTotalPreviewBufferCount; cnt++) { |
| if (GENLOCK_FAILURE == genlock_unlock_buffer((native_handle_t*)(*(frame_buffer[cnt].buffer)))) { |
| ALOGE("%s: genlock_unlock_buffer failed", __FUNCTION__); |
| return -EINVAL; |
| } |
| frame_buffer[cnt].lockState = BUFFER_UNLOCKED; |
| status_t retVal = mPreviewWindow->cancel_buffer(mPreviewWindow, |
| frame_buffer[cnt].buffer); |
| ALOGI(" Cancelling preview buffers %d ",frame_buffer[cnt].frame->fd); |
| } |
| } else { |
| ALOGE("%s: Could not get Buffer from Surface", __FUNCTION__); |
| return UNKNOWN_ERROR; |
| } |
| mPreviewBusyQueue.init(); |
| LINK_camframe_release_all_frames(CAM_PREVIEW_FRAME); |
| for(int i=ACTIVE_PREVIEW_BUFFERS ;i < kPreviewBufferCount; i++) |
| LINK_camframe_add_frame(CAM_PREVIEW_FRAME,&frames[i]); |
| |
| mBuffersInitialized = true; |
| |
| //Starting preview now as the preview buffers are allocated |
| // if(!mPreviewInitialized && !mCameraRunning) { // TODO just for testing |
| ALOGI("setPreviewWindow: Starting preview after buffer allocation"); |
| startPreviewInternal(); |
| // } |
| ALOGV(" %s : X ",__FUNCTION__); |
| return NO_ERROR; |
| } |
| void QualcommCameraHardware::release() |
| { |
| ALOGV("release E"); |
| Mutex::Autolock l(&mLock); |
| #if 0 |
| { |
| Mutex::Autolock checkLock(&singleton_lock); |
| if(singleton_releasing){ |
| ALOGE("ERROR: multiple release!"); |
| return; |
| } |
| } |
| #endif |
| ALOGI("release: mCameraRunning = %d", mCameraRunning); |
| if (mCameraRunning) { |
| if(mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME)) { |
| mRecordFrameLock.lock(); |
| mReleasedRecordingFrame = true; |
| mRecordWait.signal(); |
| mRecordFrameLock.unlock(); |
| } |
| stopPreviewInternal(); |
| ALOGI("release: stopPreviewInternal done."); |
| } |
| LINK_jpeg_encoder_join(); |
| mm_camera_ops_type_t current_ops_type = (mSnapshotFormat |
| == PICTURE_FORMAT_JPEG) ? CAMERA_OPS_CAPTURE_AND_ENCODE |
| : CAMERA_OPS_RAW_CAPTURE; |
| mCamOps.mm_camera_deinit(current_ops_type, NULL, NULL); |
| |
| //Signal the snapshot thread |
| mJpegThreadWaitLock.lock(); |
| mJpegThreadRunning = false; |
| mJpegThreadWait.signal(); |
| mJpegThreadWaitLock.unlock(); |
| |
| // Wait for snapshot thread to complete before clearing the |
| // resources. |
| mSnapshotThreadWaitLock.lock(); |
| while (mSnapshotThreadRunning) { |
| ALOGV("release: waiting for old snapshot thread to complete."); |
| mSnapshotThreadWait.wait(mSnapshotThreadWaitLock); |
| ALOGV("release: old snapshot thread completed."); |
| } |
| mSnapshotThreadWaitLock.unlock(); |
| |
| { |
| Mutex::Autolock l (&mRawPictureHeapLock); |
| deinitRaw(); |
| } |
| |
| deinitRawSnapshot(); |
| ALOGI("release: clearing resources done."); |
| if(mCurrentTarget == TARGET_MSM8660) { |
| ALOGV("release : Clearing the mThumbnailHeap and mDisplayHeap"); |
| mLastPreviewFrameHeap.clear(); |
| mLastPreviewFrameHeap = NULL; |
| mThumbnailHeap.clear(); |
| mThumbnailHeap = NULL; |
| mPostviewHeap.clear(); |
| mPostviewHeap = NULL; |
| mDisplayHeap.clear(); |
| mDisplayHeap = NULL; |
| } |
| LINK_mm_camera_deinit(); |
| if(fb_fd >= 0) { |
| close(fb_fd); |
| fb_fd = -1; |
| } |
| singleton_lock.lock(); |
| singleton_releasing = true; |
| singleton_releasing_start_time = systemTime(); |
| singleton_lock.unlock(); |
| |
| ALOGI("release X: mCameraRunning = %d, mFrameThreadRunning = %d", mCameraRunning, mFrameThreadRunning); |
| ALOGI("mVideoThreadRunning = %d, mSnapshotThreadRunning = %d, mJpegThreadRunning = %d", mVideoThreadRunning, mSnapshotThreadRunning, mJpegThreadRunning); |
| ALOGI("camframe_timeout_flag = %d, mAutoFocusThreadRunning = %d", camframe_timeout_flag, mAutoFocusThreadRunning); |
| mFrameThreadWaitLock.lock(); |
| while (mFrameThreadRunning) { |
| ALOGV("release: waiting for old frame thread to complete."); |
| mFrameThreadWait.wait(mFrameThreadWaitLock); |
| ALOGV("release: old frame thread completed."); |
| } |
| mFrameThreadWaitLock.unlock(); |
| |
| } |
| |
| QualcommCameraHardware::~QualcommCameraHardware() |
| { |
| ALOGI("~QualcommCameraHardware E"); |
| |
| //singleton_lock.lock(); |
| if( mCurrentTarget == TARGET_MSM7630 || mCurrentTarget == TARGET_QSD8250 || mCurrentTarget == TARGET_MSM8660 ) { |
| delete [] recordframes; |
| recordframes = NULL; |
| delete [] record_buffers_tracking_flag; |
| } |
| mMMCameraDLRef.clear(); |
| //singleton.clear(); |
| //singleton_releasing = false; |
| //singleton_releasing_start_time = 0; |
| //singleton_wait.signal(); |
| //singleton_lock.unlock(); |
| ALOGI("~QualcommCameraHardware X"); |
| } |
| #if 0 |
| IMemoryHeap* QualcommCameraHardware::getRawHeap() const |
| { |
| #if 0 |
| ALOGV("getRawHeap"); |
| return mDisplayHeap != NULL ? mDisplayHeap->mHeap : NULL; |
| #endif |
| } |
| |
| IMemoryHeap* QualcommCameraHardware::getPreviewHeap() const |
| { |
| #if 0 |
| ALOGV("getPreviewHeap"); |
| return mPreviewHeap[0] != NULL ? mPreviewHeap[0]->mHeap : NULL; |
| if(mIs3DModeOn != true) { |
| if(( mPreviewFormat == CAMERA_YUV_420_YV12 ) && |
| ( mCurrentTarget == TARGET_MSM7627A || mCurrentTarget == TARGET_MSM7627 ) && |
| previewWidth%32 != 0 ) |
| return mYV12Heap->mHeap; |
| |
| return mPreviewHeap != NULL ? mPreviewHeap->mHeap : NULL; |
| } else |
| return mRecordHeap != NULL ? mRecordHeap->mHeap : NULL; |
| |
| #endif |
| } |
| #endif |
| #if 0 |
| status_t QualcommCameraHardware::startInitialPreview() { |
| ALOGV(" %s : E", __FUNCTION__); |
| const char * pmem_region = "/dev/pmem_smipool"; |
| int initialPreviewWidth = INITIAL_PREVIEW_WIDTH; |
| int initialPreviewHeight = INITIAL_PREVIEW_HEIGHT; |
| int previewFrameSize = initialPreviewWidth * initialPreviewHeight * 3/2; |
| int CbCrOffset = PAD_TO_WORD(initialPreviewWidth * initialPreviewHeight); |
| mFrameThreadWaitLock.lock(); |
| while (mFrameThreadRunning) { |
| ALOGV("%s: waiting for old frame thread to complete.", __FUNCTION__); |
| mFrameThreadWait.wait(mFrameThreadWaitLock); |
| ALOGV("%s: old frame thread completed.",__FUNCTION__); |
| } |
| mFrameThreadWaitLock.unlock(); |
| |
| mInitialPreviewHeap = new PmemPool(pmem_region, |
| MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING, |
| MSM_PMEM_PREVIEW, |
| previewFrameSize, |
| kPreviewBufferCount, |
| previewFrameSize, |
| CbCrOffset, |
| 0, |
| "initial preview"); |
| |
| mDimension.display_width = initialPreviewWidth; |
| mDimension.display_height = initialPreviewHeight; |
| mDimension.video_width = initialPreviewWidth; |
| mDimension.video_height = initialPreviewHeight; |
| mDimension.display_luma_width = initialPreviewWidth; |
| mDimension.display_luma_height = initialPreviewHeight; |
| mDimension.display_chroma_width = initialPreviewWidth; |
| mDimension.display_chroma_height = initialPreviewHeight; |
| mDimension.orig_video_width = initialPreviewWidth; |
| mDimension.orig_video_height = initialPreviewHeight; |
| ALOGV("mDimension.prev_format = %d", mDimension.prev_format); |
| ALOGV("mDimension.display_luma_width = %d", mDimension.display_luma_width); |
| ALOGV("mDimension.display_luma_height = %d", mDimension.display_luma_height); |
| ALOGV("mDimension.display_chroma_width = %d", mDimension.display_chroma_width); |
| ALOGV("mDimension.display_chroma_height = %d", mDimension.display_chroma_height); |
| |
| native_set_parms(CAMERA_PARM_DIMENSION, |
| sizeof(cam_ctrl_dimension_t), &mDimension); |
| ALOGV(" %s : mDimension.video_width = %d mDimension.video_height = %d", __FUNCTION__, |
| mDimension.video_width, mDimension.video_height); |
| mRecordFrameSize = previewFrameSize; |
| ALOGV("mRecordFrameSize = %d", mRecordFrameSize); |
| |
| mRecordHeap = new PmemPool(pmem_region, |
| MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING, |
| MSM_PMEM_VIDEO, |
| previewFrameSize, |
| kRecordBufferCount, |
| previewFrameSize, |
| CbCrOffset, |
| 0, |
| "initial record"); |
| |
| if (!mRecordHeap->initialized()) { |
| mRecordHeap.clear(); |
| ALOGE("%s X: could not initialize record heap.", __FUNCTION__); |
| return false; |
| } |
| { |
| Mutex::Autolock cameraRunningLock(&mCameraRunningLock); |
| mCameraRunning = native_start_ops(CAMERA_OPS_STREAMING_VIDEO, NULL); |
| } |
| |
| ALOGV(" %s : X", __FUNCTION__); |
| return NO_ERROR; |
| } |
| #endif |
| status_t QualcommCameraHardware::startPreviewInternal() |
| { |
| ALOGV("in startPreviewInternal : E"); |
| if (!mBuffersInitialized) { |
| ALOGE("startPreviewInternal: Buffers not allocated. Cannot start preview"); |
| return NO_ERROR; |
| } |
| mPreviewStopping = false; |
| #if 0 |
| if(mZslEnable && !mZslPanorama){ |
| ALOGE("start zsl Preview called"); |
| mCamOps.mm_camera_start(CAMERA_OPS_ZSL_STREAMING_CB,NULL, NULL); |
| if (mCurrentTarget == TARGET_MSM8660) { |
| if(mLastPreviewFrameHeap != NULL) |
| mLastPreviewFrameHeap.clear(); |
| } |
| } |
| #endif |
| if(mCameraRunning) { |
| ALOGV("startPreview X: preview already running."); |
| return NO_ERROR; |
| } |
| if(mZslEnable){ |
| //call init |
| ALOGI("ZSL Enable called"); |
| uint8_t is_zsl = 1; |
| mm_camera_status_t status; |
| if(MM_CAMERA_SUCCESS != mCfgControl.mm_camera_set_parm(CAMERA_PARM_ZSL_ENABLE, |
| (void *)&is_zsl)){ |
| ALOGE("ZSL Enable failed"); |
| return UNKNOWN_ERROR; |
| } |
| } |
| |
| if (!mPreviewInitialized) { |
| mLastQueuedFrame = NULL; |
| mPreviewInitialized = initPreview(); |
| if (!mPreviewInitialized) { |
| ALOGE("startPreview X initPreview failed. Not starting preview."); |
| mPreviewBusyQueue.deinit(); |
| return UNKNOWN_ERROR; |
| } |
| } |
| |
| /* For 3D mode, start the video output, as this need to be |
| * used for display also. |
| */ |
| if(mIs3DModeOn) { |
| startRecordingInternal(); |
| if(!mVideoThreadRunning) { |
| ALOGE("startPreview X startRecording failed. Not starting preview."); |
| return UNKNOWN_ERROR; |
| } |
| } |
| |
| { |
| Mutex::Autolock cameraRunningLock(&mCameraRunningLock); |
| if(( mCurrentTarget != TARGET_MSM7630 ) && |
| (mCurrentTarget != TARGET_QSD8250) && (mCurrentTarget != TARGET_MSM8660)) |
| mCameraRunning = native_start_ops(CAMERA_OPS_STREAMING_PREVIEW, NULL); |
| else { |
| if(!mZslEnable){ |
| ALOGI("Calling CAMERA_OPS_STREAMING_VIDEO"); |
| mCameraRunning = native_start_ops(CAMERA_OPS_STREAMING_VIDEO, NULL); |
| ALOGI(": Calling CAMERA_OPS_STREAMING_VIDEO %d", mCameraRunning); |
| }else { |
| initZslParameter(); |
| mCameraRunning = false; |
| if (MM_CAMERA_SUCCESS == mCamOps.mm_camera_init(CAMERA_OPS_STREAMING_ZSL, |
| (void *)&mZslParms, NULL)) { |
| //register buffers for ZSL |
| bool status = initZslBuffers(true); |
| if(status != true) { |
| ALOGE("Failed to allocate ZSL buffers"); |
| return false; |
| } |
| if(MM_CAMERA_SUCCESS == mCamOps.mm_camera_start(CAMERA_OPS_STREAMING_ZSL,NULL, NULL)){ |
| mCameraRunning = true; |
| } |
| } |
| if(mCameraRunning == false) |
| ALOGE("Starting ZSL CAMERA_OPS_STREAMING_ZSL failed!!!"); |
| } |
| } |
| } |
| |
| if(!mCameraRunning) { |
| deinitPreview(); |
| if(mZslEnable){ |
| //deinit |
| ALOGI("ZSL DISABLE called"); |
| uint8_t is_zsl = 0; |
| mm_camera_status_t status; |
| if( MM_CAMERA_SUCCESS != mCfgControl.mm_camera_set_parm(CAMERA_PARM_ZSL_ENABLE, |
| (void *)&is_zsl)){ |
| ALOGE("ZSL_Disable failed!!"); |
| return UNKNOWN_ERROR; |
| } |
| } |
| /* Flush the Busy Q */ |
| cam_frame_flush_video(); |
| /* Need to flush the free Qs as these are initalized in initPreview.*/ |
| LINK_camframe_release_all_frames(CAM_VIDEO_FRAME); |
| LINK_camframe_release_all_frames(CAM_PREVIEW_FRAME); |
| mPreviewInitialized = false; |
| mOverlayLock.lock(); |
| //mOverlay = NULL; |
| mOverlayLock.unlock(); |
| ALOGE("startPreview X: native_start_ops: CAMERA_OPS_STREAMING_PREVIEW ioctl failed!"); |
| return UNKNOWN_ERROR; |
| } |
| |
| //Reset the Gps Information |
| exif_table_numEntries = 0; |
| previewWidthToNativeZoom = previewWidth; |
| previewHeightToNativeZoom = previewHeight; |
| |
| ALOGV("startPreviewInternal X"); |
| return NO_ERROR; |
| } |
| status_t QualcommCameraHardware::startInitialPreview() { |
| mCameraRunning = DUMMY_CAMERA_STARTED; |
| return NO_ERROR; |
| } |
| status_t QualcommCameraHardware::startPreview() |
| { |
| status_t result; |
| ALOGV("startPreview E"); |
| Mutex::Autolock l(&mLock); |
| if( mPreviewWindow == NULL) { |
| /* startPreview has been called before setting the preview |
| * window. Start the camera with initial buffers because the |
| * CameraService expects the preview to be enabled while |
| * setting a valid preview window */ |
| ALOGV(" %s : Starting preview with initial buffers ", __FUNCTION__); |
| result = startInitialPreview(); |
| } else { |
| /* startPreview has been issued after a valid preview window |
| * is set. Get the preview buffers from gralloc and start |
| * preview normally */ |
| ALOGV(" %s : Starting normal preview ", __FUNCTION__); |
| result = getBuffersAndStartPreview(); |
| } |
| ALOGV("startPreview X"); |
| return result; |
| } |
| |
| void QualcommCameraHardware::stopInitialPreview() { |
| mCameraRunning = 0;//!native_stop_ops(CAMERA_OPS_STREAMING_VIDEO, NULL); |
| #if 0 |
| ALOGV(" %s : E ", __FUNCTION__); |
| if (mCameraRunning) { |
| ALOGV(" %s : Camera was running. Stopping ", __FUNCTION__); |
| { |
| Mutex::Autolock l(&mCamframeTimeoutLock); |
| { |
| Mutex::Autolock cameraRunningLock(&mCameraRunningLock); |
| if(!camframe_timeout_flag) { |
| mCameraRunning = !native_stop_ops(CAMERA_OPS_STREAMING_VIDEO, NULL); |
| } |
| } |
| } |
| mInitialPreviewHeap.clear(); |
| mRecordHeap.clear(); |
| } |
| ALOGV(" %s : X ", __FUNCTION__); |
| #endif |
| } |
| |
| void QualcommCameraHardware::stopPreviewInternal() |
| { |
| ALOGV("stopPreviewInternal E: %d", mCameraRunning); |
| mPreviewStopping = true; |
| if (mCameraRunning && mPreviewWindow!=NULL) { |
| /* For 3D mode, we need to exit the video thread.*/ |
| if(mIs3DModeOn) { |
| mRecordingState = 0; |
| mVideoThreadWaitLock.lock(); |
| ALOGI("%s: 3D mode, exit video thread", __FUNCTION__); |
| mVideoThreadExit = 1; |
| mVideoThreadWaitLock.unlock(); |
| |
| pthread_mutex_lock(&(g_busy_frame_queue.mut)); |
| pthread_cond_signal(&(g_busy_frame_queue.wait)); |
| pthread_mutex_unlock(&(g_busy_frame_queue.mut)); |
| } |
| |
| // Cancel auto focus. |
| { |
| if (mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS)) { |
| cancelAutoFocusInternal(); |
| } |
| } |
| |
| // make mSmoothzoomThreadExit true |
| mSmoothzoomThreadLock.lock(); |
| mSmoothzoomThreadExit = true; |
| mSmoothzoomThreadLock.unlock(); |
| // singal smooth zoom thread , so that it can exit gracefully |
| mSmoothzoomThreadWaitLock.lock(); |
| if(mSmoothzoomThreadRunning) |
| mSmoothzoomThreadWait.signal(); |
| |
| mSmoothzoomThreadWaitLock.unlock(); |
| |
| Mutex::Autolock l(&mCamframeTimeoutLock); |
| { |
| Mutex::Autolock cameraRunningLock(&mCameraRunningLock); |
| if(!camframe_timeout_flag) { |
| if (( mCurrentTarget != TARGET_MSM7630 ) && |
| (mCurrentTarget != TARGET_QSD8250) && (mCurrentTarget != TARGET_MSM8660)) |
| mCameraRunning = !native_stop_ops(CAMERA_OPS_STREAMING_PREVIEW, NULL); |
| else{ |
| if(!mZslEnable){ |
| ALOGI("%s ops_streaming mCameraRunning b= %d",__FUNCTION__, mCameraRunning); |
| mCameraRunning = !native_stop_ops(CAMERA_OPS_STREAMING_VIDEO, NULL); |
| ALOGI("%s ops_streaming mCameraRunning = %d",__FUNCTION__, mCameraRunning); |
| }else { |
| mCameraRunning = true; |
| if(MM_CAMERA_SUCCESS == mCamOps.mm_camera_stop(CAMERA_OPS_STREAMING_ZSL,NULL, NULL)){ |
| deinitZslBuffers(); |
| if (MM_CAMERA_SUCCESS == mCamOps.mm_camera_deinit(CAMERA_OPS_STREAMING_ZSL, |
| (void *)&mZslParms, NULL)) { |
| mCameraRunning = false; |
| } |
| } |
| if(mCameraRunning ==true) |
| ALOGE("Starting ZSL CAMERA_OPS_STREAMING_ZSL failed!!!"); |
| } |
| } |
| } else { |
| /* This means that the camframetimeout was issued. |
| * But we did not issue native_stop_preview(), so we |
| * need to update mCameraRunning to indicate that |
| * Camera is no longer running. */ |
| ALOGE("%s, : MAKE MCAMER_RUNNING FALSE!!!",__FUNCTION__); |
| mCameraRunning = 0; |
| } |
| } |
| } |
| /* in 3D mode, wait for the video thread before clearing resources.*/ |
| if(mIs3DModeOn) { |
| mVideoThreadWaitLock.lock(); |
| while (mVideoThreadRunning) { |
| ALOGI("%s: waiting for video thread to complete.", __FUNCTION__); |
| mVideoThreadWait.wait(mVideoThreadWaitLock); |
| ALOGI("%s : video thread completed.", __FUNCTION__); |
| } |
| mVideoThreadWaitLock.unlock(); |
| } |
| ALOGI("%s, J_mCameraRunning = %d", __FUNCTION__, mCameraRunning); |
| if (!mCameraRunning) { |
| ALOGI("%s, before calling deinitpre mPreviewInitialized = %d", __FUNCTION__, mPreviewInitialized); |
| if(mPreviewInitialized) { |
| ALOGI("before calling deinitpreview"); |
| deinitPreview(); |
| if( ( mCurrentTarget == TARGET_MSM7630 ) || |
| (mCurrentTarget == TARGET_QSD8250) || |
| (mCurrentTarget == TARGET_MSM8660)) { |
| mVideoThreadWaitLock.lock(); |
| ALOGV("in stopPreviewInternal: making mVideoThreadExit 1"); |
| mVideoThreadExit = 1; |
| mVideoThreadWaitLock.unlock(); |
| //720p : signal the video thread , and check in video thread |
| //if stop is called, if so exit video thread. |
| pthread_mutex_lock(&(g_busy_frame_queue.mut)); |
| pthread_cond_signal(&(g_busy_frame_queue.wait)); |
| pthread_mutex_unlock(&(g_busy_frame_queue.mut)); |
| |
| ALOGI(" flush video and release all frames"); |
| /* Flush the Busy Q */ |
| cam_frame_flush_video(); |
| /* Flush the Free Q */ |
| LINK_camframe_release_all_frames(CAM_VIDEO_FRAME); |
| } |
| mPreviewInitialized = false; |
| } |
| } |
| else ALOGI("stopPreviewInternal: Preview is stopped already"); |
| |
| ALOGV("stopPreviewInternal X: %d", mCameraRunning); |
| } |
| |
| void QualcommCameraHardware::stopPreview() |
| { |
| ALOGV("stopPreview: E"); |
| Mutex::Autolock l(&mLock); |
| { |
| if (mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME)) |
| return; |
| } |
| if( mSnapshotThreadRunning ) { |
| ALOGV("In stopPreview during snapshot"); |
| return; |
| } |
| if( mPreviewWindow != NULL ) { |
| private_handle_t *handle; |
| for (int cnt = 0; cnt < (mZslEnable? (MAX_SNAPSHOT_BUFFERS-2) : numCapture); cnt++) { |
| if(mPreviewWindow != NULL && mThumbnailBuffer[cnt] != NULL) { |
| handle = (private_handle_t *)(*mThumbnailBuffer[cnt]); |
| ALOGI("%s: Cancelling postview buffer %d ", __FUNCTION__, handle->fd); |
| ALOGI("stoppreview : display lock"); |
| mDisplayLock.lock(); |
| if (BUFFER_LOCKED == mThumbnailLockState[cnt]) { |
| if (GENLOCK_FAILURE == genlock_unlock_buffer(handle)) { |
| ALOGE("%s: genlock_unlock_buffer failed", __FUNCTION__); |
| mDisplayLock.unlock(); |
| continue; |
| } else { |
| mThumbnailLockState[cnt] = BUFFER_UNLOCKED; |
| } |
| } |
| status_t retVal = mPreviewWindow->cancel_buffer(mPreviewWindow, |
| mThumbnailBuffer[cnt]); |
| ALOGI("stopPreview : after cancelling thumbnail buffer"); |
| if(retVal != NO_ERROR) |
| ALOGE("%s: cancelBuffer failed for postview buffer %d", |
| __FUNCTION__, handle->fd); |
| // unregister , unmap and release as well |
| int mBufferSize = previewWidth * previewHeight * 3/2; |
| int mCbCrOffset = PAD_TO_WORD(previewWidth * previewHeight); |
| if(mThumbnailMapped[cnt] && (mSnapshotFormat == PICTURE_FORMAT_JPEG) |
| || mZslEnable) { |
| ALOGI("%s: Unregistering Thumbnail Buffer %d ", __FUNCTION__, handle->fd); |
| register_buf(mBufferSize, |
| mBufferSize, mCbCrOffset, 0, |
| handle->fd, |
| 0, |
| (uint8_t *)mThumbnailMapped[cnt], |
| MSM_PMEM_THUMBNAIL, |
| false, false); |
| if (munmap((void *)(mThumbnailMapped[cnt]),handle->size ) == -1) { |
| ALOGE("StopPreview : Error un-mmapping the thumbnail buffer %d", index); |
| } |
| mThumbnailMapped[cnt] = NULL; |
| } |
| mThumbnailBuffer[cnt] = NULL; |
| ALOGI("stoppreview : display unlock"); |
| mDisplayLock.unlock(); |
| } |
| } |
| } |
| stopPreviewInternal(); |
| ALOGV("stopPreview: X"); |
| } |
| |
| void QualcommCameraHardware::runAutoFocus() |
| { |
| bool status = true; |
| void *libhandle = NULL; |
| isp3a_af_mode_t afMode = AF_MODE_AUTO; |
| |
| mAutoFocusThreadLock.lock(); |
| // Skip autofocus if focus mode is infinity. |
| |
| const char * focusMode = mParameters.get(QCameraParameters::KEY_FOCUS_MODE); |
| if ((mParameters.get(QCameraParameters::KEY_FOCUS_MODE) == 0) |
| || (strcmp(focusMode, QCameraParameters::FOCUS_MODE_INFINITY) == 0) |
| || (strcmp(focusMode, QCameraParameters::FOCUS_MODE_CONTINUOUS_VIDEO) == 0)) { |
| goto done; |
| } |
| |
| if(!libmmcamera){ |
| ALOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror()); |
| mAutoFocusThreadRunning = false; |
| mAutoFocusThreadLock.unlock(); |
| return; |
| } |
| |
| afMode = (isp3a_af_mode_t)attr_lookup(focus_modes, |
| sizeof(focus_modes) / sizeof(str_map), |
| mParameters.get(QCameraParameters::KEY_FOCUS_MODE)); |
| |
| /* This will block until either AF completes or is cancelled. */ |
| ALOGV("af start (mode %d)", afMode); |
| status_t err; |
| err = mAfLock.tryLock(); |
| if(err == NO_ERROR) { |
| { |
| Mutex::Autolock cameraRunningLock(&mCameraRunningLock); |
| if(mCameraRunning){ |
| ALOGV("Start AF"); |
| status = native_start_ops(CAMERA_OPS_FOCUS ,(void *)&afMode); |
| }else{ |
| ALOGV("As Camera preview is not running, AF not issued"); |
| status = false; |
| } |
| } |
| mAfLock.unlock(); |
| } |
| else{ |
| //AF Cancel would have acquired the lock, |
| //so, no need to perform any AF |
| ALOGV("As Cancel auto focus is in progress, auto focus request " |
| "is ignored"); |
| status = FALSE; |
| } |
| { |
| Mutex::Autolock pl(&mParametersLock); |
| if(mHasAutoFocusSupport && (updateFocusDistances(focusMode) != NO_ERROR)) { |
| ALOGE("%s: updateFocusDistances failed for %s", __FUNCTION__, focusMode); |
| } |
| } |
| |
| ALOGV("af done: %d", (int)status); |
| |
| done: |
| mAutoFocusThreadRunning = false; |
| mAutoFocusThreadLock.unlock(); |
| |
| mCallbackLock.lock(); |
| bool autoFocusEnabled = mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS); |
| camera_notify_callback cb = mNotifyCallback; |
| void *data = mCallbackCookie; |
| mCallbackLock.unlock(); |
| if (autoFocusEnabled) |
| cb(CAMERA_MSG_FOCUS, status, 0, data); |
| |
| } |
| |
| status_t QualcommCameraHardware::cancelAutoFocusInternal() |
| { |
| ALOGV("cancelAutoFocusInternal E"); |
| bool afRunning = true; |
| |
| if(!mHasAutoFocusSupport){ |
| ALOGV("cancelAutoFocusInternal X"); |
| return NO_ERROR; |
| } |
| |
| status_t rc = NO_ERROR; |
| status_t err; |
| |
| do { |
| err = mAfLock.tryLock(); |
| if(err == NO_ERROR) { |
| //Got Lock, means either AF hasn't started or |
| // AF is done. So no need to cancel it, just change the state |
| ALOGV("Auto Focus is not in progress, Cancel Auto Focus is ignored"); |
| mAfLock.unlock(); |
| |
| mAutoFocusThreadLock.lock(); |
| afRunning = mAutoFocusThreadRunning; |
| mAutoFocusThreadLock.unlock(); |
| if(afRunning) { |
| usleep( 5000 ); |
| } |
| } |
| } while ( err == NO_ERROR && afRunning ); |
| if(afRunning) { |
| //AF is in Progess, So cancel it |
| ALOGV("Lock busy...cancel AF"); |
| rc = native_stop_ops(CAMERA_OPS_FOCUS, NULL) ? |
| NO_ERROR : UNKNOWN_ERROR; |
| |
| /*now just wait for auto focus thread to be finished*/ |
| mAutoFocusThreadLock.lock(); |
| mAutoFocusThreadLock.unlock(); |
| } |
| ALOGV("cancelAutoFocusInternal X: %d", rc); |
| return rc; |
| } |
| |
| void *auto_focus_thread(void *user) |
| { |
| ALOGV("auto_focus_thread E"); |
| CAMERA_HAL_UNUSED(user); |
| QualcommCameraHardware *obj = QualcommCameraHardware::getInstance(); |
| if (obj != 0) { |
| obj->runAutoFocus(); |
| } |
| else ALOGW("not starting autofocus: the object went away!"); |
| ALOGV("auto_focus_thread X"); |
| return NULL; |
| } |
| |
| status_t QualcommCameraHardware::autoFocus() |
| { |
| ALOGV("autoFocus E"); |
| Mutex::Autolock l(&mLock); |
| |
| if(!mHasAutoFocusSupport){ |
| /* |
| * If autofocus is not supported HAL defaults |
| * focus mode to infinity and supported mode to |
| * infinity also. In this mode and fixed mode app |
| * should not call auto focus. |
| */ |
| ALOGI("Auto Focus not supported"); |
| ALOGV("autoFocus X"); |
| return INVALID_OPERATION; |
| } |
| { |
| mAutoFocusThreadLock.lock(); |
| if (!mAutoFocusThreadRunning) { |
| |
| // Create a detached thread here so that we don't have to wait |
| // for it when we cancel AF. |
| pthread_t thr; |
| pthread_attr_t attr; |
| pthread_attr_init(&attr); |
| pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); |
| mAutoFocusThreadRunning = |
| !pthread_create(&thr, &attr, |
| auto_focus_thread, NULL); |
| if (!mAutoFocusThreadRunning) { |
| ALOGE("failed to start autofocus thread"); |
| mAutoFocusThreadLock.unlock(); |
| return UNKNOWN_ERROR; |
| } |
| } |
| mAutoFocusThreadLock.unlock(); |
| } |
| |
| ALOGV("autoFocus X"); |
| return NO_ERROR; |
| } |
| |
| status_t QualcommCameraHardware::cancelAutoFocus() |
| { |
| ALOGV("cancelAutoFocus E"); |
| Mutex::Autolock l(&mLock); |
| |
| int rc = NO_ERROR; |
| if (mCameraRunning && mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS)) { |
| rc = cancelAutoFocusInternal(); |
| } |
| |
| ALOGV("cancelAutoFocus X"); |
| return rc; |
| } |
| |
| void QualcommCameraHardware::runSnapshotThread(void *data) |
| { |
| bool ret = true; |
| CAMERA_HAL_UNUSED(data); |
| ALOGI("runSnapshotThread E"); |
| |
| if(!libmmcamera){ |
| ALOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror()); |
| } |
| mSnapshotCancelLock.lock(); |
| if(mSnapshotCancel == true) { |
| mSnapshotCancel = false; |
| mSnapshotCancelLock.unlock(); |
| ALOGI("%s: cancelpicture has been called..so abort taking snapshot", __FUNCTION__); |
| deinitRaw(); |
| mInSnapshotModeWaitLock.lock(); |
| mInSnapshotMode = false; |
| mInSnapshotModeWait.signal(); |
| mInSnapshotModeWaitLock.unlock(); |
| mSnapshotThreadWaitLock.lock(); |
| mSnapshotThreadRunning = false; |
| mSnapshotThreadWait.signal(); |
| mSnapshotThreadWaitLock.unlock(); |
| return; |
| } |
| mSnapshotCancelLock.unlock(); |
| |
| mJpegThreadWaitLock.lock(); |
| mJpegThreadRunning = true; |
| mJpegThreadWait.signal(); |
| mJpegThreadWaitLock.unlock(); |
| mm_camera_ops_type_t current_ops_type = (mSnapshotFormat == PICTURE_FORMAT_JPEG) ? |
| CAMERA_OPS_CAPTURE_AND_ENCODE : |
| CAMERA_OPS_RAW_CAPTURE; |
| if(strTexturesOn == true) { |
| current_ops_type = CAMERA_OPS_CAPTURE; |
| mCamOps.mm_camera_start(current_ops_type,(void *)&mImageCaptureParms, |
| NULL); |
| } else if(mSnapshotFormat == PICTURE_FORMAT_JPEG){ |
| if(!mZslEnable || mZslFlashEnable){ |
| mCamOps.mm_camera_start(current_ops_type,(void *)&mImageCaptureParms, |
| (void *)&mImageEncodeParms); |
| }else{ |
| notifyShutter(TRUE); |
| initZslParameter(); |
| ALOGI("snapshot mZslCapture.thumbnail %d %d %d",mZslCaptureParms.thumbnail_width, |
| mZslCaptureParms.thumbnail_height,mZslCaptureParms.num_captures); |
| mCamOps.mm_camera_start(current_ops_type,(void *)&mZslCaptureParms, |
| (void *)&mImageEncodeParms); |
| } |
| mJpegThreadWaitLock.lock(); |
| while (mJpegThreadRunning) { |
| ALOGV("%s: waiting for jpeg callback.", __FUNCTION__); |
| mJpegThreadWait.wait(mJpegThreadWaitLock); |
| ALOGV("%s: jpeg callback received.", __FUNCTION__); |
| } |
| mJpegThreadWaitLock.unlock(); |
| |
| //cleanup |
| if(!mZslEnable || mZslFlashEnable) |
| deinitRaw(); |
| }else if(mSnapshotFormat == PICTURE_FORMAT_RAW){ |
| notifyShutter(TRUE); |
| mCamOps.mm_camera_start(current_ops_type,(void *)&mRawCaptureParms, |
| NULL); |
| // Waiting for callback to come |
| ALOGV("runSnapshotThread : waiting for callback to come"); |
| mJpegThreadWaitLock.lock(); |
| while (mJpegThreadRunning) { |
| ALOGV("%s: waiting for jpeg callback.", __FUNCTION__); |
| mJpegThreadWait.wait(mJpegThreadWaitLock); |
| ALOGV("%s: jpeg callback received.", __FUNCTION__); |
| } |
| mJpegThreadWaitLock.unlock(); |
| ALOGV("runSnapshotThread : calling deinitRawSnapshot"); |
| deinitRawSnapshot(); |
| |
| } |
| |
| if(!mZslEnable || mZslFlashEnable) |
| mCamOps.mm_camera_deinit(current_ops_type, NULL, NULL); |
| mZslFlashEnable = false; |
| mSnapshotThreadWaitLock.lock(); |
| mSnapshotThreadRunning = false; |
| mSnapshotThreadWait.signal(); |
| mSnapshotThreadWaitLock.unlock(); |
| ALOGV("runSnapshotThread X"); |
| } |
| |
| void *snapshot_thread(void *user) |
| { |
| ALOGD("snapshot_thread E"); |
| CAMERA_HAL_UNUSED(user); |
| QualcommCameraHardware *obj = QualcommCameraHardware::getInstance(); |
| if (obj != 0) { |
| obj->runSnapshotThread(user); |
| } |
| else ALOGW("not starting snapshot thread: the object went away!"); |
| ALOGD("snapshot_thread X"); |
| return NULL; |
| } |
| |
| status_t QualcommCameraHardware::takePicture() |
| { |
| ALOGE("takePicture(%d)", mMsgEnabled); |
| Mutex::Autolock l(&mLock); |
| if(mRecordingState ) { |
| return takeLiveSnapshotInternal( ); |
| } |
| |
| if(strTexturesOn == true){ |
| mEncodePendingWaitLock.lock(); |
| while(mEncodePending) { |
| ALOGI("takePicture: Frame given to application, waiting for encode call"); |
| mEncodePendingWait.wait(mEncodePendingWaitLock); |
| ALOGI("takePicture: Encode of the application data is done"); |
| } |
| mEncodePendingWaitLock.unlock(); |
| } |
| |
| // Wait for old snapshot thread to complete. |
| mSnapshotThreadWaitLock.lock(); |
| while (mSnapshotThreadRunning) { |
| ALOGV("takePicture: waiting for old snapshot thread to complete."); |
| mSnapshotThreadWait.wait(mSnapshotThreadWaitLock); |
| ALOGV("takePicture: old snapshot thread completed."); |
| } |
| // if flash is enabled then run snapshot as normal mode and not zsl mode. |
| // App should expect only 1 callback as multi snapshot in normal mode is not supported |
| mZslFlashEnable = false; |
| if(mZslEnable){ |
| int is_flash_needed = 0; |
| mm_camera_status_t status; |
| status = mCfgControl.mm_camera_get_parm(CAMERA_PARM_QUERY_FALSH4SNAP, |
| (void *)&is_flash_needed); |
| if(is_flash_needed) { |
| mZslFlashEnable = true; |
| } |
| } |
| //Adding ExifTag for Flash |
| const char *flash_str = mParameters.get(QCameraParameters::KEY_FLASH_MODE); |
| if(flash_str){ |
| int is_flash_fired = 0; |
| if(mCfgControl.mm_camera_get_parm(CAMERA_PARM_QUERY_FALSH4SNAP, |
| (void *)&is_flash_fired) != MM_CAMERA_SUCCESS){ |
| flashMode = FLASH_SNAP ; //for No Flash support,bit 5 will be 1 |
| } else { |
| if(!strcmp(flash_str,"on")) |
| flashMode = 1; |
| |
| if(!strcmp(flash_str,"off")) |
| flashMode = 0; |
| |
| if(!strcmp(flash_str,"auto")){ |
| //for AUTO bits 3 and 4 will be 1 |
| //for flash fired bit 0 will be 1, else 0 |
| flashMode = FLASH_AUTO; |
| if(is_flash_fired) |
| flashMode = (is_flash_fired>>1) | flashMode ; |
| } |
| } |
| addExifTag(EXIFTAGID_FLASH,EXIF_SHORT,1,1,(void *)&flashMode); |
| } |
| |
| if(mParameters.getPictureFormat() != 0 && |
| !strcmp(mParameters.getPictureFormat(), |
| QCameraParameters::PIXEL_FORMAT_RAW)){ |
| mSnapshotFormat = PICTURE_FORMAT_RAW; |
| { |
| // HACK: Raw ZSL capture is not supported yet |
| mZslFlashEnable = true; |
| } |
| } |
| else |
| mSnapshotFormat = PICTURE_FORMAT_JPEG; |
| |
| if(!mZslEnable || mZslFlashEnable){ |
| if((mSnapshotFormat == PICTURE_FORMAT_JPEG)){ |
| if(!native_start_ops(CAMERA_OPS_PREPARE_SNAPSHOT, NULL)) { |
| mSnapshotThreadWaitLock.unlock(); |
| ALOGE("PREPARE SNAPSHOT: CAMERA_OPS_PREPARE_SNAPSHOT ioctl Failed"); |
| return UNKNOWN_ERROR; |
| } |
| } |
| } |
| else { |
| int rotation = mParameters.getInt("rotation"); |
| native_set_parms(CAMERA_PARM_JPEG_ROTATION, sizeof(int), &rotation); |
| } |
| #if 0 // TODO for ICS |
| if(mCurrentTarget == TARGET_MSM8660) { |
| /* Store the last frame queued for preview. This |
| * shall be used as postview */ |
| if (!(storePreviewFrameForPostview())) |
| return UNKNOWN_ERROR; |
| } |
| #endif |
| if(!mZslEnable || mZslFlashEnable) |
| stopPreviewInternal(); |
| #if 0 |
| else if(mZslEnable && !mZslPanorama) { |
| /* Dont stop preview if ZSL Panorama is enabled for |
| * Continuous viewfinder support*/ |
| ALOGE("Calling stop preview"); |
| mCamOps.mm_camera_stop(CAMERA_OPS_ZSL_STREAMING_CB,NULL, NULL); |
| } |
| #endif |
| |
| |
| mFrameThreadWaitLock.unlock(); |
| |
| mm_camera_ops_type_t current_ops_type = (mSnapshotFormat == PICTURE_FORMAT_JPEG) ? |
| CAMERA_OPS_CAPTURE_AND_ENCODE : |
| CAMERA_OPS_RAW_CAPTURE; |
| if(strTexturesOn == true) |
| current_ops_type = CAMERA_OPS_CAPTURE; |
| |
| if( !mZslEnable || mZslFlashEnable) |
| mCamOps.mm_camera_init(current_ops_type, NULL, NULL); |
| |
| if(mSnapshotFormat == PICTURE_FORMAT_JPEG){ |
| if(!mZslEnable || mZslFlashEnable) { |
| if (!initRaw(mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE))) { |
| ALOGE("initRaw failed. Not taking picture."); |
| mSnapshotThreadWaitLock.unlock(); |
| return UNKNOWN_ERROR; |
| } |
| } |
| } else if(mSnapshotFormat == PICTURE_FORMAT_RAW ){ |
| if(!initRawSnapshot()){ |
| ALOGE("initRawSnapshot failed. Not taking picture."); |
| mSnapshotThreadWaitLock.unlock(); |
| return UNKNOWN_ERROR; |
| } |
| } |
| |
| mShutterLock.lock(); |
| mShutterPending = true; |
| mShutterLock.unlock(); |
| |
| mSnapshotCancelLock.lock(); |
| mSnapshotCancel = false; |
| mSnapshotCancelLock.unlock(); |
| |
| numJpegReceived = 0; |
| pthread_attr_t attr; |
| pthread_attr_init(&attr); |
| pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); |
| mSnapshotThreadRunning = !pthread_create(&mSnapshotThread, |
| &attr, |
| snapshot_thread, |
| NULL); |
| mSnapshotThreadWaitLock.unlock(); |
| |
| mInSnapshotModeWaitLock.lock(); |
| mInSnapshotMode = true; |
| mInSnapshotModeWaitLock.unlock(); |
| |
| ALOGV("takePicture: X"); |
| return mSnapshotThreadRunning ? NO_ERROR : UNKNOWN_ERROR; |
| } |
| |
| void QualcommCameraHardware::set_liveshot_exifinfo() |
| { |
| |
| setGpsParameters(); |
| //set TimeStamp |
| const char *str = mParameters.get(QCameraParameters::KEY_EXIF_DATETIME); |
| if(str != NULL) { |
| strncpy(dateTime, str, 19); |
| dateTime[19] = '\0'; |
| addExifTag(EXIFTAGID_EXIF_DATE_TIME_ORIGINAL, EXIF_ASCII, |
| 20, 1, (void *)dateTime); |
| } |
| } |
| |
| |
| status_t QualcommCameraHardware::takeLiveSnapshotInternal() |
| { |
| ALOGV("takeLiveSnapshotInternal : E"); |
| if(liveshot_state == LIVESHOT_IN_PROGRESS || !mRecordingState) { |
| return NO_ERROR; |
| } |
| |
| if( (mCurrentTarget != TARGET_MSM7630) && (mCurrentTarget != TARGET_MSM8660) && (mCurrentTarget != TARGET_MSM7627A)) { |
| ALOGI("LiveSnapshot not supported on this target"); |
| liveshot_state = LIVESHOT_STOPPED; |
| return NO_ERROR; |
| } |
| |
| liveshot_state = LIVESHOT_IN_PROGRESS; |
| |
| if (!initLiveSnapshot(videoWidth, videoHeight)) { |
| ALOGE("takeLiveSnapshot: Jpeg Heap Memory allocation failed. Not taking Live Snapshot."); |
| liveshot_state = LIVESHOT_STOPPED; |
| return UNKNOWN_ERROR; |
| } |
| uint32_t maxjpegsize = videoWidth * videoHeight *1.5; |
| set_liveshot_exifinfo(); |
| if(!LINK_set_liveshot_params(videoWidth, videoHeight, |
| exif_data, exif_table_numEntries, |
| (uint8_t *)mJpegLiveSnapMapped->data, maxjpegsize)) { |
| ALOGE("Link_set_liveshot_params failed."); |
| if (NULL != mJpegLiveSnapMapped) { |
| ALOGV("initLiveSnapshot: clearing old mJpegHeap."); |
| mJpegLiveSnapMapped->release(mJpegLiveSnapMapped); |
| mJpegLiveSnapMapped = NULL; |
| } |
| return NO_ERROR; |
| } |
| if((mCurrentTarget == TARGET_MSM7630) || (mCurrentTarget == TARGET_MSM8660)) { |
| if(!native_start_ops(CAMERA_OPS_LIVESHOT, NULL)) { |
| ALOGE("start_liveshot ioctl failed"); |
| liveshot_state = LIVESHOT_STOPPED; |
| if (NULL != mJpegLiveSnapMapped) { |
| ALOGV("initLiveSnapshot: clearing old mJpegHeap."); |
| mJpegLiveSnapMapped->release(mJpegLiveSnapMapped); |
| mJpegLiveSnapMapped = NULL; |
| } |
| return UNKNOWN_ERROR; |
| } |
| } |
| |
| ALOGV("takeLiveSnapshotInternal: X"); |
| return NO_ERROR; |
| } |
| |
| status_t QualcommCameraHardware::takeLiveSnapshot() |
| { |
| ALOGV("takeLiveSnapshot: E "); |
| Mutex::Autolock l(&mLock); |
| ALOGV("takeLiveSnapshot: X "); |
| return takeLiveSnapshotInternal( ); |
| } |
| |
| bool QualcommCameraHardware::initLiveSnapshot(int videowidth, int videoheight) |
| { |
| ALOGV("initLiveSnapshot E"); |
| |
| if (NULL != mJpegLiveSnapMapped) { |
| ALOGV("initLiveSnapshot: clearing old mJpegHeap."); |
| mJpegLiveSnapMapped->release(mJpegLiveSnapMapped); |
| mJpegLiveSnapMapped = NULL; |
| } |
| |
| mJpegMaxSize = videowidth * videoheight * 1.5; |
| ALOGV("initLiveSnapshot: initializing mJpegHeap."); |
| mJpegLiveSnapMapped = mGetMemory(-1, mJpegMaxSize,1,mCallbackCookie); |
| if(mJpegLiveSnapMapped == NULL) { |
| ALOGE("Failed to get camera memory for mJpegLibeSnapMapped" ); |
| return false; |
| } |
| ALOGV("initLiveSnapshot X"); |
| return true; |
| } |
| |
| |
| status_t QualcommCameraHardware::cancelPicture() |
| { |
| status_t rc; |
| ALOGV("cancelPicture: E"); |
| |
| mSnapshotCancelLock.lock(); |
| ALOGI("%s: setting mSnapshotCancel to true", __FUNCTION__); |
| mSnapshotCancel = true; |
| mSnapshotCancelLock.unlock(); |
| |
| if (mCurrentTarget == TARGET_MSM7627 || |
| (mCurrentTarget == TARGET_MSM7625A || |
| mCurrentTarget == TARGET_MSM7627A)) { |
| mSnapshotDone = TRUE; |
| mSnapshotThreadWaitLock.lock(); |
| while (mSnapshotThreadRunning) { |
| ALOGV("cancelPicture: waiting for snapshot thread to complete."); |
| mSnapshotThreadWait.wait(mSnapshotThreadWaitLock); |
| ALOGV("cancelPicture: snapshot thread completed."); |
| } |
| mSnapshotThreadWaitLock.unlock(); |
| } |
| rc = native_stop_ops(CAMERA_OPS_CAPTURE, NULL) ? NO_ERROR : UNKNOWN_ERROR; |
| mSnapshotDone = FALSE; |
| ALOGV("cancelPicture: X: %d", rc); |
| return rc; |
| } |
| |
| status_t QualcommCameraHardware::setParameters(const QCameraParameters& params) |
| { |
| ALOGV("setParameters: E params = %p", ¶ms); |
| |
| Mutex::Autolock l(&mLock); |
| Mutex::Autolock pl(&mParametersLock); |
| status_t rc, final_rc = NO_ERROR; |
| if (mSnapshotThreadRunning) { |
| if ((rc = setCameraMode(params))) final_rc = rc; |
| if ((rc = setPreviewSize(params))) final_rc = rc; |
| if ((rc = setRecordSize(params))) final_rc = rc; |
| if ((rc = setPictureSize(params))) final_rc = rc; |
| if ((rc = setJpegThumbnailSize(params))) final_rc = rc; |
| if ((rc = setJpegQuality(params))) final_rc = rc; |
| return final_rc; |
| } |
| if ((rc = setCameraMode(params))) final_rc = rc; |
| if ((rc = setPreviewSize(params))) final_rc = rc; |
| if ((rc = setRecordSize(params))) final_rc = rc; |
| if ((rc = setPictureSize(params))) final_rc = rc; |
| if ((rc = setJpegThumbnailSize(params))) final_rc = rc; |
| if ((rc = setJpegQuality(params))) final_rc = rc; |
| if ((rc = setPictureFormat(params))) final_rc = rc; |
| if ((rc = setRecordSize(params))) final_rc = rc; |
| if ((rc = setPreviewFormat(params))) final_rc = rc; |
| if ((rc = setEffect(params))) final_rc = rc; |
| if ((rc = setGpsLocation(params))) final_rc = rc; |
| if ((rc = setRotation(params))) final_rc = rc; |
| if ((rc = setZoom(params))) final_rc = rc; |
| if ((rc = setOrientation(params))) final_rc = rc; |
| if ((rc = setLensshadeValue(params))) final_rc = rc; |
| if ((rc = setMCEValue(params))) final_rc = rc; |
| //if ((rc = setHDRImaging(params))) final_rc = rc; |
| if ((rc = setExpBracketing(params))) final_rc = rc; |
| if ((rc = setPictureFormat(params))) final_rc = rc; |
| if ((rc = setSharpness(params))) final_rc = rc; |
| if ((rc = setSaturation(params))) final_rc = rc; |
| if ((rc = setTouchAfAec(params))) final_rc = rc; |
| if ((rc = setSceneMode(params))) final_rc = rc; |
| if ((rc = setContrast(params))) final_rc = rc; |
| if ((rc = setRecordSize(params))) final_rc = rc; |
| if ((rc = setSceneDetect(params))) final_rc = rc; |
| if ((rc = setStrTextures(params))) final_rc = rc; |
| if ((rc = setPreviewFormat(params))) final_rc = rc; |
| if ((rc = setSkinToneEnhancement(params))) final_rc = rc; |
| if ((rc = setAntibanding(params))) final_rc = rc; |
| if ((rc = setRedeyeReduction(params))) final_rc = rc; |
| if ((rc = setDenoise(params))) final_rc = rc; |
| if ((rc = setPreviewFpsRange(params))) final_rc = rc; |
| if ((rc = setZslParam(params))) final_rc = rc; |
| if ((rc = setSnapshotCount(params))) final_rc = rc; |
| if((rc = setRecordingHint(params))) final_rc = rc; |
| const char *str = params.get(QCameraParameters::KEY_SCENE_MODE); |
| int32_t value = attr_lookup(scenemode, sizeof(scenemode) / sizeof(str_map), str); |
| |
| if((value != NOT_FOUND) && (value == CAMERA_BESTSHOT_OFF)) { |
| if ((rc = setPreviewFrameRate(params))) final_rc = rc; |
| // if ((rc = setPreviewFrameRateMode(params))) final_rc = rc; |
| if ((rc = setAutoExposure(params))) final_rc = rc; |
| if ((rc = setExposureCompensation(params))) final_rc = rc; |
| if ((rc = setWhiteBalance(params))) final_rc = rc; |
| if ((rc = setFlash(params))) final_rc = rc; |
| if ((rc = setFocusMode(params))) final_rc = rc; |
| if ((rc = setBrightness(params))) final_rc = rc; |
| if ((rc = setISOValue(params))) final_rc = rc; |
| if ((rc = setFocusAreas(params))) final_rc = rc; |
| if ((rc = setMeteringAreas(params))) final_rc = rc; |
| } |
| //selectableZoneAF needs to be invoked after continuous AF |
| if ((rc = setSelectableZoneAf(params))) final_rc = rc; |
| // setHighFrameRate needs to be done at end, as there can |
| // be a preview restart, and need to use the updated parameters |
| if ((rc = setHighFrameRate(params))) final_rc = rc; |
| |
| ALOGV("setParameters: X"); |
| return final_rc; |
| } |
| |
| QCameraParameters QualcommCameraHardware::getParameters() const |
| { |
| ALOGV("getParameters: EX"); |
| return mParameters; |
| } |
| status_t QualcommCameraHardware::setHistogramOn() |
| { |
| ALOGV("setHistogramOn: EX"); |
| mStatsWaitLock.lock(); |
| mSendData = true; |
| if(mStatsOn == CAMERA_HISTOGRAM_ENABLE) { |
| mStatsWaitLock.unlock(); |
| return NO_ERROR; |
| } |
| #if 0 |
| if (mStatHeap != NULL) { |
| ALOGV("setHistogram on: clearing old mStatHeap."); |
| mStatHeap.clear(); |
| } |
| #endif |
| |
| mStatSize = sizeof(uint32_t)* HISTOGRAM_STATS_SIZE; |
| mCurrent = -1; |
| /*Currently the Ashmem is multiplying the buffer size with total number |
| of buffers and page aligning. This causes a crash in JNI as each buffer |
| individually expected to be page aligned */ |
| int page_size_minus_1 = getpagesize() - 1; |
| int32_t mAlignedStatSize = ((mStatSize + page_size_minus_1) & (~page_size_minus_1)); |
| #if 0 |
| mStatHeap = |
| new AshmemPool(mAlignedStatSize, |
| 3, |
| mStatSize, |
| "stat"); |
| if (!mStatHeap->initialized()) { |
| ALOGE("Stat Heap X failed "); |
| mStatHeap.clear(); |
| ALOGE("setHistogramOn X: error initializing mStatHeap"); |
| mStatsWaitLock.unlock(); |
| return UNKNOWN_ERROR; |
| } |
| #endif |
| for(int cnt = 0; cnt<3; cnt++) { |
| mStatsMapped[cnt]=mGetMemory(-1, mStatSize,1,mCallbackCookie); |
| if(mStatsMapped[cnt] == NULL) { |
| ALOGE("Failed to get camera memory for stats heap index: %d", cnt); |
| mStatsWaitLock.unlock(); |
| return false; |
| }else{ |
| ALOGV("Received following info for stats mapped data:%p,handle:%p, size:%d,release:%p", |
| mStatsMapped[cnt]->data ,mStatsMapped[cnt]->handle, mStatsMapped[cnt]->size, mStatsMapped[cnt]->release); |
| } |
| } |
| mStatsOn = CAMERA_HISTOGRAM_ENABLE; |
| mStatsWaitLock.unlock(); |
| mCfgControl.mm_camera_set_parm(CAMERA_PARM_HISTOGRAM, &mStatsOn); |
| return NO_ERROR; |
| } |
| |
| status_t QualcommCameraHardware::setHistogramOff() |
| { |
| ALOGV("setHistogramOff: EX"); |
| mStatsWaitLock.lock(); |
| if(mStatsOn == CAMERA_HISTOGRAM_DISABLE) { |
| mStatsWaitLock.unlock(); |
| return NO_ERROR; |
| } |
| mStatsOn = CAMERA_HISTOGRAM_DISABLE; |
| mStatsWaitLock.unlock(); |
| |
| mCfgControl.mm_camera_set_parm(CAMERA_PARM_HISTOGRAM, &mStatsOn); |
| |
| mStatsWaitLock.lock(); |
| // mStatHeap.clear(); |
| for(int i=0; i<3; i++){ |
| if(mStatsMapped[i] != NULL){ |
| mStatsMapped[i]->release(mStatsMapped[i]); |
| mStatsMapped[i] = NULL; |
| } |
| } |
| |
| mStatsWaitLock.unlock(); |
| return NO_ERROR; |
| } |
| |
| |
| status_t QualcommCameraHardware::runFaceDetection() |
| { |
| bool ret = true; |
| #if 0 |
| const char *str = mParameters.get(QCameraParameters::KEY_FACE_DETECTION); |
| if (str != NULL) { |
| int value = attr_lookup(facedetection, |
| sizeof(facedetection) / sizeof(str_map), str); |
| |
| mMetaDataWaitLock.lock(); |
| if (value == true) { |
| if(mMetaDataHeap != NULL) |
| mMetaDataHeap.clear(); |
| |
| mMetaDataHeap = |
| new AshmemPool((sizeof(int)*(MAX_ROI*4+1)), |
| 1, |
| (sizeof(int)*(MAX_ROI*4+1)), |
| "metadata"); |
| if (!mMetaDataHeap->initialized()) { |
| ALOGE("Meta Data Heap allocation failed "); |
| mMetaDataHeap.clear(); |
| ALOGE("runFaceDetection X: error initializing mMetaDataHeap"); |
| mMetaDataWaitLock.unlock(); |
| return UNKNOWN_ERROR; |
| } |
| mSendMetaData = true; |
| } else { |
| if(mMetaDataHeap != NULL) |
| mMetaDataHeap.clear(); |
| } |
| mMetaDataWaitLock.unlock(); |
| ret = native_set_parms(CAMERA_PARM_FD, sizeof(int8_t), (void *)&value); |
| return ret ? NO_ERROR : UNKNOWN_ERROR; |
| } |
| ALOGE("Invalid Face Detection value: %s", (str == NULL) ? "NULL" : str); |
| #endif |
| return BAD_VALUE; |
| } |
| |
| void* smoothzoom_thread(void* user) |
| { |
| // call runsmoothzoomthread |
| ALOGV("smoothzoom_thread E"); |
| CAMERA_HAL_UNUSED(user); |
| |
| QualcommCameraHardware* obj = QualcommCameraHardware::getInstance(); |
| if (obj != 0) { |
| obj->runSmoothzoomThread(user); |
| } |
| else ALOGE("not starting smooth zoom thread: the object went away!"); |
| ALOGV("Smoothzoom_thread X"); |
| return NULL; |
| } |
| |
| status_t QualcommCameraHardware::sendCommand(int32_t command, int32_t arg1, |
| int32_t arg2) |
| { |
| ALOGV("sendCommand: EX"); |
| CAMERA_HAL_UNUSED(arg1); |
| CAMERA_HAL_UNUSED(arg2); |
| Mutex::Autolock l(&mLock); |
| |
| switch(command) { |
| case CAMERA_CMD_HISTOGRAM_ON: |
| ALOGV("histogram set to on"); |
| return setHistogramOn(); |
| case CAMERA_CMD_HISTOGRAM_OFF: |
| ALOGV("histogram set to off"); |
| return setHistogramOff(); |
| case CAMERA_CMD_HISTOGRAM_SEND_DATA: |
| mStatsWaitLock.lock(); |
| if(mStatsOn == CAMERA_HISTOGRAM_ENABLE) |
| mSendData = true; |
| mStatsWaitLock.unlock(); |
| return NO_ERROR; |
| #if 0 |
| case CAMERA_CMD_FACE_DETECTION_ON: |
| if(supportsFaceDetection() == false){ |
| ALOGI("face detection support is not available"); |
| return NO_ERROR; |
| } |
| |
| setFaceDetection("on"); |
| return runFaceDetection(); |
| case CAMERA_CMD_FACE_DETECTION_OFF: |
| if(supportsFaceDetection() == false){ |
| ALOGI("face detection support is not available"); |
| return NO_ERROR; |
| } |
| setFaceDetection("off"); |
| return runFaceDetection(); |
| case CAMERA_CMD_SEND_META_DATA: |
| mMetaDataWaitLock.lock(); |
| if(mFaceDetectOn == true) { |
| mSendMetaData = true; |
| } |
| mMetaDataWaitLock.unlock(); |
| return NO_ERROR; |
| case CAMERA_CMD_START_SMOOTH_ZOOM : |
| ALOGV("HAL sendcmd start smooth zoom %d %d", arg1 , arg2); |
| mTargetSmoothZoom = arg1; |
| if(!mPreviewStopping) { |
| // create smooth zoom thread |
| mSmoothzoomThreadLock.lock(); |
| mSmoothzoomThreadExit = false; |
| pthread_attr_t attr; |
| pthread_attr_init(&attr); |
| pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); |
| pthread_create(&mSmoothzoomThread, |
| &attr, |
| smoothzoom_thread, |
| NULL); |
| mSmoothzoomThreadLock.unlock(); |
| } else |
| ALOGV(" Not creating smooth zoom thread " |
| " since preview is stopping "); |
| mTargetSmoothZoom = arg1; |
| return NO_ERROR; |
| |
| case CAMERA_CMD_STOP_SMOOTH_ZOOM : |
| mSmoothzoomThreadLock.lock(); |
| mSmoothzoomThreadExit = true; |
| mSmoothzoomThreadLock.unlock(); |
| ALOGV("HAL sendcmd stop smooth zoom"); |
| return NO_ERROR; |
| #endif |
| } |
| return BAD_VALUE; |
| } |
| |
| void QualcommCameraHardware::runSmoothzoomThread(void * data) { |
| |
| ALOGV("runSmoothzoomThread: Current zoom %d - " |
| "Target %d", mParameters.getInt("zoom"), mTargetSmoothZoom); |
| int current_zoom = mParameters.getInt("zoom"); |
| int step = (current_zoom > mTargetSmoothZoom)? -1: 1; |
| |
| if(current_zoom == mTargetSmoothZoom) { |
| ALOGV("Smoothzoom target zoom value is same as " |
| "current zoom value, return..."); |
| if(!mPreviewStopping) |
| mNotifyCallback(CAMERA_MSG_ZOOM, |
| current_zoom, 1, mCallbackCookie); |
| else |
| ALOGV("Not issuing callback since preview is stopping"); |
| return; |
| } |
| |
| QCameraParameters p = getParameters(); |
| |
| mSmoothzoomThreadWaitLock.lock(); |
| mSmoothzoomThreadRunning = true; |
| mSmoothzoomThreadWaitLock.unlock(); |
| |
| int i = current_zoom; |
| while(1) { // Thread loop |
| mSmoothzoomThreadLock.lock(); |
| if(mSmoothzoomThreadExit) { |
| ALOGV("Exiting smoothzoom thread, as stop smoothzoom called"); |
| mSmoothzoomThreadLock.unlock(); |
| break; |
| } |
| mSmoothzoomThreadLock.unlock(); |
| |
| if((i < 0) || (i > mMaxZoom)) { |
| ALOGE(" ERROR : beyond supported zoom values, break.."); |
| break; |
| } |
| // update zoom |
| p.set("zoom", i); |
| setZoom(p); |
| if(!mPreviewStopping) { |
| // give call back to zoom listener in app |
| mNotifyCallback(CAMERA_MSG_ZOOM, i, (mTargetSmoothZoom-i == 0)?1:0, |
| mCallbackCookie); |
| } else { |
| ALOGV("Preview is stopping. Breaking out of smooth zoom loop"); |
| break; |
| } |
| if(i == mTargetSmoothZoom) |
| break; |
| |
| i+=step; |
| |
| /* wait on singal, which will be signalled on |
| * receiving next preview frame */ |
| mSmoothzoomThreadWaitLock.lock(); |
| mSmoothzoomThreadWait.wait(mSmoothzoomThreadWaitLock); |
| mSmoothzoomThreadWaitLock.unlock(); |
| } // while loop over, exiting thread |
| |
| mSmoothzoomThreadWaitLock.lock(); |
| mSmoothzoomThreadRunning = false; |
| mSmoothzoomThreadWaitLock.unlock(); |
| ALOGV("Exiting Smooth Zoom Thread"); |
| } |
| |
| extern "C" QualcommCameraHardware* HAL_openCameraHardware(int cameraId) |
| { |
| int i; |
| ALOGI("openCameraHardware: call createInstance"); |
| for(i = 0; i < HAL_numOfCameras; i++) { |
| if(i == cameraId) { |
| ALOGI("openCameraHardware:Valid camera ID %d", cameraId); |
| parameter_string_initialized = false; |
| HAL_currentCameraId = cameraId; |
| /* The least significant two bits of mode parameter indicates the sensor mode |
| of 2D or 3D. The next two bits indicates the snapshot mode of |
| ZSL or NONZSL |
| */ |
| #if 0 |
| int sensorModeMask = 0x03 & mode; |
| if(sensorModeMask & HAL_cameraInfo[i].modes_supported){ |
| HAL_currentCameraMode = sensorModeMask; |
| }else{ |
| ALOGE("openCameraHardware:Invalid camera mode (%d) requested", mode); |
| return NULL; |
| } |
| #endif |
| HAL_currentCameraMode = CAMERA_MODE_2D; |
| HAL_currentSnapshotMode = CAMERA_SNAPSHOT_NONZSL; |
| //Remove values set by app other than supported values |
| //mode = mode & HAL_cameraInfo[cameraId].modes_supported; |
| //if((mode & CAMERA_SNAPSHOT_ZSL) == CAMERA_SNAPSHOT_ZSL) |
| // HAL_currentSnapshotMode = CAMERA_SNAPSHOT_ZSL; |
| ALOGI("%s: HAL_currentSnapshotMode = %d HAL_currentCameraMode = %d", __FUNCTION__, HAL_currentSnapshotMode, |
| HAL_currentCameraMode); |
| return QualcommCameraHardware::createInstance(); |
| } |
| } |
| ALOGE("openCameraHardware:Invalid camera ID %d", cameraId); |
| return NULL; |
| } |
| |
| //wp<QualcommCameraHardware> QualcommCameraHardware::singleton; |
| |
| // If the hardware already exists, return a strong pointer to the current |
| // object. If not, create a new hardware object, put it in the singleton, |
| // and return it. |
| QualcommCameraHardware* QualcommCameraHardware::createInstance() |
| { |
| ALOGV("createInstance: E"); |
| #if 0 |
| singleton_lock.lock(); |
| |
| // Wait until the previous release is done. |
| while (singleton_releasing) { |
| if((singleton_releasing_start_time != 0) && |
| (systemTime() - singleton_releasing_start_time) > SINGLETON_RELEASING_WAIT_TIME){ |
| ALOGV("in createinstance system time is %lld %lld %lld ", |
| systemTime(), singleton_releasing_start_time, SINGLETON_RELEASING_WAIT_TIME); |
| singleton_lock.unlock(); |
| ALOGE("Previous singleton is busy and time out exceeded. Returning null"); |
| return NULL; |
| } |
| ALOGI("Wait for previous release."); |
| singleton_wait.waitRelative(singleton_lock, SINGLETON_RELEASING_RECHECK_TIMEOUT); |
| ALOGI("out of Wait for previous release."); |
| } |
| |
| if (singleton != 0) { |
| sp<CameraHardwareInterface> hardware = singleton.promote(); |
| if (hardware != 0) { |
| ALOGD("createInstance: X return existing hardware=%p", &(*hardware)); |
| singleton_lock.unlock(); |
| return hardware; |
| } |
| } |
| #endif |
| { |
| struct stat st; |
| int rc = stat("/dev/oncrpc", &st); |
| if (rc < 0) { |
| ALOGD("createInstance: X failed to create hardware: %s", strerror(errno)); |
| singleton_lock.unlock(); |
| return NULL; |
| } |
| } |
| |
| QualcommCameraHardware *cam = new QualcommCameraHardware(); |
| hardware=cam; |
| |
| |
| ALOGI("createInstance: created hardware=%p", cam); |
| if (!cam->startCamera()) { |
| ALOGE("%s: startCamera failed!", __FUNCTION__); |
| //singleton_lock.unlock(); |
| delete cam; |
| return NULL; |
| } |
| |
| cam->initDefaultParameters(); |
| //singleton_lock.unlock(); |
| ALOGV("createInstance: X"); |
| return cam; |
| } |
| |
| // For internal use only, hence the strong pointer to the derived type. |
| QualcommCameraHardware* QualcommCameraHardware::getInstance() |
| { |
| //QualcommCameraHardware* hardware = singleton.promote(); |
| if (hardware != 0) { |
| // ALOGV("getInstance: X old instance of hardware"); |
| // return sp<QualcommCameraHardware>(static_cast<QualcommCameraHardware*>(hardware.get())); |
| return hardware; |
| } else { |
| ALOGV("getInstance: X new instance of hardware"); |
| return new QualcommCameraHardware(); |
| } |
| } |
| void QualcommCameraHardware::receiveRecordingFrame(struct msm_frame *frame) |
| { |
| ALOGV("receiveRecordingFrame E"); |
| // post busy frame |
| if (frame) |
| { |
| cam_frame_post_video (frame); |
| } |
| else ALOGE("in receiveRecordingFrame frame is NULL"); |
| ALOGV("receiveRecordingFrame X"); |
| } |
| |
| |
| bool QualcommCameraHardware::native_zoom_image(int fd, int srcOffset, int dstOffSet, common_crop_t *crop) |
| { |
| int result = 0; |
| struct mdp_blit_req *e; |
| |
| /* Initialize yuv structure */ |
| zoomImage.list.count = 1; |
| |
| e = &zoomImage.list.req[0]; |
| |
| e->src.width = previewWidth; |
| e->src.height = previewHeight; |
| e->src.format = MDP_Y_CBCR_H2V2; |
| e->src.offset = srcOffset; |
| e->src.memory_id = fd; |
| |
| e->dst.width = previewWidth; |
| e->dst.height = previewHeight; |
| e->dst.format = MDP_Y_CBCR_H2V2; |
| e->dst.offset = dstOffSet; |
| e->dst.memory_id = fd; |
| |
| e->transp_mask = 0xffffffff; |
| e->flags = 0; |
| e->alpha = 0xff; |
| if (crop->in1_w != 0 && crop->in1_h != 0) { |
| e->src_rect.x = (crop->out1_w - crop->in1_w + 1) / 2 - 1; |
| e->src_rect.y = (crop->out1_h - crop->in1_h + 1) / 2 - 1; |
| e->src_rect.w = crop->in1_w; |
| e->src_rect.h = crop->in1_h; |
| } else { |
| e->src_rect.x = 0; |
| e->src_rect.y = 0; |
| e->src_rect.w = previewWidth; |
| e->src_rect.h = previewHeight; |
| } |
| //ALOGV(" native_zoom : SRC_RECT : x,y = %d,%d \t w,h = %d, %d", |
| // e->src_rect.x, e->src_rect.y, e->src_rect.w, e->src_rect.h); |
| |
| e->dst_rect.x = 0; |
| e->dst_rect.y = 0; |
| e->dst_rect.w = previewWidth; |
| e->dst_rect.h = previewHeight; |
| |
| result = ioctl(fb_fd, MSMFB_BLIT, &zoomImage.list); |
| if (result < 0) { |
| ALOGE("MSM_FBIOBLT failed! line=%d\n", __LINE__); |
| return FALSE; |
| } |
| return TRUE; |
| } |
| |
| void QualcommCameraHardware::debugShowPreviewFPS() const |
| { |
| static int mFrameCount; |
| static int mLastFrameCount = 0; |
| static nsecs_t mLastFpsTime = 0; |
| static float mFps = 0; |
| mFrameCount++; |
| nsecs_t now = systemTime(); |
| nsecs_t diff = now - mLastFpsTime; |
| if (diff > ms2ns(250)) { |
| mFps = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff; |
| ALOGI("Preview Frames Per Second: %.4f", mFps); |
| mLastFpsTime = now; |
| mLastFrameCount = mFrameCount; |
| } |
| } |
| |
| void QualcommCameraHardware::debugShowVideoFPS() const |
| { |
| static int mFrameCount; |
| static int mLastFrameCount = 0; |
| static nsecs_t mLastFpsTime = 0; |
| static float mFps = 0; |
| mFrameCount++; |
| nsecs_t now = systemTime(); |
| nsecs_t diff = now - mLastFpsTime; |
| if (diff > ms2ns(250)) { |
| mFps = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff; |
| ALOGI("Video Frames Per Second: %.4f", mFps); |
| mLastFpsTime = now; |
| mLastFrameCount = mFrameCount; |
| } |
| } |
| |
| void QualcommCameraHardware::receiveLiveSnapshot(uint32_t jpeg_size) |
| { |
| ALOGV("receiveLiveSnapshot E"); |
| #if DUMP_LIVESHOT_JPEG_FILE |
| int file_fd = open("/data/LiveSnapshot.jpg", O_RDWR | O_CREAT, 0777); |
| ALOGV("dumping live shot image in /data/LiveSnapshot.jpg"); |
| if (file_fd < 0) { |
| ALOGE("cannot open file\n"); |
| } |
| else |
| { |
| write(file_fd, (uint8_t *)mJpegLiveSnapMapped->data,jpeg_size); |
| } |
| close(file_fd); |
| #endif |
| Mutex::Autolock cbLock(&mCallbackLock); |
| if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) { |
| mDataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mJpegLiveSnapMapped ,data_counter, |
| NULL, mCallbackCookie); |
| |
| } |
| else ALOGV("JPEG callback was cancelled--not delivering image."); |
| |
| //Reset the Gps Information & relieve memory |
| exif_table_numEntries = 0; |
| mJpegHeap.clear(); |
| |
| liveshot_state = LIVESHOT_DONE; |
| |
| ALOGV("receiveLiveSnapshot X"); |
| } |
| void QualcommCameraHardware::receivePreviewFrame(struct msm_frame *frame) |
| { |
| ALOGV("receivePreviewFrame E"); |
| if (!mCameraRunning) { |
| ALOGI("ignoring preview callback--camera has been stopped"); |
| LINK_camframe_add_frame(CAM_PREVIEW_FRAME,frame); |
| return; |
| } |
| if((mCurrentTarget == TARGET_MSM7627A) && ( liveshot_state == LIVESHOT_IN_PROGRESS)) { |
| LINK_set_liveshot_frame(frame); |
| } |
| if(mPreviewBusyQueue.add(frame) == false) |
| LINK_camframe_add_frame(CAM_PREVIEW_FRAME,frame); |
| |
| |
| ALOGV("receivePreviewFrame X"); |
| } |
| void QualcommCameraHardware::receiveCameraStats(camstats_type stype, camera_preview_histogram_info* histinfo) |
| { |
| // ALOGV("receiveCameraStats E"); |
| CAMERA_HAL_UNUSED(stype); |
| |
| if (!mCameraRunning) { |
| ALOGE("ignoring stats callback--camera has been stopped"); |
| return; |
| } |
| |
| mCallbackLock.lock(); |
| int msgEnabled = mMsgEnabled; |
| camera_data_callback scb = mDataCallback; |
| void *sdata = mCallbackCookie; |
| mCallbackLock.unlock(); |
| mStatsWaitLock.lock(); |
| if(mStatsOn == CAMERA_HISTOGRAM_DISABLE) { |
| mStatsWaitLock.unlock(); |
| return; |
| } |
| if(!mSendData) { |
| mStatsWaitLock.unlock(); |
| } else { |
| mSendData = false; |
| mCurrent = (mCurrent+1)%3; |
| // The first element of the array will contain the maximum hist value provided by driver. |
| // *(uint32_t *)((unsigned int)mStatHeap->mHeap->base()+ (mStatHeap->mBufferSize * mCurrent)) = histinfo->max_value; |
| // memcpy((uint32_t *)((unsigned int)mStatHeap->mHeap->base()+ (mStatHeap->mBufferSize * mCurrent)+ sizeof(int32_t)), (uint32_t *)histinfo->buffer,(sizeof(int32_t) * 256)); |
| *(uint32_t *)((unsigned int)(mStatsMapped[mCurrent]->data)) = histinfo->max_value; |
| memcpy((uint32_t *)((unsigned int)mStatsMapped[mCurrent]->data + sizeof(int32_t)), (uint32_t *)histinfo->buffer,(sizeof(int32_t) * 256)); |
| |
| mStatsWaitLock.unlock(); |
| |
| if (scb != NULL && (msgEnabled & CAMERA_MSG_STATS_DATA)) |
| scb(CAMERA_MSG_STATS_DATA, mStatsMapped[mCurrent], data_counter, NULL,sdata); |
| |
| } |
| // ALOGV("receiveCameraStats X"); |
| } |
| /*=========================================================================== |
| * FUNCTION - do_mmap - |
| * |
| * DESCRIPTION: retured virtual addresss |
| *==========================================================================*/ |
| uint8_t *mm_camera_do_mmap(uint32_t size, int *pmemFd) |
| { |
| void *ret; /* returned virtual address */ |
| int pmem_fd; |
| |
| if(mCurrentTarget == TARGET_MSM8660) |
| pmem_fd = open("/dev/pmem_smipool", O_RDWR|O_SYNC); |
| else |
| pmem_fd = open("/dev/pmem_adsp", O_RDWR|O_SYNC); |
| if (pmem_fd <= 0) { |
| ALOGE("do_mmap: Open device /dev/pmem_smipool failed!\n"); |
| return NULL; |
| } |
| /* to make it page size aligned */ |
| size = (size + 4095) & (~4095); |
| ret = mmap(NULL, |
| size, |
| PROT_READ | PROT_WRITE, |
| MAP_SHARED, |
| pmem_fd, |
| 0); |
| if (ret == MAP_FAILED) { |
| ALOGE("do_mmap: pmem mmap() failed: %s (%d)\n", strerror(errno), errno); |
| close(pmem_fd); |
| return NULL; |
| } |
| ALOGI("do_mmap: pmem mmap fd %d ptr %p len %u\n", pmem_fd, ret, size); |
| *pmemFd = pmem_fd; |
| return(uint8_t *)ret; |
| } |
| |
| |
| bool QualcommCameraHardware::initRecord() |
| { |
| const char *pmem_region; |
| int ion_heap = ION_CP_MM_HEAP_ID; |
| int CbCrOffset; |
| int recordBufferSize; |
| int active, type =0; |
| |
| ALOGV("initREcord E"); |
| if(mZslEnable){ |
| ALOGV("initRecord X.. Not intializing Record buffers in ZSL mode"); |
| return true; |
| } |
| |
| if(mCurrentTarget == TARGET_MSM8660) { |
| pmem_region = "/dev/pmem_smipool"; |
| } else { |
| pmem_region = "/dev/pmem_adsp"; |
| } |
| |
| ALOGI("initRecord: mDimension.video_width = %d mDimension.video_height = %d", |
| mDimension.video_width, mDimension.video_height); |
| // for 8x60 the Encoder expects the CbCr offset should be aligned to 2K. |
| if(mCurrentTarget == TARGET_MSM8660) { |
| CbCrOffset = PAD_TO_2K(mDimension.video_width * mDimension.video_height); |
| recordBufferSize = CbCrOffset + PAD_TO_2K((mDimension.video_width * mDimension.video_height)/2); |
| } else { |
| CbCrOffset = PAD_TO_WORD(mDimension.video_width * mDimension.video_height); |
| recordBufferSize = (mDimension.video_width * mDimension.video_height *3)/2; |
| } |
| |
| /* Buffersize and frameSize will be different when DIS is ON. |
| * We need to pass the actual framesize with video heap, as the same |
| * is used at camera MIO when negotiating with encoder. |
| */ |
| mRecordFrameSize = PAD_TO_4K(recordBufferSize); |
| bool dis_disable = 0; |
| const char *str = mParameters.get(QCameraParameters::KEY_VIDEO_HIGH_FRAME_RATE); |
| if((str != NULL) && (strcmp(str, QCameraParameters::VIDEO_HFR_OFF))) { |
| ALOGI("%s: HFR is ON, DIS has to be OFF", __FUNCTION__); |
| dis_disable = 1; |
| } |
| if((mVpeEnabled && mDisEnabled && (!dis_disable))|| mIs3DModeOn){ |
| mRecordFrameSize = videoWidth * videoHeight * 3 / 2; |
| if(mCurrentTarget == TARGET_MSM8660){ |
| mRecordFrameSize = PAD_TO_4K(PAD_TO_2K(videoWidth * videoHeight) |
| + PAD_TO_2K((videoWidth * videoHeight)/2)); |
| } |
| } |
| ALOGV("mRecordFrameSize = %d", mRecordFrameSize); |
| //if(mRecordHeap == NULL) { |
| #if 0 |
| #ifdef USE_ION |
| mRecordHeap = new IonPool(ion_heap, |
| MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING, |
| MSM_PMEM_VIDEO, |
| recordBufferSize, |
| kRecordBufferCount, |
| mRecordFrameSize, |
| CbCrOffset, |
| 0, |
| "record"); |
| #endif |
| |
| mRecordHeap = new PmemPool(pmem_region, |
| MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING, |
| MSM_PMEM_VIDEO, |
| recordBufferSize, |
| kRecordBufferCount, |
| mRecordFrameSize, |
| CbCrOffset, |
| 0, |
| "record"); |
| |
| if (!mRecordHeap->initialized()) { |
| mRecordHeap.clear(); |
| mRecordHeap = NULL; |
| ALOGE("initRecord X: could not initialize record heap."); |
| return false; |
| } |
| |
| } else { |
| if(mHFRMode == true) { |
| ALOGI("%s: register record buffers with camera driver", __FUNCTION__); |
| register_record_buffers(true); |
| mHFRMode = false; |
| } |
| } |
| #endif |
| |
| for (int cnt = 0; cnt < kRecordBufferCount; cnt++) { |
| #if 0 |
| //recordframes[cnt].fd = mRecordHeap->mHeap->getHeapID(); |
| recordframes[cnt].buffer = (unsigned long)mm_camera_do_mmap(mRecordFrameSize, &(recordframes[cnt].fd)); |
| //(uint32_t)mRecordHeap->mHeap->base() + mRecordHeap->mAlignedBufferSize * cnt; |
| if(!recordframes[cnt].buffer) |
| { |
| ALOGE("Buffer allocation for record fram %d failed",cnt); |
| return false; |
| } |
| #endif |
| #ifdef USE_ION |
| if (allocate_ion_memory(&record_main_ion_fd[cnt], &record_alloc[cnt], &record_ion_info_fd[cnt], |
| ion_heap, mRecordFrameSize, &mRecordfd[cnt]) < 0){ |
| ALOGE("do_mmap: Open device %s failed!\n",pmem_region); |
| return NULL; |
| } |
| #else |
| mRecordfd[cnt] = open(pmem_region, O_RDWR|O_SYNC); |
| if (mRecordfd[cnt] <= 0) { |
| ALOGE("%s: Open device %s failed!\n",__func__, pmem_region); |
| return NULL; |
| } |
| #endif |
| ALOGI("%s Record fd is %d ", __func__, mRecordfd[cnt]); |
| mRecordMapped[cnt]=mGetMemory(mRecordfd[cnt], mRecordFrameSize,1,mCallbackCookie); |
| if(mRecordMapped[cnt]==NULL) { |
| ALOGE("Failed to get camera memory for mRecordMapped heap"); |
| }else{ |
| ALOGI("Received following info for record mapped data:%p,handle:%p, size:%d,release:%p", |
| mRecordMapped[cnt]->data ,mRecordMapped[cnt]->handle, mRecordMapped[cnt]->size, mRecordMapped[cnt]->release); |
| } |
| #if 1 |
| recordframes[cnt].buffer = (unsigned int)mRecordMapped[cnt]->data; |
| recordframes[cnt].fd = mRecordfd[cnt]; |
| #endif |
| recordframes[cnt].planar0_off = 0; |
| recordframes[cnt].planar1_off = CbCrOffset; |
| recordframes[cnt].planar2_off = 0; |
| recordframes[cnt].path = OUTPUT_TYPE_V; |
| record_buffers_tracking_flag[cnt] = false; |
| ALOGV ("initRecord : record heap , video buffers buffer=%lu fd=%d y_off=%d cbcr_off=%d \n", |
| (unsigned long)recordframes[cnt].buffer, recordframes[cnt].fd, recordframes[cnt].planar0_off, |
| recordframes[cnt].planar1_off); |
| active=(cnt<ACTIVE_VIDEO_BUFFERS); |
| type = MSM_PMEM_VIDEO; |
| if((mVpeEnabled) && (cnt == kRecordBufferCount-1)) { |
| type = MSM_PMEM_VIDEO_VPE; |
| active = 1; |
| } |
| ALOGI("Registering buffer %d with kernel",cnt); |
| register_buf(mRecordFrameSize, |
| mRecordFrameSize, CbCrOffset, 0, |
| recordframes[cnt].fd, |
| 0, |
| (uint8_t *)recordframes[cnt].buffer, |
| type, |
| active); |
| ALOGI("Came back from register call to kernel"); |
| } |
| |
| // initial setup : buffers 1,2,3 with kernel , 4 with camframe , 5,6,7,8 in free Q |
| // flush the busy Q |
| cam_frame_flush_video(); |
| |
| mVideoThreadWaitLock.lock(); |
| while (mVideoThreadRunning) { |
| ALOGV("initRecord: waiting for old video thread to complete."); |
| mVideoThreadWait.wait(mVideoThreadWaitLock); |
| ALOGV("initRecord : old video thread completed."); |
| } |
| mVideoThreadWaitLock.unlock(); |
| |
| // flush free queue and add 5,6,7,8 buffers. |
| LINK_camframe_release_all_frames(CAM_VIDEO_FRAME); |
| if(mVpeEnabled) { |
| //If VPE is enabled, the VPE buffer shouldn't be added to Free Q initally. |
| for(int i=ACTIVE_VIDEO_BUFFERS;i <kRecordBufferCount-1; i++) |
| LINK_camframe_add_frame(CAM_VIDEO_FRAME,&recordframes[i]); |
| } else { |
| for(int i=ACTIVE_VIDEO_BUFFERS;i <kRecordBufferCount; i++) |
| LINK_camframe_add_frame(CAM_VIDEO_FRAME,&recordframes[i]); |
| } |
| ALOGV("initREcord X"); |
| |
| return true; |
| } |
| |
| |
| status_t QualcommCameraHardware::setDIS() { |
| ALOGV("setDIS E"); |
| |
| video_dis_param_ctrl_t disCtrl; |
| bool ret = true; |
| ALOGV("mDisEnabled = %d", mDisEnabled); |
| |
| int video_frame_cbcroffset; |
| video_frame_cbcroffset = PAD_TO_WORD(videoWidth * videoHeight); |
| if(mCurrentTarget == TARGET_MSM8660) |
| video_frame_cbcroffset = PAD_TO_2K(videoWidth * videoHeight); |
| |
| disCtrl.dis_enable = mDisEnabled; |
| const char *str = mParameters.get(QCameraParameters::KEY_VIDEO_HIGH_FRAME_RATE); |
| if((str != NULL) && (strcmp(str, QCameraParameters::VIDEO_HFR_OFF))) { |
| ALOGI("%s: HFR is ON, setting DIS as OFF", __FUNCTION__); |
| disCtrl.dis_enable = 0; |
| } |
| disCtrl.video_rec_width = videoWidth; |
| disCtrl.video_rec_height = videoHeight; |
| disCtrl.output_cbcr_offset = video_frame_cbcroffset; |
| |
| ret = native_set_parms( CAMERA_PARM_VIDEO_DIS, |
| sizeof(disCtrl), &disCtrl); |
| |
| ALOGV("setDIS X (%d)", ret); |
| return ret ? NO_ERROR : UNKNOWN_ERROR; |
| } |
| |
| status_t QualcommCameraHardware::setVpeParameters() |
| { |
| ALOGV("setVpeParameters E"); |
| |
| video_rotation_param_ctrl_t rotCtrl; |
| bool ret = true; |
| ALOGV("videoWidth = %d, videoHeight = %d", videoWidth, videoHeight); |
| int rotation = (mRotation + sensor_rotation)%360; |
| rotCtrl.rotation = (rotation == 0) ? ROT_NONE : |
| ((rotation == 90) ? ROT_CLOCKWISE_90 : |
| ((rotation == 180) ? ROT_CLOCKWISE_180 : ROT_CLOCKWISE_270)); |
| |
| if( ((videoWidth == 1280 && videoHeight == 720) || (videoWidth == 800 && videoHeight == 480)) |
| && (rotation == 90 || rotation == 270) ){ |
| /* Due to a limitation at video core to support heights greater than 720, adding this check. |
| * This is a temporary hack, need to be removed once video core support is available |
| */ |
| ALOGI("video resolution (%dx%d) with rotation (%d) is not supported, setting rotation to NONE", |
| videoWidth, videoHeight, rotation); |
| rotCtrl.rotation = ROT_NONE; |
| } |
| ALOGV("rotCtrl.rotation = %d", rotCtrl.rotation); |
| |
| ret = native_set_parms(CAMERA_PARM_VIDEO_ROT, |
| sizeof(rotCtrl), &rotCtrl); |
| |
| ALOGV("setVpeParameters X (%d)", ret); |
| return ret ? NO_ERROR : UNKNOWN_ERROR; |
| } |
| |
| status_t QualcommCameraHardware::startRecording() |
| { |
| ALOGV("startRecording E"); |
| int ret; |
| Mutex::Autolock l(&mLock); |
| mReleasedRecordingFrame = false; |
| if( (ret=startPreviewInternal())== NO_ERROR){ |
| if(mVpeEnabled){ |
| ALOGI("startRecording: VPE enabled, setting vpe parameters"); |
| bool status = setVpeParameters(); |
| if(status) { |
| ALOGE("Failed to set VPE parameters"); |
| return status; |
| } |
| } |
| if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250) || |
| (mCurrentTarget == TARGET_MSM8660)) { |
| for (int cnt = 0; cnt < kRecordBufferCount; cnt++) { |
| if(mStoreMetaDataInFrame) |
| { |
| ALOGI("startRecording : meta data mode enabled"); |
| metadata_memory[cnt] = mGetMemory(-1, sizeof(struct encoder_media_buffer_type), 1, mCallbackCookie); |
| struct encoder_media_buffer_type * packet = |
| (struct encoder_media_buffer_type *)metadata_memory[cnt]->data; |
| packet->meta_handle = native_handle_create(1, 2); //1 fd, 1 offset and 1 size |
| packet->buffer_type = kMetadataBufferTypeCameraSource; |
| native_handle_t * nh = const_cast<native_handle_t *>(packet->meta_handle); |
| nh->data[0] = mRecordfd[cnt]; |
| nh->data[1] = 0; |
| nh->data[2] = mRecordFrameSize; |
| } |
| } |
| ALOGV(" in startREcording : calling start_recording"); |
| native_start_ops(CAMERA_OPS_VIDEO_RECORDING, NULL); |
| mRecordingState = 1; |
| // Remove the left out frames in busy Q and them in free Q. |
| // this should be done before starting video_thread so that, |
| // frames in previous recording are flushed out. |
| ALOGV("frames in busy Q = %d", g_busy_frame_queue.num_of_frames); |
| while((g_busy_frame_queue.num_of_frames) >0){ |
| msm_frame* vframe = cam_frame_get_video (); |
| LINK_camframe_add_frame(CAM_VIDEO_FRAME,vframe); |
| } |
| ALOGV("frames in busy Q = %d after deQueing", g_busy_frame_queue.num_of_frames); |
| //Clear the dangling buffers and put them in free queue |
| for(int cnt = 0; cnt < kRecordBufferCount; cnt++) { |
| if(record_buffers_tracking_flag[cnt] == true) { |
| ALOGI("Dangling buffer: offset = %d, buffer = %d", cnt, |
| (unsigned int)recordframes[cnt].buffer); |
| LINK_camframe_add_frame(CAM_VIDEO_FRAME,&recordframes[cnt]); |
| record_buffers_tracking_flag[cnt] = false; |
| } |
| } |
| mVideoThreadWaitLock.lock(); |
| mVideoThreadExit = 0; |
| pthread_attr_t attr; |
| pthread_attr_init(&attr); |
| pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); |
| mVideoThreadRunning = pthread_create(&mVideoThread, |
| &attr, |
| video_thread, |
| NULL); |
| mVideoThreadWaitLock.unlock(); |
| } else if ( mCurrentTarget == TARGET_MSM7627A ) { |
| for (int cnt = 0; cnt < mTotalPreviewBufferCount; cnt++) { |
| if(mStoreMetaDataInFrame |
| && (metadata_memory[cnt] == NULL)) |
| { |
| ALOGI("startRecording : meta data mode enabled filling metadata memory "); |
| metadata_memory[cnt] = mGetMemory(-1, sizeof(struct encoder_media_buffer_type), 1, mCallbackCookie); |
| struct encoder_media_buffer_type * packet = |
| (struct encoder_media_buffer_type *)metadata_memory[cnt]->data; |
| packet->meta_handle = native_handle_create(1, 3); //1 fd, 1 offset and 1 size |
| packet->buffer_type = kMetadataBufferTypeCameraSource; |
| native_handle_t * nh = const_cast<native_handle_t *>(packet->meta_handle); |
| nh->data[0] = frames[cnt].fd; |
| nh->data[1] = 0; |
| nh->data[2] = previewWidth * previewHeight * 3/2; |
| nh->data[3] = (unsigned int)mPreviewMapped[cnt]->data; |
| } |
| } |
| } |
| record_flag = 1; |
| } |
| return ret; |
| } |
| |
| status_t QualcommCameraHardware::startRecordingInternal() |
| { |
| ALOGV("%s: E", __FUNCTION__); |
| mReleasedRecordingFrame = false; |
| |
| /* In 3D mode, the video thread has to be started as part |
| * of preview itself, because video buffers and video callback |
| * need to be used for both display and encoding. |
| * startRecordingInternal() will be called as part of startPreview(). |
| * This check is needed to support both 3D and non-3D mode. |
| */ |
| if(mVideoThreadRunning) { |
| ALOGI("Video Thread is in progress"); |
| return NO_ERROR; |
| } |
| |
| if(mVpeEnabled){ |
| ALOGI("startRecording: VPE enabled, setting vpe parameters"); |
| bool status = setVpeParameters(); |
| if(status) { |
| ALOGE("Failed to set VPE parameters"); |
| return status; |
| } |
| } |
| if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250) || (mCurrentTarget == TARGET_MSM8660)) { |
| // Remove the left out frames in busy Q and them in free Q. |
| // this should be done before starting video_thread so that, |
| // frames in previous recording are flushed out. |
| ALOGV("frames in busy Q = %d", g_busy_frame_queue.num_of_frames); |
| while((g_busy_frame_queue.num_of_frames) >0){ |
| msm_frame* vframe = cam_frame_get_video (); |
| LINK_camframe_add_frame(CAM_VIDEO_FRAME,vframe); |
| } |
| ALOGV("frames in busy Q = %d after deQueing", g_busy_frame_queue.num_of_frames); |
| |
| //Clear the dangling buffers and put them in free queue |
| for(int cnt = 0; cnt < kRecordBufferCount; cnt++) { |
| if(record_buffers_tracking_flag[cnt] == true) { |
| ALOGI("Dangling buffer: offset = %d, buffer = %d", cnt, (unsigned int)recordframes[cnt].buffer); |
| LINK_camframe_add_frame(CAM_VIDEO_FRAME,&recordframes[cnt]); |
| record_buffers_tracking_flag[cnt] = false; |
| } |
| } |
| |
| ALOGI(" in startREcording : calling start_recording"); |
| if(!mIs3DModeOn) |
| native_start_ops(CAMERA_OPS_VIDEO_RECORDING, NULL); |
| |
| // Start video thread and wait for busy frames to be encoded, this thread |
| // should be closed in stopRecording |
| mVideoThreadWaitLock.lock(); |
| mVideoThreadExit = 0; |
| pthread_attr_t attr; |
| pthread_attr_init(&attr); |
| pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); |
| mVideoThreadRunning = !pthread_create(&mVideoThread, |
| &attr, |
| video_thread, |
| NULL); |
| mVideoThreadWaitLock.unlock(); |
| // Remove the left out frames in busy Q and them in free Q. |
| } |
| ALOGV("%s: E", __FUNCTION__); |
| return NO_ERROR; |
| } |
| |
| void QualcommCameraHardware::stopRecording() |
| { |
| ALOGV("stopRecording: E"); |
| record_flag = 0; |
| Mutex::Autolock l(&mLock); |
| { |
| mRecordFrameLock.lock(); |
| mReleasedRecordingFrame = true; |
| mRecordWait.signal(); |
| mRecordFrameLock.unlock(); |
| |
| if(mDataCallback && !(mCurrentTarget == TARGET_QSD8250) && |
| (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)) { |
| ALOGV("stopRecording: X, preview still in progress"); |
| return; |
| } |
| } |
| if (NULL != mJpegLiveSnapMapped) { |
| ALOGI("initLiveSnapshot: clearing old mJpegHeap."); |
| mJpegLiveSnapMapped->release(mJpegLiveSnapMapped); |
| mJpegLiveSnapMapped = NULL; |
| } |
| |
| // If output2 enabled, exit video thread, invoke stop recording ioctl |
| if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250) || (mCurrentTarget == TARGET_MSM8660)) { |
| /* when 3D mode is ON, don't exit the video thread, as |
| * we need to support the preview mode. Just set the recordingState |
| * to zero, so that there won't be any rcb callbacks. video thread |
| * will be terminated as part of stop preview. |
| */ |
| if(mIs3DModeOn) { |
| ALOGV("%s: 3D mode on, so don't exit video thread", __FUNCTION__); |
| mRecordingState = 0; |
| return; |
| } |
| |
| mVideoThreadWaitLock.lock(); |
| mVideoThreadExit = 1; |
| mVideoThreadWaitLock.unlock(); |
| native_stop_ops(CAMERA_OPS_VIDEO_RECORDING, NULL); |
| |
| pthread_mutex_lock(&(g_busy_frame_queue.mut)); |
| pthread_cond_signal(&(g_busy_frame_queue.wait)); |
| pthread_mutex_unlock(&(g_busy_frame_queue.mut)); |
| for (int cnt = 0; cnt < kRecordBufferCount; cnt++) { |
| if(mStoreMetaDataInFrame && (metadata_memory[cnt] != NULL)){ |
| struct encoder_media_buffer_type * packet = |
| (struct encoder_media_buffer_type *)metadata_memory[cnt]->data; |
| native_handle_delete(const_cast<native_handle_t *>(packet->meta_handle)); |
| metadata_memory[cnt]->release(metadata_memory[cnt]); |
| metadata_memory[cnt] = NULL; |
| } |
| } |
| } |
| else if(mCurrentTarget == TARGET_MSM7627A) { |
| for (int cnt = 0; cnt < mTotalPreviewBufferCount; cnt++) { |
| if(mStoreMetaDataInFrame && (metadata_memory[cnt] != NULL)){ |
| struct encoder_media_buffer_type * packet = |
| (struct encoder_media_buffer_type *)metadata_memory[cnt]->data; |
| native_handle_delete(const_cast<native_handle_t *>(packet->meta_handle)); |
| metadata_memory[cnt]->release(metadata_memory[cnt]); |
| metadata_memory[cnt] = NULL; |
| } |
| } |
| } |
| #if 0 |
| else // for other targets where output2 is not enabled |
| stopPreviewInternal(); |
| if (mJpegHeap != NULL) { |
| ALOGV("stopRecording: clearing old mJpegHeap."); |
| mJpegHeap.clear(); |
| } |
| #endif |
| mRecordingState = 0; // recording not started |
| ALOGV("stopRecording: X"); |
| } |
| |
| void QualcommCameraHardware::releaseRecordingFrame(const void *opaque) |
| { |
| ALOGI("%s : BEGIN, opaque = 0x%p",__func__, opaque); |
| Mutex::Autolock rLock(&mRecordFrameLock); |
| mReleasedRecordingFrame = true; |
| mRecordWait.signal(); |
| |
| // Ff 7x30 : add the frame to the free camframe queue |
| if( (mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250) || (mCurrentTarget == TARGET_MSM8660)) { |
| ssize_t offset; |
| size_t size; |
| //sp<IMemoryHeap> heap = mem->getMemory(&offset, &size); |
| msm_frame* releaseframe = NULL; |
| int cnt; |
| for (cnt = 0; cnt < kRecordBufferCount; cnt++) { |
| if(mStoreMetaDataInFrame){ |
| if(metadata_memory[cnt] && metadata_memory[cnt]->data == opaque){ |
| ALOGV("in release recording frame(meta) found match , releasing buffer %d", (unsigned int)recordframes[cnt].buffer); |
| releaseframe = &recordframes[cnt]; |
| break; |
| } |
| }else { |
| if(recordframes[cnt].buffer && ((unsigned long)opaque == recordframes[cnt].buffer) ){ |
| ALOGV("in release recording frame found match , releasing buffer %d", (unsigned int)recordframes[cnt].buffer); |
| releaseframe = &recordframes[cnt]; |
| break; |
| } |
| } |
| } |
| if(cnt < kRecordBufferCount) { |
| // do this only if frame thread is running |
| mFrameThreadWaitLock.lock(); |
| if(mFrameThreadRunning ) { |
| //Reset the track flag for this frame buffer |
| record_buffers_tracking_flag[cnt] = false; |
| LINK_camframe_add_frame(CAM_VIDEO_FRAME,releaseframe); |
| } |
| |
| mFrameThreadWaitLock.unlock(); |
| } else { |
| ALOGE("in release recordingframe XXXXX error , buffer not found"); |
| for (int i=0; i< kRecordBufferCount; i++) { |
| ALOGE(" recordframes[%d].buffer = %d", i, (unsigned int)recordframes[i].buffer); |
| } |
| } |
| } |
| |
| ALOGV("releaseRecordingFrame X"); |
| } |
| |
| bool QualcommCameraHardware::recordingEnabled() |
| { |
| return mCameraRunning && mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME); |
| } |
| |
| void QualcommCameraHardware::notifyShutter(bool mPlayShutterSoundOnly) |
| { |
| private_handle_t *thumbnailHandle; |
| if(mThumbnailBuffer) { |
| thumbnailHandle = (private_handle_t *) (*mThumbnailBuffer); |
| } |
| mShutterLock.lock(); |
| //image_rect_type size; |
| |
| if(mPlayShutterSoundOnly) { |
| /* At this point, invoke Notify Callback to play shutter sound only. |
| * We want to call notify callback again when we have the |
| * yuv picture ready. This is to reduce blanking at the time |
| * of displaying postview frame. Using ext2 to indicate whether |
| * to play shutter sound only or register the postview buffers. |
| */ |
| mNotifyCallback(CAMERA_MSG_SHUTTER, 0, mPlayShutterSoundOnly, |
| mCallbackCookie); |
| mShutterLock.unlock(); |
| return; |
| } |
| |
| if (mShutterPending && mNotifyCallback && (mMsgEnabled & CAMERA_MSG_SHUTTER)) { |
| //mDisplayHeap = mThumbnailHeap; |
| #if 0 |
| if (crop != NULL && (crop->in1_w != 0 && crop->in1_h != 0)) { |
| size.width = crop->in1_w; |
| size.height = crop->in1_h; |
| } |
| else { |
| size.width = mPostviewWidth; |
| size.height = mPostviewHeight; |
| } |
| #endif |
| /* |
| if(strTexturesOn == true) { |
| mDisplayHeap = mRawHeap; |
| size.width = mPictureWidth; |
| size.height = mPictureHeight; |
| } |
| */ |
| /* Now, invoke Notify Callback to unregister preview buffer |
| * and register postview buffer with surface flinger. Set ext2 |
| * as 0 to indicate not to play shutter sound. |
| */ |
| mNotifyCallback(CAMERA_MSG_SHUTTER, 0, 0, |
| mCallbackCookie); |
| mShutterPending = false; |
| } |
| mShutterLock.unlock(); |
| } |
| |
| static void receive_shutter_callback(common_crop_t *crop) |
| { |
| ALOGV("receive_shutter_callback: E"); |
| QualcommCameraHardware* obj = QualcommCameraHardware::getInstance(); |
| if (obj != 0) { |
| /* Just play shutter sound at this time */ |
| obj->notifyShutter(TRUE); |
| } |
| ALOGV("receive_shutter_callback: X"); |
| } |
| |
| // Crop the picture in place. |
| static void crop_yuv420(uint32_t width, uint32_t height, |
| uint32_t cropped_width, uint32_t cropped_height, |
| uint8_t *image, const char *name) |
| { |
| uint32_t i; |
| uint32_t x, y; |
| uint8_t* chroma_src, *chroma_dst; |
| int yOffsetSrc, yOffsetDst, CbCrOffsetSrc, CbCrOffsetDst; |
| int mSrcSize, mDstSize; |
| |
| //check if all fields needed eg. size and also how to set y offset. If condition for 7x27 |
| //and need to check if needed for 7x30. |
| |
| LINK_jpeg_encoder_get_buffer_offset(width, height, (uint32_t *)&yOffsetSrc, |
| (uint32_t *)&CbCrOffsetSrc, (uint32_t *)&mSrcSize); |
| |
| LINK_jpeg_encoder_get_buffer_offset(cropped_width, cropped_height, (uint32_t *)&yOffsetDst, |
| (uint32_t *)&CbCrOffsetDst, (uint32_t *)&mDstSize); |
| |
| // Calculate the start position of the cropped area. |
| x = (width - cropped_width) / 2; |
| y = (height - cropped_height) / 2; |
| x &= ~1; |
| y &= ~1; |
| |
| if((mCurrentTarget == TARGET_MSM7627) |
| || (mCurrentTarget == TARGET_MSM7625A) |
| || (mCurrentTarget == TARGET_MSM7627A) |
| || (mCurrentTarget == TARGET_MSM7630) |
| || (mCurrentTarget == TARGET_MSM8660)) { |
| if (!strcmp("snapshot camera", name)) { |
| chroma_src = image + CbCrOffsetSrc; |
| chroma_dst = image + CbCrOffsetDst; |
| } else { |
| chroma_src = image + width * height; |
| chroma_dst = image + cropped_width * cropped_height; |
| yOffsetSrc = 0; |
| yOffsetDst = 0; |
| CbCrOffsetSrc = width * height; |
| CbCrOffsetDst = cropped_width * cropped_height; |
| } |
| } else { |
| chroma_src = image + CbCrOffsetSrc; |
| chroma_dst = image + CbCrOffsetDst; |
| } |
| |
| int32_t bufDst = yOffsetDst; |
| int32_t bufSrc = yOffsetSrc + (width * y) + x; |
| |
| if( bufDst > bufSrc ){ |
| ALOGV("crop yuv Y destination position follows source position"); |
| /* |
| * If buffer destination follows buffer source, memcpy |
| * of lines will lead to overwriting subsequent lines. In order |
| * to prevent this, reverse copying of lines is performed |
| * for the set of lines where destination follows source and |
| * forward copying of lines is performed for lines where source |
| * follows destination. To calculate the position to switch, |
| * the initial difference between source and destination is taken |
| * and divided by difference between width and cropped width. For |
| * every line copied the difference between source destination |
| * drops by width - cropped width |
| */ |
| //calculating inversion |
| int position = ( bufDst - bufSrc ) / (width - cropped_width); |
| // Copy luma component. |
| for(i=position+1; i < cropped_height; i++){ |
| memmove(image + yOffsetDst + i * cropped_width, |
| image + yOffsetSrc + width * (y + i) + x, |
| cropped_width); |
| } |
| for(int j=position; j>=0; j--){ |
| memmove(image + yOffsetDst + j * cropped_width, |
| image + yOffsetSrc + width * (y + j) + x, |
| cropped_width); |
| } |
| } else { |
| // Copy luma component. |
| for(i = 0; i < cropped_height; i++) |
| memcpy(image + yOffsetDst + i * cropped_width, |
| image + yOffsetSrc + width * (y + i) + x, |
| cropped_width); |
| } |
| |
| // Copy chroma components. |
| cropped_height /= 2; |
| y /= 2; |
| |
| bufDst = CbCrOffsetDst; |
| bufSrc = CbCrOffsetSrc + (width * y) + x; |
| |
| if( bufDst > bufSrc ) { |
| ALOGV("crop yuv Chroma destination position follows source position"); |
| /* |
| * Similar to y |
| */ |
| int position = ( bufDst - bufSrc ) / (width - cropped_width); |
| for(i=position+1; i < cropped_height; i++){ |
| memmove(chroma_dst + i * cropped_width, |
| chroma_src + width * (y + i) + x, |
| cropped_width); |
| } |
| for(int j=position; j >=0; j--){ |
| memmove(chroma_dst + j * cropped_width, |
| chroma_src + width * (y + j) + x, |
| cropped_width); |
| } |
| } else { |
| for(i = 0; i < cropped_height; i++) |
| memcpy(chroma_dst + i * cropped_width, |
| chroma_src + width * (y + i) + x, |
| cropped_width); |
| } |
| } |
| // ReceiveRawPicture for ICS |
| void QualcommCameraHardware::receiveRawPicture(status_t status,struct msm_frame *postviewframe, struct msm_frame *mainframe) |
| { |
| ALOGV("%s: E", __FUNCTION__); |
| |
| void* cropp; |
| mSnapshotThreadWaitLock.lock(); |
| if(mSnapshotThreadRunning == false) { |
| ALOGE("%s called in wrong state, ignore", __FUNCTION__); |
| return; |
| } |
| mSnapshotThreadWaitLock.unlock(); |
| |
| if(status != NO_ERROR){ |
| ALOGE("%s: Failed to get Snapshot Image", __FUNCTION__); |
| if(mDataCallback && |
| (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) { |
| /* get picture failed. Give jpeg callback with NULL data |
| * to the application to restore to preview mode |
| */ |
| ALOGE("get picture failed, giving jpeg callback with NULL data"); |
| mDataCallback(CAMERA_MSG_COMPRESSED_IMAGE, NULL, data_counter, NULL, mCallbackCookie); |
| } |
| mShutterLock.lock(); |
| mShutterPending = false; |
| mShutterLock.unlock(); |
| mJpegThreadWaitLock.lock(); |
| mJpegThreadRunning = false; |
| mJpegThreadWait.signal(); |
| mJpegThreadWaitLock.unlock(); |
| mInSnapshotModeWaitLock.lock(); |
| mInSnapshotMode = false; |
| mInSnapshotModeWait.signal(); |
| mInSnapshotModeWaitLock.unlock(); |
| return; |
| } |
| /* call notifyShutter to config surface and overlay |
| * for postview rendering. |
| * Its necessary to issue another notifyShutter here with |
| * mPlayShutterSoundOnly as FALSE, since that is when the |
| * preview buffers are unregistered with the surface flinger. |
| * That is necessary otherwise the preview memory wont be |
| * deallocated. |
| */ |
| cropp =postviewframe->cropinfo; |
| notifyShutter(FALSE); |
| |
| if(mSnapshotFormat == PICTURE_FORMAT_JPEG) { |
| if(cropp != NULL){ |
| common_crop_t *crop = (common_crop_t *)cropp; |
| if (crop->in1_w != 0 && crop->in1_h != 0) { |
| zoomCropInfo.left = (crop->out1_w - crop->in1_w + 1) / 2 - 1; |
| zoomCropInfo.top = (crop->out1_h - crop->in1_h + 1) / 2 - 1; |
| if(zoomCropInfo.left < 0) zoomCropInfo.left = 0; |
| if(zoomCropInfo.top < 0) zoomCropInfo.top = 0; |
| zoomCropInfo.right = zoomCropInfo.left + crop->in1_w; |
| zoomCropInfo.bottom = zoomCropInfo.top + crop->in1_h; |
| mPreviewWindow->set_crop(mPreviewWindow, |
| zoomCropInfo.left, |
| zoomCropInfo.top, |
| zoomCropInfo.right, |
| zoomCropInfo.bottom); |
| mResetWindowCrop = true; |
| } else { |
| zoomCropInfo.left = 0; |
| zoomCropInfo.top = 0; |
| zoomCropInfo.right = mPostviewWidth; |
| zoomCropInfo.bottom = mPostviewHeight; |
| mPreviewWindow->set_crop(mPreviewWindow, |
| zoomCropInfo.left, |
| zoomCropInfo.top, |
| zoomCropInfo.right, |
| zoomCropInfo.bottom); |
| } |
| } |
| ALOGI("receiverawpicture : display lock"); |
| mDisplayLock.lock(); |
| int index = mapThumbnailBuffer(postviewframe); |
| ALOGI("receiveRawPicture : mapThumbnailBuffer returned %d", index); |
| private_handle_t *handle; |
| if(mThumbnailBuffer[index] != NULL && mZslEnable == false) { |
| handle = (private_handle_t *)(*mThumbnailBuffer[index]); |
| ALOGV("%s: Queueing postview buffer for display %d", |
| __FUNCTION__,handle->fd); |
| if (BUFFER_LOCKED == mThumbnailLockState[index]) { |
| if (GENLOCK_FAILURE == genlock_unlock_buffer(handle)) { |
| ALOGE("%s: genlock_unlock_buffer failed", __FUNCTION__); |
| mDisplayLock.unlock(); |
| return; |
| } else { |
| mThumbnailLockState[index] = BUFFER_UNLOCKED; |
| } |
| } |
| status_t retVal = mPreviewWindow->enqueue_buffer(mPreviewWindow, |
| mThumbnailBuffer[index]); |
| ALOGI(" enQ thumbnailbuffer"); |
| if( retVal != NO_ERROR) { |
| ALOGE("%s: Queuebuffer failed for postview buffer", __FUNCTION__); |
| } |
| |
| } |
| mDisplayLock.unlock(); |
| ALOGI("receiverawpicture : display unlock"); |
| /* Give the main Image as raw to upper layers */ |
| //Either CAMERA_MSG_RAW_IMAGE or CAMERA_MSG_RAW_IMAGE_NOTIFY will be set not both |
| if (mDataCallback && (mMsgEnabled & CAMERA_MSG_RAW_IMAGE)) |
| mDataCallback(CAMERA_MSG_RAW_IMAGE, mRawMapped[index],data_counter, |
| NULL, mCallbackCookie); |
| else if (mNotifyCallback && (mMsgEnabled & CAMERA_MSG_RAW_IMAGE_NOTIFY)) |
| mNotifyCallback(CAMERA_MSG_RAW_IMAGE_NOTIFY, 0, 0, |
| mCallbackCookie); |
| |
| if(strTexturesOn == true) { |
| ALOGI("Raw Data given to app for processing...will wait for jpeg encode call"); |
| mEncodePending = true; |
| mEncodePendingWaitLock.unlock(); |
| mJpegThreadWaitLock.lock(); |
| mJpegThreadWait.signal(); |
| mJpegThreadWaitLock.unlock(); |
| } |
| } else { // Not Jpeg snapshot, it is Raw Snapshot , handle later |
| ALOGV("ReceiveRawPicture : raw snapshot not Jpeg, sending callback up"); |
| if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) |
| mDataCallback(CAMERA_MSG_COMPRESSED_IMAGE, |
| mRawSnapshotMapped, |
| data_counter, |
| NULL, |
| mCallbackCookie); |
| |
| // TEMP |
| ALOGI("receiveRawPicture : gave raw frame to app, giving signal"); |
| mJpegThreadWaitLock.lock(); |
| mJpegThreadRunning = false; |
| mJpegThreadWait.signal(); |
| mJpegThreadWaitLock.unlock(); |
| |
| } |
| /* can start preview at this stage? early preview? */ |
| mInSnapshotModeWaitLock.lock(); |
| mInSnapshotMode = false; |
| mInSnapshotModeWait.signal(); |
| mInSnapshotModeWaitLock.unlock(); |
| |
| ALOGV("%s: X", __FUNCTION__); |
| |
| } |
| |
| |
| void QualcommCameraHardware::receiveJpegPicture(status_t status, mm_camera_buffer_t *encoded_buffer) |
| { |
| Mutex::Autolock cbLock(&mCallbackLock); |
| numJpegReceived++; |
| uint32_t offset ; |
| int32_t index = -1; |
| int32_t buffer_size = 0; |
| if(encoded_buffer && status == NO_ERROR) { |
| buffer_size = encoded_buffer->filled_size; |
| ALOGV("receiveJpegPicture: E buffer_size %d mJpegMaxSize = %d",buffer_size, mJpegMaxSize); |
| |
| index = mapJpegBuffer(encoded_buffer); |
| ALOGI("receiveJpegPicutre : mapJpegBuffer index : %d", index); |
| } |
| if((index < 0) || (index >= (MAX_SNAPSHOT_BUFFERS-2))){ |
| ALOGE("Jpeg index is not valid or fails. "); |
| if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) { |
| mDataCallback(CAMERA_MSG_COMPRESSED_IMAGE, NULL, data_counter, NULL, mCallbackCookie); |
| } |
| mJpegThreadWaitLock.lock(); |
| mJpegThreadRunning = false; |
| mJpegThreadWait.signal(); |
| mJpegThreadWaitLock.unlock(); |
| } else { |
| ALOGV("receiveJpegPicture: Index of Jpeg is %d",index); |
| |
| if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) { |
| if(status == NO_ERROR) { |
| ALOGI("receiveJpegPicture : giving jpeg image callback to services"); |
| mJpegCopyMapped = mGetMemory(-1, encoded_buffer->filled_size,1, mCallbackCookie); |
| if(!mJpegCopyMapped){ |
| ALOGE("%s: mGetMemory failed.\n", __func__); |
| } |
| memcpy(mJpegCopyMapped->data, mJpegMapped[index]->data, encoded_buffer->filled_size ); |
| mDataCallback(CAMERA_MSG_COMPRESSED_IMAGE,mJpegCopyMapped,data_counter,NULL,mCallbackCookie); |
| if(NULL != mJpegCopyMapped) { |
| mJpegCopyMapped->release(mJpegCopyMapped); |
| mJpegCopyMapped = NULL; |
| } |
| } |
| } else { |
| ALOGI("JPEG callback was cancelled--not delivering image."); |
| } |
| if(numJpegReceived == numCapture){ |
| mJpegThreadWaitLock.lock(); |
| mJpegThreadRunning = false; |
| mJpegThreadWait.signal(); |
| mJpegThreadWaitLock.unlock(); |
| } |
| } |
| |
| ALOGV("receiveJpegPicture: X callback done."); |
| } |
| bool QualcommCameraHardware::previewEnabled() |
| { |
| /* If overlay is used the message CAMERA_MSG_PREVIEW_FRAME would |
| * be disabled at CameraService layer. Hence previewEnabled would |
| * return FALSE even though preview is running. Hence check for |
| * mOverlay not being NULL to ensure that previewEnabled returns |
| * accurate information. |
| */ |
| |
| // return mCameraRunning && mDataCallback && |
| // ((mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME) || (mOverlay != NULL)); |
| ALOGI(" : mCameraRunning : %d mPreviewWindow = %x",mCameraRunning,mPreviewWindow); |
| return mCameraRunning;// || (mPreviewWindow != NULL); |
| } |
| status_t QualcommCameraHardware::setRecordSize(const QCameraParameters& params) |
| { |
| const char *recordSize = NULL; |
| recordSize = params.get(QCameraParameters::KEY_VIDEO_SIZE); |
| if(!recordSize) { |
| mParameters.set(QCameraParameters::KEY_VIDEO_SIZE, ""); |
| //If application didn't set this parameter string, use the values from |
| //getPreviewSize() as video dimensions. |
| ALOGV("No Record Size requested, use the preview dimensions"); |
| videoWidth = previewWidth; |
| videoHeight = previewHeight; |
| } else { |
| //Extract the record witdh and height that application requested. |
| ALOGI("%s: requested record size %s", __FUNCTION__, recordSize); |
| if(!parse_size(recordSize, videoWidth, videoHeight)) { |
| mParameters.set(QCameraParameters::KEY_VIDEO_SIZE , recordSize); |
| //VFE output1 shouldn't be greater than VFE output2. |
| if( (previewWidth > videoWidth) || (previewHeight > videoHeight)) { |
| //Set preview sizes as record sizes. |
| ALOGI("Preview size %dx%d is greater than record size %dx%d,\ |
| resetting preview size to record size",previewWidth,\ |
| previewHeight, videoWidth, videoHeight); |
| previewWidth = videoWidth; |
| previewHeight = videoHeight; |
| mParameters.setPreviewSize(previewWidth, previewHeight); |
| } |
| if( (mCurrentTarget != TARGET_MSM7630) |
| && (mCurrentTarget != TARGET_QSD8250) |
| && (mCurrentTarget != TARGET_MSM8660) ) { |
| //For Single VFE output targets, use record dimensions as preview dimensions. |
| previewWidth = videoWidth; |
| previewHeight = videoHeight; |
| mParameters.setPreviewSize(previewWidth, previewHeight); |
| } |
| if(mIs3DModeOn == true) { |
| /* As preview and video frames are same in 3D mode, |
| * preview size should be same as video size. This |
| * cahnge is needed to take of video resolutions |
| * like 720P and 1080p where the application can |
| * request different preview sizes like 768x432 |
| */ |
| previewWidth = videoWidth; |
| previewHeight = videoHeight; |
| mParameters.setPreviewSize(previewWidth, previewHeight); |
| } |
| } else { |
| mParameters.set(QCameraParameters::KEY_VIDEO_SIZE, ""); |
| ALOGE("initPreview X: failed to parse parameter record-size (%s)", recordSize); |
| return BAD_VALUE; |
| } |
| } |
| ALOGI("%s: preview dimensions: %dx%d", __FUNCTION__, previewWidth, previewHeight); |
| ALOGI("%s: video dimensions: %dx%d", __FUNCTION__, videoWidth, videoHeight); |
| mDimension.display_width = previewWidth; |
| mDimension.display_height= previewHeight; |
| return NO_ERROR; |
| } |
| |
| status_t QualcommCameraHardware::setCameraMode(const QCameraParameters& params) { |
| int32_t value = params.getInt(QCameraParameters::KEY_CAMERA_MODE); |
| mParameters.set(QCameraParameters::KEY_CAMERA_MODE,value); |
| |
| ALOGI("ZSL is enabled %d", value); |
| if( value != mZslEnable) { |
| mFrameThreadWaitLock.lock(); |
| while (mFrameThreadRunning) { |
| ALOGI("initPreview: waiting for old frame thread to complete."); |
| mFrameThreadWait.wait(mFrameThreadWaitLock); |
| ALOGI("initPreview: old frame thread completed."); |
| } |
| mFrameThreadWaitLock.unlock(); |
| } |
| if(value == 1) { |
| mZslEnable = true; |
| /* mParameters.set(QCameraParameters::KEY_SUPPORTED_FOCUS_MODES, |
| QCameraParameters::FOCUS_MODE_INFINITY); |
| mParameters.set(QCameraParameters::KEY_FOCUS_MODE, |
| QCameraParameters::FOCUS_MODE_INFINITY);*/ |
| }else{ |
| mZslEnable = false; |
| /*mParameters.set(QCameraParameters::KEY_SUPPORTED_FOCUS_MODES, |
| focus_mode_values); |
| mParameters.set(QCameraParameters::KEY_FOCUS_MODE, |
| QCameraParameters::FOCUS_MODE_AUTO);*/ |
| } |
| return NO_ERROR; |
| } |
| |
| status_t QualcommCameraHardware::setPreviewSize(const QCameraParameters& params) |
| { |
| int width, height; |
| params.getPreviewSize(&width, &height); |
| ALOGV("requested preview size %d x %d", width, height); |
| |
| // Validate the preview size |
| for (size_t i = 0; i < PREVIEW_SIZE_COUNT; ++i) { |
| if (width == preview_sizes[i].width |
| && height == preview_sizes[i].height) { |
| mParameters.setPreviewSize(width, height); |
| //previewWidth = width; |
| //previewHeight = height; |
| mDimension.display_width = width; |
| mDimension.display_height= height; |
| return NO_ERROR; |
| } |
| } |
| ALOGE("Invalid preview size requested: %dx%d", width, height); |
| return BAD_VALUE; |
| } |
| status_t QualcommCameraHardware::setPreviewFpsRange(const QCameraParameters& params) |
| { |
| int minFps,maxFps; |
| params.getPreviewFpsRange(&minFps,&maxFps); |
| ALOGI("FPS Range Values: %dx%d", minFps, maxFps); |
| |
| for(size_t i=0;i<FPS_RANGES_SUPPORTED_COUNT;i++) |
| { |
| if(minFps==FpsRangesSupported[i].minFPS && maxFps == FpsRangesSupported[i].maxFPS){ |
| mParameters.setPreviewFpsRange(minFps,maxFps); |
| return NO_ERROR; |
| } |
| } |
| return BAD_VALUE; |
| } |
| |
| status_t QualcommCameraHardware::setPreviewFrameRate(const QCameraParameters& params) |
| { |
| if( !mCfgControl.mm_camera_is_supported(CAMERA_PARM_FPS)){ |
| ALOGI("Set fps is not supported for this sensor"); |
| return NO_ERROR; |
| } |
| uint16_t previousFps = (uint16_t)mParameters.getPreviewFrameRate(); |
| uint16_t fps = (uint16_t)params.getPreviewFrameRate(); |
| ALOGV("requested preview frame rate is %u", fps); |
| |
| if(mInitialized && (fps == previousFps)){ |
| ALOGV("fps same as previous fps"); |
| return NO_ERROR; |
| } |
| |
| if(MINIMUM_FPS <= fps && fps <=MAXIMUM_FPS){ |
| mParameters.setPreviewFrameRate(fps); |
| bool ret = native_set_parms(CAMERA_PARM_FPS, |
| sizeof(fps), (void *)&fps); |
| return ret ? NO_ERROR : UNKNOWN_ERROR; |
| } |
| return BAD_VALUE; |
| } |
| |
| status_t QualcommCameraHardware::setPreviewFrameRateMode(const QCameraParameters& params) { |
| if( !mCfgControl.mm_camera_is_supported(CAMERA_PARM_FPS_MODE) && !mCfgControl.mm_camera_is_supported(CAMERA_PARM_FPS)){ |
| ALOGI("set fps mode is not supported for this sensor"); |
| return NO_ERROR; |
| } |
| |
| const char *previousMode = mParameters.getPreviewFrameRateMode(); |
| const char *str = params.getPreviewFrameRateMode(); |
| if( mInitialized && !strcmp(previousMode, str)) { |
| ALOGV("frame rate mode same as previous mode %s", previousMode); |
| return NO_ERROR; |
| } |
| int32_t frameRateMode = attr_lookup(frame_rate_modes, sizeof(frame_rate_modes) / sizeof(str_map),str); |
| if(frameRateMode != NOT_FOUND) { |
| ALOGV("setPreviewFrameRateMode: %s ", str); |
| mParameters.setPreviewFrameRateMode(str); |
| bool ret = native_set_parms(CAMERA_PARM_FPS_MODE, sizeof(frameRateMode), (void *)&frameRateMode); |
| if(!ret) return ret; |
| //set the fps value when chaging modes |
| int16_t fps = (uint16_t)params.getPreviewFrameRate(); |
| if(MINIMUM_FPS <= fps && fps <=MAXIMUM_FPS){ |
| mParameters.setPreviewFrameRate(fps); |
| ret = native_set_parms(CAMERA_PARM_FPS, |
| sizeof(fps), (void *)&fps); |
| return ret ? NO_ERROR : UNKNOWN_ERROR; |
| } |
| ALOGE("Invalid preview frame rate value: %d", fps); |
| return BAD_VALUE; |
| } |
| ALOGE("Invalid preview frame rate mode value: %s", (str == NULL) ? "NULL" : str); |
| return BAD_VALUE; |
| } |
| |
| status_t QualcommCameraHardware::setJpegThumbnailSize(const QCameraParameters& params){ |
| int width = params.getInt(QCameraParameters::KEY_JPEG_THUMBNAIL_WIDTH); |
| int height = params.getInt(QCameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT); |
| ALOGV("requested jpeg thumbnail size %d x %d", width, height); |
| |
| // Validate the picture size |
| for (unsigned int i = 0; i < JPEG_THUMBNAIL_SIZE_COUNT; ++i) { |
| if (width == jpeg_thumbnail_sizes[i].width |
| && height == jpeg_thumbnail_sizes[i].height) { |
| mParameters.set(QCameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, width); |
| mParameters.set(QCameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, height); |
| return NO_ERROR; |
| } |
| } |
| return BAD_VALUE; |
| } |
| |
| bool QualcommCameraHardware::updatePictureDimension(const QCameraParameters& params, int& width, int& height) |
| { |
| bool retval = false; |
| int previewWidth, previewHeight; |
| params.getPreviewSize(&previewWidth, &previewHeight); |
| ALOGV("updatePictureDimension: %dx%d <- %dx%d", width, height, |
| previewWidth, previewHeight); |
| if ((width < previewWidth) && (height < previewHeight)) { |
| /*As we donot support jpeg downscaling for picture dimension < previewdimesnion/8 , |
| Adding support for the same for cts testcases*/ |
| mActualPictWidth = width; |
| mActualPictHeight = height; |
| if((previewWidth /8) > width ) { |
| int ratio = previewWidth/width; |
| int i; |
| for(i =0 ; i < ratio ; i++) { |
| if((ratio >> i) < 8) |
| break; |
| } |
| width = width *i*2; |
| height = height *i*2; |
| } |
| else { |
| width = previewWidth; |
| height = previewHeight; |
| } |
| mUseJpegDownScaling = true; |
| retval = true; |
| } else |
| mUseJpegDownScaling = false; |
| return retval; |
| } |
| |
| status_t QualcommCameraHardware::setPictureSize(const QCameraParameters& params) |
| { |
| int width, height; |
| params.getPictureSize(&width, &height); |
| ALOGV("requested picture size %d x %d", width, height); |
| |
| // Validate the picture size |
| for (int i = 0; i < supportedPictureSizesCount; ++i) { |
| if (width == picture_sizes_ptr[i].width |
| && height == picture_sizes_ptr[i].height) { |
| mParameters.setPictureSize(width, height); |
| mDimension.picture_width = width; |
| mDimension.picture_height = height; |
| return NO_ERROR; |
| } |
| } |
| /* Dimension not among the ones in the list. Check if |
| * its a valid dimension, if it is, then configure the |
| * camera accordingly. else reject it. |
| */ |
| if( isValidDimension(width, height) ) { |
| mParameters.setPictureSize(width, height); |
| mDimension.picture_width = width; |
| mDimension.picture_height = height; |
| return NO_ERROR; |
| } else |
| ALOGE("Invalid picture size requested: %dx%d", width, height); |
| return BAD_VALUE; |
| } |
| |
| status_t QualcommCameraHardware::setJpegQuality(const QCameraParameters& params) { |
| status_t rc = NO_ERROR; |
| int quality = params.getInt(QCameraParameters::KEY_JPEG_QUALITY); |
| if (quality >= 0 && quality <= 100) { |
| mParameters.set(QCameraParameters::KEY_JPEG_QUALITY, quality); |
| } else { |
| ALOGE("Invalid jpeg quality=%d", quality); |
| rc = BAD_VALUE; |
| } |
| |
| quality = params.getInt(QCameraParameters::KEY_JPEG_THUMBNAIL_QUALITY); |
| if (quality >= 0 && quality <= 100) { |
| mParameters.set(QCameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, quality); |
| } else { |
| ALOGE("Invalid jpeg thumbnail quality=%d", quality); |
| rc = BAD_VALUE; |
| } |
| return rc; |
| } |
| |
| status_t QualcommCameraHardware::setEffect(const QCameraParameters& params) |
| { |
| const char *str = params.get(QCameraParameters::KEY_EFFECT); |
| int result; |
| |
| if (str != NULL) { |
| int32_t value = attr_lookup(effects, sizeof(effects) / sizeof(str_map), str); |
| if (value != NOT_FOUND) { |
| if( !mCfgControl.mm_camera_is_parm_supported(CAMERA_PARM_EFFECT, (void *) &value)){ |
| ALOGI("Camera Effect - %s mode is not supported for this sensor",str); |
| return NO_ERROR; |
| }else { |
| mParameters.set(QCameraParameters::KEY_EFFECT, str); |
| bool ret = native_set_parms(CAMERA_PARM_EFFECT, sizeof(value), |
| (void *)&value,(int *)&result); |
| if(result == MM_CAMERA_ERR_INVALID_OPERATION) { |
| ALOGI("Camera Effect: %s is not set as the selected value is not supported ", str); |
| } |
| return ret ? NO_ERROR : UNKNOWN_ERROR; |
| } |
| } |
| } |
| ALOGE("Invalid effect value: %s", (str == NULL) ? "NULL" : str); |
| return BAD_VALUE; |
| } |
| |
| status_t QualcommCameraHardware::setRecordingHint(const QCameraParameters& params) |
| { |
| |
| const char * str = params.get(QCameraParameters::KEY_RECORDING_HINT); |
| |
| if(str != NULL){ |
| int32_t value = attr_lookup(recording_Hints, |
| sizeof(recording_Hints) / sizeof(str_map), str); |
| if(value != NOT_FOUND){ |
| |
| native_set_parms(CAMERA_PARM_RECORDING_HINT, sizeof(value), |
| (void *)&value); |
| /*native_set_parms(CAMERA_PARM_CAF_ENABLE, sizeof(value), |
| (void *)&value);*/ |
| mParameters.set(QCameraParameters::KEY_RECORDING_HINT, str); |
| } else { |
| ALOGE("Invalid Picture Format value: %s", str); |
| return BAD_VALUE; |
| } |
| } |
| return NO_ERROR; |
| } |
| |
| status_t QualcommCameraHardware::setExposureCompensation( |
| const QCameraParameters & params){ |
| ALOGV("DEBBUG: %s E",__FUNCTION__); |
| if(!mCfgControl.mm_camera_is_supported(CAMERA_PARM_EXPOSURE_COMPENSATION)) { |
| ALOGI("Exposure Compensation is not supported for this sensor"); |
| return NO_ERROR; |
| } |
| |
| int numerator = params.getInt(QCameraParameters::KEY_EXPOSURE_COMPENSATION); |
| if(EXPOSURE_COMPENSATION_MINIMUM_NUMERATOR <= numerator && |
| numerator <= EXPOSURE_COMPENSATION_MAXIMUM_NUMERATOR){ |
| int16_t numerator16 = (int16_t)(numerator & 0x0000ffff); |
| uint16_t denominator16 = EXPOSURE_COMPENSATION_DENOMINATOR; |
| uint32_t value = 0; |
| value = numerator16 << 16 | denominator16; |
| |
| mParameters.set(QCameraParameters::KEY_EXPOSURE_COMPENSATION, |
| numerator); |
| bool ret = native_set_parms(CAMERA_PARM_EXPOSURE_COMPENSATION, |
| sizeof(value), (void *)&value); |
| ALOGI("DEBBUG: %s ret = %d X",__FUNCTION__, ret); |
| return ret ? NO_ERROR : UNKNOWN_ERROR; |
| } |
| ALOGE("Invalid Exposure Compensation"); |
| return BAD_VALUE; |
| } |
| |
| status_t QualcommCameraHardware::setAutoExposure(const QCameraParameters& params) |
| { |
| if(!mCfgControl.mm_camera_is_supported(CAMERA_PARM_EXPOSURE)) { |
| ALOGI("Auto Exposure not supported for this sensor"); |
| return NO_ERROR; |
| } |
| const char *str = params.get(QCameraParameters::KEY_AUTO_EXPOSURE); |
| if (str != NULL) { |
| int32_t value = attr_lookup(autoexposure, sizeof(autoexposure) / sizeof(str_map), str); |
| if (value != NOT_FOUND) { |
| mParameters.set(QCameraParameters::KEY_AUTO_EXPOSURE, str); |
| bool ret = native_set_parms(CAMERA_PARM_EXPOSURE, sizeof(value), |
| (void *)&value); |
| return ret ? NO_ERROR : UNKNOWN_ERROR; |
| } |
| } |
| ALOGE("Invalid auto exposure value: %s", (str == NULL) ? "NULL" : str); |
| return BAD_VALUE; |
| } |
| |
| status_t QualcommCameraHardware::setSharpness(const QCameraParameters& params) |
| { |
| if(!mCfgControl.mm_camera_is_supported(CAMERA_PARM_SHARPNESS)) { |
| ALOGI("Sharpness not supported for this sensor"); |
| return NO_ERROR; |
| } |
| int sharpness = params.getInt(QCameraParameters::KEY_SHARPNESS); |
| if((sharpness < CAMERA_MIN_SHARPNESS |
| || sharpness > CAMERA_MAX_SHARPNESS)) |
| return UNKNOWN_ERROR; |
| |
| ALOGV("setting sharpness %d", sharpness); |
| mParameters.set(QCameraParameters::KEY_SHARPNESS, sharpness); |
| bool ret = native_set_parms(CAMERA_PARM_SHARPNESS, sizeof(sharpness), |
| (void *)&sharpness); |
| return ret ? NO_ERROR : UNKNOWN_ERROR; |
| } |
| |
| status_t QualcommCameraHardware::setContrast(const QCameraParameters& params) |
| { |
| if(!mCfgControl.mm_camera_is_supported(CAMERA_PARM_CONTRAST)) { |
| ALOGI("Contrast not supported for this sensor"); |
| return NO_ERROR; |
| } |
| |
| const char *str = params.get(QCameraParameters::KEY_SCENE_MODE); |
| int32_t value = attr_lookup(scenemode, sizeof(scenemode) / sizeof(str_map), str); |
| |
| if(value == CAMERA_BESTSHOT_OFF) { |
| int contrast = params.getInt(QCameraParameters::KEY_CONTRAST); |
| if((contrast < CAMERA_MIN_CONTRAST) |
| || (contrast > CAMERA_MAX_CONTRAST)) |
| return UNKNOWN_ERROR; |
| |
| ALOGV("setting contrast %d", contrast); |
| mParameters.set(QCameraParameters::KEY_CONTRAST, contrast); |
| bool ret = native_set_parms(CAMERA_PARM_CONTRAST, sizeof(contrast), |
| (void *)&contrast); |
| return ret ? NO_ERROR : UNKNOWN_ERROR; |
| } else { |
| ALOGI(" Contrast value will not be set " \ |
| "when the scenemode selected is %s", str); |
| return NO_ERROR; |
| } |
| } |
| |
| status_t QualcommCameraHardware::setSaturation(const QCameraParameters& params) |
| { |
| if(!mCfgControl.mm_camera_is_supported(CAMERA_PARM_SATURATION)) { |
| ALOGI("Saturation not supported for this sensor"); |
| return NO_ERROR; |
| } |
| int result; |
| int saturation = params.getInt(QCameraParameters::KEY_SATURATION); |
| |
| if((saturation < CAMERA_MIN_SATURATION) |
| || (saturation > CAMERA_MAX_SATURATION)) |
| return UNKNOWN_ERROR; |
| |
| ALOGV("Setting saturation %d", saturation); |
| mParameters.set(QCameraParameters::KEY_SATURATION, saturation); |
| bool ret = native_set_parms(CAMERA_PARM_SATURATION, sizeof(saturation), |
| (void *)&saturation, (int *)&result); |
| if(result == MM_CAMERA_ERR_INVALID_OPERATION) |
| ALOGI("Saturation Value: %d is not set as the selected value is not supported", saturation); |
| |
| return ret ? NO_ERROR : UNKNOWN_ERROR; |
| } |
| |
| status_t QualcommCameraHardware::setPreviewFormat(const QCameraParameters& params) { |
| const char *str = params.getPreviewFormat(); |
| int32_t previewFormat = attr_lookup(preview_formats, sizeof(preview_formats) / sizeof(str_map), str); |
| if(previewFormat != NOT_FOUND) { |
| mParameters.set(QCameraParameters::KEY_PREVIEW_FORMAT, str); |
| mPreviewFormat = previewFormat; |
| if(HAL_currentCameraMode != CAMERA_MODE_3D) { |
| ALOGI("Setting preview format to native"); |
| bool ret = native_set_parms(CAMERA_PARM_PREVIEW_FORMAT, sizeof(previewFormat), |
| (void *)&previewFormat); |
| }else{ |
| ALOGI("Skipping set preview format call to native"); |
| } |
| return NO_ERROR; |
| } |
| ALOGE("Invalid preview format value: %s", (str == NULL) ? "NULL" : str); |
| return BAD_VALUE; |
| } |
| |
| status_t QualcommCameraHardware::setStrTextures(const QCameraParameters& params) { |
| const char *str = params.get("strtextures"); |
| if(str != NULL) { |
| ALOGV("strtextures = %s", str); |
| mParameters.set("strtextures", str); |
| if(!strncmp(str, "on", 2) || !strncmp(str, "ON", 2)) { |
| strTexturesOn = true; |
| } else if (!strncmp(str, "off", 3) || !strncmp(str, "OFF", 3)) { |
| strTexturesOn = false; |
| } |
| } |
| return NO_ERROR; |
| } |
| |
| status_t QualcommCameraHardware::setBrightness(const QCameraParameters& params) { |
| if(!mCfgControl.mm_camera_is_supported(CAMERA_PARM_BRIGHTNESS)) { |
| ALOGI("Set Brightness not supported for this sensor"); |
| return NO_ERROR; |
| } |
| int brightness = params.getInt("luma-adaptation"); |
| if (mBrightness != brightness) { |
| ALOGV(" new brightness value : %d ", brightness); |
| mBrightness = brightness; |
| mParameters.set("luma-adaptation", brightness); |
| bool ret = native_set_parms(CAMERA_PARM_BRIGHTNESS, sizeof(mBrightness), |
| (void *)&mBrightness); |
| return ret ? NO_ERROR : UNKNOWN_ERROR; |
| } |
| return NO_ERROR; |
| } |
| |
| status_t QualcommCameraHardware::setSkinToneEnhancement(const QCameraParameters& params) { |
| if(!mCfgControl.mm_camera_is_supported(CAMERA_PARM_SCE_FACTOR)) { |
| ALOGI("SkinToneEnhancement not supported for this sensor"); |
| return NO_ERROR; |
| } |
| int skinToneValue = params.getInt("skinToneEnhancement"); |
| if (mSkinToneEnhancement != skinToneValue) { |
| ALOGV(" new skinTone correction value : %d ", skinToneValue); |
| mSkinToneEnhancement = skinToneValue; |
| mParameters.set("skinToneEnhancement", skinToneValue); |
| bool ret = native_set_parms(CAMERA_PARM_SCE_FACTOR, sizeof(mSkinToneEnhancement), |
| (void *)&mSkinToneEnhancement); |
| return ret ? NO_ERROR : UNKNOWN_ERROR; |
| } |
| return NO_ERROR; |
| } |
| |
| status_t QualcommCameraHardware::setWhiteBalance(const QCameraParameters& params) |
| { |
| if(!mCfgControl.mm_camera_is_supported(CAMERA_PARM_WHITE_BALANCE)) { |
| ALOGI("WhiteBalance not supported for this sensor"); |
| return NO_ERROR; |
| } |
| |
| int result; |
| |
| const char *str = params.get(QCameraParameters::KEY_WHITE_BALANCE); |
| if (str != NULL) { |
| int32_t value = attr_lookup(whitebalance, sizeof(whitebalance) / sizeof(str_map), str); |
| if (value != NOT_FOUND) { |
| mParameters.set(QCameraParameters::KEY_WHITE_BALANCE, str); |
| bool ret = native_set_parms(CAMERA_PARM_WHITE_BALANCE, sizeof(value), |
| (void *)&value, (int *)&result); |
| if(result == MM_CAMERA_ERR_INVALID_OPERATION) { |
| ALOGI("WhiteBalance Value: %s is not set as the selected value is not supported ", str); |
| } |
| return ret ? NO_ERROR : UNKNOWN_ERROR; |
| } |
| } |
| ALOGE("Invalid whitebalance value: %s", (str == NULL) ? "NULL" : str); |
| return BAD_VALUE; |
| |
| } |
| |
| status_t QualcommCameraHardware::setFlash(const QCameraParameters& params) |
| { |
| if(!mCfgControl.mm_camera_is_supported(CAMERA_PARM_LED_MODE)) { |
| ALOGI("%s: flash not supported", __FUNCTION__); |
| return NO_ERROR; |
| } |
| |
| const char *str = params.get(QCameraParameters::KEY_FLASH_MODE); |
| if (str != NULL) { |
| int32_t value = attr_lookup(flash, sizeof(flash) / sizeof(str_map), str); |
| if (value != NOT_FOUND) { |
| mParameters.set(QCameraParameters::KEY_FLASH_MODE, str); |
| bool ret = native_set_parms(CAMERA_PARM_LED_MODE, |
| sizeof(value), (void *)&value); |
| if(mZslEnable && (value != LED_MODE_OFF)){ |
| mParameters.set("num-snaps-per-shutter", "1"); |
| ALOGI("%s Setting num-snaps-per-shutter to 1", __FUNCTION__); |
| numCapture = 1; |
| } |
| return ret ? NO_ERROR : UNKNOWN_ERROR; |
| } |
| } |
| ALOGE("Invalid flash mode value: %s", (str == NULL) ? "NULL" : str); |
| return BAD_VALUE; |
| } |
| |
| status_t QualcommCameraHardware::setAntibanding(const QCameraParameters& params) |
| { |
| int result; |
| if(!mCfgControl.mm_camera_is_supported(CAMERA_PARM_ANTIBANDING)) { |
| ALOGI("Parameter AntiBanding is not supported for this sensor"); |
| return NO_ERROR; |
| } |
| const char *str = params.get(QCameraParameters::KEY_ANTIBANDING); |
| if (str != NULL) { |
| int value = (camera_antibanding_type)attr_lookup( |
| antibanding, sizeof(antibanding) / sizeof(str_map), str); |
| if (value != NOT_FOUND) { |
| camera_antibanding_type temp = (camera_antibanding_type) value; |
| mParameters.set(QCameraParameters::KEY_ANTIBANDING, str); |
| bool ret = native_set_parms(CAMERA_PARM_ANTIBANDING, |
| sizeof(camera_antibanding_type), (void *)&temp ,(int *)&result); |
| if(result == MM_CAMERA_ERR_INVALID_OPERATION) { |
| ALOGI("AntiBanding Value: %s is not supported for the given BestShot Mode", str); |
| } |
| return ret ? NO_ERROR : UNKNOWN_ERROR; |
| } |
| } |
| ALOGE("Invalid antibanding value: %s", (str == NULL) ? "NULL" : str); |
| return BAD_VALUE; |
| } |
| |
| status_t QualcommCameraHardware::setMCEValue(const QCameraParameters& params) |
| { |
| if(!mCfgControl.mm_camera_is_supported(CAMERA_PARM_MCE)) { |
| ALOGI("Parameter MCE is not supported for this sensor"); |
| return NO_ERROR; |
| } |
| |
| const char *str = params.get(QCameraParameters::KEY_MEMORY_COLOR_ENHANCEMENT); |
| if (str != NULL) { |
| int value = attr_lookup(mce, sizeof(mce) / sizeof(str_map), str); |
| if (value != NOT_FOUND) { |
| int8_t temp = (int8_t)value; |
| ALOGI("%s: setting MCE value of %s", __FUNCTION__, str); |
| mParameters.set(QCameraParameters::KEY_MEMORY_COLOR_ENHANCEMENT, str); |
| |
| native_set_parms(CAMERA_PARM_MCE, sizeof(int8_t), (void *)&temp); |
| return NO_ERROR; |
| } |
| } |
| ALOGE("Invalid MCE value: %s", (str == NULL) ? "NULL" : str); |
| return BAD_VALUE; |
| } |
| |
| status_t QualcommCameraHardware::setHighFrameRate(const QCameraParameters& params) |
| { |
| if((!mCfgControl.mm_camera_is_supported(CAMERA_PARM_HFR)) || (mIs3DModeOn)) { |
| ALOGI("Parameter HFR is not supported for this sensor"); |
| return NO_ERROR; |
| } |
| |
| const char *str = params.get(QCameraParameters::KEY_VIDEO_HIGH_FRAME_RATE); |
| if (str != NULL) { |
| int value = attr_lookup(hfr, sizeof(hfr) / sizeof(str_map), str); |
| if (value != NOT_FOUND) { |
| int32_t temp = (int32_t)value; |
| ALOGI("%s: setting HFR value of %s(%d)", __FUNCTION__, str, temp); |
| //Check for change in HFR value |
| const char *oldHfr = mParameters.get(QCameraParameters::KEY_VIDEO_HIGH_FRAME_RATE); |
| if(strcmp(oldHfr, str)){ |
| ALOGI("%s: old HFR: %s, new HFR %s", __FUNCTION__, oldHfr, str); |
| mParameters.set(QCameraParameters::KEY_VIDEO_HIGH_FRAME_RATE, str); |
| mHFRMode = true; |
| if(mCameraRunning == true) { |
| mHFRThreadWaitLock.lock(); |
| pthread_attr_t pattr; |
| pthread_attr_init(&pattr); |
| pthread_attr_setdetachstate(&pattr, PTHREAD_CREATE_DETACHED); |
| mHFRThreadRunning = !pthread_create(&mHFRThread, |
| &pattr, |
| hfr_thread, |
| (void*)NULL); |
| mHFRThreadWaitLock.unlock(); |
| return NO_ERROR; |
| } |
| } |
| native_set_parms(CAMERA_PARM_HFR, sizeof(int32_t), (void *)&temp); |
| return NO_ERROR; |
| } |
| } |
| ALOGE("Invalid HFR value: %s", (str == NULL) ? "NULL" : str); |
| return BAD_VALUE; |
| } |
| |
| status_t QualcommCameraHardware::setHDRImaging(const QCameraParameters& params) |
| { |
| if(!mCfgControl.mm_camera_is_supported(CAMERA_PARM_HDR) && mZslEnable) { |
| ALOGI("Parameter HDR is not supported for this sensor/ ZSL mode"); |
| return NO_ERROR; |
| } |
| const char *str = params.get(QCameraParameters::KEY_HIGH_DYNAMIC_RANGE_IMAGING); |
| if (str != NULL) { |
| int value = attr_lookup(hdr, sizeof(hdr) / sizeof(str_map), str); |
| if (value != NOT_FOUND) { |
| exp_bracketing_t temp; |
| memset(&temp, 0, sizeof(temp)); |
| temp.hdr_enable= (int32_t)value; |
| temp.mode = HDR_MODE; |
| temp.total_frames = 3; |
| temp.total_hal_frames = HDR_HAL_FRAME; |
| mHdrMode = temp.hdr_enable; |
| ALOGI("%s: setting HDR value of %s", __FUNCTION__, str); |
| mParameters.set(QCameraParameters::KEY_HIGH_DYNAMIC_RANGE_IMAGING, str); |
| if(mHdrMode){ |
| numCapture = temp.total_hal_frames; |
| } else |
| numCapture = 1; |
| native_set_parms(CAMERA_PARM_HDR, sizeof(exp_bracketing_t), (void *)&temp); |
| return NO_ERROR; |
| } |
| } |
| ALOGE("Invalid HDR value: %s", (str == NULL) ? "NULL" : str); |
| return BAD_VALUE; |
| } |
| |
| status_t QualcommCameraHardware::setExpBracketing(const QCameraParameters& params) |
| { |
| if(!mCfgControl.mm_camera_is_supported(CAMERA_PARM_HDR) && mZslEnable) { |
| ALOGI("Parameter Exposure Bracketing is not supported for this sensor/ZSL mode"); |
| return NO_ERROR; |
| } |
| const char *str = params.get("capture-burst-exposures"); |
| if ((str != NULL) && (!mHdrMode)) { |
| char exp_val[MAX_EXP_BRACKETING_LENGTH]; |
| exp_bracketing_t temp; |
| memset(&temp, 0, sizeof(temp)); |
| |
| mExpBracketMode = true; |
| temp.mode = EXP_BRACKETING_MODE; |
| temp.hdr_enable = true; |
| /* App sets values separated by comma. |
| Thus total number of snapshot to capture is strlen(str)/2 |
| eg: "-1,1,2" */ |
| strlcpy(exp_val, str, sizeof(exp_val)); |
| temp.total_frames = (strlen(exp_val) > MAX_SNAPSHOT_BUFFERS -2) ? |
| MAX_SNAPSHOT_BUFFERS -2 : strlen(exp_val); |
| temp.total_hal_frames = temp.total_frames; |
| strlcpy(temp.values, exp_val, MAX_EXP_BRACKETING_LENGTH); |
| ALOGI("%s: setting Exposure Bracketing value of %s", __FUNCTION__, temp.values); |
| mParameters.set("capture-burst-exposures", str); |
| if(!mZslEnable){ |
| numCapture = temp.total_frames; |
| } |
| native_set_parms(CAMERA_PARM_HDR, sizeof(exp_bracketing_t), (void *)&temp); |
| return NO_ERROR; |
| } else |
| mExpBracketMode = false; |
| return NO_ERROR; |
| } |
| |
| status_t QualcommCameraHardware::setLensshadeValue(const QCameraParameters& params) |
| { |
| if(!mCfgControl.mm_camera_is_supported(CAMERA_PARM_ROLLOFF)) { |
| ALOGI("Parameter Rolloff is not supported for this sensor"); |
| return NO_ERROR; |
| } |
| |
| const char *str = params.get(QCameraParameters::KEY_LENSSHADE); |
| if (str != NULL) { |
| int value = attr_lookup(lensshade, |
| sizeof(lensshade) / sizeof(str_map), str); |
| if (value != NOT_FOUND) { |
| int8_t temp = (int8_t)value; |
| mParameters.set(QCameraParameters::KEY_LENSSHADE, str); |
| |
| native_set_parms(CAMERA_PARM_ROLLOFF, sizeof(int8_t), (void *)&temp); |
| return NO_ERROR; |
| } |
| } |
| ALOGE("Invalid lensShade value: %s", (str == NULL) ? "NULL" : str); |
| return NO_ERROR; |
| } |
| |
| status_t QualcommCameraHardware::setSelectableZoneAf(const QCameraParameters& params) |
| { |
| if(mHasAutoFocusSupport && supportsSelectableZoneAf()) { |
| const char *str = params.get(QCameraParameters::KEY_SELECTABLE_ZONE_AF); |
| if (str != NULL) { |
| int32_t value = attr_lookup(selectable_zone_af, sizeof(selectable_zone_af) / sizeof(str_map), str); |
| if (value != NOT_FOUND) { |
| mParameters.set(QCameraParameters::KEY_SELECTABLE_ZONE_AF, str); |
| bool ret = native_set_parms(CAMERA_PARM_FOCUS_RECT, sizeof(value), |
| (void *)&value); |
| return ret ? NO_ERROR : UNKNOWN_ERROR; |
| } |
| } |
| ALOGE("Invalid selectable zone af value: %s", (str == NULL) ? "NULL" : str); |
| return BAD_VALUE; |
| } |
| return NO_ERROR; |
| } |
| |
| status_t QualcommCameraHardware::setTouchAfAec(const QCameraParameters& params) |
| { |
| ALOGV("%s",__func__); |
| if(mHasAutoFocusSupport){ |
| int xAec, yAec, xAf, yAf; |
| int cx, cy; |
| int width, height; |
| params.getMeteringAreaCenter(&cx, &cy); |
| mParameters.getPreviewSize(&width, &height); |
| |
| // @Punit |
| // The coords sent from upper layer is in range (-1000, -1000) to (1000, 1000) |
| // So, they are transformed to range (0, 0) to (previewWidth, previewHeight) |
| cx = cx + 1000; |
| cy = cy + 1000; |
| cx = cx * (width / 2000.0f); |
| cy = cy * (height / 2000.0f); |
| |
| //Negative values are invalid and does not update anything |
| ALOGV("Touch Area Center (cx, cy) = (%d, %d)", cx, cy); |
| |
| //Currently using same values for AF and AEC |
| xAec = cx; yAec = cy; |
| xAf = cx; yAf = cy; |
| |
| const char *str = params.get(QCameraParameters::KEY_TOUCH_AF_AEC); |
| if (str != NULL) { |
| int value = attr_lookup(touchafaec, |
| sizeof(touchafaec) / sizeof(str_map), str); |
| if (value != NOT_FOUND) { |
| |
| //Dx,Dy will be same as defined in res/layout/camera.xml |
| //passed down to HAL in a key.value pair. |
| int FOCUS_RECTANGLE_DX = params.getInt("touchAfAec-dx"); |
| int FOCUS_RECTANGLE_DY = params.getInt("touchAfAec-dy"); |
| mParameters.set(QCameraParameters::KEY_TOUCH_AF_AEC, str); |
| mParameters.setTouchIndexAec(xAec, yAec); |
| mParameters.setTouchIndexAf(xAf, yAf); |
| |
| cam_set_aec_roi_t aec_roi_value; |
| roi_info_t af_roi_value; |
| |
| memset(&af_roi_value, 0, sizeof(roi_info_t)); |
| |
| //If touch AF/AEC is enabled and touch event has occured then |
| //call the ioctl with valid values. |
| if (value == true |
| && (xAec >= 0 && yAec >= 0) |
| && (xAf >= 0 && yAf >= 0)) { |
| //Set Touch AEC params (Pass the center co-ordinate) |
| aec_roi_value.aec_roi_enable = AEC_ROI_ON; |
| aec_roi_value.aec_roi_type = AEC_ROI_BY_COORDINATE; |
| aec_roi_value.aec_roi_position.coordinate.x = xAec; |
| aec_roi_value.aec_roi_position.coordinate.y = yAec; |
| |
| //Set Touch AF params (Pass the top left co-ordinate) |
| af_roi_value.num_roi = 1; |
| if ((xAf-(FOCUS_RECTANGLE_DX/2)) < 0) |
| af_roi_value.roi[0].x = 1; |
| else |
| af_roi_value.roi[0].x = xAf - (FOCUS_RECTANGLE_DX/2); |
| |
| if ((yAf-(FOCUS_RECTANGLE_DY/2)) < 0) |
| af_roi_value.roi[0].y = 1; |
| else |
| af_roi_value.roi[0].y = yAf - (FOCUS_RECTANGLE_DY/2); |
| |
| af_roi_value.roi[0].dx = FOCUS_RECTANGLE_DX; |
| af_roi_value.roi[0].dy = FOCUS_RECTANGLE_DY; |
| af_roi_value.is_multiwindow = mMultiTouch; |
| native_set_parms(CAMERA_PARM_AEC_ROI, sizeof(cam_set_aec_roi_t), (void *)&aec_roi_value); |
| native_set_parms(CAMERA_PARM_AF_ROI, sizeof(roi_info_t), (void*)&af_roi_value); |
| } |
| else if(value == false) { |
| //Set Touch AEC params |
| aec_roi_value.aec_roi_enable = AEC_ROI_OFF; |
| aec_roi_value.aec_roi_type = AEC_ROI_BY_COORDINATE; |
| aec_roi_value.aec_roi_position.coordinate.x = DONT_CARE_COORDINATE; |
| aec_roi_value.aec_roi_position.coordinate.y = DONT_CARE_COORDINATE; |
| |
| //Set Touch AF params |
| af_roi_value.num_roi = 0; |
| native_set_parms(CAMERA_PARM_AEC_ROI, sizeof(cam_set_aec_roi_t), (void *)&aec_roi_value); |
| native_set_parms(CAMERA_PARM_AF_ROI, sizeof(roi_info_t), (void*)&af_roi_value); |
| } |
| //@Punit: If the values are negative, we dont send anything to the lower layer |
| } |
| return NO_ERROR; |
| } |
| ALOGE("Invalid Touch AF/AEC value: %s", (str == NULL) ? "NULL" : str); |
| return BAD_VALUE; |
| } |
| return NO_ERROR; |
| } |
| |
| status_t QualcommCameraHardware::setFaceDetection(const char *str) |
| { |
| if(supportsFaceDetection() == false){ |
| ALOGI("Face detection is not enabled"); |
| return NO_ERROR; |
| } |
| if (str != NULL) { |
| int value = attr_lookup(facedetection, |
| sizeof(facedetection) / sizeof(str_map), str); |
| if (value != NOT_FOUND) { |
| mMetaDataWaitLock.lock(); |
| mFaceDetectOn = value; |
| mMetaDataWaitLock.unlock(); |
| mParameters.set(QCameraParameters::KEY_FACE_DETECTION, str); |
| return NO_ERROR; |
| } |
| } |
| ALOGE("Invalid Face Detection value: %s", (str == NULL) ? "NULL" : str); |
| return BAD_VALUE; |
| } |
| |
| status_t QualcommCameraHardware::setRedeyeReduction(const QCameraParameters& params) |
| { |
| if(!mCfgControl.mm_camera_is_supported(CAMERA_PARM_REDEYE_REDUCTION)) { |
| ALOGI("Parameter Redeye Reduction is not supported for this sensor"); |
| return NO_ERROR; |
| } |
| |
| const char *str = params.get(QCameraParameters::KEY_REDEYE_REDUCTION); |
| if (str != NULL) { |
| int value = attr_lookup(redeye_reduction, sizeof(redeye_reduction) / sizeof(str_map), str); |
| if (value != NOT_FOUND) { |
| int8_t temp = (int8_t)value; |
| ALOGI("%s: setting Redeye Reduction value of %s", __FUNCTION__, str); |
| mParameters.set(QCameraParameters::KEY_REDEYE_REDUCTION, str); |
| |
| native_set_parms(CAMERA_PARM_REDEYE_REDUCTION, sizeof(int8_t), (void *)&temp); |
| return NO_ERROR; |
| } |
| } |
| ALOGE("Invalid Redeye Reduction value: %s", (str == NULL) ? "NULL" : str); |
| return BAD_VALUE; |
| } |
| |
| status_t QualcommCameraHardware::setISOValue(const QCameraParameters& params) { |
| int8_t temp_hjr; |
| if(!mCfgControl.mm_camera_is_supported(CAMERA_PARM_ISO)) { |
| ALOGI("Parameter ISO Value is not supported for this sensor"); |
| return NO_ERROR; |
| } |
| const char *str = params.get(QCameraParameters::KEY_ISO_MODE); |
| if (str != NULL) { |
| int value = (camera_iso_mode_type)attr_lookup( |
| iso, sizeof(iso) / sizeof(str_map), str); |
| if (value != NOT_FOUND) { |
| camera_iso_mode_type temp = (camera_iso_mode_type) value; |
| if (value == CAMERA_ISO_DEBLUR) { |
| temp_hjr = true; |
| native_set_parms(CAMERA_PARM_HJR, sizeof(int8_t), (void*)&temp_hjr); |
| mHJR = value; |
| } |
| else { |
| if (mHJR == CAMERA_ISO_DEBLUR) { |
| temp_hjr = false; |
| native_set_parms(CAMERA_PARM_HJR, sizeof(int8_t), (void*)&temp_hjr); |
| mHJR = value; |
| } |
| } |
| |
| mParameters.set(QCameraParameters::KEY_ISO_MODE, str); |
| native_set_parms(CAMERA_PARM_ISO, sizeof(camera_iso_mode_type), (void *)&temp); |
| return NO_ERROR; |
| } |
| } |
| ALOGE("Invalid Iso value: %s", (str == NULL) ? "NULL" : str); |
| return BAD_VALUE; |
| } |
| |
| status_t QualcommCameraHardware::setSceneDetect(const QCameraParameters& params) |
| { |
| bool retParm1, retParm2; |
| if (supportsSceneDetection()) { |
| if(!mCfgControl.mm_camera_is_supported(CAMERA_PARM_BL_DETECTION) && !mCfgControl.mm_camera_is_supported(CAMERA_PARM_SNOW_DETECTION)) { |
| ALOGI("Parameter Auto Scene Detection is not supported for this sensor"); |
| return NO_ERROR; |
| } |
| const char *str = params.get(QCameraParameters::KEY_SCENE_DETECT); |
| if (str != NULL) { |
| int32_t value = attr_lookup(scenedetect, sizeof(scenedetect) / sizeof(str_map), str); |
| if (value != NOT_FOUND) { |
| mParameters.set(QCameraParameters::KEY_SCENE_DETECT, str); |
| |
| retParm1 = native_set_parms(CAMERA_PARM_BL_DETECTION, sizeof(value), |
| (void *)&value); |
| |
| retParm2 = native_set_parms(CAMERA_PARM_SNOW_DETECTION, sizeof(value), |
| (void *)&value); |
| |
| //All Auto Scene detection modes should be all ON or all OFF. |
| if(retParm1 == false || retParm2 == false) { |
| value = !value; |
| retParm1 = native_set_parms(CAMERA_PARM_BL_DETECTION, sizeof(value), |
| (void *)&value); |
| |
| retParm2 = native_set_parms(CAMERA_PARM_SNOW_DETECTION, sizeof(value), |
| (void *)&value); |
| } |
| return (retParm1 && retParm2) ? NO_ERROR : UNKNOWN_ERROR; |
| } |
| } |
| ALOGE("Invalid auto scene detection value: %s", (str == NULL) ? "NULL" : str); |
| return BAD_VALUE; |
| } |
| return NO_ERROR; |
| } |
| |
| status_t QualcommCameraHardware::setSceneMode(const QCameraParameters& params) |
| { |
| if(!mCfgControl.mm_camera_is_supported(CAMERA_PARM_BESTSHOT_MODE)) { |
| ALOGI("Parameter Scenemode is not supported for this sensor"); |
| return NO_ERROR; |
| } |
| |
| const char *str = params.get(QCameraParameters::KEY_SCENE_MODE); |
| |
| if (str != NULL) { |
| int32_t value = attr_lookup(scenemode, sizeof(scenemode) / sizeof(str_map), str); |
| int32_t asd_val; |
| if (value != NOT_FOUND) { |
| mParameters.set(QCameraParameters::KEY_SCENE_MODE, str); |
| bool ret = native_set_parms(CAMERA_PARM_BESTSHOT_MODE, sizeof(value), |
| (void *)&value); |
| |
| if (ret == NO_ERROR) { |
| int retParm1, retParm2; |
| /*if value is auto, set ASD on, else set ASD off*/ |
| if (value == CAMERA_BESTSHOT_AUTO ) { |
| asd_val = TRUE; |
| } else { |
| asd_val = FALSE; |
| } |
| |
| /*note: we need to simplify this logic by using a single ctrl as in 8960*/ |
| retParm1 = native_set_parms(CAMERA_PARM_BL_DETECTION, sizeof(value), |
| (void *)&asd_val); |
| retParm2 = native_set_parms(CAMERA_PARM_SNOW_DETECTION, sizeof(value), |
| (void *)&asd_val); |
| } |
| return ret ? NO_ERROR : UNKNOWN_ERROR; |
| } |
| } |
| ALOGE("Invalid scenemode value: %s", (str == NULL) ? "NULL" : str); |
| return BAD_VALUE; |
| } |
| status_t QualcommCameraHardware::setGpsLocation(const QCameraParameters& params) |
| { |
| const char *method = params.get(QCameraParameters::KEY_GPS_PROCESSING_METHOD); |
| if (method) { |
| mParameters.set(QCameraParameters::KEY_GPS_PROCESSING_METHOD, method); |
| }else { |
| mParameters.remove(QCameraParameters::KEY_GPS_PROCESSING_METHOD); |
| } |
| |
| const char *latitude = params.get(QCameraParameters::KEY_GPS_LATITUDE); |
| if (latitude) { |
| ALOGI("latitude %s",latitude); |
| mParameters.set(QCameraParameters::KEY_GPS_LATITUDE, latitude); |
| }else { |
| mParameters.remove(QCameraParameters::KEY_GPS_LATITUDE); |
| } |
| |
| const char *latitudeRef = params.get(QCameraParameters::KEY_GPS_LATITUDE_REF); |
| if (latitudeRef) { |
| mParameters.set(QCameraParameters::KEY_GPS_LATITUDE_REF, latitudeRef); |
| }else { |
| mParameters.remove(QCameraParameters::KEY_GPS_LATITUDE_REF); |
| } |
| |
| const char *longitude = params.get(QCameraParameters::KEY_GPS_LONGITUDE); |
| if (longitude) { |
| mParameters.set(QCameraParameters::KEY_GPS_LONGITUDE, longitude); |
| }else { |
| mParameters.remove(QCameraParameters::KEY_GPS_LONGITUDE); |
| } |
| |
| const char *longitudeRef = params.get(QCameraParameters::KEY_GPS_LONGITUDE_REF); |
| if (longitudeRef) { |
| mParameters.set(QCameraParameters::KEY_GPS_LONGITUDE_REF, longitudeRef); |
| }else { |
| mParameters.remove(QCameraParameters::KEY_GPS_LONGITUDE_REF); |
| } |
| |
| const char *altitudeRef = params.get(QCameraParameters::KEY_GPS_ALTITUDE_REF); |
| if (altitudeRef) { |
| mParameters.set(QCameraParameters::KEY_GPS_ALTITUDE_REF, altitudeRef); |
| }else { |
| mParameters.remove(QCameraParameters::KEY_GPS_ALTITUDE_REF); |
| } |
| |
| const char *altitude = params.get(QCameraParameters::KEY_GPS_ALTITUDE); |
| if (altitude) { |
| mParameters.set(QCameraParameters::KEY_GPS_ALTITUDE, altitude); |
| }else { |
| mParameters.remove(QCameraParameters::KEY_GPS_ALTITUDE); |
| } |
| |
| const char *status = params.get(QCameraParameters::KEY_GPS_STATUS); |
| if (status) { |
| mParameters.set(QCameraParameters::KEY_GPS_STATUS, status); |
| } |
| |
| const char *dateTime = params.get(QCameraParameters::KEY_EXIF_DATETIME); |
| if (dateTime) { |
| mParameters.set(QCameraParameters::KEY_EXIF_DATETIME, dateTime); |
| }else { |
| mParameters.remove(QCameraParameters::KEY_EXIF_DATETIME); |
| } |
| |
| const char *timestamp = params.get(QCameraParameters::KEY_GPS_TIMESTAMP); |
| if (timestamp) { |
| mParameters.set(QCameraParameters::KEY_GPS_TIMESTAMP, timestamp); |
| }else { |
| mParameters.remove(QCameraParameters::KEY_GPS_TIMESTAMP); |
| } |
| |
| return NO_ERROR; |
| |
| } |
| |
| status_t QualcommCameraHardware::setRotation(const QCameraParameters& params) |
| { |
| status_t rc = NO_ERROR; |
| int sensor_mount_angle = HAL_cameraInfo[HAL_currentCameraId].sensor_mount_angle; |
| int rotation = params.getInt(QCameraParameters::KEY_ROTATION); |
| if (rotation != NOT_FOUND) { |
| if (rotation == 0 || rotation == 90 || rotation == 180 |
| || rotation == 270) { |
| rotation = (rotation + sensor_mount_angle)%360; |
| mParameters.set(QCameraParameters::KEY_ROTATION, rotation); |
| mRotation = rotation; |
| } else { |
| ALOGE("Invalid rotation value: %d", rotation); |
| rc = BAD_VALUE; |
| } |
| } |
| return rc; |
| } |
| |
| status_t QualcommCameraHardware::setZoom(const QCameraParameters& params) |
| { |
| if(!mCfgControl.mm_camera_is_supported(CAMERA_PARM_ZOOM)) { |
| ALOGI("Parameter setZoom is not supported for this sensor"); |
| return NO_ERROR; |
| } |
| status_t rc = NO_ERROR; |
| // No matter how many different zoom values the driver can provide, HAL |
| // provides applictations the same number of zoom levels. The maximum driver |
| // zoom value depends on sensor output (VFE input) and preview size (VFE |
| // output) because VFE can only crop and cannot upscale. If the preview size |
| // is bigger, the maximum zoom ratio is smaller. However, we want the |
| // zoom ratio of each zoom level is always the same whatever the preview |
| // size is. Ex: zoom level 1 is always 1.2x, zoom level 2 is 1.44x, etc. So, |
| // we need to have a fixed maximum zoom value and do read it from the |
| // driver. |
| static const int ZOOM_STEP = 1; |
| int32_t zoom_level = params.getInt("zoom"); |
| if(zoom_level >= 0 && zoom_level <= mMaxZoom-1) { |
| mParameters.set("zoom", zoom_level); |
| int32_t zoom_value = ZOOM_STEP * zoom_level; |
| bool ret = native_set_parms(CAMERA_PARM_ZOOM, |
| sizeof(zoom_value), (void *)&zoom_value); |
| rc = ret ? NO_ERROR : UNKNOWN_ERROR; |
| } else { |
| rc = BAD_VALUE; |
| } |
| |
| return rc; |
| } |
| |
| status_t QualcommCameraHardware::setDenoise(const QCameraParameters& params) |
| { |
| if(!mCfgControl.mm_camera_is_supported(CAMERA_PARM_WAVELET_DENOISE)) { |
| ALOGI("Wavelet Denoise is not supported for this sensor"); |
| return NO_ERROR; |
| } |
| const char *str = params.get(QCameraParameters::KEY_DENOISE); |
| if (str != NULL) { |
| int value = attr_lookup(denoise, |
| sizeof(denoise) / sizeof(str_map), str); |
| if ((value != NOT_FOUND) && (mDenoiseValue != value)) { |
| mDenoiseValue = value; |
| mParameters.set(QCameraParameters::KEY_DENOISE, str); |
| bool ret = native_set_parms(CAMERA_PARM_WAVELET_DENOISE, sizeof(value), |
| (void *)&value); |
| return ret ? NO_ERROR : UNKNOWN_ERROR; |
| } |
| return NO_ERROR; |
| } |
| ALOGE("Invalid Denoise value: %s", (str == NULL) ? "NULL" : str); |
| return BAD_VALUE; |
| } |
| |
| status_t QualcommCameraHardware::setZslParam(const QCameraParameters& params) |
| { |
| if(!mZslEnable) { |
| ALOGV("Zsl is not enabled"); |
| return NO_ERROR; |
| } |
| /* This ensures that restart of Preview doesnt happen when taking |
| * Snapshot for continuous viewfinder */ |
| const char *str = params.get("continuous-temporal-bracketing"); |
| if(str !=NULL) { |
| if(!strncmp(str, "enable", 8)) |
| mZslPanorama = true; |
| else |
| mZslPanorama = false; |
| return NO_ERROR; |
| } |
| mZslPanorama = false; |
| return NO_ERROR; |
| |
| } |
| |
| status_t QualcommCameraHardware::setSnapshotCount(const QCameraParameters& params) |
| { |
| int value; |
| char snapshotCount[5]; |
| if(!mZslEnable){ |
| value = numCapture; |
| } else { |
| /* ZSL case: Get value from App */ |
| const char *str = params.get("num-snaps-per-shutter"); |
| if (str != NULL) { |
| value = atoi(str); |
| } else |
| value = 1; |
| } |
| /* Sanity check */ |
| if(value > MAX_SNAPSHOT_BUFFERS -2) |
| value = MAX_SNAPSHOT_BUFFERS -2; |
| else if(value < 1) |
| value = 1; |
| snprintf(snapshotCount, sizeof(snapshotCount),"%d",value); |
| numCapture = value; |
| mParameters.set("num-snaps-per-shutter", snapshotCount); |
| ALOGI("%s setting num-snaps-per-shutter to %s", __FUNCTION__, snapshotCount); |
| return NO_ERROR; |
| |
| } |
| |
| status_t QualcommCameraHardware::updateFocusDistances(const char *focusmode) |
| { |
| ALOGV("%s: IN", __FUNCTION__); |
| focus_distances_info_t focusDistances; |
| if( mCfgControl.mm_camera_get_parm(CAMERA_PARM_FOCUS_DISTANCES, |
| (void *)&focusDistances) == MM_CAMERA_SUCCESS) { |
| String8 str; |
| char buffer[32]; |
| snprintf(buffer, sizeof(buffer), "%f", focusDistances.focus_distance[0]); |
| str.append(buffer); |
| snprintf(buffer, sizeof(buffer), ",%f", focusDistances.focus_distance[1]); |
| str.append(buffer); |
| if(strcmp(focusmode, QCameraParameters::FOCUS_MODE_INFINITY) == 0) |
| snprintf(buffer, sizeof(buffer), ",%s", "Infinity"); |
| else |
| snprintf(buffer, sizeof(buffer), ",%f", focusDistances.focus_distance[2]); |
| str.append(buffer); |
| ALOGI("%s: setting KEY_FOCUS_DISTANCES as %s", __FUNCTION__, str.string()); |
| mParameters.set(QCameraParameters::KEY_FOCUS_DISTANCES, str.string()); |
| return NO_ERROR; |
| } |
| ALOGE("%s: get CAMERA_PARM_FOCUS_DISTANCES failed!!!", __FUNCTION__); |
| return BAD_VALUE; |
| } |
| |
| status_t QualcommCameraHardware::setMeteringAreas(const QCameraParameters& params) |
| { |
| const char *str = params.get(QCameraParameters::KEY_METERING_AREAS); |
| if (str == NULL || (strcmp(str, "0") == 0)) { |
| ALOGE("%s: Parameter string is null", __FUNCTION__); |
| } |
| else { |
| // handling default string |
| if ((strcmp("(-2000,-2000,-2000,-2000,0)", str) == 0) || |
| (strcmp("(0,0,0,0,0)", str) == 0)){ |
| mParameters.set(QCameraParameters::KEY_METERING_AREAS, NULL); |
| return NO_ERROR; |
| } |
| if(checkAreaParameters(str) != 0) { |
| ALOGE("%s: Failed to parse the input string '%s'", __FUNCTION__, str); |
| return BAD_VALUE; |
| } |
| mParameters.set(QCameraParameters::KEY_METERING_AREAS, str); |
| } |
| |
| return NO_ERROR; |
| } |
| |
| status_t QualcommCameraHardware::setFocusAreas(const QCameraParameters& params) |
| { |
| const char *str = params.get(QCameraParameters::KEY_FOCUS_AREAS); |
| |
| if (str == NULL || (strcmp(str, "0") == 0)) { |
| ALOGE("%s: Parameter string is null", __FUNCTION__); |
| } |
| else { |
| // handling default string |
| if ((strcmp("(-2000,-2000,-2000,-2000,0)", str) == 0) || |
| (strcmp("(0,0,0,0,0)", str) == 0)) { |
| mParameters.set(QCameraParameters::KEY_FOCUS_AREAS, NULL); |
| return NO_ERROR; |
| } |
| |
| if(checkAreaParameters(str) != 0) { |
| ALOGE("%s: Failed to parse the input string '%s'", __FUNCTION__, str); |
| return BAD_VALUE; |
| } |
| |
| mParameters.set(QCameraParameters::KEY_FOCUS_AREAS, str); |
| } |
| |
| return NO_ERROR; |
| } |
| status_t QualcommCameraHardware::setFocusMode(const QCameraParameters& params) |
| { |
| const char *str = params.get(QCameraParameters::KEY_FOCUS_MODE); |
| if (str != NULL) { |
| ALOGI("FocusMode =%s", str); |
| int32_t value = attr_lookup(focus_modes, |
| sizeof(focus_modes) / sizeof(str_map), str); |
| if (value != NOT_FOUND) { |
| mParameters.set(QCameraParameters::KEY_FOCUS_MODE, str); |
| |
| if(mHasAutoFocusSupport && (updateFocusDistances(str) != NO_ERROR)) { |
| ALOGE("%s: updateFocusDistances failed for %s", __FUNCTION__, str); |
| return UNKNOWN_ERROR; |
| } |
| |
| if(mHasAutoFocusSupport){ |
| int cafSupport = FALSE; |
| if(!strcmp(str, QCameraParameters::FOCUS_MODE_CONTINUOUS_VIDEO) || |
| !strcmp(str, QCameraParameters::FOCUS_MODE_CONTINUOUS_PICTURE)){ |
| cafSupport = TRUE; |
| } |
| ALOGV("Continuous Auto Focus %d", cafSupport); |
| native_set_parms(CAMERA_PARM_CONTINUOUS_AF, sizeof(int8_t), (void *)&cafSupport); |
| } |
| // Focus step is reset to infinity when preview is started. We do |
| // not need to do anything now. |
| return NO_ERROR; |
| } |
| } |
| ALOGE("Invalid focus mode value: %s", (str == NULL) ? "NULL" : str); |
| return BAD_VALUE; |
| |
| } |
| QualcommCameraHardware::DispMemPool::DispMemPool(int fd, int buffer_size, |
| int num_buffers, int frame_size, |
| const char *name) : |
| QualcommCameraHardware::MemPool(buffer_size, |
| num_buffers, |
| frame_size, |
| name), |
| mFD(fd) |
| { |
| #if 0 |
| ALOGV("constructing MemPool %s from gralloc memory: " |
| "%d frames @ %d size " |
| "buffer size %d", |
| mName, |
| num_buffers, frame_size, buffer_size); |
| /* Use the fd given by gralloc and ask MemoryHeapBase to map it |
| * in this process space */ |
| mHeap = new MemoryHeapBase(mFD, buffer_size, MemoryHeapBase::NO_CACHING, 0); |
| completeInitialization(); |
| #endif |
| } |
| |
| QualcommCameraHardware::DispMemPool::~DispMemPool() |
| { |
| /* Not much to do in destructor for now */ |
| ALOGV(" ~DispMemPool : E "); |
| mFD = -1; |
| ALOGV(" ~DispMemPool : X "); |
| } |
| status_t QualcommCameraHardware::setOrientation(const QCameraParameters& params) |
| { |
| const char *str = params.get("orientation"); |
| |
| if (str != NULL) { |
| if (strcmp(str, "portrait") == 0 || strcmp(str, "landscape") == 0) { |
| // Camera service needs this to decide if the preview frames and raw |
| // pictures should be rotated. |
| mParameters.set("orientation", str); |
| } else { |
| ALOGE("Invalid orientation value: %s", str); |
| return BAD_VALUE; |
| } |
| } |
| return NO_ERROR; |
| } |
| |
| status_t QualcommCameraHardware::setPictureFormat(const QCameraParameters& params) |
| { |
| const char * str = params.get(QCameraParameters::KEY_PICTURE_FORMAT); |
| |
| if(str != NULL){ |
| int32_t value = attr_lookup(picture_formats, |
| sizeof(picture_formats) / sizeof(str_map), str); |
| if(value != NOT_FOUND){ |
| mParameters.set(QCameraParameters::KEY_PICTURE_FORMAT, str); |
| } else { |
| ALOGE("Invalid Picture Format value: %s", str); |
| return BAD_VALUE; |
| } |
| } |
| return NO_ERROR; |
| } |
| |
| QualcommCameraHardware::MMCameraDL::MMCameraDL(){ |
| ALOGV("MMCameraDL: E"); |
| libmmcamera = NULL; |
| #if DLOPEN_LIBMMCAMERA |
| libmmcamera = ::dlopen("liboemcamera.so", RTLD_NOW); |
| #endif |
| ALOGV("Open MM camera DL libeomcamera loaded at %p ", libmmcamera); |
| ALOGV("MMCameraDL: X"); |
| } |
| |
| void * QualcommCameraHardware::MMCameraDL::pointer(){ |
| return libmmcamera; |
| } |
| |
| QualcommCameraHardware::MMCameraDL::~MMCameraDL(){ |
| ALOGV("~MMCameraDL: E"); |
| LINK_mm_camera_destroy(); |
| if (libmmcamera != NULL) { |
| ::dlclose(libmmcamera); |
| ALOGV("closed MM Camera DL "); |
| } |
| libmmcamera = NULL; |
| ALOGV("~MMCameraDL: X"); |
| } |
| |
| wp<QualcommCameraHardware::MMCameraDL> QualcommCameraHardware::MMCameraDL::instance; |
| Mutex QualcommCameraHardware::MMCameraDL::singletonLock; |
| |
| |
| sp<QualcommCameraHardware::MMCameraDL> QualcommCameraHardware::MMCameraDL::getInstance(){ |
| Mutex::Autolock instanceLock(singletonLock); |
| sp<MMCameraDL> mmCamera = instance.promote(); |
| if(mmCamera == NULL){ |
| mmCamera = new MMCameraDL(); |
| instance = mmCamera; |
| } |
| return mmCamera; |
| } |
| |
| QualcommCameraHardware::MemPool::MemPool(int buffer_size, int num_buffers, |
| int frame_size, |
| const char *name) : |
| mBufferSize(buffer_size), |
| mNumBuffers(num_buffers), |
| mFrameSize(frame_size), |
| mBuffers(NULL), mName(name) |
| { |
| int page_size_minus_1 = getpagesize() - 1; |
| mAlignedBufferSize = (buffer_size + page_size_minus_1) & (~page_size_minus_1); |
| } |
| |
| void QualcommCameraHardware::MemPool::completeInitialization() |
| { |
| // If we do not know how big the frame will be, we wait to allocate |
| // the buffers describing the individual frames until we do know their |
| // size. |
| |
| if (mFrameSize > 0) { |
| ALOGI("Before new Mem BASE #buffers :%d",mNumBuffers); |
| mBuffers = new sp<MemoryBase>[mNumBuffers]; |
| for (int i = 0; i < mNumBuffers; i++) { |
| mBuffers[i] = new |
| MemoryBase(mHeap, |
| i * mAlignedBufferSize, |
| mFrameSize); |
| } |
| } |
| } |
| |
| QualcommCameraHardware::AshmemPool::AshmemPool(int buffer_size, int num_buffers, |
| int frame_size, |
| const char *name) : |
| QualcommCameraHardware::MemPool(buffer_size, |
| num_buffers, |
| frame_size, |
| name) |
| { |
| ALOGV("constructing MemPool %s backed by ashmem: " |
| "%d frames @ %d uint8_ts, " |
| "buffer size %d", |
| mName, |
| num_buffers, frame_size, buffer_size); |
| |
| int page_mask = getpagesize() - 1; |
| int ashmem_size = buffer_size * num_buffers; |
| ashmem_size += page_mask; |
| ashmem_size &= ~page_mask; |
| |
| mHeap = new MemoryHeapBase(ashmem_size); |
| |
| completeInitialization(); |
| } |
| |
| bool QualcommCameraHardware::register_record_buffers(bool register_buffer) { |
| ALOGI("%s: (%d) E", __FUNCTION__, register_buffer); |
| struct msm_pmem_info pmemBuf; |
| #if 0 |
| for (int cnt = 0; cnt < kRecordBufferCount; ++cnt) { |
| pmemBuf.type = MSM_PMEM_VIDEO; |
| pmemBuf.fd = mRecordHeap->mHeap->getHeapID(); |
| pmemBuf.offset = mRecordHeap->mAlignedBufferSize * cnt; |
| pmemBuf.len = mRecordHeap->mBufferSize; |
| pmemBuf.vaddr = (uint8_t *)mRecordHeap->mHeap->base() + mRecordHeap->mAlignedBufferSize * cnt; |
| pmemBuf.planar0_off = 0; |
| pmemBuf.planar1_off = recordframes[0].planar1_off; |
| pmemBuf.planar2_off = 0; |
| if(register_buffer == true) { |
| pmemBuf.active = (cnt<ACTIVE_VIDEO_BUFFERS); |
| if( (mVpeEnabled) && (cnt == kRecordBufferCount-1)) { |
| pmemBuf.type = MSM_PMEM_VIDEO_VPE; |
| pmemBuf.active = 1; |
| } |
| } else { |
| pmemBuf.active = false; |
| } |
| |
| ALOGV("register_buf: reg = %d buffer = %p", !register_buffer, |
| (void *)pmemBuf.vaddr); |
| if(native_start_ops(register_buffer ? CAMERA_OPS_REGISTER_BUFFER : |
| CAMERA_OPS_UNREGISTER_BUFFER ,(void *)&pmemBuf) < 0) { |
| ALOGE("register_buf: MSM_CAM_IOCTL_(UN)REGISTER_PMEM error %s", |
| strerror(errno)); |
| return false; |
| } |
| } |
| #endif |
| return true; |
| } |
| |
| QualcommCameraHardware::PmemPool::PmemPool(const char *pmem_pool, |
| int flags, |
| int pmem_type, |
| int buffer_size, int num_buffers, |
| int frame_size, int cbcr_offset, |
| int yOffset, const char *name) : |
| QualcommCameraHardware::MemPool(buffer_size, |
| num_buffers, |
| frame_size, |
| name), |
| mPmemType(pmem_type), |
| mCbCrOffset(cbcr_offset), |
| myOffset(yOffset) |
| { |
| bool all_chnls = false; |
| ALOGI("constructing MemPool %s backed by pmem pool %s: " |
| "%d frames @ %d bytes, buffer size %d", |
| mName, |
| pmem_pool, num_buffers, frame_size, |
| buffer_size); |
| |
| mMMCameraDLRef = QualcommCameraHardware::MMCameraDL::getInstance(); |
| |
| |
| // Make a new mmap'ed heap that can be shared across processes. |
| // mAlignedBufferSize is already in 4k aligned. (do we need total size necessary to be in power of 2??) |
| mAlignedSize = mAlignedBufferSize * num_buffers; |
| |
| sp<MemoryHeapBase> masterHeap = |
| new MemoryHeapBase(pmem_pool, mAlignedSize, flags); |
| |
| if (masterHeap->getHeapID() < 0) { |
| ALOGE("failed to construct master heap for pmem pool %s", pmem_pool); |
| masterHeap.clear(); |
| return; |
| } |
| |
| sp<MemoryHeapPmem> pmemHeap = new MemoryHeapPmem(masterHeap, flags); |
| if (pmemHeap->getHeapID() >= 0) { |
| pmemHeap->slap(); |
| masterHeap.clear(); |
| mHeap = pmemHeap; |
| pmemHeap.clear(); |
| |
| mFd = mHeap->getHeapID(); |
| if (::ioctl(mFd, PMEM_GET_SIZE, &mSize)) { |
| ALOGE("pmem pool %s ioctl(PMEM_GET_SIZE) error %s (%d)", |
| pmem_pool, |
| ::strerror(errno), errno); |
| mHeap.clear(); |
| return; |
| } |
| |
| ALOGV("pmem pool %s ioctl(fd = %d, PMEM_GET_SIZE) is %ld", |
| pmem_pool, |
| mFd, |
| mSize.len); |
| ALOGD("mBufferSize=%d, mAlignedBufferSize=%d\n", mBufferSize, mAlignedBufferSize); |
| // Unregister preview buffers with the camera drivers. Allow the VFE to write |
| // to all preview buffers except for the last one. |
| // Only Register the preview, snapshot and thumbnail buffers with the kernel. |
| if( (strcmp("postview", mName) != 0) ){ |
| int num_buf = num_buffers; |
| if(!strcmp("preview", mName)) num_buf = kTotalPreviewBufferCount; |
| ALOGD("num_buffers = %d", num_buf); |
| for (int cnt = 0; cnt < num_buf; ++cnt) { |
| int active = 1; |
| if(pmem_type == MSM_PMEM_VIDEO){ |
| active = (cnt<ACTIVE_VIDEO_BUFFERS); |
| //When VPE is enabled, set the last record |
| //buffer as active and pmem type as PMEM_VIDEO_VPE |
| //as this is a requirement from VPE operation. |
| //No need to set this pmem type to VIDEO_VPE while unregistering, |
| //because as per camera stack design: "the VPE AXI is also configured |
| //when VFE is configured for VIDEO, which is as part of preview |
| //initialization/start. So during this VPE AXI config camera stack |
| //will lookup the PMEM_VIDEO_VPE buffer and give it as o/p of VPE and |
| //change it's type to PMEM_VIDEO". |
| if( (mVpeEnabled) && (cnt == kRecordBufferCount-1)) { |
| active = 1; |
| pmem_type = MSM_PMEM_VIDEO_VPE; |
| } |
| ALOGV(" pmempool creating video buffers : active %d ", active); |
| } |
| else if (pmem_type == MSM_PMEM_PREVIEW){ |
| active = (cnt < ACTIVE_PREVIEW_BUFFERS); |
| } |
| else if ((pmem_type == MSM_PMEM_MAINIMG) |
| || (pmem_type == MSM_PMEM_THUMBNAIL)){ |
| active = (cnt < ACTIVE_ZSL_BUFFERS); |
| } |
| if (pmem_type == MSM_PMEM_PREVIEW && |
| mPreviewFormat == CAMERA_YUV_420_YV12 && mCurrentTarget != TARGET_MSM7627A) |
| all_chnls = true; |
| |
| register_buf(mBufferSize, |
| mFrameSize, mCbCrOffset, myOffset, |
| mHeap->getHeapID(), |
| mAlignedBufferSize * cnt, |
| (uint8_t *)mHeap->base() + mAlignedBufferSize * cnt, |
| pmem_type, |
| active,true, |
| all_chnls); |
| } |
| } |
| |
| completeInitialization(); |
| } |
| else ALOGE("pmem pool %s error: could not create master heap!", |
| pmem_pool); |
| ALOGV("%s: (%s) X ", __FUNCTION__, mName); |
| } |
| |
| QualcommCameraHardware::PmemPool::~PmemPool() |
| { |
| ALOGI("%s: %s E", __FUNCTION__, mName); |
| if (mHeap != NULL) { |
| // Unregister preview buffers with the camera drivers. |
| // Only Unregister the preview, snapshot and thumbnail |
| // buffers with the kernel. |
| if( (strcmp("postview", mName) != 0) ){ |
| int num_buffers = mNumBuffers; |
| if(!strcmp("preview", mName)) num_buffers = kTotalPreviewBufferCount; |
| for (int cnt = 0; cnt < num_buffers; ++cnt) { |
| register_buf(mBufferSize, |
| mFrameSize, |
| mCbCrOffset, |
| myOffset, |
| mHeap->getHeapID(), |
| mAlignedBufferSize * cnt, |
| (uint8_t *)mHeap->base() + mAlignedBufferSize * cnt, |
| mPmemType, |
| false, |
| false,/* unregister */ |
| false); |
| } |
| } |
| } |
| mMMCameraDLRef.clear(); |
| ALOGI("%s: %s X", __FUNCTION__, mName); |
| } |
| #if 0 |
| #ifdef USE_ION |
| const char QualcommCameraHardware::IonPool::mIonDevName[] = "/dev/ion"; |
| QualcommCameraHardware::IonPool::IonPool(int ion_heap_id, int flags, |
| int ion_type, |
| int buffer_size, int num_buffers, |
| int frame_size, int cbcr_offset, |
| int yOffset, const char *name) : |
| QualcommCameraHardware::MemPool(buffer_size, |
| num_buffers, |
| frame_size, |
| name), |
| mIonType(ion_type), |
| mCbCrOffset(cbcr_offset), |
| myOffset(yOffset) |
| { |
| ALOGI("constructing MemPool %s backed by pmem pool %s: " |
| "%d frames @ %d bytes, buffer size %d", |
| mName, |
| mIonDevName, num_buffers, frame_size, |
| buffer_size); |
| |
| mMMCameraDLRef = QualcommCameraHardware::MMCameraDL::getInstance(); |
| |
| |
| // Make a new mmap'ed heap that can be shared across processes. |
| // mAlignedBufferSize is already in 4k aligned. (do we need total size necessary to be in power of 2??) |
| mAlignedSize = mAlignedBufferSize * num_buffers; |
| sp<MemoryHeapIon> ionHeap = new MemoryHeapIon(mIonDevName, mAlignedSize, |
| flags, 0x1<<ion_heap_id); |
| if (ionHeap->getHeapID() >= 0) { |
| mHeap = ionHeap; |
| ionHeap.clear(); |
| |
| mFd = mHeap->getHeapID(); |
| ALOGE("ion pool %s fd = %d", mIonDevName, mFd); |
| ALOGE("mBufferSize=%d, mAlignedBufferSize=%d\n", |
| mBufferSize, mAlignedBufferSize); |
| |
| // Unregister preview buffers with the camera drivers. Allow the VFE to write |
| // to all preview buffers except for the last one. |
| // Only Register the preview, snapshot and thumbnail buffers with the kernel. |
| if( (strcmp("postview", mName) != 0) ){ |
| int num_buf = num_buffers; |
| if(!strcmp("preview", mName)) num_buf = kPreviewBufferCount; |
| ALOGD("num_buffers = %d", num_buf); |
| for (int cnt = 0; cnt < num_buf; ++cnt) { |
| int active = 1; |
| if(ion_type == MSM_PMEM_VIDEO){ |
| active = (cnt<ACTIVE_VIDEO_BUFFERS); |
| //When VPE is enabled, set the last record |
| //buffer as active and pmem type as PMEM_VIDEO_VPE |
| //as this is a requirement from VPE operation. |
| //No need to set this pmem type to VIDEO_VPE while unregistering, |
| //because as per camera stack design: "the VPE AXI is also configured |
| //when VFE is configured for VIDEO, which is as part of preview |
| //initialization/start. So during this VPE AXI config camera stack |
| //will lookup the PMEM_VIDEO_VPE buffer and give it as o/p of VPE and |
| //change it's type to PMEM_VIDEO". |
| if( (mVpeEnabled) && (cnt == kRecordBufferCount-1)) { |
| active = 1; |
| ion_type = MSM_PMEM_VIDEO_VPE; |
| } |
| ALOGV(" pmempool creating video buffers : active %d ", active); |
| } |
| else if (ion_type == MSM_PMEM_PREVIEW){ |
| active = (cnt < ACTIVE_PREVIEW_BUFFERS); |
| } |
| else if ((ion_type == MSM_PMEM_MAINIMG) |
| || (ion_type == MSM_PMEM_THUMBNAIL)){ |
| active = (cnt < ACTIVE_ZSL_BUFFERS); |
| } |
| register_buf(mBufferSize, |
| mFrameSize, mCbCrOffset, myOffset, |
| mHeap->getHeapID(), |
| mAlignedBufferSize * cnt, |
| (uint8_t *)mHeap->base() + mAlignedBufferSize * cnt, |
| ion_type, |
| active); |
| } |
| } |
| |
| completeInitialization(); |
| } |
| else ALOGE("pmem pool %s error: could not create master heap!", |
| mIonDevName); |
| ALOGI("%s: (%s) X ", __FUNCTION__, mName); |
| } |
| |
| QualcommCameraHardware::IonPool::~IonPool() |
| { |
| ALOGI("%s: %s E", __FUNCTION__, mName); |
| if (mHeap != NULL) { |
| // Unregister preview buffers with the camera drivers. |
| // Only Unregister the preview, snapshot and thumbnail |
| // buffers with the kernel. |
| if( (strcmp("postview", mName) != 0) ){ |
| int num_buffers = mNumBuffers; |
| if(!strcmp("preview", mName)) num_buffers = kPreviewBufferCount; |
| for (int cnt = 0; cnt < num_buffers; ++cnt) { |
| register_buf(mBufferSize, |
| mFrameSize, |
| mCbCrOffset, |
| myOffset, |
| mHeap->getHeapID(), |
| mAlignedBufferSize * cnt, |
| (uint8_t *)mHeap->base() + mAlignedBufferSize * cnt, |
| mIonType, |
| false, |
| false /* unregister */); |
| } |
| } |
| } |
| mMMCameraDLRef.clear(); |
| ALOGI("%s: %s X", __FUNCTION__, mName); |
| } |
| #endif |
| #endif |
| QualcommCameraHardware::MemPool::~MemPool() |
| { |
| ALOGV("destroying MemPool %s", mName); |
| if (mFrameSize > 0) |
| delete [] mBuffers; |
| mHeap.clear(); |
| ALOGV("destroying MemPool %s completed", mName); |
| } |
| |
| status_t QualcommCameraHardware::MemPool::dump(int fd, const Vector<String16>& args) const |
| { |
| const size_t SIZE = 256; |
| char buffer[SIZE]; |
| String8 result; |
| CAMERA_HAL_UNUSED(args); |
| snprintf(buffer, 255, "QualcommCameraHardware::AshmemPool::dump\n"); |
| result.append(buffer); |
| if (mName) { |
| snprintf(buffer, 255, "mem pool name (%s)\n", mName); |
| result.append(buffer); |
| } |
| if (mHeap != 0) { |
| snprintf(buffer, 255, "heap base(%p), size(%d), flags(%d), device(%s)\n", |
| mHeap->getBase(), mHeap->getSize(), |
| mHeap->getFlags(), mHeap->getDevice()); |
| result.append(buffer); |
| } |
| snprintf(buffer, 255, |
| "buffer size (%d), number of buffers (%d), frame size(%d)", |
| mBufferSize, mNumBuffers, mFrameSize); |
| result.append(buffer); |
| write(fd, result.string(), result.size()); |
| return NO_ERROR; |
| } |
| |
| static void receive_camframe_callback(struct msm_frame *frame) |
| { |
| QualcommCameraHardware* obj = QualcommCameraHardware::getInstance(); |
| if (obj != 0) { |
| obj->receivePreviewFrame(frame); |
| } |
| } |
| |
| static void receive_camstats_callback(camstats_type stype, camera_preview_histogram_info* histinfo) |
| { |
| QualcommCameraHardware* obj = QualcommCameraHardware::getInstance(); |
| if (obj != 0) { |
| obj->receiveCameraStats(stype,histinfo); |
| } |
| } |
| |
| static void receive_liveshot_callback(liveshot_status status, uint32_t jpeg_size) |
| { |
| if(status == LIVESHOT_SUCCESS) { |
| QualcommCameraHardware* obj = QualcommCameraHardware::getInstance(); |
| if (obj != 0) { |
| obj->receiveLiveSnapshot(jpeg_size); |
| } |
| } |
| else |
| ALOGE("Liveshot not succesful"); |
| } |
| |
| |
| static int8_t receive_event_callback(mm_camera_event* event) |
| { |
| ALOGV("%s: E", __FUNCTION__); |
| if(event == NULL) { |
| ALOGE("%s: event is NULL!", __FUNCTION__); |
| return FALSE; |
| } |
| switch(event->event_type) { |
| case SNAPSHOT_DONE: |
| { |
| /* postview buffer is received */ |
| QualcommCameraHardware* obj = QualcommCameraHardware::getInstance(); |
| if (obj != 0) { |
| |
| obj->receiveRawPicture(NO_ERROR, event->event_data.yuv_frames[0], event->event_data.yuv_frames[0]); |
| } |
| } |
| break; |
| case SNAPSHOT_FAILED: |
| { |
| /* postview buffer is received */ |
| QualcommCameraHardware* obj = QualcommCameraHardware::getInstance(); |
| if (obj != 0) { |
| |
| obj->receiveRawPicture(UNKNOWN_ERROR, NULL, NULL); |
| } |
| } |
| break; |
| case JPEG_ENC_DONE: |
| { |
| QualcommCameraHardware* obj = QualcommCameraHardware::getInstance(); |
| if (obj != 0) { |
| obj->receiveJpegPicture(NO_ERROR, event->event_data.encoded_frame); |
| } |
| } |
| break; |
| case JPEG_ENC_FAILED: |
| { |
| QualcommCameraHardware* obj = QualcommCameraHardware::getInstance(); |
| if (obj != 0) { |
| obj->receiveJpegPicture(UNKNOWN_ERROR, 0); |
| } |
| } |
| break; |
| default: |
| ALOGE("%s: ignore default case", __FUNCTION__); |
| } |
| return TRUE; |
| ALOGV("%s: X", __FUNCTION__); |
| } |
| // 720p : video frame calbback from camframe |
| static void receive_camframe_video_callback(struct msm_frame *frame) |
| { |
| ALOGV("receive_camframe_video_callback E"); |
| QualcommCameraHardware* obj = QualcommCameraHardware::getInstance(); |
| if (obj != 0) { |
| obj->receiveRecordingFrame(frame); |
| } |
| ALOGV("receive_camframe_video_callback X"); |
| } |
| |
| |
| int QualcommCameraHardware::storeMetaDataInBuffers(int enable) |
| { |
| /* this is a dummy func now. fix me later */ |
| ALOGI("in storeMetaDataInBuffers : enable %d", enable); |
| mStoreMetaDataInFrame = enable; |
| return 0; |
| } |
| |
| void QualcommCameraHardware::setCallbacks(camera_notify_callback notify_cb, |
| camera_data_callback data_cb, |
| camera_data_timestamp_callback data_cb_timestamp, |
| camera_request_memory get_memory, |
| void* user) |
| { |
| Mutex::Autolock lock(mLock); |
| mNotifyCallback = notify_cb; |
| mDataCallback = data_cb; |
| mDataCallbackTimestamp = data_cb_timestamp; |
| mGetMemory = get_memory; |
| mCallbackCookie = user; |
| } |
| int32_t QualcommCameraHardware::getNumberOfVideoBuffers() { |
| ALOGI("getNumOfVideoBuffers: %d", kRecordBufferCount); |
| return kRecordBufferCount; |
| } |
| |
| sp<IMemory> QualcommCameraHardware::getVideoBuffer(int32_t index) { |
| if(index > kRecordBufferCount) |
| return NULL; |
| else |
| return NULL; |
| #if 0 |
| return mRecordHeap->mBuffers[index]; |
| #endif |
| } |
| void QualcommCameraHardware::enableMsgType(int32_t msgType) |
| { |
| Mutex::Autolock lock(mLock); |
| mMsgEnabled |= msgType; |
| if( (mCurrentTarget != TARGET_MSM7630 ) && (mCurrentTarget != TARGET_QSD8250) && (mCurrentTarget != TARGET_MSM8660)) { |
| if(mMsgEnabled & CAMERA_MSG_VIDEO_FRAME){ |
| native_start_ops(CAMERA_OPS_VIDEO_RECORDING, NULL); |
| mRecordingState = 1; |
| } |
| } |
| } |
| |
| void QualcommCameraHardware::disableMsgType(int32_t msgType) |
| { |
| Mutex::Autolock lock(mLock); |
| if( (mCurrentTarget != TARGET_MSM7630 ) && (mCurrentTarget != TARGET_QSD8250) && (mCurrentTarget != TARGET_MSM8660)) { |
| if(mMsgEnabled & CAMERA_MSG_VIDEO_FRAME){ |
| native_stop_ops(CAMERA_OPS_VIDEO_RECORDING, NULL); |
| mRecordingState = 0; |
| } |
| } |
| mMsgEnabled &= ~msgType; |
| } |
| |
| bool QualcommCameraHardware::msgTypeEnabled(int32_t msgType) |
| { |
| return (mMsgEnabled & msgType); |
| } |
| |
| |
| void QualcommCameraHardware::receive_camframe_error_timeout(void) { |
| ALOGI("receive_camframe_error_timeout: E"); |
| Mutex::Autolock l(&mCamframeTimeoutLock); |
| ALOGE(" Camframe timed out. Not receiving any frames from camera driver "); |
| camframe_timeout_flag = TRUE; |
| mNotifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_UNKNOWN, 0, |
| mCallbackCookie); |
| ALOGI("receive_camframe_error_timeout: X"); |
| } |
| |
| static void receive_camframe_error_callback(camera_error_type err) { |
| QualcommCameraHardware* obj = QualcommCameraHardware::getInstance(); |
| if (obj != 0) { |
| if ((err == CAMERA_ERROR_TIMEOUT) || |
| (err == CAMERA_ERROR_ESD)) { |
| /* Handling different error types is dependent on the requirement. |
| * Do the same action by default |
| */ |
| obj->receive_camframe_error_timeout(); |
| } |
| } |
| } |
| |
| bool QualcommCameraHardware::storePreviewFrameForPostview(void) { |
| ALOGV("storePreviewFrameForPostview : E "); |
| |
| /* Since there is restriction on the maximum overlay dimensions |
| * that can be created, we use the last preview frame as postview |
| * for 7x30. */ |
| ALOGV("Copying the preview buffer to postview buffer %d ", |
| mPreviewFrameSize); |
| if(mLastPreviewFrameHeap == NULL) { |
| int CbCrOffset = PAD_TO_WORD(mPreviewFrameSize * 2/3); |
| #if 0 |
| #ifdef USE_ION |
| |
| mLastPreviewFrameHeap = |
| new IonPool(ION_HEAP_ADSP_ID, |
| MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING, |
| MSM_PMEM_PREVIEW, //MSM_PMEM_OUTPUT2, |
| mPreviewFrameSize, |
| 1, |
| mPreviewFrameSize, |
| CbCrOffset, |
| 0, |
| "postview"); |
| #else |
| mLastPreviewFrameHeap = |
| new PmemPool("/dev/pmem_adsp", |
| MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING, |
| MSM_PMEM_PREVIEW, //MSM_PMEM_OUTPUT2, |
| mPreviewFrameSize, |
| 1, |
| mPreviewFrameSize, |
| CbCrOffset, |
| 0, |
| "postview"); |
| #endif |
| if (!mLastPreviewFrameHeap->initialized()) { |
| mLastPreviewFrameHeap.clear(); |
| ALOGE(" Failed to initialize Postview Heap"); |
| return false; |
| } |
| #endif |
| } |
| #if 0 |
| if( mLastPreviewFrameHeap != NULL && mLastQueuedFrame != NULL) { |
| memcpy(mLastPreviewFrameHeap->mHeap->base(), |
| (uint8_t *)mLastQueuedFrame, mPreviewFrameSize ); |
| |
| if(mUseOverlay && !mZslPanorama) { |
| //mOverlayLock.lock(); |
| //if(mOverlay != NULL){ |
| //mOverlay->setFd(mLastPreviewFrameHeap->mHeap->getHeapID()); |
| if( zoomCropInfo.w !=0 && zoomCropInfo.h !=0) { |
| ALOGE("zoomCropInfo non-zero, setting crop "); |
| ALOGE("setCrop with %dx%d and %dx%d", zoomCropInfo.x, zoomCropInfo.y, zoomCropInfo.w, zoomCropInfo.h); |
| // mOverlay->setCrop(zoomCropInfo.x, zoomCropInfo.y, |
| //zoomCropInfo.w, zoomCropInfo.h); |
| } |
| ALOGV("Queueing Postview with last frame till the snapshot is done "); |
| //mOverlay->queueBuffer((void *)0); |
| } |
| //mOverlayLock.unlock(); |
| } |
| |
| } else |
| ALOGE("Failed to store Preview frame. No Postview "); |
| #endif |
| ALOGV("storePreviewFrameForPostview : X "); |
| return true; |
| } |
| |
| bool QualcommCameraHardware::isValidDimension(int width, int height) { |
| bool retVal = FALSE; |
| /* This function checks if a given resolution is valid or not. |
| * A particular resolution is considered valid if it satisfies |
| * the following conditions: |
| * 1. width & height should be multiple of 16. |
| * 2. width & height should be less than/equal to the dimensions |
| * supported by the camera sensor. |
| * 3. the aspect ratio is a valid aspect ratio and is among the |
| * commonly used aspect ratio as determined by the thumbnail_sizes |
| * data structure. |
| */ |
| |
| if( (width == CEILING16(width)) && (height == CEILING16(height)) |
| && (width <= maxSnapshotWidth) |
| && (height <= maxSnapshotHeight) ) |
| { |
| uint32_t pictureAspectRatio = (uint32_t)((width * Q12)/height); |
| for(uint32_t i = 0; i < THUMBNAIL_SIZE_COUNT; i++ ) { |
| if(thumbnail_sizes[i].aspect_ratio == pictureAspectRatio) { |
| retVal = TRUE; |
| break; |
| } |
| } |
| } |
| return retVal; |
| } |
| status_t QualcommCameraHardware::getBufferInfo(sp<IMemory>& Frame, size_t *alignedSize) { |
| status_t ret; |
| ALOGV(" getBufferInfo : E "); |
| if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250) || (mCurrentTarget == TARGET_MSM8660) ) |
| { |
| if( mRecordHeap != NULL){ |
| ALOGV(" Setting valid buffer information "); |
| Frame = mRecordHeap->mBuffers[0]; |
| if( alignedSize != NULL) { |
| *alignedSize = mRecordHeap->mAlignedBufferSize; |
| ALOGV(" HAL : alignedSize = %d ", *alignedSize); |
| ret = NO_ERROR; |
| } else { |
| ALOGE(" HAL : alignedSize is NULL. Cannot update alignedSize "); |
| ret = UNKNOWN_ERROR; |
| } |
| } else { |
| ALOGE(" RecordHeap is null. Buffer information wont be updated "); |
| Frame = NULL; |
| ret = UNKNOWN_ERROR; |
| } |
| } else { |
| if(mPreviewHeap != NULL) { |
| ALOGV(" Setting valid buffer information "); |
| // Frame = mPreviewHeap->mBuffers[0]; |
| if( alignedSize != NULL) { |
| //*alignedSize = mPreviewHeap->mAlignedBufferSize; |
| ALOGV(" HAL : alignedSize = %d ", *alignedSize); |
| ret = NO_ERROR; |
| } else { |
| ALOGE(" HAL : alignedSize is NULL. Cannot update alignedSize "); |
| ret = UNKNOWN_ERROR; |
| } |
| } else { |
| ALOGE(" PreviewHeap is null. Buffer information wont be updated "); |
| Frame = NULL; |
| ret = UNKNOWN_ERROR; |
| } |
| } |
| ALOGV(" getBufferInfo : X "); |
| return ret; |
| } |
| |
| void QualcommCameraHardware::encodeData() { |
| ALOGV("encodeData: E"); |
| |
| if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) { |
| mJpegThreadWaitLock.lock(); |
| mJpegThreadRunning = true; |
| mJpegThreadWaitLock.unlock(); |
| mm_camera_ops_type_t current_ops_type = CAMERA_OPS_ENCODE; |
| mCamOps.mm_camera_start(current_ops_type,(void *)&mImageCaptureParms, |
| (void *)&mImageEncodeParms); |
| //Wait until jpeg encoding is done and clear the resources. |
| mJpegThreadWaitLock.lock(); |
| while (mJpegThreadRunning) { |
| ALOGV("encodeData: waiting for jpeg thread to complete."); |
| mJpegThreadWait.wait(mJpegThreadWaitLock); |
| ALOGV("encodeData: jpeg thread completed."); |
| } |
| mJpegThreadWaitLock.unlock(); |
| } |
| else ALOGV("encodeData: JPEG callback is NULL, not encoding image."); |
| |
| mCamOps.mm_camera_deinit(CAMERA_OPS_CAPTURE, NULL, NULL); |
| //clear the resources |
| deinitRaw(); |
| //Encoding is done. |
| mEncodePendingWaitLock.lock(); |
| mEncodePending = false; |
| mEncodePendingWait.signal(); |
| mEncodePendingWaitLock.unlock(); |
| |
| ALOGV("encodeData: X"); |
| } |
| |
| void QualcommCameraHardware::getCameraInfo() |
| { |
| ALOGI("getCameraInfo: IN"); |
| mm_camera_status_t status; |
| |
| #if DLOPEN_LIBMMCAMERA |
| void *libhandle = ::dlopen("liboemcamera.so", RTLD_NOW); |
| ALOGI("getCameraInfo: loading libqcamera at %p", libhandle); |
| if (!libhandle) { |
| ALOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror()); |
| } |
| *(void **)&LINK_mm_camera_get_camera_info = |
| ::dlsym(libhandle, "mm_camera_get_camera_info"); |
| #endif |
| storeTargetType(); |
| status = LINK_mm_camera_get_camera_info(HAL_cameraInfo, &HAL_numOfCameras); |
| ALOGI("getCameraInfo: numOfCameras = %d", HAL_numOfCameras); |
| for(int i = 0; i < HAL_numOfCameras; i++) { |
| if((HAL_cameraInfo[i].position == BACK_CAMERA )&& |
| mCurrentTarget == TARGET_MSM8660){ |
| HAL_cameraInfo[i].modes_supported |= CAMERA_ZSL_MODE; |
| } else{ |
| HAL_cameraInfo[i].modes_supported |= CAMERA_NONZSL_MODE; |
| } |
| ALOGI("Camera sensor %d info:", i); |
| ALOGI("camera_id: %d", HAL_cameraInfo[i].camera_id); |
| ALOGI("modes_supported: %x", HAL_cameraInfo[i].modes_supported); |
| ALOGI("position: %d", HAL_cameraInfo[i].position); |
| ALOGI("sensor_mount_angle: %d", HAL_cameraInfo[i].sensor_mount_angle); |
| } |
| |
| #if DLOPEN_LIBMMCAMERA |
| if (libhandle) { |
| ::dlclose(libhandle); |
| ALOGV("getCameraInfo: dlclose(libqcamera)"); |
| } |
| #endif |
| ALOGI("getCameraInfo: OUT"); |
| } |
| |
| extern "C" int HAL_isIn3DMode() |
| { |
| return HAL_currentCameraMode == CAMERA_MODE_3D; |
| } |
| |
| extern "C" int HAL_getNumberOfCameras() |
| { |
| QualcommCameraHardware::getCameraInfo(); |
| return HAL_numOfCameras; |
| } |
| |
| extern "C" void HAL_getCameraInfo(int cameraId, struct CameraInfo* cameraInfo) |
| { |
| int i; |
| char mDeviceName[PROPERTY_VALUE_MAX]; |
| if(cameraInfo == NULL) { |
| ALOGE("cameraInfo is NULL"); |
| return; |
| } |
| |
| property_get("ro.board.platform",mDeviceName," "); |
| |
| for(i = 0; i < HAL_numOfCameras; i++) { |
| if(i == cameraId) { |
| ALOGI("Found a matching camera info for ID %d", cameraId); |
| cameraInfo->facing = (HAL_cameraInfo[i].position == BACK_CAMERA)? |
| CAMERA_FACING_BACK : CAMERA_FACING_FRONT; |
| // App Orientation not needed for 7x27 , sensor mount angle 0 is |
| // enough. |
| if(cameraInfo->facing == CAMERA_FACING_FRONT) |
| cameraInfo->orientation = HAL_cameraInfo[i].sensor_mount_angle; |
| else if( !strncmp(mDeviceName, "msm7625a", 8)) |
| cameraInfo->orientation = HAL_cameraInfo[i].sensor_mount_angle; |
| else if( !strncmp(mDeviceName, "msm7627a", 8)) |
| cameraInfo->orientation = HAL_cameraInfo[i].sensor_mount_angle; |
| else if( !strncmp(mDeviceName, "msm7627", 7)) |
| cameraInfo->orientation = HAL_cameraInfo[i].sensor_mount_angle; |
| else if( !strncmp(mDeviceName, "msm8660", 7)) |
| cameraInfo->orientation = HAL_cameraInfo[i].sensor_mount_angle; |
| else |
| cameraInfo->orientation = ((APP_ORIENTATION - HAL_cameraInfo[i].sensor_mount_angle) + 360)%360; |
| |
| ALOGI("%s: orientation = %d", __FUNCTION__, cameraInfo->orientation); |
| sensor_rotation = HAL_cameraInfo[i].sensor_mount_angle; |
| cameraInfo->mode = 0; |
| if(HAL_cameraInfo[i].modes_supported & CAMERA_MODE_2D) |
| cameraInfo->mode |= CAMERA_SUPPORT_MODE_2D; |
| if(HAL_cameraInfo[i].modes_supported & CAMERA_MODE_3D) |
| cameraInfo->mode |= CAMERA_SUPPORT_MODE_3D; |
| if((HAL_cameraInfo[i].position == BACK_CAMERA )&& |
| !strncmp(mDeviceName, "msm8660", 7)){ |
| cameraInfo->mode |= CAMERA_ZSL_MODE; |
| } else{ |
| cameraInfo->mode |= CAMERA_NONZSL_MODE; |
| } |
| |
| ALOGI("%s: modes supported = %d", __FUNCTION__, cameraInfo->mode); |
| |
| return; |
| } |
| } |
| // ALOGE("Unable to find matching camera info for ID %d", cameraId); |
| } |
| |
| }; // namespace android |