blob: 63d151ff723a5bbf9889fc31df4e7bf480792ee9 [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;
Srinivasan Kannan71229622009-12-04 12:05:58 -0800604};
605
606static SensorType sensorTypes[] = {
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800607 { "5mp", 2608, 1960, true, 2592, 1944 },
608 { "3mp", 2064, 1544, false, 2048, 1536 },
609 { "2mp", 3200, 1200, false, 1600, 1200 } };
610
Srinivasan Kannan71229622009-12-04 12:05:58 -0800611
612static SensorType * sensorType;
613
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800614static const str_map picture_formats[] = {
615 {CameraParameters::PIXEL_FORMAT_JPEG, PICTURE_FORMAT_JPEG},
616 {CameraParameters::PIXEL_FORMAT_RAW, PICTURE_FORMAT_RAW}
617};
618
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800619static bool parameter_string_initialized = false;
620static String8 preview_size_values;
621static String8 picture_size_values;
622static String8 antibanding_values;
623static String8 effect_values;
Apurva Rajguru55562b02009-12-03 12:25:35 -0800624static String8 autoexposure_values;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800625static String8 whitebalance_values;
626static String8 flash_values;
627static String8 focus_mode_values;
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530628static String8 iso_values;
629static String8 lensshade_values;
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800630static String8 picture_format_values;
631
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800632
633static String8 create_sizes_str(const camera_size_type *sizes, int len) {
634 String8 str;
635 char buffer[32];
636
637 if (len > 0) {
638 sprintf(buffer, "%dx%d", sizes[0].width, sizes[0].height);
639 str.append(buffer);
640 }
641 for (int i = 1; i < len; i++) {
642 sprintf(buffer, ",%dx%d", sizes[i].width, sizes[i].height);
643 str.append(buffer);
644 }
645 return str;
646}
647
648static String8 create_values_str(const str_map *values, int len) {
649 String8 str;
650
651 if (len > 0) {
652 str.append(values[0].desc);
653 }
654 for (int i = 1; i < len; i++) {
655 str.append(",");
656 str.append(values[i].desc);
657 }
658 return str;
659}
660
Sravankb4f5f1c2010-01-21 11:06:17 +0530661extern "C" {
662//------------------------------------------------------------------------
663// : 720p busyQ funcitons
664// --------------------------------------------------------------------
665static struct fifo_queue g_busy_frame_queue =
666 {0, 0, 0, PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER};
667};
668/*===========================================================================
669 * FUNCTION cam_frame_wait_video
670 *
671 * DESCRIPTION this function waits a video in the busy queue
672 * ===========================================================================*/
673
674static void cam_frame_wait_video (void)
675{
676 LOGV("cam_frame_wait_video E ");
677 if ((g_busy_frame_queue.num_of_frames) <=0){
678 pthread_cond_wait(&(g_busy_frame_queue.wait), &(g_busy_frame_queue.mut));
679 }
680 LOGV("cam_frame_wait_video X");
681 return;
682}
683
684/*===========================================================================
685 * FUNCTION cam_frame_flush_video
686 *
687 * DESCRIPTION this function deletes all the buffers in busy queue
688 * ===========================================================================*/
689void cam_frame_flush_video (void)
690{
691 LOGV("cam_frame_flush_video: in n = %d\n", g_busy_frame_queue.num_of_frames);
692 pthread_mutex_lock(&(g_busy_frame_queue.mut));
693
694 while (g_busy_frame_queue.front)
695 {
696 //dequeue from the busy queue
697 struct fifo_node *node = dequeue (&g_busy_frame_queue);
698 if(node)
699 free(node);
700
701 LOGV("cam_frame_flush_video: node \n");
702 }
703 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
704 LOGV("cam_frame_flush_video: out n = %d\n", g_busy_frame_queue.num_of_frames);
705 return ;
706}
707/*===========================================================================
708 * FUNCTION cam_frame_get_video
709 *
710 * DESCRIPTION this function returns a video frame from the head
711 * ===========================================================================*/
712static struct msm_frame * cam_frame_get_video()
713{
714 struct msm_frame *p = NULL;
715 LOGV("cam_frame_get_video... in\n");
716 LOGV("cam_frame_get_video... got lock\n");
717 if (g_busy_frame_queue.front)
718 {
719 //dequeue
720 struct fifo_node *node = dequeue (&g_busy_frame_queue);
721 if (node)
722 {
723 p = (struct msm_frame *)node->f;
724 free (node);
725 }
726 LOGV("cam_frame_get_video... out = %x\n", p->buffer);
727 }
728 return p;
729}
730
731/*===========================================================================
732 * FUNCTION cam_frame_post_video
733 *
734 * DESCRIPTION this function add a busy video frame to the busy queue tails
735 * ===========================================================================*/
736static void cam_frame_post_video (struct msm_frame *p)
737{
738 if (!p)
739 {
740 LOGE("post video , buffer is null");
741 return;
742 }
743 LOGV("cam_frame_post_video... in = %x\n", (unsigned int)(p->buffer));
744 pthread_mutex_lock(&(g_busy_frame_queue.mut));
745 LOGV("post_video got lock. q count before enQ %d", g_busy_frame_queue.num_of_frames);
746 //enqueue to busy queue
747 struct fifo_node *node = (struct fifo_node *)malloc (sizeof (struct fifo_node));
748 if (node)
749 {
750 LOGV(" post video , enqueing in busy queue");
751 node->f = p;
752 node->next = NULL;
753 enqueue (&g_busy_frame_queue, node);
754 LOGV("post_video got lock. q count after enQ %d", g_busy_frame_queue.num_of_frames);
755 }
756 else
757 {
758 LOGE("cam_frame_post_video error... out of memory\n");
759 }
760
761 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
762 pthread_cond_signal(&(g_busy_frame_queue.wait));
763
764 LOGV("cam_frame_post_video... out = %x\n", p->buffer);
765
766 return;
767}
768
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -0800769void QualcommCameraHardware::storeTargetType(void) {
770 char mDeviceName[PROPERTY_VALUE_MAX];
771 property_get("ro.product.device",mDeviceName," ");
772 mCurrentTarget = TARGET_MAX;
773 for( int i = 0; i < TARGET_MAX ; i++) {
774 if( !strncmp(mDeviceName, targetList[i].targetStr, 7)) {
775 mCurrentTarget = targetList[i].targetEnum;
776 break;
777 }
778 }
779 LOGV(" Storing the current target type as %d ", mCurrentTarget );
780 return;
781}
782
Sravankb4f5f1c2010-01-21 11:06:17 +0530783//-------------------------------------------------------------------------------------
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800784static Mutex singleton_lock;
785static bool singleton_releasing;
786static Condition singleton_wait;
787
788static void receive_camframe_callback(struct msm_frame *frame);
Sravankb4f5f1c2010-01-21 11:06:17 +0530789static void receive_camframe_video_callback(struct msm_frame *frame); // 720p
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800790static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size);
791static void receive_jpeg_callback(jpeg_event_t status);
792static void receive_shutter_callback(common_crop_t *crop);
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800793static void receive_camframetimeout_callback(void);
Mohan Kandra284966d2010-01-05 13:39:15 -0800794static int fb_fd = -1;
795static int32_t mMaxZoom = 0;
796static bool native_get_maxzoom(int camfd, void *pZm);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800797
Mohan Kandrad9efed92010-01-15 19:08:39 -0800798static int dstOffset = 0;
799
Brian Steuer07704892009-12-18 18:07:33 -0800800static int camerafd;
801pthread_t w_thread;
802
803void *opencamerafd(void *data) {
804 camerafd = open(MSM_CAMERA_CONTROL, O_RDWR);
805 return NULL;
806}
807
Mohan Kandrad9efed92010-01-15 19:08:39 -0800808/* When using MDP zoom, double the preview buffers. The usage of these
809 * buffers is as follows:
810 * 1. As all the buffers comes under a single FD, and at initial registration,
811 * this FD will be passed to surface flinger, surface flinger can have access
812 * to all the buffers when needed.
813 * 2. Only "kPreviewBufferCount" buffers (SrcSet) will be registered with the
814 * camera driver to receive preview frames. The remaining buffers (DstSet),
815 * will be used at HAL and by surface flinger only when crop information
816 * is present in the frame.
817 * 3. When there is no crop information, there will be no call to MDP zoom,
818 * and the buffers in SrcSet will be passed to surface flinger to display.
819 * 4. With crop information present, MDP zoom will be called, and the final
820 * data will be placed in a buffer from DstSet, and this buffer will be given
821 * to surface flinger to display.
822 */
823#define NUM_MORE_BUFS 2
824
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800825QualcommCameraHardware::QualcommCameraHardware()
826 : mParameters(),
827 mCameraRunning(false),
828 mPreviewInitialized(false),
829 mFrameThreadRunning(false),
Mohan Kandra156d0ac2010-01-25 16:59:17 -0800830 mVideoThreadRunning(false),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800831 mSnapshotThreadRunning(false),
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800832 mSnapshotFormat(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800833 mReleasedRecordingFrame(false),
834 mPreviewFrameSize(0),
835 mRawSize(0),
836 mCameraControlFd(-1),
837 mAutoFocusThreadRunning(false),
838 mAutoFocusFd(-1),
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800839 mBrightness(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800840 mInPreviewCallback(false),
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800841 mUseOverlay(0),
842 mOverlay(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800843 mMsgEnabled(0),
844 mNotifyCallback(0),
845 mDataCallback(0),
846 mDataCallbackTimestamp(0),
Mohan Kandra740cfce2010-01-07 12:58:24 -0800847 mCallbackCookie(0),
848 mDebugFps(0)
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800849{
Brian Steuer07704892009-12-18 18:07:33 -0800850
851 // Start opening camera device in a separate thread/ Since this
852 // initializes the sensor hardware, this can take a long time. So,
853 // start the process here so it will be ready by the time it's
854 // needed.
855 if ((pthread_create(&w_thread, NULL, opencamerafd, NULL)) != 0) {
856 LOGE("Camera open thread creation failed");
857 }
858
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800859 memset(&mDimension, 0, sizeof(mDimension));
860 memset(&mCrop, 0, sizeof(mCrop));
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -0800861 memset(&zoomCropInfo, 0, sizeof(zoom_crop_info));
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -0800862 storeTargetType();
Mohan Kandra740cfce2010-01-07 12:58:24 -0800863 char value[PROPERTY_VALUE_MAX];
864 property_get("persist.debug.sf.showfps", value, "0");
865 mDebugFps = atoi(value);
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -0800866 if( mCurrentTarget == TARGET_MSM7630 )
Sravankb4f5f1c2010-01-21 11:06:17 +0530867 kPreviewBufferCountActual = kPreviewBufferCount;
868 else
869 kPreviewBufferCountActual = kPreviewBufferCount + NUM_MORE_BUFS;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800870 LOGV("constructor EX");
871}
872
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800873
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -0800874void QualcommCameraHardware::filterPreviewSizes(){
875
876 unsigned int bitMask = 0;
877 int prop = 0;
878 for(prop=0;prop<sizeof(boardProperties)/sizeof(board_property);prop++){
879 if(mCurrentTarget == boardProperties[prop].target){
880 bitMask = boardProperties[prop].previewSizeMask;
881 break;
882 }
883 }
884
885 if(bitMask){
886 unsigned int mask = 1<<(PREVIEW_SIZE_COUNT-1);
887 previewSizeCount=0;
888 unsigned int i = 0;
889 while(mask){
890 if(mask&bitMask)
891 supportedPreviewSizes[previewSizeCount++] =
892 preview_sizes[i];
893 i++;
894 mask = mask >> 1;
895 }
896 }
897}
898
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800899//filter Picture sizes based on max width and height
900void QualcommCameraHardware::filterPictureSizes(){
901 int i;
902 for(i=0;i<PICTURE_SIZE_COUNT;i++){
903 if(((picture_sizes[i].width <=
904 sensorType->max_supported_snapshot_width) &&
905 (picture_sizes[i].height <=
906 sensorType->max_supported_snapshot_height))){
907 picture_sizes_ptr = picture_sizes + i;
908 supportedPictureSizesCount = PICTURE_SIZE_COUNT - i ;
909 return ;
910 }
911 }
912}
913
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800914void QualcommCameraHardware::initDefaultParameters()
915{
916 LOGV("initDefaultParameters E");
917
918 // Initialize constant parameter strings. This will happen only once in the
919 // lifetime of the mediaserver process.
920 if (!parameter_string_initialized) {
Srinivasan Kannan71229622009-12-04 12:05:58 -0800921 findSensorType();
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800922 antibanding_values = create_values_str(
923 antibanding, sizeof(antibanding) / sizeof(str_map));
924 effect_values = create_values_str(
925 effects, sizeof(effects) / sizeof(str_map));
Apurva Rajguru55562b02009-12-03 12:25:35 -0800926 autoexposure_values = create_values_str(
927 autoexposure, sizeof(autoexposure) / sizeof(str_map));
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800928 whitebalance_values = create_values_str(
929 whitebalance, sizeof(whitebalance) / sizeof(str_map));
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -0800930
931 //filter preview sizes
932 filterPreviewSizes();
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800933 preview_size_values = create_sizes_str(
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -0800934 supportedPreviewSizes, previewSizeCount);
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800935 //filter picture sizes
936 filterPictureSizes();
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800937 picture_size_values = create_sizes_str(
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800938 picture_sizes_ptr, supportedPictureSizesCount);
939
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800940 flash_values = create_values_str(
941 flash, sizeof(flash) / sizeof(str_map));
Srinivasan Kannan71229622009-12-04 12:05:58 -0800942 if(sensorType->hasAutoFocusSupport){
943 focus_mode_values = create_values_str(
944 focus_modes, sizeof(focus_modes) / sizeof(str_map));
945 }
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530946 iso_values = create_values_str(
947 iso,sizeof(iso)/sizeof(str_map));
948 lensshade_values = create_values_str(
949 lensshade,sizeof(lensshade)/sizeof(str_map));
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800950 picture_format_values = create_values_str(
951 picture_formats, sizeof(picture_formats)/sizeof(str_map));
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800952 parameter_string_initialized = true;
953 }
954
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -0800955 mParameters.setPreviewSize(DEFAULT_PREVIEW_WIDTH, DEFAULT_PREVIEW_HEIGHT);
956 mDimension.display_width = DEFAULT_PREVIEW_WIDTH;
957 mDimension.display_height = DEFAULT_PREVIEW_HEIGHT;
958
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800959 mParameters.setPreviewFrameRate(15);
960 mParameters.setPreviewFormat("yuv420sp"); // informative
961
962 mParameters.setPictureSize(DEFAULT_PICTURE_WIDTH, DEFAULT_PICTURE_HEIGHT);
963 mParameters.setPictureFormat("jpeg"); // informative
964
Mohan Kandra785619a2010-02-01 21:52:42 -0800965 mParameters.set(CameraParameters::KEY_JPEG_QUALITY, "85"); // max quality
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800966 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH,
967 THUMBNAIL_WIDTH_STR); // informative
968 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT,
969 THUMBNAIL_HEIGHT_STR); // informative
Srinivasan Kannan80d878f2009-12-18 15:06:02 -0800970 mDimension.ui_thumbnail_width =
971 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].width;
972 mDimension.ui_thumbnail_height =
973 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800974 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, "90");
975
976 mParameters.set(CameraParameters::KEY_ANTIBANDING,
Mohan Kandra785619a2010-02-01 21:52:42 -0800977 CameraParameters::ANTIBANDING_OFF);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800978 mParameters.set(CameraParameters::KEY_EFFECT,
979 CameraParameters::EFFECT_NONE);
Apurva Rajguru55562b02009-12-03 12:25:35 -0800980 mParameters.set(CameraParameters::KEY_AUTO_EXPOSURE,
981 CameraParameters::AUTO_EXPOSURE_FRAME_AVG);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800982 mParameters.set(CameraParameters::KEY_WHITE_BALANCE,
983 CameraParameters::WHITE_BALANCE_AUTO);
984 mParameters.set(CameraParameters::KEY_FOCUS_MODE,
985 CameraParameters::FOCUS_MODE_AUTO);
Priya Komarlingam044c7b52010-01-22 18:21:23 -0800986 mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS,
987 "yuv420sp");
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800988
989 mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES,
990 preview_size_values.string());
991 mParameters.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES,
992 picture_size_values.string());
993 mParameters.set(CameraParameters::KEY_SUPPORTED_ANTIBANDING,
994 antibanding_values);
995 mParameters.set(CameraParameters::KEY_SUPPORTED_EFFECTS, effect_values);
Apurva Rajguru55562b02009-12-03 12:25:35 -0800996 mParameters.set(CameraParameters::KEY_SUPPORTED_AUTO_EXPOSURE, autoexposure_values);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800997 mParameters.set(CameraParameters::KEY_SUPPORTED_WHITE_BALANCE,
998 whitebalance_values);
999 mParameters.set(CameraParameters::KEY_SUPPORTED_FOCUS_MODES,
1000 focus_mode_values);
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001001 mParameters.set(CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS,
1002 picture_format_values);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001003
1004 if (mSensorInfo.flash_enabled) {
1005 mParameters.set(CameraParameters::KEY_FLASH_MODE,
1006 CameraParameters::FLASH_MODE_OFF);
1007 mParameters.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES,
1008 flash_values);
1009 }
1010
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08001011 mParameters.set(CameraParameters::KEY_MAX_SHARPNESS,
1012 CAMERA_MAX_SHARPNESS);
1013 mParameters.set(CameraParameters::KEY_MAX_CONTRAST,
1014 CAMERA_MAX_CONTRAST);
1015 mParameters.set(CameraParameters::KEY_MAX_SATURATION,
1016 CAMERA_MAX_SATURATION);
1017
Apurva Rajguru07185952010-01-22 15:40:07 -08001018 mParameters.set("luma-adaptation", "3");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001019 mParameters.set("zoom-supported", "true");
1020 mParameters.set("max-zoom", MAX_ZOOM_LEVEL);
1021 mParameters.set("zoom", 0);
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001022 mParameters.set(CameraParameters::KEY_PICTURE_FORMAT,
1023 CameraParameters::PIXEL_FORMAT_JPEG);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001024
Kiran Kumar H N595970b2010-01-12 10:41:09 -08001025 mParameters.set(CameraParameters::KEY_SHARPNESS,
1026 CAMERA_DEF_SHARPNESS);
1027 mParameters.set(CameraParameters::KEY_CONTRAST,
1028 CAMERA_DEF_CONTRAST);
1029 mParameters.set(CameraParameters::KEY_SATURATION,
1030 CAMERA_DEF_SATURATION);
1031
Nishant Panditc8c1ee72009-12-03 16:24:02 +05301032 mParameters.set(CameraParameters::KEY_ISO_MODE,
1033 CameraParameters::ISO_AUTO);
1034 mParameters.set(CameraParameters::KEY_LENSSHADE,
1035 CameraParameters::LENSSHADE_ENABLE);
1036 mParameters.set(CameraParameters::KEY_SUPPORTED_ISO_MODES,
1037 iso_values);
1038 mParameters.set(CameraParameters::KEY_SUPPORTED_LENSSHADE_MODES,
1039 lensshade_values);
1040
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08001041 mUseOverlay = useOverlay();
1042
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001043 /* Initialize the camframe_timeout_flag*/
1044 Mutex::Autolock l(&mCamframeTimeoutLock);
1045 camframe_timeout_flag = FALSE;
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08001046 mPostViewHeap = NULL;
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001047
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001048 LOGV("initDefaultParameters X");
1049}
1050
Srinivasan Kannan71229622009-12-04 12:05:58 -08001051void QualcommCameraHardware::findSensorType(){
1052 mDimension.picture_width = DEFAULT_PICTURE_WIDTH;
1053 mDimension.picture_height = DEFAULT_PICTURE_HEIGHT;
1054 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
1055 sizeof(cam_ctrl_dimension_t), &mDimension);
1056 if (ret) {
1057 unsigned int i;
1058 for (i = 0; i < sizeof(sensorTypes) / sizeof(SensorType); i++) {
1059 if (sensorTypes[i].rawPictureHeight
1060 == mDimension.raw_picture_height) {
1061 sensorType = sensorTypes + i;
1062 return;
1063 }
1064 }
1065 }
1066 //default to 5 mp
1067 sensorType = sensorTypes;
1068 return;
1069}
1070
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001071#define ROUND_TO_PAGE(x) (((x)+0xfff)&~0xfff)
1072
1073bool QualcommCameraHardware::startCamera()
1074{
1075 LOGV("startCamera E");
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08001076 if( mCurrentTarget == TARGET_MAX ) {
1077 LOGE(" Unable to determine the target type. Camera will not work ");
1078 return false;
1079 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001080#if DLOPEN_LIBMMCAMERA
1081 libmmcamera = ::dlopen("liboemcamera.so", RTLD_NOW);
1082 LOGV("loading liboemcamera at %p", libmmcamera);
1083 if (!libmmcamera) {
1084 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
1085 return false;
1086 }
1087
1088 *(void **)&LINK_cam_frame =
1089 ::dlsym(libmmcamera, "cam_frame");
1090 *(void **)&LINK_camframe_terminate =
1091 ::dlsym(libmmcamera, "camframe_terminate");
1092
1093 *(void **)&LINK_jpeg_encoder_init =
1094 ::dlsym(libmmcamera, "jpeg_encoder_init");
1095
1096 *(void **)&LINK_jpeg_encoder_encode =
1097 ::dlsym(libmmcamera, "jpeg_encoder_encode");
1098
1099 *(void **)&LINK_jpeg_encoder_join =
1100 ::dlsym(libmmcamera, "jpeg_encoder_join");
1101
1102 *(void **)&LINK_mmcamera_camframe_callback =
1103 ::dlsym(libmmcamera, "mmcamera_camframe_callback");
1104
1105 *LINK_mmcamera_camframe_callback = receive_camframe_callback;
1106
1107 *(void **)&LINK_mmcamera_jpegfragment_callback =
1108 ::dlsym(libmmcamera, "mmcamera_jpegfragment_callback");
1109
1110 *LINK_mmcamera_jpegfragment_callback = receive_jpeg_fragment_callback;
1111
1112 *(void **)&LINK_mmcamera_jpeg_callback =
1113 ::dlsym(libmmcamera, "mmcamera_jpeg_callback");
1114
1115 *LINK_mmcamera_jpeg_callback = receive_jpeg_callback;
1116
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001117 *(void **)&LINK_camframe_timeout_callback =
1118 ::dlsym(libmmcamera, "camframe_timeout_callback");
1119
1120 *LINK_camframe_timeout_callback = receive_camframetimeout_callback;
1121
Sravankb4f5f1c2010-01-21 11:06:17 +05301122 // 720 p new recording functions
1123 *(void **)&LINK_cam_frame_flush_free_video = ::dlsym(libmmcamera, "cam_frame_flush_free_video");
1124
1125 *(void **)&LINK_camframe_free_video = ::dlsym(libmmcamera, "cam_frame_add_free_video");
1126
1127 *(void **)&LINK_camframe_video_callback = ::dlsym(libmmcamera, "mmcamera_camframe_videocallback");
1128 *LINK_camframe_video_callback = receive_camframe_video_callback;
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001129/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001130 *(void **)&LINK_mmcamera_shutter_callback =
1131 ::dlsym(libmmcamera, "mmcamera_shutter_callback");
1132
1133 *LINK_mmcamera_shutter_callback = receive_shutter_callback;
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001134*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001135 *(void**)&LINK_jpeg_encoder_setMainImageQuality =
1136 ::dlsym(libmmcamera, "jpeg_encoder_setMainImageQuality");
Kiran Kumar H N8861f302010-01-05 12:01:41 -08001137
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001138 *(void**)&LINK_jpeg_encoder_setThumbnailQuality =
1139 ::dlsym(libmmcamera, "jpeg_encoder_setThumbnailQuality");
1140
1141 *(void**)&LINK_jpeg_encoder_setRotation =
1142 ::dlsym(libmmcamera, "jpeg_encoder_setRotation");
1143
Kiran Kumar H N8861f302010-01-05 12:01:41 -08001144/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001145 *(void**)&LINK_jpeg_encoder_setLocation =
1146 ::dlsym(libmmcamera, "jpeg_encoder_setLocation");
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001147*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001148 *(void **)&LINK_cam_conf =
1149 ::dlsym(libmmcamera, "cam_conf");
1150
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001151/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001152 *(void **)&LINK_default_sensor_get_snapshot_sizes =
1153 ::dlsym(libmmcamera, "default_sensor_get_snapshot_sizes");
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001154*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001155 *(void **)&LINK_launch_cam_conf_thread =
1156 ::dlsym(libmmcamera, "launch_cam_conf_thread");
1157
1158 *(void **)&LINK_release_cam_conf_thread =
1159 ::dlsym(libmmcamera, "release_cam_conf_thread");
1160
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001161/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001162 *(void **)&LINK_zoom_crop_upscale =
1163 ::dlsym(libmmcamera, "zoom_crop_upscale");
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001164*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001165
1166#else
1167 mmcamera_camframe_callback = receive_camframe_callback;
1168 mmcamera_jpegfragment_callback = receive_jpeg_fragment_callback;
1169 mmcamera_jpeg_callback = receive_jpeg_callback;
1170 mmcamera_shutter_callback = receive_shutter_callback;
1171#endif // DLOPEN_LIBMMCAMERA
1172
1173 /* The control thread is in libcamera itself. */
Brian Steuer07704892009-12-18 18:07:33 -08001174 if (pthread_join(w_thread, NULL) != 0) {
1175 LOGE("Camera open thread exit failed");
1176 return false;
1177 }
1178 mCameraControlFd = camerafd;
1179
Kiran Kumar H N585bc362010-01-19 13:04:44 -08001180 if (mCameraControlFd < 0) {
1181 LOGE("startCamera X: %s open failed: %s!",
1182 MSM_CAMERA_CONTROL,
1183 strerror(errno));
1184 return false;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001185 }
1186
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08001187 if( mCurrentTarget != TARGET_MSM7630 ){
Mohan Kandra284966d2010-01-05 13:39:15 -08001188 fb_fd = open("/dev/graphics/fb0", O_RDWR);
1189 if (fb_fd < 0) {
1190 LOGE("startCamera: fb0 open failed: %s!", strerror(errno));
1191 return FALSE;
1192 }
1193 }
1194
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001195 /* This will block until the control thread is launched. After that, sensor
1196 * information becomes available.
1197 */
1198
1199 if (LINK_launch_cam_conf_thread()) {
1200 LOGE("failed to launch the camera config thread");
1201 return false;
1202 }
1203
1204 memset(&mSensorInfo, 0, sizeof(mSensorInfo));
1205 if (ioctl(mCameraControlFd,
1206 MSM_CAM_IOCTL_GET_SENSOR_INFO,
1207 &mSensorInfo) < 0)
1208 LOGW("%s: cannot retrieve sensor info!", __FUNCTION__);
1209 else
1210 LOGI("%s: camsensor name %s, flash %d", __FUNCTION__,
1211 mSensorInfo.name, mSensorInfo.flash_enabled);
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001212/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001213 picture_sizes = LINK_default_sensor_get_snapshot_sizes(&PICTURE_SIZE_COUNT);
1214 if (!picture_sizes || !PICTURE_SIZE_COUNT) {
1215 LOGE("startCamera X: could not get snapshot sizes");
1216 return false;
1217 }
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001218*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001219 LOGV("startCamera X");
1220 return true;
1221}
1222
1223status_t QualcommCameraHardware::dump(int fd,
1224 const Vector<String16>& args) const
1225{
1226 const size_t SIZE = 256;
1227 char buffer[SIZE];
1228 String8 result;
1229
1230 // Dump internal primitives.
1231 result.append("QualcommCameraHardware::dump");
1232 snprintf(buffer, 255, "mMsgEnabled (%d)\n", mMsgEnabled);
1233 result.append(buffer);
1234 int width, height;
1235 mParameters.getPreviewSize(&width, &height);
1236 snprintf(buffer, 255, "preview width(%d) x height (%d)\n", width, height);
1237 result.append(buffer);
1238 mParameters.getPictureSize(&width, &height);
1239 snprintf(buffer, 255, "raw width(%d) x height (%d)\n", width, height);
1240 result.append(buffer);
1241 snprintf(buffer, 255,
1242 "preview frame size(%d), raw size (%d), jpeg size (%d) "
1243 "and jpeg max size (%d)\n", mPreviewFrameSize, mRawSize,
1244 mJpegSize, mJpegMaxSize);
1245 result.append(buffer);
1246 write(fd, result.string(), result.size());
1247
1248 // Dump internal objects.
Mohan Kandrad9efed92010-01-15 19:08:39 -08001249 if (mPreviewHeap != 0) {
1250 mPreviewHeap->dump(fd, args);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001251 }
1252 if (mRawHeap != 0) {
1253 mRawHeap->dump(fd, args);
1254 }
1255 if (mJpegHeap != 0) {
1256 mJpegHeap->dump(fd, args);
1257 }
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001258 if(mRawSnapshotAshmemHeap != 0 ){
1259 mRawSnapshotAshmemHeap->dump(fd, args);
1260 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001261 mParameters.dump(fd, args);
1262 return NO_ERROR;
1263}
1264
Mohan Kandra284966d2010-01-05 13:39:15 -08001265static bool native_get_maxzoom(int camfd, void *pZm)
1266{
1267 LOGV("native_get_maxzoom E");
1268
1269 struct msm_ctrl_cmd ctrlCmd;
1270 int32_t *pZoom = (int32_t *)pZm;
1271
1272 ctrlCmd.type = CAMERA_GET_PARM_MAXZOOM;
1273 ctrlCmd.timeout_ms = 5000;
1274 ctrlCmd.length = sizeof(int32_t);
1275 ctrlCmd.value = pZoom;
1276 ctrlCmd.resp_fd = camfd;
1277
1278 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1279 LOGE("native_get_maxzoom: ioctl fd %d error %s",
1280 camfd,
1281 strerror(errno));
1282 return false;
1283 }
Brian Steuerb62adbd2010-02-02 14:47:08 -08001284 LOGD("ctrlCmd.value = %d", *(int32_t *)ctrlCmd.value);
Mohan Kandra284966d2010-01-05 13:39:15 -08001285 memcpy(pZoom, (int32_t *)ctrlCmd.value, sizeof(int32_t));
1286
1287 LOGV("native_get_maxzoom X");
1288 return true;
1289}
1290
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001291static bool native_set_afmode(int camfd, isp3a_af_mode_t af_type)
1292{
1293 int rc;
1294 struct msm_ctrl_cmd ctrlCmd;
1295
1296 ctrlCmd.timeout_ms = 5000;
1297 ctrlCmd.type = CAMERA_SET_PARM_AUTO_FOCUS;
1298 ctrlCmd.length = sizeof(af_type);
1299 ctrlCmd.value = &af_type;
1300 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1301
1302 if ((rc = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0)
1303 LOGE("native_set_afmode: ioctl fd %d error %s\n",
1304 camfd,
1305 strerror(errno));
1306
1307 LOGV("native_set_afmode: ctrlCmd.status == %d\n", ctrlCmd.status);
1308 return rc >= 0 && ctrlCmd.status == CAMERA_EXIT_CB_DONE;
1309}
1310
1311static bool native_cancel_afmode(int camfd, int af_fd)
1312{
1313 int rc;
1314 struct msm_ctrl_cmd ctrlCmd;
1315
1316 ctrlCmd.timeout_ms = 0;
1317 ctrlCmd.type = CAMERA_AUTO_FOCUS_CANCEL;
1318 ctrlCmd.length = 0;
1319 ctrlCmd.value = NULL;
1320 ctrlCmd.resp_fd = -1; // there's no response fd
1321
1322 if ((rc = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND_2, &ctrlCmd)) < 0)
1323 {
1324 LOGE("native_cancel_afmode: ioctl fd %d error %s\n",
1325 camfd,
1326 strerror(errno));
1327 return false;
1328 }
1329
1330 return true;
1331}
1332
1333static bool native_start_preview(int camfd)
1334{
1335 struct msm_ctrl_cmd ctrlCmd;
1336
1337 ctrlCmd.timeout_ms = 5000;
1338 ctrlCmd.type = CAMERA_START_PREVIEW;
1339 ctrlCmd.length = 0;
1340 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1341
1342 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1343 LOGE("native_start_preview: MSM_CAM_IOCTL_CTRL_COMMAND fd %d error %s",
1344 camfd,
1345 strerror(errno));
1346 return false;
1347 }
1348
1349 return true;
1350}
1351
1352static bool native_get_picture (int camfd, common_crop_t *crop)
1353{
1354 struct msm_ctrl_cmd ctrlCmd;
1355
1356 ctrlCmd.timeout_ms = 5000;
1357 ctrlCmd.length = sizeof(common_crop_t);
1358 ctrlCmd.value = crop;
1359
1360 if(ioctl(camfd, MSM_CAM_IOCTL_GET_PICTURE, &ctrlCmd) < 0) {
1361 LOGE("native_get_picture: MSM_CAM_IOCTL_GET_PICTURE fd %d error %s",
1362 camfd,
1363 strerror(errno));
1364 return false;
1365 }
1366
1367 LOGV("crop: in1_w %d", crop->in1_w);
1368 LOGV("crop: in1_h %d", crop->in1_h);
1369 LOGV("crop: out1_w %d", crop->out1_w);
1370 LOGV("crop: out1_h %d", crop->out1_h);
1371
1372 LOGV("crop: in2_w %d", crop->in2_w);
1373 LOGV("crop: in2_h %d", crop->in2_h);
1374 LOGV("crop: out2_w %d", crop->out2_w);
1375 LOGV("crop: out2_h %d", crop->out2_h);
1376
1377 LOGV("crop: update %d", crop->update_flag);
1378
1379 return true;
1380}
1381
1382static bool native_stop_preview(int camfd)
1383{
1384 struct msm_ctrl_cmd ctrlCmd;
1385 ctrlCmd.timeout_ms = 5000;
1386 ctrlCmd.type = CAMERA_STOP_PREVIEW;
1387 ctrlCmd.length = 0;
1388 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1389
1390 if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1391 LOGE("native_stop_preview: ioctl fd %d error %s",
1392 camfd,
1393 strerror(errno));
1394 return false;
1395 }
1396
1397 return true;
1398}
1399
1400static bool native_prepare_snapshot(int camfd)
1401{
1402 int ioctlRetVal = true;
1403 struct msm_ctrl_cmd ctrlCmd;
1404
1405 ctrlCmd.timeout_ms = 1000;
1406 ctrlCmd.type = CAMERA_PREPARE_SNAPSHOT;
1407 ctrlCmd.length = 0;
1408 ctrlCmd.value = NULL;
1409 ctrlCmd.resp_fd = camfd;
1410
1411 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1412 LOGE("native_prepare_snapshot: ioctl fd %d error %s",
1413 camfd,
1414 strerror(errno));
1415 return false;
1416 }
1417 return true;
1418}
1419
1420static bool native_start_snapshot(int camfd)
1421{
1422 struct msm_ctrl_cmd ctrlCmd;
1423
1424 ctrlCmd.timeout_ms = 5000;
1425 ctrlCmd.type = CAMERA_START_SNAPSHOT;
1426 ctrlCmd.length = 0;
1427 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1428
1429 if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1430 LOGE("native_start_snapshot: ioctl fd %d error %s",
1431 camfd,
1432 strerror(errno));
1433 return false;
1434 }
1435
1436 return true;
1437}
1438
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001439static bool native_start_raw_snapshot(int camfd)
1440{
1441 int ret;
1442 struct msm_ctrl_cmd ctrlCmd;
1443
1444 ctrlCmd.timeout_ms = 1000;
1445 ctrlCmd.type = CAMERA_START_RAW_SNAPSHOT;
1446 ctrlCmd.length = 0;
1447 ctrlCmd.value = NULL;
1448 ctrlCmd.resp_fd = camfd;
1449
1450 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1451 LOGE("native_start_raw_snapshot: ioctl failed. ioctl return value "\
1452 "is %d \n", ret);
1453 return false;
1454 }
1455 return true;
1456}
1457
1458
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001459static bool native_stop_snapshot (int camfd)
1460{
1461 struct msm_ctrl_cmd ctrlCmd;
1462
1463 ctrlCmd.timeout_ms = 0;
1464 ctrlCmd.type = CAMERA_STOP_SNAPSHOT;
1465 ctrlCmd.length = 0;
1466 ctrlCmd.resp_fd = -1;
1467
1468 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND_2, &ctrlCmd) < 0) {
1469 LOGE("native_stop_snapshot: ioctl fd %d error %s",
1470 camfd,
1471 strerror(errno));
1472 return false;
1473 }
1474
1475 return true;
1476}
Sravankb4f5f1c2010-01-21 11:06:17 +05301477/*===========================================================================
1478 * FUNCTION - native_start_recording -
1479 *
1480 * DESCRIPTION:
1481 *==========================================================================*/
1482static bool native_start_recording(int camfd)
1483{
1484 int ret;
1485 struct msm_ctrl_cmd ctrlCmd;
1486
1487 ctrlCmd.timeout_ms = 1000;
1488 ctrlCmd.type = CAMERA_START_RECORDING;
1489 ctrlCmd.length = 0;
1490 ctrlCmd.value = NULL;
1491 ctrlCmd.resp_fd = camfd;
1492
1493 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1494 LOGE("native_start_recording: ioctl failed. ioctl return value "\
1495 "is %d \n", ret);
1496 return false;
1497 }
Mohan Kandraf1ebf982010-02-02 15:25:43 -08001498 LOGV("native_start_recording: ioctl good. ioctl return value is %d \n",ret);
Sravankb4f5f1c2010-01-21 11:06:17 +05301499
1500 /* TODO: Check status of postprocessing if there is any,
1501 * PP status should be in ctrlCmd */
1502
1503 return true;
1504}
1505
1506/*===========================================================================
1507 * FUNCTION - native_stop_recording -
1508 *
1509 * DESCRIPTION:
1510 *==========================================================================*/
1511static bool native_stop_recording(int camfd)
1512{
1513 int ret;
1514 struct msm_ctrl_cmd ctrlCmd;
Kiran Kumar H Nb49af212010-02-17 15:12:17 -08001515 LOGV("in native_stop_recording ");
Sravankb4f5f1c2010-01-21 11:06:17 +05301516 ctrlCmd.timeout_ms = 1000;
1517 ctrlCmd.type = CAMERA_STOP_RECORDING;
1518 ctrlCmd.length = 0;
1519 ctrlCmd.value = NULL;
1520 ctrlCmd.resp_fd = camfd;
1521
1522 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1523 LOGE("native_stop_video: ioctl failed. ioctl return value is %d \n",
1524 ret);
1525 return false;
1526 }
1527 LOGV("in native_stop_recording returned %d", ret);
1528 return true;
1529}
1530/*===========================================================================
1531 * FUNCTION - native_start_video -
1532 *
1533 * DESCRIPTION:
1534 *==========================================================================*/
1535static bool native_start_video(int camfd)
1536{
1537 int ret;
1538 struct msm_ctrl_cmd ctrlCmd;
1539
1540 ctrlCmd.timeout_ms = 1000;
1541 ctrlCmd.type = CAMERA_START_VIDEO;
1542 ctrlCmd.length = 0;
1543 ctrlCmd.value = NULL;
1544 ctrlCmd.resp_fd = camfd;
1545
1546 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1547 LOGE("native_start_video: ioctl failed. ioctl return value is %d \n",
1548 ret);
1549 return false;
1550 }
1551
1552 /* TODO: Check status of postprocessing if there is any,
1553 * PP status should be in ctrlCmd */
1554
1555 return true;
1556}
1557
1558/*===========================================================================
1559 * FUNCTION - native_stop_video -
1560 *
1561 * DESCRIPTION:
1562 *==========================================================================*/
1563static bool native_stop_video(int camfd)
1564{
1565 int ret;
1566 struct msm_ctrl_cmd ctrlCmd;
1567
1568 ctrlCmd.timeout_ms = 1000;
1569 ctrlCmd.type = CAMERA_STOP_VIDEO;
1570 ctrlCmd.length = 0;
1571 ctrlCmd.value = NULL;
1572 ctrlCmd.resp_fd = camfd;
1573
1574 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1575 LOGE("native_stop_video: ioctl failed. ioctl return value is %d \n",
1576 ret);
1577 return false;
1578 }
1579
1580 return true;
1581}
1582/*==========================================================================*/
1583
1584static cam_frame_start_parms frame_parms;
1585static int recordingState = 0;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001586
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001587static rat_t latitude[3];
1588static rat_t longitude[3];
1589static char lonref[2];
1590static char latref[2];
1591static char dateTime[20];
1592static rat_t altitude;
1593
1594static void addExifTag(exif_tag_id_t tagid, exif_tag_type_t type,
1595 uint32_t count, uint8_t copy, void *data) {
1596
1597 if(exif_table_numEntries == MAX_EXIF_TABLE_ENTRIES) {
1598 LOGE("Number of entries exceeded limit");
1599 return;
1600 }
1601
1602 int index = exif_table_numEntries;
1603 exif_data[index].tag_id = tagid;
1604 exif_data[index].tag_entry.type = type;
1605 exif_data[index].tag_entry.count = count;
1606 exif_data[index].tag_entry.copy = copy;
1607 if((type == EXIF_RATIONAL) && (count > 1))
1608 exif_data[index].tag_entry.data._rats = (rat_t *)data;
1609 if((type == EXIF_RATIONAL) && (count == 1))
1610 exif_data[index].tag_entry.data._rat = *(rat_t *)data;
1611 else if(type == EXIF_ASCII)
1612 exif_data[index].tag_entry.data._ascii = (char *)data;
1613 else if(type == EXIF_BYTE)
1614 exif_data[index].tag_entry.data._byte = *(uint8_t *)data;
1615
1616 // Increase number of entries
1617 exif_table_numEntries++;
1618}
1619
1620static void parseLatLong(const char *latlonString, int *pDegrees,
1621 int *pMinutes, int *pSeconds ) {
1622
1623 double value = atof(latlonString);
1624 value = fabs(value);
1625 int degrees = (int) value;
1626
1627 double remainder = value - degrees;
1628 int minutes = (int) (remainder * 60);
1629 int seconds = (int) (((remainder * 60) - minutes) * 60 * 1000);
1630
1631 *pDegrees = degrees;
1632 *pMinutes = minutes;
1633 *pSeconds = seconds;
1634}
1635
1636static void setLatLon(exif_tag_id_t tag, const char *latlonString) {
1637
1638 int degrees, minutes, seconds;
1639
1640 parseLatLong(latlonString, &degrees, &minutes, &seconds);
1641
1642 rat_t value[3] = { {degrees, 1},
1643 {minutes, 1},
1644 {seconds, 1000} };
1645
1646 if(tag == EXIFTAGID_GPS_LATITUDE) {
1647 memcpy(latitude, value, sizeof(latitude));
1648 addExifTag(EXIFTAGID_GPS_LATITUDE, EXIF_RATIONAL, 3,
1649 1, (void *)latitude);
1650 } else {
1651 memcpy(longitude, value, sizeof(longitude));
1652 addExifTag(EXIFTAGID_GPS_LONGITUDE, EXIF_RATIONAL, 3,
1653 1, (void *)longitude);
1654 }
1655}
1656
1657void QualcommCameraHardware::setGpsParameters() {
1658 const char *str = NULL;
1659
1660 //Set Latitude
1661 str = mParameters.get(CameraParameters::KEY_GPS_LATITUDE);
1662 if(str != NULL) {
1663 setLatLon(EXIFTAGID_GPS_LATITUDE, str);
1664 //set Latitude Ref
1665 str = NULL;
1666 str = mParameters.get(CameraParameters::KEY_GPS_LATITUDE_REF);
1667 if(str != NULL) {
1668 strncpy(latref, str, 1);
1669 latref[1] = '\0';
1670 addExifTag(EXIFTAGID_GPS_LATITUDE_REF, EXIF_ASCII, 2,
1671 1, (void *)latref);
1672 }
1673 }
1674
1675 //set Longitude
1676 str = NULL;
1677 str = mParameters.get(CameraParameters::KEY_GPS_LONGITUDE);
1678 if(str != NULL) {
1679 setLatLon(EXIFTAGID_GPS_LONGITUDE, str);
1680 //set Longitude Ref
1681 str = NULL;
1682 str = mParameters.get(CameraParameters::KEY_GPS_LONGITUDE_REF);
1683 if(str != NULL) {
1684 strncpy(lonref, str, 1);
1685 lonref[1] = '\0';
1686 addExifTag(EXIFTAGID_GPS_LONGITUDE_REF, EXIF_ASCII, 2,
1687 1, (void *)lonref);
1688 }
1689 }
1690
1691 //set Altitude
1692 str = NULL;
1693 str = mParameters.get(CameraParameters::KEY_GPS_ALTITUDE);
1694 if(str != NULL) {
1695 int value = atoi(str);
1696 rat_t alt_value = {value, 1000};
1697 memcpy(&altitude, &alt_value, sizeof(altitude));
1698 addExifTag(EXIFTAGID_GPS_ALTITUDE, EXIF_RATIONAL, 1,
1699 1, (void *)&altitude);
1700 //set AltitudeRef
1701 int ref = mParameters.getInt(CameraParameters::KEY_GPS_ALTITUDE_REF);
1702 if( !(ref < 0 || ref > 1) )
1703 addExifTag(EXIFTAGID_GPS_ALTITUDE_REF, EXIF_BYTE, 1,
1704 1, (void *)&ref);
1705 }
1706
1707
1708}
1709
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001710bool QualcommCameraHardware::native_jpeg_encode(void)
1711{
1712 int jpeg_quality = mParameters.getInt("jpeg-quality");
1713 if (jpeg_quality >= 0) {
1714 LOGV("native_jpeg_encode, current jpeg main img quality =%d",
1715 jpeg_quality);
1716 if(!LINK_jpeg_encoder_setMainImageQuality(jpeg_quality)) {
1717 LOGE("native_jpeg_encode set jpeg-quality failed");
1718 return false;
1719 }
1720 }
1721
1722 int thumbnail_quality = mParameters.getInt("jpeg-thumbnail-quality");
1723 if (thumbnail_quality >= 0) {
1724 LOGV("native_jpeg_encode, current jpeg thumbnail quality =%d",
1725 thumbnail_quality);
1726 if(!LINK_jpeg_encoder_setThumbnailQuality(thumbnail_quality)) {
1727 LOGE("native_jpeg_encode set thumbnail-quality failed");
1728 return false;
1729 }
1730 }
1731
1732 int rotation = mParameters.getInt("rotation");
1733 if (rotation >= 0) {
1734 LOGV("native_jpeg_encode, rotation = %d", rotation);
1735 if(!LINK_jpeg_encoder_setRotation(rotation)) {
1736 LOGE("native_jpeg_encode set rotation failed");
1737 return false;
1738 }
1739 }
1740
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001741// jpeg_set_location();
1742 if(mParameters.getInt(CameraParameters::KEY_GPS_STATUS) == 1) {
1743 setGpsParameters();
1744 }
1745 //set TimeStamp
1746 const char *str = mParameters.get(CameraParameters::KEY_EXIF_DATETIME);
1747 if(str != NULL) {
1748 strncpy(dateTime, str, 19);
1749 dateTime[19] = '\0';
1750 addExifTag(EXIFTAGID_EXIF_DATE_TIME_ORIGINAL, EXIF_ASCII,
1751 20, 1, (void *)dateTime);
1752 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001753
1754 if (!LINK_jpeg_encoder_encode(&mDimension,
1755 (uint8_t *)mThumbnailHeap->mHeap->base(),
1756 mThumbnailHeap->mHeap->getHeapID(),
1757 (uint8_t *)mRawHeap->mHeap->base(),
1758 mRawHeap->mHeap->getHeapID(),
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001759 &mCrop, exif_data, exif_table_numEntries)) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001760 LOGE("native_jpeg_encode: jpeg_encoder_encode failed.");
1761 return false;
1762 }
1763 return true;
1764}
1765
1766bool QualcommCameraHardware::native_set_parm(
1767 cam_ctrl_type type, uint16_t length, void *value)
1768{
1769 struct msm_ctrl_cmd ctrlCmd;
1770
1771 ctrlCmd.timeout_ms = 5000;
1772 ctrlCmd.type = (uint16_t)type;
1773 ctrlCmd.length = length;
1774 // FIXME: this will be put in by the kernel
1775 ctrlCmd.resp_fd = mCameraControlFd;
1776 ctrlCmd.value = value;
1777
1778 LOGV("%s: fd %d, type %d, length %d", __FUNCTION__,
1779 mCameraControlFd, type, length);
1780 if (ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0 ||
1781 ctrlCmd.status != CAM_CTRL_SUCCESS) {
1782 LOGE("%s: error (%s): fd %d, type %d, length %d, status %d",
1783 __FUNCTION__, strerror(errno),
1784 mCameraControlFd, type, length, ctrlCmd.status);
1785 return false;
1786 }
1787 return true;
1788}
1789
1790void QualcommCameraHardware::jpeg_set_location()
1791{
1792 bool encode_location = true;
1793 camera_position_type pt;
1794
1795#define PARSE_LOCATION(what,type,fmt,desc) do { \
1796 pt.what = 0; \
1797 const char *what##_str = mParameters.get("gps-"#what); \
1798 LOGV("GPS PARM %s --> [%s]", "gps-"#what, what##_str); \
1799 if (what##_str) { \
1800 type what = 0; \
1801 if (sscanf(what##_str, fmt, &what) == 1) \
1802 pt.what = what; \
1803 else { \
1804 LOGE("GPS " #what " %s could not" \
1805 " be parsed as a " #desc, what##_str); \
1806 encode_location = false; \
1807 } \
1808 } \
1809 else { \
1810 LOGV("GPS " #what " not specified: " \
1811 "defaulting to zero in EXIF header."); \
1812 encode_location = false; \
1813 } \
1814 } while(0)
1815
1816 PARSE_LOCATION(timestamp, long, "%ld", "long");
1817 if (!pt.timestamp) pt.timestamp = time(NULL);
1818 PARSE_LOCATION(altitude, short, "%hd", "short");
1819 PARSE_LOCATION(latitude, double, "%lf", "double float");
1820 PARSE_LOCATION(longitude, double, "%lf", "double float");
1821
1822#undef PARSE_LOCATION
1823
1824 if (encode_location) {
1825 LOGD("setting image location ALT %d LAT %lf LON %lf",
1826 pt.altitude, pt.latitude, pt.longitude);
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001827/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001828 if (!LINK_jpeg_encoder_setLocation(&pt)) {
1829 LOGE("jpeg_set_location: LINK_jpeg_encoder_setLocation failed.");
1830 }
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001831*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001832 }
1833 else LOGV("not setting image location");
1834}
1835
1836void QualcommCameraHardware::runFrameThread(void *data)
1837{
1838 LOGV("runFrameThread E");
1839
1840 int cnt;
1841
1842#if DLOPEN_LIBMMCAMERA
1843 // We need to maintain a reference to libqcamera.so for the duration of the
1844 // frame thread, because we do not know when it will exit relative to the
1845 // lifetime of this object. We do not want to dlclose() libqcamera while
1846 // LINK_cam_frame is still running.
1847 void *libhandle = ::dlopen("liboemcamera.so", RTLD_NOW);
1848 LOGV("FRAME: loading libqcamera at %p", libhandle);
1849 if (!libhandle) {
1850 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
1851 }
1852 if (libhandle)
1853#endif
1854 {
1855 LINK_cam_frame(data);
1856 }
1857
Mohan Kandrad9efed92010-01-15 19:08:39 -08001858 mPreviewHeap.clear();
Mohan Kandraf1ebf982010-02-02 15:25:43 -08001859 if(( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250))
Sravankb4f5f1c2010-01-21 11:06:17 +05301860 mRecordHeap.clear();
1861
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001862#if DLOPEN_LIBMMCAMERA
1863 if (libhandle) {
1864 ::dlclose(libhandle);
1865 LOGV("FRAME: dlclose(libqcamera)");
1866 }
1867#endif
1868
1869 mFrameThreadWaitLock.lock();
1870 mFrameThreadRunning = false;
1871 mFrameThreadWait.signal();
1872 mFrameThreadWaitLock.unlock();
1873
1874 LOGV("runFrameThread X");
1875}
1876
Sravankb4f5f1c2010-01-21 11:06:17 +05301877void QualcommCameraHardware::runVideoThread(void *data)
1878{
1879 LOGD("runVideoThread E");
1880 msm_frame* vframe = NULL;
1881
1882 while(true) {
1883 pthread_mutex_lock(&(g_busy_frame_queue.mut));
1884
Kiran Kumar H Nb49af212010-02-17 15:12:17 -08001885 LOGV("in video_thread : wait for video frame ");
Sravankb4f5f1c2010-01-21 11:06:17 +05301886 // check if any frames are available in busyQ and give callback to
1887 // services/video encoder
1888 cam_frame_wait_video();
1889 LOGV("video_thread, wait over..");
1890
1891 // Exit the thread , in case of stop recording..
1892 mVideoThreadWaitLock.lock();
1893 if(mVideoThreadExit){
Kiran Kumar H Nb49af212010-02-17 15:12:17 -08001894 LOGV("Exiting video thread..");
Sravankb4f5f1c2010-01-21 11:06:17 +05301895 mVideoThreadWaitLock.unlock();
1896 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
1897 break;
1898 }
1899 mVideoThreadWaitLock.unlock();
1900
1901 // Get the video frame to be encoded
1902 vframe = cam_frame_get_video ();
Apurva Rajgurud9b0b302010-02-19 11:22:56 -08001903 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
Sravankb4f5f1c2010-01-21 11:06:17 +05301904 LOGV("in video_thread : got video frame ");
1905
Mohan Kandrabad0eaa2010-02-04 15:11:54 -08001906 if (UNLIKELY(mDebugFps)) {
1907 debugShowVideoFPS();
1908 }
1909
Sravankb4f5f1c2010-01-21 11:06:17 +05301910 if(vframe != NULL) {
1911 // Find the offset within the heap of the current buffer.
1912 LOGV("Got video frame : buffer %d base %d ", vframe->buffer, mRecordHeap->mHeap->base());
1913 ssize_t offset =
1914 (ssize_t)vframe->buffer - (ssize_t)mRecordHeap->mHeap->base();
1915 LOGV("offset = %d , alignsize = %d , offset later = %d", offset, mRecordHeap->mAlignedBufferSize, (offset / mRecordHeap->mAlignedBufferSize));
1916
1917 offset /= mRecordHeap->mAlignedBufferSize;
1918
1919 // dump frames for test purpose
1920#ifdef DUMP_VIDEO_FRAMES
1921 static int frameCnt = 0;
1922 if (frameCnt >= 11 && frameCnt <= 13 ) {
1923 char buf[128];
1924 sprintf(buf, "/data/%d_v.yuv", frameCnt);
1925 int file_fd = open(buf, O_RDWR | O_CREAT, 0777);
1926 LOGV("dumping video frame %d", frameCnt);
1927 if (file_fd < 0) {
1928 LOGE("cannot open file\n");
1929 }
1930 else
1931 {
1932 write(file_fd, (const void *)vframe->buffer,
1933 vframe->cbcr_off * 3 / 2);
1934 }
1935 close(file_fd);
1936 }
1937 frameCnt++;
1938#endif
1939 // Enable IF block to give frames to encoder , ELSE block for just simulation
1940#if 1
1941 LOGV("in video_thread : got video frame, before if check giving frame to services/encoder");
1942 mCallbackLock.lock();
1943 int msgEnabled = mMsgEnabled;
1944 data_callback_timestamp rcb = mDataCallbackTimestamp;
1945 void *rdata = mCallbackCookie;
1946 mCallbackLock.unlock();
1947
1948 if(rcb != NULL && (msgEnabled & CAMERA_MSG_VIDEO_FRAME) ) {
1949 LOGV("in video_thread : got video frame, giving frame to services/encoder");
1950 rcb(systemTime(), CAMERA_MSG_VIDEO_FRAME, mRecordHeap->mBuffers[offset], rdata);
Sravankb4f5f1c2010-01-21 11:06:17 +05301951 }
1952#else
1953 // 720p output2 : simulate release frame here:
1954 LOGE("in video_thread simulation , releasing the video frame");
1955 LINK_camframe_free_video(vframe);
1956#endif
1957
1958 } else LOGE("in video_thread get frame returned null");
1959
Sravankb4f5f1c2010-01-21 11:06:17 +05301960
1961 } // end of while loop
Mohan Kandra156d0ac2010-01-25 16:59:17 -08001962
1963 mVideoThreadWaitLock.lock();
1964 mVideoThreadRunning = false;
1965 mVideoThreadWait.signal();
1966 mVideoThreadWaitLock.unlock();
1967
Sravankb4f5f1c2010-01-21 11:06:17 +05301968 LOGV("runVideoThread X");
1969}
1970
1971void *video_thread(void *user)
1972{
1973 LOGV("video_thread E");
1974 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
1975 if (obj != 0) {
1976 obj->runVideoThread(user);
1977 }
1978 else LOGE("not starting video thread: the object went away!");
1979 LOGV("video_thread X");
1980 return NULL;
1981}
1982
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001983void *frame_thread(void *user)
1984{
1985 LOGD("frame_thread E");
1986 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
1987 if (obj != 0) {
1988 obj->runFrameThread(user);
1989 }
1990 else LOGW("not starting frame thread: the object went away!");
1991 LOGD("frame_thread X");
1992 return NULL;
1993}
1994
1995bool QualcommCameraHardware::initPreview()
1996{
1997 // See comments in deinitPreview() for why we have to wait for the frame
1998 // thread here, and why we can't use pthread_join().
Sravankb4f5f1c2010-01-21 11:06:17 +05301999 int videoWidth, videoHeight;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002000 mParameters.getPreviewSize(&previewWidth, &previewHeight);
Sravankb4f5f1c2010-01-21 11:06:17 +05302001
2002 videoWidth = previewWidth; // temporary , should be configurable later
2003 videoHeight = previewHeight;
2004 LOGV("initPreview E: preview size=%dx%d videosize = %d x %d", previewWidth, previewHeight, videoWidth, videoHeight );
2005
Mohan Kandraf1ebf982010-02-02 15:25:43 -08002006 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05302007 mDimension.video_width = videoWidth;
Kiran Kumar H N7ac84e32010-02-01 10:58:47 -08002008 mDimension.video_width = CEILING16(mDimension.video_width);
Sravankb4f5f1c2010-01-21 11:06:17 +05302009 mDimension.video_height = videoHeight;
Sravank64461e82010-02-25 15:10:09 +05302010 // for 720p , preview can be 768X432
2011 previewWidth = mDimension.display_width;
2012 previewHeight= mDimension.display_height;
Sravankb4f5f1c2010-01-21 11:06:17 +05302013 LOGV("initPreview : preview size=%dx%d videosize = %d x %d", previewWidth, previewHeight, mDimension.video_width, mDimension.video_height );
2014 }
2015
2016
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002017 mFrameThreadWaitLock.lock();
2018 while (mFrameThreadRunning) {
2019 LOGV("initPreview: waiting for old frame thread to complete.");
2020 mFrameThreadWait.wait(mFrameThreadWaitLock);
2021 LOGV("initPreview: old frame thread completed.");
2022 }
2023 mFrameThreadWaitLock.unlock();
2024
2025 mSnapshotThreadWaitLock.lock();
2026 while (mSnapshotThreadRunning) {
2027 LOGV("initPreview: waiting for old snapshot thread to complete.");
2028 mSnapshotThreadWait.wait(mSnapshotThreadWaitLock);
2029 LOGV("initPreview: old snapshot thread completed.");
2030 }
2031 mSnapshotThreadWaitLock.unlock();
2032
2033 int cnt = 0;
2034 mPreviewFrameSize = previewWidth * previewHeight * 3/2;
Mohan Kandrad9efed92010-01-15 19:08:39 -08002035 dstOffset = 0;
2036 mPreviewHeap = new PmemPool("/dev/pmem_adsp",
Mohan Kandra284966d2010-01-05 13:39:15 -08002037 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
2038 mCameraControlFd,
Sravankb4f5f1c2010-01-21 11:06:17 +05302039 MSM_PMEM_PREVIEW, //MSM_PMEM_OUTPUT2,
Mohan Kandra284966d2010-01-05 13:39:15 -08002040 mPreviewFrameSize,
Mohan Kandrad9efed92010-01-15 19:08:39 -08002041 kPreviewBufferCountActual,
Mohan Kandra284966d2010-01-05 13:39:15 -08002042 mPreviewFrameSize,
Mohan Kandrad9efed92010-01-15 19:08:39 -08002043 "preview");
Mohan Kandra284966d2010-01-05 13:39:15 -08002044
Mohan Kandrad9efed92010-01-15 19:08:39 -08002045 if (!mPreviewHeap->initialized()) {
2046 mPreviewHeap.clear();
Mohan Kandra284966d2010-01-05 13:39:15 -08002047 LOGE("initPreview X: could not initialize Camera preview heap.");
2048 return false;
2049 }
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002050 if( mCurrentTarget == TARGET_MSM7630 ) {
Srinivasan Kannan613301c2010-02-10 17:08:53 -08002051 mPostViewHeap.clear();
Kiran Kumar H N595970b2010-01-12 10:41:09 -08002052 if(mPostViewHeap == NULL) {
2053 LOGV(" Allocating Postview heap ");
2054 /* mPostViewHeap should be declared only for 7630 target */
2055 mPostViewHeap =
2056 new PmemPool("/dev/pmem_adsp",
2057 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
2058 mCameraControlFd,
Sravankb4f5f1c2010-01-21 11:06:17 +05302059 MSM_PMEM_PREVIEW, //MSM_PMEM_OUTPUT2,
Kiran Kumar H N595970b2010-01-12 10:41:09 -08002060 mPreviewFrameSize,
2061 1,
2062 mPreviewFrameSize,
2063 "postview");
Mohan Kandra284966d2010-01-05 13:39:15 -08002064
Kiran Kumar H N595970b2010-01-12 10:41:09 -08002065 if (!mPostViewHeap->initialized()) {
2066 mPostViewHeap.clear();
2067 LOGE(" Failed to initialize Postview Heap");
2068 return false;
2069 }
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002070 }
Mohan Kandraf1ebf982010-02-02 15:25:43 -08002071 }
2072
2073 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250) ) {
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002074
2075 // Allocate video buffers after allocating preview buffers.
Sravankb4f5f1c2010-01-21 11:06:17 +05302076 initRecord();
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002077 }
Sravankb4f5f1c2010-01-21 11:06:17 +05302078
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002079 // mDimension will be filled with thumbnail_width, thumbnail_height,
2080 // orig_picture_dx, and orig_picture_dy after this function call. We need to
2081 // keep it for jpeg_encoder_encode.
2082 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
2083 sizeof(cam_ctrl_dimension_t), &mDimension);
2084
2085 if (ret) {
2086 for (cnt = 0; cnt < kPreviewBufferCount; cnt++) {
Mohan Kandrad9efed92010-01-15 19:08:39 -08002087 frames[cnt].fd = mPreviewHeap->mHeap->getHeapID();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002088 frames[cnt].buffer =
Mohan Kandrad9efed92010-01-15 19:08:39 -08002089 (uint32_t)mPreviewHeap->mHeap->base() + mPreviewHeap->mAlignedBufferSize * cnt;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002090 frames[cnt].y_off = 0;
2091 frames[cnt].cbcr_off = previewWidth * previewHeight;
Sravankb4f5f1c2010-01-21 11:06:17 +05302092 frames[cnt].path = OUTPUT_TYPE_P; // MSM_FRAME_ENC;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002093 }
2094
2095 mFrameThreadWaitLock.lock();
2096 pthread_attr_t attr;
2097 pthread_attr_init(&attr);
2098 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
Sravankb4f5f1c2010-01-21 11:06:17 +05302099
2100 frame_parms.frame = frames[kPreviewBufferCount - 1];
2101 frame_parms.video_frame = recordframes[kPreviewBufferCount - 1];
2102
2103 LOGV ("initpreview before cam_frame thread carete , video frame buffer=%lu fd=%d y_off=%d cbcr_off=%d \n",
2104 (unsigned long)frame_parms.video_frame.buffer, frame_parms.video_frame.fd, frame_parms.video_frame.y_off,
2105 frame_parms.video_frame.cbcr_off);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002106 mFrameThreadRunning = !pthread_create(&mFrameThread,
2107 &attr,
2108 frame_thread,
Sravankb4f5f1c2010-01-21 11:06:17 +05302109 (void*)&(frame_parms));
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002110 ret = mFrameThreadRunning;
2111 mFrameThreadWaitLock.unlock();
2112 }
2113
2114 LOGV("initPreview X: %d", ret);
2115 return ret;
2116}
2117
2118void QualcommCameraHardware::deinitPreview(void)
2119{
2120 LOGI("deinitPreview E");
2121
2122 // When we call deinitPreview(), we signal to the frame thread that it
2123 // needs to exit, but we DO NOT WAIT for it to complete here. The problem
2124 // is that deinitPreview is sometimes called from the frame-thread's
2125 // callback, when the refcount on the Camera client reaches zero. If we
2126 // called pthread_join(), we would deadlock. So, we just call
2127 // LINK_camframe_terminate() in deinitPreview(), which makes sure that
2128 // after the preview callback returns, the camframe thread will exit. We
2129 // could call pthread_join() in initPreview() to join the last frame
2130 // thread. However, we would also have to call pthread_join() in release
2131 // as well, shortly before we destroy the object; this would cause the same
2132 // deadlock, since release(), like deinitPreview(), may also be called from
2133 // the frame-thread's callback. This we have to make the frame thread
2134 // detached, and use a separate mechanism to wait for it to complete.
2135
Kiran Kumar H N7ac84e32010-02-01 10:58:47 -08002136 LINK_camframe_terminate();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002137 LOGI("deinitPreview X");
2138}
2139
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002140bool QualcommCameraHardware::initRawSnapshot()
2141{
2142 LOGV("initRawSnapshot E");
2143
2144 //get width and height from Dimension Object
2145 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
2146 sizeof(cam_ctrl_dimension_t), &mDimension);
2147
2148 if(!ret){
2149 LOGE("initRawSnapshot X: failed to set dimension");
2150 return false;
2151 }
2152 int rawSnapshotSize = mDimension.raw_picture_height *
2153 mDimension.raw_picture_width;
2154
2155 LOGV("raw_snapshot_buffer_size = %d, raw_picture_height = %d, "\
2156 "raw_picture_width = %d",
2157 rawSnapshotSize, mDimension.raw_picture_height,
2158 mDimension.raw_picture_width);
2159
2160 if (mRawSnapShotPmemHeap != NULL) {
2161 LOGV("initRawSnapshot: clearing old mRawSnapShotPmemHeap.");
2162 mRawSnapShotPmemHeap.clear();
2163 }
2164
2165 //Pmem based pool for Camera Driver
2166 mRawSnapShotPmemHeap = new PmemPool("/dev/pmem_adsp",
2167 MemoryHeapBase::READ_ONLY,
2168 mCameraControlFd,
2169 MSM_PMEM_RAW_MAINIMG,
2170 rawSnapshotSize,
2171 1,
2172 rawSnapshotSize,
2173 "raw pmem snapshot camera");
2174
2175 if (!mRawSnapShotPmemHeap->initialized()) {
2176 mRawSnapShotPmemHeap.clear();
2177 LOGE("initRawSnapshot X: error initializing mRawSnapshotHeap");
2178 return false;
2179 }
2180 LOGV("initRawSnapshot X");
2181 return true;
2182
2183}
2184
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002185bool QualcommCameraHardware::initRaw(bool initJpegHeap)
2186{
2187 int rawWidth, rawHeight;
Apurva Rajguru8d1773b2009-12-02 14:21:23 -08002188
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002189 mParameters.getPictureSize(&rawWidth, &rawHeight);
2190 LOGV("initRaw E: picture size=%dx%d", rawWidth, rawHeight);
2191
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08002192 int thumbnailBufferSize;
2193 //Thumbnail height should be smaller than Picture height
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002194 if (rawHeight > (int)thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height){
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08002195 mDimension.ui_thumbnail_width =
2196 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].width;
2197 mDimension.ui_thumbnail_height =
2198 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height;
2199 uint32_t pictureAspectRatio = (uint32_t)((rawWidth * Q12) / rawHeight);
2200 uint32_t i;
2201 for(i = 0; i < THUMBNAIL_SIZE_COUNT; i++ )
2202 {
2203 if(thumbnail_sizes[i].aspect_ratio == pictureAspectRatio)
2204 {
2205 mDimension.ui_thumbnail_width = thumbnail_sizes[i].width;
2206 mDimension.ui_thumbnail_height = thumbnail_sizes[i].height;
2207 break;
2208 }
2209 }
2210 }
2211 else{
2212 mDimension.ui_thumbnail_height = THUMBNAIL_SMALL_HEIGHT;
2213 mDimension.ui_thumbnail_width =
2214 (THUMBNAIL_SMALL_HEIGHT * rawWidth)/ rawHeight;
2215 }
2216
2217 LOGV("Thumbnail Size Width %d Height %d",
2218 mDimension.ui_thumbnail_width,
2219 mDimension.ui_thumbnail_height);
2220
2221 thumbnailBufferSize = mDimension.ui_thumbnail_width *
2222 mDimension.ui_thumbnail_height * 3 / 2;
2223
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002224 // mDimension will be filled with thumbnail_width, thumbnail_height,
2225 // orig_picture_dx, and orig_picture_dy after this function call. We need to
2226 // keep it for jpeg_encoder_encode.
2227 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
2228 sizeof(cam_ctrl_dimension_t), &mDimension);
2229 if(!ret) {
2230 LOGE("initRaw X: failed to set dimension");
2231 return false;
2232 }
2233
2234 if (mJpegHeap != NULL) {
2235 LOGV("initRaw: clearing old mJpegHeap.");
2236 mJpegHeap.clear();
2237 }
2238
2239 // Snapshot
2240 mRawSize = rawWidth * rawHeight * 3 / 2;
Apurva Rajguru8d1773b2009-12-02 14:21:23 -08002241
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002242 if( mCurrentTarget == TARGET_MSM7627 )
Apurva Rajguru8d1773b2009-12-02 14:21:23 -08002243 mJpegMaxSize = CEILING16(rawWidth) * CEILING16(rawHeight) * 3 / 2;
2244 else
2245 mJpegMaxSize = rawWidth * rawHeight * 3 / 2;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002246
2247 LOGV("initRaw: initializing mRawHeap.");
2248 mRawHeap =
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002249 new PmemPool("/dev/pmem_adsp",
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002250 MemoryHeapBase::READ_ONLY,
2251 mCameraControlFd,
2252 MSM_PMEM_MAINIMG,
2253 mJpegMaxSize,
2254 kRawBufferCount,
2255 mRawSize,
2256 "snapshot camera");
2257
2258 if (!mRawHeap->initialized()) {
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002259 LOGE("initRaw X failed ");
2260 mRawHeap.clear();
2261 LOGE("initRaw X: error initializing mRawHeap");
2262 return false;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002263 }
2264
2265 LOGV("do_mmap snapshot pbuf = %p, pmem_fd = %d",
2266 (uint8_t *)mRawHeap->mHeap->base(), mRawHeap->mHeap->getHeapID());
2267
2268 // Jpeg
2269
2270 if (initJpegHeap) {
2271 LOGV("initRaw: initializing mJpegHeap.");
2272 mJpegHeap =
2273 new AshmemPool(mJpegMaxSize,
2274 kJpegBufferCount,
2275 0, // we do not know how big the picture will be
2276 "jpeg");
2277
2278 if (!mJpegHeap->initialized()) {
2279 mJpegHeap.clear();
2280 mRawHeap.clear();
2281 LOGE("initRaw X failed: error initializing mJpegHeap.");
2282 return false;
2283 }
2284
2285 // Thumbnails
2286
2287 mThumbnailHeap =
2288 new PmemPool("/dev/pmem_adsp",
2289 MemoryHeapBase::READ_ONLY,
2290 mCameraControlFd,
2291 MSM_PMEM_THUMBNAIL,
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08002292 thumbnailBufferSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002293 1,
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08002294 thumbnailBufferSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002295 "thumbnail");
2296
2297 if (!mThumbnailHeap->initialized()) {
2298 mThumbnailHeap.clear();
2299 mJpegHeap.clear();
2300 mRawHeap.clear();
2301 LOGE("initRaw X failed: error initializing mThumbnailHeap.");
2302 return false;
2303 }
2304 }
2305
2306 LOGV("initRaw X");
2307 return true;
2308}
2309
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002310
2311void QualcommCameraHardware::deinitRawSnapshot()
2312{
2313 LOGV("deinitRawSnapshot E");
2314 mRawSnapShotPmemHeap.clear();
2315 mRawSnapshotAshmemHeap.clear();
2316 LOGV("deinitRawSnapshot X");
2317}
2318
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002319void QualcommCameraHardware::deinitRaw()
2320{
2321 LOGV("deinitRaw E");
2322
2323 mThumbnailHeap.clear();
2324 mJpegHeap.clear();
2325 mRawHeap.clear();
2326 mDisplayHeap.clear();
2327
2328 LOGV("deinitRaw X");
2329}
2330
2331void QualcommCameraHardware::release()
2332{
2333 LOGD("release E");
2334 Mutex::Autolock l(&mLock);
2335
2336#if DLOPEN_LIBMMCAMERA
2337 if (libmmcamera == NULL) {
2338 LOGE("ERROR: multiple release!");
2339 return;
2340 }
2341#else
2342#warning "Cannot detect multiple release when not dlopen()ing libqcamera!"
2343#endif
2344
2345 int cnt, rc;
2346 struct msm_ctrl_cmd ctrlCmd;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002347 if (mCameraRunning) {
2348 if(mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME)) {
2349 mRecordFrameLock.lock();
2350 mReleasedRecordingFrame = true;
2351 mRecordWait.signal();
2352 mRecordFrameLock.unlock();
2353 }
2354 stopPreviewInternal();
2355 }
2356
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002357 if( mCurrentTarget == TARGET_MSM7630 ) {
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002358 mPostViewHeap.clear();
2359 mPostViewHeap = NULL;
2360 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002361 LINK_jpeg_encoder_join();
2362 deinitRaw();
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002363 deinitRawSnapshot();
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002364 {
2365 Mutex::Autolock l(&mCamframeTimeoutLock);
2366 if(!camframe_timeout_flag) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002367
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002368 ctrlCmd.timeout_ms = 5000;
2369 ctrlCmd.length = 0;
2370 ctrlCmd.type = (uint16_t)CAMERA_EXIT;
2371 ctrlCmd.resp_fd = mCameraControlFd; // FIXME: this will be put in by the kernel
2372 if (ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0)
2373 LOGE("ioctl CAMERA_EXIT fd %d error %s",
2374 mCameraControlFd, strerror(errno));
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002375
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002376 }
2377 }
Kiran Kumar H N7ac84e32010-02-01 10:58:47 -08002378 LINK_release_cam_conf_thread();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002379 close(mCameraControlFd);
2380 mCameraControlFd = -1;
Mohan Kandra284966d2010-01-05 13:39:15 -08002381 if(fb_fd >= 0) {
2382 close(fb_fd);
2383 fb_fd = -1;
2384 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002385#if DLOPEN_LIBMMCAMERA
2386 if (libmmcamera) {
2387 ::dlclose(libmmcamera);
2388 LOGV("dlclose(libqcamera)");
2389 libmmcamera = NULL;
2390 }
2391#endif
2392
2393 Mutex::Autolock lock(&singleton_lock);
2394 singleton_releasing = true;
2395
2396 LOGD("release X");
2397}
2398
2399QualcommCameraHardware::~QualcommCameraHardware()
2400{
2401 LOGD("~QualcommCameraHardware E");
2402 Mutex::Autolock lock(&singleton_lock);
2403 singleton.clear();
2404 singleton_releasing = false;
2405 singleton_wait.signal();
2406 LOGD("~QualcommCameraHardware X");
2407}
2408
2409sp<IMemoryHeap> QualcommCameraHardware::getRawHeap() const
2410{
2411 LOGV("getRawHeap");
2412 return mDisplayHeap != NULL ? mDisplayHeap->mHeap : NULL;
2413}
2414
2415sp<IMemoryHeap> QualcommCameraHardware::getPreviewHeap() const
2416{
2417 LOGV("getPreviewHeap");
Mohan Kandrad9efed92010-01-15 19:08:39 -08002418 return mPreviewHeap != NULL ? mPreviewHeap->mHeap : NULL;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002419}
2420
2421status_t QualcommCameraHardware::startPreviewInternal()
2422{
Sravankb4f5f1c2010-01-21 11:06:17 +05302423 LOGV("in startPreviewInternal : E");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002424 if(mCameraRunning) {
2425 LOGV("startPreview X: preview already running.");
2426 return NO_ERROR;
2427 }
2428
2429 if (!mPreviewInitialized) {
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002430 mLastQueuedFrame = NULL;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002431 mPreviewInitialized = initPreview();
2432 if (!mPreviewInitialized) {
2433 LOGE("startPreview X initPreview failed. Not starting preview.");
2434 return UNKNOWN_ERROR;
2435 }
2436 }
2437
Mohan Kandraf1ebf982010-02-02 15:25:43 -08002438 if(( mCurrentTarget != TARGET_MSM7630 ) && (mCurrentTarget != TARGET_QSD8250))
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002439 mCameraRunning = native_start_preview(mCameraControlFd);
Sravankb4f5f1c2010-01-21 11:06:17 +05302440 else
2441 mCameraRunning = native_start_video(mCameraControlFd);
2442
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002443 if(!mCameraRunning) {
2444 deinitPreview();
2445 mPreviewInitialized = false;
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08002446 mOverlay = NULL;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002447 LOGE("startPreview X: native_start_preview failed!");
2448 return UNKNOWN_ERROR;
2449 }
2450
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08002451 //Reset the Gps Information
2452 exif_table_numEntries = 0;
Mohan Kandra284966d2010-01-05 13:39:15 -08002453
2454 if(native_get_maxzoom(mCameraControlFd, (void *)&mMaxZoom) == true){
Brian Steuerb62adbd2010-02-02 14:47:08 -08002455 LOGD("Maximum zoom value is %d", mMaxZoom);
Mohan Kandra284966d2010-01-05 13:39:15 -08002456 mParameters.set("zoom-supported", "true");
2457 } else {
2458 LOGE("Failed to get maximum zoom value...setting max zoom to zero");
2459 mParameters.set("zoom-supported", "false");
2460 mMaxZoom = 0;
2461 }
2462 mParameters.set("max-zoom",mMaxZoom);
2463
Sravankb4f5f1c2010-01-21 11:06:17 +05302464 LOGV("startPreviewInternal X");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002465 return NO_ERROR;
2466}
2467
2468status_t QualcommCameraHardware::startPreview()
2469{
2470 LOGV("startPreview E");
2471 Mutex::Autolock l(&mLock);
2472 return startPreviewInternal();
2473}
2474
2475void QualcommCameraHardware::stopPreviewInternal()
2476{
2477 LOGV("stopPreviewInternal E: %d", mCameraRunning);
2478 if (mCameraRunning) {
2479 // Cancel auto focus.
2480 {
2481 if (mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS)) {
2482 cancelAutoFocusInternal();
2483 }
2484 }
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002485
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002486 Mutex::Autolock l(&mCamframeTimeoutLock);
2487 if(!camframe_timeout_flag) {
Mohan Kandraf1ebf982010-02-02 15:25:43 -08002488 if (( mCurrentTarget != TARGET_MSM7630 ) && (mCurrentTarget != TARGET_QSD8250))
Sravankb4f5f1c2010-01-21 11:06:17 +05302489 mCameraRunning = !native_stop_preview(mCameraControlFd);
2490 else
2491 mCameraRunning = !native_stop_video(mCameraControlFd);
2492
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002493 } else {
2494 /* This means that the camframetimeout was issued.
2495 * But we did not issue native_stop_preview(), so we
Kiran Kumar H Nac2f4952009-12-17 01:16:53 -08002496 * need to update mCameraRunning to indicate that
2497 * Camera is no longer running. */
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002498 mCameraRunning = 0;
Kiran Kumar H Nac2f4952009-12-17 01:16:53 -08002499 }
2500 if (!mCameraRunning && mPreviewInitialized) {
2501 deinitPreview();
Mohan Kandraf1ebf982010-02-02 15:25:43 -08002502 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250)) {
Mohan Kandra156d0ac2010-01-25 16:59:17 -08002503 mVideoThreadWaitLock.lock();
2504 LOGV("in stopPreviewInternal: making mVideoThreadExit 1");
2505 mVideoThreadExit = 1;
2506 mVideoThreadWaitLock.unlock();
2507 // 720p : signal the video thread , and check in video thread if stop is called, if so exit video thread.
2508 pthread_mutex_lock(&(g_busy_frame_queue.mut));
2509 pthread_cond_signal(&(g_busy_frame_queue.wait));
2510 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
Mohan Kandra1ade9a82010-03-02 10:11:26 -08002511 /* Flush the Busy Q */
2512 cam_frame_flush_video();
2513 /* Flush the Free Q */
2514 LINK_cam_frame_flush_free_video();
Mohan Kandra156d0ac2010-01-25 16:59:17 -08002515 }
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002516 mPreviewInitialized = false;
2517 }
Kiran Kumar H Nac2f4952009-12-17 01:16:53 -08002518 else LOGE("stopPreviewInternal: failed to stop preview");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002519 }
2520 LOGV("stopPreviewInternal X: %d", mCameraRunning);
2521}
2522
2523void QualcommCameraHardware::stopPreview()
2524{
2525 LOGV("stopPreview: E");
2526 Mutex::Autolock l(&mLock);
2527 {
2528 if (mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME))
2529 return;
2530 }
2531 stopPreviewInternal();
2532 LOGV("stopPreview: X");
2533}
2534
2535void QualcommCameraHardware::runAutoFocus()
2536{
2537 bool status = true;
2538 void *libhandle = NULL;
Srinivasan Kannan71229622009-12-04 12:05:58 -08002539 isp3a_af_mode_t afMode;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002540
2541 mAutoFocusThreadLock.lock();
2542 // Skip autofocus if focus mode is infinity.
2543 if (strcmp(mParameters.get(CameraParameters::KEY_FOCUS_MODE),
2544 CameraParameters::FOCUS_MODE_INFINITY) == 0) {
2545 goto done;
2546 }
2547
2548 mAutoFocusFd = open(MSM_CAMERA_CONTROL, O_RDWR);
2549 if (mAutoFocusFd < 0) {
2550 LOGE("autofocus: cannot open %s: %s",
2551 MSM_CAMERA_CONTROL,
2552 strerror(errno));
2553 mAutoFocusThreadRunning = false;
2554 mAutoFocusThreadLock.unlock();
2555 return;
2556 }
2557
2558#if DLOPEN_LIBMMCAMERA
2559 // We need to maintain a reference to libqcamera.so for the duration of the
2560 // AF thread, because we do not know when it will exit relative to the
2561 // lifetime of this object. We do not want to dlclose() libqcamera while
2562 // LINK_cam_frame is still running.
2563 libhandle = ::dlopen("liboemcamera.so", RTLD_NOW);
2564 LOGV("AF: loading libqcamera at %p", libhandle);
2565 if (!libhandle) {
2566 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
2567 close(mAutoFocusFd);
2568 mAutoFocusFd = -1;
2569 mAutoFocusThreadRunning = false;
2570 mAutoFocusThreadLock.unlock();
2571 return;
2572 }
2573#endif
2574
Srinivasan Kannan71229622009-12-04 12:05:58 -08002575 afMode = (isp3a_af_mode_t)attr_lookup(focus_modes,
2576 sizeof(focus_modes) / sizeof(str_map),
2577 mParameters.get(CameraParameters::KEY_FOCUS_MODE));
2578
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002579 /* This will block until either AF completes or is cancelled. */
Srinivasan Kannan71229622009-12-04 12:05:58 -08002580 LOGV("af start (fd %d mode %d)", mAutoFocusFd, afMode);
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08002581 status_t err;
2582 err = mAfLock.tryLock();
2583 if(err == NO_ERROR) {
Srinivasan Kannan99e82422010-02-28 15:32:16 -08002584 LOGV("Start AF");
2585 status = native_set_afmode(mAutoFocusFd, afMode);
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08002586 mAfLock.unlock();
2587 }
2588 else{
2589 //AF Cancel would have acquired the lock,
2590 //so, no need to perform any AF
Srinivasan Kannan99e82422010-02-28 15:32:16 -08002591 LOGV("As Cancel auto focus is in progress, auto focus request "
2592 "is ignored");
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08002593 status = FALSE;
2594 }
2595
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002596 LOGV("af done: %d", (int)status);
2597 close(mAutoFocusFd);
2598 mAutoFocusFd = -1;
2599
2600done:
2601 mAutoFocusThreadRunning = false;
2602 mAutoFocusThreadLock.unlock();
2603
2604 mCallbackLock.lock();
2605 bool autoFocusEnabled = mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS);
2606 notify_callback cb = mNotifyCallback;
2607 void *data = mCallbackCookie;
2608 mCallbackLock.unlock();
2609 if (autoFocusEnabled)
2610 cb(CAMERA_MSG_FOCUS, status, 0, data);
2611
2612#if DLOPEN_LIBMMCAMERA
2613 if (libhandle) {
2614 ::dlclose(libhandle);
2615 LOGV("AF: dlclose(libqcamera)");
2616 }
2617#endif
2618}
2619
2620status_t QualcommCameraHardware::cancelAutoFocusInternal()
2621{
2622 LOGV("cancelAutoFocusInternal E");
2623
Srinivasan Kannan71229622009-12-04 12:05:58 -08002624 if(!sensorType->hasAutoFocusSupport){
2625 LOGV("cancelAutoFocusInternal X");
2626 return NO_ERROR;
2627 }
2628
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002629#if 0
2630 if (mAutoFocusFd < 0) {
2631 LOGV("cancelAutoFocusInternal X: not in progress");
2632 return NO_ERROR;
2633 }
2634#endif
2635
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08002636 status_t rc = NO_ERROR;
2637 status_t err;
2638 err = mAfLock.tryLock();
2639 if(err == NO_ERROR) {
2640 //Got Lock, means either AF hasn't started or
2641 // AF is done. So no need to cancel it, just change the state
Srinivasan Kannan99e82422010-02-28 15:32:16 -08002642 LOGV("As Auto Focus is not in progress, Cancel Auto Focus "
2643 "is ignored");
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08002644 mAfLock.unlock();
2645 }
2646 else {
2647 //AF is in Progess, So cancel it
2648 LOGV("Lock busy...cancel AF");
2649 rc = native_cancel_afmode(mCameraControlFd, mAutoFocusFd) ?
2650 NO_ERROR :
2651 UNKNOWN_ERROR;
2652 }
2653
2654
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002655
2656 LOGV("cancelAutoFocusInternal X: %d", rc);
2657 return rc;
2658}
2659
2660void *auto_focus_thread(void *user)
2661{
2662 LOGV("auto_focus_thread E");
2663 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
2664 if (obj != 0) {
2665 obj->runAutoFocus();
2666 }
2667 else LOGW("not starting autofocus: the object went away!");
2668 LOGV("auto_focus_thread X");
2669 return NULL;
2670}
2671
2672status_t QualcommCameraHardware::autoFocus()
2673{
2674 LOGV("autoFocus E");
2675 Mutex::Autolock l(&mLock);
2676
Srinivasan Kannan71229622009-12-04 12:05:58 -08002677 if(!sensorType->hasAutoFocusSupport){
Srinivasan Kannandf085222009-12-09 18:31:00 -08002678 bool status = false;
2679 mCallbackLock.lock();
2680 bool autoFocusEnabled = mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS);
2681 notify_callback cb = mNotifyCallback;
2682 void *data = mCallbackCookie;
2683 mCallbackLock.unlock();
2684 if (autoFocusEnabled)
2685 cb(CAMERA_MSG_FOCUS, status, 0, data);
Srinivasan Kannan71229622009-12-04 12:05:58 -08002686 LOGV("autoFocus X");
2687 return NO_ERROR;
2688 }
2689
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002690 if (mCameraControlFd < 0) {
2691 LOGE("not starting autofocus: main control fd %d", mCameraControlFd);
2692 return UNKNOWN_ERROR;
2693 }
2694
2695 {
2696 mAutoFocusThreadLock.lock();
2697 if (!mAutoFocusThreadRunning) {
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08002698 if (native_prepare_snapshot(mCameraControlFd) == FALSE) {
2699 LOGE("native_prepare_snapshot failed!\n");
2700 mAutoFocusThreadLock.unlock();
2701 return UNKNOWN_ERROR;
2702 }
2703
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002704 // Create a detached thread here so that we don't have to wait
2705 // for it when we cancel AF.
2706 pthread_t thr;
2707 pthread_attr_t attr;
2708 pthread_attr_init(&attr);
2709 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2710 mAutoFocusThreadRunning =
2711 !pthread_create(&thr, &attr,
2712 auto_focus_thread, NULL);
2713 if (!mAutoFocusThreadRunning) {
2714 LOGE("failed to start autofocus thread");
2715 mAutoFocusThreadLock.unlock();
2716 return UNKNOWN_ERROR;
2717 }
2718 }
2719 mAutoFocusThreadLock.unlock();
2720 }
2721
2722 LOGV("autoFocus X");
2723 return NO_ERROR;
2724}
2725
2726status_t QualcommCameraHardware::cancelAutoFocus()
2727{
2728 LOGV("cancelAutoFocus E");
2729 Mutex::Autolock l(&mLock);
2730
2731 int rc = NO_ERROR;
2732 if (mCameraRunning && mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS)) {
2733 rc = cancelAutoFocusInternal();
2734 }
2735
2736 LOGV("cancelAutoFocus X");
2737 return rc;
2738}
2739
2740void QualcommCameraHardware::runSnapshotThread(void *data)
2741{
2742 LOGV("runSnapshotThread E");
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002743 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
2744 if (native_start_snapshot(mCameraControlFd))
2745 receiveRawPicture();
2746 else
2747 LOGE("main: native_start_snapshot failed!");
2748 } else if(mSnapshotFormat == PICTURE_FORMAT_RAW){
2749 if(native_start_raw_snapshot(mCameraControlFd)){
2750 receiveRawSnapshot();
2751 } else {
2752 LOGE("main: native_start_raw_snapshot failed!");
2753 }
2754 }
2755
2756 mSnapshotFormat = 0;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002757
2758 mSnapshotThreadWaitLock.lock();
2759 mSnapshotThreadRunning = false;
2760 mSnapshotThreadWait.signal();
2761 mSnapshotThreadWaitLock.unlock();
2762
2763 LOGV("runSnapshotThread X");
2764}
2765
2766void *snapshot_thread(void *user)
2767{
2768 LOGD("snapshot_thread E");
2769 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
2770 if (obj != 0) {
2771 obj->runSnapshotThread(user);
2772 }
2773 else LOGW("not starting snapshot thread: the object went away!");
2774 LOGD("snapshot_thread X");
2775 return NULL;
2776}
2777
2778status_t QualcommCameraHardware::takePicture()
2779{
2780 LOGV("takePicture(%d)", mMsgEnabled);
2781 Mutex::Autolock l(&mLock);
2782
2783 // Wait for old snapshot thread to complete.
2784 mSnapshotThreadWaitLock.lock();
2785 while (mSnapshotThreadRunning) {
2786 LOGV("takePicture: waiting for old snapshot thread to complete.");
2787 mSnapshotThreadWait.wait(mSnapshotThreadWaitLock);
2788 LOGV("takePicture: old snapshot thread completed.");
2789 }
2790
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002791 if( mCurrentTarget == TARGET_MSM7630 ) {
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002792 /* Store the last frame queued for preview. This
2793 * shall be used as postview */
2794 storePreviewFrameForPostview();
2795 }
2796
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002797 //mSnapshotFormat is protected by mSnapshotThreadWaitLock
2798 if(mParameters.getPictureFormat() != 0 &&
2799 !strcmp(mParameters.getPictureFormat(),
2800 CameraParameters::PIXEL_FORMAT_RAW))
2801 mSnapshotFormat = PICTURE_FORMAT_RAW;
2802 else
2803 mSnapshotFormat = PICTURE_FORMAT_JPEG;
2804
2805 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
2806 if(!native_prepare_snapshot(mCameraControlFd)) {
2807 mSnapshotThreadWaitLock.unlock();
2808 return UNKNOWN_ERROR;
2809 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002810 }
2811
2812 stopPreviewInternal();
2813
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002814 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
2815 if (!initRaw(mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE))) {
2816 LOGE("initRaw failed. Not taking picture.");
2817 mSnapshotThreadWaitLock.unlock();
2818 return UNKNOWN_ERROR;
2819 }
2820 } else if(mSnapshotFormat == PICTURE_FORMAT_RAW ){
2821 if(!initRawSnapshot()){
2822 LOGE("initRawSnapshot failed. Not taking picture.");
2823 mSnapshotThreadWaitLock.unlock();
2824 return UNKNOWN_ERROR;
2825 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002826 }
2827
2828 mShutterLock.lock();
2829 mShutterPending = true;
2830 mShutterLock.unlock();
2831
2832 pthread_attr_t attr;
2833 pthread_attr_init(&attr);
2834 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2835 mSnapshotThreadRunning = !pthread_create(&mSnapshotThread,
2836 &attr,
2837 snapshot_thread,
2838 NULL);
2839 mSnapshotThreadWaitLock.unlock();
2840
2841 LOGV("takePicture: X");
2842 return mSnapshotThreadRunning ? NO_ERROR : UNKNOWN_ERROR;
2843}
2844
2845status_t QualcommCameraHardware::cancelPicture()
2846{
2847 status_t rc;
2848 LOGV("cancelPicture: E");
2849 rc = native_stop_snapshot(mCameraControlFd) ? NO_ERROR : UNKNOWN_ERROR;
2850 LOGV("cancelPicture: X: %d", rc);
2851 return rc;
2852}
2853
2854status_t QualcommCameraHardware::setParameters(const CameraParameters& params)
2855{
2856 LOGV("setParameters: E params = %p", &params);
2857
2858 Mutex::Autolock l(&mLock);
2859 status_t rc, final_rc = NO_ERROR;
2860
2861 if ((rc = setPreviewSize(params))) final_rc = rc;
2862 if ((rc = setPictureSize(params))) final_rc = rc;
2863 if ((rc = setJpegQuality(params))) final_rc = rc;
2864 if ((rc = setAntibanding(params))) final_rc = rc;
Apurva Rajguru55562b02009-12-03 12:25:35 -08002865 if ((rc = setAutoExposure(params))) final_rc = rc;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002866 if ((rc = setWhiteBalance(params))) final_rc = rc;
Vamshidhar Kondrae7b9b5a2010-02-25 15:40:37 +05302867 if ((rc = setEffect(params))) final_rc = rc;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002868 if ((rc = setFlash(params))) final_rc = rc;
2869 if ((rc = setGpsLocation(params))) final_rc = rc;
2870 if ((rc = setRotation(params))) final_rc = rc;
2871 if ((rc = setZoom(params))) final_rc = rc;
2872 if ((rc = setFocusMode(params))) final_rc = rc;
2873 if ((rc = setOrientation(params))) final_rc = rc;
Nishant Panditc8c1ee72009-12-03 16:24:02 +05302874 if ((rc = setBrightness(params))) final_rc = rc;
2875 if ((rc = setLensshadeValue(params))) final_rc = rc;
2876 if ((rc = setISOValue(params))) final_rc = rc;
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002877 if ((rc = setPictureFormat(params))) final_rc = rc;
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08002878 if ((rc = setSharpness(params))) final_rc = rc;
2879 if ((rc = setContrast(params))) final_rc = rc;
2880 if ((rc = setSaturation(params))) final_rc = rc;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002881
2882 LOGV("setParameters: X");
2883 return final_rc;
2884}
2885
2886CameraParameters QualcommCameraHardware::getParameters() const
2887{
2888 LOGV("getParameters: EX");
2889 return mParameters;
2890}
2891
2892status_t QualcommCameraHardware::sendCommand(int32_t command, int32_t arg1,
2893 int32_t arg2)
2894{
2895 LOGV("sendCommand: EX");
2896 return BAD_VALUE;
2897}
2898
2899extern "C" sp<CameraHardwareInterface> openCameraHardware()
2900{
2901 LOGV("openCameraHardware: call createInstance");
2902 return QualcommCameraHardware::createInstance();
2903}
2904
2905wp<QualcommCameraHardware> QualcommCameraHardware::singleton;
2906
2907// If the hardware already exists, return a strong pointer to the current
2908// object. If not, create a new hardware object, put it in the singleton,
2909// and return it.
2910sp<CameraHardwareInterface> QualcommCameraHardware::createInstance()
2911{
2912 LOGD("createInstance: E");
2913
2914 Mutex::Autolock lock(&singleton_lock);
2915
2916 // Wait until the previous release is done.
2917 while (singleton_releasing) {
2918 LOGD("Wait for previous release.");
2919 singleton_wait.wait(singleton_lock);
2920 }
2921
2922 if (singleton != 0) {
2923 sp<CameraHardwareInterface> hardware = singleton.promote();
2924 if (hardware != 0) {
2925 LOGD("createInstance: X return existing hardware=%p", &(*hardware));
2926 return hardware;
2927 }
2928 }
2929
2930 {
2931 struct stat st;
2932 int rc = stat("/dev/oncrpc", &st);
2933 if (rc < 0) {
2934 LOGD("createInstance: X failed to create hardware: %s", strerror(errno));
2935 return NULL;
2936 }
2937 }
2938
2939 QualcommCameraHardware *cam = new QualcommCameraHardware();
2940 sp<QualcommCameraHardware> hardware(cam);
2941 singleton = hardware;
2942
2943 if (!cam->startCamera()) {
2944 LOGE("%s: startCamera failed!", __FUNCTION__);
2945 return NULL;
2946 }
2947
2948 cam->initDefaultParameters();
2949 LOGD("createInstance: X created hardware=%p", &(*hardware));
2950 return hardware;
2951}
2952
2953// For internal use only, hence the strong pointer to the derived type.
2954sp<QualcommCameraHardware> QualcommCameraHardware::getInstance()
2955{
2956 sp<CameraHardwareInterface> hardware = singleton.promote();
2957 if (hardware != 0) {
2958 // LOGV("getInstance: X old instance of hardware");
2959 return sp<QualcommCameraHardware>(static_cast<QualcommCameraHardware*>(hardware.get()));
2960 } else {
2961 LOGV("getInstance: X new instance of hardware");
2962 return sp<QualcommCameraHardware>();
2963 }
2964}
Sravankb4f5f1c2010-01-21 11:06:17 +05302965void QualcommCameraHardware::receiveRecordingFrame(struct msm_frame *frame)
2966{
2967 LOGV("receiveRecordingFrame E");
2968 // post busy frame
2969 if (frame)
2970 {
2971 cam_frame_post_video (frame);
2972 }
2973 else LOGE("in receiveRecordingFrame frame is NULL");
2974 LOGV("receiveRecordingFrame X");
2975}
2976
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002977
Mohan Kandrad9efed92010-01-15 19:08:39 -08002978bool QualcommCameraHardware::native_zoom_image(int fd, int srcOffset, int dstOffSet, common_crop_t *crop)
Mohan Kandra284966d2010-01-05 13:39:15 -08002979{
2980 int result = 0;
2981 struct mdp_blit_req *e;
2982 struct timeval td1, td2;
2983
Mohan Kandra284966d2010-01-05 13:39:15 -08002984 /* Initialize yuv structure */
2985 zoomImage.list.count = 1;
2986
2987 e = &zoomImage.list.req[0];
2988
2989 e->src.width = previewWidth;
2990 e->src.height = previewHeight;
2991 e->src.format = MDP_Y_CBCR_H2V2;
Mohan Kandrad9efed92010-01-15 19:08:39 -08002992 e->src.offset = srcOffset;
2993 e->src.memory_id = fd;
Mohan Kandra284966d2010-01-05 13:39:15 -08002994
2995 e->dst.width = previewWidth;
2996 e->dst.height = previewHeight;
2997 e->dst.format = MDP_Y_CBCR_H2V2;
Mohan Kandrad9efed92010-01-15 19:08:39 -08002998 e->dst.offset = dstOffSet;
2999 e->dst.memory_id = fd;
Mohan Kandra284966d2010-01-05 13:39:15 -08003000
3001 e->transp_mask = 0xffffffff;
3002 e->flags = 0;
3003 e->alpha = 0xff;
3004 if (crop->in2_w != 0 || crop->in2_h != 0) {
3005 e->src_rect.x = (crop->out2_w - crop->in2_w + 1) / 2 - 1;
3006 e->src_rect.y = (crop->out2_h - crop->in2_h + 1) / 2 - 1;
3007 e->src_rect.w = crop->in2_w;
3008 e->src_rect.h = crop->in2_h;
3009 } else {
3010 e->src_rect.x = 0;
3011 e->src_rect.y = 0;
3012 e->src_rect.w = previewWidth;
3013 e->src_rect.h = previewHeight;
3014 }
Mohan Kandrad9efed92010-01-15 19:08:39 -08003015 //LOGV(" native_zoom : SRC_RECT : x,y = %d,%d \t w,h = %d, %d",
3016 // e->src_rect.x, e->src_rect.y, e->src_rect.w, e->src_rect.h);
Mohan Kandra284966d2010-01-05 13:39:15 -08003017
3018 e->dst_rect.x = 0;
3019 e->dst_rect.y = 0;
3020 e->dst_rect.w = previewWidth;
3021 e->dst_rect.h = previewHeight;
3022
3023 result = ioctl(fb_fd, MSMFB_BLIT, &zoomImage.list);
3024 if (result < 0) {
3025 LOGE("MSM_FBIOBLT failed! line=%d\n", __LINE__);
3026 return FALSE;
3027 }
3028 return TRUE;
3029}
3030
Mohan Kandrabad0eaa2010-02-04 15:11:54 -08003031void QualcommCameraHardware::debugShowPreviewFPS() const
Mohan Kandra740cfce2010-01-07 12:58:24 -08003032{
3033 static int mFrameCount;
3034 static int mLastFrameCount = 0;
3035 static nsecs_t mLastFpsTime = 0;
3036 static float mFps = 0;
3037 mFrameCount++;
3038 nsecs_t now = systemTime();
3039 nsecs_t diff = now - mLastFpsTime;
3040 if (diff > ms2ns(250)) {
3041 mFps = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
Mohan Kandrabad0eaa2010-02-04 15:11:54 -08003042 LOGI("Preview Frames Per Second: %.4f", mFps);
Mohan Kandra740cfce2010-01-07 12:58:24 -08003043 mLastFpsTime = now;
3044 mLastFrameCount = mFrameCount;
3045 }
3046}
3047
Mohan Kandrabad0eaa2010-02-04 15:11:54 -08003048void QualcommCameraHardware::debugShowVideoFPS() const
3049{
3050 static int mFrameCount;
3051 static int mLastFrameCount = 0;
3052 static nsecs_t mLastFpsTime = 0;
3053 static float mFps = 0;
3054 mFrameCount++;
3055 nsecs_t now = systemTime();
3056 nsecs_t diff = now - mLastFpsTime;
3057 if (diff > ms2ns(250)) {
3058 mFps = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
3059 LOGI("Video Frames Per Second: %.4f", mFps);
3060 mLastFpsTime = now;
3061 mLastFrameCount = mFrameCount;
3062 }
3063}
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003064void QualcommCameraHardware::receivePreviewFrame(struct msm_frame *frame)
3065{
3066// LOGV("receivePreviewFrame E");
3067
3068 if (!mCameraRunning) {
3069 LOGE("ignoring preview callback--camera has been stopped");
3070 return;
3071 }
3072
Mohan Kandra740cfce2010-01-07 12:58:24 -08003073 if (UNLIKELY(mDebugFps)) {
Mohan Kandrabad0eaa2010-02-04 15:11:54 -08003074 debugShowPreviewFPS();
Mohan Kandra740cfce2010-01-07 12:58:24 -08003075 }
3076
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003077 mCallbackLock.lock();
3078 int msgEnabled = mMsgEnabled;
3079 data_callback pcb = mDataCallback;
3080 void *pdata = mCallbackCookie;
3081 data_callback_timestamp rcb = mDataCallbackTimestamp;
3082 void *rdata = mCallbackCookie;
3083 mCallbackLock.unlock();
3084
3085 // Find the offset within the heap of the current buffer.
Mohan Kandra284966d2010-01-05 13:39:15 -08003086 ssize_t offset_addr =
Mohan Kandrad9efed92010-01-15 19:08:39 -08003087 (ssize_t)frame->buffer - (ssize_t)mPreviewHeap->mHeap->base();
3088 ssize_t offset = offset_addr / mPreviewHeap->mAlignedBufferSize;
Mohan Kandra284966d2010-01-05 13:39:15 -08003089
3090 common_crop_t *crop = (common_crop_t *) (frame->cropinfo);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003091
3092 mInPreviewCallback = true;
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003093 if(mUseOverlay) {
3094 if(mOverlay != NULL) {
3095 mOverlayLock.lock();
Mohan Kandrad9efed92010-01-15 19:08:39 -08003096 mOverlay->setFd(mPreviewHeap->mHeap->getHeapID());
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003097 if (crop->in2_w != 0 || crop->in2_h != 0) {
3098 zoomCropInfo.x = (crop->out2_w - crop->in2_w + 1) / 2 - 1;
3099 zoomCropInfo.y = (crop->out2_h - crop->in2_h + 1) / 2 - 1;
3100 zoomCropInfo.w = crop->in2_w;
3101 zoomCropInfo.h = crop->in2_h;
3102 mOverlay->setCrop(zoomCropInfo.x, zoomCropInfo.y,
3103 zoomCropInfo.w, zoomCropInfo.h);
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08003104 } else {
3105 // Reset zoomCropInfo variables. This will ensure that
3106 // stale values wont be used for postview
3107 zoomCropInfo.w = crop->in2_w;
3108 zoomCropInfo.h = crop->in2_h;
3109 }
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003110 mOverlay->queueBuffer((void *)offset_addr);
3111 mLastQueuedFrame = (void *)frame->buffer;
3112 mOverlayLock.unlock();
3113 }
Mohan Kandra284966d2010-01-05 13:39:15 -08003114 } else {
Mohan Kandrad9efed92010-01-15 19:08:39 -08003115 if (crop->in2_w != 0 || crop->in2_h != 0) {
3116 dstOffset = (dstOffset + 1) % NUM_MORE_BUFS;
3117 offset = kPreviewBufferCount + dstOffset;
3118 ssize_t dstOffset_addr = offset * mPreviewHeap->mAlignedBufferSize;
3119 if( !native_zoom_image(mPreviewHeap->mHeap->getHeapID(),
3120 offset_addr, dstOffset_addr, crop)) {
3121 LOGE(" Error while doing MDP zoom ");
3122 }
3123 }
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08003124 }
Mohan Kandrad9efed92010-01-15 19:08:39 -08003125 if (pcb != NULL && (msgEnabled & CAMERA_MSG_PREVIEW_FRAME))
3126 pcb(CAMERA_MSG_PREVIEW_FRAME, mPreviewHeap->mBuffers[offset],
3127 pdata);
3128
Sravankb4f5f1c2010-01-21 11:06:17 +05303129 // If output2 enabled, Start Recording if recording is enabled by Services
Mohan Kandraf1ebf982010-02-02 15:25:43 -08003130 if( ((mCurrentTarget == TARGET_MSM7630) || (mCurrentTarget == TARGET_QSD8250)) && recordingEnabled() ) {
Sravankb4f5f1c2010-01-21 11:06:17 +05303131 if(!recordingState){
3132 recordingState = 1; // recording started
3133 LOGV(" in receivePreviewframe : recording enabled calling startRecording ");
3134 startRecording();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003135 }
Sravankb4f5f1c2010-01-21 11:06:17 +05303136 }
3137
3138 // If output is NOT enabled (targets otherthan 7x30 currently..)
Mohan Kandraf1ebf982010-02-02 15:25:43 -08003139 if( (mCurrentTarget != TARGET_MSM7630 ) && (mCurrentTarget != TARGET_QSD8250)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05303140 if(rcb != NULL && (msgEnabled & CAMERA_MSG_VIDEO_FRAME)) {
3141 rcb(systemTime(), CAMERA_MSG_VIDEO_FRAME, mPreviewHeap->mBuffers[offset], rdata);
3142 Mutex::Autolock rLock(&mRecordFrameLock);
3143 if (mReleasedRecordingFrame != true) {
3144 LOGV("block waiting for frame release");
3145 mRecordWait.wait(mRecordFrameLock);
3146 LOGV("frame released, continuing");
3147 }
3148 mReleasedRecordingFrame = false;
3149 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003150 }
3151 mInPreviewCallback = false;
3152
3153// LOGV("receivePreviewFrame X");
3154}
3155
Sravankb4f5f1c2010-01-21 11:06:17 +05303156
3157bool QualcommCameraHardware::initRecord()
3158{
3159 LOGV("initREcord E");
3160
3161 mRecordFrameSize = (mDimension.video_width * mDimension.video_height *3)/2;
3162 mRecordHeap = new PmemPool("/dev/pmem_adsp",
3163 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
3164 mCameraControlFd,
3165 MSM_PMEM_VIDEO,
3166 mRecordFrameSize,
3167 kRecordBufferCount,
3168 mRecordFrameSize,
3169 "record");
3170 if (!mRecordHeap->initialized()) {
3171 mRecordHeap.clear();
3172 LOGE("initRecord X: could not initialize record heap.");
3173 return false;
3174 }
3175 for (int cnt = 0; cnt < kRecordBufferCount; cnt++) {
3176 recordframes[cnt].fd = mRecordHeap->mHeap->getHeapID();
3177 recordframes[cnt].buffer =
3178 (uint32_t)mRecordHeap->mHeap->base() + mRecordHeap->mAlignedBufferSize * cnt;
3179 recordframes[cnt].y_off = 0;
3180 recordframes[cnt].cbcr_off = mDimension.video_width * mDimension.video_height;
3181 recordframes[cnt].path = OUTPUT_TYPE_V;
3182
3183 LOGV ("initRecord : record heap , video buffers buffer=%lu fd=%d y_off=%d cbcr_off=%d \n",
3184 (unsigned long)recordframes[cnt].buffer, recordframes[cnt].fd, recordframes[cnt].y_off,
3185 recordframes[cnt].cbcr_off);
3186 }
3187
3188 // initial setup : buffers 1,2,3 with kernel , 4 with camframe , 5,6,7,8 in free Q
3189 // flush the busy Q
3190 cam_frame_flush_video();
3191
Mohan Kandra156d0ac2010-01-25 16:59:17 -08003192 mVideoThreadWaitLock.lock();
3193 while (mVideoThreadRunning) {
3194 LOGV("initRecord: waiting for old video thread to complete.");
3195 mVideoThreadWait.wait(mVideoThreadWaitLock);
3196 LOGV("initRecord : old video thread completed.");
3197 }
3198 mVideoThreadWaitLock.unlock();
3199
Sravankdf7a9202010-02-08 15:02:51 +05303200 // flush free queue and add 5,6,7,8 buffers.
3201 LINK_cam_frame_flush_free_video();
3202 for(int i=ACTIVE_VIDEO_BUFFERS+1;i <kRecordBufferCount; i++)
3203 LINK_camframe_free_video(&recordframes[i]);
Sravankb4f5f1c2010-01-21 11:06:17 +05303204 LOGV("initREcord X");
3205
3206 return true;
3207}
3208
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003209status_t QualcommCameraHardware::startRecording()
3210{
3211 LOGV("startRecording E");
Sravankb4f5f1c2010-01-21 11:06:17 +05303212 int ret;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003213 Mutex::Autolock l(&mLock);
3214 mReleasedRecordingFrame = false;
Sravankb4f5f1c2010-01-21 11:06:17 +05303215 if( (ret=startPreviewInternal())== NO_ERROR){
Mohan Kandraf1ebf982010-02-02 15:25:43 -08003216 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05303217 LOGV(" in startREcording : calling native_start_recording");
3218 native_start_recording(mCameraControlFd);
3219 recordingState = 1;
Sravank64461e82010-02-25 15:10:09 +05303220 // Remove the left out frames in busy Q and them in free Q.
3221 // this should be done before starting video_thread so that,
3222 // frames in previous recording are flushed out.
3223 LOGV("frames in busy Q = %d", g_busy_frame_queue.num_of_frames);
3224 while((g_busy_frame_queue.num_of_frames) >0){
3225 msm_frame* vframe = cam_frame_get_video ();
3226 LINK_camframe_free_video(vframe);
3227 }
3228 LOGV("frames in busy Q = %d after deQueing", g_busy_frame_queue.num_of_frames);
3229
Sravankdf7a9202010-02-08 15:02:51 +05303230 // Start video thread and wait for busy frames to be encoded, this thread
3231 // should be closed in stopRecording
3232 mVideoThreadWaitLock.lock();
3233 mVideoThreadExit = 0;
3234 pthread_attr_t attr;
3235 pthread_attr_init(&attr);
3236 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
3237 mVideoThreadRunning = pthread_create(&mVideoThread,
3238 &attr,
3239 video_thread,
3240 NULL);
3241 mVideoThreadWaitLock.unlock();
3242 // Remove the left out frames in busy Q and them in free Q.
Sravankb4f5f1c2010-01-21 11:06:17 +05303243 }
3244 }
3245 return ret;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003246}
3247
3248void QualcommCameraHardware::stopRecording()
3249{
3250 LOGV("stopRecording: E");
3251 Mutex::Autolock l(&mLock);
3252 {
3253 mRecordFrameLock.lock();
3254 mReleasedRecordingFrame = true;
3255 mRecordWait.signal();
3256 mRecordFrameLock.unlock();
3257
Sravankdf7a9202010-02-08 15:02:51 +05303258 if(mDataCallback && !(mCurrentTarget == TARGET_QSD8250) &&
3259 (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003260 LOGV("stopRecording: X, preview still in progress");
3261 return;
3262 }
3263 }
Sravankb4f5f1c2010-01-21 11:06:17 +05303264 // If output2 enabled, exit video thread, invoke stop recording ioctl
Mohan Kandraf1ebf982010-02-02 15:25:43 -08003265 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05303266 mVideoThreadWaitLock.lock();
3267 mVideoThreadExit = 1;
3268 mVideoThreadWaitLock.unlock();
3269 native_stop_recording(mCameraControlFd);
3270 }
3271 else // for other targets where output2 is not enabled
3272 stopPreviewInternal();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003273
Sravankb4f5f1c2010-01-21 11:06:17 +05303274 recordingState = 0; // recording not started
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003275 LOGV("stopRecording: X");
3276}
3277
3278void QualcommCameraHardware::releaseRecordingFrame(
3279 const sp<IMemory>& mem __attribute__((unused)))
3280{
3281 LOGV("releaseRecordingFrame E");
3282 Mutex::Autolock rLock(&mRecordFrameLock);
3283 mReleasedRecordingFrame = true;
3284 mRecordWait.signal();
Sravankb4f5f1c2010-01-21 11:06:17 +05303285
3286 // Ff 7x30 : add the frame to the free camframe queue
Mohan Kandraf1ebf982010-02-02 15:25:43 -08003287 if( (mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05303288 ssize_t offset;
3289 size_t size;
3290 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
3291 msm_frame* releaseframe = NULL;
3292 LOGV(" in release recording frame : heap base %d offset %d buffer %d ", heap->base(), offset, heap->base() + offset );
3293 int cnt;
3294 for (cnt = 0; cnt < kRecordBufferCount; cnt++) {
3295 if((unsigned int)recordframes[cnt].buffer == (unsigned int)(heap->base()+ offset)){
3296 LOGV("in release recording frame found match , releasing buffer %d", (unsigned int)recordframes[cnt].buffer);
3297 releaseframe = &recordframes[cnt];
3298 break;
3299 }
3300 }
3301 if(cnt < kRecordBufferCount) {
3302 // do this only if frame thread is running
3303 mFrameThreadWaitLock.lock();
3304 if(mFrameThreadRunning )
3305 LINK_camframe_free_video(releaseframe);
3306
3307 mFrameThreadWaitLock.unlock();
3308 } else {
3309 LOGE("in release recordingframe XXXXX error , buffer not found");
3310 for (int i=0; i< kRecordBufferCount; i++) {
3311 LOGE(" recordframes[%d].buffer = %d", i, (unsigned int)recordframes[i].buffer);
3312 }
3313 }
3314 }
3315
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003316 LOGV("releaseRecordingFrame X");
3317}
3318
3319bool QualcommCameraHardware::recordingEnabled()
3320{
3321 return mCameraRunning && mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME);
3322}
3323
3324void QualcommCameraHardware::notifyShutter(common_crop_t *crop)
3325{
3326 mShutterLock.lock();
3327 image_rect_type size;
3328
3329 if (mShutterPending && mNotifyCallback && (mMsgEnabled & CAMERA_MSG_SHUTTER)) {
3330 LOGV("out2_w=%d, out2_h=%d, in2_w=%d, in2_h=%d",
3331 crop->out2_w, crop->out2_h, crop->in2_w, crop->in2_h);
3332 LOGV("out1_w=%d, out1_h=%d, in1_w=%d, in1_h=%d",
3333 crop->out1_w, crop->out1_h, crop->in1_w, crop->in1_h);
3334
3335 // To workaround a bug in MDP which happens if either
3336 // dimension > 2048, we display the thumbnail instead.
3337 mDisplayHeap = mRawHeap;
3338 if (crop->in1_w == 0 || crop->in1_h == 0) {
3339 // Full size
3340 size.width = mDimension.picture_width;
3341 size.height = mDimension.picture_height;
3342 if (size.width > 2048 || size.height > 2048) {
3343 size.width = mDimension.ui_thumbnail_width;
3344 size.height = mDimension.ui_thumbnail_height;
3345 mDisplayHeap = mThumbnailHeap;
3346 }
3347 } else {
3348 // Cropped
Apurva Rajgurua8b1fc92010-01-27 20:03:55 -08003349 size.width = (crop->in2_w + JPEG_ENCODER_PADDING) & ~1;
3350 size.height = (crop->in2_h + JPEG_ENCODER_PADDING) & ~1;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003351 if (size.width > 2048 || size.height > 2048) {
Apurva Rajgurua8b1fc92010-01-27 20:03:55 -08003352 size.width = (crop->in1_w + JPEG_ENCODER_PADDING) & ~1;
3353 size.height = (crop->in1_h + JPEG_ENCODER_PADDING) & ~1;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003354 mDisplayHeap = mThumbnailHeap;
3355 }
3356 }
3357
3358 mNotifyCallback(CAMERA_MSG_SHUTTER, (int32_t)&size, 0,
3359 mCallbackCookie);
3360 mShutterPending = false;
3361 }
3362 mShutterLock.unlock();
3363}
3364
3365static void receive_shutter_callback(common_crop_t *crop)
3366{
3367 LOGV("receive_shutter_callback: E");
3368 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
3369 if (obj != 0) {
3370 obj->notifyShutter(crop);
3371 }
3372 LOGV("receive_shutter_callback: X");
3373}
3374
3375// Crop the picture in place.
3376static void crop_yuv420(uint32_t width, uint32_t height,
3377 uint32_t cropped_width, uint32_t cropped_height,
3378 uint8_t *image)
3379{
3380 uint32_t i, x, y;
3381 uint8_t* chroma_src, *chroma_dst;
3382
3383 // Calculate the start position of the cropped area.
3384 x = (width - cropped_width) / 2;
3385 y = (height - cropped_height) / 2;
3386 x &= ~1;
3387 y &= ~1;
3388
3389 // Copy luma component.
3390 for(i = 0; i < cropped_height; i++)
3391 memcpy(image + i * cropped_width,
3392 image + width * (y + i) + x,
3393 cropped_width);
3394
3395 chroma_src = image + width * height;
3396 chroma_dst = image + cropped_width * cropped_height;
3397
3398 // Copy chroma components.
3399 cropped_height /= 2;
3400 y /= 2;
3401 for(i = 0; i < cropped_height; i++)
3402 memcpy(chroma_dst + i * cropped_width,
3403 chroma_src + width * (y + i) + x,
3404 cropped_width);
3405}
3406
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08003407
3408void QualcommCameraHardware::receiveRawSnapshot(){
3409 LOGV("receiveRawSnapshot E");
3410
3411 Mutex::Autolock cbLock(&mCallbackLock);
3412
3413 notifyShutter(&mCrop);
3414
3415 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
3416
3417 if(native_get_picture(mCameraControlFd, &mCrop) == false) {
3418 LOGE("receiveRawSnapshot X: native_get_picture failed!");
3419 return;
3420 }
3421
3422 //Create a Ashmem heap to copy data from PMem heap for application layer
3423 if(mRawSnapshotAshmemHeap != NULL){
3424 LOGV("receiveRawSnapshot: clearing old mRawSnapShotAshmemHeap.");
3425 mRawSnapshotAshmemHeap.clear();
3426 }
3427 mRawSnapshotAshmemHeap = new AshmemPool(
3428 mRawSnapShotPmemHeap->mBufferSize,
3429 mRawSnapShotPmemHeap->mNumBuffers,
3430 mRawSnapShotPmemHeap->mFrameSize,
3431 "raw ashmem snapshot camera"
3432 );
3433
3434 if(!mRawSnapshotAshmemHeap->initialized()){
3435 LOGE("receiveRawSnapshot X: error initializing mRawSnapshotHeap");
3436 deinitRawSnapshot();
3437 return;
3438 }
3439
3440 memcpy(mRawSnapshotAshmemHeap->mHeap->base(),
3441 mRawSnapShotPmemHeap->mHeap->base(),
3442 mRawSnapShotPmemHeap->mHeap->getSize());
3443
3444 mDataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mRawSnapshotAshmemHeap->mBuffers[0],
3445 mCallbackCookie);
3446
3447 }
3448
3449 //cleanup
3450 deinitRawSnapshot();
3451
3452 LOGV("receiveRawSnapshot X");
3453}
3454
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003455void QualcommCameraHardware::receiveRawPicture()
3456{
3457 LOGV("receiveRawPicture: E");
3458
3459 Mutex::Autolock cbLock(&mCallbackLock);
3460 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_RAW_IMAGE)) {
3461 if(native_get_picture(mCameraControlFd, &mCrop) == false) {
3462 LOGE("getPicture failed!");
3463 return;
3464 }
3465 mCrop.in1_w &= ~1;
3466 mCrop.in1_h &= ~1;
3467 mCrop.in2_w &= ~1;
3468 mCrop.in2_h &= ~1;
3469
3470 // By the time native_get_picture returns, picture is taken. Call
3471 // shutter callback if cam config thread has not done that.
3472 notifyShutter(&mCrop);
3473
3474 // Crop the image if zoomed.
3475 if (mCrop.in2_w != 0 && mCrop.in2_h != 0) {
Apurva Rajgurua8b1fc92010-01-27 20:03:55 -08003476 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 -08003477 (uint8_t *)mRawHeap->mHeap->base());
Apurva Rajgurua8b1fc92010-01-27 20:03:55 -08003478 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 -08003479 (uint8_t *)mThumbnailHeap->mHeap->base());
3480 // We do not need jpeg encoder to upscale the image. Set the new
3481 // dimension for encoder.
Apurva Rajgurua8b1fc92010-01-27 20:03:55 -08003482 mDimension.orig_picture_dx = mCrop.in2_w + JPEG_ENCODER_PADDING;
3483 mDimension.orig_picture_dy = mCrop.in2_h + JPEG_ENCODER_PADDING;
3484 mDimension.thumbnail_width = mCrop.in1_w + JPEG_ENCODER_PADDING;
3485 mDimension.thumbnail_height = mCrop.in1_h + JPEG_ENCODER_PADDING;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003486 }
3487
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003488 if( mUseOverlay && (mOverlay != NULL) ) {
3489 mOverlay->setFd(mPostViewHeap->mHeap->getHeapID());
3490 if( zoomCropInfo.w !=0 && zoomCropInfo.h !=0) {
3491 LOGD(" zoomCropInfo non-zero, setting crop ");
3492 mOverlay->setCrop(zoomCropInfo.x, zoomCropInfo.y,
3493 zoomCropInfo.w, zoomCropInfo.h);
3494 }
3495 LOGD(" Queueing Postview for display ");
3496 mOverlay->queueBuffer((void *)0);
3497 }
3498
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003499 mDataCallback(CAMERA_MSG_RAW_IMAGE, mDisplayHeap->mBuffers[0],
3500 mCallbackCookie);
3501 }
3502 else LOGV("Raw-picture callback was canceled--skipping.");
3503
3504 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
3505 mJpegSize = 0;
3506 if (LINK_jpeg_encoder_init()) {
3507 if(native_jpeg_encode()) {
3508 LOGV("receiveRawPicture: X (success)");
3509 return;
3510 }
3511 LOGE("jpeg encoding failed");
3512 }
3513 else LOGE("receiveRawPicture X: jpeg_encoder_init failed.");
3514 }
3515 else LOGV("JPEG callback is NULL, not encoding image.");
3516 deinitRaw();
3517 LOGV("receiveRawPicture: X");
3518}
3519
3520void QualcommCameraHardware::receiveJpegPictureFragment(
3521 uint8_t *buff_ptr, uint32_t buff_size)
3522{
3523 uint32_t remaining = mJpegHeap->mHeap->virtualSize();
3524 remaining -= mJpegSize;
3525 uint8_t *base = (uint8_t *)mJpegHeap->mHeap->base();
3526
3527 LOGV("receiveJpegPictureFragment size %d", buff_size);
3528 if (buff_size > remaining) {
3529 LOGE("receiveJpegPictureFragment: size %d exceeds what "
3530 "remains in JPEG heap (%d), truncating",
3531 buff_size,
3532 remaining);
3533 buff_size = remaining;
3534 }
3535 memcpy(base + mJpegSize, buff_ptr, buff_size);
3536 mJpegSize += buff_size;
3537}
3538
3539void QualcommCameraHardware::receiveJpegPicture(void)
3540{
3541 LOGV("receiveJpegPicture: E image (%d uint8_ts out of %d)",
3542 mJpegSize, mJpegHeap->mBufferSize);
3543 Mutex::Autolock cbLock(&mCallbackLock);
3544
3545 int index = 0, rc;
3546
3547 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
3548 // The reason we do not allocate into mJpegHeap->mBuffers[offset] is
3549 // that the JPEG image's size will probably change from one snapshot
3550 // to the next, so we cannot reuse the MemoryBase object.
3551 sp<MemoryBase> buffer = new
3552 MemoryBase(mJpegHeap->mHeap,
3553 index * mJpegHeap->mBufferSize +
3554 0,
3555 mJpegSize);
3556 mDataCallback(CAMERA_MSG_COMPRESSED_IMAGE, buffer, mCallbackCookie);
3557 buffer = NULL;
3558 }
3559 else LOGV("JPEG callback was cancelled--not delivering image.");
3560
3561 LINK_jpeg_encoder_join();
3562 deinitRaw();
3563
3564 LOGV("receiveJpegPicture: X callback done.");
3565}
3566
3567bool QualcommCameraHardware::previewEnabled()
3568{
3569 return mCameraRunning && mDataCallback && (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME);
3570}
3571
3572status_t QualcommCameraHardware::setPreviewSize(const CameraParameters& params)
3573{
3574 int width, height;
3575 params.getPreviewSize(&width, &height);
3576 LOGV("requested preview size %d x %d", width, height);
3577
3578 // Validate the preview size
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -08003579 for (size_t i = 0; i < previewSizeCount; ++i) {
3580 if (width == supportedPreviewSizes[i].width
3581 && height == supportedPreviewSizes[i].height) {
Sravank64461e82010-02-25 15:10:09 +05303582 // 720p , preview can be 768X432 (currently for 7x30 and 8k
3583 // targets)
3584 if(width == 1280 && height == 720 &&
3585 ((mCurrentTarget == TARGET_MSM7630) || (mCurrentTarget == TARGET_QSD8250))){
3586 LOGD("change preview resolution to 768X432 since recording is in 720p");
3587 mDimension.display_width = preview_sizes[2].width;
3588 mDimension.display_height= preview_sizes[2].height;
3589 }else {
3590 mDimension.display_width = width;
3591 mDimension.display_height= height;
3592 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003593 mParameters.setPreviewSize(width, height);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003594 return NO_ERROR;
3595 }
3596 }
3597 LOGE("Invalid preview size requested: %dx%d", width, height);
3598 return BAD_VALUE;
3599}
3600
3601status_t QualcommCameraHardware::setPictureSize(const CameraParameters& params)
3602{
3603 int width, height;
3604 params.getPictureSize(&width, &height);
3605 LOGV("requested picture size %d x %d", width, height);
3606
3607 // Validate the picture size
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -08003608 for (int i = 0; i < supportedPictureSizesCount; ++i) {
3609 if (width == picture_sizes_ptr[i].width
3610 && height == picture_sizes_ptr[i].height) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003611 mParameters.setPictureSize(width, height);
3612 mDimension.picture_width = width;
3613 mDimension.picture_height = height;
3614 return NO_ERROR;
3615 }
3616 }
Kiran Kumar H Nb49af212010-02-17 15:12:17 -08003617 /* Dimension not among the ones in the list. Check if
3618 * its a valid dimension, if it is, then configure the
3619 * camera accordingly. else reject it.
3620 */
3621 if( isValidDimension(width, height) ) {
3622 mParameters.setPictureSize(width, height);
3623 mDimension.picture_width = width;
3624 mDimension.picture_height = height;
3625 return NO_ERROR;
3626 } else
3627 LOGE("Invalid picture size requested: %dx%d", width, height);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003628 return BAD_VALUE;
3629}
3630
3631status_t QualcommCameraHardware::setJpegQuality(const CameraParameters& params) {
3632 status_t rc = NO_ERROR;
3633 int quality = params.getInt(CameraParameters::KEY_JPEG_QUALITY);
3634 if (quality > 0 && quality <= 100) {
3635 mParameters.set(CameraParameters::KEY_JPEG_QUALITY, quality);
3636 } else {
3637 LOGE("Invalid jpeg quality=%d", quality);
3638 rc = BAD_VALUE;
3639 }
3640
3641 quality = params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY);
3642 if (quality > 0 && quality <= 100) {
3643 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, quality);
3644 } else {
3645 LOGE("Invalid jpeg thumbnail quality=%d", quality);
3646 rc = BAD_VALUE;
3647 }
3648 return rc;
3649}
3650
3651status_t QualcommCameraHardware::setEffect(const CameraParameters& params)
3652{
3653 const char *str = params.get(CameraParameters::KEY_EFFECT);
3654 if (str != NULL) {
3655 int32_t value = attr_lookup(effects, sizeof(effects) / sizeof(str_map), str);
3656 if (value != NOT_FOUND) {
Mohan Kandra93f1bfb2009-12-15 16:55:33 -08003657 if(!strcmp(sensorType->name, "2mp") && (value != CAMERA_EFFECT_OFF)
3658 &&(value != CAMERA_EFFECT_MONO) && (value != CAMERA_EFFECT_NEGATIVE)
3659 &&(value != CAMERA_EFFECT_SOLARIZE) && (value != CAMERA_EFFECT_SEPIA)) {
3660 LOGE("Special effect parameter is not supported for this sensor");
3661 return NO_ERROR;
3662 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003663 mParameters.set(CameraParameters::KEY_EFFECT, str);
3664 bool ret = native_set_parm(CAMERA_SET_PARM_EFFECT, sizeof(value),
3665 (void *)&value);
3666 return ret ? NO_ERROR : UNKNOWN_ERROR;
3667 }
3668 }
3669 LOGE("Invalid effect value: %s", (str == NULL) ? "NULL" : str);
3670 return BAD_VALUE;
3671}
3672
Apurva Rajguru55562b02009-12-03 12:25:35 -08003673status_t QualcommCameraHardware::setAutoExposure(const CameraParameters& params)
3674{
Mohan Kandra93f1bfb2009-12-15 16:55:33 -08003675 if(!strcmp(sensorType->name, "2mp")) {
3676 LOGE("Auto Exposure not supported for this sensor");
3677 return NO_ERROR;
3678 }
Apurva Rajguru55562b02009-12-03 12:25:35 -08003679 const char *str = params.get(CameraParameters::KEY_AUTO_EXPOSURE);
3680 if (str != NULL) {
3681 int32_t value = attr_lookup(autoexposure, sizeof(autoexposure) / sizeof(str_map), str);
3682 if (value != NOT_FOUND) {
3683 mParameters.set(CameraParameters::KEY_AUTO_EXPOSURE, str);
3684 bool ret = native_set_parm(CAMERA_SET_PARM_EXPOSURE, sizeof(value),
3685 (void *)&value);
3686 return ret ? NO_ERROR : UNKNOWN_ERROR;
3687 }
3688 }
3689 LOGE("Invalid auto exposure value: %s", (str == NULL) ? "NULL" : str);
3690 return BAD_VALUE;
3691}
3692
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003693status_t QualcommCameraHardware::setSharpness(const CameraParameters& params)
3694{
3695 if(!strcmp(sensorType->name, "2mp")) {
3696 LOGE("Sharpness not supported for this sensor");
3697 return NO_ERROR;
3698 }
3699 int sharpness = params.getInt(CameraParameters::KEY_SHARPNESS);
3700 if((sharpness < CAMERA_MIN_SHARPNESS
3701 || sharpness > CAMERA_MAX_SHARPNESS))
3702 return UNKNOWN_ERROR;
Srinivasan Kannan551fd262010-01-14 17:48:30 -08003703
3704 LOGV("setting sharpness %d", sharpness);
3705 mParameters.set(CameraParameters::KEY_SHARPNESS, sharpness);
3706 bool ret = native_set_parm(CAMERA_SET_PARM_SHARPNESS, sizeof(sharpness),
3707 (void *)&sharpness);
3708 return ret ? NO_ERROR : UNKNOWN_ERROR;
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003709}
3710
3711status_t QualcommCameraHardware::setContrast(const CameraParameters& params)
3712{
3713 if(!strcmp(sensorType->name, "2mp")) {
3714 LOGE("Contrast not supported for this sensor");
3715 return NO_ERROR;
3716 }
3717 int contrast = params.getInt(CameraParameters::KEY_CONTRAST);
3718 if((contrast < CAMERA_MIN_CONTRAST)
3719 || (contrast > CAMERA_MAX_CONTRAST))
3720 return UNKNOWN_ERROR;
Srinivasan Kannan551fd262010-01-14 17:48:30 -08003721
3722 LOGV("setting contrast %d", contrast);
3723 mParameters.set(CameraParameters::KEY_CONTRAST, contrast);
3724 bool ret = native_set_parm(CAMERA_SET_PARM_CONTRAST, sizeof(contrast),
3725 (void *)&contrast);
3726 return ret ? NO_ERROR : UNKNOWN_ERROR;
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003727}
3728
3729status_t QualcommCameraHardware::setSaturation(const CameraParameters& params)
3730{
3731 if(!strcmp(sensorType->name, "2mp")) {
3732 LOGE("Saturation not supported for this sensor");
3733 return NO_ERROR;
3734 }
Srinivasan Kannan551fd262010-01-14 17:48:30 -08003735
Kiran Kumar H Nf87cf862010-01-27 14:34:34 -08003736 const char *str = params.get(CameraParameters::KEY_EFFECT);
3737 int32_t value = attr_lookup(effects, sizeof(effects) / sizeof(str_map), str);
3738
3739 if( (value != CAMERA_EFFECT_MONO) && (value != CAMERA_EFFECT_NEGATIVE)
3740 && (value != CAMERA_EFFECT_AQUA) && (value != CAMERA_EFFECT_SEPIA)) {
3741
3742 int saturation = params.getInt(CameraParameters::KEY_SATURATION);
3743 if((saturation < CAMERA_MIN_SATURATION)
3744 || (saturation > CAMERA_MAX_SATURATION))
3745 return UNKNOWN_ERROR;
3746
3747 LOGV("setting saturation %d", saturation);
3748 mParameters.set(CameraParameters::KEY_SATURATION, saturation);
3749 bool ret = native_set_parm(CAMERA_SET_PARM_SATURATION, sizeof(saturation),
3750 (void *)&saturation);
3751 return ret ? NO_ERROR : UNKNOWN_ERROR;
3752 } else {
3753 LOGE(" Saturation value will not be set " \
3754 "when the effect selected is %s", str);
3755 return NO_ERROR;
3756 }
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003757}
3758
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303759status_t QualcommCameraHardware::setBrightness(const CameraParameters& params) {
3760 int brightness = params.getInt("luma-adaptation");
3761 if (mBrightness != brightness) {
3762 LOGV(" new brightness value : %d ", brightness);
3763 mBrightness = brightness;
3764
3765 bool ret = native_set_parm(CAMERA_SET_PARM_BRIGHTNESS, sizeof(mBrightness),
3766 (void *)&mBrightness);
3767 return ret ? NO_ERROR : UNKNOWN_ERROR;
3768 } else {
3769 return NO_ERROR;
3770 }
3771}
3772
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003773status_t QualcommCameraHardware::setWhiteBalance(const CameraParameters& params)
3774{
3775 const char *str = params.get(CameraParameters::KEY_WHITE_BALANCE);
3776 if (str != NULL) {
3777 int32_t value = attr_lookup(whitebalance, sizeof(whitebalance) / sizeof(str_map), str);
3778 if (value != NOT_FOUND) {
3779 mParameters.set(CameraParameters::KEY_WHITE_BALANCE, str);
3780 bool ret = native_set_parm(CAMERA_SET_PARM_WB, sizeof(value),
3781 (void *)&value);
3782 return ret ? NO_ERROR : UNKNOWN_ERROR;
3783 }
3784 }
3785 LOGE("Invalid whitebalance value: %s", (str == NULL) ? "NULL" : str);
3786 return BAD_VALUE;
3787}
3788
3789status_t QualcommCameraHardware::setFlash(const CameraParameters& params)
3790{
3791 if (!mSensorInfo.flash_enabled) {
3792 LOGV("%s: flash not supported", __FUNCTION__);
3793 return NO_ERROR;
3794 }
3795
3796 const char *str = params.get(CameraParameters::KEY_FLASH_MODE);
3797 if (str != NULL) {
3798 int32_t value = attr_lookup(flash, sizeof(flash) / sizeof(str_map), str);
3799 if (value != NOT_FOUND) {
3800 mParameters.set(CameraParameters::KEY_FLASH_MODE, str);
3801 bool ret = native_set_parm(CAMERA_SET_PARM_LED_MODE,
3802 sizeof(value), (void *)&value);
3803 return ret ? NO_ERROR : UNKNOWN_ERROR;
3804 }
3805 }
3806 LOGE("Invalid flash mode value: %s", (str == NULL) ? "NULL" : str);
3807 return BAD_VALUE;
3808}
3809
3810status_t QualcommCameraHardware::setAntibanding(const CameraParameters& params)
3811{
Srinivasan Kannan2229d272010-01-05 14:58:28 -08003812 if(!strcmp(sensorType->name, "2mp")) {
3813 LOGE("Parameter AntiBanding is not supported for this sensor");
3814 return NO_ERROR;
3815 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003816 const char *str = params.get(CameraParameters::KEY_ANTIBANDING);
3817 if (str != NULL) {
3818 int value = (camera_antibanding_type)attr_lookup(
3819 antibanding, sizeof(antibanding) / sizeof(str_map), str);
3820 if (value != NOT_FOUND) {
3821 camera_antibanding_type temp = (camera_antibanding_type) value;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003822 mParameters.set(CameraParameters::KEY_ANTIBANDING, str);
Srinivasan Kannan2229d272010-01-05 14:58:28 -08003823 bool ret;
3824 if (temp == CAMERA_ANTIBANDING_AUTO) {
3825 ret = native_set_parm(CAMERA_ENABLE_AFD,
3826 0, NULL);
3827 } else {
3828 ret = native_set_parm(CAMERA_SET_PARM_ANTIBANDING,
3829 sizeof(camera_antibanding_type), (void *)&temp);
3830 }
3831 return ret ? NO_ERROR : UNKNOWN_ERROR;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003832 }
3833 }
3834 LOGE("Invalid antibanding value: %s", (str == NULL) ? "NULL" : str);
3835 return BAD_VALUE;
3836}
3837
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303838status_t QualcommCameraHardware::setLensshadeValue(const CameraParameters& params)
3839{
Mohan Kandra93f1bfb2009-12-15 16:55:33 -08003840 if(!strcmp(sensorType->name, "2mp")) {
3841 LOGE("Parameter Rolloff is not supported for this sensor");
3842 return NO_ERROR;
3843 }
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303844 const char *str = params.get(CameraParameters::KEY_LENSSHADE);
3845 if (str != NULL) {
3846 int value = attr_lookup(lensshade,
3847 sizeof(lensshade) / sizeof(str_map), str);
3848 if (value != NOT_FOUND) {
3849 int8_t temp = (int8_t)value;
3850 mParameters.set(CameraParameters::KEY_LENSSHADE, str);
3851 native_set_parm(CAMERA_SET_PARM_ROLLOFF, sizeof(int8_t), (void *)&temp);
3852 return NO_ERROR;
3853 }
3854 }
3855 LOGE("Invalid lensShade value: %s", (str == NULL) ? "NULL" : str);
3856 return BAD_VALUE;
3857}
3858
3859status_t QualcommCameraHardware::setISOValue(const CameraParameters& params) {
3860 const char *str = params.get(CameraParameters::KEY_ISO_MODE);
3861 if (str != NULL) {
3862 int value = (camera_iso_mode_type)attr_lookup(
3863 iso, sizeof(iso) / sizeof(str_map), str);
3864 if (value != NOT_FOUND) {
3865 camera_iso_mode_type temp = (camera_iso_mode_type) value;
3866 mParameters.set(CameraParameters::KEY_ISO_MODE, str);
3867 native_set_parm(CAMERA_SET_PARM_ISO, sizeof(camera_iso_mode_type), (void *)&temp);
3868 return NO_ERROR;
3869 }
3870 }
3871 LOGE("Invalid Iso value: %s", (str == NULL) ? "NULL" : str);
3872 return BAD_VALUE;
3873}
3874
3875
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003876status_t QualcommCameraHardware::setGpsLocation(const CameraParameters& params)
3877{
3878 const char *latitude = params.get(CameraParameters::KEY_GPS_LATITUDE);
3879 if (latitude) {
3880 mParameters.set(CameraParameters::KEY_GPS_LATITUDE, latitude);
3881 }
3882
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08003883 const char *latitudeRef = params.get(CameraParameters::KEY_GPS_LATITUDE_REF);
3884 if (latitudeRef) {
3885 mParameters.set(CameraParameters::KEY_GPS_LATITUDE_REF, latitudeRef);
3886 }
3887
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003888 const char *longitude = params.get(CameraParameters::KEY_GPS_LONGITUDE);
3889 if (longitude) {
3890 mParameters.set(CameraParameters::KEY_GPS_LONGITUDE, longitude);
3891 }
3892
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08003893 const char *longitudeRef = params.get(CameraParameters::KEY_GPS_LONGITUDE_REF);
3894 if (longitudeRef) {
3895 mParameters.set(CameraParameters::KEY_GPS_LONGITUDE_REF, longitudeRef);
3896 }
3897
3898 const char *altitudeRef = params.get(CameraParameters::KEY_GPS_ALTITUDE_REF);
3899 if (altitudeRef) {
3900 mParameters.set(CameraParameters::KEY_GPS_ALTITUDE_REF, altitudeRef);
3901 }
3902
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003903 const char *altitude = params.get(CameraParameters::KEY_GPS_ALTITUDE);
3904 if (altitude) {
3905 mParameters.set(CameraParameters::KEY_GPS_ALTITUDE, altitude);
3906 }
3907
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08003908 const char *status = params.get(CameraParameters::KEY_GPS_STATUS);
3909 if (status) {
3910 mParameters.set(CameraParameters::KEY_GPS_STATUS, status);
3911 }
3912
3913 const char *dateTime = params.get(CameraParameters::KEY_EXIF_DATETIME);
3914 if (dateTime) {
3915 mParameters.set(CameraParameters::KEY_EXIF_DATETIME, dateTime);
3916 }
3917
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003918 const char *timestamp = params.get(CameraParameters::KEY_GPS_TIMESTAMP);
3919 if (timestamp) {
3920 mParameters.set(CameraParameters::KEY_GPS_TIMESTAMP, timestamp);
3921 }
3922 return NO_ERROR;
3923}
3924
3925status_t QualcommCameraHardware::setRotation(const CameraParameters& params)
3926{
3927 status_t rc = NO_ERROR;
3928 int rotation = params.getInt(CameraParameters::KEY_ROTATION);
3929 if (rotation != NOT_FOUND) {
3930 if (rotation == 0 || rotation == 90 || rotation == 180
3931 || rotation == 270) {
3932 mParameters.set(CameraParameters::KEY_ROTATION, rotation);
3933 } else {
3934 LOGE("Invalid rotation value: %d", rotation);
3935 rc = BAD_VALUE;
3936 }
3937 }
3938 return rc;
3939}
3940
3941status_t QualcommCameraHardware::setZoom(const CameraParameters& params)
3942{
3943 status_t rc = NO_ERROR;
3944 // No matter how many different zoom values the driver can provide, HAL
3945 // provides applictations the same number of zoom levels. The maximum driver
3946 // zoom value depends on sensor output (VFE input) and preview size (VFE
3947 // output) because VFE can only crop and cannot upscale. If the preview size
3948 // is bigger, the maximum zoom ratio is smaller. However, we want the
3949 // zoom ratio of each zoom level is always the same whatever the preview
3950 // size is. Ex: zoom level 1 is always 1.2x, zoom level 2 is 1.44x, etc. So,
3951 // we need to have a fixed maximum zoom value and do read it from the
3952 // driver.
Mohan Kandra284966d2010-01-05 13:39:15 -08003953 static const int ZOOM_STEP = 1;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003954 int32_t zoom_level = params.getInt("zoom");
3955
Mohan Kandra284966d2010-01-05 13:39:15 -08003956 LOGV("Set zoom=%d", zoom_level);
3957 if(zoom_level >= 0 && zoom_level <= mMaxZoom) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003958 mParameters.set("zoom", zoom_level);
3959 int32_t zoom_value = ZOOM_STEP * zoom_level;
3960 bool ret = native_set_parm(CAMERA_SET_PARM_ZOOM,
3961 sizeof(zoom_value), (void *)&zoom_value);
3962 rc = ret ? NO_ERROR : UNKNOWN_ERROR;
3963 } else {
3964 rc = BAD_VALUE;
3965 }
3966
3967 return rc;
3968}
3969
3970status_t QualcommCameraHardware::setFocusMode(const CameraParameters& params)
3971{
3972 const char *str = params.get(CameraParameters::KEY_FOCUS_MODE);
3973 if (str != NULL) {
3974 int32_t value = attr_lookup(focus_modes,
3975 sizeof(focus_modes) / sizeof(str_map), str);
3976 if (value != NOT_FOUND) {
3977 mParameters.set(CameraParameters::KEY_FOCUS_MODE, str);
3978 // Focus step is reset to infinity when preview is started. We do
3979 // not need to do anything now.
3980 return NO_ERROR;
3981 }
3982 }
3983 LOGE("Invalid focus mode value: %s", (str == NULL) ? "NULL" : str);
3984 return BAD_VALUE;
3985}
3986
3987status_t QualcommCameraHardware::setOrientation(const CameraParameters& params)
3988{
3989 const char *str = params.get("orientation");
3990
3991 if (str != NULL) {
3992 if (strcmp(str, "portrait") == 0 || strcmp(str, "landscape") == 0) {
3993 // Camera service needs this to decide if the preview frames and raw
3994 // pictures should be rotated.
3995 mParameters.set("orientation", str);
3996 } else {
3997 LOGE("Invalid orientation value: %s", str);
3998 return BAD_VALUE;
3999 }
4000 }
4001 return NO_ERROR;
4002}
4003
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08004004status_t QualcommCameraHardware::setPictureFormat(const CameraParameters& params)
4005{
4006 const char * str = params.get(CameraParameters::KEY_PICTURE_FORMAT);
4007
4008 if(str != NULL){
4009 int32_t value = attr_lookup(picture_formats,
4010 sizeof(picture_formats) / sizeof(str_map), str);
4011 if(value != NOT_FOUND){
4012 mParameters.set(CameraParameters::KEY_PICTURE_FORMAT, str);
4013 } else {
4014 LOGE("Invalid Picture Format value: %s", str);
4015 return BAD_VALUE;
4016 }
4017 }
4018 return NO_ERROR;
4019}
4020
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004021QualcommCameraHardware::MemPool::MemPool(int buffer_size, int num_buffers,
4022 int frame_size,
4023 const char *name) :
4024 mBufferSize(buffer_size),
4025 mNumBuffers(num_buffers),
4026 mFrameSize(frame_size),
4027 mBuffers(NULL), mName(name)
4028{
4029 int page_size_minus_1 = getpagesize() - 1;
4030 mAlignedBufferSize = (buffer_size + page_size_minus_1) & (~page_size_minus_1);
4031}
4032
4033void QualcommCameraHardware::MemPool::completeInitialization()
4034{
4035 // If we do not know how big the frame will be, we wait to allocate
4036 // the buffers describing the individual frames until we do know their
4037 // size.
4038
4039 if (mFrameSize > 0) {
4040 mBuffers = new sp<MemoryBase>[mNumBuffers];
4041 for (int i = 0; i < mNumBuffers; i++) {
4042 mBuffers[i] = new
4043 MemoryBase(mHeap,
4044 i * mAlignedBufferSize,
4045 mFrameSize);
4046 }
4047 }
4048}
4049
4050QualcommCameraHardware::AshmemPool::AshmemPool(int buffer_size, int num_buffers,
4051 int frame_size,
4052 const char *name) :
4053 QualcommCameraHardware::MemPool(buffer_size,
4054 num_buffers,
4055 frame_size,
4056 name)
4057{
4058 LOGV("constructing MemPool %s backed by ashmem: "
4059 "%d frames @ %d uint8_ts, "
4060 "buffer size %d",
4061 mName,
4062 num_buffers, frame_size, buffer_size);
4063
4064 int page_mask = getpagesize() - 1;
4065 int ashmem_size = buffer_size * num_buffers;
4066 ashmem_size += page_mask;
4067 ashmem_size &= ~page_mask;
4068
4069 mHeap = new MemoryHeapBase(ashmem_size);
4070
4071 completeInitialization();
4072}
4073
4074static bool register_buf(int camfd,
4075 int size,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08004076 int frame_size,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004077 int pmempreviewfd,
4078 uint32_t offset,
4079 uint8_t *buf,
4080 int pmem_type,
4081 bool vfe_can_write,
4082 bool register_buffer = true);
4083
4084QualcommCameraHardware::PmemPool::PmemPool(const char *pmem_pool,
4085 int flags,
4086 int camera_control_fd,
4087 int pmem_type,
4088 int buffer_size, int num_buffers,
4089 int frame_size,
4090 const char *name) :
4091 QualcommCameraHardware::MemPool(buffer_size,
4092 num_buffers,
4093 frame_size,
4094 name),
4095 mPmemType(pmem_type),
4096 mCameraControlFd(dup(camera_control_fd))
4097{
4098 LOGV("constructing MemPool %s backed by pmem pool %s: "
4099 "%d frames @ %d bytes, buffer size %d",
4100 mName,
4101 pmem_pool, num_buffers, frame_size,
4102 buffer_size);
4103
4104 LOGV("%s: duplicating control fd %d --> %d",
4105 __FUNCTION__,
4106 camera_control_fd, mCameraControlFd);
4107
4108 // Make a new mmap'ed heap that can be shared across processes.
4109 // mAlignedBufferSize is already in 4k aligned. (do we need total size necessary to be in power of 2??)
4110 mAlignedSize = mAlignedBufferSize * num_buffers;
4111
4112 sp<MemoryHeapBase> masterHeap =
4113 new MemoryHeapBase(pmem_pool, mAlignedSize, flags);
4114
4115 if (masterHeap->getHeapID() < 0) {
4116 LOGE("failed to construct master heap for pmem pool %s", pmem_pool);
4117 masterHeap.clear();
4118 return;
4119 }
4120
4121 sp<MemoryHeapPmem> pmemHeap = new MemoryHeapPmem(masterHeap, flags);
4122 if (pmemHeap->getHeapID() >= 0) {
4123 pmemHeap->slap();
4124 masterHeap.clear();
4125 mHeap = pmemHeap;
4126 pmemHeap.clear();
4127
4128 mFd = mHeap->getHeapID();
4129 if (::ioctl(mFd, PMEM_GET_SIZE, &mSize)) {
4130 LOGE("pmem pool %s ioctl(PMEM_GET_SIZE) error %s (%d)",
4131 pmem_pool,
4132 ::strerror(errno), errno);
4133 mHeap.clear();
4134 return;
4135 }
4136
4137 LOGV("pmem pool %s ioctl(fd = %d, PMEM_GET_SIZE) is %ld",
4138 pmem_pool,
4139 mFd,
4140 mSize.len);
Mohan Kandra284966d2010-01-05 13:39:15 -08004141 LOGD("mBufferSize=%d, mAlignedBufferSize=%d\n", mBufferSize, mAlignedBufferSize);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004142 // Unregister preview buffers with the camera drivers. Allow the VFE to write
4143 // to all preview buffers except for the last one.
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08004144 // Only Register the preview, snapshot and thumbnail buffers with the kernel.
Mohan Kandrad9efed92010-01-15 19:08:39 -08004145 if( (strcmp("postview", mName) != 0) ){
4146 int num_buf = num_buffers;
4147 if(!strcmp("preview", mName)) num_buf = kPreviewBufferCount;
Brian Steuerb62adbd2010-02-02 14:47:08 -08004148 LOGD("num_buffers = %d", num_buf);
Mohan Kandrad9efed92010-01-15 19:08:39 -08004149 for (int cnt = 0; cnt < num_buf; ++cnt) {
Sravankb4f5f1c2010-01-21 11:06:17 +05304150 int active = 1;
4151 if(pmem_type == MSM_PMEM_VIDEO){
4152 active = (cnt<ACTIVE_VIDEO_BUFFERS);
4153 LOGV(" pmempool creating video buffers : active %d ", active);
4154 }
4155 else if (pmem_type == MSM_PMEM_PREVIEW){
4156 active = (cnt < (num_buf-1));
4157 }
Mohan Kandra284966d2010-01-05 13:39:15 -08004158 register_buf(mCameraControlFd,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004159 mBufferSize,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08004160 mFrameSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004161 mHeap->getHeapID(),
4162 mAlignedBufferSize * cnt,
4163 (uint8_t *)mHeap->base() + mAlignedBufferSize * cnt,
4164 pmem_type,
Sravankb4f5f1c2010-01-21 11:06:17 +05304165 active);
Mohan Kandra284966d2010-01-05 13:39:15 -08004166 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004167 }
4168
4169 completeInitialization();
4170 }
4171 else LOGE("pmem pool %s error: could not create master heap!",
4172 pmem_pool);
4173}
4174
4175QualcommCameraHardware::PmemPool::~PmemPool()
4176{
4177 LOGV("%s: %s E", __FUNCTION__, mName);
4178 if (mHeap != NULL) {
4179 // Unregister preview buffers with the camera drivers.
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08004180 // Only Unregister the preview, snapshot and thumbnail
4181 // buffers with the kernel.
Mohan Kandrad9efed92010-01-15 19:08:39 -08004182 if( (strcmp("postview", mName) != 0) ){
4183 int num_buffers = mNumBuffers;
4184 if(!strcmp("preview", mName)) num_buffers = kPreviewBufferCount;
4185 for (int cnt = 0; cnt < num_buffers; ++cnt) {
Mohan Kandra284966d2010-01-05 13:39:15 -08004186 register_buf(mCameraControlFd,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004187 mBufferSize,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08004188 mFrameSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004189 mHeap->getHeapID(),
4190 mAlignedBufferSize * cnt,
4191 (uint8_t *)mHeap->base() + mAlignedBufferSize * cnt,
4192 mPmemType,
4193 false,
4194 false /* unregister */);
Mohan Kandra284966d2010-01-05 13:39:15 -08004195 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004196 }
4197 }
4198 LOGV("destroying PmemPool %s: closing control fd %d",
4199 mName,
4200 mCameraControlFd);
4201 close(mCameraControlFd);
4202 LOGV("%s: %s X", __FUNCTION__, mName);
4203}
4204
4205QualcommCameraHardware::MemPool::~MemPool()
4206{
4207 LOGV("destroying MemPool %s", mName);
4208 if (mFrameSize > 0)
4209 delete [] mBuffers;
4210 mHeap.clear();
4211 LOGV("destroying MemPool %s completed", mName);
4212}
4213
4214static bool register_buf(int camfd,
4215 int size,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08004216 int frame_size,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004217 int pmempreviewfd,
4218 uint32_t offset,
4219 uint8_t *buf,
4220 int pmem_type,
4221 bool vfe_can_write,
4222 bool register_buffer)
4223{
4224 struct msm_pmem_info pmemBuf;
4225
4226 pmemBuf.type = pmem_type;
4227 pmemBuf.fd = pmempreviewfd;
4228 pmemBuf.offset = offset;
4229 pmemBuf.len = size;
4230 pmemBuf.vaddr = buf;
4231 pmemBuf.y_off = 0;
Srinivasan Kannanb36a4fe2010-01-29 19:34:09 -08004232
4233 if(pmem_type == MSM_PMEM_RAW_MAINIMG)
4234 pmemBuf.cbcr_off = 0;
4235 else
4236 pmemBuf.cbcr_off = PAD_TO_WORD(frame_size * 2 / 3);
4237
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004238 pmemBuf.active = vfe_can_write;
4239
4240 LOGV("register_buf: camfd = %d, reg = %d buffer = %p",
4241 camfd, !register_buffer, buf);
4242 if (ioctl(camfd,
4243 register_buffer ?
4244 MSM_CAM_IOCTL_REGISTER_PMEM :
4245 MSM_CAM_IOCTL_UNREGISTER_PMEM,
4246 &pmemBuf) < 0) {
4247 LOGE("register_buf: MSM_CAM_IOCTL_(UN)REGISTER_PMEM fd %d error %s",
4248 camfd,
4249 strerror(errno));
4250 return false;
4251 }
4252 return true;
4253}
4254
4255status_t QualcommCameraHardware::MemPool::dump(int fd, const Vector<String16>& args) const
4256{
4257 const size_t SIZE = 256;
4258 char buffer[SIZE];
4259 String8 result;
4260 snprintf(buffer, 255, "QualcommCameraHardware::AshmemPool::dump\n");
4261 result.append(buffer);
4262 if (mName) {
4263 snprintf(buffer, 255, "mem pool name (%s)\n", mName);
4264 result.append(buffer);
4265 }
4266 if (mHeap != 0) {
4267 snprintf(buffer, 255, "heap base(%p), size(%d), flags(%d), device(%s)\n",
4268 mHeap->getBase(), mHeap->getSize(),
4269 mHeap->getFlags(), mHeap->getDevice());
4270 result.append(buffer);
4271 }
4272 snprintf(buffer, 255,
4273 "buffer size (%d), number of buffers (%d), frame size(%d)",
4274 mBufferSize, mNumBuffers, mFrameSize);
4275 result.append(buffer);
4276 write(fd, result.string(), result.size());
4277 return NO_ERROR;
4278}
4279
4280static void receive_camframe_callback(struct msm_frame *frame)
4281{
4282 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4283 if (obj != 0) {
4284 obj->receivePreviewFrame(frame);
4285 }
4286}
4287
4288static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size)
4289{
4290 LOGV("receive_jpeg_fragment_callback E");
4291 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4292 if (obj != 0) {
4293 obj->receiveJpegPictureFragment(buff_ptr, buff_size);
4294 }
4295 LOGV("receive_jpeg_fragment_callback X");
4296}
4297
4298static void receive_jpeg_callback(jpeg_event_t status)
4299{
4300 LOGV("receive_jpeg_callback E (completion status %d)", status);
4301 if (status == JPEG_EVENT_DONE) {
4302 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4303 if (obj != 0) {
4304 obj->receiveJpegPicture();
4305 }
4306 }
4307 LOGV("receive_jpeg_callback X");
4308}
Sravankb4f5f1c2010-01-21 11:06:17 +05304309// 720p : video frame calbback from camframe
4310static void receive_camframe_video_callback(struct msm_frame *frame)
4311{
4312 LOGV("receive_camframe_video_callback E");
4313 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4314 if (obj != 0) {
4315 obj->receiveRecordingFrame(frame);
4316 }
4317 LOGV("receive_camframe_video_callback X");
4318}
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004319
4320void QualcommCameraHardware::setCallbacks(notify_callback notify_cb,
4321 data_callback data_cb,
4322 data_callback_timestamp data_cb_timestamp,
4323 void* user)
4324{
4325 Mutex::Autolock lock(mLock);
4326 mNotifyCallback = notify_cb;
4327 mDataCallback = data_cb;
4328 mDataCallbackTimestamp = data_cb_timestamp;
4329 mCallbackCookie = user;
4330}
4331
4332void QualcommCameraHardware::enableMsgType(int32_t msgType)
4333{
4334 Mutex::Autolock lock(mLock);
4335 mMsgEnabled |= msgType;
4336}
4337
4338void QualcommCameraHardware::disableMsgType(int32_t msgType)
4339{
4340 Mutex::Autolock lock(mLock);
4341 mMsgEnabled &= ~msgType;
4342}
4343
4344bool QualcommCameraHardware::msgTypeEnabled(int32_t msgType)
4345{
4346 return (mMsgEnabled & msgType);
4347}
4348
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08004349bool QualcommCameraHardware::useOverlay(void)
4350{
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08004351 if( mCurrentTarget == TARGET_MSM7630 ) {
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08004352 /* Only 7x30 supports Overlay */
4353 mUseOverlay = TRUE;
4354 } else
4355 mUseOverlay = FALSE;
4356
4357 LOGV(" Using Overlay : %s ", mUseOverlay ? "YES" : "NO" );
4358 return mUseOverlay;
4359}
4360
4361status_t QualcommCameraHardware::setOverlay(const sp<Overlay> &Overlay)
4362{
4363 if( Overlay != NULL) {
4364 LOGV(" Valid overlay object ");
4365 mOverlayLock.lock();
4366 mOverlay = Overlay;
4367 mOverlayLock.unlock();
4368 } else {
4369 LOGE(" Overlay object NULL. returning ");
Mohan Kandrad9efed92010-01-15 19:08:39 -08004370 mOverlay = NULL;
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08004371 return UNKNOWN_ERROR;
4372 }
4373 return NO_ERROR;
4374}
Kiran Kumar H N215cac42009-12-08 01:53:46 -08004375
4376void QualcommCameraHardware::receive_camframetimeout(void) {
4377 LOGV("receive_camframetimeout: E");
4378 Mutex::Autolock l(&mCamframeTimeoutLock);
Kiran Kumar H N7ac84e32010-02-01 10:58:47 -08004379 LOGD(" Camframe timed out. Not receiving any frames from camera driver ");
Kiran Kumar H N215cac42009-12-08 01:53:46 -08004380 camframe_timeout_flag = TRUE;
4381 LOGV("receive_camframetimeout: X");
4382}
4383
4384static void receive_camframetimeout_callback(void) {
4385 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4386 if (obj != 0) {
4387 obj->receive_camframetimeout();
4388 }
4389}
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08004390
4391void QualcommCameraHardware::storePreviewFrameForPostview(void) {
4392 LOGV(" storePreviewFrameForPostview : E ");
4393
4394 /* Since there is restriction on the maximum overlay dimensions
4395 * that can be created, we use the last preview frame as postview
4396 * for 7x30. */
4397 LOGV(" Copying the preview buffer to postview buffer %d ",
4398 mPreviewFrameSize);
4399 if( mPostViewHeap != NULL && mLastQueuedFrame != NULL) {
4400 memcpy(mPostViewHeap->mHeap->base(),
4401 (uint8_t *)mLastQueuedFrame, mPreviewFrameSize );
4402 } else
4403 LOGE(" Failed to store Preview frame. No Postview ");
4404
4405 LOGV(" storePreviewFrameForPostview : X ");
4406}
Kiran Kumar H Nb49af212010-02-17 15:12:17 -08004407
4408bool QualcommCameraHardware::isValidDimension(int width, int height) {
4409 bool retVal = FALSE;
4410 /* This function checks if a given resolution is valid or not.
4411 * A particular resolution is considered valid if it satisfies
4412 * the following conditions:
4413 * 1. width & height should be multiple of 16.
4414 * 2. width & height should be less than/equal to the dimensions
4415 * supported by the camera sensor.
4416 * 3. the aspect ratio is a valid aspect ratio and is among the
4417 * commonly used aspect ratio as determined by the thumbnail_sizes
4418 * data structure.
4419 */
4420
4421 if( (width == CEILING16(width)) && (height == CEILING16(height))
4422 && (width <= sensorType->max_supported_snapshot_width)
4423 && (height <= sensorType->max_supported_snapshot_height) )
4424 {
4425 uint32_t pictureAspectRatio = (uint32_t)((width * Q12)/height);
4426 for(int i = 0; i < THUMBNAIL_SIZE_COUNT; i++ ) {
4427 if(thumbnail_sizes[i].aspect_ratio == pictureAspectRatio) {
4428 retVal = TRUE;
4429 break;
4430 }
4431 }
4432 }
4433 return retVal;
4434}
4435
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004436}; // namespace android