blob: 295c338027dc404189464ccc6d419f36b57c5896 [file] [log] [blame]
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001/*
2** Copyright 2008, Google Inc.
Apurva Rajguru08383852010-05-17 14:25:39 -07003** Copyright (c) 2009-2010 Code Aurora Forum. All rights reserved.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18//#define LOG_NDEBUG 0
Mohan Kandrabad0eaa2010-02-04 15:11:54 -080019#define LOG_NIDEBUG 0
Apurva Rajguruf0593dd2010-07-27 17:50:23 -070020
Priya Komarlingamb85535d2009-11-30 13:06:01 -080021#define LOG_TAG "QualcommCameraHardware"
22#include <utils/Log.h>
23
24#include "QualcommCameraHardware.h"
25
26#include <utils/Errors.h>
27#include <utils/threads.h>
28#include <binder/MemoryHeapPmem.h>
29#include <utils/String16.h>
30#include <sys/types.h>
31#include <sys/stat.h>
32#include <unistd.h>
Sravankb4f5f1c2010-01-21 11:06:17 +053033#include <fcntl.h>
Apurva Rajguru8d1773b2009-12-02 14:21:23 -080034#include <cutils/properties.h>
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -080035#include <math.h>
Priya Komarlingamb85535d2009-11-30 13:06:01 -080036#if HAVE_ANDROID_OS
37#include <linux/android_pmem.h>
38#endif
39#include <linux/ioctl.h>
Priya Komarlingam9bb2d492010-06-23 19:21:52 -070040#include <camera/CameraParameters.h>
Vamshidhar Kondra92ce9142010-09-03 18:22:08 +053041#include <media/mediarecorder.h>
Priya Komarlingamb85535d2009-11-30 13:06:01 -080042
Mohan Kandra284966d2010-01-05 13:39:15 -080043#include "linux/msm_mdp.h"
44#include <linux/fb.h>
45
Priya Komarlingamb85535d2009-11-30 13:06:01 -080046#define LIKELY(exp) __builtin_expect(!!(exp), 1)
47#define UNLIKELY(exp) __builtin_expect(!!(exp), 0)
48
49extern "C" {
50#include <fcntl.h>
51#include <time.h>
52#include <pthread.h>
53#include <stdio.h>
54#include <string.h>
55#include <unistd.h>
56#include <termios.h>
57#include <assert.h>
58#include <stdlib.h>
59#include <ctype.h>
60#include <signal.h>
61#include <errno.h>
62#include <sys/mman.h>
63#include <sys/system_properties.h>
64#include <sys/time.h>
65#include <stdlib.h>
66
67#include <media/msm_camera.h>
68
69#include <camera.h>
70#include <camframe.h>
Vamshidhar Kondra92ce9142010-09-03 18:22:08 +053071#include <liveshot.h>
Priya Komarlingamb85535d2009-11-30 13:06:01 -080072#include <mm-still/jpeg/jpege.h>
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -080073#include <jpeg_encoder.h>
Priya Komarlingamb85535d2009-11-30 13:06:01 -080074
Vamshidhar Kondra92ce9142010-09-03 18:22:08 +053075#define DUMP_LIVESHOT_JPEG_FILE 0
76
Nishant Pandit2eedc1b2010-09-25 04:47:39 +053077#define DEFAULT_PICTURE_WIDTH 640
78#define DEFAULT_PICTURE_HEIGHT 480
Priya Komarlingamb85535d2009-11-30 13:06:01 -080079#define THUMBNAIL_BUFFER_SIZE (THUMBNAIL_WIDTH * THUMBNAIL_HEIGHT * 3/2)
80#define MAX_ZOOM_LEVEL 5
81#define NOT_FOUND -1
Sravankb4f5f1c2010-01-21 11:06:17 +053082// Number of video buffers held by kernal (initially 1,2 &3)
83#define ACTIVE_VIDEO_BUFFERS 3
84
Nishant Panditc6fd2c22010-08-03 00:10:47 +053085#define PAD_TO_2K(x) (((x)+2047)& ~2047)
Nishant Panditbde07612010-07-28 00:16:28 +053086
Priya Komarlingamb85535d2009-11-30 13:06:01 -080087#if DLOPEN_LIBMMCAMERA
88#include <dlfcn.h>
89
90void* (*LINK_cam_conf)(void *data);
91void* (*LINK_cam_frame)(void *data);
92bool (*LINK_jpeg_encoder_init)();
93void (*LINK_jpeg_encoder_join)();
94bool (*LINK_jpeg_encoder_encode)(const cam_ctrl_dimension_t *dimen,
95 const uint8_t *thumbnailbuf, int thumbnailfd,
96 const uint8_t *snapshotbuf, int snapshotfd,
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -080097 common_crop_t *scaling_parms, exif_tags_info_t *exif_data,
Mohan Kandra1659b0c2010-07-18 16:36:25 -070098 int exif_table_numEntries, int jpegPadding, const int32_t cbcroffset);
Kiran Kumar H N7ac84e32010-02-01 10:58:47 -080099void (*LINK_camframe_terminate)(void);
Sravankb4f5f1c2010-01-21 11:06:17 +0530100//for 720p
101// Function to add a video buffer to free Q
102void (*LINK_camframe_free_video)(struct msm_frame *frame);
103// Function pointer , called by camframe when a video frame is available.
104void (**LINK_camframe_video_callback)(struct msm_frame * frame);
105// To flush free Q in cam frame.
106void (*LINK_cam_frame_flush_free_video)(void);
107
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800108int8_t (*LINK_jpeg_encoder_setMainImageQuality)(uint32_t quality);
109int8_t (*LINK_jpeg_encoder_setThumbnailQuality)(uint32_t quality);
110int8_t (*LINK_jpeg_encoder_setRotation)(uint32_t rotation);
Mohan Kandra02486042010-06-18 16:49:43 -0700111int8_t (*LINK_jpeg_encoder_get_buffer_offset)(uint32_t width, uint32_t height,
112 uint32_t* p_y_offset,
113 uint32_t* p_cbcr_offset,
114 uint32_t* p_buf_size);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800115int8_t (*LINK_jpeg_encoder_setLocation)(const camera_position_type *location);
116const struct camera_size_type *(*LINK_default_sensor_get_snapshot_sizes)(int *len);
117int (*LINK_launch_cam_conf_thread)(void);
118int (*LINK_release_cam_conf_thread)(void);
Nishant Pandit741742b2010-09-21 03:24:20 +0530119mm_camera_status_t (*LINK_mm_camera_config_init)(mm_camera_config *);
120mm_camera_status_t (*LINK_mm_camera_config_deinit)(mm_camera_config *);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800121int8_t (*LINK_zoom_crop_upscale)(uint32_t width, uint32_t height,
122 uint32_t cropped_width, uint32_t cropped_height, uint8_t *img_buf);
123
124// callbacks
125void (**LINK_mmcamera_camframe_callback)(struct msm_frame *frame);
Nishant Pandit741742b2010-09-21 03:24:20 +0530126void (**LINK_mmcamera_camstats_callback)(camstats_type stype, camera_preview_histogram_info* histinfo);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800127void (**LINK_mmcamera_jpegfragment_callback)(uint8_t *buff_ptr,
128 uint32_t buff_size);
129void (**LINK_mmcamera_jpeg_callback)(jpeg_event_t status);
130void (**LINK_mmcamera_shutter_callback)(common_crop_t *crop);
Mohan Kandra3dd524f2010-09-20 13:41:42 -0700131void (**LINK_camframe_error_callback)(camera_error_type err);
Vamshidhar Kondra92ce9142010-09-03 18:22:08 +0530132void (**LINK_mmcamera_liveshot_callback)(liveshot_status status, uint32_t jpeg_size);
133void (**LINK_cancel_liveshot)(void);
134int8_t (*LINK_set_liveshot_params)(uint32_t a_width, uint32_t a_height, exif_tags_info_t *a_exif_data,
135 int a_exif_numEntries, uint8_t* a_out_buffer, uint32_t a_outbuffer_size);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800136#else
137#define LINK_cam_conf cam_conf
138#define LINK_cam_frame cam_frame
139#define LINK_jpeg_encoder_init jpeg_encoder_init
140#define LINK_jpeg_encoder_join jpeg_encoder_join
141#define LINK_jpeg_encoder_encode jpeg_encoder_encode
142#define LINK_camframe_terminate camframe_terminate
143#define LINK_jpeg_encoder_setMainImageQuality jpeg_encoder_setMainImageQuality
144#define LINK_jpeg_encoder_setThumbnailQuality jpeg_encoder_setThumbnailQuality
145#define LINK_jpeg_encoder_setRotation jpeg_encoder_setRotation
Mohan Kandra02486042010-06-18 16:49:43 -0700146#define LINK_jpeg_encoder_get_buffer_offset jpeg_encoder_get_buffer_offset
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800147#define LINK_jpeg_encoder_setLocation jpeg_encoder_setLocation
148#define LINK_default_sensor_get_snapshot_sizes default_sensor_get_snapshot_sizes
149#define LINK_launch_cam_conf_thread launch_cam_conf_thread
150#define LINK_release_cam_conf_thread release_cam_conf_thread
151#define LINK_zoom_crop_upscale zoom_crop_upscale
Nishant Pandit741742b2010-09-21 03:24:20 +0530152#define LINK_mm_camera_config_init mm_camera_config_init
153#define LINK_mm_camera_config_deinit mm_camera_config_deinit
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800154extern void (*mmcamera_camframe_callback)(struct msm_frame *frame);
Nishant Pandit741742b2010-09-21 03:24:20 +0530155extern void (*mmcamera_camstats_callback)(camstats_type stype, camera_preview_histogram_info* histinfo);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800156extern void (*mmcamera_jpegfragment_callback)(uint8_t *buff_ptr,
157 uint32_t buff_size);
158extern void (*mmcamera_jpeg_callback)(jpeg_event_t status);
159extern void (*mmcamera_shutter_callback)(common_crop_t *crop);
Vamshidhar Kondra92ce9142010-09-03 18:22:08 +0530160extern void (*mmcamera_liveshot_callback)(liveshot_status status, uint32_t jpeg_size);
161#define LINK_set_liveshot_params set_liveshot_params
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800162#endif
163
164} // extern "C"
165
166#ifndef HAVE_CAMERA_SIZE_TYPE
167struct camera_size_type {
168 int width;
169 int height;
170};
171#endif
172
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -0800173typedef struct crop_info_struct {
174 uint32_t x;
175 uint32_t y;
176 uint32_t w;
177 uint32_t h;
178} zoom_crop_info;
179
Mohan Kandra740cfce2010-01-07 12:58:24 -0800180union zoomimage
Mohan Kandra284966d2010-01-05 13:39:15 -0800181{
182 char d[sizeof(struct mdp_blit_req_list) + sizeof(struct mdp_blit_req) * 1];
183 struct mdp_blit_req_list list;
184} zoomImage;
185
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800186//Default to WVGA
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -0800187#define DEFAULT_PREVIEW_WIDTH 800
188#define DEFAULT_PREVIEW_HEIGHT 480
189
Srinivasan Kannana01751b2010-06-24 18:44:40 -0700190//Default FPS
191#define MINIMUM_FPS 5
Mohan Kandrae3077162010-10-05 17:01:25 -0700192#define MAXIMUM_FPS 31
Srinivasan Kannana01751b2010-06-24 18:44:40 -0700193#define DEFAULT_FPS MAXIMUM_FPS
194
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -0800195/*
196 * Modifying preview size requires modification
197 * in bitmasks for boardproperties
198 */
199
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800200static const camera_size_type preview_sizes[] = {
Nishant Pandit2f7681e2010-08-18 02:44:54 +0530201 { 1920, 1088 }, //1080p
Srinivasan Kannanfa7edae2009-12-16 18:02:01 -0800202 { 1280, 720 }, // 720P, reserved
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800203 { 800, 480 }, // WVGA
Srinivasan Kannan613301c2010-02-10 17:08:53 -0800204 { 768, 432 },
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800205 { 720, 480 },
206 { 640, 480 }, // VGA
207 { 576, 432 },
208 { 480, 320 }, // HVGA
209 { 384, 288 },
210 { 352, 288 }, // CIF
211 { 320, 240 }, // QVGA
212 { 240, 160 }, // SQVGA
213 { 176, 144 }, // QCIF
214};
215#define PREVIEW_SIZE_COUNT (sizeof(preview_sizes)/sizeof(camera_size_type))
216
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -0800217static camera_size_type supportedPreviewSizes[PREVIEW_SIZE_COUNT];
218static unsigned int previewSizeCount;
219
220board_property boardProperties[] = {
Apurva Rajgurue5965c42010-09-09 14:24:54 -0700221 {TARGET_MSM7625, 0x00000fff, false, false},
222 {TARGET_MSM7627, 0x000006ff, false, false},
223 {TARGET_MSM7630, 0x00000fff, true, true},
224 {TARGET_MSM8660, 0x00001fff, true, true},
225 {TARGET_QSD8250, 0x00000fff, false, false}
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -0800226};
227
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800228//static const camera_size_type* picture_sizes;
229//static int PICTURE_SIZE_COUNT;
230/* TODO
231 * Ideally this should be a populated by lower layers.
232 * But currently this is no API to do that at lower layer.
233 * Hence populating with default sizes for now. This needs
234 * to be changed once the API is supported.
235 */
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800236//sorted on column basis
Nishant Pandit741742b2010-09-21 03:24:20 +0530237static camera_size_type* picture_sizes;
238static unsigned int PICTURE_SIZE_COUNT;
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800239static const camera_size_type * picture_sizes_ptr;
240static int supportedPictureSizesCount;
Vamshidhar Kondra92ce9142010-09-03 18:22:08 +0530241static liveshotState liveshot_state = LIVESHOT_DONE;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800242
Srinivasan Kannan80d878f2009-12-18 15:06:02 -0800243#ifdef Q12
244#undef Q12
245#endif
246
247#define Q12 4096
248
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -0800249static const target_map targetList [] = {
250 { "msm7625", TARGET_MSM7625 },
251 { "msm7627", TARGET_MSM7627 },
252 { "qsd8250", TARGET_QSD8250 },
Nishant Pandit3c278cd2010-07-13 15:56:04 +0530253 { "msm7630", TARGET_MSM7630 },
254 { "msm8660", TARGET_MSM8660 }
255
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -0800256};
257static targetType mCurrentTarget = TARGET_MAX;
258
Srinivasan Kannan80d878f2009-12-18 15:06:02 -0800259typedef struct {
260 uint32_t aspect_ratio;
261 uint32_t width;
262 uint32_t height;
263} thumbnail_size_type;
264
265static thumbnail_size_type thumbnail_sizes[] = {
266 { 7281, 512, 288 }, //1.777778
267 { 6826, 480, 288 }, //1.666667
Kiran Kumar H Nb49af212010-02-17 15:12:17 -0800268 { 6144, 432, 288 }, //1.5
Srinivasan Kannan80d878f2009-12-18 15:06:02 -0800269 { 5461, 512, 384 }, //1.333333
270 { 5006, 352, 288 }, //1.222222
271};
272#define THUMBNAIL_SIZE_COUNT (sizeof(thumbnail_sizes)/sizeof(thumbnail_size_type))
273#define DEFAULT_THUMBNAIL_SETTING 2
274#define THUMBNAIL_WIDTH_STR "512"
275#define THUMBNAIL_HEIGHT_STR "384"
276#define THUMBNAIL_SMALL_HEIGHT 144
Srinivasan Kannan264376e2010-08-13 18:54:35 -0700277static camera_size_type jpeg_thumbnail_sizes[] = {
278 { 512, 288 },
279 { 480, 288 },
280 { 432, 288 },
281 { 512, 384 },
282 { 352, 288 },
283 {0,0}
284};
Srinivasan Kannan80d878f2009-12-18 15:06:02 -0800285
Srinivasan Kannan264376e2010-08-13 18:54:35 -0700286#define JPEG_THUMBNAIL_SIZE_COUNT (sizeof(jpeg_thumbnail_sizes)/sizeof(camera_size_type))
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800287static int attr_lookup(const str_map arr[], int len, const char *name)
288{
289 if (name) {
290 for (int i = 0; i < len; i++) {
291 if (!strcmp(arr[i].desc, name))
292 return arr[i].val;
293 }
294 }
295 return NOT_FOUND;
296}
297
298// round to the next power of two
299static inline unsigned clp2(unsigned x)
300{
301 x = x - 1;
302 x = x | (x >> 1);
303 x = x | (x >> 2);
304 x = x | (x >> 4);
305 x = x | (x >> 8);
306 x = x | (x >>16);
307 return x + 1;
308}
309
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -0800310static int exif_table_numEntries = 0;
Srinivasan Kannan09de3382010-08-16 16:42:00 -0700311#define MAX_EXIF_TABLE_ENTRIES 11
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -0800312exif_tags_info_t exif_data[MAX_EXIF_TABLE_ENTRIES];
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -0800313static zoom_crop_info zoomCropInfo;
314static void *mLastQueuedFrame = NULL;
Haynes George7dbe49d2010-08-09 12:33:12 -0700315#define RECORD_BUFFERS 9
Vinay Kaliaba3555f2010-07-21 11:37:36 -0700316#define RECORD_BUFFERS_8x50 8
Apurva Rajguruc73c1722010-04-15 17:39:11 -0700317static int kRecordBufferCount;
Mohan Kandra39fad8d2010-07-15 12:29:19 -0700318/* controls whether VPE is avialable for the target
319 * under consideration.
320 * 1: VPE support is available
321 * 0: VPE support is not available (default)
322 */
323static bool mVpeEnabled;
Apurva Rajguruc73c1722010-04-15 17:39:11 -0700324
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -0800325
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800326namespace android {
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800327
328static const int PICTURE_FORMAT_JPEG = 1;
329static const int PICTURE_FORMAT_RAW = 2;
330
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800331// from aeecamera.h
332static const str_map whitebalance[] = {
333 { CameraParameters::WHITE_BALANCE_AUTO, CAMERA_WB_AUTO },
334 { CameraParameters::WHITE_BALANCE_INCANDESCENT, CAMERA_WB_INCANDESCENT },
335 { CameraParameters::WHITE_BALANCE_FLUORESCENT, CAMERA_WB_FLUORESCENT },
336 { CameraParameters::WHITE_BALANCE_DAYLIGHT, CAMERA_WB_DAYLIGHT },
337 { CameraParameters::WHITE_BALANCE_CLOUDY_DAYLIGHT, CAMERA_WB_CLOUDY_DAYLIGHT }
338};
339
340// from camera_effect_t. This list must match aeecamera.h
341static const str_map effects[] = {
342 { CameraParameters::EFFECT_NONE, CAMERA_EFFECT_OFF },
343 { CameraParameters::EFFECT_MONO, CAMERA_EFFECT_MONO },
344 { CameraParameters::EFFECT_NEGATIVE, CAMERA_EFFECT_NEGATIVE },
345 { CameraParameters::EFFECT_SOLARIZE, CAMERA_EFFECT_SOLARIZE },
346 { CameraParameters::EFFECT_SEPIA, CAMERA_EFFECT_SEPIA },
347 { CameraParameters::EFFECT_POSTERIZE, CAMERA_EFFECT_POSTERIZE },
348 { CameraParameters::EFFECT_WHITEBOARD, CAMERA_EFFECT_WHITEBOARD },
349 { CameraParameters::EFFECT_BLACKBOARD, CAMERA_EFFECT_BLACKBOARD },
350 { CameraParameters::EFFECT_AQUA, CAMERA_EFFECT_AQUA }
351};
352
353// from qcamera/common/camera.h
Apurva Rajguru55562b02009-12-03 12:25:35 -0800354static const str_map autoexposure[] = {
355 { CameraParameters::AUTO_EXPOSURE_FRAME_AVG, CAMERA_AEC_FRAME_AVERAGE },
356 { CameraParameters::AUTO_EXPOSURE_CENTER_WEIGHTED, CAMERA_AEC_CENTER_WEIGHTED },
357 { CameraParameters::AUTO_EXPOSURE_SPOT_METERING, CAMERA_AEC_SPOT_METERING }
358};
359
360// from qcamera/common/camera.h
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800361static const str_map antibanding[] = {
362 { CameraParameters::ANTIBANDING_OFF, CAMERA_ANTIBANDING_OFF },
363 { CameraParameters::ANTIBANDING_50HZ, CAMERA_ANTIBANDING_50HZ },
364 { CameraParameters::ANTIBANDING_60HZ, CAMERA_ANTIBANDING_60HZ },
365 { CameraParameters::ANTIBANDING_AUTO, CAMERA_ANTIBANDING_AUTO }
366};
367
368/* Mapping from MCC to antibanding type */
369struct country_map {
370 uint32_t country_code;
371 camera_antibanding_type type;
372};
373
374static struct country_map country_numeric[] = {
375 { 202, CAMERA_ANTIBANDING_50HZ }, // Greece
376 { 204, CAMERA_ANTIBANDING_50HZ }, // Netherlands
377 { 206, CAMERA_ANTIBANDING_50HZ }, // Belgium
378 { 208, CAMERA_ANTIBANDING_50HZ }, // France
379 { 212, CAMERA_ANTIBANDING_50HZ }, // Monaco
380 { 213, CAMERA_ANTIBANDING_50HZ }, // Andorra
381 { 214, CAMERA_ANTIBANDING_50HZ }, // Spain
382 { 216, CAMERA_ANTIBANDING_50HZ }, // Hungary
383 { 219, CAMERA_ANTIBANDING_50HZ }, // Croatia
384 { 220, CAMERA_ANTIBANDING_50HZ }, // Serbia
385 { 222, CAMERA_ANTIBANDING_50HZ }, // Italy
386 { 226, CAMERA_ANTIBANDING_50HZ }, // Romania
387 { 228, CAMERA_ANTIBANDING_50HZ }, // Switzerland
388 { 230, CAMERA_ANTIBANDING_50HZ }, // Czech Republic
389 { 231, CAMERA_ANTIBANDING_50HZ }, // Slovakia
390 { 232, CAMERA_ANTIBANDING_50HZ }, // Austria
391 { 234, CAMERA_ANTIBANDING_50HZ }, // United Kingdom
392 { 235, CAMERA_ANTIBANDING_50HZ }, // United Kingdom
393 { 238, CAMERA_ANTIBANDING_50HZ }, // Denmark
394 { 240, CAMERA_ANTIBANDING_50HZ }, // Sweden
395 { 242, CAMERA_ANTIBANDING_50HZ }, // Norway
396 { 244, CAMERA_ANTIBANDING_50HZ }, // Finland
397 { 246, CAMERA_ANTIBANDING_50HZ }, // Lithuania
398 { 247, CAMERA_ANTIBANDING_50HZ }, // Latvia
399 { 248, CAMERA_ANTIBANDING_50HZ }, // Estonia
400 { 250, CAMERA_ANTIBANDING_50HZ }, // Russian Federation
401 { 255, CAMERA_ANTIBANDING_50HZ }, // Ukraine
402 { 257, CAMERA_ANTIBANDING_50HZ }, // Belarus
403 { 259, CAMERA_ANTIBANDING_50HZ }, // Moldova
404 { 260, CAMERA_ANTIBANDING_50HZ }, // Poland
405 { 262, CAMERA_ANTIBANDING_50HZ }, // Germany
406 { 266, CAMERA_ANTIBANDING_50HZ }, // Gibraltar
407 { 268, CAMERA_ANTIBANDING_50HZ }, // Portugal
408 { 270, CAMERA_ANTIBANDING_50HZ }, // Luxembourg
409 { 272, CAMERA_ANTIBANDING_50HZ }, // Ireland
410 { 274, CAMERA_ANTIBANDING_50HZ }, // Iceland
411 { 276, CAMERA_ANTIBANDING_50HZ }, // Albania
412 { 278, CAMERA_ANTIBANDING_50HZ }, // Malta
413 { 280, CAMERA_ANTIBANDING_50HZ }, // Cyprus
414 { 282, CAMERA_ANTIBANDING_50HZ }, // Georgia
415 { 283, CAMERA_ANTIBANDING_50HZ }, // Armenia
416 { 284, CAMERA_ANTIBANDING_50HZ }, // Bulgaria
417 { 286, CAMERA_ANTIBANDING_50HZ }, // Turkey
418 { 288, CAMERA_ANTIBANDING_50HZ }, // Faroe Islands
419 { 290, CAMERA_ANTIBANDING_50HZ }, // Greenland
420 { 293, CAMERA_ANTIBANDING_50HZ }, // Slovenia
421 { 294, CAMERA_ANTIBANDING_50HZ }, // Macedonia
422 { 295, CAMERA_ANTIBANDING_50HZ }, // Liechtenstein
423 { 297, CAMERA_ANTIBANDING_50HZ }, // Montenegro
424 { 302, CAMERA_ANTIBANDING_60HZ }, // Canada
425 { 310, CAMERA_ANTIBANDING_60HZ }, // United States of America
426 { 311, CAMERA_ANTIBANDING_60HZ }, // United States of America
427 { 312, CAMERA_ANTIBANDING_60HZ }, // United States of America
428 { 313, CAMERA_ANTIBANDING_60HZ }, // United States of America
429 { 314, CAMERA_ANTIBANDING_60HZ }, // United States of America
430 { 315, CAMERA_ANTIBANDING_60HZ }, // United States of America
431 { 316, CAMERA_ANTIBANDING_60HZ }, // United States of America
432 { 330, CAMERA_ANTIBANDING_60HZ }, // Puerto Rico
433 { 334, CAMERA_ANTIBANDING_60HZ }, // Mexico
434 { 338, CAMERA_ANTIBANDING_50HZ }, // Jamaica
435 { 340, CAMERA_ANTIBANDING_50HZ }, // Martinique
436 { 342, CAMERA_ANTIBANDING_50HZ }, // Barbados
437 { 346, CAMERA_ANTIBANDING_60HZ }, // Cayman Islands
438 { 350, CAMERA_ANTIBANDING_60HZ }, // Bermuda
439 { 352, CAMERA_ANTIBANDING_50HZ }, // Grenada
440 { 354, CAMERA_ANTIBANDING_60HZ }, // Montserrat
441 { 362, CAMERA_ANTIBANDING_50HZ }, // Netherlands Antilles
442 { 363, CAMERA_ANTIBANDING_60HZ }, // Aruba
443 { 364, CAMERA_ANTIBANDING_60HZ }, // Bahamas
444 { 365, CAMERA_ANTIBANDING_60HZ }, // Anguilla
445 { 366, CAMERA_ANTIBANDING_50HZ }, // Dominica
446 { 368, CAMERA_ANTIBANDING_60HZ }, // Cuba
447 { 370, CAMERA_ANTIBANDING_60HZ }, // Dominican Republic
448 { 372, CAMERA_ANTIBANDING_60HZ }, // Haiti
449 { 401, CAMERA_ANTIBANDING_50HZ }, // Kazakhstan
450 { 402, CAMERA_ANTIBANDING_50HZ }, // Bhutan
451 { 404, CAMERA_ANTIBANDING_50HZ }, // India
452 { 405, CAMERA_ANTIBANDING_50HZ }, // India
453 { 410, CAMERA_ANTIBANDING_50HZ }, // Pakistan
454 { 413, CAMERA_ANTIBANDING_50HZ }, // Sri Lanka
455 { 414, CAMERA_ANTIBANDING_50HZ }, // Myanmar
456 { 415, CAMERA_ANTIBANDING_50HZ }, // Lebanon
457 { 416, CAMERA_ANTIBANDING_50HZ }, // Jordan
458 { 417, CAMERA_ANTIBANDING_50HZ }, // Syria
459 { 418, CAMERA_ANTIBANDING_50HZ }, // Iraq
460 { 419, CAMERA_ANTIBANDING_50HZ }, // Kuwait
461 { 420, CAMERA_ANTIBANDING_60HZ }, // Saudi Arabia
462 { 421, CAMERA_ANTIBANDING_50HZ }, // Yemen
463 { 422, CAMERA_ANTIBANDING_50HZ }, // Oman
464 { 424, CAMERA_ANTIBANDING_50HZ }, // United Arab Emirates
465 { 425, CAMERA_ANTIBANDING_50HZ }, // Israel
466 { 426, CAMERA_ANTIBANDING_50HZ }, // Bahrain
467 { 427, CAMERA_ANTIBANDING_50HZ }, // Qatar
468 { 428, CAMERA_ANTIBANDING_50HZ }, // Mongolia
469 { 429, CAMERA_ANTIBANDING_50HZ }, // Nepal
470 { 430, CAMERA_ANTIBANDING_50HZ }, // United Arab Emirates
471 { 431, CAMERA_ANTIBANDING_50HZ }, // United Arab Emirates
472 { 432, CAMERA_ANTIBANDING_50HZ }, // Iran
473 { 434, CAMERA_ANTIBANDING_50HZ }, // Uzbekistan
474 { 436, CAMERA_ANTIBANDING_50HZ }, // Tajikistan
475 { 437, CAMERA_ANTIBANDING_50HZ }, // Kyrgyz Rep
476 { 438, CAMERA_ANTIBANDING_50HZ }, // Turkmenistan
477 { 440, CAMERA_ANTIBANDING_60HZ }, // Japan
478 { 441, CAMERA_ANTIBANDING_60HZ }, // Japan
479 { 452, CAMERA_ANTIBANDING_50HZ }, // Vietnam
480 { 454, CAMERA_ANTIBANDING_50HZ }, // Hong Kong
481 { 455, CAMERA_ANTIBANDING_50HZ }, // Macao
482 { 456, CAMERA_ANTIBANDING_50HZ }, // Cambodia
483 { 457, CAMERA_ANTIBANDING_50HZ }, // Laos
484 { 460, CAMERA_ANTIBANDING_50HZ }, // China
485 { 466, CAMERA_ANTIBANDING_60HZ }, // Taiwan
486 { 470, CAMERA_ANTIBANDING_50HZ }, // Bangladesh
487 { 472, CAMERA_ANTIBANDING_50HZ }, // Maldives
488 { 502, CAMERA_ANTIBANDING_50HZ }, // Malaysia
489 { 505, CAMERA_ANTIBANDING_50HZ }, // Australia
490 { 510, CAMERA_ANTIBANDING_50HZ }, // Indonesia
491 { 514, CAMERA_ANTIBANDING_50HZ }, // East Timor
492 { 515, CAMERA_ANTIBANDING_60HZ }, // Philippines
493 { 520, CAMERA_ANTIBANDING_50HZ }, // Thailand
494 { 525, CAMERA_ANTIBANDING_50HZ }, // Singapore
495 { 530, CAMERA_ANTIBANDING_50HZ }, // New Zealand
496 { 535, CAMERA_ANTIBANDING_60HZ }, // Guam
497 { 536, CAMERA_ANTIBANDING_50HZ }, // Nauru
498 { 537, CAMERA_ANTIBANDING_50HZ }, // Papua New Guinea
499 { 539, CAMERA_ANTIBANDING_50HZ }, // Tonga
500 { 541, CAMERA_ANTIBANDING_50HZ }, // Vanuatu
501 { 542, CAMERA_ANTIBANDING_50HZ }, // Fiji
502 { 544, CAMERA_ANTIBANDING_60HZ }, // American Samoa
503 { 545, CAMERA_ANTIBANDING_50HZ }, // Kiribati
504 { 546, CAMERA_ANTIBANDING_50HZ }, // New Caledonia
505 { 548, CAMERA_ANTIBANDING_50HZ }, // Cook Islands
506 { 602, CAMERA_ANTIBANDING_50HZ }, // Egypt
507 { 603, CAMERA_ANTIBANDING_50HZ }, // Algeria
508 { 604, CAMERA_ANTIBANDING_50HZ }, // Morocco
509 { 605, CAMERA_ANTIBANDING_50HZ }, // Tunisia
510 { 606, CAMERA_ANTIBANDING_50HZ }, // Libya
511 { 607, CAMERA_ANTIBANDING_50HZ }, // Gambia
512 { 608, CAMERA_ANTIBANDING_50HZ }, // Senegal
513 { 609, CAMERA_ANTIBANDING_50HZ }, // Mauritania
514 { 610, CAMERA_ANTIBANDING_50HZ }, // Mali
515 { 611, CAMERA_ANTIBANDING_50HZ }, // Guinea
516 { 613, CAMERA_ANTIBANDING_50HZ }, // Burkina Faso
517 { 614, CAMERA_ANTIBANDING_50HZ }, // Niger
518 { 616, CAMERA_ANTIBANDING_50HZ }, // Benin
519 { 617, CAMERA_ANTIBANDING_50HZ }, // Mauritius
520 { 618, CAMERA_ANTIBANDING_50HZ }, // Liberia
521 { 619, CAMERA_ANTIBANDING_50HZ }, // Sierra Leone
522 { 620, CAMERA_ANTIBANDING_50HZ }, // Ghana
523 { 621, CAMERA_ANTIBANDING_50HZ }, // Nigeria
524 { 622, CAMERA_ANTIBANDING_50HZ }, // Chad
525 { 623, CAMERA_ANTIBANDING_50HZ }, // Central African Republic
526 { 624, CAMERA_ANTIBANDING_50HZ }, // Cameroon
527 { 625, CAMERA_ANTIBANDING_50HZ }, // Cape Verde
528 { 627, CAMERA_ANTIBANDING_50HZ }, // Equatorial Guinea
529 { 631, CAMERA_ANTIBANDING_50HZ }, // Angola
530 { 633, CAMERA_ANTIBANDING_50HZ }, // Seychelles
531 { 634, CAMERA_ANTIBANDING_50HZ }, // Sudan
532 { 636, CAMERA_ANTIBANDING_50HZ }, // Ethiopia
533 { 637, CAMERA_ANTIBANDING_50HZ }, // Somalia
534 { 638, CAMERA_ANTIBANDING_50HZ }, // Djibouti
535 { 639, CAMERA_ANTIBANDING_50HZ }, // Kenya
536 { 640, CAMERA_ANTIBANDING_50HZ }, // Tanzania
537 { 641, CAMERA_ANTIBANDING_50HZ }, // Uganda
538 { 642, CAMERA_ANTIBANDING_50HZ }, // Burundi
539 { 643, CAMERA_ANTIBANDING_50HZ }, // Mozambique
540 { 645, CAMERA_ANTIBANDING_50HZ }, // Zambia
541 { 646, CAMERA_ANTIBANDING_50HZ }, // Madagascar
542 { 647, CAMERA_ANTIBANDING_50HZ }, // France
543 { 648, CAMERA_ANTIBANDING_50HZ }, // Zimbabwe
544 { 649, CAMERA_ANTIBANDING_50HZ }, // Namibia
545 { 650, CAMERA_ANTIBANDING_50HZ }, // Malawi
546 { 651, CAMERA_ANTIBANDING_50HZ }, // Lesotho
547 { 652, CAMERA_ANTIBANDING_50HZ }, // Botswana
548 { 653, CAMERA_ANTIBANDING_50HZ }, // Swaziland
549 { 654, CAMERA_ANTIBANDING_50HZ }, // Comoros
550 { 655, CAMERA_ANTIBANDING_50HZ }, // South Africa
551 { 657, CAMERA_ANTIBANDING_50HZ }, // Eritrea
552 { 702, CAMERA_ANTIBANDING_60HZ }, // Belize
553 { 704, CAMERA_ANTIBANDING_60HZ }, // Guatemala
554 { 706, CAMERA_ANTIBANDING_60HZ }, // El Salvador
555 { 708, CAMERA_ANTIBANDING_60HZ }, // Honduras
556 { 710, CAMERA_ANTIBANDING_60HZ }, // Nicaragua
557 { 712, CAMERA_ANTIBANDING_60HZ }, // Costa Rica
558 { 714, CAMERA_ANTIBANDING_60HZ }, // Panama
559 { 722, CAMERA_ANTIBANDING_50HZ }, // Argentina
560 { 724, CAMERA_ANTIBANDING_60HZ }, // Brazil
561 { 730, CAMERA_ANTIBANDING_50HZ }, // Chile
562 { 732, CAMERA_ANTIBANDING_60HZ }, // Colombia
563 { 734, CAMERA_ANTIBANDING_60HZ }, // Venezuela
564 { 736, CAMERA_ANTIBANDING_50HZ }, // Bolivia
565 { 738, CAMERA_ANTIBANDING_60HZ }, // Guyana
566 { 740, CAMERA_ANTIBANDING_60HZ }, // Ecuador
567 { 742, CAMERA_ANTIBANDING_50HZ }, // French Guiana
568 { 744, CAMERA_ANTIBANDING_50HZ }, // Paraguay
569 { 746, CAMERA_ANTIBANDING_60HZ }, // Suriname
570 { 748, CAMERA_ANTIBANDING_50HZ }, // Uruguay
571 { 750, CAMERA_ANTIBANDING_50HZ }, // Falkland Islands
572};
573
Apurva Rajguru08383852010-05-17 14:25:39 -0700574static const str_map scenemode[] = {
575 { CameraParameters::SCENE_MODE_AUTO, CAMERA_BESTSHOT_OFF },
576 { CameraParameters::SCENE_MODE_ACTION, CAMERA_BESTSHOT_ACTION },
577 { CameraParameters::SCENE_MODE_PORTRAIT, CAMERA_BESTSHOT_PORTRAIT },
578 { CameraParameters::SCENE_MODE_LANDSCAPE, CAMERA_BESTSHOT_LANDSCAPE },
579 { CameraParameters::SCENE_MODE_NIGHT, CAMERA_BESTSHOT_NIGHT },
580 { CameraParameters::SCENE_MODE_NIGHT_PORTRAIT, CAMERA_BESTSHOT_NIGHT_PORTRAIT },
581 { CameraParameters::SCENE_MODE_THEATRE, CAMERA_BESTSHOT_THEATRE },
582 { CameraParameters::SCENE_MODE_BEACH, CAMERA_BESTSHOT_BEACH },
583 { CameraParameters::SCENE_MODE_SNOW, CAMERA_BESTSHOT_SNOW },
584 { CameraParameters::SCENE_MODE_SUNSET, CAMERA_BESTSHOT_SUNSET },
585 { CameraParameters::SCENE_MODE_STEADYPHOTO, CAMERA_BESTSHOT_ANTISHAKE },
586 { CameraParameters::SCENE_MODE_FIREWORKS , CAMERA_BESTSHOT_FIREWORKS },
587 { CameraParameters::SCENE_MODE_SPORTS , CAMERA_BESTSHOT_SPORTS },
588 { CameraParameters::SCENE_MODE_PARTY, CAMERA_BESTSHOT_PARTY },
589 { CameraParameters::SCENE_MODE_CANDLELIGHT, CAMERA_BESTSHOT_CANDLELIGHT },
590 { CameraParameters::SCENE_MODE_BACKLIGHT, CAMERA_BESTSHOT_BACKLIGHT },
591 { CameraParameters::SCENE_MODE_FLOWERS, CAMERA_BESTSHOT_FLOWERS },
592};
593
Apurva Rajguru8e0a8da2010-06-02 11:26:36 -0700594static const str_map scenedetect[] = {
595 { CameraParameters::SCENE_DETECT_OFF, FALSE },
596 { CameraParameters::SCENE_DETECT_ON, TRUE },
597};
598
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800599#define country_number (sizeof(country_numeric) / sizeof(country_map))
Srinivasan Kannan264376e2010-08-13 18:54:35 -0700600/* TODO : setting dummy values as of now, need to query for correct
601 * values from sensor in future
602 */
603#define CAMERA_FOCAL_LENGTH_DEFAULT 4.31
604#define CAMERA_HORIZONTAL_VIEW_ANGLE_DEFAULT 54.8
605#define CAMERA_VERTICAL_VIEW_ANGLE_DEFAULT 42.5
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800606
607/* Look up pre-sorted antibanding_type table by current MCC. */
608static camera_antibanding_type camera_get_location(void) {
609 char value[PROP_VALUE_MAX];
610 char country_value[PROP_VALUE_MAX];
611 uint32_t country_code, count;
612 memset(value, 0x00, sizeof(value));
613 memset(country_value, 0x00, sizeof(country_value));
614 if (!__system_property_get("gsm.operator.numeric", value)) {
615 return CAMERA_ANTIBANDING_60HZ;
616 }
617 memcpy(country_value, value, 3);
618 country_code = atoi(country_value);
619 LOGD("value:%s, country value:%s, country code:%d\n",
620 value, country_value, country_code);
621 int left = 0;
622 int right = country_number - 1;
623 while (left <= right) {
624 int index = (left + right) >> 1;
625 if (country_numeric[index].country_code == country_code)
626 return country_numeric[index].type;
627 else if (country_numeric[index].country_code > country_code)
628 right = index - 1;
629 else
630 left = index + 1;
631 }
632 return CAMERA_ANTIBANDING_60HZ;
633}
634
635// from camera.h, led_mode_t
636static const str_map flash[] = {
637 { CameraParameters::FLASH_MODE_OFF, LED_MODE_OFF },
638 { CameraParameters::FLASH_MODE_AUTO, LED_MODE_AUTO },
Srinivasan Kannanda9a7052010-07-09 10:12:31 -0700639 { CameraParameters::FLASH_MODE_ON, LED_MODE_ON },
640 { CameraParameters::FLASH_MODE_TORCH, LED_MODE_TORCH}
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800641};
642
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530643// from mm-camera/common/camera.h.
644static const str_map iso[] = {
645 { CameraParameters::ISO_AUTO, CAMERA_ISO_AUTO},
646 { CameraParameters::ISO_HJR, CAMERA_ISO_DEBLUR},
647 { CameraParameters::ISO_100, CAMERA_ISO_100},
648 { CameraParameters::ISO_200, CAMERA_ISO_200},
649 { CameraParameters::ISO_400, CAMERA_ISO_400},
Mohan Kandra61db0d02010-04-28 18:28:30 -0700650 { CameraParameters::ISO_800, CAMERA_ISO_800 },
651 { CameraParameters::ISO_1600, CAMERA_ISO_1600 }
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530652};
653
654
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800655#define DONT_CARE 0
656static const str_map focus_modes[] = {
Srinivasan Kannan71229622009-12-04 12:05:58 -0800657 { CameraParameters::FOCUS_MODE_AUTO, AF_MODE_AUTO},
658 { CameraParameters::FOCUS_MODE_INFINITY, DONT_CARE },
659 { CameraParameters::FOCUS_MODE_NORMAL, AF_MODE_NORMAL },
660 { CameraParameters::FOCUS_MODE_MACRO, AF_MODE_MACRO }
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800661};
662
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530663static const str_map lensshade[] = {
664 { CameraParameters::LENSSHADE_ENABLE, TRUE },
665 { CameraParameters::LENSSHADE_DISABLE, FALSE }
666};
667
Nishant Pandit741742b2010-09-21 03:24:20 +0530668static const str_map histogram[] = {
669 { CameraParameters::HISTOGRAM_ENABLE, TRUE },
670 { CameraParameters::HISTOGRAM_DISABLE, FALSE }
671};
672
Apurva Rajguru7b949c92010-05-26 15:46:57 -0700673static const str_map continuous_af[] = {
674 { CameraParameters::CONTINUOUS_AF_OFF, FALSE },
675 { CameraParameters::CONTINUOUS_AF_ON, TRUE }
676};
677
Apurva Rajgurue5965c42010-09-09 14:24:54 -0700678static const str_map selectable_zone_af[] = {
679 { CameraParameters::SELECTABLE_ZONE_AF_AUTO, AUTO },
680 { CameraParameters::SELECTABLE_ZONE_AF_SPOT_METERING, SPOT },
681 { CameraParameters::SELECTABLE_ZONE_AF_CENTER_WEIGHTED, CENTER_WEIGHTED },
682 { CameraParameters::SELECTABLE_ZONE_AF_FRAME_AVERAGE, AVERAGE }
683};
684
Apurva Rajguru0a2cb922010-06-08 15:33:22 -0700685#define DONT_CARE_COORDINATE -1
686static const str_map touchafaec[] = {
687 { CameraParameters::TOUCH_AF_AEC_OFF, FALSE },
688 { CameraParameters::TOUCH_AF_AEC_ON, TRUE }
689};
690
Srinivasan Kannan71229622009-12-04 12:05:58 -0800691struct SensorType {
692 const char *name;
693 int rawPictureWidth;
694 int rawPictureHeight;
695 bool hasAutoFocusSupport;
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800696 int max_supported_snapshot_width;
697 int max_supported_snapshot_height;
Apurva Rajguruffe264a2010-03-09 13:50:53 -0800698 int bitMask;
Srinivasan Kannan71229622009-12-04 12:05:58 -0800699};
700
Srinivasan Kannan4cc4b862010-06-30 14:22:26 -0700701
702/*
703 * Values based on aec.c
704 */
705
Nishant Pandit741742b2010-09-21 03:24:20 +0530706#define CAMERA_HISTOGRAM_ENABLE 1
707#define CAMERA_HISTOGRAM_DISABLE 0
708#define HISTOGRAM_STATS_SIZE 257
709
Srinivasan Kannan4cc4b862010-06-30 14:22:26 -0700710#define EXPOSURE_COMPENSATION_MAXIMUM_NUMERATOR 12
711#define EXPOSURE_COMPENSATION_MINIMUM_NUMERATOR -12
712#define EXPOSURE_COMPENSATION_DEFAULT_NUMERATOR 0
713#define EXPOSURE_COMPENSATION_DENOMINATOR 6
714#define EXPOSURE_COMPENSATION_STEP ((float (1))/EXPOSURE_COMPENSATION_DENOMINATOR)
715
Srinivasan Kannan71229622009-12-04 12:05:58 -0800716static SensorType sensorTypes[] = {
Priyanka Kharat0fa7f9f2010-08-30 19:00:35 -0700717 { "12mp", 5464, 3120, true, 4000, 3000,0x00001fff },
Yen-Pin Hsiaoa6612f12010-07-19 15:17:21 -0700718 { "12mp_sn12m0pz",4032, 3024, true, 4000, 3000,0x00000fff },
Apurva Rajguruffe264a2010-03-09 13:50:53 -0800719 { "5mp", 2608, 1960, true, 2592, 1944,0x00000fff },
720 { "3mp", 2064, 1544, false, 2048, 1536,0x000007ff },
Nishant Pandit2eedc1b2010-09-25 04:47:39 +0530721 { "2mp", 3200, 1200, false, 1600, 1200,0x000007ff },
722 { "ov7692", 640, 480, false, 640, 480, 0x000000ff } }; //Web Camera
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800723
Srinivasan Kannan71229622009-12-04 12:05:58 -0800724
725static SensorType * sensorType;
726
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800727static const str_map picture_formats[] = {
728 {CameraParameters::PIXEL_FORMAT_JPEG, PICTURE_FORMAT_JPEG},
729 {CameraParameters::PIXEL_FORMAT_RAW, PICTURE_FORMAT_RAW}
730};
731
Mohan Kandrabf6146d2010-07-20 18:48:37 -0700732static const str_map frame_rate_modes[] = {
733 {CameraParameters::KEY_PREVIEW_FRAME_RATE_AUTO_MODE, FPS_MODE_AUTO},
734 {CameraParameters::KEY_PREVIEW_FRAME_RATE_FIXED_MODE, FPS_MODE_FIXED}
735};
736
Mohan Kandra7110c242010-07-18 15:34:48 -0700737static int mPreviewFormat;
738static const str_map preview_formats[] = {
739 {CameraParameters::PIXEL_FORMAT_YUV420SP, CAMERA_YUV_420_NV21},
740 {CameraParameters::PIXEL_FORMAT_YUV420SP_ADRENO, CAMERA_YUV_420_NV21_ADRENO}
741};
742
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800743static bool parameter_string_initialized = false;
744static String8 preview_size_values;
745static String8 picture_size_values;
Srinivasan Kannan264376e2010-08-13 18:54:35 -0700746static String8 jpeg_thumbnail_size_values;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800747static String8 antibanding_values;
748static String8 effect_values;
Apurva Rajguru55562b02009-12-03 12:25:35 -0800749static String8 autoexposure_values;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800750static String8 whitebalance_values;
751static String8 flash_values;
752static String8 focus_mode_values;
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530753static String8 iso_values;
754static String8 lensshade_values;
Nishant Pandit741742b2010-09-21 03:24:20 +0530755static String8 histogram_values;
Apurva Rajguru0a2cb922010-06-08 15:33:22 -0700756static String8 touchafaec_values;
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800757static String8 picture_format_values;
Apurva Rajguru08383852010-05-17 14:25:39 -0700758static String8 scenemode_values;
Apurva Rajguru7b949c92010-05-26 15:46:57 -0700759static String8 continuous_af_values;
Srinivasan Kannan6bce42b2010-07-12 19:10:08 -0700760static String8 zoom_ratio_values;
Srinivasan Kannana01751b2010-06-24 18:44:40 -0700761static String8 preview_frame_rate_values;
Mohan Kandrabf6146d2010-07-20 18:48:37 -0700762static String8 frame_rate_mode_values;
Apurva Rajguru8e0a8da2010-06-02 11:26:36 -0700763static String8 scenedetect_values;
Mohan Kandra7110c242010-07-18 15:34:48 -0700764static String8 preview_format_values;
Apurva Rajgurue5965c42010-09-09 14:24:54 -0700765static String8 selectable_zone_af_values;
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800766
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800767static String8 create_sizes_str(const camera_size_type *sizes, int len) {
768 String8 str;
769 char buffer[32];
770
771 if (len > 0) {
772 sprintf(buffer, "%dx%d", sizes[0].width, sizes[0].height);
773 str.append(buffer);
774 }
775 for (int i = 1; i < len; i++) {
776 sprintf(buffer, ",%dx%d", sizes[i].width, sizes[i].height);
777 str.append(buffer);
778 }
779 return str;
780}
781
782static String8 create_values_str(const str_map *values, int len) {
783 String8 str;
784
785 if (len > 0) {
786 str.append(values[0].desc);
787 }
788 for (int i = 1; i < len; i++) {
789 str.append(",");
790 str.append(values[i].desc);
791 }
792 return str;
793}
794
Srinivasan Kannana01751b2010-06-24 18:44:40 -0700795
Srinivasan Kannan6bce42b2010-07-12 19:10:08 -0700796static String8 create_str(int16_t *arr, int length){
797 String8 str;
798 char buffer[32];
799
800 if(length > 0){
801 snprintf(buffer, sizeof(buffer), "%d", arr[0]);
802 str.append(buffer);
803 }
804
805 for (int i =1;i<length;i++){
806 snprintf(buffer, sizeof(buffer), ",%d",arr[i]);
807 str.append(buffer);
808 }
809 return str;
810}
811
Srinivasan Kannana01751b2010-06-24 18:44:40 -0700812static String8 create_values_range_str(int min, int max){
813 String8 str;
814 char buffer[32];
815
816 if(min <= max){
817 snprintf(buffer, sizeof(buffer), "%d", min);
818 str.append(buffer);
819
820 for (int i = min + 1; i <= max; i++) {
821 snprintf(buffer, sizeof(buffer), ",%d", i);
822 str.append(buffer);
823 }
824 }
825 return str;
826}
Srinivasan Kannan6bce42b2010-07-12 19:10:08 -0700827
Sravankb4f5f1c2010-01-21 11:06:17 +0530828extern "C" {
829//------------------------------------------------------------------------
830// : 720p busyQ funcitons
831// --------------------------------------------------------------------
832static struct fifo_queue g_busy_frame_queue =
833 {0, 0, 0, PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER};
834};
835/*===========================================================================
836 * FUNCTION cam_frame_wait_video
837 *
838 * DESCRIPTION this function waits a video in the busy queue
839 * ===========================================================================*/
840
841static void cam_frame_wait_video (void)
842{
843 LOGV("cam_frame_wait_video E ");
844 if ((g_busy_frame_queue.num_of_frames) <=0){
845 pthread_cond_wait(&(g_busy_frame_queue.wait), &(g_busy_frame_queue.mut));
846 }
847 LOGV("cam_frame_wait_video X");
848 return;
849}
850
851/*===========================================================================
852 * FUNCTION cam_frame_flush_video
853 *
854 * DESCRIPTION this function deletes all the buffers in busy queue
855 * ===========================================================================*/
856void cam_frame_flush_video (void)
857{
858 LOGV("cam_frame_flush_video: in n = %d\n", g_busy_frame_queue.num_of_frames);
859 pthread_mutex_lock(&(g_busy_frame_queue.mut));
860
861 while (g_busy_frame_queue.front)
862 {
863 //dequeue from the busy queue
864 struct fifo_node *node = dequeue (&g_busy_frame_queue);
865 if(node)
866 free(node);
867
868 LOGV("cam_frame_flush_video: node \n");
869 }
870 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
871 LOGV("cam_frame_flush_video: out n = %d\n", g_busy_frame_queue.num_of_frames);
872 return ;
873}
874/*===========================================================================
875 * FUNCTION cam_frame_get_video
876 *
877 * DESCRIPTION this function returns a video frame from the head
878 * ===========================================================================*/
879static struct msm_frame * cam_frame_get_video()
880{
881 struct msm_frame *p = NULL;
882 LOGV("cam_frame_get_video... in\n");
883 LOGV("cam_frame_get_video... got lock\n");
884 if (g_busy_frame_queue.front)
885 {
886 //dequeue
887 struct fifo_node *node = dequeue (&g_busy_frame_queue);
888 if (node)
889 {
890 p = (struct msm_frame *)node->f;
891 free (node);
892 }
893 LOGV("cam_frame_get_video... out = %x\n", p->buffer);
894 }
895 return p;
896}
897
898/*===========================================================================
899 * FUNCTION cam_frame_post_video
900 *
901 * DESCRIPTION this function add a busy video frame to the busy queue tails
902 * ===========================================================================*/
903static void cam_frame_post_video (struct msm_frame *p)
904{
905 if (!p)
906 {
907 LOGE("post video , buffer is null");
908 return;
909 }
910 LOGV("cam_frame_post_video... in = %x\n", (unsigned int)(p->buffer));
911 pthread_mutex_lock(&(g_busy_frame_queue.mut));
912 LOGV("post_video got lock. q count before enQ %d", g_busy_frame_queue.num_of_frames);
913 //enqueue to busy queue
914 struct fifo_node *node = (struct fifo_node *)malloc (sizeof (struct fifo_node));
915 if (node)
916 {
917 LOGV(" post video , enqueing in busy queue");
918 node->f = p;
919 node->next = NULL;
920 enqueue (&g_busy_frame_queue, node);
921 LOGV("post_video got lock. q count after enQ %d", g_busy_frame_queue.num_of_frames);
922 }
923 else
924 {
925 LOGE("cam_frame_post_video error... out of memory\n");
926 }
927
928 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
929 pthread_cond_signal(&(g_busy_frame_queue.wait));
930
931 LOGV("cam_frame_post_video... out = %x\n", p->buffer);
932
933 return;
934}
935
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -0800936void QualcommCameraHardware::storeTargetType(void) {
937 char mDeviceName[PROPERTY_VALUE_MAX];
938 property_get("ro.product.device",mDeviceName," ");
939 mCurrentTarget = TARGET_MAX;
940 for( int i = 0; i < TARGET_MAX ; i++) {
941 if( !strncmp(mDeviceName, targetList[i].targetStr, 7)) {
942 mCurrentTarget = targetList[i].targetEnum;
943 break;
944 }
945 }
946 LOGV(" Storing the current target type as %d ", mCurrentTarget );
947 return;
948}
949
Sravankb4f5f1c2010-01-21 11:06:17 +0530950//-------------------------------------------------------------------------------------
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800951static Mutex singleton_lock;
952static bool singleton_releasing;
Srinivasan Kannan78444e42010-06-10 15:39:29 -0700953static nsecs_t singleton_releasing_start_time;
954static const nsecs_t SINGLETON_RELEASING_WAIT_TIME = seconds_to_nanoseconds(5);
955static const nsecs_t SINGLETON_RELEASING_RECHECK_TIMEOUT = seconds_to_nanoseconds(1);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800956static Condition singleton_wait;
957
958static void receive_camframe_callback(struct msm_frame *frame);
Vamshidhar Kondra92ce9142010-09-03 18:22:08 +0530959static void receive_liveshot_callback(liveshot_status status, uint32_t jpeg_size);
Nishant Pandit741742b2010-09-21 03:24:20 +0530960static void receive_camstats_callback(camstats_type stype, camera_preview_histogram_info* histinfo);
Sravankb4f5f1c2010-01-21 11:06:17 +0530961static void receive_camframe_video_callback(struct msm_frame *frame); // 720p
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800962static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size);
963static void receive_jpeg_callback(jpeg_event_t status);
964static void receive_shutter_callback(common_crop_t *crop);
Mohan Kandra3dd524f2010-09-20 13:41:42 -0700965static void receive_camframe_error_callback(camera_error_type err);
Mohan Kandra284966d2010-01-05 13:39:15 -0800966static int fb_fd = -1;
967static int32_t mMaxZoom = 0;
Srinivasan Kannan6bce42b2010-07-12 19:10:08 -0700968static bool zoomSupported = false;
Mohan Kandra284966d2010-01-05 13:39:15 -0800969static bool native_get_maxzoom(int camfd, void *pZm);
Srinivasan Kannan6bce42b2010-07-12 19:10:08 -0700970static bool native_get_zoomratios(int camfd, void *pZr, int maxZoomLevel);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800971
Mohan Kandrad9efed92010-01-15 19:08:39 -0800972static int dstOffset = 0;
973
Brian Steuer07704892009-12-18 18:07:33 -0800974static int camerafd;
975pthread_t w_thread;
976
977void *opencamerafd(void *data) {
978 camerafd = open(MSM_CAMERA_CONTROL, O_RDWR);
979 return NULL;
980}
981
Mohan Kandrad9efed92010-01-15 19:08:39 -0800982/* When using MDP zoom, double the preview buffers. The usage of these
983 * buffers is as follows:
984 * 1. As all the buffers comes under a single FD, and at initial registration,
985 * this FD will be passed to surface flinger, surface flinger can have access
986 * to all the buffers when needed.
987 * 2. Only "kPreviewBufferCount" buffers (SrcSet) will be registered with the
988 * camera driver to receive preview frames. The remaining buffers (DstSet),
989 * will be used at HAL and by surface flinger only when crop information
990 * is present in the frame.
991 * 3. When there is no crop information, there will be no call to MDP zoom,
992 * and the buffers in SrcSet will be passed to surface flinger to display.
993 * 4. With crop information present, MDP zoom will be called, and the final
994 * data will be placed in a buffer from DstSet, and this buffer will be given
995 * to surface flinger to display.
996 */
997#define NUM_MORE_BUFS 2
998
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800999QualcommCameraHardware::QualcommCameraHardware()
1000 : mParameters(),
1001 mCameraRunning(false),
1002 mPreviewInitialized(false),
1003 mFrameThreadRunning(false),
Mohan Kandra156d0ac2010-01-25 16:59:17 -08001004 mVideoThreadRunning(false),
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001005 mSnapshotThreadRunning(false),
Mohan Kandra1659b0c2010-07-18 16:36:25 -07001006 mEncodePending(false),
Mohan Kandraca2e7a92010-06-21 15:48:45 -07001007 mJpegThreadRunning(false),
Mohan Kandra62429cc2010-07-19 10:21:05 -07001008 mInSnapshotMode(false),
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001009 mSnapshotFormat(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001010 mReleasedRecordingFrame(false),
1011 mPreviewFrameSize(0),
1012 mRawSize(0),
Mohan Kandra1659b0c2010-07-18 16:36:25 -07001013 mCbCrOffsetRaw(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001014 mCameraControlFd(-1),
1015 mAutoFocusThreadRunning(false),
1016 mAutoFocusFd(-1),
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001017 mBrightness(0),
Apurva Rajguruf12d9d22010-04-05 16:47:12 -07001018 mHJR(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001019 mInPreviewCallback(false),
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001020 mUseOverlay(0),
1021 mOverlay(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001022 mMsgEnabled(0),
1023 mNotifyCallback(0),
1024 mDataCallback(0),
1025 mDataCallbackTimestamp(0),
Mohan Kandra740cfce2010-01-07 12:58:24 -08001026 mCallbackCookie(0),
Srinivasan Kannana01751b2010-06-24 18:44:40 -07001027 mInitialized(false),
Apurva Rajguru3da1a702010-07-28 12:32:42 -07001028 mDebugFps(0),
Mohan Kandra39fad8d2010-07-15 12:29:19 -07001029 mSnapshotDone(0),
Deepak Kurienbf83f8e2010-09-30 10:29:26 -07001030 mSnapshotPrepare(0),
Mohan Kandra39fad8d2010-07-15 12:29:19 -07001031 mDisEnabled(0),
Mohan Kandra9aff1f42010-09-02 19:00:41 -07001032 mRotation(0),
Mohan Kandra5e4f9d92010-08-26 18:23:50 -07001033 mResetOverlayCrop(false),
1034 mThumbnailWidth(0),
1035 mThumbnailHeight(0)
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001036{
Mohan Kandra0d115d12010-08-19 11:47:15 -07001037 LOGI("QualcommCameraHardware constructor E");
Brian Steuer07704892009-12-18 18:07:33 -08001038 // Start opening camera device in a separate thread/ Since this
1039 // initializes the sensor hardware, this can take a long time. So,
1040 // start the process here so it will be ready by the time it's
1041 // needed.
1042 if ((pthread_create(&w_thread, NULL, opencamerafd, NULL)) != 0) {
1043 LOGE("Camera open thread creation failed");
1044 }
1045
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001046 memset(&mDimension, 0, sizeof(mDimension));
1047 memset(&mCrop, 0, sizeof(mCrop));
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08001048 memset(&zoomCropInfo, 0, sizeof(zoom_crop_info));
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08001049 storeTargetType();
Mohan Kandra740cfce2010-01-07 12:58:24 -08001050 char value[PROPERTY_VALUE_MAX];
1051 property_get("persist.debug.sf.showfps", value, "0");
1052 mDebugFps = atoi(value);
Nishant Pandit3c278cd2010-07-13 15:56:04 +05301053 if( mCurrentTarget == TARGET_MSM7630 || mCurrentTarget == TARGET_MSM8660 ) {
Sravankb4f5f1c2010-01-21 11:06:17 +05301054 kPreviewBufferCountActual = kPreviewBufferCount;
Nishant Pandit3c278cd2010-07-13 15:56:04 +05301055 kRecordBufferCount = RECORD_BUFFERS;
Apurva Rajguruc73c1722010-04-15 17:39:11 -07001056 recordframes = new msm_frame[kRecordBufferCount];
Mohan Kandra1fd90f92010-06-17 14:54:17 -07001057 record_buffers_tracking_flag = new bool[kRecordBufferCount];
Apurva Rajguruc73c1722010-04-15 17:39:11 -07001058 }
1059 else {
Sravankb4f5f1c2010-01-21 11:06:17 +05301060 kPreviewBufferCountActual = kPreviewBufferCount + NUM_MORE_BUFS;
Apurva Rajguruc73c1722010-04-15 17:39:11 -07001061 if( mCurrentTarget == TARGET_QSD8250 ) {
1062 kRecordBufferCount = RECORD_BUFFERS_8x50;
1063 recordframes = new msm_frame[kRecordBufferCount];
Mohan Kandra1fd90f92010-06-17 14:54:17 -07001064 record_buffers_tracking_flag = new bool[kRecordBufferCount];
Apurva Rajguruc73c1722010-04-15 17:39:11 -07001065 }
1066 }
Srinivasan Kannan5701a942010-04-15 16:17:21 -07001067
1068 switch(mCurrentTarget){
1069 case TARGET_MSM7627:
1070 jpegPadding = 8;
1071 break;
1072 case TARGET_QSD8250:
1073 case TARGET_MSM7630:
Nishant Pandit3c278cd2010-07-13 15:56:04 +05301074 case TARGET_MSM8660:
Srinivasan Kannan5701a942010-04-15 16:17:21 -07001075 jpegPadding = 0;
1076 break;
1077 default:
1078 jpegPadding = 0;
1079 break;
1080 }
Mohan Kandra7110c242010-07-18 15:34:48 -07001081 // Initialize with default format values. The format values can be
1082 // overriden when application requests.
1083 mDimension.prev_format = CAMERA_YUV_420_NV21;
1084 mPreviewFormat = CAMERA_YUV_420_NV21;
1085 mDimension.enc_format = CAMERA_YUV_420_NV21;
Mohan Kandra88db27a2010-08-22 12:33:36 -07001086 if((mCurrentTarget == TARGET_MSM7630) || (mCurrentTarget == TARGET_MSM8660))
Mohan Kandra7110c242010-07-18 15:34:48 -07001087 mDimension.enc_format = CAMERA_YUV_420_NV12;
1088
1089 mDimension.main_img_format = CAMERA_YUV_420_NV21;
1090 mDimension.thumb_format = CAMERA_YUV_420_NV21;
1091
Mohan Kandrafdbc2192010-08-24 20:39:59 -07001092 if( (mCurrentTarget == TARGET_MSM7630) || (mCurrentTarget == TARGET_MSM8660) ){
Mohan Kandra39fad8d2010-07-15 12:29:19 -07001093 /* DIS is enabled all the time in VPE support targets.
1094 * No provision for the user to control this.
1095 */
1096 mDisEnabled = 1;
Mohan Kandraec958742010-08-19 10:56:05 -07001097 /* Get the DIS value from properties, to check whether
1098 * DIS is disabled or not
1099 */
1100 property_get("persist.camera.hal.dis", value, "1");
1101 mDisEnabled = atoi(value);
Mohan Kandra39fad8d2010-07-15 12:29:19 -07001102 mVpeEnabled = 1;
1103 }
1104
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001105 LOGV("constructor EX");
1106}
1107
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -08001108void QualcommCameraHardware::filterPreviewSizes(){
1109
Apurva Rajguruffe264a2010-03-09 13:50:53 -08001110 unsigned int boardMask = 0;
Mohan Kandra62429cc2010-07-19 10:21:05 -07001111 unsigned int prop = 0;
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -08001112 for(prop=0;prop<sizeof(boardProperties)/sizeof(board_property);prop++){
1113 if(mCurrentTarget == boardProperties[prop].target){
Apurva Rajguruffe264a2010-03-09 13:50:53 -08001114 boardMask = boardProperties[prop].previewSizeMask;
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -08001115 break;
1116 }
1117 }
1118
Apurva Rajguruffe264a2010-03-09 13:50:53 -08001119 int bitMask = boardMask & sensorType->bitMask;
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -08001120 if(bitMask){
1121 unsigned int mask = 1<<(PREVIEW_SIZE_COUNT-1);
1122 previewSizeCount=0;
1123 unsigned int i = 0;
1124 while(mask){
1125 if(mask&bitMask)
1126 supportedPreviewSizes[previewSizeCount++] =
1127 preview_sizes[i];
1128 i++;
1129 mask = mask >> 1;
1130 }
1131 }
1132}
1133
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -08001134//filter Picture sizes based on max width and height
1135void QualcommCameraHardware::filterPictureSizes(){
1136 int i;
1137 for(i=0;i<PICTURE_SIZE_COUNT;i++){
1138 if(((picture_sizes[i].width <=
1139 sensorType->max_supported_snapshot_width) &&
1140 (picture_sizes[i].height <=
1141 sensorType->max_supported_snapshot_height))){
1142 picture_sizes_ptr = picture_sizes + i;
1143 supportedPictureSizesCount = PICTURE_SIZE_COUNT - i ;
1144 return ;
1145 }
1146 }
1147}
1148
Apurva Rajguru8e0a8da2010-06-02 11:26:36 -07001149bool QualcommCameraHardware::supportsSceneDetection() {
1150 int prop = 0;
1151 for(prop=0; prop<sizeof(boardProperties)/sizeof(board_property); prop++) {
1152 if((mCurrentTarget == boardProperties[prop].target)
1153 && boardProperties[prop].hasSceneDetect == true) {
1154 return true;
1155 break;
1156 }
1157 }
1158 return false;
1159}
1160
Apurva Rajgurue5965c42010-09-09 14:24:54 -07001161bool QualcommCameraHardware::supportsSelectableZoneAf() {
1162 int prop = 0;
1163 for(prop=0; prop<sizeof(boardProperties)/sizeof(board_property); prop++) {
1164 if((mCurrentTarget == boardProperties[prop].target)
1165 && boardProperties[prop].hasSelectableZoneAf == true) {
1166 return true;
1167 break;
1168 }
1169 }
1170 return false;
1171}
1172
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001173void QualcommCameraHardware::initDefaultParameters()
1174{
Mohan Kandra0d115d12010-08-19 11:47:15 -07001175 LOGI("initDefaultParameters E");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001176
Apurva Rajguru59ec7122010-08-25 13:03:30 -07001177 findSensorType();
Nishant Pandit2eedc1b2010-09-25 04:47:39 +05301178 //Disable DIS for Web Camera
1179 if(!strcmp(sensorType->name, "ov7692"))
1180 mDisEnabled = 0;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001181 // Initialize constant parameter strings. This will happen only once in the
1182 // lifetime of the mediaserver process.
1183 if (!parameter_string_initialized) {
1184 antibanding_values = create_values_str(
1185 antibanding, sizeof(antibanding) / sizeof(str_map));
1186 effect_values = create_values_str(
1187 effects, sizeof(effects) / sizeof(str_map));
Apurva Rajguru55562b02009-12-03 12:25:35 -08001188 autoexposure_values = create_values_str(
1189 autoexposure, sizeof(autoexposure) / sizeof(str_map));
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001190 whitebalance_values = create_values_str(
1191 whitebalance, sizeof(whitebalance) / sizeof(str_map));
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -08001192
1193 //filter preview sizes
1194 filterPreviewSizes();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001195 preview_size_values = create_sizes_str(
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -08001196 supportedPreviewSizes, previewSizeCount);
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -08001197 //filter picture sizes
1198 filterPictureSizes();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001199 picture_size_values = create_sizes_str(
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -08001200 picture_sizes_ptr, supportedPictureSizesCount);
1201
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001202 flash_values = create_values_str(
1203 flash, sizeof(flash) / sizeof(str_map));
Srinivasan Kannan71229622009-12-04 12:05:58 -08001204 if(sensorType->hasAutoFocusSupport){
1205 focus_mode_values = create_values_str(
1206 focus_modes, sizeof(focus_modes) / sizeof(str_map));
1207 }
Nishant Panditc8c1ee72009-12-03 16:24:02 +05301208 iso_values = create_values_str(
1209 iso,sizeof(iso)/sizeof(str_map));
1210 lensshade_values = create_values_str(
1211 lensshade,sizeof(lensshade)/sizeof(str_map));
Nishant Pandit741742b2010-09-21 03:24:20 +05301212 //Currently Enabling Histogram for 8x60
1213 if(mCurrentTarget == TARGET_MSM8660) {
1214 histogram_values = create_values_str(
1215 histogram,sizeof(histogram)/sizeof(str_map));
1216 }
Apurva Rajguruf0593dd2010-07-27 17:50:23 -07001217 if(sensorType->hasAutoFocusSupport){
1218 touchafaec_values = create_values_str(
1219 touchafaec,sizeof(touchafaec)/sizeof(str_map));
1220 }
Apurva Rajguru0a2cb922010-06-08 15:33:22 -07001221
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001222 picture_format_values = create_values_str(
1223 picture_formats, sizeof(picture_formats)/sizeof(str_map));
Apurva Rajguru7b949c92010-05-26 15:46:57 -07001224
1225 if(sensorType->hasAutoFocusSupport){
1226 continuous_af_values = create_values_str(
1227 continuous_af, sizeof(continuous_af) / sizeof(str_map));
1228 }
Srinivasan Kannan6bce42b2010-07-12 19:10:08 -07001229
1230 if(native_get_maxzoom(mCameraControlFd,
1231 (void *)&mMaxZoom) == true){
1232 LOGD("Maximum zoom value is %d", mMaxZoom);
1233 zoomSupported = true;
1234 if(mMaxZoom > 0){
1235 //if max zoom is available find the zoom ratios
1236 int16_t * zoomRatios = new int16_t[mMaxZoom+1];
1237 if(zoomRatios != NULL){
1238 if(native_get_zoomratios(mCameraControlFd,
1239 (void *)zoomRatios, mMaxZoom + 1) == true){
1240 zoom_ratio_values =
1241 create_str(zoomRatios, mMaxZoom + 1);
1242 }else {
1243 LOGE("Failed to get zoomratios...");
1244 }
1245 delete zoomRatios;
1246 } else {
1247 LOGE("zoom ratios failed to acquire memory");
1248 }
1249 }
1250 } else {
1251 zoomSupported = false;
1252 LOGE("Failed to get maximum zoom value...setting max "
1253 "zoom to zero");
1254 mMaxZoom = 0;
1255 }
Srinivasan Kannana01751b2010-06-24 18:44:40 -07001256 preview_frame_rate_values = create_values_range_str(
1257 MINIMUM_FPS, MAXIMUM_FPS);
Apurva Rajguru08383852010-05-17 14:25:39 -07001258
1259 scenemode_values = create_values_str(
1260 scenemode, sizeof(scenemode) / sizeof(str_map));
Srinivasan Kannan264376e2010-08-13 18:54:35 -07001261
Apurva Rajguru8e0a8da2010-06-02 11:26:36 -07001262 if(supportsSceneDetection()) {
1263 scenedetect_values = create_values_str(
1264 scenedetect, sizeof(scenedetect) / sizeof(str_map));
1265 }
1266
Apurva Rajgurue5965c42010-09-09 14:24:54 -07001267 if(sensorType->hasAutoFocusSupport && supportsSelectableZoneAf()){
1268 selectable_zone_af_values = create_values_str(
1269 selectable_zone_af, sizeof(selectable_zone_af) / sizeof(str_map));
1270 }
1271
Apurva Rajguru8e0a8da2010-06-02 11:26:36 -07001272 parameter_string_initialized = true;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001273 }
1274
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -08001275 mParameters.setPreviewSize(DEFAULT_PREVIEW_WIDTH, DEFAULT_PREVIEW_HEIGHT);
1276 mDimension.display_width = DEFAULT_PREVIEW_WIDTH;
1277 mDimension.display_height = DEFAULT_PREVIEW_HEIGHT;
1278
Srinivasan Kannana01751b2010-06-24 18:44:40 -07001279 mParameters.setPreviewFrameRate(DEFAULT_FPS);
Nishant Pandit2eedc1b2010-09-25 04:47:39 +05301280 if((strcmp(sensorType->name, "2mp")) &&
1281 (strcmp(sensorType->name, "ov7692"))){
Srinivasan Kannanf01d8592010-07-25 13:47:08 -07001282 mParameters.set(
Srinivasan Kannana01751b2010-06-24 18:44:40 -07001283 CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES,
1284 preview_frame_rate_values.string());
Srinivasan Kannan264376e2010-08-13 18:54:35 -07001285 } else {
1286 mParameters.set(
1287 CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES,
1288 DEFAULT_FPS);
1289 }
Mohan Kandrabf6146d2010-07-20 18:48:37 -07001290 mParameters.setPreviewFrameRateMode("frame-rate-auto");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001291 mParameters.setPreviewFormat("yuv420sp"); // informative
1292
1293 mParameters.setPictureSize(DEFAULT_PICTURE_WIDTH, DEFAULT_PICTURE_HEIGHT);
1294 mParameters.setPictureFormat("jpeg"); // informative
1295
Mohan Kandra785619a2010-02-01 21:52:42 -08001296 mParameters.set(CameraParameters::KEY_JPEG_QUALITY, "85"); // max quality
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001297 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH,
1298 THUMBNAIL_WIDTH_STR); // informative
1299 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT,
1300 THUMBNAIL_HEIGHT_STR); // informative
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08001301 mDimension.ui_thumbnail_width =
1302 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].width;
1303 mDimension.ui_thumbnail_height =
1304 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001305 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, "90");
1306
Srinivasan Kannan264376e2010-08-13 18:54:35 -07001307 String8 valuesStr = create_sizes_str(jpeg_thumbnail_sizes, JPEG_THUMBNAIL_SIZE_COUNT);
1308 mParameters.set(CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES,
1309 valuesStr.string());
1310
Srinivasan Kannan6bce42b2010-07-12 19:10:08 -07001311 if(zoomSupported){
1312 mParameters.set(CameraParameters::KEY_ZOOM_SUPPORTED, "true");
1313 LOGV("max zoom is %d", mMaxZoom);
1314 mParameters.set("max-zoom",mMaxZoom);
1315 mParameters.set(CameraParameters::KEY_ZOOM_RATIOS,
1316 zoom_ratio_values);
1317 } else {
1318 mParameters.set(CameraParameters::KEY_ZOOM_SUPPORTED, "false");
1319 }
Mohan Kandra39fad8d2010-07-15 12:29:19 -07001320 /* Enable zoom support for video application if VPE enabled */
1321 if(zoomSupported && mVpeEnabled) {
1322 mParameters.set("video-zoom-support", "true");
1323 } else {
1324 mParameters.set("video-zoom-support", "false");
1325 }
Srinivasan Kannan6bce42b2010-07-12 19:10:08 -07001326
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001327 mParameters.set(CameraParameters::KEY_ANTIBANDING,
Mohan Kandra785619a2010-02-01 21:52:42 -08001328 CameraParameters::ANTIBANDING_OFF);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001329 mParameters.set(CameraParameters::KEY_EFFECT,
1330 CameraParameters::EFFECT_NONE);
Apurva Rajguru55562b02009-12-03 12:25:35 -08001331 mParameters.set(CameraParameters::KEY_AUTO_EXPOSURE,
1332 CameraParameters::AUTO_EXPOSURE_FRAME_AVG);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001333 mParameters.set(CameraParameters::KEY_WHITE_BALANCE,
1334 CameraParameters::WHITE_BALANCE_AUTO);
1335 mParameters.set(CameraParameters::KEY_FOCUS_MODE,
1336 CameraParameters::FOCUS_MODE_AUTO);
Mohan Kandra7110c242010-07-18 15:34:48 -07001337 if( (mCurrentTarget != TARGET_MSM7630) && (mCurrentTarget != TARGET_QSD8250) ) {
Priya Komarlingam044c7b52010-01-22 18:21:23 -08001338 mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS,
1339 "yuv420sp");
Mohan Kandra7110c242010-07-18 15:34:48 -07001340 }
1341 else {
1342 preview_format_values = create_values_str(
1343 preview_formats, sizeof(preview_formats) / sizeof(str_map));
1344 mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS,
1345 preview_format_values.string());
1346 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001347
Mohan Kandrabf6146d2010-07-20 18:48:37 -07001348 frame_rate_mode_values = create_values_str(
1349 frame_rate_modes, sizeof(frame_rate_modes) / sizeof(str_map));
Nishant Pandit2eedc1b2010-09-25 04:47:39 +05301350 if((strcmp(sensorType->name, "2mp")) &&
1351 (strcmp(sensorType->name, "ov7692"))){
Mohan Kandrabf6146d2010-07-20 18:48:37 -07001352 mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATE_MODES,
1353 frame_rate_mode_values.string());
1354 }
1355
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001356 mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES,
1357 preview_size_values.string());
1358 mParameters.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES,
1359 picture_size_values.string());
1360 mParameters.set(CameraParameters::KEY_SUPPORTED_ANTIBANDING,
1361 antibanding_values);
1362 mParameters.set(CameraParameters::KEY_SUPPORTED_EFFECTS, effect_values);
Apurva Rajguru55562b02009-12-03 12:25:35 -08001363 mParameters.set(CameraParameters::KEY_SUPPORTED_AUTO_EXPOSURE, autoexposure_values);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001364 mParameters.set(CameraParameters::KEY_SUPPORTED_WHITE_BALANCE,
1365 whitebalance_values);
Srinivasan Kannan264376e2010-08-13 18:54:35 -07001366 if((strcmp(mSensorInfo.name, "vx6953")) &&
1367 (strcmp(mSensorInfo.name, "VX6953")))
1368
1369 mParameters.set(CameraParameters::KEY_SUPPORTED_FOCUS_MODES,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001370 focus_mode_values);
Srinivasan Kannan264376e2010-08-13 18:54:35 -07001371 else
1372 mParameters.set(CameraParameters::KEY_SUPPORTED_FOCUS_MODES,
1373 CameraParameters::FOCUS_MODE_INFINITY);
1374
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001375 mParameters.set(CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS,
1376 picture_format_values);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001377
1378 if (mSensorInfo.flash_enabled) {
1379 mParameters.set(CameraParameters::KEY_FLASH_MODE,
1380 CameraParameters::FLASH_MODE_OFF);
1381 mParameters.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES,
1382 flash_values);
1383 }
1384
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08001385 mParameters.set(CameraParameters::KEY_MAX_SHARPNESS,
1386 CAMERA_MAX_SHARPNESS);
1387 mParameters.set(CameraParameters::KEY_MAX_CONTRAST,
1388 CAMERA_MAX_CONTRAST);
1389 mParameters.set(CameraParameters::KEY_MAX_SATURATION,
1390 CAMERA_MAX_SATURATION);
1391
Srinivasan Kannan4cc4b862010-06-30 14:22:26 -07001392 mParameters.set(
1393 CameraParameters::KEY_MAX_EXPOSURE_COMPENSATION,
1394 EXPOSURE_COMPENSATION_MAXIMUM_NUMERATOR);
1395 mParameters.set(
1396 CameraParameters::KEY_MIN_EXPOSURE_COMPENSATION,
1397 EXPOSURE_COMPENSATION_MINIMUM_NUMERATOR);
1398 mParameters.set(
1399 CameraParameters::KEY_EXPOSURE_COMPENSATION,
1400 EXPOSURE_COMPENSATION_DEFAULT_NUMERATOR);
1401 mParameters.setFloat(
1402 CameraParameters::KEY_EXPOSURE_COMPENSATION_STEP,
1403 EXPOSURE_COMPENSATION_STEP);
1404
Apurva Rajguru07185952010-01-22 15:40:07 -08001405 mParameters.set("luma-adaptation", "3");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001406 mParameters.set("zoom-supported", "true");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001407 mParameters.set("zoom", 0);
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001408 mParameters.set(CameraParameters::KEY_PICTURE_FORMAT,
1409 CameraParameters::PIXEL_FORMAT_JPEG);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001410
Kiran Kumar H N595970b2010-01-12 10:41:09 -08001411 mParameters.set(CameraParameters::KEY_SHARPNESS,
1412 CAMERA_DEF_SHARPNESS);
1413 mParameters.set(CameraParameters::KEY_CONTRAST,
1414 CAMERA_DEF_CONTRAST);
1415 mParameters.set(CameraParameters::KEY_SATURATION,
1416 CAMERA_DEF_SATURATION);
1417
Nishant Panditc8c1ee72009-12-03 16:24:02 +05301418 mParameters.set(CameraParameters::KEY_ISO_MODE,
1419 CameraParameters::ISO_AUTO);
1420 mParameters.set(CameraParameters::KEY_LENSSHADE,
1421 CameraParameters::LENSSHADE_ENABLE);
1422 mParameters.set(CameraParameters::KEY_SUPPORTED_ISO_MODES,
1423 iso_values);
1424 mParameters.set(CameraParameters::KEY_SUPPORTED_LENSSHADE_MODES,
1425 lensshade_values);
Nishant Pandit741742b2010-09-21 03:24:20 +05301426 mParameters.set(CameraParameters::KEY_HISTOGRAM,
1427 CameraParameters::HISTOGRAM_DISABLE);
1428 mParameters.set(CameraParameters::KEY_SUPPORTED_HISTOGRAM_MODES,
1429 histogram_values);
Apurva Rajguru08383852010-05-17 14:25:39 -07001430 mParameters.set(CameraParameters::KEY_SCENE_MODE,
1431 CameraParameters::SCENE_MODE_AUTO);
Mohan Kandra7110c242010-07-18 15:34:48 -07001432 mParameters.set("strtextures", "OFF");
1433
Apurva Rajguru08383852010-05-17 14:25:39 -07001434 mParameters.set(CameraParameters::KEY_SUPPORTED_SCENE_MODES,
1435 scenemode_values);
Apurva Rajguru7b949c92010-05-26 15:46:57 -07001436 mParameters.set(CameraParameters::KEY_CONTINUOUS_AF,
1437 CameraParameters::CONTINUOUS_AF_OFF);
1438 mParameters.set(CameraParameters::KEY_SUPPORTED_CONTINUOUS_AF,
1439 continuous_af_values);
Apurva Rajguru0a2cb922010-06-08 15:33:22 -07001440 mParameters.set(CameraParameters::KEY_TOUCH_AF_AEC,
1441 CameraParameters::TOUCH_AF_AEC_OFF);
1442 mParameters.set(CameraParameters::KEY_SUPPORTED_TOUCH_AF_AEC,
1443 touchafaec_values);
Apurva Rajguruf0593dd2010-07-27 17:50:23 -07001444 mParameters.setTouchIndexAec(-1, -1);
1445 mParameters.setTouchIndexAf(-1, -1);
Apurva Rajguru8e0a8da2010-06-02 11:26:36 -07001446 mParameters.set(CameraParameters::KEY_SCENE_DETECT,
1447 CameraParameters::SCENE_DETECT_OFF);
1448 mParameters.set(CameraParameters::KEY_SUPPORTED_SCENE_DETECT,
1449 scenedetect_values);
Srinivasan Kannan264376e2010-08-13 18:54:35 -07001450 mParameters.setFloat(CameraParameters::KEY_FOCAL_LENGTH,
1451 CAMERA_FOCAL_LENGTH_DEFAULT);
1452 mParameters.setFloat(CameraParameters::KEY_HORIZONTAL_VIEW_ANGLE,
1453 CAMERA_HORIZONTAL_VIEW_ANGLE_DEFAULT);
1454 mParameters.setFloat(CameraParameters::KEY_VERTICAL_VIEW_ANGLE,
1455 CAMERA_VERTICAL_VIEW_ANGLE_DEFAULT);
Apurva Rajgurue5965c42010-09-09 14:24:54 -07001456 mParameters.set(CameraParameters::KEY_SELECTABLE_ZONE_AF,
1457 CameraParameters::SELECTABLE_ZONE_AF_AUTO);
1458 mParameters.set(CameraParameters::KEY_SUPPORTED_SELECTABLE_ZONE_AF,
1459 selectable_zone_af_values);
Priyanka Kharat67cfe532010-03-29 17:28:22 -07001460 if (setParameters(mParameters) != NO_ERROR) {
1461 LOGE("Failed to set default parameters?!");
1462 }
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08001463 mUseOverlay = useOverlay();
1464
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001465 /* Initialize the camframe_timeout_flag*/
1466 Mutex::Autolock l(&mCamframeTimeoutLock);
1467 camframe_timeout_flag = FALSE;
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08001468 mPostViewHeap = NULL;
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001469
Srinivasan Kannana01751b2010-06-24 18:44:40 -07001470 mInitialized = true;
1471
Mohan Kandra0d115d12010-08-19 11:47:15 -07001472 LOGI("initDefaultParameters X");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001473}
1474
Srinivasan Kannan71229622009-12-04 12:05:58 -08001475void QualcommCameraHardware::findSensorType(){
1476 mDimension.picture_width = DEFAULT_PICTURE_WIDTH;
1477 mDimension.picture_height = DEFAULT_PICTURE_HEIGHT;
1478 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
1479 sizeof(cam_ctrl_dimension_t), &mDimension);
1480 if (ret) {
1481 unsigned int i;
1482 for (i = 0; i < sizeof(sensorTypes) / sizeof(SensorType); i++) {
1483 if (sensorTypes[i].rawPictureHeight
1484 == mDimension.raw_picture_height) {
1485 sensorType = sensorTypes + i;
1486 return;
1487 }
1488 }
1489 }
1490 //default to 5 mp
1491 sensorType = sensorTypes;
1492 return;
1493}
1494
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001495#define ROUND_TO_PAGE(x) (((x)+0xfff)&~0xfff)
1496
1497bool QualcommCameraHardware::startCamera()
1498{
1499 LOGV("startCamera E");
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08001500 if( mCurrentTarget == TARGET_MAX ) {
1501 LOGE(" Unable to determine the target type. Camera will not work ");
1502 return false;
1503 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001504#if DLOPEN_LIBMMCAMERA
1505 libmmcamera = ::dlopen("liboemcamera.so", RTLD_NOW);
Priya Komarlingam9bb2d492010-06-23 19:21:52 -07001506
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001507 LOGV("loading liboemcamera at %p", libmmcamera);
1508 if (!libmmcamera) {
1509 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
1510 return false;
1511 }
1512
1513 *(void **)&LINK_cam_frame =
1514 ::dlsym(libmmcamera, "cam_frame");
1515 *(void **)&LINK_camframe_terminate =
1516 ::dlsym(libmmcamera, "camframe_terminate");
1517
1518 *(void **)&LINK_jpeg_encoder_init =
1519 ::dlsym(libmmcamera, "jpeg_encoder_init");
1520
1521 *(void **)&LINK_jpeg_encoder_encode =
1522 ::dlsym(libmmcamera, "jpeg_encoder_encode");
1523
1524 *(void **)&LINK_jpeg_encoder_join =
1525 ::dlsym(libmmcamera, "jpeg_encoder_join");
1526
1527 *(void **)&LINK_mmcamera_camframe_callback =
1528 ::dlsym(libmmcamera, "mmcamera_camframe_callback");
1529
1530 *LINK_mmcamera_camframe_callback = receive_camframe_callback;
1531
Nishant Pandit741742b2010-09-21 03:24:20 +05301532 *(void **)&LINK_mmcamera_camstats_callback =
1533 ::dlsym(libmmcamera, "mmcamera_camstats_callback");
1534
1535 *LINK_mmcamera_camstats_callback = receive_camstats_callback;
1536
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001537 *(void **)&LINK_mmcamera_jpegfragment_callback =
1538 ::dlsym(libmmcamera, "mmcamera_jpegfragment_callback");
1539
1540 *LINK_mmcamera_jpegfragment_callback = receive_jpeg_fragment_callback;
1541
1542 *(void **)&LINK_mmcamera_jpeg_callback =
1543 ::dlsym(libmmcamera, "mmcamera_jpeg_callback");
1544
1545 *LINK_mmcamera_jpeg_callback = receive_jpeg_callback;
1546
Mohan Kandra3dd524f2010-09-20 13:41:42 -07001547 *(void **)&LINK_camframe_error_callback =
1548 ::dlsym(libmmcamera, "camframe_error_callback");
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001549
Mohan Kandra3dd524f2010-09-20 13:41:42 -07001550 *LINK_camframe_error_callback = receive_camframe_error_callback;
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001551
Sravankb4f5f1c2010-01-21 11:06:17 +05301552 // 720 p new recording functions
1553 *(void **)&LINK_cam_frame_flush_free_video = ::dlsym(libmmcamera, "cam_frame_flush_free_video");
1554
1555 *(void **)&LINK_camframe_free_video = ::dlsym(libmmcamera, "cam_frame_add_free_video");
1556
1557 *(void **)&LINK_camframe_video_callback = ::dlsym(libmmcamera, "mmcamera_camframe_videocallback");
1558 *LINK_camframe_video_callback = receive_camframe_video_callback;
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08001559
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001560 *(void **)&LINK_mmcamera_shutter_callback =
1561 ::dlsym(libmmcamera, "mmcamera_shutter_callback");
1562
1563 *LINK_mmcamera_shutter_callback = receive_shutter_callback;
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08001564
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001565 *(void**)&LINK_jpeg_encoder_setMainImageQuality =
1566 ::dlsym(libmmcamera, "jpeg_encoder_setMainImageQuality");
Kiran Kumar H N8861f302010-01-05 12:01:41 -08001567
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001568 *(void**)&LINK_jpeg_encoder_setThumbnailQuality =
1569 ::dlsym(libmmcamera, "jpeg_encoder_setThumbnailQuality");
1570
1571 *(void**)&LINK_jpeg_encoder_setRotation =
1572 ::dlsym(libmmcamera, "jpeg_encoder_setRotation");
1573
Mohan Kandra02486042010-06-18 16:49:43 -07001574 *(void**)&LINK_jpeg_encoder_get_buffer_offset =
1575 ::dlsym(libmmcamera, "jpeg_encoder_get_buffer_offset");
1576
Kiran Kumar H N8861f302010-01-05 12:01:41 -08001577/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001578 *(void**)&LINK_jpeg_encoder_setLocation =
1579 ::dlsym(libmmcamera, "jpeg_encoder_setLocation");
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001580*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001581 *(void **)&LINK_cam_conf =
1582 ::dlsym(libmmcamera, "cam_conf");
1583
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001584/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001585 *(void **)&LINK_default_sensor_get_snapshot_sizes =
1586 ::dlsym(libmmcamera, "default_sensor_get_snapshot_sizes");
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001587*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001588 *(void **)&LINK_launch_cam_conf_thread =
1589 ::dlsym(libmmcamera, "launch_cam_conf_thread");
1590
1591 *(void **)&LINK_release_cam_conf_thread =
1592 ::dlsym(libmmcamera, "release_cam_conf_thread");
Nishant Pandit741742b2010-09-21 03:24:20 +05301593 *(void **)&LINK_mm_camera_config_init =
1594 ::dlsym(libmmcamera, "mm_camera_config_init");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001595
Vamshidhar Kondra92ce9142010-09-03 18:22:08 +05301596 *(void **)&LINK_mmcamera_liveshot_callback =
1597 ::dlsym(libmmcamera, "mmcamera_liveshot_callback");
1598
1599 *LINK_mmcamera_liveshot_callback = receive_liveshot_callback;
1600
1601 *(void **)&LINK_cancel_liveshot =
1602 ::dlsym(libmmcamera, "cancel_liveshot");
1603
1604 *(void **)&LINK_set_liveshot_params =
1605 ::dlsym(libmmcamera, "set_liveshot_params");
1606
Nishant Pandit741742b2010-09-21 03:24:20 +05301607 *(void **)&LINK_mm_camera_config_deinit =
1608 ::dlsym(libmmcamera, "mm_camera_config_deinit");
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001609/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001610 *(void **)&LINK_zoom_crop_upscale =
1611 ::dlsym(libmmcamera, "zoom_crop_upscale");
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001612*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001613
1614#else
1615 mmcamera_camframe_callback = receive_camframe_callback;
Nishant Pandit741742b2010-09-21 03:24:20 +05301616 mmcamera_camstats_callback = receive_camstats_callback;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001617 mmcamera_jpegfragment_callback = receive_jpeg_fragment_callback;
1618 mmcamera_jpeg_callback = receive_jpeg_callback;
1619 mmcamera_shutter_callback = receive_shutter_callback;
Vamshidhar Kondra92ce9142010-09-03 18:22:08 +05301620 mmcamera_liveshot_callback = receive_liveshot_callback;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001621#endif // DLOPEN_LIBMMCAMERA
1622
1623 /* The control thread is in libcamera itself. */
Brian Steuer07704892009-12-18 18:07:33 -08001624 if (pthread_join(w_thread, NULL) != 0) {
1625 LOGE("Camera open thread exit failed");
1626 return false;
1627 }
1628 mCameraControlFd = camerafd;
1629
Kiran Kumar H N585bc362010-01-19 13:04:44 -08001630 if (mCameraControlFd < 0) {
1631 LOGE("startCamera X: %s open failed: %s!",
1632 MSM_CAMERA_CONTROL,
1633 strerror(errno));
1634 return false;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001635 }
1636
Nishant Pandit741742b2010-09-21 03:24:20 +05301637 if (MM_CAMERA_STATUS_SUCCESS != LINK_mm_camera_config_init(&mCfgControl)) {
1638 LOGE("startCamera: mm_camera_config_init failed:");
1639 return FALSE;
1640 }
1641
Nishant Pandit3c278cd2010-07-13 15:56:04 +05301642 if((mCurrentTarget != TARGET_MSM7630) && (mCurrentTarget != TARGET_MSM8660)){
Mohan Kandra284966d2010-01-05 13:39:15 -08001643 fb_fd = open("/dev/graphics/fb0", O_RDWR);
1644 if (fb_fd < 0) {
1645 LOGE("startCamera: fb0 open failed: %s!", strerror(errno));
1646 return FALSE;
1647 }
1648 }
1649
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001650 /* This will block until the control thread is launched. After that, sensor
1651 * information becomes available.
1652 */
1653
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001654 memset(&mSensorInfo, 0, sizeof(mSensorInfo));
1655 if (ioctl(mCameraControlFd,
1656 MSM_CAM_IOCTL_GET_SENSOR_INFO,
1657 &mSensorInfo) < 0)
1658 LOGW("%s: cannot retrieve sensor info!", __FUNCTION__);
1659 else
1660 LOGI("%s: camsensor name %s, flash %d", __FUNCTION__,
1661 mSensorInfo.name, mSensorInfo.flash_enabled);
Nishant Pandit741742b2010-09-21 03:24:20 +05301662
1663 mCfgControl.mm_camera_query_parms(CAMERA_PARM_PICT_SIZE, (void **)&picture_sizes, &PICTURE_SIZE_COUNT);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001664 if (!picture_sizes || !PICTURE_SIZE_COUNT) {
1665 LOGE("startCamera X: could not get snapshot sizes");
1666 return false;
1667 }
Nishant Pandit741742b2010-09-21 03:24:20 +05301668 LOGV("startCamera picture_sizes %p PICTURE_SIZE_COUNT %d", picture_sizes, PICTURE_SIZE_COUNT);
1669
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001670 LOGV("startCamera X");
1671 return true;
1672}
1673
1674status_t QualcommCameraHardware::dump(int fd,
1675 const Vector<String16>& args) const
1676{
1677 const size_t SIZE = 256;
1678 char buffer[SIZE];
1679 String8 result;
1680
1681 // Dump internal primitives.
1682 result.append("QualcommCameraHardware::dump");
1683 snprintf(buffer, 255, "mMsgEnabled (%d)\n", mMsgEnabled);
1684 result.append(buffer);
1685 int width, height;
1686 mParameters.getPreviewSize(&width, &height);
1687 snprintf(buffer, 255, "preview width(%d) x height (%d)\n", width, height);
1688 result.append(buffer);
1689 mParameters.getPictureSize(&width, &height);
1690 snprintf(buffer, 255, "raw width(%d) x height (%d)\n", width, height);
1691 result.append(buffer);
1692 snprintf(buffer, 255,
1693 "preview frame size(%d), raw size (%d), jpeg size (%d) "
1694 "and jpeg max size (%d)\n", mPreviewFrameSize, mRawSize,
1695 mJpegSize, mJpegMaxSize);
1696 result.append(buffer);
1697 write(fd, result.string(), result.size());
1698
1699 // Dump internal objects.
Mohan Kandrad9efed92010-01-15 19:08:39 -08001700 if (mPreviewHeap != 0) {
1701 mPreviewHeap->dump(fd, args);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001702 }
1703 if (mRawHeap != 0) {
1704 mRawHeap->dump(fd, args);
1705 }
1706 if (mJpegHeap != 0) {
1707 mJpegHeap->dump(fd, args);
1708 }
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001709 if(mRawSnapshotAshmemHeap != 0 ){
1710 mRawSnapshotAshmemHeap->dump(fd, args);
1711 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001712 mParameters.dump(fd, args);
1713 return NO_ERROR;
1714}
1715
Mohan Kandra284966d2010-01-05 13:39:15 -08001716static bool native_get_maxzoom(int camfd, void *pZm)
1717{
1718 LOGV("native_get_maxzoom E");
1719
1720 struct msm_ctrl_cmd ctrlCmd;
1721 int32_t *pZoom = (int32_t *)pZm;
1722
1723 ctrlCmd.type = CAMERA_GET_PARM_MAXZOOM;
1724 ctrlCmd.timeout_ms = 5000;
1725 ctrlCmd.length = sizeof(int32_t);
1726 ctrlCmd.value = pZoom;
1727 ctrlCmd.resp_fd = camfd;
1728
1729 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1730 LOGE("native_get_maxzoom: ioctl fd %d error %s",
1731 camfd,
1732 strerror(errno));
1733 return false;
1734 }
Brian Steuerb62adbd2010-02-02 14:47:08 -08001735 LOGD("ctrlCmd.value = %d", *(int32_t *)ctrlCmd.value);
Mohan Kandra284966d2010-01-05 13:39:15 -08001736 memcpy(pZoom, (int32_t *)ctrlCmd.value, sizeof(int32_t));
1737
1738 LOGV("native_get_maxzoom X");
1739 return true;
1740}
1741
Srinivasan Kannan6bce42b2010-07-12 19:10:08 -07001742static bool native_get_zoomratios(int camfd, void *pZr, int maxZoomSize)
1743{
1744 LOGV("native_get_zoomratios E");
1745 struct msm_ctrl_cmd ctrlCmd;
1746 int16_t *zoomRatios = (int16_t *)pZr;
1747
1748 if(maxZoomSize <= 0)
1749 return false;
1750
1751 ctrlCmd.type = CAMERA_GET_PARM_ZOOMRATIOS;
1752 ctrlCmd.timeout_ms = 5000;
1753 ctrlCmd.length = sizeof(int16_t)* (maxZoomSize);
1754 ctrlCmd.value = zoomRatios;
1755 ctrlCmd.resp_fd = camfd;
1756
1757 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1758 LOGE("native_get_zoomratios: ioctl fd %d error %s",
1759 camfd,
1760 strerror(errno));
1761 return false;
1762 }
1763 LOGV("native_get_zoomratios X");
1764 return true;
1765}
1766
1767
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001768static bool native_set_afmode(int camfd, isp3a_af_mode_t af_type)
1769{
1770 int rc;
1771 struct msm_ctrl_cmd ctrlCmd;
1772
1773 ctrlCmd.timeout_ms = 5000;
1774 ctrlCmd.type = CAMERA_SET_PARM_AUTO_FOCUS;
1775 ctrlCmd.length = sizeof(af_type);
1776 ctrlCmd.value = &af_type;
1777 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1778
1779 if ((rc = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0)
1780 LOGE("native_set_afmode: ioctl fd %d error %s\n",
1781 camfd,
1782 strerror(errno));
1783
1784 LOGV("native_set_afmode: ctrlCmd.status == %d\n", ctrlCmd.status);
1785 return rc >= 0 && ctrlCmd.status == CAMERA_EXIT_CB_DONE;
1786}
1787
1788static bool native_cancel_afmode(int camfd, int af_fd)
1789{
1790 int rc;
1791 struct msm_ctrl_cmd ctrlCmd;
1792
1793 ctrlCmd.timeout_ms = 0;
1794 ctrlCmd.type = CAMERA_AUTO_FOCUS_CANCEL;
1795 ctrlCmd.length = 0;
1796 ctrlCmd.value = NULL;
1797 ctrlCmd.resp_fd = -1; // there's no response fd
1798
1799 if ((rc = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND_2, &ctrlCmd)) < 0)
1800 {
1801 LOGE("native_cancel_afmode: ioctl fd %d error %s\n",
1802 camfd,
1803 strerror(errno));
1804 return false;
1805 }
1806
1807 return true;
1808}
1809
1810static bool native_start_preview(int camfd)
1811{
1812 struct msm_ctrl_cmd ctrlCmd;
1813
1814 ctrlCmd.timeout_ms = 5000;
1815 ctrlCmd.type = CAMERA_START_PREVIEW;
1816 ctrlCmd.length = 0;
1817 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1818
1819 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1820 LOGE("native_start_preview: MSM_CAM_IOCTL_CTRL_COMMAND fd %d error %s",
1821 camfd,
1822 strerror(errno));
1823 return false;
1824 }
1825
1826 return true;
1827}
1828
1829static bool native_get_picture (int camfd, common_crop_t *crop)
1830{
1831 struct msm_ctrl_cmd ctrlCmd;
1832
1833 ctrlCmd.timeout_ms = 5000;
1834 ctrlCmd.length = sizeof(common_crop_t);
1835 ctrlCmd.value = crop;
1836
1837 if(ioctl(camfd, MSM_CAM_IOCTL_GET_PICTURE, &ctrlCmd) < 0) {
1838 LOGE("native_get_picture: MSM_CAM_IOCTL_GET_PICTURE fd %d error %s",
1839 camfd,
1840 strerror(errno));
1841 return false;
1842 }
1843
1844 LOGV("crop: in1_w %d", crop->in1_w);
1845 LOGV("crop: in1_h %d", crop->in1_h);
1846 LOGV("crop: out1_w %d", crop->out1_w);
1847 LOGV("crop: out1_h %d", crop->out1_h);
1848
1849 LOGV("crop: in2_w %d", crop->in2_w);
1850 LOGV("crop: in2_h %d", crop->in2_h);
1851 LOGV("crop: out2_w %d", crop->out2_w);
1852 LOGV("crop: out2_h %d", crop->out2_h);
1853
1854 LOGV("crop: update %d", crop->update_flag);
1855
1856 return true;
1857}
1858
1859static bool native_stop_preview(int camfd)
1860{
1861 struct msm_ctrl_cmd ctrlCmd;
1862 ctrlCmd.timeout_ms = 5000;
1863 ctrlCmd.type = CAMERA_STOP_PREVIEW;
1864 ctrlCmd.length = 0;
1865 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1866
1867 if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1868 LOGE("native_stop_preview: ioctl fd %d error %s",
1869 camfd,
1870 strerror(errno));
1871 return false;
1872 }
1873
1874 return true;
1875}
1876
1877static bool native_prepare_snapshot(int camfd)
1878{
1879 int ioctlRetVal = true;
1880 struct msm_ctrl_cmd ctrlCmd;
1881
1882 ctrlCmd.timeout_ms = 1000;
1883 ctrlCmd.type = CAMERA_PREPARE_SNAPSHOT;
1884 ctrlCmd.length = 0;
1885 ctrlCmd.value = NULL;
1886 ctrlCmd.resp_fd = camfd;
1887
1888 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1889 LOGE("native_prepare_snapshot: ioctl fd %d error %s",
1890 camfd,
1891 strerror(errno));
1892 return false;
1893 }
1894 return true;
1895}
1896
1897static bool native_start_snapshot(int camfd)
1898{
1899 struct msm_ctrl_cmd ctrlCmd;
1900
1901 ctrlCmd.timeout_ms = 5000;
1902 ctrlCmd.type = CAMERA_START_SNAPSHOT;
1903 ctrlCmd.length = 0;
1904 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1905
1906 if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1907 LOGE("native_start_snapshot: ioctl fd %d error %s",
1908 camfd,
1909 strerror(errno));
1910 return false;
1911 }
1912
1913 return true;
1914}
1915
Vamshidhar Kondra92ce9142010-09-03 18:22:08 +05301916static bool native_start_liveshot(int camfd)
1917{
1918 int ret;
1919 struct msm_ctrl_cmd ctrlCmd;
1920 ctrlCmd.timeout_ms = 5000;
1921 ctrlCmd.type = CAMERA_START_LIVESHOT;
1922 ctrlCmd.length = 0;
1923 ctrlCmd.value = NULL;
1924 ctrlCmd.resp_fd = camfd;
1925 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1926 LOGE("native_start_liveshot: ioctl failed. ioctl return value is %d ", ret);
1927 return false;
1928 }
1929 return true;
1930}
1931
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001932static bool native_start_raw_snapshot(int camfd)
1933{
1934 int ret;
1935 struct msm_ctrl_cmd ctrlCmd;
1936
1937 ctrlCmd.timeout_ms = 1000;
1938 ctrlCmd.type = CAMERA_START_RAW_SNAPSHOT;
1939 ctrlCmd.length = 0;
1940 ctrlCmd.value = NULL;
1941 ctrlCmd.resp_fd = camfd;
1942
1943 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1944 LOGE("native_start_raw_snapshot: ioctl failed. ioctl return value "\
1945 "is %d \n", ret);
1946 return false;
1947 }
1948 return true;
1949}
1950
1951
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001952static bool native_stop_snapshot (int camfd)
1953{
1954 struct msm_ctrl_cmd ctrlCmd;
1955
1956 ctrlCmd.timeout_ms = 0;
1957 ctrlCmd.type = CAMERA_STOP_SNAPSHOT;
1958 ctrlCmd.length = 0;
1959 ctrlCmd.resp_fd = -1;
1960
1961 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND_2, &ctrlCmd) < 0) {
1962 LOGE("native_stop_snapshot: ioctl fd %d error %s",
1963 camfd,
1964 strerror(errno));
1965 return false;
1966 }
1967
1968 return true;
1969}
Sravankb4f5f1c2010-01-21 11:06:17 +05301970/*===========================================================================
1971 * FUNCTION - native_start_recording -
1972 *
1973 * DESCRIPTION:
1974 *==========================================================================*/
1975static bool native_start_recording(int camfd)
1976{
1977 int ret;
1978 struct msm_ctrl_cmd ctrlCmd;
1979
1980 ctrlCmd.timeout_ms = 1000;
1981 ctrlCmd.type = CAMERA_START_RECORDING;
1982 ctrlCmd.length = 0;
1983 ctrlCmd.value = NULL;
1984 ctrlCmd.resp_fd = camfd;
1985
1986 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1987 LOGE("native_start_recording: ioctl failed. ioctl return value "\
1988 "is %d \n", ret);
1989 return false;
1990 }
Mohan Kandraf1ebf982010-02-02 15:25:43 -08001991 LOGV("native_start_recording: ioctl good. ioctl return value is %d \n",ret);
Sravankb4f5f1c2010-01-21 11:06:17 +05301992
1993 /* TODO: Check status of postprocessing if there is any,
1994 * PP status should be in ctrlCmd */
1995
1996 return true;
1997}
1998
1999/*===========================================================================
2000 * FUNCTION - native_stop_recording -
2001 *
2002 * DESCRIPTION:
2003 *==========================================================================*/
2004static bool native_stop_recording(int camfd)
2005{
2006 int ret;
2007 struct msm_ctrl_cmd ctrlCmd;
Kiran Kumar H Nb49af212010-02-17 15:12:17 -08002008 LOGV("in native_stop_recording ");
Sravankb4f5f1c2010-01-21 11:06:17 +05302009 ctrlCmd.timeout_ms = 1000;
2010 ctrlCmd.type = CAMERA_STOP_RECORDING;
2011 ctrlCmd.length = 0;
2012 ctrlCmd.value = NULL;
2013 ctrlCmd.resp_fd = camfd;
2014
2015 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
2016 LOGE("native_stop_video: ioctl failed. ioctl return value is %d \n",
2017 ret);
2018 return false;
2019 }
2020 LOGV("in native_stop_recording returned %d", ret);
2021 return true;
2022}
2023/*===========================================================================
2024 * FUNCTION - native_start_video -
2025 *
2026 * DESCRIPTION:
2027 *==========================================================================*/
2028static bool native_start_video(int camfd)
2029{
2030 int ret;
2031 struct msm_ctrl_cmd ctrlCmd;
2032
2033 ctrlCmd.timeout_ms = 1000;
2034 ctrlCmd.type = CAMERA_START_VIDEO;
2035 ctrlCmd.length = 0;
2036 ctrlCmd.value = NULL;
2037 ctrlCmd.resp_fd = camfd;
2038
2039 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
2040 LOGE("native_start_video: ioctl failed. ioctl return value is %d \n",
2041 ret);
2042 return false;
2043 }
2044
2045 /* TODO: Check status of postprocessing if there is any,
2046 * PP status should be in ctrlCmd */
2047
2048 return true;
2049}
2050
2051/*===========================================================================
2052 * FUNCTION - native_stop_video -
2053 *
2054 * DESCRIPTION:
2055 *==========================================================================*/
2056static bool native_stop_video(int camfd)
2057{
2058 int ret;
2059 struct msm_ctrl_cmd ctrlCmd;
2060
2061 ctrlCmd.timeout_ms = 1000;
2062 ctrlCmd.type = CAMERA_STOP_VIDEO;
2063 ctrlCmd.length = 0;
2064 ctrlCmd.value = NULL;
2065 ctrlCmd.resp_fd = camfd;
2066
2067 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
2068 LOGE("native_stop_video: ioctl failed. ioctl return value is %d \n",
2069 ret);
2070 return false;
2071 }
2072
2073 return true;
2074}
2075/*==========================================================================*/
2076
2077static cam_frame_start_parms frame_parms;
2078static int recordingState = 0;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002079
Srinivasan Kannan09de3382010-08-16 16:42:00 -07002080#define GPS_PROCESSING_METHOD_SIZE 101
2081#define FOCAL_LENGTH_DECIMAL_PRECISON 100
2082
2083static const char ExifAsciiPrefix[] = { 0x41, 0x53, 0x43, 0x49, 0x49, 0x0, 0x0, 0x0 };
2084#define EXIF_ASCII_PREFIX_SIZE (sizeof(ExifAsciiPrefix))
2085
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08002086static rat_t latitude[3];
2087static rat_t longitude[3];
2088static char lonref[2];
2089static char latref[2];
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08002090static rat_t altitude;
Apurva Rajguru5ec76132010-06-16 17:43:46 -07002091static rat_t gpsTimestamp[3];
Srinivasan Kannan09de3382010-08-16 16:42:00 -07002092static char gpsDatestamp[20];
Apurva Rajguru5ec76132010-06-16 17:43:46 -07002093static char dateTime[20];
Srinivasan Kannan09de3382010-08-16 16:42:00 -07002094static rat_t focalLength;
2095static char gpsProcessingMethod[EXIF_ASCII_PREFIX_SIZE + GPS_PROCESSING_METHOD_SIZE];
2096
2097
2098
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08002099static void addExifTag(exif_tag_id_t tagid, exif_tag_type_t type,
2100 uint32_t count, uint8_t copy, void *data) {
2101
2102 if(exif_table_numEntries == MAX_EXIF_TABLE_ENTRIES) {
2103 LOGE("Number of entries exceeded limit");
2104 return;
2105 }
2106
2107 int index = exif_table_numEntries;
2108 exif_data[index].tag_id = tagid;
2109 exif_data[index].tag_entry.type = type;
2110 exif_data[index].tag_entry.count = count;
2111 exif_data[index].tag_entry.copy = copy;
2112 if((type == EXIF_RATIONAL) && (count > 1))
2113 exif_data[index].tag_entry.data._rats = (rat_t *)data;
2114 if((type == EXIF_RATIONAL) && (count == 1))
2115 exif_data[index].tag_entry.data._rat = *(rat_t *)data;
2116 else if(type == EXIF_ASCII)
2117 exif_data[index].tag_entry.data._ascii = (char *)data;
2118 else if(type == EXIF_BYTE)
2119 exif_data[index].tag_entry.data._byte = *(uint8_t *)data;
2120
2121 // Increase number of entries
2122 exif_table_numEntries++;
2123}
2124
2125static void parseLatLong(const char *latlonString, int *pDegrees,
2126 int *pMinutes, int *pSeconds ) {
2127
2128 double value = atof(latlonString);
2129 value = fabs(value);
2130 int degrees = (int) value;
2131
2132 double remainder = value - degrees;
2133 int minutes = (int) (remainder * 60);
2134 int seconds = (int) (((remainder * 60) - minutes) * 60 * 1000);
2135
2136 *pDegrees = degrees;
2137 *pMinutes = minutes;
2138 *pSeconds = seconds;
2139}
2140
2141static void setLatLon(exif_tag_id_t tag, const char *latlonString) {
2142
2143 int degrees, minutes, seconds;
2144
2145 parseLatLong(latlonString, &degrees, &minutes, &seconds);
2146
2147 rat_t value[3] = { {degrees, 1},
2148 {minutes, 1},
2149 {seconds, 1000} };
2150
2151 if(tag == EXIFTAGID_GPS_LATITUDE) {
2152 memcpy(latitude, value, sizeof(latitude));
2153 addExifTag(EXIFTAGID_GPS_LATITUDE, EXIF_RATIONAL, 3,
2154 1, (void *)latitude);
2155 } else {
2156 memcpy(longitude, value, sizeof(longitude));
2157 addExifTag(EXIFTAGID_GPS_LONGITUDE, EXIF_RATIONAL, 3,
2158 1, (void *)longitude);
2159 }
2160}
2161
2162void QualcommCameraHardware::setGpsParameters() {
2163 const char *str = NULL;
2164
Srinivasan Kannan09de3382010-08-16 16:42:00 -07002165 str = mParameters.get(CameraParameters::KEY_GPS_PROCESSING_METHOD);
2166
2167 if(str!=NULL ){
2168 memcpy(gpsProcessingMethod, ExifAsciiPrefix, EXIF_ASCII_PREFIX_SIZE);
2169 strncpy(gpsProcessingMethod + EXIF_ASCII_PREFIX_SIZE, str,
2170 GPS_PROCESSING_METHOD_SIZE-1);
2171 gpsProcessingMethod[EXIF_ASCII_PREFIX_SIZE + GPS_PROCESSING_METHOD_SIZE-1] = '\0';
2172 addExifTag(EXIFTAGID_GPS_PROCESSINGMETHOD, EXIF_ASCII,
2173 EXIF_ASCII_PREFIX_SIZE + strlen(gpsProcessingMethod + EXIF_ASCII_PREFIX_SIZE) + 1,
2174 1, (void *)gpsProcessingMethod);
2175 }
2176
2177 str = NULL;
2178
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08002179 //Set Latitude
2180 str = mParameters.get(CameraParameters::KEY_GPS_LATITUDE);
2181 if(str != NULL) {
2182 setLatLon(EXIFTAGID_GPS_LATITUDE, str);
2183 //set Latitude Ref
Srinivasan Kannan09de3382010-08-16 16:42:00 -07002184 float latitudeValue = mParameters.getFloat(CameraParameters::KEY_GPS_LATITUDE);
2185 latref[0] = 'N';
2186 if(latitudeValue < 0 ){
2187 latref[0] = 'S';
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08002188 }
Srinivasan Kannan09de3382010-08-16 16:42:00 -07002189 latref[1] = '\0';
2190 mParameters.set(CameraParameters::KEY_GPS_LATITUDE_REF, latref);
2191 addExifTag(EXIFTAGID_GPS_LATITUDE_REF, EXIF_ASCII, 2,
2192 1, (void *)latref);
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08002193 }
2194
2195 //set Longitude
2196 str = NULL;
2197 str = mParameters.get(CameraParameters::KEY_GPS_LONGITUDE);
2198 if(str != NULL) {
2199 setLatLon(EXIFTAGID_GPS_LONGITUDE, str);
2200 //set Longitude Ref
Srinivasan Kannan09de3382010-08-16 16:42:00 -07002201 float longitudeValue = mParameters.getFloat(CameraParameters::KEY_GPS_LONGITUDE);
2202 lonref[0] = 'E';
2203 if(longitudeValue < 0){
2204 lonref[0] = 'W';
2205 }
2206 lonref[1] = '\0';
2207 mParameters.set(CameraParameters::KEY_GPS_LONGITUDE_REF, lonref);
2208 addExifTag(EXIFTAGID_GPS_LONGITUDE_REF, EXIF_ASCII, 2,
2209 1, (void *)lonref);
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08002210 }
2211
2212 //set Altitude
2213 str = NULL;
2214 str = mParameters.get(CameraParameters::KEY_GPS_ALTITUDE);
2215 if(str != NULL) {
2216 int value = atoi(str);
Srinivasan Kannan09de3382010-08-16 16:42:00 -07002217 int ref = 0;
2218 if(value < 0){
2219 ref = 1;
2220 value = -value;
2221 }
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08002222 rat_t alt_value = {value, 1000};
2223 memcpy(&altitude, &alt_value, sizeof(altitude));
2224 addExifTag(EXIFTAGID_GPS_ALTITUDE, EXIF_RATIONAL, 1,
2225 1, (void *)&altitude);
2226 //set AltitudeRef
Srinivasan Kannan09de3382010-08-16 16:42:00 -07002227 mParameters.set(CameraParameters::KEY_GPS_ALTITUDE_REF, ref);
2228 addExifTag(EXIFTAGID_GPS_ALTITUDE_REF, EXIF_BYTE, 1,
2229 1, (void *)&ref);
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08002230 }
2231
Apurva Rajguru5ec76132010-06-16 17:43:46 -07002232 //set Gps TimeStamp
2233 str = NULL;
2234 str = mParameters.get(CameraParameters::KEY_GPS_TIMESTAMP);
2235 if(str != NULL) {
2236
2237 long value = atol(str);
2238 time_t unixTime;
2239 struct tm *UTCTimestamp;
2240
2241 unixTime = (time_t)value;
2242 UTCTimestamp = gmtime(&unixTime);
2243
Srinivasan Kannan09de3382010-08-16 16:42:00 -07002244 strftime(gpsDatestamp, sizeof(gpsDatestamp), "%Y:%m:%d", UTCTimestamp);
2245 addExifTag(EXIFTAGID_GPS_DATESTAMP, EXIF_ASCII,
2246 strlen(gpsDatestamp)+1 , 1, (void *)&gpsDatestamp);
2247
Apurva Rajguru5ec76132010-06-16 17:43:46 -07002248 rat_t time_value[3] = { {UTCTimestamp->tm_hour, 1},
2249 {UTCTimestamp->tm_min, 1},
2250 {UTCTimestamp->tm_sec, 1} };
2251
Srinivasan Kannan09de3382010-08-16 16:42:00 -07002252
Apurva Rajguru5ec76132010-06-16 17:43:46 -07002253 memcpy(&gpsTimestamp, &time_value, sizeof(gpsTimestamp));
2254 addExifTag(EXIFTAGID_GPS_TIMESTAMP, EXIF_RATIONAL,
2255 3, 1, (void *)&gpsTimestamp);
2256 }
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08002257
2258}
2259
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002260bool QualcommCameraHardware::native_jpeg_encode(void)
2261{
2262 int jpeg_quality = mParameters.getInt("jpeg-quality");
2263 if (jpeg_quality >= 0) {
2264 LOGV("native_jpeg_encode, current jpeg main img quality =%d",
2265 jpeg_quality);
2266 if(!LINK_jpeg_encoder_setMainImageQuality(jpeg_quality)) {
2267 LOGE("native_jpeg_encode set jpeg-quality failed");
2268 return false;
2269 }
2270 }
2271
2272 int thumbnail_quality = mParameters.getInt("jpeg-thumbnail-quality");
2273 if (thumbnail_quality >= 0) {
2274 LOGV("native_jpeg_encode, current jpeg thumbnail quality =%d",
2275 thumbnail_quality);
2276 if(!LINK_jpeg_encoder_setThumbnailQuality(thumbnail_quality)) {
2277 LOGE("native_jpeg_encode set thumbnail-quality failed");
2278 return false;
2279 }
2280 }
2281
Priyanka Kharat32409f72010-08-25 18:11:03 -07002282 if( (mCurrentTarget != TARGET_MSM7630) && (mCurrentTarget != TARGET_MSM7627) && (mCurrentTarget != TARGET_MSM8660) ) {
Mohan Kandra02486042010-06-18 16:49:43 -07002283 int rotation = mParameters.getInt("rotation");
2284 if (rotation >= 0) {
2285 LOGV("native_jpeg_encode, rotation = %d", rotation);
2286 if(!LINK_jpeg_encoder_setRotation(rotation)) {
2287 LOGE("native_jpeg_encode set rotation failed");
2288 return false;
2289 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002290 }
2291 }
2292
Apurva Rajguru5ec76132010-06-16 17:43:46 -07002293 jpeg_set_location();
2294
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08002295 //set TimeStamp
2296 const char *str = mParameters.get(CameraParameters::KEY_EXIF_DATETIME);
2297 if(str != NULL) {
2298 strncpy(dateTime, str, 19);
2299 dateTime[19] = '\0';
2300 addExifTag(EXIFTAGID_EXIF_DATE_TIME_ORIGINAL, EXIF_ASCII,
2301 20, 1, (void *)dateTime);
2302 }
Mohan Kandra1659b0c2010-07-18 16:36:25 -07002303
Srinivasan Kannan09de3382010-08-16 16:42:00 -07002304 int focalLengthValue = (int) (mParameters.getFloat(
2305 CameraParameters::KEY_FOCAL_LENGTH) * FOCAL_LENGTH_DECIMAL_PRECISON);
2306 rat_t focalLengthRational = {focalLengthValue, FOCAL_LENGTH_DECIMAL_PRECISON};
2307 memcpy(&focalLength, &focalLengthRational, sizeof(focalLengthRational));
2308 addExifTag(EXIFTAGID_FOCAL_LENGTH, EXIF_RATIONAL, 1,
2309 1, (void *)&focalLength);
2310
Srinivasan Kannan264376e2010-08-13 18:54:35 -07002311 uint8_t * thumbnailHeap = NULL;
2312 int thumbfd = -1;
2313
2314 int width = mParameters.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH);
2315 int height = mParameters.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT);
2316
2317 LOGV("width %d and height %d", width , height);
2318
2319 if(width != 0 && height != 0){
Mohan Kandra5e4f9d92010-08-26 18:23:50 -07002320 if((mCurrentTarget == TARGET_MSM7630) ||
2321 (mCurrentTarget == TARGET_MSM8660) ||
2322 (mPreviewFormat == CAMERA_YUV_420_NV21_ADRENO)) {
Srinivasan Kannan264376e2010-08-13 18:54:35 -07002323 thumbnailHeap = (uint8_t *)mRawHeap->mHeap->base();
2324 thumbfd = mRawHeap->mHeap->getHeapID();
2325 } else {
2326 thumbnailHeap = (uint8_t *)mThumbnailHeap->mHeap->base();
2327 thumbfd = mThumbnailHeap->mHeap->getHeapID();
2328 }
2329 }else {
2330 thumbnailHeap = NULL;
2331 thumbfd = 0;
2332 }
2333
Mohan Kandra5e4f9d92010-08-26 18:23:50 -07002334 if( (mCurrentTarget == TARGET_MSM7630) ||
2335 (mCurrentTarget == TARGET_MSM8660) ||
2336 (mPreviewFormat == CAMERA_YUV_420_NV21_ADRENO) ) {
Mohan Kandra1659b0c2010-07-18 16:36:25 -07002337 // Pass the main image as thumbnail buffer, so that jpeg encoder will
2338 // generate thumbnail based on main image.
2339 // Set the input and output dimensions for thumbnail generation to main
2340 // image dimensions and required thumbanail size repectively, for the
2341 // encoder to do downscaling of the main image accordingly.
2342 mCrop.in1_w = mDimension.orig_picture_dx;
2343 mCrop.in1_h = mDimension.orig_picture_dy;
Mohan Kandra5e4f9d92010-08-26 18:23:50 -07002344 /* For Adreno format on targets that don't use VFE other output
2345 * for postView, thumbnail_width and thumbnail_height has the
2346 * actual thumbnail dimensions.
2347 */
Mohan Kandra1659b0c2010-07-18 16:36:25 -07002348 mCrop.out1_w = mDimension.thumbnail_width;
2349 mCrop.out1_h = mDimension.thumbnail_height;
Mohan Kandra5e4f9d92010-08-26 18:23:50 -07002350 /* For targets, that uses VFE other output for postview,
2351 * thumbnail_width and thumbnail_height has values based on postView
2352 * dimensions(mostly previewWidth X previewHeight), but not based on
2353 * required thumbnail dimensions. So, while downscaling, we need to
2354 * pass the actual thumbnail dimensions, not the postview dimensions.
2355 * mThumbnailWidth/Height has the required thumbnail dimensions, so
2356 * use them here.
2357 */
2358 if( (mCurrentTarget == TARGET_MSM7630)||
2359 (mCurrentTarget == TARGET_MSM8660)) {
2360 mCrop.out1_w = mThumbnailWidth;
2361 mCrop.out1_h = mThumbnailHeight;
2362 }
Mohan Kandra1659b0c2010-07-18 16:36:25 -07002363 mDimension.thumbnail_width = mDimension.orig_picture_dx;
2364 mDimension.thumbnail_height = mDimension.orig_picture_dy;
Mohan Kandra5e4f9d92010-08-26 18:23:50 -07002365 LOGV("mCrop.in1_w = %d, mCrop.in1_h = %d", mCrop.in1_w, mCrop.in1_h);
2366 LOGV("mCrop.out1_w = %d, mCrop.out1_h = %d", mCrop.out1_w, mCrop.out1_h);
2367 LOGV("mDimension.thumbnail_width = %d, mDimension.thumbnail_height = %d", mDimension.thumbnail_width, mDimension.thumbnail_height);
2368 int CbCrOffset = -1;
2369 if(mPreviewFormat == CAMERA_YUV_420_NV21_ADRENO)
2370 CbCrOffset = mCbCrOffsetRaw;
2371
Mohan Kandra1659b0c2010-07-18 16:36:25 -07002372 if (!LINK_jpeg_encoder_encode(&mDimension,
Srinivasan Kannan264376e2010-08-13 18:54:35 -07002373 thumbnailHeap,
2374 thumbfd,
Mohan Kandra1659b0c2010-07-18 16:36:25 -07002375 (uint8_t *)mRawHeap->mHeap->base(),
2376 mRawHeap->mHeap->getHeapID(),
2377 &mCrop, exif_data, exif_table_numEntries,
Mohan Kandra5e4f9d92010-08-26 18:23:50 -07002378 jpegPadding/2, CbCrOffset)) {
Mohan Kandra1659b0c2010-07-18 16:36:25 -07002379 LOGE("native_jpeg_encode: jpeg_encoder_encode failed.");
2380 return false;
2381 }
2382 } else {
Srinivasan Kannan264376e2010-08-13 18:54:35 -07002383 if (!LINK_jpeg_encoder_encode(&mDimension,
Mohan Kandra5e4f9d92010-08-26 18:23:50 -07002384 thumbnailHeap,
2385 thumbfd,
2386 (uint8_t *)mRawHeap->mHeap->base(),
2387 mRawHeap->mHeap->getHeapID(),
2388 &mCrop, exif_data, exif_table_numEntries,
2389 jpegPadding/2, -1)) {
Srinivasan Kannan264376e2010-08-13 18:54:35 -07002390 LOGE("native_jpeg_encode: jpeg_encoder_encode failed.");
2391 return false;
2392 }
Mohan Kandra1659b0c2010-07-18 16:36:25 -07002393 }
Mohan Kandra5e4f9d92010-08-26 18:23:50 -07002394
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002395 return true;
2396}
2397
2398bool QualcommCameraHardware::native_set_parm(
2399 cam_ctrl_type type, uint16_t length, void *value)
2400{
2401 struct msm_ctrl_cmd ctrlCmd;
2402
2403 ctrlCmd.timeout_ms = 5000;
2404 ctrlCmd.type = (uint16_t)type;
2405 ctrlCmd.length = length;
2406 // FIXME: this will be put in by the kernel
2407 ctrlCmd.resp_fd = mCameraControlFd;
2408 ctrlCmd.value = value;
2409
2410 LOGV("%s: fd %d, type %d, length %d", __FUNCTION__,
2411 mCameraControlFd, type, length);
2412 if (ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0 ||
2413 ctrlCmd.status != CAM_CTRL_SUCCESS) {
2414 LOGE("%s: error (%s): fd %d, type %d, length %d, status %d",
2415 __FUNCTION__, strerror(errno),
2416 mCameraControlFd, type, length, ctrlCmd.status);
2417 return false;
2418 }
2419 return true;
2420}
2421
2422void QualcommCameraHardware::jpeg_set_location()
2423{
2424 bool encode_location = true;
2425 camera_position_type pt;
2426
2427#define PARSE_LOCATION(what,type,fmt,desc) do { \
2428 pt.what = 0; \
2429 const char *what##_str = mParameters.get("gps-"#what); \
2430 LOGV("GPS PARM %s --> [%s]", "gps-"#what, what##_str); \
2431 if (what##_str) { \
2432 type what = 0; \
2433 if (sscanf(what##_str, fmt, &what) == 1) \
2434 pt.what = what; \
2435 else { \
2436 LOGE("GPS " #what " %s could not" \
2437 " be parsed as a " #desc, what##_str); \
2438 encode_location = false; \
2439 } \
2440 } \
2441 else { \
2442 LOGV("GPS " #what " not specified: " \
2443 "defaulting to zero in EXIF header."); \
2444 encode_location = false; \
2445 } \
2446 } while(0)
2447
2448 PARSE_LOCATION(timestamp, long, "%ld", "long");
2449 if (!pt.timestamp) pt.timestamp = time(NULL);
2450 PARSE_LOCATION(altitude, short, "%hd", "short");
2451 PARSE_LOCATION(latitude, double, "%lf", "double float");
2452 PARSE_LOCATION(longitude, double, "%lf", "double float");
2453
2454#undef PARSE_LOCATION
2455
2456 if (encode_location) {
2457 LOGD("setting image location ALT %d LAT %lf LON %lf",
2458 pt.altitude, pt.latitude, pt.longitude);
Apurva Rajguru5ec76132010-06-16 17:43:46 -07002459
2460 setGpsParameters();
2461 /* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002462 if (!LINK_jpeg_encoder_setLocation(&pt)) {
2463 LOGE("jpeg_set_location: LINK_jpeg_encoder_setLocation failed.");
2464 }
Apurva Rajguru5ec76132010-06-16 17:43:46 -07002465 */
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002466 }
2467 else LOGV("not setting image location");
2468}
2469
2470void QualcommCameraHardware::runFrameThread(void *data)
2471{
2472 LOGV("runFrameThread E");
2473
2474 int cnt;
2475
2476#if DLOPEN_LIBMMCAMERA
2477 // We need to maintain a reference to libqcamera.so for the duration of the
2478 // frame thread, because we do not know when it will exit relative to the
2479 // lifetime of this object. We do not want to dlclose() libqcamera while
2480 // LINK_cam_frame is still running.
2481 void *libhandle = ::dlopen("liboemcamera.so", RTLD_NOW);
2482 LOGV("FRAME: loading libqcamera at %p", libhandle);
2483 if (!libhandle) {
2484 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
2485 }
2486 if (libhandle)
2487#endif
2488 {
2489 LINK_cam_frame(data);
2490 }
2491
Mohan Kandrad9efed92010-01-15 19:08:39 -08002492 mPreviewHeap.clear();
Nishant Pandit3c278cd2010-07-13 15:56:04 +05302493 if(( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250) || (mCurrentTarget == TARGET_MSM8660))
Sravankb4f5f1c2010-01-21 11:06:17 +05302494 mRecordHeap.clear();
2495
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002496#if DLOPEN_LIBMMCAMERA
2497 if (libhandle) {
2498 ::dlclose(libhandle);
2499 LOGV("FRAME: dlclose(libqcamera)");
2500 }
2501#endif
2502
2503 mFrameThreadWaitLock.lock();
2504 mFrameThreadRunning = false;
2505 mFrameThreadWait.signal();
2506 mFrameThreadWaitLock.unlock();
2507
2508 LOGV("runFrameThread X");
2509}
2510
Sravankb4f5f1c2010-01-21 11:06:17 +05302511void QualcommCameraHardware::runVideoThread(void *data)
2512{
2513 LOGD("runVideoThread E");
2514 msm_frame* vframe = NULL;
2515
2516 while(true) {
2517 pthread_mutex_lock(&(g_busy_frame_queue.mut));
2518
Srinivasan Kannanfc3915c2010-03-18 10:54:40 -07002519 // Exit the thread , in case of stop recording..
2520 mVideoThreadWaitLock.lock();
2521 if(mVideoThreadExit){
2522 LOGV("Exiting video thread..");
2523 mVideoThreadWaitLock.unlock();
2524 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
2525 break;
2526 }
2527 mVideoThreadWaitLock.unlock();
2528
Kiran Kumar H Nb49af212010-02-17 15:12:17 -08002529 LOGV("in video_thread : wait for video frame ");
Sravankb4f5f1c2010-01-21 11:06:17 +05302530 // check if any frames are available in busyQ and give callback to
2531 // services/video encoder
2532 cam_frame_wait_video();
2533 LOGV("video_thread, wait over..");
2534
2535 // Exit the thread , in case of stop recording..
2536 mVideoThreadWaitLock.lock();
2537 if(mVideoThreadExit){
Kiran Kumar H Nb49af212010-02-17 15:12:17 -08002538 LOGV("Exiting video thread..");
Sravankb4f5f1c2010-01-21 11:06:17 +05302539 mVideoThreadWaitLock.unlock();
2540 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
2541 break;
2542 }
2543 mVideoThreadWaitLock.unlock();
2544
2545 // Get the video frame to be encoded
2546 vframe = cam_frame_get_video ();
Apurva Rajgurud9b0b302010-02-19 11:22:56 -08002547 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
Sravankb4f5f1c2010-01-21 11:06:17 +05302548 LOGV("in video_thread : got video frame ");
2549
Mohan Kandrabad0eaa2010-02-04 15:11:54 -08002550 if (UNLIKELY(mDebugFps)) {
2551 debugShowVideoFPS();
2552 }
2553
Sravankb4f5f1c2010-01-21 11:06:17 +05302554 if(vframe != NULL) {
2555 // Find the offset within the heap of the current buffer.
2556 LOGV("Got video frame : buffer %d base %d ", vframe->buffer, mRecordHeap->mHeap->base());
2557 ssize_t offset =
2558 (ssize_t)vframe->buffer - (ssize_t)mRecordHeap->mHeap->base();
2559 LOGV("offset = %d , alignsize = %d , offset later = %d", offset, mRecordHeap->mAlignedBufferSize, (offset / mRecordHeap->mAlignedBufferSize));
2560
2561 offset /= mRecordHeap->mAlignedBufferSize;
Mohan Kandra1fd90f92010-06-17 14:54:17 -07002562
2563 //set the track flag to true for this video buffer
2564 record_buffers_tracking_flag[offset] = true;
2565
Mohan Kandra1307f312010-04-29 10:18:42 -07002566 /* Extract the timestamp of this frame */
2567 nsecs_t timeStamp = nsecs_t(vframe->ts.tv_sec)*1000000000LL + vframe->ts.tv_nsec;
Sravankb4f5f1c2010-01-21 11:06:17 +05302568
2569 // dump frames for test purpose
2570#ifdef DUMP_VIDEO_FRAMES
2571 static int frameCnt = 0;
2572 if (frameCnt >= 11 && frameCnt <= 13 ) {
2573 char buf[128];
2574 sprintf(buf, "/data/%d_v.yuv", frameCnt);
2575 int file_fd = open(buf, O_RDWR | O_CREAT, 0777);
2576 LOGV("dumping video frame %d", frameCnt);
2577 if (file_fd < 0) {
2578 LOGE("cannot open file\n");
2579 }
2580 else
2581 {
2582 write(file_fd, (const void *)vframe->buffer,
2583 vframe->cbcr_off * 3 / 2);
2584 }
2585 close(file_fd);
2586 }
2587 frameCnt++;
2588#endif
2589 // Enable IF block to give frames to encoder , ELSE block for just simulation
2590#if 1
2591 LOGV("in video_thread : got video frame, before if check giving frame to services/encoder");
2592 mCallbackLock.lock();
2593 int msgEnabled = mMsgEnabled;
2594 data_callback_timestamp rcb = mDataCallbackTimestamp;
2595 void *rdata = mCallbackCookie;
2596 mCallbackLock.unlock();
2597
2598 if(rcb != NULL && (msgEnabled & CAMERA_MSG_VIDEO_FRAME) ) {
2599 LOGV("in video_thread : got video frame, giving frame to services/encoder");
Mohan Kandra1307f312010-04-29 10:18:42 -07002600 rcb(timeStamp, CAMERA_MSG_VIDEO_FRAME, mRecordHeap->mBuffers[offset], rdata);
Sravankb4f5f1c2010-01-21 11:06:17 +05302601 }
2602#else
2603 // 720p output2 : simulate release frame here:
2604 LOGE("in video_thread simulation , releasing the video frame");
2605 LINK_camframe_free_video(vframe);
2606#endif
2607
2608 } else LOGE("in video_thread get frame returned null");
2609
Sravankb4f5f1c2010-01-21 11:06:17 +05302610
2611 } // end of while loop
Mohan Kandra156d0ac2010-01-25 16:59:17 -08002612
2613 mVideoThreadWaitLock.lock();
2614 mVideoThreadRunning = false;
2615 mVideoThreadWait.signal();
2616 mVideoThreadWaitLock.unlock();
2617
Sravankb4f5f1c2010-01-21 11:06:17 +05302618 LOGV("runVideoThread X");
2619}
2620
2621void *video_thread(void *user)
2622{
2623 LOGV("video_thread E");
2624 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
2625 if (obj != 0) {
2626 obj->runVideoThread(user);
2627 }
2628 else LOGE("not starting video thread: the object went away!");
2629 LOGV("video_thread X");
2630 return NULL;
2631}
2632
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002633void *frame_thread(void *user)
2634{
2635 LOGD("frame_thread E");
2636 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
2637 if (obj != 0) {
2638 obj->runFrameThread(user);
2639 }
2640 else LOGW("not starting frame thread: the object went away!");
2641 LOGD("frame_thread X");
2642 return NULL;
2643}
2644
Mohan Kandra091d5ab2010-07-14 16:53:25 -07002645static int parse_size(const char *str, int &width, int &height)
2646{
2647 // Find the width.
2648 char *end;
2649 int w = (int)strtol(str, &end, 10);
2650 // If an 'x' or 'X' does not immediately follow, give up.
2651 if ( (*end != 'x') && (*end != 'X') )
2652 return -1;
2653
2654 // Find the height, immediately after the 'x'.
2655 int h = (int)strtol(end+1, 0, 10);
2656
2657 width = w;
2658 height = h;
2659
2660 return 0;
2661}
2662
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002663bool QualcommCameraHardware::initPreview()
2664{
2665 // See comments in deinitPreview() for why we have to wait for the frame
2666 // thread here, and why we can't use pthread_join().
Nishant Pandit2cc7a4b2010-08-10 00:13:15 +05302667 const char * pmem_region;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002668 mParameters.getPreviewSize(&previewWidth, &previewHeight);
Sravankb4f5f1c2010-01-21 11:06:17 +05302669
Mohan Kandra091d5ab2010-07-14 16:53:25 -07002670 //Get the Record sizes
2671 const char *recordSize = NULL;
2672 recordSize = mParameters.get("record-size");
2673 if(!recordSize) {
2674 //If application didn't set this parameter string, use the values from
2675 //getPreviewSize() as video dimensions.
2676 LOGI("No Record Size requested, use the preview dimensions");
2677 videoWidth = previewWidth;
2678 videoHeight = previewHeight;
2679 } else {
2680 //Extract the record witdh and height that application requested.
2681 if(!parse_size(recordSize, videoWidth, videoHeight)) {
2682 //VFE output1 shouldn't be greater than VFE output2.
2683 if( (previewWidth > videoWidth) || (previewHeight > videoHeight)) {
2684 //Set preview sizes as record sizes.
2685 LOGI("Preview size %dx%d is greater than record size %dx%d,\
2686 resetting preview size to record size",previewWidth,\
2687 previewHeight, videoWidth, videoHeight);
2688 previewWidth = videoWidth;
2689 previewHeight = videoHeight;
2690 mParameters.setPreviewSize(previewWidth, previewHeight);
2691 }
2692 if( (mCurrentTarget != TARGET_MSM7630)
2693 && (mCurrentTarget != TARGET_QSD8250)
2694 && (mCurrentTarget != TARGET_MSM8660) ) {
2695 //For Single VFE output targets, use record dimensions as preview dimensions.
2696 previewWidth = videoWidth;
2697 previewHeight = videoHeight;
2698 mParameters.setPreviewSize(previewWidth, previewHeight);
2699 }
2700 } else {
2701 LOGE("initPreview X: failed to parse parameter record-size (%s)", recordSize);
2702 return false;
2703 }
2704 }
2705
Mohan Kandra0d115d12010-08-19 11:47:15 -07002706 mDimension.display_width = previewWidth;
2707 mDimension.display_height= previewHeight;
2708
Sravankb4f5f1c2010-01-21 11:06:17 +05302709 LOGV("initPreview E: preview size=%dx%d videosize = %d x %d", previewWidth, previewHeight, videoWidth, videoHeight );
2710
Nishant Pandit3c278cd2010-07-13 15:56:04 +05302711 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250) || (mCurrentTarget == TARGET_MSM8660)) {
Mohan Kandra39fad8d2010-07-15 12:29:19 -07002712 mDimension.video_width = CEILING16(videoWidth);
2713 /* Backup the video dimensions, as video dimensions in mDimension
2714 * will be modified when DIS is supported. Need the actual values
2715 * to pass ap part of VPE config
2716 */
2717 videoWidth = mDimension.video_width;
Sravankb4f5f1c2010-01-21 11:06:17 +05302718 mDimension.video_height = videoHeight;
2719 LOGV("initPreview : preview size=%dx%d videosize = %d x %d", previewWidth, previewHeight, mDimension.video_width, mDimension.video_height );
2720 }
2721
2722
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002723 mFrameThreadWaitLock.lock();
2724 while (mFrameThreadRunning) {
2725 LOGV("initPreview: waiting for old frame thread to complete.");
2726 mFrameThreadWait.wait(mFrameThreadWaitLock);
2727 LOGV("initPreview: old frame thread completed.");
2728 }
2729 mFrameThreadWaitLock.unlock();
2730
Mohan Kandraca2e7a92010-06-21 15:48:45 -07002731 mInSnapshotModeWaitLock.lock();
2732 while (mInSnapshotMode) {
2733 LOGV("initPreview: waiting for snapshot mode to complete.");
2734 mInSnapshotModeWait.wait(mInSnapshotModeWaitLock);
2735 LOGV("initPreview: snapshot mode completed.");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002736 }
Mohan Kandraca2e7a92010-06-21 15:48:45 -07002737 mInSnapshotModeWaitLock.unlock();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002738
Nishant Pandit2cc7a4b2010-08-10 00:13:15 +05302739 /*Temporary migrating the preview buffers to smi pool for 8x60 till the bug is resolved in the pmem_adsp pool*/
2740 if(mCurrentTarget == TARGET_MSM8660)
2741 pmem_region = "/dev/pmem_smipool";
2742 else
2743 pmem_region = "/dev/pmem_adsp";
2744
2745
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002746 int cnt = 0;
2747 mPreviewFrameSize = previewWidth * previewHeight * 3/2;
Mohan Kandra02486042010-06-18 16:49:43 -07002748 int CbCrOffset = PAD_TO_WORD(previewWidth * previewHeight);
Mohan Kandra7110c242010-07-18 15:34:48 -07002749
2750 //Pass the yuv formats, display dimensions,
2751 //so that vfe will be initialized accordingly.
2752 mDimension.display_luma_width = previewWidth;
2753 mDimension.display_luma_height = previewHeight;
2754 mDimension.display_chroma_width = previewWidth;
2755 mDimension.display_chroma_height = previewHeight;
2756 if(mPreviewFormat == CAMERA_YUV_420_NV21_ADRENO) {
2757 mPreviewFrameSize = PAD_TO_4K(CEILING32(previewWidth) * CEILING32(previewHeight)) +
2758 2 * (CEILING32(previewWidth/2) * CEILING32(previewHeight/2));
2759 CbCrOffset = PAD_TO_4K(CEILING32(previewWidth) * CEILING32(previewHeight));
2760 mDimension.prev_format = CAMERA_YUV_420_NV21_ADRENO;
2761 mDimension.display_luma_width = CEILING32(previewWidth);
2762 mDimension.display_luma_height = CEILING32(previewHeight);
2763 mDimension.display_chroma_width = 2 * CEILING32(previewWidth/2);
2764 //Chroma Height is not needed as of now. Just sending with other dimensions.
2765 mDimension.display_chroma_height = CEILING32(previewHeight/2);
2766 }
2767 LOGV("mDimension.prev_format = %d", mDimension.prev_format);
2768 LOGV("mDimension.display_luma_width = %d", mDimension.display_luma_width);
2769 LOGV("mDimension.display_luma_height = %d", mDimension.display_luma_height);
2770 LOGV("mDimension.display_chroma_width = %d", mDimension.display_chroma_width);
2771 LOGV("mDimension.display_chroma_height = %d", mDimension.display_chroma_height);
2772
Mohan Kandrad9efed92010-01-15 19:08:39 -08002773 dstOffset = 0;
Nishant Pandit2cc7a4b2010-08-10 00:13:15 +05302774 mPreviewHeap = new PmemPool(pmem_region,
Mohan Kandra284966d2010-01-05 13:39:15 -08002775 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
2776 mCameraControlFd,
Sravankb4f5f1c2010-01-21 11:06:17 +05302777 MSM_PMEM_PREVIEW, //MSM_PMEM_OUTPUT2,
Mohan Kandra284966d2010-01-05 13:39:15 -08002778 mPreviewFrameSize,
Mohan Kandrad9efed92010-01-15 19:08:39 -08002779 kPreviewBufferCountActual,
Mohan Kandra284966d2010-01-05 13:39:15 -08002780 mPreviewFrameSize,
Mohan Kandra02486042010-06-18 16:49:43 -07002781 CbCrOffset,
2782 0,
Mohan Kandrad9efed92010-01-15 19:08:39 -08002783 "preview");
Mohan Kandra284966d2010-01-05 13:39:15 -08002784
Mohan Kandrad9efed92010-01-15 19:08:39 -08002785 if (!mPreviewHeap->initialized()) {
2786 mPreviewHeap.clear();
Mohan Kandra284966d2010-01-05 13:39:15 -08002787 LOGE("initPreview X: could not initialize Camera preview heap.");
2788 return false;
2789 }
Mohan Kandra5e4f9d92010-08-26 18:23:50 -07002790 if(mCurrentTarget == TARGET_MSM7627) {
Srinivasan Kannan613301c2010-02-10 17:08:53 -08002791 mPostViewHeap.clear();
Mohan Kandra5e4f9d92010-08-26 18:23:50 -07002792 if(mPostViewHeap == NULL) {
2793 LOGV(" Allocating Postview heap ");
2794 /* mPostViewHeap should be declared only for 7630 target */
2795 mPostViewHeap =
2796 new PmemPool("/dev/pmem_adsp",
2797 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
2798 mCameraControlFd,
2799 MSM_PMEM_PREVIEW, //MSM_PMEM_OUTPUT2,
2800 mPreviewFrameSize,
2801 1,
2802 mPreviewFrameSize,
Mohan Kandra02486042010-06-18 16:49:43 -07002803 CbCrOffset,
2804 0,
Mohan Kandra5e4f9d92010-08-26 18:23:50 -07002805 "postview");
Mohan Kandra284966d2010-01-05 13:39:15 -08002806
Mohan Kandra5e4f9d92010-08-26 18:23:50 -07002807 if (!mPostViewHeap->initialized()) {
2808 mPostViewHeap.clear();
2809 LOGE(" Failed to initialize Postview Heap");
2810 return false;
2811 }
2812 }
Mohan Kandraf1ebf982010-02-02 15:25:43 -08002813 }
2814
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002815
Mohan Kandracedd6cc2010-09-14 14:37:08 -07002816 //set DIS value to get the updated video width and height to calculate
2817 //the required record buffer size
2818 if(mVpeEnabled) {
2819 bool status = setDIS();
2820 if(status) {
2821 LOGE("Failed to set DIS");
2822 return false;
2823 }
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002824 }
Sravankb4f5f1c2010-01-21 11:06:17 +05302825
Mohan Kandracedd6cc2010-09-14 14:37:08 -07002826 //Pass the original video width and height and get the required width
2827 //and height for record buffer allocation
2828 mDimension.orig_video_width = videoWidth;
2829 mDimension.orig_video_height = videoHeight;
2830
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002831 // mDimension will be filled with thumbnail_width, thumbnail_height,
2832 // orig_picture_dx, and orig_picture_dy after this function call. We need to
2833 // keep it for jpeg_encoder_encode.
2834 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
2835 sizeof(cam_ctrl_dimension_t), &mDimension);
2836
Mohan Kandracedd6cc2010-09-14 14:37:08 -07002837 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250) || (mCurrentTarget == TARGET_MSM8660)) {
2838
2839 // Allocate video buffers after allocating preview buffers.
2840 initRecord();
2841 }
2842
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002843 if (ret) {
2844 for (cnt = 0; cnt < kPreviewBufferCount; cnt++) {
Mohan Kandrad9efed92010-01-15 19:08:39 -08002845 frames[cnt].fd = mPreviewHeap->mHeap->getHeapID();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002846 frames[cnt].buffer =
Mohan Kandrad9efed92010-01-15 19:08:39 -08002847 (uint32_t)mPreviewHeap->mHeap->base() + mPreviewHeap->mAlignedBufferSize * cnt;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002848 frames[cnt].y_off = 0;
Mohan Kandra02486042010-06-18 16:49:43 -07002849 frames[cnt].cbcr_off = CbCrOffset;
Sravankb4f5f1c2010-01-21 11:06:17 +05302850 frames[cnt].path = OUTPUT_TYPE_P; // MSM_FRAME_ENC;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002851 }
2852
2853 mFrameThreadWaitLock.lock();
2854 pthread_attr_t attr;
2855 pthread_attr_init(&attr);
2856 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
Sravankb4f5f1c2010-01-21 11:06:17 +05302857
2858 frame_parms.frame = frames[kPreviewBufferCount - 1];
Apurva Rajguruc73c1722010-04-15 17:39:11 -07002859
Nishant Pandit3c278cd2010-07-13 15:56:04 +05302860 if( mCurrentTarget == TARGET_MSM7630 || mCurrentTarget == TARGET_QSD8250 || mCurrentTarget == TARGET_MSM8660)
Apurva Rajguruc73c1722010-04-15 17:39:11 -07002861 frame_parms.video_frame = recordframes[kPreviewBufferCount - 1];
2862 else
2863 frame_parms.video_frame = frames[kPreviewBufferCount - 1];
Sravankb4f5f1c2010-01-21 11:06:17 +05302864
2865 LOGV ("initpreview before cam_frame thread carete , video frame buffer=%lu fd=%d y_off=%d cbcr_off=%d \n",
2866 (unsigned long)frame_parms.video_frame.buffer, frame_parms.video_frame.fd, frame_parms.video_frame.y_off,
2867 frame_parms.video_frame.cbcr_off);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002868 mFrameThreadRunning = !pthread_create(&mFrameThread,
2869 &attr,
2870 frame_thread,
Sravankb4f5f1c2010-01-21 11:06:17 +05302871 (void*)&(frame_parms));
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002872 ret = mFrameThreadRunning;
2873 mFrameThreadWaitLock.unlock();
2874 }
2875
2876 LOGV("initPreview X: %d", ret);
2877 return ret;
2878}
2879
2880void QualcommCameraHardware::deinitPreview(void)
2881{
2882 LOGI("deinitPreview E");
2883
2884 // When we call deinitPreview(), we signal to the frame thread that it
2885 // needs to exit, but we DO NOT WAIT for it to complete here. The problem
2886 // is that deinitPreview is sometimes called from the frame-thread's
2887 // callback, when the refcount on the Camera client reaches zero. If we
2888 // called pthread_join(), we would deadlock. So, we just call
2889 // LINK_camframe_terminate() in deinitPreview(), which makes sure that
2890 // after the preview callback returns, the camframe thread will exit. We
2891 // could call pthread_join() in initPreview() to join the last frame
2892 // thread. However, we would also have to call pthread_join() in release
2893 // as well, shortly before we destroy the object; this would cause the same
2894 // deadlock, since release(), like deinitPreview(), may also be called from
2895 // the frame-thread's callback. This we have to make the frame thread
2896 // detached, and use a separate mechanism to wait for it to complete.
2897
Kiran Kumar H N7ac84e32010-02-01 10:58:47 -08002898 LINK_camframe_terminate();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002899 LOGI("deinitPreview X");
2900}
2901
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002902bool QualcommCameraHardware::initRawSnapshot()
2903{
2904 LOGV("initRawSnapshot E");
Nishant Pandit62fe9aa2010-07-27 04:23:17 +05302905 const char * pmem_region;
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002906
2907 //get width and height from Dimension Object
2908 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
2909 sizeof(cam_ctrl_dimension_t), &mDimension);
2910
2911 if(!ret){
2912 LOGE("initRawSnapshot X: failed to set dimension");
2913 return false;
2914 }
2915 int rawSnapshotSize = mDimension.raw_picture_height *
2916 mDimension.raw_picture_width;
2917
2918 LOGV("raw_snapshot_buffer_size = %d, raw_picture_height = %d, "\
2919 "raw_picture_width = %d",
2920 rawSnapshotSize, mDimension.raw_picture_height,
2921 mDimension.raw_picture_width);
2922
2923 if (mRawSnapShotPmemHeap != NULL) {
2924 LOGV("initRawSnapshot: clearing old mRawSnapShotPmemHeap.");
2925 mRawSnapShotPmemHeap.clear();
2926 }
Nishant Pandit62fe9aa2010-07-27 04:23:17 +05302927 if(mCurrentTarget == TARGET_MSM8660)
2928 pmem_region = "/dev/pmem_smipool";
2929 else
2930 pmem_region = "/dev/pmem_adsp";
2931
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002932
2933 //Pmem based pool for Camera Driver
Nishant Pandit62fe9aa2010-07-27 04:23:17 +05302934 mRawSnapShotPmemHeap = new PmemPool(pmem_region,
Dinesh Gargeecf1a62010-04-19 16:31:30 -07002935 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002936 mCameraControlFd,
2937 MSM_PMEM_RAW_MAINIMG,
2938 rawSnapshotSize,
2939 1,
2940 rawSnapshotSize,
Mohan Kandra02486042010-06-18 16:49:43 -07002941 0,
2942 0,
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002943 "raw pmem snapshot camera");
2944
2945 if (!mRawSnapShotPmemHeap->initialized()) {
2946 mRawSnapShotPmemHeap.clear();
2947 LOGE("initRawSnapshot X: error initializing mRawSnapshotHeap");
2948 return false;
2949 }
2950 LOGV("initRawSnapshot X");
2951 return true;
2952
2953}
2954
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002955bool QualcommCameraHardware::initRaw(bool initJpegHeap)
2956{
2957 int rawWidth, rawHeight;
Nishant Pandit62fe9aa2010-07-27 04:23:17 +05302958 const char * pmem_region;
Apurva Rajguru8d1773b2009-12-02 14:21:23 -08002959
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002960 mParameters.getPictureSize(&rawWidth, &rawHeight);
2961 LOGV("initRaw E: picture size=%dx%d", rawWidth, rawHeight);
2962
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08002963 int thumbnailBufferSize;
2964 //Thumbnail height should be smaller than Picture height
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002965 if (rawHeight > (int)thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height){
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08002966 mDimension.ui_thumbnail_width =
2967 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].width;
2968 mDimension.ui_thumbnail_height =
2969 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height;
2970 uint32_t pictureAspectRatio = (uint32_t)((rawWidth * Q12) / rawHeight);
2971 uint32_t i;
2972 for(i = 0; i < THUMBNAIL_SIZE_COUNT; i++ )
2973 {
2974 if(thumbnail_sizes[i].aspect_ratio == pictureAspectRatio)
2975 {
2976 mDimension.ui_thumbnail_width = thumbnail_sizes[i].width;
2977 mDimension.ui_thumbnail_height = thumbnail_sizes[i].height;
2978 break;
2979 }
2980 }
2981 }
2982 else{
2983 mDimension.ui_thumbnail_height = THUMBNAIL_SMALL_HEIGHT;
2984 mDimension.ui_thumbnail_width =
2985 (THUMBNAIL_SMALL_HEIGHT * rawWidth)/ rawHeight;
2986 }
2987
Mohan Kandra5e4f9d92010-08-26 18:23:50 -07002988 if((mCurrentTarget == TARGET_MSM7630) ||
2989 (mCurrentTarget == TARGET_MSM8660)) {
2990 if(rawHeight < previewHeight) {
2991 mDimension.ui_thumbnail_height = THUMBNAIL_SMALL_HEIGHT;
2992 mDimension.ui_thumbnail_width =
2993 (THUMBNAIL_SMALL_HEIGHT * rawWidth)/ rawHeight;
2994 }
2995 /* store the thumbanil dimensions which are needed
2996 * by the jpeg downscaler to generate thumbnails from
2997 * main YUV image.
2998 */
2999 mThumbnailWidth = mDimension.ui_thumbnail_width;
3000 mThumbnailHeight = mDimension.ui_thumbnail_height;
3001 /* As thumbnail is generated from main YUV image,
3002 * configure and use the VFE other output to get
3003 * an image of preview dimensions for postView use.
3004 * So, mThumbnailHeap will be used for postview rather than
3005 * as thumbnail(Not changing the terminology to keep changes minimum).
3006 */
3007 if(rawHeight >= previewHeight) {
3008 mDimension.ui_thumbnail_width = previewWidth;
3009 mDimension.ui_thumbnail_height = previewHeight;
3010 }
3011 }
3012
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08003013 LOGV("Thumbnail Size Width %d Height %d",
3014 mDimension.ui_thumbnail_width,
3015 mDimension.ui_thumbnail_height);
3016
3017 thumbnailBufferSize = mDimension.ui_thumbnail_width *
3018 mDimension.ui_thumbnail_height * 3 / 2;
Mohan Kandra02486042010-06-18 16:49:43 -07003019 int CbCrOffsetThumb = PAD_TO_WORD(mDimension.ui_thumbnail_width *
3020 mDimension.ui_thumbnail_height);
Mohan Kandra7110c242010-07-18 15:34:48 -07003021 if(mPreviewFormat == CAMERA_YUV_420_NV21_ADRENO){
Mohan Kandra1659b0c2010-07-18 16:36:25 -07003022 mDimension.main_img_format = CAMERA_YUV_420_NV21_ADRENO;
3023 mDimension.thumb_format = CAMERA_YUV_420_NV21_ADRENO;
Mohan Kandra7110c242010-07-18 15:34:48 -07003024 thumbnailBufferSize = PAD_TO_4K(CEILING32(mDimension.ui_thumbnail_width) *
3025 CEILING32(mDimension.ui_thumbnail_height)) +
3026 2 * (CEILING32(mDimension.ui_thumbnail_width/2) *
3027 CEILING32(mDimension.ui_thumbnail_height/2));
3028 CbCrOffsetThumb = PAD_TO_4K(CEILING32(mDimension.ui_thumbnail_width) *
3029 CEILING32(mDimension.ui_thumbnail_height));
3030 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003031 // mDimension will be filled with thumbnail_width, thumbnail_height,
3032 // orig_picture_dx, and orig_picture_dy after this function call. We need to
3033 // keep it for jpeg_encoder_encode.
3034 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
3035 sizeof(cam_ctrl_dimension_t), &mDimension);
3036 if(!ret) {
3037 LOGE("initRaw X: failed to set dimension");
3038 return false;
3039 }
3040
3041 if (mJpegHeap != NULL) {
3042 LOGV("initRaw: clearing old mJpegHeap.");
3043 mJpegHeap.clear();
3044 }
3045
3046 // Snapshot
3047 mRawSize = rawWidth * rawHeight * 3 / 2;
Mohan Kandra1659b0c2010-07-18 16:36:25 -07003048 mCbCrOffsetRaw = PAD_TO_WORD(rawWidth * rawHeight);
Mohan Kandra7110c242010-07-18 15:34:48 -07003049 if(mPreviewFormat == CAMERA_YUV_420_NV21_ADRENO) {
3050 mRawSize = PAD_TO_4K(CEILING32(rawWidth) * CEILING32(rawHeight)) +
3051 2 * (CEILING32(rawWidth/2) * CEILING32(rawHeight/2));
Mohan Kandra1659b0c2010-07-18 16:36:25 -07003052 mCbCrOffsetRaw = PAD_TO_4K(CEILING32(rawWidth) * CEILING32(rawHeight));
Mohan Kandra7110c242010-07-18 15:34:48 -07003053 }
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08003054 if( mCurrentTarget == TARGET_MSM7627 )
Mohan Kandra7110c242010-07-18 15:34:48 -07003055 mJpegMaxSize = CEILING16(rawWidth) * CEILING16(rawHeight) * 3 / 2;
3056 else {
3057 mJpegMaxSize = rawWidth * rawHeight * 3 / 2;
3058 if(mPreviewFormat == CAMERA_YUV_420_NV21_ADRENO){
3059 mJpegMaxSize =
3060 PAD_TO_4K(CEILING32(rawWidth) * CEILING32(rawHeight)) +
3061 2 * (CEILING32(rawWidth/2) * CEILING32(rawHeight/2));
3062 }
3063 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003064
Mohan Kandra02486042010-06-18 16:49:43 -07003065 //For offline jpeg hw encoder, jpeg encoder will provide us the
3066 //required offsets and buffer size depending on the rotation.
3067 int yOffset = 0;
Priyanka Kharat32409f72010-08-25 18:11:03 -07003068 if( (mCurrentTarget == TARGET_MSM7630) || (mCurrentTarget == TARGET_MSM7627) || (mCurrentTarget == TARGET_MSM8660)) {
Mohan Kandra02486042010-06-18 16:49:43 -07003069 int rotation = mParameters.getInt("rotation");
3070 if (rotation >= 0) {
3071 LOGV("initRaw, jpeg_rotation = %d", rotation);
3072 if(!LINK_jpeg_encoder_setRotation(rotation)) {
3073 LOGE("native_jpeg_encode set rotation failed");
3074 return false;
3075 }
3076 }
Mohan Kandra1659b0c2010-07-18 16:36:25 -07003077 //Don't call the get_buffer_offset() for ADRENO, as the width and height
3078 //for Adreno format will be of CEILING32.
3079 if(mPreviewFormat != CAMERA_YUV_420_NV21_ADRENO) {
Mohan Kandra5e4f9d92010-08-26 18:23:50 -07003080 LINK_jpeg_encoder_get_buffer_offset(rawWidth, rawHeight, (uint32_t *)&yOffset,
Mohan Kandra1659b0c2010-07-18 16:36:25 -07003081 (uint32_t *)&mCbCrOffsetRaw, (uint32_t *)&mRawSize);
Mohan Kandra5e4f9d92010-08-26 18:23:50 -07003082 mJpegMaxSize = mRawSize;
3083 }
Mohan Kandra1659b0c2010-07-18 16:36:25 -07003084 LOGV("initRaw: yOffset = %d, mCbCrOffsetRaw = %d, mRawSize = %d",
3085 yOffset, mCbCrOffsetRaw, mRawSize);
3086 }
Mohan Kandra02486042010-06-18 16:49:43 -07003087
Nishant Pandit62fe9aa2010-07-27 04:23:17 +05303088 if(mCurrentTarget == TARGET_MSM8660)
3089 pmem_region = "/dev/pmem_smipool";
3090 else
3091 pmem_region = "/dev/pmem_adsp";
3092
3093
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003094 LOGV("initRaw: initializing mRawHeap.");
3095 mRawHeap =
Nishant Pandit62fe9aa2010-07-27 04:23:17 +05303096 new PmemPool(pmem_region,
Dinesh Gargeecf1a62010-04-19 16:31:30 -07003097 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003098 mCameraControlFd,
3099 MSM_PMEM_MAINIMG,
3100 mJpegMaxSize,
3101 kRawBufferCount,
3102 mRawSize,
Mohan Kandra1659b0c2010-07-18 16:36:25 -07003103 mCbCrOffsetRaw,
Mohan Kandra02486042010-06-18 16:49:43 -07003104 yOffset,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003105 "snapshot camera");
3106
3107 if (!mRawHeap->initialized()) {
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08003108 LOGE("initRaw X failed ");
3109 mRawHeap.clear();
3110 LOGE("initRaw X: error initializing mRawHeap");
3111 return false;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003112 }
3113
Mohan Kandra1659b0c2010-07-18 16:36:25 -07003114 //This is kind of workaround for the GPU limitation, as it can't
3115 //output in line to correct NV21 adreno formula for some snapshot
3116 //sizes (like 3264x2448). This change of cbcr offset will ensure that
3117 //chroma plane always starts at the beginning of a row.
3118 if(mPreviewFormat != CAMERA_YUV_420_NV21_ADRENO)
3119 mCbCrOffsetRaw = CEILING32(rawWidth) * CEILING32(rawHeight);
3120
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003121 LOGV("do_mmap snapshot pbuf = %p, pmem_fd = %d",
3122 (uint8_t *)mRawHeap->mHeap->base(), mRawHeap->mHeap->getHeapID());
3123
3124 // Jpeg
3125
3126 if (initJpegHeap) {
3127 LOGV("initRaw: initializing mJpegHeap.");
3128 mJpegHeap =
3129 new AshmemPool(mJpegMaxSize,
3130 kJpegBufferCount,
3131 0, // we do not know how big the picture will be
3132 "jpeg");
3133
3134 if (!mJpegHeap->initialized()) {
3135 mJpegHeap.clear();
3136 mRawHeap.clear();
3137 LOGE("initRaw X failed: error initializing mJpegHeap.");
3138 return false;
3139 }
3140
3141 // Thumbnails
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003142 mThumbnailHeap =
Nishant Pandit62fe9aa2010-07-27 04:23:17 +05303143 new PmemPool(pmem_region,
Dinesh Gargeecf1a62010-04-19 16:31:30 -07003144 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003145 mCameraControlFd,
3146 MSM_PMEM_THUMBNAIL,
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08003147 thumbnailBufferSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003148 1,
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08003149 thumbnailBufferSize,
Mohan Kandra02486042010-06-18 16:49:43 -07003150 CbCrOffsetThumb,
3151 0,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003152 "thumbnail");
3153
3154 if (!mThumbnailHeap->initialized()) {
3155 mThumbnailHeap.clear();
3156 mJpegHeap.clear();
3157 mRawHeap.clear();
3158 LOGE("initRaw X failed: error initializing mThumbnailHeap.");
3159 return false;
3160 }
3161 }
3162
3163 LOGV("initRaw X");
3164 return true;
3165}
3166
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08003167
3168void QualcommCameraHardware::deinitRawSnapshot()
3169{
3170 LOGV("deinitRawSnapshot E");
3171 mRawSnapShotPmemHeap.clear();
3172 mRawSnapshotAshmemHeap.clear();
3173 LOGV("deinitRawSnapshot X");
3174}
3175
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003176void QualcommCameraHardware::deinitRaw()
3177{
3178 LOGV("deinitRaw E");
3179
3180 mThumbnailHeap.clear();
3181 mJpegHeap.clear();
3182 mRawHeap.clear();
3183 mDisplayHeap.clear();
3184
3185 LOGV("deinitRaw X");
3186}
3187
3188void QualcommCameraHardware::release()
3189{
Mohan Kandra0d115d12010-08-19 11:47:15 -07003190 LOGI("release E");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003191 Mutex::Autolock l(&mLock);
3192
3193#if DLOPEN_LIBMMCAMERA
3194 if (libmmcamera == NULL) {
3195 LOGE("ERROR: multiple release!");
3196 return;
3197 }
3198#else
3199#warning "Cannot detect multiple release when not dlopen()ing libqcamera!"
3200#endif
3201
3202 int cnt, rc;
3203 struct msm_ctrl_cmd ctrlCmd;
Mohan Kandra0d115d12010-08-19 11:47:15 -07003204 LOGI("release: mCameraRunning = %d", mCameraRunning);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003205 if (mCameraRunning) {
3206 if(mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME)) {
3207 mRecordFrameLock.lock();
3208 mReleasedRecordingFrame = true;
3209 mRecordWait.signal();
3210 mRecordFrameLock.unlock();
3211 }
3212 stopPreviewInternal();
Mohan Kandra0d115d12010-08-19 11:47:15 -07003213 LOGI("release: stopPreviewInternal done.");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003214 }
3215
Mohan Kandra5e4f9d92010-08-26 18:23:50 -07003216 if(mCurrentTarget == TARGET_MSM7627) {
3217 mPostViewHeap.clear();
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003218 mPostViewHeap = NULL;
3219 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003220 LINK_jpeg_encoder_join();
Srinivasan Kannan426cde72010-06-04 09:37:21 -07003221 {
3222 Mutex::Autolock l (&mRawPictureHeapLock);
3223 deinitRaw();
3224 }
Mohan Kandraca2e7a92010-06-21 15:48:45 -07003225 //Signal the snapshot thread
3226 mJpegThreadWaitLock.lock();
3227 mJpegThreadRunning = false;
3228 mJpegThreadWait.signal();
3229 mJpegThreadWaitLock.unlock();
3230
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08003231 deinitRawSnapshot();
Mohan Kandra0d115d12010-08-19 11:47:15 -07003232 LOGI("release: clearing resources done.");
Srinivasan Kannan426cde72010-06-04 09:37:21 -07003233
Priyanka Kharat85cebed2010-05-12 14:57:57 -07003234
3235 ctrlCmd.timeout_ms = 5000;
3236 ctrlCmd.length = 0;
3237 ctrlCmd.type = (uint16_t)CAMERA_EXIT;
3238 ctrlCmd.resp_fd = mCameraControlFd; // FIXME: this will be put in by the kernel
3239 if (ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0)
3240 LOGE("ioctl CAMERA_EXIT fd %d error %s",
3241 mCameraControlFd, strerror(errno));
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003242
Nishant Pandit741742b2010-09-21 03:24:20 +05303243 LINK_mm_camera_config_deinit(&mCfgControl);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003244 close(mCameraControlFd);
3245 mCameraControlFd = -1;
Mohan Kandra284966d2010-01-05 13:39:15 -08003246 if(fb_fd >= 0) {
3247 close(fb_fd);
3248 fb_fd = -1;
3249 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003250#if DLOPEN_LIBMMCAMERA
3251 if (libmmcamera) {
3252 ::dlclose(libmmcamera);
3253 LOGV("dlclose(libqcamera)");
3254 libmmcamera = NULL;
3255 }
3256#endif
3257
Priyanka Kharatf2deffb2010-05-17 18:11:31 -07003258 singleton_lock.lock();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003259 singleton_releasing = true;
Srinivasan Kannan78444e42010-06-10 15:39:29 -07003260 singleton_releasing_start_time = systemTime();
Priyanka Kharatf2deffb2010-05-17 18:11:31 -07003261 singleton_lock.unlock();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003262
Mohan Kandra0d115d12010-08-19 11:47:15 -07003263 LOGI("release X: mCameraRunning = %d, mFrameThreadRunning = %d", mCameraRunning, mFrameThreadRunning);
3264 LOGI("mVideoThreadRunning = %d, mSnapshotThreadRunning = %d, mJpegThreadRunning = %d", mVideoThreadRunning, mSnapshotThreadRunning, mJpegThreadRunning);
3265 LOGI("camframe_timeout_flag = %d, mAutoFocusThreadRunning = %d", camframe_timeout_flag, mAutoFocusThreadRunning);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003266}
3267
3268QualcommCameraHardware::~QualcommCameraHardware()
3269{
Mohan Kandra0d115d12010-08-19 11:47:15 -07003270 LOGI("~QualcommCameraHardware E");
Priyanka Kharatf2deffb2010-05-17 18:11:31 -07003271 singleton_lock.lock();
Apurva Rajguruc73c1722010-04-15 17:39:11 -07003272
Nishant Pandit3c278cd2010-07-13 15:56:04 +05303273 if( mCurrentTarget == TARGET_MSM7630 || mCurrentTarget == TARGET_QSD8250 || mCurrentTarget == TARGET_MSM8660 ) {
Apurva Rajguruc73c1722010-04-15 17:39:11 -07003274 delete [] recordframes;
3275 recordframes = NULL;
Mohan Kandra1fd90f92010-06-17 14:54:17 -07003276 delete [] record_buffers_tracking_flag;
3277 record_buffers_tracking_flag = NULL;
Apurva Rajguruc73c1722010-04-15 17:39:11 -07003278 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003279 singleton.clear();
3280 singleton_releasing = false;
Srinivasan Kannan78444e42010-06-10 15:39:29 -07003281 singleton_releasing_start_time = 0;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003282 singleton_wait.signal();
Priyanka Kharatf2deffb2010-05-17 18:11:31 -07003283 singleton_lock.unlock();
Mohan Kandra0d115d12010-08-19 11:47:15 -07003284 LOGI("~QualcommCameraHardware X");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003285}
3286
3287sp<IMemoryHeap> QualcommCameraHardware::getRawHeap() const
3288{
3289 LOGV("getRawHeap");
3290 return mDisplayHeap != NULL ? mDisplayHeap->mHeap : NULL;
3291}
3292
3293sp<IMemoryHeap> QualcommCameraHardware::getPreviewHeap() const
3294{
3295 LOGV("getPreviewHeap");
Mohan Kandrad9efed92010-01-15 19:08:39 -08003296 return mPreviewHeap != NULL ? mPreviewHeap->mHeap : NULL;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003297}
3298
3299status_t QualcommCameraHardware::startPreviewInternal()
3300{
Sravankb4f5f1c2010-01-21 11:06:17 +05303301 LOGV("in startPreviewInternal : E");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003302 if(mCameraRunning) {
3303 LOGV("startPreview X: preview already running.");
3304 return NO_ERROR;
3305 }
3306
3307 if (!mPreviewInitialized) {
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08003308 mLastQueuedFrame = NULL;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003309 mPreviewInitialized = initPreview();
3310 if (!mPreviewInitialized) {
3311 LOGE("startPreview X initPreview failed. Not starting preview.");
3312 return UNKNOWN_ERROR;
3313 }
3314 }
3315
Srinivasan Kannan74712c92010-04-07 13:36:48 -07003316 {
3317 Mutex::Autolock cameraRunningLock(&mCameraRunningLock);
3318 if(( mCurrentTarget != TARGET_MSM7630 ) &&
Nishant Pandit3c278cd2010-07-13 15:56:04 +05303319 (mCurrentTarget != TARGET_QSD8250) && (mCurrentTarget != TARGET_MSM8660))
Srinivasan Kannan74712c92010-04-07 13:36:48 -07003320 mCameraRunning = native_start_preview(mCameraControlFd);
3321 else
3322 mCameraRunning = native_start_video(mCameraControlFd);
3323 }
Sravankb4f5f1c2010-01-21 11:06:17 +05303324
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003325 if(!mCameraRunning) {
3326 deinitPreview();
3327 mPreviewInitialized = false;
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08003328 mOverlay = NULL;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003329 LOGE("startPreview X: native_start_preview failed!");
3330 return UNKNOWN_ERROR;
3331 }
3332
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08003333 //Reset the Gps Information
3334 exif_table_numEntries = 0;
Mohan Kandra284966d2010-01-05 13:39:15 -08003335
Sravankb4f5f1c2010-01-21 11:06:17 +05303336 LOGV("startPreviewInternal X");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003337 return NO_ERROR;
3338}
3339
3340status_t QualcommCameraHardware::startPreview()
3341{
3342 LOGV("startPreview E");
3343 Mutex::Autolock l(&mLock);
3344 return startPreviewInternal();
3345}
3346
3347void QualcommCameraHardware::stopPreviewInternal()
3348{
Mohan Kandra0d115d12010-08-19 11:47:15 -07003349 LOGI("stopPreviewInternal E: %d", mCameraRunning);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003350 if (mCameraRunning) {
3351 // Cancel auto focus.
3352 {
3353 if (mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS)) {
3354 cancelAutoFocusInternal();
3355 }
3356 }
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003357
Kiran Kumar H N215cac42009-12-08 01:53:46 -08003358 Mutex::Autolock l(&mCamframeTimeoutLock);
Srinivasan Kannan74712c92010-04-07 13:36:48 -07003359 {
3360 Mutex::Autolock cameraRunningLock(&mCameraRunningLock);
3361 if(!camframe_timeout_flag) {
3362 if (( mCurrentTarget != TARGET_MSM7630 ) &&
Nishant Pandit3c278cd2010-07-13 15:56:04 +05303363 (mCurrentTarget != TARGET_QSD8250) && (mCurrentTarget != TARGET_MSM8660))
Srinivasan Kannan74712c92010-04-07 13:36:48 -07003364 mCameraRunning = !native_stop_preview(mCameraControlFd);
3365 else
3366 mCameraRunning = !native_stop_video(mCameraControlFd);
3367 } else {
3368 /* This means that the camframetimeout was issued.
3369 * But we did not issue native_stop_preview(), so we
3370 * need to update mCameraRunning to indicate that
3371 * Camera is no longer running. */
3372 mCameraRunning = 0;
3373 }
3374 }
Sravankb4f5f1c2010-01-21 11:06:17 +05303375
Kiran Kumar H Nac2f4952009-12-17 01:16:53 -08003376 if (!mCameraRunning && mPreviewInitialized) {
3377 deinitPreview();
Nishant Pandit3c278cd2010-07-13 15:56:04 +05303378 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250) || (mCurrentTarget == TARGET_MSM8660)) {
Mohan Kandra156d0ac2010-01-25 16:59:17 -08003379 mVideoThreadWaitLock.lock();
3380 LOGV("in stopPreviewInternal: making mVideoThreadExit 1");
3381 mVideoThreadExit = 1;
3382 mVideoThreadWaitLock.unlock();
3383 // 720p : signal the video thread , and check in video thread if stop is called, if so exit video thread.
3384 pthread_mutex_lock(&(g_busy_frame_queue.mut));
3385 pthread_cond_signal(&(g_busy_frame_queue.wait));
3386 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
Mohan Kandra1ade9a82010-03-02 10:11:26 -08003387 /* Flush the Busy Q */
3388 cam_frame_flush_video();
3389 /* Flush the Free Q */
3390 LINK_cam_frame_flush_free_video();
Mohan Kandra156d0ac2010-01-25 16:59:17 -08003391 }
Kiran Kumar H N215cac42009-12-08 01:53:46 -08003392 mPreviewInitialized = false;
3393 }
Kiran Kumar H Nac2f4952009-12-17 01:16:53 -08003394 else LOGE("stopPreviewInternal: failed to stop preview");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003395 }
Mohan Kandra0d115d12010-08-19 11:47:15 -07003396 LOGI("stopPreviewInternal X: %d", mCameraRunning);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003397}
3398
3399void QualcommCameraHardware::stopPreview()
3400{
3401 LOGV("stopPreview: E");
3402 Mutex::Autolock l(&mLock);
3403 {
3404 if (mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME))
3405 return;
3406 }
3407 stopPreviewInternal();
3408 LOGV("stopPreview: X");
3409}
3410
3411void QualcommCameraHardware::runAutoFocus()
3412{
3413 bool status = true;
3414 void *libhandle = NULL;
Srinivasan Kannan71229622009-12-04 12:05:58 -08003415 isp3a_af_mode_t afMode;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003416
3417 mAutoFocusThreadLock.lock();
3418 // Skip autofocus if focus mode is infinity.
Srinivasan Kannan74712c92010-04-07 13:36:48 -07003419 if ((mParameters.get(CameraParameters::KEY_FOCUS_MODE) == 0)
3420 || (strcmp(mParameters.get(CameraParameters::KEY_FOCUS_MODE),
3421 CameraParameters::FOCUS_MODE_INFINITY) == 0)) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003422 goto done;
3423 }
3424
3425 mAutoFocusFd = open(MSM_CAMERA_CONTROL, O_RDWR);
3426 if (mAutoFocusFd < 0) {
3427 LOGE("autofocus: cannot open %s: %s",
3428 MSM_CAMERA_CONTROL,
3429 strerror(errno));
3430 mAutoFocusThreadRunning = false;
3431 mAutoFocusThreadLock.unlock();
3432 return;
3433 }
3434
3435#if DLOPEN_LIBMMCAMERA
3436 // We need to maintain a reference to libqcamera.so for the duration of the
3437 // AF thread, because we do not know when it will exit relative to the
3438 // lifetime of this object. We do not want to dlclose() libqcamera while
3439 // LINK_cam_frame is still running.
3440 libhandle = ::dlopen("liboemcamera.so", RTLD_NOW);
3441 LOGV("AF: loading libqcamera at %p", libhandle);
3442 if (!libhandle) {
3443 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
3444 close(mAutoFocusFd);
3445 mAutoFocusFd = -1;
3446 mAutoFocusThreadRunning = false;
3447 mAutoFocusThreadLock.unlock();
3448 return;
3449 }
3450#endif
3451
Srinivasan Kannan71229622009-12-04 12:05:58 -08003452 afMode = (isp3a_af_mode_t)attr_lookup(focus_modes,
3453 sizeof(focus_modes) / sizeof(str_map),
3454 mParameters.get(CameraParameters::KEY_FOCUS_MODE));
3455
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003456 /* This will block until either AF completes or is cancelled. */
Srinivasan Kannan71229622009-12-04 12:05:58 -08003457 LOGV("af start (fd %d mode %d)", mAutoFocusFd, afMode);
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08003458 status_t err;
3459 err = mAfLock.tryLock();
3460 if(err == NO_ERROR) {
Srinivasan Kannan74712c92010-04-07 13:36:48 -07003461 {
3462 Mutex::Autolock cameraRunningLock(&mCameraRunningLock);
3463 if(mCameraRunning){
3464 LOGV("Start AF");
3465 status = native_set_afmode(mAutoFocusFd, afMode);
3466 }else{
3467 LOGV("As Camera preview is not running, AF not issued");
3468 status = false;
3469 }
3470 }
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08003471 mAfLock.unlock();
3472 }
3473 else{
3474 //AF Cancel would have acquired the lock,
3475 //so, no need to perform any AF
Srinivasan Kannan99e82422010-02-28 15:32:16 -08003476 LOGV("As Cancel auto focus is in progress, auto focus request "
3477 "is ignored");
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08003478 status = FALSE;
3479 }
3480
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003481 LOGV("af done: %d", (int)status);
3482 close(mAutoFocusFd);
3483 mAutoFocusFd = -1;
3484
3485done:
3486 mAutoFocusThreadRunning = false;
3487 mAutoFocusThreadLock.unlock();
3488
3489 mCallbackLock.lock();
3490 bool autoFocusEnabled = mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS);
3491 notify_callback cb = mNotifyCallback;
3492 void *data = mCallbackCookie;
3493 mCallbackLock.unlock();
3494 if (autoFocusEnabled)
3495 cb(CAMERA_MSG_FOCUS, status, 0, data);
3496
3497#if DLOPEN_LIBMMCAMERA
3498 if (libhandle) {
3499 ::dlclose(libhandle);
3500 LOGV("AF: dlclose(libqcamera)");
3501 }
3502#endif
3503}
3504
3505status_t QualcommCameraHardware::cancelAutoFocusInternal()
3506{
3507 LOGV("cancelAutoFocusInternal E");
3508
Srinivasan Kannan71229622009-12-04 12:05:58 -08003509 if(!sensorType->hasAutoFocusSupport){
3510 LOGV("cancelAutoFocusInternal X");
3511 return NO_ERROR;
3512 }
3513
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003514#if 0
3515 if (mAutoFocusFd < 0) {
3516 LOGV("cancelAutoFocusInternal X: not in progress");
3517 return NO_ERROR;
3518 }
3519#endif
3520
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08003521 status_t rc = NO_ERROR;
3522 status_t err;
3523 err = mAfLock.tryLock();
3524 if(err == NO_ERROR) {
3525 //Got Lock, means either AF hasn't started or
3526 // AF is done. So no need to cancel it, just change the state
Srinivasan Kannan99e82422010-02-28 15:32:16 -08003527 LOGV("As Auto Focus is not in progress, Cancel Auto Focus "
3528 "is ignored");
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08003529 mAfLock.unlock();
3530 }
3531 else {
3532 //AF is in Progess, So cancel it
3533 LOGV("Lock busy...cancel AF");
3534 rc = native_cancel_afmode(mCameraControlFd, mAutoFocusFd) ?
3535 NO_ERROR :
3536 UNKNOWN_ERROR;
3537 }
3538
3539
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003540
3541 LOGV("cancelAutoFocusInternal X: %d", rc);
3542 return rc;
3543}
3544
3545void *auto_focus_thread(void *user)
3546{
3547 LOGV("auto_focus_thread E");
3548 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
3549 if (obj != 0) {
3550 obj->runAutoFocus();
3551 }
3552 else LOGW("not starting autofocus: the object went away!");
3553 LOGV("auto_focus_thread X");
3554 return NULL;
3555}
3556
3557status_t QualcommCameraHardware::autoFocus()
3558{
3559 LOGV("autoFocus E");
3560 Mutex::Autolock l(&mLock);
3561
Srinivasan Kannan71229622009-12-04 12:05:58 -08003562 if(!sensorType->hasAutoFocusSupport){
Srinivasan Kannandf085222009-12-09 18:31:00 -08003563 bool status = false;
3564 mCallbackLock.lock();
3565 bool autoFocusEnabled = mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS);
3566 notify_callback cb = mNotifyCallback;
3567 void *data = mCallbackCookie;
3568 mCallbackLock.unlock();
3569 if (autoFocusEnabled)
3570 cb(CAMERA_MSG_FOCUS, status, 0, data);
Srinivasan Kannan71229622009-12-04 12:05:58 -08003571 LOGV("autoFocus X");
3572 return NO_ERROR;
3573 }
3574
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003575 if (mCameraControlFd < 0) {
3576 LOGE("not starting autofocus: main control fd %d", mCameraControlFd);
3577 return UNKNOWN_ERROR;
3578 }
3579
3580 {
3581 mAutoFocusThreadLock.lock();
3582 if (!mAutoFocusThreadRunning) {
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08003583 if (native_prepare_snapshot(mCameraControlFd) == FALSE) {
3584 LOGE("native_prepare_snapshot failed!\n");
3585 mAutoFocusThreadLock.unlock();
3586 return UNKNOWN_ERROR;
Deepak Kurienbf83f8e2010-09-30 10:29:26 -07003587 } else {
3588 mSnapshotPrepare = TRUE;
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08003589 }
3590
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003591 // Create a detached thread here so that we don't have to wait
3592 // for it when we cancel AF.
3593 pthread_t thr;
3594 pthread_attr_t attr;
3595 pthread_attr_init(&attr);
3596 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
3597 mAutoFocusThreadRunning =
3598 !pthread_create(&thr, &attr,
3599 auto_focus_thread, NULL);
3600 if (!mAutoFocusThreadRunning) {
3601 LOGE("failed to start autofocus thread");
3602 mAutoFocusThreadLock.unlock();
3603 return UNKNOWN_ERROR;
3604 }
3605 }
3606 mAutoFocusThreadLock.unlock();
3607 }
3608
3609 LOGV("autoFocus X");
3610 return NO_ERROR;
3611}
3612
3613status_t QualcommCameraHardware::cancelAutoFocus()
3614{
3615 LOGV("cancelAutoFocus E");
3616 Mutex::Autolock l(&mLock);
3617
3618 int rc = NO_ERROR;
3619 if (mCameraRunning && mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS)) {
3620 rc = cancelAutoFocusInternal();
3621 }
3622
3623 LOGV("cancelAutoFocus X");
3624 return rc;
3625}
3626
3627void QualcommCameraHardware::runSnapshotThread(void *data)
3628{
3629 LOGV("runSnapshotThread E");
Deepak Kurien74b2cca2010-07-28 16:32:55 -07003630#if DLOPEN_LIBMMCAMERA
3631 // We need to maintain a reference to libqcamera.so for the duration of the
3632 // Snapshot thread, because we do not know when it will exit relative to the
3633 // lifetime of this object. We do not want to dlclose() libqcamera while
3634 // LINK_cam_frame is still running.
3635 void *libhandle = ::dlopen("liboemcamera.so", RTLD_NOW);
3636 LOGV("SNAPSHOT: loading libqcamera at %p", libhandle);
3637 if (!libhandle) {
3638 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
3639 }
3640#endif
3641
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08003642 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
3643 if (native_start_snapshot(mCameraControlFd))
3644 receiveRawPicture();
3645 else
3646 LOGE("main: native_start_snapshot failed!");
3647 } else if(mSnapshotFormat == PICTURE_FORMAT_RAW){
3648 if(native_start_raw_snapshot(mCameraControlFd)){
3649 receiveRawSnapshot();
3650 } else {
3651 LOGE("main: native_start_raw_snapshot failed!");
3652 }
3653 }
Mohan Kandraca2e7a92010-06-21 15:48:45 -07003654 mInSnapshotModeWaitLock.lock();
3655 mInSnapshotMode = false;
3656 mInSnapshotModeWait.signal();
3657 mInSnapshotModeWaitLock.unlock();
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08003658
3659 mSnapshotFormat = 0;
Mohan Kandra1659b0c2010-07-18 16:36:25 -07003660 if(mPreviewFormat != CAMERA_YUV_420_NV21_ADRENO ) {
3661 mJpegThreadWaitLock.lock();
3662 while (mJpegThreadRunning) {
3663 LOGV("runSnapshotThread: waiting for jpeg thread to complete.");
3664 mJpegThreadWait.wait(mJpegThreadWaitLock);
3665 LOGV("runSnapshotThread: jpeg thread completed.");
3666 }
3667 mJpegThreadWaitLock.unlock();
3668 //clear the resources
Deepak Kurien74b2cca2010-07-28 16:32:55 -07003669#if DLOPEN_LIBMMCAMERA
Mohan Kandra1659b0c2010-07-18 16:36:25 -07003670 if(libhandle)
Deepak Kurien74b2cca2010-07-28 16:32:55 -07003671#endif
Mohan Kandra1659b0c2010-07-18 16:36:25 -07003672 {
3673 LINK_jpeg_encoder_join();
3674 }
3675 deinitRaw();
Deepak Kurien74b2cca2010-07-28 16:32:55 -07003676 }
Mohan Kandraca2e7a92010-06-21 15:48:45 -07003677
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003678 mSnapshotThreadWaitLock.lock();
3679 mSnapshotThreadRunning = false;
3680 mSnapshotThreadWait.signal();
3681 mSnapshotThreadWaitLock.unlock();
Deepak Kurien74b2cca2010-07-28 16:32:55 -07003682#if DLOPEN_LIBMMCAMERA
3683 if (libhandle) {
3684 ::dlclose(libhandle);
3685 LOGV("SNAPSHOT: dlclose(libqcamera)");
3686 }
3687#endif
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003688
3689 LOGV("runSnapshotThread X");
3690}
3691
3692void *snapshot_thread(void *user)
3693{
3694 LOGD("snapshot_thread E");
3695 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
3696 if (obj != 0) {
3697 obj->runSnapshotThread(user);
3698 }
3699 else LOGW("not starting snapshot thread: the object went away!");
3700 LOGD("snapshot_thread X");
3701 return NULL;
3702}
3703
3704status_t QualcommCameraHardware::takePicture()
3705{
3706 LOGV("takePicture(%d)", mMsgEnabled);
3707 Mutex::Autolock l(&mLock);
3708
Mohan Kandra1659b0c2010-07-18 16:36:25 -07003709 if(mPreviewFormat == CAMERA_YUV_420_NV21_ADRENO){
3710 mEncodePendingWaitLock.lock();
3711 while(mEncodePending) {
3712 LOGE("takePicture: Frame given to application, waiting for encode call");
3713 mEncodePendingWait.wait(mEncodePendingWaitLock);
3714 LOGE("takePicture: Encode of the application data is done");
3715 }
3716 mEncodePendingWaitLock.unlock();
3717 }
3718
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003719 // Wait for old snapshot thread to complete.
3720 mSnapshotThreadWaitLock.lock();
3721 while (mSnapshotThreadRunning) {
3722 LOGV("takePicture: waiting for old snapshot thread to complete.");
3723 mSnapshotThreadWait.wait(mSnapshotThreadWaitLock);
3724 LOGV("takePicture: old snapshot thread completed.");
3725 }
3726
Mohan Kandra5e4f9d92010-08-26 18:23:50 -07003727 if(mCurrentTarget == TARGET_MSM7627) {
3728 /* Store the last frame queued for preview. This
3729 * shall be used as postview */
3730 storePreviewFrameForPostview();
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003731 }
3732
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08003733 //mSnapshotFormat is protected by mSnapshotThreadWaitLock
3734 if(mParameters.getPictureFormat() != 0 &&
3735 !strcmp(mParameters.getPictureFormat(),
3736 CameraParameters::PIXEL_FORMAT_RAW))
3737 mSnapshotFormat = PICTURE_FORMAT_RAW;
3738 else
3739 mSnapshotFormat = PICTURE_FORMAT_JPEG;
3740
3741 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
Deepak Kurienbf83f8e2010-09-30 10:29:26 -07003742 if(!mSnapshotPrepare){
3743 if(!native_prepare_snapshot(mCameraControlFd)) {
3744 mSnapshotThreadWaitLock.unlock();
3745 return UNKNOWN_ERROR;
3746 }
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08003747 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003748 }
Deepak Kurienbf83f8e2010-09-30 10:29:26 -07003749 mSnapshotPrepare = FALSE;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003750 stopPreviewInternal();
3751
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08003752 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
3753 if (!initRaw(mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE))) {
3754 LOGE("initRaw failed. Not taking picture.");
3755 mSnapshotThreadWaitLock.unlock();
3756 return UNKNOWN_ERROR;
3757 }
3758 } else if(mSnapshotFormat == PICTURE_FORMAT_RAW ){
3759 if(!initRawSnapshot()){
3760 LOGE("initRawSnapshot failed. Not taking picture.");
3761 mSnapshotThreadWaitLock.unlock();
3762 return UNKNOWN_ERROR;
3763 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003764 }
3765
3766 mShutterLock.lock();
3767 mShutterPending = true;
3768 mShutterLock.unlock();
3769
3770 pthread_attr_t attr;
3771 pthread_attr_init(&attr);
3772 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
3773 mSnapshotThreadRunning = !pthread_create(&mSnapshotThread,
3774 &attr,
3775 snapshot_thread,
3776 NULL);
3777 mSnapshotThreadWaitLock.unlock();
3778
Mohan Kandraca2e7a92010-06-21 15:48:45 -07003779 mInSnapshotModeWaitLock.lock();
3780 mInSnapshotMode = true;
3781 mInSnapshotModeWaitLock.unlock();
3782
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003783 LOGV("takePicture: X");
3784 return mSnapshotThreadRunning ? NO_ERROR : UNKNOWN_ERROR;
3785}
3786
Vamshidhar Kondra92ce9142010-09-03 18:22:08 +05303787void QualcommCameraHardware::set_liveshot_exifinfo()
3788{
3789 setGpsParameters();
3790 //set TimeStamp
3791 const char *str = mParameters.get(CameraParameters::KEY_EXIF_DATETIME);
3792 if(str != NULL) {
3793 strncpy(dateTime, str, 19);
3794 dateTime[19] = '\0';
3795 addExifTag(EXIFTAGID_EXIF_DATE_TIME_ORIGINAL, EXIF_ASCII,
3796 20, 1, (void *)dateTime);
3797 }
3798}
3799
3800status_t QualcommCameraHardware::takeLiveSnapshot()
3801{
3802 LOGV("takeLiveSnapshot: E ");
3803 Mutex::Autolock l(&mLock);
3804
3805 if(liveshot_state == LIVESHOT_IN_PROGRESS || !recordingState) {
3806 return NO_ERROR;
3807 }
3808
3809 if( (mCurrentTarget != TARGET_MSM7630) && (mCurrentTarget != TARGET_MSM8660)) {
3810 LOGI("LiveSnapshot not supported on this target");
3811 liveshot_state = LIVESHOT_STOPPED;
3812 return NO_ERROR;
3813 }
3814
3815 liveshot_state = LIVESHOT_IN_PROGRESS;
3816
3817 if (!initLiveSnapshot(videoWidth, videoHeight)) {
3818 LOGE("takeLiveSnapshot: Jpeg Heap Memory allocation failed. Not taking Live Snapshot.");
3819 liveshot_state = LIVESHOT_STOPPED;
3820 return UNKNOWN_ERROR;
3821 }
3822
3823 uint32_t maxjpegsize = videoWidth * videoHeight *1.5;
3824 set_liveshot_exifinfo();
3825 if(!LINK_set_liveshot_params(videoWidth, videoHeight,
3826 exif_data, exif_table_numEntries,
3827 (uint8_t *)mJpegHeap->mHeap->base(), maxjpegsize)) {
3828 LOGE("Link_set_liveshot_params failed.");
3829 mJpegHeap.clear();
3830 return NO_ERROR;
3831 }
3832
3833 if(!native_start_liveshot(mCameraControlFd)) {
3834 LOGE("native_start_liveshot failed");
3835 liveshot_state = LIVESHOT_STOPPED;
3836 mJpegHeap.clear();
3837 return UNKNOWN_ERROR;
3838 }
3839
3840 LOGV("takeLiveSnapshot: X");
3841 return NO_ERROR;
3842}
3843
3844bool QualcommCameraHardware::initLiveSnapshot(int videowidth, int videoheight)
3845{
3846 LOGV("initLiveSnapshot E");
3847
3848 if (mJpegHeap != NULL) {
3849 LOGV("initLiveSnapshot: clearing old mJpegHeap.");
3850 mJpegHeap.clear();
3851 }
3852
3853 mJpegMaxSize = videowidth * videoheight * 1.5;
3854
3855 LOGV("initLiveSnapshot: initializing mJpegHeap.");
3856 mJpegHeap =
3857 new AshmemPool(mJpegMaxSize,
3858 kJpegBufferCount,
3859 0, // we do not know how big the picture will be
3860 "jpeg");
3861
3862 if (!mJpegHeap->initialized()) {
3863 mJpegHeap.clear();
3864 LOGE("initLiveSnapshot X failed: error initializing mJpegHeap.");
3865 return false;
3866 }
3867
3868 LOGV("initLiveSnapshot X");
3869 return true;
3870}
3871
3872
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003873status_t QualcommCameraHardware::cancelPicture()
3874{
3875 status_t rc;
3876 LOGV("cancelPicture: E");
Apurva Rajguru3da1a702010-07-28 12:32:42 -07003877 if (mCurrentTarget == TARGET_MSM7627) {
3878 mSnapshotDone = TRUE;
3879 mSnapshotThreadWaitLock.lock();
3880 while (mSnapshotThreadRunning) {
3881 LOGV("cancelPicture: waiting for snapshot thread to complete.");
3882 mSnapshotThreadWait.wait(mSnapshotThreadWaitLock);
3883 LOGV("cancelPicture: snapshot thread completed.");
3884 }
3885 mSnapshotThreadWaitLock.unlock();
3886 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003887 rc = native_stop_snapshot(mCameraControlFd) ? NO_ERROR : UNKNOWN_ERROR;
Apurva Rajguru3da1a702010-07-28 12:32:42 -07003888 mSnapshotDone = FALSE;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003889 LOGV("cancelPicture: X: %d", rc);
3890 return rc;
3891}
3892
3893status_t QualcommCameraHardware::setParameters(const CameraParameters& params)
3894{
3895 LOGV("setParameters: E params = %p", &params);
3896
3897 Mutex::Autolock l(&mLock);
3898 status_t rc, final_rc = NO_ERROR;
3899
3900 if ((rc = setPreviewSize(params))) final_rc = rc;
3901 if ((rc = setPictureSize(params))) final_rc = rc;
Srinivasan Kannan264376e2010-08-13 18:54:35 -07003902 if ((rc = setJpegThumbnailSize(params))) final_rc = rc;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003903 if ((rc = setJpegQuality(params))) final_rc = rc;
Vamshidhar Kondrae7b9b5a2010-02-25 15:40:37 +05303904 if ((rc = setEffect(params))) final_rc = rc;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003905 if ((rc = setGpsLocation(params))) final_rc = rc;
3906 if ((rc = setRotation(params))) final_rc = rc;
3907 if ((rc = setZoom(params))) final_rc = rc;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003908 if ((rc = setOrientation(params))) final_rc = rc;
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303909 if ((rc = setLensshadeValue(params))) final_rc = rc;
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08003910 if ((rc = setPictureFormat(params))) final_rc = rc;
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003911 if ((rc = setSharpness(params))) final_rc = rc;
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003912 if ((rc = setSaturation(params))) final_rc = rc;
Apurva Rajguru7b949c92010-05-26 15:46:57 -07003913 if ((rc = setContinuousAf(params))) final_rc = rc;
Apurva Rajgurue5965c42010-09-09 14:24:54 -07003914 if ((rc = setSelectableZoneAf(params))) final_rc = rc;
Apurva Rajguru0a2cb922010-06-08 15:33:22 -07003915 if ((rc = setTouchAfAec(params))) final_rc = rc;
Apurva Rajgurua5e7a6e2010-08-10 19:22:44 -07003916 if ((rc = setSceneMode(params))) final_rc = rc;
Apurva Rajguru08383852010-05-17 14:25:39 -07003917 if ((rc = setContrast(params))) final_rc = rc;
Mohan Kandra091d5ab2010-07-14 16:53:25 -07003918 if ((rc = setRecordSize(params))) final_rc = rc;
Apurva Rajguru8e0a8da2010-06-02 11:26:36 -07003919 if ((rc = setSceneDetect(params))) final_rc = rc;
Mohan Kandra7110c242010-07-18 15:34:48 -07003920 if ((rc = setStrTextures(params))) final_rc = rc;
3921 if ((rc = setPreviewFormat(params))) final_rc = rc;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003922
Apurva Rajgurua5e7a6e2010-08-10 19:22:44 -07003923 const char *str = params.get(CameraParameters::KEY_SCENE_MODE);
3924 int32_t value = attr_lookup(scenemode, sizeof(scenemode) / sizeof(str_map), str);
3925
3926 if((value != NOT_FOUND) && (value == CAMERA_BESTSHOT_OFF)) {
3927 if ((rc = setPreviewFrameRate(params))) final_rc = rc;
3928 if ((rc = setPreviewFrameRateMode(params))) final_rc = rc;
3929 if ((rc = setAntibanding(params))) final_rc = rc;
3930 if ((rc = setAutoExposure(params))) final_rc = rc;
3931 if ((rc = setExposureCompensation(params))) final_rc = rc;
3932 if ((rc = setWhiteBalance(params))) final_rc = rc;
3933 if ((rc = setFlash(params))) final_rc = rc;
3934 if ((rc = setFocusMode(params))) final_rc = rc;
3935 if ((rc = setBrightness(params))) final_rc = rc;
3936 if ((rc = setISOValue(params))) final_rc = rc;
3937 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003938 LOGV("setParameters: X");
3939 return final_rc;
3940}
3941
3942CameraParameters QualcommCameraHardware::getParameters() const
3943{
3944 LOGV("getParameters: EX");
3945 return mParameters;
3946}
Nishant Pandit741742b2010-09-21 03:24:20 +05303947status_t QualcommCameraHardware::setHistogramOn()
3948{
3949 LOGV("setHistogramOn: EX");
3950
3951 mStatsWaitLock.lock();
3952 mSendData = true;
3953 if(mStatsOn == CAMERA_HISTOGRAM_ENABLE) {
3954 mStatsWaitLock.unlock();
3955 return NO_ERROR;
3956 }
3957
3958 if (mStatHeap != NULL) {
3959 LOGV("setHistogram on: clearing old mStatHeap.");
3960 mStatHeap.clear();
3961 }
3962
3963 mStatSize = sizeof(uint32_t)* HISTOGRAM_STATS_SIZE;
3964 mCurrent = -1;
3965 /*Currently the Ashmem is multiplying the buffer size with total number
3966 of buffers and page aligning. This causes a crash in JNI as each buffer
3967 individually expected to be page aligned */
3968 int page_size_minus_1 = getpagesize() - 1;
3969 int32_t mAlignedStatSize = ((mStatSize + page_size_minus_1) & (~page_size_minus_1));
3970
3971 mStatHeap =
3972 new AshmemPool(mAlignedStatSize,
3973 3,
3974 mStatSize,
3975 "stat");
3976 if (!mStatHeap->initialized()) {
3977 LOGE("Stat Heap X failed ");
3978 mStatHeap.clear();
3979 LOGE("setHistogramOn X: error initializing mStatHeap");
3980 mStatsWaitLock.unlock();
3981 return UNKNOWN_ERROR;
3982 }
3983 mStatsOn = CAMERA_HISTOGRAM_ENABLE;
3984
3985 mStatsWaitLock.unlock();
3986 mCfgControl.mm_camera_set_parm(CAMERA_PARM_HISTOGRAM, &mStatsOn);
3987 return NO_ERROR;
3988
3989}
3990
3991status_t QualcommCameraHardware::setHistogramOff()
3992{
3993 LOGV("setHistogramOff: EX");
3994 mStatsWaitLock.lock();
3995 if(mStatsOn == CAMERA_HISTOGRAM_DISABLE) {
3996 mStatsWaitLock.unlock();
3997 return NO_ERROR;
3998 }
3999 mStatsOn = CAMERA_HISTOGRAM_DISABLE;
4000 mStatsWaitLock.unlock();
4001
4002 mCfgControl.mm_camera_set_parm(CAMERA_PARM_HISTOGRAM, &mStatsOn);
4003
4004 mStatsWaitLock.lock();
4005 mStatHeap.clear();
4006 mStatsWaitLock.unlock();
4007
4008 return NO_ERROR;
4009}
4010
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004011
4012status_t QualcommCameraHardware::sendCommand(int32_t command, int32_t arg1,
4013 int32_t arg2)
4014{
4015 LOGV("sendCommand: EX");
Nishant Pandit741742b2010-09-21 03:24:20 +05304016 Mutex::Autolock l(&mLock);
4017
4018 switch(command) {
4019
4020 case CAMERA_CMD_HISTOGRAM_ON:
4021 LOGV("histogram set to on");
4022 return setHistogramOn();
4023 case CAMERA_CMD_HISTOGRAM_OFF:
4024 LOGV("histogram set to off");
4025 return setHistogramOff();
4026 case CAMERA_CMD_HISTOGRAM_SEND_DATA:
4027 mStatsWaitLock.lock();
4028 if(mStatsOn == CAMERA_HISTOGRAM_ENABLE)
4029 mSendData = true;
4030 mStatsWaitLock.unlock();
4031 return NO_ERROR;
4032 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004033 return BAD_VALUE;
4034}
4035
4036extern "C" sp<CameraHardwareInterface> openCameraHardware()
4037{
Mohan Kandra0d115d12010-08-19 11:47:15 -07004038 LOGI("openCameraHardware: call createInstance");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004039 return QualcommCameraHardware::createInstance();
4040}
4041
4042wp<QualcommCameraHardware> QualcommCameraHardware::singleton;
4043
4044// If the hardware already exists, return a strong pointer to the current
4045// object. If not, create a new hardware object, put it in the singleton,
4046// and return it.
4047sp<CameraHardwareInterface> QualcommCameraHardware::createInstance()
4048{
Mohan Kandra0d115d12010-08-19 11:47:15 -07004049 LOGI("createInstance: E");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004050
Priyanka Kharatf2deffb2010-05-17 18:11:31 -07004051 singleton_lock.lock();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004052
4053 // Wait until the previous release is done.
4054 while (singleton_releasing) {
Srinivasan Kannan78444e42010-06-10 15:39:29 -07004055 if((singleton_releasing_start_time != 0) &&
4056 (systemTime() - singleton_releasing_start_time) > SINGLETON_RELEASING_WAIT_TIME){
4057 LOGV("in createinstance system time is %lld %lld %lld ",
4058 systemTime(), singleton_releasing_start_time, SINGLETON_RELEASING_WAIT_TIME);
4059 singleton_lock.unlock();
4060 LOGE("Previous singleton is busy and time out exceeded. Returning null");
4061 return NULL;
4062 }
4063 LOGI("Wait for previous release.");
4064 singleton_wait.waitRelative(singleton_lock, SINGLETON_RELEASING_RECHECK_TIMEOUT);
4065 LOGI("out of Wait for previous release.");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004066 }
4067
4068 if (singleton != 0) {
4069 sp<CameraHardwareInterface> hardware = singleton.promote();
4070 if (hardware != 0) {
4071 LOGD("createInstance: X return existing hardware=%p", &(*hardware));
Priyanka Kharatf2deffb2010-05-17 18:11:31 -07004072 singleton_lock.unlock();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004073 return hardware;
4074 }
4075 }
4076
4077 {
4078 struct stat st;
4079 int rc = stat("/dev/oncrpc", &st);
4080 if (rc < 0) {
4081 LOGD("createInstance: X failed to create hardware: %s", strerror(errno));
Priyanka Kharatf2deffb2010-05-17 18:11:31 -07004082 singleton_lock.unlock();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004083 return NULL;
4084 }
4085 }
4086
4087 QualcommCameraHardware *cam = new QualcommCameraHardware();
4088 sp<QualcommCameraHardware> hardware(cam);
4089 singleton = hardware;
4090
Mohan Kandra0d115d12010-08-19 11:47:15 -07004091 LOGI("createInstance: created hardware=%p", &(*hardware));
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004092 if (!cam->startCamera()) {
4093 LOGE("%s: startCamera failed!", __FUNCTION__);
Priyanka Kharatf2deffb2010-05-17 18:11:31 -07004094 singleton_lock.unlock();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004095 return NULL;
4096 }
4097
4098 cam->initDefaultParameters();
Priyanka Kharatf2deffb2010-05-17 18:11:31 -07004099 singleton_lock.unlock();
Mohan Kandra0d115d12010-08-19 11:47:15 -07004100 LOGI("createInstance: X");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004101 return hardware;
4102}
4103
4104// For internal use only, hence the strong pointer to the derived type.
4105sp<QualcommCameraHardware> QualcommCameraHardware::getInstance()
4106{
4107 sp<CameraHardwareInterface> hardware = singleton.promote();
4108 if (hardware != 0) {
4109 // LOGV("getInstance: X old instance of hardware");
4110 return sp<QualcommCameraHardware>(static_cast<QualcommCameraHardware*>(hardware.get()));
4111 } else {
4112 LOGV("getInstance: X new instance of hardware");
4113 return sp<QualcommCameraHardware>();
4114 }
4115}
Sravankb4f5f1c2010-01-21 11:06:17 +05304116void QualcommCameraHardware::receiveRecordingFrame(struct msm_frame *frame)
4117{
4118 LOGV("receiveRecordingFrame E");
4119 // post busy frame
4120 if (frame)
4121 {
4122 cam_frame_post_video (frame);
4123 }
4124 else LOGE("in receiveRecordingFrame frame is NULL");
4125 LOGV("receiveRecordingFrame X");
4126}
4127
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004128
Mohan Kandrad9efed92010-01-15 19:08:39 -08004129bool QualcommCameraHardware::native_zoom_image(int fd, int srcOffset, int dstOffSet, common_crop_t *crop)
Mohan Kandra284966d2010-01-05 13:39:15 -08004130{
4131 int result = 0;
4132 struct mdp_blit_req *e;
4133 struct timeval td1, td2;
4134
Mohan Kandra284966d2010-01-05 13:39:15 -08004135 /* Initialize yuv structure */
4136 zoomImage.list.count = 1;
4137
4138 e = &zoomImage.list.req[0];
4139
4140 e->src.width = previewWidth;
4141 e->src.height = previewHeight;
4142 e->src.format = MDP_Y_CBCR_H2V2;
Mohan Kandrad9efed92010-01-15 19:08:39 -08004143 e->src.offset = srcOffset;
4144 e->src.memory_id = fd;
Mohan Kandra284966d2010-01-05 13:39:15 -08004145
4146 e->dst.width = previewWidth;
4147 e->dst.height = previewHeight;
4148 e->dst.format = MDP_Y_CBCR_H2V2;
Mohan Kandrad9efed92010-01-15 19:08:39 -08004149 e->dst.offset = dstOffSet;
4150 e->dst.memory_id = fd;
Mohan Kandra284966d2010-01-05 13:39:15 -08004151
4152 e->transp_mask = 0xffffffff;
4153 e->flags = 0;
4154 e->alpha = 0xff;
Apurva Rajguru4ffd6cb2010-08-30 18:57:41 -07004155 if (crop->in1_w != 0 && crop->in1_h != 0) {
Mohan Kandra39fad8d2010-07-15 12:29:19 -07004156 e->src_rect.x = (crop->out1_w - crop->in1_w + 1) / 2 - 1;
4157 e->src_rect.y = (crop->out1_h - crop->in1_h + 1) / 2 - 1;
4158 e->src_rect.w = crop->in1_w;
4159 e->src_rect.h = crop->in1_h;
Mohan Kandra284966d2010-01-05 13:39:15 -08004160 } else {
4161 e->src_rect.x = 0;
4162 e->src_rect.y = 0;
4163 e->src_rect.w = previewWidth;
4164 e->src_rect.h = previewHeight;
4165 }
Mohan Kandrad9efed92010-01-15 19:08:39 -08004166 //LOGV(" native_zoom : SRC_RECT : x,y = %d,%d \t w,h = %d, %d",
4167 // e->src_rect.x, e->src_rect.y, e->src_rect.w, e->src_rect.h);
Mohan Kandra284966d2010-01-05 13:39:15 -08004168
4169 e->dst_rect.x = 0;
4170 e->dst_rect.y = 0;
4171 e->dst_rect.w = previewWidth;
4172 e->dst_rect.h = previewHeight;
4173
4174 result = ioctl(fb_fd, MSMFB_BLIT, &zoomImage.list);
4175 if (result < 0) {
4176 LOGE("MSM_FBIOBLT failed! line=%d\n", __LINE__);
4177 return FALSE;
4178 }
4179 return TRUE;
4180}
4181
Mohan Kandrabad0eaa2010-02-04 15:11:54 -08004182void QualcommCameraHardware::debugShowPreviewFPS() const
Mohan Kandra740cfce2010-01-07 12:58:24 -08004183{
4184 static int mFrameCount;
4185 static int mLastFrameCount = 0;
4186 static nsecs_t mLastFpsTime = 0;
4187 static float mFps = 0;
4188 mFrameCount++;
4189 nsecs_t now = systemTime();
4190 nsecs_t diff = now - mLastFpsTime;
4191 if (diff > ms2ns(250)) {
4192 mFps = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
Mohan Kandrabad0eaa2010-02-04 15:11:54 -08004193 LOGI("Preview Frames Per Second: %.4f", mFps);
Mohan Kandra740cfce2010-01-07 12:58:24 -08004194 mLastFpsTime = now;
4195 mLastFrameCount = mFrameCount;
4196 }
4197}
4198
Mohan Kandrabad0eaa2010-02-04 15:11:54 -08004199void QualcommCameraHardware::debugShowVideoFPS() const
4200{
4201 static int mFrameCount;
4202 static int mLastFrameCount = 0;
4203 static nsecs_t mLastFpsTime = 0;
4204 static float mFps = 0;
4205 mFrameCount++;
4206 nsecs_t now = systemTime();
4207 nsecs_t diff = now - mLastFpsTime;
4208 if (diff > ms2ns(250)) {
4209 mFps = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
4210 LOGI("Video Frames Per Second: %.4f", mFps);
4211 mLastFpsTime = now;
4212 mLastFrameCount = mFrameCount;
4213 }
4214}
Vamshidhar Kondra92ce9142010-09-03 18:22:08 +05304215
4216void QualcommCameraHardware::receiveLiveSnapshot(uint32_t jpeg_size)
4217{
4218 LOGV("receiveLiveSnapshot E");
4219
4220#ifdef DUMP_LIVESHOT_JPEG_FILE
4221 int file_fd = open("/data/LiveSnapshot.jpg", O_RDWR | O_CREAT, 0777);
4222 LOGV("dumping live shot image in /data/LiveSnapshot.jpg");
4223 if (file_fd < 0) {
4224 LOGE("cannot open file\n");
4225 }
4226 else
4227 {
4228 write(file_fd, (uint8_t *)mJpegHeap->mHeap->base(),jpeg_size);
4229 }
4230 close(file_fd);
4231#endif
4232
4233 Mutex::Autolock cbLock(&mCallbackLock);
4234 if (mDataCallback && (mMsgEnabled & MEDIA_RECORDER_MSG_COMPRESSED_IMAGE)) {
4235 sp<MemoryBase> buffer = new
4236 MemoryBase(mJpegHeap->mHeap,
4237 0,
4238 jpeg_size);
4239 mDataCallback(MEDIA_RECORDER_MSG_COMPRESSED_IMAGE, buffer, mCallbackCookie);
4240 buffer = NULL;
4241 }
4242 else LOGV("JPEG callback was cancelled--not delivering image.");
4243
4244 //Reset the Gps Information & relieve memory
4245 exif_table_numEntries = 0;
4246 mJpegHeap.clear();
4247
4248 liveshot_state = LIVESHOT_DONE;
4249
4250 LOGV("receiveLiveSnapshot X");
4251}
4252
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004253void QualcommCameraHardware::receivePreviewFrame(struct msm_frame *frame)
4254{
4255// LOGV("receivePreviewFrame E");
4256
4257 if (!mCameraRunning) {
4258 LOGE("ignoring preview callback--camera has been stopped");
4259 return;
4260 }
4261
Mohan Kandra740cfce2010-01-07 12:58:24 -08004262 if (UNLIKELY(mDebugFps)) {
Mohan Kandrabad0eaa2010-02-04 15:11:54 -08004263 debugShowPreviewFPS();
Mohan Kandra740cfce2010-01-07 12:58:24 -08004264 }
4265
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004266 mCallbackLock.lock();
4267 int msgEnabled = mMsgEnabled;
4268 data_callback pcb = mDataCallback;
4269 void *pdata = mCallbackCookie;
4270 data_callback_timestamp rcb = mDataCallbackTimestamp;
4271 void *rdata = mCallbackCookie;
4272 mCallbackLock.unlock();
4273
4274 // Find the offset within the heap of the current buffer.
Mohan Kandra284966d2010-01-05 13:39:15 -08004275 ssize_t offset_addr =
Mohan Kandrad9efed92010-01-15 19:08:39 -08004276 (ssize_t)frame->buffer - (ssize_t)mPreviewHeap->mHeap->base();
4277 ssize_t offset = offset_addr / mPreviewHeap->mAlignedBufferSize;
Mohan Kandra284966d2010-01-05 13:39:15 -08004278
4279 common_crop_t *crop = (common_crop_t *) (frame->cropinfo);
Nishant Pandit3c278cd2010-07-13 15:56:04 +05304280#ifdef DUMP_PREVIEW_FRAMES
4281 static int frameCnt = 0;
4282 int written;
4283 if (frameCnt >= 0 && frameCnt <= 10 ) {
4284 char buf[128];
4285 sprintf(buf, "/data/%d_preview.yuv", frameCnt);
4286 int file_fd = open(buf, O_RDWR | O_CREAT, 0777);
4287 LOGV("dumping preview frame %d", frameCnt);
4288 if (file_fd < 0) {
4289 LOGE("cannot open file\n");
4290 }
4291 else
4292 {
4293 LOGV("dumping data");
4294 written = write(file_fd, (uint8_t *)frame->buffer,
4295 mPreviewFrameSize );
4296 if(written < 0)
4297 LOGE("error in data write");
4298 }
4299 close(file_fd);
4300 }
4301 frameCnt++;
4302#endif
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004303 mInPreviewCallback = true;
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08004304 if(mUseOverlay) {
Apurva Rajguru905b8532010-08-02 18:29:38 -07004305 if(mOverlay != NULL) {
4306 mOverlayLock.lock();
Mohan Kandra54e2a022010-07-06 16:23:58 -07004307 mOverlay->setFd(mPreviewHeap->mHeap->getHeapID());
Apurva Rajguru4ffd6cb2010-08-30 18:57:41 -07004308 if (crop->in1_w != 0 && crop->in1_h != 0) {
Mohan Kandra39fad8d2010-07-15 12:29:19 -07004309 zoomCropInfo.x = (crop->out1_w - crop->in1_w + 1) / 2 - 1;
4310 zoomCropInfo.y = (crop->out1_h - crop->in1_h + 1) / 2 - 1;
4311 zoomCropInfo.w = crop->in1_w;
4312 zoomCropInfo.h = crop->in1_h;
Apurva Rajguru905b8532010-08-02 18:29:38 -07004313 mOverlay->setCrop(zoomCropInfo.x, zoomCropInfo.y,
Mohan Kandra39fad8d2010-07-15 12:29:19 -07004314 zoomCropInfo.w, zoomCropInfo.h);
Mohan Kandra9aff1f42010-09-02 19:00:41 -07004315 /* Set mResetOverlayCrop to true, so that when there is
4316 * no crop information, setCrop will be called
4317 * with zero crop values.
4318 */
4319 mResetOverlayCrop = true;
4320
Apurva Rajguru905b8532010-08-02 18:29:38 -07004321 } else {
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08004322 // Reset zoomCropInfo variables. This will ensure that
4323 // stale values wont be used for postview
Mohan Kandra39fad8d2010-07-15 12:29:19 -07004324 zoomCropInfo.w = crop->in1_w;
4325 zoomCropInfo.h = crop->in1_h;
Mohan Kandra9aff1f42010-09-02 19:00:41 -07004326 /* This reset is required, if not, overlay driver continues
4327 * to use the old crop information for these preview
4328 * frames which is not the correct behavior. To avoid
4329 * multiple calls, reset once.
4330 */
4331 if(mResetOverlayCrop == true){
4332 mOverlay->setCrop(0, 0,previewWidth, previewHeight);
4333 mResetOverlayCrop = false;
4334 }
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08004335 }
Apurva Rajguru905b8532010-08-02 18:29:38 -07004336 mOverlay->queueBuffer((void *)offset_addr);
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08004337 mLastQueuedFrame = (void *)frame->buffer;
Apurva Rajguru905b8532010-08-02 18:29:38 -07004338 mOverlayLock.unlock();
4339 }
Mohan Kandra284966d2010-01-05 13:39:15 -08004340 } else {
Apurva Rajguru4ffd6cb2010-08-30 18:57:41 -07004341 if (crop->in1_w != 0 && crop->in1_h != 0) {
Mohan Kandra39fad8d2010-07-15 12:29:19 -07004342 dstOffset = (dstOffset + 1) % NUM_MORE_BUFS;
4343 offset = kPreviewBufferCount + dstOffset;
4344 ssize_t dstOffset_addr = offset * mPreviewHeap->mAlignedBufferSize;
4345 if( !native_zoom_image(mPreviewHeap->mHeap->getHeapID(),
4346 offset_addr, dstOffset_addr, crop)) {
4347 LOGE(" Error while doing MDP zoom ");
Kiran Kumar H N1ece71c2010-03-30 10:31:21 -07004348 offset = offset_addr / mPreviewHeap->mAlignedBufferSize;
Mohan Kandra39fad8d2010-07-15 12:29:19 -07004349 }
Apurva Rajguru905b8532010-08-02 18:29:38 -07004350 }
4351 if (mCurrentTarget == TARGET_MSM7627) {
4352 mLastQueuedFrame = (void *)mPreviewHeap->mBuffers[offset]->pointer();
4353 }
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08004354 }
Mohan Kandrad9efed92010-01-15 19:08:39 -08004355 if (pcb != NULL && (msgEnabled & CAMERA_MSG_PREVIEW_FRAME))
4356 pcb(CAMERA_MSG_PREVIEW_FRAME, mPreviewHeap->mBuffers[offset],
4357 pdata);
4358
Nishant Pandit3c278cd2010-07-13 15:56:04 +05304359 // If output is NOT enabled (targets otherthan 7x30 , 8x50 and 8x60 currently..)
4360 if( (mCurrentTarget != TARGET_MSM7630 ) && (mCurrentTarget != TARGET_QSD8250) && (mCurrentTarget != TARGET_MSM8660)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05304361 if(rcb != NULL && (msgEnabled & CAMERA_MSG_VIDEO_FRAME)) {
4362 rcb(systemTime(), CAMERA_MSG_VIDEO_FRAME, mPreviewHeap->mBuffers[offset], rdata);
4363 Mutex::Autolock rLock(&mRecordFrameLock);
4364 if (mReleasedRecordingFrame != true) {
4365 LOGV("block waiting for frame release");
4366 mRecordWait.wait(mRecordFrameLock);
4367 LOGV("frame released, continuing");
4368 }
4369 mReleasedRecordingFrame = false;
4370 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004371 }
4372 mInPreviewCallback = false;
4373
4374// LOGV("receivePreviewFrame X");
4375}
Nishant Pandit741742b2010-09-21 03:24:20 +05304376void QualcommCameraHardware::receiveCameraStats(camstats_type stype, camera_preview_histogram_info* histinfo)
4377{
4378 // LOGV("receiveCameraStats E");
4379
4380 if (!mCameraRunning) {
4381 LOGE("ignoring stats callback--camera has been stopped");
4382 return;
4383 }
4384
4385 if(mOverlay == NULL) {
4386 return;
4387 }
4388 mCallbackLock.lock();
4389 int msgEnabled = mMsgEnabled;
4390 data_callback scb = mDataCallback;
4391 void *sdata = mCallbackCookie;
4392 mCallbackLock.unlock();
4393 mStatsWaitLock.lock();
4394 if(mStatsOn == CAMERA_HISTOGRAM_DISABLE) {
4395 mStatsWaitLock.unlock();
4396 return;
4397 }
4398 if(!mSendData) {
4399 mStatsWaitLock.unlock();
4400 } else {
4401 mSendData = false;
4402 mCurrent = (mCurrent+1)%3;
4403 // The first element of the array will contain the maximum hist value provided by driver.
4404 *(uint32_t *)(mStatHeap->mHeap->base()+ (mStatHeap->mBufferSize * mCurrent)) = histinfo->max_value;
4405 memcpy((uint32_t *)((unsigned int)mStatHeap->mHeap->base()+ (mStatHeap->mBufferSize * mCurrent)+ sizeof(int32_t)), (uint32_t *)histinfo->buffer,(sizeof(int32_t) * 256));
4406
4407 mStatsWaitLock.unlock();
4408
4409 if (scb != NULL && (msgEnabled & CAMERA_MSG_STATS_DATA))
4410 scb(CAMERA_MSG_STATS_DATA, mStatHeap->mBuffers[mCurrent],
4411 sdata);
4412 }
4413 // LOGV("receiveCameraStats X");
4414}
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004415
Sravankb4f5f1c2010-01-21 11:06:17 +05304416
4417bool QualcommCameraHardware::initRecord()
4418{
Mohan Kandra62429cc2010-07-19 10:21:05 -07004419 const char *pmem_region;
Nishant Panditbde07612010-07-28 00:16:28 +05304420 int CbCrOffset;
Mohan Kandra39fad8d2010-07-15 12:29:19 -07004421 int recordBufferSize;
Apurva Rajguruc73c1722010-04-15 17:39:11 -07004422
Sravankb4f5f1c2010-01-21 11:06:17 +05304423 LOGV("initREcord E");
4424
Vinay Kaliaba3555f2010-07-21 11:37:36 -07004425 if(mCurrentTarget == TARGET_MSM8660)
Apurva Rajguruc73c1722010-04-15 17:39:11 -07004426 pmem_region = "/dev/pmem_smipool";
4427 else
4428 pmem_region = "/dev/pmem_adsp";
4429
Nishant Panditbde07612010-07-28 00:16:28 +05304430 // for 8x60 the Encoder expects the CbCr offset should be aligned to 2K.
4431 if(mCurrentTarget == TARGET_MSM8660) {
4432 CbCrOffset = PAD_TO_2K(mDimension.video_width * mDimension.video_height);
Mohan Kandra39fad8d2010-07-15 12:29:19 -07004433 recordBufferSize = CbCrOffset + PAD_TO_2K((mDimension.video_width * mDimension.video_height)/2);
Nishant Panditbde07612010-07-28 00:16:28 +05304434 } else {
4435 CbCrOffset = PAD_TO_WORD(mDimension.video_width * mDimension.video_height);
Mohan Kandra39fad8d2010-07-15 12:29:19 -07004436 recordBufferSize = (mDimension.video_width * mDimension.video_height *3)/2;
Nishant Panditbde07612010-07-28 00:16:28 +05304437 }
Mohan Kandrafdbc2192010-08-24 20:39:59 -07004438 LOGV("initRecord: mDimension.video_width = %d mDimension.video_height = %d",
4439 mDimension.video_width, mDimension.video_height);
Mohan Kandra39fad8d2010-07-15 12:29:19 -07004440
4441 /* Buffersize and frameSize will be different when DIS is ON.
4442 * We need to pass the actual framesize with video heap, as the same
4443 * is used at camera MIO when negotiating with encoder.
4444 */
4445 mRecordFrameSize = recordBufferSize;
Mohan Kandrafdbc2192010-08-24 20:39:59 -07004446 if(mVpeEnabled && mDisEnabled){
Mohan Kandra39fad8d2010-07-15 12:29:19 -07004447 mRecordFrameSize = videoWidth * videoHeight * 3 / 2;
Mohan Kandrafdbc2192010-08-24 20:39:59 -07004448 if(mCurrentTarget == TARGET_MSM8660){
4449 mRecordFrameSize = PAD_TO_2K(videoWidth * videoHeight)
4450 + PAD_TO_2K((videoWidth * videoHeight)/2);
4451 }
4452 }
4453 LOGV("mRecordFrameSize = %d", mRecordFrameSize);
Mohan Kandra39fad8d2010-07-15 12:29:19 -07004454
Apurva Rajguruc73c1722010-04-15 17:39:11 -07004455 mRecordHeap = new PmemPool(pmem_region,
Sravankb4f5f1c2010-01-21 11:06:17 +05304456 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
4457 mCameraControlFd,
4458 MSM_PMEM_VIDEO,
Mohan Kandra39fad8d2010-07-15 12:29:19 -07004459 recordBufferSize,
Sravankb4f5f1c2010-01-21 11:06:17 +05304460 kRecordBufferCount,
4461 mRecordFrameSize,
Mohan Kandra02486042010-06-18 16:49:43 -07004462 CbCrOffset,
4463 0,
Sravankb4f5f1c2010-01-21 11:06:17 +05304464 "record");
Apurva Rajguruc73c1722010-04-15 17:39:11 -07004465
Sravankb4f5f1c2010-01-21 11:06:17 +05304466 if (!mRecordHeap->initialized()) {
4467 mRecordHeap.clear();
4468 LOGE("initRecord X: could not initialize record heap.");
4469 return false;
4470 }
4471 for (int cnt = 0; cnt < kRecordBufferCount; cnt++) {
4472 recordframes[cnt].fd = mRecordHeap->mHeap->getHeapID();
4473 recordframes[cnt].buffer =
4474 (uint32_t)mRecordHeap->mHeap->base() + mRecordHeap->mAlignedBufferSize * cnt;
4475 recordframes[cnt].y_off = 0;
Nishant Panditbde07612010-07-28 00:16:28 +05304476 recordframes[cnt].cbcr_off = CbCrOffset;
Sravankb4f5f1c2010-01-21 11:06:17 +05304477 recordframes[cnt].path = OUTPUT_TYPE_V;
Mohan Kandra1fd90f92010-06-17 14:54:17 -07004478 record_buffers_tracking_flag[cnt] = false;
Sravankb4f5f1c2010-01-21 11:06:17 +05304479 LOGV ("initRecord : record heap , video buffers buffer=%lu fd=%d y_off=%d cbcr_off=%d \n",
4480 (unsigned long)recordframes[cnt].buffer, recordframes[cnt].fd, recordframes[cnt].y_off,
4481 recordframes[cnt].cbcr_off);
4482 }
4483
4484 // initial setup : buffers 1,2,3 with kernel , 4 with camframe , 5,6,7,8 in free Q
4485 // flush the busy Q
4486 cam_frame_flush_video();
4487
Mohan Kandra156d0ac2010-01-25 16:59:17 -08004488 mVideoThreadWaitLock.lock();
4489 while (mVideoThreadRunning) {
4490 LOGV("initRecord: waiting for old video thread to complete.");
4491 mVideoThreadWait.wait(mVideoThreadWaitLock);
4492 LOGV("initRecord : old video thread completed.");
4493 }
4494 mVideoThreadWaitLock.unlock();
4495
Sravankdf7a9202010-02-08 15:02:51 +05304496 // flush free queue and add 5,6,7,8 buffers.
4497 LINK_cam_frame_flush_free_video();
Mohan Kandra39fad8d2010-07-15 12:29:19 -07004498 if(mVpeEnabled) {
4499 //If VPE is enabled, the VPE buffer shouldn't be added to Free Q initally.
4500 for(int i=ACTIVE_VIDEO_BUFFERS+1;i <kRecordBufferCount-1; i++)
4501 LINK_camframe_free_video(&recordframes[i]);
4502 } else {
4503 for(int i=ACTIVE_VIDEO_BUFFERS+1;i <kRecordBufferCount; i++)
4504 LINK_camframe_free_video(&recordframes[i]);
4505 }
Sravankb4f5f1c2010-01-21 11:06:17 +05304506 LOGV("initREcord X");
4507
4508 return true;
4509}
4510
Mohan Kandracedd6cc2010-09-14 14:37:08 -07004511
4512status_t QualcommCameraHardware::setDIS() {
4513 LOGV("setDIS E");
4514
4515 video_dis_param_ctrl_t disCtrl;
4516 bool ret = true;
4517 LOGI("mDisEnabled = %d", mDisEnabled);
4518
4519 int video_frame_cbcroffset;
4520 video_frame_cbcroffset = PAD_TO_WORD(videoWidth * videoHeight);
4521 if(mCurrentTarget == TARGET_MSM8660)
4522 video_frame_cbcroffset = PAD_TO_2K(videoWidth * videoHeight);
4523
4524 disCtrl.dis_enable = mDisEnabled;
4525 disCtrl.video_rec_width = videoWidth;
4526 disCtrl.video_rec_height = videoHeight;
4527 disCtrl.output_cbcr_offset = video_frame_cbcroffset;
4528
4529 ret = native_set_parm(CAMERA_SET_VIDEO_DIS_PARAMS,
4530 sizeof(disCtrl), &disCtrl);
4531 LOGV("setDIS X (%d)", ret);
4532 return ret ? NO_ERROR : UNKNOWN_ERROR;
4533}
4534
Mohan Kandra39fad8d2010-07-15 12:29:19 -07004535status_t QualcommCameraHardware::setVpeParameters()
4536{
4537 LOGV("setVpeParameters E");
4538
Mohan Kandra39fad8d2010-07-15 12:29:19 -07004539 video_rotation_param_ctrl_t rotCtrl;
Mohan Kandraec958742010-08-19 10:56:05 -07004540 bool ret = true;
Mohan Kandra39fad8d2010-07-15 12:29:19 -07004541 LOGV("videoWidth = %d, videoHeight = %d", videoWidth, videoHeight);
Mohan Kandra39fad8d2010-07-15 12:29:19 -07004542 rotCtrl.rotation = (mRotation == 0) ? ROT_NONE :
4543 ((mRotation == 90) ? ROT_CLOCKWISE_90 :
4544 ((mRotation == 180) ? ROT_CLOCKWISE_180 : ROT_CLOCKWISE_270));
4545
Mohan Kandraec958742010-08-19 10:56:05 -07004546 if( ((videoWidth == 1280 && videoHeight == 720) || (videoWidth == 800 && videoHeight == 480))
4547 && (mRotation == 90 || mRotation == 270) ){
4548 /* Due to a limitation at video core to support heights greater than 720, adding this check.
4549 * This is a temporary hack, need to be removed once video core support is available
4550 */
Mohan Kandra5e4f9d92010-08-26 18:23:50 -07004551 LOGI("video resolution (%dx%d) with rotation (%d) is not supported, setting rotation to NONE",
Mohan Kandraec958742010-08-19 10:56:05 -07004552 videoWidth, videoHeight, mRotation);
4553 rotCtrl.rotation = ROT_NONE;
Mohan Kandraec958742010-08-19 10:56:05 -07004554 }
Mohan Kandrafdbc2192010-08-24 20:39:59 -07004555 LOGV("rotCtrl.rotation = %d", rotCtrl.rotation);
4556
4557 ret = native_set_parm(CAMERA_SET_VIDEO_ROT_PARAMS,
4558 sizeof(rotCtrl), &rotCtrl);
Mohan Kandra39fad8d2010-07-15 12:29:19 -07004559
4560 LOGV("setVpeParameters X (%d)", ret);
4561 return ret ? NO_ERROR : UNKNOWN_ERROR;
4562}
4563
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004564status_t QualcommCameraHardware::startRecording()
4565{
4566 LOGV("startRecording E");
Sravankb4f5f1c2010-01-21 11:06:17 +05304567 int ret;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004568 Mutex::Autolock l(&mLock);
4569 mReleasedRecordingFrame = false;
Sravankb4f5f1c2010-01-21 11:06:17 +05304570 if( (ret=startPreviewInternal())== NO_ERROR){
Mohan Kandra39fad8d2010-07-15 12:29:19 -07004571 if(mVpeEnabled){
4572 LOGI("startRecording: VPE enabled, setting vpe parameters");
4573 bool status = setVpeParameters();
4574 if(status) {
4575 LOGE("Failed to set VPE parameters");
4576 return status;
4577 }
4578 }
Nishant Pandit3c278cd2010-07-13 15:56:04 +05304579 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250) || (mCurrentTarget == TARGET_MSM8660)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05304580 LOGV(" in startREcording : calling native_start_recording");
4581 native_start_recording(mCameraControlFd);
4582 recordingState = 1;
Sravank64461e82010-02-25 15:10:09 +05304583 // Remove the left out frames in busy Q and them in free Q.
4584 // this should be done before starting video_thread so that,
4585 // frames in previous recording are flushed out.
4586 LOGV("frames in busy Q = %d", g_busy_frame_queue.num_of_frames);
4587 while((g_busy_frame_queue.num_of_frames) >0){
4588 msm_frame* vframe = cam_frame_get_video ();
4589 LINK_camframe_free_video(vframe);
4590 }
4591 LOGV("frames in busy Q = %d after deQueing", g_busy_frame_queue.num_of_frames);
4592
Mohan Kandra1fd90f92010-06-17 14:54:17 -07004593 //Clear the dangling buffers and put them in free queue
4594 for(int cnt = 0; cnt < kRecordBufferCount; cnt++) {
4595 if(record_buffers_tracking_flag[cnt] == true) {
Mohan Kandra62429cc2010-07-19 10:21:05 -07004596 LOGI("Dangling buffer: offset = %d, buffer = %d", cnt, (unsigned int)recordframes[cnt].buffer);
Mohan Kandra1fd90f92010-06-17 14:54:17 -07004597 LINK_camframe_free_video(&recordframes[cnt]);
4598 record_buffers_tracking_flag[cnt] = false;
4599 }
4600 }
4601
Sravankdf7a9202010-02-08 15:02:51 +05304602 // Start video thread and wait for busy frames to be encoded, this thread
4603 // should be closed in stopRecording
4604 mVideoThreadWaitLock.lock();
4605 mVideoThreadExit = 0;
4606 pthread_attr_t attr;
4607 pthread_attr_init(&attr);
4608 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
4609 mVideoThreadRunning = pthread_create(&mVideoThread,
4610 &attr,
4611 video_thread,
4612 NULL);
4613 mVideoThreadWaitLock.unlock();
4614 // Remove the left out frames in busy Q and them in free Q.
Sravankb4f5f1c2010-01-21 11:06:17 +05304615 }
4616 }
4617 return ret;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004618}
4619
4620void QualcommCameraHardware::stopRecording()
4621{
4622 LOGV("stopRecording: E");
4623 Mutex::Autolock l(&mLock);
4624 {
4625 mRecordFrameLock.lock();
4626 mReleasedRecordingFrame = true;
4627 mRecordWait.signal();
4628 mRecordFrameLock.unlock();
4629
Sravankdf7a9202010-02-08 15:02:51 +05304630 if(mDataCallback && !(mCurrentTarget == TARGET_QSD8250) &&
4631 (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004632 LOGV("stopRecording: X, preview still in progress");
4633 return;
4634 }
4635 }
Sravankb4f5f1c2010-01-21 11:06:17 +05304636 // If output2 enabled, exit video thread, invoke stop recording ioctl
Nishant Pandit3c278cd2010-07-13 15:56:04 +05304637 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250) || (mCurrentTarget == TARGET_MSM8660)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05304638 mVideoThreadWaitLock.lock();
4639 mVideoThreadExit = 1;
4640 mVideoThreadWaitLock.unlock();
4641 native_stop_recording(mCameraControlFd);
Srinivasan Kannanfc3915c2010-03-18 10:54:40 -07004642
4643 pthread_mutex_lock(&(g_busy_frame_queue.mut));
4644 pthread_cond_signal(&(g_busy_frame_queue.wait));
4645 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
Sravankb4f5f1c2010-01-21 11:06:17 +05304646 }
4647 else // for other targets where output2 is not enabled
4648 stopPreviewInternal();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004649
Vamshidhar Kondra92ce9142010-09-03 18:22:08 +05304650 if (mJpegHeap != NULL) {
4651 LOGV("stopRecording: clearing old mJpegHeap.");
4652 mJpegHeap.clear();
4653 }
Sravankb4f5f1c2010-01-21 11:06:17 +05304654 recordingState = 0; // recording not started
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004655 LOGV("stopRecording: X");
4656}
4657
4658void QualcommCameraHardware::releaseRecordingFrame(
4659 const sp<IMemory>& mem __attribute__((unused)))
4660{
4661 LOGV("releaseRecordingFrame E");
4662 Mutex::Autolock rLock(&mRecordFrameLock);
4663 mReleasedRecordingFrame = true;
4664 mRecordWait.signal();
Sravankb4f5f1c2010-01-21 11:06:17 +05304665
4666 // Ff 7x30 : add the frame to the free camframe queue
Nishant Pandit3c278cd2010-07-13 15:56:04 +05304667 if( (mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250) || (mCurrentTarget == TARGET_MSM8660)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05304668 ssize_t offset;
4669 size_t size;
4670 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
4671 msm_frame* releaseframe = NULL;
4672 LOGV(" in release recording frame : heap base %d offset %d buffer %d ", heap->base(), offset, heap->base() + offset );
4673 int cnt;
4674 for (cnt = 0; cnt < kRecordBufferCount; cnt++) {
Mohan Kandra62429cc2010-07-19 10:21:05 -07004675 if((unsigned int)recordframes[cnt].buffer == ((unsigned int)heap->base()+ offset)){
Sravankb4f5f1c2010-01-21 11:06:17 +05304676 LOGV("in release recording frame found match , releasing buffer %d", (unsigned int)recordframes[cnt].buffer);
4677 releaseframe = &recordframes[cnt];
4678 break;
4679 }
4680 }
4681 if(cnt < kRecordBufferCount) {
4682 // do this only if frame thread is running
4683 mFrameThreadWaitLock.lock();
Mohan Kandra1fd90f92010-06-17 14:54:17 -07004684 if(mFrameThreadRunning ) {
4685 //Reset the track flag for this frame buffer
4686 record_buffers_tracking_flag[cnt] = false;
Sravankb4f5f1c2010-01-21 11:06:17 +05304687 LINK_camframe_free_video(releaseframe);
Mohan Kandra1fd90f92010-06-17 14:54:17 -07004688 }
Sravankb4f5f1c2010-01-21 11:06:17 +05304689
4690 mFrameThreadWaitLock.unlock();
4691 } else {
4692 LOGE("in release recordingframe XXXXX error , buffer not found");
4693 for (int i=0; i< kRecordBufferCount; i++) {
4694 LOGE(" recordframes[%d].buffer = %d", i, (unsigned int)recordframes[i].buffer);
4695 }
4696 }
4697 }
4698
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004699 LOGV("releaseRecordingFrame X");
4700}
4701
4702bool QualcommCameraHardware::recordingEnabled()
4703{
4704 return mCameraRunning && mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME);
4705}
4706
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08004707void QualcommCameraHardware::notifyShutter(common_crop_t *crop, bool mPlayShutterSoundOnly)
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004708{
4709 mShutterLock.lock();
4710 image_rect_type size;
4711
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08004712 if(mPlayShutterSoundOnly) {
4713 /* At this point, invoke Notify Callback to play shutter sound only.
4714 * We want to call notify callback again when we have the
4715 * yuv picture ready. This is to reduce blanking at the time
4716 * of displaying postview frame. Using ext2 to indicate whether
4717 * to play shutter sound only or register the postview buffers.
4718 */
4719 mNotifyCallback(CAMERA_MSG_SHUTTER, 0, mPlayShutterSoundOnly,
4720 mCallbackCookie);
4721 mShutterLock.unlock();
4722 return;
4723 }
4724
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004725 if (mShutterPending && mNotifyCallback && (mMsgEnabled & CAMERA_MSG_SHUTTER)) {
Deepak Kurienc1e3cd42010-10-01 12:09:52 -07004726 if (mSnapshotFormat == PICTURE_FORMAT_RAW) {
4727 size.width = previewWidth;
4728 size.height = previewHeight;
4729 mNotifyCallback(CAMERA_MSG_SHUTTER, (int32_t)&size, 0,
4730 mCallbackCookie);
4731 mShutterPending = false;
4732 mShutterLock.unlock();
4733 return;
4734 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004735 LOGV("out2_w=%d, out2_h=%d, in2_w=%d, in2_h=%d",
4736 crop->out2_w, crop->out2_h, crop->in2_w, crop->in2_h);
4737 LOGV("out1_w=%d, out1_h=%d, in1_w=%d, in1_h=%d",
4738 crop->out1_w, crop->out1_h, crop->in1_w, crop->in1_h);
4739
4740 // To workaround a bug in MDP which happens if either
4741 // dimension > 2048, we display the thumbnail instead.
Apurva Rajguru905b8532010-08-02 18:29:38 -07004742
4743 if (mCurrentTarget == TARGET_MSM7627)
4744 mDisplayHeap = mPostViewHeap;
4745 else
4746 mDisplayHeap = mRawHeap;
4747
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004748 if (crop->in1_w == 0 || crop->in1_h == 0) {
4749 // Full size
4750 size.width = mDimension.picture_width;
4751 size.height = mDimension.picture_height;
4752 if (size.width > 2048 || size.height > 2048) {
4753 size.width = mDimension.ui_thumbnail_width;
4754 size.height = mDimension.ui_thumbnail_height;
4755 mDisplayHeap = mThumbnailHeap;
4756 }
Apurva Rajguru905b8532010-08-02 18:29:38 -07004757 else {
4758 if (mCurrentTarget == TARGET_MSM7627) {
4759 size.width = previewWidth;
4760 size.height = previewHeight;
4761 }
4762 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004763 } else {
4764 // Cropped
Srinivasan Kannan5701a942010-04-15 16:17:21 -07004765 size.width = (crop->in2_w + jpegPadding) & ~1;
4766 size.height = (crop->in2_h + jpegPadding) & ~1;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004767 if (size.width > 2048 || size.height > 2048) {
Srinivasan Kannan5701a942010-04-15 16:17:21 -07004768 size.width = (crop->in1_w + jpegPadding) & ~1;
4769 size.height = (crop->in1_h + jpegPadding) & ~1;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004770 mDisplayHeap = mThumbnailHeap;
4771 }
Apurva Rajguru905b8532010-08-02 18:29:38 -07004772 else {
4773 if (mCurrentTarget == TARGET_MSM7627) {
4774 size.width = previewWidth;
4775 size.height = previewHeight;
4776 }
4777 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004778 }
Mohan Kandra5e4f9d92010-08-26 18:23:50 -07004779 //We need to create overlay with dimensions that the VFE output
4780 //is configured for post view.
4781 if((mCurrentTarget == TARGET_MSM7630) ||
4782 (mCurrentTarget == TARGET_MSM8660)) {
4783 size.width = mDimension.ui_thumbnail_width;
4784 size.height = mDimension.ui_thumbnail_height;
4785 //Make ThumbnailHeap as Displayheap for post view.
4786 mDisplayHeap = mThumbnailHeap;
4787 }
4788
Mohan Kandra1659b0c2010-07-18 16:36:25 -07004789 //For Adreno format, we need to pass the main image in all the cases.
Mohan Kandra73875f02010-09-24 17:34:54 -07004790 if(mPreviewFormat == CAMERA_YUV_420_NV21_ADRENO) {
4791 int rawWidth, rawHeight;
4792 mParameters.getPictureSize(&rawWidth, &rawHeight);
4793 size.width = rawWidth;
4794 size.height = rawHeight;
Mohan Kandra1659b0c2010-07-18 16:36:25 -07004795 mDisplayHeap = mRawHeap;
Mohan Kandra73875f02010-09-24 17:34:54 -07004796 }
Mohan Kandra1659b0c2010-07-18 16:36:25 -07004797
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08004798 /* Now, invoke Notify Callback to unregister preview buffer
4799 * and register postview buffer with surface flinger. Set ext2
4800 * as 0 to indicate not to play shutter sound.
4801 */
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004802 mNotifyCallback(CAMERA_MSG_SHUTTER, (int32_t)&size, 0,
4803 mCallbackCookie);
4804 mShutterPending = false;
4805 }
4806 mShutterLock.unlock();
4807}
4808
4809static void receive_shutter_callback(common_crop_t *crop)
4810{
4811 LOGV("receive_shutter_callback: E");
4812 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4813 if (obj != 0) {
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08004814 /* Just play shutter sound at this time */
4815 obj->notifyShutter(crop, TRUE);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004816 }
4817 LOGV("receive_shutter_callback: X");
4818}
4819
4820// Crop the picture in place.
4821static void crop_yuv420(uint32_t width, uint32_t height,
4822 uint32_t cropped_width, uint32_t cropped_height,
Apurva Rajguru905b8532010-08-02 18:29:38 -07004823 uint8_t *image, const char *name)
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004824{
Srinivasan Kannan970bb4f2010-09-08 20:08:16 -07004825 int32_t i;
4826 uint32_t x, y;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004827 uint8_t* chroma_src, *chroma_dst;
Apurva Rajguru905b8532010-08-02 18:29:38 -07004828 int yOffsetSrc, yOffsetDst, CbCrOffsetSrc, CbCrOffsetDst;
4829 int mSrcSize, mDstSize;
4830
4831 //check if all fields needed eg. size and also how to set y offset. If condition for 7x27
4832 //and need to check if needed for 7x30.
4833
4834 LINK_jpeg_encoder_get_buffer_offset(width, height, (uint32_t *)&yOffsetSrc,
4835 (uint32_t *)&CbCrOffsetSrc, (uint32_t *)&mSrcSize);
4836
4837 LINK_jpeg_encoder_get_buffer_offset(cropped_width, cropped_height, (uint32_t *)&yOffsetDst,
4838 (uint32_t *)&CbCrOffsetDst, (uint32_t *)&mDstSize);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004839
4840 // Calculate the start position of the cropped area.
4841 x = (width - cropped_width) / 2;
4842 y = (height - cropped_height) / 2;
4843 x &= ~1;
4844 y &= ~1;
4845
Apurva Rajguru905b8532010-08-02 18:29:38 -07004846 if((mCurrentTarget == TARGET_MSM7627)
Priyanka Kharat32409f72010-08-25 18:11:03 -07004847 || (mCurrentTarget == TARGET_MSM7630)
4848 || (mCurrentTarget == TARGET_MSM8660)) {
Apurva Rajguru905b8532010-08-02 18:29:38 -07004849 if (!strcmp("snapshot camera", name)) {
4850 chroma_src = image + CbCrOffsetSrc;
4851 chroma_dst = image + CbCrOffsetDst;
4852 } else {
4853 chroma_src = image + width * height;
4854 chroma_dst = image + cropped_width * cropped_height;
Apurva Rajgurubfc04522010-08-11 16:22:25 -07004855 yOffsetSrc = 0;
4856 yOffsetDst = 0;
Srinivasan Kannan970bb4f2010-09-08 20:08:16 -07004857 CbCrOffsetSrc = width * height;
4858 CbCrOffsetDst = cropped_width * cropped_height;
Apurva Rajguru905b8532010-08-02 18:29:38 -07004859 }
4860 } else {
4861 chroma_src = image + CbCrOffsetSrc;
4862 chroma_dst = image + CbCrOffsetDst;
4863 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004864
Srinivasan Kannan970bb4f2010-09-08 20:08:16 -07004865 int32_t bufDst = yOffsetDst;
4866 int32_t bufSrc = yOffsetSrc + (width * y) + x;
4867
4868 if( bufDst > bufSrc ){
4869 LOGV("crop yuv Y destination position follows source position");
4870 /*
4871 * If buffer destination follows buffer source, memcpy
4872 * of lines will lead to overwriting subsequent lines. In order
4873 * to prevent this, reverse copying of lines is performed
4874 * for the set of lines where destination follows source and
4875 * forward copying of lines is performed for lines where source
4876 * follows destination. To calculate the position to switch,
4877 * the initial difference between source and destination is taken
4878 * and divided by difference between width and cropped width. For
4879 * every line copied the difference between source destination
4880 * drops by width - cropped width
4881 */
4882 //calculating inversion
4883 int position = ( bufDst - bufSrc ) / (width - cropped_width);
4884 // Copy luma component.
4885 for(i=position+1; i < cropped_height; i++){
4886 memmove(image + yOffsetDst + i * cropped_width,
4887 image + yOffsetSrc + width * (y + i) + x,
4888 cropped_width);
4889 }
4890 for(i=position; i>=0; i--){
4891 memmove(image + yOffsetDst + i * cropped_width,
4892 image + yOffsetSrc + width * (y + i) + x,
4893 cropped_width);
4894 }
4895 } else {
4896 // Copy luma component.
4897 for(i = 0; i < cropped_height; i++)
4898 memcpy(image + yOffsetDst + i * cropped_width,
4899 image + yOffsetSrc + width * (y + i) + x,
4900 cropped_width);
4901 }
4902
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004903 // Copy chroma components.
4904 cropped_height /= 2;
4905 y /= 2;
Srinivasan Kannan970bb4f2010-09-08 20:08:16 -07004906
4907 bufDst = CbCrOffsetDst;
4908 bufSrc = CbCrOffsetSrc + (width * y) + x;
4909
4910 if( bufDst > bufSrc ) {
4911 LOGV("crop yuv Chroma destination position follows source position");
4912 /*
4913 * Similar to y
4914 */
4915 int position = ( bufDst - bufSrc ) / (width - cropped_width);
4916 for(i=position+1; i < cropped_height; i++){
4917 memmove(chroma_dst + i * cropped_width,
4918 chroma_src + width * (y + i) + x,
4919 cropped_width);
4920 }
4921 for(i=position; i >=0; i--){
4922 memmove(chroma_dst + i * cropped_width,
4923 chroma_src + width * (y + i) + x,
4924 cropped_width);
4925 }
4926 } else {
4927 for(i = 0; i < cropped_height; i++)
4928 memcpy(chroma_dst + i * cropped_width,
4929 chroma_src + width * (y + i) + x,
4930 cropped_width);
4931 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004932}
4933
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08004934void QualcommCameraHardware::receiveRawSnapshot(){
4935 LOGV("receiveRawSnapshot E");
4936
4937 Mutex::Autolock cbLock(&mCallbackLock);
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08004938 /* Issue notifyShutter with mPlayShutterSoundOnly as TRUE */
4939 notifyShutter(&mCrop, TRUE);
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08004940
4941 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
4942
4943 if(native_get_picture(mCameraControlFd, &mCrop) == false) {
4944 LOGE("receiveRawSnapshot X: native_get_picture failed!");
4945 return;
4946 }
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08004947 /* Its necessary to issue another notifyShutter here with
4948 * mPlayShutterSoundOnly as FALSE, since that is when the
4949 * preview buffers are unregistered with the surface flinger.
4950 * That is necessary otherwise the preview memory wont be
4951 * deallocated.
4952 */
4953 notifyShutter(&mCrop, FALSE);
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08004954
4955 //Create a Ashmem heap to copy data from PMem heap for application layer
4956 if(mRawSnapshotAshmemHeap != NULL){
4957 LOGV("receiveRawSnapshot: clearing old mRawSnapShotAshmemHeap.");
4958 mRawSnapshotAshmemHeap.clear();
4959 }
4960 mRawSnapshotAshmemHeap = new AshmemPool(
4961 mRawSnapShotPmemHeap->mBufferSize,
4962 mRawSnapShotPmemHeap->mNumBuffers,
4963 mRawSnapShotPmemHeap->mFrameSize,
4964 "raw ashmem snapshot camera"
4965 );
4966
4967 if(!mRawSnapshotAshmemHeap->initialized()){
4968 LOGE("receiveRawSnapshot X: error initializing mRawSnapshotHeap");
4969 deinitRawSnapshot();
4970 return;
4971 }
4972
4973 memcpy(mRawSnapshotAshmemHeap->mHeap->base(),
4974 mRawSnapShotPmemHeap->mHeap->base(),
4975 mRawSnapShotPmemHeap->mHeap->getSize());
Nishant Panditb861be52010-03-02 16:43:49 +05304976 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE))
4977 mDataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mRawSnapshotAshmemHeap->mBuffers[0],
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08004978 mCallbackCookie);
4979
4980 }
4981
4982 //cleanup
4983 deinitRawSnapshot();
4984
4985 LOGV("receiveRawSnapshot X");
4986}
4987
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004988void QualcommCameraHardware::receiveRawPicture()
4989{
4990 LOGV("receiveRawPicture: E");
4991
4992 Mutex::Autolock cbLock(&mCallbackLock);
Apurva Rajguru3da1a702010-07-28 12:32:42 -07004993 if (mDataCallback && ((mMsgEnabled & CAMERA_MSG_RAW_IMAGE) || mSnapshotDone)) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004994 if(native_get_picture(mCameraControlFd, &mCrop) == false) {
4995 LOGE("getPicture failed!");
4996 return;
4997 }
Apurva Rajguru3da1a702010-07-28 12:32:42 -07004998 mSnapshotDone = FALSE;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004999 mCrop.in1_w &= ~1;
5000 mCrop.in1_h &= ~1;
5001 mCrop.in2_w &= ~1;
5002 mCrop.in2_h &= ~1;
5003
Priya Komarlingamb85535d2009-11-30 13:06:01 -08005004
5005 // Crop the image if zoomed.
Srinivasan Kannan5701a942010-04-15 16:17:21 -07005006 if (mCrop.in2_w != 0 && mCrop.in2_h != 0 &&
5007 ((mCrop.in2_w + jpegPadding) < mCrop.out2_w) &&
5008 ((mCrop.in2_h + jpegPadding) < mCrop.out2_h) &&
5009 ((mCrop.in1_w + jpegPadding) < mCrop.out1_w) &&
5010 ((mCrop.in1_h + jpegPadding) < mCrop.out1_h) ) {
5011
5012 // By the time native_get_picture returns, picture is taken. Call
5013 // shutter callback if cam config thread has not done that.
5014 notifyShutter(&mCrop, FALSE);
Srinivasan Kannan426cde72010-06-04 09:37:21 -07005015 {
5016 Mutex::Autolock l(&mRawPictureHeapLock);
Mohan Kandra5e4f9d92010-08-26 18:23:50 -07005017 if(mRawHeap != NULL){
5018 crop_yuv420(mCrop.out2_w, mCrop.out2_h, (mCrop.in2_w + jpegPadding), (mCrop.in2_h + jpegPadding),
Apurva Rajguru905b8532010-08-02 18:29:38 -07005019 (uint8_t *)mRawHeap->mHeap->base(), mRawHeap->mName);
Mohan Kandra5e4f9d92010-08-26 18:23:50 -07005020 }
5021 if( (mThumbnailHeap != NULL) &&
5022 (mCurrentTarget != TARGET_MSM7630) &&
5023 (mCurrentTarget != TARGET_MSM8660) ) {
5024 //Don't crop the mThumbnailHeap for 7630. As this heap
5025 //is used for postview rather than for thumbnail. (thumbnail is generated from main image).
5026 //overlay's setCrop will take of cropping while displaying postview.
Srinivasan Kannan426cde72010-06-04 09:37:21 -07005027 crop_yuv420(mCrop.out1_w, mCrop.out1_h, (mCrop.in1_w + jpegPadding), (mCrop.in1_h + jpegPadding),
Apurva Rajguru905b8532010-08-02 18:29:38 -07005028 (uint8_t *)mThumbnailHeap->mHeap->base(), mThumbnailHeap->mName);
5029 }
Srinivasan Kannan426cde72010-06-04 09:37:21 -07005030 }
Srinivasan Kannan5701a942010-04-15 16:17:21 -07005031
Priya Komarlingamb85535d2009-11-30 13:06:01 -08005032 // We do not need jpeg encoder to upscale the image. Set the new
5033 // dimension for encoder.
Srinivasan Kannan5701a942010-04-15 16:17:21 -07005034 mDimension.orig_picture_dx = mCrop.in2_w + jpegPadding;
5035 mDimension.orig_picture_dy = mCrop.in2_h + jpegPadding;
Mohan Kandra5e4f9d92010-08-26 18:23:50 -07005036 /* Don't update the thumbnail_width/height, if jpeg downscaling
5037 * is used to generate thumbnail. These parameters should contain
5038 * the original thumbnail dimensions.
5039 */
5040 if(mPreviewFormat != CAMERA_YUV_420_NV21_ADRENO) {
5041 mDimension.thumbnail_width = mCrop.in1_w + jpegPadding;
5042 mDimension.thumbnail_height = mCrop.in1_h + jpegPadding;
5043 }
Srinivasan Kannan5701a942010-04-15 16:17:21 -07005044 }else {
5045 memset(&mCrop, 0 ,sizeof(mCrop));
5046 // By the time native_get_picture returns, picture is taken. Call
5047 // shutter callback if cam config thread has not done that.
5048 notifyShutter(&mCrop, FALSE);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08005049 }
5050
Mohan Kandra5e4f9d92010-08-26 18:23:50 -07005051 if( mUseOverlay && (mOverlay != NULL) ) {
5052 mOverlay->setFd(mDisplayHeap->mHeap->getHeapID());
5053 int cropX = 0;
5054 int cropY = 0;
5055 int cropW = 0;
5056 int cropH = 0;
5057 //Caculate the crop dimensions from mCrop.
5058 //mCrop will have the crop dimensions for VFE's
5059 //postview output.
5060 if (mCrop.in1_w != 0 || mCrop.in1_h != 0) {
5061 cropX = (mCrop.out1_w - mCrop.in1_w + 1) / 2 - 1;
5062 cropY = (mCrop.out1_h - mCrop.in1_h + 1) / 2 - 1;
5063 cropW = mCrop.in1_w;
5064 cropH = mCrop.in1_h;
5065 mOverlay->setCrop(cropX, cropY, cropW, cropH);
5066 }
5067 LOGV(" Queueing Postview for display ");
5068 mOverlay->queueBuffer((void *)0);
5069 }
5070 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_RAW_IMAGE))
5071 mDataCallback(CAMERA_MSG_RAW_IMAGE, mDisplayHeap->mBuffers[0],
Priya Komarlingamb85535d2009-11-30 13:06:01 -08005072 mCallbackCookie);
Mohan Kandra5e4f9d92010-08-26 18:23:50 -07005073 if(mPreviewFormat == CAMERA_YUV_420_NV21_ADRENO) {
5074 LOGI("Raw Data given to app for processing...will wait for jpeg encode call");
5075 mEncodePendingWaitLock.lock();
5076 mEncodePending = true;
5077 mEncodePendingWaitLock.unlock();
5078 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08005079 }
5080 else LOGV("Raw-picture callback was canceled--skipping.");
5081
Mohan Kandra1659b0c2010-07-18 16:36:25 -07005082 if(mPreviewFormat != CAMERA_YUV_420_NV21_ADRENO) {
5083 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
5084 mJpegSize = 0;
5085 mJpegThreadWaitLock.lock();
5086 if (LINK_jpeg_encoder_init()) {
5087 mJpegThreadRunning = true;
5088 mJpegThreadWaitLock.unlock();
5089 if(native_jpeg_encode()) {
5090 LOGV("receiveRawPicture: X (success)");
5091 return;
5092 }
5093 LOGE("jpeg encoding failed");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08005094 }
Mohan Kandra1659b0c2010-07-18 16:36:25 -07005095 else {
5096 LOGE("receiveRawPicture X: jpeg_encoder_init failed.");
5097 mJpegThreadWaitLock.unlock();
5098 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08005099 }
Mohan Kandra1659b0c2010-07-18 16:36:25 -07005100 else LOGV("JPEG callback is NULL, not encoding image.");
5101 deinitRaw();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08005102 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08005103 LOGV("receiveRawPicture: X");
5104}
5105
5106void QualcommCameraHardware::receiveJpegPictureFragment(
5107 uint8_t *buff_ptr, uint32_t buff_size)
5108{
Vamshidhar Kondra92ce9142010-09-03 18:22:08 +05305109 LOGV("receiveJpegPictureFragment size %d", buff_size);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08005110 uint32_t remaining = mJpegHeap->mHeap->virtualSize();
5111 remaining -= mJpegSize;
5112 uint8_t *base = (uint8_t *)mJpegHeap->mHeap->base();
5113
Priya Komarlingamb85535d2009-11-30 13:06:01 -08005114 if (buff_size > remaining) {
5115 LOGE("receiveJpegPictureFragment: size %d exceeds what "
5116 "remains in JPEG heap (%d), truncating",
5117 buff_size,
5118 remaining);
5119 buff_size = remaining;
5120 }
5121 memcpy(base + mJpegSize, buff_ptr, buff_size);
5122 mJpegSize += buff_size;
5123}
5124
5125void QualcommCameraHardware::receiveJpegPicture(void)
5126{
5127 LOGV("receiveJpegPicture: E image (%d uint8_ts out of %d)",
5128 mJpegSize, mJpegHeap->mBufferSize);
5129 Mutex::Autolock cbLock(&mCallbackLock);
5130
5131 int index = 0, rc;
5132
5133 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
5134 // The reason we do not allocate into mJpegHeap->mBuffers[offset] is
5135 // that the JPEG image's size will probably change from one snapshot
5136 // to the next, so we cannot reuse the MemoryBase object.
5137 sp<MemoryBase> buffer = new
5138 MemoryBase(mJpegHeap->mHeap,
5139 index * mJpegHeap->mBufferSize +
5140 0,
5141 mJpegSize);
5142 mDataCallback(CAMERA_MSG_COMPRESSED_IMAGE, buffer, mCallbackCookie);
5143 buffer = NULL;
5144 }
5145 else LOGV("JPEG callback was cancelled--not delivering image.");
5146
Mohan Kandraca2e7a92010-06-21 15:48:45 -07005147 mJpegThreadWaitLock.lock();
5148 mJpegThreadRunning = false;
5149 mJpegThreadWait.signal();
5150 mJpegThreadWaitLock.unlock();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08005151
5152 LOGV("receiveJpegPicture: X callback done.");
5153}
5154
5155bool QualcommCameraHardware::previewEnabled()
5156{
Kiran Kumar H N280d4de2010-05-05 13:40:15 -07005157 /* If overlay is used the message CAMERA_MSG_PREVIEW_FRAME would
5158 * be disabled at CameraService layer. Hence previewEnabled would
5159 * return FALSE even though preview is running. Hence check for
5160 * mOverlay not being NULL to ensure that previewEnabled returns
5161 * accurate information.
5162 */
5163 return mCameraRunning && mDataCallback &&
5164 ((mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME) || (mOverlay != NULL));
Priya Komarlingamb85535d2009-11-30 13:06:01 -08005165}
Mohan Kandra091d5ab2010-07-14 16:53:25 -07005166status_t QualcommCameraHardware::setRecordSize(const CameraParameters& params)
5167{
5168 int width, height;
5169 const char *str = params.get("record-size");
5170 if(str) {
5171 LOGV("Requested Record size %s", str);
5172 mParameters.set("record-size" , str);
5173 } else {
5174 //set the record-size value to null.
5175 //This is required as the application can request
5176 //to reset this value, so that it won't be carried
5177 //when switched to camera.
5178 mParameters.set("record-size", "");
5179 }
5180 return NO_ERROR;
5181}
5182
Priya Komarlingamb85535d2009-11-30 13:06:01 -08005183
5184status_t QualcommCameraHardware::setPreviewSize(const CameraParameters& params)
5185{
5186 int width, height;
5187 params.getPreviewSize(&width, &height);
5188 LOGV("requested preview size %d x %d", width, height);
5189
5190 // Validate the preview size
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -08005191 for (size_t i = 0; i < previewSizeCount; ++i) {
5192 if (width == supportedPreviewSizes[i].width
5193 && height == supportedPreviewSizes[i].height) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08005194 mParameters.setPreviewSize(width, height);
Mohan Kandra091d5ab2010-07-14 16:53:25 -07005195 mDimension.display_width = width;
5196 mDimension.display_height= height;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08005197 return NO_ERROR;
5198 }
5199 }
5200 LOGE("Invalid preview size requested: %dx%d", width, height);
5201 return BAD_VALUE;
5202}
5203
Srinivasan Kannana01751b2010-06-24 18:44:40 -07005204status_t QualcommCameraHardware::setPreviewFrameRate(const CameraParameters& params)
5205{
Nishant Pandit2eedc1b2010-09-25 04:47:39 +05305206 if((!strcmp(sensorType->name, "2mp")) ||
5207 (!strcmp(sensorType->name, "ov7692"))){
Srinivasan Kannan2c99dba2010-07-28 13:50:53 -07005208 LOGI("set fps is not supported for this sensor");
5209 return NO_ERROR;
Srinivasan Kannanf01d8592010-07-25 13:47:08 -07005210 }
Srinivasan Kannana01751b2010-06-24 18:44:40 -07005211 uint16_t previousFps = (uint16_t)mParameters.getPreviewFrameRate();
5212 uint16_t fps = (uint16_t)params.getPreviewFrameRate();
5213 LOGV("requested preview frame rate is %u", fps);
5214
5215 if(mInitialized && (fps == previousFps)){
5216 LOGV("fps same as previous fps");
5217 return NO_ERROR;
5218 }
5219
5220 if(MINIMUM_FPS <= fps && fps <=MAXIMUM_FPS){
5221 mParameters.setPreviewFrameRate(fps);
5222 bool ret = native_set_parm(CAMERA_SET_PARM_FPS,
5223 sizeof(fps), (void *)&fps);
5224 return ret ? NO_ERROR : UNKNOWN_ERROR;
5225 }
5226 return BAD_VALUE;
Mohan Kandrabf6146d2010-07-20 18:48:37 -07005227}
Srinivasan Kannana01751b2010-06-24 18:44:40 -07005228
Mohan Kandrabf6146d2010-07-20 18:48:37 -07005229status_t QualcommCameraHardware::setPreviewFrameRateMode(const CameraParameters& params) {
Nishant Pandit2eedc1b2010-09-25 04:47:39 +05305230 if((!strcmp(sensorType->name, "2mp")) ||
5231 (!strcmp(sensorType->name, "ov7692"))){
Mohan Kandrabf6146d2010-07-20 18:48:37 -07005232 LOGI("set fps mode is not supported for this sensor");
5233 return NO_ERROR;
5234 }
5235 const char *previousMode = mParameters.getPreviewFrameRateMode();
5236 const char *str = params.getPreviewFrameRateMode();
5237 if( mInitialized && !strcmp(previousMode, str)) {
5238 LOGV("frame rate mode same as previous mode %s", previousMode);
5239 return NO_ERROR;
5240 }
5241 int32_t frameRateMode = attr_lookup(frame_rate_modes, sizeof(frame_rate_modes) / sizeof(str_map),str);
5242 if(frameRateMode != NOT_FOUND) {
5243 LOGV("setPreviewFrameRateMode: %s ", str);
5244 mParameters.setPreviewFrameRateMode(str);
5245 bool ret = native_set_parm(CAMERA_SET_FPS_MODE, sizeof(frameRateMode), (void *)&frameRateMode);
5246 if(!ret) return ret;
5247 //set the fps value when chaging modes
5248 int16_t fps = (uint16_t)params.getPreviewFrameRate();
5249 if(MINIMUM_FPS <= fps && fps <=MAXIMUM_FPS){
5250 mParameters.setPreviewFrameRate(fps);
5251 ret = native_set_parm(CAMERA_SET_PARM_FPS,
5252 sizeof(fps), (void *)&fps);
5253 return ret ? NO_ERROR : UNKNOWN_ERROR;
5254 }
5255 LOGI("Invalid preview frame rate value: %d", fps);
5256 return BAD_VALUE;
5257 }
5258 LOGI("Invalid preview frame rate mode value: %s", (str == NULL) ? "NULL" : str);
5259 return BAD_VALUE;
Srinivasan Kannana01751b2010-06-24 18:44:40 -07005260}
5261
Srinivasan Kannan264376e2010-08-13 18:54:35 -07005262status_t QualcommCameraHardware::setJpegThumbnailSize(const CameraParameters& params){
5263 int width = params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH);
5264 int height = params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT);
5265 LOGV("requested jpeg thumbnail size %d x %d", width, height);
5266
5267 // Validate the picture size
5268 for (int i = 0; i < JPEG_THUMBNAIL_SIZE_COUNT; ++i) {
5269 if (width == jpeg_thumbnail_sizes[i].width
5270 && height == jpeg_thumbnail_sizes[i].height) {
5271 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, width);
5272 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, height);
5273 return NO_ERROR;
5274 }
5275 }
5276 return BAD_VALUE;
5277}
5278
Priya Komarlingamb85535d2009-11-30 13:06:01 -08005279status_t QualcommCameraHardware::setPictureSize(const CameraParameters& params)
5280{
5281 int width, height;
5282 params.getPictureSize(&width, &height);
5283 LOGV("requested picture size %d x %d", width, height);
5284
5285 // Validate the picture size
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -08005286 for (int i = 0; i < supportedPictureSizesCount; ++i) {
5287 if (width == picture_sizes_ptr[i].width
5288 && height == picture_sizes_ptr[i].height) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08005289 mParameters.setPictureSize(width, height);
5290 mDimension.picture_width = width;
5291 mDimension.picture_height = height;
5292 return NO_ERROR;
5293 }
5294 }
Kiran Kumar H Nb49af212010-02-17 15:12:17 -08005295 /* Dimension not among the ones in the list. Check if
5296 * its a valid dimension, if it is, then configure the
5297 * camera accordingly. else reject it.
5298 */
5299 if( isValidDimension(width, height) ) {
5300 mParameters.setPictureSize(width, height);
5301 mDimension.picture_width = width;
5302 mDimension.picture_height = height;
5303 return NO_ERROR;
5304 } else
5305 LOGE("Invalid picture size requested: %dx%d", width, height);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08005306 return BAD_VALUE;
5307}
5308
5309status_t QualcommCameraHardware::setJpegQuality(const CameraParameters& params) {
5310 status_t rc = NO_ERROR;
5311 int quality = params.getInt(CameraParameters::KEY_JPEG_QUALITY);
5312 if (quality > 0 && quality <= 100) {
5313 mParameters.set(CameraParameters::KEY_JPEG_QUALITY, quality);
5314 } else {
5315 LOGE("Invalid jpeg quality=%d", quality);
5316 rc = BAD_VALUE;
5317 }
5318
5319 quality = params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY);
5320 if (quality > 0 && quality <= 100) {
5321 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, quality);
5322 } else {
5323 LOGE("Invalid jpeg thumbnail quality=%d", quality);
5324 rc = BAD_VALUE;
5325 }
5326 return rc;
5327}
5328
5329status_t QualcommCameraHardware::setEffect(const CameraParameters& params)
5330{
Apurva Rajguru7360db42010-04-09 16:37:36 -07005331
5332 const char *str_wb = mParameters.get(CameraParameters::KEY_WHITE_BALANCE);
5333 int32_t value_wb = attr_lookup(whitebalance, sizeof(whitebalance) / sizeof(str_map), str_wb);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08005334 const char *str = params.get(CameraParameters::KEY_EFFECT);
Apurva Rajguru7360db42010-04-09 16:37:36 -07005335
Priya Komarlingamb85535d2009-11-30 13:06:01 -08005336 if (str != NULL) {
5337 int32_t value = attr_lookup(effects, sizeof(effects) / sizeof(str_map), str);
5338 if (value != NOT_FOUND) {
Nishant Pandit2eedc1b2010-09-25 04:47:39 +05305339 if((!strcmp(sensorType->name, "2mp") || !strcmp(sensorType->name, "ov7692")) && (value != CAMERA_EFFECT_OFF)
Mohan Kandra93f1bfb2009-12-15 16:55:33 -08005340 &&(value != CAMERA_EFFECT_MONO) && (value != CAMERA_EFFECT_NEGATIVE)
5341 &&(value != CAMERA_EFFECT_SOLARIZE) && (value != CAMERA_EFFECT_SEPIA)) {
5342 LOGE("Special effect parameter is not supported for this sensor");
5343 return NO_ERROR;
5344 }
Apurva Rajguru7360db42010-04-09 16:37:36 -07005345
5346 if(((value == CAMERA_EFFECT_MONO) || (value == CAMERA_EFFECT_NEGATIVE)
5347 || (value == CAMERA_EFFECT_AQUA) || (value == CAMERA_EFFECT_SEPIA))
5348 && (value_wb != CAMERA_WB_AUTO)) {
5349 LOGE("Color Effect value will not be set " \
5350 "when the whitebalance selected is %s", str_wb);
5351 return NO_ERROR;
5352 }
5353 else {
5354 mParameters.set(CameraParameters::KEY_EFFECT, str);
5355 bool ret = native_set_parm(CAMERA_SET_PARM_EFFECT, sizeof(value),
5356 (void *)&value);
5357 return ret ? NO_ERROR : UNKNOWN_ERROR;
5358 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08005359 }
5360 }
5361 LOGE("Invalid effect value: %s", (str == NULL) ? "NULL" : str);
5362 return BAD_VALUE;
5363}
5364
Srinivasan Kannan4cc4b862010-06-30 14:22:26 -07005365status_t QualcommCameraHardware::setExposureCompensation(
5366 const CameraParameters & params){
5367
Nishant Pandit2eedc1b2010-09-25 04:47:39 +05305368 if((!strcmp(sensorType->name, "2mp")) || (!strcmp(sensorType->name, "ov7692"))) {
Srinivasan Kannan4cc4b862010-06-30 14:22:26 -07005369 LOGE("Exposure Compensation is not supported for this sensor");
5370 return NO_ERROR;
5371 }
5372
5373 int numerator = params.getInt(CameraParameters::KEY_EXPOSURE_COMPENSATION);
5374 if(EXPOSURE_COMPENSATION_MINIMUM_NUMERATOR <= numerator &&
5375 numerator <= EXPOSURE_COMPENSATION_MAXIMUM_NUMERATOR){
5376 int16_t numerator16 = (int16_t)(numerator & 0x0000ffff);
5377 uint16_t denominator16 = EXPOSURE_COMPENSATION_DENOMINATOR;
5378 uint32_t value = 0;
5379 value = numerator16 << 16 | denominator16;
5380
5381 mParameters.set(CameraParameters::KEY_EXPOSURE_COMPENSATION,
5382 numerator);
5383 bool ret = native_set_parm(CAMERA_SET_PARM_EXPOSURE_COMPENSATION,
5384 sizeof(value), (void *)&value);
5385 return ret ? NO_ERROR : UNKNOWN_ERROR;
5386 }
5387 return BAD_VALUE;
5388}
5389
Apurva Rajguru55562b02009-12-03 12:25:35 -08005390status_t QualcommCameraHardware::setAutoExposure(const CameraParameters& params)
5391{
Nishant Pandit2eedc1b2010-09-25 04:47:39 +05305392 if((!strcmp(sensorType->name, "2mp")) || (!strcmp(sensorType->name, "ov7692"))) {
Mohan Kandra93f1bfb2009-12-15 16:55:33 -08005393 LOGE("Auto Exposure not supported for this sensor");
5394 return NO_ERROR;
5395 }
Apurva Rajguru55562b02009-12-03 12:25:35 -08005396 const char *str = params.get(CameraParameters::KEY_AUTO_EXPOSURE);
5397 if (str != NULL) {
5398 int32_t value = attr_lookup(autoexposure, sizeof(autoexposure) / sizeof(str_map), str);
5399 if (value != NOT_FOUND) {
5400 mParameters.set(CameraParameters::KEY_AUTO_EXPOSURE, str);
5401 bool ret = native_set_parm(CAMERA_SET_PARM_EXPOSURE, sizeof(value),
5402 (void *)&value);
5403 return ret ? NO_ERROR : UNKNOWN_ERROR;
5404 }
5405 }
5406 LOGE("Invalid auto exposure value: %s", (str == NULL) ? "NULL" : str);
5407 return BAD_VALUE;
5408}
5409
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08005410status_t QualcommCameraHardware::setSharpness(const CameraParameters& params)
5411{
Nishant Pandit2eedc1b2010-09-25 04:47:39 +05305412 if((!strcmp(sensorType->name, "2mp")) || (!strcmp(sensorType->name, "ov7692"))) {
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08005413 LOGE("Sharpness not supported for this sensor");
5414 return NO_ERROR;
5415 }
5416 int sharpness = params.getInt(CameraParameters::KEY_SHARPNESS);
5417 if((sharpness < CAMERA_MIN_SHARPNESS
5418 || sharpness > CAMERA_MAX_SHARPNESS))
5419 return UNKNOWN_ERROR;
Srinivasan Kannan551fd262010-01-14 17:48:30 -08005420
5421 LOGV("setting sharpness %d", sharpness);
5422 mParameters.set(CameraParameters::KEY_SHARPNESS, sharpness);
5423 bool ret = native_set_parm(CAMERA_SET_PARM_SHARPNESS, sizeof(sharpness),
5424 (void *)&sharpness);
5425 return ret ? NO_ERROR : UNKNOWN_ERROR;
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08005426}
5427
5428status_t QualcommCameraHardware::setContrast(const CameraParameters& params)
5429{
Nishant Pandit2eedc1b2010-09-25 04:47:39 +05305430 if((!strcmp(sensorType->name, "2mp")) || (!strcmp(sensorType->name, "ov7692"))) {
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08005431 LOGE("Contrast not supported for this sensor");
5432 return NO_ERROR;
5433 }
Srinivasan Kannan551fd262010-01-14 17:48:30 -08005434
Apurva Rajguru08383852010-05-17 14:25:39 -07005435 const char *str = params.get(CameraParameters::KEY_SCENE_MODE);
5436 int32_t value = attr_lookup(scenemode, sizeof(scenemode) / sizeof(str_map), str);
5437
5438 if(value == CAMERA_BESTSHOT_OFF) {
5439 int contrast = params.getInt(CameraParameters::KEY_CONTRAST);
5440 if((contrast < CAMERA_MIN_CONTRAST)
5441 || (contrast > CAMERA_MAX_CONTRAST))
5442 return UNKNOWN_ERROR;
5443
5444 LOGV("setting contrast %d", contrast);
5445 mParameters.set(CameraParameters::KEY_CONTRAST, contrast);
5446 bool ret = native_set_parm(CAMERA_SET_PARM_CONTRAST, sizeof(contrast),
5447 (void *)&contrast);
5448 return ret ? NO_ERROR : UNKNOWN_ERROR;
5449 } else {
5450 LOGE(" Contrast value will not be set " \
5451 "when the scenemode selected is %s", str);
5452 return NO_ERROR;
5453 }
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08005454}
5455
5456status_t QualcommCameraHardware::setSaturation(const CameraParameters& params)
5457{
Nishant Pandit2eedc1b2010-09-25 04:47:39 +05305458 if((!strcmp(sensorType->name, "2mp")) || (!strcmp(sensorType->name, "ov7692"))) {
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08005459 LOGE("Saturation not supported for this sensor");
5460 return NO_ERROR;
5461 }
Srinivasan Kannan551fd262010-01-14 17:48:30 -08005462
Kiran Kumar H Nf87cf862010-01-27 14:34:34 -08005463 const char *str = params.get(CameraParameters::KEY_EFFECT);
5464 int32_t value = attr_lookup(effects, sizeof(effects) / sizeof(str_map), str);
5465
5466 if( (value != CAMERA_EFFECT_MONO) && (value != CAMERA_EFFECT_NEGATIVE)
5467 && (value != CAMERA_EFFECT_AQUA) && (value != CAMERA_EFFECT_SEPIA)) {
5468
5469 int saturation = params.getInt(CameraParameters::KEY_SATURATION);
5470 if((saturation < CAMERA_MIN_SATURATION)
5471 || (saturation > CAMERA_MAX_SATURATION))
5472 return UNKNOWN_ERROR;
5473
Apurva Rajguru08383852010-05-17 14:25:39 -07005474 LOGV("Setting saturation %d", saturation);
Kiran Kumar H Nf87cf862010-01-27 14:34:34 -08005475 mParameters.set(CameraParameters::KEY_SATURATION, saturation);
5476 bool ret = native_set_parm(CAMERA_SET_PARM_SATURATION, sizeof(saturation),
5477 (void *)&saturation);
5478 return ret ? NO_ERROR : UNKNOWN_ERROR;
5479 } else {
5480 LOGE(" Saturation value will not be set " \
5481 "when the effect selected is %s", str);
5482 return NO_ERROR;
5483 }
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08005484}
5485
Mohan Kandra7110c242010-07-18 15:34:48 -07005486status_t QualcommCameraHardware::setPreviewFormat(const CameraParameters& params) {
5487 const char *str = params.getPreviewFormat();
5488 int32_t previewFormat = attr_lookup(preview_formats, sizeof(preview_formats) / sizeof(str_map), str);
5489 if(previewFormat != NOT_FOUND) {
5490 mParameters.set(CameraParameters::KEY_PREVIEW_FORMAT, str);
5491 mPreviewFormat = previewFormat;
5492 return NO_ERROR;
5493 }
5494 LOGI("Invalid preview format value: %s", (str == NULL) ? "NULL" : str);
5495 return BAD_VALUE;
5496}
5497
5498status_t QualcommCameraHardware::setStrTextures(const CameraParameters& params) {
5499 const char *str = params.get("strtextures");
5500 if(str != NULL) {
5501 LOGI("strtextures = %s", str);
5502 mParameters.set("strtextures", str);
5503 if(mUseOverlay) {
5504 if(!strncmp(str, "on", 2) || !strncmp(str, "ON", 2)) {
5505 LOGI("Resetting mUseOverlay to false");
5506 mUseOverlay = false;
5507 }
5508 }
5509 }
5510 return NO_ERROR;
5511}
5512
Nishant Panditc8c1ee72009-12-03 16:24:02 +05305513status_t QualcommCameraHardware::setBrightness(const CameraParameters& params) {
5514 int brightness = params.getInt("luma-adaptation");
5515 if (mBrightness != brightness) {
5516 LOGV(" new brightness value : %d ", brightness);
5517 mBrightness = brightness;
5518
5519 bool ret = native_set_parm(CAMERA_SET_PARM_BRIGHTNESS, sizeof(mBrightness),
5520 (void *)&mBrightness);
5521 return ret ? NO_ERROR : UNKNOWN_ERROR;
5522 } else {
5523 return NO_ERROR;
5524 }
5525}
5526
Priya Komarlingamb85535d2009-11-30 13:06:01 -08005527status_t QualcommCameraHardware::setWhiteBalance(const CameraParameters& params)
5528{
Apurva Rajguru7360db42010-04-09 16:37:36 -07005529
5530 const char *str_effect = mParameters.get(CameraParameters::KEY_EFFECT);
5531 int32_t value_effect = attr_lookup(effects, sizeof(effects) / sizeof(str_map), str_effect);
5532
5533 if( (value_effect != CAMERA_EFFECT_MONO) && (value_effect != CAMERA_EFFECT_NEGATIVE)
5534 && (value_effect != CAMERA_EFFECT_AQUA) && (value_effect != CAMERA_EFFECT_SEPIA)) {
5535 const char *str = params.get(CameraParameters::KEY_WHITE_BALANCE);
5536
5537 if (str != NULL) {
5538 int32_t value = attr_lookup(whitebalance, sizeof(whitebalance) / sizeof(str_map), str);
5539 if (value != NOT_FOUND) {
5540 mParameters.set(CameraParameters::KEY_WHITE_BALANCE, str);
5541 bool ret = native_set_parm(CAMERA_SET_PARM_WB, sizeof(value),
5542 (void *)&value);
5543 return ret ? NO_ERROR : UNKNOWN_ERROR;
5544 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08005545 }
Apurva Rajguru7360db42010-04-09 16:37:36 -07005546 LOGE("Invalid whitebalance value: %s", (str == NULL) ? "NULL" : str);
5547 return BAD_VALUE;
5548 } else {
5549 LOGE("Whitebalance value will not be set " \
5550 "when the effect selected is %s", str_effect);
5551 return NO_ERROR;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08005552 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08005553}
5554
5555status_t QualcommCameraHardware::setFlash(const CameraParameters& params)
5556{
5557 if (!mSensorInfo.flash_enabled) {
5558 LOGV("%s: flash not supported", __FUNCTION__);
5559 return NO_ERROR;
5560 }
5561
5562 const char *str = params.get(CameraParameters::KEY_FLASH_MODE);
5563 if (str != NULL) {
5564 int32_t value = attr_lookup(flash, sizeof(flash) / sizeof(str_map), str);
5565 if (value != NOT_FOUND) {
5566 mParameters.set(CameraParameters::KEY_FLASH_MODE, str);
5567 bool ret = native_set_parm(CAMERA_SET_PARM_LED_MODE,
5568 sizeof(value), (void *)&value);
5569 return ret ? NO_ERROR : UNKNOWN_ERROR;
5570 }
5571 }
5572 LOGE("Invalid flash mode value: %s", (str == NULL) ? "NULL" : str);
5573 return BAD_VALUE;
5574}
5575
5576status_t QualcommCameraHardware::setAntibanding(const CameraParameters& params)
5577{
Nishant Pandit2eedc1b2010-09-25 04:47:39 +05305578 if((!strcmp(sensorType->name, "2mp")) || (!strcmp(sensorType->name, "ov7692"))) {
Srinivasan Kannan2229d272010-01-05 14:58:28 -08005579 LOGE("Parameter AntiBanding is not supported for this sensor");
5580 return NO_ERROR;
5581 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08005582 const char *str = params.get(CameraParameters::KEY_ANTIBANDING);
5583 if (str != NULL) {
5584 int value = (camera_antibanding_type)attr_lookup(
5585 antibanding, sizeof(antibanding) / sizeof(str_map), str);
5586 if (value != NOT_FOUND) {
5587 camera_antibanding_type temp = (camera_antibanding_type) value;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08005588 mParameters.set(CameraParameters::KEY_ANTIBANDING, str);
Srinivasan Kannan2229d272010-01-05 14:58:28 -08005589 bool ret;
5590 if (temp == CAMERA_ANTIBANDING_AUTO) {
5591 ret = native_set_parm(CAMERA_ENABLE_AFD,
5592 0, NULL);
5593 } else {
5594 ret = native_set_parm(CAMERA_SET_PARM_ANTIBANDING,
5595 sizeof(camera_antibanding_type), (void *)&temp);
5596 }
5597 return ret ? NO_ERROR : UNKNOWN_ERROR;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08005598 }
5599 }
5600 LOGE("Invalid antibanding value: %s", (str == NULL) ? "NULL" : str);
5601 return BAD_VALUE;
5602}
5603
Nishant Panditc8c1ee72009-12-03 16:24:02 +05305604status_t QualcommCameraHardware::setLensshadeValue(const CameraParameters& params)
5605{
Mohan Kandrace6bf562010-04-26 13:00:19 -07005606 if( (!strcmp(sensorType->name, "2mp")) ||
Nishant Pandit2eedc1b2010-09-25 04:47:39 +05305607 (!strcmp(sensorType->name, "ov7692")) ||
Nishant Pandit5ca94662010-09-15 03:25:09 +05305608 (!strcmp(sensorType->name, "12mp")) ||
Mohan Kandrace6bf562010-04-26 13:00:19 -07005609 (!strcmp(mSensorInfo.name, "vx6953")) ||
5610 (!strcmp(mSensorInfo.name, "VX6953")) ) {
Mohan Kandra1307f312010-04-29 10:18:42 -07005611 LOGI("Parameter Rolloff is not supported for this sensor");
Mohan Kandra93f1bfb2009-12-15 16:55:33 -08005612 return NO_ERROR;
5613 }
Nishant Panditc8c1ee72009-12-03 16:24:02 +05305614 const char *str = params.get(CameraParameters::KEY_LENSSHADE);
5615 if (str != NULL) {
5616 int value = attr_lookup(lensshade,
5617 sizeof(lensshade) / sizeof(str_map), str);
5618 if (value != NOT_FOUND) {
5619 int8_t temp = (int8_t)value;
5620 mParameters.set(CameraParameters::KEY_LENSSHADE, str);
Apurva Rajguru7b949c92010-05-26 15:46:57 -07005621
Nishant Panditc8c1ee72009-12-03 16:24:02 +05305622 native_set_parm(CAMERA_SET_PARM_ROLLOFF, sizeof(int8_t), (void *)&temp);
5623 return NO_ERROR;
5624 }
5625 }
5626 LOGE("Invalid lensShade value: %s", (str == NULL) ? "NULL" : str);
5627 return BAD_VALUE;
5628}
5629
Apurva Rajguru7b949c92010-05-26 15:46:57 -07005630status_t QualcommCameraHardware::setContinuousAf(const CameraParameters& params)
5631{
Apurva Rajguruf0593dd2010-07-27 17:50:23 -07005632 if(sensorType->hasAutoFocusSupport){
5633 const char *str = params.get(CameraParameters::KEY_CONTINUOUS_AF);
5634 if (str != NULL) {
5635 int value = attr_lookup(continuous_af,
5636 sizeof(continuous_af) / sizeof(str_map), str);
5637 if (value != NOT_FOUND) {
5638 int8_t temp = (int8_t)value;
5639 mParameters.set(CameraParameters::KEY_CONTINUOUS_AF, str);
Apurva Rajguru7b949c92010-05-26 15:46:57 -07005640
Apurva Rajguruf0593dd2010-07-27 17:50:23 -07005641 native_set_parm(CAMERA_SET_CAF, sizeof(int8_t), (void *)&temp);
5642 return NO_ERROR;
5643 }
Apurva Rajguru7b949c92010-05-26 15:46:57 -07005644 }
Apurva Rajguruf0593dd2010-07-27 17:50:23 -07005645 LOGE("Invalid continuous Af value: %s", (str == NULL) ? "NULL" : str);
5646 return BAD_VALUE;
Apurva Rajguru7b949c92010-05-26 15:46:57 -07005647 }
Apurva Rajguruf0593dd2010-07-27 17:50:23 -07005648 return NO_ERROR;
Apurva Rajguru7b949c92010-05-26 15:46:57 -07005649}
5650
Apurva Rajgurue5965c42010-09-09 14:24:54 -07005651status_t QualcommCameraHardware::setSelectableZoneAf(const CameraParameters& params)
5652{
5653 if(sensorType->hasAutoFocusSupport && supportsSelectableZoneAf()) {
5654 const char *str = params.get(CameraParameters::KEY_SELECTABLE_ZONE_AF);
5655 if (str != NULL) {
5656 int32_t value = attr_lookup(selectable_zone_af, sizeof(selectable_zone_af) / sizeof(str_map), str);
5657 if (value != NOT_FOUND) {
5658 mParameters.set(CameraParameters::KEY_SELECTABLE_ZONE_AF, str);
5659 bool ret = native_set_parm(CAMERA_SET_PARM_FOCUS_RECT, sizeof(value),
5660 (void *)&value);
5661 return ret ? NO_ERROR : UNKNOWN_ERROR;
5662 }
5663 }
5664 LOGE("Invalid selectable zone af value: %s", (str == NULL) ? "NULL" : str);
5665 return BAD_VALUE;
5666 }
5667 return NO_ERROR;
5668}
5669
Apurva Rajguru0a2cb922010-06-08 15:33:22 -07005670status_t QualcommCameraHardware::setTouchAfAec(const CameraParameters& params)
5671{
Apurva Rajguruf0593dd2010-07-27 17:50:23 -07005672 if(sensorType->hasAutoFocusSupport){
5673 int xAec, yAec, xAf, yAf;
Apurva Rajguru0a2cb922010-06-08 15:33:22 -07005674
Apurva Rajguruf0593dd2010-07-27 17:50:23 -07005675 params.getTouchIndexAec(&xAec, &yAec);
5676 params.getTouchIndexAf(&xAf, &yAf);
5677 const char *str = params.get(CameraParameters::KEY_TOUCH_AF_AEC);
Apurva Rajguru0a2cb922010-06-08 15:33:22 -07005678
Apurva Rajguruf0593dd2010-07-27 17:50:23 -07005679 if (str != NULL) {
5680 int value = attr_lookup(touchafaec,
5681 sizeof(touchafaec) / sizeof(str_map), str);
5682 if (value != NOT_FOUND) {
5683 mParameters.set(CameraParameters::KEY_TOUCH_AF_AEC, str);
5684 mParameters.setTouchIndexAec(xAec, yAec);
5685 mParameters.setTouchIndexAf(xAf, yAf);
Apurva Rajguru0a2cb922010-06-08 15:33:22 -07005686
Apurva Rajguruf0593dd2010-07-27 17:50:23 -07005687 cam_set_aec_roi_t aec_roi_value;
5688 roi_info_t af_roi_value;
Apurva Rajguru0a2cb922010-06-08 15:33:22 -07005689
Apurva Rajguruf0593dd2010-07-27 17:50:23 -07005690 memset(&af_roi_value, 0, sizeof(roi_info_t));
5691
5692 //If touch AF/AEC is enabled and touch event has occured then
5693 //call the ioctl with valid values.
5694
5695 if (value == true
5696 && (xAec >= 0 && yAec >= 0)
5697 && (xAf >= 0 && yAf >= 0)) {
5698 //Set Touch AEC params
5699 aec_roi_value.aec_roi_enable = AEC_ROI_ON;
5700 aec_roi_value.aec_roi_type = AEC_ROI_BY_COORDINATE;
5701 aec_roi_value.aec_roi_position.coordinate.x = xAec;
5702 aec_roi_value.aec_roi_position.coordinate.y = yAec;
5703
5704 //Set Touch AF params
5705 af_roi_value.num_roi = 1;
5706 af_roi_value.roi[0].x = xAf;
5707 af_roi_value.roi[0].y = yAf;
5708 af_roi_value.roi[0].dx = 100;
5709 af_roi_value.roi[0].dy = 100;
5710 }
5711 else {
5712 //Set Touch AEC params
5713 aec_roi_value.aec_roi_enable = AEC_ROI_OFF;
5714 aec_roi_value.aec_roi_type = AEC_ROI_BY_COORDINATE;
5715 aec_roi_value.aec_roi_position.coordinate.x = DONT_CARE_COORDINATE;
5716 aec_roi_value.aec_roi_position.coordinate.y = DONT_CARE_COORDINATE;
5717
5718 //Set Touch AF params
5719 af_roi_value.num_roi = 0;
5720 }
5721 native_set_parm(CAMERA_SET_PARM_AEC_ROI, sizeof(cam_set_aec_roi_t), (void *)&aec_roi_value);
5722 native_set_parm(CAMERA_SET_PARM_AF_ROI, sizeof(roi_info_t), (void*)&af_roi_value);
Apurva Rajguru0a2cb922010-06-08 15:33:22 -07005723 }
Apurva Rajguruf0593dd2010-07-27 17:50:23 -07005724 return NO_ERROR;
Apurva Rajguru0a2cb922010-06-08 15:33:22 -07005725 }
Apurva Rajguruf0593dd2010-07-27 17:50:23 -07005726 LOGE("Invalid Touch AF/AEC value: %s", (str == NULL) ? "NULL" : str);
5727 return BAD_VALUE;
Apurva Rajguru0a2cb922010-06-08 15:33:22 -07005728 }
Apurva Rajguruf0593dd2010-07-27 17:50:23 -07005729 return NO_ERROR;
Apurva Rajguru0a2cb922010-06-08 15:33:22 -07005730}
5731
Nishant Panditc8c1ee72009-12-03 16:24:02 +05305732status_t QualcommCameraHardware::setISOValue(const CameraParameters& params) {
Apurva Rajguruf12d9d22010-04-05 16:47:12 -07005733 int8_t temp_hjr;
Nishant Panditc8c1ee72009-12-03 16:24:02 +05305734 const char *str = params.get(CameraParameters::KEY_ISO_MODE);
5735 if (str != NULL) {
5736 int value = (camera_iso_mode_type)attr_lookup(
5737 iso, sizeof(iso) / sizeof(str_map), str);
5738 if (value != NOT_FOUND) {
5739 camera_iso_mode_type temp = (camera_iso_mode_type) value;
Apurva Rajguruf12d9d22010-04-05 16:47:12 -07005740 if (value == CAMERA_ISO_DEBLUR) {
5741 temp_hjr = true;
5742 native_set_parm(CAMERA_SET_PARM_HJR, sizeof(int8_t), (void*)&temp_hjr);
5743 mHJR = value;
5744 }
5745 else {
5746 if (mHJR == CAMERA_ISO_DEBLUR) {
5747 temp_hjr = false;
5748 native_set_parm(CAMERA_SET_PARM_HJR, sizeof(int8_t), (void*)&temp_hjr);
5749 mHJR = value;
5750 }
5751 }
5752
Nishant Panditc8c1ee72009-12-03 16:24:02 +05305753 mParameters.set(CameraParameters::KEY_ISO_MODE, str);
5754 native_set_parm(CAMERA_SET_PARM_ISO, sizeof(camera_iso_mode_type), (void *)&temp);
5755 return NO_ERROR;
5756 }
5757 }
5758 LOGE("Invalid Iso value: %s", (str == NULL) ? "NULL" : str);
5759 return BAD_VALUE;
5760}
5761
Apurva Rajguru8e0a8da2010-06-02 11:26:36 -07005762status_t QualcommCameraHardware::setSceneDetect(const CameraParameters& params)
5763{
5764
5765 bool retParm1, retParm2;
5766 if (supportsSceneDetection()) {
Nishant Pandit2eedc1b2010-09-25 04:47:39 +05305767 if((!strcmp(sensorType->name, "2mp")) || (!strcmp(sensorType->name, "ov7692"))) {
Apurva Rajguru0d400562010-09-13 14:12:02 -07005768 LOGI("Parameter Auto Scene Detection is not supported for this sensor");
5769 return NO_ERROR;
5770 }
Apurva Rajguru8e0a8da2010-06-02 11:26:36 -07005771 const char *str = params.get(CameraParameters::KEY_SCENE_DETECT);
5772 if (str != NULL) {
5773 int32_t value = attr_lookup(scenedetect, sizeof(scenedetect) / sizeof(str_map), str);
5774 if (value != NOT_FOUND) {
5775 mParameters.set(CameraParameters::KEY_SCENE_DETECT, str);
5776
5777 retParm1 = native_set_parm(CAMERA_SET_PARM_BL_DETECTION_ENABLE, sizeof(value),
5778 (void *)&value);
5779
5780 retParm2 = native_set_parm(CAMERA_SET_PARM_SNOW_DETECTION_ENABLE, sizeof(value),
5781 (void *)&value);
5782
5783 //All Auto Scene detection modes should be all ON or all OFF.
5784 if(retParm1 == false || retParm2 == false) {
5785 value = !value;
5786 retParm1 = native_set_parm(CAMERA_SET_PARM_BL_DETECTION_ENABLE, sizeof(value),
5787 (void *)&value);
5788
5789 retParm2 = native_set_parm(CAMERA_SET_PARM_SNOW_DETECTION_ENABLE, sizeof(value),
5790 (void *)&value);
5791 }
5792 return (retParm1 && retParm2) ? NO_ERROR : UNKNOWN_ERROR;
5793 }
5794 }
5795 LOGE("Invalid auto scene detection value: %s", (str == NULL) ? "NULL" : str);
5796 return BAD_VALUE;
5797 }
5798 return NO_ERROR;
5799}
Nishant Panditc8c1ee72009-12-03 16:24:02 +05305800
Apurva Rajguru08383852010-05-17 14:25:39 -07005801status_t QualcommCameraHardware::setSceneMode(const CameraParameters& params)
5802{
Apurva Rajguruf0593dd2010-07-27 17:50:23 -07005803
Nishant Pandit2eedc1b2010-09-25 04:47:39 +05305804 if((!strcmp(sensorType->name, "2mp")) || (!strcmp(sensorType->name, "ov7692"))) {
Apurva Rajguruf0593dd2010-07-27 17:50:23 -07005805 LOGI("Parameter Scenemode is not supported for this sensor");
5806 return NO_ERROR;
5807 }
5808
Apurva Rajguru08383852010-05-17 14:25:39 -07005809 const char *str = params.get(CameraParameters::KEY_SCENE_MODE);
5810
5811 if (str != NULL) {
5812 int32_t value = attr_lookup(scenemode, sizeof(scenemode) / sizeof(str_map), str);
5813 if (value != NOT_FOUND) {
5814 mParameters.set(CameraParameters::KEY_SCENE_MODE, str);
5815 bool ret = native_set_parm(CAMERA_SET_PARM_BESTSHOT_MODE, sizeof(value),
5816 (void *)&value);
5817 return ret ? NO_ERROR : UNKNOWN_ERROR;
5818 }
5819 }
5820 LOGE("Invalid scenemode value: %s", (str == NULL) ? "NULL" : str);
5821 return BAD_VALUE;
5822}
Priya Komarlingamb85535d2009-11-30 13:06:01 -08005823status_t QualcommCameraHardware::setGpsLocation(const CameraParameters& params)
5824{
Srinivasan Kannan09de3382010-08-16 16:42:00 -07005825 const char *method = params.get(CameraParameters::KEY_GPS_PROCESSING_METHOD);
5826 if (method) {
5827 mParameters.set(CameraParameters::KEY_GPS_PROCESSING_METHOD, method);
5828 }
5829
Priya Komarlingamb85535d2009-11-30 13:06:01 -08005830 const char *latitude = params.get(CameraParameters::KEY_GPS_LATITUDE);
5831 if (latitude) {
5832 mParameters.set(CameraParameters::KEY_GPS_LATITUDE, latitude);
5833 }
5834
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08005835 const char *latitudeRef = params.get(CameraParameters::KEY_GPS_LATITUDE_REF);
5836 if (latitudeRef) {
5837 mParameters.set(CameraParameters::KEY_GPS_LATITUDE_REF, latitudeRef);
5838 }
5839
Priya Komarlingamb85535d2009-11-30 13:06:01 -08005840 const char *longitude = params.get(CameraParameters::KEY_GPS_LONGITUDE);
5841 if (longitude) {
5842 mParameters.set(CameraParameters::KEY_GPS_LONGITUDE, longitude);
5843 }
5844
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08005845 const char *longitudeRef = params.get(CameraParameters::KEY_GPS_LONGITUDE_REF);
5846 if (longitudeRef) {
5847 mParameters.set(CameraParameters::KEY_GPS_LONGITUDE_REF, longitudeRef);
5848 }
5849
5850 const char *altitudeRef = params.get(CameraParameters::KEY_GPS_ALTITUDE_REF);
5851 if (altitudeRef) {
5852 mParameters.set(CameraParameters::KEY_GPS_ALTITUDE_REF, altitudeRef);
5853 }
5854
Priya Komarlingamb85535d2009-11-30 13:06:01 -08005855 const char *altitude = params.get(CameraParameters::KEY_GPS_ALTITUDE);
5856 if (altitude) {
5857 mParameters.set(CameraParameters::KEY_GPS_ALTITUDE, altitude);
5858 }
5859
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08005860 const char *status = params.get(CameraParameters::KEY_GPS_STATUS);
5861 if (status) {
5862 mParameters.set(CameraParameters::KEY_GPS_STATUS, status);
5863 }
5864
5865 const char *dateTime = params.get(CameraParameters::KEY_EXIF_DATETIME);
5866 if (dateTime) {
5867 mParameters.set(CameraParameters::KEY_EXIF_DATETIME, dateTime);
5868 }
5869
Priya Komarlingamb85535d2009-11-30 13:06:01 -08005870 const char *timestamp = params.get(CameraParameters::KEY_GPS_TIMESTAMP);
5871 if (timestamp) {
5872 mParameters.set(CameraParameters::KEY_GPS_TIMESTAMP, timestamp);
5873 }
5874 return NO_ERROR;
5875}
5876
5877status_t QualcommCameraHardware::setRotation(const CameraParameters& params)
5878{
5879 status_t rc = NO_ERROR;
5880 int rotation = params.getInt(CameraParameters::KEY_ROTATION);
5881 if (rotation != NOT_FOUND) {
5882 if (rotation == 0 || rotation == 90 || rotation == 180
5883 || rotation == 270) {
5884 mParameters.set(CameraParameters::KEY_ROTATION, rotation);
Mohan Kandra39fad8d2010-07-15 12:29:19 -07005885 mRotation = rotation;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08005886 } else {
5887 LOGE("Invalid rotation value: %d", rotation);
5888 rc = BAD_VALUE;
5889 }
5890 }
5891 return rc;
5892}
5893
5894status_t QualcommCameraHardware::setZoom(const CameraParameters& params)
5895{
5896 status_t rc = NO_ERROR;
5897 // No matter how many different zoom values the driver can provide, HAL
5898 // provides applictations the same number of zoom levels. The maximum driver
5899 // zoom value depends on sensor output (VFE input) and preview size (VFE
5900 // output) because VFE can only crop and cannot upscale. If the preview size
5901 // is bigger, the maximum zoom ratio is smaller. However, we want the
5902 // zoom ratio of each zoom level is always the same whatever the preview
5903 // size is. Ex: zoom level 1 is always 1.2x, zoom level 2 is 1.44x, etc. So,
5904 // we need to have a fixed maximum zoom value and do read it from the
5905 // driver.
Mohan Kandra284966d2010-01-05 13:39:15 -08005906 static const int ZOOM_STEP = 1;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08005907 int32_t zoom_level = params.getInt("zoom");
5908
Mohan Kandra284966d2010-01-05 13:39:15 -08005909 LOGV("Set zoom=%d", zoom_level);
5910 if(zoom_level >= 0 && zoom_level <= mMaxZoom) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08005911 mParameters.set("zoom", zoom_level);
5912 int32_t zoom_value = ZOOM_STEP * zoom_level;
5913 bool ret = native_set_parm(CAMERA_SET_PARM_ZOOM,
5914 sizeof(zoom_value), (void *)&zoom_value);
5915 rc = ret ? NO_ERROR : UNKNOWN_ERROR;
5916 } else {
5917 rc = BAD_VALUE;
5918 }
5919
5920 return rc;
5921}
5922
5923status_t QualcommCameraHardware::setFocusMode(const CameraParameters& params)
5924{
5925 const char *str = params.get(CameraParameters::KEY_FOCUS_MODE);
5926 if (str != NULL) {
5927 int32_t value = attr_lookup(focus_modes,
5928 sizeof(focus_modes) / sizeof(str_map), str);
5929 if (value != NOT_FOUND) {
5930 mParameters.set(CameraParameters::KEY_FOCUS_MODE, str);
5931 // Focus step is reset to infinity when preview is started. We do
5932 // not need to do anything now.
5933 return NO_ERROR;
5934 }
5935 }
5936 LOGE("Invalid focus mode value: %s", (str == NULL) ? "NULL" : str);
5937 return BAD_VALUE;
5938}
5939
5940status_t QualcommCameraHardware::setOrientation(const CameraParameters& params)
5941{
5942 const char *str = params.get("orientation");
5943
5944 if (str != NULL) {
5945 if (strcmp(str, "portrait") == 0 || strcmp(str, "landscape") == 0) {
5946 // Camera service needs this to decide if the preview frames and raw
5947 // pictures should be rotated.
5948 mParameters.set("orientation", str);
5949 } else {
5950 LOGE("Invalid orientation value: %s", str);
5951 return BAD_VALUE;
5952 }
5953 }
5954 return NO_ERROR;
5955}
5956
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08005957status_t QualcommCameraHardware::setPictureFormat(const CameraParameters& params)
5958{
5959 const char * str = params.get(CameraParameters::KEY_PICTURE_FORMAT);
5960
5961 if(str != NULL){
5962 int32_t value = attr_lookup(picture_formats,
5963 sizeof(picture_formats) / sizeof(str_map), str);
5964 if(value != NOT_FOUND){
5965 mParameters.set(CameraParameters::KEY_PICTURE_FORMAT, str);
5966 } else {
5967 LOGE("Invalid Picture Format value: %s", str);
5968 return BAD_VALUE;
5969 }
5970 }
5971 return NO_ERROR;
5972}
5973
Priya Komarlingamb85535d2009-11-30 13:06:01 -08005974QualcommCameraHardware::MemPool::MemPool(int buffer_size, int num_buffers,
5975 int frame_size,
5976 const char *name) :
5977 mBufferSize(buffer_size),
5978 mNumBuffers(num_buffers),
5979 mFrameSize(frame_size),
5980 mBuffers(NULL), mName(name)
5981{
5982 int page_size_minus_1 = getpagesize() - 1;
5983 mAlignedBufferSize = (buffer_size + page_size_minus_1) & (~page_size_minus_1);
5984}
5985
5986void QualcommCameraHardware::MemPool::completeInitialization()
5987{
5988 // If we do not know how big the frame will be, we wait to allocate
5989 // the buffers describing the individual frames until we do know their
5990 // size.
5991
5992 if (mFrameSize > 0) {
5993 mBuffers = new sp<MemoryBase>[mNumBuffers];
5994 for (int i = 0; i < mNumBuffers; i++) {
5995 mBuffers[i] = new
5996 MemoryBase(mHeap,
5997 i * mAlignedBufferSize,
5998 mFrameSize);
5999 }
6000 }
6001}
6002
6003QualcommCameraHardware::AshmemPool::AshmemPool(int buffer_size, int num_buffers,
6004 int frame_size,
6005 const char *name) :
6006 QualcommCameraHardware::MemPool(buffer_size,
6007 num_buffers,
6008 frame_size,
6009 name)
6010{
6011 LOGV("constructing MemPool %s backed by ashmem: "
6012 "%d frames @ %d uint8_ts, "
6013 "buffer size %d",
6014 mName,
6015 num_buffers, frame_size, buffer_size);
6016
6017 int page_mask = getpagesize() - 1;
6018 int ashmem_size = buffer_size * num_buffers;
6019 ashmem_size += page_mask;
6020 ashmem_size &= ~page_mask;
6021
6022 mHeap = new MemoryHeapBase(ashmem_size);
6023
6024 completeInitialization();
6025}
6026
6027static bool register_buf(int camfd,
6028 int size,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08006029 int frame_size,
Mohan Kandra02486042010-06-18 16:49:43 -07006030 int cbcr_offset,
6031 int yoffset,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08006032 int pmempreviewfd,
6033 uint32_t offset,
6034 uint8_t *buf,
6035 int pmem_type,
6036 bool vfe_can_write,
6037 bool register_buffer = true);
6038
6039QualcommCameraHardware::PmemPool::PmemPool(const char *pmem_pool,
6040 int flags,
6041 int camera_control_fd,
6042 int pmem_type,
6043 int buffer_size, int num_buffers,
Mohan Kandra02486042010-06-18 16:49:43 -07006044 int frame_size, int cbcr_offset,
6045 int yOffset, const char *name) :
Priya Komarlingamb85535d2009-11-30 13:06:01 -08006046 QualcommCameraHardware::MemPool(buffer_size,
6047 num_buffers,
6048 frame_size,
6049 name),
6050 mPmemType(pmem_type),
Mohan Kandra02486042010-06-18 16:49:43 -07006051 mCbCrOffset(cbcr_offset),
6052 myOffset(yOffset),
Priya Komarlingamb85535d2009-11-30 13:06:01 -08006053 mCameraControlFd(dup(camera_control_fd))
6054{
6055 LOGV("constructing MemPool %s backed by pmem pool %s: "
6056 "%d frames @ %d bytes, buffer size %d",
6057 mName,
6058 pmem_pool, num_buffers, frame_size,
6059 buffer_size);
6060
6061 LOGV("%s: duplicating control fd %d --> %d",
6062 __FUNCTION__,
6063 camera_control_fd, mCameraControlFd);
6064
6065 // Make a new mmap'ed heap that can be shared across processes.
6066 // mAlignedBufferSize is already in 4k aligned. (do we need total size necessary to be in power of 2??)
6067 mAlignedSize = mAlignedBufferSize * num_buffers;
6068
6069 sp<MemoryHeapBase> masterHeap =
6070 new MemoryHeapBase(pmem_pool, mAlignedSize, flags);
6071
6072 if (masterHeap->getHeapID() < 0) {
6073 LOGE("failed to construct master heap for pmem pool %s", pmem_pool);
6074 masterHeap.clear();
6075 return;
6076 }
6077
6078 sp<MemoryHeapPmem> pmemHeap = new MemoryHeapPmem(masterHeap, flags);
6079 if (pmemHeap->getHeapID() >= 0) {
6080 pmemHeap->slap();
6081 masterHeap.clear();
6082 mHeap = pmemHeap;
6083 pmemHeap.clear();
6084
6085 mFd = mHeap->getHeapID();
6086 if (::ioctl(mFd, PMEM_GET_SIZE, &mSize)) {
6087 LOGE("pmem pool %s ioctl(PMEM_GET_SIZE) error %s (%d)",
6088 pmem_pool,
6089 ::strerror(errno), errno);
6090 mHeap.clear();
6091 return;
6092 }
6093
6094 LOGV("pmem pool %s ioctl(fd = %d, PMEM_GET_SIZE) is %ld",
6095 pmem_pool,
6096 mFd,
6097 mSize.len);
Mohan Kandra284966d2010-01-05 13:39:15 -08006098 LOGD("mBufferSize=%d, mAlignedBufferSize=%d\n", mBufferSize, mAlignedBufferSize);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08006099 // Unregister preview buffers with the camera drivers. Allow the VFE to write
6100 // to all preview buffers except for the last one.
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08006101 // Only Register the preview, snapshot and thumbnail buffers with the kernel.
Mohan Kandrad9efed92010-01-15 19:08:39 -08006102 if( (strcmp("postview", mName) != 0) ){
6103 int num_buf = num_buffers;
6104 if(!strcmp("preview", mName)) num_buf = kPreviewBufferCount;
Brian Steuerb62adbd2010-02-02 14:47:08 -08006105 LOGD("num_buffers = %d", num_buf);
Mohan Kandrad9efed92010-01-15 19:08:39 -08006106 for (int cnt = 0; cnt < num_buf; ++cnt) {
Sravankb4f5f1c2010-01-21 11:06:17 +05306107 int active = 1;
6108 if(pmem_type == MSM_PMEM_VIDEO){
6109 active = (cnt<ACTIVE_VIDEO_BUFFERS);
Mohan Kandra39fad8d2010-07-15 12:29:19 -07006110 //When VPE is enabled, set the last record
6111 //buffer as active and pmem type as PMEM_VIDEO_VPE
6112 //as this is a requirement from VPE operation.
Mohan Kandra88db27a2010-08-22 12:33:36 -07006113 //No need to set this pmem type to VIDEO_VPE while unregistering,
6114 //because as per camera stack design: "the VPE AXI is also configured
6115 //when VFE is configured for VIDEO, which is as part of preview
6116 //initialization/start. So during this VPE AXI config camera stack
6117 //will lookup the PMEM_VIDEO_VPE buffer and give it as o/p of VPE and
6118 //change it's type to PMEM_VIDEO".
Mohan Kandra39fad8d2010-07-15 12:29:19 -07006119 if( (mVpeEnabled) && (cnt == kRecordBufferCount-1)) {
6120 active = 1;
6121 pmem_type = MSM_PMEM_VIDEO_VPE;
6122 }
Sravankb4f5f1c2010-01-21 11:06:17 +05306123 LOGV(" pmempool creating video buffers : active %d ", active);
6124 }
6125 else if (pmem_type == MSM_PMEM_PREVIEW){
6126 active = (cnt < (num_buf-1));
6127 }
Mohan Kandra284966d2010-01-05 13:39:15 -08006128 register_buf(mCameraControlFd,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08006129 mBufferSize,
Mohan Kandra02486042010-06-18 16:49:43 -07006130 mFrameSize, mCbCrOffset, myOffset,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08006131 mHeap->getHeapID(),
6132 mAlignedBufferSize * cnt,
6133 (uint8_t *)mHeap->base() + mAlignedBufferSize * cnt,
6134 pmem_type,
Sravankb4f5f1c2010-01-21 11:06:17 +05306135 active);
Mohan Kandra284966d2010-01-05 13:39:15 -08006136 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08006137 }
6138
6139 completeInitialization();
6140 }
6141 else LOGE("pmem pool %s error: could not create master heap!",
6142 pmem_pool);
6143}
6144
6145QualcommCameraHardware::PmemPool::~PmemPool()
6146{
6147 LOGV("%s: %s E", __FUNCTION__, mName);
6148 if (mHeap != NULL) {
6149 // Unregister preview buffers with the camera drivers.
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08006150 // Only Unregister the preview, snapshot and thumbnail
6151 // buffers with the kernel.
Mohan Kandrad9efed92010-01-15 19:08:39 -08006152 if( (strcmp("postview", mName) != 0) ){
6153 int num_buffers = mNumBuffers;
6154 if(!strcmp("preview", mName)) num_buffers = kPreviewBufferCount;
6155 for (int cnt = 0; cnt < num_buffers; ++cnt) {
Mohan Kandra284966d2010-01-05 13:39:15 -08006156 register_buf(mCameraControlFd,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08006157 mBufferSize,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08006158 mFrameSize,
Mohan Kandra02486042010-06-18 16:49:43 -07006159 mCbCrOffset,
6160 myOffset,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08006161 mHeap->getHeapID(),
6162 mAlignedBufferSize * cnt,
6163 (uint8_t *)mHeap->base() + mAlignedBufferSize * cnt,
6164 mPmemType,
6165 false,
6166 false /* unregister */);
Mohan Kandra284966d2010-01-05 13:39:15 -08006167 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08006168 }
6169 }
6170 LOGV("destroying PmemPool %s: closing control fd %d",
6171 mName,
6172 mCameraControlFd);
6173 close(mCameraControlFd);
6174 LOGV("%s: %s X", __FUNCTION__, mName);
6175}
6176
6177QualcommCameraHardware::MemPool::~MemPool()
6178{
6179 LOGV("destroying MemPool %s", mName);
6180 if (mFrameSize > 0)
6181 delete [] mBuffers;
6182 mHeap.clear();
6183 LOGV("destroying MemPool %s completed", mName);
6184}
6185
6186static bool register_buf(int camfd,
6187 int size,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08006188 int frame_size,
Mohan Kandra02486042010-06-18 16:49:43 -07006189 int cbcr_offset,
6190 int yoffset,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08006191 int pmempreviewfd,
6192 uint32_t offset,
6193 uint8_t *buf,
6194 int pmem_type,
6195 bool vfe_can_write,
6196 bool register_buffer)
6197{
6198 struct msm_pmem_info pmemBuf;
6199
6200 pmemBuf.type = pmem_type;
6201 pmemBuf.fd = pmempreviewfd;
6202 pmemBuf.offset = offset;
6203 pmemBuf.len = size;
6204 pmemBuf.vaddr = buf;
Mohan Kandra02486042010-06-18 16:49:43 -07006205 pmemBuf.y_off = yoffset;
6206 pmemBuf.cbcr_off = cbcr_offset;
Srinivasan Kannanb36a4fe2010-01-29 19:34:09 -08006207
Priya Komarlingamb85535d2009-11-30 13:06:01 -08006208 pmemBuf.active = vfe_can_write;
6209
6210 LOGV("register_buf: camfd = %d, reg = %d buffer = %p",
6211 camfd, !register_buffer, buf);
6212 if (ioctl(camfd,
6213 register_buffer ?
6214 MSM_CAM_IOCTL_REGISTER_PMEM :
6215 MSM_CAM_IOCTL_UNREGISTER_PMEM,
6216 &pmemBuf) < 0) {
6217 LOGE("register_buf: MSM_CAM_IOCTL_(UN)REGISTER_PMEM fd %d error %s",
6218 camfd,
6219 strerror(errno));
6220 return false;
6221 }
6222 return true;
6223}
6224
6225status_t QualcommCameraHardware::MemPool::dump(int fd, const Vector<String16>& args) const
6226{
6227 const size_t SIZE = 256;
6228 char buffer[SIZE];
6229 String8 result;
6230 snprintf(buffer, 255, "QualcommCameraHardware::AshmemPool::dump\n");
6231 result.append(buffer);
6232 if (mName) {
6233 snprintf(buffer, 255, "mem pool name (%s)\n", mName);
6234 result.append(buffer);
6235 }
6236 if (mHeap != 0) {
6237 snprintf(buffer, 255, "heap base(%p), size(%d), flags(%d), device(%s)\n",
6238 mHeap->getBase(), mHeap->getSize(),
6239 mHeap->getFlags(), mHeap->getDevice());
6240 result.append(buffer);
6241 }
6242 snprintf(buffer, 255,
6243 "buffer size (%d), number of buffers (%d), frame size(%d)",
6244 mBufferSize, mNumBuffers, mFrameSize);
6245 result.append(buffer);
6246 write(fd, result.string(), result.size());
6247 return NO_ERROR;
6248}
6249
6250static void receive_camframe_callback(struct msm_frame *frame)
6251{
6252 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
6253 if (obj != 0) {
6254 obj->receivePreviewFrame(frame);
6255 }
6256}
6257
Nishant Pandit741742b2010-09-21 03:24:20 +05306258static void receive_camstats_callback(camstats_type stype, camera_preview_histogram_info* histinfo)
6259{
6260 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
6261 if (obj != 0) {
6262 obj->receiveCameraStats(stype,histinfo);
6263 }
6264}
6265
Vamshidhar Kondra92ce9142010-09-03 18:22:08 +05306266static void receive_liveshot_callback(liveshot_status status, uint32_t jpeg_size)
6267{
6268 if(status == LIVESHOT_SUCCESS) {
6269 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
6270 if (obj != 0) {
6271 obj->receiveLiveSnapshot(jpeg_size);
6272 }
6273 }
6274 else
6275 LOGE("Liveshot not succesful");
6276}
6277
6278
Priya Komarlingamb85535d2009-11-30 13:06:01 -08006279static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size)
6280{
6281 LOGV("receive_jpeg_fragment_callback E");
6282 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
6283 if (obj != 0) {
6284 obj->receiveJpegPictureFragment(buff_ptr, buff_size);
6285 }
6286 LOGV("receive_jpeg_fragment_callback X");
6287}
6288
6289static void receive_jpeg_callback(jpeg_event_t status)
6290{
6291 LOGV("receive_jpeg_callback E (completion status %d)", status);
6292 if (status == JPEG_EVENT_DONE) {
6293 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
6294 if (obj != 0) {
6295 obj->receiveJpegPicture();
6296 }
6297 }
6298 LOGV("receive_jpeg_callback X");
6299}
Sravankb4f5f1c2010-01-21 11:06:17 +05306300// 720p : video frame calbback from camframe
6301static void receive_camframe_video_callback(struct msm_frame *frame)
6302{
6303 LOGV("receive_camframe_video_callback E");
6304 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
6305 if (obj != 0) {
6306 obj->receiveRecordingFrame(frame);
6307 }
6308 LOGV("receive_camframe_video_callback X");
6309}
Priya Komarlingamb85535d2009-11-30 13:06:01 -08006310
6311void QualcommCameraHardware::setCallbacks(notify_callback notify_cb,
6312 data_callback data_cb,
6313 data_callback_timestamp data_cb_timestamp,
6314 void* user)
6315{
6316 Mutex::Autolock lock(mLock);
6317 mNotifyCallback = notify_cb;
6318 mDataCallback = data_cb;
6319 mDataCallbackTimestamp = data_cb_timestamp;
6320 mCallbackCookie = user;
6321}
6322
6323void QualcommCameraHardware::enableMsgType(int32_t msgType)
6324{
6325 Mutex::Autolock lock(mLock);
6326 mMsgEnabled |= msgType;
6327}
6328
6329void QualcommCameraHardware::disableMsgType(int32_t msgType)
6330{
6331 Mutex::Autolock lock(mLock);
6332 mMsgEnabled &= ~msgType;
6333}
6334
6335bool QualcommCameraHardware::msgTypeEnabled(int32_t msgType)
6336{
6337 return (mMsgEnabled & msgType);
6338}
6339
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08006340bool QualcommCameraHardware::useOverlay(void)
6341{
Nishant Pandit3c278cd2010-07-13 15:56:04 +05306342 if((mCurrentTarget == TARGET_MSM7630) || (mCurrentTarget == TARGET_MSM8660)) {
6343 /* 7x30 and 8x60 supports Overlay */
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08006344 mUseOverlay = TRUE;
6345 } else
6346 mUseOverlay = FALSE;
6347
6348 LOGV(" Using Overlay : %s ", mUseOverlay ? "YES" : "NO" );
6349 return mUseOverlay;
6350}
6351
6352status_t QualcommCameraHardware::setOverlay(const sp<Overlay> &Overlay)
6353{
6354 if( Overlay != NULL) {
6355 LOGV(" Valid overlay object ");
6356 mOverlayLock.lock();
6357 mOverlay = Overlay;
6358 mOverlayLock.unlock();
6359 } else {
Apurva Rajguruc73c1722010-04-15 17:39:11 -07006360 LOGV(" Overlay object NULL. returning ");
Mohan Kandrad9efed92010-01-15 19:08:39 -08006361 mOverlay = NULL;
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08006362 return UNKNOWN_ERROR;
6363 }
6364 return NO_ERROR;
6365}
Kiran Kumar H N215cac42009-12-08 01:53:46 -08006366
Mohan Kandra3dd524f2010-09-20 13:41:42 -07006367void QualcommCameraHardware::receive_camframe_error_timeout(void) {
6368 LOGI("receive_camframe_error_timeout: E");
Kiran Kumar H N215cac42009-12-08 01:53:46 -08006369 Mutex::Autolock l(&mCamframeTimeoutLock);
Mohan Kandra1307f312010-04-29 10:18:42 -07006370 LOGE(" Camframe timed out. Not receiving any frames from camera driver ");
Kiran Kumar H N215cac42009-12-08 01:53:46 -08006371 camframe_timeout_flag = TRUE;
Priyanka Kharatae03c212010-05-19 15:32:50 -07006372 mNotifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_UKNOWN, 0,
6373 mCallbackCookie);
Mohan Kandra3dd524f2010-09-20 13:41:42 -07006374 LOGI("receive_camframe_error_timeout: X");
Kiran Kumar H N215cac42009-12-08 01:53:46 -08006375}
6376
Mohan Kandra3dd524f2010-09-20 13:41:42 -07006377static void receive_camframe_error_callback(camera_error_type err) {
Kiran Kumar H N215cac42009-12-08 01:53:46 -08006378 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
6379 if (obj != 0) {
Mohan Kandra3dd524f2010-09-20 13:41:42 -07006380 if ((err == CAMERA_ERROR_TIMEOUT) ||
6381 (err == CAMERA_ERROR_ESD)) {
6382 /* Handling different error types is dependent on the requirement.
6383 * Do the same action by default
6384 */
6385 obj->receive_camframe_error_timeout();
6386 }
Kiran Kumar H N215cac42009-12-08 01:53:46 -08006387 }
6388}
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08006389
6390void QualcommCameraHardware::storePreviewFrameForPostview(void) {
6391 LOGV(" storePreviewFrameForPostview : E ");
6392
6393 /* Since there is restriction on the maximum overlay dimensions
6394 * that can be created, we use the last preview frame as postview
6395 * for 7x30. */
6396 LOGV(" Copying the preview buffer to postview buffer %d ",
6397 mPreviewFrameSize);
6398 if( mPostViewHeap != NULL && mLastQueuedFrame != NULL) {
6399 memcpy(mPostViewHeap->mHeap->base(),
6400 (uint8_t *)mLastQueuedFrame, mPreviewFrameSize );
6401 } else
6402 LOGE(" Failed to store Preview frame. No Postview ");
6403
6404 LOGV(" storePreviewFrameForPostview : X ");
6405}
Kiran Kumar H Nb49af212010-02-17 15:12:17 -08006406
6407bool QualcommCameraHardware::isValidDimension(int width, int height) {
6408 bool retVal = FALSE;
6409 /* This function checks if a given resolution is valid or not.
6410 * A particular resolution is considered valid if it satisfies
6411 * the following conditions:
6412 * 1. width & height should be multiple of 16.
6413 * 2. width & height should be less than/equal to the dimensions
6414 * supported by the camera sensor.
6415 * 3. the aspect ratio is a valid aspect ratio and is among the
6416 * commonly used aspect ratio as determined by the thumbnail_sizes
6417 * data structure.
6418 */
6419
6420 if( (width == CEILING16(width)) && (height == CEILING16(height))
6421 && (width <= sensorType->max_supported_snapshot_width)
6422 && (height <= sensorType->max_supported_snapshot_height) )
6423 {
6424 uint32_t pictureAspectRatio = (uint32_t)((width * Q12)/height);
Mohan Kandra62429cc2010-07-19 10:21:05 -07006425 for(uint32_t i = 0; i < THUMBNAIL_SIZE_COUNT; i++ ) {
Kiran Kumar H Nb49af212010-02-17 15:12:17 -08006426 if(thumbnail_sizes[i].aspect_ratio == pictureAspectRatio) {
6427 retVal = TRUE;
6428 break;
6429 }
6430 }
6431 }
6432 return retVal;
6433}
Kiran Kumar H N4dd45a62010-02-26 15:56:33 -08006434status_t QualcommCameraHardware::getBufferInfo(sp<IMemory>& Frame, size_t *alignedSize) {
6435 status_t ret;
6436 LOGV(" getBufferInfo : E ");
Nishant Pandit3c278cd2010-07-13 15:56:04 +05306437 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250) || (mCurrentTarget == TARGET_MSM8660) )
Vamshidhar Kondrab362be62010-03-22 19:07:29 +05306438 {
6439 if( mRecordHeap != NULL){
6440 LOGV(" Setting valid buffer information ");
6441 Frame = mRecordHeap->mBuffers[0];
6442 if( alignedSize != NULL) {
6443 *alignedSize = mRecordHeap->mAlignedBufferSize;
6444 LOGV(" HAL : alignedSize = %d ", *alignedSize);
6445 ret = NO_ERROR;
6446 } else {
6447 LOGE(" HAL : alignedSize is NULL. Cannot update alignedSize ");
6448 ret = UNKNOWN_ERROR;
6449 }
Kiran Kumar H N4dd45a62010-02-26 15:56:33 -08006450 } else {
Vamshidhar Kondrab362be62010-03-22 19:07:29 +05306451 LOGE(" RecordHeap is null. Buffer information wont be updated ");
6452 Frame = NULL;
6453 ret = UNKNOWN_ERROR;
6454 }
Kiran Kumar H N4dd45a62010-02-26 15:56:33 -08006455 } else {
Vamshidhar Kondrab362be62010-03-22 19:07:29 +05306456 if(mPreviewHeap != NULL) {
6457 LOGV(" Setting valid buffer information ");
6458 Frame = mPreviewHeap->mBuffers[0];
6459 if( alignedSize != NULL) {
6460 *alignedSize = mPreviewHeap->mAlignedBufferSize;
6461 LOGV(" HAL : alignedSize = %d ", *alignedSize);
6462 ret = NO_ERROR;
6463 } else {
6464 LOGE(" HAL : alignedSize is NULL. Cannot update alignedSize ");
6465 ret = UNKNOWN_ERROR;
6466 }
6467 } else {
6468 LOGE(" PreviewHeap is null. Buffer information wont be updated ");
6469 Frame = NULL;
6470 ret = UNKNOWN_ERROR;
6471 }
Kiran Kumar H N4dd45a62010-02-26 15:56:33 -08006472 }
6473 LOGV(" getBufferInfo : X ");
6474 return ret;
6475}
Kiran Kumar H Nb49af212010-02-17 15:12:17 -08006476
Mohan Kandra1659b0c2010-07-18 16:36:25 -07006477void QualcommCameraHardware::encodeData() {
6478 LOGV("encodeData: E");
6479
6480 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
6481 mJpegSize = 0;
6482 mJpegThreadWaitLock.lock();
6483 if (LINK_jpeg_encoder_init()) {
6484 mJpegThreadRunning = true;
6485 mJpegThreadWaitLock.unlock();
6486 if(native_jpeg_encode()) {
6487 LOGV("encodeData: X (success)");
6488 //Wait until jpeg encoding is done and call jpeg join
6489 //in this context. Also clear the resources.
6490 mJpegThreadWaitLock.lock();
6491 while (mJpegThreadRunning) {
6492 LOGV("encodeData: waiting for jpeg thread to complete.");
6493 mJpegThreadWait.wait(mJpegThreadWaitLock);
6494 LOGV("encodeData: jpeg thread completed.");
6495 }
6496 mJpegThreadWaitLock.unlock();
6497 //Call jpeg join in this thread context
6498 LINK_jpeg_encoder_join();
6499 }
6500 LOGE("encodeData: jpeg encoding failed");
6501 }
6502 else {
6503 LOGE("encodeData X: jpeg_encoder_init failed.");
6504 mJpegThreadWaitLock.unlock();
6505 }
6506 }
6507 else LOGV("encodeData: JPEG callback is NULL, not encoding image.");
6508 //clear the resources
6509 deinitRaw();
6510 //Encoding is done.
6511 mEncodePendingWaitLock.lock();
6512 mEncodePending = false;
6513 mEncodePendingWait.signal();
6514 mEncodePendingWaitLock.unlock();
6515
6516 LOGV("encodeData: X");
6517}
6518
Priya Komarlingamb85535d2009-11-30 13:06:01 -08006519}; // namespace android
Vamshidhar Kondra92ce9142010-09-03 18:22:08 +05306520