blob: 2385286023051a36a029e738604deea1992236eb [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
Mohan Kandra284966d2010-01-05 13:39:15 -080039#include "linux/msm_mdp.h"
40#include <linux/fb.h>
41
Priya Komarlingamb85535d2009-11-30 13:06:01 -080042#define LIKELY(exp) __builtin_expect(!!(exp), 1)
43#define UNLIKELY(exp) __builtin_expect(!!(exp), 0)
44
45extern "C" {
46#include <fcntl.h>
47#include <time.h>
48#include <pthread.h>
49#include <stdio.h>
50#include <string.h>
51#include <unistd.h>
52#include <termios.h>
53#include <assert.h>
54#include <stdlib.h>
55#include <ctype.h>
56#include <signal.h>
57#include <errno.h>
58#include <sys/mman.h>
59#include <sys/system_properties.h>
60#include <sys/time.h>
61#include <stdlib.h>
62
63#include <media/msm_camera.h>
64
65#include <camera.h>
66#include <camframe.h>
67#include <mm-still/jpeg/jpege.h>
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -080068#include <jpeg_encoder.h>
Priya Komarlingamb85535d2009-11-30 13:06:01 -080069
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -080070#define DEFAULT_PICTURE_WIDTH 1024
71#define DEFAULT_PICTURE_HEIGHT 768
Priya Komarlingamb85535d2009-11-30 13:06:01 -080072#define THUMBNAIL_BUFFER_SIZE (THUMBNAIL_WIDTH * THUMBNAIL_HEIGHT * 3/2)
73#define MAX_ZOOM_LEVEL 5
74#define NOT_FOUND -1
75
76#if DLOPEN_LIBMMCAMERA
77#include <dlfcn.h>
78
79void* (*LINK_cam_conf)(void *data);
80void* (*LINK_cam_frame)(void *data);
81bool (*LINK_jpeg_encoder_init)();
82void (*LINK_jpeg_encoder_join)();
83bool (*LINK_jpeg_encoder_encode)(const cam_ctrl_dimension_t *dimen,
84 const uint8_t *thumbnailbuf, int thumbnailfd,
85 const uint8_t *snapshotbuf, int snapshotfd,
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -080086 common_crop_t *scaling_parms, exif_tags_info_t *exif_data,
87 int exif_table_numEntries);
Priya Komarlingamb85535d2009-11-30 13:06:01 -080088int (*LINK_camframe_terminate)(void);
89int8_t (*LINK_jpeg_encoder_setMainImageQuality)(uint32_t quality);
90int8_t (*LINK_jpeg_encoder_setThumbnailQuality)(uint32_t quality);
91int8_t (*LINK_jpeg_encoder_setRotation)(uint32_t rotation);
92int8_t (*LINK_jpeg_encoder_setLocation)(const camera_position_type *location);
93const struct camera_size_type *(*LINK_default_sensor_get_snapshot_sizes)(int *len);
94int (*LINK_launch_cam_conf_thread)(void);
95int (*LINK_release_cam_conf_thread)(void);
96int8_t (*LINK_zoom_crop_upscale)(uint32_t width, uint32_t height,
97 uint32_t cropped_width, uint32_t cropped_height, uint8_t *img_buf);
98
99// callbacks
100void (**LINK_mmcamera_camframe_callback)(struct msm_frame *frame);
101void (**LINK_mmcamera_jpegfragment_callback)(uint8_t *buff_ptr,
102 uint32_t buff_size);
103void (**LINK_mmcamera_jpeg_callback)(jpeg_event_t status);
104void (**LINK_mmcamera_shutter_callback)(common_crop_t *crop);
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800105void (**LINK_camframe_timeout_callback)(void);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800106#else
107#define LINK_cam_conf cam_conf
108#define LINK_cam_frame cam_frame
109#define LINK_jpeg_encoder_init jpeg_encoder_init
110#define LINK_jpeg_encoder_join jpeg_encoder_join
111#define LINK_jpeg_encoder_encode jpeg_encoder_encode
112#define LINK_camframe_terminate camframe_terminate
113#define LINK_jpeg_encoder_setMainImageQuality jpeg_encoder_setMainImageQuality
114#define LINK_jpeg_encoder_setThumbnailQuality jpeg_encoder_setThumbnailQuality
115#define LINK_jpeg_encoder_setRotation jpeg_encoder_setRotation
116#define LINK_jpeg_encoder_setLocation jpeg_encoder_setLocation
117#define LINK_default_sensor_get_snapshot_sizes default_sensor_get_snapshot_sizes
118#define LINK_launch_cam_conf_thread launch_cam_conf_thread
119#define LINK_release_cam_conf_thread release_cam_conf_thread
120#define LINK_zoom_crop_upscale zoom_crop_upscale
121extern void (*mmcamera_camframe_callback)(struct msm_frame *frame);
122extern void (*mmcamera_jpegfragment_callback)(uint8_t *buff_ptr,
123 uint32_t buff_size);
124extern void (*mmcamera_jpeg_callback)(jpeg_event_t status);
125extern void (*mmcamera_shutter_callback)(common_crop_t *crop);
126#endif
127
128} // extern "C"
129
130#ifndef HAVE_CAMERA_SIZE_TYPE
131struct camera_size_type {
132 int width;
133 int height;
134};
135#endif
136
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -0800137typedef struct crop_info_struct {
138 uint32_t x;
139 uint32_t y;
140 uint32_t w;
141 uint32_t h;
142} zoom_crop_info;
143
Mohan Kandra284966d2010-01-05 13:39:15 -0800144static char mDeviceName[PROPERTY_VALUE_MAX];
Mohan Kandra740cfce2010-01-07 12:58:24 -0800145union zoomimage
Mohan Kandra284966d2010-01-05 13:39:15 -0800146{
147 char d[sizeof(struct mdp_blit_req_list) + sizeof(struct mdp_blit_req) * 1];
148 struct mdp_blit_req_list list;
149} zoomImage;
150
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800151//Default to WVGA
Srinivasan Kannanfa7edae2009-12-16 18:02:01 -0800152#define DEFAULT_PREVIEW_SETTING 1
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800153static const camera_size_type preview_sizes[] = {
Srinivasan Kannanfa7edae2009-12-16 18:02:01 -0800154 { 1280, 720 }, // 720P, reserved
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800155 { 800, 480 }, // WVGA
156 { 720, 480 },
157 { 640, 480 }, // VGA
158 { 576, 432 },
159 { 480, 320 }, // HVGA
160 { 384, 288 },
161 { 352, 288 }, // CIF
162 { 320, 240 }, // QVGA
163 { 240, 160 }, // SQVGA
164 { 176, 144 }, // QCIF
165};
166#define PREVIEW_SIZE_COUNT (sizeof(preview_sizes)/sizeof(camera_size_type))
167
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800168//static const camera_size_type* picture_sizes;
169//static int PICTURE_SIZE_COUNT;
170/* TODO
171 * Ideally this should be a populated by lower layers.
172 * But currently this is no API to do that at lower layer.
173 * Hence populating with default sizes for now. This needs
174 * to be changed once the API is supported.
175 */
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800176//sorted on column basis
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800177static const camera_size_type picture_sizes[] = {
178 { 2592, 1944 }, // 5MP
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800179 { 2048, 1536 }, // 3MP QXGA
180 { 1920, 1080 }, //HD1080
181 { 1600, 1200 }, // 2MP UXGA
182 { 1280, 768 }, //WXGA
183 { 1280, 720 }, //HD720
184 { 1024, 768}, // 1MP XGA
185 { 800, 600 }, //SVGA
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800186 { 800, 480 }, // WVGA
187 { 640, 480 }, // VGA
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800188 { 352, 288 }, //CIF
189 { 320, 240 }, // QVGA
190 { 176, 144 } // QCIF
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800191};
192static int PICTURE_SIZE_COUNT = sizeof(picture_sizes)/sizeof(camera_size_type);
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800193static const camera_size_type * picture_sizes_ptr;
194static int supportedPictureSizesCount;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800195
Srinivasan Kannan80d878f2009-12-18 15:06:02 -0800196#ifdef Q12
197#undef Q12
198#endif
199
200#define Q12 4096
201
202typedef struct {
203 uint32_t aspect_ratio;
204 uint32_t width;
205 uint32_t height;
206} thumbnail_size_type;
207
208static thumbnail_size_type thumbnail_sizes[] = {
209 { 7281, 512, 288 }, //1.777778
210 { 6826, 480, 288 }, //1.666667
211 { 5461, 512, 384 }, //1.333333
212 { 5006, 352, 288 }, //1.222222
213};
214#define THUMBNAIL_SIZE_COUNT (sizeof(thumbnail_sizes)/sizeof(thumbnail_size_type))
215#define DEFAULT_THUMBNAIL_SETTING 2
216#define THUMBNAIL_WIDTH_STR "512"
217#define THUMBNAIL_HEIGHT_STR "384"
218#define THUMBNAIL_SMALL_HEIGHT 144
219
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800220static int attr_lookup(const str_map arr[], int len, const char *name)
221{
222 if (name) {
223 for (int i = 0; i < len; i++) {
224 if (!strcmp(arr[i].desc, name))
225 return arr[i].val;
226 }
227 }
228 return NOT_FOUND;
229}
230
231// round to the next power of two
232static inline unsigned clp2(unsigned x)
233{
234 x = x - 1;
235 x = x | (x >> 1);
236 x = x | (x >> 2);
237 x = x | (x >> 4);
238 x = x | (x >> 8);
239 x = x | (x >>16);
240 return x + 1;
241}
242
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -0800243static int exif_table_numEntries = 0;
244#define MAX_EXIF_TABLE_ENTRIES 7
245exif_tags_info_t exif_data[MAX_EXIF_TABLE_ENTRIES];
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -0800246static zoom_crop_info zoomCropInfo;
247static void *mLastQueuedFrame = NULL;
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -0800248
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800249namespace android {
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800250
251static const int PICTURE_FORMAT_JPEG = 1;
252static const int PICTURE_FORMAT_RAW = 2;
253
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800254// from aeecamera.h
255static const str_map whitebalance[] = {
256 { CameraParameters::WHITE_BALANCE_AUTO, CAMERA_WB_AUTO },
257 { CameraParameters::WHITE_BALANCE_INCANDESCENT, CAMERA_WB_INCANDESCENT },
258 { CameraParameters::WHITE_BALANCE_FLUORESCENT, CAMERA_WB_FLUORESCENT },
259 { CameraParameters::WHITE_BALANCE_DAYLIGHT, CAMERA_WB_DAYLIGHT },
260 { CameraParameters::WHITE_BALANCE_CLOUDY_DAYLIGHT, CAMERA_WB_CLOUDY_DAYLIGHT }
261};
262
263// from camera_effect_t. This list must match aeecamera.h
264static const str_map effects[] = {
265 { CameraParameters::EFFECT_NONE, CAMERA_EFFECT_OFF },
266 { CameraParameters::EFFECT_MONO, CAMERA_EFFECT_MONO },
267 { CameraParameters::EFFECT_NEGATIVE, CAMERA_EFFECT_NEGATIVE },
268 { CameraParameters::EFFECT_SOLARIZE, CAMERA_EFFECT_SOLARIZE },
269 { CameraParameters::EFFECT_SEPIA, CAMERA_EFFECT_SEPIA },
270 { CameraParameters::EFFECT_POSTERIZE, CAMERA_EFFECT_POSTERIZE },
271 { CameraParameters::EFFECT_WHITEBOARD, CAMERA_EFFECT_WHITEBOARD },
272 { CameraParameters::EFFECT_BLACKBOARD, CAMERA_EFFECT_BLACKBOARD },
273 { CameraParameters::EFFECT_AQUA, CAMERA_EFFECT_AQUA }
274};
275
276// from qcamera/common/camera.h
Apurva Rajguru55562b02009-12-03 12:25:35 -0800277static const str_map autoexposure[] = {
278 { CameraParameters::AUTO_EXPOSURE_FRAME_AVG, CAMERA_AEC_FRAME_AVERAGE },
279 { CameraParameters::AUTO_EXPOSURE_CENTER_WEIGHTED, CAMERA_AEC_CENTER_WEIGHTED },
280 { CameraParameters::AUTO_EXPOSURE_SPOT_METERING, CAMERA_AEC_SPOT_METERING }
281};
282
283// from qcamera/common/camera.h
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800284static const str_map antibanding[] = {
285 { CameraParameters::ANTIBANDING_OFF, CAMERA_ANTIBANDING_OFF },
286 { CameraParameters::ANTIBANDING_50HZ, CAMERA_ANTIBANDING_50HZ },
287 { CameraParameters::ANTIBANDING_60HZ, CAMERA_ANTIBANDING_60HZ },
288 { CameraParameters::ANTIBANDING_AUTO, CAMERA_ANTIBANDING_AUTO }
289};
290
291/* Mapping from MCC to antibanding type */
292struct country_map {
293 uint32_t country_code;
294 camera_antibanding_type type;
295};
296
297static struct country_map country_numeric[] = {
298 { 202, CAMERA_ANTIBANDING_50HZ }, // Greece
299 { 204, CAMERA_ANTIBANDING_50HZ }, // Netherlands
300 { 206, CAMERA_ANTIBANDING_50HZ }, // Belgium
301 { 208, CAMERA_ANTIBANDING_50HZ }, // France
302 { 212, CAMERA_ANTIBANDING_50HZ }, // Monaco
303 { 213, CAMERA_ANTIBANDING_50HZ }, // Andorra
304 { 214, CAMERA_ANTIBANDING_50HZ }, // Spain
305 { 216, CAMERA_ANTIBANDING_50HZ }, // Hungary
306 { 219, CAMERA_ANTIBANDING_50HZ }, // Croatia
307 { 220, CAMERA_ANTIBANDING_50HZ }, // Serbia
308 { 222, CAMERA_ANTIBANDING_50HZ }, // Italy
309 { 226, CAMERA_ANTIBANDING_50HZ }, // Romania
310 { 228, CAMERA_ANTIBANDING_50HZ }, // Switzerland
311 { 230, CAMERA_ANTIBANDING_50HZ }, // Czech Republic
312 { 231, CAMERA_ANTIBANDING_50HZ }, // Slovakia
313 { 232, CAMERA_ANTIBANDING_50HZ }, // Austria
314 { 234, CAMERA_ANTIBANDING_50HZ }, // United Kingdom
315 { 235, CAMERA_ANTIBANDING_50HZ }, // United Kingdom
316 { 238, CAMERA_ANTIBANDING_50HZ }, // Denmark
317 { 240, CAMERA_ANTIBANDING_50HZ }, // Sweden
318 { 242, CAMERA_ANTIBANDING_50HZ }, // Norway
319 { 244, CAMERA_ANTIBANDING_50HZ }, // Finland
320 { 246, CAMERA_ANTIBANDING_50HZ }, // Lithuania
321 { 247, CAMERA_ANTIBANDING_50HZ }, // Latvia
322 { 248, CAMERA_ANTIBANDING_50HZ }, // Estonia
323 { 250, CAMERA_ANTIBANDING_50HZ }, // Russian Federation
324 { 255, CAMERA_ANTIBANDING_50HZ }, // Ukraine
325 { 257, CAMERA_ANTIBANDING_50HZ }, // Belarus
326 { 259, CAMERA_ANTIBANDING_50HZ }, // Moldova
327 { 260, CAMERA_ANTIBANDING_50HZ }, // Poland
328 { 262, CAMERA_ANTIBANDING_50HZ }, // Germany
329 { 266, CAMERA_ANTIBANDING_50HZ }, // Gibraltar
330 { 268, CAMERA_ANTIBANDING_50HZ }, // Portugal
331 { 270, CAMERA_ANTIBANDING_50HZ }, // Luxembourg
332 { 272, CAMERA_ANTIBANDING_50HZ }, // Ireland
333 { 274, CAMERA_ANTIBANDING_50HZ }, // Iceland
334 { 276, CAMERA_ANTIBANDING_50HZ }, // Albania
335 { 278, CAMERA_ANTIBANDING_50HZ }, // Malta
336 { 280, CAMERA_ANTIBANDING_50HZ }, // Cyprus
337 { 282, CAMERA_ANTIBANDING_50HZ }, // Georgia
338 { 283, CAMERA_ANTIBANDING_50HZ }, // Armenia
339 { 284, CAMERA_ANTIBANDING_50HZ }, // Bulgaria
340 { 286, CAMERA_ANTIBANDING_50HZ }, // Turkey
341 { 288, CAMERA_ANTIBANDING_50HZ }, // Faroe Islands
342 { 290, CAMERA_ANTIBANDING_50HZ }, // Greenland
343 { 293, CAMERA_ANTIBANDING_50HZ }, // Slovenia
344 { 294, CAMERA_ANTIBANDING_50HZ }, // Macedonia
345 { 295, CAMERA_ANTIBANDING_50HZ }, // Liechtenstein
346 { 297, CAMERA_ANTIBANDING_50HZ }, // Montenegro
347 { 302, CAMERA_ANTIBANDING_60HZ }, // Canada
348 { 310, CAMERA_ANTIBANDING_60HZ }, // United States of America
349 { 311, CAMERA_ANTIBANDING_60HZ }, // United States of America
350 { 312, CAMERA_ANTIBANDING_60HZ }, // United States of America
351 { 313, CAMERA_ANTIBANDING_60HZ }, // United States of America
352 { 314, CAMERA_ANTIBANDING_60HZ }, // United States of America
353 { 315, CAMERA_ANTIBANDING_60HZ }, // United States of America
354 { 316, CAMERA_ANTIBANDING_60HZ }, // United States of America
355 { 330, CAMERA_ANTIBANDING_60HZ }, // Puerto Rico
356 { 334, CAMERA_ANTIBANDING_60HZ }, // Mexico
357 { 338, CAMERA_ANTIBANDING_50HZ }, // Jamaica
358 { 340, CAMERA_ANTIBANDING_50HZ }, // Martinique
359 { 342, CAMERA_ANTIBANDING_50HZ }, // Barbados
360 { 346, CAMERA_ANTIBANDING_60HZ }, // Cayman Islands
361 { 350, CAMERA_ANTIBANDING_60HZ }, // Bermuda
362 { 352, CAMERA_ANTIBANDING_50HZ }, // Grenada
363 { 354, CAMERA_ANTIBANDING_60HZ }, // Montserrat
364 { 362, CAMERA_ANTIBANDING_50HZ }, // Netherlands Antilles
365 { 363, CAMERA_ANTIBANDING_60HZ }, // Aruba
366 { 364, CAMERA_ANTIBANDING_60HZ }, // Bahamas
367 { 365, CAMERA_ANTIBANDING_60HZ }, // Anguilla
368 { 366, CAMERA_ANTIBANDING_50HZ }, // Dominica
369 { 368, CAMERA_ANTIBANDING_60HZ }, // Cuba
370 { 370, CAMERA_ANTIBANDING_60HZ }, // Dominican Republic
371 { 372, CAMERA_ANTIBANDING_60HZ }, // Haiti
372 { 401, CAMERA_ANTIBANDING_50HZ }, // Kazakhstan
373 { 402, CAMERA_ANTIBANDING_50HZ }, // Bhutan
374 { 404, CAMERA_ANTIBANDING_50HZ }, // India
375 { 405, CAMERA_ANTIBANDING_50HZ }, // India
376 { 410, CAMERA_ANTIBANDING_50HZ }, // Pakistan
377 { 413, CAMERA_ANTIBANDING_50HZ }, // Sri Lanka
378 { 414, CAMERA_ANTIBANDING_50HZ }, // Myanmar
379 { 415, CAMERA_ANTIBANDING_50HZ }, // Lebanon
380 { 416, CAMERA_ANTIBANDING_50HZ }, // Jordan
381 { 417, CAMERA_ANTIBANDING_50HZ }, // Syria
382 { 418, CAMERA_ANTIBANDING_50HZ }, // Iraq
383 { 419, CAMERA_ANTIBANDING_50HZ }, // Kuwait
384 { 420, CAMERA_ANTIBANDING_60HZ }, // Saudi Arabia
385 { 421, CAMERA_ANTIBANDING_50HZ }, // Yemen
386 { 422, CAMERA_ANTIBANDING_50HZ }, // Oman
387 { 424, CAMERA_ANTIBANDING_50HZ }, // United Arab Emirates
388 { 425, CAMERA_ANTIBANDING_50HZ }, // Israel
389 { 426, CAMERA_ANTIBANDING_50HZ }, // Bahrain
390 { 427, CAMERA_ANTIBANDING_50HZ }, // Qatar
391 { 428, CAMERA_ANTIBANDING_50HZ }, // Mongolia
392 { 429, CAMERA_ANTIBANDING_50HZ }, // Nepal
393 { 430, CAMERA_ANTIBANDING_50HZ }, // United Arab Emirates
394 { 431, CAMERA_ANTIBANDING_50HZ }, // United Arab Emirates
395 { 432, CAMERA_ANTIBANDING_50HZ }, // Iran
396 { 434, CAMERA_ANTIBANDING_50HZ }, // Uzbekistan
397 { 436, CAMERA_ANTIBANDING_50HZ }, // Tajikistan
398 { 437, CAMERA_ANTIBANDING_50HZ }, // Kyrgyz Rep
399 { 438, CAMERA_ANTIBANDING_50HZ }, // Turkmenistan
400 { 440, CAMERA_ANTIBANDING_60HZ }, // Japan
401 { 441, CAMERA_ANTIBANDING_60HZ }, // Japan
402 { 452, CAMERA_ANTIBANDING_50HZ }, // Vietnam
403 { 454, CAMERA_ANTIBANDING_50HZ }, // Hong Kong
404 { 455, CAMERA_ANTIBANDING_50HZ }, // Macao
405 { 456, CAMERA_ANTIBANDING_50HZ }, // Cambodia
406 { 457, CAMERA_ANTIBANDING_50HZ }, // Laos
407 { 460, CAMERA_ANTIBANDING_50HZ }, // China
408 { 466, CAMERA_ANTIBANDING_60HZ }, // Taiwan
409 { 470, CAMERA_ANTIBANDING_50HZ }, // Bangladesh
410 { 472, CAMERA_ANTIBANDING_50HZ }, // Maldives
411 { 502, CAMERA_ANTIBANDING_50HZ }, // Malaysia
412 { 505, CAMERA_ANTIBANDING_50HZ }, // Australia
413 { 510, CAMERA_ANTIBANDING_50HZ }, // Indonesia
414 { 514, CAMERA_ANTIBANDING_50HZ }, // East Timor
415 { 515, CAMERA_ANTIBANDING_60HZ }, // Philippines
416 { 520, CAMERA_ANTIBANDING_50HZ }, // Thailand
417 { 525, CAMERA_ANTIBANDING_50HZ }, // Singapore
418 { 530, CAMERA_ANTIBANDING_50HZ }, // New Zealand
419 { 535, CAMERA_ANTIBANDING_60HZ }, // Guam
420 { 536, CAMERA_ANTIBANDING_50HZ }, // Nauru
421 { 537, CAMERA_ANTIBANDING_50HZ }, // Papua New Guinea
422 { 539, CAMERA_ANTIBANDING_50HZ }, // Tonga
423 { 541, CAMERA_ANTIBANDING_50HZ }, // Vanuatu
424 { 542, CAMERA_ANTIBANDING_50HZ }, // Fiji
425 { 544, CAMERA_ANTIBANDING_60HZ }, // American Samoa
426 { 545, CAMERA_ANTIBANDING_50HZ }, // Kiribati
427 { 546, CAMERA_ANTIBANDING_50HZ }, // New Caledonia
428 { 548, CAMERA_ANTIBANDING_50HZ }, // Cook Islands
429 { 602, CAMERA_ANTIBANDING_50HZ }, // Egypt
430 { 603, CAMERA_ANTIBANDING_50HZ }, // Algeria
431 { 604, CAMERA_ANTIBANDING_50HZ }, // Morocco
432 { 605, CAMERA_ANTIBANDING_50HZ }, // Tunisia
433 { 606, CAMERA_ANTIBANDING_50HZ }, // Libya
434 { 607, CAMERA_ANTIBANDING_50HZ }, // Gambia
435 { 608, CAMERA_ANTIBANDING_50HZ }, // Senegal
436 { 609, CAMERA_ANTIBANDING_50HZ }, // Mauritania
437 { 610, CAMERA_ANTIBANDING_50HZ }, // Mali
438 { 611, CAMERA_ANTIBANDING_50HZ }, // Guinea
439 { 613, CAMERA_ANTIBANDING_50HZ }, // Burkina Faso
440 { 614, CAMERA_ANTIBANDING_50HZ }, // Niger
441 { 616, CAMERA_ANTIBANDING_50HZ }, // Benin
442 { 617, CAMERA_ANTIBANDING_50HZ }, // Mauritius
443 { 618, CAMERA_ANTIBANDING_50HZ }, // Liberia
444 { 619, CAMERA_ANTIBANDING_50HZ }, // Sierra Leone
445 { 620, CAMERA_ANTIBANDING_50HZ }, // Ghana
446 { 621, CAMERA_ANTIBANDING_50HZ }, // Nigeria
447 { 622, CAMERA_ANTIBANDING_50HZ }, // Chad
448 { 623, CAMERA_ANTIBANDING_50HZ }, // Central African Republic
449 { 624, CAMERA_ANTIBANDING_50HZ }, // Cameroon
450 { 625, CAMERA_ANTIBANDING_50HZ }, // Cape Verde
451 { 627, CAMERA_ANTIBANDING_50HZ }, // Equatorial Guinea
452 { 631, CAMERA_ANTIBANDING_50HZ }, // Angola
453 { 633, CAMERA_ANTIBANDING_50HZ }, // Seychelles
454 { 634, CAMERA_ANTIBANDING_50HZ }, // Sudan
455 { 636, CAMERA_ANTIBANDING_50HZ }, // Ethiopia
456 { 637, CAMERA_ANTIBANDING_50HZ }, // Somalia
457 { 638, CAMERA_ANTIBANDING_50HZ }, // Djibouti
458 { 639, CAMERA_ANTIBANDING_50HZ }, // Kenya
459 { 640, CAMERA_ANTIBANDING_50HZ }, // Tanzania
460 { 641, CAMERA_ANTIBANDING_50HZ }, // Uganda
461 { 642, CAMERA_ANTIBANDING_50HZ }, // Burundi
462 { 643, CAMERA_ANTIBANDING_50HZ }, // Mozambique
463 { 645, CAMERA_ANTIBANDING_50HZ }, // Zambia
464 { 646, CAMERA_ANTIBANDING_50HZ }, // Madagascar
465 { 647, CAMERA_ANTIBANDING_50HZ }, // France
466 { 648, CAMERA_ANTIBANDING_50HZ }, // Zimbabwe
467 { 649, CAMERA_ANTIBANDING_50HZ }, // Namibia
468 { 650, CAMERA_ANTIBANDING_50HZ }, // Malawi
469 { 651, CAMERA_ANTIBANDING_50HZ }, // Lesotho
470 { 652, CAMERA_ANTIBANDING_50HZ }, // Botswana
471 { 653, CAMERA_ANTIBANDING_50HZ }, // Swaziland
472 { 654, CAMERA_ANTIBANDING_50HZ }, // Comoros
473 { 655, CAMERA_ANTIBANDING_50HZ }, // South Africa
474 { 657, CAMERA_ANTIBANDING_50HZ }, // Eritrea
475 { 702, CAMERA_ANTIBANDING_60HZ }, // Belize
476 { 704, CAMERA_ANTIBANDING_60HZ }, // Guatemala
477 { 706, CAMERA_ANTIBANDING_60HZ }, // El Salvador
478 { 708, CAMERA_ANTIBANDING_60HZ }, // Honduras
479 { 710, CAMERA_ANTIBANDING_60HZ }, // Nicaragua
480 { 712, CAMERA_ANTIBANDING_60HZ }, // Costa Rica
481 { 714, CAMERA_ANTIBANDING_60HZ }, // Panama
482 { 722, CAMERA_ANTIBANDING_50HZ }, // Argentina
483 { 724, CAMERA_ANTIBANDING_60HZ }, // Brazil
484 { 730, CAMERA_ANTIBANDING_50HZ }, // Chile
485 { 732, CAMERA_ANTIBANDING_60HZ }, // Colombia
486 { 734, CAMERA_ANTIBANDING_60HZ }, // Venezuela
487 { 736, CAMERA_ANTIBANDING_50HZ }, // Bolivia
488 { 738, CAMERA_ANTIBANDING_60HZ }, // Guyana
489 { 740, CAMERA_ANTIBANDING_60HZ }, // Ecuador
490 { 742, CAMERA_ANTIBANDING_50HZ }, // French Guiana
491 { 744, CAMERA_ANTIBANDING_50HZ }, // Paraguay
492 { 746, CAMERA_ANTIBANDING_60HZ }, // Suriname
493 { 748, CAMERA_ANTIBANDING_50HZ }, // Uruguay
494 { 750, CAMERA_ANTIBANDING_50HZ }, // Falkland Islands
495};
496
497#define country_number (sizeof(country_numeric) / sizeof(country_map))
498
499/* Look up pre-sorted antibanding_type table by current MCC. */
500static camera_antibanding_type camera_get_location(void) {
501 char value[PROP_VALUE_MAX];
502 char country_value[PROP_VALUE_MAX];
503 uint32_t country_code, count;
504 memset(value, 0x00, sizeof(value));
505 memset(country_value, 0x00, sizeof(country_value));
506 if (!__system_property_get("gsm.operator.numeric", value)) {
507 return CAMERA_ANTIBANDING_60HZ;
508 }
509 memcpy(country_value, value, 3);
510 country_code = atoi(country_value);
511 LOGD("value:%s, country value:%s, country code:%d\n",
512 value, country_value, country_code);
513 int left = 0;
514 int right = country_number - 1;
515 while (left <= right) {
516 int index = (left + right) >> 1;
517 if (country_numeric[index].country_code == country_code)
518 return country_numeric[index].type;
519 else if (country_numeric[index].country_code > country_code)
520 right = index - 1;
521 else
522 left = index + 1;
523 }
524 return CAMERA_ANTIBANDING_60HZ;
525}
526
527// from camera.h, led_mode_t
528static const str_map flash[] = {
529 { CameraParameters::FLASH_MODE_OFF, LED_MODE_OFF },
530 { CameraParameters::FLASH_MODE_AUTO, LED_MODE_AUTO },
531 { CameraParameters::FLASH_MODE_ON, LED_MODE_ON }
532};
533
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530534// from mm-camera/common/camera.h.
535static const str_map iso[] = {
536 { CameraParameters::ISO_AUTO, CAMERA_ISO_AUTO},
537 { CameraParameters::ISO_HJR, CAMERA_ISO_DEBLUR},
538 { CameraParameters::ISO_100, CAMERA_ISO_100},
539 { CameraParameters::ISO_200, CAMERA_ISO_200},
540 { CameraParameters::ISO_400, CAMERA_ISO_400},
541 { CameraParameters::ISO_800, CAMERA_ISO_800 }
542};
543
544
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800545#define DONT_CARE 0
546static const str_map focus_modes[] = {
Srinivasan Kannan71229622009-12-04 12:05:58 -0800547 { CameraParameters::FOCUS_MODE_AUTO, AF_MODE_AUTO},
548 { CameraParameters::FOCUS_MODE_INFINITY, DONT_CARE },
549 { CameraParameters::FOCUS_MODE_NORMAL, AF_MODE_NORMAL },
550 { CameraParameters::FOCUS_MODE_MACRO, AF_MODE_MACRO }
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800551};
552
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530553static const str_map lensshade[] = {
554 { CameraParameters::LENSSHADE_ENABLE, TRUE },
555 { CameraParameters::LENSSHADE_DISABLE, FALSE }
556};
557
Srinivasan Kannan71229622009-12-04 12:05:58 -0800558struct SensorType {
559 const char *name;
560 int rawPictureWidth;
561 int rawPictureHeight;
562 bool hasAutoFocusSupport;
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800563 int max_supported_snapshot_width;
564 int max_supported_snapshot_height;
Srinivasan Kannan71229622009-12-04 12:05:58 -0800565};
566
567static SensorType sensorTypes[] = {
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800568 { "5mp", 2608, 1960, true, 2592, 1944 },
569 { "3mp", 2064, 1544, false, 2048, 1536 },
570 { "2mp", 3200, 1200, false, 1600, 1200 } };
571
Srinivasan Kannan71229622009-12-04 12:05:58 -0800572
573static SensorType * sensorType;
574
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800575static const str_map picture_formats[] = {
576 {CameraParameters::PIXEL_FORMAT_JPEG, PICTURE_FORMAT_JPEG},
577 {CameraParameters::PIXEL_FORMAT_RAW, PICTURE_FORMAT_RAW}
578};
579
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800580static bool parameter_string_initialized = false;
581static String8 preview_size_values;
582static String8 picture_size_values;
583static String8 antibanding_values;
584static String8 effect_values;
Apurva Rajguru55562b02009-12-03 12:25:35 -0800585static String8 autoexposure_values;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800586static String8 whitebalance_values;
587static String8 flash_values;
588static String8 focus_mode_values;
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530589static String8 iso_values;
590static String8 lensshade_values;
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800591static String8 picture_format_values;
592
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800593
594static String8 create_sizes_str(const camera_size_type *sizes, int len) {
595 String8 str;
596 char buffer[32];
597
598 if (len > 0) {
599 sprintf(buffer, "%dx%d", sizes[0].width, sizes[0].height);
600 str.append(buffer);
601 }
602 for (int i = 1; i < len; i++) {
603 sprintf(buffer, ",%dx%d", sizes[i].width, sizes[i].height);
604 str.append(buffer);
605 }
606 return str;
607}
608
609static String8 create_values_str(const str_map *values, int len) {
610 String8 str;
611
612 if (len > 0) {
613 str.append(values[0].desc);
614 }
615 for (int i = 1; i < len; i++) {
616 str.append(",");
617 str.append(values[i].desc);
618 }
619 return str;
620}
621
622static Mutex singleton_lock;
623static bool singleton_releasing;
624static Condition singleton_wait;
625
626static void receive_camframe_callback(struct msm_frame *frame);
627static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size);
628static void receive_jpeg_callback(jpeg_event_t status);
629static void receive_shutter_callback(common_crop_t *crop);
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800630static void receive_camframetimeout_callback(void);
Mohan Kandra284966d2010-01-05 13:39:15 -0800631static int fb_fd = -1;
632static int32_t mMaxZoom = 0;
633static bool native_get_maxzoom(int camfd, void *pZm);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800634
635QualcommCameraHardware::QualcommCameraHardware()
636 : mParameters(),
637 mCameraRunning(false),
638 mPreviewInitialized(false),
639 mFrameThreadRunning(false),
640 mSnapshotThreadRunning(false),
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800641 mSnapshotFormat(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800642 mReleasedRecordingFrame(false),
643 mPreviewFrameSize(0),
644 mRawSize(0),
645 mCameraControlFd(-1),
646 mAutoFocusThreadRunning(false),
647 mAutoFocusFd(-1),
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800648 mBrightness(0),
Srinivasan Kannanbddfd502010-01-03 17:27:36 -0800649 mSharpness(0),
650 mContrast(0),
651 mSaturation(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800652 mInPreviewCallback(false),
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800653 mUseOverlay(0),
654 mOverlay(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800655 mMsgEnabled(0),
656 mNotifyCallback(0),
657 mDataCallback(0),
658 mDataCallbackTimestamp(0),
Mohan Kandra740cfce2010-01-07 12:58:24 -0800659 mCallbackCookie(0),
660 mDebugFps(0)
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800661{
662 memset(&mDimension, 0, sizeof(mDimension));
663 memset(&mCrop, 0, sizeof(mCrop));
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -0800664 memset(&zoomCropInfo, 0, sizeof(zoom_crop_info));
Mohan Kandra284966d2010-01-05 13:39:15 -0800665 property_get("ro.product.device",mDeviceName," ");
Mohan Kandra740cfce2010-01-07 12:58:24 -0800666 char value[PROPERTY_VALUE_MAX];
667 property_get("persist.debug.sf.showfps", value, "0");
668 mDebugFps = atoi(value);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800669 LOGV("constructor EX");
670}
671
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800672
673//filter Picture sizes based on max width and height
674void QualcommCameraHardware::filterPictureSizes(){
675 int i;
676 for(i=0;i<PICTURE_SIZE_COUNT;i++){
677 if(((picture_sizes[i].width <=
678 sensorType->max_supported_snapshot_width) &&
679 (picture_sizes[i].height <=
680 sensorType->max_supported_snapshot_height))){
681 picture_sizes_ptr = picture_sizes + i;
682 supportedPictureSizesCount = PICTURE_SIZE_COUNT - i ;
683 return ;
684 }
685 }
686}
687
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800688void QualcommCameraHardware::initDefaultParameters()
689{
690 LOGV("initDefaultParameters E");
691
692 // Initialize constant parameter strings. This will happen only once in the
693 // lifetime of the mediaserver process.
694 if (!parameter_string_initialized) {
Srinivasan Kannan71229622009-12-04 12:05:58 -0800695 findSensorType();
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800696 antibanding_values = create_values_str(
697 antibanding, sizeof(antibanding) / sizeof(str_map));
698 effect_values = create_values_str(
699 effects, sizeof(effects) / sizeof(str_map));
Apurva Rajguru55562b02009-12-03 12:25:35 -0800700 autoexposure_values = create_values_str(
701 autoexposure, sizeof(autoexposure) / sizeof(str_map));
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800702 whitebalance_values = create_values_str(
703 whitebalance, sizeof(whitebalance) / sizeof(str_map));
704 preview_size_values = create_sizes_str(
705 preview_sizes, PREVIEW_SIZE_COUNT);
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800706 //filter picture sizes
707 filterPictureSizes();
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800708 picture_size_values = create_sizes_str(
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800709 picture_sizes_ptr, supportedPictureSizesCount);
710
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800711 flash_values = create_values_str(
712 flash, sizeof(flash) / sizeof(str_map));
Srinivasan Kannan71229622009-12-04 12:05:58 -0800713 if(sensorType->hasAutoFocusSupport){
714 focus_mode_values = create_values_str(
715 focus_modes, sizeof(focus_modes) / sizeof(str_map));
716 }
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530717 iso_values = create_values_str(
718 iso,sizeof(iso)/sizeof(str_map));
719 lensshade_values = create_values_str(
720 lensshade,sizeof(lensshade)/sizeof(str_map));
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800721 picture_format_values = create_values_str(
722 picture_formats, sizeof(picture_formats)/sizeof(str_map));
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800723 parameter_string_initialized = true;
724 }
725
726 const camera_size_type *ps = &preview_sizes[DEFAULT_PREVIEW_SETTING];
727 mParameters.setPreviewSize(ps->width, ps->height);
728 mDimension.display_width = ps->width;
729 mDimension.display_height = ps->height;
730 mParameters.setPreviewFrameRate(15);
731 mParameters.setPreviewFormat("yuv420sp"); // informative
732
733 mParameters.setPictureSize(DEFAULT_PICTURE_WIDTH, DEFAULT_PICTURE_HEIGHT);
734 mParameters.setPictureFormat("jpeg"); // informative
735
736 mParameters.set(CameraParameters::KEY_JPEG_QUALITY, "100"); // max quality
737 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH,
738 THUMBNAIL_WIDTH_STR); // informative
739 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT,
740 THUMBNAIL_HEIGHT_STR); // informative
Srinivasan Kannan80d878f2009-12-18 15:06:02 -0800741 mDimension.ui_thumbnail_width =
742 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].width;
743 mDimension.ui_thumbnail_height =
744 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800745 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, "90");
746
747 mParameters.set(CameraParameters::KEY_ANTIBANDING,
748 CameraParameters::ANTIBANDING_AUTO);
749 mParameters.set(CameraParameters::KEY_EFFECT,
750 CameraParameters::EFFECT_NONE);
Apurva Rajguru55562b02009-12-03 12:25:35 -0800751 mParameters.set(CameraParameters::KEY_AUTO_EXPOSURE,
752 CameraParameters::AUTO_EXPOSURE_FRAME_AVG);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800753 mParameters.set(CameraParameters::KEY_WHITE_BALANCE,
754 CameraParameters::WHITE_BALANCE_AUTO);
755 mParameters.set(CameraParameters::KEY_FOCUS_MODE,
756 CameraParameters::FOCUS_MODE_AUTO);
757
758 mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES,
759 preview_size_values.string());
760 mParameters.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES,
761 picture_size_values.string());
762 mParameters.set(CameraParameters::KEY_SUPPORTED_ANTIBANDING,
763 antibanding_values);
764 mParameters.set(CameraParameters::KEY_SUPPORTED_EFFECTS, effect_values);
Apurva Rajguru55562b02009-12-03 12:25:35 -0800765 mParameters.set(CameraParameters::KEY_SUPPORTED_AUTO_EXPOSURE, autoexposure_values);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800766 mParameters.set(CameraParameters::KEY_SUPPORTED_WHITE_BALANCE,
767 whitebalance_values);
768 mParameters.set(CameraParameters::KEY_SUPPORTED_FOCUS_MODES,
769 focus_mode_values);
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800770 mParameters.set(CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS,
771 picture_format_values);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800772
773 if (mSensorInfo.flash_enabled) {
774 mParameters.set(CameraParameters::KEY_FLASH_MODE,
775 CameraParameters::FLASH_MODE_OFF);
776 mParameters.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES,
777 flash_values);
778 }
779
Srinivasan Kannanbddfd502010-01-03 17:27:36 -0800780 mParameters.set(CameraParameters::KEY_MAX_SHARPNESS,
781 CAMERA_MAX_SHARPNESS);
782 mParameters.set(CameraParameters::KEY_MAX_CONTRAST,
783 CAMERA_MAX_CONTRAST);
784 mParameters.set(CameraParameters::KEY_MAX_SATURATION,
785 CAMERA_MAX_SATURATION);
786
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530787 mParameters.set("luma-adaptation", "18");
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800788 mParameters.set("zoom-supported", "true");
789 mParameters.set("max-zoom", MAX_ZOOM_LEVEL);
790 mParameters.set("zoom", 0);
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800791 mParameters.set(CameraParameters::KEY_PICTURE_FORMAT,
792 CameraParameters::PIXEL_FORMAT_JPEG);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800793
Kiran Kumar H N595970b2010-01-12 10:41:09 -0800794 mParameters.set(CameraParameters::KEY_SHARPNESS,
795 CAMERA_DEF_SHARPNESS);
796 mParameters.set(CameraParameters::KEY_CONTRAST,
797 CAMERA_DEF_CONTRAST);
798 mParameters.set(CameraParameters::KEY_SATURATION,
799 CAMERA_DEF_SATURATION);
800
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530801 mParameters.set(CameraParameters::KEY_ISO_MODE,
802 CameraParameters::ISO_AUTO);
803 mParameters.set(CameraParameters::KEY_LENSSHADE,
804 CameraParameters::LENSSHADE_ENABLE);
805 mParameters.set(CameraParameters::KEY_SUPPORTED_ISO_MODES,
806 iso_values);
807 mParameters.set(CameraParameters::KEY_SUPPORTED_LENSSHADE_MODES,
808 lensshade_values);
809
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800810 if (setParameters(mParameters) != NO_ERROR) {
811 LOGE("Failed to set default parameters?!");
812 }
813
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -0800814 mUseOverlay = useOverlay();
815
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800816 /* Initialize the camframe_timeout_flag*/
817 Mutex::Autolock l(&mCamframeTimeoutLock);
818 camframe_timeout_flag = FALSE;
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -0800819 mPostViewHeap = NULL;
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800820
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800821 LOGV("initDefaultParameters X");
822}
823
Srinivasan Kannan71229622009-12-04 12:05:58 -0800824void QualcommCameraHardware::findSensorType(){
825 mDimension.picture_width = DEFAULT_PICTURE_WIDTH;
826 mDimension.picture_height = DEFAULT_PICTURE_HEIGHT;
827 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
828 sizeof(cam_ctrl_dimension_t), &mDimension);
829 if (ret) {
830 unsigned int i;
831 for (i = 0; i < sizeof(sensorTypes) / sizeof(SensorType); i++) {
832 if (sensorTypes[i].rawPictureHeight
833 == mDimension.raw_picture_height) {
834 sensorType = sensorTypes + i;
835 return;
836 }
837 }
838 }
839 //default to 5 mp
840 sensorType = sensorTypes;
841 return;
842}
843
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800844#define ROUND_TO_PAGE(x) (((x)+0xfff)&~0xfff)
845
846bool QualcommCameraHardware::startCamera()
847{
848 LOGV("startCamera E");
849#if DLOPEN_LIBMMCAMERA
850 libmmcamera = ::dlopen("liboemcamera.so", RTLD_NOW);
851 LOGV("loading liboemcamera at %p", libmmcamera);
852 if (!libmmcamera) {
853 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
854 return false;
855 }
856
857 *(void **)&LINK_cam_frame =
858 ::dlsym(libmmcamera, "cam_frame");
859 *(void **)&LINK_camframe_terminate =
860 ::dlsym(libmmcamera, "camframe_terminate");
861
862 *(void **)&LINK_jpeg_encoder_init =
863 ::dlsym(libmmcamera, "jpeg_encoder_init");
864
865 *(void **)&LINK_jpeg_encoder_encode =
866 ::dlsym(libmmcamera, "jpeg_encoder_encode");
867
868 *(void **)&LINK_jpeg_encoder_join =
869 ::dlsym(libmmcamera, "jpeg_encoder_join");
870
871 *(void **)&LINK_mmcamera_camframe_callback =
872 ::dlsym(libmmcamera, "mmcamera_camframe_callback");
873
874 *LINK_mmcamera_camframe_callback = receive_camframe_callback;
875
876 *(void **)&LINK_mmcamera_jpegfragment_callback =
877 ::dlsym(libmmcamera, "mmcamera_jpegfragment_callback");
878
879 *LINK_mmcamera_jpegfragment_callback = receive_jpeg_fragment_callback;
880
881 *(void **)&LINK_mmcamera_jpeg_callback =
882 ::dlsym(libmmcamera, "mmcamera_jpeg_callback");
883
884 *LINK_mmcamera_jpeg_callback = receive_jpeg_callback;
885
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800886 *(void **)&LINK_camframe_timeout_callback =
887 ::dlsym(libmmcamera, "camframe_timeout_callback");
888
889 *LINK_camframe_timeout_callback = receive_camframetimeout_callback;
890
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800891/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800892 *(void **)&LINK_mmcamera_shutter_callback =
893 ::dlsym(libmmcamera, "mmcamera_shutter_callback");
894
895 *LINK_mmcamera_shutter_callback = receive_shutter_callback;
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800896*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800897 *(void**)&LINK_jpeg_encoder_setMainImageQuality =
898 ::dlsym(libmmcamera, "jpeg_encoder_setMainImageQuality");
Kiran Kumar H N8861f302010-01-05 12:01:41 -0800899
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800900 *(void**)&LINK_jpeg_encoder_setThumbnailQuality =
901 ::dlsym(libmmcamera, "jpeg_encoder_setThumbnailQuality");
902
903 *(void**)&LINK_jpeg_encoder_setRotation =
904 ::dlsym(libmmcamera, "jpeg_encoder_setRotation");
905
Kiran Kumar H N8861f302010-01-05 12:01:41 -0800906/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800907 *(void**)&LINK_jpeg_encoder_setLocation =
908 ::dlsym(libmmcamera, "jpeg_encoder_setLocation");
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800909*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800910 *(void **)&LINK_cam_conf =
911 ::dlsym(libmmcamera, "cam_conf");
912
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800913/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800914 *(void **)&LINK_default_sensor_get_snapshot_sizes =
915 ::dlsym(libmmcamera, "default_sensor_get_snapshot_sizes");
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800916*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800917 *(void **)&LINK_launch_cam_conf_thread =
918 ::dlsym(libmmcamera, "launch_cam_conf_thread");
919
920 *(void **)&LINK_release_cam_conf_thread =
921 ::dlsym(libmmcamera, "release_cam_conf_thread");
922
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800923/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800924 *(void **)&LINK_zoom_crop_upscale =
925 ::dlsym(libmmcamera, "zoom_crop_upscale");
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800926*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800927
928#else
929 mmcamera_camframe_callback = receive_camframe_callback;
930 mmcamera_jpegfragment_callback = receive_jpeg_fragment_callback;
931 mmcamera_jpeg_callback = receive_jpeg_callback;
932 mmcamera_shutter_callback = receive_shutter_callback;
933#endif // DLOPEN_LIBMMCAMERA
934
935 /* The control thread is in libcamera itself. */
936 mCameraControlFd = open(MSM_CAMERA_CONTROL, O_RDWR);
Kiran Kumar H N494c9fc2010-01-07 15:55:15 -0800937 if (mCameraControlFd <= 0) {
938 if( mCameraControlFd == 0 ) {
939 /* This should not happen. But if and when it
940 * happens, we should not be using fd 0 for issuing
941 * any IOCTL calls to camera driver since the
942 * behaviour is undeterministic. Hence adding a
943 * workaround to deal with this issue */
944 LOGD(" Returned FD is 0....open again ");
945 mCameraControlFd = open(MSM_CAMERA_CONTROL, O_RDWR);
946 }
947 if (mCameraControlFd < 0) {
948 LOGE("startCamera X: %s open failed: %s!",
949 MSM_CAMERA_CONTROL,
950 strerror(errno));
951 return false;
952 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800953 }
954
Mohan Kandra284966d2010-01-05 13:39:15 -0800955 if(strncmp(mDeviceName,"msm7630", 7)){
956 fb_fd = open("/dev/graphics/fb0", O_RDWR);
957 if (fb_fd < 0) {
958 LOGE("startCamera: fb0 open failed: %s!", strerror(errno));
959 return FALSE;
960 }
961 }
962
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800963 /* This will block until the control thread is launched. After that, sensor
964 * information becomes available.
965 */
966
967 if (LINK_launch_cam_conf_thread()) {
968 LOGE("failed to launch the camera config thread");
969 return false;
970 }
971
972 memset(&mSensorInfo, 0, sizeof(mSensorInfo));
973 if (ioctl(mCameraControlFd,
974 MSM_CAM_IOCTL_GET_SENSOR_INFO,
975 &mSensorInfo) < 0)
976 LOGW("%s: cannot retrieve sensor info!", __FUNCTION__);
977 else
978 LOGI("%s: camsensor name %s, flash %d", __FUNCTION__,
979 mSensorInfo.name, mSensorInfo.flash_enabled);
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800980/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800981 picture_sizes = LINK_default_sensor_get_snapshot_sizes(&PICTURE_SIZE_COUNT);
982 if (!picture_sizes || !PICTURE_SIZE_COUNT) {
983 LOGE("startCamera X: could not get snapshot sizes");
984 return false;
985 }
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800986*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800987 LOGV("startCamera X");
988 return true;
989}
990
991status_t QualcommCameraHardware::dump(int fd,
992 const Vector<String16>& args) const
993{
994 const size_t SIZE = 256;
995 char buffer[SIZE];
996 String8 result;
997
998 // Dump internal primitives.
999 result.append("QualcommCameraHardware::dump");
1000 snprintf(buffer, 255, "mMsgEnabled (%d)\n", mMsgEnabled);
1001 result.append(buffer);
1002 int width, height;
1003 mParameters.getPreviewSize(&width, &height);
1004 snprintf(buffer, 255, "preview width(%d) x height (%d)\n", width, height);
1005 result.append(buffer);
1006 mParameters.getPictureSize(&width, &height);
1007 snprintf(buffer, 255, "raw width(%d) x height (%d)\n", width, height);
1008 result.append(buffer);
1009 snprintf(buffer, 255,
1010 "preview frame size(%d), raw size (%d), jpeg size (%d) "
1011 "and jpeg max size (%d)\n", mPreviewFrameSize, mRawSize,
1012 mJpegSize, mJpegMaxSize);
1013 result.append(buffer);
1014 write(fd, result.string(), result.size());
1015
1016 // Dump internal objects.
Mohan Kandra284966d2010-01-05 13:39:15 -08001017 if (mCameraPreviewHeap != 0) {
1018 mCameraPreviewHeap->dump(fd, args);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001019 }
1020 if (mRawHeap != 0) {
1021 mRawHeap->dump(fd, args);
1022 }
1023 if (mJpegHeap != 0) {
1024 mJpegHeap->dump(fd, args);
1025 }
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001026 if(mRawSnapshotAshmemHeap != 0 ){
1027 mRawSnapshotAshmemHeap->dump(fd, args);
1028 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001029 mParameters.dump(fd, args);
1030 return NO_ERROR;
1031}
1032
Mohan Kandra284966d2010-01-05 13:39:15 -08001033static bool native_get_maxzoom(int camfd, void *pZm)
1034{
1035 LOGV("native_get_maxzoom E");
1036
1037 struct msm_ctrl_cmd ctrlCmd;
1038 int32_t *pZoom = (int32_t *)pZm;
1039
1040 ctrlCmd.type = CAMERA_GET_PARM_MAXZOOM;
1041 ctrlCmd.timeout_ms = 5000;
1042 ctrlCmd.length = sizeof(int32_t);
1043 ctrlCmd.value = pZoom;
1044 ctrlCmd.resp_fd = camfd;
1045
1046 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1047 LOGE("native_get_maxzoom: ioctl fd %d error %s",
1048 camfd,
1049 strerror(errno));
1050 return false;
1051 }
1052 LOGE("ctrlCmd.value = %d", *(int32_t *)ctrlCmd.value);
1053 memcpy(pZoom, (int32_t *)ctrlCmd.value, sizeof(int32_t));
1054
1055 LOGV("native_get_maxzoom X");
1056 return true;
1057}
1058
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001059static bool native_set_afmode(int camfd, isp3a_af_mode_t af_type)
1060{
1061 int rc;
1062 struct msm_ctrl_cmd ctrlCmd;
1063
1064 ctrlCmd.timeout_ms = 5000;
1065 ctrlCmd.type = CAMERA_SET_PARM_AUTO_FOCUS;
1066 ctrlCmd.length = sizeof(af_type);
1067 ctrlCmd.value = &af_type;
1068 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1069
1070 if ((rc = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0)
1071 LOGE("native_set_afmode: ioctl fd %d error %s\n",
1072 camfd,
1073 strerror(errno));
1074
1075 LOGV("native_set_afmode: ctrlCmd.status == %d\n", ctrlCmd.status);
1076 return rc >= 0 && ctrlCmd.status == CAMERA_EXIT_CB_DONE;
1077}
1078
1079static bool native_cancel_afmode(int camfd, int af_fd)
1080{
1081 int rc;
1082 struct msm_ctrl_cmd ctrlCmd;
1083
1084 ctrlCmd.timeout_ms = 0;
1085 ctrlCmd.type = CAMERA_AUTO_FOCUS_CANCEL;
1086 ctrlCmd.length = 0;
1087 ctrlCmd.value = NULL;
1088 ctrlCmd.resp_fd = -1; // there's no response fd
1089
1090 if ((rc = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND_2, &ctrlCmd)) < 0)
1091 {
1092 LOGE("native_cancel_afmode: ioctl fd %d error %s\n",
1093 camfd,
1094 strerror(errno));
1095 return false;
1096 }
1097
1098 return true;
1099}
1100
1101static bool native_start_preview(int camfd)
1102{
1103 struct msm_ctrl_cmd ctrlCmd;
1104
1105 ctrlCmd.timeout_ms = 5000;
1106 ctrlCmd.type = CAMERA_START_PREVIEW;
1107 ctrlCmd.length = 0;
1108 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1109
1110 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1111 LOGE("native_start_preview: MSM_CAM_IOCTL_CTRL_COMMAND fd %d error %s",
1112 camfd,
1113 strerror(errno));
1114 return false;
1115 }
1116
1117 return true;
1118}
1119
1120static bool native_get_picture (int camfd, common_crop_t *crop)
1121{
1122 struct msm_ctrl_cmd ctrlCmd;
1123
1124 ctrlCmd.timeout_ms = 5000;
1125 ctrlCmd.length = sizeof(common_crop_t);
1126 ctrlCmd.value = crop;
1127
1128 if(ioctl(camfd, MSM_CAM_IOCTL_GET_PICTURE, &ctrlCmd) < 0) {
1129 LOGE("native_get_picture: MSM_CAM_IOCTL_GET_PICTURE fd %d error %s",
1130 camfd,
1131 strerror(errno));
1132 return false;
1133 }
1134
1135 LOGV("crop: in1_w %d", crop->in1_w);
1136 LOGV("crop: in1_h %d", crop->in1_h);
1137 LOGV("crop: out1_w %d", crop->out1_w);
1138 LOGV("crop: out1_h %d", crop->out1_h);
1139
1140 LOGV("crop: in2_w %d", crop->in2_w);
1141 LOGV("crop: in2_h %d", crop->in2_h);
1142 LOGV("crop: out2_w %d", crop->out2_w);
1143 LOGV("crop: out2_h %d", crop->out2_h);
1144
1145 LOGV("crop: update %d", crop->update_flag);
1146
1147 return true;
1148}
1149
1150static bool native_stop_preview(int camfd)
1151{
1152 struct msm_ctrl_cmd ctrlCmd;
1153 ctrlCmd.timeout_ms = 5000;
1154 ctrlCmd.type = CAMERA_STOP_PREVIEW;
1155 ctrlCmd.length = 0;
1156 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1157
1158 if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1159 LOGE("native_stop_preview: ioctl fd %d error %s",
1160 camfd,
1161 strerror(errno));
1162 return false;
1163 }
1164
1165 return true;
1166}
1167
1168static bool native_prepare_snapshot(int camfd)
1169{
1170 int ioctlRetVal = true;
1171 struct msm_ctrl_cmd ctrlCmd;
1172
1173 ctrlCmd.timeout_ms = 1000;
1174 ctrlCmd.type = CAMERA_PREPARE_SNAPSHOT;
1175 ctrlCmd.length = 0;
1176 ctrlCmd.value = NULL;
1177 ctrlCmd.resp_fd = camfd;
1178
1179 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1180 LOGE("native_prepare_snapshot: ioctl fd %d error %s",
1181 camfd,
1182 strerror(errno));
1183 return false;
1184 }
1185 return true;
1186}
1187
1188static bool native_start_snapshot(int camfd)
1189{
1190 struct msm_ctrl_cmd ctrlCmd;
1191
1192 ctrlCmd.timeout_ms = 5000;
1193 ctrlCmd.type = CAMERA_START_SNAPSHOT;
1194 ctrlCmd.length = 0;
1195 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1196
1197 if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1198 LOGE("native_start_snapshot: ioctl fd %d error %s",
1199 camfd,
1200 strerror(errno));
1201 return false;
1202 }
1203
1204 return true;
1205}
1206
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001207static bool native_start_raw_snapshot(int camfd)
1208{
1209 int ret;
1210 struct msm_ctrl_cmd ctrlCmd;
1211
1212 ctrlCmd.timeout_ms = 1000;
1213 ctrlCmd.type = CAMERA_START_RAW_SNAPSHOT;
1214 ctrlCmd.length = 0;
1215 ctrlCmd.value = NULL;
1216 ctrlCmd.resp_fd = camfd;
1217
1218 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1219 LOGE("native_start_raw_snapshot: ioctl failed. ioctl return value "\
1220 "is %d \n", ret);
1221 return false;
1222 }
1223 return true;
1224}
1225
1226
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001227static bool native_stop_snapshot (int camfd)
1228{
1229 struct msm_ctrl_cmd ctrlCmd;
1230
1231 ctrlCmd.timeout_ms = 0;
1232 ctrlCmd.type = CAMERA_STOP_SNAPSHOT;
1233 ctrlCmd.length = 0;
1234 ctrlCmd.resp_fd = -1;
1235
1236 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND_2, &ctrlCmd) < 0) {
1237 LOGE("native_stop_snapshot: ioctl fd %d error %s",
1238 camfd,
1239 strerror(errno));
1240 return false;
1241 }
1242
1243 return true;
1244}
1245
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001246static rat_t latitude[3];
1247static rat_t longitude[3];
1248static char lonref[2];
1249static char latref[2];
1250static char dateTime[20];
1251static rat_t altitude;
1252
1253static void addExifTag(exif_tag_id_t tagid, exif_tag_type_t type,
1254 uint32_t count, uint8_t copy, void *data) {
1255
1256 if(exif_table_numEntries == MAX_EXIF_TABLE_ENTRIES) {
1257 LOGE("Number of entries exceeded limit");
1258 return;
1259 }
1260
1261 int index = exif_table_numEntries;
1262 exif_data[index].tag_id = tagid;
1263 exif_data[index].tag_entry.type = type;
1264 exif_data[index].tag_entry.count = count;
1265 exif_data[index].tag_entry.copy = copy;
1266 if((type == EXIF_RATIONAL) && (count > 1))
1267 exif_data[index].tag_entry.data._rats = (rat_t *)data;
1268 if((type == EXIF_RATIONAL) && (count == 1))
1269 exif_data[index].tag_entry.data._rat = *(rat_t *)data;
1270 else if(type == EXIF_ASCII)
1271 exif_data[index].tag_entry.data._ascii = (char *)data;
1272 else if(type == EXIF_BYTE)
1273 exif_data[index].tag_entry.data._byte = *(uint8_t *)data;
1274
1275 // Increase number of entries
1276 exif_table_numEntries++;
1277}
1278
1279static void parseLatLong(const char *latlonString, int *pDegrees,
1280 int *pMinutes, int *pSeconds ) {
1281
1282 double value = atof(latlonString);
1283 value = fabs(value);
1284 int degrees = (int) value;
1285
1286 double remainder = value - degrees;
1287 int minutes = (int) (remainder * 60);
1288 int seconds = (int) (((remainder * 60) - minutes) * 60 * 1000);
1289
1290 *pDegrees = degrees;
1291 *pMinutes = minutes;
1292 *pSeconds = seconds;
1293}
1294
1295static void setLatLon(exif_tag_id_t tag, const char *latlonString) {
1296
1297 int degrees, minutes, seconds;
1298
1299 parseLatLong(latlonString, &degrees, &minutes, &seconds);
1300
1301 rat_t value[3] = { {degrees, 1},
1302 {minutes, 1},
1303 {seconds, 1000} };
1304
1305 if(tag == EXIFTAGID_GPS_LATITUDE) {
1306 memcpy(latitude, value, sizeof(latitude));
1307 addExifTag(EXIFTAGID_GPS_LATITUDE, EXIF_RATIONAL, 3,
1308 1, (void *)latitude);
1309 } else {
1310 memcpy(longitude, value, sizeof(longitude));
1311 addExifTag(EXIFTAGID_GPS_LONGITUDE, EXIF_RATIONAL, 3,
1312 1, (void *)longitude);
1313 }
1314}
1315
1316void QualcommCameraHardware::setGpsParameters() {
1317 const char *str = NULL;
1318
1319 //Set Latitude
1320 str = mParameters.get(CameraParameters::KEY_GPS_LATITUDE);
1321 if(str != NULL) {
1322 setLatLon(EXIFTAGID_GPS_LATITUDE, str);
1323 //set Latitude Ref
1324 str = NULL;
1325 str = mParameters.get(CameraParameters::KEY_GPS_LATITUDE_REF);
1326 if(str != NULL) {
1327 strncpy(latref, str, 1);
1328 latref[1] = '\0';
1329 addExifTag(EXIFTAGID_GPS_LATITUDE_REF, EXIF_ASCII, 2,
1330 1, (void *)latref);
1331 }
1332 }
1333
1334 //set Longitude
1335 str = NULL;
1336 str = mParameters.get(CameraParameters::KEY_GPS_LONGITUDE);
1337 if(str != NULL) {
1338 setLatLon(EXIFTAGID_GPS_LONGITUDE, str);
1339 //set Longitude Ref
1340 str = NULL;
1341 str = mParameters.get(CameraParameters::KEY_GPS_LONGITUDE_REF);
1342 if(str != NULL) {
1343 strncpy(lonref, str, 1);
1344 lonref[1] = '\0';
1345 addExifTag(EXIFTAGID_GPS_LONGITUDE_REF, EXIF_ASCII, 2,
1346 1, (void *)lonref);
1347 }
1348 }
1349
1350 //set Altitude
1351 str = NULL;
1352 str = mParameters.get(CameraParameters::KEY_GPS_ALTITUDE);
1353 if(str != NULL) {
1354 int value = atoi(str);
1355 rat_t alt_value = {value, 1000};
1356 memcpy(&altitude, &alt_value, sizeof(altitude));
1357 addExifTag(EXIFTAGID_GPS_ALTITUDE, EXIF_RATIONAL, 1,
1358 1, (void *)&altitude);
1359 //set AltitudeRef
1360 int ref = mParameters.getInt(CameraParameters::KEY_GPS_ALTITUDE_REF);
1361 if( !(ref < 0 || ref > 1) )
1362 addExifTag(EXIFTAGID_GPS_ALTITUDE_REF, EXIF_BYTE, 1,
1363 1, (void *)&ref);
1364 }
1365
1366
1367}
1368
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001369bool QualcommCameraHardware::native_jpeg_encode(void)
1370{
1371 int jpeg_quality = mParameters.getInt("jpeg-quality");
1372 if (jpeg_quality >= 0) {
1373 LOGV("native_jpeg_encode, current jpeg main img quality =%d",
1374 jpeg_quality);
1375 if(!LINK_jpeg_encoder_setMainImageQuality(jpeg_quality)) {
1376 LOGE("native_jpeg_encode set jpeg-quality failed");
1377 return false;
1378 }
1379 }
1380
1381 int thumbnail_quality = mParameters.getInt("jpeg-thumbnail-quality");
1382 if (thumbnail_quality >= 0) {
1383 LOGV("native_jpeg_encode, current jpeg thumbnail quality =%d",
1384 thumbnail_quality);
1385 if(!LINK_jpeg_encoder_setThumbnailQuality(thumbnail_quality)) {
1386 LOGE("native_jpeg_encode set thumbnail-quality failed");
1387 return false;
1388 }
1389 }
1390
1391 int rotation = mParameters.getInt("rotation");
1392 if (rotation >= 0) {
1393 LOGV("native_jpeg_encode, rotation = %d", rotation);
1394 if(!LINK_jpeg_encoder_setRotation(rotation)) {
1395 LOGE("native_jpeg_encode set rotation failed");
1396 return false;
1397 }
1398 }
1399
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001400// jpeg_set_location();
1401 if(mParameters.getInt(CameraParameters::KEY_GPS_STATUS) == 1) {
1402 setGpsParameters();
1403 }
1404 //set TimeStamp
1405 const char *str = mParameters.get(CameraParameters::KEY_EXIF_DATETIME);
1406 if(str != NULL) {
1407 strncpy(dateTime, str, 19);
1408 dateTime[19] = '\0';
1409 addExifTag(EXIFTAGID_EXIF_DATE_TIME_ORIGINAL, EXIF_ASCII,
1410 20, 1, (void *)dateTime);
1411 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001412
1413 if (!LINK_jpeg_encoder_encode(&mDimension,
1414 (uint8_t *)mThumbnailHeap->mHeap->base(),
1415 mThumbnailHeap->mHeap->getHeapID(),
1416 (uint8_t *)mRawHeap->mHeap->base(),
1417 mRawHeap->mHeap->getHeapID(),
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001418 &mCrop, exif_data, exif_table_numEntries)) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001419 LOGE("native_jpeg_encode: jpeg_encoder_encode failed.");
1420 return false;
1421 }
1422 return true;
1423}
1424
1425bool QualcommCameraHardware::native_set_parm(
1426 cam_ctrl_type type, uint16_t length, void *value)
1427{
1428 struct msm_ctrl_cmd ctrlCmd;
1429
1430 ctrlCmd.timeout_ms = 5000;
1431 ctrlCmd.type = (uint16_t)type;
1432 ctrlCmd.length = length;
1433 // FIXME: this will be put in by the kernel
1434 ctrlCmd.resp_fd = mCameraControlFd;
1435 ctrlCmd.value = value;
1436
1437 LOGV("%s: fd %d, type %d, length %d", __FUNCTION__,
1438 mCameraControlFd, type, length);
1439 if (ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0 ||
1440 ctrlCmd.status != CAM_CTRL_SUCCESS) {
1441 LOGE("%s: error (%s): fd %d, type %d, length %d, status %d",
1442 __FUNCTION__, strerror(errno),
1443 mCameraControlFd, type, length, ctrlCmd.status);
1444 return false;
1445 }
1446 return true;
1447}
1448
1449void QualcommCameraHardware::jpeg_set_location()
1450{
1451 bool encode_location = true;
1452 camera_position_type pt;
1453
1454#define PARSE_LOCATION(what,type,fmt,desc) do { \
1455 pt.what = 0; \
1456 const char *what##_str = mParameters.get("gps-"#what); \
1457 LOGV("GPS PARM %s --> [%s]", "gps-"#what, what##_str); \
1458 if (what##_str) { \
1459 type what = 0; \
1460 if (sscanf(what##_str, fmt, &what) == 1) \
1461 pt.what = what; \
1462 else { \
1463 LOGE("GPS " #what " %s could not" \
1464 " be parsed as a " #desc, what##_str); \
1465 encode_location = false; \
1466 } \
1467 } \
1468 else { \
1469 LOGV("GPS " #what " not specified: " \
1470 "defaulting to zero in EXIF header."); \
1471 encode_location = false; \
1472 } \
1473 } while(0)
1474
1475 PARSE_LOCATION(timestamp, long, "%ld", "long");
1476 if (!pt.timestamp) pt.timestamp = time(NULL);
1477 PARSE_LOCATION(altitude, short, "%hd", "short");
1478 PARSE_LOCATION(latitude, double, "%lf", "double float");
1479 PARSE_LOCATION(longitude, double, "%lf", "double float");
1480
1481#undef PARSE_LOCATION
1482
1483 if (encode_location) {
1484 LOGD("setting image location ALT %d LAT %lf LON %lf",
1485 pt.altitude, pt.latitude, pt.longitude);
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001486/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001487 if (!LINK_jpeg_encoder_setLocation(&pt)) {
1488 LOGE("jpeg_set_location: LINK_jpeg_encoder_setLocation failed.");
1489 }
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001490*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001491 }
1492 else LOGV("not setting image location");
1493}
1494
1495void QualcommCameraHardware::runFrameThread(void *data)
1496{
1497 LOGV("runFrameThread E");
1498
1499 int cnt;
1500
1501#if DLOPEN_LIBMMCAMERA
1502 // We need to maintain a reference to libqcamera.so for the duration of the
1503 // frame thread, because we do not know when it will exit relative to the
1504 // lifetime of this object. We do not want to dlclose() libqcamera while
1505 // LINK_cam_frame is still running.
1506 void *libhandle = ::dlopen("liboemcamera.so", RTLD_NOW);
1507 LOGV("FRAME: loading libqcamera at %p", libhandle);
1508 if (!libhandle) {
1509 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
1510 }
1511 if (libhandle)
1512#endif
1513 {
1514 LINK_cam_frame(data);
1515 }
1516
Mohan Kandra284966d2010-01-05 13:39:15 -08001517 mCameraPreviewHeap.clear();
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08001518 if(strncmp(mDeviceName,"msm7630", 7)) {
1519 mPreviewHeap.clear();
1520 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001521#if DLOPEN_LIBMMCAMERA
1522 if (libhandle) {
1523 ::dlclose(libhandle);
1524 LOGV("FRAME: dlclose(libqcamera)");
1525 }
1526#endif
1527
1528 mFrameThreadWaitLock.lock();
1529 mFrameThreadRunning = false;
1530 mFrameThreadWait.signal();
1531 mFrameThreadWaitLock.unlock();
1532
1533 LOGV("runFrameThread X");
1534}
1535
1536void *frame_thread(void *user)
1537{
1538 LOGD("frame_thread E");
1539 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
1540 if (obj != 0) {
1541 obj->runFrameThread(user);
1542 }
1543 else LOGW("not starting frame thread: the object went away!");
1544 LOGD("frame_thread X");
1545 return NULL;
1546}
1547
1548bool QualcommCameraHardware::initPreview()
1549{
1550 // See comments in deinitPreview() for why we have to wait for the frame
1551 // thread here, and why we can't use pthread_join().
1552 int previewWidth, previewHeight;
1553 mParameters.getPreviewSize(&previewWidth, &previewHeight);
1554 LOGI("initPreview E: preview size=%dx%d", previewWidth, previewHeight);
1555 mFrameThreadWaitLock.lock();
1556 while (mFrameThreadRunning) {
1557 LOGV("initPreview: waiting for old frame thread to complete.");
1558 mFrameThreadWait.wait(mFrameThreadWaitLock);
1559 LOGV("initPreview: old frame thread completed.");
1560 }
1561 mFrameThreadWaitLock.unlock();
1562
1563 mSnapshotThreadWaitLock.lock();
1564 while (mSnapshotThreadRunning) {
1565 LOGV("initPreview: waiting for old snapshot thread to complete.");
1566 mSnapshotThreadWait.wait(mSnapshotThreadWaitLock);
1567 LOGV("initPreview: old snapshot thread completed.");
1568 }
1569 mSnapshotThreadWaitLock.unlock();
1570
1571 int cnt = 0;
1572 mPreviewFrameSize = previewWidth * previewHeight * 3/2;
Mohan Kandra284966d2010-01-05 13:39:15 -08001573 mCameraPreviewHeap = new PmemPool("/dev/pmem_adsp",
1574 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
1575 mCameraControlFd,
1576 MSM_PMEM_OUTPUT2,
1577 mPreviewFrameSize,
1578 kPreviewBufferCount,
1579 mPreviewFrameSize,
1580 "Camera preview");
1581
1582 if (!mCameraPreviewHeap->initialized()) {
1583 mCameraPreviewHeap.clear();
1584 LOGE("initPreview X: could not initialize Camera preview heap.");
1585 return false;
1586 }
Kiran Kumar H N595970b2010-01-12 10:41:09 -08001587 if( !strncmp(mDeviceName,"msm7630", 7) ) {
1588 mPreviewHeap = NULL;
1589 if(mPostViewHeap == NULL) {
1590 LOGV(" Allocating Postview heap ");
1591 /* mPostViewHeap should be declared only for 7630 target */
1592 mPostViewHeap =
1593 new PmemPool("/dev/pmem_adsp",
1594 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
1595 mCameraControlFd,
1596 MSM_PMEM_OUTPUT2,
1597 mPreviewFrameSize,
1598 1,
1599 mPreviewFrameSize,
1600 "postview");
Mohan Kandra284966d2010-01-05 13:39:15 -08001601
Kiran Kumar H N595970b2010-01-12 10:41:09 -08001602 if (!mPostViewHeap->initialized()) {
1603 mPostViewHeap.clear();
1604 LOGE(" Failed to initialize Postview Heap");
1605 return false;
1606 }
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08001607 }
1608 } else {
1609 mPreviewHeap = new PmemPool("/dev/pmem_adsp",
1610 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
1611 mCameraControlFd,
1612 MSM_PMEM_OUTPUT2,
1613 mPreviewFrameSize,
1614 kPreviewBufferCount,
1615 mPreviewFrameSize,
1616 "preview");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001617
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08001618 if (!mPreviewHeap->initialized()) {
1619 mPreviewHeap.clear();
1620 LOGE("initPreview X: could not initialize preview heap.");
1621 return false;
1622 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001623 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001624 // mDimension will be filled with thumbnail_width, thumbnail_height,
1625 // orig_picture_dx, and orig_picture_dy after this function call. We need to
1626 // keep it for jpeg_encoder_encode.
1627 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
1628 sizeof(cam_ctrl_dimension_t), &mDimension);
1629
1630 if (ret) {
1631 for (cnt = 0; cnt < kPreviewBufferCount; cnt++) {
Mohan Kandra284966d2010-01-05 13:39:15 -08001632 frames[cnt].fd = mCameraPreviewHeap->mHeap->getHeapID();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001633 frames[cnt].buffer =
Mohan Kandra284966d2010-01-05 13:39:15 -08001634 (uint32_t)mCameraPreviewHeap->mHeap->base() + mCameraPreviewHeap->mAlignedBufferSize * cnt;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001635 frames[cnt].y_off = 0;
1636 frames[cnt].cbcr_off = previewWidth * previewHeight;
1637 frames[cnt].path = MSM_FRAME_ENC;
1638 }
1639
1640 mFrameThreadWaitLock.lock();
1641 pthread_attr_t attr;
1642 pthread_attr_init(&attr);
1643 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1644 mFrameThreadRunning = !pthread_create(&mFrameThread,
1645 &attr,
1646 frame_thread,
1647 &frames[kPreviewBufferCount-1]);
1648 ret = mFrameThreadRunning;
1649 mFrameThreadWaitLock.unlock();
1650 }
1651
1652 LOGV("initPreview X: %d", ret);
1653 return ret;
1654}
1655
1656void QualcommCameraHardware::deinitPreview(void)
1657{
1658 LOGI("deinitPreview E");
1659
1660 // When we call deinitPreview(), we signal to the frame thread that it
1661 // needs to exit, but we DO NOT WAIT for it to complete here. The problem
1662 // is that deinitPreview is sometimes called from the frame-thread's
1663 // callback, when the refcount on the Camera client reaches zero. If we
1664 // called pthread_join(), we would deadlock. So, we just call
1665 // LINK_camframe_terminate() in deinitPreview(), which makes sure that
1666 // after the preview callback returns, the camframe thread will exit. We
1667 // could call pthread_join() in initPreview() to join the last frame
1668 // thread. However, we would also have to call pthread_join() in release
1669 // as well, shortly before we destroy the object; this would cause the same
1670 // deadlock, since release(), like deinitPreview(), may also be called from
1671 // the frame-thread's callback. This we have to make the frame thread
1672 // detached, and use a separate mechanism to wait for it to complete.
1673
1674 if (LINK_camframe_terminate() < 0)
1675 LOGE("failed to stop the camframe thread: %s",
1676 strerror(errno));
1677 LOGI("deinitPreview X");
1678}
1679
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001680bool QualcommCameraHardware::initRawSnapshot()
1681{
1682 LOGV("initRawSnapshot E");
1683
1684 //get width and height from Dimension Object
1685 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
1686 sizeof(cam_ctrl_dimension_t), &mDimension);
1687
1688 if(!ret){
1689 LOGE("initRawSnapshot X: failed to set dimension");
1690 return false;
1691 }
1692 int rawSnapshotSize = mDimension.raw_picture_height *
1693 mDimension.raw_picture_width;
1694
1695 LOGV("raw_snapshot_buffer_size = %d, raw_picture_height = %d, "\
1696 "raw_picture_width = %d",
1697 rawSnapshotSize, mDimension.raw_picture_height,
1698 mDimension.raw_picture_width);
1699
1700 if (mRawSnapShotPmemHeap != NULL) {
1701 LOGV("initRawSnapshot: clearing old mRawSnapShotPmemHeap.");
1702 mRawSnapShotPmemHeap.clear();
1703 }
1704
1705 //Pmem based pool for Camera Driver
1706 mRawSnapShotPmemHeap = new PmemPool("/dev/pmem_adsp",
1707 MemoryHeapBase::READ_ONLY,
1708 mCameraControlFd,
1709 MSM_PMEM_RAW_MAINIMG,
1710 rawSnapshotSize,
1711 1,
1712 rawSnapshotSize,
1713 "raw pmem snapshot camera");
1714
1715 if (!mRawSnapShotPmemHeap->initialized()) {
1716 mRawSnapShotPmemHeap.clear();
1717 LOGE("initRawSnapshot X: error initializing mRawSnapshotHeap");
1718 return false;
1719 }
1720 LOGV("initRawSnapshot X");
1721 return true;
1722
1723}
1724
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001725bool QualcommCameraHardware::initRaw(bool initJpegHeap)
1726{
1727 int rawWidth, rawHeight;
Apurva Rajguru8d1773b2009-12-02 14:21:23 -08001728
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001729 mParameters.getPictureSize(&rawWidth, &rawHeight);
1730 LOGV("initRaw E: picture size=%dx%d", rawWidth, rawHeight);
1731
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08001732 int thumbnailBufferSize;
1733 //Thumbnail height should be smaller than Picture height
1734 if (rawHeight > thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height){
1735 mDimension.ui_thumbnail_width =
1736 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].width;
1737 mDimension.ui_thumbnail_height =
1738 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height;
1739 uint32_t pictureAspectRatio = (uint32_t)((rawWidth * Q12) / rawHeight);
1740 uint32_t i;
1741 for(i = 0; i < THUMBNAIL_SIZE_COUNT; i++ )
1742 {
1743 if(thumbnail_sizes[i].aspect_ratio == pictureAspectRatio)
1744 {
1745 mDimension.ui_thumbnail_width = thumbnail_sizes[i].width;
1746 mDimension.ui_thumbnail_height = thumbnail_sizes[i].height;
1747 break;
1748 }
1749 }
1750 }
1751 else{
1752 mDimension.ui_thumbnail_height = THUMBNAIL_SMALL_HEIGHT;
1753 mDimension.ui_thumbnail_width =
1754 (THUMBNAIL_SMALL_HEIGHT * rawWidth)/ rawHeight;
1755 }
1756
1757 LOGV("Thumbnail Size Width %d Height %d",
1758 mDimension.ui_thumbnail_width,
1759 mDimension.ui_thumbnail_height);
1760
1761 thumbnailBufferSize = mDimension.ui_thumbnail_width *
1762 mDimension.ui_thumbnail_height * 3 / 2;
1763
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001764 // mDimension will be filled with thumbnail_width, thumbnail_height,
1765 // orig_picture_dx, and orig_picture_dy after this function call. We need to
1766 // keep it for jpeg_encoder_encode.
1767 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
1768 sizeof(cam_ctrl_dimension_t), &mDimension);
1769 if(!ret) {
1770 LOGE("initRaw X: failed to set dimension");
1771 return false;
1772 }
1773
1774 if (mJpegHeap != NULL) {
1775 LOGV("initRaw: clearing old mJpegHeap.");
1776 mJpegHeap.clear();
1777 }
1778
1779 // Snapshot
1780 mRawSize = rawWidth * rawHeight * 3 / 2;
Apurva Rajguru8d1773b2009-12-02 14:21:23 -08001781
Mohan Kandra284966d2010-01-05 13:39:15 -08001782 if(!strcmp(mDeviceName,"msm7627_surf"))
Apurva Rajguru8d1773b2009-12-02 14:21:23 -08001783 mJpegMaxSize = CEILING16(rawWidth) * CEILING16(rawHeight) * 3 / 2;
1784 else
1785 mJpegMaxSize = rawWidth * rawHeight * 3 / 2;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001786
1787 LOGV("initRaw: initializing mRawHeap.");
1788 mRawHeap =
1789 new PmemPool("/dev/pmem_camera",
1790 MemoryHeapBase::READ_ONLY,
1791 mCameraControlFd,
1792 MSM_PMEM_MAINIMG,
1793 mJpegMaxSize,
1794 kRawBufferCount,
1795 mRawSize,
1796 "snapshot camera");
1797
1798 if (!mRawHeap->initialized()) {
1799 LOGE("initRaw X failed with pmem_camera, trying with pmem_adsp");
1800 mRawHeap =
1801 new PmemPool("/dev/pmem_adsp",
1802 MemoryHeapBase::READ_ONLY,
1803 mCameraControlFd,
1804 MSM_PMEM_MAINIMG,
1805 mJpegMaxSize,
1806 kRawBufferCount,
1807 mRawSize,
1808 "snapshot camera");
1809 if (!mRawHeap->initialized()) {
1810 mRawHeap.clear();
1811 LOGE("initRaw X: error initializing mRawHeap");
1812 return false;
1813 }
1814 }
1815
1816 LOGV("do_mmap snapshot pbuf = %p, pmem_fd = %d",
1817 (uint8_t *)mRawHeap->mHeap->base(), mRawHeap->mHeap->getHeapID());
1818
1819 // Jpeg
1820
1821 if (initJpegHeap) {
1822 LOGV("initRaw: initializing mJpegHeap.");
1823 mJpegHeap =
1824 new AshmemPool(mJpegMaxSize,
1825 kJpegBufferCount,
1826 0, // we do not know how big the picture will be
1827 "jpeg");
1828
1829 if (!mJpegHeap->initialized()) {
1830 mJpegHeap.clear();
1831 mRawHeap.clear();
1832 LOGE("initRaw X failed: error initializing mJpegHeap.");
1833 return false;
1834 }
1835
1836 // Thumbnails
1837
1838 mThumbnailHeap =
1839 new PmemPool("/dev/pmem_adsp",
1840 MemoryHeapBase::READ_ONLY,
1841 mCameraControlFd,
1842 MSM_PMEM_THUMBNAIL,
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08001843 thumbnailBufferSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001844 1,
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08001845 thumbnailBufferSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001846 "thumbnail");
1847
1848 if (!mThumbnailHeap->initialized()) {
1849 mThumbnailHeap.clear();
1850 mJpegHeap.clear();
1851 mRawHeap.clear();
1852 LOGE("initRaw X failed: error initializing mThumbnailHeap.");
1853 return false;
1854 }
1855 }
1856
1857 LOGV("initRaw X");
1858 return true;
1859}
1860
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001861
1862void QualcommCameraHardware::deinitRawSnapshot()
1863{
1864 LOGV("deinitRawSnapshot E");
1865 mRawSnapShotPmemHeap.clear();
1866 mRawSnapshotAshmemHeap.clear();
1867 LOGV("deinitRawSnapshot X");
1868}
1869
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001870void QualcommCameraHardware::deinitRaw()
1871{
1872 LOGV("deinitRaw E");
1873
1874 mThumbnailHeap.clear();
1875 mJpegHeap.clear();
1876 mRawHeap.clear();
1877 mDisplayHeap.clear();
1878
1879 LOGV("deinitRaw X");
1880}
1881
1882void QualcommCameraHardware::release()
1883{
1884 LOGD("release E");
1885 Mutex::Autolock l(&mLock);
1886
1887#if DLOPEN_LIBMMCAMERA
1888 if (libmmcamera == NULL) {
1889 LOGE("ERROR: multiple release!");
1890 return;
1891 }
1892#else
1893#warning "Cannot detect multiple release when not dlopen()ing libqcamera!"
1894#endif
1895
1896 int cnt, rc;
1897 struct msm_ctrl_cmd ctrlCmd;
1898
1899 if (mCameraRunning) {
1900 if(mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME)) {
1901 mRecordFrameLock.lock();
1902 mReleasedRecordingFrame = true;
1903 mRecordWait.signal();
1904 mRecordFrameLock.unlock();
1905 }
1906 stopPreviewInternal();
1907 }
1908
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08001909 if(!strncmp(mDeviceName,"msm7630", 7)) {
1910 mPostViewHeap.clear();
1911 mPostViewHeap = NULL;
1912 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001913 LINK_jpeg_encoder_join();
1914 deinitRaw();
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001915 deinitRawSnapshot();
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001916 {
1917 Mutex::Autolock l(&mCamframeTimeoutLock);
1918 if(!camframe_timeout_flag) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001919
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001920 ctrlCmd.timeout_ms = 5000;
1921 ctrlCmd.length = 0;
1922 ctrlCmd.type = (uint16_t)CAMERA_EXIT;
1923 ctrlCmd.resp_fd = mCameraControlFd; // FIXME: this will be put in by the kernel
1924 if (ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0)
1925 LOGE("ioctl CAMERA_EXIT fd %d error %s",
1926 mCameraControlFd, strerror(errno));
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001927
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001928 }
Kiran Kumar H Nac2f4952009-12-17 01:16:53 -08001929 LINK_release_cam_conf_thread();
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001930 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001931 close(mCameraControlFd);
1932 mCameraControlFd = -1;
Mohan Kandra284966d2010-01-05 13:39:15 -08001933 if(fb_fd >= 0) {
1934 close(fb_fd);
1935 fb_fd = -1;
1936 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001937#if DLOPEN_LIBMMCAMERA
1938 if (libmmcamera) {
1939 ::dlclose(libmmcamera);
1940 LOGV("dlclose(libqcamera)");
1941 libmmcamera = NULL;
1942 }
1943#endif
1944
1945 Mutex::Autolock lock(&singleton_lock);
1946 singleton_releasing = true;
1947
1948 LOGD("release X");
1949}
1950
1951QualcommCameraHardware::~QualcommCameraHardware()
1952{
1953 LOGD("~QualcommCameraHardware E");
1954 Mutex::Autolock lock(&singleton_lock);
1955 singleton.clear();
1956 singleton_releasing = false;
1957 singleton_wait.signal();
1958 LOGD("~QualcommCameraHardware X");
1959}
1960
1961sp<IMemoryHeap> QualcommCameraHardware::getRawHeap() const
1962{
1963 LOGV("getRawHeap");
1964 return mDisplayHeap != NULL ? mDisplayHeap->mHeap : NULL;
1965}
1966
1967sp<IMemoryHeap> QualcommCameraHardware::getPreviewHeap() const
1968{
1969 LOGV("getPreviewHeap");
1970 return mPreviewHeap != NULL ? mPreviewHeap->mHeap : NULL;
1971}
1972
1973status_t QualcommCameraHardware::startPreviewInternal()
1974{
1975 if(mCameraRunning) {
1976 LOGV("startPreview X: preview already running.");
1977 return NO_ERROR;
1978 }
1979
1980 if (!mPreviewInitialized) {
1981 mPreviewInitialized = initPreview();
1982 if (!mPreviewInitialized) {
1983 LOGE("startPreview X initPreview failed. Not starting preview.");
1984 return UNKNOWN_ERROR;
1985 }
1986 }
1987
1988 mCameraRunning = native_start_preview(mCameraControlFd);
1989 if(!mCameraRunning) {
1990 deinitPreview();
1991 mPreviewInitialized = false;
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08001992 mOverlay = NULL;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001993 LOGE("startPreview X: native_start_preview failed!");
1994 return UNKNOWN_ERROR;
1995 }
1996
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001997 //Reset the Gps Information
1998 exif_table_numEntries = 0;
Mohan Kandra284966d2010-01-05 13:39:15 -08001999
2000 if(native_get_maxzoom(mCameraControlFd, (void *)&mMaxZoom) == true){
2001 LOGE("Maximum zoom value is %d", mMaxZoom);
2002 mParameters.set("zoom-supported", "true");
2003 } else {
2004 LOGE("Failed to get maximum zoom value...setting max zoom to zero");
2005 mParameters.set("zoom-supported", "false");
2006 mMaxZoom = 0;
2007 }
2008 mParameters.set("max-zoom",mMaxZoom);
2009
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002010 LOGV("startPreview X");
2011 return NO_ERROR;
2012}
2013
2014status_t QualcommCameraHardware::startPreview()
2015{
2016 LOGV("startPreview E");
2017 Mutex::Autolock l(&mLock);
2018 return startPreviewInternal();
2019}
2020
2021void QualcommCameraHardware::stopPreviewInternal()
2022{
2023 LOGV("stopPreviewInternal E: %d", mCameraRunning);
2024 if (mCameraRunning) {
2025 // Cancel auto focus.
2026 {
2027 if (mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS)) {
2028 cancelAutoFocusInternal();
2029 }
2030 }
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002031
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002032 Mutex::Autolock l(&mCamframeTimeoutLock);
2033 if(!camframe_timeout_flag) {
2034 mCameraRunning = !native_stop_preview(mCameraControlFd);
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002035 } else {
2036 /* This means that the camframetimeout was issued.
2037 * But we did not issue native_stop_preview(), so we
Kiran Kumar H Nac2f4952009-12-17 01:16:53 -08002038 * need to update mCameraRunning to indicate that
2039 * Camera is no longer running. */
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002040 mCameraRunning = 0;
Kiran Kumar H Nac2f4952009-12-17 01:16:53 -08002041 }
2042 if (!mCameraRunning && mPreviewInitialized) {
2043 deinitPreview();
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002044 mPreviewInitialized = false;
2045 }
Kiran Kumar H Nac2f4952009-12-17 01:16:53 -08002046 else LOGE("stopPreviewInternal: failed to stop preview");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002047 }
2048 LOGV("stopPreviewInternal X: %d", mCameraRunning);
2049}
2050
2051void QualcommCameraHardware::stopPreview()
2052{
2053 LOGV("stopPreview: E");
2054 Mutex::Autolock l(&mLock);
2055 {
2056 if (mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME))
2057 return;
2058 }
2059 stopPreviewInternal();
2060 LOGV("stopPreview: X");
2061}
2062
2063void QualcommCameraHardware::runAutoFocus()
2064{
2065 bool status = true;
2066 void *libhandle = NULL;
Srinivasan Kannan71229622009-12-04 12:05:58 -08002067 isp3a_af_mode_t afMode;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002068
2069 mAutoFocusThreadLock.lock();
2070 // Skip autofocus if focus mode is infinity.
2071 if (strcmp(mParameters.get(CameraParameters::KEY_FOCUS_MODE),
2072 CameraParameters::FOCUS_MODE_INFINITY) == 0) {
2073 goto done;
2074 }
2075
2076 mAutoFocusFd = open(MSM_CAMERA_CONTROL, O_RDWR);
2077 if (mAutoFocusFd < 0) {
2078 LOGE("autofocus: cannot open %s: %s",
2079 MSM_CAMERA_CONTROL,
2080 strerror(errno));
2081 mAutoFocusThreadRunning = false;
2082 mAutoFocusThreadLock.unlock();
2083 return;
2084 }
2085
2086#if DLOPEN_LIBMMCAMERA
2087 // We need to maintain a reference to libqcamera.so for the duration of the
2088 // AF thread, because we do not know when it will exit relative to the
2089 // lifetime of this object. We do not want to dlclose() libqcamera while
2090 // LINK_cam_frame is still running.
2091 libhandle = ::dlopen("liboemcamera.so", RTLD_NOW);
2092 LOGV("AF: loading libqcamera at %p", libhandle);
2093 if (!libhandle) {
2094 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
2095 close(mAutoFocusFd);
2096 mAutoFocusFd = -1;
2097 mAutoFocusThreadRunning = false;
2098 mAutoFocusThreadLock.unlock();
2099 return;
2100 }
2101#endif
2102
Srinivasan Kannan71229622009-12-04 12:05:58 -08002103 afMode = (isp3a_af_mode_t)attr_lookup(focus_modes,
2104 sizeof(focus_modes) / sizeof(str_map),
2105 mParameters.get(CameraParameters::KEY_FOCUS_MODE));
2106
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002107 /* This will block until either AF completes or is cancelled. */
Srinivasan Kannan71229622009-12-04 12:05:58 -08002108 LOGV("af start (fd %d mode %d)", mAutoFocusFd, afMode);
2109 status = native_set_afmode(mAutoFocusFd, afMode);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002110 LOGV("af done: %d", (int)status);
2111 close(mAutoFocusFd);
2112 mAutoFocusFd = -1;
2113
2114done:
2115 mAutoFocusThreadRunning = false;
2116 mAutoFocusThreadLock.unlock();
2117
2118 mCallbackLock.lock();
2119 bool autoFocusEnabled = mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS);
2120 notify_callback cb = mNotifyCallback;
2121 void *data = mCallbackCookie;
2122 mCallbackLock.unlock();
2123 if (autoFocusEnabled)
2124 cb(CAMERA_MSG_FOCUS, status, 0, data);
2125
2126#if DLOPEN_LIBMMCAMERA
2127 if (libhandle) {
2128 ::dlclose(libhandle);
2129 LOGV("AF: dlclose(libqcamera)");
2130 }
2131#endif
2132}
2133
2134status_t QualcommCameraHardware::cancelAutoFocusInternal()
2135{
2136 LOGV("cancelAutoFocusInternal E");
2137
Srinivasan Kannan71229622009-12-04 12:05:58 -08002138 if(!sensorType->hasAutoFocusSupport){
2139 LOGV("cancelAutoFocusInternal X");
2140 return NO_ERROR;
2141 }
2142
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002143#if 0
2144 if (mAutoFocusFd < 0) {
2145 LOGV("cancelAutoFocusInternal X: not in progress");
2146 return NO_ERROR;
2147 }
2148#endif
2149
2150 status_t rc = native_cancel_afmode(mCameraControlFd, mAutoFocusFd) ?
2151 NO_ERROR :
2152 UNKNOWN_ERROR;
2153
2154 LOGV("cancelAutoFocusInternal X: %d", rc);
2155 return rc;
2156}
2157
2158void *auto_focus_thread(void *user)
2159{
2160 LOGV("auto_focus_thread E");
2161 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
2162 if (obj != 0) {
2163 obj->runAutoFocus();
2164 }
2165 else LOGW("not starting autofocus: the object went away!");
2166 LOGV("auto_focus_thread X");
2167 return NULL;
2168}
2169
2170status_t QualcommCameraHardware::autoFocus()
2171{
2172 LOGV("autoFocus E");
2173 Mutex::Autolock l(&mLock);
2174
Srinivasan Kannan71229622009-12-04 12:05:58 -08002175 if(!sensorType->hasAutoFocusSupport){
Srinivasan Kannandf085222009-12-09 18:31:00 -08002176 bool status = false;
2177 mCallbackLock.lock();
2178 bool autoFocusEnabled = mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS);
2179 notify_callback cb = mNotifyCallback;
2180 void *data = mCallbackCookie;
2181 mCallbackLock.unlock();
2182 if (autoFocusEnabled)
2183 cb(CAMERA_MSG_FOCUS, status, 0, data);
Srinivasan Kannan71229622009-12-04 12:05:58 -08002184 LOGV("autoFocus X");
2185 return NO_ERROR;
2186 }
2187
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002188 if (mCameraControlFd < 0) {
2189 LOGE("not starting autofocus: main control fd %d", mCameraControlFd);
2190 return UNKNOWN_ERROR;
2191 }
2192
2193 {
2194 mAutoFocusThreadLock.lock();
2195 if (!mAutoFocusThreadRunning) {
2196 // Create a detached thread here so that we don't have to wait
2197 // for it when we cancel AF.
2198 pthread_t thr;
2199 pthread_attr_t attr;
2200 pthread_attr_init(&attr);
2201 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2202 mAutoFocusThreadRunning =
2203 !pthread_create(&thr, &attr,
2204 auto_focus_thread, NULL);
2205 if (!mAutoFocusThreadRunning) {
2206 LOGE("failed to start autofocus thread");
2207 mAutoFocusThreadLock.unlock();
2208 return UNKNOWN_ERROR;
2209 }
2210 }
2211 mAutoFocusThreadLock.unlock();
2212 }
2213
2214 LOGV("autoFocus X");
2215 return NO_ERROR;
2216}
2217
2218status_t QualcommCameraHardware::cancelAutoFocus()
2219{
2220 LOGV("cancelAutoFocus E");
2221 Mutex::Autolock l(&mLock);
2222
2223 int rc = NO_ERROR;
2224 if (mCameraRunning && mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS)) {
2225 rc = cancelAutoFocusInternal();
2226 }
2227
2228 LOGV("cancelAutoFocus X");
2229 return rc;
2230}
2231
2232void QualcommCameraHardware::runSnapshotThread(void *data)
2233{
2234 LOGV("runSnapshotThread E");
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002235 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
2236 if (native_start_snapshot(mCameraControlFd))
2237 receiveRawPicture();
2238 else
2239 LOGE("main: native_start_snapshot failed!");
2240 } else if(mSnapshotFormat == PICTURE_FORMAT_RAW){
2241 if(native_start_raw_snapshot(mCameraControlFd)){
2242 receiveRawSnapshot();
2243 } else {
2244 LOGE("main: native_start_raw_snapshot failed!");
2245 }
2246 }
2247
2248 mSnapshotFormat = 0;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002249
2250 mSnapshotThreadWaitLock.lock();
2251 mSnapshotThreadRunning = false;
2252 mSnapshotThreadWait.signal();
2253 mSnapshotThreadWaitLock.unlock();
2254
2255 LOGV("runSnapshotThread X");
2256}
2257
2258void *snapshot_thread(void *user)
2259{
2260 LOGD("snapshot_thread E");
2261 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
2262 if (obj != 0) {
2263 obj->runSnapshotThread(user);
2264 }
2265 else LOGW("not starting snapshot thread: the object went away!");
2266 LOGD("snapshot_thread X");
2267 return NULL;
2268}
2269
2270status_t QualcommCameraHardware::takePicture()
2271{
2272 LOGV("takePicture(%d)", mMsgEnabled);
2273 Mutex::Autolock l(&mLock);
2274
2275 // Wait for old snapshot thread to complete.
2276 mSnapshotThreadWaitLock.lock();
2277 while (mSnapshotThreadRunning) {
2278 LOGV("takePicture: waiting for old snapshot thread to complete.");
2279 mSnapshotThreadWait.wait(mSnapshotThreadWaitLock);
2280 LOGV("takePicture: old snapshot thread completed.");
2281 }
2282
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002283 if(!strcmp(mDeviceName,"msm7630_surf")) {
2284 /* Store the last frame queued for preview. This
2285 * shall be used as postview */
2286 storePreviewFrameForPostview();
2287 }
2288
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002289 //mSnapshotFormat is protected by mSnapshotThreadWaitLock
2290 if(mParameters.getPictureFormat() != 0 &&
2291 !strcmp(mParameters.getPictureFormat(),
2292 CameraParameters::PIXEL_FORMAT_RAW))
2293 mSnapshotFormat = PICTURE_FORMAT_RAW;
2294 else
2295 mSnapshotFormat = PICTURE_FORMAT_JPEG;
2296
2297 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
2298 if(!native_prepare_snapshot(mCameraControlFd)) {
2299 mSnapshotThreadWaitLock.unlock();
2300 return UNKNOWN_ERROR;
2301 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002302 }
2303
2304 stopPreviewInternal();
2305
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002306 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
2307 if (!initRaw(mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE))) {
2308 LOGE("initRaw failed. Not taking picture.");
2309 mSnapshotThreadWaitLock.unlock();
2310 return UNKNOWN_ERROR;
2311 }
2312 } else if(mSnapshotFormat == PICTURE_FORMAT_RAW ){
2313 if(!initRawSnapshot()){
2314 LOGE("initRawSnapshot failed. Not taking picture.");
2315 mSnapshotThreadWaitLock.unlock();
2316 return UNKNOWN_ERROR;
2317 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002318 }
2319
2320 mShutterLock.lock();
2321 mShutterPending = true;
2322 mShutterLock.unlock();
2323
2324 pthread_attr_t attr;
2325 pthread_attr_init(&attr);
2326 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2327 mSnapshotThreadRunning = !pthread_create(&mSnapshotThread,
2328 &attr,
2329 snapshot_thread,
2330 NULL);
2331 mSnapshotThreadWaitLock.unlock();
2332
2333 LOGV("takePicture: X");
2334 return mSnapshotThreadRunning ? NO_ERROR : UNKNOWN_ERROR;
2335}
2336
2337status_t QualcommCameraHardware::cancelPicture()
2338{
2339 status_t rc;
2340 LOGV("cancelPicture: E");
2341 rc = native_stop_snapshot(mCameraControlFd) ? NO_ERROR : UNKNOWN_ERROR;
2342 LOGV("cancelPicture: X: %d", rc);
2343 return rc;
2344}
2345
2346status_t QualcommCameraHardware::setParameters(const CameraParameters& params)
2347{
2348 LOGV("setParameters: E params = %p", &params);
2349
2350 Mutex::Autolock l(&mLock);
2351 status_t rc, final_rc = NO_ERROR;
2352
2353 if ((rc = setPreviewSize(params))) final_rc = rc;
2354 if ((rc = setPictureSize(params))) final_rc = rc;
2355 if ((rc = setJpegQuality(params))) final_rc = rc;
2356 if ((rc = setAntibanding(params))) final_rc = rc;
2357 if ((rc = setEffect(params))) final_rc = rc;
Apurva Rajguru55562b02009-12-03 12:25:35 -08002358 if ((rc = setAutoExposure(params))) final_rc = rc;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002359 if ((rc = setWhiteBalance(params))) final_rc = rc;
2360 if ((rc = setFlash(params))) final_rc = rc;
2361 if ((rc = setGpsLocation(params))) final_rc = rc;
2362 if ((rc = setRotation(params))) final_rc = rc;
2363 if ((rc = setZoom(params))) final_rc = rc;
2364 if ((rc = setFocusMode(params))) final_rc = rc;
2365 if ((rc = setOrientation(params))) final_rc = rc;
Nishant Panditc8c1ee72009-12-03 16:24:02 +05302366 if ((rc = setBrightness(params))) final_rc = rc;
2367 if ((rc = setLensshadeValue(params))) final_rc = rc;
2368 if ((rc = setISOValue(params))) final_rc = rc;
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002369 if ((rc = setPictureFormat(params))) final_rc = rc;
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08002370 if ((rc = setSharpness(params))) final_rc = rc;
2371 if ((rc = setContrast(params))) final_rc = rc;
2372 if ((rc = setSaturation(params))) final_rc = rc;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002373
2374 LOGV("setParameters: X");
2375 return final_rc;
2376}
2377
2378CameraParameters QualcommCameraHardware::getParameters() const
2379{
2380 LOGV("getParameters: EX");
2381 return mParameters;
2382}
2383
2384status_t QualcommCameraHardware::sendCommand(int32_t command, int32_t arg1,
2385 int32_t arg2)
2386{
2387 LOGV("sendCommand: EX");
2388 return BAD_VALUE;
2389}
2390
2391extern "C" sp<CameraHardwareInterface> openCameraHardware()
2392{
2393 LOGV("openCameraHardware: call createInstance");
2394 return QualcommCameraHardware::createInstance();
2395}
2396
2397wp<QualcommCameraHardware> QualcommCameraHardware::singleton;
2398
2399// If the hardware already exists, return a strong pointer to the current
2400// object. If not, create a new hardware object, put it in the singleton,
2401// and return it.
2402sp<CameraHardwareInterface> QualcommCameraHardware::createInstance()
2403{
2404 LOGD("createInstance: E");
2405
2406 Mutex::Autolock lock(&singleton_lock);
2407
2408 // Wait until the previous release is done.
2409 while (singleton_releasing) {
2410 LOGD("Wait for previous release.");
2411 singleton_wait.wait(singleton_lock);
2412 }
2413
2414 if (singleton != 0) {
2415 sp<CameraHardwareInterface> hardware = singleton.promote();
2416 if (hardware != 0) {
2417 LOGD("createInstance: X return existing hardware=%p", &(*hardware));
2418 return hardware;
2419 }
2420 }
2421
2422 {
2423 struct stat st;
2424 int rc = stat("/dev/oncrpc", &st);
2425 if (rc < 0) {
2426 LOGD("createInstance: X failed to create hardware: %s", strerror(errno));
2427 return NULL;
2428 }
2429 }
2430
2431 QualcommCameraHardware *cam = new QualcommCameraHardware();
2432 sp<QualcommCameraHardware> hardware(cam);
2433 singleton = hardware;
2434
2435 if (!cam->startCamera()) {
2436 LOGE("%s: startCamera failed!", __FUNCTION__);
2437 return NULL;
2438 }
2439
2440 cam->initDefaultParameters();
2441 LOGD("createInstance: X created hardware=%p", &(*hardware));
2442 return hardware;
2443}
2444
2445// For internal use only, hence the strong pointer to the derived type.
2446sp<QualcommCameraHardware> QualcommCameraHardware::getInstance()
2447{
2448 sp<CameraHardwareInterface> hardware = singleton.promote();
2449 if (hardware != 0) {
2450 // LOGV("getInstance: X old instance of hardware");
2451 return sp<QualcommCameraHardware>(static_cast<QualcommCameraHardware*>(hardware.get()));
2452 } else {
2453 LOGV("getInstance: X new instance of hardware");
2454 return sp<QualcommCameraHardware>();
2455 }
2456}
2457
Mohan Kandra284966d2010-01-05 13:39:15 -08002458bool QualcommCameraHardware::native_zoom_image(int srcFd, int dstFd, int offSet, common_crop_t *crop)
2459{
2460 int result = 0;
2461 struct mdp_blit_req *e;
2462 struct timeval td1, td2;
2463
2464 int previewWidth, previewHeight;
2465 mParameters.getPreviewSize(&previewWidth, &previewHeight);
2466
2467 /* Initialize yuv structure */
2468 zoomImage.list.count = 1;
2469
2470 e = &zoomImage.list.req[0];
2471
2472 e->src.width = previewWidth;
2473 e->src.height = previewHeight;
2474 e->src.format = MDP_Y_CBCR_H2V2;
2475 e->src.offset = offSet;
2476 e->src.memory_id = srcFd;
2477
2478 e->dst.width = previewWidth;
2479 e->dst.height = previewHeight;
2480 e->dst.format = MDP_Y_CBCR_H2V2;
2481 e->dst.offset = offSet;
2482 e->dst.memory_id = dstFd;
2483
2484 LOGV(" Source FD = %d, Destination FD = %d offSet = %d",srcFd, dstFd, offSet);
2485
2486 e->transp_mask = 0xffffffff;
2487 e->flags = 0;
2488 e->alpha = 0xff;
2489 if (crop->in2_w != 0 || crop->in2_h != 0) {
2490 e->src_rect.x = (crop->out2_w - crop->in2_w + 1) / 2 - 1;
2491 e->src_rect.y = (crop->out2_h - crop->in2_h + 1) / 2 - 1;
2492 e->src_rect.w = crop->in2_w;
2493 e->src_rect.h = crop->in2_h;
2494 } else {
2495 e->src_rect.x = 0;
2496 e->src_rect.y = 0;
2497 e->src_rect.w = previewWidth;
2498 e->src_rect.h = previewHeight;
2499 }
2500 LOGV(" native_zoom : SRC_RECT : x,y = %d,%d \t w,h = %d, %d",
2501 e->src_rect.x, e->src_rect.y, e->src_rect.w, e->src_rect.h);
2502
2503 e->dst_rect.x = 0;
2504 e->dst_rect.y = 0;
2505 e->dst_rect.w = previewWidth;
2506 e->dst_rect.h = previewHeight;
2507
2508 result = ioctl(fb_fd, MSMFB_BLIT, &zoomImage.list);
2509 if (result < 0) {
2510 LOGE("MSM_FBIOBLT failed! line=%d\n", __LINE__);
2511 return FALSE;
2512 }
2513 return TRUE;
2514}
2515
Mohan Kandra740cfce2010-01-07 12:58:24 -08002516void QualcommCameraHardware::debugShowFPS() const
2517{
2518 static int mFrameCount;
2519 static int mLastFrameCount = 0;
2520 static nsecs_t mLastFpsTime = 0;
2521 static float mFps = 0;
2522 mFrameCount++;
2523 nsecs_t now = systemTime();
2524 nsecs_t diff = now - mLastFpsTime;
2525 if (diff > ms2ns(250)) {
2526 mFps = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
2527 LOGI("Frames Per Second: %.4f", mFps);
2528 mLastFpsTime = now;
2529 mLastFrameCount = mFrameCount;
2530 }
2531}
2532
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002533void QualcommCameraHardware::receivePreviewFrame(struct msm_frame *frame)
2534{
2535// LOGV("receivePreviewFrame E");
2536
2537 if (!mCameraRunning) {
2538 LOGE("ignoring preview callback--camera has been stopped");
2539 return;
2540 }
2541
Mohan Kandra740cfce2010-01-07 12:58:24 -08002542 if (UNLIKELY(mDebugFps)) {
2543 debugShowFPS();
2544 }
2545
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002546 mCallbackLock.lock();
2547 int msgEnabled = mMsgEnabled;
2548 data_callback pcb = mDataCallback;
2549 void *pdata = mCallbackCookie;
2550 data_callback_timestamp rcb = mDataCallbackTimestamp;
2551 void *rdata = mCallbackCookie;
2552 mCallbackLock.unlock();
2553
2554 // Find the offset within the heap of the current buffer.
Mohan Kandra284966d2010-01-05 13:39:15 -08002555 ssize_t offset_addr =
2556 (ssize_t)frame->buffer - (ssize_t)mCameraPreviewHeap->mHeap->base();
2557 ssize_t offset = offset_addr / mCameraPreviewHeap->mAlignedBufferSize;
2558
2559 common_crop_t *crop = (common_crop_t *) (frame->cropinfo);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002560
2561 mInPreviewCallback = true;
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002562 if(mUseOverlay) {
2563 if(mOverlay != NULL) {
2564 mOverlayLock.lock();
2565 mOverlay->setFd(mCameraPreviewHeap->mHeap->getHeapID());
2566 if (crop->in2_w != 0 || crop->in2_h != 0) {
2567 zoomCropInfo.x = (crop->out2_w - crop->in2_w + 1) / 2 - 1;
2568 zoomCropInfo.y = (crop->out2_h - crop->in2_h + 1) / 2 - 1;
2569 zoomCropInfo.w = crop->in2_w;
2570 zoomCropInfo.h = crop->in2_h;
2571 mOverlay->setCrop(zoomCropInfo.x, zoomCropInfo.y,
2572 zoomCropInfo.w, zoomCropInfo.h);
2573 }
2574 mOverlay->queueBuffer((void *)offset_addr);
2575 mLastQueuedFrame = (void *)frame->buffer;
2576 mOverlayLock.unlock();
2577 }
Mohan Kandra284966d2010-01-05 13:39:15 -08002578 if (pcb != NULL && (msgEnabled & CAMERA_MSG_PREVIEW_FRAME))
2579 pcb(CAMERA_MSG_PREVIEW_FRAME, mCameraPreviewHeap->mBuffers[offset],
2580 pdata);
2581 } else {
2582 if( !native_zoom_image(mCameraPreviewHeap->mHeap->getHeapID(),
2583 mPreviewHeap->mHeap->getHeapID(),
2584 offset_addr, crop)) {
2585 LOGE(" Error while doing MDP zoom ");
2586 }
2587 if (pcb != NULL && (msgEnabled & CAMERA_MSG_PREVIEW_FRAME))
2588 pcb(CAMERA_MSG_PREVIEW_FRAME, mPreviewHeap->mBuffers[offset],
2589 pdata);
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08002590 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002591 if(rcb != NULL && (msgEnabled & CAMERA_MSG_VIDEO_FRAME)) {
Mohan Kandra284966d2010-01-05 13:39:15 -08002592 rcb(systemTime(), CAMERA_MSG_VIDEO_FRAME, mCameraPreviewHeap->mBuffers[offset], rdata);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002593 Mutex::Autolock rLock(&mRecordFrameLock);
2594 if (mReleasedRecordingFrame != true) {
2595 LOGV("block waiting for frame release");
2596 mRecordWait.wait(mRecordFrameLock);
2597 LOGV("frame released, continuing");
2598 }
2599 mReleasedRecordingFrame = false;
2600 }
2601 mInPreviewCallback = false;
2602
2603// LOGV("receivePreviewFrame X");
2604}
2605
2606status_t QualcommCameraHardware::startRecording()
2607{
2608 LOGV("startRecording E");
2609 Mutex::Autolock l(&mLock);
2610 mReleasedRecordingFrame = false;
2611 return startPreviewInternal();
2612}
2613
2614void QualcommCameraHardware::stopRecording()
2615{
2616 LOGV("stopRecording: E");
2617 Mutex::Autolock l(&mLock);
2618 {
2619 mRecordFrameLock.lock();
2620 mReleasedRecordingFrame = true;
2621 mRecordWait.signal();
2622 mRecordFrameLock.unlock();
2623
2624 if(mDataCallback && (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)) {
2625 LOGV("stopRecording: X, preview still in progress");
2626 return;
2627 }
2628 }
2629
2630 stopPreviewInternal();
2631 LOGV("stopRecording: X");
2632}
2633
2634void QualcommCameraHardware::releaseRecordingFrame(
2635 const sp<IMemory>& mem __attribute__((unused)))
2636{
2637 LOGV("releaseRecordingFrame E");
2638 Mutex::Autolock rLock(&mRecordFrameLock);
2639 mReleasedRecordingFrame = true;
2640 mRecordWait.signal();
2641 LOGV("releaseRecordingFrame X");
2642}
2643
2644bool QualcommCameraHardware::recordingEnabled()
2645{
2646 return mCameraRunning && mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME);
2647}
2648
2649void QualcommCameraHardware::notifyShutter(common_crop_t *crop)
2650{
2651 mShutterLock.lock();
2652 image_rect_type size;
2653
2654 if (mShutterPending && mNotifyCallback && (mMsgEnabled & CAMERA_MSG_SHUTTER)) {
2655 LOGV("out2_w=%d, out2_h=%d, in2_w=%d, in2_h=%d",
2656 crop->out2_w, crop->out2_h, crop->in2_w, crop->in2_h);
2657 LOGV("out1_w=%d, out1_h=%d, in1_w=%d, in1_h=%d",
2658 crop->out1_w, crop->out1_h, crop->in1_w, crop->in1_h);
2659
2660 // To workaround a bug in MDP which happens if either
2661 // dimension > 2048, we display the thumbnail instead.
2662 mDisplayHeap = mRawHeap;
2663 if (crop->in1_w == 0 || crop->in1_h == 0) {
2664 // Full size
2665 size.width = mDimension.picture_width;
2666 size.height = mDimension.picture_height;
2667 if (size.width > 2048 || size.height > 2048) {
2668 size.width = mDimension.ui_thumbnail_width;
2669 size.height = mDimension.ui_thumbnail_height;
2670 mDisplayHeap = mThumbnailHeap;
2671 }
2672 } else {
2673 // Cropped
2674 size.width = crop->in2_w & ~1;
2675 size.height = crop->in2_h & ~1;
2676 if (size.width > 2048 || size.height > 2048) {
2677 size.width = crop->in1_w & ~1;
2678 size.height = crop->in1_h & ~1;
2679 mDisplayHeap = mThumbnailHeap;
2680 }
2681 }
2682
2683 mNotifyCallback(CAMERA_MSG_SHUTTER, (int32_t)&size, 0,
2684 mCallbackCookie);
2685 mShutterPending = false;
2686 }
2687 mShutterLock.unlock();
2688}
2689
2690static void receive_shutter_callback(common_crop_t *crop)
2691{
2692 LOGV("receive_shutter_callback: E");
2693 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
2694 if (obj != 0) {
2695 obj->notifyShutter(crop);
2696 }
2697 LOGV("receive_shutter_callback: X");
2698}
2699
2700// Crop the picture in place.
2701static void crop_yuv420(uint32_t width, uint32_t height,
2702 uint32_t cropped_width, uint32_t cropped_height,
2703 uint8_t *image)
2704{
2705 uint32_t i, x, y;
2706 uint8_t* chroma_src, *chroma_dst;
2707
2708 // Calculate the start position of the cropped area.
2709 x = (width - cropped_width) / 2;
2710 y = (height - cropped_height) / 2;
2711 x &= ~1;
2712 y &= ~1;
2713
2714 // Copy luma component.
2715 for(i = 0; i < cropped_height; i++)
2716 memcpy(image + i * cropped_width,
2717 image + width * (y + i) + x,
2718 cropped_width);
2719
2720 chroma_src = image + width * height;
2721 chroma_dst = image + cropped_width * cropped_height;
2722
2723 // Copy chroma components.
2724 cropped_height /= 2;
2725 y /= 2;
2726 for(i = 0; i < cropped_height; i++)
2727 memcpy(chroma_dst + i * cropped_width,
2728 chroma_src + width * (y + i) + x,
2729 cropped_width);
2730}
2731
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002732
2733void QualcommCameraHardware::receiveRawSnapshot(){
2734 LOGV("receiveRawSnapshot E");
2735
2736 Mutex::Autolock cbLock(&mCallbackLock);
2737
2738 notifyShutter(&mCrop);
2739
2740 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
2741
2742 if(native_get_picture(mCameraControlFd, &mCrop) == false) {
2743 LOGE("receiveRawSnapshot X: native_get_picture failed!");
2744 return;
2745 }
2746
2747 //Create a Ashmem heap to copy data from PMem heap for application layer
2748 if(mRawSnapshotAshmemHeap != NULL){
2749 LOGV("receiveRawSnapshot: clearing old mRawSnapShotAshmemHeap.");
2750 mRawSnapshotAshmemHeap.clear();
2751 }
2752 mRawSnapshotAshmemHeap = new AshmemPool(
2753 mRawSnapShotPmemHeap->mBufferSize,
2754 mRawSnapShotPmemHeap->mNumBuffers,
2755 mRawSnapShotPmemHeap->mFrameSize,
2756 "raw ashmem snapshot camera"
2757 );
2758
2759 if(!mRawSnapshotAshmemHeap->initialized()){
2760 LOGE("receiveRawSnapshot X: error initializing mRawSnapshotHeap");
2761 deinitRawSnapshot();
2762 return;
2763 }
2764
2765 memcpy(mRawSnapshotAshmemHeap->mHeap->base(),
2766 mRawSnapShotPmemHeap->mHeap->base(),
2767 mRawSnapShotPmemHeap->mHeap->getSize());
2768
2769 mDataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mRawSnapshotAshmemHeap->mBuffers[0],
2770 mCallbackCookie);
2771
2772 }
2773
2774 //cleanup
2775 deinitRawSnapshot();
2776
2777 LOGV("receiveRawSnapshot X");
2778}
2779
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002780void QualcommCameraHardware::receiveRawPicture()
2781{
2782 LOGV("receiveRawPicture: E");
2783
2784 Mutex::Autolock cbLock(&mCallbackLock);
2785 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_RAW_IMAGE)) {
2786 if(native_get_picture(mCameraControlFd, &mCrop) == false) {
2787 LOGE("getPicture failed!");
2788 return;
2789 }
2790 mCrop.in1_w &= ~1;
2791 mCrop.in1_h &= ~1;
2792 mCrop.in2_w &= ~1;
2793 mCrop.in2_h &= ~1;
2794
2795 // By the time native_get_picture returns, picture is taken. Call
2796 // shutter callback if cam config thread has not done that.
2797 notifyShutter(&mCrop);
2798
2799 // Crop the image if zoomed.
2800 if (mCrop.in2_w != 0 && mCrop.in2_h != 0) {
2801 crop_yuv420(mCrop.out2_w, mCrop.out2_h, mCrop.in2_w, mCrop.in2_h,
2802 (uint8_t *)mRawHeap->mHeap->base());
2803 crop_yuv420(mCrop.out1_w, mCrop.out1_h, mCrop.in1_w, mCrop.in1_h,
2804 (uint8_t *)mThumbnailHeap->mHeap->base());
2805 // We do not need jpeg encoder to upscale the image. Set the new
2806 // dimension for encoder.
2807 mDimension.orig_picture_dx = mCrop.in2_w;
2808 mDimension.orig_picture_dy = mCrop.in2_h;
2809 mDimension.thumbnail_width = mCrop.in1_w;
2810 mDimension.thumbnail_height = mCrop.in1_h;
2811 memset(&mCrop, 0, sizeof(mCrop));
2812 }
2813
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002814 if( mUseOverlay && (mOverlay != NULL) ) {
2815 mOverlay->setFd(mPostViewHeap->mHeap->getHeapID());
2816 if( zoomCropInfo.w !=0 && zoomCropInfo.h !=0) {
2817 LOGD(" zoomCropInfo non-zero, setting crop ");
2818 mOverlay->setCrop(zoomCropInfo.x, zoomCropInfo.y,
2819 zoomCropInfo.w, zoomCropInfo.h);
2820 }
2821 LOGD(" Queueing Postview for display ");
2822 mOverlay->queueBuffer((void *)0);
2823 }
2824
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002825 mDataCallback(CAMERA_MSG_RAW_IMAGE, mDisplayHeap->mBuffers[0],
2826 mCallbackCookie);
2827 }
2828 else LOGV("Raw-picture callback was canceled--skipping.");
2829
2830 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
2831 mJpegSize = 0;
2832 if (LINK_jpeg_encoder_init()) {
2833 if(native_jpeg_encode()) {
2834 LOGV("receiveRawPicture: X (success)");
2835 return;
2836 }
2837 LOGE("jpeg encoding failed");
2838 }
2839 else LOGE("receiveRawPicture X: jpeg_encoder_init failed.");
2840 }
2841 else LOGV("JPEG callback is NULL, not encoding image.");
2842 deinitRaw();
2843 LOGV("receiveRawPicture: X");
2844}
2845
2846void QualcommCameraHardware::receiveJpegPictureFragment(
2847 uint8_t *buff_ptr, uint32_t buff_size)
2848{
2849 uint32_t remaining = mJpegHeap->mHeap->virtualSize();
2850 remaining -= mJpegSize;
2851 uint8_t *base = (uint8_t *)mJpegHeap->mHeap->base();
2852
2853 LOGV("receiveJpegPictureFragment size %d", buff_size);
2854 if (buff_size > remaining) {
2855 LOGE("receiveJpegPictureFragment: size %d exceeds what "
2856 "remains in JPEG heap (%d), truncating",
2857 buff_size,
2858 remaining);
2859 buff_size = remaining;
2860 }
2861 memcpy(base + mJpegSize, buff_ptr, buff_size);
2862 mJpegSize += buff_size;
2863}
2864
2865void QualcommCameraHardware::receiveJpegPicture(void)
2866{
2867 LOGV("receiveJpegPicture: E image (%d uint8_ts out of %d)",
2868 mJpegSize, mJpegHeap->mBufferSize);
2869 Mutex::Autolock cbLock(&mCallbackLock);
2870
2871 int index = 0, rc;
2872
2873 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
2874 // The reason we do not allocate into mJpegHeap->mBuffers[offset] is
2875 // that the JPEG image's size will probably change from one snapshot
2876 // to the next, so we cannot reuse the MemoryBase object.
2877 sp<MemoryBase> buffer = new
2878 MemoryBase(mJpegHeap->mHeap,
2879 index * mJpegHeap->mBufferSize +
2880 0,
2881 mJpegSize);
2882 mDataCallback(CAMERA_MSG_COMPRESSED_IMAGE, buffer, mCallbackCookie);
2883 buffer = NULL;
2884 }
2885 else LOGV("JPEG callback was cancelled--not delivering image.");
2886
2887 LINK_jpeg_encoder_join();
2888 deinitRaw();
2889
2890 LOGV("receiveJpegPicture: X callback done.");
2891}
2892
2893bool QualcommCameraHardware::previewEnabled()
2894{
2895 return mCameraRunning && mDataCallback && (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME);
2896}
2897
2898status_t QualcommCameraHardware::setPreviewSize(const CameraParameters& params)
2899{
2900 int width, height;
2901 params.getPreviewSize(&width, &height);
2902 LOGV("requested preview size %d x %d", width, height);
2903
2904 // Validate the preview size
2905 for (size_t i = 0; i < PREVIEW_SIZE_COUNT; ++i) {
2906 if (width == preview_sizes[i].width
2907 && height == preview_sizes[i].height) {
2908 mParameters.setPreviewSize(width, height);
2909 mDimension.display_width = width;
2910 mDimension.display_height = height;
2911 return NO_ERROR;
2912 }
2913 }
2914 LOGE("Invalid preview size requested: %dx%d", width, height);
2915 return BAD_VALUE;
2916}
2917
2918status_t QualcommCameraHardware::setPictureSize(const CameraParameters& params)
2919{
2920 int width, height;
2921 params.getPictureSize(&width, &height);
2922 LOGV("requested picture size %d x %d", width, height);
2923
2924 // Validate the picture size
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -08002925 for (int i = 0; i < supportedPictureSizesCount; ++i) {
2926 if (width == picture_sizes_ptr[i].width
2927 && height == picture_sizes_ptr[i].height) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002928 mParameters.setPictureSize(width, height);
2929 mDimension.picture_width = width;
2930 mDimension.picture_height = height;
2931 return NO_ERROR;
2932 }
2933 }
2934 LOGE("Invalid picture size requested: %dx%d", width, height);
2935 return BAD_VALUE;
2936}
2937
2938status_t QualcommCameraHardware::setJpegQuality(const CameraParameters& params) {
2939 status_t rc = NO_ERROR;
2940 int quality = params.getInt(CameraParameters::KEY_JPEG_QUALITY);
2941 if (quality > 0 && quality <= 100) {
2942 mParameters.set(CameraParameters::KEY_JPEG_QUALITY, quality);
2943 } else {
2944 LOGE("Invalid jpeg quality=%d", quality);
2945 rc = BAD_VALUE;
2946 }
2947
2948 quality = params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY);
2949 if (quality > 0 && quality <= 100) {
2950 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, quality);
2951 } else {
2952 LOGE("Invalid jpeg thumbnail quality=%d", quality);
2953 rc = BAD_VALUE;
2954 }
2955 return rc;
2956}
2957
2958status_t QualcommCameraHardware::setEffect(const CameraParameters& params)
2959{
2960 const char *str = params.get(CameraParameters::KEY_EFFECT);
2961 if (str != NULL) {
2962 int32_t value = attr_lookup(effects, sizeof(effects) / sizeof(str_map), str);
2963 if (value != NOT_FOUND) {
Mohan Kandra93f1bfb2009-12-15 16:55:33 -08002964 if(!strcmp(sensorType->name, "2mp") && (value != CAMERA_EFFECT_OFF)
2965 &&(value != CAMERA_EFFECT_MONO) && (value != CAMERA_EFFECT_NEGATIVE)
2966 &&(value != CAMERA_EFFECT_SOLARIZE) && (value != CAMERA_EFFECT_SEPIA)) {
2967 LOGE("Special effect parameter is not supported for this sensor");
2968 return NO_ERROR;
2969 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002970 mParameters.set(CameraParameters::KEY_EFFECT, str);
2971 bool ret = native_set_parm(CAMERA_SET_PARM_EFFECT, sizeof(value),
2972 (void *)&value);
2973 return ret ? NO_ERROR : UNKNOWN_ERROR;
2974 }
2975 }
2976 LOGE("Invalid effect value: %s", (str == NULL) ? "NULL" : str);
2977 return BAD_VALUE;
2978}
2979
Apurva Rajguru55562b02009-12-03 12:25:35 -08002980status_t QualcommCameraHardware::setAutoExposure(const CameraParameters& params)
2981{
Mohan Kandra93f1bfb2009-12-15 16:55:33 -08002982 if(!strcmp(sensorType->name, "2mp")) {
2983 LOGE("Auto Exposure not supported for this sensor");
2984 return NO_ERROR;
2985 }
Apurva Rajguru55562b02009-12-03 12:25:35 -08002986 const char *str = params.get(CameraParameters::KEY_AUTO_EXPOSURE);
2987 if (str != NULL) {
2988 int32_t value = attr_lookup(autoexposure, sizeof(autoexposure) / sizeof(str_map), str);
2989 if (value != NOT_FOUND) {
2990 mParameters.set(CameraParameters::KEY_AUTO_EXPOSURE, str);
2991 bool ret = native_set_parm(CAMERA_SET_PARM_EXPOSURE, sizeof(value),
2992 (void *)&value);
2993 return ret ? NO_ERROR : UNKNOWN_ERROR;
2994 }
2995 }
2996 LOGE("Invalid auto exposure value: %s", (str == NULL) ? "NULL" : str);
2997 return BAD_VALUE;
2998}
2999
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003000status_t QualcommCameraHardware::setSharpness(const CameraParameters& params)
3001{
3002 if(!strcmp(sensorType->name, "2mp")) {
3003 LOGE("Sharpness not supported for this sensor");
3004 return NO_ERROR;
3005 }
3006 int sharpness = params.getInt(CameraParameters::KEY_SHARPNESS);
3007 if((sharpness < CAMERA_MIN_SHARPNESS
3008 || sharpness > CAMERA_MAX_SHARPNESS))
3009 return UNKNOWN_ERROR;
3010 if (mSharpness != sharpness) {
3011 mSharpness = sharpness;
3012 bool ret = native_set_parm(CAMERA_SET_PARM_SHARPNESS, sizeof(mSharpness),
3013 (void *)&mSharpness);
3014 return ret ? NO_ERROR : UNKNOWN_ERROR;
3015 } else {
3016 return NO_ERROR;
3017 }
3018}
3019
3020status_t QualcommCameraHardware::setContrast(const CameraParameters& params)
3021{
3022 if(!strcmp(sensorType->name, "2mp")) {
3023 LOGE("Contrast not supported for this sensor");
3024 return NO_ERROR;
3025 }
3026 int contrast = params.getInt(CameraParameters::KEY_CONTRAST);
3027 if((contrast < CAMERA_MIN_CONTRAST)
3028 || (contrast > CAMERA_MAX_CONTRAST))
3029 return UNKNOWN_ERROR;
3030 if (mContrast != contrast) {
3031 mContrast = contrast;
3032 bool ret = native_set_parm(CAMERA_SET_PARM_CONTRAST, sizeof(mContrast),
3033 (void *)&mContrast);
3034 return ret ? NO_ERROR : UNKNOWN_ERROR;
3035 } else {
3036 return NO_ERROR;
3037 }
3038}
3039
3040status_t QualcommCameraHardware::setSaturation(const CameraParameters& params)
3041{
3042 if(!strcmp(sensorType->name, "2mp")) {
3043 LOGE("Saturation not supported for this sensor");
3044 return NO_ERROR;
3045 }
3046 int saturation = params.getInt(CameraParameters::KEY_SATURATION);
3047 if((saturation < CAMERA_MIN_SATURATION)
3048 || (saturation > CAMERA_MAX_SATURATION))
3049 return UNKNOWN_ERROR;
3050 if (mSaturation != saturation) {
3051 mSaturation = saturation;
3052 bool ret = native_set_parm(CAMERA_SET_PARM_SATURATION, sizeof(mSaturation),
3053 (void *)&mSaturation);
3054 return ret ? NO_ERROR : UNKNOWN_ERROR;
3055 } else {
3056 return NO_ERROR;
3057 }
3058}
3059
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303060status_t QualcommCameraHardware::setBrightness(const CameraParameters& params) {
3061 int brightness = params.getInt("luma-adaptation");
3062 if (mBrightness != brightness) {
3063 LOGV(" new brightness value : %d ", brightness);
3064 mBrightness = brightness;
3065
3066 bool ret = native_set_parm(CAMERA_SET_PARM_BRIGHTNESS, sizeof(mBrightness),
3067 (void *)&mBrightness);
3068 return ret ? NO_ERROR : UNKNOWN_ERROR;
3069 } else {
3070 return NO_ERROR;
3071 }
3072}
3073
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003074status_t QualcommCameraHardware::setWhiteBalance(const CameraParameters& params)
3075{
3076 const char *str = params.get(CameraParameters::KEY_WHITE_BALANCE);
3077 if (str != NULL) {
3078 int32_t value = attr_lookup(whitebalance, sizeof(whitebalance) / sizeof(str_map), str);
3079 if (value != NOT_FOUND) {
3080 mParameters.set(CameraParameters::KEY_WHITE_BALANCE, str);
3081 bool ret = native_set_parm(CAMERA_SET_PARM_WB, sizeof(value),
3082 (void *)&value);
3083 return ret ? NO_ERROR : UNKNOWN_ERROR;
3084 }
3085 }
3086 LOGE("Invalid whitebalance value: %s", (str == NULL) ? "NULL" : str);
3087 return BAD_VALUE;
3088}
3089
3090status_t QualcommCameraHardware::setFlash(const CameraParameters& params)
3091{
3092 if (!mSensorInfo.flash_enabled) {
3093 LOGV("%s: flash not supported", __FUNCTION__);
3094 return NO_ERROR;
3095 }
3096
3097 const char *str = params.get(CameraParameters::KEY_FLASH_MODE);
3098 if (str != NULL) {
3099 int32_t value = attr_lookup(flash, sizeof(flash) / sizeof(str_map), str);
3100 if (value != NOT_FOUND) {
3101 mParameters.set(CameraParameters::KEY_FLASH_MODE, str);
3102 bool ret = native_set_parm(CAMERA_SET_PARM_LED_MODE,
3103 sizeof(value), (void *)&value);
3104 return ret ? NO_ERROR : UNKNOWN_ERROR;
3105 }
3106 }
3107 LOGE("Invalid flash mode value: %s", (str == NULL) ? "NULL" : str);
3108 return BAD_VALUE;
3109}
3110
3111status_t QualcommCameraHardware::setAntibanding(const CameraParameters& params)
3112{
Srinivasan Kannan2229d272010-01-05 14:58:28 -08003113 if(!strcmp(sensorType->name, "2mp")) {
3114 LOGE("Parameter AntiBanding is not supported for this sensor");
3115 return NO_ERROR;
3116 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003117 const char *str = params.get(CameraParameters::KEY_ANTIBANDING);
3118 if (str != NULL) {
3119 int value = (camera_antibanding_type)attr_lookup(
3120 antibanding, sizeof(antibanding) / sizeof(str_map), str);
3121 if (value != NOT_FOUND) {
3122 camera_antibanding_type temp = (camera_antibanding_type) value;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003123 mParameters.set(CameraParameters::KEY_ANTIBANDING, str);
Srinivasan Kannan2229d272010-01-05 14:58:28 -08003124 bool ret;
3125 if (temp == CAMERA_ANTIBANDING_AUTO) {
3126 ret = native_set_parm(CAMERA_ENABLE_AFD,
3127 0, NULL);
3128 } else {
3129 ret = native_set_parm(CAMERA_SET_PARM_ANTIBANDING,
3130 sizeof(camera_antibanding_type), (void *)&temp);
3131 }
3132 return ret ? NO_ERROR : UNKNOWN_ERROR;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003133 }
3134 }
3135 LOGE("Invalid antibanding value: %s", (str == NULL) ? "NULL" : str);
3136 return BAD_VALUE;
3137}
3138
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303139status_t QualcommCameraHardware::setLensshadeValue(const CameraParameters& params)
3140{
Mohan Kandra93f1bfb2009-12-15 16:55:33 -08003141 if(!strcmp(sensorType->name, "2mp")) {
3142 LOGE("Parameter Rolloff is not supported for this sensor");
3143 return NO_ERROR;
3144 }
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303145 const char *str = params.get(CameraParameters::KEY_LENSSHADE);
3146 if (str != NULL) {
3147 int value = attr_lookup(lensshade,
3148 sizeof(lensshade) / sizeof(str_map), str);
3149 if (value != NOT_FOUND) {
3150 int8_t temp = (int8_t)value;
3151 mParameters.set(CameraParameters::KEY_LENSSHADE, str);
3152 native_set_parm(CAMERA_SET_PARM_ROLLOFF, sizeof(int8_t), (void *)&temp);
3153 return NO_ERROR;
3154 }
3155 }
3156 LOGE("Invalid lensShade value: %s", (str == NULL) ? "NULL" : str);
3157 return BAD_VALUE;
3158}
3159
3160status_t QualcommCameraHardware::setISOValue(const CameraParameters& params) {
3161 const char *str = params.get(CameraParameters::KEY_ISO_MODE);
3162 if (str != NULL) {
3163 int value = (camera_iso_mode_type)attr_lookup(
3164 iso, sizeof(iso) / sizeof(str_map), str);
3165 if (value != NOT_FOUND) {
3166 camera_iso_mode_type temp = (camera_iso_mode_type) value;
3167 mParameters.set(CameraParameters::KEY_ISO_MODE, str);
3168 native_set_parm(CAMERA_SET_PARM_ISO, sizeof(camera_iso_mode_type), (void *)&temp);
3169 return NO_ERROR;
3170 }
3171 }
3172 LOGE("Invalid Iso value: %s", (str == NULL) ? "NULL" : str);
3173 return BAD_VALUE;
3174}
3175
3176
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003177status_t QualcommCameraHardware::setGpsLocation(const CameraParameters& params)
3178{
3179 const char *latitude = params.get(CameraParameters::KEY_GPS_LATITUDE);
3180 if (latitude) {
3181 mParameters.set(CameraParameters::KEY_GPS_LATITUDE, latitude);
3182 }
3183
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08003184 const char *latitudeRef = params.get(CameraParameters::KEY_GPS_LATITUDE_REF);
3185 if (latitudeRef) {
3186 mParameters.set(CameraParameters::KEY_GPS_LATITUDE_REF, latitudeRef);
3187 }
3188
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003189 const char *longitude = params.get(CameraParameters::KEY_GPS_LONGITUDE);
3190 if (longitude) {
3191 mParameters.set(CameraParameters::KEY_GPS_LONGITUDE, longitude);
3192 }
3193
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08003194 const char *longitudeRef = params.get(CameraParameters::KEY_GPS_LONGITUDE_REF);
3195 if (longitudeRef) {
3196 mParameters.set(CameraParameters::KEY_GPS_LONGITUDE_REF, longitudeRef);
3197 }
3198
3199 const char *altitudeRef = params.get(CameraParameters::KEY_GPS_ALTITUDE_REF);
3200 if (altitudeRef) {
3201 mParameters.set(CameraParameters::KEY_GPS_ALTITUDE_REF, altitudeRef);
3202 }
3203
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003204 const char *altitude = params.get(CameraParameters::KEY_GPS_ALTITUDE);
3205 if (altitude) {
3206 mParameters.set(CameraParameters::KEY_GPS_ALTITUDE, altitude);
3207 }
3208
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08003209 const char *status = params.get(CameraParameters::KEY_GPS_STATUS);
3210 if (status) {
3211 mParameters.set(CameraParameters::KEY_GPS_STATUS, status);
3212 }
3213
3214 const char *dateTime = params.get(CameraParameters::KEY_EXIF_DATETIME);
3215 if (dateTime) {
3216 mParameters.set(CameraParameters::KEY_EXIF_DATETIME, dateTime);
3217 }
3218
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003219 const char *timestamp = params.get(CameraParameters::KEY_GPS_TIMESTAMP);
3220 if (timestamp) {
3221 mParameters.set(CameraParameters::KEY_GPS_TIMESTAMP, timestamp);
3222 }
3223 return NO_ERROR;
3224}
3225
3226status_t QualcommCameraHardware::setRotation(const CameraParameters& params)
3227{
3228 status_t rc = NO_ERROR;
3229 int rotation = params.getInt(CameraParameters::KEY_ROTATION);
3230 if (rotation != NOT_FOUND) {
3231 if (rotation == 0 || rotation == 90 || rotation == 180
3232 || rotation == 270) {
3233 mParameters.set(CameraParameters::KEY_ROTATION, rotation);
3234 } else {
3235 LOGE("Invalid rotation value: %d", rotation);
3236 rc = BAD_VALUE;
3237 }
3238 }
3239 return rc;
3240}
3241
3242status_t QualcommCameraHardware::setZoom(const CameraParameters& params)
3243{
3244 status_t rc = NO_ERROR;
3245 // No matter how many different zoom values the driver can provide, HAL
3246 // provides applictations the same number of zoom levels. The maximum driver
3247 // zoom value depends on sensor output (VFE input) and preview size (VFE
3248 // output) because VFE can only crop and cannot upscale. If the preview size
3249 // is bigger, the maximum zoom ratio is smaller. However, we want the
3250 // zoom ratio of each zoom level is always the same whatever the preview
3251 // size is. Ex: zoom level 1 is always 1.2x, zoom level 2 is 1.44x, etc. So,
3252 // we need to have a fixed maximum zoom value and do read it from the
3253 // driver.
Mohan Kandra284966d2010-01-05 13:39:15 -08003254 static const int ZOOM_STEP = 1;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003255 int32_t zoom_level = params.getInt("zoom");
3256
Mohan Kandra284966d2010-01-05 13:39:15 -08003257 LOGV("Set zoom=%d", zoom_level);
3258 if(zoom_level >= 0 && zoom_level <= mMaxZoom) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003259 mParameters.set("zoom", zoom_level);
3260 int32_t zoom_value = ZOOM_STEP * zoom_level;
3261 bool ret = native_set_parm(CAMERA_SET_PARM_ZOOM,
3262 sizeof(zoom_value), (void *)&zoom_value);
3263 rc = ret ? NO_ERROR : UNKNOWN_ERROR;
3264 } else {
3265 rc = BAD_VALUE;
3266 }
3267
3268 return rc;
3269}
3270
3271status_t QualcommCameraHardware::setFocusMode(const CameraParameters& params)
3272{
3273 const char *str = params.get(CameraParameters::KEY_FOCUS_MODE);
3274 if (str != NULL) {
3275 int32_t value = attr_lookup(focus_modes,
3276 sizeof(focus_modes) / sizeof(str_map), str);
3277 if (value != NOT_FOUND) {
3278 mParameters.set(CameraParameters::KEY_FOCUS_MODE, str);
3279 // Focus step is reset to infinity when preview is started. We do
3280 // not need to do anything now.
3281 return NO_ERROR;
3282 }
3283 }
3284 LOGE("Invalid focus mode value: %s", (str == NULL) ? "NULL" : str);
3285 return BAD_VALUE;
3286}
3287
3288status_t QualcommCameraHardware::setOrientation(const CameraParameters& params)
3289{
3290 const char *str = params.get("orientation");
3291
3292 if (str != NULL) {
3293 if (strcmp(str, "portrait") == 0 || strcmp(str, "landscape") == 0) {
3294 // Camera service needs this to decide if the preview frames and raw
3295 // pictures should be rotated.
3296 mParameters.set("orientation", str);
3297 } else {
3298 LOGE("Invalid orientation value: %s", str);
3299 return BAD_VALUE;
3300 }
3301 }
3302 return NO_ERROR;
3303}
3304
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08003305status_t QualcommCameraHardware::setPictureFormat(const CameraParameters& params)
3306{
3307 const char * str = params.get(CameraParameters::KEY_PICTURE_FORMAT);
3308
3309 if(str != NULL){
3310 int32_t value = attr_lookup(picture_formats,
3311 sizeof(picture_formats) / sizeof(str_map), str);
3312 if(value != NOT_FOUND){
3313 mParameters.set(CameraParameters::KEY_PICTURE_FORMAT, str);
3314 } else {
3315 LOGE("Invalid Picture Format value: %s", str);
3316 return BAD_VALUE;
3317 }
3318 }
3319 return NO_ERROR;
3320}
3321
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003322QualcommCameraHardware::MemPool::MemPool(int buffer_size, int num_buffers,
3323 int frame_size,
3324 const char *name) :
3325 mBufferSize(buffer_size),
3326 mNumBuffers(num_buffers),
3327 mFrameSize(frame_size),
3328 mBuffers(NULL), mName(name)
3329{
3330 int page_size_minus_1 = getpagesize() - 1;
3331 mAlignedBufferSize = (buffer_size + page_size_minus_1) & (~page_size_minus_1);
3332}
3333
3334void QualcommCameraHardware::MemPool::completeInitialization()
3335{
3336 // If we do not know how big the frame will be, we wait to allocate
3337 // the buffers describing the individual frames until we do know their
3338 // size.
3339
3340 if (mFrameSize > 0) {
3341 mBuffers = new sp<MemoryBase>[mNumBuffers];
3342 for (int i = 0; i < mNumBuffers; i++) {
3343 mBuffers[i] = new
3344 MemoryBase(mHeap,
3345 i * mAlignedBufferSize,
3346 mFrameSize);
3347 }
3348 }
3349}
3350
3351QualcommCameraHardware::AshmemPool::AshmemPool(int buffer_size, int num_buffers,
3352 int frame_size,
3353 const char *name) :
3354 QualcommCameraHardware::MemPool(buffer_size,
3355 num_buffers,
3356 frame_size,
3357 name)
3358{
3359 LOGV("constructing MemPool %s backed by ashmem: "
3360 "%d frames @ %d uint8_ts, "
3361 "buffer size %d",
3362 mName,
3363 num_buffers, frame_size, buffer_size);
3364
3365 int page_mask = getpagesize() - 1;
3366 int ashmem_size = buffer_size * num_buffers;
3367 ashmem_size += page_mask;
3368 ashmem_size &= ~page_mask;
3369
3370 mHeap = new MemoryHeapBase(ashmem_size);
3371
3372 completeInitialization();
3373}
3374
3375static bool register_buf(int camfd,
3376 int size,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08003377 int frame_size,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003378 int pmempreviewfd,
3379 uint32_t offset,
3380 uint8_t *buf,
3381 int pmem_type,
3382 bool vfe_can_write,
3383 bool register_buffer = true);
3384
3385QualcommCameraHardware::PmemPool::PmemPool(const char *pmem_pool,
3386 int flags,
3387 int camera_control_fd,
3388 int pmem_type,
3389 int buffer_size, int num_buffers,
3390 int frame_size,
3391 const char *name) :
3392 QualcommCameraHardware::MemPool(buffer_size,
3393 num_buffers,
3394 frame_size,
3395 name),
3396 mPmemType(pmem_type),
3397 mCameraControlFd(dup(camera_control_fd))
3398{
3399 LOGV("constructing MemPool %s backed by pmem pool %s: "
3400 "%d frames @ %d bytes, buffer size %d",
3401 mName,
3402 pmem_pool, num_buffers, frame_size,
3403 buffer_size);
3404
Kiran Kumar H N494c9fc2010-01-07 15:55:15 -08003405 if( mCameraControlFd == 0 ) {
3406 /* This should not happen. But if and when it
3407 * happens, we should not be using fd 0 for issuing
3408 * any IOCTL calls to camera driver since the
3409 * behaviour is undeterministic. Hence adding a
3410 * workaround to deal with this issue */
3411 LOGD(" 'dup'ed FD is 0....dup again ");
3412 mCameraControlFd = dup(camera_control_fd);
3413 }
3414
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003415 LOGV("%s: duplicating control fd %d --> %d",
3416 __FUNCTION__,
3417 camera_control_fd, mCameraControlFd);
3418
3419 // Make a new mmap'ed heap that can be shared across processes.
3420 // mAlignedBufferSize is already in 4k aligned. (do we need total size necessary to be in power of 2??)
3421 mAlignedSize = mAlignedBufferSize * num_buffers;
3422
3423 sp<MemoryHeapBase> masterHeap =
3424 new MemoryHeapBase(pmem_pool, mAlignedSize, flags);
3425
3426 if (masterHeap->getHeapID() < 0) {
3427 LOGE("failed to construct master heap for pmem pool %s", pmem_pool);
3428 masterHeap.clear();
3429 return;
3430 }
3431
3432 sp<MemoryHeapPmem> pmemHeap = new MemoryHeapPmem(masterHeap, flags);
3433 if (pmemHeap->getHeapID() >= 0) {
3434 pmemHeap->slap();
3435 masterHeap.clear();
3436 mHeap = pmemHeap;
3437 pmemHeap.clear();
3438
3439 mFd = mHeap->getHeapID();
3440 if (::ioctl(mFd, PMEM_GET_SIZE, &mSize)) {
3441 LOGE("pmem pool %s ioctl(PMEM_GET_SIZE) error %s (%d)",
3442 pmem_pool,
3443 ::strerror(errno), errno);
3444 mHeap.clear();
3445 return;
3446 }
3447
3448 LOGV("pmem pool %s ioctl(fd = %d, PMEM_GET_SIZE) is %ld",
3449 pmem_pool,
3450 mFd,
3451 mSize.len);
Mohan Kandra284966d2010-01-05 13:39:15 -08003452 LOGD("mBufferSize=%d, mAlignedBufferSize=%d\n", mBufferSize, mAlignedBufferSize);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003453 // Unregister preview buffers with the camera drivers. Allow the VFE to write
3454 // to all preview buffers except for the last one.
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003455 // Only Register the preview, snapshot and thumbnail buffers with the kernel.
3456 if( (strcmp("preview", mName) != 0)
3457 && (strcmp("postview", mName) != 0) ){
Mohan Kandra284966d2010-01-05 13:39:15 -08003458 for (int cnt = 0; cnt < num_buffers; ++cnt) {
3459 register_buf(mCameraControlFd,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003460 mBufferSize,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08003461 mFrameSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003462 mHeap->getHeapID(),
3463 mAlignedBufferSize * cnt,
3464 (uint8_t *)mHeap->base() + mAlignedBufferSize * cnt,
3465 pmem_type,
3466 !(cnt == num_buffers - 1 && pmem_type == MSM_PMEM_OUTPUT2));
Mohan Kandra284966d2010-01-05 13:39:15 -08003467 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003468 }
3469
3470 completeInitialization();
3471 }
3472 else LOGE("pmem pool %s error: could not create master heap!",
3473 pmem_pool);
3474}
3475
3476QualcommCameraHardware::PmemPool::~PmemPool()
3477{
3478 LOGV("%s: %s E", __FUNCTION__, mName);
3479 if (mHeap != NULL) {
3480 // Unregister preview buffers with the camera drivers.
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003481 // Only Unregister the preview, snapshot and thumbnail
3482 // buffers with the kernel.
3483 if( (strcmp("preview", mName) != 0)
3484 && (strcmp("postview", mName) != 0) ){
Mohan Kandra284966d2010-01-05 13:39:15 -08003485 for (int cnt = 0; cnt < mNumBuffers; ++cnt) {
3486 register_buf(mCameraControlFd,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003487 mBufferSize,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08003488 mFrameSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003489 mHeap->getHeapID(),
3490 mAlignedBufferSize * cnt,
3491 (uint8_t *)mHeap->base() + mAlignedBufferSize * cnt,
3492 mPmemType,
3493 false,
3494 false /* unregister */);
Mohan Kandra284966d2010-01-05 13:39:15 -08003495 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003496 }
3497 }
3498 LOGV("destroying PmemPool %s: closing control fd %d",
3499 mName,
3500 mCameraControlFd);
3501 close(mCameraControlFd);
3502 LOGV("%s: %s X", __FUNCTION__, mName);
3503}
3504
3505QualcommCameraHardware::MemPool::~MemPool()
3506{
3507 LOGV("destroying MemPool %s", mName);
3508 if (mFrameSize > 0)
3509 delete [] mBuffers;
3510 mHeap.clear();
3511 LOGV("destroying MemPool %s completed", mName);
3512}
3513
3514static bool register_buf(int camfd,
3515 int size,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08003516 int frame_size,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003517 int pmempreviewfd,
3518 uint32_t offset,
3519 uint8_t *buf,
3520 int pmem_type,
3521 bool vfe_can_write,
3522 bool register_buffer)
3523{
3524 struct msm_pmem_info pmemBuf;
3525
3526 pmemBuf.type = pmem_type;
3527 pmemBuf.fd = pmempreviewfd;
3528 pmemBuf.offset = offset;
3529 pmemBuf.len = size;
3530 pmemBuf.vaddr = buf;
3531 pmemBuf.y_off = 0;
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08003532 pmemBuf.cbcr_off = PAD_TO_WORD(frame_size * 2 / 3);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003533 pmemBuf.active = vfe_can_write;
3534
3535 LOGV("register_buf: camfd = %d, reg = %d buffer = %p",
3536 camfd, !register_buffer, buf);
3537 if (ioctl(camfd,
3538 register_buffer ?
3539 MSM_CAM_IOCTL_REGISTER_PMEM :
3540 MSM_CAM_IOCTL_UNREGISTER_PMEM,
3541 &pmemBuf) < 0) {
3542 LOGE("register_buf: MSM_CAM_IOCTL_(UN)REGISTER_PMEM fd %d error %s",
3543 camfd,
3544 strerror(errno));
3545 return false;
3546 }
3547 return true;
3548}
3549
3550status_t QualcommCameraHardware::MemPool::dump(int fd, const Vector<String16>& args) const
3551{
3552 const size_t SIZE = 256;
3553 char buffer[SIZE];
3554 String8 result;
3555 snprintf(buffer, 255, "QualcommCameraHardware::AshmemPool::dump\n");
3556 result.append(buffer);
3557 if (mName) {
3558 snprintf(buffer, 255, "mem pool name (%s)\n", mName);
3559 result.append(buffer);
3560 }
3561 if (mHeap != 0) {
3562 snprintf(buffer, 255, "heap base(%p), size(%d), flags(%d), device(%s)\n",
3563 mHeap->getBase(), mHeap->getSize(),
3564 mHeap->getFlags(), mHeap->getDevice());
3565 result.append(buffer);
3566 }
3567 snprintf(buffer, 255,
3568 "buffer size (%d), number of buffers (%d), frame size(%d)",
3569 mBufferSize, mNumBuffers, mFrameSize);
3570 result.append(buffer);
3571 write(fd, result.string(), result.size());
3572 return NO_ERROR;
3573}
3574
3575static void receive_camframe_callback(struct msm_frame *frame)
3576{
3577 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
3578 if (obj != 0) {
3579 obj->receivePreviewFrame(frame);
3580 }
3581}
3582
3583static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size)
3584{
3585 LOGV("receive_jpeg_fragment_callback E");
3586 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
3587 if (obj != 0) {
3588 obj->receiveJpegPictureFragment(buff_ptr, buff_size);
3589 }
3590 LOGV("receive_jpeg_fragment_callback X");
3591}
3592
3593static void receive_jpeg_callback(jpeg_event_t status)
3594{
3595 LOGV("receive_jpeg_callback E (completion status %d)", status);
3596 if (status == JPEG_EVENT_DONE) {
3597 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
3598 if (obj != 0) {
3599 obj->receiveJpegPicture();
3600 }
3601 }
3602 LOGV("receive_jpeg_callback X");
3603}
3604
3605void QualcommCameraHardware::setCallbacks(notify_callback notify_cb,
3606 data_callback data_cb,
3607 data_callback_timestamp data_cb_timestamp,
3608 void* user)
3609{
3610 Mutex::Autolock lock(mLock);
3611 mNotifyCallback = notify_cb;
3612 mDataCallback = data_cb;
3613 mDataCallbackTimestamp = data_cb_timestamp;
3614 mCallbackCookie = user;
3615}
3616
3617void QualcommCameraHardware::enableMsgType(int32_t msgType)
3618{
3619 Mutex::Autolock lock(mLock);
3620 mMsgEnabled |= msgType;
3621}
3622
3623void QualcommCameraHardware::disableMsgType(int32_t msgType)
3624{
3625 Mutex::Autolock lock(mLock);
3626 mMsgEnabled &= ~msgType;
3627}
3628
3629bool QualcommCameraHardware::msgTypeEnabled(int32_t msgType)
3630{
3631 return (mMsgEnabled & msgType);
3632}
3633
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08003634bool QualcommCameraHardware::useOverlay(void)
3635{
Mohan Kandra284966d2010-01-05 13:39:15 -08003636 if(!strcmp(mDeviceName,"msm7630_surf")) {
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08003637 /* Only 7x30 supports Overlay */
3638 mUseOverlay = TRUE;
3639 } else
3640 mUseOverlay = FALSE;
3641
3642 LOGV(" Using Overlay : %s ", mUseOverlay ? "YES" : "NO" );
3643 return mUseOverlay;
3644}
3645
3646status_t QualcommCameraHardware::setOverlay(const sp<Overlay> &Overlay)
3647{
3648 if( Overlay != NULL) {
3649 LOGV(" Valid overlay object ");
3650 mOverlayLock.lock();
3651 mOverlay = Overlay;
3652 mOverlayLock.unlock();
3653 } else {
3654 LOGE(" Overlay object NULL. returning ");
3655 return UNKNOWN_ERROR;
3656 }
3657 return NO_ERROR;
3658}
Kiran Kumar H N215cac42009-12-08 01:53:46 -08003659
3660void QualcommCameraHardware::receive_camframetimeout(void) {
3661 LOGV("receive_camframetimeout: E");
3662 Mutex::Autolock l(&mCamframeTimeoutLock);
3663 camframe_timeout_flag = TRUE;
3664 LOGV("receive_camframetimeout: X");
3665}
3666
3667static void receive_camframetimeout_callback(void) {
3668 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
3669 if (obj != 0) {
3670 obj->receive_camframetimeout();
3671 }
3672}
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003673
3674void QualcommCameraHardware::storePreviewFrameForPostview(void) {
3675 LOGV(" storePreviewFrameForPostview : E ");
3676
3677 /* Since there is restriction on the maximum overlay dimensions
3678 * that can be created, we use the last preview frame as postview
3679 * for 7x30. */
3680 LOGV(" Copying the preview buffer to postview buffer %d ",
3681 mPreviewFrameSize);
3682 if( mPostViewHeap != NULL && mLastQueuedFrame != NULL) {
3683 memcpy(mPostViewHeap->mHeap->base(),
3684 (uint8_t *)mLastQueuedFrame, mPreviewFrameSize );
3685 } else
3686 LOGE(" Failed to store Preview frame. No Postview ");
3687
3688 LOGV(" storePreviewFrameForPostview : X ");
3689}
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003690}; // namespace android