blob: 4b811128a0c62056b38ac941fabfa6ed84af2f45 [file] [log] [blame]
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001/*
2** Copyright 2008, Google Inc.
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303** Copyright (c) 2009, Code Aurora Forum. All rights reserved.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18//#define LOG_NDEBUG 0
19#define LOG_TAG "QualcommCameraHardware"
20#include <utils/Log.h>
21
22#include "QualcommCameraHardware.h"
23
24#include <utils/Errors.h>
25#include <utils/threads.h>
26#include <binder/MemoryHeapPmem.h>
27#include <utils/String16.h>
28#include <sys/types.h>
29#include <sys/stat.h>
30#include <unistd.h>
Sravankb4f5f1c2010-01-21 11:06:17 +053031#include <fcntl.h>
Apurva Rajguru8d1773b2009-12-02 14:21:23 -080032#include <cutils/properties.h>
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -080033#include <math.h>
Priya Komarlingamb85535d2009-11-30 13:06:01 -080034#if HAVE_ANDROID_OS
35#include <linux/android_pmem.h>
36#endif
37#include <linux/ioctl.h>
38#include <ui/CameraParameters.h>
39
Mohan Kandra284966d2010-01-05 13:39:15 -080040#include "linux/msm_mdp.h"
41#include <linux/fb.h>
42
Priya Komarlingamb85535d2009-11-30 13:06:01 -080043#define LIKELY(exp) __builtin_expect(!!(exp), 1)
44#define UNLIKELY(exp) __builtin_expect(!!(exp), 0)
45
46extern "C" {
47#include <fcntl.h>
48#include <time.h>
49#include <pthread.h>
50#include <stdio.h>
51#include <string.h>
52#include <unistd.h>
53#include <termios.h>
54#include <assert.h>
55#include <stdlib.h>
56#include <ctype.h>
57#include <signal.h>
58#include <errno.h>
59#include <sys/mman.h>
60#include <sys/system_properties.h>
61#include <sys/time.h>
62#include <stdlib.h>
63
64#include <media/msm_camera.h>
65
66#include <camera.h>
67#include <camframe.h>
68#include <mm-still/jpeg/jpege.h>
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -080069#include <jpeg_encoder.h>
Priya Komarlingamb85535d2009-11-30 13:06:01 -080070
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -080071#define DEFAULT_PICTURE_WIDTH 1024
72#define DEFAULT_PICTURE_HEIGHT 768
Priya Komarlingamb85535d2009-11-30 13:06:01 -080073#define THUMBNAIL_BUFFER_SIZE (THUMBNAIL_WIDTH * THUMBNAIL_HEIGHT * 3/2)
74#define MAX_ZOOM_LEVEL 5
75#define NOT_FOUND -1
76
Sravankb4f5f1c2010-01-21 11:06:17 +053077// Number of video buffers held by kernal (initially 1,2 &3)
78#define ACTIVE_VIDEO_BUFFERS 3
79
Priya Komarlingamb85535d2009-11-30 13:06:01 -080080#if DLOPEN_LIBMMCAMERA
81#include <dlfcn.h>
82
83void* (*LINK_cam_conf)(void *data);
84void* (*LINK_cam_frame)(void *data);
85bool (*LINK_jpeg_encoder_init)();
86void (*LINK_jpeg_encoder_join)();
87bool (*LINK_jpeg_encoder_encode)(const cam_ctrl_dimension_t *dimen,
88 const uint8_t *thumbnailbuf, int thumbnailfd,
89 const uint8_t *snapshotbuf, int snapshotfd,
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -080090 common_crop_t *scaling_parms, exif_tags_info_t *exif_data,
91 int exif_table_numEntries);
Kiran Kumar H N7ac84e32010-02-01 10:58:47 -080092void (*LINK_camframe_terminate)(void);
Sravankb4f5f1c2010-01-21 11:06:17 +053093//for 720p
94// Function to add a video buffer to free Q
95void (*LINK_camframe_free_video)(struct msm_frame *frame);
96// Function pointer , called by camframe when a video frame is available.
97void (**LINK_camframe_video_callback)(struct msm_frame * frame);
98// To flush free Q in cam frame.
99void (*LINK_cam_frame_flush_free_video)(void);
100
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800101int8_t (*LINK_jpeg_encoder_setMainImageQuality)(uint32_t quality);
102int8_t (*LINK_jpeg_encoder_setThumbnailQuality)(uint32_t quality);
103int8_t (*LINK_jpeg_encoder_setRotation)(uint32_t rotation);
104int8_t (*LINK_jpeg_encoder_setLocation)(const camera_position_type *location);
105const struct camera_size_type *(*LINK_default_sensor_get_snapshot_sizes)(int *len);
106int (*LINK_launch_cam_conf_thread)(void);
107int (*LINK_release_cam_conf_thread)(void);
108int8_t (*LINK_zoom_crop_upscale)(uint32_t width, uint32_t height,
109 uint32_t cropped_width, uint32_t cropped_height, uint8_t *img_buf);
110
111// callbacks
112void (**LINK_mmcamera_camframe_callback)(struct msm_frame *frame);
113void (**LINK_mmcamera_jpegfragment_callback)(uint8_t *buff_ptr,
114 uint32_t buff_size);
115void (**LINK_mmcamera_jpeg_callback)(jpeg_event_t status);
116void (**LINK_mmcamera_shutter_callback)(common_crop_t *crop);
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800117void (**LINK_camframe_timeout_callback)(void);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800118#else
119#define LINK_cam_conf cam_conf
120#define LINK_cam_frame cam_frame
121#define LINK_jpeg_encoder_init jpeg_encoder_init
122#define LINK_jpeg_encoder_join jpeg_encoder_join
123#define LINK_jpeg_encoder_encode jpeg_encoder_encode
124#define LINK_camframe_terminate camframe_terminate
125#define LINK_jpeg_encoder_setMainImageQuality jpeg_encoder_setMainImageQuality
126#define LINK_jpeg_encoder_setThumbnailQuality jpeg_encoder_setThumbnailQuality
127#define LINK_jpeg_encoder_setRotation jpeg_encoder_setRotation
128#define LINK_jpeg_encoder_setLocation jpeg_encoder_setLocation
129#define LINK_default_sensor_get_snapshot_sizes default_sensor_get_snapshot_sizes
130#define LINK_launch_cam_conf_thread launch_cam_conf_thread
131#define LINK_release_cam_conf_thread release_cam_conf_thread
132#define LINK_zoom_crop_upscale zoom_crop_upscale
133extern void (*mmcamera_camframe_callback)(struct msm_frame *frame);
134extern void (*mmcamera_jpegfragment_callback)(uint8_t *buff_ptr,
135 uint32_t buff_size);
136extern void (*mmcamera_jpeg_callback)(jpeg_event_t status);
137extern void (*mmcamera_shutter_callback)(common_crop_t *crop);
138#endif
139
140} // extern "C"
141
142#ifndef HAVE_CAMERA_SIZE_TYPE
143struct camera_size_type {
144 int width;
145 int height;
146};
147#endif
148
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -0800149typedef struct crop_info_struct {
150 uint32_t x;
151 uint32_t y;
152 uint32_t w;
153 uint32_t h;
154} zoom_crop_info;
155
Mohan Kandra740cfce2010-01-07 12:58:24 -0800156union zoomimage
Mohan Kandra284966d2010-01-05 13:39:15 -0800157{
158 char d[sizeof(struct mdp_blit_req_list) + sizeof(struct mdp_blit_req) * 1];
159 struct mdp_blit_req_list list;
160} zoomImage;
161
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800162//Default to WVGA
Srinivasan Kannanfa7edae2009-12-16 18:02:01 -0800163#define DEFAULT_PREVIEW_SETTING 1
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800164static const camera_size_type preview_sizes[] = {
Srinivasan Kannanfa7edae2009-12-16 18:02:01 -0800165 { 1280, 720 }, // 720P, reserved
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800166 { 800, 480 }, // WVGA
Srinivasan Kannan613301c2010-02-10 17:08:53 -0800167 { 768, 432 },
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800168 { 720, 480 },
169 { 640, 480 }, // VGA
170 { 576, 432 },
171 { 480, 320 }, // HVGA
172 { 384, 288 },
173 { 352, 288 }, // CIF
174 { 320, 240 }, // QVGA
175 { 240, 160 }, // SQVGA
176 { 176, 144 }, // QCIF
177};
178#define PREVIEW_SIZE_COUNT (sizeof(preview_sizes)/sizeof(camera_size_type))
179
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800180//static const camera_size_type* picture_sizes;
181//static int PICTURE_SIZE_COUNT;
182/* TODO
183 * Ideally this should be a populated by lower layers.
184 * But currently this is no API to do that at lower layer.
185 * Hence populating with default sizes for now. This needs
186 * to be changed once the API is supported.
187 */
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800188//sorted on column basis
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800189static const camera_size_type picture_sizes[] = {
190 { 2592, 1944 }, // 5MP
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800191 { 2048, 1536 }, // 3MP QXGA
192 { 1920, 1080 }, //HD1080
193 { 1600, 1200 }, // 2MP UXGA
194 { 1280, 768 }, //WXGA
195 { 1280, 720 }, //HD720
196 { 1024, 768}, // 1MP XGA
197 { 800, 600 }, //SVGA
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800198 { 800, 480 }, // WVGA
199 { 640, 480 }, // VGA
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800200 { 352, 288 }, //CIF
201 { 320, 240 }, // QVGA
202 { 176, 144 } // QCIF
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800203};
204static int PICTURE_SIZE_COUNT = sizeof(picture_sizes)/sizeof(camera_size_type);
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800205static const camera_size_type * picture_sizes_ptr;
206static int supportedPictureSizesCount;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800207
Srinivasan Kannan80d878f2009-12-18 15:06:02 -0800208#ifdef Q12
209#undef Q12
210#endif
211
212#define Q12 4096
213
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -0800214static const target_map targetList [] = {
215 { "msm7625", TARGET_MSM7625 },
216 { "msm7627", TARGET_MSM7627 },
217 { "qsd8250", TARGET_QSD8250 },
218 { "msm7630", TARGET_MSM7630 }
219};
220static targetType mCurrentTarget = TARGET_MAX;
221
Srinivasan Kannan80d878f2009-12-18 15:06:02 -0800222typedef struct {
223 uint32_t aspect_ratio;
224 uint32_t width;
225 uint32_t height;
226} thumbnail_size_type;
227
228static thumbnail_size_type thumbnail_sizes[] = {
229 { 7281, 512, 288 }, //1.777778
230 { 6826, 480, 288 }, //1.666667
231 { 5461, 512, 384 }, //1.333333
232 { 5006, 352, 288 }, //1.222222
233};
234#define THUMBNAIL_SIZE_COUNT (sizeof(thumbnail_sizes)/sizeof(thumbnail_size_type))
235#define DEFAULT_THUMBNAIL_SETTING 2
236#define THUMBNAIL_WIDTH_STR "512"
237#define THUMBNAIL_HEIGHT_STR "384"
238#define THUMBNAIL_SMALL_HEIGHT 144
239
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800240static int attr_lookup(const str_map arr[], int len, const char *name)
241{
242 if (name) {
243 for (int i = 0; i < len; i++) {
244 if (!strcmp(arr[i].desc, name))
245 return arr[i].val;
246 }
247 }
248 return NOT_FOUND;
249}
250
251// round to the next power of two
252static inline unsigned clp2(unsigned x)
253{
254 x = x - 1;
255 x = x | (x >> 1);
256 x = x | (x >> 2);
257 x = x | (x >> 4);
258 x = x | (x >> 8);
259 x = x | (x >>16);
260 return x + 1;
261}
262
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -0800263static int exif_table_numEntries = 0;
264#define MAX_EXIF_TABLE_ENTRIES 7
265exif_tags_info_t exif_data[MAX_EXIF_TABLE_ENTRIES];
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -0800266static zoom_crop_info zoomCropInfo;
267static void *mLastQueuedFrame = NULL;
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -0800268
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800269namespace android {
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800270
271static const int PICTURE_FORMAT_JPEG = 1;
272static const int PICTURE_FORMAT_RAW = 2;
273
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800274// from aeecamera.h
275static const str_map whitebalance[] = {
276 { CameraParameters::WHITE_BALANCE_AUTO, CAMERA_WB_AUTO },
277 { CameraParameters::WHITE_BALANCE_INCANDESCENT, CAMERA_WB_INCANDESCENT },
278 { CameraParameters::WHITE_BALANCE_FLUORESCENT, CAMERA_WB_FLUORESCENT },
279 { CameraParameters::WHITE_BALANCE_DAYLIGHT, CAMERA_WB_DAYLIGHT },
280 { CameraParameters::WHITE_BALANCE_CLOUDY_DAYLIGHT, CAMERA_WB_CLOUDY_DAYLIGHT }
281};
282
283// from camera_effect_t. This list must match aeecamera.h
284static const str_map effects[] = {
285 { CameraParameters::EFFECT_NONE, CAMERA_EFFECT_OFF },
286 { CameraParameters::EFFECT_MONO, CAMERA_EFFECT_MONO },
287 { CameraParameters::EFFECT_NEGATIVE, CAMERA_EFFECT_NEGATIVE },
288 { CameraParameters::EFFECT_SOLARIZE, CAMERA_EFFECT_SOLARIZE },
289 { CameraParameters::EFFECT_SEPIA, CAMERA_EFFECT_SEPIA },
290 { CameraParameters::EFFECT_POSTERIZE, CAMERA_EFFECT_POSTERIZE },
291 { CameraParameters::EFFECT_WHITEBOARD, CAMERA_EFFECT_WHITEBOARD },
292 { CameraParameters::EFFECT_BLACKBOARD, CAMERA_EFFECT_BLACKBOARD },
293 { CameraParameters::EFFECT_AQUA, CAMERA_EFFECT_AQUA }
294};
295
296// from qcamera/common/camera.h
Apurva Rajguru55562b02009-12-03 12:25:35 -0800297static const str_map autoexposure[] = {
298 { CameraParameters::AUTO_EXPOSURE_FRAME_AVG, CAMERA_AEC_FRAME_AVERAGE },
299 { CameraParameters::AUTO_EXPOSURE_CENTER_WEIGHTED, CAMERA_AEC_CENTER_WEIGHTED },
300 { CameraParameters::AUTO_EXPOSURE_SPOT_METERING, CAMERA_AEC_SPOT_METERING }
301};
302
303// from qcamera/common/camera.h
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800304static const str_map antibanding[] = {
305 { CameraParameters::ANTIBANDING_OFF, CAMERA_ANTIBANDING_OFF },
306 { CameraParameters::ANTIBANDING_50HZ, CAMERA_ANTIBANDING_50HZ },
307 { CameraParameters::ANTIBANDING_60HZ, CAMERA_ANTIBANDING_60HZ },
308 { CameraParameters::ANTIBANDING_AUTO, CAMERA_ANTIBANDING_AUTO }
309};
310
311/* Mapping from MCC to antibanding type */
312struct country_map {
313 uint32_t country_code;
314 camera_antibanding_type type;
315};
316
317static struct country_map country_numeric[] = {
318 { 202, CAMERA_ANTIBANDING_50HZ }, // Greece
319 { 204, CAMERA_ANTIBANDING_50HZ }, // Netherlands
320 { 206, CAMERA_ANTIBANDING_50HZ }, // Belgium
321 { 208, CAMERA_ANTIBANDING_50HZ }, // France
322 { 212, CAMERA_ANTIBANDING_50HZ }, // Monaco
323 { 213, CAMERA_ANTIBANDING_50HZ }, // Andorra
324 { 214, CAMERA_ANTIBANDING_50HZ }, // Spain
325 { 216, CAMERA_ANTIBANDING_50HZ }, // Hungary
326 { 219, CAMERA_ANTIBANDING_50HZ }, // Croatia
327 { 220, CAMERA_ANTIBANDING_50HZ }, // Serbia
328 { 222, CAMERA_ANTIBANDING_50HZ }, // Italy
329 { 226, CAMERA_ANTIBANDING_50HZ }, // Romania
330 { 228, CAMERA_ANTIBANDING_50HZ }, // Switzerland
331 { 230, CAMERA_ANTIBANDING_50HZ }, // Czech Republic
332 { 231, CAMERA_ANTIBANDING_50HZ }, // Slovakia
333 { 232, CAMERA_ANTIBANDING_50HZ }, // Austria
334 { 234, CAMERA_ANTIBANDING_50HZ }, // United Kingdom
335 { 235, CAMERA_ANTIBANDING_50HZ }, // United Kingdom
336 { 238, CAMERA_ANTIBANDING_50HZ }, // Denmark
337 { 240, CAMERA_ANTIBANDING_50HZ }, // Sweden
338 { 242, CAMERA_ANTIBANDING_50HZ }, // Norway
339 { 244, CAMERA_ANTIBANDING_50HZ }, // Finland
340 { 246, CAMERA_ANTIBANDING_50HZ }, // Lithuania
341 { 247, CAMERA_ANTIBANDING_50HZ }, // Latvia
342 { 248, CAMERA_ANTIBANDING_50HZ }, // Estonia
343 { 250, CAMERA_ANTIBANDING_50HZ }, // Russian Federation
344 { 255, CAMERA_ANTIBANDING_50HZ }, // Ukraine
345 { 257, CAMERA_ANTIBANDING_50HZ }, // Belarus
346 { 259, CAMERA_ANTIBANDING_50HZ }, // Moldova
347 { 260, CAMERA_ANTIBANDING_50HZ }, // Poland
348 { 262, CAMERA_ANTIBANDING_50HZ }, // Germany
349 { 266, CAMERA_ANTIBANDING_50HZ }, // Gibraltar
350 { 268, CAMERA_ANTIBANDING_50HZ }, // Portugal
351 { 270, CAMERA_ANTIBANDING_50HZ }, // Luxembourg
352 { 272, CAMERA_ANTIBANDING_50HZ }, // Ireland
353 { 274, CAMERA_ANTIBANDING_50HZ }, // Iceland
354 { 276, CAMERA_ANTIBANDING_50HZ }, // Albania
355 { 278, CAMERA_ANTIBANDING_50HZ }, // Malta
356 { 280, CAMERA_ANTIBANDING_50HZ }, // Cyprus
357 { 282, CAMERA_ANTIBANDING_50HZ }, // Georgia
358 { 283, CAMERA_ANTIBANDING_50HZ }, // Armenia
359 { 284, CAMERA_ANTIBANDING_50HZ }, // Bulgaria
360 { 286, CAMERA_ANTIBANDING_50HZ }, // Turkey
361 { 288, CAMERA_ANTIBANDING_50HZ }, // Faroe Islands
362 { 290, CAMERA_ANTIBANDING_50HZ }, // Greenland
363 { 293, CAMERA_ANTIBANDING_50HZ }, // Slovenia
364 { 294, CAMERA_ANTIBANDING_50HZ }, // Macedonia
365 { 295, CAMERA_ANTIBANDING_50HZ }, // Liechtenstein
366 { 297, CAMERA_ANTIBANDING_50HZ }, // Montenegro
367 { 302, CAMERA_ANTIBANDING_60HZ }, // Canada
368 { 310, CAMERA_ANTIBANDING_60HZ }, // United States of America
369 { 311, CAMERA_ANTIBANDING_60HZ }, // United States of America
370 { 312, CAMERA_ANTIBANDING_60HZ }, // United States of America
371 { 313, CAMERA_ANTIBANDING_60HZ }, // United States of America
372 { 314, CAMERA_ANTIBANDING_60HZ }, // United States of America
373 { 315, CAMERA_ANTIBANDING_60HZ }, // United States of America
374 { 316, CAMERA_ANTIBANDING_60HZ }, // United States of America
375 { 330, CAMERA_ANTIBANDING_60HZ }, // Puerto Rico
376 { 334, CAMERA_ANTIBANDING_60HZ }, // Mexico
377 { 338, CAMERA_ANTIBANDING_50HZ }, // Jamaica
378 { 340, CAMERA_ANTIBANDING_50HZ }, // Martinique
379 { 342, CAMERA_ANTIBANDING_50HZ }, // Barbados
380 { 346, CAMERA_ANTIBANDING_60HZ }, // Cayman Islands
381 { 350, CAMERA_ANTIBANDING_60HZ }, // Bermuda
382 { 352, CAMERA_ANTIBANDING_50HZ }, // Grenada
383 { 354, CAMERA_ANTIBANDING_60HZ }, // Montserrat
384 { 362, CAMERA_ANTIBANDING_50HZ }, // Netherlands Antilles
385 { 363, CAMERA_ANTIBANDING_60HZ }, // Aruba
386 { 364, CAMERA_ANTIBANDING_60HZ }, // Bahamas
387 { 365, CAMERA_ANTIBANDING_60HZ }, // Anguilla
388 { 366, CAMERA_ANTIBANDING_50HZ }, // Dominica
389 { 368, CAMERA_ANTIBANDING_60HZ }, // Cuba
390 { 370, CAMERA_ANTIBANDING_60HZ }, // Dominican Republic
391 { 372, CAMERA_ANTIBANDING_60HZ }, // Haiti
392 { 401, CAMERA_ANTIBANDING_50HZ }, // Kazakhstan
393 { 402, CAMERA_ANTIBANDING_50HZ }, // Bhutan
394 { 404, CAMERA_ANTIBANDING_50HZ }, // India
395 { 405, CAMERA_ANTIBANDING_50HZ }, // India
396 { 410, CAMERA_ANTIBANDING_50HZ }, // Pakistan
397 { 413, CAMERA_ANTIBANDING_50HZ }, // Sri Lanka
398 { 414, CAMERA_ANTIBANDING_50HZ }, // Myanmar
399 { 415, CAMERA_ANTIBANDING_50HZ }, // Lebanon
400 { 416, CAMERA_ANTIBANDING_50HZ }, // Jordan
401 { 417, CAMERA_ANTIBANDING_50HZ }, // Syria
402 { 418, CAMERA_ANTIBANDING_50HZ }, // Iraq
403 { 419, CAMERA_ANTIBANDING_50HZ }, // Kuwait
404 { 420, CAMERA_ANTIBANDING_60HZ }, // Saudi Arabia
405 { 421, CAMERA_ANTIBANDING_50HZ }, // Yemen
406 { 422, CAMERA_ANTIBANDING_50HZ }, // Oman
407 { 424, CAMERA_ANTIBANDING_50HZ }, // United Arab Emirates
408 { 425, CAMERA_ANTIBANDING_50HZ }, // Israel
409 { 426, CAMERA_ANTIBANDING_50HZ }, // Bahrain
410 { 427, CAMERA_ANTIBANDING_50HZ }, // Qatar
411 { 428, CAMERA_ANTIBANDING_50HZ }, // Mongolia
412 { 429, CAMERA_ANTIBANDING_50HZ }, // Nepal
413 { 430, CAMERA_ANTIBANDING_50HZ }, // United Arab Emirates
414 { 431, CAMERA_ANTIBANDING_50HZ }, // United Arab Emirates
415 { 432, CAMERA_ANTIBANDING_50HZ }, // Iran
416 { 434, CAMERA_ANTIBANDING_50HZ }, // Uzbekistan
417 { 436, CAMERA_ANTIBANDING_50HZ }, // Tajikistan
418 { 437, CAMERA_ANTIBANDING_50HZ }, // Kyrgyz Rep
419 { 438, CAMERA_ANTIBANDING_50HZ }, // Turkmenistan
420 { 440, CAMERA_ANTIBANDING_60HZ }, // Japan
421 { 441, CAMERA_ANTIBANDING_60HZ }, // Japan
422 { 452, CAMERA_ANTIBANDING_50HZ }, // Vietnam
423 { 454, CAMERA_ANTIBANDING_50HZ }, // Hong Kong
424 { 455, CAMERA_ANTIBANDING_50HZ }, // Macao
425 { 456, CAMERA_ANTIBANDING_50HZ }, // Cambodia
426 { 457, CAMERA_ANTIBANDING_50HZ }, // Laos
427 { 460, CAMERA_ANTIBANDING_50HZ }, // China
428 { 466, CAMERA_ANTIBANDING_60HZ }, // Taiwan
429 { 470, CAMERA_ANTIBANDING_50HZ }, // Bangladesh
430 { 472, CAMERA_ANTIBANDING_50HZ }, // Maldives
431 { 502, CAMERA_ANTIBANDING_50HZ }, // Malaysia
432 { 505, CAMERA_ANTIBANDING_50HZ }, // Australia
433 { 510, CAMERA_ANTIBANDING_50HZ }, // Indonesia
434 { 514, CAMERA_ANTIBANDING_50HZ }, // East Timor
435 { 515, CAMERA_ANTIBANDING_60HZ }, // Philippines
436 { 520, CAMERA_ANTIBANDING_50HZ }, // Thailand
437 { 525, CAMERA_ANTIBANDING_50HZ }, // Singapore
438 { 530, CAMERA_ANTIBANDING_50HZ }, // New Zealand
439 { 535, CAMERA_ANTIBANDING_60HZ }, // Guam
440 { 536, CAMERA_ANTIBANDING_50HZ }, // Nauru
441 { 537, CAMERA_ANTIBANDING_50HZ }, // Papua New Guinea
442 { 539, CAMERA_ANTIBANDING_50HZ }, // Tonga
443 { 541, CAMERA_ANTIBANDING_50HZ }, // Vanuatu
444 { 542, CAMERA_ANTIBANDING_50HZ }, // Fiji
445 { 544, CAMERA_ANTIBANDING_60HZ }, // American Samoa
446 { 545, CAMERA_ANTIBANDING_50HZ }, // Kiribati
447 { 546, CAMERA_ANTIBANDING_50HZ }, // New Caledonia
448 { 548, CAMERA_ANTIBANDING_50HZ }, // Cook Islands
449 { 602, CAMERA_ANTIBANDING_50HZ }, // Egypt
450 { 603, CAMERA_ANTIBANDING_50HZ }, // Algeria
451 { 604, CAMERA_ANTIBANDING_50HZ }, // Morocco
452 { 605, CAMERA_ANTIBANDING_50HZ }, // Tunisia
453 { 606, CAMERA_ANTIBANDING_50HZ }, // Libya
454 { 607, CAMERA_ANTIBANDING_50HZ }, // Gambia
455 { 608, CAMERA_ANTIBANDING_50HZ }, // Senegal
456 { 609, CAMERA_ANTIBANDING_50HZ }, // Mauritania
457 { 610, CAMERA_ANTIBANDING_50HZ }, // Mali
458 { 611, CAMERA_ANTIBANDING_50HZ }, // Guinea
459 { 613, CAMERA_ANTIBANDING_50HZ }, // Burkina Faso
460 { 614, CAMERA_ANTIBANDING_50HZ }, // Niger
461 { 616, CAMERA_ANTIBANDING_50HZ }, // Benin
462 { 617, CAMERA_ANTIBANDING_50HZ }, // Mauritius
463 { 618, CAMERA_ANTIBANDING_50HZ }, // Liberia
464 { 619, CAMERA_ANTIBANDING_50HZ }, // Sierra Leone
465 { 620, CAMERA_ANTIBANDING_50HZ }, // Ghana
466 { 621, CAMERA_ANTIBANDING_50HZ }, // Nigeria
467 { 622, CAMERA_ANTIBANDING_50HZ }, // Chad
468 { 623, CAMERA_ANTIBANDING_50HZ }, // Central African Republic
469 { 624, CAMERA_ANTIBANDING_50HZ }, // Cameroon
470 { 625, CAMERA_ANTIBANDING_50HZ }, // Cape Verde
471 { 627, CAMERA_ANTIBANDING_50HZ }, // Equatorial Guinea
472 { 631, CAMERA_ANTIBANDING_50HZ }, // Angola
473 { 633, CAMERA_ANTIBANDING_50HZ }, // Seychelles
474 { 634, CAMERA_ANTIBANDING_50HZ }, // Sudan
475 { 636, CAMERA_ANTIBANDING_50HZ }, // Ethiopia
476 { 637, CAMERA_ANTIBANDING_50HZ }, // Somalia
477 { 638, CAMERA_ANTIBANDING_50HZ }, // Djibouti
478 { 639, CAMERA_ANTIBANDING_50HZ }, // Kenya
479 { 640, CAMERA_ANTIBANDING_50HZ }, // Tanzania
480 { 641, CAMERA_ANTIBANDING_50HZ }, // Uganda
481 { 642, CAMERA_ANTIBANDING_50HZ }, // Burundi
482 { 643, CAMERA_ANTIBANDING_50HZ }, // Mozambique
483 { 645, CAMERA_ANTIBANDING_50HZ }, // Zambia
484 { 646, CAMERA_ANTIBANDING_50HZ }, // Madagascar
485 { 647, CAMERA_ANTIBANDING_50HZ }, // France
486 { 648, CAMERA_ANTIBANDING_50HZ }, // Zimbabwe
487 { 649, CAMERA_ANTIBANDING_50HZ }, // Namibia
488 { 650, CAMERA_ANTIBANDING_50HZ }, // Malawi
489 { 651, CAMERA_ANTIBANDING_50HZ }, // Lesotho
490 { 652, CAMERA_ANTIBANDING_50HZ }, // Botswana
491 { 653, CAMERA_ANTIBANDING_50HZ }, // Swaziland
492 { 654, CAMERA_ANTIBANDING_50HZ }, // Comoros
493 { 655, CAMERA_ANTIBANDING_50HZ }, // South Africa
494 { 657, CAMERA_ANTIBANDING_50HZ }, // Eritrea
495 { 702, CAMERA_ANTIBANDING_60HZ }, // Belize
496 { 704, CAMERA_ANTIBANDING_60HZ }, // Guatemala
497 { 706, CAMERA_ANTIBANDING_60HZ }, // El Salvador
498 { 708, CAMERA_ANTIBANDING_60HZ }, // Honduras
499 { 710, CAMERA_ANTIBANDING_60HZ }, // Nicaragua
500 { 712, CAMERA_ANTIBANDING_60HZ }, // Costa Rica
501 { 714, CAMERA_ANTIBANDING_60HZ }, // Panama
502 { 722, CAMERA_ANTIBANDING_50HZ }, // Argentina
503 { 724, CAMERA_ANTIBANDING_60HZ }, // Brazil
504 { 730, CAMERA_ANTIBANDING_50HZ }, // Chile
505 { 732, CAMERA_ANTIBANDING_60HZ }, // Colombia
506 { 734, CAMERA_ANTIBANDING_60HZ }, // Venezuela
507 { 736, CAMERA_ANTIBANDING_50HZ }, // Bolivia
508 { 738, CAMERA_ANTIBANDING_60HZ }, // Guyana
509 { 740, CAMERA_ANTIBANDING_60HZ }, // Ecuador
510 { 742, CAMERA_ANTIBANDING_50HZ }, // French Guiana
511 { 744, CAMERA_ANTIBANDING_50HZ }, // Paraguay
512 { 746, CAMERA_ANTIBANDING_60HZ }, // Suriname
513 { 748, CAMERA_ANTIBANDING_50HZ }, // Uruguay
514 { 750, CAMERA_ANTIBANDING_50HZ }, // Falkland Islands
515};
516
517#define country_number (sizeof(country_numeric) / sizeof(country_map))
518
519/* Look up pre-sorted antibanding_type table by current MCC. */
520static camera_antibanding_type camera_get_location(void) {
521 char value[PROP_VALUE_MAX];
522 char country_value[PROP_VALUE_MAX];
523 uint32_t country_code, count;
524 memset(value, 0x00, sizeof(value));
525 memset(country_value, 0x00, sizeof(country_value));
526 if (!__system_property_get("gsm.operator.numeric", value)) {
527 return CAMERA_ANTIBANDING_60HZ;
528 }
529 memcpy(country_value, value, 3);
530 country_code = atoi(country_value);
531 LOGD("value:%s, country value:%s, country code:%d\n",
532 value, country_value, country_code);
533 int left = 0;
534 int right = country_number - 1;
535 while (left <= right) {
536 int index = (left + right) >> 1;
537 if (country_numeric[index].country_code == country_code)
538 return country_numeric[index].type;
539 else if (country_numeric[index].country_code > country_code)
540 right = index - 1;
541 else
542 left = index + 1;
543 }
544 return CAMERA_ANTIBANDING_60HZ;
545}
546
547// from camera.h, led_mode_t
548static const str_map flash[] = {
549 { CameraParameters::FLASH_MODE_OFF, LED_MODE_OFF },
550 { CameraParameters::FLASH_MODE_AUTO, LED_MODE_AUTO },
551 { CameraParameters::FLASH_MODE_ON, LED_MODE_ON }
552};
553
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530554// from mm-camera/common/camera.h.
555static const str_map iso[] = {
556 { CameraParameters::ISO_AUTO, CAMERA_ISO_AUTO},
557 { CameraParameters::ISO_HJR, CAMERA_ISO_DEBLUR},
558 { CameraParameters::ISO_100, CAMERA_ISO_100},
559 { CameraParameters::ISO_200, CAMERA_ISO_200},
560 { CameraParameters::ISO_400, CAMERA_ISO_400},
561 { CameraParameters::ISO_800, CAMERA_ISO_800 }
562};
563
564
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800565#define DONT_CARE 0
566static const str_map focus_modes[] = {
Srinivasan Kannan71229622009-12-04 12:05:58 -0800567 { CameraParameters::FOCUS_MODE_AUTO, AF_MODE_AUTO},
568 { CameraParameters::FOCUS_MODE_INFINITY, DONT_CARE },
569 { CameraParameters::FOCUS_MODE_NORMAL, AF_MODE_NORMAL },
570 { CameraParameters::FOCUS_MODE_MACRO, AF_MODE_MACRO }
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800571};
572
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530573static const str_map lensshade[] = {
574 { CameraParameters::LENSSHADE_ENABLE, TRUE },
575 { CameraParameters::LENSSHADE_DISABLE, FALSE }
576};
577
Srinivasan Kannan71229622009-12-04 12:05:58 -0800578struct SensorType {
579 const char *name;
580 int rawPictureWidth;
581 int rawPictureHeight;
582 bool hasAutoFocusSupport;
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800583 int max_supported_snapshot_width;
584 int max_supported_snapshot_height;
Srinivasan Kannan71229622009-12-04 12:05:58 -0800585};
586
587static SensorType sensorTypes[] = {
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800588 { "5mp", 2608, 1960, true, 2592, 1944 },
589 { "3mp", 2064, 1544, false, 2048, 1536 },
590 { "2mp", 3200, 1200, false, 1600, 1200 } };
591
Srinivasan Kannan71229622009-12-04 12:05:58 -0800592
593static SensorType * sensorType;
594
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800595static const str_map picture_formats[] = {
596 {CameraParameters::PIXEL_FORMAT_JPEG, PICTURE_FORMAT_JPEG},
597 {CameraParameters::PIXEL_FORMAT_RAW, PICTURE_FORMAT_RAW}
598};
599
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800600static bool parameter_string_initialized = false;
601static String8 preview_size_values;
602static String8 picture_size_values;
603static String8 antibanding_values;
604static String8 effect_values;
Apurva Rajguru55562b02009-12-03 12:25:35 -0800605static String8 autoexposure_values;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800606static String8 whitebalance_values;
607static String8 flash_values;
608static String8 focus_mode_values;
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530609static String8 iso_values;
610static String8 lensshade_values;
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800611static String8 picture_format_values;
612
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800613
614static String8 create_sizes_str(const camera_size_type *sizes, int len) {
615 String8 str;
616 char buffer[32];
617
618 if (len > 0) {
619 sprintf(buffer, "%dx%d", sizes[0].width, sizes[0].height);
620 str.append(buffer);
621 }
622 for (int i = 1; i < len; i++) {
623 sprintf(buffer, ",%dx%d", sizes[i].width, sizes[i].height);
624 str.append(buffer);
625 }
626 return str;
627}
628
629static String8 create_values_str(const str_map *values, int len) {
630 String8 str;
631
632 if (len > 0) {
633 str.append(values[0].desc);
634 }
635 for (int i = 1; i < len; i++) {
636 str.append(",");
637 str.append(values[i].desc);
638 }
639 return str;
640}
641
Sravankb4f5f1c2010-01-21 11:06:17 +0530642extern "C" {
643//------------------------------------------------------------------------
644// : 720p busyQ funcitons
645// --------------------------------------------------------------------
646static struct fifo_queue g_busy_frame_queue =
647 {0, 0, 0, PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER};
648};
649/*===========================================================================
650 * FUNCTION cam_frame_wait_video
651 *
652 * DESCRIPTION this function waits a video in the busy queue
653 * ===========================================================================*/
654
655static void cam_frame_wait_video (void)
656{
657 LOGV("cam_frame_wait_video E ");
658 if ((g_busy_frame_queue.num_of_frames) <=0){
659 pthread_cond_wait(&(g_busy_frame_queue.wait), &(g_busy_frame_queue.mut));
660 }
661 LOGV("cam_frame_wait_video X");
662 return;
663}
664
665/*===========================================================================
666 * FUNCTION cam_frame_flush_video
667 *
668 * DESCRIPTION this function deletes all the buffers in busy queue
669 * ===========================================================================*/
670void cam_frame_flush_video (void)
671{
672 LOGV("cam_frame_flush_video: in n = %d\n", g_busy_frame_queue.num_of_frames);
673 pthread_mutex_lock(&(g_busy_frame_queue.mut));
674
675 while (g_busy_frame_queue.front)
676 {
677 //dequeue from the busy queue
678 struct fifo_node *node = dequeue (&g_busy_frame_queue);
679 if(node)
680 free(node);
681
682 LOGV("cam_frame_flush_video: node \n");
683 }
684 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
685 LOGV("cam_frame_flush_video: out n = %d\n", g_busy_frame_queue.num_of_frames);
686 return ;
687}
688/*===========================================================================
689 * FUNCTION cam_frame_get_video
690 *
691 * DESCRIPTION this function returns a video frame from the head
692 * ===========================================================================*/
693static struct msm_frame * cam_frame_get_video()
694{
695 struct msm_frame *p = NULL;
696 LOGV("cam_frame_get_video... in\n");
697 LOGV("cam_frame_get_video... got lock\n");
698 if (g_busy_frame_queue.front)
699 {
700 //dequeue
701 struct fifo_node *node = dequeue (&g_busy_frame_queue);
702 if (node)
703 {
704 p = (struct msm_frame *)node->f;
705 free (node);
706 }
707 LOGV("cam_frame_get_video... out = %x\n", p->buffer);
708 }
709 return p;
710}
711
712/*===========================================================================
713 * FUNCTION cam_frame_post_video
714 *
715 * DESCRIPTION this function add a busy video frame to the busy queue tails
716 * ===========================================================================*/
717static void cam_frame_post_video (struct msm_frame *p)
718{
719 if (!p)
720 {
721 LOGE("post video , buffer is null");
722 return;
723 }
724 LOGV("cam_frame_post_video... in = %x\n", (unsigned int)(p->buffer));
725 pthread_mutex_lock(&(g_busy_frame_queue.mut));
726 LOGV("post_video got lock. q count before enQ %d", g_busy_frame_queue.num_of_frames);
727 //enqueue to busy queue
728 struct fifo_node *node = (struct fifo_node *)malloc (sizeof (struct fifo_node));
729 if (node)
730 {
731 LOGV(" post video , enqueing in busy queue");
732 node->f = p;
733 node->next = NULL;
734 enqueue (&g_busy_frame_queue, node);
735 LOGV("post_video got lock. q count after enQ %d", g_busy_frame_queue.num_of_frames);
736 }
737 else
738 {
739 LOGE("cam_frame_post_video error... out of memory\n");
740 }
741
742 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
743 pthread_cond_signal(&(g_busy_frame_queue.wait));
744
745 LOGV("cam_frame_post_video... out = %x\n", p->buffer);
746
747 return;
748}
749
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -0800750void QualcommCameraHardware::storeTargetType(void) {
751 char mDeviceName[PROPERTY_VALUE_MAX];
752 property_get("ro.product.device",mDeviceName," ");
753 mCurrentTarget = TARGET_MAX;
754 for( int i = 0; i < TARGET_MAX ; i++) {
755 if( !strncmp(mDeviceName, targetList[i].targetStr, 7)) {
756 mCurrentTarget = targetList[i].targetEnum;
757 break;
758 }
759 }
760 LOGV(" Storing the current target type as %d ", mCurrentTarget );
761 return;
762}
763
Sravankb4f5f1c2010-01-21 11:06:17 +0530764//-------------------------------------------------------------------------------------
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800765static Mutex singleton_lock;
766static bool singleton_releasing;
767static Condition singleton_wait;
768
769static void receive_camframe_callback(struct msm_frame *frame);
Sravankb4f5f1c2010-01-21 11:06:17 +0530770static void receive_camframe_video_callback(struct msm_frame *frame); // 720p
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800771static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size);
772static void receive_jpeg_callback(jpeg_event_t status);
773static void receive_shutter_callback(common_crop_t *crop);
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800774static void receive_camframetimeout_callback(void);
Mohan Kandra284966d2010-01-05 13:39:15 -0800775static int fb_fd = -1;
776static int32_t mMaxZoom = 0;
777static bool native_get_maxzoom(int camfd, void *pZm);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800778
Mohan Kandrad9efed92010-01-15 19:08:39 -0800779static int dstOffset = 0;
780
Brian Steuer07704892009-12-18 18:07:33 -0800781static int camerafd;
782pthread_t w_thread;
783
784void *opencamerafd(void *data) {
785 camerafd = open(MSM_CAMERA_CONTROL, O_RDWR);
786 return NULL;
787}
788
Mohan Kandrad9efed92010-01-15 19:08:39 -0800789/* When using MDP zoom, double the preview buffers. The usage of these
790 * buffers is as follows:
791 * 1. As all the buffers comes under a single FD, and at initial registration,
792 * this FD will be passed to surface flinger, surface flinger can have access
793 * to all the buffers when needed.
794 * 2. Only "kPreviewBufferCount" buffers (SrcSet) will be registered with the
795 * camera driver to receive preview frames. The remaining buffers (DstSet),
796 * will be used at HAL and by surface flinger only when crop information
797 * is present in the frame.
798 * 3. When there is no crop information, there will be no call to MDP zoom,
799 * and the buffers in SrcSet will be passed to surface flinger to display.
800 * 4. With crop information present, MDP zoom will be called, and the final
801 * data will be placed in a buffer from DstSet, and this buffer will be given
802 * to surface flinger to display.
803 */
804#define NUM_MORE_BUFS 2
805
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800806QualcommCameraHardware::QualcommCameraHardware()
807 : mParameters(),
808 mCameraRunning(false),
809 mPreviewInitialized(false),
810 mFrameThreadRunning(false),
Mohan Kandra156d0ac2010-01-25 16:59:17 -0800811 mVideoThreadRunning(false),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800812 mSnapshotThreadRunning(false),
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800813 mSnapshotFormat(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800814 mReleasedRecordingFrame(false),
815 mPreviewFrameSize(0),
816 mRawSize(0),
817 mCameraControlFd(-1),
818 mAutoFocusThreadRunning(false),
819 mAutoFocusFd(-1),
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800820 mBrightness(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800821 mInPreviewCallback(false),
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800822 mUseOverlay(0),
823 mOverlay(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800824 mMsgEnabled(0),
825 mNotifyCallback(0),
826 mDataCallback(0),
827 mDataCallbackTimestamp(0),
Mohan Kandra740cfce2010-01-07 12:58:24 -0800828 mCallbackCookie(0),
829 mDebugFps(0)
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800830{
Brian Steuer07704892009-12-18 18:07:33 -0800831
832 // Start opening camera device in a separate thread/ Since this
833 // initializes the sensor hardware, this can take a long time. So,
834 // start the process here so it will be ready by the time it's
835 // needed.
836 if ((pthread_create(&w_thread, NULL, opencamerafd, NULL)) != 0) {
837 LOGE("Camera open thread creation failed");
838 }
839
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800840 memset(&mDimension, 0, sizeof(mDimension));
841 memset(&mCrop, 0, sizeof(mCrop));
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -0800842 memset(&zoomCropInfo, 0, sizeof(zoom_crop_info));
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -0800843 storeTargetType();
Mohan Kandra740cfce2010-01-07 12:58:24 -0800844 char value[PROPERTY_VALUE_MAX];
845 property_get("persist.debug.sf.showfps", value, "0");
846 mDebugFps = atoi(value);
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -0800847 if( mCurrentTarget == TARGET_MSM7630 )
Sravankb4f5f1c2010-01-21 11:06:17 +0530848 kPreviewBufferCountActual = kPreviewBufferCount;
849 else
850 kPreviewBufferCountActual = kPreviewBufferCount + NUM_MORE_BUFS;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800851 LOGV("constructor EX");
852}
853
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800854
855//filter Picture sizes based on max width and height
856void QualcommCameraHardware::filterPictureSizes(){
857 int i;
858 for(i=0;i<PICTURE_SIZE_COUNT;i++){
859 if(((picture_sizes[i].width <=
860 sensorType->max_supported_snapshot_width) &&
861 (picture_sizes[i].height <=
862 sensorType->max_supported_snapshot_height))){
863 picture_sizes_ptr = picture_sizes + i;
864 supportedPictureSizesCount = PICTURE_SIZE_COUNT - i ;
865 return ;
866 }
867 }
868}
869
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800870void QualcommCameraHardware::initDefaultParameters()
871{
872 LOGV("initDefaultParameters E");
873
874 // Initialize constant parameter strings. This will happen only once in the
875 // lifetime of the mediaserver process.
876 if (!parameter_string_initialized) {
Srinivasan Kannan71229622009-12-04 12:05:58 -0800877 findSensorType();
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800878 antibanding_values = create_values_str(
879 antibanding, sizeof(antibanding) / sizeof(str_map));
880 effect_values = create_values_str(
881 effects, sizeof(effects) / sizeof(str_map));
Apurva Rajguru55562b02009-12-03 12:25:35 -0800882 autoexposure_values = create_values_str(
883 autoexposure, sizeof(autoexposure) / sizeof(str_map));
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800884 whitebalance_values = create_values_str(
885 whitebalance, sizeof(whitebalance) / sizeof(str_map));
886 preview_size_values = create_sizes_str(
887 preview_sizes, PREVIEW_SIZE_COUNT);
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800888 //filter picture sizes
889 filterPictureSizes();
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800890 picture_size_values = create_sizes_str(
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800891 picture_sizes_ptr, supportedPictureSizesCount);
892
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800893 flash_values = create_values_str(
894 flash, sizeof(flash) / sizeof(str_map));
Srinivasan Kannan71229622009-12-04 12:05:58 -0800895 if(sensorType->hasAutoFocusSupport){
896 focus_mode_values = create_values_str(
897 focus_modes, sizeof(focus_modes) / sizeof(str_map));
898 }
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530899 iso_values = create_values_str(
900 iso,sizeof(iso)/sizeof(str_map));
901 lensshade_values = create_values_str(
902 lensshade,sizeof(lensshade)/sizeof(str_map));
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800903 picture_format_values = create_values_str(
904 picture_formats, sizeof(picture_formats)/sizeof(str_map));
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800905 parameter_string_initialized = true;
906 }
907
908 const camera_size_type *ps = &preview_sizes[DEFAULT_PREVIEW_SETTING];
909 mParameters.setPreviewSize(ps->width, ps->height);
910 mDimension.display_width = ps->width;
911 mDimension.display_height = ps->height;
912 mParameters.setPreviewFrameRate(15);
913 mParameters.setPreviewFormat("yuv420sp"); // informative
914
915 mParameters.setPictureSize(DEFAULT_PICTURE_WIDTH, DEFAULT_PICTURE_HEIGHT);
916 mParameters.setPictureFormat("jpeg"); // informative
917
Mohan Kandra785619a2010-02-01 21:52:42 -0800918 mParameters.set(CameraParameters::KEY_JPEG_QUALITY, "85"); // max quality
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800919 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH,
920 THUMBNAIL_WIDTH_STR); // informative
921 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT,
922 THUMBNAIL_HEIGHT_STR); // informative
Srinivasan Kannan80d878f2009-12-18 15:06:02 -0800923 mDimension.ui_thumbnail_width =
924 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].width;
925 mDimension.ui_thumbnail_height =
926 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800927 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, "90");
928
929 mParameters.set(CameraParameters::KEY_ANTIBANDING,
Mohan Kandra785619a2010-02-01 21:52:42 -0800930 CameraParameters::ANTIBANDING_OFF);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800931 mParameters.set(CameraParameters::KEY_EFFECT,
932 CameraParameters::EFFECT_NONE);
Apurva Rajguru55562b02009-12-03 12:25:35 -0800933 mParameters.set(CameraParameters::KEY_AUTO_EXPOSURE,
934 CameraParameters::AUTO_EXPOSURE_FRAME_AVG);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800935 mParameters.set(CameraParameters::KEY_WHITE_BALANCE,
936 CameraParameters::WHITE_BALANCE_AUTO);
937 mParameters.set(CameraParameters::KEY_FOCUS_MODE,
938 CameraParameters::FOCUS_MODE_AUTO);
Priya Komarlingam044c7b52010-01-22 18:21:23 -0800939 mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS,
940 "yuv420sp");
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800941
942 mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES,
943 preview_size_values.string());
944 mParameters.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES,
945 picture_size_values.string());
946 mParameters.set(CameraParameters::KEY_SUPPORTED_ANTIBANDING,
947 antibanding_values);
948 mParameters.set(CameraParameters::KEY_SUPPORTED_EFFECTS, effect_values);
Apurva Rajguru55562b02009-12-03 12:25:35 -0800949 mParameters.set(CameraParameters::KEY_SUPPORTED_AUTO_EXPOSURE, autoexposure_values);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800950 mParameters.set(CameraParameters::KEY_SUPPORTED_WHITE_BALANCE,
951 whitebalance_values);
952 mParameters.set(CameraParameters::KEY_SUPPORTED_FOCUS_MODES,
953 focus_mode_values);
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800954 mParameters.set(CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS,
955 picture_format_values);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800956
957 if (mSensorInfo.flash_enabled) {
958 mParameters.set(CameraParameters::KEY_FLASH_MODE,
959 CameraParameters::FLASH_MODE_OFF);
960 mParameters.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES,
961 flash_values);
962 }
963
Srinivasan Kannanbddfd502010-01-03 17:27:36 -0800964 mParameters.set(CameraParameters::KEY_MAX_SHARPNESS,
965 CAMERA_MAX_SHARPNESS);
966 mParameters.set(CameraParameters::KEY_MAX_CONTRAST,
967 CAMERA_MAX_CONTRAST);
968 mParameters.set(CameraParameters::KEY_MAX_SATURATION,
969 CAMERA_MAX_SATURATION);
970
Apurva Rajguru07185952010-01-22 15:40:07 -0800971 mParameters.set("luma-adaptation", "3");
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800972 mParameters.set("zoom-supported", "true");
973 mParameters.set("max-zoom", MAX_ZOOM_LEVEL);
974 mParameters.set("zoom", 0);
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800975 mParameters.set(CameraParameters::KEY_PICTURE_FORMAT,
976 CameraParameters::PIXEL_FORMAT_JPEG);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800977
Kiran Kumar H N595970b2010-01-12 10:41:09 -0800978 mParameters.set(CameraParameters::KEY_SHARPNESS,
979 CAMERA_DEF_SHARPNESS);
980 mParameters.set(CameraParameters::KEY_CONTRAST,
981 CAMERA_DEF_CONTRAST);
982 mParameters.set(CameraParameters::KEY_SATURATION,
983 CAMERA_DEF_SATURATION);
984
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530985 mParameters.set(CameraParameters::KEY_ISO_MODE,
986 CameraParameters::ISO_AUTO);
987 mParameters.set(CameraParameters::KEY_LENSSHADE,
988 CameraParameters::LENSSHADE_ENABLE);
989 mParameters.set(CameraParameters::KEY_SUPPORTED_ISO_MODES,
990 iso_values);
991 mParameters.set(CameraParameters::KEY_SUPPORTED_LENSSHADE_MODES,
992 lensshade_values);
993
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800994 if (setParameters(mParameters) != NO_ERROR) {
995 LOGE("Failed to set default parameters?!");
996 }
997
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -0800998 mUseOverlay = useOverlay();
999
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001000 /* Initialize the camframe_timeout_flag*/
1001 Mutex::Autolock l(&mCamframeTimeoutLock);
1002 camframe_timeout_flag = FALSE;
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08001003 mPostViewHeap = NULL;
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001004
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001005 LOGV("initDefaultParameters X");
1006}
1007
Srinivasan Kannan71229622009-12-04 12:05:58 -08001008void QualcommCameraHardware::findSensorType(){
1009 mDimension.picture_width = DEFAULT_PICTURE_WIDTH;
1010 mDimension.picture_height = DEFAULT_PICTURE_HEIGHT;
1011 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
1012 sizeof(cam_ctrl_dimension_t), &mDimension);
1013 if (ret) {
1014 unsigned int i;
1015 for (i = 0; i < sizeof(sensorTypes) / sizeof(SensorType); i++) {
1016 if (sensorTypes[i].rawPictureHeight
1017 == mDimension.raw_picture_height) {
1018 sensorType = sensorTypes + i;
1019 return;
1020 }
1021 }
1022 }
1023 //default to 5 mp
1024 sensorType = sensorTypes;
1025 return;
1026}
1027
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001028#define ROUND_TO_PAGE(x) (((x)+0xfff)&~0xfff)
1029
1030bool QualcommCameraHardware::startCamera()
1031{
1032 LOGV("startCamera E");
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08001033 if( mCurrentTarget == TARGET_MAX ) {
1034 LOGE(" Unable to determine the target type. Camera will not work ");
1035 return false;
1036 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001037#if DLOPEN_LIBMMCAMERA
1038 libmmcamera = ::dlopen("liboemcamera.so", RTLD_NOW);
1039 LOGV("loading liboemcamera at %p", libmmcamera);
1040 if (!libmmcamera) {
1041 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
1042 return false;
1043 }
1044
1045 *(void **)&LINK_cam_frame =
1046 ::dlsym(libmmcamera, "cam_frame");
1047 *(void **)&LINK_camframe_terminate =
1048 ::dlsym(libmmcamera, "camframe_terminate");
1049
1050 *(void **)&LINK_jpeg_encoder_init =
1051 ::dlsym(libmmcamera, "jpeg_encoder_init");
1052
1053 *(void **)&LINK_jpeg_encoder_encode =
1054 ::dlsym(libmmcamera, "jpeg_encoder_encode");
1055
1056 *(void **)&LINK_jpeg_encoder_join =
1057 ::dlsym(libmmcamera, "jpeg_encoder_join");
1058
1059 *(void **)&LINK_mmcamera_camframe_callback =
1060 ::dlsym(libmmcamera, "mmcamera_camframe_callback");
1061
1062 *LINK_mmcamera_camframe_callback = receive_camframe_callback;
1063
1064 *(void **)&LINK_mmcamera_jpegfragment_callback =
1065 ::dlsym(libmmcamera, "mmcamera_jpegfragment_callback");
1066
1067 *LINK_mmcamera_jpegfragment_callback = receive_jpeg_fragment_callback;
1068
1069 *(void **)&LINK_mmcamera_jpeg_callback =
1070 ::dlsym(libmmcamera, "mmcamera_jpeg_callback");
1071
1072 *LINK_mmcamera_jpeg_callback = receive_jpeg_callback;
1073
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001074 *(void **)&LINK_camframe_timeout_callback =
1075 ::dlsym(libmmcamera, "camframe_timeout_callback");
1076
1077 *LINK_camframe_timeout_callback = receive_camframetimeout_callback;
1078
Sravankb4f5f1c2010-01-21 11:06:17 +05301079 // 720 p new recording functions
1080 *(void **)&LINK_cam_frame_flush_free_video = ::dlsym(libmmcamera, "cam_frame_flush_free_video");
1081
1082 *(void **)&LINK_camframe_free_video = ::dlsym(libmmcamera, "cam_frame_add_free_video");
1083
1084 *(void **)&LINK_camframe_video_callback = ::dlsym(libmmcamera, "mmcamera_camframe_videocallback");
1085 *LINK_camframe_video_callback = receive_camframe_video_callback;
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001086/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001087 *(void **)&LINK_mmcamera_shutter_callback =
1088 ::dlsym(libmmcamera, "mmcamera_shutter_callback");
1089
1090 *LINK_mmcamera_shutter_callback = receive_shutter_callback;
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001091*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001092 *(void**)&LINK_jpeg_encoder_setMainImageQuality =
1093 ::dlsym(libmmcamera, "jpeg_encoder_setMainImageQuality");
Kiran Kumar H N8861f302010-01-05 12:01:41 -08001094
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001095 *(void**)&LINK_jpeg_encoder_setThumbnailQuality =
1096 ::dlsym(libmmcamera, "jpeg_encoder_setThumbnailQuality");
1097
1098 *(void**)&LINK_jpeg_encoder_setRotation =
1099 ::dlsym(libmmcamera, "jpeg_encoder_setRotation");
1100
Kiran Kumar H N8861f302010-01-05 12:01:41 -08001101/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001102 *(void**)&LINK_jpeg_encoder_setLocation =
1103 ::dlsym(libmmcamera, "jpeg_encoder_setLocation");
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001104*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001105 *(void **)&LINK_cam_conf =
1106 ::dlsym(libmmcamera, "cam_conf");
1107
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001108/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001109 *(void **)&LINK_default_sensor_get_snapshot_sizes =
1110 ::dlsym(libmmcamera, "default_sensor_get_snapshot_sizes");
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001111*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001112 *(void **)&LINK_launch_cam_conf_thread =
1113 ::dlsym(libmmcamera, "launch_cam_conf_thread");
1114
1115 *(void **)&LINK_release_cam_conf_thread =
1116 ::dlsym(libmmcamera, "release_cam_conf_thread");
1117
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001118/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001119 *(void **)&LINK_zoom_crop_upscale =
1120 ::dlsym(libmmcamera, "zoom_crop_upscale");
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001121*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001122
1123#else
1124 mmcamera_camframe_callback = receive_camframe_callback;
1125 mmcamera_jpegfragment_callback = receive_jpeg_fragment_callback;
1126 mmcamera_jpeg_callback = receive_jpeg_callback;
1127 mmcamera_shutter_callback = receive_shutter_callback;
1128#endif // DLOPEN_LIBMMCAMERA
1129
1130 /* The control thread is in libcamera itself. */
Brian Steuer07704892009-12-18 18:07:33 -08001131 if (pthread_join(w_thread, NULL) != 0) {
1132 LOGE("Camera open thread exit failed");
1133 return false;
1134 }
1135 mCameraControlFd = camerafd;
1136
Kiran Kumar H N585bc362010-01-19 13:04:44 -08001137 if (mCameraControlFd < 0) {
1138 LOGE("startCamera X: %s open failed: %s!",
1139 MSM_CAMERA_CONTROL,
1140 strerror(errno));
1141 return false;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001142 }
1143
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08001144 if( mCurrentTarget != TARGET_MSM7630 ){
Mohan Kandra284966d2010-01-05 13:39:15 -08001145 fb_fd = open("/dev/graphics/fb0", O_RDWR);
1146 if (fb_fd < 0) {
1147 LOGE("startCamera: fb0 open failed: %s!", strerror(errno));
1148 return FALSE;
1149 }
1150 }
1151
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001152 /* This will block until the control thread is launched. After that, sensor
1153 * information becomes available.
1154 */
1155
1156 if (LINK_launch_cam_conf_thread()) {
1157 LOGE("failed to launch the camera config thread");
1158 return false;
1159 }
1160
1161 memset(&mSensorInfo, 0, sizeof(mSensorInfo));
1162 if (ioctl(mCameraControlFd,
1163 MSM_CAM_IOCTL_GET_SENSOR_INFO,
1164 &mSensorInfo) < 0)
1165 LOGW("%s: cannot retrieve sensor info!", __FUNCTION__);
1166 else
1167 LOGI("%s: camsensor name %s, flash %d", __FUNCTION__,
1168 mSensorInfo.name, mSensorInfo.flash_enabled);
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001169/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001170 picture_sizes = LINK_default_sensor_get_snapshot_sizes(&PICTURE_SIZE_COUNT);
1171 if (!picture_sizes || !PICTURE_SIZE_COUNT) {
1172 LOGE("startCamera X: could not get snapshot sizes");
1173 return false;
1174 }
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001175*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001176 LOGV("startCamera X");
1177 return true;
1178}
1179
1180status_t QualcommCameraHardware::dump(int fd,
1181 const Vector<String16>& args) const
1182{
1183 const size_t SIZE = 256;
1184 char buffer[SIZE];
1185 String8 result;
1186
1187 // Dump internal primitives.
1188 result.append("QualcommCameraHardware::dump");
1189 snprintf(buffer, 255, "mMsgEnabled (%d)\n", mMsgEnabled);
1190 result.append(buffer);
1191 int width, height;
1192 mParameters.getPreviewSize(&width, &height);
1193 snprintf(buffer, 255, "preview width(%d) x height (%d)\n", width, height);
1194 result.append(buffer);
1195 mParameters.getPictureSize(&width, &height);
1196 snprintf(buffer, 255, "raw width(%d) x height (%d)\n", width, height);
1197 result.append(buffer);
1198 snprintf(buffer, 255,
1199 "preview frame size(%d), raw size (%d), jpeg size (%d) "
1200 "and jpeg max size (%d)\n", mPreviewFrameSize, mRawSize,
1201 mJpegSize, mJpegMaxSize);
1202 result.append(buffer);
1203 write(fd, result.string(), result.size());
1204
1205 // Dump internal objects.
Mohan Kandrad9efed92010-01-15 19:08:39 -08001206 if (mPreviewHeap != 0) {
1207 mPreviewHeap->dump(fd, args);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001208 }
1209 if (mRawHeap != 0) {
1210 mRawHeap->dump(fd, args);
1211 }
1212 if (mJpegHeap != 0) {
1213 mJpegHeap->dump(fd, args);
1214 }
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001215 if(mRawSnapshotAshmemHeap != 0 ){
1216 mRawSnapshotAshmemHeap->dump(fd, args);
1217 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001218 mParameters.dump(fd, args);
1219 return NO_ERROR;
1220}
1221
Mohan Kandra284966d2010-01-05 13:39:15 -08001222static bool native_get_maxzoom(int camfd, void *pZm)
1223{
1224 LOGV("native_get_maxzoom E");
1225
1226 struct msm_ctrl_cmd ctrlCmd;
1227 int32_t *pZoom = (int32_t *)pZm;
1228
1229 ctrlCmd.type = CAMERA_GET_PARM_MAXZOOM;
1230 ctrlCmd.timeout_ms = 5000;
1231 ctrlCmd.length = sizeof(int32_t);
1232 ctrlCmd.value = pZoom;
1233 ctrlCmd.resp_fd = camfd;
1234
1235 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1236 LOGE("native_get_maxzoom: ioctl fd %d error %s",
1237 camfd,
1238 strerror(errno));
1239 return false;
1240 }
Brian Steuerb62adbd2010-02-02 14:47:08 -08001241 LOGD("ctrlCmd.value = %d", *(int32_t *)ctrlCmd.value);
Mohan Kandra284966d2010-01-05 13:39:15 -08001242 memcpy(pZoom, (int32_t *)ctrlCmd.value, sizeof(int32_t));
1243
1244 LOGV("native_get_maxzoom X");
1245 return true;
1246}
1247
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001248static bool native_set_afmode(int camfd, isp3a_af_mode_t af_type)
1249{
1250 int rc;
1251 struct msm_ctrl_cmd ctrlCmd;
1252
1253 ctrlCmd.timeout_ms = 5000;
1254 ctrlCmd.type = CAMERA_SET_PARM_AUTO_FOCUS;
1255 ctrlCmd.length = sizeof(af_type);
1256 ctrlCmd.value = &af_type;
1257 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1258
1259 if ((rc = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0)
1260 LOGE("native_set_afmode: ioctl fd %d error %s\n",
1261 camfd,
1262 strerror(errno));
1263
1264 LOGV("native_set_afmode: ctrlCmd.status == %d\n", ctrlCmd.status);
1265 return rc >= 0 && ctrlCmd.status == CAMERA_EXIT_CB_DONE;
1266}
1267
1268static bool native_cancel_afmode(int camfd, int af_fd)
1269{
1270 int rc;
1271 struct msm_ctrl_cmd ctrlCmd;
1272
1273 ctrlCmd.timeout_ms = 0;
1274 ctrlCmd.type = CAMERA_AUTO_FOCUS_CANCEL;
1275 ctrlCmd.length = 0;
1276 ctrlCmd.value = NULL;
1277 ctrlCmd.resp_fd = -1; // there's no response fd
1278
1279 if ((rc = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND_2, &ctrlCmd)) < 0)
1280 {
1281 LOGE("native_cancel_afmode: ioctl fd %d error %s\n",
1282 camfd,
1283 strerror(errno));
1284 return false;
1285 }
1286
1287 return true;
1288}
1289
1290static bool native_start_preview(int camfd)
1291{
1292 struct msm_ctrl_cmd ctrlCmd;
1293
1294 ctrlCmd.timeout_ms = 5000;
1295 ctrlCmd.type = CAMERA_START_PREVIEW;
1296 ctrlCmd.length = 0;
1297 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1298
1299 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1300 LOGE("native_start_preview: MSM_CAM_IOCTL_CTRL_COMMAND fd %d error %s",
1301 camfd,
1302 strerror(errno));
1303 return false;
1304 }
1305
1306 return true;
1307}
1308
1309static bool native_get_picture (int camfd, common_crop_t *crop)
1310{
1311 struct msm_ctrl_cmd ctrlCmd;
1312
1313 ctrlCmd.timeout_ms = 5000;
1314 ctrlCmd.length = sizeof(common_crop_t);
1315 ctrlCmd.value = crop;
1316
1317 if(ioctl(camfd, MSM_CAM_IOCTL_GET_PICTURE, &ctrlCmd) < 0) {
1318 LOGE("native_get_picture: MSM_CAM_IOCTL_GET_PICTURE fd %d error %s",
1319 camfd,
1320 strerror(errno));
1321 return false;
1322 }
1323
1324 LOGV("crop: in1_w %d", crop->in1_w);
1325 LOGV("crop: in1_h %d", crop->in1_h);
1326 LOGV("crop: out1_w %d", crop->out1_w);
1327 LOGV("crop: out1_h %d", crop->out1_h);
1328
1329 LOGV("crop: in2_w %d", crop->in2_w);
1330 LOGV("crop: in2_h %d", crop->in2_h);
1331 LOGV("crop: out2_w %d", crop->out2_w);
1332 LOGV("crop: out2_h %d", crop->out2_h);
1333
1334 LOGV("crop: update %d", crop->update_flag);
1335
1336 return true;
1337}
1338
1339static bool native_stop_preview(int camfd)
1340{
1341 struct msm_ctrl_cmd ctrlCmd;
1342 ctrlCmd.timeout_ms = 5000;
1343 ctrlCmd.type = CAMERA_STOP_PREVIEW;
1344 ctrlCmd.length = 0;
1345 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1346
1347 if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1348 LOGE("native_stop_preview: ioctl fd %d error %s",
1349 camfd,
1350 strerror(errno));
1351 return false;
1352 }
1353
1354 return true;
1355}
1356
1357static bool native_prepare_snapshot(int camfd)
1358{
1359 int ioctlRetVal = true;
1360 struct msm_ctrl_cmd ctrlCmd;
1361
1362 ctrlCmd.timeout_ms = 1000;
1363 ctrlCmd.type = CAMERA_PREPARE_SNAPSHOT;
1364 ctrlCmd.length = 0;
1365 ctrlCmd.value = NULL;
1366 ctrlCmd.resp_fd = camfd;
1367
1368 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1369 LOGE("native_prepare_snapshot: ioctl fd %d error %s",
1370 camfd,
1371 strerror(errno));
1372 return false;
1373 }
1374 return true;
1375}
1376
1377static bool native_start_snapshot(int camfd)
1378{
1379 struct msm_ctrl_cmd ctrlCmd;
1380
1381 ctrlCmd.timeout_ms = 5000;
1382 ctrlCmd.type = CAMERA_START_SNAPSHOT;
1383 ctrlCmd.length = 0;
1384 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1385
1386 if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1387 LOGE("native_start_snapshot: ioctl fd %d error %s",
1388 camfd,
1389 strerror(errno));
1390 return false;
1391 }
1392
1393 return true;
1394}
1395
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001396static bool native_start_raw_snapshot(int camfd)
1397{
1398 int ret;
1399 struct msm_ctrl_cmd ctrlCmd;
1400
1401 ctrlCmd.timeout_ms = 1000;
1402 ctrlCmd.type = CAMERA_START_RAW_SNAPSHOT;
1403 ctrlCmd.length = 0;
1404 ctrlCmd.value = NULL;
1405 ctrlCmd.resp_fd = camfd;
1406
1407 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1408 LOGE("native_start_raw_snapshot: ioctl failed. ioctl return value "\
1409 "is %d \n", ret);
1410 return false;
1411 }
1412 return true;
1413}
1414
1415
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001416static bool native_stop_snapshot (int camfd)
1417{
1418 struct msm_ctrl_cmd ctrlCmd;
1419
1420 ctrlCmd.timeout_ms = 0;
1421 ctrlCmd.type = CAMERA_STOP_SNAPSHOT;
1422 ctrlCmd.length = 0;
1423 ctrlCmd.resp_fd = -1;
1424
1425 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND_2, &ctrlCmd) < 0) {
1426 LOGE("native_stop_snapshot: ioctl fd %d error %s",
1427 camfd,
1428 strerror(errno));
1429 return false;
1430 }
1431
1432 return true;
1433}
Sravankb4f5f1c2010-01-21 11:06:17 +05301434/*===========================================================================
1435 * FUNCTION - native_start_recording -
1436 *
1437 * DESCRIPTION:
1438 *==========================================================================*/
1439static bool native_start_recording(int camfd)
1440{
1441 int ret;
1442 struct msm_ctrl_cmd ctrlCmd;
1443
1444 ctrlCmd.timeout_ms = 1000;
1445 ctrlCmd.type = CAMERA_START_RECORDING;
1446 ctrlCmd.length = 0;
1447 ctrlCmd.value = NULL;
1448 ctrlCmd.resp_fd = camfd;
1449
1450 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1451 LOGE("native_start_recording: ioctl failed. ioctl return value "\
1452 "is %d \n", ret);
1453 return false;
1454 }
Mohan Kandraf1ebf982010-02-02 15:25:43 -08001455 LOGV("native_start_recording: ioctl good. ioctl return value is %d \n",ret);
Sravankb4f5f1c2010-01-21 11:06:17 +05301456
1457 /* TODO: Check status of postprocessing if there is any,
1458 * PP status should be in ctrlCmd */
1459
1460 return true;
1461}
1462
1463/*===========================================================================
1464 * FUNCTION - native_stop_recording -
1465 *
1466 * DESCRIPTION:
1467 *==========================================================================*/
1468static bool native_stop_recording(int camfd)
1469{
1470 int ret;
1471 struct msm_ctrl_cmd ctrlCmd;
1472LOGE("in native_stop_recording ");
1473 ctrlCmd.timeout_ms = 1000;
1474 ctrlCmd.type = CAMERA_STOP_RECORDING;
1475 ctrlCmd.length = 0;
1476 ctrlCmd.value = NULL;
1477 ctrlCmd.resp_fd = camfd;
1478
1479 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1480 LOGE("native_stop_video: ioctl failed. ioctl return value is %d \n",
1481 ret);
1482 return false;
1483 }
1484 LOGV("in native_stop_recording returned %d", ret);
1485 return true;
1486}
1487/*===========================================================================
1488 * FUNCTION - native_start_video -
1489 *
1490 * DESCRIPTION:
1491 *==========================================================================*/
1492static bool native_start_video(int camfd)
1493{
1494 int ret;
1495 struct msm_ctrl_cmd ctrlCmd;
1496
1497 ctrlCmd.timeout_ms = 1000;
1498 ctrlCmd.type = CAMERA_START_VIDEO;
1499 ctrlCmd.length = 0;
1500 ctrlCmd.value = NULL;
1501 ctrlCmd.resp_fd = camfd;
1502
1503 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1504 LOGE("native_start_video: ioctl failed. ioctl return value is %d \n",
1505 ret);
1506 return false;
1507 }
1508
1509 /* TODO: Check status of postprocessing if there is any,
1510 * PP status should be in ctrlCmd */
1511
1512 return true;
1513}
1514
1515/*===========================================================================
1516 * FUNCTION - native_stop_video -
1517 *
1518 * DESCRIPTION:
1519 *==========================================================================*/
1520static bool native_stop_video(int camfd)
1521{
1522 int ret;
1523 struct msm_ctrl_cmd ctrlCmd;
1524
1525 ctrlCmd.timeout_ms = 1000;
1526 ctrlCmd.type = CAMERA_STOP_VIDEO;
1527 ctrlCmd.length = 0;
1528 ctrlCmd.value = NULL;
1529 ctrlCmd.resp_fd = camfd;
1530
1531 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1532 LOGE("native_stop_video: ioctl failed. ioctl return value is %d \n",
1533 ret);
1534 return false;
1535 }
1536
1537 return true;
1538}
1539/*==========================================================================*/
1540
1541static cam_frame_start_parms frame_parms;
1542static int recordingState = 0;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001543
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001544static rat_t latitude[3];
1545static rat_t longitude[3];
1546static char lonref[2];
1547static char latref[2];
1548static char dateTime[20];
1549static rat_t altitude;
1550
1551static void addExifTag(exif_tag_id_t tagid, exif_tag_type_t type,
1552 uint32_t count, uint8_t copy, void *data) {
1553
1554 if(exif_table_numEntries == MAX_EXIF_TABLE_ENTRIES) {
1555 LOGE("Number of entries exceeded limit");
1556 return;
1557 }
1558
1559 int index = exif_table_numEntries;
1560 exif_data[index].tag_id = tagid;
1561 exif_data[index].tag_entry.type = type;
1562 exif_data[index].tag_entry.count = count;
1563 exif_data[index].tag_entry.copy = copy;
1564 if((type == EXIF_RATIONAL) && (count > 1))
1565 exif_data[index].tag_entry.data._rats = (rat_t *)data;
1566 if((type == EXIF_RATIONAL) && (count == 1))
1567 exif_data[index].tag_entry.data._rat = *(rat_t *)data;
1568 else if(type == EXIF_ASCII)
1569 exif_data[index].tag_entry.data._ascii = (char *)data;
1570 else if(type == EXIF_BYTE)
1571 exif_data[index].tag_entry.data._byte = *(uint8_t *)data;
1572
1573 // Increase number of entries
1574 exif_table_numEntries++;
1575}
1576
1577static void parseLatLong(const char *latlonString, int *pDegrees,
1578 int *pMinutes, int *pSeconds ) {
1579
1580 double value = atof(latlonString);
1581 value = fabs(value);
1582 int degrees = (int) value;
1583
1584 double remainder = value - degrees;
1585 int minutes = (int) (remainder * 60);
1586 int seconds = (int) (((remainder * 60) - minutes) * 60 * 1000);
1587
1588 *pDegrees = degrees;
1589 *pMinutes = minutes;
1590 *pSeconds = seconds;
1591}
1592
1593static void setLatLon(exif_tag_id_t tag, const char *latlonString) {
1594
1595 int degrees, minutes, seconds;
1596
1597 parseLatLong(latlonString, &degrees, &minutes, &seconds);
1598
1599 rat_t value[3] = { {degrees, 1},
1600 {minutes, 1},
1601 {seconds, 1000} };
1602
1603 if(tag == EXIFTAGID_GPS_LATITUDE) {
1604 memcpy(latitude, value, sizeof(latitude));
1605 addExifTag(EXIFTAGID_GPS_LATITUDE, EXIF_RATIONAL, 3,
1606 1, (void *)latitude);
1607 } else {
1608 memcpy(longitude, value, sizeof(longitude));
1609 addExifTag(EXIFTAGID_GPS_LONGITUDE, EXIF_RATIONAL, 3,
1610 1, (void *)longitude);
1611 }
1612}
1613
1614void QualcommCameraHardware::setGpsParameters() {
1615 const char *str = NULL;
1616
1617 //Set Latitude
1618 str = mParameters.get(CameraParameters::KEY_GPS_LATITUDE);
1619 if(str != NULL) {
1620 setLatLon(EXIFTAGID_GPS_LATITUDE, str);
1621 //set Latitude Ref
1622 str = NULL;
1623 str = mParameters.get(CameraParameters::KEY_GPS_LATITUDE_REF);
1624 if(str != NULL) {
1625 strncpy(latref, str, 1);
1626 latref[1] = '\0';
1627 addExifTag(EXIFTAGID_GPS_LATITUDE_REF, EXIF_ASCII, 2,
1628 1, (void *)latref);
1629 }
1630 }
1631
1632 //set Longitude
1633 str = NULL;
1634 str = mParameters.get(CameraParameters::KEY_GPS_LONGITUDE);
1635 if(str != NULL) {
1636 setLatLon(EXIFTAGID_GPS_LONGITUDE, str);
1637 //set Longitude Ref
1638 str = NULL;
1639 str = mParameters.get(CameraParameters::KEY_GPS_LONGITUDE_REF);
1640 if(str != NULL) {
1641 strncpy(lonref, str, 1);
1642 lonref[1] = '\0';
1643 addExifTag(EXIFTAGID_GPS_LONGITUDE_REF, EXIF_ASCII, 2,
1644 1, (void *)lonref);
1645 }
1646 }
1647
1648 //set Altitude
1649 str = NULL;
1650 str = mParameters.get(CameraParameters::KEY_GPS_ALTITUDE);
1651 if(str != NULL) {
1652 int value = atoi(str);
1653 rat_t alt_value = {value, 1000};
1654 memcpy(&altitude, &alt_value, sizeof(altitude));
1655 addExifTag(EXIFTAGID_GPS_ALTITUDE, EXIF_RATIONAL, 1,
1656 1, (void *)&altitude);
1657 //set AltitudeRef
1658 int ref = mParameters.getInt(CameraParameters::KEY_GPS_ALTITUDE_REF);
1659 if( !(ref < 0 || ref > 1) )
1660 addExifTag(EXIFTAGID_GPS_ALTITUDE_REF, EXIF_BYTE, 1,
1661 1, (void *)&ref);
1662 }
1663
1664
1665}
1666
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001667bool QualcommCameraHardware::native_jpeg_encode(void)
1668{
1669 int jpeg_quality = mParameters.getInt("jpeg-quality");
1670 if (jpeg_quality >= 0) {
1671 LOGV("native_jpeg_encode, current jpeg main img quality =%d",
1672 jpeg_quality);
1673 if(!LINK_jpeg_encoder_setMainImageQuality(jpeg_quality)) {
1674 LOGE("native_jpeg_encode set jpeg-quality failed");
1675 return false;
1676 }
1677 }
1678
1679 int thumbnail_quality = mParameters.getInt("jpeg-thumbnail-quality");
1680 if (thumbnail_quality >= 0) {
1681 LOGV("native_jpeg_encode, current jpeg thumbnail quality =%d",
1682 thumbnail_quality);
1683 if(!LINK_jpeg_encoder_setThumbnailQuality(thumbnail_quality)) {
1684 LOGE("native_jpeg_encode set thumbnail-quality failed");
1685 return false;
1686 }
1687 }
1688
1689 int rotation = mParameters.getInt("rotation");
1690 if (rotation >= 0) {
1691 LOGV("native_jpeg_encode, rotation = %d", rotation);
1692 if(!LINK_jpeg_encoder_setRotation(rotation)) {
1693 LOGE("native_jpeg_encode set rotation failed");
1694 return false;
1695 }
1696 }
1697
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001698// jpeg_set_location();
1699 if(mParameters.getInt(CameraParameters::KEY_GPS_STATUS) == 1) {
1700 setGpsParameters();
1701 }
1702 //set TimeStamp
1703 const char *str = mParameters.get(CameraParameters::KEY_EXIF_DATETIME);
1704 if(str != NULL) {
1705 strncpy(dateTime, str, 19);
1706 dateTime[19] = '\0';
1707 addExifTag(EXIFTAGID_EXIF_DATE_TIME_ORIGINAL, EXIF_ASCII,
1708 20, 1, (void *)dateTime);
1709 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001710
1711 if (!LINK_jpeg_encoder_encode(&mDimension,
1712 (uint8_t *)mThumbnailHeap->mHeap->base(),
1713 mThumbnailHeap->mHeap->getHeapID(),
1714 (uint8_t *)mRawHeap->mHeap->base(),
1715 mRawHeap->mHeap->getHeapID(),
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001716 &mCrop, exif_data, exif_table_numEntries)) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001717 LOGE("native_jpeg_encode: jpeg_encoder_encode failed.");
1718 return false;
1719 }
1720 return true;
1721}
1722
1723bool QualcommCameraHardware::native_set_parm(
1724 cam_ctrl_type type, uint16_t length, void *value)
1725{
1726 struct msm_ctrl_cmd ctrlCmd;
1727
1728 ctrlCmd.timeout_ms = 5000;
1729 ctrlCmd.type = (uint16_t)type;
1730 ctrlCmd.length = length;
1731 // FIXME: this will be put in by the kernel
1732 ctrlCmd.resp_fd = mCameraControlFd;
1733 ctrlCmd.value = value;
1734
1735 LOGV("%s: fd %d, type %d, length %d", __FUNCTION__,
1736 mCameraControlFd, type, length);
1737 if (ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0 ||
1738 ctrlCmd.status != CAM_CTRL_SUCCESS) {
1739 LOGE("%s: error (%s): fd %d, type %d, length %d, status %d",
1740 __FUNCTION__, strerror(errno),
1741 mCameraControlFd, type, length, ctrlCmd.status);
1742 return false;
1743 }
1744 return true;
1745}
1746
1747void QualcommCameraHardware::jpeg_set_location()
1748{
1749 bool encode_location = true;
1750 camera_position_type pt;
1751
1752#define PARSE_LOCATION(what,type,fmt,desc) do { \
1753 pt.what = 0; \
1754 const char *what##_str = mParameters.get("gps-"#what); \
1755 LOGV("GPS PARM %s --> [%s]", "gps-"#what, what##_str); \
1756 if (what##_str) { \
1757 type what = 0; \
1758 if (sscanf(what##_str, fmt, &what) == 1) \
1759 pt.what = what; \
1760 else { \
1761 LOGE("GPS " #what " %s could not" \
1762 " be parsed as a " #desc, what##_str); \
1763 encode_location = false; \
1764 } \
1765 } \
1766 else { \
1767 LOGV("GPS " #what " not specified: " \
1768 "defaulting to zero in EXIF header."); \
1769 encode_location = false; \
1770 } \
1771 } while(0)
1772
1773 PARSE_LOCATION(timestamp, long, "%ld", "long");
1774 if (!pt.timestamp) pt.timestamp = time(NULL);
1775 PARSE_LOCATION(altitude, short, "%hd", "short");
1776 PARSE_LOCATION(latitude, double, "%lf", "double float");
1777 PARSE_LOCATION(longitude, double, "%lf", "double float");
1778
1779#undef PARSE_LOCATION
1780
1781 if (encode_location) {
1782 LOGD("setting image location ALT %d LAT %lf LON %lf",
1783 pt.altitude, pt.latitude, pt.longitude);
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001784/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001785 if (!LINK_jpeg_encoder_setLocation(&pt)) {
1786 LOGE("jpeg_set_location: LINK_jpeg_encoder_setLocation failed.");
1787 }
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001788*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001789 }
1790 else LOGV("not setting image location");
1791}
1792
1793void QualcommCameraHardware::runFrameThread(void *data)
1794{
1795 LOGV("runFrameThread E");
1796
1797 int cnt;
1798
1799#if DLOPEN_LIBMMCAMERA
1800 // We need to maintain a reference to libqcamera.so for the duration of the
1801 // frame thread, because we do not know when it will exit relative to the
1802 // lifetime of this object. We do not want to dlclose() libqcamera while
1803 // LINK_cam_frame is still running.
1804 void *libhandle = ::dlopen("liboemcamera.so", RTLD_NOW);
1805 LOGV("FRAME: loading libqcamera at %p", libhandle);
1806 if (!libhandle) {
1807 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
1808 }
1809 if (libhandle)
1810#endif
1811 {
1812 LINK_cam_frame(data);
1813 }
1814
Mohan Kandrad9efed92010-01-15 19:08:39 -08001815 mPreviewHeap.clear();
Mohan Kandraf1ebf982010-02-02 15:25:43 -08001816 if(( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250))
Sravankb4f5f1c2010-01-21 11:06:17 +05301817 mRecordHeap.clear();
1818
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001819#if DLOPEN_LIBMMCAMERA
1820 if (libhandle) {
1821 ::dlclose(libhandle);
1822 LOGV("FRAME: dlclose(libqcamera)");
1823 }
1824#endif
1825
1826 mFrameThreadWaitLock.lock();
1827 mFrameThreadRunning = false;
1828 mFrameThreadWait.signal();
1829 mFrameThreadWaitLock.unlock();
1830
1831 LOGV("runFrameThread X");
1832}
1833
Sravankb4f5f1c2010-01-21 11:06:17 +05301834void QualcommCameraHardware::runVideoThread(void *data)
1835{
1836 LOGD("runVideoThread E");
1837 msm_frame* vframe = NULL;
1838
1839 while(true) {
1840 pthread_mutex_lock(&(g_busy_frame_queue.mut));
1841
1842 LOGE("in video_thread : wait for video frame ");
1843 // check if any frames are available in busyQ and give callback to
1844 // services/video encoder
1845 cam_frame_wait_video();
1846 LOGV("video_thread, wait over..");
1847
1848 // Exit the thread , in case of stop recording..
1849 mVideoThreadWaitLock.lock();
1850 if(mVideoThreadExit){
1851 LOGE("Exiting video thread..");
1852 mVideoThreadWaitLock.unlock();
1853 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
1854 break;
1855 }
1856 mVideoThreadWaitLock.unlock();
1857
1858 // Get the video frame to be encoded
1859 vframe = cam_frame_get_video ();
Apurva Rajgurud9b0b302010-02-19 11:22:56 -08001860 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
Sravankb4f5f1c2010-01-21 11:06:17 +05301861 LOGV("in video_thread : got video frame ");
1862
1863 if(vframe != NULL) {
1864 // Find the offset within the heap of the current buffer.
1865 LOGV("Got video frame : buffer %d base %d ", vframe->buffer, mRecordHeap->mHeap->base());
1866 ssize_t offset =
1867 (ssize_t)vframe->buffer - (ssize_t)mRecordHeap->mHeap->base();
1868 LOGV("offset = %d , alignsize = %d , offset later = %d", offset, mRecordHeap->mAlignedBufferSize, (offset / mRecordHeap->mAlignedBufferSize));
1869
1870 offset /= mRecordHeap->mAlignedBufferSize;
1871
1872 // dump frames for test purpose
1873#ifdef DUMP_VIDEO_FRAMES
1874 static int frameCnt = 0;
1875 if (frameCnt >= 11 && frameCnt <= 13 ) {
1876 char buf[128];
1877 sprintf(buf, "/data/%d_v.yuv", frameCnt);
1878 int file_fd = open(buf, O_RDWR | O_CREAT, 0777);
1879 LOGV("dumping video frame %d", frameCnt);
1880 if (file_fd < 0) {
1881 LOGE("cannot open file\n");
1882 }
1883 else
1884 {
1885 write(file_fd, (const void *)vframe->buffer,
1886 vframe->cbcr_off * 3 / 2);
1887 }
1888 close(file_fd);
1889 }
1890 frameCnt++;
1891#endif
1892 // Enable IF block to give frames to encoder , ELSE block for just simulation
1893#if 1
1894 LOGV("in video_thread : got video frame, before if check giving frame to services/encoder");
1895 mCallbackLock.lock();
1896 int msgEnabled = mMsgEnabled;
1897 data_callback_timestamp rcb = mDataCallbackTimestamp;
1898 void *rdata = mCallbackCookie;
1899 mCallbackLock.unlock();
1900
1901 if(rcb != NULL && (msgEnabled & CAMERA_MSG_VIDEO_FRAME) ) {
1902 LOGV("in video_thread : got video frame, giving frame to services/encoder");
1903 rcb(systemTime(), CAMERA_MSG_VIDEO_FRAME, mRecordHeap->mBuffers[offset], rdata);
1904 Mutex::Autolock rLock(&mRecordFrameLock);
1905 if (mReleasedRecordingFrame != true) {
1906 LOGV("block waiting for frame release");
1907 mRecordWait.wait(mRecordFrameLock);
1908 LOGV("video frame released, continuing");
1909 }
1910 mReleasedRecordingFrame = false;
1911 }
1912#else
1913 // 720p output2 : simulate release frame here:
1914 LOGE("in video_thread simulation , releasing the video frame");
1915 LINK_camframe_free_video(vframe);
1916#endif
1917
1918 } else LOGE("in video_thread get frame returned null");
1919
Sravankb4f5f1c2010-01-21 11:06:17 +05301920
1921 } // end of while loop
Mohan Kandra156d0ac2010-01-25 16:59:17 -08001922
1923 mVideoThreadWaitLock.lock();
1924 mVideoThreadRunning = false;
1925 mVideoThreadWait.signal();
1926 mVideoThreadWaitLock.unlock();
1927
Sravankb4f5f1c2010-01-21 11:06:17 +05301928 LOGV("runVideoThread X");
1929}
1930
1931void *video_thread(void *user)
1932{
1933 LOGV("video_thread E");
1934 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
1935 if (obj != 0) {
1936 obj->runVideoThread(user);
1937 }
1938 else LOGE("not starting video thread: the object went away!");
1939 LOGV("video_thread X");
1940 return NULL;
1941}
1942
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001943void *frame_thread(void *user)
1944{
1945 LOGD("frame_thread E");
1946 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
1947 if (obj != 0) {
1948 obj->runFrameThread(user);
1949 }
1950 else LOGW("not starting frame thread: the object went away!");
1951 LOGD("frame_thread X");
1952 return NULL;
1953}
1954
1955bool QualcommCameraHardware::initPreview()
1956{
1957 // See comments in deinitPreview() for why we have to wait for the frame
1958 // thread here, and why we can't use pthread_join().
Sravankb4f5f1c2010-01-21 11:06:17 +05301959 int videoWidth, videoHeight;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001960 mParameters.getPreviewSize(&previewWidth, &previewHeight);
Sravankb4f5f1c2010-01-21 11:06:17 +05301961
1962 videoWidth = previewWidth; // temporary , should be configurable later
1963 videoHeight = previewHeight;
1964 LOGV("initPreview E: preview size=%dx%d videosize = %d x %d", previewWidth, previewHeight, videoWidth, videoHeight );
1965
Mohan Kandraf1ebf982010-02-02 15:25:43 -08001966 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05301967 mDimension.video_width = videoWidth;
Kiran Kumar H N7ac84e32010-02-01 10:58:47 -08001968 mDimension.video_width = CEILING16(mDimension.video_width);
Sravankb4f5f1c2010-01-21 11:06:17 +05301969 mDimension.video_height = videoHeight;
1970 LOGV("initPreview : preview size=%dx%d videosize = %d x %d", previewWidth, previewHeight, mDimension.video_width, mDimension.video_height );
1971 }
1972
1973
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001974 mFrameThreadWaitLock.lock();
1975 while (mFrameThreadRunning) {
1976 LOGV("initPreview: waiting for old frame thread to complete.");
1977 mFrameThreadWait.wait(mFrameThreadWaitLock);
1978 LOGV("initPreview: old frame thread completed.");
1979 }
1980 mFrameThreadWaitLock.unlock();
1981
1982 mSnapshotThreadWaitLock.lock();
1983 while (mSnapshotThreadRunning) {
1984 LOGV("initPreview: waiting for old snapshot thread to complete.");
1985 mSnapshotThreadWait.wait(mSnapshotThreadWaitLock);
1986 LOGV("initPreview: old snapshot thread completed.");
1987 }
1988 mSnapshotThreadWaitLock.unlock();
1989
1990 int cnt = 0;
1991 mPreviewFrameSize = previewWidth * previewHeight * 3/2;
Mohan Kandrad9efed92010-01-15 19:08:39 -08001992 dstOffset = 0;
1993 mPreviewHeap = new PmemPool("/dev/pmem_adsp",
Mohan Kandra284966d2010-01-05 13:39:15 -08001994 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
1995 mCameraControlFd,
Sravankb4f5f1c2010-01-21 11:06:17 +05301996 MSM_PMEM_PREVIEW, //MSM_PMEM_OUTPUT2,
Mohan Kandra284966d2010-01-05 13:39:15 -08001997 mPreviewFrameSize,
Mohan Kandrad9efed92010-01-15 19:08:39 -08001998 kPreviewBufferCountActual,
Mohan Kandra284966d2010-01-05 13:39:15 -08001999 mPreviewFrameSize,
Mohan Kandrad9efed92010-01-15 19:08:39 -08002000 "preview");
Mohan Kandra284966d2010-01-05 13:39:15 -08002001
Mohan Kandrad9efed92010-01-15 19:08:39 -08002002 if (!mPreviewHeap->initialized()) {
2003 mPreviewHeap.clear();
Mohan Kandra284966d2010-01-05 13:39:15 -08002004 LOGE("initPreview X: could not initialize Camera preview heap.");
2005 return false;
2006 }
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002007 if( mCurrentTarget == TARGET_MSM7630 ) {
Srinivasan Kannan613301c2010-02-10 17:08:53 -08002008 mPostViewHeap.clear();
Kiran Kumar H N595970b2010-01-12 10:41:09 -08002009 if(mPostViewHeap == NULL) {
2010 LOGV(" Allocating Postview heap ");
2011 /* mPostViewHeap should be declared only for 7630 target */
2012 mPostViewHeap =
2013 new PmemPool("/dev/pmem_adsp",
2014 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
2015 mCameraControlFd,
Sravankb4f5f1c2010-01-21 11:06:17 +05302016 MSM_PMEM_PREVIEW, //MSM_PMEM_OUTPUT2,
Kiran Kumar H N595970b2010-01-12 10:41:09 -08002017 mPreviewFrameSize,
2018 1,
2019 mPreviewFrameSize,
2020 "postview");
Mohan Kandra284966d2010-01-05 13:39:15 -08002021
Kiran Kumar H N595970b2010-01-12 10:41:09 -08002022 if (!mPostViewHeap->initialized()) {
2023 mPostViewHeap.clear();
2024 LOGE(" Failed to initialize Postview Heap");
2025 return false;
2026 }
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002027 }
Mohan Kandraf1ebf982010-02-02 15:25:43 -08002028 }
2029
2030 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250) ) {
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002031
2032 // Allocate video buffers after allocating preview buffers.
Sravankb4f5f1c2010-01-21 11:06:17 +05302033 initRecord();
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002034 }
Sravankb4f5f1c2010-01-21 11:06:17 +05302035
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002036 // mDimension will be filled with thumbnail_width, thumbnail_height,
2037 // orig_picture_dx, and orig_picture_dy after this function call. We need to
2038 // keep it for jpeg_encoder_encode.
2039 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
2040 sizeof(cam_ctrl_dimension_t), &mDimension);
2041
2042 if (ret) {
2043 for (cnt = 0; cnt < kPreviewBufferCount; cnt++) {
Mohan Kandrad9efed92010-01-15 19:08:39 -08002044 frames[cnt].fd = mPreviewHeap->mHeap->getHeapID();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002045 frames[cnt].buffer =
Mohan Kandrad9efed92010-01-15 19:08:39 -08002046 (uint32_t)mPreviewHeap->mHeap->base() + mPreviewHeap->mAlignedBufferSize * cnt;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002047 frames[cnt].y_off = 0;
2048 frames[cnt].cbcr_off = previewWidth * previewHeight;
Sravankb4f5f1c2010-01-21 11:06:17 +05302049 frames[cnt].path = OUTPUT_TYPE_P; // MSM_FRAME_ENC;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002050 }
2051
2052 mFrameThreadWaitLock.lock();
2053 pthread_attr_t attr;
2054 pthread_attr_init(&attr);
2055 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
Sravankb4f5f1c2010-01-21 11:06:17 +05302056
2057 frame_parms.frame = frames[kPreviewBufferCount - 1];
2058 frame_parms.video_frame = recordframes[kPreviewBufferCount - 1];
2059
2060 LOGV ("initpreview before cam_frame thread carete , video frame buffer=%lu fd=%d y_off=%d cbcr_off=%d \n",
2061 (unsigned long)frame_parms.video_frame.buffer, frame_parms.video_frame.fd, frame_parms.video_frame.y_off,
2062 frame_parms.video_frame.cbcr_off);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002063 mFrameThreadRunning = !pthread_create(&mFrameThread,
2064 &attr,
2065 frame_thread,
Sravankb4f5f1c2010-01-21 11:06:17 +05302066 (void*)&(frame_parms));
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002067 ret = mFrameThreadRunning;
2068 mFrameThreadWaitLock.unlock();
2069 }
2070
2071 LOGV("initPreview X: %d", ret);
2072 return ret;
2073}
2074
2075void QualcommCameraHardware::deinitPreview(void)
2076{
2077 LOGI("deinitPreview E");
2078
2079 // When we call deinitPreview(), we signal to the frame thread that it
2080 // needs to exit, but we DO NOT WAIT for it to complete here. The problem
2081 // is that deinitPreview is sometimes called from the frame-thread's
2082 // callback, when the refcount on the Camera client reaches zero. If we
2083 // called pthread_join(), we would deadlock. So, we just call
2084 // LINK_camframe_terminate() in deinitPreview(), which makes sure that
2085 // after the preview callback returns, the camframe thread will exit. We
2086 // could call pthread_join() in initPreview() to join the last frame
2087 // thread. However, we would also have to call pthread_join() in release
2088 // as well, shortly before we destroy the object; this would cause the same
2089 // deadlock, since release(), like deinitPreview(), may also be called from
2090 // the frame-thread's callback. This we have to make the frame thread
2091 // detached, and use a separate mechanism to wait for it to complete.
2092
Kiran Kumar H N7ac84e32010-02-01 10:58:47 -08002093 LINK_camframe_terminate();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002094 LOGI("deinitPreview X");
2095}
2096
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002097bool QualcommCameraHardware::initRawSnapshot()
2098{
2099 LOGV("initRawSnapshot E");
2100
2101 //get width and height from Dimension Object
2102 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
2103 sizeof(cam_ctrl_dimension_t), &mDimension);
2104
2105 if(!ret){
2106 LOGE("initRawSnapshot X: failed to set dimension");
2107 return false;
2108 }
2109 int rawSnapshotSize = mDimension.raw_picture_height *
2110 mDimension.raw_picture_width;
2111
2112 LOGV("raw_snapshot_buffer_size = %d, raw_picture_height = %d, "\
2113 "raw_picture_width = %d",
2114 rawSnapshotSize, mDimension.raw_picture_height,
2115 mDimension.raw_picture_width);
2116
2117 if (mRawSnapShotPmemHeap != NULL) {
2118 LOGV("initRawSnapshot: clearing old mRawSnapShotPmemHeap.");
2119 mRawSnapShotPmemHeap.clear();
2120 }
2121
2122 //Pmem based pool for Camera Driver
2123 mRawSnapShotPmemHeap = new PmemPool("/dev/pmem_adsp",
2124 MemoryHeapBase::READ_ONLY,
2125 mCameraControlFd,
2126 MSM_PMEM_RAW_MAINIMG,
2127 rawSnapshotSize,
2128 1,
2129 rawSnapshotSize,
2130 "raw pmem snapshot camera");
2131
2132 if (!mRawSnapShotPmemHeap->initialized()) {
2133 mRawSnapShotPmemHeap.clear();
2134 LOGE("initRawSnapshot X: error initializing mRawSnapshotHeap");
2135 return false;
2136 }
2137 LOGV("initRawSnapshot X");
2138 return true;
2139
2140}
2141
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002142bool QualcommCameraHardware::initRaw(bool initJpegHeap)
2143{
2144 int rawWidth, rawHeight;
Apurva Rajguru8d1773b2009-12-02 14:21:23 -08002145
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002146 mParameters.getPictureSize(&rawWidth, &rawHeight);
2147 LOGV("initRaw E: picture size=%dx%d", rawWidth, rawHeight);
2148
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08002149 int thumbnailBufferSize;
2150 //Thumbnail height should be smaller than Picture height
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002151 if (rawHeight > (int)thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height){
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08002152 mDimension.ui_thumbnail_width =
2153 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].width;
2154 mDimension.ui_thumbnail_height =
2155 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height;
2156 uint32_t pictureAspectRatio = (uint32_t)((rawWidth * Q12) / rawHeight);
2157 uint32_t i;
2158 for(i = 0; i < THUMBNAIL_SIZE_COUNT; i++ )
2159 {
2160 if(thumbnail_sizes[i].aspect_ratio == pictureAspectRatio)
2161 {
2162 mDimension.ui_thumbnail_width = thumbnail_sizes[i].width;
2163 mDimension.ui_thumbnail_height = thumbnail_sizes[i].height;
2164 break;
2165 }
2166 }
2167 }
2168 else{
2169 mDimension.ui_thumbnail_height = THUMBNAIL_SMALL_HEIGHT;
2170 mDimension.ui_thumbnail_width =
2171 (THUMBNAIL_SMALL_HEIGHT * rawWidth)/ rawHeight;
2172 }
2173
2174 LOGV("Thumbnail Size Width %d Height %d",
2175 mDimension.ui_thumbnail_width,
2176 mDimension.ui_thumbnail_height);
2177
2178 thumbnailBufferSize = mDimension.ui_thumbnail_width *
2179 mDimension.ui_thumbnail_height * 3 / 2;
2180
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002181 // mDimension will be filled with thumbnail_width, thumbnail_height,
2182 // orig_picture_dx, and orig_picture_dy after this function call. We need to
2183 // keep it for jpeg_encoder_encode.
2184 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
2185 sizeof(cam_ctrl_dimension_t), &mDimension);
2186 if(!ret) {
2187 LOGE("initRaw X: failed to set dimension");
2188 return false;
2189 }
2190
2191 if (mJpegHeap != NULL) {
2192 LOGV("initRaw: clearing old mJpegHeap.");
2193 mJpegHeap.clear();
2194 }
2195
2196 // Snapshot
2197 mRawSize = rawWidth * rawHeight * 3 / 2;
Apurva Rajguru8d1773b2009-12-02 14:21:23 -08002198
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002199 if( mCurrentTarget == TARGET_MSM7627 )
Apurva Rajguru8d1773b2009-12-02 14:21:23 -08002200 mJpegMaxSize = CEILING16(rawWidth) * CEILING16(rawHeight) * 3 / 2;
2201 else
2202 mJpegMaxSize = rawWidth * rawHeight * 3 / 2;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002203
2204 LOGV("initRaw: initializing mRawHeap.");
2205 mRawHeap =
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002206 new PmemPool("/dev/pmem_adsp",
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002207 MemoryHeapBase::READ_ONLY,
2208 mCameraControlFd,
2209 MSM_PMEM_MAINIMG,
2210 mJpegMaxSize,
2211 kRawBufferCount,
2212 mRawSize,
2213 "snapshot camera");
2214
2215 if (!mRawHeap->initialized()) {
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002216 LOGE("initRaw X failed ");
2217 mRawHeap.clear();
2218 LOGE("initRaw X: error initializing mRawHeap");
2219 return false;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002220 }
2221
2222 LOGV("do_mmap snapshot pbuf = %p, pmem_fd = %d",
2223 (uint8_t *)mRawHeap->mHeap->base(), mRawHeap->mHeap->getHeapID());
2224
2225 // Jpeg
2226
2227 if (initJpegHeap) {
2228 LOGV("initRaw: initializing mJpegHeap.");
2229 mJpegHeap =
2230 new AshmemPool(mJpegMaxSize,
2231 kJpegBufferCount,
2232 0, // we do not know how big the picture will be
2233 "jpeg");
2234
2235 if (!mJpegHeap->initialized()) {
2236 mJpegHeap.clear();
2237 mRawHeap.clear();
2238 LOGE("initRaw X failed: error initializing mJpegHeap.");
2239 return false;
2240 }
2241
2242 // Thumbnails
2243
2244 mThumbnailHeap =
2245 new PmemPool("/dev/pmem_adsp",
2246 MemoryHeapBase::READ_ONLY,
2247 mCameraControlFd,
2248 MSM_PMEM_THUMBNAIL,
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08002249 thumbnailBufferSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002250 1,
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08002251 thumbnailBufferSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002252 "thumbnail");
2253
2254 if (!mThumbnailHeap->initialized()) {
2255 mThumbnailHeap.clear();
2256 mJpegHeap.clear();
2257 mRawHeap.clear();
2258 LOGE("initRaw X failed: error initializing mThumbnailHeap.");
2259 return false;
2260 }
2261 }
2262
2263 LOGV("initRaw X");
2264 return true;
2265}
2266
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002267
2268void QualcommCameraHardware::deinitRawSnapshot()
2269{
2270 LOGV("deinitRawSnapshot E");
2271 mRawSnapShotPmemHeap.clear();
2272 mRawSnapshotAshmemHeap.clear();
2273 LOGV("deinitRawSnapshot X");
2274}
2275
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002276void QualcommCameraHardware::deinitRaw()
2277{
2278 LOGV("deinitRaw E");
2279
2280 mThumbnailHeap.clear();
2281 mJpegHeap.clear();
2282 mRawHeap.clear();
2283 mDisplayHeap.clear();
2284
2285 LOGV("deinitRaw X");
2286}
2287
2288void QualcommCameraHardware::release()
2289{
2290 LOGD("release E");
2291 Mutex::Autolock l(&mLock);
2292
2293#if DLOPEN_LIBMMCAMERA
2294 if (libmmcamera == NULL) {
2295 LOGE("ERROR: multiple release!");
2296 return;
2297 }
2298#else
2299#warning "Cannot detect multiple release when not dlopen()ing libqcamera!"
2300#endif
2301
2302 int cnt, rc;
2303 struct msm_ctrl_cmd ctrlCmd;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002304 if (mCameraRunning) {
2305 if(mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME)) {
2306 mRecordFrameLock.lock();
2307 mReleasedRecordingFrame = true;
2308 mRecordWait.signal();
2309 mRecordFrameLock.unlock();
2310 }
2311 stopPreviewInternal();
2312 }
2313
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002314 if( mCurrentTarget == TARGET_MSM7630 ) {
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002315 mPostViewHeap.clear();
2316 mPostViewHeap = NULL;
2317 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002318 LINK_jpeg_encoder_join();
2319 deinitRaw();
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002320 deinitRawSnapshot();
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002321 {
2322 Mutex::Autolock l(&mCamframeTimeoutLock);
2323 if(!camframe_timeout_flag) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002324
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002325 ctrlCmd.timeout_ms = 5000;
2326 ctrlCmd.length = 0;
2327 ctrlCmd.type = (uint16_t)CAMERA_EXIT;
2328 ctrlCmd.resp_fd = mCameraControlFd; // FIXME: this will be put in by the kernel
2329 if (ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0)
2330 LOGE("ioctl CAMERA_EXIT fd %d error %s",
2331 mCameraControlFd, strerror(errno));
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002332
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002333 }
2334 }
Kiran Kumar H N7ac84e32010-02-01 10:58:47 -08002335 LINK_release_cam_conf_thread();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002336 close(mCameraControlFd);
2337 mCameraControlFd = -1;
Mohan Kandra284966d2010-01-05 13:39:15 -08002338 if(fb_fd >= 0) {
2339 close(fb_fd);
2340 fb_fd = -1;
2341 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002342#if DLOPEN_LIBMMCAMERA
2343 if (libmmcamera) {
2344 ::dlclose(libmmcamera);
2345 LOGV("dlclose(libqcamera)");
2346 libmmcamera = NULL;
2347 }
2348#endif
2349
2350 Mutex::Autolock lock(&singleton_lock);
2351 singleton_releasing = true;
2352
2353 LOGD("release X");
2354}
2355
2356QualcommCameraHardware::~QualcommCameraHardware()
2357{
2358 LOGD("~QualcommCameraHardware E");
2359 Mutex::Autolock lock(&singleton_lock);
2360 singleton.clear();
2361 singleton_releasing = false;
2362 singleton_wait.signal();
2363 LOGD("~QualcommCameraHardware X");
2364}
2365
2366sp<IMemoryHeap> QualcommCameraHardware::getRawHeap() const
2367{
2368 LOGV("getRawHeap");
2369 return mDisplayHeap != NULL ? mDisplayHeap->mHeap : NULL;
2370}
2371
2372sp<IMemoryHeap> QualcommCameraHardware::getPreviewHeap() const
2373{
2374 LOGV("getPreviewHeap");
Mohan Kandrad9efed92010-01-15 19:08:39 -08002375 return mPreviewHeap != NULL ? mPreviewHeap->mHeap : NULL;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002376}
2377
2378status_t QualcommCameraHardware::startPreviewInternal()
2379{
Sravankb4f5f1c2010-01-21 11:06:17 +05302380 LOGV("in startPreviewInternal : E");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002381 if(mCameraRunning) {
2382 LOGV("startPreview X: preview already running.");
2383 return NO_ERROR;
2384 }
2385
2386 if (!mPreviewInitialized) {
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002387 mLastQueuedFrame = NULL;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002388 mPreviewInitialized = initPreview();
2389 if (!mPreviewInitialized) {
2390 LOGE("startPreview X initPreview failed. Not starting preview.");
2391 return UNKNOWN_ERROR;
2392 }
2393 }
2394
Mohan Kandraf1ebf982010-02-02 15:25:43 -08002395 if(( mCurrentTarget != TARGET_MSM7630 ) && (mCurrentTarget != TARGET_QSD8250))
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002396 mCameraRunning = native_start_preview(mCameraControlFd);
Sravankb4f5f1c2010-01-21 11:06:17 +05302397 else
2398 mCameraRunning = native_start_video(mCameraControlFd);
2399
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002400 if(!mCameraRunning) {
2401 deinitPreview();
2402 mPreviewInitialized = false;
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08002403 mOverlay = NULL;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002404 LOGE("startPreview X: native_start_preview failed!");
2405 return UNKNOWN_ERROR;
2406 }
2407
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08002408 //Reset the Gps Information
2409 exif_table_numEntries = 0;
Mohan Kandra284966d2010-01-05 13:39:15 -08002410
2411 if(native_get_maxzoom(mCameraControlFd, (void *)&mMaxZoom) == true){
Brian Steuerb62adbd2010-02-02 14:47:08 -08002412 LOGD("Maximum zoom value is %d", mMaxZoom);
Mohan Kandra284966d2010-01-05 13:39:15 -08002413 mParameters.set("zoom-supported", "true");
2414 } else {
2415 LOGE("Failed to get maximum zoom value...setting max zoom to zero");
2416 mParameters.set("zoom-supported", "false");
2417 mMaxZoom = 0;
2418 }
2419 mParameters.set("max-zoom",mMaxZoom);
2420
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08002421 //Initialize AF state to AF_NOTSTARTED
2422 mAfLock.lock();
2423 mAfState = AF_NOTSTARTED;
2424 mAfLock.unlock();
2425
Sravankb4f5f1c2010-01-21 11:06:17 +05302426 LOGV("startPreviewInternal X");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002427 return NO_ERROR;
2428}
2429
2430status_t QualcommCameraHardware::startPreview()
2431{
2432 LOGV("startPreview E");
2433 Mutex::Autolock l(&mLock);
2434 return startPreviewInternal();
2435}
2436
2437void QualcommCameraHardware::stopPreviewInternal()
2438{
2439 LOGV("stopPreviewInternal E: %d", mCameraRunning);
2440 if (mCameraRunning) {
2441 // Cancel auto focus.
2442 {
2443 if (mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS)) {
2444 cancelAutoFocusInternal();
2445 }
2446 }
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002447
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002448 Mutex::Autolock l(&mCamframeTimeoutLock);
2449 if(!camframe_timeout_flag) {
Mohan Kandraf1ebf982010-02-02 15:25:43 -08002450 if (( mCurrentTarget != TARGET_MSM7630 ) && (mCurrentTarget != TARGET_QSD8250))
Sravankb4f5f1c2010-01-21 11:06:17 +05302451 mCameraRunning = !native_stop_preview(mCameraControlFd);
2452 else
2453 mCameraRunning = !native_stop_video(mCameraControlFd);
2454
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002455 } else {
2456 /* This means that the camframetimeout was issued.
2457 * But we did not issue native_stop_preview(), so we
Kiran Kumar H Nac2f4952009-12-17 01:16:53 -08002458 * need to update mCameraRunning to indicate that
2459 * Camera is no longer running. */
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002460 mCameraRunning = 0;
Kiran Kumar H Nac2f4952009-12-17 01:16:53 -08002461 }
2462 if (!mCameraRunning && mPreviewInitialized) {
2463 deinitPreview();
Mohan Kandraf1ebf982010-02-02 15:25:43 -08002464 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250)) {
Mohan Kandra156d0ac2010-01-25 16:59:17 -08002465 mVideoThreadWaitLock.lock();
2466 LOGV("in stopPreviewInternal: making mVideoThreadExit 1");
2467 mVideoThreadExit = 1;
2468 mVideoThreadWaitLock.unlock();
2469 // 720p : signal the video thread , and check in video thread if stop is called, if so exit video thread.
2470 pthread_mutex_lock(&(g_busy_frame_queue.mut));
2471 pthread_cond_signal(&(g_busy_frame_queue.wait));
2472 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
2473 }
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002474 mPreviewInitialized = false;
2475 }
Kiran Kumar H Nac2f4952009-12-17 01:16:53 -08002476 else LOGE("stopPreviewInternal: failed to stop preview");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002477 }
2478 LOGV("stopPreviewInternal X: %d", mCameraRunning);
2479}
2480
2481void QualcommCameraHardware::stopPreview()
2482{
2483 LOGV("stopPreview: E");
2484 Mutex::Autolock l(&mLock);
2485 {
2486 if (mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME))
2487 return;
2488 }
2489 stopPreviewInternal();
2490 LOGV("stopPreview: X");
2491}
2492
2493void QualcommCameraHardware::runAutoFocus()
2494{
2495 bool status = true;
2496 void *libhandle = NULL;
Srinivasan Kannan71229622009-12-04 12:05:58 -08002497 isp3a_af_mode_t afMode;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002498
2499 mAutoFocusThreadLock.lock();
2500 // Skip autofocus if focus mode is infinity.
2501 if (strcmp(mParameters.get(CameraParameters::KEY_FOCUS_MODE),
2502 CameraParameters::FOCUS_MODE_INFINITY) == 0) {
2503 goto done;
2504 }
2505
2506 mAutoFocusFd = open(MSM_CAMERA_CONTROL, O_RDWR);
2507 if (mAutoFocusFd < 0) {
2508 LOGE("autofocus: cannot open %s: %s",
2509 MSM_CAMERA_CONTROL,
2510 strerror(errno));
2511 mAutoFocusThreadRunning = false;
2512 mAutoFocusThreadLock.unlock();
2513 return;
2514 }
2515
2516#if DLOPEN_LIBMMCAMERA
2517 // We need to maintain a reference to libqcamera.so for the duration of the
2518 // AF thread, because we do not know when it will exit relative to the
2519 // lifetime of this object. We do not want to dlclose() libqcamera while
2520 // LINK_cam_frame is still running.
2521 libhandle = ::dlopen("liboemcamera.so", RTLD_NOW);
2522 LOGV("AF: loading libqcamera at %p", libhandle);
2523 if (!libhandle) {
2524 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
2525 close(mAutoFocusFd);
2526 mAutoFocusFd = -1;
2527 mAutoFocusThreadRunning = false;
2528 mAutoFocusThreadLock.unlock();
2529 return;
2530 }
2531#endif
2532
Srinivasan Kannan71229622009-12-04 12:05:58 -08002533 afMode = (isp3a_af_mode_t)attr_lookup(focus_modes,
2534 sizeof(focus_modes) / sizeof(str_map),
2535 mParameters.get(CameraParameters::KEY_FOCUS_MODE));
2536
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002537 /* This will block until either AF completes or is cancelled. */
Srinivasan Kannan71229622009-12-04 12:05:58 -08002538 LOGV("af start (fd %d mode %d)", mAutoFocusFd, afMode);
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08002539 status_t err;
2540 err = mAfLock.tryLock();
2541 if(err == NO_ERROR) {
2542 //Got Lock, so start AF if required.
2543 if(mAfState != AF_CANCELLED) {
2544 mAfState = AF_STARTED;
2545 LOGV("Start AF");
2546 status = native_set_afmode(mAutoFocusFd, afMode);
2547 } else {
2548 status = FALSE;
2549 }
2550 mAfLock.unlock();
2551 }
2552 else{
2553 //AF Cancel would have acquired the lock,
2554 //so, no need to perform any AF
2555 LOGV("Failed to obtain Lock...is busy");
2556 status = FALSE;
2557 }
2558
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002559 LOGV("af done: %d", (int)status);
2560 close(mAutoFocusFd);
2561 mAutoFocusFd = -1;
2562
2563done:
2564 mAutoFocusThreadRunning = false;
2565 mAutoFocusThreadLock.unlock();
2566
2567 mCallbackLock.lock();
2568 bool autoFocusEnabled = mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS);
2569 notify_callback cb = mNotifyCallback;
2570 void *data = mCallbackCookie;
2571 mCallbackLock.unlock();
2572 if (autoFocusEnabled)
2573 cb(CAMERA_MSG_FOCUS, status, 0, data);
2574
2575#if DLOPEN_LIBMMCAMERA
2576 if (libhandle) {
2577 ::dlclose(libhandle);
2578 LOGV("AF: dlclose(libqcamera)");
2579 }
2580#endif
2581}
2582
2583status_t QualcommCameraHardware::cancelAutoFocusInternal()
2584{
2585 LOGV("cancelAutoFocusInternal E");
2586
Srinivasan Kannan71229622009-12-04 12:05:58 -08002587 if(!sensorType->hasAutoFocusSupport){
2588 LOGV("cancelAutoFocusInternal X");
2589 return NO_ERROR;
2590 }
2591
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002592#if 0
2593 if (mAutoFocusFd < 0) {
2594 LOGV("cancelAutoFocusInternal X: not in progress");
2595 return NO_ERROR;
2596 }
2597#endif
2598
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08002599 status_t rc = NO_ERROR;
2600 status_t err;
2601 err = mAfLock.tryLock();
2602 if(err == NO_ERROR) {
2603 //Got Lock, means either AF hasn't started or
2604 // AF is done. So no need to cancel it, just change the state
2605 LOGV("Change AF State to Cancelled");
2606 mAfState = AF_CANCELLED;
2607 mAfLock.unlock();
2608 }
2609 else {
2610 //AF is in Progess, So cancel it
2611 LOGV("Lock busy...cancel AF");
2612 rc = native_cancel_afmode(mCameraControlFd, mAutoFocusFd) ?
2613 NO_ERROR :
2614 UNKNOWN_ERROR;
2615 }
2616
2617
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002618
2619 LOGV("cancelAutoFocusInternal X: %d", rc);
2620 return rc;
2621}
2622
2623void *auto_focus_thread(void *user)
2624{
2625 LOGV("auto_focus_thread E");
2626 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
2627 if (obj != 0) {
2628 obj->runAutoFocus();
2629 }
2630 else LOGW("not starting autofocus: the object went away!");
2631 LOGV("auto_focus_thread X");
2632 return NULL;
2633}
2634
2635status_t QualcommCameraHardware::autoFocus()
2636{
2637 LOGV("autoFocus E");
2638 Mutex::Autolock l(&mLock);
2639
Srinivasan Kannan71229622009-12-04 12:05:58 -08002640 if(!sensorType->hasAutoFocusSupport){
Srinivasan Kannandf085222009-12-09 18:31:00 -08002641 bool status = false;
2642 mCallbackLock.lock();
2643 bool autoFocusEnabled = mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS);
2644 notify_callback cb = mNotifyCallback;
2645 void *data = mCallbackCookie;
2646 mCallbackLock.unlock();
2647 if (autoFocusEnabled)
2648 cb(CAMERA_MSG_FOCUS, status, 0, data);
Srinivasan Kannan71229622009-12-04 12:05:58 -08002649 LOGV("autoFocus X");
2650 return NO_ERROR;
2651 }
2652
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002653 if (mCameraControlFd < 0) {
2654 LOGE("not starting autofocus: main control fd %d", mCameraControlFd);
2655 return UNKNOWN_ERROR;
2656 }
2657
2658 {
2659 mAutoFocusThreadLock.lock();
2660 if (!mAutoFocusThreadRunning) {
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08002661 if (native_prepare_snapshot(mCameraControlFd) == FALSE) {
2662 LOGE("native_prepare_snapshot failed!\n");
2663 mAutoFocusThreadLock.unlock();
2664 return UNKNOWN_ERROR;
2665 }
2666
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002667 // Create a detached thread here so that we don't have to wait
2668 // for it when we cancel AF.
2669 pthread_t thr;
2670 pthread_attr_t attr;
2671 pthread_attr_init(&attr);
2672 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2673 mAutoFocusThreadRunning =
2674 !pthread_create(&thr, &attr,
2675 auto_focus_thread, NULL);
2676 if (!mAutoFocusThreadRunning) {
2677 LOGE("failed to start autofocus thread");
2678 mAutoFocusThreadLock.unlock();
2679 return UNKNOWN_ERROR;
2680 }
2681 }
2682 mAutoFocusThreadLock.unlock();
2683 }
2684
2685 LOGV("autoFocus X");
2686 return NO_ERROR;
2687}
2688
2689status_t QualcommCameraHardware::cancelAutoFocus()
2690{
2691 LOGV("cancelAutoFocus E");
2692 Mutex::Autolock l(&mLock);
2693
2694 int rc = NO_ERROR;
2695 if (mCameraRunning && mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS)) {
2696 rc = cancelAutoFocusInternal();
2697 }
2698
2699 LOGV("cancelAutoFocus X");
2700 return rc;
2701}
2702
2703void QualcommCameraHardware::runSnapshotThread(void *data)
2704{
2705 LOGV("runSnapshotThread E");
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002706 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
2707 if (native_start_snapshot(mCameraControlFd))
2708 receiveRawPicture();
2709 else
2710 LOGE("main: native_start_snapshot failed!");
2711 } else if(mSnapshotFormat == PICTURE_FORMAT_RAW){
2712 if(native_start_raw_snapshot(mCameraControlFd)){
2713 receiveRawSnapshot();
2714 } else {
2715 LOGE("main: native_start_raw_snapshot failed!");
2716 }
2717 }
2718
2719 mSnapshotFormat = 0;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002720
2721 mSnapshotThreadWaitLock.lock();
2722 mSnapshotThreadRunning = false;
2723 mSnapshotThreadWait.signal();
2724 mSnapshotThreadWaitLock.unlock();
2725
2726 LOGV("runSnapshotThread X");
2727}
2728
2729void *snapshot_thread(void *user)
2730{
2731 LOGD("snapshot_thread E");
2732 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
2733 if (obj != 0) {
2734 obj->runSnapshotThread(user);
2735 }
2736 else LOGW("not starting snapshot thread: the object went away!");
2737 LOGD("snapshot_thread X");
2738 return NULL;
2739}
2740
2741status_t QualcommCameraHardware::takePicture()
2742{
2743 LOGV("takePicture(%d)", mMsgEnabled);
2744 Mutex::Autolock l(&mLock);
2745
2746 // Wait for old snapshot thread to complete.
2747 mSnapshotThreadWaitLock.lock();
2748 while (mSnapshotThreadRunning) {
2749 LOGV("takePicture: waiting for old snapshot thread to complete.");
2750 mSnapshotThreadWait.wait(mSnapshotThreadWaitLock);
2751 LOGV("takePicture: old snapshot thread completed.");
2752 }
2753
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002754 if( mCurrentTarget == TARGET_MSM7630 ) {
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002755 /* Store the last frame queued for preview. This
2756 * shall be used as postview */
2757 storePreviewFrameForPostview();
2758 }
2759
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002760 //mSnapshotFormat is protected by mSnapshotThreadWaitLock
2761 if(mParameters.getPictureFormat() != 0 &&
2762 !strcmp(mParameters.getPictureFormat(),
2763 CameraParameters::PIXEL_FORMAT_RAW))
2764 mSnapshotFormat = PICTURE_FORMAT_RAW;
2765 else
2766 mSnapshotFormat = PICTURE_FORMAT_JPEG;
2767
2768 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
2769 if(!native_prepare_snapshot(mCameraControlFd)) {
2770 mSnapshotThreadWaitLock.unlock();
2771 return UNKNOWN_ERROR;
2772 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002773 }
2774
2775 stopPreviewInternal();
2776
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002777 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
2778 if (!initRaw(mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE))) {
2779 LOGE("initRaw failed. Not taking picture.");
2780 mSnapshotThreadWaitLock.unlock();
2781 return UNKNOWN_ERROR;
2782 }
2783 } else if(mSnapshotFormat == PICTURE_FORMAT_RAW ){
2784 if(!initRawSnapshot()){
2785 LOGE("initRawSnapshot failed. Not taking picture.");
2786 mSnapshotThreadWaitLock.unlock();
2787 return UNKNOWN_ERROR;
2788 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002789 }
2790
2791 mShutterLock.lock();
2792 mShutterPending = true;
2793 mShutterLock.unlock();
2794
2795 pthread_attr_t attr;
2796 pthread_attr_init(&attr);
2797 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2798 mSnapshotThreadRunning = !pthread_create(&mSnapshotThread,
2799 &attr,
2800 snapshot_thread,
2801 NULL);
2802 mSnapshotThreadWaitLock.unlock();
2803
2804 LOGV("takePicture: X");
2805 return mSnapshotThreadRunning ? NO_ERROR : UNKNOWN_ERROR;
2806}
2807
2808status_t QualcommCameraHardware::cancelPicture()
2809{
2810 status_t rc;
2811 LOGV("cancelPicture: E");
2812 rc = native_stop_snapshot(mCameraControlFd) ? NO_ERROR : UNKNOWN_ERROR;
2813 LOGV("cancelPicture: X: %d", rc);
2814 return rc;
2815}
2816
2817status_t QualcommCameraHardware::setParameters(const CameraParameters& params)
2818{
2819 LOGV("setParameters: E params = %p", &params);
2820
2821 Mutex::Autolock l(&mLock);
2822 status_t rc, final_rc = NO_ERROR;
2823
2824 if ((rc = setPreviewSize(params))) final_rc = rc;
2825 if ((rc = setPictureSize(params))) final_rc = rc;
2826 if ((rc = setJpegQuality(params))) final_rc = rc;
2827 if ((rc = setAntibanding(params))) final_rc = rc;
2828 if ((rc = setEffect(params))) final_rc = rc;
Apurva Rajguru55562b02009-12-03 12:25:35 -08002829 if ((rc = setAutoExposure(params))) final_rc = rc;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002830 if ((rc = setWhiteBalance(params))) final_rc = rc;
2831 if ((rc = setFlash(params))) final_rc = rc;
2832 if ((rc = setGpsLocation(params))) final_rc = rc;
2833 if ((rc = setRotation(params))) final_rc = rc;
2834 if ((rc = setZoom(params))) final_rc = rc;
2835 if ((rc = setFocusMode(params))) final_rc = rc;
2836 if ((rc = setOrientation(params))) final_rc = rc;
Nishant Panditc8c1ee72009-12-03 16:24:02 +05302837 if ((rc = setBrightness(params))) final_rc = rc;
2838 if ((rc = setLensshadeValue(params))) final_rc = rc;
2839 if ((rc = setISOValue(params))) final_rc = rc;
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002840 if ((rc = setPictureFormat(params))) final_rc = rc;
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08002841 if ((rc = setSharpness(params))) final_rc = rc;
2842 if ((rc = setContrast(params))) final_rc = rc;
2843 if ((rc = setSaturation(params))) final_rc = rc;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002844
2845 LOGV("setParameters: X");
2846 return final_rc;
2847}
2848
2849CameraParameters QualcommCameraHardware::getParameters() const
2850{
2851 LOGV("getParameters: EX");
2852 return mParameters;
2853}
2854
2855status_t QualcommCameraHardware::sendCommand(int32_t command, int32_t arg1,
2856 int32_t arg2)
2857{
2858 LOGV("sendCommand: EX");
2859 return BAD_VALUE;
2860}
2861
2862extern "C" sp<CameraHardwareInterface> openCameraHardware()
2863{
2864 LOGV("openCameraHardware: call createInstance");
2865 return QualcommCameraHardware::createInstance();
2866}
2867
2868wp<QualcommCameraHardware> QualcommCameraHardware::singleton;
2869
2870// If the hardware already exists, return a strong pointer to the current
2871// object. If not, create a new hardware object, put it in the singleton,
2872// and return it.
2873sp<CameraHardwareInterface> QualcommCameraHardware::createInstance()
2874{
2875 LOGD("createInstance: E");
2876
2877 Mutex::Autolock lock(&singleton_lock);
2878
2879 // Wait until the previous release is done.
2880 while (singleton_releasing) {
2881 LOGD("Wait for previous release.");
2882 singleton_wait.wait(singleton_lock);
2883 }
2884
2885 if (singleton != 0) {
2886 sp<CameraHardwareInterface> hardware = singleton.promote();
2887 if (hardware != 0) {
2888 LOGD("createInstance: X return existing hardware=%p", &(*hardware));
2889 return hardware;
2890 }
2891 }
2892
2893 {
2894 struct stat st;
2895 int rc = stat("/dev/oncrpc", &st);
2896 if (rc < 0) {
2897 LOGD("createInstance: X failed to create hardware: %s", strerror(errno));
2898 return NULL;
2899 }
2900 }
2901
2902 QualcommCameraHardware *cam = new QualcommCameraHardware();
2903 sp<QualcommCameraHardware> hardware(cam);
2904 singleton = hardware;
2905
2906 if (!cam->startCamera()) {
2907 LOGE("%s: startCamera failed!", __FUNCTION__);
2908 return NULL;
2909 }
2910
2911 cam->initDefaultParameters();
2912 LOGD("createInstance: X created hardware=%p", &(*hardware));
2913 return hardware;
2914}
2915
2916// For internal use only, hence the strong pointer to the derived type.
2917sp<QualcommCameraHardware> QualcommCameraHardware::getInstance()
2918{
2919 sp<CameraHardwareInterface> hardware = singleton.promote();
2920 if (hardware != 0) {
2921 // LOGV("getInstance: X old instance of hardware");
2922 return sp<QualcommCameraHardware>(static_cast<QualcommCameraHardware*>(hardware.get()));
2923 } else {
2924 LOGV("getInstance: X new instance of hardware");
2925 return sp<QualcommCameraHardware>();
2926 }
2927}
Sravankb4f5f1c2010-01-21 11:06:17 +05302928void QualcommCameraHardware::receiveRecordingFrame(struct msm_frame *frame)
2929{
2930 LOGV("receiveRecordingFrame E");
2931 // post busy frame
2932 if (frame)
2933 {
2934 cam_frame_post_video (frame);
2935 }
2936 else LOGE("in receiveRecordingFrame frame is NULL");
2937 LOGV("receiveRecordingFrame X");
2938}
2939
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002940
Mohan Kandrad9efed92010-01-15 19:08:39 -08002941bool QualcommCameraHardware::native_zoom_image(int fd, int srcOffset, int dstOffSet, common_crop_t *crop)
Mohan Kandra284966d2010-01-05 13:39:15 -08002942{
2943 int result = 0;
2944 struct mdp_blit_req *e;
2945 struct timeval td1, td2;
2946
Mohan Kandra284966d2010-01-05 13:39:15 -08002947 /* Initialize yuv structure */
2948 zoomImage.list.count = 1;
2949
2950 e = &zoomImage.list.req[0];
2951
2952 e->src.width = previewWidth;
2953 e->src.height = previewHeight;
2954 e->src.format = MDP_Y_CBCR_H2V2;
Mohan Kandrad9efed92010-01-15 19:08:39 -08002955 e->src.offset = srcOffset;
2956 e->src.memory_id = fd;
Mohan Kandra284966d2010-01-05 13:39:15 -08002957
2958 e->dst.width = previewWidth;
2959 e->dst.height = previewHeight;
2960 e->dst.format = MDP_Y_CBCR_H2V2;
Mohan Kandrad9efed92010-01-15 19:08:39 -08002961 e->dst.offset = dstOffSet;
2962 e->dst.memory_id = fd;
Mohan Kandra284966d2010-01-05 13:39:15 -08002963
2964 e->transp_mask = 0xffffffff;
2965 e->flags = 0;
2966 e->alpha = 0xff;
2967 if (crop->in2_w != 0 || crop->in2_h != 0) {
2968 e->src_rect.x = (crop->out2_w - crop->in2_w + 1) / 2 - 1;
2969 e->src_rect.y = (crop->out2_h - crop->in2_h + 1) / 2 - 1;
2970 e->src_rect.w = crop->in2_w;
2971 e->src_rect.h = crop->in2_h;
2972 } else {
2973 e->src_rect.x = 0;
2974 e->src_rect.y = 0;
2975 e->src_rect.w = previewWidth;
2976 e->src_rect.h = previewHeight;
2977 }
Mohan Kandrad9efed92010-01-15 19:08:39 -08002978 //LOGV(" native_zoom : SRC_RECT : x,y = %d,%d \t w,h = %d, %d",
2979 // e->src_rect.x, e->src_rect.y, e->src_rect.w, e->src_rect.h);
Mohan Kandra284966d2010-01-05 13:39:15 -08002980
2981 e->dst_rect.x = 0;
2982 e->dst_rect.y = 0;
2983 e->dst_rect.w = previewWidth;
2984 e->dst_rect.h = previewHeight;
2985
2986 result = ioctl(fb_fd, MSMFB_BLIT, &zoomImage.list);
2987 if (result < 0) {
2988 LOGE("MSM_FBIOBLT failed! line=%d\n", __LINE__);
2989 return FALSE;
2990 }
2991 return TRUE;
2992}
2993
Mohan Kandra740cfce2010-01-07 12:58:24 -08002994void QualcommCameraHardware::debugShowFPS() const
2995{
2996 static int mFrameCount;
2997 static int mLastFrameCount = 0;
2998 static nsecs_t mLastFpsTime = 0;
2999 static float mFps = 0;
3000 mFrameCount++;
3001 nsecs_t now = systemTime();
3002 nsecs_t diff = now - mLastFpsTime;
3003 if (diff > ms2ns(250)) {
3004 mFps = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
3005 LOGI("Frames Per Second: %.4f", mFps);
3006 mLastFpsTime = now;
3007 mLastFrameCount = mFrameCount;
3008 }
3009}
3010
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003011void QualcommCameraHardware::receivePreviewFrame(struct msm_frame *frame)
3012{
3013// LOGV("receivePreviewFrame E");
3014
3015 if (!mCameraRunning) {
3016 LOGE("ignoring preview callback--camera has been stopped");
3017 return;
3018 }
3019
Mohan Kandra740cfce2010-01-07 12:58:24 -08003020 if (UNLIKELY(mDebugFps)) {
3021 debugShowFPS();
3022 }
3023
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003024 mCallbackLock.lock();
3025 int msgEnabled = mMsgEnabled;
3026 data_callback pcb = mDataCallback;
3027 void *pdata = mCallbackCookie;
3028 data_callback_timestamp rcb = mDataCallbackTimestamp;
3029 void *rdata = mCallbackCookie;
3030 mCallbackLock.unlock();
3031
3032 // Find the offset within the heap of the current buffer.
Mohan Kandra284966d2010-01-05 13:39:15 -08003033 ssize_t offset_addr =
Mohan Kandrad9efed92010-01-15 19:08:39 -08003034 (ssize_t)frame->buffer - (ssize_t)mPreviewHeap->mHeap->base();
3035 ssize_t offset = offset_addr / mPreviewHeap->mAlignedBufferSize;
Mohan Kandra284966d2010-01-05 13:39:15 -08003036
3037 common_crop_t *crop = (common_crop_t *) (frame->cropinfo);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003038
3039 mInPreviewCallback = true;
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003040 if(mUseOverlay) {
3041 if(mOverlay != NULL) {
3042 mOverlayLock.lock();
Mohan Kandrad9efed92010-01-15 19:08:39 -08003043 mOverlay->setFd(mPreviewHeap->mHeap->getHeapID());
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003044 if (crop->in2_w != 0 || crop->in2_h != 0) {
3045 zoomCropInfo.x = (crop->out2_w - crop->in2_w + 1) / 2 - 1;
3046 zoomCropInfo.y = (crop->out2_h - crop->in2_h + 1) / 2 - 1;
3047 zoomCropInfo.w = crop->in2_w;
3048 zoomCropInfo.h = crop->in2_h;
3049 mOverlay->setCrop(zoomCropInfo.x, zoomCropInfo.y,
3050 zoomCropInfo.w, zoomCropInfo.h);
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08003051 } else {
3052 // Reset zoomCropInfo variables. This will ensure that
3053 // stale values wont be used for postview
3054 zoomCropInfo.w = crop->in2_w;
3055 zoomCropInfo.h = crop->in2_h;
3056 }
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003057 mOverlay->queueBuffer((void *)offset_addr);
3058 mLastQueuedFrame = (void *)frame->buffer;
3059 mOverlayLock.unlock();
3060 }
Mohan Kandra284966d2010-01-05 13:39:15 -08003061 } else {
Mohan Kandrad9efed92010-01-15 19:08:39 -08003062 if (crop->in2_w != 0 || crop->in2_h != 0) {
3063 dstOffset = (dstOffset + 1) % NUM_MORE_BUFS;
3064 offset = kPreviewBufferCount + dstOffset;
3065 ssize_t dstOffset_addr = offset * mPreviewHeap->mAlignedBufferSize;
3066 if( !native_zoom_image(mPreviewHeap->mHeap->getHeapID(),
3067 offset_addr, dstOffset_addr, crop)) {
3068 LOGE(" Error while doing MDP zoom ");
3069 }
3070 }
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08003071 }
Mohan Kandrad9efed92010-01-15 19:08:39 -08003072 if (pcb != NULL && (msgEnabled & CAMERA_MSG_PREVIEW_FRAME))
3073 pcb(CAMERA_MSG_PREVIEW_FRAME, mPreviewHeap->mBuffers[offset],
3074 pdata);
3075
Sravankb4f5f1c2010-01-21 11:06:17 +05303076 // If output2 enabled, Start Recording if recording is enabled by Services
Mohan Kandraf1ebf982010-02-02 15:25:43 -08003077 if( ((mCurrentTarget == TARGET_MSM7630) || (mCurrentTarget == TARGET_QSD8250)) && recordingEnabled() ) {
Sravankb4f5f1c2010-01-21 11:06:17 +05303078 if(!recordingState){
3079 recordingState = 1; // recording started
3080 LOGV(" in receivePreviewframe : recording enabled calling startRecording ");
3081 startRecording();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003082 }
Sravankb4f5f1c2010-01-21 11:06:17 +05303083 }
3084
3085 // If output is NOT enabled (targets otherthan 7x30 currently..)
Mohan Kandraf1ebf982010-02-02 15:25:43 -08003086 if( (mCurrentTarget != TARGET_MSM7630 ) && (mCurrentTarget != TARGET_QSD8250)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05303087 if(rcb != NULL && (msgEnabled & CAMERA_MSG_VIDEO_FRAME)) {
3088 rcb(systemTime(), CAMERA_MSG_VIDEO_FRAME, mPreviewHeap->mBuffers[offset], rdata);
3089 Mutex::Autolock rLock(&mRecordFrameLock);
3090 if (mReleasedRecordingFrame != true) {
3091 LOGV("block waiting for frame release");
3092 mRecordWait.wait(mRecordFrameLock);
3093 LOGV("frame released, continuing");
3094 }
3095 mReleasedRecordingFrame = false;
3096 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003097 }
3098 mInPreviewCallback = false;
3099
3100// LOGV("receivePreviewFrame X");
3101}
3102
Sravankb4f5f1c2010-01-21 11:06:17 +05303103
3104bool QualcommCameraHardware::initRecord()
3105{
3106 LOGV("initREcord E");
3107
3108 mRecordFrameSize = (mDimension.video_width * mDimension.video_height *3)/2;
3109 mRecordHeap = new PmemPool("/dev/pmem_adsp",
3110 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
3111 mCameraControlFd,
3112 MSM_PMEM_VIDEO,
3113 mRecordFrameSize,
3114 kRecordBufferCount,
3115 mRecordFrameSize,
3116 "record");
3117 if (!mRecordHeap->initialized()) {
3118 mRecordHeap.clear();
3119 LOGE("initRecord X: could not initialize record heap.");
3120 return false;
3121 }
3122 for (int cnt = 0; cnt < kRecordBufferCount; cnt++) {
3123 recordframes[cnt].fd = mRecordHeap->mHeap->getHeapID();
3124 recordframes[cnt].buffer =
3125 (uint32_t)mRecordHeap->mHeap->base() + mRecordHeap->mAlignedBufferSize * cnt;
3126 recordframes[cnt].y_off = 0;
3127 recordframes[cnt].cbcr_off = mDimension.video_width * mDimension.video_height;
3128 recordframes[cnt].path = OUTPUT_TYPE_V;
3129
3130 LOGV ("initRecord : record heap , video buffers buffer=%lu fd=%d y_off=%d cbcr_off=%d \n",
3131 (unsigned long)recordframes[cnt].buffer, recordframes[cnt].fd, recordframes[cnt].y_off,
3132 recordframes[cnt].cbcr_off);
3133 }
3134
3135 // initial setup : buffers 1,2,3 with kernel , 4 with camframe , 5,6,7,8 in free Q
3136 // flush the busy Q
3137 cam_frame_flush_video();
3138
Mohan Kandra156d0ac2010-01-25 16:59:17 -08003139 mVideoThreadWaitLock.lock();
3140 while (mVideoThreadRunning) {
3141 LOGV("initRecord: waiting for old video thread to complete.");
3142 mVideoThreadWait.wait(mVideoThreadWaitLock);
3143 LOGV("initRecord : old video thread completed.");
3144 }
3145 mVideoThreadWaitLock.unlock();
3146
Sravankdf7a9202010-02-08 15:02:51 +05303147 // flush free queue and add 5,6,7,8 buffers.
3148 LINK_cam_frame_flush_free_video();
3149 for(int i=ACTIVE_VIDEO_BUFFERS+1;i <kRecordBufferCount; i++)
3150 LINK_camframe_free_video(&recordframes[i]);
Sravankb4f5f1c2010-01-21 11:06:17 +05303151 LOGV("initREcord X");
3152
3153 return true;
3154}
3155
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003156status_t QualcommCameraHardware::startRecording()
3157{
3158 LOGV("startRecording E");
Sravankb4f5f1c2010-01-21 11:06:17 +05303159 int ret;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003160 Mutex::Autolock l(&mLock);
3161 mReleasedRecordingFrame = false;
Sravankb4f5f1c2010-01-21 11:06:17 +05303162 if( (ret=startPreviewInternal())== NO_ERROR){
Mohan Kandraf1ebf982010-02-02 15:25:43 -08003163 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05303164 LOGV(" in startREcording : calling native_start_recording");
3165 native_start_recording(mCameraControlFd);
3166 recordingState = 1;
Sravankdf7a9202010-02-08 15:02:51 +05303167 // Start video thread and wait for busy frames to be encoded, this thread
3168 // should be closed in stopRecording
3169 mVideoThreadWaitLock.lock();
3170 mVideoThreadExit = 0;
3171 pthread_attr_t attr;
3172 pthread_attr_init(&attr);
3173 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
3174 mVideoThreadRunning = pthread_create(&mVideoThread,
3175 &attr,
3176 video_thread,
3177 NULL);
3178 mVideoThreadWaitLock.unlock();
3179 // Remove the left out frames in busy Q and them in free Q.
3180 LOGV("frames in busy Q = %d", g_busy_frame_queue.num_of_frames);
3181 while((g_busy_frame_queue.num_of_frames) >0){
3182 msm_frame* vframe = cam_frame_get_video ();
3183 LINK_camframe_free_video(vframe);
3184 }
3185 LOGV("frames in busy Q = %d after deQueing", g_busy_frame_queue.num_of_frames);
Sravankb4f5f1c2010-01-21 11:06:17 +05303186 }
3187 }
3188 return ret;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003189}
3190
3191void QualcommCameraHardware::stopRecording()
3192{
3193 LOGV("stopRecording: E");
3194 Mutex::Autolock l(&mLock);
3195 {
3196 mRecordFrameLock.lock();
3197 mReleasedRecordingFrame = true;
3198 mRecordWait.signal();
3199 mRecordFrameLock.unlock();
3200
Sravankdf7a9202010-02-08 15:02:51 +05303201 if(mDataCallback && !(mCurrentTarget == TARGET_QSD8250) &&
3202 (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003203 LOGV("stopRecording: X, preview still in progress");
3204 return;
3205 }
3206 }
Sravankb4f5f1c2010-01-21 11:06:17 +05303207 // If output2 enabled, exit video thread, invoke stop recording ioctl
Mohan Kandraf1ebf982010-02-02 15:25:43 -08003208 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05303209 mVideoThreadWaitLock.lock();
3210 mVideoThreadExit = 1;
3211 mVideoThreadWaitLock.unlock();
3212 native_stop_recording(mCameraControlFd);
3213 }
3214 else // for other targets where output2 is not enabled
3215 stopPreviewInternal();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003216
Sravankb4f5f1c2010-01-21 11:06:17 +05303217 recordingState = 0; // recording not started
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003218 LOGV("stopRecording: X");
3219}
3220
3221void QualcommCameraHardware::releaseRecordingFrame(
3222 const sp<IMemory>& mem __attribute__((unused)))
3223{
3224 LOGV("releaseRecordingFrame E");
3225 Mutex::Autolock rLock(&mRecordFrameLock);
3226 mReleasedRecordingFrame = true;
3227 mRecordWait.signal();
Sravankb4f5f1c2010-01-21 11:06:17 +05303228
3229 // Ff 7x30 : add the frame to the free camframe queue
Mohan Kandraf1ebf982010-02-02 15:25:43 -08003230 if( (mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05303231 ssize_t offset;
3232 size_t size;
3233 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
3234 msm_frame* releaseframe = NULL;
3235 LOGV(" in release recording frame : heap base %d offset %d buffer %d ", heap->base(), offset, heap->base() + offset );
3236 int cnt;
3237 for (cnt = 0; cnt < kRecordBufferCount; cnt++) {
3238 if((unsigned int)recordframes[cnt].buffer == (unsigned int)(heap->base()+ offset)){
3239 LOGV("in release recording frame found match , releasing buffer %d", (unsigned int)recordframes[cnt].buffer);
3240 releaseframe = &recordframes[cnt];
3241 break;
3242 }
3243 }
3244 if(cnt < kRecordBufferCount) {
3245 // do this only if frame thread is running
3246 mFrameThreadWaitLock.lock();
3247 if(mFrameThreadRunning )
3248 LINK_camframe_free_video(releaseframe);
3249
3250 mFrameThreadWaitLock.unlock();
3251 } else {
3252 LOGE("in release recordingframe XXXXX error , buffer not found");
3253 for (int i=0; i< kRecordBufferCount; i++) {
3254 LOGE(" recordframes[%d].buffer = %d", i, (unsigned int)recordframes[i].buffer);
3255 }
3256 }
3257 }
3258
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003259 LOGV("releaseRecordingFrame X");
3260}
3261
3262bool QualcommCameraHardware::recordingEnabled()
3263{
3264 return mCameraRunning && mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME);
3265}
3266
3267void QualcommCameraHardware::notifyShutter(common_crop_t *crop)
3268{
3269 mShutterLock.lock();
3270 image_rect_type size;
3271
3272 if (mShutterPending && mNotifyCallback && (mMsgEnabled & CAMERA_MSG_SHUTTER)) {
3273 LOGV("out2_w=%d, out2_h=%d, in2_w=%d, in2_h=%d",
3274 crop->out2_w, crop->out2_h, crop->in2_w, crop->in2_h);
3275 LOGV("out1_w=%d, out1_h=%d, in1_w=%d, in1_h=%d",
3276 crop->out1_w, crop->out1_h, crop->in1_w, crop->in1_h);
3277
3278 // To workaround a bug in MDP which happens if either
3279 // dimension > 2048, we display the thumbnail instead.
3280 mDisplayHeap = mRawHeap;
3281 if (crop->in1_w == 0 || crop->in1_h == 0) {
3282 // Full size
3283 size.width = mDimension.picture_width;
3284 size.height = mDimension.picture_height;
3285 if (size.width > 2048 || size.height > 2048) {
3286 size.width = mDimension.ui_thumbnail_width;
3287 size.height = mDimension.ui_thumbnail_height;
3288 mDisplayHeap = mThumbnailHeap;
3289 }
3290 } else {
3291 // Cropped
3292 size.width = crop->in2_w & ~1;
3293 size.height = crop->in2_h & ~1;
3294 if (size.width > 2048 || size.height > 2048) {
3295 size.width = crop->in1_w & ~1;
3296 size.height = crop->in1_h & ~1;
3297 mDisplayHeap = mThumbnailHeap;
3298 }
3299 }
3300
3301 mNotifyCallback(CAMERA_MSG_SHUTTER, (int32_t)&size, 0,
3302 mCallbackCookie);
3303 mShutterPending = false;
3304 }
3305 mShutterLock.unlock();
3306}
3307
3308static void receive_shutter_callback(common_crop_t *crop)
3309{
3310 LOGV("receive_shutter_callback: E");
3311 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
3312 if (obj != 0) {
3313 obj->notifyShutter(crop);
3314 }
3315 LOGV("receive_shutter_callback: X");
3316}
3317
3318// Crop the picture in place.
3319static void crop_yuv420(uint32_t width, uint32_t height,
3320 uint32_t cropped_width, uint32_t cropped_height,
3321 uint8_t *image)
3322{
3323 uint32_t i, x, y;
3324 uint8_t* chroma_src, *chroma_dst;
3325
3326 // Calculate the start position of the cropped area.
3327 x = (width - cropped_width) / 2;
3328 y = (height - cropped_height) / 2;
3329 x &= ~1;
3330 y &= ~1;
3331
3332 // Copy luma component.
3333 for(i = 0; i < cropped_height; i++)
3334 memcpy(image + i * cropped_width,
3335 image + width * (y + i) + x,
3336 cropped_width);
3337
3338 chroma_src = image + width * height;
3339 chroma_dst = image + cropped_width * cropped_height;
3340
3341 // Copy chroma components.
3342 cropped_height /= 2;
3343 y /= 2;
3344 for(i = 0; i < cropped_height; i++)
3345 memcpy(chroma_dst + i * cropped_width,
3346 chroma_src + width * (y + i) + x,
3347 cropped_width);
3348}
3349
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08003350
3351void QualcommCameraHardware::receiveRawSnapshot(){
3352 LOGV("receiveRawSnapshot E");
3353
3354 Mutex::Autolock cbLock(&mCallbackLock);
3355
3356 notifyShutter(&mCrop);
3357
3358 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
3359
3360 if(native_get_picture(mCameraControlFd, &mCrop) == false) {
3361 LOGE("receiveRawSnapshot X: native_get_picture failed!");
3362 return;
3363 }
3364
3365 //Create a Ashmem heap to copy data from PMem heap for application layer
3366 if(mRawSnapshotAshmemHeap != NULL){
3367 LOGV("receiveRawSnapshot: clearing old mRawSnapShotAshmemHeap.");
3368 mRawSnapshotAshmemHeap.clear();
3369 }
3370 mRawSnapshotAshmemHeap = new AshmemPool(
3371 mRawSnapShotPmemHeap->mBufferSize,
3372 mRawSnapShotPmemHeap->mNumBuffers,
3373 mRawSnapShotPmemHeap->mFrameSize,
3374 "raw ashmem snapshot camera"
3375 );
3376
3377 if(!mRawSnapshotAshmemHeap->initialized()){
3378 LOGE("receiveRawSnapshot X: error initializing mRawSnapshotHeap");
3379 deinitRawSnapshot();
3380 return;
3381 }
3382
3383 memcpy(mRawSnapshotAshmemHeap->mHeap->base(),
3384 mRawSnapShotPmemHeap->mHeap->base(),
3385 mRawSnapShotPmemHeap->mHeap->getSize());
3386
3387 mDataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mRawSnapshotAshmemHeap->mBuffers[0],
3388 mCallbackCookie);
3389
3390 }
3391
3392 //cleanup
3393 deinitRawSnapshot();
3394
3395 LOGV("receiveRawSnapshot X");
3396}
3397
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003398void QualcommCameraHardware::receiveRawPicture()
3399{
3400 LOGV("receiveRawPicture: E");
3401
3402 Mutex::Autolock cbLock(&mCallbackLock);
3403 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_RAW_IMAGE)) {
3404 if(native_get_picture(mCameraControlFd, &mCrop) == false) {
3405 LOGE("getPicture failed!");
3406 return;
3407 }
3408 mCrop.in1_w &= ~1;
3409 mCrop.in1_h &= ~1;
3410 mCrop.in2_w &= ~1;
3411 mCrop.in2_h &= ~1;
3412
3413 // By the time native_get_picture returns, picture is taken. Call
3414 // shutter callback if cam config thread has not done that.
3415 notifyShutter(&mCrop);
3416
3417 // Crop the image if zoomed.
3418 if (mCrop.in2_w != 0 && mCrop.in2_h != 0) {
3419 crop_yuv420(mCrop.out2_w, mCrop.out2_h, mCrop.in2_w, mCrop.in2_h,
3420 (uint8_t *)mRawHeap->mHeap->base());
3421 crop_yuv420(mCrop.out1_w, mCrop.out1_h, mCrop.in1_w, mCrop.in1_h,
3422 (uint8_t *)mThumbnailHeap->mHeap->base());
3423 // We do not need jpeg encoder to upscale the image. Set the new
3424 // dimension for encoder.
3425 mDimension.orig_picture_dx = mCrop.in2_w;
3426 mDimension.orig_picture_dy = mCrop.in2_h;
3427 mDimension.thumbnail_width = mCrop.in1_w;
3428 mDimension.thumbnail_height = mCrop.in1_h;
3429 memset(&mCrop, 0, sizeof(mCrop));
3430 }
3431
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003432 if( mUseOverlay && (mOverlay != NULL) ) {
3433 mOverlay->setFd(mPostViewHeap->mHeap->getHeapID());
3434 if( zoomCropInfo.w !=0 && zoomCropInfo.h !=0) {
3435 LOGD(" zoomCropInfo non-zero, setting crop ");
3436 mOverlay->setCrop(zoomCropInfo.x, zoomCropInfo.y,
3437 zoomCropInfo.w, zoomCropInfo.h);
3438 }
3439 LOGD(" Queueing Postview for display ");
3440 mOverlay->queueBuffer((void *)0);
3441 }
3442
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003443 mDataCallback(CAMERA_MSG_RAW_IMAGE, mDisplayHeap->mBuffers[0],
3444 mCallbackCookie);
3445 }
3446 else LOGV("Raw-picture callback was canceled--skipping.");
3447
3448 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
3449 mJpegSize = 0;
3450 if (LINK_jpeg_encoder_init()) {
3451 if(native_jpeg_encode()) {
3452 LOGV("receiveRawPicture: X (success)");
3453 return;
3454 }
3455 LOGE("jpeg encoding failed");
3456 }
3457 else LOGE("receiveRawPicture X: jpeg_encoder_init failed.");
3458 }
3459 else LOGV("JPEG callback is NULL, not encoding image.");
3460 deinitRaw();
3461 LOGV("receiveRawPicture: X");
3462}
3463
3464void QualcommCameraHardware::receiveJpegPictureFragment(
3465 uint8_t *buff_ptr, uint32_t buff_size)
3466{
3467 uint32_t remaining = mJpegHeap->mHeap->virtualSize();
3468 remaining -= mJpegSize;
3469 uint8_t *base = (uint8_t *)mJpegHeap->mHeap->base();
3470
3471 LOGV("receiveJpegPictureFragment size %d", buff_size);
3472 if (buff_size > remaining) {
3473 LOGE("receiveJpegPictureFragment: size %d exceeds what "
3474 "remains in JPEG heap (%d), truncating",
3475 buff_size,
3476 remaining);
3477 buff_size = remaining;
3478 }
3479 memcpy(base + mJpegSize, buff_ptr, buff_size);
3480 mJpegSize += buff_size;
3481}
3482
3483void QualcommCameraHardware::receiveJpegPicture(void)
3484{
3485 LOGV("receiveJpegPicture: E image (%d uint8_ts out of %d)",
3486 mJpegSize, mJpegHeap->mBufferSize);
3487 Mutex::Autolock cbLock(&mCallbackLock);
3488
3489 int index = 0, rc;
3490
3491 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
3492 // The reason we do not allocate into mJpegHeap->mBuffers[offset] is
3493 // that the JPEG image's size will probably change from one snapshot
3494 // to the next, so we cannot reuse the MemoryBase object.
3495 sp<MemoryBase> buffer = new
3496 MemoryBase(mJpegHeap->mHeap,
3497 index * mJpegHeap->mBufferSize +
3498 0,
3499 mJpegSize);
3500 mDataCallback(CAMERA_MSG_COMPRESSED_IMAGE, buffer, mCallbackCookie);
3501 buffer = NULL;
3502 }
3503 else LOGV("JPEG callback was cancelled--not delivering image.");
3504
3505 LINK_jpeg_encoder_join();
3506 deinitRaw();
3507
3508 LOGV("receiveJpegPicture: X callback done.");
3509}
3510
3511bool QualcommCameraHardware::previewEnabled()
3512{
3513 return mCameraRunning && mDataCallback && (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME);
3514}
3515
3516status_t QualcommCameraHardware::setPreviewSize(const CameraParameters& params)
3517{
3518 int width, height;
3519 params.getPreviewSize(&width, &height);
3520 LOGV("requested preview size %d x %d", width, height);
3521
3522 // Validate the preview size
3523 for (size_t i = 0; i < PREVIEW_SIZE_COUNT; ++i) {
3524 if (width == preview_sizes[i].width
3525 && height == preview_sizes[i].height) {
3526 mParameters.setPreviewSize(width, height);
3527 mDimension.display_width = width;
3528 mDimension.display_height = height;
3529 return NO_ERROR;
3530 }
3531 }
3532 LOGE("Invalid preview size requested: %dx%d", width, height);
3533 return BAD_VALUE;
3534}
3535
3536status_t QualcommCameraHardware::setPictureSize(const CameraParameters& params)
3537{
3538 int width, height;
3539 params.getPictureSize(&width, &height);
3540 LOGV("requested picture size %d x %d", width, height);
3541
3542 // Validate the picture size
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -08003543 for (int i = 0; i < supportedPictureSizesCount; ++i) {
3544 if (width == picture_sizes_ptr[i].width
3545 && height == picture_sizes_ptr[i].height) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003546 mParameters.setPictureSize(width, height);
3547 mDimension.picture_width = width;
3548 mDimension.picture_height = height;
3549 return NO_ERROR;
3550 }
3551 }
3552 LOGE("Invalid picture size requested: %dx%d", width, height);
3553 return BAD_VALUE;
3554}
3555
3556status_t QualcommCameraHardware::setJpegQuality(const CameraParameters& params) {
3557 status_t rc = NO_ERROR;
3558 int quality = params.getInt(CameraParameters::KEY_JPEG_QUALITY);
3559 if (quality > 0 && quality <= 100) {
3560 mParameters.set(CameraParameters::KEY_JPEG_QUALITY, quality);
3561 } else {
3562 LOGE("Invalid jpeg quality=%d", quality);
3563 rc = BAD_VALUE;
3564 }
3565
3566 quality = params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY);
3567 if (quality > 0 && quality <= 100) {
3568 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, quality);
3569 } else {
3570 LOGE("Invalid jpeg thumbnail quality=%d", quality);
3571 rc = BAD_VALUE;
3572 }
3573 return rc;
3574}
3575
3576status_t QualcommCameraHardware::setEffect(const CameraParameters& params)
3577{
3578 const char *str = params.get(CameraParameters::KEY_EFFECT);
3579 if (str != NULL) {
3580 int32_t value = attr_lookup(effects, sizeof(effects) / sizeof(str_map), str);
3581 if (value != NOT_FOUND) {
Mohan Kandra93f1bfb2009-12-15 16:55:33 -08003582 if(!strcmp(sensorType->name, "2mp") && (value != CAMERA_EFFECT_OFF)
3583 &&(value != CAMERA_EFFECT_MONO) && (value != CAMERA_EFFECT_NEGATIVE)
3584 &&(value != CAMERA_EFFECT_SOLARIZE) && (value != CAMERA_EFFECT_SEPIA)) {
3585 LOGE("Special effect parameter is not supported for this sensor");
3586 return NO_ERROR;
3587 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003588 mParameters.set(CameraParameters::KEY_EFFECT, str);
3589 bool ret = native_set_parm(CAMERA_SET_PARM_EFFECT, sizeof(value),
3590 (void *)&value);
3591 return ret ? NO_ERROR : UNKNOWN_ERROR;
3592 }
3593 }
3594 LOGE("Invalid effect value: %s", (str == NULL) ? "NULL" : str);
3595 return BAD_VALUE;
3596}
3597
Apurva Rajguru55562b02009-12-03 12:25:35 -08003598status_t QualcommCameraHardware::setAutoExposure(const CameraParameters& params)
3599{
Mohan Kandra93f1bfb2009-12-15 16:55:33 -08003600 if(!strcmp(sensorType->name, "2mp")) {
3601 LOGE("Auto Exposure not supported for this sensor");
3602 return NO_ERROR;
3603 }
Apurva Rajguru55562b02009-12-03 12:25:35 -08003604 const char *str = params.get(CameraParameters::KEY_AUTO_EXPOSURE);
3605 if (str != NULL) {
3606 int32_t value = attr_lookup(autoexposure, sizeof(autoexposure) / sizeof(str_map), str);
3607 if (value != NOT_FOUND) {
3608 mParameters.set(CameraParameters::KEY_AUTO_EXPOSURE, str);
3609 bool ret = native_set_parm(CAMERA_SET_PARM_EXPOSURE, sizeof(value),
3610 (void *)&value);
3611 return ret ? NO_ERROR : UNKNOWN_ERROR;
3612 }
3613 }
3614 LOGE("Invalid auto exposure value: %s", (str == NULL) ? "NULL" : str);
3615 return BAD_VALUE;
3616}
3617
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003618status_t QualcommCameraHardware::setSharpness(const CameraParameters& params)
3619{
3620 if(!strcmp(sensorType->name, "2mp")) {
3621 LOGE("Sharpness not supported for this sensor");
3622 return NO_ERROR;
3623 }
3624 int sharpness = params.getInt(CameraParameters::KEY_SHARPNESS);
3625 if((sharpness < CAMERA_MIN_SHARPNESS
3626 || sharpness > CAMERA_MAX_SHARPNESS))
3627 return UNKNOWN_ERROR;
Srinivasan Kannan551fd262010-01-14 17:48:30 -08003628
3629 LOGV("setting sharpness %d", sharpness);
3630 mParameters.set(CameraParameters::KEY_SHARPNESS, sharpness);
3631 bool ret = native_set_parm(CAMERA_SET_PARM_SHARPNESS, sizeof(sharpness),
3632 (void *)&sharpness);
3633 return ret ? NO_ERROR : UNKNOWN_ERROR;
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003634}
3635
3636status_t QualcommCameraHardware::setContrast(const CameraParameters& params)
3637{
3638 if(!strcmp(sensorType->name, "2mp")) {
3639 LOGE("Contrast not supported for this sensor");
3640 return NO_ERROR;
3641 }
3642 int contrast = params.getInt(CameraParameters::KEY_CONTRAST);
3643 if((contrast < CAMERA_MIN_CONTRAST)
3644 || (contrast > CAMERA_MAX_CONTRAST))
3645 return UNKNOWN_ERROR;
Srinivasan Kannan551fd262010-01-14 17:48:30 -08003646
3647 LOGV("setting contrast %d", contrast);
3648 mParameters.set(CameraParameters::KEY_CONTRAST, contrast);
3649 bool ret = native_set_parm(CAMERA_SET_PARM_CONTRAST, sizeof(contrast),
3650 (void *)&contrast);
3651 return ret ? NO_ERROR : UNKNOWN_ERROR;
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003652}
3653
3654status_t QualcommCameraHardware::setSaturation(const CameraParameters& params)
3655{
3656 if(!strcmp(sensorType->name, "2mp")) {
3657 LOGE("Saturation not supported for this sensor");
3658 return NO_ERROR;
3659 }
Srinivasan Kannan551fd262010-01-14 17:48:30 -08003660
Kiran Kumar H Nf87cf862010-01-27 14:34:34 -08003661 const char *str = params.get(CameraParameters::KEY_EFFECT);
3662 int32_t value = attr_lookup(effects, sizeof(effects) / sizeof(str_map), str);
3663
3664 if( (value != CAMERA_EFFECT_MONO) && (value != CAMERA_EFFECT_NEGATIVE)
3665 && (value != CAMERA_EFFECT_AQUA) && (value != CAMERA_EFFECT_SEPIA)) {
3666
3667 int saturation = params.getInt(CameraParameters::KEY_SATURATION);
3668 if((saturation < CAMERA_MIN_SATURATION)
3669 || (saturation > CAMERA_MAX_SATURATION))
3670 return UNKNOWN_ERROR;
3671
3672 LOGV("setting saturation %d", saturation);
3673 mParameters.set(CameraParameters::KEY_SATURATION, saturation);
3674 bool ret = native_set_parm(CAMERA_SET_PARM_SATURATION, sizeof(saturation),
3675 (void *)&saturation);
3676 return ret ? NO_ERROR : UNKNOWN_ERROR;
3677 } else {
3678 LOGE(" Saturation value will not be set " \
3679 "when the effect selected is %s", str);
3680 return NO_ERROR;
3681 }
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003682}
3683
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303684status_t QualcommCameraHardware::setBrightness(const CameraParameters& params) {
3685 int brightness = params.getInt("luma-adaptation");
3686 if (mBrightness != brightness) {
3687 LOGV(" new brightness value : %d ", brightness);
3688 mBrightness = brightness;
3689
3690 bool ret = native_set_parm(CAMERA_SET_PARM_BRIGHTNESS, sizeof(mBrightness),
3691 (void *)&mBrightness);
3692 return ret ? NO_ERROR : UNKNOWN_ERROR;
3693 } else {
3694 return NO_ERROR;
3695 }
3696}
3697
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003698status_t QualcommCameraHardware::setWhiteBalance(const CameraParameters& params)
3699{
3700 const char *str = params.get(CameraParameters::KEY_WHITE_BALANCE);
3701 if (str != NULL) {
3702 int32_t value = attr_lookup(whitebalance, sizeof(whitebalance) / sizeof(str_map), str);
3703 if (value != NOT_FOUND) {
3704 mParameters.set(CameraParameters::KEY_WHITE_BALANCE, str);
3705 bool ret = native_set_parm(CAMERA_SET_PARM_WB, sizeof(value),
3706 (void *)&value);
3707 return ret ? NO_ERROR : UNKNOWN_ERROR;
3708 }
3709 }
3710 LOGE("Invalid whitebalance value: %s", (str == NULL) ? "NULL" : str);
3711 return BAD_VALUE;
3712}
3713
3714status_t QualcommCameraHardware::setFlash(const CameraParameters& params)
3715{
3716 if (!mSensorInfo.flash_enabled) {
3717 LOGV("%s: flash not supported", __FUNCTION__);
3718 return NO_ERROR;
3719 }
3720
3721 const char *str = params.get(CameraParameters::KEY_FLASH_MODE);
3722 if (str != NULL) {
3723 int32_t value = attr_lookup(flash, sizeof(flash) / sizeof(str_map), str);
3724 if (value != NOT_FOUND) {
3725 mParameters.set(CameraParameters::KEY_FLASH_MODE, str);
3726 bool ret = native_set_parm(CAMERA_SET_PARM_LED_MODE,
3727 sizeof(value), (void *)&value);
3728 return ret ? NO_ERROR : UNKNOWN_ERROR;
3729 }
3730 }
3731 LOGE("Invalid flash mode value: %s", (str == NULL) ? "NULL" : str);
3732 return BAD_VALUE;
3733}
3734
3735status_t QualcommCameraHardware::setAntibanding(const CameraParameters& params)
3736{
Srinivasan Kannan2229d272010-01-05 14:58:28 -08003737 if(!strcmp(sensorType->name, "2mp")) {
3738 LOGE("Parameter AntiBanding is not supported for this sensor");
3739 return NO_ERROR;
3740 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003741 const char *str = params.get(CameraParameters::KEY_ANTIBANDING);
3742 if (str != NULL) {
3743 int value = (camera_antibanding_type)attr_lookup(
3744 antibanding, sizeof(antibanding) / sizeof(str_map), str);
3745 if (value != NOT_FOUND) {
3746 camera_antibanding_type temp = (camera_antibanding_type) value;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003747 mParameters.set(CameraParameters::KEY_ANTIBANDING, str);
Srinivasan Kannan2229d272010-01-05 14:58:28 -08003748 bool ret;
3749 if (temp == CAMERA_ANTIBANDING_AUTO) {
3750 ret = native_set_parm(CAMERA_ENABLE_AFD,
3751 0, NULL);
3752 } else {
3753 ret = native_set_parm(CAMERA_SET_PARM_ANTIBANDING,
3754 sizeof(camera_antibanding_type), (void *)&temp);
3755 }
3756 return ret ? NO_ERROR : UNKNOWN_ERROR;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003757 }
3758 }
3759 LOGE("Invalid antibanding value: %s", (str == NULL) ? "NULL" : str);
3760 return BAD_VALUE;
3761}
3762
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303763status_t QualcommCameraHardware::setLensshadeValue(const CameraParameters& params)
3764{
Mohan Kandra93f1bfb2009-12-15 16:55:33 -08003765 if(!strcmp(sensorType->name, "2mp")) {
3766 LOGE("Parameter Rolloff is not supported for this sensor");
3767 return NO_ERROR;
3768 }
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303769 const char *str = params.get(CameraParameters::KEY_LENSSHADE);
3770 if (str != NULL) {
3771 int value = attr_lookup(lensshade,
3772 sizeof(lensshade) / sizeof(str_map), str);
3773 if (value != NOT_FOUND) {
3774 int8_t temp = (int8_t)value;
3775 mParameters.set(CameraParameters::KEY_LENSSHADE, str);
3776 native_set_parm(CAMERA_SET_PARM_ROLLOFF, sizeof(int8_t), (void *)&temp);
3777 return NO_ERROR;
3778 }
3779 }
3780 LOGE("Invalid lensShade value: %s", (str == NULL) ? "NULL" : str);
3781 return BAD_VALUE;
3782}
3783
3784status_t QualcommCameraHardware::setISOValue(const CameraParameters& params) {
3785 const char *str = params.get(CameraParameters::KEY_ISO_MODE);
3786 if (str != NULL) {
3787 int value = (camera_iso_mode_type)attr_lookup(
3788 iso, sizeof(iso) / sizeof(str_map), str);
3789 if (value != NOT_FOUND) {
3790 camera_iso_mode_type temp = (camera_iso_mode_type) value;
3791 mParameters.set(CameraParameters::KEY_ISO_MODE, str);
3792 native_set_parm(CAMERA_SET_PARM_ISO, sizeof(camera_iso_mode_type), (void *)&temp);
3793 return NO_ERROR;
3794 }
3795 }
3796 LOGE("Invalid Iso value: %s", (str == NULL) ? "NULL" : str);
3797 return BAD_VALUE;
3798}
3799
3800
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003801status_t QualcommCameraHardware::setGpsLocation(const CameraParameters& params)
3802{
3803 const char *latitude = params.get(CameraParameters::KEY_GPS_LATITUDE);
3804 if (latitude) {
3805 mParameters.set(CameraParameters::KEY_GPS_LATITUDE, latitude);
3806 }
3807
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08003808 const char *latitudeRef = params.get(CameraParameters::KEY_GPS_LATITUDE_REF);
3809 if (latitudeRef) {
3810 mParameters.set(CameraParameters::KEY_GPS_LATITUDE_REF, latitudeRef);
3811 }
3812
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003813 const char *longitude = params.get(CameraParameters::KEY_GPS_LONGITUDE);
3814 if (longitude) {
3815 mParameters.set(CameraParameters::KEY_GPS_LONGITUDE, longitude);
3816 }
3817
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08003818 const char *longitudeRef = params.get(CameraParameters::KEY_GPS_LONGITUDE_REF);
3819 if (longitudeRef) {
3820 mParameters.set(CameraParameters::KEY_GPS_LONGITUDE_REF, longitudeRef);
3821 }
3822
3823 const char *altitudeRef = params.get(CameraParameters::KEY_GPS_ALTITUDE_REF);
3824 if (altitudeRef) {
3825 mParameters.set(CameraParameters::KEY_GPS_ALTITUDE_REF, altitudeRef);
3826 }
3827
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003828 const char *altitude = params.get(CameraParameters::KEY_GPS_ALTITUDE);
3829 if (altitude) {
3830 mParameters.set(CameraParameters::KEY_GPS_ALTITUDE, altitude);
3831 }
3832
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08003833 const char *status = params.get(CameraParameters::KEY_GPS_STATUS);
3834 if (status) {
3835 mParameters.set(CameraParameters::KEY_GPS_STATUS, status);
3836 }
3837
3838 const char *dateTime = params.get(CameraParameters::KEY_EXIF_DATETIME);
3839 if (dateTime) {
3840 mParameters.set(CameraParameters::KEY_EXIF_DATETIME, dateTime);
3841 }
3842
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003843 const char *timestamp = params.get(CameraParameters::KEY_GPS_TIMESTAMP);
3844 if (timestamp) {
3845 mParameters.set(CameraParameters::KEY_GPS_TIMESTAMP, timestamp);
3846 }
3847 return NO_ERROR;
3848}
3849
3850status_t QualcommCameraHardware::setRotation(const CameraParameters& params)
3851{
3852 status_t rc = NO_ERROR;
3853 int rotation = params.getInt(CameraParameters::KEY_ROTATION);
3854 if (rotation != NOT_FOUND) {
3855 if (rotation == 0 || rotation == 90 || rotation == 180
3856 || rotation == 270) {
3857 mParameters.set(CameraParameters::KEY_ROTATION, rotation);
3858 } else {
3859 LOGE("Invalid rotation value: %d", rotation);
3860 rc = BAD_VALUE;
3861 }
3862 }
3863 return rc;
3864}
3865
3866status_t QualcommCameraHardware::setZoom(const CameraParameters& params)
3867{
3868 status_t rc = NO_ERROR;
3869 // No matter how many different zoom values the driver can provide, HAL
3870 // provides applictations the same number of zoom levels. The maximum driver
3871 // zoom value depends on sensor output (VFE input) and preview size (VFE
3872 // output) because VFE can only crop and cannot upscale. If the preview size
3873 // is bigger, the maximum zoom ratio is smaller. However, we want the
3874 // zoom ratio of each zoom level is always the same whatever the preview
3875 // size is. Ex: zoom level 1 is always 1.2x, zoom level 2 is 1.44x, etc. So,
3876 // we need to have a fixed maximum zoom value and do read it from the
3877 // driver.
Mohan Kandra284966d2010-01-05 13:39:15 -08003878 static const int ZOOM_STEP = 1;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003879 int32_t zoom_level = params.getInt("zoom");
3880
Mohan Kandra284966d2010-01-05 13:39:15 -08003881 LOGV("Set zoom=%d", zoom_level);
3882 if(zoom_level >= 0 && zoom_level <= mMaxZoom) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003883 mParameters.set("zoom", zoom_level);
3884 int32_t zoom_value = ZOOM_STEP * zoom_level;
3885 bool ret = native_set_parm(CAMERA_SET_PARM_ZOOM,
3886 sizeof(zoom_value), (void *)&zoom_value);
3887 rc = ret ? NO_ERROR : UNKNOWN_ERROR;
3888 } else {
3889 rc = BAD_VALUE;
3890 }
3891
3892 return rc;
3893}
3894
3895status_t QualcommCameraHardware::setFocusMode(const CameraParameters& params)
3896{
3897 const char *str = params.get(CameraParameters::KEY_FOCUS_MODE);
3898 if (str != NULL) {
3899 int32_t value = attr_lookup(focus_modes,
3900 sizeof(focus_modes) / sizeof(str_map), str);
3901 if (value != NOT_FOUND) {
3902 mParameters.set(CameraParameters::KEY_FOCUS_MODE, str);
3903 // Focus step is reset to infinity when preview is started. We do
3904 // not need to do anything now.
3905 return NO_ERROR;
3906 }
3907 }
3908 LOGE("Invalid focus mode value: %s", (str == NULL) ? "NULL" : str);
3909 return BAD_VALUE;
3910}
3911
3912status_t QualcommCameraHardware::setOrientation(const CameraParameters& params)
3913{
3914 const char *str = params.get("orientation");
3915
3916 if (str != NULL) {
3917 if (strcmp(str, "portrait") == 0 || strcmp(str, "landscape") == 0) {
3918 // Camera service needs this to decide if the preview frames and raw
3919 // pictures should be rotated.
3920 mParameters.set("orientation", str);
3921 } else {
3922 LOGE("Invalid orientation value: %s", str);
3923 return BAD_VALUE;
3924 }
3925 }
3926 return NO_ERROR;
3927}
3928
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08003929status_t QualcommCameraHardware::setPictureFormat(const CameraParameters& params)
3930{
3931 const char * str = params.get(CameraParameters::KEY_PICTURE_FORMAT);
3932
3933 if(str != NULL){
3934 int32_t value = attr_lookup(picture_formats,
3935 sizeof(picture_formats) / sizeof(str_map), str);
3936 if(value != NOT_FOUND){
3937 mParameters.set(CameraParameters::KEY_PICTURE_FORMAT, str);
3938 } else {
3939 LOGE("Invalid Picture Format value: %s", str);
3940 return BAD_VALUE;
3941 }
3942 }
3943 return NO_ERROR;
3944}
3945
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003946QualcommCameraHardware::MemPool::MemPool(int buffer_size, int num_buffers,
3947 int frame_size,
3948 const char *name) :
3949 mBufferSize(buffer_size),
3950 mNumBuffers(num_buffers),
3951 mFrameSize(frame_size),
3952 mBuffers(NULL), mName(name)
3953{
3954 int page_size_minus_1 = getpagesize() - 1;
3955 mAlignedBufferSize = (buffer_size + page_size_minus_1) & (~page_size_minus_1);
3956}
3957
3958void QualcommCameraHardware::MemPool::completeInitialization()
3959{
3960 // If we do not know how big the frame will be, we wait to allocate
3961 // the buffers describing the individual frames until we do know their
3962 // size.
3963
3964 if (mFrameSize > 0) {
3965 mBuffers = new sp<MemoryBase>[mNumBuffers];
3966 for (int i = 0; i < mNumBuffers; i++) {
3967 mBuffers[i] = new
3968 MemoryBase(mHeap,
3969 i * mAlignedBufferSize,
3970 mFrameSize);
3971 }
3972 }
3973}
3974
3975QualcommCameraHardware::AshmemPool::AshmemPool(int buffer_size, int num_buffers,
3976 int frame_size,
3977 const char *name) :
3978 QualcommCameraHardware::MemPool(buffer_size,
3979 num_buffers,
3980 frame_size,
3981 name)
3982{
3983 LOGV("constructing MemPool %s backed by ashmem: "
3984 "%d frames @ %d uint8_ts, "
3985 "buffer size %d",
3986 mName,
3987 num_buffers, frame_size, buffer_size);
3988
3989 int page_mask = getpagesize() - 1;
3990 int ashmem_size = buffer_size * num_buffers;
3991 ashmem_size += page_mask;
3992 ashmem_size &= ~page_mask;
3993
3994 mHeap = new MemoryHeapBase(ashmem_size);
3995
3996 completeInitialization();
3997}
3998
3999static bool register_buf(int camfd,
4000 int size,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08004001 int frame_size,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004002 int pmempreviewfd,
4003 uint32_t offset,
4004 uint8_t *buf,
4005 int pmem_type,
4006 bool vfe_can_write,
4007 bool register_buffer = true);
4008
4009QualcommCameraHardware::PmemPool::PmemPool(const char *pmem_pool,
4010 int flags,
4011 int camera_control_fd,
4012 int pmem_type,
4013 int buffer_size, int num_buffers,
4014 int frame_size,
4015 const char *name) :
4016 QualcommCameraHardware::MemPool(buffer_size,
4017 num_buffers,
4018 frame_size,
4019 name),
4020 mPmemType(pmem_type),
4021 mCameraControlFd(dup(camera_control_fd))
4022{
4023 LOGV("constructing MemPool %s backed by pmem pool %s: "
4024 "%d frames @ %d bytes, buffer size %d",
4025 mName,
4026 pmem_pool, num_buffers, frame_size,
4027 buffer_size);
4028
4029 LOGV("%s: duplicating control fd %d --> %d",
4030 __FUNCTION__,
4031 camera_control_fd, mCameraControlFd);
4032
4033 // Make a new mmap'ed heap that can be shared across processes.
4034 // mAlignedBufferSize is already in 4k aligned. (do we need total size necessary to be in power of 2??)
4035 mAlignedSize = mAlignedBufferSize * num_buffers;
4036
4037 sp<MemoryHeapBase> masterHeap =
4038 new MemoryHeapBase(pmem_pool, mAlignedSize, flags);
4039
4040 if (masterHeap->getHeapID() < 0) {
4041 LOGE("failed to construct master heap for pmem pool %s", pmem_pool);
4042 masterHeap.clear();
4043 return;
4044 }
4045
4046 sp<MemoryHeapPmem> pmemHeap = new MemoryHeapPmem(masterHeap, flags);
4047 if (pmemHeap->getHeapID() >= 0) {
4048 pmemHeap->slap();
4049 masterHeap.clear();
4050 mHeap = pmemHeap;
4051 pmemHeap.clear();
4052
4053 mFd = mHeap->getHeapID();
4054 if (::ioctl(mFd, PMEM_GET_SIZE, &mSize)) {
4055 LOGE("pmem pool %s ioctl(PMEM_GET_SIZE) error %s (%d)",
4056 pmem_pool,
4057 ::strerror(errno), errno);
4058 mHeap.clear();
4059 return;
4060 }
4061
4062 LOGV("pmem pool %s ioctl(fd = %d, PMEM_GET_SIZE) is %ld",
4063 pmem_pool,
4064 mFd,
4065 mSize.len);
Mohan Kandra284966d2010-01-05 13:39:15 -08004066 LOGD("mBufferSize=%d, mAlignedBufferSize=%d\n", mBufferSize, mAlignedBufferSize);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004067 // Unregister preview buffers with the camera drivers. Allow the VFE to write
4068 // to all preview buffers except for the last one.
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08004069 // Only Register the preview, snapshot and thumbnail buffers with the kernel.
Mohan Kandrad9efed92010-01-15 19:08:39 -08004070 if( (strcmp("postview", mName) != 0) ){
4071 int num_buf = num_buffers;
4072 if(!strcmp("preview", mName)) num_buf = kPreviewBufferCount;
Brian Steuerb62adbd2010-02-02 14:47:08 -08004073 LOGD("num_buffers = %d", num_buf);
Mohan Kandrad9efed92010-01-15 19:08:39 -08004074 for (int cnt = 0; cnt < num_buf; ++cnt) {
Sravankb4f5f1c2010-01-21 11:06:17 +05304075 int active = 1;
4076 if(pmem_type == MSM_PMEM_VIDEO){
4077 active = (cnt<ACTIVE_VIDEO_BUFFERS);
4078 LOGV(" pmempool creating video buffers : active %d ", active);
4079 }
4080 else if (pmem_type == MSM_PMEM_PREVIEW){
4081 active = (cnt < (num_buf-1));
4082 }
Mohan Kandra284966d2010-01-05 13:39:15 -08004083 register_buf(mCameraControlFd,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004084 mBufferSize,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08004085 mFrameSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004086 mHeap->getHeapID(),
4087 mAlignedBufferSize * cnt,
4088 (uint8_t *)mHeap->base() + mAlignedBufferSize * cnt,
4089 pmem_type,
Sravankb4f5f1c2010-01-21 11:06:17 +05304090 active);
Mohan Kandra284966d2010-01-05 13:39:15 -08004091 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004092 }
4093
4094 completeInitialization();
4095 }
4096 else LOGE("pmem pool %s error: could not create master heap!",
4097 pmem_pool);
4098}
4099
4100QualcommCameraHardware::PmemPool::~PmemPool()
4101{
4102 LOGV("%s: %s E", __FUNCTION__, mName);
4103 if (mHeap != NULL) {
4104 // Unregister preview buffers with the camera drivers.
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08004105 // Only Unregister the preview, snapshot and thumbnail
4106 // buffers with the kernel.
Mohan Kandrad9efed92010-01-15 19:08:39 -08004107 if( (strcmp("postview", mName) != 0) ){
4108 int num_buffers = mNumBuffers;
4109 if(!strcmp("preview", mName)) num_buffers = kPreviewBufferCount;
4110 for (int cnt = 0; cnt < num_buffers; ++cnt) {
Mohan Kandra284966d2010-01-05 13:39:15 -08004111 register_buf(mCameraControlFd,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004112 mBufferSize,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08004113 mFrameSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004114 mHeap->getHeapID(),
4115 mAlignedBufferSize * cnt,
4116 (uint8_t *)mHeap->base() + mAlignedBufferSize * cnt,
4117 mPmemType,
4118 false,
4119 false /* unregister */);
Mohan Kandra284966d2010-01-05 13:39:15 -08004120 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004121 }
4122 }
4123 LOGV("destroying PmemPool %s: closing control fd %d",
4124 mName,
4125 mCameraControlFd);
4126 close(mCameraControlFd);
4127 LOGV("%s: %s X", __FUNCTION__, mName);
4128}
4129
4130QualcommCameraHardware::MemPool::~MemPool()
4131{
4132 LOGV("destroying MemPool %s", mName);
4133 if (mFrameSize > 0)
4134 delete [] mBuffers;
4135 mHeap.clear();
4136 LOGV("destroying MemPool %s completed", mName);
4137}
4138
4139static bool register_buf(int camfd,
4140 int size,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08004141 int frame_size,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004142 int pmempreviewfd,
4143 uint32_t offset,
4144 uint8_t *buf,
4145 int pmem_type,
4146 bool vfe_can_write,
4147 bool register_buffer)
4148{
4149 struct msm_pmem_info pmemBuf;
4150
4151 pmemBuf.type = pmem_type;
4152 pmemBuf.fd = pmempreviewfd;
4153 pmemBuf.offset = offset;
4154 pmemBuf.len = size;
4155 pmemBuf.vaddr = buf;
4156 pmemBuf.y_off = 0;
Srinivasan Kannanb36a4fe2010-01-29 19:34:09 -08004157
4158 if(pmem_type == MSM_PMEM_RAW_MAINIMG)
4159 pmemBuf.cbcr_off = 0;
4160 else
4161 pmemBuf.cbcr_off = PAD_TO_WORD(frame_size * 2 / 3);
4162
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004163 pmemBuf.active = vfe_can_write;
4164
4165 LOGV("register_buf: camfd = %d, reg = %d buffer = %p",
4166 camfd, !register_buffer, buf);
4167 if (ioctl(camfd,
4168 register_buffer ?
4169 MSM_CAM_IOCTL_REGISTER_PMEM :
4170 MSM_CAM_IOCTL_UNREGISTER_PMEM,
4171 &pmemBuf) < 0) {
4172 LOGE("register_buf: MSM_CAM_IOCTL_(UN)REGISTER_PMEM fd %d error %s",
4173 camfd,
4174 strerror(errno));
4175 return false;
4176 }
4177 return true;
4178}
4179
4180status_t QualcommCameraHardware::MemPool::dump(int fd, const Vector<String16>& args) const
4181{
4182 const size_t SIZE = 256;
4183 char buffer[SIZE];
4184 String8 result;
4185 snprintf(buffer, 255, "QualcommCameraHardware::AshmemPool::dump\n");
4186 result.append(buffer);
4187 if (mName) {
4188 snprintf(buffer, 255, "mem pool name (%s)\n", mName);
4189 result.append(buffer);
4190 }
4191 if (mHeap != 0) {
4192 snprintf(buffer, 255, "heap base(%p), size(%d), flags(%d), device(%s)\n",
4193 mHeap->getBase(), mHeap->getSize(),
4194 mHeap->getFlags(), mHeap->getDevice());
4195 result.append(buffer);
4196 }
4197 snprintf(buffer, 255,
4198 "buffer size (%d), number of buffers (%d), frame size(%d)",
4199 mBufferSize, mNumBuffers, mFrameSize);
4200 result.append(buffer);
4201 write(fd, result.string(), result.size());
4202 return NO_ERROR;
4203}
4204
4205static void receive_camframe_callback(struct msm_frame *frame)
4206{
4207 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4208 if (obj != 0) {
4209 obj->receivePreviewFrame(frame);
4210 }
4211}
4212
4213static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size)
4214{
4215 LOGV("receive_jpeg_fragment_callback E");
4216 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4217 if (obj != 0) {
4218 obj->receiveJpegPictureFragment(buff_ptr, buff_size);
4219 }
4220 LOGV("receive_jpeg_fragment_callback X");
4221}
4222
4223static void receive_jpeg_callback(jpeg_event_t status)
4224{
4225 LOGV("receive_jpeg_callback E (completion status %d)", status);
4226 if (status == JPEG_EVENT_DONE) {
4227 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4228 if (obj != 0) {
4229 obj->receiveJpegPicture();
4230 }
4231 }
4232 LOGV("receive_jpeg_callback X");
4233}
Sravankb4f5f1c2010-01-21 11:06:17 +05304234// 720p : video frame calbback from camframe
4235static void receive_camframe_video_callback(struct msm_frame *frame)
4236{
4237 LOGV("receive_camframe_video_callback E");
4238 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4239 if (obj != 0) {
4240 obj->receiveRecordingFrame(frame);
4241 }
4242 LOGV("receive_camframe_video_callback X");
4243}
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004244
4245void QualcommCameraHardware::setCallbacks(notify_callback notify_cb,
4246 data_callback data_cb,
4247 data_callback_timestamp data_cb_timestamp,
4248 void* user)
4249{
4250 Mutex::Autolock lock(mLock);
4251 mNotifyCallback = notify_cb;
4252 mDataCallback = data_cb;
4253 mDataCallbackTimestamp = data_cb_timestamp;
4254 mCallbackCookie = user;
4255}
4256
4257void QualcommCameraHardware::enableMsgType(int32_t msgType)
4258{
4259 Mutex::Autolock lock(mLock);
4260 mMsgEnabled |= msgType;
4261}
4262
4263void QualcommCameraHardware::disableMsgType(int32_t msgType)
4264{
4265 Mutex::Autolock lock(mLock);
4266 mMsgEnabled &= ~msgType;
4267}
4268
4269bool QualcommCameraHardware::msgTypeEnabled(int32_t msgType)
4270{
4271 return (mMsgEnabled & msgType);
4272}
4273
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08004274bool QualcommCameraHardware::useOverlay(void)
4275{
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08004276 if( mCurrentTarget == TARGET_MSM7630 ) {
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08004277 /* Only 7x30 supports Overlay */
4278 mUseOverlay = TRUE;
4279 } else
4280 mUseOverlay = FALSE;
4281
4282 LOGV(" Using Overlay : %s ", mUseOverlay ? "YES" : "NO" );
4283 return mUseOverlay;
4284}
4285
4286status_t QualcommCameraHardware::setOverlay(const sp<Overlay> &Overlay)
4287{
4288 if( Overlay != NULL) {
4289 LOGV(" Valid overlay object ");
4290 mOverlayLock.lock();
4291 mOverlay = Overlay;
4292 mOverlayLock.unlock();
4293 } else {
4294 LOGE(" Overlay object NULL. returning ");
Mohan Kandrad9efed92010-01-15 19:08:39 -08004295 mOverlay = NULL;
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08004296 return UNKNOWN_ERROR;
4297 }
4298 return NO_ERROR;
4299}
Kiran Kumar H N215cac42009-12-08 01:53:46 -08004300
4301void QualcommCameraHardware::receive_camframetimeout(void) {
4302 LOGV("receive_camframetimeout: E");
4303 Mutex::Autolock l(&mCamframeTimeoutLock);
Kiran Kumar H N7ac84e32010-02-01 10:58:47 -08004304 LOGD(" Camframe timed out. Not receiving any frames from camera driver ");
Kiran Kumar H N215cac42009-12-08 01:53:46 -08004305 camframe_timeout_flag = TRUE;
4306 LOGV("receive_camframetimeout: X");
4307}
4308
4309static void receive_camframetimeout_callback(void) {
4310 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4311 if (obj != 0) {
4312 obj->receive_camframetimeout();
4313 }
4314}
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08004315
4316void QualcommCameraHardware::storePreviewFrameForPostview(void) {
4317 LOGV(" storePreviewFrameForPostview : E ");
4318
4319 /* Since there is restriction on the maximum overlay dimensions
4320 * that can be created, we use the last preview frame as postview
4321 * for 7x30. */
4322 LOGV(" Copying the preview buffer to postview buffer %d ",
4323 mPreviewFrameSize);
4324 if( mPostViewHeap != NULL && mLastQueuedFrame != NULL) {
4325 memcpy(mPostViewHeap->mHeap->base(),
4326 (uint8_t *)mLastQueuedFrame, mPreviewFrameSize );
4327 } else
4328 LOGE(" Failed to store Preview frame. No Postview ");
4329
4330 LOGV(" storePreviewFrameForPostview : X ");
4331}
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004332}; // namespace android