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