blob: 3d169e6f2811deac8a578b51abca358d5662be87 [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
Mohan Kandrabad0eaa2010-02-04 15:11:54 -080019#define LOG_NIDEBUG 0
Priya Komarlingamb85535d2009-11-30 13:06:01 -080020#define LOG_TAG "QualcommCameraHardware"
21#include <utils/Log.h>
22
23#include "QualcommCameraHardware.h"
24
25#include <utils/Errors.h>
26#include <utils/threads.h>
27#include <binder/MemoryHeapPmem.h>
28#include <utils/String16.h>
29#include <sys/types.h>
30#include <sys/stat.h>
31#include <unistd.h>
Sravankb4f5f1c2010-01-21 11:06:17 +053032#include <fcntl.h>
Apurva Rajguru8d1773b2009-12-02 14:21:23 -080033#include <cutils/properties.h>
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -080034#include <math.h>
Priya Komarlingamb85535d2009-11-30 13:06:01 -080035#if HAVE_ANDROID_OS
36#include <linux/android_pmem.h>
37#endif
38#include <linux/ioctl.h>
39#include <ui/CameraParameters.h>
40
Mohan Kandra284966d2010-01-05 13:39:15 -080041#include "linux/msm_mdp.h"
42#include <linux/fb.h>
43
Priya Komarlingamb85535d2009-11-30 13:06:01 -080044#define LIKELY(exp) __builtin_expect(!!(exp), 1)
45#define UNLIKELY(exp) __builtin_expect(!!(exp), 0)
46
47extern "C" {
48#include <fcntl.h>
49#include <time.h>
50#include <pthread.h>
51#include <stdio.h>
52#include <string.h>
53#include <unistd.h>
54#include <termios.h>
55#include <assert.h>
56#include <stdlib.h>
57#include <ctype.h>
58#include <signal.h>
59#include <errno.h>
60#include <sys/mman.h>
61#include <sys/system_properties.h>
62#include <sys/time.h>
63#include <stdlib.h>
64
65#include <media/msm_camera.h>
66
67#include <camera.h>
68#include <camframe.h>
69#include <mm-still/jpeg/jpege.h>
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -080070#include <jpeg_encoder.h>
Priya Komarlingamb85535d2009-11-30 13:06:01 -080071
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -080072#define DEFAULT_PICTURE_WIDTH 1024
73#define DEFAULT_PICTURE_HEIGHT 768
Priya Komarlingamb85535d2009-11-30 13:06:01 -080074#define THUMBNAIL_BUFFER_SIZE (THUMBNAIL_WIDTH * THUMBNAIL_HEIGHT * 3/2)
75#define MAX_ZOOM_LEVEL 5
76#define NOT_FOUND -1
Apurva Rajgurua8b1fc92010-01-27 20:03:55 -080077#define JPEG_ENCODER_PADDING 8
Sravankb4f5f1c2010-01-21 11:06:17 +053078// Number of video buffers held by kernal (initially 1,2 &3)
79#define ACTIVE_VIDEO_BUFFERS 3
80
Priya Komarlingamb85535d2009-11-30 13:06:01 -080081#if DLOPEN_LIBMMCAMERA
82#include <dlfcn.h>
83
84void* (*LINK_cam_conf)(void *data);
85void* (*LINK_cam_frame)(void *data);
86bool (*LINK_jpeg_encoder_init)();
87void (*LINK_jpeg_encoder_join)();
88bool (*LINK_jpeg_encoder_encode)(const cam_ctrl_dimension_t *dimen,
89 const uint8_t *thumbnailbuf, int thumbnailfd,
90 const uint8_t *snapshotbuf, int snapshotfd,
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -080091 common_crop_t *scaling_parms, exif_tags_info_t *exif_data,
92 int exif_table_numEntries);
Kiran Kumar H N7ac84e32010-02-01 10:58:47 -080093void (*LINK_camframe_terminate)(void);
Sravankb4f5f1c2010-01-21 11:06:17 +053094//for 720p
95// Function to add a video buffer to free Q
96void (*LINK_camframe_free_video)(struct msm_frame *frame);
97// Function pointer , called by camframe when a video frame is available.
98void (**LINK_camframe_video_callback)(struct msm_frame * frame);
99// To flush free Q in cam frame.
100void (*LINK_cam_frame_flush_free_video)(void);
101
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800102int8_t (*LINK_jpeg_encoder_setMainImageQuality)(uint32_t quality);
103int8_t (*LINK_jpeg_encoder_setThumbnailQuality)(uint32_t quality);
104int8_t (*LINK_jpeg_encoder_setRotation)(uint32_t rotation);
105int8_t (*LINK_jpeg_encoder_setLocation)(const camera_position_type *location);
106const struct camera_size_type *(*LINK_default_sensor_get_snapshot_sizes)(int *len);
107int (*LINK_launch_cam_conf_thread)(void);
108int (*LINK_release_cam_conf_thread)(void);
109int8_t (*LINK_zoom_crop_upscale)(uint32_t width, uint32_t height,
110 uint32_t cropped_width, uint32_t cropped_height, uint8_t *img_buf);
111
112// callbacks
113void (**LINK_mmcamera_camframe_callback)(struct msm_frame *frame);
114void (**LINK_mmcamera_jpegfragment_callback)(uint8_t *buff_ptr,
115 uint32_t buff_size);
116void (**LINK_mmcamera_jpeg_callback)(jpeg_event_t status);
117void (**LINK_mmcamera_shutter_callback)(common_crop_t *crop);
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800118void (**LINK_camframe_timeout_callback)(void);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800119#else
120#define LINK_cam_conf cam_conf
121#define LINK_cam_frame cam_frame
122#define LINK_jpeg_encoder_init jpeg_encoder_init
123#define LINK_jpeg_encoder_join jpeg_encoder_join
124#define LINK_jpeg_encoder_encode jpeg_encoder_encode
125#define LINK_camframe_terminate camframe_terminate
126#define LINK_jpeg_encoder_setMainImageQuality jpeg_encoder_setMainImageQuality
127#define LINK_jpeg_encoder_setThumbnailQuality jpeg_encoder_setThumbnailQuality
128#define LINK_jpeg_encoder_setRotation jpeg_encoder_setRotation
129#define LINK_jpeg_encoder_setLocation jpeg_encoder_setLocation
130#define LINK_default_sensor_get_snapshot_sizes default_sensor_get_snapshot_sizes
131#define LINK_launch_cam_conf_thread launch_cam_conf_thread
132#define LINK_release_cam_conf_thread release_cam_conf_thread
133#define LINK_zoom_crop_upscale zoom_crop_upscale
134extern void (*mmcamera_camframe_callback)(struct msm_frame *frame);
135extern void (*mmcamera_jpegfragment_callback)(uint8_t *buff_ptr,
136 uint32_t buff_size);
137extern void (*mmcamera_jpeg_callback)(jpeg_event_t status);
138extern void (*mmcamera_shutter_callback)(common_crop_t *crop);
139#endif
140
141} // extern "C"
142
143#ifndef HAVE_CAMERA_SIZE_TYPE
144struct camera_size_type {
145 int width;
146 int height;
147};
148#endif
149
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -0800150typedef struct crop_info_struct {
151 uint32_t x;
152 uint32_t y;
153 uint32_t w;
154 uint32_t h;
155} zoom_crop_info;
156
Mohan Kandra740cfce2010-01-07 12:58:24 -0800157union zoomimage
Mohan Kandra284966d2010-01-05 13:39:15 -0800158{
159 char d[sizeof(struct mdp_blit_req_list) + sizeof(struct mdp_blit_req) * 1];
160 struct mdp_blit_req_list list;
161} zoomImage;
162
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800163//Default to WVGA
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -0800164#define DEFAULT_PREVIEW_WIDTH 800
165#define DEFAULT_PREVIEW_HEIGHT 480
166
167/*
168 * Modifying preview size requires modification
169 * in bitmasks for boardproperties
170 */
171
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800172static const camera_size_type preview_sizes[] = {
Srinivasan Kannanfa7edae2009-12-16 18:02:01 -0800173 { 1280, 720 }, // 720P, reserved
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800174 { 800, 480 }, // WVGA
Srinivasan Kannan613301c2010-02-10 17:08:53 -0800175 { 768, 432 },
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800176 { 720, 480 },
177 { 640, 480 }, // VGA
178 { 576, 432 },
179 { 480, 320 }, // HVGA
180 { 384, 288 },
181 { 352, 288 }, // CIF
182 { 320, 240 }, // QVGA
183 { 240, 160 }, // SQVGA
184 { 176, 144 }, // QCIF
185};
186#define PREVIEW_SIZE_COUNT (sizeof(preview_sizes)/sizeof(camera_size_type))
187
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -0800188static camera_size_type supportedPreviewSizes[PREVIEW_SIZE_COUNT];
189static unsigned int previewSizeCount;
190
191board_property boardProperties[] = {
192 {TARGET_MSM7625, 0x00000fff},
193 {TARGET_MSM7627, 0x000006ff},
194 {TARGET_MSM7630, 0x00000fff},
195 {TARGET_QSD8250, 0x00000fff}
196};
197
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800198//static const camera_size_type* picture_sizes;
199//static int PICTURE_SIZE_COUNT;
200/* TODO
201 * Ideally this should be a populated by lower layers.
202 * But currently this is no API to do that at lower layer.
203 * Hence populating with default sizes for now. This needs
204 * to be changed once the API is supported.
205 */
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800206//sorted on column basis
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800207static const camera_size_type picture_sizes[] = {
208 { 2592, 1944 }, // 5MP
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800209 { 2048, 1536 }, // 3MP QXGA
210 { 1920, 1080 }, //HD1080
211 { 1600, 1200 }, // 2MP UXGA
212 { 1280, 768 }, //WXGA
213 { 1280, 720 }, //HD720
214 { 1024, 768}, // 1MP XGA
215 { 800, 600 }, //SVGA
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800216 { 800, 480 }, // WVGA
217 { 640, 480 }, // VGA
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800218 { 352, 288 }, //CIF
219 { 320, 240 }, // QVGA
220 { 176, 144 } // QCIF
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800221};
222static int PICTURE_SIZE_COUNT = sizeof(picture_sizes)/sizeof(camera_size_type);
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800223static const camera_size_type * picture_sizes_ptr;
224static int supportedPictureSizesCount;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800225
Srinivasan Kannan80d878f2009-12-18 15:06:02 -0800226#ifdef Q12
227#undef Q12
228#endif
229
230#define Q12 4096
231
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -0800232static const target_map targetList [] = {
233 { "msm7625", TARGET_MSM7625 },
234 { "msm7627", TARGET_MSM7627 },
235 { "qsd8250", TARGET_QSD8250 },
236 { "msm7630", TARGET_MSM7630 }
237};
238static targetType mCurrentTarget = TARGET_MAX;
239
Srinivasan Kannan80d878f2009-12-18 15:06:02 -0800240typedef struct {
241 uint32_t aspect_ratio;
242 uint32_t width;
243 uint32_t height;
244} thumbnail_size_type;
245
246static thumbnail_size_type thumbnail_sizes[] = {
247 { 7281, 512, 288 }, //1.777778
248 { 6826, 480, 288 }, //1.666667
Kiran Kumar H Nb49af212010-02-17 15:12:17 -0800249 { 6144, 432, 288 }, //1.5
Srinivasan Kannan80d878f2009-12-18 15:06:02 -0800250 { 5461, 512, 384 }, //1.333333
251 { 5006, 352, 288 }, //1.222222
252};
253#define THUMBNAIL_SIZE_COUNT (sizeof(thumbnail_sizes)/sizeof(thumbnail_size_type))
254#define DEFAULT_THUMBNAIL_SETTING 2
255#define THUMBNAIL_WIDTH_STR "512"
256#define THUMBNAIL_HEIGHT_STR "384"
257#define THUMBNAIL_SMALL_HEIGHT 144
258
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800259static int attr_lookup(const str_map arr[], int len, const char *name)
260{
261 if (name) {
262 for (int i = 0; i < len; i++) {
263 if (!strcmp(arr[i].desc, name))
264 return arr[i].val;
265 }
266 }
267 return NOT_FOUND;
268}
269
270// round to the next power of two
271static inline unsigned clp2(unsigned x)
272{
273 x = x - 1;
274 x = x | (x >> 1);
275 x = x | (x >> 2);
276 x = x | (x >> 4);
277 x = x | (x >> 8);
278 x = x | (x >>16);
279 return x + 1;
280}
281
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -0800282static int exif_table_numEntries = 0;
283#define MAX_EXIF_TABLE_ENTRIES 7
284exif_tags_info_t exif_data[MAX_EXIF_TABLE_ENTRIES];
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -0800285static zoom_crop_info zoomCropInfo;
286static void *mLastQueuedFrame = NULL;
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -0800287
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800288namespace android {
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800289
290static const int PICTURE_FORMAT_JPEG = 1;
291static const int PICTURE_FORMAT_RAW = 2;
292
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800293// from aeecamera.h
294static const str_map whitebalance[] = {
295 { CameraParameters::WHITE_BALANCE_AUTO, CAMERA_WB_AUTO },
296 { CameraParameters::WHITE_BALANCE_INCANDESCENT, CAMERA_WB_INCANDESCENT },
297 { CameraParameters::WHITE_BALANCE_FLUORESCENT, CAMERA_WB_FLUORESCENT },
298 { CameraParameters::WHITE_BALANCE_DAYLIGHT, CAMERA_WB_DAYLIGHT },
299 { CameraParameters::WHITE_BALANCE_CLOUDY_DAYLIGHT, CAMERA_WB_CLOUDY_DAYLIGHT }
300};
301
302// from camera_effect_t. This list must match aeecamera.h
303static const str_map effects[] = {
304 { CameraParameters::EFFECT_NONE, CAMERA_EFFECT_OFF },
305 { CameraParameters::EFFECT_MONO, CAMERA_EFFECT_MONO },
306 { CameraParameters::EFFECT_NEGATIVE, CAMERA_EFFECT_NEGATIVE },
307 { CameraParameters::EFFECT_SOLARIZE, CAMERA_EFFECT_SOLARIZE },
308 { CameraParameters::EFFECT_SEPIA, CAMERA_EFFECT_SEPIA },
309 { CameraParameters::EFFECT_POSTERIZE, CAMERA_EFFECT_POSTERIZE },
310 { CameraParameters::EFFECT_WHITEBOARD, CAMERA_EFFECT_WHITEBOARD },
311 { CameraParameters::EFFECT_BLACKBOARD, CAMERA_EFFECT_BLACKBOARD },
312 { CameraParameters::EFFECT_AQUA, CAMERA_EFFECT_AQUA }
313};
314
315// from qcamera/common/camera.h
Apurva Rajguru55562b02009-12-03 12:25:35 -0800316static const str_map autoexposure[] = {
317 { CameraParameters::AUTO_EXPOSURE_FRAME_AVG, CAMERA_AEC_FRAME_AVERAGE },
318 { CameraParameters::AUTO_EXPOSURE_CENTER_WEIGHTED, CAMERA_AEC_CENTER_WEIGHTED },
319 { CameraParameters::AUTO_EXPOSURE_SPOT_METERING, CAMERA_AEC_SPOT_METERING }
320};
321
322// from qcamera/common/camera.h
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800323static const str_map antibanding[] = {
324 { CameraParameters::ANTIBANDING_OFF, CAMERA_ANTIBANDING_OFF },
325 { CameraParameters::ANTIBANDING_50HZ, CAMERA_ANTIBANDING_50HZ },
326 { CameraParameters::ANTIBANDING_60HZ, CAMERA_ANTIBANDING_60HZ },
327 { CameraParameters::ANTIBANDING_AUTO, CAMERA_ANTIBANDING_AUTO }
328};
329
330/* Mapping from MCC to antibanding type */
331struct country_map {
332 uint32_t country_code;
333 camera_antibanding_type type;
334};
335
336static struct country_map country_numeric[] = {
337 { 202, CAMERA_ANTIBANDING_50HZ }, // Greece
338 { 204, CAMERA_ANTIBANDING_50HZ }, // Netherlands
339 { 206, CAMERA_ANTIBANDING_50HZ }, // Belgium
340 { 208, CAMERA_ANTIBANDING_50HZ }, // France
341 { 212, CAMERA_ANTIBANDING_50HZ }, // Monaco
342 { 213, CAMERA_ANTIBANDING_50HZ }, // Andorra
343 { 214, CAMERA_ANTIBANDING_50HZ }, // Spain
344 { 216, CAMERA_ANTIBANDING_50HZ }, // Hungary
345 { 219, CAMERA_ANTIBANDING_50HZ }, // Croatia
346 { 220, CAMERA_ANTIBANDING_50HZ }, // Serbia
347 { 222, CAMERA_ANTIBANDING_50HZ }, // Italy
348 { 226, CAMERA_ANTIBANDING_50HZ }, // Romania
349 { 228, CAMERA_ANTIBANDING_50HZ }, // Switzerland
350 { 230, CAMERA_ANTIBANDING_50HZ }, // Czech Republic
351 { 231, CAMERA_ANTIBANDING_50HZ }, // Slovakia
352 { 232, CAMERA_ANTIBANDING_50HZ }, // Austria
353 { 234, CAMERA_ANTIBANDING_50HZ }, // United Kingdom
354 { 235, CAMERA_ANTIBANDING_50HZ }, // United Kingdom
355 { 238, CAMERA_ANTIBANDING_50HZ }, // Denmark
356 { 240, CAMERA_ANTIBANDING_50HZ }, // Sweden
357 { 242, CAMERA_ANTIBANDING_50HZ }, // Norway
358 { 244, CAMERA_ANTIBANDING_50HZ }, // Finland
359 { 246, CAMERA_ANTIBANDING_50HZ }, // Lithuania
360 { 247, CAMERA_ANTIBANDING_50HZ }, // Latvia
361 { 248, CAMERA_ANTIBANDING_50HZ }, // Estonia
362 { 250, CAMERA_ANTIBANDING_50HZ }, // Russian Federation
363 { 255, CAMERA_ANTIBANDING_50HZ }, // Ukraine
364 { 257, CAMERA_ANTIBANDING_50HZ }, // Belarus
365 { 259, CAMERA_ANTIBANDING_50HZ }, // Moldova
366 { 260, CAMERA_ANTIBANDING_50HZ }, // Poland
367 { 262, CAMERA_ANTIBANDING_50HZ }, // Germany
368 { 266, CAMERA_ANTIBANDING_50HZ }, // Gibraltar
369 { 268, CAMERA_ANTIBANDING_50HZ }, // Portugal
370 { 270, CAMERA_ANTIBANDING_50HZ }, // Luxembourg
371 { 272, CAMERA_ANTIBANDING_50HZ }, // Ireland
372 { 274, CAMERA_ANTIBANDING_50HZ }, // Iceland
373 { 276, CAMERA_ANTIBANDING_50HZ }, // Albania
374 { 278, CAMERA_ANTIBANDING_50HZ }, // Malta
375 { 280, CAMERA_ANTIBANDING_50HZ }, // Cyprus
376 { 282, CAMERA_ANTIBANDING_50HZ }, // Georgia
377 { 283, CAMERA_ANTIBANDING_50HZ }, // Armenia
378 { 284, CAMERA_ANTIBANDING_50HZ }, // Bulgaria
379 { 286, CAMERA_ANTIBANDING_50HZ }, // Turkey
380 { 288, CAMERA_ANTIBANDING_50HZ }, // Faroe Islands
381 { 290, CAMERA_ANTIBANDING_50HZ }, // Greenland
382 { 293, CAMERA_ANTIBANDING_50HZ }, // Slovenia
383 { 294, CAMERA_ANTIBANDING_50HZ }, // Macedonia
384 { 295, CAMERA_ANTIBANDING_50HZ }, // Liechtenstein
385 { 297, CAMERA_ANTIBANDING_50HZ }, // Montenegro
386 { 302, CAMERA_ANTIBANDING_60HZ }, // Canada
387 { 310, CAMERA_ANTIBANDING_60HZ }, // United States of America
388 { 311, CAMERA_ANTIBANDING_60HZ }, // United States of America
389 { 312, CAMERA_ANTIBANDING_60HZ }, // United States of America
390 { 313, CAMERA_ANTIBANDING_60HZ }, // United States of America
391 { 314, CAMERA_ANTIBANDING_60HZ }, // United States of America
392 { 315, CAMERA_ANTIBANDING_60HZ }, // United States of America
393 { 316, CAMERA_ANTIBANDING_60HZ }, // United States of America
394 { 330, CAMERA_ANTIBANDING_60HZ }, // Puerto Rico
395 { 334, CAMERA_ANTIBANDING_60HZ }, // Mexico
396 { 338, CAMERA_ANTIBANDING_50HZ }, // Jamaica
397 { 340, CAMERA_ANTIBANDING_50HZ }, // Martinique
398 { 342, CAMERA_ANTIBANDING_50HZ }, // Barbados
399 { 346, CAMERA_ANTIBANDING_60HZ }, // Cayman Islands
400 { 350, CAMERA_ANTIBANDING_60HZ }, // Bermuda
401 { 352, CAMERA_ANTIBANDING_50HZ }, // Grenada
402 { 354, CAMERA_ANTIBANDING_60HZ }, // Montserrat
403 { 362, CAMERA_ANTIBANDING_50HZ }, // Netherlands Antilles
404 { 363, CAMERA_ANTIBANDING_60HZ }, // Aruba
405 { 364, CAMERA_ANTIBANDING_60HZ }, // Bahamas
406 { 365, CAMERA_ANTIBANDING_60HZ }, // Anguilla
407 { 366, CAMERA_ANTIBANDING_50HZ }, // Dominica
408 { 368, CAMERA_ANTIBANDING_60HZ }, // Cuba
409 { 370, CAMERA_ANTIBANDING_60HZ }, // Dominican Republic
410 { 372, CAMERA_ANTIBANDING_60HZ }, // Haiti
411 { 401, CAMERA_ANTIBANDING_50HZ }, // Kazakhstan
412 { 402, CAMERA_ANTIBANDING_50HZ }, // Bhutan
413 { 404, CAMERA_ANTIBANDING_50HZ }, // India
414 { 405, CAMERA_ANTIBANDING_50HZ }, // India
415 { 410, CAMERA_ANTIBANDING_50HZ }, // Pakistan
416 { 413, CAMERA_ANTIBANDING_50HZ }, // Sri Lanka
417 { 414, CAMERA_ANTIBANDING_50HZ }, // Myanmar
418 { 415, CAMERA_ANTIBANDING_50HZ }, // Lebanon
419 { 416, CAMERA_ANTIBANDING_50HZ }, // Jordan
420 { 417, CAMERA_ANTIBANDING_50HZ }, // Syria
421 { 418, CAMERA_ANTIBANDING_50HZ }, // Iraq
422 { 419, CAMERA_ANTIBANDING_50HZ }, // Kuwait
423 { 420, CAMERA_ANTIBANDING_60HZ }, // Saudi Arabia
424 { 421, CAMERA_ANTIBANDING_50HZ }, // Yemen
425 { 422, CAMERA_ANTIBANDING_50HZ }, // Oman
426 { 424, CAMERA_ANTIBANDING_50HZ }, // United Arab Emirates
427 { 425, CAMERA_ANTIBANDING_50HZ }, // Israel
428 { 426, CAMERA_ANTIBANDING_50HZ }, // Bahrain
429 { 427, CAMERA_ANTIBANDING_50HZ }, // Qatar
430 { 428, CAMERA_ANTIBANDING_50HZ }, // Mongolia
431 { 429, CAMERA_ANTIBANDING_50HZ }, // Nepal
432 { 430, CAMERA_ANTIBANDING_50HZ }, // United Arab Emirates
433 { 431, CAMERA_ANTIBANDING_50HZ }, // United Arab Emirates
434 { 432, CAMERA_ANTIBANDING_50HZ }, // Iran
435 { 434, CAMERA_ANTIBANDING_50HZ }, // Uzbekistan
436 { 436, CAMERA_ANTIBANDING_50HZ }, // Tajikistan
437 { 437, CAMERA_ANTIBANDING_50HZ }, // Kyrgyz Rep
438 { 438, CAMERA_ANTIBANDING_50HZ }, // Turkmenistan
439 { 440, CAMERA_ANTIBANDING_60HZ }, // Japan
440 { 441, CAMERA_ANTIBANDING_60HZ }, // Japan
441 { 452, CAMERA_ANTIBANDING_50HZ }, // Vietnam
442 { 454, CAMERA_ANTIBANDING_50HZ }, // Hong Kong
443 { 455, CAMERA_ANTIBANDING_50HZ }, // Macao
444 { 456, CAMERA_ANTIBANDING_50HZ }, // Cambodia
445 { 457, CAMERA_ANTIBANDING_50HZ }, // Laos
446 { 460, CAMERA_ANTIBANDING_50HZ }, // China
447 { 466, CAMERA_ANTIBANDING_60HZ }, // Taiwan
448 { 470, CAMERA_ANTIBANDING_50HZ }, // Bangladesh
449 { 472, CAMERA_ANTIBANDING_50HZ }, // Maldives
450 { 502, CAMERA_ANTIBANDING_50HZ }, // Malaysia
451 { 505, CAMERA_ANTIBANDING_50HZ }, // Australia
452 { 510, CAMERA_ANTIBANDING_50HZ }, // Indonesia
453 { 514, CAMERA_ANTIBANDING_50HZ }, // East Timor
454 { 515, CAMERA_ANTIBANDING_60HZ }, // Philippines
455 { 520, CAMERA_ANTIBANDING_50HZ }, // Thailand
456 { 525, CAMERA_ANTIBANDING_50HZ }, // Singapore
457 { 530, CAMERA_ANTIBANDING_50HZ }, // New Zealand
458 { 535, CAMERA_ANTIBANDING_60HZ }, // Guam
459 { 536, CAMERA_ANTIBANDING_50HZ }, // Nauru
460 { 537, CAMERA_ANTIBANDING_50HZ }, // Papua New Guinea
461 { 539, CAMERA_ANTIBANDING_50HZ }, // Tonga
462 { 541, CAMERA_ANTIBANDING_50HZ }, // Vanuatu
463 { 542, CAMERA_ANTIBANDING_50HZ }, // Fiji
464 { 544, CAMERA_ANTIBANDING_60HZ }, // American Samoa
465 { 545, CAMERA_ANTIBANDING_50HZ }, // Kiribati
466 { 546, CAMERA_ANTIBANDING_50HZ }, // New Caledonia
467 { 548, CAMERA_ANTIBANDING_50HZ }, // Cook Islands
468 { 602, CAMERA_ANTIBANDING_50HZ }, // Egypt
469 { 603, CAMERA_ANTIBANDING_50HZ }, // Algeria
470 { 604, CAMERA_ANTIBANDING_50HZ }, // Morocco
471 { 605, CAMERA_ANTIBANDING_50HZ }, // Tunisia
472 { 606, CAMERA_ANTIBANDING_50HZ }, // Libya
473 { 607, CAMERA_ANTIBANDING_50HZ }, // Gambia
474 { 608, CAMERA_ANTIBANDING_50HZ }, // Senegal
475 { 609, CAMERA_ANTIBANDING_50HZ }, // Mauritania
476 { 610, CAMERA_ANTIBANDING_50HZ }, // Mali
477 { 611, CAMERA_ANTIBANDING_50HZ }, // Guinea
478 { 613, CAMERA_ANTIBANDING_50HZ }, // Burkina Faso
479 { 614, CAMERA_ANTIBANDING_50HZ }, // Niger
480 { 616, CAMERA_ANTIBANDING_50HZ }, // Benin
481 { 617, CAMERA_ANTIBANDING_50HZ }, // Mauritius
482 { 618, CAMERA_ANTIBANDING_50HZ }, // Liberia
483 { 619, CAMERA_ANTIBANDING_50HZ }, // Sierra Leone
484 { 620, CAMERA_ANTIBANDING_50HZ }, // Ghana
485 { 621, CAMERA_ANTIBANDING_50HZ }, // Nigeria
486 { 622, CAMERA_ANTIBANDING_50HZ }, // Chad
487 { 623, CAMERA_ANTIBANDING_50HZ }, // Central African Republic
488 { 624, CAMERA_ANTIBANDING_50HZ }, // Cameroon
489 { 625, CAMERA_ANTIBANDING_50HZ }, // Cape Verde
490 { 627, CAMERA_ANTIBANDING_50HZ }, // Equatorial Guinea
491 { 631, CAMERA_ANTIBANDING_50HZ }, // Angola
492 { 633, CAMERA_ANTIBANDING_50HZ }, // Seychelles
493 { 634, CAMERA_ANTIBANDING_50HZ }, // Sudan
494 { 636, CAMERA_ANTIBANDING_50HZ }, // Ethiopia
495 { 637, CAMERA_ANTIBANDING_50HZ }, // Somalia
496 { 638, CAMERA_ANTIBANDING_50HZ }, // Djibouti
497 { 639, CAMERA_ANTIBANDING_50HZ }, // Kenya
498 { 640, CAMERA_ANTIBANDING_50HZ }, // Tanzania
499 { 641, CAMERA_ANTIBANDING_50HZ }, // Uganda
500 { 642, CAMERA_ANTIBANDING_50HZ }, // Burundi
501 { 643, CAMERA_ANTIBANDING_50HZ }, // Mozambique
502 { 645, CAMERA_ANTIBANDING_50HZ }, // Zambia
503 { 646, CAMERA_ANTIBANDING_50HZ }, // Madagascar
504 { 647, CAMERA_ANTIBANDING_50HZ }, // France
505 { 648, CAMERA_ANTIBANDING_50HZ }, // Zimbabwe
506 { 649, CAMERA_ANTIBANDING_50HZ }, // Namibia
507 { 650, CAMERA_ANTIBANDING_50HZ }, // Malawi
508 { 651, CAMERA_ANTIBANDING_50HZ }, // Lesotho
509 { 652, CAMERA_ANTIBANDING_50HZ }, // Botswana
510 { 653, CAMERA_ANTIBANDING_50HZ }, // Swaziland
511 { 654, CAMERA_ANTIBANDING_50HZ }, // Comoros
512 { 655, CAMERA_ANTIBANDING_50HZ }, // South Africa
513 { 657, CAMERA_ANTIBANDING_50HZ }, // Eritrea
514 { 702, CAMERA_ANTIBANDING_60HZ }, // Belize
515 { 704, CAMERA_ANTIBANDING_60HZ }, // Guatemala
516 { 706, CAMERA_ANTIBANDING_60HZ }, // El Salvador
517 { 708, CAMERA_ANTIBANDING_60HZ }, // Honduras
518 { 710, CAMERA_ANTIBANDING_60HZ }, // Nicaragua
519 { 712, CAMERA_ANTIBANDING_60HZ }, // Costa Rica
520 { 714, CAMERA_ANTIBANDING_60HZ }, // Panama
521 { 722, CAMERA_ANTIBANDING_50HZ }, // Argentina
522 { 724, CAMERA_ANTIBANDING_60HZ }, // Brazil
523 { 730, CAMERA_ANTIBANDING_50HZ }, // Chile
524 { 732, CAMERA_ANTIBANDING_60HZ }, // Colombia
525 { 734, CAMERA_ANTIBANDING_60HZ }, // Venezuela
526 { 736, CAMERA_ANTIBANDING_50HZ }, // Bolivia
527 { 738, CAMERA_ANTIBANDING_60HZ }, // Guyana
528 { 740, CAMERA_ANTIBANDING_60HZ }, // Ecuador
529 { 742, CAMERA_ANTIBANDING_50HZ }, // French Guiana
530 { 744, CAMERA_ANTIBANDING_50HZ }, // Paraguay
531 { 746, CAMERA_ANTIBANDING_60HZ }, // Suriname
532 { 748, CAMERA_ANTIBANDING_50HZ }, // Uruguay
533 { 750, CAMERA_ANTIBANDING_50HZ }, // Falkland Islands
534};
535
536#define country_number (sizeof(country_numeric) / sizeof(country_map))
537
538/* Look up pre-sorted antibanding_type table by current MCC. */
539static camera_antibanding_type camera_get_location(void) {
540 char value[PROP_VALUE_MAX];
541 char country_value[PROP_VALUE_MAX];
542 uint32_t country_code, count;
543 memset(value, 0x00, sizeof(value));
544 memset(country_value, 0x00, sizeof(country_value));
545 if (!__system_property_get("gsm.operator.numeric", value)) {
546 return CAMERA_ANTIBANDING_60HZ;
547 }
548 memcpy(country_value, value, 3);
549 country_code = atoi(country_value);
550 LOGD("value:%s, country value:%s, country code:%d\n",
551 value, country_value, country_code);
552 int left = 0;
553 int right = country_number - 1;
554 while (left <= right) {
555 int index = (left + right) >> 1;
556 if (country_numeric[index].country_code == country_code)
557 return country_numeric[index].type;
558 else if (country_numeric[index].country_code > country_code)
559 right = index - 1;
560 else
561 left = index + 1;
562 }
563 return CAMERA_ANTIBANDING_60HZ;
564}
565
566// from camera.h, led_mode_t
567static const str_map flash[] = {
568 { CameraParameters::FLASH_MODE_OFF, LED_MODE_OFF },
569 { CameraParameters::FLASH_MODE_AUTO, LED_MODE_AUTO },
570 { CameraParameters::FLASH_MODE_ON, LED_MODE_ON }
571};
572
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530573// from mm-camera/common/camera.h.
574static const str_map iso[] = {
575 { CameraParameters::ISO_AUTO, CAMERA_ISO_AUTO},
576 { CameraParameters::ISO_HJR, CAMERA_ISO_DEBLUR},
577 { CameraParameters::ISO_100, CAMERA_ISO_100},
578 { CameraParameters::ISO_200, CAMERA_ISO_200},
579 { CameraParameters::ISO_400, CAMERA_ISO_400},
580 { CameraParameters::ISO_800, CAMERA_ISO_800 }
581};
582
583
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800584#define DONT_CARE 0
585static const str_map focus_modes[] = {
Srinivasan Kannan71229622009-12-04 12:05:58 -0800586 { CameraParameters::FOCUS_MODE_AUTO, AF_MODE_AUTO},
587 { CameraParameters::FOCUS_MODE_INFINITY, DONT_CARE },
588 { CameraParameters::FOCUS_MODE_NORMAL, AF_MODE_NORMAL },
589 { CameraParameters::FOCUS_MODE_MACRO, AF_MODE_MACRO }
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800590};
591
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530592static const str_map lensshade[] = {
593 { CameraParameters::LENSSHADE_ENABLE, TRUE },
594 { CameraParameters::LENSSHADE_DISABLE, FALSE }
595};
596
Srinivasan Kannan71229622009-12-04 12:05:58 -0800597struct SensorType {
598 const char *name;
599 int rawPictureWidth;
600 int rawPictureHeight;
601 bool hasAutoFocusSupport;
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800602 int max_supported_snapshot_width;
603 int max_supported_snapshot_height;
Apurva Rajguruffe264a2010-03-09 13:50:53 -0800604 int bitMask;
Srinivasan Kannan71229622009-12-04 12:05:58 -0800605};
606
607static SensorType sensorTypes[] = {
Apurva Rajguruffe264a2010-03-09 13:50:53 -0800608 { "5mp", 2608, 1960, true, 2592, 1944,0x00000fff },
609 { "3mp", 2064, 1544, false, 2048, 1536,0x000007ff },
610 { "2mp", 3200, 1200, false, 1600, 1200,0x000007ff } };
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800611
Srinivasan Kannan71229622009-12-04 12:05:58 -0800612
613static SensorType * sensorType;
614
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800615static const str_map picture_formats[] = {
616 {CameraParameters::PIXEL_FORMAT_JPEG, PICTURE_FORMAT_JPEG},
617 {CameraParameters::PIXEL_FORMAT_RAW, PICTURE_FORMAT_RAW}
618};
619
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800620static bool parameter_string_initialized = false;
621static String8 preview_size_values;
622static String8 picture_size_values;
623static String8 antibanding_values;
624static String8 effect_values;
Apurva Rajguru55562b02009-12-03 12:25:35 -0800625static String8 autoexposure_values;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800626static String8 whitebalance_values;
627static String8 flash_values;
628static String8 focus_mode_values;
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530629static String8 iso_values;
630static String8 lensshade_values;
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800631static String8 picture_format_values;
632
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800633
634static String8 create_sizes_str(const camera_size_type *sizes, int len) {
635 String8 str;
636 char buffer[32];
637
638 if (len > 0) {
639 sprintf(buffer, "%dx%d", sizes[0].width, sizes[0].height);
640 str.append(buffer);
641 }
642 for (int i = 1; i < len; i++) {
643 sprintf(buffer, ",%dx%d", sizes[i].width, sizes[i].height);
644 str.append(buffer);
645 }
646 return str;
647}
648
649static String8 create_values_str(const str_map *values, int len) {
650 String8 str;
651
652 if (len > 0) {
653 str.append(values[0].desc);
654 }
655 for (int i = 1; i < len; i++) {
656 str.append(",");
657 str.append(values[i].desc);
658 }
659 return str;
660}
661
Sravankb4f5f1c2010-01-21 11:06:17 +0530662extern "C" {
663//------------------------------------------------------------------------
664// : 720p busyQ funcitons
665// --------------------------------------------------------------------
666static struct fifo_queue g_busy_frame_queue =
667 {0, 0, 0, PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER};
668};
669/*===========================================================================
670 * FUNCTION cam_frame_wait_video
671 *
672 * DESCRIPTION this function waits a video in the busy queue
673 * ===========================================================================*/
674
675static void cam_frame_wait_video (void)
676{
677 LOGV("cam_frame_wait_video E ");
678 if ((g_busy_frame_queue.num_of_frames) <=0){
679 pthread_cond_wait(&(g_busy_frame_queue.wait), &(g_busy_frame_queue.mut));
680 }
681 LOGV("cam_frame_wait_video X");
682 return;
683}
684
685/*===========================================================================
686 * FUNCTION cam_frame_flush_video
687 *
688 * DESCRIPTION this function deletes all the buffers in busy queue
689 * ===========================================================================*/
690void cam_frame_flush_video (void)
691{
692 LOGV("cam_frame_flush_video: in n = %d\n", g_busy_frame_queue.num_of_frames);
693 pthread_mutex_lock(&(g_busy_frame_queue.mut));
694
695 while (g_busy_frame_queue.front)
696 {
697 //dequeue from the busy queue
698 struct fifo_node *node = dequeue (&g_busy_frame_queue);
699 if(node)
700 free(node);
701
702 LOGV("cam_frame_flush_video: node \n");
703 }
704 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
705 LOGV("cam_frame_flush_video: out n = %d\n", g_busy_frame_queue.num_of_frames);
706 return ;
707}
708/*===========================================================================
709 * FUNCTION cam_frame_get_video
710 *
711 * DESCRIPTION this function returns a video frame from the head
712 * ===========================================================================*/
713static struct msm_frame * cam_frame_get_video()
714{
715 struct msm_frame *p = NULL;
716 LOGV("cam_frame_get_video... in\n");
717 LOGV("cam_frame_get_video... got lock\n");
718 if (g_busy_frame_queue.front)
719 {
720 //dequeue
721 struct fifo_node *node = dequeue (&g_busy_frame_queue);
722 if (node)
723 {
724 p = (struct msm_frame *)node->f;
725 free (node);
726 }
727 LOGV("cam_frame_get_video... out = %x\n", p->buffer);
728 }
729 return p;
730}
731
732/*===========================================================================
733 * FUNCTION cam_frame_post_video
734 *
735 * DESCRIPTION this function add a busy video frame to the busy queue tails
736 * ===========================================================================*/
737static void cam_frame_post_video (struct msm_frame *p)
738{
739 if (!p)
740 {
741 LOGE("post video , buffer is null");
742 return;
743 }
744 LOGV("cam_frame_post_video... in = %x\n", (unsigned int)(p->buffer));
745 pthread_mutex_lock(&(g_busy_frame_queue.mut));
746 LOGV("post_video got lock. q count before enQ %d", g_busy_frame_queue.num_of_frames);
747 //enqueue to busy queue
748 struct fifo_node *node = (struct fifo_node *)malloc (sizeof (struct fifo_node));
749 if (node)
750 {
751 LOGV(" post video , enqueing in busy queue");
752 node->f = p;
753 node->next = NULL;
754 enqueue (&g_busy_frame_queue, node);
755 LOGV("post_video got lock. q count after enQ %d", g_busy_frame_queue.num_of_frames);
756 }
757 else
758 {
759 LOGE("cam_frame_post_video error... out of memory\n");
760 }
761
762 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
763 pthread_cond_signal(&(g_busy_frame_queue.wait));
764
765 LOGV("cam_frame_post_video... out = %x\n", p->buffer);
766
767 return;
768}
769
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -0800770void QualcommCameraHardware::storeTargetType(void) {
771 char mDeviceName[PROPERTY_VALUE_MAX];
772 property_get("ro.product.device",mDeviceName," ");
773 mCurrentTarget = TARGET_MAX;
774 for( int i = 0; i < TARGET_MAX ; i++) {
775 if( !strncmp(mDeviceName, targetList[i].targetStr, 7)) {
776 mCurrentTarget = targetList[i].targetEnum;
777 break;
778 }
779 }
780 LOGV(" Storing the current target type as %d ", mCurrentTarget );
781 return;
782}
783
Sravankb4f5f1c2010-01-21 11:06:17 +0530784//-------------------------------------------------------------------------------------
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800785static Mutex singleton_lock;
786static bool singleton_releasing;
787static Condition singleton_wait;
788
789static void receive_camframe_callback(struct msm_frame *frame);
Sravankb4f5f1c2010-01-21 11:06:17 +0530790static void receive_camframe_video_callback(struct msm_frame *frame); // 720p
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800791static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size);
792static void receive_jpeg_callback(jpeg_event_t status);
793static void receive_shutter_callback(common_crop_t *crop);
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800794static void receive_camframetimeout_callback(void);
Mohan Kandra284966d2010-01-05 13:39:15 -0800795static int fb_fd = -1;
796static int32_t mMaxZoom = 0;
797static bool native_get_maxzoom(int camfd, void *pZm);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800798
Mohan Kandrad9efed92010-01-15 19:08:39 -0800799static int dstOffset = 0;
800
Brian Steuer07704892009-12-18 18:07:33 -0800801static int camerafd;
802pthread_t w_thread;
803
804void *opencamerafd(void *data) {
805 camerafd = open(MSM_CAMERA_CONTROL, O_RDWR);
806 return NULL;
807}
808
Mohan Kandrad9efed92010-01-15 19:08:39 -0800809/* When using MDP zoom, double the preview buffers. The usage of these
810 * buffers is as follows:
811 * 1. As all the buffers comes under a single FD, and at initial registration,
812 * this FD will be passed to surface flinger, surface flinger can have access
813 * to all the buffers when needed.
814 * 2. Only "kPreviewBufferCount" buffers (SrcSet) will be registered with the
815 * camera driver to receive preview frames. The remaining buffers (DstSet),
816 * will be used at HAL and by surface flinger only when crop information
817 * is present in the frame.
818 * 3. When there is no crop information, there will be no call to MDP zoom,
819 * and the buffers in SrcSet will be passed to surface flinger to display.
820 * 4. With crop information present, MDP zoom will be called, and the final
821 * data will be placed in a buffer from DstSet, and this buffer will be given
822 * to surface flinger to display.
823 */
824#define NUM_MORE_BUFS 2
825
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800826QualcommCameraHardware::QualcommCameraHardware()
827 : mParameters(),
828 mCameraRunning(false),
829 mPreviewInitialized(false),
830 mFrameThreadRunning(false),
Mohan Kandra156d0ac2010-01-25 16:59:17 -0800831 mVideoThreadRunning(false),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800832 mSnapshotThreadRunning(false),
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800833 mSnapshotFormat(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800834 mReleasedRecordingFrame(false),
835 mPreviewFrameSize(0),
836 mRawSize(0),
837 mCameraControlFd(-1),
838 mAutoFocusThreadRunning(false),
839 mAutoFocusFd(-1),
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800840 mBrightness(0),
Apurva Rajguruf12d9d22010-04-05 16:47:12 -0700841 mHJR(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800842 mInPreviewCallback(false),
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800843 mUseOverlay(0),
844 mOverlay(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800845 mMsgEnabled(0),
846 mNotifyCallback(0),
847 mDataCallback(0),
848 mDataCallbackTimestamp(0),
Mohan Kandra740cfce2010-01-07 12:58:24 -0800849 mCallbackCookie(0),
850 mDebugFps(0)
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800851{
Brian Steuer07704892009-12-18 18:07:33 -0800852
853 // Start opening camera device in a separate thread/ Since this
854 // initializes the sensor hardware, this can take a long time. So,
855 // start the process here so it will be ready by the time it's
856 // needed.
857 if ((pthread_create(&w_thread, NULL, opencamerafd, NULL)) != 0) {
858 LOGE("Camera open thread creation failed");
859 }
860
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800861 memset(&mDimension, 0, sizeof(mDimension));
862 memset(&mCrop, 0, sizeof(mCrop));
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -0800863 memset(&zoomCropInfo, 0, sizeof(zoom_crop_info));
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -0800864 storeTargetType();
Mohan Kandra740cfce2010-01-07 12:58:24 -0800865 char value[PROPERTY_VALUE_MAX];
866 property_get("persist.debug.sf.showfps", value, "0");
867 mDebugFps = atoi(value);
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -0800868 if( mCurrentTarget == TARGET_MSM7630 )
Sravankb4f5f1c2010-01-21 11:06:17 +0530869 kPreviewBufferCountActual = kPreviewBufferCount;
870 else
871 kPreviewBufferCountActual = kPreviewBufferCount + NUM_MORE_BUFS;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800872 LOGV("constructor EX");
873}
874
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800875
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -0800876void QualcommCameraHardware::filterPreviewSizes(){
877
Apurva Rajguruffe264a2010-03-09 13:50:53 -0800878 unsigned int boardMask = 0;
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -0800879 int prop = 0;
880 for(prop=0;prop<sizeof(boardProperties)/sizeof(board_property);prop++){
881 if(mCurrentTarget == boardProperties[prop].target){
Apurva Rajguruffe264a2010-03-09 13:50:53 -0800882 boardMask = boardProperties[prop].previewSizeMask;
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -0800883 break;
884 }
885 }
886
Apurva Rajguruffe264a2010-03-09 13:50:53 -0800887 int bitMask = boardMask & sensorType->bitMask;
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -0800888 if(bitMask){
889 unsigned int mask = 1<<(PREVIEW_SIZE_COUNT-1);
890 previewSizeCount=0;
891 unsigned int i = 0;
892 while(mask){
893 if(mask&bitMask)
894 supportedPreviewSizes[previewSizeCount++] =
895 preview_sizes[i];
896 i++;
897 mask = mask >> 1;
898 }
899 }
900}
901
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800902//filter Picture sizes based on max width and height
903void QualcommCameraHardware::filterPictureSizes(){
904 int i;
905 for(i=0;i<PICTURE_SIZE_COUNT;i++){
906 if(((picture_sizes[i].width <=
907 sensorType->max_supported_snapshot_width) &&
908 (picture_sizes[i].height <=
909 sensorType->max_supported_snapshot_height))){
910 picture_sizes_ptr = picture_sizes + i;
911 supportedPictureSizesCount = PICTURE_SIZE_COUNT - i ;
912 return ;
913 }
914 }
915}
916
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800917void QualcommCameraHardware::initDefaultParameters()
918{
919 LOGV("initDefaultParameters E");
920
921 // Initialize constant parameter strings. This will happen only once in the
922 // lifetime of the mediaserver process.
923 if (!parameter_string_initialized) {
Srinivasan Kannan71229622009-12-04 12:05:58 -0800924 findSensorType();
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800925 antibanding_values = create_values_str(
926 antibanding, sizeof(antibanding) / sizeof(str_map));
927 effect_values = create_values_str(
928 effects, sizeof(effects) / sizeof(str_map));
Apurva Rajguru55562b02009-12-03 12:25:35 -0800929 autoexposure_values = create_values_str(
930 autoexposure, sizeof(autoexposure) / sizeof(str_map));
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800931 whitebalance_values = create_values_str(
932 whitebalance, sizeof(whitebalance) / sizeof(str_map));
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -0800933
934 //filter preview sizes
935 filterPreviewSizes();
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800936 preview_size_values = create_sizes_str(
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -0800937 supportedPreviewSizes, previewSizeCount);
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800938 //filter picture sizes
939 filterPictureSizes();
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800940 picture_size_values = create_sizes_str(
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800941 picture_sizes_ptr, supportedPictureSizesCount);
942
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800943 flash_values = create_values_str(
944 flash, sizeof(flash) / sizeof(str_map));
Srinivasan Kannan71229622009-12-04 12:05:58 -0800945 if(sensorType->hasAutoFocusSupport){
946 focus_mode_values = create_values_str(
947 focus_modes, sizeof(focus_modes) / sizeof(str_map));
948 }
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530949 iso_values = create_values_str(
950 iso,sizeof(iso)/sizeof(str_map));
951 lensshade_values = create_values_str(
952 lensshade,sizeof(lensshade)/sizeof(str_map));
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800953 picture_format_values = create_values_str(
954 picture_formats, sizeof(picture_formats)/sizeof(str_map));
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800955 parameter_string_initialized = true;
956 }
957
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -0800958 mParameters.setPreviewSize(DEFAULT_PREVIEW_WIDTH, DEFAULT_PREVIEW_HEIGHT);
959 mDimension.display_width = DEFAULT_PREVIEW_WIDTH;
960 mDimension.display_height = DEFAULT_PREVIEW_HEIGHT;
961
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800962 mParameters.setPreviewFrameRate(15);
963 mParameters.setPreviewFormat("yuv420sp"); // informative
964
965 mParameters.setPictureSize(DEFAULT_PICTURE_WIDTH, DEFAULT_PICTURE_HEIGHT);
966 mParameters.setPictureFormat("jpeg"); // informative
967
Mohan Kandra785619a2010-02-01 21:52:42 -0800968 mParameters.set(CameraParameters::KEY_JPEG_QUALITY, "85"); // max quality
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800969 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH,
970 THUMBNAIL_WIDTH_STR); // informative
971 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT,
972 THUMBNAIL_HEIGHT_STR); // informative
Srinivasan Kannan80d878f2009-12-18 15:06:02 -0800973 mDimension.ui_thumbnail_width =
974 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].width;
975 mDimension.ui_thumbnail_height =
976 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800977 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, "90");
978
979 mParameters.set(CameraParameters::KEY_ANTIBANDING,
Mohan Kandra785619a2010-02-01 21:52:42 -0800980 CameraParameters::ANTIBANDING_OFF);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800981 mParameters.set(CameraParameters::KEY_EFFECT,
982 CameraParameters::EFFECT_NONE);
Apurva Rajguru55562b02009-12-03 12:25:35 -0800983 mParameters.set(CameraParameters::KEY_AUTO_EXPOSURE,
984 CameraParameters::AUTO_EXPOSURE_FRAME_AVG);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800985 mParameters.set(CameraParameters::KEY_WHITE_BALANCE,
986 CameraParameters::WHITE_BALANCE_AUTO);
987 mParameters.set(CameraParameters::KEY_FOCUS_MODE,
988 CameraParameters::FOCUS_MODE_AUTO);
Priya Komarlingam044c7b52010-01-22 18:21:23 -0800989 mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS,
990 "yuv420sp");
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800991
992 mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES,
993 preview_size_values.string());
994 mParameters.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES,
995 picture_size_values.string());
996 mParameters.set(CameraParameters::KEY_SUPPORTED_ANTIBANDING,
997 antibanding_values);
998 mParameters.set(CameraParameters::KEY_SUPPORTED_EFFECTS, effect_values);
Apurva Rajguru55562b02009-12-03 12:25:35 -0800999 mParameters.set(CameraParameters::KEY_SUPPORTED_AUTO_EXPOSURE, autoexposure_values);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001000 mParameters.set(CameraParameters::KEY_SUPPORTED_WHITE_BALANCE,
1001 whitebalance_values);
1002 mParameters.set(CameraParameters::KEY_SUPPORTED_FOCUS_MODES,
1003 focus_mode_values);
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001004 mParameters.set(CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS,
1005 picture_format_values);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001006
1007 if (mSensorInfo.flash_enabled) {
1008 mParameters.set(CameraParameters::KEY_FLASH_MODE,
1009 CameraParameters::FLASH_MODE_OFF);
1010 mParameters.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES,
1011 flash_values);
1012 }
1013
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08001014 mParameters.set(CameraParameters::KEY_MAX_SHARPNESS,
1015 CAMERA_MAX_SHARPNESS);
1016 mParameters.set(CameraParameters::KEY_MAX_CONTRAST,
1017 CAMERA_MAX_CONTRAST);
1018 mParameters.set(CameraParameters::KEY_MAX_SATURATION,
1019 CAMERA_MAX_SATURATION);
1020
Apurva Rajguru07185952010-01-22 15:40:07 -08001021 mParameters.set("luma-adaptation", "3");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001022 mParameters.set("zoom-supported", "true");
1023 mParameters.set("max-zoom", MAX_ZOOM_LEVEL);
1024 mParameters.set("zoom", 0);
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001025 mParameters.set(CameraParameters::KEY_PICTURE_FORMAT,
1026 CameraParameters::PIXEL_FORMAT_JPEG);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001027
Kiran Kumar H N595970b2010-01-12 10:41:09 -08001028 mParameters.set(CameraParameters::KEY_SHARPNESS,
1029 CAMERA_DEF_SHARPNESS);
1030 mParameters.set(CameraParameters::KEY_CONTRAST,
1031 CAMERA_DEF_CONTRAST);
1032 mParameters.set(CameraParameters::KEY_SATURATION,
1033 CAMERA_DEF_SATURATION);
1034
Nishant Panditc8c1ee72009-12-03 16:24:02 +05301035 mParameters.set(CameraParameters::KEY_ISO_MODE,
1036 CameraParameters::ISO_AUTO);
1037 mParameters.set(CameraParameters::KEY_LENSSHADE,
1038 CameraParameters::LENSSHADE_ENABLE);
1039 mParameters.set(CameraParameters::KEY_SUPPORTED_ISO_MODES,
1040 iso_values);
1041 mParameters.set(CameraParameters::KEY_SUPPORTED_LENSSHADE_MODES,
1042 lensshade_values);
1043
Priyanka Kharat67cfe532010-03-29 17:28:22 -07001044 if (setParameters(mParameters) != NO_ERROR) {
1045 LOGE("Failed to set default parameters?!");
1046 }
1047
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08001048 mUseOverlay = useOverlay();
1049
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001050 /* Initialize the camframe_timeout_flag*/
1051 Mutex::Autolock l(&mCamframeTimeoutLock);
1052 camframe_timeout_flag = FALSE;
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08001053 mPostViewHeap = NULL;
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001054
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001055 LOGV("initDefaultParameters X");
1056}
1057
Srinivasan Kannan71229622009-12-04 12:05:58 -08001058void QualcommCameraHardware::findSensorType(){
1059 mDimension.picture_width = DEFAULT_PICTURE_WIDTH;
1060 mDimension.picture_height = DEFAULT_PICTURE_HEIGHT;
1061 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
1062 sizeof(cam_ctrl_dimension_t), &mDimension);
1063 if (ret) {
1064 unsigned int i;
1065 for (i = 0; i < sizeof(sensorTypes) / sizeof(SensorType); i++) {
1066 if (sensorTypes[i].rawPictureHeight
1067 == mDimension.raw_picture_height) {
1068 sensorType = sensorTypes + i;
1069 return;
1070 }
1071 }
1072 }
1073 //default to 5 mp
1074 sensorType = sensorTypes;
1075 return;
1076}
1077
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001078#define ROUND_TO_PAGE(x) (((x)+0xfff)&~0xfff)
1079
1080bool QualcommCameraHardware::startCamera()
1081{
1082 LOGV("startCamera E");
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08001083 if( mCurrentTarget == TARGET_MAX ) {
1084 LOGE(" Unable to determine the target type. Camera will not work ");
1085 return false;
1086 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001087#if DLOPEN_LIBMMCAMERA
1088 libmmcamera = ::dlopen("liboemcamera.so", RTLD_NOW);
1089 LOGV("loading liboemcamera at %p", libmmcamera);
1090 if (!libmmcamera) {
1091 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
1092 return false;
1093 }
1094
1095 *(void **)&LINK_cam_frame =
1096 ::dlsym(libmmcamera, "cam_frame");
1097 *(void **)&LINK_camframe_terminate =
1098 ::dlsym(libmmcamera, "camframe_terminate");
1099
1100 *(void **)&LINK_jpeg_encoder_init =
1101 ::dlsym(libmmcamera, "jpeg_encoder_init");
1102
1103 *(void **)&LINK_jpeg_encoder_encode =
1104 ::dlsym(libmmcamera, "jpeg_encoder_encode");
1105
1106 *(void **)&LINK_jpeg_encoder_join =
1107 ::dlsym(libmmcamera, "jpeg_encoder_join");
1108
1109 *(void **)&LINK_mmcamera_camframe_callback =
1110 ::dlsym(libmmcamera, "mmcamera_camframe_callback");
1111
1112 *LINK_mmcamera_camframe_callback = receive_camframe_callback;
1113
1114 *(void **)&LINK_mmcamera_jpegfragment_callback =
1115 ::dlsym(libmmcamera, "mmcamera_jpegfragment_callback");
1116
1117 *LINK_mmcamera_jpegfragment_callback = receive_jpeg_fragment_callback;
1118
1119 *(void **)&LINK_mmcamera_jpeg_callback =
1120 ::dlsym(libmmcamera, "mmcamera_jpeg_callback");
1121
1122 *LINK_mmcamera_jpeg_callback = receive_jpeg_callback;
1123
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001124 *(void **)&LINK_camframe_timeout_callback =
1125 ::dlsym(libmmcamera, "camframe_timeout_callback");
1126
1127 *LINK_camframe_timeout_callback = receive_camframetimeout_callback;
1128
Sravankb4f5f1c2010-01-21 11:06:17 +05301129 // 720 p new recording functions
1130 *(void **)&LINK_cam_frame_flush_free_video = ::dlsym(libmmcamera, "cam_frame_flush_free_video");
1131
1132 *(void **)&LINK_camframe_free_video = ::dlsym(libmmcamera, "cam_frame_add_free_video");
1133
1134 *(void **)&LINK_camframe_video_callback = ::dlsym(libmmcamera, "mmcamera_camframe_videocallback");
1135 *LINK_camframe_video_callback = receive_camframe_video_callback;
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08001136
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001137 *(void **)&LINK_mmcamera_shutter_callback =
1138 ::dlsym(libmmcamera, "mmcamera_shutter_callback");
1139
1140 *LINK_mmcamera_shutter_callback = receive_shutter_callback;
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08001141
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001142 *(void**)&LINK_jpeg_encoder_setMainImageQuality =
1143 ::dlsym(libmmcamera, "jpeg_encoder_setMainImageQuality");
Kiran Kumar H N8861f302010-01-05 12:01:41 -08001144
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001145 *(void**)&LINK_jpeg_encoder_setThumbnailQuality =
1146 ::dlsym(libmmcamera, "jpeg_encoder_setThumbnailQuality");
1147
1148 *(void**)&LINK_jpeg_encoder_setRotation =
1149 ::dlsym(libmmcamera, "jpeg_encoder_setRotation");
1150
Kiran Kumar H N8861f302010-01-05 12:01:41 -08001151/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001152 *(void**)&LINK_jpeg_encoder_setLocation =
1153 ::dlsym(libmmcamera, "jpeg_encoder_setLocation");
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001154*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001155 *(void **)&LINK_cam_conf =
1156 ::dlsym(libmmcamera, "cam_conf");
1157
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001158/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001159 *(void **)&LINK_default_sensor_get_snapshot_sizes =
1160 ::dlsym(libmmcamera, "default_sensor_get_snapshot_sizes");
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001161*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001162 *(void **)&LINK_launch_cam_conf_thread =
1163 ::dlsym(libmmcamera, "launch_cam_conf_thread");
1164
1165 *(void **)&LINK_release_cam_conf_thread =
1166 ::dlsym(libmmcamera, "release_cam_conf_thread");
1167
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001168/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001169 *(void **)&LINK_zoom_crop_upscale =
1170 ::dlsym(libmmcamera, "zoom_crop_upscale");
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001171*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001172
1173#else
1174 mmcamera_camframe_callback = receive_camframe_callback;
1175 mmcamera_jpegfragment_callback = receive_jpeg_fragment_callback;
1176 mmcamera_jpeg_callback = receive_jpeg_callback;
1177 mmcamera_shutter_callback = receive_shutter_callback;
1178#endif // DLOPEN_LIBMMCAMERA
1179
1180 /* The control thread is in libcamera itself. */
Brian Steuer07704892009-12-18 18:07:33 -08001181 if (pthread_join(w_thread, NULL) != 0) {
1182 LOGE("Camera open thread exit failed");
1183 return false;
1184 }
1185 mCameraControlFd = camerafd;
1186
Kiran Kumar H N585bc362010-01-19 13:04:44 -08001187 if (mCameraControlFd < 0) {
1188 LOGE("startCamera X: %s open failed: %s!",
1189 MSM_CAMERA_CONTROL,
1190 strerror(errno));
1191 return false;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001192 }
1193
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08001194 if( mCurrentTarget != TARGET_MSM7630 ){
Mohan Kandra284966d2010-01-05 13:39:15 -08001195 fb_fd = open("/dev/graphics/fb0", O_RDWR);
1196 if (fb_fd < 0) {
1197 LOGE("startCamera: fb0 open failed: %s!", strerror(errno));
1198 return FALSE;
1199 }
1200 }
1201
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001202 /* This will block until the control thread is launched. After that, sensor
1203 * information becomes available.
1204 */
1205
1206 if (LINK_launch_cam_conf_thread()) {
1207 LOGE("failed to launch the camera config thread");
1208 return false;
1209 }
1210
1211 memset(&mSensorInfo, 0, sizeof(mSensorInfo));
1212 if (ioctl(mCameraControlFd,
1213 MSM_CAM_IOCTL_GET_SENSOR_INFO,
1214 &mSensorInfo) < 0)
1215 LOGW("%s: cannot retrieve sensor info!", __FUNCTION__);
1216 else
1217 LOGI("%s: camsensor name %s, flash %d", __FUNCTION__,
1218 mSensorInfo.name, mSensorInfo.flash_enabled);
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001219/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001220 picture_sizes = LINK_default_sensor_get_snapshot_sizes(&PICTURE_SIZE_COUNT);
1221 if (!picture_sizes || !PICTURE_SIZE_COUNT) {
1222 LOGE("startCamera X: could not get snapshot sizes");
1223 return false;
1224 }
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001225*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001226 LOGV("startCamera X");
1227 return true;
1228}
1229
1230status_t QualcommCameraHardware::dump(int fd,
1231 const Vector<String16>& args) const
1232{
1233 const size_t SIZE = 256;
1234 char buffer[SIZE];
1235 String8 result;
1236
1237 // Dump internal primitives.
1238 result.append("QualcommCameraHardware::dump");
1239 snprintf(buffer, 255, "mMsgEnabled (%d)\n", mMsgEnabled);
1240 result.append(buffer);
1241 int width, height;
1242 mParameters.getPreviewSize(&width, &height);
1243 snprintf(buffer, 255, "preview width(%d) x height (%d)\n", width, height);
1244 result.append(buffer);
1245 mParameters.getPictureSize(&width, &height);
1246 snprintf(buffer, 255, "raw width(%d) x height (%d)\n", width, height);
1247 result.append(buffer);
1248 snprintf(buffer, 255,
1249 "preview frame size(%d), raw size (%d), jpeg size (%d) "
1250 "and jpeg max size (%d)\n", mPreviewFrameSize, mRawSize,
1251 mJpegSize, mJpegMaxSize);
1252 result.append(buffer);
1253 write(fd, result.string(), result.size());
1254
1255 // Dump internal objects.
Mohan Kandrad9efed92010-01-15 19:08:39 -08001256 if (mPreviewHeap != 0) {
1257 mPreviewHeap->dump(fd, args);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001258 }
1259 if (mRawHeap != 0) {
1260 mRawHeap->dump(fd, args);
1261 }
1262 if (mJpegHeap != 0) {
1263 mJpegHeap->dump(fd, args);
1264 }
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001265 if(mRawSnapshotAshmemHeap != 0 ){
1266 mRawSnapshotAshmemHeap->dump(fd, args);
1267 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001268 mParameters.dump(fd, args);
1269 return NO_ERROR;
1270}
1271
Mohan Kandra284966d2010-01-05 13:39:15 -08001272static bool native_get_maxzoom(int camfd, void *pZm)
1273{
1274 LOGV("native_get_maxzoom E");
1275
1276 struct msm_ctrl_cmd ctrlCmd;
1277 int32_t *pZoom = (int32_t *)pZm;
1278
1279 ctrlCmd.type = CAMERA_GET_PARM_MAXZOOM;
1280 ctrlCmd.timeout_ms = 5000;
1281 ctrlCmd.length = sizeof(int32_t);
1282 ctrlCmd.value = pZoom;
1283 ctrlCmd.resp_fd = camfd;
1284
1285 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1286 LOGE("native_get_maxzoom: ioctl fd %d error %s",
1287 camfd,
1288 strerror(errno));
1289 return false;
1290 }
Brian Steuerb62adbd2010-02-02 14:47:08 -08001291 LOGD("ctrlCmd.value = %d", *(int32_t *)ctrlCmd.value);
Mohan Kandra284966d2010-01-05 13:39:15 -08001292 memcpy(pZoom, (int32_t *)ctrlCmd.value, sizeof(int32_t));
1293
1294 LOGV("native_get_maxzoom X");
1295 return true;
1296}
1297
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001298static bool native_set_afmode(int camfd, isp3a_af_mode_t af_type)
1299{
1300 int rc;
1301 struct msm_ctrl_cmd ctrlCmd;
1302
1303 ctrlCmd.timeout_ms = 5000;
1304 ctrlCmd.type = CAMERA_SET_PARM_AUTO_FOCUS;
1305 ctrlCmd.length = sizeof(af_type);
1306 ctrlCmd.value = &af_type;
1307 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1308
1309 if ((rc = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0)
1310 LOGE("native_set_afmode: ioctl fd %d error %s\n",
1311 camfd,
1312 strerror(errno));
1313
1314 LOGV("native_set_afmode: ctrlCmd.status == %d\n", ctrlCmd.status);
1315 return rc >= 0 && ctrlCmd.status == CAMERA_EXIT_CB_DONE;
1316}
1317
1318static bool native_cancel_afmode(int camfd, int af_fd)
1319{
1320 int rc;
1321 struct msm_ctrl_cmd ctrlCmd;
1322
1323 ctrlCmd.timeout_ms = 0;
1324 ctrlCmd.type = CAMERA_AUTO_FOCUS_CANCEL;
1325 ctrlCmd.length = 0;
1326 ctrlCmd.value = NULL;
1327 ctrlCmd.resp_fd = -1; // there's no response fd
1328
1329 if ((rc = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND_2, &ctrlCmd)) < 0)
1330 {
1331 LOGE("native_cancel_afmode: ioctl fd %d error %s\n",
1332 camfd,
1333 strerror(errno));
1334 return false;
1335 }
1336
1337 return true;
1338}
1339
1340static bool native_start_preview(int camfd)
1341{
1342 struct msm_ctrl_cmd ctrlCmd;
1343
1344 ctrlCmd.timeout_ms = 5000;
1345 ctrlCmd.type = CAMERA_START_PREVIEW;
1346 ctrlCmd.length = 0;
1347 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1348
1349 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1350 LOGE("native_start_preview: MSM_CAM_IOCTL_CTRL_COMMAND fd %d error %s",
1351 camfd,
1352 strerror(errno));
1353 return false;
1354 }
1355
1356 return true;
1357}
1358
1359static bool native_get_picture (int camfd, common_crop_t *crop)
1360{
1361 struct msm_ctrl_cmd ctrlCmd;
1362
1363 ctrlCmd.timeout_ms = 5000;
1364 ctrlCmd.length = sizeof(common_crop_t);
1365 ctrlCmd.value = crop;
1366
1367 if(ioctl(camfd, MSM_CAM_IOCTL_GET_PICTURE, &ctrlCmd) < 0) {
1368 LOGE("native_get_picture: MSM_CAM_IOCTL_GET_PICTURE fd %d error %s",
1369 camfd,
1370 strerror(errno));
1371 return false;
1372 }
1373
1374 LOGV("crop: in1_w %d", crop->in1_w);
1375 LOGV("crop: in1_h %d", crop->in1_h);
1376 LOGV("crop: out1_w %d", crop->out1_w);
1377 LOGV("crop: out1_h %d", crop->out1_h);
1378
1379 LOGV("crop: in2_w %d", crop->in2_w);
1380 LOGV("crop: in2_h %d", crop->in2_h);
1381 LOGV("crop: out2_w %d", crop->out2_w);
1382 LOGV("crop: out2_h %d", crop->out2_h);
1383
1384 LOGV("crop: update %d", crop->update_flag);
1385
1386 return true;
1387}
1388
1389static bool native_stop_preview(int camfd)
1390{
1391 struct msm_ctrl_cmd ctrlCmd;
1392 ctrlCmd.timeout_ms = 5000;
1393 ctrlCmd.type = CAMERA_STOP_PREVIEW;
1394 ctrlCmd.length = 0;
1395 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1396
1397 if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1398 LOGE("native_stop_preview: ioctl fd %d error %s",
1399 camfd,
1400 strerror(errno));
1401 return false;
1402 }
1403
1404 return true;
1405}
1406
1407static bool native_prepare_snapshot(int camfd)
1408{
1409 int ioctlRetVal = true;
1410 struct msm_ctrl_cmd ctrlCmd;
1411
1412 ctrlCmd.timeout_ms = 1000;
1413 ctrlCmd.type = CAMERA_PREPARE_SNAPSHOT;
1414 ctrlCmd.length = 0;
1415 ctrlCmd.value = NULL;
1416 ctrlCmd.resp_fd = camfd;
1417
1418 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1419 LOGE("native_prepare_snapshot: ioctl fd %d error %s",
1420 camfd,
1421 strerror(errno));
1422 return false;
1423 }
1424 return true;
1425}
1426
1427static bool native_start_snapshot(int camfd)
1428{
1429 struct msm_ctrl_cmd ctrlCmd;
1430
1431 ctrlCmd.timeout_ms = 5000;
1432 ctrlCmd.type = CAMERA_START_SNAPSHOT;
1433 ctrlCmd.length = 0;
1434 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1435
1436 if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1437 LOGE("native_start_snapshot: ioctl fd %d error %s",
1438 camfd,
1439 strerror(errno));
1440 return false;
1441 }
1442
1443 return true;
1444}
1445
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001446static bool native_start_raw_snapshot(int camfd)
1447{
1448 int ret;
1449 struct msm_ctrl_cmd ctrlCmd;
1450
1451 ctrlCmd.timeout_ms = 1000;
1452 ctrlCmd.type = CAMERA_START_RAW_SNAPSHOT;
1453 ctrlCmd.length = 0;
1454 ctrlCmd.value = NULL;
1455 ctrlCmd.resp_fd = camfd;
1456
1457 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1458 LOGE("native_start_raw_snapshot: ioctl failed. ioctl return value "\
1459 "is %d \n", ret);
1460 return false;
1461 }
1462 return true;
1463}
1464
1465
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001466static bool native_stop_snapshot (int camfd)
1467{
1468 struct msm_ctrl_cmd ctrlCmd;
1469
1470 ctrlCmd.timeout_ms = 0;
1471 ctrlCmd.type = CAMERA_STOP_SNAPSHOT;
1472 ctrlCmd.length = 0;
1473 ctrlCmd.resp_fd = -1;
1474
1475 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND_2, &ctrlCmd) < 0) {
1476 LOGE("native_stop_snapshot: ioctl fd %d error %s",
1477 camfd,
1478 strerror(errno));
1479 return false;
1480 }
1481
1482 return true;
1483}
Sravankb4f5f1c2010-01-21 11:06:17 +05301484/*===========================================================================
1485 * FUNCTION - native_start_recording -
1486 *
1487 * DESCRIPTION:
1488 *==========================================================================*/
1489static bool native_start_recording(int camfd)
1490{
1491 int ret;
1492 struct msm_ctrl_cmd ctrlCmd;
1493
1494 ctrlCmd.timeout_ms = 1000;
1495 ctrlCmd.type = CAMERA_START_RECORDING;
1496 ctrlCmd.length = 0;
1497 ctrlCmd.value = NULL;
1498 ctrlCmd.resp_fd = camfd;
1499
1500 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1501 LOGE("native_start_recording: ioctl failed. ioctl return value "\
1502 "is %d \n", ret);
1503 return false;
1504 }
Mohan Kandraf1ebf982010-02-02 15:25:43 -08001505 LOGV("native_start_recording: ioctl good. ioctl return value is %d \n",ret);
Sravankb4f5f1c2010-01-21 11:06:17 +05301506
1507 /* TODO: Check status of postprocessing if there is any,
1508 * PP status should be in ctrlCmd */
1509
1510 return true;
1511}
1512
1513/*===========================================================================
1514 * FUNCTION - native_stop_recording -
1515 *
1516 * DESCRIPTION:
1517 *==========================================================================*/
1518static bool native_stop_recording(int camfd)
1519{
1520 int ret;
1521 struct msm_ctrl_cmd ctrlCmd;
Kiran Kumar H Nb49af212010-02-17 15:12:17 -08001522 LOGV("in native_stop_recording ");
Sravankb4f5f1c2010-01-21 11:06:17 +05301523 ctrlCmd.timeout_ms = 1000;
1524 ctrlCmd.type = CAMERA_STOP_RECORDING;
1525 ctrlCmd.length = 0;
1526 ctrlCmd.value = NULL;
1527 ctrlCmd.resp_fd = camfd;
1528
1529 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1530 LOGE("native_stop_video: ioctl failed. ioctl return value is %d \n",
1531 ret);
1532 return false;
1533 }
1534 LOGV("in native_stop_recording returned %d", ret);
1535 return true;
1536}
1537/*===========================================================================
1538 * FUNCTION - native_start_video -
1539 *
1540 * DESCRIPTION:
1541 *==========================================================================*/
1542static bool native_start_video(int camfd)
1543{
1544 int ret;
1545 struct msm_ctrl_cmd ctrlCmd;
1546
1547 ctrlCmd.timeout_ms = 1000;
1548 ctrlCmd.type = CAMERA_START_VIDEO;
1549 ctrlCmd.length = 0;
1550 ctrlCmd.value = NULL;
1551 ctrlCmd.resp_fd = camfd;
1552
1553 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1554 LOGE("native_start_video: ioctl failed. ioctl return value is %d \n",
1555 ret);
1556 return false;
1557 }
1558
1559 /* TODO: Check status of postprocessing if there is any,
1560 * PP status should be in ctrlCmd */
1561
1562 return true;
1563}
1564
1565/*===========================================================================
1566 * FUNCTION - native_stop_video -
1567 *
1568 * DESCRIPTION:
1569 *==========================================================================*/
1570static bool native_stop_video(int camfd)
1571{
1572 int ret;
1573 struct msm_ctrl_cmd ctrlCmd;
1574
1575 ctrlCmd.timeout_ms = 1000;
1576 ctrlCmd.type = CAMERA_STOP_VIDEO;
1577 ctrlCmd.length = 0;
1578 ctrlCmd.value = NULL;
1579 ctrlCmd.resp_fd = camfd;
1580
1581 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1582 LOGE("native_stop_video: ioctl failed. ioctl return value is %d \n",
1583 ret);
1584 return false;
1585 }
1586
1587 return true;
1588}
1589/*==========================================================================*/
1590
1591static cam_frame_start_parms frame_parms;
1592static int recordingState = 0;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001593
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001594static rat_t latitude[3];
1595static rat_t longitude[3];
1596static char lonref[2];
1597static char latref[2];
1598static char dateTime[20];
1599static rat_t altitude;
1600
1601static void addExifTag(exif_tag_id_t tagid, exif_tag_type_t type,
1602 uint32_t count, uint8_t copy, void *data) {
1603
1604 if(exif_table_numEntries == MAX_EXIF_TABLE_ENTRIES) {
1605 LOGE("Number of entries exceeded limit");
1606 return;
1607 }
1608
1609 int index = exif_table_numEntries;
1610 exif_data[index].tag_id = tagid;
1611 exif_data[index].tag_entry.type = type;
1612 exif_data[index].tag_entry.count = count;
1613 exif_data[index].tag_entry.copy = copy;
1614 if((type == EXIF_RATIONAL) && (count > 1))
1615 exif_data[index].tag_entry.data._rats = (rat_t *)data;
1616 if((type == EXIF_RATIONAL) && (count == 1))
1617 exif_data[index].tag_entry.data._rat = *(rat_t *)data;
1618 else if(type == EXIF_ASCII)
1619 exif_data[index].tag_entry.data._ascii = (char *)data;
1620 else if(type == EXIF_BYTE)
1621 exif_data[index].tag_entry.data._byte = *(uint8_t *)data;
1622
1623 // Increase number of entries
1624 exif_table_numEntries++;
1625}
1626
1627static void parseLatLong(const char *latlonString, int *pDegrees,
1628 int *pMinutes, int *pSeconds ) {
1629
1630 double value = atof(latlonString);
1631 value = fabs(value);
1632 int degrees = (int) value;
1633
1634 double remainder = value - degrees;
1635 int minutes = (int) (remainder * 60);
1636 int seconds = (int) (((remainder * 60) - minutes) * 60 * 1000);
1637
1638 *pDegrees = degrees;
1639 *pMinutes = minutes;
1640 *pSeconds = seconds;
1641}
1642
1643static void setLatLon(exif_tag_id_t tag, const char *latlonString) {
1644
1645 int degrees, minutes, seconds;
1646
1647 parseLatLong(latlonString, &degrees, &minutes, &seconds);
1648
1649 rat_t value[3] = { {degrees, 1},
1650 {minutes, 1},
1651 {seconds, 1000} };
1652
1653 if(tag == EXIFTAGID_GPS_LATITUDE) {
1654 memcpy(latitude, value, sizeof(latitude));
1655 addExifTag(EXIFTAGID_GPS_LATITUDE, EXIF_RATIONAL, 3,
1656 1, (void *)latitude);
1657 } else {
1658 memcpy(longitude, value, sizeof(longitude));
1659 addExifTag(EXIFTAGID_GPS_LONGITUDE, EXIF_RATIONAL, 3,
1660 1, (void *)longitude);
1661 }
1662}
1663
1664void QualcommCameraHardware::setGpsParameters() {
1665 const char *str = NULL;
1666
1667 //Set Latitude
1668 str = mParameters.get(CameraParameters::KEY_GPS_LATITUDE);
1669 if(str != NULL) {
1670 setLatLon(EXIFTAGID_GPS_LATITUDE, str);
1671 //set Latitude Ref
1672 str = NULL;
1673 str = mParameters.get(CameraParameters::KEY_GPS_LATITUDE_REF);
1674 if(str != NULL) {
1675 strncpy(latref, str, 1);
1676 latref[1] = '\0';
1677 addExifTag(EXIFTAGID_GPS_LATITUDE_REF, EXIF_ASCII, 2,
1678 1, (void *)latref);
1679 }
1680 }
1681
1682 //set Longitude
1683 str = NULL;
1684 str = mParameters.get(CameraParameters::KEY_GPS_LONGITUDE);
1685 if(str != NULL) {
1686 setLatLon(EXIFTAGID_GPS_LONGITUDE, str);
1687 //set Longitude Ref
1688 str = NULL;
1689 str = mParameters.get(CameraParameters::KEY_GPS_LONGITUDE_REF);
1690 if(str != NULL) {
1691 strncpy(lonref, str, 1);
1692 lonref[1] = '\0';
1693 addExifTag(EXIFTAGID_GPS_LONGITUDE_REF, EXIF_ASCII, 2,
1694 1, (void *)lonref);
1695 }
1696 }
1697
1698 //set Altitude
1699 str = NULL;
1700 str = mParameters.get(CameraParameters::KEY_GPS_ALTITUDE);
1701 if(str != NULL) {
1702 int value = atoi(str);
1703 rat_t alt_value = {value, 1000};
1704 memcpy(&altitude, &alt_value, sizeof(altitude));
1705 addExifTag(EXIFTAGID_GPS_ALTITUDE, EXIF_RATIONAL, 1,
1706 1, (void *)&altitude);
1707 //set AltitudeRef
1708 int ref = mParameters.getInt(CameraParameters::KEY_GPS_ALTITUDE_REF);
1709 if( !(ref < 0 || ref > 1) )
1710 addExifTag(EXIFTAGID_GPS_ALTITUDE_REF, EXIF_BYTE, 1,
1711 1, (void *)&ref);
1712 }
1713
1714
1715}
1716
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001717bool QualcommCameraHardware::native_jpeg_encode(void)
1718{
1719 int jpeg_quality = mParameters.getInt("jpeg-quality");
1720 if (jpeg_quality >= 0) {
1721 LOGV("native_jpeg_encode, current jpeg main img quality =%d",
1722 jpeg_quality);
1723 if(!LINK_jpeg_encoder_setMainImageQuality(jpeg_quality)) {
1724 LOGE("native_jpeg_encode set jpeg-quality failed");
1725 return false;
1726 }
1727 }
1728
1729 int thumbnail_quality = mParameters.getInt("jpeg-thumbnail-quality");
1730 if (thumbnail_quality >= 0) {
1731 LOGV("native_jpeg_encode, current jpeg thumbnail quality =%d",
1732 thumbnail_quality);
1733 if(!LINK_jpeg_encoder_setThumbnailQuality(thumbnail_quality)) {
1734 LOGE("native_jpeg_encode set thumbnail-quality failed");
1735 return false;
1736 }
1737 }
1738
1739 int rotation = mParameters.getInt("rotation");
1740 if (rotation >= 0) {
1741 LOGV("native_jpeg_encode, rotation = %d", rotation);
1742 if(!LINK_jpeg_encoder_setRotation(rotation)) {
1743 LOGE("native_jpeg_encode set rotation failed");
1744 return false;
1745 }
1746 }
1747
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001748// jpeg_set_location();
1749 if(mParameters.getInt(CameraParameters::KEY_GPS_STATUS) == 1) {
1750 setGpsParameters();
1751 }
1752 //set TimeStamp
1753 const char *str = mParameters.get(CameraParameters::KEY_EXIF_DATETIME);
1754 if(str != NULL) {
1755 strncpy(dateTime, str, 19);
1756 dateTime[19] = '\0';
1757 addExifTag(EXIFTAGID_EXIF_DATE_TIME_ORIGINAL, EXIF_ASCII,
1758 20, 1, (void *)dateTime);
1759 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001760
1761 if (!LINK_jpeg_encoder_encode(&mDimension,
1762 (uint8_t *)mThumbnailHeap->mHeap->base(),
1763 mThumbnailHeap->mHeap->getHeapID(),
1764 (uint8_t *)mRawHeap->mHeap->base(),
1765 mRawHeap->mHeap->getHeapID(),
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001766 &mCrop, exif_data, exif_table_numEntries)) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001767 LOGE("native_jpeg_encode: jpeg_encoder_encode failed.");
1768 return false;
1769 }
1770 return true;
1771}
1772
1773bool QualcommCameraHardware::native_set_parm(
1774 cam_ctrl_type type, uint16_t length, void *value)
1775{
1776 struct msm_ctrl_cmd ctrlCmd;
1777
1778 ctrlCmd.timeout_ms = 5000;
1779 ctrlCmd.type = (uint16_t)type;
1780 ctrlCmd.length = length;
1781 // FIXME: this will be put in by the kernel
1782 ctrlCmd.resp_fd = mCameraControlFd;
1783 ctrlCmd.value = value;
1784
1785 LOGV("%s: fd %d, type %d, length %d", __FUNCTION__,
1786 mCameraControlFd, type, length);
1787 if (ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0 ||
1788 ctrlCmd.status != CAM_CTRL_SUCCESS) {
1789 LOGE("%s: error (%s): fd %d, type %d, length %d, status %d",
1790 __FUNCTION__, strerror(errno),
1791 mCameraControlFd, type, length, ctrlCmd.status);
1792 return false;
1793 }
1794 return true;
1795}
1796
1797void QualcommCameraHardware::jpeg_set_location()
1798{
1799 bool encode_location = true;
1800 camera_position_type pt;
1801
1802#define PARSE_LOCATION(what,type,fmt,desc) do { \
1803 pt.what = 0; \
1804 const char *what##_str = mParameters.get("gps-"#what); \
1805 LOGV("GPS PARM %s --> [%s]", "gps-"#what, what##_str); \
1806 if (what##_str) { \
1807 type what = 0; \
1808 if (sscanf(what##_str, fmt, &what) == 1) \
1809 pt.what = what; \
1810 else { \
1811 LOGE("GPS " #what " %s could not" \
1812 " be parsed as a " #desc, what##_str); \
1813 encode_location = false; \
1814 } \
1815 } \
1816 else { \
1817 LOGV("GPS " #what " not specified: " \
1818 "defaulting to zero in EXIF header."); \
1819 encode_location = false; \
1820 } \
1821 } while(0)
1822
1823 PARSE_LOCATION(timestamp, long, "%ld", "long");
1824 if (!pt.timestamp) pt.timestamp = time(NULL);
1825 PARSE_LOCATION(altitude, short, "%hd", "short");
1826 PARSE_LOCATION(latitude, double, "%lf", "double float");
1827 PARSE_LOCATION(longitude, double, "%lf", "double float");
1828
1829#undef PARSE_LOCATION
1830
1831 if (encode_location) {
1832 LOGD("setting image location ALT %d LAT %lf LON %lf",
1833 pt.altitude, pt.latitude, pt.longitude);
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001834/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001835 if (!LINK_jpeg_encoder_setLocation(&pt)) {
1836 LOGE("jpeg_set_location: LINK_jpeg_encoder_setLocation failed.");
1837 }
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001838*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001839 }
1840 else LOGV("not setting image location");
1841}
1842
1843void QualcommCameraHardware::runFrameThread(void *data)
1844{
1845 LOGV("runFrameThread E");
1846
1847 int cnt;
1848
1849#if DLOPEN_LIBMMCAMERA
1850 // We need to maintain a reference to libqcamera.so for the duration of the
1851 // frame thread, because we do not know when it will exit relative to the
1852 // lifetime of this object. We do not want to dlclose() libqcamera while
1853 // LINK_cam_frame is still running.
1854 void *libhandle = ::dlopen("liboemcamera.so", RTLD_NOW);
1855 LOGV("FRAME: loading libqcamera at %p", libhandle);
1856 if (!libhandle) {
1857 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
1858 }
1859 if (libhandle)
1860#endif
1861 {
1862 LINK_cam_frame(data);
1863 }
1864
Mohan Kandrad9efed92010-01-15 19:08:39 -08001865 mPreviewHeap.clear();
Mohan Kandraf1ebf982010-02-02 15:25:43 -08001866 if(( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250))
Sravankb4f5f1c2010-01-21 11:06:17 +05301867 mRecordHeap.clear();
1868
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001869#if DLOPEN_LIBMMCAMERA
1870 if (libhandle) {
1871 ::dlclose(libhandle);
1872 LOGV("FRAME: dlclose(libqcamera)");
1873 }
1874#endif
1875
1876 mFrameThreadWaitLock.lock();
1877 mFrameThreadRunning = false;
1878 mFrameThreadWait.signal();
1879 mFrameThreadWaitLock.unlock();
1880
1881 LOGV("runFrameThread X");
1882}
1883
Sravankb4f5f1c2010-01-21 11:06:17 +05301884void QualcommCameraHardware::runVideoThread(void *data)
1885{
1886 LOGD("runVideoThread E");
1887 msm_frame* vframe = NULL;
1888
1889 while(true) {
1890 pthread_mutex_lock(&(g_busy_frame_queue.mut));
1891
Srinivasan Kannanfc3915c2010-03-18 10:54:40 -07001892 // Exit the thread , in case of stop recording..
1893 mVideoThreadWaitLock.lock();
1894 if(mVideoThreadExit){
1895 LOGV("Exiting video thread..");
1896 mVideoThreadWaitLock.unlock();
1897 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
1898 break;
1899 }
1900 mVideoThreadWaitLock.unlock();
1901
Kiran Kumar H Nb49af212010-02-17 15:12:17 -08001902 LOGV("in video_thread : wait for video frame ");
Sravankb4f5f1c2010-01-21 11:06:17 +05301903 // check if any frames are available in busyQ and give callback to
1904 // services/video encoder
1905 cam_frame_wait_video();
1906 LOGV("video_thread, wait over..");
1907
1908 // Exit the thread , in case of stop recording..
1909 mVideoThreadWaitLock.lock();
1910 if(mVideoThreadExit){
Kiran Kumar H Nb49af212010-02-17 15:12:17 -08001911 LOGV("Exiting video thread..");
Sravankb4f5f1c2010-01-21 11:06:17 +05301912 mVideoThreadWaitLock.unlock();
1913 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
1914 break;
1915 }
1916 mVideoThreadWaitLock.unlock();
1917
1918 // Get the video frame to be encoded
1919 vframe = cam_frame_get_video ();
Apurva Rajgurud9b0b302010-02-19 11:22:56 -08001920 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
Sravankb4f5f1c2010-01-21 11:06:17 +05301921 LOGV("in video_thread : got video frame ");
1922
Mohan Kandrabad0eaa2010-02-04 15:11:54 -08001923 if (UNLIKELY(mDebugFps)) {
1924 debugShowVideoFPS();
1925 }
1926
Sravankb4f5f1c2010-01-21 11:06:17 +05301927 if(vframe != NULL) {
1928 // Find the offset within the heap of the current buffer.
1929 LOGV("Got video frame : buffer %d base %d ", vframe->buffer, mRecordHeap->mHeap->base());
1930 ssize_t offset =
1931 (ssize_t)vframe->buffer - (ssize_t)mRecordHeap->mHeap->base();
1932 LOGV("offset = %d , alignsize = %d , offset later = %d", offset, mRecordHeap->mAlignedBufferSize, (offset / mRecordHeap->mAlignedBufferSize));
1933
1934 offset /= mRecordHeap->mAlignedBufferSize;
1935
1936 // dump frames for test purpose
1937#ifdef DUMP_VIDEO_FRAMES
1938 static int frameCnt = 0;
1939 if (frameCnt >= 11 && frameCnt <= 13 ) {
1940 char buf[128];
1941 sprintf(buf, "/data/%d_v.yuv", frameCnt);
1942 int file_fd = open(buf, O_RDWR | O_CREAT, 0777);
1943 LOGV("dumping video frame %d", frameCnt);
1944 if (file_fd < 0) {
1945 LOGE("cannot open file\n");
1946 }
1947 else
1948 {
1949 write(file_fd, (const void *)vframe->buffer,
1950 vframe->cbcr_off * 3 / 2);
1951 }
1952 close(file_fd);
1953 }
1954 frameCnt++;
1955#endif
1956 // Enable IF block to give frames to encoder , ELSE block for just simulation
1957#if 1
1958 LOGV("in video_thread : got video frame, before if check giving frame to services/encoder");
1959 mCallbackLock.lock();
1960 int msgEnabled = mMsgEnabled;
1961 data_callback_timestamp rcb = mDataCallbackTimestamp;
1962 void *rdata = mCallbackCookie;
1963 mCallbackLock.unlock();
1964
1965 if(rcb != NULL && (msgEnabled & CAMERA_MSG_VIDEO_FRAME) ) {
1966 LOGV("in video_thread : got video frame, giving frame to services/encoder");
1967 rcb(systemTime(), CAMERA_MSG_VIDEO_FRAME, mRecordHeap->mBuffers[offset], rdata);
Sravankb4f5f1c2010-01-21 11:06:17 +05301968 }
1969#else
1970 // 720p output2 : simulate release frame here:
1971 LOGE("in video_thread simulation , releasing the video frame");
1972 LINK_camframe_free_video(vframe);
1973#endif
1974
1975 } else LOGE("in video_thread get frame returned null");
1976
Sravankb4f5f1c2010-01-21 11:06:17 +05301977
1978 } // end of while loop
Mohan Kandra156d0ac2010-01-25 16:59:17 -08001979
1980 mVideoThreadWaitLock.lock();
1981 mVideoThreadRunning = false;
1982 mVideoThreadWait.signal();
1983 mVideoThreadWaitLock.unlock();
1984
Sravankb4f5f1c2010-01-21 11:06:17 +05301985 LOGV("runVideoThread X");
1986}
1987
1988void *video_thread(void *user)
1989{
1990 LOGV("video_thread E");
1991 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
1992 if (obj != 0) {
1993 obj->runVideoThread(user);
1994 }
1995 else LOGE("not starting video thread: the object went away!");
1996 LOGV("video_thread X");
1997 return NULL;
1998}
1999
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002000void *frame_thread(void *user)
2001{
2002 LOGD("frame_thread E");
2003 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
2004 if (obj != 0) {
2005 obj->runFrameThread(user);
2006 }
2007 else LOGW("not starting frame thread: the object went away!");
2008 LOGD("frame_thread X");
2009 return NULL;
2010}
2011
2012bool QualcommCameraHardware::initPreview()
2013{
2014 // See comments in deinitPreview() for why we have to wait for the frame
2015 // thread here, and why we can't use pthread_join().
Sravankb4f5f1c2010-01-21 11:06:17 +05302016 int videoWidth, videoHeight;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002017 mParameters.getPreviewSize(&previewWidth, &previewHeight);
Sravankb4f5f1c2010-01-21 11:06:17 +05302018
2019 videoWidth = previewWidth; // temporary , should be configurable later
2020 videoHeight = previewHeight;
2021 LOGV("initPreview E: preview size=%dx%d videosize = %d x %d", previewWidth, previewHeight, videoWidth, videoHeight );
2022
Mohan Kandraf1ebf982010-02-02 15:25:43 -08002023 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05302024 mDimension.video_width = videoWidth;
Kiran Kumar H N7ac84e32010-02-01 10:58:47 -08002025 mDimension.video_width = CEILING16(mDimension.video_width);
Sravankb4f5f1c2010-01-21 11:06:17 +05302026 mDimension.video_height = videoHeight;
Sravank64461e82010-02-25 15:10:09 +05302027 // for 720p , preview can be 768X432
2028 previewWidth = mDimension.display_width;
2029 previewHeight= mDimension.display_height;
Sravankb4f5f1c2010-01-21 11:06:17 +05302030 LOGV("initPreview : preview size=%dx%d videosize = %d x %d", previewWidth, previewHeight, mDimension.video_width, mDimension.video_height );
2031 }
2032
2033
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002034 mFrameThreadWaitLock.lock();
2035 while (mFrameThreadRunning) {
2036 LOGV("initPreview: waiting for old frame thread to complete.");
2037 mFrameThreadWait.wait(mFrameThreadWaitLock);
2038 LOGV("initPreview: old frame thread completed.");
2039 }
2040 mFrameThreadWaitLock.unlock();
2041
2042 mSnapshotThreadWaitLock.lock();
2043 while (mSnapshotThreadRunning) {
2044 LOGV("initPreview: waiting for old snapshot thread to complete.");
2045 mSnapshotThreadWait.wait(mSnapshotThreadWaitLock);
2046 LOGV("initPreview: old snapshot thread completed.");
2047 }
2048 mSnapshotThreadWaitLock.unlock();
2049
2050 int cnt = 0;
2051 mPreviewFrameSize = previewWidth * previewHeight * 3/2;
Mohan Kandrad9efed92010-01-15 19:08:39 -08002052 dstOffset = 0;
2053 mPreviewHeap = new PmemPool("/dev/pmem_adsp",
Mohan Kandra284966d2010-01-05 13:39:15 -08002054 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
2055 mCameraControlFd,
Sravankb4f5f1c2010-01-21 11:06:17 +05302056 MSM_PMEM_PREVIEW, //MSM_PMEM_OUTPUT2,
Mohan Kandra284966d2010-01-05 13:39:15 -08002057 mPreviewFrameSize,
Mohan Kandrad9efed92010-01-15 19:08:39 -08002058 kPreviewBufferCountActual,
Mohan Kandra284966d2010-01-05 13:39:15 -08002059 mPreviewFrameSize,
Mohan Kandrad9efed92010-01-15 19:08:39 -08002060 "preview");
Mohan Kandra284966d2010-01-05 13:39:15 -08002061
Mohan Kandrad9efed92010-01-15 19:08:39 -08002062 if (!mPreviewHeap->initialized()) {
2063 mPreviewHeap.clear();
Mohan Kandra284966d2010-01-05 13:39:15 -08002064 LOGE("initPreview X: could not initialize Camera preview heap.");
2065 return false;
2066 }
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002067 if( mCurrentTarget == TARGET_MSM7630 ) {
Srinivasan Kannan613301c2010-02-10 17:08:53 -08002068 mPostViewHeap.clear();
Kiran Kumar H N595970b2010-01-12 10:41:09 -08002069 if(mPostViewHeap == NULL) {
2070 LOGV(" Allocating Postview heap ");
2071 /* mPostViewHeap should be declared only for 7630 target */
2072 mPostViewHeap =
2073 new PmemPool("/dev/pmem_adsp",
2074 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
2075 mCameraControlFd,
Sravankb4f5f1c2010-01-21 11:06:17 +05302076 MSM_PMEM_PREVIEW, //MSM_PMEM_OUTPUT2,
Kiran Kumar H N595970b2010-01-12 10:41:09 -08002077 mPreviewFrameSize,
2078 1,
2079 mPreviewFrameSize,
2080 "postview");
Mohan Kandra284966d2010-01-05 13:39:15 -08002081
Kiran Kumar H N595970b2010-01-12 10:41:09 -08002082 if (!mPostViewHeap->initialized()) {
2083 mPostViewHeap.clear();
2084 LOGE(" Failed to initialize Postview Heap");
2085 return false;
2086 }
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002087 }
Mohan Kandraf1ebf982010-02-02 15:25:43 -08002088 }
2089
2090 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250) ) {
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002091
2092 // Allocate video buffers after allocating preview buffers.
Sravankb4f5f1c2010-01-21 11:06:17 +05302093 initRecord();
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002094 }
Sravankb4f5f1c2010-01-21 11:06:17 +05302095
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002096 // mDimension will be filled with thumbnail_width, thumbnail_height,
2097 // orig_picture_dx, and orig_picture_dy after this function call. We need to
2098 // keep it for jpeg_encoder_encode.
2099 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
2100 sizeof(cam_ctrl_dimension_t), &mDimension);
2101
2102 if (ret) {
2103 for (cnt = 0; cnt < kPreviewBufferCount; cnt++) {
Mohan Kandrad9efed92010-01-15 19:08:39 -08002104 frames[cnt].fd = mPreviewHeap->mHeap->getHeapID();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002105 frames[cnt].buffer =
Mohan Kandrad9efed92010-01-15 19:08:39 -08002106 (uint32_t)mPreviewHeap->mHeap->base() + mPreviewHeap->mAlignedBufferSize * cnt;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002107 frames[cnt].y_off = 0;
2108 frames[cnt].cbcr_off = previewWidth * previewHeight;
Sravankb4f5f1c2010-01-21 11:06:17 +05302109 frames[cnt].path = OUTPUT_TYPE_P; // MSM_FRAME_ENC;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002110 }
2111
2112 mFrameThreadWaitLock.lock();
2113 pthread_attr_t attr;
2114 pthread_attr_init(&attr);
2115 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
Sravankb4f5f1c2010-01-21 11:06:17 +05302116
2117 frame_parms.frame = frames[kPreviewBufferCount - 1];
2118 frame_parms.video_frame = recordframes[kPreviewBufferCount - 1];
2119
2120 LOGV ("initpreview before cam_frame thread carete , video frame buffer=%lu fd=%d y_off=%d cbcr_off=%d \n",
2121 (unsigned long)frame_parms.video_frame.buffer, frame_parms.video_frame.fd, frame_parms.video_frame.y_off,
2122 frame_parms.video_frame.cbcr_off);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002123 mFrameThreadRunning = !pthread_create(&mFrameThread,
2124 &attr,
2125 frame_thread,
Sravankb4f5f1c2010-01-21 11:06:17 +05302126 (void*)&(frame_parms));
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002127 ret = mFrameThreadRunning;
2128 mFrameThreadWaitLock.unlock();
2129 }
2130
2131 LOGV("initPreview X: %d", ret);
2132 return ret;
2133}
2134
2135void QualcommCameraHardware::deinitPreview(void)
2136{
2137 LOGI("deinitPreview E");
2138
2139 // When we call deinitPreview(), we signal to the frame thread that it
2140 // needs to exit, but we DO NOT WAIT for it to complete here. The problem
2141 // is that deinitPreview is sometimes called from the frame-thread's
2142 // callback, when the refcount on the Camera client reaches zero. If we
2143 // called pthread_join(), we would deadlock. So, we just call
2144 // LINK_camframe_terminate() in deinitPreview(), which makes sure that
2145 // after the preview callback returns, the camframe thread will exit. We
2146 // could call pthread_join() in initPreview() to join the last frame
2147 // thread. However, we would also have to call pthread_join() in release
2148 // as well, shortly before we destroy the object; this would cause the same
2149 // deadlock, since release(), like deinitPreview(), may also be called from
2150 // the frame-thread's callback. This we have to make the frame thread
2151 // detached, and use a separate mechanism to wait for it to complete.
2152
Kiran Kumar H N7ac84e32010-02-01 10:58:47 -08002153 LINK_camframe_terminate();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002154 LOGI("deinitPreview X");
2155}
2156
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002157bool QualcommCameraHardware::initRawSnapshot()
2158{
2159 LOGV("initRawSnapshot E");
2160
2161 //get width and height from Dimension Object
2162 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
2163 sizeof(cam_ctrl_dimension_t), &mDimension);
2164
2165 if(!ret){
2166 LOGE("initRawSnapshot X: failed to set dimension");
2167 return false;
2168 }
2169 int rawSnapshotSize = mDimension.raw_picture_height *
2170 mDimension.raw_picture_width;
2171
2172 LOGV("raw_snapshot_buffer_size = %d, raw_picture_height = %d, "\
2173 "raw_picture_width = %d",
2174 rawSnapshotSize, mDimension.raw_picture_height,
2175 mDimension.raw_picture_width);
2176
2177 if (mRawSnapShotPmemHeap != NULL) {
2178 LOGV("initRawSnapshot: clearing old mRawSnapShotPmemHeap.");
2179 mRawSnapShotPmemHeap.clear();
2180 }
2181
2182 //Pmem based pool for Camera Driver
2183 mRawSnapShotPmemHeap = new PmemPool("/dev/pmem_adsp",
2184 MemoryHeapBase::READ_ONLY,
2185 mCameraControlFd,
2186 MSM_PMEM_RAW_MAINIMG,
2187 rawSnapshotSize,
2188 1,
2189 rawSnapshotSize,
2190 "raw pmem snapshot camera");
2191
2192 if (!mRawSnapShotPmemHeap->initialized()) {
2193 mRawSnapShotPmemHeap.clear();
2194 LOGE("initRawSnapshot X: error initializing mRawSnapshotHeap");
2195 return false;
2196 }
2197 LOGV("initRawSnapshot X");
2198 return true;
2199
2200}
2201
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002202bool QualcommCameraHardware::initRaw(bool initJpegHeap)
2203{
2204 int rawWidth, rawHeight;
Apurva Rajguru8d1773b2009-12-02 14:21:23 -08002205
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002206 mParameters.getPictureSize(&rawWidth, &rawHeight);
2207 LOGV("initRaw E: picture size=%dx%d", rawWidth, rawHeight);
2208
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08002209 int thumbnailBufferSize;
2210 //Thumbnail height should be smaller than Picture height
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002211 if (rawHeight > (int)thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height){
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08002212 mDimension.ui_thumbnail_width =
2213 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].width;
2214 mDimension.ui_thumbnail_height =
2215 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height;
2216 uint32_t pictureAspectRatio = (uint32_t)((rawWidth * Q12) / rawHeight);
2217 uint32_t i;
2218 for(i = 0; i < THUMBNAIL_SIZE_COUNT; i++ )
2219 {
2220 if(thumbnail_sizes[i].aspect_ratio == pictureAspectRatio)
2221 {
2222 mDimension.ui_thumbnail_width = thumbnail_sizes[i].width;
2223 mDimension.ui_thumbnail_height = thumbnail_sizes[i].height;
2224 break;
2225 }
2226 }
2227 }
2228 else{
2229 mDimension.ui_thumbnail_height = THUMBNAIL_SMALL_HEIGHT;
2230 mDimension.ui_thumbnail_width =
2231 (THUMBNAIL_SMALL_HEIGHT * rawWidth)/ rawHeight;
2232 }
2233
2234 LOGV("Thumbnail Size Width %d Height %d",
2235 mDimension.ui_thumbnail_width,
2236 mDimension.ui_thumbnail_height);
2237
2238 thumbnailBufferSize = mDimension.ui_thumbnail_width *
2239 mDimension.ui_thumbnail_height * 3 / 2;
2240
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002241 // mDimension will be filled with thumbnail_width, thumbnail_height,
2242 // orig_picture_dx, and orig_picture_dy after this function call. We need to
2243 // keep it for jpeg_encoder_encode.
2244 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
2245 sizeof(cam_ctrl_dimension_t), &mDimension);
2246 if(!ret) {
2247 LOGE("initRaw X: failed to set dimension");
2248 return false;
2249 }
2250
2251 if (mJpegHeap != NULL) {
2252 LOGV("initRaw: clearing old mJpegHeap.");
2253 mJpegHeap.clear();
2254 }
2255
2256 // Snapshot
2257 mRawSize = rawWidth * rawHeight * 3 / 2;
Apurva Rajguru8d1773b2009-12-02 14:21:23 -08002258
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002259 if( mCurrentTarget == TARGET_MSM7627 )
Apurva Rajguru8d1773b2009-12-02 14:21:23 -08002260 mJpegMaxSize = CEILING16(rawWidth) * CEILING16(rawHeight) * 3 / 2;
2261 else
2262 mJpegMaxSize = rawWidth * rawHeight * 3 / 2;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002263
2264 LOGV("initRaw: initializing mRawHeap.");
2265 mRawHeap =
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002266 new PmemPool("/dev/pmem_adsp",
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002267 MemoryHeapBase::READ_ONLY,
2268 mCameraControlFd,
2269 MSM_PMEM_MAINIMG,
2270 mJpegMaxSize,
2271 kRawBufferCount,
2272 mRawSize,
2273 "snapshot camera");
2274
2275 if (!mRawHeap->initialized()) {
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002276 LOGE("initRaw X failed ");
2277 mRawHeap.clear();
2278 LOGE("initRaw X: error initializing mRawHeap");
2279 return false;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002280 }
2281
2282 LOGV("do_mmap snapshot pbuf = %p, pmem_fd = %d",
2283 (uint8_t *)mRawHeap->mHeap->base(), mRawHeap->mHeap->getHeapID());
2284
2285 // Jpeg
2286
2287 if (initJpegHeap) {
2288 LOGV("initRaw: initializing mJpegHeap.");
2289 mJpegHeap =
2290 new AshmemPool(mJpegMaxSize,
2291 kJpegBufferCount,
2292 0, // we do not know how big the picture will be
2293 "jpeg");
2294
2295 if (!mJpegHeap->initialized()) {
2296 mJpegHeap.clear();
2297 mRawHeap.clear();
2298 LOGE("initRaw X failed: error initializing mJpegHeap.");
2299 return false;
2300 }
2301
2302 // Thumbnails
2303
2304 mThumbnailHeap =
2305 new PmemPool("/dev/pmem_adsp",
2306 MemoryHeapBase::READ_ONLY,
2307 mCameraControlFd,
2308 MSM_PMEM_THUMBNAIL,
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08002309 thumbnailBufferSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002310 1,
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08002311 thumbnailBufferSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002312 "thumbnail");
2313
2314 if (!mThumbnailHeap->initialized()) {
2315 mThumbnailHeap.clear();
2316 mJpegHeap.clear();
2317 mRawHeap.clear();
2318 LOGE("initRaw X failed: error initializing mThumbnailHeap.");
2319 return false;
2320 }
2321 }
2322
2323 LOGV("initRaw X");
2324 return true;
2325}
2326
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002327
2328void QualcommCameraHardware::deinitRawSnapshot()
2329{
2330 LOGV("deinitRawSnapshot E");
2331 mRawSnapShotPmemHeap.clear();
2332 mRawSnapshotAshmemHeap.clear();
2333 LOGV("deinitRawSnapshot X");
2334}
2335
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002336void QualcommCameraHardware::deinitRaw()
2337{
2338 LOGV("deinitRaw E");
2339
2340 mThumbnailHeap.clear();
2341 mJpegHeap.clear();
2342 mRawHeap.clear();
2343 mDisplayHeap.clear();
2344
2345 LOGV("deinitRaw X");
2346}
2347
2348void QualcommCameraHardware::release()
2349{
2350 LOGD("release E");
2351 Mutex::Autolock l(&mLock);
2352
2353#if DLOPEN_LIBMMCAMERA
2354 if (libmmcamera == NULL) {
2355 LOGE("ERROR: multiple release!");
2356 return;
2357 }
2358#else
2359#warning "Cannot detect multiple release when not dlopen()ing libqcamera!"
2360#endif
2361
2362 int cnt, rc;
2363 struct msm_ctrl_cmd ctrlCmd;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002364 if (mCameraRunning) {
2365 if(mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME)) {
2366 mRecordFrameLock.lock();
2367 mReleasedRecordingFrame = true;
2368 mRecordWait.signal();
2369 mRecordFrameLock.unlock();
2370 }
2371 stopPreviewInternal();
2372 }
2373
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002374 if( mCurrentTarget == TARGET_MSM7630 ) {
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002375 mPostViewHeap.clear();
2376 mPostViewHeap = NULL;
2377 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002378 LINK_jpeg_encoder_join();
2379 deinitRaw();
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002380 deinitRawSnapshot();
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002381 {
2382 Mutex::Autolock l(&mCamframeTimeoutLock);
2383 if(!camframe_timeout_flag) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002384
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002385 ctrlCmd.timeout_ms = 5000;
2386 ctrlCmd.length = 0;
2387 ctrlCmd.type = (uint16_t)CAMERA_EXIT;
2388 ctrlCmd.resp_fd = mCameraControlFd; // FIXME: this will be put in by the kernel
2389 if (ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0)
2390 LOGE("ioctl CAMERA_EXIT fd %d error %s",
2391 mCameraControlFd, strerror(errno));
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002392
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002393 }
2394 }
Kiran Kumar H N7ac84e32010-02-01 10:58:47 -08002395 LINK_release_cam_conf_thread();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002396 close(mCameraControlFd);
2397 mCameraControlFd = -1;
Mohan Kandra284966d2010-01-05 13:39:15 -08002398 if(fb_fd >= 0) {
2399 close(fb_fd);
2400 fb_fd = -1;
2401 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002402#if DLOPEN_LIBMMCAMERA
2403 if (libmmcamera) {
2404 ::dlclose(libmmcamera);
2405 LOGV("dlclose(libqcamera)");
2406 libmmcamera = NULL;
2407 }
2408#endif
2409
2410 Mutex::Autolock lock(&singleton_lock);
2411 singleton_releasing = true;
2412
2413 LOGD("release X");
2414}
2415
2416QualcommCameraHardware::~QualcommCameraHardware()
2417{
2418 LOGD("~QualcommCameraHardware E");
2419 Mutex::Autolock lock(&singleton_lock);
2420 singleton.clear();
2421 singleton_releasing = false;
2422 singleton_wait.signal();
2423 LOGD("~QualcommCameraHardware X");
2424}
2425
2426sp<IMemoryHeap> QualcommCameraHardware::getRawHeap() const
2427{
2428 LOGV("getRawHeap");
2429 return mDisplayHeap != NULL ? mDisplayHeap->mHeap : NULL;
2430}
2431
2432sp<IMemoryHeap> QualcommCameraHardware::getPreviewHeap() const
2433{
2434 LOGV("getPreviewHeap");
Mohan Kandrad9efed92010-01-15 19:08:39 -08002435 return mPreviewHeap != NULL ? mPreviewHeap->mHeap : NULL;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002436}
2437
2438status_t QualcommCameraHardware::startPreviewInternal()
2439{
Sravankb4f5f1c2010-01-21 11:06:17 +05302440 LOGV("in startPreviewInternal : E");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002441 if(mCameraRunning) {
2442 LOGV("startPreview X: preview already running.");
2443 return NO_ERROR;
2444 }
2445
2446 if (!mPreviewInitialized) {
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002447 mLastQueuedFrame = NULL;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002448 mPreviewInitialized = initPreview();
2449 if (!mPreviewInitialized) {
2450 LOGE("startPreview X initPreview failed. Not starting preview.");
2451 return UNKNOWN_ERROR;
2452 }
2453 }
2454
Srinivasan Kannan74712c92010-04-07 13:36:48 -07002455 {
2456 Mutex::Autolock cameraRunningLock(&mCameraRunningLock);
2457 if(( mCurrentTarget != TARGET_MSM7630 ) &&
2458 (mCurrentTarget != TARGET_QSD8250))
2459 mCameraRunning = native_start_preview(mCameraControlFd);
2460 else
2461 mCameraRunning = native_start_video(mCameraControlFd);
2462 }
Sravankb4f5f1c2010-01-21 11:06:17 +05302463
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002464 if(!mCameraRunning) {
2465 deinitPreview();
2466 mPreviewInitialized = false;
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08002467 mOverlay = NULL;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002468 LOGE("startPreview X: native_start_preview failed!");
2469 return UNKNOWN_ERROR;
2470 }
2471
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08002472 //Reset the Gps Information
2473 exif_table_numEntries = 0;
Mohan Kandra284966d2010-01-05 13:39:15 -08002474
2475 if(native_get_maxzoom(mCameraControlFd, (void *)&mMaxZoom) == true){
Brian Steuerb62adbd2010-02-02 14:47:08 -08002476 LOGD("Maximum zoom value is %d", mMaxZoom);
Mohan Kandra284966d2010-01-05 13:39:15 -08002477 mParameters.set("zoom-supported", "true");
2478 } else {
2479 LOGE("Failed to get maximum zoom value...setting max zoom to zero");
2480 mParameters.set("zoom-supported", "false");
2481 mMaxZoom = 0;
2482 }
2483 mParameters.set("max-zoom",mMaxZoom);
2484
Sravankb4f5f1c2010-01-21 11:06:17 +05302485 LOGV("startPreviewInternal X");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002486 return NO_ERROR;
2487}
2488
2489status_t QualcommCameraHardware::startPreview()
2490{
2491 LOGV("startPreview E");
2492 Mutex::Autolock l(&mLock);
2493 return startPreviewInternal();
2494}
2495
2496void QualcommCameraHardware::stopPreviewInternal()
2497{
2498 LOGV("stopPreviewInternal E: %d", mCameraRunning);
2499 if (mCameraRunning) {
2500 // Cancel auto focus.
2501 {
2502 if (mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS)) {
2503 cancelAutoFocusInternal();
2504 }
2505 }
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002506
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002507 Mutex::Autolock l(&mCamframeTimeoutLock);
Srinivasan Kannan74712c92010-04-07 13:36:48 -07002508 {
2509 Mutex::Autolock cameraRunningLock(&mCameraRunningLock);
2510 if(!camframe_timeout_flag) {
2511 if (( mCurrentTarget != TARGET_MSM7630 ) &&
2512 (mCurrentTarget != TARGET_QSD8250))
2513 mCameraRunning = !native_stop_preview(mCameraControlFd);
2514 else
2515 mCameraRunning = !native_stop_video(mCameraControlFd);
2516 } else {
2517 /* This means that the camframetimeout was issued.
2518 * But we did not issue native_stop_preview(), so we
2519 * need to update mCameraRunning to indicate that
2520 * Camera is no longer running. */
2521 mCameraRunning = 0;
2522 }
2523 }
Sravankb4f5f1c2010-01-21 11:06:17 +05302524
Kiran Kumar H Nac2f4952009-12-17 01:16:53 -08002525 if (!mCameraRunning && mPreviewInitialized) {
2526 deinitPreview();
Mohan Kandraf1ebf982010-02-02 15:25:43 -08002527 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250)) {
Mohan Kandra156d0ac2010-01-25 16:59:17 -08002528 mVideoThreadWaitLock.lock();
2529 LOGV("in stopPreviewInternal: making mVideoThreadExit 1");
2530 mVideoThreadExit = 1;
2531 mVideoThreadWaitLock.unlock();
2532 // 720p : signal the video thread , and check in video thread if stop is called, if so exit video thread.
2533 pthread_mutex_lock(&(g_busy_frame_queue.mut));
2534 pthread_cond_signal(&(g_busy_frame_queue.wait));
2535 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
Mohan Kandra1ade9a82010-03-02 10:11:26 -08002536 /* Flush the Busy Q */
2537 cam_frame_flush_video();
2538 /* Flush the Free Q */
2539 LINK_cam_frame_flush_free_video();
Mohan Kandra156d0ac2010-01-25 16:59:17 -08002540 }
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002541 mPreviewInitialized = false;
2542 }
Kiran Kumar H Nac2f4952009-12-17 01:16:53 -08002543 else LOGE("stopPreviewInternal: failed to stop preview");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002544 }
2545 LOGV("stopPreviewInternal X: %d", mCameraRunning);
2546}
2547
2548void QualcommCameraHardware::stopPreview()
2549{
2550 LOGV("stopPreview: E");
2551 Mutex::Autolock l(&mLock);
2552 {
2553 if (mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME))
2554 return;
2555 }
2556 stopPreviewInternal();
2557 LOGV("stopPreview: X");
2558}
2559
2560void QualcommCameraHardware::runAutoFocus()
2561{
2562 bool status = true;
2563 void *libhandle = NULL;
Srinivasan Kannan71229622009-12-04 12:05:58 -08002564 isp3a_af_mode_t afMode;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002565
2566 mAutoFocusThreadLock.lock();
2567 // Skip autofocus if focus mode is infinity.
Srinivasan Kannan74712c92010-04-07 13:36:48 -07002568 if ((mParameters.get(CameraParameters::KEY_FOCUS_MODE) == 0)
2569 || (strcmp(mParameters.get(CameraParameters::KEY_FOCUS_MODE),
2570 CameraParameters::FOCUS_MODE_INFINITY) == 0)) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002571 goto done;
2572 }
2573
2574 mAutoFocusFd = open(MSM_CAMERA_CONTROL, O_RDWR);
2575 if (mAutoFocusFd < 0) {
2576 LOGE("autofocus: cannot open %s: %s",
2577 MSM_CAMERA_CONTROL,
2578 strerror(errno));
2579 mAutoFocusThreadRunning = false;
2580 mAutoFocusThreadLock.unlock();
2581 return;
2582 }
2583
2584#if DLOPEN_LIBMMCAMERA
2585 // We need to maintain a reference to libqcamera.so for the duration of the
2586 // AF thread, because we do not know when it will exit relative to the
2587 // lifetime of this object. We do not want to dlclose() libqcamera while
2588 // LINK_cam_frame is still running.
2589 libhandle = ::dlopen("liboemcamera.so", RTLD_NOW);
2590 LOGV("AF: loading libqcamera at %p", libhandle);
2591 if (!libhandle) {
2592 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
2593 close(mAutoFocusFd);
2594 mAutoFocusFd = -1;
2595 mAutoFocusThreadRunning = false;
2596 mAutoFocusThreadLock.unlock();
2597 return;
2598 }
2599#endif
2600
Srinivasan Kannan71229622009-12-04 12:05:58 -08002601 afMode = (isp3a_af_mode_t)attr_lookup(focus_modes,
2602 sizeof(focus_modes) / sizeof(str_map),
2603 mParameters.get(CameraParameters::KEY_FOCUS_MODE));
2604
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002605 /* This will block until either AF completes or is cancelled. */
Srinivasan Kannan71229622009-12-04 12:05:58 -08002606 LOGV("af start (fd %d mode %d)", mAutoFocusFd, afMode);
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08002607 status_t err;
2608 err = mAfLock.tryLock();
2609 if(err == NO_ERROR) {
Srinivasan Kannan74712c92010-04-07 13:36:48 -07002610 {
2611 Mutex::Autolock cameraRunningLock(&mCameraRunningLock);
2612 if(mCameraRunning){
2613 LOGV("Start AF");
2614 status = native_set_afmode(mAutoFocusFd, afMode);
2615 }else{
2616 LOGV("As Camera preview is not running, AF not issued");
2617 status = false;
2618 }
2619 }
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08002620 mAfLock.unlock();
2621 }
2622 else{
2623 //AF Cancel would have acquired the lock,
2624 //so, no need to perform any AF
Srinivasan Kannan99e82422010-02-28 15:32:16 -08002625 LOGV("As Cancel auto focus is in progress, auto focus request "
2626 "is ignored");
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08002627 status = FALSE;
2628 }
2629
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002630 LOGV("af done: %d", (int)status);
2631 close(mAutoFocusFd);
2632 mAutoFocusFd = -1;
2633
2634done:
2635 mAutoFocusThreadRunning = false;
2636 mAutoFocusThreadLock.unlock();
2637
2638 mCallbackLock.lock();
2639 bool autoFocusEnabled = mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS);
2640 notify_callback cb = mNotifyCallback;
2641 void *data = mCallbackCookie;
2642 mCallbackLock.unlock();
2643 if (autoFocusEnabled)
2644 cb(CAMERA_MSG_FOCUS, status, 0, data);
2645
2646#if DLOPEN_LIBMMCAMERA
2647 if (libhandle) {
2648 ::dlclose(libhandle);
2649 LOGV("AF: dlclose(libqcamera)");
2650 }
2651#endif
2652}
2653
2654status_t QualcommCameraHardware::cancelAutoFocusInternal()
2655{
2656 LOGV("cancelAutoFocusInternal E");
2657
Srinivasan Kannan71229622009-12-04 12:05:58 -08002658 if(!sensorType->hasAutoFocusSupport){
2659 LOGV("cancelAutoFocusInternal X");
2660 return NO_ERROR;
2661 }
2662
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002663#if 0
2664 if (mAutoFocusFd < 0) {
2665 LOGV("cancelAutoFocusInternal X: not in progress");
2666 return NO_ERROR;
2667 }
2668#endif
2669
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08002670 status_t rc = NO_ERROR;
2671 status_t err;
2672 err = mAfLock.tryLock();
2673 if(err == NO_ERROR) {
2674 //Got Lock, means either AF hasn't started or
2675 // AF is done. So no need to cancel it, just change the state
Srinivasan Kannan99e82422010-02-28 15:32:16 -08002676 LOGV("As Auto Focus is not in progress, Cancel Auto Focus "
2677 "is ignored");
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08002678 mAfLock.unlock();
2679 }
2680 else {
2681 //AF is in Progess, So cancel it
2682 LOGV("Lock busy...cancel AF");
2683 rc = native_cancel_afmode(mCameraControlFd, mAutoFocusFd) ?
2684 NO_ERROR :
2685 UNKNOWN_ERROR;
2686 }
2687
2688
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002689
2690 LOGV("cancelAutoFocusInternal X: %d", rc);
2691 return rc;
2692}
2693
2694void *auto_focus_thread(void *user)
2695{
2696 LOGV("auto_focus_thread E");
2697 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
2698 if (obj != 0) {
2699 obj->runAutoFocus();
2700 }
2701 else LOGW("not starting autofocus: the object went away!");
2702 LOGV("auto_focus_thread X");
2703 return NULL;
2704}
2705
2706status_t QualcommCameraHardware::autoFocus()
2707{
2708 LOGV("autoFocus E");
2709 Mutex::Autolock l(&mLock);
2710
Srinivasan Kannan71229622009-12-04 12:05:58 -08002711 if(!sensorType->hasAutoFocusSupport){
Srinivasan Kannandf085222009-12-09 18:31:00 -08002712 bool status = false;
2713 mCallbackLock.lock();
2714 bool autoFocusEnabled = mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS);
2715 notify_callback cb = mNotifyCallback;
2716 void *data = mCallbackCookie;
2717 mCallbackLock.unlock();
2718 if (autoFocusEnabled)
2719 cb(CAMERA_MSG_FOCUS, status, 0, data);
Srinivasan Kannan71229622009-12-04 12:05:58 -08002720 LOGV("autoFocus X");
2721 return NO_ERROR;
2722 }
2723
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002724 if (mCameraControlFd < 0) {
2725 LOGE("not starting autofocus: main control fd %d", mCameraControlFd);
2726 return UNKNOWN_ERROR;
2727 }
2728
2729 {
2730 mAutoFocusThreadLock.lock();
2731 if (!mAutoFocusThreadRunning) {
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08002732 if (native_prepare_snapshot(mCameraControlFd) == FALSE) {
2733 LOGE("native_prepare_snapshot failed!\n");
2734 mAutoFocusThreadLock.unlock();
2735 return UNKNOWN_ERROR;
2736 }
2737
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002738 // Create a detached thread here so that we don't have to wait
2739 // for it when we cancel AF.
2740 pthread_t thr;
2741 pthread_attr_t attr;
2742 pthread_attr_init(&attr);
2743 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2744 mAutoFocusThreadRunning =
2745 !pthread_create(&thr, &attr,
2746 auto_focus_thread, NULL);
2747 if (!mAutoFocusThreadRunning) {
2748 LOGE("failed to start autofocus thread");
2749 mAutoFocusThreadLock.unlock();
2750 return UNKNOWN_ERROR;
2751 }
2752 }
2753 mAutoFocusThreadLock.unlock();
2754 }
2755
2756 LOGV("autoFocus X");
2757 return NO_ERROR;
2758}
2759
2760status_t QualcommCameraHardware::cancelAutoFocus()
2761{
2762 LOGV("cancelAutoFocus E");
2763 Mutex::Autolock l(&mLock);
2764
2765 int rc = NO_ERROR;
2766 if (mCameraRunning && mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS)) {
2767 rc = cancelAutoFocusInternal();
2768 }
2769
2770 LOGV("cancelAutoFocus X");
2771 return rc;
2772}
2773
2774void QualcommCameraHardware::runSnapshotThread(void *data)
2775{
2776 LOGV("runSnapshotThread E");
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002777 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
2778 if (native_start_snapshot(mCameraControlFd))
2779 receiveRawPicture();
2780 else
2781 LOGE("main: native_start_snapshot failed!");
2782 } else if(mSnapshotFormat == PICTURE_FORMAT_RAW){
2783 if(native_start_raw_snapshot(mCameraControlFd)){
2784 receiveRawSnapshot();
2785 } else {
2786 LOGE("main: native_start_raw_snapshot failed!");
2787 }
2788 }
2789
2790 mSnapshotFormat = 0;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002791
2792 mSnapshotThreadWaitLock.lock();
2793 mSnapshotThreadRunning = false;
2794 mSnapshotThreadWait.signal();
2795 mSnapshotThreadWaitLock.unlock();
2796
2797 LOGV("runSnapshotThread X");
2798}
2799
2800void *snapshot_thread(void *user)
2801{
2802 LOGD("snapshot_thread E");
2803 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
2804 if (obj != 0) {
2805 obj->runSnapshotThread(user);
2806 }
2807 else LOGW("not starting snapshot thread: the object went away!");
2808 LOGD("snapshot_thread X");
2809 return NULL;
2810}
2811
2812status_t QualcommCameraHardware::takePicture()
2813{
2814 LOGV("takePicture(%d)", mMsgEnabled);
2815 Mutex::Autolock l(&mLock);
2816
2817 // Wait for old snapshot thread to complete.
2818 mSnapshotThreadWaitLock.lock();
2819 while (mSnapshotThreadRunning) {
2820 LOGV("takePicture: waiting for old snapshot thread to complete.");
2821 mSnapshotThreadWait.wait(mSnapshotThreadWaitLock);
2822 LOGV("takePicture: old snapshot thread completed.");
2823 }
2824
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002825 if( mCurrentTarget == TARGET_MSM7630 ) {
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002826 /* Store the last frame queued for preview. This
2827 * shall be used as postview */
2828 storePreviewFrameForPostview();
2829 }
2830
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002831 //mSnapshotFormat is protected by mSnapshotThreadWaitLock
2832 if(mParameters.getPictureFormat() != 0 &&
2833 !strcmp(mParameters.getPictureFormat(),
2834 CameraParameters::PIXEL_FORMAT_RAW))
2835 mSnapshotFormat = PICTURE_FORMAT_RAW;
2836 else
2837 mSnapshotFormat = PICTURE_FORMAT_JPEG;
2838
2839 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
2840 if(!native_prepare_snapshot(mCameraControlFd)) {
2841 mSnapshotThreadWaitLock.unlock();
2842 return UNKNOWN_ERROR;
2843 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002844 }
2845
2846 stopPreviewInternal();
2847
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002848 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
2849 if (!initRaw(mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE))) {
2850 LOGE("initRaw failed. Not taking picture.");
2851 mSnapshotThreadWaitLock.unlock();
2852 return UNKNOWN_ERROR;
2853 }
2854 } else if(mSnapshotFormat == PICTURE_FORMAT_RAW ){
2855 if(!initRawSnapshot()){
2856 LOGE("initRawSnapshot failed. Not taking picture.");
2857 mSnapshotThreadWaitLock.unlock();
2858 return UNKNOWN_ERROR;
2859 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002860 }
2861
2862 mShutterLock.lock();
2863 mShutterPending = true;
2864 mShutterLock.unlock();
2865
2866 pthread_attr_t attr;
2867 pthread_attr_init(&attr);
2868 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2869 mSnapshotThreadRunning = !pthread_create(&mSnapshotThread,
2870 &attr,
2871 snapshot_thread,
2872 NULL);
2873 mSnapshotThreadWaitLock.unlock();
2874
2875 LOGV("takePicture: X");
2876 return mSnapshotThreadRunning ? NO_ERROR : UNKNOWN_ERROR;
2877}
2878
2879status_t QualcommCameraHardware::cancelPicture()
2880{
2881 status_t rc;
2882 LOGV("cancelPicture: E");
2883 rc = native_stop_snapshot(mCameraControlFd) ? NO_ERROR : UNKNOWN_ERROR;
2884 LOGV("cancelPicture: X: %d", rc);
2885 return rc;
2886}
2887
2888status_t QualcommCameraHardware::setParameters(const CameraParameters& params)
2889{
2890 LOGV("setParameters: E params = %p", &params);
2891
2892 Mutex::Autolock l(&mLock);
2893 status_t rc, final_rc = NO_ERROR;
2894
2895 if ((rc = setPreviewSize(params))) final_rc = rc;
2896 if ((rc = setPictureSize(params))) final_rc = rc;
2897 if ((rc = setJpegQuality(params))) final_rc = rc;
2898 if ((rc = setAntibanding(params))) final_rc = rc;
Apurva Rajguru55562b02009-12-03 12:25:35 -08002899 if ((rc = setAutoExposure(params))) final_rc = rc;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002900 if ((rc = setWhiteBalance(params))) final_rc = rc;
Vamshidhar Kondrae7b9b5a2010-02-25 15:40:37 +05302901 if ((rc = setEffect(params))) final_rc = rc;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002902 if ((rc = setFlash(params))) final_rc = rc;
2903 if ((rc = setGpsLocation(params))) final_rc = rc;
2904 if ((rc = setRotation(params))) final_rc = rc;
2905 if ((rc = setZoom(params))) final_rc = rc;
2906 if ((rc = setFocusMode(params))) final_rc = rc;
2907 if ((rc = setOrientation(params))) final_rc = rc;
Nishant Panditc8c1ee72009-12-03 16:24:02 +05302908 if ((rc = setBrightness(params))) final_rc = rc;
2909 if ((rc = setLensshadeValue(params))) final_rc = rc;
2910 if ((rc = setISOValue(params))) final_rc = rc;
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002911 if ((rc = setPictureFormat(params))) final_rc = rc;
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08002912 if ((rc = setSharpness(params))) final_rc = rc;
2913 if ((rc = setContrast(params))) final_rc = rc;
2914 if ((rc = setSaturation(params))) final_rc = rc;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002915
2916 LOGV("setParameters: X");
2917 return final_rc;
2918}
2919
2920CameraParameters QualcommCameraHardware::getParameters() const
2921{
2922 LOGV("getParameters: EX");
2923 return mParameters;
2924}
2925
2926status_t QualcommCameraHardware::sendCommand(int32_t command, int32_t arg1,
2927 int32_t arg2)
2928{
2929 LOGV("sendCommand: EX");
2930 return BAD_VALUE;
2931}
2932
2933extern "C" sp<CameraHardwareInterface> openCameraHardware()
2934{
2935 LOGV("openCameraHardware: call createInstance");
2936 return QualcommCameraHardware::createInstance();
2937}
2938
2939wp<QualcommCameraHardware> QualcommCameraHardware::singleton;
2940
2941// If the hardware already exists, return a strong pointer to the current
2942// object. If not, create a new hardware object, put it in the singleton,
2943// and return it.
2944sp<CameraHardwareInterface> QualcommCameraHardware::createInstance()
2945{
2946 LOGD("createInstance: E");
2947
2948 Mutex::Autolock lock(&singleton_lock);
2949
2950 // Wait until the previous release is done.
2951 while (singleton_releasing) {
2952 LOGD("Wait for previous release.");
2953 singleton_wait.wait(singleton_lock);
2954 }
2955
2956 if (singleton != 0) {
2957 sp<CameraHardwareInterface> hardware = singleton.promote();
2958 if (hardware != 0) {
2959 LOGD("createInstance: X return existing hardware=%p", &(*hardware));
2960 return hardware;
2961 }
2962 }
2963
2964 {
2965 struct stat st;
2966 int rc = stat("/dev/oncrpc", &st);
2967 if (rc < 0) {
2968 LOGD("createInstance: X failed to create hardware: %s", strerror(errno));
2969 return NULL;
2970 }
2971 }
2972
2973 QualcommCameraHardware *cam = new QualcommCameraHardware();
2974 sp<QualcommCameraHardware> hardware(cam);
2975 singleton = hardware;
2976
2977 if (!cam->startCamera()) {
2978 LOGE("%s: startCamera failed!", __FUNCTION__);
2979 return NULL;
2980 }
2981
2982 cam->initDefaultParameters();
2983 LOGD("createInstance: X created hardware=%p", &(*hardware));
2984 return hardware;
2985}
2986
2987// For internal use only, hence the strong pointer to the derived type.
2988sp<QualcommCameraHardware> QualcommCameraHardware::getInstance()
2989{
2990 sp<CameraHardwareInterface> hardware = singleton.promote();
2991 if (hardware != 0) {
2992 // LOGV("getInstance: X old instance of hardware");
2993 return sp<QualcommCameraHardware>(static_cast<QualcommCameraHardware*>(hardware.get()));
2994 } else {
2995 LOGV("getInstance: X new instance of hardware");
2996 return sp<QualcommCameraHardware>();
2997 }
2998}
Sravankb4f5f1c2010-01-21 11:06:17 +05302999void QualcommCameraHardware::receiveRecordingFrame(struct msm_frame *frame)
3000{
3001 LOGV("receiveRecordingFrame E");
3002 // post busy frame
3003 if (frame)
3004 {
3005 cam_frame_post_video (frame);
3006 }
3007 else LOGE("in receiveRecordingFrame frame is NULL");
3008 LOGV("receiveRecordingFrame X");
3009}
3010
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003011
Mohan Kandrad9efed92010-01-15 19:08:39 -08003012bool QualcommCameraHardware::native_zoom_image(int fd, int srcOffset, int dstOffSet, common_crop_t *crop)
Mohan Kandra284966d2010-01-05 13:39:15 -08003013{
3014 int result = 0;
3015 struct mdp_blit_req *e;
3016 struct timeval td1, td2;
3017
Mohan Kandra284966d2010-01-05 13:39:15 -08003018 /* Initialize yuv structure */
3019 zoomImage.list.count = 1;
3020
3021 e = &zoomImage.list.req[0];
3022
3023 e->src.width = previewWidth;
3024 e->src.height = previewHeight;
3025 e->src.format = MDP_Y_CBCR_H2V2;
Mohan Kandrad9efed92010-01-15 19:08:39 -08003026 e->src.offset = srcOffset;
3027 e->src.memory_id = fd;
Mohan Kandra284966d2010-01-05 13:39:15 -08003028
3029 e->dst.width = previewWidth;
3030 e->dst.height = previewHeight;
3031 e->dst.format = MDP_Y_CBCR_H2V2;
Mohan Kandrad9efed92010-01-15 19:08:39 -08003032 e->dst.offset = dstOffSet;
3033 e->dst.memory_id = fd;
Mohan Kandra284966d2010-01-05 13:39:15 -08003034
3035 e->transp_mask = 0xffffffff;
3036 e->flags = 0;
3037 e->alpha = 0xff;
3038 if (crop->in2_w != 0 || crop->in2_h != 0) {
3039 e->src_rect.x = (crop->out2_w - crop->in2_w + 1) / 2 - 1;
3040 e->src_rect.y = (crop->out2_h - crop->in2_h + 1) / 2 - 1;
3041 e->src_rect.w = crop->in2_w;
3042 e->src_rect.h = crop->in2_h;
3043 } else {
3044 e->src_rect.x = 0;
3045 e->src_rect.y = 0;
3046 e->src_rect.w = previewWidth;
3047 e->src_rect.h = previewHeight;
3048 }
Mohan Kandrad9efed92010-01-15 19:08:39 -08003049 //LOGV(" native_zoom : SRC_RECT : x,y = %d,%d \t w,h = %d, %d",
3050 // e->src_rect.x, e->src_rect.y, e->src_rect.w, e->src_rect.h);
Mohan Kandra284966d2010-01-05 13:39:15 -08003051
3052 e->dst_rect.x = 0;
3053 e->dst_rect.y = 0;
3054 e->dst_rect.w = previewWidth;
3055 e->dst_rect.h = previewHeight;
3056
3057 result = ioctl(fb_fd, MSMFB_BLIT, &zoomImage.list);
3058 if (result < 0) {
3059 LOGE("MSM_FBIOBLT failed! line=%d\n", __LINE__);
3060 return FALSE;
3061 }
3062 return TRUE;
3063}
3064
Mohan Kandrabad0eaa2010-02-04 15:11:54 -08003065void QualcommCameraHardware::debugShowPreviewFPS() const
Mohan Kandra740cfce2010-01-07 12:58:24 -08003066{
3067 static int mFrameCount;
3068 static int mLastFrameCount = 0;
3069 static nsecs_t mLastFpsTime = 0;
3070 static float mFps = 0;
3071 mFrameCount++;
3072 nsecs_t now = systemTime();
3073 nsecs_t diff = now - mLastFpsTime;
3074 if (diff > ms2ns(250)) {
3075 mFps = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
Mohan Kandrabad0eaa2010-02-04 15:11:54 -08003076 LOGI("Preview Frames Per Second: %.4f", mFps);
Mohan Kandra740cfce2010-01-07 12:58:24 -08003077 mLastFpsTime = now;
3078 mLastFrameCount = mFrameCount;
3079 }
3080}
3081
Mohan Kandrabad0eaa2010-02-04 15:11:54 -08003082void QualcommCameraHardware::debugShowVideoFPS() const
3083{
3084 static int mFrameCount;
3085 static int mLastFrameCount = 0;
3086 static nsecs_t mLastFpsTime = 0;
3087 static float mFps = 0;
3088 mFrameCount++;
3089 nsecs_t now = systemTime();
3090 nsecs_t diff = now - mLastFpsTime;
3091 if (diff > ms2ns(250)) {
3092 mFps = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
3093 LOGI("Video Frames Per Second: %.4f", mFps);
3094 mLastFpsTime = now;
3095 mLastFrameCount = mFrameCount;
3096 }
3097}
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003098void QualcommCameraHardware::receivePreviewFrame(struct msm_frame *frame)
3099{
3100// LOGV("receivePreviewFrame E");
3101
3102 if (!mCameraRunning) {
3103 LOGE("ignoring preview callback--camera has been stopped");
3104 return;
3105 }
3106
Mohan Kandra740cfce2010-01-07 12:58:24 -08003107 if (UNLIKELY(mDebugFps)) {
Mohan Kandrabad0eaa2010-02-04 15:11:54 -08003108 debugShowPreviewFPS();
Mohan Kandra740cfce2010-01-07 12:58:24 -08003109 }
3110
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003111 mCallbackLock.lock();
3112 int msgEnabled = mMsgEnabled;
3113 data_callback pcb = mDataCallback;
3114 void *pdata = mCallbackCookie;
3115 data_callback_timestamp rcb = mDataCallbackTimestamp;
3116 void *rdata = mCallbackCookie;
3117 mCallbackLock.unlock();
3118
3119 // Find the offset within the heap of the current buffer.
Mohan Kandra284966d2010-01-05 13:39:15 -08003120 ssize_t offset_addr =
Mohan Kandrad9efed92010-01-15 19:08:39 -08003121 (ssize_t)frame->buffer - (ssize_t)mPreviewHeap->mHeap->base();
3122 ssize_t offset = offset_addr / mPreviewHeap->mAlignedBufferSize;
Mohan Kandra284966d2010-01-05 13:39:15 -08003123
3124 common_crop_t *crop = (common_crop_t *) (frame->cropinfo);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003125
3126 mInPreviewCallback = true;
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003127 if(mUseOverlay) {
3128 if(mOverlay != NULL) {
3129 mOverlayLock.lock();
Mohan Kandrad9efed92010-01-15 19:08:39 -08003130 mOverlay->setFd(mPreviewHeap->mHeap->getHeapID());
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003131 if (crop->in2_w != 0 || crop->in2_h != 0) {
3132 zoomCropInfo.x = (crop->out2_w - crop->in2_w + 1) / 2 - 1;
3133 zoomCropInfo.y = (crop->out2_h - crop->in2_h + 1) / 2 - 1;
3134 zoomCropInfo.w = crop->in2_w;
3135 zoomCropInfo.h = crop->in2_h;
3136 mOverlay->setCrop(zoomCropInfo.x, zoomCropInfo.y,
3137 zoomCropInfo.w, zoomCropInfo.h);
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08003138 } else {
3139 // Reset zoomCropInfo variables. This will ensure that
3140 // stale values wont be used for postview
3141 zoomCropInfo.w = crop->in2_w;
3142 zoomCropInfo.h = crop->in2_h;
3143 }
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003144 mOverlay->queueBuffer((void *)offset_addr);
3145 mLastQueuedFrame = (void *)frame->buffer;
3146 mOverlayLock.unlock();
3147 }
Mohan Kandra284966d2010-01-05 13:39:15 -08003148 } else {
Mohan Kandrad9efed92010-01-15 19:08:39 -08003149 if (crop->in2_w != 0 || crop->in2_h != 0) {
3150 dstOffset = (dstOffset + 1) % NUM_MORE_BUFS;
3151 offset = kPreviewBufferCount + dstOffset;
3152 ssize_t dstOffset_addr = offset * mPreviewHeap->mAlignedBufferSize;
3153 if( !native_zoom_image(mPreviewHeap->mHeap->getHeapID(),
3154 offset_addr, dstOffset_addr, crop)) {
3155 LOGE(" Error while doing MDP zoom ");
Kiran Kumar H N1ece71c2010-03-30 10:31:21 -07003156 offset = offset_addr / mPreviewHeap->mAlignedBufferSize;
Mohan Kandrad9efed92010-01-15 19:08:39 -08003157 }
3158 }
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08003159 }
Mohan Kandrad9efed92010-01-15 19:08:39 -08003160 if (pcb != NULL && (msgEnabled & CAMERA_MSG_PREVIEW_FRAME))
3161 pcb(CAMERA_MSG_PREVIEW_FRAME, mPreviewHeap->mBuffers[offset],
3162 pdata);
3163
Sravankb4f5f1c2010-01-21 11:06:17 +05303164 // If output is NOT enabled (targets otherthan 7x30 currently..)
Mohan Kandraf1ebf982010-02-02 15:25:43 -08003165 if( (mCurrentTarget != TARGET_MSM7630 ) && (mCurrentTarget != TARGET_QSD8250)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05303166 if(rcb != NULL && (msgEnabled & CAMERA_MSG_VIDEO_FRAME)) {
3167 rcb(systemTime(), CAMERA_MSG_VIDEO_FRAME, mPreviewHeap->mBuffers[offset], rdata);
3168 Mutex::Autolock rLock(&mRecordFrameLock);
3169 if (mReleasedRecordingFrame != true) {
3170 LOGV("block waiting for frame release");
3171 mRecordWait.wait(mRecordFrameLock);
3172 LOGV("frame released, continuing");
3173 }
3174 mReleasedRecordingFrame = false;
3175 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003176 }
3177 mInPreviewCallback = false;
3178
3179// LOGV("receivePreviewFrame X");
3180}
3181
Sravankb4f5f1c2010-01-21 11:06:17 +05303182
3183bool QualcommCameraHardware::initRecord()
3184{
3185 LOGV("initREcord E");
3186
3187 mRecordFrameSize = (mDimension.video_width * mDimension.video_height *3)/2;
3188 mRecordHeap = new PmemPool("/dev/pmem_adsp",
3189 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
3190 mCameraControlFd,
3191 MSM_PMEM_VIDEO,
3192 mRecordFrameSize,
3193 kRecordBufferCount,
3194 mRecordFrameSize,
3195 "record");
3196 if (!mRecordHeap->initialized()) {
3197 mRecordHeap.clear();
3198 LOGE("initRecord X: could not initialize record heap.");
3199 return false;
3200 }
3201 for (int cnt = 0; cnt < kRecordBufferCount; cnt++) {
3202 recordframes[cnt].fd = mRecordHeap->mHeap->getHeapID();
3203 recordframes[cnt].buffer =
3204 (uint32_t)mRecordHeap->mHeap->base() + mRecordHeap->mAlignedBufferSize * cnt;
3205 recordframes[cnt].y_off = 0;
3206 recordframes[cnt].cbcr_off = mDimension.video_width * mDimension.video_height;
3207 recordframes[cnt].path = OUTPUT_TYPE_V;
3208
3209 LOGV ("initRecord : record heap , video buffers buffer=%lu fd=%d y_off=%d cbcr_off=%d \n",
3210 (unsigned long)recordframes[cnt].buffer, recordframes[cnt].fd, recordframes[cnt].y_off,
3211 recordframes[cnt].cbcr_off);
3212 }
3213
3214 // initial setup : buffers 1,2,3 with kernel , 4 with camframe , 5,6,7,8 in free Q
3215 // flush the busy Q
3216 cam_frame_flush_video();
3217
Mohan Kandra156d0ac2010-01-25 16:59:17 -08003218 mVideoThreadWaitLock.lock();
3219 while (mVideoThreadRunning) {
3220 LOGV("initRecord: waiting for old video thread to complete.");
3221 mVideoThreadWait.wait(mVideoThreadWaitLock);
3222 LOGV("initRecord : old video thread completed.");
3223 }
3224 mVideoThreadWaitLock.unlock();
3225
Sravankdf7a9202010-02-08 15:02:51 +05303226 // flush free queue and add 5,6,7,8 buffers.
3227 LINK_cam_frame_flush_free_video();
3228 for(int i=ACTIVE_VIDEO_BUFFERS+1;i <kRecordBufferCount; i++)
3229 LINK_camframe_free_video(&recordframes[i]);
Sravankb4f5f1c2010-01-21 11:06:17 +05303230 LOGV("initREcord X");
3231
3232 return true;
3233}
3234
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003235status_t QualcommCameraHardware::startRecording()
3236{
3237 LOGV("startRecording E");
Sravankb4f5f1c2010-01-21 11:06:17 +05303238 int ret;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003239 Mutex::Autolock l(&mLock);
3240 mReleasedRecordingFrame = false;
Sravankb4f5f1c2010-01-21 11:06:17 +05303241 if( (ret=startPreviewInternal())== NO_ERROR){
Mohan Kandraf1ebf982010-02-02 15:25:43 -08003242 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05303243 LOGV(" in startREcording : calling native_start_recording");
3244 native_start_recording(mCameraControlFd);
3245 recordingState = 1;
Sravank64461e82010-02-25 15:10:09 +05303246 // Remove the left out frames in busy Q and them in free Q.
3247 // this should be done before starting video_thread so that,
3248 // frames in previous recording are flushed out.
3249 LOGV("frames in busy Q = %d", g_busy_frame_queue.num_of_frames);
3250 while((g_busy_frame_queue.num_of_frames) >0){
3251 msm_frame* vframe = cam_frame_get_video ();
3252 LINK_camframe_free_video(vframe);
3253 }
3254 LOGV("frames in busy Q = %d after deQueing", g_busy_frame_queue.num_of_frames);
3255
Sravankdf7a9202010-02-08 15:02:51 +05303256 // Start video thread and wait for busy frames to be encoded, this thread
3257 // should be closed in stopRecording
3258 mVideoThreadWaitLock.lock();
3259 mVideoThreadExit = 0;
3260 pthread_attr_t attr;
3261 pthread_attr_init(&attr);
3262 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
3263 mVideoThreadRunning = pthread_create(&mVideoThread,
3264 &attr,
3265 video_thread,
3266 NULL);
3267 mVideoThreadWaitLock.unlock();
3268 // Remove the left out frames in busy Q and them in free Q.
Sravankb4f5f1c2010-01-21 11:06:17 +05303269 }
3270 }
3271 return ret;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003272}
3273
3274void QualcommCameraHardware::stopRecording()
3275{
3276 LOGV("stopRecording: E");
3277 Mutex::Autolock l(&mLock);
3278 {
3279 mRecordFrameLock.lock();
3280 mReleasedRecordingFrame = true;
3281 mRecordWait.signal();
3282 mRecordFrameLock.unlock();
3283
Sravankdf7a9202010-02-08 15:02:51 +05303284 if(mDataCallback && !(mCurrentTarget == TARGET_QSD8250) &&
3285 (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003286 LOGV("stopRecording: X, preview still in progress");
3287 return;
3288 }
3289 }
Sravankb4f5f1c2010-01-21 11:06:17 +05303290 // If output2 enabled, exit video thread, invoke stop recording ioctl
Mohan Kandraf1ebf982010-02-02 15:25:43 -08003291 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05303292 mVideoThreadWaitLock.lock();
3293 mVideoThreadExit = 1;
3294 mVideoThreadWaitLock.unlock();
3295 native_stop_recording(mCameraControlFd);
Srinivasan Kannanfc3915c2010-03-18 10:54:40 -07003296
3297 pthread_mutex_lock(&(g_busy_frame_queue.mut));
3298 pthread_cond_signal(&(g_busy_frame_queue.wait));
3299 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
Sravankb4f5f1c2010-01-21 11:06:17 +05303300 }
3301 else // for other targets where output2 is not enabled
3302 stopPreviewInternal();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003303
Sravankb4f5f1c2010-01-21 11:06:17 +05303304 recordingState = 0; // recording not started
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003305 LOGV("stopRecording: X");
3306}
3307
3308void QualcommCameraHardware::releaseRecordingFrame(
3309 const sp<IMemory>& mem __attribute__((unused)))
3310{
3311 LOGV("releaseRecordingFrame E");
3312 Mutex::Autolock rLock(&mRecordFrameLock);
3313 mReleasedRecordingFrame = true;
3314 mRecordWait.signal();
Sravankb4f5f1c2010-01-21 11:06:17 +05303315
3316 // Ff 7x30 : add the frame to the free camframe queue
Mohan Kandraf1ebf982010-02-02 15:25:43 -08003317 if( (mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05303318 ssize_t offset;
3319 size_t size;
3320 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
3321 msm_frame* releaseframe = NULL;
3322 LOGV(" in release recording frame : heap base %d offset %d buffer %d ", heap->base(), offset, heap->base() + offset );
3323 int cnt;
3324 for (cnt = 0; cnt < kRecordBufferCount; cnt++) {
3325 if((unsigned int)recordframes[cnt].buffer == (unsigned int)(heap->base()+ offset)){
3326 LOGV("in release recording frame found match , releasing buffer %d", (unsigned int)recordframes[cnt].buffer);
3327 releaseframe = &recordframes[cnt];
3328 break;
3329 }
3330 }
3331 if(cnt < kRecordBufferCount) {
3332 // do this only if frame thread is running
3333 mFrameThreadWaitLock.lock();
3334 if(mFrameThreadRunning )
3335 LINK_camframe_free_video(releaseframe);
3336
3337 mFrameThreadWaitLock.unlock();
3338 } else {
3339 LOGE("in release recordingframe XXXXX error , buffer not found");
3340 for (int i=0; i< kRecordBufferCount; i++) {
3341 LOGE(" recordframes[%d].buffer = %d", i, (unsigned int)recordframes[i].buffer);
3342 }
3343 }
3344 }
3345
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003346 LOGV("releaseRecordingFrame X");
3347}
3348
3349bool QualcommCameraHardware::recordingEnabled()
3350{
3351 return mCameraRunning && mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME);
3352}
3353
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08003354void QualcommCameraHardware::notifyShutter(common_crop_t *crop, bool mPlayShutterSoundOnly)
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003355{
3356 mShutterLock.lock();
3357 image_rect_type size;
3358
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08003359 if(mPlayShutterSoundOnly) {
3360 /* At this point, invoke Notify Callback to play shutter sound only.
3361 * We want to call notify callback again when we have the
3362 * yuv picture ready. This is to reduce blanking at the time
3363 * of displaying postview frame. Using ext2 to indicate whether
3364 * to play shutter sound only or register the postview buffers.
3365 */
3366 mNotifyCallback(CAMERA_MSG_SHUTTER, 0, mPlayShutterSoundOnly,
3367 mCallbackCookie);
3368 mShutterLock.unlock();
3369 return;
3370 }
3371
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003372 if (mShutterPending && mNotifyCallback && (mMsgEnabled & CAMERA_MSG_SHUTTER)) {
3373 LOGV("out2_w=%d, out2_h=%d, in2_w=%d, in2_h=%d",
3374 crop->out2_w, crop->out2_h, crop->in2_w, crop->in2_h);
3375 LOGV("out1_w=%d, out1_h=%d, in1_w=%d, in1_h=%d",
3376 crop->out1_w, crop->out1_h, crop->in1_w, crop->in1_h);
3377
3378 // To workaround a bug in MDP which happens if either
3379 // dimension > 2048, we display the thumbnail instead.
3380 mDisplayHeap = mRawHeap;
3381 if (crop->in1_w == 0 || crop->in1_h == 0) {
3382 // Full size
3383 size.width = mDimension.picture_width;
3384 size.height = mDimension.picture_height;
3385 if (size.width > 2048 || size.height > 2048) {
3386 size.width = mDimension.ui_thumbnail_width;
3387 size.height = mDimension.ui_thumbnail_height;
3388 mDisplayHeap = mThumbnailHeap;
3389 }
3390 } else {
3391 // Cropped
Apurva Rajgurua8b1fc92010-01-27 20:03:55 -08003392 size.width = (crop->in2_w + JPEG_ENCODER_PADDING) & ~1;
3393 size.height = (crop->in2_h + JPEG_ENCODER_PADDING) & ~1;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003394 if (size.width > 2048 || size.height > 2048) {
Apurva Rajgurua8b1fc92010-01-27 20:03:55 -08003395 size.width = (crop->in1_w + JPEG_ENCODER_PADDING) & ~1;
3396 size.height = (crop->in1_h + JPEG_ENCODER_PADDING) & ~1;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003397 mDisplayHeap = mThumbnailHeap;
3398 }
3399 }
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08003400 /* Now, invoke Notify Callback to unregister preview buffer
3401 * and register postview buffer with surface flinger. Set ext2
3402 * as 0 to indicate not to play shutter sound.
3403 */
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003404 mNotifyCallback(CAMERA_MSG_SHUTTER, (int32_t)&size, 0,
3405 mCallbackCookie);
3406 mShutterPending = false;
3407 }
3408 mShutterLock.unlock();
3409}
3410
3411static void receive_shutter_callback(common_crop_t *crop)
3412{
3413 LOGV("receive_shutter_callback: E");
3414 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
3415 if (obj != 0) {
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08003416 /* Just play shutter sound at this time */
3417 obj->notifyShutter(crop, TRUE);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003418 }
3419 LOGV("receive_shutter_callback: X");
3420}
3421
3422// Crop the picture in place.
3423static void crop_yuv420(uint32_t width, uint32_t height,
3424 uint32_t cropped_width, uint32_t cropped_height,
3425 uint8_t *image)
3426{
3427 uint32_t i, x, y;
3428 uint8_t* chroma_src, *chroma_dst;
3429
3430 // Calculate the start position of the cropped area.
3431 x = (width - cropped_width) / 2;
3432 y = (height - cropped_height) / 2;
3433 x &= ~1;
3434 y &= ~1;
3435
3436 // Copy luma component.
3437 for(i = 0; i < cropped_height; i++)
3438 memcpy(image + i * cropped_width,
3439 image + width * (y + i) + x,
3440 cropped_width);
3441
3442 chroma_src = image + width * height;
3443 chroma_dst = image + cropped_width * cropped_height;
3444
3445 // Copy chroma components.
3446 cropped_height /= 2;
3447 y /= 2;
3448 for(i = 0; i < cropped_height; i++)
3449 memcpy(chroma_dst + i * cropped_width,
3450 chroma_src + width * (y + i) + x,
3451 cropped_width);
3452}
3453
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08003454
3455void QualcommCameraHardware::receiveRawSnapshot(){
3456 LOGV("receiveRawSnapshot E");
3457
3458 Mutex::Autolock cbLock(&mCallbackLock);
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08003459 /* Issue notifyShutter with mPlayShutterSoundOnly as TRUE */
3460 notifyShutter(&mCrop, TRUE);
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08003461
3462 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
3463
3464 if(native_get_picture(mCameraControlFd, &mCrop) == false) {
3465 LOGE("receiveRawSnapshot X: native_get_picture failed!");
3466 return;
3467 }
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08003468 /* Its necessary to issue another notifyShutter here with
3469 * mPlayShutterSoundOnly as FALSE, since that is when the
3470 * preview buffers are unregistered with the surface flinger.
3471 * That is necessary otherwise the preview memory wont be
3472 * deallocated.
3473 */
3474 notifyShutter(&mCrop, FALSE);
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08003475
3476 //Create a Ashmem heap to copy data from PMem heap for application layer
3477 if(mRawSnapshotAshmemHeap != NULL){
3478 LOGV("receiveRawSnapshot: clearing old mRawSnapShotAshmemHeap.");
3479 mRawSnapshotAshmemHeap.clear();
3480 }
3481 mRawSnapshotAshmemHeap = new AshmemPool(
3482 mRawSnapShotPmemHeap->mBufferSize,
3483 mRawSnapShotPmemHeap->mNumBuffers,
3484 mRawSnapShotPmemHeap->mFrameSize,
3485 "raw ashmem snapshot camera"
3486 );
3487
3488 if(!mRawSnapshotAshmemHeap->initialized()){
3489 LOGE("receiveRawSnapshot X: error initializing mRawSnapshotHeap");
3490 deinitRawSnapshot();
3491 return;
3492 }
3493
3494 memcpy(mRawSnapshotAshmemHeap->mHeap->base(),
3495 mRawSnapShotPmemHeap->mHeap->base(),
3496 mRawSnapShotPmemHeap->mHeap->getSize());
Nishant Panditb861be52010-03-02 16:43:49 +05303497 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE))
3498 mDataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mRawSnapshotAshmemHeap->mBuffers[0],
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08003499 mCallbackCookie);
3500
3501 }
3502
3503 //cleanup
3504 deinitRawSnapshot();
3505
3506 LOGV("receiveRawSnapshot X");
3507}
3508
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003509void QualcommCameraHardware::receiveRawPicture()
3510{
3511 LOGV("receiveRawPicture: E");
3512
3513 Mutex::Autolock cbLock(&mCallbackLock);
3514 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_RAW_IMAGE)) {
3515 if(native_get_picture(mCameraControlFd, &mCrop) == false) {
3516 LOGE("getPicture failed!");
3517 return;
3518 }
3519 mCrop.in1_w &= ~1;
3520 mCrop.in1_h &= ~1;
3521 mCrop.in2_w &= ~1;
3522 mCrop.in2_h &= ~1;
3523
3524 // By the time native_get_picture returns, picture is taken. Call
3525 // shutter callback if cam config thread has not done that.
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08003526 notifyShutter(&mCrop, FALSE);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003527
3528 // Crop the image if zoomed.
3529 if (mCrop.in2_w != 0 && mCrop.in2_h != 0) {
Apurva Rajgurua8b1fc92010-01-27 20:03:55 -08003530 crop_yuv420(mCrop.out2_w, mCrop.out2_h, (mCrop.in2_w + JPEG_ENCODER_PADDING), (mCrop.in2_h + JPEG_ENCODER_PADDING),
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003531 (uint8_t *)mRawHeap->mHeap->base());
Apurva Rajgurua8b1fc92010-01-27 20:03:55 -08003532 crop_yuv420(mCrop.out1_w, mCrop.out1_h, (mCrop.in1_w + JPEG_ENCODER_PADDING), (mCrop.in1_h + JPEG_ENCODER_PADDING),
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003533 (uint8_t *)mThumbnailHeap->mHeap->base());
3534 // We do not need jpeg encoder to upscale the image. Set the new
3535 // dimension for encoder.
Apurva Rajgurua8b1fc92010-01-27 20:03:55 -08003536 mDimension.orig_picture_dx = mCrop.in2_w + JPEG_ENCODER_PADDING;
3537 mDimension.orig_picture_dy = mCrop.in2_h + JPEG_ENCODER_PADDING;
3538 mDimension.thumbnail_width = mCrop.in1_w + JPEG_ENCODER_PADDING;
3539 mDimension.thumbnail_height = mCrop.in1_h + JPEG_ENCODER_PADDING;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003540 }
3541
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003542 if( mUseOverlay && (mOverlay != NULL) ) {
3543 mOverlay->setFd(mPostViewHeap->mHeap->getHeapID());
3544 if( zoomCropInfo.w !=0 && zoomCropInfo.h !=0) {
3545 LOGD(" zoomCropInfo non-zero, setting crop ");
3546 mOverlay->setCrop(zoomCropInfo.x, zoomCropInfo.y,
3547 zoomCropInfo.w, zoomCropInfo.h);
3548 }
3549 LOGD(" Queueing Postview for display ");
3550 mOverlay->queueBuffer((void *)0);
3551 }
Nishant Panditb861be52010-03-02 16:43:49 +05303552 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_RAW_IMAGE))
3553 mDataCallback(CAMERA_MSG_RAW_IMAGE, mDisplayHeap->mBuffers[0],
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003554 mCallbackCookie);
3555 }
3556 else LOGV("Raw-picture callback was canceled--skipping.");
3557
3558 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
3559 mJpegSize = 0;
3560 if (LINK_jpeg_encoder_init()) {
3561 if(native_jpeg_encode()) {
3562 LOGV("receiveRawPicture: X (success)");
3563 return;
3564 }
3565 LOGE("jpeg encoding failed");
3566 }
3567 else LOGE("receiveRawPicture X: jpeg_encoder_init failed.");
3568 }
3569 else LOGV("JPEG callback is NULL, not encoding image.");
3570 deinitRaw();
3571 LOGV("receiveRawPicture: X");
3572}
3573
3574void QualcommCameraHardware::receiveJpegPictureFragment(
3575 uint8_t *buff_ptr, uint32_t buff_size)
3576{
3577 uint32_t remaining = mJpegHeap->mHeap->virtualSize();
3578 remaining -= mJpegSize;
3579 uint8_t *base = (uint8_t *)mJpegHeap->mHeap->base();
3580
3581 LOGV("receiveJpegPictureFragment size %d", buff_size);
3582 if (buff_size > remaining) {
3583 LOGE("receiveJpegPictureFragment: size %d exceeds what "
3584 "remains in JPEG heap (%d), truncating",
3585 buff_size,
3586 remaining);
3587 buff_size = remaining;
3588 }
3589 memcpy(base + mJpegSize, buff_ptr, buff_size);
3590 mJpegSize += buff_size;
3591}
3592
3593void QualcommCameraHardware::receiveJpegPicture(void)
3594{
3595 LOGV("receiveJpegPicture: E image (%d uint8_ts out of %d)",
3596 mJpegSize, mJpegHeap->mBufferSize);
3597 Mutex::Autolock cbLock(&mCallbackLock);
3598
3599 int index = 0, rc;
3600
3601 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
3602 // The reason we do not allocate into mJpegHeap->mBuffers[offset] is
3603 // that the JPEG image's size will probably change from one snapshot
3604 // to the next, so we cannot reuse the MemoryBase object.
3605 sp<MemoryBase> buffer = new
3606 MemoryBase(mJpegHeap->mHeap,
3607 index * mJpegHeap->mBufferSize +
3608 0,
3609 mJpegSize);
3610 mDataCallback(CAMERA_MSG_COMPRESSED_IMAGE, buffer, mCallbackCookie);
3611 buffer = NULL;
3612 }
3613 else LOGV("JPEG callback was cancelled--not delivering image.");
3614
3615 LINK_jpeg_encoder_join();
3616 deinitRaw();
3617
3618 LOGV("receiveJpegPicture: X callback done.");
3619}
3620
3621bool QualcommCameraHardware::previewEnabled()
3622{
3623 return mCameraRunning && mDataCallback && (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME);
3624}
3625
3626status_t QualcommCameraHardware::setPreviewSize(const CameraParameters& params)
3627{
3628 int width, height;
3629 params.getPreviewSize(&width, &height);
3630 LOGV("requested preview size %d x %d", width, height);
3631
3632 // Validate the preview size
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -08003633 for (size_t i = 0; i < previewSizeCount; ++i) {
3634 if (width == supportedPreviewSizes[i].width
3635 && height == supportedPreviewSizes[i].height) {
Sravank64461e82010-02-25 15:10:09 +05303636 // 720p , preview can be 768X432 (currently for 7x30 and 8k
3637 // targets)
3638 if(width == 1280 && height == 720 &&
3639 ((mCurrentTarget == TARGET_MSM7630) || (mCurrentTarget == TARGET_QSD8250))){
3640 LOGD("change preview resolution to 768X432 since recording is in 720p");
3641 mDimension.display_width = preview_sizes[2].width;
3642 mDimension.display_height= preview_sizes[2].height;
3643 }else {
3644 mDimension.display_width = width;
3645 mDimension.display_height= height;
3646 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003647 mParameters.setPreviewSize(width, height);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003648 return NO_ERROR;
3649 }
3650 }
3651 LOGE("Invalid preview size requested: %dx%d", width, height);
3652 return BAD_VALUE;
3653}
3654
3655status_t QualcommCameraHardware::setPictureSize(const CameraParameters& params)
3656{
3657 int width, height;
3658 params.getPictureSize(&width, &height);
3659 LOGV("requested picture size %d x %d", width, height);
3660
3661 // Validate the picture size
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -08003662 for (int i = 0; i < supportedPictureSizesCount; ++i) {
3663 if (width == picture_sizes_ptr[i].width
3664 && height == picture_sizes_ptr[i].height) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003665 mParameters.setPictureSize(width, height);
3666 mDimension.picture_width = width;
3667 mDimension.picture_height = height;
3668 return NO_ERROR;
3669 }
3670 }
Kiran Kumar H Nb49af212010-02-17 15:12:17 -08003671 /* Dimension not among the ones in the list. Check if
3672 * its a valid dimension, if it is, then configure the
3673 * camera accordingly. else reject it.
3674 */
3675 if( isValidDimension(width, height) ) {
3676 mParameters.setPictureSize(width, height);
3677 mDimension.picture_width = width;
3678 mDimension.picture_height = height;
3679 return NO_ERROR;
3680 } else
3681 LOGE("Invalid picture size requested: %dx%d", width, height);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003682 return BAD_VALUE;
3683}
3684
3685status_t QualcommCameraHardware::setJpegQuality(const CameraParameters& params) {
3686 status_t rc = NO_ERROR;
3687 int quality = params.getInt(CameraParameters::KEY_JPEG_QUALITY);
3688 if (quality > 0 && quality <= 100) {
3689 mParameters.set(CameraParameters::KEY_JPEG_QUALITY, quality);
3690 } else {
3691 LOGE("Invalid jpeg quality=%d", quality);
3692 rc = BAD_VALUE;
3693 }
3694
3695 quality = params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY);
3696 if (quality > 0 && quality <= 100) {
3697 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, quality);
3698 } else {
3699 LOGE("Invalid jpeg thumbnail quality=%d", quality);
3700 rc = BAD_VALUE;
3701 }
3702 return rc;
3703}
3704
3705status_t QualcommCameraHardware::setEffect(const CameraParameters& params)
3706{
Apurva Rajguru7360db42010-04-09 16:37:36 -07003707
3708 const char *str_wb = mParameters.get(CameraParameters::KEY_WHITE_BALANCE);
3709 int32_t value_wb = attr_lookup(whitebalance, sizeof(whitebalance) / sizeof(str_map), str_wb);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003710 const char *str = params.get(CameraParameters::KEY_EFFECT);
Apurva Rajguru7360db42010-04-09 16:37:36 -07003711
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003712 if (str != NULL) {
3713 int32_t value = attr_lookup(effects, sizeof(effects) / sizeof(str_map), str);
3714 if (value != NOT_FOUND) {
Mohan Kandra93f1bfb2009-12-15 16:55:33 -08003715 if(!strcmp(sensorType->name, "2mp") && (value != CAMERA_EFFECT_OFF)
3716 &&(value != CAMERA_EFFECT_MONO) && (value != CAMERA_EFFECT_NEGATIVE)
3717 &&(value != CAMERA_EFFECT_SOLARIZE) && (value != CAMERA_EFFECT_SEPIA)) {
3718 LOGE("Special effect parameter is not supported for this sensor");
3719 return NO_ERROR;
3720 }
Apurva Rajguru7360db42010-04-09 16:37:36 -07003721
3722 if(((value == CAMERA_EFFECT_MONO) || (value == CAMERA_EFFECT_NEGATIVE)
3723 || (value == CAMERA_EFFECT_AQUA) || (value == CAMERA_EFFECT_SEPIA))
3724 && (value_wb != CAMERA_WB_AUTO)) {
3725 LOGE("Color Effect value will not be set " \
3726 "when the whitebalance selected is %s", str_wb);
3727 return NO_ERROR;
3728 }
3729 else {
3730 mParameters.set(CameraParameters::KEY_EFFECT, str);
3731 bool ret = native_set_parm(CAMERA_SET_PARM_EFFECT, sizeof(value),
3732 (void *)&value);
3733 return ret ? NO_ERROR : UNKNOWN_ERROR;
3734 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003735 }
3736 }
3737 LOGE("Invalid effect value: %s", (str == NULL) ? "NULL" : str);
3738 return BAD_VALUE;
3739}
3740
Apurva Rajguru55562b02009-12-03 12:25:35 -08003741status_t QualcommCameraHardware::setAutoExposure(const CameraParameters& params)
3742{
Mohan Kandra93f1bfb2009-12-15 16:55:33 -08003743 if(!strcmp(sensorType->name, "2mp")) {
3744 LOGE("Auto Exposure not supported for this sensor");
3745 return NO_ERROR;
3746 }
Apurva Rajguru55562b02009-12-03 12:25:35 -08003747 const char *str = params.get(CameraParameters::KEY_AUTO_EXPOSURE);
3748 if (str != NULL) {
3749 int32_t value = attr_lookup(autoexposure, sizeof(autoexposure) / sizeof(str_map), str);
3750 if (value != NOT_FOUND) {
3751 mParameters.set(CameraParameters::KEY_AUTO_EXPOSURE, str);
3752 bool ret = native_set_parm(CAMERA_SET_PARM_EXPOSURE, sizeof(value),
3753 (void *)&value);
3754 return ret ? NO_ERROR : UNKNOWN_ERROR;
3755 }
3756 }
3757 LOGE("Invalid auto exposure value: %s", (str == NULL) ? "NULL" : str);
3758 return BAD_VALUE;
3759}
3760
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003761status_t QualcommCameraHardware::setSharpness(const CameraParameters& params)
3762{
3763 if(!strcmp(sensorType->name, "2mp")) {
3764 LOGE("Sharpness not supported for this sensor");
3765 return NO_ERROR;
3766 }
3767 int sharpness = params.getInt(CameraParameters::KEY_SHARPNESS);
3768 if((sharpness < CAMERA_MIN_SHARPNESS
3769 || sharpness > CAMERA_MAX_SHARPNESS))
3770 return UNKNOWN_ERROR;
Srinivasan Kannan551fd262010-01-14 17:48:30 -08003771
3772 LOGV("setting sharpness %d", sharpness);
3773 mParameters.set(CameraParameters::KEY_SHARPNESS, sharpness);
3774 bool ret = native_set_parm(CAMERA_SET_PARM_SHARPNESS, sizeof(sharpness),
3775 (void *)&sharpness);
3776 return ret ? NO_ERROR : UNKNOWN_ERROR;
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003777}
3778
3779status_t QualcommCameraHardware::setContrast(const CameraParameters& params)
3780{
3781 if(!strcmp(sensorType->name, "2mp")) {
3782 LOGE("Contrast not supported for this sensor");
3783 return NO_ERROR;
3784 }
3785 int contrast = params.getInt(CameraParameters::KEY_CONTRAST);
3786 if((contrast < CAMERA_MIN_CONTRAST)
3787 || (contrast > CAMERA_MAX_CONTRAST))
3788 return UNKNOWN_ERROR;
Srinivasan Kannan551fd262010-01-14 17:48:30 -08003789
3790 LOGV("setting contrast %d", contrast);
3791 mParameters.set(CameraParameters::KEY_CONTRAST, contrast);
3792 bool ret = native_set_parm(CAMERA_SET_PARM_CONTRAST, sizeof(contrast),
3793 (void *)&contrast);
3794 return ret ? NO_ERROR : UNKNOWN_ERROR;
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003795}
3796
3797status_t QualcommCameraHardware::setSaturation(const CameraParameters& params)
3798{
3799 if(!strcmp(sensorType->name, "2mp")) {
3800 LOGE("Saturation not supported for this sensor");
3801 return NO_ERROR;
3802 }
Srinivasan Kannan551fd262010-01-14 17:48:30 -08003803
Kiran Kumar H Nf87cf862010-01-27 14:34:34 -08003804 const char *str = params.get(CameraParameters::KEY_EFFECT);
3805 int32_t value = attr_lookup(effects, sizeof(effects) / sizeof(str_map), str);
3806
3807 if( (value != CAMERA_EFFECT_MONO) && (value != CAMERA_EFFECT_NEGATIVE)
3808 && (value != CAMERA_EFFECT_AQUA) && (value != CAMERA_EFFECT_SEPIA)) {
3809
3810 int saturation = params.getInt(CameraParameters::KEY_SATURATION);
3811 if((saturation < CAMERA_MIN_SATURATION)
3812 || (saturation > CAMERA_MAX_SATURATION))
3813 return UNKNOWN_ERROR;
3814
3815 LOGV("setting saturation %d", saturation);
3816 mParameters.set(CameraParameters::KEY_SATURATION, saturation);
3817 bool ret = native_set_parm(CAMERA_SET_PARM_SATURATION, sizeof(saturation),
3818 (void *)&saturation);
3819 return ret ? NO_ERROR : UNKNOWN_ERROR;
3820 } else {
3821 LOGE(" Saturation value will not be set " \
3822 "when the effect selected is %s", str);
3823 return NO_ERROR;
3824 }
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003825}
3826
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303827status_t QualcommCameraHardware::setBrightness(const CameraParameters& params) {
3828 int brightness = params.getInt("luma-adaptation");
3829 if (mBrightness != brightness) {
3830 LOGV(" new brightness value : %d ", brightness);
3831 mBrightness = brightness;
3832
3833 bool ret = native_set_parm(CAMERA_SET_PARM_BRIGHTNESS, sizeof(mBrightness),
3834 (void *)&mBrightness);
3835 return ret ? NO_ERROR : UNKNOWN_ERROR;
3836 } else {
3837 return NO_ERROR;
3838 }
3839}
3840
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003841status_t QualcommCameraHardware::setWhiteBalance(const CameraParameters& params)
3842{
Apurva Rajguru7360db42010-04-09 16:37:36 -07003843
3844 const char *str_effect = mParameters.get(CameraParameters::KEY_EFFECT);
3845 int32_t value_effect = attr_lookup(effects, sizeof(effects) / sizeof(str_map), str_effect);
3846
3847 if( (value_effect != CAMERA_EFFECT_MONO) && (value_effect != CAMERA_EFFECT_NEGATIVE)
3848 && (value_effect != CAMERA_EFFECT_AQUA) && (value_effect != CAMERA_EFFECT_SEPIA)) {
3849 const char *str = params.get(CameraParameters::KEY_WHITE_BALANCE);
3850
3851 if (str != NULL) {
3852 int32_t value = attr_lookup(whitebalance, sizeof(whitebalance) / sizeof(str_map), str);
3853 if (value != NOT_FOUND) {
3854 mParameters.set(CameraParameters::KEY_WHITE_BALANCE, str);
3855 bool ret = native_set_parm(CAMERA_SET_PARM_WB, sizeof(value),
3856 (void *)&value);
3857 return ret ? NO_ERROR : UNKNOWN_ERROR;
3858 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003859 }
Apurva Rajguru7360db42010-04-09 16:37:36 -07003860 LOGE("Invalid whitebalance value: %s", (str == NULL) ? "NULL" : str);
3861 return BAD_VALUE;
3862 } else {
3863 LOGE("Whitebalance value will not be set " \
3864 "when the effect selected is %s", str_effect);
3865 return NO_ERROR;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003866 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003867}
3868
3869status_t QualcommCameraHardware::setFlash(const CameraParameters& params)
3870{
3871 if (!mSensorInfo.flash_enabled) {
3872 LOGV("%s: flash not supported", __FUNCTION__);
3873 return NO_ERROR;
3874 }
3875
3876 const char *str = params.get(CameraParameters::KEY_FLASH_MODE);
3877 if (str != NULL) {
3878 int32_t value = attr_lookup(flash, sizeof(flash) / sizeof(str_map), str);
3879 if (value != NOT_FOUND) {
3880 mParameters.set(CameraParameters::KEY_FLASH_MODE, str);
3881 bool ret = native_set_parm(CAMERA_SET_PARM_LED_MODE,
3882 sizeof(value), (void *)&value);
3883 return ret ? NO_ERROR : UNKNOWN_ERROR;
3884 }
3885 }
3886 LOGE("Invalid flash mode value: %s", (str == NULL) ? "NULL" : str);
3887 return BAD_VALUE;
3888}
3889
3890status_t QualcommCameraHardware::setAntibanding(const CameraParameters& params)
3891{
Srinivasan Kannan2229d272010-01-05 14:58:28 -08003892 if(!strcmp(sensorType->name, "2mp")) {
3893 LOGE("Parameter AntiBanding is not supported for this sensor");
3894 return NO_ERROR;
3895 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003896 const char *str = params.get(CameraParameters::KEY_ANTIBANDING);
3897 if (str != NULL) {
3898 int value = (camera_antibanding_type)attr_lookup(
3899 antibanding, sizeof(antibanding) / sizeof(str_map), str);
3900 if (value != NOT_FOUND) {
3901 camera_antibanding_type temp = (camera_antibanding_type) value;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003902 mParameters.set(CameraParameters::KEY_ANTIBANDING, str);
Srinivasan Kannan2229d272010-01-05 14:58:28 -08003903 bool ret;
3904 if (temp == CAMERA_ANTIBANDING_AUTO) {
3905 ret = native_set_parm(CAMERA_ENABLE_AFD,
3906 0, NULL);
3907 } else {
3908 ret = native_set_parm(CAMERA_SET_PARM_ANTIBANDING,
3909 sizeof(camera_antibanding_type), (void *)&temp);
3910 }
3911 return ret ? NO_ERROR : UNKNOWN_ERROR;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003912 }
3913 }
3914 LOGE("Invalid antibanding value: %s", (str == NULL) ? "NULL" : str);
3915 return BAD_VALUE;
3916}
3917
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303918status_t QualcommCameraHardware::setLensshadeValue(const CameraParameters& params)
3919{
Mohan Kandra93f1bfb2009-12-15 16:55:33 -08003920 if(!strcmp(sensorType->name, "2mp")) {
3921 LOGE("Parameter Rolloff is not supported for this sensor");
3922 return NO_ERROR;
3923 }
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303924 const char *str = params.get(CameraParameters::KEY_LENSSHADE);
3925 if (str != NULL) {
3926 int value = attr_lookup(lensshade,
3927 sizeof(lensshade) / sizeof(str_map), str);
3928 if (value != NOT_FOUND) {
3929 int8_t temp = (int8_t)value;
3930 mParameters.set(CameraParameters::KEY_LENSSHADE, str);
3931 native_set_parm(CAMERA_SET_PARM_ROLLOFF, sizeof(int8_t), (void *)&temp);
3932 return NO_ERROR;
3933 }
3934 }
3935 LOGE("Invalid lensShade value: %s", (str == NULL) ? "NULL" : str);
3936 return BAD_VALUE;
3937}
3938
3939status_t QualcommCameraHardware::setISOValue(const CameraParameters& params) {
Apurva Rajguruf12d9d22010-04-05 16:47:12 -07003940 int8_t temp_hjr;
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303941 const char *str = params.get(CameraParameters::KEY_ISO_MODE);
3942 if (str != NULL) {
3943 int value = (camera_iso_mode_type)attr_lookup(
3944 iso, sizeof(iso) / sizeof(str_map), str);
3945 if (value != NOT_FOUND) {
3946 camera_iso_mode_type temp = (camera_iso_mode_type) value;
Apurva Rajguruf12d9d22010-04-05 16:47:12 -07003947 if (value == CAMERA_ISO_DEBLUR) {
3948 temp_hjr = true;
3949 native_set_parm(CAMERA_SET_PARM_HJR, sizeof(int8_t), (void*)&temp_hjr);
3950 mHJR = value;
3951 }
3952 else {
3953 if (mHJR == CAMERA_ISO_DEBLUR) {
3954 temp_hjr = false;
3955 native_set_parm(CAMERA_SET_PARM_HJR, sizeof(int8_t), (void*)&temp_hjr);
3956 mHJR = value;
3957 }
3958 }
3959
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303960 mParameters.set(CameraParameters::KEY_ISO_MODE, str);
3961 native_set_parm(CAMERA_SET_PARM_ISO, sizeof(camera_iso_mode_type), (void *)&temp);
3962 return NO_ERROR;
3963 }
3964 }
3965 LOGE("Invalid Iso value: %s", (str == NULL) ? "NULL" : str);
3966 return BAD_VALUE;
3967}
3968
3969
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003970status_t QualcommCameraHardware::setGpsLocation(const CameraParameters& params)
3971{
3972 const char *latitude = params.get(CameraParameters::KEY_GPS_LATITUDE);
3973 if (latitude) {
3974 mParameters.set(CameraParameters::KEY_GPS_LATITUDE, latitude);
3975 }
3976
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08003977 const char *latitudeRef = params.get(CameraParameters::KEY_GPS_LATITUDE_REF);
3978 if (latitudeRef) {
3979 mParameters.set(CameraParameters::KEY_GPS_LATITUDE_REF, latitudeRef);
3980 }
3981
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003982 const char *longitude = params.get(CameraParameters::KEY_GPS_LONGITUDE);
3983 if (longitude) {
3984 mParameters.set(CameraParameters::KEY_GPS_LONGITUDE, longitude);
3985 }
3986
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08003987 const char *longitudeRef = params.get(CameraParameters::KEY_GPS_LONGITUDE_REF);
3988 if (longitudeRef) {
3989 mParameters.set(CameraParameters::KEY_GPS_LONGITUDE_REF, longitudeRef);
3990 }
3991
3992 const char *altitudeRef = params.get(CameraParameters::KEY_GPS_ALTITUDE_REF);
3993 if (altitudeRef) {
3994 mParameters.set(CameraParameters::KEY_GPS_ALTITUDE_REF, altitudeRef);
3995 }
3996
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003997 const char *altitude = params.get(CameraParameters::KEY_GPS_ALTITUDE);
3998 if (altitude) {
3999 mParameters.set(CameraParameters::KEY_GPS_ALTITUDE, altitude);
4000 }
4001
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08004002 const char *status = params.get(CameraParameters::KEY_GPS_STATUS);
4003 if (status) {
4004 mParameters.set(CameraParameters::KEY_GPS_STATUS, status);
4005 }
4006
4007 const char *dateTime = params.get(CameraParameters::KEY_EXIF_DATETIME);
4008 if (dateTime) {
4009 mParameters.set(CameraParameters::KEY_EXIF_DATETIME, dateTime);
4010 }
4011
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004012 const char *timestamp = params.get(CameraParameters::KEY_GPS_TIMESTAMP);
4013 if (timestamp) {
4014 mParameters.set(CameraParameters::KEY_GPS_TIMESTAMP, timestamp);
4015 }
4016 return NO_ERROR;
4017}
4018
4019status_t QualcommCameraHardware::setRotation(const CameraParameters& params)
4020{
4021 status_t rc = NO_ERROR;
4022 int rotation = params.getInt(CameraParameters::KEY_ROTATION);
4023 if (rotation != NOT_FOUND) {
4024 if (rotation == 0 || rotation == 90 || rotation == 180
4025 || rotation == 270) {
4026 mParameters.set(CameraParameters::KEY_ROTATION, rotation);
4027 } else {
4028 LOGE("Invalid rotation value: %d", rotation);
4029 rc = BAD_VALUE;
4030 }
4031 }
4032 return rc;
4033}
4034
4035status_t QualcommCameraHardware::setZoom(const CameraParameters& params)
4036{
4037 status_t rc = NO_ERROR;
4038 // No matter how many different zoom values the driver can provide, HAL
4039 // provides applictations the same number of zoom levels. The maximum driver
4040 // zoom value depends on sensor output (VFE input) and preview size (VFE
4041 // output) because VFE can only crop and cannot upscale. If the preview size
4042 // is bigger, the maximum zoom ratio is smaller. However, we want the
4043 // zoom ratio of each zoom level is always the same whatever the preview
4044 // size is. Ex: zoom level 1 is always 1.2x, zoom level 2 is 1.44x, etc. So,
4045 // we need to have a fixed maximum zoom value and do read it from the
4046 // driver.
Mohan Kandra284966d2010-01-05 13:39:15 -08004047 static const int ZOOM_STEP = 1;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004048 int32_t zoom_level = params.getInt("zoom");
4049
Mohan Kandra284966d2010-01-05 13:39:15 -08004050 LOGV("Set zoom=%d", zoom_level);
4051 if(zoom_level >= 0 && zoom_level <= mMaxZoom) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004052 mParameters.set("zoom", zoom_level);
4053 int32_t zoom_value = ZOOM_STEP * zoom_level;
4054 bool ret = native_set_parm(CAMERA_SET_PARM_ZOOM,
4055 sizeof(zoom_value), (void *)&zoom_value);
4056 rc = ret ? NO_ERROR : UNKNOWN_ERROR;
4057 } else {
4058 rc = BAD_VALUE;
4059 }
4060
4061 return rc;
4062}
4063
4064status_t QualcommCameraHardware::setFocusMode(const CameraParameters& params)
4065{
4066 const char *str = params.get(CameraParameters::KEY_FOCUS_MODE);
4067 if (str != NULL) {
4068 int32_t value = attr_lookup(focus_modes,
4069 sizeof(focus_modes) / sizeof(str_map), str);
4070 if (value != NOT_FOUND) {
4071 mParameters.set(CameraParameters::KEY_FOCUS_MODE, str);
4072 // Focus step is reset to infinity when preview is started. We do
4073 // not need to do anything now.
4074 return NO_ERROR;
4075 }
4076 }
4077 LOGE("Invalid focus mode value: %s", (str == NULL) ? "NULL" : str);
4078 return BAD_VALUE;
4079}
4080
4081status_t QualcommCameraHardware::setOrientation(const CameraParameters& params)
4082{
4083 const char *str = params.get("orientation");
4084
4085 if (str != NULL) {
4086 if (strcmp(str, "portrait") == 0 || strcmp(str, "landscape") == 0) {
4087 // Camera service needs this to decide if the preview frames and raw
4088 // pictures should be rotated.
4089 mParameters.set("orientation", str);
4090 } else {
4091 LOGE("Invalid orientation value: %s", str);
4092 return BAD_VALUE;
4093 }
4094 }
4095 return NO_ERROR;
4096}
4097
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08004098status_t QualcommCameraHardware::setPictureFormat(const CameraParameters& params)
4099{
4100 const char * str = params.get(CameraParameters::KEY_PICTURE_FORMAT);
4101
4102 if(str != NULL){
4103 int32_t value = attr_lookup(picture_formats,
4104 sizeof(picture_formats) / sizeof(str_map), str);
4105 if(value != NOT_FOUND){
4106 mParameters.set(CameraParameters::KEY_PICTURE_FORMAT, str);
4107 } else {
4108 LOGE("Invalid Picture Format value: %s", str);
4109 return BAD_VALUE;
4110 }
4111 }
4112 return NO_ERROR;
4113}
4114
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004115QualcommCameraHardware::MemPool::MemPool(int buffer_size, int num_buffers,
4116 int frame_size,
4117 const char *name) :
4118 mBufferSize(buffer_size),
4119 mNumBuffers(num_buffers),
4120 mFrameSize(frame_size),
4121 mBuffers(NULL), mName(name)
4122{
4123 int page_size_minus_1 = getpagesize() - 1;
4124 mAlignedBufferSize = (buffer_size + page_size_minus_1) & (~page_size_minus_1);
4125}
4126
4127void QualcommCameraHardware::MemPool::completeInitialization()
4128{
4129 // If we do not know how big the frame will be, we wait to allocate
4130 // the buffers describing the individual frames until we do know their
4131 // size.
4132
4133 if (mFrameSize > 0) {
4134 mBuffers = new sp<MemoryBase>[mNumBuffers];
4135 for (int i = 0; i < mNumBuffers; i++) {
4136 mBuffers[i] = new
4137 MemoryBase(mHeap,
4138 i * mAlignedBufferSize,
4139 mFrameSize);
4140 }
4141 }
4142}
4143
4144QualcommCameraHardware::AshmemPool::AshmemPool(int buffer_size, int num_buffers,
4145 int frame_size,
4146 const char *name) :
4147 QualcommCameraHardware::MemPool(buffer_size,
4148 num_buffers,
4149 frame_size,
4150 name)
4151{
4152 LOGV("constructing MemPool %s backed by ashmem: "
4153 "%d frames @ %d uint8_ts, "
4154 "buffer size %d",
4155 mName,
4156 num_buffers, frame_size, buffer_size);
4157
4158 int page_mask = getpagesize() - 1;
4159 int ashmem_size = buffer_size * num_buffers;
4160 ashmem_size += page_mask;
4161 ashmem_size &= ~page_mask;
4162
4163 mHeap = new MemoryHeapBase(ashmem_size);
4164
4165 completeInitialization();
4166}
4167
4168static bool register_buf(int camfd,
4169 int size,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08004170 int frame_size,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004171 int pmempreviewfd,
4172 uint32_t offset,
4173 uint8_t *buf,
4174 int pmem_type,
4175 bool vfe_can_write,
4176 bool register_buffer = true);
4177
4178QualcommCameraHardware::PmemPool::PmemPool(const char *pmem_pool,
4179 int flags,
4180 int camera_control_fd,
4181 int pmem_type,
4182 int buffer_size, int num_buffers,
4183 int frame_size,
4184 const char *name) :
4185 QualcommCameraHardware::MemPool(buffer_size,
4186 num_buffers,
4187 frame_size,
4188 name),
4189 mPmemType(pmem_type),
4190 mCameraControlFd(dup(camera_control_fd))
4191{
4192 LOGV("constructing MemPool %s backed by pmem pool %s: "
4193 "%d frames @ %d bytes, buffer size %d",
4194 mName,
4195 pmem_pool, num_buffers, frame_size,
4196 buffer_size);
4197
4198 LOGV("%s: duplicating control fd %d --> %d",
4199 __FUNCTION__,
4200 camera_control_fd, mCameraControlFd);
4201
4202 // Make a new mmap'ed heap that can be shared across processes.
4203 // mAlignedBufferSize is already in 4k aligned. (do we need total size necessary to be in power of 2??)
4204 mAlignedSize = mAlignedBufferSize * num_buffers;
4205
4206 sp<MemoryHeapBase> masterHeap =
4207 new MemoryHeapBase(pmem_pool, mAlignedSize, flags);
4208
4209 if (masterHeap->getHeapID() < 0) {
4210 LOGE("failed to construct master heap for pmem pool %s", pmem_pool);
4211 masterHeap.clear();
4212 return;
4213 }
4214
4215 sp<MemoryHeapPmem> pmemHeap = new MemoryHeapPmem(masterHeap, flags);
4216 if (pmemHeap->getHeapID() >= 0) {
4217 pmemHeap->slap();
4218 masterHeap.clear();
4219 mHeap = pmemHeap;
4220 pmemHeap.clear();
4221
4222 mFd = mHeap->getHeapID();
4223 if (::ioctl(mFd, PMEM_GET_SIZE, &mSize)) {
4224 LOGE("pmem pool %s ioctl(PMEM_GET_SIZE) error %s (%d)",
4225 pmem_pool,
4226 ::strerror(errno), errno);
4227 mHeap.clear();
4228 return;
4229 }
4230
4231 LOGV("pmem pool %s ioctl(fd = %d, PMEM_GET_SIZE) is %ld",
4232 pmem_pool,
4233 mFd,
4234 mSize.len);
Mohan Kandra284966d2010-01-05 13:39:15 -08004235 LOGD("mBufferSize=%d, mAlignedBufferSize=%d\n", mBufferSize, mAlignedBufferSize);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004236 // Unregister preview buffers with the camera drivers. Allow the VFE to write
4237 // to all preview buffers except for the last one.
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08004238 // Only Register the preview, snapshot and thumbnail buffers with the kernel.
Mohan Kandrad9efed92010-01-15 19:08:39 -08004239 if( (strcmp("postview", mName) != 0) ){
4240 int num_buf = num_buffers;
4241 if(!strcmp("preview", mName)) num_buf = kPreviewBufferCount;
Brian Steuerb62adbd2010-02-02 14:47:08 -08004242 LOGD("num_buffers = %d", num_buf);
Mohan Kandrad9efed92010-01-15 19:08:39 -08004243 for (int cnt = 0; cnt < num_buf; ++cnt) {
Sravankb4f5f1c2010-01-21 11:06:17 +05304244 int active = 1;
4245 if(pmem_type == MSM_PMEM_VIDEO){
4246 active = (cnt<ACTIVE_VIDEO_BUFFERS);
4247 LOGV(" pmempool creating video buffers : active %d ", active);
4248 }
4249 else if (pmem_type == MSM_PMEM_PREVIEW){
4250 active = (cnt < (num_buf-1));
4251 }
Mohan Kandra284966d2010-01-05 13:39:15 -08004252 register_buf(mCameraControlFd,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004253 mBufferSize,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08004254 mFrameSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004255 mHeap->getHeapID(),
4256 mAlignedBufferSize * cnt,
4257 (uint8_t *)mHeap->base() + mAlignedBufferSize * cnt,
4258 pmem_type,
Sravankb4f5f1c2010-01-21 11:06:17 +05304259 active);
Mohan Kandra284966d2010-01-05 13:39:15 -08004260 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004261 }
4262
4263 completeInitialization();
4264 }
4265 else LOGE("pmem pool %s error: could not create master heap!",
4266 pmem_pool);
4267}
4268
4269QualcommCameraHardware::PmemPool::~PmemPool()
4270{
4271 LOGV("%s: %s E", __FUNCTION__, mName);
4272 if (mHeap != NULL) {
4273 // Unregister preview buffers with the camera drivers.
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08004274 // Only Unregister the preview, snapshot and thumbnail
4275 // buffers with the kernel.
Mohan Kandrad9efed92010-01-15 19:08:39 -08004276 if( (strcmp("postview", mName) != 0) ){
4277 int num_buffers = mNumBuffers;
4278 if(!strcmp("preview", mName)) num_buffers = kPreviewBufferCount;
4279 for (int cnt = 0; cnt < num_buffers; ++cnt) {
Mohan Kandra284966d2010-01-05 13:39:15 -08004280 register_buf(mCameraControlFd,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004281 mBufferSize,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08004282 mFrameSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004283 mHeap->getHeapID(),
4284 mAlignedBufferSize * cnt,
4285 (uint8_t *)mHeap->base() + mAlignedBufferSize * cnt,
4286 mPmemType,
4287 false,
4288 false /* unregister */);
Mohan Kandra284966d2010-01-05 13:39:15 -08004289 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004290 }
4291 }
4292 LOGV("destroying PmemPool %s: closing control fd %d",
4293 mName,
4294 mCameraControlFd);
4295 close(mCameraControlFd);
4296 LOGV("%s: %s X", __FUNCTION__, mName);
4297}
4298
4299QualcommCameraHardware::MemPool::~MemPool()
4300{
4301 LOGV("destroying MemPool %s", mName);
4302 if (mFrameSize > 0)
4303 delete [] mBuffers;
4304 mHeap.clear();
4305 LOGV("destroying MemPool %s completed", mName);
4306}
4307
4308static bool register_buf(int camfd,
4309 int size,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08004310 int frame_size,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004311 int pmempreviewfd,
4312 uint32_t offset,
4313 uint8_t *buf,
4314 int pmem_type,
4315 bool vfe_can_write,
4316 bool register_buffer)
4317{
4318 struct msm_pmem_info pmemBuf;
4319
4320 pmemBuf.type = pmem_type;
4321 pmemBuf.fd = pmempreviewfd;
4322 pmemBuf.offset = offset;
4323 pmemBuf.len = size;
4324 pmemBuf.vaddr = buf;
4325 pmemBuf.y_off = 0;
Srinivasan Kannanb36a4fe2010-01-29 19:34:09 -08004326
4327 if(pmem_type == MSM_PMEM_RAW_MAINIMG)
4328 pmemBuf.cbcr_off = 0;
4329 else
4330 pmemBuf.cbcr_off = PAD_TO_WORD(frame_size * 2 / 3);
4331
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004332 pmemBuf.active = vfe_can_write;
4333
4334 LOGV("register_buf: camfd = %d, reg = %d buffer = %p",
4335 camfd, !register_buffer, buf);
4336 if (ioctl(camfd,
4337 register_buffer ?
4338 MSM_CAM_IOCTL_REGISTER_PMEM :
4339 MSM_CAM_IOCTL_UNREGISTER_PMEM,
4340 &pmemBuf) < 0) {
4341 LOGE("register_buf: MSM_CAM_IOCTL_(UN)REGISTER_PMEM fd %d error %s",
4342 camfd,
4343 strerror(errno));
4344 return false;
4345 }
4346 return true;
4347}
4348
4349status_t QualcommCameraHardware::MemPool::dump(int fd, const Vector<String16>& args) const
4350{
4351 const size_t SIZE = 256;
4352 char buffer[SIZE];
4353 String8 result;
4354 snprintf(buffer, 255, "QualcommCameraHardware::AshmemPool::dump\n");
4355 result.append(buffer);
4356 if (mName) {
4357 snprintf(buffer, 255, "mem pool name (%s)\n", mName);
4358 result.append(buffer);
4359 }
4360 if (mHeap != 0) {
4361 snprintf(buffer, 255, "heap base(%p), size(%d), flags(%d), device(%s)\n",
4362 mHeap->getBase(), mHeap->getSize(),
4363 mHeap->getFlags(), mHeap->getDevice());
4364 result.append(buffer);
4365 }
4366 snprintf(buffer, 255,
4367 "buffer size (%d), number of buffers (%d), frame size(%d)",
4368 mBufferSize, mNumBuffers, mFrameSize);
4369 result.append(buffer);
4370 write(fd, result.string(), result.size());
4371 return NO_ERROR;
4372}
4373
4374static void receive_camframe_callback(struct msm_frame *frame)
4375{
4376 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4377 if (obj != 0) {
4378 obj->receivePreviewFrame(frame);
4379 }
4380}
4381
4382static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size)
4383{
4384 LOGV("receive_jpeg_fragment_callback E");
4385 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4386 if (obj != 0) {
4387 obj->receiveJpegPictureFragment(buff_ptr, buff_size);
4388 }
4389 LOGV("receive_jpeg_fragment_callback X");
4390}
4391
4392static void receive_jpeg_callback(jpeg_event_t status)
4393{
4394 LOGV("receive_jpeg_callback E (completion status %d)", status);
4395 if (status == JPEG_EVENT_DONE) {
4396 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4397 if (obj != 0) {
4398 obj->receiveJpegPicture();
4399 }
4400 }
4401 LOGV("receive_jpeg_callback X");
4402}
Sravankb4f5f1c2010-01-21 11:06:17 +05304403// 720p : video frame calbback from camframe
4404static void receive_camframe_video_callback(struct msm_frame *frame)
4405{
4406 LOGV("receive_camframe_video_callback E");
4407 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4408 if (obj != 0) {
4409 obj->receiveRecordingFrame(frame);
4410 }
4411 LOGV("receive_camframe_video_callback X");
4412}
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004413
4414void QualcommCameraHardware::setCallbacks(notify_callback notify_cb,
4415 data_callback data_cb,
4416 data_callback_timestamp data_cb_timestamp,
4417 void* user)
4418{
4419 Mutex::Autolock lock(mLock);
4420 mNotifyCallback = notify_cb;
4421 mDataCallback = data_cb;
4422 mDataCallbackTimestamp = data_cb_timestamp;
4423 mCallbackCookie = user;
4424}
4425
4426void QualcommCameraHardware::enableMsgType(int32_t msgType)
4427{
4428 Mutex::Autolock lock(mLock);
4429 mMsgEnabled |= msgType;
4430}
4431
4432void QualcommCameraHardware::disableMsgType(int32_t msgType)
4433{
4434 Mutex::Autolock lock(mLock);
4435 mMsgEnabled &= ~msgType;
4436}
4437
4438bool QualcommCameraHardware::msgTypeEnabled(int32_t msgType)
4439{
4440 return (mMsgEnabled & msgType);
4441}
4442
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08004443bool QualcommCameraHardware::useOverlay(void)
4444{
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08004445 if( mCurrentTarget == TARGET_MSM7630 ) {
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08004446 /* Only 7x30 supports Overlay */
4447 mUseOverlay = TRUE;
4448 } else
4449 mUseOverlay = FALSE;
4450
4451 LOGV(" Using Overlay : %s ", mUseOverlay ? "YES" : "NO" );
4452 return mUseOverlay;
4453}
4454
4455status_t QualcommCameraHardware::setOverlay(const sp<Overlay> &Overlay)
4456{
4457 if( Overlay != NULL) {
4458 LOGV(" Valid overlay object ");
4459 mOverlayLock.lock();
4460 mOverlay = Overlay;
4461 mOverlayLock.unlock();
4462 } else {
4463 LOGE(" Overlay object NULL. returning ");
Mohan Kandrad9efed92010-01-15 19:08:39 -08004464 mOverlay = NULL;
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08004465 return UNKNOWN_ERROR;
4466 }
4467 return NO_ERROR;
4468}
Kiran Kumar H N215cac42009-12-08 01:53:46 -08004469
4470void QualcommCameraHardware::receive_camframetimeout(void) {
4471 LOGV("receive_camframetimeout: E");
4472 Mutex::Autolock l(&mCamframeTimeoutLock);
Kiran Kumar H N7ac84e32010-02-01 10:58:47 -08004473 LOGD(" Camframe timed out. Not receiving any frames from camera driver ");
Kiran Kumar H N215cac42009-12-08 01:53:46 -08004474 camframe_timeout_flag = TRUE;
4475 LOGV("receive_camframetimeout: X");
4476}
4477
4478static void receive_camframetimeout_callback(void) {
4479 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4480 if (obj != 0) {
4481 obj->receive_camframetimeout();
4482 }
4483}
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08004484
4485void QualcommCameraHardware::storePreviewFrameForPostview(void) {
4486 LOGV(" storePreviewFrameForPostview : E ");
4487
4488 /* Since there is restriction on the maximum overlay dimensions
4489 * that can be created, we use the last preview frame as postview
4490 * for 7x30. */
4491 LOGV(" Copying the preview buffer to postview buffer %d ",
4492 mPreviewFrameSize);
4493 if( mPostViewHeap != NULL && mLastQueuedFrame != NULL) {
4494 memcpy(mPostViewHeap->mHeap->base(),
4495 (uint8_t *)mLastQueuedFrame, mPreviewFrameSize );
4496 } else
4497 LOGE(" Failed to store Preview frame. No Postview ");
4498
4499 LOGV(" storePreviewFrameForPostview : X ");
4500}
Kiran Kumar H Nb49af212010-02-17 15:12:17 -08004501
4502bool QualcommCameraHardware::isValidDimension(int width, int height) {
4503 bool retVal = FALSE;
4504 /* This function checks if a given resolution is valid or not.
4505 * A particular resolution is considered valid if it satisfies
4506 * the following conditions:
4507 * 1. width & height should be multiple of 16.
4508 * 2. width & height should be less than/equal to the dimensions
4509 * supported by the camera sensor.
4510 * 3. the aspect ratio is a valid aspect ratio and is among the
4511 * commonly used aspect ratio as determined by the thumbnail_sizes
4512 * data structure.
4513 */
4514
4515 if( (width == CEILING16(width)) && (height == CEILING16(height))
4516 && (width <= sensorType->max_supported_snapshot_width)
4517 && (height <= sensorType->max_supported_snapshot_height) )
4518 {
4519 uint32_t pictureAspectRatio = (uint32_t)((width * Q12)/height);
4520 for(int i = 0; i < THUMBNAIL_SIZE_COUNT; i++ ) {
4521 if(thumbnail_sizes[i].aspect_ratio == pictureAspectRatio) {
4522 retVal = TRUE;
4523 break;
4524 }
4525 }
4526 }
4527 return retVal;
4528}
Kiran Kumar H N4dd45a62010-02-26 15:56:33 -08004529status_t QualcommCameraHardware::getBufferInfo(sp<IMemory>& Frame, size_t *alignedSize) {
4530 status_t ret;
4531 LOGV(" getBufferInfo : E ");
Vamshidhar Kondrab362be62010-03-22 19:07:29 +05304532 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250) )
4533 {
4534 if( mRecordHeap != NULL){
4535 LOGV(" Setting valid buffer information ");
4536 Frame = mRecordHeap->mBuffers[0];
4537 if( alignedSize != NULL) {
4538 *alignedSize = mRecordHeap->mAlignedBufferSize;
4539 LOGV(" HAL : alignedSize = %d ", *alignedSize);
4540 ret = NO_ERROR;
4541 } else {
4542 LOGE(" HAL : alignedSize is NULL. Cannot update alignedSize ");
4543 ret = UNKNOWN_ERROR;
4544 }
Kiran Kumar H N4dd45a62010-02-26 15:56:33 -08004545 } else {
Vamshidhar Kondrab362be62010-03-22 19:07:29 +05304546 LOGE(" RecordHeap is null. Buffer information wont be updated ");
4547 Frame = NULL;
4548 ret = UNKNOWN_ERROR;
4549 }
Kiran Kumar H N4dd45a62010-02-26 15:56:33 -08004550 } else {
Vamshidhar Kondrab362be62010-03-22 19:07:29 +05304551 if(mPreviewHeap != NULL) {
4552 LOGV(" Setting valid buffer information ");
4553 Frame = mPreviewHeap->mBuffers[0];
4554 if( alignedSize != NULL) {
4555 *alignedSize = mPreviewHeap->mAlignedBufferSize;
4556 LOGV(" HAL : alignedSize = %d ", *alignedSize);
4557 ret = NO_ERROR;
4558 } else {
4559 LOGE(" HAL : alignedSize is NULL. Cannot update alignedSize ");
4560 ret = UNKNOWN_ERROR;
4561 }
4562 } else {
4563 LOGE(" PreviewHeap is null. Buffer information wont be updated ");
4564 Frame = NULL;
4565 ret = UNKNOWN_ERROR;
4566 }
Kiran Kumar H N4dd45a62010-02-26 15:56:33 -08004567 }
4568 LOGV(" getBufferInfo : X ");
4569 return ret;
4570}
Kiran Kumar H Nb49af212010-02-17 15:12:17 -08004571
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004572}; // namespace android