blob: 1c8575d3676a91f77edfd73da4a1c4711a9cb03a [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
167 { 720, 480 },
168 { 640, 480 }, // VGA
169 { 576, 432 },
170 { 480, 320 }, // HVGA
171 { 384, 288 },
172 { 352, 288 }, // CIF
173 { 320, 240 }, // QVGA
174 { 240, 160 }, // SQVGA
175 { 176, 144 }, // QCIF
176};
177#define PREVIEW_SIZE_COUNT (sizeof(preview_sizes)/sizeof(camera_size_type))
178
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800179//static const camera_size_type* picture_sizes;
180//static int PICTURE_SIZE_COUNT;
181/* TODO
182 * Ideally this should be a populated by lower layers.
183 * But currently this is no API to do that at lower layer.
184 * Hence populating with default sizes for now. This needs
185 * to be changed once the API is supported.
186 */
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800187//sorted on column basis
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800188static const camera_size_type picture_sizes[] = {
189 { 2592, 1944 }, // 5MP
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800190 { 2048, 1536 }, // 3MP QXGA
191 { 1920, 1080 }, //HD1080
192 { 1600, 1200 }, // 2MP UXGA
193 { 1280, 768 }, //WXGA
194 { 1280, 720 }, //HD720
195 { 1024, 768}, // 1MP XGA
196 { 800, 600 }, //SVGA
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800197 { 800, 480 }, // WVGA
198 { 640, 480 }, // VGA
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800199 { 352, 288 }, //CIF
200 { 320, 240 }, // QVGA
201 { 176, 144 } // QCIF
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800202};
203static int PICTURE_SIZE_COUNT = sizeof(picture_sizes)/sizeof(camera_size_type);
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800204static const camera_size_type * picture_sizes_ptr;
205static int supportedPictureSizesCount;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800206
Srinivasan Kannan80d878f2009-12-18 15:06:02 -0800207#ifdef Q12
208#undef Q12
209#endif
210
211#define Q12 4096
212
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -0800213static const target_map targetList [] = {
214 { "msm7625", TARGET_MSM7625 },
215 { "msm7627", TARGET_MSM7627 },
216 { "qsd8250", TARGET_QSD8250 },
217 { "msm7630", TARGET_MSM7630 }
218};
219static targetType mCurrentTarget = TARGET_MAX;
220
Srinivasan Kannan80d878f2009-12-18 15:06:02 -0800221typedef struct {
222 uint32_t aspect_ratio;
223 uint32_t width;
224 uint32_t height;
225} thumbnail_size_type;
226
227static thumbnail_size_type thumbnail_sizes[] = {
228 { 7281, 512, 288 }, //1.777778
229 { 6826, 480, 288 }, //1.666667
230 { 5461, 512, 384 }, //1.333333
231 { 5006, 352, 288 }, //1.222222
232};
233#define THUMBNAIL_SIZE_COUNT (sizeof(thumbnail_sizes)/sizeof(thumbnail_size_type))
234#define DEFAULT_THUMBNAIL_SETTING 2
235#define THUMBNAIL_WIDTH_STR "512"
236#define THUMBNAIL_HEIGHT_STR "384"
237#define THUMBNAIL_SMALL_HEIGHT 144
238
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800239static int attr_lookup(const str_map arr[], int len, const char *name)
240{
241 if (name) {
242 for (int i = 0; i < len; i++) {
243 if (!strcmp(arr[i].desc, name))
244 return arr[i].val;
245 }
246 }
247 return NOT_FOUND;
248}
249
250// round to the next power of two
251static inline unsigned clp2(unsigned x)
252{
253 x = x - 1;
254 x = x | (x >> 1);
255 x = x | (x >> 2);
256 x = x | (x >> 4);
257 x = x | (x >> 8);
258 x = x | (x >>16);
259 return x + 1;
260}
261
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -0800262static int exif_table_numEntries = 0;
263#define MAX_EXIF_TABLE_ENTRIES 7
264exif_tags_info_t exif_data[MAX_EXIF_TABLE_ENTRIES];
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -0800265static zoom_crop_info zoomCropInfo;
266static void *mLastQueuedFrame = NULL;
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -0800267
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800268namespace android {
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800269
270static const int PICTURE_FORMAT_JPEG = 1;
271static const int PICTURE_FORMAT_RAW = 2;
272
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800273// from aeecamera.h
274static const str_map whitebalance[] = {
275 { CameraParameters::WHITE_BALANCE_AUTO, CAMERA_WB_AUTO },
276 { CameraParameters::WHITE_BALANCE_INCANDESCENT, CAMERA_WB_INCANDESCENT },
277 { CameraParameters::WHITE_BALANCE_FLUORESCENT, CAMERA_WB_FLUORESCENT },
278 { CameraParameters::WHITE_BALANCE_DAYLIGHT, CAMERA_WB_DAYLIGHT },
279 { CameraParameters::WHITE_BALANCE_CLOUDY_DAYLIGHT, CAMERA_WB_CLOUDY_DAYLIGHT }
280};
281
282// from camera_effect_t. This list must match aeecamera.h
283static const str_map effects[] = {
284 { CameraParameters::EFFECT_NONE, CAMERA_EFFECT_OFF },
285 { CameraParameters::EFFECT_MONO, CAMERA_EFFECT_MONO },
286 { CameraParameters::EFFECT_NEGATIVE, CAMERA_EFFECT_NEGATIVE },
287 { CameraParameters::EFFECT_SOLARIZE, CAMERA_EFFECT_SOLARIZE },
288 { CameraParameters::EFFECT_SEPIA, CAMERA_EFFECT_SEPIA },
289 { CameraParameters::EFFECT_POSTERIZE, CAMERA_EFFECT_POSTERIZE },
290 { CameraParameters::EFFECT_WHITEBOARD, CAMERA_EFFECT_WHITEBOARD },
291 { CameraParameters::EFFECT_BLACKBOARD, CAMERA_EFFECT_BLACKBOARD },
292 { CameraParameters::EFFECT_AQUA, CAMERA_EFFECT_AQUA }
293};
294
295// from qcamera/common/camera.h
Apurva Rajguru55562b02009-12-03 12:25:35 -0800296static const str_map autoexposure[] = {
297 { CameraParameters::AUTO_EXPOSURE_FRAME_AVG, CAMERA_AEC_FRAME_AVERAGE },
298 { CameraParameters::AUTO_EXPOSURE_CENTER_WEIGHTED, CAMERA_AEC_CENTER_WEIGHTED },
299 { CameraParameters::AUTO_EXPOSURE_SPOT_METERING, CAMERA_AEC_SPOT_METERING }
300};
301
302// from qcamera/common/camera.h
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800303static const str_map antibanding[] = {
304 { CameraParameters::ANTIBANDING_OFF, CAMERA_ANTIBANDING_OFF },
305 { CameraParameters::ANTIBANDING_50HZ, CAMERA_ANTIBANDING_50HZ },
306 { CameraParameters::ANTIBANDING_60HZ, CAMERA_ANTIBANDING_60HZ },
307 { CameraParameters::ANTIBANDING_AUTO, CAMERA_ANTIBANDING_AUTO }
308};
309
310/* Mapping from MCC to antibanding type */
311struct country_map {
312 uint32_t country_code;
313 camera_antibanding_type type;
314};
315
316static struct country_map country_numeric[] = {
317 { 202, CAMERA_ANTIBANDING_50HZ }, // Greece
318 { 204, CAMERA_ANTIBANDING_50HZ }, // Netherlands
319 { 206, CAMERA_ANTIBANDING_50HZ }, // Belgium
320 { 208, CAMERA_ANTIBANDING_50HZ }, // France
321 { 212, CAMERA_ANTIBANDING_50HZ }, // Monaco
322 { 213, CAMERA_ANTIBANDING_50HZ }, // Andorra
323 { 214, CAMERA_ANTIBANDING_50HZ }, // Spain
324 { 216, CAMERA_ANTIBANDING_50HZ }, // Hungary
325 { 219, CAMERA_ANTIBANDING_50HZ }, // Croatia
326 { 220, CAMERA_ANTIBANDING_50HZ }, // Serbia
327 { 222, CAMERA_ANTIBANDING_50HZ }, // Italy
328 { 226, CAMERA_ANTIBANDING_50HZ }, // Romania
329 { 228, CAMERA_ANTIBANDING_50HZ }, // Switzerland
330 { 230, CAMERA_ANTIBANDING_50HZ }, // Czech Republic
331 { 231, CAMERA_ANTIBANDING_50HZ }, // Slovakia
332 { 232, CAMERA_ANTIBANDING_50HZ }, // Austria
333 { 234, CAMERA_ANTIBANDING_50HZ }, // United Kingdom
334 { 235, CAMERA_ANTIBANDING_50HZ }, // United Kingdom
335 { 238, CAMERA_ANTIBANDING_50HZ }, // Denmark
336 { 240, CAMERA_ANTIBANDING_50HZ }, // Sweden
337 { 242, CAMERA_ANTIBANDING_50HZ }, // Norway
338 { 244, CAMERA_ANTIBANDING_50HZ }, // Finland
339 { 246, CAMERA_ANTIBANDING_50HZ }, // Lithuania
340 { 247, CAMERA_ANTIBANDING_50HZ }, // Latvia
341 { 248, CAMERA_ANTIBANDING_50HZ }, // Estonia
342 { 250, CAMERA_ANTIBANDING_50HZ }, // Russian Federation
343 { 255, CAMERA_ANTIBANDING_50HZ }, // Ukraine
344 { 257, CAMERA_ANTIBANDING_50HZ }, // Belarus
345 { 259, CAMERA_ANTIBANDING_50HZ }, // Moldova
346 { 260, CAMERA_ANTIBANDING_50HZ }, // Poland
347 { 262, CAMERA_ANTIBANDING_50HZ }, // Germany
348 { 266, CAMERA_ANTIBANDING_50HZ }, // Gibraltar
349 { 268, CAMERA_ANTIBANDING_50HZ }, // Portugal
350 { 270, CAMERA_ANTIBANDING_50HZ }, // Luxembourg
351 { 272, CAMERA_ANTIBANDING_50HZ }, // Ireland
352 { 274, CAMERA_ANTIBANDING_50HZ }, // Iceland
353 { 276, CAMERA_ANTIBANDING_50HZ }, // Albania
354 { 278, CAMERA_ANTIBANDING_50HZ }, // Malta
355 { 280, CAMERA_ANTIBANDING_50HZ }, // Cyprus
356 { 282, CAMERA_ANTIBANDING_50HZ }, // Georgia
357 { 283, CAMERA_ANTIBANDING_50HZ }, // Armenia
358 { 284, CAMERA_ANTIBANDING_50HZ }, // Bulgaria
359 { 286, CAMERA_ANTIBANDING_50HZ }, // Turkey
360 { 288, CAMERA_ANTIBANDING_50HZ }, // Faroe Islands
361 { 290, CAMERA_ANTIBANDING_50HZ }, // Greenland
362 { 293, CAMERA_ANTIBANDING_50HZ }, // Slovenia
363 { 294, CAMERA_ANTIBANDING_50HZ }, // Macedonia
364 { 295, CAMERA_ANTIBANDING_50HZ }, // Liechtenstein
365 { 297, CAMERA_ANTIBANDING_50HZ }, // Montenegro
366 { 302, CAMERA_ANTIBANDING_60HZ }, // Canada
367 { 310, CAMERA_ANTIBANDING_60HZ }, // United States of America
368 { 311, CAMERA_ANTIBANDING_60HZ }, // United States of America
369 { 312, CAMERA_ANTIBANDING_60HZ }, // United States of America
370 { 313, CAMERA_ANTIBANDING_60HZ }, // United States of America
371 { 314, CAMERA_ANTIBANDING_60HZ }, // United States of America
372 { 315, CAMERA_ANTIBANDING_60HZ }, // United States of America
373 { 316, CAMERA_ANTIBANDING_60HZ }, // United States of America
374 { 330, CAMERA_ANTIBANDING_60HZ }, // Puerto Rico
375 { 334, CAMERA_ANTIBANDING_60HZ }, // Mexico
376 { 338, CAMERA_ANTIBANDING_50HZ }, // Jamaica
377 { 340, CAMERA_ANTIBANDING_50HZ }, // Martinique
378 { 342, CAMERA_ANTIBANDING_50HZ }, // Barbados
379 { 346, CAMERA_ANTIBANDING_60HZ }, // Cayman Islands
380 { 350, CAMERA_ANTIBANDING_60HZ }, // Bermuda
381 { 352, CAMERA_ANTIBANDING_50HZ }, // Grenada
382 { 354, CAMERA_ANTIBANDING_60HZ }, // Montserrat
383 { 362, CAMERA_ANTIBANDING_50HZ }, // Netherlands Antilles
384 { 363, CAMERA_ANTIBANDING_60HZ }, // Aruba
385 { 364, CAMERA_ANTIBANDING_60HZ }, // Bahamas
386 { 365, CAMERA_ANTIBANDING_60HZ }, // Anguilla
387 { 366, CAMERA_ANTIBANDING_50HZ }, // Dominica
388 { 368, CAMERA_ANTIBANDING_60HZ }, // Cuba
389 { 370, CAMERA_ANTIBANDING_60HZ }, // Dominican Republic
390 { 372, CAMERA_ANTIBANDING_60HZ }, // Haiti
391 { 401, CAMERA_ANTIBANDING_50HZ }, // Kazakhstan
392 { 402, CAMERA_ANTIBANDING_50HZ }, // Bhutan
393 { 404, CAMERA_ANTIBANDING_50HZ }, // India
394 { 405, CAMERA_ANTIBANDING_50HZ }, // India
395 { 410, CAMERA_ANTIBANDING_50HZ }, // Pakistan
396 { 413, CAMERA_ANTIBANDING_50HZ }, // Sri Lanka
397 { 414, CAMERA_ANTIBANDING_50HZ }, // Myanmar
398 { 415, CAMERA_ANTIBANDING_50HZ }, // Lebanon
399 { 416, CAMERA_ANTIBANDING_50HZ }, // Jordan
400 { 417, CAMERA_ANTIBANDING_50HZ }, // Syria
401 { 418, CAMERA_ANTIBANDING_50HZ }, // Iraq
402 { 419, CAMERA_ANTIBANDING_50HZ }, // Kuwait
403 { 420, CAMERA_ANTIBANDING_60HZ }, // Saudi Arabia
404 { 421, CAMERA_ANTIBANDING_50HZ }, // Yemen
405 { 422, CAMERA_ANTIBANDING_50HZ }, // Oman
406 { 424, CAMERA_ANTIBANDING_50HZ }, // United Arab Emirates
407 { 425, CAMERA_ANTIBANDING_50HZ }, // Israel
408 { 426, CAMERA_ANTIBANDING_50HZ }, // Bahrain
409 { 427, CAMERA_ANTIBANDING_50HZ }, // Qatar
410 { 428, CAMERA_ANTIBANDING_50HZ }, // Mongolia
411 { 429, CAMERA_ANTIBANDING_50HZ }, // Nepal
412 { 430, CAMERA_ANTIBANDING_50HZ }, // United Arab Emirates
413 { 431, CAMERA_ANTIBANDING_50HZ }, // United Arab Emirates
414 { 432, CAMERA_ANTIBANDING_50HZ }, // Iran
415 { 434, CAMERA_ANTIBANDING_50HZ }, // Uzbekistan
416 { 436, CAMERA_ANTIBANDING_50HZ }, // Tajikistan
417 { 437, CAMERA_ANTIBANDING_50HZ }, // Kyrgyz Rep
418 { 438, CAMERA_ANTIBANDING_50HZ }, // Turkmenistan
419 { 440, CAMERA_ANTIBANDING_60HZ }, // Japan
420 { 441, CAMERA_ANTIBANDING_60HZ }, // Japan
421 { 452, CAMERA_ANTIBANDING_50HZ }, // Vietnam
422 { 454, CAMERA_ANTIBANDING_50HZ }, // Hong Kong
423 { 455, CAMERA_ANTIBANDING_50HZ }, // Macao
424 { 456, CAMERA_ANTIBANDING_50HZ }, // Cambodia
425 { 457, CAMERA_ANTIBANDING_50HZ }, // Laos
426 { 460, CAMERA_ANTIBANDING_50HZ }, // China
427 { 466, CAMERA_ANTIBANDING_60HZ }, // Taiwan
428 { 470, CAMERA_ANTIBANDING_50HZ }, // Bangladesh
429 { 472, CAMERA_ANTIBANDING_50HZ }, // Maldives
430 { 502, CAMERA_ANTIBANDING_50HZ }, // Malaysia
431 { 505, CAMERA_ANTIBANDING_50HZ }, // Australia
432 { 510, CAMERA_ANTIBANDING_50HZ }, // Indonesia
433 { 514, CAMERA_ANTIBANDING_50HZ }, // East Timor
434 { 515, CAMERA_ANTIBANDING_60HZ }, // Philippines
435 { 520, CAMERA_ANTIBANDING_50HZ }, // Thailand
436 { 525, CAMERA_ANTIBANDING_50HZ }, // Singapore
437 { 530, CAMERA_ANTIBANDING_50HZ }, // New Zealand
438 { 535, CAMERA_ANTIBANDING_60HZ }, // Guam
439 { 536, CAMERA_ANTIBANDING_50HZ }, // Nauru
440 { 537, CAMERA_ANTIBANDING_50HZ }, // Papua New Guinea
441 { 539, CAMERA_ANTIBANDING_50HZ }, // Tonga
442 { 541, CAMERA_ANTIBANDING_50HZ }, // Vanuatu
443 { 542, CAMERA_ANTIBANDING_50HZ }, // Fiji
444 { 544, CAMERA_ANTIBANDING_60HZ }, // American Samoa
445 { 545, CAMERA_ANTIBANDING_50HZ }, // Kiribati
446 { 546, CAMERA_ANTIBANDING_50HZ }, // New Caledonia
447 { 548, CAMERA_ANTIBANDING_50HZ }, // Cook Islands
448 { 602, CAMERA_ANTIBANDING_50HZ }, // Egypt
449 { 603, CAMERA_ANTIBANDING_50HZ }, // Algeria
450 { 604, CAMERA_ANTIBANDING_50HZ }, // Morocco
451 { 605, CAMERA_ANTIBANDING_50HZ }, // Tunisia
452 { 606, CAMERA_ANTIBANDING_50HZ }, // Libya
453 { 607, CAMERA_ANTIBANDING_50HZ }, // Gambia
454 { 608, CAMERA_ANTIBANDING_50HZ }, // Senegal
455 { 609, CAMERA_ANTIBANDING_50HZ }, // Mauritania
456 { 610, CAMERA_ANTIBANDING_50HZ }, // Mali
457 { 611, CAMERA_ANTIBANDING_50HZ }, // Guinea
458 { 613, CAMERA_ANTIBANDING_50HZ }, // Burkina Faso
459 { 614, CAMERA_ANTIBANDING_50HZ }, // Niger
460 { 616, CAMERA_ANTIBANDING_50HZ }, // Benin
461 { 617, CAMERA_ANTIBANDING_50HZ }, // Mauritius
462 { 618, CAMERA_ANTIBANDING_50HZ }, // Liberia
463 { 619, CAMERA_ANTIBANDING_50HZ }, // Sierra Leone
464 { 620, CAMERA_ANTIBANDING_50HZ }, // Ghana
465 { 621, CAMERA_ANTIBANDING_50HZ }, // Nigeria
466 { 622, CAMERA_ANTIBANDING_50HZ }, // Chad
467 { 623, CAMERA_ANTIBANDING_50HZ }, // Central African Republic
468 { 624, CAMERA_ANTIBANDING_50HZ }, // Cameroon
469 { 625, CAMERA_ANTIBANDING_50HZ }, // Cape Verde
470 { 627, CAMERA_ANTIBANDING_50HZ }, // Equatorial Guinea
471 { 631, CAMERA_ANTIBANDING_50HZ }, // Angola
472 { 633, CAMERA_ANTIBANDING_50HZ }, // Seychelles
473 { 634, CAMERA_ANTIBANDING_50HZ }, // Sudan
474 { 636, CAMERA_ANTIBANDING_50HZ }, // Ethiopia
475 { 637, CAMERA_ANTIBANDING_50HZ }, // Somalia
476 { 638, CAMERA_ANTIBANDING_50HZ }, // Djibouti
477 { 639, CAMERA_ANTIBANDING_50HZ }, // Kenya
478 { 640, CAMERA_ANTIBANDING_50HZ }, // Tanzania
479 { 641, CAMERA_ANTIBANDING_50HZ }, // Uganda
480 { 642, CAMERA_ANTIBANDING_50HZ }, // Burundi
481 { 643, CAMERA_ANTIBANDING_50HZ }, // Mozambique
482 { 645, CAMERA_ANTIBANDING_50HZ }, // Zambia
483 { 646, CAMERA_ANTIBANDING_50HZ }, // Madagascar
484 { 647, CAMERA_ANTIBANDING_50HZ }, // France
485 { 648, CAMERA_ANTIBANDING_50HZ }, // Zimbabwe
486 { 649, CAMERA_ANTIBANDING_50HZ }, // Namibia
487 { 650, CAMERA_ANTIBANDING_50HZ }, // Malawi
488 { 651, CAMERA_ANTIBANDING_50HZ }, // Lesotho
489 { 652, CAMERA_ANTIBANDING_50HZ }, // Botswana
490 { 653, CAMERA_ANTIBANDING_50HZ }, // Swaziland
491 { 654, CAMERA_ANTIBANDING_50HZ }, // Comoros
492 { 655, CAMERA_ANTIBANDING_50HZ }, // South Africa
493 { 657, CAMERA_ANTIBANDING_50HZ }, // Eritrea
494 { 702, CAMERA_ANTIBANDING_60HZ }, // Belize
495 { 704, CAMERA_ANTIBANDING_60HZ }, // Guatemala
496 { 706, CAMERA_ANTIBANDING_60HZ }, // El Salvador
497 { 708, CAMERA_ANTIBANDING_60HZ }, // Honduras
498 { 710, CAMERA_ANTIBANDING_60HZ }, // Nicaragua
499 { 712, CAMERA_ANTIBANDING_60HZ }, // Costa Rica
500 { 714, CAMERA_ANTIBANDING_60HZ }, // Panama
501 { 722, CAMERA_ANTIBANDING_50HZ }, // Argentina
502 { 724, CAMERA_ANTIBANDING_60HZ }, // Brazil
503 { 730, CAMERA_ANTIBANDING_50HZ }, // Chile
504 { 732, CAMERA_ANTIBANDING_60HZ }, // Colombia
505 { 734, CAMERA_ANTIBANDING_60HZ }, // Venezuela
506 { 736, CAMERA_ANTIBANDING_50HZ }, // Bolivia
507 { 738, CAMERA_ANTIBANDING_60HZ }, // Guyana
508 { 740, CAMERA_ANTIBANDING_60HZ }, // Ecuador
509 { 742, CAMERA_ANTIBANDING_50HZ }, // French Guiana
510 { 744, CAMERA_ANTIBANDING_50HZ }, // Paraguay
511 { 746, CAMERA_ANTIBANDING_60HZ }, // Suriname
512 { 748, CAMERA_ANTIBANDING_50HZ }, // Uruguay
513 { 750, CAMERA_ANTIBANDING_50HZ }, // Falkland Islands
514};
515
516#define country_number (sizeof(country_numeric) / sizeof(country_map))
517
518/* Look up pre-sorted antibanding_type table by current MCC. */
519static camera_antibanding_type camera_get_location(void) {
520 char value[PROP_VALUE_MAX];
521 char country_value[PROP_VALUE_MAX];
522 uint32_t country_code, count;
523 memset(value, 0x00, sizeof(value));
524 memset(country_value, 0x00, sizeof(country_value));
525 if (!__system_property_get("gsm.operator.numeric", value)) {
526 return CAMERA_ANTIBANDING_60HZ;
527 }
528 memcpy(country_value, value, 3);
529 country_code = atoi(country_value);
530 LOGD("value:%s, country value:%s, country code:%d\n",
531 value, country_value, country_code);
532 int left = 0;
533 int right = country_number - 1;
534 while (left <= right) {
535 int index = (left + right) >> 1;
536 if (country_numeric[index].country_code == country_code)
537 return country_numeric[index].type;
538 else if (country_numeric[index].country_code > country_code)
539 right = index - 1;
540 else
541 left = index + 1;
542 }
543 return CAMERA_ANTIBANDING_60HZ;
544}
545
546// from camera.h, led_mode_t
547static const str_map flash[] = {
548 { CameraParameters::FLASH_MODE_OFF, LED_MODE_OFF },
549 { CameraParameters::FLASH_MODE_AUTO, LED_MODE_AUTO },
550 { CameraParameters::FLASH_MODE_ON, LED_MODE_ON }
551};
552
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530553// from mm-camera/common/camera.h.
554static const str_map iso[] = {
555 { CameraParameters::ISO_AUTO, CAMERA_ISO_AUTO},
556 { CameraParameters::ISO_HJR, CAMERA_ISO_DEBLUR},
557 { CameraParameters::ISO_100, CAMERA_ISO_100},
558 { CameraParameters::ISO_200, CAMERA_ISO_200},
559 { CameraParameters::ISO_400, CAMERA_ISO_400},
560 { CameraParameters::ISO_800, CAMERA_ISO_800 }
561};
562
563
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800564#define DONT_CARE 0
565static const str_map focus_modes[] = {
Srinivasan Kannan71229622009-12-04 12:05:58 -0800566 { CameraParameters::FOCUS_MODE_AUTO, AF_MODE_AUTO},
567 { CameraParameters::FOCUS_MODE_INFINITY, DONT_CARE },
568 { CameraParameters::FOCUS_MODE_NORMAL, AF_MODE_NORMAL },
569 { CameraParameters::FOCUS_MODE_MACRO, AF_MODE_MACRO }
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800570};
571
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530572static const str_map lensshade[] = {
573 { CameraParameters::LENSSHADE_ENABLE, TRUE },
574 { CameraParameters::LENSSHADE_DISABLE, FALSE }
575};
576
Srinivasan Kannan71229622009-12-04 12:05:58 -0800577struct SensorType {
578 const char *name;
579 int rawPictureWidth;
580 int rawPictureHeight;
581 bool hasAutoFocusSupport;
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800582 int max_supported_snapshot_width;
583 int max_supported_snapshot_height;
Srinivasan Kannan71229622009-12-04 12:05:58 -0800584};
585
586static SensorType sensorTypes[] = {
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800587 { "5mp", 2608, 1960, true, 2592, 1944 },
588 { "3mp", 2064, 1544, false, 2048, 1536 },
589 { "2mp", 3200, 1200, false, 1600, 1200 } };
590
Srinivasan Kannan71229622009-12-04 12:05:58 -0800591
592static SensorType * sensorType;
593
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800594static const str_map picture_formats[] = {
595 {CameraParameters::PIXEL_FORMAT_JPEG, PICTURE_FORMAT_JPEG},
596 {CameraParameters::PIXEL_FORMAT_RAW, PICTURE_FORMAT_RAW}
597};
598
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800599static bool parameter_string_initialized = false;
600static String8 preview_size_values;
601static String8 picture_size_values;
602static String8 antibanding_values;
603static String8 effect_values;
Apurva Rajguru55562b02009-12-03 12:25:35 -0800604static String8 autoexposure_values;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800605static String8 whitebalance_values;
606static String8 flash_values;
607static String8 focus_mode_values;
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530608static String8 iso_values;
609static String8 lensshade_values;
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800610static String8 picture_format_values;
611
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800612
613static String8 create_sizes_str(const camera_size_type *sizes, int len) {
614 String8 str;
615 char buffer[32];
616
617 if (len > 0) {
618 sprintf(buffer, "%dx%d", sizes[0].width, sizes[0].height);
619 str.append(buffer);
620 }
621 for (int i = 1; i < len; i++) {
622 sprintf(buffer, ",%dx%d", sizes[i].width, sizes[i].height);
623 str.append(buffer);
624 }
625 return str;
626}
627
628static String8 create_values_str(const str_map *values, int len) {
629 String8 str;
630
631 if (len > 0) {
632 str.append(values[0].desc);
633 }
634 for (int i = 1; i < len; i++) {
635 str.append(",");
636 str.append(values[i].desc);
637 }
638 return str;
639}
640
Sravankb4f5f1c2010-01-21 11:06:17 +0530641extern "C" {
642//------------------------------------------------------------------------
643// : 720p busyQ funcitons
644// --------------------------------------------------------------------
645static struct fifo_queue g_busy_frame_queue =
646 {0, 0, 0, PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER};
647};
648/*===========================================================================
649 * FUNCTION cam_frame_wait_video
650 *
651 * DESCRIPTION this function waits a video in the busy queue
652 * ===========================================================================*/
653
654static void cam_frame_wait_video (void)
655{
656 LOGV("cam_frame_wait_video E ");
657 if ((g_busy_frame_queue.num_of_frames) <=0){
658 pthread_cond_wait(&(g_busy_frame_queue.wait), &(g_busy_frame_queue.mut));
659 }
660 LOGV("cam_frame_wait_video X");
661 return;
662}
663
664/*===========================================================================
665 * FUNCTION cam_frame_flush_video
666 *
667 * DESCRIPTION this function deletes all the buffers in busy queue
668 * ===========================================================================*/
669void cam_frame_flush_video (void)
670{
671 LOGV("cam_frame_flush_video: in n = %d\n", g_busy_frame_queue.num_of_frames);
672 pthread_mutex_lock(&(g_busy_frame_queue.mut));
673
674 while (g_busy_frame_queue.front)
675 {
676 //dequeue from the busy queue
677 struct fifo_node *node = dequeue (&g_busy_frame_queue);
678 if(node)
679 free(node);
680
681 LOGV("cam_frame_flush_video: node \n");
682 }
683 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
684 LOGV("cam_frame_flush_video: out n = %d\n", g_busy_frame_queue.num_of_frames);
685 return ;
686}
687/*===========================================================================
688 * FUNCTION cam_frame_get_video
689 *
690 * DESCRIPTION this function returns a video frame from the head
691 * ===========================================================================*/
692static struct msm_frame * cam_frame_get_video()
693{
694 struct msm_frame *p = NULL;
695 LOGV("cam_frame_get_video... in\n");
696 LOGV("cam_frame_get_video... got lock\n");
697 if (g_busy_frame_queue.front)
698 {
699 //dequeue
700 struct fifo_node *node = dequeue (&g_busy_frame_queue);
701 if (node)
702 {
703 p = (struct msm_frame *)node->f;
704 free (node);
705 }
706 LOGV("cam_frame_get_video... out = %x\n", p->buffer);
707 }
708 return p;
709}
710
711/*===========================================================================
712 * FUNCTION cam_frame_post_video
713 *
714 * DESCRIPTION this function add a busy video frame to the busy queue tails
715 * ===========================================================================*/
716static void cam_frame_post_video (struct msm_frame *p)
717{
718 if (!p)
719 {
720 LOGE("post video , buffer is null");
721 return;
722 }
723 LOGV("cam_frame_post_video... in = %x\n", (unsigned int)(p->buffer));
724 pthread_mutex_lock(&(g_busy_frame_queue.mut));
725 LOGV("post_video got lock. q count before enQ %d", g_busy_frame_queue.num_of_frames);
726 //enqueue to busy queue
727 struct fifo_node *node = (struct fifo_node *)malloc (sizeof (struct fifo_node));
728 if (node)
729 {
730 LOGV(" post video , enqueing in busy queue");
731 node->f = p;
732 node->next = NULL;
733 enqueue (&g_busy_frame_queue, node);
734 LOGV("post_video got lock. q count after enQ %d", g_busy_frame_queue.num_of_frames);
735 }
736 else
737 {
738 LOGE("cam_frame_post_video error... out of memory\n");
739 }
740
741 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
742 pthread_cond_signal(&(g_busy_frame_queue.wait));
743
744 LOGV("cam_frame_post_video... out = %x\n", p->buffer);
745
746 return;
747}
748
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -0800749void QualcommCameraHardware::storeTargetType(void) {
750 char mDeviceName[PROPERTY_VALUE_MAX];
751 property_get("ro.product.device",mDeviceName," ");
752 mCurrentTarget = TARGET_MAX;
753 for( int i = 0; i < TARGET_MAX ; i++) {
754 if( !strncmp(mDeviceName, targetList[i].targetStr, 7)) {
755 mCurrentTarget = targetList[i].targetEnum;
756 break;
757 }
758 }
759 LOGV(" Storing the current target type as %d ", mCurrentTarget );
760 return;
761}
762
Sravankb4f5f1c2010-01-21 11:06:17 +0530763//-------------------------------------------------------------------------------------
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800764static Mutex singleton_lock;
765static bool singleton_releasing;
766static Condition singleton_wait;
767
768static void receive_camframe_callback(struct msm_frame *frame);
Sravankb4f5f1c2010-01-21 11:06:17 +0530769static void receive_camframe_video_callback(struct msm_frame *frame); // 720p
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800770static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size);
771static void receive_jpeg_callback(jpeg_event_t status);
772static void receive_shutter_callback(common_crop_t *crop);
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800773static void receive_camframetimeout_callback(void);
Mohan Kandra284966d2010-01-05 13:39:15 -0800774static int fb_fd = -1;
775static int32_t mMaxZoom = 0;
776static bool native_get_maxzoom(int camfd, void *pZm);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800777
Mohan Kandrad9efed92010-01-15 19:08:39 -0800778static int dstOffset = 0;
779
Brian Steuer07704892009-12-18 18:07:33 -0800780static int camerafd;
781pthread_t w_thread;
782
783void *opencamerafd(void *data) {
784 camerafd = open(MSM_CAMERA_CONTROL, O_RDWR);
785 return NULL;
786}
787
Mohan Kandrad9efed92010-01-15 19:08:39 -0800788/* When using MDP zoom, double the preview buffers. The usage of these
789 * buffers is as follows:
790 * 1. As all the buffers comes under a single FD, and at initial registration,
791 * this FD will be passed to surface flinger, surface flinger can have access
792 * to all the buffers when needed.
793 * 2. Only "kPreviewBufferCount" buffers (SrcSet) will be registered with the
794 * camera driver to receive preview frames. The remaining buffers (DstSet),
795 * will be used at HAL and by surface flinger only when crop information
796 * is present in the frame.
797 * 3. When there is no crop information, there will be no call to MDP zoom,
798 * and the buffers in SrcSet will be passed to surface flinger to display.
799 * 4. With crop information present, MDP zoom will be called, and the final
800 * data will be placed in a buffer from DstSet, and this buffer will be given
801 * to surface flinger to display.
802 */
803#define NUM_MORE_BUFS 2
804
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800805QualcommCameraHardware::QualcommCameraHardware()
806 : mParameters(),
807 mCameraRunning(false),
808 mPreviewInitialized(false),
809 mFrameThreadRunning(false),
Mohan Kandra156d0ac2010-01-25 16:59:17 -0800810 mVideoThreadRunning(false),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800811 mSnapshotThreadRunning(false),
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800812 mSnapshotFormat(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800813 mReleasedRecordingFrame(false),
814 mPreviewFrameSize(0),
815 mRawSize(0),
816 mCameraControlFd(-1),
817 mAutoFocusThreadRunning(false),
818 mAutoFocusFd(-1),
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800819 mBrightness(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800820 mInPreviewCallback(false),
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800821 mUseOverlay(0),
822 mOverlay(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800823 mMsgEnabled(0),
824 mNotifyCallback(0),
825 mDataCallback(0),
826 mDataCallbackTimestamp(0),
Mohan Kandra740cfce2010-01-07 12:58:24 -0800827 mCallbackCookie(0),
828 mDebugFps(0)
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800829{
Brian Steuer07704892009-12-18 18:07:33 -0800830
831 // Start opening camera device in a separate thread/ Since this
832 // initializes the sensor hardware, this can take a long time. So,
833 // start the process here so it will be ready by the time it's
834 // needed.
835 if ((pthread_create(&w_thread, NULL, opencamerafd, NULL)) != 0) {
836 LOGE("Camera open thread creation failed");
837 }
838
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800839 memset(&mDimension, 0, sizeof(mDimension));
840 memset(&mCrop, 0, sizeof(mCrop));
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -0800841 memset(&zoomCropInfo, 0, sizeof(zoom_crop_info));
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -0800842 storeTargetType();
Mohan Kandra740cfce2010-01-07 12:58:24 -0800843 char value[PROPERTY_VALUE_MAX];
844 property_get("persist.debug.sf.showfps", value, "0");
845 mDebugFps = atoi(value);
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -0800846 if( mCurrentTarget == TARGET_MSM7630 )
Sravankb4f5f1c2010-01-21 11:06:17 +0530847 kPreviewBufferCountActual = kPreviewBufferCount;
848 else
849 kPreviewBufferCountActual = kPreviewBufferCount + NUM_MORE_BUFS;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800850 LOGV("constructor EX");
851}
852
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800853
854//filter Picture sizes based on max width and height
855void QualcommCameraHardware::filterPictureSizes(){
856 int i;
857 for(i=0;i<PICTURE_SIZE_COUNT;i++){
858 if(((picture_sizes[i].width <=
859 sensorType->max_supported_snapshot_width) &&
860 (picture_sizes[i].height <=
861 sensorType->max_supported_snapshot_height))){
862 picture_sizes_ptr = picture_sizes + i;
863 supportedPictureSizesCount = PICTURE_SIZE_COUNT - i ;
864 return ;
865 }
866 }
867}
868
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800869void QualcommCameraHardware::initDefaultParameters()
870{
871 LOGV("initDefaultParameters E");
872
873 // Initialize constant parameter strings. This will happen only once in the
874 // lifetime of the mediaserver process.
875 if (!parameter_string_initialized) {
Srinivasan Kannan71229622009-12-04 12:05:58 -0800876 findSensorType();
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800877 antibanding_values = create_values_str(
878 antibanding, sizeof(antibanding) / sizeof(str_map));
879 effect_values = create_values_str(
880 effects, sizeof(effects) / sizeof(str_map));
Apurva Rajguru55562b02009-12-03 12:25:35 -0800881 autoexposure_values = create_values_str(
882 autoexposure, sizeof(autoexposure) / sizeof(str_map));
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800883 whitebalance_values = create_values_str(
884 whitebalance, sizeof(whitebalance) / sizeof(str_map));
885 preview_size_values = create_sizes_str(
886 preview_sizes, PREVIEW_SIZE_COUNT);
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800887 //filter picture sizes
888 filterPictureSizes();
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800889 picture_size_values = create_sizes_str(
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800890 picture_sizes_ptr, supportedPictureSizesCount);
891
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800892 flash_values = create_values_str(
893 flash, sizeof(flash) / sizeof(str_map));
Srinivasan Kannan71229622009-12-04 12:05:58 -0800894 if(sensorType->hasAutoFocusSupport){
895 focus_mode_values = create_values_str(
896 focus_modes, sizeof(focus_modes) / sizeof(str_map));
897 }
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530898 iso_values = create_values_str(
899 iso,sizeof(iso)/sizeof(str_map));
900 lensshade_values = create_values_str(
901 lensshade,sizeof(lensshade)/sizeof(str_map));
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800902 picture_format_values = create_values_str(
903 picture_formats, sizeof(picture_formats)/sizeof(str_map));
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800904 parameter_string_initialized = true;
905 }
906
907 const camera_size_type *ps = &preview_sizes[DEFAULT_PREVIEW_SETTING];
908 mParameters.setPreviewSize(ps->width, ps->height);
909 mDimension.display_width = ps->width;
910 mDimension.display_height = ps->height;
911 mParameters.setPreviewFrameRate(15);
912 mParameters.setPreviewFormat("yuv420sp"); // informative
913
914 mParameters.setPictureSize(DEFAULT_PICTURE_WIDTH, DEFAULT_PICTURE_HEIGHT);
915 mParameters.setPictureFormat("jpeg"); // informative
916
Mohan Kandra785619a2010-02-01 21:52:42 -0800917 mParameters.set(CameraParameters::KEY_JPEG_QUALITY, "85"); // max quality
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800918 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH,
919 THUMBNAIL_WIDTH_STR); // informative
920 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT,
921 THUMBNAIL_HEIGHT_STR); // informative
Srinivasan Kannan80d878f2009-12-18 15:06:02 -0800922 mDimension.ui_thumbnail_width =
923 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].width;
924 mDimension.ui_thumbnail_height =
925 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800926 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, "90");
927
928 mParameters.set(CameraParameters::KEY_ANTIBANDING,
Mohan Kandra785619a2010-02-01 21:52:42 -0800929 CameraParameters::ANTIBANDING_OFF);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800930 mParameters.set(CameraParameters::KEY_EFFECT,
931 CameraParameters::EFFECT_NONE);
Apurva Rajguru55562b02009-12-03 12:25:35 -0800932 mParameters.set(CameraParameters::KEY_AUTO_EXPOSURE,
933 CameraParameters::AUTO_EXPOSURE_FRAME_AVG);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800934 mParameters.set(CameraParameters::KEY_WHITE_BALANCE,
935 CameraParameters::WHITE_BALANCE_AUTO);
936 mParameters.set(CameraParameters::KEY_FOCUS_MODE,
937 CameraParameters::FOCUS_MODE_AUTO);
Priya Komarlingam044c7b52010-01-22 18:21:23 -0800938 mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS,
939 "yuv420sp");
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800940
941 mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES,
942 preview_size_values.string());
943 mParameters.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES,
944 picture_size_values.string());
945 mParameters.set(CameraParameters::KEY_SUPPORTED_ANTIBANDING,
946 antibanding_values);
947 mParameters.set(CameraParameters::KEY_SUPPORTED_EFFECTS, effect_values);
Apurva Rajguru55562b02009-12-03 12:25:35 -0800948 mParameters.set(CameraParameters::KEY_SUPPORTED_AUTO_EXPOSURE, autoexposure_values);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800949 mParameters.set(CameraParameters::KEY_SUPPORTED_WHITE_BALANCE,
950 whitebalance_values);
951 mParameters.set(CameraParameters::KEY_SUPPORTED_FOCUS_MODES,
952 focus_mode_values);
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800953 mParameters.set(CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS,
954 picture_format_values);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800955
956 if (mSensorInfo.flash_enabled) {
957 mParameters.set(CameraParameters::KEY_FLASH_MODE,
958 CameraParameters::FLASH_MODE_OFF);
959 mParameters.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES,
960 flash_values);
961 }
962
Srinivasan Kannanbddfd502010-01-03 17:27:36 -0800963 mParameters.set(CameraParameters::KEY_MAX_SHARPNESS,
964 CAMERA_MAX_SHARPNESS);
965 mParameters.set(CameraParameters::KEY_MAX_CONTRAST,
966 CAMERA_MAX_CONTRAST);
967 mParameters.set(CameraParameters::KEY_MAX_SATURATION,
968 CAMERA_MAX_SATURATION);
969
Apurva Rajguru07185952010-01-22 15:40:07 -0800970 mParameters.set("luma-adaptation", "3");
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800971 mParameters.set("zoom-supported", "true");
972 mParameters.set("max-zoom", MAX_ZOOM_LEVEL);
973 mParameters.set("zoom", 0);
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800974 mParameters.set(CameraParameters::KEY_PICTURE_FORMAT,
975 CameraParameters::PIXEL_FORMAT_JPEG);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800976
Kiran Kumar H N595970b2010-01-12 10:41:09 -0800977 mParameters.set(CameraParameters::KEY_SHARPNESS,
978 CAMERA_DEF_SHARPNESS);
979 mParameters.set(CameraParameters::KEY_CONTRAST,
980 CAMERA_DEF_CONTRAST);
981 mParameters.set(CameraParameters::KEY_SATURATION,
982 CAMERA_DEF_SATURATION);
983
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530984 mParameters.set(CameraParameters::KEY_ISO_MODE,
985 CameraParameters::ISO_AUTO);
986 mParameters.set(CameraParameters::KEY_LENSSHADE,
987 CameraParameters::LENSSHADE_ENABLE);
988 mParameters.set(CameraParameters::KEY_SUPPORTED_ISO_MODES,
989 iso_values);
990 mParameters.set(CameraParameters::KEY_SUPPORTED_LENSSHADE_MODES,
991 lensshade_values);
992
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800993 if (setParameters(mParameters) != NO_ERROR) {
994 LOGE("Failed to set default parameters?!");
995 }
996
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -0800997 mUseOverlay = useOverlay();
998
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800999 /* Initialize the camframe_timeout_flag*/
1000 Mutex::Autolock l(&mCamframeTimeoutLock);
1001 camframe_timeout_flag = FALSE;
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08001002 mPostViewHeap = NULL;
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001003
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001004 LOGV("initDefaultParameters X");
1005}
1006
Srinivasan Kannan71229622009-12-04 12:05:58 -08001007void QualcommCameraHardware::findSensorType(){
1008 mDimension.picture_width = DEFAULT_PICTURE_WIDTH;
1009 mDimension.picture_height = DEFAULT_PICTURE_HEIGHT;
1010 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
1011 sizeof(cam_ctrl_dimension_t), &mDimension);
1012 if (ret) {
1013 unsigned int i;
1014 for (i = 0; i < sizeof(sensorTypes) / sizeof(SensorType); i++) {
1015 if (sensorTypes[i].rawPictureHeight
1016 == mDimension.raw_picture_height) {
1017 sensorType = sensorTypes + i;
1018 return;
1019 }
1020 }
1021 }
1022 //default to 5 mp
1023 sensorType = sensorTypes;
1024 return;
1025}
1026
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001027#define ROUND_TO_PAGE(x) (((x)+0xfff)&~0xfff)
1028
1029bool QualcommCameraHardware::startCamera()
1030{
1031 LOGV("startCamera E");
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08001032 if( mCurrentTarget == TARGET_MAX ) {
1033 LOGE(" Unable to determine the target type. Camera will not work ");
1034 return false;
1035 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001036#if DLOPEN_LIBMMCAMERA
1037 libmmcamera = ::dlopen("liboemcamera.so", RTLD_NOW);
1038 LOGV("loading liboemcamera at %p", libmmcamera);
1039 if (!libmmcamera) {
1040 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
1041 return false;
1042 }
1043
1044 *(void **)&LINK_cam_frame =
1045 ::dlsym(libmmcamera, "cam_frame");
1046 *(void **)&LINK_camframe_terminate =
1047 ::dlsym(libmmcamera, "camframe_terminate");
1048
1049 *(void **)&LINK_jpeg_encoder_init =
1050 ::dlsym(libmmcamera, "jpeg_encoder_init");
1051
1052 *(void **)&LINK_jpeg_encoder_encode =
1053 ::dlsym(libmmcamera, "jpeg_encoder_encode");
1054
1055 *(void **)&LINK_jpeg_encoder_join =
1056 ::dlsym(libmmcamera, "jpeg_encoder_join");
1057
1058 *(void **)&LINK_mmcamera_camframe_callback =
1059 ::dlsym(libmmcamera, "mmcamera_camframe_callback");
1060
1061 *LINK_mmcamera_camframe_callback = receive_camframe_callback;
1062
1063 *(void **)&LINK_mmcamera_jpegfragment_callback =
1064 ::dlsym(libmmcamera, "mmcamera_jpegfragment_callback");
1065
1066 *LINK_mmcamera_jpegfragment_callback = receive_jpeg_fragment_callback;
1067
1068 *(void **)&LINK_mmcamera_jpeg_callback =
1069 ::dlsym(libmmcamera, "mmcamera_jpeg_callback");
1070
1071 *LINK_mmcamera_jpeg_callback = receive_jpeg_callback;
1072
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001073 *(void **)&LINK_camframe_timeout_callback =
1074 ::dlsym(libmmcamera, "camframe_timeout_callback");
1075
1076 *LINK_camframe_timeout_callback = receive_camframetimeout_callback;
1077
Sravankb4f5f1c2010-01-21 11:06:17 +05301078 // 720 p new recording functions
1079 *(void **)&LINK_cam_frame_flush_free_video = ::dlsym(libmmcamera, "cam_frame_flush_free_video");
1080
1081 *(void **)&LINK_camframe_free_video = ::dlsym(libmmcamera, "cam_frame_add_free_video");
1082
1083 *(void **)&LINK_camframe_video_callback = ::dlsym(libmmcamera, "mmcamera_camframe_videocallback");
1084 *LINK_camframe_video_callback = receive_camframe_video_callback;
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001085/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001086 *(void **)&LINK_mmcamera_shutter_callback =
1087 ::dlsym(libmmcamera, "mmcamera_shutter_callback");
1088
1089 *LINK_mmcamera_shutter_callback = receive_shutter_callback;
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001090*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001091 *(void**)&LINK_jpeg_encoder_setMainImageQuality =
1092 ::dlsym(libmmcamera, "jpeg_encoder_setMainImageQuality");
Kiran Kumar H N8861f302010-01-05 12:01:41 -08001093
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001094 *(void**)&LINK_jpeg_encoder_setThumbnailQuality =
1095 ::dlsym(libmmcamera, "jpeg_encoder_setThumbnailQuality");
1096
1097 *(void**)&LINK_jpeg_encoder_setRotation =
1098 ::dlsym(libmmcamera, "jpeg_encoder_setRotation");
1099
Kiran Kumar H N8861f302010-01-05 12:01:41 -08001100/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001101 *(void**)&LINK_jpeg_encoder_setLocation =
1102 ::dlsym(libmmcamera, "jpeg_encoder_setLocation");
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001103*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001104 *(void **)&LINK_cam_conf =
1105 ::dlsym(libmmcamera, "cam_conf");
1106
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001107/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001108 *(void **)&LINK_default_sensor_get_snapshot_sizes =
1109 ::dlsym(libmmcamera, "default_sensor_get_snapshot_sizes");
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001110*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001111 *(void **)&LINK_launch_cam_conf_thread =
1112 ::dlsym(libmmcamera, "launch_cam_conf_thread");
1113
1114 *(void **)&LINK_release_cam_conf_thread =
1115 ::dlsym(libmmcamera, "release_cam_conf_thread");
1116
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001117/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001118 *(void **)&LINK_zoom_crop_upscale =
1119 ::dlsym(libmmcamera, "zoom_crop_upscale");
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001120*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001121
1122#else
1123 mmcamera_camframe_callback = receive_camframe_callback;
1124 mmcamera_jpegfragment_callback = receive_jpeg_fragment_callback;
1125 mmcamera_jpeg_callback = receive_jpeg_callback;
1126 mmcamera_shutter_callback = receive_shutter_callback;
1127#endif // DLOPEN_LIBMMCAMERA
1128
1129 /* The control thread is in libcamera itself. */
Brian Steuer07704892009-12-18 18:07:33 -08001130 if (pthread_join(w_thread, NULL) != 0) {
1131 LOGE("Camera open thread exit failed");
1132 return false;
1133 }
1134 mCameraControlFd = camerafd;
1135
Kiran Kumar H N585bc362010-01-19 13:04:44 -08001136 if (mCameraControlFd < 0) {
1137 LOGE("startCamera X: %s open failed: %s!",
1138 MSM_CAMERA_CONTROL,
1139 strerror(errno));
1140 return false;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001141 }
1142
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08001143 if( mCurrentTarget != TARGET_MSM7630 ){
Mohan Kandra284966d2010-01-05 13:39:15 -08001144 fb_fd = open("/dev/graphics/fb0", O_RDWR);
1145 if (fb_fd < 0) {
1146 LOGE("startCamera: fb0 open failed: %s!", strerror(errno));
1147 return FALSE;
1148 }
1149 }
1150
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001151 /* This will block until the control thread is launched. After that, sensor
1152 * information becomes available.
1153 */
1154
1155 if (LINK_launch_cam_conf_thread()) {
1156 LOGE("failed to launch the camera config thread");
1157 return false;
1158 }
1159
1160 memset(&mSensorInfo, 0, sizeof(mSensorInfo));
1161 if (ioctl(mCameraControlFd,
1162 MSM_CAM_IOCTL_GET_SENSOR_INFO,
1163 &mSensorInfo) < 0)
1164 LOGW("%s: cannot retrieve sensor info!", __FUNCTION__);
1165 else
1166 LOGI("%s: camsensor name %s, flash %d", __FUNCTION__,
1167 mSensorInfo.name, mSensorInfo.flash_enabled);
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001168/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001169 picture_sizes = LINK_default_sensor_get_snapshot_sizes(&PICTURE_SIZE_COUNT);
1170 if (!picture_sizes || !PICTURE_SIZE_COUNT) {
1171 LOGE("startCamera X: could not get snapshot sizes");
1172 return false;
1173 }
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001174*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001175 LOGV("startCamera X");
1176 return true;
1177}
1178
1179status_t QualcommCameraHardware::dump(int fd,
1180 const Vector<String16>& args) const
1181{
1182 const size_t SIZE = 256;
1183 char buffer[SIZE];
1184 String8 result;
1185
1186 // Dump internal primitives.
1187 result.append("QualcommCameraHardware::dump");
1188 snprintf(buffer, 255, "mMsgEnabled (%d)\n", mMsgEnabled);
1189 result.append(buffer);
1190 int width, height;
1191 mParameters.getPreviewSize(&width, &height);
1192 snprintf(buffer, 255, "preview width(%d) x height (%d)\n", width, height);
1193 result.append(buffer);
1194 mParameters.getPictureSize(&width, &height);
1195 snprintf(buffer, 255, "raw width(%d) x height (%d)\n", width, height);
1196 result.append(buffer);
1197 snprintf(buffer, 255,
1198 "preview frame size(%d), raw size (%d), jpeg size (%d) "
1199 "and jpeg max size (%d)\n", mPreviewFrameSize, mRawSize,
1200 mJpegSize, mJpegMaxSize);
1201 result.append(buffer);
1202 write(fd, result.string(), result.size());
1203
1204 // Dump internal objects.
Mohan Kandrad9efed92010-01-15 19:08:39 -08001205 if (mPreviewHeap != 0) {
1206 mPreviewHeap->dump(fd, args);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001207 }
1208 if (mRawHeap != 0) {
1209 mRawHeap->dump(fd, args);
1210 }
1211 if (mJpegHeap != 0) {
1212 mJpegHeap->dump(fd, args);
1213 }
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001214 if(mRawSnapshotAshmemHeap != 0 ){
1215 mRawSnapshotAshmemHeap->dump(fd, args);
1216 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001217 mParameters.dump(fd, args);
1218 return NO_ERROR;
1219}
1220
Mohan Kandra284966d2010-01-05 13:39:15 -08001221static bool native_get_maxzoom(int camfd, void *pZm)
1222{
1223 LOGV("native_get_maxzoom E");
1224
1225 struct msm_ctrl_cmd ctrlCmd;
1226 int32_t *pZoom = (int32_t *)pZm;
1227
1228 ctrlCmd.type = CAMERA_GET_PARM_MAXZOOM;
1229 ctrlCmd.timeout_ms = 5000;
1230 ctrlCmd.length = sizeof(int32_t);
1231 ctrlCmd.value = pZoom;
1232 ctrlCmd.resp_fd = camfd;
1233
1234 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1235 LOGE("native_get_maxzoom: ioctl fd %d error %s",
1236 camfd,
1237 strerror(errno));
1238 return false;
1239 }
Brian Steuerb62adbd2010-02-02 14:47:08 -08001240 LOGD("ctrlCmd.value = %d", *(int32_t *)ctrlCmd.value);
Mohan Kandra284966d2010-01-05 13:39:15 -08001241 memcpy(pZoom, (int32_t *)ctrlCmd.value, sizeof(int32_t));
1242
1243 LOGV("native_get_maxzoom X");
1244 return true;
1245}
1246
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001247static bool native_set_afmode(int camfd, isp3a_af_mode_t af_type)
1248{
1249 int rc;
1250 struct msm_ctrl_cmd ctrlCmd;
1251
1252 ctrlCmd.timeout_ms = 5000;
1253 ctrlCmd.type = CAMERA_SET_PARM_AUTO_FOCUS;
1254 ctrlCmd.length = sizeof(af_type);
1255 ctrlCmd.value = &af_type;
1256 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1257
1258 if ((rc = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0)
1259 LOGE("native_set_afmode: ioctl fd %d error %s\n",
1260 camfd,
1261 strerror(errno));
1262
1263 LOGV("native_set_afmode: ctrlCmd.status == %d\n", ctrlCmd.status);
1264 return rc >= 0 && ctrlCmd.status == CAMERA_EXIT_CB_DONE;
1265}
1266
1267static bool native_cancel_afmode(int camfd, int af_fd)
1268{
1269 int rc;
1270 struct msm_ctrl_cmd ctrlCmd;
1271
1272 ctrlCmd.timeout_ms = 0;
1273 ctrlCmd.type = CAMERA_AUTO_FOCUS_CANCEL;
1274 ctrlCmd.length = 0;
1275 ctrlCmd.value = NULL;
1276 ctrlCmd.resp_fd = -1; // there's no response fd
1277
1278 if ((rc = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND_2, &ctrlCmd)) < 0)
1279 {
1280 LOGE("native_cancel_afmode: ioctl fd %d error %s\n",
1281 camfd,
1282 strerror(errno));
1283 return false;
1284 }
1285
1286 return true;
1287}
1288
1289static bool native_start_preview(int camfd)
1290{
1291 struct msm_ctrl_cmd ctrlCmd;
1292
1293 ctrlCmd.timeout_ms = 5000;
1294 ctrlCmd.type = CAMERA_START_PREVIEW;
1295 ctrlCmd.length = 0;
1296 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1297
1298 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1299 LOGE("native_start_preview: MSM_CAM_IOCTL_CTRL_COMMAND fd %d error %s",
1300 camfd,
1301 strerror(errno));
1302 return false;
1303 }
1304
1305 return true;
1306}
1307
1308static bool native_get_picture (int camfd, common_crop_t *crop)
1309{
1310 struct msm_ctrl_cmd ctrlCmd;
1311
1312 ctrlCmd.timeout_ms = 5000;
1313 ctrlCmd.length = sizeof(common_crop_t);
1314 ctrlCmd.value = crop;
1315
1316 if(ioctl(camfd, MSM_CAM_IOCTL_GET_PICTURE, &ctrlCmd) < 0) {
1317 LOGE("native_get_picture: MSM_CAM_IOCTL_GET_PICTURE fd %d error %s",
1318 camfd,
1319 strerror(errno));
1320 return false;
1321 }
1322
1323 LOGV("crop: in1_w %d", crop->in1_w);
1324 LOGV("crop: in1_h %d", crop->in1_h);
1325 LOGV("crop: out1_w %d", crop->out1_w);
1326 LOGV("crop: out1_h %d", crop->out1_h);
1327
1328 LOGV("crop: in2_w %d", crop->in2_w);
1329 LOGV("crop: in2_h %d", crop->in2_h);
1330 LOGV("crop: out2_w %d", crop->out2_w);
1331 LOGV("crop: out2_h %d", crop->out2_h);
1332
1333 LOGV("crop: update %d", crop->update_flag);
1334
1335 return true;
1336}
1337
1338static bool native_stop_preview(int camfd)
1339{
1340 struct msm_ctrl_cmd ctrlCmd;
1341 ctrlCmd.timeout_ms = 5000;
1342 ctrlCmd.type = CAMERA_STOP_PREVIEW;
1343 ctrlCmd.length = 0;
1344 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1345
1346 if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1347 LOGE("native_stop_preview: ioctl fd %d error %s",
1348 camfd,
1349 strerror(errno));
1350 return false;
1351 }
1352
1353 return true;
1354}
1355
1356static bool native_prepare_snapshot(int camfd)
1357{
1358 int ioctlRetVal = true;
1359 struct msm_ctrl_cmd ctrlCmd;
1360
1361 ctrlCmd.timeout_ms = 1000;
1362 ctrlCmd.type = CAMERA_PREPARE_SNAPSHOT;
1363 ctrlCmd.length = 0;
1364 ctrlCmd.value = NULL;
1365 ctrlCmd.resp_fd = camfd;
1366
1367 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1368 LOGE("native_prepare_snapshot: ioctl fd %d error %s",
1369 camfd,
1370 strerror(errno));
1371 return false;
1372 }
1373 return true;
1374}
1375
1376static bool native_start_snapshot(int camfd)
1377{
1378 struct msm_ctrl_cmd ctrlCmd;
1379
1380 ctrlCmd.timeout_ms = 5000;
1381 ctrlCmd.type = CAMERA_START_SNAPSHOT;
1382 ctrlCmd.length = 0;
1383 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1384
1385 if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1386 LOGE("native_start_snapshot: ioctl fd %d error %s",
1387 camfd,
1388 strerror(errno));
1389 return false;
1390 }
1391
1392 return true;
1393}
1394
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001395static bool native_start_raw_snapshot(int camfd)
1396{
1397 int ret;
1398 struct msm_ctrl_cmd ctrlCmd;
1399
1400 ctrlCmd.timeout_ms = 1000;
1401 ctrlCmd.type = CAMERA_START_RAW_SNAPSHOT;
1402 ctrlCmd.length = 0;
1403 ctrlCmd.value = NULL;
1404 ctrlCmd.resp_fd = camfd;
1405
1406 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1407 LOGE("native_start_raw_snapshot: ioctl failed. ioctl return value "\
1408 "is %d \n", ret);
1409 return false;
1410 }
1411 return true;
1412}
1413
1414
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001415static bool native_stop_snapshot (int camfd)
1416{
1417 struct msm_ctrl_cmd ctrlCmd;
1418
1419 ctrlCmd.timeout_ms = 0;
1420 ctrlCmd.type = CAMERA_STOP_SNAPSHOT;
1421 ctrlCmd.length = 0;
1422 ctrlCmd.resp_fd = -1;
1423
1424 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND_2, &ctrlCmd) < 0) {
1425 LOGE("native_stop_snapshot: ioctl fd %d error %s",
1426 camfd,
1427 strerror(errno));
1428 return false;
1429 }
1430
1431 return true;
1432}
Sravankb4f5f1c2010-01-21 11:06:17 +05301433/*===========================================================================
1434 * FUNCTION - native_start_recording -
1435 *
1436 * DESCRIPTION:
1437 *==========================================================================*/
1438static bool native_start_recording(int camfd)
1439{
1440 int ret;
1441 struct msm_ctrl_cmd ctrlCmd;
1442
1443 ctrlCmd.timeout_ms = 1000;
1444 ctrlCmd.type = CAMERA_START_RECORDING;
1445 ctrlCmd.length = 0;
1446 ctrlCmd.value = NULL;
1447 ctrlCmd.resp_fd = camfd;
1448
1449 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1450 LOGE("native_start_recording: ioctl failed. ioctl return value "\
1451 "is %d \n", ret);
1452 return false;
1453 }
Mohan Kandraf1ebf982010-02-02 15:25:43 -08001454 LOGV("native_start_recording: ioctl good. ioctl return value is %d \n",ret);
Sravankb4f5f1c2010-01-21 11:06:17 +05301455
1456 /* TODO: Check status of postprocessing if there is any,
1457 * PP status should be in ctrlCmd */
1458
1459 return true;
1460}
1461
1462/*===========================================================================
1463 * FUNCTION - native_stop_recording -
1464 *
1465 * DESCRIPTION:
1466 *==========================================================================*/
1467static bool native_stop_recording(int camfd)
1468{
1469 int ret;
1470 struct msm_ctrl_cmd ctrlCmd;
1471LOGE("in native_stop_recording ");
1472 ctrlCmd.timeout_ms = 1000;
1473 ctrlCmd.type = CAMERA_STOP_RECORDING;
1474 ctrlCmd.length = 0;
1475 ctrlCmd.value = NULL;
1476 ctrlCmd.resp_fd = camfd;
1477
1478 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1479 LOGE("native_stop_video: ioctl failed. ioctl return value is %d \n",
1480 ret);
1481 return false;
1482 }
1483 LOGV("in native_stop_recording returned %d", ret);
1484 return true;
1485}
1486/*===========================================================================
1487 * FUNCTION - native_start_video -
1488 *
1489 * DESCRIPTION:
1490 *==========================================================================*/
1491static bool native_start_video(int camfd)
1492{
1493 int ret;
1494 struct msm_ctrl_cmd ctrlCmd;
1495
1496 ctrlCmd.timeout_ms = 1000;
1497 ctrlCmd.type = CAMERA_START_VIDEO;
1498 ctrlCmd.length = 0;
1499 ctrlCmd.value = NULL;
1500 ctrlCmd.resp_fd = camfd;
1501
1502 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1503 LOGE("native_start_video: ioctl failed. ioctl return value is %d \n",
1504 ret);
1505 return false;
1506 }
1507
1508 /* TODO: Check status of postprocessing if there is any,
1509 * PP status should be in ctrlCmd */
1510
1511 return true;
1512}
1513
1514/*===========================================================================
1515 * FUNCTION - native_stop_video -
1516 *
1517 * DESCRIPTION:
1518 *==========================================================================*/
1519static bool native_stop_video(int camfd)
1520{
1521 int ret;
1522 struct msm_ctrl_cmd ctrlCmd;
1523
1524 ctrlCmd.timeout_ms = 1000;
1525 ctrlCmd.type = CAMERA_STOP_VIDEO;
1526 ctrlCmd.length = 0;
1527 ctrlCmd.value = NULL;
1528 ctrlCmd.resp_fd = camfd;
1529
1530 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1531 LOGE("native_stop_video: ioctl failed. ioctl return value is %d \n",
1532 ret);
1533 return false;
1534 }
1535
1536 return true;
1537}
1538/*==========================================================================*/
1539
1540static cam_frame_start_parms frame_parms;
1541static int recordingState = 0;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001542
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001543static rat_t latitude[3];
1544static rat_t longitude[3];
1545static char lonref[2];
1546static char latref[2];
1547static char dateTime[20];
1548static rat_t altitude;
1549
1550static void addExifTag(exif_tag_id_t tagid, exif_tag_type_t type,
1551 uint32_t count, uint8_t copy, void *data) {
1552
1553 if(exif_table_numEntries == MAX_EXIF_TABLE_ENTRIES) {
1554 LOGE("Number of entries exceeded limit");
1555 return;
1556 }
1557
1558 int index = exif_table_numEntries;
1559 exif_data[index].tag_id = tagid;
1560 exif_data[index].tag_entry.type = type;
1561 exif_data[index].tag_entry.count = count;
1562 exif_data[index].tag_entry.copy = copy;
1563 if((type == EXIF_RATIONAL) && (count > 1))
1564 exif_data[index].tag_entry.data._rats = (rat_t *)data;
1565 if((type == EXIF_RATIONAL) && (count == 1))
1566 exif_data[index].tag_entry.data._rat = *(rat_t *)data;
1567 else if(type == EXIF_ASCII)
1568 exif_data[index].tag_entry.data._ascii = (char *)data;
1569 else if(type == EXIF_BYTE)
1570 exif_data[index].tag_entry.data._byte = *(uint8_t *)data;
1571
1572 // Increase number of entries
1573 exif_table_numEntries++;
1574}
1575
1576static void parseLatLong(const char *latlonString, int *pDegrees,
1577 int *pMinutes, int *pSeconds ) {
1578
1579 double value = atof(latlonString);
1580 value = fabs(value);
1581 int degrees = (int) value;
1582
1583 double remainder = value - degrees;
1584 int minutes = (int) (remainder * 60);
1585 int seconds = (int) (((remainder * 60) - minutes) * 60 * 1000);
1586
1587 *pDegrees = degrees;
1588 *pMinutes = minutes;
1589 *pSeconds = seconds;
1590}
1591
1592static void setLatLon(exif_tag_id_t tag, const char *latlonString) {
1593
1594 int degrees, minutes, seconds;
1595
1596 parseLatLong(latlonString, &degrees, &minutes, &seconds);
1597
1598 rat_t value[3] = { {degrees, 1},
1599 {minutes, 1},
1600 {seconds, 1000} };
1601
1602 if(tag == EXIFTAGID_GPS_LATITUDE) {
1603 memcpy(latitude, value, sizeof(latitude));
1604 addExifTag(EXIFTAGID_GPS_LATITUDE, EXIF_RATIONAL, 3,
1605 1, (void *)latitude);
1606 } else {
1607 memcpy(longitude, value, sizeof(longitude));
1608 addExifTag(EXIFTAGID_GPS_LONGITUDE, EXIF_RATIONAL, 3,
1609 1, (void *)longitude);
1610 }
1611}
1612
1613void QualcommCameraHardware::setGpsParameters() {
1614 const char *str = NULL;
1615
1616 //Set Latitude
1617 str = mParameters.get(CameraParameters::KEY_GPS_LATITUDE);
1618 if(str != NULL) {
1619 setLatLon(EXIFTAGID_GPS_LATITUDE, str);
1620 //set Latitude Ref
1621 str = NULL;
1622 str = mParameters.get(CameraParameters::KEY_GPS_LATITUDE_REF);
1623 if(str != NULL) {
1624 strncpy(latref, str, 1);
1625 latref[1] = '\0';
1626 addExifTag(EXIFTAGID_GPS_LATITUDE_REF, EXIF_ASCII, 2,
1627 1, (void *)latref);
1628 }
1629 }
1630
1631 //set Longitude
1632 str = NULL;
1633 str = mParameters.get(CameraParameters::KEY_GPS_LONGITUDE);
1634 if(str != NULL) {
1635 setLatLon(EXIFTAGID_GPS_LONGITUDE, str);
1636 //set Longitude Ref
1637 str = NULL;
1638 str = mParameters.get(CameraParameters::KEY_GPS_LONGITUDE_REF);
1639 if(str != NULL) {
1640 strncpy(lonref, str, 1);
1641 lonref[1] = '\0';
1642 addExifTag(EXIFTAGID_GPS_LONGITUDE_REF, EXIF_ASCII, 2,
1643 1, (void *)lonref);
1644 }
1645 }
1646
1647 //set Altitude
1648 str = NULL;
1649 str = mParameters.get(CameraParameters::KEY_GPS_ALTITUDE);
1650 if(str != NULL) {
1651 int value = atoi(str);
1652 rat_t alt_value = {value, 1000};
1653 memcpy(&altitude, &alt_value, sizeof(altitude));
1654 addExifTag(EXIFTAGID_GPS_ALTITUDE, EXIF_RATIONAL, 1,
1655 1, (void *)&altitude);
1656 //set AltitudeRef
1657 int ref = mParameters.getInt(CameraParameters::KEY_GPS_ALTITUDE_REF);
1658 if( !(ref < 0 || ref > 1) )
1659 addExifTag(EXIFTAGID_GPS_ALTITUDE_REF, EXIF_BYTE, 1,
1660 1, (void *)&ref);
1661 }
1662
1663
1664}
1665
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001666bool QualcommCameraHardware::native_jpeg_encode(void)
1667{
1668 int jpeg_quality = mParameters.getInt("jpeg-quality");
1669 if (jpeg_quality >= 0) {
1670 LOGV("native_jpeg_encode, current jpeg main img quality =%d",
1671 jpeg_quality);
1672 if(!LINK_jpeg_encoder_setMainImageQuality(jpeg_quality)) {
1673 LOGE("native_jpeg_encode set jpeg-quality failed");
1674 return false;
1675 }
1676 }
1677
1678 int thumbnail_quality = mParameters.getInt("jpeg-thumbnail-quality");
1679 if (thumbnail_quality >= 0) {
1680 LOGV("native_jpeg_encode, current jpeg thumbnail quality =%d",
1681 thumbnail_quality);
1682 if(!LINK_jpeg_encoder_setThumbnailQuality(thumbnail_quality)) {
1683 LOGE("native_jpeg_encode set thumbnail-quality failed");
1684 return false;
1685 }
1686 }
1687
1688 int rotation = mParameters.getInt("rotation");
1689 if (rotation >= 0) {
1690 LOGV("native_jpeg_encode, rotation = %d", rotation);
1691 if(!LINK_jpeg_encoder_setRotation(rotation)) {
1692 LOGE("native_jpeg_encode set rotation failed");
1693 return false;
1694 }
1695 }
1696
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001697// jpeg_set_location();
1698 if(mParameters.getInt(CameraParameters::KEY_GPS_STATUS) == 1) {
1699 setGpsParameters();
1700 }
1701 //set TimeStamp
1702 const char *str = mParameters.get(CameraParameters::KEY_EXIF_DATETIME);
1703 if(str != NULL) {
1704 strncpy(dateTime, str, 19);
1705 dateTime[19] = '\0';
1706 addExifTag(EXIFTAGID_EXIF_DATE_TIME_ORIGINAL, EXIF_ASCII,
1707 20, 1, (void *)dateTime);
1708 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001709
1710 if (!LINK_jpeg_encoder_encode(&mDimension,
1711 (uint8_t *)mThumbnailHeap->mHeap->base(),
1712 mThumbnailHeap->mHeap->getHeapID(),
1713 (uint8_t *)mRawHeap->mHeap->base(),
1714 mRawHeap->mHeap->getHeapID(),
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001715 &mCrop, exif_data, exif_table_numEntries)) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001716 LOGE("native_jpeg_encode: jpeg_encoder_encode failed.");
1717 return false;
1718 }
1719 return true;
1720}
1721
1722bool QualcommCameraHardware::native_set_parm(
1723 cam_ctrl_type type, uint16_t length, void *value)
1724{
1725 struct msm_ctrl_cmd ctrlCmd;
1726
1727 ctrlCmd.timeout_ms = 5000;
1728 ctrlCmd.type = (uint16_t)type;
1729 ctrlCmd.length = length;
1730 // FIXME: this will be put in by the kernel
1731 ctrlCmd.resp_fd = mCameraControlFd;
1732 ctrlCmd.value = value;
1733
1734 LOGV("%s: fd %d, type %d, length %d", __FUNCTION__,
1735 mCameraControlFd, type, length);
1736 if (ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0 ||
1737 ctrlCmd.status != CAM_CTRL_SUCCESS) {
1738 LOGE("%s: error (%s): fd %d, type %d, length %d, status %d",
1739 __FUNCTION__, strerror(errno),
1740 mCameraControlFd, type, length, ctrlCmd.status);
1741 return false;
1742 }
1743 return true;
1744}
1745
1746void QualcommCameraHardware::jpeg_set_location()
1747{
1748 bool encode_location = true;
1749 camera_position_type pt;
1750
1751#define PARSE_LOCATION(what,type,fmt,desc) do { \
1752 pt.what = 0; \
1753 const char *what##_str = mParameters.get("gps-"#what); \
1754 LOGV("GPS PARM %s --> [%s]", "gps-"#what, what##_str); \
1755 if (what##_str) { \
1756 type what = 0; \
1757 if (sscanf(what##_str, fmt, &what) == 1) \
1758 pt.what = what; \
1759 else { \
1760 LOGE("GPS " #what " %s could not" \
1761 " be parsed as a " #desc, what##_str); \
1762 encode_location = false; \
1763 } \
1764 } \
1765 else { \
1766 LOGV("GPS " #what " not specified: " \
1767 "defaulting to zero in EXIF header."); \
1768 encode_location = false; \
1769 } \
1770 } while(0)
1771
1772 PARSE_LOCATION(timestamp, long, "%ld", "long");
1773 if (!pt.timestamp) pt.timestamp = time(NULL);
1774 PARSE_LOCATION(altitude, short, "%hd", "short");
1775 PARSE_LOCATION(latitude, double, "%lf", "double float");
1776 PARSE_LOCATION(longitude, double, "%lf", "double float");
1777
1778#undef PARSE_LOCATION
1779
1780 if (encode_location) {
1781 LOGD("setting image location ALT %d LAT %lf LON %lf",
1782 pt.altitude, pt.latitude, pt.longitude);
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001783/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001784 if (!LINK_jpeg_encoder_setLocation(&pt)) {
1785 LOGE("jpeg_set_location: LINK_jpeg_encoder_setLocation failed.");
1786 }
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001787*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001788 }
1789 else LOGV("not setting image location");
1790}
1791
1792void QualcommCameraHardware::runFrameThread(void *data)
1793{
1794 LOGV("runFrameThread E");
1795
1796 int cnt;
1797
1798#if DLOPEN_LIBMMCAMERA
1799 // We need to maintain a reference to libqcamera.so for the duration of the
1800 // frame thread, because we do not know when it will exit relative to the
1801 // lifetime of this object. We do not want to dlclose() libqcamera while
1802 // LINK_cam_frame is still running.
1803 void *libhandle = ::dlopen("liboemcamera.so", RTLD_NOW);
1804 LOGV("FRAME: loading libqcamera at %p", libhandle);
1805 if (!libhandle) {
1806 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
1807 }
1808 if (libhandle)
1809#endif
1810 {
1811 LINK_cam_frame(data);
1812 }
1813
Mohan Kandrad9efed92010-01-15 19:08:39 -08001814 mPreviewHeap.clear();
Mohan Kandraf1ebf982010-02-02 15:25:43 -08001815 if(( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250))
Sravankb4f5f1c2010-01-21 11:06:17 +05301816 mRecordHeap.clear();
1817
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001818#if DLOPEN_LIBMMCAMERA
1819 if (libhandle) {
1820 ::dlclose(libhandle);
1821 LOGV("FRAME: dlclose(libqcamera)");
1822 }
1823#endif
1824
1825 mFrameThreadWaitLock.lock();
1826 mFrameThreadRunning = false;
1827 mFrameThreadWait.signal();
1828 mFrameThreadWaitLock.unlock();
1829
1830 LOGV("runFrameThread X");
1831}
1832
Sravankb4f5f1c2010-01-21 11:06:17 +05301833void QualcommCameraHardware::runVideoThread(void *data)
1834{
1835 LOGD("runVideoThread E");
1836 msm_frame* vframe = NULL;
1837
1838 while(true) {
1839 pthread_mutex_lock(&(g_busy_frame_queue.mut));
1840
1841 LOGE("in video_thread : wait for video frame ");
1842 // check if any frames are available in busyQ and give callback to
1843 // services/video encoder
1844 cam_frame_wait_video();
1845 LOGV("video_thread, wait over..");
1846
1847 // Exit the thread , in case of stop recording..
1848 mVideoThreadWaitLock.lock();
1849 if(mVideoThreadExit){
1850 LOGE("Exiting video thread..");
1851 mVideoThreadWaitLock.unlock();
1852 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
1853 break;
1854 }
1855 mVideoThreadWaitLock.unlock();
1856
1857 // Get the video frame to be encoded
1858 vframe = cam_frame_get_video ();
Apurva Rajgurud9b0b302010-02-19 11:22:56 -08001859 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
Sravankb4f5f1c2010-01-21 11:06:17 +05301860 LOGV("in video_thread : got video frame ");
1861
1862 if(vframe != NULL) {
1863 // Find the offset within the heap of the current buffer.
1864 LOGV("Got video frame : buffer %d base %d ", vframe->buffer, mRecordHeap->mHeap->base());
1865 ssize_t offset =
1866 (ssize_t)vframe->buffer - (ssize_t)mRecordHeap->mHeap->base();
1867 LOGV("offset = %d , alignsize = %d , offset later = %d", offset, mRecordHeap->mAlignedBufferSize, (offset / mRecordHeap->mAlignedBufferSize));
1868
1869 offset /= mRecordHeap->mAlignedBufferSize;
1870
1871 // dump frames for test purpose
1872#ifdef DUMP_VIDEO_FRAMES
1873 static int frameCnt = 0;
1874 if (frameCnt >= 11 && frameCnt <= 13 ) {
1875 char buf[128];
1876 sprintf(buf, "/data/%d_v.yuv", frameCnt);
1877 int file_fd = open(buf, O_RDWR | O_CREAT, 0777);
1878 LOGV("dumping video frame %d", frameCnt);
1879 if (file_fd < 0) {
1880 LOGE("cannot open file\n");
1881 }
1882 else
1883 {
1884 write(file_fd, (const void *)vframe->buffer,
1885 vframe->cbcr_off * 3 / 2);
1886 }
1887 close(file_fd);
1888 }
1889 frameCnt++;
1890#endif
1891 // Enable IF block to give frames to encoder , ELSE block for just simulation
1892#if 1
1893 LOGV("in video_thread : got video frame, before if check giving frame to services/encoder");
1894 mCallbackLock.lock();
1895 int msgEnabled = mMsgEnabled;
1896 data_callback_timestamp rcb = mDataCallbackTimestamp;
1897 void *rdata = mCallbackCookie;
1898 mCallbackLock.unlock();
1899
1900 if(rcb != NULL && (msgEnabled & CAMERA_MSG_VIDEO_FRAME) ) {
1901 LOGV("in video_thread : got video frame, giving frame to services/encoder");
1902 rcb(systemTime(), CAMERA_MSG_VIDEO_FRAME, mRecordHeap->mBuffers[offset], rdata);
1903 Mutex::Autolock rLock(&mRecordFrameLock);
1904 if (mReleasedRecordingFrame != true) {
1905 LOGV("block waiting for frame release");
1906 mRecordWait.wait(mRecordFrameLock);
1907 LOGV("video frame released, continuing");
1908 }
1909 mReleasedRecordingFrame = false;
1910 }
1911#else
1912 // 720p output2 : simulate release frame here:
1913 LOGE("in video_thread simulation , releasing the video frame");
1914 LINK_camframe_free_video(vframe);
1915#endif
1916
1917 } else LOGE("in video_thread get frame returned null");
1918
Sravankb4f5f1c2010-01-21 11:06:17 +05301919
1920 } // end of while loop
Mohan Kandra156d0ac2010-01-25 16:59:17 -08001921
1922 mVideoThreadWaitLock.lock();
1923 mVideoThreadRunning = false;
1924 mVideoThreadWait.signal();
1925 mVideoThreadWaitLock.unlock();
1926
Sravankb4f5f1c2010-01-21 11:06:17 +05301927 LOGV("runVideoThread X");
1928}
1929
1930void *video_thread(void *user)
1931{
1932 LOGV("video_thread E");
1933 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
1934 if (obj != 0) {
1935 obj->runVideoThread(user);
1936 }
1937 else LOGE("not starting video thread: the object went away!");
1938 LOGV("video_thread X");
1939 return NULL;
1940}
1941
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001942void *frame_thread(void *user)
1943{
1944 LOGD("frame_thread E");
1945 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
1946 if (obj != 0) {
1947 obj->runFrameThread(user);
1948 }
1949 else LOGW("not starting frame thread: the object went away!");
1950 LOGD("frame_thread X");
1951 return NULL;
1952}
1953
1954bool QualcommCameraHardware::initPreview()
1955{
1956 // See comments in deinitPreview() for why we have to wait for the frame
1957 // thread here, and why we can't use pthread_join().
Sravankb4f5f1c2010-01-21 11:06:17 +05301958 int videoWidth, videoHeight;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001959 mParameters.getPreviewSize(&previewWidth, &previewHeight);
Sravankb4f5f1c2010-01-21 11:06:17 +05301960
1961 videoWidth = previewWidth; // temporary , should be configurable later
1962 videoHeight = previewHeight;
1963 LOGV("initPreview E: preview size=%dx%d videosize = %d x %d", previewWidth, previewHeight, videoWidth, videoHeight );
1964
Mohan Kandraf1ebf982010-02-02 15:25:43 -08001965 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05301966 mDimension.video_width = videoWidth;
Kiran Kumar H N7ac84e32010-02-01 10:58:47 -08001967 mDimension.video_width = CEILING16(mDimension.video_width);
Sravankb4f5f1c2010-01-21 11:06:17 +05301968 mDimension.video_height = videoHeight;
1969 LOGV("initPreview : preview size=%dx%d videosize = %d x %d", previewWidth, previewHeight, mDimension.video_width, mDimension.video_height );
1970 }
1971
1972
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001973 mFrameThreadWaitLock.lock();
1974 while (mFrameThreadRunning) {
1975 LOGV("initPreview: waiting for old frame thread to complete.");
1976 mFrameThreadWait.wait(mFrameThreadWaitLock);
1977 LOGV("initPreview: old frame thread completed.");
1978 }
1979 mFrameThreadWaitLock.unlock();
1980
1981 mSnapshotThreadWaitLock.lock();
1982 while (mSnapshotThreadRunning) {
1983 LOGV("initPreview: waiting for old snapshot thread to complete.");
1984 mSnapshotThreadWait.wait(mSnapshotThreadWaitLock);
1985 LOGV("initPreview: old snapshot thread completed.");
1986 }
1987 mSnapshotThreadWaitLock.unlock();
1988
1989 int cnt = 0;
1990 mPreviewFrameSize = previewWidth * previewHeight * 3/2;
Mohan Kandrad9efed92010-01-15 19:08:39 -08001991 dstOffset = 0;
1992 mPreviewHeap = new PmemPool("/dev/pmem_adsp",
Mohan Kandra284966d2010-01-05 13:39:15 -08001993 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
1994 mCameraControlFd,
Sravankb4f5f1c2010-01-21 11:06:17 +05301995 MSM_PMEM_PREVIEW, //MSM_PMEM_OUTPUT2,
Mohan Kandra284966d2010-01-05 13:39:15 -08001996 mPreviewFrameSize,
Mohan Kandrad9efed92010-01-15 19:08:39 -08001997 kPreviewBufferCountActual,
Mohan Kandra284966d2010-01-05 13:39:15 -08001998 mPreviewFrameSize,
Mohan Kandrad9efed92010-01-15 19:08:39 -08001999 "preview");
Mohan Kandra284966d2010-01-05 13:39:15 -08002000
Mohan Kandrad9efed92010-01-15 19:08:39 -08002001 if (!mPreviewHeap->initialized()) {
2002 mPreviewHeap.clear();
Mohan Kandra284966d2010-01-05 13:39:15 -08002003 LOGE("initPreview X: could not initialize Camera preview heap.");
2004 return false;
2005 }
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002006 if( mCurrentTarget == TARGET_MSM7630 ) {
Kiran Kumar H N595970b2010-01-12 10:41:09 -08002007 if(mPostViewHeap == NULL) {
2008 LOGV(" Allocating Postview heap ");
2009 /* mPostViewHeap should be declared only for 7630 target */
2010 mPostViewHeap =
2011 new PmemPool("/dev/pmem_adsp",
2012 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
2013 mCameraControlFd,
Sravankb4f5f1c2010-01-21 11:06:17 +05302014 MSM_PMEM_PREVIEW, //MSM_PMEM_OUTPUT2,
Kiran Kumar H N595970b2010-01-12 10:41:09 -08002015 mPreviewFrameSize,
2016 1,
2017 mPreviewFrameSize,
2018 "postview");
Mohan Kandra284966d2010-01-05 13:39:15 -08002019
Kiran Kumar H N595970b2010-01-12 10:41:09 -08002020 if (!mPostViewHeap->initialized()) {
2021 mPostViewHeap.clear();
2022 LOGE(" Failed to initialize Postview Heap");
2023 return false;
2024 }
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002025 }
Mohan Kandraf1ebf982010-02-02 15:25:43 -08002026 }
2027
2028 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250) ) {
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002029
2030 // Allocate video buffers after allocating preview buffers.
Sravankb4f5f1c2010-01-21 11:06:17 +05302031 initRecord();
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002032 }
Sravankb4f5f1c2010-01-21 11:06:17 +05302033
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002034 // mDimension will be filled with thumbnail_width, thumbnail_height,
2035 // orig_picture_dx, and orig_picture_dy after this function call. We need to
2036 // keep it for jpeg_encoder_encode.
2037 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
2038 sizeof(cam_ctrl_dimension_t), &mDimension);
2039
2040 if (ret) {
2041 for (cnt = 0; cnt < kPreviewBufferCount; cnt++) {
Mohan Kandrad9efed92010-01-15 19:08:39 -08002042 frames[cnt].fd = mPreviewHeap->mHeap->getHeapID();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002043 frames[cnt].buffer =
Mohan Kandrad9efed92010-01-15 19:08:39 -08002044 (uint32_t)mPreviewHeap->mHeap->base() + mPreviewHeap->mAlignedBufferSize * cnt;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002045 frames[cnt].y_off = 0;
2046 frames[cnt].cbcr_off = previewWidth * previewHeight;
Sravankb4f5f1c2010-01-21 11:06:17 +05302047 frames[cnt].path = OUTPUT_TYPE_P; // MSM_FRAME_ENC;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002048 }
2049
2050 mFrameThreadWaitLock.lock();
2051 pthread_attr_t attr;
2052 pthread_attr_init(&attr);
2053 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
Sravankb4f5f1c2010-01-21 11:06:17 +05302054
2055 frame_parms.frame = frames[kPreviewBufferCount - 1];
2056 frame_parms.video_frame = recordframes[kPreviewBufferCount - 1];
2057
2058 LOGV ("initpreview before cam_frame thread carete , video frame buffer=%lu fd=%d y_off=%d cbcr_off=%d \n",
2059 (unsigned long)frame_parms.video_frame.buffer, frame_parms.video_frame.fd, frame_parms.video_frame.y_off,
2060 frame_parms.video_frame.cbcr_off);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002061 mFrameThreadRunning = !pthread_create(&mFrameThread,
2062 &attr,
2063 frame_thread,
Sravankb4f5f1c2010-01-21 11:06:17 +05302064 (void*)&(frame_parms));
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002065 ret = mFrameThreadRunning;
2066 mFrameThreadWaitLock.unlock();
2067 }
2068
2069 LOGV("initPreview X: %d", ret);
2070 return ret;
2071}
2072
2073void QualcommCameraHardware::deinitPreview(void)
2074{
2075 LOGI("deinitPreview E");
2076
2077 // When we call deinitPreview(), we signal to the frame thread that it
2078 // needs to exit, but we DO NOT WAIT for it to complete here. The problem
2079 // is that deinitPreview is sometimes called from the frame-thread's
2080 // callback, when the refcount on the Camera client reaches zero. If we
2081 // called pthread_join(), we would deadlock. So, we just call
2082 // LINK_camframe_terminate() in deinitPreview(), which makes sure that
2083 // after the preview callback returns, the camframe thread will exit. We
2084 // could call pthread_join() in initPreview() to join the last frame
2085 // thread. However, we would also have to call pthread_join() in release
2086 // as well, shortly before we destroy the object; this would cause the same
2087 // deadlock, since release(), like deinitPreview(), may also be called from
2088 // the frame-thread's callback. This we have to make the frame thread
2089 // detached, and use a separate mechanism to wait for it to complete.
2090
Kiran Kumar H N7ac84e32010-02-01 10:58:47 -08002091 LINK_camframe_terminate();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002092 LOGI("deinitPreview X");
2093}
2094
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002095bool QualcommCameraHardware::initRawSnapshot()
2096{
2097 LOGV("initRawSnapshot E");
2098
2099 //get width and height from Dimension Object
2100 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
2101 sizeof(cam_ctrl_dimension_t), &mDimension);
2102
2103 if(!ret){
2104 LOGE("initRawSnapshot X: failed to set dimension");
2105 return false;
2106 }
2107 int rawSnapshotSize = mDimension.raw_picture_height *
2108 mDimension.raw_picture_width;
2109
2110 LOGV("raw_snapshot_buffer_size = %d, raw_picture_height = %d, "\
2111 "raw_picture_width = %d",
2112 rawSnapshotSize, mDimension.raw_picture_height,
2113 mDimension.raw_picture_width);
2114
2115 if (mRawSnapShotPmemHeap != NULL) {
2116 LOGV("initRawSnapshot: clearing old mRawSnapShotPmemHeap.");
2117 mRawSnapShotPmemHeap.clear();
2118 }
2119
2120 //Pmem based pool for Camera Driver
2121 mRawSnapShotPmemHeap = new PmemPool("/dev/pmem_adsp",
2122 MemoryHeapBase::READ_ONLY,
2123 mCameraControlFd,
2124 MSM_PMEM_RAW_MAINIMG,
2125 rawSnapshotSize,
2126 1,
2127 rawSnapshotSize,
2128 "raw pmem snapshot camera");
2129
2130 if (!mRawSnapShotPmemHeap->initialized()) {
2131 mRawSnapShotPmemHeap.clear();
2132 LOGE("initRawSnapshot X: error initializing mRawSnapshotHeap");
2133 return false;
2134 }
2135 LOGV("initRawSnapshot X");
2136 return true;
2137
2138}
2139
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002140bool QualcommCameraHardware::initRaw(bool initJpegHeap)
2141{
2142 int rawWidth, rawHeight;
Apurva Rajguru8d1773b2009-12-02 14:21:23 -08002143
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002144 mParameters.getPictureSize(&rawWidth, &rawHeight);
2145 LOGV("initRaw E: picture size=%dx%d", rawWidth, rawHeight);
2146
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08002147 int thumbnailBufferSize;
2148 //Thumbnail height should be smaller than Picture height
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002149 if (rawHeight > (int)thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height){
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08002150 mDimension.ui_thumbnail_width =
2151 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].width;
2152 mDimension.ui_thumbnail_height =
2153 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height;
2154 uint32_t pictureAspectRatio = (uint32_t)((rawWidth * Q12) / rawHeight);
2155 uint32_t i;
2156 for(i = 0; i < THUMBNAIL_SIZE_COUNT; i++ )
2157 {
2158 if(thumbnail_sizes[i].aspect_ratio == pictureAspectRatio)
2159 {
2160 mDimension.ui_thumbnail_width = thumbnail_sizes[i].width;
2161 mDimension.ui_thumbnail_height = thumbnail_sizes[i].height;
2162 break;
2163 }
2164 }
2165 }
2166 else{
2167 mDimension.ui_thumbnail_height = THUMBNAIL_SMALL_HEIGHT;
2168 mDimension.ui_thumbnail_width =
2169 (THUMBNAIL_SMALL_HEIGHT * rawWidth)/ rawHeight;
2170 }
2171
2172 LOGV("Thumbnail Size Width %d Height %d",
2173 mDimension.ui_thumbnail_width,
2174 mDimension.ui_thumbnail_height);
2175
2176 thumbnailBufferSize = mDimension.ui_thumbnail_width *
2177 mDimension.ui_thumbnail_height * 3 / 2;
2178
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002179 // mDimension will be filled with thumbnail_width, thumbnail_height,
2180 // orig_picture_dx, and orig_picture_dy after this function call. We need to
2181 // keep it for jpeg_encoder_encode.
2182 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
2183 sizeof(cam_ctrl_dimension_t), &mDimension);
2184 if(!ret) {
2185 LOGE("initRaw X: failed to set dimension");
2186 return false;
2187 }
2188
2189 if (mJpegHeap != NULL) {
2190 LOGV("initRaw: clearing old mJpegHeap.");
2191 mJpegHeap.clear();
2192 }
2193
2194 // Snapshot
2195 mRawSize = rawWidth * rawHeight * 3 / 2;
Apurva Rajguru8d1773b2009-12-02 14:21:23 -08002196
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002197 if( mCurrentTarget == TARGET_MSM7627 )
Apurva Rajguru8d1773b2009-12-02 14:21:23 -08002198 mJpegMaxSize = CEILING16(rawWidth) * CEILING16(rawHeight) * 3 / 2;
2199 else
2200 mJpegMaxSize = rawWidth * rawHeight * 3 / 2;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002201
2202 LOGV("initRaw: initializing mRawHeap.");
2203 mRawHeap =
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002204 new PmemPool("/dev/pmem_adsp",
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002205 MemoryHeapBase::READ_ONLY,
2206 mCameraControlFd,
2207 MSM_PMEM_MAINIMG,
2208 mJpegMaxSize,
2209 kRawBufferCount,
2210 mRawSize,
2211 "snapshot camera");
2212
2213 if (!mRawHeap->initialized()) {
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002214 LOGE("initRaw X failed ");
2215 mRawHeap.clear();
2216 LOGE("initRaw X: error initializing mRawHeap");
2217 return false;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002218 }
2219
2220 LOGV("do_mmap snapshot pbuf = %p, pmem_fd = %d",
2221 (uint8_t *)mRawHeap->mHeap->base(), mRawHeap->mHeap->getHeapID());
2222
2223 // Jpeg
2224
2225 if (initJpegHeap) {
2226 LOGV("initRaw: initializing mJpegHeap.");
2227 mJpegHeap =
2228 new AshmemPool(mJpegMaxSize,
2229 kJpegBufferCount,
2230 0, // we do not know how big the picture will be
2231 "jpeg");
2232
2233 if (!mJpegHeap->initialized()) {
2234 mJpegHeap.clear();
2235 mRawHeap.clear();
2236 LOGE("initRaw X failed: error initializing mJpegHeap.");
2237 return false;
2238 }
2239
2240 // Thumbnails
2241
2242 mThumbnailHeap =
2243 new PmemPool("/dev/pmem_adsp",
2244 MemoryHeapBase::READ_ONLY,
2245 mCameraControlFd,
2246 MSM_PMEM_THUMBNAIL,
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08002247 thumbnailBufferSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002248 1,
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08002249 thumbnailBufferSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002250 "thumbnail");
2251
2252 if (!mThumbnailHeap->initialized()) {
2253 mThumbnailHeap.clear();
2254 mJpegHeap.clear();
2255 mRawHeap.clear();
2256 LOGE("initRaw X failed: error initializing mThumbnailHeap.");
2257 return false;
2258 }
2259 }
2260
2261 LOGV("initRaw X");
2262 return true;
2263}
2264
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002265
2266void QualcommCameraHardware::deinitRawSnapshot()
2267{
2268 LOGV("deinitRawSnapshot E");
2269 mRawSnapShotPmemHeap.clear();
2270 mRawSnapshotAshmemHeap.clear();
2271 LOGV("deinitRawSnapshot X");
2272}
2273
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002274void QualcommCameraHardware::deinitRaw()
2275{
2276 LOGV("deinitRaw E");
2277
2278 mThumbnailHeap.clear();
2279 mJpegHeap.clear();
2280 mRawHeap.clear();
2281 mDisplayHeap.clear();
2282
2283 LOGV("deinitRaw X");
2284}
2285
2286void QualcommCameraHardware::release()
2287{
2288 LOGD("release E");
2289 Mutex::Autolock l(&mLock);
2290
2291#if DLOPEN_LIBMMCAMERA
2292 if (libmmcamera == NULL) {
2293 LOGE("ERROR: multiple release!");
2294 return;
2295 }
2296#else
2297#warning "Cannot detect multiple release when not dlopen()ing libqcamera!"
2298#endif
2299
2300 int cnt, rc;
2301 struct msm_ctrl_cmd ctrlCmd;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002302 if (mCameraRunning) {
2303 if(mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME)) {
2304 mRecordFrameLock.lock();
2305 mReleasedRecordingFrame = true;
2306 mRecordWait.signal();
2307 mRecordFrameLock.unlock();
2308 }
2309 stopPreviewInternal();
2310 }
2311
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002312 if( mCurrentTarget == TARGET_MSM7630 ) {
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002313 mPostViewHeap.clear();
2314 mPostViewHeap = NULL;
2315 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002316 LINK_jpeg_encoder_join();
2317 deinitRaw();
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002318 deinitRawSnapshot();
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002319 {
2320 Mutex::Autolock l(&mCamframeTimeoutLock);
2321 if(!camframe_timeout_flag) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002322
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002323 ctrlCmd.timeout_ms = 5000;
2324 ctrlCmd.length = 0;
2325 ctrlCmd.type = (uint16_t)CAMERA_EXIT;
2326 ctrlCmd.resp_fd = mCameraControlFd; // FIXME: this will be put in by the kernel
2327 if (ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0)
2328 LOGE("ioctl CAMERA_EXIT fd %d error %s",
2329 mCameraControlFd, strerror(errno));
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002330
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002331 }
2332 }
Kiran Kumar H N7ac84e32010-02-01 10:58:47 -08002333 LINK_release_cam_conf_thread();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002334 close(mCameraControlFd);
2335 mCameraControlFd = -1;
Mohan Kandra284966d2010-01-05 13:39:15 -08002336 if(fb_fd >= 0) {
2337 close(fb_fd);
2338 fb_fd = -1;
2339 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002340#if DLOPEN_LIBMMCAMERA
2341 if (libmmcamera) {
2342 ::dlclose(libmmcamera);
2343 LOGV("dlclose(libqcamera)");
2344 libmmcamera = NULL;
2345 }
2346#endif
2347
2348 Mutex::Autolock lock(&singleton_lock);
2349 singleton_releasing = true;
2350
2351 LOGD("release X");
2352}
2353
2354QualcommCameraHardware::~QualcommCameraHardware()
2355{
2356 LOGD("~QualcommCameraHardware E");
2357 Mutex::Autolock lock(&singleton_lock);
2358 singleton.clear();
2359 singleton_releasing = false;
2360 singleton_wait.signal();
2361 LOGD("~QualcommCameraHardware X");
2362}
2363
2364sp<IMemoryHeap> QualcommCameraHardware::getRawHeap() const
2365{
2366 LOGV("getRawHeap");
2367 return mDisplayHeap != NULL ? mDisplayHeap->mHeap : NULL;
2368}
2369
2370sp<IMemoryHeap> QualcommCameraHardware::getPreviewHeap() const
2371{
2372 LOGV("getPreviewHeap");
Mohan Kandrad9efed92010-01-15 19:08:39 -08002373 return mPreviewHeap != NULL ? mPreviewHeap->mHeap : NULL;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002374}
2375
2376status_t QualcommCameraHardware::startPreviewInternal()
2377{
Sravankb4f5f1c2010-01-21 11:06:17 +05302378 LOGV("in startPreviewInternal : E");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002379 if(mCameraRunning) {
2380 LOGV("startPreview X: preview already running.");
2381 return NO_ERROR;
2382 }
2383
2384 if (!mPreviewInitialized) {
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002385 mLastQueuedFrame = NULL;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002386 mPreviewInitialized = initPreview();
2387 if (!mPreviewInitialized) {
2388 LOGE("startPreview X initPreview failed. Not starting preview.");
2389 return UNKNOWN_ERROR;
2390 }
2391 }
2392
Mohan Kandraf1ebf982010-02-02 15:25:43 -08002393 if(( mCurrentTarget != TARGET_MSM7630 ) && (mCurrentTarget != TARGET_QSD8250))
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002394 mCameraRunning = native_start_preview(mCameraControlFd);
Sravankb4f5f1c2010-01-21 11:06:17 +05302395 else
2396 mCameraRunning = native_start_video(mCameraControlFd);
2397
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002398 if(!mCameraRunning) {
2399 deinitPreview();
2400 mPreviewInitialized = false;
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08002401 mOverlay = NULL;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002402 LOGE("startPreview X: native_start_preview failed!");
2403 return UNKNOWN_ERROR;
2404 }
2405
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08002406 //Reset the Gps Information
2407 exif_table_numEntries = 0;
Mohan Kandra284966d2010-01-05 13:39:15 -08002408
2409 if(native_get_maxzoom(mCameraControlFd, (void *)&mMaxZoom) == true){
Brian Steuerb62adbd2010-02-02 14:47:08 -08002410 LOGD("Maximum zoom value is %d", mMaxZoom);
Mohan Kandra284966d2010-01-05 13:39:15 -08002411 mParameters.set("zoom-supported", "true");
2412 } else {
2413 LOGE("Failed to get maximum zoom value...setting max zoom to zero");
2414 mParameters.set("zoom-supported", "false");
2415 mMaxZoom = 0;
2416 }
2417 mParameters.set("max-zoom",mMaxZoom);
2418
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08002419 //Initialize AF state to AF_NOTSTARTED
2420 mAfLock.lock();
2421 mAfState = AF_NOTSTARTED;
2422 mAfLock.unlock();
2423
Sravankb4f5f1c2010-01-21 11:06:17 +05302424 LOGV("startPreviewInternal X");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002425 return NO_ERROR;
2426}
2427
2428status_t QualcommCameraHardware::startPreview()
2429{
2430 LOGV("startPreview E");
2431 Mutex::Autolock l(&mLock);
2432 return startPreviewInternal();
2433}
2434
2435void QualcommCameraHardware::stopPreviewInternal()
2436{
2437 LOGV("stopPreviewInternal E: %d", mCameraRunning);
2438 if (mCameraRunning) {
2439 // Cancel auto focus.
2440 {
2441 if (mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS)) {
2442 cancelAutoFocusInternal();
2443 }
2444 }
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002445
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002446 Mutex::Autolock l(&mCamframeTimeoutLock);
2447 if(!camframe_timeout_flag) {
Mohan Kandraf1ebf982010-02-02 15:25:43 -08002448 if (( mCurrentTarget != TARGET_MSM7630 ) && (mCurrentTarget != TARGET_QSD8250))
Sravankb4f5f1c2010-01-21 11:06:17 +05302449 mCameraRunning = !native_stop_preview(mCameraControlFd);
2450 else
2451 mCameraRunning = !native_stop_video(mCameraControlFd);
2452
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002453 } else {
2454 /* This means that the camframetimeout was issued.
2455 * But we did not issue native_stop_preview(), so we
Kiran Kumar H Nac2f4952009-12-17 01:16:53 -08002456 * need to update mCameraRunning to indicate that
2457 * Camera is no longer running. */
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002458 mCameraRunning = 0;
Kiran Kumar H Nac2f4952009-12-17 01:16:53 -08002459 }
2460 if (!mCameraRunning && mPreviewInitialized) {
2461 deinitPreview();
Mohan Kandraf1ebf982010-02-02 15:25:43 -08002462 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250)) {
Mohan Kandra156d0ac2010-01-25 16:59:17 -08002463 mVideoThreadWaitLock.lock();
2464 LOGV("in stopPreviewInternal: making mVideoThreadExit 1");
2465 mVideoThreadExit = 1;
2466 mVideoThreadWaitLock.unlock();
2467 // 720p : signal the video thread , and check in video thread if stop is called, if so exit video thread.
2468 pthread_mutex_lock(&(g_busy_frame_queue.mut));
2469 pthread_cond_signal(&(g_busy_frame_queue.wait));
2470 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
2471 }
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002472 mPreviewInitialized = false;
2473 }
Kiran Kumar H Nac2f4952009-12-17 01:16:53 -08002474 else LOGE("stopPreviewInternal: failed to stop preview");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002475 }
2476 LOGV("stopPreviewInternal X: %d", mCameraRunning);
2477}
2478
2479void QualcommCameraHardware::stopPreview()
2480{
2481 LOGV("stopPreview: E");
2482 Mutex::Autolock l(&mLock);
2483 {
2484 if (mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME))
2485 return;
2486 }
2487 stopPreviewInternal();
2488 LOGV("stopPreview: X");
2489}
2490
2491void QualcommCameraHardware::runAutoFocus()
2492{
2493 bool status = true;
2494 void *libhandle = NULL;
Srinivasan Kannan71229622009-12-04 12:05:58 -08002495 isp3a_af_mode_t afMode;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002496
2497 mAutoFocusThreadLock.lock();
2498 // Skip autofocus if focus mode is infinity.
2499 if (strcmp(mParameters.get(CameraParameters::KEY_FOCUS_MODE),
2500 CameraParameters::FOCUS_MODE_INFINITY) == 0) {
2501 goto done;
2502 }
2503
2504 mAutoFocusFd = open(MSM_CAMERA_CONTROL, O_RDWR);
2505 if (mAutoFocusFd < 0) {
2506 LOGE("autofocus: cannot open %s: %s",
2507 MSM_CAMERA_CONTROL,
2508 strerror(errno));
2509 mAutoFocusThreadRunning = false;
2510 mAutoFocusThreadLock.unlock();
2511 return;
2512 }
2513
2514#if DLOPEN_LIBMMCAMERA
2515 // We need to maintain a reference to libqcamera.so for the duration of the
2516 // AF thread, because we do not know when it will exit relative to the
2517 // lifetime of this object. We do not want to dlclose() libqcamera while
2518 // LINK_cam_frame is still running.
2519 libhandle = ::dlopen("liboemcamera.so", RTLD_NOW);
2520 LOGV("AF: loading libqcamera at %p", libhandle);
2521 if (!libhandle) {
2522 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
2523 close(mAutoFocusFd);
2524 mAutoFocusFd = -1;
2525 mAutoFocusThreadRunning = false;
2526 mAutoFocusThreadLock.unlock();
2527 return;
2528 }
2529#endif
2530
Srinivasan Kannan71229622009-12-04 12:05:58 -08002531 afMode = (isp3a_af_mode_t)attr_lookup(focus_modes,
2532 sizeof(focus_modes) / sizeof(str_map),
2533 mParameters.get(CameraParameters::KEY_FOCUS_MODE));
2534
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002535 /* This will block until either AF completes or is cancelled. */
Srinivasan Kannan71229622009-12-04 12:05:58 -08002536 LOGV("af start (fd %d mode %d)", mAutoFocusFd, afMode);
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08002537 status_t err;
2538 err = mAfLock.tryLock();
2539 if(err == NO_ERROR) {
2540 //Got Lock, so start AF if required.
2541 if(mAfState != AF_CANCELLED) {
2542 mAfState = AF_STARTED;
2543 LOGV("Start AF");
2544 status = native_set_afmode(mAutoFocusFd, afMode);
2545 } else {
2546 status = FALSE;
2547 }
2548 mAfLock.unlock();
2549 }
2550 else{
2551 //AF Cancel would have acquired the lock,
2552 //so, no need to perform any AF
2553 LOGV("Failed to obtain Lock...is busy");
2554 status = FALSE;
2555 }
2556
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002557 LOGV("af done: %d", (int)status);
2558 close(mAutoFocusFd);
2559 mAutoFocusFd = -1;
2560
2561done:
2562 mAutoFocusThreadRunning = false;
2563 mAutoFocusThreadLock.unlock();
2564
2565 mCallbackLock.lock();
2566 bool autoFocusEnabled = mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS);
2567 notify_callback cb = mNotifyCallback;
2568 void *data = mCallbackCookie;
2569 mCallbackLock.unlock();
2570 if (autoFocusEnabled)
2571 cb(CAMERA_MSG_FOCUS, status, 0, data);
2572
2573#if DLOPEN_LIBMMCAMERA
2574 if (libhandle) {
2575 ::dlclose(libhandle);
2576 LOGV("AF: dlclose(libqcamera)");
2577 }
2578#endif
2579}
2580
2581status_t QualcommCameraHardware::cancelAutoFocusInternal()
2582{
2583 LOGV("cancelAutoFocusInternal E");
2584
Srinivasan Kannan71229622009-12-04 12:05:58 -08002585 if(!sensorType->hasAutoFocusSupport){
2586 LOGV("cancelAutoFocusInternal X");
2587 return NO_ERROR;
2588 }
2589
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002590#if 0
2591 if (mAutoFocusFd < 0) {
2592 LOGV("cancelAutoFocusInternal X: not in progress");
2593 return NO_ERROR;
2594 }
2595#endif
2596
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08002597 status_t rc = NO_ERROR;
2598 status_t err;
2599 err = mAfLock.tryLock();
2600 if(err == NO_ERROR) {
2601 //Got Lock, means either AF hasn't started or
2602 // AF is done. So no need to cancel it, just change the state
2603 LOGV("Change AF State to Cancelled");
2604 mAfState = AF_CANCELLED;
2605 mAfLock.unlock();
2606 }
2607 else {
2608 //AF is in Progess, So cancel it
2609 LOGV("Lock busy...cancel AF");
2610 rc = native_cancel_afmode(mCameraControlFd, mAutoFocusFd) ?
2611 NO_ERROR :
2612 UNKNOWN_ERROR;
2613 }
2614
2615
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002616
2617 LOGV("cancelAutoFocusInternal X: %d", rc);
2618 return rc;
2619}
2620
2621void *auto_focus_thread(void *user)
2622{
2623 LOGV("auto_focus_thread E");
2624 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
2625 if (obj != 0) {
2626 obj->runAutoFocus();
2627 }
2628 else LOGW("not starting autofocus: the object went away!");
2629 LOGV("auto_focus_thread X");
2630 return NULL;
2631}
2632
2633status_t QualcommCameraHardware::autoFocus()
2634{
2635 LOGV("autoFocus E");
2636 Mutex::Autolock l(&mLock);
2637
Srinivasan Kannan71229622009-12-04 12:05:58 -08002638 if(!sensorType->hasAutoFocusSupport){
Srinivasan Kannandf085222009-12-09 18:31:00 -08002639 bool status = false;
2640 mCallbackLock.lock();
2641 bool autoFocusEnabled = mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS);
2642 notify_callback cb = mNotifyCallback;
2643 void *data = mCallbackCookie;
2644 mCallbackLock.unlock();
2645 if (autoFocusEnabled)
2646 cb(CAMERA_MSG_FOCUS, status, 0, data);
Srinivasan Kannan71229622009-12-04 12:05:58 -08002647 LOGV("autoFocus X");
2648 return NO_ERROR;
2649 }
2650
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002651 if (mCameraControlFd < 0) {
2652 LOGE("not starting autofocus: main control fd %d", mCameraControlFd);
2653 return UNKNOWN_ERROR;
2654 }
2655
2656 {
2657 mAutoFocusThreadLock.lock();
2658 if (!mAutoFocusThreadRunning) {
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08002659 if (native_prepare_snapshot(mCameraControlFd) == FALSE) {
2660 LOGE("native_prepare_snapshot failed!\n");
2661 mAutoFocusThreadLock.unlock();
2662 return UNKNOWN_ERROR;
2663 }
2664
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002665 // Create a detached thread here so that we don't have to wait
2666 // for it when we cancel AF.
2667 pthread_t thr;
2668 pthread_attr_t attr;
2669 pthread_attr_init(&attr);
2670 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2671 mAutoFocusThreadRunning =
2672 !pthread_create(&thr, &attr,
2673 auto_focus_thread, NULL);
2674 if (!mAutoFocusThreadRunning) {
2675 LOGE("failed to start autofocus thread");
2676 mAutoFocusThreadLock.unlock();
2677 return UNKNOWN_ERROR;
2678 }
2679 }
2680 mAutoFocusThreadLock.unlock();
2681 }
2682
2683 LOGV("autoFocus X");
2684 return NO_ERROR;
2685}
2686
2687status_t QualcommCameraHardware::cancelAutoFocus()
2688{
2689 LOGV("cancelAutoFocus E");
2690 Mutex::Autolock l(&mLock);
2691
2692 int rc = NO_ERROR;
2693 if (mCameraRunning && mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS)) {
2694 rc = cancelAutoFocusInternal();
2695 }
2696
2697 LOGV("cancelAutoFocus X");
2698 return rc;
2699}
2700
2701void QualcommCameraHardware::runSnapshotThread(void *data)
2702{
2703 LOGV("runSnapshotThread E");
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002704 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
2705 if (native_start_snapshot(mCameraControlFd))
2706 receiveRawPicture();
2707 else
2708 LOGE("main: native_start_snapshot failed!");
2709 } else if(mSnapshotFormat == PICTURE_FORMAT_RAW){
2710 if(native_start_raw_snapshot(mCameraControlFd)){
2711 receiveRawSnapshot();
2712 } else {
2713 LOGE("main: native_start_raw_snapshot failed!");
2714 }
2715 }
2716
2717 mSnapshotFormat = 0;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002718
2719 mSnapshotThreadWaitLock.lock();
2720 mSnapshotThreadRunning = false;
2721 mSnapshotThreadWait.signal();
2722 mSnapshotThreadWaitLock.unlock();
2723
2724 LOGV("runSnapshotThread X");
2725}
2726
2727void *snapshot_thread(void *user)
2728{
2729 LOGD("snapshot_thread E");
2730 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
2731 if (obj != 0) {
2732 obj->runSnapshotThread(user);
2733 }
2734 else LOGW("not starting snapshot thread: the object went away!");
2735 LOGD("snapshot_thread X");
2736 return NULL;
2737}
2738
2739status_t QualcommCameraHardware::takePicture()
2740{
2741 LOGV("takePicture(%d)", mMsgEnabled);
2742 Mutex::Autolock l(&mLock);
2743
2744 // Wait for old snapshot thread to complete.
2745 mSnapshotThreadWaitLock.lock();
2746 while (mSnapshotThreadRunning) {
2747 LOGV("takePicture: waiting for old snapshot thread to complete.");
2748 mSnapshotThreadWait.wait(mSnapshotThreadWaitLock);
2749 LOGV("takePicture: old snapshot thread completed.");
2750 }
2751
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002752 if( mCurrentTarget == TARGET_MSM7630 ) {
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002753 /* Store the last frame queued for preview. This
2754 * shall be used as postview */
2755 storePreviewFrameForPostview();
2756 }
2757
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002758 //mSnapshotFormat is protected by mSnapshotThreadWaitLock
2759 if(mParameters.getPictureFormat() != 0 &&
2760 !strcmp(mParameters.getPictureFormat(),
2761 CameraParameters::PIXEL_FORMAT_RAW))
2762 mSnapshotFormat = PICTURE_FORMAT_RAW;
2763 else
2764 mSnapshotFormat = PICTURE_FORMAT_JPEG;
2765
2766 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
2767 if(!native_prepare_snapshot(mCameraControlFd)) {
2768 mSnapshotThreadWaitLock.unlock();
2769 return UNKNOWN_ERROR;
2770 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002771 }
2772
2773 stopPreviewInternal();
2774
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002775 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
2776 if (!initRaw(mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE))) {
2777 LOGE("initRaw failed. Not taking picture.");
2778 mSnapshotThreadWaitLock.unlock();
2779 return UNKNOWN_ERROR;
2780 }
2781 } else if(mSnapshotFormat == PICTURE_FORMAT_RAW ){
2782 if(!initRawSnapshot()){
2783 LOGE("initRawSnapshot failed. Not taking picture.");
2784 mSnapshotThreadWaitLock.unlock();
2785 return UNKNOWN_ERROR;
2786 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002787 }
2788
2789 mShutterLock.lock();
2790 mShutterPending = true;
2791 mShutterLock.unlock();
2792
2793 pthread_attr_t attr;
2794 pthread_attr_init(&attr);
2795 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2796 mSnapshotThreadRunning = !pthread_create(&mSnapshotThread,
2797 &attr,
2798 snapshot_thread,
2799 NULL);
2800 mSnapshotThreadWaitLock.unlock();
2801
2802 LOGV("takePicture: X");
2803 return mSnapshotThreadRunning ? NO_ERROR : UNKNOWN_ERROR;
2804}
2805
2806status_t QualcommCameraHardware::cancelPicture()
2807{
2808 status_t rc;
2809 LOGV("cancelPicture: E");
2810 rc = native_stop_snapshot(mCameraControlFd) ? NO_ERROR : UNKNOWN_ERROR;
2811 LOGV("cancelPicture: X: %d", rc);
2812 return rc;
2813}
2814
2815status_t QualcommCameraHardware::setParameters(const CameraParameters& params)
2816{
2817 LOGV("setParameters: E params = %p", &params);
2818
2819 Mutex::Autolock l(&mLock);
2820 status_t rc, final_rc = NO_ERROR;
2821
2822 if ((rc = setPreviewSize(params))) final_rc = rc;
2823 if ((rc = setPictureSize(params))) final_rc = rc;
2824 if ((rc = setJpegQuality(params))) final_rc = rc;
2825 if ((rc = setAntibanding(params))) final_rc = rc;
2826 if ((rc = setEffect(params))) final_rc = rc;
Apurva Rajguru55562b02009-12-03 12:25:35 -08002827 if ((rc = setAutoExposure(params))) final_rc = rc;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002828 if ((rc = setWhiteBalance(params))) final_rc = rc;
2829 if ((rc = setFlash(params))) final_rc = rc;
2830 if ((rc = setGpsLocation(params))) final_rc = rc;
2831 if ((rc = setRotation(params))) final_rc = rc;
2832 if ((rc = setZoom(params))) final_rc = rc;
2833 if ((rc = setFocusMode(params))) final_rc = rc;
2834 if ((rc = setOrientation(params))) final_rc = rc;
Nishant Panditc8c1ee72009-12-03 16:24:02 +05302835 if ((rc = setBrightness(params))) final_rc = rc;
2836 if ((rc = setLensshadeValue(params))) final_rc = rc;
2837 if ((rc = setISOValue(params))) final_rc = rc;
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002838 if ((rc = setPictureFormat(params))) final_rc = rc;
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08002839 if ((rc = setSharpness(params))) final_rc = rc;
2840 if ((rc = setContrast(params))) final_rc = rc;
2841 if ((rc = setSaturation(params))) final_rc = rc;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002842
2843 LOGV("setParameters: X");
2844 return final_rc;
2845}
2846
2847CameraParameters QualcommCameraHardware::getParameters() const
2848{
2849 LOGV("getParameters: EX");
2850 return mParameters;
2851}
2852
2853status_t QualcommCameraHardware::sendCommand(int32_t command, int32_t arg1,
2854 int32_t arg2)
2855{
2856 LOGV("sendCommand: EX");
2857 return BAD_VALUE;
2858}
2859
2860extern "C" sp<CameraHardwareInterface> openCameraHardware()
2861{
2862 LOGV("openCameraHardware: call createInstance");
2863 return QualcommCameraHardware::createInstance();
2864}
2865
2866wp<QualcommCameraHardware> QualcommCameraHardware::singleton;
2867
2868// If the hardware already exists, return a strong pointer to the current
2869// object. If not, create a new hardware object, put it in the singleton,
2870// and return it.
2871sp<CameraHardwareInterface> QualcommCameraHardware::createInstance()
2872{
2873 LOGD("createInstance: E");
2874
2875 Mutex::Autolock lock(&singleton_lock);
2876
2877 // Wait until the previous release is done.
2878 while (singleton_releasing) {
2879 LOGD("Wait for previous release.");
2880 singleton_wait.wait(singleton_lock);
2881 }
2882
2883 if (singleton != 0) {
2884 sp<CameraHardwareInterface> hardware = singleton.promote();
2885 if (hardware != 0) {
2886 LOGD("createInstance: X return existing hardware=%p", &(*hardware));
2887 return hardware;
2888 }
2889 }
2890
2891 {
2892 struct stat st;
2893 int rc = stat("/dev/oncrpc", &st);
2894 if (rc < 0) {
2895 LOGD("createInstance: X failed to create hardware: %s", strerror(errno));
2896 return NULL;
2897 }
2898 }
2899
2900 QualcommCameraHardware *cam = new QualcommCameraHardware();
2901 sp<QualcommCameraHardware> hardware(cam);
2902 singleton = hardware;
2903
2904 if (!cam->startCamera()) {
2905 LOGE("%s: startCamera failed!", __FUNCTION__);
2906 return NULL;
2907 }
2908
2909 cam->initDefaultParameters();
2910 LOGD("createInstance: X created hardware=%p", &(*hardware));
2911 return hardware;
2912}
2913
2914// For internal use only, hence the strong pointer to the derived type.
2915sp<QualcommCameraHardware> QualcommCameraHardware::getInstance()
2916{
2917 sp<CameraHardwareInterface> hardware = singleton.promote();
2918 if (hardware != 0) {
2919 // LOGV("getInstance: X old instance of hardware");
2920 return sp<QualcommCameraHardware>(static_cast<QualcommCameraHardware*>(hardware.get()));
2921 } else {
2922 LOGV("getInstance: X new instance of hardware");
2923 return sp<QualcommCameraHardware>();
2924 }
2925}
Sravankb4f5f1c2010-01-21 11:06:17 +05302926void QualcommCameraHardware::receiveRecordingFrame(struct msm_frame *frame)
2927{
2928 LOGV("receiveRecordingFrame E");
2929 // post busy frame
2930 if (frame)
2931 {
2932 cam_frame_post_video (frame);
2933 }
2934 else LOGE("in receiveRecordingFrame frame is NULL");
2935 LOGV("receiveRecordingFrame X");
2936}
2937
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002938
Mohan Kandrad9efed92010-01-15 19:08:39 -08002939bool QualcommCameraHardware::native_zoom_image(int fd, int srcOffset, int dstOffSet, common_crop_t *crop)
Mohan Kandra284966d2010-01-05 13:39:15 -08002940{
2941 int result = 0;
2942 struct mdp_blit_req *e;
2943 struct timeval td1, td2;
2944
Mohan Kandra284966d2010-01-05 13:39:15 -08002945 /* Initialize yuv structure */
2946 zoomImage.list.count = 1;
2947
2948 e = &zoomImage.list.req[0];
2949
2950 e->src.width = previewWidth;
2951 e->src.height = previewHeight;
2952 e->src.format = MDP_Y_CBCR_H2V2;
Mohan Kandrad9efed92010-01-15 19:08:39 -08002953 e->src.offset = srcOffset;
2954 e->src.memory_id = fd;
Mohan Kandra284966d2010-01-05 13:39:15 -08002955
2956 e->dst.width = previewWidth;
2957 e->dst.height = previewHeight;
2958 e->dst.format = MDP_Y_CBCR_H2V2;
Mohan Kandrad9efed92010-01-15 19:08:39 -08002959 e->dst.offset = dstOffSet;
2960 e->dst.memory_id = fd;
Mohan Kandra284966d2010-01-05 13:39:15 -08002961
2962 e->transp_mask = 0xffffffff;
2963 e->flags = 0;
2964 e->alpha = 0xff;
2965 if (crop->in2_w != 0 || crop->in2_h != 0) {
2966 e->src_rect.x = (crop->out2_w - crop->in2_w + 1) / 2 - 1;
2967 e->src_rect.y = (crop->out2_h - crop->in2_h + 1) / 2 - 1;
2968 e->src_rect.w = crop->in2_w;
2969 e->src_rect.h = crop->in2_h;
2970 } else {
2971 e->src_rect.x = 0;
2972 e->src_rect.y = 0;
2973 e->src_rect.w = previewWidth;
2974 e->src_rect.h = previewHeight;
2975 }
Mohan Kandrad9efed92010-01-15 19:08:39 -08002976 //LOGV(" native_zoom : SRC_RECT : x,y = %d,%d \t w,h = %d, %d",
2977 // e->src_rect.x, e->src_rect.y, e->src_rect.w, e->src_rect.h);
Mohan Kandra284966d2010-01-05 13:39:15 -08002978
2979 e->dst_rect.x = 0;
2980 e->dst_rect.y = 0;
2981 e->dst_rect.w = previewWidth;
2982 e->dst_rect.h = previewHeight;
2983
2984 result = ioctl(fb_fd, MSMFB_BLIT, &zoomImage.list);
2985 if (result < 0) {
2986 LOGE("MSM_FBIOBLT failed! line=%d\n", __LINE__);
2987 return FALSE;
2988 }
2989 return TRUE;
2990}
2991
Mohan Kandra740cfce2010-01-07 12:58:24 -08002992void QualcommCameraHardware::debugShowFPS() const
2993{
2994 static int mFrameCount;
2995 static int mLastFrameCount = 0;
2996 static nsecs_t mLastFpsTime = 0;
2997 static float mFps = 0;
2998 mFrameCount++;
2999 nsecs_t now = systemTime();
3000 nsecs_t diff = now - mLastFpsTime;
3001 if (diff > ms2ns(250)) {
3002 mFps = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
3003 LOGI("Frames Per Second: %.4f", mFps);
3004 mLastFpsTime = now;
3005 mLastFrameCount = mFrameCount;
3006 }
3007}
3008
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003009void QualcommCameraHardware::receivePreviewFrame(struct msm_frame *frame)
3010{
3011// LOGV("receivePreviewFrame E");
3012
3013 if (!mCameraRunning) {
3014 LOGE("ignoring preview callback--camera has been stopped");
3015 return;
3016 }
3017
Mohan Kandra740cfce2010-01-07 12:58:24 -08003018 if (UNLIKELY(mDebugFps)) {
3019 debugShowFPS();
3020 }
3021
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003022 mCallbackLock.lock();
3023 int msgEnabled = mMsgEnabled;
3024 data_callback pcb = mDataCallback;
3025 void *pdata = mCallbackCookie;
3026 data_callback_timestamp rcb = mDataCallbackTimestamp;
3027 void *rdata = mCallbackCookie;
3028 mCallbackLock.unlock();
3029
3030 // Find the offset within the heap of the current buffer.
Mohan Kandra284966d2010-01-05 13:39:15 -08003031 ssize_t offset_addr =
Mohan Kandrad9efed92010-01-15 19:08:39 -08003032 (ssize_t)frame->buffer - (ssize_t)mPreviewHeap->mHeap->base();
3033 ssize_t offset = offset_addr / mPreviewHeap->mAlignedBufferSize;
Mohan Kandra284966d2010-01-05 13:39:15 -08003034
3035 common_crop_t *crop = (common_crop_t *) (frame->cropinfo);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003036
3037 mInPreviewCallback = true;
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003038 if(mUseOverlay) {
3039 if(mOverlay != NULL) {
3040 mOverlayLock.lock();
Mohan Kandrad9efed92010-01-15 19:08:39 -08003041 mOverlay->setFd(mPreviewHeap->mHeap->getHeapID());
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003042 if (crop->in2_w != 0 || crop->in2_h != 0) {
3043 zoomCropInfo.x = (crop->out2_w - crop->in2_w + 1) / 2 - 1;
3044 zoomCropInfo.y = (crop->out2_h - crop->in2_h + 1) / 2 - 1;
3045 zoomCropInfo.w = crop->in2_w;
3046 zoomCropInfo.h = crop->in2_h;
3047 mOverlay->setCrop(zoomCropInfo.x, zoomCropInfo.y,
3048 zoomCropInfo.w, zoomCropInfo.h);
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08003049 } else {
3050 // Reset zoomCropInfo variables. This will ensure that
3051 // stale values wont be used for postview
3052 zoomCropInfo.w = crop->in2_w;
3053 zoomCropInfo.h = crop->in2_h;
3054 }
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003055 mOverlay->queueBuffer((void *)offset_addr);
3056 mLastQueuedFrame = (void *)frame->buffer;
3057 mOverlayLock.unlock();
3058 }
Mohan Kandra284966d2010-01-05 13:39:15 -08003059 } else {
Mohan Kandrad9efed92010-01-15 19:08:39 -08003060 if (crop->in2_w != 0 || crop->in2_h != 0) {
3061 dstOffset = (dstOffset + 1) % NUM_MORE_BUFS;
3062 offset = kPreviewBufferCount + dstOffset;
3063 ssize_t dstOffset_addr = offset * mPreviewHeap->mAlignedBufferSize;
3064 if( !native_zoom_image(mPreviewHeap->mHeap->getHeapID(),
3065 offset_addr, dstOffset_addr, crop)) {
3066 LOGE(" Error while doing MDP zoom ");
3067 }
3068 }
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08003069 }
Mohan Kandrad9efed92010-01-15 19:08:39 -08003070 if (pcb != NULL && (msgEnabled & CAMERA_MSG_PREVIEW_FRAME))
3071 pcb(CAMERA_MSG_PREVIEW_FRAME, mPreviewHeap->mBuffers[offset],
3072 pdata);
3073
Sravankb4f5f1c2010-01-21 11:06:17 +05303074 // If output2 enabled, Start Recording if recording is enabled by Services
Mohan Kandraf1ebf982010-02-02 15:25:43 -08003075 if( ((mCurrentTarget == TARGET_MSM7630) || (mCurrentTarget == TARGET_QSD8250)) && recordingEnabled() ) {
Sravankb4f5f1c2010-01-21 11:06:17 +05303076 if(!recordingState){
3077 recordingState = 1; // recording started
3078 LOGV(" in receivePreviewframe : recording enabled calling startRecording ");
3079 startRecording();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003080 }
Sravankb4f5f1c2010-01-21 11:06:17 +05303081 }
3082
3083 // If output is NOT enabled (targets otherthan 7x30 currently..)
Mohan Kandraf1ebf982010-02-02 15:25:43 -08003084 if( (mCurrentTarget != TARGET_MSM7630 ) && (mCurrentTarget != TARGET_QSD8250)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05303085 if(rcb != NULL && (msgEnabled & CAMERA_MSG_VIDEO_FRAME)) {
3086 rcb(systemTime(), CAMERA_MSG_VIDEO_FRAME, mPreviewHeap->mBuffers[offset], rdata);
3087 Mutex::Autolock rLock(&mRecordFrameLock);
3088 if (mReleasedRecordingFrame != true) {
3089 LOGV("block waiting for frame release");
3090 mRecordWait.wait(mRecordFrameLock);
3091 LOGV("frame released, continuing");
3092 }
3093 mReleasedRecordingFrame = false;
3094 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003095 }
3096 mInPreviewCallback = false;
3097
3098// LOGV("receivePreviewFrame X");
3099}
3100
Sravankb4f5f1c2010-01-21 11:06:17 +05303101
3102bool QualcommCameraHardware::initRecord()
3103{
3104 LOGV("initREcord E");
3105
3106 mRecordFrameSize = (mDimension.video_width * mDimension.video_height *3)/2;
3107 mRecordHeap = new PmemPool("/dev/pmem_adsp",
3108 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
3109 mCameraControlFd,
3110 MSM_PMEM_VIDEO,
3111 mRecordFrameSize,
3112 kRecordBufferCount,
3113 mRecordFrameSize,
3114 "record");
3115 if (!mRecordHeap->initialized()) {
3116 mRecordHeap.clear();
3117 LOGE("initRecord X: could not initialize record heap.");
3118 return false;
3119 }
3120 for (int cnt = 0; cnt < kRecordBufferCount; cnt++) {
3121 recordframes[cnt].fd = mRecordHeap->mHeap->getHeapID();
3122 recordframes[cnt].buffer =
3123 (uint32_t)mRecordHeap->mHeap->base() + mRecordHeap->mAlignedBufferSize * cnt;
3124 recordframes[cnt].y_off = 0;
3125 recordframes[cnt].cbcr_off = mDimension.video_width * mDimension.video_height;
3126 recordframes[cnt].path = OUTPUT_TYPE_V;
3127
3128 LOGV ("initRecord : record heap , video buffers buffer=%lu fd=%d y_off=%d cbcr_off=%d \n",
3129 (unsigned long)recordframes[cnt].buffer, recordframes[cnt].fd, recordframes[cnt].y_off,
3130 recordframes[cnt].cbcr_off);
3131 }
3132
3133 // initial setup : buffers 1,2,3 with kernel , 4 with camframe , 5,6,7,8 in free Q
3134 // flush the busy Q
3135 cam_frame_flush_video();
3136
Mohan Kandra156d0ac2010-01-25 16:59:17 -08003137 mVideoThreadWaitLock.lock();
3138 while (mVideoThreadRunning) {
3139 LOGV("initRecord: waiting for old video thread to complete.");
3140 mVideoThreadWait.wait(mVideoThreadWaitLock);
3141 LOGV("initRecord : old video thread completed.");
3142 }
3143 mVideoThreadWaitLock.unlock();
3144
Sravankdf7a9202010-02-08 15:02:51 +05303145 // flush free queue and add 5,6,7,8 buffers.
3146 LINK_cam_frame_flush_free_video();
3147 for(int i=ACTIVE_VIDEO_BUFFERS+1;i <kRecordBufferCount; i++)
3148 LINK_camframe_free_video(&recordframes[i]);
Sravankb4f5f1c2010-01-21 11:06:17 +05303149 LOGV("initREcord X");
3150
3151 return true;
3152}
3153
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003154status_t QualcommCameraHardware::startRecording()
3155{
3156 LOGV("startRecording E");
Sravankb4f5f1c2010-01-21 11:06:17 +05303157 int ret;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003158 Mutex::Autolock l(&mLock);
3159 mReleasedRecordingFrame = false;
Sravankb4f5f1c2010-01-21 11:06:17 +05303160 if( (ret=startPreviewInternal())== NO_ERROR){
Mohan Kandraf1ebf982010-02-02 15:25:43 -08003161 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05303162 LOGV(" in startREcording : calling native_start_recording");
3163 native_start_recording(mCameraControlFd);
3164 recordingState = 1;
Sravankdf7a9202010-02-08 15:02:51 +05303165 // Start video thread and wait for busy frames to be encoded, this thread
3166 // should be closed in stopRecording
3167 mVideoThreadWaitLock.lock();
3168 mVideoThreadExit = 0;
3169 pthread_attr_t attr;
3170 pthread_attr_init(&attr);
3171 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
3172 mVideoThreadRunning = pthread_create(&mVideoThread,
3173 &attr,
3174 video_thread,
3175 NULL);
3176 mVideoThreadWaitLock.unlock();
3177 // Remove the left out frames in busy Q and them in free Q.
3178 LOGV("frames in busy Q = %d", g_busy_frame_queue.num_of_frames);
3179 while((g_busy_frame_queue.num_of_frames) >0){
3180 msm_frame* vframe = cam_frame_get_video ();
3181 LINK_camframe_free_video(vframe);
3182 }
3183 LOGV("frames in busy Q = %d after deQueing", g_busy_frame_queue.num_of_frames);
Sravankb4f5f1c2010-01-21 11:06:17 +05303184 }
3185 }
3186 return ret;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003187}
3188
3189void QualcommCameraHardware::stopRecording()
3190{
3191 LOGV("stopRecording: E");
3192 Mutex::Autolock l(&mLock);
3193 {
3194 mRecordFrameLock.lock();
3195 mReleasedRecordingFrame = true;
3196 mRecordWait.signal();
3197 mRecordFrameLock.unlock();
3198
Sravankdf7a9202010-02-08 15:02:51 +05303199 if(mDataCallback && !(mCurrentTarget == TARGET_QSD8250) &&
3200 (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003201 LOGV("stopRecording: X, preview still in progress");
3202 return;
3203 }
3204 }
Sravankb4f5f1c2010-01-21 11:06:17 +05303205 // If output2 enabled, exit video thread, invoke stop recording ioctl
Mohan Kandraf1ebf982010-02-02 15:25:43 -08003206 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05303207 mVideoThreadWaitLock.lock();
3208 mVideoThreadExit = 1;
3209 mVideoThreadWaitLock.unlock();
3210 native_stop_recording(mCameraControlFd);
3211 }
3212 else // for other targets where output2 is not enabled
3213 stopPreviewInternal();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003214
Sravankb4f5f1c2010-01-21 11:06:17 +05303215 recordingState = 0; // recording not started
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003216 LOGV("stopRecording: X");
3217}
3218
3219void QualcommCameraHardware::releaseRecordingFrame(
3220 const sp<IMemory>& mem __attribute__((unused)))
3221{
3222 LOGV("releaseRecordingFrame E");
3223 Mutex::Autolock rLock(&mRecordFrameLock);
3224 mReleasedRecordingFrame = true;
3225 mRecordWait.signal();
Sravankb4f5f1c2010-01-21 11:06:17 +05303226
3227 // Ff 7x30 : add the frame to the free camframe queue
Mohan Kandraf1ebf982010-02-02 15:25:43 -08003228 if( (mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05303229 ssize_t offset;
3230 size_t size;
3231 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
3232 msm_frame* releaseframe = NULL;
3233 LOGV(" in release recording frame : heap base %d offset %d buffer %d ", heap->base(), offset, heap->base() + offset );
3234 int cnt;
3235 for (cnt = 0; cnt < kRecordBufferCount; cnt++) {
3236 if((unsigned int)recordframes[cnt].buffer == (unsigned int)(heap->base()+ offset)){
3237 LOGV("in release recording frame found match , releasing buffer %d", (unsigned int)recordframes[cnt].buffer);
3238 releaseframe = &recordframes[cnt];
3239 break;
3240 }
3241 }
3242 if(cnt < kRecordBufferCount) {
3243 // do this only if frame thread is running
3244 mFrameThreadWaitLock.lock();
3245 if(mFrameThreadRunning )
3246 LINK_camframe_free_video(releaseframe);
3247
3248 mFrameThreadWaitLock.unlock();
3249 } else {
3250 LOGE("in release recordingframe XXXXX error , buffer not found");
3251 for (int i=0; i< kRecordBufferCount; i++) {
3252 LOGE(" recordframes[%d].buffer = %d", i, (unsigned int)recordframes[i].buffer);
3253 }
3254 }
3255 }
3256
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003257 LOGV("releaseRecordingFrame X");
3258}
3259
3260bool QualcommCameraHardware::recordingEnabled()
3261{
3262 return mCameraRunning && mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME);
3263}
3264
3265void QualcommCameraHardware::notifyShutter(common_crop_t *crop)
3266{
3267 mShutterLock.lock();
3268 image_rect_type size;
3269
3270 if (mShutterPending && mNotifyCallback && (mMsgEnabled & CAMERA_MSG_SHUTTER)) {
3271 LOGV("out2_w=%d, out2_h=%d, in2_w=%d, in2_h=%d",
3272 crop->out2_w, crop->out2_h, crop->in2_w, crop->in2_h);
3273 LOGV("out1_w=%d, out1_h=%d, in1_w=%d, in1_h=%d",
3274 crop->out1_w, crop->out1_h, crop->in1_w, crop->in1_h);
3275
3276 // To workaround a bug in MDP which happens if either
3277 // dimension > 2048, we display the thumbnail instead.
3278 mDisplayHeap = mRawHeap;
3279 if (crop->in1_w == 0 || crop->in1_h == 0) {
3280 // Full size
3281 size.width = mDimension.picture_width;
3282 size.height = mDimension.picture_height;
3283 if (size.width > 2048 || size.height > 2048) {
3284 size.width = mDimension.ui_thumbnail_width;
3285 size.height = mDimension.ui_thumbnail_height;
3286 mDisplayHeap = mThumbnailHeap;
3287 }
3288 } else {
3289 // Cropped
3290 size.width = crop->in2_w & ~1;
3291 size.height = crop->in2_h & ~1;
3292 if (size.width > 2048 || size.height > 2048) {
3293 size.width = crop->in1_w & ~1;
3294 size.height = crop->in1_h & ~1;
3295 mDisplayHeap = mThumbnailHeap;
3296 }
3297 }
3298
3299 mNotifyCallback(CAMERA_MSG_SHUTTER, (int32_t)&size, 0,
3300 mCallbackCookie);
3301 mShutterPending = false;
3302 }
3303 mShutterLock.unlock();
3304}
3305
3306static void receive_shutter_callback(common_crop_t *crop)
3307{
3308 LOGV("receive_shutter_callback: E");
3309 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
3310 if (obj != 0) {
3311 obj->notifyShutter(crop);
3312 }
3313 LOGV("receive_shutter_callback: X");
3314}
3315
3316// Crop the picture in place.
3317static void crop_yuv420(uint32_t width, uint32_t height,
3318 uint32_t cropped_width, uint32_t cropped_height,
3319 uint8_t *image)
3320{
3321 uint32_t i, x, y;
3322 uint8_t* chroma_src, *chroma_dst;
3323
3324 // Calculate the start position of the cropped area.
3325 x = (width - cropped_width) / 2;
3326 y = (height - cropped_height) / 2;
3327 x &= ~1;
3328 y &= ~1;
3329
3330 // Copy luma component.
3331 for(i = 0; i < cropped_height; i++)
3332 memcpy(image + i * cropped_width,
3333 image + width * (y + i) + x,
3334 cropped_width);
3335
3336 chroma_src = image + width * height;
3337 chroma_dst = image + cropped_width * cropped_height;
3338
3339 // Copy chroma components.
3340 cropped_height /= 2;
3341 y /= 2;
3342 for(i = 0; i < cropped_height; i++)
3343 memcpy(chroma_dst + i * cropped_width,
3344 chroma_src + width * (y + i) + x,
3345 cropped_width);
3346}
3347
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08003348
3349void QualcommCameraHardware::receiveRawSnapshot(){
3350 LOGV("receiveRawSnapshot E");
3351
3352 Mutex::Autolock cbLock(&mCallbackLock);
3353
3354 notifyShutter(&mCrop);
3355
3356 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
3357
3358 if(native_get_picture(mCameraControlFd, &mCrop) == false) {
3359 LOGE("receiveRawSnapshot X: native_get_picture failed!");
3360 return;
3361 }
3362
3363 //Create a Ashmem heap to copy data from PMem heap for application layer
3364 if(mRawSnapshotAshmemHeap != NULL){
3365 LOGV("receiveRawSnapshot: clearing old mRawSnapShotAshmemHeap.");
3366 mRawSnapshotAshmemHeap.clear();
3367 }
3368 mRawSnapshotAshmemHeap = new AshmemPool(
3369 mRawSnapShotPmemHeap->mBufferSize,
3370 mRawSnapShotPmemHeap->mNumBuffers,
3371 mRawSnapShotPmemHeap->mFrameSize,
3372 "raw ashmem snapshot camera"
3373 );
3374
3375 if(!mRawSnapshotAshmemHeap->initialized()){
3376 LOGE("receiveRawSnapshot X: error initializing mRawSnapshotHeap");
3377 deinitRawSnapshot();
3378 return;
3379 }
3380
3381 memcpy(mRawSnapshotAshmemHeap->mHeap->base(),
3382 mRawSnapShotPmemHeap->mHeap->base(),
3383 mRawSnapShotPmemHeap->mHeap->getSize());
3384
3385 mDataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mRawSnapshotAshmemHeap->mBuffers[0],
3386 mCallbackCookie);
3387
3388 }
3389
3390 //cleanup
3391 deinitRawSnapshot();
3392
3393 LOGV("receiveRawSnapshot X");
3394}
3395
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003396void QualcommCameraHardware::receiveRawPicture()
3397{
3398 LOGV("receiveRawPicture: E");
3399
3400 Mutex::Autolock cbLock(&mCallbackLock);
3401 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_RAW_IMAGE)) {
3402 if(native_get_picture(mCameraControlFd, &mCrop) == false) {
3403 LOGE("getPicture failed!");
3404 return;
3405 }
3406 mCrop.in1_w &= ~1;
3407 mCrop.in1_h &= ~1;
3408 mCrop.in2_w &= ~1;
3409 mCrop.in2_h &= ~1;
3410
3411 // By the time native_get_picture returns, picture is taken. Call
3412 // shutter callback if cam config thread has not done that.
3413 notifyShutter(&mCrop);
3414
3415 // Crop the image if zoomed.
3416 if (mCrop.in2_w != 0 && mCrop.in2_h != 0) {
3417 crop_yuv420(mCrop.out2_w, mCrop.out2_h, mCrop.in2_w, mCrop.in2_h,
3418 (uint8_t *)mRawHeap->mHeap->base());
3419 crop_yuv420(mCrop.out1_w, mCrop.out1_h, mCrop.in1_w, mCrop.in1_h,
3420 (uint8_t *)mThumbnailHeap->mHeap->base());
3421 // We do not need jpeg encoder to upscale the image. Set the new
3422 // dimension for encoder.
3423 mDimension.orig_picture_dx = mCrop.in2_w;
3424 mDimension.orig_picture_dy = mCrop.in2_h;
3425 mDimension.thumbnail_width = mCrop.in1_w;
3426 mDimension.thumbnail_height = mCrop.in1_h;
3427 memset(&mCrop, 0, sizeof(mCrop));
3428 }
3429
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003430 if( mUseOverlay && (mOverlay != NULL) ) {
3431 mOverlay->setFd(mPostViewHeap->mHeap->getHeapID());
3432 if( zoomCropInfo.w !=0 && zoomCropInfo.h !=0) {
3433 LOGD(" zoomCropInfo non-zero, setting crop ");
3434 mOverlay->setCrop(zoomCropInfo.x, zoomCropInfo.y,
3435 zoomCropInfo.w, zoomCropInfo.h);
3436 }
3437 LOGD(" Queueing Postview for display ");
3438 mOverlay->queueBuffer((void *)0);
3439 }
3440
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003441 mDataCallback(CAMERA_MSG_RAW_IMAGE, mDisplayHeap->mBuffers[0],
3442 mCallbackCookie);
3443 }
3444 else LOGV("Raw-picture callback was canceled--skipping.");
3445
3446 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
3447 mJpegSize = 0;
3448 if (LINK_jpeg_encoder_init()) {
3449 if(native_jpeg_encode()) {
3450 LOGV("receiveRawPicture: X (success)");
3451 return;
3452 }
3453 LOGE("jpeg encoding failed");
3454 }
3455 else LOGE("receiveRawPicture X: jpeg_encoder_init failed.");
3456 }
3457 else LOGV("JPEG callback is NULL, not encoding image.");
3458 deinitRaw();
3459 LOGV("receiveRawPicture: X");
3460}
3461
3462void QualcommCameraHardware::receiveJpegPictureFragment(
3463 uint8_t *buff_ptr, uint32_t buff_size)
3464{
3465 uint32_t remaining = mJpegHeap->mHeap->virtualSize();
3466 remaining -= mJpegSize;
3467 uint8_t *base = (uint8_t *)mJpegHeap->mHeap->base();
3468
3469 LOGV("receiveJpegPictureFragment size %d", buff_size);
3470 if (buff_size > remaining) {
3471 LOGE("receiveJpegPictureFragment: size %d exceeds what "
3472 "remains in JPEG heap (%d), truncating",
3473 buff_size,
3474 remaining);
3475 buff_size = remaining;
3476 }
3477 memcpy(base + mJpegSize, buff_ptr, buff_size);
3478 mJpegSize += buff_size;
3479}
3480
3481void QualcommCameraHardware::receiveJpegPicture(void)
3482{
3483 LOGV("receiveJpegPicture: E image (%d uint8_ts out of %d)",
3484 mJpegSize, mJpegHeap->mBufferSize);
3485 Mutex::Autolock cbLock(&mCallbackLock);
3486
3487 int index = 0, rc;
3488
3489 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
3490 // The reason we do not allocate into mJpegHeap->mBuffers[offset] is
3491 // that the JPEG image's size will probably change from one snapshot
3492 // to the next, so we cannot reuse the MemoryBase object.
3493 sp<MemoryBase> buffer = new
3494 MemoryBase(mJpegHeap->mHeap,
3495 index * mJpegHeap->mBufferSize +
3496 0,
3497 mJpegSize);
3498 mDataCallback(CAMERA_MSG_COMPRESSED_IMAGE, buffer, mCallbackCookie);
3499 buffer = NULL;
3500 }
3501 else LOGV("JPEG callback was cancelled--not delivering image.");
3502
3503 LINK_jpeg_encoder_join();
3504 deinitRaw();
3505
3506 LOGV("receiveJpegPicture: X callback done.");
3507}
3508
3509bool QualcommCameraHardware::previewEnabled()
3510{
3511 return mCameraRunning && mDataCallback && (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME);
3512}
3513
3514status_t QualcommCameraHardware::setPreviewSize(const CameraParameters& params)
3515{
3516 int width, height;
3517 params.getPreviewSize(&width, &height);
3518 LOGV("requested preview size %d x %d", width, height);
3519
3520 // Validate the preview size
3521 for (size_t i = 0; i < PREVIEW_SIZE_COUNT; ++i) {
3522 if (width == preview_sizes[i].width
3523 && height == preview_sizes[i].height) {
3524 mParameters.setPreviewSize(width, height);
3525 mDimension.display_width = width;
3526 mDimension.display_height = height;
3527 return NO_ERROR;
3528 }
3529 }
3530 LOGE("Invalid preview size requested: %dx%d", width, height);
3531 return BAD_VALUE;
3532}
3533
3534status_t QualcommCameraHardware::setPictureSize(const CameraParameters& params)
3535{
3536 int width, height;
3537 params.getPictureSize(&width, &height);
3538 LOGV("requested picture size %d x %d", width, height);
3539
3540 // Validate the picture size
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -08003541 for (int i = 0; i < supportedPictureSizesCount; ++i) {
3542 if (width == picture_sizes_ptr[i].width
3543 && height == picture_sizes_ptr[i].height) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003544 mParameters.setPictureSize(width, height);
3545 mDimension.picture_width = width;
3546 mDimension.picture_height = height;
3547 return NO_ERROR;
3548 }
3549 }
3550 LOGE("Invalid picture size requested: %dx%d", width, height);
3551 return BAD_VALUE;
3552}
3553
3554status_t QualcommCameraHardware::setJpegQuality(const CameraParameters& params) {
3555 status_t rc = NO_ERROR;
3556 int quality = params.getInt(CameraParameters::KEY_JPEG_QUALITY);
3557 if (quality > 0 && quality <= 100) {
3558 mParameters.set(CameraParameters::KEY_JPEG_QUALITY, quality);
3559 } else {
3560 LOGE("Invalid jpeg quality=%d", quality);
3561 rc = BAD_VALUE;
3562 }
3563
3564 quality = params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY);
3565 if (quality > 0 && quality <= 100) {
3566 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, quality);
3567 } else {
3568 LOGE("Invalid jpeg thumbnail quality=%d", quality);
3569 rc = BAD_VALUE;
3570 }
3571 return rc;
3572}
3573
3574status_t QualcommCameraHardware::setEffect(const CameraParameters& params)
3575{
3576 const char *str = params.get(CameraParameters::KEY_EFFECT);
3577 if (str != NULL) {
3578 int32_t value = attr_lookup(effects, sizeof(effects) / sizeof(str_map), str);
3579 if (value != NOT_FOUND) {
Mohan Kandra93f1bfb2009-12-15 16:55:33 -08003580 if(!strcmp(sensorType->name, "2mp") && (value != CAMERA_EFFECT_OFF)
3581 &&(value != CAMERA_EFFECT_MONO) && (value != CAMERA_EFFECT_NEGATIVE)
3582 &&(value != CAMERA_EFFECT_SOLARIZE) && (value != CAMERA_EFFECT_SEPIA)) {
3583 LOGE("Special effect parameter is not supported for this sensor");
3584 return NO_ERROR;
3585 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003586 mParameters.set(CameraParameters::KEY_EFFECT, str);
3587 bool ret = native_set_parm(CAMERA_SET_PARM_EFFECT, sizeof(value),
3588 (void *)&value);
3589 return ret ? NO_ERROR : UNKNOWN_ERROR;
3590 }
3591 }
3592 LOGE("Invalid effect value: %s", (str == NULL) ? "NULL" : str);
3593 return BAD_VALUE;
3594}
3595
Apurva Rajguru55562b02009-12-03 12:25:35 -08003596status_t QualcommCameraHardware::setAutoExposure(const CameraParameters& params)
3597{
Mohan Kandra93f1bfb2009-12-15 16:55:33 -08003598 if(!strcmp(sensorType->name, "2mp")) {
3599 LOGE("Auto Exposure not supported for this sensor");
3600 return NO_ERROR;
3601 }
Apurva Rajguru55562b02009-12-03 12:25:35 -08003602 const char *str = params.get(CameraParameters::KEY_AUTO_EXPOSURE);
3603 if (str != NULL) {
3604 int32_t value = attr_lookup(autoexposure, sizeof(autoexposure) / sizeof(str_map), str);
3605 if (value != NOT_FOUND) {
3606 mParameters.set(CameraParameters::KEY_AUTO_EXPOSURE, str);
3607 bool ret = native_set_parm(CAMERA_SET_PARM_EXPOSURE, sizeof(value),
3608 (void *)&value);
3609 return ret ? NO_ERROR : UNKNOWN_ERROR;
3610 }
3611 }
3612 LOGE("Invalid auto exposure value: %s", (str == NULL) ? "NULL" : str);
3613 return BAD_VALUE;
3614}
3615
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003616status_t QualcommCameraHardware::setSharpness(const CameraParameters& params)
3617{
3618 if(!strcmp(sensorType->name, "2mp")) {
3619 LOGE("Sharpness not supported for this sensor");
3620 return NO_ERROR;
3621 }
3622 int sharpness = params.getInt(CameraParameters::KEY_SHARPNESS);
3623 if((sharpness < CAMERA_MIN_SHARPNESS
3624 || sharpness > CAMERA_MAX_SHARPNESS))
3625 return UNKNOWN_ERROR;
Srinivasan Kannan551fd262010-01-14 17:48:30 -08003626
3627 LOGV("setting sharpness %d", sharpness);
3628 mParameters.set(CameraParameters::KEY_SHARPNESS, sharpness);
3629 bool ret = native_set_parm(CAMERA_SET_PARM_SHARPNESS, sizeof(sharpness),
3630 (void *)&sharpness);
3631 return ret ? NO_ERROR : UNKNOWN_ERROR;
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003632}
3633
3634status_t QualcommCameraHardware::setContrast(const CameraParameters& params)
3635{
3636 if(!strcmp(sensorType->name, "2mp")) {
3637 LOGE("Contrast not supported for this sensor");
3638 return NO_ERROR;
3639 }
3640 int contrast = params.getInt(CameraParameters::KEY_CONTRAST);
3641 if((contrast < CAMERA_MIN_CONTRAST)
3642 || (contrast > CAMERA_MAX_CONTRAST))
3643 return UNKNOWN_ERROR;
Srinivasan Kannan551fd262010-01-14 17:48:30 -08003644
3645 LOGV("setting contrast %d", contrast);
3646 mParameters.set(CameraParameters::KEY_CONTRAST, contrast);
3647 bool ret = native_set_parm(CAMERA_SET_PARM_CONTRAST, sizeof(contrast),
3648 (void *)&contrast);
3649 return ret ? NO_ERROR : UNKNOWN_ERROR;
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003650}
3651
3652status_t QualcommCameraHardware::setSaturation(const CameraParameters& params)
3653{
3654 if(!strcmp(sensorType->name, "2mp")) {
3655 LOGE("Saturation not supported for this sensor");
3656 return NO_ERROR;
3657 }
Srinivasan Kannan551fd262010-01-14 17:48:30 -08003658
Kiran Kumar H Nf87cf862010-01-27 14:34:34 -08003659 const char *str = params.get(CameraParameters::KEY_EFFECT);
3660 int32_t value = attr_lookup(effects, sizeof(effects) / sizeof(str_map), str);
3661
3662 if( (value != CAMERA_EFFECT_MONO) && (value != CAMERA_EFFECT_NEGATIVE)
3663 && (value != CAMERA_EFFECT_AQUA) && (value != CAMERA_EFFECT_SEPIA)) {
3664
3665 int saturation = params.getInt(CameraParameters::KEY_SATURATION);
3666 if((saturation < CAMERA_MIN_SATURATION)
3667 || (saturation > CAMERA_MAX_SATURATION))
3668 return UNKNOWN_ERROR;
3669
3670 LOGV("setting saturation %d", saturation);
3671 mParameters.set(CameraParameters::KEY_SATURATION, saturation);
3672 bool ret = native_set_parm(CAMERA_SET_PARM_SATURATION, sizeof(saturation),
3673 (void *)&saturation);
3674 return ret ? NO_ERROR : UNKNOWN_ERROR;
3675 } else {
3676 LOGE(" Saturation value will not be set " \
3677 "when the effect selected is %s", str);
3678 return NO_ERROR;
3679 }
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003680}
3681
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303682status_t QualcommCameraHardware::setBrightness(const CameraParameters& params) {
3683 int brightness = params.getInt("luma-adaptation");
3684 if (mBrightness != brightness) {
3685 LOGV(" new brightness value : %d ", brightness);
3686 mBrightness = brightness;
3687
3688 bool ret = native_set_parm(CAMERA_SET_PARM_BRIGHTNESS, sizeof(mBrightness),
3689 (void *)&mBrightness);
3690 return ret ? NO_ERROR : UNKNOWN_ERROR;
3691 } else {
3692 return NO_ERROR;
3693 }
3694}
3695
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003696status_t QualcommCameraHardware::setWhiteBalance(const CameraParameters& params)
3697{
3698 const char *str = params.get(CameraParameters::KEY_WHITE_BALANCE);
3699 if (str != NULL) {
3700 int32_t value = attr_lookup(whitebalance, sizeof(whitebalance) / sizeof(str_map), str);
3701 if (value != NOT_FOUND) {
3702 mParameters.set(CameraParameters::KEY_WHITE_BALANCE, str);
3703 bool ret = native_set_parm(CAMERA_SET_PARM_WB, sizeof(value),
3704 (void *)&value);
3705 return ret ? NO_ERROR : UNKNOWN_ERROR;
3706 }
3707 }
3708 LOGE("Invalid whitebalance value: %s", (str == NULL) ? "NULL" : str);
3709 return BAD_VALUE;
3710}
3711
3712status_t QualcommCameraHardware::setFlash(const CameraParameters& params)
3713{
3714 if (!mSensorInfo.flash_enabled) {
3715 LOGV("%s: flash not supported", __FUNCTION__);
3716 return NO_ERROR;
3717 }
3718
3719 const char *str = params.get(CameraParameters::KEY_FLASH_MODE);
3720 if (str != NULL) {
3721 int32_t value = attr_lookup(flash, sizeof(flash) / sizeof(str_map), str);
3722 if (value != NOT_FOUND) {
3723 mParameters.set(CameraParameters::KEY_FLASH_MODE, str);
3724 bool ret = native_set_parm(CAMERA_SET_PARM_LED_MODE,
3725 sizeof(value), (void *)&value);
3726 return ret ? NO_ERROR : UNKNOWN_ERROR;
3727 }
3728 }
3729 LOGE("Invalid flash mode value: %s", (str == NULL) ? "NULL" : str);
3730 return BAD_VALUE;
3731}
3732
3733status_t QualcommCameraHardware::setAntibanding(const CameraParameters& params)
3734{
Srinivasan Kannan2229d272010-01-05 14:58:28 -08003735 if(!strcmp(sensorType->name, "2mp")) {
3736 LOGE("Parameter AntiBanding is not supported for this sensor");
3737 return NO_ERROR;
3738 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003739 const char *str = params.get(CameraParameters::KEY_ANTIBANDING);
3740 if (str != NULL) {
3741 int value = (camera_antibanding_type)attr_lookup(
3742 antibanding, sizeof(antibanding) / sizeof(str_map), str);
3743 if (value != NOT_FOUND) {
3744 camera_antibanding_type temp = (camera_antibanding_type) value;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003745 mParameters.set(CameraParameters::KEY_ANTIBANDING, str);
Srinivasan Kannan2229d272010-01-05 14:58:28 -08003746 bool ret;
3747 if (temp == CAMERA_ANTIBANDING_AUTO) {
3748 ret = native_set_parm(CAMERA_ENABLE_AFD,
3749 0, NULL);
3750 } else {
3751 ret = native_set_parm(CAMERA_SET_PARM_ANTIBANDING,
3752 sizeof(camera_antibanding_type), (void *)&temp);
3753 }
3754 return ret ? NO_ERROR : UNKNOWN_ERROR;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003755 }
3756 }
3757 LOGE("Invalid antibanding value: %s", (str == NULL) ? "NULL" : str);
3758 return BAD_VALUE;
3759}
3760
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303761status_t QualcommCameraHardware::setLensshadeValue(const CameraParameters& params)
3762{
Mohan Kandra93f1bfb2009-12-15 16:55:33 -08003763 if(!strcmp(sensorType->name, "2mp")) {
3764 LOGE("Parameter Rolloff is not supported for this sensor");
3765 return NO_ERROR;
3766 }
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303767 const char *str = params.get(CameraParameters::KEY_LENSSHADE);
3768 if (str != NULL) {
3769 int value = attr_lookup(lensshade,
3770 sizeof(lensshade) / sizeof(str_map), str);
3771 if (value != NOT_FOUND) {
3772 int8_t temp = (int8_t)value;
3773 mParameters.set(CameraParameters::KEY_LENSSHADE, str);
3774 native_set_parm(CAMERA_SET_PARM_ROLLOFF, sizeof(int8_t), (void *)&temp);
3775 return NO_ERROR;
3776 }
3777 }
3778 LOGE("Invalid lensShade value: %s", (str == NULL) ? "NULL" : str);
3779 return BAD_VALUE;
3780}
3781
3782status_t QualcommCameraHardware::setISOValue(const CameraParameters& params) {
3783 const char *str = params.get(CameraParameters::KEY_ISO_MODE);
3784 if (str != NULL) {
3785 int value = (camera_iso_mode_type)attr_lookup(
3786 iso, sizeof(iso) / sizeof(str_map), str);
3787 if (value != NOT_FOUND) {
3788 camera_iso_mode_type temp = (camera_iso_mode_type) value;
3789 mParameters.set(CameraParameters::KEY_ISO_MODE, str);
3790 native_set_parm(CAMERA_SET_PARM_ISO, sizeof(camera_iso_mode_type), (void *)&temp);
3791 return NO_ERROR;
3792 }
3793 }
3794 LOGE("Invalid Iso value: %s", (str == NULL) ? "NULL" : str);
3795 return BAD_VALUE;
3796}
3797
3798
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003799status_t QualcommCameraHardware::setGpsLocation(const CameraParameters& params)
3800{
3801 const char *latitude = params.get(CameraParameters::KEY_GPS_LATITUDE);
3802 if (latitude) {
3803 mParameters.set(CameraParameters::KEY_GPS_LATITUDE, latitude);
3804 }
3805
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08003806 const char *latitudeRef = params.get(CameraParameters::KEY_GPS_LATITUDE_REF);
3807 if (latitudeRef) {
3808 mParameters.set(CameraParameters::KEY_GPS_LATITUDE_REF, latitudeRef);
3809 }
3810
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003811 const char *longitude = params.get(CameraParameters::KEY_GPS_LONGITUDE);
3812 if (longitude) {
3813 mParameters.set(CameraParameters::KEY_GPS_LONGITUDE, longitude);
3814 }
3815
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08003816 const char *longitudeRef = params.get(CameraParameters::KEY_GPS_LONGITUDE_REF);
3817 if (longitudeRef) {
3818 mParameters.set(CameraParameters::KEY_GPS_LONGITUDE_REF, longitudeRef);
3819 }
3820
3821 const char *altitudeRef = params.get(CameraParameters::KEY_GPS_ALTITUDE_REF);
3822 if (altitudeRef) {
3823 mParameters.set(CameraParameters::KEY_GPS_ALTITUDE_REF, altitudeRef);
3824 }
3825
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003826 const char *altitude = params.get(CameraParameters::KEY_GPS_ALTITUDE);
3827 if (altitude) {
3828 mParameters.set(CameraParameters::KEY_GPS_ALTITUDE, altitude);
3829 }
3830
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08003831 const char *status = params.get(CameraParameters::KEY_GPS_STATUS);
3832 if (status) {
3833 mParameters.set(CameraParameters::KEY_GPS_STATUS, status);
3834 }
3835
3836 const char *dateTime = params.get(CameraParameters::KEY_EXIF_DATETIME);
3837 if (dateTime) {
3838 mParameters.set(CameraParameters::KEY_EXIF_DATETIME, dateTime);
3839 }
3840
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003841 const char *timestamp = params.get(CameraParameters::KEY_GPS_TIMESTAMP);
3842 if (timestamp) {
3843 mParameters.set(CameraParameters::KEY_GPS_TIMESTAMP, timestamp);
3844 }
3845 return NO_ERROR;
3846}
3847
3848status_t QualcommCameraHardware::setRotation(const CameraParameters& params)
3849{
3850 status_t rc = NO_ERROR;
3851 int rotation = params.getInt(CameraParameters::KEY_ROTATION);
3852 if (rotation != NOT_FOUND) {
3853 if (rotation == 0 || rotation == 90 || rotation == 180
3854 || rotation == 270) {
3855 mParameters.set(CameraParameters::KEY_ROTATION, rotation);
3856 } else {
3857 LOGE("Invalid rotation value: %d", rotation);
3858 rc = BAD_VALUE;
3859 }
3860 }
3861 return rc;
3862}
3863
3864status_t QualcommCameraHardware::setZoom(const CameraParameters& params)
3865{
3866 status_t rc = NO_ERROR;
3867 // No matter how many different zoom values the driver can provide, HAL
3868 // provides applictations the same number of zoom levels. The maximum driver
3869 // zoom value depends on sensor output (VFE input) and preview size (VFE
3870 // output) because VFE can only crop and cannot upscale. If the preview size
3871 // is bigger, the maximum zoom ratio is smaller. However, we want the
3872 // zoom ratio of each zoom level is always the same whatever the preview
3873 // size is. Ex: zoom level 1 is always 1.2x, zoom level 2 is 1.44x, etc. So,
3874 // we need to have a fixed maximum zoom value and do read it from the
3875 // driver.
Mohan Kandra284966d2010-01-05 13:39:15 -08003876 static const int ZOOM_STEP = 1;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003877 int32_t zoom_level = params.getInt("zoom");
3878
Mohan Kandra284966d2010-01-05 13:39:15 -08003879 LOGV("Set zoom=%d", zoom_level);
3880 if(zoom_level >= 0 && zoom_level <= mMaxZoom) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003881 mParameters.set("zoom", zoom_level);
3882 int32_t zoom_value = ZOOM_STEP * zoom_level;
3883 bool ret = native_set_parm(CAMERA_SET_PARM_ZOOM,
3884 sizeof(zoom_value), (void *)&zoom_value);
3885 rc = ret ? NO_ERROR : UNKNOWN_ERROR;
3886 } else {
3887 rc = BAD_VALUE;
3888 }
3889
3890 return rc;
3891}
3892
3893status_t QualcommCameraHardware::setFocusMode(const CameraParameters& params)
3894{
3895 const char *str = params.get(CameraParameters::KEY_FOCUS_MODE);
3896 if (str != NULL) {
3897 int32_t value = attr_lookup(focus_modes,
3898 sizeof(focus_modes) / sizeof(str_map), str);
3899 if (value != NOT_FOUND) {
3900 mParameters.set(CameraParameters::KEY_FOCUS_MODE, str);
3901 // Focus step is reset to infinity when preview is started. We do
3902 // not need to do anything now.
3903 return NO_ERROR;
3904 }
3905 }
3906 LOGE("Invalid focus mode value: %s", (str == NULL) ? "NULL" : str);
3907 return BAD_VALUE;
3908}
3909
3910status_t QualcommCameraHardware::setOrientation(const CameraParameters& params)
3911{
3912 const char *str = params.get("orientation");
3913
3914 if (str != NULL) {
3915 if (strcmp(str, "portrait") == 0 || strcmp(str, "landscape") == 0) {
3916 // Camera service needs this to decide if the preview frames and raw
3917 // pictures should be rotated.
3918 mParameters.set("orientation", str);
3919 } else {
3920 LOGE("Invalid orientation value: %s", str);
3921 return BAD_VALUE;
3922 }
3923 }
3924 return NO_ERROR;
3925}
3926
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08003927status_t QualcommCameraHardware::setPictureFormat(const CameraParameters& params)
3928{
3929 const char * str = params.get(CameraParameters::KEY_PICTURE_FORMAT);
3930
3931 if(str != NULL){
3932 int32_t value = attr_lookup(picture_formats,
3933 sizeof(picture_formats) / sizeof(str_map), str);
3934 if(value != NOT_FOUND){
3935 mParameters.set(CameraParameters::KEY_PICTURE_FORMAT, str);
3936 } else {
3937 LOGE("Invalid Picture Format value: %s", str);
3938 return BAD_VALUE;
3939 }
3940 }
3941 return NO_ERROR;
3942}
3943
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003944QualcommCameraHardware::MemPool::MemPool(int buffer_size, int num_buffers,
3945 int frame_size,
3946 const char *name) :
3947 mBufferSize(buffer_size),
3948 mNumBuffers(num_buffers),
3949 mFrameSize(frame_size),
3950 mBuffers(NULL), mName(name)
3951{
3952 int page_size_minus_1 = getpagesize() - 1;
3953 mAlignedBufferSize = (buffer_size + page_size_minus_1) & (~page_size_minus_1);
3954}
3955
3956void QualcommCameraHardware::MemPool::completeInitialization()
3957{
3958 // If we do not know how big the frame will be, we wait to allocate
3959 // the buffers describing the individual frames until we do know their
3960 // size.
3961
3962 if (mFrameSize > 0) {
3963 mBuffers = new sp<MemoryBase>[mNumBuffers];
3964 for (int i = 0; i < mNumBuffers; i++) {
3965 mBuffers[i] = new
3966 MemoryBase(mHeap,
3967 i * mAlignedBufferSize,
3968 mFrameSize);
3969 }
3970 }
3971}
3972
3973QualcommCameraHardware::AshmemPool::AshmemPool(int buffer_size, int num_buffers,
3974 int frame_size,
3975 const char *name) :
3976 QualcommCameraHardware::MemPool(buffer_size,
3977 num_buffers,
3978 frame_size,
3979 name)
3980{
3981 LOGV("constructing MemPool %s backed by ashmem: "
3982 "%d frames @ %d uint8_ts, "
3983 "buffer size %d",
3984 mName,
3985 num_buffers, frame_size, buffer_size);
3986
3987 int page_mask = getpagesize() - 1;
3988 int ashmem_size = buffer_size * num_buffers;
3989 ashmem_size += page_mask;
3990 ashmem_size &= ~page_mask;
3991
3992 mHeap = new MemoryHeapBase(ashmem_size);
3993
3994 completeInitialization();
3995}
3996
3997static bool register_buf(int camfd,
3998 int size,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08003999 int frame_size,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004000 int pmempreviewfd,
4001 uint32_t offset,
4002 uint8_t *buf,
4003 int pmem_type,
4004 bool vfe_can_write,
4005 bool register_buffer = true);
4006
4007QualcommCameraHardware::PmemPool::PmemPool(const char *pmem_pool,
4008 int flags,
4009 int camera_control_fd,
4010 int pmem_type,
4011 int buffer_size, int num_buffers,
4012 int frame_size,
4013 const char *name) :
4014 QualcommCameraHardware::MemPool(buffer_size,
4015 num_buffers,
4016 frame_size,
4017 name),
4018 mPmemType(pmem_type),
4019 mCameraControlFd(dup(camera_control_fd))
4020{
4021 LOGV("constructing MemPool %s backed by pmem pool %s: "
4022 "%d frames @ %d bytes, buffer size %d",
4023 mName,
4024 pmem_pool, num_buffers, frame_size,
4025 buffer_size);
4026
4027 LOGV("%s: duplicating control fd %d --> %d",
4028 __FUNCTION__,
4029 camera_control_fd, mCameraControlFd);
4030
4031 // Make a new mmap'ed heap that can be shared across processes.
4032 // mAlignedBufferSize is already in 4k aligned. (do we need total size necessary to be in power of 2??)
4033 mAlignedSize = mAlignedBufferSize * num_buffers;
4034
4035 sp<MemoryHeapBase> masterHeap =
4036 new MemoryHeapBase(pmem_pool, mAlignedSize, flags);
4037
4038 if (masterHeap->getHeapID() < 0) {
4039 LOGE("failed to construct master heap for pmem pool %s", pmem_pool);
4040 masterHeap.clear();
4041 return;
4042 }
4043
4044 sp<MemoryHeapPmem> pmemHeap = new MemoryHeapPmem(masterHeap, flags);
4045 if (pmemHeap->getHeapID() >= 0) {
4046 pmemHeap->slap();
4047 masterHeap.clear();
4048 mHeap = pmemHeap;
4049 pmemHeap.clear();
4050
4051 mFd = mHeap->getHeapID();
4052 if (::ioctl(mFd, PMEM_GET_SIZE, &mSize)) {
4053 LOGE("pmem pool %s ioctl(PMEM_GET_SIZE) error %s (%d)",
4054 pmem_pool,
4055 ::strerror(errno), errno);
4056 mHeap.clear();
4057 return;
4058 }
4059
4060 LOGV("pmem pool %s ioctl(fd = %d, PMEM_GET_SIZE) is %ld",
4061 pmem_pool,
4062 mFd,
4063 mSize.len);
Mohan Kandra284966d2010-01-05 13:39:15 -08004064 LOGD("mBufferSize=%d, mAlignedBufferSize=%d\n", mBufferSize, mAlignedBufferSize);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004065 // Unregister preview buffers with the camera drivers. Allow the VFE to write
4066 // to all preview buffers except for the last one.
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08004067 // Only Register the preview, snapshot and thumbnail buffers with the kernel.
Mohan Kandrad9efed92010-01-15 19:08:39 -08004068 if( (strcmp("postview", mName) != 0) ){
4069 int num_buf = num_buffers;
4070 if(!strcmp("preview", mName)) num_buf = kPreviewBufferCount;
Brian Steuerb62adbd2010-02-02 14:47:08 -08004071 LOGD("num_buffers = %d", num_buf);
Mohan Kandrad9efed92010-01-15 19:08:39 -08004072 for (int cnt = 0; cnt < num_buf; ++cnt) {
Sravankb4f5f1c2010-01-21 11:06:17 +05304073 int active = 1;
4074 if(pmem_type == MSM_PMEM_VIDEO){
4075 active = (cnt<ACTIVE_VIDEO_BUFFERS);
4076 LOGV(" pmempool creating video buffers : active %d ", active);
4077 }
4078 else if (pmem_type == MSM_PMEM_PREVIEW){
4079 active = (cnt < (num_buf-1));
4080 }
Mohan Kandra284966d2010-01-05 13:39:15 -08004081 register_buf(mCameraControlFd,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004082 mBufferSize,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08004083 mFrameSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004084 mHeap->getHeapID(),
4085 mAlignedBufferSize * cnt,
4086 (uint8_t *)mHeap->base() + mAlignedBufferSize * cnt,
4087 pmem_type,
Sravankb4f5f1c2010-01-21 11:06:17 +05304088 active);
Mohan Kandra284966d2010-01-05 13:39:15 -08004089 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004090 }
4091
4092 completeInitialization();
4093 }
4094 else LOGE("pmem pool %s error: could not create master heap!",
4095 pmem_pool);
4096}
4097
4098QualcommCameraHardware::PmemPool::~PmemPool()
4099{
4100 LOGV("%s: %s E", __FUNCTION__, mName);
4101 if (mHeap != NULL) {
4102 // Unregister preview buffers with the camera drivers.
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08004103 // Only Unregister the preview, snapshot and thumbnail
4104 // buffers with the kernel.
Mohan Kandrad9efed92010-01-15 19:08:39 -08004105 if( (strcmp("postview", mName) != 0) ){
4106 int num_buffers = mNumBuffers;
4107 if(!strcmp("preview", mName)) num_buffers = kPreviewBufferCount;
4108 for (int cnt = 0; cnt < num_buffers; ++cnt) {
Mohan Kandra284966d2010-01-05 13:39:15 -08004109 register_buf(mCameraControlFd,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004110 mBufferSize,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08004111 mFrameSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004112 mHeap->getHeapID(),
4113 mAlignedBufferSize * cnt,
4114 (uint8_t *)mHeap->base() + mAlignedBufferSize * cnt,
4115 mPmemType,
4116 false,
4117 false /* unregister */);
Mohan Kandra284966d2010-01-05 13:39:15 -08004118 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004119 }
4120 }
4121 LOGV("destroying PmemPool %s: closing control fd %d",
4122 mName,
4123 mCameraControlFd);
4124 close(mCameraControlFd);
4125 LOGV("%s: %s X", __FUNCTION__, mName);
4126}
4127
4128QualcommCameraHardware::MemPool::~MemPool()
4129{
4130 LOGV("destroying MemPool %s", mName);
4131 if (mFrameSize > 0)
4132 delete [] mBuffers;
4133 mHeap.clear();
4134 LOGV("destroying MemPool %s completed", mName);
4135}
4136
4137static bool register_buf(int camfd,
4138 int size,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08004139 int frame_size,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004140 int pmempreviewfd,
4141 uint32_t offset,
4142 uint8_t *buf,
4143 int pmem_type,
4144 bool vfe_can_write,
4145 bool register_buffer)
4146{
4147 struct msm_pmem_info pmemBuf;
4148
4149 pmemBuf.type = pmem_type;
4150 pmemBuf.fd = pmempreviewfd;
4151 pmemBuf.offset = offset;
4152 pmemBuf.len = size;
4153 pmemBuf.vaddr = buf;
4154 pmemBuf.y_off = 0;
Srinivasan Kannanb36a4fe2010-01-29 19:34:09 -08004155
4156 if(pmem_type == MSM_PMEM_RAW_MAINIMG)
4157 pmemBuf.cbcr_off = 0;
4158 else
4159 pmemBuf.cbcr_off = PAD_TO_WORD(frame_size * 2 / 3);
4160
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004161 pmemBuf.active = vfe_can_write;
4162
4163 LOGV("register_buf: camfd = %d, reg = %d buffer = %p",
4164 camfd, !register_buffer, buf);
4165 if (ioctl(camfd,
4166 register_buffer ?
4167 MSM_CAM_IOCTL_REGISTER_PMEM :
4168 MSM_CAM_IOCTL_UNREGISTER_PMEM,
4169 &pmemBuf) < 0) {
4170 LOGE("register_buf: MSM_CAM_IOCTL_(UN)REGISTER_PMEM fd %d error %s",
4171 camfd,
4172 strerror(errno));
4173 return false;
4174 }
4175 return true;
4176}
4177
4178status_t QualcommCameraHardware::MemPool::dump(int fd, const Vector<String16>& args) const
4179{
4180 const size_t SIZE = 256;
4181 char buffer[SIZE];
4182 String8 result;
4183 snprintf(buffer, 255, "QualcommCameraHardware::AshmemPool::dump\n");
4184 result.append(buffer);
4185 if (mName) {
4186 snprintf(buffer, 255, "mem pool name (%s)\n", mName);
4187 result.append(buffer);
4188 }
4189 if (mHeap != 0) {
4190 snprintf(buffer, 255, "heap base(%p), size(%d), flags(%d), device(%s)\n",
4191 mHeap->getBase(), mHeap->getSize(),
4192 mHeap->getFlags(), mHeap->getDevice());
4193 result.append(buffer);
4194 }
4195 snprintf(buffer, 255,
4196 "buffer size (%d), number of buffers (%d), frame size(%d)",
4197 mBufferSize, mNumBuffers, mFrameSize);
4198 result.append(buffer);
4199 write(fd, result.string(), result.size());
4200 return NO_ERROR;
4201}
4202
4203static void receive_camframe_callback(struct msm_frame *frame)
4204{
4205 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4206 if (obj != 0) {
4207 obj->receivePreviewFrame(frame);
4208 }
4209}
4210
4211static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size)
4212{
4213 LOGV("receive_jpeg_fragment_callback E");
4214 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4215 if (obj != 0) {
4216 obj->receiveJpegPictureFragment(buff_ptr, buff_size);
4217 }
4218 LOGV("receive_jpeg_fragment_callback X");
4219}
4220
4221static void receive_jpeg_callback(jpeg_event_t status)
4222{
4223 LOGV("receive_jpeg_callback E (completion status %d)", status);
4224 if (status == JPEG_EVENT_DONE) {
4225 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4226 if (obj != 0) {
4227 obj->receiveJpegPicture();
4228 }
4229 }
4230 LOGV("receive_jpeg_callback X");
4231}
Sravankb4f5f1c2010-01-21 11:06:17 +05304232// 720p : video frame calbback from camframe
4233static void receive_camframe_video_callback(struct msm_frame *frame)
4234{
4235 LOGV("receive_camframe_video_callback E");
4236 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4237 if (obj != 0) {
4238 obj->receiveRecordingFrame(frame);
4239 }
4240 LOGV("receive_camframe_video_callback X");
4241}
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004242
4243void QualcommCameraHardware::setCallbacks(notify_callback notify_cb,
4244 data_callback data_cb,
4245 data_callback_timestamp data_cb_timestamp,
4246 void* user)
4247{
4248 Mutex::Autolock lock(mLock);
4249 mNotifyCallback = notify_cb;
4250 mDataCallback = data_cb;
4251 mDataCallbackTimestamp = data_cb_timestamp;
4252 mCallbackCookie = user;
4253}
4254
4255void QualcommCameraHardware::enableMsgType(int32_t msgType)
4256{
4257 Mutex::Autolock lock(mLock);
4258 mMsgEnabled |= msgType;
4259}
4260
4261void QualcommCameraHardware::disableMsgType(int32_t msgType)
4262{
4263 Mutex::Autolock lock(mLock);
4264 mMsgEnabled &= ~msgType;
4265}
4266
4267bool QualcommCameraHardware::msgTypeEnabled(int32_t msgType)
4268{
4269 return (mMsgEnabled & msgType);
4270}
4271
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08004272bool QualcommCameraHardware::useOverlay(void)
4273{
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08004274 if( mCurrentTarget == TARGET_MSM7630 ) {
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08004275 /* Only 7x30 supports Overlay */
4276 mUseOverlay = TRUE;
4277 } else
4278 mUseOverlay = FALSE;
4279
4280 LOGV(" Using Overlay : %s ", mUseOverlay ? "YES" : "NO" );
4281 return mUseOverlay;
4282}
4283
4284status_t QualcommCameraHardware::setOverlay(const sp<Overlay> &Overlay)
4285{
4286 if( Overlay != NULL) {
4287 LOGV(" Valid overlay object ");
4288 mOverlayLock.lock();
4289 mOverlay = Overlay;
4290 mOverlayLock.unlock();
4291 } else {
4292 LOGE(" Overlay object NULL. returning ");
Mohan Kandrad9efed92010-01-15 19:08:39 -08004293 mOverlay = NULL;
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08004294 return UNKNOWN_ERROR;
4295 }
4296 return NO_ERROR;
4297}
Kiran Kumar H N215cac42009-12-08 01:53:46 -08004298
4299void QualcommCameraHardware::receive_camframetimeout(void) {
4300 LOGV("receive_camframetimeout: E");
4301 Mutex::Autolock l(&mCamframeTimeoutLock);
Kiran Kumar H N7ac84e32010-02-01 10:58:47 -08004302 LOGD(" Camframe timed out. Not receiving any frames from camera driver ");
Kiran Kumar H N215cac42009-12-08 01:53:46 -08004303 camframe_timeout_flag = TRUE;
4304 LOGV("receive_camframetimeout: X");
4305}
4306
4307static void receive_camframetimeout_callback(void) {
4308 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4309 if (obj != 0) {
4310 obj->receive_camframetimeout();
4311 }
4312}
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08004313
4314void QualcommCameraHardware::storePreviewFrameForPostview(void) {
4315 LOGV(" storePreviewFrameForPostview : E ");
4316
4317 /* Since there is restriction on the maximum overlay dimensions
4318 * that can be created, we use the last preview frame as postview
4319 * for 7x30. */
4320 LOGV(" Copying the preview buffer to postview buffer %d ",
4321 mPreviewFrameSize);
4322 if( mPostViewHeap != NULL && mLastQueuedFrame != NULL) {
4323 memcpy(mPostViewHeap->mHeap->base(),
4324 (uint8_t *)mLastQueuedFrame, mPreviewFrameSize );
4325 } else
4326 LOGE(" Failed to store Preview frame. No Postview ");
4327
4328 LOGV(" storePreviewFrameForPostview : X ");
4329}
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004330}; // namespace android