blob: f0a33aa29393228eb07f45fc397c79d6ac24c4c5 [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
39#define LIKELY(exp) __builtin_expect(!!(exp), 1)
40#define UNLIKELY(exp) __builtin_expect(!!(exp), 0)
41
42extern "C" {
43#include <fcntl.h>
44#include <time.h>
45#include <pthread.h>
46#include <stdio.h>
47#include <string.h>
48#include <unistd.h>
49#include <termios.h>
50#include <assert.h>
51#include <stdlib.h>
52#include <ctype.h>
53#include <signal.h>
54#include <errno.h>
55#include <sys/mman.h>
56#include <sys/system_properties.h>
57#include <sys/time.h>
58#include <stdlib.h>
59
60#include <media/msm_camera.h>
61
62#include <camera.h>
63#include <camframe.h>
64#include <mm-still/jpeg/jpege.h>
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -080065#include <jpeg_encoder.h>
Priya Komarlingamb85535d2009-11-30 13:06:01 -080066
67#define THUMBNAIL_WIDTH 512
68#define THUMBNAIL_HEIGHT 384
69#define THUMBNAIL_WIDTH_STR "512"
70#define THUMBNAIL_HEIGHT_STR "384"
71#define DEFAULT_PICTURE_WIDTH 2048
72#define DEFAULT_PICTURE_HEIGHT 1536
73#define THUMBNAIL_BUFFER_SIZE (THUMBNAIL_WIDTH * THUMBNAIL_HEIGHT * 3/2)
74#define MAX_ZOOM_LEVEL 5
75#define NOT_FOUND -1
76
77#if DLOPEN_LIBMMCAMERA
78#include <dlfcn.h>
79
80void* (*LINK_cam_conf)(void *data);
81void* (*LINK_cam_frame)(void *data);
82bool (*LINK_jpeg_encoder_init)();
83void (*LINK_jpeg_encoder_join)();
84bool (*LINK_jpeg_encoder_encode)(const cam_ctrl_dimension_t *dimen,
85 const uint8_t *thumbnailbuf, int thumbnailfd,
86 const uint8_t *snapshotbuf, int snapshotfd,
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -080087 common_crop_t *scaling_parms, exif_tags_info_t *exif_data,
88 int exif_table_numEntries);
Priya Komarlingamb85535d2009-11-30 13:06:01 -080089int (*LINK_camframe_terminate)(void);
90int8_t (*LINK_jpeg_encoder_setMainImageQuality)(uint32_t quality);
91int8_t (*LINK_jpeg_encoder_setThumbnailQuality)(uint32_t quality);
92int8_t (*LINK_jpeg_encoder_setRotation)(uint32_t rotation);
93int8_t (*LINK_jpeg_encoder_setLocation)(const camera_position_type *location);
94const struct camera_size_type *(*LINK_default_sensor_get_snapshot_sizes)(int *len);
95int (*LINK_launch_cam_conf_thread)(void);
96int (*LINK_release_cam_conf_thread)(void);
97int8_t (*LINK_zoom_crop_upscale)(uint32_t width, uint32_t height,
98 uint32_t cropped_width, uint32_t cropped_height, uint8_t *img_buf);
99
100// callbacks
101void (**LINK_mmcamera_camframe_callback)(struct msm_frame *frame);
102void (**LINK_mmcamera_jpegfragment_callback)(uint8_t *buff_ptr,
103 uint32_t buff_size);
104void (**LINK_mmcamera_jpeg_callback)(jpeg_event_t status);
105void (**LINK_mmcamera_shutter_callback)(common_crop_t *crop);
106#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
137#define DEFAULT_PREVIEW_SETTING 2
138static const camera_size_type preview_sizes[] = {
139 { 1280, 720 }, // 720P, reserved
140 { 800, 480 }, // WVGA
141 { 720, 480 },
142 { 640, 480 }, // VGA
143 { 576, 432 },
144 { 480, 320 }, // HVGA
145 { 384, 288 },
146 { 352, 288 }, // CIF
147 { 320, 240 }, // QVGA
148 { 240, 160 }, // SQVGA
149 { 176, 144 }, // QCIF
150};
151#define PREVIEW_SIZE_COUNT (sizeof(preview_sizes)/sizeof(camera_size_type))
152
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800153//static const camera_size_type* picture_sizes;
154//static int PICTURE_SIZE_COUNT;
155/* TODO
156 * Ideally this should be a populated by lower layers.
157 * But currently this is no API to do that at lower layer.
158 * Hence populating with default sizes for now. This needs
159 * to be changed once the API is supported.
160 */
161static const camera_size_type picture_sizes[] = {
162 { 2592, 1944 }, // 5MP
163 { 2048, 1536 }, // 3MP
164 { 1600, 1200 }, // 2MP
165 { 800, 480 }, // WVGA
166 { 640, 480 }, // VGA
167 { 320, 240 } // QVGA
168};
169static int PICTURE_SIZE_COUNT = sizeof(picture_sizes)/sizeof(camera_size_type);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800170
171static int attr_lookup(const str_map arr[], int len, const char *name)
172{
173 if (name) {
174 for (int i = 0; i < len; i++) {
175 if (!strcmp(arr[i].desc, name))
176 return arr[i].val;
177 }
178 }
179 return NOT_FOUND;
180}
181
182// round to the next power of two
183static inline unsigned clp2(unsigned x)
184{
185 x = x - 1;
186 x = x | (x >> 1);
187 x = x | (x >> 2);
188 x = x | (x >> 4);
189 x = x | (x >> 8);
190 x = x | (x >>16);
191 return x + 1;
192}
193
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -0800194static int exif_table_numEntries = 0;
195#define MAX_EXIF_TABLE_ENTRIES 7
196exif_tags_info_t exif_data[MAX_EXIF_TABLE_ENTRIES];
197
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800198namespace android {
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800199
200static const int PICTURE_FORMAT_JPEG = 1;
201static const int PICTURE_FORMAT_RAW = 2;
202
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800203// from aeecamera.h
204static const str_map whitebalance[] = {
205 { CameraParameters::WHITE_BALANCE_AUTO, CAMERA_WB_AUTO },
206 { CameraParameters::WHITE_BALANCE_INCANDESCENT, CAMERA_WB_INCANDESCENT },
207 { CameraParameters::WHITE_BALANCE_FLUORESCENT, CAMERA_WB_FLUORESCENT },
208 { CameraParameters::WHITE_BALANCE_DAYLIGHT, CAMERA_WB_DAYLIGHT },
209 { CameraParameters::WHITE_BALANCE_CLOUDY_DAYLIGHT, CAMERA_WB_CLOUDY_DAYLIGHT }
210};
211
212// from camera_effect_t. This list must match aeecamera.h
213static const str_map effects[] = {
214 { CameraParameters::EFFECT_NONE, CAMERA_EFFECT_OFF },
215 { CameraParameters::EFFECT_MONO, CAMERA_EFFECT_MONO },
216 { CameraParameters::EFFECT_NEGATIVE, CAMERA_EFFECT_NEGATIVE },
217 { CameraParameters::EFFECT_SOLARIZE, CAMERA_EFFECT_SOLARIZE },
218 { CameraParameters::EFFECT_SEPIA, CAMERA_EFFECT_SEPIA },
219 { CameraParameters::EFFECT_POSTERIZE, CAMERA_EFFECT_POSTERIZE },
220 { CameraParameters::EFFECT_WHITEBOARD, CAMERA_EFFECT_WHITEBOARD },
221 { CameraParameters::EFFECT_BLACKBOARD, CAMERA_EFFECT_BLACKBOARD },
222 { CameraParameters::EFFECT_AQUA, CAMERA_EFFECT_AQUA }
223};
224
225// from qcamera/common/camera.h
Apurva Rajguru55562b02009-12-03 12:25:35 -0800226static const str_map autoexposure[] = {
227 { CameraParameters::AUTO_EXPOSURE_FRAME_AVG, CAMERA_AEC_FRAME_AVERAGE },
228 { CameraParameters::AUTO_EXPOSURE_CENTER_WEIGHTED, CAMERA_AEC_CENTER_WEIGHTED },
229 { CameraParameters::AUTO_EXPOSURE_SPOT_METERING, CAMERA_AEC_SPOT_METERING }
230};
231
232// from qcamera/common/camera.h
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800233static const str_map antibanding[] = {
234 { CameraParameters::ANTIBANDING_OFF, CAMERA_ANTIBANDING_OFF },
235 { CameraParameters::ANTIBANDING_50HZ, CAMERA_ANTIBANDING_50HZ },
236 { CameraParameters::ANTIBANDING_60HZ, CAMERA_ANTIBANDING_60HZ },
237 { CameraParameters::ANTIBANDING_AUTO, CAMERA_ANTIBANDING_AUTO }
238};
239
240/* Mapping from MCC to antibanding type */
241struct country_map {
242 uint32_t country_code;
243 camera_antibanding_type type;
244};
245
246static struct country_map country_numeric[] = {
247 { 202, CAMERA_ANTIBANDING_50HZ }, // Greece
248 { 204, CAMERA_ANTIBANDING_50HZ }, // Netherlands
249 { 206, CAMERA_ANTIBANDING_50HZ }, // Belgium
250 { 208, CAMERA_ANTIBANDING_50HZ }, // France
251 { 212, CAMERA_ANTIBANDING_50HZ }, // Monaco
252 { 213, CAMERA_ANTIBANDING_50HZ }, // Andorra
253 { 214, CAMERA_ANTIBANDING_50HZ }, // Spain
254 { 216, CAMERA_ANTIBANDING_50HZ }, // Hungary
255 { 219, CAMERA_ANTIBANDING_50HZ }, // Croatia
256 { 220, CAMERA_ANTIBANDING_50HZ }, // Serbia
257 { 222, CAMERA_ANTIBANDING_50HZ }, // Italy
258 { 226, CAMERA_ANTIBANDING_50HZ }, // Romania
259 { 228, CAMERA_ANTIBANDING_50HZ }, // Switzerland
260 { 230, CAMERA_ANTIBANDING_50HZ }, // Czech Republic
261 { 231, CAMERA_ANTIBANDING_50HZ }, // Slovakia
262 { 232, CAMERA_ANTIBANDING_50HZ }, // Austria
263 { 234, CAMERA_ANTIBANDING_50HZ }, // United Kingdom
264 { 235, CAMERA_ANTIBANDING_50HZ }, // United Kingdom
265 { 238, CAMERA_ANTIBANDING_50HZ }, // Denmark
266 { 240, CAMERA_ANTIBANDING_50HZ }, // Sweden
267 { 242, CAMERA_ANTIBANDING_50HZ }, // Norway
268 { 244, CAMERA_ANTIBANDING_50HZ }, // Finland
269 { 246, CAMERA_ANTIBANDING_50HZ }, // Lithuania
270 { 247, CAMERA_ANTIBANDING_50HZ }, // Latvia
271 { 248, CAMERA_ANTIBANDING_50HZ }, // Estonia
272 { 250, CAMERA_ANTIBANDING_50HZ }, // Russian Federation
273 { 255, CAMERA_ANTIBANDING_50HZ }, // Ukraine
274 { 257, CAMERA_ANTIBANDING_50HZ }, // Belarus
275 { 259, CAMERA_ANTIBANDING_50HZ }, // Moldova
276 { 260, CAMERA_ANTIBANDING_50HZ }, // Poland
277 { 262, CAMERA_ANTIBANDING_50HZ }, // Germany
278 { 266, CAMERA_ANTIBANDING_50HZ }, // Gibraltar
279 { 268, CAMERA_ANTIBANDING_50HZ }, // Portugal
280 { 270, CAMERA_ANTIBANDING_50HZ }, // Luxembourg
281 { 272, CAMERA_ANTIBANDING_50HZ }, // Ireland
282 { 274, CAMERA_ANTIBANDING_50HZ }, // Iceland
283 { 276, CAMERA_ANTIBANDING_50HZ }, // Albania
284 { 278, CAMERA_ANTIBANDING_50HZ }, // Malta
285 { 280, CAMERA_ANTIBANDING_50HZ }, // Cyprus
286 { 282, CAMERA_ANTIBANDING_50HZ }, // Georgia
287 { 283, CAMERA_ANTIBANDING_50HZ }, // Armenia
288 { 284, CAMERA_ANTIBANDING_50HZ }, // Bulgaria
289 { 286, CAMERA_ANTIBANDING_50HZ }, // Turkey
290 { 288, CAMERA_ANTIBANDING_50HZ }, // Faroe Islands
291 { 290, CAMERA_ANTIBANDING_50HZ }, // Greenland
292 { 293, CAMERA_ANTIBANDING_50HZ }, // Slovenia
293 { 294, CAMERA_ANTIBANDING_50HZ }, // Macedonia
294 { 295, CAMERA_ANTIBANDING_50HZ }, // Liechtenstein
295 { 297, CAMERA_ANTIBANDING_50HZ }, // Montenegro
296 { 302, CAMERA_ANTIBANDING_60HZ }, // Canada
297 { 310, CAMERA_ANTIBANDING_60HZ }, // United States of America
298 { 311, CAMERA_ANTIBANDING_60HZ }, // United States of America
299 { 312, CAMERA_ANTIBANDING_60HZ }, // United States of America
300 { 313, CAMERA_ANTIBANDING_60HZ }, // United States of America
301 { 314, CAMERA_ANTIBANDING_60HZ }, // United States of America
302 { 315, CAMERA_ANTIBANDING_60HZ }, // United States of America
303 { 316, CAMERA_ANTIBANDING_60HZ }, // United States of America
304 { 330, CAMERA_ANTIBANDING_60HZ }, // Puerto Rico
305 { 334, CAMERA_ANTIBANDING_60HZ }, // Mexico
306 { 338, CAMERA_ANTIBANDING_50HZ }, // Jamaica
307 { 340, CAMERA_ANTIBANDING_50HZ }, // Martinique
308 { 342, CAMERA_ANTIBANDING_50HZ }, // Barbados
309 { 346, CAMERA_ANTIBANDING_60HZ }, // Cayman Islands
310 { 350, CAMERA_ANTIBANDING_60HZ }, // Bermuda
311 { 352, CAMERA_ANTIBANDING_50HZ }, // Grenada
312 { 354, CAMERA_ANTIBANDING_60HZ }, // Montserrat
313 { 362, CAMERA_ANTIBANDING_50HZ }, // Netherlands Antilles
314 { 363, CAMERA_ANTIBANDING_60HZ }, // Aruba
315 { 364, CAMERA_ANTIBANDING_60HZ }, // Bahamas
316 { 365, CAMERA_ANTIBANDING_60HZ }, // Anguilla
317 { 366, CAMERA_ANTIBANDING_50HZ }, // Dominica
318 { 368, CAMERA_ANTIBANDING_60HZ }, // Cuba
319 { 370, CAMERA_ANTIBANDING_60HZ }, // Dominican Republic
320 { 372, CAMERA_ANTIBANDING_60HZ }, // Haiti
321 { 401, CAMERA_ANTIBANDING_50HZ }, // Kazakhstan
322 { 402, CAMERA_ANTIBANDING_50HZ }, // Bhutan
323 { 404, CAMERA_ANTIBANDING_50HZ }, // India
324 { 405, CAMERA_ANTIBANDING_50HZ }, // India
325 { 410, CAMERA_ANTIBANDING_50HZ }, // Pakistan
326 { 413, CAMERA_ANTIBANDING_50HZ }, // Sri Lanka
327 { 414, CAMERA_ANTIBANDING_50HZ }, // Myanmar
328 { 415, CAMERA_ANTIBANDING_50HZ }, // Lebanon
329 { 416, CAMERA_ANTIBANDING_50HZ }, // Jordan
330 { 417, CAMERA_ANTIBANDING_50HZ }, // Syria
331 { 418, CAMERA_ANTIBANDING_50HZ }, // Iraq
332 { 419, CAMERA_ANTIBANDING_50HZ }, // Kuwait
333 { 420, CAMERA_ANTIBANDING_60HZ }, // Saudi Arabia
334 { 421, CAMERA_ANTIBANDING_50HZ }, // Yemen
335 { 422, CAMERA_ANTIBANDING_50HZ }, // Oman
336 { 424, CAMERA_ANTIBANDING_50HZ }, // United Arab Emirates
337 { 425, CAMERA_ANTIBANDING_50HZ }, // Israel
338 { 426, CAMERA_ANTIBANDING_50HZ }, // Bahrain
339 { 427, CAMERA_ANTIBANDING_50HZ }, // Qatar
340 { 428, CAMERA_ANTIBANDING_50HZ }, // Mongolia
341 { 429, CAMERA_ANTIBANDING_50HZ }, // Nepal
342 { 430, CAMERA_ANTIBANDING_50HZ }, // United Arab Emirates
343 { 431, CAMERA_ANTIBANDING_50HZ }, // United Arab Emirates
344 { 432, CAMERA_ANTIBANDING_50HZ }, // Iran
345 { 434, CAMERA_ANTIBANDING_50HZ }, // Uzbekistan
346 { 436, CAMERA_ANTIBANDING_50HZ }, // Tajikistan
347 { 437, CAMERA_ANTIBANDING_50HZ }, // Kyrgyz Rep
348 { 438, CAMERA_ANTIBANDING_50HZ }, // Turkmenistan
349 { 440, CAMERA_ANTIBANDING_60HZ }, // Japan
350 { 441, CAMERA_ANTIBANDING_60HZ }, // Japan
351 { 452, CAMERA_ANTIBANDING_50HZ }, // Vietnam
352 { 454, CAMERA_ANTIBANDING_50HZ }, // Hong Kong
353 { 455, CAMERA_ANTIBANDING_50HZ }, // Macao
354 { 456, CAMERA_ANTIBANDING_50HZ }, // Cambodia
355 { 457, CAMERA_ANTIBANDING_50HZ }, // Laos
356 { 460, CAMERA_ANTIBANDING_50HZ }, // China
357 { 466, CAMERA_ANTIBANDING_60HZ }, // Taiwan
358 { 470, CAMERA_ANTIBANDING_50HZ }, // Bangladesh
359 { 472, CAMERA_ANTIBANDING_50HZ }, // Maldives
360 { 502, CAMERA_ANTIBANDING_50HZ }, // Malaysia
361 { 505, CAMERA_ANTIBANDING_50HZ }, // Australia
362 { 510, CAMERA_ANTIBANDING_50HZ }, // Indonesia
363 { 514, CAMERA_ANTIBANDING_50HZ }, // East Timor
364 { 515, CAMERA_ANTIBANDING_60HZ }, // Philippines
365 { 520, CAMERA_ANTIBANDING_50HZ }, // Thailand
366 { 525, CAMERA_ANTIBANDING_50HZ }, // Singapore
367 { 530, CAMERA_ANTIBANDING_50HZ }, // New Zealand
368 { 535, CAMERA_ANTIBANDING_60HZ }, // Guam
369 { 536, CAMERA_ANTIBANDING_50HZ }, // Nauru
370 { 537, CAMERA_ANTIBANDING_50HZ }, // Papua New Guinea
371 { 539, CAMERA_ANTIBANDING_50HZ }, // Tonga
372 { 541, CAMERA_ANTIBANDING_50HZ }, // Vanuatu
373 { 542, CAMERA_ANTIBANDING_50HZ }, // Fiji
374 { 544, CAMERA_ANTIBANDING_60HZ }, // American Samoa
375 { 545, CAMERA_ANTIBANDING_50HZ }, // Kiribati
376 { 546, CAMERA_ANTIBANDING_50HZ }, // New Caledonia
377 { 548, CAMERA_ANTIBANDING_50HZ }, // Cook Islands
378 { 602, CAMERA_ANTIBANDING_50HZ }, // Egypt
379 { 603, CAMERA_ANTIBANDING_50HZ }, // Algeria
380 { 604, CAMERA_ANTIBANDING_50HZ }, // Morocco
381 { 605, CAMERA_ANTIBANDING_50HZ }, // Tunisia
382 { 606, CAMERA_ANTIBANDING_50HZ }, // Libya
383 { 607, CAMERA_ANTIBANDING_50HZ }, // Gambia
384 { 608, CAMERA_ANTIBANDING_50HZ }, // Senegal
385 { 609, CAMERA_ANTIBANDING_50HZ }, // Mauritania
386 { 610, CAMERA_ANTIBANDING_50HZ }, // Mali
387 { 611, CAMERA_ANTIBANDING_50HZ }, // Guinea
388 { 613, CAMERA_ANTIBANDING_50HZ }, // Burkina Faso
389 { 614, CAMERA_ANTIBANDING_50HZ }, // Niger
390 { 616, CAMERA_ANTIBANDING_50HZ }, // Benin
391 { 617, CAMERA_ANTIBANDING_50HZ }, // Mauritius
392 { 618, CAMERA_ANTIBANDING_50HZ }, // Liberia
393 { 619, CAMERA_ANTIBANDING_50HZ }, // Sierra Leone
394 { 620, CAMERA_ANTIBANDING_50HZ }, // Ghana
395 { 621, CAMERA_ANTIBANDING_50HZ }, // Nigeria
396 { 622, CAMERA_ANTIBANDING_50HZ }, // Chad
397 { 623, CAMERA_ANTIBANDING_50HZ }, // Central African Republic
398 { 624, CAMERA_ANTIBANDING_50HZ }, // Cameroon
399 { 625, CAMERA_ANTIBANDING_50HZ }, // Cape Verde
400 { 627, CAMERA_ANTIBANDING_50HZ }, // Equatorial Guinea
401 { 631, CAMERA_ANTIBANDING_50HZ }, // Angola
402 { 633, CAMERA_ANTIBANDING_50HZ }, // Seychelles
403 { 634, CAMERA_ANTIBANDING_50HZ }, // Sudan
404 { 636, CAMERA_ANTIBANDING_50HZ }, // Ethiopia
405 { 637, CAMERA_ANTIBANDING_50HZ }, // Somalia
406 { 638, CAMERA_ANTIBANDING_50HZ }, // Djibouti
407 { 639, CAMERA_ANTIBANDING_50HZ }, // Kenya
408 { 640, CAMERA_ANTIBANDING_50HZ }, // Tanzania
409 { 641, CAMERA_ANTIBANDING_50HZ }, // Uganda
410 { 642, CAMERA_ANTIBANDING_50HZ }, // Burundi
411 { 643, CAMERA_ANTIBANDING_50HZ }, // Mozambique
412 { 645, CAMERA_ANTIBANDING_50HZ }, // Zambia
413 { 646, CAMERA_ANTIBANDING_50HZ }, // Madagascar
414 { 647, CAMERA_ANTIBANDING_50HZ }, // France
415 { 648, CAMERA_ANTIBANDING_50HZ }, // Zimbabwe
416 { 649, CAMERA_ANTIBANDING_50HZ }, // Namibia
417 { 650, CAMERA_ANTIBANDING_50HZ }, // Malawi
418 { 651, CAMERA_ANTIBANDING_50HZ }, // Lesotho
419 { 652, CAMERA_ANTIBANDING_50HZ }, // Botswana
420 { 653, CAMERA_ANTIBANDING_50HZ }, // Swaziland
421 { 654, CAMERA_ANTIBANDING_50HZ }, // Comoros
422 { 655, CAMERA_ANTIBANDING_50HZ }, // South Africa
423 { 657, CAMERA_ANTIBANDING_50HZ }, // Eritrea
424 { 702, CAMERA_ANTIBANDING_60HZ }, // Belize
425 { 704, CAMERA_ANTIBANDING_60HZ }, // Guatemala
426 { 706, CAMERA_ANTIBANDING_60HZ }, // El Salvador
427 { 708, CAMERA_ANTIBANDING_60HZ }, // Honduras
428 { 710, CAMERA_ANTIBANDING_60HZ }, // Nicaragua
429 { 712, CAMERA_ANTIBANDING_60HZ }, // Costa Rica
430 { 714, CAMERA_ANTIBANDING_60HZ }, // Panama
431 { 722, CAMERA_ANTIBANDING_50HZ }, // Argentina
432 { 724, CAMERA_ANTIBANDING_60HZ }, // Brazil
433 { 730, CAMERA_ANTIBANDING_50HZ }, // Chile
434 { 732, CAMERA_ANTIBANDING_60HZ }, // Colombia
435 { 734, CAMERA_ANTIBANDING_60HZ }, // Venezuela
436 { 736, CAMERA_ANTIBANDING_50HZ }, // Bolivia
437 { 738, CAMERA_ANTIBANDING_60HZ }, // Guyana
438 { 740, CAMERA_ANTIBANDING_60HZ }, // Ecuador
439 { 742, CAMERA_ANTIBANDING_50HZ }, // French Guiana
440 { 744, CAMERA_ANTIBANDING_50HZ }, // Paraguay
441 { 746, CAMERA_ANTIBANDING_60HZ }, // Suriname
442 { 748, CAMERA_ANTIBANDING_50HZ }, // Uruguay
443 { 750, CAMERA_ANTIBANDING_50HZ }, // Falkland Islands
444};
445
446#define country_number (sizeof(country_numeric) / sizeof(country_map))
447
448/* Look up pre-sorted antibanding_type table by current MCC. */
449static camera_antibanding_type camera_get_location(void) {
450 char value[PROP_VALUE_MAX];
451 char country_value[PROP_VALUE_MAX];
452 uint32_t country_code, count;
453 memset(value, 0x00, sizeof(value));
454 memset(country_value, 0x00, sizeof(country_value));
455 if (!__system_property_get("gsm.operator.numeric", value)) {
456 return CAMERA_ANTIBANDING_60HZ;
457 }
458 memcpy(country_value, value, 3);
459 country_code = atoi(country_value);
460 LOGD("value:%s, country value:%s, country code:%d\n",
461 value, country_value, country_code);
462 int left = 0;
463 int right = country_number - 1;
464 while (left <= right) {
465 int index = (left + right) >> 1;
466 if (country_numeric[index].country_code == country_code)
467 return country_numeric[index].type;
468 else if (country_numeric[index].country_code > country_code)
469 right = index - 1;
470 else
471 left = index + 1;
472 }
473 return CAMERA_ANTIBANDING_60HZ;
474}
475
476// from camera.h, led_mode_t
477static const str_map flash[] = {
478 { CameraParameters::FLASH_MODE_OFF, LED_MODE_OFF },
479 { CameraParameters::FLASH_MODE_AUTO, LED_MODE_AUTO },
480 { CameraParameters::FLASH_MODE_ON, LED_MODE_ON }
481};
482
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530483// from mm-camera/common/camera.h.
484static const str_map iso[] = {
485 { CameraParameters::ISO_AUTO, CAMERA_ISO_AUTO},
486 { CameraParameters::ISO_HJR, CAMERA_ISO_DEBLUR},
487 { CameraParameters::ISO_100, CAMERA_ISO_100},
488 { CameraParameters::ISO_200, CAMERA_ISO_200},
489 { CameraParameters::ISO_400, CAMERA_ISO_400},
490 { CameraParameters::ISO_800, CAMERA_ISO_800 }
491};
492
493
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800494#define DONT_CARE 0
495static const str_map focus_modes[] = {
Srinivasan Kannan71229622009-12-04 12:05:58 -0800496 { CameraParameters::FOCUS_MODE_AUTO, AF_MODE_AUTO},
497 { CameraParameters::FOCUS_MODE_INFINITY, DONT_CARE },
498 { CameraParameters::FOCUS_MODE_NORMAL, AF_MODE_NORMAL },
499 { CameraParameters::FOCUS_MODE_MACRO, AF_MODE_MACRO }
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800500};
501
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530502static const str_map lensshade[] = {
503 { CameraParameters::LENSSHADE_ENABLE, TRUE },
504 { CameraParameters::LENSSHADE_DISABLE, FALSE }
505};
506
Srinivasan Kannan71229622009-12-04 12:05:58 -0800507struct SensorType {
508 const char *name;
509 int rawPictureWidth;
510 int rawPictureHeight;
511 bool hasAutoFocusSupport;
512};
513
514static SensorType sensorTypes[] = {
515 { "5mp", 2608, 1960, true },
516 { "3mp", 2064, 1544, false },
517 { "2mp", 3200, 1200, false } };
518
519static SensorType * sensorType;
520
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800521static const str_map picture_formats[] = {
522 {CameraParameters::PIXEL_FORMAT_JPEG, PICTURE_FORMAT_JPEG},
523 {CameraParameters::PIXEL_FORMAT_RAW, PICTURE_FORMAT_RAW}
524};
525
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800526static bool parameter_string_initialized = false;
527static String8 preview_size_values;
528static String8 picture_size_values;
529static String8 antibanding_values;
530static String8 effect_values;
Apurva Rajguru55562b02009-12-03 12:25:35 -0800531static String8 autoexposure_values;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800532static String8 whitebalance_values;
533static String8 flash_values;
534static String8 focus_mode_values;
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530535static String8 iso_values;
536static String8 lensshade_values;
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800537static String8 picture_format_values;
538
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800539
540static String8 create_sizes_str(const camera_size_type *sizes, int len) {
541 String8 str;
542 char buffer[32];
543
544 if (len > 0) {
545 sprintf(buffer, "%dx%d", sizes[0].width, sizes[0].height);
546 str.append(buffer);
547 }
548 for (int i = 1; i < len; i++) {
549 sprintf(buffer, ",%dx%d", sizes[i].width, sizes[i].height);
550 str.append(buffer);
551 }
552 return str;
553}
554
555static String8 create_values_str(const str_map *values, int len) {
556 String8 str;
557
558 if (len > 0) {
559 str.append(values[0].desc);
560 }
561 for (int i = 1; i < len; i++) {
562 str.append(",");
563 str.append(values[i].desc);
564 }
565 return str;
566}
567
568static Mutex singleton_lock;
569static bool singleton_releasing;
570static Condition singleton_wait;
571
572static void receive_camframe_callback(struct msm_frame *frame);
573static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size);
574static void receive_jpeg_callback(jpeg_event_t status);
575static void receive_shutter_callback(common_crop_t *crop);
576
577QualcommCameraHardware::QualcommCameraHardware()
578 : mParameters(),
579 mCameraRunning(false),
580 mPreviewInitialized(false),
581 mFrameThreadRunning(false),
582 mSnapshotThreadRunning(false),
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800583 mSnapshotFormat(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800584 mReleasedRecordingFrame(false),
585 mPreviewFrameSize(0),
586 mRawSize(0),
587 mCameraControlFd(-1),
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530588 mBrightness(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800589 mAutoFocusThreadRunning(false),
590 mAutoFocusFd(-1),
591 mInPreviewCallback(false),
592 mMsgEnabled(0),
593 mNotifyCallback(0),
594 mDataCallback(0),
595 mDataCallbackTimestamp(0),
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -0800596 mCallbackCookie(0),
597 mOverlay(0),
598 mUseOverlay(0)
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800599{
600 memset(&mDimension, 0, sizeof(mDimension));
601 memset(&mCrop, 0, sizeof(mCrop));
602 LOGV("constructor EX");
603}
604
605void QualcommCameraHardware::initDefaultParameters()
606{
607 LOGV("initDefaultParameters E");
608
609 // Initialize constant parameter strings. This will happen only once in the
610 // lifetime of the mediaserver process.
611 if (!parameter_string_initialized) {
Srinivasan Kannan71229622009-12-04 12:05:58 -0800612 findSensorType();
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800613 antibanding_values = create_values_str(
614 antibanding, sizeof(antibanding) / sizeof(str_map));
615 effect_values = create_values_str(
616 effects, sizeof(effects) / sizeof(str_map));
Apurva Rajguru55562b02009-12-03 12:25:35 -0800617 autoexposure_values = create_values_str(
618 autoexposure, sizeof(autoexposure) / sizeof(str_map));
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800619 whitebalance_values = create_values_str(
620 whitebalance, sizeof(whitebalance) / sizeof(str_map));
621 preview_size_values = create_sizes_str(
622 preview_sizes, PREVIEW_SIZE_COUNT);
623 picture_size_values = create_sizes_str(
624 picture_sizes, PICTURE_SIZE_COUNT);
625 flash_values = create_values_str(
626 flash, sizeof(flash) / sizeof(str_map));
Srinivasan Kannan71229622009-12-04 12:05:58 -0800627 if(sensorType->hasAutoFocusSupport){
628 focus_mode_values = create_values_str(
629 focus_modes, sizeof(focus_modes) / sizeof(str_map));
630 }
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530631 iso_values = create_values_str(
632 iso,sizeof(iso)/sizeof(str_map));
633 lensshade_values = create_values_str(
634 lensshade,sizeof(lensshade)/sizeof(str_map));
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800635 picture_format_values = create_values_str(
636 picture_formats, sizeof(picture_formats)/sizeof(str_map));
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800637 parameter_string_initialized = true;
638 }
639
640 const camera_size_type *ps = &preview_sizes[DEFAULT_PREVIEW_SETTING];
641 mParameters.setPreviewSize(ps->width, ps->height);
642 mDimension.display_width = ps->width;
643 mDimension.display_height = ps->height;
644 mParameters.setPreviewFrameRate(15);
645 mParameters.setPreviewFormat("yuv420sp"); // informative
646
647 mParameters.setPictureSize(DEFAULT_PICTURE_WIDTH, DEFAULT_PICTURE_HEIGHT);
648 mParameters.setPictureFormat("jpeg"); // informative
649
650 mParameters.set(CameraParameters::KEY_JPEG_QUALITY, "100"); // max quality
651 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH,
652 THUMBNAIL_WIDTH_STR); // informative
653 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT,
654 THUMBNAIL_HEIGHT_STR); // informative
655 mDimension.ui_thumbnail_width = THUMBNAIL_WIDTH;
656 mDimension.ui_thumbnail_height = THUMBNAIL_HEIGHT;
657 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, "90");
658
659 mParameters.set(CameraParameters::KEY_ANTIBANDING,
660 CameraParameters::ANTIBANDING_AUTO);
661 mParameters.set(CameraParameters::KEY_EFFECT,
662 CameraParameters::EFFECT_NONE);
Apurva Rajguru55562b02009-12-03 12:25:35 -0800663 mParameters.set(CameraParameters::KEY_AUTO_EXPOSURE,
664 CameraParameters::AUTO_EXPOSURE_FRAME_AVG);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800665 mParameters.set(CameraParameters::KEY_WHITE_BALANCE,
666 CameraParameters::WHITE_BALANCE_AUTO);
667 mParameters.set(CameraParameters::KEY_FOCUS_MODE,
668 CameraParameters::FOCUS_MODE_AUTO);
669
670 mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES,
671 preview_size_values.string());
672 mParameters.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES,
673 picture_size_values.string());
674 mParameters.set(CameraParameters::KEY_SUPPORTED_ANTIBANDING,
675 antibanding_values);
676 mParameters.set(CameraParameters::KEY_SUPPORTED_EFFECTS, effect_values);
Apurva Rajguru55562b02009-12-03 12:25:35 -0800677 mParameters.set(CameraParameters::KEY_SUPPORTED_AUTO_EXPOSURE, autoexposure_values);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800678 mParameters.set(CameraParameters::KEY_SUPPORTED_WHITE_BALANCE,
679 whitebalance_values);
680 mParameters.set(CameraParameters::KEY_SUPPORTED_FOCUS_MODES,
681 focus_mode_values);
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800682 mParameters.set(CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS,
683 picture_format_values);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800684
685 if (mSensorInfo.flash_enabled) {
686 mParameters.set(CameraParameters::KEY_FLASH_MODE,
687 CameraParameters::FLASH_MODE_OFF);
688 mParameters.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES,
689 flash_values);
690 }
691
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530692 mParameters.set("luma-adaptation", "18");
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800693 mParameters.set("zoom-supported", "true");
694 mParameters.set("max-zoom", MAX_ZOOM_LEVEL);
695 mParameters.set("zoom", 0);
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800696 mParameters.set(CameraParameters::KEY_PICTURE_FORMAT,
697 CameraParameters::PIXEL_FORMAT_JPEG);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800698
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530699 mParameters.set(CameraParameters::KEY_ISO_MODE,
700 CameraParameters::ISO_AUTO);
701 mParameters.set(CameraParameters::KEY_LENSSHADE,
702 CameraParameters::LENSSHADE_ENABLE);
703 mParameters.set(CameraParameters::KEY_SUPPORTED_ISO_MODES,
704 iso_values);
705 mParameters.set(CameraParameters::KEY_SUPPORTED_LENSSHADE_MODES,
706 lensshade_values);
707
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800708 if (setParameters(mParameters) != NO_ERROR) {
709 LOGE("Failed to set default parameters?!");
710 }
711
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -0800712 mUseOverlay = useOverlay();
713
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800714 LOGV("initDefaultParameters X");
715}
716
Srinivasan Kannan71229622009-12-04 12:05:58 -0800717void QualcommCameraHardware::findSensorType(){
718 mDimension.picture_width = DEFAULT_PICTURE_WIDTH;
719 mDimension.picture_height = DEFAULT_PICTURE_HEIGHT;
720 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
721 sizeof(cam_ctrl_dimension_t), &mDimension);
722 if (ret) {
723 unsigned int i;
724 for (i = 0; i < sizeof(sensorTypes) / sizeof(SensorType); i++) {
725 if (sensorTypes[i].rawPictureHeight
726 == mDimension.raw_picture_height) {
727 sensorType = sensorTypes + i;
728 return;
729 }
730 }
731 }
732 //default to 5 mp
733 sensorType = sensorTypes;
734 return;
735}
736
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800737#define ROUND_TO_PAGE(x) (((x)+0xfff)&~0xfff)
738
739bool QualcommCameraHardware::startCamera()
740{
741 LOGV("startCamera E");
742#if DLOPEN_LIBMMCAMERA
743 libmmcamera = ::dlopen("liboemcamera.so", RTLD_NOW);
744 LOGV("loading liboemcamera at %p", libmmcamera);
745 if (!libmmcamera) {
746 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
747 return false;
748 }
749
750 *(void **)&LINK_cam_frame =
751 ::dlsym(libmmcamera, "cam_frame");
752 *(void **)&LINK_camframe_terminate =
753 ::dlsym(libmmcamera, "camframe_terminate");
754
755 *(void **)&LINK_jpeg_encoder_init =
756 ::dlsym(libmmcamera, "jpeg_encoder_init");
757
758 *(void **)&LINK_jpeg_encoder_encode =
759 ::dlsym(libmmcamera, "jpeg_encoder_encode");
760
761 *(void **)&LINK_jpeg_encoder_join =
762 ::dlsym(libmmcamera, "jpeg_encoder_join");
763
764 *(void **)&LINK_mmcamera_camframe_callback =
765 ::dlsym(libmmcamera, "mmcamera_camframe_callback");
766
767 *LINK_mmcamera_camframe_callback = receive_camframe_callback;
768
769 *(void **)&LINK_mmcamera_jpegfragment_callback =
770 ::dlsym(libmmcamera, "mmcamera_jpegfragment_callback");
771
772 *LINK_mmcamera_jpegfragment_callback = receive_jpeg_fragment_callback;
773
774 *(void **)&LINK_mmcamera_jpeg_callback =
775 ::dlsym(libmmcamera, "mmcamera_jpeg_callback");
776
777 *LINK_mmcamera_jpeg_callback = receive_jpeg_callback;
778
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800779/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800780 *(void **)&LINK_mmcamera_shutter_callback =
781 ::dlsym(libmmcamera, "mmcamera_shutter_callback");
782
783 *LINK_mmcamera_shutter_callback = receive_shutter_callback;
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800784*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800785 *(void**)&LINK_jpeg_encoder_setMainImageQuality =
786 ::dlsym(libmmcamera, "jpeg_encoder_setMainImageQuality");
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800787/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800788 *(void**)&LINK_jpeg_encoder_setThumbnailQuality =
789 ::dlsym(libmmcamera, "jpeg_encoder_setThumbnailQuality");
790
791 *(void**)&LINK_jpeg_encoder_setRotation =
792 ::dlsym(libmmcamera, "jpeg_encoder_setRotation");
793
794 *(void**)&LINK_jpeg_encoder_setLocation =
795 ::dlsym(libmmcamera, "jpeg_encoder_setLocation");
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800796*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800797 *(void **)&LINK_cam_conf =
798 ::dlsym(libmmcamera, "cam_conf");
799
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800800/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800801 *(void **)&LINK_default_sensor_get_snapshot_sizes =
802 ::dlsym(libmmcamera, "default_sensor_get_snapshot_sizes");
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800803*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800804 *(void **)&LINK_launch_cam_conf_thread =
805 ::dlsym(libmmcamera, "launch_cam_conf_thread");
806
807 *(void **)&LINK_release_cam_conf_thread =
808 ::dlsym(libmmcamera, "release_cam_conf_thread");
809
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800810/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800811 *(void **)&LINK_zoom_crop_upscale =
812 ::dlsym(libmmcamera, "zoom_crop_upscale");
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800813*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800814
815#else
816 mmcamera_camframe_callback = receive_camframe_callback;
817 mmcamera_jpegfragment_callback = receive_jpeg_fragment_callback;
818 mmcamera_jpeg_callback = receive_jpeg_callback;
819 mmcamera_shutter_callback = receive_shutter_callback;
820#endif // DLOPEN_LIBMMCAMERA
821
822 /* The control thread is in libcamera itself. */
823 mCameraControlFd = open(MSM_CAMERA_CONTROL, O_RDWR);
824 if (mCameraControlFd < 0) {
825 LOGE("startCamera X: %s open failed: %s!",
826 MSM_CAMERA_CONTROL,
827 strerror(errno));
828 return false;
829 }
830
831 /* This will block until the control thread is launched. After that, sensor
832 * information becomes available.
833 */
834
835 if (LINK_launch_cam_conf_thread()) {
836 LOGE("failed to launch the camera config thread");
837 return false;
838 }
839
840 memset(&mSensorInfo, 0, sizeof(mSensorInfo));
841 if (ioctl(mCameraControlFd,
842 MSM_CAM_IOCTL_GET_SENSOR_INFO,
843 &mSensorInfo) < 0)
844 LOGW("%s: cannot retrieve sensor info!", __FUNCTION__);
845 else
846 LOGI("%s: camsensor name %s, flash %d", __FUNCTION__,
847 mSensorInfo.name, mSensorInfo.flash_enabled);
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800848/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800849 picture_sizes = LINK_default_sensor_get_snapshot_sizes(&PICTURE_SIZE_COUNT);
850 if (!picture_sizes || !PICTURE_SIZE_COUNT) {
851 LOGE("startCamera X: could not get snapshot sizes");
852 return false;
853 }
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800854*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800855 LOGV("startCamera X");
856 return true;
857}
858
859status_t QualcommCameraHardware::dump(int fd,
860 const Vector<String16>& args) const
861{
862 const size_t SIZE = 256;
863 char buffer[SIZE];
864 String8 result;
865
866 // Dump internal primitives.
867 result.append("QualcommCameraHardware::dump");
868 snprintf(buffer, 255, "mMsgEnabled (%d)\n", mMsgEnabled);
869 result.append(buffer);
870 int width, height;
871 mParameters.getPreviewSize(&width, &height);
872 snprintf(buffer, 255, "preview width(%d) x height (%d)\n", width, height);
873 result.append(buffer);
874 mParameters.getPictureSize(&width, &height);
875 snprintf(buffer, 255, "raw width(%d) x height (%d)\n", width, height);
876 result.append(buffer);
877 snprintf(buffer, 255,
878 "preview frame size(%d), raw size (%d), jpeg size (%d) "
879 "and jpeg max size (%d)\n", mPreviewFrameSize, mRawSize,
880 mJpegSize, mJpegMaxSize);
881 result.append(buffer);
882 write(fd, result.string(), result.size());
883
884 // Dump internal objects.
885 if (mPreviewHeap != 0) {
886 mPreviewHeap->dump(fd, args);
887 }
888 if (mRawHeap != 0) {
889 mRawHeap->dump(fd, args);
890 }
891 if (mJpegHeap != 0) {
892 mJpegHeap->dump(fd, args);
893 }
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800894 if(mRawSnapshotAshmemHeap != 0 ){
895 mRawSnapshotAshmemHeap->dump(fd, args);
896 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800897 mParameters.dump(fd, args);
898 return NO_ERROR;
899}
900
901static bool native_set_afmode(int camfd, isp3a_af_mode_t af_type)
902{
903 int rc;
904 struct msm_ctrl_cmd ctrlCmd;
905
906 ctrlCmd.timeout_ms = 5000;
907 ctrlCmd.type = CAMERA_SET_PARM_AUTO_FOCUS;
908 ctrlCmd.length = sizeof(af_type);
909 ctrlCmd.value = &af_type;
910 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
911
912 if ((rc = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0)
913 LOGE("native_set_afmode: ioctl fd %d error %s\n",
914 camfd,
915 strerror(errno));
916
917 LOGV("native_set_afmode: ctrlCmd.status == %d\n", ctrlCmd.status);
918 return rc >= 0 && ctrlCmd.status == CAMERA_EXIT_CB_DONE;
919}
920
921static bool native_cancel_afmode(int camfd, int af_fd)
922{
923 int rc;
924 struct msm_ctrl_cmd ctrlCmd;
925
926 ctrlCmd.timeout_ms = 0;
927 ctrlCmd.type = CAMERA_AUTO_FOCUS_CANCEL;
928 ctrlCmd.length = 0;
929 ctrlCmd.value = NULL;
930 ctrlCmd.resp_fd = -1; // there's no response fd
931
932 if ((rc = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND_2, &ctrlCmd)) < 0)
933 {
934 LOGE("native_cancel_afmode: ioctl fd %d error %s\n",
935 camfd,
936 strerror(errno));
937 return false;
938 }
939
940 return true;
941}
942
943static bool native_start_preview(int camfd)
944{
945 struct msm_ctrl_cmd ctrlCmd;
946
947 ctrlCmd.timeout_ms = 5000;
948 ctrlCmd.type = CAMERA_START_PREVIEW;
949 ctrlCmd.length = 0;
950 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
951
952 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
953 LOGE("native_start_preview: MSM_CAM_IOCTL_CTRL_COMMAND fd %d error %s",
954 camfd,
955 strerror(errno));
956 return false;
957 }
958
959 return true;
960}
961
962static bool native_get_picture (int camfd, common_crop_t *crop)
963{
964 struct msm_ctrl_cmd ctrlCmd;
965
966 ctrlCmd.timeout_ms = 5000;
967 ctrlCmd.length = sizeof(common_crop_t);
968 ctrlCmd.value = crop;
969
970 if(ioctl(camfd, MSM_CAM_IOCTL_GET_PICTURE, &ctrlCmd) < 0) {
971 LOGE("native_get_picture: MSM_CAM_IOCTL_GET_PICTURE fd %d error %s",
972 camfd,
973 strerror(errno));
974 return false;
975 }
976
977 LOGV("crop: in1_w %d", crop->in1_w);
978 LOGV("crop: in1_h %d", crop->in1_h);
979 LOGV("crop: out1_w %d", crop->out1_w);
980 LOGV("crop: out1_h %d", crop->out1_h);
981
982 LOGV("crop: in2_w %d", crop->in2_w);
983 LOGV("crop: in2_h %d", crop->in2_h);
984 LOGV("crop: out2_w %d", crop->out2_w);
985 LOGV("crop: out2_h %d", crop->out2_h);
986
987 LOGV("crop: update %d", crop->update_flag);
988
989 return true;
990}
991
992static bool native_stop_preview(int camfd)
993{
994 struct msm_ctrl_cmd ctrlCmd;
995 ctrlCmd.timeout_ms = 5000;
996 ctrlCmd.type = CAMERA_STOP_PREVIEW;
997 ctrlCmd.length = 0;
998 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
999
1000 if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1001 LOGE("native_stop_preview: ioctl fd %d error %s",
1002 camfd,
1003 strerror(errno));
1004 return false;
1005 }
1006
1007 return true;
1008}
1009
1010static bool native_prepare_snapshot(int camfd)
1011{
1012 int ioctlRetVal = true;
1013 struct msm_ctrl_cmd ctrlCmd;
1014
1015 ctrlCmd.timeout_ms = 1000;
1016 ctrlCmd.type = CAMERA_PREPARE_SNAPSHOT;
1017 ctrlCmd.length = 0;
1018 ctrlCmd.value = NULL;
1019 ctrlCmd.resp_fd = camfd;
1020
1021 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1022 LOGE("native_prepare_snapshot: ioctl fd %d error %s",
1023 camfd,
1024 strerror(errno));
1025 return false;
1026 }
1027 return true;
1028}
1029
1030static bool native_start_snapshot(int camfd)
1031{
1032 struct msm_ctrl_cmd ctrlCmd;
1033
1034 ctrlCmd.timeout_ms = 5000;
1035 ctrlCmd.type = CAMERA_START_SNAPSHOT;
1036 ctrlCmd.length = 0;
1037 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1038
1039 if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1040 LOGE("native_start_snapshot: ioctl fd %d error %s",
1041 camfd,
1042 strerror(errno));
1043 return false;
1044 }
1045
1046 return true;
1047}
1048
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001049static bool native_start_raw_snapshot(int camfd)
1050{
1051 int ret;
1052 struct msm_ctrl_cmd ctrlCmd;
1053
1054 ctrlCmd.timeout_ms = 1000;
1055 ctrlCmd.type = CAMERA_START_RAW_SNAPSHOT;
1056 ctrlCmd.length = 0;
1057 ctrlCmd.value = NULL;
1058 ctrlCmd.resp_fd = camfd;
1059
1060 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1061 LOGE("native_start_raw_snapshot: ioctl failed. ioctl return value "\
1062 "is %d \n", ret);
1063 return false;
1064 }
1065 return true;
1066}
1067
1068
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001069static bool native_stop_snapshot (int camfd)
1070{
1071 struct msm_ctrl_cmd ctrlCmd;
1072
1073 ctrlCmd.timeout_ms = 0;
1074 ctrlCmd.type = CAMERA_STOP_SNAPSHOT;
1075 ctrlCmd.length = 0;
1076 ctrlCmd.resp_fd = -1;
1077
1078 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND_2, &ctrlCmd) < 0) {
1079 LOGE("native_stop_snapshot: ioctl fd %d error %s",
1080 camfd,
1081 strerror(errno));
1082 return false;
1083 }
1084
1085 return true;
1086}
1087
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001088static rat_t latitude[3];
1089static rat_t longitude[3];
1090static char lonref[2];
1091static char latref[2];
1092static char dateTime[20];
1093static rat_t altitude;
1094
1095static void addExifTag(exif_tag_id_t tagid, exif_tag_type_t type,
1096 uint32_t count, uint8_t copy, void *data) {
1097
1098 if(exif_table_numEntries == MAX_EXIF_TABLE_ENTRIES) {
1099 LOGE("Number of entries exceeded limit");
1100 return;
1101 }
1102
1103 int index = exif_table_numEntries;
1104 exif_data[index].tag_id = tagid;
1105 exif_data[index].tag_entry.type = type;
1106 exif_data[index].tag_entry.count = count;
1107 exif_data[index].tag_entry.copy = copy;
1108 if((type == EXIF_RATIONAL) && (count > 1))
1109 exif_data[index].tag_entry.data._rats = (rat_t *)data;
1110 if((type == EXIF_RATIONAL) && (count == 1))
1111 exif_data[index].tag_entry.data._rat = *(rat_t *)data;
1112 else if(type == EXIF_ASCII)
1113 exif_data[index].tag_entry.data._ascii = (char *)data;
1114 else if(type == EXIF_BYTE)
1115 exif_data[index].tag_entry.data._byte = *(uint8_t *)data;
1116
1117 // Increase number of entries
1118 exif_table_numEntries++;
1119}
1120
1121static void parseLatLong(const char *latlonString, int *pDegrees,
1122 int *pMinutes, int *pSeconds ) {
1123
1124 double value = atof(latlonString);
1125 value = fabs(value);
1126 int degrees = (int) value;
1127
1128 double remainder = value - degrees;
1129 int minutes = (int) (remainder * 60);
1130 int seconds = (int) (((remainder * 60) - minutes) * 60 * 1000);
1131
1132 *pDegrees = degrees;
1133 *pMinutes = minutes;
1134 *pSeconds = seconds;
1135}
1136
1137static void setLatLon(exif_tag_id_t tag, const char *latlonString) {
1138
1139 int degrees, minutes, seconds;
1140
1141 parseLatLong(latlonString, &degrees, &minutes, &seconds);
1142
1143 rat_t value[3] = { {degrees, 1},
1144 {minutes, 1},
1145 {seconds, 1000} };
1146
1147 if(tag == EXIFTAGID_GPS_LATITUDE) {
1148 memcpy(latitude, value, sizeof(latitude));
1149 addExifTag(EXIFTAGID_GPS_LATITUDE, EXIF_RATIONAL, 3,
1150 1, (void *)latitude);
1151 } else {
1152 memcpy(longitude, value, sizeof(longitude));
1153 addExifTag(EXIFTAGID_GPS_LONGITUDE, EXIF_RATIONAL, 3,
1154 1, (void *)longitude);
1155 }
1156}
1157
1158void QualcommCameraHardware::setGpsParameters() {
1159 const char *str = NULL;
1160
1161 //Set Latitude
1162 str = mParameters.get(CameraParameters::KEY_GPS_LATITUDE);
1163 if(str != NULL) {
1164 setLatLon(EXIFTAGID_GPS_LATITUDE, str);
1165 //set Latitude Ref
1166 str = NULL;
1167 str = mParameters.get(CameraParameters::KEY_GPS_LATITUDE_REF);
1168 if(str != NULL) {
1169 strncpy(latref, str, 1);
1170 latref[1] = '\0';
1171 addExifTag(EXIFTAGID_GPS_LATITUDE_REF, EXIF_ASCII, 2,
1172 1, (void *)latref);
1173 }
1174 }
1175
1176 //set Longitude
1177 str = NULL;
1178 str = mParameters.get(CameraParameters::KEY_GPS_LONGITUDE);
1179 if(str != NULL) {
1180 setLatLon(EXIFTAGID_GPS_LONGITUDE, str);
1181 //set Longitude Ref
1182 str = NULL;
1183 str = mParameters.get(CameraParameters::KEY_GPS_LONGITUDE_REF);
1184 if(str != NULL) {
1185 strncpy(lonref, str, 1);
1186 lonref[1] = '\0';
1187 addExifTag(EXIFTAGID_GPS_LONGITUDE_REF, EXIF_ASCII, 2,
1188 1, (void *)lonref);
1189 }
1190 }
1191
1192 //set Altitude
1193 str = NULL;
1194 str = mParameters.get(CameraParameters::KEY_GPS_ALTITUDE);
1195 if(str != NULL) {
1196 int value = atoi(str);
1197 rat_t alt_value = {value, 1000};
1198 memcpy(&altitude, &alt_value, sizeof(altitude));
1199 addExifTag(EXIFTAGID_GPS_ALTITUDE, EXIF_RATIONAL, 1,
1200 1, (void *)&altitude);
1201 //set AltitudeRef
1202 int ref = mParameters.getInt(CameraParameters::KEY_GPS_ALTITUDE_REF);
1203 if( !(ref < 0 || ref > 1) )
1204 addExifTag(EXIFTAGID_GPS_ALTITUDE_REF, EXIF_BYTE, 1,
1205 1, (void *)&ref);
1206 }
1207
1208
1209}
1210
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001211bool QualcommCameraHardware::native_jpeg_encode(void)
1212{
1213 int jpeg_quality = mParameters.getInt("jpeg-quality");
1214 if (jpeg_quality >= 0) {
1215 LOGV("native_jpeg_encode, current jpeg main img quality =%d",
1216 jpeg_quality);
1217 if(!LINK_jpeg_encoder_setMainImageQuality(jpeg_quality)) {
1218 LOGE("native_jpeg_encode set jpeg-quality failed");
1219 return false;
1220 }
1221 }
1222
1223 int thumbnail_quality = mParameters.getInt("jpeg-thumbnail-quality");
1224 if (thumbnail_quality >= 0) {
1225 LOGV("native_jpeg_encode, current jpeg thumbnail quality =%d",
1226 thumbnail_quality);
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001227/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001228 if(!LINK_jpeg_encoder_setThumbnailQuality(thumbnail_quality)) {
1229 LOGE("native_jpeg_encode set thumbnail-quality failed");
1230 return false;
1231 }
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001232*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001233 }
1234
1235 int rotation = mParameters.getInt("rotation");
1236 if (rotation >= 0) {
1237 LOGV("native_jpeg_encode, rotation = %d", rotation);
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001238/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001239 if(!LINK_jpeg_encoder_setRotation(rotation)) {
1240 LOGE("native_jpeg_encode set rotation failed");
1241 return false;
1242 }
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001243*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001244 }
1245
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001246// jpeg_set_location();
1247 if(mParameters.getInt(CameraParameters::KEY_GPS_STATUS) == 1) {
1248 setGpsParameters();
1249 }
1250 //set TimeStamp
1251 const char *str = mParameters.get(CameraParameters::KEY_EXIF_DATETIME);
1252 if(str != NULL) {
1253 strncpy(dateTime, str, 19);
1254 dateTime[19] = '\0';
1255 addExifTag(EXIFTAGID_EXIF_DATE_TIME_ORIGINAL, EXIF_ASCII,
1256 20, 1, (void *)dateTime);
1257 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001258
1259 if (!LINK_jpeg_encoder_encode(&mDimension,
1260 (uint8_t *)mThumbnailHeap->mHeap->base(),
1261 mThumbnailHeap->mHeap->getHeapID(),
1262 (uint8_t *)mRawHeap->mHeap->base(),
1263 mRawHeap->mHeap->getHeapID(),
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001264 &mCrop, exif_data, exif_table_numEntries)) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001265 LOGE("native_jpeg_encode: jpeg_encoder_encode failed.");
1266 return false;
1267 }
1268 return true;
1269}
1270
1271bool QualcommCameraHardware::native_set_parm(
1272 cam_ctrl_type type, uint16_t length, void *value)
1273{
1274 struct msm_ctrl_cmd ctrlCmd;
1275
1276 ctrlCmd.timeout_ms = 5000;
1277 ctrlCmd.type = (uint16_t)type;
1278 ctrlCmd.length = length;
1279 // FIXME: this will be put in by the kernel
1280 ctrlCmd.resp_fd = mCameraControlFd;
1281 ctrlCmd.value = value;
1282
1283 LOGV("%s: fd %d, type %d, length %d", __FUNCTION__,
1284 mCameraControlFd, type, length);
1285 if (ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0 ||
1286 ctrlCmd.status != CAM_CTRL_SUCCESS) {
1287 LOGE("%s: error (%s): fd %d, type %d, length %d, status %d",
1288 __FUNCTION__, strerror(errno),
1289 mCameraControlFd, type, length, ctrlCmd.status);
1290 return false;
1291 }
1292 return true;
1293}
1294
1295void QualcommCameraHardware::jpeg_set_location()
1296{
1297 bool encode_location = true;
1298 camera_position_type pt;
1299
1300#define PARSE_LOCATION(what,type,fmt,desc) do { \
1301 pt.what = 0; \
1302 const char *what##_str = mParameters.get("gps-"#what); \
1303 LOGV("GPS PARM %s --> [%s]", "gps-"#what, what##_str); \
1304 if (what##_str) { \
1305 type what = 0; \
1306 if (sscanf(what##_str, fmt, &what) == 1) \
1307 pt.what = what; \
1308 else { \
1309 LOGE("GPS " #what " %s could not" \
1310 " be parsed as a " #desc, what##_str); \
1311 encode_location = false; \
1312 } \
1313 } \
1314 else { \
1315 LOGV("GPS " #what " not specified: " \
1316 "defaulting to zero in EXIF header."); \
1317 encode_location = false; \
1318 } \
1319 } while(0)
1320
1321 PARSE_LOCATION(timestamp, long, "%ld", "long");
1322 if (!pt.timestamp) pt.timestamp = time(NULL);
1323 PARSE_LOCATION(altitude, short, "%hd", "short");
1324 PARSE_LOCATION(latitude, double, "%lf", "double float");
1325 PARSE_LOCATION(longitude, double, "%lf", "double float");
1326
1327#undef PARSE_LOCATION
1328
1329 if (encode_location) {
1330 LOGD("setting image location ALT %d LAT %lf LON %lf",
1331 pt.altitude, pt.latitude, pt.longitude);
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001332/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001333 if (!LINK_jpeg_encoder_setLocation(&pt)) {
1334 LOGE("jpeg_set_location: LINK_jpeg_encoder_setLocation failed.");
1335 }
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001336*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001337 }
1338 else LOGV("not setting image location");
1339}
1340
1341void QualcommCameraHardware::runFrameThread(void *data)
1342{
1343 LOGV("runFrameThread E");
1344
1345 int cnt;
1346
1347#if DLOPEN_LIBMMCAMERA
1348 // We need to maintain a reference to libqcamera.so for the duration of the
1349 // frame thread, because we do not know when it will exit relative to the
1350 // lifetime of this object. We do not want to dlclose() libqcamera while
1351 // LINK_cam_frame is still running.
1352 void *libhandle = ::dlopen("liboemcamera.so", RTLD_NOW);
1353 LOGV("FRAME: loading libqcamera at %p", libhandle);
1354 if (!libhandle) {
1355 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
1356 }
1357 if (libhandle)
1358#endif
1359 {
1360 LINK_cam_frame(data);
1361 }
1362
1363 mPreviewHeap.clear();
1364
1365#if DLOPEN_LIBMMCAMERA
1366 if (libhandle) {
1367 ::dlclose(libhandle);
1368 LOGV("FRAME: dlclose(libqcamera)");
1369 }
1370#endif
1371
1372 mFrameThreadWaitLock.lock();
1373 mFrameThreadRunning = false;
1374 mFrameThreadWait.signal();
1375 mFrameThreadWaitLock.unlock();
1376
1377 LOGV("runFrameThread X");
1378}
1379
1380void *frame_thread(void *user)
1381{
1382 LOGD("frame_thread E");
1383 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
1384 if (obj != 0) {
1385 obj->runFrameThread(user);
1386 }
1387 else LOGW("not starting frame thread: the object went away!");
1388 LOGD("frame_thread X");
1389 return NULL;
1390}
1391
1392bool QualcommCameraHardware::initPreview()
1393{
1394 // See comments in deinitPreview() for why we have to wait for the frame
1395 // thread here, and why we can't use pthread_join().
1396 int previewWidth, previewHeight;
1397 mParameters.getPreviewSize(&previewWidth, &previewHeight);
1398 LOGI("initPreview E: preview size=%dx%d", previewWidth, previewHeight);
1399 mFrameThreadWaitLock.lock();
1400 while (mFrameThreadRunning) {
1401 LOGV("initPreview: waiting for old frame thread to complete.");
1402 mFrameThreadWait.wait(mFrameThreadWaitLock);
1403 LOGV("initPreview: old frame thread completed.");
1404 }
1405 mFrameThreadWaitLock.unlock();
1406
1407 mSnapshotThreadWaitLock.lock();
1408 while (mSnapshotThreadRunning) {
1409 LOGV("initPreview: waiting for old snapshot thread to complete.");
1410 mSnapshotThreadWait.wait(mSnapshotThreadWaitLock);
1411 LOGV("initPreview: old snapshot thread completed.");
1412 }
1413 mSnapshotThreadWaitLock.unlock();
1414
1415 int cnt = 0;
1416 mPreviewFrameSize = previewWidth * previewHeight * 3/2;
1417 mPreviewHeap = new PmemPool("/dev/pmem_adsp",
1418 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
1419 mCameraControlFd,
1420 MSM_PMEM_OUTPUT2,
1421 mPreviewFrameSize,
1422 kPreviewBufferCount,
1423 mPreviewFrameSize,
1424 "preview");
1425
1426 if (!mPreviewHeap->initialized()) {
1427 mPreviewHeap.clear();
1428 LOGE("initPreview X: could not initialize preview heap.");
1429 return false;
1430 }
1431
1432 // mDimension will be filled with thumbnail_width, thumbnail_height,
1433 // orig_picture_dx, and orig_picture_dy after this function call. We need to
1434 // keep it for jpeg_encoder_encode.
1435 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
1436 sizeof(cam_ctrl_dimension_t), &mDimension);
1437
1438 if (ret) {
1439 for (cnt = 0; cnt < kPreviewBufferCount; cnt++) {
1440 frames[cnt].fd = mPreviewHeap->mHeap->getHeapID();
1441 frames[cnt].buffer =
1442 (uint32_t)mPreviewHeap->mHeap->base() + mPreviewHeap->mAlignedBufferSize * cnt;
1443 frames[cnt].y_off = 0;
1444 frames[cnt].cbcr_off = previewWidth * previewHeight;
1445 frames[cnt].path = MSM_FRAME_ENC;
1446 }
1447
1448 mFrameThreadWaitLock.lock();
1449 pthread_attr_t attr;
1450 pthread_attr_init(&attr);
1451 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1452 mFrameThreadRunning = !pthread_create(&mFrameThread,
1453 &attr,
1454 frame_thread,
1455 &frames[kPreviewBufferCount-1]);
1456 ret = mFrameThreadRunning;
1457 mFrameThreadWaitLock.unlock();
1458 }
1459
1460 LOGV("initPreview X: %d", ret);
1461 return ret;
1462}
1463
1464void QualcommCameraHardware::deinitPreview(void)
1465{
1466 LOGI("deinitPreview E");
1467
1468 // When we call deinitPreview(), we signal to the frame thread that it
1469 // needs to exit, but we DO NOT WAIT for it to complete here. The problem
1470 // is that deinitPreview is sometimes called from the frame-thread's
1471 // callback, when the refcount on the Camera client reaches zero. If we
1472 // called pthread_join(), we would deadlock. So, we just call
1473 // LINK_camframe_terminate() in deinitPreview(), which makes sure that
1474 // after the preview callback returns, the camframe thread will exit. We
1475 // could call pthread_join() in initPreview() to join the last frame
1476 // thread. However, we would also have to call pthread_join() in release
1477 // as well, shortly before we destroy the object; this would cause the same
1478 // deadlock, since release(), like deinitPreview(), may also be called from
1479 // the frame-thread's callback. This we have to make the frame thread
1480 // detached, and use a separate mechanism to wait for it to complete.
1481
1482 if (LINK_camframe_terminate() < 0)
1483 LOGE("failed to stop the camframe thread: %s",
1484 strerror(errno));
1485 LOGI("deinitPreview X");
1486}
1487
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001488bool QualcommCameraHardware::initRawSnapshot()
1489{
1490 LOGV("initRawSnapshot E");
1491
1492 //get width and height from Dimension Object
1493 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
1494 sizeof(cam_ctrl_dimension_t), &mDimension);
1495
1496 if(!ret){
1497 LOGE("initRawSnapshot X: failed to set dimension");
1498 return false;
1499 }
1500 int rawSnapshotSize = mDimension.raw_picture_height *
1501 mDimension.raw_picture_width;
1502
1503 LOGV("raw_snapshot_buffer_size = %d, raw_picture_height = %d, "\
1504 "raw_picture_width = %d",
1505 rawSnapshotSize, mDimension.raw_picture_height,
1506 mDimension.raw_picture_width);
1507
1508 if (mRawSnapShotPmemHeap != NULL) {
1509 LOGV("initRawSnapshot: clearing old mRawSnapShotPmemHeap.");
1510 mRawSnapShotPmemHeap.clear();
1511 }
1512
1513 //Pmem based pool for Camera Driver
1514 mRawSnapShotPmemHeap = new PmemPool("/dev/pmem_adsp",
1515 MemoryHeapBase::READ_ONLY,
1516 mCameraControlFd,
1517 MSM_PMEM_RAW_MAINIMG,
1518 rawSnapshotSize,
1519 1,
1520 rawSnapshotSize,
1521 "raw pmem snapshot camera");
1522
1523 if (!mRawSnapShotPmemHeap->initialized()) {
1524 mRawSnapShotPmemHeap.clear();
1525 LOGE("initRawSnapshot X: error initializing mRawSnapshotHeap");
1526 return false;
1527 }
1528 LOGV("initRawSnapshot X");
1529 return true;
1530
1531}
1532
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001533bool QualcommCameraHardware::initRaw(bool initJpegHeap)
1534{
1535 int rawWidth, rawHeight;
Apurva Rajguru8d1773b2009-12-02 14:21:23 -08001536 char value[PROPERTY_VALUE_MAX];
1537
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001538 mParameters.getPictureSize(&rawWidth, &rawHeight);
1539 LOGV("initRaw E: picture size=%dx%d", rawWidth, rawHeight);
1540
1541 // mDimension will be filled with thumbnail_width, thumbnail_height,
1542 // orig_picture_dx, and orig_picture_dy after this function call. We need to
1543 // keep it for jpeg_encoder_encode.
1544 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
1545 sizeof(cam_ctrl_dimension_t), &mDimension);
1546 if(!ret) {
1547 LOGE("initRaw X: failed to set dimension");
1548 return false;
1549 }
1550
1551 if (mJpegHeap != NULL) {
1552 LOGV("initRaw: clearing old mJpegHeap.");
1553 mJpegHeap.clear();
1554 }
1555
1556 // Snapshot
1557 mRawSize = rawWidth * rawHeight * 3 / 2;
Apurva Rajguru8d1773b2009-12-02 14:21:23 -08001558 property_get("ro.product.device",value," ");
1559
1560 if(!strcmp(value,"msm7627_surf"))
1561 mJpegMaxSize = CEILING16(rawWidth) * CEILING16(rawHeight) * 3 / 2;
1562 else
1563 mJpegMaxSize = rawWidth * rawHeight * 3 / 2;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001564
1565 LOGV("initRaw: initializing mRawHeap.");
1566 mRawHeap =
1567 new PmemPool("/dev/pmem_camera",
1568 MemoryHeapBase::READ_ONLY,
1569 mCameraControlFd,
1570 MSM_PMEM_MAINIMG,
1571 mJpegMaxSize,
1572 kRawBufferCount,
1573 mRawSize,
1574 "snapshot camera");
1575
1576 if (!mRawHeap->initialized()) {
1577 LOGE("initRaw X failed with pmem_camera, trying with pmem_adsp");
1578 mRawHeap =
1579 new PmemPool("/dev/pmem_adsp",
1580 MemoryHeapBase::READ_ONLY,
1581 mCameraControlFd,
1582 MSM_PMEM_MAINIMG,
1583 mJpegMaxSize,
1584 kRawBufferCount,
1585 mRawSize,
1586 "snapshot camera");
1587 if (!mRawHeap->initialized()) {
1588 mRawHeap.clear();
1589 LOGE("initRaw X: error initializing mRawHeap");
1590 return false;
1591 }
1592 }
1593
1594 LOGV("do_mmap snapshot pbuf = %p, pmem_fd = %d",
1595 (uint8_t *)mRawHeap->mHeap->base(), mRawHeap->mHeap->getHeapID());
1596
1597 // Jpeg
1598
1599 if (initJpegHeap) {
1600 LOGV("initRaw: initializing mJpegHeap.");
1601 mJpegHeap =
1602 new AshmemPool(mJpegMaxSize,
1603 kJpegBufferCount,
1604 0, // we do not know how big the picture will be
1605 "jpeg");
1606
1607 if (!mJpegHeap->initialized()) {
1608 mJpegHeap.clear();
1609 mRawHeap.clear();
1610 LOGE("initRaw X failed: error initializing mJpegHeap.");
1611 return false;
1612 }
1613
1614 // Thumbnails
1615
1616 mThumbnailHeap =
1617 new PmemPool("/dev/pmem_adsp",
1618 MemoryHeapBase::READ_ONLY,
1619 mCameraControlFd,
1620 MSM_PMEM_THUMBNAIL,
1621 THUMBNAIL_BUFFER_SIZE,
1622 1,
1623 THUMBNAIL_BUFFER_SIZE,
1624 "thumbnail");
1625
1626 if (!mThumbnailHeap->initialized()) {
1627 mThumbnailHeap.clear();
1628 mJpegHeap.clear();
1629 mRawHeap.clear();
1630 LOGE("initRaw X failed: error initializing mThumbnailHeap.");
1631 return false;
1632 }
1633 }
1634
1635 LOGV("initRaw X");
1636 return true;
1637}
1638
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001639
1640void QualcommCameraHardware::deinitRawSnapshot()
1641{
1642 LOGV("deinitRawSnapshot E");
1643 mRawSnapShotPmemHeap.clear();
1644 mRawSnapshotAshmemHeap.clear();
1645 LOGV("deinitRawSnapshot X");
1646}
1647
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001648void QualcommCameraHardware::deinitRaw()
1649{
1650 LOGV("deinitRaw E");
1651
1652 mThumbnailHeap.clear();
1653 mJpegHeap.clear();
1654 mRawHeap.clear();
1655 mDisplayHeap.clear();
1656
1657 LOGV("deinitRaw X");
1658}
1659
1660void QualcommCameraHardware::release()
1661{
1662 LOGD("release E");
1663 Mutex::Autolock l(&mLock);
1664
1665#if DLOPEN_LIBMMCAMERA
1666 if (libmmcamera == NULL) {
1667 LOGE("ERROR: multiple release!");
1668 return;
1669 }
1670#else
1671#warning "Cannot detect multiple release when not dlopen()ing libqcamera!"
1672#endif
1673
1674 int cnt, rc;
1675 struct msm_ctrl_cmd ctrlCmd;
1676
1677 if (mCameraRunning) {
1678 if(mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME)) {
1679 mRecordFrameLock.lock();
1680 mReleasedRecordingFrame = true;
1681 mRecordWait.signal();
1682 mRecordFrameLock.unlock();
1683 }
1684 stopPreviewInternal();
1685 }
1686
1687 LINK_jpeg_encoder_join();
1688 deinitRaw();
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001689 deinitRawSnapshot();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001690
1691 ctrlCmd.timeout_ms = 5000;
1692 ctrlCmd.length = 0;
1693 ctrlCmd.type = (uint16_t)CAMERA_EXIT;
1694 ctrlCmd.resp_fd = mCameraControlFd; // FIXME: this will be put in by the kernel
1695 if (ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0)
1696 LOGE("ioctl CAMERA_EXIT fd %d error %s",
1697 mCameraControlFd, strerror(errno));
1698
1699 LINK_release_cam_conf_thread();
1700
1701 close(mCameraControlFd);
1702 mCameraControlFd = -1;
1703
1704#if DLOPEN_LIBMMCAMERA
1705 if (libmmcamera) {
1706 ::dlclose(libmmcamera);
1707 LOGV("dlclose(libqcamera)");
1708 libmmcamera = NULL;
1709 }
1710#endif
1711
1712 Mutex::Autolock lock(&singleton_lock);
1713 singleton_releasing = true;
1714
1715 LOGD("release X");
1716}
1717
1718QualcommCameraHardware::~QualcommCameraHardware()
1719{
1720 LOGD("~QualcommCameraHardware E");
1721 Mutex::Autolock lock(&singleton_lock);
1722 singleton.clear();
1723 singleton_releasing = false;
1724 singleton_wait.signal();
1725 LOGD("~QualcommCameraHardware X");
1726}
1727
1728sp<IMemoryHeap> QualcommCameraHardware::getRawHeap() const
1729{
1730 LOGV("getRawHeap");
1731 return mDisplayHeap != NULL ? mDisplayHeap->mHeap : NULL;
1732}
1733
1734sp<IMemoryHeap> QualcommCameraHardware::getPreviewHeap() const
1735{
1736 LOGV("getPreviewHeap");
1737 return mPreviewHeap != NULL ? mPreviewHeap->mHeap : NULL;
1738}
1739
1740status_t QualcommCameraHardware::startPreviewInternal()
1741{
1742 if(mCameraRunning) {
1743 LOGV("startPreview X: preview already running.");
1744 return NO_ERROR;
1745 }
1746
1747 if (!mPreviewInitialized) {
1748 mPreviewInitialized = initPreview();
1749 if (!mPreviewInitialized) {
1750 LOGE("startPreview X initPreview failed. Not starting preview.");
1751 return UNKNOWN_ERROR;
1752 }
1753 }
1754
1755 mCameraRunning = native_start_preview(mCameraControlFd);
1756 if(!mCameraRunning) {
1757 deinitPreview();
1758 mPreviewInitialized = false;
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08001759 mOverlay = NULL;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001760 LOGE("startPreview X: native_start_preview failed!");
1761 return UNKNOWN_ERROR;
1762 }
1763
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001764 //Reset the Gps Information
1765 exif_table_numEntries = 0;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001766 LOGV("startPreview X");
1767 return NO_ERROR;
1768}
1769
1770status_t QualcommCameraHardware::startPreview()
1771{
1772 LOGV("startPreview E");
1773 Mutex::Autolock l(&mLock);
1774 return startPreviewInternal();
1775}
1776
1777void QualcommCameraHardware::stopPreviewInternal()
1778{
1779 LOGV("stopPreviewInternal E: %d", mCameraRunning);
1780 if (mCameraRunning) {
1781 // Cancel auto focus.
1782 {
1783 if (mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS)) {
1784 cancelAutoFocusInternal();
1785 }
1786 }
1787
1788 mCameraRunning = !native_stop_preview(mCameraControlFd);
1789 if (!mCameraRunning && mPreviewInitialized) {
1790 deinitPreview();
1791 mPreviewInitialized = false;
1792 }
1793 else LOGE("stopPreviewInternal: failed to stop preview");
1794 }
1795 LOGV("stopPreviewInternal X: %d", mCameraRunning);
1796}
1797
1798void QualcommCameraHardware::stopPreview()
1799{
1800 LOGV("stopPreview: E");
1801 Mutex::Autolock l(&mLock);
1802 {
1803 if (mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME))
1804 return;
1805 }
1806 stopPreviewInternal();
1807 LOGV("stopPreview: X");
1808}
1809
1810void QualcommCameraHardware::runAutoFocus()
1811{
1812 bool status = true;
1813 void *libhandle = NULL;
Srinivasan Kannan71229622009-12-04 12:05:58 -08001814 isp3a_af_mode_t afMode;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001815
1816 mAutoFocusThreadLock.lock();
1817 // Skip autofocus if focus mode is infinity.
1818 if (strcmp(mParameters.get(CameraParameters::KEY_FOCUS_MODE),
1819 CameraParameters::FOCUS_MODE_INFINITY) == 0) {
1820 goto done;
1821 }
1822
1823 mAutoFocusFd = open(MSM_CAMERA_CONTROL, O_RDWR);
1824 if (mAutoFocusFd < 0) {
1825 LOGE("autofocus: cannot open %s: %s",
1826 MSM_CAMERA_CONTROL,
1827 strerror(errno));
1828 mAutoFocusThreadRunning = false;
1829 mAutoFocusThreadLock.unlock();
1830 return;
1831 }
1832
1833#if DLOPEN_LIBMMCAMERA
1834 // We need to maintain a reference to libqcamera.so for the duration of the
1835 // AF thread, because we do not know when it will exit relative to the
1836 // lifetime of this object. We do not want to dlclose() libqcamera while
1837 // LINK_cam_frame is still running.
1838 libhandle = ::dlopen("liboemcamera.so", RTLD_NOW);
1839 LOGV("AF: loading libqcamera at %p", libhandle);
1840 if (!libhandle) {
1841 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
1842 close(mAutoFocusFd);
1843 mAutoFocusFd = -1;
1844 mAutoFocusThreadRunning = false;
1845 mAutoFocusThreadLock.unlock();
1846 return;
1847 }
1848#endif
1849
Srinivasan Kannan71229622009-12-04 12:05:58 -08001850 afMode = (isp3a_af_mode_t)attr_lookup(focus_modes,
1851 sizeof(focus_modes) / sizeof(str_map),
1852 mParameters.get(CameraParameters::KEY_FOCUS_MODE));
1853
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001854 /* This will block until either AF completes or is cancelled. */
Srinivasan Kannan71229622009-12-04 12:05:58 -08001855 LOGV("af start (fd %d mode %d)", mAutoFocusFd, afMode);
1856 status = native_set_afmode(mAutoFocusFd, afMode);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001857 LOGV("af done: %d", (int)status);
1858 close(mAutoFocusFd);
1859 mAutoFocusFd = -1;
1860
1861done:
1862 mAutoFocusThreadRunning = false;
1863 mAutoFocusThreadLock.unlock();
1864
1865 mCallbackLock.lock();
1866 bool autoFocusEnabled = mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS);
1867 notify_callback cb = mNotifyCallback;
1868 void *data = mCallbackCookie;
1869 mCallbackLock.unlock();
1870 if (autoFocusEnabled)
1871 cb(CAMERA_MSG_FOCUS, status, 0, data);
1872
1873#if DLOPEN_LIBMMCAMERA
1874 if (libhandle) {
1875 ::dlclose(libhandle);
1876 LOGV("AF: dlclose(libqcamera)");
1877 }
1878#endif
1879}
1880
1881status_t QualcommCameraHardware::cancelAutoFocusInternal()
1882{
1883 LOGV("cancelAutoFocusInternal E");
1884
Srinivasan Kannan71229622009-12-04 12:05:58 -08001885 if(!sensorType->hasAutoFocusSupport){
1886 LOGV("cancelAutoFocusInternal X");
1887 return NO_ERROR;
1888 }
1889
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001890#if 0
1891 if (mAutoFocusFd < 0) {
1892 LOGV("cancelAutoFocusInternal X: not in progress");
1893 return NO_ERROR;
1894 }
1895#endif
1896
1897 status_t rc = native_cancel_afmode(mCameraControlFd, mAutoFocusFd) ?
1898 NO_ERROR :
1899 UNKNOWN_ERROR;
1900
1901 LOGV("cancelAutoFocusInternal X: %d", rc);
1902 return rc;
1903}
1904
1905void *auto_focus_thread(void *user)
1906{
1907 LOGV("auto_focus_thread E");
1908 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
1909 if (obj != 0) {
1910 obj->runAutoFocus();
1911 }
1912 else LOGW("not starting autofocus: the object went away!");
1913 LOGV("auto_focus_thread X");
1914 return NULL;
1915}
1916
1917status_t QualcommCameraHardware::autoFocus()
1918{
1919 LOGV("autoFocus E");
1920 Mutex::Autolock l(&mLock);
1921
Srinivasan Kannan71229622009-12-04 12:05:58 -08001922 if(!sensorType->hasAutoFocusSupport){
Srinivasan Kannandf085222009-12-09 18:31:00 -08001923 bool status = false;
1924 mCallbackLock.lock();
1925 bool autoFocusEnabled = mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS);
1926 notify_callback cb = mNotifyCallback;
1927 void *data = mCallbackCookie;
1928 mCallbackLock.unlock();
1929 if (autoFocusEnabled)
1930 cb(CAMERA_MSG_FOCUS, status, 0, data);
Srinivasan Kannan71229622009-12-04 12:05:58 -08001931 LOGV("autoFocus X");
1932 return NO_ERROR;
1933 }
1934
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001935 if (mCameraControlFd < 0) {
1936 LOGE("not starting autofocus: main control fd %d", mCameraControlFd);
1937 return UNKNOWN_ERROR;
1938 }
1939
1940 {
1941 mAutoFocusThreadLock.lock();
1942 if (!mAutoFocusThreadRunning) {
1943 // Create a detached thread here so that we don't have to wait
1944 // for it when we cancel AF.
1945 pthread_t thr;
1946 pthread_attr_t attr;
1947 pthread_attr_init(&attr);
1948 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1949 mAutoFocusThreadRunning =
1950 !pthread_create(&thr, &attr,
1951 auto_focus_thread, NULL);
1952 if (!mAutoFocusThreadRunning) {
1953 LOGE("failed to start autofocus thread");
1954 mAutoFocusThreadLock.unlock();
1955 return UNKNOWN_ERROR;
1956 }
1957 }
1958 mAutoFocusThreadLock.unlock();
1959 }
1960
1961 LOGV("autoFocus X");
1962 return NO_ERROR;
1963}
1964
1965status_t QualcommCameraHardware::cancelAutoFocus()
1966{
1967 LOGV("cancelAutoFocus E");
1968 Mutex::Autolock l(&mLock);
1969
1970 int rc = NO_ERROR;
1971 if (mCameraRunning && mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS)) {
1972 rc = cancelAutoFocusInternal();
1973 }
1974
1975 LOGV("cancelAutoFocus X");
1976 return rc;
1977}
1978
1979void QualcommCameraHardware::runSnapshotThread(void *data)
1980{
1981 LOGV("runSnapshotThread E");
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001982 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
1983 if (native_start_snapshot(mCameraControlFd))
1984 receiveRawPicture();
1985 else
1986 LOGE("main: native_start_snapshot failed!");
1987 } else if(mSnapshotFormat == PICTURE_FORMAT_RAW){
1988 if(native_start_raw_snapshot(mCameraControlFd)){
1989 receiveRawSnapshot();
1990 } else {
1991 LOGE("main: native_start_raw_snapshot failed!");
1992 }
1993 }
1994
1995 mSnapshotFormat = 0;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001996
1997 mSnapshotThreadWaitLock.lock();
1998 mSnapshotThreadRunning = false;
1999 mSnapshotThreadWait.signal();
2000 mSnapshotThreadWaitLock.unlock();
2001
2002 LOGV("runSnapshotThread X");
2003}
2004
2005void *snapshot_thread(void *user)
2006{
2007 LOGD("snapshot_thread E");
2008 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
2009 if (obj != 0) {
2010 obj->runSnapshotThread(user);
2011 }
2012 else LOGW("not starting snapshot thread: the object went away!");
2013 LOGD("snapshot_thread X");
2014 return NULL;
2015}
2016
2017status_t QualcommCameraHardware::takePicture()
2018{
2019 LOGV("takePicture(%d)", mMsgEnabled);
2020 Mutex::Autolock l(&mLock);
2021
2022 // Wait for old snapshot thread to complete.
2023 mSnapshotThreadWaitLock.lock();
2024 while (mSnapshotThreadRunning) {
2025 LOGV("takePicture: waiting for old snapshot thread to complete.");
2026 mSnapshotThreadWait.wait(mSnapshotThreadWaitLock);
2027 LOGV("takePicture: old snapshot thread completed.");
2028 }
2029
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002030 //mSnapshotFormat is protected by mSnapshotThreadWaitLock
2031 if(mParameters.getPictureFormat() != 0 &&
2032 !strcmp(mParameters.getPictureFormat(),
2033 CameraParameters::PIXEL_FORMAT_RAW))
2034 mSnapshotFormat = PICTURE_FORMAT_RAW;
2035 else
2036 mSnapshotFormat = PICTURE_FORMAT_JPEG;
2037
2038 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
2039 if(!native_prepare_snapshot(mCameraControlFd)) {
2040 mSnapshotThreadWaitLock.unlock();
2041 return UNKNOWN_ERROR;
2042 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002043 }
2044
2045 stopPreviewInternal();
2046
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002047 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
2048 if (!initRaw(mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE))) {
2049 LOGE("initRaw failed. Not taking picture.");
2050 mSnapshotThreadWaitLock.unlock();
2051 return UNKNOWN_ERROR;
2052 }
2053 } else if(mSnapshotFormat == PICTURE_FORMAT_RAW ){
2054 if(!initRawSnapshot()){
2055 LOGE("initRawSnapshot failed. Not taking picture.");
2056 mSnapshotThreadWaitLock.unlock();
2057 return UNKNOWN_ERROR;
2058 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002059 }
2060
2061 mShutterLock.lock();
2062 mShutterPending = true;
2063 mShutterLock.unlock();
2064
2065 pthread_attr_t attr;
2066 pthread_attr_init(&attr);
2067 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2068 mSnapshotThreadRunning = !pthread_create(&mSnapshotThread,
2069 &attr,
2070 snapshot_thread,
2071 NULL);
2072 mSnapshotThreadWaitLock.unlock();
2073
2074 LOGV("takePicture: X");
2075 return mSnapshotThreadRunning ? NO_ERROR : UNKNOWN_ERROR;
2076}
2077
2078status_t QualcommCameraHardware::cancelPicture()
2079{
2080 status_t rc;
2081 LOGV("cancelPicture: E");
2082 rc = native_stop_snapshot(mCameraControlFd) ? NO_ERROR : UNKNOWN_ERROR;
2083 LOGV("cancelPicture: X: %d", rc);
2084 return rc;
2085}
2086
2087status_t QualcommCameraHardware::setParameters(const CameraParameters& params)
2088{
2089 LOGV("setParameters: E params = %p", &params);
2090
2091 Mutex::Autolock l(&mLock);
2092 status_t rc, final_rc = NO_ERROR;
2093
2094 if ((rc = setPreviewSize(params))) final_rc = rc;
2095 if ((rc = setPictureSize(params))) final_rc = rc;
2096 if ((rc = setJpegQuality(params))) final_rc = rc;
2097 if ((rc = setAntibanding(params))) final_rc = rc;
2098 if ((rc = setEffect(params))) final_rc = rc;
Apurva Rajguru55562b02009-12-03 12:25:35 -08002099 if ((rc = setAutoExposure(params))) final_rc = rc;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002100 if ((rc = setWhiteBalance(params))) final_rc = rc;
2101 if ((rc = setFlash(params))) final_rc = rc;
2102 if ((rc = setGpsLocation(params))) final_rc = rc;
2103 if ((rc = setRotation(params))) final_rc = rc;
2104 if ((rc = setZoom(params))) final_rc = rc;
2105 if ((rc = setFocusMode(params))) final_rc = rc;
2106 if ((rc = setOrientation(params))) final_rc = rc;
Nishant Panditc8c1ee72009-12-03 16:24:02 +05302107 if ((rc = setBrightness(params))) final_rc = rc;
2108 if ((rc = setLensshadeValue(params))) final_rc = rc;
2109 if ((rc = setISOValue(params))) final_rc = rc;
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002110 if ((rc = setPictureFormat(params))) final_rc = rc;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002111
2112 LOGV("setParameters: X");
2113 return final_rc;
2114}
2115
2116CameraParameters QualcommCameraHardware::getParameters() const
2117{
2118 LOGV("getParameters: EX");
2119 return mParameters;
2120}
2121
2122status_t QualcommCameraHardware::sendCommand(int32_t command, int32_t arg1,
2123 int32_t arg2)
2124{
2125 LOGV("sendCommand: EX");
2126 return BAD_VALUE;
2127}
2128
2129extern "C" sp<CameraHardwareInterface> openCameraHardware()
2130{
2131 LOGV("openCameraHardware: call createInstance");
2132 return QualcommCameraHardware::createInstance();
2133}
2134
2135wp<QualcommCameraHardware> QualcommCameraHardware::singleton;
2136
2137// If the hardware already exists, return a strong pointer to the current
2138// object. If not, create a new hardware object, put it in the singleton,
2139// and return it.
2140sp<CameraHardwareInterface> QualcommCameraHardware::createInstance()
2141{
2142 LOGD("createInstance: E");
2143
2144 Mutex::Autolock lock(&singleton_lock);
2145
2146 // Wait until the previous release is done.
2147 while (singleton_releasing) {
2148 LOGD("Wait for previous release.");
2149 singleton_wait.wait(singleton_lock);
2150 }
2151
2152 if (singleton != 0) {
2153 sp<CameraHardwareInterface> hardware = singleton.promote();
2154 if (hardware != 0) {
2155 LOGD("createInstance: X return existing hardware=%p", &(*hardware));
2156 return hardware;
2157 }
2158 }
2159
2160 {
2161 struct stat st;
2162 int rc = stat("/dev/oncrpc", &st);
2163 if (rc < 0) {
2164 LOGD("createInstance: X failed to create hardware: %s", strerror(errno));
2165 return NULL;
2166 }
2167 }
2168
2169 QualcommCameraHardware *cam = new QualcommCameraHardware();
2170 sp<QualcommCameraHardware> hardware(cam);
2171 singleton = hardware;
2172
2173 if (!cam->startCamera()) {
2174 LOGE("%s: startCamera failed!", __FUNCTION__);
2175 return NULL;
2176 }
2177
2178 cam->initDefaultParameters();
2179 LOGD("createInstance: X created hardware=%p", &(*hardware));
2180 return hardware;
2181}
2182
2183// For internal use only, hence the strong pointer to the derived type.
2184sp<QualcommCameraHardware> QualcommCameraHardware::getInstance()
2185{
2186 sp<CameraHardwareInterface> hardware = singleton.promote();
2187 if (hardware != 0) {
2188 // LOGV("getInstance: X old instance of hardware");
2189 return sp<QualcommCameraHardware>(static_cast<QualcommCameraHardware*>(hardware.get()));
2190 } else {
2191 LOGV("getInstance: X new instance of hardware");
2192 return sp<QualcommCameraHardware>();
2193 }
2194}
2195
2196void QualcommCameraHardware::receivePreviewFrame(struct msm_frame *frame)
2197{
2198// LOGV("receivePreviewFrame E");
2199
2200 if (!mCameraRunning) {
2201 LOGE("ignoring preview callback--camera has been stopped");
2202 return;
2203 }
2204
2205 mCallbackLock.lock();
2206 int msgEnabled = mMsgEnabled;
2207 data_callback pcb = mDataCallback;
2208 void *pdata = mCallbackCookie;
2209 data_callback_timestamp rcb = mDataCallbackTimestamp;
2210 void *rdata = mCallbackCookie;
2211 mCallbackLock.unlock();
2212
2213 // Find the offset within the heap of the current buffer.
2214 ssize_t offset =
2215 (ssize_t)frame->buffer - (ssize_t)mPreviewHeap->mHeap->base();
2216 offset /= mPreviewHeap->mAlignedBufferSize;
2217
2218 mInPreviewCallback = true;
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08002219 if((mUseOverlay == true) && (mOverlay != NULL) ) {
2220 ssize_t offset_addr =
2221 (ssize_t)frame->buffer - (ssize_t)mPreviewHeap->mHeap->base();
2222 mOverlayLock.lock();
2223 mOverlay->setFd(mPreviewHeap->mHeap->getHeapID());
2224 mOverlay->queueBuffer((void *)offset_addr);
2225 mOverlayLock.unlock();
2226 LOGV(" Queueing buffer %x from HAL for display ", offset_addr );
2227 }
2228 /* In case of Overlay, the MSG_PREVIEW_FRAME will be disabled
2229 * second frame onwards. Hence we can keep this piece of code
2230 * in overlay case as well. */
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002231 if (pcb != NULL && (msgEnabled & CAMERA_MSG_PREVIEW_FRAME))
2232 pcb(CAMERA_MSG_PREVIEW_FRAME, mPreviewHeap->mBuffers[offset],
2233 pdata);
2234
2235 if(rcb != NULL && (msgEnabled & CAMERA_MSG_VIDEO_FRAME)) {
2236 rcb(systemTime(), CAMERA_MSG_VIDEO_FRAME, mPreviewHeap->mBuffers[offset], rdata);
2237 Mutex::Autolock rLock(&mRecordFrameLock);
2238 if (mReleasedRecordingFrame != true) {
2239 LOGV("block waiting for frame release");
2240 mRecordWait.wait(mRecordFrameLock);
2241 LOGV("frame released, continuing");
2242 }
2243 mReleasedRecordingFrame = false;
2244 }
2245 mInPreviewCallback = false;
2246
2247// LOGV("receivePreviewFrame X");
2248}
2249
2250status_t QualcommCameraHardware::startRecording()
2251{
2252 LOGV("startRecording E");
2253 Mutex::Autolock l(&mLock);
2254 mReleasedRecordingFrame = false;
2255 return startPreviewInternal();
2256}
2257
2258void QualcommCameraHardware::stopRecording()
2259{
2260 LOGV("stopRecording: E");
2261 Mutex::Autolock l(&mLock);
2262 {
2263 mRecordFrameLock.lock();
2264 mReleasedRecordingFrame = true;
2265 mRecordWait.signal();
2266 mRecordFrameLock.unlock();
2267
2268 if(mDataCallback && (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)) {
2269 LOGV("stopRecording: X, preview still in progress");
2270 return;
2271 }
2272 }
2273
2274 stopPreviewInternal();
2275 LOGV("stopRecording: X");
2276}
2277
2278void QualcommCameraHardware::releaseRecordingFrame(
2279 const sp<IMemory>& mem __attribute__((unused)))
2280{
2281 LOGV("releaseRecordingFrame E");
2282 Mutex::Autolock rLock(&mRecordFrameLock);
2283 mReleasedRecordingFrame = true;
2284 mRecordWait.signal();
2285 LOGV("releaseRecordingFrame X");
2286}
2287
2288bool QualcommCameraHardware::recordingEnabled()
2289{
2290 return mCameraRunning && mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME);
2291}
2292
2293void QualcommCameraHardware::notifyShutter(common_crop_t *crop)
2294{
2295 mShutterLock.lock();
2296 image_rect_type size;
2297
2298 if (mShutterPending && mNotifyCallback && (mMsgEnabled & CAMERA_MSG_SHUTTER)) {
2299 LOGV("out2_w=%d, out2_h=%d, in2_w=%d, in2_h=%d",
2300 crop->out2_w, crop->out2_h, crop->in2_w, crop->in2_h);
2301 LOGV("out1_w=%d, out1_h=%d, in1_w=%d, in1_h=%d",
2302 crop->out1_w, crop->out1_h, crop->in1_w, crop->in1_h);
2303
2304 // To workaround a bug in MDP which happens if either
2305 // dimension > 2048, we display the thumbnail instead.
2306 mDisplayHeap = mRawHeap;
2307 if (crop->in1_w == 0 || crop->in1_h == 0) {
2308 // Full size
2309 size.width = mDimension.picture_width;
2310 size.height = mDimension.picture_height;
2311 if (size.width > 2048 || size.height > 2048) {
2312 size.width = mDimension.ui_thumbnail_width;
2313 size.height = mDimension.ui_thumbnail_height;
2314 mDisplayHeap = mThumbnailHeap;
2315 }
2316 } else {
2317 // Cropped
2318 size.width = crop->in2_w & ~1;
2319 size.height = crop->in2_h & ~1;
2320 if (size.width > 2048 || size.height > 2048) {
2321 size.width = crop->in1_w & ~1;
2322 size.height = crop->in1_h & ~1;
2323 mDisplayHeap = mThumbnailHeap;
2324 }
2325 }
2326
2327 mNotifyCallback(CAMERA_MSG_SHUTTER, (int32_t)&size, 0,
2328 mCallbackCookie);
2329 mShutterPending = false;
2330 }
2331 mShutterLock.unlock();
2332}
2333
2334static void receive_shutter_callback(common_crop_t *crop)
2335{
2336 LOGV("receive_shutter_callback: E");
2337 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
2338 if (obj != 0) {
2339 obj->notifyShutter(crop);
2340 }
2341 LOGV("receive_shutter_callback: X");
2342}
2343
2344// Crop the picture in place.
2345static void crop_yuv420(uint32_t width, uint32_t height,
2346 uint32_t cropped_width, uint32_t cropped_height,
2347 uint8_t *image)
2348{
2349 uint32_t i, x, y;
2350 uint8_t* chroma_src, *chroma_dst;
2351
2352 // Calculate the start position of the cropped area.
2353 x = (width - cropped_width) / 2;
2354 y = (height - cropped_height) / 2;
2355 x &= ~1;
2356 y &= ~1;
2357
2358 // Copy luma component.
2359 for(i = 0; i < cropped_height; i++)
2360 memcpy(image + i * cropped_width,
2361 image + width * (y + i) + x,
2362 cropped_width);
2363
2364 chroma_src = image + width * height;
2365 chroma_dst = image + cropped_width * cropped_height;
2366
2367 // Copy chroma components.
2368 cropped_height /= 2;
2369 y /= 2;
2370 for(i = 0; i < cropped_height; i++)
2371 memcpy(chroma_dst + i * cropped_width,
2372 chroma_src + width * (y + i) + x,
2373 cropped_width);
2374}
2375
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002376
2377void QualcommCameraHardware::receiveRawSnapshot(){
2378 LOGV("receiveRawSnapshot E");
2379
2380 Mutex::Autolock cbLock(&mCallbackLock);
2381
2382 notifyShutter(&mCrop);
2383
2384 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
2385
2386 if(native_get_picture(mCameraControlFd, &mCrop) == false) {
2387 LOGE("receiveRawSnapshot X: native_get_picture failed!");
2388 return;
2389 }
2390
2391 //Create a Ashmem heap to copy data from PMem heap for application layer
2392 if(mRawSnapshotAshmemHeap != NULL){
2393 LOGV("receiveRawSnapshot: clearing old mRawSnapShotAshmemHeap.");
2394 mRawSnapshotAshmemHeap.clear();
2395 }
2396 mRawSnapshotAshmemHeap = new AshmemPool(
2397 mRawSnapShotPmemHeap->mBufferSize,
2398 mRawSnapShotPmemHeap->mNumBuffers,
2399 mRawSnapShotPmemHeap->mFrameSize,
2400 "raw ashmem snapshot camera"
2401 );
2402
2403 if(!mRawSnapshotAshmemHeap->initialized()){
2404 LOGE("receiveRawSnapshot X: error initializing mRawSnapshotHeap");
2405 deinitRawSnapshot();
2406 return;
2407 }
2408
2409 memcpy(mRawSnapshotAshmemHeap->mHeap->base(),
2410 mRawSnapShotPmemHeap->mHeap->base(),
2411 mRawSnapShotPmemHeap->mHeap->getSize());
2412
2413 mDataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mRawSnapshotAshmemHeap->mBuffers[0],
2414 mCallbackCookie);
2415
2416 }
2417
2418 //cleanup
2419 deinitRawSnapshot();
2420
2421 LOGV("receiveRawSnapshot X");
2422}
2423
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002424void QualcommCameraHardware::receiveRawPicture()
2425{
2426 LOGV("receiveRawPicture: E");
2427
2428 Mutex::Autolock cbLock(&mCallbackLock);
2429 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_RAW_IMAGE)) {
2430 if(native_get_picture(mCameraControlFd, &mCrop) == false) {
2431 LOGE("getPicture failed!");
2432 return;
2433 }
2434 mCrop.in1_w &= ~1;
2435 mCrop.in1_h &= ~1;
2436 mCrop.in2_w &= ~1;
2437 mCrop.in2_h &= ~1;
2438
2439 // By the time native_get_picture returns, picture is taken. Call
2440 // shutter callback if cam config thread has not done that.
2441 notifyShutter(&mCrop);
2442
2443 // Crop the image if zoomed.
2444 if (mCrop.in2_w != 0 && mCrop.in2_h != 0) {
2445 crop_yuv420(mCrop.out2_w, mCrop.out2_h, mCrop.in2_w, mCrop.in2_h,
2446 (uint8_t *)mRawHeap->mHeap->base());
2447 crop_yuv420(mCrop.out1_w, mCrop.out1_h, mCrop.in1_w, mCrop.in1_h,
2448 (uint8_t *)mThumbnailHeap->mHeap->base());
2449 // We do not need jpeg encoder to upscale the image. Set the new
2450 // dimension for encoder.
2451 mDimension.orig_picture_dx = mCrop.in2_w;
2452 mDimension.orig_picture_dy = mCrop.in2_h;
2453 mDimension.thumbnail_width = mCrop.in1_w;
2454 mDimension.thumbnail_height = mCrop.in1_h;
2455 memset(&mCrop, 0, sizeof(mCrop));
2456 }
2457
2458 mDataCallback(CAMERA_MSG_RAW_IMAGE, mDisplayHeap->mBuffers[0],
2459 mCallbackCookie);
2460 }
2461 else LOGV("Raw-picture callback was canceled--skipping.");
2462
2463 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
2464 mJpegSize = 0;
2465 if (LINK_jpeg_encoder_init()) {
2466 if(native_jpeg_encode()) {
2467 LOGV("receiveRawPicture: X (success)");
2468 return;
2469 }
2470 LOGE("jpeg encoding failed");
2471 }
2472 else LOGE("receiveRawPicture X: jpeg_encoder_init failed.");
2473 }
2474 else LOGV("JPEG callback is NULL, not encoding image.");
2475 deinitRaw();
2476 LOGV("receiveRawPicture: X");
2477}
2478
2479void QualcommCameraHardware::receiveJpegPictureFragment(
2480 uint8_t *buff_ptr, uint32_t buff_size)
2481{
2482 uint32_t remaining = mJpegHeap->mHeap->virtualSize();
2483 remaining -= mJpegSize;
2484 uint8_t *base = (uint8_t *)mJpegHeap->mHeap->base();
2485
2486 LOGV("receiveJpegPictureFragment size %d", buff_size);
2487 if (buff_size > remaining) {
2488 LOGE("receiveJpegPictureFragment: size %d exceeds what "
2489 "remains in JPEG heap (%d), truncating",
2490 buff_size,
2491 remaining);
2492 buff_size = remaining;
2493 }
2494 memcpy(base + mJpegSize, buff_ptr, buff_size);
2495 mJpegSize += buff_size;
2496}
2497
2498void QualcommCameraHardware::receiveJpegPicture(void)
2499{
2500 LOGV("receiveJpegPicture: E image (%d uint8_ts out of %d)",
2501 mJpegSize, mJpegHeap->mBufferSize);
2502 Mutex::Autolock cbLock(&mCallbackLock);
2503
2504 int index = 0, rc;
2505
2506 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
2507 // The reason we do not allocate into mJpegHeap->mBuffers[offset] is
2508 // that the JPEG image's size will probably change from one snapshot
2509 // to the next, so we cannot reuse the MemoryBase object.
2510 sp<MemoryBase> buffer = new
2511 MemoryBase(mJpegHeap->mHeap,
2512 index * mJpegHeap->mBufferSize +
2513 0,
2514 mJpegSize);
2515 mDataCallback(CAMERA_MSG_COMPRESSED_IMAGE, buffer, mCallbackCookie);
2516 buffer = NULL;
2517 }
2518 else LOGV("JPEG callback was cancelled--not delivering image.");
2519
2520 LINK_jpeg_encoder_join();
2521 deinitRaw();
2522
2523 LOGV("receiveJpegPicture: X callback done.");
2524}
2525
2526bool QualcommCameraHardware::previewEnabled()
2527{
2528 return mCameraRunning && mDataCallback && (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME);
2529}
2530
2531status_t QualcommCameraHardware::setPreviewSize(const CameraParameters& params)
2532{
2533 int width, height;
2534 params.getPreviewSize(&width, &height);
2535 LOGV("requested preview size %d x %d", width, height);
2536
2537 // Validate the preview size
2538 for (size_t i = 0; i < PREVIEW_SIZE_COUNT; ++i) {
2539 if (width == preview_sizes[i].width
2540 && height == preview_sizes[i].height) {
2541 mParameters.setPreviewSize(width, height);
2542 mDimension.display_width = width;
2543 mDimension.display_height = height;
2544 return NO_ERROR;
2545 }
2546 }
2547 LOGE("Invalid preview size requested: %dx%d", width, height);
2548 return BAD_VALUE;
2549}
2550
2551status_t QualcommCameraHardware::setPictureSize(const CameraParameters& params)
2552{
2553 int width, height;
2554 params.getPictureSize(&width, &height);
2555 LOGV("requested picture size %d x %d", width, height);
2556
2557 // Validate the picture size
2558 for (int i = 0; i < PICTURE_SIZE_COUNT; ++i) {
2559 if (width == picture_sizes[i].width
2560 && height == picture_sizes[i].height) {
2561 mParameters.setPictureSize(width, height);
2562 mDimension.picture_width = width;
2563 mDimension.picture_height = height;
2564 return NO_ERROR;
2565 }
2566 }
2567 LOGE("Invalid picture size requested: %dx%d", width, height);
2568 return BAD_VALUE;
2569}
2570
2571status_t QualcommCameraHardware::setJpegQuality(const CameraParameters& params) {
2572 status_t rc = NO_ERROR;
2573 int quality = params.getInt(CameraParameters::KEY_JPEG_QUALITY);
2574 if (quality > 0 && quality <= 100) {
2575 mParameters.set(CameraParameters::KEY_JPEG_QUALITY, quality);
2576 } else {
2577 LOGE("Invalid jpeg quality=%d", quality);
2578 rc = BAD_VALUE;
2579 }
2580
2581 quality = params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY);
2582 if (quality > 0 && quality <= 100) {
2583 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, quality);
2584 } else {
2585 LOGE("Invalid jpeg thumbnail quality=%d", quality);
2586 rc = BAD_VALUE;
2587 }
2588 return rc;
2589}
2590
2591status_t QualcommCameraHardware::setEffect(const CameraParameters& params)
2592{
2593 const char *str = params.get(CameraParameters::KEY_EFFECT);
2594 if (str != NULL) {
2595 int32_t value = attr_lookup(effects, sizeof(effects) / sizeof(str_map), str);
2596 if (value != NOT_FOUND) {
2597 mParameters.set(CameraParameters::KEY_EFFECT, str);
2598 bool ret = native_set_parm(CAMERA_SET_PARM_EFFECT, sizeof(value),
2599 (void *)&value);
2600 return ret ? NO_ERROR : UNKNOWN_ERROR;
2601 }
2602 }
2603 LOGE("Invalid effect value: %s", (str == NULL) ? "NULL" : str);
2604 return BAD_VALUE;
2605}
2606
Apurva Rajguru55562b02009-12-03 12:25:35 -08002607status_t QualcommCameraHardware::setAutoExposure(const CameraParameters& params)
2608{
2609 const char *str = params.get(CameraParameters::KEY_AUTO_EXPOSURE);
2610 if (str != NULL) {
2611 int32_t value = attr_lookup(autoexposure, sizeof(autoexposure) / sizeof(str_map), str);
2612 if (value != NOT_FOUND) {
2613 mParameters.set(CameraParameters::KEY_AUTO_EXPOSURE, str);
2614 bool ret = native_set_parm(CAMERA_SET_PARM_EXPOSURE, sizeof(value),
2615 (void *)&value);
2616 return ret ? NO_ERROR : UNKNOWN_ERROR;
2617 }
2618 }
2619 LOGE("Invalid auto exposure value: %s", (str == NULL) ? "NULL" : str);
2620 return BAD_VALUE;
2621}
2622
Nishant Panditc8c1ee72009-12-03 16:24:02 +05302623status_t QualcommCameraHardware::setBrightness(const CameraParameters& params) {
2624 int brightness = params.getInt("luma-adaptation");
2625 if (mBrightness != brightness) {
2626 LOGV(" new brightness value : %d ", brightness);
2627 mBrightness = brightness;
2628
2629 bool ret = native_set_parm(CAMERA_SET_PARM_BRIGHTNESS, sizeof(mBrightness),
2630 (void *)&mBrightness);
2631 return ret ? NO_ERROR : UNKNOWN_ERROR;
2632 } else {
2633 return NO_ERROR;
2634 }
2635}
2636
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002637status_t QualcommCameraHardware::setWhiteBalance(const CameraParameters& params)
2638{
2639 const char *str = params.get(CameraParameters::KEY_WHITE_BALANCE);
2640 if (str != NULL) {
2641 int32_t value = attr_lookup(whitebalance, sizeof(whitebalance) / sizeof(str_map), str);
2642 if (value != NOT_FOUND) {
2643 mParameters.set(CameraParameters::KEY_WHITE_BALANCE, str);
2644 bool ret = native_set_parm(CAMERA_SET_PARM_WB, sizeof(value),
2645 (void *)&value);
2646 return ret ? NO_ERROR : UNKNOWN_ERROR;
2647 }
2648 }
2649 LOGE("Invalid whitebalance value: %s", (str == NULL) ? "NULL" : str);
2650 return BAD_VALUE;
2651}
2652
2653status_t QualcommCameraHardware::setFlash(const CameraParameters& params)
2654{
2655 if (!mSensorInfo.flash_enabled) {
2656 LOGV("%s: flash not supported", __FUNCTION__);
2657 return NO_ERROR;
2658 }
2659
2660 const char *str = params.get(CameraParameters::KEY_FLASH_MODE);
2661 if (str != NULL) {
2662 int32_t value = attr_lookup(flash, sizeof(flash) / sizeof(str_map), str);
2663 if (value != NOT_FOUND) {
2664 mParameters.set(CameraParameters::KEY_FLASH_MODE, str);
2665 bool ret = native_set_parm(CAMERA_SET_PARM_LED_MODE,
2666 sizeof(value), (void *)&value);
2667 return ret ? NO_ERROR : UNKNOWN_ERROR;
2668 }
2669 }
2670 LOGE("Invalid flash mode value: %s", (str == NULL) ? "NULL" : str);
2671 return BAD_VALUE;
2672}
2673
2674status_t QualcommCameraHardware::setAntibanding(const CameraParameters& params)
2675{
2676 const char *str = params.get(CameraParameters::KEY_ANTIBANDING);
2677 if (str != NULL) {
2678 int value = (camera_antibanding_type)attr_lookup(
2679 antibanding, sizeof(antibanding) / sizeof(str_map), str);
2680 if (value != NOT_FOUND) {
2681 camera_antibanding_type temp = (camera_antibanding_type) value;
2682 // We don't have auto antibanding now, and simply set the frequency by country.
2683 if (temp == CAMERA_ANTIBANDING_AUTO) {
2684 temp = camera_get_location();
2685 }
2686 mParameters.set(CameraParameters::KEY_ANTIBANDING, str);
2687 native_set_parm(CAMERA_SET_PARM_ANTIBANDING, sizeof(camera_antibanding_type), (void *)&temp);
2688 return NO_ERROR;
2689 }
2690 }
2691 LOGE("Invalid antibanding value: %s", (str == NULL) ? "NULL" : str);
2692 return BAD_VALUE;
2693}
2694
Nishant Panditc8c1ee72009-12-03 16:24:02 +05302695status_t QualcommCameraHardware::setLensshadeValue(const CameraParameters& params)
2696{
2697 const char *str = params.get(CameraParameters::KEY_LENSSHADE);
2698 if (str != NULL) {
2699 int value = attr_lookup(lensshade,
2700 sizeof(lensshade) / sizeof(str_map), str);
2701 if (value != NOT_FOUND) {
2702 int8_t temp = (int8_t)value;
2703 mParameters.set(CameraParameters::KEY_LENSSHADE, str);
2704 native_set_parm(CAMERA_SET_PARM_ROLLOFF, sizeof(int8_t), (void *)&temp);
2705 return NO_ERROR;
2706 }
2707 }
2708 LOGE("Invalid lensShade value: %s", (str == NULL) ? "NULL" : str);
2709 return BAD_VALUE;
2710}
2711
2712status_t QualcommCameraHardware::setISOValue(const CameraParameters& params) {
2713 const char *str = params.get(CameraParameters::KEY_ISO_MODE);
2714 if (str != NULL) {
2715 int value = (camera_iso_mode_type)attr_lookup(
2716 iso, sizeof(iso) / sizeof(str_map), str);
2717 if (value != NOT_FOUND) {
2718 camera_iso_mode_type temp = (camera_iso_mode_type) value;
2719 mParameters.set(CameraParameters::KEY_ISO_MODE, str);
2720 native_set_parm(CAMERA_SET_PARM_ISO, sizeof(camera_iso_mode_type), (void *)&temp);
2721 return NO_ERROR;
2722 }
2723 }
2724 LOGE("Invalid Iso value: %s", (str == NULL) ? "NULL" : str);
2725 return BAD_VALUE;
2726}
2727
2728
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002729status_t QualcommCameraHardware::setGpsLocation(const CameraParameters& params)
2730{
2731 const char *latitude = params.get(CameraParameters::KEY_GPS_LATITUDE);
2732 if (latitude) {
2733 mParameters.set(CameraParameters::KEY_GPS_LATITUDE, latitude);
2734 }
2735
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08002736 const char *latitudeRef = params.get(CameraParameters::KEY_GPS_LATITUDE_REF);
2737 if (latitudeRef) {
2738 mParameters.set(CameraParameters::KEY_GPS_LATITUDE_REF, latitudeRef);
2739 }
2740
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002741 const char *longitude = params.get(CameraParameters::KEY_GPS_LONGITUDE);
2742 if (longitude) {
2743 mParameters.set(CameraParameters::KEY_GPS_LONGITUDE, longitude);
2744 }
2745
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08002746 const char *longitudeRef = params.get(CameraParameters::KEY_GPS_LONGITUDE_REF);
2747 if (longitudeRef) {
2748 mParameters.set(CameraParameters::KEY_GPS_LONGITUDE_REF, longitudeRef);
2749 }
2750
2751 const char *altitudeRef = params.get(CameraParameters::KEY_GPS_ALTITUDE_REF);
2752 if (altitudeRef) {
2753 mParameters.set(CameraParameters::KEY_GPS_ALTITUDE_REF, altitudeRef);
2754 }
2755
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002756 const char *altitude = params.get(CameraParameters::KEY_GPS_ALTITUDE);
2757 if (altitude) {
2758 mParameters.set(CameraParameters::KEY_GPS_ALTITUDE, altitude);
2759 }
2760
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08002761 const char *status = params.get(CameraParameters::KEY_GPS_STATUS);
2762 if (status) {
2763 mParameters.set(CameraParameters::KEY_GPS_STATUS, status);
2764 }
2765
2766 const char *dateTime = params.get(CameraParameters::KEY_EXIF_DATETIME);
2767 if (dateTime) {
2768 mParameters.set(CameraParameters::KEY_EXIF_DATETIME, dateTime);
2769 }
2770
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002771 const char *timestamp = params.get(CameraParameters::KEY_GPS_TIMESTAMP);
2772 if (timestamp) {
2773 mParameters.set(CameraParameters::KEY_GPS_TIMESTAMP, timestamp);
2774 }
2775 return NO_ERROR;
2776}
2777
2778status_t QualcommCameraHardware::setRotation(const CameraParameters& params)
2779{
2780 status_t rc = NO_ERROR;
2781 int rotation = params.getInt(CameraParameters::KEY_ROTATION);
2782 if (rotation != NOT_FOUND) {
2783 if (rotation == 0 || rotation == 90 || rotation == 180
2784 || rotation == 270) {
2785 mParameters.set(CameraParameters::KEY_ROTATION, rotation);
2786 } else {
2787 LOGE("Invalid rotation value: %d", rotation);
2788 rc = BAD_VALUE;
2789 }
2790 }
2791 return rc;
2792}
2793
2794status_t QualcommCameraHardware::setZoom(const CameraParameters& params)
2795{
2796 status_t rc = NO_ERROR;
2797 // No matter how many different zoom values the driver can provide, HAL
2798 // provides applictations the same number of zoom levels. The maximum driver
2799 // zoom value depends on sensor output (VFE input) and preview size (VFE
2800 // output) because VFE can only crop and cannot upscale. If the preview size
2801 // is bigger, the maximum zoom ratio is smaller. However, we want the
2802 // zoom ratio of each zoom level is always the same whatever the preview
2803 // size is. Ex: zoom level 1 is always 1.2x, zoom level 2 is 1.44x, etc. So,
2804 // we need to have a fixed maximum zoom value and do read it from the
2805 // driver.
2806 static const int ZOOM_STEP = 6;
2807 int32_t zoom_level = params.getInt("zoom");
2808
2809 LOGI("Set zoom=%d", zoom_level);
2810 if(zoom_level >= 0 && zoom_level <= MAX_ZOOM_LEVEL) {
2811 mParameters.set("zoom", zoom_level);
2812 int32_t zoom_value = ZOOM_STEP * zoom_level;
2813 bool ret = native_set_parm(CAMERA_SET_PARM_ZOOM,
2814 sizeof(zoom_value), (void *)&zoom_value);
2815 rc = ret ? NO_ERROR : UNKNOWN_ERROR;
2816 } else {
2817 rc = BAD_VALUE;
2818 }
2819
2820 return rc;
2821}
2822
2823status_t QualcommCameraHardware::setFocusMode(const CameraParameters& params)
2824{
2825 const char *str = params.get(CameraParameters::KEY_FOCUS_MODE);
2826 if (str != NULL) {
2827 int32_t value = attr_lookup(focus_modes,
2828 sizeof(focus_modes) / sizeof(str_map), str);
2829 if (value != NOT_FOUND) {
2830 mParameters.set(CameraParameters::KEY_FOCUS_MODE, str);
2831 // Focus step is reset to infinity when preview is started. We do
2832 // not need to do anything now.
2833 return NO_ERROR;
2834 }
2835 }
2836 LOGE("Invalid focus mode value: %s", (str == NULL) ? "NULL" : str);
2837 return BAD_VALUE;
2838}
2839
2840status_t QualcommCameraHardware::setOrientation(const CameraParameters& params)
2841{
2842 const char *str = params.get("orientation");
2843
2844 if (str != NULL) {
2845 if (strcmp(str, "portrait") == 0 || strcmp(str, "landscape") == 0) {
2846 // Camera service needs this to decide if the preview frames and raw
2847 // pictures should be rotated.
2848 mParameters.set("orientation", str);
2849 } else {
2850 LOGE("Invalid orientation value: %s", str);
2851 return BAD_VALUE;
2852 }
2853 }
2854 return NO_ERROR;
2855}
2856
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002857status_t QualcommCameraHardware::setPictureFormat(const CameraParameters& params)
2858{
2859 const char * str = params.get(CameraParameters::KEY_PICTURE_FORMAT);
2860
2861 if(str != NULL){
2862 int32_t value = attr_lookup(picture_formats,
2863 sizeof(picture_formats) / sizeof(str_map), str);
2864 if(value != NOT_FOUND){
2865 mParameters.set(CameraParameters::KEY_PICTURE_FORMAT, str);
2866 } else {
2867 LOGE("Invalid Picture Format value: %s", str);
2868 return BAD_VALUE;
2869 }
2870 }
2871 return NO_ERROR;
2872}
2873
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002874QualcommCameraHardware::MemPool::MemPool(int buffer_size, int num_buffers,
2875 int frame_size,
2876 const char *name) :
2877 mBufferSize(buffer_size),
2878 mNumBuffers(num_buffers),
2879 mFrameSize(frame_size),
2880 mBuffers(NULL), mName(name)
2881{
2882 int page_size_minus_1 = getpagesize() - 1;
2883 mAlignedBufferSize = (buffer_size + page_size_minus_1) & (~page_size_minus_1);
2884}
2885
2886void QualcommCameraHardware::MemPool::completeInitialization()
2887{
2888 // If we do not know how big the frame will be, we wait to allocate
2889 // the buffers describing the individual frames until we do know their
2890 // size.
2891
2892 if (mFrameSize > 0) {
2893 mBuffers = new sp<MemoryBase>[mNumBuffers];
2894 for (int i = 0; i < mNumBuffers; i++) {
2895 mBuffers[i] = new
2896 MemoryBase(mHeap,
2897 i * mAlignedBufferSize,
2898 mFrameSize);
2899 }
2900 }
2901}
2902
2903QualcommCameraHardware::AshmemPool::AshmemPool(int buffer_size, int num_buffers,
2904 int frame_size,
2905 const char *name) :
2906 QualcommCameraHardware::MemPool(buffer_size,
2907 num_buffers,
2908 frame_size,
2909 name)
2910{
2911 LOGV("constructing MemPool %s backed by ashmem: "
2912 "%d frames @ %d uint8_ts, "
2913 "buffer size %d",
2914 mName,
2915 num_buffers, frame_size, buffer_size);
2916
2917 int page_mask = getpagesize() - 1;
2918 int ashmem_size = buffer_size * num_buffers;
2919 ashmem_size += page_mask;
2920 ashmem_size &= ~page_mask;
2921
2922 mHeap = new MemoryHeapBase(ashmem_size);
2923
2924 completeInitialization();
2925}
2926
2927static bool register_buf(int camfd,
2928 int size,
2929 int pmempreviewfd,
2930 uint32_t offset,
2931 uint8_t *buf,
2932 int pmem_type,
2933 bool vfe_can_write,
2934 bool register_buffer = true);
2935
2936QualcommCameraHardware::PmemPool::PmemPool(const char *pmem_pool,
2937 int flags,
2938 int camera_control_fd,
2939 int pmem_type,
2940 int buffer_size, int num_buffers,
2941 int frame_size,
2942 const char *name) :
2943 QualcommCameraHardware::MemPool(buffer_size,
2944 num_buffers,
2945 frame_size,
2946 name),
2947 mPmemType(pmem_type),
2948 mCameraControlFd(dup(camera_control_fd))
2949{
2950 LOGV("constructing MemPool %s backed by pmem pool %s: "
2951 "%d frames @ %d bytes, buffer size %d",
2952 mName,
2953 pmem_pool, num_buffers, frame_size,
2954 buffer_size);
2955
2956 LOGV("%s: duplicating control fd %d --> %d",
2957 __FUNCTION__,
2958 camera_control_fd, mCameraControlFd);
2959
2960 // Make a new mmap'ed heap that can be shared across processes.
2961 // mAlignedBufferSize is already in 4k aligned. (do we need total size necessary to be in power of 2??)
2962 mAlignedSize = mAlignedBufferSize * num_buffers;
2963
2964 sp<MemoryHeapBase> masterHeap =
2965 new MemoryHeapBase(pmem_pool, mAlignedSize, flags);
2966
2967 if (masterHeap->getHeapID() < 0) {
2968 LOGE("failed to construct master heap for pmem pool %s", pmem_pool);
2969 masterHeap.clear();
2970 return;
2971 }
2972
2973 sp<MemoryHeapPmem> pmemHeap = new MemoryHeapPmem(masterHeap, flags);
2974 if (pmemHeap->getHeapID() >= 0) {
2975 pmemHeap->slap();
2976 masterHeap.clear();
2977 mHeap = pmemHeap;
2978 pmemHeap.clear();
2979
2980 mFd = mHeap->getHeapID();
2981 if (::ioctl(mFd, PMEM_GET_SIZE, &mSize)) {
2982 LOGE("pmem pool %s ioctl(PMEM_GET_SIZE) error %s (%d)",
2983 pmem_pool,
2984 ::strerror(errno), errno);
2985 mHeap.clear();
2986 return;
2987 }
2988
2989 LOGV("pmem pool %s ioctl(fd = %d, PMEM_GET_SIZE) is %ld",
2990 pmem_pool,
2991 mFd,
2992 mSize.len);
2993 LOGD("mBufferSize=%d, mAlignedBufferSize=%d\n", mBufferSize, mAlignedBufferSize);
2994 // Unregister preview buffers with the camera drivers. Allow the VFE to write
2995 // to all preview buffers except for the last one.
2996 for (int cnt = 0; cnt < num_buffers; ++cnt) {
2997 register_buf(mCameraControlFd,
2998 mBufferSize,
2999 mHeap->getHeapID(),
3000 mAlignedBufferSize * cnt,
3001 (uint8_t *)mHeap->base() + mAlignedBufferSize * cnt,
3002 pmem_type,
3003 !(cnt == num_buffers - 1 && pmem_type == MSM_PMEM_OUTPUT2));
3004 }
3005
3006 completeInitialization();
3007 }
3008 else LOGE("pmem pool %s error: could not create master heap!",
3009 pmem_pool);
3010}
3011
3012QualcommCameraHardware::PmemPool::~PmemPool()
3013{
3014 LOGV("%s: %s E", __FUNCTION__, mName);
3015 if (mHeap != NULL) {
3016 // Unregister preview buffers with the camera drivers.
3017 for (int cnt = 0; cnt < mNumBuffers; ++cnt) {
3018 register_buf(mCameraControlFd,
3019 mBufferSize,
3020 mHeap->getHeapID(),
3021 mAlignedBufferSize * cnt,
3022 (uint8_t *)mHeap->base() + mAlignedBufferSize * cnt,
3023 mPmemType,
3024 false,
3025 false /* unregister */);
3026 }
3027 }
3028 LOGV("destroying PmemPool %s: closing control fd %d",
3029 mName,
3030 mCameraControlFd);
3031 close(mCameraControlFd);
3032 LOGV("%s: %s X", __FUNCTION__, mName);
3033}
3034
3035QualcommCameraHardware::MemPool::~MemPool()
3036{
3037 LOGV("destroying MemPool %s", mName);
3038 if (mFrameSize > 0)
3039 delete [] mBuffers;
3040 mHeap.clear();
3041 LOGV("destroying MemPool %s completed", mName);
3042}
3043
3044static bool register_buf(int camfd,
3045 int size,
3046 int pmempreviewfd,
3047 uint32_t offset,
3048 uint8_t *buf,
3049 int pmem_type,
3050 bool vfe_can_write,
3051 bool register_buffer)
3052{
3053 struct msm_pmem_info pmemBuf;
3054
3055 pmemBuf.type = pmem_type;
3056 pmemBuf.fd = pmempreviewfd;
3057 pmemBuf.offset = offset;
3058 pmemBuf.len = size;
3059 pmemBuf.vaddr = buf;
3060 pmemBuf.y_off = 0;
3061 pmemBuf.cbcr_off = PAD_TO_WORD(size * 2 / 3);
3062 pmemBuf.active = vfe_can_write;
3063
3064 LOGV("register_buf: camfd = %d, reg = %d buffer = %p",
3065 camfd, !register_buffer, buf);
3066 if (ioctl(camfd,
3067 register_buffer ?
3068 MSM_CAM_IOCTL_REGISTER_PMEM :
3069 MSM_CAM_IOCTL_UNREGISTER_PMEM,
3070 &pmemBuf) < 0) {
3071 LOGE("register_buf: MSM_CAM_IOCTL_(UN)REGISTER_PMEM fd %d error %s",
3072 camfd,
3073 strerror(errno));
3074 return false;
3075 }
3076 return true;
3077}
3078
3079status_t QualcommCameraHardware::MemPool::dump(int fd, const Vector<String16>& args) const
3080{
3081 const size_t SIZE = 256;
3082 char buffer[SIZE];
3083 String8 result;
3084 snprintf(buffer, 255, "QualcommCameraHardware::AshmemPool::dump\n");
3085 result.append(buffer);
3086 if (mName) {
3087 snprintf(buffer, 255, "mem pool name (%s)\n", mName);
3088 result.append(buffer);
3089 }
3090 if (mHeap != 0) {
3091 snprintf(buffer, 255, "heap base(%p), size(%d), flags(%d), device(%s)\n",
3092 mHeap->getBase(), mHeap->getSize(),
3093 mHeap->getFlags(), mHeap->getDevice());
3094 result.append(buffer);
3095 }
3096 snprintf(buffer, 255,
3097 "buffer size (%d), number of buffers (%d), frame size(%d)",
3098 mBufferSize, mNumBuffers, mFrameSize);
3099 result.append(buffer);
3100 write(fd, result.string(), result.size());
3101 return NO_ERROR;
3102}
3103
3104static void receive_camframe_callback(struct msm_frame *frame)
3105{
3106 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
3107 if (obj != 0) {
3108 obj->receivePreviewFrame(frame);
3109 }
3110}
3111
3112static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size)
3113{
3114 LOGV("receive_jpeg_fragment_callback E");
3115 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
3116 if (obj != 0) {
3117 obj->receiveJpegPictureFragment(buff_ptr, buff_size);
3118 }
3119 LOGV("receive_jpeg_fragment_callback X");
3120}
3121
3122static void receive_jpeg_callback(jpeg_event_t status)
3123{
3124 LOGV("receive_jpeg_callback E (completion status %d)", status);
3125 if (status == JPEG_EVENT_DONE) {
3126 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
3127 if (obj != 0) {
3128 obj->receiveJpegPicture();
3129 }
3130 }
3131 LOGV("receive_jpeg_callback X");
3132}
3133
3134void QualcommCameraHardware::setCallbacks(notify_callback notify_cb,
3135 data_callback data_cb,
3136 data_callback_timestamp data_cb_timestamp,
3137 void* user)
3138{
3139 Mutex::Autolock lock(mLock);
3140 mNotifyCallback = notify_cb;
3141 mDataCallback = data_cb;
3142 mDataCallbackTimestamp = data_cb_timestamp;
3143 mCallbackCookie = user;
3144}
3145
3146void QualcommCameraHardware::enableMsgType(int32_t msgType)
3147{
3148 Mutex::Autolock lock(mLock);
3149 mMsgEnabled |= msgType;
3150}
3151
3152void QualcommCameraHardware::disableMsgType(int32_t msgType)
3153{
3154 Mutex::Autolock lock(mLock);
3155 mMsgEnabled &= ~msgType;
3156}
3157
3158bool QualcommCameraHardware::msgTypeEnabled(int32_t msgType)
3159{
3160 return (mMsgEnabled & msgType);
3161}
3162
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08003163bool QualcommCameraHardware::useOverlay(void)
3164{
3165 char value[PROPERTY_VALUE_MAX];
3166 property_get("ro.product.device",value," ");
3167
3168 if(!strcmp(value,"msm7630_surf")) {
3169 /* Only 7x30 supports Overlay */
3170 mUseOverlay = TRUE;
3171 } else
3172 mUseOverlay = FALSE;
3173
3174 LOGV(" Using Overlay : %s ", mUseOverlay ? "YES" : "NO" );
3175 return mUseOverlay;
3176}
3177
3178status_t QualcommCameraHardware::setOverlay(const sp<Overlay> &Overlay)
3179{
3180 if( Overlay != NULL) {
3181 LOGV(" Valid overlay object ");
3182 mOverlayLock.lock();
3183 mOverlay = Overlay;
3184 mOverlayLock.unlock();
3185 } else {
3186 LOGE(" Overlay object NULL. returning ");
3187 return UNKNOWN_ERROR;
3188 }
3189 return NO_ERROR;
3190}
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003191}; // namespace android