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