blob: dd3f0b3ccfe6c8afe6196ba77d6c4dfce213e296 [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>
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -080032#include <math.h>
Priya Komarlingamb85535d2009-11-30 13:06:01 -080033#if HAVE_ANDROID_OS
34#include <linux/android_pmem.h>
35#endif
36#include <linux/ioctl.h>
37#include <ui/CameraParameters.h>
38
39#define LIKELY(exp) __builtin_expect(!!(exp), 1)
40#define UNLIKELY(exp) __builtin_expect(!!(exp), 0)
41
42extern "C" {
43#include <fcntl.h>
44#include <time.h>
45#include <pthread.h>
46#include <stdio.h>
47#include <string.h>
48#include <unistd.h>
49#include <termios.h>
50#include <assert.h>
51#include <stdlib.h>
52#include <ctype.h>
53#include <signal.h>
54#include <errno.h>
55#include <sys/mman.h>
56#include <sys/system_properties.h>
57#include <sys/time.h>
58#include <stdlib.h>
59
60#include <media/msm_camera.h>
61
62#include <camera.h>
63#include <camframe.h>
64#include <mm-still/jpeg/jpege.h>
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -080065#include <jpeg_encoder.h>
Priya Komarlingamb85535d2009-11-30 13:06:01 -080066
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -080067#define DEFAULT_PICTURE_WIDTH 1024
68#define DEFAULT_PICTURE_HEIGHT 768
Priya Komarlingamb85535d2009-11-30 13:06:01 -080069#define THUMBNAIL_BUFFER_SIZE (THUMBNAIL_WIDTH * THUMBNAIL_HEIGHT * 3/2)
70#define MAX_ZOOM_LEVEL 5
71#define NOT_FOUND -1
72
73#if DLOPEN_LIBMMCAMERA
74#include <dlfcn.h>
75
76void* (*LINK_cam_conf)(void *data);
77void* (*LINK_cam_frame)(void *data);
78bool (*LINK_jpeg_encoder_init)();
79void (*LINK_jpeg_encoder_join)();
80bool (*LINK_jpeg_encoder_encode)(const cam_ctrl_dimension_t *dimen,
81 const uint8_t *thumbnailbuf, int thumbnailfd,
82 const uint8_t *snapshotbuf, int snapshotfd,
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -080083 common_crop_t *scaling_parms, exif_tags_info_t *exif_data,
84 int exif_table_numEntries);
Priya Komarlingamb85535d2009-11-30 13:06:01 -080085int (*LINK_camframe_terminate)(void);
86int8_t (*LINK_jpeg_encoder_setMainImageQuality)(uint32_t quality);
87int8_t (*LINK_jpeg_encoder_setThumbnailQuality)(uint32_t quality);
88int8_t (*LINK_jpeg_encoder_setRotation)(uint32_t rotation);
89int8_t (*LINK_jpeg_encoder_setLocation)(const camera_position_type *location);
90const struct camera_size_type *(*LINK_default_sensor_get_snapshot_sizes)(int *len);
91int (*LINK_launch_cam_conf_thread)(void);
92int (*LINK_release_cam_conf_thread)(void);
93int8_t (*LINK_zoom_crop_upscale)(uint32_t width, uint32_t height,
94 uint32_t cropped_width, uint32_t cropped_height, uint8_t *img_buf);
95
96// callbacks
97void (**LINK_mmcamera_camframe_callback)(struct msm_frame *frame);
98void (**LINK_mmcamera_jpegfragment_callback)(uint8_t *buff_ptr,
99 uint32_t buff_size);
100void (**LINK_mmcamera_jpeg_callback)(jpeg_event_t status);
101void (**LINK_mmcamera_shutter_callback)(common_crop_t *crop);
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800102void (**LINK_camframe_timeout_callback)(void);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800103#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
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800134//Default to WVGA
Srinivasan Kannanfa7edae2009-12-16 18:02:01 -0800135#define DEFAULT_PREVIEW_SETTING 1
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800136static const camera_size_type preview_sizes[] = {
Srinivasan Kannanfa7edae2009-12-16 18:02:01 -0800137 { 1280, 720 }, // 720P, reserved
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800138 { 800, 480 }, // WVGA
139 { 720, 480 },
140 { 640, 480 }, // VGA
141 { 576, 432 },
142 { 480, 320 }, // HVGA
143 { 384, 288 },
144 { 352, 288 }, // CIF
145 { 320, 240 }, // QVGA
146 { 240, 160 }, // SQVGA
147 { 176, 144 }, // QCIF
148};
149#define PREVIEW_SIZE_COUNT (sizeof(preview_sizes)/sizeof(camera_size_type))
150
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800151//static const camera_size_type* picture_sizes;
152//static int PICTURE_SIZE_COUNT;
153/* TODO
154 * Ideally this should be a populated by lower layers.
155 * But currently this is no API to do that at lower layer.
156 * Hence populating with default sizes for now. This needs
157 * to be changed once the API is supported.
158 */
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800159//sorted on column basis
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800160static const camera_size_type picture_sizes[] = {
161 { 2592, 1944 }, // 5MP
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800162 { 2048, 1536 }, // 3MP QXGA
163 { 1920, 1080 }, //HD1080
164 { 1600, 1200 }, // 2MP UXGA
165 { 1280, 768 }, //WXGA
166 { 1280, 720 }, //HD720
167 { 1024, 768}, // 1MP XGA
168 { 800, 600 }, //SVGA
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800169 { 800, 480 }, // WVGA
170 { 640, 480 }, // VGA
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800171 { 352, 288 }, //CIF
172 { 320, 240 }, // QVGA
173 { 176, 144 } // QCIF
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800174};
175static int PICTURE_SIZE_COUNT = sizeof(picture_sizes)/sizeof(camera_size_type);
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800176static const camera_size_type * picture_sizes_ptr;
177static int supportedPictureSizesCount;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800178
Srinivasan Kannan80d878f2009-12-18 15:06:02 -0800179#ifdef Q12
180#undef Q12
181#endif
182
183#define Q12 4096
184
185typedef struct {
186 uint32_t aspect_ratio;
187 uint32_t width;
188 uint32_t height;
189} thumbnail_size_type;
190
191static thumbnail_size_type thumbnail_sizes[] = {
192 { 7281, 512, 288 }, //1.777778
193 { 6826, 480, 288 }, //1.666667
194 { 5461, 512, 384 }, //1.333333
195 { 5006, 352, 288 }, //1.222222
196};
197#define THUMBNAIL_SIZE_COUNT (sizeof(thumbnail_sizes)/sizeof(thumbnail_size_type))
198#define DEFAULT_THUMBNAIL_SETTING 2
199#define THUMBNAIL_WIDTH_STR "512"
200#define THUMBNAIL_HEIGHT_STR "384"
201#define THUMBNAIL_SMALL_HEIGHT 144
202
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800203static int attr_lookup(const str_map arr[], int len, const char *name)
204{
205 if (name) {
206 for (int i = 0; i < len; i++) {
207 if (!strcmp(arr[i].desc, name))
208 return arr[i].val;
209 }
210 }
211 return NOT_FOUND;
212}
213
214// round to the next power of two
215static inline unsigned clp2(unsigned x)
216{
217 x = x - 1;
218 x = x | (x >> 1);
219 x = x | (x >> 2);
220 x = x | (x >> 4);
221 x = x | (x >> 8);
222 x = x | (x >>16);
223 return x + 1;
224}
225
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -0800226static int exif_table_numEntries = 0;
227#define MAX_EXIF_TABLE_ENTRIES 7
228exif_tags_info_t exif_data[MAX_EXIF_TABLE_ENTRIES];
229
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800230namespace android {
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800231
232static const int PICTURE_FORMAT_JPEG = 1;
233static const int PICTURE_FORMAT_RAW = 2;
234
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800235// from aeecamera.h
236static const str_map whitebalance[] = {
237 { CameraParameters::WHITE_BALANCE_AUTO, CAMERA_WB_AUTO },
238 { CameraParameters::WHITE_BALANCE_INCANDESCENT, CAMERA_WB_INCANDESCENT },
239 { CameraParameters::WHITE_BALANCE_FLUORESCENT, CAMERA_WB_FLUORESCENT },
240 { CameraParameters::WHITE_BALANCE_DAYLIGHT, CAMERA_WB_DAYLIGHT },
241 { CameraParameters::WHITE_BALANCE_CLOUDY_DAYLIGHT, CAMERA_WB_CLOUDY_DAYLIGHT }
242};
243
244// from camera_effect_t. This list must match aeecamera.h
245static const str_map effects[] = {
246 { CameraParameters::EFFECT_NONE, CAMERA_EFFECT_OFF },
247 { CameraParameters::EFFECT_MONO, CAMERA_EFFECT_MONO },
248 { CameraParameters::EFFECT_NEGATIVE, CAMERA_EFFECT_NEGATIVE },
249 { CameraParameters::EFFECT_SOLARIZE, CAMERA_EFFECT_SOLARIZE },
250 { CameraParameters::EFFECT_SEPIA, CAMERA_EFFECT_SEPIA },
251 { CameraParameters::EFFECT_POSTERIZE, CAMERA_EFFECT_POSTERIZE },
252 { CameraParameters::EFFECT_WHITEBOARD, CAMERA_EFFECT_WHITEBOARD },
253 { CameraParameters::EFFECT_BLACKBOARD, CAMERA_EFFECT_BLACKBOARD },
254 { CameraParameters::EFFECT_AQUA, CAMERA_EFFECT_AQUA }
255};
256
257// from qcamera/common/camera.h
Apurva Rajguru55562b02009-12-03 12:25:35 -0800258static const str_map autoexposure[] = {
259 { CameraParameters::AUTO_EXPOSURE_FRAME_AVG, CAMERA_AEC_FRAME_AVERAGE },
260 { CameraParameters::AUTO_EXPOSURE_CENTER_WEIGHTED, CAMERA_AEC_CENTER_WEIGHTED },
261 { CameraParameters::AUTO_EXPOSURE_SPOT_METERING, CAMERA_AEC_SPOT_METERING }
262};
263
264// from qcamera/common/camera.h
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800265static const str_map antibanding[] = {
266 { CameraParameters::ANTIBANDING_OFF, CAMERA_ANTIBANDING_OFF },
267 { CameraParameters::ANTIBANDING_50HZ, CAMERA_ANTIBANDING_50HZ },
268 { CameraParameters::ANTIBANDING_60HZ, CAMERA_ANTIBANDING_60HZ },
269 { CameraParameters::ANTIBANDING_AUTO, CAMERA_ANTIBANDING_AUTO }
270};
271
272/* Mapping from MCC to antibanding type */
273struct country_map {
274 uint32_t country_code;
275 camera_antibanding_type type;
276};
277
278static struct country_map country_numeric[] = {
279 { 202, CAMERA_ANTIBANDING_50HZ }, // Greece
280 { 204, CAMERA_ANTIBANDING_50HZ }, // Netherlands
281 { 206, CAMERA_ANTIBANDING_50HZ }, // Belgium
282 { 208, CAMERA_ANTIBANDING_50HZ }, // France
283 { 212, CAMERA_ANTIBANDING_50HZ }, // Monaco
284 { 213, CAMERA_ANTIBANDING_50HZ }, // Andorra
285 { 214, CAMERA_ANTIBANDING_50HZ }, // Spain
286 { 216, CAMERA_ANTIBANDING_50HZ }, // Hungary
287 { 219, CAMERA_ANTIBANDING_50HZ }, // Croatia
288 { 220, CAMERA_ANTIBANDING_50HZ }, // Serbia
289 { 222, CAMERA_ANTIBANDING_50HZ }, // Italy
290 { 226, CAMERA_ANTIBANDING_50HZ }, // Romania
291 { 228, CAMERA_ANTIBANDING_50HZ }, // Switzerland
292 { 230, CAMERA_ANTIBANDING_50HZ }, // Czech Republic
293 { 231, CAMERA_ANTIBANDING_50HZ }, // Slovakia
294 { 232, CAMERA_ANTIBANDING_50HZ }, // Austria
295 { 234, CAMERA_ANTIBANDING_50HZ }, // United Kingdom
296 { 235, CAMERA_ANTIBANDING_50HZ }, // United Kingdom
297 { 238, CAMERA_ANTIBANDING_50HZ }, // Denmark
298 { 240, CAMERA_ANTIBANDING_50HZ }, // Sweden
299 { 242, CAMERA_ANTIBANDING_50HZ }, // Norway
300 { 244, CAMERA_ANTIBANDING_50HZ }, // Finland
301 { 246, CAMERA_ANTIBANDING_50HZ }, // Lithuania
302 { 247, CAMERA_ANTIBANDING_50HZ }, // Latvia
303 { 248, CAMERA_ANTIBANDING_50HZ }, // Estonia
304 { 250, CAMERA_ANTIBANDING_50HZ }, // Russian Federation
305 { 255, CAMERA_ANTIBANDING_50HZ }, // Ukraine
306 { 257, CAMERA_ANTIBANDING_50HZ }, // Belarus
307 { 259, CAMERA_ANTIBANDING_50HZ }, // Moldova
308 { 260, CAMERA_ANTIBANDING_50HZ }, // Poland
309 { 262, CAMERA_ANTIBANDING_50HZ }, // Germany
310 { 266, CAMERA_ANTIBANDING_50HZ }, // Gibraltar
311 { 268, CAMERA_ANTIBANDING_50HZ }, // Portugal
312 { 270, CAMERA_ANTIBANDING_50HZ }, // Luxembourg
313 { 272, CAMERA_ANTIBANDING_50HZ }, // Ireland
314 { 274, CAMERA_ANTIBANDING_50HZ }, // Iceland
315 { 276, CAMERA_ANTIBANDING_50HZ }, // Albania
316 { 278, CAMERA_ANTIBANDING_50HZ }, // Malta
317 { 280, CAMERA_ANTIBANDING_50HZ }, // Cyprus
318 { 282, CAMERA_ANTIBANDING_50HZ }, // Georgia
319 { 283, CAMERA_ANTIBANDING_50HZ }, // Armenia
320 { 284, CAMERA_ANTIBANDING_50HZ }, // Bulgaria
321 { 286, CAMERA_ANTIBANDING_50HZ }, // Turkey
322 { 288, CAMERA_ANTIBANDING_50HZ }, // Faroe Islands
323 { 290, CAMERA_ANTIBANDING_50HZ }, // Greenland
324 { 293, CAMERA_ANTIBANDING_50HZ }, // Slovenia
325 { 294, CAMERA_ANTIBANDING_50HZ }, // Macedonia
326 { 295, CAMERA_ANTIBANDING_50HZ }, // Liechtenstein
327 { 297, CAMERA_ANTIBANDING_50HZ }, // Montenegro
328 { 302, CAMERA_ANTIBANDING_60HZ }, // Canada
329 { 310, CAMERA_ANTIBANDING_60HZ }, // United States of America
330 { 311, CAMERA_ANTIBANDING_60HZ }, // United States of America
331 { 312, CAMERA_ANTIBANDING_60HZ }, // United States of America
332 { 313, CAMERA_ANTIBANDING_60HZ }, // United States of America
333 { 314, CAMERA_ANTIBANDING_60HZ }, // United States of America
334 { 315, CAMERA_ANTIBANDING_60HZ }, // United States of America
335 { 316, CAMERA_ANTIBANDING_60HZ }, // United States of America
336 { 330, CAMERA_ANTIBANDING_60HZ }, // Puerto Rico
337 { 334, CAMERA_ANTIBANDING_60HZ }, // Mexico
338 { 338, CAMERA_ANTIBANDING_50HZ }, // Jamaica
339 { 340, CAMERA_ANTIBANDING_50HZ }, // Martinique
340 { 342, CAMERA_ANTIBANDING_50HZ }, // Barbados
341 { 346, CAMERA_ANTIBANDING_60HZ }, // Cayman Islands
342 { 350, CAMERA_ANTIBANDING_60HZ }, // Bermuda
343 { 352, CAMERA_ANTIBANDING_50HZ }, // Grenada
344 { 354, CAMERA_ANTIBANDING_60HZ }, // Montserrat
345 { 362, CAMERA_ANTIBANDING_50HZ }, // Netherlands Antilles
346 { 363, CAMERA_ANTIBANDING_60HZ }, // Aruba
347 { 364, CAMERA_ANTIBANDING_60HZ }, // Bahamas
348 { 365, CAMERA_ANTIBANDING_60HZ }, // Anguilla
349 { 366, CAMERA_ANTIBANDING_50HZ }, // Dominica
350 { 368, CAMERA_ANTIBANDING_60HZ }, // Cuba
351 { 370, CAMERA_ANTIBANDING_60HZ }, // Dominican Republic
352 { 372, CAMERA_ANTIBANDING_60HZ }, // Haiti
353 { 401, CAMERA_ANTIBANDING_50HZ }, // Kazakhstan
354 { 402, CAMERA_ANTIBANDING_50HZ }, // Bhutan
355 { 404, CAMERA_ANTIBANDING_50HZ }, // India
356 { 405, CAMERA_ANTIBANDING_50HZ }, // India
357 { 410, CAMERA_ANTIBANDING_50HZ }, // Pakistan
358 { 413, CAMERA_ANTIBANDING_50HZ }, // Sri Lanka
359 { 414, CAMERA_ANTIBANDING_50HZ }, // Myanmar
360 { 415, CAMERA_ANTIBANDING_50HZ }, // Lebanon
361 { 416, CAMERA_ANTIBANDING_50HZ }, // Jordan
362 { 417, CAMERA_ANTIBANDING_50HZ }, // Syria
363 { 418, CAMERA_ANTIBANDING_50HZ }, // Iraq
364 { 419, CAMERA_ANTIBANDING_50HZ }, // Kuwait
365 { 420, CAMERA_ANTIBANDING_60HZ }, // Saudi Arabia
366 { 421, CAMERA_ANTIBANDING_50HZ }, // Yemen
367 { 422, CAMERA_ANTIBANDING_50HZ }, // Oman
368 { 424, CAMERA_ANTIBANDING_50HZ }, // United Arab Emirates
369 { 425, CAMERA_ANTIBANDING_50HZ }, // Israel
370 { 426, CAMERA_ANTIBANDING_50HZ }, // Bahrain
371 { 427, CAMERA_ANTIBANDING_50HZ }, // Qatar
372 { 428, CAMERA_ANTIBANDING_50HZ }, // Mongolia
373 { 429, CAMERA_ANTIBANDING_50HZ }, // Nepal
374 { 430, CAMERA_ANTIBANDING_50HZ }, // United Arab Emirates
375 { 431, CAMERA_ANTIBANDING_50HZ }, // United Arab Emirates
376 { 432, CAMERA_ANTIBANDING_50HZ }, // Iran
377 { 434, CAMERA_ANTIBANDING_50HZ }, // Uzbekistan
378 { 436, CAMERA_ANTIBANDING_50HZ }, // Tajikistan
379 { 437, CAMERA_ANTIBANDING_50HZ }, // Kyrgyz Rep
380 { 438, CAMERA_ANTIBANDING_50HZ }, // Turkmenistan
381 { 440, CAMERA_ANTIBANDING_60HZ }, // Japan
382 { 441, CAMERA_ANTIBANDING_60HZ }, // Japan
383 { 452, CAMERA_ANTIBANDING_50HZ }, // Vietnam
384 { 454, CAMERA_ANTIBANDING_50HZ }, // Hong Kong
385 { 455, CAMERA_ANTIBANDING_50HZ }, // Macao
386 { 456, CAMERA_ANTIBANDING_50HZ }, // Cambodia
387 { 457, CAMERA_ANTIBANDING_50HZ }, // Laos
388 { 460, CAMERA_ANTIBANDING_50HZ }, // China
389 { 466, CAMERA_ANTIBANDING_60HZ }, // Taiwan
390 { 470, CAMERA_ANTIBANDING_50HZ }, // Bangladesh
391 { 472, CAMERA_ANTIBANDING_50HZ }, // Maldives
392 { 502, CAMERA_ANTIBANDING_50HZ }, // Malaysia
393 { 505, CAMERA_ANTIBANDING_50HZ }, // Australia
394 { 510, CAMERA_ANTIBANDING_50HZ }, // Indonesia
395 { 514, CAMERA_ANTIBANDING_50HZ }, // East Timor
396 { 515, CAMERA_ANTIBANDING_60HZ }, // Philippines
397 { 520, CAMERA_ANTIBANDING_50HZ }, // Thailand
398 { 525, CAMERA_ANTIBANDING_50HZ }, // Singapore
399 { 530, CAMERA_ANTIBANDING_50HZ }, // New Zealand
400 { 535, CAMERA_ANTIBANDING_60HZ }, // Guam
401 { 536, CAMERA_ANTIBANDING_50HZ }, // Nauru
402 { 537, CAMERA_ANTIBANDING_50HZ }, // Papua New Guinea
403 { 539, CAMERA_ANTIBANDING_50HZ }, // Tonga
404 { 541, CAMERA_ANTIBANDING_50HZ }, // Vanuatu
405 { 542, CAMERA_ANTIBANDING_50HZ }, // Fiji
406 { 544, CAMERA_ANTIBANDING_60HZ }, // American Samoa
407 { 545, CAMERA_ANTIBANDING_50HZ }, // Kiribati
408 { 546, CAMERA_ANTIBANDING_50HZ }, // New Caledonia
409 { 548, CAMERA_ANTIBANDING_50HZ }, // Cook Islands
410 { 602, CAMERA_ANTIBANDING_50HZ }, // Egypt
411 { 603, CAMERA_ANTIBANDING_50HZ }, // Algeria
412 { 604, CAMERA_ANTIBANDING_50HZ }, // Morocco
413 { 605, CAMERA_ANTIBANDING_50HZ }, // Tunisia
414 { 606, CAMERA_ANTIBANDING_50HZ }, // Libya
415 { 607, CAMERA_ANTIBANDING_50HZ }, // Gambia
416 { 608, CAMERA_ANTIBANDING_50HZ }, // Senegal
417 { 609, CAMERA_ANTIBANDING_50HZ }, // Mauritania
418 { 610, CAMERA_ANTIBANDING_50HZ }, // Mali
419 { 611, CAMERA_ANTIBANDING_50HZ }, // Guinea
420 { 613, CAMERA_ANTIBANDING_50HZ }, // Burkina Faso
421 { 614, CAMERA_ANTIBANDING_50HZ }, // Niger
422 { 616, CAMERA_ANTIBANDING_50HZ }, // Benin
423 { 617, CAMERA_ANTIBANDING_50HZ }, // Mauritius
424 { 618, CAMERA_ANTIBANDING_50HZ }, // Liberia
425 { 619, CAMERA_ANTIBANDING_50HZ }, // Sierra Leone
426 { 620, CAMERA_ANTIBANDING_50HZ }, // Ghana
427 { 621, CAMERA_ANTIBANDING_50HZ }, // Nigeria
428 { 622, CAMERA_ANTIBANDING_50HZ }, // Chad
429 { 623, CAMERA_ANTIBANDING_50HZ }, // Central African Republic
430 { 624, CAMERA_ANTIBANDING_50HZ }, // Cameroon
431 { 625, CAMERA_ANTIBANDING_50HZ }, // Cape Verde
432 { 627, CAMERA_ANTIBANDING_50HZ }, // Equatorial Guinea
433 { 631, CAMERA_ANTIBANDING_50HZ }, // Angola
434 { 633, CAMERA_ANTIBANDING_50HZ }, // Seychelles
435 { 634, CAMERA_ANTIBANDING_50HZ }, // Sudan
436 { 636, CAMERA_ANTIBANDING_50HZ }, // Ethiopia
437 { 637, CAMERA_ANTIBANDING_50HZ }, // Somalia
438 { 638, CAMERA_ANTIBANDING_50HZ }, // Djibouti
439 { 639, CAMERA_ANTIBANDING_50HZ }, // Kenya
440 { 640, CAMERA_ANTIBANDING_50HZ }, // Tanzania
441 { 641, CAMERA_ANTIBANDING_50HZ }, // Uganda
442 { 642, CAMERA_ANTIBANDING_50HZ }, // Burundi
443 { 643, CAMERA_ANTIBANDING_50HZ }, // Mozambique
444 { 645, CAMERA_ANTIBANDING_50HZ }, // Zambia
445 { 646, CAMERA_ANTIBANDING_50HZ }, // Madagascar
446 { 647, CAMERA_ANTIBANDING_50HZ }, // France
447 { 648, CAMERA_ANTIBANDING_50HZ }, // Zimbabwe
448 { 649, CAMERA_ANTIBANDING_50HZ }, // Namibia
449 { 650, CAMERA_ANTIBANDING_50HZ }, // Malawi
450 { 651, CAMERA_ANTIBANDING_50HZ }, // Lesotho
451 { 652, CAMERA_ANTIBANDING_50HZ }, // Botswana
452 { 653, CAMERA_ANTIBANDING_50HZ }, // Swaziland
453 { 654, CAMERA_ANTIBANDING_50HZ }, // Comoros
454 { 655, CAMERA_ANTIBANDING_50HZ }, // South Africa
455 { 657, CAMERA_ANTIBANDING_50HZ }, // Eritrea
456 { 702, CAMERA_ANTIBANDING_60HZ }, // Belize
457 { 704, CAMERA_ANTIBANDING_60HZ }, // Guatemala
458 { 706, CAMERA_ANTIBANDING_60HZ }, // El Salvador
459 { 708, CAMERA_ANTIBANDING_60HZ }, // Honduras
460 { 710, CAMERA_ANTIBANDING_60HZ }, // Nicaragua
461 { 712, CAMERA_ANTIBANDING_60HZ }, // Costa Rica
462 { 714, CAMERA_ANTIBANDING_60HZ }, // Panama
463 { 722, CAMERA_ANTIBANDING_50HZ }, // Argentina
464 { 724, CAMERA_ANTIBANDING_60HZ }, // Brazil
465 { 730, CAMERA_ANTIBANDING_50HZ }, // Chile
466 { 732, CAMERA_ANTIBANDING_60HZ }, // Colombia
467 { 734, CAMERA_ANTIBANDING_60HZ }, // Venezuela
468 { 736, CAMERA_ANTIBANDING_50HZ }, // Bolivia
469 { 738, CAMERA_ANTIBANDING_60HZ }, // Guyana
470 { 740, CAMERA_ANTIBANDING_60HZ }, // Ecuador
471 { 742, CAMERA_ANTIBANDING_50HZ }, // French Guiana
472 { 744, CAMERA_ANTIBANDING_50HZ }, // Paraguay
473 { 746, CAMERA_ANTIBANDING_60HZ }, // Suriname
474 { 748, CAMERA_ANTIBANDING_50HZ }, // Uruguay
475 { 750, CAMERA_ANTIBANDING_50HZ }, // Falkland Islands
476};
477
478#define country_number (sizeof(country_numeric) / sizeof(country_map))
479
480/* Look up pre-sorted antibanding_type table by current MCC. */
481static camera_antibanding_type camera_get_location(void) {
482 char value[PROP_VALUE_MAX];
483 char country_value[PROP_VALUE_MAX];
484 uint32_t country_code, count;
485 memset(value, 0x00, sizeof(value));
486 memset(country_value, 0x00, sizeof(country_value));
487 if (!__system_property_get("gsm.operator.numeric", value)) {
488 return CAMERA_ANTIBANDING_60HZ;
489 }
490 memcpy(country_value, value, 3);
491 country_code = atoi(country_value);
492 LOGD("value:%s, country value:%s, country code:%d\n",
493 value, country_value, country_code);
494 int left = 0;
495 int right = country_number - 1;
496 while (left <= right) {
497 int index = (left + right) >> 1;
498 if (country_numeric[index].country_code == country_code)
499 return country_numeric[index].type;
500 else if (country_numeric[index].country_code > country_code)
501 right = index - 1;
502 else
503 left = index + 1;
504 }
505 return CAMERA_ANTIBANDING_60HZ;
506}
507
508// from camera.h, led_mode_t
509static const str_map flash[] = {
510 { CameraParameters::FLASH_MODE_OFF, LED_MODE_OFF },
511 { CameraParameters::FLASH_MODE_AUTO, LED_MODE_AUTO },
512 { CameraParameters::FLASH_MODE_ON, LED_MODE_ON }
513};
514
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530515// from mm-camera/common/camera.h.
516static const str_map iso[] = {
517 { CameraParameters::ISO_AUTO, CAMERA_ISO_AUTO},
518 { CameraParameters::ISO_HJR, CAMERA_ISO_DEBLUR},
519 { CameraParameters::ISO_100, CAMERA_ISO_100},
520 { CameraParameters::ISO_200, CAMERA_ISO_200},
521 { CameraParameters::ISO_400, CAMERA_ISO_400},
522 { CameraParameters::ISO_800, CAMERA_ISO_800 }
523};
524
525
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800526#define DONT_CARE 0
527static const str_map focus_modes[] = {
Srinivasan Kannan71229622009-12-04 12:05:58 -0800528 { CameraParameters::FOCUS_MODE_AUTO, AF_MODE_AUTO},
529 { CameraParameters::FOCUS_MODE_INFINITY, DONT_CARE },
530 { CameraParameters::FOCUS_MODE_NORMAL, AF_MODE_NORMAL },
531 { CameraParameters::FOCUS_MODE_MACRO, AF_MODE_MACRO }
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800532};
533
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530534static const str_map lensshade[] = {
535 { CameraParameters::LENSSHADE_ENABLE, TRUE },
536 { CameraParameters::LENSSHADE_DISABLE, FALSE }
537};
538
Srinivasan Kannan71229622009-12-04 12:05:58 -0800539struct SensorType {
540 const char *name;
541 int rawPictureWidth;
542 int rawPictureHeight;
543 bool hasAutoFocusSupport;
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800544 int max_supported_snapshot_width;
545 int max_supported_snapshot_height;
Srinivasan Kannan71229622009-12-04 12:05:58 -0800546};
547
548static SensorType sensorTypes[] = {
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800549 { "5mp", 2608, 1960, true, 2592, 1944 },
550 { "3mp", 2064, 1544, false, 2048, 1536 },
551 { "2mp", 3200, 1200, false, 1600, 1200 } };
552
Srinivasan Kannan71229622009-12-04 12:05:58 -0800553
554static SensorType * sensorType;
555
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800556static const str_map picture_formats[] = {
557 {CameraParameters::PIXEL_FORMAT_JPEG, PICTURE_FORMAT_JPEG},
558 {CameraParameters::PIXEL_FORMAT_RAW, PICTURE_FORMAT_RAW}
559};
560
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800561static bool parameter_string_initialized = false;
562static String8 preview_size_values;
563static String8 picture_size_values;
564static String8 antibanding_values;
565static String8 effect_values;
Apurva Rajguru55562b02009-12-03 12:25:35 -0800566static String8 autoexposure_values;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800567static String8 whitebalance_values;
568static String8 flash_values;
569static String8 focus_mode_values;
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530570static String8 iso_values;
571static String8 lensshade_values;
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800572static String8 picture_format_values;
573
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800574
575static String8 create_sizes_str(const camera_size_type *sizes, int len) {
576 String8 str;
577 char buffer[32];
578
579 if (len > 0) {
580 sprintf(buffer, "%dx%d", sizes[0].width, sizes[0].height);
581 str.append(buffer);
582 }
583 for (int i = 1; i < len; i++) {
584 sprintf(buffer, ",%dx%d", sizes[i].width, sizes[i].height);
585 str.append(buffer);
586 }
587 return str;
588}
589
590static String8 create_values_str(const str_map *values, int len) {
591 String8 str;
592
593 if (len > 0) {
594 str.append(values[0].desc);
595 }
596 for (int i = 1; i < len; i++) {
597 str.append(",");
598 str.append(values[i].desc);
599 }
600 return str;
601}
602
603static Mutex singleton_lock;
604static bool singleton_releasing;
605static Condition singleton_wait;
606
607static void receive_camframe_callback(struct msm_frame *frame);
608static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size);
609static void receive_jpeg_callback(jpeg_event_t status);
610static void receive_shutter_callback(common_crop_t *crop);
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800611static void receive_camframetimeout_callback(void);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800612
613QualcommCameraHardware::QualcommCameraHardware()
614 : mParameters(),
615 mCameraRunning(false),
616 mPreviewInitialized(false),
617 mFrameThreadRunning(false),
618 mSnapshotThreadRunning(false),
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800619 mSnapshotFormat(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800620 mReleasedRecordingFrame(false),
621 mPreviewFrameSize(0),
622 mRawSize(0),
623 mCameraControlFd(-1),
624 mAutoFocusThreadRunning(false),
625 mAutoFocusFd(-1),
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800626 mBrightness(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800627 mInPreviewCallback(false),
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800628 mUseOverlay(0),
629 mOverlay(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800630 mMsgEnabled(0),
631 mNotifyCallback(0),
632 mDataCallback(0),
633 mDataCallbackTimestamp(0),
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800634 mCallbackCookie(0)
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800635{
636 memset(&mDimension, 0, sizeof(mDimension));
637 memset(&mCrop, 0, sizeof(mCrop));
638 LOGV("constructor EX");
639}
640
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800641
642//filter Picture sizes based on max width and height
643void QualcommCameraHardware::filterPictureSizes(){
644 int i;
645 for(i=0;i<PICTURE_SIZE_COUNT;i++){
646 if(((picture_sizes[i].width <=
647 sensorType->max_supported_snapshot_width) &&
648 (picture_sizes[i].height <=
649 sensorType->max_supported_snapshot_height))){
650 picture_sizes_ptr = picture_sizes + i;
651 supportedPictureSizesCount = PICTURE_SIZE_COUNT - i ;
652 return ;
653 }
654 }
655}
656
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800657void QualcommCameraHardware::initDefaultParameters()
658{
659 LOGV("initDefaultParameters E");
660
661 // Initialize constant parameter strings. This will happen only once in the
662 // lifetime of the mediaserver process.
663 if (!parameter_string_initialized) {
Srinivasan Kannan71229622009-12-04 12:05:58 -0800664 findSensorType();
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800665 antibanding_values = create_values_str(
666 antibanding, sizeof(antibanding) / sizeof(str_map));
667 effect_values = create_values_str(
668 effects, sizeof(effects) / sizeof(str_map));
Apurva Rajguru55562b02009-12-03 12:25:35 -0800669 autoexposure_values = create_values_str(
670 autoexposure, sizeof(autoexposure) / sizeof(str_map));
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800671 whitebalance_values = create_values_str(
672 whitebalance, sizeof(whitebalance) / sizeof(str_map));
673 preview_size_values = create_sizes_str(
674 preview_sizes, PREVIEW_SIZE_COUNT);
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800675 //filter picture sizes
676 filterPictureSizes();
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800677 picture_size_values = create_sizes_str(
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800678 picture_sizes_ptr, supportedPictureSizesCount);
679
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800680 flash_values = create_values_str(
681 flash, sizeof(flash) / sizeof(str_map));
Srinivasan Kannan71229622009-12-04 12:05:58 -0800682 if(sensorType->hasAutoFocusSupport){
683 focus_mode_values = create_values_str(
684 focus_modes, sizeof(focus_modes) / sizeof(str_map));
685 }
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530686 iso_values = create_values_str(
687 iso,sizeof(iso)/sizeof(str_map));
688 lensshade_values = create_values_str(
689 lensshade,sizeof(lensshade)/sizeof(str_map));
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800690 picture_format_values = create_values_str(
691 picture_formats, sizeof(picture_formats)/sizeof(str_map));
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800692 parameter_string_initialized = true;
693 }
694
695 const camera_size_type *ps = &preview_sizes[DEFAULT_PREVIEW_SETTING];
696 mParameters.setPreviewSize(ps->width, ps->height);
697 mDimension.display_width = ps->width;
698 mDimension.display_height = ps->height;
699 mParameters.setPreviewFrameRate(15);
700 mParameters.setPreviewFormat("yuv420sp"); // informative
701
702 mParameters.setPictureSize(DEFAULT_PICTURE_WIDTH, DEFAULT_PICTURE_HEIGHT);
703 mParameters.setPictureFormat("jpeg"); // informative
704
705 mParameters.set(CameraParameters::KEY_JPEG_QUALITY, "100"); // max quality
706 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH,
707 THUMBNAIL_WIDTH_STR); // informative
708 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT,
709 THUMBNAIL_HEIGHT_STR); // informative
Srinivasan Kannan80d878f2009-12-18 15:06:02 -0800710 mDimension.ui_thumbnail_width =
711 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].width;
712 mDimension.ui_thumbnail_height =
713 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800714 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, "90");
715
716 mParameters.set(CameraParameters::KEY_ANTIBANDING,
717 CameraParameters::ANTIBANDING_AUTO);
718 mParameters.set(CameraParameters::KEY_EFFECT,
719 CameraParameters::EFFECT_NONE);
Apurva Rajguru55562b02009-12-03 12:25:35 -0800720 mParameters.set(CameraParameters::KEY_AUTO_EXPOSURE,
721 CameraParameters::AUTO_EXPOSURE_FRAME_AVG);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800722 mParameters.set(CameraParameters::KEY_WHITE_BALANCE,
723 CameraParameters::WHITE_BALANCE_AUTO);
724 mParameters.set(CameraParameters::KEY_FOCUS_MODE,
725 CameraParameters::FOCUS_MODE_AUTO);
726
727 mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES,
728 preview_size_values.string());
729 mParameters.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES,
730 picture_size_values.string());
731 mParameters.set(CameraParameters::KEY_SUPPORTED_ANTIBANDING,
732 antibanding_values);
733 mParameters.set(CameraParameters::KEY_SUPPORTED_EFFECTS, effect_values);
Apurva Rajguru55562b02009-12-03 12:25:35 -0800734 mParameters.set(CameraParameters::KEY_SUPPORTED_AUTO_EXPOSURE, autoexposure_values);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800735 mParameters.set(CameraParameters::KEY_SUPPORTED_WHITE_BALANCE,
736 whitebalance_values);
737 mParameters.set(CameraParameters::KEY_SUPPORTED_FOCUS_MODES,
738 focus_mode_values);
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800739 mParameters.set(CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS,
740 picture_format_values);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800741
742 if (mSensorInfo.flash_enabled) {
743 mParameters.set(CameraParameters::KEY_FLASH_MODE,
744 CameraParameters::FLASH_MODE_OFF);
745 mParameters.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES,
746 flash_values);
747 }
748
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530749 mParameters.set("luma-adaptation", "18");
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800750 mParameters.set("zoom-supported", "true");
751 mParameters.set("max-zoom", MAX_ZOOM_LEVEL);
752 mParameters.set("zoom", 0);
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800753 mParameters.set(CameraParameters::KEY_PICTURE_FORMAT,
754 CameraParameters::PIXEL_FORMAT_JPEG);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800755
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530756 mParameters.set(CameraParameters::KEY_ISO_MODE,
757 CameraParameters::ISO_AUTO);
758 mParameters.set(CameraParameters::KEY_LENSSHADE,
759 CameraParameters::LENSSHADE_ENABLE);
760 mParameters.set(CameraParameters::KEY_SUPPORTED_ISO_MODES,
761 iso_values);
762 mParameters.set(CameraParameters::KEY_SUPPORTED_LENSSHADE_MODES,
763 lensshade_values);
764
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800765 if (setParameters(mParameters) != NO_ERROR) {
766 LOGE("Failed to set default parameters?!");
767 }
768
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -0800769 mUseOverlay = useOverlay();
770
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800771 /* Initialize the camframe_timeout_flag*/
772 Mutex::Autolock l(&mCamframeTimeoutLock);
773 camframe_timeout_flag = FALSE;
774
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800775 LOGV("initDefaultParameters X");
776}
777
Srinivasan Kannan71229622009-12-04 12:05:58 -0800778void QualcommCameraHardware::findSensorType(){
779 mDimension.picture_width = DEFAULT_PICTURE_WIDTH;
780 mDimension.picture_height = DEFAULT_PICTURE_HEIGHT;
781 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
782 sizeof(cam_ctrl_dimension_t), &mDimension);
783 if (ret) {
784 unsigned int i;
785 for (i = 0; i < sizeof(sensorTypes) / sizeof(SensorType); i++) {
786 if (sensorTypes[i].rawPictureHeight
787 == mDimension.raw_picture_height) {
788 sensorType = sensorTypes + i;
789 return;
790 }
791 }
792 }
793 //default to 5 mp
794 sensorType = sensorTypes;
795 return;
796}
797
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800798#define ROUND_TO_PAGE(x) (((x)+0xfff)&~0xfff)
799
800bool QualcommCameraHardware::startCamera()
801{
802 LOGV("startCamera E");
803#if DLOPEN_LIBMMCAMERA
804 libmmcamera = ::dlopen("liboemcamera.so", RTLD_NOW);
805 LOGV("loading liboemcamera at %p", libmmcamera);
806 if (!libmmcamera) {
807 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
808 return false;
809 }
810
811 *(void **)&LINK_cam_frame =
812 ::dlsym(libmmcamera, "cam_frame");
813 *(void **)&LINK_camframe_terminate =
814 ::dlsym(libmmcamera, "camframe_terminate");
815
816 *(void **)&LINK_jpeg_encoder_init =
817 ::dlsym(libmmcamera, "jpeg_encoder_init");
818
819 *(void **)&LINK_jpeg_encoder_encode =
820 ::dlsym(libmmcamera, "jpeg_encoder_encode");
821
822 *(void **)&LINK_jpeg_encoder_join =
823 ::dlsym(libmmcamera, "jpeg_encoder_join");
824
825 *(void **)&LINK_mmcamera_camframe_callback =
826 ::dlsym(libmmcamera, "mmcamera_camframe_callback");
827
828 *LINK_mmcamera_camframe_callback = receive_camframe_callback;
829
830 *(void **)&LINK_mmcamera_jpegfragment_callback =
831 ::dlsym(libmmcamera, "mmcamera_jpegfragment_callback");
832
833 *LINK_mmcamera_jpegfragment_callback = receive_jpeg_fragment_callback;
834
835 *(void **)&LINK_mmcamera_jpeg_callback =
836 ::dlsym(libmmcamera, "mmcamera_jpeg_callback");
837
838 *LINK_mmcamera_jpeg_callback = receive_jpeg_callback;
839
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800840 *(void **)&LINK_camframe_timeout_callback =
841 ::dlsym(libmmcamera, "camframe_timeout_callback");
842
843 *LINK_camframe_timeout_callback = receive_camframetimeout_callback;
844
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800845/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800846 *(void **)&LINK_mmcamera_shutter_callback =
847 ::dlsym(libmmcamera, "mmcamera_shutter_callback");
848
849 *LINK_mmcamera_shutter_callback = receive_shutter_callback;
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800850*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800851 *(void**)&LINK_jpeg_encoder_setMainImageQuality =
852 ::dlsym(libmmcamera, "jpeg_encoder_setMainImageQuality");
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800853/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800854 *(void**)&LINK_jpeg_encoder_setThumbnailQuality =
855 ::dlsym(libmmcamera, "jpeg_encoder_setThumbnailQuality");
856
857 *(void**)&LINK_jpeg_encoder_setRotation =
858 ::dlsym(libmmcamera, "jpeg_encoder_setRotation");
859
860 *(void**)&LINK_jpeg_encoder_setLocation =
861 ::dlsym(libmmcamera, "jpeg_encoder_setLocation");
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800862*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800863 *(void **)&LINK_cam_conf =
864 ::dlsym(libmmcamera, "cam_conf");
865
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800866/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800867 *(void **)&LINK_default_sensor_get_snapshot_sizes =
868 ::dlsym(libmmcamera, "default_sensor_get_snapshot_sizes");
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800869*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800870 *(void **)&LINK_launch_cam_conf_thread =
871 ::dlsym(libmmcamera, "launch_cam_conf_thread");
872
873 *(void **)&LINK_release_cam_conf_thread =
874 ::dlsym(libmmcamera, "release_cam_conf_thread");
875
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800876/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800877 *(void **)&LINK_zoom_crop_upscale =
878 ::dlsym(libmmcamera, "zoom_crop_upscale");
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800879*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800880
881#else
882 mmcamera_camframe_callback = receive_camframe_callback;
883 mmcamera_jpegfragment_callback = receive_jpeg_fragment_callback;
884 mmcamera_jpeg_callback = receive_jpeg_callback;
885 mmcamera_shutter_callback = receive_shutter_callback;
886#endif // DLOPEN_LIBMMCAMERA
887
888 /* The control thread is in libcamera itself. */
889 mCameraControlFd = open(MSM_CAMERA_CONTROL, O_RDWR);
890 if (mCameraControlFd < 0) {
891 LOGE("startCamera X: %s open failed: %s!",
892 MSM_CAMERA_CONTROL,
893 strerror(errno));
894 return false;
895 }
896
897 /* This will block until the control thread is launched. After that, sensor
898 * information becomes available.
899 */
900
901 if (LINK_launch_cam_conf_thread()) {
902 LOGE("failed to launch the camera config thread");
903 return false;
904 }
905
906 memset(&mSensorInfo, 0, sizeof(mSensorInfo));
907 if (ioctl(mCameraControlFd,
908 MSM_CAM_IOCTL_GET_SENSOR_INFO,
909 &mSensorInfo) < 0)
910 LOGW("%s: cannot retrieve sensor info!", __FUNCTION__);
911 else
912 LOGI("%s: camsensor name %s, flash %d", __FUNCTION__,
913 mSensorInfo.name, mSensorInfo.flash_enabled);
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800914/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800915 picture_sizes = LINK_default_sensor_get_snapshot_sizes(&PICTURE_SIZE_COUNT);
916 if (!picture_sizes || !PICTURE_SIZE_COUNT) {
917 LOGE("startCamera X: could not get snapshot sizes");
918 return false;
919 }
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800920*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800921 LOGV("startCamera X");
922 return true;
923}
924
925status_t QualcommCameraHardware::dump(int fd,
926 const Vector<String16>& args) const
927{
928 const size_t SIZE = 256;
929 char buffer[SIZE];
930 String8 result;
931
932 // Dump internal primitives.
933 result.append("QualcommCameraHardware::dump");
934 snprintf(buffer, 255, "mMsgEnabled (%d)\n", mMsgEnabled);
935 result.append(buffer);
936 int width, height;
937 mParameters.getPreviewSize(&width, &height);
938 snprintf(buffer, 255, "preview width(%d) x height (%d)\n", width, height);
939 result.append(buffer);
940 mParameters.getPictureSize(&width, &height);
941 snprintf(buffer, 255, "raw width(%d) x height (%d)\n", width, height);
942 result.append(buffer);
943 snprintf(buffer, 255,
944 "preview frame size(%d), raw size (%d), jpeg size (%d) "
945 "and jpeg max size (%d)\n", mPreviewFrameSize, mRawSize,
946 mJpegSize, mJpegMaxSize);
947 result.append(buffer);
948 write(fd, result.string(), result.size());
949
950 // Dump internal objects.
951 if (mPreviewHeap != 0) {
952 mPreviewHeap->dump(fd, args);
953 }
954 if (mRawHeap != 0) {
955 mRawHeap->dump(fd, args);
956 }
957 if (mJpegHeap != 0) {
958 mJpegHeap->dump(fd, args);
959 }
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800960 if(mRawSnapshotAshmemHeap != 0 ){
961 mRawSnapshotAshmemHeap->dump(fd, args);
962 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800963 mParameters.dump(fd, args);
964 return NO_ERROR;
965}
966
967static bool native_set_afmode(int camfd, isp3a_af_mode_t af_type)
968{
969 int rc;
970 struct msm_ctrl_cmd ctrlCmd;
971
972 ctrlCmd.timeout_ms = 5000;
973 ctrlCmd.type = CAMERA_SET_PARM_AUTO_FOCUS;
974 ctrlCmd.length = sizeof(af_type);
975 ctrlCmd.value = &af_type;
976 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
977
978 if ((rc = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0)
979 LOGE("native_set_afmode: ioctl fd %d error %s\n",
980 camfd,
981 strerror(errno));
982
983 LOGV("native_set_afmode: ctrlCmd.status == %d\n", ctrlCmd.status);
984 return rc >= 0 && ctrlCmd.status == CAMERA_EXIT_CB_DONE;
985}
986
987static bool native_cancel_afmode(int camfd, int af_fd)
988{
989 int rc;
990 struct msm_ctrl_cmd ctrlCmd;
991
992 ctrlCmd.timeout_ms = 0;
993 ctrlCmd.type = CAMERA_AUTO_FOCUS_CANCEL;
994 ctrlCmd.length = 0;
995 ctrlCmd.value = NULL;
996 ctrlCmd.resp_fd = -1; // there's no response fd
997
998 if ((rc = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND_2, &ctrlCmd)) < 0)
999 {
1000 LOGE("native_cancel_afmode: ioctl fd %d error %s\n",
1001 camfd,
1002 strerror(errno));
1003 return false;
1004 }
1005
1006 return true;
1007}
1008
1009static bool native_start_preview(int camfd)
1010{
1011 struct msm_ctrl_cmd ctrlCmd;
1012
1013 ctrlCmd.timeout_ms = 5000;
1014 ctrlCmd.type = CAMERA_START_PREVIEW;
1015 ctrlCmd.length = 0;
1016 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1017
1018 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1019 LOGE("native_start_preview: MSM_CAM_IOCTL_CTRL_COMMAND fd %d error %s",
1020 camfd,
1021 strerror(errno));
1022 return false;
1023 }
1024
1025 return true;
1026}
1027
1028static bool native_get_picture (int camfd, common_crop_t *crop)
1029{
1030 struct msm_ctrl_cmd ctrlCmd;
1031
1032 ctrlCmd.timeout_ms = 5000;
1033 ctrlCmd.length = sizeof(common_crop_t);
1034 ctrlCmd.value = crop;
1035
1036 if(ioctl(camfd, MSM_CAM_IOCTL_GET_PICTURE, &ctrlCmd) < 0) {
1037 LOGE("native_get_picture: MSM_CAM_IOCTL_GET_PICTURE fd %d error %s",
1038 camfd,
1039 strerror(errno));
1040 return false;
1041 }
1042
1043 LOGV("crop: in1_w %d", crop->in1_w);
1044 LOGV("crop: in1_h %d", crop->in1_h);
1045 LOGV("crop: out1_w %d", crop->out1_w);
1046 LOGV("crop: out1_h %d", crop->out1_h);
1047
1048 LOGV("crop: in2_w %d", crop->in2_w);
1049 LOGV("crop: in2_h %d", crop->in2_h);
1050 LOGV("crop: out2_w %d", crop->out2_w);
1051 LOGV("crop: out2_h %d", crop->out2_h);
1052
1053 LOGV("crop: update %d", crop->update_flag);
1054
1055 return true;
1056}
1057
1058static bool native_stop_preview(int camfd)
1059{
1060 struct msm_ctrl_cmd ctrlCmd;
1061 ctrlCmd.timeout_ms = 5000;
1062 ctrlCmd.type = CAMERA_STOP_PREVIEW;
1063 ctrlCmd.length = 0;
1064 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1065
1066 if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1067 LOGE("native_stop_preview: ioctl fd %d error %s",
1068 camfd,
1069 strerror(errno));
1070 return false;
1071 }
1072
1073 return true;
1074}
1075
1076static bool native_prepare_snapshot(int camfd)
1077{
1078 int ioctlRetVal = true;
1079 struct msm_ctrl_cmd ctrlCmd;
1080
1081 ctrlCmd.timeout_ms = 1000;
1082 ctrlCmd.type = CAMERA_PREPARE_SNAPSHOT;
1083 ctrlCmd.length = 0;
1084 ctrlCmd.value = NULL;
1085 ctrlCmd.resp_fd = camfd;
1086
1087 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1088 LOGE("native_prepare_snapshot: ioctl fd %d error %s",
1089 camfd,
1090 strerror(errno));
1091 return false;
1092 }
1093 return true;
1094}
1095
1096static bool native_start_snapshot(int camfd)
1097{
1098 struct msm_ctrl_cmd ctrlCmd;
1099
1100 ctrlCmd.timeout_ms = 5000;
1101 ctrlCmd.type = CAMERA_START_SNAPSHOT;
1102 ctrlCmd.length = 0;
1103 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1104
1105 if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1106 LOGE("native_start_snapshot: ioctl fd %d error %s",
1107 camfd,
1108 strerror(errno));
1109 return false;
1110 }
1111
1112 return true;
1113}
1114
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001115static bool native_start_raw_snapshot(int camfd)
1116{
1117 int ret;
1118 struct msm_ctrl_cmd ctrlCmd;
1119
1120 ctrlCmd.timeout_ms = 1000;
1121 ctrlCmd.type = CAMERA_START_RAW_SNAPSHOT;
1122 ctrlCmd.length = 0;
1123 ctrlCmd.value = NULL;
1124 ctrlCmd.resp_fd = camfd;
1125
1126 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1127 LOGE("native_start_raw_snapshot: ioctl failed. ioctl return value "\
1128 "is %d \n", ret);
1129 return false;
1130 }
1131 return true;
1132}
1133
1134
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001135static bool native_stop_snapshot (int camfd)
1136{
1137 struct msm_ctrl_cmd ctrlCmd;
1138
1139 ctrlCmd.timeout_ms = 0;
1140 ctrlCmd.type = CAMERA_STOP_SNAPSHOT;
1141 ctrlCmd.length = 0;
1142 ctrlCmd.resp_fd = -1;
1143
1144 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND_2, &ctrlCmd) < 0) {
1145 LOGE("native_stop_snapshot: ioctl fd %d error %s",
1146 camfd,
1147 strerror(errno));
1148 return false;
1149 }
1150
1151 return true;
1152}
1153
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001154static rat_t latitude[3];
1155static rat_t longitude[3];
1156static char lonref[2];
1157static char latref[2];
1158static char dateTime[20];
1159static rat_t altitude;
1160
1161static void addExifTag(exif_tag_id_t tagid, exif_tag_type_t type,
1162 uint32_t count, uint8_t copy, void *data) {
1163
1164 if(exif_table_numEntries == MAX_EXIF_TABLE_ENTRIES) {
1165 LOGE("Number of entries exceeded limit");
1166 return;
1167 }
1168
1169 int index = exif_table_numEntries;
1170 exif_data[index].tag_id = tagid;
1171 exif_data[index].tag_entry.type = type;
1172 exif_data[index].tag_entry.count = count;
1173 exif_data[index].tag_entry.copy = copy;
1174 if((type == EXIF_RATIONAL) && (count > 1))
1175 exif_data[index].tag_entry.data._rats = (rat_t *)data;
1176 if((type == EXIF_RATIONAL) && (count == 1))
1177 exif_data[index].tag_entry.data._rat = *(rat_t *)data;
1178 else if(type == EXIF_ASCII)
1179 exif_data[index].tag_entry.data._ascii = (char *)data;
1180 else if(type == EXIF_BYTE)
1181 exif_data[index].tag_entry.data._byte = *(uint8_t *)data;
1182
1183 // Increase number of entries
1184 exif_table_numEntries++;
1185}
1186
1187static void parseLatLong(const char *latlonString, int *pDegrees,
1188 int *pMinutes, int *pSeconds ) {
1189
1190 double value = atof(latlonString);
1191 value = fabs(value);
1192 int degrees = (int) value;
1193
1194 double remainder = value - degrees;
1195 int minutes = (int) (remainder * 60);
1196 int seconds = (int) (((remainder * 60) - minutes) * 60 * 1000);
1197
1198 *pDegrees = degrees;
1199 *pMinutes = minutes;
1200 *pSeconds = seconds;
1201}
1202
1203static void setLatLon(exif_tag_id_t tag, const char *latlonString) {
1204
1205 int degrees, minutes, seconds;
1206
1207 parseLatLong(latlonString, &degrees, &minutes, &seconds);
1208
1209 rat_t value[3] = { {degrees, 1},
1210 {minutes, 1},
1211 {seconds, 1000} };
1212
1213 if(tag == EXIFTAGID_GPS_LATITUDE) {
1214 memcpy(latitude, value, sizeof(latitude));
1215 addExifTag(EXIFTAGID_GPS_LATITUDE, EXIF_RATIONAL, 3,
1216 1, (void *)latitude);
1217 } else {
1218 memcpy(longitude, value, sizeof(longitude));
1219 addExifTag(EXIFTAGID_GPS_LONGITUDE, EXIF_RATIONAL, 3,
1220 1, (void *)longitude);
1221 }
1222}
1223
1224void QualcommCameraHardware::setGpsParameters() {
1225 const char *str = NULL;
1226
1227 //Set Latitude
1228 str = mParameters.get(CameraParameters::KEY_GPS_LATITUDE);
1229 if(str != NULL) {
1230 setLatLon(EXIFTAGID_GPS_LATITUDE, str);
1231 //set Latitude Ref
1232 str = NULL;
1233 str = mParameters.get(CameraParameters::KEY_GPS_LATITUDE_REF);
1234 if(str != NULL) {
1235 strncpy(latref, str, 1);
1236 latref[1] = '\0';
1237 addExifTag(EXIFTAGID_GPS_LATITUDE_REF, EXIF_ASCII, 2,
1238 1, (void *)latref);
1239 }
1240 }
1241
1242 //set Longitude
1243 str = NULL;
1244 str = mParameters.get(CameraParameters::KEY_GPS_LONGITUDE);
1245 if(str != NULL) {
1246 setLatLon(EXIFTAGID_GPS_LONGITUDE, str);
1247 //set Longitude Ref
1248 str = NULL;
1249 str = mParameters.get(CameraParameters::KEY_GPS_LONGITUDE_REF);
1250 if(str != NULL) {
1251 strncpy(lonref, str, 1);
1252 lonref[1] = '\0';
1253 addExifTag(EXIFTAGID_GPS_LONGITUDE_REF, EXIF_ASCII, 2,
1254 1, (void *)lonref);
1255 }
1256 }
1257
1258 //set Altitude
1259 str = NULL;
1260 str = mParameters.get(CameraParameters::KEY_GPS_ALTITUDE);
1261 if(str != NULL) {
1262 int value = atoi(str);
1263 rat_t alt_value = {value, 1000};
1264 memcpy(&altitude, &alt_value, sizeof(altitude));
1265 addExifTag(EXIFTAGID_GPS_ALTITUDE, EXIF_RATIONAL, 1,
1266 1, (void *)&altitude);
1267 //set AltitudeRef
1268 int ref = mParameters.getInt(CameraParameters::KEY_GPS_ALTITUDE_REF);
1269 if( !(ref < 0 || ref > 1) )
1270 addExifTag(EXIFTAGID_GPS_ALTITUDE_REF, EXIF_BYTE, 1,
1271 1, (void *)&ref);
1272 }
1273
1274
1275}
1276
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001277bool QualcommCameraHardware::native_jpeg_encode(void)
1278{
1279 int jpeg_quality = mParameters.getInt("jpeg-quality");
1280 if (jpeg_quality >= 0) {
1281 LOGV("native_jpeg_encode, current jpeg main img quality =%d",
1282 jpeg_quality);
1283 if(!LINK_jpeg_encoder_setMainImageQuality(jpeg_quality)) {
1284 LOGE("native_jpeg_encode set jpeg-quality failed");
1285 return false;
1286 }
1287 }
1288
1289 int thumbnail_quality = mParameters.getInt("jpeg-thumbnail-quality");
1290 if (thumbnail_quality >= 0) {
1291 LOGV("native_jpeg_encode, current jpeg thumbnail quality =%d",
1292 thumbnail_quality);
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001293/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001294 if(!LINK_jpeg_encoder_setThumbnailQuality(thumbnail_quality)) {
1295 LOGE("native_jpeg_encode set thumbnail-quality failed");
1296 return false;
1297 }
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001298*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001299 }
1300
1301 int rotation = mParameters.getInt("rotation");
1302 if (rotation >= 0) {
1303 LOGV("native_jpeg_encode, rotation = %d", rotation);
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001304/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001305 if(!LINK_jpeg_encoder_setRotation(rotation)) {
1306 LOGE("native_jpeg_encode set rotation failed");
1307 return false;
1308 }
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001309*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001310 }
1311
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001312// jpeg_set_location();
1313 if(mParameters.getInt(CameraParameters::KEY_GPS_STATUS) == 1) {
1314 setGpsParameters();
1315 }
1316 //set TimeStamp
1317 const char *str = mParameters.get(CameraParameters::KEY_EXIF_DATETIME);
1318 if(str != NULL) {
1319 strncpy(dateTime, str, 19);
1320 dateTime[19] = '\0';
1321 addExifTag(EXIFTAGID_EXIF_DATE_TIME_ORIGINAL, EXIF_ASCII,
1322 20, 1, (void *)dateTime);
1323 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001324
1325 if (!LINK_jpeg_encoder_encode(&mDimension,
1326 (uint8_t *)mThumbnailHeap->mHeap->base(),
1327 mThumbnailHeap->mHeap->getHeapID(),
1328 (uint8_t *)mRawHeap->mHeap->base(),
1329 mRawHeap->mHeap->getHeapID(),
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001330 &mCrop, exif_data, exif_table_numEntries)) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001331 LOGE("native_jpeg_encode: jpeg_encoder_encode failed.");
1332 return false;
1333 }
1334 return true;
1335}
1336
1337bool QualcommCameraHardware::native_set_parm(
1338 cam_ctrl_type type, uint16_t length, void *value)
1339{
1340 struct msm_ctrl_cmd ctrlCmd;
1341
1342 ctrlCmd.timeout_ms = 5000;
1343 ctrlCmd.type = (uint16_t)type;
1344 ctrlCmd.length = length;
1345 // FIXME: this will be put in by the kernel
1346 ctrlCmd.resp_fd = mCameraControlFd;
1347 ctrlCmd.value = value;
1348
1349 LOGV("%s: fd %d, type %d, length %d", __FUNCTION__,
1350 mCameraControlFd, type, length);
1351 if (ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0 ||
1352 ctrlCmd.status != CAM_CTRL_SUCCESS) {
1353 LOGE("%s: error (%s): fd %d, type %d, length %d, status %d",
1354 __FUNCTION__, strerror(errno),
1355 mCameraControlFd, type, length, ctrlCmd.status);
1356 return false;
1357 }
1358 return true;
1359}
1360
1361void QualcommCameraHardware::jpeg_set_location()
1362{
1363 bool encode_location = true;
1364 camera_position_type pt;
1365
1366#define PARSE_LOCATION(what,type,fmt,desc) do { \
1367 pt.what = 0; \
1368 const char *what##_str = mParameters.get("gps-"#what); \
1369 LOGV("GPS PARM %s --> [%s]", "gps-"#what, what##_str); \
1370 if (what##_str) { \
1371 type what = 0; \
1372 if (sscanf(what##_str, fmt, &what) == 1) \
1373 pt.what = what; \
1374 else { \
1375 LOGE("GPS " #what " %s could not" \
1376 " be parsed as a " #desc, what##_str); \
1377 encode_location = false; \
1378 } \
1379 } \
1380 else { \
1381 LOGV("GPS " #what " not specified: " \
1382 "defaulting to zero in EXIF header."); \
1383 encode_location = false; \
1384 } \
1385 } while(0)
1386
1387 PARSE_LOCATION(timestamp, long, "%ld", "long");
1388 if (!pt.timestamp) pt.timestamp = time(NULL);
1389 PARSE_LOCATION(altitude, short, "%hd", "short");
1390 PARSE_LOCATION(latitude, double, "%lf", "double float");
1391 PARSE_LOCATION(longitude, double, "%lf", "double float");
1392
1393#undef PARSE_LOCATION
1394
1395 if (encode_location) {
1396 LOGD("setting image location ALT %d LAT %lf LON %lf",
1397 pt.altitude, pt.latitude, pt.longitude);
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001398/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001399 if (!LINK_jpeg_encoder_setLocation(&pt)) {
1400 LOGE("jpeg_set_location: LINK_jpeg_encoder_setLocation failed.");
1401 }
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001402*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001403 }
1404 else LOGV("not setting image location");
1405}
1406
1407void QualcommCameraHardware::runFrameThread(void *data)
1408{
1409 LOGV("runFrameThread E");
1410
1411 int cnt;
1412
1413#if DLOPEN_LIBMMCAMERA
1414 // We need to maintain a reference to libqcamera.so for the duration of the
1415 // frame thread, because we do not know when it will exit relative to the
1416 // lifetime of this object. We do not want to dlclose() libqcamera while
1417 // LINK_cam_frame is still running.
1418 void *libhandle = ::dlopen("liboemcamera.so", RTLD_NOW);
1419 LOGV("FRAME: loading libqcamera at %p", libhandle);
1420 if (!libhandle) {
1421 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
1422 }
1423 if (libhandle)
1424#endif
1425 {
1426 LINK_cam_frame(data);
1427 }
1428
1429 mPreviewHeap.clear();
1430
1431#if DLOPEN_LIBMMCAMERA
1432 if (libhandle) {
1433 ::dlclose(libhandle);
1434 LOGV("FRAME: dlclose(libqcamera)");
1435 }
1436#endif
1437
1438 mFrameThreadWaitLock.lock();
1439 mFrameThreadRunning = false;
1440 mFrameThreadWait.signal();
1441 mFrameThreadWaitLock.unlock();
1442
1443 LOGV("runFrameThread X");
1444}
1445
1446void *frame_thread(void *user)
1447{
1448 LOGD("frame_thread E");
1449 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
1450 if (obj != 0) {
1451 obj->runFrameThread(user);
1452 }
1453 else LOGW("not starting frame thread: the object went away!");
1454 LOGD("frame_thread X");
1455 return NULL;
1456}
1457
1458bool QualcommCameraHardware::initPreview()
1459{
1460 // See comments in deinitPreview() for why we have to wait for the frame
1461 // thread here, and why we can't use pthread_join().
1462 int previewWidth, previewHeight;
1463 mParameters.getPreviewSize(&previewWidth, &previewHeight);
1464 LOGI("initPreview E: preview size=%dx%d", previewWidth, previewHeight);
1465 mFrameThreadWaitLock.lock();
1466 while (mFrameThreadRunning) {
1467 LOGV("initPreview: waiting for old frame thread to complete.");
1468 mFrameThreadWait.wait(mFrameThreadWaitLock);
1469 LOGV("initPreview: old frame thread completed.");
1470 }
1471 mFrameThreadWaitLock.unlock();
1472
1473 mSnapshotThreadWaitLock.lock();
1474 while (mSnapshotThreadRunning) {
1475 LOGV("initPreview: waiting for old snapshot thread to complete.");
1476 mSnapshotThreadWait.wait(mSnapshotThreadWaitLock);
1477 LOGV("initPreview: old snapshot thread completed.");
1478 }
1479 mSnapshotThreadWaitLock.unlock();
1480
1481 int cnt = 0;
1482 mPreviewFrameSize = previewWidth * previewHeight * 3/2;
1483 mPreviewHeap = new PmemPool("/dev/pmem_adsp",
1484 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
1485 mCameraControlFd,
1486 MSM_PMEM_OUTPUT2,
1487 mPreviewFrameSize,
1488 kPreviewBufferCount,
1489 mPreviewFrameSize,
1490 "preview");
1491
1492 if (!mPreviewHeap->initialized()) {
1493 mPreviewHeap.clear();
1494 LOGE("initPreview X: could not initialize preview heap.");
1495 return false;
1496 }
1497
1498 // mDimension will be filled with thumbnail_width, thumbnail_height,
1499 // orig_picture_dx, and orig_picture_dy after this function call. We need to
1500 // keep it for jpeg_encoder_encode.
1501 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
1502 sizeof(cam_ctrl_dimension_t), &mDimension);
1503
1504 if (ret) {
1505 for (cnt = 0; cnt < kPreviewBufferCount; cnt++) {
1506 frames[cnt].fd = mPreviewHeap->mHeap->getHeapID();
1507 frames[cnt].buffer =
1508 (uint32_t)mPreviewHeap->mHeap->base() + mPreviewHeap->mAlignedBufferSize * cnt;
1509 frames[cnt].y_off = 0;
1510 frames[cnt].cbcr_off = previewWidth * previewHeight;
1511 frames[cnt].path = MSM_FRAME_ENC;
1512 }
1513
1514 mFrameThreadWaitLock.lock();
1515 pthread_attr_t attr;
1516 pthread_attr_init(&attr);
1517 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1518 mFrameThreadRunning = !pthread_create(&mFrameThread,
1519 &attr,
1520 frame_thread,
1521 &frames[kPreviewBufferCount-1]);
1522 ret = mFrameThreadRunning;
1523 mFrameThreadWaitLock.unlock();
1524 }
1525
1526 LOGV("initPreview X: %d", ret);
1527 return ret;
1528}
1529
1530void QualcommCameraHardware::deinitPreview(void)
1531{
1532 LOGI("deinitPreview E");
1533
1534 // When we call deinitPreview(), we signal to the frame thread that it
1535 // needs to exit, but we DO NOT WAIT for it to complete here. The problem
1536 // is that deinitPreview is sometimes called from the frame-thread's
1537 // callback, when the refcount on the Camera client reaches zero. If we
1538 // called pthread_join(), we would deadlock. So, we just call
1539 // LINK_camframe_terminate() in deinitPreview(), which makes sure that
1540 // after the preview callback returns, the camframe thread will exit. We
1541 // could call pthread_join() in initPreview() to join the last frame
1542 // thread. However, we would also have to call pthread_join() in release
1543 // as well, shortly before we destroy the object; this would cause the same
1544 // deadlock, since release(), like deinitPreview(), may also be called from
1545 // the frame-thread's callback. This we have to make the frame thread
1546 // detached, and use a separate mechanism to wait for it to complete.
1547
1548 if (LINK_camframe_terminate() < 0)
1549 LOGE("failed to stop the camframe thread: %s",
1550 strerror(errno));
1551 LOGI("deinitPreview X");
1552}
1553
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001554bool QualcommCameraHardware::initRawSnapshot()
1555{
1556 LOGV("initRawSnapshot E");
1557
1558 //get width and height from Dimension Object
1559 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
1560 sizeof(cam_ctrl_dimension_t), &mDimension);
1561
1562 if(!ret){
1563 LOGE("initRawSnapshot X: failed to set dimension");
1564 return false;
1565 }
1566 int rawSnapshotSize = mDimension.raw_picture_height *
1567 mDimension.raw_picture_width;
1568
1569 LOGV("raw_snapshot_buffer_size = %d, raw_picture_height = %d, "\
1570 "raw_picture_width = %d",
1571 rawSnapshotSize, mDimension.raw_picture_height,
1572 mDimension.raw_picture_width);
1573
1574 if (mRawSnapShotPmemHeap != NULL) {
1575 LOGV("initRawSnapshot: clearing old mRawSnapShotPmemHeap.");
1576 mRawSnapShotPmemHeap.clear();
1577 }
1578
1579 //Pmem based pool for Camera Driver
1580 mRawSnapShotPmemHeap = new PmemPool("/dev/pmem_adsp",
1581 MemoryHeapBase::READ_ONLY,
1582 mCameraControlFd,
1583 MSM_PMEM_RAW_MAINIMG,
1584 rawSnapshotSize,
1585 1,
1586 rawSnapshotSize,
1587 "raw pmem snapshot camera");
1588
1589 if (!mRawSnapShotPmemHeap->initialized()) {
1590 mRawSnapShotPmemHeap.clear();
1591 LOGE("initRawSnapshot X: error initializing mRawSnapshotHeap");
1592 return false;
1593 }
1594 LOGV("initRawSnapshot X");
1595 return true;
1596
1597}
1598
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001599bool QualcommCameraHardware::initRaw(bool initJpegHeap)
1600{
1601 int rawWidth, rawHeight;
Apurva Rajguru8d1773b2009-12-02 14:21:23 -08001602 char value[PROPERTY_VALUE_MAX];
1603
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001604 mParameters.getPictureSize(&rawWidth, &rawHeight);
1605 LOGV("initRaw E: picture size=%dx%d", rawWidth, rawHeight);
1606
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08001607 int thumbnailBufferSize;
1608 //Thumbnail height should be smaller than Picture height
1609 if (rawHeight > thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height){
1610 mDimension.ui_thumbnail_width =
1611 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].width;
1612 mDimension.ui_thumbnail_height =
1613 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height;
1614 uint32_t pictureAspectRatio = (uint32_t)((rawWidth * Q12) / rawHeight);
1615 uint32_t i;
1616 for(i = 0; i < THUMBNAIL_SIZE_COUNT; i++ )
1617 {
1618 if(thumbnail_sizes[i].aspect_ratio == pictureAspectRatio)
1619 {
1620 mDimension.ui_thumbnail_width = thumbnail_sizes[i].width;
1621 mDimension.ui_thumbnail_height = thumbnail_sizes[i].height;
1622 break;
1623 }
1624 }
1625 }
1626 else{
1627 mDimension.ui_thumbnail_height = THUMBNAIL_SMALL_HEIGHT;
1628 mDimension.ui_thumbnail_width =
1629 (THUMBNAIL_SMALL_HEIGHT * rawWidth)/ rawHeight;
1630 }
1631
1632 LOGV("Thumbnail Size Width %d Height %d",
1633 mDimension.ui_thumbnail_width,
1634 mDimension.ui_thumbnail_height);
1635
1636 thumbnailBufferSize = mDimension.ui_thumbnail_width *
1637 mDimension.ui_thumbnail_height * 3 / 2;
1638
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001639 // mDimension will be filled with thumbnail_width, thumbnail_height,
1640 // orig_picture_dx, and orig_picture_dy after this function call. We need to
1641 // keep it for jpeg_encoder_encode.
1642 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
1643 sizeof(cam_ctrl_dimension_t), &mDimension);
1644 if(!ret) {
1645 LOGE("initRaw X: failed to set dimension");
1646 return false;
1647 }
1648
1649 if (mJpegHeap != NULL) {
1650 LOGV("initRaw: clearing old mJpegHeap.");
1651 mJpegHeap.clear();
1652 }
1653
1654 // Snapshot
1655 mRawSize = rawWidth * rawHeight * 3 / 2;
Apurva Rajguru8d1773b2009-12-02 14:21:23 -08001656 property_get("ro.product.device",value," ");
1657
1658 if(!strcmp(value,"msm7627_surf"))
1659 mJpegMaxSize = CEILING16(rawWidth) * CEILING16(rawHeight) * 3 / 2;
1660 else
1661 mJpegMaxSize = rawWidth * rawHeight * 3 / 2;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001662
1663 LOGV("initRaw: initializing mRawHeap.");
1664 mRawHeap =
1665 new PmemPool("/dev/pmem_camera",
1666 MemoryHeapBase::READ_ONLY,
1667 mCameraControlFd,
1668 MSM_PMEM_MAINIMG,
1669 mJpegMaxSize,
1670 kRawBufferCount,
1671 mRawSize,
1672 "snapshot camera");
1673
1674 if (!mRawHeap->initialized()) {
1675 LOGE("initRaw X failed with pmem_camera, trying with pmem_adsp");
1676 mRawHeap =
1677 new PmemPool("/dev/pmem_adsp",
1678 MemoryHeapBase::READ_ONLY,
1679 mCameraControlFd,
1680 MSM_PMEM_MAINIMG,
1681 mJpegMaxSize,
1682 kRawBufferCount,
1683 mRawSize,
1684 "snapshot camera");
1685 if (!mRawHeap->initialized()) {
1686 mRawHeap.clear();
1687 LOGE("initRaw X: error initializing mRawHeap");
1688 return false;
1689 }
1690 }
1691
1692 LOGV("do_mmap snapshot pbuf = %p, pmem_fd = %d",
1693 (uint8_t *)mRawHeap->mHeap->base(), mRawHeap->mHeap->getHeapID());
1694
1695 // Jpeg
1696
1697 if (initJpegHeap) {
1698 LOGV("initRaw: initializing mJpegHeap.");
1699 mJpegHeap =
1700 new AshmemPool(mJpegMaxSize,
1701 kJpegBufferCount,
1702 0, // we do not know how big the picture will be
1703 "jpeg");
1704
1705 if (!mJpegHeap->initialized()) {
1706 mJpegHeap.clear();
1707 mRawHeap.clear();
1708 LOGE("initRaw X failed: error initializing mJpegHeap.");
1709 return false;
1710 }
1711
1712 // Thumbnails
1713
1714 mThumbnailHeap =
1715 new PmemPool("/dev/pmem_adsp",
1716 MemoryHeapBase::READ_ONLY,
1717 mCameraControlFd,
1718 MSM_PMEM_THUMBNAIL,
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08001719 thumbnailBufferSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001720 1,
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08001721 thumbnailBufferSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001722 "thumbnail");
1723
1724 if (!mThumbnailHeap->initialized()) {
1725 mThumbnailHeap.clear();
1726 mJpegHeap.clear();
1727 mRawHeap.clear();
1728 LOGE("initRaw X failed: error initializing mThumbnailHeap.");
1729 return false;
1730 }
1731 }
1732
1733 LOGV("initRaw X");
1734 return true;
1735}
1736
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001737
1738void QualcommCameraHardware::deinitRawSnapshot()
1739{
1740 LOGV("deinitRawSnapshot E");
1741 mRawSnapShotPmemHeap.clear();
1742 mRawSnapshotAshmemHeap.clear();
1743 LOGV("deinitRawSnapshot X");
1744}
1745
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001746void QualcommCameraHardware::deinitRaw()
1747{
1748 LOGV("deinitRaw E");
1749
1750 mThumbnailHeap.clear();
1751 mJpegHeap.clear();
1752 mRawHeap.clear();
1753 mDisplayHeap.clear();
1754
1755 LOGV("deinitRaw X");
1756}
1757
1758void QualcommCameraHardware::release()
1759{
1760 LOGD("release E");
1761 Mutex::Autolock l(&mLock);
1762
1763#if DLOPEN_LIBMMCAMERA
1764 if (libmmcamera == NULL) {
1765 LOGE("ERROR: multiple release!");
1766 return;
1767 }
1768#else
1769#warning "Cannot detect multiple release when not dlopen()ing libqcamera!"
1770#endif
1771
1772 int cnt, rc;
1773 struct msm_ctrl_cmd ctrlCmd;
1774
1775 if (mCameraRunning) {
1776 if(mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME)) {
1777 mRecordFrameLock.lock();
1778 mReleasedRecordingFrame = true;
1779 mRecordWait.signal();
1780 mRecordFrameLock.unlock();
1781 }
1782 stopPreviewInternal();
1783 }
1784
1785 LINK_jpeg_encoder_join();
1786 deinitRaw();
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001787 deinitRawSnapshot();
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001788 {
1789 Mutex::Autolock l(&mCamframeTimeoutLock);
1790 if(!camframe_timeout_flag) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001791
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001792 ctrlCmd.timeout_ms = 5000;
1793 ctrlCmd.length = 0;
1794 ctrlCmd.type = (uint16_t)CAMERA_EXIT;
1795 ctrlCmd.resp_fd = mCameraControlFd; // FIXME: this will be put in by the kernel
1796 if (ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0)
1797 LOGE("ioctl CAMERA_EXIT fd %d error %s",
1798 mCameraControlFd, strerror(errno));
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001799
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001800 LINK_release_cam_conf_thread();
1801 }
1802 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001803 close(mCameraControlFd);
1804 mCameraControlFd = -1;
1805
1806#if DLOPEN_LIBMMCAMERA
1807 if (libmmcamera) {
1808 ::dlclose(libmmcamera);
1809 LOGV("dlclose(libqcamera)");
1810 libmmcamera = NULL;
1811 }
1812#endif
1813
1814 Mutex::Autolock lock(&singleton_lock);
1815 singleton_releasing = true;
1816
1817 LOGD("release X");
1818}
1819
1820QualcommCameraHardware::~QualcommCameraHardware()
1821{
1822 LOGD("~QualcommCameraHardware E");
1823 Mutex::Autolock lock(&singleton_lock);
1824 singleton.clear();
1825 singleton_releasing = false;
1826 singleton_wait.signal();
1827 LOGD("~QualcommCameraHardware X");
1828}
1829
1830sp<IMemoryHeap> QualcommCameraHardware::getRawHeap() const
1831{
1832 LOGV("getRawHeap");
1833 return mDisplayHeap != NULL ? mDisplayHeap->mHeap : NULL;
1834}
1835
1836sp<IMemoryHeap> QualcommCameraHardware::getPreviewHeap() const
1837{
1838 LOGV("getPreviewHeap");
1839 return mPreviewHeap != NULL ? mPreviewHeap->mHeap : NULL;
1840}
1841
1842status_t QualcommCameraHardware::startPreviewInternal()
1843{
1844 if(mCameraRunning) {
1845 LOGV("startPreview X: preview already running.");
1846 return NO_ERROR;
1847 }
1848
1849 if (!mPreviewInitialized) {
1850 mPreviewInitialized = initPreview();
1851 if (!mPreviewInitialized) {
1852 LOGE("startPreview X initPreview failed. Not starting preview.");
1853 return UNKNOWN_ERROR;
1854 }
1855 }
1856
1857 mCameraRunning = native_start_preview(mCameraControlFd);
1858 if(!mCameraRunning) {
1859 deinitPreview();
1860 mPreviewInitialized = false;
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08001861 mOverlay = NULL;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001862 LOGE("startPreview X: native_start_preview failed!");
1863 return UNKNOWN_ERROR;
1864 }
1865
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001866 //Reset the Gps Information
1867 exif_table_numEntries = 0;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001868 LOGV("startPreview X");
1869 return NO_ERROR;
1870}
1871
1872status_t QualcommCameraHardware::startPreview()
1873{
1874 LOGV("startPreview E");
1875 Mutex::Autolock l(&mLock);
1876 return startPreviewInternal();
1877}
1878
1879void QualcommCameraHardware::stopPreviewInternal()
1880{
1881 LOGV("stopPreviewInternal E: %d", mCameraRunning);
1882 if (mCameraRunning) {
1883 // Cancel auto focus.
1884 {
1885 if (mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS)) {
1886 cancelAutoFocusInternal();
1887 }
1888 }
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001889 Mutex::Autolock l(&mCamframeTimeoutLock);
1890 if(!camframe_timeout_flag) {
1891 mCameraRunning = !native_stop_preview(mCameraControlFd);
1892 if (!mCameraRunning && mPreviewInitialized) {
1893 deinitPreview();
1894 mPreviewInitialized = false;
1895 }
1896 else LOGE("stopPreviewInternal: failed to stop preview");
1897 } else {
1898 /* This means that the camframetimeout was issued.
1899 * But we did not issue native_stop_preview(), so we
1900 * need to update mCameraRunning & mPreviewInitialized
1901 * to indicate that Camera is no longer running.
1902 */
1903 mCameraRunning = 0;
1904 mPreviewInitialized = false;
1905 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001906 }
1907 LOGV("stopPreviewInternal X: %d", mCameraRunning);
1908}
1909
1910void QualcommCameraHardware::stopPreview()
1911{
1912 LOGV("stopPreview: E");
1913 Mutex::Autolock l(&mLock);
1914 {
1915 if (mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME))
1916 return;
1917 }
1918 stopPreviewInternal();
1919 LOGV("stopPreview: X");
1920}
1921
1922void QualcommCameraHardware::runAutoFocus()
1923{
1924 bool status = true;
1925 void *libhandle = NULL;
Srinivasan Kannan71229622009-12-04 12:05:58 -08001926 isp3a_af_mode_t afMode;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001927
1928 mAutoFocusThreadLock.lock();
1929 // Skip autofocus if focus mode is infinity.
1930 if (strcmp(mParameters.get(CameraParameters::KEY_FOCUS_MODE),
1931 CameraParameters::FOCUS_MODE_INFINITY) == 0) {
1932 goto done;
1933 }
1934
1935 mAutoFocusFd = open(MSM_CAMERA_CONTROL, O_RDWR);
1936 if (mAutoFocusFd < 0) {
1937 LOGE("autofocus: cannot open %s: %s",
1938 MSM_CAMERA_CONTROL,
1939 strerror(errno));
1940 mAutoFocusThreadRunning = false;
1941 mAutoFocusThreadLock.unlock();
1942 return;
1943 }
1944
1945#if DLOPEN_LIBMMCAMERA
1946 // We need to maintain a reference to libqcamera.so for the duration of the
1947 // AF thread, because we do not know when it will exit relative to the
1948 // lifetime of this object. We do not want to dlclose() libqcamera while
1949 // LINK_cam_frame is still running.
1950 libhandle = ::dlopen("liboemcamera.so", RTLD_NOW);
1951 LOGV("AF: loading libqcamera at %p", libhandle);
1952 if (!libhandle) {
1953 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
1954 close(mAutoFocusFd);
1955 mAutoFocusFd = -1;
1956 mAutoFocusThreadRunning = false;
1957 mAutoFocusThreadLock.unlock();
1958 return;
1959 }
1960#endif
1961
Srinivasan Kannan71229622009-12-04 12:05:58 -08001962 afMode = (isp3a_af_mode_t)attr_lookup(focus_modes,
1963 sizeof(focus_modes) / sizeof(str_map),
1964 mParameters.get(CameraParameters::KEY_FOCUS_MODE));
1965
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001966 /* This will block until either AF completes or is cancelled. */
Srinivasan Kannan71229622009-12-04 12:05:58 -08001967 LOGV("af start (fd %d mode %d)", mAutoFocusFd, afMode);
1968 status = native_set_afmode(mAutoFocusFd, afMode);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001969 LOGV("af done: %d", (int)status);
1970 close(mAutoFocusFd);
1971 mAutoFocusFd = -1;
1972
1973done:
1974 mAutoFocusThreadRunning = false;
1975 mAutoFocusThreadLock.unlock();
1976
1977 mCallbackLock.lock();
1978 bool autoFocusEnabled = mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS);
1979 notify_callback cb = mNotifyCallback;
1980 void *data = mCallbackCookie;
1981 mCallbackLock.unlock();
1982 if (autoFocusEnabled)
1983 cb(CAMERA_MSG_FOCUS, status, 0, data);
1984
1985#if DLOPEN_LIBMMCAMERA
1986 if (libhandle) {
1987 ::dlclose(libhandle);
1988 LOGV("AF: dlclose(libqcamera)");
1989 }
1990#endif
1991}
1992
1993status_t QualcommCameraHardware::cancelAutoFocusInternal()
1994{
1995 LOGV("cancelAutoFocusInternal E");
1996
Srinivasan Kannan71229622009-12-04 12:05:58 -08001997 if(!sensorType->hasAutoFocusSupport){
1998 LOGV("cancelAutoFocusInternal X");
1999 return NO_ERROR;
2000 }
2001
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002002#if 0
2003 if (mAutoFocusFd < 0) {
2004 LOGV("cancelAutoFocusInternal X: not in progress");
2005 return NO_ERROR;
2006 }
2007#endif
2008
2009 status_t rc = native_cancel_afmode(mCameraControlFd, mAutoFocusFd) ?
2010 NO_ERROR :
2011 UNKNOWN_ERROR;
2012
2013 LOGV("cancelAutoFocusInternal X: %d", rc);
2014 return rc;
2015}
2016
2017void *auto_focus_thread(void *user)
2018{
2019 LOGV("auto_focus_thread E");
2020 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
2021 if (obj != 0) {
2022 obj->runAutoFocus();
2023 }
2024 else LOGW("not starting autofocus: the object went away!");
2025 LOGV("auto_focus_thread X");
2026 return NULL;
2027}
2028
2029status_t QualcommCameraHardware::autoFocus()
2030{
2031 LOGV("autoFocus E");
2032 Mutex::Autolock l(&mLock);
2033
Srinivasan Kannan71229622009-12-04 12:05:58 -08002034 if(!sensorType->hasAutoFocusSupport){
Srinivasan Kannandf085222009-12-09 18:31:00 -08002035 bool status = false;
2036 mCallbackLock.lock();
2037 bool autoFocusEnabled = mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS);
2038 notify_callback cb = mNotifyCallback;
2039 void *data = mCallbackCookie;
2040 mCallbackLock.unlock();
2041 if (autoFocusEnabled)
2042 cb(CAMERA_MSG_FOCUS, status, 0, data);
Srinivasan Kannan71229622009-12-04 12:05:58 -08002043 LOGV("autoFocus X");
2044 return NO_ERROR;
2045 }
2046
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002047 if (mCameraControlFd < 0) {
2048 LOGE("not starting autofocus: main control fd %d", mCameraControlFd);
2049 return UNKNOWN_ERROR;
2050 }
2051
2052 {
2053 mAutoFocusThreadLock.lock();
2054 if (!mAutoFocusThreadRunning) {
2055 // Create a detached thread here so that we don't have to wait
2056 // for it when we cancel AF.
2057 pthread_t thr;
2058 pthread_attr_t attr;
2059 pthread_attr_init(&attr);
2060 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2061 mAutoFocusThreadRunning =
2062 !pthread_create(&thr, &attr,
2063 auto_focus_thread, NULL);
2064 if (!mAutoFocusThreadRunning) {
2065 LOGE("failed to start autofocus thread");
2066 mAutoFocusThreadLock.unlock();
2067 return UNKNOWN_ERROR;
2068 }
2069 }
2070 mAutoFocusThreadLock.unlock();
2071 }
2072
2073 LOGV("autoFocus X");
2074 return NO_ERROR;
2075}
2076
2077status_t QualcommCameraHardware::cancelAutoFocus()
2078{
2079 LOGV("cancelAutoFocus E");
2080 Mutex::Autolock l(&mLock);
2081
2082 int rc = NO_ERROR;
2083 if (mCameraRunning && mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS)) {
2084 rc = cancelAutoFocusInternal();
2085 }
2086
2087 LOGV("cancelAutoFocus X");
2088 return rc;
2089}
2090
2091void QualcommCameraHardware::runSnapshotThread(void *data)
2092{
2093 LOGV("runSnapshotThread E");
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002094 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
2095 if (native_start_snapshot(mCameraControlFd))
2096 receiveRawPicture();
2097 else
2098 LOGE("main: native_start_snapshot failed!");
2099 } else if(mSnapshotFormat == PICTURE_FORMAT_RAW){
2100 if(native_start_raw_snapshot(mCameraControlFd)){
2101 receiveRawSnapshot();
2102 } else {
2103 LOGE("main: native_start_raw_snapshot failed!");
2104 }
2105 }
2106
2107 mSnapshotFormat = 0;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002108
2109 mSnapshotThreadWaitLock.lock();
2110 mSnapshotThreadRunning = false;
2111 mSnapshotThreadWait.signal();
2112 mSnapshotThreadWaitLock.unlock();
2113
2114 LOGV("runSnapshotThread X");
2115}
2116
2117void *snapshot_thread(void *user)
2118{
2119 LOGD("snapshot_thread E");
2120 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
2121 if (obj != 0) {
2122 obj->runSnapshotThread(user);
2123 }
2124 else LOGW("not starting snapshot thread: the object went away!");
2125 LOGD("snapshot_thread X");
2126 return NULL;
2127}
2128
2129status_t QualcommCameraHardware::takePicture()
2130{
2131 LOGV("takePicture(%d)", mMsgEnabled);
2132 Mutex::Autolock l(&mLock);
2133
2134 // Wait for old snapshot thread to complete.
2135 mSnapshotThreadWaitLock.lock();
2136 while (mSnapshotThreadRunning) {
2137 LOGV("takePicture: waiting for old snapshot thread to complete.");
2138 mSnapshotThreadWait.wait(mSnapshotThreadWaitLock);
2139 LOGV("takePicture: old snapshot thread completed.");
2140 }
2141
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002142 //mSnapshotFormat is protected by mSnapshotThreadWaitLock
2143 if(mParameters.getPictureFormat() != 0 &&
2144 !strcmp(mParameters.getPictureFormat(),
2145 CameraParameters::PIXEL_FORMAT_RAW))
2146 mSnapshotFormat = PICTURE_FORMAT_RAW;
2147 else
2148 mSnapshotFormat = PICTURE_FORMAT_JPEG;
2149
2150 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
2151 if(!native_prepare_snapshot(mCameraControlFd)) {
2152 mSnapshotThreadWaitLock.unlock();
2153 return UNKNOWN_ERROR;
2154 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002155 }
2156
2157 stopPreviewInternal();
2158
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002159 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
2160 if (!initRaw(mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE))) {
2161 LOGE("initRaw failed. Not taking picture.");
2162 mSnapshotThreadWaitLock.unlock();
2163 return UNKNOWN_ERROR;
2164 }
2165 } else if(mSnapshotFormat == PICTURE_FORMAT_RAW ){
2166 if(!initRawSnapshot()){
2167 LOGE("initRawSnapshot failed. Not taking picture.");
2168 mSnapshotThreadWaitLock.unlock();
2169 return UNKNOWN_ERROR;
2170 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002171 }
2172
2173 mShutterLock.lock();
2174 mShutterPending = true;
2175 mShutterLock.unlock();
2176
2177 pthread_attr_t attr;
2178 pthread_attr_init(&attr);
2179 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2180 mSnapshotThreadRunning = !pthread_create(&mSnapshotThread,
2181 &attr,
2182 snapshot_thread,
2183 NULL);
2184 mSnapshotThreadWaitLock.unlock();
2185
2186 LOGV("takePicture: X");
2187 return mSnapshotThreadRunning ? NO_ERROR : UNKNOWN_ERROR;
2188}
2189
2190status_t QualcommCameraHardware::cancelPicture()
2191{
2192 status_t rc;
2193 LOGV("cancelPicture: E");
2194 rc = native_stop_snapshot(mCameraControlFd) ? NO_ERROR : UNKNOWN_ERROR;
2195 LOGV("cancelPicture: X: %d", rc);
2196 return rc;
2197}
2198
2199status_t QualcommCameraHardware::setParameters(const CameraParameters& params)
2200{
2201 LOGV("setParameters: E params = %p", &params);
2202
2203 Mutex::Autolock l(&mLock);
2204 status_t rc, final_rc = NO_ERROR;
2205
2206 if ((rc = setPreviewSize(params))) final_rc = rc;
2207 if ((rc = setPictureSize(params))) final_rc = rc;
2208 if ((rc = setJpegQuality(params))) final_rc = rc;
2209 if ((rc = setAntibanding(params))) final_rc = rc;
2210 if ((rc = setEffect(params))) final_rc = rc;
Apurva Rajguru55562b02009-12-03 12:25:35 -08002211 if ((rc = setAutoExposure(params))) final_rc = rc;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002212 if ((rc = setWhiteBalance(params))) final_rc = rc;
2213 if ((rc = setFlash(params))) final_rc = rc;
2214 if ((rc = setGpsLocation(params))) final_rc = rc;
2215 if ((rc = setRotation(params))) final_rc = rc;
2216 if ((rc = setZoom(params))) final_rc = rc;
2217 if ((rc = setFocusMode(params))) final_rc = rc;
2218 if ((rc = setOrientation(params))) final_rc = rc;
Nishant Panditc8c1ee72009-12-03 16:24:02 +05302219 if ((rc = setBrightness(params))) final_rc = rc;
2220 if ((rc = setLensshadeValue(params))) final_rc = rc;
2221 if ((rc = setISOValue(params))) final_rc = rc;
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002222 if ((rc = setPictureFormat(params))) final_rc = rc;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002223
2224 LOGV("setParameters: X");
2225 return final_rc;
2226}
2227
2228CameraParameters QualcommCameraHardware::getParameters() const
2229{
2230 LOGV("getParameters: EX");
2231 return mParameters;
2232}
2233
2234status_t QualcommCameraHardware::sendCommand(int32_t command, int32_t arg1,
2235 int32_t arg2)
2236{
2237 LOGV("sendCommand: EX");
2238 return BAD_VALUE;
2239}
2240
2241extern "C" sp<CameraHardwareInterface> openCameraHardware()
2242{
2243 LOGV("openCameraHardware: call createInstance");
2244 return QualcommCameraHardware::createInstance();
2245}
2246
2247wp<QualcommCameraHardware> QualcommCameraHardware::singleton;
2248
2249// If the hardware already exists, return a strong pointer to the current
2250// object. If not, create a new hardware object, put it in the singleton,
2251// and return it.
2252sp<CameraHardwareInterface> QualcommCameraHardware::createInstance()
2253{
2254 LOGD("createInstance: E");
2255
2256 Mutex::Autolock lock(&singleton_lock);
2257
2258 // Wait until the previous release is done.
2259 while (singleton_releasing) {
2260 LOGD("Wait for previous release.");
2261 singleton_wait.wait(singleton_lock);
2262 }
2263
2264 if (singleton != 0) {
2265 sp<CameraHardwareInterface> hardware = singleton.promote();
2266 if (hardware != 0) {
2267 LOGD("createInstance: X return existing hardware=%p", &(*hardware));
2268 return hardware;
2269 }
2270 }
2271
2272 {
2273 struct stat st;
2274 int rc = stat("/dev/oncrpc", &st);
2275 if (rc < 0) {
2276 LOGD("createInstance: X failed to create hardware: %s", strerror(errno));
2277 return NULL;
2278 }
2279 }
2280
2281 QualcommCameraHardware *cam = new QualcommCameraHardware();
2282 sp<QualcommCameraHardware> hardware(cam);
2283 singleton = hardware;
2284
2285 if (!cam->startCamera()) {
2286 LOGE("%s: startCamera failed!", __FUNCTION__);
2287 return NULL;
2288 }
2289
2290 cam->initDefaultParameters();
2291 LOGD("createInstance: X created hardware=%p", &(*hardware));
2292 return hardware;
2293}
2294
2295// For internal use only, hence the strong pointer to the derived type.
2296sp<QualcommCameraHardware> QualcommCameraHardware::getInstance()
2297{
2298 sp<CameraHardwareInterface> hardware = singleton.promote();
2299 if (hardware != 0) {
2300 // LOGV("getInstance: X old instance of hardware");
2301 return sp<QualcommCameraHardware>(static_cast<QualcommCameraHardware*>(hardware.get()));
2302 } else {
2303 LOGV("getInstance: X new instance of hardware");
2304 return sp<QualcommCameraHardware>();
2305 }
2306}
2307
2308void QualcommCameraHardware::receivePreviewFrame(struct msm_frame *frame)
2309{
2310// LOGV("receivePreviewFrame E");
2311
2312 if (!mCameraRunning) {
2313 LOGE("ignoring preview callback--camera has been stopped");
2314 return;
2315 }
2316
2317 mCallbackLock.lock();
2318 int msgEnabled = mMsgEnabled;
2319 data_callback pcb = mDataCallback;
2320 void *pdata = mCallbackCookie;
2321 data_callback_timestamp rcb = mDataCallbackTimestamp;
2322 void *rdata = mCallbackCookie;
2323 mCallbackLock.unlock();
2324
2325 // Find the offset within the heap of the current buffer.
2326 ssize_t offset =
2327 (ssize_t)frame->buffer - (ssize_t)mPreviewHeap->mHeap->base();
2328 offset /= mPreviewHeap->mAlignedBufferSize;
2329
2330 mInPreviewCallback = true;
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08002331 if((mUseOverlay == true) && (mOverlay != NULL) ) {
2332 ssize_t offset_addr =
2333 (ssize_t)frame->buffer - (ssize_t)mPreviewHeap->mHeap->base();
2334 mOverlayLock.lock();
2335 mOverlay->setFd(mPreviewHeap->mHeap->getHeapID());
2336 mOverlay->queueBuffer((void *)offset_addr);
2337 mOverlayLock.unlock();
2338 LOGV(" Queueing buffer %x from HAL for display ", offset_addr );
2339 }
2340 /* In case of Overlay, the MSG_PREVIEW_FRAME will be disabled
2341 * second frame onwards. Hence we can keep this piece of code
2342 * in overlay case as well. */
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002343 if (pcb != NULL && (msgEnabled & CAMERA_MSG_PREVIEW_FRAME))
2344 pcb(CAMERA_MSG_PREVIEW_FRAME, mPreviewHeap->mBuffers[offset],
2345 pdata);
2346
2347 if(rcb != NULL && (msgEnabled & CAMERA_MSG_VIDEO_FRAME)) {
2348 rcb(systemTime(), CAMERA_MSG_VIDEO_FRAME, mPreviewHeap->mBuffers[offset], rdata);
2349 Mutex::Autolock rLock(&mRecordFrameLock);
2350 if (mReleasedRecordingFrame != true) {
2351 LOGV("block waiting for frame release");
2352 mRecordWait.wait(mRecordFrameLock);
2353 LOGV("frame released, continuing");
2354 }
2355 mReleasedRecordingFrame = false;
2356 }
2357 mInPreviewCallback = false;
2358
2359// LOGV("receivePreviewFrame X");
2360}
2361
2362status_t QualcommCameraHardware::startRecording()
2363{
2364 LOGV("startRecording E");
2365 Mutex::Autolock l(&mLock);
2366 mReleasedRecordingFrame = false;
2367 return startPreviewInternal();
2368}
2369
2370void QualcommCameraHardware::stopRecording()
2371{
2372 LOGV("stopRecording: E");
2373 Mutex::Autolock l(&mLock);
2374 {
2375 mRecordFrameLock.lock();
2376 mReleasedRecordingFrame = true;
2377 mRecordWait.signal();
2378 mRecordFrameLock.unlock();
2379
2380 if(mDataCallback && (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)) {
2381 LOGV("stopRecording: X, preview still in progress");
2382 return;
2383 }
2384 }
2385
2386 stopPreviewInternal();
2387 LOGV("stopRecording: X");
2388}
2389
2390void QualcommCameraHardware::releaseRecordingFrame(
2391 const sp<IMemory>& mem __attribute__((unused)))
2392{
2393 LOGV("releaseRecordingFrame E");
2394 Mutex::Autolock rLock(&mRecordFrameLock);
2395 mReleasedRecordingFrame = true;
2396 mRecordWait.signal();
2397 LOGV("releaseRecordingFrame X");
2398}
2399
2400bool QualcommCameraHardware::recordingEnabled()
2401{
2402 return mCameraRunning && mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME);
2403}
2404
2405void QualcommCameraHardware::notifyShutter(common_crop_t *crop)
2406{
2407 mShutterLock.lock();
2408 image_rect_type size;
2409
2410 if (mShutterPending && mNotifyCallback && (mMsgEnabled & CAMERA_MSG_SHUTTER)) {
2411 LOGV("out2_w=%d, out2_h=%d, in2_w=%d, in2_h=%d",
2412 crop->out2_w, crop->out2_h, crop->in2_w, crop->in2_h);
2413 LOGV("out1_w=%d, out1_h=%d, in1_w=%d, in1_h=%d",
2414 crop->out1_w, crop->out1_h, crop->in1_w, crop->in1_h);
2415
2416 // To workaround a bug in MDP which happens if either
2417 // dimension > 2048, we display the thumbnail instead.
2418 mDisplayHeap = mRawHeap;
2419 if (crop->in1_w == 0 || crop->in1_h == 0) {
2420 // Full size
2421 size.width = mDimension.picture_width;
2422 size.height = mDimension.picture_height;
2423 if (size.width > 2048 || size.height > 2048) {
2424 size.width = mDimension.ui_thumbnail_width;
2425 size.height = mDimension.ui_thumbnail_height;
2426 mDisplayHeap = mThumbnailHeap;
2427 }
2428 } else {
2429 // Cropped
2430 size.width = crop->in2_w & ~1;
2431 size.height = crop->in2_h & ~1;
2432 if (size.width > 2048 || size.height > 2048) {
2433 size.width = crop->in1_w & ~1;
2434 size.height = crop->in1_h & ~1;
2435 mDisplayHeap = mThumbnailHeap;
2436 }
2437 }
2438
2439 mNotifyCallback(CAMERA_MSG_SHUTTER, (int32_t)&size, 0,
2440 mCallbackCookie);
2441 mShutterPending = false;
2442 }
2443 mShutterLock.unlock();
2444}
2445
2446static void receive_shutter_callback(common_crop_t *crop)
2447{
2448 LOGV("receive_shutter_callback: E");
2449 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
2450 if (obj != 0) {
2451 obj->notifyShutter(crop);
2452 }
2453 LOGV("receive_shutter_callback: X");
2454}
2455
2456// Crop the picture in place.
2457static void crop_yuv420(uint32_t width, uint32_t height,
2458 uint32_t cropped_width, uint32_t cropped_height,
2459 uint8_t *image)
2460{
2461 uint32_t i, x, y;
2462 uint8_t* chroma_src, *chroma_dst;
2463
2464 // Calculate the start position of the cropped area.
2465 x = (width - cropped_width) / 2;
2466 y = (height - cropped_height) / 2;
2467 x &= ~1;
2468 y &= ~1;
2469
2470 // Copy luma component.
2471 for(i = 0; i < cropped_height; i++)
2472 memcpy(image + i * cropped_width,
2473 image + width * (y + i) + x,
2474 cropped_width);
2475
2476 chroma_src = image + width * height;
2477 chroma_dst = image + cropped_width * cropped_height;
2478
2479 // Copy chroma components.
2480 cropped_height /= 2;
2481 y /= 2;
2482 for(i = 0; i < cropped_height; i++)
2483 memcpy(chroma_dst + i * cropped_width,
2484 chroma_src + width * (y + i) + x,
2485 cropped_width);
2486}
2487
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002488
2489void QualcommCameraHardware::receiveRawSnapshot(){
2490 LOGV("receiveRawSnapshot E");
2491
2492 Mutex::Autolock cbLock(&mCallbackLock);
2493
2494 notifyShutter(&mCrop);
2495
2496 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
2497
2498 if(native_get_picture(mCameraControlFd, &mCrop) == false) {
2499 LOGE("receiveRawSnapshot X: native_get_picture failed!");
2500 return;
2501 }
2502
2503 //Create a Ashmem heap to copy data from PMem heap for application layer
2504 if(mRawSnapshotAshmemHeap != NULL){
2505 LOGV("receiveRawSnapshot: clearing old mRawSnapShotAshmemHeap.");
2506 mRawSnapshotAshmemHeap.clear();
2507 }
2508 mRawSnapshotAshmemHeap = new AshmemPool(
2509 mRawSnapShotPmemHeap->mBufferSize,
2510 mRawSnapShotPmemHeap->mNumBuffers,
2511 mRawSnapShotPmemHeap->mFrameSize,
2512 "raw ashmem snapshot camera"
2513 );
2514
2515 if(!mRawSnapshotAshmemHeap->initialized()){
2516 LOGE("receiveRawSnapshot X: error initializing mRawSnapshotHeap");
2517 deinitRawSnapshot();
2518 return;
2519 }
2520
2521 memcpy(mRawSnapshotAshmemHeap->mHeap->base(),
2522 mRawSnapShotPmemHeap->mHeap->base(),
2523 mRawSnapShotPmemHeap->mHeap->getSize());
2524
2525 mDataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mRawSnapshotAshmemHeap->mBuffers[0],
2526 mCallbackCookie);
2527
2528 }
2529
2530 //cleanup
2531 deinitRawSnapshot();
2532
2533 LOGV("receiveRawSnapshot X");
2534}
2535
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002536void QualcommCameraHardware::receiveRawPicture()
2537{
2538 LOGV("receiveRawPicture: E");
2539
2540 Mutex::Autolock cbLock(&mCallbackLock);
2541 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_RAW_IMAGE)) {
2542 if(native_get_picture(mCameraControlFd, &mCrop) == false) {
2543 LOGE("getPicture failed!");
2544 return;
2545 }
2546 mCrop.in1_w &= ~1;
2547 mCrop.in1_h &= ~1;
2548 mCrop.in2_w &= ~1;
2549 mCrop.in2_h &= ~1;
2550
2551 // By the time native_get_picture returns, picture is taken. Call
2552 // shutter callback if cam config thread has not done that.
2553 notifyShutter(&mCrop);
2554
2555 // Crop the image if zoomed.
2556 if (mCrop.in2_w != 0 && mCrop.in2_h != 0) {
2557 crop_yuv420(mCrop.out2_w, mCrop.out2_h, mCrop.in2_w, mCrop.in2_h,
2558 (uint8_t *)mRawHeap->mHeap->base());
2559 crop_yuv420(mCrop.out1_w, mCrop.out1_h, mCrop.in1_w, mCrop.in1_h,
2560 (uint8_t *)mThumbnailHeap->mHeap->base());
2561 // We do not need jpeg encoder to upscale the image. Set the new
2562 // dimension for encoder.
2563 mDimension.orig_picture_dx = mCrop.in2_w;
2564 mDimension.orig_picture_dy = mCrop.in2_h;
2565 mDimension.thumbnail_width = mCrop.in1_w;
2566 mDimension.thumbnail_height = mCrop.in1_h;
2567 memset(&mCrop, 0, sizeof(mCrop));
2568 }
2569
2570 mDataCallback(CAMERA_MSG_RAW_IMAGE, mDisplayHeap->mBuffers[0],
2571 mCallbackCookie);
2572 }
2573 else LOGV("Raw-picture callback was canceled--skipping.");
2574
2575 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
2576 mJpegSize = 0;
2577 if (LINK_jpeg_encoder_init()) {
2578 if(native_jpeg_encode()) {
2579 LOGV("receiveRawPicture: X (success)");
2580 return;
2581 }
2582 LOGE("jpeg encoding failed");
2583 }
2584 else LOGE("receiveRawPicture X: jpeg_encoder_init failed.");
2585 }
2586 else LOGV("JPEG callback is NULL, not encoding image.");
2587 deinitRaw();
2588 LOGV("receiveRawPicture: X");
2589}
2590
2591void QualcommCameraHardware::receiveJpegPictureFragment(
2592 uint8_t *buff_ptr, uint32_t buff_size)
2593{
2594 uint32_t remaining = mJpegHeap->mHeap->virtualSize();
2595 remaining -= mJpegSize;
2596 uint8_t *base = (uint8_t *)mJpegHeap->mHeap->base();
2597
2598 LOGV("receiveJpegPictureFragment size %d", buff_size);
2599 if (buff_size > remaining) {
2600 LOGE("receiveJpegPictureFragment: size %d exceeds what "
2601 "remains in JPEG heap (%d), truncating",
2602 buff_size,
2603 remaining);
2604 buff_size = remaining;
2605 }
2606 memcpy(base + mJpegSize, buff_ptr, buff_size);
2607 mJpegSize += buff_size;
2608}
2609
2610void QualcommCameraHardware::receiveJpegPicture(void)
2611{
2612 LOGV("receiveJpegPicture: E image (%d uint8_ts out of %d)",
2613 mJpegSize, mJpegHeap->mBufferSize);
2614 Mutex::Autolock cbLock(&mCallbackLock);
2615
2616 int index = 0, rc;
2617
2618 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
2619 // The reason we do not allocate into mJpegHeap->mBuffers[offset] is
2620 // that the JPEG image's size will probably change from one snapshot
2621 // to the next, so we cannot reuse the MemoryBase object.
2622 sp<MemoryBase> buffer = new
2623 MemoryBase(mJpegHeap->mHeap,
2624 index * mJpegHeap->mBufferSize +
2625 0,
2626 mJpegSize);
2627 mDataCallback(CAMERA_MSG_COMPRESSED_IMAGE, buffer, mCallbackCookie);
2628 buffer = NULL;
2629 }
2630 else LOGV("JPEG callback was cancelled--not delivering image.");
2631
2632 LINK_jpeg_encoder_join();
2633 deinitRaw();
2634
2635 LOGV("receiveJpegPicture: X callback done.");
2636}
2637
2638bool QualcommCameraHardware::previewEnabled()
2639{
2640 return mCameraRunning && mDataCallback && (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME);
2641}
2642
2643status_t QualcommCameraHardware::setPreviewSize(const CameraParameters& params)
2644{
2645 int width, height;
2646 params.getPreviewSize(&width, &height);
2647 LOGV("requested preview size %d x %d", width, height);
2648
2649 // Validate the preview size
2650 for (size_t i = 0; i < PREVIEW_SIZE_COUNT; ++i) {
2651 if (width == preview_sizes[i].width
2652 && height == preview_sizes[i].height) {
2653 mParameters.setPreviewSize(width, height);
2654 mDimension.display_width = width;
2655 mDimension.display_height = height;
2656 return NO_ERROR;
2657 }
2658 }
2659 LOGE("Invalid preview size requested: %dx%d", width, height);
2660 return BAD_VALUE;
2661}
2662
2663status_t QualcommCameraHardware::setPictureSize(const CameraParameters& params)
2664{
2665 int width, height;
2666 params.getPictureSize(&width, &height);
2667 LOGV("requested picture size %d x %d", width, height);
2668
2669 // Validate the picture size
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -08002670 for (int i = 0; i < supportedPictureSizesCount; ++i) {
2671 if (width == picture_sizes_ptr[i].width
2672 && height == picture_sizes_ptr[i].height) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002673 mParameters.setPictureSize(width, height);
2674 mDimension.picture_width = width;
2675 mDimension.picture_height = height;
2676 return NO_ERROR;
2677 }
2678 }
2679 LOGE("Invalid picture size requested: %dx%d", width, height);
2680 return BAD_VALUE;
2681}
2682
2683status_t QualcommCameraHardware::setJpegQuality(const CameraParameters& params) {
2684 status_t rc = NO_ERROR;
2685 int quality = params.getInt(CameraParameters::KEY_JPEG_QUALITY);
2686 if (quality > 0 && quality <= 100) {
2687 mParameters.set(CameraParameters::KEY_JPEG_QUALITY, quality);
2688 } else {
2689 LOGE("Invalid jpeg quality=%d", quality);
2690 rc = BAD_VALUE;
2691 }
2692
2693 quality = params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY);
2694 if (quality > 0 && quality <= 100) {
2695 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, quality);
2696 } else {
2697 LOGE("Invalid jpeg thumbnail quality=%d", quality);
2698 rc = BAD_VALUE;
2699 }
2700 return rc;
2701}
2702
2703status_t QualcommCameraHardware::setEffect(const CameraParameters& params)
2704{
2705 const char *str = params.get(CameraParameters::KEY_EFFECT);
2706 if (str != NULL) {
2707 int32_t value = attr_lookup(effects, sizeof(effects) / sizeof(str_map), str);
2708 if (value != NOT_FOUND) {
Mohan Kandra93f1bfb2009-12-15 16:55:33 -08002709 if(!strcmp(sensorType->name, "2mp") && (value != CAMERA_EFFECT_OFF)
2710 &&(value != CAMERA_EFFECT_MONO) && (value != CAMERA_EFFECT_NEGATIVE)
2711 &&(value != CAMERA_EFFECT_SOLARIZE) && (value != CAMERA_EFFECT_SEPIA)) {
2712 LOGE("Special effect parameter is not supported for this sensor");
2713 return NO_ERROR;
2714 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002715 mParameters.set(CameraParameters::KEY_EFFECT, str);
2716 bool ret = native_set_parm(CAMERA_SET_PARM_EFFECT, sizeof(value),
2717 (void *)&value);
2718 return ret ? NO_ERROR : UNKNOWN_ERROR;
2719 }
2720 }
2721 LOGE("Invalid effect value: %s", (str == NULL) ? "NULL" : str);
2722 return BAD_VALUE;
2723}
2724
Apurva Rajguru55562b02009-12-03 12:25:35 -08002725status_t QualcommCameraHardware::setAutoExposure(const CameraParameters& params)
2726{
Mohan Kandra93f1bfb2009-12-15 16:55:33 -08002727 if(!strcmp(sensorType->name, "2mp")) {
2728 LOGE("Auto Exposure not supported for this sensor");
2729 return NO_ERROR;
2730 }
Apurva Rajguru55562b02009-12-03 12:25:35 -08002731 const char *str = params.get(CameraParameters::KEY_AUTO_EXPOSURE);
2732 if (str != NULL) {
2733 int32_t value = attr_lookup(autoexposure, sizeof(autoexposure) / sizeof(str_map), str);
2734 if (value != NOT_FOUND) {
2735 mParameters.set(CameraParameters::KEY_AUTO_EXPOSURE, str);
2736 bool ret = native_set_parm(CAMERA_SET_PARM_EXPOSURE, sizeof(value),
2737 (void *)&value);
2738 return ret ? NO_ERROR : UNKNOWN_ERROR;
2739 }
2740 }
2741 LOGE("Invalid auto exposure value: %s", (str == NULL) ? "NULL" : str);
2742 return BAD_VALUE;
2743}
2744
Nishant Panditc8c1ee72009-12-03 16:24:02 +05302745status_t QualcommCameraHardware::setBrightness(const CameraParameters& params) {
2746 int brightness = params.getInt("luma-adaptation");
2747 if (mBrightness != brightness) {
2748 LOGV(" new brightness value : %d ", brightness);
2749 mBrightness = brightness;
2750
2751 bool ret = native_set_parm(CAMERA_SET_PARM_BRIGHTNESS, sizeof(mBrightness),
2752 (void *)&mBrightness);
2753 return ret ? NO_ERROR : UNKNOWN_ERROR;
2754 } else {
2755 return NO_ERROR;
2756 }
2757}
2758
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002759status_t QualcommCameraHardware::setWhiteBalance(const CameraParameters& params)
2760{
2761 const char *str = params.get(CameraParameters::KEY_WHITE_BALANCE);
2762 if (str != NULL) {
2763 int32_t value = attr_lookup(whitebalance, sizeof(whitebalance) / sizeof(str_map), str);
2764 if (value != NOT_FOUND) {
2765 mParameters.set(CameraParameters::KEY_WHITE_BALANCE, str);
2766 bool ret = native_set_parm(CAMERA_SET_PARM_WB, sizeof(value),
2767 (void *)&value);
2768 return ret ? NO_ERROR : UNKNOWN_ERROR;
2769 }
2770 }
2771 LOGE("Invalid whitebalance value: %s", (str == NULL) ? "NULL" : str);
2772 return BAD_VALUE;
2773}
2774
2775status_t QualcommCameraHardware::setFlash(const CameraParameters& params)
2776{
2777 if (!mSensorInfo.flash_enabled) {
2778 LOGV("%s: flash not supported", __FUNCTION__);
2779 return NO_ERROR;
2780 }
2781
2782 const char *str = params.get(CameraParameters::KEY_FLASH_MODE);
2783 if (str != NULL) {
2784 int32_t value = attr_lookup(flash, sizeof(flash) / sizeof(str_map), str);
2785 if (value != NOT_FOUND) {
2786 mParameters.set(CameraParameters::KEY_FLASH_MODE, str);
2787 bool ret = native_set_parm(CAMERA_SET_PARM_LED_MODE,
2788 sizeof(value), (void *)&value);
2789 return ret ? NO_ERROR : UNKNOWN_ERROR;
2790 }
2791 }
2792 LOGE("Invalid flash mode value: %s", (str == NULL) ? "NULL" : str);
2793 return BAD_VALUE;
2794}
2795
2796status_t QualcommCameraHardware::setAntibanding(const CameraParameters& params)
2797{
2798 const char *str = params.get(CameraParameters::KEY_ANTIBANDING);
2799 if (str != NULL) {
2800 int value = (camera_antibanding_type)attr_lookup(
2801 antibanding, sizeof(antibanding) / sizeof(str_map), str);
2802 if (value != NOT_FOUND) {
2803 camera_antibanding_type temp = (camera_antibanding_type) value;
2804 // We don't have auto antibanding now, and simply set the frequency by country.
2805 if (temp == CAMERA_ANTIBANDING_AUTO) {
2806 temp = camera_get_location();
2807 }
2808 mParameters.set(CameraParameters::KEY_ANTIBANDING, str);
2809 native_set_parm(CAMERA_SET_PARM_ANTIBANDING, sizeof(camera_antibanding_type), (void *)&temp);
2810 return NO_ERROR;
2811 }
2812 }
2813 LOGE("Invalid antibanding value: %s", (str == NULL) ? "NULL" : str);
2814 return BAD_VALUE;
2815}
2816
Nishant Panditc8c1ee72009-12-03 16:24:02 +05302817status_t QualcommCameraHardware::setLensshadeValue(const CameraParameters& params)
2818{
Mohan Kandra93f1bfb2009-12-15 16:55:33 -08002819 if(!strcmp(sensorType->name, "2mp")) {
2820 LOGE("Parameter Rolloff is not supported for this sensor");
2821 return NO_ERROR;
2822 }
Nishant Panditc8c1ee72009-12-03 16:24:02 +05302823 const char *str = params.get(CameraParameters::KEY_LENSSHADE);
2824 if (str != NULL) {
2825 int value = attr_lookup(lensshade,
2826 sizeof(lensshade) / sizeof(str_map), str);
2827 if (value != NOT_FOUND) {
2828 int8_t temp = (int8_t)value;
2829 mParameters.set(CameraParameters::KEY_LENSSHADE, str);
2830 native_set_parm(CAMERA_SET_PARM_ROLLOFF, sizeof(int8_t), (void *)&temp);
2831 return NO_ERROR;
2832 }
2833 }
2834 LOGE("Invalid lensShade value: %s", (str == NULL) ? "NULL" : str);
2835 return BAD_VALUE;
2836}
2837
2838status_t QualcommCameraHardware::setISOValue(const CameraParameters& params) {
2839 const char *str = params.get(CameraParameters::KEY_ISO_MODE);
2840 if (str != NULL) {
2841 int value = (camera_iso_mode_type)attr_lookup(
2842 iso, sizeof(iso) / sizeof(str_map), str);
2843 if (value != NOT_FOUND) {
2844 camera_iso_mode_type temp = (camera_iso_mode_type) value;
2845 mParameters.set(CameraParameters::KEY_ISO_MODE, str);
2846 native_set_parm(CAMERA_SET_PARM_ISO, sizeof(camera_iso_mode_type), (void *)&temp);
2847 return NO_ERROR;
2848 }
2849 }
2850 LOGE("Invalid Iso value: %s", (str == NULL) ? "NULL" : str);
2851 return BAD_VALUE;
2852}
2853
2854
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002855status_t QualcommCameraHardware::setGpsLocation(const CameraParameters& params)
2856{
2857 const char *latitude = params.get(CameraParameters::KEY_GPS_LATITUDE);
2858 if (latitude) {
2859 mParameters.set(CameraParameters::KEY_GPS_LATITUDE, latitude);
2860 }
2861
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08002862 const char *latitudeRef = params.get(CameraParameters::KEY_GPS_LATITUDE_REF);
2863 if (latitudeRef) {
2864 mParameters.set(CameraParameters::KEY_GPS_LATITUDE_REF, latitudeRef);
2865 }
2866
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002867 const char *longitude = params.get(CameraParameters::KEY_GPS_LONGITUDE);
2868 if (longitude) {
2869 mParameters.set(CameraParameters::KEY_GPS_LONGITUDE, longitude);
2870 }
2871
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08002872 const char *longitudeRef = params.get(CameraParameters::KEY_GPS_LONGITUDE_REF);
2873 if (longitudeRef) {
2874 mParameters.set(CameraParameters::KEY_GPS_LONGITUDE_REF, longitudeRef);
2875 }
2876
2877 const char *altitudeRef = params.get(CameraParameters::KEY_GPS_ALTITUDE_REF);
2878 if (altitudeRef) {
2879 mParameters.set(CameraParameters::KEY_GPS_ALTITUDE_REF, altitudeRef);
2880 }
2881
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002882 const char *altitude = params.get(CameraParameters::KEY_GPS_ALTITUDE);
2883 if (altitude) {
2884 mParameters.set(CameraParameters::KEY_GPS_ALTITUDE, altitude);
2885 }
2886
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08002887 const char *status = params.get(CameraParameters::KEY_GPS_STATUS);
2888 if (status) {
2889 mParameters.set(CameraParameters::KEY_GPS_STATUS, status);
2890 }
2891
2892 const char *dateTime = params.get(CameraParameters::KEY_EXIF_DATETIME);
2893 if (dateTime) {
2894 mParameters.set(CameraParameters::KEY_EXIF_DATETIME, dateTime);
2895 }
2896
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002897 const char *timestamp = params.get(CameraParameters::KEY_GPS_TIMESTAMP);
2898 if (timestamp) {
2899 mParameters.set(CameraParameters::KEY_GPS_TIMESTAMP, timestamp);
2900 }
2901 return NO_ERROR;
2902}
2903
2904status_t QualcommCameraHardware::setRotation(const CameraParameters& params)
2905{
2906 status_t rc = NO_ERROR;
2907 int rotation = params.getInt(CameraParameters::KEY_ROTATION);
2908 if (rotation != NOT_FOUND) {
2909 if (rotation == 0 || rotation == 90 || rotation == 180
2910 || rotation == 270) {
2911 mParameters.set(CameraParameters::KEY_ROTATION, rotation);
2912 } else {
2913 LOGE("Invalid rotation value: %d", rotation);
2914 rc = BAD_VALUE;
2915 }
2916 }
2917 return rc;
2918}
2919
2920status_t QualcommCameraHardware::setZoom(const CameraParameters& params)
2921{
2922 status_t rc = NO_ERROR;
2923 // No matter how many different zoom values the driver can provide, HAL
2924 // provides applictations the same number of zoom levels. The maximum driver
2925 // zoom value depends on sensor output (VFE input) and preview size (VFE
2926 // output) because VFE can only crop and cannot upscale. If the preview size
2927 // is bigger, the maximum zoom ratio is smaller. However, we want the
2928 // zoom ratio of each zoom level is always the same whatever the preview
2929 // size is. Ex: zoom level 1 is always 1.2x, zoom level 2 is 1.44x, etc. So,
2930 // we need to have a fixed maximum zoom value and do read it from the
2931 // driver.
2932 static const int ZOOM_STEP = 6;
2933 int32_t zoom_level = params.getInt("zoom");
2934
2935 LOGI("Set zoom=%d", zoom_level);
2936 if(zoom_level >= 0 && zoom_level <= MAX_ZOOM_LEVEL) {
2937 mParameters.set("zoom", zoom_level);
2938 int32_t zoom_value = ZOOM_STEP * zoom_level;
2939 bool ret = native_set_parm(CAMERA_SET_PARM_ZOOM,
2940 sizeof(zoom_value), (void *)&zoom_value);
2941 rc = ret ? NO_ERROR : UNKNOWN_ERROR;
2942 } else {
2943 rc = BAD_VALUE;
2944 }
2945
2946 return rc;
2947}
2948
2949status_t QualcommCameraHardware::setFocusMode(const CameraParameters& params)
2950{
2951 const char *str = params.get(CameraParameters::KEY_FOCUS_MODE);
2952 if (str != NULL) {
2953 int32_t value = attr_lookup(focus_modes,
2954 sizeof(focus_modes) / sizeof(str_map), str);
2955 if (value != NOT_FOUND) {
2956 mParameters.set(CameraParameters::KEY_FOCUS_MODE, str);
2957 // Focus step is reset to infinity when preview is started. We do
2958 // not need to do anything now.
2959 return NO_ERROR;
2960 }
2961 }
2962 LOGE("Invalid focus mode value: %s", (str == NULL) ? "NULL" : str);
2963 return BAD_VALUE;
2964}
2965
2966status_t QualcommCameraHardware::setOrientation(const CameraParameters& params)
2967{
2968 const char *str = params.get("orientation");
2969
2970 if (str != NULL) {
2971 if (strcmp(str, "portrait") == 0 || strcmp(str, "landscape") == 0) {
2972 // Camera service needs this to decide if the preview frames and raw
2973 // pictures should be rotated.
2974 mParameters.set("orientation", str);
2975 } else {
2976 LOGE("Invalid orientation value: %s", str);
2977 return BAD_VALUE;
2978 }
2979 }
2980 return NO_ERROR;
2981}
2982
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002983status_t QualcommCameraHardware::setPictureFormat(const CameraParameters& params)
2984{
2985 const char * str = params.get(CameraParameters::KEY_PICTURE_FORMAT);
2986
2987 if(str != NULL){
2988 int32_t value = attr_lookup(picture_formats,
2989 sizeof(picture_formats) / sizeof(str_map), str);
2990 if(value != NOT_FOUND){
2991 mParameters.set(CameraParameters::KEY_PICTURE_FORMAT, str);
2992 } else {
2993 LOGE("Invalid Picture Format value: %s", str);
2994 return BAD_VALUE;
2995 }
2996 }
2997 return NO_ERROR;
2998}
2999
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003000QualcommCameraHardware::MemPool::MemPool(int buffer_size, int num_buffers,
3001 int frame_size,
3002 const char *name) :
3003 mBufferSize(buffer_size),
3004 mNumBuffers(num_buffers),
3005 mFrameSize(frame_size),
3006 mBuffers(NULL), mName(name)
3007{
3008 int page_size_minus_1 = getpagesize() - 1;
3009 mAlignedBufferSize = (buffer_size + page_size_minus_1) & (~page_size_minus_1);
3010}
3011
3012void QualcommCameraHardware::MemPool::completeInitialization()
3013{
3014 // If we do not know how big the frame will be, we wait to allocate
3015 // the buffers describing the individual frames until we do know their
3016 // size.
3017
3018 if (mFrameSize > 0) {
3019 mBuffers = new sp<MemoryBase>[mNumBuffers];
3020 for (int i = 0; i < mNumBuffers; i++) {
3021 mBuffers[i] = new
3022 MemoryBase(mHeap,
3023 i * mAlignedBufferSize,
3024 mFrameSize);
3025 }
3026 }
3027}
3028
3029QualcommCameraHardware::AshmemPool::AshmemPool(int buffer_size, int num_buffers,
3030 int frame_size,
3031 const char *name) :
3032 QualcommCameraHardware::MemPool(buffer_size,
3033 num_buffers,
3034 frame_size,
3035 name)
3036{
3037 LOGV("constructing MemPool %s backed by ashmem: "
3038 "%d frames @ %d uint8_ts, "
3039 "buffer size %d",
3040 mName,
3041 num_buffers, frame_size, buffer_size);
3042
3043 int page_mask = getpagesize() - 1;
3044 int ashmem_size = buffer_size * num_buffers;
3045 ashmem_size += page_mask;
3046 ashmem_size &= ~page_mask;
3047
3048 mHeap = new MemoryHeapBase(ashmem_size);
3049
3050 completeInitialization();
3051}
3052
3053static bool register_buf(int camfd,
3054 int size,
3055 int pmempreviewfd,
3056 uint32_t offset,
3057 uint8_t *buf,
3058 int pmem_type,
3059 bool vfe_can_write,
3060 bool register_buffer = true);
3061
3062QualcommCameraHardware::PmemPool::PmemPool(const char *pmem_pool,
3063 int flags,
3064 int camera_control_fd,
3065 int pmem_type,
3066 int buffer_size, int num_buffers,
3067 int frame_size,
3068 const char *name) :
3069 QualcommCameraHardware::MemPool(buffer_size,
3070 num_buffers,
3071 frame_size,
3072 name),
3073 mPmemType(pmem_type),
3074 mCameraControlFd(dup(camera_control_fd))
3075{
3076 LOGV("constructing MemPool %s backed by pmem pool %s: "
3077 "%d frames @ %d bytes, buffer size %d",
3078 mName,
3079 pmem_pool, num_buffers, frame_size,
3080 buffer_size);
3081
3082 LOGV("%s: duplicating control fd %d --> %d",
3083 __FUNCTION__,
3084 camera_control_fd, mCameraControlFd);
3085
3086 // Make a new mmap'ed heap that can be shared across processes.
3087 // mAlignedBufferSize is already in 4k aligned. (do we need total size necessary to be in power of 2??)
3088 mAlignedSize = mAlignedBufferSize * num_buffers;
3089
3090 sp<MemoryHeapBase> masterHeap =
3091 new MemoryHeapBase(pmem_pool, mAlignedSize, flags);
3092
3093 if (masterHeap->getHeapID() < 0) {
3094 LOGE("failed to construct master heap for pmem pool %s", pmem_pool);
3095 masterHeap.clear();
3096 return;
3097 }
3098
3099 sp<MemoryHeapPmem> pmemHeap = new MemoryHeapPmem(masterHeap, flags);
3100 if (pmemHeap->getHeapID() >= 0) {
3101 pmemHeap->slap();
3102 masterHeap.clear();
3103 mHeap = pmemHeap;
3104 pmemHeap.clear();
3105
3106 mFd = mHeap->getHeapID();
3107 if (::ioctl(mFd, PMEM_GET_SIZE, &mSize)) {
3108 LOGE("pmem pool %s ioctl(PMEM_GET_SIZE) error %s (%d)",
3109 pmem_pool,
3110 ::strerror(errno), errno);
3111 mHeap.clear();
3112 return;
3113 }
3114
3115 LOGV("pmem pool %s ioctl(fd = %d, PMEM_GET_SIZE) is %ld",
3116 pmem_pool,
3117 mFd,
3118 mSize.len);
3119 LOGD("mBufferSize=%d, mAlignedBufferSize=%d\n", mBufferSize, mAlignedBufferSize);
3120 // Unregister preview buffers with the camera drivers. Allow the VFE to write
3121 // to all preview buffers except for the last one.
3122 for (int cnt = 0; cnt < num_buffers; ++cnt) {
3123 register_buf(mCameraControlFd,
3124 mBufferSize,
3125 mHeap->getHeapID(),
3126 mAlignedBufferSize * cnt,
3127 (uint8_t *)mHeap->base() + mAlignedBufferSize * cnt,
3128 pmem_type,
3129 !(cnt == num_buffers - 1 && pmem_type == MSM_PMEM_OUTPUT2));
3130 }
3131
3132 completeInitialization();
3133 }
3134 else LOGE("pmem pool %s error: could not create master heap!",
3135 pmem_pool);
3136}
3137
3138QualcommCameraHardware::PmemPool::~PmemPool()
3139{
3140 LOGV("%s: %s E", __FUNCTION__, mName);
3141 if (mHeap != NULL) {
3142 // Unregister preview buffers with the camera drivers.
3143 for (int cnt = 0; cnt < mNumBuffers; ++cnt) {
3144 register_buf(mCameraControlFd,
3145 mBufferSize,
3146 mHeap->getHeapID(),
3147 mAlignedBufferSize * cnt,
3148 (uint8_t *)mHeap->base() + mAlignedBufferSize * cnt,
3149 mPmemType,
3150 false,
3151 false /* unregister */);
3152 }
3153 }
3154 LOGV("destroying PmemPool %s: closing control fd %d",
3155 mName,
3156 mCameraControlFd);
3157 close(mCameraControlFd);
3158 LOGV("%s: %s X", __FUNCTION__, mName);
3159}
3160
3161QualcommCameraHardware::MemPool::~MemPool()
3162{
3163 LOGV("destroying MemPool %s", mName);
3164 if (mFrameSize > 0)
3165 delete [] mBuffers;
3166 mHeap.clear();
3167 LOGV("destroying MemPool %s completed", mName);
3168}
3169
3170static bool register_buf(int camfd,
3171 int size,
3172 int pmempreviewfd,
3173 uint32_t offset,
3174 uint8_t *buf,
3175 int pmem_type,
3176 bool vfe_can_write,
3177 bool register_buffer)
3178{
3179 struct msm_pmem_info pmemBuf;
3180
3181 pmemBuf.type = pmem_type;
3182 pmemBuf.fd = pmempreviewfd;
3183 pmemBuf.offset = offset;
3184 pmemBuf.len = size;
3185 pmemBuf.vaddr = buf;
3186 pmemBuf.y_off = 0;
3187 pmemBuf.cbcr_off = PAD_TO_WORD(size * 2 / 3);
3188 pmemBuf.active = vfe_can_write;
3189
3190 LOGV("register_buf: camfd = %d, reg = %d buffer = %p",
3191 camfd, !register_buffer, buf);
3192 if (ioctl(camfd,
3193 register_buffer ?
3194 MSM_CAM_IOCTL_REGISTER_PMEM :
3195 MSM_CAM_IOCTL_UNREGISTER_PMEM,
3196 &pmemBuf) < 0) {
3197 LOGE("register_buf: MSM_CAM_IOCTL_(UN)REGISTER_PMEM fd %d error %s",
3198 camfd,
3199 strerror(errno));
3200 return false;
3201 }
3202 return true;
3203}
3204
3205status_t QualcommCameraHardware::MemPool::dump(int fd, const Vector<String16>& args) const
3206{
3207 const size_t SIZE = 256;
3208 char buffer[SIZE];
3209 String8 result;
3210 snprintf(buffer, 255, "QualcommCameraHardware::AshmemPool::dump\n");
3211 result.append(buffer);
3212 if (mName) {
3213 snprintf(buffer, 255, "mem pool name (%s)\n", mName);
3214 result.append(buffer);
3215 }
3216 if (mHeap != 0) {
3217 snprintf(buffer, 255, "heap base(%p), size(%d), flags(%d), device(%s)\n",
3218 mHeap->getBase(), mHeap->getSize(),
3219 mHeap->getFlags(), mHeap->getDevice());
3220 result.append(buffer);
3221 }
3222 snprintf(buffer, 255,
3223 "buffer size (%d), number of buffers (%d), frame size(%d)",
3224 mBufferSize, mNumBuffers, mFrameSize);
3225 result.append(buffer);
3226 write(fd, result.string(), result.size());
3227 return NO_ERROR;
3228}
3229
3230static void receive_camframe_callback(struct msm_frame *frame)
3231{
3232 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
3233 if (obj != 0) {
3234 obj->receivePreviewFrame(frame);
3235 }
3236}
3237
3238static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size)
3239{
3240 LOGV("receive_jpeg_fragment_callback E");
3241 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
3242 if (obj != 0) {
3243 obj->receiveJpegPictureFragment(buff_ptr, buff_size);
3244 }
3245 LOGV("receive_jpeg_fragment_callback X");
3246}
3247
3248static void receive_jpeg_callback(jpeg_event_t status)
3249{
3250 LOGV("receive_jpeg_callback E (completion status %d)", status);
3251 if (status == JPEG_EVENT_DONE) {
3252 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
3253 if (obj != 0) {
3254 obj->receiveJpegPicture();
3255 }
3256 }
3257 LOGV("receive_jpeg_callback X");
3258}
3259
3260void QualcommCameraHardware::setCallbacks(notify_callback notify_cb,
3261 data_callback data_cb,
3262 data_callback_timestamp data_cb_timestamp,
3263 void* user)
3264{
3265 Mutex::Autolock lock(mLock);
3266 mNotifyCallback = notify_cb;
3267 mDataCallback = data_cb;
3268 mDataCallbackTimestamp = data_cb_timestamp;
3269 mCallbackCookie = user;
3270}
3271
3272void QualcommCameraHardware::enableMsgType(int32_t msgType)
3273{
3274 Mutex::Autolock lock(mLock);
3275 mMsgEnabled |= msgType;
3276}
3277
3278void QualcommCameraHardware::disableMsgType(int32_t msgType)
3279{
3280 Mutex::Autolock lock(mLock);
3281 mMsgEnabled &= ~msgType;
3282}
3283
3284bool QualcommCameraHardware::msgTypeEnabled(int32_t msgType)
3285{
3286 return (mMsgEnabled & msgType);
3287}
3288
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08003289bool QualcommCameraHardware::useOverlay(void)
3290{
3291 char value[PROPERTY_VALUE_MAX];
3292 property_get("ro.product.device",value," ");
3293
3294 if(!strcmp(value,"msm7630_surf")) {
3295 /* Only 7x30 supports Overlay */
3296 mUseOverlay = TRUE;
3297 } else
3298 mUseOverlay = FALSE;
3299
3300 LOGV(" Using Overlay : %s ", mUseOverlay ? "YES" : "NO" );
3301 return mUseOverlay;
3302}
3303
3304status_t QualcommCameraHardware::setOverlay(const sp<Overlay> &Overlay)
3305{
3306 if( Overlay != NULL) {
3307 LOGV(" Valid overlay object ");
3308 mOverlayLock.lock();
3309 mOverlay = Overlay;
3310 mOverlayLock.unlock();
3311 } else {
3312 LOGE(" Overlay object NULL. returning ");
3313 return UNKNOWN_ERROR;
3314 }
3315 return NO_ERROR;
3316}
Kiran Kumar H N215cac42009-12-08 01:53:46 -08003317
3318void QualcommCameraHardware::receive_camframetimeout(void) {
3319 LOGV("receive_camframetimeout: E");
3320 Mutex::Autolock l(&mCamframeTimeoutLock);
3321 camframe_timeout_flag = TRUE;
3322 LOGV("receive_camframetimeout: X");
3323}
3324
3325static void receive_camframetimeout_callback(void) {
3326 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
3327 if (obj != 0) {
3328 obj->receive_camframetimeout();
3329 }
3330}
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003331}; // namespace android