blob: 86e94d897d98eb9e01bcb806abde24cc88545a0c [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
Priya Komarlingamb85535d2009-11-30 13:06:01 -080020#define LOG_TAG "QualcommCameraHardware"
21#include <utils/Log.h>
22
23#include "QualcommCameraHardware.h"
24
25#include <utils/Errors.h>
26#include <utils/threads.h>
27#include <binder/MemoryHeapPmem.h>
28#include <utils/String16.h>
29#include <sys/types.h>
30#include <sys/stat.h>
31#include <unistd.h>
Sravankb4f5f1c2010-01-21 11:06:17 +053032#include <fcntl.h>
Apurva Rajguru8d1773b2009-12-02 14:21:23 -080033#include <cutils/properties.h>
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -080034#include <math.h>
Priya Komarlingamb85535d2009-11-30 13:06:01 -080035#if HAVE_ANDROID_OS
36#include <linux/android_pmem.h>
37#endif
38#include <linux/ioctl.h>
Priya Komarlingam9bb2d492010-06-23 19:21:52 -070039#include <camera/CameraParameters.h>
Priya Komarlingamb85535d2009-11-30 13:06:01 -080040
Mohan Kandra284966d2010-01-05 13:39:15 -080041#include "linux/msm_mdp.h"
42#include <linux/fb.h>
43
Priya Komarlingamb85535d2009-11-30 13:06:01 -080044#define LIKELY(exp) __builtin_expect(!!(exp), 1)
45#define UNLIKELY(exp) __builtin_expect(!!(exp), 0)
46
47extern "C" {
48#include <fcntl.h>
49#include <time.h>
50#include <pthread.h>
51#include <stdio.h>
52#include <string.h>
53#include <unistd.h>
54#include <termios.h>
55#include <assert.h>
56#include <stdlib.h>
57#include <ctype.h>
58#include <signal.h>
59#include <errno.h>
60#include <sys/mman.h>
61#include <sys/system_properties.h>
62#include <sys/time.h>
63#include <stdlib.h>
64
65#include <media/msm_camera.h>
66
67#include <camera.h>
68#include <camframe.h>
69#include <mm-still/jpeg/jpege.h>
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -080070#include <jpeg_encoder.h>
Priya Komarlingamb85535d2009-11-30 13:06:01 -080071
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -080072#define DEFAULT_PICTURE_WIDTH 1024
73#define DEFAULT_PICTURE_HEIGHT 768
Priya Komarlingamb85535d2009-11-30 13:06:01 -080074#define THUMBNAIL_BUFFER_SIZE (THUMBNAIL_WIDTH * THUMBNAIL_HEIGHT * 3/2)
75#define MAX_ZOOM_LEVEL 5
76#define NOT_FOUND -1
Sravankb4f5f1c2010-01-21 11:06:17 +053077// Number of video buffers held by kernal (initially 1,2 &3)
78#define ACTIVE_VIDEO_BUFFERS 3
79
Priya Komarlingamb85535d2009-11-30 13:06:01 -080080#if DLOPEN_LIBMMCAMERA
81#include <dlfcn.h>
82
83void* (*LINK_cam_conf)(void *data);
84void* (*LINK_cam_frame)(void *data);
85bool (*LINK_jpeg_encoder_init)();
86void (*LINK_jpeg_encoder_join)();
87bool (*LINK_jpeg_encoder_encode)(const cam_ctrl_dimension_t *dimen,
88 const uint8_t *thumbnailbuf, int thumbnailfd,
89 const uint8_t *snapshotbuf, int snapshotfd,
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -080090 common_crop_t *scaling_parms, exif_tags_info_t *exif_data,
Srinivasan Kannan5701a942010-04-15 16:17:21 -070091 int exif_table_numEntries, int jpegPadding);
Kiran Kumar H N7ac84e32010-02-01 10:58:47 -080092void (*LINK_camframe_terminate)(void);
Sravankb4f5f1c2010-01-21 11:06:17 +053093//for 720p
94// Function to add a video buffer to free Q
95void (*LINK_camframe_free_video)(struct msm_frame *frame);
96// Function pointer , called by camframe when a video frame is available.
97void (**LINK_camframe_video_callback)(struct msm_frame * frame);
98// To flush free Q in cam frame.
99void (*LINK_cam_frame_flush_free_video)(void);
100
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800101int8_t (*LINK_jpeg_encoder_setMainImageQuality)(uint32_t quality);
102int8_t (*LINK_jpeg_encoder_setThumbnailQuality)(uint32_t quality);
103int8_t (*LINK_jpeg_encoder_setRotation)(uint32_t rotation);
Mohan Kandra02486042010-06-18 16:49:43 -0700104int8_t (*LINK_jpeg_encoder_get_buffer_offset)(uint32_t width, uint32_t height,
105 uint32_t* p_y_offset,
106 uint32_t* p_cbcr_offset,
107 uint32_t* p_buf_size);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800108int8_t (*LINK_jpeg_encoder_setLocation)(const camera_position_type *location);
109const struct camera_size_type *(*LINK_default_sensor_get_snapshot_sizes)(int *len);
110int (*LINK_launch_cam_conf_thread)(void);
111int (*LINK_release_cam_conf_thread)(void);
112int8_t (*LINK_zoom_crop_upscale)(uint32_t width, uint32_t height,
113 uint32_t cropped_width, uint32_t cropped_height, uint8_t *img_buf);
114
115// callbacks
116void (**LINK_mmcamera_camframe_callback)(struct msm_frame *frame);
117void (**LINK_mmcamera_jpegfragment_callback)(uint8_t *buff_ptr,
118 uint32_t buff_size);
119void (**LINK_mmcamera_jpeg_callback)(jpeg_event_t status);
120void (**LINK_mmcamera_shutter_callback)(common_crop_t *crop);
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800121void (**LINK_camframe_timeout_callback)(void);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800122#else
123#define LINK_cam_conf cam_conf
124#define LINK_cam_frame cam_frame
125#define LINK_jpeg_encoder_init jpeg_encoder_init
126#define LINK_jpeg_encoder_join jpeg_encoder_join
127#define LINK_jpeg_encoder_encode jpeg_encoder_encode
128#define LINK_camframe_terminate camframe_terminate
129#define LINK_jpeg_encoder_setMainImageQuality jpeg_encoder_setMainImageQuality
130#define LINK_jpeg_encoder_setThumbnailQuality jpeg_encoder_setThumbnailQuality
131#define LINK_jpeg_encoder_setRotation jpeg_encoder_setRotation
Mohan Kandra02486042010-06-18 16:49:43 -0700132#define LINK_jpeg_encoder_get_buffer_offset jpeg_encoder_get_buffer_offset
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800133#define LINK_jpeg_encoder_setLocation jpeg_encoder_setLocation
134#define LINK_default_sensor_get_snapshot_sizes default_sensor_get_snapshot_sizes
135#define LINK_launch_cam_conf_thread launch_cam_conf_thread
136#define LINK_release_cam_conf_thread release_cam_conf_thread
137#define LINK_zoom_crop_upscale zoom_crop_upscale
138extern void (*mmcamera_camframe_callback)(struct msm_frame *frame);
139extern void (*mmcamera_jpegfragment_callback)(uint8_t *buff_ptr,
140 uint32_t buff_size);
141extern void (*mmcamera_jpeg_callback)(jpeg_event_t status);
142extern void (*mmcamera_shutter_callback)(common_crop_t *crop);
143#endif
144
145} // extern "C"
146
147#ifndef HAVE_CAMERA_SIZE_TYPE
148struct camera_size_type {
149 int width;
150 int height;
151};
152#endif
153
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -0800154typedef struct crop_info_struct {
155 uint32_t x;
156 uint32_t y;
157 uint32_t w;
158 uint32_t h;
159} zoom_crop_info;
160
Mohan Kandra740cfce2010-01-07 12:58:24 -0800161union zoomimage
Mohan Kandra284966d2010-01-05 13:39:15 -0800162{
163 char d[sizeof(struct mdp_blit_req_list) + sizeof(struct mdp_blit_req) * 1];
164 struct mdp_blit_req_list list;
165} zoomImage;
166
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800167//Default to WVGA
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -0800168#define DEFAULT_PREVIEW_WIDTH 800
169#define DEFAULT_PREVIEW_HEIGHT 480
170
Srinivasan Kannana01751b2010-06-24 18:44:40 -0700171//Default FPS
172#define MINIMUM_FPS 5
173#define MAXIMUM_FPS 30
174#define DEFAULT_FPS MAXIMUM_FPS
175
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -0800176/*
177 * Modifying preview size requires modification
178 * in bitmasks for boardproperties
179 */
180
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800181static const camera_size_type preview_sizes[] = {
Srinivasan Kannanfa7edae2009-12-16 18:02:01 -0800182 { 1280, 720 }, // 720P, reserved
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800183 { 800, 480 }, // WVGA
Srinivasan Kannan613301c2010-02-10 17:08:53 -0800184 { 768, 432 },
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800185 { 720, 480 },
186 { 640, 480 }, // VGA
187 { 576, 432 },
188 { 480, 320 }, // HVGA
189 { 384, 288 },
190 { 352, 288 }, // CIF
191 { 320, 240 }, // QVGA
192 { 240, 160 }, // SQVGA
193 { 176, 144 }, // QCIF
194};
195#define PREVIEW_SIZE_COUNT (sizeof(preview_sizes)/sizeof(camera_size_type))
196
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -0800197static camera_size_type supportedPreviewSizes[PREVIEW_SIZE_COUNT];
198static unsigned int previewSizeCount;
199
200board_property boardProperties[] = {
201 {TARGET_MSM7625, 0x00000fff},
202 {TARGET_MSM7627, 0x000006ff},
203 {TARGET_MSM7630, 0x00000fff},
Nishant Pandit3c278cd2010-07-13 15:56:04 +0530204 {TARGET_MSM8660, 0x00000fff},
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -0800205 {TARGET_QSD8250, 0x00000fff}
206};
207
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800208//static const camera_size_type* picture_sizes;
209//static int PICTURE_SIZE_COUNT;
210/* TODO
211 * Ideally this should be a populated by lower layers.
212 * But currently this is no API to do that at lower layer.
213 * Hence populating with default sizes for now. This needs
214 * to be changed once the API is supported.
215 */
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800216//sorted on column basis
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800217static const camera_size_type picture_sizes[] = {
218 { 2592, 1944 }, // 5MP
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800219 { 2048, 1536 }, // 3MP QXGA
220 { 1920, 1080 }, //HD1080
221 { 1600, 1200 }, // 2MP UXGA
222 { 1280, 768 }, //WXGA
223 { 1280, 720 }, //HD720
224 { 1024, 768}, // 1MP XGA
225 { 800, 600 }, //SVGA
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800226 { 800, 480 }, // WVGA
227 { 640, 480 }, // VGA
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800228 { 352, 288 }, //CIF
229 { 320, 240 }, // QVGA
230 { 176, 144 } // QCIF
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800231};
232static int PICTURE_SIZE_COUNT = sizeof(picture_sizes)/sizeof(camera_size_type);
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800233static const camera_size_type * picture_sizes_ptr;
234static int supportedPictureSizesCount;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800235
Srinivasan Kannan80d878f2009-12-18 15:06:02 -0800236#ifdef Q12
237#undef Q12
238#endif
239
240#define Q12 4096
241
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -0800242static const target_map targetList [] = {
243 { "msm7625", TARGET_MSM7625 },
244 { "msm7627", TARGET_MSM7627 },
245 { "qsd8250", TARGET_QSD8250 },
Nishant Pandit3c278cd2010-07-13 15:56:04 +0530246 { "msm7630", TARGET_MSM7630 },
247 { "msm8660", TARGET_MSM8660 }
248
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -0800249};
250static targetType mCurrentTarget = TARGET_MAX;
251
Srinivasan Kannan80d878f2009-12-18 15:06:02 -0800252typedef struct {
253 uint32_t aspect_ratio;
254 uint32_t width;
255 uint32_t height;
256} thumbnail_size_type;
257
258static thumbnail_size_type thumbnail_sizes[] = {
259 { 7281, 512, 288 }, //1.777778
260 { 6826, 480, 288 }, //1.666667
Kiran Kumar H Nb49af212010-02-17 15:12:17 -0800261 { 6144, 432, 288 }, //1.5
Srinivasan Kannan80d878f2009-12-18 15:06:02 -0800262 { 5461, 512, 384 }, //1.333333
263 { 5006, 352, 288 }, //1.222222
264};
265#define THUMBNAIL_SIZE_COUNT (sizeof(thumbnail_sizes)/sizeof(thumbnail_size_type))
266#define DEFAULT_THUMBNAIL_SETTING 2
267#define THUMBNAIL_WIDTH_STR "512"
268#define THUMBNAIL_HEIGHT_STR "384"
269#define THUMBNAIL_SMALL_HEIGHT 144
270
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800271static int attr_lookup(const str_map arr[], int len, const char *name)
272{
273 if (name) {
274 for (int i = 0; i < len; i++) {
275 if (!strcmp(arr[i].desc, name))
276 return arr[i].val;
277 }
278 }
279 return NOT_FOUND;
280}
281
282// round to the next power of two
283static inline unsigned clp2(unsigned x)
284{
285 x = x - 1;
286 x = x | (x >> 1);
287 x = x | (x >> 2);
288 x = x | (x >> 4);
289 x = x | (x >> 8);
290 x = x | (x >>16);
291 return x + 1;
292}
293
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -0800294static int exif_table_numEntries = 0;
Apurva Rajguru5ec76132010-06-16 17:43:46 -0700295#define MAX_EXIF_TABLE_ENTRIES 8
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -0800296exif_tags_info_t exif_data[MAX_EXIF_TABLE_ENTRIES];
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -0800297static zoom_crop_info zoomCropInfo;
298static void *mLastQueuedFrame = NULL;
Nishant Pandit3c278cd2010-07-13 15:56:04 +0530299#define RECORD_BUFFERS 8
Apurva Rajguruc73c1722010-04-15 17:39:11 -0700300#define RECORD_BUFFERS_8x50 6
301static int kRecordBufferCount;
302
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -0800303
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800304namespace android {
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800305
306static const int PICTURE_FORMAT_JPEG = 1;
307static const int PICTURE_FORMAT_RAW = 2;
308
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800309// from aeecamera.h
310static const str_map whitebalance[] = {
311 { CameraParameters::WHITE_BALANCE_AUTO, CAMERA_WB_AUTO },
312 { CameraParameters::WHITE_BALANCE_INCANDESCENT, CAMERA_WB_INCANDESCENT },
313 { CameraParameters::WHITE_BALANCE_FLUORESCENT, CAMERA_WB_FLUORESCENT },
314 { CameraParameters::WHITE_BALANCE_DAYLIGHT, CAMERA_WB_DAYLIGHT },
315 { CameraParameters::WHITE_BALANCE_CLOUDY_DAYLIGHT, CAMERA_WB_CLOUDY_DAYLIGHT }
316};
317
318// from camera_effect_t. This list must match aeecamera.h
319static const str_map effects[] = {
320 { CameraParameters::EFFECT_NONE, CAMERA_EFFECT_OFF },
321 { CameraParameters::EFFECT_MONO, CAMERA_EFFECT_MONO },
322 { CameraParameters::EFFECT_NEGATIVE, CAMERA_EFFECT_NEGATIVE },
323 { CameraParameters::EFFECT_SOLARIZE, CAMERA_EFFECT_SOLARIZE },
324 { CameraParameters::EFFECT_SEPIA, CAMERA_EFFECT_SEPIA },
325 { CameraParameters::EFFECT_POSTERIZE, CAMERA_EFFECT_POSTERIZE },
326 { CameraParameters::EFFECT_WHITEBOARD, CAMERA_EFFECT_WHITEBOARD },
327 { CameraParameters::EFFECT_BLACKBOARD, CAMERA_EFFECT_BLACKBOARD },
328 { CameraParameters::EFFECT_AQUA, CAMERA_EFFECT_AQUA }
329};
330
331// from qcamera/common/camera.h
Apurva Rajguru55562b02009-12-03 12:25:35 -0800332static const str_map autoexposure[] = {
333 { CameraParameters::AUTO_EXPOSURE_FRAME_AVG, CAMERA_AEC_FRAME_AVERAGE },
334 { CameraParameters::AUTO_EXPOSURE_CENTER_WEIGHTED, CAMERA_AEC_CENTER_WEIGHTED },
335 { CameraParameters::AUTO_EXPOSURE_SPOT_METERING, CAMERA_AEC_SPOT_METERING }
336};
337
338// from qcamera/common/camera.h
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800339static const str_map antibanding[] = {
340 { CameraParameters::ANTIBANDING_OFF, CAMERA_ANTIBANDING_OFF },
341 { CameraParameters::ANTIBANDING_50HZ, CAMERA_ANTIBANDING_50HZ },
342 { CameraParameters::ANTIBANDING_60HZ, CAMERA_ANTIBANDING_60HZ },
343 { CameraParameters::ANTIBANDING_AUTO, CAMERA_ANTIBANDING_AUTO }
344};
345
346/* Mapping from MCC to antibanding type */
347struct country_map {
348 uint32_t country_code;
349 camera_antibanding_type type;
350};
351
352static struct country_map country_numeric[] = {
353 { 202, CAMERA_ANTIBANDING_50HZ }, // Greece
354 { 204, CAMERA_ANTIBANDING_50HZ }, // Netherlands
355 { 206, CAMERA_ANTIBANDING_50HZ }, // Belgium
356 { 208, CAMERA_ANTIBANDING_50HZ }, // France
357 { 212, CAMERA_ANTIBANDING_50HZ }, // Monaco
358 { 213, CAMERA_ANTIBANDING_50HZ }, // Andorra
359 { 214, CAMERA_ANTIBANDING_50HZ }, // Spain
360 { 216, CAMERA_ANTIBANDING_50HZ }, // Hungary
361 { 219, CAMERA_ANTIBANDING_50HZ }, // Croatia
362 { 220, CAMERA_ANTIBANDING_50HZ }, // Serbia
363 { 222, CAMERA_ANTIBANDING_50HZ }, // Italy
364 { 226, CAMERA_ANTIBANDING_50HZ }, // Romania
365 { 228, CAMERA_ANTIBANDING_50HZ }, // Switzerland
366 { 230, CAMERA_ANTIBANDING_50HZ }, // Czech Republic
367 { 231, CAMERA_ANTIBANDING_50HZ }, // Slovakia
368 { 232, CAMERA_ANTIBANDING_50HZ }, // Austria
369 { 234, CAMERA_ANTIBANDING_50HZ }, // United Kingdom
370 { 235, CAMERA_ANTIBANDING_50HZ }, // United Kingdom
371 { 238, CAMERA_ANTIBANDING_50HZ }, // Denmark
372 { 240, CAMERA_ANTIBANDING_50HZ }, // Sweden
373 { 242, CAMERA_ANTIBANDING_50HZ }, // Norway
374 { 244, CAMERA_ANTIBANDING_50HZ }, // Finland
375 { 246, CAMERA_ANTIBANDING_50HZ }, // Lithuania
376 { 247, CAMERA_ANTIBANDING_50HZ }, // Latvia
377 { 248, CAMERA_ANTIBANDING_50HZ }, // Estonia
378 { 250, CAMERA_ANTIBANDING_50HZ }, // Russian Federation
379 { 255, CAMERA_ANTIBANDING_50HZ }, // Ukraine
380 { 257, CAMERA_ANTIBANDING_50HZ }, // Belarus
381 { 259, CAMERA_ANTIBANDING_50HZ }, // Moldova
382 { 260, CAMERA_ANTIBANDING_50HZ }, // Poland
383 { 262, CAMERA_ANTIBANDING_50HZ }, // Germany
384 { 266, CAMERA_ANTIBANDING_50HZ }, // Gibraltar
385 { 268, CAMERA_ANTIBANDING_50HZ }, // Portugal
386 { 270, CAMERA_ANTIBANDING_50HZ }, // Luxembourg
387 { 272, CAMERA_ANTIBANDING_50HZ }, // Ireland
388 { 274, CAMERA_ANTIBANDING_50HZ }, // Iceland
389 { 276, CAMERA_ANTIBANDING_50HZ }, // Albania
390 { 278, CAMERA_ANTIBANDING_50HZ }, // Malta
391 { 280, CAMERA_ANTIBANDING_50HZ }, // Cyprus
392 { 282, CAMERA_ANTIBANDING_50HZ }, // Georgia
393 { 283, CAMERA_ANTIBANDING_50HZ }, // Armenia
394 { 284, CAMERA_ANTIBANDING_50HZ }, // Bulgaria
395 { 286, CAMERA_ANTIBANDING_50HZ }, // Turkey
396 { 288, CAMERA_ANTIBANDING_50HZ }, // Faroe Islands
397 { 290, CAMERA_ANTIBANDING_50HZ }, // Greenland
398 { 293, CAMERA_ANTIBANDING_50HZ }, // Slovenia
399 { 294, CAMERA_ANTIBANDING_50HZ }, // Macedonia
400 { 295, CAMERA_ANTIBANDING_50HZ }, // Liechtenstein
401 { 297, CAMERA_ANTIBANDING_50HZ }, // Montenegro
402 { 302, CAMERA_ANTIBANDING_60HZ }, // Canada
403 { 310, CAMERA_ANTIBANDING_60HZ }, // United States of America
404 { 311, CAMERA_ANTIBANDING_60HZ }, // United States of America
405 { 312, CAMERA_ANTIBANDING_60HZ }, // United States of America
406 { 313, CAMERA_ANTIBANDING_60HZ }, // United States of America
407 { 314, CAMERA_ANTIBANDING_60HZ }, // United States of America
408 { 315, CAMERA_ANTIBANDING_60HZ }, // United States of America
409 { 316, CAMERA_ANTIBANDING_60HZ }, // United States of America
410 { 330, CAMERA_ANTIBANDING_60HZ }, // Puerto Rico
411 { 334, CAMERA_ANTIBANDING_60HZ }, // Mexico
412 { 338, CAMERA_ANTIBANDING_50HZ }, // Jamaica
413 { 340, CAMERA_ANTIBANDING_50HZ }, // Martinique
414 { 342, CAMERA_ANTIBANDING_50HZ }, // Barbados
415 { 346, CAMERA_ANTIBANDING_60HZ }, // Cayman Islands
416 { 350, CAMERA_ANTIBANDING_60HZ }, // Bermuda
417 { 352, CAMERA_ANTIBANDING_50HZ }, // Grenada
418 { 354, CAMERA_ANTIBANDING_60HZ }, // Montserrat
419 { 362, CAMERA_ANTIBANDING_50HZ }, // Netherlands Antilles
420 { 363, CAMERA_ANTIBANDING_60HZ }, // Aruba
421 { 364, CAMERA_ANTIBANDING_60HZ }, // Bahamas
422 { 365, CAMERA_ANTIBANDING_60HZ }, // Anguilla
423 { 366, CAMERA_ANTIBANDING_50HZ }, // Dominica
424 { 368, CAMERA_ANTIBANDING_60HZ }, // Cuba
425 { 370, CAMERA_ANTIBANDING_60HZ }, // Dominican Republic
426 { 372, CAMERA_ANTIBANDING_60HZ }, // Haiti
427 { 401, CAMERA_ANTIBANDING_50HZ }, // Kazakhstan
428 { 402, CAMERA_ANTIBANDING_50HZ }, // Bhutan
429 { 404, CAMERA_ANTIBANDING_50HZ }, // India
430 { 405, CAMERA_ANTIBANDING_50HZ }, // India
431 { 410, CAMERA_ANTIBANDING_50HZ }, // Pakistan
432 { 413, CAMERA_ANTIBANDING_50HZ }, // Sri Lanka
433 { 414, CAMERA_ANTIBANDING_50HZ }, // Myanmar
434 { 415, CAMERA_ANTIBANDING_50HZ }, // Lebanon
435 { 416, CAMERA_ANTIBANDING_50HZ }, // Jordan
436 { 417, CAMERA_ANTIBANDING_50HZ }, // Syria
437 { 418, CAMERA_ANTIBANDING_50HZ }, // Iraq
438 { 419, CAMERA_ANTIBANDING_50HZ }, // Kuwait
439 { 420, CAMERA_ANTIBANDING_60HZ }, // Saudi Arabia
440 { 421, CAMERA_ANTIBANDING_50HZ }, // Yemen
441 { 422, CAMERA_ANTIBANDING_50HZ }, // Oman
442 { 424, CAMERA_ANTIBANDING_50HZ }, // United Arab Emirates
443 { 425, CAMERA_ANTIBANDING_50HZ }, // Israel
444 { 426, CAMERA_ANTIBANDING_50HZ }, // Bahrain
445 { 427, CAMERA_ANTIBANDING_50HZ }, // Qatar
446 { 428, CAMERA_ANTIBANDING_50HZ }, // Mongolia
447 { 429, CAMERA_ANTIBANDING_50HZ }, // Nepal
448 { 430, CAMERA_ANTIBANDING_50HZ }, // United Arab Emirates
449 { 431, CAMERA_ANTIBANDING_50HZ }, // United Arab Emirates
450 { 432, CAMERA_ANTIBANDING_50HZ }, // Iran
451 { 434, CAMERA_ANTIBANDING_50HZ }, // Uzbekistan
452 { 436, CAMERA_ANTIBANDING_50HZ }, // Tajikistan
453 { 437, CAMERA_ANTIBANDING_50HZ }, // Kyrgyz Rep
454 { 438, CAMERA_ANTIBANDING_50HZ }, // Turkmenistan
455 { 440, CAMERA_ANTIBANDING_60HZ }, // Japan
456 { 441, CAMERA_ANTIBANDING_60HZ }, // Japan
457 { 452, CAMERA_ANTIBANDING_50HZ }, // Vietnam
458 { 454, CAMERA_ANTIBANDING_50HZ }, // Hong Kong
459 { 455, CAMERA_ANTIBANDING_50HZ }, // Macao
460 { 456, CAMERA_ANTIBANDING_50HZ }, // Cambodia
461 { 457, CAMERA_ANTIBANDING_50HZ }, // Laos
462 { 460, CAMERA_ANTIBANDING_50HZ }, // China
463 { 466, CAMERA_ANTIBANDING_60HZ }, // Taiwan
464 { 470, CAMERA_ANTIBANDING_50HZ }, // Bangladesh
465 { 472, CAMERA_ANTIBANDING_50HZ }, // Maldives
466 { 502, CAMERA_ANTIBANDING_50HZ }, // Malaysia
467 { 505, CAMERA_ANTIBANDING_50HZ }, // Australia
468 { 510, CAMERA_ANTIBANDING_50HZ }, // Indonesia
469 { 514, CAMERA_ANTIBANDING_50HZ }, // East Timor
470 { 515, CAMERA_ANTIBANDING_60HZ }, // Philippines
471 { 520, CAMERA_ANTIBANDING_50HZ }, // Thailand
472 { 525, CAMERA_ANTIBANDING_50HZ }, // Singapore
473 { 530, CAMERA_ANTIBANDING_50HZ }, // New Zealand
474 { 535, CAMERA_ANTIBANDING_60HZ }, // Guam
475 { 536, CAMERA_ANTIBANDING_50HZ }, // Nauru
476 { 537, CAMERA_ANTIBANDING_50HZ }, // Papua New Guinea
477 { 539, CAMERA_ANTIBANDING_50HZ }, // Tonga
478 { 541, CAMERA_ANTIBANDING_50HZ }, // Vanuatu
479 { 542, CAMERA_ANTIBANDING_50HZ }, // Fiji
480 { 544, CAMERA_ANTIBANDING_60HZ }, // American Samoa
481 { 545, CAMERA_ANTIBANDING_50HZ }, // Kiribati
482 { 546, CAMERA_ANTIBANDING_50HZ }, // New Caledonia
483 { 548, CAMERA_ANTIBANDING_50HZ }, // Cook Islands
484 { 602, CAMERA_ANTIBANDING_50HZ }, // Egypt
485 { 603, CAMERA_ANTIBANDING_50HZ }, // Algeria
486 { 604, CAMERA_ANTIBANDING_50HZ }, // Morocco
487 { 605, CAMERA_ANTIBANDING_50HZ }, // Tunisia
488 { 606, CAMERA_ANTIBANDING_50HZ }, // Libya
489 { 607, CAMERA_ANTIBANDING_50HZ }, // Gambia
490 { 608, CAMERA_ANTIBANDING_50HZ }, // Senegal
491 { 609, CAMERA_ANTIBANDING_50HZ }, // Mauritania
492 { 610, CAMERA_ANTIBANDING_50HZ }, // Mali
493 { 611, CAMERA_ANTIBANDING_50HZ }, // Guinea
494 { 613, CAMERA_ANTIBANDING_50HZ }, // Burkina Faso
495 { 614, CAMERA_ANTIBANDING_50HZ }, // Niger
496 { 616, CAMERA_ANTIBANDING_50HZ }, // Benin
497 { 617, CAMERA_ANTIBANDING_50HZ }, // Mauritius
498 { 618, CAMERA_ANTIBANDING_50HZ }, // Liberia
499 { 619, CAMERA_ANTIBANDING_50HZ }, // Sierra Leone
500 { 620, CAMERA_ANTIBANDING_50HZ }, // Ghana
501 { 621, CAMERA_ANTIBANDING_50HZ }, // Nigeria
502 { 622, CAMERA_ANTIBANDING_50HZ }, // Chad
503 { 623, CAMERA_ANTIBANDING_50HZ }, // Central African Republic
504 { 624, CAMERA_ANTIBANDING_50HZ }, // Cameroon
505 { 625, CAMERA_ANTIBANDING_50HZ }, // Cape Verde
506 { 627, CAMERA_ANTIBANDING_50HZ }, // Equatorial Guinea
507 { 631, CAMERA_ANTIBANDING_50HZ }, // Angola
508 { 633, CAMERA_ANTIBANDING_50HZ }, // Seychelles
509 { 634, CAMERA_ANTIBANDING_50HZ }, // Sudan
510 { 636, CAMERA_ANTIBANDING_50HZ }, // Ethiopia
511 { 637, CAMERA_ANTIBANDING_50HZ }, // Somalia
512 { 638, CAMERA_ANTIBANDING_50HZ }, // Djibouti
513 { 639, CAMERA_ANTIBANDING_50HZ }, // Kenya
514 { 640, CAMERA_ANTIBANDING_50HZ }, // Tanzania
515 { 641, CAMERA_ANTIBANDING_50HZ }, // Uganda
516 { 642, CAMERA_ANTIBANDING_50HZ }, // Burundi
517 { 643, CAMERA_ANTIBANDING_50HZ }, // Mozambique
518 { 645, CAMERA_ANTIBANDING_50HZ }, // Zambia
519 { 646, CAMERA_ANTIBANDING_50HZ }, // Madagascar
520 { 647, CAMERA_ANTIBANDING_50HZ }, // France
521 { 648, CAMERA_ANTIBANDING_50HZ }, // Zimbabwe
522 { 649, CAMERA_ANTIBANDING_50HZ }, // Namibia
523 { 650, CAMERA_ANTIBANDING_50HZ }, // Malawi
524 { 651, CAMERA_ANTIBANDING_50HZ }, // Lesotho
525 { 652, CAMERA_ANTIBANDING_50HZ }, // Botswana
526 { 653, CAMERA_ANTIBANDING_50HZ }, // Swaziland
527 { 654, CAMERA_ANTIBANDING_50HZ }, // Comoros
528 { 655, CAMERA_ANTIBANDING_50HZ }, // South Africa
529 { 657, CAMERA_ANTIBANDING_50HZ }, // Eritrea
530 { 702, CAMERA_ANTIBANDING_60HZ }, // Belize
531 { 704, CAMERA_ANTIBANDING_60HZ }, // Guatemala
532 { 706, CAMERA_ANTIBANDING_60HZ }, // El Salvador
533 { 708, CAMERA_ANTIBANDING_60HZ }, // Honduras
534 { 710, CAMERA_ANTIBANDING_60HZ }, // Nicaragua
535 { 712, CAMERA_ANTIBANDING_60HZ }, // Costa Rica
536 { 714, CAMERA_ANTIBANDING_60HZ }, // Panama
537 { 722, CAMERA_ANTIBANDING_50HZ }, // Argentina
538 { 724, CAMERA_ANTIBANDING_60HZ }, // Brazil
539 { 730, CAMERA_ANTIBANDING_50HZ }, // Chile
540 { 732, CAMERA_ANTIBANDING_60HZ }, // Colombia
541 { 734, CAMERA_ANTIBANDING_60HZ }, // Venezuela
542 { 736, CAMERA_ANTIBANDING_50HZ }, // Bolivia
543 { 738, CAMERA_ANTIBANDING_60HZ }, // Guyana
544 { 740, CAMERA_ANTIBANDING_60HZ }, // Ecuador
545 { 742, CAMERA_ANTIBANDING_50HZ }, // French Guiana
546 { 744, CAMERA_ANTIBANDING_50HZ }, // Paraguay
547 { 746, CAMERA_ANTIBANDING_60HZ }, // Suriname
548 { 748, CAMERA_ANTIBANDING_50HZ }, // Uruguay
549 { 750, CAMERA_ANTIBANDING_50HZ }, // Falkland Islands
550};
551
Apurva Rajguru08383852010-05-17 14:25:39 -0700552
553static const str_map scenemode[] = {
554 { CameraParameters::SCENE_MODE_AUTO, CAMERA_BESTSHOT_OFF },
555 { CameraParameters::SCENE_MODE_ACTION, CAMERA_BESTSHOT_ACTION },
556 { CameraParameters::SCENE_MODE_PORTRAIT, CAMERA_BESTSHOT_PORTRAIT },
557 { CameraParameters::SCENE_MODE_LANDSCAPE, CAMERA_BESTSHOT_LANDSCAPE },
558 { CameraParameters::SCENE_MODE_NIGHT, CAMERA_BESTSHOT_NIGHT },
559 { CameraParameters::SCENE_MODE_NIGHT_PORTRAIT, CAMERA_BESTSHOT_NIGHT_PORTRAIT },
560 { CameraParameters::SCENE_MODE_THEATRE, CAMERA_BESTSHOT_THEATRE },
561 { CameraParameters::SCENE_MODE_BEACH, CAMERA_BESTSHOT_BEACH },
562 { CameraParameters::SCENE_MODE_SNOW, CAMERA_BESTSHOT_SNOW },
563 { CameraParameters::SCENE_MODE_SUNSET, CAMERA_BESTSHOT_SUNSET },
564 { CameraParameters::SCENE_MODE_STEADYPHOTO, CAMERA_BESTSHOT_ANTISHAKE },
565 { CameraParameters::SCENE_MODE_FIREWORKS , CAMERA_BESTSHOT_FIREWORKS },
566 { CameraParameters::SCENE_MODE_SPORTS , CAMERA_BESTSHOT_SPORTS },
567 { CameraParameters::SCENE_MODE_PARTY, CAMERA_BESTSHOT_PARTY },
568 { CameraParameters::SCENE_MODE_CANDLELIGHT, CAMERA_BESTSHOT_CANDLELIGHT },
569 { CameraParameters::SCENE_MODE_BACKLIGHT, CAMERA_BESTSHOT_BACKLIGHT },
570 { CameraParameters::SCENE_MODE_FLOWERS, CAMERA_BESTSHOT_FLOWERS },
571};
572
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800573#define country_number (sizeof(country_numeric) / sizeof(country_map))
574
575/* Look up pre-sorted antibanding_type table by current MCC. */
576static camera_antibanding_type camera_get_location(void) {
577 char value[PROP_VALUE_MAX];
578 char country_value[PROP_VALUE_MAX];
579 uint32_t country_code, count;
580 memset(value, 0x00, sizeof(value));
581 memset(country_value, 0x00, sizeof(country_value));
582 if (!__system_property_get("gsm.operator.numeric", value)) {
583 return CAMERA_ANTIBANDING_60HZ;
584 }
585 memcpy(country_value, value, 3);
586 country_code = atoi(country_value);
587 LOGD("value:%s, country value:%s, country code:%d\n",
588 value, country_value, country_code);
589 int left = 0;
590 int right = country_number - 1;
591 while (left <= right) {
592 int index = (left + right) >> 1;
593 if (country_numeric[index].country_code == country_code)
594 return country_numeric[index].type;
595 else if (country_numeric[index].country_code > country_code)
596 right = index - 1;
597 else
598 left = index + 1;
599 }
600 return CAMERA_ANTIBANDING_60HZ;
601}
602
603// from camera.h, led_mode_t
604static const str_map flash[] = {
605 { CameraParameters::FLASH_MODE_OFF, LED_MODE_OFF },
606 { CameraParameters::FLASH_MODE_AUTO, LED_MODE_AUTO },
Srinivasan Kannanda9a7052010-07-09 10:12:31 -0700607 { CameraParameters::FLASH_MODE_ON, LED_MODE_ON },
608 { CameraParameters::FLASH_MODE_TORCH, LED_MODE_TORCH}
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800609};
610
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530611// from mm-camera/common/camera.h.
612static const str_map iso[] = {
613 { CameraParameters::ISO_AUTO, CAMERA_ISO_AUTO},
614 { CameraParameters::ISO_HJR, CAMERA_ISO_DEBLUR},
615 { CameraParameters::ISO_100, CAMERA_ISO_100},
616 { CameraParameters::ISO_200, CAMERA_ISO_200},
617 { CameraParameters::ISO_400, CAMERA_ISO_400},
Mohan Kandra61db0d02010-04-28 18:28:30 -0700618 { CameraParameters::ISO_800, CAMERA_ISO_800 },
619 { CameraParameters::ISO_1600, CAMERA_ISO_1600 }
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530620};
621
622
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800623#define DONT_CARE 0
624static const str_map focus_modes[] = {
Srinivasan Kannan71229622009-12-04 12:05:58 -0800625 { CameraParameters::FOCUS_MODE_AUTO, AF_MODE_AUTO},
626 { CameraParameters::FOCUS_MODE_INFINITY, DONT_CARE },
627 { CameraParameters::FOCUS_MODE_NORMAL, AF_MODE_NORMAL },
628 { CameraParameters::FOCUS_MODE_MACRO, AF_MODE_MACRO }
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800629};
630
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530631static const str_map lensshade[] = {
632 { CameraParameters::LENSSHADE_ENABLE, TRUE },
633 { CameraParameters::LENSSHADE_DISABLE, FALSE }
634};
635
Apurva Rajguru7b949c92010-05-26 15:46:57 -0700636static const str_map continuous_af[] = {
637 { CameraParameters::CONTINUOUS_AF_OFF, FALSE },
638 { CameraParameters::CONTINUOUS_AF_ON, TRUE }
639};
640
Apurva Rajguru0a2cb922010-06-08 15:33:22 -0700641#define DONT_CARE_COORDINATE -1
642static const str_map touchafaec[] = {
643 { CameraParameters::TOUCH_AF_AEC_OFF, FALSE },
644 { CameraParameters::TOUCH_AF_AEC_ON, TRUE }
645};
646
Srinivasan Kannan71229622009-12-04 12:05:58 -0800647struct SensorType {
648 const char *name;
649 int rawPictureWidth;
650 int rawPictureHeight;
651 bool hasAutoFocusSupport;
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800652 int max_supported_snapshot_width;
653 int max_supported_snapshot_height;
Apurva Rajguruffe264a2010-03-09 13:50:53 -0800654 int bitMask;
Srinivasan Kannan71229622009-12-04 12:05:58 -0800655};
656
Srinivasan Kannan4cc4b862010-06-30 14:22:26 -0700657
658/*
659 * Values based on aec.c
660 */
661
662#define EXPOSURE_COMPENSATION_MAXIMUM_NUMERATOR 12
663#define EXPOSURE_COMPENSATION_MINIMUM_NUMERATOR -12
664#define EXPOSURE_COMPENSATION_DEFAULT_NUMERATOR 0
665#define EXPOSURE_COMPENSATION_DENOMINATOR 6
666#define EXPOSURE_COMPENSATION_STEP ((float (1))/EXPOSURE_COMPENSATION_DENOMINATOR)
667
Srinivasan Kannan71229622009-12-04 12:05:58 -0800668static SensorType sensorTypes[] = {
Nishant Pandit3c278cd2010-07-13 15:56:04 +0530669 { "12mp", 4096, 3120, false, 4096, 3120,0x00000fff },
Apurva Rajguruffe264a2010-03-09 13:50:53 -0800670 { "5mp", 2608, 1960, true, 2592, 1944,0x00000fff },
671 { "3mp", 2064, 1544, false, 2048, 1536,0x000007ff },
672 { "2mp", 3200, 1200, false, 1600, 1200,0x000007ff } };
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800673
Srinivasan Kannan71229622009-12-04 12:05:58 -0800674
675static SensorType * sensorType;
676
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800677static const str_map picture_formats[] = {
678 {CameraParameters::PIXEL_FORMAT_JPEG, PICTURE_FORMAT_JPEG},
679 {CameraParameters::PIXEL_FORMAT_RAW, PICTURE_FORMAT_RAW}
680};
681
Mohan Kandrabf6146d2010-07-20 18:48:37 -0700682static const str_map frame_rate_modes[] = {
683 {CameraParameters::KEY_PREVIEW_FRAME_RATE_AUTO_MODE, FPS_MODE_AUTO},
684 {CameraParameters::KEY_PREVIEW_FRAME_RATE_FIXED_MODE, FPS_MODE_FIXED}
685};
686
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800687static bool parameter_string_initialized = false;
688static String8 preview_size_values;
689static String8 picture_size_values;
690static String8 antibanding_values;
691static String8 effect_values;
Apurva Rajguru55562b02009-12-03 12:25:35 -0800692static String8 autoexposure_values;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800693static String8 whitebalance_values;
694static String8 flash_values;
695static String8 focus_mode_values;
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530696static String8 iso_values;
697static String8 lensshade_values;
Apurva Rajguru0a2cb922010-06-08 15:33:22 -0700698static String8 touchafaec_values;
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800699static String8 picture_format_values;
Apurva Rajguru08383852010-05-17 14:25:39 -0700700static String8 scenemode_values;
Apurva Rajguru7b949c92010-05-26 15:46:57 -0700701static String8 continuous_af_values;
Srinivasan Kannan6bce42b2010-07-12 19:10:08 -0700702static String8 zoom_ratio_values;
Srinivasan Kannana01751b2010-06-24 18:44:40 -0700703static String8 preview_frame_rate_values;
Mohan Kandrabf6146d2010-07-20 18:48:37 -0700704static String8 frame_rate_mode_values;
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800705
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800706static String8 create_sizes_str(const camera_size_type *sizes, int len) {
707 String8 str;
708 char buffer[32];
709
710 if (len > 0) {
711 sprintf(buffer, "%dx%d", sizes[0].width, sizes[0].height);
712 str.append(buffer);
713 }
714 for (int i = 1; i < len; i++) {
715 sprintf(buffer, ",%dx%d", sizes[i].width, sizes[i].height);
716 str.append(buffer);
717 }
718 return str;
719}
720
721static String8 create_values_str(const str_map *values, int len) {
722 String8 str;
723
724 if (len > 0) {
725 str.append(values[0].desc);
726 }
727 for (int i = 1; i < len; i++) {
728 str.append(",");
729 str.append(values[i].desc);
730 }
731 return str;
732}
733
Srinivasan Kannana01751b2010-06-24 18:44:40 -0700734
Srinivasan Kannan6bce42b2010-07-12 19:10:08 -0700735static String8 create_str(int16_t *arr, int length){
736 String8 str;
737 char buffer[32];
738
739 if(length > 0){
740 snprintf(buffer, sizeof(buffer), "%d", arr[0]);
741 str.append(buffer);
742 }
743
744 for (int i =1;i<length;i++){
745 snprintf(buffer, sizeof(buffer), ",%d",arr[i]);
746 str.append(buffer);
747 }
748 return str;
749}
750
Srinivasan Kannana01751b2010-06-24 18:44:40 -0700751static String8 create_values_range_str(int min, int max){
752 String8 str;
753 char buffer[32];
754
755 if(min <= max){
756 snprintf(buffer, sizeof(buffer), "%d", min);
757 str.append(buffer);
758
759 for (int i = min + 1; i <= max; i++) {
760 snprintf(buffer, sizeof(buffer), ",%d", i);
761 str.append(buffer);
762 }
763 }
764 return str;
765}
Srinivasan Kannan6bce42b2010-07-12 19:10:08 -0700766
Sravankb4f5f1c2010-01-21 11:06:17 +0530767extern "C" {
768//------------------------------------------------------------------------
769// : 720p busyQ funcitons
770// --------------------------------------------------------------------
771static struct fifo_queue g_busy_frame_queue =
772 {0, 0, 0, PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER};
773};
774/*===========================================================================
775 * FUNCTION cam_frame_wait_video
776 *
777 * DESCRIPTION this function waits a video in the busy queue
778 * ===========================================================================*/
779
780static void cam_frame_wait_video (void)
781{
782 LOGV("cam_frame_wait_video E ");
783 if ((g_busy_frame_queue.num_of_frames) <=0){
784 pthread_cond_wait(&(g_busy_frame_queue.wait), &(g_busy_frame_queue.mut));
785 }
786 LOGV("cam_frame_wait_video X");
787 return;
788}
789
790/*===========================================================================
791 * FUNCTION cam_frame_flush_video
792 *
793 * DESCRIPTION this function deletes all the buffers in busy queue
794 * ===========================================================================*/
795void cam_frame_flush_video (void)
796{
797 LOGV("cam_frame_flush_video: in n = %d\n", g_busy_frame_queue.num_of_frames);
798 pthread_mutex_lock(&(g_busy_frame_queue.mut));
799
800 while (g_busy_frame_queue.front)
801 {
802 //dequeue from the busy queue
803 struct fifo_node *node = dequeue (&g_busy_frame_queue);
804 if(node)
805 free(node);
806
807 LOGV("cam_frame_flush_video: node \n");
808 }
809 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
810 LOGV("cam_frame_flush_video: out n = %d\n", g_busy_frame_queue.num_of_frames);
811 return ;
812}
813/*===========================================================================
814 * FUNCTION cam_frame_get_video
815 *
816 * DESCRIPTION this function returns a video frame from the head
817 * ===========================================================================*/
818static struct msm_frame * cam_frame_get_video()
819{
820 struct msm_frame *p = NULL;
821 LOGV("cam_frame_get_video... in\n");
822 LOGV("cam_frame_get_video... got lock\n");
823 if (g_busy_frame_queue.front)
824 {
825 //dequeue
826 struct fifo_node *node = dequeue (&g_busy_frame_queue);
827 if (node)
828 {
829 p = (struct msm_frame *)node->f;
830 free (node);
831 }
832 LOGV("cam_frame_get_video... out = %x\n", p->buffer);
833 }
834 return p;
835}
836
837/*===========================================================================
838 * FUNCTION cam_frame_post_video
839 *
840 * DESCRIPTION this function add a busy video frame to the busy queue tails
841 * ===========================================================================*/
842static void cam_frame_post_video (struct msm_frame *p)
843{
844 if (!p)
845 {
846 LOGE("post video , buffer is null");
847 return;
848 }
849 LOGV("cam_frame_post_video... in = %x\n", (unsigned int)(p->buffer));
850 pthread_mutex_lock(&(g_busy_frame_queue.mut));
851 LOGV("post_video got lock. q count before enQ %d", g_busy_frame_queue.num_of_frames);
852 //enqueue to busy queue
853 struct fifo_node *node = (struct fifo_node *)malloc (sizeof (struct fifo_node));
854 if (node)
855 {
856 LOGV(" post video , enqueing in busy queue");
857 node->f = p;
858 node->next = NULL;
859 enqueue (&g_busy_frame_queue, node);
860 LOGV("post_video got lock. q count after enQ %d", g_busy_frame_queue.num_of_frames);
861 }
862 else
863 {
864 LOGE("cam_frame_post_video error... out of memory\n");
865 }
866
867 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
868 pthread_cond_signal(&(g_busy_frame_queue.wait));
869
870 LOGV("cam_frame_post_video... out = %x\n", p->buffer);
871
872 return;
873}
874
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -0800875void QualcommCameraHardware::storeTargetType(void) {
876 char mDeviceName[PROPERTY_VALUE_MAX];
877 property_get("ro.product.device",mDeviceName," ");
878 mCurrentTarget = TARGET_MAX;
879 for( int i = 0; i < TARGET_MAX ; i++) {
880 if( !strncmp(mDeviceName, targetList[i].targetStr, 7)) {
881 mCurrentTarget = targetList[i].targetEnum;
882 break;
883 }
884 }
885 LOGV(" Storing the current target type as %d ", mCurrentTarget );
886 return;
887}
888
Sravankb4f5f1c2010-01-21 11:06:17 +0530889//-------------------------------------------------------------------------------------
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800890static Mutex singleton_lock;
891static bool singleton_releasing;
Srinivasan Kannan78444e42010-06-10 15:39:29 -0700892static nsecs_t singleton_releasing_start_time;
893static const nsecs_t SINGLETON_RELEASING_WAIT_TIME = seconds_to_nanoseconds(5);
894static const nsecs_t SINGLETON_RELEASING_RECHECK_TIMEOUT = seconds_to_nanoseconds(1);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800895static Condition singleton_wait;
896
897static void receive_camframe_callback(struct msm_frame *frame);
Sravankb4f5f1c2010-01-21 11:06:17 +0530898static void receive_camframe_video_callback(struct msm_frame *frame); // 720p
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800899static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size);
900static void receive_jpeg_callback(jpeg_event_t status);
901static void receive_shutter_callback(common_crop_t *crop);
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800902static void receive_camframetimeout_callback(void);
Mohan Kandra284966d2010-01-05 13:39:15 -0800903static int fb_fd = -1;
904static int32_t mMaxZoom = 0;
Srinivasan Kannan6bce42b2010-07-12 19:10:08 -0700905static bool zoomSupported = false;
Mohan Kandra284966d2010-01-05 13:39:15 -0800906static bool native_get_maxzoom(int camfd, void *pZm);
Srinivasan Kannan6bce42b2010-07-12 19:10:08 -0700907static bool native_get_zoomratios(int camfd, void *pZr, int maxZoomLevel);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800908
Mohan Kandrad9efed92010-01-15 19:08:39 -0800909static int dstOffset = 0;
910
Brian Steuer07704892009-12-18 18:07:33 -0800911static int camerafd;
912pthread_t w_thread;
913
914void *opencamerafd(void *data) {
915 camerafd = open(MSM_CAMERA_CONTROL, O_RDWR);
916 return NULL;
917}
918
Mohan Kandrad9efed92010-01-15 19:08:39 -0800919/* When using MDP zoom, double the preview buffers. The usage of these
920 * buffers is as follows:
921 * 1. As all the buffers comes under a single FD, and at initial registration,
922 * this FD will be passed to surface flinger, surface flinger can have access
923 * to all the buffers when needed.
924 * 2. Only "kPreviewBufferCount" buffers (SrcSet) will be registered with the
925 * camera driver to receive preview frames. The remaining buffers (DstSet),
926 * will be used at HAL and by surface flinger only when crop information
927 * is present in the frame.
928 * 3. When there is no crop information, there will be no call to MDP zoom,
929 * and the buffers in SrcSet will be passed to surface flinger to display.
930 * 4. With crop information present, MDP zoom will be called, and the final
931 * data will be placed in a buffer from DstSet, and this buffer will be given
932 * to surface flinger to display.
933 */
934#define NUM_MORE_BUFS 2
935
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800936QualcommCameraHardware::QualcommCameraHardware()
937 : mParameters(),
938 mCameraRunning(false),
939 mPreviewInitialized(false),
940 mFrameThreadRunning(false),
Mohan Kandra156d0ac2010-01-25 16:59:17 -0800941 mVideoThreadRunning(false),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800942 mSnapshotThreadRunning(false),
Mohan Kandraca2e7a92010-06-21 15:48:45 -0700943 mJpegThreadRunning(false),
Mohan Kandra62429cc2010-07-19 10:21:05 -0700944 mInSnapshotMode(false),
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800945 mSnapshotFormat(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800946 mReleasedRecordingFrame(false),
947 mPreviewFrameSize(0),
948 mRawSize(0),
949 mCameraControlFd(-1),
950 mAutoFocusThreadRunning(false),
951 mAutoFocusFd(-1),
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800952 mBrightness(0),
Apurva Rajguruf12d9d22010-04-05 16:47:12 -0700953 mHJR(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800954 mInPreviewCallback(false),
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800955 mUseOverlay(0),
956 mOverlay(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800957 mMsgEnabled(0),
958 mNotifyCallback(0),
959 mDataCallback(0),
960 mDataCallbackTimestamp(0),
Mohan Kandra740cfce2010-01-07 12:58:24 -0800961 mCallbackCookie(0),
Srinivasan Kannana01751b2010-06-24 18:44:40 -0700962 mInitialized(false),
Mohan Kandra740cfce2010-01-07 12:58:24 -0800963 mDebugFps(0)
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800964{
Brian Steuer07704892009-12-18 18:07:33 -0800965
966 // Start opening camera device in a separate thread/ Since this
967 // initializes the sensor hardware, this can take a long time. So,
968 // start the process here so it will be ready by the time it's
969 // needed.
970 if ((pthread_create(&w_thread, NULL, opencamerafd, NULL)) != 0) {
971 LOGE("Camera open thread creation failed");
972 }
973
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800974 memset(&mDimension, 0, sizeof(mDimension));
975 memset(&mCrop, 0, sizeof(mCrop));
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -0800976 memset(&zoomCropInfo, 0, sizeof(zoom_crop_info));
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -0800977 storeTargetType();
Mohan Kandra740cfce2010-01-07 12:58:24 -0800978 char value[PROPERTY_VALUE_MAX];
979 property_get("persist.debug.sf.showfps", value, "0");
980 mDebugFps = atoi(value);
Nishant Pandit3c278cd2010-07-13 15:56:04 +0530981 if( mCurrentTarget == TARGET_MSM7630 || mCurrentTarget == TARGET_MSM8660 ) {
Sravankb4f5f1c2010-01-21 11:06:17 +0530982 kPreviewBufferCountActual = kPreviewBufferCount;
Nishant Pandit3c278cd2010-07-13 15:56:04 +0530983 kRecordBufferCount = RECORD_BUFFERS;
Apurva Rajguruc73c1722010-04-15 17:39:11 -0700984 recordframes = new msm_frame[kRecordBufferCount];
Mohan Kandra1fd90f92010-06-17 14:54:17 -0700985 record_buffers_tracking_flag = new bool[kRecordBufferCount];
Apurva Rajguruc73c1722010-04-15 17:39:11 -0700986 }
987 else {
Sravankb4f5f1c2010-01-21 11:06:17 +0530988 kPreviewBufferCountActual = kPreviewBufferCount + NUM_MORE_BUFS;
Apurva Rajguruc73c1722010-04-15 17:39:11 -0700989 if( mCurrentTarget == TARGET_QSD8250 ) {
990 kRecordBufferCount = RECORD_BUFFERS_8x50;
991 recordframes = new msm_frame[kRecordBufferCount];
Mohan Kandra1fd90f92010-06-17 14:54:17 -0700992 record_buffers_tracking_flag = new bool[kRecordBufferCount];
Apurva Rajguruc73c1722010-04-15 17:39:11 -0700993 }
994 }
Srinivasan Kannan5701a942010-04-15 16:17:21 -0700995
996 switch(mCurrentTarget){
997 case TARGET_MSM7627:
998 jpegPadding = 8;
999 break;
1000 case TARGET_QSD8250:
1001 case TARGET_MSM7630:
Nishant Pandit3c278cd2010-07-13 15:56:04 +05301002 case TARGET_MSM8660:
Srinivasan Kannan5701a942010-04-15 16:17:21 -07001003 jpegPadding = 0;
1004 break;
1005 default:
1006 jpegPadding = 0;
1007 break;
1008 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001009 LOGV("constructor EX");
1010}
1011
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -08001012
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -08001013void QualcommCameraHardware::filterPreviewSizes(){
1014
Apurva Rajguruffe264a2010-03-09 13:50:53 -08001015 unsigned int boardMask = 0;
Mohan Kandra62429cc2010-07-19 10:21:05 -07001016 unsigned int prop = 0;
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -08001017 for(prop=0;prop<sizeof(boardProperties)/sizeof(board_property);prop++){
1018 if(mCurrentTarget == boardProperties[prop].target){
Apurva Rajguruffe264a2010-03-09 13:50:53 -08001019 boardMask = boardProperties[prop].previewSizeMask;
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -08001020 break;
1021 }
1022 }
1023
Apurva Rajguruffe264a2010-03-09 13:50:53 -08001024 int bitMask = boardMask & sensorType->bitMask;
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -08001025 if(bitMask){
1026 unsigned int mask = 1<<(PREVIEW_SIZE_COUNT-1);
1027 previewSizeCount=0;
1028 unsigned int i = 0;
1029 while(mask){
1030 if(mask&bitMask)
1031 supportedPreviewSizes[previewSizeCount++] =
1032 preview_sizes[i];
1033 i++;
1034 mask = mask >> 1;
1035 }
1036 }
1037}
1038
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -08001039//filter Picture sizes based on max width and height
1040void QualcommCameraHardware::filterPictureSizes(){
1041 int i;
1042 for(i=0;i<PICTURE_SIZE_COUNT;i++){
1043 if(((picture_sizes[i].width <=
1044 sensorType->max_supported_snapshot_width) &&
1045 (picture_sizes[i].height <=
1046 sensorType->max_supported_snapshot_height))){
1047 picture_sizes_ptr = picture_sizes + i;
1048 supportedPictureSizesCount = PICTURE_SIZE_COUNT - i ;
1049 return ;
1050 }
1051 }
1052}
1053
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001054void QualcommCameraHardware::initDefaultParameters()
1055{
1056 LOGV("initDefaultParameters E");
1057
1058 // Initialize constant parameter strings. This will happen only once in the
1059 // lifetime of the mediaserver process.
1060 if (!parameter_string_initialized) {
Srinivasan Kannan71229622009-12-04 12:05:58 -08001061 findSensorType();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001062 antibanding_values = create_values_str(
1063 antibanding, sizeof(antibanding) / sizeof(str_map));
1064 effect_values = create_values_str(
1065 effects, sizeof(effects) / sizeof(str_map));
Apurva Rajguru55562b02009-12-03 12:25:35 -08001066 autoexposure_values = create_values_str(
1067 autoexposure, sizeof(autoexposure) / sizeof(str_map));
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001068 whitebalance_values = create_values_str(
1069 whitebalance, sizeof(whitebalance) / sizeof(str_map));
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -08001070
1071 //filter preview sizes
1072 filterPreviewSizes();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001073 preview_size_values = create_sizes_str(
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -08001074 supportedPreviewSizes, previewSizeCount);
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -08001075 //filter picture sizes
1076 filterPictureSizes();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001077 picture_size_values = create_sizes_str(
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -08001078 picture_sizes_ptr, supportedPictureSizesCount);
1079
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001080 flash_values = create_values_str(
1081 flash, sizeof(flash) / sizeof(str_map));
Srinivasan Kannan71229622009-12-04 12:05:58 -08001082 if(sensorType->hasAutoFocusSupport){
1083 focus_mode_values = create_values_str(
1084 focus_modes, sizeof(focus_modes) / sizeof(str_map));
1085 }
Nishant Panditc8c1ee72009-12-03 16:24:02 +05301086 iso_values = create_values_str(
1087 iso,sizeof(iso)/sizeof(str_map));
1088 lensshade_values = create_values_str(
1089 lensshade,sizeof(lensshade)/sizeof(str_map));
Apurva Rajguru0a2cb922010-06-08 15:33:22 -07001090
1091 touchafaec_values = create_values_str(
1092 touchafaec,sizeof(touchafaec)/sizeof(str_map));
1093
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001094 picture_format_values = create_values_str(
1095 picture_formats, sizeof(picture_formats)/sizeof(str_map));
Apurva Rajguru7b949c92010-05-26 15:46:57 -07001096
1097 if(sensorType->hasAutoFocusSupport){
1098 continuous_af_values = create_values_str(
1099 continuous_af, sizeof(continuous_af) / sizeof(str_map));
1100 }
Srinivasan Kannan6bce42b2010-07-12 19:10:08 -07001101
1102 if(native_get_maxzoom(mCameraControlFd,
1103 (void *)&mMaxZoom) == true){
1104 LOGD("Maximum zoom value is %d", mMaxZoom);
1105 zoomSupported = true;
1106 if(mMaxZoom > 0){
1107 //if max zoom is available find the zoom ratios
1108 int16_t * zoomRatios = new int16_t[mMaxZoom+1];
1109 if(zoomRatios != NULL){
1110 if(native_get_zoomratios(mCameraControlFd,
1111 (void *)zoomRatios, mMaxZoom + 1) == true){
1112 zoom_ratio_values =
1113 create_str(zoomRatios, mMaxZoom + 1);
1114 }else {
1115 LOGE("Failed to get zoomratios...");
1116 }
1117 delete zoomRatios;
1118 } else {
1119 LOGE("zoom ratios failed to acquire memory");
1120 }
1121 }
1122 } else {
1123 zoomSupported = false;
1124 LOGE("Failed to get maximum zoom value...setting max "
1125 "zoom to zero");
1126 mMaxZoom = 0;
1127 }
Srinivasan Kannana01751b2010-06-24 18:44:40 -07001128 preview_frame_rate_values = create_values_range_str(
1129 MINIMUM_FPS, MAXIMUM_FPS);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001130 parameter_string_initialized = true;
Apurva Rajguru08383852010-05-17 14:25:39 -07001131
1132 scenemode_values = create_values_str(
1133 scenemode, sizeof(scenemode) / sizeof(str_map));
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001134 }
1135
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -08001136 mParameters.setPreviewSize(DEFAULT_PREVIEW_WIDTH, DEFAULT_PREVIEW_HEIGHT);
1137 mDimension.display_width = DEFAULT_PREVIEW_WIDTH;
1138 mDimension.display_height = DEFAULT_PREVIEW_HEIGHT;
1139
Srinivasan Kannana01751b2010-06-24 18:44:40 -07001140 mParameters.setPreviewFrameRate(DEFAULT_FPS);
Srinivasan Kannanf01d8592010-07-25 13:47:08 -07001141 if((strcmp(mSensorInfo.name, "vx6953")) &&
1142 (strcmp(mSensorInfo.name, "VX6953"))){
1143 mParameters.set(
Srinivasan Kannana01751b2010-06-24 18:44:40 -07001144 CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES,
1145 preview_frame_rate_values.string());
Srinivasan Kannanf01d8592010-07-25 13:47:08 -07001146 }
Mohan Kandrabf6146d2010-07-20 18:48:37 -07001147 mParameters.setPreviewFrameRateMode("frame-rate-auto");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001148 mParameters.setPreviewFormat("yuv420sp"); // informative
1149
1150 mParameters.setPictureSize(DEFAULT_PICTURE_WIDTH, DEFAULT_PICTURE_HEIGHT);
1151 mParameters.setPictureFormat("jpeg"); // informative
1152
Mohan Kandra785619a2010-02-01 21:52:42 -08001153 mParameters.set(CameraParameters::KEY_JPEG_QUALITY, "85"); // max quality
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001154 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH,
1155 THUMBNAIL_WIDTH_STR); // informative
1156 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT,
1157 THUMBNAIL_HEIGHT_STR); // informative
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08001158 mDimension.ui_thumbnail_width =
1159 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].width;
1160 mDimension.ui_thumbnail_height =
1161 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001162 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, "90");
1163
Srinivasan Kannan6bce42b2010-07-12 19:10:08 -07001164 if(zoomSupported){
1165 mParameters.set(CameraParameters::KEY_ZOOM_SUPPORTED, "true");
1166 LOGV("max zoom is %d", mMaxZoom);
1167 mParameters.set("max-zoom",mMaxZoom);
1168 mParameters.set(CameraParameters::KEY_ZOOM_RATIOS,
1169 zoom_ratio_values);
1170 } else {
1171 mParameters.set(CameraParameters::KEY_ZOOM_SUPPORTED, "false");
1172 }
1173
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001174 mParameters.set(CameraParameters::KEY_ANTIBANDING,
Mohan Kandra785619a2010-02-01 21:52:42 -08001175 CameraParameters::ANTIBANDING_OFF);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001176 mParameters.set(CameraParameters::KEY_EFFECT,
1177 CameraParameters::EFFECT_NONE);
Apurva Rajguru55562b02009-12-03 12:25:35 -08001178 mParameters.set(CameraParameters::KEY_AUTO_EXPOSURE,
1179 CameraParameters::AUTO_EXPOSURE_FRAME_AVG);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001180 mParameters.set(CameraParameters::KEY_WHITE_BALANCE,
1181 CameraParameters::WHITE_BALANCE_AUTO);
1182 mParameters.set(CameraParameters::KEY_FOCUS_MODE,
1183 CameraParameters::FOCUS_MODE_AUTO);
Priya Komarlingam044c7b52010-01-22 18:21:23 -08001184 mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS,
1185 "yuv420sp");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001186
Mohan Kandrabf6146d2010-07-20 18:48:37 -07001187 frame_rate_mode_values = create_values_str(
1188 frame_rate_modes, sizeof(frame_rate_modes) / sizeof(str_map));
1189 if((strcmp(mSensorInfo.name, "vx6953")) &&
1190 (strcmp(mSensorInfo.name, "VX6953"))){
1191 mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATE_MODES,
1192 frame_rate_mode_values.string());
1193 }
1194
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001195 mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES,
1196 preview_size_values.string());
1197 mParameters.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES,
1198 picture_size_values.string());
1199 mParameters.set(CameraParameters::KEY_SUPPORTED_ANTIBANDING,
1200 antibanding_values);
1201 mParameters.set(CameraParameters::KEY_SUPPORTED_EFFECTS, effect_values);
Apurva Rajguru55562b02009-12-03 12:25:35 -08001202 mParameters.set(CameraParameters::KEY_SUPPORTED_AUTO_EXPOSURE, autoexposure_values);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001203 mParameters.set(CameraParameters::KEY_SUPPORTED_WHITE_BALANCE,
1204 whitebalance_values);
1205 mParameters.set(CameraParameters::KEY_SUPPORTED_FOCUS_MODES,
1206 focus_mode_values);
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001207 mParameters.set(CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS,
1208 picture_format_values);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001209
1210 if (mSensorInfo.flash_enabled) {
1211 mParameters.set(CameraParameters::KEY_FLASH_MODE,
1212 CameraParameters::FLASH_MODE_OFF);
1213 mParameters.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES,
1214 flash_values);
1215 }
1216
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08001217 mParameters.set(CameraParameters::KEY_MAX_SHARPNESS,
1218 CAMERA_MAX_SHARPNESS);
1219 mParameters.set(CameraParameters::KEY_MAX_CONTRAST,
1220 CAMERA_MAX_CONTRAST);
1221 mParameters.set(CameraParameters::KEY_MAX_SATURATION,
1222 CAMERA_MAX_SATURATION);
1223
Srinivasan Kannan4cc4b862010-06-30 14:22:26 -07001224 mParameters.set(
1225 CameraParameters::KEY_MAX_EXPOSURE_COMPENSATION,
1226 EXPOSURE_COMPENSATION_MAXIMUM_NUMERATOR);
1227 mParameters.set(
1228 CameraParameters::KEY_MIN_EXPOSURE_COMPENSATION,
1229 EXPOSURE_COMPENSATION_MINIMUM_NUMERATOR);
1230 mParameters.set(
1231 CameraParameters::KEY_EXPOSURE_COMPENSATION,
1232 EXPOSURE_COMPENSATION_DEFAULT_NUMERATOR);
1233 mParameters.setFloat(
1234 CameraParameters::KEY_EXPOSURE_COMPENSATION_STEP,
1235 EXPOSURE_COMPENSATION_STEP);
1236
Apurva Rajguru07185952010-01-22 15:40:07 -08001237 mParameters.set("luma-adaptation", "3");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001238 mParameters.set("zoom-supported", "true");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001239 mParameters.set("zoom", 0);
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001240 mParameters.set(CameraParameters::KEY_PICTURE_FORMAT,
1241 CameraParameters::PIXEL_FORMAT_JPEG);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001242
Kiran Kumar H N595970b2010-01-12 10:41:09 -08001243 mParameters.set(CameraParameters::KEY_SHARPNESS,
1244 CAMERA_DEF_SHARPNESS);
1245 mParameters.set(CameraParameters::KEY_CONTRAST,
1246 CAMERA_DEF_CONTRAST);
1247 mParameters.set(CameraParameters::KEY_SATURATION,
1248 CAMERA_DEF_SATURATION);
1249
Nishant Panditc8c1ee72009-12-03 16:24:02 +05301250 mParameters.set(CameraParameters::KEY_ISO_MODE,
1251 CameraParameters::ISO_AUTO);
1252 mParameters.set(CameraParameters::KEY_LENSSHADE,
1253 CameraParameters::LENSSHADE_ENABLE);
1254 mParameters.set(CameraParameters::KEY_SUPPORTED_ISO_MODES,
1255 iso_values);
1256 mParameters.set(CameraParameters::KEY_SUPPORTED_LENSSHADE_MODES,
1257 lensshade_values);
Apurva Rajguru08383852010-05-17 14:25:39 -07001258 mParameters.set(CameraParameters::KEY_SCENE_MODE,
1259 CameraParameters::SCENE_MODE_AUTO);
Nishant Panditc8c1ee72009-12-03 16:24:02 +05301260
Apurva Rajguru08383852010-05-17 14:25:39 -07001261 mParameters.set(CameraParameters::KEY_SUPPORTED_SCENE_MODES,
1262 scenemode_values);
Apurva Rajguru7b949c92010-05-26 15:46:57 -07001263 mParameters.set(CameraParameters::KEY_CONTINUOUS_AF,
1264 CameraParameters::CONTINUOUS_AF_OFF);
1265 mParameters.set(CameraParameters::KEY_SUPPORTED_CONTINUOUS_AF,
1266 continuous_af_values);
Apurva Rajguru0a2cb922010-06-08 15:33:22 -07001267 mParameters.set(CameraParameters::KEY_TOUCH_AF_AEC,
1268 CameraParameters::TOUCH_AF_AEC_OFF);
1269 mParameters.set(CameraParameters::KEY_SUPPORTED_TOUCH_AF_AEC,
1270 touchafaec_values);
Priyanka Kharat67cfe532010-03-29 17:28:22 -07001271 if (setParameters(mParameters) != NO_ERROR) {
1272 LOGE("Failed to set default parameters?!");
1273 }
1274
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08001275 mUseOverlay = useOverlay();
1276
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001277 /* Initialize the camframe_timeout_flag*/
1278 Mutex::Autolock l(&mCamframeTimeoutLock);
1279 camframe_timeout_flag = FALSE;
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08001280 mPostViewHeap = NULL;
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001281
Srinivasan Kannana01751b2010-06-24 18:44:40 -07001282 mInitialized = true;
1283
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001284 LOGV("initDefaultParameters X");
1285}
1286
Srinivasan Kannan71229622009-12-04 12:05:58 -08001287void QualcommCameraHardware::findSensorType(){
1288 mDimension.picture_width = DEFAULT_PICTURE_WIDTH;
1289 mDimension.picture_height = DEFAULT_PICTURE_HEIGHT;
1290 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
1291 sizeof(cam_ctrl_dimension_t), &mDimension);
1292 if (ret) {
1293 unsigned int i;
1294 for (i = 0; i < sizeof(sensorTypes) / sizeof(SensorType); i++) {
1295 if (sensorTypes[i].rawPictureHeight
1296 == mDimension.raw_picture_height) {
1297 sensorType = sensorTypes + i;
1298 return;
1299 }
1300 }
1301 }
1302 //default to 5 mp
1303 sensorType = sensorTypes;
1304 return;
1305}
1306
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001307#define ROUND_TO_PAGE(x) (((x)+0xfff)&~0xfff)
1308
1309bool QualcommCameraHardware::startCamera()
1310{
1311 LOGV("startCamera E");
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08001312 if( mCurrentTarget == TARGET_MAX ) {
1313 LOGE(" Unable to determine the target type. Camera will not work ");
1314 return false;
1315 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001316#if DLOPEN_LIBMMCAMERA
1317 libmmcamera = ::dlopen("liboemcamera.so", RTLD_NOW);
Priya Komarlingam9bb2d492010-06-23 19:21:52 -07001318
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001319 LOGV("loading liboemcamera at %p", libmmcamera);
1320 if (!libmmcamera) {
1321 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
1322 return false;
1323 }
1324
1325 *(void **)&LINK_cam_frame =
1326 ::dlsym(libmmcamera, "cam_frame");
1327 *(void **)&LINK_camframe_terminate =
1328 ::dlsym(libmmcamera, "camframe_terminate");
1329
1330 *(void **)&LINK_jpeg_encoder_init =
1331 ::dlsym(libmmcamera, "jpeg_encoder_init");
1332
1333 *(void **)&LINK_jpeg_encoder_encode =
1334 ::dlsym(libmmcamera, "jpeg_encoder_encode");
1335
1336 *(void **)&LINK_jpeg_encoder_join =
1337 ::dlsym(libmmcamera, "jpeg_encoder_join");
1338
1339 *(void **)&LINK_mmcamera_camframe_callback =
1340 ::dlsym(libmmcamera, "mmcamera_camframe_callback");
1341
1342 *LINK_mmcamera_camframe_callback = receive_camframe_callback;
1343
1344 *(void **)&LINK_mmcamera_jpegfragment_callback =
1345 ::dlsym(libmmcamera, "mmcamera_jpegfragment_callback");
1346
1347 *LINK_mmcamera_jpegfragment_callback = receive_jpeg_fragment_callback;
1348
1349 *(void **)&LINK_mmcamera_jpeg_callback =
1350 ::dlsym(libmmcamera, "mmcamera_jpeg_callback");
1351
1352 *LINK_mmcamera_jpeg_callback = receive_jpeg_callback;
1353
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001354 *(void **)&LINK_camframe_timeout_callback =
1355 ::dlsym(libmmcamera, "camframe_timeout_callback");
1356
1357 *LINK_camframe_timeout_callback = receive_camframetimeout_callback;
1358
Sravankb4f5f1c2010-01-21 11:06:17 +05301359 // 720 p new recording functions
1360 *(void **)&LINK_cam_frame_flush_free_video = ::dlsym(libmmcamera, "cam_frame_flush_free_video");
1361
1362 *(void **)&LINK_camframe_free_video = ::dlsym(libmmcamera, "cam_frame_add_free_video");
1363
1364 *(void **)&LINK_camframe_video_callback = ::dlsym(libmmcamera, "mmcamera_camframe_videocallback");
1365 *LINK_camframe_video_callback = receive_camframe_video_callback;
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08001366
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001367 *(void **)&LINK_mmcamera_shutter_callback =
1368 ::dlsym(libmmcamera, "mmcamera_shutter_callback");
1369
1370 *LINK_mmcamera_shutter_callback = receive_shutter_callback;
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08001371
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001372 *(void**)&LINK_jpeg_encoder_setMainImageQuality =
1373 ::dlsym(libmmcamera, "jpeg_encoder_setMainImageQuality");
Kiran Kumar H N8861f302010-01-05 12:01:41 -08001374
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001375 *(void**)&LINK_jpeg_encoder_setThumbnailQuality =
1376 ::dlsym(libmmcamera, "jpeg_encoder_setThumbnailQuality");
1377
1378 *(void**)&LINK_jpeg_encoder_setRotation =
1379 ::dlsym(libmmcamera, "jpeg_encoder_setRotation");
1380
Mohan Kandra02486042010-06-18 16:49:43 -07001381 *(void**)&LINK_jpeg_encoder_get_buffer_offset =
1382 ::dlsym(libmmcamera, "jpeg_encoder_get_buffer_offset");
1383
Kiran Kumar H N8861f302010-01-05 12:01:41 -08001384/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001385 *(void**)&LINK_jpeg_encoder_setLocation =
1386 ::dlsym(libmmcamera, "jpeg_encoder_setLocation");
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001387*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001388 *(void **)&LINK_cam_conf =
1389 ::dlsym(libmmcamera, "cam_conf");
1390
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001391/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001392 *(void **)&LINK_default_sensor_get_snapshot_sizes =
1393 ::dlsym(libmmcamera, "default_sensor_get_snapshot_sizes");
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001394*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001395 *(void **)&LINK_launch_cam_conf_thread =
1396 ::dlsym(libmmcamera, "launch_cam_conf_thread");
1397
1398 *(void **)&LINK_release_cam_conf_thread =
1399 ::dlsym(libmmcamera, "release_cam_conf_thread");
1400
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001401/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001402 *(void **)&LINK_zoom_crop_upscale =
1403 ::dlsym(libmmcamera, "zoom_crop_upscale");
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001404*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001405
1406#else
1407 mmcamera_camframe_callback = receive_camframe_callback;
1408 mmcamera_jpegfragment_callback = receive_jpeg_fragment_callback;
1409 mmcamera_jpeg_callback = receive_jpeg_callback;
1410 mmcamera_shutter_callback = receive_shutter_callback;
1411#endif // DLOPEN_LIBMMCAMERA
1412
1413 /* The control thread is in libcamera itself. */
Brian Steuer07704892009-12-18 18:07:33 -08001414 if (pthread_join(w_thread, NULL) != 0) {
1415 LOGE("Camera open thread exit failed");
1416 return false;
1417 }
1418 mCameraControlFd = camerafd;
1419
Kiran Kumar H N585bc362010-01-19 13:04:44 -08001420 if (mCameraControlFd < 0) {
1421 LOGE("startCamera X: %s open failed: %s!",
1422 MSM_CAMERA_CONTROL,
1423 strerror(errno));
1424 return false;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001425 }
1426
Nishant Pandit3c278cd2010-07-13 15:56:04 +05301427 if((mCurrentTarget != TARGET_MSM7630) && (mCurrentTarget != TARGET_MSM8660)){
Mohan Kandra284966d2010-01-05 13:39:15 -08001428 fb_fd = open("/dev/graphics/fb0", O_RDWR);
1429 if (fb_fd < 0) {
1430 LOGE("startCamera: fb0 open failed: %s!", strerror(errno));
1431 return FALSE;
1432 }
1433 }
1434
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001435 /* This will block until the control thread is launched. After that, sensor
1436 * information becomes available.
1437 */
1438
1439 if (LINK_launch_cam_conf_thread()) {
1440 LOGE("failed to launch the camera config thread");
1441 return false;
1442 }
1443
1444 memset(&mSensorInfo, 0, sizeof(mSensorInfo));
1445 if (ioctl(mCameraControlFd,
1446 MSM_CAM_IOCTL_GET_SENSOR_INFO,
1447 &mSensorInfo) < 0)
1448 LOGW("%s: cannot retrieve sensor info!", __FUNCTION__);
1449 else
1450 LOGI("%s: camsensor name %s, flash %d", __FUNCTION__,
1451 mSensorInfo.name, mSensorInfo.flash_enabled);
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001452/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001453 picture_sizes = LINK_default_sensor_get_snapshot_sizes(&PICTURE_SIZE_COUNT);
1454 if (!picture_sizes || !PICTURE_SIZE_COUNT) {
1455 LOGE("startCamera X: could not get snapshot sizes");
1456 return false;
1457 }
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001458*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001459 LOGV("startCamera X");
1460 return true;
1461}
1462
1463status_t QualcommCameraHardware::dump(int fd,
1464 const Vector<String16>& args) const
1465{
1466 const size_t SIZE = 256;
1467 char buffer[SIZE];
1468 String8 result;
1469
1470 // Dump internal primitives.
1471 result.append("QualcommCameraHardware::dump");
1472 snprintf(buffer, 255, "mMsgEnabled (%d)\n", mMsgEnabled);
1473 result.append(buffer);
1474 int width, height;
1475 mParameters.getPreviewSize(&width, &height);
1476 snprintf(buffer, 255, "preview width(%d) x height (%d)\n", width, height);
1477 result.append(buffer);
1478 mParameters.getPictureSize(&width, &height);
1479 snprintf(buffer, 255, "raw width(%d) x height (%d)\n", width, height);
1480 result.append(buffer);
1481 snprintf(buffer, 255,
1482 "preview frame size(%d), raw size (%d), jpeg size (%d) "
1483 "and jpeg max size (%d)\n", mPreviewFrameSize, mRawSize,
1484 mJpegSize, mJpegMaxSize);
1485 result.append(buffer);
1486 write(fd, result.string(), result.size());
1487
1488 // Dump internal objects.
Mohan Kandrad9efed92010-01-15 19:08:39 -08001489 if (mPreviewHeap != 0) {
1490 mPreviewHeap->dump(fd, args);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001491 }
1492 if (mRawHeap != 0) {
1493 mRawHeap->dump(fd, args);
1494 }
1495 if (mJpegHeap != 0) {
1496 mJpegHeap->dump(fd, args);
1497 }
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001498 if(mRawSnapshotAshmemHeap != 0 ){
1499 mRawSnapshotAshmemHeap->dump(fd, args);
1500 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001501 mParameters.dump(fd, args);
1502 return NO_ERROR;
1503}
1504
Mohan Kandra284966d2010-01-05 13:39:15 -08001505static bool native_get_maxzoom(int camfd, void *pZm)
1506{
1507 LOGV("native_get_maxzoom E");
1508
1509 struct msm_ctrl_cmd ctrlCmd;
1510 int32_t *pZoom = (int32_t *)pZm;
1511
1512 ctrlCmd.type = CAMERA_GET_PARM_MAXZOOM;
1513 ctrlCmd.timeout_ms = 5000;
1514 ctrlCmd.length = sizeof(int32_t);
1515 ctrlCmd.value = pZoom;
1516 ctrlCmd.resp_fd = camfd;
1517
1518 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1519 LOGE("native_get_maxzoom: ioctl fd %d error %s",
1520 camfd,
1521 strerror(errno));
1522 return false;
1523 }
Brian Steuerb62adbd2010-02-02 14:47:08 -08001524 LOGD("ctrlCmd.value = %d", *(int32_t *)ctrlCmd.value);
Mohan Kandra284966d2010-01-05 13:39:15 -08001525 memcpy(pZoom, (int32_t *)ctrlCmd.value, sizeof(int32_t));
1526
1527 LOGV("native_get_maxzoom X");
1528 return true;
1529}
1530
Srinivasan Kannan6bce42b2010-07-12 19:10:08 -07001531static bool native_get_zoomratios(int camfd, void *pZr, int maxZoomSize)
1532{
1533 LOGV("native_get_zoomratios E");
1534 struct msm_ctrl_cmd ctrlCmd;
1535 int16_t *zoomRatios = (int16_t *)pZr;
1536
1537 if(maxZoomSize <= 0)
1538 return false;
1539
1540 ctrlCmd.type = CAMERA_GET_PARM_ZOOMRATIOS;
1541 ctrlCmd.timeout_ms = 5000;
1542 ctrlCmd.length = sizeof(int16_t)* (maxZoomSize);
1543 ctrlCmd.value = zoomRatios;
1544 ctrlCmd.resp_fd = camfd;
1545
1546 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1547 LOGE("native_get_zoomratios: ioctl fd %d error %s",
1548 camfd,
1549 strerror(errno));
1550 return false;
1551 }
1552 LOGV("native_get_zoomratios X");
1553 return true;
1554}
1555
1556
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001557static bool native_set_afmode(int camfd, isp3a_af_mode_t af_type)
1558{
1559 int rc;
1560 struct msm_ctrl_cmd ctrlCmd;
1561
1562 ctrlCmd.timeout_ms = 5000;
1563 ctrlCmd.type = CAMERA_SET_PARM_AUTO_FOCUS;
1564 ctrlCmd.length = sizeof(af_type);
1565 ctrlCmd.value = &af_type;
1566 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1567
1568 if ((rc = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0)
1569 LOGE("native_set_afmode: ioctl fd %d error %s\n",
1570 camfd,
1571 strerror(errno));
1572
1573 LOGV("native_set_afmode: ctrlCmd.status == %d\n", ctrlCmd.status);
1574 return rc >= 0 && ctrlCmd.status == CAMERA_EXIT_CB_DONE;
1575}
1576
1577static bool native_cancel_afmode(int camfd, int af_fd)
1578{
1579 int rc;
1580 struct msm_ctrl_cmd ctrlCmd;
1581
1582 ctrlCmd.timeout_ms = 0;
1583 ctrlCmd.type = CAMERA_AUTO_FOCUS_CANCEL;
1584 ctrlCmd.length = 0;
1585 ctrlCmd.value = NULL;
1586 ctrlCmd.resp_fd = -1; // there's no response fd
1587
1588 if ((rc = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND_2, &ctrlCmd)) < 0)
1589 {
1590 LOGE("native_cancel_afmode: ioctl fd %d error %s\n",
1591 camfd,
1592 strerror(errno));
1593 return false;
1594 }
1595
1596 return true;
1597}
1598
1599static bool native_start_preview(int camfd)
1600{
1601 struct msm_ctrl_cmd ctrlCmd;
1602
1603 ctrlCmd.timeout_ms = 5000;
1604 ctrlCmd.type = CAMERA_START_PREVIEW;
1605 ctrlCmd.length = 0;
1606 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1607
1608 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1609 LOGE("native_start_preview: MSM_CAM_IOCTL_CTRL_COMMAND fd %d error %s",
1610 camfd,
1611 strerror(errno));
1612 return false;
1613 }
1614
1615 return true;
1616}
1617
1618static bool native_get_picture (int camfd, common_crop_t *crop)
1619{
1620 struct msm_ctrl_cmd ctrlCmd;
1621
1622 ctrlCmd.timeout_ms = 5000;
1623 ctrlCmd.length = sizeof(common_crop_t);
1624 ctrlCmd.value = crop;
1625
1626 if(ioctl(camfd, MSM_CAM_IOCTL_GET_PICTURE, &ctrlCmd) < 0) {
1627 LOGE("native_get_picture: MSM_CAM_IOCTL_GET_PICTURE fd %d error %s",
1628 camfd,
1629 strerror(errno));
1630 return false;
1631 }
1632
1633 LOGV("crop: in1_w %d", crop->in1_w);
1634 LOGV("crop: in1_h %d", crop->in1_h);
1635 LOGV("crop: out1_w %d", crop->out1_w);
1636 LOGV("crop: out1_h %d", crop->out1_h);
1637
1638 LOGV("crop: in2_w %d", crop->in2_w);
1639 LOGV("crop: in2_h %d", crop->in2_h);
1640 LOGV("crop: out2_w %d", crop->out2_w);
1641 LOGV("crop: out2_h %d", crop->out2_h);
1642
1643 LOGV("crop: update %d", crop->update_flag);
1644
1645 return true;
1646}
1647
1648static bool native_stop_preview(int camfd)
1649{
1650 struct msm_ctrl_cmd ctrlCmd;
1651 ctrlCmd.timeout_ms = 5000;
1652 ctrlCmd.type = CAMERA_STOP_PREVIEW;
1653 ctrlCmd.length = 0;
1654 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1655
1656 if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1657 LOGE("native_stop_preview: ioctl fd %d error %s",
1658 camfd,
1659 strerror(errno));
1660 return false;
1661 }
1662
1663 return true;
1664}
1665
1666static bool native_prepare_snapshot(int camfd)
1667{
1668 int ioctlRetVal = true;
1669 struct msm_ctrl_cmd ctrlCmd;
1670
1671 ctrlCmd.timeout_ms = 1000;
1672 ctrlCmd.type = CAMERA_PREPARE_SNAPSHOT;
1673 ctrlCmd.length = 0;
1674 ctrlCmd.value = NULL;
1675 ctrlCmd.resp_fd = camfd;
1676
1677 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1678 LOGE("native_prepare_snapshot: ioctl fd %d error %s",
1679 camfd,
1680 strerror(errno));
1681 return false;
1682 }
1683 return true;
1684}
1685
1686static bool native_start_snapshot(int camfd)
1687{
1688 struct msm_ctrl_cmd ctrlCmd;
1689
1690 ctrlCmd.timeout_ms = 5000;
1691 ctrlCmd.type = CAMERA_START_SNAPSHOT;
1692 ctrlCmd.length = 0;
1693 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1694
1695 if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1696 LOGE("native_start_snapshot: ioctl fd %d error %s",
1697 camfd,
1698 strerror(errno));
1699 return false;
1700 }
1701
1702 return true;
1703}
1704
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001705static bool native_start_raw_snapshot(int camfd)
1706{
1707 int ret;
1708 struct msm_ctrl_cmd ctrlCmd;
1709
1710 ctrlCmd.timeout_ms = 1000;
1711 ctrlCmd.type = CAMERA_START_RAW_SNAPSHOT;
1712 ctrlCmd.length = 0;
1713 ctrlCmd.value = NULL;
1714 ctrlCmd.resp_fd = camfd;
1715
1716 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1717 LOGE("native_start_raw_snapshot: ioctl failed. ioctl return value "\
1718 "is %d \n", ret);
1719 return false;
1720 }
1721 return true;
1722}
1723
1724
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001725static bool native_stop_snapshot (int camfd)
1726{
1727 struct msm_ctrl_cmd ctrlCmd;
1728
1729 ctrlCmd.timeout_ms = 0;
1730 ctrlCmd.type = CAMERA_STOP_SNAPSHOT;
1731 ctrlCmd.length = 0;
1732 ctrlCmd.resp_fd = -1;
1733
1734 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND_2, &ctrlCmd) < 0) {
1735 LOGE("native_stop_snapshot: ioctl fd %d error %s",
1736 camfd,
1737 strerror(errno));
1738 return false;
1739 }
1740
1741 return true;
1742}
Sravankb4f5f1c2010-01-21 11:06:17 +05301743/*===========================================================================
1744 * FUNCTION - native_start_recording -
1745 *
1746 * DESCRIPTION:
1747 *==========================================================================*/
1748static bool native_start_recording(int camfd)
1749{
1750 int ret;
1751 struct msm_ctrl_cmd ctrlCmd;
1752
1753 ctrlCmd.timeout_ms = 1000;
1754 ctrlCmd.type = CAMERA_START_RECORDING;
1755 ctrlCmd.length = 0;
1756 ctrlCmd.value = NULL;
1757 ctrlCmd.resp_fd = camfd;
1758
1759 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1760 LOGE("native_start_recording: ioctl failed. ioctl return value "\
1761 "is %d \n", ret);
1762 return false;
1763 }
Mohan Kandraf1ebf982010-02-02 15:25:43 -08001764 LOGV("native_start_recording: ioctl good. ioctl return value is %d \n",ret);
Sravankb4f5f1c2010-01-21 11:06:17 +05301765
1766 /* TODO: Check status of postprocessing if there is any,
1767 * PP status should be in ctrlCmd */
1768
1769 return true;
1770}
1771
1772/*===========================================================================
1773 * FUNCTION - native_stop_recording -
1774 *
1775 * DESCRIPTION:
1776 *==========================================================================*/
1777static bool native_stop_recording(int camfd)
1778{
1779 int ret;
1780 struct msm_ctrl_cmd ctrlCmd;
Kiran Kumar H Nb49af212010-02-17 15:12:17 -08001781 LOGV("in native_stop_recording ");
Sravankb4f5f1c2010-01-21 11:06:17 +05301782 ctrlCmd.timeout_ms = 1000;
1783 ctrlCmd.type = CAMERA_STOP_RECORDING;
1784 ctrlCmd.length = 0;
1785 ctrlCmd.value = NULL;
1786 ctrlCmd.resp_fd = camfd;
1787
1788 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1789 LOGE("native_stop_video: ioctl failed. ioctl return value is %d \n",
1790 ret);
1791 return false;
1792 }
1793 LOGV("in native_stop_recording returned %d", ret);
1794 return true;
1795}
1796/*===========================================================================
1797 * FUNCTION - native_start_video -
1798 *
1799 * DESCRIPTION:
1800 *==========================================================================*/
1801static bool native_start_video(int camfd)
1802{
1803 int ret;
1804 struct msm_ctrl_cmd ctrlCmd;
1805
1806 ctrlCmd.timeout_ms = 1000;
1807 ctrlCmd.type = CAMERA_START_VIDEO;
1808 ctrlCmd.length = 0;
1809 ctrlCmd.value = NULL;
1810 ctrlCmd.resp_fd = camfd;
1811
1812 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1813 LOGE("native_start_video: ioctl failed. ioctl return value is %d \n",
1814 ret);
1815 return false;
1816 }
1817
1818 /* TODO: Check status of postprocessing if there is any,
1819 * PP status should be in ctrlCmd */
1820
1821 return true;
1822}
1823
1824/*===========================================================================
1825 * FUNCTION - native_stop_video -
1826 *
1827 * DESCRIPTION:
1828 *==========================================================================*/
1829static bool native_stop_video(int camfd)
1830{
1831 int ret;
1832 struct msm_ctrl_cmd ctrlCmd;
1833
1834 ctrlCmd.timeout_ms = 1000;
1835 ctrlCmd.type = CAMERA_STOP_VIDEO;
1836 ctrlCmd.length = 0;
1837 ctrlCmd.value = NULL;
1838 ctrlCmd.resp_fd = camfd;
1839
1840 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1841 LOGE("native_stop_video: ioctl failed. ioctl return value is %d \n",
1842 ret);
1843 return false;
1844 }
1845
1846 return true;
1847}
1848/*==========================================================================*/
1849
1850static cam_frame_start_parms frame_parms;
1851static int recordingState = 0;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001852
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001853static rat_t latitude[3];
1854static rat_t longitude[3];
1855static char lonref[2];
1856static char latref[2];
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001857static rat_t altitude;
Apurva Rajguru5ec76132010-06-16 17:43:46 -07001858static rat_t gpsTimestamp[3];
1859static char dateTime[20];
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001860static void addExifTag(exif_tag_id_t tagid, exif_tag_type_t type,
1861 uint32_t count, uint8_t copy, void *data) {
1862
1863 if(exif_table_numEntries == MAX_EXIF_TABLE_ENTRIES) {
1864 LOGE("Number of entries exceeded limit");
1865 return;
1866 }
1867
1868 int index = exif_table_numEntries;
1869 exif_data[index].tag_id = tagid;
1870 exif_data[index].tag_entry.type = type;
1871 exif_data[index].tag_entry.count = count;
1872 exif_data[index].tag_entry.copy = copy;
1873 if((type == EXIF_RATIONAL) && (count > 1))
1874 exif_data[index].tag_entry.data._rats = (rat_t *)data;
1875 if((type == EXIF_RATIONAL) && (count == 1))
1876 exif_data[index].tag_entry.data._rat = *(rat_t *)data;
1877 else if(type == EXIF_ASCII)
1878 exif_data[index].tag_entry.data._ascii = (char *)data;
1879 else if(type == EXIF_BYTE)
1880 exif_data[index].tag_entry.data._byte = *(uint8_t *)data;
1881
1882 // Increase number of entries
1883 exif_table_numEntries++;
1884}
1885
1886static void parseLatLong(const char *latlonString, int *pDegrees,
1887 int *pMinutes, int *pSeconds ) {
1888
1889 double value = atof(latlonString);
1890 value = fabs(value);
1891 int degrees = (int) value;
1892
1893 double remainder = value - degrees;
1894 int minutes = (int) (remainder * 60);
1895 int seconds = (int) (((remainder * 60) - minutes) * 60 * 1000);
1896
1897 *pDegrees = degrees;
1898 *pMinutes = minutes;
1899 *pSeconds = seconds;
1900}
1901
1902static void setLatLon(exif_tag_id_t tag, const char *latlonString) {
1903
1904 int degrees, minutes, seconds;
1905
1906 parseLatLong(latlonString, &degrees, &minutes, &seconds);
1907
1908 rat_t value[3] = { {degrees, 1},
1909 {minutes, 1},
1910 {seconds, 1000} };
1911
1912 if(tag == EXIFTAGID_GPS_LATITUDE) {
1913 memcpy(latitude, value, sizeof(latitude));
1914 addExifTag(EXIFTAGID_GPS_LATITUDE, EXIF_RATIONAL, 3,
1915 1, (void *)latitude);
1916 } else {
1917 memcpy(longitude, value, sizeof(longitude));
1918 addExifTag(EXIFTAGID_GPS_LONGITUDE, EXIF_RATIONAL, 3,
1919 1, (void *)longitude);
1920 }
1921}
1922
1923void QualcommCameraHardware::setGpsParameters() {
1924 const char *str = NULL;
1925
1926 //Set Latitude
1927 str = mParameters.get(CameraParameters::KEY_GPS_LATITUDE);
1928 if(str != NULL) {
1929 setLatLon(EXIFTAGID_GPS_LATITUDE, str);
1930 //set Latitude Ref
1931 str = NULL;
1932 str = mParameters.get(CameraParameters::KEY_GPS_LATITUDE_REF);
1933 if(str != NULL) {
1934 strncpy(latref, str, 1);
1935 latref[1] = '\0';
1936 addExifTag(EXIFTAGID_GPS_LATITUDE_REF, EXIF_ASCII, 2,
1937 1, (void *)latref);
1938 }
1939 }
1940
1941 //set Longitude
1942 str = NULL;
1943 str = mParameters.get(CameraParameters::KEY_GPS_LONGITUDE);
1944 if(str != NULL) {
1945 setLatLon(EXIFTAGID_GPS_LONGITUDE, str);
1946 //set Longitude Ref
1947 str = NULL;
1948 str = mParameters.get(CameraParameters::KEY_GPS_LONGITUDE_REF);
1949 if(str != NULL) {
1950 strncpy(lonref, str, 1);
1951 lonref[1] = '\0';
1952 addExifTag(EXIFTAGID_GPS_LONGITUDE_REF, EXIF_ASCII, 2,
1953 1, (void *)lonref);
1954 }
1955 }
1956
1957 //set Altitude
1958 str = NULL;
1959 str = mParameters.get(CameraParameters::KEY_GPS_ALTITUDE);
1960 if(str != NULL) {
1961 int value = atoi(str);
1962 rat_t alt_value = {value, 1000};
1963 memcpy(&altitude, &alt_value, sizeof(altitude));
1964 addExifTag(EXIFTAGID_GPS_ALTITUDE, EXIF_RATIONAL, 1,
1965 1, (void *)&altitude);
1966 //set AltitudeRef
1967 int ref = mParameters.getInt(CameraParameters::KEY_GPS_ALTITUDE_REF);
1968 if( !(ref < 0 || ref > 1) )
1969 addExifTag(EXIFTAGID_GPS_ALTITUDE_REF, EXIF_BYTE, 1,
1970 1, (void *)&ref);
1971 }
1972
Apurva Rajguru5ec76132010-06-16 17:43:46 -07001973 //set Gps TimeStamp
1974 str = NULL;
1975 str = mParameters.get(CameraParameters::KEY_GPS_TIMESTAMP);
1976 if(str != NULL) {
1977
1978 long value = atol(str);
1979 time_t unixTime;
1980 struct tm *UTCTimestamp;
1981
1982 unixTime = (time_t)value;
1983 UTCTimestamp = gmtime(&unixTime);
1984
1985 rat_t time_value[3] = { {UTCTimestamp->tm_hour, 1},
1986 {UTCTimestamp->tm_min, 1},
1987 {UTCTimestamp->tm_sec, 1} };
1988
1989 memcpy(&gpsTimestamp, &time_value, sizeof(gpsTimestamp));
1990 addExifTag(EXIFTAGID_GPS_TIMESTAMP, EXIF_RATIONAL,
1991 3, 1, (void *)&gpsTimestamp);
1992 }
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001993
1994}
1995
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001996bool QualcommCameraHardware::native_jpeg_encode(void)
1997{
1998 int jpeg_quality = mParameters.getInt("jpeg-quality");
1999 if (jpeg_quality >= 0) {
2000 LOGV("native_jpeg_encode, current jpeg main img quality =%d",
2001 jpeg_quality);
2002 if(!LINK_jpeg_encoder_setMainImageQuality(jpeg_quality)) {
2003 LOGE("native_jpeg_encode set jpeg-quality failed");
2004 return false;
2005 }
2006 }
2007
2008 int thumbnail_quality = mParameters.getInt("jpeg-thumbnail-quality");
2009 if (thumbnail_quality >= 0) {
2010 LOGV("native_jpeg_encode, current jpeg thumbnail quality =%d",
2011 thumbnail_quality);
2012 if(!LINK_jpeg_encoder_setThumbnailQuality(thumbnail_quality)) {
2013 LOGE("native_jpeg_encode set thumbnail-quality failed");
2014 return false;
2015 }
2016 }
2017
Mohan Kandra62429cc2010-07-19 10:21:05 -07002018 if( (mCurrentTarget != TARGET_MSM7630) && (mCurrentTarget != TARGET_MSM7627) ) {
Mohan Kandra02486042010-06-18 16:49:43 -07002019 int rotation = mParameters.getInt("rotation");
2020 if (rotation >= 0) {
2021 LOGV("native_jpeg_encode, rotation = %d", rotation);
2022 if(!LINK_jpeg_encoder_setRotation(rotation)) {
2023 LOGE("native_jpeg_encode set rotation failed");
2024 return false;
2025 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002026 }
2027 }
2028
Apurva Rajguru5ec76132010-06-16 17:43:46 -07002029 jpeg_set_location();
2030
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08002031 //set TimeStamp
2032 const char *str = mParameters.get(CameraParameters::KEY_EXIF_DATETIME);
2033 if(str != NULL) {
2034 strncpy(dateTime, str, 19);
2035 dateTime[19] = '\0';
2036 addExifTag(EXIFTAGID_EXIF_DATE_TIME_ORIGINAL, EXIF_ASCII,
2037 20, 1, (void *)dateTime);
2038 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002039 if (!LINK_jpeg_encoder_encode(&mDimension,
2040 (uint8_t *)mThumbnailHeap->mHeap->base(),
2041 mThumbnailHeap->mHeap->getHeapID(),
2042 (uint8_t *)mRawHeap->mHeap->base(),
2043 mRawHeap->mHeap->getHeapID(),
Srinivasan Kannan5701a942010-04-15 16:17:21 -07002044 &mCrop, exif_data, exif_table_numEntries,
2045 jpegPadding/2)) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002046 LOGE("native_jpeg_encode: jpeg_encoder_encode failed.");
2047 return false;
2048 }
2049 return true;
2050}
2051
2052bool QualcommCameraHardware::native_set_parm(
2053 cam_ctrl_type type, uint16_t length, void *value)
2054{
2055 struct msm_ctrl_cmd ctrlCmd;
2056
2057 ctrlCmd.timeout_ms = 5000;
2058 ctrlCmd.type = (uint16_t)type;
2059 ctrlCmd.length = length;
2060 // FIXME: this will be put in by the kernel
2061 ctrlCmd.resp_fd = mCameraControlFd;
2062 ctrlCmd.value = value;
2063
2064 LOGV("%s: fd %d, type %d, length %d", __FUNCTION__,
2065 mCameraControlFd, type, length);
2066 if (ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0 ||
2067 ctrlCmd.status != CAM_CTRL_SUCCESS) {
2068 LOGE("%s: error (%s): fd %d, type %d, length %d, status %d",
2069 __FUNCTION__, strerror(errno),
2070 mCameraControlFd, type, length, ctrlCmd.status);
2071 return false;
2072 }
2073 return true;
2074}
2075
2076void QualcommCameraHardware::jpeg_set_location()
2077{
2078 bool encode_location = true;
2079 camera_position_type pt;
2080
2081#define PARSE_LOCATION(what,type,fmt,desc) do { \
2082 pt.what = 0; \
2083 const char *what##_str = mParameters.get("gps-"#what); \
2084 LOGV("GPS PARM %s --> [%s]", "gps-"#what, what##_str); \
2085 if (what##_str) { \
2086 type what = 0; \
2087 if (sscanf(what##_str, fmt, &what) == 1) \
2088 pt.what = what; \
2089 else { \
2090 LOGE("GPS " #what " %s could not" \
2091 " be parsed as a " #desc, what##_str); \
2092 encode_location = false; \
2093 } \
2094 } \
2095 else { \
2096 LOGV("GPS " #what " not specified: " \
2097 "defaulting to zero in EXIF header."); \
2098 encode_location = false; \
2099 } \
2100 } while(0)
2101
2102 PARSE_LOCATION(timestamp, long, "%ld", "long");
2103 if (!pt.timestamp) pt.timestamp = time(NULL);
2104 PARSE_LOCATION(altitude, short, "%hd", "short");
2105 PARSE_LOCATION(latitude, double, "%lf", "double float");
2106 PARSE_LOCATION(longitude, double, "%lf", "double float");
2107
2108#undef PARSE_LOCATION
2109
2110 if (encode_location) {
2111 LOGD("setting image location ALT %d LAT %lf LON %lf",
2112 pt.altitude, pt.latitude, pt.longitude);
Apurva Rajguru5ec76132010-06-16 17:43:46 -07002113
2114 setGpsParameters();
2115 /* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002116 if (!LINK_jpeg_encoder_setLocation(&pt)) {
2117 LOGE("jpeg_set_location: LINK_jpeg_encoder_setLocation failed.");
2118 }
Apurva Rajguru5ec76132010-06-16 17:43:46 -07002119 */
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002120 }
2121 else LOGV("not setting image location");
2122}
2123
2124void QualcommCameraHardware::runFrameThread(void *data)
2125{
2126 LOGV("runFrameThread E");
2127
2128 int cnt;
2129
2130#if DLOPEN_LIBMMCAMERA
2131 // We need to maintain a reference to libqcamera.so for the duration of the
2132 // frame thread, because we do not know when it will exit relative to the
2133 // lifetime of this object. We do not want to dlclose() libqcamera while
2134 // LINK_cam_frame is still running.
2135 void *libhandle = ::dlopen("liboemcamera.so", RTLD_NOW);
2136 LOGV("FRAME: loading libqcamera at %p", libhandle);
2137 if (!libhandle) {
2138 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
2139 }
2140 if (libhandle)
2141#endif
2142 {
2143 LINK_cam_frame(data);
2144 }
2145
Mohan Kandrad9efed92010-01-15 19:08:39 -08002146 mPreviewHeap.clear();
Nishant Pandit3c278cd2010-07-13 15:56:04 +05302147 if(( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250) || (mCurrentTarget == TARGET_MSM8660))
Sravankb4f5f1c2010-01-21 11:06:17 +05302148 mRecordHeap.clear();
2149
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002150#if DLOPEN_LIBMMCAMERA
2151 if (libhandle) {
2152 ::dlclose(libhandle);
2153 LOGV("FRAME: dlclose(libqcamera)");
2154 }
2155#endif
2156
2157 mFrameThreadWaitLock.lock();
2158 mFrameThreadRunning = false;
2159 mFrameThreadWait.signal();
2160 mFrameThreadWaitLock.unlock();
2161
2162 LOGV("runFrameThread X");
2163}
2164
Sravankb4f5f1c2010-01-21 11:06:17 +05302165void QualcommCameraHardware::runVideoThread(void *data)
2166{
2167 LOGD("runVideoThread E");
2168 msm_frame* vframe = NULL;
2169
2170 while(true) {
2171 pthread_mutex_lock(&(g_busy_frame_queue.mut));
2172
Srinivasan Kannanfc3915c2010-03-18 10:54:40 -07002173 // Exit the thread , in case of stop recording..
2174 mVideoThreadWaitLock.lock();
2175 if(mVideoThreadExit){
2176 LOGV("Exiting video thread..");
2177 mVideoThreadWaitLock.unlock();
2178 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
2179 break;
2180 }
2181 mVideoThreadWaitLock.unlock();
2182
Kiran Kumar H Nb49af212010-02-17 15:12:17 -08002183 LOGV("in video_thread : wait for video frame ");
Sravankb4f5f1c2010-01-21 11:06:17 +05302184 // check if any frames are available in busyQ and give callback to
2185 // services/video encoder
2186 cam_frame_wait_video();
2187 LOGV("video_thread, wait over..");
2188
2189 // Exit the thread , in case of stop recording..
2190 mVideoThreadWaitLock.lock();
2191 if(mVideoThreadExit){
Kiran Kumar H Nb49af212010-02-17 15:12:17 -08002192 LOGV("Exiting video thread..");
Sravankb4f5f1c2010-01-21 11:06:17 +05302193 mVideoThreadWaitLock.unlock();
2194 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
2195 break;
2196 }
2197 mVideoThreadWaitLock.unlock();
2198
2199 // Get the video frame to be encoded
2200 vframe = cam_frame_get_video ();
Apurva Rajgurud9b0b302010-02-19 11:22:56 -08002201 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
Sravankb4f5f1c2010-01-21 11:06:17 +05302202 LOGV("in video_thread : got video frame ");
2203
Mohan Kandrabad0eaa2010-02-04 15:11:54 -08002204 if (UNLIKELY(mDebugFps)) {
2205 debugShowVideoFPS();
2206 }
2207
Sravankb4f5f1c2010-01-21 11:06:17 +05302208 if(vframe != NULL) {
2209 // Find the offset within the heap of the current buffer.
2210 LOGV("Got video frame : buffer %d base %d ", vframe->buffer, mRecordHeap->mHeap->base());
2211 ssize_t offset =
2212 (ssize_t)vframe->buffer - (ssize_t)mRecordHeap->mHeap->base();
2213 LOGV("offset = %d , alignsize = %d , offset later = %d", offset, mRecordHeap->mAlignedBufferSize, (offset / mRecordHeap->mAlignedBufferSize));
2214
2215 offset /= mRecordHeap->mAlignedBufferSize;
Mohan Kandra1fd90f92010-06-17 14:54:17 -07002216
2217 //set the track flag to true for this video buffer
2218 record_buffers_tracking_flag[offset] = true;
2219
Mohan Kandra1307f312010-04-29 10:18:42 -07002220 /* Extract the timestamp of this frame */
2221 nsecs_t timeStamp = nsecs_t(vframe->ts.tv_sec)*1000000000LL + vframe->ts.tv_nsec;
Sravankb4f5f1c2010-01-21 11:06:17 +05302222
2223 // dump frames for test purpose
2224#ifdef DUMP_VIDEO_FRAMES
2225 static int frameCnt = 0;
2226 if (frameCnt >= 11 && frameCnt <= 13 ) {
2227 char buf[128];
2228 sprintf(buf, "/data/%d_v.yuv", frameCnt);
2229 int file_fd = open(buf, O_RDWR | O_CREAT, 0777);
2230 LOGV("dumping video frame %d", frameCnt);
2231 if (file_fd < 0) {
2232 LOGE("cannot open file\n");
2233 }
2234 else
2235 {
2236 write(file_fd, (const void *)vframe->buffer,
2237 vframe->cbcr_off * 3 / 2);
2238 }
2239 close(file_fd);
2240 }
2241 frameCnt++;
2242#endif
2243 // Enable IF block to give frames to encoder , ELSE block for just simulation
2244#if 1
2245 LOGV("in video_thread : got video frame, before if check giving frame to services/encoder");
2246 mCallbackLock.lock();
2247 int msgEnabled = mMsgEnabled;
2248 data_callback_timestamp rcb = mDataCallbackTimestamp;
2249 void *rdata = mCallbackCookie;
2250 mCallbackLock.unlock();
2251
2252 if(rcb != NULL && (msgEnabled & CAMERA_MSG_VIDEO_FRAME) ) {
2253 LOGV("in video_thread : got video frame, giving frame to services/encoder");
Mohan Kandra1307f312010-04-29 10:18:42 -07002254 rcb(timeStamp, CAMERA_MSG_VIDEO_FRAME, mRecordHeap->mBuffers[offset], rdata);
Sravankb4f5f1c2010-01-21 11:06:17 +05302255 }
2256#else
2257 // 720p output2 : simulate release frame here:
2258 LOGE("in video_thread simulation , releasing the video frame");
2259 LINK_camframe_free_video(vframe);
2260#endif
2261
2262 } else LOGE("in video_thread get frame returned null");
2263
Sravankb4f5f1c2010-01-21 11:06:17 +05302264
2265 } // end of while loop
Mohan Kandra156d0ac2010-01-25 16:59:17 -08002266
2267 mVideoThreadWaitLock.lock();
2268 mVideoThreadRunning = false;
2269 mVideoThreadWait.signal();
2270 mVideoThreadWaitLock.unlock();
2271
Sravankb4f5f1c2010-01-21 11:06:17 +05302272 LOGV("runVideoThread X");
2273}
2274
2275void *video_thread(void *user)
2276{
2277 LOGV("video_thread E");
2278 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
2279 if (obj != 0) {
2280 obj->runVideoThread(user);
2281 }
2282 else LOGE("not starting video thread: the object went away!");
2283 LOGV("video_thread X");
2284 return NULL;
2285}
2286
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002287void *frame_thread(void *user)
2288{
2289 LOGD("frame_thread E");
2290 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
2291 if (obj != 0) {
2292 obj->runFrameThread(user);
2293 }
2294 else LOGW("not starting frame thread: the object went away!");
2295 LOGD("frame_thread X");
2296 return NULL;
2297}
2298
2299bool QualcommCameraHardware::initPreview()
2300{
2301 // See comments in deinitPreview() for why we have to wait for the frame
2302 // thread here, and why we can't use pthread_join().
Sravankb4f5f1c2010-01-21 11:06:17 +05302303 int videoWidth, videoHeight;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002304 mParameters.getPreviewSize(&previewWidth, &previewHeight);
Sravankb4f5f1c2010-01-21 11:06:17 +05302305
2306 videoWidth = previewWidth; // temporary , should be configurable later
2307 videoHeight = previewHeight;
2308 LOGV("initPreview E: preview size=%dx%d videosize = %d x %d", previewWidth, previewHeight, videoWidth, videoHeight );
2309
Nishant Pandit3c278cd2010-07-13 15:56:04 +05302310 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250) || (mCurrentTarget == TARGET_MSM8660)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05302311 mDimension.video_width = videoWidth;
Kiran Kumar H N7ac84e32010-02-01 10:58:47 -08002312 mDimension.video_width = CEILING16(mDimension.video_width);
Sravankb4f5f1c2010-01-21 11:06:17 +05302313 mDimension.video_height = videoHeight;
Sravank64461e82010-02-25 15:10:09 +05302314 // for 720p , preview can be 768X432
2315 previewWidth = mDimension.display_width;
2316 previewHeight= mDimension.display_height;
Sravankb4f5f1c2010-01-21 11:06:17 +05302317 LOGV("initPreview : preview size=%dx%d videosize = %d x %d", previewWidth, previewHeight, mDimension.video_width, mDimension.video_height );
2318 }
2319
2320
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002321 mFrameThreadWaitLock.lock();
2322 while (mFrameThreadRunning) {
2323 LOGV("initPreview: waiting for old frame thread to complete.");
2324 mFrameThreadWait.wait(mFrameThreadWaitLock);
2325 LOGV("initPreview: old frame thread completed.");
2326 }
2327 mFrameThreadWaitLock.unlock();
2328
Mohan Kandraca2e7a92010-06-21 15:48:45 -07002329 mInSnapshotModeWaitLock.lock();
2330 while (mInSnapshotMode) {
2331 LOGV("initPreview: waiting for snapshot mode to complete.");
2332 mInSnapshotModeWait.wait(mInSnapshotModeWaitLock);
2333 LOGV("initPreview: snapshot mode completed.");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002334 }
Mohan Kandraca2e7a92010-06-21 15:48:45 -07002335 mInSnapshotModeWaitLock.unlock();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002336
2337 int cnt = 0;
2338 mPreviewFrameSize = previewWidth * previewHeight * 3/2;
Mohan Kandra02486042010-06-18 16:49:43 -07002339 int CbCrOffset = PAD_TO_WORD(previewWidth * previewHeight);
Mohan Kandrad9efed92010-01-15 19:08:39 -08002340 dstOffset = 0;
2341 mPreviewHeap = new PmemPool("/dev/pmem_adsp",
Mohan Kandra284966d2010-01-05 13:39:15 -08002342 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
2343 mCameraControlFd,
Sravankb4f5f1c2010-01-21 11:06:17 +05302344 MSM_PMEM_PREVIEW, //MSM_PMEM_OUTPUT2,
Mohan Kandra284966d2010-01-05 13:39:15 -08002345 mPreviewFrameSize,
Mohan Kandrad9efed92010-01-15 19:08:39 -08002346 kPreviewBufferCountActual,
Mohan Kandra284966d2010-01-05 13:39:15 -08002347 mPreviewFrameSize,
Mohan Kandra02486042010-06-18 16:49:43 -07002348 CbCrOffset,
2349 0,
Mohan Kandrad9efed92010-01-15 19:08:39 -08002350 "preview");
Mohan Kandra284966d2010-01-05 13:39:15 -08002351
Mohan Kandrad9efed92010-01-15 19:08:39 -08002352 if (!mPreviewHeap->initialized()) {
2353 mPreviewHeap.clear();
Mohan Kandra284966d2010-01-05 13:39:15 -08002354 LOGE("initPreview X: could not initialize Camera preview heap.");
2355 return false;
2356 }
Nishant Pandit3c278cd2010-07-13 15:56:04 +05302357 if( (mCurrentTarget == TARGET_MSM7630) || (mCurrentTarget == TARGET_MSM8660)) {
Srinivasan Kannan613301c2010-02-10 17:08:53 -08002358 mPostViewHeap.clear();
Kiran Kumar H N595970b2010-01-12 10:41:09 -08002359 if(mPostViewHeap == NULL) {
2360 LOGV(" Allocating Postview heap ");
2361 /* mPostViewHeap should be declared only for 7630 target */
2362 mPostViewHeap =
2363 new PmemPool("/dev/pmem_adsp",
2364 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
2365 mCameraControlFd,
Sravankb4f5f1c2010-01-21 11:06:17 +05302366 MSM_PMEM_PREVIEW, //MSM_PMEM_OUTPUT2,
Kiran Kumar H N595970b2010-01-12 10:41:09 -08002367 mPreviewFrameSize,
2368 1,
2369 mPreviewFrameSize,
Mohan Kandra02486042010-06-18 16:49:43 -07002370 CbCrOffset,
2371 0,
Kiran Kumar H N595970b2010-01-12 10:41:09 -08002372 "postview");
Mohan Kandra284966d2010-01-05 13:39:15 -08002373
Kiran Kumar H N595970b2010-01-12 10:41:09 -08002374 if (!mPostViewHeap->initialized()) {
2375 mPostViewHeap.clear();
2376 LOGE(" Failed to initialize Postview Heap");
2377 return false;
2378 }
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002379 }
Mohan Kandraf1ebf982010-02-02 15:25:43 -08002380 }
2381
Nishant Pandit3c278cd2010-07-13 15:56:04 +05302382 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250) || (mCurrentTarget == TARGET_MSM8660)) {
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002383
2384 // Allocate video buffers after allocating preview buffers.
Sravankb4f5f1c2010-01-21 11:06:17 +05302385 initRecord();
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002386 }
Sravankb4f5f1c2010-01-21 11:06:17 +05302387
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002388 // mDimension will be filled with thumbnail_width, thumbnail_height,
2389 // orig_picture_dx, and orig_picture_dy after this function call. We need to
2390 // keep it for jpeg_encoder_encode.
2391 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
2392 sizeof(cam_ctrl_dimension_t), &mDimension);
2393
2394 if (ret) {
2395 for (cnt = 0; cnt < kPreviewBufferCount; cnt++) {
Mohan Kandrad9efed92010-01-15 19:08:39 -08002396 frames[cnt].fd = mPreviewHeap->mHeap->getHeapID();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002397 frames[cnt].buffer =
Mohan Kandrad9efed92010-01-15 19:08:39 -08002398 (uint32_t)mPreviewHeap->mHeap->base() + mPreviewHeap->mAlignedBufferSize * cnt;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002399 frames[cnt].y_off = 0;
Mohan Kandra02486042010-06-18 16:49:43 -07002400 frames[cnt].cbcr_off = CbCrOffset;
Sravankb4f5f1c2010-01-21 11:06:17 +05302401 frames[cnt].path = OUTPUT_TYPE_P; // MSM_FRAME_ENC;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002402 }
2403
2404 mFrameThreadWaitLock.lock();
2405 pthread_attr_t attr;
2406 pthread_attr_init(&attr);
2407 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
Sravankb4f5f1c2010-01-21 11:06:17 +05302408
2409 frame_parms.frame = frames[kPreviewBufferCount - 1];
Apurva Rajguruc73c1722010-04-15 17:39:11 -07002410
Nishant Pandit3c278cd2010-07-13 15:56:04 +05302411 if( mCurrentTarget == TARGET_MSM7630 || mCurrentTarget == TARGET_QSD8250 || mCurrentTarget == TARGET_MSM8660)
Apurva Rajguruc73c1722010-04-15 17:39:11 -07002412 frame_parms.video_frame = recordframes[kPreviewBufferCount - 1];
2413 else
2414 frame_parms.video_frame = frames[kPreviewBufferCount - 1];
Sravankb4f5f1c2010-01-21 11:06:17 +05302415
2416 LOGV ("initpreview before cam_frame thread carete , video frame buffer=%lu fd=%d y_off=%d cbcr_off=%d \n",
2417 (unsigned long)frame_parms.video_frame.buffer, frame_parms.video_frame.fd, frame_parms.video_frame.y_off,
2418 frame_parms.video_frame.cbcr_off);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002419 mFrameThreadRunning = !pthread_create(&mFrameThread,
2420 &attr,
2421 frame_thread,
Sravankb4f5f1c2010-01-21 11:06:17 +05302422 (void*)&(frame_parms));
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002423 ret = mFrameThreadRunning;
2424 mFrameThreadWaitLock.unlock();
2425 }
2426
2427 LOGV("initPreview X: %d", ret);
2428 return ret;
2429}
2430
2431void QualcommCameraHardware::deinitPreview(void)
2432{
2433 LOGI("deinitPreview E");
2434
2435 // When we call deinitPreview(), we signal to the frame thread that it
2436 // needs to exit, but we DO NOT WAIT for it to complete here. The problem
2437 // is that deinitPreview is sometimes called from the frame-thread's
2438 // callback, when the refcount on the Camera client reaches zero. If we
2439 // called pthread_join(), we would deadlock. So, we just call
2440 // LINK_camframe_terminate() in deinitPreview(), which makes sure that
2441 // after the preview callback returns, the camframe thread will exit. We
2442 // could call pthread_join() in initPreview() to join the last frame
2443 // thread. However, we would also have to call pthread_join() in release
2444 // as well, shortly before we destroy the object; this would cause the same
2445 // deadlock, since release(), like deinitPreview(), may also be called from
2446 // the frame-thread's callback. This we have to make the frame thread
2447 // detached, and use a separate mechanism to wait for it to complete.
2448
Kiran Kumar H N7ac84e32010-02-01 10:58:47 -08002449 LINK_camframe_terminate();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002450 LOGI("deinitPreview X");
2451}
2452
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002453bool QualcommCameraHardware::initRawSnapshot()
2454{
2455 LOGV("initRawSnapshot E");
Nishant Pandit62fe9aa2010-07-27 04:23:17 +05302456 const char * pmem_region;
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002457
2458 //get width and height from Dimension Object
2459 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
2460 sizeof(cam_ctrl_dimension_t), &mDimension);
2461
2462 if(!ret){
2463 LOGE("initRawSnapshot X: failed to set dimension");
2464 return false;
2465 }
2466 int rawSnapshotSize = mDimension.raw_picture_height *
2467 mDimension.raw_picture_width;
2468
2469 LOGV("raw_snapshot_buffer_size = %d, raw_picture_height = %d, "\
2470 "raw_picture_width = %d",
2471 rawSnapshotSize, mDimension.raw_picture_height,
2472 mDimension.raw_picture_width);
2473
2474 if (mRawSnapShotPmemHeap != NULL) {
2475 LOGV("initRawSnapshot: clearing old mRawSnapShotPmemHeap.");
2476 mRawSnapShotPmemHeap.clear();
2477 }
Nishant Pandit62fe9aa2010-07-27 04:23:17 +05302478 if(mCurrentTarget == TARGET_MSM8660)
2479 pmem_region = "/dev/pmem_smipool";
2480 else
2481 pmem_region = "/dev/pmem_adsp";
2482
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002483
2484 //Pmem based pool for Camera Driver
Nishant Pandit62fe9aa2010-07-27 04:23:17 +05302485 mRawSnapShotPmemHeap = new PmemPool(pmem_region,
Dinesh Gargeecf1a62010-04-19 16:31:30 -07002486 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002487 mCameraControlFd,
2488 MSM_PMEM_RAW_MAINIMG,
2489 rawSnapshotSize,
2490 1,
2491 rawSnapshotSize,
Mohan Kandra02486042010-06-18 16:49:43 -07002492 0,
2493 0,
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002494 "raw pmem snapshot camera");
2495
2496 if (!mRawSnapShotPmemHeap->initialized()) {
2497 mRawSnapShotPmemHeap.clear();
2498 LOGE("initRawSnapshot X: error initializing mRawSnapshotHeap");
2499 return false;
2500 }
2501 LOGV("initRawSnapshot X");
2502 return true;
2503
2504}
2505
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002506bool QualcommCameraHardware::initRaw(bool initJpegHeap)
2507{
2508 int rawWidth, rawHeight;
Nishant Pandit62fe9aa2010-07-27 04:23:17 +05302509 const char * pmem_region;
Apurva Rajguru8d1773b2009-12-02 14:21:23 -08002510
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002511 mParameters.getPictureSize(&rawWidth, &rawHeight);
2512 LOGV("initRaw E: picture size=%dx%d", rawWidth, rawHeight);
2513
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08002514 int thumbnailBufferSize;
2515 //Thumbnail height should be smaller than Picture height
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002516 if (rawHeight > (int)thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height){
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08002517 mDimension.ui_thumbnail_width =
2518 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].width;
2519 mDimension.ui_thumbnail_height =
2520 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height;
2521 uint32_t pictureAspectRatio = (uint32_t)((rawWidth * Q12) / rawHeight);
2522 uint32_t i;
2523 for(i = 0; i < THUMBNAIL_SIZE_COUNT; i++ )
2524 {
2525 if(thumbnail_sizes[i].aspect_ratio == pictureAspectRatio)
2526 {
2527 mDimension.ui_thumbnail_width = thumbnail_sizes[i].width;
2528 mDimension.ui_thumbnail_height = thumbnail_sizes[i].height;
2529 break;
2530 }
2531 }
2532 }
2533 else{
2534 mDimension.ui_thumbnail_height = THUMBNAIL_SMALL_HEIGHT;
2535 mDimension.ui_thumbnail_width =
2536 (THUMBNAIL_SMALL_HEIGHT * rawWidth)/ rawHeight;
2537 }
2538
2539 LOGV("Thumbnail Size Width %d Height %d",
2540 mDimension.ui_thumbnail_width,
2541 mDimension.ui_thumbnail_height);
2542
2543 thumbnailBufferSize = mDimension.ui_thumbnail_width *
2544 mDimension.ui_thumbnail_height * 3 / 2;
Mohan Kandra02486042010-06-18 16:49:43 -07002545 int CbCrOffsetThumb = PAD_TO_WORD(mDimension.ui_thumbnail_width *
2546 mDimension.ui_thumbnail_height);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002547 // mDimension will be filled with thumbnail_width, thumbnail_height,
2548 // orig_picture_dx, and orig_picture_dy after this function call. We need to
2549 // keep it for jpeg_encoder_encode.
2550 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
2551 sizeof(cam_ctrl_dimension_t), &mDimension);
2552 if(!ret) {
2553 LOGE("initRaw X: failed to set dimension");
2554 return false;
2555 }
2556
2557 if (mJpegHeap != NULL) {
2558 LOGV("initRaw: clearing old mJpegHeap.");
2559 mJpegHeap.clear();
2560 }
2561
2562 // Snapshot
2563 mRawSize = rawWidth * rawHeight * 3 / 2;
Mohan Kandra02486042010-06-18 16:49:43 -07002564 int CbCrOffsetRaw = PAD_TO_WORD(rawWidth * rawHeight);
Apurva Rajguru8d1773b2009-12-02 14:21:23 -08002565
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002566 if( mCurrentTarget == TARGET_MSM7627 )
Apurva Rajguru8d1773b2009-12-02 14:21:23 -08002567 mJpegMaxSize = CEILING16(rawWidth) * CEILING16(rawHeight) * 3 / 2;
2568 else
2569 mJpegMaxSize = rawWidth * rawHeight * 3 / 2;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002570
Mohan Kandra02486042010-06-18 16:49:43 -07002571 //For offline jpeg hw encoder, jpeg encoder will provide us the
2572 //required offsets and buffer size depending on the rotation.
2573 int yOffset = 0;
Mohan Kandra62429cc2010-07-19 10:21:05 -07002574 if( (mCurrentTarget == TARGET_MSM7630) || (mCurrentTarget == TARGET_MSM7627) ) {
Mohan Kandra02486042010-06-18 16:49:43 -07002575 int rotation = mParameters.getInt("rotation");
2576 if (rotation >= 0) {
2577 LOGV("initRaw, jpeg_rotation = %d", rotation);
2578 if(!LINK_jpeg_encoder_setRotation(rotation)) {
2579 LOGE("native_jpeg_encode set rotation failed");
2580 return false;
2581 }
2582 }
2583 LINK_jpeg_encoder_get_buffer_offset(rawWidth, rawHeight, (uint32_t *)&yOffset,
2584 (uint32_t *)&CbCrOffsetRaw, (uint32_t *)&mRawSize);
2585 LOGV("initRaw: yOffset = %d, CbCrOffsetRaw = %d, mRawSize = %d",
2586 yOffset, CbCrOffsetRaw, mRawSize);
2587 mJpegMaxSize = mRawSize;
2588 }
2589
Nishant Pandit62fe9aa2010-07-27 04:23:17 +05302590 if(mCurrentTarget == TARGET_MSM8660)
2591 pmem_region = "/dev/pmem_smipool";
2592 else
2593 pmem_region = "/dev/pmem_adsp";
2594
2595
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002596 LOGV("initRaw: initializing mRawHeap.");
2597 mRawHeap =
Nishant Pandit62fe9aa2010-07-27 04:23:17 +05302598 new PmemPool(pmem_region,
Dinesh Gargeecf1a62010-04-19 16:31:30 -07002599 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002600 mCameraControlFd,
2601 MSM_PMEM_MAINIMG,
2602 mJpegMaxSize,
2603 kRawBufferCount,
2604 mRawSize,
Mohan Kandra02486042010-06-18 16:49:43 -07002605 CbCrOffsetRaw,
2606 yOffset,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002607 "snapshot camera");
2608
2609 if (!mRawHeap->initialized()) {
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002610 LOGE("initRaw X failed ");
2611 mRawHeap.clear();
2612 LOGE("initRaw X: error initializing mRawHeap");
2613 return false;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002614 }
2615
2616 LOGV("do_mmap snapshot pbuf = %p, pmem_fd = %d",
2617 (uint8_t *)mRawHeap->mHeap->base(), mRawHeap->mHeap->getHeapID());
2618
2619 // Jpeg
2620
2621 if (initJpegHeap) {
2622 LOGV("initRaw: initializing mJpegHeap.");
2623 mJpegHeap =
2624 new AshmemPool(mJpegMaxSize,
2625 kJpegBufferCount,
2626 0, // we do not know how big the picture will be
2627 "jpeg");
2628
2629 if (!mJpegHeap->initialized()) {
2630 mJpegHeap.clear();
2631 mRawHeap.clear();
2632 LOGE("initRaw X failed: error initializing mJpegHeap.");
2633 return false;
2634 }
2635
2636 // Thumbnails
2637
2638 mThumbnailHeap =
Nishant Pandit62fe9aa2010-07-27 04:23:17 +05302639 new PmemPool(pmem_region,
Dinesh Gargeecf1a62010-04-19 16:31:30 -07002640 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002641 mCameraControlFd,
2642 MSM_PMEM_THUMBNAIL,
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08002643 thumbnailBufferSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002644 1,
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08002645 thumbnailBufferSize,
Mohan Kandra02486042010-06-18 16:49:43 -07002646 CbCrOffsetThumb,
2647 0,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002648 "thumbnail");
2649
2650 if (!mThumbnailHeap->initialized()) {
2651 mThumbnailHeap.clear();
2652 mJpegHeap.clear();
2653 mRawHeap.clear();
2654 LOGE("initRaw X failed: error initializing mThumbnailHeap.");
2655 return false;
2656 }
2657 }
2658
2659 LOGV("initRaw X");
2660 return true;
2661}
2662
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002663
2664void QualcommCameraHardware::deinitRawSnapshot()
2665{
2666 LOGV("deinitRawSnapshot E");
2667 mRawSnapShotPmemHeap.clear();
2668 mRawSnapshotAshmemHeap.clear();
2669 LOGV("deinitRawSnapshot X");
2670}
2671
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002672void QualcommCameraHardware::deinitRaw()
2673{
2674 LOGV("deinitRaw E");
2675
2676 mThumbnailHeap.clear();
2677 mJpegHeap.clear();
2678 mRawHeap.clear();
2679 mDisplayHeap.clear();
2680
2681 LOGV("deinitRaw X");
2682}
2683
2684void QualcommCameraHardware::release()
2685{
2686 LOGD("release E");
2687 Mutex::Autolock l(&mLock);
2688
2689#if DLOPEN_LIBMMCAMERA
2690 if (libmmcamera == NULL) {
2691 LOGE("ERROR: multiple release!");
2692 return;
2693 }
2694#else
2695#warning "Cannot detect multiple release when not dlopen()ing libqcamera!"
2696#endif
2697
2698 int cnt, rc;
2699 struct msm_ctrl_cmd ctrlCmd;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002700 if (mCameraRunning) {
2701 if(mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME)) {
2702 mRecordFrameLock.lock();
2703 mReleasedRecordingFrame = true;
2704 mRecordWait.signal();
2705 mRecordFrameLock.unlock();
2706 }
2707 stopPreviewInternal();
2708 }
2709
Nishant Pandit3c278cd2010-07-13 15:56:04 +05302710 if( (mCurrentTarget == TARGET_MSM7630) || (mCurrentTarget == TARGET_MSM8660) ) {
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002711 mPostViewHeap.clear();
2712 mPostViewHeap = NULL;
2713 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002714 LINK_jpeg_encoder_join();
Srinivasan Kannan426cde72010-06-04 09:37:21 -07002715 {
2716 Mutex::Autolock l (&mRawPictureHeapLock);
2717 deinitRaw();
2718 }
Mohan Kandraca2e7a92010-06-21 15:48:45 -07002719 //Signal the snapshot thread
2720 mJpegThreadWaitLock.lock();
2721 mJpegThreadRunning = false;
2722 mJpegThreadWait.signal();
2723 mJpegThreadWaitLock.unlock();
2724
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002725 deinitRawSnapshot();
Srinivasan Kannan426cde72010-06-04 09:37:21 -07002726
Priyanka Kharat85cebed2010-05-12 14:57:57 -07002727
2728 ctrlCmd.timeout_ms = 5000;
2729 ctrlCmd.length = 0;
2730 ctrlCmd.type = (uint16_t)CAMERA_EXIT;
2731 ctrlCmd.resp_fd = mCameraControlFd; // FIXME: this will be put in by the kernel
2732 if (ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0)
2733 LOGE("ioctl CAMERA_EXIT fd %d error %s",
2734 mCameraControlFd, strerror(errno));
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002735
Kiran Kumar H N7ac84e32010-02-01 10:58:47 -08002736 LINK_release_cam_conf_thread();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002737 close(mCameraControlFd);
2738 mCameraControlFd = -1;
Mohan Kandra284966d2010-01-05 13:39:15 -08002739 if(fb_fd >= 0) {
2740 close(fb_fd);
2741 fb_fd = -1;
2742 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002743#if DLOPEN_LIBMMCAMERA
2744 if (libmmcamera) {
2745 ::dlclose(libmmcamera);
2746 LOGV("dlclose(libqcamera)");
2747 libmmcamera = NULL;
2748 }
2749#endif
2750
Priyanka Kharatf2deffb2010-05-17 18:11:31 -07002751 singleton_lock.lock();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002752 singleton_releasing = true;
Srinivasan Kannan78444e42010-06-10 15:39:29 -07002753 singleton_releasing_start_time = systemTime();
Priyanka Kharatf2deffb2010-05-17 18:11:31 -07002754 singleton_lock.unlock();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002755
2756 LOGD("release X");
2757}
2758
2759QualcommCameraHardware::~QualcommCameraHardware()
2760{
2761 LOGD("~QualcommCameraHardware E");
Priyanka Kharatf2deffb2010-05-17 18:11:31 -07002762 singleton_lock.lock();
Apurva Rajguruc73c1722010-04-15 17:39:11 -07002763
Nishant Pandit3c278cd2010-07-13 15:56:04 +05302764 if( mCurrentTarget == TARGET_MSM7630 || mCurrentTarget == TARGET_QSD8250 || mCurrentTarget == TARGET_MSM8660 ) {
Apurva Rajguruc73c1722010-04-15 17:39:11 -07002765 delete [] recordframes;
2766 recordframes = NULL;
Mohan Kandra1fd90f92010-06-17 14:54:17 -07002767 delete [] record_buffers_tracking_flag;
2768 record_buffers_tracking_flag = NULL;
Apurva Rajguruc73c1722010-04-15 17:39:11 -07002769 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002770 singleton.clear();
2771 singleton_releasing = false;
Srinivasan Kannan78444e42010-06-10 15:39:29 -07002772 singleton_releasing_start_time = 0;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002773 singleton_wait.signal();
Priyanka Kharatf2deffb2010-05-17 18:11:31 -07002774 singleton_lock.unlock();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002775 LOGD("~QualcommCameraHardware X");
2776}
2777
2778sp<IMemoryHeap> QualcommCameraHardware::getRawHeap() const
2779{
2780 LOGV("getRawHeap");
2781 return mDisplayHeap != NULL ? mDisplayHeap->mHeap : NULL;
2782}
2783
2784sp<IMemoryHeap> QualcommCameraHardware::getPreviewHeap() const
2785{
2786 LOGV("getPreviewHeap");
Mohan Kandrad9efed92010-01-15 19:08:39 -08002787 return mPreviewHeap != NULL ? mPreviewHeap->mHeap : NULL;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002788}
2789
2790status_t QualcommCameraHardware::startPreviewInternal()
2791{
Sravankb4f5f1c2010-01-21 11:06:17 +05302792 LOGV("in startPreviewInternal : E");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002793 if(mCameraRunning) {
2794 LOGV("startPreview X: preview already running.");
2795 return NO_ERROR;
2796 }
2797
2798 if (!mPreviewInitialized) {
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002799 mLastQueuedFrame = NULL;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002800 mPreviewInitialized = initPreview();
2801 if (!mPreviewInitialized) {
2802 LOGE("startPreview X initPreview failed. Not starting preview.");
2803 return UNKNOWN_ERROR;
2804 }
2805 }
2806
Srinivasan Kannan74712c92010-04-07 13:36:48 -07002807 {
2808 Mutex::Autolock cameraRunningLock(&mCameraRunningLock);
2809 if(( mCurrentTarget != TARGET_MSM7630 ) &&
Nishant Pandit3c278cd2010-07-13 15:56:04 +05302810 (mCurrentTarget != TARGET_QSD8250) && (mCurrentTarget != TARGET_MSM8660))
Srinivasan Kannan74712c92010-04-07 13:36:48 -07002811 mCameraRunning = native_start_preview(mCameraControlFd);
2812 else
2813 mCameraRunning = native_start_video(mCameraControlFd);
2814 }
Sravankb4f5f1c2010-01-21 11:06:17 +05302815
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002816 if(!mCameraRunning) {
2817 deinitPreview();
2818 mPreviewInitialized = false;
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08002819 mOverlay = NULL;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002820 LOGE("startPreview X: native_start_preview failed!");
2821 return UNKNOWN_ERROR;
2822 }
2823
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08002824 //Reset the Gps Information
2825 exif_table_numEntries = 0;
Mohan Kandra284966d2010-01-05 13:39:15 -08002826
Sravankb4f5f1c2010-01-21 11:06:17 +05302827 LOGV("startPreviewInternal X");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002828 return NO_ERROR;
2829}
2830
2831status_t QualcommCameraHardware::startPreview()
2832{
2833 LOGV("startPreview E");
2834 Mutex::Autolock l(&mLock);
2835 return startPreviewInternal();
2836}
2837
2838void QualcommCameraHardware::stopPreviewInternal()
2839{
2840 LOGV("stopPreviewInternal E: %d", mCameraRunning);
2841 if (mCameraRunning) {
2842 // Cancel auto focus.
2843 {
2844 if (mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS)) {
2845 cancelAutoFocusInternal();
2846 }
2847 }
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002848
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002849 Mutex::Autolock l(&mCamframeTimeoutLock);
Srinivasan Kannan74712c92010-04-07 13:36:48 -07002850 {
2851 Mutex::Autolock cameraRunningLock(&mCameraRunningLock);
2852 if(!camframe_timeout_flag) {
2853 if (( mCurrentTarget != TARGET_MSM7630 ) &&
Nishant Pandit3c278cd2010-07-13 15:56:04 +05302854 (mCurrentTarget != TARGET_QSD8250) && (mCurrentTarget != TARGET_MSM8660))
Srinivasan Kannan74712c92010-04-07 13:36:48 -07002855 mCameraRunning = !native_stop_preview(mCameraControlFd);
2856 else
2857 mCameraRunning = !native_stop_video(mCameraControlFd);
2858 } else {
2859 /* This means that the camframetimeout was issued.
2860 * But we did not issue native_stop_preview(), so we
2861 * need to update mCameraRunning to indicate that
2862 * Camera is no longer running. */
2863 mCameraRunning = 0;
2864 }
2865 }
Sravankb4f5f1c2010-01-21 11:06:17 +05302866
Kiran Kumar H Nac2f4952009-12-17 01:16:53 -08002867 if (!mCameraRunning && mPreviewInitialized) {
2868 deinitPreview();
Nishant Pandit3c278cd2010-07-13 15:56:04 +05302869 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250) || (mCurrentTarget == TARGET_MSM8660)) {
Mohan Kandra156d0ac2010-01-25 16:59:17 -08002870 mVideoThreadWaitLock.lock();
2871 LOGV("in stopPreviewInternal: making mVideoThreadExit 1");
2872 mVideoThreadExit = 1;
2873 mVideoThreadWaitLock.unlock();
2874 // 720p : signal the video thread , and check in video thread if stop is called, if so exit video thread.
2875 pthread_mutex_lock(&(g_busy_frame_queue.mut));
2876 pthread_cond_signal(&(g_busy_frame_queue.wait));
2877 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
Mohan Kandra1ade9a82010-03-02 10:11:26 -08002878 /* Flush the Busy Q */
2879 cam_frame_flush_video();
2880 /* Flush the Free Q */
2881 LINK_cam_frame_flush_free_video();
Mohan Kandra156d0ac2010-01-25 16:59:17 -08002882 }
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002883 mPreviewInitialized = false;
2884 }
Kiran Kumar H Nac2f4952009-12-17 01:16:53 -08002885 else LOGE("stopPreviewInternal: failed to stop preview");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002886 }
2887 LOGV("stopPreviewInternal X: %d", mCameraRunning);
2888}
2889
2890void QualcommCameraHardware::stopPreview()
2891{
2892 LOGV("stopPreview: E");
2893 Mutex::Autolock l(&mLock);
2894 {
2895 if (mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME))
2896 return;
2897 }
2898 stopPreviewInternal();
2899 LOGV("stopPreview: X");
2900}
2901
2902void QualcommCameraHardware::runAutoFocus()
2903{
2904 bool status = true;
2905 void *libhandle = NULL;
Srinivasan Kannan71229622009-12-04 12:05:58 -08002906 isp3a_af_mode_t afMode;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002907
2908 mAutoFocusThreadLock.lock();
2909 // Skip autofocus if focus mode is infinity.
Srinivasan Kannan74712c92010-04-07 13:36:48 -07002910 if ((mParameters.get(CameraParameters::KEY_FOCUS_MODE) == 0)
2911 || (strcmp(mParameters.get(CameraParameters::KEY_FOCUS_MODE),
2912 CameraParameters::FOCUS_MODE_INFINITY) == 0)) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002913 goto done;
2914 }
2915
2916 mAutoFocusFd = open(MSM_CAMERA_CONTROL, O_RDWR);
2917 if (mAutoFocusFd < 0) {
2918 LOGE("autofocus: cannot open %s: %s",
2919 MSM_CAMERA_CONTROL,
2920 strerror(errno));
2921 mAutoFocusThreadRunning = false;
2922 mAutoFocusThreadLock.unlock();
2923 return;
2924 }
2925
2926#if DLOPEN_LIBMMCAMERA
2927 // We need to maintain a reference to libqcamera.so for the duration of the
2928 // AF thread, because we do not know when it will exit relative to the
2929 // lifetime of this object. We do not want to dlclose() libqcamera while
2930 // LINK_cam_frame is still running.
2931 libhandle = ::dlopen("liboemcamera.so", RTLD_NOW);
2932 LOGV("AF: loading libqcamera at %p", libhandle);
2933 if (!libhandle) {
2934 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
2935 close(mAutoFocusFd);
2936 mAutoFocusFd = -1;
2937 mAutoFocusThreadRunning = false;
2938 mAutoFocusThreadLock.unlock();
2939 return;
2940 }
2941#endif
2942
Srinivasan Kannan71229622009-12-04 12:05:58 -08002943 afMode = (isp3a_af_mode_t)attr_lookup(focus_modes,
2944 sizeof(focus_modes) / sizeof(str_map),
2945 mParameters.get(CameraParameters::KEY_FOCUS_MODE));
2946
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002947 /* This will block until either AF completes or is cancelled. */
Srinivasan Kannan71229622009-12-04 12:05:58 -08002948 LOGV("af start (fd %d mode %d)", mAutoFocusFd, afMode);
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08002949 status_t err;
2950 err = mAfLock.tryLock();
2951 if(err == NO_ERROR) {
Srinivasan Kannan74712c92010-04-07 13:36:48 -07002952 {
2953 Mutex::Autolock cameraRunningLock(&mCameraRunningLock);
2954 if(mCameraRunning){
2955 LOGV("Start AF");
2956 status = native_set_afmode(mAutoFocusFd, afMode);
2957 }else{
2958 LOGV("As Camera preview is not running, AF not issued");
2959 status = false;
2960 }
2961 }
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08002962 mAfLock.unlock();
2963 }
2964 else{
2965 //AF Cancel would have acquired the lock,
2966 //so, no need to perform any AF
Srinivasan Kannan99e82422010-02-28 15:32:16 -08002967 LOGV("As Cancel auto focus is in progress, auto focus request "
2968 "is ignored");
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08002969 status = FALSE;
2970 }
2971
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002972 LOGV("af done: %d", (int)status);
2973 close(mAutoFocusFd);
2974 mAutoFocusFd = -1;
2975
2976done:
2977 mAutoFocusThreadRunning = false;
2978 mAutoFocusThreadLock.unlock();
2979
2980 mCallbackLock.lock();
2981 bool autoFocusEnabled = mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS);
2982 notify_callback cb = mNotifyCallback;
2983 void *data = mCallbackCookie;
2984 mCallbackLock.unlock();
2985 if (autoFocusEnabled)
2986 cb(CAMERA_MSG_FOCUS, status, 0, data);
2987
2988#if DLOPEN_LIBMMCAMERA
2989 if (libhandle) {
2990 ::dlclose(libhandle);
2991 LOGV("AF: dlclose(libqcamera)");
2992 }
2993#endif
2994}
2995
2996status_t QualcommCameraHardware::cancelAutoFocusInternal()
2997{
2998 LOGV("cancelAutoFocusInternal E");
2999
Srinivasan Kannan71229622009-12-04 12:05:58 -08003000 if(!sensorType->hasAutoFocusSupport){
3001 LOGV("cancelAutoFocusInternal X");
3002 return NO_ERROR;
3003 }
3004
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003005#if 0
3006 if (mAutoFocusFd < 0) {
3007 LOGV("cancelAutoFocusInternal X: not in progress");
3008 return NO_ERROR;
3009 }
3010#endif
3011
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08003012 status_t rc = NO_ERROR;
3013 status_t err;
3014 err = mAfLock.tryLock();
3015 if(err == NO_ERROR) {
3016 //Got Lock, means either AF hasn't started or
3017 // AF is done. So no need to cancel it, just change the state
Srinivasan Kannan99e82422010-02-28 15:32:16 -08003018 LOGV("As Auto Focus is not in progress, Cancel Auto Focus "
3019 "is ignored");
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08003020 mAfLock.unlock();
3021 }
3022 else {
3023 //AF is in Progess, So cancel it
3024 LOGV("Lock busy...cancel AF");
3025 rc = native_cancel_afmode(mCameraControlFd, mAutoFocusFd) ?
3026 NO_ERROR :
3027 UNKNOWN_ERROR;
3028 }
3029
3030
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003031
3032 LOGV("cancelAutoFocusInternal X: %d", rc);
3033 return rc;
3034}
3035
3036void *auto_focus_thread(void *user)
3037{
3038 LOGV("auto_focus_thread E");
3039 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
3040 if (obj != 0) {
3041 obj->runAutoFocus();
3042 }
3043 else LOGW("not starting autofocus: the object went away!");
3044 LOGV("auto_focus_thread X");
3045 return NULL;
3046}
3047
3048status_t QualcommCameraHardware::autoFocus()
3049{
3050 LOGV("autoFocus E");
3051 Mutex::Autolock l(&mLock);
3052
Srinivasan Kannan71229622009-12-04 12:05:58 -08003053 if(!sensorType->hasAutoFocusSupport){
Srinivasan Kannandf085222009-12-09 18:31:00 -08003054 bool status = false;
3055 mCallbackLock.lock();
3056 bool autoFocusEnabled = mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS);
3057 notify_callback cb = mNotifyCallback;
3058 void *data = mCallbackCookie;
3059 mCallbackLock.unlock();
3060 if (autoFocusEnabled)
3061 cb(CAMERA_MSG_FOCUS, status, 0, data);
Srinivasan Kannan71229622009-12-04 12:05:58 -08003062 LOGV("autoFocus X");
3063 return NO_ERROR;
3064 }
3065
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003066 if (mCameraControlFd < 0) {
3067 LOGE("not starting autofocus: main control fd %d", mCameraControlFd);
3068 return UNKNOWN_ERROR;
3069 }
3070
3071 {
3072 mAutoFocusThreadLock.lock();
3073 if (!mAutoFocusThreadRunning) {
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08003074 if (native_prepare_snapshot(mCameraControlFd) == FALSE) {
3075 LOGE("native_prepare_snapshot failed!\n");
3076 mAutoFocusThreadLock.unlock();
3077 return UNKNOWN_ERROR;
3078 }
3079
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003080 // Create a detached thread here so that we don't have to wait
3081 // for it when we cancel AF.
3082 pthread_t thr;
3083 pthread_attr_t attr;
3084 pthread_attr_init(&attr);
3085 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
3086 mAutoFocusThreadRunning =
3087 !pthread_create(&thr, &attr,
3088 auto_focus_thread, NULL);
3089 if (!mAutoFocusThreadRunning) {
3090 LOGE("failed to start autofocus thread");
3091 mAutoFocusThreadLock.unlock();
3092 return UNKNOWN_ERROR;
3093 }
3094 }
3095 mAutoFocusThreadLock.unlock();
3096 }
3097
3098 LOGV("autoFocus X");
3099 return NO_ERROR;
3100}
3101
3102status_t QualcommCameraHardware::cancelAutoFocus()
3103{
3104 LOGV("cancelAutoFocus E");
3105 Mutex::Autolock l(&mLock);
3106
3107 int rc = NO_ERROR;
3108 if (mCameraRunning && mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS)) {
3109 rc = cancelAutoFocusInternal();
3110 }
3111
3112 LOGV("cancelAutoFocus X");
3113 return rc;
3114}
3115
3116void QualcommCameraHardware::runSnapshotThread(void *data)
3117{
3118 LOGV("runSnapshotThread E");
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08003119 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
3120 if (native_start_snapshot(mCameraControlFd))
3121 receiveRawPicture();
3122 else
3123 LOGE("main: native_start_snapshot failed!");
3124 } else if(mSnapshotFormat == PICTURE_FORMAT_RAW){
3125 if(native_start_raw_snapshot(mCameraControlFd)){
3126 receiveRawSnapshot();
3127 } else {
3128 LOGE("main: native_start_raw_snapshot failed!");
3129 }
3130 }
Mohan Kandraca2e7a92010-06-21 15:48:45 -07003131 mInSnapshotModeWaitLock.lock();
3132 mInSnapshotMode = false;
3133 mInSnapshotModeWait.signal();
3134 mInSnapshotModeWaitLock.unlock();
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08003135
3136 mSnapshotFormat = 0;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003137
Mohan Kandraca2e7a92010-06-21 15:48:45 -07003138 mJpegThreadWaitLock.lock();
3139 while (mJpegThreadRunning) {
3140 LOGV("runSnapshotThread: waiting for jpeg thread to complete.");
3141 mJpegThreadWait.wait(mJpegThreadWaitLock);
3142 LOGV("runSnapshotThread: jpeg thread completed.");
3143 }
3144 mJpegThreadWaitLock.unlock();
3145 //clear the resources
3146 LINK_jpeg_encoder_join();
3147 deinitRaw();
3148
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003149 mSnapshotThreadWaitLock.lock();
3150 mSnapshotThreadRunning = false;
3151 mSnapshotThreadWait.signal();
3152 mSnapshotThreadWaitLock.unlock();
3153
3154 LOGV("runSnapshotThread X");
3155}
3156
3157void *snapshot_thread(void *user)
3158{
3159 LOGD("snapshot_thread E");
3160 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
3161 if (obj != 0) {
3162 obj->runSnapshotThread(user);
3163 }
3164 else LOGW("not starting snapshot thread: the object went away!");
3165 LOGD("snapshot_thread X");
3166 return NULL;
3167}
3168
3169status_t QualcommCameraHardware::takePicture()
3170{
3171 LOGV("takePicture(%d)", mMsgEnabled);
3172 Mutex::Autolock l(&mLock);
3173
3174 // Wait for old snapshot thread to complete.
3175 mSnapshotThreadWaitLock.lock();
3176 while (mSnapshotThreadRunning) {
3177 LOGV("takePicture: waiting for old snapshot thread to complete.");
3178 mSnapshotThreadWait.wait(mSnapshotThreadWaitLock);
3179 LOGV("takePicture: old snapshot thread completed.");
3180 }
3181
Nishant Pandit3c278cd2010-07-13 15:56:04 +05303182 if( (mCurrentTarget == TARGET_MSM7630) || (mCurrentTarget == TARGET_MSM8660)) {
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003183 /* Store the last frame queued for preview. This
3184 * shall be used as postview */
3185 storePreviewFrameForPostview();
3186 }
3187
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08003188 //mSnapshotFormat is protected by mSnapshotThreadWaitLock
3189 if(mParameters.getPictureFormat() != 0 &&
3190 !strcmp(mParameters.getPictureFormat(),
3191 CameraParameters::PIXEL_FORMAT_RAW))
3192 mSnapshotFormat = PICTURE_FORMAT_RAW;
3193 else
3194 mSnapshotFormat = PICTURE_FORMAT_JPEG;
3195
3196 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
3197 if(!native_prepare_snapshot(mCameraControlFd)) {
3198 mSnapshotThreadWaitLock.unlock();
3199 return UNKNOWN_ERROR;
3200 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003201 }
3202
3203 stopPreviewInternal();
3204
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08003205 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
3206 if (!initRaw(mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE))) {
3207 LOGE("initRaw failed. Not taking picture.");
3208 mSnapshotThreadWaitLock.unlock();
3209 return UNKNOWN_ERROR;
3210 }
3211 } else if(mSnapshotFormat == PICTURE_FORMAT_RAW ){
3212 if(!initRawSnapshot()){
3213 LOGE("initRawSnapshot failed. Not taking picture.");
3214 mSnapshotThreadWaitLock.unlock();
3215 return UNKNOWN_ERROR;
3216 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003217 }
3218
3219 mShutterLock.lock();
3220 mShutterPending = true;
3221 mShutterLock.unlock();
3222
3223 pthread_attr_t attr;
3224 pthread_attr_init(&attr);
3225 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
3226 mSnapshotThreadRunning = !pthread_create(&mSnapshotThread,
3227 &attr,
3228 snapshot_thread,
3229 NULL);
3230 mSnapshotThreadWaitLock.unlock();
3231
Mohan Kandraca2e7a92010-06-21 15:48:45 -07003232 mInSnapshotModeWaitLock.lock();
3233 mInSnapshotMode = true;
3234 mInSnapshotModeWaitLock.unlock();
3235
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003236 LOGV("takePicture: X");
3237 return mSnapshotThreadRunning ? NO_ERROR : UNKNOWN_ERROR;
3238}
3239
3240status_t QualcommCameraHardware::cancelPicture()
3241{
3242 status_t rc;
3243 LOGV("cancelPicture: E");
3244 rc = native_stop_snapshot(mCameraControlFd) ? NO_ERROR : UNKNOWN_ERROR;
3245 LOGV("cancelPicture: X: %d", rc);
3246 return rc;
3247}
3248
3249status_t QualcommCameraHardware::setParameters(const CameraParameters& params)
3250{
3251 LOGV("setParameters: E params = %p", &params);
3252
3253 Mutex::Autolock l(&mLock);
3254 status_t rc, final_rc = NO_ERROR;
3255
3256 if ((rc = setPreviewSize(params))) final_rc = rc;
Srinivasan Kannana01751b2010-06-24 18:44:40 -07003257 if ((rc = setPreviewFrameRate(params))) final_rc = rc;
Mohan Kandrabf6146d2010-07-20 18:48:37 -07003258 if ((rc = setPreviewFrameRateMode(params))) final_rc = rc;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003259 if ((rc = setPictureSize(params))) final_rc = rc;
3260 if ((rc = setJpegQuality(params))) final_rc = rc;
3261 if ((rc = setAntibanding(params))) final_rc = rc;
Srinivasan Kannan4cc4b862010-06-30 14:22:26 -07003262 if ((rc = setExposureCompensation(params))) final_rc = rc;
Apurva Rajguru55562b02009-12-03 12:25:35 -08003263 if ((rc = setAutoExposure(params))) final_rc = rc;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003264 if ((rc = setWhiteBalance(params))) final_rc = rc;
Vamshidhar Kondrae7b9b5a2010-02-25 15:40:37 +05303265 if ((rc = setEffect(params))) final_rc = rc;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003266 if ((rc = setFlash(params))) final_rc = rc;
3267 if ((rc = setGpsLocation(params))) final_rc = rc;
3268 if ((rc = setRotation(params))) final_rc = rc;
3269 if ((rc = setZoom(params))) final_rc = rc;
3270 if ((rc = setFocusMode(params))) final_rc = rc;
3271 if ((rc = setOrientation(params))) final_rc = rc;
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303272 if ((rc = setBrightness(params))) final_rc = rc;
3273 if ((rc = setLensshadeValue(params))) final_rc = rc;
3274 if ((rc = setISOValue(params))) final_rc = rc;
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08003275 if ((rc = setPictureFormat(params))) final_rc = rc;
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003276 if ((rc = setSharpness(params))) final_rc = rc;
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003277 if ((rc = setSaturation(params))) final_rc = rc;
Apurva Rajguru7b949c92010-05-26 15:46:57 -07003278 if ((rc = setContinuousAf(params))) final_rc = rc;
Apurva Rajguru0a2cb922010-06-08 15:33:22 -07003279 if ((rc = setTouchAfAec(params))) final_rc = rc;
Apurva Rajguru08383852010-05-17 14:25:39 -07003280 if ((rc = setSceneMode(params))) final_rc = rc;
3281 if ((rc = setContrast(params))) final_rc = rc;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003282
3283 LOGV("setParameters: X");
3284 return final_rc;
3285}
3286
3287CameraParameters QualcommCameraHardware::getParameters() const
3288{
3289 LOGV("getParameters: EX");
3290 return mParameters;
3291}
3292
3293status_t QualcommCameraHardware::sendCommand(int32_t command, int32_t arg1,
3294 int32_t arg2)
3295{
3296 LOGV("sendCommand: EX");
3297 return BAD_VALUE;
3298}
3299
3300extern "C" sp<CameraHardwareInterface> openCameraHardware()
3301{
3302 LOGV("openCameraHardware: call createInstance");
3303 return QualcommCameraHardware::createInstance();
3304}
3305
3306wp<QualcommCameraHardware> QualcommCameraHardware::singleton;
3307
3308// If the hardware already exists, return a strong pointer to the current
3309// object. If not, create a new hardware object, put it in the singleton,
3310// and return it.
3311sp<CameraHardwareInterface> QualcommCameraHardware::createInstance()
3312{
3313 LOGD("createInstance: E");
3314
Priyanka Kharatf2deffb2010-05-17 18:11:31 -07003315 singleton_lock.lock();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003316
3317 // Wait until the previous release is done.
3318 while (singleton_releasing) {
Srinivasan Kannan78444e42010-06-10 15:39:29 -07003319 if((singleton_releasing_start_time != 0) &&
3320 (systemTime() - singleton_releasing_start_time) > SINGLETON_RELEASING_WAIT_TIME){
3321 LOGV("in createinstance system time is %lld %lld %lld ",
3322 systemTime(), singleton_releasing_start_time, SINGLETON_RELEASING_WAIT_TIME);
3323 singleton_lock.unlock();
3324 LOGE("Previous singleton is busy and time out exceeded. Returning null");
3325 return NULL;
3326 }
3327 LOGI("Wait for previous release.");
3328 singleton_wait.waitRelative(singleton_lock, SINGLETON_RELEASING_RECHECK_TIMEOUT);
3329 LOGI("out of Wait for previous release.");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003330 }
3331
3332 if (singleton != 0) {
3333 sp<CameraHardwareInterface> hardware = singleton.promote();
3334 if (hardware != 0) {
3335 LOGD("createInstance: X return existing hardware=%p", &(*hardware));
Priyanka Kharatf2deffb2010-05-17 18:11:31 -07003336 singleton_lock.unlock();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003337 return hardware;
3338 }
3339 }
3340
3341 {
3342 struct stat st;
3343 int rc = stat("/dev/oncrpc", &st);
3344 if (rc < 0) {
3345 LOGD("createInstance: X failed to create hardware: %s", strerror(errno));
Priyanka Kharatf2deffb2010-05-17 18:11:31 -07003346 singleton_lock.unlock();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003347 return NULL;
3348 }
3349 }
3350
3351 QualcommCameraHardware *cam = new QualcommCameraHardware();
3352 sp<QualcommCameraHardware> hardware(cam);
3353 singleton = hardware;
3354
3355 if (!cam->startCamera()) {
3356 LOGE("%s: startCamera failed!", __FUNCTION__);
Priyanka Kharatf2deffb2010-05-17 18:11:31 -07003357 singleton_lock.unlock();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003358 return NULL;
3359 }
3360
3361 cam->initDefaultParameters();
3362 LOGD("createInstance: X created hardware=%p", &(*hardware));
Priyanka Kharatf2deffb2010-05-17 18:11:31 -07003363 singleton_lock.unlock();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003364 return hardware;
3365}
3366
3367// For internal use only, hence the strong pointer to the derived type.
3368sp<QualcommCameraHardware> QualcommCameraHardware::getInstance()
3369{
3370 sp<CameraHardwareInterface> hardware = singleton.promote();
3371 if (hardware != 0) {
3372 // LOGV("getInstance: X old instance of hardware");
3373 return sp<QualcommCameraHardware>(static_cast<QualcommCameraHardware*>(hardware.get()));
3374 } else {
3375 LOGV("getInstance: X new instance of hardware");
3376 return sp<QualcommCameraHardware>();
3377 }
3378}
Sravankb4f5f1c2010-01-21 11:06:17 +05303379void QualcommCameraHardware::receiveRecordingFrame(struct msm_frame *frame)
3380{
3381 LOGV("receiveRecordingFrame E");
3382 // post busy frame
3383 if (frame)
3384 {
3385 cam_frame_post_video (frame);
3386 }
3387 else LOGE("in receiveRecordingFrame frame is NULL");
3388 LOGV("receiveRecordingFrame X");
3389}
3390
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003391
Mohan Kandrad9efed92010-01-15 19:08:39 -08003392bool QualcommCameraHardware::native_zoom_image(int fd, int srcOffset, int dstOffSet, common_crop_t *crop)
Mohan Kandra284966d2010-01-05 13:39:15 -08003393{
3394 int result = 0;
3395 struct mdp_blit_req *e;
3396 struct timeval td1, td2;
3397
Mohan Kandra284966d2010-01-05 13:39:15 -08003398 /* Initialize yuv structure */
3399 zoomImage.list.count = 1;
3400
3401 e = &zoomImage.list.req[0];
3402
3403 e->src.width = previewWidth;
3404 e->src.height = previewHeight;
3405 e->src.format = MDP_Y_CBCR_H2V2;
Mohan Kandrad9efed92010-01-15 19:08:39 -08003406 e->src.offset = srcOffset;
3407 e->src.memory_id = fd;
Mohan Kandra284966d2010-01-05 13:39:15 -08003408
3409 e->dst.width = previewWidth;
3410 e->dst.height = previewHeight;
3411 e->dst.format = MDP_Y_CBCR_H2V2;
Mohan Kandrad9efed92010-01-15 19:08:39 -08003412 e->dst.offset = dstOffSet;
3413 e->dst.memory_id = fd;
Mohan Kandra284966d2010-01-05 13:39:15 -08003414
3415 e->transp_mask = 0xffffffff;
3416 e->flags = 0;
3417 e->alpha = 0xff;
3418 if (crop->in2_w != 0 || crop->in2_h != 0) {
3419 e->src_rect.x = (crop->out2_w - crop->in2_w + 1) / 2 - 1;
3420 e->src_rect.y = (crop->out2_h - crop->in2_h + 1) / 2 - 1;
3421 e->src_rect.w = crop->in2_w;
3422 e->src_rect.h = crop->in2_h;
3423 } else {
3424 e->src_rect.x = 0;
3425 e->src_rect.y = 0;
3426 e->src_rect.w = previewWidth;
3427 e->src_rect.h = previewHeight;
3428 }
Mohan Kandrad9efed92010-01-15 19:08:39 -08003429 //LOGV(" native_zoom : SRC_RECT : x,y = %d,%d \t w,h = %d, %d",
3430 // e->src_rect.x, e->src_rect.y, e->src_rect.w, e->src_rect.h);
Mohan Kandra284966d2010-01-05 13:39:15 -08003431
3432 e->dst_rect.x = 0;
3433 e->dst_rect.y = 0;
3434 e->dst_rect.w = previewWidth;
3435 e->dst_rect.h = previewHeight;
3436
3437 result = ioctl(fb_fd, MSMFB_BLIT, &zoomImage.list);
3438 if (result < 0) {
3439 LOGE("MSM_FBIOBLT failed! line=%d\n", __LINE__);
3440 return FALSE;
3441 }
3442 return TRUE;
3443}
3444
Mohan Kandrabad0eaa2010-02-04 15:11:54 -08003445void QualcommCameraHardware::debugShowPreviewFPS() const
Mohan Kandra740cfce2010-01-07 12:58:24 -08003446{
3447 static int mFrameCount;
3448 static int mLastFrameCount = 0;
3449 static nsecs_t mLastFpsTime = 0;
3450 static float mFps = 0;
3451 mFrameCount++;
3452 nsecs_t now = systemTime();
3453 nsecs_t diff = now - mLastFpsTime;
3454 if (diff > ms2ns(250)) {
3455 mFps = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
Mohan Kandrabad0eaa2010-02-04 15:11:54 -08003456 LOGI("Preview Frames Per Second: %.4f", mFps);
Mohan Kandra740cfce2010-01-07 12:58:24 -08003457 mLastFpsTime = now;
3458 mLastFrameCount = mFrameCount;
3459 }
3460}
3461
Mohan Kandrabad0eaa2010-02-04 15:11:54 -08003462void QualcommCameraHardware::debugShowVideoFPS() const
3463{
3464 static int mFrameCount;
3465 static int mLastFrameCount = 0;
3466 static nsecs_t mLastFpsTime = 0;
3467 static float mFps = 0;
3468 mFrameCount++;
3469 nsecs_t now = systemTime();
3470 nsecs_t diff = now - mLastFpsTime;
3471 if (diff > ms2ns(250)) {
3472 mFps = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
3473 LOGI("Video Frames Per Second: %.4f", mFps);
3474 mLastFpsTime = now;
3475 mLastFrameCount = mFrameCount;
3476 }
3477}
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003478void QualcommCameraHardware::receivePreviewFrame(struct msm_frame *frame)
3479{
3480// LOGV("receivePreviewFrame E");
3481
3482 if (!mCameraRunning) {
3483 LOGE("ignoring preview callback--camera has been stopped");
3484 return;
3485 }
3486
Mohan Kandra740cfce2010-01-07 12:58:24 -08003487 if (UNLIKELY(mDebugFps)) {
Mohan Kandrabad0eaa2010-02-04 15:11:54 -08003488 debugShowPreviewFPS();
Mohan Kandra740cfce2010-01-07 12:58:24 -08003489 }
3490
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003491 mCallbackLock.lock();
3492 int msgEnabled = mMsgEnabled;
3493 data_callback pcb = mDataCallback;
3494 void *pdata = mCallbackCookie;
3495 data_callback_timestamp rcb = mDataCallbackTimestamp;
3496 void *rdata = mCallbackCookie;
3497 mCallbackLock.unlock();
3498
3499 // Find the offset within the heap of the current buffer.
Mohan Kandra284966d2010-01-05 13:39:15 -08003500 ssize_t offset_addr =
Mohan Kandrad9efed92010-01-15 19:08:39 -08003501 (ssize_t)frame->buffer - (ssize_t)mPreviewHeap->mHeap->base();
3502 ssize_t offset = offset_addr / mPreviewHeap->mAlignedBufferSize;
Mohan Kandra284966d2010-01-05 13:39:15 -08003503
3504 common_crop_t *crop = (common_crop_t *) (frame->cropinfo);
Nishant Pandit3c278cd2010-07-13 15:56:04 +05303505#ifdef DUMP_PREVIEW_FRAMES
3506 static int frameCnt = 0;
3507 int written;
3508 if (frameCnt >= 0 && frameCnt <= 10 ) {
3509 char buf[128];
3510 sprintf(buf, "/data/%d_preview.yuv", frameCnt);
3511 int file_fd = open(buf, O_RDWR | O_CREAT, 0777);
3512 LOGV("dumping preview frame %d", frameCnt);
3513 if (file_fd < 0) {
3514 LOGE("cannot open file\n");
3515 }
3516 else
3517 {
3518 LOGV("dumping data");
3519 written = write(file_fd, (uint8_t *)frame->buffer,
3520 mPreviewFrameSize );
3521 if(written < 0)
3522 LOGE("error in data write");
3523 }
3524 close(file_fd);
3525 }
3526 frameCnt++;
3527#endif
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003528 mInPreviewCallback = true;
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003529 if(mUseOverlay) {
3530 if(mOverlay != NULL) {
3531 mOverlayLock.lock();
Mohan Kandra54e2a022010-07-06 16:23:58 -07003532 mOverlay->setFd(mPreviewHeap->mHeap->getHeapID());
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003533 if (crop->in2_w != 0 || crop->in2_h != 0) {
3534 zoomCropInfo.x = (crop->out2_w - crop->in2_w + 1) / 2 - 1;
3535 zoomCropInfo.y = (crop->out2_h - crop->in2_h + 1) / 2 - 1;
3536 zoomCropInfo.w = crop->in2_w;
3537 zoomCropInfo.h = crop->in2_h;
3538 mOverlay->setCrop(zoomCropInfo.x, zoomCropInfo.y,
3539 zoomCropInfo.w, zoomCropInfo.h);
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08003540 } else {
3541 // Reset zoomCropInfo variables. This will ensure that
3542 // stale values wont be used for postview
3543 zoomCropInfo.w = crop->in2_w;
3544 zoomCropInfo.h = crop->in2_h;
3545 }
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003546 mOverlay->queueBuffer((void *)offset_addr);
3547 mLastQueuedFrame = (void *)frame->buffer;
3548 mOverlayLock.unlock();
3549 }
Mohan Kandra284966d2010-01-05 13:39:15 -08003550 } else {
Mohan Kandrad9efed92010-01-15 19:08:39 -08003551 if (crop->in2_w != 0 || crop->in2_h != 0) {
3552 dstOffset = (dstOffset + 1) % NUM_MORE_BUFS;
3553 offset = kPreviewBufferCount + dstOffset;
3554 ssize_t dstOffset_addr = offset * mPreviewHeap->mAlignedBufferSize;
3555 if( !native_zoom_image(mPreviewHeap->mHeap->getHeapID(),
3556 offset_addr, dstOffset_addr, crop)) {
3557 LOGE(" Error while doing MDP zoom ");
Kiran Kumar H N1ece71c2010-03-30 10:31:21 -07003558 offset = offset_addr / mPreviewHeap->mAlignedBufferSize;
Mohan Kandrad9efed92010-01-15 19:08:39 -08003559 }
3560 }
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08003561 }
Mohan Kandrad9efed92010-01-15 19:08:39 -08003562 if (pcb != NULL && (msgEnabled & CAMERA_MSG_PREVIEW_FRAME))
3563 pcb(CAMERA_MSG_PREVIEW_FRAME, mPreviewHeap->mBuffers[offset],
3564 pdata);
3565
Nishant Pandit3c278cd2010-07-13 15:56:04 +05303566 // If output is NOT enabled (targets otherthan 7x30 , 8x50 and 8x60 currently..)
3567 if( (mCurrentTarget != TARGET_MSM7630 ) && (mCurrentTarget != TARGET_QSD8250) && (mCurrentTarget != TARGET_MSM8660)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05303568 if(rcb != NULL && (msgEnabled & CAMERA_MSG_VIDEO_FRAME)) {
3569 rcb(systemTime(), CAMERA_MSG_VIDEO_FRAME, mPreviewHeap->mBuffers[offset], rdata);
3570 Mutex::Autolock rLock(&mRecordFrameLock);
3571 if (mReleasedRecordingFrame != true) {
3572 LOGV("block waiting for frame release");
3573 mRecordWait.wait(mRecordFrameLock);
3574 LOGV("frame released, continuing");
3575 }
3576 mReleasedRecordingFrame = false;
3577 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003578 }
3579 mInPreviewCallback = false;
3580
3581// LOGV("receivePreviewFrame X");
3582}
3583
Sravankb4f5f1c2010-01-21 11:06:17 +05303584
3585bool QualcommCameraHardware::initRecord()
3586{
Mohan Kandra62429cc2010-07-19 10:21:05 -07003587 const char *pmem_region;
Apurva Rajguruc73c1722010-04-15 17:39:11 -07003588
Sravankb4f5f1c2010-01-21 11:06:17 +05303589 LOGV("initREcord E");
3590
3591 mRecordFrameSize = (mDimension.video_width * mDimension.video_height *3)/2;
Apurva Rajguruc73c1722010-04-15 17:39:11 -07003592
Nishant Pandit62fe9aa2010-07-27 04:23:17 +05303593 if((mCurrentTarget == TARGET_QSD8250) || (mCurrentTarget == TARGET_MSM8660))
Apurva Rajguruc73c1722010-04-15 17:39:11 -07003594 pmem_region = "/dev/pmem_smipool";
3595 else
3596 pmem_region = "/dev/pmem_adsp";
3597
Mohan Kandra02486042010-06-18 16:49:43 -07003598 int CbCrOffset = PAD_TO_WORD(mDimension.video_width * mDimension.video_height);
Apurva Rajguruc73c1722010-04-15 17:39:11 -07003599 mRecordHeap = new PmemPool(pmem_region,
Sravankb4f5f1c2010-01-21 11:06:17 +05303600 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
3601 mCameraControlFd,
3602 MSM_PMEM_VIDEO,
3603 mRecordFrameSize,
3604 kRecordBufferCount,
3605 mRecordFrameSize,
Mohan Kandra02486042010-06-18 16:49:43 -07003606 CbCrOffset,
3607 0,
Sravankb4f5f1c2010-01-21 11:06:17 +05303608 "record");
Apurva Rajguruc73c1722010-04-15 17:39:11 -07003609
Sravankb4f5f1c2010-01-21 11:06:17 +05303610 if (!mRecordHeap->initialized()) {
3611 mRecordHeap.clear();
3612 LOGE("initRecord X: could not initialize record heap.");
3613 return false;
3614 }
3615 for (int cnt = 0; cnt < kRecordBufferCount; cnt++) {
3616 recordframes[cnt].fd = mRecordHeap->mHeap->getHeapID();
3617 recordframes[cnt].buffer =
3618 (uint32_t)mRecordHeap->mHeap->base() + mRecordHeap->mAlignedBufferSize * cnt;
3619 recordframes[cnt].y_off = 0;
3620 recordframes[cnt].cbcr_off = mDimension.video_width * mDimension.video_height;
3621 recordframes[cnt].path = OUTPUT_TYPE_V;
Mohan Kandra1fd90f92010-06-17 14:54:17 -07003622 record_buffers_tracking_flag[cnt] = false;
Sravankb4f5f1c2010-01-21 11:06:17 +05303623 LOGV ("initRecord : record heap , video buffers buffer=%lu fd=%d y_off=%d cbcr_off=%d \n",
3624 (unsigned long)recordframes[cnt].buffer, recordframes[cnt].fd, recordframes[cnt].y_off,
3625 recordframes[cnt].cbcr_off);
3626 }
3627
3628 // initial setup : buffers 1,2,3 with kernel , 4 with camframe , 5,6,7,8 in free Q
3629 // flush the busy Q
3630 cam_frame_flush_video();
3631
Mohan Kandra156d0ac2010-01-25 16:59:17 -08003632 mVideoThreadWaitLock.lock();
3633 while (mVideoThreadRunning) {
3634 LOGV("initRecord: waiting for old video thread to complete.");
3635 mVideoThreadWait.wait(mVideoThreadWaitLock);
3636 LOGV("initRecord : old video thread completed.");
3637 }
3638 mVideoThreadWaitLock.unlock();
3639
Sravankdf7a9202010-02-08 15:02:51 +05303640 // flush free queue and add 5,6,7,8 buffers.
3641 LINK_cam_frame_flush_free_video();
3642 for(int i=ACTIVE_VIDEO_BUFFERS+1;i <kRecordBufferCount; i++)
3643 LINK_camframe_free_video(&recordframes[i]);
Sravankb4f5f1c2010-01-21 11:06:17 +05303644 LOGV("initREcord X");
3645
3646 return true;
3647}
3648
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003649status_t QualcommCameraHardware::startRecording()
3650{
3651 LOGV("startRecording E");
Sravankb4f5f1c2010-01-21 11:06:17 +05303652 int ret;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003653 Mutex::Autolock l(&mLock);
3654 mReleasedRecordingFrame = false;
Sravankb4f5f1c2010-01-21 11:06:17 +05303655 if( (ret=startPreviewInternal())== NO_ERROR){
Nishant Pandit3c278cd2010-07-13 15:56:04 +05303656 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250) || (mCurrentTarget == TARGET_MSM8660)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05303657 LOGV(" in startREcording : calling native_start_recording");
3658 native_start_recording(mCameraControlFd);
3659 recordingState = 1;
Sravank64461e82010-02-25 15:10:09 +05303660 // Remove the left out frames in busy Q and them in free Q.
3661 // this should be done before starting video_thread so that,
3662 // frames in previous recording are flushed out.
3663 LOGV("frames in busy Q = %d", g_busy_frame_queue.num_of_frames);
3664 while((g_busy_frame_queue.num_of_frames) >0){
3665 msm_frame* vframe = cam_frame_get_video ();
3666 LINK_camframe_free_video(vframe);
3667 }
3668 LOGV("frames in busy Q = %d after deQueing", g_busy_frame_queue.num_of_frames);
3669
Mohan Kandra1fd90f92010-06-17 14:54:17 -07003670 //Clear the dangling buffers and put them in free queue
3671 for(int cnt = 0; cnt < kRecordBufferCount; cnt++) {
3672 if(record_buffers_tracking_flag[cnt] == true) {
Mohan Kandra62429cc2010-07-19 10:21:05 -07003673 LOGI("Dangling buffer: offset = %d, buffer = %d", cnt, (unsigned int)recordframes[cnt].buffer);
Mohan Kandra1fd90f92010-06-17 14:54:17 -07003674 LINK_camframe_free_video(&recordframes[cnt]);
3675 record_buffers_tracking_flag[cnt] = false;
3676 }
3677 }
3678
Sravankdf7a9202010-02-08 15:02:51 +05303679 // Start video thread and wait for busy frames to be encoded, this thread
3680 // should be closed in stopRecording
3681 mVideoThreadWaitLock.lock();
3682 mVideoThreadExit = 0;
3683 pthread_attr_t attr;
3684 pthread_attr_init(&attr);
3685 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
3686 mVideoThreadRunning = pthread_create(&mVideoThread,
3687 &attr,
3688 video_thread,
3689 NULL);
3690 mVideoThreadWaitLock.unlock();
3691 // Remove the left out frames in busy Q and them in free Q.
Sravankb4f5f1c2010-01-21 11:06:17 +05303692 }
3693 }
3694 return ret;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003695}
3696
3697void QualcommCameraHardware::stopRecording()
3698{
3699 LOGV("stopRecording: E");
3700 Mutex::Autolock l(&mLock);
3701 {
3702 mRecordFrameLock.lock();
3703 mReleasedRecordingFrame = true;
3704 mRecordWait.signal();
3705 mRecordFrameLock.unlock();
3706
Sravankdf7a9202010-02-08 15:02:51 +05303707 if(mDataCallback && !(mCurrentTarget == TARGET_QSD8250) &&
3708 (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003709 LOGV("stopRecording: X, preview still in progress");
3710 return;
3711 }
3712 }
Sravankb4f5f1c2010-01-21 11:06:17 +05303713 // If output2 enabled, exit video thread, invoke stop recording ioctl
Nishant Pandit3c278cd2010-07-13 15:56:04 +05303714 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250) || (mCurrentTarget == TARGET_MSM8660)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05303715 mVideoThreadWaitLock.lock();
3716 mVideoThreadExit = 1;
3717 mVideoThreadWaitLock.unlock();
3718 native_stop_recording(mCameraControlFd);
Srinivasan Kannanfc3915c2010-03-18 10:54:40 -07003719
3720 pthread_mutex_lock(&(g_busy_frame_queue.mut));
3721 pthread_cond_signal(&(g_busy_frame_queue.wait));
3722 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
Sravankb4f5f1c2010-01-21 11:06:17 +05303723 }
3724 else // for other targets where output2 is not enabled
3725 stopPreviewInternal();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003726
Sravankb4f5f1c2010-01-21 11:06:17 +05303727 recordingState = 0; // recording not started
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003728 LOGV("stopRecording: X");
3729}
3730
3731void QualcommCameraHardware::releaseRecordingFrame(
3732 const sp<IMemory>& mem __attribute__((unused)))
3733{
3734 LOGV("releaseRecordingFrame E");
3735 Mutex::Autolock rLock(&mRecordFrameLock);
3736 mReleasedRecordingFrame = true;
3737 mRecordWait.signal();
Sravankb4f5f1c2010-01-21 11:06:17 +05303738
3739 // Ff 7x30 : add the frame to the free camframe queue
Nishant Pandit3c278cd2010-07-13 15:56:04 +05303740 if( (mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250) || (mCurrentTarget == TARGET_MSM8660)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05303741 ssize_t offset;
3742 size_t size;
3743 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
3744 msm_frame* releaseframe = NULL;
3745 LOGV(" in release recording frame : heap base %d offset %d buffer %d ", heap->base(), offset, heap->base() + offset );
3746 int cnt;
3747 for (cnt = 0; cnt < kRecordBufferCount; cnt++) {
Mohan Kandra62429cc2010-07-19 10:21:05 -07003748 if((unsigned int)recordframes[cnt].buffer == ((unsigned int)heap->base()+ offset)){
Sravankb4f5f1c2010-01-21 11:06:17 +05303749 LOGV("in release recording frame found match , releasing buffer %d", (unsigned int)recordframes[cnt].buffer);
3750 releaseframe = &recordframes[cnt];
3751 break;
3752 }
3753 }
3754 if(cnt < kRecordBufferCount) {
3755 // do this only if frame thread is running
3756 mFrameThreadWaitLock.lock();
Mohan Kandra1fd90f92010-06-17 14:54:17 -07003757 if(mFrameThreadRunning ) {
3758 //Reset the track flag for this frame buffer
3759 record_buffers_tracking_flag[cnt] = false;
Sravankb4f5f1c2010-01-21 11:06:17 +05303760 LINK_camframe_free_video(releaseframe);
Mohan Kandra1fd90f92010-06-17 14:54:17 -07003761 }
Sravankb4f5f1c2010-01-21 11:06:17 +05303762
3763 mFrameThreadWaitLock.unlock();
3764 } else {
3765 LOGE("in release recordingframe XXXXX error , buffer not found");
3766 for (int i=0; i< kRecordBufferCount; i++) {
3767 LOGE(" recordframes[%d].buffer = %d", i, (unsigned int)recordframes[i].buffer);
3768 }
3769 }
3770 }
3771
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003772 LOGV("releaseRecordingFrame X");
3773}
3774
3775bool QualcommCameraHardware::recordingEnabled()
3776{
3777 return mCameraRunning && mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME);
3778}
3779
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08003780void QualcommCameraHardware::notifyShutter(common_crop_t *crop, bool mPlayShutterSoundOnly)
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003781{
3782 mShutterLock.lock();
3783 image_rect_type size;
3784
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08003785 if(mPlayShutterSoundOnly) {
3786 /* At this point, invoke Notify Callback to play shutter sound only.
3787 * We want to call notify callback again when we have the
3788 * yuv picture ready. This is to reduce blanking at the time
3789 * of displaying postview frame. Using ext2 to indicate whether
3790 * to play shutter sound only or register the postview buffers.
3791 */
3792 mNotifyCallback(CAMERA_MSG_SHUTTER, 0, mPlayShutterSoundOnly,
3793 mCallbackCookie);
3794 mShutterLock.unlock();
3795 return;
3796 }
3797
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003798 if (mShutterPending && mNotifyCallback && (mMsgEnabled & CAMERA_MSG_SHUTTER)) {
3799 LOGV("out2_w=%d, out2_h=%d, in2_w=%d, in2_h=%d",
3800 crop->out2_w, crop->out2_h, crop->in2_w, crop->in2_h);
3801 LOGV("out1_w=%d, out1_h=%d, in1_w=%d, in1_h=%d",
3802 crop->out1_w, crop->out1_h, crop->in1_w, crop->in1_h);
3803
3804 // To workaround a bug in MDP which happens if either
3805 // dimension > 2048, we display the thumbnail instead.
3806 mDisplayHeap = mRawHeap;
3807 if (crop->in1_w == 0 || crop->in1_h == 0) {
3808 // Full size
3809 size.width = mDimension.picture_width;
3810 size.height = mDimension.picture_height;
3811 if (size.width > 2048 || size.height > 2048) {
3812 size.width = mDimension.ui_thumbnail_width;
3813 size.height = mDimension.ui_thumbnail_height;
3814 mDisplayHeap = mThumbnailHeap;
3815 }
3816 } else {
3817 // Cropped
Srinivasan Kannan5701a942010-04-15 16:17:21 -07003818 size.width = (crop->in2_w + jpegPadding) & ~1;
3819 size.height = (crop->in2_h + jpegPadding) & ~1;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003820 if (size.width > 2048 || size.height > 2048) {
Srinivasan Kannan5701a942010-04-15 16:17:21 -07003821 size.width = (crop->in1_w + jpegPadding) & ~1;
3822 size.height = (crop->in1_h + jpegPadding) & ~1;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003823 mDisplayHeap = mThumbnailHeap;
3824 }
3825 }
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08003826 /* Now, invoke Notify Callback to unregister preview buffer
3827 * and register postview buffer with surface flinger. Set ext2
3828 * as 0 to indicate not to play shutter sound.
3829 */
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003830 mNotifyCallback(CAMERA_MSG_SHUTTER, (int32_t)&size, 0,
3831 mCallbackCookie);
3832 mShutterPending = false;
3833 }
3834 mShutterLock.unlock();
3835}
3836
3837static void receive_shutter_callback(common_crop_t *crop)
3838{
3839 LOGV("receive_shutter_callback: E");
3840 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
3841 if (obj != 0) {
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08003842 /* Just play shutter sound at this time */
3843 obj->notifyShutter(crop, TRUE);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003844 }
3845 LOGV("receive_shutter_callback: X");
3846}
3847
3848// Crop the picture in place.
3849static void crop_yuv420(uint32_t width, uint32_t height,
3850 uint32_t cropped_width, uint32_t cropped_height,
3851 uint8_t *image)
3852{
3853 uint32_t i, x, y;
3854 uint8_t* chroma_src, *chroma_dst;
3855
3856 // Calculate the start position of the cropped area.
3857 x = (width - cropped_width) / 2;
3858 y = (height - cropped_height) / 2;
3859 x &= ~1;
3860 y &= ~1;
3861
3862 // Copy luma component.
3863 for(i = 0; i < cropped_height; i++)
3864 memcpy(image + i * cropped_width,
3865 image + width * (y + i) + x,
3866 cropped_width);
3867
3868 chroma_src = image + width * height;
3869 chroma_dst = image + cropped_width * cropped_height;
3870
3871 // Copy chroma components.
3872 cropped_height /= 2;
3873 y /= 2;
3874 for(i = 0; i < cropped_height; i++)
3875 memcpy(chroma_dst + i * cropped_width,
3876 chroma_src + width * (y + i) + x,
3877 cropped_width);
3878}
3879
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08003880
3881void QualcommCameraHardware::receiveRawSnapshot(){
3882 LOGV("receiveRawSnapshot E");
3883
3884 Mutex::Autolock cbLock(&mCallbackLock);
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08003885 /* Issue notifyShutter with mPlayShutterSoundOnly as TRUE */
3886 notifyShutter(&mCrop, TRUE);
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08003887
3888 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
3889
3890 if(native_get_picture(mCameraControlFd, &mCrop) == false) {
3891 LOGE("receiveRawSnapshot X: native_get_picture failed!");
3892 return;
3893 }
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08003894 /* Its necessary to issue another notifyShutter here with
3895 * mPlayShutterSoundOnly as FALSE, since that is when the
3896 * preview buffers are unregistered with the surface flinger.
3897 * That is necessary otherwise the preview memory wont be
3898 * deallocated.
3899 */
3900 notifyShutter(&mCrop, FALSE);
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08003901
3902 //Create a Ashmem heap to copy data from PMem heap for application layer
3903 if(mRawSnapshotAshmemHeap != NULL){
3904 LOGV("receiveRawSnapshot: clearing old mRawSnapShotAshmemHeap.");
3905 mRawSnapshotAshmemHeap.clear();
3906 }
3907 mRawSnapshotAshmemHeap = new AshmemPool(
3908 mRawSnapShotPmemHeap->mBufferSize,
3909 mRawSnapShotPmemHeap->mNumBuffers,
3910 mRawSnapShotPmemHeap->mFrameSize,
3911 "raw ashmem snapshot camera"
3912 );
3913
3914 if(!mRawSnapshotAshmemHeap->initialized()){
3915 LOGE("receiveRawSnapshot X: error initializing mRawSnapshotHeap");
3916 deinitRawSnapshot();
3917 return;
3918 }
3919
3920 memcpy(mRawSnapshotAshmemHeap->mHeap->base(),
3921 mRawSnapShotPmemHeap->mHeap->base(),
3922 mRawSnapShotPmemHeap->mHeap->getSize());
Nishant Panditb861be52010-03-02 16:43:49 +05303923 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE))
3924 mDataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mRawSnapshotAshmemHeap->mBuffers[0],
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08003925 mCallbackCookie);
3926
3927 }
3928
3929 //cleanup
3930 deinitRawSnapshot();
3931
3932 LOGV("receiveRawSnapshot X");
3933}
3934
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003935void QualcommCameraHardware::receiveRawPicture()
3936{
3937 LOGV("receiveRawPicture: E");
3938
3939 Mutex::Autolock cbLock(&mCallbackLock);
3940 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_RAW_IMAGE)) {
3941 if(native_get_picture(mCameraControlFd, &mCrop) == false) {
3942 LOGE("getPicture failed!");
3943 return;
3944 }
3945 mCrop.in1_w &= ~1;
3946 mCrop.in1_h &= ~1;
3947 mCrop.in2_w &= ~1;
3948 mCrop.in2_h &= ~1;
3949
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003950
3951 // Crop the image if zoomed.
Srinivasan Kannan5701a942010-04-15 16:17:21 -07003952 if (mCrop.in2_w != 0 && mCrop.in2_h != 0 &&
3953 ((mCrop.in2_w + jpegPadding) < mCrop.out2_w) &&
3954 ((mCrop.in2_h + jpegPadding) < mCrop.out2_h) &&
3955 ((mCrop.in1_w + jpegPadding) < mCrop.out1_w) &&
3956 ((mCrop.in1_h + jpegPadding) < mCrop.out1_h) ) {
3957
3958 // By the time native_get_picture returns, picture is taken. Call
3959 // shutter callback if cam config thread has not done that.
3960 notifyShutter(&mCrop, FALSE);
Srinivasan Kannan426cde72010-06-04 09:37:21 -07003961 {
3962 Mutex::Autolock l(&mRawPictureHeapLock);
3963 if(mRawHeap != NULL)
3964 crop_yuv420(mCrop.out2_w, mCrop.out2_h, (mCrop.in2_w + jpegPadding), (mCrop.in2_h + jpegPadding),
3965 (uint8_t *)mRawHeap->mHeap->base());
3966 if(mThumbnailHeap != NULL)
3967 crop_yuv420(mCrop.out1_w, mCrop.out1_h, (mCrop.in1_w + jpegPadding), (mCrop.in1_h + jpegPadding),
3968 (uint8_t *)mThumbnailHeap->mHeap->base());
3969 }
Srinivasan Kannan5701a942010-04-15 16:17:21 -07003970
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003971 // We do not need jpeg encoder to upscale the image. Set the new
3972 // dimension for encoder.
Srinivasan Kannan5701a942010-04-15 16:17:21 -07003973 mDimension.orig_picture_dx = mCrop.in2_w + jpegPadding;
3974 mDimension.orig_picture_dy = mCrop.in2_h + jpegPadding;
3975 mDimension.thumbnail_width = mCrop.in1_w + jpegPadding;
3976 mDimension.thumbnail_height = mCrop.in1_h + jpegPadding;
3977 }else {
3978 memset(&mCrop, 0 ,sizeof(mCrop));
3979 // By the time native_get_picture returns, picture is taken. Call
3980 // shutter callback if cam config thread has not done that.
3981 notifyShutter(&mCrop, FALSE);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003982 }
3983
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003984 if( mUseOverlay && (mOverlay != NULL) ) {
Mohan Kandra54e2a022010-07-06 16:23:58 -07003985 mOverlay->setFd(mPostViewHeap->mHeap->getHeapID());
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003986 if( zoomCropInfo.w !=0 && zoomCropInfo.h !=0) {
3987 LOGD(" zoomCropInfo non-zero, setting crop ");
3988 mOverlay->setCrop(zoomCropInfo.x, zoomCropInfo.y,
3989 zoomCropInfo.w, zoomCropInfo.h);
3990 }
3991 LOGD(" Queueing Postview for display ");
3992 mOverlay->queueBuffer((void *)0);
3993 }
Nishant Panditb861be52010-03-02 16:43:49 +05303994 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_RAW_IMAGE))
3995 mDataCallback(CAMERA_MSG_RAW_IMAGE, mDisplayHeap->mBuffers[0],
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003996 mCallbackCookie);
3997 }
3998 else LOGV("Raw-picture callback was canceled--skipping.");
3999
4000 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
4001 mJpegSize = 0;
Mohan Kandraca2e7a92010-06-21 15:48:45 -07004002 mJpegThreadWaitLock.lock();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004003 if (LINK_jpeg_encoder_init()) {
Mohan Kandraca2e7a92010-06-21 15:48:45 -07004004 mJpegThreadRunning = true;
4005 mJpegThreadWaitLock.unlock();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004006 if(native_jpeg_encode()) {
4007 LOGV("receiveRawPicture: X (success)");
4008 return;
4009 }
4010 LOGE("jpeg encoding failed");
4011 }
Mohan Kandraca2e7a92010-06-21 15:48:45 -07004012 else {
4013 LOGE("receiveRawPicture X: jpeg_encoder_init failed.");
4014 mJpegThreadWaitLock.unlock();
4015 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004016 }
4017 else LOGV("JPEG callback is NULL, not encoding image.");
4018 deinitRaw();
4019 LOGV("receiveRawPicture: X");
4020}
4021
4022void QualcommCameraHardware::receiveJpegPictureFragment(
4023 uint8_t *buff_ptr, uint32_t buff_size)
4024{
4025 uint32_t remaining = mJpegHeap->mHeap->virtualSize();
4026 remaining -= mJpegSize;
4027 uint8_t *base = (uint8_t *)mJpegHeap->mHeap->base();
4028
4029 LOGV("receiveJpegPictureFragment size %d", buff_size);
4030 if (buff_size > remaining) {
4031 LOGE("receiveJpegPictureFragment: size %d exceeds what "
4032 "remains in JPEG heap (%d), truncating",
4033 buff_size,
4034 remaining);
4035 buff_size = remaining;
4036 }
4037 memcpy(base + mJpegSize, buff_ptr, buff_size);
4038 mJpegSize += buff_size;
4039}
4040
4041void QualcommCameraHardware::receiveJpegPicture(void)
4042{
4043 LOGV("receiveJpegPicture: E image (%d uint8_ts out of %d)",
4044 mJpegSize, mJpegHeap->mBufferSize);
4045 Mutex::Autolock cbLock(&mCallbackLock);
4046
4047 int index = 0, rc;
4048
4049 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
4050 // The reason we do not allocate into mJpegHeap->mBuffers[offset] is
4051 // that the JPEG image's size will probably change from one snapshot
4052 // to the next, so we cannot reuse the MemoryBase object.
4053 sp<MemoryBase> buffer = new
4054 MemoryBase(mJpegHeap->mHeap,
4055 index * mJpegHeap->mBufferSize +
4056 0,
4057 mJpegSize);
4058 mDataCallback(CAMERA_MSG_COMPRESSED_IMAGE, buffer, mCallbackCookie);
4059 buffer = NULL;
4060 }
4061 else LOGV("JPEG callback was cancelled--not delivering image.");
4062
Mohan Kandraca2e7a92010-06-21 15:48:45 -07004063 mJpegThreadWaitLock.lock();
4064 mJpegThreadRunning = false;
4065 mJpegThreadWait.signal();
4066 mJpegThreadWaitLock.unlock();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004067
4068 LOGV("receiveJpegPicture: X callback done.");
4069}
4070
4071bool QualcommCameraHardware::previewEnabled()
4072{
Kiran Kumar H N280d4de2010-05-05 13:40:15 -07004073 /* If overlay is used the message CAMERA_MSG_PREVIEW_FRAME would
4074 * be disabled at CameraService layer. Hence previewEnabled would
4075 * return FALSE even though preview is running. Hence check for
4076 * mOverlay not being NULL to ensure that previewEnabled returns
4077 * accurate information.
4078 */
4079 return mCameraRunning && mDataCallback &&
4080 ((mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME) || (mOverlay != NULL));
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004081}
4082
4083status_t QualcommCameraHardware::setPreviewSize(const CameraParameters& params)
4084{
4085 int width, height;
4086 params.getPreviewSize(&width, &height);
4087 LOGV("requested preview size %d x %d", width, height);
4088
4089 // Validate the preview size
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -08004090 for (size_t i = 0; i < previewSizeCount; ++i) {
4091 if (width == supportedPreviewSizes[i].width
4092 && height == supportedPreviewSizes[i].height) {
Sravank64461e82010-02-25 15:10:09 +05304093 // 720p , preview can be 768X432 (currently for 7x30 and 8k
4094 // targets)
4095 if(width == 1280 && height == 720 &&
Nishant Pandit3c278cd2010-07-13 15:56:04 +05304096 ((mCurrentTarget == TARGET_MSM7630) || (mCurrentTarget == TARGET_QSD8250) || (mCurrentTarget == TARGET_MSM8660))){
Sravank64461e82010-02-25 15:10:09 +05304097 LOGD("change preview resolution to 768X432 since recording is in 720p");
4098 mDimension.display_width = preview_sizes[2].width;
4099 mDimension.display_height= preview_sizes[2].height;
4100 }else {
4101 mDimension.display_width = width;
4102 mDimension.display_height= height;
4103 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004104 mParameters.setPreviewSize(width, height);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004105 return NO_ERROR;
4106 }
4107 }
4108 LOGE("Invalid preview size requested: %dx%d", width, height);
4109 return BAD_VALUE;
4110}
4111
Srinivasan Kannana01751b2010-06-24 18:44:40 -07004112status_t QualcommCameraHardware::setPreviewFrameRate(const CameraParameters& params)
4113{
Srinivasan Kannanf01d8592010-07-25 13:47:08 -07004114 //Temporary check for mipi sensor
4115 if((!strcmp(mSensorInfo.name, "vx6953")) ||
4116 (!strcmp(mSensorInfo.name, "VX6953"))){
4117 LOGI("set fps is not supported for this sensor");
4118 return NO_ERROR;
4119 }
Srinivasan Kannana01751b2010-06-24 18:44:40 -07004120 uint16_t previousFps = (uint16_t)mParameters.getPreviewFrameRate();
4121 uint16_t fps = (uint16_t)params.getPreviewFrameRate();
4122 LOGV("requested preview frame rate is %u", fps);
4123
4124 if(mInitialized && (fps == previousFps)){
4125 LOGV("fps same as previous fps");
4126 return NO_ERROR;
4127 }
4128
4129 if(MINIMUM_FPS <= fps && fps <=MAXIMUM_FPS){
4130 mParameters.setPreviewFrameRate(fps);
4131 bool ret = native_set_parm(CAMERA_SET_PARM_FPS,
4132 sizeof(fps), (void *)&fps);
4133 return ret ? NO_ERROR : UNKNOWN_ERROR;
4134 }
4135 return BAD_VALUE;
Mohan Kandrabf6146d2010-07-20 18:48:37 -07004136}
Srinivasan Kannana01751b2010-06-24 18:44:40 -07004137
Mohan Kandrabf6146d2010-07-20 18:48:37 -07004138status_t QualcommCameraHardware::setPreviewFrameRateMode(const CameraParameters& params) {
4139 //Temporary check for mipi sensor
4140 if((!strcmp(mSensorInfo.name, "vx6953")) ||
4141 (!strcmp(mSensorInfo.name, "VX6953"))){
4142 LOGI("set fps mode is not supported for this sensor");
4143 return NO_ERROR;
4144 }
4145 const char *previousMode = mParameters.getPreviewFrameRateMode();
4146 const char *str = params.getPreviewFrameRateMode();
4147 if( mInitialized && !strcmp(previousMode, str)) {
4148 LOGV("frame rate mode same as previous mode %s", previousMode);
4149 return NO_ERROR;
4150 }
4151 int32_t frameRateMode = attr_lookup(frame_rate_modes, sizeof(frame_rate_modes) / sizeof(str_map),str);
4152 if(frameRateMode != NOT_FOUND) {
4153 LOGV("setPreviewFrameRateMode: %s ", str);
4154 mParameters.setPreviewFrameRateMode(str);
4155 bool ret = native_set_parm(CAMERA_SET_FPS_MODE, sizeof(frameRateMode), (void *)&frameRateMode);
4156 if(!ret) return ret;
4157 //set the fps value when chaging modes
4158 int16_t fps = (uint16_t)params.getPreviewFrameRate();
4159 if(MINIMUM_FPS <= fps && fps <=MAXIMUM_FPS){
4160 mParameters.setPreviewFrameRate(fps);
4161 ret = native_set_parm(CAMERA_SET_PARM_FPS,
4162 sizeof(fps), (void *)&fps);
4163 return ret ? NO_ERROR : UNKNOWN_ERROR;
4164 }
4165 LOGI("Invalid preview frame rate value: %d", fps);
4166 return BAD_VALUE;
4167 }
4168 LOGI("Invalid preview frame rate mode value: %s", (str == NULL) ? "NULL" : str);
4169 return BAD_VALUE;
Srinivasan Kannana01751b2010-06-24 18:44:40 -07004170}
4171
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004172status_t QualcommCameraHardware::setPictureSize(const CameraParameters& params)
4173{
4174 int width, height;
4175 params.getPictureSize(&width, &height);
4176 LOGV("requested picture size %d x %d", width, height);
4177
4178 // Validate the picture size
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -08004179 for (int i = 0; i < supportedPictureSizesCount; ++i) {
4180 if (width == picture_sizes_ptr[i].width
4181 && height == picture_sizes_ptr[i].height) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004182 mParameters.setPictureSize(width, height);
4183 mDimension.picture_width = width;
4184 mDimension.picture_height = height;
4185 return NO_ERROR;
4186 }
4187 }
Kiran Kumar H Nb49af212010-02-17 15:12:17 -08004188 /* Dimension not among the ones in the list. Check if
4189 * its a valid dimension, if it is, then configure the
4190 * camera accordingly. else reject it.
4191 */
4192 if( isValidDimension(width, height) ) {
4193 mParameters.setPictureSize(width, height);
4194 mDimension.picture_width = width;
4195 mDimension.picture_height = height;
4196 return NO_ERROR;
4197 } else
4198 LOGE("Invalid picture size requested: %dx%d", width, height);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004199 return BAD_VALUE;
4200}
4201
4202status_t QualcommCameraHardware::setJpegQuality(const CameraParameters& params) {
4203 status_t rc = NO_ERROR;
4204 int quality = params.getInt(CameraParameters::KEY_JPEG_QUALITY);
4205 if (quality > 0 && quality <= 100) {
4206 mParameters.set(CameraParameters::KEY_JPEG_QUALITY, quality);
4207 } else {
4208 LOGE("Invalid jpeg quality=%d", quality);
4209 rc = BAD_VALUE;
4210 }
4211
4212 quality = params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY);
4213 if (quality > 0 && quality <= 100) {
4214 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, quality);
4215 } else {
4216 LOGE("Invalid jpeg thumbnail quality=%d", quality);
4217 rc = BAD_VALUE;
4218 }
4219 return rc;
4220}
4221
4222status_t QualcommCameraHardware::setEffect(const CameraParameters& params)
4223{
Apurva Rajguru7360db42010-04-09 16:37:36 -07004224
4225 const char *str_wb = mParameters.get(CameraParameters::KEY_WHITE_BALANCE);
4226 int32_t value_wb = attr_lookup(whitebalance, sizeof(whitebalance) / sizeof(str_map), str_wb);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004227 const char *str = params.get(CameraParameters::KEY_EFFECT);
Apurva Rajguru7360db42010-04-09 16:37:36 -07004228
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004229 if (str != NULL) {
4230 int32_t value = attr_lookup(effects, sizeof(effects) / sizeof(str_map), str);
4231 if (value != NOT_FOUND) {
Mohan Kandra93f1bfb2009-12-15 16:55:33 -08004232 if(!strcmp(sensorType->name, "2mp") && (value != CAMERA_EFFECT_OFF)
4233 &&(value != CAMERA_EFFECT_MONO) && (value != CAMERA_EFFECT_NEGATIVE)
4234 &&(value != CAMERA_EFFECT_SOLARIZE) && (value != CAMERA_EFFECT_SEPIA)) {
4235 LOGE("Special effect parameter is not supported for this sensor");
4236 return NO_ERROR;
4237 }
Apurva Rajguru7360db42010-04-09 16:37:36 -07004238
4239 if(((value == CAMERA_EFFECT_MONO) || (value == CAMERA_EFFECT_NEGATIVE)
4240 || (value == CAMERA_EFFECT_AQUA) || (value == CAMERA_EFFECT_SEPIA))
4241 && (value_wb != CAMERA_WB_AUTO)) {
4242 LOGE("Color Effect value will not be set " \
4243 "when the whitebalance selected is %s", str_wb);
4244 return NO_ERROR;
4245 }
4246 else {
4247 mParameters.set(CameraParameters::KEY_EFFECT, str);
4248 bool ret = native_set_parm(CAMERA_SET_PARM_EFFECT, sizeof(value),
4249 (void *)&value);
4250 return ret ? NO_ERROR : UNKNOWN_ERROR;
4251 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004252 }
4253 }
4254 LOGE("Invalid effect value: %s", (str == NULL) ? "NULL" : str);
4255 return BAD_VALUE;
4256}
4257
Srinivasan Kannan4cc4b862010-06-30 14:22:26 -07004258status_t QualcommCameraHardware::setExposureCompensation(
4259 const CameraParameters & params){
4260
4261 if(!strcmp(sensorType->name, "2mp")) {
4262 LOGE("Exposure Compensation is not supported for this sensor");
4263 return NO_ERROR;
4264 }
4265
4266 int numerator = params.getInt(CameraParameters::KEY_EXPOSURE_COMPENSATION);
4267 if(EXPOSURE_COMPENSATION_MINIMUM_NUMERATOR <= numerator &&
4268 numerator <= EXPOSURE_COMPENSATION_MAXIMUM_NUMERATOR){
4269 int16_t numerator16 = (int16_t)(numerator & 0x0000ffff);
4270 uint16_t denominator16 = EXPOSURE_COMPENSATION_DENOMINATOR;
4271 uint32_t value = 0;
4272 value = numerator16 << 16 | denominator16;
4273
4274 mParameters.set(CameraParameters::KEY_EXPOSURE_COMPENSATION,
4275 numerator);
4276 bool ret = native_set_parm(CAMERA_SET_PARM_EXPOSURE_COMPENSATION,
4277 sizeof(value), (void *)&value);
4278 return ret ? NO_ERROR : UNKNOWN_ERROR;
4279 }
4280 return BAD_VALUE;
4281}
4282
Apurva Rajguru55562b02009-12-03 12:25:35 -08004283status_t QualcommCameraHardware::setAutoExposure(const CameraParameters& params)
4284{
Mohan Kandra93f1bfb2009-12-15 16:55:33 -08004285 if(!strcmp(sensorType->name, "2mp")) {
4286 LOGE("Auto Exposure not supported for this sensor");
4287 return NO_ERROR;
4288 }
Apurva Rajguru55562b02009-12-03 12:25:35 -08004289 const char *str = params.get(CameraParameters::KEY_AUTO_EXPOSURE);
4290 if (str != NULL) {
4291 int32_t value = attr_lookup(autoexposure, sizeof(autoexposure) / sizeof(str_map), str);
4292 if (value != NOT_FOUND) {
4293 mParameters.set(CameraParameters::KEY_AUTO_EXPOSURE, str);
4294 bool ret = native_set_parm(CAMERA_SET_PARM_EXPOSURE, sizeof(value),
4295 (void *)&value);
4296 return ret ? NO_ERROR : UNKNOWN_ERROR;
4297 }
4298 }
4299 LOGE("Invalid auto exposure value: %s", (str == NULL) ? "NULL" : str);
4300 return BAD_VALUE;
4301}
4302
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08004303status_t QualcommCameraHardware::setSharpness(const CameraParameters& params)
4304{
4305 if(!strcmp(sensorType->name, "2mp")) {
4306 LOGE("Sharpness not supported for this sensor");
4307 return NO_ERROR;
4308 }
4309 int sharpness = params.getInt(CameraParameters::KEY_SHARPNESS);
4310 if((sharpness < CAMERA_MIN_SHARPNESS
4311 || sharpness > CAMERA_MAX_SHARPNESS))
4312 return UNKNOWN_ERROR;
Srinivasan Kannan551fd262010-01-14 17:48:30 -08004313
4314 LOGV("setting sharpness %d", sharpness);
4315 mParameters.set(CameraParameters::KEY_SHARPNESS, sharpness);
4316 bool ret = native_set_parm(CAMERA_SET_PARM_SHARPNESS, sizeof(sharpness),
4317 (void *)&sharpness);
4318 return ret ? NO_ERROR : UNKNOWN_ERROR;
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08004319}
4320
4321status_t QualcommCameraHardware::setContrast(const CameraParameters& params)
4322{
4323 if(!strcmp(sensorType->name, "2mp")) {
4324 LOGE("Contrast not supported for this sensor");
4325 return NO_ERROR;
4326 }
Srinivasan Kannan551fd262010-01-14 17:48:30 -08004327
Apurva Rajguru08383852010-05-17 14:25:39 -07004328 const char *str = params.get(CameraParameters::KEY_SCENE_MODE);
4329 int32_t value = attr_lookup(scenemode, sizeof(scenemode) / sizeof(str_map), str);
4330
4331 if(value == CAMERA_BESTSHOT_OFF) {
4332 int contrast = params.getInt(CameraParameters::KEY_CONTRAST);
4333 if((contrast < CAMERA_MIN_CONTRAST)
4334 || (contrast > CAMERA_MAX_CONTRAST))
4335 return UNKNOWN_ERROR;
4336
4337 LOGV("setting contrast %d", contrast);
4338 mParameters.set(CameraParameters::KEY_CONTRAST, contrast);
4339 bool ret = native_set_parm(CAMERA_SET_PARM_CONTRAST, sizeof(contrast),
4340 (void *)&contrast);
4341 return ret ? NO_ERROR : UNKNOWN_ERROR;
4342 } else {
4343 LOGE(" Contrast value will not be set " \
4344 "when the scenemode selected is %s", str);
4345 return NO_ERROR;
4346 }
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08004347}
4348
4349status_t QualcommCameraHardware::setSaturation(const CameraParameters& params)
4350{
4351 if(!strcmp(sensorType->name, "2mp")) {
4352 LOGE("Saturation not supported for this sensor");
4353 return NO_ERROR;
4354 }
Srinivasan Kannan551fd262010-01-14 17:48:30 -08004355
Kiran Kumar H Nf87cf862010-01-27 14:34:34 -08004356 const char *str = params.get(CameraParameters::KEY_EFFECT);
4357 int32_t value = attr_lookup(effects, sizeof(effects) / sizeof(str_map), str);
4358
4359 if( (value != CAMERA_EFFECT_MONO) && (value != CAMERA_EFFECT_NEGATIVE)
4360 && (value != CAMERA_EFFECT_AQUA) && (value != CAMERA_EFFECT_SEPIA)) {
4361
4362 int saturation = params.getInt(CameraParameters::KEY_SATURATION);
4363 if((saturation < CAMERA_MIN_SATURATION)
4364 || (saturation > CAMERA_MAX_SATURATION))
4365 return UNKNOWN_ERROR;
4366
Apurva Rajguru08383852010-05-17 14:25:39 -07004367 LOGV("Setting saturation %d", saturation);
Kiran Kumar H Nf87cf862010-01-27 14:34:34 -08004368 mParameters.set(CameraParameters::KEY_SATURATION, saturation);
4369 bool ret = native_set_parm(CAMERA_SET_PARM_SATURATION, sizeof(saturation),
4370 (void *)&saturation);
4371 return ret ? NO_ERROR : UNKNOWN_ERROR;
4372 } else {
4373 LOGE(" Saturation value will not be set " \
4374 "when the effect selected is %s", str);
4375 return NO_ERROR;
4376 }
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08004377}
4378
Nishant Panditc8c1ee72009-12-03 16:24:02 +05304379status_t QualcommCameraHardware::setBrightness(const CameraParameters& params) {
4380 int brightness = params.getInt("luma-adaptation");
4381 if (mBrightness != brightness) {
4382 LOGV(" new brightness value : %d ", brightness);
4383 mBrightness = brightness;
4384
4385 bool ret = native_set_parm(CAMERA_SET_PARM_BRIGHTNESS, sizeof(mBrightness),
4386 (void *)&mBrightness);
4387 return ret ? NO_ERROR : UNKNOWN_ERROR;
4388 } else {
4389 return NO_ERROR;
4390 }
4391}
4392
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004393status_t QualcommCameraHardware::setWhiteBalance(const CameraParameters& params)
4394{
Apurva Rajguru7360db42010-04-09 16:37:36 -07004395
4396 const char *str_effect = mParameters.get(CameraParameters::KEY_EFFECT);
4397 int32_t value_effect = attr_lookup(effects, sizeof(effects) / sizeof(str_map), str_effect);
4398
4399 if( (value_effect != CAMERA_EFFECT_MONO) && (value_effect != CAMERA_EFFECT_NEGATIVE)
4400 && (value_effect != CAMERA_EFFECT_AQUA) && (value_effect != CAMERA_EFFECT_SEPIA)) {
4401 const char *str = params.get(CameraParameters::KEY_WHITE_BALANCE);
4402
4403 if (str != NULL) {
4404 int32_t value = attr_lookup(whitebalance, sizeof(whitebalance) / sizeof(str_map), str);
4405 if (value != NOT_FOUND) {
4406 mParameters.set(CameraParameters::KEY_WHITE_BALANCE, str);
4407 bool ret = native_set_parm(CAMERA_SET_PARM_WB, sizeof(value),
4408 (void *)&value);
4409 return ret ? NO_ERROR : UNKNOWN_ERROR;
4410 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004411 }
Apurva Rajguru7360db42010-04-09 16:37:36 -07004412 LOGE("Invalid whitebalance value: %s", (str == NULL) ? "NULL" : str);
4413 return BAD_VALUE;
4414 } else {
4415 LOGE("Whitebalance value will not be set " \
4416 "when the effect selected is %s", str_effect);
4417 return NO_ERROR;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004418 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004419}
4420
4421status_t QualcommCameraHardware::setFlash(const CameraParameters& params)
4422{
4423 if (!mSensorInfo.flash_enabled) {
4424 LOGV("%s: flash not supported", __FUNCTION__);
4425 return NO_ERROR;
4426 }
4427
4428 const char *str = params.get(CameraParameters::KEY_FLASH_MODE);
4429 if (str != NULL) {
4430 int32_t value = attr_lookup(flash, sizeof(flash) / sizeof(str_map), str);
4431 if (value != NOT_FOUND) {
4432 mParameters.set(CameraParameters::KEY_FLASH_MODE, str);
4433 bool ret = native_set_parm(CAMERA_SET_PARM_LED_MODE,
4434 sizeof(value), (void *)&value);
4435 return ret ? NO_ERROR : UNKNOWN_ERROR;
4436 }
4437 }
4438 LOGE("Invalid flash mode value: %s", (str == NULL) ? "NULL" : str);
4439 return BAD_VALUE;
4440}
4441
4442status_t QualcommCameraHardware::setAntibanding(const CameraParameters& params)
4443{
Srinivasan Kannan2229d272010-01-05 14:58:28 -08004444 if(!strcmp(sensorType->name, "2mp")) {
4445 LOGE("Parameter AntiBanding is not supported for this sensor");
4446 return NO_ERROR;
4447 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004448 const char *str = params.get(CameraParameters::KEY_ANTIBANDING);
4449 if (str != NULL) {
4450 int value = (camera_antibanding_type)attr_lookup(
4451 antibanding, sizeof(antibanding) / sizeof(str_map), str);
4452 if (value != NOT_FOUND) {
4453 camera_antibanding_type temp = (camera_antibanding_type) value;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004454 mParameters.set(CameraParameters::KEY_ANTIBANDING, str);
Srinivasan Kannan2229d272010-01-05 14:58:28 -08004455 bool ret;
4456 if (temp == CAMERA_ANTIBANDING_AUTO) {
4457 ret = native_set_parm(CAMERA_ENABLE_AFD,
4458 0, NULL);
4459 } else {
4460 ret = native_set_parm(CAMERA_SET_PARM_ANTIBANDING,
4461 sizeof(camera_antibanding_type), (void *)&temp);
4462 }
4463 return ret ? NO_ERROR : UNKNOWN_ERROR;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004464 }
4465 }
4466 LOGE("Invalid antibanding value: %s", (str == NULL) ? "NULL" : str);
4467 return BAD_VALUE;
4468}
4469
Nishant Panditc8c1ee72009-12-03 16:24:02 +05304470status_t QualcommCameraHardware::setLensshadeValue(const CameraParameters& params)
4471{
Mohan Kandrace6bf562010-04-26 13:00:19 -07004472 if( (!strcmp(sensorType->name, "2mp")) ||
4473 (!strcmp(mSensorInfo.name, "vx6953")) ||
4474 (!strcmp(mSensorInfo.name, "VX6953")) ) {
Mohan Kandra1307f312010-04-29 10:18:42 -07004475 LOGI("Parameter Rolloff is not supported for this sensor");
Mohan Kandra93f1bfb2009-12-15 16:55:33 -08004476 return NO_ERROR;
4477 }
Nishant Panditc8c1ee72009-12-03 16:24:02 +05304478 const char *str = params.get(CameraParameters::KEY_LENSSHADE);
4479 if (str != NULL) {
4480 int value = attr_lookup(lensshade,
4481 sizeof(lensshade) / sizeof(str_map), str);
4482 if (value != NOT_FOUND) {
4483 int8_t temp = (int8_t)value;
4484 mParameters.set(CameraParameters::KEY_LENSSHADE, str);
Apurva Rajguru7b949c92010-05-26 15:46:57 -07004485
Nishant Panditc8c1ee72009-12-03 16:24:02 +05304486 native_set_parm(CAMERA_SET_PARM_ROLLOFF, sizeof(int8_t), (void *)&temp);
4487 return NO_ERROR;
4488 }
4489 }
4490 LOGE("Invalid lensShade value: %s", (str == NULL) ? "NULL" : str);
4491 return BAD_VALUE;
4492}
4493
Apurva Rajguru7b949c92010-05-26 15:46:57 -07004494status_t QualcommCameraHardware::setContinuousAf(const CameraParameters& params)
4495{
4496 const char *str = params.get(CameraParameters::KEY_CONTINUOUS_AF);
4497 if (str != NULL) {
4498 int value = attr_lookup(continuous_af,
4499 sizeof(continuous_af) / sizeof(str_map), str);
4500 if (value != NOT_FOUND) {
4501 int8_t temp = (int8_t)value;
4502 mParameters.set(CameraParameters::KEY_CONTINUOUS_AF, str);
4503
4504 native_set_parm(CAMERA_SET_CAF, sizeof(int8_t), (void *)&temp);
4505 return NO_ERROR;
4506 }
4507 }
4508 LOGE("Invalid continuous Af value: %s", (str == NULL) ? "NULL" : str);
4509 return BAD_VALUE;
4510}
4511
Apurva Rajguru0a2cb922010-06-08 15:33:22 -07004512status_t QualcommCameraHardware::setTouchAfAec(const CameraParameters& params)
4513{
4514 int x, y;
4515
4516 params.getTouchIndexAec(&x, &y);
4517 const char *str = params.get(CameraParameters::KEY_TOUCH_AF_AEC);
4518
4519 if (str != NULL) {
4520 int value = attr_lookup(touchafaec,
4521 sizeof(touchafaec) / sizeof(str_map), str);
4522 if (value != NOT_FOUND) {
4523 mParameters.set(CameraParameters::KEY_TOUCH_AF_AEC, str);
4524
4525 //If touch AF/AEC is enabled and touch event has occured then
4526 //call the ioctl with valid values.
4527
4528 cam_set_aec_roi_t aec_roi_value;
4529 if (value == true && x >= 0 && y >= 0) {
4530 aec_roi_value.aec_roi_enable = AEC_ROI_ON;
4531 aec_roi_value.aec_roi_type = AEC_ROI_BY_COORDINATE;
4532 aec_roi_value.aec_roi_position.coordinate.x = x;
4533 aec_roi_value.aec_roi_position.coordinate.y = y;
4534 }
4535 else {
4536 aec_roi_value.aec_roi_enable = AEC_ROI_OFF;
4537 aec_roi_value.aec_roi_type = AEC_ROI_BY_COORDINATE;
4538 aec_roi_value.aec_roi_position.coordinate.x = DONT_CARE_COORDINATE;
4539 aec_roi_value.aec_roi_position.coordinate.y = DONT_CARE_COORDINATE;
4540 }
4541 native_set_parm(CAMERA_SET_PARM_AEC_ROI, sizeof(cam_set_aec_roi_t), (void *)&aec_roi_value);
4542 }
4543 return NO_ERROR;
4544 }
4545 LOGE("Invalid touchafaec value: %s", (str == NULL) ? "NULL" : str);
4546 return BAD_VALUE;
4547}
4548
Nishant Panditc8c1ee72009-12-03 16:24:02 +05304549status_t QualcommCameraHardware::setISOValue(const CameraParameters& params) {
Apurva Rajguruf12d9d22010-04-05 16:47:12 -07004550 int8_t temp_hjr;
Nishant Panditc8c1ee72009-12-03 16:24:02 +05304551 const char *str = params.get(CameraParameters::KEY_ISO_MODE);
4552 if (str != NULL) {
4553 int value = (camera_iso_mode_type)attr_lookup(
4554 iso, sizeof(iso) / sizeof(str_map), str);
4555 if (value != NOT_FOUND) {
4556 camera_iso_mode_type temp = (camera_iso_mode_type) value;
Apurva Rajguruf12d9d22010-04-05 16:47:12 -07004557 if (value == CAMERA_ISO_DEBLUR) {
4558 temp_hjr = true;
4559 native_set_parm(CAMERA_SET_PARM_HJR, sizeof(int8_t), (void*)&temp_hjr);
4560 mHJR = value;
4561 }
4562 else {
4563 if (mHJR == CAMERA_ISO_DEBLUR) {
4564 temp_hjr = false;
4565 native_set_parm(CAMERA_SET_PARM_HJR, sizeof(int8_t), (void*)&temp_hjr);
4566 mHJR = value;
4567 }
4568 }
4569
Nishant Panditc8c1ee72009-12-03 16:24:02 +05304570 mParameters.set(CameraParameters::KEY_ISO_MODE, str);
4571 native_set_parm(CAMERA_SET_PARM_ISO, sizeof(camera_iso_mode_type), (void *)&temp);
4572 return NO_ERROR;
4573 }
4574 }
4575 LOGE("Invalid Iso value: %s", (str == NULL) ? "NULL" : str);
4576 return BAD_VALUE;
4577}
4578
4579
Apurva Rajguru08383852010-05-17 14:25:39 -07004580status_t QualcommCameraHardware::setSceneMode(const CameraParameters& params)
4581{
4582 const char *str = params.get(CameraParameters::KEY_SCENE_MODE);
4583
4584 if (str != NULL) {
4585 int32_t value = attr_lookup(scenemode, sizeof(scenemode) / sizeof(str_map), str);
4586 if (value != NOT_FOUND) {
4587 mParameters.set(CameraParameters::KEY_SCENE_MODE, str);
4588 bool ret = native_set_parm(CAMERA_SET_PARM_BESTSHOT_MODE, sizeof(value),
4589 (void *)&value);
4590 return ret ? NO_ERROR : UNKNOWN_ERROR;
4591 }
4592 }
4593 LOGE("Invalid scenemode value: %s", (str == NULL) ? "NULL" : str);
4594 return BAD_VALUE;
4595}
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004596status_t QualcommCameraHardware::setGpsLocation(const CameraParameters& params)
4597{
4598 const char *latitude = params.get(CameraParameters::KEY_GPS_LATITUDE);
4599 if (latitude) {
4600 mParameters.set(CameraParameters::KEY_GPS_LATITUDE, latitude);
4601 }
4602
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08004603 const char *latitudeRef = params.get(CameraParameters::KEY_GPS_LATITUDE_REF);
4604 if (latitudeRef) {
4605 mParameters.set(CameraParameters::KEY_GPS_LATITUDE_REF, latitudeRef);
4606 }
4607
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004608 const char *longitude = params.get(CameraParameters::KEY_GPS_LONGITUDE);
4609 if (longitude) {
4610 mParameters.set(CameraParameters::KEY_GPS_LONGITUDE, longitude);
4611 }
4612
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08004613 const char *longitudeRef = params.get(CameraParameters::KEY_GPS_LONGITUDE_REF);
4614 if (longitudeRef) {
4615 mParameters.set(CameraParameters::KEY_GPS_LONGITUDE_REF, longitudeRef);
4616 }
4617
4618 const char *altitudeRef = params.get(CameraParameters::KEY_GPS_ALTITUDE_REF);
4619 if (altitudeRef) {
4620 mParameters.set(CameraParameters::KEY_GPS_ALTITUDE_REF, altitudeRef);
4621 }
4622
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004623 const char *altitude = params.get(CameraParameters::KEY_GPS_ALTITUDE);
4624 if (altitude) {
4625 mParameters.set(CameraParameters::KEY_GPS_ALTITUDE, altitude);
4626 }
4627
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08004628 const char *status = params.get(CameraParameters::KEY_GPS_STATUS);
4629 if (status) {
4630 mParameters.set(CameraParameters::KEY_GPS_STATUS, status);
4631 }
4632
4633 const char *dateTime = params.get(CameraParameters::KEY_EXIF_DATETIME);
4634 if (dateTime) {
4635 mParameters.set(CameraParameters::KEY_EXIF_DATETIME, dateTime);
4636 }
4637
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004638 const char *timestamp = params.get(CameraParameters::KEY_GPS_TIMESTAMP);
4639 if (timestamp) {
4640 mParameters.set(CameraParameters::KEY_GPS_TIMESTAMP, timestamp);
4641 }
4642 return NO_ERROR;
4643}
4644
4645status_t QualcommCameraHardware::setRotation(const CameraParameters& params)
4646{
4647 status_t rc = NO_ERROR;
4648 int rotation = params.getInt(CameraParameters::KEY_ROTATION);
4649 if (rotation != NOT_FOUND) {
4650 if (rotation == 0 || rotation == 90 || rotation == 180
4651 || rotation == 270) {
4652 mParameters.set(CameraParameters::KEY_ROTATION, rotation);
4653 } else {
4654 LOGE("Invalid rotation value: %d", rotation);
4655 rc = BAD_VALUE;
4656 }
4657 }
4658 return rc;
4659}
4660
4661status_t QualcommCameraHardware::setZoom(const CameraParameters& params)
4662{
4663 status_t rc = NO_ERROR;
4664 // No matter how many different zoom values the driver can provide, HAL
4665 // provides applictations the same number of zoom levels. The maximum driver
4666 // zoom value depends on sensor output (VFE input) and preview size (VFE
4667 // output) because VFE can only crop and cannot upscale. If the preview size
4668 // is bigger, the maximum zoom ratio is smaller. However, we want the
4669 // zoom ratio of each zoom level is always the same whatever the preview
4670 // size is. Ex: zoom level 1 is always 1.2x, zoom level 2 is 1.44x, etc. So,
4671 // we need to have a fixed maximum zoom value and do read it from the
4672 // driver.
Mohan Kandra284966d2010-01-05 13:39:15 -08004673 static const int ZOOM_STEP = 1;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004674 int32_t zoom_level = params.getInt("zoom");
4675
Mohan Kandra284966d2010-01-05 13:39:15 -08004676 LOGV("Set zoom=%d", zoom_level);
4677 if(zoom_level >= 0 && zoom_level <= mMaxZoom) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004678 mParameters.set("zoom", zoom_level);
4679 int32_t zoom_value = ZOOM_STEP * zoom_level;
4680 bool ret = native_set_parm(CAMERA_SET_PARM_ZOOM,
4681 sizeof(zoom_value), (void *)&zoom_value);
4682 rc = ret ? NO_ERROR : UNKNOWN_ERROR;
4683 } else {
4684 rc = BAD_VALUE;
4685 }
4686
4687 return rc;
4688}
4689
4690status_t QualcommCameraHardware::setFocusMode(const CameraParameters& params)
4691{
4692 const char *str = params.get(CameraParameters::KEY_FOCUS_MODE);
4693 if (str != NULL) {
4694 int32_t value = attr_lookup(focus_modes,
4695 sizeof(focus_modes) / sizeof(str_map), str);
4696 if (value != NOT_FOUND) {
4697 mParameters.set(CameraParameters::KEY_FOCUS_MODE, str);
4698 // Focus step is reset to infinity when preview is started. We do
4699 // not need to do anything now.
4700 return NO_ERROR;
4701 }
4702 }
4703 LOGE("Invalid focus mode value: %s", (str == NULL) ? "NULL" : str);
4704 return BAD_VALUE;
4705}
4706
4707status_t QualcommCameraHardware::setOrientation(const CameraParameters& params)
4708{
4709 const char *str = params.get("orientation");
4710
4711 if (str != NULL) {
4712 if (strcmp(str, "portrait") == 0 || strcmp(str, "landscape") == 0) {
4713 // Camera service needs this to decide if the preview frames and raw
4714 // pictures should be rotated.
4715 mParameters.set("orientation", str);
4716 } else {
4717 LOGE("Invalid orientation value: %s", str);
4718 return BAD_VALUE;
4719 }
4720 }
4721 return NO_ERROR;
4722}
4723
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08004724status_t QualcommCameraHardware::setPictureFormat(const CameraParameters& params)
4725{
4726 const char * str = params.get(CameraParameters::KEY_PICTURE_FORMAT);
4727
4728 if(str != NULL){
4729 int32_t value = attr_lookup(picture_formats,
4730 sizeof(picture_formats) / sizeof(str_map), str);
4731 if(value != NOT_FOUND){
4732 mParameters.set(CameraParameters::KEY_PICTURE_FORMAT, str);
4733 } else {
4734 LOGE("Invalid Picture Format value: %s", str);
4735 return BAD_VALUE;
4736 }
4737 }
4738 return NO_ERROR;
4739}
4740
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004741QualcommCameraHardware::MemPool::MemPool(int buffer_size, int num_buffers,
4742 int frame_size,
4743 const char *name) :
4744 mBufferSize(buffer_size),
4745 mNumBuffers(num_buffers),
4746 mFrameSize(frame_size),
4747 mBuffers(NULL), mName(name)
4748{
4749 int page_size_minus_1 = getpagesize() - 1;
4750 mAlignedBufferSize = (buffer_size + page_size_minus_1) & (~page_size_minus_1);
4751}
4752
4753void QualcommCameraHardware::MemPool::completeInitialization()
4754{
4755 // If we do not know how big the frame will be, we wait to allocate
4756 // the buffers describing the individual frames until we do know their
4757 // size.
4758
4759 if (mFrameSize > 0) {
4760 mBuffers = new sp<MemoryBase>[mNumBuffers];
4761 for (int i = 0; i < mNumBuffers; i++) {
4762 mBuffers[i] = new
4763 MemoryBase(mHeap,
4764 i * mAlignedBufferSize,
4765 mFrameSize);
4766 }
4767 }
4768}
4769
4770QualcommCameraHardware::AshmemPool::AshmemPool(int buffer_size, int num_buffers,
4771 int frame_size,
4772 const char *name) :
4773 QualcommCameraHardware::MemPool(buffer_size,
4774 num_buffers,
4775 frame_size,
4776 name)
4777{
4778 LOGV("constructing MemPool %s backed by ashmem: "
4779 "%d frames @ %d uint8_ts, "
4780 "buffer size %d",
4781 mName,
4782 num_buffers, frame_size, buffer_size);
4783
4784 int page_mask = getpagesize() - 1;
4785 int ashmem_size = buffer_size * num_buffers;
4786 ashmem_size += page_mask;
4787 ashmem_size &= ~page_mask;
4788
4789 mHeap = new MemoryHeapBase(ashmem_size);
4790
4791 completeInitialization();
4792}
4793
4794static bool register_buf(int camfd,
4795 int size,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08004796 int frame_size,
Mohan Kandra02486042010-06-18 16:49:43 -07004797 int cbcr_offset,
4798 int yoffset,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004799 int pmempreviewfd,
4800 uint32_t offset,
4801 uint8_t *buf,
4802 int pmem_type,
4803 bool vfe_can_write,
4804 bool register_buffer = true);
4805
4806QualcommCameraHardware::PmemPool::PmemPool(const char *pmem_pool,
4807 int flags,
4808 int camera_control_fd,
4809 int pmem_type,
4810 int buffer_size, int num_buffers,
Mohan Kandra02486042010-06-18 16:49:43 -07004811 int frame_size, int cbcr_offset,
4812 int yOffset, const char *name) :
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004813 QualcommCameraHardware::MemPool(buffer_size,
4814 num_buffers,
4815 frame_size,
4816 name),
4817 mPmemType(pmem_type),
Mohan Kandra02486042010-06-18 16:49:43 -07004818 mCbCrOffset(cbcr_offset),
4819 myOffset(yOffset),
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004820 mCameraControlFd(dup(camera_control_fd))
4821{
4822 LOGV("constructing MemPool %s backed by pmem pool %s: "
4823 "%d frames @ %d bytes, buffer size %d",
4824 mName,
4825 pmem_pool, num_buffers, frame_size,
4826 buffer_size);
4827
4828 LOGV("%s: duplicating control fd %d --> %d",
4829 __FUNCTION__,
4830 camera_control_fd, mCameraControlFd);
4831
4832 // Make a new mmap'ed heap that can be shared across processes.
4833 // mAlignedBufferSize is already in 4k aligned. (do we need total size necessary to be in power of 2??)
4834 mAlignedSize = mAlignedBufferSize * num_buffers;
4835
4836 sp<MemoryHeapBase> masterHeap =
4837 new MemoryHeapBase(pmem_pool, mAlignedSize, flags);
4838
4839 if (masterHeap->getHeapID() < 0) {
4840 LOGE("failed to construct master heap for pmem pool %s", pmem_pool);
4841 masterHeap.clear();
4842 return;
4843 }
4844
4845 sp<MemoryHeapPmem> pmemHeap = new MemoryHeapPmem(masterHeap, flags);
4846 if (pmemHeap->getHeapID() >= 0) {
4847 pmemHeap->slap();
4848 masterHeap.clear();
4849 mHeap = pmemHeap;
4850 pmemHeap.clear();
4851
4852 mFd = mHeap->getHeapID();
4853 if (::ioctl(mFd, PMEM_GET_SIZE, &mSize)) {
4854 LOGE("pmem pool %s ioctl(PMEM_GET_SIZE) error %s (%d)",
4855 pmem_pool,
4856 ::strerror(errno), errno);
4857 mHeap.clear();
4858 return;
4859 }
4860
4861 LOGV("pmem pool %s ioctl(fd = %d, PMEM_GET_SIZE) is %ld",
4862 pmem_pool,
4863 mFd,
4864 mSize.len);
Mohan Kandra284966d2010-01-05 13:39:15 -08004865 LOGD("mBufferSize=%d, mAlignedBufferSize=%d\n", mBufferSize, mAlignedBufferSize);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004866 // Unregister preview buffers with the camera drivers. Allow the VFE to write
4867 // to all preview buffers except for the last one.
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08004868 // Only Register the preview, snapshot and thumbnail buffers with the kernel.
Mohan Kandrad9efed92010-01-15 19:08:39 -08004869 if( (strcmp("postview", mName) != 0) ){
4870 int num_buf = num_buffers;
4871 if(!strcmp("preview", mName)) num_buf = kPreviewBufferCount;
Brian Steuerb62adbd2010-02-02 14:47:08 -08004872 LOGD("num_buffers = %d", num_buf);
Mohan Kandrad9efed92010-01-15 19:08:39 -08004873 for (int cnt = 0; cnt < num_buf; ++cnt) {
Sravankb4f5f1c2010-01-21 11:06:17 +05304874 int active = 1;
4875 if(pmem_type == MSM_PMEM_VIDEO){
4876 active = (cnt<ACTIVE_VIDEO_BUFFERS);
4877 LOGV(" pmempool creating video buffers : active %d ", active);
4878 }
4879 else if (pmem_type == MSM_PMEM_PREVIEW){
4880 active = (cnt < (num_buf-1));
4881 }
Mohan Kandra284966d2010-01-05 13:39:15 -08004882 register_buf(mCameraControlFd,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004883 mBufferSize,
Mohan Kandra02486042010-06-18 16:49:43 -07004884 mFrameSize, mCbCrOffset, myOffset,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004885 mHeap->getHeapID(),
4886 mAlignedBufferSize * cnt,
4887 (uint8_t *)mHeap->base() + mAlignedBufferSize * cnt,
4888 pmem_type,
Sravankb4f5f1c2010-01-21 11:06:17 +05304889 active);
Mohan Kandra284966d2010-01-05 13:39:15 -08004890 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004891 }
4892
4893 completeInitialization();
4894 }
4895 else LOGE("pmem pool %s error: could not create master heap!",
4896 pmem_pool);
4897}
4898
4899QualcommCameraHardware::PmemPool::~PmemPool()
4900{
4901 LOGV("%s: %s E", __FUNCTION__, mName);
4902 if (mHeap != NULL) {
4903 // Unregister preview buffers with the camera drivers.
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08004904 // Only Unregister the preview, snapshot and thumbnail
4905 // buffers with the kernel.
Mohan Kandrad9efed92010-01-15 19:08:39 -08004906 if( (strcmp("postview", mName) != 0) ){
4907 int num_buffers = mNumBuffers;
4908 if(!strcmp("preview", mName)) num_buffers = kPreviewBufferCount;
4909 for (int cnt = 0; cnt < num_buffers; ++cnt) {
Mohan Kandra284966d2010-01-05 13:39:15 -08004910 register_buf(mCameraControlFd,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004911 mBufferSize,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08004912 mFrameSize,
Mohan Kandra02486042010-06-18 16:49:43 -07004913 mCbCrOffset,
4914 myOffset,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004915 mHeap->getHeapID(),
4916 mAlignedBufferSize * cnt,
4917 (uint8_t *)mHeap->base() + mAlignedBufferSize * cnt,
4918 mPmemType,
4919 false,
4920 false /* unregister */);
Mohan Kandra284966d2010-01-05 13:39:15 -08004921 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004922 }
4923 }
4924 LOGV("destroying PmemPool %s: closing control fd %d",
4925 mName,
4926 mCameraControlFd);
4927 close(mCameraControlFd);
4928 LOGV("%s: %s X", __FUNCTION__, mName);
4929}
4930
4931QualcommCameraHardware::MemPool::~MemPool()
4932{
4933 LOGV("destroying MemPool %s", mName);
4934 if (mFrameSize > 0)
4935 delete [] mBuffers;
4936 mHeap.clear();
4937 LOGV("destroying MemPool %s completed", mName);
4938}
4939
4940static bool register_buf(int camfd,
4941 int size,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08004942 int frame_size,
Mohan Kandra02486042010-06-18 16:49:43 -07004943 int cbcr_offset,
4944 int yoffset,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004945 int pmempreviewfd,
4946 uint32_t offset,
4947 uint8_t *buf,
4948 int pmem_type,
4949 bool vfe_can_write,
4950 bool register_buffer)
4951{
4952 struct msm_pmem_info pmemBuf;
4953
4954 pmemBuf.type = pmem_type;
4955 pmemBuf.fd = pmempreviewfd;
4956 pmemBuf.offset = offset;
4957 pmemBuf.len = size;
4958 pmemBuf.vaddr = buf;
Mohan Kandra02486042010-06-18 16:49:43 -07004959 pmemBuf.y_off = yoffset;
4960 pmemBuf.cbcr_off = cbcr_offset;
Srinivasan Kannanb36a4fe2010-01-29 19:34:09 -08004961
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004962 pmemBuf.active = vfe_can_write;
4963
4964 LOGV("register_buf: camfd = %d, reg = %d buffer = %p",
4965 camfd, !register_buffer, buf);
4966 if (ioctl(camfd,
4967 register_buffer ?
4968 MSM_CAM_IOCTL_REGISTER_PMEM :
4969 MSM_CAM_IOCTL_UNREGISTER_PMEM,
4970 &pmemBuf) < 0) {
4971 LOGE("register_buf: MSM_CAM_IOCTL_(UN)REGISTER_PMEM fd %d error %s",
4972 camfd,
4973 strerror(errno));
4974 return false;
4975 }
4976 return true;
4977}
4978
4979status_t QualcommCameraHardware::MemPool::dump(int fd, const Vector<String16>& args) const
4980{
4981 const size_t SIZE = 256;
4982 char buffer[SIZE];
4983 String8 result;
4984 snprintf(buffer, 255, "QualcommCameraHardware::AshmemPool::dump\n");
4985 result.append(buffer);
4986 if (mName) {
4987 snprintf(buffer, 255, "mem pool name (%s)\n", mName);
4988 result.append(buffer);
4989 }
4990 if (mHeap != 0) {
4991 snprintf(buffer, 255, "heap base(%p), size(%d), flags(%d), device(%s)\n",
4992 mHeap->getBase(), mHeap->getSize(),
4993 mHeap->getFlags(), mHeap->getDevice());
4994 result.append(buffer);
4995 }
4996 snprintf(buffer, 255,
4997 "buffer size (%d), number of buffers (%d), frame size(%d)",
4998 mBufferSize, mNumBuffers, mFrameSize);
4999 result.append(buffer);
5000 write(fd, result.string(), result.size());
5001 return NO_ERROR;
5002}
5003
5004static void receive_camframe_callback(struct msm_frame *frame)
5005{
5006 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
5007 if (obj != 0) {
5008 obj->receivePreviewFrame(frame);
5009 }
5010}
5011
5012static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size)
5013{
5014 LOGV("receive_jpeg_fragment_callback E");
5015 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
5016 if (obj != 0) {
5017 obj->receiveJpegPictureFragment(buff_ptr, buff_size);
5018 }
5019 LOGV("receive_jpeg_fragment_callback X");
5020}
5021
5022static void receive_jpeg_callback(jpeg_event_t status)
5023{
5024 LOGV("receive_jpeg_callback E (completion status %d)", status);
5025 if (status == JPEG_EVENT_DONE) {
5026 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
5027 if (obj != 0) {
5028 obj->receiveJpegPicture();
5029 }
5030 }
5031 LOGV("receive_jpeg_callback X");
5032}
Sravankb4f5f1c2010-01-21 11:06:17 +05305033// 720p : video frame calbback from camframe
5034static void receive_camframe_video_callback(struct msm_frame *frame)
5035{
5036 LOGV("receive_camframe_video_callback E");
5037 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
5038 if (obj != 0) {
5039 obj->receiveRecordingFrame(frame);
5040 }
5041 LOGV("receive_camframe_video_callback X");
5042}
Priya Komarlingamb85535d2009-11-30 13:06:01 -08005043
5044void QualcommCameraHardware::setCallbacks(notify_callback notify_cb,
5045 data_callback data_cb,
5046 data_callback_timestamp data_cb_timestamp,
5047 void* user)
5048{
5049 Mutex::Autolock lock(mLock);
5050 mNotifyCallback = notify_cb;
5051 mDataCallback = data_cb;
5052 mDataCallbackTimestamp = data_cb_timestamp;
5053 mCallbackCookie = user;
5054}
5055
5056void QualcommCameraHardware::enableMsgType(int32_t msgType)
5057{
5058 Mutex::Autolock lock(mLock);
5059 mMsgEnabled |= msgType;
5060}
5061
5062void QualcommCameraHardware::disableMsgType(int32_t msgType)
5063{
5064 Mutex::Autolock lock(mLock);
5065 mMsgEnabled &= ~msgType;
5066}
5067
5068bool QualcommCameraHardware::msgTypeEnabled(int32_t msgType)
5069{
5070 return (mMsgEnabled & msgType);
5071}
5072
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08005073bool QualcommCameraHardware::useOverlay(void)
5074{
Nishant Pandit3c278cd2010-07-13 15:56:04 +05305075 if((mCurrentTarget == TARGET_MSM7630) || (mCurrentTarget == TARGET_MSM8660)) {
5076 /* 7x30 and 8x60 supports Overlay */
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08005077 mUseOverlay = TRUE;
5078 } else
5079 mUseOverlay = FALSE;
5080
5081 LOGV(" Using Overlay : %s ", mUseOverlay ? "YES" : "NO" );
5082 return mUseOverlay;
5083}
5084
5085status_t QualcommCameraHardware::setOverlay(const sp<Overlay> &Overlay)
5086{
5087 if( Overlay != NULL) {
5088 LOGV(" Valid overlay object ");
5089 mOverlayLock.lock();
5090 mOverlay = Overlay;
5091 mOverlayLock.unlock();
5092 } else {
Apurva Rajguruc73c1722010-04-15 17:39:11 -07005093 LOGV(" Overlay object NULL. returning ");
Mohan Kandrad9efed92010-01-15 19:08:39 -08005094 mOverlay = NULL;
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08005095 return UNKNOWN_ERROR;
5096 }
5097 return NO_ERROR;
5098}
Kiran Kumar H N215cac42009-12-08 01:53:46 -08005099
5100void QualcommCameraHardware::receive_camframetimeout(void) {
5101 LOGV("receive_camframetimeout: E");
5102 Mutex::Autolock l(&mCamframeTimeoutLock);
Mohan Kandra1307f312010-04-29 10:18:42 -07005103 LOGE(" Camframe timed out. Not receiving any frames from camera driver ");
Kiran Kumar H N215cac42009-12-08 01:53:46 -08005104 camframe_timeout_flag = TRUE;
Priyanka Kharatae03c212010-05-19 15:32:50 -07005105 mNotifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_UKNOWN, 0,
5106 mCallbackCookie);
Kiran Kumar H N215cac42009-12-08 01:53:46 -08005107 LOGV("receive_camframetimeout: X");
5108}
5109
5110static void receive_camframetimeout_callback(void) {
5111 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
5112 if (obj != 0) {
5113 obj->receive_camframetimeout();
5114 }
5115}
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08005116
5117void QualcommCameraHardware::storePreviewFrameForPostview(void) {
5118 LOGV(" storePreviewFrameForPostview : E ");
5119
5120 /* Since there is restriction on the maximum overlay dimensions
5121 * that can be created, we use the last preview frame as postview
5122 * for 7x30. */
5123 LOGV(" Copying the preview buffer to postview buffer %d ",
5124 mPreviewFrameSize);
5125 if( mPostViewHeap != NULL && mLastQueuedFrame != NULL) {
5126 memcpy(mPostViewHeap->mHeap->base(),
5127 (uint8_t *)mLastQueuedFrame, mPreviewFrameSize );
5128 } else
5129 LOGE(" Failed to store Preview frame. No Postview ");
5130
5131 LOGV(" storePreviewFrameForPostview : X ");
5132}
Kiran Kumar H Nb49af212010-02-17 15:12:17 -08005133
5134bool QualcommCameraHardware::isValidDimension(int width, int height) {
5135 bool retVal = FALSE;
5136 /* This function checks if a given resolution is valid or not.
5137 * A particular resolution is considered valid if it satisfies
5138 * the following conditions:
5139 * 1. width & height should be multiple of 16.
5140 * 2. width & height should be less than/equal to the dimensions
5141 * supported by the camera sensor.
5142 * 3. the aspect ratio is a valid aspect ratio and is among the
5143 * commonly used aspect ratio as determined by the thumbnail_sizes
5144 * data structure.
5145 */
5146
5147 if( (width == CEILING16(width)) && (height == CEILING16(height))
5148 && (width <= sensorType->max_supported_snapshot_width)
5149 && (height <= sensorType->max_supported_snapshot_height) )
5150 {
5151 uint32_t pictureAspectRatio = (uint32_t)((width * Q12)/height);
Mohan Kandra62429cc2010-07-19 10:21:05 -07005152 for(uint32_t i = 0; i < THUMBNAIL_SIZE_COUNT; i++ ) {
Kiran Kumar H Nb49af212010-02-17 15:12:17 -08005153 if(thumbnail_sizes[i].aspect_ratio == pictureAspectRatio) {
5154 retVal = TRUE;
5155 break;
5156 }
5157 }
5158 }
5159 return retVal;
5160}
Kiran Kumar H N4dd45a62010-02-26 15:56:33 -08005161status_t QualcommCameraHardware::getBufferInfo(sp<IMemory>& Frame, size_t *alignedSize) {
5162 status_t ret;
5163 LOGV(" getBufferInfo : E ");
Nishant Pandit3c278cd2010-07-13 15:56:04 +05305164 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250) || (mCurrentTarget == TARGET_MSM8660) )
Vamshidhar Kondrab362be62010-03-22 19:07:29 +05305165 {
5166 if( mRecordHeap != NULL){
5167 LOGV(" Setting valid buffer information ");
5168 Frame = mRecordHeap->mBuffers[0];
5169 if( alignedSize != NULL) {
5170 *alignedSize = mRecordHeap->mAlignedBufferSize;
5171 LOGV(" HAL : alignedSize = %d ", *alignedSize);
5172 ret = NO_ERROR;
5173 } else {
5174 LOGE(" HAL : alignedSize is NULL. Cannot update alignedSize ");
5175 ret = UNKNOWN_ERROR;
5176 }
Kiran Kumar H N4dd45a62010-02-26 15:56:33 -08005177 } else {
Vamshidhar Kondrab362be62010-03-22 19:07:29 +05305178 LOGE(" RecordHeap is null. Buffer information wont be updated ");
5179 Frame = NULL;
5180 ret = UNKNOWN_ERROR;
5181 }
Kiran Kumar H N4dd45a62010-02-26 15:56:33 -08005182 } else {
Vamshidhar Kondrab362be62010-03-22 19:07:29 +05305183 if(mPreviewHeap != NULL) {
5184 LOGV(" Setting valid buffer information ");
5185 Frame = mPreviewHeap->mBuffers[0];
5186 if( alignedSize != NULL) {
5187 *alignedSize = mPreviewHeap->mAlignedBufferSize;
5188 LOGV(" HAL : alignedSize = %d ", *alignedSize);
5189 ret = NO_ERROR;
5190 } else {
5191 LOGE(" HAL : alignedSize is NULL. Cannot update alignedSize ");
5192 ret = UNKNOWN_ERROR;
5193 }
5194 } else {
5195 LOGE(" PreviewHeap is null. Buffer information wont be updated ");
5196 Frame = NULL;
5197 ret = UNKNOWN_ERROR;
5198 }
Kiran Kumar H N4dd45a62010-02-26 15:56:33 -08005199 }
5200 LOGV(" getBufferInfo : X ");
5201 return ret;
5202}
Kiran Kumar H Nb49af212010-02-17 15:12:17 -08005203
Priya Komarlingamb85535d2009-11-30 13:06:01 -08005204}; // namespace android