blob: 12adae876902b5a10c56e2839af0a7adc516d26a [file] [log] [blame]
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001/*
2** Copyright 2008, Google Inc.
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303** Copyright (c) 2009, 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
19#define LOG_TAG "QualcommCameraHardware"
20#include <utils/Log.h>
21
22#include "QualcommCameraHardware.h"
23
24#include <utils/Errors.h>
25#include <utils/threads.h>
26#include <binder/MemoryHeapPmem.h>
27#include <utils/String16.h>
28#include <sys/types.h>
29#include <sys/stat.h>
30#include <unistd.h>
Apurva Rajguru8d1773b2009-12-02 14:21:23 -080031#include <cutils/properties.h>
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -080032#include <math.h>
Priya Komarlingamb85535d2009-11-30 13:06:01 -080033#if HAVE_ANDROID_OS
34#include <linux/android_pmem.h>
35#endif
36#include <linux/ioctl.h>
37#include <ui/CameraParameters.h>
38
Mohan Kandra284966d2010-01-05 13:39:15 -080039#include "linux/msm_mdp.h"
40#include <linux/fb.h>
41
Priya Komarlingamb85535d2009-11-30 13:06:01 -080042#define LIKELY(exp) __builtin_expect(!!(exp), 1)
43#define UNLIKELY(exp) __builtin_expect(!!(exp), 0)
44
45extern "C" {
46#include <fcntl.h>
47#include <time.h>
48#include <pthread.h>
49#include <stdio.h>
50#include <string.h>
51#include <unistd.h>
52#include <termios.h>
53#include <assert.h>
54#include <stdlib.h>
55#include <ctype.h>
56#include <signal.h>
57#include <errno.h>
58#include <sys/mman.h>
59#include <sys/system_properties.h>
60#include <sys/time.h>
61#include <stdlib.h>
62
63#include <media/msm_camera.h>
64
65#include <camera.h>
66#include <camframe.h>
67#include <mm-still/jpeg/jpege.h>
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -080068#include <jpeg_encoder.h>
Priya Komarlingamb85535d2009-11-30 13:06:01 -080069
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -080070#define DEFAULT_PICTURE_WIDTH 1024
71#define DEFAULT_PICTURE_HEIGHT 768
Priya Komarlingamb85535d2009-11-30 13:06:01 -080072#define THUMBNAIL_BUFFER_SIZE (THUMBNAIL_WIDTH * THUMBNAIL_HEIGHT * 3/2)
73#define MAX_ZOOM_LEVEL 5
74#define NOT_FOUND -1
75
76#if DLOPEN_LIBMMCAMERA
77#include <dlfcn.h>
78
79void* (*LINK_cam_conf)(void *data);
80void* (*LINK_cam_frame)(void *data);
81bool (*LINK_jpeg_encoder_init)();
82void (*LINK_jpeg_encoder_join)();
83bool (*LINK_jpeg_encoder_encode)(const cam_ctrl_dimension_t *dimen,
84 const uint8_t *thumbnailbuf, int thumbnailfd,
85 const uint8_t *snapshotbuf, int snapshotfd,
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -080086 common_crop_t *scaling_parms, exif_tags_info_t *exif_data,
87 int exif_table_numEntries);
Priya Komarlingamb85535d2009-11-30 13:06:01 -080088int (*LINK_camframe_terminate)(void);
89int8_t (*LINK_jpeg_encoder_setMainImageQuality)(uint32_t quality);
90int8_t (*LINK_jpeg_encoder_setThumbnailQuality)(uint32_t quality);
91int8_t (*LINK_jpeg_encoder_setRotation)(uint32_t rotation);
92int8_t (*LINK_jpeg_encoder_setLocation)(const camera_position_type *location);
93const struct camera_size_type *(*LINK_default_sensor_get_snapshot_sizes)(int *len);
94int (*LINK_launch_cam_conf_thread)(void);
95int (*LINK_release_cam_conf_thread)(void);
96int8_t (*LINK_zoom_crop_upscale)(uint32_t width, uint32_t height,
97 uint32_t cropped_width, uint32_t cropped_height, uint8_t *img_buf);
98
99// callbacks
100void (**LINK_mmcamera_camframe_callback)(struct msm_frame *frame);
101void (**LINK_mmcamera_jpegfragment_callback)(uint8_t *buff_ptr,
102 uint32_t buff_size);
103void (**LINK_mmcamera_jpeg_callback)(jpeg_event_t status);
104void (**LINK_mmcamera_shutter_callback)(common_crop_t *crop);
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800105void (**LINK_camframe_timeout_callback)(void);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800106#else
107#define LINK_cam_conf cam_conf
108#define LINK_cam_frame cam_frame
109#define LINK_jpeg_encoder_init jpeg_encoder_init
110#define LINK_jpeg_encoder_join jpeg_encoder_join
111#define LINK_jpeg_encoder_encode jpeg_encoder_encode
112#define LINK_camframe_terminate camframe_terminate
113#define LINK_jpeg_encoder_setMainImageQuality jpeg_encoder_setMainImageQuality
114#define LINK_jpeg_encoder_setThumbnailQuality jpeg_encoder_setThumbnailQuality
115#define LINK_jpeg_encoder_setRotation jpeg_encoder_setRotation
116#define LINK_jpeg_encoder_setLocation jpeg_encoder_setLocation
117#define LINK_default_sensor_get_snapshot_sizes default_sensor_get_snapshot_sizes
118#define LINK_launch_cam_conf_thread launch_cam_conf_thread
119#define LINK_release_cam_conf_thread release_cam_conf_thread
120#define LINK_zoom_crop_upscale zoom_crop_upscale
121extern void (*mmcamera_camframe_callback)(struct msm_frame *frame);
122extern void (*mmcamera_jpegfragment_callback)(uint8_t *buff_ptr,
123 uint32_t buff_size);
124extern void (*mmcamera_jpeg_callback)(jpeg_event_t status);
125extern void (*mmcamera_shutter_callback)(common_crop_t *crop);
126#endif
127
128} // extern "C"
129
130#ifndef HAVE_CAMERA_SIZE_TYPE
131struct camera_size_type {
132 int width;
133 int height;
134};
135#endif
136
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -0800137typedef struct crop_info_struct {
138 uint32_t x;
139 uint32_t y;
140 uint32_t w;
141 uint32_t h;
142} zoom_crop_info;
143
Mohan Kandra284966d2010-01-05 13:39:15 -0800144static char mDeviceName[PROPERTY_VALUE_MAX];
Mohan Kandra740cfce2010-01-07 12:58:24 -0800145union zoomimage
Mohan Kandra284966d2010-01-05 13:39:15 -0800146{
147 char d[sizeof(struct mdp_blit_req_list) + sizeof(struct mdp_blit_req) * 1];
148 struct mdp_blit_req_list list;
149} zoomImage;
150
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800151//Default to WVGA
Srinivasan Kannanfa7edae2009-12-16 18:02:01 -0800152#define DEFAULT_PREVIEW_SETTING 1
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800153static const camera_size_type preview_sizes[] = {
Srinivasan Kannanfa7edae2009-12-16 18:02:01 -0800154 { 1280, 720 }, // 720P, reserved
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800155 { 800, 480 }, // WVGA
156 { 720, 480 },
157 { 640, 480 }, // VGA
158 { 576, 432 },
159 { 480, 320 }, // HVGA
160 { 384, 288 },
161 { 352, 288 }, // CIF
162 { 320, 240 }, // QVGA
163 { 240, 160 }, // SQVGA
164 { 176, 144 }, // QCIF
165};
166#define PREVIEW_SIZE_COUNT (sizeof(preview_sizes)/sizeof(camera_size_type))
167
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800168//static const camera_size_type* picture_sizes;
169//static int PICTURE_SIZE_COUNT;
170/* TODO
171 * Ideally this should be a populated by lower layers.
172 * But currently this is no API to do that at lower layer.
173 * Hence populating with default sizes for now. This needs
174 * to be changed once the API is supported.
175 */
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800176//sorted on column basis
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800177static const camera_size_type picture_sizes[] = {
178 { 2592, 1944 }, // 5MP
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800179 { 2048, 1536 }, // 3MP QXGA
180 { 1920, 1080 }, //HD1080
181 { 1600, 1200 }, // 2MP UXGA
182 { 1280, 768 }, //WXGA
183 { 1280, 720 }, //HD720
184 { 1024, 768}, // 1MP XGA
185 { 800, 600 }, //SVGA
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800186 { 800, 480 }, // WVGA
187 { 640, 480 }, // VGA
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800188 { 352, 288 }, //CIF
189 { 320, 240 }, // QVGA
190 { 176, 144 } // QCIF
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800191};
192static int PICTURE_SIZE_COUNT = sizeof(picture_sizes)/sizeof(camera_size_type);
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800193static const camera_size_type * picture_sizes_ptr;
194static int supportedPictureSizesCount;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800195
Srinivasan Kannan80d878f2009-12-18 15:06:02 -0800196#ifdef Q12
197#undef Q12
198#endif
199
200#define Q12 4096
201
202typedef struct {
203 uint32_t aspect_ratio;
204 uint32_t width;
205 uint32_t height;
206} thumbnail_size_type;
207
208static thumbnail_size_type thumbnail_sizes[] = {
209 { 7281, 512, 288 }, //1.777778
210 { 6826, 480, 288 }, //1.666667
211 { 5461, 512, 384 }, //1.333333
212 { 5006, 352, 288 }, //1.222222
213};
214#define THUMBNAIL_SIZE_COUNT (sizeof(thumbnail_sizes)/sizeof(thumbnail_size_type))
215#define DEFAULT_THUMBNAIL_SETTING 2
216#define THUMBNAIL_WIDTH_STR "512"
217#define THUMBNAIL_HEIGHT_STR "384"
218#define THUMBNAIL_SMALL_HEIGHT 144
219
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800220static int attr_lookup(const str_map arr[], int len, const char *name)
221{
222 if (name) {
223 for (int i = 0; i < len; i++) {
224 if (!strcmp(arr[i].desc, name))
225 return arr[i].val;
226 }
227 }
228 return NOT_FOUND;
229}
230
231// round to the next power of two
232static inline unsigned clp2(unsigned x)
233{
234 x = x - 1;
235 x = x | (x >> 1);
236 x = x | (x >> 2);
237 x = x | (x >> 4);
238 x = x | (x >> 8);
239 x = x | (x >>16);
240 return x + 1;
241}
242
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -0800243static int exif_table_numEntries = 0;
244#define MAX_EXIF_TABLE_ENTRIES 7
245exif_tags_info_t exif_data[MAX_EXIF_TABLE_ENTRIES];
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -0800246static zoom_crop_info zoomCropInfo;
247static void *mLastQueuedFrame = NULL;
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -0800248
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800249namespace android {
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800250
251static const int PICTURE_FORMAT_JPEG = 1;
252static const int PICTURE_FORMAT_RAW = 2;
253
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800254// from aeecamera.h
255static const str_map whitebalance[] = {
256 { CameraParameters::WHITE_BALANCE_AUTO, CAMERA_WB_AUTO },
257 { CameraParameters::WHITE_BALANCE_INCANDESCENT, CAMERA_WB_INCANDESCENT },
258 { CameraParameters::WHITE_BALANCE_FLUORESCENT, CAMERA_WB_FLUORESCENT },
259 { CameraParameters::WHITE_BALANCE_DAYLIGHT, CAMERA_WB_DAYLIGHT },
260 { CameraParameters::WHITE_BALANCE_CLOUDY_DAYLIGHT, CAMERA_WB_CLOUDY_DAYLIGHT }
261};
262
263// from camera_effect_t. This list must match aeecamera.h
264static const str_map effects[] = {
265 { CameraParameters::EFFECT_NONE, CAMERA_EFFECT_OFF },
266 { CameraParameters::EFFECT_MONO, CAMERA_EFFECT_MONO },
267 { CameraParameters::EFFECT_NEGATIVE, CAMERA_EFFECT_NEGATIVE },
268 { CameraParameters::EFFECT_SOLARIZE, CAMERA_EFFECT_SOLARIZE },
269 { CameraParameters::EFFECT_SEPIA, CAMERA_EFFECT_SEPIA },
270 { CameraParameters::EFFECT_POSTERIZE, CAMERA_EFFECT_POSTERIZE },
271 { CameraParameters::EFFECT_WHITEBOARD, CAMERA_EFFECT_WHITEBOARD },
272 { CameraParameters::EFFECT_BLACKBOARD, CAMERA_EFFECT_BLACKBOARD },
273 { CameraParameters::EFFECT_AQUA, CAMERA_EFFECT_AQUA }
274};
275
276// from qcamera/common/camera.h
Apurva Rajguru55562b02009-12-03 12:25:35 -0800277static const str_map autoexposure[] = {
278 { CameraParameters::AUTO_EXPOSURE_FRAME_AVG, CAMERA_AEC_FRAME_AVERAGE },
279 { CameraParameters::AUTO_EXPOSURE_CENTER_WEIGHTED, CAMERA_AEC_CENTER_WEIGHTED },
280 { CameraParameters::AUTO_EXPOSURE_SPOT_METERING, CAMERA_AEC_SPOT_METERING }
281};
282
283// from qcamera/common/camera.h
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800284static const str_map antibanding[] = {
285 { CameraParameters::ANTIBANDING_OFF, CAMERA_ANTIBANDING_OFF },
286 { CameraParameters::ANTIBANDING_50HZ, CAMERA_ANTIBANDING_50HZ },
287 { CameraParameters::ANTIBANDING_60HZ, CAMERA_ANTIBANDING_60HZ },
288 { CameraParameters::ANTIBANDING_AUTO, CAMERA_ANTIBANDING_AUTO }
289};
290
291/* Mapping from MCC to antibanding type */
292struct country_map {
293 uint32_t country_code;
294 camera_antibanding_type type;
295};
296
297static struct country_map country_numeric[] = {
298 { 202, CAMERA_ANTIBANDING_50HZ }, // Greece
299 { 204, CAMERA_ANTIBANDING_50HZ }, // Netherlands
300 { 206, CAMERA_ANTIBANDING_50HZ }, // Belgium
301 { 208, CAMERA_ANTIBANDING_50HZ }, // France
302 { 212, CAMERA_ANTIBANDING_50HZ }, // Monaco
303 { 213, CAMERA_ANTIBANDING_50HZ }, // Andorra
304 { 214, CAMERA_ANTIBANDING_50HZ }, // Spain
305 { 216, CAMERA_ANTIBANDING_50HZ }, // Hungary
306 { 219, CAMERA_ANTIBANDING_50HZ }, // Croatia
307 { 220, CAMERA_ANTIBANDING_50HZ }, // Serbia
308 { 222, CAMERA_ANTIBANDING_50HZ }, // Italy
309 { 226, CAMERA_ANTIBANDING_50HZ }, // Romania
310 { 228, CAMERA_ANTIBANDING_50HZ }, // Switzerland
311 { 230, CAMERA_ANTIBANDING_50HZ }, // Czech Republic
312 { 231, CAMERA_ANTIBANDING_50HZ }, // Slovakia
313 { 232, CAMERA_ANTIBANDING_50HZ }, // Austria
314 { 234, CAMERA_ANTIBANDING_50HZ }, // United Kingdom
315 { 235, CAMERA_ANTIBANDING_50HZ }, // United Kingdom
316 { 238, CAMERA_ANTIBANDING_50HZ }, // Denmark
317 { 240, CAMERA_ANTIBANDING_50HZ }, // Sweden
318 { 242, CAMERA_ANTIBANDING_50HZ }, // Norway
319 { 244, CAMERA_ANTIBANDING_50HZ }, // Finland
320 { 246, CAMERA_ANTIBANDING_50HZ }, // Lithuania
321 { 247, CAMERA_ANTIBANDING_50HZ }, // Latvia
322 { 248, CAMERA_ANTIBANDING_50HZ }, // Estonia
323 { 250, CAMERA_ANTIBANDING_50HZ }, // Russian Federation
324 { 255, CAMERA_ANTIBANDING_50HZ }, // Ukraine
325 { 257, CAMERA_ANTIBANDING_50HZ }, // Belarus
326 { 259, CAMERA_ANTIBANDING_50HZ }, // Moldova
327 { 260, CAMERA_ANTIBANDING_50HZ }, // Poland
328 { 262, CAMERA_ANTIBANDING_50HZ }, // Germany
329 { 266, CAMERA_ANTIBANDING_50HZ }, // Gibraltar
330 { 268, CAMERA_ANTIBANDING_50HZ }, // Portugal
331 { 270, CAMERA_ANTIBANDING_50HZ }, // Luxembourg
332 { 272, CAMERA_ANTIBANDING_50HZ }, // Ireland
333 { 274, CAMERA_ANTIBANDING_50HZ }, // Iceland
334 { 276, CAMERA_ANTIBANDING_50HZ }, // Albania
335 { 278, CAMERA_ANTIBANDING_50HZ }, // Malta
336 { 280, CAMERA_ANTIBANDING_50HZ }, // Cyprus
337 { 282, CAMERA_ANTIBANDING_50HZ }, // Georgia
338 { 283, CAMERA_ANTIBANDING_50HZ }, // Armenia
339 { 284, CAMERA_ANTIBANDING_50HZ }, // Bulgaria
340 { 286, CAMERA_ANTIBANDING_50HZ }, // Turkey
341 { 288, CAMERA_ANTIBANDING_50HZ }, // Faroe Islands
342 { 290, CAMERA_ANTIBANDING_50HZ }, // Greenland
343 { 293, CAMERA_ANTIBANDING_50HZ }, // Slovenia
344 { 294, CAMERA_ANTIBANDING_50HZ }, // Macedonia
345 { 295, CAMERA_ANTIBANDING_50HZ }, // Liechtenstein
346 { 297, CAMERA_ANTIBANDING_50HZ }, // Montenegro
347 { 302, CAMERA_ANTIBANDING_60HZ }, // Canada
348 { 310, CAMERA_ANTIBANDING_60HZ }, // United States of America
349 { 311, CAMERA_ANTIBANDING_60HZ }, // United States of America
350 { 312, CAMERA_ANTIBANDING_60HZ }, // United States of America
351 { 313, CAMERA_ANTIBANDING_60HZ }, // United States of America
352 { 314, CAMERA_ANTIBANDING_60HZ }, // United States of America
353 { 315, CAMERA_ANTIBANDING_60HZ }, // United States of America
354 { 316, CAMERA_ANTIBANDING_60HZ }, // United States of America
355 { 330, CAMERA_ANTIBANDING_60HZ }, // Puerto Rico
356 { 334, CAMERA_ANTIBANDING_60HZ }, // Mexico
357 { 338, CAMERA_ANTIBANDING_50HZ }, // Jamaica
358 { 340, CAMERA_ANTIBANDING_50HZ }, // Martinique
359 { 342, CAMERA_ANTIBANDING_50HZ }, // Barbados
360 { 346, CAMERA_ANTIBANDING_60HZ }, // Cayman Islands
361 { 350, CAMERA_ANTIBANDING_60HZ }, // Bermuda
362 { 352, CAMERA_ANTIBANDING_50HZ }, // Grenada
363 { 354, CAMERA_ANTIBANDING_60HZ }, // Montserrat
364 { 362, CAMERA_ANTIBANDING_50HZ }, // Netherlands Antilles
365 { 363, CAMERA_ANTIBANDING_60HZ }, // Aruba
366 { 364, CAMERA_ANTIBANDING_60HZ }, // Bahamas
367 { 365, CAMERA_ANTIBANDING_60HZ }, // Anguilla
368 { 366, CAMERA_ANTIBANDING_50HZ }, // Dominica
369 { 368, CAMERA_ANTIBANDING_60HZ }, // Cuba
370 { 370, CAMERA_ANTIBANDING_60HZ }, // Dominican Republic
371 { 372, CAMERA_ANTIBANDING_60HZ }, // Haiti
372 { 401, CAMERA_ANTIBANDING_50HZ }, // Kazakhstan
373 { 402, CAMERA_ANTIBANDING_50HZ }, // Bhutan
374 { 404, CAMERA_ANTIBANDING_50HZ }, // India
375 { 405, CAMERA_ANTIBANDING_50HZ }, // India
376 { 410, CAMERA_ANTIBANDING_50HZ }, // Pakistan
377 { 413, CAMERA_ANTIBANDING_50HZ }, // Sri Lanka
378 { 414, CAMERA_ANTIBANDING_50HZ }, // Myanmar
379 { 415, CAMERA_ANTIBANDING_50HZ }, // Lebanon
380 { 416, CAMERA_ANTIBANDING_50HZ }, // Jordan
381 { 417, CAMERA_ANTIBANDING_50HZ }, // Syria
382 { 418, CAMERA_ANTIBANDING_50HZ }, // Iraq
383 { 419, CAMERA_ANTIBANDING_50HZ }, // Kuwait
384 { 420, CAMERA_ANTIBANDING_60HZ }, // Saudi Arabia
385 { 421, CAMERA_ANTIBANDING_50HZ }, // Yemen
386 { 422, CAMERA_ANTIBANDING_50HZ }, // Oman
387 { 424, CAMERA_ANTIBANDING_50HZ }, // United Arab Emirates
388 { 425, CAMERA_ANTIBANDING_50HZ }, // Israel
389 { 426, CAMERA_ANTIBANDING_50HZ }, // Bahrain
390 { 427, CAMERA_ANTIBANDING_50HZ }, // Qatar
391 { 428, CAMERA_ANTIBANDING_50HZ }, // Mongolia
392 { 429, CAMERA_ANTIBANDING_50HZ }, // Nepal
393 { 430, CAMERA_ANTIBANDING_50HZ }, // United Arab Emirates
394 { 431, CAMERA_ANTIBANDING_50HZ }, // United Arab Emirates
395 { 432, CAMERA_ANTIBANDING_50HZ }, // Iran
396 { 434, CAMERA_ANTIBANDING_50HZ }, // Uzbekistan
397 { 436, CAMERA_ANTIBANDING_50HZ }, // Tajikistan
398 { 437, CAMERA_ANTIBANDING_50HZ }, // Kyrgyz Rep
399 { 438, CAMERA_ANTIBANDING_50HZ }, // Turkmenistan
400 { 440, CAMERA_ANTIBANDING_60HZ }, // Japan
401 { 441, CAMERA_ANTIBANDING_60HZ }, // Japan
402 { 452, CAMERA_ANTIBANDING_50HZ }, // Vietnam
403 { 454, CAMERA_ANTIBANDING_50HZ }, // Hong Kong
404 { 455, CAMERA_ANTIBANDING_50HZ }, // Macao
405 { 456, CAMERA_ANTIBANDING_50HZ }, // Cambodia
406 { 457, CAMERA_ANTIBANDING_50HZ }, // Laos
407 { 460, CAMERA_ANTIBANDING_50HZ }, // China
408 { 466, CAMERA_ANTIBANDING_60HZ }, // Taiwan
409 { 470, CAMERA_ANTIBANDING_50HZ }, // Bangladesh
410 { 472, CAMERA_ANTIBANDING_50HZ }, // Maldives
411 { 502, CAMERA_ANTIBANDING_50HZ }, // Malaysia
412 { 505, CAMERA_ANTIBANDING_50HZ }, // Australia
413 { 510, CAMERA_ANTIBANDING_50HZ }, // Indonesia
414 { 514, CAMERA_ANTIBANDING_50HZ }, // East Timor
415 { 515, CAMERA_ANTIBANDING_60HZ }, // Philippines
416 { 520, CAMERA_ANTIBANDING_50HZ }, // Thailand
417 { 525, CAMERA_ANTIBANDING_50HZ }, // Singapore
418 { 530, CAMERA_ANTIBANDING_50HZ }, // New Zealand
419 { 535, CAMERA_ANTIBANDING_60HZ }, // Guam
420 { 536, CAMERA_ANTIBANDING_50HZ }, // Nauru
421 { 537, CAMERA_ANTIBANDING_50HZ }, // Papua New Guinea
422 { 539, CAMERA_ANTIBANDING_50HZ }, // Tonga
423 { 541, CAMERA_ANTIBANDING_50HZ }, // Vanuatu
424 { 542, CAMERA_ANTIBANDING_50HZ }, // Fiji
425 { 544, CAMERA_ANTIBANDING_60HZ }, // American Samoa
426 { 545, CAMERA_ANTIBANDING_50HZ }, // Kiribati
427 { 546, CAMERA_ANTIBANDING_50HZ }, // New Caledonia
428 { 548, CAMERA_ANTIBANDING_50HZ }, // Cook Islands
429 { 602, CAMERA_ANTIBANDING_50HZ }, // Egypt
430 { 603, CAMERA_ANTIBANDING_50HZ }, // Algeria
431 { 604, CAMERA_ANTIBANDING_50HZ }, // Morocco
432 { 605, CAMERA_ANTIBANDING_50HZ }, // Tunisia
433 { 606, CAMERA_ANTIBANDING_50HZ }, // Libya
434 { 607, CAMERA_ANTIBANDING_50HZ }, // Gambia
435 { 608, CAMERA_ANTIBANDING_50HZ }, // Senegal
436 { 609, CAMERA_ANTIBANDING_50HZ }, // Mauritania
437 { 610, CAMERA_ANTIBANDING_50HZ }, // Mali
438 { 611, CAMERA_ANTIBANDING_50HZ }, // Guinea
439 { 613, CAMERA_ANTIBANDING_50HZ }, // Burkina Faso
440 { 614, CAMERA_ANTIBANDING_50HZ }, // Niger
441 { 616, CAMERA_ANTIBANDING_50HZ }, // Benin
442 { 617, CAMERA_ANTIBANDING_50HZ }, // Mauritius
443 { 618, CAMERA_ANTIBANDING_50HZ }, // Liberia
444 { 619, CAMERA_ANTIBANDING_50HZ }, // Sierra Leone
445 { 620, CAMERA_ANTIBANDING_50HZ }, // Ghana
446 { 621, CAMERA_ANTIBANDING_50HZ }, // Nigeria
447 { 622, CAMERA_ANTIBANDING_50HZ }, // Chad
448 { 623, CAMERA_ANTIBANDING_50HZ }, // Central African Republic
449 { 624, CAMERA_ANTIBANDING_50HZ }, // Cameroon
450 { 625, CAMERA_ANTIBANDING_50HZ }, // Cape Verde
451 { 627, CAMERA_ANTIBANDING_50HZ }, // Equatorial Guinea
452 { 631, CAMERA_ANTIBANDING_50HZ }, // Angola
453 { 633, CAMERA_ANTIBANDING_50HZ }, // Seychelles
454 { 634, CAMERA_ANTIBANDING_50HZ }, // Sudan
455 { 636, CAMERA_ANTIBANDING_50HZ }, // Ethiopia
456 { 637, CAMERA_ANTIBANDING_50HZ }, // Somalia
457 { 638, CAMERA_ANTIBANDING_50HZ }, // Djibouti
458 { 639, CAMERA_ANTIBANDING_50HZ }, // Kenya
459 { 640, CAMERA_ANTIBANDING_50HZ }, // Tanzania
460 { 641, CAMERA_ANTIBANDING_50HZ }, // Uganda
461 { 642, CAMERA_ANTIBANDING_50HZ }, // Burundi
462 { 643, CAMERA_ANTIBANDING_50HZ }, // Mozambique
463 { 645, CAMERA_ANTIBANDING_50HZ }, // Zambia
464 { 646, CAMERA_ANTIBANDING_50HZ }, // Madagascar
465 { 647, CAMERA_ANTIBANDING_50HZ }, // France
466 { 648, CAMERA_ANTIBANDING_50HZ }, // Zimbabwe
467 { 649, CAMERA_ANTIBANDING_50HZ }, // Namibia
468 { 650, CAMERA_ANTIBANDING_50HZ }, // Malawi
469 { 651, CAMERA_ANTIBANDING_50HZ }, // Lesotho
470 { 652, CAMERA_ANTIBANDING_50HZ }, // Botswana
471 { 653, CAMERA_ANTIBANDING_50HZ }, // Swaziland
472 { 654, CAMERA_ANTIBANDING_50HZ }, // Comoros
473 { 655, CAMERA_ANTIBANDING_50HZ }, // South Africa
474 { 657, CAMERA_ANTIBANDING_50HZ }, // Eritrea
475 { 702, CAMERA_ANTIBANDING_60HZ }, // Belize
476 { 704, CAMERA_ANTIBANDING_60HZ }, // Guatemala
477 { 706, CAMERA_ANTIBANDING_60HZ }, // El Salvador
478 { 708, CAMERA_ANTIBANDING_60HZ }, // Honduras
479 { 710, CAMERA_ANTIBANDING_60HZ }, // Nicaragua
480 { 712, CAMERA_ANTIBANDING_60HZ }, // Costa Rica
481 { 714, CAMERA_ANTIBANDING_60HZ }, // Panama
482 { 722, CAMERA_ANTIBANDING_50HZ }, // Argentina
483 { 724, CAMERA_ANTIBANDING_60HZ }, // Brazil
484 { 730, CAMERA_ANTIBANDING_50HZ }, // Chile
485 { 732, CAMERA_ANTIBANDING_60HZ }, // Colombia
486 { 734, CAMERA_ANTIBANDING_60HZ }, // Venezuela
487 { 736, CAMERA_ANTIBANDING_50HZ }, // Bolivia
488 { 738, CAMERA_ANTIBANDING_60HZ }, // Guyana
489 { 740, CAMERA_ANTIBANDING_60HZ }, // Ecuador
490 { 742, CAMERA_ANTIBANDING_50HZ }, // French Guiana
491 { 744, CAMERA_ANTIBANDING_50HZ }, // Paraguay
492 { 746, CAMERA_ANTIBANDING_60HZ }, // Suriname
493 { 748, CAMERA_ANTIBANDING_50HZ }, // Uruguay
494 { 750, CAMERA_ANTIBANDING_50HZ }, // Falkland Islands
495};
496
497#define country_number (sizeof(country_numeric) / sizeof(country_map))
498
499/* Look up pre-sorted antibanding_type table by current MCC. */
500static camera_antibanding_type camera_get_location(void) {
501 char value[PROP_VALUE_MAX];
502 char country_value[PROP_VALUE_MAX];
503 uint32_t country_code, count;
504 memset(value, 0x00, sizeof(value));
505 memset(country_value, 0x00, sizeof(country_value));
506 if (!__system_property_get("gsm.operator.numeric", value)) {
507 return CAMERA_ANTIBANDING_60HZ;
508 }
509 memcpy(country_value, value, 3);
510 country_code = atoi(country_value);
511 LOGD("value:%s, country value:%s, country code:%d\n",
512 value, country_value, country_code);
513 int left = 0;
514 int right = country_number - 1;
515 while (left <= right) {
516 int index = (left + right) >> 1;
517 if (country_numeric[index].country_code == country_code)
518 return country_numeric[index].type;
519 else if (country_numeric[index].country_code > country_code)
520 right = index - 1;
521 else
522 left = index + 1;
523 }
524 return CAMERA_ANTIBANDING_60HZ;
525}
526
527// from camera.h, led_mode_t
528static const str_map flash[] = {
529 { CameraParameters::FLASH_MODE_OFF, LED_MODE_OFF },
530 { CameraParameters::FLASH_MODE_AUTO, LED_MODE_AUTO },
531 { CameraParameters::FLASH_MODE_ON, LED_MODE_ON }
532};
533
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530534// from mm-camera/common/camera.h.
535static const str_map iso[] = {
536 { CameraParameters::ISO_AUTO, CAMERA_ISO_AUTO},
537 { CameraParameters::ISO_HJR, CAMERA_ISO_DEBLUR},
538 { CameraParameters::ISO_100, CAMERA_ISO_100},
539 { CameraParameters::ISO_200, CAMERA_ISO_200},
540 { CameraParameters::ISO_400, CAMERA_ISO_400},
541 { CameraParameters::ISO_800, CAMERA_ISO_800 }
542};
543
544
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800545#define DONT_CARE 0
546static const str_map focus_modes[] = {
Srinivasan Kannan71229622009-12-04 12:05:58 -0800547 { CameraParameters::FOCUS_MODE_AUTO, AF_MODE_AUTO},
548 { CameraParameters::FOCUS_MODE_INFINITY, DONT_CARE },
549 { CameraParameters::FOCUS_MODE_NORMAL, AF_MODE_NORMAL },
550 { CameraParameters::FOCUS_MODE_MACRO, AF_MODE_MACRO }
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800551};
552
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530553static const str_map lensshade[] = {
554 { CameraParameters::LENSSHADE_ENABLE, TRUE },
555 { CameraParameters::LENSSHADE_DISABLE, FALSE }
556};
557
Srinivasan Kannan71229622009-12-04 12:05:58 -0800558struct SensorType {
559 const char *name;
560 int rawPictureWidth;
561 int rawPictureHeight;
562 bool hasAutoFocusSupport;
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800563 int max_supported_snapshot_width;
564 int max_supported_snapshot_height;
Srinivasan Kannan71229622009-12-04 12:05:58 -0800565};
566
567static SensorType sensorTypes[] = {
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800568 { "5mp", 2608, 1960, true, 2592, 1944 },
569 { "3mp", 2064, 1544, false, 2048, 1536 },
570 { "2mp", 3200, 1200, false, 1600, 1200 } };
571
Srinivasan Kannan71229622009-12-04 12:05:58 -0800572
573static SensorType * sensorType;
574
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800575static const str_map picture_formats[] = {
576 {CameraParameters::PIXEL_FORMAT_JPEG, PICTURE_FORMAT_JPEG},
577 {CameraParameters::PIXEL_FORMAT_RAW, PICTURE_FORMAT_RAW}
578};
579
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800580static bool parameter_string_initialized = false;
581static String8 preview_size_values;
582static String8 picture_size_values;
583static String8 antibanding_values;
584static String8 effect_values;
Apurva Rajguru55562b02009-12-03 12:25:35 -0800585static String8 autoexposure_values;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800586static String8 whitebalance_values;
587static String8 flash_values;
588static String8 focus_mode_values;
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530589static String8 iso_values;
590static String8 lensshade_values;
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800591static String8 picture_format_values;
592
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800593
594static String8 create_sizes_str(const camera_size_type *sizes, int len) {
595 String8 str;
596 char buffer[32];
597
598 if (len > 0) {
599 sprintf(buffer, "%dx%d", sizes[0].width, sizes[0].height);
600 str.append(buffer);
601 }
602 for (int i = 1; i < len; i++) {
603 sprintf(buffer, ",%dx%d", sizes[i].width, sizes[i].height);
604 str.append(buffer);
605 }
606 return str;
607}
608
609static String8 create_values_str(const str_map *values, int len) {
610 String8 str;
611
612 if (len > 0) {
613 str.append(values[0].desc);
614 }
615 for (int i = 1; i < len; i++) {
616 str.append(",");
617 str.append(values[i].desc);
618 }
619 return str;
620}
621
622static Mutex singleton_lock;
623static bool singleton_releasing;
624static Condition singleton_wait;
625
626static void receive_camframe_callback(struct msm_frame *frame);
627static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size);
628static void receive_jpeg_callback(jpeg_event_t status);
629static void receive_shutter_callback(common_crop_t *crop);
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800630static void receive_camframetimeout_callback(void);
Mohan Kandra284966d2010-01-05 13:39:15 -0800631static int fb_fd = -1;
632static int32_t mMaxZoom = 0;
633static bool native_get_maxzoom(int camfd, void *pZm);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800634
635QualcommCameraHardware::QualcommCameraHardware()
636 : mParameters(),
637 mCameraRunning(false),
638 mPreviewInitialized(false),
639 mFrameThreadRunning(false),
640 mSnapshotThreadRunning(false),
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800641 mSnapshotFormat(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800642 mReleasedRecordingFrame(false),
643 mPreviewFrameSize(0),
644 mRawSize(0),
645 mCameraControlFd(-1),
646 mAutoFocusThreadRunning(false),
647 mAutoFocusFd(-1),
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800648 mBrightness(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800649 mInPreviewCallback(false),
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800650 mUseOverlay(0),
651 mOverlay(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800652 mMsgEnabled(0),
653 mNotifyCallback(0),
654 mDataCallback(0),
655 mDataCallbackTimestamp(0),
Mohan Kandra740cfce2010-01-07 12:58:24 -0800656 mCallbackCookie(0),
657 mDebugFps(0)
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800658{
659 memset(&mDimension, 0, sizeof(mDimension));
660 memset(&mCrop, 0, sizeof(mCrop));
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -0800661 memset(&zoomCropInfo, 0, sizeof(zoom_crop_info));
Mohan Kandra284966d2010-01-05 13:39:15 -0800662 property_get("ro.product.device",mDeviceName," ");
Mohan Kandra740cfce2010-01-07 12:58:24 -0800663 char value[PROPERTY_VALUE_MAX];
664 property_get("persist.debug.sf.showfps", value, "0");
665 mDebugFps = atoi(value);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800666 LOGV("constructor EX");
667}
668
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800669
670//filter Picture sizes based on max width and height
671void QualcommCameraHardware::filterPictureSizes(){
672 int i;
673 for(i=0;i<PICTURE_SIZE_COUNT;i++){
674 if(((picture_sizes[i].width <=
675 sensorType->max_supported_snapshot_width) &&
676 (picture_sizes[i].height <=
677 sensorType->max_supported_snapshot_height))){
678 picture_sizes_ptr = picture_sizes + i;
679 supportedPictureSizesCount = PICTURE_SIZE_COUNT - i ;
680 return ;
681 }
682 }
683}
684
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800685void QualcommCameraHardware::initDefaultParameters()
686{
687 LOGV("initDefaultParameters E");
688
689 // Initialize constant parameter strings. This will happen only once in the
690 // lifetime of the mediaserver process.
691 if (!parameter_string_initialized) {
Srinivasan Kannan71229622009-12-04 12:05:58 -0800692 findSensorType();
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800693 antibanding_values = create_values_str(
694 antibanding, sizeof(antibanding) / sizeof(str_map));
695 effect_values = create_values_str(
696 effects, sizeof(effects) / sizeof(str_map));
Apurva Rajguru55562b02009-12-03 12:25:35 -0800697 autoexposure_values = create_values_str(
698 autoexposure, sizeof(autoexposure) / sizeof(str_map));
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800699 whitebalance_values = create_values_str(
700 whitebalance, sizeof(whitebalance) / sizeof(str_map));
701 preview_size_values = create_sizes_str(
702 preview_sizes, PREVIEW_SIZE_COUNT);
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800703 //filter picture sizes
704 filterPictureSizes();
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800705 picture_size_values = create_sizes_str(
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800706 picture_sizes_ptr, supportedPictureSizesCount);
707
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800708 flash_values = create_values_str(
709 flash, sizeof(flash) / sizeof(str_map));
Srinivasan Kannan71229622009-12-04 12:05:58 -0800710 if(sensorType->hasAutoFocusSupport){
711 focus_mode_values = create_values_str(
712 focus_modes, sizeof(focus_modes) / sizeof(str_map));
713 }
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530714 iso_values = create_values_str(
715 iso,sizeof(iso)/sizeof(str_map));
716 lensshade_values = create_values_str(
717 lensshade,sizeof(lensshade)/sizeof(str_map));
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800718 picture_format_values = create_values_str(
719 picture_formats, sizeof(picture_formats)/sizeof(str_map));
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800720 parameter_string_initialized = true;
721 }
722
723 const camera_size_type *ps = &preview_sizes[DEFAULT_PREVIEW_SETTING];
724 mParameters.setPreviewSize(ps->width, ps->height);
725 mDimension.display_width = ps->width;
726 mDimension.display_height = ps->height;
727 mParameters.setPreviewFrameRate(15);
728 mParameters.setPreviewFormat("yuv420sp"); // informative
729
730 mParameters.setPictureSize(DEFAULT_PICTURE_WIDTH, DEFAULT_PICTURE_HEIGHT);
731 mParameters.setPictureFormat("jpeg"); // informative
732
733 mParameters.set(CameraParameters::KEY_JPEG_QUALITY, "100"); // max quality
734 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH,
735 THUMBNAIL_WIDTH_STR); // informative
736 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT,
737 THUMBNAIL_HEIGHT_STR); // informative
Srinivasan Kannan80d878f2009-12-18 15:06:02 -0800738 mDimension.ui_thumbnail_width =
739 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].width;
740 mDimension.ui_thumbnail_height =
741 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800742 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, "90");
743
744 mParameters.set(CameraParameters::KEY_ANTIBANDING,
745 CameraParameters::ANTIBANDING_AUTO);
746 mParameters.set(CameraParameters::KEY_EFFECT,
747 CameraParameters::EFFECT_NONE);
Apurva Rajguru55562b02009-12-03 12:25:35 -0800748 mParameters.set(CameraParameters::KEY_AUTO_EXPOSURE,
749 CameraParameters::AUTO_EXPOSURE_FRAME_AVG);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800750 mParameters.set(CameraParameters::KEY_WHITE_BALANCE,
751 CameraParameters::WHITE_BALANCE_AUTO);
752 mParameters.set(CameraParameters::KEY_FOCUS_MODE,
753 CameraParameters::FOCUS_MODE_AUTO);
754
755 mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES,
756 preview_size_values.string());
757 mParameters.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES,
758 picture_size_values.string());
759 mParameters.set(CameraParameters::KEY_SUPPORTED_ANTIBANDING,
760 antibanding_values);
761 mParameters.set(CameraParameters::KEY_SUPPORTED_EFFECTS, effect_values);
Apurva Rajguru55562b02009-12-03 12:25:35 -0800762 mParameters.set(CameraParameters::KEY_SUPPORTED_AUTO_EXPOSURE, autoexposure_values);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800763 mParameters.set(CameraParameters::KEY_SUPPORTED_WHITE_BALANCE,
764 whitebalance_values);
765 mParameters.set(CameraParameters::KEY_SUPPORTED_FOCUS_MODES,
766 focus_mode_values);
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800767 mParameters.set(CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS,
768 picture_format_values);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800769
770 if (mSensorInfo.flash_enabled) {
771 mParameters.set(CameraParameters::KEY_FLASH_MODE,
772 CameraParameters::FLASH_MODE_OFF);
773 mParameters.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES,
774 flash_values);
775 }
776
Srinivasan Kannanbddfd502010-01-03 17:27:36 -0800777 mParameters.set(CameraParameters::KEY_MAX_SHARPNESS,
778 CAMERA_MAX_SHARPNESS);
779 mParameters.set(CameraParameters::KEY_MAX_CONTRAST,
780 CAMERA_MAX_CONTRAST);
781 mParameters.set(CameraParameters::KEY_MAX_SATURATION,
782 CAMERA_MAX_SATURATION);
783
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530784 mParameters.set("luma-adaptation", "18");
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800785 mParameters.set("zoom-supported", "true");
786 mParameters.set("max-zoom", MAX_ZOOM_LEVEL);
787 mParameters.set("zoom", 0);
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800788 mParameters.set(CameraParameters::KEY_PICTURE_FORMAT,
789 CameraParameters::PIXEL_FORMAT_JPEG);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800790
Kiran Kumar H N595970b2010-01-12 10:41:09 -0800791 mParameters.set(CameraParameters::KEY_SHARPNESS,
792 CAMERA_DEF_SHARPNESS);
793 mParameters.set(CameraParameters::KEY_CONTRAST,
794 CAMERA_DEF_CONTRAST);
795 mParameters.set(CameraParameters::KEY_SATURATION,
796 CAMERA_DEF_SATURATION);
797
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530798 mParameters.set(CameraParameters::KEY_ISO_MODE,
799 CameraParameters::ISO_AUTO);
800 mParameters.set(CameraParameters::KEY_LENSSHADE,
801 CameraParameters::LENSSHADE_ENABLE);
802 mParameters.set(CameraParameters::KEY_SUPPORTED_ISO_MODES,
803 iso_values);
804 mParameters.set(CameraParameters::KEY_SUPPORTED_LENSSHADE_MODES,
805 lensshade_values);
806
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800807 if (setParameters(mParameters) != NO_ERROR) {
808 LOGE("Failed to set default parameters?!");
809 }
810
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -0800811 mUseOverlay = useOverlay();
812
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800813 /* Initialize the camframe_timeout_flag*/
814 Mutex::Autolock l(&mCamframeTimeoutLock);
815 camframe_timeout_flag = FALSE;
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -0800816 mPostViewHeap = NULL;
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800817
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800818 LOGV("initDefaultParameters X");
819}
820
Srinivasan Kannan71229622009-12-04 12:05:58 -0800821void QualcommCameraHardware::findSensorType(){
822 mDimension.picture_width = DEFAULT_PICTURE_WIDTH;
823 mDimension.picture_height = DEFAULT_PICTURE_HEIGHT;
824 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
825 sizeof(cam_ctrl_dimension_t), &mDimension);
826 if (ret) {
827 unsigned int i;
828 for (i = 0; i < sizeof(sensorTypes) / sizeof(SensorType); i++) {
829 if (sensorTypes[i].rawPictureHeight
830 == mDimension.raw_picture_height) {
831 sensorType = sensorTypes + i;
832 return;
833 }
834 }
835 }
836 //default to 5 mp
837 sensorType = sensorTypes;
838 return;
839}
840
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800841#define ROUND_TO_PAGE(x) (((x)+0xfff)&~0xfff)
842
843bool QualcommCameraHardware::startCamera()
844{
845 LOGV("startCamera E");
846#if DLOPEN_LIBMMCAMERA
847 libmmcamera = ::dlopen("liboemcamera.so", RTLD_NOW);
848 LOGV("loading liboemcamera at %p", libmmcamera);
849 if (!libmmcamera) {
850 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
851 return false;
852 }
853
854 *(void **)&LINK_cam_frame =
855 ::dlsym(libmmcamera, "cam_frame");
856 *(void **)&LINK_camframe_terminate =
857 ::dlsym(libmmcamera, "camframe_terminate");
858
859 *(void **)&LINK_jpeg_encoder_init =
860 ::dlsym(libmmcamera, "jpeg_encoder_init");
861
862 *(void **)&LINK_jpeg_encoder_encode =
863 ::dlsym(libmmcamera, "jpeg_encoder_encode");
864
865 *(void **)&LINK_jpeg_encoder_join =
866 ::dlsym(libmmcamera, "jpeg_encoder_join");
867
868 *(void **)&LINK_mmcamera_camframe_callback =
869 ::dlsym(libmmcamera, "mmcamera_camframe_callback");
870
871 *LINK_mmcamera_camframe_callback = receive_camframe_callback;
872
873 *(void **)&LINK_mmcamera_jpegfragment_callback =
874 ::dlsym(libmmcamera, "mmcamera_jpegfragment_callback");
875
876 *LINK_mmcamera_jpegfragment_callback = receive_jpeg_fragment_callback;
877
878 *(void **)&LINK_mmcamera_jpeg_callback =
879 ::dlsym(libmmcamera, "mmcamera_jpeg_callback");
880
881 *LINK_mmcamera_jpeg_callback = receive_jpeg_callback;
882
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800883 *(void **)&LINK_camframe_timeout_callback =
884 ::dlsym(libmmcamera, "camframe_timeout_callback");
885
886 *LINK_camframe_timeout_callback = receive_camframetimeout_callback;
887
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800888/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800889 *(void **)&LINK_mmcamera_shutter_callback =
890 ::dlsym(libmmcamera, "mmcamera_shutter_callback");
891
892 *LINK_mmcamera_shutter_callback = receive_shutter_callback;
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800893*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800894 *(void**)&LINK_jpeg_encoder_setMainImageQuality =
895 ::dlsym(libmmcamera, "jpeg_encoder_setMainImageQuality");
Kiran Kumar H N8861f302010-01-05 12:01:41 -0800896
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800897 *(void**)&LINK_jpeg_encoder_setThumbnailQuality =
898 ::dlsym(libmmcamera, "jpeg_encoder_setThumbnailQuality");
899
900 *(void**)&LINK_jpeg_encoder_setRotation =
901 ::dlsym(libmmcamera, "jpeg_encoder_setRotation");
902
Kiran Kumar H N8861f302010-01-05 12:01:41 -0800903/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800904 *(void**)&LINK_jpeg_encoder_setLocation =
905 ::dlsym(libmmcamera, "jpeg_encoder_setLocation");
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800906*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800907 *(void **)&LINK_cam_conf =
908 ::dlsym(libmmcamera, "cam_conf");
909
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800910/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800911 *(void **)&LINK_default_sensor_get_snapshot_sizes =
912 ::dlsym(libmmcamera, "default_sensor_get_snapshot_sizes");
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800913*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800914 *(void **)&LINK_launch_cam_conf_thread =
915 ::dlsym(libmmcamera, "launch_cam_conf_thread");
916
917 *(void **)&LINK_release_cam_conf_thread =
918 ::dlsym(libmmcamera, "release_cam_conf_thread");
919
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800920/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800921 *(void **)&LINK_zoom_crop_upscale =
922 ::dlsym(libmmcamera, "zoom_crop_upscale");
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800923*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800924
925#else
926 mmcamera_camframe_callback = receive_camframe_callback;
927 mmcamera_jpegfragment_callback = receive_jpeg_fragment_callback;
928 mmcamera_jpeg_callback = receive_jpeg_callback;
929 mmcamera_shutter_callback = receive_shutter_callback;
930#endif // DLOPEN_LIBMMCAMERA
931
932 /* The control thread is in libcamera itself. */
933 mCameraControlFd = open(MSM_CAMERA_CONTROL, O_RDWR);
Kiran Kumar H N494c9fc2010-01-07 15:55:15 -0800934 if (mCameraControlFd <= 0) {
935 if( mCameraControlFd == 0 ) {
936 /* This should not happen. But if and when it
937 * happens, we should not be using fd 0 for issuing
938 * any IOCTL calls to camera driver since the
939 * behaviour is undeterministic. Hence adding a
940 * workaround to deal with this issue */
941 LOGD(" Returned FD is 0....open again ");
942 mCameraControlFd = open(MSM_CAMERA_CONTROL, O_RDWR);
943 }
944 if (mCameraControlFd < 0) {
945 LOGE("startCamera X: %s open failed: %s!",
946 MSM_CAMERA_CONTROL,
947 strerror(errno));
948 return false;
949 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800950 }
951
Mohan Kandra284966d2010-01-05 13:39:15 -0800952 if(strncmp(mDeviceName,"msm7630", 7)){
953 fb_fd = open("/dev/graphics/fb0", O_RDWR);
954 if (fb_fd < 0) {
955 LOGE("startCamera: fb0 open failed: %s!", strerror(errno));
956 return FALSE;
957 }
958 }
959
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800960 /* This will block until the control thread is launched. After that, sensor
961 * information becomes available.
962 */
963
964 if (LINK_launch_cam_conf_thread()) {
965 LOGE("failed to launch the camera config thread");
966 return false;
967 }
968
969 memset(&mSensorInfo, 0, sizeof(mSensorInfo));
970 if (ioctl(mCameraControlFd,
971 MSM_CAM_IOCTL_GET_SENSOR_INFO,
972 &mSensorInfo) < 0)
973 LOGW("%s: cannot retrieve sensor info!", __FUNCTION__);
974 else
975 LOGI("%s: camsensor name %s, flash %d", __FUNCTION__,
976 mSensorInfo.name, mSensorInfo.flash_enabled);
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800977/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800978 picture_sizes = LINK_default_sensor_get_snapshot_sizes(&PICTURE_SIZE_COUNT);
979 if (!picture_sizes || !PICTURE_SIZE_COUNT) {
980 LOGE("startCamera X: could not get snapshot sizes");
981 return false;
982 }
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800983*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800984 LOGV("startCamera X");
985 return true;
986}
987
988status_t QualcommCameraHardware::dump(int fd,
989 const Vector<String16>& args) const
990{
991 const size_t SIZE = 256;
992 char buffer[SIZE];
993 String8 result;
994
995 // Dump internal primitives.
996 result.append("QualcommCameraHardware::dump");
997 snprintf(buffer, 255, "mMsgEnabled (%d)\n", mMsgEnabled);
998 result.append(buffer);
999 int width, height;
1000 mParameters.getPreviewSize(&width, &height);
1001 snprintf(buffer, 255, "preview width(%d) x height (%d)\n", width, height);
1002 result.append(buffer);
1003 mParameters.getPictureSize(&width, &height);
1004 snprintf(buffer, 255, "raw width(%d) x height (%d)\n", width, height);
1005 result.append(buffer);
1006 snprintf(buffer, 255,
1007 "preview frame size(%d), raw size (%d), jpeg size (%d) "
1008 "and jpeg max size (%d)\n", mPreviewFrameSize, mRawSize,
1009 mJpegSize, mJpegMaxSize);
1010 result.append(buffer);
1011 write(fd, result.string(), result.size());
1012
1013 // Dump internal objects.
Mohan Kandra284966d2010-01-05 13:39:15 -08001014 if (mCameraPreviewHeap != 0) {
1015 mCameraPreviewHeap->dump(fd, args);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001016 }
1017 if (mRawHeap != 0) {
1018 mRawHeap->dump(fd, args);
1019 }
1020 if (mJpegHeap != 0) {
1021 mJpegHeap->dump(fd, args);
1022 }
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001023 if(mRawSnapshotAshmemHeap != 0 ){
1024 mRawSnapshotAshmemHeap->dump(fd, args);
1025 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001026 mParameters.dump(fd, args);
1027 return NO_ERROR;
1028}
1029
Mohan Kandra284966d2010-01-05 13:39:15 -08001030static bool native_get_maxzoom(int camfd, void *pZm)
1031{
1032 LOGV("native_get_maxzoom E");
1033
1034 struct msm_ctrl_cmd ctrlCmd;
1035 int32_t *pZoom = (int32_t *)pZm;
1036
1037 ctrlCmd.type = CAMERA_GET_PARM_MAXZOOM;
1038 ctrlCmd.timeout_ms = 5000;
1039 ctrlCmd.length = sizeof(int32_t);
1040 ctrlCmd.value = pZoom;
1041 ctrlCmd.resp_fd = camfd;
1042
1043 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1044 LOGE("native_get_maxzoom: ioctl fd %d error %s",
1045 camfd,
1046 strerror(errno));
1047 return false;
1048 }
1049 LOGE("ctrlCmd.value = %d", *(int32_t *)ctrlCmd.value);
1050 memcpy(pZoom, (int32_t *)ctrlCmd.value, sizeof(int32_t));
1051
1052 LOGV("native_get_maxzoom X");
1053 return true;
1054}
1055
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001056static bool native_set_afmode(int camfd, isp3a_af_mode_t af_type)
1057{
1058 int rc;
1059 struct msm_ctrl_cmd ctrlCmd;
1060
1061 ctrlCmd.timeout_ms = 5000;
1062 ctrlCmd.type = CAMERA_SET_PARM_AUTO_FOCUS;
1063 ctrlCmd.length = sizeof(af_type);
1064 ctrlCmd.value = &af_type;
1065 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1066
1067 if ((rc = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0)
1068 LOGE("native_set_afmode: ioctl fd %d error %s\n",
1069 camfd,
1070 strerror(errno));
1071
1072 LOGV("native_set_afmode: ctrlCmd.status == %d\n", ctrlCmd.status);
1073 return rc >= 0 && ctrlCmd.status == CAMERA_EXIT_CB_DONE;
1074}
1075
1076static bool native_cancel_afmode(int camfd, int af_fd)
1077{
1078 int rc;
1079 struct msm_ctrl_cmd ctrlCmd;
1080
1081 ctrlCmd.timeout_ms = 0;
1082 ctrlCmd.type = CAMERA_AUTO_FOCUS_CANCEL;
1083 ctrlCmd.length = 0;
1084 ctrlCmd.value = NULL;
1085 ctrlCmd.resp_fd = -1; // there's no response fd
1086
1087 if ((rc = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND_2, &ctrlCmd)) < 0)
1088 {
1089 LOGE("native_cancel_afmode: ioctl fd %d error %s\n",
1090 camfd,
1091 strerror(errno));
1092 return false;
1093 }
1094
1095 return true;
1096}
1097
1098static bool native_start_preview(int camfd)
1099{
1100 struct msm_ctrl_cmd ctrlCmd;
1101
1102 ctrlCmd.timeout_ms = 5000;
1103 ctrlCmd.type = CAMERA_START_PREVIEW;
1104 ctrlCmd.length = 0;
1105 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1106
1107 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1108 LOGE("native_start_preview: MSM_CAM_IOCTL_CTRL_COMMAND fd %d error %s",
1109 camfd,
1110 strerror(errno));
1111 return false;
1112 }
1113
1114 return true;
1115}
1116
1117static bool native_get_picture (int camfd, common_crop_t *crop)
1118{
1119 struct msm_ctrl_cmd ctrlCmd;
1120
1121 ctrlCmd.timeout_ms = 5000;
1122 ctrlCmd.length = sizeof(common_crop_t);
1123 ctrlCmd.value = crop;
1124
1125 if(ioctl(camfd, MSM_CAM_IOCTL_GET_PICTURE, &ctrlCmd) < 0) {
1126 LOGE("native_get_picture: MSM_CAM_IOCTL_GET_PICTURE fd %d error %s",
1127 camfd,
1128 strerror(errno));
1129 return false;
1130 }
1131
1132 LOGV("crop: in1_w %d", crop->in1_w);
1133 LOGV("crop: in1_h %d", crop->in1_h);
1134 LOGV("crop: out1_w %d", crop->out1_w);
1135 LOGV("crop: out1_h %d", crop->out1_h);
1136
1137 LOGV("crop: in2_w %d", crop->in2_w);
1138 LOGV("crop: in2_h %d", crop->in2_h);
1139 LOGV("crop: out2_w %d", crop->out2_w);
1140 LOGV("crop: out2_h %d", crop->out2_h);
1141
1142 LOGV("crop: update %d", crop->update_flag);
1143
1144 return true;
1145}
1146
1147static bool native_stop_preview(int camfd)
1148{
1149 struct msm_ctrl_cmd ctrlCmd;
1150 ctrlCmd.timeout_ms = 5000;
1151 ctrlCmd.type = CAMERA_STOP_PREVIEW;
1152 ctrlCmd.length = 0;
1153 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1154
1155 if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1156 LOGE("native_stop_preview: ioctl fd %d error %s",
1157 camfd,
1158 strerror(errno));
1159 return false;
1160 }
1161
1162 return true;
1163}
1164
1165static bool native_prepare_snapshot(int camfd)
1166{
1167 int ioctlRetVal = true;
1168 struct msm_ctrl_cmd ctrlCmd;
1169
1170 ctrlCmd.timeout_ms = 1000;
1171 ctrlCmd.type = CAMERA_PREPARE_SNAPSHOT;
1172 ctrlCmd.length = 0;
1173 ctrlCmd.value = NULL;
1174 ctrlCmd.resp_fd = camfd;
1175
1176 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1177 LOGE("native_prepare_snapshot: ioctl fd %d error %s",
1178 camfd,
1179 strerror(errno));
1180 return false;
1181 }
1182 return true;
1183}
1184
1185static bool native_start_snapshot(int camfd)
1186{
1187 struct msm_ctrl_cmd ctrlCmd;
1188
1189 ctrlCmd.timeout_ms = 5000;
1190 ctrlCmd.type = CAMERA_START_SNAPSHOT;
1191 ctrlCmd.length = 0;
1192 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1193
1194 if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1195 LOGE("native_start_snapshot: ioctl fd %d error %s",
1196 camfd,
1197 strerror(errno));
1198 return false;
1199 }
1200
1201 return true;
1202}
1203
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001204static bool native_start_raw_snapshot(int camfd)
1205{
1206 int ret;
1207 struct msm_ctrl_cmd ctrlCmd;
1208
1209 ctrlCmd.timeout_ms = 1000;
1210 ctrlCmd.type = CAMERA_START_RAW_SNAPSHOT;
1211 ctrlCmd.length = 0;
1212 ctrlCmd.value = NULL;
1213 ctrlCmd.resp_fd = camfd;
1214
1215 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1216 LOGE("native_start_raw_snapshot: ioctl failed. ioctl return value "\
1217 "is %d \n", ret);
1218 return false;
1219 }
1220 return true;
1221}
1222
1223
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001224static bool native_stop_snapshot (int camfd)
1225{
1226 struct msm_ctrl_cmd ctrlCmd;
1227
1228 ctrlCmd.timeout_ms = 0;
1229 ctrlCmd.type = CAMERA_STOP_SNAPSHOT;
1230 ctrlCmd.length = 0;
1231 ctrlCmd.resp_fd = -1;
1232
1233 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND_2, &ctrlCmd) < 0) {
1234 LOGE("native_stop_snapshot: ioctl fd %d error %s",
1235 camfd,
1236 strerror(errno));
1237 return false;
1238 }
1239
1240 return true;
1241}
1242
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001243static rat_t latitude[3];
1244static rat_t longitude[3];
1245static char lonref[2];
1246static char latref[2];
1247static char dateTime[20];
1248static rat_t altitude;
1249
1250static void addExifTag(exif_tag_id_t tagid, exif_tag_type_t type,
1251 uint32_t count, uint8_t copy, void *data) {
1252
1253 if(exif_table_numEntries == MAX_EXIF_TABLE_ENTRIES) {
1254 LOGE("Number of entries exceeded limit");
1255 return;
1256 }
1257
1258 int index = exif_table_numEntries;
1259 exif_data[index].tag_id = tagid;
1260 exif_data[index].tag_entry.type = type;
1261 exif_data[index].tag_entry.count = count;
1262 exif_data[index].tag_entry.copy = copy;
1263 if((type == EXIF_RATIONAL) && (count > 1))
1264 exif_data[index].tag_entry.data._rats = (rat_t *)data;
1265 if((type == EXIF_RATIONAL) && (count == 1))
1266 exif_data[index].tag_entry.data._rat = *(rat_t *)data;
1267 else if(type == EXIF_ASCII)
1268 exif_data[index].tag_entry.data._ascii = (char *)data;
1269 else if(type == EXIF_BYTE)
1270 exif_data[index].tag_entry.data._byte = *(uint8_t *)data;
1271
1272 // Increase number of entries
1273 exif_table_numEntries++;
1274}
1275
1276static void parseLatLong(const char *latlonString, int *pDegrees,
1277 int *pMinutes, int *pSeconds ) {
1278
1279 double value = atof(latlonString);
1280 value = fabs(value);
1281 int degrees = (int) value;
1282
1283 double remainder = value - degrees;
1284 int minutes = (int) (remainder * 60);
1285 int seconds = (int) (((remainder * 60) - minutes) * 60 * 1000);
1286
1287 *pDegrees = degrees;
1288 *pMinutes = minutes;
1289 *pSeconds = seconds;
1290}
1291
1292static void setLatLon(exif_tag_id_t tag, const char *latlonString) {
1293
1294 int degrees, minutes, seconds;
1295
1296 parseLatLong(latlonString, &degrees, &minutes, &seconds);
1297
1298 rat_t value[3] = { {degrees, 1},
1299 {minutes, 1},
1300 {seconds, 1000} };
1301
1302 if(tag == EXIFTAGID_GPS_LATITUDE) {
1303 memcpy(latitude, value, sizeof(latitude));
1304 addExifTag(EXIFTAGID_GPS_LATITUDE, EXIF_RATIONAL, 3,
1305 1, (void *)latitude);
1306 } else {
1307 memcpy(longitude, value, sizeof(longitude));
1308 addExifTag(EXIFTAGID_GPS_LONGITUDE, EXIF_RATIONAL, 3,
1309 1, (void *)longitude);
1310 }
1311}
1312
1313void QualcommCameraHardware::setGpsParameters() {
1314 const char *str = NULL;
1315
1316 //Set Latitude
1317 str = mParameters.get(CameraParameters::KEY_GPS_LATITUDE);
1318 if(str != NULL) {
1319 setLatLon(EXIFTAGID_GPS_LATITUDE, str);
1320 //set Latitude Ref
1321 str = NULL;
1322 str = mParameters.get(CameraParameters::KEY_GPS_LATITUDE_REF);
1323 if(str != NULL) {
1324 strncpy(latref, str, 1);
1325 latref[1] = '\0';
1326 addExifTag(EXIFTAGID_GPS_LATITUDE_REF, EXIF_ASCII, 2,
1327 1, (void *)latref);
1328 }
1329 }
1330
1331 //set Longitude
1332 str = NULL;
1333 str = mParameters.get(CameraParameters::KEY_GPS_LONGITUDE);
1334 if(str != NULL) {
1335 setLatLon(EXIFTAGID_GPS_LONGITUDE, str);
1336 //set Longitude Ref
1337 str = NULL;
1338 str = mParameters.get(CameraParameters::KEY_GPS_LONGITUDE_REF);
1339 if(str != NULL) {
1340 strncpy(lonref, str, 1);
1341 lonref[1] = '\0';
1342 addExifTag(EXIFTAGID_GPS_LONGITUDE_REF, EXIF_ASCII, 2,
1343 1, (void *)lonref);
1344 }
1345 }
1346
1347 //set Altitude
1348 str = NULL;
1349 str = mParameters.get(CameraParameters::KEY_GPS_ALTITUDE);
1350 if(str != NULL) {
1351 int value = atoi(str);
1352 rat_t alt_value = {value, 1000};
1353 memcpy(&altitude, &alt_value, sizeof(altitude));
1354 addExifTag(EXIFTAGID_GPS_ALTITUDE, EXIF_RATIONAL, 1,
1355 1, (void *)&altitude);
1356 //set AltitudeRef
1357 int ref = mParameters.getInt(CameraParameters::KEY_GPS_ALTITUDE_REF);
1358 if( !(ref < 0 || ref > 1) )
1359 addExifTag(EXIFTAGID_GPS_ALTITUDE_REF, EXIF_BYTE, 1,
1360 1, (void *)&ref);
1361 }
1362
1363
1364}
1365
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001366bool QualcommCameraHardware::native_jpeg_encode(void)
1367{
1368 int jpeg_quality = mParameters.getInt("jpeg-quality");
1369 if (jpeg_quality >= 0) {
1370 LOGV("native_jpeg_encode, current jpeg main img quality =%d",
1371 jpeg_quality);
1372 if(!LINK_jpeg_encoder_setMainImageQuality(jpeg_quality)) {
1373 LOGE("native_jpeg_encode set jpeg-quality failed");
1374 return false;
1375 }
1376 }
1377
1378 int thumbnail_quality = mParameters.getInt("jpeg-thumbnail-quality");
1379 if (thumbnail_quality >= 0) {
1380 LOGV("native_jpeg_encode, current jpeg thumbnail quality =%d",
1381 thumbnail_quality);
1382 if(!LINK_jpeg_encoder_setThumbnailQuality(thumbnail_quality)) {
1383 LOGE("native_jpeg_encode set thumbnail-quality failed");
1384 return false;
1385 }
1386 }
1387
1388 int rotation = mParameters.getInt("rotation");
1389 if (rotation >= 0) {
1390 LOGV("native_jpeg_encode, rotation = %d", rotation);
1391 if(!LINK_jpeg_encoder_setRotation(rotation)) {
1392 LOGE("native_jpeg_encode set rotation failed");
1393 return false;
1394 }
1395 }
1396
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001397// jpeg_set_location();
1398 if(mParameters.getInt(CameraParameters::KEY_GPS_STATUS) == 1) {
1399 setGpsParameters();
1400 }
1401 //set TimeStamp
1402 const char *str = mParameters.get(CameraParameters::KEY_EXIF_DATETIME);
1403 if(str != NULL) {
1404 strncpy(dateTime, str, 19);
1405 dateTime[19] = '\0';
1406 addExifTag(EXIFTAGID_EXIF_DATE_TIME_ORIGINAL, EXIF_ASCII,
1407 20, 1, (void *)dateTime);
1408 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001409
1410 if (!LINK_jpeg_encoder_encode(&mDimension,
1411 (uint8_t *)mThumbnailHeap->mHeap->base(),
1412 mThumbnailHeap->mHeap->getHeapID(),
1413 (uint8_t *)mRawHeap->mHeap->base(),
1414 mRawHeap->mHeap->getHeapID(),
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001415 &mCrop, exif_data, exif_table_numEntries)) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001416 LOGE("native_jpeg_encode: jpeg_encoder_encode failed.");
1417 return false;
1418 }
1419 return true;
1420}
1421
1422bool QualcommCameraHardware::native_set_parm(
1423 cam_ctrl_type type, uint16_t length, void *value)
1424{
1425 struct msm_ctrl_cmd ctrlCmd;
1426
1427 ctrlCmd.timeout_ms = 5000;
1428 ctrlCmd.type = (uint16_t)type;
1429 ctrlCmd.length = length;
1430 // FIXME: this will be put in by the kernel
1431 ctrlCmd.resp_fd = mCameraControlFd;
1432 ctrlCmd.value = value;
1433
1434 LOGV("%s: fd %d, type %d, length %d", __FUNCTION__,
1435 mCameraControlFd, type, length);
1436 if (ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0 ||
1437 ctrlCmd.status != CAM_CTRL_SUCCESS) {
1438 LOGE("%s: error (%s): fd %d, type %d, length %d, status %d",
1439 __FUNCTION__, strerror(errno),
1440 mCameraControlFd, type, length, ctrlCmd.status);
1441 return false;
1442 }
1443 return true;
1444}
1445
1446void QualcommCameraHardware::jpeg_set_location()
1447{
1448 bool encode_location = true;
1449 camera_position_type pt;
1450
1451#define PARSE_LOCATION(what,type,fmt,desc) do { \
1452 pt.what = 0; \
1453 const char *what##_str = mParameters.get("gps-"#what); \
1454 LOGV("GPS PARM %s --> [%s]", "gps-"#what, what##_str); \
1455 if (what##_str) { \
1456 type what = 0; \
1457 if (sscanf(what##_str, fmt, &what) == 1) \
1458 pt.what = what; \
1459 else { \
1460 LOGE("GPS " #what " %s could not" \
1461 " be parsed as a " #desc, what##_str); \
1462 encode_location = false; \
1463 } \
1464 } \
1465 else { \
1466 LOGV("GPS " #what " not specified: " \
1467 "defaulting to zero in EXIF header."); \
1468 encode_location = false; \
1469 } \
1470 } while(0)
1471
1472 PARSE_LOCATION(timestamp, long, "%ld", "long");
1473 if (!pt.timestamp) pt.timestamp = time(NULL);
1474 PARSE_LOCATION(altitude, short, "%hd", "short");
1475 PARSE_LOCATION(latitude, double, "%lf", "double float");
1476 PARSE_LOCATION(longitude, double, "%lf", "double float");
1477
1478#undef PARSE_LOCATION
1479
1480 if (encode_location) {
1481 LOGD("setting image location ALT %d LAT %lf LON %lf",
1482 pt.altitude, pt.latitude, pt.longitude);
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001483/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001484 if (!LINK_jpeg_encoder_setLocation(&pt)) {
1485 LOGE("jpeg_set_location: LINK_jpeg_encoder_setLocation failed.");
1486 }
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001487*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001488 }
1489 else LOGV("not setting image location");
1490}
1491
1492void QualcommCameraHardware::runFrameThread(void *data)
1493{
1494 LOGV("runFrameThread E");
1495
1496 int cnt;
1497
1498#if DLOPEN_LIBMMCAMERA
1499 // We need to maintain a reference to libqcamera.so for the duration of the
1500 // frame thread, because we do not know when it will exit relative to the
1501 // lifetime of this object. We do not want to dlclose() libqcamera while
1502 // LINK_cam_frame is still running.
1503 void *libhandle = ::dlopen("liboemcamera.so", RTLD_NOW);
1504 LOGV("FRAME: loading libqcamera at %p", libhandle);
1505 if (!libhandle) {
1506 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
1507 }
1508 if (libhandle)
1509#endif
1510 {
1511 LINK_cam_frame(data);
1512 }
1513
Mohan Kandra284966d2010-01-05 13:39:15 -08001514 mCameraPreviewHeap.clear();
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08001515 if(strncmp(mDeviceName,"msm7630", 7)) {
Apurva Rajguru4ee824e2010-01-13 16:47:41 -08001516 //mPreviewHeap.clear();
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08001517 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001518#if DLOPEN_LIBMMCAMERA
1519 if (libhandle) {
1520 ::dlclose(libhandle);
1521 LOGV("FRAME: dlclose(libqcamera)");
1522 }
1523#endif
1524
1525 mFrameThreadWaitLock.lock();
1526 mFrameThreadRunning = false;
1527 mFrameThreadWait.signal();
1528 mFrameThreadWaitLock.unlock();
1529
1530 LOGV("runFrameThread X");
1531}
1532
1533void *frame_thread(void *user)
1534{
1535 LOGD("frame_thread E");
1536 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
1537 if (obj != 0) {
1538 obj->runFrameThread(user);
1539 }
1540 else LOGW("not starting frame thread: the object went away!");
1541 LOGD("frame_thread X");
1542 return NULL;
1543}
1544
1545bool QualcommCameraHardware::initPreview()
1546{
1547 // See comments in deinitPreview() for why we have to wait for the frame
1548 // thread here, and why we can't use pthread_join().
1549 int previewWidth, previewHeight;
1550 mParameters.getPreviewSize(&previewWidth, &previewHeight);
1551 LOGI("initPreview E: preview size=%dx%d", previewWidth, previewHeight);
1552 mFrameThreadWaitLock.lock();
1553 while (mFrameThreadRunning) {
1554 LOGV("initPreview: waiting for old frame thread to complete.");
1555 mFrameThreadWait.wait(mFrameThreadWaitLock);
1556 LOGV("initPreview: old frame thread completed.");
1557 }
1558 mFrameThreadWaitLock.unlock();
1559
1560 mSnapshotThreadWaitLock.lock();
1561 while (mSnapshotThreadRunning) {
1562 LOGV("initPreview: waiting for old snapshot thread to complete.");
1563 mSnapshotThreadWait.wait(mSnapshotThreadWaitLock);
1564 LOGV("initPreview: old snapshot thread completed.");
1565 }
1566 mSnapshotThreadWaitLock.unlock();
1567
1568 int cnt = 0;
1569 mPreviewFrameSize = previewWidth * previewHeight * 3/2;
Mohan Kandra284966d2010-01-05 13:39:15 -08001570 mCameraPreviewHeap = new PmemPool("/dev/pmem_adsp",
1571 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
1572 mCameraControlFd,
1573 MSM_PMEM_OUTPUT2,
1574 mPreviewFrameSize,
1575 kPreviewBufferCount,
1576 mPreviewFrameSize,
1577 "Camera preview");
1578
1579 if (!mCameraPreviewHeap->initialized()) {
1580 mCameraPreviewHeap.clear();
1581 LOGE("initPreview X: could not initialize Camera preview heap.");
1582 return false;
1583 }
Kiran Kumar H N595970b2010-01-12 10:41:09 -08001584 if( !strncmp(mDeviceName,"msm7630", 7) ) {
Apurva Rajguru4ee824e2010-01-13 16:47:41 -08001585 //mPreviewHeap = NULL;
Kiran Kumar H N595970b2010-01-12 10:41:09 -08001586 if(mPostViewHeap == NULL) {
1587 LOGV(" Allocating Postview heap ");
1588 /* mPostViewHeap should be declared only for 7630 target */
1589 mPostViewHeap =
1590 new PmemPool("/dev/pmem_adsp",
1591 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
1592 mCameraControlFd,
1593 MSM_PMEM_OUTPUT2,
1594 mPreviewFrameSize,
1595 1,
1596 mPreviewFrameSize,
1597 "postview");
Mohan Kandra284966d2010-01-05 13:39:15 -08001598
Kiran Kumar H N595970b2010-01-12 10:41:09 -08001599 if (!mPostViewHeap->initialized()) {
1600 mPostViewHeap.clear();
1601 LOGE(" Failed to initialize Postview Heap");
1602 return false;
1603 }
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08001604 }
Apurva Rajguru4ee824e2010-01-13 16:47:41 -08001605 } /*else {
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08001606 mPreviewHeap = new PmemPool("/dev/pmem_adsp",
1607 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
1608 mCameraControlFd,
1609 MSM_PMEM_OUTPUT2,
1610 mPreviewFrameSize,
1611 kPreviewBufferCount,
1612 mPreviewFrameSize,
1613 "preview");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001614
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08001615 if (!mPreviewHeap->initialized()) {
1616 mPreviewHeap.clear();
1617 LOGE("initPreview X: could not initialize preview heap.");
1618 return false;
1619 }
Apurva Rajguru4ee824e2010-01-13 16:47:41 -08001620 }*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001621 // mDimension will be filled with thumbnail_width, thumbnail_height,
1622 // orig_picture_dx, and orig_picture_dy after this function call. We need to
1623 // keep it for jpeg_encoder_encode.
1624 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
1625 sizeof(cam_ctrl_dimension_t), &mDimension);
1626
1627 if (ret) {
1628 for (cnt = 0; cnt < kPreviewBufferCount; cnt++) {
Mohan Kandra284966d2010-01-05 13:39:15 -08001629 frames[cnt].fd = mCameraPreviewHeap->mHeap->getHeapID();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001630 frames[cnt].buffer =
Mohan Kandra284966d2010-01-05 13:39:15 -08001631 (uint32_t)mCameraPreviewHeap->mHeap->base() + mCameraPreviewHeap->mAlignedBufferSize * cnt;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001632 frames[cnt].y_off = 0;
1633 frames[cnt].cbcr_off = previewWidth * previewHeight;
1634 frames[cnt].path = MSM_FRAME_ENC;
1635 }
1636
1637 mFrameThreadWaitLock.lock();
1638 pthread_attr_t attr;
1639 pthread_attr_init(&attr);
1640 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1641 mFrameThreadRunning = !pthread_create(&mFrameThread,
1642 &attr,
1643 frame_thread,
1644 &frames[kPreviewBufferCount-1]);
1645 ret = mFrameThreadRunning;
1646 mFrameThreadWaitLock.unlock();
1647 }
1648
1649 LOGV("initPreview X: %d", ret);
1650 return ret;
1651}
1652
1653void QualcommCameraHardware::deinitPreview(void)
1654{
1655 LOGI("deinitPreview E");
1656
1657 // When we call deinitPreview(), we signal to the frame thread that it
1658 // needs to exit, but we DO NOT WAIT for it to complete here. The problem
1659 // is that deinitPreview is sometimes called from the frame-thread's
1660 // callback, when the refcount on the Camera client reaches zero. If we
1661 // called pthread_join(), we would deadlock. So, we just call
1662 // LINK_camframe_terminate() in deinitPreview(), which makes sure that
1663 // after the preview callback returns, the camframe thread will exit. We
1664 // could call pthread_join() in initPreview() to join the last frame
1665 // thread. However, we would also have to call pthread_join() in release
1666 // as well, shortly before we destroy the object; this would cause the same
1667 // deadlock, since release(), like deinitPreview(), may also be called from
1668 // the frame-thread's callback. This we have to make the frame thread
1669 // detached, and use a separate mechanism to wait for it to complete.
1670
1671 if (LINK_camframe_terminate() < 0)
1672 LOGE("failed to stop the camframe thread: %s",
1673 strerror(errno));
1674 LOGI("deinitPreview X");
1675}
1676
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001677bool QualcommCameraHardware::initRawSnapshot()
1678{
1679 LOGV("initRawSnapshot E");
1680
1681 //get width and height from Dimension Object
1682 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
1683 sizeof(cam_ctrl_dimension_t), &mDimension);
1684
1685 if(!ret){
1686 LOGE("initRawSnapshot X: failed to set dimension");
1687 return false;
1688 }
1689 int rawSnapshotSize = mDimension.raw_picture_height *
1690 mDimension.raw_picture_width;
1691
1692 LOGV("raw_snapshot_buffer_size = %d, raw_picture_height = %d, "\
1693 "raw_picture_width = %d",
1694 rawSnapshotSize, mDimension.raw_picture_height,
1695 mDimension.raw_picture_width);
1696
1697 if (mRawSnapShotPmemHeap != NULL) {
1698 LOGV("initRawSnapshot: clearing old mRawSnapShotPmemHeap.");
1699 mRawSnapShotPmemHeap.clear();
1700 }
1701
1702 //Pmem based pool for Camera Driver
1703 mRawSnapShotPmemHeap = new PmemPool("/dev/pmem_adsp",
1704 MemoryHeapBase::READ_ONLY,
1705 mCameraControlFd,
1706 MSM_PMEM_RAW_MAINIMG,
1707 rawSnapshotSize,
1708 1,
1709 rawSnapshotSize,
1710 "raw pmem snapshot camera");
1711
1712 if (!mRawSnapShotPmemHeap->initialized()) {
1713 mRawSnapShotPmemHeap.clear();
1714 LOGE("initRawSnapshot X: error initializing mRawSnapshotHeap");
1715 return false;
1716 }
1717 LOGV("initRawSnapshot X");
1718 return true;
1719
1720}
1721
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001722bool QualcommCameraHardware::initRaw(bool initJpegHeap)
1723{
1724 int rawWidth, rawHeight;
Apurva Rajguru8d1773b2009-12-02 14:21:23 -08001725
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001726 mParameters.getPictureSize(&rawWidth, &rawHeight);
1727 LOGV("initRaw E: picture size=%dx%d", rawWidth, rawHeight);
1728
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08001729 int thumbnailBufferSize;
1730 //Thumbnail height should be smaller than Picture height
1731 if (rawHeight > thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height){
1732 mDimension.ui_thumbnail_width =
1733 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].width;
1734 mDimension.ui_thumbnail_height =
1735 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height;
1736 uint32_t pictureAspectRatio = (uint32_t)((rawWidth * Q12) / rawHeight);
1737 uint32_t i;
1738 for(i = 0; i < THUMBNAIL_SIZE_COUNT; i++ )
1739 {
1740 if(thumbnail_sizes[i].aspect_ratio == pictureAspectRatio)
1741 {
1742 mDimension.ui_thumbnail_width = thumbnail_sizes[i].width;
1743 mDimension.ui_thumbnail_height = thumbnail_sizes[i].height;
1744 break;
1745 }
1746 }
1747 }
1748 else{
1749 mDimension.ui_thumbnail_height = THUMBNAIL_SMALL_HEIGHT;
1750 mDimension.ui_thumbnail_width =
1751 (THUMBNAIL_SMALL_HEIGHT * rawWidth)/ rawHeight;
1752 }
1753
1754 LOGV("Thumbnail Size Width %d Height %d",
1755 mDimension.ui_thumbnail_width,
1756 mDimension.ui_thumbnail_height);
1757
1758 thumbnailBufferSize = mDimension.ui_thumbnail_width *
1759 mDimension.ui_thumbnail_height * 3 / 2;
1760
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001761 // mDimension will be filled with thumbnail_width, thumbnail_height,
1762 // orig_picture_dx, and orig_picture_dy after this function call. We need to
1763 // keep it for jpeg_encoder_encode.
1764 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
1765 sizeof(cam_ctrl_dimension_t), &mDimension);
1766 if(!ret) {
1767 LOGE("initRaw X: failed to set dimension");
1768 return false;
1769 }
1770
1771 if (mJpegHeap != NULL) {
1772 LOGV("initRaw: clearing old mJpegHeap.");
1773 mJpegHeap.clear();
1774 }
1775
1776 // Snapshot
1777 mRawSize = rawWidth * rawHeight * 3 / 2;
Apurva Rajguru8d1773b2009-12-02 14:21:23 -08001778
Mohan Kandra284966d2010-01-05 13:39:15 -08001779 if(!strcmp(mDeviceName,"msm7627_surf"))
Apurva Rajguru8d1773b2009-12-02 14:21:23 -08001780 mJpegMaxSize = CEILING16(rawWidth) * CEILING16(rawHeight) * 3 / 2;
1781 else
1782 mJpegMaxSize = rawWidth * rawHeight * 3 / 2;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001783
1784 LOGV("initRaw: initializing mRawHeap.");
1785 mRawHeap =
1786 new PmemPool("/dev/pmem_camera",
1787 MemoryHeapBase::READ_ONLY,
1788 mCameraControlFd,
1789 MSM_PMEM_MAINIMG,
1790 mJpegMaxSize,
1791 kRawBufferCount,
1792 mRawSize,
1793 "snapshot camera");
1794
1795 if (!mRawHeap->initialized()) {
1796 LOGE("initRaw X failed with pmem_camera, trying with pmem_adsp");
1797 mRawHeap =
1798 new PmemPool("/dev/pmem_adsp",
1799 MemoryHeapBase::READ_ONLY,
1800 mCameraControlFd,
1801 MSM_PMEM_MAINIMG,
1802 mJpegMaxSize,
1803 kRawBufferCount,
1804 mRawSize,
1805 "snapshot camera");
1806 if (!mRawHeap->initialized()) {
1807 mRawHeap.clear();
1808 LOGE("initRaw X: error initializing mRawHeap");
1809 return false;
1810 }
1811 }
1812
1813 LOGV("do_mmap snapshot pbuf = %p, pmem_fd = %d",
1814 (uint8_t *)mRawHeap->mHeap->base(), mRawHeap->mHeap->getHeapID());
1815
1816 // Jpeg
1817
1818 if (initJpegHeap) {
1819 LOGV("initRaw: initializing mJpegHeap.");
1820 mJpegHeap =
1821 new AshmemPool(mJpegMaxSize,
1822 kJpegBufferCount,
1823 0, // we do not know how big the picture will be
1824 "jpeg");
1825
1826 if (!mJpegHeap->initialized()) {
1827 mJpegHeap.clear();
1828 mRawHeap.clear();
1829 LOGE("initRaw X failed: error initializing mJpegHeap.");
1830 return false;
1831 }
1832
1833 // Thumbnails
1834
1835 mThumbnailHeap =
1836 new PmemPool("/dev/pmem_adsp",
1837 MemoryHeapBase::READ_ONLY,
1838 mCameraControlFd,
1839 MSM_PMEM_THUMBNAIL,
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08001840 thumbnailBufferSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001841 1,
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08001842 thumbnailBufferSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001843 "thumbnail");
1844
1845 if (!mThumbnailHeap->initialized()) {
1846 mThumbnailHeap.clear();
1847 mJpegHeap.clear();
1848 mRawHeap.clear();
1849 LOGE("initRaw X failed: error initializing mThumbnailHeap.");
1850 return false;
1851 }
1852 }
1853
1854 LOGV("initRaw X");
1855 return true;
1856}
1857
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001858
1859void QualcommCameraHardware::deinitRawSnapshot()
1860{
1861 LOGV("deinitRawSnapshot E");
1862 mRawSnapShotPmemHeap.clear();
1863 mRawSnapshotAshmemHeap.clear();
1864 LOGV("deinitRawSnapshot X");
1865}
1866
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001867void QualcommCameraHardware::deinitRaw()
1868{
1869 LOGV("deinitRaw E");
1870
1871 mThumbnailHeap.clear();
1872 mJpegHeap.clear();
1873 mRawHeap.clear();
1874 mDisplayHeap.clear();
1875
1876 LOGV("deinitRaw X");
1877}
1878
1879void QualcommCameraHardware::release()
1880{
1881 LOGD("release E");
1882 Mutex::Autolock l(&mLock);
1883
1884#if DLOPEN_LIBMMCAMERA
1885 if (libmmcamera == NULL) {
1886 LOGE("ERROR: multiple release!");
1887 return;
1888 }
1889#else
1890#warning "Cannot detect multiple release when not dlopen()ing libqcamera!"
1891#endif
1892
1893 int cnt, rc;
1894 struct msm_ctrl_cmd ctrlCmd;
1895
1896 if (mCameraRunning) {
1897 if(mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME)) {
1898 mRecordFrameLock.lock();
1899 mReleasedRecordingFrame = true;
1900 mRecordWait.signal();
1901 mRecordFrameLock.unlock();
1902 }
1903 stopPreviewInternal();
1904 }
1905
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08001906 if(!strncmp(mDeviceName,"msm7630", 7)) {
1907 mPostViewHeap.clear();
1908 mPostViewHeap = NULL;
1909 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001910 LINK_jpeg_encoder_join();
1911 deinitRaw();
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001912 deinitRawSnapshot();
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001913 {
1914 Mutex::Autolock l(&mCamframeTimeoutLock);
1915 if(!camframe_timeout_flag) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001916
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001917 ctrlCmd.timeout_ms = 5000;
1918 ctrlCmd.length = 0;
1919 ctrlCmd.type = (uint16_t)CAMERA_EXIT;
1920 ctrlCmd.resp_fd = mCameraControlFd; // FIXME: this will be put in by the kernel
1921 if (ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0)
1922 LOGE("ioctl CAMERA_EXIT fd %d error %s",
1923 mCameraControlFd, strerror(errno));
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001924
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001925 }
Kiran Kumar H Nac2f4952009-12-17 01:16:53 -08001926 LINK_release_cam_conf_thread();
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001927 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001928 close(mCameraControlFd);
1929 mCameraControlFd = -1;
Mohan Kandra284966d2010-01-05 13:39:15 -08001930 if(fb_fd >= 0) {
1931 close(fb_fd);
1932 fb_fd = -1;
1933 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001934#if DLOPEN_LIBMMCAMERA
1935 if (libmmcamera) {
1936 ::dlclose(libmmcamera);
1937 LOGV("dlclose(libqcamera)");
1938 libmmcamera = NULL;
1939 }
1940#endif
1941
1942 Mutex::Autolock lock(&singleton_lock);
1943 singleton_releasing = true;
1944
1945 LOGD("release X");
1946}
1947
1948QualcommCameraHardware::~QualcommCameraHardware()
1949{
1950 LOGD("~QualcommCameraHardware E");
1951 Mutex::Autolock lock(&singleton_lock);
1952 singleton.clear();
1953 singleton_releasing = false;
1954 singleton_wait.signal();
1955 LOGD("~QualcommCameraHardware X");
1956}
1957
1958sp<IMemoryHeap> QualcommCameraHardware::getRawHeap() const
1959{
1960 LOGV("getRawHeap");
1961 return mDisplayHeap != NULL ? mDisplayHeap->mHeap : NULL;
1962}
1963
1964sp<IMemoryHeap> QualcommCameraHardware::getPreviewHeap() const
1965{
1966 LOGV("getPreviewHeap");
Apurva Rajguru4ee824e2010-01-13 16:47:41 -08001967 return mCameraPreviewHeap != NULL ? mCameraPreviewHeap->mHeap : NULL;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001968}
1969
1970status_t QualcommCameraHardware::startPreviewInternal()
1971{
1972 if(mCameraRunning) {
1973 LOGV("startPreview X: preview already running.");
1974 return NO_ERROR;
1975 }
1976
1977 if (!mPreviewInitialized) {
1978 mPreviewInitialized = initPreview();
1979 if (!mPreviewInitialized) {
1980 LOGE("startPreview X initPreview failed. Not starting preview.");
1981 return UNKNOWN_ERROR;
1982 }
1983 }
1984
1985 mCameraRunning = native_start_preview(mCameraControlFd);
1986 if(!mCameraRunning) {
1987 deinitPreview();
1988 mPreviewInitialized = false;
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08001989 mOverlay = NULL;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001990 LOGE("startPreview X: native_start_preview failed!");
1991 return UNKNOWN_ERROR;
1992 }
1993
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001994 //Reset the Gps Information
1995 exif_table_numEntries = 0;
Mohan Kandra284966d2010-01-05 13:39:15 -08001996
1997 if(native_get_maxzoom(mCameraControlFd, (void *)&mMaxZoom) == true){
1998 LOGE("Maximum zoom value is %d", mMaxZoom);
1999 mParameters.set("zoom-supported", "true");
2000 } else {
2001 LOGE("Failed to get maximum zoom value...setting max zoom to zero");
2002 mParameters.set("zoom-supported", "false");
2003 mMaxZoom = 0;
2004 }
2005 mParameters.set("max-zoom",mMaxZoom);
2006
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002007 LOGV("startPreview X");
2008 return NO_ERROR;
2009}
2010
2011status_t QualcommCameraHardware::startPreview()
2012{
2013 LOGV("startPreview E");
2014 Mutex::Autolock l(&mLock);
2015 return startPreviewInternal();
2016}
2017
2018void QualcommCameraHardware::stopPreviewInternal()
2019{
2020 LOGV("stopPreviewInternal E: %d", mCameraRunning);
2021 if (mCameraRunning) {
2022 // Cancel auto focus.
2023 {
2024 if (mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS)) {
2025 cancelAutoFocusInternal();
2026 }
2027 }
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002028
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002029 Mutex::Autolock l(&mCamframeTimeoutLock);
2030 if(!camframe_timeout_flag) {
2031 mCameraRunning = !native_stop_preview(mCameraControlFd);
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002032 } else {
2033 /* This means that the camframetimeout was issued.
2034 * But we did not issue native_stop_preview(), so we
Kiran Kumar H Nac2f4952009-12-17 01:16:53 -08002035 * need to update mCameraRunning to indicate that
2036 * Camera is no longer running. */
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002037 mCameraRunning = 0;
Kiran Kumar H Nac2f4952009-12-17 01:16:53 -08002038 }
2039 if (!mCameraRunning && mPreviewInitialized) {
2040 deinitPreview();
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002041 mPreviewInitialized = false;
2042 }
Kiran Kumar H Nac2f4952009-12-17 01:16:53 -08002043 else LOGE("stopPreviewInternal: failed to stop preview");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002044 }
2045 LOGV("stopPreviewInternal X: %d", mCameraRunning);
2046}
2047
2048void QualcommCameraHardware::stopPreview()
2049{
2050 LOGV("stopPreview: E");
2051 Mutex::Autolock l(&mLock);
2052 {
2053 if (mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME))
2054 return;
2055 }
2056 stopPreviewInternal();
2057 LOGV("stopPreview: X");
2058}
2059
2060void QualcommCameraHardware::runAutoFocus()
2061{
2062 bool status = true;
2063 void *libhandle = NULL;
Srinivasan Kannan71229622009-12-04 12:05:58 -08002064 isp3a_af_mode_t afMode;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002065
2066 mAutoFocusThreadLock.lock();
2067 // Skip autofocus if focus mode is infinity.
2068 if (strcmp(mParameters.get(CameraParameters::KEY_FOCUS_MODE),
2069 CameraParameters::FOCUS_MODE_INFINITY) == 0) {
2070 goto done;
2071 }
2072
2073 mAutoFocusFd = open(MSM_CAMERA_CONTROL, O_RDWR);
2074 if (mAutoFocusFd < 0) {
2075 LOGE("autofocus: cannot open %s: %s",
2076 MSM_CAMERA_CONTROL,
2077 strerror(errno));
2078 mAutoFocusThreadRunning = false;
2079 mAutoFocusThreadLock.unlock();
2080 return;
2081 }
2082
2083#if DLOPEN_LIBMMCAMERA
2084 // We need to maintain a reference to libqcamera.so for the duration of the
2085 // AF thread, because we do not know when it will exit relative to the
2086 // lifetime of this object. We do not want to dlclose() libqcamera while
2087 // LINK_cam_frame is still running.
2088 libhandle = ::dlopen("liboemcamera.so", RTLD_NOW);
2089 LOGV("AF: loading libqcamera at %p", libhandle);
2090 if (!libhandle) {
2091 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
2092 close(mAutoFocusFd);
2093 mAutoFocusFd = -1;
2094 mAutoFocusThreadRunning = false;
2095 mAutoFocusThreadLock.unlock();
2096 return;
2097 }
2098#endif
2099
Srinivasan Kannan71229622009-12-04 12:05:58 -08002100 afMode = (isp3a_af_mode_t)attr_lookup(focus_modes,
2101 sizeof(focus_modes) / sizeof(str_map),
2102 mParameters.get(CameraParameters::KEY_FOCUS_MODE));
2103
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002104 /* This will block until either AF completes or is cancelled. */
Srinivasan Kannan71229622009-12-04 12:05:58 -08002105 LOGV("af start (fd %d mode %d)", mAutoFocusFd, afMode);
2106 status = native_set_afmode(mAutoFocusFd, afMode);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002107 LOGV("af done: %d", (int)status);
2108 close(mAutoFocusFd);
2109 mAutoFocusFd = -1;
2110
2111done:
2112 mAutoFocusThreadRunning = false;
2113 mAutoFocusThreadLock.unlock();
2114
2115 mCallbackLock.lock();
2116 bool autoFocusEnabled = mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS);
2117 notify_callback cb = mNotifyCallback;
2118 void *data = mCallbackCookie;
2119 mCallbackLock.unlock();
2120 if (autoFocusEnabled)
2121 cb(CAMERA_MSG_FOCUS, status, 0, data);
2122
2123#if DLOPEN_LIBMMCAMERA
2124 if (libhandle) {
2125 ::dlclose(libhandle);
2126 LOGV("AF: dlclose(libqcamera)");
2127 }
2128#endif
2129}
2130
2131status_t QualcommCameraHardware::cancelAutoFocusInternal()
2132{
2133 LOGV("cancelAutoFocusInternal E");
2134
Srinivasan Kannan71229622009-12-04 12:05:58 -08002135 if(!sensorType->hasAutoFocusSupport){
2136 LOGV("cancelAutoFocusInternal X");
2137 return NO_ERROR;
2138 }
2139
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002140#if 0
2141 if (mAutoFocusFd < 0) {
2142 LOGV("cancelAutoFocusInternal X: not in progress");
2143 return NO_ERROR;
2144 }
2145#endif
2146
2147 status_t rc = native_cancel_afmode(mCameraControlFd, mAutoFocusFd) ?
2148 NO_ERROR :
2149 UNKNOWN_ERROR;
2150
2151 LOGV("cancelAutoFocusInternal X: %d", rc);
2152 return rc;
2153}
2154
2155void *auto_focus_thread(void *user)
2156{
2157 LOGV("auto_focus_thread E");
2158 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
2159 if (obj != 0) {
2160 obj->runAutoFocus();
2161 }
2162 else LOGW("not starting autofocus: the object went away!");
2163 LOGV("auto_focus_thread X");
2164 return NULL;
2165}
2166
2167status_t QualcommCameraHardware::autoFocus()
2168{
2169 LOGV("autoFocus E");
2170 Mutex::Autolock l(&mLock);
2171
Srinivasan Kannan71229622009-12-04 12:05:58 -08002172 if(!sensorType->hasAutoFocusSupport){
Srinivasan Kannandf085222009-12-09 18:31:00 -08002173 bool status = false;
2174 mCallbackLock.lock();
2175 bool autoFocusEnabled = mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS);
2176 notify_callback cb = mNotifyCallback;
2177 void *data = mCallbackCookie;
2178 mCallbackLock.unlock();
2179 if (autoFocusEnabled)
2180 cb(CAMERA_MSG_FOCUS, status, 0, data);
Srinivasan Kannan71229622009-12-04 12:05:58 -08002181 LOGV("autoFocus X");
2182 return NO_ERROR;
2183 }
2184
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002185 if (mCameraControlFd < 0) {
2186 LOGE("not starting autofocus: main control fd %d", mCameraControlFd);
2187 return UNKNOWN_ERROR;
2188 }
2189
2190 {
2191 mAutoFocusThreadLock.lock();
2192 if (!mAutoFocusThreadRunning) {
2193 // Create a detached thread here so that we don't have to wait
2194 // for it when we cancel AF.
2195 pthread_t thr;
2196 pthread_attr_t attr;
2197 pthread_attr_init(&attr);
2198 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2199 mAutoFocusThreadRunning =
2200 !pthread_create(&thr, &attr,
2201 auto_focus_thread, NULL);
2202 if (!mAutoFocusThreadRunning) {
2203 LOGE("failed to start autofocus thread");
2204 mAutoFocusThreadLock.unlock();
2205 return UNKNOWN_ERROR;
2206 }
2207 }
2208 mAutoFocusThreadLock.unlock();
2209 }
2210
2211 LOGV("autoFocus X");
2212 return NO_ERROR;
2213}
2214
2215status_t QualcommCameraHardware::cancelAutoFocus()
2216{
2217 LOGV("cancelAutoFocus E");
2218 Mutex::Autolock l(&mLock);
2219
2220 int rc = NO_ERROR;
2221 if (mCameraRunning && mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS)) {
2222 rc = cancelAutoFocusInternal();
2223 }
2224
2225 LOGV("cancelAutoFocus X");
2226 return rc;
2227}
2228
2229void QualcommCameraHardware::runSnapshotThread(void *data)
2230{
2231 LOGV("runSnapshotThread E");
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002232 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
2233 if (native_start_snapshot(mCameraControlFd))
2234 receiveRawPicture();
2235 else
2236 LOGE("main: native_start_snapshot failed!");
2237 } else if(mSnapshotFormat == PICTURE_FORMAT_RAW){
2238 if(native_start_raw_snapshot(mCameraControlFd)){
2239 receiveRawSnapshot();
2240 } else {
2241 LOGE("main: native_start_raw_snapshot failed!");
2242 }
2243 }
2244
2245 mSnapshotFormat = 0;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002246
2247 mSnapshotThreadWaitLock.lock();
2248 mSnapshotThreadRunning = false;
2249 mSnapshotThreadWait.signal();
2250 mSnapshotThreadWaitLock.unlock();
2251
2252 LOGV("runSnapshotThread X");
2253}
2254
2255void *snapshot_thread(void *user)
2256{
2257 LOGD("snapshot_thread E");
2258 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
2259 if (obj != 0) {
2260 obj->runSnapshotThread(user);
2261 }
2262 else LOGW("not starting snapshot thread: the object went away!");
2263 LOGD("snapshot_thread X");
2264 return NULL;
2265}
2266
2267status_t QualcommCameraHardware::takePicture()
2268{
2269 LOGV("takePicture(%d)", mMsgEnabled);
2270 Mutex::Autolock l(&mLock);
2271
2272 // Wait for old snapshot thread to complete.
2273 mSnapshotThreadWaitLock.lock();
2274 while (mSnapshotThreadRunning) {
2275 LOGV("takePicture: waiting for old snapshot thread to complete.");
2276 mSnapshotThreadWait.wait(mSnapshotThreadWaitLock);
2277 LOGV("takePicture: old snapshot thread completed.");
2278 }
2279
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002280 if(!strcmp(mDeviceName,"msm7630_surf")) {
2281 /* Store the last frame queued for preview. This
2282 * shall be used as postview */
2283 storePreviewFrameForPostview();
2284 }
2285
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002286 //mSnapshotFormat is protected by mSnapshotThreadWaitLock
2287 if(mParameters.getPictureFormat() != 0 &&
2288 !strcmp(mParameters.getPictureFormat(),
2289 CameraParameters::PIXEL_FORMAT_RAW))
2290 mSnapshotFormat = PICTURE_FORMAT_RAW;
2291 else
2292 mSnapshotFormat = PICTURE_FORMAT_JPEG;
2293
2294 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
2295 if(!native_prepare_snapshot(mCameraControlFd)) {
2296 mSnapshotThreadWaitLock.unlock();
2297 return UNKNOWN_ERROR;
2298 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002299 }
2300
2301 stopPreviewInternal();
2302
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002303 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
2304 if (!initRaw(mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE))) {
2305 LOGE("initRaw failed. Not taking picture.");
2306 mSnapshotThreadWaitLock.unlock();
2307 return UNKNOWN_ERROR;
2308 }
2309 } else if(mSnapshotFormat == PICTURE_FORMAT_RAW ){
2310 if(!initRawSnapshot()){
2311 LOGE("initRawSnapshot failed. Not taking picture.");
2312 mSnapshotThreadWaitLock.unlock();
2313 return UNKNOWN_ERROR;
2314 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002315 }
2316
2317 mShutterLock.lock();
2318 mShutterPending = true;
2319 mShutterLock.unlock();
2320
2321 pthread_attr_t attr;
2322 pthread_attr_init(&attr);
2323 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2324 mSnapshotThreadRunning = !pthread_create(&mSnapshotThread,
2325 &attr,
2326 snapshot_thread,
2327 NULL);
2328 mSnapshotThreadWaitLock.unlock();
2329
2330 LOGV("takePicture: X");
2331 return mSnapshotThreadRunning ? NO_ERROR : UNKNOWN_ERROR;
2332}
2333
2334status_t QualcommCameraHardware::cancelPicture()
2335{
2336 status_t rc;
2337 LOGV("cancelPicture: E");
2338 rc = native_stop_snapshot(mCameraControlFd) ? NO_ERROR : UNKNOWN_ERROR;
2339 LOGV("cancelPicture: X: %d", rc);
2340 return rc;
2341}
2342
2343status_t QualcommCameraHardware::setParameters(const CameraParameters& params)
2344{
2345 LOGV("setParameters: E params = %p", &params);
2346
2347 Mutex::Autolock l(&mLock);
2348 status_t rc, final_rc = NO_ERROR;
2349
2350 if ((rc = setPreviewSize(params))) final_rc = rc;
2351 if ((rc = setPictureSize(params))) final_rc = rc;
2352 if ((rc = setJpegQuality(params))) final_rc = rc;
2353 if ((rc = setAntibanding(params))) final_rc = rc;
2354 if ((rc = setEffect(params))) final_rc = rc;
Apurva Rajguru55562b02009-12-03 12:25:35 -08002355 if ((rc = setAutoExposure(params))) final_rc = rc;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002356 if ((rc = setWhiteBalance(params))) final_rc = rc;
2357 if ((rc = setFlash(params))) final_rc = rc;
2358 if ((rc = setGpsLocation(params))) final_rc = rc;
2359 if ((rc = setRotation(params))) final_rc = rc;
2360 if ((rc = setZoom(params))) final_rc = rc;
2361 if ((rc = setFocusMode(params))) final_rc = rc;
2362 if ((rc = setOrientation(params))) final_rc = rc;
Nishant Panditc8c1ee72009-12-03 16:24:02 +05302363 if ((rc = setBrightness(params))) final_rc = rc;
2364 if ((rc = setLensshadeValue(params))) final_rc = rc;
2365 if ((rc = setISOValue(params))) final_rc = rc;
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002366 if ((rc = setPictureFormat(params))) final_rc = rc;
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08002367 if ((rc = setSharpness(params))) final_rc = rc;
2368 if ((rc = setContrast(params))) final_rc = rc;
2369 if ((rc = setSaturation(params))) final_rc = rc;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002370
2371 LOGV("setParameters: X");
2372 return final_rc;
2373}
2374
2375CameraParameters QualcommCameraHardware::getParameters() const
2376{
2377 LOGV("getParameters: EX");
2378 return mParameters;
2379}
2380
2381status_t QualcommCameraHardware::sendCommand(int32_t command, int32_t arg1,
2382 int32_t arg2)
2383{
2384 LOGV("sendCommand: EX");
2385 return BAD_VALUE;
2386}
2387
2388extern "C" sp<CameraHardwareInterface> openCameraHardware()
2389{
2390 LOGV("openCameraHardware: call createInstance");
2391 return QualcommCameraHardware::createInstance();
2392}
2393
2394wp<QualcommCameraHardware> QualcommCameraHardware::singleton;
2395
2396// If the hardware already exists, return a strong pointer to the current
2397// object. If not, create a new hardware object, put it in the singleton,
2398// and return it.
2399sp<CameraHardwareInterface> QualcommCameraHardware::createInstance()
2400{
2401 LOGD("createInstance: E");
2402
2403 Mutex::Autolock lock(&singleton_lock);
2404
2405 // Wait until the previous release is done.
2406 while (singleton_releasing) {
2407 LOGD("Wait for previous release.");
2408 singleton_wait.wait(singleton_lock);
2409 }
2410
2411 if (singleton != 0) {
2412 sp<CameraHardwareInterface> hardware = singleton.promote();
2413 if (hardware != 0) {
2414 LOGD("createInstance: X return existing hardware=%p", &(*hardware));
2415 return hardware;
2416 }
2417 }
2418
2419 {
2420 struct stat st;
2421 int rc = stat("/dev/oncrpc", &st);
2422 if (rc < 0) {
2423 LOGD("createInstance: X failed to create hardware: %s", strerror(errno));
2424 return NULL;
2425 }
2426 }
2427
2428 QualcommCameraHardware *cam = new QualcommCameraHardware();
2429 sp<QualcommCameraHardware> hardware(cam);
2430 singleton = hardware;
2431
2432 if (!cam->startCamera()) {
2433 LOGE("%s: startCamera failed!", __FUNCTION__);
2434 return NULL;
2435 }
2436
2437 cam->initDefaultParameters();
2438 LOGD("createInstance: X created hardware=%p", &(*hardware));
2439 return hardware;
2440}
2441
2442// For internal use only, hence the strong pointer to the derived type.
2443sp<QualcommCameraHardware> QualcommCameraHardware::getInstance()
2444{
2445 sp<CameraHardwareInterface> hardware = singleton.promote();
2446 if (hardware != 0) {
2447 // LOGV("getInstance: X old instance of hardware");
2448 return sp<QualcommCameraHardware>(static_cast<QualcommCameraHardware*>(hardware.get()));
2449 } else {
2450 LOGV("getInstance: X new instance of hardware");
2451 return sp<QualcommCameraHardware>();
2452 }
2453}
2454
Mohan Kandra284966d2010-01-05 13:39:15 -08002455bool QualcommCameraHardware::native_zoom_image(int srcFd, int dstFd, int offSet, common_crop_t *crop)
2456{
2457 int result = 0;
2458 struct mdp_blit_req *e;
2459 struct timeval td1, td2;
2460
2461 int previewWidth, previewHeight;
2462 mParameters.getPreviewSize(&previewWidth, &previewHeight);
2463
2464 /* Initialize yuv structure */
2465 zoomImage.list.count = 1;
2466
2467 e = &zoomImage.list.req[0];
2468
2469 e->src.width = previewWidth;
2470 e->src.height = previewHeight;
2471 e->src.format = MDP_Y_CBCR_H2V2;
2472 e->src.offset = offSet;
2473 e->src.memory_id = srcFd;
2474
2475 e->dst.width = previewWidth;
2476 e->dst.height = previewHeight;
2477 e->dst.format = MDP_Y_CBCR_H2V2;
2478 e->dst.offset = offSet;
2479 e->dst.memory_id = dstFd;
2480
2481 LOGV(" Source FD = %d, Destination FD = %d offSet = %d",srcFd, dstFd, offSet);
2482
2483 e->transp_mask = 0xffffffff;
2484 e->flags = 0;
2485 e->alpha = 0xff;
2486 if (crop->in2_w != 0 || crop->in2_h != 0) {
2487 e->src_rect.x = (crop->out2_w - crop->in2_w + 1) / 2 - 1;
2488 e->src_rect.y = (crop->out2_h - crop->in2_h + 1) / 2 - 1;
2489 e->src_rect.w = crop->in2_w;
2490 e->src_rect.h = crop->in2_h;
2491 } else {
2492 e->src_rect.x = 0;
2493 e->src_rect.y = 0;
2494 e->src_rect.w = previewWidth;
2495 e->src_rect.h = previewHeight;
2496 }
2497 LOGV(" native_zoom : SRC_RECT : x,y = %d,%d \t w,h = %d, %d",
2498 e->src_rect.x, e->src_rect.y, e->src_rect.w, e->src_rect.h);
2499
2500 e->dst_rect.x = 0;
2501 e->dst_rect.y = 0;
2502 e->dst_rect.w = previewWidth;
2503 e->dst_rect.h = previewHeight;
2504
2505 result = ioctl(fb_fd, MSMFB_BLIT, &zoomImage.list);
2506 if (result < 0) {
2507 LOGE("MSM_FBIOBLT failed! line=%d\n", __LINE__);
2508 return FALSE;
2509 }
2510 return TRUE;
2511}
2512
Mohan Kandra740cfce2010-01-07 12:58:24 -08002513void QualcommCameraHardware::debugShowFPS() const
2514{
2515 static int mFrameCount;
2516 static int mLastFrameCount = 0;
2517 static nsecs_t mLastFpsTime = 0;
2518 static float mFps = 0;
2519 mFrameCount++;
2520 nsecs_t now = systemTime();
2521 nsecs_t diff = now - mLastFpsTime;
2522 if (diff > ms2ns(250)) {
2523 mFps = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
2524 LOGI("Frames Per Second: %.4f", mFps);
2525 mLastFpsTime = now;
2526 mLastFrameCount = mFrameCount;
2527 }
2528}
2529
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002530void QualcommCameraHardware::receivePreviewFrame(struct msm_frame *frame)
2531{
2532// LOGV("receivePreviewFrame E");
2533
2534 if (!mCameraRunning) {
2535 LOGE("ignoring preview callback--camera has been stopped");
2536 return;
2537 }
2538
Mohan Kandra740cfce2010-01-07 12:58:24 -08002539 if (UNLIKELY(mDebugFps)) {
2540 debugShowFPS();
2541 }
2542
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002543 mCallbackLock.lock();
2544 int msgEnabled = mMsgEnabled;
2545 data_callback pcb = mDataCallback;
2546 void *pdata = mCallbackCookie;
2547 data_callback_timestamp rcb = mDataCallbackTimestamp;
2548 void *rdata = mCallbackCookie;
2549 mCallbackLock.unlock();
2550
2551 // Find the offset within the heap of the current buffer.
Mohan Kandra284966d2010-01-05 13:39:15 -08002552 ssize_t offset_addr =
2553 (ssize_t)frame->buffer - (ssize_t)mCameraPreviewHeap->mHeap->base();
2554 ssize_t offset = offset_addr / mCameraPreviewHeap->mAlignedBufferSize;
2555
2556 common_crop_t *crop = (common_crop_t *) (frame->cropinfo);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002557
2558 mInPreviewCallback = true;
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002559 if(mUseOverlay) {
2560 if(mOverlay != NULL) {
2561 mOverlayLock.lock();
2562 mOverlay->setFd(mCameraPreviewHeap->mHeap->getHeapID());
2563 if (crop->in2_w != 0 || crop->in2_h != 0) {
2564 zoomCropInfo.x = (crop->out2_w - crop->in2_w + 1) / 2 - 1;
2565 zoomCropInfo.y = (crop->out2_h - crop->in2_h + 1) / 2 - 1;
2566 zoomCropInfo.w = crop->in2_w;
2567 zoomCropInfo.h = crop->in2_h;
2568 mOverlay->setCrop(zoomCropInfo.x, zoomCropInfo.y,
2569 zoomCropInfo.w, zoomCropInfo.h);
2570 }
2571 mOverlay->queueBuffer((void *)offset_addr);
2572 mLastQueuedFrame = (void *)frame->buffer;
2573 mOverlayLock.unlock();
2574 }
Mohan Kandra284966d2010-01-05 13:39:15 -08002575 if (pcb != NULL && (msgEnabled & CAMERA_MSG_PREVIEW_FRAME))
2576 pcb(CAMERA_MSG_PREVIEW_FRAME, mCameraPreviewHeap->mBuffers[offset],
2577 pdata);
2578 } else {
Apurva Rajguru4ee824e2010-01-13 16:47:41 -08002579 /*if( !native_zoom_image(mCameraPreviewHeap->mHeap->getHeapID(),
Mohan Kandra284966d2010-01-05 13:39:15 -08002580 mPreviewHeap->mHeap->getHeapID(),
2581 offset_addr, crop)) {
2582 LOGE(" Error while doing MDP zoom ");
Apurva Rajguru4ee824e2010-01-13 16:47:41 -08002583 }*/
Mohan Kandra284966d2010-01-05 13:39:15 -08002584 if (pcb != NULL && (msgEnabled & CAMERA_MSG_PREVIEW_FRAME))
Apurva Rajguru4ee824e2010-01-13 16:47:41 -08002585 pcb(CAMERA_MSG_PREVIEW_FRAME, mCameraPreviewHeap->mBuffers[offset],
Mohan Kandra284966d2010-01-05 13:39:15 -08002586 pdata);
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08002587 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002588 if(rcb != NULL && (msgEnabled & CAMERA_MSG_VIDEO_FRAME)) {
Mohan Kandra284966d2010-01-05 13:39:15 -08002589 rcb(systemTime(), CAMERA_MSG_VIDEO_FRAME, mCameraPreviewHeap->mBuffers[offset], rdata);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002590 Mutex::Autolock rLock(&mRecordFrameLock);
2591 if (mReleasedRecordingFrame != true) {
2592 LOGV("block waiting for frame release");
2593 mRecordWait.wait(mRecordFrameLock);
2594 LOGV("frame released, continuing");
2595 }
2596 mReleasedRecordingFrame = false;
2597 }
2598 mInPreviewCallback = false;
2599
2600// LOGV("receivePreviewFrame X");
2601}
2602
2603status_t QualcommCameraHardware::startRecording()
2604{
2605 LOGV("startRecording E");
2606 Mutex::Autolock l(&mLock);
2607 mReleasedRecordingFrame = false;
2608 return startPreviewInternal();
2609}
2610
2611void QualcommCameraHardware::stopRecording()
2612{
2613 LOGV("stopRecording: E");
2614 Mutex::Autolock l(&mLock);
2615 {
2616 mRecordFrameLock.lock();
2617 mReleasedRecordingFrame = true;
2618 mRecordWait.signal();
2619 mRecordFrameLock.unlock();
2620
2621 if(mDataCallback && (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)) {
2622 LOGV("stopRecording: X, preview still in progress");
2623 return;
2624 }
2625 }
2626
2627 stopPreviewInternal();
2628 LOGV("stopRecording: X");
2629}
2630
2631void QualcommCameraHardware::releaseRecordingFrame(
2632 const sp<IMemory>& mem __attribute__((unused)))
2633{
2634 LOGV("releaseRecordingFrame E");
2635 Mutex::Autolock rLock(&mRecordFrameLock);
2636 mReleasedRecordingFrame = true;
2637 mRecordWait.signal();
2638 LOGV("releaseRecordingFrame X");
2639}
2640
2641bool QualcommCameraHardware::recordingEnabled()
2642{
2643 return mCameraRunning && mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME);
2644}
2645
2646void QualcommCameraHardware::notifyShutter(common_crop_t *crop)
2647{
2648 mShutterLock.lock();
2649 image_rect_type size;
2650
2651 if (mShutterPending && mNotifyCallback && (mMsgEnabled & CAMERA_MSG_SHUTTER)) {
2652 LOGV("out2_w=%d, out2_h=%d, in2_w=%d, in2_h=%d",
2653 crop->out2_w, crop->out2_h, crop->in2_w, crop->in2_h);
2654 LOGV("out1_w=%d, out1_h=%d, in1_w=%d, in1_h=%d",
2655 crop->out1_w, crop->out1_h, crop->in1_w, crop->in1_h);
2656
2657 // To workaround a bug in MDP which happens if either
2658 // dimension > 2048, we display the thumbnail instead.
2659 mDisplayHeap = mRawHeap;
2660 if (crop->in1_w == 0 || crop->in1_h == 0) {
2661 // Full size
2662 size.width = mDimension.picture_width;
2663 size.height = mDimension.picture_height;
2664 if (size.width > 2048 || size.height > 2048) {
2665 size.width = mDimension.ui_thumbnail_width;
2666 size.height = mDimension.ui_thumbnail_height;
2667 mDisplayHeap = mThumbnailHeap;
2668 }
2669 } else {
2670 // Cropped
2671 size.width = crop->in2_w & ~1;
2672 size.height = crop->in2_h & ~1;
2673 if (size.width > 2048 || size.height > 2048) {
2674 size.width = crop->in1_w & ~1;
2675 size.height = crop->in1_h & ~1;
2676 mDisplayHeap = mThumbnailHeap;
2677 }
2678 }
2679
2680 mNotifyCallback(CAMERA_MSG_SHUTTER, (int32_t)&size, 0,
2681 mCallbackCookie);
2682 mShutterPending = false;
2683 }
2684 mShutterLock.unlock();
2685}
2686
2687static void receive_shutter_callback(common_crop_t *crop)
2688{
2689 LOGV("receive_shutter_callback: E");
2690 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
2691 if (obj != 0) {
2692 obj->notifyShutter(crop);
2693 }
2694 LOGV("receive_shutter_callback: X");
2695}
2696
2697// Crop the picture in place.
2698static void crop_yuv420(uint32_t width, uint32_t height,
2699 uint32_t cropped_width, uint32_t cropped_height,
2700 uint8_t *image)
2701{
2702 uint32_t i, x, y;
2703 uint8_t* chroma_src, *chroma_dst;
2704
2705 // Calculate the start position of the cropped area.
2706 x = (width - cropped_width) / 2;
2707 y = (height - cropped_height) / 2;
2708 x &= ~1;
2709 y &= ~1;
2710
2711 // Copy luma component.
2712 for(i = 0; i < cropped_height; i++)
2713 memcpy(image + i * cropped_width,
2714 image + width * (y + i) + x,
2715 cropped_width);
2716
2717 chroma_src = image + width * height;
2718 chroma_dst = image + cropped_width * cropped_height;
2719
2720 // Copy chroma components.
2721 cropped_height /= 2;
2722 y /= 2;
2723 for(i = 0; i < cropped_height; i++)
2724 memcpy(chroma_dst + i * cropped_width,
2725 chroma_src + width * (y + i) + x,
2726 cropped_width);
2727}
2728
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002729
2730void QualcommCameraHardware::receiveRawSnapshot(){
2731 LOGV("receiveRawSnapshot E");
2732
2733 Mutex::Autolock cbLock(&mCallbackLock);
2734
2735 notifyShutter(&mCrop);
2736
2737 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
2738
2739 if(native_get_picture(mCameraControlFd, &mCrop) == false) {
2740 LOGE("receiveRawSnapshot X: native_get_picture failed!");
2741 return;
2742 }
2743
2744 //Create a Ashmem heap to copy data from PMem heap for application layer
2745 if(mRawSnapshotAshmemHeap != NULL){
2746 LOGV("receiveRawSnapshot: clearing old mRawSnapShotAshmemHeap.");
2747 mRawSnapshotAshmemHeap.clear();
2748 }
2749 mRawSnapshotAshmemHeap = new AshmemPool(
2750 mRawSnapShotPmemHeap->mBufferSize,
2751 mRawSnapShotPmemHeap->mNumBuffers,
2752 mRawSnapShotPmemHeap->mFrameSize,
2753 "raw ashmem snapshot camera"
2754 );
2755
2756 if(!mRawSnapshotAshmemHeap->initialized()){
2757 LOGE("receiveRawSnapshot X: error initializing mRawSnapshotHeap");
2758 deinitRawSnapshot();
2759 return;
2760 }
2761
2762 memcpy(mRawSnapshotAshmemHeap->mHeap->base(),
2763 mRawSnapShotPmemHeap->mHeap->base(),
2764 mRawSnapShotPmemHeap->mHeap->getSize());
2765
2766 mDataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mRawSnapshotAshmemHeap->mBuffers[0],
2767 mCallbackCookie);
2768
2769 }
2770
2771 //cleanup
2772 deinitRawSnapshot();
2773
2774 LOGV("receiveRawSnapshot X");
2775}
2776
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002777void QualcommCameraHardware::receiveRawPicture()
2778{
2779 LOGV("receiveRawPicture: E");
2780
2781 Mutex::Autolock cbLock(&mCallbackLock);
2782 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_RAW_IMAGE)) {
2783 if(native_get_picture(mCameraControlFd, &mCrop) == false) {
2784 LOGE("getPicture failed!");
2785 return;
2786 }
2787 mCrop.in1_w &= ~1;
2788 mCrop.in1_h &= ~1;
2789 mCrop.in2_w &= ~1;
2790 mCrop.in2_h &= ~1;
2791
2792 // By the time native_get_picture returns, picture is taken. Call
2793 // shutter callback if cam config thread has not done that.
2794 notifyShutter(&mCrop);
2795
2796 // Crop the image if zoomed.
2797 if (mCrop.in2_w != 0 && mCrop.in2_h != 0) {
2798 crop_yuv420(mCrop.out2_w, mCrop.out2_h, mCrop.in2_w, mCrop.in2_h,
2799 (uint8_t *)mRawHeap->mHeap->base());
2800 crop_yuv420(mCrop.out1_w, mCrop.out1_h, mCrop.in1_w, mCrop.in1_h,
2801 (uint8_t *)mThumbnailHeap->mHeap->base());
2802 // We do not need jpeg encoder to upscale the image. Set the new
2803 // dimension for encoder.
2804 mDimension.orig_picture_dx = mCrop.in2_w;
2805 mDimension.orig_picture_dy = mCrop.in2_h;
2806 mDimension.thumbnail_width = mCrop.in1_w;
2807 mDimension.thumbnail_height = mCrop.in1_h;
2808 memset(&mCrop, 0, sizeof(mCrop));
2809 }
2810
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002811 if( mUseOverlay && (mOverlay != NULL) ) {
2812 mOverlay->setFd(mPostViewHeap->mHeap->getHeapID());
2813 if( zoomCropInfo.w !=0 && zoomCropInfo.h !=0) {
2814 LOGD(" zoomCropInfo non-zero, setting crop ");
2815 mOverlay->setCrop(zoomCropInfo.x, zoomCropInfo.y,
2816 zoomCropInfo.w, zoomCropInfo.h);
2817 }
2818 LOGD(" Queueing Postview for display ");
2819 mOverlay->queueBuffer((void *)0);
2820 }
2821
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002822 mDataCallback(CAMERA_MSG_RAW_IMAGE, mDisplayHeap->mBuffers[0],
2823 mCallbackCookie);
2824 }
2825 else LOGV("Raw-picture callback was canceled--skipping.");
2826
2827 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
2828 mJpegSize = 0;
2829 if (LINK_jpeg_encoder_init()) {
2830 if(native_jpeg_encode()) {
2831 LOGV("receiveRawPicture: X (success)");
2832 return;
2833 }
2834 LOGE("jpeg encoding failed");
2835 }
2836 else LOGE("receiveRawPicture X: jpeg_encoder_init failed.");
2837 }
2838 else LOGV("JPEG callback is NULL, not encoding image.");
2839 deinitRaw();
2840 LOGV("receiveRawPicture: X");
2841}
2842
2843void QualcommCameraHardware::receiveJpegPictureFragment(
2844 uint8_t *buff_ptr, uint32_t buff_size)
2845{
2846 uint32_t remaining = mJpegHeap->mHeap->virtualSize();
2847 remaining -= mJpegSize;
2848 uint8_t *base = (uint8_t *)mJpegHeap->mHeap->base();
2849
2850 LOGV("receiveJpegPictureFragment size %d", buff_size);
2851 if (buff_size > remaining) {
2852 LOGE("receiveJpegPictureFragment: size %d exceeds what "
2853 "remains in JPEG heap (%d), truncating",
2854 buff_size,
2855 remaining);
2856 buff_size = remaining;
2857 }
2858 memcpy(base + mJpegSize, buff_ptr, buff_size);
2859 mJpegSize += buff_size;
2860}
2861
2862void QualcommCameraHardware::receiveJpegPicture(void)
2863{
2864 LOGV("receiveJpegPicture: E image (%d uint8_ts out of %d)",
2865 mJpegSize, mJpegHeap->mBufferSize);
2866 Mutex::Autolock cbLock(&mCallbackLock);
2867
2868 int index = 0, rc;
2869
2870 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
2871 // The reason we do not allocate into mJpegHeap->mBuffers[offset] is
2872 // that the JPEG image's size will probably change from one snapshot
2873 // to the next, so we cannot reuse the MemoryBase object.
2874 sp<MemoryBase> buffer = new
2875 MemoryBase(mJpegHeap->mHeap,
2876 index * mJpegHeap->mBufferSize +
2877 0,
2878 mJpegSize);
2879 mDataCallback(CAMERA_MSG_COMPRESSED_IMAGE, buffer, mCallbackCookie);
2880 buffer = NULL;
2881 }
2882 else LOGV("JPEG callback was cancelled--not delivering image.");
2883
2884 LINK_jpeg_encoder_join();
2885 deinitRaw();
2886
2887 LOGV("receiveJpegPicture: X callback done.");
2888}
2889
2890bool QualcommCameraHardware::previewEnabled()
2891{
2892 return mCameraRunning && mDataCallback && (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME);
2893}
2894
2895status_t QualcommCameraHardware::setPreviewSize(const CameraParameters& params)
2896{
2897 int width, height;
2898 params.getPreviewSize(&width, &height);
2899 LOGV("requested preview size %d x %d", width, height);
2900
2901 // Validate the preview size
2902 for (size_t i = 0; i < PREVIEW_SIZE_COUNT; ++i) {
2903 if (width == preview_sizes[i].width
2904 && height == preview_sizes[i].height) {
2905 mParameters.setPreviewSize(width, height);
2906 mDimension.display_width = width;
2907 mDimension.display_height = height;
2908 return NO_ERROR;
2909 }
2910 }
2911 LOGE("Invalid preview size requested: %dx%d", width, height);
2912 return BAD_VALUE;
2913}
2914
2915status_t QualcommCameraHardware::setPictureSize(const CameraParameters& params)
2916{
2917 int width, height;
2918 params.getPictureSize(&width, &height);
2919 LOGV("requested picture size %d x %d", width, height);
2920
2921 // Validate the picture size
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -08002922 for (int i = 0; i < supportedPictureSizesCount; ++i) {
2923 if (width == picture_sizes_ptr[i].width
2924 && height == picture_sizes_ptr[i].height) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002925 mParameters.setPictureSize(width, height);
2926 mDimension.picture_width = width;
2927 mDimension.picture_height = height;
2928 return NO_ERROR;
2929 }
2930 }
2931 LOGE("Invalid picture size requested: %dx%d", width, height);
2932 return BAD_VALUE;
2933}
2934
2935status_t QualcommCameraHardware::setJpegQuality(const CameraParameters& params) {
2936 status_t rc = NO_ERROR;
2937 int quality = params.getInt(CameraParameters::KEY_JPEG_QUALITY);
2938 if (quality > 0 && quality <= 100) {
2939 mParameters.set(CameraParameters::KEY_JPEG_QUALITY, quality);
2940 } else {
2941 LOGE("Invalid jpeg quality=%d", quality);
2942 rc = BAD_VALUE;
2943 }
2944
2945 quality = params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY);
2946 if (quality > 0 && quality <= 100) {
2947 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, quality);
2948 } else {
2949 LOGE("Invalid jpeg thumbnail quality=%d", quality);
2950 rc = BAD_VALUE;
2951 }
2952 return rc;
2953}
2954
2955status_t QualcommCameraHardware::setEffect(const CameraParameters& params)
2956{
2957 const char *str = params.get(CameraParameters::KEY_EFFECT);
2958 if (str != NULL) {
2959 int32_t value = attr_lookup(effects, sizeof(effects) / sizeof(str_map), str);
2960 if (value != NOT_FOUND) {
Mohan Kandra93f1bfb2009-12-15 16:55:33 -08002961 if(!strcmp(sensorType->name, "2mp") && (value != CAMERA_EFFECT_OFF)
2962 &&(value != CAMERA_EFFECT_MONO) && (value != CAMERA_EFFECT_NEGATIVE)
2963 &&(value != CAMERA_EFFECT_SOLARIZE) && (value != CAMERA_EFFECT_SEPIA)) {
2964 LOGE("Special effect parameter is not supported for this sensor");
2965 return NO_ERROR;
2966 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002967 mParameters.set(CameraParameters::KEY_EFFECT, str);
2968 bool ret = native_set_parm(CAMERA_SET_PARM_EFFECT, sizeof(value),
2969 (void *)&value);
2970 return ret ? NO_ERROR : UNKNOWN_ERROR;
2971 }
2972 }
2973 LOGE("Invalid effect value: %s", (str == NULL) ? "NULL" : str);
2974 return BAD_VALUE;
2975}
2976
Apurva Rajguru55562b02009-12-03 12:25:35 -08002977status_t QualcommCameraHardware::setAutoExposure(const CameraParameters& params)
2978{
Mohan Kandra93f1bfb2009-12-15 16:55:33 -08002979 if(!strcmp(sensorType->name, "2mp")) {
2980 LOGE("Auto Exposure not supported for this sensor");
2981 return NO_ERROR;
2982 }
Apurva Rajguru55562b02009-12-03 12:25:35 -08002983 const char *str = params.get(CameraParameters::KEY_AUTO_EXPOSURE);
2984 if (str != NULL) {
2985 int32_t value = attr_lookup(autoexposure, sizeof(autoexposure) / sizeof(str_map), str);
2986 if (value != NOT_FOUND) {
2987 mParameters.set(CameraParameters::KEY_AUTO_EXPOSURE, str);
2988 bool ret = native_set_parm(CAMERA_SET_PARM_EXPOSURE, sizeof(value),
2989 (void *)&value);
2990 return ret ? NO_ERROR : UNKNOWN_ERROR;
2991 }
2992 }
2993 LOGE("Invalid auto exposure value: %s", (str == NULL) ? "NULL" : str);
2994 return BAD_VALUE;
2995}
2996
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08002997status_t QualcommCameraHardware::setSharpness(const CameraParameters& params)
2998{
2999 if(!strcmp(sensorType->name, "2mp")) {
3000 LOGE("Sharpness not supported for this sensor");
3001 return NO_ERROR;
3002 }
3003 int sharpness = params.getInt(CameraParameters::KEY_SHARPNESS);
3004 if((sharpness < CAMERA_MIN_SHARPNESS
3005 || sharpness > CAMERA_MAX_SHARPNESS))
3006 return UNKNOWN_ERROR;
Srinivasan Kannan551fd262010-01-14 17:48:30 -08003007
3008 LOGV("setting sharpness %d", sharpness);
3009 mParameters.set(CameraParameters::KEY_SHARPNESS, sharpness);
3010 bool ret = native_set_parm(CAMERA_SET_PARM_SHARPNESS, sizeof(sharpness),
3011 (void *)&sharpness);
3012 return ret ? NO_ERROR : UNKNOWN_ERROR;
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003013}
3014
3015status_t QualcommCameraHardware::setContrast(const CameraParameters& params)
3016{
3017 if(!strcmp(sensorType->name, "2mp")) {
3018 LOGE("Contrast not supported for this sensor");
3019 return NO_ERROR;
3020 }
3021 int contrast = params.getInt(CameraParameters::KEY_CONTRAST);
3022 if((contrast < CAMERA_MIN_CONTRAST)
3023 || (contrast > CAMERA_MAX_CONTRAST))
3024 return UNKNOWN_ERROR;
Srinivasan Kannan551fd262010-01-14 17:48:30 -08003025
3026 LOGV("setting contrast %d", contrast);
3027 mParameters.set(CameraParameters::KEY_CONTRAST, contrast);
3028 bool ret = native_set_parm(CAMERA_SET_PARM_CONTRAST, sizeof(contrast),
3029 (void *)&contrast);
3030 return ret ? NO_ERROR : UNKNOWN_ERROR;
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003031}
3032
3033status_t QualcommCameraHardware::setSaturation(const CameraParameters& params)
3034{
3035 if(!strcmp(sensorType->name, "2mp")) {
3036 LOGE("Saturation not supported for this sensor");
3037 return NO_ERROR;
3038 }
3039 int saturation = params.getInt(CameraParameters::KEY_SATURATION);
3040 if((saturation < CAMERA_MIN_SATURATION)
3041 || (saturation > CAMERA_MAX_SATURATION))
3042 return UNKNOWN_ERROR;
Srinivasan Kannan551fd262010-01-14 17:48:30 -08003043
3044 LOGV("setting saturation %d", saturation);
3045 mParameters.set(CameraParameters::KEY_SATURATION, saturation);
3046 bool ret = native_set_parm(CAMERA_SET_PARM_SATURATION, sizeof(saturation),
3047 (void *)&saturation);
3048 return ret ? NO_ERROR : UNKNOWN_ERROR;
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003049}
3050
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303051status_t QualcommCameraHardware::setBrightness(const CameraParameters& params) {
3052 int brightness = params.getInt("luma-adaptation");
3053 if (mBrightness != brightness) {
3054 LOGV(" new brightness value : %d ", brightness);
3055 mBrightness = brightness;
3056
3057 bool ret = native_set_parm(CAMERA_SET_PARM_BRIGHTNESS, sizeof(mBrightness),
3058 (void *)&mBrightness);
3059 return ret ? NO_ERROR : UNKNOWN_ERROR;
3060 } else {
3061 return NO_ERROR;
3062 }
3063}
3064
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003065status_t QualcommCameraHardware::setWhiteBalance(const CameraParameters& params)
3066{
3067 const char *str = params.get(CameraParameters::KEY_WHITE_BALANCE);
3068 if (str != NULL) {
3069 int32_t value = attr_lookup(whitebalance, sizeof(whitebalance) / sizeof(str_map), str);
3070 if (value != NOT_FOUND) {
3071 mParameters.set(CameraParameters::KEY_WHITE_BALANCE, str);
3072 bool ret = native_set_parm(CAMERA_SET_PARM_WB, sizeof(value),
3073 (void *)&value);
3074 return ret ? NO_ERROR : UNKNOWN_ERROR;
3075 }
3076 }
3077 LOGE("Invalid whitebalance value: %s", (str == NULL) ? "NULL" : str);
3078 return BAD_VALUE;
3079}
3080
3081status_t QualcommCameraHardware::setFlash(const CameraParameters& params)
3082{
3083 if (!mSensorInfo.flash_enabled) {
3084 LOGV("%s: flash not supported", __FUNCTION__);
3085 return NO_ERROR;
3086 }
3087
3088 const char *str = params.get(CameraParameters::KEY_FLASH_MODE);
3089 if (str != NULL) {
3090 int32_t value = attr_lookup(flash, sizeof(flash) / sizeof(str_map), str);
3091 if (value != NOT_FOUND) {
3092 mParameters.set(CameraParameters::KEY_FLASH_MODE, str);
3093 bool ret = native_set_parm(CAMERA_SET_PARM_LED_MODE,
3094 sizeof(value), (void *)&value);
3095 return ret ? NO_ERROR : UNKNOWN_ERROR;
3096 }
3097 }
3098 LOGE("Invalid flash mode value: %s", (str == NULL) ? "NULL" : str);
3099 return BAD_VALUE;
3100}
3101
3102status_t QualcommCameraHardware::setAntibanding(const CameraParameters& params)
3103{
Srinivasan Kannan2229d272010-01-05 14:58:28 -08003104 if(!strcmp(sensorType->name, "2mp")) {
3105 LOGE("Parameter AntiBanding is not supported for this sensor");
3106 return NO_ERROR;
3107 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003108 const char *str = params.get(CameraParameters::KEY_ANTIBANDING);
3109 if (str != NULL) {
3110 int value = (camera_antibanding_type)attr_lookup(
3111 antibanding, sizeof(antibanding) / sizeof(str_map), str);
3112 if (value != NOT_FOUND) {
3113 camera_antibanding_type temp = (camera_antibanding_type) value;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003114 mParameters.set(CameraParameters::KEY_ANTIBANDING, str);
Srinivasan Kannan2229d272010-01-05 14:58:28 -08003115 bool ret;
3116 if (temp == CAMERA_ANTIBANDING_AUTO) {
3117 ret = native_set_parm(CAMERA_ENABLE_AFD,
3118 0, NULL);
3119 } else {
3120 ret = native_set_parm(CAMERA_SET_PARM_ANTIBANDING,
3121 sizeof(camera_antibanding_type), (void *)&temp);
3122 }
3123 return ret ? NO_ERROR : UNKNOWN_ERROR;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003124 }
3125 }
3126 LOGE("Invalid antibanding value: %s", (str == NULL) ? "NULL" : str);
3127 return BAD_VALUE;
3128}
3129
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303130status_t QualcommCameraHardware::setLensshadeValue(const CameraParameters& params)
3131{
Mohan Kandra93f1bfb2009-12-15 16:55:33 -08003132 if(!strcmp(sensorType->name, "2mp")) {
3133 LOGE("Parameter Rolloff is not supported for this sensor");
3134 return NO_ERROR;
3135 }
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303136 const char *str = params.get(CameraParameters::KEY_LENSSHADE);
3137 if (str != NULL) {
3138 int value = attr_lookup(lensshade,
3139 sizeof(lensshade) / sizeof(str_map), str);
3140 if (value != NOT_FOUND) {
3141 int8_t temp = (int8_t)value;
3142 mParameters.set(CameraParameters::KEY_LENSSHADE, str);
3143 native_set_parm(CAMERA_SET_PARM_ROLLOFF, sizeof(int8_t), (void *)&temp);
3144 return NO_ERROR;
3145 }
3146 }
3147 LOGE("Invalid lensShade value: %s", (str == NULL) ? "NULL" : str);
3148 return BAD_VALUE;
3149}
3150
3151status_t QualcommCameraHardware::setISOValue(const CameraParameters& params) {
3152 const char *str = params.get(CameraParameters::KEY_ISO_MODE);
3153 if (str != NULL) {
3154 int value = (camera_iso_mode_type)attr_lookup(
3155 iso, sizeof(iso) / sizeof(str_map), str);
3156 if (value != NOT_FOUND) {
3157 camera_iso_mode_type temp = (camera_iso_mode_type) value;
3158 mParameters.set(CameraParameters::KEY_ISO_MODE, str);
3159 native_set_parm(CAMERA_SET_PARM_ISO, sizeof(camera_iso_mode_type), (void *)&temp);
3160 return NO_ERROR;
3161 }
3162 }
3163 LOGE("Invalid Iso value: %s", (str == NULL) ? "NULL" : str);
3164 return BAD_VALUE;
3165}
3166
3167
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003168status_t QualcommCameraHardware::setGpsLocation(const CameraParameters& params)
3169{
3170 const char *latitude = params.get(CameraParameters::KEY_GPS_LATITUDE);
3171 if (latitude) {
3172 mParameters.set(CameraParameters::KEY_GPS_LATITUDE, latitude);
3173 }
3174
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08003175 const char *latitudeRef = params.get(CameraParameters::KEY_GPS_LATITUDE_REF);
3176 if (latitudeRef) {
3177 mParameters.set(CameraParameters::KEY_GPS_LATITUDE_REF, latitudeRef);
3178 }
3179
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003180 const char *longitude = params.get(CameraParameters::KEY_GPS_LONGITUDE);
3181 if (longitude) {
3182 mParameters.set(CameraParameters::KEY_GPS_LONGITUDE, longitude);
3183 }
3184
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08003185 const char *longitudeRef = params.get(CameraParameters::KEY_GPS_LONGITUDE_REF);
3186 if (longitudeRef) {
3187 mParameters.set(CameraParameters::KEY_GPS_LONGITUDE_REF, longitudeRef);
3188 }
3189
3190 const char *altitudeRef = params.get(CameraParameters::KEY_GPS_ALTITUDE_REF);
3191 if (altitudeRef) {
3192 mParameters.set(CameraParameters::KEY_GPS_ALTITUDE_REF, altitudeRef);
3193 }
3194
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003195 const char *altitude = params.get(CameraParameters::KEY_GPS_ALTITUDE);
3196 if (altitude) {
3197 mParameters.set(CameraParameters::KEY_GPS_ALTITUDE, altitude);
3198 }
3199
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08003200 const char *status = params.get(CameraParameters::KEY_GPS_STATUS);
3201 if (status) {
3202 mParameters.set(CameraParameters::KEY_GPS_STATUS, status);
3203 }
3204
3205 const char *dateTime = params.get(CameraParameters::KEY_EXIF_DATETIME);
3206 if (dateTime) {
3207 mParameters.set(CameraParameters::KEY_EXIF_DATETIME, dateTime);
3208 }
3209
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003210 const char *timestamp = params.get(CameraParameters::KEY_GPS_TIMESTAMP);
3211 if (timestamp) {
3212 mParameters.set(CameraParameters::KEY_GPS_TIMESTAMP, timestamp);
3213 }
3214 return NO_ERROR;
3215}
3216
3217status_t QualcommCameraHardware::setRotation(const CameraParameters& params)
3218{
3219 status_t rc = NO_ERROR;
3220 int rotation = params.getInt(CameraParameters::KEY_ROTATION);
3221 if (rotation != NOT_FOUND) {
3222 if (rotation == 0 || rotation == 90 || rotation == 180
3223 || rotation == 270) {
3224 mParameters.set(CameraParameters::KEY_ROTATION, rotation);
3225 } else {
3226 LOGE("Invalid rotation value: %d", rotation);
3227 rc = BAD_VALUE;
3228 }
3229 }
3230 return rc;
3231}
3232
3233status_t QualcommCameraHardware::setZoom(const CameraParameters& params)
3234{
3235 status_t rc = NO_ERROR;
3236 // No matter how many different zoom values the driver can provide, HAL
3237 // provides applictations the same number of zoom levels. The maximum driver
3238 // zoom value depends on sensor output (VFE input) and preview size (VFE
3239 // output) because VFE can only crop and cannot upscale. If the preview size
3240 // is bigger, the maximum zoom ratio is smaller. However, we want the
3241 // zoom ratio of each zoom level is always the same whatever the preview
3242 // size is. Ex: zoom level 1 is always 1.2x, zoom level 2 is 1.44x, etc. So,
3243 // we need to have a fixed maximum zoom value and do read it from the
3244 // driver.
Mohan Kandra284966d2010-01-05 13:39:15 -08003245 static const int ZOOM_STEP = 1;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003246 int32_t zoom_level = params.getInt("zoom");
3247
Mohan Kandra284966d2010-01-05 13:39:15 -08003248 LOGV("Set zoom=%d", zoom_level);
3249 if(zoom_level >= 0 && zoom_level <= mMaxZoom) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003250 mParameters.set("zoom", zoom_level);
3251 int32_t zoom_value = ZOOM_STEP * zoom_level;
3252 bool ret = native_set_parm(CAMERA_SET_PARM_ZOOM,
3253 sizeof(zoom_value), (void *)&zoom_value);
3254 rc = ret ? NO_ERROR : UNKNOWN_ERROR;
3255 } else {
3256 rc = BAD_VALUE;
3257 }
3258
3259 return rc;
3260}
3261
3262status_t QualcommCameraHardware::setFocusMode(const CameraParameters& params)
3263{
3264 const char *str = params.get(CameraParameters::KEY_FOCUS_MODE);
3265 if (str != NULL) {
3266 int32_t value = attr_lookup(focus_modes,
3267 sizeof(focus_modes) / sizeof(str_map), str);
3268 if (value != NOT_FOUND) {
3269 mParameters.set(CameraParameters::KEY_FOCUS_MODE, str);
3270 // Focus step is reset to infinity when preview is started. We do
3271 // not need to do anything now.
3272 return NO_ERROR;
3273 }
3274 }
3275 LOGE("Invalid focus mode value: %s", (str == NULL) ? "NULL" : str);
3276 return BAD_VALUE;
3277}
3278
3279status_t QualcommCameraHardware::setOrientation(const CameraParameters& params)
3280{
3281 const char *str = params.get("orientation");
3282
3283 if (str != NULL) {
3284 if (strcmp(str, "portrait") == 0 || strcmp(str, "landscape") == 0) {
3285 // Camera service needs this to decide if the preview frames and raw
3286 // pictures should be rotated.
3287 mParameters.set("orientation", str);
3288 } else {
3289 LOGE("Invalid orientation value: %s", str);
3290 return BAD_VALUE;
3291 }
3292 }
3293 return NO_ERROR;
3294}
3295
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08003296status_t QualcommCameraHardware::setPictureFormat(const CameraParameters& params)
3297{
3298 const char * str = params.get(CameraParameters::KEY_PICTURE_FORMAT);
3299
3300 if(str != NULL){
3301 int32_t value = attr_lookup(picture_formats,
3302 sizeof(picture_formats) / sizeof(str_map), str);
3303 if(value != NOT_FOUND){
3304 mParameters.set(CameraParameters::KEY_PICTURE_FORMAT, str);
3305 } else {
3306 LOGE("Invalid Picture Format value: %s", str);
3307 return BAD_VALUE;
3308 }
3309 }
3310 return NO_ERROR;
3311}
3312
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003313QualcommCameraHardware::MemPool::MemPool(int buffer_size, int num_buffers,
3314 int frame_size,
3315 const char *name) :
3316 mBufferSize(buffer_size),
3317 mNumBuffers(num_buffers),
3318 mFrameSize(frame_size),
3319 mBuffers(NULL), mName(name)
3320{
3321 int page_size_minus_1 = getpagesize() - 1;
3322 mAlignedBufferSize = (buffer_size + page_size_minus_1) & (~page_size_minus_1);
3323}
3324
3325void QualcommCameraHardware::MemPool::completeInitialization()
3326{
3327 // If we do not know how big the frame will be, we wait to allocate
3328 // the buffers describing the individual frames until we do know their
3329 // size.
3330
3331 if (mFrameSize > 0) {
3332 mBuffers = new sp<MemoryBase>[mNumBuffers];
3333 for (int i = 0; i < mNumBuffers; i++) {
3334 mBuffers[i] = new
3335 MemoryBase(mHeap,
3336 i * mAlignedBufferSize,
3337 mFrameSize);
3338 }
3339 }
3340}
3341
3342QualcommCameraHardware::AshmemPool::AshmemPool(int buffer_size, int num_buffers,
3343 int frame_size,
3344 const char *name) :
3345 QualcommCameraHardware::MemPool(buffer_size,
3346 num_buffers,
3347 frame_size,
3348 name)
3349{
3350 LOGV("constructing MemPool %s backed by ashmem: "
3351 "%d frames @ %d uint8_ts, "
3352 "buffer size %d",
3353 mName,
3354 num_buffers, frame_size, buffer_size);
3355
3356 int page_mask = getpagesize() - 1;
3357 int ashmem_size = buffer_size * num_buffers;
3358 ashmem_size += page_mask;
3359 ashmem_size &= ~page_mask;
3360
3361 mHeap = new MemoryHeapBase(ashmem_size);
3362
3363 completeInitialization();
3364}
3365
3366static bool register_buf(int camfd,
3367 int size,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08003368 int frame_size,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003369 int pmempreviewfd,
3370 uint32_t offset,
3371 uint8_t *buf,
3372 int pmem_type,
3373 bool vfe_can_write,
3374 bool register_buffer = true);
3375
3376QualcommCameraHardware::PmemPool::PmemPool(const char *pmem_pool,
3377 int flags,
3378 int camera_control_fd,
3379 int pmem_type,
3380 int buffer_size, int num_buffers,
3381 int frame_size,
3382 const char *name) :
3383 QualcommCameraHardware::MemPool(buffer_size,
3384 num_buffers,
3385 frame_size,
3386 name),
3387 mPmemType(pmem_type),
3388 mCameraControlFd(dup(camera_control_fd))
3389{
3390 LOGV("constructing MemPool %s backed by pmem pool %s: "
3391 "%d frames @ %d bytes, buffer size %d",
3392 mName,
3393 pmem_pool, num_buffers, frame_size,
3394 buffer_size);
3395
Kiran Kumar H N494c9fc2010-01-07 15:55:15 -08003396 if( mCameraControlFd == 0 ) {
3397 /* This should not happen. But if and when it
3398 * happens, we should not be using fd 0 for issuing
3399 * any IOCTL calls to camera driver since the
3400 * behaviour is undeterministic. Hence adding a
3401 * workaround to deal with this issue */
3402 LOGD(" 'dup'ed FD is 0....dup again ");
3403 mCameraControlFd = dup(camera_control_fd);
3404 }
3405
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003406 LOGV("%s: duplicating control fd %d --> %d",
3407 __FUNCTION__,
3408 camera_control_fd, mCameraControlFd);
3409
3410 // Make a new mmap'ed heap that can be shared across processes.
3411 // mAlignedBufferSize is already in 4k aligned. (do we need total size necessary to be in power of 2??)
3412 mAlignedSize = mAlignedBufferSize * num_buffers;
3413
3414 sp<MemoryHeapBase> masterHeap =
3415 new MemoryHeapBase(pmem_pool, mAlignedSize, flags);
3416
3417 if (masterHeap->getHeapID() < 0) {
3418 LOGE("failed to construct master heap for pmem pool %s", pmem_pool);
3419 masterHeap.clear();
3420 return;
3421 }
3422
3423 sp<MemoryHeapPmem> pmemHeap = new MemoryHeapPmem(masterHeap, flags);
3424 if (pmemHeap->getHeapID() >= 0) {
3425 pmemHeap->slap();
3426 masterHeap.clear();
3427 mHeap = pmemHeap;
3428 pmemHeap.clear();
3429
3430 mFd = mHeap->getHeapID();
3431 if (::ioctl(mFd, PMEM_GET_SIZE, &mSize)) {
3432 LOGE("pmem pool %s ioctl(PMEM_GET_SIZE) error %s (%d)",
3433 pmem_pool,
3434 ::strerror(errno), errno);
3435 mHeap.clear();
3436 return;
3437 }
3438
3439 LOGV("pmem pool %s ioctl(fd = %d, PMEM_GET_SIZE) is %ld",
3440 pmem_pool,
3441 mFd,
3442 mSize.len);
Mohan Kandra284966d2010-01-05 13:39:15 -08003443 LOGD("mBufferSize=%d, mAlignedBufferSize=%d\n", mBufferSize, mAlignedBufferSize);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003444 // Unregister preview buffers with the camera drivers. Allow the VFE to write
3445 // to all preview buffers except for the last one.
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003446 // Only Register the preview, snapshot and thumbnail buffers with the kernel.
3447 if( (strcmp("preview", mName) != 0)
3448 && (strcmp("postview", mName) != 0) ){
Mohan Kandra284966d2010-01-05 13:39:15 -08003449 for (int cnt = 0; cnt < num_buffers; ++cnt) {
3450 register_buf(mCameraControlFd,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003451 mBufferSize,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08003452 mFrameSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003453 mHeap->getHeapID(),
3454 mAlignedBufferSize * cnt,
3455 (uint8_t *)mHeap->base() + mAlignedBufferSize * cnt,
3456 pmem_type,
3457 !(cnt == num_buffers - 1 && pmem_type == MSM_PMEM_OUTPUT2));
Mohan Kandra284966d2010-01-05 13:39:15 -08003458 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003459 }
3460
3461 completeInitialization();
3462 }
3463 else LOGE("pmem pool %s error: could not create master heap!",
3464 pmem_pool);
3465}
3466
3467QualcommCameraHardware::PmemPool::~PmemPool()
3468{
3469 LOGV("%s: %s E", __FUNCTION__, mName);
3470 if (mHeap != NULL) {
3471 // Unregister preview buffers with the camera drivers.
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003472 // Only Unregister the preview, snapshot and thumbnail
3473 // buffers with the kernel.
3474 if( (strcmp("preview", mName) != 0)
3475 && (strcmp("postview", mName) != 0) ){
Mohan Kandra284966d2010-01-05 13:39:15 -08003476 for (int cnt = 0; cnt < mNumBuffers; ++cnt) {
3477 register_buf(mCameraControlFd,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003478 mBufferSize,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08003479 mFrameSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003480 mHeap->getHeapID(),
3481 mAlignedBufferSize * cnt,
3482 (uint8_t *)mHeap->base() + mAlignedBufferSize * cnt,
3483 mPmemType,
3484 false,
3485 false /* unregister */);
Mohan Kandra284966d2010-01-05 13:39:15 -08003486 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003487 }
3488 }
3489 LOGV("destroying PmemPool %s: closing control fd %d",
3490 mName,
3491 mCameraControlFd);
3492 close(mCameraControlFd);
3493 LOGV("%s: %s X", __FUNCTION__, mName);
3494}
3495
3496QualcommCameraHardware::MemPool::~MemPool()
3497{
3498 LOGV("destroying MemPool %s", mName);
3499 if (mFrameSize > 0)
3500 delete [] mBuffers;
3501 mHeap.clear();
3502 LOGV("destroying MemPool %s completed", mName);
3503}
3504
3505static bool register_buf(int camfd,
3506 int size,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08003507 int frame_size,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003508 int pmempreviewfd,
3509 uint32_t offset,
3510 uint8_t *buf,
3511 int pmem_type,
3512 bool vfe_can_write,
3513 bool register_buffer)
3514{
3515 struct msm_pmem_info pmemBuf;
3516
3517 pmemBuf.type = pmem_type;
3518 pmemBuf.fd = pmempreviewfd;
3519 pmemBuf.offset = offset;
3520 pmemBuf.len = size;
3521 pmemBuf.vaddr = buf;
3522 pmemBuf.y_off = 0;
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08003523 pmemBuf.cbcr_off = PAD_TO_WORD(frame_size * 2 / 3);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003524 pmemBuf.active = vfe_can_write;
3525
3526 LOGV("register_buf: camfd = %d, reg = %d buffer = %p",
3527 camfd, !register_buffer, buf);
3528 if (ioctl(camfd,
3529 register_buffer ?
3530 MSM_CAM_IOCTL_REGISTER_PMEM :
3531 MSM_CAM_IOCTL_UNREGISTER_PMEM,
3532 &pmemBuf) < 0) {
3533 LOGE("register_buf: MSM_CAM_IOCTL_(UN)REGISTER_PMEM fd %d error %s",
3534 camfd,
3535 strerror(errno));
3536 return false;
3537 }
3538 return true;
3539}
3540
3541status_t QualcommCameraHardware::MemPool::dump(int fd, const Vector<String16>& args) const
3542{
3543 const size_t SIZE = 256;
3544 char buffer[SIZE];
3545 String8 result;
3546 snprintf(buffer, 255, "QualcommCameraHardware::AshmemPool::dump\n");
3547 result.append(buffer);
3548 if (mName) {
3549 snprintf(buffer, 255, "mem pool name (%s)\n", mName);
3550 result.append(buffer);
3551 }
3552 if (mHeap != 0) {
3553 snprintf(buffer, 255, "heap base(%p), size(%d), flags(%d), device(%s)\n",
3554 mHeap->getBase(), mHeap->getSize(),
3555 mHeap->getFlags(), mHeap->getDevice());
3556 result.append(buffer);
3557 }
3558 snprintf(buffer, 255,
3559 "buffer size (%d), number of buffers (%d), frame size(%d)",
3560 mBufferSize, mNumBuffers, mFrameSize);
3561 result.append(buffer);
3562 write(fd, result.string(), result.size());
3563 return NO_ERROR;
3564}
3565
3566static void receive_camframe_callback(struct msm_frame *frame)
3567{
3568 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
3569 if (obj != 0) {
3570 obj->receivePreviewFrame(frame);
3571 }
3572}
3573
3574static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size)
3575{
3576 LOGV("receive_jpeg_fragment_callback E");
3577 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
3578 if (obj != 0) {
3579 obj->receiveJpegPictureFragment(buff_ptr, buff_size);
3580 }
3581 LOGV("receive_jpeg_fragment_callback X");
3582}
3583
3584static void receive_jpeg_callback(jpeg_event_t status)
3585{
3586 LOGV("receive_jpeg_callback E (completion status %d)", status);
3587 if (status == JPEG_EVENT_DONE) {
3588 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
3589 if (obj != 0) {
3590 obj->receiveJpegPicture();
3591 }
3592 }
3593 LOGV("receive_jpeg_callback X");
3594}
3595
3596void QualcommCameraHardware::setCallbacks(notify_callback notify_cb,
3597 data_callback data_cb,
3598 data_callback_timestamp data_cb_timestamp,
3599 void* user)
3600{
3601 Mutex::Autolock lock(mLock);
3602 mNotifyCallback = notify_cb;
3603 mDataCallback = data_cb;
3604 mDataCallbackTimestamp = data_cb_timestamp;
3605 mCallbackCookie = user;
3606}
3607
3608void QualcommCameraHardware::enableMsgType(int32_t msgType)
3609{
3610 Mutex::Autolock lock(mLock);
3611 mMsgEnabled |= msgType;
3612}
3613
3614void QualcommCameraHardware::disableMsgType(int32_t msgType)
3615{
3616 Mutex::Autolock lock(mLock);
3617 mMsgEnabled &= ~msgType;
3618}
3619
3620bool QualcommCameraHardware::msgTypeEnabled(int32_t msgType)
3621{
3622 return (mMsgEnabled & msgType);
3623}
3624
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08003625bool QualcommCameraHardware::useOverlay(void)
3626{
Mohan Kandra284966d2010-01-05 13:39:15 -08003627 if(!strcmp(mDeviceName,"msm7630_surf")) {
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08003628 /* Only 7x30 supports Overlay */
3629 mUseOverlay = TRUE;
3630 } else
3631 mUseOverlay = FALSE;
3632
3633 LOGV(" Using Overlay : %s ", mUseOverlay ? "YES" : "NO" );
3634 return mUseOverlay;
3635}
3636
3637status_t QualcommCameraHardware::setOverlay(const sp<Overlay> &Overlay)
3638{
3639 if( Overlay != NULL) {
3640 LOGV(" Valid overlay object ");
3641 mOverlayLock.lock();
3642 mOverlay = Overlay;
3643 mOverlayLock.unlock();
3644 } else {
3645 LOGE(" Overlay object NULL. returning ");
3646 return UNKNOWN_ERROR;
3647 }
3648 return NO_ERROR;
3649}
Kiran Kumar H N215cac42009-12-08 01:53:46 -08003650
3651void QualcommCameraHardware::receive_camframetimeout(void) {
3652 LOGV("receive_camframetimeout: E");
3653 Mutex::Autolock l(&mCamframeTimeoutLock);
3654 camframe_timeout_flag = TRUE;
3655 LOGV("receive_camframetimeout: X");
3656}
3657
3658static void receive_camframetimeout_callback(void) {
3659 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
3660 if (obj != 0) {
3661 obj->receive_camframetimeout();
3662 }
3663}
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003664
3665void QualcommCameraHardware::storePreviewFrameForPostview(void) {
3666 LOGV(" storePreviewFrameForPostview : E ");
3667
3668 /* Since there is restriction on the maximum overlay dimensions
3669 * that can be created, we use the last preview frame as postview
3670 * for 7x30. */
3671 LOGV(" Copying the preview buffer to postview buffer %d ",
3672 mPreviewFrameSize);
3673 if( mPostViewHeap != NULL && mLastQueuedFrame != NULL) {
3674 memcpy(mPostViewHeap->mHeap->base(),
3675 (uint8_t *)mLastQueuedFrame, mPreviewFrameSize );
3676 } else
3677 LOGE(" Failed to store Preview frame. No Postview ");
3678
3679 LOGV(" storePreviewFrameForPostview : X ");
3680}
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003681}; // namespace android