blob: 326a94ff05a9a42322a39d7c59578f0c08dbc47e [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 Rajguruc73c1722010-04-15 17:39:11 -0700287#define RECORD_BUFFERS_7x30 8
288#define RECORD_BUFFERS_8x50 6
289static int kRecordBufferCount;
290
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -0800291
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800292namespace android {
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800293
294static const int PICTURE_FORMAT_JPEG = 1;
295static const int PICTURE_FORMAT_RAW = 2;
296
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800297// from aeecamera.h
298static const str_map whitebalance[] = {
299 { CameraParameters::WHITE_BALANCE_AUTO, CAMERA_WB_AUTO },
300 { CameraParameters::WHITE_BALANCE_INCANDESCENT, CAMERA_WB_INCANDESCENT },
301 { CameraParameters::WHITE_BALANCE_FLUORESCENT, CAMERA_WB_FLUORESCENT },
302 { CameraParameters::WHITE_BALANCE_DAYLIGHT, CAMERA_WB_DAYLIGHT },
303 { CameraParameters::WHITE_BALANCE_CLOUDY_DAYLIGHT, CAMERA_WB_CLOUDY_DAYLIGHT }
304};
305
306// from camera_effect_t. This list must match aeecamera.h
307static const str_map effects[] = {
308 { CameraParameters::EFFECT_NONE, CAMERA_EFFECT_OFF },
309 { CameraParameters::EFFECT_MONO, CAMERA_EFFECT_MONO },
310 { CameraParameters::EFFECT_NEGATIVE, CAMERA_EFFECT_NEGATIVE },
311 { CameraParameters::EFFECT_SOLARIZE, CAMERA_EFFECT_SOLARIZE },
312 { CameraParameters::EFFECT_SEPIA, CAMERA_EFFECT_SEPIA },
313 { CameraParameters::EFFECT_POSTERIZE, CAMERA_EFFECT_POSTERIZE },
314 { CameraParameters::EFFECT_WHITEBOARD, CAMERA_EFFECT_WHITEBOARD },
315 { CameraParameters::EFFECT_BLACKBOARD, CAMERA_EFFECT_BLACKBOARD },
316 { CameraParameters::EFFECT_AQUA, CAMERA_EFFECT_AQUA }
317};
318
319// from qcamera/common/camera.h
Apurva Rajguru55562b02009-12-03 12:25:35 -0800320static const str_map autoexposure[] = {
321 { CameraParameters::AUTO_EXPOSURE_FRAME_AVG, CAMERA_AEC_FRAME_AVERAGE },
322 { CameraParameters::AUTO_EXPOSURE_CENTER_WEIGHTED, CAMERA_AEC_CENTER_WEIGHTED },
323 { CameraParameters::AUTO_EXPOSURE_SPOT_METERING, CAMERA_AEC_SPOT_METERING }
324};
325
326// from qcamera/common/camera.h
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800327static const str_map antibanding[] = {
328 { CameraParameters::ANTIBANDING_OFF, CAMERA_ANTIBANDING_OFF },
329 { CameraParameters::ANTIBANDING_50HZ, CAMERA_ANTIBANDING_50HZ },
330 { CameraParameters::ANTIBANDING_60HZ, CAMERA_ANTIBANDING_60HZ },
331 { CameraParameters::ANTIBANDING_AUTO, CAMERA_ANTIBANDING_AUTO }
332};
333
334/* Mapping from MCC to antibanding type */
335struct country_map {
336 uint32_t country_code;
337 camera_antibanding_type type;
338};
339
340static struct country_map country_numeric[] = {
341 { 202, CAMERA_ANTIBANDING_50HZ }, // Greece
342 { 204, CAMERA_ANTIBANDING_50HZ }, // Netherlands
343 { 206, CAMERA_ANTIBANDING_50HZ }, // Belgium
344 { 208, CAMERA_ANTIBANDING_50HZ }, // France
345 { 212, CAMERA_ANTIBANDING_50HZ }, // Monaco
346 { 213, CAMERA_ANTIBANDING_50HZ }, // Andorra
347 { 214, CAMERA_ANTIBANDING_50HZ }, // Spain
348 { 216, CAMERA_ANTIBANDING_50HZ }, // Hungary
349 { 219, CAMERA_ANTIBANDING_50HZ }, // Croatia
350 { 220, CAMERA_ANTIBANDING_50HZ }, // Serbia
351 { 222, CAMERA_ANTIBANDING_50HZ }, // Italy
352 { 226, CAMERA_ANTIBANDING_50HZ }, // Romania
353 { 228, CAMERA_ANTIBANDING_50HZ }, // Switzerland
354 { 230, CAMERA_ANTIBANDING_50HZ }, // Czech Republic
355 { 231, CAMERA_ANTIBANDING_50HZ }, // Slovakia
356 { 232, CAMERA_ANTIBANDING_50HZ }, // Austria
357 { 234, CAMERA_ANTIBANDING_50HZ }, // United Kingdom
358 { 235, CAMERA_ANTIBANDING_50HZ }, // United Kingdom
359 { 238, CAMERA_ANTIBANDING_50HZ }, // Denmark
360 { 240, CAMERA_ANTIBANDING_50HZ }, // Sweden
361 { 242, CAMERA_ANTIBANDING_50HZ }, // Norway
362 { 244, CAMERA_ANTIBANDING_50HZ }, // Finland
363 { 246, CAMERA_ANTIBANDING_50HZ }, // Lithuania
364 { 247, CAMERA_ANTIBANDING_50HZ }, // Latvia
365 { 248, CAMERA_ANTIBANDING_50HZ }, // Estonia
366 { 250, CAMERA_ANTIBANDING_50HZ }, // Russian Federation
367 { 255, CAMERA_ANTIBANDING_50HZ }, // Ukraine
368 { 257, CAMERA_ANTIBANDING_50HZ }, // Belarus
369 { 259, CAMERA_ANTIBANDING_50HZ }, // Moldova
370 { 260, CAMERA_ANTIBANDING_50HZ }, // Poland
371 { 262, CAMERA_ANTIBANDING_50HZ }, // Germany
372 { 266, CAMERA_ANTIBANDING_50HZ }, // Gibraltar
373 { 268, CAMERA_ANTIBANDING_50HZ }, // Portugal
374 { 270, CAMERA_ANTIBANDING_50HZ }, // Luxembourg
375 { 272, CAMERA_ANTIBANDING_50HZ }, // Ireland
376 { 274, CAMERA_ANTIBANDING_50HZ }, // Iceland
377 { 276, CAMERA_ANTIBANDING_50HZ }, // Albania
378 { 278, CAMERA_ANTIBANDING_50HZ }, // Malta
379 { 280, CAMERA_ANTIBANDING_50HZ }, // Cyprus
380 { 282, CAMERA_ANTIBANDING_50HZ }, // Georgia
381 { 283, CAMERA_ANTIBANDING_50HZ }, // Armenia
382 { 284, CAMERA_ANTIBANDING_50HZ }, // Bulgaria
383 { 286, CAMERA_ANTIBANDING_50HZ }, // Turkey
384 { 288, CAMERA_ANTIBANDING_50HZ }, // Faroe Islands
385 { 290, CAMERA_ANTIBANDING_50HZ }, // Greenland
386 { 293, CAMERA_ANTIBANDING_50HZ }, // Slovenia
387 { 294, CAMERA_ANTIBANDING_50HZ }, // Macedonia
388 { 295, CAMERA_ANTIBANDING_50HZ }, // Liechtenstein
389 { 297, CAMERA_ANTIBANDING_50HZ }, // Montenegro
390 { 302, CAMERA_ANTIBANDING_60HZ }, // Canada
391 { 310, CAMERA_ANTIBANDING_60HZ }, // United States of America
392 { 311, CAMERA_ANTIBANDING_60HZ }, // United States of America
393 { 312, CAMERA_ANTIBANDING_60HZ }, // United States of America
394 { 313, CAMERA_ANTIBANDING_60HZ }, // United States of America
395 { 314, CAMERA_ANTIBANDING_60HZ }, // United States of America
396 { 315, CAMERA_ANTIBANDING_60HZ }, // United States of America
397 { 316, CAMERA_ANTIBANDING_60HZ }, // United States of America
398 { 330, CAMERA_ANTIBANDING_60HZ }, // Puerto Rico
399 { 334, CAMERA_ANTIBANDING_60HZ }, // Mexico
400 { 338, CAMERA_ANTIBANDING_50HZ }, // Jamaica
401 { 340, CAMERA_ANTIBANDING_50HZ }, // Martinique
402 { 342, CAMERA_ANTIBANDING_50HZ }, // Barbados
403 { 346, CAMERA_ANTIBANDING_60HZ }, // Cayman Islands
404 { 350, CAMERA_ANTIBANDING_60HZ }, // Bermuda
405 { 352, CAMERA_ANTIBANDING_50HZ }, // Grenada
406 { 354, CAMERA_ANTIBANDING_60HZ }, // Montserrat
407 { 362, CAMERA_ANTIBANDING_50HZ }, // Netherlands Antilles
408 { 363, CAMERA_ANTIBANDING_60HZ }, // Aruba
409 { 364, CAMERA_ANTIBANDING_60HZ }, // Bahamas
410 { 365, CAMERA_ANTIBANDING_60HZ }, // Anguilla
411 { 366, CAMERA_ANTIBANDING_50HZ }, // Dominica
412 { 368, CAMERA_ANTIBANDING_60HZ }, // Cuba
413 { 370, CAMERA_ANTIBANDING_60HZ }, // Dominican Republic
414 { 372, CAMERA_ANTIBANDING_60HZ }, // Haiti
415 { 401, CAMERA_ANTIBANDING_50HZ }, // Kazakhstan
416 { 402, CAMERA_ANTIBANDING_50HZ }, // Bhutan
417 { 404, CAMERA_ANTIBANDING_50HZ }, // India
418 { 405, CAMERA_ANTIBANDING_50HZ }, // India
419 { 410, CAMERA_ANTIBANDING_50HZ }, // Pakistan
420 { 413, CAMERA_ANTIBANDING_50HZ }, // Sri Lanka
421 { 414, CAMERA_ANTIBANDING_50HZ }, // Myanmar
422 { 415, CAMERA_ANTIBANDING_50HZ }, // Lebanon
423 { 416, CAMERA_ANTIBANDING_50HZ }, // Jordan
424 { 417, CAMERA_ANTIBANDING_50HZ }, // Syria
425 { 418, CAMERA_ANTIBANDING_50HZ }, // Iraq
426 { 419, CAMERA_ANTIBANDING_50HZ }, // Kuwait
427 { 420, CAMERA_ANTIBANDING_60HZ }, // Saudi Arabia
428 { 421, CAMERA_ANTIBANDING_50HZ }, // Yemen
429 { 422, CAMERA_ANTIBANDING_50HZ }, // Oman
430 { 424, CAMERA_ANTIBANDING_50HZ }, // United Arab Emirates
431 { 425, CAMERA_ANTIBANDING_50HZ }, // Israel
432 { 426, CAMERA_ANTIBANDING_50HZ }, // Bahrain
433 { 427, CAMERA_ANTIBANDING_50HZ }, // Qatar
434 { 428, CAMERA_ANTIBANDING_50HZ }, // Mongolia
435 { 429, CAMERA_ANTIBANDING_50HZ }, // Nepal
436 { 430, CAMERA_ANTIBANDING_50HZ }, // United Arab Emirates
437 { 431, CAMERA_ANTIBANDING_50HZ }, // United Arab Emirates
438 { 432, CAMERA_ANTIBANDING_50HZ }, // Iran
439 { 434, CAMERA_ANTIBANDING_50HZ }, // Uzbekistan
440 { 436, CAMERA_ANTIBANDING_50HZ }, // Tajikistan
441 { 437, CAMERA_ANTIBANDING_50HZ }, // Kyrgyz Rep
442 { 438, CAMERA_ANTIBANDING_50HZ }, // Turkmenistan
443 { 440, CAMERA_ANTIBANDING_60HZ }, // Japan
444 { 441, CAMERA_ANTIBANDING_60HZ }, // Japan
445 { 452, CAMERA_ANTIBANDING_50HZ }, // Vietnam
446 { 454, CAMERA_ANTIBANDING_50HZ }, // Hong Kong
447 { 455, CAMERA_ANTIBANDING_50HZ }, // Macao
448 { 456, CAMERA_ANTIBANDING_50HZ }, // Cambodia
449 { 457, CAMERA_ANTIBANDING_50HZ }, // Laos
450 { 460, CAMERA_ANTIBANDING_50HZ }, // China
451 { 466, CAMERA_ANTIBANDING_60HZ }, // Taiwan
452 { 470, CAMERA_ANTIBANDING_50HZ }, // Bangladesh
453 { 472, CAMERA_ANTIBANDING_50HZ }, // Maldives
454 { 502, CAMERA_ANTIBANDING_50HZ }, // Malaysia
455 { 505, CAMERA_ANTIBANDING_50HZ }, // Australia
456 { 510, CAMERA_ANTIBANDING_50HZ }, // Indonesia
457 { 514, CAMERA_ANTIBANDING_50HZ }, // East Timor
458 { 515, CAMERA_ANTIBANDING_60HZ }, // Philippines
459 { 520, CAMERA_ANTIBANDING_50HZ }, // Thailand
460 { 525, CAMERA_ANTIBANDING_50HZ }, // Singapore
461 { 530, CAMERA_ANTIBANDING_50HZ }, // New Zealand
462 { 535, CAMERA_ANTIBANDING_60HZ }, // Guam
463 { 536, CAMERA_ANTIBANDING_50HZ }, // Nauru
464 { 537, CAMERA_ANTIBANDING_50HZ }, // Papua New Guinea
465 { 539, CAMERA_ANTIBANDING_50HZ }, // Tonga
466 { 541, CAMERA_ANTIBANDING_50HZ }, // Vanuatu
467 { 542, CAMERA_ANTIBANDING_50HZ }, // Fiji
468 { 544, CAMERA_ANTIBANDING_60HZ }, // American Samoa
469 { 545, CAMERA_ANTIBANDING_50HZ }, // Kiribati
470 { 546, CAMERA_ANTIBANDING_50HZ }, // New Caledonia
471 { 548, CAMERA_ANTIBANDING_50HZ }, // Cook Islands
472 { 602, CAMERA_ANTIBANDING_50HZ }, // Egypt
473 { 603, CAMERA_ANTIBANDING_50HZ }, // Algeria
474 { 604, CAMERA_ANTIBANDING_50HZ }, // Morocco
475 { 605, CAMERA_ANTIBANDING_50HZ }, // Tunisia
476 { 606, CAMERA_ANTIBANDING_50HZ }, // Libya
477 { 607, CAMERA_ANTIBANDING_50HZ }, // Gambia
478 { 608, CAMERA_ANTIBANDING_50HZ }, // Senegal
479 { 609, CAMERA_ANTIBANDING_50HZ }, // Mauritania
480 { 610, CAMERA_ANTIBANDING_50HZ }, // Mali
481 { 611, CAMERA_ANTIBANDING_50HZ }, // Guinea
482 { 613, CAMERA_ANTIBANDING_50HZ }, // Burkina Faso
483 { 614, CAMERA_ANTIBANDING_50HZ }, // Niger
484 { 616, CAMERA_ANTIBANDING_50HZ }, // Benin
485 { 617, CAMERA_ANTIBANDING_50HZ }, // Mauritius
486 { 618, CAMERA_ANTIBANDING_50HZ }, // Liberia
487 { 619, CAMERA_ANTIBANDING_50HZ }, // Sierra Leone
488 { 620, CAMERA_ANTIBANDING_50HZ }, // Ghana
489 { 621, CAMERA_ANTIBANDING_50HZ }, // Nigeria
490 { 622, CAMERA_ANTIBANDING_50HZ }, // Chad
491 { 623, CAMERA_ANTIBANDING_50HZ }, // Central African Republic
492 { 624, CAMERA_ANTIBANDING_50HZ }, // Cameroon
493 { 625, CAMERA_ANTIBANDING_50HZ }, // Cape Verde
494 { 627, CAMERA_ANTIBANDING_50HZ }, // Equatorial Guinea
495 { 631, CAMERA_ANTIBANDING_50HZ }, // Angola
496 { 633, CAMERA_ANTIBANDING_50HZ }, // Seychelles
497 { 634, CAMERA_ANTIBANDING_50HZ }, // Sudan
498 { 636, CAMERA_ANTIBANDING_50HZ }, // Ethiopia
499 { 637, CAMERA_ANTIBANDING_50HZ }, // Somalia
500 { 638, CAMERA_ANTIBANDING_50HZ }, // Djibouti
501 { 639, CAMERA_ANTIBANDING_50HZ }, // Kenya
502 { 640, CAMERA_ANTIBANDING_50HZ }, // Tanzania
503 { 641, CAMERA_ANTIBANDING_50HZ }, // Uganda
504 { 642, CAMERA_ANTIBANDING_50HZ }, // Burundi
505 { 643, CAMERA_ANTIBANDING_50HZ }, // Mozambique
506 { 645, CAMERA_ANTIBANDING_50HZ }, // Zambia
507 { 646, CAMERA_ANTIBANDING_50HZ }, // Madagascar
508 { 647, CAMERA_ANTIBANDING_50HZ }, // France
509 { 648, CAMERA_ANTIBANDING_50HZ }, // Zimbabwe
510 { 649, CAMERA_ANTIBANDING_50HZ }, // Namibia
511 { 650, CAMERA_ANTIBANDING_50HZ }, // Malawi
512 { 651, CAMERA_ANTIBANDING_50HZ }, // Lesotho
513 { 652, CAMERA_ANTIBANDING_50HZ }, // Botswana
514 { 653, CAMERA_ANTIBANDING_50HZ }, // Swaziland
515 { 654, CAMERA_ANTIBANDING_50HZ }, // Comoros
516 { 655, CAMERA_ANTIBANDING_50HZ }, // South Africa
517 { 657, CAMERA_ANTIBANDING_50HZ }, // Eritrea
518 { 702, CAMERA_ANTIBANDING_60HZ }, // Belize
519 { 704, CAMERA_ANTIBANDING_60HZ }, // Guatemala
520 { 706, CAMERA_ANTIBANDING_60HZ }, // El Salvador
521 { 708, CAMERA_ANTIBANDING_60HZ }, // Honduras
522 { 710, CAMERA_ANTIBANDING_60HZ }, // Nicaragua
523 { 712, CAMERA_ANTIBANDING_60HZ }, // Costa Rica
524 { 714, CAMERA_ANTIBANDING_60HZ }, // Panama
525 { 722, CAMERA_ANTIBANDING_50HZ }, // Argentina
526 { 724, CAMERA_ANTIBANDING_60HZ }, // Brazil
527 { 730, CAMERA_ANTIBANDING_50HZ }, // Chile
528 { 732, CAMERA_ANTIBANDING_60HZ }, // Colombia
529 { 734, CAMERA_ANTIBANDING_60HZ }, // Venezuela
530 { 736, CAMERA_ANTIBANDING_50HZ }, // Bolivia
531 { 738, CAMERA_ANTIBANDING_60HZ }, // Guyana
532 { 740, CAMERA_ANTIBANDING_60HZ }, // Ecuador
533 { 742, CAMERA_ANTIBANDING_50HZ }, // French Guiana
534 { 744, CAMERA_ANTIBANDING_50HZ }, // Paraguay
535 { 746, CAMERA_ANTIBANDING_60HZ }, // Suriname
536 { 748, CAMERA_ANTIBANDING_50HZ }, // Uruguay
537 { 750, CAMERA_ANTIBANDING_50HZ }, // Falkland Islands
538};
539
540#define country_number (sizeof(country_numeric) / sizeof(country_map))
541
542/* Look up pre-sorted antibanding_type table by current MCC. */
543static camera_antibanding_type camera_get_location(void) {
544 char value[PROP_VALUE_MAX];
545 char country_value[PROP_VALUE_MAX];
546 uint32_t country_code, count;
547 memset(value, 0x00, sizeof(value));
548 memset(country_value, 0x00, sizeof(country_value));
549 if (!__system_property_get("gsm.operator.numeric", value)) {
550 return CAMERA_ANTIBANDING_60HZ;
551 }
552 memcpy(country_value, value, 3);
553 country_code = atoi(country_value);
554 LOGD("value:%s, country value:%s, country code:%d\n",
555 value, country_value, country_code);
556 int left = 0;
557 int right = country_number - 1;
558 while (left <= right) {
559 int index = (left + right) >> 1;
560 if (country_numeric[index].country_code == country_code)
561 return country_numeric[index].type;
562 else if (country_numeric[index].country_code > country_code)
563 right = index - 1;
564 else
565 left = index + 1;
566 }
567 return CAMERA_ANTIBANDING_60HZ;
568}
569
570// from camera.h, led_mode_t
571static const str_map flash[] = {
572 { CameraParameters::FLASH_MODE_OFF, LED_MODE_OFF },
573 { CameraParameters::FLASH_MODE_AUTO, LED_MODE_AUTO },
574 { CameraParameters::FLASH_MODE_ON, LED_MODE_ON }
575};
576
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530577// from mm-camera/common/camera.h.
578static const str_map iso[] = {
579 { CameraParameters::ISO_AUTO, CAMERA_ISO_AUTO},
580 { CameraParameters::ISO_HJR, CAMERA_ISO_DEBLUR},
581 { CameraParameters::ISO_100, CAMERA_ISO_100},
582 { CameraParameters::ISO_200, CAMERA_ISO_200},
583 { CameraParameters::ISO_400, CAMERA_ISO_400},
584 { CameraParameters::ISO_800, CAMERA_ISO_800 }
585};
586
587
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800588#define DONT_CARE 0
589static const str_map focus_modes[] = {
Srinivasan Kannan71229622009-12-04 12:05:58 -0800590 { CameraParameters::FOCUS_MODE_AUTO, AF_MODE_AUTO},
591 { CameraParameters::FOCUS_MODE_INFINITY, DONT_CARE },
592 { CameraParameters::FOCUS_MODE_NORMAL, AF_MODE_NORMAL },
593 { CameraParameters::FOCUS_MODE_MACRO, AF_MODE_MACRO }
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800594};
595
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530596static const str_map lensshade[] = {
597 { CameraParameters::LENSSHADE_ENABLE, TRUE },
598 { CameraParameters::LENSSHADE_DISABLE, FALSE }
599};
600
Srinivasan Kannan71229622009-12-04 12:05:58 -0800601struct SensorType {
602 const char *name;
603 int rawPictureWidth;
604 int rawPictureHeight;
605 bool hasAutoFocusSupport;
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800606 int max_supported_snapshot_width;
607 int max_supported_snapshot_height;
Apurva Rajguruffe264a2010-03-09 13:50:53 -0800608 int bitMask;
Srinivasan Kannan71229622009-12-04 12:05:58 -0800609};
610
611static SensorType sensorTypes[] = {
Apurva Rajguruffe264a2010-03-09 13:50:53 -0800612 { "5mp", 2608, 1960, true, 2592, 1944,0x00000fff },
613 { "3mp", 2064, 1544, false, 2048, 1536,0x000007ff },
614 { "2mp", 3200, 1200, false, 1600, 1200,0x000007ff } };
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800615
Srinivasan Kannan71229622009-12-04 12:05:58 -0800616
617static SensorType * sensorType;
618
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800619static const str_map picture_formats[] = {
620 {CameraParameters::PIXEL_FORMAT_JPEG, PICTURE_FORMAT_JPEG},
621 {CameraParameters::PIXEL_FORMAT_RAW, PICTURE_FORMAT_RAW}
622};
623
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800624static bool parameter_string_initialized = false;
625static String8 preview_size_values;
626static String8 picture_size_values;
627static String8 antibanding_values;
628static String8 effect_values;
Apurva Rajguru55562b02009-12-03 12:25:35 -0800629static String8 autoexposure_values;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800630static String8 whitebalance_values;
631static String8 flash_values;
632static String8 focus_mode_values;
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530633static String8 iso_values;
634static String8 lensshade_values;
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800635static String8 picture_format_values;
636
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800637
638static String8 create_sizes_str(const camera_size_type *sizes, int len) {
639 String8 str;
640 char buffer[32];
641
642 if (len > 0) {
643 sprintf(buffer, "%dx%d", sizes[0].width, sizes[0].height);
644 str.append(buffer);
645 }
646 for (int i = 1; i < len; i++) {
647 sprintf(buffer, ",%dx%d", sizes[i].width, sizes[i].height);
648 str.append(buffer);
649 }
650 return str;
651}
652
653static String8 create_values_str(const str_map *values, int len) {
654 String8 str;
655
656 if (len > 0) {
657 str.append(values[0].desc);
658 }
659 for (int i = 1; i < len; i++) {
660 str.append(",");
661 str.append(values[i].desc);
662 }
663 return str;
664}
665
Sravankb4f5f1c2010-01-21 11:06:17 +0530666extern "C" {
667//------------------------------------------------------------------------
668// : 720p busyQ funcitons
669// --------------------------------------------------------------------
670static struct fifo_queue g_busy_frame_queue =
671 {0, 0, 0, PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER};
672};
673/*===========================================================================
674 * FUNCTION cam_frame_wait_video
675 *
676 * DESCRIPTION this function waits a video in the busy queue
677 * ===========================================================================*/
678
679static void cam_frame_wait_video (void)
680{
681 LOGV("cam_frame_wait_video E ");
682 if ((g_busy_frame_queue.num_of_frames) <=0){
683 pthread_cond_wait(&(g_busy_frame_queue.wait), &(g_busy_frame_queue.mut));
684 }
685 LOGV("cam_frame_wait_video X");
686 return;
687}
688
689/*===========================================================================
690 * FUNCTION cam_frame_flush_video
691 *
692 * DESCRIPTION this function deletes all the buffers in busy queue
693 * ===========================================================================*/
694void cam_frame_flush_video (void)
695{
696 LOGV("cam_frame_flush_video: in n = %d\n", g_busy_frame_queue.num_of_frames);
697 pthread_mutex_lock(&(g_busy_frame_queue.mut));
698
699 while (g_busy_frame_queue.front)
700 {
701 //dequeue from the busy queue
702 struct fifo_node *node = dequeue (&g_busy_frame_queue);
703 if(node)
704 free(node);
705
706 LOGV("cam_frame_flush_video: node \n");
707 }
708 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
709 LOGV("cam_frame_flush_video: out n = %d\n", g_busy_frame_queue.num_of_frames);
710 return ;
711}
712/*===========================================================================
713 * FUNCTION cam_frame_get_video
714 *
715 * DESCRIPTION this function returns a video frame from the head
716 * ===========================================================================*/
717static struct msm_frame * cam_frame_get_video()
718{
719 struct msm_frame *p = NULL;
720 LOGV("cam_frame_get_video... in\n");
721 LOGV("cam_frame_get_video... got lock\n");
722 if (g_busy_frame_queue.front)
723 {
724 //dequeue
725 struct fifo_node *node = dequeue (&g_busy_frame_queue);
726 if (node)
727 {
728 p = (struct msm_frame *)node->f;
729 free (node);
730 }
731 LOGV("cam_frame_get_video... out = %x\n", p->buffer);
732 }
733 return p;
734}
735
736/*===========================================================================
737 * FUNCTION cam_frame_post_video
738 *
739 * DESCRIPTION this function add a busy video frame to the busy queue tails
740 * ===========================================================================*/
741static void cam_frame_post_video (struct msm_frame *p)
742{
743 if (!p)
744 {
745 LOGE("post video , buffer is null");
746 return;
747 }
748 LOGV("cam_frame_post_video... in = %x\n", (unsigned int)(p->buffer));
749 pthread_mutex_lock(&(g_busy_frame_queue.mut));
750 LOGV("post_video got lock. q count before enQ %d", g_busy_frame_queue.num_of_frames);
751 //enqueue to busy queue
752 struct fifo_node *node = (struct fifo_node *)malloc (sizeof (struct fifo_node));
753 if (node)
754 {
755 LOGV(" post video , enqueing in busy queue");
756 node->f = p;
757 node->next = NULL;
758 enqueue (&g_busy_frame_queue, node);
759 LOGV("post_video got lock. q count after enQ %d", g_busy_frame_queue.num_of_frames);
760 }
761 else
762 {
763 LOGE("cam_frame_post_video error... out of memory\n");
764 }
765
766 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
767 pthread_cond_signal(&(g_busy_frame_queue.wait));
768
769 LOGV("cam_frame_post_video... out = %x\n", p->buffer);
770
771 return;
772}
773
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -0800774void QualcommCameraHardware::storeTargetType(void) {
775 char mDeviceName[PROPERTY_VALUE_MAX];
776 property_get("ro.product.device",mDeviceName," ");
777 mCurrentTarget = TARGET_MAX;
778 for( int i = 0; i < TARGET_MAX ; i++) {
779 if( !strncmp(mDeviceName, targetList[i].targetStr, 7)) {
780 mCurrentTarget = targetList[i].targetEnum;
781 break;
782 }
783 }
784 LOGV(" Storing the current target type as %d ", mCurrentTarget );
785 return;
786}
787
Sravankb4f5f1c2010-01-21 11:06:17 +0530788//-------------------------------------------------------------------------------------
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800789static Mutex singleton_lock;
790static bool singleton_releasing;
791static Condition singleton_wait;
792
793static void receive_camframe_callback(struct msm_frame *frame);
Sravankb4f5f1c2010-01-21 11:06:17 +0530794static void receive_camframe_video_callback(struct msm_frame *frame); // 720p
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800795static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size);
796static void receive_jpeg_callback(jpeg_event_t status);
797static void receive_shutter_callback(common_crop_t *crop);
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800798static void receive_camframetimeout_callback(void);
Mohan Kandra284966d2010-01-05 13:39:15 -0800799static int fb_fd = -1;
800static int32_t mMaxZoom = 0;
801static bool native_get_maxzoom(int camfd, void *pZm);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800802
Mohan Kandrad9efed92010-01-15 19:08:39 -0800803static int dstOffset = 0;
804
Brian Steuer07704892009-12-18 18:07:33 -0800805static int camerafd;
806pthread_t w_thread;
807
808void *opencamerafd(void *data) {
809 camerafd = open(MSM_CAMERA_CONTROL, O_RDWR);
810 return NULL;
811}
812
Mohan Kandrad9efed92010-01-15 19:08:39 -0800813/* When using MDP zoom, double the preview buffers. The usage of these
814 * buffers is as follows:
815 * 1. As all the buffers comes under a single FD, and at initial registration,
816 * this FD will be passed to surface flinger, surface flinger can have access
817 * to all the buffers when needed.
818 * 2. Only "kPreviewBufferCount" buffers (SrcSet) will be registered with the
819 * camera driver to receive preview frames. The remaining buffers (DstSet),
820 * will be used at HAL and by surface flinger only when crop information
821 * is present in the frame.
822 * 3. When there is no crop information, there will be no call to MDP zoom,
823 * and the buffers in SrcSet will be passed to surface flinger to display.
824 * 4. With crop information present, MDP zoom will be called, and the final
825 * data will be placed in a buffer from DstSet, and this buffer will be given
826 * to surface flinger to display.
827 */
828#define NUM_MORE_BUFS 2
829
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800830QualcommCameraHardware::QualcommCameraHardware()
831 : mParameters(),
832 mCameraRunning(false),
833 mPreviewInitialized(false),
834 mFrameThreadRunning(false),
Mohan Kandra156d0ac2010-01-25 16:59:17 -0800835 mVideoThreadRunning(false),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800836 mSnapshotThreadRunning(false),
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800837 mSnapshotFormat(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800838 mReleasedRecordingFrame(false),
839 mPreviewFrameSize(0),
840 mRawSize(0),
841 mCameraControlFd(-1),
842 mAutoFocusThreadRunning(false),
843 mAutoFocusFd(-1),
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800844 mBrightness(0),
Apurva Rajguruf12d9d22010-04-05 16:47:12 -0700845 mHJR(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800846 mInPreviewCallback(false),
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800847 mUseOverlay(0),
848 mOverlay(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800849 mMsgEnabled(0),
850 mNotifyCallback(0),
851 mDataCallback(0),
852 mDataCallbackTimestamp(0),
Mohan Kandra740cfce2010-01-07 12:58:24 -0800853 mCallbackCookie(0),
854 mDebugFps(0)
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800855{
Brian Steuer07704892009-12-18 18:07:33 -0800856
857 // Start opening camera device in a separate thread/ Since this
858 // initializes the sensor hardware, this can take a long time. So,
859 // start the process here so it will be ready by the time it's
860 // needed.
861 if ((pthread_create(&w_thread, NULL, opencamerafd, NULL)) != 0) {
862 LOGE("Camera open thread creation failed");
863 }
864
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800865 memset(&mDimension, 0, sizeof(mDimension));
866 memset(&mCrop, 0, sizeof(mCrop));
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -0800867 memset(&zoomCropInfo, 0, sizeof(zoom_crop_info));
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -0800868 storeTargetType();
Mohan Kandra740cfce2010-01-07 12:58:24 -0800869 char value[PROPERTY_VALUE_MAX];
870 property_get("persist.debug.sf.showfps", value, "0");
871 mDebugFps = atoi(value);
Apurva Rajguruc73c1722010-04-15 17:39:11 -0700872 if( mCurrentTarget == TARGET_MSM7630 ) {
Sravankb4f5f1c2010-01-21 11:06:17 +0530873 kPreviewBufferCountActual = kPreviewBufferCount;
Apurva Rajguruc73c1722010-04-15 17:39:11 -0700874 kRecordBufferCount = RECORD_BUFFERS_7x30;
875 recordframes = new msm_frame[kRecordBufferCount];
876 }
877 else {
Sravankb4f5f1c2010-01-21 11:06:17 +0530878 kPreviewBufferCountActual = kPreviewBufferCount + NUM_MORE_BUFS;
Apurva Rajguruc73c1722010-04-15 17:39:11 -0700879 if( mCurrentTarget == TARGET_QSD8250 ) {
880 kRecordBufferCount = RECORD_BUFFERS_8x50;
881 recordframes = new msm_frame[kRecordBufferCount];
882 }
883 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800884 LOGV("constructor EX");
885}
886
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800887
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -0800888void QualcommCameraHardware::filterPreviewSizes(){
889
Apurva Rajguruffe264a2010-03-09 13:50:53 -0800890 unsigned int boardMask = 0;
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -0800891 int prop = 0;
892 for(prop=0;prop<sizeof(boardProperties)/sizeof(board_property);prop++){
893 if(mCurrentTarget == boardProperties[prop].target){
Apurva Rajguruffe264a2010-03-09 13:50:53 -0800894 boardMask = boardProperties[prop].previewSizeMask;
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -0800895 break;
896 }
897 }
898
Apurva Rajguruffe264a2010-03-09 13:50:53 -0800899 int bitMask = boardMask & sensorType->bitMask;
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -0800900 if(bitMask){
901 unsigned int mask = 1<<(PREVIEW_SIZE_COUNT-1);
902 previewSizeCount=0;
903 unsigned int i = 0;
904 while(mask){
905 if(mask&bitMask)
906 supportedPreviewSizes[previewSizeCount++] =
907 preview_sizes[i];
908 i++;
909 mask = mask >> 1;
910 }
911 }
912}
913
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800914//filter Picture sizes based on max width and height
915void QualcommCameraHardware::filterPictureSizes(){
916 int i;
917 for(i=0;i<PICTURE_SIZE_COUNT;i++){
918 if(((picture_sizes[i].width <=
919 sensorType->max_supported_snapshot_width) &&
920 (picture_sizes[i].height <=
921 sensorType->max_supported_snapshot_height))){
922 picture_sizes_ptr = picture_sizes + i;
923 supportedPictureSizesCount = PICTURE_SIZE_COUNT - i ;
924 return ;
925 }
926 }
927}
928
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800929void QualcommCameraHardware::initDefaultParameters()
930{
931 LOGV("initDefaultParameters E");
932
933 // Initialize constant parameter strings. This will happen only once in the
934 // lifetime of the mediaserver process.
935 if (!parameter_string_initialized) {
Srinivasan Kannan71229622009-12-04 12:05:58 -0800936 findSensorType();
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800937 antibanding_values = create_values_str(
938 antibanding, sizeof(antibanding) / sizeof(str_map));
939 effect_values = create_values_str(
940 effects, sizeof(effects) / sizeof(str_map));
Apurva Rajguru55562b02009-12-03 12:25:35 -0800941 autoexposure_values = create_values_str(
942 autoexposure, sizeof(autoexposure) / sizeof(str_map));
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800943 whitebalance_values = create_values_str(
944 whitebalance, sizeof(whitebalance) / sizeof(str_map));
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -0800945
946 //filter preview sizes
947 filterPreviewSizes();
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800948 preview_size_values = create_sizes_str(
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -0800949 supportedPreviewSizes, previewSizeCount);
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800950 //filter picture sizes
951 filterPictureSizes();
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800952 picture_size_values = create_sizes_str(
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800953 picture_sizes_ptr, supportedPictureSizesCount);
954
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800955 flash_values = create_values_str(
956 flash, sizeof(flash) / sizeof(str_map));
Srinivasan Kannan71229622009-12-04 12:05:58 -0800957 if(sensorType->hasAutoFocusSupport){
958 focus_mode_values = create_values_str(
959 focus_modes, sizeof(focus_modes) / sizeof(str_map));
960 }
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530961 iso_values = create_values_str(
962 iso,sizeof(iso)/sizeof(str_map));
963 lensshade_values = create_values_str(
964 lensshade,sizeof(lensshade)/sizeof(str_map));
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800965 picture_format_values = create_values_str(
966 picture_formats, sizeof(picture_formats)/sizeof(str_map));
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800967 parameter_string_initialized = true;
968 }
969
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -0800970 mParameters.setPreviewSize(DEFAULT_PREVIEW_WIDTH, DEFAULT_PREVIEW_HEIGHT);
971 mDimension.display_width = DEFAULT_PREVIEW_WIDTH;
972 mDimension.display_height = DEFAULT_PREVIEW_HEIGHT;
973
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800974 mParameters.setPreviewFrameRate(15);
975 mParameters.setPreviewFormat("yuv420sp"); // informative
976
977 mParameters.setPictureSize(DEFAULT_PICTURE_WIDTH, DEFAULT_PICTURE_HEIGHT);
978 mParameters.setPictureFormat("jpeg"); // informative
979
Mohan Kandra785619a2010-02-01 21:52:42 -0800980 mParameters.set(CameraParameters::KEY_JPEG_QUALITY, "85"); // max quality
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800981 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH,
982 THUMBNAIL_WIDTH_STR); // informative
983 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT,
984 THUMBNAIL_HEIGHT_STR); // informative
Srinivasan Kannan80d878f2009-12-18 15:06:02 -0800985 mDimension.ui_thumbnail_width =
986 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].width;
987 mDimension.ui_thumbnail_height =
988 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800989 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, "90");
990
991 mParameters.set(CameraParameters::KEY_ANTIBANDING,
Mohan Kandra785619a2010-02-01 21:52:42 -0800992 CameraParameters::ANTIBANDING_OFF);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800993 mParameters.set(CameraParameters::KEY_EFFECT,
994 CameraParameters::EFFECT_NONE);
Apurva Rajguru55562b02009-12-03 12:25:35 -0800995 mParameters.set(CameraParameters::KEY_AUTO_EXPOSURE,
996 CameraParameters::AUTO_EXPOSURE_FRAME_AVG);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800997 mParameters.set(CameraParameters::KEY_WHITE_BALANCE,
998 CameraParameters::WHITE_BALANCE_AUTO);
999 mParameters.set(CameraParameters::KEY_FOCUS_MODE,
1000 CameraParameters::FOCUS_MODE_AUTO);
Priya Komarlingam044c7b52010-01-22 18:21:23 -08001001 mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS,
1002 "yuv420sp");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001003
1004 mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES,
1005 preview_size_values.string());
1006 mParameters.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES,
1007 picture_size_values.string());
1008 mParameters.set(CameraParameters::KEY_SUPPORTED_ANTIBANDING,
1009 antibanding_values);
1010 mParameters.set(CameraParameters::KEY_SUPPORTED_EFFECTS, effect_values);
Apurva Rajguru55562b02009-12-03 12:25:35 -08001011 mParameters.set(CameraParameters::KEY_SUPPORTED_AUTO_EXPOSURE, autoexposure_values);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001012 mParameters.set(CameraParameters::KEY_SUPPORTED_WHITE_BALANCE,
1013 whitebalance_values);
1014 mParameters.set(CameraParameters::KEY_SUPPORTED_FOCUS_MODES,
1015 focus_mode_values);
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001016 mParameters.set(CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS,
1017 picture_format_values);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001018
1019 if (mSensorInfo.flash_enabled) {
1020 mParameters.set(CameraParameters::KEY_FLASH_MODE,
1021 CameraParameters::FLASH_MODE_OFF);
1022 mParameters.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES,
1023 flash_values);
1024 }
1025
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08001026 mParameters.set(CameraParameters::KEY_MAX_SHARPNESS,
1027 CAMERA_MAX_SHARPNESS);
1028 mParameters.set(CameraParameters::KEY_MAX_CONTRAST,
1029 CAMERA_MAX_CONTRAST);
1030 mParameters.set(CameraParameters::KEY_MAX_SATURATION,
1031 CAMERA_MAX_SATURATION);
1032
Apurva Rajguru07185952010-01-22 15:40:07 -08001033 mParameters.set("luma-adaptation", "3");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001034 mParameters.set("zoom-supported", "true");
1035 mParameters.set("max-zoom", MAX_ZOOM_LEVEL);
1036 mParameters.set("zoom", 0);
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001037 mParameters.set(CameraParameters::KEY_PICTURE_FORMAT,
1038 CameraParameters::PIXEL_FORMAT_JPEG);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001039
Kiran Kumar H N595970b2010-01-12 10:41:09 -08001040 mParameters.set(CameraParameters::KEY_SHARPNESS,
1041 CAMERA_DEF_SHARPNESS);
1042 mParameters.set(CameraParameters::KEY_CONTRAST,
1043 CAMERA_DEF_CONTRAST);
1044 mParameters.set(CameraParameters::KEY_SATURATION,
1045 CAMERA_DEF_SATURATION);
1046
Nishant Panditc8c1ee72009-12-03 16:24:02 +05301047 mParameters.set(CameraParameters::KEY_ISO_MODE,
1048 CameraParameters::ISO_AUTO);
1049 mParameters.set(CameraParameters::KEY_LENSSHADE,
1050 CameraParameters::LENSSHADE_ENABLE);
1051 mParameters.set(CameraParameters::KEY_SUPPORTED_ISO_MODES,
1052 iso_values);
1053 mParameters.set(CameraParameters::KEY_SUPPORTED_LENSSHADE_MODES,
1054 lensshade_values);
1055
Priyanka Kharat67cfe532010-03-29 17:28:22 -07001056 if (setParameters(mParameters) != NO_ERROR) {
1057 LOGE("Failed to set default parameters?!");
1058 }
1059
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08001060 mUseOverlay = useOverlay();
1061
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001062 /* Initialize the camframe_timeout_flag*/
1063 Mutex::Autolock l(&mCamframeTimeoutLock);
1064 camframe_timeout_flag = FALSE;
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08001065 mPostViewHeap = NULL;
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001066
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001067 LOGV("initDefaultParameters X");
1068}
1069
Srinivasan Kannan71229622009-12-04 12:05:58 -08001070void QualcommCameraHardware::findSensorType(){
1071 mDimension.picture_width = DEFAULT_PICTURE_WIDTH;
1072 mDimension.picture_height = DEFAULT_PICTURE_HEIGHT;
1073 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
1074 sizeof(cam_ctrl_dimension_t), &mDimension);
1075 if (ret) {
1076 unsigned int i;
1077 for (i = 0; i < sizeof(sensorTypes) / sizeof(SensorType); i++) {
1078 if (sensorTypes[i].rawPictureHeight
1079 == mDimension.raw_picture_height) {
1080 sensorType = sensorTypes + i;
1081 return;
1082 }
1083 }
1084 }
1085 //default to 5 mp
1086 sensorType = sensorTypes;
1087 return;
1088}
1089
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001090#define ROUND_TO_PAGE(x) (((x)+0xfff)&~0xfff)
1091
1092bool QualcommCameraHardware::startCamera()
1093{
1094 LOGV("startCamera E");
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08001095 if( mCurrentTarget == TARGET_MAX ) {
1096 LOGE(" Unable to determine the target type. Camera will not work ");
1097 return false;
1098 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001099#if DLOPEN_LIBMMCAMERA
1100 libmmcamera = ::dlopen("liboemcamera.so", RTLD_NOW);
1101 LOGV("loading liboemcamera at %p", libmmcamera);
1102 if (!libmmcamera) {
1103 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
1104 return false;
1105 }
1106
1107 *(void **)&LINK_cam_frame =
1108 ::dlsym(libmmcamera, "cam_frame");
1109 *(void **)&LINK_camframe_terminate =
1110 ::dlsym(libmmcamera, "camframe_terminate");
1111
1112 *(void **)&LINK_jpeg_encoder_init =
1113 ::dlsym(libmmcamera, "jpeg_encoder_init");
1114
1115 *(void **)&LINK_jpeg_encoder_encode =
1116 ::dlsym(libmmcamera, "jpeg_encoder_encode");
1117
1118 *(void **)&LINK_jpeg_encoder_join =
1119 ::dlsym(libmmcamera, "jpeg_encoder_join");
1120
1121 *(void **)&LINK_mmcamera_camframe_callback =
1122 ::dlsym(libmmcamera, "mmcamera_camframe_callback");
1123
1124 *LINK_mmcamera_camframe_callback = receive_camframe_callback;
1125
1126 *(void **)&LINK_mmcamera_jpegfragment_callback =
1127 ::dlsym(libmmcamera, "mmcamera_jpegfragment_callback");
1128
1129 *LINK_mmcamera_jpegfragment_callback = receive_jpeg_fragment_callback;
1130
1131 *(void **)&LINK_mmcamera_jpeg_callback =
1132 ::dlsym(libmmcamera, "mmcamera_jpeg_callback");
1133
1134 *LINK_mmcamera_jpeg_callback = receive_jpeg_callback;
1135
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001136 *(void **)&LINK_camframe_timeout_callback =
1137 ::dlsym(libmmcamera, "camframe_timeout_callback");
1138
1139 *LINK_camframe_timeout_callback = receive_camframetimeout_callback;
1140
Sravankb4f5f1c2010-01-21 11:06:17 +05301141 // 720 p new recording functions
1142 *(void **)&LINK_cam_frame_flush_free_video = ::dlsym(libmmcamera, "cam_frame_flush_free_video");
1143
1144 *(void **)&LINK_camframe_free_video = ::dlsym(libmmcamera, "cam_frame_add_free_video");
1145
1146 *(void **)&LINK_camframe_video_callback = ::dlsym(libmmcamera, "mmcamera_camframe_videocallback");
1147 *LINK_camframe_video_callback = receive_camframe_video_callback;
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08001148
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001149 *(void **)&LINK_mmcamera_shutter_callback =
1150 ::dlsym(libmmcamera, "mmcamera_shutter_callback");
1151
1152 *LINK_mmcamera_shutter_callback = receive_shutter_callback;
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08001153
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001154 *(void**)&LINK_jpeg_encoder_setMainImageQuality =
1155 ::dlsym(libmmcamera, "jpeg_encoder_setMainImageQuality");
Kiran Kumar H N8861f302010-01-05 12:01:41 -08001156
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001157 *(void**)&LINK_jpeg_encoder_setThumbnailQuality =
1158 ::dlsym(libmmcamera, "jpeg_encoder_setThumbnailQuality");
1159
1160 *(void**)&LINK_jpeg_encoder_setRotation =
1161 ::dlsym(libmmcamera, "jpeg_encoder_setRotation");
1162
Kiran Kumar H N8861f302010-01-05 12:01:41 -08001163/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001164 *(void**)&LINK_jpeg_encoder_setLocation =
1165 ::dlsym(libmmcamera, "jpeg_encoder_setLocation");
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001166*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001167 *(void **)&LINK_cam_conf =
1168 ::dlsym(libmmcamera, "cam_conf");
1169
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001170/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001171 *(void **)&LINK_default_sensor_get_snapshot_sizes =
1172 ::dlsym(libmmcamera, "default_sensor_get_snapshot_sizes");
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001173*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001174 *(void **)&LINK_launch_cam_conf_thread =
1175 ::dlsym(libmmcamera, "launch_cam_conf_thread");
1176
1177 *(void **)&LINK_release_cam_conf_thread =
1178 ::dlsym(libmmcamera, "release_cam_conf_thread");
1179
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001180/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001181 *(void **)&LINK_zoom_crop_upscale =
1182 ::dlsym(libmmcamera, "zoom_crop_upscale");
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001183*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001184
1185#else
1186 mmcamera_camframe_callback = receive_camframe_callback;
1187 mmcamera_jpegfragment_callback = receive_jpeg_fragment_callback;
1188 mmcamera_jpeg_callback = receive_jpeg_callback;
1189 mmcamera_shutter_callback = receive_shutter_callback;
1190#endif // DLOPEN_LIBMMCAMERA
1191
1192 /* The control thread is in libcamera itself. */
Brian Steuer07704892009-12-18 18:07:33 -08001193 if (pthread_join(w_thread, NULL) != 0) {
1194 LOGE("Camera open thread exit failed");
1195 return false;
1196 }
1197 mCameraControlFd = camerafd;
1198
Kiran Kumar H N585bc362010-01-19 13:04:44 -08001199 if (mCameraControlFd < 0) {
1200 LOGE("startCamera X: %s open failed: %s!",
1201 MSM_CAMERA_CONTROL,
1202 strerror(errno));
1203 return false;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001204 }
1205
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08001206 if( mCurrentTarget != TARGET_MSM7630 ){
Mohan Kandra284966d2010-01-05 13:39:15 -08001207 fb_fd = open("/dev/graphics/fb0", O_RDWR);
1208 if (fb_fd < 0) {
1209 LOGE("startCamera: fb0 open failed: %s!", strerror(errno));
1210 return FALSE;
1211 }
1212 }
1213
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001214 /* This will block until the control thread is launched. After that, sensor
1215 * information becomes available.
1216 */
1217
1218 if (LINK_launch_cam_conf_thread()) {
1219 LOGE("failed to launch the camera config thread");
1220 return false;
1221 }
1222
1223 memset(&mSensorInfo, 0, sizeof(mSensorInfo));
1224 if (ioctl(mCameraControlFd,
1225 MSM_CAM_IOCTL_GET_SENSOR_INFO,
1226 &mSensorInfo) < 0)
1227 LOGW("%s: cannot retrieve sensor info!", __FUNCTION__);
1228 else
1229 LOGI("%s: camsensor name %s, flash %d", __FUNCTION__,
1230 mSensorInfo.name, mSensorInfo.flash_enabled);
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001231/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001232 picture_sizes = LINK_default_sensor_get_snapshot_sizes(&PICTURE_SIZE_COUNT);
1233 if (!picture_sizes || !PICTURE_SIZE_COUNT) {
1234 LOGE("startCamera X: could not get snapshot sizes");
1235 return false;
1236 }
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001237*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001238 LOGV("startCamera X");
1239 return true;
1240}
1241
1242status_t QualcommCameraHardware::dump(int fd,
1243 const Vector<String16>& args) const
1244{
1245 const size_t SIZE = 256;
1246 char buffer[SIZE];
1247 String8 result;
1248
1249 // Dump internal primitives.
1250 result.append("QualcommCameraHardware::dump");
1251 snprintf(buffer, 255, "mMsgEnabled (%d)\n", mMsgEnabled);
1252 result.append(buffer);
1253 int width, height;
1254 mParameters.getPreviewSize(&width, &height);
1255 snprintf(buffer, 255, "preview width(%d) x height (%d)\n", width, height);
1256 result.append(buffer);
1257 mParameters.getPictureSize(&width, &height);
1258 snprintf(buffer, 255, "raw width(%d) x height (%d)\n", width, height);
1259 result.append(buffer);
1260 snprintf(buffer, 255,
1261 "preview frame size(%d), raw size (%d), jpeg size (%d) "
1262 "and jpeg max size (%d)\n", mPreviewFrameSize, mRawSize,
1263 mJpegSize, mJpegMaxSize);
1264 result.append(buffer);
1265 write(fd, result.string(), result.size());
1266
1267 // Dump internal objects.
Mohan Kandrad9efed92010-01-15 19:08:39 -08001268 if (mPreviewHeap != 0) {
1269 mPreviewHeap->dump(fd, args);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001270 }
1271 if (mRawHeap != 0) {
1272 mRawHeap->dump(fd, args);
1273 }
1274 if (mJpegHeap != 0) {
1275 mJpegHeap->dump(fd, args);
1276 }
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001277 if(mRawSnapshotAshmemHeap != 0 ){
1278 mRawSnapshotAshmemHeap->dump(fd, args);
1279 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001280 mParameters.dump(fd, args);
1281 return NO_ERROR;
1282}
1283
Mohan Kandra284966d2010-01-05 13:39:15 -08001284static bool native_get_maxzoom(int camfd, void *pZm)
1285{
1286 LOGV("native_get_maxzoom E");
1287
1288 struct msm_ctrl_cmd ctrlCmd;
1289 int32_t *pZoom = (int32_t *)pZm;
1290
1291 ctrlCmd.type = CAMERA_GET_PARM_MAXZOOM;
1292 ctrlCmd.timeout_ms = 5000;
1293 ctrlCmd.length = sizeof(int32_t);
1294 ctrlCmd.value = pZoom;
1295 ctrlCmd.resp_fd = camfd;
1296
1297 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1298 LOGE("native_get_maxzoom: ioctl fd %d error %s",
1299 camfd,
1300 strerror(errno));
1301 return false;
1302 }
Brian Steuerb62adbd2010-02-02 14:47:08 -08001303 LOGD("ctrlCmd.value = %d", *(int32_t *)ctrlCmd.value);
Mohan Kandra284966d2010-01-05 13:39:15 -08001304 memcpy(pZoom, (int32_t *)ctrlCmd.value, sizeof(int32_t));
1305
1306 LOGV("native_get_maxzoom X");
1307 return true;
1308}
1309
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001310static bool native_set_afmode(int camfd, isp3a_af_mode_t af_type)
1311{
1312 int rc;
1313 struct msm_ctrl_cmd ctrlCmd;
1314
1315 ctrlCmd.timeout_ms = 5000;
1316 ctrlCmd.type = CAMERA_SET_PARM_AUTO_FOCUS;
1317 ctrlCmd.length = sizeof(af_type);
1318 ctrlCmd.value = &af_type;
1319 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1320
1321 if ((rc = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0)
1322 LOGE("native_set_afmode: ioctl fd %d error %s\n",
1323 camfd,
1324 strerror(errno));
1325
1326 LOGV("native_set_afmode: ctrlCmd.status == %d\n", ctrlCmd.status);
1327 return rc >= 0 && ctrlCmd.status == CAMERA_EXIT_CB_DONE;
1328}
1329
1330static bool native_cancel_afmode(int camfd, int af_fd)
1331{
1332 int rc;
1333 struct msm_ctrl_cmd ctrlCmd;
1334
1335 ctrlCmd.timeout_ms = 0;
1336 ctrlCmd.type = CAMERA_AUTO_FOCUS_CANCEL;
1337 ctrlCmd.length = 0;
1338 ctrlCmd.value = NULL;
1339 ctrlCmd.resp_fd = -1; // there's no response fd
1340
1341 if ((rc = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND_2, &ctrlCmd)) < 0)
1342 {
1343 LOGE("native_cancel_afmode: ioctl fd %d error %s\n",
1344 camfd,
1345 strerror(errno));
1346 return false;
1347 }
1348
1349 return true;
1350}
1351
1352static bool native_start_preview(int camfd)
1353{
1354 struct msm_ctrl_cmd ctrlCmd;
1355
1356 ctrlCmd.timeout_ms = 5000;
1357 ctrlCmd.type = CAMERA_START_PREVIEW;
1358 ctrlCmd.length = 0;
1359 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1360
1361 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1362 LOGE("native_start_preview: MSM_CAM_IOCTL_CTRL_COMMAND fd %d error %s",
1363 camfd,
1364 strerror(errno));
1365 return false;
1366 }
1367
1368 return true;
1369}
1370
1371static bool native_get_picture (int camfd, common_crop_t *crop)
1372{
1373 struct msm_ctrl_cmd ctrlCmd;
1374
1375 ctrlCmd.timeout_ms = 5000;
1376 ctrlCmd.length = sizeof(common_crop_t);
1377 ctrlCmd.value = crop;
1378
1379 if(ioctl(camfd, MSM_CAM_IOCTL_GET_PICTURE, &ctrlCmd) < 0) {
1380 LOGE("native_get_picture: MSM_CAM_IOCTL_GET_PICTURE fd %d error %s",
1381 camfd,
1382 strerror(errno));
1383 return false;
1384 }
1385
1386 LOGV("crop: in1_w %d", crop->in1_w);
1387 LOGV("crop: in1_h %d", crop->in1_h);
1388 LOGV("crop: out1_w %d", crop->out1_w);
1389 LOGV("crop: out1_h %d", crop->out1_h);
1390
1391 LOGV("crop: in2_w %d", crop->in2_w);
1392 LOGV("crop: in2_h %d", crop->in2_h);
1393 LOGV("crop: out2_w %d", crop->out2_w);
1394 LOGV("crop: out2_h %d", crop->out2_h);
1395
1396 LOGV("crop: update %d", crop->update_flag);
1397
1398 return true;
1399}
1400
1401static bool native_stop_preview(int camfd)
1402{
1403 struct msm_ctrl_cmd ctrlCmd;
1404 ctrlCmd.timeout_ms = 5000;
1405 ctrlCmd.type = CAMERA_STOP_PREVIEW;
1406 ctrlCmd.length = 0;
1407 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1408
1409 if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1410 LOGE("native_stop_preview: ioctl fd %d error %s",
1411 camfd,
1412 strerror(errno));
1413 return false;
1414 }
1415
1416 return true;
1417}
1418
1419static bool native_prepare_snapshot(int camfd)
1420{
1421 int ioctlRetVal = true;
1422 struct msm_ctrl_cmd ctrlCmd;
1423
1424 ctrlCmd.timeout_ms = 1000;
1425 ctrlCmd.type = CAMERA_PREPARE_SNAPSHOT;
1426 ctrlCmd.length = 0;
1427 ctrlCmd.value = NULL;
1428 ctrlCmd.resp_fd = camfd;
1429
1430 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1431 LOGE("native_prepare_snapshot: ioctl fd %d error %s",
1432 camfd,
1433 strerror(errno));
1434 return false;
1435 }
1436 return true;
1437}
1438
1439static bool native_start_snapshot(int camfd)
1440{
1441 struct msm_ctrl_cmd ctrlCmd;
1442
1443 ctrlCmd.timeout_ms = 5000;
1444 ctrlCmd.type = CAMERA_START_SNAPSHOT;
1445 ctrlCmd.length = 0;
1446 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1447
1448 if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1449 LOGE("native_start_snapshot: ioctl fd %d error %s",
1450 camfd,
1451 strerror(errno));
1452 return false;
1453 }
1454
1455 return true;
1456}
1457
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001458static bool native_start_raw_snapshot(int camfd)
1459{
1460 int ret;
1461 struct msm_ctrl_cmd ctrlCmd;
1462
1463 ctrlCmd.timeout_ms = 1000;
1464 ctrlCmd.type = CAMERA_START_RAW_SNAPSHOT;
1465 ctrlCmd.length = 0;
1466 ctrlCmd.value = NULL;
1467 ctrlCmd.resp_fd = camfd;
1468
1469 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1470 LOGE("native_start_raw_snapshot: ioctl failed. ioctl return value "\
1471 "is %d \n", ret);
1472 return false;
1473 }
1474 return true;
1475}
1476
1477
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001478static bool native_stop_snapshot (int camfd)
1479{
1480 struct msm_ctrl_cmd ctrlCmd;
1481
1482 ctrlCmd.timeout_ms = 0;
1483 ctrlCmd.type = CAMERA_STOP_SNAPSHOT;
1484 ctrlCmd.length = 0;
1485 ctrlCmd.resp_fd = -1;
1486
1487 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND_2, &ctrlCmd) < 0) {
1488 LOGE("native_stop_snapshot: ioctl fd %d error %s",
1489 camfd,
1490 strerror(errno));
1491 return false;
1492 }
1493
1494 return true;
1495}
Sravankb4f5f1c2010-01-21 11:06:17 +05301496/*===========================================================================
1497 * FUNCTION - native_start_recording -
1498 *
1499 * DESCRIPTION:
1500 *==========================================================================*/
1501static bool native_start_recording(int camfd)
1502{
1503 int ret;
1504 struct msm_ctrl_cmd ctrlCmd;
1505
1506 ctrlCmd.timeout_ms = 1000;
1507 ctrlCmd.type = CAMERA_START_RECORDING;
1508 ctrlCmd.length = 0;
1509 ctrlCmd.value = NULL;
1510 ctrlCmd.resp_fd = camfd;
1511
1512 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1513 LOGE("native_start_recording: ioctl failed. ioctl return value "\
1514 "is %d \n", ret);
1515 return false;
1516 }
Mohan Kandraf1ebf982010-02-02 15:25:43 -08001517 LOGV("native_start_recording: ioctl good. ioctl return value is %d \n",ret);
Sravankb4f5f1c2010-01-21 11:06:17 +05301518
1519 /* TODO: Check status of postprocessing if there is any,
1520 * PP status should be in ctrlCmd */
1521
1522 return true;
1523}
1524
1525/*===========================================================================
1526 * FUNCTION - native_stop_recording -
1527 *
1528 * DESCRIPTION:
1529 *==========================================================================*/
1530static bool native_stop_recording(int camfd)
1531{
1532 int ret;
1533 struct msm_ctrl_cmd ctrlCmd;
Kiran Kumar H Nb49af212010-02-17 15:12:17 -08001534 LOGV("in native_stop_recording ");
Sravankb4f5f1c2010-01-21 11:06:17 +05301535 ctrlCmd.timeout_ms = 1000;
1536 ctrlCmd.type = CAMERA_STOP_RECORDING;
1537 ctrlCmd.length = 0;
1538 ctrlCmd.value = NULL;
1539 ctrlCmd.resp_fd = camfd;
1540
1541 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1542 LOGE("native_stop_video: ioctl failed. ioctl return value is %d \n",
1543 ret);
1544 return false;
1545 }
1546 LOGV("in native_stop_recording returned %d", ret);
1547 return true;
1548}
1549/*===========================================================================
1550 * FUNCTION - native_start_video -
1551 *
1552 * DESCRIPTION:
1553 *==========================================================================*/
1554static bool native_start_video(int camfd)
1555{
1556 int ret;
1557 struct msm_ctrl_cmd ctrlCmd;
1558
1559 ctrlCmd.timeout_ms = 1000;
1560 ctrlCmd.type = CAMERA_START_VIDEO;
1561 ctrlCmd.length = 0;
1562 ctrlCmd.value = NULL;
1563 ctrlCmd.resp_fd = camfd;
1564
1565 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1566 LOGE("native_start_video: ioctl failed. ioctl return value is %d \n",
1567 ret);
1568 return false;
1569 }
1570
1571 /* TODO: Check status of postprocessing if there is any,
1572 * PP status should be in ctrlCmd */
1573
1574 return true;
1575}
1576
1577/*===========================================================================
1578 * FUNCTION - native_stop_video -
1579 *
1580 * DESCRIPTION:
1581 *==========================================================================*/
1582static bool native_stop_video(int camfd)
1583{
1584 int ret;
1585 struct msm_ctrl_cmd ctrlCmd;
1586
1587 ctrlCmd.timeout_ms = 1000;
1588 ctrlCmd.type = CAMERA_STOP_VIDEO;
1589 ctrlCmd.length = 0;
1590 ctrlCmd.value = NULL;
1591 ctrlCmd.resp_fd = camfd;
1592
1593 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1594 LOGE("native_stop_video: ioctl failed. ioctl return value is %d \n",
1595 ret);
1596 return false;
1597 }
1598
1599 return true;
1600}
1601/*==========================================================================*/
1602
1603static cam_frame_start_parms frame_parms;
1604static int recordingState = 0;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001605
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001606static rat_t latitude[3];
1607static rat_t longitude[3];
1608static char lonref[2];
1609static char latref[2];
1610static char dateTime[20];
1611static rat_t altitude;
1612
1613static void addExifTag(exif_tag_id_t tagid, exif_tag_type_t type,
1614 uint32_t count, uint8_t copy, void *data) {
1615
1616 if(exif_table_numEntries == MAX_EXIF_TABLE_ENTRIES) {
1617 LOGE("Number of entries exceeded limit");
1618 return;
1619 }
1620
1621 int index = exif_table_numEntries;
1622 exif_data[index].tag_id = tagid;
1623 exif_data[index].tag_entry.type = type;
1624 exif_data[index].tag_entry.count = count;
1625 exif_data[index].tag_entry.copy = copy;
1626 if((type == EXIF_RATIONAL) && (count > 1))
1627 exif_data[index].tag_entry.data._rats = (rat_t *)data;
1628 if((type == EXIF_RATIONAL) && (count == 1))
1629 exif_data[index].tag_entry.data._rat = *(rat_t *)data;
1630 else if(type == EXIF_ASCII)
1631 exif_data[index].tag_entry.data._ascii = (char *)data;
1632 else if(type == EXIF_BYTE)
1633 exif_data[index].tag_entry.data._byte = *(uint8_t *)data;
1634
1635 // Increase number of entries
1636 exif_table_numEntries++;
1637}
1638
1639static void parseLatLong(const char *latlonString, int *pDegrees,
1640 int *pMinutes, int *pSeconds ) {
1641
1642 double value = atof(latlonString);
1643 value = fabs(value);
1644 int degrees = (int) value;
1645
1646 double remainder = value - degrees;
1647 int minutes = (int) (remainder * 60);
1648 int seconds = (int) (((remainder * 60) - minutes) * 60 * 1000);
1649
1650 *pDegrees = degrees;
1651 *pMinutes = minutes;
1652 *pSeconds = seconds;
1653}
1654
1655static void setLatLon(exif_tag_id_t tag, const char *latlonString) {
1656
1657 int degrees, minutes, seconds;
1658
1659 parseLatLong(latlonString, &degrees, &minutes, &seconds);
1660
1661 rat_t value[3] = { {degrees, 1},
1662 {minutes, 1},
1663 {seconds, 1000} };
1664
1665 if(tag == EXIFTAGID_GPS_LATITUDE) {
1666 memcpy(latitude, value, sizeof(latitude));
1667 addExifTag(EXIFTAGID_GPS_LATITUDE, EXIF_RATIONAL, 3,
1668 1, (void *)latitude);
1669 } else {
1670 memcpy(longitude, value, sizeof(longitude));
1671 addExifTag(EXIFTAGID_GPS_LONGITUDE, EXIF_RATIONAL, 3,
1672 1, (void *)longitude);
1673 }
1674}
1675
1676void QualcommCameraHardware::setGpsParameters() {
1677 const char *str = NULL;
1678
1679 //Set Latitude
1680 str = mParameters.get(CameraParameters::KEY_GPS_LATITUDE);
1681 if(str != NULL) {
1682 setLatLon(EXIFTAGID_GPS_LATITUDE, str);
1683 //set Latitude Ref
1684 str = NULL;
1685 str = mParameters.get(CameraParameters::KEY_GPS_LATITUDE_REF);
1686 if(str != NULL) {
1687 strncpy(latref, str, 1);
1688 latref[1] = '\0';
1689 addExifTag(EXIFTAGID_GPS_LATITUDE_REF, EXIF_ASCII, 2,
1690 1, (void *)latref);
1691 }
1692 }
1693
1694 //set Longitude
1695 str = NULL;
1696 str = mParameters.get(CameraParameters::KEY_GPS_LONGITUDE);
1697 if(str != NULL) {
1698 setLatLon(EXIFTAGID_GPS_LONGITUDE, str);
1699 //set Longitude Ref
1700 str = NULL;
1701 str = mParameters.get(CameraParameters::KEY_GPS_LONGITUDE_REF);
1702 if(str != NULL) {
1703 strncpy(lonref, str, 1);
1704 lonref[1] = '\0';
1705 addExifTag(EXIFTAGID_GPS_LONGITUDE_REF, EXIF_ASCII, 2,
1706 1, (void *)lonref);
1707 }
1708 }
1709
1710 //set Altitude
1711 str = NULL;
1712 str = mParameters.get(CameraParameters::KEY_GPS_ALTITUDE);
1713 if(str != NULL) {
1714 int value = atoi(str);
1715 rat_t alt_value = {value, 1000};
1716 memcpy(&altitude, &alt_value, sizeof(altitude));
1717 addExifTag(EXIFTAGID_GPS_ALTITUDE, EXIF_RATIONAL, 1,
1718 1, (void *)&altitude);
1719 //set AltitudeRef
1720 int ref = mParameters.getInt(CameraParameters::KEY_GPS_ALTITUDE_REF);
1721 if( !(ref < 0 || ref > 1) )
1722 addExifTag(EXIFTAGID_GPS_ALTITUDE_REF, EXIF_BYTE, 1,
1723 1, (void *)&ref);
1724 }
1725
1726
1727}
1728
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001729bool QualcommCameraHardware::native_jpeg_encode(void)
1730{
1731 int jpeg_quality = mParameters.getInt("jpeg-quality");
1732 if (jpeg_quality >= 0) {
1733 LOGV("native_jpeg_encode, current jpeg main img quality =%d",
1734 jpeg_quality);
1735 if(!LINK_jpeg_encoder_setMainImageQuality(jpeg_quality)) {
1736 LOGE("native_jpeg_encode set jpeg-quality failed");
1737 return false;
1738 }
1739 }
1740
1741 int thumbnail_quality = mParameters.getInt("jpeg-thumbnail-quality");
1742 if (thumbnail_quality >= 0) {
1743 LOGV("native_jpeg_encode, current jpeg thumbnail quality =%d",
1744 thumbnail_quality);
1745 if(!LINK_jpeg_encoder_setThumbnailQuality(thumbnail_quality)) {
1746 LOGE("native_jpeg_encode set thumbnail-quality failed");
1747 return false;
1748 }
1749 }
1750
1751 int rotation = mParameters.getInt("rotation");
1752 if (rotation >= 0) {
1753 LOGV("native_jpeg_encode, rotation = %d", rotation);
1754 if(!LINK_jpeg_encoder_setRotation(rotation)) {
1755 LOGE("native_jpeg_encode set rotation failed");
1756 return false;
1757 }
1758 }
1759
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001760// jpeg_set_location();
1761 if(mParameters.getInt(CameraParameters::KEY_GPS_STATUS) == 1) {
1762 setGpsParameters();
1763 }
1764 //set TimeStamp
1765 const char *str = mParameters.get(CameraParameters::KEY_EXIF_DATETIME);
1766 if(str != NULL) {
1767 strncpy(dateTime, str, 19);
1768 dateTime[19] = '\0';
1769 addExifTag(EXIFTAGID_EXIF_DATE_TIME_ORIGINAL, EXIF_ASCII,
1770 20, 1, (void *)dateTime);
1771 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001772
1773 if (!LINK_jpeg_encoder_encode(&mDimension,
1774 (uint8_t *)mThumbnailHeap->mHeap->base(),
1775 mThumbnailHeap->mHeap->getHeapID(),
1776 (uint8_t *)mRawHeap->mHeap->base(),
1777 mRawHeap->mHeap->getHeapID(),
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001778 &mCrop, exif_data, exif_table_numEntries)) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001779 LOGE("native_jpeg_encode: jpeg_encoder_encode failed.");
1780 return false;
1781 }
1782 return true;
1783}
1784
1785bool QualcommCameraHardware::native_set_parm(
1786 cam_ctrl_type type, uint16_t length, void *value)
1787{
1788 struct msm_ctrl_cmd ctrlCmd;
1789
1790 ctrlCmd.timeout_ms = 5000;
1791 ctrlCmd.type = (uint16_t)type;
1792 ctrlCmd.length = length;
1793 // FIXME: this will be put in by the kernel
1794 ctrlCmd.resp_fd = mCameraControlFd;
1795 ctrlCmd.value = value;
1796
1797 LOGV("%s: fd %d, type %d, length %d", __FUNCTION__,
1798 mCameraControlFd, type, length);
1799 if (ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0 ||
1800 ctrlCmd.status != CAM_CTRL_SUCCESS) {
1801 LOGE("%s: error (%s): fd %d, type %d, length %d, status %d",
1802 __FUNCTION__, strerror(errno),
1803 mCameraControlFd, type, length, ctrlCmd.status);
1804 return false;
1805 }
1806 return true;
1807}
1808
1809void QualcommCameraHardware::jpeg_set_location()
1810{
1811 bool encode_location = true;
1812 camera_position_type pt;
1813
1814#define PARSE_LOCATION(what,type,fmt,desc) do { \
1815 pt.what = 0; \
1816 const char *what##_str = mParameters.get("gps-"#what); \
1817 LOGV("GPS PARM %s --> [%s]", "gps-"#what, what##_str); \
1818 if (what##_str) { \
1819 type what = 0; \
1820 if (sscanf(what##_str, fmt, &what) == 1) \
1821 pt.what = what; \
1822 else { \
1823 LOGE("GPS " #what " %s could not" \
1824 " be parsed as a " #desc, what##_str); \
1825 encode_location = false; \
1826 } \
1827 } \
1828 else { \
1829 LOGV("GPS " #what " not specified: " \
1830 "defaulting to zero in EXIF header."); \
1831 encode_location = false; \
1832 } \
1833 } while(0)
1834
1835 PARSE_LOCATION(timestamp, long, "%ld", "long");
1836 if (!pt.timestamp) pt.timestamp = time(NULL);
1837 PARSE_LOCATION(altitude, short, "%hd", "short");
1838 PARSE_LOCATION(latitude, double, "%lf", "double float");
1839 PARSE_LOCATION(longitude, double, "%lf", "double float");
1840
1841#undef PARSE_LOCATION
1842
1843 if (encode_location) {
1844 LOGD("setting image location ALT %d LAT %lf LON %lf",
1845 pt.altitude, pt.latitude, pt.longitude);
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001846/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001847 if (!LINK_jpeg_encoder_setLocation(&pt)) {
1848 LOGE("jpeg_set_location: LINK_jpeg_encoder_setLocation failed.");
1849 }
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001850*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001851 }
1852 else LOGV("not setting image location");
1853}
1854
1855void QualcommCameraHardware::runFrameThread(void *data)
1856{
1857 LOGV("runFrameThread E");
1858
1859 int cnt;
1860
1861#if DLOPEN_LIBMMCAMERA
1862 // We need to maintain a reference to libqcamera.so for the duration of the
1863 // frame thread, because we do not know when it will exit relative to the
1864 // lifetime of this object. We do not want to dlclose() libqcamera while
1865 // LINK_cam_frame is still running.
1866 void *libhandle = ::dlopen("liboemcamera.so", RTLD_NOW);
1867 LOGV("FRAME: loading libqcamera at %p", libhandle);
1868 if (!libhandle) {
1869 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
1870 }
1871 if (libhandle)
1872#endif
1873 {
1874 LINK_cam_frame(data);
1875 }
1876
Mohan Kandrad9efed92010-01-15 19:08:39 -08001877 mPreviewHeap.clear();
Mohan Kandraf1ebf982010-02-02 15:25:43 -08001878 if(( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250))
Sravankb4f5f1c2010-01-21 11:06:17 +05301879 mRecordHeap.clear();
1880
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001881#if DLOPEN_LIBMMCAMERA
1882 if (libhandle) {
1883 ::dlclose(libhandle);
1884 LOGV("FRAME: dlclose(libqcamera)");
1885 }
1886#endif
1887
1888 mFrameThreadWaitLock.lock();
1889 mFrameThreadRunning = false;
1890 mFrameThreadWait.signal();
1891 mFrameThreadWaitLock.unlock();
1892
1893 LOGV("runFrameThread X");
1894}
1895
Sravankb4f5f1c2010-01-21 11:06:17 +05301896void QualcommCameraHardware::runVideoThread(void *data)
1897{
1898 LOGD("runVideoThread E");
1899 msm_frame* vframe = NULL;
1900
1901 while(true) {
1902 pthread_mutex_lock(&(g_busy_frame_queue.mut));
1903
Srinivasan Kannanfc3915c2010-03-18 10:54:40 -07001904 // Exit the thread , in case of stop recording..
1905 mVideoThreadWaitLock.lock();
1906 if(mVideoThreadExit){
1907 LOGV("Exiting video thread..");
1908 mVideoThreadWaitLock.unlock();
1909 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
1910 break;
1911 }
1912 mVideoThreadWaitLock.unlock();
1913
Kiran Kumar H Nb49af212010-02-17 15:12:17 -08001914 LOGV("in video_thread : wait for video frame ");
Sravankb4f5f1c2010-01-21 11:06:17 +05301915 // check if any frames are available in busyQ and give callback to
1916 // services/video encoder
1917 cam_frame_wait_video();
1918 LOGV("video_thread, wait over..");
1919
1920 // Exit the thread , in case of stop recording..
1921 mVideoThreadWaitLock.lock();
1922 if(mVideoThreadExit){
Kiran Kumar H Nb49af212010-02-17 15:12:17 -08001923 LOGV("Exiting video thread..");
Sravankb4f5f1c2010-01-21 11:06:17 +05301924 mVideoThreadWaitLock.unlock();
1925 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
1926 break;
1927 }
1928 mVideoThreadWaitLock.unlock();
1929
1930 // Get the video frame to be encoded
1931 vframe = cam_frame_get_video ();
Apurva Rajgurud9b0b302010-02-19 11:22:56 -08001932 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
Sravankb4f5f1c2010-01-21 11:06:17 +05301933 LOGV("in video_thread : got video frame ");
1934
Mohan Kandrabad0eaa2010-02-04 15:11:54 -08001935 if (UNLIKELY(mDebugFps)) {
1936 debugShowVideoFPS();
1937 }
1938
Sravankb4f5f1c2010-01-21 11:06:17 +05301939 if(vframe != NULL) {
1940 // Find the offset within the heap of the current buffer.
1941 LOGV("Got video frame : buffer %d base %d ", vframe->buffer, mRecordHeap->mHeap->base());
1942 ssize_t offset =
1943 (ssize_t)vframe->buffer - (ssize_t)mRecordHeap->mHeap->base();
1944 LOGV("offset = %d , alignsize = %d , offset later = %d", offset, mRecordHeap->mAlignedBufferSize, (offset / mRecordHeap->mAlignedBufferSize));
1945
1946 offset /= mRecordHeap->mAlignedBufferSize;
1947
1948 // dump frames for test purpose
1949#ifdef DUMP_VIDEO_FRAMES
1950 static int frameCnt = 0;
1951 if (frameCnt >= 11 && frameCnt <= 13 ) {
1952 char buf[128];
1953 sprintf(buf, "/data/%d_v.yuv", frameCnt);
1954 int file_fd = open(buf, O_RDWR | O_CREAT, 0777);
1955 LOGV("dumping video frame %d", frameCnt);
1956 if (file_fd < 0) {
1957 LOGE("cannot open file\n");
1958 }
1959 else
1960 {
1961 write(file_fd, (const void *)vframe->buffer,
1962 vframe->cbcr_off * 3 / 2);
1963 }
1964 close(file_fd);
1965 }
1966 frameCnt++;
1967#endif
1968 // Enable IF block to give frames to encoder , ELSE block for just simulation
1969#if 1
1970 LOGV("in video_thread : got video frame, before if check giving frame to services/encoder");
1971 mCallbackLock.lock();
1972 int msgEnabled = mMsgEnabled;
1973 data_callback_timestamp rcb = mDataCallbackTimestamp;
1974 void *rdata = mCallbackCookie;
1975 mCallbackLock.unlock();
1976
1977 if(rcb != NULL && (msgEnabled & CAMERA_MSG_VIDEO_FRAME) ) {
1978 LOGV("in video_thread : got video frame, giving frame to services/encoder");
1979 rcb(systemTime(), CAMERA_MSG_VIDEO_FRAME, mRecordHeap->mBuffers[offset], rdata);
Sravankb4f5f1c2010-01-21 11:06:17 +05301980 }
1981#else
1982 // 720p output2 : simulate release frame here:
1983 LOGE("in video_thread simulation , releasing the video frame");
1984 LINK_camframe_free_video(vframe);
1985#endif
1986
1987 } else LOGE("in video_thread get frame returned null");
1988
Sravankb4f5f1c2010-01-21 11:06:17 +05301989
1990 } // end of while loop
Mohan Kandra156d0ac2010-01-25 16:59:17 -08001991
1992 mVideoThreadWaitLock.lock();
1993 mVideoThreadRunning = false;
1994 mVideoThreadWait.signal();
1995 mVideoThreadWaitLock.unlock();
1996
Sravankb4f5f1c2010-01-21 11:06:17 +05301997 LOGV("runVideoThread X");
1998}
1999
2000void *video_thread(void *user)
2001{
2002 LOGV("video_thread E");
2003 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
2004 if (obj != 0) {
2005 obj->runVideoThread(user);
2006 }
2007 else LOGE("not starting video thread: the object went away!");
2008 LOGV("video_thread X");
2009 return NULL;
2010}
2011
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002012void *frame_thread(void *user)
2013{
2014 LOGD("frame_thread E");
2015 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
2016 if (obj != 0) {
2017 obj->runFrameThread(user);
2018 }
2019 else LOGW("not starting frame thread: the object went away!");
2020 LOGD("frame_thread X");
2021 return NULL;
2022}
2023
2024bool QualcommCameraHardware::initPreview()
2025{
2026 // See comments in deinitPreview() for why we have to wait for the frame
2027 // thread here, and why we can't use pthread_join().
Sravankb4f5f1c2010-01-21 11:06:17 +05302028 int videoWidth, videoHeight;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002029 mParameters.getPreviewSize(&previewWidth, &previewHeight);
Sravankb4f5f1c2010-01-21 11:06:17 +05302030
2031 videoWidth = previewWidth; // temporary , should be configurable later
2032 videoHeight = previewHeight;
2033 LOGV("initPreview E: preview size=%dx%d videosize = %d x %d", previewWidth, previewHeight, videoWidth, videoHeight );
2034
Mohan Kandraf1ebf982010-02-02 15:25:43 -08002035 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05302036 mDimension.video_width = videoWidth;
Kiran Kumar H N7ac84e32010-02-01 10:58:47 -08002037 mDimension.video_width = CEILING16(mDimension.video_width);
Sravankb4f5f1c2010-01-21 11:06:17 +05302038 mDimension.video_height = videoHeight;
Sravank64461e82010-02-25 15:10:09 +05302039 // for 720p , preview can be 768X432
2040 previewWidth = mDimension.display_width;
2041 previewHeight= mDimension.display_height;
Sravankb4f5f1c2010-01-21 11:06:17 +05302042 LOGV("initPreview : preview size=%dx%d videosize = %d x %d", previewWidth, previewHeight, mDimension.video_width, mDimension.video_height );
2043 }
2044
2045
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002046 mFrameThreadWaitLock.lock();
2047 while (mFrameThreadRunning) {
2048 LOGV("initPreview: waiting for old frame thread to complete.");
2049 mFrameThreadWait.wait(mFrameThreadWaitLock);
2050 LOGV("initPreview: old frame thread completed.");
2051 }
2052 mFrameThreadWaitLock.unlock();
2053
2054 mSnapshotThreadWaitLock.lock();
2055 while (mSnapshotThreadRunning) {
2056 LOGV("initPreview: waiting for old snapshot thread to complete.");
2057 mSnapshotThreadWait.wait(mSnapshotThreadWaitLock);
2058 LOGV("initPreview: old snapshot thread completed.");
2059 }
2060 mSnapshotThreadWaitLock.unlock();
2061
2062 int cnt = 0;
2063 mPreviewFrameSize = previewWidth * previewHeight * 3/2;
Mohan Kandrad9efed92010-01-15 19:08:39 -08002064 dstOffset = 0;
2065 mPreviewHeap = new PmemPool("/dev/pmem_adsp",
Mohan Kandra284966d2010-01-05 13:39:15 -08002066 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
2067 mCameraControlFd,
Sravankb4f5f1c2010-01-21 11:06:17 +05302068 MSM_PMEM_PREVIEW, //MSM_PMEM_OUTPUT2,
Mohan Kandra284966d2010-01-05 13:39:15 -08002069 mPreviewFrameSize,
Mohan Kandrad9efed92010-01-15 19:08:39 -08002070 kPreviewBufferCountActual,
Mohan Kandra284966d2010-01-05 13:39:15 -08002071 mPreviewFrameSize,
Mohan Kandrad9efed92010-01-15 19:08:39 -08002072 "preview");
Mohan Kandra284966d2010-01-05 13:39:15 -08002073
Mohan Kandrad9efed92010-01-15 19:08:39 -08002074 if (!mPreviewHeap->initialized()) {
2075 mPreviewHeap.clear();
Mohan Kandra284966d2010-01-05 13:39:15 -08002076 LOGE("initPreview X: could not initialize Camera preview heap.");
2077 return false;
2078 }
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002079 if( mCurrentTarget == TARGET_MSM7630 ) {
Srinivasan Kannan613301c2010-02-10 17:08:53 -08002080 mPostViewHeap.clear();
Kiran Kumar H N595970b2010-01-12 10:41:09 -08002081 if(mPostViewHeap == NULL) {
2082 LOGV(" Allocating Postview heap ");
2083 /* mPostViewHeap should be declared only for 7630 target */
2084 mPostViewHeap =
2085 new PmemPool("/dev/pmem_adsp",
2086 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
2087 mCameraControlFd,
Sravankb4f5f1c2010-01-21 11:06:17 +05302088 MSM_PMEM_PREVIEW, //MSM_PMEM_OUTPUT2,
Kiran Kumar H N595970b2010-01-12 10:41:09 -08002089 mPreviewFrameSize,
2090 1,
2091 mPreviewFrameSize,
2092 "postview");
Mohan Kandra284966d2010-01-05 13:39:15 -08002093
Kiran Kumar H N595970b2010-01-12 10:41:09 -08002094 if (!mPostViewHeap->initialized()) {
2095 mPostViewHeap.clear();
2096 LOGE(" Failed to initialize Postview Heap");
2097 return false;
2098 }
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002099 }
Mohan Kandraf1ebf982010-02-02 15:25:43 -08002100 }
2101
2102 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250) ) {
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002103
2104 // Allocate video buffers after allocating preview buffers.
Sravankb4f5f1c2010-01-21 11:06:17 +05302105 initRecord();
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002106 }
Sravankb4f5f1c2010-01-21 11:06:17 +05302107
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002108 // mDimension will be filled with thumbnail_width, thumbnail_height,
2109 // orig_picture_dx, and orig_picture_dy after this function call. We need to
2110 // keep it for jpeg_encoder_encode.
2111 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
2112 sizeof(cam_ctrl_dimension_t), &mDimension);
2113
2114 if (ret) {
2115 for (cnt = 0; cnt < kPreviewBufferCount; cnt++) {
Mohan Kandrad9efed92010-01-15 19:08:39 -08002116 frames[cnt].fd = mPreviewHeap->mHeap->getHeapID();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002117 frames[cnt].buffer =
Mohan Kandrad9efed92010-01-15 19:08:39 -08002118 (uint32_t)mPreviewHeap->mHeap->base() + mPreviewHeap->mAlignedBufferSize * cnt;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002119 frames[cnt].y_off = 0;
2120 frames[cnt].cbcr_off = previewWidth * previewHeight;
Sravankb4f5f1c2010-01-21 11:06:17 +05302121 frames[cnt].path = OUTPUT_TYPE_P; // MSM_FRAME_ENC;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002122 }
2123
2124 mFrameThreadWaitLock.lock();
2125 pthread_attr_t attr;
2126 pthread_attr_init(&attr);
2127 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
Sravankb4f5f1c2010-01-21 11:06:17 +05302128
2129 frame_parms.frame = frames[kPreviewBufferCount - 1];
Apurva Rajguruc73c1722010-04-15 17:39:11 -07002130
2131 if( mCurrentTarget == TARGET_MSM7630 || mCurrentTarget == TARGET_QSD8250 )
2132 frame_parms.video_frame = recordframes[kPreviewBufferCount - 1];
2133 else
2134 frame_parms.video_frame = frames[kPreviewBufferCount - 1];
Sravankb4f5f1c2010-01-21 11:06:17 +05302135
2136 LOGV ("initpreview before cam_frame thread carete , video frame buffer=%lu fd=%d y_off=%d cbcr_off=%d \n",
2137 (unsigned long)frame_parms.video_frame.buffer, frame_parms.video_frame.fd, frame_parms.video_frame.y_off,
2138 frame_parms.video_frame.cbcr_off);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002139 mFrameThreadRunning = !pthread_create(&mFrameThread,
2140 &attr,
2141 frame_thread,
Sravankb4f5f1c2010-01-21 11:06:17 +05302142 (void*)&(frame_parms));
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002143 ret = mFrameThreadRunning;
2144 mFrameThreadWaitLock.unlock();
2145 }
2146
2147 LOGV("initPreview X: %d", ret);
2148 return ret;
2149}
2150
2151void QualcommCameraHardware::deinitPreview(void)
2152{
2153 LOGI("deinitPreview E");
2154
2155 // When we call deinitPreview(), we signal to the frame thread that it
2156 // needs to exit, but we DO NOT WAIT for it to complete here. The problem
2157 // is that deinitPreview is sometimes called from the frame-thread's
2158 // callback, when the refcount on the Camera client reaches zero. If we
2159 // called pthread_join(), we would deadlock. So, we just call
2160 // LINK_camframe_terminate() in deinitPreview(), which makes sure that
2161 // after the preview callback returns, the camframe thread will exit. We
2162 // could call pthread_join() in initPreview() to join the last frame
2163 // thread. However, we would also have to call pthread_join() in release
2164 // as well, shortly before we destroy the object; this would cause the same
2165 // deadlock, since release(), like deinitPreview(), may also be called from
2166 // the frame-thread's callback. This we have to make the frame thread
2167 // detached, and use a separate mechanism to wait for it to complete.
2168
Kiran Kumar H N7ac84e32010-02-01 10:58:47 -08002169 LINK_camframe_terminate();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002170 LOGI("deinitPreview X");
2171}
2172
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002173bool QualcommCameraHardware::initRawSnapshot()
2174{
2175 LOGV("initRawSnapshot E");
2176
2177 //get width and height from Dimension Object
2178 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
2179 sizeof(cam_ctrl_dimension_t), &mDimension);
2180
2181 if(!ret){
2182 LOGE("initRawSnapshot X: failed to set dimension");
2183 return false;
2184 }
2185 int rawSnapshotSize = mDimension.raw_picture_height *
2186 mDimension.raw_picture_width;
2187
2188 LOGV("raw_snapshot_buffer_size = %d, raw_picture_height = %d, "\
2189 "raw_picture_width = %d",
2190 rawSnapshotSize, mDimension.raw_picture_height,
2191 mDimension.raw_picture_width);
2192
2193 if (mRawSnapShotPmemHeap != NULL) {
2194 LOGV("initRawSnapshot: clearing old mRawSnapShotPmemHeap.");
2195 mRawSnapShotPmemHeap.clear();
2196 }
2197
2198 //Pmem based pool for Camera Driver
2199 mRawSnapShotPmemHeap = new PmemPool("/dev/pmem_adsp",
Dinesh Gargeecf1a62010-04-19 16:31:30 -07002200 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002201 mCameraControlFd,
2202 MSM_PMEM_RAW_MAINIMG,
2203 rawSnapshotSize,
2204 1,
2205 rawSnapshotSize,
2206 "raw pmem snapshot camera");
2207
2208 if (!mRawSnapShotPmemHeap->initialized()) {
2209 mRawSnapShotPmemHeap.clear();
2210 LOGE("initRawSnapshot X: error initializing mRawSnapshotHeap");
2211 return false;
2212 }
2213 LOGV("initRawSnapshot X");
2214 return true;
2215
2216}
2217
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002218bool QualcommCameraHardware::initRaw(bool initJpegHeap)
2219{
2220 int rawWidth, rawHeight;
Apurva Rajguru8d1773b2009-12-02 14:21:23 -08002221
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002222 mParameters.getPictureSize(&rawWidth, &rawHeight);
2223 LOGV("initRaw E: picture size=%dx%d", rawWidth, rawHeight);
2224
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08002225 int thumbnailBufferSize;
2226 //Thumbnail height should be smaller than Picture height
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002227 if (rawHeight > (int)thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height){
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08002228 mDimension.ui_thumbnail_width =
2229 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].width;
2230 mDimension.ui_thumbnail_height =
2231 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height;
2232 uint32_t pictureAspectRatio = (uint32_t)((rawWidth * Q12) / rawHeight);
2233 uint32_t i;
2234 for(i = 0; i < THUMBNAIL_SIZE_COUNT; i++ )
2235 {
2236 if(thumbnail_sizes[i].aspect_ratio == pictureAspectRatio)
2237 {
2238 mDimension.ui_thumbnail_width = thumbnail_sizes[i].width;
2239 mDimension.ui_thumbnail_height = thumbnail_sizes[i].height;
2240 break;
2241 }
2242 }
2243 }
2244 else{
2245 mDimension.ui_thumbnail_height = THUMBNAIL_SMALL_HEIGHT;
2246 mDimension.ui_thumbnail_width =
2247 (THUMBNAIL_SMALL_HEIGHT * rawWidth)/ rawHeight;
2248 }
2249
2250 LOGV("Thumbnail Size Width %d Height %d",
2251 mDimension.ui_thumbnail_width,
2252 mDimension.ui_thumbnail_height);
2253
2254 thumbnailBufferSize = mDimension.ui_thumbnail_width *
2255 mDimension.ui_thumbnail_height * 3 / 2;
2256
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002257 // mDimension will be filled with thumbnail_width, thumbnail_height,
2258 // orig_picture_dx, and orig_picture_dy after this function call. We need to
2259 // keep it for jpeg_encoder_encode.
2260 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
2261 sizeof(cam_ctrl_dimension_t), &mDimension);
2262 if(!ret) {
2263 LOGE("initRaw X: failed to set dimension");
2264 return false;
2265 }
2266
2267 if (mJpegHeap != NULL) {
2268 LOGV("initRaw: clearing old mJpegHeap.");
2269 mJpegHeap.clear();
2270 }
2271
2272 // Snapshot
2273 mRawSize = rawWidth * rawHeight * 3 / 2;
Apurva Rajguru8d1773b2009-12-02 14:21:23 -08002274
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002275 if( mCurrentTarget == TARGET_MSM7627 )
Apurva Rajguru8d1773b2009-12-02 14:21:23 -08002276 mJpegMaxSize = CEILING16(rawWidth) * CEILING16(rawHeight) * 3 / 2;
2277 else
2278 mJpegMaxSize = rawWidth * rawHeight * 3 / 2;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002279
2280 LOGV("initRaw: initializing mRawHeap.");
2281 mRawHeap =
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002282 new PmemPool("/dev/pmem_adsp",
Dinesh Gargeecf1a62010-04-19 16:31:30 -07002283 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002284 mCameraControlFd,
2285 MSM_PMEM_MAINIMG,
2286 mJpegMaxSize,
2287 kRawBufferCount,
2288 mRawSize,
2289 "snapshot camera");
2290
2291 if (!mRawHeap->initialized()) {
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002292 LOGE("initRaw X failed ");
2293 mRawHeap.clear();
2294 LOGE("initRaw X: error initializing mRawHeap");
2295 return false;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002296 }
2297
2298 LOGV("do_mmap snapshot pbuf = %p, pmem_fd = %d",
2299 (uint8_t *)mRawHeap->mHeap->base(), mRawHeap->mHeap->getHeapID());
2300
2301 // Jpeg
2302
2303 if (initJpegHeap) {
2304 LOGV("initRaw: initializing mJpegHeap.");
2305 mJpegHeap =
2306 new AshmemPool(mJpegMaxSize,
2307 kJpegBufferCount,
2308 0, // we do not know how big the picture will be
2309 "jpeg");
2310
2311 if (!mJpegHeap->initialized()) {
2312 mJpegHeap.clear();
2313 mRawHeap.clear();
2314 LOGE("initRaw X failed: error initializing mJpegHeap.");
2315 return false;
2316 }
2317
2318 // Thumbnails
2319
2320 mThumbnailHeap =
2321 new PmemPool("/dev/pmem_adsp",
Dinesh Gargeecf1a62010-04-19 16:31:30 -07002322 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002323 mCameraControlFd,
2324 MSM_PMEM_THUMBNAIL,
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08002325 thumbnailBufferSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002326 1,
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08002327 thumbnailBufferSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002328 "thumbnail");
2329
2330 if (!mThumbnailHeap->initialized()) {
2331 mThumbnailHeap.clear();
2332 mJpegHeap.clear();
2333 mRawHeap.clear();
2334 LOGE("initRaw X failed: error initializing mThumbnailHeap.");
2335 return false;
2336 }
2337 }
2338
2339 LOGV("initRaw X");
2340 return true;
2341}
2342
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002343
2344void QualcommCameraHardware::deinitRawSnapshot()
2345{
2346 LOGV("deinitRawSnapshot E");
2347 mRawSnapShotPmemHeap.clear();
2348 mRawSnapshotAshmemHeap.clear();
2349 LOGV("deinitRawSnapshot X");
2350}
2351
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002352void QualcommCameraHardware::deinitRaw()
2353{
2354 LOGV("deinitRaw E");
2355
2356 mThumbnailHeap.clear();
2357 mJpegHeap.clear();
2358 mRawHeap.clear();
2359 mDisplayHeap.clear();
2360
2361 LOGV("deinitRaw X");
2362}
2363
2364void QualcommCameraHardware::release()
2365{
2366 LOGD("release E");
2367 Mutex::Autolock l(&mLock);
2368
2369#if DLOPEN_LIBMMCAMERA
2370 if (libmmcamera == NULL) {
2371 LOGE("ERROR: multiple release!");
2372 return;
2373 }
2374#else
2375#warning "Cannot detect multiple release when not dlopen()ing libqcamera!"
2376#endif
2377
2378 int cnt, rc;
2379 struct msm_ctrl_cmd ctrlCmd;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002380 if (mCameraRunning) {
2381 if(mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME)) {
2382 mRecordFrameLock.lock();
2383 mReleasedRecordingFrame = true;
2384 mRecordWait.signal();
2385 mRecordFrameLock.unlock();
2386 }
2387 stopPreviewInternal();
2388 }
2389
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002390 if( mCurrentTarget == TARGET_MSM7630 ) {
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002391 mPostViewHeap.clear();
2392 mPostViewHeap = NULL;
2393 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002394 LINK_jpeg_encoder_join();
2395 deinitRaw();
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002396 deinitRawSnapshot();
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002397 {
2398 Mutex::Autolock l(&mCamframeTimeoutLock);
2399 if(!camframe_timeout_flag) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002400
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002401 ctrlCmd.timeout_ms = 5000;
2402 ctrlCmd.length = 0;
2403 ctrlCmd.type = (uint16_t)CAMERA_EXIT;
2404 ctrlCmd.resp_fd = mCameraControlFd; // FIXME: this will be put in by the kernel
2405 if (ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0)
2406 LOGE("ioctl CAMERA_EXIT fd %d error %s",
2407 mCameraControlFd, strerror(errno));
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002408
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002409 }
2410 }
Kiran Kumar H N7ac84e32010-02-01 10:58:47 -08002411 LINK_release_cam_conf_thread();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002412 close(mCameraControlFd);
2413 mCameraControlFd = -1;
Mohan Kandra284966d2010-01-05 13:39:15 -08002414 if(fb_fd >= 0) {
2415 close(fb_fd);
2416 fb_fd = -1;
2417 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002418#if DLOPEN_LIBMMCAMERA
2419 if (libmmcamera) {
2420 ::dlclose(libmmcamera);
2421 LOGV("dlclose(libqcamera)");
2422 libmmcamera = NULL;
2423 }
2424#endif
2425
2426 Mutex::Autolock lock(&singleton_lock);
2427 singleton_releasing = true;
2428
2429 LOGD("release X");
2430}
2431
2432QualcommCameraHardware::~QualcommCameraHardware()
2433{
2434 LOGD("~QualcommCameraHardware E");
2435 Mutex::Autolock lock(&singleton_lock);
Apurva Rajguruc73c1722010-04-15 17:39:11 -07002436
2437 if( mCurrentTarget == TARGET_MSM7630 || mCurrentTarget == TARGET_QSD8250 ) {
2438 delete [] recordframes;
2439 recordframes = NULL;
2440 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002441 singleton.clear();
2442 singleton_releasing = false;
2443 singleton_wait.signal();
2444 LOGD("~QualcommCameraHardware X");
2445}
2446
2447sp<IMemoryHeap> QualcommCameraHardware::getRawHeap() const
2448{
2449 LOGV("getRawHeap");
2450 return mDisplayHeap != NULL ? mDisplayHeap->mHeap : NULL;
2451}
2452
2453sp<IMemoryHeap> QualcommCameraHardware::getPreviewHeap() const
2454{
2455 LOGV("getPreviewHeap");
Mohan Kandrad9efed92010-01-15 19:08:39 -08002456 return mPreviewHeap != NULL ? mPreviewHeap->mHeap : NULL;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002457}
2458
2459status_t QualcommCameraHardware::startPreviewInternal()
2460{
Sravankb4f5f1c2010-01-21 11:06:17 +05302461 LOGV("in startPreviewInternal : E");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002462 if(mCameraRunning) {
2463 LOGV("startPreview X: preview already running.");
2464 return NO_ERROR;
2465 }
2466
2467 if (!mPreviewInitialized) {
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002468 mLastQueuedFrame = NULL;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002469 mPreviewInitialized = initPreview();
2470 if (!mPreviewInitialized) {
2471 LOGE("startPreview X initPreview failed. Not starting preview.");
2472 return UNKNOWN_ERROR;
2473 }
2474 }
2475
Srinivasan Kannan74712c92010-04-07 13:36:48 -07002476 {
2477 Mutex::Autolock cameraRunningLock(&mCameraRunningLock);
2478 if(( mCurrentTarget != TARGET_MSM7630 ) &&
2479 (mCurrentTarget != TARGET_QSD8250))
2480 mCameraRunning = native_start_preview(mCameraControlFd);
2481 else
2482 mCameraRunning = native_start_video(mCameraControlFd);
2483 }
Sravankb4f5f1c2010-01-21 11:06:17 +05302484
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002485 if(!mCameraRunning) {
2486 deinitPreview();
2487 mPreviewInitialized = false;
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08002488 mOverlay = NULL;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002489 LOGE("startPreview X: native_start_preview failed!");
2490 return UNKNOWN_ERROR;
2491 }
2492
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08002493 //Reset the Gps Information
2494 exif_table_numEntries = 0;
Mohan Kandra284966d2010-01-05 13:39:15 -08002495
2496 if(native_get_maxzoom(mCameraControlFd, (void *)&mMaxZoom) == true){
Brian Steuerb62adbd2010-02-02 14:47:08 -08002497 LOGD("Maximum zoom value is %d", mMaxZoom);
Mohan Kandra284966d2010-01-05 13:39:15 -08002498 mParameters.set("zoom-supported", "true");
2499 } else {
2500 LOGE("Failed to get maximum zoom value...setting max zoom to zero");
2501 mParameters.set("zoom-supported", "false");
2502 mMaxZoom = 0;
2503 }
2504 mParameters.set("max-zoom",mMaxZoom);
2505
Sravankb4f5f1c2010-01-21 11:06:17 +05302506 LOGV("startPreviewInternal X");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002507 return NO_ERROR;
2508}
2509
2510status_t QualcommCameraHardware::startPreview()
2511{
2512 LOGV("startPreview E");
2513 Mutex::Autolock l(&mLock);
2514 return startPreviewInternal();
2515}
2516
2517void QualcommCameraHardware::stopPreviewInternal()
2518{
2519 LOGV("stopPreviewInternal E: %d", mCameraRunning);
2520 if (mCameraRunning) {
2521 // Cancel auto focus.
2522 {
2523 if (mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS)) {
2524 cancelAutoFocusInternal();
2525 }
2526 }
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002527
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002528 Mutex::Autolock l(&mCamframeTimeoutLock);
Srinivasan Kannan74712c92010-04-07 13:36:48 -07002529 {
2530 Mutex::Autolock cameraRunningLock(&mCameraRunningLock);
2531 if(!camframe_timeout_flag) {
2532 if (( mCurrentTarget != TARGET_MSM7630 ) &&
2533 (mCurrentTarget != TARGET_QSD8250))
2534 mCameraRunning = !native_stop_preview(mCameraControlFd);
2535 else
2536 mCameraRunning = !native_stop_video(mCameraControlFd);
2537 } else {
2538 /* This means that the camframetimeout was issued.
2539 * But we did not issue native_stop_preview(), so we
2540 * need to update mCameraRunning to indicate that
2541 * Camera is no longer running. */
2542 mCameraRunning = 0;
2543 }
2544 }
Sravankb4f5f1c2010-01-21 11:06:17 +05302545
Kiran Kumar H Nac2f4952009-12-17 01:16:53 -08002546 if (!mCameraRunning && mPreviewInitialized) {
2547 deinitPreview();
Mohan Kandraf1ebf982010-02-02 15:25:43 -08002548 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250)) {
Mohan Kandra156d0ac2010-01-25 16:59:17 -08002549 mVideoThreadWaitLock.lock();
2550 LOGV("in stopPreviewInternal: making mVideoThreadExit 1");
2551 mVideoThreadExit = 1;
2552 mVideoThreadWaitLock.unlock();
2553 // 720p : signal the video thread , and check in video thread if stop is called, if so exit video thread.
2554 pthread_mutex_lock(&(g_busy_frame_queue.mut));
2555 pthread_cond_signal(&(g_busy_frame_queue.wait));
2556 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
Mohan Kandra1ade9a82010-03-02 10:11:26 -08002557 /* Flush the Busy Q */
2558 cam_frame_flush_video();
2559 /* Flush the Free Q */
2560 LINK_cam_frame_flush_free_video();
Mohan Kandra156d0ac2010-01-25 16:59:17 -08002561 }
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002562 mPreviewInitialized = false;
2563 }
Kiran Kumar H Nac2f4952009-12-17 01:16:53 -08002564 else LOGE("stopPreviewInternal: failed to stop preview");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002565 }
2566 LOGV("stopPreviewInternal X: %d", mCameraRunning);
2567}
2568
2569void QualcommCameraHardware::stopPreview()
2570{
2571 LOGV("stopPreview: E");
2572 Mutex::Autolock l(&mLock);
2573 {
2574 if (mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME))
2575 return;
2576 }
2577 stopPreviewInternal();
2578 LOGV("stopPreview: X");
2579}
2580
2581void QualcommCameraHardware::runAutoFocus()
2582{
2583 bool status = true;
2584 void *libhandle = NULL;
Srinivasan Kannan71229622009-12-04 12:05:58 -08002585 isp3a_af_mode_t afMode;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002586
2587 mAutoFocusThreadLock.lock();
2588 // Skip autofocus if focus mode is infinity.
Srinivasan Kannan74712c92010-04-07 13:36:48 -07002589 if ((mParameters.get(CameraParameters::KEY_FOCUS_MODE) == 0)
2590 || (strcmp(mParameters.get(CameraParameters::KEY_FOCUS_MODE),
2591 CameraParameters::FOCUS_MODE_INFINITY) == 0)) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002592 goto done;
2593 }
2594
2595 mAutoFocusFd = open(MSM_CAMERA_CONTROL, O_RDWR);
2596 if (mAutoFocusFd < 0) {
2597 LOGE("autofocus: cannot open %s: %s",
2598 MSM_CAMERA_CONTROL,
2599 strerror(errno));
2600 mAutoFocusThreadRunning = false;
2601 mAutoFocusThreadLock.unlock();
2602 return;
2603 }
2604
2605#if DLOPEN_LIBMMCAMERA
2606 // We need to maintain a reference to libqcamera.so for the duration of the
2607 // AF thread, because we do not know when it will exit relative to the
2608 // lifetime of this object. We do not want to dlclose() libqcamera while
2609 // LINK_cam_frame is still running.
2610 libhandle = ::dlopen("liboemcamera.so", RTLD_NOW);
2611 LOGV("AF: loading libqcamera at %p", libhandle);
2612 if (!libhandle) {
2613 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
2614 close(mAutoFocusFd);
2615 mAutoFocusFd = -1;
2616 mAutoFocusThreadRunning = false;
2617 mAutoFocusThreadLock.unlock();
2618 return;
2619 }
2620#endif
2621
Srinivasan Kannan71229622009-12-04 12:05:58 -08002622 afMode = (isp3a_af_mode_t)attr_lookup(focus_modes,
2623 sizeof(focus_modes) / sizeof(str_map),
2624 mParameters.get(CameraParameters::KEY_FOCUS_MODE));
2625
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002626 /* This will block until either AF completes or is cancelled. */
Srinivasan Kannan71229622009-12-04 12:05:58 -08002627 LOGV("af start (fd %d mode %d)", mAutoFocusFd, afMode);
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08002628 status_t err;
2629 err = mAfLock.tryLock();
2630 if(err == NO_ERROR) {
Srinivasan Kannan74712c92010-04-07 13:36:48 -07002631 {
2632 Mutex::Autolock cameraRunningLock(&mCameraRunningLock);
2633 if(mCameraRunning){
2634 LOGV("Start AF");
2635 status = native_set_afmode(mAutoFocusFd, afMode);
2636 }else{
2637 LOGV("As Camera preview is not running, AF not issued");
2638 status = false;
2639 }
2640 }
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08002641 mAfLock.unlock();
2642 }
2643 else{
2644 //AF Cancel would have acquired the lock,
2645 //so, no need to perform any AF
Srinivasan Kannan99e82422010-02-28 15:32:16 -08002646 LOGV("As Cancel auto focus is in progress, auto focus request "
2647 "is ignored");
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08002648 status = FALSE;
2649 }
2650
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002651 LOGV("af done: %d", (int)status);
2652 close(mAutoFocusFd);
2653 mAutoFocusFd = -1;
2654
2655done:
2656 mAutoFocusThreadRunning = false;
2657 mAutoFocusThreadLock.unlock();
2658
2659 mCallbackLock.lock();
2660 bool autoFocusEnabled = mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS);
2661 notify_callback cb = mNotifyCallback;
2662 void *data = mCallbackCookie;
2663 mCallbackLock.unlock();
2664 if (autoFocusEnabled)
2665 cb(CAMERA_MSG_FOCUS, status, 0, data);
2666
2667#if DLOPEN_LIBMMCAMERA
2668 if (libhandle) {
2669 ::dlclose(libhandle);
2670 LOGV("AF: dlclose(libqcamera)");
2671 }
2672#endif
2673}
2674
2675status_t QualcommCameraHardware::cancelAutoFocusInternal()
2676{
2677 LOGV("cancelAutoFocusInternal E");
2678
Srinivasan Kannan71229622009-12-04 12:05:58 -08002679 if(!sensorType->hasAutoFocusSupport){
2680 LOGV("cancelAutoFocusInternal X");
2681 return NO_ERROR;
2682 }
2683
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002684#if 0
2685 if (mAutoFocusFd < 0) {
2686 LOGV("cancelAutoFocusInternal X: not in progress");
2687 return NO_ERROR;
2688 }
2689#endif
2690
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08002691 status_t rc = NO_ERROR;
2692 status_t err;
2693 err = mAfLock.tryLock();
2694 if(err == NO_ERROR) {
2695 //Got Lock, means either AF hasn't started or
2696 // AF is done. So no need to cancel it, just change the state
Srinivasan Kannan99e82422010-02-28 15:32:16 -08002697 LOGV("As Auto Focus is not in progress, Cancel Auto Focus "
2698 "is ignored");
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08002699 mAfLock.unlock();
2700 }
2701 else {
2702 //AF is in Progess, So cancel it
2703 LOGV("Lock busy...cancel AF");
2704 rc = native_cancel_afmode(mCameraControlFd, mAutoFocusFd) ?
2705 NO_ERROR :
2706 UNKNOWN_ERROR;
2707 }
2708
2709
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002710
2711 LOGV("cancelAutoFocusInternal X: %d", rc);
2712 return rc;
2713}
2714
2715void *auto_focus_thread(void *user)
2716{
2717 LOGV("auto_focus_thread E");
2718 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
2719 if (obj != 0) {
2720 obj->runAutoFocus();
2721 }
2722 else LOGW("not starting autofocus: the object went away!");
2723 LOGV("auto_focus_thread X");
2724 return NULL;
2725}
2726
2727status_t QualcommCameraHardware::autoFocus()
2728{
2729 LOGV("autoFocus E");
2730 Mutex::Autolock l(&mLock);
2731
Srinivasan Kannan71229622009-12-04 12:05:58 -08002732 if(!sensorType->hasAutoFocusSupport){
Srinivasan Kannandf085222009-12-09 18:31:00 -08002733 bool status = false;
2734 mCallbackLock.lock();
2735 bool autoFocusEnabled = mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS);
2736 notify_callback cb = mNotifyCallback;
2737 void *data = mCallbackCookie;
2738 mCallbackLock.unlock();
2739 if (autoFocusEnabled)
2740 cb(CAMERA_MSG_FOCUS, status, 0, data);
Srinivasan Kannan71229622009-12-04 12:05:58 -08002741 LOGV("autoFocus X");
2742 return NO_ERROR;
2743 }
2744
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002745 if (mCameraControlFd < 0) {
2746 LOGE("not starting autofocus: main control fd %d", mCameraControlFd);
2747 return UNKNOWN_ERROR;
2748 }
2749
2750 {
2751 mAutoFocusThreadLock.lock();
2752 if (!mAutoFocusThreadRunning) {
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08002753 if (native_prepare_snapshot(mCameraControlFd) == FALSE) {
2754 LOGE("native_prepare_snapshot failed!\n");
2755 mAutoFocusThreadLock.unlock();
2756 return UNKNOWN_ERROR;
2757 }
2758
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002759 // Create a detached thread here so that we don't have to wait
2760 // for it when we cancel AF.
2761 pthread_t thr;
2762 pthread_attr_t attr;
2763 pthread_attr_init(&attr);
2764 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2765 mAutoFocusThreadRunning =
2766 !pthread_create(&thr, &attr,
2767 auto_focus_thread, NULL);
2768 if (!mAutoFocusThreadRunning) {
2769 LOGE("failed to start autofocus thread");
2770 mAutoFocusThreadLock.unlock();
2771 return UNKNOWN_ERROR;
2772 }
2773 }
2774 mAutoFocusThreadLock.unlock();
2775 }
2776
2777 LOGV("autoFocus X");
2778 return NO_ERROR;
2779}
2780
2781status_t QualcommCameraHardware::cancelAutoFocus()
2782{
2783 LOGV("cancelAutoFocus E");
2784 Mutex::Autolock l(&mLock);
2785
2786 int rc = NO_ERROR;
2787 if (mCameraRunning && mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS)) {
2788 rc = cancelAutoFocusInternal();
2789 }
2790
2791 LOGV("cancelAutoFocus X");
2792 return rc;
2793}
2794
2795void QualcommCameraHardware::runSnapshotThread(void *data)
2796{
2797 LOGV("runSnapshotThread E");
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002798 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
2799 if (native_start_snapshot(mCameraControlFd))
2800 receiveRawPicture();
2801 else
2802 LOGE("main: native_start_snapshot failed!");
2803 } else if(mSnapshotFormat == PICTURE_FORMAT_RAW){
2804 if(native_start_raw_snapshot(mCameraControlFd)){
2805 receiveRawSnapshot();
2806 } else {
2807 LOGE("main: native_start_raw_snapshot failed!");
2808 }
2809 }
2810
2811 mSnapshotFormat = 0;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002812
2813 mSnapshotThreadWaitLock.lock();
2814 mSnapshotThreadRunning = false;
2815 mSnapshotThreadWait.signal();
2816 mSnapshotThreadWaitLock.unlock();
2817
2818 LOGV("runSnapshotThread X");
2819}
2820
2821void *snapshot_thread(void *user)
2822{
2823 LOGD("snapshot_thread E");
2824 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
2825 if (obj != 0) {
2826 obj->runSnapshotThread(user);
2827 }
2828 else LOGW("not starting snapshot thread: the object went away!");
2829 LOGD("snapshot_thread X");
2830 return NULL;
2831}
2832
2833status_t QualcommCameraHardware::takePicture()
2834{
2835 LOGV("takePicture(%d)", mMsgEnabled);
2836 Mutex::Autolock l(&mLock);
2837
2838 // Wait for old snapshot thread to complete.
2839 mSnapshotThreadWaitLock.lock();
2840 while (mSnapshotThreadRunning) {
2841 LOGV("takePicture: waiting for old snapshot thread to complete.");
2842 mSnapshotThreadWait.wait(mSnapshotThreadWaitLock);
2843 LOGV("takePicture: old snapshot thread completed.");
2844 }
2845
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002846 if( mCurrentTarget == TARGET_MSM7630 ) {
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002847 /* Store the last frame queued for preview. This
2848 * shall be used as postview */
2849 storePreviewFrameForPostview();
2850 }
2851
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002852 //mSnapshotFormat is protected by mSnapshotThreadWaitLock
2853 if(mParameters.getPictureFormat() != 0 &&
2854 !strcmp(mParameters.getPictureFormat(),
2855 CameraParameters::PIXEL_FORMAT_RAW))
2856 mSnapshotFormat = PICTURE_FORMAT_RAW;
2857 else
2858 mSnapshotFormat = PICTURE_FORMAT_JPEG;
2859
2860 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
2861 if(!native_prepare_snapshot(mCameraControlFd)) {
2862 mSnapshotThreadWaitLock.unlock();
2863 return UNKNOWN_ERROR;
2864 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002865 }
2866
2867 stopPreviewInternal();
2868
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002869 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
2870 if (!initRaw(mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE))) {
2871 LOGE("initRaw failed. Not taking picture.");
2872 mSnapshotThreadWaitLock.unlock();
2873 return UNKNOWN_ERROR;
2874 }
2875 } else if(mSnapshotFormat == PICTURE_FORMAT_RAW ){
2876 if(!initRawSnapshot()){
2877 LOGE("initRawSnapshot failed. Not taking picture.");
2878 mSnapshotThreadWaitLock.unlock();
2879 return UNKNOWN_ERROR;
2880 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002881 }
2882
2883 mShutterLock.lock();
2884 mShutterPending = true;
2885 mShutterLock.unlock();
2886
2887 pthread_attr_t attr;
2888 pthread_attr_init(&attr);
2889 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2890 mSnapshotThreadRunning = !pthread_create(&mSnapshotThread,
2891 &attr,
2892 snapshot_thread,
2893 NULL);
2894 mSnapshotThreadWaitLock.unlock();
2895
2896 LOGV("takePicture: X");
2897 return mSnapshotThreadRunning ? NO_ERROR : UNKNOWN_ERROR;
2898}
2899
2900status_t QualcommCameraHardware::cancelPicture()
2901{
2902 status_t rc;
2903 LOGV("cancelPicture: E");
2904 rc = native_stop_snapshot(mCameraControlFd) ? NO_ERROR : UNKNOWN_ERROR;
2905 LOGV("cancelPicture: X: %d", rc);
2906 return rc;
2907}
2908
2909status_t QualcommCameraHardware::setParameters(const CameraParameters& params)
2910{
2911 LOGV("setParameters: E params = %p", &params);
2912
2913 Mutex::Autolock l(&mLock);
2914 status_t rc, final_rc = NO_ERROR;
2915
2916 if ((rc = setPreviewSize(params))) final_rc = rc;
2917 if ((rc = setPictureSize(params))) final_rc = rc;
2918 if ((rc = setJpegQuality(params))) final_rc = rc;
2919 if ((rc = setAntibanding(params))) final_rc = rc;
Apurva Rajguru55562b02009-12-03 12:25:35 -08002920 if ((rc = setAutoExposure(params))) final_rc = rc;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002921 if ((rc = setWhiteBalance(params))) final_rc = rc;
Vamshidhar Kondrae7b9b5a2010-02-25 15:40:37 +05302922 if ((rc = setEffect(params))) final_rc = rc;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002923 if ((rc = setFlash(params))) final_rc = rc;
2924 if ((rc = setGpsLocation(params))) final_rc = rc;
2925 if ((rc = setRotation(params))) final_rc = rc;
2926 if ((rc = setZoom(params))) final_rc = rc;
2927 if ((rc = setFocusMode(params))) final_rc = rc;
2928 if ((rc = setOrientation(params))) final_rc = rc;
Nishant Panditc8c1ee72009-12-03 16:24:02 +05302929 if ((rc = setBrightness(params))) final_rc = rc;
2930 if ((rc = setLensshadeValue(params))) final_rc = rc;
2931 if ((rc = setISOValue(params))) final_rc = rc;
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002932 if ((rc = setPictureFormat(params))) final_rc = rc;
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08002933 if ((rc = setSharpness(params))) final_rc = rc;
2934 if ((rc = setContrast(params))) final_rc = rc;
2935 if ((rc = setSaturation(params))) final_rc = rc;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002936
2937 LOGV("setParameters: X");
2938 return final_rc;
2939}
2940
2941CameraParameters QualcommCameraHardware::getParameters() const
2942{
2943 LOGV("getParameters: EX");
2944 return mParameters;
2945}
2946
2947status_t QualcommCameraHardware::sendCommand(int32_t command, int32_t arg1,
2948 int32_t arg2)
2949{
2950 LOGV("sendCommand: EX");
2951 return BAD_VALUE;
2952}
2953
2954extern "C" sp<CameraHardwareInterface> openCameraHardware()
2955{
2956 LOGV("openCameraHardware: call createInstance");
2957 return QualcommCameraHardware::createInstance();
2958}
2959
2960wp<QualcommCameraHardware> QualcommCameraHardware::singleton;
2961
2962// If the hardware already exists, return a strong pointer to the current
2963// object. If not, create a new hardware object, put it in the singleton,
2964// and return it.
2965sp<CameraHardwareInterface> QualcommCameraHardware::createInstance()
2966{
2967 LOGD("createInstance: E");
2968
2969 Mutex::Autolock lock(&singleton_lock);
2970
2971 // Wait until the previous release is done.
2972 while (singleton_releasing) {
2973 LOGD("Wait for previous release.");
2974 singleton_wait.wait(singleton_lock);
2975 }
2976
2977 if (singleton != 0) {
2978 sp<CameraHardwareInterface> hardware = singleton.promote();
2979 if (hardware != 0) {
2980 LOGD("createInstance: X return existing hardware=%p", &(*hardware));
2981 return hardware;
2982 }
2983 }
2984
2985 {
2986 struct stat st;
2987 int rc = stat("/dev/oncrpc", &st);
2988 if (rc < 0) {
2989 LOGD("createInstance: X failed to create hardware: %s", strerror(errno));
2990 return NULL;
2991 }
2992 }
2993
2994 QualcommCameraHardware *cam = new QualcommCameraHardware();
2995 sp<QualcommCameraHardware> hardware(cam);
2996 singleton = hardware;
2997
2998 if (!cam->startCamera()) {
2999 LOGE("%s: startCamera failed!", __FUNCTION__);
3000 return NULL;
3001 }
3002
3003 cam->initDefaultParameters();
3004 LOGD("createInstance: X created hardware=%p", &(*hardware));
3005 return hardware;
3006}
3007
3008// For internal use only, hence the strong pointer to the derived type.
3009sp<QualcommCameraHardware> QualcommCameraHardware::getInstance()
3010{
3011 sp<CameraHardwareInterface> hardware = singleton.promote();
3012 if (hardware != 0) {
3013 // LOGV("getInstance: X old instance of hardware");
3014 return sp<QualcommCameraHardware>(static_cast<QualcommCameraHardware*>(hardware.get()));
3015 } else {
3016 LOGV("getInstance: X new instance of hardware");
3017 return sp<QualcommCameraHardware>();
3018 }
3019}
Sravankb4f5f1c2010-01-21 11:06:17 +05303020void QualcommCameraHardware::receiveRecordingFrame(struct msm_frame *frame)
3021{
3022 LOGV("receiveRecordingFrame E");
3023 // post busy frame
3024 if (frame)
3025 {
3026 cam_frame_post_video (frame);
3027 }
3028 else LOGE("in receiveRecordingFrame frame is NULL");
3029 LOGV("receiveRecordingFrame X");
3030}
3031
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003032
Mohan Kandrad9efed92010-01-15 19:08:39 -08003033bool QualcommCameraHardware::native_zoom_image(int fd, int srcOffset, int dstOffSet, common_crop_t *crop)
Mohan Kandra284966d2010-01-05 13:39:15 -08003034{
3035 int result = 0;
3036 struct mdp_blit_req *e;
3037 struct timeval td1, td2;
3038
Mohan Kandra284966d2010-01-05 13:39:15 -08003039 /* Initialize yuv structure */
3040 zoomImage.list.count = 1;
3041
3042 e = &zoomImage.list.req[0];
3043
3044 e->src.width = previewWidth;
3045 e->src.height = previewHeight;
3046 e->src.format = MDP_Y_CBCR_H2V2;
Mohan Kandrad9efed92010-01-15 19:08:39 -08003047 e->src.offset = srcOffset;
3048 e->src.memory_id = fd;
Mohan Kandra284966d2010-01-05 13:39:15 -08003049
3050 e->dst.width = previewWidth;
3051 e->dst.height = previewHeight;
3052 e->dst.format = MDP_Y_CBCR_H2V2;
Mohan Kandrad9efed92010-01-15 19:08:39 -08003053 e->dst.offset = dstOffSet;
3054 e->dst.memory_id = fd;
Mohan Kandra284966d2010-01-05 13:39:15 -08003055
3056 e->transp_mask = 0xffffffff;
3057 e->flags = 0;
3058 e->alpha = 0xff;
3059 if (crop->in2_w != 0 || crop->in2_h != 0) {
3060 e->src_rect.x = (crop->out2_w - crop->in2_w + 1) / 2 - 1;
3061 e->src_rect.y = (crop->out2_h - crop->in2_h + 1) / 2 - 1;
3062 e->src_rect.w = crop->in2_w;
3063 e->src_rect.h = crop->in2_h;
3064 } else {
3065 e->src_rect.x = 0;
3066 e->src_rect.y = 0;
3067 e->src_rect.w = previewWidth;
3068 e->src_rect.h = previewHeight;
3069 }
Mohan Kandrad9efed92010-01-15 19:08:39 -08003070 //LOGV(" native_zoom : SRC_RECT : x,y = %d,%d \t w,h = %d, %d",
3071 // e->src_rect.x, e->src_rect.y, e->src_rect.w, e->src_rect.h);
Mohan Kandra284966d2010-01-05 13:39:15 -08003072
3073 e->dst_rect.x = 0;
3074 e->dst_rect.y = 0;
3075 e->dst_rect.w = previewWidth;
3076 e->dst_rect.h = previewHeight;
3077
3078 result = ioctl(fb_fd, MSMFB_BLIT, &zoomImage.list);
3079 if (result < 0) {
3080 LOGE("MSM_FBIOBLT failed! line=%d\n", __LINE__);
3081 return FALSE;
3082 }
3083 return TRUE;
3084}
3085
Mohan Kandrabad0eaa2010-02-04 15:11:54 -08003086void QualcommCameraHardware::debugShowPreviewFPS() const
Mohan Kandra740cfce2010-01-07 12:58:24 -08003087{
3088 static int mFrameCount;
3089 static int mLastFrameCount = 0;
3090 static nsecs_t mLastFpsTime = 0;
3091 static float mFps = 0;
3092 mFrameCount++;
3093 nsecs_t now = systemTime();
3094 nsecs_t diff = now - mLastFpsTime;
3095 if (diff > ms2ns(250)) {
3096 mFps = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
Mohan Kandrabad0eaa2010-02-04 15:11:54 -08003097 LOGI("Preview Frames Per Second: %.4f", mFps);
Mohan Kandra740cfce2010-01-07 12:58:24 -08003098 mLastFpsTime = now;
3099 mLastFrameCount = mFrameCount;
3100 }
3101}
3102
Mohan Kandrabad0eaa2010-02-04 15:11:54 -08003103void QualcommCameraHardware::debugShowVideoFPS() const
3104{
3105 static int mFrameCount;
3106 static int mLastFrameCount = 0;
3107 static nsecs_t mLastFpsTime = 0;
3108 static float mFps = 0;
3109 mFrameCount++;
3110 nsecs_t now = systemTime();
3111 nsecs_t diff = now - mLastFpsTime;
3112 if (diff > ms2ns(250)) {
3113 mFps = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
3114 LOGI("Video Frames Per Second: %.4f", mFps);
3115 mLastFpsTime = now;
3116 mLastFrameCount = mFrameCount;
3117 }
3118}
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003119void QualcommCameraHardware::receivePreviewFrame(struct msm_frame *frame)
3120{
3121// LOGV("receivePreviewFrame E");
3122
3123 if (!mCameraRunning) {
3124 LOGE("ignoring preview callback--camera has been stopped");
3125 return;
3126 }
3127
Mohan Kandra740cfce2010-01-07 12:58:24 -08003128 if (UNLIKELY(mDebugFps)) {
Mohan Kandrabad0eaa2010-02-04 15:11:54 -08003129 debugShowPreviewFPS();
Mohan Kandra740cfce2010-01-07 12:58:24 -08003130 }
3131
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003132 mCallbackLock.lock();
3133 int msgEnabled = mMsgEnabled;
3134 data_callback pcb = mDataCallback;
3135 void *pdata = mCallbackCookie;
3136 data_callback_timestamp rcb = mDataCallbackTimestamp;
3137 void *rdata = mCallbackCookie;
3138 mCallbackLock.unlock();
3139
3140 // Find the offset within the heap of the current buffer.
Mohan Kandra284966d2010-01-05 13:39:15 -08003141 ssize_t offset_addr =
Mohan Kandrad9efed92010-01-15 19:08:39 -08003142 (ssize_t)frame->buffer - (ssize_t)mPreviewHeap->mHeap->base();
3143 ssize_t offset = offset_addr / mPreviewHeap->mAlignedBufferSize;
Mohan Kandra284966d2010-01-05 13:39:15 -08003144
3145 common_crop_t *crop = (common_crop_t *) (frame->cropinfo);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003146
3147 mInPreviewCallback = true;
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003148 if(mUseOverlay) {
3149 if(mOverlay != NULL) {
3150 mOverlayLock.lock();
Mohan Kandrad9efed92010-01-15 19:08:39 -08003151 mOverlay->setFd(mPreviewHeap->mHeap->getHeapID());
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003152 if (crop->in2_w != 0 || crop->in2_h != 0) {
3153 zoomCropInfo.x = (crop->out2_w - crop->in2_w + 1) / 2 - 1;
3154 zoomCropInfo.y = (crop->out2_h - crop->in2_h + 1) / 2 - 1;
3155 zoomCropInfo.w = crop->in2_w;
3156 zoomCropInfo.h = crop->in2_h;
3157 mOverlay->setCrop(zoomCropInfo.x, zoomCropInfo.y,
3158 zoomCropInfo.w, zoomCropInfo.h);
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08003159 } else {
3160 // Reset zoomCropInfo variables. This will ensure that
3161 // stale values wont be used for postview
3162 zoomCropInfo.w = crop->in2_w;
3163 zoomCropInfo.h = crop->in2_h;
3164 }
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003165 mOverlay->queueBuffer((void *)offset_addr);
3166 mLastQueuedFrame = (void *)frame->buffer;
3167 mOverlayLock.unlock();
3168 }
Mohan Kandra284966d2010-01-05 13:39:15 -08003169 } else {
Mohan Kandrad9efed92010-01-15 19:08:39 -08003170 if (crop->in2_w != 0 || crop->in2_h != 0) {
3171 dstOffset = (dstOffset + 1) % NUM_MORE_BUFS;
3172 offset = kPreviewBufferCount + dstOffset;
3173 ssize_t dstOffset_addr = offset * mPreviewHeap->mAlignedBufferSize;
3174 if( !native_zoom_image(mPreviewHeap->mHeap->getHeapID(),
3175 offset_addr, dstOffset_addr, crop)) {
3176 LOGE(" Error while doing MDP zoom ");
Kiran Kumar H N1ece71c2010-03-30 10:31:21 -07003177 offset = offset_addr / mPreviewHeap->mAlignedBufferSize;
Mohan Kandrad9efed92010-01-15 19:08:39 -08003178 }
3179 }
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08003180 }
Mohan Kandrad9efed92010-01-15 19:08:39 -08003181 if (pcb != NULL && (msgEnabled & CAMERA_MSG_PREVIEW_FRAME))
3182 pcb(CAMERA_MSG_PREVIEW_FRAME, mPreviewHeap->mBuffers[offset],
3183 pdata);
3184
Sravankb4f5f1c2010-01-21 11:06:17 +05303185 // If output is NOT enabled (targets otherthan 7x30 currently..)
Mohan Kandraf1ebf982010-02-02 15:25:43 -08003186 if( (mCurrentTarget != TARGET_MSM7630 ) && (mCurrentTarget != TARGET_QSD8250)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05303187 if(rcb != NULL && (msgEnabled & CAMERA_MSG_VIDEO_FRAME)) {
3188 rcb(systemTime(), CAMERA_MSG_VIDEO_FRAME, mPreviewHeap->mBuffers[offset], rdata);
3189 Mutex::Autolock rLock(&mRecordFrameLock);
3190 if (mReleasedRecordingFrame != true) {
3191 LOGV("block waiting for frame release");
3192 mRecordWait.wait(mRecordFrameLock);
3193 LOGV("frame released, continuing");
3194 }
3195 mReleasedRecordingFrame = false;
3196 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003197 }
3198 mInPreviewCallback = false;
3199
3200// LOGV("receivePreviewFrame X");
3201}
3202
Sravankb4f5f1c2010-01-21 11:06:17 +05303203
3204bool QualcommCameraHardware::initRecord()
3205{
Apurva Rajguruc73c1722010-04-15 17:39:11 -07003206 char *pmem_region;
3207
Sravankb4f5f1c2010-01-21 11:06:17 +05303208 LOGV("initREcord E");
3209
3210 mRecordFrameSize = (mDimension.video_width * mDimension.video_height *3)/2;
Apurva Rajguruc73c1722010-04-15 17:39:11 -07003211
3212 if( mCurrentTarget == TARGET_QSD8250 )
3213 pmem_region = "/dev/pmem_smipool";
3214 else
3215 pmem_region = "/dev/pmem_adsp";
3216
3217 mRecordHeap = new PmemPool(pmem_region,
Sravankb4f5f1c2010-01-21 11:06:17 +05303218 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
3219 mCameraControlFd,
3220 MSM_PMEM_VIDEO,
3221 mRecordFrameSize,
3222 kRecordBufferCount,
3223 mRecordFrameSize,
3224 "record");
Apurva Rajguruc73c1722010-04-15 17:39:11 -07003225
Sravankb4f5f1c2010-01-21 11:06:17 +05303226 if (!mRecordHeap->initialized()) {
3227 mRecordHeap.clear();
3228 LOGE("initRecord X: could not initialize record heap.");
3229 return false;
3230 }
3231 for (int cnt = 0; cnt < kRecordBufferCount; cnt++) {
3232 recordframes[cnt].fd = mRecordHeap->mHeap->getHeapID();
3233 recordframes[cnt].buffer =
3234 (uint32_t)mRecordHeap->mHeap->base() + mRecordHeap->mAlignedBufferSize * cnt;
3235 recordframes[cnt].y_off = 0;
3236 recordframes[cnt].cbcr_off = mDimension.video_width * mDimension.video_height;
3237 recordframes[cnt].path = OUTPUT_TYPE_V;
3238
3239 LOGV ("initRecord : record heap , video buffers buffer=%lu fd=%d y_off=%d cbcr_off=%d \n",
3240 (unsigned long)recordframes[cnt].buffer, recordframes[cnt].fd, recordframes[cnt].y_off,
3241 recordframes[cnt].cbcr_off);
3242 }
3243
3244 // initial setup : buffers 1,2,3 with kernel , 4 with camframe , 5,6,7,8 in free Q
3245 // flush the busy Q
3246 cam_frame_flush_video();
3247
Mohan Kandra156d0ac2010-01-25 16:59:17 -08003248 mVideoThreadWaitLock.lock();
3249 while (mVideoThreadRunning) {
3250 LOGV("initRecord: waiting for old video thread to complete.");
3251 mVideoThreadWait.wait(mVideoThreadWaitLock);
3252 LOGV("initRecord : old video thread completed.");
3253 }
3254 mVideoThreadWaitLock.unlock();
3255
Sravankdf7a9202010-02-08 15:02:51 +05303256 // flush free queue and add 5,6,7,8 buffers.
3257 LINK_cam_frame_flush_free_video();
3258 for(int i=ACTIVE_VIDEO_BUFFERS+1;i <kRecordBufferCount; i++)
3259 LINK_camframe_free_video(&recordframes[i]);
Sravankb4f5f1c2010-01-21 11:06:17 +05303260 LOGV("initREcord X");
3261
3262 return true;
3263}
3264
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003265status_t QualcommCameraHardware::startRecording()
3266{
3267 LOGV("startRecording E");
Sravankb4f5f1c2010-01-21 11:06:17 +05303268 int ret;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003269 Mutex::Autolock l(&mLock);
3270 mReleasedRecordingFrame = false;
Sravankb4f5f1c2010-01-21 11:06:17 +05303271 if( (ret=startPreviewInternal())== NO_ERROR){
Mohan Kandraf1ebf982010-02-02 15:25:43 -08003272 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05303273 LOGV(" in startREcording : calling native_start_recording");
3274 native_start_recording(mCameraControlFd);
3275 recordingState = 1;
Sravank64461e82010-02-25 15:10:09 +05303276 // Remove the left out frames in busy Q and them in free Q.
3277 // this should be done before starting video_thread so that,
3278 // frames in previous recording are flushed out.
3279 LOGV("frames in busy Q = %d", g_busy_frame_queue.num_of_frames);
3280 while((g_busy_frame_queue.num_of_frames) >0){
3281 msm_frame* vframe = cam_frame_get_video ();
3282 LINK_camframe_free_video(vframe);
3283 }
3284 LOGV("frames in busy Q = %d after deQueing", g_busy_frame_queue.num_of_frames);
3285
Sravankdf7a9202010-02-08 15:02:51 +05303286 // Start video thread and wait for busy frames to be encoded, this thread
3287 // should be closed in stopRecording
3288 mVideoThreadWaitLock.lock();
3289 mVideoThreadExit = 0;
3290 pthread_attr_t attr;
3291 pthread_attr_init(&attr);
3292 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
3293 mVideoThreadRunning = pthread_create(&mVideoThread,
3294 &attr,
3295 video_thread,
3296 NULL);
3297 mVideoThreadWaitLock.unlock();
3298 // Remove the left out frames in busy Q and them in free Q.
Sravankb4f5f1c2010-01-21 11:06:17 +05303299 }
3300 }
3301 return ret;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003302}
3303
3304void QualcommCameraHardware::stopRecording()
3305{
3306 LOGV("stopRecording: E");
3307 Mutex::Autolock l(&mLock);
3308 {
3309 mRecordFrameLock.lock();
3310 mReleasedRecordingFrame = true;
3311 mRecordWait.signal();
3312 mRecordFrameLock.unlock();
3313
Sravankdf7a9202010-02-08 15:02:51 +05303314 if(mDataCallback && !(mCurrentTarget == TARGET_QSD8250) &&
3315 (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003316 LOGV("stopRecording: X, preview still in progress");
3317 return;
3318 }
3319 }
Sravankb4f5f1c2010-01-21 11:06:17 +05303320 // If output2 enabled, exit video thread, invoke stop recording ioctl
Mohan Kandraf1ebf982010-02-02 15:25:43 -08003321 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05303322 mVideoThreadWaitLock.lock();
3323 mVideoThreadExit = 1;
3324 mVideoThreadWaitLock.unlock();
3325 native_stop_recording(mCameraControlFd);
Srinivasan Kannanfc3915c2010-03-18 10:54:40 -07003326
3327 pthread_mutex_lock(&(g_busy_frame_queue.mut));
3328 pthread_cond_signal(&(g_busy_frame_queue.wait));
3329 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
Sravankb4f5f1c2010-01-21 11:06:17 +05303330 }
3331 else // for other targets where output2 is not enabled
3332 stopPreviewInternal();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003333
Sravankb4f5f1c2010-01-21 11:06:17 +05303334 recordingState = 0; // recording not started
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003335 LOGV("stopRecording: X");
3336}
3337
3338void QualcommCameraHardware::releaseRecordingFrame(
3339 const sp<IMemory>& mem __attribute__((unused)))
3340{
3341 LOGV("releaseRecordingFrame E");
3342 Mutex::Autolock rLock(&mRecordFrameLock);
3343 mReleasedRecordingFrame = true;
3344 mRecordWait.signal();
Sravankb4f5f1c2010-01-21 11:06:17 +05303345
3346 // Ff 7x30 : add the frame to the free camframe queue
Mohan Kandraf1ebf982010-02-02 15:25:43 -08003347 if( (mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05303348 ssize_t offset;
3349 size_t size;
3350 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
3351 msm_frame* releaseframe = NULL;
3352 LOGV(" in release recording frame : heap base %d offset %d buffer %d ", heap->base(), offset, heap->base() + offset );
3353 int cnt;
3354 for (cnt = 0; cnt < kRecordBufferCount; cnt++) {
3355 if((unsigned int)recordframes[cnt].buffer == (unsigned int)(heap->base()+ offset)){
3356 LOGV("in release recording frame found match , releasing buffer %d", (unsigned int)recordframes[cnt].buffer);
3357 releaseframe = &recordframes[cnt];
3358 break;
3359 }
3360 }
3361 if(cnt < kRecordBufferCount) {
3362 // do this only if frame thread is running
3363 mFrameThreadWaitLock.lock();
3364 if(mFrameThreadRunning )
3365 LINK_camframe_free_video(releaseframe);
3366
3367 mFrameThreadWaitLock.unlock();
3368 } else {
3369 LOGE("in release recordingframe XXXXX error , buffer not found");
3370 for (int i=0; i< kRecordBufferCount; i++) {
3371 LOGE(" recordframes[%d].buffer = %d", i, (unsigned int)recordframes[i].buffer);
3372 }
3373 }
3374 }
3375
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003376 LOGV("releaseRecordingFrame X");
3377}
3378
3379bool QualcommCameraHardware::recordingEnabled()
3380{
3381 return mCameraRunning && mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME);
3382}
3383
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08003384void QualcommCameraHardware::notifyShutter(common_crop_t *crop, bool mPlayShutterSoundOnly)
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003385{
3386 mShutterLock.lock();
3387 image_rect_type size;
3388
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08003389 if(mPlayShutterSoundOnly) {
3390 /* At this point, invoke Notify Callback to play shutter sound only.
3391 * We want to call notify callback again when we have the
3392 * yuv picture ready. This is to reduce blanking at the time
3393 * of displaying postview frame. Using ext2 to indicate whether
3394 * to play shutter sound only or register the postview buffers.
3395 */
3396 mNotifyCallback(CAMERA_MSG_SHUTTER, 0, mPlayShutterSoundOnly,
3397 mCallbackCookie);
3398 mShutterLock.unlock();
3399 return;
3400 }
3401
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003402 if (mShutterPending && mNotifyCallback && (mMsgEnabled & CAMERA_MSG_SHUTTER)) {
3403 LOGV("out2_w=%d, out2_h=%d, in2_w=%d, in2_h=%d",
3404 crop->out2_w, crop->out2_h, crop->in2_w, crop->in2_h);
3405 LOGV("out1_w=%d, out1_h=%d, in1_w=%d, in1_h=%d",
3406 crop->out1_w, crop->out1_h, crop->in1_w, crop->in1_h);
3407
3408 // To workaround a bug in MDP which happens if either
3409 // dimension > 2048, we display the thumbnail instead.
3410 mDisplayHeap = mRawHeap;
3411 if (crop->in1_w == 0 || crop->in1_h == 0) {
3412 // Full size
3413 size.width = mDimension.picture_width;
3414 size.height = mDimension.picture_height;
3415 if (size.width > 2048 || size.height > 2048) {
3416 size.width = mDimension.ui_thumbnail_width;
3417 size.height = mDimension.ui_thumbnail_height;
3418 mDisplayHeap = mThumbnailHeap;
3419 }
3420 } else {
3421 // Cropped
Apurva Rajgurua8b1fc92010-01-27 20:03:55 -08003422 size.width = (crop->in2_w + JPEG_ENCODER_PADDING) & ~1;
3423 size.height = (crop->in2_h + JPEG_ENCODER_PADDING) & ~1;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003424 if (size.width > 2048 || size.height > 2048) {
Apurva Rajgurua8b1fc92010-01-27 20:03:55 -08003425 size.width = (crop->in1_w + JPEG_ENCODER_PADDING) & ~1;
3426 size.height = (crop->in1_h + JPEG_ENCODER_PADDING) & ~1;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003427 mDisplayHeap = mThumbnailHeap;
3428 }
3429 }
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08003430 /* Now, invoke Notify Callback to unregister preview buffer
3431 * and register postview buffer with surface flinger. Set ext2
3432 * as 0 to indicate not to play shutter sound.
3433 */
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003434 mNotifyCallback(CAMERA_MSG_SHUTTER, (int32_t)&size, 0,
3435 mCallbackCookie);
3436 mShutterPending = false;
3437 }
3438 mShutterLock.unlock();
3439}
3440
3441static void receive_shutter_callback(common_crop_t *crop)
3442{
3443 LOGV("receive_shutter_callback: E");
3444 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
3445 if (obj != 0) {
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08003446 /* Just play shutter sound at this time */
3447 obj->notifyShutter(crop, TRUE);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003448 }
3449 LOGV("receive_shutter_callback: X");
3450}
3451
3452// Crop the picture in place.
3453static void crop_yuv420(uint32_t width, uint32_t height,
3454 uint32_t cropped_width, uint32_t cropped_height,
3455 uint8_t *image)
3456{
3457 uint32_t i, x, y;
3458 uint8_t* chroma_src, *chroma_dst;
3459
3460 // Calculate the start position of the cropped area.
3461 x = (width - cropped_width) / 2;
3462 y = (height - cropped_height) / 2;
3463 x &= ~1;
3464 y &= ~1;
3465
3466 // Copy luma component.
3467 for(i = 0; i < cropped_height; i++)
3468 memcpy(image + i * cropped_width,
3469 image + width * (y + i) + x,
3470 cropped_width);
3471
3472 chroma_src = image + width * height;
3473 chroma_dst = image + cropped_width * cropped_height;
3474
3475 // Copy chroma components.
3476 cropped_height /= 2;
3477 y /= 2;
3478 for(i = 0; i < cropped_height; i++)
3479 memcpy(chroma_dst + i * cropped_width,
3480 chroma_src + width * (y + i) + x,
3481 cropped_width);
3482}
3483
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08003484
3485void QualcommCameraHardware::receiveRawSnapshot(){
3486 LOGV("receiveRawSnapshot E");
3487
3488 Mutex::Autolock cbLock(&mCallbackLock);
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08003489 /* Issue notifyShutter with mPlayShutterSoundOnly as TRUE */
3490 notifyShutter(&mCrop, TRUE);
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08003491
3492 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
3493
3494 if(native_get_picture(mCameraControlFd, &mCrop) == false) {
3495 LOGE("receiveRawSnapshot X: native_get_picture failed!");
3496 return;
3497 }
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08003498 /* Its necessary to issue another notifyShutter here with
3499 * mPlayShutterSoundOnly as FALSE, since that is when the
3500 * preview buffers are unregistered with the surface flinger.
3501 * That is necessary otherwise the preview memory wont be
3502 * deallocated.
3503 */
3504 notifyShutter(&mCrop, FALSE);
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08003505
3506 //Create a Ashmem heap to copy data from PMem heap for application layer
3507 if(mRawSnapshotAshmemHeap != NULL){
3508 LOGV("receiveRawSnapshot: clearing old mRawSnapShotAshmemHeap.");
3509 mRawSnapshotAshmemHeap.clear();
3510 }
3511 mRawSnapshotAshmemHeap = new AshmemPool(
3512 mRawSnapShotPmemHeap->mBufferSize,
3513 mRawSnapShotPmemHeap->mNumBuffers,
3514 mRawSnapShotPmemHeap->mFrameSize,
3515 "raw ashmem snapshot camera"
3516 );
3517
3518 if(!mRawSnapshotAshmemHeap->initialized()){
3519 LOGE("receiveRawSnapshot X: error initializing mRawSnapshotHeap");
3520 deinitRawSnapshot();
3521 return;
3522 }
3523
3524 memcpy(mRawSnapshotAshmemHeap->mHeap->base(),
3525 mRawSnapShotPmemHeap->mHeap->base(),
3526 mRawSnapShotPmemHeap->mHeap->getSize());
Nishant Panditb861be52010-03-02 16:43:49 +05303527 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE))
3528 mDataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mRawSnapshotAshmemHeap->mBuffers[0],
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08003529 mCallbackCookie);
3530
3531 }
3532
3533 //cleanup
3534 deinitRawSnapshot();
3535
3536 LOGV("receiveRawSnapshot X");
3537}
3538
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003539void QualcommCameraHardware::receiveRawPicture()
3540{
3541 LOGV("receiveRawPicture: E");
3542
3543 Mutex::Autolock cbLock(&mCallbackLock);
3544 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_RAW_IMAGE)) {
3545 if(native_get_picture(mCameraControlFd, &mCrop) == false) {
3546 LOGE("getPicture failed!");
3547 return;
3548 }
3549 mCrop.in1_w &= ~1;
3550 mCrop.in1_h &= ~1;
3551 mCrop.in2_w &= ~1;
3552 mCrop.in2_h &= ~1;
3553
3554 // By the time native_get_picture returns, picture is taken. Call
3555 // shutter callback if cam config thread has not done that.
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08003556 notifyShutter(&mCrop, FALSE);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003557
3558 // Crop the image if zoomed.
3559 if (mCrop.in2_w != 0 && mCrop.in2_h != 0) {
Apurva Rajgurua8b1fc92010-01-27 20:03:55 -08003560 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 -08003561 (uint8_t *)mRawHeap->mHeap->base());
Apurva Rajgurua8b1fc92010-01-27 20:03:55 -08003562 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 -08003563 (uint8_t *)mThumbnailHeap->mHeap->base());
3564 // We do not need jpeg encoder to upscale the image. Set the new
3565 // dimension for encoder.
Apurva Rajgurua8b1fc92010-01-27 20:03:55 -08003566 mDimension.orig_picture_dx = mCrop.in2_w + JPEG_ENCODER_PADDING;
3567 mDimension.orig_picture_dy = mCrop.in2_h + JPEG_ENCODER_PADDING;
3568 mDimension.thumbnail_width = mCrop.in1_w + JPEG_ENCODER_PADDING;
3569 mDimension.thumbnail_height = mCrop.in1_h + JPEG_ENCODER_PADDING;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003570 }
3571
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003572 if( mUseOverlay && (mOverlay != NULL) ) {
3573 mOverlay->setFd(mPostViewHeap->mHeap->getHeapID());
3574 if( zoomCropInfo.w !=0 && zoomCropInfo.h !=0) {
3575 LOGD(" zoomCropInfo non-zero, setting crop ");
3576 mOverlay->setCrop(zoomCropInfo.x, zoomCropInfo.y,
3577 zoomCropInfo.w, zoomCropInfo.h);
3578 }
3579 LOGD(" Queueing Postview for display ");
3580 mOverlay->queueBuffer((void *)0);
3581 }
Nishant Panditb861be52010-03-02 16:43:49 +05303582 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_RAW_IMAGE))
3583 mDataCallback(CAMERA_MSG_RAW_IMAGE, mDisplayHeap->mBuffers[0],
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003584 mCallbackCookie);
3585 }
3586 else LOGV("Raw-picture callback was canceled--skipping.");
3587
3588 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
3589 mJpegSize = 0;
3590 if (LINK_jpeg_encoder_init()) {
3591 if(native_jpeg_encode()) {
3592 LOGV("receiveRawPicture: X (success)");
3593 return;
3594 }
3595 LOGE("jpeg encoding failed");
3596 }
3597 else LOGE("receiveRawPicture X: jpeg_encoder_init failed.");
3598 }
3599 else LOGV("JPEG callback is NULL, not encoding image.");
3600 deinitRaw();
3601 LOGV("receiveRawPicture: X");
3602}
3603
3604void QualcommCameraHardware::receiveJpegPictureFragment(
3605 uint8_t *buff_ptr, uint32_t buff_size)
3606{
3607 uint32_t remaining = mJpegHeap->mHeap->virtualSize();
3608 remaining -= mJpegSize;
3609 uint8_t *base = (uint8_t *)mJpegHeap->mHeap->base();
3610
3611 LOGV("receiveJpegPictureFragment size %d", buff_size);
3612 if (buff_size > remaining) {
3613 LOGE("receiveJpegPictureFragment: size %d exceeds what "
3614 "remains in JPEG heap (%d), truncating",
3615 buff_size,
3616 remaining);
3617 buff_size = remaining;
3618 }
3619 memcpy(base + mJpegSize, buff_ptr, buff_size);
3620 mJpegSize += buff_size;
3621}
3622
3623void QualcommCameraHardware::receiveJpegPicture(void)
3624{
3625 LOGV("receiveJpegPicture: E image (%d uint8_ts out of %d)",
3626 mJpegSize, mJpegHeap->mBufferSize);
3627 Mutex::Autolock cbLock(&mCallbackLock);
3628
3629 int index = 0, rc;
3630
3631 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
3632 // The reason we do not allocate into mJpegHeap->mBuffers[offset] is
3633 // that the JPEG image's size will probably change from one snapshot
3634 // to the next, so we cannot reuse the MemoryBase object.
3635 sp<MemoryBase> buffer = new
3636 MemoryBase(mJpegHeap->mHeap,
3637 index * mJpegHeap->mBufferSize +
3638 0,
3639 mJpegSize);
3640 mDataCallback(CAMERA_MSG_COMPRESSED_IMAGE, buffer, mCallbackCookie);
3641 buffer = NULL;
3642 }
3643 else LOGV("JPEG callback was cancelled--not delivering image.");
3644
3645 LINK_jpeg_encoder_join();
3646 deinitRaw();
3647
3648 LOGV("receiveJpegPicture: X callback done.");
3649}
3650
3651bool QualcommCameraHardware::previewEnabled()
3652{
3653 return mCameraRunning && mDataCallback && (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME);
3654}
3655
3656status_t QualcommCameraHardware::setPreviewSize(const CameraParameters& params)
3657{
3658 int width, height;
3659 params.getPreviewSize(&width, &height);
3660 LOGV("requested preview size %d x %d", width, height);
3661
3662 // Validate the preview size
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -08003663 for (size_t i = 0; i < previewSizeCount; ++i) {
3664 if (width == supportedPreviewSizes[i].width
3665 && height == supportedPreviewSizes[i].height) {
Sravank64461e82010-02-25 15:10:09 +05303666 // 720p , preview can be 768X432 (currently for 7x30 and 8k
3667 // targets)
3668 if(width == 1280 && height == 720 &&
3669 ((mCurrentTarget == TARGET_MSM7630) || (mCurrentTarget == TARGET_QSD8250))){
3670 LOGD("change preview resolution to 768X432 since recording is in 720p");
3671 mDimension.display_width = preview_sizes[2].width;
3672 mDimension.display_height= preview_sizes[2].height;
3673 }else {
3674 mDimension.display_width = width;
3675 mDimension.display_height= height;
3676 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003677 mParameters.setPreviewSize(width, height);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003678 return NO_ERROR;
3679 }
3680 }
3681 LOGE("Invalid preview size requested: %dx%d", width, height);
3682 return BAD_VALUE;
3683}
3684
3685status_t QualcommCameraHardware::setPictureSize(const CameraParameters& params)
3686{
3687 int width, height;
3688 params.getPictureSize(&width, &height);
3689 LOGV("requested picture size %d x %d", width, height);
3690
3691 // Validate the picture size
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -08003692 for (int i = 0; i < supportedPictureSizesCount; ++i) {
3693 if (width == picture_sizes_ptr[i].width
3694 && height == picture_sizes_ptr[i].height) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003695 mParameters.setPictureSize(width, height);
3696 mDimension.picture_width = width;
3697 mDimension.picture_height = height;
3698 return NO_ERROR;
3699 }
3700 }
Kiran Kumar H Nb49af212010-02-17 15:12:17 -08003701 /* Dimension not among the ones in the list. Check if
3702 * its a valid dimension, if it is, then configure the
3703 * camera accordingly. else reject it.
3704 */
3705 if( isValidDimension(width, height) ) {
3706 mParameters.setPictureSize(width, height);
3707 mDimension.picture_width = width;
3708 mDimension.picture_height = height;
3709 return NO_ERROR;
3710 } else
3711 LOGE("Invalid picture size requested: %dx%d", width, height);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003712 return BAD_VALUE;
3713}
3714
3715status_t QualcommCameraHardware::setJpegQuality(const CameraParameters& params) {
3716 status_t rc = NO_ERROR;
3717 int quality = params.getInt(CameraParameters::KEY_JPEG_QUALITY);
3718 if (quality > 0 && quality <= 100) {
3719 mParameters.set(CameraParameters::KEY_JPEG_QUALITY, quality);
3720 } else {
3721 LOGE("Invalid jpeg quality=%d", quality);
3722 rc = BAD_VALUE;
3723 }
3724
3725 quality = params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY);
3726 if (quality > 0 && quality <= 100) {
3727 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, quality);
3728 } else {
3729 LOGE("Invalid jpeg thumbnail quality=%d", quality);
3730 rc = BAD_VALUE;
3731 }
3732 return rc;
3733}
3734
3735status_t QualcommCameraHardware::setEffect(const CameraParameters& params)
3736{
Apurva Rajguru7360db42010-04-09 16:37:36 -07003737
3738 const char *str_wb = mParameters.get(CameraParameters::KEY_WHITE_BALANCE);
3739 int32_t value_wb = attr_lookup(whitebalance, sizeof(whitebalance) / sizeof(str_map), str_wb);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003740 const char *str = params.get(CameraParameters::KEY_EFFECT);
Apurva Rajguru7360db42010-04-09 16:37:36 -07003741
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003742 if (str != NULL) {
3743 int32_t value = attr_lookup(effects, sizeof(effects) / sizeof(str_map), str);
3744 if (value != NOT_FOUND) {
Mohan Kandra93f1bfb2009-12-15 16:55:33 -08003745 if(!strcmp(sensorType->name, "2mp") && (value != CAMERA_EFFECT_OFF)
3746 &&(value != CAMERA_EFFECT_MONO) && (value != CAMERA_EFFECT_NEGATIVE)
3747 &&(value != CAMERA_EFFECT_SOLARIZE) && (value != CAMERA_EFFECT_SEPIA)) {
3748 LOGE("Special effect parameter is not supported for this sensor");
3749 return NO_ERROR;
3750 }
Apurva Rajguru7360db42010-04-09 16:37:36 -07003751
3752 if(((value == CAMERA_EFFECT_MONO) || (value == CAMERA_EFFECT_NEGATIVE)
3753 || (value == CAMERA_EFFECT_AQUA) || (value == CAMERA_EFFECT_SEPIA))
3754 && (value_wb != CAMERA_WB_AUTO)) {
3755 LOGE("Color Effect value will not be set " \
3756 "when the whitebalance selected is %s", str_wb);
3757 return NO_ERROR;
3758 }
3759 else {
3760 mParameters.set(CameraParameters::KEY_EFFECT, str);
3761 bool ret = native_set_parm(CAMERA_SET_PARM_EFFECT, sizeof(value),
3762 (void *)&value);
3763 return ret ? NO_ERROR : UNKNOWN_ERROR;
3764 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003765 }
3766 }
3767 LOGE("Invalid effect value: %s", (str == NULL) ? "NULL" : str);
3768 return BAD_VALUE;
3769}
3770
Apurva Rajguru55562b02009-12-03 12:25:35 -08003771status_t QualcommCameraHardware::setAutoExposure(const CameraParameters& params)
3772{
Mohan Kandra93f1bfb2009-12-15 16:55:33 -08003773 if(!strcmp(sensorType->name, "2mp")) {
3774 LOGE("Auto Exposure not supported for this sensor");
3775 return NO_ERROR;
3776 }
Apurva Rajguru55562b02009-12-03 12:25:35 -08003777 const char *str = params.get(CameraParameters::KEY_AUTO_EXPOSURE);
3778 if (str != NULL) {
3779 int32_t value = attr_lookup(autoexposure, sizeof(autoexposure) / sizeof(str_map), str);
3780 if (value != NOT_FOUND) {
3781 mParameters.set(CameraParameters::KEY_AUTO_EXPOSURE, str);
3782 bool ret = native_set_parm(CAMERA_SET_PARM_EXPOSURE, sizeof(value),
3783 (void *)&value);
3784 return ret ? NO_ERROR : UNKNOWN_ERROR;
3785 }
3786 }
3787 LOGE("Invalid auto exposure value: %s", (str == NULL) ? "NULL" : str);
3788 return BAD_VALUE;
3789}
3790
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003791status_t QualcommCameraHardware::setSharpness(const CameraParameters& params)
3792{
3793 if(!strcmp(sensorType->name, "2mp")) {
3794 LOGE("Sharpness not supported for this sensor");
3795 return NO_ERROR;
3796 }
3797 int sharpness = params.getInt(CameraParameters::KEY_SHARPNESS);
3798 if((sharpness < CAMERA_MIN_SHARPNESS
3799 || sharpness > CAMERA_MAX_SHARPNESS))
3800 return UNKNOWN_ERROR;
Srinivasan Kannan551fd262010-01-14 17:48:30 -08003801
3802 LOGV("setting sharpness %d", sharpness);
3803 mParameters.set(CameraParameters::KEY_SHARPNESS, sharpness);
3804 bool ret = native_set_parm(CAMERA_SET_PARM_SHARPNESS, sizeof(sharpness),
3805 (void *)&sharpness);
3806 return ret ? NO_ERROR : UNKNOWN_ERROR;
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003807}
3808
3809status_t QualcommCameraHardware::setContrast(const CameraParameters& params)
3810{
3811 if(!strcmp(sensorType->name, "2mp")) {
3812 LOGE("Contrast not supported for this sensor");
3813 return NO_ERROR;
3814 }
3815 int contrast = params.getInt(CameraParameters::KEY_CONTRAST);
3816 if((contrast < CAMERA_MIN_CONTRAST)
3817 || (contrast > CAMERA_MAX_CONTRAST))
3818 return UNKNOWN_ERROR;
Srinivasan Kannan551fd262010-01-14 17:48:30 -08003819
3820 LOGV("setting contrast %d", contrast);
3821 mParameters.set(CameraParameters::KEY_CONTRAST, contrast);
3822 bool ret = native_set_parm(CAMERA_SET_PARM_CONTRAST, sizeof(contrast),
3823 (void *)&contrast);
3824 return ret ? NO_ERROR : UNKNOWN_ERROR;
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003825}
3826
3827status_t QualcommCameraHardware::setSaturation(const CameraParameters& params)
3828{
3829 if(!strcmp(sensorType->name, "2mp")) {
3830 LOGE("Saturation not supported for this sensor");
3831 return NO_ERROR;
3832 }
Srinivasan Kannan551fd262010-01-14 17:48:30 -08003833
Kiran Kumar H Nf87cf862010-01-27 14:34:34 -08003834 const char *str = params.get(CameraParameters::KEY_EFFECT);
3835 int32_t value = attr_lookup(effects, sizeof(effects) / sizeof(str_map), str);
3836
3837 if( (value != CAMERA_EFFECT_MONO) && (value != CAMERA_EFFECT_NEGATIVE)
3838 && (value != CAMERA_EFFECT_AQUA) && (value != CAMERA_EFFECT_SEPIA)) {
3839
3840 int saturation = params.getInt(CameraParameters::KEY_SATURATION);
3841 if((saturation < CAMERA_MIN_SATURATION)
3842 || (saturation > CAMERA_MAX_SATURATION))
3843 return UNKNOWN_ERROR;
3844
3845 LOGV("setting saturation %d", saturation);
3846 mParameters.set(CameraParameters::KEY_SATURATION, saturation);
3847 bool ret = native_set_parm(CAMERA_SET_PARM_SATURATION, sizeof(saturation),
3848 (void *)&saturation);
3849 return ret ? NO_ERROR : UNKNOWN_ERROR;
3850 } else {
3851 LOGE(" Saturation value will not be set " \
3852 "when the effect selected is %s", str);
3853 return NO_ERROR;
3854 }
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003855}
3856
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303857status_t QualcommCameraHardware::setBrightness(const CameraParameters& params) {
3858 int brightness = params.getInt("luma-adaptation");
3859 if (mBrightness != brightness) {
3860 LOGV(" new brightness value : %d ", brightness);
3861 mBrightness = brightness;
3862
3863 bool ret = native_set_parm(CAMERA_SET_PARM_BRIGHTNESS, sizeof(mBrightness),
3864 (void *)&mBrightness);
3865 return ret ? NO_ERROR : UNKNOWN_ERROR;
3866 } else {
3867 return NO_ERROR;
3868 }
3869}
3870
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003871status_t QualcommCameraHardware::setWhiteBalance(const CameraParameters& params)
3872{
Apurva Rajguru7360db42010-04-09 16:37:36 -07003873
3874 const char *str_effect = mParameters.get(CameraParameters::KEY_EFFECT);
3875 int32_t value_effect = attr_lookup(effects, sizeof(effects) / sizeof(str_map), str_effect);
3876
3877 if( (value_effect != CAMERA_EFFECT_MONO) && (value_effect != CAMERA_EFFECT_NEGATIVE)
3878 && (value_effect != CAMERA_EFFECT_AQUA) && (value_effect != CAMERA_EFFECT_SEPIA)) {
3879 const char *str = params.get(CameraParameters::KEY_WHITE_BALANCE);
3880
3881 if (str != NULL) {
3882 int32_t value = attr_lookup(whitebalance, sizeof(whitebalance) / sizeof(str_map), str);
3883 if (value != NOT_FOUND) {
3884 mParameters.set(CameraParameters::KEY_WHITE_BALANCE, str);
3885 bool ret = native_set_parm(CAMERA_SET_PARM_WB, sizeof(value),
3886 (void *)&value);
3887 return ret ? NO_ERROR : UNKNOWN_ERROR;
3888 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003889 }
Apurva Rajguru7360db42010-04-09 16:37:36 -07003890 LOGE("Invalid whitebalance value: %s", (str == NULL) ? "NULL" : str);
3891 return BAD_VALUE;
3892 } else {
3893 LOGE("Whitebalance value will not be set " \
3894 "when the effect selected is %s", str_effect);
3895 return NO_ERROR;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003896 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003897}
3898
3899status_t QualcommCameraHardware::setFlash(const CameraParameters& params)
3900{
3901 if (!mSensorInfo.flash_enabled) {
3902 LOGV("%s: flash not supported", __FUNCTION__);
3903 return NO_ERROR;
3904 }
3905
3906 const char *str = params.get(CameraParameters::KEY_FLASH_MODE);
3907 if (str != NULL) {
3908 int32_t value = attr_lookup(flash, sizeof(flash) / sizeof(str_map), str);
3909 if (value != NOT_FOUND) {
3910 mParameters.set(CameraParameters::KEY_FLASH_MODE, str);
3911 bool ret = native_set_parm(CAMERA_SET_PARM_LED_MODE,
3912 sizeof(value), (void *)&value);
3913 return ret ? NO_ERROR : UNKNOWN_ERROR;
3914 }
3915 }
3916 LOGE("Invalid flash mode value: %s", (str == NULL) ? "NULL" : str);
3917 return BAD_VALUE;
3918}
3919
3920status_t QualcommCameraHardware::setAntibanding(const CameraParameters& params)
3921{
Srinivasan Kannan2229d272010-01-05 14:58:28 -08003922 if(!strcmp(sensorType->name, "2mp")) {
3923 LOGE("Parameter AntiBanding is not supported for this sensor");
3924 return NO_ERROR;
3925 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003926 const char *str = params.get(CameraParameters::KEY_ANTIBANDING);
3927 if (str != NULL) {
3928 int value = (camera_antibanding_type)attr_lookup(
3929 antibanding, sizeof(antibanding) / sizeof(str_map), str);
3930 if (value != NOT_FOUND) {
3931 camera_antibanding_type temp = (camera_antibanding_type) value;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003932 mParameters.set(CameraParameters::KEY_ANTIBANDING, str);
Srinivasan Kannan2229d272010-01-05 14:58:28 -08003933 bool ret;
3934 if (temp == CAMERA_ANTIBANDING_AUTO) {
3935 ret = native_set_parm(CAMERA_ENABLE_AFD,
3936 0, NULL);
3937 } else {
3938 ret = native_set_parm(CAMERA_SET_PARM_ANTIBANDING,
3939 sizeof(camera_antibanding_type), (void *)&temp);
3940 }
3941 return ret ? NO_ERROR : UNKNOWN_ERROR;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003942 }
3943 }
3944 LOGE("Invalid antibanding value: %s", (str == NULL) ? "NULL" : str);
3945 return BAD_VALUE;
3946}
3947
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303948status_t QualcommCameraHardware::setLensshadeValue(const CameraParameters& params)
3949{
Mohan Kandra93f1bfb2009-12-15 16:55:33 -08003950 if(!strcmp(sensorType->name, "2mp")) {
3951 LOGE("Parameter Rolloff is not supported for this sensor");
3952 return NO_ERROR;
3953 }
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303954 const char *str = params.get(CameraParameters::KEY_LENSSHADE);
3955 if (str != NULL) {
3956 int value = attr_lookup(lensshade,
3957 sizeof(lensshade) / sizeof(str_map), str);
3958 if (value != NOT_FOUND) {
3959 int8_t temp = (int8_t)value;
3960 mParameters.set(CameraParameters::KEY_LENSSHADE, str);
3961 native_set_parm(CAMERA_SET_PARM_ROLLOFF, sizeof(int8_t), (void *)&temp);
3962 return NO_ERROR;
3963 }
3964 }
3965 LOGE("Invalid lensShade value: %s", (str == NULL) ? "NULL" : str);
3966 return BAD_VALUE;
3967}
3968
3969status_t QualcommCameraHardware::setISOValue(const CameraParameters& params) {
Apurva Rajguruf12d9d22010-04-05 16:47:12 -07003970 int8_t temp_hjr;
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303971 const char *str = params.get(CameraParameters::KEY_ISO_MODE);
3972 if (str != NULL) {
3973 int value = (camera_iso_mode_type)attr_lookup(
3974 iso, sizeof(iso) / sizeof(str_map), str);
3975 if (value != NOT_FOUND) {
3976 camera_iso_mode_type temp = (camera_iso_mode_type) value;
Apurva Rajguruf12d9d22010-04-05 16:47:12 -07003977 if (value == CAMERA_ISO_DEBLUR) {
3978 temp_hjr = true;
3979 native_set_parm(CAMERA_SET_PARM_HJR, sizeof(int8_t), (void*)&temp_hjr);
3980 mHJR = value;
3981 }
3982 else {
3983 if (mHJR == CAMERA_ISO_DEBLUR) {
3984 temp_hjr = false;
3985 native_set_parm(CAMERA_SET_PARM_HJR, sizeof(int8_t), (void*)&temp_hjr);
3986 mHJR = value;
3987 }
3988 }
3989
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303990 mParameters.set(CameraParameters::KEY_ISO_MODE, str);
3991 native_set_parm(CAMERA_SET_PARM_ISO, sizeof(camera_iso_mode_type), (void *)&temp);
3992 return NO_ERROR;
3993 }
3994 }
3995 LOGE("Invalid Iso value: %s", (str == NULL) ? "NULL" : str);
3996 return BAD_VALUE;
3997}
3998
3999
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004000status_t QualcommCameraHardware::setGpsLocation(const CameraParameters& params)
4001{
4002 const char *latitude = params.get(CameraParameters::KEY_GPS_LATITUDE);
4003 if (latitude) {
4004 mParameters.set(CameraParameters::KEY_GPS_LATITUDE, latitude);
4005 }
4006
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08004007 const char *latitudeRef = params.get(CameraParameters::KEY_GPS_LATITUDE_REF);
4008 if (latitudeRef) {
4009 mParameters.set(CameraParameters::KEY_GPS_LATITUDE_REF, latitudeRef);
4010 }
4011
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004012 const char *longitude = params.get(CameraParameters::KEY_GPS_LONGITUDE);
4013 if (longitude) {
4014 mParameters.set(CameraParameters::KEY_GPS_LONGITUDE, longitude);
4015 }
4016
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08004017 const char *longitudeRef = params.get(CameraParameters::KEY_GPS_LONGITUDE_REF);
4018 if (longitudeRef) {
4019 mParameters.set(CameraParameters::KEY_GPS_LONGITUDE_REF, longitudeRef);
4020 }
4021
4022 const char *altitudeRef = params.get(CameraParameters::KEY_GPS_ALTITUDE_REF);
4023 if (altitudeRef) {
4024 mParameters.set(CameraParameters::KEY_GPS_ALTITUDE_REF, altitudeRef);
4025 }
4026
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004027 const char *altitude = params.get(CameraParameters::KEY_GPS_ALTITUDE);
4028 if (altitude) {
4029 mParameters.set(CameraParameters::KEY_GPS_ALTITUDE, altitude);
4030 }
4031
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08004032 const char *status = params.get(CameraParameters::KEY_GPS_STATUS);
4033 if (status) {
4034 mParameters.set(CameraParameters::KEY_GPS_STATUS, status);
4035 }
4036
4037 const char *dateTime = params.get(CameraParameters::KEY_EXIF_DATETIME);
4038 if (dateTime) {
4039 mParameters.set(CameraParameters::KEY_EXIF_DATETIME, dateTime);
4040 }
4041
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004042 const char *timestamp = params.get(CameraParameters::KEY_GPS_TIMESTAMP);
4043 if (timestamp) {
4044 mParameters.set(CameraParameters::KEY_GPS_TIMESTAMP, timestamp);
4045 }
4046 return NO_ERROR;
4047}
4048
4049status_t QualcommCameraHardware::setRotation(const CameraParameters& params)
4050{
4051 status_t rc = NO_ERROR;
4052 int rotation = params.getInt(CameraParameters::KEY_ROTATION);
4053 if (rotation != NOT_FOUND) {
4054 if (rotation == 0 || rotation == 90 || rotation == 180
4055 || rotation == 270) {
4056 mParameters.set(CameraParameters::KEY_ROTATION, rotation);
4057 } else {
4058 LOGE("Invalid rotation value: %d", rotation);
4059 rc = BAD_VALUE;
4060 }
4061 }
4062 return rc;
4063}
4064
4065status_t QualcommCameraHardware::setZoom(const CameraParameters& params)
4066{
4067 status_t rc = NO_ERROR;
4068 // No matter how many different zoom values the driver can provide, HAL
4069 // provides applictations the same number of zoom levels. The maximum driver
4070 // zoom value depends on sensor output (VFE input) and preview size (VFE
4071 // output) because VFE can only crop and cannot upscale. If the preview size
4072 // is bigger, the maximum zoom ratio is smaller. However, we want the
4073 // zoom ratio of each zoom level is always the same whatever the preview
4074 // size is. Ex: zoom level 1 is always 1.2x, zoom level 2 is 1.44x, etc. So,
4075 // we need to have a fixed maximum zoom value and do read it from the
4076 // driver.
Mohan Kandra284966d2010-01-05 13:39:15 -08004077 static const int ZOOM_STEP = 1;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004078 int32_t zoom_level = params.getInt("zoom");
4079
Mohan Kandra284966d2010-01-05 13:39:15 -08004080 LOGV("Set zoom=%d", zoom_level);
4081 if(zoom_level >= 0 && zoom_level <= mMaxZoom) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004082 mParameters.set("zoom", zoom_level);
4083 int32_t zoom_value = ZOOM_STEP * zoom_level;
4084 bool ret = native_set_parm(CAMERA_SET_PARM_ZOOM,
4085 sizeof(zoom_value), (void *)&zoom_value);
4086 rc = ret ? NO_ERROR : UNKNOWN_ERROR;
4087 } else {
4088 rc = BAD_VALUE;
4089 }
4090
4091 return rc;
4092}
4093
4094status_t QualcommCameraHardware::setFocusMode(const CameraParameters& params)
4095{
4096 const char *str = params.get(CameraParameters::KEY_FOCUS_MODE);
4097 if (str != NULL) {
4098 int32_t value = attr_lookup(focus_modes,
4099 sizeof(focus_modes) / sizeof(str_map), str);
4100 if (value != NOT_FOUND) {
4101 mParameters.set(CameraParameters::KEY_FOCUS_MODE, str);
4102 // Focus step is reset to infinity when preview is started. We do
4103 // not need to do anything now.
4104 return NO_ERROR;
4105 }
4106 }
4107 LOGE("Invalid focus mode value: %s", (str == NULL) ? "NULL" : str);
4108 return BAD_VALUE;
4109}
4110
4111status_t QualcommCameraHardware::setOrientation(const CameraParameters& params)
4112{
4113 const char *str = params.get("orientation");
4114
4115 if (str != NULL) {
4116 if (strcmp(str, "portrait") == 0 || strcmp(str, "landscape") == 0) {
4117 // Camera service needs this to decide if the preview frames and raw
4118 // pictures should be rotated.
4119 mParameters.set("orientation", str);
4120 } else {
4121 LOGE("Invalid orientation value: %s", str);
4122 return BAD_VALUE;
4123 }
4124 }
4125 return NO_ERROR;
4126}
4127
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08004128status_t QualcommCameraHardware::setPictureFormat(const CameraParameters& params)
4129{
4130 const char * str = params.get(CameraParameters::KEY_PICTURE_FORMAT);
4131
4132 if(str != NULL){
4133 int32_t value = attr_lookup(picture_formats,
4134 sizeof(picture_formats) / sizeof(str_map), str);
4135 if(value != NOT_FOUND){
4136 mParameters.set(CameraParameters::KEY_PICTURE_FORMAT, str);
4137 } else {
4138 LOGE("Invalid Picture Format value: %s", str);
4139 return BAD_VALUE;
4140 }
4141 }
4142 return NO_ERROR;
4143}
4144
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004145QualcommCameraHardware::MemPool::MemPool(int buffer_size, int num_buffers,
4146 int frame_size,
4147 const char *name) :
4148 mBufferSize(buffer_size),
4149 mNumBuffers(num_buffers),
4150 mFrameSize(frame_size),
4151 mBuffers(NULL), mName(name)
4152{
4153 int page_size_minus_1 = getpagesize() - 1;
4154 mAlignedBufferSize = (buffer_size + page_size_minus_1) & (~page_size_minus_1);
4155}
4156
4157void QualcommCameraHardware::MemPool::completeInitialization()
4158{
4159 // If we do not know how big the frame will be, we wait to allocate
4160 // the buffers describing the individual frames until we do know their
4161 // size.
4162
4163 if (mFrameSize > 0) {
4164 mBuffers = new sp<MemoryBase>[mNumBuffers];
4165 for (int i = 0; i < mNumBuffers; i++) {
4166 mBuffers[i] = new
4167 MemoryBase(mHeap,
4168 i * mAlignedBufferSize,
4169 mFrameSize);
4170 }
4171 }
4172}
4173
4174QualcommCameraHardware::AshmemPool::AshmemPool(int buffer_size, int num_buffers,
4175 int frame_size,
4176 const char *name) :
4177 QualcommCameraHardware::MemPool(buffer_size,
4178 num_buffers,
4179 frame_size,
4180 name)
4181{
4182 LOGV("constructing MemPool %s backed by ashmem: "
4183 "%d frames @ %d uint8_ts, "
4184 "buffer size %d",
4185 mName,
4186 num_buffers, frame_size, buffer_size);
4187
4188 int page_mask = getpagesize() - 1;
4189 int ashmem_size = buffer_size * num_buffers;
4190 ashmem_size += page_mask;
4191 ashmem_size &= ~page_mask;
4192
4193 mHeap = new MemoryHeapBase(ashmem_size);
4194
4195 completeInitialization();
4196}
4197
4198static bool register_buf(int camfd,
4199 int size,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08004200 int frame_size,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004201 int pmempreviewfd,
4202 uint32_t offset,
4203 uint8_t *buf,
4204 int pmem_type,
4205 bool vfe_can_write,
4206 bool register_buffer = true);
4207
4208QualcommCameraHardware::PmemPool::PmemPool(const char *pmem_pool,
4209 int flags,
4210 int camera_control_fd,
4211 int pmem_type,
4212 int buffer_size, int num_buffers,
4213 int frame_size,
4214 const char *name) :
4215 QualcommCameraHardware::MemPool(buffer_size,
4216 num_buffers,
4217 frame_size,
4218 name),
4219 mPmemType(pmem_type),
4220 mCameraControlFd(dup(camera_control_fd))
4221{
4222 LOGV("constructing MemPool %s backed by pmem pool %s: "
4223 "%d frames @ %d bytes, buffer size %d",
4224 mName,
4225 pmem_pool, num_buffers, frame_size,
4226 buffer_size);
4227
4228 LOGV("%s: duplicating control fd %d --> %d",
4229 __FUNCTION__,
4230 camera_control_fd, mCameraControlFd);
4231
4232 // Make a new mmap'ed heap that can be shared across processes.
4233 // mAlignedBufferSize is already in 4k aligned. (do we need total size necessary to be in power of 2??)
4234 mAlignedSize = mAlignedBufferSize * num_buffers;
4235
4236 sp<MemoryHeapBase> masterHeap =
4237 new MemoryHeapBase(pmem_pool, mAlignedSize, flags);
4238
4239 if (masterHeap->getHeapID() < 0) {
4240 LOGE("failed to construct master heap for pmem pool %s", pmem_pool);
4241 masterHeap.clear();
4242 return;
4243 }
4244
4245 sp<MemoryHeapPmem> pmemHeap = new MemoryHeapPmem(masterHeap, flags);
4246 if (pmemHeap->getHeapID() >= 0) {
4247 pmemHeap->slap();
4248 masterHeap.clear();
4249 mHeap = pmemHeap;
4250 pmemHeap.clear();
4251
4252 mFd = mHeap->getHeapID();
4253 if (::ioctl(mFd, PMEM_GET_SIZE, &mSize)) {
4254 LOGE("pmem pool %s ioctl(PMEM_GET_SIZE) error %s (%d)",
4255 pmem_pool,
4256 ::strerror(errno), errno);
4257 mHeap.clear();
4258 return;
4259 }
4260
4261 LOGV("pmem pool %s ioctl(fd = %d, PMEM_GET_SIZE) is %ld",
4262 pmem_pool,
4263 mFd,
4264 mSize.len);
Mohan Kandra284966d2010-01-05 13:39:15 -08004265 LOGD("mBufferSize=%d, mAlignedBufferSize=%d\n", mBufferSize, mAlignedBufferSize);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004266 // Unregister preview buffers with the camera drivers. Allow the VFE to write
4267 // to all preview buffers except for the last one.
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08004268 // Only Register the preview, snapshot and thumbnail buffers with the kernel.
Mohan Kandrad9efed92010-01-15 19:08:39 -08004269 if( (strcmp("postview", mName) != 0) ){
4270 int num_buf = num_buffers;
4271 if(!strcmp("preview", mName)) num_buf = kPreviewBufferCount;
Brian Steuerb62adbd2010-02-02 14:47:08 -08004272 LOGD("num_buffers = %d", num_buf);
Mohan Kandrad9efed92010-01-15 19:08:39 -08004273 for (int cnt = 0; cnt < num_buf; ++cnt) {
Sravankb4f5f1c2010-01-21 11:06:17 +05304274 int active = 1;
4275 if(pmem_type == MSM_PMEM_VIDEO){
4276 active = (cnt<ACTIVE_VIDEO_BUFFERS);
4277 LOGV(" pmempool creating video buffers : active %d ", active);
4278 }
4279 else if (pmem_type == MSM_PMEM_PREVIEW){
4280 active = (cnt < (num_buf-1));
4281 }
Mohan Kandra284966d2010-01-05 13:39:15 -08004282 register_buf(mCameraControlFd,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004283 mBufferSize,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08004284 mFrameSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004285 mHeap->getHeapID(),
4286 mAlignedBufferSize * cnt,
4287 (uint8_t *)mHeap->base() + mAlignedBufferSize * cnt,
4288 pmem_type,
Sravankb4f5f1c2010-01-21 11:06:17 +05304289 active);
Mohan Kandra284966d2010-01-05 13:39:15 -08004290 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004291 }
4292
4293 completeInitialization();
4294 }
4295 else LOGE("pmem pool %s error: could not create master heap!",
4296 pmem_pool);
4297}
4298
4299QualcommCameraHardware::PmemPool::~PmemPool()
4300{
4301 LOGV("%s: %s E", __FUNCTION__, mName);
4302 if (mHeap != NULL) {
4303 // Unregister preview buffers with the camera drivers.
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08004304 // Only Unregister the preview, snapshot and thumbnail
4305 // buffers with the kernel.
Mohan Kandrad9efed92010-01-15 19:08:39 -08004306 if( (strcmp("postview", mName) != 0) ){
4307 int num_buffers = mNumBuffers;
4308 if(!strcmp("preview", mName)) num_buffers = kPreviewBufferCount;
4309 for (int cnt = 0; cnt < num_buffers; ++cnt) {
Mohan Kandra284966d2010-01-05 13:39:15 -08004310 register_buf(mCameraControlFd,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004311 mBufferSize,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08004312 mFrameSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004313 mHeap->getHeapID(),
4314 mAlignedBufferSize * cnt,
4315 (uint8_t *)mHeap->base() + mAlignedBufferSize * cnt,
4316 mPmemType,
4317 false,
4318 false /* unregister */);
Mohan Kandra284966d2010-01-05 13:39:15 -08004319 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004320 }
4321 }
4322 LOGV("destroying PmemPool %s: closing control fd %d",
4323 mName,
4324 mCameraControlFd);
4325 close(mCameraControlFd);
4326 LOGV("%s: %s X", __FUNCTION__, mName);
4327}
4328
4329QualcommCameraHardware::MemPool::~MemPool()
4330{
4331 LOGV("destroying MemPool %s", mName);
4332 if (mFrameSize > 0)
4333 delete [] mBuffers;
4334 mHeap.clear();
4335 LOGV("destroying MemPool %s completed", mName);
4336}
4337
4338static bool register_buf(int camfd,
4339 int size,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08004340 int frame_size,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004341 int pmempreviewfd,
4342 uint32_t offset,
4343 uint8_t *buf,
4344 int pmem_type,
4345 bool vfe_can_write,
4346 bool register_buffer)
4347{
4348 struct msm_pmem_info pmemBuf;
4349
4350 pmemBuf.type = pmem_type;
4351 pmemBuf.fd = pmempreviewfd;
4352 pmemBuf.offset = offset;
4353 pmemBuf.len = size;
4354 pmemBuf.vaddr = buf;
4355 pmemBuf.y_off = 0;
Srinivasan Kannanb36a4fe2010-01-29 19:34:09 -08004356
4357 if(pmem_type == MSM_PMEM_RAW_MAINIMG)
4358 pmemBuf.cbcr_off = 0;
4359 else
4360 pmemBuf.cbcr_off = PAD_TO_WORD(frame_size * 2 / 3);
4361
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004362 pmemBuf.active = vfe_can_write;
4363
4364 LOGV("register_buf: camfd = %d, reg = %d buffer = %p",
4365 camfd, !register_buffer, buf);
4366 if (ioctl(camfd,
4367 register_buffer ?
4368 MSM_CAM_IOCTL_REGISTER_PMEM :
4369 MSM_CAM_IOCTL_UNREGISTER_PMEM,
4370 &pmemBuf) < 0) {
4371 LOGE("register_buf: MSM_CAM_IOCTL_(UN)REGISTER_PMEM fd %d error %s",
4372 camfd,
4373 strerror(errno));
4374 return false;
4375 }
4376 return true;
4377}
4378
4379status_t QualcommCameraHardware::MemPool::dump(int fd, const Vector<String16>& args) const
4380{
4381 const size_t SIZE = 256;
4382 char buffer[SIZE];
4383 String8 result;
4384 snprintf(buffer, 255, "QualcommCameraHardware::AshmemPool::dump\n");
4385 result.append(buffer);
4386 if (mName) {
4387 snprintf(buffer, 255, "mem pool name (%s)\n", mName);
4388 result.append(buffer);
4389 }
4390 if (mHeap != 0) {
4391 snprintf(buffer, 255, "heap base(%p), size(%d), flags(%d), device(%s)\n",
4392 mHeap->getBase(), mHeap->getSize(),
4393 mHeap->getFlags(), mHeap->getDevice());
4394 result.append(buffer);
4395 }
4396 snprintf(buffer, 255,
4397 "buffer size (%d), number of buffers (%d), frame size(%d)",
4398 mBufferSize, mNumBuffers, mFrameSize);
4399 result.append(buffer);
4400 write(fd, result.string(), result.size());
4401 return NO_ERROR;
4402}
4403
4404static void receive_camframe_callback(struct msm_frame *frame)
4405{
4406 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4407 if (obj != 0) {
4408 obj->receivePreviewFrame(frame);
4409 }
4410}
4411
4412static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size)
4413{
4414 LOGV("receive_jpeg_fragment_callback E");
4415 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4416 if (obj != 0) {
4417 obj->receiveJpegPictureFragment(buff_ptr, buff_size);
4418 }
4419 LOGV("receive_jpeg_fragment_callback X");
4420}
4421
4422static void receive_jpeg_callback(jpeg_event_t status)
4423{
4424 LOGV("receive_jpeg_callback E (completion status %d)", status);
4425 if (status == JPEG_EVENT_DONE) {
4426 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4427 if (obj != 0) {
4428 obj->receiveJpegPicture();
4429 }
4430 }
4431 LOGV("receive_jpeg_callback X");
4432}
Sravankb4f5f1c2010-01-21 11:06:17 +05304433// 720p : video frame calbback from camframe
4434static void receive_camframe_video_callback(struct msm_frame *frame)
4435{
4436 LOGV("receive_camframe_video_callback E");
4437 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4438 if (obj != 0) {
4439 obj->receiveRecordingFrame(frame);
4440 }
4441 LOGV("receive_camframe_video_callback X");
4442}
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004443
4444void QualcommCameraHardware::setCallbacks(notify_callback notify_cb,
4445 data_callback data_cb,
4446 data_callback_timestamp data_cb_timestamp,
4447 void* user)
4448{
4449 Mutex::Autolock lock(mLock);
4450 mNotifyCallback = notify_cb;
4451 mDataCallback = data_cb;
4452 mDataCallbackTimestamp = data_cb_timestamp;
4453 mCallbackCookie = user;
4454}
4455
4456void QualcommCameraHardware::enableMsgType(int32_t msgType)
4457{
4458 Mutex::Autolock lock(mLock);
4459 mMsgEnabled |= msgType;
4460}
4461
4462void QualcommCameraHardware::disableMsgType(int32_t msgType)
4463{
4464 Mutex::Autolock lock(mLock);
4465 mMsgEnabled &= ~msgType;
4466}
4467
4468bool QualcommCameraHardware::msgTypeEnabled(int32_t msgType)
4469{
4470 return (mMsgEnabled & msgType);
4471}
4472
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08004473bool QualcommCameraHardware::useOverlay(void)
4474{
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08004475 if( mCurrentTarget == TARGET_MSM7630 ) {
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08004476 /* Only 7x30 supports Overlay */
4477 mUseOverlay = TRUE;
4478 } else
4479 mUseOverlay = FALSE;
4480
4481 LOGV(" Using Overlay : %s ", mUseOverlay ? "YES" : "NO" );
4482 return mUseOverlay;
4483}
4484
4485status_t QualcommCameraHardware::setOverlay(const sp<Overlay> &Overlay)
4486{
4487 if( Overlay != NULL) {
4488 LOGV(" Valid overlay object ");
4489 mOverlayLock.lock();
4490 mOverlay = Overlay;
4491 mOverlayLock.unlock();
4492 } else {
Apurva Rajguruc73c1722010-04-15 17:39:11 -07004493 LOGV(" Overlay object NULL. returning ");
Mohan Kandrad9efed92010-01-15 19:08:39 -08004494 mOverlay = NULL;
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08004495 return UNKNOWN_ERROR;
4496 }
4497 return NO_ERROR;
4498}
Kiran Kumar H N215cac42009-12-08 01:53:46 -08004499
4500void QualcommCameraHardware::receive_camframetimeout(void) {
4501 LOGV("receive_camframetimeout: E");
4502 Mutex::Autolock l(&mCamframeTimeoutLock);
Kiran Kumar H N7ac84e32010-02-01 10:58:47 -08004503 LOGD(" Camframe timed out. Not receiving any frames from camera driver ");
Kiran Kumar H N215cac42009-12-08 01:53:46 -08004504 camframe_timeout_flag = TRUE;
4505 LOGV("receive_camframetimeout: X");
4506}
4507
4508static void receive_camframetimeout_callback(void) {
4509 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4510 if (obj != 0) {
4511 obj->receive_camframetimeout();
4512 }
4513}
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08004514
4515void QualcommCameraHardware::storePreviewFrameForPostview(void) {
4516 LOGV(" storePreviewFrameForPostview : E ");
4517
4518 /* Since there is restriction on the maximum overlay dimensions
4519 * that can be created, we use the last preview frame as postview
4520 * for 7x30. */
4521 LOGV(" Copying the preview buffer to postview buffer %d ",
4522 mPreviewFrameSize);
4523 if( mPostViewHeap != NULL && mLastQueuedFrame != NULL) {
4524 memcpy(mPostViewHeap->mHeap->base(),
4525 (uint8_t *)mLastQueuedFrame, mPreviewFrameSize );
4526 } else
4527 LOGE(" Failed to store Preview frame. No Postview ");
4528
4529 LOGV(" storePreviewFrameForPostview : X ");
4530}
Kiran Kumar H Nb49af212010-02-17 15:12:17 -08004531
4532bool QualcommCameraHardware::isValidDimension(int width, int height) {
4533 bool retVal = FALSE;
4534 /* This function checks if a given resolution is valid or not.
4535 * A particular resolution is considered valid if it satisfies
4536 * the following conditions:
4537 * 1. width & height should be multiple of 16.
4538 * 2. width & height should be less than/equal to the dimensions
4539 * supported by the camera sensor.
4540 * 3. the aspect ratio is a valid aspect ratio and is among the
4541 * commonly used aspect ratio as determined by the thumbnail_sizes
4542 * data structure.
4543 */
4544
4545 if( (width == CEILING16(width)) && (height == CEILING16(height))
4546 && (width <= sensorType->max_supported_snapshot_width)
4547 && (height <= sensorType->max_supported_snapshot_height) )
4548 {
4549 uint32_t pictureAspectRatio = (uint32_t)((width * Q12)/height);
4550 for(int i = 0; i < THUMBNAIL_SIZE_COUNT; i++ ) {
4551 if(thumbnail_sizes[i].aspect_ratio == pictureAspectRatio) {
4552 retVal = TRUE;
4553 break;
4554 }
4555 }
4556 }
4557 return retVal;
4558}
Kiran Kumar H N4dd45a62010-02-26 15:56:33 -08004559status_t QualcommCameraHardware::getBufferInfo(sp<IMemory>& Frame, size_t *alignedSize) {
4560 status_t ret;
4561 LOGV(" getBufferInfo : E ");
Vamshidhar Kondrab362be62010-03-22 19:07:29 +05304562 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250) )
4563 {
4564 if( mRecordHeap != NULL){
4565 LOGV(" Setting valid buffer information ");
4566 Frame = mRecordHeap->mBuffers[0];
4567 if( alignedSize != NULL) {
4568 *alignedSize = mRecordHeap->mAlignedBufferSize;
4569 LOGV(" HAL : alignedSize = %d ", *alignedSize);
4570 ret = NO_ERROR;
4571 } else {
4572 LOGE(" HAL : alignedSize is NULL. Cannot update alignedSize ");
4573 ret = UNKNOWN_ERROR;
4574 }
Kiran Kumar H N4dd45a62010-02-26 15:56:33 -08004575 } else {
Vamshidhar Kondrab362be62010-03-22 19:07:29 +05304576 LOGE(" RecordHeap is null. Buffer information wont be updated ");
4577 Frame = NULL;
4578 ret = UNKNOWN_ERROR;
4579 }
Kiran Kumar H N4dd45a62010-02-26 15:56:33 -08004580 } else {
Vamshidhar Kondrab362be62010-03-22 19:07:29 +05304581 if(mPreviewHeap != NULL) {
4582 LOGV(" Setting valid buffer information ");
4583 Frame = mPreviewHeap->mBuffers[0];
4584 if( alignedSize != NULL) {
4585 *alignedSize = mPreviewHeap->mAlignedBufferSize;
4586 LOGV(" HAL : alignedSize = %d ", *alignedSize);
4587 ret = NO_ERROR;
4588 } else {
4589 LOGE(" HAL : alignedSize is NULL. Cannot update alignedSize ");
4590 ret = UNKNOWN_ERROR;
4591 }
4592 } else {
4593 LOGE(" PreviewHeap is null. Buffer information wont be updated ");
4594 Frame = NULL;
4595 ret = UNKNOWN_ERROR;
4596 }
Kiran Kumar H N4dd45a62010-02-26 15:56:33 -08004597 }
4598 LOGV(" getBufferInfo : X ");
4599 return ret;
4600}
Kiran Kumar H Nb49af212010-02-17 15:12:17 -08004601
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004602}; // namespace android