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