blob: dcd5cc1b89eba3cbc21556b2f926cc61b961260b [file] [log] [blame]
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001/*
2** Copyright 2008, Google Inc.
3**
4** Licensed under the Apache License, Version 2.0 (the "License");
5** you may not use this file except in compliance with the License.
6** You may obtain a copy of the License at
7**
8** http://www.apache.org/licenses/LICENSE-2.0
9**
10** Unless required by applicable law or agreed to in writing, software
11** distributed under the License is distributed on an "AS IS" BASIS,
12** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13** See the License for the specific language governing permissions and
14** limitations under the License.
15*/
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "QualcommCameraHardware"
19#include <utils/Log.h>
20
21#include "QualcommCameraHardware.h"
22
23#include <utils/Errors.h>
24#include <utils/threads.h>
25#include <binder/MemoryHeapPmem.h>
26#include <utils/String16.h>
27#include <sys/types.h>
28#include <sys/stat.h>
29#include <unistd.h>
30#if HAVE_ANDROID_OS
31#include <linux/android_pmem.h>
32#endif
33#include <linux/ioctl.h>
34#include <ui/CameraParameters.h>
35
36#define LIKELY(exp) __builtin_expect(!!(exp), 1)
37#define UNLIKELY(exp) __builtin_expect(!!(exp), 0)
38
39extern "C" {
40#include <fcntl.h>
41#include <time.h>
42#include <pthread.h>
43#include <stdio.h>
44#include <string.h>
45#include <unistd.h>
46#include <termios.h>
47#include <assert.h>
48#include <stdlib.h>
49#include <ctype.h>
50#include <signal.h>
51#include <errno.h>
52#include <sys/mman.h>
53#include <sys/system_properties.h>
54#include <sys/time.h>
55#include <stdlib.h>
56
57#include <media/msm_camera.h>
58
59#include <camera.h>
60#include <camframe.h>
61#include <mm-still/jpeg/jpege.h>
62
63#define THUMBNAIL_WIDTH 512
64#define THUMBNAIL_HEIGHT 384
65#define THUMBNAIL_WIDTH_STR "512"
66#define THUMBNAIL_HEIGHT_STR "384"
67#define DEFAULT_PICTURE_WIDTH 2048
68#define DEFAULT_PICTURE_HEIGHT 1536
69#define THUMBNAIL_BUFFER_SIZE (THUMBNAIL_WIDTH * THUMBNAIL_HEIGHT * 3/2)
70#define MAX_ZOOM_LEVEL 5
71#define NOT_FOUND -1
72
73#if DLOPEN_LIBMMCAMERA
74#include <dlfcn.h>
75
76void* (*LINK_cam_conf)(void *data);
77void* (*LINK_cam_frame)(void *data);
78bool (*LINK_jpeg_encoder_init)();
79void (*LINK_jpeg_encoder_join)();
80bool (*LINK_jpeg_encoder_encode)(const cam_ctrl_dimension_t *dimen,
81 const uint8_t *thumbnailbuf, int thumbnailfd,
82 const uint8_t *snapshotbuf, int snapshotfd,
83 common_crop_t *scaling_parms);
84int (*LINK_camframe_terminate)(void);
85int8_t (*LINK_jpeg_encoder_setMainImageQuality)(uint32_t quality);
86int8_t (*LINK_jpeg_encoder_setThumbnailQuality)(uint32_t quality);
87int8_t (*LINK_jpeg_encoder_setRotation)(uint32_t rotation);
88int8_t (*LINK_jpeg_encoder_setLocation)(const camera_position_type *location);
89const struct camera_size_type *(*LINK_default_sensor_get_snapshot_sizes)(int *len);
90int (*LINK_launch_cam_conf_thread)(void);
91int (*LINK_release_cam_conf_thread)(void);
92int8_t (*LINK_zoom_crop_upscale)(uint32_t width, uint32_t height,
93 uint32_t cropped_width, uint32_t cropped_height, uint8_t *img_buf);
94
95// callbacks
96void (**LINK_mmcamera_camframe_callback)(struct msm_frame *frame);
97void (**LINK_mmcamera_jpegfragment_callback)(uint8_t *buff_ptr,
98 uint32_t buff_size);
99void (**LINK_mmcamera_jpeg_callback)(jpeg_event_t status);
100void (**LINK_mmcamera_shutter_callback)(common_crop_t *crop);
101#else
102#define LINK_cam_conf cam_conf
103#define LINK_cam_frame cam_frame
104#define LINK_jpeg_encoder_init jpeg_encoder_init
105#define LINK_jpeg_encoder_join jpeg_encoder_join
106#define LINK_jpeg_encoder_encode jpeg_encoder_encode
107#define LINK_camframe_terminate camframe_terminate
108#define LINK_jpeg_encoder_setMainImageQuality jpeg_encoder_setMainImageQuality
109#define LINK_jpeg_encoder_setThumbnailQuality jpeg_encoder_setThumbnailQuality
110#define LINK_jpeg_encoder_setRotation jpeg_encoder_setRotation
111#define LINK_jpeg_encoder_setLocation jpeg_encoder_setLocation
112#define LINK_default_sensor_get_snapshot_sizes default_sensor_get_snapshot_sizes
113#define LINK_launch_cam_conf_thread launch_cam_conf_thread
114#define LINK_release_cam_conf_thread release_cam_conf_thread
115#define LINK_zoom_crop_upscale zoom_crop_upscale
116extern void (*mmcamera_camframe_callback)(struct msm_frame *frame);
117extern void (*mmcamera_jpegfragment_callback)(uint8_t *buff_ptr,
118 uint32_t buff_size);
119extern void (*mmcamera_jpeg_callback)(jpeg_event_t status);
120extern void (*mmcamera_shutter_callback)(common_crop_t *crop);
121#endif
122
123} // extern "C"
124
125#ifndef HAVE_CAMERA_SIZE_TYPE
126struct camera_size_type {
127 int width;
128 int height;
129};
130#endif
131
132#define DEFAULT_PREVIEW_SETTING 2
133static const camera_size_type preview_sizes[] = {
134 { 1280, 720 }, // 720P, reserved
135 { 800, 480 }, // WVGA
136 { 720, 480 },
137 { 640, 480 }, // VGA
138 { 576, 432 },
139 { 480, 320 }, // HVGA
140 { 384, 288 },
141 { 352, 288 }, // CIF
142 { 320, 240 }, // QVGA
143 { 240, 160 }, // SQVGA
144 { 176, 144 }, // QCIF
145};
146#define PREVIEW_SIZE_COUNT (sizeof(preview_sizes)/sizeof(camera_size_type))
147
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800148//static const camera_size_type* picture_sizes;
149//static int PICTURE_SIZE_COUNT;
150/* TODO
151 * Ideally this should be a populated by lower layers.
152 * But currently this is no API to do that at lower layer.
153 * Hence populating with default sizes for now. This needs
154 * to be changed once the API is supported.
155 */
156static const camera_size_type picture_sizes[] = {
157 { 2592, 1944 }, // 5MP
158 { 2048, 1536 }, // 3MP
159 { 1600, 1200 }, // 2MP
160 { 800, 480 }, // WVGA
161 { 640, 480 }, // VGA
162 { 320, 240 } // QVGA
163};
164static int PICTURE_SIZE_COUNT = sizeof(picture_sizes)/sizeof(camera_size_type);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800165
166static int attr_lookup(const str_map arr[], int len, const char *name)
167{
168 if (name) {
169 for (int i = 0; i < len; i++) {
170 if (!strcmp(arr[i].desc, name))
171 return arr[i].val;
172 }
173 }
174 return NOT_FOUND;
175}
176
177// round to the next power of two
178static inline unsigned clp2(unsigned x)
179{
180 x = x - 1;
181 x = x | (x >> 1);
182 x = x | (x >> 2);
183 x = x | (x >> 4);
184 x = x | (x >> 8);
185 x = x | (x >>16);
186 return x + 1;
187}
188
189namespace android {
190// from aeecamera.h
191static const str_map whitebalance[] = {
192 { CameraParameters::WHITE_BALANCE_AUTO, CAMERA_WB_AUTO },
193 { CameraParameters::WHITE_BALANCE_INCANDESCENT, CAMERA_WB_INCANDESCENT },
194 { CameraParameters::WHITE_BALANCE_FLUORESCENT, CAMERA_WB_FLUORESCENT },
195 { CameraParameters::WHITE_BALANCE_DAYLIGHT, CAMERA_WB_DAYLIGHT },
196 { CameraParameters::WHITE_BALANCE_CLOUDY_DAYLIGHT, CAMERA_WB_CLOUDY_DAYLIGHT }
197};
198
199// from camera_effect_t. This list must match aeecamera.h
200static const str_map effects[] = {
201 { CameraParameters::EFFECT_NONE, CAMERA_EFFECT_OFF },
202 { CameraParameters::EFFECT_MONO, CAMERA_EFFECT_MONO },
203 { CameraParameters::EFFECT_NEGATIVE, CAMERA_EFFECT_NEGATIVE },
204 { CameraParameters::EFFECT_SOLARIZE, CAMERA_EFFECT_SOLARIZE },
205 { CameraParameters::EFFECT_SEPIA, CAMERA_EFFECT_SEPIA },
206 { CameraParameters::EFFECT_POSTERIZE, CAMERA_EFFECT_POSTERIZE },
207 { CameraParameters::EFFECT_WHITEBOARD, CAMERA_EFFECT_WHITEBOARD },
208 { CameraParameters::EFFECT_BLACKBOARD, CAMERA_EFFECT_BLACKBOARD },
209 { CameraParameters::EFFECT_AQUA, CAMERA_EFFECT_AQUA }
210};
211
212// from qcamera/common/camera.h
213static const str_map antibanding[] = {
214 { CameraParameters::ANTIBANDING_OFF, CAMERA_ANTIBANDING_OFF },
215 { CameraParameters::ANTIBANDING_50HZ, CAMERA_ANTIBANDING_50HZ },
216 { CameraParameters::ANTIBANDING_60HZ, CAMERA_ANTIBANDING_60HZ },
217 { CameraParameters::ANTIBANDING_AUTO, CAMERA_ANTIBANDING_AUTO }
218};
219
220/* Mapping from MCC to antibanding type */
221struct country_map {
222 uint32_t country_code;
223 camera_antibanding_type type;
224};
225
226static struct country_map country_numeric[] = {
227 { 202, CAMERA_ANTIBANDING_50HZ }, // Greece
228 { 204, CAMERA_ANTIBANDING_50HZ }, // Netherlands
229 { 206, CAMERA_ANTIBANDING_50HZ }, // Belgium
230 { 208, CAMERA_ANTIBANDING_50HZ }, // France
231 { 212, CAMERA_ANTIBANDING_50HZ }, // Monaco
232 { 213, CAMERA_ANTIBANDING_50HZ }, // Andorra
233 { 214, CAMERA_ANTIBANDING_50HZ }, // Spain
234 { 216, CAMERA_ANTIBANDING_50HZ }, // Hungary
235 { 219, CAMERA_ANTIBANDING_50HZ }, // Croatia
236 { 220, CAMERA_ANTIBANDING_50HZ }, // Serbia
237 { 222, CAMERA_ANTIBANDING_50HZ }, // Italy
238 { 226, CAMERA_ANTIBANDING_50HZ }, // Romania
239 { 228, CAMERA_ANTIBANDING_50HZ }, // Switzerland
240 { 230, CAMERA_ANTIBANDING_50HZ }, // Czech Republic
241 { 231, CAMERA_ANTIBANDING_50HZ }, // Slovakia
242 { 232, CAMERA_ANTIBANDING_50HZ }, // Austria
243 { 234, CAMERA_ANTIBANDING_50HZ }, // United Kingdom
244 { 235, CAMERA_ANTIBANDING_50HZ }, // United Kingdom
245 { 238, CAMERA_ANTIBANDING_50HZ }, // Denmark
246 { 240, CAMERA_ANTIBANDING_50HZ }, // Sweden
247 { 242, CAMERA_ANTIBANDING_50HZ }, // Norway
248 { 244, CAMERA_ANTIBANDING_50HZ }, // Finland
249 { 246, CAMERA_ANTIBANDING_50HZ }, // Lithuania
250 { 247, CAMERA_ANTIBANDING_50HZ }, // Latvia
251 { 248, CAMERA_ANTIBANDING_50HZ }, // Estonia
252 { 250, CAMERA_ANTIBANDING_50HZ }, // Russian Federation
253 { 255, CAMERA_ANTIBANDING_50HZ }, // Ukraine
254 { 257, CAMERA_ANTIBANDING_50HZ }, // Belarus
255 { 259, CAMERA_ANTIBANDING_50HZ }, // Moldova
256 { 260, CAMERA_ANTIBANDING_50HZ }, // Poland
257 { 262, CAMERA_ANTIBANDING_50HZ }, // Germany
258 { 266, CAMERA_ANTIBANDING_50HZ }, // Gibraltar
259 { 268, CAMERA_ANTIBANDING_50HZ }, // Portugal
260 { 270, CAMERA_ANTIBANDING_50HZ }, // Luxembourg
261 { 272, CAMERA_ANTIBANDING_50HZ }, // Ireland
262 { 274, CAMERA_ANTIBANDING_50HZ }, // Iceland
263 { 276, CAMERA_ANTIBANDING_50HZ }, // Albania
264 { 278, CAMERA_ANTIBANDING_50HZ }, // Malta
265 { 280, CAMERA_ANTIBANDING_50HZ }, // Cyprus
266 { 282, CAMERA_ANTIBANDING_50HZ }, // Georgia
267 { 283, CAMERA_ANTIBANDING_50HZ }, // Armenia
268 { 284, CAMERA_ANTIBANDING_50HZ }, // Bulgaria
269 { 286, CAMERA_ANTIBANDING_50HZ }, // Turkey
270 { 288, CAMERA_ANTIBANDING_50HZ }, // Faroe Islands
271 { 290, CAMERA_ANTIBANDING_50HZ }, // Greenland
272 { 293, CAMERA_ANTIBANDING_50HZ }, // Slovenia
273 { 294, CAMERA_ANTIBANDING_50HZ }, // Macedonia
274 { 295, CAMERA_ANTIBANDING_50HZ }, // Liechtenstein
275 { 297, CAMERA_ANTIBANDING_50HZ }, // Montenegro
276 { 302, CAMERA_ANTIBANDING_60HZ }, // Canada
277 { 310, CAMERA_ANTIBANDING_60HZ }, // United States of America
278 { 311, CAMERA_ANTIBANDING_60HZ }, // United States of America
279 { 312, CAMERA_ANTIBANDING_60HZ }, // United States of America
280 { 313, CAMERA_ANTIBANDING_60HZ }, // United States of America
281 { 314, CAMERA_ANTIBANDING_60HZ }, // United States of America
282 { 315, CAMERA_ANTIBANDING_60HZ }, // United States of America
283 { 316, CAMERA_ANTIBANDING_60HZ }, // United States of America
284 { 330, CAMERA_ANTIBANDING_60HZ }, // Puerto Rico
285 { 334, CAMERA_ANTIBANDING_60HZ }, // Mexico
286 { 338, CAMERA_ANTIBANDING_50HZ }, // Jamaica
287 { 340, CAMERA_ANTIBANDING_50HZ }, // Martinique
288 { 342, CAMERA_ANTIBANDING_50HZ }, // Barbados
289 { 346, CAMERA_ANTIBANDING_60HZ }, // Cayman Islands
290 { 350, CAMERA_ANTIBANDING_60HZ }, // Bermuda
291 { 352, CAMERA_ANTIBANDING_50HZ }, // Grenada
292 { 354, CAMERA_ANTIBANDING_60HZ }, // Montserrat
293 { 362, CAMERA_ANTIBANDING_50HZ }, // Netherlands Antilles
294 { 363, CAMERA_ANTIBANDING_60HZ }, // Aruba
295 { 364, CAMERA_ANTIBANDING_60HZ }, // Bahamas
296 { 365, CAMERA_ANTIBANDING_60HZ }, // Anguilla
297 { 366, CAMERA_ANTIBANDING_50HZ }, // Dominica
298 { 368, CAMERA_ANTIBANDING_60HZ }, // Cuba
299 { 370, CAMERA_ANTIBANDING_60HZ }, // Dominican Republic
300 { 372, CAMERA_ANTIBANDING_60HZ }, // Haiti
301 { 401, CAMERA_ANTIBANDING_50HZ }, // Kazakhstan
302 { 402, CAMERA_ANTIBANDING_50HZ }, // Bhutan
303 { 404, CAMERA_ANTIBANDING_50HZ }, // India
304 { 405, CAMERA_ANTIBANDING_50HZ }, // India
305 { 410, CAMERA_ANTIBANDING_50HZ }, // Pakistan
306 { 413, CAMERA_ANTIBANDING_50HZ }, // Sri Lanka
307 { 414, CAMERA_ANTIBANDING_50HZ }, // Myanmar
308 { 415, CAMERA_ANTIBANDING_50HZ }, // Lebanon
309 { 416, CAMERA_ANTIBANDING_50HZ }, // Jordan
310 { 417, CAMERA_ANTIBANDING_50HZ }, // Syria
311 { 418, CAMERA_ANTIBANDING_50HZ }, // Iraq
312 { 419, CAMERA_ANTIBANDING_50HZ }, // Kuwait
313 { 420, CAMERA_ANTIBANDING_60HZ }, // Saudi Arabia
314 { 421, CAMERA_ANTIBANDING_50HZ }, // Yemen
315 { 422, CAMERA_ANTIBANDING_50HZ }, // Oman
316 { 424, CAMERA_ANTIBANDING_50HZ }, // United Arab Emirates
317 { 425, CAMERA_ANTIBANDING_50HZ }, // Israel
318 { 426, CAMERA_ANTIBANDING_50HZ }, // Bahrain
319 { 427, CAMERA_ANTIBANDING_50HZ }, // Qatar
320 { 428, CAMERA_ANTIBANDING_50HZ }, // Mongolia
321 { 429, CAMERA_ANTIBANDING_50HZ }, // Nepal
322 { 430, CAMERA_ANTIBANDING_50HZ }, // United Arab Emirates
323 { 431, CAMERA_ANTIBANDING_50HZ }, // United Arab Emirates
324 { 432, CAMERA_ANTIBANDING_50HZ }, // Iran
325 { 434, CAMERA_ANTIBANDING_50HZ }, // Uzbekistan
326 { 436, CAMERA_ANTIBANDING_50HZ }, // Tajikistan
327 { 437, CAMERA_ANTIBANDING_50HZ }, // Kyrgyz Rep
328 { 438, CAMERA_ANTIBANDING_50HZ }, // Turkmenistan
329 { 440, CAMERA_ANTIBANDING_60HZ }, // Japan
330 { 441, CAMERA_ANTIBANDING_60HZ }, // Japan
331 { 452, CAMERA_ANTIBANDING_50HZ }, // Vietnam
332 { 454, CAMERA_ANTIBANDING_50HZ }, // Hong Kong
333 { 455, CAMERA_ANTIBANDING_50HZ }, // Macao
334 { 456, CAMERA_ANTIBANDING_50HZ }, // Cambodia
335 { 457, CAMERA_ANTIBANDING_50HZ }, // Laos
336 { 460, CAMERA_ANTIBANDING_50HZ }, // China
337 { 466, CAMERA_ANTIBANDING_60HZ }, // Taiwan
338 { 470, CAMERA_ANTIBANDING_50HZ }, // Bangladesh
339 { 472, CAMERA_ANTIBANDING_50HZ }, // Maldives
340 { 502, CAMERA_ANTIBANDING_50HZ }, // Malaysia
341 { 505, CAMERA_ANTIBANDING_50HZ }, // Australia
342 { 510, CAMERA_ANTIBANDING_50HZ }, // Indonesia
343 { 514, CAMERA_ANTIBANDING_50HZ }, // East Timor
344 { 515, CAMERA_ANTIBANDING_60HZ }, // Philippines
345 { 520, CAMERA_ANTIBANDING_50HZ }, // Thailand
346 { 525, CAMERA_ANTIBANDING_50HZ }, // Singapore
347 { 530, CAMERA_ANTIBANDING_50HZ }, // New Zealand
348 { 535, CAMERA_ANTIBANDING_60HZ }, // Guam
349 { 536, CAMERA_ANTIBANDING_50HZ }, // Nauru
350 { 537, CAMERA_ANTIBANDING_50HZ }, // Papua New Guinea
351 { 539, CAMERA_ANTIBANDING_50HZ }, // Tonga
352 { 541, CAMERA_ANTIBANDING_50HZ }, // Vanuatu
353 { 542, CAMERA_ANTIBANDING_50HZ }, // Fiji
354 { 544, CAMERA_ANTIBANDING_60HZ }, // American Samoa
355 { 545, CAMERA_ANTIBANDING_50HZ }, // Kiribati
356 { 546, CAMERA_ANTIBANDING_50HZ }, // New Caledonia
357 { 548, CAMERA_ANTIBANDING_50HZ }, // Cook Islands
358 { 602, CAMERA_ANTIBANDING_50HZ }, // Egypt
359 { 603, CAMERA_ANTIBANDING_50HZ }, // Algeria
360 { 604, CAMERA_ANTIBANDING_50HZ }, // Morocco
361 { 605, CAMERA_ANTIBANDING_50HZ }, // Tunisia
362 { 606, CAMERA_ANTIBANDING_50HZ }, // Libya
363 { 607, CAMERA_ANTIBANDING_50HZ }, // Gambia
364 { 608, CAMERA_ANTIBANDING_50HZ }, // Senegal
365 { 609, CAMERA_ANTIBANDING_50HZ }, // Mauritania
366 { 610, CAMERA_ANTIBANDING_50HZ }, // Mali
367 { 611, CAMERA_ANTIBANDING_50HZ }, // Guinea
368 { 613, CAMERA_ANTIBANDING_50HZ }, // Burkina Faso
369 { 614, CAMERA_ANTIBANDING_50HZ }, // Niger
370 { 616, CAMERA_ANTIBANDING_50HZ }, // Benin
371 { 617, CAMERA_ANTIBANDING_50HZ }, // Mauritius
372 { 618, CAMERA_ANTIBANDING_50HZ }, // Liberia
373 { 619, CAMERA_ANTIBANDING_50HZ }, // Sierra Leone
374 { 620, CAMERA_ANTIBANDING_50HZ }, // Ghana
375 { 621, CAMERA_ANTIBANDING_50HZ }, // Nigeria
376 { 622, CAMERA_ANTIBANDING_50HZ }, // Chad
377 { 623, CAMERA_ANTIBANDING_50HZ }, // Central African Republic
378 { 624, CAMERA_ANTIBANDING_50HZ }, // Cameroon
379 { 625, CAMERA_ANTIBANDING_50HZ }, // Cape Verde
380 { 627, CAMERA_ANTIBANDING_50HZ }, // Equatorial Guinea
381 { 631, CAMERA_ANTIBANDING_50HZ }, // Angola
382 { 633, CAMERA_ANTIBANDING_50HZ }, // Seychelles
383 { 634, CAMERA_ANTIBANDING_50HZ }, // Sudan
384 { 636, CAMERA_ANTIBANDING_50HZ }, // Ethiopia
385 { 637, CAMERA_ANTIBANDING_50HZ }, // Somalia
386 { 638, CAMERA_ANTIBANDING_50HZ }, // Djibouti
387 { 639, CAMERA_ANTIBANDING_50HZ }, // Kenya
388 { 640, CAMERA_ANTIBANDING_50HZ }, // Tanzania
389 { 641, CAMERA_ANTIBANDING_50HZ }, // Uganda
390 { 642, CAMERA_ANTIBANDING_50HZ }, // Burundi
391 { 643, CAMERA_ANTIBANDING_50HZ }, // Mozambique
392 { 645, CAMERA_ANTIBANDING_50HZ }, // Zambia
393 { 646, CAMERA_ANTIBANDING_50HZ }, // Madagascar
394 { 647, CAMERA_ANTIBANDING_50HZ }, // France
395 { 648, CAMERA_ANTIBANDING_50HZ }, // Zimbabwe
396 { 649, CAMERA_ANTIBANDING_50HZ }, // Namibia
397 { 650, CAMERA_ANTIBANDING_50HZ }, // Malawi
398 { 651, CAMERA_ANTIBANDING_50HZ }, // Lesotho
399 { 652, CAMERA_ANTIBANDING_50HZ }, // Botswana
400 { 653, CAMERA_ANTIBANDING_50HZ }, // Swaziland
401 { 654, CAMERA_ANTIBANDING_50HZ }, // Comoros
402 { 655, CAMERA_ANTIBANDING_50HZ }, // South Africa
403 { 657, CAMERA_ANTIBANDING_50HZ }, // Eritrea
404 { 702, CAMERA_ANTIBANDING_60HZ }, // Belize
405 { 704, CAMERA_ANTIBANDING_60HZ }, // Guatemala
406 { 706, CAMERA_ANTIBANDING_60HZ }, // El Salvador
407 { 708, CAMERA_ANTIBANDING_60HZ }, // Honduras
408 { 710, CAMERA_ANTIBANDING_60HZ }, // Nicaragua
409 { 712, CAMERA_ANTIBANDING_60HZ }, // Costa Rica
410 { 714, CAMERA_ANTIBANDING_60HZ }, // Panama
411 { 722, CAMERA_ANTIBANDING_50HZ }, // Argentina
412 { 724, CAMERA_ANTIBANDING_60HZ }, // Brazil
413 { 730, CAMERA_ANTIBANDING_50HZ }, // Chile
414 { 732, CAMERA_ANTIBANDING_60HZ }, // Colombia
415 { 734, CAMERA_ANTIBANDING_60HZ }, // Venezuela
416 { 736, CAMERA_ANTIBANDING_50HZ }, // Bolivia
417 { 738, CAMERA_ANTIBANDING_60HZ }, // Guyana
418 { 740, CAMERA_ANTIBANDING_60HZ }, // Ecuador
419 { 742, CAMERA_ANTIBANDING_50HZ }, // French Guiana
420 { 744, CAMERA_ANTIBANDING_50HZ }, // Paraguay
421 { 746, CAMERA_ANTIBANDING_60HZ }, // Suriname
422 { 748, CAMERA_ANTIBANDING_50HZ }, // Uruguay
423 { 750, CAMERA_ANTIBANDING_50HZ }, // Falkland Islands
424};
425
426#define country_number (sizeof(country_numeric) / sizeof(country_map))
427
428/* Look up pre-sorted antibanding_type table by current MCC. */
429static camera_antibanding_type camera_get_location(void) {
430 char value[PROP_VALUE_MAX];
431 char country_value[PROP_VALUE_MAX];
432 uint32_t country_code, count;
433 memset(value, 0x00, sizeof(value));
434 memset(country_value, 0x00, sizeof(country_value));
435 if (!__system_property_get("gsm.operator.numeric", value)) {
436 return CAMERA_ANTIBANDING_60HZ;
437 }
438 memcpy(country_value, value, 3);
439 country_code = atoi(country_value);
440 LOGD("value:%s, country value:%s, country code:%d\n",
441 value, country_value, country_code);
442 int left = 0;
443 int right = country_number - 1;
444 while (left <= right) {
445 int index = (left + right) >> 1;
446 if (country_numeric[index].country_code == country_code)
447 return country_numeric[index].type;
448 else if (country_numeric[index].country_code > country_code)
449 right = index - 1;
450 else
451 left = index + 1;
452 }
453 return CAMERA_ANTIBANDING_60HZ;
454}
455
456// from camera.h, led_mode_t
457static const str_map flash[] = {
458 { CameraParameters::FLASH_MODE_OFF, LED_MODE_OFF },
459 { CameraParameters::FLASH_MODE_AUTO, LED_MODE_AUTO },
460 { CameraParameters::FLASH_MODE_ON, LED_MODE_ON }
461};
462
463#define DONT_CARE 0
464static const str_map focus_modes[] = {
465 { CameraParameters::FOCUS_MODE_AUTO, DONT_CARE },
466 { CameraParameters::FOCUS_MODE_INFINITY, DONT_CARE }
467};
468
469static bool parameter_string_initialized = false;
470static String8 preview_size_values;
471static String8 picture_size_values;
472static String8 antibanding_values;
473static String8 effect_values;
474static String8 whitebalance_values;
475static String8 flash_values;
476static String8 focus_mode_values;
477
478static String8 create_sizes_str(const camera_size_type *sizes, int len) {
479 String8 str;
480 char buffer[32];
481
482 if (len > 0) {
483 sprintf(buffer, "%dx%d", sizes[0].width, sizes[0].height);
484 str.append(buffer);
485 }
486 for (int i = 1; i < len; i++) {
487 sprintf(buffer, ",%dx%d", sizes[i].width, sizes[i].height);
488 str.append(buffer);
489 }
490 return str;
491}
492
493static String8 create_values_str(const str_map *values, int len) {
494 String8 str;
495
496 if (len > 0) {
497 str.append(values[0].desc);
498 }
499 for (int i = 1; i < len; i++) {
500 str.append(",");
501 str.append(values[i].desc);
502 }
503 return str;
504}
505
506static Mutex singleton_lock;
507static bool singleton_releasing;
508static Condition singleton_wait;
509
510static void receive_camframe_callback(struct msm_frame *frame);
511static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size);
512static void receive_jpeg_callback(jpeg_event_t status);
513static void receive_shutter_callback(common_crop_t *crop);
514
515QualcommCameraHardware::QualcommCameraHardware()
516 : mParameters(),
517 mCameraRunning(false),
518 mPreviewInitialized(false),
519 mFrameThreadRunning(false),
520 mSnapshotThreadRunning(false),
521 mReleasedRecordingFrame(false),
522 mPreviewFrameSize(0),
523 mRawSize(0),
524 mCameraControlFd(-1),
525 mAutoFocusThreadRunning(false),
526 mAutoFocusFd(-1),
527 mInPreviewCallback(false),
528 mMsgEnabled(0),
529 mNotifyCallback(0),
530 mDataCallback(0),
531 mDataCallbackTimestamp(0),
532 mCallbackCookie(0)
533{
534 memset(&mDimension, 0, sizeof(mDimension));
535 memset(&mCrop, 0, sizeof(mCrop));
536 LOGV("constructor EX");
537}
538
539void QualcommCameraHardware::initDefaultParameters()
540{
541 LOGV("initDefaultParameters E");
542
543 // Initialize constant parameter strings. This will happen only once in the
544 // lifetime of the mediaserver process.
545 if (!parameter_string_initialized) {
546 antibanding_values = create_values_str(
547 antibanding, sizeof(antibanding) / sizeof(str_map));
548 effect_values = create_values_str(
549 effects, sizeof(effects) / sizeof(str_map));
550 whitebalance_values = create_values_str(
551 whitebalance, sizeof(whitebalance) / sizeof(str_map));
552 preview_size_values = create_sizes_str(
553 preview_sizes, PREVIEW_SIZE_COUNT);
554 picture_size_values = create_sizes_str(
555 picture_sizes, PICTURE_SIZE_COUNT);
556 flash_values = create_values_str(
557 flash, sizeof(flash) / sizeof(str_map));
558 focus_mode_values = create_values_str(
559 focus_modes, sizeof(focus_modes) / sizeof(str_map));
560 parameter_string_initialized = true;
561 }
562
563 const camera_size_type *ps = &preview_sizes[DEFAULT_PREVIEW_SETTING];
564 mParameters.setPreviewSize(ps->width, ps->height);
565 mDimension.display_width = ps->width;
566 mDimension.display_height = ps->height;
567 mParameters.setPreviewFrameRate(15);
568 mParameters.setPreviewFormat("yuv420sp"); // informative
569
570 mParameters.setPictureSize(DEFAULT_PICTURE_WIDTH, DEFAULT_PICTURE_HEIGHT);
571 mParameters.setPictureFormat("jpeg"); // informative
572
573 mParameters.set(CameraParameters::KEY_JPEG_QUALITY, "100"); // max quality
574 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH,
575 THUMBNAIL_WIDTH_STR); // informative
576 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT,
577 THUMBNAIL_HEIGHT_STR); // informative
578 mDimension.ui_thumbnail_width = THUMBNAIL_WIDTH;
579 mDimension.ui_thumbnail_height = THUMBNAIL_HEIGHT;
580 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, "90");
581
582 mParameters.set(CameraParameters::KEY_ANTIBANDING,
583 CameraParameters::ANTIBANDING_AUTO);
584 mParameters.set(CameraParameters::KEY_EFFECT,
585 CameraParameters::EFFECT_NONE);
586 mParameters.set(CameraParameters::KEY_WHITE_BALANCE,
587 CameraParameters::WHITE_BALANCE_AUTO);
588 mParameters.set(CameraParameters::KEY_FOCUS_MODE,
589 CameraParameters::FOCUS_MODE_AUTO);
590
591 mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES,
592 preview_size_values.string());
593 mParameters.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES,
594 picture_size_values.string());
595 mParameters.set(CameraParameters::KEY_SUPPORTED_ANTIBANDING,
596 antibanding_values);
597 mParameters.set(CameraParameters::KEY_SUPPORTED_EFFECTS, effect_values);
598 mParameters.set(CameraParameters::KEY_SUPPORTED_WHITE_BALANCE,
599 whitebalance_values);
600 mParameters.set(CameraParameters::KEY_SUPPORTED_FOCUS_MODES,
601 focus_mode_values);
602
603 if (mSensorInfo.flash_enabled) {
604 mParameters.set(CameraParameters::KEY_FLASH_MODE,
605 CameraParameters::FLASH_MODE_OFF);
606 mParameters.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES,
607 flash_values);
608 }
609
610 mParameters.set("zoom-supported", "true");
611 mParameters.set("max-zoom", MAX_ZOOM_LEVEL);
612 mParameters.set("zoom", 0);
613
614 if (setParameters(mParameters) != NO_ERROR) {
615 LOGE("Failed to set default parameters?!");
616 }
617
618 LOGV("initDefaultParameters X");
619}
620
621#define ROUND_TO_PAGE(x) (((x)+0xfff)&~0xfff)
622
623bool QualcommCameraHardware::startCamera()
624{
625 LOGV("startCamera E");
626#if DLOPEN_LIBMMCAMERA
627 libmmcamera = ::dlopen("liboemcamera.so", RTLD_NOW);
628 LOGV("loading liboemcamera at %p", libmmcamera);
629 if (!libmmcamera) {
630 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
631 return false;
632 }
633
634 *(void **)&LINK_cam_frame =
635 ::dlsym(libmmcamera, "cam_frame");
636 *(void **)&LINK_camframe_terminate =
637 ::dlsym(libmmcamera, "camframe_terminate");
638
639 *(void **)&LINK_jpeg_encoder_init =
640 ::dlsym(libmmcamera, "jpeg_encoder_init");
641
642 *(void **)&LINK_jpeg_encoder_encode =
643 ::dlsym(libmmcamera, "jpeg_encoder_encode");
644
645 *(void **)&LINK_jpeg_encoder_join =
646 ::dlsym(libmmcamera, "jpeg_encoder_join");
647
648 *(void **)&LINK_mmcamera_camframe_callback =
649 ::dlsym(libmmcamera, "mmcamera_camframe_callback");
650
651 *LINK_mmcamera_camframe_callback = receive_camframe_callback;
652
653 *(void **)&LINK_mmcamera_jpegfragment_callback =
654 ::dlsym(libmmcamera, "mmcamera_jpegfragment_callback");
655
656 *LINK_mmcamera_jpegfragment_callback = receive_jpeg_fragment_callback;
657
658 *(void **)&LINK_mmcamera_jpeg_callback =
659 ::dlsym(libmmcamera, "mmcamera_jpeg_callback");
660
661 *LINK_mmcamera_jpeg_callback = receive_jpeg_callback;
662
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800663/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800664 *(void **)&LINK_mmcamera_shutter_callback =
665 ::dlsym(libmmcamera, "mmcamera_shutter_callback");
666
667 *LINK_mmcamera_shutter_callback = receive_shutter_callback;
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800668*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800669 *(void**)&LINK_jpeg_encoder_setMainImageQuality =
670 ::dlsym(libmmcamera, "jpeg_encoder_setMainImageQuality");
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800671/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800672 *(void**)&LINK_jpeg_encoder_setThumbnailQuality =
673 ::dlsym(libmmcamera, "jpeg_encoder_setThumbnailQuality");
674
675 *(void**)&LINK_jpeg_encoder_setRotation =
676 ::dlsym(libmmcamera, "jpeg_encoder_setRotation");
677
678 *(void**)&LINK_jpeg_encoder_setLocation =
679 ::dlsym(libmmcamera, "jpeg_encoder_setLocation");
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800680*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800681 *(void **)&LINK_cam_conf =
682 ::dlsym(libmmcamera, "cam_conf");
683
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800684/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800685 *(void **)&LINK_default_sensor_get_snapshot_sizes =
686 ::dlsym(libmmcamera, "default_sensor_get_snapshot_sizes");
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800687*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800688 *(void **)&LINK_launch_cam_conf_thread =
689 ::dlsym(libmmcamera, "launch_cam_conf_thread");
690
691 *(void **)&LINK_release_cam_conf_thread =
692 ::dlsym(libmmcamera, "release_cam_conf_thread");
693
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800694/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800695 *(void **)&LINK_zoom_crop_upscale =
696 ::dlsym(libmmcamera, "zoom_crop_upscale");
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800697*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800698
699#else
700 mmcamera_camframe_callback = receive_camframe_callback;
701 mmcamera_jpegfragment_callback = receive_jpeg_fragment_callback;
702 mmcamera_jpeg_callback = receive_jpeg_callback;
703 mmcamera_shutter_callback = receive_shutter_callback;
704#endif // DLOPEN_LIBMMCAMERA
705
706 /* The control thread is in libcamera itself. */
707 mCameraControlFd = open(MSM_CAMERA_CONTROL, O_RDWR);
708 if (mCameraControlFd < 0) {
709 LOGE("startCamera X: %s open failed: %s!",
710 MSM_CAMERA_CONTROL,
711 strerror(errno));
712 return false;
713 }
714
715 /* This will block until the control thread is launched. After that, sensor
716 * information becomes available.
717 */
718
719 if (LINK_launch_cam_conf_thread()) {
720 LOGE("failed to launch the camera config thread");
721 return false;
722 }
723
724 memset(&mSensorInfo, 0, sizeof(mSensorInfo));
725 if (ioctl(mCameraControlFd,
726 MSM_CAM_IOCTL_GET_SENSOR_INFO,
727 &mSensorInfo) < 0)
728 LOGW("%s: cannot retrieve sensor info!", __FUNCTION__);
729 else
730 LOGI("%s: camsensor name %s, flash %d", __FUNCTION__,
731 mSensorInfo.name, mSensorInfo.flash_enabled);
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800732/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800733 picture_sizes = LINK_default_sensor_get_snapshot_sizes(&PICTURE_SIZE_COUNT);
734 if (!picture_sizes || !PICTURE_SIZE_COUNT) {
735 LOGE("startCamera X: could not get snapshot sizes");
736 return false;
737 }
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800738*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800739 LOGV("startCamera X");
740 return true;
741}
742
743status_t QualcommCameraHardware::dump(int fd,
744 const Vector<String16>& args) const
745{
746 const size_t SIZE = 256;
747 char buffer[SIZE];
748 String8 result;
749
750 // Dump internal primitives.
751 result.append("QualcommCameraHardware::dump");
752 snprintf(buffer, 255, "mMsgEnabled (%d)\n", mMsgEnabled);
753 result.append(buffer);
754 int width, height;
755 mParameters.getPreviewSize(&width, &height);
756 snprintf(buffer, 255, "preview width(%d) x height (%d)\n", width, height);
757 result.append(buffer);
758 mParameters.getPictureSize(&width, &height);
759 snprintf(buffer, 255, "raw width(%d) x height (%d)\n", width, height);
760 result.append(buffer);
761 snprintf(buffer, 255,
762 "preview frame size(%d), raw size (%d), jpeg size (%d) "
763 "and jpeg max size (%d)\n", mPreviewFrameSize, mRawSize,
764 mJpegSize, mJpegMaxSize);
765 result.append(buffer);
766 write(fd, result.string(), result.size());
767
768 // Dump internal objects.
769 if (mPreviewHeap != 0) {
770 mPreviewHeap->dump(fd, args);
771 }
772 if (mRawHeap != 0) {
773 mRawHeap->dump(fd, args);
774 }
775 if (mJpegHeap != 0) {
776 mJpegHeap->dump(fd, args);
777 }
778 mParameters.dump(fd, args);
779 return NO_ERROR;
780}
781
782static bool native_set_afmode(int camfd, isp3a_af_mode_t af_type)
783{
784 int rc;
785 struct msm_ctrl_cmd ctrlCmd;
786
787 ctrlCmd.timeout_ms = 5000;
788 ctrlCmd.type = CAMERA_SET_PARM_AUTO_FOCUS;
789 ctrlCmd.length = sizeof(af_type);
790 ctrlCmd.value = &af_type;
791 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
792
793 if ((rc = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0)
794 LOGE("native_set_afmode: ioctl fd %d error %s\n",
795 camfd,
796 strerror(errno));
797
798 LOGV("native_set_afmode: ctrlCmd.status == %d\n", ctrlCmd.status);
799 return rc >= 0 && ctrlCmd.status == CAMERA_EXIT_CB_DONE;
800}
801
802static bool native_cancel_afmode(int camfd, int af_fd)
803{
804 int rc;
805 struct msm_ctrl_cmd ctrlCmd;
806
807 ctrlCmd.timeout_ms = 0;
808 ctrlCmd.type = CAMERA_AUTO_FOCUS_CANCEL;
809 ctrlCmd.length = 0;
810 ctrlCmd.value = NULL;
811 ctrlCmd.resp_fd = -1; // there's no response fd
812
813 if ((rc = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND_2, &ctrlCmd)) < 0)
814 {
815 LOGE("native_cancel_afmode: ioctl fd %d error %s\n",
816 camfd,
817 strerror(errno));
818 return false;
819 }
820
821 return true;
822}
823
824static bool native_start_preview(int camfd)
825{
826 struct msm_ctrl_cmd ctrlCmd;
827
828 ctrlCmd.timeout_ms = 5000;
829 ctrlCmd.type = CAMERA_START_PREVIEW;
830 ctrlCmd.length = 0;
831 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
832
833 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
834 LOGE("native_start_preview: MSM_CAM_IOCTL_CTRL_COMMAND fd %d error %s",
835 camfd,
836 strerror(errno));
837 return false;
838 }
839
840 return true;
841}
842
843static bool native_get_picture (int camfd, common_crop_t *crop)
844{
845 struct msm_ctrl_cmd ctrlCmd;
846
847 ctrlCmd.timeout_ms = 5000;
848 ctrlCmd.length = sizeof(common_crop_t);
849 ctrlCmd.value = crop;
850
851 if(ioctl(camfd, MSM_CAM_IOCTL_GET_PICTURE, &ctrlCmd) < 0) {
852 LOGE("native_get_picture: MSM_CAM_IOCTL_GET_PICTURE fd %d error %s",
853 camfd,
854 strerror(errno));
855 return false;
856 }
857
858 LOGV("crop: in1_w %d", crop->in1_w);
859 LOGV("crop: in1_h %d", crop->in1_h);
860 LOGV("crop: out1_w %d", crop->out1_w);
861 LOGV("crop: out1_h %d", crop->out1_h);
862
863 LOGV("crop: in2_w %d", crop->in2_w);
864 LOGV("crop: in2_h %d", crop->in2_h);
865 LOGV("crop: out2_w %d", crop->out2_w);
866 LOGV("crop: out2_h %d", crop->out2_h);
867
868 LOGV("crop: update %d", crop->update_flag);
869
870 return true;
871}
872
873static bool native_stop_preview(int camfd)
874{
875 struct msm_ctrl_cmd ctrlCmd;
876 ctrlCmd.timeout_ms = 5000;
877 ctrlCmd.type = CAMERA_STOP_PREVIEW;
878 ctrlCmd.length = 0;
879 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
880
881 if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
882 LOGE("native_stop_preview: ioctl fd %d error %s",
883 camfd,
884 strerror(errno));
885 return false;
886 }
887
888 return true;
889}
890
891static bool native_prepare_snapshot(int camfd)
892{
893 int ioctlRetVal = true;
894 struct msm_ctrl_cmd ctrlCmd;
895
896 ctrlCmd.timeout_ms = 1000;
897 ctrlCmd.type = CAMERA_PREPARE_SNAPSHOT;
898 ctrlCmd.length = 0;
899 ctrlCmd.value = NULL;
900 ctrlCmd.resp_fd = camfd;
901
902 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
903 LOGE("native_prepare_snapshot: ioctl fd %d error %s",
904 camfd,
905 strerror(errno));
906 return false;
907 }
908 return true;
909}
910
911static bool native_start_snapshot(int camfd)
912{
913 struct msm_ctrl_cmd ctrlCmd;
914
915 ctrlCmd.timeout_ms = 5000;
916 ctrlCmd.type = CAMERA_START_SNAPSHOT;
917 ctrlCmd.length = 0;
918 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
919
920 if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
921 LOGE("native_start_snapshot: ioctl fd %d error %s",
922 camfd,
923 strerror(errno));
924 return false;
925 }
926
927 return true;
928}
929
930static bool native_stop_snapshot (int camfd)
931{
932 struct msm_ctrl_cmd ctrlCmd;
933
934 ctrlCmd.timeout_ms = 0;
935 ctrlCmd.type = CAMERA_STOP_SNAPSHOT;
936 ctrlCmd.length = 0;
937 ctrlCmd.resp_fd = -1;
938
939 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND_2, &ctrlCmd) < 0) {
940 LOGE("native_stop_snapshot: ioctl fd %d error %s",
941 camfd,
942 strerror(errno));
943 return false;
944 }
945
946 return true;
947}
948
949bool QualcommCameraHardware::native_jpeg_encode(void)
950{
951 int jpeg_quality = mParameters.getInt("jpeg-quality");
952 if (jpeg_quality >= 0) {
953 LOGV("native_jpeg_encode, current jpeg main img quality =%d",
954 jpeg_quality);
955 if(!LINK_jpeg_encoder_setMainImageQuality(jpeg_quality)) {
956 LOGE("native_jpeg_encode set jpeg-quality failed");
957 return false;
958 }
959 }
960
961 int thumbnail_quality = mParameters.getInt("jpeg-thumbnail-quality");
962 if (thumbnail_quality >= 0) {
963 LOGV("native_jpeg_encode, current jpeg thumbnail quality =%d",
964 thumbnail_quality);
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800965/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800966 if(!LINK_jpeg_encoder_setThumbnailQuality(thumbnail_quality)) {
967 LOGE("native_jpeg_encode set thumbnail-quality failed");
968 return false;
969 }
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800970*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800971 }
972
973 int rotation = mParameters.getInt("rotation");
974 if (rotation >= 0) {
975 LOGV("native_jpeg_encode, rotation = %d", rotation);
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800976/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800977 if(!LINK_jpeg_encoder_setRotation(rotation)) {
978 LOGE("native_jpeg_encode set rotation failed");
979 return false;
980 }
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800981*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800982 }
983
984 jpeg_set_location();
985
986 if (!LINK_jpeg_encoder_encode(&mDimension,
987 (uint8_t *)mThumbnailHeap->mHeap->base(),
988 mThumbnailHeap->mHeap->getHeapID(),
989 (uint8_t *)mRawHeap->mHeap->base(),
990 mRawHeap->mHeap->getHeapID(),
991 &mCrop)) {
992 LOGE("native_jpeg_encode: jpeg_encoder_encode failed.");
993 return false;
994 }
995 return true;
996}
997
998bool QualcommCameraHardware::native_set_parm(
999 cam_ctrl_type type, uint16_t length, void *value)
1000{
1001 struct msm_ctrl_cmd ctrlCmd;
1002
1003 ctrlCmd.timeout_ms = 5000;
1004 ctrlCmd.type = (uint16_t)type;
1005 ctrlCmd.length = length;
1006 // FIXME: this will be put in by the kernel
1007 ctrlCmd.resp_fd = mCameraControlFd;
1008 ctrlCmd.value = value;
1009
1010 LOGV("%s: fd %d, type %d, length %d", __FUNCTION__,
1011 mCameraControlFd, type, length);
1012 if (ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0 ||
1013 ctrlCmd.status != CAM_CTRL_SUCCESS) {
1014 LOGE("%s: error (%s): fd %d, type %d, length %d, status %d",
1015 __FUNCTION__, strerror(errno),
1016 mCameraControlFd, type, length, ctrlCmd.status);
1017 return false;
1018 }
1019 return true;
1020}
1021
1022void QualcommCameraHardware::jpeg_set_location()
1023{
1024 bool encode_location = true;
1025 camera_position_type pt;
1026
1027#define PARSE_LOCATION(what,type,fmt,desc) do { \
1028 pt.what = 0; \
1029 const char *what##_str = mParameters.get("gps-"#what); \
1030 LOGV("GPS PARM %s --> [%s]", "gps-"#what, what##_str); \
1031 if (what##_str) { \
1032 type what = 0; \
1033 if (sscanf(what##_str, fmt, &what) == 1) \
1034 pt.what = what; \
1035 else { \
1036 LOGE("GPS " #what " %s could not" \
1037 " be parsed as a " #desc, what##_str); \
1038 encode_location = false; \
1039 } \
1040 } \
1041 else { \
1042 LOGV("GPS " #what " not specified: " \
1043 "defaulting to zero in EXIF header."); \
1044 encode_location = false; \
1045 } \
1046 } while(0)
1047
1048 PARSE_LOCATION(timestamp, long, "%ld", "long");
1049 if (!pt.timestamp) pt.timestamp = time(NULL);
1050 PARSE_LOCATION(altitude, short, "%hd", "short");
1051 PARSE_LOCATION(latitude, double, "%lf", "double float");
1052 PARSE_LOCATION(longitude, double, "%lf", "double float");
1053
1054#undef PARSE_LOCATION
1055
1056 if (encode_location) {
1057 LOGD("setting image location ALT %d LAT %lf LON %lf",
1058 pt.altitude, pt.latitude, pt.longitude);
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001059/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001060 if (!LINK_jpeg_encoder_setLocation(&pt)) {
1061 LOGE("jpeg_set_location: LINK_jpeg_encoder_setLocation failed.");
1062 }
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001063*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001064 }
1065 else LOGV("not setting image location");
1066}
1067
1068void QualcommCameraHardware::runFrameThread(void *data)
1069{
1070 LOGV("runFrameThread E");
1071
1072 int cnt;
1073
1074#if DLOPEN_LIBMMCAMERA
1075 // We need to maintain a reference to libqcamera.so for the duration of the
1076 // frame thread, because we do not know when it will exit relative to the
1077 // lifetime of this object. We do not want to dlclose() libqcamera while
1078 // LINK_cam_frame is still running.
1079 void *libhandle = ::dlopen("liboemcamera.so", RTLD_NOW);
1080 LOGV("FRAME: loading libqcamera at %p", libhandle);
1081 if (!libhandle) {
1082 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
1083 }
1084 if (libhandle)
1085#endif
1086 {
1087 LINK_cam_frame(data);
1088 }
1089
1090 mPreviewHeap.clear();
1091
1092#if DLOPEN_LIBMMCAMERA
1093 if (libhandle) {
1094 ::dlclose(libhandle);
1095 LOGV("FRAME: dlclose(libqcamera)");
1096 }
1097#endif
1098
1099 mFrameThreadWaitLock.lock();
1100 mFrameThreadRunning = false;
1101 mFrameThreadWait.signal();
1102 mFrameThreadWaitLock.unlock();
1103
1104 LOGV("runFrameThread X");
1105}
1106
1107void *frame_thread(void *user)
1108{
1109 LOGD("frame_thread E");
1110 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
1111 if (obj != 0) {
1112 obj->runFrameThread(user);
1113 }
1114 else LOGW("not starting frame thread: the object went away!");
1115 LOGD("frame_thread X");
1116 return NULL;
1117}
1118
1119bool QualcommCameraHardware::initPreview()
1120{
1121 // See comments in deinitPreview() for why we have to wait for the frame
1122 // thread here, and why we can't use pthread_join().
1123 int previewWidth, previewHeight;
1124 mParameters.getPreviewSize(&previewWidth, &previewHeight);
1125 LOGI("initPreview E: preview size=%dx%d", previewWidth, previewHeight);
1126 mFrameThreadWaitLock.lock();
1127 while (mFrameThreadRunning) {
1128 LOGV("initPreview: waiting for old frame thread to complete.");
1129 mFrameThreadWait.wait(mFrameThreadWaitLock);
1130 LOGV("initPreview: old frame thread completed.");
1131 }
1132 mFrameThreadWaitLock.unlock();
1133
1134 mSnapshotThreadWaitLock.lock();
1135 while (mSnapshotThreadRunning) {
1136 LOGV("initPreview: waiting for old snapshot thread to complete.");
1137 mSnapshotThreadWait.wait(mSnapshotThreadWaitLock);
1138 LOGV("initPreview: old snapshot thread completed.");
1139 }
1140 mSnapshotThreadWaitLock.unlock();
1141
1142 int cnt = 0;
1143 mPreviewFrameSize = previewWidth * previewHeight * 3/2;
1144 mPreviewHeap = new PmemPool("/dev/pmem_adsp",
1145 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
1146 mCameraControlFd,
1147 MSM_PMEM_OUTPUT2,
1148 mPreviewFrameSize,
1149 kPreviewBufferCount,
1150 mPreviewFrameSize,
1151 "preview");
1152
1153 if (!mPreviewHeap->initialized()) {
1154 mPreviewHeap.clear();
1155 LOGE("initPreview X: could not initialize preview heap.");
1156 return false;
1157 }
1158
1159 // mDimension will be filled with thumbnail_width, thumbnail_height,
1160 // orig_picture_dx, and orig_picture_dy after this function call. We need to
1161 // keep it for jpeg_encoder_encode.
1162 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
1163 sizeof(cam_ctrl_dimension_t), &mDimension);
1164
1165 if (ret) {
1166 for (cnt = 0; cnt < kPreviewBufferCount; cnt++) {
1167 frames[cnt].fd = mPreviewHeap->mHeap->getHeapID();
1168 frames[cnt].buffer =
1169 (uint32_t)mPreviewHeap->mHeap->base() + mPreviewHeap->mAlignedBufferSize * cnt;
1170 frames[cnt].y_off = 0;
1171 frames[cnt].cbcr_off = previewWidth * previewHeight;
1172 frames[cnt].path = MSM_FRAME_ENC;
1173 }
1174
1175 mFrameThreadWaitLock.lock();
1176 pthread_attr_t attr;
1177 pthread_attr_init(&attr);
1178 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1179 mFrameThreadRunning = !pthread_create(&mFrameThread,
1180 &attr,
1181 frame_thread,
1182 &frames[kPreviewBufferCount-1]);
1183 ret = mFrameThreadRunning;
1184 mFrameThreadWaitLock.unlock();
1185 }
1186
1187 LOGV("initPreview X: %d", ret);
1188 return ret;
1189}
1190
1191void QualcommCameraHardware::deinitPreview(void)
1192{
1193 LOGI("deinitPreview E");
1194
1195 // When we call deinitPreview(), we signal to the frame thread that it
1196 // needs to exit, but we DO NOT WAIT for it to complete here. The problem
1197 // is that deinitPreview is sometimes called from the frame-thread's
1198 // callback, when the refcount on the Camera client reaches zero. If we
1199 // called pthread_join(), we would deadlock. So, we just call
1200 // LINK_camframe_terminate() in deinitPreview(), which makes sure that
1201 // after the preview callback returns, the camframe thread will exit. We
1202 // could call pthread_join() in initPreview() to join the last frame
1203 // thread. However, we would also have to call pthread_join() in release
1204 // as well, shortly before we destroy the object; this would cause the same
1205 // deadlock, since release(), like deinitPreview(), may also be called from
1206 // the frame-thread's callback. This we have to make the frame thread
1207 // detached, and use a separate mechanism to wait for it to complete.
1208
1209 if (LINK_camframe_terminate() < 0)
1210 LOGE("failed to stop the camframe thread: %s",
1211 strerror(errno));
1212 LOGI("deinitPreview X");
1213}
1214
1215bool QualcommCameraHardware::initRaw(bool initJpegHeap)
1216{
1217 int rawWidth, rawHeight;
1218 mParameters.getPictureSize(&rawWidth, &rawHeight);
1219 LOGV("initRaw E: picture size=%dx%d", rawWidth, rawHeight);
1220
1221 // mDimension will be filled with thumbnail_width, thumbnail_height,
1222 // orig_picture_dx, and orig_picture_dy after this function call. We need to
1223 // keep it for jpeg_encoder_encode.
1224 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
1225 sizeof(cam_ctrl_dimension_t), &mDimension);
1226 if(!ret) {
1227 LOGE("initRaw X: failed to set dimension");
1228 return false;
1229 }
1230
1231 if (mJpegHeap != NULL) {
1232 LOGV("initRaw: clearing old mJpegHeap.");
1233 mJpegHeap.clear();
1234 }
1235
1236 // Snapshot
1237 mRawSize = rawWidth * rawHeight * 3 / 2;
1238 mJpegMaxSize = rawWidth * rawHeight * 3 / 2;
1239
1240 LOGV("initRaw: initializing mRawHeap.");
1241 mRawHeap =
1242 new PmemPool("/dev/pmem_camera",
1243 MemoryHeapBase::READ_ONLY,
1244 mCameraControlFd,
1245 MSM_PMEM_MAINIMG,
1246 mJpegMaxSize,
1247 kRawBufferCount,
1248 mRawSize,
1249 "snapshot camera");
1250
1251 if (!mRawHeap->initialized()) {
1252 LOGE("initRaw X failed with pmem_camera, trying with pmem_adsp");
1253 mRawHeap =
1254 new PmemPool("/dev/pmem_adsp",
1255 MemoryHeapBase::READ_ONLY,
1256 mCameraControlFd,
1257 MSM_PMEM_MAINIMG,
1258 mJpegMaxSize,
1259 kRawBufferCount,
1260 mRawSize,
1261 "snapshot camera");
1262 if (!mRawHeap->initialized()) {
1263 mRawHeap.clear();
1264 LOGE("initRaw X: error initializing mRawHeap");
1265 return false;
1266 }
1267 }
1268
1269 LOGV("do_mmap snapshot pbuf = %p, pmem_fd = %d",
1270 (uint8_t *)mRawHeap->mHeap->base(), mRawHeap->mHeap->getHeapID());
1271
1272 // Jpeg
1273
1274 if (initJpegHeap) {
1275 LOGV("initRaw: initializing mJpegHeap.");
1276 mJpegHeap =
1277 new AshmemPool(mJpegMaxSize,
1278 kJpegBufferCount,
1279 0, // we do not know how big the picture will be
1280 "jpeg");
1281
1282 if (!mJpegHeap->initialized()) {
1283 mJpegHeap.clear();
1284 mRawHeap.clear();
1285 LOGE("initRaw X failed: error initializing mJpegHeap.");
1286 return false;
1287 }
1288
1289 // Thumbnails
1290
1291 mThumbnailHeap =
1292 new PmemPool("/dev/pmem_adsp",
1293 MemoryHeapBase::READ_ONLY,
1294 mCameraControlFd,
1295 MSM_PMEM_THUMBNAIL,
1296 THUMBNAIL_BUFFER_SIZE,
1297 1,
1298 THUMBNAIL_BUFFER_SIZE,
1299 "thumbnail");
1300
1301 if (!mThumbnailHeap->initialized()) {
1302 mThumbnailHeap.clear();
1303 mJpegHeap.clear();
1304 mRawHeap.clear();
1305 LOGE("initRaw X failed: error initializing mThumbnailHeap.");
1306 return false;
1307 }
1308 }
1309
1310 LOGV("initRaw X");
1311 return true;
1312}
1313
1314void QualcommCameraHardware::deinitRaw()
1315{
1316 LOGV("deinitRaw E");
1317
1318 mThumbnailHeap.clear();
1319 mJpegHeap.clear();
1320 mRawHeap.clear();
1321 mDisplayHeap.clear();
1322
1323 LOGV("deinitRaw X");
1324}
1325
1326void QualcommCameraHardware::release()
1327{
1328 LOGD("release E");
1329 Mutex::Autolock l(&mLock);
1330
1331#if DLOPEN_LIBMMCAMERA
1332 if (libmmcamera == NULL) {
1333 LOGE("ERROR: multiple release!");
1334 return;
1335 }
1336#else
1337#warning "Cannot detect multiple release when not dlopen()ing libqcamera!"
1338#endif
1339
1340 int cnt, rc;
1341 struct msm_ctrl_cmd ctrlCmd;
1342
1343 if (mCameraRunning) {
1344 if(mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME)) {
1345 mRecordFrameLock.lock();
1346 mReleasedRecordingFrame = true;
1347 mRecordWait.signal();
1348 mRecordFrameLock.unlock();
1349 }
1350 stopPreviewInternal();
1351 }
1352
1353 LINK_jpeg_encoder_join();
1354 deinitRaw();
1355
1356 ctrlCmd.timeout_ms = 5000;
1357 ctrlCmd.length = 0;
1358 ctrlCmd.type = (uint16_t)CAMERA_EXIT;
1359 ctrlCmd.resp_fd = mCameraControlFd; // FIXME: this will be put in by the kernel
1360 if (ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0)
1361 LOGE("ioctl CAMERA_EXIT fd %d error %s",
1362 mCameraControlFd, strerror(errno));
1363
1364 LINK_release_cam_conf_thread();
1365
1366 close(mCameraControlFd);
1367 mCameraControlFd = -1;
1368
1369#if DLOPEN_LIBMMCAMERA
1370 if (libmmcamera) {
1371 ::dlclose(libmmcamera);
1372 LOGV("dlclose(libqcamera)");
1373 libmmcamera = NULL;
1374 }
1375#endif
1376
1377 Mutex::Autolock lock(&singleton_lock);
1378 singleton_releasing = true;
1379
1380 LOGD("release X");
1381}
1382
1383QualcommCameraHardware::~QualcommCameraHardware()
1384{
1385 LOGD("~QualcommCameraHardware E");
1386 Mutex::Autolock lock(&singleton_lock);
1387 singleton.clear();
1388 singleton_releasing = false;
1389 singleton_wait.signal();
1390 LOGD("~QualcommCameraHardware X");
1391}
1392
1393sp<IMemoryHeap> QualcommCameraHardware::getRawHeap() const
1394{
1395 LOGV("getRawHeap");
1396 return mDisplayHeap != NULL ? mDisplayHeap->mHeap : NULL;
1397}
1398
1399sp<IMemoryHeap> QualcommCameraHardware::getPreviewHeap() const
1400{
1401 LOGV("getPreviewHeap");
1402 return mPreviewHeap != NULL ? mPreviewHeap->mHeap : NULL;
1403}
1404
1405status_t QualcommCameraHardware::startPreviewInternal()
1406{
1407 if(mCameraRunning) {
1408 LOGV("startPreview X: preview already running.");
1409 return NO_ERROR;
1410 }
1411
1412 if (!mPreviewInitialized) {
1413 mPreviewInitialized = initPreview();
1414 if (!mPreviewInitialized) {
1415 LOGE("startPreview X initPreview failed. Not starting preview.");
1416 return UNKNOWN_ERROR;
1417 }
1418 }
1419
1420 mCameraRunning = native_start_preview(mCameraControlFd);
1421 if(!mCameraRunning) {
1422 deinitPreview();
1423 mPreviewInitialized = false;
1424 LOGE("startPreview X: native_start_preview failed!");
1425 return UNKNOWN_ERROR;
1426 }
1427
1428 LOGV("startPreview X");
1429 return NO_ERROR;
1430}
1431
1432status_t QualcommCameraHardware::startPreview()
1433{
1434 LOGV("startPreview E");
1435 Mutex::Autolock l(&mLock);
1436 return startPreviewInternal();
1437}
1438
1439void QualcommCameraHardware::stopPreviewInternal()
1440{
1441 LOGV("stopPreviewInternal E: %d", mCameraRunning);
1442 if (mCameraRunning) {
1443 // Cancel auto focus.
1444 {
1445 if (mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS)) {
1446 cancelAutoFocusInternal();
1447 }
1448 }
1449
1450 mCameraRunning = !native_stop_preview(mCameraControlFd);
1451 if (!mCameraRunning && mPreviewInitialized) {
1452 deinitPreview();
1453 mPreviewInitialized = false;
1454 }
1455 else LOGE("stopPreviewInternal: failed to stop preview");
1456 }
1457 LOGV("stopPreviewInternal X: %d", mCameraRunning);
1458}
1459
1460void QualcommCameraHardware::stopPreview()
1461{
1462 LOGV("stopPreview: E");
1463 Mutex::Autolock l(&mLock);
1464 {
1465 if (mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME))
1466 return;
1467 }
1468 stopPreviewInternal();
1469 LOGV("stopPreview: X");
1470}
1471
1472void QualcommCameraHardware::runAutoFocus()
1473{
1474 bool status = true;
1475 void *libhandle = NULL;
1476
1477 mAutoFocusThreadLock.lock();
1478 // Skip autofocus if focus mode is infinity.
1479 if (strcmp(mParameters.get(CameraParameters::KEY_FOCUS_MODE),
1480 CameraParameters::FOCUS_MODE_INFINITY) == 0) {
1481 goto done;
1482 }
1483
1484 mAutoFocusFd = open(MSM_CAMERA_CONTROL, O_RDWR);
1485 if (mAutoFocusFd < 0) {
1486 LOGE("autofocus: cannot open %s: %s",
1487 MSM_CAMERA_CONTROL,
1488 strerror(errno));
1489 mAutoFocusThreadRunning = false;
1490 mAutoFocusThreadLock.unlock();
1491 return;
1492 }
1493
1494#if DLOPEN_LIBMMCAMERA
1495 // We need to maintain a reference to libqcamera.so for the duration of the
1496 // AF thread, because we do not know when it will exit relative to the
1497 // lifetime of this object. We do not want to dlclose() libqcamera while
1498 // LINK_cam_frame is still running.
1499 libhandle = ::dlopen("liboemcamera.so", RTLD_NOW);
1500 LOGV("AF: loading libqcamera at %p", libhandle);
1501 if (!libhandle) {
1502 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
1503 close(mAutoFocusFd);
1504 mAutoFocusFd = -1;
1505 mAutoFocusThreadRunning = false;
1506 mAutoFocusThreadLock.unlock();
1507 return;
1508 }
1509#endif
1510
1511 /* This will block until either AF completes or is cancelled. */
1512 LOGV("af start (fd %d)", mAutoFocusFd);
1513 status = native_set_afmode(mAutoFocusFd, AF_MODE_AUTO);
1514 LOGV("af done: %d", (int)status);
1515 close(mAutoFocusFd);
1516 mAutoFocusFd = -1;
1517
1518done:
1519 mAutoFocusThreadRunning = false;
1520 mAutoFocusThreadLock.unlock();
1521
1522 mCallbackLock.lock();
1523 bool autoFocusEnabled = mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS);
1524 notify_callback cb = mNotifyCallback;
1525 void *data = mCallbackCookie;
1526 mCallbackLock.unlock();
1527 if (autoFocusEnabled)
1528 cb(CAMERA_MSG_FOCUS, status, 0, data);
1529
1530#if DLOPEN_LIBMMCAMERA
1531 if (libhandle) {
1532 ::dlclose(libhandle);
1533 LOGV("AF: dlclose(libqcamera)");
1534 }
1535#endif
1536}
1537
1538status_t QualcommCameraHardware::cancelAutoFocusInternal()
1539{
1540 LOGV("cancelAutoFocusInternal E");
1541
1542#if 0
1543 if (mAutoFocusFd < 0) {
1544 LOGV("cancelAutoFocusInternal X: not in progress");
1545 return NO_ERROR;
1546 }
1547#endif
1548
1549 status_t rc = native_cancel_afmode(mCameraControlFd, mAutoFocusFd) ?
1550 NO_ERROR :
1551 UNKNOWN_ERROR;
1552
1553 LOGV("cancelAutoFocusInternal X: %d", rc);
1554 return rc;
1555}
1556
1557void *auto_focus_thread(void *user)
1558{
1559 LOGV("auto_focus_thread E");
1560 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
1561 if (obj != 0) {
1562 obj->runAutoFocus();
1563 }
1564 else LOGW("not starting autofocus: the object went away!");
1565 LOGV("auto_focus_thread X");
1566 return NULL;
1567}
1568
1569status_t QualcommCameraHardware::autoFocus()
1570{
1571 LOGV("autoFocus E");
1572 Mutex::Autolock l(&mLock);
1573
1574 if (mCameraControlFd < 0) {
1575 LOGE("not starting autofocus: main control fd %d", mCameraControlFd);
1576 return UNKNOWN_ERROR;
1577 }
1578
1579 {
1580 mAutoFocusThreadLock.lock();
1581 if (!mAutoFocusThreadRunning) {
1582 // Create a detached thread here so that we don't have to wait
1583 // for it when we cancel AF.
1584 pthread_t thr;
1585 pthread_attr_t attr;
1586 pthread_attr_init(&attr);
1587 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1588 mAutoFocusThreadRunning =
1589 !pthread_create(&thr, &attr,
1590 auto_focus_thread, NULL);
1591 if (!mAutoFocusThreadRunning) {
1592 LOGE("failed to start autofocus thread");
1593 mAutoFocusThreadLock.unlock();
1594 return UNKNOWN_ERROR;
1595 }
1596 }
1597 mAutoFocusThreadLock.unlock();
1598 }
1599
1600 LOGV("autoFocus X");
1601 return NO_ERROR;
1602}
1603
1604status_t QualcommCameraHardware::cancelAutoFocus()
1605{
1606 LOGV("cancelAutoFocus E");
1607 Mutex::Autolock l(&mLock);
1608
1609 int rc = NO_ERROR;
1610 if (mCameraRunning && mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS)) {
1611 rc = cancelAutoFocusInternal();
1612 }
1613
1614 LOGV("cancelAutoFocus X");
1615 return rc;
1616}
1617
1618void QualcommCameraHardware::runSnapshotThread(void *data)
1619{
1620 LOGV("runSnapshotThread E");
1621 if (native_start_snapshot(mCameraControlFd))
1622 receiveRawPicture();
1623 else
1624 LOGE("main: native_start_snapshot failed!");
1625
1626 mSnapshotThreadWaitLock.lock();
1627 mSnapshotThreadRunning = false;
1628 mSnapshotThreadWait.signal();
1629 mSnapshotThreadWaitLock.unlock();
1630
1631 LOGV("runSnapshotThread X");
1632}
1633
1634void *snapshot_thread(void *user)
1635{
1636 LOGD("snapshot_thread E");
1637 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
1638 if (obj != 0) {
1639 obj->runSnapshotThread(user);
1640 }
1641 else LOGW("not starting snapshot thread: the object went away!");
1642 LOGD("snapshot_thread X");
1643 return NULL;
1644}
1645
1646status_t QualcommCameraHardware::takePicture()
1647{
1648 LOGV("takePicture(%d)", mMsgEnabled);
1649 Mutex::Autolock l(&mLock);
1650
1651 // Wait for old snapshot thread to complete.
1652 mSnapshotThreadWaitLock.lock();
1653 while (mSnapshotThreadRunning) {
1654 LOGV("takePicture: waiting for old snapshot thread to complete.");
1655 mSnapshotThreadWait.wait(mSnapshotThreadWaitLock);
1656 LOGV("takePicture: old snapshot thread completed.");
1657 }
1658
1659 if(!native_prepare_snapshot(mCameraControlFd)) {
1660 mSnapshotThreadWaitLock.unlock();
1661 return UNKNOWN_ERROR;
1662 }
1663
1664 stopPreviewInternal();
1665
1666 if (!initRaw(mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE))) {
1667 LOGE("initRaw failed. Not taking picture.");
1668 mSnapshotThreadWaitLock.unlock();
1669 return UNKNOWN_ERROR;
1670 }
1671
1672 mShutterLock.lock();
1673 mShutterPending = true;
1674 mShutterLock.unlock();
1675
1676 pthread_attr_t attr;
1677 pthread_attr_init(&attr);
1678 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1679 mSnapshotThreadRunning = !pthread_create(&mSnapshotThread,
1680 &attr,
1681 snapshot_thread,
1682 NULL);
1683 mSnapshotThreadWaitLock.unlock();
1684
1685 LOGV("takePicture: X");
1686 return mSnapshotThreadRunning ? NO_ERROR : UNKNOWN_ERROR;
1687}
1688
1689status_t QualcommCameraHardware::cancelPicture()
1690{
1691 status_t rc;
1692 LOGV("cancelPicture: E");
1693 rc = native_stop_snapshot(mCameraControlFd) ? NO_ERROR : UNKNOWN_ERROR;
1694 LOGV("cancelPicture: X: %d", rc);
1695 return rc;
1696}
1697
1698status_t QualcommCameraHardware::setParameters(const CameraParameters& params)
1699{
1700 LOGV("setParameters: E params = %p", &params);
1701
1702 Mutex::Autolock l(&mLock);
1703 status_t rc, final_rc = NO_ERROR;
1704
1705 if ((rc = setPreviewSize(params))) final_rc = rc;
1706 if ((rc = setPictureSize(params))) final_rc = rc;
1707 if ((rc = setJpegQuality(params))) final_rc = rc;
1708 if ((rc = setAntibanding(params))) final_rc = rc;
1709 if ((rc = setEffect(params))) final_rc = rc;
1710 if ((rc = setWhiteBalance(params))) final_rc = rc;
1711 if ((rc = setFlash(params))) final_rc = rc;
1712 if ((rc = setGpsLocation(params))) final_rc = rc;
1713 if ((rc = setRotation(params))) final_rc = rc;
1714 if ((rc = setZoom(params))) final_rc = rc;
1715 if ((rc = setFocusMode(params))) final_rc = rc;
1716 if ((rc = setOrientation(params))) final_rc = rc;
1717
1718 LOGV("setParameters: X");
1719 return final_rc;
1720}
1721
1722CameraParameters QualcommCameraHardware::getParameters() const
1723{
1724 LOGV("getParameters: EX");
1725 return mParameters;
1726}
1727
1728status_t QualcommCameraHardware::sendCommand(int32_t command, int32_t arg1,
1729 int32_t arg2)
1730{
1731 LOGV("sendCommand: EX");
1732 return BAD_VALUE;
1733}
1734
1735extern "C" sp<CameraHardwareInterface> openCameraHardware()
1736{
1737 LOGV("openCameraHardware: call createInstance");
1738 return QualcommCameraHardware::createInstance();
1739}
1740
1741wp<QualcommCameraHardware> QualcommCameraHardware::singleton;
1742
1743// If the hardware already exists, return a strong pointer to the current
1744// object. If not, create a new hardware object, put it in the singleton,
1745// and return it.
1746sp<CameraHardwareInterface> QualcommCameraHardware::createInstance()
1747{
1748 LOGD("createInstance: E");
1749
1750 Mutex::Autolock lock(&singleton_lock);
1751
1752 // Wait until the previous release is done.
1753 while (singleton_releasing) {
1754 LOGD("Wait for previous release.");
1755 singleton_wait.wait(singleton_lock);
1756 }
1757
1758 if (singleton != 0) {
1759 sp<CameraHardwareInterface> hardware = singleton.promote();
1760 if (hardware != 0) {
1761 LOGD("createInstance: X return existing hardware=%p", &(*hardware));
1762 return hardware;
1763 }
1764 }
1765
1766 {
1767 struct stat st;
1768 int rc = stat("/dev/oncrpc", &st);
1769 if (rc < 0) {
1770 LOGD("createInstance: X failed to create hardware: %s", strerror(errno));
1771 return NULL;
1772 }
1773 }
1774
1775 QualcommCameraHardware *cam = new QualcommCameraHardware();
1776 sp<QualcommCameraHardware> hardware(cam);
1777 singleton = hardware;
1778
1779 if (!cam->startCamera()) {
1780 LOGE("%s: startCamera failed!", __FUNCTION__);
1781 return NULL;
1782 }
1783
1784 cam->initDefaultParameters();
1785 LOGD("createInstance: X created hardware=%p", &(*hardware));
1786 return hardware;
1787}
1788
1789// For internal use only, hence the strong pointer to the derived type.
1790sp<QualcommCameraHardware> QualcommCameraHardware::getInstance()
1791{
1792 sp<CameraHardwareInterface> hardware = singleton.promote();
1793 if (hardware != 0) {
1794 // LOGV("getInstance: X old instance of hardware");
1795 return sp<QualcommCameraHardware>(static_cast<QualcommCameraHardware*>(hardware.get()));
1796 } else {
1797 LOGV("getInstance: X new instance of hardware");
1798 return sp<QualcommCameraHardware>();
1799 }
1800}
1801
1802void QualcommCameraHardware::receivePreviewFrame(struct msm_frame *frame)
1803{
1804// LOGV("receivePreviewFrame E");
1805
1806 if (!mCameraRunning) {
1807 LOGE("ignoring preview callback--camera has been stopped");
1808 return;
1809 }
1810
1811 mCallbackLock.lock();
1812 int msgEnabled = mMsgEnabled;
1813 data_callback pcb = mDataCallback;
1814 void *pdata = mCallbackCookie;
1815 data_callback_timestamp rcb = mDataCallbackTimestamp;
1816 void *rdata = mCallbackCookie;
1817 mCallbackLock.unlock();
1818
1819 // Find the offset within the heap of the current buffer.
1820 ssize_t offset =
1821 (ssize_t)frame->buffer - (ssize_t)mPreviewHeap->mHeap->base();
1822 offset /= mPreviewHeap->mAlignedBufferSize;
1823
1824 mInPreviewCallback = true;
1825 if (pcb != NULL && (msgEnabled & CAMERA_MSG_PREVIEW_FRAME))
1826 pcb(CAMERA_MSG_PREVIEW_FRAME, mPreviewHeap->mBuffers[offset],
1827 pdata);
1828
1829 if(rcb != NULL && (msgEnabled & CAMERA_MSG_VIDEO_FRAME)) {
1830 rcb(systemTime(), CAMERA_MSG_VIDEO_FRAME, mPreviewHeap->mBuffers[offset], rdata);
1831 Mutex::Autolock rLock(&mRecordFrameLock);
1832 if (mReleasedRecordingFrame != true) {
1833 LOGV("block waiting for frame release");
1834 mRecordWait.wait(mRecordFrameLock);
1835 LOGV("frame released, continuing");
1836 }
1837 mReleasedRecordingFrame = false;
1838 }
1839 mInPreviewCallback = false;
1840
1841// LOGV("receivePreviewFrame X");
1842}
1843
1844status_t QualcommCameraHardware::startRecording()
1845{
1846 LOGV("startRecording E");
1847 Mutex::Autolock l(&mLock);
1848 mReleasedRecordingFrame = false;
1849 return startPreviewInternal();
1850}
1851
1852void QualcommCameraHardware::stopRecording()
1853{
1854 LOGV("stopRecording: E");
1855 Mutex::Autolock l(&mLock);
1856 {
1857 mRecordFrameLock.lock();
1858 mReleasedRecordingFrame = true;
1859 mRecordWait.signal();
1860 mRecordFrameLock.unlock();
1861
1862 if(mDataCallback && (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)) {
1863 LOGV("stopRecording: X, preview still in progress");
1864 return;
1865 }
1866 }
1867
1868 stopPreviewInternal();
1869 LOGV("stopRecording: X");
1870}
1871
1872void QualcommCameraHardware::releaseRecordingFrame(
1873 const sp<IMemory>& mem __attribute__((unused)))
1874{
1875 LOGV("releaseRecordingFrame E");
1876 Mutex::Autolock rLock(&mRecordFrameLock);
1877 mReleasedRecordingFrame = true;
1878 mRecordWait.signal();
1879 LOGV("releaseRecordingFrame X");
1880}
1881
1882bool QualcommCameraHardware::recordingEnabled()
1883{
1884 return mCameraRunning && mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME);
1885}
1886
1887void QualcommCameraHardware::notifyShutter(common_crop_t *crop)
1888{
1889 mShutterLock.lock();
1890 image_rect_type size;
1891
1892 if (mShutterPending && mNotifyCallback && (mMsgEnabled & CAMERA_MSG_SHUTTER)) {
1893 LOGV("out2_w=%d, out2_h=%d, in2_w=%d, in2_h=%d",
1894 crop->out2_w, crop->out2_h, crop->in2_w, crop->in2_h);
1895 LOGV("out1_w=%d, out1_h=%d, in1_w=%d, in1_h=%d",
1896 crop->out1_w, crop->out1_h, crop->in1_w, crop->in1_h);
1897
1898 // To workaround a bug in MDP which happens if either
1899 // dimension > 2048, we display the thumbnail instead.
1900 mDisplayHeap = mRawHeap;
1901 if (crop->in1_w == 0 || crop->in1_h == 0) {
1902 // Full size
1903 size.width = mDimension.picture_width;
1904 size.height = mDimension.picture_height;
1905 if (size.width > 2048 || size.height > 2048) {
1906 size.width = mDimension.ui_thumbnail_width;
1907 size.height = mDimension.ui_thumbnail_height;
1908 mDisplayHeap = mThumbnailHeap;
1909 }
1910 } else {
1911 // Cropped
1912 size.width = crop->in2_w & ~1;
1913 size.height = crop->in2_h & ~1;
1914 if (size.width > 2048 || size.height > 2048) {
1915 size.width = crop->in1_w & ~1;
1916 size.height = crop->in1_h & ~1;
1917 mDisplayHeap = mThumbnailHeap;
1918 }
1919 }
1920
1921 mNotifyCallback(CAMERA_MSG_SHUTTER, (int32_t)&size, 0,
1922 mCallbackCookie);
1923 mShutterPending = false;
1924 }
1925 mShutterLock.unlock();
1926}
1927
1928static void receive_shutter_callback(common_crop_t *crop)
1929{
1930 LOGV("receive_shutter_callback: E");
1931 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
1932 if (obj != 0) {
1933 obj->notifyShutter(crop);
1934 }
1935 LOGV("receive_shutter_callback: X");
1936}
1937
1938// Crop the picture in place.
1939static void crop_yuv420(uint32_t width, uint32_t height,
1940 uint32_t cropped_width, uint32_t cropped_height,
1941 uint8_t *image)
1942{
1943 uint32_t i, x, y;
1944 uint8_t* chroma_src, *chroma_dst;
1945
1946 // Calculate the start position of the cropped area.
1947 x = (width - cropped_width) / 2;
1948 y = (height - cropped_height) / 2;
1949 x &= ~1;
1950 y &= ~1;
1951
1952 // Copy luma component.
1953 for(i = 0; i < cropped_height; i++)
1954 memcpy(image + i * cropped_width,
1955 image + width * (y + i) + x,
1956 cropped_width);
1957
1958 chroma_src = image + width * height;
1959 chroma_dst = image + cropped_width * cropped_height;
1960
1961 // Copy chroma components.
1962 cropped_height /= 2;
1963 y /= 2;
1964 for(i = 0; i < cropped_height; i++)
1965 memcpy(chroma_dst + i * cropped_width,
1966 chroma_src + width * (y + i) + x,
1967 cropped_width);
1968}
1969
1970void QualcommCameraHardware::receiveRawPicture()
1971{
1972 LOGV("receiveRawPicture: E");
1973
1974 Mutex::Autolock cbLock(&mCallbackLock);
1975 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_RAW_IMAGE)) {
1976 if(native_get_picture(mCameraControlFd, &mCrop) == false) {
1977 LOGE("getPicture failed!");
1978 return;
1979 }
1980 mCrop.in1_w &= ~1;
1981 mCrop.in1_h &= ~1;
1982 mCrop.in2_w &= ~1;
1983 mCrop.in2_h &= ~1;
1984
1985 // By the time native_get_picture returns, picture is taken. Call
1986 // shutter callback if cam config thread has not done that.
1987 notifyShutter(&mCrop);
1988
1989 // Crop the image if zoomed.
1990 if (mCrop.in2_w != 0 && mCrop.in2_h != 0) {
1991 crop_yuv420(mCrop.out2_w, mCrop.out2_h, mCrop.in2_w, mCrop.in2_h,
1992 (uint8_t *)mRawHeap->mHeap->base());
1993 crop_yuv420(mCrop.out1_w, mCrop.out1_h, mCrop.in1_w, mCrop.in1_h,
1994 (uint8_t *)mThumbnailHeap->mHeap->base());
1995 // We do not need jpeg encoder to upscale the image. Set the new
1996 // dimension for encoder.
1997 mDimension.orig_picture_dx = mCrop.in2_w;
1998 mDimension.orig_picture_dy = mCrop.in2_h;
1999 mDimension.thumbnail_width = mCrop.in1_w;
2000 mDimension.thumbnail_height = mCrop.in1_h;
2001 memset(&mCrop, 0, sizeof(mCrop));
2002 }
2003
2004 mDataCallback(CAMERA_MSG_RAW_IMAGE, mDisplayHeap->mBuffers[0],
2005 mCallbackCookie);
2006 }
2007 else LOGV("Raw-picture callback was canceled--skipping.");
2008
2009 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
2010 mJpegSize = 0;
2011 if (LINK_jpeg_encoder_init()) {
2012 if(native_jpeg_encode()) {
2013 LOGV("receiveRawPicture: X (success)");
2014 return;
2015 }
2016 LOGE("jpeg encoding failed");
2017 }
2018 else LOGE("receiveRawPicture X: jpeg_encoder_init failed.");
2019 }
2020 else LOGV("JPEG callback is NULL, not encoding image.");
2021 deinitRaw();
2022 LOGV("receiveRawPicture: X");
2023}
2024
2025void QualcommCameraHardware::receiveJpegPictureFragment(
2026 uint8_t *buff_ptr, uint32_t buff_size)
2027{
2028 uint32_t remaining = mJpegHeap->mHeap->virtualSize();
2029 remaining -= mJpegSize;
2030 uint8_t *base = (uint8_t *)mJpegHeap->mHeap->base();
2031
2032 LOGV("receiveJpegPictureFragment size %d", buff_size);
2033 if (buff_size > remaining) {
2034 LOGE("receiveJpegPictureFragment: size %d exceeds what "
2035 "remains in JPEG heap (%d), truncating",
2036 buff_size,
2037 remaining);
2038 buff_size = remaining;
2039 }
2040 memcpy(base + mJpegSize, buff_ptr, buff_size);
2041 mJpegSize += buff_size;
2042}
2043
2044void QualcommCameraHardware::receiveJpegPicture(void)
2045{
2046 LOGV("receiveJpegPicture: E image (%d uint8_ts out of %d)",
2047 mJpegSize, mJpegHeap->mBufferSize);
2048 Mutex::Autolock cbLock(&mCallbackLock);
2049
2050 int index = 0, rc;
2051
2052 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
2053 // The reason we do not allocate into mJpegHeap->mBuffers[offset] is
2054 // that the JPEG image's size will probably change from one snapshot
2055 // to the next, so we cannot reuse the MemoryBase object.
2056 sp<MemoryBase> buffer = new
2057 MemoryBase(mJpegHeap->mHeap,
2058 index * mJpegHeap->mBufferSize +
2059 0,
2060 mJpegSize);
2061 mDataCallback(CAMERA_MSG_COMPRESSED_IMAGE, buffer, mCallbackCookie);
2062 buffer = NULL;
2063 }
2064 else LOGV("JPEG callback was cancelled--not delivering image.");
2065
2066 LINK_jpeg_encoder_join();
2067 deinitRaw();
2068
2069 LOGV("receiveJpegPicture: X callback done.");
2070}
2071
2072bool QualcommCameraHardware::previewEnabled()
2073{
2074 return mCameraRunning && mDataCallback && (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME);
2075}
2076
2077status_t QualcommCameraHardware::setPreviewSize(const CameraParameters& params)
2078{
2079 int width, height;
2080 params.getPreviewSize(&width, &height);
2081 LOGV("requested preview size %d x %d", width, height);
2082
2083 // Validate the preview size
2084 for (size_t i = 0; i < PREVIEW_SIZE_COUNT; ++i) {
2085 if (width == preview_sizes[i].width
2086 && height == preview_sizes[i].height) {
2087 mParameters.setPreviewSize(width, height);
2088 mDimension.display_width = width;
2089 mDimension.display_height = height;
2090 return NO_ERROR;
2091 }
2092 }
2093 LOGE("Invalid preview size requested: %dx%d", width, height);
2094 return BAD_VALUE;
2095}
2096
2097status_t QualcommCameraHardware::setPictureSize(const CameraParameters& params)
2098{
2099 int width, height;
2100 params.getPictureSize(&width, &height);
2101 LOGV("requested picture size %d x %d", width, height);
2102
2103 // Validate the picture size
2104 for (int i = 0; i < PICTURE_SIZE_COUNT; ++i) {
2105 if (width == picture_sizes[i].width
2106 && height == picture_sizes[i].height) {
2107 mParameters.setPictureSize(width, height);
2108 mDimension.picture_width = width;
2109 mDimension.picture_height = height;
2110 return NO_ERROR;
2111 }
2112 }
2113 LOGE("Invalid picture size requested: %dx%d", width, height);
2114 return BAD_VALUE;
2115}
2116
2117status_t QualcommCameraHardware::setJpegQuality(const CameraParameters& params) {
2118 status_t rc = NO_ERROR;
2119 int quality = params.getInt(CameraParameters::KEY_JPEG_QUALITY);
2120 if (quality > 0 && quality <= 100) {
2121 mParameters.set(CameraParameters::KEY_JPEG_QUALITY, quality);
2122 } else {
2123 LOGE("Invalid jpeg quality=%d", quality);
2124 rc = BAD_VALUE;
2125 }
2126
2127 quality = params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY);
2128 if (quality > 0 && quality <= 100) {
2129 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, quality);
2130 } else {
2131 LOGE("Invalid jpeg thumbnail quality=%d", quality);
2132 rc = BAD_VALUE;
2133 }
2134 return rc;
2135}
2136
2137status_t QualcommCameraHardware::setEffect(const CameraParameters& params)
2138{
2139 const char *str = params.get(CameraParameters::KEY_EFFECT);
2140 if (str != NULL) {
2141 int32_t value = attr_lookup(effects, sizeof(effects) / sizeof(str_map), str);
2142 if (value != NOT_FOUND) {
2143 mParameters.set(CameraParameters::KEY_EFFECT, str);
2144 bool ret = native_set_parm(CAMERA_SET_PARM_EFFECT, sizeof(value),
2145 (void *)&value);
2146 return ret ? NO_ERROR : UNKNOWN_ERROR;
2147 }
2148 }
2149 LOGE("Invalid effect value: %s", (str == NULL) ? "NULL" : str);
2150 return BAD_VALUE;
2151}
2152
2153status_t QualcommCameraHardware::setWhiteBalance(const CameraParameters& params)
2154{
2155 const char *str = params.get(CameraParameters::KEY_WHITE_BALANCE);
2156 if (str != NULL) {
2157 int32_t value = attr_lookup(whitebalance, sizeof(whitebalance) / sizeof(str_map), str);
2158 if (value != NOT_FOUND) {
2159 mParameters.set(CameraParameters::KEY_WHITE_BALANCE, str);
2160 bool ret = native_set_parm(CAMERA_SET_PARM_WB, sizeof(value),
2161 (void *)&value);
2162 return ret ? NO_ERROR : UNKNOWN_ERROR;
2163 }
2164 }
2165 LOGE("Invalid whitebalance value: %s", (str == NULL) ? "NULL" : str);
2166 return BAD_VALUE;
2167}
2168
2169status_t QualcommCameraHardware::setFlash(const CameraParameters& params)
2170{
2171 if (!mSensorInfo.flash_enabled) {
2172 LOGV("%s: flash not supported", __FUNCTION__);
2173 return NO_ERROR;
2174 }
2175
2176 const char *str = params.get(CameraParameters::KEY_FLASH_MODE);
2177 if (str != NULL) {
2178 int32_t value = attr_lookup(flash, sizeof(flash) / sizeof(str_map), str);
2179 if (value != NOT_FOUND) {
2180 mParameters.set(CameraParameters::KEY_FLASH_MODE, str);
2181 bool ret = native_set_parm(CAMERA_SET_PARM_LED_MODE,
2182 sizeof(value), (void *)&value);
2183 return ret ? NO_ERROR : UNKNOWN_ERROR;
2184 }
2185 }
2186 LOGE("Invalid flash mode value: %s", (str == NULL) ? "NULL" : str);
2187 return BAD_VALUE;
2188}
2189
2190status_t QualcommCameraHardware::setAntibanding(const CameraParameters& params)
2191{
2192 const char *str = params.get(CameraParameters::KEY_ANTIBANDING);
2193 if (str != NULL) {
2194 int value = (camera_antibanding_type)attr_lookup(
2195 antibanding, sizeof(antibanding) / sizeof(str_map), str);
2196 if (value != NOT_FOUND) {
2197 camera_antibanding_type temp = (camera_antibanding_type) value;
2198 // We don't have auto antibanding now, and simply set the frequency by country.
2199 if (temp == CAMERA_ANTIBANDING_AUTO) {
2200 temp = camera_get_location();
2201 }
2202 mParameters.set(CameraParameters::KEY_ANTIBANDING, str);
2203 native_set_parm(CAMERA_SET_PARM_ANTIBANDING, sizeof(camera_antibanding_type), (void *)&temp);
2204 return NO_ERROR;
2205 }
2206 }
2207 LOGE("Invalid antibanding value: %s", (str == NULL) ? "NULL" : str);
2208 return BAD_VALUE;
2209}
2210
2211status_t QualcommCameraHardware::setGpsLocation(const CameraParameters& params)
2212{
2213 const char *latitude = params.get(CameraParameters::KEY_GPS_LATITUDE);
2214 if (latitude) {
2215 mParameters.set(CameraParameters::KEY_GPS_LATITUDE, latitude);
2216 }
2217
2218 const char *longitude = params.get(CameraParameters::KEY_GPS_LONGITUDE);
2219 if (longitude) {
2220 mParameters.set(CameraParameters::KEY_GPS_LONGITUDE, longitude);
2221 }
2222
2223 const char *altitude = params.get(CameraParameters::KEY_GPS_ALTITUDE);
2224 if (altitude) {
2225 mParameters.set(CameraParameters::KEY_GPS_ALTITUDE, altitude);
2226 }
2227
2228 const char *timestamp = params.get(CameraParameters::KEY_GPS_TIMESTAMP);
2229 if (timestamp) {
2230 mParameters.set(CameraParameters::KEY_GPS_TIMESTAMP, timestamp);
2231 }
2232 return NO_ERROR;
2233}
2234
2235status_t QualcommCameraHardware::setRotation(const CameraParameters& params)
2236{
2237 status_t rc = NO_ERROR;
2238 int rotation = params.getInt(CameraParameters::KEY_ROTATION);
2239 if (rotation != NOT_FOUND) {
2240 if (rotation == 0 || rotation == 90 || rotation == 180
2241 || rotation == 270) {
2242 mParameters.set(CameraParameters::KEY_ROTATION, rotation);
2243 } else {
2244 LOGE("Invalid rotation value: %d", rotation);
2245 rc = BAD_VALUE;
2246 }
2247 }
2248 return rc;
2249}
2250
2251status_t QualcommCameraHardware::setZoom(const CameraParameters& params)
2252{
2253 status_t rc = NO_ERROR;
2254 // No matter how many different zoom values the driver can provide, HAL
2255 // provides applictations the same number of zoom levels. The maximum driver
2256 // zoom value depends on sensor output (VFE input) and preview size (VFE
2257 // output) because VFE can only crop and cannot upscale. If the preview size
2258 // is bigger, the maximum zoom ratio is smaller. However, we want the
2259 // zoom ratio of each zoom level is always the same whatever the preview
2260 // size is. Ex: zoom level 1 is always 1.2x, zoom level 2 is 1.44x, etc. So,
2261 // we need to have a fixed maximum zoom value and do read it from the
2262 // driver.
2263 static const int ZOOM_STEP = 6;
2264 int32_t zoom_level = params.getInt("zoom");
2265
2266 LOGI("Set zoom=%d", zoom_level);
2267 if(zoom_level >= 0 && zoom_level <= MAX_ZOOM_LEVEL) {
2268 mParameters.set("zoom", zoom_level);
2269 int32_t zoom_value = ZOOM_STEP * zoom_level;
2270 bool ret = native_set_parm(CAMERA_SET_PARM_ZOOM,
2271 sizeof(zoom_value), (void *)&zoom_value);
2272 rc = ret ? NO_ERROR : UNKNOWN_ERROR;
2273 } else {
2274 rc = BAD_VALUE;
2275 }
2276
2277 return rc;
2278}
2279
2280status_t QualcommCameraHardware::setFocusMode(const CameraParameters& params)
2281{
2282 const char *str = params.get(CameraParameters::KEY_FOCUS_MODE);
2283 if (str != NULL) {
2284 int32_t value = attr_lookup(focus_modes,
2285 sizeof(focus_modes) / sizeof(str_map), str);
2286 if (value != NOT_FOUND) {
2287 mParameters.set(CameraParameters::KEY_FOCUS_MODE, str);
2288 // Focus step is reset to infinity when preview is started. We do
2289 // not need to do anything now.
2290 return NO_ERROR;
2291 }
2292 }
2293 LOGE("Invalid focus mode value: %s", (str == NULL) ? "NULL" : str);
2294 return BAD_VALUE;
2295}
2296
2297status_t QualcommCameraHardware::setOrientation(const CameraParameters& params)
2298{
2299 const char *str = params.get("orientation");
2300
2301 if (str != NULL) {
2302 if (strcmp(str, "portrait") == 0 || strcmp(str, "landscape") == 0) {
2303 // Camera service needs this to decide if the preview frames and raw
2304 // pictures should be rotated.
2305 mParameters.set("orientation", str);
2306 } else {
2307 LOGE("Invalid orientation value: %s", str);
2308 return BAD_VALUE;
2309 }
2310 }
2311 return NO_ERROR;
2312}
2313
2314QualcommCameraHardware::MemPool::MemPool(int buffer_size, int num_buffers,
2315 int frame_size,
2316 const char *name) :
2317 mBufferSize(buffer_size),
2318 mNumBuffers(num_buffers),
2319 mFrameSize(frame_size),
2320 mBuffers(NULL), mName(name)
2321{
2322 int page_size_minus_1 = getpagesize() - 1;
2323 mAlignedBufferSize = (buffer_size + page_size_minus_1) & (~page_size_minus_1);
2324}
2325
2326void QualcommCameraHardware::MemPool::completeInitialization()
2327{
2328 // If we do not know how big the frame will be, we wait to allocate
2329 // the buffers describing the individual frames until we do know their
2330 // size.
2331
2332 if (mFrameSize > 0) {
2333 mBuffers = new sp<MemoryBase>[mNumBuffers];
2334 for (int i = 0; i < mNumBuffers; i++) {
2335 mBuffers[i] = new
2336 MemoryBase(mHeap,
2337 i * mAlignedBufferSize,
2338 mFrameSize);
2339 }
2340 }
2341}
2342
2343QualcommCameraHardware::AshmemPool::AshmemPool(int buffer_size, int num_buffers,
2344 int frame_size,
2345 const char *name) :
2346 QualcommCameraHardware::MemPool(buffer_size,
2347 num_buffers,
2348 frame_size,
2349 name)
2350{
2351 LOGV("constructing MemPool %s backed by ashmem: "
2352 "%d frames @ %d uint8_ts, "
2353 "buffer size %d",
2354 mName,
2355 num_buffers, frame_size, buffer_size);
2356
2357 int page_mask = getpagesize() - 1;
2358 int ashmem_size = buffer_size * num_buffers;
2359 ashmem_size += page_mask;
2360 ashmem_size &= ~page_mask;
2361
2362 mHeap = new MemoryHeapBase(ashmem_size);
2363
2364 completeInitialization();
2365}
2366
2367static bool register_buf(int camfd,
2368 int size,
2369 int pmempreviewfd,
2370 uint32_t offset,
2371 uint8_t *buf,
2372 int pmem_type,
2373 bool vfe_can_write,
2374 bool register_buffer = true);
2375
2376QualcommCameraHardware::PmemPool::PmemPool(const char *pmem_pool,
2377 int flags,
2378 int camera_control_fd,
2379 int pmem_type,
2380 int buffer_size, int num_buffers,
2381 int frame_size,
2382 const char *name) :
2383 QualcommCameraHardware::MemPool(buffer_size,
2384 num_buffers,
2385 frame_size,
2386 name),
2387 mPmemType(pmem_type),
2388 mCameraControlFd(dup(camera_control_fd))
2389{
2390 LOGV("constructing MemPool %s backed by pmem pool %s: "
2391 "%d frames @ %d bytes, buffer size %d",
2392 mName,
2393 pmem_pool, num_buffers, frame_size,
2394 buffer_size);
2395
2396 LOGV("%s: duplicating control fd %d --> %d",
2397 __FUNCTION__,
2398 camera_control_fd, mCameraControlFd);
2399
2400 // Make a new mmap'ed heap that can be shared across processes.
2401 // mAlignedBufferSize is already in 4k aligned. (do we need total size necessary to be in power of 2??)
2402 mAlignedSize = mAlignedBufferSize * num_buffers;
2403
2404 sp<MemoryHeapBase> masterHeap =
2405 new MemoryHeapBase(pmem_pool, mAlignedSize, flags);
2406
2407 if (masterHeap->getHeapID() < 0) {
2408 LOGE("failed to construct master heap for pmem pool %s", pmem_pool);
2409 masterHeap.clear();
2410 return;
2411 }
2412
2413 sp<MemoryHeapPmem> pmemHeap = new MemoryHeapPmem(masterHeap, flags);
2414 if (pmemHeap->getHeapID() >= 0) {
2415 pmemHeap->slap();
2416 masterHeap.clear();
2417 mHeap = pmemHeap;
2418 pmemHeap.clear();
2419
2420 mFd = mHeap->getHeapID();
2421 if (::ioctl(mFd, PMEM_GET_SIZE, &mSize)) {
2422 LOGE("pmem pool %s ioctl(PMEM_GET_SIZE) error %s (%d)",
2423 pmem_pool,
2424 ::strerror(errno), errno);
2425 mHeap.clear();
2426 return;
2427 }
2428
2429 LOGV("pmem pool %s ioctl(fd = %d, PMEM_GET_SIZE) is %ld",
2430 pmem_pool,
2431 mFd,
2432 mSize.len);
2433 LOGD("mBufferSize=%d, mAlignedBufferSize=%d\n", mBufferSize, mAlignedBufferSize);
2434 // Unregister preview buffers with the camera drivers. Allow the VFE to write
2435 // to all preview buffers except for the last one.
2436 for (int cnt = 0; cnt < num_buffers; ++cnt) {
2437 register_buf(mCameraControlFd,
2438 mBufferSize,
2439 mHeap->getHeapID(),
2440 mAlignedBufferSize * cnt,
2441 (uint8_t *)mHeap->base() + mAlignedBufferSize * cnt,
2442 pmem_type,
2443 !(cnt == num_buffers - 1 && pmem_type == MSM_PMEM_OUTPUT2));
2444 }
2445
2446 completeInitialization();
2447 }
2448 else LOGE("pmem pool %s error: could not create master heap!",
2449 pmem_pool);
2450}
2451
2452QualcommCameraHardware::PmemPool::~PmemPool()
2453{
2454 LOGV("%s: %s E", __FUNCTION__, mName);
2455 if (mHeap != NULL) {
2456 // Unregister preview buffers with the camera drivers.
2457 for (int cnt = 0; cnt < mNumBuffers; ++cnt) {
2458 register_buf(mCameraControlFd,
2459 mBufferSize,
2460 mHeap->getHeapID(),
2461 mAlignedBufferSize * cnt,
2462 (uint8_t *)mHeap->base() + mAlignedBufferSize * cnt,
2463 mPmemType,
2464 false,
2465 false /* unregister */);
2466 }
2467 }
2468 LOGV("destroying PmemPool %s: closing control fd %d",
2469 mName,
2470 mCameraControlFd);
2471 close(mCameraControlFd);
2472 LOGV("%s: %s X", __FUNCTION__, mName);
2473}
2474
2475QualcommCameraHardware::MemPool::~MemPool()
2476{
2477 LOGV("destroying MemPool %s", mName);
2478 if (mFrameSize > 0)
2479 delete [] mBuffers;
2480 mHeap.clear();
2481 LOGV("destroying MemPool %s completed", mName);
2482}
2483
2484static bool register_buf(int camfd,
2485 int size,
2486 int pmempreviewfd,
2487 uint32_t offset,
2488 uint8_t *buf,
2489 int pmem_type,
2490 bool vfe_can_write,
2491 bool register_buffer)
2492{
2493 struct msm_pmem_info pmemBuf;
2494
2495 pmemBuf.type = pmem_type;
2496 pmemBuf.fd = pmempreviewfd;
2497 pmemBuf.offset = offset;
2498 pmemBuf.len = size;
2499 pmemBuf.vaddr = buf;
2500 pmemBuf.y_off = 0;
2501 pmemBuf.cbcr_off = PAD_TO_WORD(size * 2 / 3);
2502 pmemBuf.active = vfe_can_write;
2503
2504 LOGV("register_buf: camfd = %d, reg = %d buffer = %p",
2505 camfd, !register_buffer, buf);
2506 if (ioctl(camfd,
2507 register_buffer ?
2508 MSM_CAM_IOCTL_REGISTER_PMEM :
2509 MSM_CAM_IOCTL_UNREGISTER_PMEM,
2510 &pmemBuf) < 0) {
2511 LOGE("register_buf: MSM_CAM_IOCTL_(UN)REGISTER_PMEM fd %d error %s",
2512 camfd,
2513 strerror(errno));
2514 return false;
2515 }
2516 return true;
2517}
2518
2519status_t QualcommCameraHardware::MemPool::dump(int fd, const Vector<String16>& args) const
2520{
2521 const size_t SIZE = 256;
2522 char buffer[SIZE];
2523 String8 result;
2524 snprintf(buffer, 255, "QualcommCameraHardware::AshmemPool::dump\n");
2525 result.append(buffer);
2526 if (mName) {
2527 snprintf(buffer, 255, "mem pool name (%s)\n", mName);
2528 result.append(buffer);
2529 }
2530 if (mHeap != 0) {
2531 snprintf(buffer, 255, "heap base(%p), size(%d), flags(%d), device(%s)\n",
2532 mHeap->getBase(), mHeap->getSize(),
2533 mHeap->getFlags(), mHeap->getDevice());
2534 result.append(buffer);
2535 }
2536 snprintf(buffer, 255,
2537 "buffer size (%d), number of buffers (%d), frame size(%d)",
2538 mBufferSize, mNumBuffers, mFrameSize);
2539 result.append(buffer);
2540 write(fd, result.string(), result.size());
2541 return NO_ERROR;
2542}
2543
2544static void receive_camframe_callback(struct msm_frame *frame)
2545{
2546 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
2547 if (obj != 0) {
2548 obj->receivePreviewFrame(frame);
2549 }
2550}
2551
2552static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size)
2553{
2554 LOGV("receive_jpeg_fragment_callback E");
2555 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
2556 if (obj != 0) {
2557 obj->receiveJpegPictureFragment(buff_ptr, buff_size);
2558 }
2559 LOGV("receive_jpeg_fragment_callback X");
2560}
2561
2562static void receive_jpeg_callback(jpeg_event_t status)
2563{
2564 LOGV("receive_jpeg_callback E (completion status %d)", status);
2565 if (status == JPEG_EVENT_DONE) {
2566 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
2567 if (obj != 0) {
2568 obj->receiveJpegPicture();
2569 }
2570 }
2571 LOGV("receive_jpeg_callback X");
2572}
2573
2574void QualcommCameraHardware::setCallbacks(notify_callback notify_cb,
2575 data_callback data_cb,
2576 data_callback_timestamp data_cb_timestamp,
2577 void* user)
2578{
2579 Mutex::Autolock lock(mLock);
2580 mNotifyCallback = notify_cb;
2581 mDataCallback = data_cb;
2582 mDataCallbackTimestamp = data_cb_timestamp;
2583 mCallbackCookie = user;
2584}
2585
2586void QualcommCameraHardware::enableMsgType(int32_t msgType)
2587{
2588 Mutex::Autolock lock(mLock);
2589 mMsgEnabled |= msgType;
2590}
2591
2592void QualcommCameraHardware::disableMsgType(int32_t msgType)
2593{
2594 Mutex::Autolock lock(mLock);
2595 mMsgEnabled &= ~msgType;
2596}
2597
2598bool QualcommCameraHardware::msgTypeEnabled(int32_t msgType)
2599{
2600 return (mMsgEnabled & msgType);
2601}
2602
2603}; // namespace android