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