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