blob: db04f01eb895f7625b3aa35ad7c49cbe03e1196c [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
Mohan Kandrad9efed92010-01-15 19:08:39 -0800635static int dstOffset = 0;
636
637/* When using MDP zoom, double the preview buffers. The usage of these
638 * buffers is as follows:
639 * 1. As all the buffers comes under a single FD, and at initial registration,
640 * this FD will be passed to surface flinger, surface flinger can have access
641 * to all the buffers when needed.
642 * 2. Only "kPreviewBufferCount" buffers (SrcSet) will be registered with the
643 * camera driver to receive preview frames. The remaining buffers (DstSet),
644 * will be used at HAL and by surface flinger only when crop information
645 * is present in the frame.
646 * 3. When there is no crop information, there will be no call to MDP zoom,
647 * and the buffers in SrcSet will be passed to surface flinger to display.
648 * 4. With crop information present, MDP zoom will be called, and the final
649 * data will be placed in a buffer from DstSet, and this buffer will be given
650 * to surface flinger to display.
651 */
652#define NUM_MORE_BUFS 2
653
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800654QualcommCameraHardware::QualcommCameraHardware()
655 : mParameters(),
656 mCameraRunning(false),
657 mPreviewInitialized(false),
658 mFrameThreadRunning(false),
659 mSnapshotThreadRunning(false),
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800660 mSnapshotFormat(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800661 mReleasedRecordingFrame(false),
662 mPreviewFrameSize(0),
663 mRawSize(0),
664 mCameraControlFd(-1),
665 mAutoFocusThreadRunning(false),
666 mAutoFocusFd(-1),
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800667 mBrightness(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800668 mInPreviewCallback(false),
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800669 mUseOverlay(0),
670 mOverlay(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800671 mMsgEnabled(0),
672 mNotifyCallback(0),
673 mDataCallback(0),
674 mDataCallbackTimestamp(0),
Mohan Kandra740cfce2010-01-07 12:58:24 -0800675 mCallbackCookie(0),
676 mDebugFps(0)
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800677{
678 memset(&mDimension, 0, sizeof(mDimension));
679 memset(&mCrop, 0, sizeof(mCrop));
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -0800680 memset(&zoomCropInfo, 0, sizeof(zoom_crop_info));
Mohan Kandra284966d2010-01-05 13:39:15 -0800681 property_get("ro.product.device",mDeviceName," ");
Mohan Kandra740cfce2010-01-07 12:58:24 -0800682 char value[PROPERTY_VALUE_MAX];
683 property_get("persist.debug.sf.showfps", value, "0");
684 mDebugFps = atoi(value);
Mohan Kandrad9efed92010-01-15 19:08:39 -0800685 kPreviewBufferCountActual = kPreviewBufferCount + NUM_MORE_BUFS;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800686 LOGV("constructor EX");
687}
688
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800689
690//filter Picture sizes based on max width and height
691void QualcommCameraHardware::filterPictureSizes(){
692 int i;
693 for(i=0;i<PICTURE_SIZE_COUNT;i++){
694 if(((picture_sizes[i].width <=
695 sensorType->max_supported_snapshot_width) &&
696 (picture_sizes[i].height <=
697 sensorType->max_supported_snapshot_height))){
698 picture_sizes_ptr = picture_sizes + i;
699 supportedPictureSizesCount = PICTURE_SIZE_COUNT - i ;
700 return ;
701 }
702 }
703}
704
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800705void QualcommCameraHardware::initDefaultParameters()
706{
707 LOGV("initDefaultParameters E");
708
709 // Initialize constant parameter strings. This will happen only once in the
710 // lifetime of the mediaserver process.
711 if (!parameter_string_initialized) {
Srinivasan Kannan71229622009-12-04 12:05:58 -0800712 findSensorType();
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800713 antibanding_values = create_values_str(
714 antibanding, sizeof(antibanding) / sizeof(str_map));
715 effect_values = create_values_str(
716 effects, sizeof(effects) / sizeof(str_map));
Apurva Rajguru55562b02009-12-03 12:25:35 -0800717 autoexposure_values = create_values_str(
718 autoexposure, sizeof(autoexposure) / sizeof(str_map));
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800719 whitebalance_values = create_values_str(
720 whitebalance, sizeof(whitebalance) / sizeof(str_map));
721 preview_size_values = create_sizes_str(
722 preview_sizes, PREVIEW_SIZE_COUNT);
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800723 //filter picture sizes
724 filterPictureSizes();
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800725 picture_size_values = create_sizes_str(
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800726 picture_sizes_ptr, supportedPictureSizesCount);
727
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800728 flash_values = create_values_str(
729 flash, sizeof(flash) / sizeof(str_map));
Srinivasan Kannan71229622009-12-04 12:05:58 -0800730 if(sensorType->hasAutoFocusSupport){
731 focus_mode_values = create_values_str(
732 focus_modes, sizeof(focus_modes) / sizeof(str_map));
733 }
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530734 iso_values = create_values_str(
735 iso,sizeof(iso)/sizeof(str_map));
736 lensshade_values = create_values_str(
737 lensshade,sizeof(lensshade)/sizeof(str_map));
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800738 picture_format_values = create_values_str(
739 picture_formats, sizeof(picture_formats)/sizeof(str_map));
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800740 parameter_string_initialized = true;
741 }
742
743 const camera_size_type *ps = &preview_sizes[DEFAULT_PREVIEW_SETTING];
744 mParameters.setPreviewSize(ps->width, ps->height);
745 mDimension.display_width = ps->width;
746 mDimension.display_height = ps->height;
747 mParameters.setPreviewFrameRate(15);
748 mParameters.setPreviewFormat("yuv420sp"); // informative
749
750 mParameters.setPictureSize(DEFAULT_PICTURE_WIDTH, DEFAULT_PICTURE_HEIGHT);
751 mParameters.setPictureFormat("jpeg"); // informative
752
753 mParameters.set(CameraParameters::KEY_JPEG_QUALITY, "100"); // max quality
754 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH,
755 THUMBNAIL_WIDTH_STR); // informative
756 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT,
757 THUMBNAIL_HEIGHT_STR); // informative
Srinivasan Kannan80d878f2009-12-18 15:06:02 -0800758 mDimension.ui_thumbnail_width =
759 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].width;
760 mDimension.ui_thumbnail_height =
761 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800762 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, "90");
763
764 mParameters.set(CameraParameters::KEY_ANTIBANDING,
765 CameraParameters::ANTIBANDING_AUTO);
766 mParameters.set(CameraParameters::KEY_EFFECT,
767 CameraParameters::EFFECT_NONE);
Apurva Rajguru55562b02009-12-03 12:25:35 -0800768 mParameters.set(CameraParameters::KEY_AUTO_EXPOSURE,
769 CameraParameters::AUTO_EXPOSURE_FRAME_AVG);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800770 mParameters.set(CameraParameters::KEY_WHITE_BALANCE,
771 CameraParameters::WHITE_BALANCE_AUTO);
772 mParameters.set(CameraParameters::KEY_FOCUS_MODE,
773 CameraParameters::FOCUS_MODE_AUTO);
774
775 mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES,
776 preview_size_values.string());
777 mParameters.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES,
778 picture_size_values.string());
779 mParameters.set(CameraParameters::KEY_SUPPORTED_ANTIBANDING,
780 antibanding_values);
781 mParameters.set(CameraParameters::KEY_SUPPORTED_EFFECTS, effect_values);
Apurva Rajguru55562b02009-12-03 12:25:35 -0800782 mParameters.set(CameraParameters::KEY_SUPPORTED_AUTO_EXPOSURE, autoexposure_values);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800783 mParameters.set(CameraParameters::KEY_SUPPORTED_WHITE_BALANCE,
784 whitebalance_values);
785 mParameters.set(CameraParameters::KEY_SUPPORTED_FOCUS_MODES,
786 focus_mode_values);
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800787 mParameters.set(CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS,
788 picture_format_values);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800789
790 if (mSensorInfo.flash_enabled) {
791 mParameters.set(CameraParameters::KEY_FLASH_MODE,
792 CameraParameters::FLASH_MODE_OFF);
793 mParameters.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES,
794 flash_values);
795 }
796
Srinivasan Kannanbddfd502010-01-03 17:27:36 -0800797 mParameters.set(CameraParameters::KEY_MAX_SHARPNESS,
798 CAMERA_MAX_SHARPNESS);
799 mParameters.set(CameraParameters::KEY_MAX_CONTRAST,
800 CAMERA_MAX_CONTRAST);
801 mParameters.set(CameraParameters::KEY_MAX_SATURATION,
802 CAMERA_MAX_SATURATION);
803
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530804 mParameters.set("luma-adaptation", "18");
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800805 mParameters.set("zoom-supported", "true");
806 mParameters.set("max-zoom", MAX_ZOOM_LEVEL);
807 mParameters.set("zoom", 0);
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800808 mParameters.set(CameraParameters::KEY_PICTURE_FORMAT,
809 CameraParameters::PIXEL_FORMAT_JPEG);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800810
Kiran Kumar H N595970b2010-01-12 10:41:09 -0800811 mParameters.set(CameraParameters::KEY_SHARPNESS,
812 CAMERA_DEF_SHARPNESS);
813 mParameters.set(CameraParameters::KEY_CONTRAST,
814 CAMERA_DEF_CONTRAST);
815 mParameters.set(CameraParameters::KEY_SATURATION,
816 CAMERA_DEF_SATURATION);
817
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530818 mParameters.set(CameraParameters::KEY_ISO_MODE,
819 CameraParameters::ISO_AUTO);
820 mParameters.set(CameraParameters::KEY_LENSSHADE,
821 CameraParameters::LENSSHADE_ENABLE);
822 mParameters.set(CameraParameters::KEY_SUPPORTED_ISO_MODES,
823 iso_values);
824 mParameters.set(CameraParameters::KEY_SUPPORTED_LENSSHADE_MODES,
825 lensshade_values);
826
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800827 if (setParameters(mParameters) != NO_ERROR) {
828 LOGE("Failed to set default parameters?!");
829 }
830
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -0800831 mUseOverlay = useOverlay();
832
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800833 /* Initialize the camframe_timeout_flag*/
834 Mutex::Autolock l(&mCamframeTimeoutLock);
835 camframe_timeout_flag = FALSE;
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -0800836 mPostViewHeap = NULL;
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800837
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800838 LOGV("initDefaultParameters X");
839}
840
Srinivasan Kannan71229622009-12-04 12:05:58 -0800841void QualcommCameraHardware::findSensorType(){
842 mDimension.picture_width = DEFAULT_PICTURE_WIDTH;
843 mDimension.picture_height = DEFAULT_PICTURE_HEIGHT;
844 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
845 sizeof(cam_ctrl_dimension_t), &mDimension);
846 if (ret) {
847 unsigned int i;
848 for (i = 0; i < sizeof(sensorTypes) / sizeof(SensorType); i++) {
849 if (sensorTypes[i].rawPictureHeight
850 == mDimension.raw_picture_height) {
851 sensorType = sensorTypes + i;
852 return;
853 }
854 }
855 }
856 //default to 5 mp
857 sensorType = sensorTypes;
858 return;
859}
860
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800861#define ROUND_TO_PAGE(x) (((x)+0xfff)&~0xfff)
862
863bool QualcommCameraHardware::startCamera()
864{
865 LOGV("startCamera E");
866#if DLOPEN_LIBMMCAMERA
867 libmmcamera = ::dlopen("liboemcamera.so", RTLD_NOW);
868 LOGV("loading liboemcamera at %p", libmmcamera);
869 if (!libmmcamera) {
870 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
871 return false;
872 }
873
874 *(void **)&LINK_cam_frame =
875 ::dlsym(libmmcamera, "cam_frame");
876 *(void **)&LINK_camframe_terminate =
877 ::dlsym(libmmcamera, "camframe_terminate");
878
879 *(void **)&LINK_jpeg_encoder_init =
880 ::dlsym(libmmcamera, "jpeg_encoder_init");
881
882 *(void **)&LINK_jpeg_encoder_encode =
883 ::dlsym(libmmcamera, "jpeg_encoder_encode");
884
885 *(void **)&LINK_jpeg_encoder_join =
886 ::dlsym(libmmcamera, "jpeg_encoder_join");
887
888 *(void **)&LINK_mmcamera_camframe_callback =
889 ::dlsym(libmmcamera, "mmcamera_camframe_callback");
890
891 *LINK_mmcamera_camframe_callback = receive_camframe_callback;
892
893 *(void **)&LINK_mmcamera_jpegfragment_callback =
894 ::dlsym(libmmcamera, "mmcamera_jpegfragment_callback");
895
896 *LINK_mmcamera_jpegfragment_callback = receive_jpeg_fragment_callback;
897
898 *(void **)&LINK_mmcamera_jpeg_callback =
899 ::dlsym(libmmcamera, "mmcamera_jpeg_callback");
900
901 *LINK_mmcamera_jpeg_callback = receive_jpeg_callback;
902
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800903 *(void **)&LINK_camframe_timeout_callback =
904 ::dlsym(libmmcamera, "camframe_timeout_callback");
905
906 *LINK_camframe_timeout_callback = receive_camframetimeout_callback;
907
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800908/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800909 *(void **)&LINK_mmcamera_shutter_callback =
910 ::dlsym(libmmcamera, "mmcamera_shutter_callback");
911
912 *LINK_mmcamera_shutter_callback = receive_shutter_callback;
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800913*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800914 *(void**)&LINK_jpeg_encoder_setMainImageQuality =
915 ::dlsym(libmmcamera, "jpeg_encoder_setMainImageQuality");
Kiran Kumar H N8861f302010-01-05 12:01:41 -0800916
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800917 *(void**)&LINK_jpeg_encoder_setThumbnailQuality =
918 ::dlsym(libmmcamera, "jpeg_encoder_setThumbnailQuality");
919
920 *(void**)&LINK_jpeg_encoder_setRotation =
921 ::dlsym(libmmcamera, "jpeg_encoder_setRotation");
922
Kiran Kumar H N8861f302010-01-05 12:01:41 -0800923/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800924 *(void**)&LINK_jpeg_encoder_setLocation =
925 ::dlsym(libmmcamera, "jpeg_encoder_setLocation");
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800926*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800927 *(void **)&LINK_cam_conf =
928 ::dlsym(libmmcamera, "cam_conf");
929
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800930/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800931 *(void **)&LINK_default_sensor_get_snapshot_sizes =
932 ::dlsym(libmmcamera, "default_sensor_get_snapshot_sizes");
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800933*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800934 *(void **)&LINK_launch_cam_conf_thread =
935 ::dlsym(libmmcamera, "launch_cam_conf_thread");
936
937 *(void **)&LINK_release_cam_conf_thread =
938 ::dlsym(libmmcamera, "release_cam_conf_thread");
939
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800940/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800941 *(void **)&LINK_zoom_crop_upscale =
942 ::dlsym(libmmcamera, "zoom_crop_upscale");
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800943*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800944
945#else
946 mmcamera_camframe_callback = receive_camframe_callback;
947 mmcamera_jpegfragment_callback = receive_jpeg_fragment_callback;
948 mmcamera_jpeg_callback = receive_jpeg_callback;
949 mmcamera_shutter_callback = receive_shutter_callback;
950#endif // DLOPEN_LIBMMCAMERA
951
952 /* The control thread is in libcamera itself. */
953 mCameraControlFd = open(MSM_CAMERA_CONTROL, O_RDWR);
Kiran Kumar H N585bc362010-01-19 13:04:44 -0800954 if (mCameraControlFd < 0) {
955 LOGE("startCamera X: %s open failed: %s!",
956 MSM_CAMERA_CONTROL,
957 strerror(errno));
958 return false;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800959 }
960
Mohan Kandra284966d2010-01-05 13:39:15 -0800961 if(strncmp(mDeviceName,"msm7630", 7)){
962 fb_fd = open("/dev/graphics/fb0", O_RDWR);
963 if (fb_fd < 0) {
964 LOGE("startCamera: fb0 open failed: %s!", strerror(errno));
965 return FALSE;
966 }
967 }
968
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800969 /* This will block until the control thread is launched. After that, sensor
970 * information becomes available.
971 */
972
973 if (LINK_launch_cam_conf_thread()) {
974 LOGE("failed to launch the camera config thread");
975 return false;
976 }
977
978 memset(&mSensorInfo, 0, sizeof(mSensorInfo));
979 if (ioctl(mCameraControlFd,
980 MSM_CAM_IOCTL_GET_SENSOR_INFO,
981 &mSensorInfo) < 0)
982 LOGW("%s: cannot retrieve sensor info!", __FUNCTION__);
983 else
984 LOGI("%s: camsensor name %s, flash %d", __FUNCTION__,
985 mSensorInfo.name, mSensorInfo.flash_enabled);
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800986/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800987 picture_sizes = LINK_default_sensor_get_snapshot_sizes(&PICTURE_SIZE_COUNT);
988 if (!picture_sizes || !PICTURE_SIZE_COUNT) {
989 LOGE("startCamera X: could not get snapshot sizes");
990 return false;
991 }
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800992*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800993 LOGV("startCamera X");
994 return true;
995}
996
997status_t QualcommCameraHardware::dump(int fd,
998 const Vector<String16>& args) const
999{
1000 const size_t SIZE = 256;
1001 char buffer[SIZE];
1002 String8 result;
1003
1004 // Dump internal primitives.
1005 result.append("QualcommCameraHardware::dump");
1006 snprintf(buffer, 255, "mMsgEnabled (%d)\n", mMsgEnabled);
1007 result.append(buffer);
1008 int width, height;
1009 mParameters.getPreviewSize(&width, &height);
1010 snprintf(buffer, 255, "preview width(%d) x height (%d)\n", width, height);
1011 result.append(buffer);
1012 mParameters.getPictureSize(&width, &height);
1013 snprintf(buffer, 255, "raw width(%d) x height (%d)\n", width, height);
1014 result.append(buffer);
1015 snprintf(buffer, 255,
1016 "preview frame size(%d), raw size (%d), jpeg size (%d) "
1017 "and jpeg max size (%d)\n", mPreviewFrameSize, mRawSize,
1018 mJpegSize, mJpegMaxSize);
1019 result.append(buffer);
1020 write(fd, result.string(), result.size());
1021
1022 // Dump internal objects.
Mohan Kandrad9efed92010-01-15 19:08:39 -08001023 if (mPreviewHeap != 0) {
1024 mPreviewHeap->dump(fd, args);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001025 }
1026 if (mRawHeap != 0) {
1027 mRawHeap->dump(fd, args);
1028 }
1029 if (mJpegHeap != 0) {
1030 mJpegHeap->dump(fd, args);
1031 }
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001032 if(mRawSnapshotAshmemHeap != 0 ){
1033 mRawSnapshotAshmemHeap->dump(fd, args);
1034 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001035 mParameters.dump(fd, args);
1036 return NO_ERROR;
1037}
1038
Mohan Kandra284966d2010-01-05 13:39:15 -08001039static bool native_get_maxzoom(int camfd, void *pZm)
1040{
1041 LOGV("native_get_maxzoom E");
1042
1043 struct msm_ctrl_cmd ctrlCmd;
1044 int32_t *pZoom = (int32_t *)pZm;
1045
1046 ctrlCmd.type = CAMERA_GET_PARM_MAXZOOM;
1047 ctrlCmd.timeout_ms = 5000;
1048 ctrlCmd.length = sizeof(int32_t);
1049 ctrlCmd.value = pZoom;
1050 ctrlCmd.resp_fd = camfd;
1051
1052 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1053 LOGE("native_get_maxzoom: ioctl fd %d error %s",
1054 camfd,
1055 strerror(errno));
1056 return false;
1057 }
1058 LOGE("ctrlCmd.value = %d", *(int32_t *)ctrlCmd.value);
1059 memcpy(pZoom, (int32_t *)ctrlCmd.value, sizeof(int32_t));
1060
1061 LOGV("native_get_maxzoom X");
1062 return true;
1063}
1064
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001065static bool native_set_afmode(int camfd, isp3a_af_mode_t af_type)
1066{
1067 int rc;
1068 struct msm_ctrl_cmd ctrlCmd;
1069
1070 ctrlCmd.timeout_ms = 5000;
1071 ctrlCmd.type = CAMERA_SET_PARM_AUTO_FOCUS;
1072 ctrlCmd.length = sizeof(af_type);
1073 ctrlCmd.value = &af_type;
1074 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1075
1076 if ((rc = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0)
1077 LOGE("native_set_afmode: ioctl fd %d error %s\n",
1078 camfd,
1079 strerror(errno));
1080
1081 LOGV("native_set_afmode: ctrlCmd.status == %d\n", ctrlCmd.status);
1082 return rc >= 0 && ctrlCmd.status == CAMERA_EXIT_CB_DONE;
1083}
1084
1085static bool native_cancel_afmode(int camfd, int af_fd)
1086{
1087 int rc;
1088 struct msm_ctrl_cmd ctrlCmd;
1089
1090 ctrlCmd.timeout_ms = 0;
1091 ctrlCmd.type = CAMERA_AUTO_FOCUS_CANCEL;
1092 ctrlCmd.length = 0;
1093 ctrlCmd.value = NULL;
1094 ctrlCmd.resp_fd = -1; // there's no response fd
1095
1096 if ((rc = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND_2, &ctrlCmd)) < 0)
1097 {
1098 LOGE("native_cancel_afmode: ioctl fd %d error %s\n",
1099 camfd,
1100 strerror(errno));
1101 return false;
1102 }
1103
1104 return true;
1105}
1106
1107static bool native_start_preview(int camfd)
1108{
1109 struct msm_ctrl_cmd ctrlCmd;
1110
1111 ctrlCmd.timeout_ms = 5000;
1112 ctrlCmd.type = CAMERA_START_PREVIEW;
1113 ctrlCmd.length = 0;
1114 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1115
1116 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1117 LOGE("native_start_preview: MSM_CAM_IOCTL_CTRL_COMMAND fd %d error %s",
1118 camfd,
1119 strerror(errno));
1120 return false;
1121 }
1122
1123 return true;
1124}
1125
1126static bool native_get_picture (int camfd, common_crop_t *crop)
1127{
1128 struct msm_ctrl_cmd ctrlCmd;
1129
1130 ctrlCmd.timeout_ms = 5000;
1131 ctrlCmd.length = sizeof(common_crop_t);
1132 ctrlCmd.value = crop;
1133
1134 if(ioctl(camfd, MSM_CAM_IOCTL_GET_PICTURE, &ctrlCmd) < 0) {
1135 LOGE("native_get_picture: MSM_CAM_IOCTL_GET_PICTURE fd %d error %s",
1136 camfd,
1137 strerror(errno));
1138 return false;
1139 }
1140
1141 LOGV("crop: in1_w %d", crop->in1_w);
1142 LOGV("crop: in1_h %d", crop->in1_h);
1143 LOGV("crop: out1_w %d", crop->out1_w);
1144 LOGV("crop: out1_h %d", crop->out1_h);
1145
1146 LOGV("crop: in2_w %d", crop->in2_w);
1147 LOGV("crop: in2_h %d", crop->in2_h);
1148 LOGV("crop: out2_w %d", crop->out2_w);
1149 LOGV("crop: out2_h %d", crop->out2_h);
1150
1151 LOGV("crop: update %d", crop->update_flag);
1152
1153 return true;
1154}
1155
1156static bool native_stop_preview(int camfd)
1157{
1158 struct msm_ctrl_cmd ctrlCmd;
1159 ctrlCmd.timeout_ms = 5000;
1160 ctrlCmd.type = CAMERA_STOP_PREVIEW;
1161 ctrlCmd.length = 0;
1162 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1163
1164 if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1165 LOGE("native_stop_preview: ioctl fd %d error %s",
1166 camfd,
1167 strerror(errno));
1168 return false;
1169 }
1170
1171 return true;
1172}
1173
1174static bool native_prepare_snapshot(int camfd)
1175{
1176 int ioctlRetVal = true;
1177 struct msm_ctrl_cmd ctrlCmd;
1178
1179 ctrlCmd.timeout_ms = 1000;
1180 ctrlCmd.type = CAMERA_PREPARE_SNAPSHOT;
1181 ctrlCmd.length = 0;
1182 ctrlCmd.value = NULL;
1183 ctrlCmd.resp_fd = camfd;
1184
1185 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1186 LOGE("native_prepare_snapshot: ioctl fd %d error %s",
1187 camfd,
1188 strerror(errno));
1189 return false;
1190 }
1191 return true;
1192}
1193
1194static bool native_start_snapshot(int camfd)
1195{
1196 struct msm_ctrl_cmd ctrlCmd;
1197
1198 ctrlCmd.timeout_ms = 5000;
1199 ctrlCmd.type = CAMERA_START_SNAPSHOT;
1200 ctrlCmd.length = 0;
1201 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1202
1203 if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1204 LOGE("native_start_snapshot: ioctl fd %d error %s",
1205 camfd,
1206 strerror(errno));
1207 return false;
1208 }
1209
1210 return true;
1211}
1212
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001213static bool native_start_raw_snapshot(int camfd)
1214{
1215 int ret;
1216 struct msm_ctrl_cmd ctrlCmd;
1217
1218 ctrlCmd.timeout_ms = 1000;
1219 ctrlCmd.type = CAMERA_START_RAW_SNAPSHOT;
1220 ctrlCmd.length = 0;
1221 ctrlCmd.value = NULL;
1222 ctrlCmd.resp_fd = camfd;
1223
1224 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1225 LOGE("native_start_raw_snapshot: ioctl failed. ioctl return value "\
1226 "is %d \n", ret);
1227 return false;
1228 }
1229 return true;
1230}
1231
1232
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001233static bool native_stop_snapshot (int camfd)
1234{
1235 struct msm_ctrl_cmd ctrlCmd;
1236
1237 ctrlCmd.timeout_ms = 0;
1238 ctrlCmd.type = CAMERA_STOP_SNAPSHOT;
1239 ctrlCmd.length = 0;
1240 ctrlCmd.resp_fd = -1;
1241
1242 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND_2, &ctrlCmd) < 0) {
1243 LOGE("native_stop_snapshot: ioctl fd %d error %s",
1244 camfd,
1245 strerror(errno));
1246 return false;
1247 }
1248
1249 return true;
1250}
1251
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001252static rat_t latitude[3];
1253static rat_t longitude[3];
1254static char lonref[2];
1255static char latref[2];
1256static char dateTime[20];
1257static rat_t altitude;
1258
1259static void addExifTag(exif_tag_id_t tagid, exif_tag_type_t type,
1260 uint32_t count, uint8_t copy, void *data) {
1261
1262 if(exif_table_numEntries == MAX_EXIF_TABLE_ENTRIES) {
1263 LOGE("Number of entries exceeded limit");
1264 return;
1265 }
1266
1267 int index = exif_table_numEntries;
1268 exif_data[index].tag_id = tagid;
1269 exif_data[index].tag_entry.type = type;
1270 exif_data[index].tag_entry.count = count;
1271 exif_data[index].tag_entry.copy = copy;
1272 if((type == EXIF_RATIONAL) && (count > 1))
1273 exif_data[index].tag_entry.data._rats = (rat_t *)data;
1274 if((type == EXIF_RATIONAL) && (count == 1))
1275 exif_data[index].tag_entry.data._rat = *(rat_t *)data;
1276 else if(type == EXIF_ASCII)
1277 exif_data[index].tag_entry.data._ascii = (char *)data;
1278 else if(type == EXIF_BYTE)
1279 exif_data[index].tag_entry.data._byte = *(uint8_t *)data;
1280
1281 // Increase number of entries
1282 exif_table_numEntries++;
1283}
1284
1285static void parseLatLong(const char *latlonString, int *pDegrees,
1286 int *pMinutes, int *pSeconds ) {
1287
1288 double value = atof(latlonString);
1289 value = fabs(value);
1290 int degrees = (int) value;
1291
1292 double remainder = value - degrees;
1293 int minutes = (int) (remainder * 60);
1294 int seconds = (int) (((remainder * 60) - minutes) * 60 * 1000);
1295
1296 *pDegrees = degrees;
1297 *pMinutes = minutes;
1298 *pSeconds = seconds;
1299}
1300
1301static void setLatLon(exif_tag_id_t tag, const char *latlonString) {
1302
1303 int degrees, minutes, seconds;
1304
1305 parseLatLong(latlonString, &degrees, &minutes, &seconds);
1306
1307 rat_t value[3] = { {degrees, 1},
1308 {minutes, 1},
1309 {seconds, 1000} };
1310
1311 if(tag == EXIFTAGID_GPS_LATITUDE) {
1312 memcpy(latitude, value, sizeof(latitude));
1313 addExifTag(EXIFTAGID_GPS_LATITUDE, EXIF_RATIONAL, 3,
1314 1, (void *)latitude);
1315 } else {
1316 memcpy(longitude, value, sizeof(longitude));
1317 addExifTag(EXIFTAGID_GPS_LONGITUDE, EXIF_RATIONAL, 3,
1318 1, (void *)longitude);
1319 }
1320}
1321
1322void QualcommCameraHardware::setGpsParameters() {
1323 const char *str = NULL;
1324
1325 //Set Latitude
1326 str = mParameters.get(CameraParameters::KEY_GPS_LATITUDE);
1327 if(str != NULL) {
1328 setLatLon(EXIFTAGID_GPS_LATITUDE, str);
1329 //set Latitude Ref
1330 str = NULL;
1331 str = mParameters.get(CameraParameters::KEY_GPS_LATITUDE_REF);
1332 if(str != NULL) {
1333 strncpy(latref, str, 1);
1334 latref[1] = '\0';
1335 addExifTag(EXIFTAGID_GPS_LATITUDE_REF, EXIF_ASCII, 2,
1336 1, (void *)latref);
1337 }
1338 }
1339
1340 //set Longitude
1341 str = NULL;
1342 str = mParameters.get(CameraParameters::KEY_GPS_LONGITUDE);
1343 if(str != NULL) {
1344 setLatLon(EXIFTAGID_GPS_LONGITUDE, str);
1345 //set Longitude Ref
1346 str = NULL;
1347 str = mParameters.get(CameraParameters::KEY_GPS_LONGITUDE_REF);
1348 if(str != NULL) {
1349 strncpy(lonref, str, 1);
1350 lonref[1] = '\0';
1351 addExifTag(EXIFTAGID_GPS_LONGITUDE_REF, EXIF_ASCII, 2,
1352 1, (void *)lonref);
1353 }
1354 }
1355
1356 //set Altitude
1357 str = NULL;
1358 str = mParameters.get(CameraParameters::KEY_GPS_ALTITUDE);
1359 if(str != NULL) {
1360 int value = atoi(str);
1361 rat_t alt_value = {value, 1000};
1362 memcpy(&altitude, &alt_value, sizeof(altitude));
1363 addExifTag(EXIFTAGID_GPS_ALTITUDE, EXIF_RATIONAL, 1,
1364 1, (void *)&altitude);
1365 //set AltitudeRef
1366 int ref = mParameters.getInt(CameraParameters::KEY_GPS_ALTITUDE_REF);
1367 if( !(ref < 0 || ref > 1) )
1368 addExifTag(EXIFTAGID_GPS_ALTITUDE_REF, EXIF_BYTE, 1,
1369 1, (void *)&ref);
1370 }
1371
1372
1373}
1374
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001375bool QualcommCameraHardware::native_jpeg_encode(void)
1376{
1377 int jpeg_quality = mParameters.getInt("jpeg-quality");
1378 if (jpeg_quality >= 0) {
1379 LOGV("native_jpeg_encode, current jpeg main img quality =%d",
1380 jpeg_quality);
1381 if(!LINK_jpeg_encoder_setMainImageQuality(jpeg_quality)) {
1382 LOGE("native_jpeg_encode set jpeg-quality failed");
1383 return false;
1384 }
1385 }
1386
1387 int thumbnail_quality = mParameters.getInt("jpeg-thumbnail-quality");
1388 if (thumbnail_quality >= 0) {
1389 LOGV("native_jpeg_encode, current jpeg thumbnail quality =%d",
1390 thumbnail_quality);
1391 if(!LINK_jpeg_encoder_setThumbnailQuality(thumbnail_quality)) {
1392 LOGE("native_jpeg_encode set thumbnail-quality failed");
1393 return false;
1394 }
1395 }
1396
1397 int rotation = mParameters.getInt("rotation");
1398 if (rotation >= 0) {
1399 LOGV("native_jpeg_encode, rotation = %d", rotation);
1400 if(!LINK_jpeg_encoder_setRotation(rotation)) {
1401 LOGE("native_jpeg_encode set rotation failed");
1402 return false;
1403 }
1404 }
1405
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001406// jpeg_set_location();
1407 if(mParameters.getInt(CameraParameters::KEY_GPS_STATUS) == 1) {
1408 setGpsParameters();
1409 }
1410 //set TimeStamp
1411 const char *str = mParameters.get(CameraParameters::KEY_EXIF_DATETIME);
1412 if(str != NULL) {
1413 strncpy(dateTime, str, 19);
1414 dateTime[19] = '\0';
1415 addExifTag(EXIFTAGID_EXIF_DATE_TIME_ORIGINAL, EXIF_ASCII,
1416 20, 1, (void *)dateTime);
1417 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001418
1419 if (!LINK_jpeg_encoder_encode(&mDimension,
1420 (uint8_t *)mThumbnailHeap->mHeap->base(),
1421 mThumbnailHeap->mHeap->getHeapID(),
1422 (uint8_t *)mRawHeap->mHeap->base(),
1423 mRawHeap->mHeap->getHeapID(),
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001424 &mCrop, exif_data, exif_table_numEntries)) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001425 LOGE("native_jpeg_encode: jpeg_encoder_encode failed.");
1426 return false;
1427 }
1428 return true;
1429}
1430
1431bool QualcommCameraHardware::native_set_parm(
1432 cam_ctrl_type type, uint16_t length, void *value)
1433{
1434 struct msm_ctrl_cmd ctrlCmd;
1435
1436 ctrlCmd.timeout_ms = 5000;
1437 ctrlCmd.type = (uint16_t)type;
1438 ctrlCmd.length = length;
1439 // FIXME: this will be put in by the kernel
1440 ctrlCmd.resp_fd = mCameraControlFd;
1441 ctrlCmd.value = value;
1442
1443 LOGV("%s: fd %d, type %d, length %d", __FUNCTION__,
1444 mCameraControlFd, type, length);
1445 if (ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0 ||
1446 ctrlCmd.status != CAM_CTRL_SUCCESS) {
1447 LOGE("%s: error (%s): fd %d, type %d, length %d, status %d",
1448 __FUNCTION__, strerror(errno),
1449 mCameraControlFd, type, length, ctrlCmd.status);
1450 return false;
1451 }
1452 return true;
1453}
1454
1455void QualcommCameraHardware::jpeg_set_location()
1456{
1457 bool encode_location = true;
1458 camera_position_type pt;
1459
1460#define PARSE_LOCATION(what,type,fmt,desc) do { \
1461 pt.what = 0; \
1462 const char *what##_str = mParameters.get("gps-"#what); \
1463 LOGV("GPS PARM %s --> [%s]", "gps-"#what, what##_str); \
1464 if (what##_str) { \
1465 type what = 0; \
1466 if (sscanf(what##_str, fmt, &what) == 1) \
1467 pt.what = what; \
1468 else { \
1469 LOGE("GPS " #what " %s could not" \
1470 " be parsed as a " #desc, what##_str); \
1471 encode_location = false; \
1472 } \
1473 } \
1474 else { \
1475 LOGV("GPS " #what " not specified: " \
1476 "defaulting to zero in EXIF header."); \
1477 encode_location = false; \
1478 } \
1479 } while(0)
1480
1481 PARSE_LOCATION(timestamp, long, "%ld", "long");
1482 if (!pt.timestamp) pt.timestamp = time(NULL);
1483 PARSE_LOCATION(altitude, short, "%hd", "short");
1484 PARSE_LOCATION(latitude, double, "%lf", "double float");
1485 PARSE_LOCATION(longitude, double, "%lf", "double float");
1486
1487#undef PARSE_LOCATION
1488
1489 if (encode_location) {
1490 LOGD("setting image location ALT %d LAT %lf LON %lf",
1491 pt.altitude, pt.latitude, pt.longitude);
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001492/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001493 if (!LINK_jpeg_encoder_setLocation(&pt)) {
1494 LOGE("jpeg_set_location: LINK_jpeg_encoder_setLocation failed.");
1495 }
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001496*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001497 }
1498 else LOGV("not setting image location");
1499}
1500
1501void QualcommCameraHardware::runFrameThread(void *data)
1502{
1503 LOGV("runFrameThread E");
1504
1505 int cnt;
1506
1507#if DLOPEN_LIBMMCAMERA
1508 // We need to maintain a reference to libqcamera.so for the duration of the
1509 // frame thread, because we do not know when it will exit relative to the
1510 // lifetime of this object. We do not want to dlclose() libqcamera while
1511 // LINK_cam_frame is still running.
1512 void *libhandle = ::dlopen("liboemcamera.so", RTLD_NOW);
1513 LOGV("FRAME: loading libqcamera at %p", libhandle);
1514 if (!libhandle) {
1515 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
1516 }
1517 if (libhandle)
1518#endif
1519 {
1520 LINK_cam_frame(data);
1521 }
1522
Mohan Kandrad9efed92010-01-15 19:08:39 -08001523 mPreviewHeap.clear();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001524#if DLOPEN_LIBMMCAMERA
1525 if (libhandle) {
1526 ::dlclose(libhandle);
1527 LOGV("FRAME: dlclose(libqcamera)");
1528 }
1529#endif
1530
1531 mFrameThreadWaitLock.lock();
1532 mFrameThreadRunning = false;
1533 mFrameThreadWait.signal();
1534 mFrameThreadWaitLock.unlock();
1535
1536 LOGV("runFrameThread X");
1537}
1538
1539void *frame_thread(void *user)
1540{
1541 LOGD("frame_thread E");
1542 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
1543 if (obj != 0) {
1544 obj->runFrameThread(user);
1545 }
1546 else LOGW("not starting frame thread: the object went away!");
1547 LOGD("frame_thread X");
1548 return NULL;
1549}
1550
1551bool QualcommCameraHardware::initPreview()
1552{
1553 // See comments in deinitPreview() for why we have to wait for the frame
1554 // thread here, and why we can't use pthread_join().
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001555 mParameters.getPreviewSize(&previewWidth, &previewHeight);
1556 LOGI("initPreview E: preview size=%dx%d", previewWidth, previewHeight);
1557 mFrameThreadWaitLock.lock();
1558 while (mFrameThreadRunning) {
1559 LOGV("initPreview: waiting for old frame thread to complete.");
1560 mFrameThreadWait.wait(mFrameThreadWaitLock);
1561 LOGV("initPreview: old frame thread completed.");
1562 }
1563 mFrameThreadWaitLock.unlock();
1564
1565 mSnapshotThreadWaitLock.lock();
1566 while (mSnapshotThreadRunning) {
1567 LOGV("initPreview: waiting for old snapshot thread to complete.");
1568 mSnapshotThreadWait.wait(mSnapshotThreadWaitLock);
1569 LOGV("initPreview: old snapshot thread completed.");
1570 }
1571 mSnapshotThreadWaitLock.unlock();
1572
1573 int cnt = 0;
1574 mPreviewFrameSize = previewWidth * previewHeight * 3/2;
Mohan Kandrad9efed92010-01-15 19:08:39 -08001575 dstOffset = 0;
1576 mPreviewHeap = new PmemPool("/dev/pmem_adsp",
Mohan Kandra284966d2010-01-05 13:39:15 -08001577 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
1578 mCameraControlFd,
1579 MSM_PMEM_OUTPUT2,
1580 mPreviewFrameSize,
Mohan Kandrad9efed92010-01-15 19:08:39 -08001581 kPreviewBufferCountActual,
Mohan Kandra284966d2010-01-05 13:39:15 -08001582 mPreviewFrameSize,
Mohan Kandrad9efed92010-01-15 19:08:39 -08001583 "preview");
Mohan Kandra284966d2010-01-05 13:39:15 -08001584
Mohan Kandrad9efed92010-01-15 19:08:39 -08001585 if (!mPreviewHeap->initialized()) {
1586 mPreviewHeap.clear();
Mohan Kandra284966d2010-01-05 13:39:15 -08001587 LOGE("initPreview X: could not initialize Camera preview heap.");
1588 return false;
1589 }
Kiran Kumar H N595970b2010-01-12 10:41:09 -08001590 if( !strncmp(mDeviceName,"msm7630", 7) ) {
Kiran Kumar H N595970b2010-01-12 10:41:09 -08001591 if(mPostViewHeap == NULL) {
1592 LOGV(" Allocating Postview heap ");
1593 /* mPostViewHeap should be declared only for 7630 target */
1594 mPostViewHeap =
1595 new PmemPool("/dev/pmem_adsp",
1596 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
1597 mCameraControlFd,
1598 MSM_PMEM_OUTPUT2,
1599 mPreviewFrameSize,
1600 1,
1601 mPreviewFrameSize,
1602 "postview");
Mohan Kandra284966d2010-01-05 13:39:15 -08001603
Kiran Kumar H N595970b2010-01-12 10:41:09 -08001604 if (!mPostViewHeap->initialized()) {
1605 mPostViewHeap.clear();
1606 LOGE(" Failed to initialize Postview Heap");
1607 return false;
1608 }
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08001609 }
Mohan Kandrad9efed92010-01-15 19:08:39 -08001610 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001611 // mDimension will be filled with thumbnail_width, thumbnail_height,
1612 // orig_picture_dx, and orig_picture_dy after this function call. We need to
1613 // keep it for jpeg_encoder_encode.
1614 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
1615 sizeof(cam_ctrl_dimension_t), &mDimension);
1616
1617 if (ret) {
1618 for (cnt = 0; cnt < kPreviewBufferCount; cnt++) {
Mohan Kandrad9efed92010-01-15 19:08:39 -08001619 frames[cnt].fd = mPreviewHeap->mHeap->getHeapID();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001620 frames[cnt].buffer =
Mohan Kandrad9efed92010-01-15 19:08:39 -08001621 (uint32_t)mPreviewHeap->mHeap->base() + mPreviewHeap->mAlignedBufferSize * cnt;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001622 frames[cnt].y_off = 0;
1623 frames[cnt].cbcr_off = previewWidth * previewHeight;
1624 frames[cnt].path = MSM_FRAME_ENC;
1625 }
1626
1627 mFrameThreadWaitLock.lock();
1628 pthread_attr_t attr;
1629 pthread_attr_init(&attr);
1630 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1631 mFrameThreadRunning = !pthread_create(&mFrameThread,
1632 &attr,
1633 frame_thread,
1634 &frames[kPreviewBufferCount-1]);
1635 ret = mFrameThreadRunning;
1636 mFrameThreadWaitLock.unlock();
1637 }
1638
1639 LOGV("initPreview X: %d", ret);
1640 return ret;
1641}
1642
1643void QualcommCameraHardware::deinitPreview(void)
1644{
1645 LOGI("deinitPreview E");
1646
1647 // When we call deinitPreview(), we signal to the frame thread that it
1648 // needs to exit, but we DO NOT WAIT for it to complete here. The problem
1649 // is that deinitPreview is sometimes called from the frame-thread's
1650 // callback, when the refcount on the Camera client reaches zero. If we
1651 // called pthread_join(), we would deadlock. So, we just call
1652 // LINK_camframe_terminate() in deinitPreview(), which makes sure that
1653 // after the preview callback returns, the camframe thread will exit. We
1654 // could call pthread_join() in initPreview() to join the last frame
1655 // thread. However, we would also have to call pthread_join() in release
1656 // as well, shortly before we destroy the object; this would cause the same
1657 // deadlock, since release(), like deinitPreview(), may also be called from
1658 // the frame-thread's callback. This we have to make the frame thread
1659 // detached, and use a separate mechanism to wait for it to complete.
1660
1661 if (LINK_camframe_terminate() < 0)
1662 LOGE("failed to stop the camframe thread: %s",
1663 strerror(errno));
1664 LOGI("deinitPreview X");
1665}
1666
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001667bool QualcommCameraHardware::initRawSnapshot()
1668{
1669 LOGV("initRawSnapshot E");
1670
1671 //get width and height from Dimension Object
1672 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
1673 sizeof(cam_ctrl_dimension_t), &mDimension);
1674
1675 if(!ret){
1676 LOGE("initRawSnapshot X: failed to set dimension");
1677 return false;
1678 }
1679 int rawSnapshotSize = mDimension.raw_picture_height *
1680 mDimension.raw_picture_width;
1681
1682 LOGV("raw_snapshot_buffer_size = %d, raw_picture_height = %d, "\
1683 "raw_picture_width = %d",
1684 rawSnapshotSize, mDimension.raw_picture_height,
1685 mDimension.raw_picture_width);
1686
1687 if (mRawSnapShotPmemHeap != NULL) {
1688 LOGV("initRawSnapshot: clearing old mRawSnapShotPmemHeap.");
1689 mRawSnapShotPmemHeap.clear();
1690 }
1691
1692 //Pmem based pool for Camera Driver
1693 mRawSnapShotPmemHeap = new PmemPool("/dev/pmem_adsp",
1694 MemoryHeapBase::READ_ONLY,
1695 mCameraControlFd,
1696 MSM_PMEM_RAW_MAINIMG,
1697 rawSnapshotSize,
1698 1,
1699 rawSnapshotSize,
1700 "raw pmem snapshot camera");
1701
1702 if (!mRawSnapShotPmemHeap->initialized()) {
1703 mRawSnapShotPmemHeap.clear();
1704 LOGE("initRawSnapshot X: error initializing mRawSnapshotHeap");
1705 return false;
1706 }
1707 LOGV("initRawSnapshot X");
1708 return true;
1709
1710}
1711
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001712bool QualcommCameraHardware::initRaw(bool initJpegHeap)
1713{
1714 int rawWidth, rawHeight;
Apurva Rajguru8d1773b2009-12-02 14:21:23 -08001715
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001716 mParameters.getPictureSize(&rawWidth, &rawHeight);
1717 LOGV("initRaw E: picture size=%dx%d", rawWidth, rawHeight);
1718
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08001719 int thumbnailBufferSize;
1720 //Thumbnail height should be smaller than Picture height
1721 if (rawHeight > thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height){
1722 mDimension.ui_thumbnail_width =
1723 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].width;
1724 mDimension.ui_thumbnail_height =
1725 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height;
1726 uint32_t pictureAspectRatio = (uint32_t)((rawWidth * Q12) / rawHeight);
1727 uint32_t i;
1728 for(i = 0; i < THUMBNAIL_SIZE_COUNT; i++ )
1729 {
1730 if(thumbnail_sizes[i].aspect_ratio == pictureAspectRatio)
1731 {
1732 mDimension.ui_thumbnail_width = thumbnail_sizes[i].width;
1733 mDimension.ui_thumbnail_height = thumbnail_sizes[i].height;
1734 break;
1735 }
1736 }
1737 }
1738 else{
1739 mDimension.ui_thumbnail_height = THUMBNAIL_SMALL_HEIGHT;
1740 mDimension.ui_thumbnail_width =
1741 (THUMBNAIL_SMALL_HEIGHT * rawWidth)/ rawHeight;
1742 }
1743
1744 LOGV("Thumbnail Size Width %d Height %d",
1745 mDimension.ui_thumbnail_width,
1746 mDimension.ui_thumbnail_height);
1747
1748 thumbnailBufferSize = mDimension.ui_thumbnail_width *
1749 mDimension.ui_thumbnail_height * 3 / 2;
1750
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001751 // mDimension will be filled with thumbnail_width, thumbnail_height,
1752 // orig_picture_dx, and orig_picture_dy after this function call. We need to
1753 // keep it for jpeg_encoder_encode.
1754 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
1755 sizeof(cam_ctrl_dimension_t), &mDimension);
1756 if(!ret) {
1757 LOGE("initRaw X: failed to set dimension");
1758 return false;
1759 }
1760
1761 if (mJpegHeap != NULL) {
1762 LOGV("initRaw: clearing old mJpegHeap.");
1763 mJpegHeap.clear();
1764 }
1765
1766 // Snapshot
1767 mRawSize = rawWidth * rawHeight * 3 / 2;
Apurva Rajguru8d1773b2009-12-02 14:21:23 -08001768
Mohan Kandra284966d2010-01-05 13:39:15 -08001769 if(!strcmp(mDeviceName,"msm7627_surf"))
Apurva Rajguru8d1773b2009-12-02 14:21:23 -08001770 mJpegMaxSize = CEILING16(rawWidth) * CEILING16(rawHeight) * 3 / 2;
1771 else
1772 mJpegMaxSize = rawWidth * rawHeight * 3 / 2;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001773
1774 LOGV("initRaw: initializing mRawHeap.");
1775 mRawHeap =
1776 new PmemPool("/dev/pmem_camera",
1777 MemoryHeapBase::READ_ONLY,
1778 mCameraControlFd,
1779 MSM_PMEM_MAINIMG,
1780 mJpegMaxSize,
1781 kRawBufferCount,
1782 mRawSize,
1783 "snapshot camera");
1784
1785 if (!mRawHeap->initialized()) {
1786 LOGE("initRaw X failed with pmem_camera, trying with pmem_adsp");
1787 mRawHeap =
1788 new PmemPool("/dev/pmem_adsp",
1789 MemoryHeapBase::READ_ONLY,
1790 mCameraControlFd,
1791 MSM_PMEM_MAINIMG,
1792 mJpegMaxSize,
1793 kRawBufferCount,
1794 mRawSize,
1795 "snapshot camera");
1796 if (!mRawHeap->initialized()) {
1797 mRawHeap.clear();
1798 LOGE("initRaw X: error initializing mRawHeap");
1799 return false;
1800 }
1801 }
1802
1803 LOGV("do_mmap snapshot pbuf = %p, pmem_fd = %d",
1804 (uint8_t *)mRawHeap->mHeap->base(), mRawHeap->mHeap->getHeapID());
1805
1806 // Jpeg
1807
1808 if (initJpegHeap) {
1809 LOGV("initRaw: initializing mJpegHeap.");
1810 mJpegHeap =
1811 new AshmemPool(mJpegMaxSize,
1812 kJpegBufferCount,
1813 0, // we do not know how big the picture will be
1814 "jpeg");
1815
1816 if (!mJpegHeap->initialized()) {
1817 mJpegHeap.clear();
1818 mRawHeap.clear();
1819 LOGE("initRaw X failed: error initializing mJpegHeap.");
1820 return false;
1821 }
1822
1823 // Thumbnails
1824
1825 mThumbnailHeap =
1826 new PmemPool("/dev/pmem_adsp",
1827 MemoryHeapBase::READ_ONLY,
1828 mCameraControlFd,
1829 MSM_PMEM_THUMBNAIL,
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08001830 thumbnailBufferSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001831 1,
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08001832 thumbnailBufferSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001833 "thumbnail");
1834
1835 if (!mThumbnailHeap->initialized()) {
1836 mThumbnailHeap.clear();
1837 mJpegHeap.clear();
1838 mRawHeap.clear();
1839 LOGE("initRaw X failed: error initializing mThumbnailHeap.");
1840 return false;
1841 }
1842 }
1843
1844 LOGV("initRaw X");
1845 return true;
1846}
1847
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001848
1849void QualcommCameraHardware::deinitRawSnapshot()
1850{
1851 LOGV("deinitRawSnapshot E");
1852 mRawSnapShotPmemHeap.clear();
1853 mRawSnapshotAshmemHeap.clear();
1854 LOGV("deinitRawSnapshot X");
1855}
1856
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001857void QualcommCameraHardware::deinitRaw()
1858{
1859 LOGV("deinitRaw E");
1860
1861 mThumbnailHeap.clear();
1862 mJpegHeap.clear();
1863 mRawHeap.clear();
1864 mDisplayHeap.clear();
1865
1866 LOGV("deinitRaw X");
1867}
1868
1869void QualcommCameraHardware::release()
1870{
1871 LOGD("release E");
1872 Mutex::Autolock l(&mLock);
1873
1874#if DLOPEN_LIBMMCAMERA
1875 if (libmmcamera == NULL) {
1876 LOGE("ERROR: multiple release!");
1877 return;
1878 }
1879#else
1880#warning "Cannot detect multiple release when not dlopen()ing libqcamera!"
1881#endif
1882
1883 int cnt, rc;
1884 struct msm_ctrl_cmd ctrlCmd;
1885
1886 if (mCameraRunning) {
1887 if(mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME)) {
1888 mRecordFrameLock.lock();
1889 mReleasedRecordingFrame = true;
1890 mRecordWait.signal();
1891 mRecordFrameLock.unlock();
1892 }
1893 stopPreviewInternal();
1894 }
1895
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08001896 if(!strncmp(mDeviceName,"msm7630", 7)) {
1897 mPostViewHeap.clear();
1898 mPostViewHeap = NULL;
1899 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001900 LINK_jpeg_encoder_join();
1901 deinitRaw();
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001902 deinitRawSnapshot();
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001903 {
1904 Mutex::Autolock l(&mCamframeTimeoutLock);
1905 if(!camframe_timeout_flag) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001906
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001907 ctrlCmd.timeout_ms = 5000;
1908 ctrlCmd.length = 0;
1909 ctrlCmd.type = (uint16_t)CAMERA_EXIT;
1910 ctrlCmd.resp_fd = mCameraControlFd; // FIXME: this will be put in by the kernel
1911 if (ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0)
1912 LOGE("ioctl CAMERA_EXIT fd %d error %s",
1913 mCameraControlFd, strerror(errno));
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001914
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001915 }
Kiran Kumar H Nac2f4952009-12-17 01:16:53 -08001916 LINK_release_cam_conf_thread();
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001917 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001918 close(mCameraControlFd);
1919 mCameraControlFd = -1;
Mohan Kandra284966d2010-01-05 13:39:15 -08001920 if(fb_fd >= 0) {
1921 close(fb_fd);
1922 fb_fd = -1;
1923 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001924#if DLOPEN_LIBMMCAMERA
1925 if (libmmcamera) {
1926 ::dlclose(libmmcamera);
1927 LOGV("dlclose(libqcamera)");
1928 libmmcamera = NULL;
1929 }
1930#endif
1931
1932 Mutex::Autolock lock(&singleton_lock);
1933 singleton_releasing = true;
1934
1935 LOGD("release X");
1936}
1937
1938QualcommCameraHardware::~QualcommCameraHardware()
1939{
1940 LOGD("~QualcommCameraHardware E");
1941 Mutex::Autolock lock(&singleton_lock);
1942 singleton.clear();
1943 singleton_releasing = false;
1944 singleton_wait.signal();
1945 LOGD("~QualcommCameraHardware X");
1946}
1947
1948sp<IMemoryHeap> QualcommCameraHardware::getRawHeap() const
1949{
1950 LOGV("getRawHeap");
1951 return mDisplayHeap != NULL ? mDisplayHeap->mHeap : NULL;
1952}
1953
1954sp<IMemoryHeap> QualcommCameraHardware::getPreviewHeap() const
1955{
1956 LOGV("getPreviewHeap");
Mohan Kandrad9efed92010-01-15 19:08:39 -08001957 return mPreviewHeap != NULL ? mPreviewHeap->mHeap : NULL;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001958}
1959
1960status_t QualcommCameraHardware::startPreviewInternal()
1961{
1962 if(mCameraRunning) {
1963 LOGV("startPreview X: preview already running.");
1964 return NO_ERROR;
1965 }
1966
1967 if (!mPreviewInitialized) {
1968 mPreviewInitialized = initPreview();
1969 if (!mPreviewInitialized) {
1970 LOGE("startPreview X initPreview failed. Not starting preview.");
1971 return UNKNOWN_ERROR;
1972 }
1973 }
1974
1975 mCameraRunning = native_start_preview(mCameraControlFd);
1976 if(!mCameraRunning) {
1977 deinitPreview();
1978 mPreviewInitialized = false;
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08001979 mOverlay = NULL;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001980 LOGE("startPreview X: native_start_preview failed!");
1981 return UNKNOWN_ERROR;
1982 }
1983
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001984 //Reset the Gps Information
1985 exif_table_numEntries = 0;
Mohan Kandra284966d2010-01-05 13:39:15 -08001986
1987 if(native_get_maxzoom(mCameraControlFd, (void *)&mMaxZoom) == true){
1988 LOGE("Maximum zoom value is %d", mMaxZoom);
1989 mParameters.set("zoom-supported", "true");
1990 } else {
1991 LOGE("Failed to get maximum zoom value...setting max zoom to zero");
1992 mParameters.set("zoom-supported", "false");
1993 mMaxZoom = 0;
1994 }
1995 mParameters.set("max-zoom",mMaxZoom);
1996
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001997 LOGV("startPreview X");
1998 return NO_ERROR;
1999}
2000
2001status_t QualcommCameraHardware::startPreview()
2002{
2003 LOGV("startPreview E");
2004 Mutex::Autolock l(&mLock);
2005 return startPreviewInternal();
2006}
2007
2008void QualcommCameraHardware::stopPreviewInternal()
2009{
2010 LOGV("stopPreviewInternal E: %d", mCameraRunning);
2011 if (mCameraRunning) {
2012 // Cancel auto focus.
2013 {
2014 if (mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS)) {
2015 cancelAutoFocusInternal();
2016 }
2017 }
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002018
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002019 Mutex::Autolock l(&mCamframeTimeoutLock);
2020 if(!camframe_timeout_flag) {
2021 mCameraRunning = !native_stop_preview(mCameraControlFd);
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002022 } else {
2023 /* This means that the camframetimeout was issued.
2024 * But we did not issue native_stop_preview(), so we
Kiran Kumar H Nac2f4952009-12-17 01:16:53 -08002025 * need to update mCameraRunning to indicate that
2026 * Camera is no longer running. */
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002027 mCameraRunning = 0;
Kiran Kumar H Nac2f4952009-12-17 01:16:53 -08002028 }
2029 if (!mCameraRunning && mPreviewInitialized) {
2030 deinitPreview();
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002031 mPreviewInitialized = false;
2032 }
Kiran Kumar H Nac2f4952009-12-17 01:16:53 -08002033 else LOGE("stopPreviewInternal: failed to stop preview");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002034 }
2035 LOGV("stopPreviewInternal X: %d", mCameraRunning);
2036}
2037
2038void QualcommCameraHardware::stopPreview()
2039{
2040 LOGV("stopPreview: E");
2041 Mutex::Autolock l(&mLock);
2042 {
2043 if (mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME))
2044 return;
2045 }
2046 stopPreviewInternal();
2047 LOGV("stopPreview: X");
2048}
2049
2050void QualcommCameraHardware::runAutoFocus()
2051{
2052 bool status = true;
2053 void *libhandle = NULL;
Srinivasan Kannan71229622009-12-04 12:05:58 -08002054 isp3a_af_mode_t afMode;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002055
2056 mAutoFocusThreadLock.lock();
2057 // Skip autofocus if focus mode is infinity.
2058 if (strcmp(mParameters.get(CameraParameters::KEY_FOCUS_MODE),
2059 CameraParameters::FOCUS_MODE_INFINITY) == 0) {
2060 goto done;
2061 }
2062
2063 mAutoFocusFd = open(MSM_CAMERA_CONTROL, O_RDWR);
2064 if (mAutoFocusFd < 0) {
2065 LOGE("autofocus: cannot open %s: %s",
2066 MSM_CAMERA_CONTROL,
2067 strerror(errno));
2068 mAutoFocusThreadRunning = false;
2069 mAutoFocusThreadLock.unlock();
2070 return;
2071 }
2072
2073#if DLOPEN_LIBMMCAMERA
2074 // We need to maintain a reference to libqcamera.so for the duration of the
2075 // AF thread, because we do not know when it will exit relative to the
2076 // lifetime of this object. We do not want to dlclose() libqcamera while
2077 // LINK_cam_frame is still running.
2078 libhandle = ::dlopen("liboemcamera.so", RTLD_NOW);
2079 LOGV("AF: loading libqcamera at %p", libhandle);
2080 if (!libhandle) {
2081 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
2082 close(mAutoFocusFd);
2083 mAutoFocusFd = -1;
2084 mAutoFocusThreadRunning = false;
2085 mAutoFocusThreadLock.unlock();
2086 return;
2087 }
2088#endif
2089
Srinivasan Kannan71229622009-12-04 12:05:58 -08002090 afMode = (isp3a_af_mode_t)attr_lookup(focus_modes,
2091 sizeof(focus_modes) / sizeof(str_map),
2092 mParameters.get(CameraParameters::KEY_FOCUS_MODE));
2093
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002094 /* This will block until either AF completes or is cancelled. */
Srinivasan Kannan71229622009-12-04 12:05:58 -08002095 LOGV("af start (fd %d mode %d)", mAutoFocusFd, afMode);
2096 status = native_set_afmode(mAutoFocusFd, afMode);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002097 LOGV("af done: %d", (int)status);
2098 close(mAutoFocusFd);
2099 mAutoFocusFd = -1;
2100
2101done:
2102 mAutoFocusThreadRunning = false;
2103 mAutoFocusThreadLock.unlock();
2104
2105 mCallbackLock.lock();
2106 bool autoFocusEnabled = mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS);
2107 notify_callback cb = mNotifyCallback;
2108 void *data = mCallbackCookie;
2109 mCallbackLock.unlock();
2110 if (autoFocusEnabled)
2111 cb(CAMERA_MSG_FOCUS, status, 0, data);
2112
2113#if DLOPEN_LIBMMCAMERA
2114 if (libhandle) {
2115 ::dlclose(libhandle);
2116 LOGV("AF: dlclose(libqcamera)");
2117 }
2118#endif
2119}
2120
2121status_t QualcommCameraHardware::cancelAutoFocusInternal()
2122{
2123 LOGV("cancelAutoFocusInternal E");
2124
Srinivasan Kannan71229622009-12-04 12:05:58 -08002125 if(!sensorType->hasAutoFocusSupport){
2126 LOGV("cancelAutoFocusInternal X");
2127 return NO_ERROR;
2128 }
2129
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002130#if 0
2131 if (mAutoFocusFd < 0) {
2132 LOGV("cancelAutoFocusInternal X: not in progress");
2133 return NO_ERROR;
2134 }
2135#endif
2136
2137 status_t rc = native_cancel_afmode(mCameraControlFd, mAutoFocusFd) ?
2138 NO_ERROR :
2139 UNKNOWN_ERROR;
2140
2141 LOGV("cancelAutoFocusInternal X: %d", rc);
2142 return rc;
2143}
2144
2145void *auto_focus_thread(void *user)
2146{
2147 LOGV("auto_focus_thread E");
2148 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
2149 if (obj != 0) {
2150 obj->runAutoFocus();
2151 }
2152 else LOGW("not starting autofocus: the object went away!");
2153 LOGV("auto_focus_thread X");
2154 return NULL;
2155}
2156
2157status_t QualcommCameraHardware::autoFocus()
2158{
2159 LOGV("autoFocus E");
2160 Mutex::Autolock l(&mLock);
2161
Srinivasan Kannan71229622009-12-04 12:05:58 -08002162 if(!sensorType->hasAutoFocusSupport){
Srinivasan Kannandf085222009-12-09 18:31:00 -08002163 bool status = false;
2164 mCallbackLock.lock();
2165 bool autoFocusEnabled = mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS);
2166 notify_callback cb = mNotifyCallback;
2167 void *data = mCallbackCookie;
2168 mCallbackLock.unlock();
2169 if (autoFocusEnabled)
2170 cb(CAMERA_MSG_FOCUS, status, 0, data);
Srinivasan Kannan71229622009-12-04 12:05:58 -08002171 LOGV("autoFocus X");
2172 return NO_ERROR;
2173 }
2174
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002175 if (mCameraControlFd < 0) {
2176 LOGE("not starting autofocus: main control fd %d", mCameraControlFd);
2177 return UNKNOWN_ERROR;
2178 }
2179
2180 {
2181 mAutoFocusThreadLock.lock();
2182 if (!mAutoFocusThreadRunning) {
2183 // Create a detached thread here so that we don't have to wait
2184 // for it when we cancel AF.
2185 pthread_t thr;
2186 pthread_attr_t attr;
2187 pthread_attr_init(&attr);
2188 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2189 mAutoFocusThreadRunning =
2190 !pthread_create(&thr, &attr,
2191 auto_focus_thread, NULL);
2192 if (!mAutoFocusThreadRunning) {
2193 LOGE("failed to start autofocus thread");
2194 mAutoFocusThreadLock.unlock();
2195 return UNKNOWN_ERROR;
2196 }
2197 }
2198 mAutoFocusThreadLock.unlock();
2199 }
2200
2201 LOGV("autoFocus X");
2202 return NO_ERROR;
2203}
2204
2205status_t QualcommCameraHardware::cancelAutoFocus()
2206{
2207 LOGV("cancelAutoFocus E");
2208 Mutex::Autolock l(&mLock);
2209
2210 int rc = NO_ERROR;
2211 if (mCameraRunning && mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS)) {
2212 rc = cancelAutoFocusInternal();
2213 }
2214
2215 LOGV("cancelAutoFocus X");
2216 return rc;
2217}
2218
2219void QualcommCameraHardware::runSnapshotThread(void *data)
2220{
2221 LOGV("runSnapshotThread E");
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002222 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
2223 if (native_start_snapshot(mCameraControlFd))
2224 receiveRawPicture();
2225 else
2226 LOGE("main: native_start_snapshot failed!");
2227 } else if(mSnapshotFormat == PICTURE_FORMAT_RAW){
2228 if(native_start_raw_snapshot(mCameraControlFd)){
2229 receiveRawSnapshot();
2230 } else {
2231 LOGE("main: native_start_raw_snapshot failed!");
2232 }
2233 }
2234
2235 mSnapshotFormat = 0;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002236
2237 mSnapshotThreadWaitLock.lock();
2238 mSnapshotThreadRunning = false;
2239 mSnapshotThreadWait.signal();
2240 mSnapshotThreadWaitLock.unlock();
2241
2242 LOGV("runSnapshotThread X");
2243}
2244
2245void *snapshot_thread(void *user)
2246{
2247 LOGD("snapshot_thread E");
2248 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
2249 if (obj != 0) {
2250 obj->runSnapshotThread(user);
2251 }
2252 else LOGW("not starting snapshot thread: the object went away!");
2253 LOGD("snapshot_thread X");
2254 return NULL;
2255}
2256
2257status_t QualcommCameraHardware::takePicture()
2258{
2259 LOGV("takePicture(%d)", mMsgEnabled);
2260 Mutex::Autolock l(&mLock);
2261
2262 // Wait for old snapshot thread to complete.
2263 mSnapshotThreadWaitLock.lock();
2264 while (mSnapshotThreadRunning) {
2265 LOGV("takePicture: waiting for old snapshot thread to complete.");
2266 mSnapshotThreadWait.wait(mSnapshotThreadWaitLock);
2267 LOGV("takePicture: old snapshot thread completed.");
2268 }
2269
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002270 if(!strcmp(mDeviceName,"msm7630_surf")) {
2271 /* Store the last frame queued for preview. This
2272 * shall be used as postview */
2273 storePreviewFrameForPostview();
2274 }
2275
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002276 //mSnapshotFormat is protected by mSnapshotThreadWaitLock
2277 if(mParameters.getPictureFormat() != 0 &&
2278 !strcmp(mParameters.getPictureFormat(),
2279 CameraParameters::PIXEL_FORMAT_RAW))
2280 mSnapshotFormat = PICTURE_FORMAT_RAW;
2281 else
2282 mSnapshotFormat = PICTURE_FORMAT_JPEG;
2283
2284 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
2285 if(!native_prepare_snapshot(mCameraControlFd)) {
2286 mSnapshotThreadWaitLock.unlock();
2287 return UNKNOWN_ERROR;
2288 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002289 }
2290
2291 stopPreviewInternal();
2292
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002293 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
2294 if (!initRaw(mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE))) {
2295 LOGE("initRaw failed. Not taking picture.");
2296 mSnapshotThreadWaitLock.unlock();
2297 return UNKNOWN_ERROR;
2298 }
2299 } else if(mSnapshotFormat == PICTURE_FORMAT_RAW ){
2300 if(!initRawSnapshot()){
2301 LOGE("initRawSnapshot failed. Not taking picture.");
2302 mSnapshotThreadWaitLock.unlock();
2303 return UNKNOWN_ERROR;
2304 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002305 }
2306
2307 mShutterLock.lock();
2308 mShutterPending = true;
2309 mShutterLock.unlock();
2310
2311 pthread_attr_t attr;
2312 pthread_attr_init(&attr);
2313 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2314 mSnapshotThreadRunning = !pthread_create(&mSnapshotThread,
2315 &attr,
2316 snapshot_thread,
2317 NULL);
2318 mSnapshotThreadWaitLock.unlock();
2319
2320 LOGV("takePicture: X");
2321 return mSnapshotThreadRunning ? NO_ERROR : UNKNOWN_ERROR;
2322}
2323
2324status_t QualcommCameraHardware::cancelPicture()
2325{
2326 status_t rc;
2327 LOGV("cancelPicture: E");
2328 rc = native_stop_snapshot(mCameraControlFd) ? NO_ERROR : UNKNOWN_ERROR;
2329 LOGV("cancelPicture: X: %d", rc);
2330 return rc;
2331}
2332
2333status_t QualcommCameraHardware::setParameters(const CameraParameters& params)
2334{
2335 LOGV("setParameters: E params = %p", &params);
2336
2337 Mutex::Autolock l(&mLock);
2338 status_t rc, final_rc = NO_ERROR;
2339
2340 if ((rc = setPreviewSize(params))) final_rc = rc;
2341 if ((rc = setPictureSize(params))) final_rc = rc;
2342 if ((rc = setJpegQuality(params))) final_rc = rc;
2343 if ((rc = setAntibanding(params))) final_rc = rc;
2344 if ((rc = setEffect(params))) final_rc = rc;
Apurva Rajguru55562b02009-12-03 12:25:35 -08002345 if ((rc = setAutoExposure(params))) final_rc = rc;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002346 if ((rc = setWhiteBalance(params))) final_rc = rc;
2347 if ((rc = setFlash(params))) final_rc = rc;
2348 if ((rc = setGpsLocation(params))) final_rc = rc;
2349 if ((rc = setRotation(params))) final_rc = rc;
2350 if ((rc = setZoom(params))) final_rc = rc;
2351 if ((rc = setFocusMode(params))) final_rc = rc;
2352 if ((rc = setOrientation(params))) final_rc = rc;
Nishant Panditc8c1ee72009-12-03 16:24:02 +05302353 if ((rc = setBrightness(params))) final_rc = rc;
2354 if ((rc = setLensshadeValue(params))) final_rc = rc;
2355 if ((rc = setISOValue(params))) final_rc = rc;
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002356 if ((rc = setPictureFormat(params))) final_rc = rc;
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08002357 if ((rc = setSharpness(params))) final_rc = rc;
2358 if ((rc = setContrast(params))) final_rc = rc;
2359 if ((rc = setSaturation(params))) final_rc = rc;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002360
2361 LOGV("setParameters: X");
2362 return final_rc;
2363}
2364
2365CameraParameters QualcommCameraHardware::getParameters() const
2366{
2367 LOGV("getParameters: EX");
2368 return mParameters;
2369}
2370
2371status_t QualcommCameraHardware::sendCommand(int32_t command, int32_t arg1,
2372 int32_t arg2)
2373{
2374 LOGV("sendCommand: EX");
2375 return BAD_VALUE;
2376}
2377
2378extern "C" sp<CameraHardwareInterface> openCameraHardware()
2379{
2380 LOGV("openCameraHardware: call createInstance");
2381 return QualcommCameraHardware::createInstance();
2382}
2383
2384wp<QualcommCameraHardware> QualcommCameraHardware::singleton;
2385
2386// If the hardware already exists, return a strong pointer to the current
2387// object. If not, create a new hardware object, put it in the singleton,
2388// and return it.
2389sp<CameraHardwareInterface> QualcommCameraHardware::createInstance()
2390{
2391 LOGD("createInstance: E");
2392
2393 Mutex::Autolock lock(&singleton_lock);
2394
2395 // Wait until the previous release is done.
2396 while (singleton_releasing) {
2397 LOGD("Wait for previous release.");
2398 singleton_wait.wait(singleton_lock);
2399 }
2400
2401 if (singleton != 0) {
2402 sp<CameraHardwareInterface> hardware = singleton.promote();
2403 if (hardware != 0) {
2404 LOGD("createInstance: X return existing hardware=%p", &(*hardware));
2405 return hardware;
2406 }
2407 }
2408
2409 {
2410 struct stat st;
2411 int rc = stat("/dev/oncrpc", &st);
2412 if (rc < 0) {
2413 LOGD("createInstance: X failed to create hardware: %s", strerror(errno));
2414 return NULL;
2415 }
2416 }
2417
2418 QualcommCameraHardware *cam = new QualcommCameraHardware();
2419 sp<QualcommCameraHardware> hardware(cam);
2420 singleton = hardware;
2421
2422 if (!cam->startCamera()) {
2423 LOGE("%s: startCamera failed!", __FUNCTION__);
2424 return NULL;
2425 }
2426
2427 cam->initDefaultParameters();
2428 LOGD("createInstance: X created hardware=%p", &(*hardware));
2429 return hardware;
2430}
2431
2432// For internal use only, hence the strong pointer to the derived type.
2433sp<QualcommCameraHardware> QualcommCameraHardware::getInstance()
2434{
2435 sp<CameraHardwareInterface> hardware = singleton.promote();
2436 if (hardware != 0) {
2437 // LOGV("getInstance: X old instance of hardware");
2438 return sp<QualcommCameraHardware>(static_cast<QualcommCameraHardware*>(hardware.get()));
2439 } else {
2440 LOGV("getInstance: X new instance of hardware");
2441 return sp<QualcommCameraHardware>();
2442 }
2443}
2444
Mohan Kandrad9efed92010-01-15 19:08:39 -08002445bool QualcommCameraHardware::native_zoom_image(int fd, int srcOffset, int dstOffSet, common_crop_t *crop)
Mohan Kandra284966d2010-01-05 13:39:15 -08002446{
2447 int result = 0;
2448 struct mdp_blit_req *e;
2449 struct timeval td1, td2;
2450
Mohan Kandra284966d2010-01-05 13:39:15 -08002451 /* Initialize yuv structure */
2452 zoomImage.list.count = 1;
2453
2454 e = &zoomImage.list.req[0];
2455
2456 e->src.width = previewWidth;
2457 e->src.height = previewHeight;
2458 e->src.format = MDP_Y_CBCR_H2V2;
Mohan Kandrad9efed92010-01-15 19:08:39 -08002459 e->src.offset = srcOffset;
2460 e->src.memory_id = fd;
Mohan Kandra284966d2010-01-05 13:39:15 -08002461
2462 e->dst.width = previewWidth;
2463 e->dst.height = previewHeight;
2464 e->dst.format = MDP_Y_CBCR_H2V2;
Mohan Kandrad9efed92010-01-15 19:08:39 -08002465 e->dst.offset = dstOffSet;
2466 e->dst.memory_id = fd;
Mohan Kandra284966d2010-01-05 13:39:15 -08002467
2468 e->transp_mask = 0xffffffff;
2469 e->flags = 0;
2470 e->alpha = 0xff;
2471 if (crop->in2_w != 0 || crop->in2_h != 0) {
2472 e->src_rect.x = (crop->out2_w - crop->in2_w + 1) / 2 - 1;
2473 e->src_rect.y = (crop->out2_h - crop->in2_h + 1) / 2 - 1;
2474 e->src_rect.w = crop->in2_w;
2475 e->src_rect.h = crop->in2_h;
2476 } else {
2477 e->src_rect.x = 0;
2478 e->src_rect.y = 0;
2479 e->src_rect.w = previewWidth;
2480 e->src_rect.h = previewHeight;
2481 }
Mohan Kandrad9efed92010-01-15 19:08:39 -08002482 //LOGV(" native_zoom : SRC_RECT : x,y = %d,%d \t w,h = %d, %d",
2483 // e->src_rect.x, e->src_rect.y, e->src_rect.w, e->src_rect.h);
Mohan Kandra284966d2010-01-05 13:39:15 -08002484
2485 e->dst_rect.x = 0;
2486 e->dst_rect.y = 0;
2487 e->dst_rect.w = previewWidth;
2488 e->dst_rect.h = previewHeight;
2489
2490 result = ioctl(fb_fd, MSMFB_BLIT, &zoomImage.list);
2491 if (result < 0) {
2492 LOGE("MSM_FBIOBLT failed! line=%d\n", __LINE__);
2493 return FALSE;
2494 }
2495 return TRUE;
2496}
2497
Mohan Kandra740cfce2010-01-07 12:58:24 -08002498void QualcommCameraHardware::debugShowFPS() const
2499{
2500 static int mFrameCount;
2501 static int mLastFrameCount = 0;
2502 static nsecs_t mLastFpsTime = 0;
2503 static float mFps = 0;
2504 mFrameCount++;
2505 nsecs_t now = systemTime();
2506 nsecs_t diff = now - mLastFpsTime;
2507 if (diff > ms2ns(250)) {
2508 mFps = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
2509 LOGI("Frames Per Second: %.4f", mFps);
2510 mLastFpsTime = now;
2511 mLastFrameCount = mFrameCount;
2512 }
2513}
2514
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002515void QualcommCameraHardware::receivePreviewFrame(struct msm_frame *frame)
2516{
2517// LOGV("receivePreviewFrame E");
2518
2519 if (!mCameraRunning) {
2520 LOGE("ignoring preview callback--camera has been stopped");
2521 return;
2522 }
2523
Mohan Kandra740cfce2010-01-07 12:58:24 -08002524 if (UNLIKELY(mDebugFps)) {
2525 debugShowFPS();
2526 }
2527
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002528 mCallbackLock.lock();
2529 int msgEnabled = mMsgEnabled;
2530 data_callback pcb = mDataCallback;
2531 void *pdata = mCallbackCookie;
2532 data_callback_timestamp rcb = mDataCallbackTimestamp;
2533 void *rdata = mCallbackCookie;
2534 mCallbackLock.unlock();
2535
2536 // Find the offset within the heap of the current buffer.
Mohan Kandra284966d2010-01-05 13:39:15 -08002537 ssize_t offset_addr =
Mohan Kandrad9efed92010-01-15 19:08:39 -08002538 (ssize_t)frame->buffer - (ssize_t)mPreviewHeap->mHeap->base();
2539 ssize_t offset = offset_addr / mPreviewHeap->mAlignedBufferSize;
Mohan Kandra284966d2010-01-05 13:39:15 -08002540
2541 common_crop_t *crop = (common_crop_t *) (frame->cropinfo);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002542
2543 mInPreviewCallback = true;
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002544 if(mUseOverlay) {
2545 if(mOverlay != NULL) {
2546 mOverlayLock.lock();
Mohan Kandrad9efed92010-01-15 19:08:39 -08002547 mOverlay->setFd(mPreviewHeap->mHeap->getHeapID());
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002548 if (crop->in2_w != 0 || crop->in2_h != 0) {
2549 zoomCropInfo.x = (crop->out2_w - crop->in2_w + 1) / 2 - 1;
2550 zoomCropInfo.y = (crop->out2_h - crop->in2_h + 1) / 2 - 1;
2551 zoomCropInfo.w = crop->in2_w;
2552 zoomCropInfo.h = crop->in2_h;
2553 mOverlay->setCrop(zoomCropInfo.x, zoomCropInfo.y,
2554 zoomCropInfo.w, zoomCropInfo.h);
2555 }
2556 mOverlay->queueBuffer((void *)offset_addr);
2557 mLastQueuedFrame = (void *)frame->buffer;
2558 mOverlayLock.unlock();
2559 }
Mohan Kandra284966d2010-01-05 13:39:15 -08002560 } else {
Mohan Kandrad9efed92010-01-15 19:08:39 -08002561 if (crop->in2_w != 0 || crop->in2_h != 0) {
2562 dstOffset = (dstOffset + 1) % NUM_MORE_BUFS;
2563 offset = kPreviewBufferCount + dstOffset;
2564 ssize_t dstOffset_addr = offset * mPreviewHeap->mAlignedBufferSize;
2565 if( !native_zoom_image(mPreviewHeap->mHeap->getHeapID(),
2566 offset_addr, dstOffset_addr, crop)) {
2567 LOGE(" Error while doing MDP zoom ");
2568 }
2569 }
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08002570 }
Mohan Kandrad9efed92010-01-15 19:08:39 -08002571 if (pcb != NULL && (msgEnabled & CAMERA_MSG_PREVIEW_FRAME))
2572 pcb(CAMERA_MSG_PREVIEW_FRAME, mPreviewHeap->mBuffers[offset],
2573 pdata);
2574
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002575 if(rcb != NULL && (msgEnabled & CAMERA_MSG_VIDEO_FRAME)) {
Mohan Kandrad9efed92010-01-15 19:08:39 -08002576 rcb(systemTime(), CAMERA_MSG_VIDEO_FRAME, mPreviewHeap->mBuffers[offset], rdata);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002577 Mutex::Autolock rLock(&mRecordFrameLock);
2578 if (mReleasedRecordingFrame != true) {
2579 LOGV("block waiting for frame release");
2580 mRecordWait.wait(mRecordFrameLock);
2581 LOGV("frame released, continuing");
2582 }
2583 mReleasedRecordingFrame = false;
2584 }
2585 mInPreviewCallback = false;
2586
2587// LOGV("receivePreviewFrame X");
2588}
2589
2590status_t QualcommCameraHardware::startRecording()
2591{
2592 LOGV("startRecording E");
2593 Mutex::Autolock l(&mLock);
2594 mReleasedRecordingFrame = false;
2595 return startPreviewInternal();
2596}
2597
2598void QualcommCameraHardware::stopRecording()
2599{
2600 LOGV("stopRecording: E");
2601 Mutex::Autolock l(&mLock);
2602 {
2603 mRecordFrameLock.lock();
2604 mReleasedRecordingFrame = true;
2605 mRecordWait.signal();
2606 mRecordFrameLock.unlock();
2607
2608 if(mDataCallback && (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)) {
2609 LOGV("stopRecording: X, preview still in progress");
2610 return;
2611 }
2612 }
2613
2614 stopPreviewInternal();
2615 LOGV("stopRecording: X");
2616}
2617
2618void QualcommCameraHardware::releaseRecordingFrame(
2619 const sp<IMemory>& mem __attribute__((unused)))
2620{
2621 LOGV("releaseRecordingFrame E");
2622 Mutex::Autolock rLock(&mRecordFrameLock);
2623 mReleasedRecordingFrame = true;
2624 mRecordWait.signal();
2625 LOGV("releaseRecordingFrame X");
2626}
2627
2628bool QualcommCameraHardware::recordingEnabled()
2629{
2630 return mCameraRunning && mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME);
2631}
2632
2633void QualcommCameraHardware::notifyShutter(common_crop_t *crop)
2634{
2635 mShutterLock.lock();
2636 image_rect_type size;
2637
2638 if (mShutterPending && mNotifyCallback && (mMsgEnabled & CAMERA_MSG_SHUTTER)) {
2639 LOGV("out2_w=%d, out2_h=%d, in2_w=%d, in2_h=%d",
2640 crop->out2_w, crop->out2_h, crop->in2_w, crop->in2_h);
2641 LOGV("out1_w=%d, out1_h=%d, in1_w=%d, in1_h=%d",
2642 crop->out1_w, crop->out1_h, crop->in1_w, crop->in1_h);
2643
2644 // To workaround a bug in MDP which happens if either
2645 // dimension > 2048, we display the thumbnail instead.
2646 mDisplayHeap = mRawHeap;
2647 if (crop->in1_w == 0 || crop->in1_h == 0) {
2648 // Full size
2649 size.width = mDimension.picture_width;
2650 size.height = mDimension.picture_height;
2651 if (size.width > 2048 || size.height > 2048) {
2652 size.width = mDimension.ui_thumbnail_width;
2653 size.height = mDimension.ui_thumbnail_height;
2654 mDisplayHeap = mThumbnailHeap;
2655 }
2656 } else {
2657 // Cropped
2658 size.width = crop->in2_w & ~1;
2659 size.height = crop->in2_h & ~1;
2660 if (size.width > 2048 || size.height > 2048) {
2661 size.width = crop->in1_w & ~1;
2662 size.height = crop->in1_h & ~1;
2663 mDisplayHeap = mThumbnailHeap;
2664 }
2665 }
2666
2667 mNotifyCallback(CAMERA_MSG_SHUTTER, (int32_t)&size, 0,
2668 mCallbackCookie);
2669 mShutterPending = false;
2670 }
2671 mShutterLock.unlock();
2672}
2673
2674static void receive_shutter_callback(common_crop_t *crop)
2675{
2676 LOGV("receive_shutter_callback: E");
2677 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
2678 if (obj != 0) {
2679 obj->notifyShutter(crop);
2680 }
2681 LOGV("receive_shutter_callback: X");
2682}
2683
2684// Crop the picture in place.
2685static void crop_yuv420(uint32_t width, uint32_t height,
2686 uint32_t cropped_width, uint32_t cropped_height,
2687 uint8_t *image)
2688{
2689 uint32_t i, x, y;
2690 uint8_t* chroma_src, *chroma_dst;
2691
2692 // Calculate the start position of the cropped area.
2693 x = (width - cropped_width) / 2;
2694 y = (height - cropped_height) / 2;
2695 x &= ~1;
2696 y &= ~1;
2697
2698 // Copy luma component.
2699 for(i = 0; i < cropped_height; i++)
2700 memcpy(image + i * cropped_width,
2701 image + width * (y + i) + x,
2702 cropped_width);
2703
2704 chroma_src = image + width * height;
2705 chroma_dst = image + cropped_width * cropped_height;
2706
2707 // Copy chroma components.
2708 cropped_height /= 2;
2709 y /= 2;
2710 for(i = 0; i < cropped_height; i++)
2711 memcpy(chroma_dst + i * cropped_width,
2712 chroma_src + width * (y + i) + x,
2713 cropped_width);
2714}
2715
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002716
2717void QualcommCameraHardware::receiveRawSnapshot(){
2718 LOGV("receiveRawSnapshot E");
2719
2720 Mutex::Autolock cbLock(&mCallbackLock);
2721
2722 notifyShutter(&mCrop);
2723
2724 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
2725
2726 if(native_get_picture(mCameraControlFd, &mCrop) == false) {
2727 LOGE("receiveRawSnapshot X: native_get_picture failed!");
2728 return;
2729 }
2730
2731 //Create a Ashmem heap to copy data from PMem heap for application layer
2732 if(mRawSnapshotAshmemHeap != NULL){
2733 LOGV("receiveRawSnapshot: clearing old mRawSnapShotAshmemHeap.");
2734 mRawSnapshotAshmemHeap.clear();
2735 }
2736 mRawSnapshotAshmemHeap = new AshmemPool(
2737 mRawSnapShotPmemHeap->mBufferSize,
2738 mRawSnapShotPmemHeap->mNumBuffers,
2739 mRawSnapShotPmemHeap->mFrameSize,
2740 "raw ashmem snapshot camera"
2741 );
2742
2743 if(!mRawSnapshotAshmemHeap->initialized()){
2744 LOGE("receiveRawSnapshot X: error initializing mRawSnapshotHeap");
2745 deinitRawSnapshot();
2746 return;
2747 }
2748
2749 memcpy(mRawSnapshotAshmemHeap->mHeap->base(),
2750 mRawSnapShotPmemHeap->mHeap->base(),
2751 mRawSnapShotPmemHeap->mHeap->getSize());
2752
2753 mDataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mRawSnapshotAshmemHeap->mBuffers[0],
2754 mCallbackCookie);
2755
2756 }
2757
2758 //cleanup
2759 deinitRawSnapshot();
2760
2761 LOGV("receiveRawSnapshot X");
2762}
2763
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002764void QualcommCameraHardware::receiveRawPicture()
2765{
2766 LOGV("receiveRawPicture: E");
2767
2768 Mutex::Autolock cbLock(&mCallbackLock);
2769 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_RAW_IMAGE)) {
2770 if(native_get_picture(mCameraControlFd, &mCrop) == false) {
2771 LOGE("getPicture failed!");
2772 return;
2773 }
2774 mCrop.in1_w &= ~1;
2775 mCrop.in1_h &= ~1;
2776 mCrop.in2_w &= ~1;
2777 mCrop.in2_h &= ~1;
2778
2779 // By the time native_get_picture returns, picture is taken. Call
2780 // shutter callback if cam config thread has not done that.
2781 notifyShutter(&mCrop);
2782
2783 // Crop the image if zoomed.
2784 if (mCrop.in2_w != 0 && mCrop.in2_h != 0) {
2785 crop_yuv420(mCrop.out2_w, mCrop.out2_h, mCrop.in2_w, mCrop.in2_h,
2786 (uint8_t *)mRawHeap->mHeap->base());
2787 crop_yuv420(mCrop.out1_w, mCrop.out1_h, mCrop.in1_w, mCrop.in1_h,
2788 (uint8_t *)mThumbnailHeap->mHeap->base());
2789 // We do not need jpeg encoder to upscale the image. Set the new
2790 // dimension for encoder.
2791 mDimension.orig_picture_dx = mCrop.in2_w;
2792 mDimension.orig_picture_dy = mCrop.in2_h;
2793 mDimension.thumbnail_width = mCrop.in1_w;
2794 mDimension.thumbnail_height = mCrop.in1_h;
2795 memset(&mCrop, 0, sizeof(mCrop));
2796 }
2797
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002798 if( mUseOverlay && (mOverlay != NULL) ) {
2799 mOverlay->setFd(mPostViewHeap->mHeap->getHeapID());
2800 if( zoomCropInfo.w !=0 && zoomCropInfo.h !=0) {
2801 LOGD(" zoomCropInfo non-zero, setting crop ");
2802 mOverlay->setCrop(zoomCropInfo.x, zoomCropInfo.y,
2803 zoomCropInfo.w, zoomCropInfo.h);
2804 }
2805 LOGD(" Queueing Postview for display ");
2806 mOverlay->queueBuffer((void *)0);
2807 }
2808
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002809 mDataCallback(CAMERA_MSG_RAW_IMAGE, mDisplayHeap->mBuffers[0],
2810 mCallbackCookie);
2811 }
2812 else LOGV("Raw-picture callback was canceled--skipping.");
2813
2814 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
2815 mJpegSize = 0;
2816 if (LINK_jpeg_encoder_init()) {
2817 if(native_jpeg_encode()) {
2818 LOGV("receiveRawPicture: X (success)");
2819 return;
2820 }
2821 LOGE("jpeg encoding failed");
2822 }
2823 else LOGE("receiveRawPicture X: jpeg_encoder_init failed.");
2824 }
2825 else LOGV("JPEG callback is NULL, not encoding image.");
2826 deinitRaw();
2827 LOGV("receiveRawPicture: X");
2828}
2829
2830void QualcommCameraHardware::receiveJpegPictureFragment(
2831 uint8_t *buff_ptr, uint32_t buff_size)
2832{
2833 uint32_t remaining = mJpegHeap->mHeap->virtualSize();
2834 remaining -= mJpegSize;
2835 uint8_t *base = (uint8_t *)mJpegHeap->mHeap->base();
2836
2837 LOGV("receiveJpegPictureFragment size %d", buff_size);
2838 if (buff_size > remaining) {
2839 LOGE("receiveJpegPictureFragment: size %d exceeds what "
2840 "remains in JPEG heap (%d), truncating",
2841 buff_size,
2842 remaining);
2843 buff_size = remaining;
2844 }
2845 memcpy(base + mJpegSize, buff_ptr, buff_size);
2846 mJpegSize += buff_size;
2847}
2848
2849void QualcommCameraHardware::receiveJpegPicture(void)
2850{
2851 LOGV("receiveJpegPicture: E image (%d uint8_ts out of %d)",
2852 mJpegSize, mJpegHeap->mBufferSize);
2853 Mutex::Autolock cbLock(&mCallbackLock);
2854
2855 int index = 0, rc;
2856
2857 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
2858 // The reason we do not allocate into mJpegHeap->mBuffers[offset] is
2859 // that the JPEG image's size will probably change from one snapshot
2860 // to the next, so we cannot reuse the MemoryBase object.
2861 sp<MemoryBase> buffer = new
2862 MemoryBase(mJpegHeap->mHeap,
2863 index * mJpegHeap->mBufferSize +
2864 0,
2865 mJpegSize);
2866 mDataCallback(CAMERA_MSG_COMPRESSED_IMAGE, buffer, mCallbackCookie);
2867 buffer = NULL;
2868 }
2869 else LOGV("JPEG callback was cancelled--not delivering image.");
2870
2871 LINK_jpeg_encoder_join();
2872 deinitRaw();
2873
2874 LOGV("receiveJpegPicture: X callback done.");
2875}
2876
2877bool QualcommCameraHardware::previewEnabled()
2878{
2879 return mCameraRunning && mDataCallback && (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME);
2880}
2881
2882status_t QualcommCameraHardware::setPreviewSize(const CameraParameters& params)
2883{
2884 int width, height;
2885 params.getPreviewSize(&width, &height);
2886 LOGV("requested preview size %d x %d", width, height);
2887
2888 // Validate the preview size
2889 for (size_t i = 0; i < PREVIEW_SIZE_COUNT; ++i) {
2890 if (width == preview_sizes[i].width
2891 && height == preview_sizes[i].height) {
2892 mParameters.setPreviewSize(width, height);
2893 mDimension.display_width = width;
2894 mDimension.display_height = height;
2895 return NO_ERROR;
2896 }
2897 }
2898 LOGE("Invalid preview size requested: %dx%d", width, height);
2899 return BAD_VALUE;
2900}
2901
2902status_t QualcommCameraHardware::setPictureSize(const CameraParameters& params)
2903{
2904 int width, height;
2905 params.getPictureSize(&width, &height);
2906 LOGV("requested picture size %d x %d", width, height);
2907
2908 // Validate the picture size
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -08002909 for (int i = 0; i < supportedPictureSizesCount; ++i) {
2910 if (width == picture_sizes_ptr[i].width
2911 && height == picture_sizes_ptr[i].height) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002912 mParameters.setPictureSize(width, height);
2913 mDimension.picture_width = width;
2914 mDimension.picture_height = height;
2915 return NO_ERROR;
2916 }
2917 }
2918 LOGE("Invalid picture size requested: %dx%d", width, height);
2919 return BAD_VALUE;
2920}
2921
2922status_t QualcommCameraHardware::setJpegQuality(const CameraParameters& params) {
2923 status_t rc = NO_ERROR;
2924 int quality = params.getInt(CameraParameters::KEY_JPEG_QUALITY);
2925 if (quality > 0 && quality <= 100) {
2926 mParameters.set(CameraParameters::KEY_JPEG_QUALITY, quality);
2927 } else {
2928 LOGE("Invalid jpeg quality=%d", quality);
2929 rc = BAD_VALUE;
2930 }
2931
2932 quality = params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY);
2933 if (quality > 0 && quality <= 100) {
2934 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, quality);
2935 } else {
2936 LOGE("Invalid jpeg thumbnail quality=%d", quality);
2937 rc = BAD_VALUE;
2938 }
2939 return rc;
2940}
2941
2942status_t QualcommCameraHardware::setEffect(const CameraParameters& params)
2943{
2944 const char *str = params.get(CameraParameters::KEY_EFFECT);
2945 if (str != NULL) {
2946 int32_t value = attr_lookup(effects, sizeof(effects) / sizeof(str_map), str);
2947 if (value != NOT_FOUND) {
Mohan Kandra93f1bfb2009-12-15 16:55:33 -08002948 if(!strcmp(sensorType->name, "2mp") && (value != CAMERA_EFFECT_OFF)
2949 &&(value != CAMERA_EFFECT_MONO) && (value != CAMERA_EFFECT_NEGATIVE)
2950 &&(value != CAMERA_EFFECT_SOLARIZE) && (value != CAMERA_EFFECT_SEPIA)) {
2951 LOGE("Special effect parameter is not supported for this sensor");
2952 return NO_ERROR;
2953 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002954 mParameters.set(CameraParameters::KEY_EFFECT, str);
2955 bool ret = native_set_parm(CAMERA_SET_PARM_EFFECT, sizeof(value),
2956 (void *)&value);
2957 return ret ? NO_ERROR : UNKNOWN_ERROR;
2958 }
2959 }
2960 LOGE("Invalid effect value: %s", (str == NULL) ? "NULL" : str);
2961 return BAD_VALUE;
2962}
2963
Apurva Rajguru55562b02009-12-03 12:25:35 -08002964status_t QualcommCameraHardware::setAutoExposure(const CameraParameters& params)
2965{
Mohan Kandra93f1bfb2009-12-15 16:55:33 -08002966 if(!strcmp(sensorType->name, "2mp")) {
2967 LOGE("Auto Exposure not supported for this sensor");
2968 return NO_ERROR;
2969 }
Apurva Rajguru55562b02009-12-03 12:25:35 -08002970 const char *str = params.get(CameraParameters::KEY_AUTO_EXPOSURE);
2971 if (str != NULL) {
2972 int32_t value = attr_lookup(autoexposure, sizeof(autoexposure) / sizeof(str_map), str);
2973 if (value != NOT_FOUND) {
2974 mParameters.set(CameraParameters::KEY_AUTO_EXPOSURE, str);
2975 bool ret = native_set_parm(CAMERA_SET_PARM_EXPOSURE, sizeof(value),
2976 (void *)&value);
2977 return ret ? NO_ERROR : UNKNOWN_ERROR;
2978 }
2979 }
2980 LOGE("Invalid auto exposure value: %s", (str == NULL) ? "NULL" : str);
2981 return BAD_VALUE;
2982}
2983
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08002984status_t QualcommCameraHardware::setSharpness(const CameraParameters& params)
2985{
2986 if(!strcmp(sensorType->name, "2mp")) {
2987 LOGE("Sharpness not supported for this sensor");
2988 return NO_ERROR;
2989 }
2990 int sharpness = params.getInt(CameraParameters::KEY_SHARPNESS);
2991 if((sharpness < CAMERA_MIN_SHARPNESS
2992 || sharpness > CAMERA_MAX_SHARPNESS))
2993 return UNKNOWN_ERROR;
Srinivasan Kannan551fd262010-01-14 17:48:30 -08002994
2995 LOGV("setting sharpness %d", sharpness);
2996 mParameters.set(CameraParameters::KEY_SHARPNESS, sharpness);
2997 bool ret = native_set_parm(CAMERA_SET_PARM_SHARPNESS, sizeof(sharpness),
2998 (void *)&sharpness);
2999 return ret ? NO_ERROR : UNKNOWN_ERROR;
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003000}
3001
3002status_t QualcommCameraHardware::setContrast(const CameraParameters& params)
3003{
3004 if(!strcmp(sensorType->name, "2mp")) {
3005 LOGE("Contrast not supported for this sensor");
3006 return NO_ERROR;
3007 }
3008 int contrast = params.getInt(CameraParameters::KEY_CONTRAST);
3009 if((contrast < CAMERA_MIN_CONTRAST)
3010 || (contrast > CAMERA_MAX_CONTRAST))
3011 return UNKNOWN_ERROR;
Srinivasan Kannan551fd262010-01-14 17:48:30 -08003012
3013 LOGV("setting contrast %d", contrast);
3014 mParameters.set(CameraParameters::KEY_CONTRAST, contrast);
3015 bool ret = native_set_parm(CAMERA_SET_PARM_CONTRAST, sizeof(contrast),
3016 (void *)&contrast);
3017 return ret ? NO_ERROR : UNKNOWN_ERROR;
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003018}
3019
3020status_t QualcommCameraHardware::setSaturation(const CameraParameters& params)
3021{
3022 if(!strcmp(sensorType->name, "2mp")) {
3023 LOGE("Saturation not supported for this sensor");
3024 return NO_ERROR;
3025 }
3026 int saturation = params.getInt(CameraParameters::KEY_SATURATION);
3027 if((saturation < CAMERA_MIN_SATURATION)
3028 || (saturation > CAMERA_MAX_SATURATION))
3029 return UNKNOWN_ERROR;
Srinivasan Kannan551fd262010-01-14 17:48:30 -08003030
3031 LOGV("setting saturation %d", saturation);
3032 mParameters.set(CameraParameters::KEY_SATURATION, saturation);
3033 bool ret = native_set_parm(CAMERA_SET_PARM_SATURATION, sizeof(saturation),
3034 (void *)&saturation);
3035 return ret ? NO_ERROR : UNKNOWN_ERROR;
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003036}
3037
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303038status_t QualcommCameraHardware::setBrightness(const CameraParameters& params) {
3039 int brightness = params.getInt("luma-adaptation");
3040 if (mBrightness != brightness) {
3041 LOGV(" new brightness value : %d ", brightness);
3042 mBrightness = brightness;
3043
3044 bool ret = native_set_parm(CAMERA_SET_PARM_BRIGHTNESS, sizeof(mBrightness),
3045 (void *)&mBrightness);
3046 return ret ? NO_ERROR : UNKNOWN_ERROR;
3047 } else {
3048 return NO_ERROR;
3049 }
3050}
3051
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003052status_t QualcommCameraHardware::setWhiteBalance(const CameraParameters& params)
3053{
3054 const char *str = params.get(CameraParameters::KEY_WHITE_BALANCE);
3055 if (str != NULL) {
3056 int32_t value = attr_lookup(whitebalance, sizeof(whitebalance) / sizeof(str_map), str);
3057 if (value != NOT_FOUND) {
3058 mParameters.set(CameraParameters::KEY_WHITE_BALANCE, str);
3059 bool ret = native_set_parm(CAMERA_SET_PARM_WB, sizeof(value),
3060 (void *)&value);
3061 return ret ? NO_ERROR : UNKNOWN_ERROR;
3062 }
3063 }
3064 LOGE("Invalid whitebalance value: %s", (str == NULL) ? "NULL" : str);
3065 return BAD_VALUE;
3066}
3067
3068status_t QualcommCameraHardware::setFlash(const CameraParameters& params)
3069{
3070 if (!mSensorInfo.flash_enabled) {
3071 LOGV("%s: flash not supported", __FUNCTION__);
3072 return NO_ERROR;
3073 }
3074
3075 const char *str = params.get(CameraParameters::KEY_FLASH_MODE);
3076 if (str != NULL) {
3077 int32_t value = attr_lookup(flash, sizeof(flash) / sizeof(str_map), str);
3078 if (value != NOT_FOUND) {
3079 mParameters.set(CameraParameters::KEY_FLASH_MODE, str);
3080 bool ret = native_set_parm(CAMERA_SET_PARM_LED_MODE,
3081 sizeof(value), (void *)&value);
3082 return ret ? NO_ERROR : UNKNOWN_ERROR;
3083 }
3084 }
3085 LOGE("Invalid flash mode value: %s", (str == NULL) ? "NULL" : str);
3086 return BAD_VALUE;
3087}
3088
3089status_t QualcommCameraHardware::setAntibanding(const CameraParameters& params)
3090{
Srinivasan Kannan2229d272010-01-05 14:58:28 -08003091 if(!strcmp(sensorType->name, "2mp")) {
3092 LOGE("Parameter AntiBanding is not supported for this sensor");
3093 return NO_ERROR;
3094 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003095 const char *str = params.get(CameraParameters::KEY_ANTIBANDING);
3096 if (str != NULL) {
3097 int value = (camera_antibanding_type)attr_lookup(
3098 antibanding, sizeof(antibanding) / sizeof(str_map), str);
3099 if (value != NOT_FOUND) {
3100 camera_antibanding_type temp = (camera_antibanding_type) value;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003101 mParameters.set(CameraParameters::KEY_ANTIBANDING, str);
Srinivasan Kannan2229d272010-01-05 14:58:28 -08003102 bool ret;
3103 if (temp == CAMERA_ANTIBANDING_AUTO) {
3104 ret = native_set_parm(CAMERA_ENABLE_AFD,
3105 0, NULL);
3106 } else {
3107 ret = native_set_parm(CAMERA_SET_PARM_ANTIBANDING,
3108 sizeof(camera_antibanding_type), (void *)&temp);
3109 }
3110 return ret ? NO_ERROR : UNKNOWN_ERROR;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003111 }
3112 }
3113 LOGE("Invalid antibanding value: %s", (str == NULL) ? "NULL" : str);
3114 return BAD_VALUE;
3115}
3116
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303117status_t QualcommCameraHardware::setLensshadeValue(const CameraParameters& params)
3118{
Mohan Kandra93f1bfb2009-12-15 16:55:33 -08003119 if(!strcmp(sensorType->name, "2mp")) {
3120 LOGE("Parameter Rolloff is not supported for this sensor");
3121 return NO_ERROR;
3122 }
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303123 const char *str = params.get(CameraParameters::KEY_LENSSHADE);
3124 if (str != NULL) {
3125 int value = attr_lookup(lensshade,
3126 sizeof(lensshade) / sizeof(str_map), str);
3127 if (value != NOT_FOUND) {
3128 int8_t temp = (int8_t)value;
3129 mParameters.set(CameraParameters::KEY_LENSSHADE, str);
3130 native_set_parm(CAMERA_SET_PARM_ROLLOFF, sizeof(int8_t), (void *)&temp);
3131 return NO_ERROR;
3132 }
3133 }
3134 LOGE("Invalid lensShade value: %s", (str == NULL) ? "NULL" : str);
3135 return BAD_VALUE;
3136}
3137
3138status_t QualcommCameraHardware::setISOValue(const CameraParameters& params) {
3139 const char *str = params.get(CameraParameters::KEY_ISO_MODE);
3140 if (str != NULL) {
3141 int value = (camera_iso_mode_type)attr_lookup(
3142 iso, sizeof(iso) / sizeof(str_map), str);
3143 if (value != NOT_FOUND) {
3144 camera_iso_mode_type temp = (camera_iso_mode_type) value;
3145 mParameters.set(CameraParameters::KEY_ISO_MODE, str);
3146 native_set_parm(CAMERA_SET_PARM_ISO, sizeof(camera_iso_mode_type), (void *)&temp);
3147 return NO_ERROR;
3148 }
3149 }
3150 LOGE("Invalid Iso value: %s", (str == NULL) ? "NULL" : str);
3151 return BAD_VALUE;
3152}
3153
3154
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003155status_t QualcommCameraHardware::setGpsLocation(const CameraParameters& params)
3156{
3157 const char *latitude = params.get(CameraParameters::KEY_GPS_LATITUDE);
3158 if (latitude) {
3159 mParameters.set(CameraParameters::KEY_GPS_LATITUDE, latitude);
3160 }
3161
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08003162 const char *latitudeRef = params.get(CameraParameters::KEY_GPS_LATITUDE_REF);
3163 if (latitudeRef) {
3164 mParameters.set(CameraParameters::KEY_GPS_LATITUDE_REF, latitudeRef);
3165 }
3166
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003167 const char *longitude = params.get(CameraParameters::KEY_GPS_LONGITUDE);
3168 if (longitude) {
3169 mParameters.set(CameraParameters::KEY_GPS_LONGITUDE, longitude);
3170 }
3171
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08003172 const char *longitudeRef = params.get(CameraParameters::KEY_GPS_LONGITUDE_REF);
3173 if (longitudeRef) {
3174 mParameters.set(CameraParameters::KEY_GPS_LONGITUDE_REF, longitudeRef);
3175 }
3176
3177 const char *altitudeRef = params.get(CameraParameters::KEY_GPS_ALTITUDE_REF);
3178 if (altitudeRef) {
3179 mParameters.set(CameraParameters::KEY_GPS_ALTITUDE_REF, altitudeRef);
3180 }
3181
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003182 const char *altitude = params.get(CameraParameters::KEY_GPS_ALTITUDE);
3183 if (altitude) {
3184 mParameters.set(CameraParameters::KEY_GPS_ALTITUDE, altitude);
3185 }
3186
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08003187 const char *status = params.get(CameraParameters::KEY_GPS_STATUS);
3188 if (status) {
3189 mParameters.set(CameraParameters::KEY_GPS_STATUS, status);
3190 }
3191
3192 const char *dateTime = params.get(CameraParameters::KEY_EXIF_DATETIME);
3193 if (dateTime) {
3194 mParameters.set(CameraParameters::KEY_EXIF_DATETIME, dateTime);
3195 }
3196
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003197 const char *timestamp = params.get(CameraParameters::KEY_GPS_TIMESTAMP);
3198 if (timestamp) {
3199 mParameters.set(CameraParameters::KEY_GPS_TIMESTAMP, timestamp);
3200 }
3201 return NO_ERROR;
3202}
3203
3204status_t QualcommCameraHardware::setRotation(const CameraParameters& params)
3205{
3206 status_t rc = NO_ERROR;
3207 int rotation = params.getInt(CameraParameters::KEY_ROTATION);
3208 if (rotation != NOT_FOUND) {
3209 if (rotation == 0 || rotation == 90 || rotation == 180
3210 || rotation == 270) {
3211 mParameters.set(CameraParameters::KEY_ROTATION, rotation);
3212 } else {
3213 LOGE("Invalid rotation value: %d", rotation);
3214 rc = BAD_VALUE;
3215 }
3216 }
3217 return rc;
3218}
3219
3220status_t QualcommCameraHardware::setZoom(const CameraParameters& params)
3221{
3222 status_t rc = NO_ERROR;
3223 // No matter how many different zoom values the driver can provide, HAL
3224 // provides applictations the same number of zoom levels. The maximum driver
3225 // zoom value depends on sensor output (VFE input) and preview size (VFE
3226 // output) because VFE can only crop and cannot upscale. If the preview size
3227 // is bigger, the maximum zoom ratio is smaller. However, we want the
3228 // zoom ratio of each zoom level is always the same whatever the preview
3229 // size is. Ex: zoom level 1 is always 1.2x, zoom level 2 is 1.44x, etc. So,
3230 // we need to have a fixed maximum zoom value and do read it from the
3231 // driver.
Mohan Kandra284966d2010-01-05 13:39:15 -08003232 static const int ZOOM_STEP = 1;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003233 int32_t zoom_level = params.getInt("zoom");
3234
Mohan Kandra284966d2010-01-05 13:39:15 -08003235 LOGV("Set zoom=%d", zoom_level);
3236 if(zoom_level >= 0 && zoom_level <= mMaxZoom) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003237 mParameters.set("zoom", zoom_level);
3238 int32_t zoom_value = ZOOM_STEP * zoom_level;
3239 bool ret = native_set_parm(CAMERA_SET_PARM_ZOOM,
3240 sizeof(zoom_value), (void *)&zoom_value);
3241 rc = ret ? NO_ERROR : UNKNOWN_ERROR;
3242 } else {
3243 rc = BAD_VALUE;
3244 }
3245
3246 return rc;
3247}
3248
3249status_t QualcommCameraHardware::setFocusMode(const CameraParameters& params)
3250{
3251 const char *str = params.get(CameraParameters::KEY_FOCUS_MODE);
3252 if (str != NULL) {
3253 int32_t value = attr_lookup(focus_modes,
3254 sizeof(focus_modes) / sizeof(str_map), str);
3255 if (value != NOT_FOUND) {
3256 mParameters.set(CameraParameters::KEY_FOCUS_MODE, str);
3257 // Focus step is reset to infinity when preview is started. We do
3258 // not need to do anything now.
3259 return NO_ERROR;
3260 }
3261 }
3262 LOGE("Invalid focus mode value: %s", (str == NULL) ? "NULL" : str);
3263 return BAD_VALUE;
3264}
3265
3266status_t QualcommCameraHardware::setOrientation(const CameraParameters& params)
3267{
3268 const char *str = params.get("orientation");
3269
3270 if (str != NULL) {
3271 if (strcmp(str, "portrait") == 0 || strcmp(str, "landscape") == 0) {
3272 // Camera service needs this to decide if the preview frames and raw
3273 // pictures should be rotated.
3274 mParameters.set("orientation", str);
3275 } else {
3276 LOGE("Invalid orientation value: %s", str);
3277 return BAD_VALUE;
3278 }
3279 }
3280 return NO_ERROR;
3281}
3282
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08003283status_t QualcommCameraHardware::setPictureFormat(const CameraParameters& params)
3284{
3285 const char * str = params.get(CameraParameters::KEY_PICTURE_FORMAT);
3286
3287 if(str != NULL){
3288 int32_t value = attr_lookup(picture_formats,
3289 sizeof(picture_formats) / sizeof(str_map), str);
3290 if(value != NOT_FOUND){
3291 mParameters.set(CameraParameters::KEY_PICTURE_FORMAT, str);
3292 } else {
3293 LOGE("Invalid Picture Format value: %s", str);
3294 return BAD_VALUE;
3295 }
3296 }
3297 return NO_ERROR;
3298}
3299
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003300QualcommCameraHardware::MemPool::MemPool(int buffer_size, int num_buffers,
3301 int frame_size,
3302 const char *name) :
3303 mBufferSize(buffer_size),
3304 mNumBuffers(num_buffers),
3305 mFrameSize(frame_size),
3306 mBuffers(NULL), mName(name)
3307{
3308 int page_size_minus_1 = getpagesize() - 1;
3309 mAlignedBufferSize = (buffer_size + page_size_minus_1) & (~page_size_minus_1);
3310}
3311
3312void QualcommCameraHardware::MemPool::completeInitialization()
3313{
3314 // If we do not know how big the frame will be, we wait to allocate
3315 // the buffers describing the individual frames until we do know their
3316 // size.
3317
3318 if (mFrameSize > 0) {
3319 mBuffers = new sp<MemoryBase>[mNumBuffers];
3320 for (int i = 0; i < mNumBuffers; i++) {
3321 mBuffers[i] = new
3322 MemoryBase(mHeap,
3323 i * mAlignedBufferSize,
3324 mFrameSize);
3325 }
3326 }
3327}
3328
3329QualcommCameraHardware::AshmemPool::AshmemPool(int buffer_size, int num_buffers,
3330 int frame_size,
3331 const char *name) :
3332 QualcommCameraHardware::MemPool(buffer_size,
3333 num_buffers,
3334 frame_size,
3335 name)
3336{
3337 LOGV("constructing MemPool %s backed by ashmem: "
3338 "%d frames @ %d uint8_ts, "
3339 "buffer size %d",
3340 mName,
3341 num_buffers, frame_size, buffer_size);
3342
3343 int page_mask = getpagesize() - 1;
3344 int ashmem_size = buffer_size * num_buffers;
3345 ashmem_size += page_mask;
3346 ashmem_size &= ~page_mask;
3347
3348 mHeap = new MemoryHeapBase(ashmem_size);
3349
3350 completeInitialization();
3351}
3352
3353static bool register_buf(int camfd,
3354 int size,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08003355 int frame_size,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003356 int pmempreviewfd,
3357 uint32_t offset,
3358 uint8_t *buf,
3359 int pmem_type,
3360 bool vfe_can_write,
3361 bool register_buffer = true);
3362
3363QualcommCameraHardware::PmemPool::PmemPool(const char *pmem_pool,
3364 int flags,
3365 int camera_control_fd,
3366 int pmem_type,
3367 int buffer_size, int num_buffers,
3368 int frame_size,
3369 const char *name) :
3370 QualcommCameraHardware::MemPool(buffer_size,
3371 num_buffers,
3372 frame_size,
3373 name),
3374 mPmemType(pmem_type),
3375 mCameraControlFd(dup(camera_control_fd))
3376{
3377 LOGV("constructing MemPool %s backed by pmem pool %s: "
3378 "%d frames @ %d bytes, buffer size %d",
3379 mName,
3380 pmem_pool, num_buffers, frame_size,
3381 buffer_size);
3382
3383 LOGV("%s: duplicating control fd %d --> %d",
3384 __FUNCTION__,
3385 camera_control_fd, mCameraControlFd);
3386
3387 // Make a new mmap'ed heap that can be shared across processes.
3388 // mAlignedBufferSize is already in 4k aligned. (do we need total size necessary to be in power of 2??)
3389 mAlignedSize = mAlignedBufferSize * num_buffers;
3390
3391 sp<MemoryHeapBase> masterHeap =
3392 new MemoryHeapBase(pmem_pool, mAlignedSize, flags);
3393
3394 if (masterHeap->getHeapID() < 0) {
3395 LOGE("failed to construct master heap for pmem pool %s", pmem_pool);
3396 masterHeap.clear();
3397 return;
3398 }
3399
3400 sp<MemoryHeapPmem> pmemHeap = new MemoryHeapPmem(masterHeap, flags);
3401 if (pmemHeap->getHeapID() >= 0) {
3402 pmemHeap->slap();
3403 masterHeap.clear();
3404 mHeap = pmemHeap;
3405 pmemHeap.clear();
3406
3407 mFd = mHeap->getHeapID();
3408 if (::ioctl(mFd, PMEM_GET_SIZE, &mSize)) {
3409 LOGE("pmem pool %s ioctl(PMEM_GET_SIZE) error %s (%d)",
3410 pmem_pool,
3411 ::strerror(errno), errno);
3412 mHeap.clear();
3413 return;
3414 }
3415
3416 LOGV("pmem pool %s ioctl(fd = %d, PMEM_GET_SIZE) is %ld",
3417 pmem_pool,
3418 mFd,
3419 mSize.len);
Mohan Kandra284966d2010-01-05 13:39:15 -08003420 LOGD("mBufferSize=%d, mAlignedBufferSize=%d\n", mBufferSize, mAlignedBufferSize);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003421 // Unregister preview buffers with the camera drivers. Allow the VFE to write
3422 // to all preview buffers except for the last one.
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003423 // Only Register the preview, snapshot and thumbnail buffers with the kernel.
Mohan Kandrad9efed92010-01-15 19:08:39 -08003424 if( (strcmp("postview", mName) != 0) ){
3425 int num_buf = num_buffers;
3426 if(!strcmp("preview", mName)) num_buf = kPreviewBufferCount;
3427 LOGE("num_buffers = %d", num_buf);
3428 for (int cnt = 0; cnt < num_buf; ++cnt) {
Mohan Kandra284966d2010-01-05 13:39:15 -08003429 register_buf(mCameraControlFd,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003430 mBufferSize,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08003431 mFrameSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003432 mHeap->getHeapID(),
3433 mAlignedBufferSize * cnt,
3434 (uint8_t *)mHeap->base() + mAlignedBufferSize * cnt,
3435 pmem_type,
Mohan Kandrad9efed92010-01-15 19:08:39 -08003436 !(cnt == num_buf - 1 && pmem_type == MSM_PMEM_OUTPUT2));
Mohan Kandra284966d2010-01-05 13:39:15 -08003437 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003438 }
3439
3440 completeInitialization();
3441 }
3442 else LOGE("pmem pool %s error: could not create master heap!",
3443 pmem_pool);
3444}
3445
3446QualcommCameraHardware::PmemPool::~PmemPool()
3447{
3448 LOGV("%s: %s E", __FUNCTION__, mName);
3449 if (mHeap != NULL) {
3450 // Unregister preview buffers with the camera drivers.
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003451 // Only Unregister the preview, snapshot and thumbnail
3452 // buffers with the kernel.
Mohan Kandrad9efed92010-01-15 19:08:39 -08003453 if( (strcmp("postview", mName) != 0) ){
3454 int num_buffers = mNumBuffers;
3455 if(!strcmp("preview", mName)) num_buffers = kPreviewBufferCount;
3456 for (int cnt = 0; cnt < num_buffers; ++cnt) {
Mohan Kandra284966d2010-01-05 13:39:15 -08003457 register_buf(mCameraControlFd,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003458 mBufferSize,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08003459 mFrameSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003460 mHeap->getHeapID(),
3461 mAlignedBufferSize * cnt,
3462 (uint8_t *)mHeap->base() + mAlignedBufferSize * cnt,
3463 mPmemType,
3464 false,
3465 false /* unregister */);
Mohan Kandra284966d2010-01-05 13:39:15 -08003466 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003467 }
3468 }
3469 LOGV("destroying PmemPool %s: closing control fd %d",
3470 mName,
3471 mCameraControlFd);
3472 close(mCameraControlFd);
3473 LOGV("%s: %s X", __FUNCTION__, mName);
3474}
3475
3476QualcommCameraHardware::MemPool::~MemPool()
3477{
3478 LOGV("destroying MemPool %s", mName);
3479 if (mFrameSize > 0)
3480 delete [] mBuffers;
3481 mHeap.clear();
3482 LOGV("destroying MemPool %s completed", mName);
3483}
3484
3485static bool register_buf(int camfd,
3486 int size,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08003487 int frame_size,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003488 int pmempreviewfd,
3489 uint32_t offset,
3490 uint8_t *buf,
3491 int pmem_type,
3492 bool vfe_can_write,
3493 bool register_buffer)
3494{
3495 struct msm_pmem_info pmemBuf;
3496
3497 pmemBuf.type = pmem_type;
3498 pmemBuf.fd = pmempreviewfd;
3499 pmemBuf.offset = offset;
3500 pmemBuf.len = size;
3501 pmemBuf.vaddr = buf;
3502 pmemBuf.y_off = 0;
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08003503 pmemBuf.cbcr_off = PAD_TO_WORD(frame_size * 2 / 3);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003504 pmemBuf.active = vfe_can_write;
3505
3506 LOGV("register_buf: camfd = %d, reg = %d buffer = %p",
3507 camfd, !register_buffer, buf);
3508 if (ioctl(camfd,
3509 register_buffer ?
3510 MSM_CAM_IOCTL_REGISTER_PMEM :
3511 MSM_CAM_IOCTL_UNREGISTER_PMEM,
3512 &pmemBuf) < 0) {
3513 LOGE("register_buf: MSM_CAM_IOCTL_(UN)REGISTER_PMEM fd %d error %s",
3514 camfd,
3515 strerror(errno));
3516 return false;
3517 }
3518 return true;
3519}
3520
3521status_t QualcommCameraHardware::MemPool::dump(int fd, const Vector<String16>& args) const
3522{
3523 const size_t SIZE = 256;
3524 char buffer[SIZE];
3525 String8 result;
3526 snprintf(buffer, 255, "QualcommCameraHardware::AshmemPool::dump\n");
3527 result.append(buffer);
3528 if (mName) {
3529 snprintf(buffer, 255, "mem pool name (%s)\n", mName);
3530 result.append(buffer);
3531 }
3532 if (mHeap != 0) {
3533 snprintf(buffer, 255, "heap base(%p), size(%d), flags(%d), device(%s)\n",
3534 mHeap->getBase(), mHeap->getSize(),
3535 mHeap->getFlags(), mHeap->getDevice());
3536 result.append(buffer);
3537 }
3538 snprintf(buffer, 255,
3539 "buffer size (%d), number of buffers (%d), frame size(%d)",
3540 mBufferSize, mNumBuffers, mFrameSize);
3541 result.append(buffer);
3542 write(fd, result.string(), result.size());
3543 return NO_ERROR;
3544}
3545
3546static void receive_camframe_callback(struct msm_frame *frame)
3547{
3548 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
3549 if (obj != 0) {
3550 obj->receivePreviewFrame(frame);
3551 }
3552}
3553
3554static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size)
3555{
3556 LOGV("receive_jpeg_fragment_callback E");
3557 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
3558 if (obj != 0) {
3559 obj->receiveJpegPictureFragment(buff_ptr, buff_size);
3560 }
3561 LOGV("receive_jpeg_fragment_callback X");
3562}
3563
3564static void receive_jpeg_callback(jpeg_event_t status)
3565{
3566 LOGV("receive_jpeg_callback E (completion status %d)", status);
3567 if (status == JPEG_EVENT_DONE) {
3568 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
3569 if (obj != 0) {
3570 obj->receiveJpegPicture();
3571 }
3572 }
3573 LOGV("receive_jpeg_callback X");
3574}
3575
3576void QualcommCameraHardware::setCallbacks(notify_callback notify_cb,
3577 data_callback data_cb,
3578 data_callback_timestamp data_cb_timestamp,
3579 void* user)
3580{
3581 Mutex::Autolock lock(mLock);
3582 mNotifyCallback = notify_cb;
3583 mDataCallback = data_cb;
3584 mDataCallbackTimestamp = data_cb_timestamp;
3585 mCallbackCookie = user;
3586}
3587
3588void QualcommCameraHardware::enableMsgType(int32_t msgType)
3589{
3590 Mutex::Autolock lock(mLock);
3591 mMsgEnabled |= msgType;
3592}
3593
3594void QualcommCameraHardware::disableMsgType(int32_t msgType)
3595{
3596 Mutex::Autolock lock(mLock);
3597 mMsgEnabled &= ~msgType;
3598}
3599
3600bool QualcommCameraHardware::msgTypeEnabled(int32_t msgType)
3601{
3602 return (mMsgEnabled & msgType);
3603}
3604
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08003605bool QualcommCameraHardware::useOverlay(void)
3606{
Mohan Kandra284966d2010-01-05 13:39:15 -08003607 if(!strcmp(mDeviceName,"msm7630_surf")) {
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08003608 /* Only 7x30 supports Overlay */
3609 mUseOverlay = TRUE;
3610 } else
3611 mUseOverlay = FALSE;
3612
3613 LOGV(" Using Overlay : %s ", mUseOverlay ? "YES" : "NO" );
3614 return mUseOverlay;
3615}
3616
3617status_t QualcommCameraHardware::setOverlay(const sp<Overlay> &Overlay)
3618{
3619 if( Overlay != NULL) {
3620 LOGV(" Valid overlay object ");
3621 mOverlayLock.lock();
3622 mOverlay = Overlay;
3623 mOverlayLock.unlock();
3624 } else {
3625 LOGE(" Overlay object NULL. returning ");
Mohan Kandrad9efed92010-01-15 19:08:39 -08003626 mOverlay = NULL;
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08003627 return UNKNOWN_ERROR;
3628 }
3629 return NO_ERROR;
3630}
Kiran Kumar H N215cac42009-12-08 01:53:46 -08003631
3632void QualcommCameraHardware::receive_camframetimeout(void) {
3633 LOGV("receive_camframetimeout: E");
3634 Mutex::Autolock l(&mCamframeTimeoutLock);
3635 camframe_timeout_flag = TRUE;
3636 LOGV("receive_camframetimeout: X");
3637}
3638
3639static void receive_camframetimeout_callback(void) {
3640 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
3641 if (obj != 0) {
3642 obj->receive_camframetimeout();
3643 }
3644}
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003645
3646void QualcommCameraHardware::storePreviewFrameForPostview(void) {
3647 LOGV(" storePreviewFrameForPostview : E ");
3648
3649 /* Since there is restriction on the maximum overlay dimensions
3650 * that can be created, we use the last preview frame as postview
3651 * for 7x30. */
3652 LOGV(" Copying the preview buffer to postview buffer %d ",
3653 mPreviewFrameSize);
3654 if( mPostViewHeap != NULL && mLastQueuedFrame != NULL) {
3655 memcpy(mPostViewHeap->mHeap->base(),
3656 (uint8_t *)mLastQueuedFrame, mPreviewFrameSize );
3657 } else
3658 LOGE(" Failed to store Preview frame. No Postview ");
3659
3660 LOGV(" storePreviewFrameForPostview : X ");
3661}
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003662}; // namespace android