blob: 0aadcfabe6fef8dea89f874795b89513c8e2d5ac [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);
Priya Komarlingamb85535d2009-11-30 13:06:01 -080092int (*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 Kandra284966d2010-01-05 13:39:15 -0800156static char mDeviceName[PROPERTY_VALUE_MAX];
Mohan Kandra740cfce2010-01-07 12:58:24 -0800157union zoomimage
Mohan Kandra284966d2010-01-05 13:39:15 -0800158{
159 char d[sizeof(struct mdp_blit_req_list) + sizeof(struct mdp_blit_req) * 1];
160 struct mdp_blit_req_list list;
161} zoomImage;
162
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800163//Default to WVGA
Srinivasan Kannanfa7edae2009-12-16 18:02:01 -0800164#define DEFAULT_PREVIEW_SETTING 1
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800165static const camera_size_type preview_sizes[] = {
Srinivasan Kannanfa7edae2009-12-16 18:02:01 -0800166 { 1280, 720 }, // 720P, reserved
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800167 { 800, 480 }, // WVGA
168 { 720, 480 },
169 { 640, 480 }, // VGA
170 { 576, 432 },
171 { 480, 320 }, // HVGA
172 { 384, 288 },
173 { 352, 288 }, // CIF
174 { 320, 240 }, // QVGA
175 { 240, 160 }, // SQVGA
176 { 176, 144 }, // QCIF
177};
178#define PREVIEW_SIZE_COUNT (sizeof(preview_sizes)/sizeof(camera_size_type))
179
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800180//static const camera_size_type* picture_sizes;
181//static int PICTURE_SIZE_COUNT;
182/* TODO
183 * Ideally this should be a populated by lower layers.
184 * But currently this is no API to do that at lower layer.
185 * Hence populating with default sizes for now. This needs
186 * to be changed once the API is supported.
187 */
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800188//sorted on column basis
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800189static const camera_size_type picture_sizes[] = {
190 { 2592, 1944 }, // 5MP
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800191 { 2048, 1536 }, // 3MP QXGA
192 { 1920, 1080 }, //HD1080
193 { 1600, 1200 }, // 2MP UXGA
194 { 1280, 768 }, //WXGA
195 { 1280, 720 }, //HD720
196 { 1024, 768}, // 1MP XGA
197 { 800, 600 }, //SVGA
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800198 { 800, 480 }, // WVGA
199 { 640, 480 }, // VGA
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800200 { 352, 288 }, //CIF
201 { 320, 240 }, // QVGA
202 { 176, 144 } // QCIF
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800203};
204static int PICTURE_SIZE_COUNT = sizeof(picture_sizes)/sizeof(camera_size_type);
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800205static const camera_size_type * picture_sizes_ptr;
206static int supportedPictureSizesCount;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800207
Srinivasan Kannan80d878f2009-12-18 15:06:02 -0800208#ifdef Q12
209#undef Q12
210#endif
211
212#define Q12 4096
213
214typedef struct {
215 uint32_t aspect_ratio;
216 uint32_t width;
217 uint32_t height;
218} thumbnail_size_type;
219
220static thumbnail_size_type thumbnail_sizes[] = {
221 { 7281, 512, 288 }, //1.777778
222 { 6826, 480, 288 }, //1.666667
223 { 5461, 512, 384 }, //1.333333
224 { 5006, 352, 288 }, //1.222222
225};
226#define THUMBNAIL_SIZE_COUNT (sizeof(thumbnail_sizes)/sizeof(thumbnail_size_type))
227#define DEFAULT_THUMBNAIL_SETTING 2
228#define THUMBNAIL_WIDTH_STR "512"
229#define THUMBNAIL_HEIGHT_STR "384"
230#define THUMBNAIL_SMALL_HEIGHT 144
231
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800232static int attr_lookup(const str_map arr[], int len, const char *name)
233{
234 if (name) {
235 for (int i = 0; i < len; i++) {
236 if (!strcmp(arr[i].desc, name))
237 return arr[i].val;
238 }
239 }
240 return NOT_FOUND;
241}
242
243// round to the next power of two
244static inline unsigned clp2(unsigned x)
245{
246 x = x - 1;
247 x = x | (x >> 1);
248 x = x | (x >> 2);
249 x = x | (x >> 4);
250 x = x | (x >> 8);
251 x = x | (x >>16);
252 return x + 1;
253}
254
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -0800255static int exif_table_numEntries = 0;
256#define MAX_EXIF_TABLE_ENTRIES 7
257exif_tags_info_t exif_data[MAX_EXIF_TABLE_ENTRIES];
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -0800258static zoom_crop_info zoomCropInfo;
259static void *mLastQueuedFrame = NULL;
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -0800260
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800261namespace android {
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800262
263static const int PICTURE_FORMAT_JPEG = 1;
264static const int PICTURE_FORMAT_RAW = 2;
265
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800266// from aeecamera.h
267static const str_map whitebalance[] = {
268 { CameraParameters::WHITE_BALANCE_AUTO, CAMERA_WB_AUTO },
269 { CameraParameters::WHITE_BALANCE_INCANDESCENT, CAMERA_WB_INCANDESCENT },
270 { CameraParameters::WHITE_BALANCE_FLUORESCENT, CAMERA_WB_FLUORESCENT },
271 { CameraParameters::WHITE_BALANCE_DAYLIGHT, CAMERA_WB_DAYLIGHT },
272 { CameraParameters::WHITE_BALANCE_CLOUDY_DAYLIGHT, CAMERA_WB_CLOUDY_DAYLIGHT }
273};
274
275// from camera_effect_t. This list must match aeecamera.h
276static const str_map effects[] = {
277 { CameraParameters::EFFECT_NONE, CAMERA_EFFECT_OFF },
278 { CameraParameters::EFFECT_MONO, CAMERA_EFFECT_MONO },
279 { CameraParameters::EFFECT_NEGATIVE, CAMERA_EFFECT_NEGATIVE },
280 { CameraParameters::EFFECT_SOLARIZE, CAMERA_EFFECT_SOLARIZE },
281 { CameraParameters::EFFECT_SEPIA, CAMERA_EFFECT_SEPIA },
282 { CameraParameters::EFFECT_POSTERIZE, CAMERA_EFFECT_POSTERIZE },
283 { CameraParameters::EFFECT_WHITEBOARD, CAMERA_EFFECT_WHITEBOARD },
284 { CameraParameters::EFFECT_BLACKBOARD, CAMERA_EFFECT_BLACKBOARD },
285 { CameraParameters::EFFECT_AQUA, CAMERA_EFFECT_AQUA }
286};
287
288// from qcamera/common/camera.h
Apurva Rajguru55562b02009-12-03 12:25:35 -0800289static const str_map autoexposure[] = {
290 { CameraParameters::AUTO_EXPOSURE_FRAME_AVG, CAMERA_AEC_FRAME_AVERAGE },
291 { CameraParameters::AUTO_EXPOSURE_CENTER_WEIGHTED, CAMERA_AEC_CENTER_WEIGHTED },
292 { CameraParameters::AUTO_EXPOSURE_SPOT_METERING, CAMERA_AEC_SPOT_METERING }
293};
294
295// from qcamera/common/camera.h
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800296static const str_map antibanding[] = {
297 { CameraParameters::ANTIBANDING_OFF, CAMERA_ANTIBANDING_OFF },
298 { CameraParameters::ANTIBANDING_50HZ, CAMERA_ANTIBANDING_50HZ },
299 { CameraParameters::ANTIBANDING_60HZ, CAMERA_ANTIBANDING_60HZ },
300 { CameraParameters::ANTIBANDING_AUTO, CAMERA_ANTIBANDING_AUTO }
301};
302
303/* Mapping from MCC to antibanding type */
304struct country_map {
305 uint32_t country_code;
306 camera_antibanding_type type;
307};
308
309static struct country_map country_numeric[] = {
310 { 202, CAMERA_ANTIBANDING_50HZ }, // Greece
311 { 204, CAMERA_ANTIBANDING_50HZ }, // Netherlands
312 { 206, CAMERA_ANTIBANDING_50HZ }, // Belgium
313 { 208, CAMERA_ANTIBANDING_50HZ }, // France
314 { 212, CAMERA_ANTIBANDING_50HZ }, // Monaco
315 { 213, CAMERA_ANTIBANDING_50HZ }, // Andorra
316 { 214, CAMERA_ANTIBANDING_50HZ }, // Spain
317 { 216, CAMERA_ANTIBANDING_50HZ }, // Hungary
318 { 219, CAMERA_ANTIBANDING_50HZ }, // Croatia
319 { 220, CAMERA_ANTIBANDING_50HZ }, // Serbia
320 { 222, CAMERA_ANTIBANDING_50HZ }, // Italy
321 { 226, CAMERA_ANTIBANDING_50HZ }, // Romania
322 { 228, CAMERA_ANTIBANDING_50HZ }, // Switzerland
323 { 230, CAMERA_ANTIBANDING_50HZ }, // Czech Republic
324 { 231, CAMERA_ANTIBANDING_50HZ }, // Slovakia
325 { 232, CAMERA_ANTIBANDING_50HZ }, // Austria
326 { 234, CAMERA_ANTIBANDING_50HZ }, // United Kingdom
327 { 235, CAMERA_ANTIBANDING_50HZ }, // United Kingdom
328 { 238, CAMERA_ANTIBANDING_50HZ }, // Denmark
329 { 240, CAMERA_ANTIBANDING_50HZ }, // Sweden
330 { 242, CAMERA_ANTIBANDING_50HZ }, // Norway
331 { 244, CAMERA_ANTIBANDING_50HZ }, // Finland
332 { 246, CAMERA_ANTIBANDING_50HZ }, // Lithuania
333 { 247, CAMERA_ANTIBANDING_50HZ }, // Latvia
334 { 248, CAMERA_ANTIBANDING_50HZ }, // Estonia
335 { 250, CAMERA_ANTIBANDING_50HZ }, // Russian Federation
336 { 255, CAMERA_ANTIBANDING_50HZ }, // Ukraine
337 { 257, CAMERA_ANTIBANDING_50HZ }, // Belarus
338 { 259, CAMERA_ANTIBANDING_50HZ }, // Moldova
339 { 260, CAMERA_ANTIBANDING_50HZ }, // Poland
340 { 262, CAMERA_ANTIBANDING_50HZ }, // Germany
341 { 266, CAMERA_ANTIBANDING_50HZ }, // Gibraltar
342 { 268, CAMERA_ANTIBANDING_50HZ }, // Portugal
343 { 270, CAMERA_ANTIBANDING_50HZ }, // Luxembourg
344 { 272, CAMERA_ANTIBANDING_50HZ }, // Ireland
345 { 274, CAMERA_ANTIBANDING_50HZ }, // Iceland
346 { 276, CAMERA_ANTIBANDING_50HZ }, // Albania
347 { 278, CAMERA_ANTIBANDING_50HZ }, // Malta
348 { 280, CAMERA_ANTIBANDING_50HZ }, // Cyprus
349 { 282, CAMERA_ANTIBANDING_50HZ }, // Georgia
350 { 283, CAMERA_ANTIBANDING_50HZ }, // Armenia
351 { 284, CAMERA_ANTIBANDING_50HZ }, // Bulgaria
352 { 286, CAMERA_ANTIBANDING_50HZ }, // Turkey
353 { 288, CAMERA_ANTIBANDING_50HZ }, // Faroe Islands
354 { 290, CAMERA_ANTIBANDING_50HZ }, // Greenland
355 { 293, CAMERA_ANTIBANDING_50HZ }, // Slovenia
356 { 294, CAMERA_ANTIBANDING_50HZ }, // Macedonia
357 { 295, CAMERA_ANTIBANDING_50HZ }, // Liechtenstein
358 { 297, CAMERA_ANTIBANDING_50HZ }, // Montenegro
359 { 302, CAMERA_ANTIBANDING_60HZ }, // Canada
360 { 310, CAMERA_ANTIBANDING_60HZ }, // United States of America
361 { 311, CAMERA_ANTIBANDING_60HZ }, // United States of America
362 { 312, CAMERA_ANTIBANDING_60HZ }, // United States of America
363 { 313, CAMERA_ANTIBANDING_60HZ }, // United States of America
364 { 314, CAMERA_ANTIBANDING_60HZ }, // United States of America
365 { 315, CAMERA_ANTIBANDING_60HZ }, // United States of America
366 { 316, CAMERA_ANTIBANDING_60HZ }, // United States of America
367 { 330, CAMERA_ANTIBANDING_60HZ }, // Puerto Rico
368 { 334, CAMERA_ANTIBANDING_60HZ }, // Mexico
369 { 338, CAMERA_ANTIBANDING_50HZ }, // Jamaica
370 { 340, CAMERA_ANTIBANDING_50HZ }, // Martinique
371 { 342, CAMERA_ANTIBANDING_50HZ }, // Barbados
372 { 346, CAMERA_ANTIBANDING_60HZ }, // Cayman Islands
373 { 350, CAMERA_ANTIBANDING_60HZ }, // Bermuda
374 { 352, CAMERA_ANTIBANDING_50HZ }, // Grenada
375 { 354, CAMERA_ANTIBANDING_60HZ }, // Montserrat
376 { 362, CAMERA_ANTIBANDING_50HZ }, // Netherlands Antilles
377 { 363, CAMERA_ANTIBANDING_60HZ }, // Aruba
378 { 364, CAMERA_ANTIBANDING_60HZ }, // Bahamas
379 { 365, CAMERA_ANTIBANDING_60HZ }, // Anguilla
380 { 366, CAMERA_ANTIBANDING_50HZ }, // Dominica
381 { 368, CAMERA_ANTIBANDING_60HZ }, // Cuba
382 { 370, CAMERA_ANTIBANDING_60HZ }, // Dominican Republic
383 { 372, CAMERA_ANTIBANDING_60HZ }, // Haiti
384 { 401, CAMERA_ANTIBANDING_50HZ }, // Kazakhstan
385 { 402, CAMERA_ANTIBANDING_50HZ }, // Bhutan
386 { 404, CAMERA_ANTIBANDING_50HZ }, // India
387 { 405, CAMERA_ANTIBANDING_50HZ }, // India
388 { 410, CAMERA_ANTIBANDING_50HZ }, // Pakistan
389 { 413, CAMERA_ANTIBANDING_50HZ }, // Sri Lanka
390 { 414, CAMERA_ANTIBANDING_50HZ }, // Myanmar
391 { 415, CAMERA_ANTIBANDING_50HZ }, // Lebanon
392 { 416, CAMERA_ANTIBANDING_50HZ }, // Jordan
393 { 417, CAMERA_ANTIBANDING_50HZ }, // Syria
394 { 418, CAMERA_ANTIBANDING_50HZ }, // Iraq
395 { 419, CAMERA_ANTIBANDING_50HZ }, // Kuwait
396 { 420, CAMERA_ANTIBANDING_60HZ }, // Saudi Arabia
397 { 421, CAMERA_ANTIBANDING_50HZ }, // Yemen
398 { 422, CAMERA_ANTIBANDING_50HZ }, // Oman
399 { 424, CAMERA_ANTIBANDING_50HZ }, // United Arab Emirates
400 { 425, CAMERA_ANTIBANDING_50HZ }, // Israel
401 { 426, CAMERA_ANTIBANDING_50HZ }, // Bahrain
402 { 427, CAMERA_ANTIBANDING_50HZ }, // Qatar
403 { 428, CAMERA_ANTIBANDING_50HZ }, // Mongolia
404 { 429, CAMERA_ANTIBANDING_50HZ }, // Nepal
405 { 430, CAMERA_ANTIBANDING_50HZ }, // United Arab Emirates
406 { 431, CAMERA_ANTIBANDING_50HZ }, // United Arab Emirates
407 { 432, CAMERA_ANTIBANDING_50HZ }, // Iran
408 { 434, CAMERA_ANTIBANDING_50HZ }, // Uzbekistan
409 { 436, CAMERA_ANTIBANDING_50HZ }, // Tajikistan
410 { 437, CAMERA_ANTIBANDING_50HZ }, // Kyrgyz Rep
411 { 438, CAMERA_ANTIBANDING_50HZ }, // Turkmenistan
412 { 440, CAMERA_ANTIBANDING_60HZ }, // Japan
413 { 441, CAMERA_ANTIBANDING_60HZ }, // Japan
414 { 452, CAMERA_ANTIBANDING_50HZ }, // Vietnam
415 { 454, CAMERA_ANTIBANDING_50HZ }, // Hong Kong
416 { 455, CAMERA_ANTIBANDING_50HZ }, // Macao
417 { 456, CAMERA_ANTIBANDING_50HZ }, // Cambodia
418 { 457, CAMERA_ANTIBANDING_50HZ }, // Laos
419 { 460, CAMERA_ANTIBANDING_50HZ }, // China
420 { 466, CAMERA_ANTIBANDING_60HZ }, // Taiwan
421 { 470, CAMERA_ANTIBANDING_50HZ }, // Bangladesh
422 { 472, CAMERA_ANTIBANDING_50HZ }, // Maldives
423 { 502, CAMERA_ANTIBANDING_50HZ }, // Malaysia
424 { 505, CAMERA_ANTIBANDING_50HZ }, // Australia
425 { 510, CAMERA_ANTIBANDING_50HZ }, // Indonesia
426 { 514, CAMERA_ANTIBANDING_50HZ }, // East Timor
427 { 515, CAMERA_ANTIBANDING_60HZ }, // Philippines
428 { 520, CAMERA_ANTIBANDING_50HZ }, // Thailand
429 { 525, CAMERA_ANTIBANDING_50HZ }, // Singapore
430 { 530, CAMERA_ANTIBANDING_50HZ }, // New Zealand
431 { 535, CAMERA_ANTIBANDING_60HZ }, // Guam
432 { 536, CAMERA_ANTIBANDING_50HZ }, // Nauru
433 { 537, CAMERA_ANTIBANDING_50HZ }, // Papua New Guinea
434 { 539, CAMERA_ANTIBANDING_50HZ }, // Tonga
435 { 541, CAMERA_ANTIBANDING_50HZ }, // Vanuatu
436 { 542, CAMERA_ANTIBANDING_50HZ }, // Fiji
437 { 544, CAMERA_ANTIBANDING_60HZ }, // American Samoa
438 { 545, CAMERA_ANTIBANDING_50HZ }, // Kiribati
439 { 546, CAMERA_ANTIBANDING_50HZ }, // New Caledonia
440 { 548, CAMERA_ANTIBANDING_50HZ }, // Cook Islands
441 { 602, CAMERA_ANTIBANDING_50HZ }, // Egypt
442 { 603, CAMERA_ANTIBANDING_50HZ }, // Algeria
443 { 604, CAMERA_ANTIBANDING_50HZ }, // Morocco
444 { 605, CAMERA_ANTIBANDING_50HZ }, // Tunisia
445 { 606, CAMERA_ANTIBANDING_50HZ }, // Libya
446 { 607, CAMERA_ANTIBANDING_50HZ }, // Gambia
447 { 608, CAMERA_ANTIBANDING_50HZ }, // Senegal
448 { 609, CAMERA_ANTIBANDING_50HZ }, // Mauritania
449 { 610, CAMERA_ANTIBANDING_50HZ }, // Mali
450 { 611, CAMERA_ANTIBANDING_50HZ }, // Guinea
451 { 613, CAMERA_ANTIBANDING_50HZ }, // Burkina Faso
452 { 614, CAMERA_ANTIBANDING_50HZ }, // Niger
453 { 616, CAMERA_ANTIBANDING_50HZ }, // Benin
454 { 617, CAMERA_ANTIBANDING_50HZ }, // Mauritius
455 { 618, CAMERA_ANTIBANDING_50HZ }, // Liberia
456 { 619, CAMERA_ANTIBANDING_50HZ }, // Sierra Leone
457 { 620, CAMERA_ANTIBANDING_50HZ }, // Ghana
458 { 621, CAMERA_ANTIBANDING_50HZ }, // Nigeria
459 { 622, CAMERA_ANTIBANDING_50HZ }, // Chad
460 { 623, CAMERA_ANTIBANDING_50HZ }, // Central African Republic
461 { 624, CAMERA_ANTIBANDING_50HZ }, // Cameroon
462 { 625, CAMERA_ANTIBANDING_50HZ }, // Cape Verde
463 { 627, CAMERA_ANTIBANDING_50HZ }, // Equatorial Guinea
464 { 631, CAMERA_ANTIBANDING_50HZ }, // Angola
465 { 633, CAMERA_ANTIBANDING_50HZ }, // Seychelles
466 { 634, CAMERA_ANTIBANDING_50HZ }, // Sudan
467 { 636, CAMERA_ANTIBANDING_50HZ }, // Ethiopia
468 { 637, CAMERA_ANTIBANDING_50HZ }, // Somalia
469 { 638, CAMERA_ANTIBANDING_50HZ }, // Djibouti
470 { 639, CAMERA_ANTIBANDING_50HZ }, // Kenya
471 { 640, CAMERA_ANTIBANDING_50HZ }, // Tanzania
472 { 641, CAMERA_ANTIBANDING_50HZ }, // Uganda
473 { 642, CAMERA_ANTIBANDING_50HZ }, // Burundi
474 { 643, CAMERA_ANTIBANDING_50HZ }, // Mozambique
475 { 645, CAMERA_ANTIBANDING_50HZ }, // Zambia
476 { 646, CAMERA_ANTIBANDING_50HZ }, // Madagascar
477 { 647, CAMERA_ANTIBANDING_50HZ }, // France
478 { 648, CAMERA_ANTIBANDING_50HZ }, // Zimbabwe
479 { 649, CAMERA_ANTIBANDING_50HZ }, // Namibia
480 { 650, CAMERA_ANTIBANDING_50HZ }, // Malawi
481 { 651, CAMERA_ANTIBANDING_50HZ }, // Lesotho
482 { 652, CAMERA_ANTIBANDING_50HZ }, // Botswana
483 { 653, CAMERA_ANTIBANDING_50HZ }, // Swaziland
484 { 654, CAMERA_ANTIBANDING_50HZ }, // Comoros
485 { 655, CAMERA_ANTIBANDING_50HZ }, // South Africa
486 { 657, CAMERA_ANTIBANDING_50HZ }, // Eritrea
487 { 702, CAMERA_ANTIBANDING_60HZ }, // Belize
488 { 704, CAMERA_ANTIBANDING_60HZ }, // Guatemala
489 { 706, CAMERA_ANTIBANDING_60HZ }, // El Salvador
490 { 708, CAMERA_ANTIBANDING_60HZ }, // Honduras
491 { 710, CAMERA_ANTIBANDING_60HZ }, // Nicaragua
492 { 712, CAMERA_ANTIBANDING_60HZ }, // Costa Rica
493 { 714, CAMERA_ANTIBANDING_60HZ }, // Panama
494 { 722, CAMERA_ANTIBANDING_50HZ }, // Argentina
495 { 724, CAMERA_ANTIBANDING_60HZ }, // Brazil
496 { 730, CAMERA_ANTIBANDING_50HZ }, // Chile
497 { 732, CAMERA_ANTIBANDING_60HZ }, // Colombia
498 { 734, CAMERA_ANTIBANDING_60HZ }, // Venezuela
499 { 736, CAMERA_ANTIBANDING_50HZ }, // Bolivia
500 { 738, CAMERA_ANTIBANDING_60HZ }, // Guyana
501 { 740, CAMERA_ANTIBANDING_60HZ }, // Ecuador
502 { 742, CAMERA_ANTIBANDING_50HZ }, // French Guiana
503 { 744, CAMERA_ANTIBANDING_50HZ }, // Paraguay
504 { 746, CAMERA_ANTIBANDING_60HZ }, // Suriname
505 { 748, CAMERA_ANTIBANDING_50HZ }, // Uruguay
506 { 750, CAMERA_ANTIBANDING_50HZ }, // Falkland Islands
507};
508
509#define country_number (sizeof(country_numeric) / sizeof(country_map))
510
511/* Look up pre-sorted antibanding_type table by current MCC. */
512static camera_antibanding_type camera_get_location(void) {
513 char value[PROP_VALUE_MAX];
514 char country_value[PROP_VALUE_MAX];
515 uint32_t country_code, count;
516 memset(value, 0x00, sizeof(value));
517 memset(country_value, 0x00, sizeof(country_value));
518 if (!__system_property_get("gsm.operator.numeric", value)) {
519 return CAMERA_ANTIBANDING_60HZ;
520 }
521 memcpy(country_value, value, 3);
522 country_code = atoi(country_value);
523 LOGD("value:%s, country value:%s, country code:%d\n",
524 value, country_value, country_code);
525 int left = 0;
526 int right = country_number - 1;
527 while (left <= right) {
528 int index = (left + right) >> 1;
529 if (country_numeric[index].country_code == country_code)
530 return country_numeric[index].type;
531 else if (country_numeric[index].country_code > country_code)
532 right = index - 1;
533 else
534 left = index + 1;
535 }
536 return CAMERA_ANTIBANDING_60HZ;
537}
538
539// from camera.h, led_mode_t
540static const str_map flash[] = {
541 { CameraParameters::FLASH_MODE_OFF, LED_MODE_OFF },
542 { CameraParameters::FLASH_MODE_AUTO, LED_MODE_AUTO },
543 { CameraParameters::FLASH_MODE_ON, LED_MODE_ON }
544};
545
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530546// from mm-camera/common/camera.h.
547static const str_map iso[] = {
548 { CameraParameters::ISO_AUTO, CAMERA_ISO_AUTO},
549 { CameraParameters::ISO_HJR, CAMERA_ISO_DEBLUR},
550 { CameraParameters::ISO_100, CAMERA_ISO_100},
551 { CameraParameters::ISO_200, CAMERA_ISO_200},
552 { CameraParameters::ISO_400, CAMERA_ISO_400},
553 { CameraParameters::ISO_800, CAMERA_ISO_800 }
554};
555
556
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800557#define DONT_CARE 0
558static const str_map focus_modes[] = {
Srinivasan Kannan71229622009-12-04 12:05:58 -0800559 { CameraParameters::FOCUS_MODE_AUTO, AF_MODE_AUTO},
560 { CameraParameters::FOCUS_MODE_INFINITY, DONT_CARE },
561 { CameraParameters::FOCUS_MODE_NORMAL, AF_MODE_NORMAL },
562 { CameraParameters::FOCUS_MODE_MACRO, AF_MODE_MACRO }
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800563};
564
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530565static const str_map lensshade[] = {
566 { CameraParameters::LENSSHADE_ENABLE, TRUE },
567 { CameraParameters::LENSSHADE_DISABLE, FALSE }
568};
569
Srinivasan Kannan71229622009-12-04 12:05:58 -0800570struct SensorType {
571 const char *name;
572 int rawPictureWidth;
573 int rawPictureHeight;
574 bool hasAutoFocusSupport;
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800575 int max_supported_snapshot_width;
576 int max_supported_snapshot_height;
Srinivasan Kannan71229622009-12-04 12:05:58 -0800577};
578
579static SensorType sensorTypes[] = {
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800580 { "5mp", 2608, 1960, true, 2592, 1944 },
581 { "3mp", 2064, 1544, false, 2048, 1536 },
582 { "2mp", 3200, 1200, false, 1600, 1200 } };
583
Srinivasan Kannan71229622009-12-04 12:05:58 -0800584
585static SensorType * sensorType;
586
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800587static const str_map picture_formats[] = {
588 {CameraParameters::PIXEL_FORMAT_JPEG, PICTURE_FORMAT_JPEG},
589 {CameraParameters::PIXEL_FORMAT_RAW, PICTURE_FORMAT_RAW}
590};
591
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800592static bool parameter_string_initialized = false;
593static String8 preview_size_values;
594static String8 picture_size_values;
595static String8 antibanding_values;
596static String8 effect_values;
Apurva Rajguru55562b02009-12-03 12:25:35 -0800597static String8 autoexposure_values;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800598static String8 whitebalance_values;
599static String8 flash_values;
600static String8 focus_mode_values;
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530601static String8 iso_values;
602static String8 lensshade_values;
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800603static String8 picture_format_values;
604
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800605
606static String8 create_sizes_str(const camera_size_type *sizes, int len) {
607 String8 str;
608 char buffer[32];
609
610 if (len > 0) {
611 sprintf(buffer, "%dx%d", sizes[0].width, sizes[0].height);
612 str.append(buffer);
613 }
614 for (int i = 1; i < len; i++) {
615 sprintf(buffer, ",%dx%d", sizes[i].width, sizes[i].height);
616 str.append(buffer);
617 }
618 return str;
619}
620
621static String8 create_values_str(const str_map *values, int len) {
622 String8 str;
623
624 if (len > 0) {
625 str.append(values[0].desc);
626 }
627 for (int i = 1; i < len; i++) {
628 str.append(",");
629 str.append(values[i].desc);
630 }
631 return str;
632}
633
Sravankb4f5f1c2010-01-21 11:06:17 +0530634extern "C" {
635//------------------------------------------------------------------------
636// : 720p busyQ funcitons
637// --------------------------------------------------------------------
638static struct fifo_queue g_busy_frame_queue =
639 {0, 0, 0, PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER};
640};
641/*===========================================================================
642 * FUNCTION cam_frame_wait_video
643 *
644 * DESCRIPTION this function waits a video in the busy queue
645 * ===========================================================================*/
646
647static void cam_frame_wait_video (void)
648{
649 LOGV("cam_frame_wait_video E ");
650 if ((g_busy_frame_queue.num_of_frames) <=0){
651 pthread_cond_wait(&(g_busy_frame_queue.wait), &(g_busy_frame_queue.mut));
652 }
653 LOGV("cam_frame_wait_video X");
654 return;
655}
656
657/*===========================================================================
658 * FUNCTION cam_frame_flush_video
659 *
660 * DESCRIPTION this function deletes all the buffers in busy queue
661 * ===========================================================================*/
662void cam_frame_flush_video (void)
663{
664 LOGV("cam_frame_flush_video: in n = %d\n", g_busy_frame_queue.num_of_frames);
665 pthread_mutex_lock(&(g_busy_frame_queue.mut));
666
667 while (g_busy_frame_queue.front)
668 {
669 //dequeue from the busy queue
670 struct fifo_node *node = dequeue (&g_busy_frame_queue);
671 if(node)
672 free(node);
673
674 LOGV("cam_frame_flush_video: node \n");
675 }
676 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
677 LOGV("cam_frame_flush_video: out n = %d\n", g_busy_frame_queue.num_of_frames);
678 return ;
679}
680/*===========================================================================
681 * FUNCTION cam_frame_get_video
682 *
683 * DESCRIPTION this function returns a video frame from the head
684 * ===========================================================================*/
685static struct msm_frame * cam_frame_get_video()
686{
687 struct msm_frame *p = NULL;
688 LOGV("cam_frame_get_video... in\n");
689 LOGV("cam_frame_get_video... got lock\n");
690 if (g_busy_frame_queue.front)
691 {
692 //dequeue
693 struct fifo_node *node = dequeue (&g_busy_frame_queue);
694 if (node)
695 {
696 p = (struct msm_frame *)node->f;
697 free (node);
698 }
699 LOGV("cam_frame_get_video... out = %x\n", p->buffer);
700 }
701 return p;
702}
703
704/*===========================================================================
705 * FUNCTION cam_frame_post_video
706 *
707 * DESCRIPTION this function add a busy video frame to the busy queue tails
708 * ===========================================================================*/
709static void cam_frame_post_video (struct msm_frame *p)
710{
711 if (!p)
712 {
713 LOGE("post video , buffer is null");
714 return;
715 }
716 LOGV("cam_frame_post_video... in = %x\n", (unsigned int)(p->buffer));
717 pthread_mutex_lock(&(g_busy_frame_queue.mut));
718 LOGV("post_video got lock. q count before enQ %d", g_busy_frame_queue.num_of_frames);
719 //enqueue to busy queue
720 struct fifo_node *node = (struct fifo_node *)malloc (sizeof (struct fifo_node));
721 if (node)
722 {
723 LOGV(" post video , enqueing in busy queue");
724 node->f = p;
725 node->next = NULL;
726 enqueue (&g_busy_frame_queue, node);
727 LOGV("post_video got lock. q count after enQ %d", g_busy_frame_queue.num_of_frames);
728 }
729 else
730 {
731 LOGE("cam_frame_post_video error... out of memory\n");
732 }
733
734 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
735 pthread_cond_signal(&(g_busy_frame_queue.wait));
736
737 LOGV("cam_frame_post_video... out = %x\n", p->buffer);
738
739 return;
740}
741
742//-------------------------------------------------------------------------------------
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800743static Mutex singleton_lock;
744static bool singleton_releasing;
745static Condition singleton_wait;
746
747static void receive_camframe_callback(struct msm_frame *frame);
Sravankb4f5f1c2010-01-21 11:06:17 +0530748static void receive_camframe_video_callback(struct msm_frame *frame); // 720p
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800749static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size);
750static void receive_jpeg_callback(jpeg_event_t status);
751static void receive_shutter_callback(common_crop_t *crop);
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800752static void receive_camframetimeout_callback(void);
Mohan Kandra284966d2010-01-05 13:39:15 -0800753static int fb_fd = -1;
754static int32_t mMaxZoom = 0;
755static bool native_get_maxzoom(int camfd, void *pZm);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800756
Mohan Kandrad9efed92010-01-15 19:08:39 -0800757static int dstOffset = 0;
758
759/* When using MDP zoom, double the preview buffers. The usage of these
760 * buffers is as follows:
761 * 1. As all the buffers comes under a single FD, and at initial registration,
762 * this FD will be passed to surface flinger, surface flinger can have access
763 * to all the buffers when needed.
764 * 2. Only "kPreviewBufferCount" buffers (SrcSet) will be registered with the
765 * camera driver to receive preview frames. The remaining buffers (DstSet),
766 * will be used at HAL and by surface flinger only when crop information
767 * is present in the frame.
768 * 3. When there is no crop information, there will be no call to MDP zoom,
769 * and the buffers in SrcSet will be passed to surface flinger to display.
770 * 4. With crop information present, MDP zoom will be called, and the final
771 * data will be placed in a buffer from DstSet, and this buffer will be given
772 * to surface flinger to display.
773 */
774#define NUM_MORE_BUFS 2
775
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800776QualcommCameraHardware::QualcommCameraHardware()
777 : mParameters(),
778 mCameraRunning(false),
779 mPreviewInitialized(false),
780 mFrameThreadRunning(false),
781 mSnapshotThreadRunning(false),
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800782 mSnapshotFormat(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800783 mReleasedRecordingFrame(false),
784 mPreviewFrameSize(0),
785 mRawSize(0),
786 mCameraControlFd(-1),
787 mAutoFocusThreadRunning(false),
788 mAutoFocusFd(-1),
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800789 mBrightness(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800790 mInPreviewCallback(false),
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800791 mUseOverlay(0),
792 mOverlay(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800793 mMsgEnabled(0),
794 mNotifyCallback(0),
795 mDataCallback(0),
796 mDataCallbackTimestamp(0),
Mohan Kandra740cfce2010-01-07 12:58:24 -0800797 mCallbackCookie(0),
798 mDebugFps(0)
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800799{
800 memset(&mDimension, 0, sizeof(mDimension));
801 memset(&mCrop, 0, sizeof(mCrop));
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -0800802 memset(&zoomCropInfo, 0, sizeof(zoom_crop_info));
Mohan Kandra284966d2010-01-05 13:39:15 -0800803 property_get("ro.product.device",mDeviceName," ");
Mohan Kandra740cfce2010-01-07 12:58:24 -0800804 char value[PROPERTY_VALUE_MAX];
805 property_get("persist.debug.sf.showfps", value, "0");
806 mDebugFps = atoi(value);
Sravankb4f5f1c2010-01-21 11:06:17 +0530807 if(!strncmp(mDeviceName,"msm7630", 7))
808 kPreviewBufferCountActual = kPreviewBufferCount;
809 else
810 kPreviewBufferCountActual = kPreviewBufferCount + NUM_MORE_BUFS;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800811 LOGV("constructor EX");
812}
813
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800814
815//filter Picture sizes based on max width and height
816void QualcommCameraHardware::filterPictureSizes(){
817 int i;
818 for(i=0;i<PICTURE_SIZE_COUNT;i++){
819 if(((picture_sizes[i].width <=
820 sensorType->max_supported_snapshot_width) &&
821 (picture_sizes[i].height <=
822 sensorType->max_supported_snapshot_height))){
823 picture_sizes_ptr = picture_sizes + i;
824 supportedPictureSizesCount = PICTURE_SIZE_COUNT - i ;
825 return ;
826 }
827 }
828}
829
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800830void QualcommCameraHardware::initDefaultParameters()
831{
832 LOGV("initDefaultParameters E");
833
834 // Initialize constant parameter strings. This will happen only once in the
835 // lifetime of the mediaserver process.
836 if (!parameter_string_initialized) {
Srinivasan Kannan71229622009-12-04 12:05:58 -0800837 findSensorType();
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800838 antibanding_values = create_values_str(
839 antibanding, sizeof(antibanding) / sizeof(str_map));
840 effect_values = create_values_str(
841 effects, sizeof(effects) / sizeof(str_map));
Apurva Rajguru55562b02009-12-03 12:25:35 -0800842 autoexposure_values = create_values_str(
843 autoexposure, sizeof(autoexposure) / sizeof(str_map));
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800844 whitebalance_values = create_values_str(
845 whitebalance, sizeof(whitebalance) / sizeof(str_map));
846 preview_size_values = create_sizes_str(
847 preview_sizes, PREVIEW_SIZE_COUNT);
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800848 //filter picture sizes
849 filterPictureSizes();
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800850 picture_size_values = create_sizes_str(
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800851 picture_sizes_ptr, supportedPictureSizesCount);
852
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800853 flash_values = create_values_str(
854 flash, sizeof(flash) / sizeof(str_map));
Srinivasan Kannan71229622009-12-04 12:05:58 -0800855 if(sensorType->hasAutoFocusSupport){
856 focus_mode_values = create_values_str(
857 focus_modes, sizeof(focus_modes) / sizeof(str_map));
858 }
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530859 iso_values = create_values_str(
860 iso,sizeof(iso)/sizeof(str_map));
861 lensshade_values = create_values_str(
862 lensshade,sizeof(lensshade)/sizeof(str_map));
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800863 picture_format_values = create_values_str(
864 picture_formats, sizeof(picture_formats)/sizeof(str_map));
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800865 parameter_string_initialized = true;
866 }
867
868 const camera_size_type *ps = &preview_sizes[DEFAULT_PREVIEW_SETTING];
869 mParameters.setPreviewSize(ps->width, ps->height);
870 mDimension.display_width = ps->width;
871 mDimension.display_height = ps->height;
872 mParameters.setPreviewFrameRate(15);
873 mParameters.setPreviewFormat("yuv420sp"); // informative
874
875 mParameters.setPictureSize(DEFAULT_PICTURE_WIDTH, DEFAULT_PICTURE_HEIGHT);
876 mParameters.setPictureFormat("jpeg"); // informative
877
878 mParameters.set(CameraParameters::KEY_JPEG_QUALITY, "100"); // max quality
879 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH,
880 THUMBNAIL_WIDTH_STR); // informative
881 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT,
882 THUMBNAIL_HEIGHT_STR); // informative
Srinivasan Kannan80d878f2009-12-18 15:06:02 -0800883 mDimension.ui_thumbnail_width =
884 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].width;
885 mDimension.ui_thumbnail_height =
886 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800887 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, "90");
888
889 mParameters.set(CameraParameters::KEY_ANTIBANDING,
890 CameraParameters::ANTIBANDING_AUTO);
891 mParameters.set(CameraParameters::KEY_EFFECT,
892 CameraParameters::EFFECT_NONE);
Apurva Rajguru55562b02009-12-03 12:25:35 -0800893 mParameters.set(CameraParameters::KEY_AUTO_EXPOSURE,
894 CameraParameters::AUTO_EXPOSURE_FRAME_AVG);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800895 mParameters.set(CameraParameters::KEY_WHITE_BALANCE,
896 CameraParameters::WHITE_BALANCE_AUTO);
897 mParameters.set(CameraParameters::KEY_FOCUS_MODE,
898 CameraParameters::FOCUS_MODE_AUTO);
899
900 mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES,
901 preview_size_values.string());
902 mParameters.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES,
903 picture_size_values.string());
904 mParameters.set(CameraParameters::KEY_SUPPORTED_ANTIBANDING,
905 antibanding_values);
906 mParameters.set(CameraParameters::KEY_SUPPORTED_EFFECTS, effect_values);
Apurva Rajguru55562b02009-12-03 12:25:35 -0800907 mParameters.set(CameraParameters::KEY_SUPPORTED_AUTO_EXPOSURE, autoexposure_values);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800908 mParameters.set(CameraParameters::KEY_SUPPORTED_WHITE_BALANCE,
909 whitebalance_values);
910 mParameters.set(CameraParameters::KEY_SUPPORTED_FOCUS_MODES,
911 focus_mode_values);
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800912 mParameters.set(CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS,
913 picture_format_values);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800914
915 if (mSensorInfo.flash_enabled) {
916 mParameters.set(CameraParameters::KEY_FLASH_MODE,
917 CameraParameters::FLASH_MODE_OFF);
918 mParameters.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES,
919 flash_values);
920 }
921
Srinivasan Kannanbddfd502010-01-03 17:27:36 -0800922 mParameters.set(CameraParameters::KEY_MAX_SHARPNESS,
923 CAMERA_MAX_SHARPNESS);
924 mParameters.set(CameraParameters::KEY_MAX_CONTRAST,
925 CAMERA_MAX_CONTRAST);
926 mParameters.set(CameraParameters::KEY_MAX_SATURATION,
927 CAMERA_MAX_SATURATION);
928
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530929 mParameters.set("luma-adaptation", "18");
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800930 mParameters.set("zoom-supported", "true");
931 mParameters.set("max-zoom", MAX_ZOOM_LEVEL);
932 mParameters.set("zoom", 0);
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800933 mParameters.set(CameraParameters::KEY_PICTURE_FORMAT,
934 CameraParameters::PIXEL_FORMAT_JPEG);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800935
Kiran Kumar H N595970b2010-01-12 10:41:09 -0800936 mParameters.set(CameraParameters::KEY_SHARPNESS,
937 CAMERA_DEF_SHARPNESS);
938 mParameters.set(CameraParameters::KEY_CONTRAST,
939 CAMERA_DEF_CONTRAST);
940 mParameters.set(CameraParameters::KEY_SATURATION,
941 CAMERA_DEF_SATURATION);
942
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530943 mParameters.set(CameraParameters::KEY_ISO_MODE,
944 CameraParameters::ISO_AUTO);
945 mParameters.set(CameraParameters::KEY_LENSSHADE,
946 CameraParameters::LENSSHADE_ENABLE);
947 mParameters.set(CameraParameters::KEY_SUPPORTED_ISO_MODES,
948 iso_values);
949 mParameters.set(CameraParameters::KEY_SUPPORTED_LENSSHADE_MODES,
950 lensshade_values);
951
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800952 if (setParameters(mParameters) != NO_ERROR) {
953 LOGE("Failed to set default parameters?!");
954 }
955
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -0800956 mUseOverlay = useOverlay();
957
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800958 /* Initialize the camframe_timeout_flag*/
959 Mutex::Autolock l(&mCamframeTimeoutLock);
960 camframe_timeout_flag = FALSE;
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -0800961 mPostViewHeap = NULL;
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800962
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800963 LOGV("initDefaultParameters X");
964}
965
Srinivasan Kannan71229622009-12-04 12:05:58 -0800966void QualcommCameraHardware::findSensorType(){
967 mDimension.picture_width = DEFAULT_PICTURE_WIDTH;
968 mDimension.picture_height = DEFAULT_PICTURE_HEIGHT;
969 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
970 sizeof(cam_ctrl_dimension_t), &mDimension);
971 if (ret) {
972 unsigned int i;
973 for (i = 0; i < sizeof(sensorTypes) / sizeof(SensorType); i++) {
974 if (sensorTypes[i].rawPictureHeight
975 == mDimension.raw_picture_height) {
976 sensorType = sensorTypes + i;
977 return;
978 }
979 }
980 }
981 //default to 5 mp
982 sensorType = sensorTypes;
983 return;
984}
985
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800986#define ROUND_TO_PAGE(x) (((x)+0xfff)&~0xfff)
987
988bool QualcommCameraHardware::startCamera()
989{
990 LOGV("startCamera E");
991#if DLOPEN_LIBMMCAMERA
992 libmmcamera = ::dlopen("liboemcamera.so", RTLD_NOW);
993 LOGV("loading liboemcamera at %p", libmmcamera);
994 if (!libmmcamera) {
995 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
996 return false;
997 }
998
999 *(void **)&LINK_cam_frame =
1000 ::dlsym(libmmcamera, "cam_frame");
1001 *(void **)&LINK_camframe_terminate =
1002 ::dlsym(libmmcamera, "camframe_terminate");
1003
1004 *(void **)&LINK_jpeg_encoder_init =
1005 ::dlsym(libmmcamera, "jpeg_encoder_init");
1006
1007 *(void **)&LINK_jpeg_encoder_encode =
1008 ::dlsym(libmmcamera, "jpeg_encoder_encode");
1009
1010 *(void **)&LINK_jpeg_encoder_join =
1011 ::dlsym(libmmcamera, "jpeg_encoder_join");
1012
1013 *(void **)&LINK_mmcamera_camframe_callback =
1014 ::dlsym(libmmcamera, "mmcamera_camframe_callback");
1015
1016 *LINK_mmcamera_camframe_callback = receive_camframe_callback;
1017
1018 *(void **)&LINK_mmcamera_jpegfragment_callback =
1019 ::dlsym(libmmcamera, "mmcamera_jpegfragment_callback");
1020
1021 *LINK_mmcamera_jpegfragment_callback = receive_jpeg_fragment_callback;
1022
1023 *(void **)&LINK_mmcamera_jpeg_callback =
1024 ::dlsym(libmmcamera, "mmcamera_jpeg_callback");
1025
1026 *LINK_mmcamera_jpeg_callback = receive_jpeg_callback;
1027
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001028 *(void **)&LINK_camframe_timeout_callback =
1029 ::dlsym(libmmcamera, "camframe_timeout_callback");
1030
1031 *LINK_camframe_timeout_callback = receive_camframetimeout_callback;
1032
Sravankb4f5f1c2010-01-21 11:06:17 +05301033 // 720 p new recording functions
1034 *(void **)&LINK_cam_frame_flush_free_video = ::dlsym(libmmcamera, "cam_frame_flush_free_video");
1035
1036 *(void **)&LINK_camframe_free_video = ::dlsym(libmmcamera, "cam_frame_add_free_video");
1037
1038 *(void **)&LINK_camframe_video_callback = ::dlsym(libmmcamera, "mmcamera_camframe_videocallback");
1039 *LINK_camframe_video_callback = receive_camframe_video_callback;
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001040/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001041 *(void **)&LINK_mmcamera_shutter_callback =
1042 ::dlsym(libmmcamera, "mmcamera_shutter_callback");
1043
1044 *LINK_mmcamera_shutter_callback = receive_shutter_callback;
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001045*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001046 *(void**)&LINK_jpeg_encoder_setMainImageQuality =
1047 ::dlsym(libmmcamera, "jpeg_encoder_setMainImageQuality");
Kiran Kumar H N8861f302010-01-05 12:01:41 -08001048
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001049 *(void**)&LINK_jpeg_encoder_setThumbnailQuality =
1050 ::dlsym(libmmcamera, "jpeg_encoder_setThumbnailQuality");
1051
1052 *(void**)&LINK_jpeg_encoder_setRotation =
1053 ::dlsym(libmmcamera, "jpeg_encoder_setRotation");
1054
Kiran Kumar H N8861f302010-01-05 12:01:41 -08001055/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001056 *(void**)&LINK_jpeg_encoder_setLocation =
1057 ::dlsym(libmmcamera, "jpeg_encoder_setLocation");
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001058*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001059 *(void **)&LINK_cam_conf =
1060 ::dlsym(libmmcamera, "cam_conf");
1061
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001062/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001063 *(void **)&LINK_default_sensor_get_snapshot_sizes =
1064 ::dlsym(libmmcamera, "default_sensor_get_snapshot_sizes");
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001065*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001066 *(void **)&LINK_launch_cam_conf_thread =
1067 ::dlsym(libmmcamera, "launch_cam_conf_thread");
1068
1069 *(void **)&LINK_release_cam_conf_thread =
1070 ::dlsym(libmmcamera, "release_cam_conf_thread");
1071
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001072/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001073 *(void **)&LINK_zoom_crop_upscale =
1074 ::dlsym(libmmcamera, "zoom_crop_upscale");
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001075*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001076
1077#else
1078 mmcamera_camframe_callback = receive_camframe_callback;
1079 mmcamera_jpegfragment_callback = receive_jpeg_fragment_callback;
1080 mmcamera_jpeg_callback = receive_jpeg_callback;
1081 mmcamera_shutter_callback = receive_shutter_callback;
1082#endif // DLOPEN_LIBMMCAMERA
1083
1084 /* The control thread is in libcamera itself. */
1085 mCameraControlFd = open(MSM_CAMERA_CONTROL, O_RDWR);
Kiran Kumar H N585bc362010-01-19 13:04:44 -08001086 if (mCameraControlFd < 0) {
1087 LOGE("startCamera X: %s open failed: %s!",
1088 MSM_CAMERA_CONTROL,
1089 strerror(errno));
1090 return false;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001091 }
1092
Mohan Kandra284966d2010-01-05 13:39:15 -08001093 if(strncmp(mDeviceName,"msm7630", 7)){
1094 fb_fd = open("/dev/graphics/fb0", O_RDWR);
1095 if (fb_fd < 0) {
1096 LOGE("startCamera: fb0 open failed: %s!", strerror(errno));
1097 return FALSE;
1098 }
1099 }
1100
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001101 /* This will block until the control thread is launched. After that, sensor
1102 * information becomes available.
1103 */
1104
1105 if (LINK_launch_cam_conf_thread()) {
1106 LOGE("failed to launch the camera config thread");
1107 return false;
1108 }
1109
1110 memset(&mSensorInfo, 0, sizeof(mSensorInfo));
1111 if (ioctl(mCameraControlFd,
1112 MSM_CAM_IOCTL_GET_SENSOR_INFO,
1113 &mSensorInfo) < 0)
1114 LOGW("%s: cannot retrieve sensor info!", __FUNCTION__);
1115 else
1116 LOGI("%s: camsensor name %s, flash %d", __FUNCTION__,
1117 mSensorInfo.name, mSensorInfo.flash_enabled);
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001118/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001119 picture_sizes = LINK_default_sensor_get_snapshot_sizes(&PICTURE_SIZE_COUNT);
1120 if (!picture_sizes || !PICTURE_SIZE_COUNT) {
1121 LOGE("startCamera X: could not get snapshot sizes");
1122 return false;
1123 }
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001124*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001125 LOGV("startCamera X");
1126 return true;
1127}
1128
1129status_t QualcommCameraHardware::dump(int fd,
1130 const Vector<String16>& args) const
1131{
1132 const size_t SIZE = 256;
1133 char buffer[SIZE];
1134 String8 result;
1135
1136 // Dump internal primitives.
1137 result.append("QualcommCameraHardware::dump");
1138 snprintf(buffer, 255, "mMsgEnabled (%d)\n", mMsgEnabled);
1139 result.append(buffer);
1140 int width, height;
1141 mParameters.getPreviewSize(&width, &height);
1142 snprintf(buffer, 255, "preview width(%d) x height (%d)\n", width, height);
1143 result.append(buffer);
1144 mParameters.getPictureSize(&width, &height);
1145 snprintf(buffer, 255, "raw width(%d) x height (%d)\n", width, height);
1146 result.append(buffer);
1147 snprintf(buffer, 255,
1148 "preview frame size(%d), raw size (%d), jpeg size (%d) "
1149 "and jpeg max size (%d)\n", mPreviewFrameSize, mRawSize,
1150 mJpegSize, mJpegMaxSize);
1151 result.append(buffer);
1152 write(fd, result.string(), result.size());
1153
1154 // Dump internal objects.
Mohan Kandrad9efed92010-01-15 19:08:39 -08001155 if (mPreviewHeap != 0) {
1156 mPreviewHeap->dump(fd, args);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001157 }
1158 if (mRawHeap != 0) {
1159 mRawHeap->dump(fd, args);
1160 }
1161 if (mJpegHeap != 0) {
1162 mJpegHeap->dump(fd, args);
1163 }
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001164 if(mRawSnapshotAshmemHeap != 0 ){
1165 mRawSnapshotAshmemHeap->dump(fd, args);
1166 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001167 mParameters.dump(fd, args);
1168 return NO_ERROR;
1169}
1170
Mohan Kandra284966d2010-01-05 13:39:15 -08001171static bool native_get_maxzoom(int camfd, void *pZm)
1172{
1173 LOGV("native_get_maxzoom E");
1174
1175 struct msm_ctrl_cmd ctrlCmd;
1176 int32_t *pZoom = (int32_t *)pZm;
1177
1178 ctrlCmd.type = CAMERA_GET_PARM_MAXZOOM;
1179 ctrlCmd.timeout_ms = 5000;
1180 ctrlCmd.length = sizeof(int32_t);
1181 ctrlCmd.value = pZoom;
1182 ctrlCmd.resp_fd = camfd;
1183
1184 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1185 LOGE("native_get_maxzoom: ioctl fd %d error %s",
1186 camfd,
1187 strerror(errno));
1188 return false;
1189 }
1190 LOGE("ctrlCmd.value = %d", *(int32_t *)ctrlCmd.value);
1191 memcpy(pZoom, (int32_t *)ctrlCmd.value, sizeof(int32_t));
1192
1193 LOGV("native_get_maxzoom X");
1194 return true;
1195}
1196
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001197static bool native_set_afmode(int camfd, isp3a_af_mode_t af_type)
1198{
1199 int rc;
1200 struct msm_ctrl_cmd ctrlCmd;
1201
1202 ctrlCmd.timeout_ms = 5000;
1203 ctrlCmd.type = CAMERA_SET_PARM_AUTO_FOCUS;
1204 ctrlCmd.length = sizeof(af_type);
1205 ctrlCmd.value = &af_type;
1206 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1207
1208 if ((rc = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0)
1209 LOGE("native_set_afmode: ioctl fd %d error %s\n",
1210 camfd,
1211 strerror(errno));
1212
1213 LOGV("native_set_afmode: ctrlCmd.status == %d\n", ctrlCmd.status);
1214 return rc >= 0 && ctrlCmd.status == CAMERA_EXIT_CB_DONE;
1215}
1216
1217static bool native_cancel_afmode(int camfd, int af_fd)
1218{
1219 int rc;
1220 struct msm_ctrl_cmd ctrlCmd;
1221
1222 ctrlCmd.timeout_ms = 0;
1223 ctrlCmd.type = CAMERA_AUTO_FOCUS_CANCEL;
1224 ctrlCmd.length = 0;
1225 ctrlCmd.value = NULL;
1226 ctrlCmd.resp_fd = -1; // there's no response fd
1227
1228 if ((rc = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND_2, &ctrlCmd)) < 0)
1229 {
1230 LOGE("native_cancel_afmode: ioctl fd %d error %s\n",
1231 camfd,
1232 strerror(errno));
1233 return false;
1234 }
1235
1236 return true;
1237}
1238
1239static bool native_start_preview(int camfd)
1240{
1241 struct msm_ctrl_cmd ctrlCmd;
1242
1243 ctrlCmd.timeout_ms = 5000;
1244 ctrlCmd.type = CAMERA_START_PREVIEW;
1245 ctrlCmd.length = 0;
1246 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1247
1248 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1249 LOGE("native_start_preview: MSM_CAM_IOCTL_CTRL_COMMAND fd %d error %s",
1250 camfd,
1251 strerror(errno));
1252 return false;
1253 }
1254
1255 return true;
1256}
1257
1258static bool native_get_picture (int camfd, common_crop_t *crop)
1259{
1260 struct msm_ctrl_cmd ctrlCmd;
1261
1262 ctrlCmd.timeout_ms = 5000;
1263 ctrlCmd.length = sizeof(common_crop_t);
1264 ctrlCmd.value = crop;
1265
1266 if(ioctl(camfd, MSM_CAM_IOCTL_GET_PICTURE, &ctrlCmd) < 0) {
1267 LOGE("native_get_picture: MSM_CAM_IOCTL_GET_PICTURE fd %d error %s",
1268 camfd,
1269 strerror(errno));
1270 return false;
1271 }
1272
1273 LOGV("crop: in1_w %d", crop->in1_w);
1274 LOGV("crop: in1_h %d", crop->in1_h);
1275 LOGV("crop: out1_w %d", crop->out1_w);
1276 LOGV("crop: out1_h %d", crop->out1_h);
1277
1278 LOGV("crop: in2_w %d", crop->in2_w);
1279 LOGV("crop: in2_h %d", crop->in2_h);
1280 LOGV("crop: out2_w %d", crop->out2_w);
1281 LOGV("crop: out2_h %d", crop->out2_h);
1282
1283 LOGV("crop: update %d", crop->update_flag);
1284
1285 return true;
1286}
1287
1288static bool native_stop_preview(int camfd)
1289{
1290 struct msm_ctrl_cmd ctrlCmd;
1291 ctrlCmd.timeout_ms = 5000;
1292 ctrlCmd.type = CAMERA_STOP_PREVIEW;
1293 ctrlCmd.length = 0;
1294 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1295
1296 if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1297 LOGE("native_stop_preview: ioctl fd %d error %s",
1298 camfd,
1299 strerror(errno));
1300 return false;
1301 }
1302
1303 return true;
1304}
1305
1306static bool native_prepare_snapshot(int camfd)
1307{
1308 int ioctlRetVal = true;
1309 struct msm_ctrl_cmd ctrlCmd;
1310
1311 ctrlCmd.timeout_ms = 1000;
1312 ctrlCmd.type = CAMERA_PREPARE_SNAPSHOT;
1313 ctrlCmd.length = 0;
1314 ctrlCmd.value = NULL;
1315 ctrlCmd.resp_fd = camfd;
1316
1317 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1318 LOGE("native_prepare_snapshot: ioctl fd %d error %s",
1319 camfd,
1320 strerror(errno));
1321 return false;
1322 }
1323 return true;
1324}
1325
1326static bool native_start_snapshot(int camfd)
1327{
1328 struct msm_ctrl_cmd ctrlCmd;
1329
1330 ctrlCmd.timeout_ms = 5000;
1331 ctrlCmd.type = CAMERA_START_SNAPSHOT;
1332 ctrlCmd.length = 0;
1333 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1334
1335 if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1336 LOGE("native_start_snapshot: ioctl fd %d error %s",
1337 camfd,
1338 strerror(errno));
1339 return false;
1340 }
1341
1342 return true;
1343}
1344
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001345static bool native_start_raw_snapshot(int camfd)
1346{
1347 int ret;
1348 struct msm_ctrl_cmd ctrlCmd;
1349
1350 ctrlCmd.timeout_ms = 1000;
1351 ctrlCmd.type = CAMERA_START_RAW_SNAPSHOT;
1352 ctrlCmd.length = 0;
1353 ctrlCmd.value = NULL;
1354 ctrlCmd.resp_fd = camfd;
1355
1356 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1357 LOGE("native_start_raw_snapshot: ioctl failed. ioctl return value "\
1358 "is %d \n", ret);
1359 return false;
1360 }
1361 return true;
1362}
1363
1364
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001365static bool native_stop_snapshot (int camfd)
1366{
1367 struct msm_ctrl_cmd ctrlCmd;
1368
1369 ctrlCmd.timeout_ms = 0;
1370 ctrlCmd.type = CAMERA_STOP_SNAPSHOT;
1371 ctrlCmd.length = 0;
1372 ctrlCmd.resp_fd = -1;
1373
1374 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND_2, &ctrlCmd) < 0) {
1375 LOGE("native_stop_snapshot: ioctl fd %d error %s",
1376 camfd,
1377 strerror(errno));
1378 return false;
1379 }
1380
1381 return true;
1382}
Sravankb4f5f1c2010-01-21 11:06:17 +05301383/*===========================================================================
1384 * FUNCTION - native_start_recording -
1385 *
1386 * DESCRIPTION:
1387 *==========================================================================*/
1388static bool native_start_recording(int camfd)
1389{
1390 int ret;
1391 struct msm_ctrl_cmd ctrlCmd;
1392
1393 ctrlCmd.timeout_ms = 1000;
1394 ctrlCmd.type = CAMERA_START_RECORDING;
1395 ctrlCmd.length = 0;
1396 ctrlCmd.value = NULL;
1397 ctrlCmd.resp_fd = camfd;
1398
1399 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1400 LOGE("native_start_recording: ioctl failed. ioctl return value "\
1401 "is %d \n", ret);
1402 return false;
1403 }
1404 LOGV("native_start_video: ioctl good. ioctl return value is %d \n",ret);
1405
1406 /* TODO: Check status of postprocessing if there is any,
1407 * PP status should be in ctrlCmd */
1408
1409 return true;
1410}
1411
1412/*===========================================================================
1413 * FUNCTION - native_stop_recording -
1414 *
1415 * DESCRIPTION:
1416 *==========================================================================*/
1417static bool native_stop_recording(int camfd)
1418{
1419 int ret;
1420 struct msm_ctrl_cmd ctrlCmd;
1421LOGE("in native_stop_recording ");
1422 ctrlCmd.timeout_ms = 1000;
1423 ctrlCmd.type = CAMERA_STOP_RECORDING;
1424 ctrlCmd.length = 0;
1425 ctrlCmd.value = NULL;
1426 ctrlCmd.resp_fd = camfd;
1427
1428 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1429 LOGE("native_stop_video: ioctl failed. ioctl return value is %d \n",
1430 ret);
1431 return false;
1432 }
1433 LOGV("in native_stop_recording returned %d", ret);
1434 return true;
1435}
1436/*===========================================================================
1437 * FUNCTION - native_start_video -
1438 *
1439 * DESCRIPTION:
1440 *==========================================================================*/
1441static bool native_start_video(int camfd)
1442{
1443 int ret;
1444 struct msm_ctrl_cmd ctrlCmd;
1445
1446 ctrlCmd.timeout_ms = 1000;
1447 ctrlCmd.type = CAMERA_START_VIDEO;
1448 ctrlCmd.length = 0;
1449 ctrlCmd.value = NULL;
1450 ctrlCmd.resp_fd = camfd;
1451
1452 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1453 LOGE("native_start_video: ioctl failed. ioctl return value is %d \n",
1454 ret);
1455 return false;
1456 }
1457
1458 /* TODO: Check status of postprocessing if there is any,
1459 * PP status should be in ctrlCmd */
1460
1461 return true;
1462}
1463
1464/*===========================================================================
1465 * FUNCTION - native_stop_video -
1466 *
1467 * DESCRIPTION:
1468 *==========================================================================*/
1469static bool native_stop_video(int camfd)
1470{
1471 int ret;
1472 struct msm_ctrl_cmd ctrlCmd;
1473
1474 ctrlCmd.timeout_ms = 1000;
1475 ctrlCmd.type = CAMERA_STOP_VIDEO;
1476 ctrlCmd.length = 0;
1477 ctrlCmd.value = NULL;
1478 ctrlCmd.resp_fd = camfd;
1479
1480 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1481 LOGE("native_stop_video: ioctl failed. ioctl return value is %d \n",
1482 ret);
1483 return false;
1484 }
1485
1486 return true;
1487}
1488/*==========================================================================*/
1489
1490static cam_frame_start_parms frame_parms;
1491static int recordingState = 0;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001492
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001493static rat_t latitude[3];
1494static rat_t longitude[3];
1495static char lonref[2];
1496static char latref[2];
1497static char dateTime[20];
1498static rat_t altitude;
1499
1500static void addExifTag(exif_tag_id_t tagid, exif_tag_type_t type,
1501 uint32_t count, uint8_t copy, void *data) {
1502
1503 if(exif_table_numEntries == MAX_EXIF_TABLE_ENTRIES) {
1504 LOGE("Number of entries exceeded limit");
1505 return;
1506 }
1507
1508 int index = exif_table_numEntries;
1509 exif_data[index].tag_id = tagid;
1510 exif_data[index].tag_entry.type = type;
1511 exif_data[index].tag_entry.count = count;
1512 exif_data[index].tag_entry.copy = copy;
1513 if((type == EXIF_RATIONAL) && (count > 1))
1514 exif_data[index].tag_entry.data._rats = (rat_t *)data;
1515 if((type == EXIF_RATIONAL) && (count == 1))
1516 exif_data[index].tag_entry.data._rat = *(rat_t *)data;
1517 else if(type == EXIF_ASCII)
1518 exif_data[index].tag_entry.data._ascii = (char *)data;
1519 else if(type == EXIF_BYTE)
1520 exif_data[index].tag_entry.data._byte = *(uint8_t *)data;
1521
1522 // Increase number of entries
1523 exif_table_numEntries++;
1524}
1525
1526static void parseLatLong(const char *latlonString, int *pDegrees,
1527 int *pMinutes, int *pSeconds ) {
1528
1529 double value = atof(latlonString);
1530 value = fabs(value);
1531 int degrees = (int) value;
1532
1533 double remainder = value - degrees;
1534 int minutes = (int) (remainder * 60);
1535 int seconds = (int) (((remainder * 60) - minutes) * 60 * 1000);
1536
1537 *pDegrees = degrees;
1538 *pMinutes = minutes;
1539 *pSeconds = seconds;
1540}
1541
1542static void setLatLon(exif_tag_id_t tag, const char *latlonString) {
1543
1544 int degrees, minutes, seconds;
1545
1546 parseLatLong(latlonString, &degrees, &minutes, &seconds);
1547
1548 rat_t value[3] = { {degrees, 1},
1549 {minutes, 1},
1550 {seconds, 1000} };
1551
1552 if(tag == EXIFTAGID_GPS_LATITUDE) {
1553 memcpy(latitude, value, sizeof(latitude));
1554 addExifTag(EXIFTAGID_GPS_LATITUDE, EXIF_RATIONAL, 3,
1555 1, (void *)latitude);
1556 } else {
1557 memcpy(longitude, value, sizeof(longitude));
1558 addExifTag(EXIFTAGID_GPS_LONGITUDE, EXIF_RATIONAL, 3,
1559 1, (void *)longitude);
1560 }
1561}
1562
1563void QualcommCameraHardware::setGpsParameters() {
1564 const char *str = NULL;
1565
1566 //Set Latitude
1567 str = mParameters.get(CameraParameters::KEY_GPS_LATITUDE);
1568 if(str != NULL) {
1569 setLatLon(EXIFTAGID_GPS_LATITUDE, str);
1570 //set Latitude Ref
1571 str = NULL;
1572 str = mParameters.get(CameraParameters::KEY_GPS_LATITUDE_REF);
1573 if(str != NULL) {
1574 strncpy(latref, str, 1);
1575 latref[1] = '\0';
1576 addExifTag(EXIFTAGID_GPS_LATITUDE_REF, EXIF_ASCII, 2,
1577 1, (void *)latref);
1578 }
1579 }
1580
1581 //set Longitude
1582 str = NULL;
1583 str = mParameters.get(CameraParameters::KEY_GPS_LONGITUDE);
1584 if(str != NULL) {
1585 setLatLon(EXIFTAGID_GPS_LONGITUDE, str);
1586 //set Longitude Ref
1587 str = NULL;
1588 str = mParameters.get(CameraParameters::KEY_GPS_LONGITUDE_REF);
1589 if(str != NULL) {
1590 strncpy(lonref, str, 1);
1591 lonref[1] = '\0';
1592 addExifTag(EXIFTAGID_GPS_LONGITUDE_REF, EXIF_ASCII, 2,
1593 1, (void *)lonref);
1594 }
1595 }
1596
1597 //set Altitude
1598 str = NULL;
1599 str = mParameters.get(CameraParameters::KEY_GPS_ALTITUDE);
1600 if(str != NULL) {
1601 int value = atoi(str);
1602 rat_t alt_value = {value, 1000};
1603 memcpy(&altitude, &alt_value, sizeof(altitude));
1604 addExifTag(EXIFTAGID_GPS_ALTITUDE, EXIF_RATIONAL, 1,
1605 1, (void *)&altitude);
1606 //set AltitudeRef
1607 int ref = mParameters.getInt(CameraParameters::KEY_GPS_ALTITUDE_REF);
1608 if( !(ref < 0 || ref > 1) )
1609 addExifTag(EXIFTAGID_GPS_ALTITUDE_REF, EXIF_BYTE, 1,
1610 1, (void *)&ref);
1611 }
1612
1613
1614}
1615
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001616bool QualcommCameraHardware::native_jpeg_encode(void)
1617{
1618 int jpeg_quality = mParameters.getInt("jpeg-quality");
1619 if (jpeg_quality >= 0) {
1620 LOGV("native_jpeg_encode, current jpeg main img quality =%d",
1621 jpeg_quality);
1622 if(!LINK_jpeg_encoder_setMainImageQuality(jpeg_quality)) {
1623 LOGE("native_jpeg_encode set jpeg-quality failed");
1624 return false;
1625 }
1626 }
1627
1628 int thumbnail_quality = mParameters.getInt("jpeg-thumbnail-quality");
1629 if (thumbnail_quality >= 0) {
1630 LOGV("native_jpeg_encode, current jpeg thumbnail quality =%d",
1631 thumbnail_quality);
1632 if(!LINK_jpeg_encoder_setThumbnailQuality(thumbnail_quality)) {
1633 LOGE("native_jpeg_encode set thumbnail-quality failed");
1634 return false;
1635 }
1636 }
1637
1638 int rotation = mParameters.getInt("rotation");
1639 if (rotation >= 0) {
1640 LOGV("native_jpeg_encode, rotation = %d", rotation);
1641 if(!LINK_jpeg_encoder_setRotation(rotation)) {
1642 LOGE("native_jpeg_encode set rotation failed");
1643 return false;
1644 }
1645 }
1646
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001647// jpeg_set_location();
1648 if(mParameters.getInt(CameraParameters::KEY_GPS_STATUS) == 1) {
1649 setGpsParameters();
1650 }
1651 //set TimeStamp
1652 const char *str = mParameters.get(CameraParameters::KEY_EXIF_DATETIME);
1653 if(str != NULL) {
1654 strncpy(dateTime, str, 19);
1655 dateTime[19] = '\0';
1656 addExifTag(EXIFTAGID_EXIF_DATE_TIME_ORIGINAL, EXIF_ASCII,
1657 20, 1, (void *)dateTime);
1658 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001659
1660 if (!LINK_jpeg_encoder_encode(&mDimension,
1661 (uint8_t *)mThumbnailHeap->mHeap->base(),
1662 mThumbnailHeap->mHeap->getHeapID(),
1663 (uint8_t *)mRawHeap->mHeap->base(),
1664 mRawHeap->mHeap->getHeapID(),
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001665 &mCrop, exif_data, exif_table_numEntries)) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001666 LOGE("native_jpeg_encode: jpeg_encoder_encode failed.");
1667 return false;
1668 }
1669 return true;
1670}
1671
1672bool QualcommCameraHardware::native_set_parm(
1673 cam_ctrl_type type, uint16_t length, void *value)
1674{
1675 struct msm_ctrl_cmd ctrlCmd;
1676
1677 ctrlCmd.timeout_ms = 5000;
1678 ctrlCmd.type = (uint16_t)type;
1679 ctrlCmd.length = length;
1680 // FIXME: this will be put in by the kernel
1681 ctrlCmd.resp_fd = mCameraControlFd;
1682 ctrlCmd.value = value;
1683
1684 LOGV("%s: fd %d, type %d, length %d", __FUNCTION__,
1685 mCameraControlFd, type, length);
1686 if (ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0 ||
1687 ctrlCmd.status != CAM_CTRL_SUCCESS) {
1688 LOGE("%s: error (%s): fd %d, type %d, length %d, status %d",
1689 __FUNCTION__, strerror(errno),
1690 mCameraControlFd, type, length, ctrlCmd.status);
1691 return false;
1692 }
1693 return true;
1694}
1695
1696void QualcommCameraHardware::jpeg_set_location()
1697{
1698 bool encode_location = true;
1699 camera_position_type pt;
1700
1701#define PARSE_LOCATION(what,type,fmt,desc) do { \
1702 pt.what = 0; \
1703 const char *what##_str = mParameters.get("gps-"#what); \
1704 LOGV("GPS PARM %s --> [%s]", "gps-"#what, what##_str); \
1705 if (what##_str) { \
1706 type what = 0; \
1707 if (sscanf(what##_str, fmt, &what) == 1) \
1708 pt.what = what; \
1709 else { \
1710 LOGE("GPS " #what " %s could not" \
1711 " be parsed as a " #desc, what##_str); \
1712 encode_location = false; \
1713 } \
1714 } \
1715 else { \
1716 LOGV("GPS " #what " not specified: " \
1717 "defaulting to zero in EXIF header."); \
1718 encode_location = false; \
1719 } \
1720 } while(0)
1721
1722 PARSE_LOCATION(timestamp, long, "%ld", "long");
1723 if (!pt.timestamp) pt.timestamp = time(NULL);
1724 PARSE_LOCATION(altitude, short, "%hd", "short");
1725 PARSE_LOCATION(latitude, double, "%lf", "double float");
1726 PARSE_LOCATION(longitude, double, "%lf", "double float");
1727
1728#undef PARSE_LOCATION
1729
1730 if (encode_location) {
1731 LOGD("setting image location ALT %d LAT %lf LON %lf",
1732 pt.altitude, pt.latitude, pt.longitude);
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001733/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001734 if (!LINK_jpeg_encoder_setLocation(&pt)) {
1735 LOGE("jpeg_set_location: LINK_jpeg_encoder_setLocation failed.");
1736 }
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001737*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001738 }
1739 else LOGV("not setting image location");
1740}
1741
1742void QualcommCameraHardware::runFrameThread(void *data)
1743{
1744 LOGV("runFrameThread E");
1745
1746 int cnt;
1747
1748#if DLOPEN_LIBMMCAMERA
1749 // We need to maintain a reference to libqcamera.so for the duration of the
1750 // frame thread, because we do not know when it will exit relative to the
1751 // lifetime of this object. We do not want to dlclose() libqcamera while
1752 // LINK_cam_frame is still running.
1753 void *libhandle = ::dlopen("liboemcamera.so", RTLD_NOW);
1754 LOGV("FRAME: loading libqcamera at %p", libhandle);
1755 if (!libhandle) {
1756 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
1757 }
1758 if (libhandle)
1759#endif
1760 {
1761 LINK_cam_frame(data);
1762 }
1763
Mohan Kandrad9efed92010-01-15 19:08:39 -08001764 mPreviewHeap.clear();
Sravankb4f5f1c2010-01-21 11:06:17 +05301765 if(!strncmp(mDeviceName,"msm7630", 7))
1766 mRecordHeap.clear();
1767
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001768#if DLOPEN_LIBMMCAMERA
1769 if (libhandle) {
1770 ::dlclose(libhandle);
1771 LOGV("FRAME: dlclose(libqcamera)");
1772 }
1773#endif
1774
1775 mFrameThreadWaitLock.lock();
1776 mFrameThreadRunning = false;
1777 mFrameThreadWait.signal();
1778 mFrameThreadWaitLock.unlock();
1779
1780 LOGV("runFrameThread X");
1781}
1782
Sravankb4f5f1c2010-01-21 11:06:17 +05301783void QualcommCameraHardware::runVideoThread(void *data)
1784{
1785 LOGD("runVideoThread E");
1786 msm_frame* vframe = NULL;
1787
1788 while(true) {
1789 pthread_mutex_lock(&(g_busy_frame_queue.mut));
1790
1791 LOGE("in video_thread : wait for video frame ");
1792 // check if any frames are available in busyQ and give callback to
1793 // services/video encoder
1794 cam_frame_wait_video();
1795 LOGV("video_thread, wait over..");
1796
1797 // Exit the thread , in case of stop recording..
1798 mVideoThreadWaitLock.lock();
1799 if(mVideoThreadExit){
1800 LOGE("Exiting video thread..");
1801 mVideoThreadWaitLock.unlock();
1802 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
1803 break;
1804 }
1805 mVideoThreadWaitLock.unlock();
1806
1807 // Get the video frame to be encoded
1808 vframe = cam_frame_get_video ();
1809 LOGV("in video_thread : got video frame ");
1810
1811 if(vframe != NULL) {
1812 // Find the offset within the heap of the current buffer.
1813 LOGV("Got video frame : buffer %d base %d ", vframe->buffer, mRecordHeap->mHeap->base());
1814 ssize_t offset =
1815 (ssize_t)vframe->buffer - (ssize_t)mRecordHeap->mHeap->base();
1816 LOGV("offset = %d , alignsize = %d , offset later = %d", offset, mRecordHeap->mAlignedBufferSize, (offset / mRecordHeap->mAlignedBufferSize));
1817
1818 offset /= mRecordHeap->mAlignedBufferSize;
1819
1820 // dump frames for test purpose
1821#ifdef DUMP_VIDEO_FRAMES
1822 static int frameCnt = 0;
1823 if (frameCnt >= 11 && frameCnt <= 13 ) {
1824 char buf[128];
1825 sprintf(buf, "/data/%d_v.yuv", frameCnt);
1826 int file_fd = open(buf, O_RDWR | O_CREAT, 0777);
1827 LOGV("dumping video frame %d", frameCnt);
1828 if (file_fd < 0) {
1829 LOGE("cannot open file\n");
1830 }
1831 else
1832 {
1833 write(file_fd, (const void *)vframe->buffer,
1834 vframe->cbcr_off * 3 / 2);
1835 }
1836 close(file_fd);
1837 }
1838 frameCnt++;
1839#endif
1840 // Enable IF block to give frames to encoder , ELSE block for just simulation
1841#if 1
1842 LOGV("in video_thread : got video frame, before if check giving frame to services/encoder");
1843 mCallbackLock.lock();
1844 int msgEnabled = mMsgEnabled;
1845 data_callback_timestamp rcb = mDataCallbackTimestamp;
1846 void *rdata = mCallbackCookie;
1847 mCallbackLock.unlock();
1848
1849 if(rcb != NULL && (msgEnabled & CAMERA_MSG_VIDEO_FRAME) ) {
1850 LOGV("in video_thread : got video frame, giving frame to services/encoder");
1851 rcb(systemTime(), CAMERA_MSG_VIDEO_FRAME, mRecordHeap->mBuffers[offset], rdata);
1852 Mutex::Autolock rLock(&mRecordFrameLock);
1853 if (mReleasedRecordingFrame != true) {
1854 LOGV("block waiting for frame release");
1855 mRecordWait.wait(mRecordFrameLock);
1856 LOGV("video frame released, continuing");
1857 }
1858 mReleasedRecordingFrame = false;
1859 }
1860#else
1861 // 720p output2 : simulate release frame here:
1862 LOGE("in video_thread simulation , releasing the video frame");
1863 LINK_camframe_free_video(vframe);
1864#endif
1865
1866 } else LOGE("in video_thread get frame returned null");
1867
1868 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
1869
1870 } // end of while loop
1871 LOGV("runVideoThread X");
1872}
1873
1874void *video_thread(void *user)
1875{
1876 LOGV("video_thread E");
1877 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
1878 if (obj != 0) {
1879 obj->runVideoThread(user);
1880 }
1881 else LOGE("not starting video thread: the object went away!");
1882 LOGV("video_thread X");
1883 return NULL;
1884}
1885
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001886void *frame_thread(void *user)
1887{
1888 LOGD("frame_thread E");
1889 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
1890 if (obj != 0) {
1891 obj->runFrameThread(user);
1892 }
1893 else LOGW("not starting frame thread: the object went away!");
1894 LOGD("frame_thread X");
1895 return NULL;
1896}
1897
1898bool QualcommCameraHardware::initPreview()
1899{
1900 // See comments in deinitPreview() for why we have to wait for the frame
1901 // thread here, and why we can't use pthread_join().
Sravankb4f5f1c2010-01-21 11:06:17 +05301902 int videoWidth, videoHeight;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001903 mParameters.getPreviewSize(&previewWidth, &previewHeight);
Sravankb4f5f1c2010-01-21 11:06:17 +05301904
1905 videoWidth = previewWidth; // temporary , should be configurable later
1906 videoHeight = previewHeight;
1907 LOGV("initPreview E: preview size=%dx%d videosize = %d x %d", previewWidth, previewHeight, videoWidth, videoHeight );
1908
1909 if(!strncmp(mDeviceName,"msm7630", 7)) {
1910 mDimension.video_width = videoWidth;
1911 mDimension.video_width = CEILING32(mDimension.video_width);
1912 mDimension.video_height = videoHeight;
1913 LOGV("initPreview : preview size=%dx%d videosize = %d x %d", previewWidth, previewHeight, mDimension.video_width, mDimension.video_height );
1914 }
1915
1916
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001917 mFrameThreadWaitLock.lock();
1918 while (mFrameThreadRunning) {
1919 LOGV("initPreview: waiting for old frame thread to complete.");
1920 mFrameThreadWait.wait(mFrameThreadWaitLock);
1921 LOGV("initPreview: old frame thread completed.");
1922 }
1923 mFrameThreadWaitLock.unlock();
1924
1925 mSnapshotThreadWaitLock.lock();
1926 while (mSnapshotThreadRunning) {
1927 LOGV("initPreview: waiting for old snapshot thread to complete.");
1928 mSnapshotThreadWait.wait(mSnapshotThreadWaitLock);
1929 LOGV("initPreview: old snapshot thread completed.");
1930 }
1931 mSnapshotThreadWaitLock.unlock();
1932
1933 int cnt = 0;
1934 mPreviewFrameSize = previewWidth * previewHeight * 3/2;
Mohan Kandrad9efed92010-01-15 19:08:39 -08001935 dstOffset = 0;
1936 mPreviewHeap = new PmemPool("/dev/pmem_adsp",
Mohan Kandra284966d2010-01-05 13:39:15 -08001937 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
1938 mCameraControlFd,
Sravankb4f5f1c2010-01-21 11:06:17 +05301939 MSM_PMEM_PREVIEW, //MSM_PMEM_OUTPUT2,
Mohan Kandra284966d2010-01-05 13:39:15 -08001940 mPreviewFrameSize,
Mohan Kandrad9efed92010-01-15 19:08:39 -08001941 kPreviewBufferCountActual,
Mohan Kandra284966d2010-01-05 13:39:15 -08001942 mPreviewFrameSize,
Mohan Kandrad9efed92010-01-15 19:08:39 -08001943 "preview");
Mohan Kandra284966d2010-01-05 13:39:15 -08001944
Mohan Kandrad9efed92010-01-15 19:08:39 -08001945 if (!mPreviewHeap->initialized()) {
1946 mPreviewHeap.clear();
Mohan Kandra284966d2010-01-05 13:39:15 -08001947 LOGE("initPreview X: could not initialize Camera preview heap.");
1948 return false;
1949 }
Kiran Kumar H N595970b2010-01-12 10:41:09 -08001950 if( !strncmp(mDeviceName,"msm7630", 7) ) {
Kiran Kumar H N595970b2010-01-12 10:41:09 -08001951 if(mPostViewHeap == NULL) {
1952 LOGV(" Allocating Postview heap ");
1953 /* mPostViewHeap should be declared only for 7630 target */
1954 mPostViewHeap =
1955 new PmemPool("/dev/pmem_adsp",
1956 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
1957 mCameraControlFd,
Sravankb4f5f1c2010-01-21 11:06:17 +05301958 MSM_PMEM_PREVIEW, //MSM_PMEM_OUTPUT2,
Kiran Kumar H N595970b2010-01-12 10:41:09 -08001959 mPreviewFrameSize,
1960 1,
1961 mPreviewFrameSize,
1962 "postview");
Mohan Kandra284966d2010-01-05 13:39:15 -08001963
Kiran Kumar H N595970b2010-01-12 10:41:09 -08001964 if (!mPostViewHeap->initialized()) {
1965 mPostViewHeap.clear();
1966 LOGE(" Failed to initialize Postview Heap");
1967 return false;
1968 }
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08001969 }
Mohan Kandrad9efed92010-01-15 19:08:39 -08001970 }
Sravankb4f5f1c2010-01-21 11:06:17 +05301971 // Allocate video buffers after allocating preview buffers.
1972 if( !strncmp(mDeviceName,"msm7630", 7) )
1973 initRecord();
1974
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001975 // mDimension will be filled with thumbnail_width, thumbnail_height,
1976 // orig_picture_dx, and orig_picture_dy after this function call. We need to
1977 // keep it for jpeg_encoder_encode.
1978 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
1979 sizeof(cam_ctrl_dimension_t), &mDimension);
1980
1981 if (ret) {
1982 for (cnt = 0; cnt < kPreviewBufferCount; cnt++) {
Mohan Kandrad9efed92010-01-15 19:08:39 -08001983 frames[cnt].fd = mPreviewHeap->mHeap->getHeapID();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001984 frames[cnt].buffer =
Mohan Kandrad9efed92010-01-15 19:08:39 -08001985 (uint32_t)mPreviewHeap->mHeap->base() + mPreviewHeap->mAlignedBufferSize * cnt;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001986 frames[cnt].y_off = 0;
1987 frames[cnt].cbcr_off = previewWidth * previewHeight;
Sravankb4f5f1c2010-01-21 11:06:17 +05301988 frames[cnt].path = OUTPUT_TYPE_P; // MSM_FRAME_ENC;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001989 }
1990
1991 mFrameThreadWaitLock.lock();
1992 pthread_attr_t attr;
1993 pthread_attr_init(&attr);
1994 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
Sravankb4f5f1c2010-01-21 11:06:17 +05301995
1996 frame_parms.frame = frames[kPreviewBufferCount - 1];
1997 frame_parms.video_frame = recordframes[kPreviewBufferCount - 1];
1998
1999 LOGV ("initpreview before cam_frame thread carete , video frame buffer=%lu fd=%d y_off=%d cbcr_off=%d \n",
2000 (unsigned long)frame_parms.video_frame.buffer, frame_parms.video_frame.fd, frame_parms.video_frame.y_off,
2001 frame_parms.video_frame.cbcr_off);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002002 mFrameThreadRunning = !pthread_create(&mFrameThread,
2003 &attr,
2004 frame_thread,
Sravankb4f5f1c2010-01-21 11:06:17 +05302005 (void*)&(frame_parms));
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002006 ret = mFrameThreadRunning;
2007 mFrameThreadWaitLock.unlock();
2008 }
2009
2010 LOGV("initPreview X: %d", ret);
2011 return ret;
2012}
2013
2014void QualcommCameraHardware::deinitPreview(void)
2015{
2016 LOGI("deinitPreview E");
2017
2018 // When we call deinitPreview(), we signal to the frame thread that it
2019 // needs to exit, but we DO NOT WAIT for it to complete here. The problem
2020 // is that deinitPreview is sometimes called from the frame-thread's
2021 // callback, when the refcount on the Camera client reaches zero. If we
2022 // called pthread_join(), we would deadlock. So, we just call
2023 // LINK_camframe_terminate() in deinitPreview(), which makes sure that
2024 // after the preview callback returns, the camframe thread will exit. We
2025 // could call pthread_join() in initPreview() to join the last frame
2026 // thread. However, we would also have to call pthread_join() in release
2027 // as well, shortly before we destroy the object; this would cause the same
2028 // deadlock, since release(), like deinitPreview(), may also be called from
2029 // the frame-thread's callback. This we have to make the frame thread
2030 // detached, and use a separate mechanism to wait for it to complete.
2031
2032 if (LINK_camframe_terminate() < 0)
2033 LOGE("failed to stop the camframe thread: %s",
2034 strerror(errno));
2035 LOGI("deinitPreview X");
2036}
2037
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002038bool QualcommCameraHardware::initRawSnapshot()
2039{
2040 LOGV("initRawSnapshot E");
2041
2042 //get width and height from Dimension Object
2043 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
2044 sizeof(cam_ctrl_dimension_t), &mDimension);
2045
2046 if(!ret){
2047 LOGE("initRawSnapshot X: failed to set dimension");
2048 return false;
2049 }
2050 int rawSnapshotSize = mDimension.raw_picture_height *
2051 mDimension.raw_picture_width;
2052
2053 LOGV("raw_snapshot_buffer_size = %d, raw_picture_height = %d, "\
2054 "raw_picture_width = %d",
2055 rawSnapshotSize, mDimension.raw_picture_height,
2056 mDimension.raw_picture_width);
2057
2058 if (mRawSnapShotPmemHeap != NULL) {
2059 LOGV("initRawSnapshot: clearing old mRawSnapShotPmemHeap.");
2060 mRawSnapShotPmemHeap.clear();
2061 }
2062
2063 //Pmem based pool for Camera Driver
2064 mRawSnapShotPmemHeap = new PmemPool("/dev/pmem_adsp",
2065 MemoryHeapBase::READ_ONLY,
2066 mCameraControlFd,
2067 MSM_PMEM_RAW_MAINIMG,
2068 rawSnapshotSize,
2069 1,
2070 rawSnapshotSize,
2071 "raw pmem snapshot camera");
2072
2073 if (!mRawSnapShotPmemHeap->initialized()) {
2074 mRawSnapShotPmemHeap.clear();
2075 LOGE("initRawSnapshot X: error initializing mRawSnapshotHeap");
2076 return false;
2077 }
2078 LOGV("initRawSnapshot X");
2079 return true;
2080
2081}
2082
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002083bool QualcommCameraHardware::initRaw(bool initJpegHeap)
2084{
2085 int rawWidth, rawHeight;
Apurva Rajguru8d1773b2009-12-02 14:21:23 -08002086
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002087 mParameters.getPictureSize(&rawWidth, &rawHeight);
2088 LOGV("initRaw E: picture size=%dx%d", rawWidth, rawHeight);
2089
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08002090 int thumbnailBufferSize;
2091 //Thumbnail height should be smaller than Picture height
2092 if (rawHeight > thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height){
2093 mDimension.ui_thumbnail_width =
2094 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].width;
2095 mDimension.ui_thumbnail_height =
2096 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height;
2097 uint32_t pictureAspectRatio = (uint32_t)((rawWidth * Q12) / rawHeight);
2098 uint32_t i;
2099 for(i = 0; i < THUMBNAIL_SIZE_COUNT; i++ )
2100 {
2101 if(thumbnail_sizes[i].aspect_ratio == pictureAspectRatio)
2102 {
2103 mDimension.ui_thumbnail_width = thumbnail_sizes[i].width;
2104 mDimension.ui_thumbnail_height = thumbnail_sizes[i].height;
2105 break;
2106 }
2107 }
2108 }
2109 else{
2110 mDimension.ui_thumbnail_height = THUMBNAIL_SMALL_HEIGHT;
2111 mDimension.ui_thumbnail_width =
2112 (THUMBNAIL_SMALL_HEIGHT * rawWidth)/ rawHeight;
2113 }
2114
2115 LOGV("Thumbnail Size Width %d Height %d",
2116 mDimension.ui_thumbnail_width,
2117 mDimension.ui_thumbnail_height);
2118
2119 thumbnailBufferSize = mDimension.ui_thumbnail_width *
2120 mDimension.ui_thumbnail_height * 3 / 2;
2121
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002122 // mDimension will be filled with thumbnail_width, thumbnail_height,
2123 // orig_picture_dx, and orig_picture_dy after this function call. We need to
2124 // keep it for jpeg_encoder_encode.
2125 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
2126 sizeof(cam_ctrl_dimension_t), &mDimension);
2127 if(!ret) {
2128 LOGE("initRaw X: failed to set dimension");
2129 return false;
2130 }
2131
2132 if (mJpegHeap != NULL) {
2133 LOGV("initRaw: clearing old mJpegHeap.");
2134 mJpegHeap.clear();
2135 }
2136
2137 // Snapshot
2138 mRawSize = rawWidth * rawHeight * 3 / 2;
Apurva Rajguru8d1773b2009-12-02 14:21:23 -08002139
Mohan Kandra284966d2010-01-05 13:39:15 -08002140 if(!strcmp(mDeviceName,"msm7627_surf"))
Apurva Rajguru8d1773b2009-12-02 14:21:23 -08002141 mJpegMaxSize = CEILING16(rawWidth) * CEILING16(rawHeight) * 3 / 2;
2142 else
2143 mJpegMaxSize = rawWidth * rawHeight * 3 / 2;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002144
2145 LOGV("initRaw: initializing mRawHeap.");
2146 mRawHeap =
2147 new PmemPool("/dev/pmem_camera",
2148 MemoryHeapBase::READ_ONLY,
2149 mCameraControlFd,
2150 MSM_PMEM_MAINIMG,
2151 mJpegMaxSize,
2152 kRawBufferCount,
2153 mRawSize,
2154 "snapshot camera");
2155
2156 if (!mRawHeap->initialized()) {
2157 LOGE("initRaw X failed with pmem_camera, trying with pmem_adsp");
2158 mRawHeap =
2159 new PmemPool("/dev/pmem_adsp",
2160 MemoryHeapBase::READ_ONLY,
2161 mCameraControlFd,
2162 MSM_PMEM_MAINIMG,
2163 mJpegMaxSize,
2164 kRawBufferCount,
2165 mRawSize,
2166 "snapshot camera");
2167 if (!mRawHeap->initialized()) {
2168 mRawHeap.clear();
2169 LOGE("initRaw X: error initializing mRawHeap");
2170 return false;
2171 }
2172 }
2173
2174 LOGV("do_mmap snapshot pbuf = %p, pmem_fd = %d",
2175 (uint8_t *)mRawHeap->mHeap->base(), mRawHeap->mHeap->getHeapID());
2176
2177 // Jpeg
2178
2179 if (initJpegHeap) {
2180 LOGV("initRaw: initializing mJpegHeap.");
2181 mJpegHeap =
2182 new AshmemPool(mJpegMaxSize,
2183 kJpegBufferCount,
2184 0, // we do not know how big the picture will be
2185 "jpeg");
2186
2187 if (!mJpegHeap->initialized()) {
2188 mJpegHeap.clear();
2189 mRawHeap.clear();
2190 LOGE("initRaw X failed: error initializing mJpegHeap.");
2191 return false;
2192 }
2193
2194 // Thumbnails
2195
2196 mThumbnailHeap =
2197 new PmemPool("/dev/pmem_adsp",
2198 MemoryHeapBase::READ_ONLY,
2199 mCameraControlFd,
2200 MSM_PMEM_THUMBNAIL,
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08002201 thumbnailBufferSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002202 1,
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08002203 thumbnailBufferSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002204 "thumbnail");
2205
2206 if (!mThumbnailHeap->initialized()) {
2207 mThumbnailHeap.clear();
2208 mJpegHeap.clear();
2209 mRawHeap.clear();
2210 LOGE("initRaw X failed: error initializing mThumbnailHeap.");
2211 return false;
2212 }
2213 }
2214
2215 LOGV("initRaw X");
2216 return true;
2217}
2218
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002219
2220void QualcommCameraHardware::deinitRawSnapshot()
2221{
2222 LOGV("deinitRawSnapshot E");
2223 mRawSnapShotPmemHeap.clear();
2224 mRawSnapshotAshmemHeap.clear();
2225 LOGV("deinitRawSnapshot X");
2226}
2227
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002228void QualcommCameraHardware::deinitRaw()
2229{
2230 LOGV("deinitRaw E");
2231
2232 mThumbnailHeap.clear();
2233 mJpegHeap.clear();
2234 mRawHeap.clear();
2235 mDisplayHeap.clear();
2236
2237 LOGV("deinitRaw X");
2238}
2239
2240void QualcommCameraHardware::release()
2241{
2242 LOGD("release E");
2243 Mutex::Autolock l(&mLock);
2244
2245#if DLOPEN_LIBMMCAMERA
2246 if (libmmcamera == NULL) {
2247 LOGE("ERROR: multiple release!");
2248 return;
2249 }
2250#else
2251#warning "Cannot detect multiple release when not dlopen()ing libqcamera!"
2252#endif
2253
2254 int cnt, rc;
2255 struct msm_ctrl_cmd ctrlCmd;
2256
Sravankb4f5f1c2010-01-21 11:06:17 +05302257 // exit video thread
2258 mVideoThreadWaitLock.lock();
2259 LOGV("in release : making mVideoThreadExit 1");
2260 mVideoThreadExit = 1;
2261 mVideoThreadWaitLock.unlock();
2262 // 720p : signal the video thread , and check in video thread if stop is called, if so exit video thread.
2263 pthread_mutex_lock(&(g_busy_frame_queue.mut));
2264 pthread_cond_signal(&(g_busy_frame_queue.wait));
2265 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
2266
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002267 if (mCameraRunning) {
2268 if(mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME)) {
2269 mRecordFrameLock.lock();
2270 mReleasedRecordingFrame = true;
2271 mRecordWait.signal();
2272 mRecordFrameLock.unlock();
2273 }
2274 stopPreviewInternal();
2275 }
2276
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002277 if(!strncmp(mDeviceName,"msm7630", 7)) {
2278 mPostViewHeap.clear();
2279 mPostViewHeap = NULL;
2280 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002281 LINK_jpeg_encoder_join();
2282 deinitRaw();
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002283 deinitRawSnapshot();
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002284 {
2285 Mutex::Autolock l(&mCamframeTimeoutLock);
2286 if(!camframe_timeout_flag) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002287
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002288 ctrlCmd.timeout_ms = 5000;
2289 ctrlCmd.length = 0;
2290 ctrlCmd.type = (uint16_t)CAMERA_EXIT;
2291 ctrlCmd.resp_fd = mCameraControlFd; // FIXME: this will be put in by the kernel
2292 if (ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0)
2293 LOGE("ioctl CAMERA_EXIT fd %d error %s",
2294 mCameraControlFd, strerror(errno));
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002295
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002296 }
Kiran Kumar H Nac2f4952009-12-17 01:16:53 -08002297 LINK_release_cam_conf_thread();
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002298 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002299 close(mCameraControlFd);
2300 mCameraControlFd = -1;
Mohan Kandra284966d2010-01-05 13:39:15 -08002301 if(fb_fd >= 0) {
2302 close(fb_fd);
2303 fb_fd = -1;
2304 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002305#if DLOPEN_LIBMMCAMERA
2306 if (libmmcamera) {
2307 ::dlclose(libmmcamera);
2308 LOGV("dlclose(libqcamera)");
2309 libmmcamera = NULL;
2310 }
2311#endif
2312
2313 Mutex::Autolock lock(&singleton_lock);
2314 singleton_releasing = true;
2315
2316 LOGD("release X");
2317}
2318
2319QualcommCameraHardware::~QualcommCameraHardware()
2320{
2321 LOGD("~QualcommCameraHardware E");
2322 Mutex::Autolock lock(&singleton_lock);
2323 singleton.clear();
2324 singleton_releasing = false;
2325 singleton_wait.signal();
2326 LOGD("~QualcommCameraHardware X");
2327}
2328
2329sp<IMemoryHeap> QualcommCameraHardware::getRawHeap() const
2330{
2331 LOGV("getRawHeap");
2332 return mDisplayHeap != NULL ? mDisplayHeap->mHeap : NULL;
2333}
2334
2335sp<IMemoryHeap> QualcommCameraHardware::getPreviewHeap() const
2336{
2337 LOGV("getPreviewHeap");
Mohan Kandrad9efed92010-01-15 19:08:39 -08002338 return mPreviewHeap != NULL ? mPreviewHeap->mHeap : NULL;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002339}
2340
2341status_t QualcommCameraHardware::startPreviewInternal()
2342{
Sravankb4f5f1c2010-01-21 11:06:17 +05302343 LOGV("in startPreviewInternal : E");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002344 if(mCameraRunning) {
2345 LOGV("startPreview X: preview already running.");
2346 return NO_ERROR;
2347 }
2348
2349 if (!mPreviewInitialized) {
2350 mPreviewInitialized = initPreview();
2351 if (!mPreviewInitialized) {
2352 LOGE("startPreview X initPreview failed. Not starting preview.");
2353 return UNKNOWN_ERROR;
2354 }
2355 }
2356
Sravankb4f5f1c2010-01-21 11:06:17 +05302357 if( strncmp(mDeviceName,"msm7630", 7) )
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002358 mCameraRunning = native_start_preview(mCameraControlFd);
Sravankb4f5f1c2010-01-21 11:06:17 +05302359 else
2360 mCameraRunning = native_start_video(mCameraControlFd);
2361
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002362 if(!mCameraRunning) {
2363 deinitPreview();
2364 mPreviewInitialized = false;
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08002365 mOverlay = NULL;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002366 LOGE("startPreview X: native_start_preview failed!");
2367 return UNKNOWN_ERROR;
2368 }
2369
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08002370 //Reset the Gps Information
2371 exif_table_numEntries = 0;
Mohan Kandra284966d2010-01-05 13:39:15 -08002372
2373 if(native_get_maxzoom(mCameraControlFd, (void *)&mMaxZoom) == true){
2374 LOGE("Maximum zoom value is %d", mMaxZoom);
2375 mParameters.set("zoom-supported", "true");
2376 } else {
2377 LOGE("Failed to get maximum zoom value...setting max zoom to zero");
2378 mParameters.set("zoom-supported", "false");
2379 mMaxZoom = 0;
2380 }
2381 mParameters.set("max-zoom",mMaxZoom);
2382
Sravankb4f5f1c2010-01-21 11:06:17 +05302383 LOGV("startPreviewInternal X");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002384 return NO_ERROR;
2385}
2386
2387status_t QualcommCameraHardware::startPreview()
2388{
2389 LOGV("startPreview E");
2390 Mutex::Autolock l(&mLock);
2391 return startPreviewInternal();
2392}
2393
2394void QualcommCameraHardware::stopPreviewInternal()
2395{
2396 LOGV("stopPreviewInternal E: %d", mCameraRunning);
2397 if (mCameraRunning) {
2398 // Cancel auto focus.
2399 {
2400 if (mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS)) {
2401 cancelAutoFocusInternal();
2402 }
2403 }
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002404
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002405 Mutex::Autolock l(&mCamframeTimeoutLock);
2406 if(!camframe_timeout_flag) {
Sravankb4f5f1c2010-01-21 11:06:17 +05302407 if ( strncmp(mDeviceName,"msm7630", 7) )
2408 mCameraRunning = !native_stop_preview(mCameraControlFd);
2409 else
2410 mCameraRunning = !native_stop_video(mCameraControlFd);
2411
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002412 } else {
2413 /* This means that the camframetimeout was issued.
2414 * But we did not issue native_stop_preview(), so we
Kiran Kumar H Nac2f4952009-12-17 01:16:53 -08002415 * need to update mCameraRunning to indicate that
2416 * Camera is no longer running. */
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002417 mCameraRunning = 0;
Kiran Kumar H Nac2f4952009-12-17 01:16:53 -08002418 }
2419 if (!mCameraRunning && mPreviewInitialized) {
2420 deinitPreview();
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002421 mPreviewInitialized = false;
2422 }
Kiran Kumar H Nac2f4952009-12-17 01:16:53 -08002423 else LOGE("stopPreviewInternal: failed to stop preview");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002424 }
2425 LOGV("stopPreviewInternal X: %d", mCameraRunning);
2426}
2427
2428void QualcommCameraHardware::stopPreview()
2429{
2430 LOGV("stopPreview: E");
2431 Mutex::Autolock l(&mLock);
2432 {
2433 if (mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME))
2434 return;
2435 }
2436 stopPreviewInternal();
2437 LOGV("stopPreview: X");
2438}
2439
2440void QualcommCameraHardware::runAutoFocus()
2441{
2442 bool status = true;
2443 void *libhandle = NULL;
Srinivasan Kannan71229622009-12-04 12:05:58 -08002444 isp3a_af_mode_t afMode;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002445
2446 mAutoFocusThreadLock.lock();
2447 // Skip autofocus if focus mode is infinity.
2448 if (strcmp(mParameters.get(CameraParameters::KEY_FOCUS_MODE),
2449 CameraParameters::FOCUS_MODE_INFINITY) == 0) {
2450 goto done;
2451 }
2452
2453 mAutoFocusFd = open(MSM_CAMERA_CONTROL, O_RDWR);
2454 if (mAutoFocusFd < 0) {
2455 LOGE("autofocus: cannot open %s: %s",
2456 MSM_CAMERA_CONTROL,
2457 strerror(errno));
2458 mAutoFocusThreadRunning = false;
2459 mAutoFocusThreadLock.unlock();
2460 return;
2461 }
2462
2463#if DLOPEN_LIBMMCAMERA
2464 // We need to maintain a reference to libqcamera.so for the duration of the
2465 // AF thread, because we do not know when it will exit relative to the
2466 // lifetime of this object. We do not want to dlclose() libqcamera while
2467 // LINK_cam_frame is still running.
2468 libhandle = ::dlopen("liboemcamera.so", RTLD_NOW);
2469 LOGV("AF: loading libqcamera at %p", libhandle);
2470 if (!libhandle) {
2471 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
2472 close(mAutoFocusFd);
2473 mAutoFocusFd = -1;
2474 mAutoFocusThreadRunning = false;
2475 mAutoFocusThreadLock.unlock();
2476 return;
2477 }
2478#endif
2479
Srinivasan Kannan71229622009-12-04 12:05:58 -08002480 afMode = (isp3a_af_mode_t)attr_lookup(focus_modes,
2481 sizeof(focus_modes) / sizeof(str_map),
2482 mParameters.get(CameraParameters::KEY_FOCUS_MODE));
2483
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002484 /* This will block until either AF completes or is cancelled. */
Srinivasan Kannan71229622009-12-04 12:05:58 -08002485 LOGV("af start (fd %d mode %d)", mAutoFocusFd, afMode);
2486 status = native_set_afmode(mAutoFocusFd, afMode);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002487 LOGV("af done: %d", (int)status);
2488 close(mAutoFocusFd);
2489 mAutoFocusFd = -1;
2490
2491done:
2492 mAutoFocusThreadRunning = false;
2493 mAutoFocusThreadLock.unlock();
2494
2495 mCallbackLock.lock();
2496 bool autoFocusEnabled = mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS);
2497 notify_callback cb = mNotifyCallback;
2498 void *data = mCallbackCookie;
2499 mCallbackLock.unlock();
2500 if (autoFocusEnabled)
2501 cb(CAMERA_MSG_FOCUS, status, 0, data);
2502
2503#if DLOPEN_LIBMMCAMERA
2504 if (libhandle) {
2505 ::dlclose(libhandle);
2506 LOGV("AF: dlclose(libqcamera)");
2507 }
2508#endif
2509}
2510
2511status_t QualcommCameraHardware::cancelAutoFocusInternal()
2512{
2513 LOGV("cancelAutoFocusInternal E");
2514
Srinivasan Kannan71229622009-12-04 12:05:58 -08002515 if(!sensorType->hasAutoFocusSupport){
2516 LOGV("cancelAutoFocusInternal X");
2517 return NO_ERROR;
2518 }
2519
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002520#if 0
2521 if (mAutoFocusFd < 0) {
2522 LOGV("cancelAutoFocusInternal X: not in progress");
2523 return NO_ERROR;
2524 }
2525#endif
2526
2527 status_t rc = native_cancel_afmode(mCameraControlFd, mAutoFocusFd) ?
2528 NO_ERROR :
2529 UNKNOWN_ERROR;
2530
2531 LOGV("cancelAutoFocusInternal X: %d", rc);
2532 return rc;
2533}
2534
2535void *auto_focus_thread(void *user)
2536{
2537 LOGV("auto_focus_thread E");
2538 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
2539 if (obj != 0) {
2540 obj->runAutoFocus();
2541 }
2542 else LOGW("not starting autofocus: the object went away!");
2543 LOGV("auto_focus_thread X");
2544 return NULL;
2545}
2546
2547status_t QualcommCameraHardware::autoFocus()
2548{
2549 LOGV("autoFocus E");
2550 Mutex::Autolock l(&mLock);
2551
Srinivasan Kannan71229622009-12-04 12:05:58 -08002552 if(!sensorType->hasAutoFocusSupport){
Srinivasan Kannandf085222009-12-09 18:31:00 -08002553 bool status = false;
2554 mCallbackLock.lock();
2555 bool autoFocusEnabled = mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS);
2556 notify_callback cb = mNotifyCallback;
2557 void *data = mCallbackCookie;
2558 mCallbackLock.unlock();
2559 if (autoFocusEnabled)
2560 cb(CAMERA_MSG_FOCUS, status, 0, data);
Srinivasan Kannan71229622009-12-04 12:05:58 -08002561 LOGV("autoFocus X");
2562 return NO_ERROR;
2563 }
2564
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002565 if (mCameraControlFd < 0) {
2566 LOGE("not starting autofocus: main control fd %d", mCameraControlFd);
2567 return UNKNOWN_ERROR;
2568 }
2569
2570 {
2571 mAutoFocusThreadLock.lock();
2572 if (!mAutoFocusThreadRunning) {
2573 // Create a detached thread here so that we don't have to wait
2574 // for it when we cancel AF.
2575 pthread_t thr;
2576 pthread_attr_t attr;
2577 pthread_attr_init(&attr);
2578 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2579 mAutoFocusThreadRunning =
2580 !pthread_create(&thr, &attr,
2581 auto_focus_thread, NULL);
2582 if (!mAutoFocusThreadRunning) {
2583 LOGE("failed to start autofocus thread");
2584 mAutoFocusThreadLock.unlock();
2585 return UNKNOWN_ERROR;
2586 }
2587 }
2588 mAutoFocusThreadLock.unlock();
2589 }
2590
2591 LOGV("autoFocus X");
2592 return NO_ERROR;
2593}
2594
2595status_t QualcommCameraHardware::cancelAutoFocus()
2596{
2597 LOGV("cancelAutoFocus E");
2598 Mutex::Autolock l(&mLock);
2599
2600 int rc = NO_ERROR;
2601 if (mCameraRunning && mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS)) {
2602 rc = cancelAutoFocusInternal();
2603 }
2604
2605 LOGV("cancelAutoFocus X");
2606 return rc;
2607}
2608
2609void QualcommCameraHardware::runSnapshotThread(void *data)
2610{
2611 LOGV("runSnapshotThread E");
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002612 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
2613 if (native_start_snapshot(mCameraControlFd))
2614 receiveRawPicture();
2615 else
2616 LOGE("main: native_start_snapshot failed!");
2617 } else if(mSnapshotFormat == PICTURE_FORMAT_RAW){
2618 if(native_start_raw_snapshot(mCameraControlFd)){
2619 receiveRawSnapshot();
2620 } else {
2621 LOGE("main: native_start_raw_snapshot failed!");
2622 }
2623 }
2624
2625 mSnapshotFormat = 0;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002626
2627 mSnapshotThreadWaitLock.lock();
2628 mSnapshotThreadRunning = false;
2629 mSnapshotThreadWait.signal();
2630 mSnapshotThreadWaitLock.unlock();
2631
2632 LOGV("runSnapshotThread X");
2633}
2634
2635void *snapshot_thread(void *user)
2636{
2637 LOGD("snapshot_thread E");
2638 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
2639 if (obj != 0) {
2640 obj->runSnapshotThread(user);
2641 }
2642 else LOGW("not starting snapshot thread: the object went away!");
2643 LOGD("snapshot_thread X");
2644 return NULL;
2645}
2646
2647status_t QualcommCameraHardware::takePicture()
2648{
2649 LOGV("takePicture(%d)", mMsgEnabled);
2650 Mutex::Autolock l(&mLock);
2651
2652 // Wait for old snapshot thread to complete.
2653 mSnapshotThreadWaitLock.lock();
2654 while (mSnapshotThreadRunning) {
2655 LOGV("takePicture: waiting for old snapshot thread to complete.");
2656 mSnapshotThreadWait.wait(mSnapshotThreadWaitLock);
2657 LOGV("takePicture: old snapshot thread completed.");
2658 }
2659
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002660 if(!strcmp(mDeviceName,"msm7630_surf")) {
2661 /* Store the last frame queued for preview. This
2662 * shall be used as postview */
2663 storePreviewFrameForPostview();
2664 }
2665
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002666 //mSnapshotFormat is protected by mSnapshotThreadWaitLock
2667 if(mParameters.getPictureFormat() != 0 &&
2668 !strcmp(mParameters.getPictureFormat(),
2669 CameraParameters::PIXEL_FORMAT_RAW))
2670 mSnapshotFormat = PICTURE_FORMAT_RAW;
2671 else
2672 mSnapshotFormat = PICTURE_FORMAT_JPEG;
2673
2674 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
2675 if(!native_prepare_snapshot(mCameraControlFd)) {
2676 mSnapshotThreadWaitLock.unlock();
2677 return UNKNOWN_ERROR;
2678 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002679 }
2680
2681 stopPreviewInternal();
2682
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002683 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
2684 if (!initRaw(mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE))) {
2685 LOGE("initRaw failed. Not taking picture.");
2686 mSnapshotThreadWaitLock.unlock();
2687 return UNKNOWN_ERROR;
2688 }
2689 } else if(mSnapshotFormat == PICTURE_FORMAT_RAW ){
2690 if(!initRawSnapshot()){
2691 LOGE("initRawSnapshot failed. Not taking picture.");
2692 mSnapshotThreadWaitLock.unlock();
2693 return UNKNOWN_ERROR;
2694 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002695 }
2696
2697 mShutterLock.lock();
2698 mShutterPending = true;
2699 mShutterLock.unlock();
2700
2701 pthread_attr_t attr;
2702 pthread_attr_init(&attr);
2703 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2704 mSnapshotThreadRunning = !pthread_create(&mSnapshotThread,
2705 &attr,
2706 snapshot_thread,
2707 NULL);
2708 mSnapshotThreadWaitLock.unlock();
2709
2710 LOGV("takePicture: X");
2711 return mSnapshotThreadRunning ? NO_ERROR : UNKNOWN_ERROR;
2712}
2713
2714status_t QualcommCameraHardware::cancelPicture()
2715{
2716 status_t rc;
2717 LOGV("cancelPicture: E");
2718 rc = native_stop_snapshot(mCameraControlFd) ? NO_ERROR : UNKNOWN_ERROR;
2719 LOGV("cancelPicture: X: %d", rc);
2720 return rc;
2721}
2722
2723status_t QualcommCameraHardware::setParameters(const CameraParameters& params)
2724{
2725 LOGV("setParameters: E params = %p", &params);
2726
2727 Mutex::Autolock l(&mLock);
2728 status_t rc, final_rc = NO_ERROR;
2729
2730 if ((rc = setPreviewSize(params))) final_rc = rc;
2731 if ((rc = setPictureSize(params))) final_rc = rc;
2732 if ((rc = setJpegQuality(params))) final_rc = rc;
2733 if ((rc = setAntibanding(params))) final_rc = rc;
2734 if ((rc = setEffect(params))) final_rc = rc;
Apurva Rajguru55562b02009-12-03 12:25:35 -08002735 if ((rc = setAutoExposure(params))) final_rc = rc;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002736 if ((rc = setWhiteBalance(params))) final_rc = rc;
2737 if ((rc = setFlash(params))) final_rc = rc;
2738 if ((rc = setGpsLocation(params))) final_rc = rc;
2739 if ((rc = setRotation(params))) final_rc = rc;
2740 if ((rc = setZoom(params))) final_rc = rc;
2741 if ((rc = setFocusMode(params))) final_rc = rc;
2742 if ((rc = setOrientation(params))) final_rc = rc;
Nishant Panditc8c1ee72009-12-03 16:24:02 +05302743 if ((rc = setBrightness(params))) final_rc = rc;
2744 if ((rc = setLensshadeValue(params))) final_rc = rc;
2745 if ((rc = setISOValue(params))) final_rc = rc;
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002746 if ((rc = setPictureFormat(params))) final_rc = rc;
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08002747 if ((rc = setSharpness(params))) final_rc = rc;
2748 if ((rc = setContrast(params))) final_rc = rc;
2749 if ((rc = setSaturation(params))) final_rc = rc;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002750
2751 LOGV("setParameters: X");
2752 return final_rc;
2753}
2754
2755CameraParameters QualcommCameraHardware::getParameters() const
2756{
2757 LOGV("getParameters: EX");
2758 return mParameters;
2759}
2760
2761status_t QualcommCameraHardware::sendCommand(int32_t command, int32_t arg1,
2762 int32_t arg2)
2763{
2764 LOGV("sendCommand: EX");
2765 return BAD_VALUE;
2766}
2767
2768extern "C" sp<CameraHardwareInterface> openCameraHardware()
2769{
2770 LOGV("openCameraHardware: call createInstance");
2771 return QualcommCameraHardware::createInstance();
2772}
2773
2774wp<QualcommCameraHardware> QualcommCameraHardware::singleton;
2775
2776// If the hardware already exists, return a strong pointer to the current
2777// object. If not, create a new hardware object, put it in the singleton,
2778// and return it.
2779sp<CameraHardwareInterface> QualcommCameraHardware::createInstance()
2780{
2781 LOGD("createInstance: E");
2782
2783 Mutex::Autolock lock(&singleton_lock);
2784
2785 // Wait until the previous release is done.
2786 while (singleton_releasing) {
2787 LOGD("Wait for previous release.");
2788 singleton_wait.wait(singleton_lock);
2789 }
2790
2791 if (singleton != 0) {
2792 sp<CameraHardwareInterface> hardware = singleton.promote();
2793 if (hardware != 0) {
2794 LOGD("createInstance: X return existing hardware=%p", &(*hardware));
2795 return hardware;
2796 }
2797 }
2798
2799 {
2800 struct stat st;
2801 int rc = stat("/dev/oncrpc", &st);
2802 if (rc < 0) {
2803 LOGD("createInstance: X failed to create hardware: %s", strerror(errno));
2804 return NULL;
2805 }
2806 }
2807
2808 QualcommCameraHardware *cam = new QualcommCameraHardware();
2809 sp<QualcommCameraHardware> hardware(cam);
2810 singleton = hardware;
2811
2812 if (!cam->startCamera()) {
2813 LOGE("%s: startCamera failed!", __FUNCTION__);
2814 return NULL;
2815 }
2816
2817 cam->initDefaultParameters();
2818 LOGD("createInstance: X created hardware=%p", &(*hardware));
2819 return hardware;
2820}
2821
2822// For internal use only, hence the strong pointer to the derived type.
2823sp<QualcommCameraHardware> QualcommCameraHardware::getInstance()
2824{
2825 sp<CameraHardwareInterface> hardware = singleton.promote();
2826 if (hardware != 0) {
2827 // LOGV("getInstance: X old instance of hardware");
2828 return sp<QualcommCameraHardware>(static_cast<QualcommCameraHardware*>(hardware.get()));
2829 } else {
2830 LOGV("getInstance: X new instance of hardware");
2831 return sp<QualcommCameraHardware>();
2832 }
2833}
Sravankb4f5f1c2010-01-21 11:06:17 +05302834void QualcommCameraHardware::receiveRecordingFrame(struct msm_frame *frame)
2835{
2836 LOGV("receiveRecordingFrame E");
2837 // post busy frame
2838 if (frame)
2839 {
2840 cam_frame_post_video (frame);
2841 }
2842 else LOGE("in receiveRecordingFrame frame is NULL");
2843 LOGV("receiveRecordingFrame X");
2844}
2845
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002846
Mohan Kandrad9efed92010-01-15 19:08:39 -08002847bool QualcommCameraHardware::native_zoom_image(int fd, int srcOffset, int dstOffSet, common_crop_t *crop)
Mohan Kandra284966d2010-01-05 13:39:15 -08002848{
2849 int result = 0;
2850 struct mdp_blit_req *e;
2851 struct timeval td1, td2;
2852
Mohan Kandra284966d2010-01-05 13:39:15 -08002853 /* Initialize yuv structure */
2854 zoomImage.list.count = 1;
2855
2856 e = &zoomImage.list.req[0];
2857
2858 e->src.width = previewWidth;
2859 e->src.height = previewHeight;
2860 e->src.format = MDP_Y_CBCR_H2V2;
Mohan Kandrad9efed92010-01-15 19:08:39 -08002861 e->src.offset = srcOffset;
2862 e->src.memory_id = fd;
Mohan Kandra284966d2010-01-05 13:39:15 -08002863
2864 e->dst.width = previewWidth;
2865 e->dst.height = previewHeight;
2866 e->dst.format = MDP_Y_CBCR_H2V2;
Mohan Kandrad9efed92010-01-15 19:08:39 -08002867 e->dst.offset = dstOffSet;
2868 e->dst.memory_id = fd;
Mohan Kandra284966d2010-01-05 13:39:15 -08002869
2870 e->transp_mask = 0xffffffff;
2871 e->flags = 0;
2872 e->alpha = 0xff;
2873 if (crop->in2_w != 0 || crop->in2_h != 0) {
2874 e->src_rect.x = (crop->out2_w - crop->in2_w + 1) / 2 - 1;
2875 e->src_rect.y = (crop->out2_h - crop->in2_h + 1) / 2 - 1;
2876 e->src_rect.w = crop->in2_w;
2877 e->src_rect.h = crop->in2_h;
2878 } else {
2879 e->src_rect.x = 0;
2880 e->src_rect.y = 0;
2881 e->src_rect.w = previewWidth;
2882 e->src_rect.h = previewHeight;
2883 }
Mohan Kandrad9efed92010-01-15 19:08:39 -08002884 //LOGV(" native_zoom : SRC_RECT : x,y = %d,%d \t w,h = %d, %d",
2885 // e->src_rect.x, e->src_rect.y, e->src_rect.w, e->src_rect.h);
Mohan Kandra284966d2010-01-05 13:39:15 -08002886
2887 e->dst_rect.x = 0;
2888 e->dst_rect.y = 0;
2889 e->dst_rect.w = previewWidth;
2890 e->dst_rect.h = previewHeight;
2891
2892 result = ioctl(fb_fd, MSMFB_BLIT, &zoomImage.list);
2893 if (result < 0) {
2894 LOGE("MSM_FBIOBLT failed! line=%d\n", __LINE__);
2895 return FALSE;
2896 }
2897 return TRUE;
2898}
2899
Mohan Kandra740cfce2010-01-07 12:58:24 -08002900void QualcommCameraHardware::debugShowFPS() const
2901{
2902 static int mFrameCount;
2903 static int mLastFrameCount = 0;
2904 static nsecs_t mLastFpsTime = 0;
2905 static float mFps = 0;
2906 mFrameCount++;
2907 nsecs_t now = systemTime();
2908 nsecs_t diff = now - mLastFpsTime;
2909 if (diff > ms2ns(250)) {
2910 mFps = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
2911 LOGI("Frames Per Second: %.4f", mFps);
2912 mLastFpsTime = now;
2913 mLastFrameCount = mFrameCount;
2914 }
2915}
2916
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002917void QualcommCameraHardware::receivePreviewFrame(struct msm_frame *frame)
2918{
2919// LOGV("receivePreviewFrame E");
2920
2921 if (!mCameraRunning) {
2922 LOGE("ignoring preview callback--camera has been stopped");
2923 return;
2924 }
2925
Mohan Kandra740cfce2010-01-07 12:58:24 -08002926 if (UNLIKELY(mDebugFps)) {
2927 debugShowFPS();
2928 }
2929
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002930 mCallbackLock.lock();
2931 int msgEnabled = mMsgEnabled;
2932 data_callback pcb = mDataCallback;
2933 void *pdata = mCallbackCookie;
2934 data_callback_timestamp rcb = mDataCallbackTimestamp;
2935 void *rdata = mCallbackCookie;
2936 mCallbackLock.unlock();
2937
2938 // Find the offset within the heap of the current buffer.
Mohan Kandra284966d2010-01-05 13:39:15 -08002939 ssize_t offset_addr =
Mohan Kandrad9efed92010-01-15 19:08:39 -08002940 (ssize_t)frame->buffer - (ssize_t)mPreviewHeap->mHeap->base();
2941 ssize_t offset = offset_addr / mPreviewHeap->mAlignedBufferSize;
Mohan Kandra284966d2010-01-05 13:39:15 -08002942
2943 common_crop_t *crop = (common_crop_t *) (frame->cropinfo);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002944
2945 mInPreviewCallback = true;
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002946 if(mUseOverlay) {
2947 if(mOverlay != NULL) {
2948 mOverlayLock.lock();
Mohan Kandrad9efed92010-01-15 19:08:39 -08002949 mOverlay->setFd(mPreviewHeap->mHeap->getHeapID());
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002950 if (crop->in2_w != 0 || crop->in2_h != 0) {
2951 zoomCropInfo.x = (crop->out2_w - crop->in2_w + 1) / 2 - 1;
2952 zoomCropInfo.y = (crop->out2_h - crop->in2_h + 1) / 2 - 1;
2953 zoomCropInfo.w = crop->in2_w;
2954 zoomCropInfo.h = crop->in2_h;
2955 mOverlay->setCrop(zoomCropInfo.x, zoomCropInfo.y,
2956 zoomCropInfo.w, zoomCropInfo.h);
2957 }
2958 mOverlay->queueBuffer((void *)offset_addr);
2959 mLastQueuedFrame = (void *)frame->buffer;
2960 mOverlayLock.unlock();
2961 }
Mohan Kandra284966d2010-01-05 13:39:15 -08002962 } else {
Mohan Kandrad9efed92010-01-15 19:08:39 -08002963 if (crop->in2_w != 0 || crop->in2_h != 0) {
2964 dstOffset = (dstOffset + 1) % NUM_MORE_BUFS;
2965 offset = kPreviewBufferCount + dstOffset;
2966 ssize_t dstOffset_addr = offset * mPreviewHeap->mAlignedBufferSize;
2967 if( !native_zoom_image(mPreviewHeap->mHeap->getHeapID(),
2968 offset_addr, dstOffset_addr, crop)) {
2969 LOGE(" Error while doing MDP zoom ");
2970 }
2971 }
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08002972 }
Mohan Kandrad9efed92010-01-15 19:08:39 -08002973 if (pcb != NULL && (msgEnabled & CAMERA_MSG_PREVIEW_FRAME))
2974 pcb(CAMERA_MSG_PREVIEW_FRAME, mPreviewHeap->mBuffers[offset],
2975 pdata);
2976
Sravankb4f5f1c2010-01-21 11:06:17 +05302977 // If output2 enabled, Start Recording if recording is enabled by Services
2978 if(!strncmp(mDeviceName,"msm7630", 7) && recordingEnabled() ) {
2979 if(!recordingState){
2980 recordingState = 1; // recording started
2981 LOGV(" in receivePreviewframe : recording enabled calling startRecording ");
2982 startRecording();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002983 }
Sravankb4f5f1c2010-01-21 11:06:17 +05302984 }
2985
2986 // If output is NOT enabled (targets otherthan 7x30 currently..)
2987 if(strncmp(mDeviceName,"msm7630", 7)) {
2988 if(rcb != NULL && (msgEnabled & CAMERA_MSG_VIDEO_FRAME)) {
2989 rcb(systemTime(), CAMERA_MSG_VIDEO_FRAME, mPreviewHeap->mBuffers[offset], rdata);
2990 Mutex::Autolock rLock(&mRecordFrameLock);
2991 if (mReleasedRecordingFrame != true) {
2992 LOGV("block waiting for frame release");
2993 mRecordWait.wait(mRecordFrameLock);
2994 LOGV("frame released, continuing");
2995 }
2996 mReleasedRecordingFrame = false;
2997 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002998 }
2999 mInPreviewCallback = false;
3000
3001// LOGV("receivePreviewFrame X");
3002}
3003
Sravankb4f5f1c2010-01-21 11:06:17 +05303004
3005bool QualcommCameraHardware::initRecord()
3006{
3007 LOGV("initREcord E");
3008
3009 mRecordFrameSize = (mDimension.video_width * mDimension.video_height *3)/2;
3010 mRecordHeap = new PmemPool("/dev/pmem_adsp",
3011 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
3012 mCameraControlFd,
3013 MSM_PMEM_VIDEO,
3014 mRecordFrameSize,
3015 kRecordBufferCount,
3016 mRecordFrameSize,
3017 "record");
3018 if (!mRecordHeap->initialized()) {
3019 mRecordHeap.clear();
3020 LOGE("initRecord X: could not initialize record heap.");
3021 return false;
3022 }
3023 for (int cnt = 0; cnt < kRecordBufferCount; cnt++) {
3024 recordframes[cnt].fd = mRecordHeap->mHeap->getHeapID();
3025 recordframes[cnt].buffer =
3026 (uint32_t)mRecordHeap->mHeap->base() + mRecordHeap->mAlignedBufferSize * cnt;
3027 recordframes[cnt].y_off = 0;
3028 recordframes[cnt].cbcr_off = mDimension.video_width * mDimension.video_height;
3029 recordframes[cnt].path = OUTPUT_TYPE_V;
3030
3031 LOGV ("initRecord : record heap , video buffers buffer=%lu fd=%d y_off=%d cbcr_off=%d \n",
3032 (unsigned long)recordframes[cnt].buffer, recordframes[cnt].fd, recordframes[cnt].y_off,
3033 recordframes[cnt].cbcr_off);
3034 }
3035
3036 // initial setup : buffers 1,2,3 with kernel , 4 with camframe , 5,6,7,8 in free Q
3037 // flush the busy Q
3038 cam_frame_flush_video();
3039
3040 // Start video thread and wait for busy frames to be encoded.
3041 mVideoThreadWaitLock.lock();
3042 mVideoThreadExit = 0;
3043 pthread_attr_t attr;
3044 pthread_attr_init(&attr);
3045 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
3046 pthread_create(&mVideoThread,
3047 &attr,
3048 video_thread,
3049 NULL);
3050 mVideoThreadWaitLock.unlock();
3051 LOGV("initREcord X");
3052
3053 return true;
3054}
3055
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003056status_t QualcommCameraHardware::startRecording()
3057{
3058 LOGV("startRecording E");
Sravankb4f5f1c2010-01-21 11:06:17 +05303059 int ret;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003060 Mutex::Autolock l(&mLock);
3061 mReleasedRecordingFrame = false;
Sravankb4f5f1c2010-01-21 11:06:17 +05303062 if( (ret=startPreviewInternal())== NO_ERROR){
3063 if(!strncmp(mDeviceName,"msm7630", 7)) {
3064 // flush free queue and add 5,6,7,8 buffers.
3065 LINK_cam_frame_flush_free_video();
3066 for(int i=ACTIVE_VIDEO_BUFFERS+1;i <kRecordBufferCount; i++)
3067 LINK_camframe_free_video(&recordframes[i]);
3068
3069 LOGV(" in startREcording : calling native_start_recording");
3070 native_start_recording(mCameraControlFd);
3071 recordingState = 1;
3072 }
3073 }
3074 return ret;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003075}
3076
3077void QualcommCameraHardware::stopRecording()
3078{
3079 LOGV("stopRecording: E");
3080 Mutex::Autolock l(&mLock);
3081 {
3082 mRecordFrameLock.lock();
3083 mReleasedRecordingFrame = true;
3084 mRecordWait.signal();
3085 mRecordFrameLock.unlock();
3086
3087 if(mDataCallback && (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)) {
3088 LOGV("stopRecording: X, preview still in progress");
3089 return;
3090 }
3091 }
Sravankb4f5f1c2010-01-21 11:06:17 +05303092 // If output2 enabled, exit video thread, invoke stop recording ioctl
3093 if(!strncmp(mDeviceName,"msm7630", 7)) {
3094 mVideoThreadWaitLock.lock();
3095 mVideoThreadExit = 1;
3096 mVideoThreadWaitLock.unlock();
3097 native_stop_recording(mCameraControlFd);
3098 }
3099 else // for other targets where output2 is not enabled
3100 stopPreviewInternal();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003101
Sravankb4f5f1c2010-01-21 11:06:17 +05303102 recordingState = 0; // recording not started
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003103 LOGV("stopRecording: X");
3104}
3105
3106void QualcommCameraHardware::releaseRecordingFrame(
3107 const sp<IMemory>& mem __attribute__((unused)))
3108{
3109 LOGV("releaseRecordingFrame E");
3110 Mutex::Autolock rLock(&mRecordFrameLock);
3111 mReleasedRecordingFrame = true;
3112 mRecordWait.signal();
Sravankb4f5f1c2010-01-21 11:06:17 +05303113
3114 // Ff 7x30 : add the frame to the free camframe queue
3115 if(!strcmp(mDeviceName,"msm7630_surf")) {
3116 ssize_t offset;
3117 size_t size;
3118 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
3119 msm_frame* releaseframe = NULL;
3120 LOGV(" in release recording frame : heap base %d offset %d buffer %d ", heap->base(), offset, heap->base() + offset );
3121 int cnt;
3122 for (cnt = 0; cnt < kRecordBufferCount; cnt++) {
3123 if((unsigned int)recordframes[cnt].buffer == (unsigned int)(heap->base()+ offset)){
3124 LOGV("in release recording frame found match , releasing buffer %d", (unsigned int)recordframes[cnt].buffer);
3125 releaseframe = &recordframes[cnt];
3126 break;
3127 }
3128 }
3129 if(cnt < kRecordBufferCount) {
3130 // do this only if frame thread is running
3131 mFrameThreadWaitLock.lock();
3132 if(mFrameThreadRunning )
3133 LINK_camframe_free_video(releaseframe);
3134
3135 mFrameThreadWaitLock.unlock();
3136 } else {
3137 LOGE("in release recordingframe XXXXX error , buffer not found");
3138 for (int i=0; i< kRecordBufferCount; i++) {
3139 LOGE(" recordframes[%d].buffer = %d", i, (unsigned int)recordframes[i].buffer);
3140 }
3141 }
3142 }
3143
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003144 LOGV("releaseRecordingFrame X");
3145}
3146
3147bool QualcommCameraHardware::recordingEnabled()
3148{
3149 return mCameraRunning && mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME);
3150}
3151
3152void QualcommCameraHardware::notifyShutter(common_crop_t *crop)
3153{
3154 mShutterLock.lock();
3155 image_rect_type size;
3156
3157 if (mShutterPending && mNotifyCallback && (mMsgEnabled & CAMERA_MSG_SHUTTER)) {
3158 LOGV("out2_w=%d, out2_h=%d, in2_w=%d, in2_h=%d",
3159 crop->out2_w, crop->out2_h, crop->in2_w, crop->in2_h);
3160 LOGV("out1_w=%d, out1_h=%d, in1_w=%d, in1_h=%d",
3161 crop->out1_w, crop->out1_h, crop->in1_w, crop->in1_h);
3162
3163 // To workaround a bug in MDP which happens if either
3164 // dimension > 2048, we display the thumbnail instead.
3165 mDisplayHeap = mRawHeap;
3166 if (crop->in1_w == 0 || crop->in1_h == 0) {
3167 // Full size
3168 size.width = mDimension.picture_width;
3169 size.height = mDimension.picture_height;
3170 if (size.width > 2048 || size.height > 2048) {
3171 size.width = mDimension.ui_thumbnail_width;
3172 size.height = mDimension.ui_thumbnail_height;
3173 mDisplayHeap = mThumbnailHeap;
3174 }
3175 } else {
3176 // Cropped
3177 size.width = crop->in2_w & ~1;
3178 size.height = crop->in2_h & ~1;
3179 if (size.width > 2048 || size.height > 2048) {
3180 size.width = crop->in1_w & ~1;
3181 size.height = crop->in1_h & ~1;
3182 mDisplayHeap = mThumbnailHeap;
3183 }
3184 }
3185
3186 mNotifyCallback(CAMERA_MSG_SHUTTER, (int32_t)&size, 0,
3187 mCallbackCookie);
3188 mShutterPending = false;
3189 }
3190 mShutterLock.unlock();
3191}
3192
3193static void receive_shutter_callback(common_crop_t *crop)
3194{
3195 LOGV("receive_shutter_callback: E");
3196 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
3197 if (obj != 0) {
3198 obj->notifyShutter(crop);
3199 }
3200 LOGV("receive_shutter_callback: X");
3201}
3202
3203// Crop the picture in place.
3204static void crop_yuv420(uint32_t width, uint32_t height,
3205 uint32_t cropped_width, uint32_t cropped_height,
3206 uint8_t *image)
3207{
3208 uint32_t i, x, y;
3209 uint8_t* chroma_src, *chroma_dst;
3210
3211 // Calculate the start position of the cropped area.
3212 x = (width - cropped_width) / 2;
3213 y = (height - cropped_height) / 2;
3214 x &= ~1;
3215 y &= ~1;
3216
3217 // Copy luma component.
3218 for(i = 0; i < cropped_height; i++)
3219 memcpy(image + i * cropped_width,
3220 image + width * (y + i) + x,
3221 cropped_width);
3222
3223 chroma_src = image + width * height;
3224 chroma_dst = image + cropped_width * cropped_height;
3225
3226 // Copy chroma components.
3227 cropped_height /= 2;
3228 y /= 2;
3229 for(i = 0; i < cropped_height; i++)
3230 memcpy(chroma_dst + i * cropped_width,
3231 chroma_src + width * (y + i) + x,
3232 cropped_width);
3233}
3234
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08003235
3236void QualcommCameraHardware::receiveRawSnapshot(){
3237 LOGV("receiveRawSnapshot E");
3238
3239 Mutex::Autolock cbLock(&mCallbackLock);
3240
3241 notifyShutter(&mCrop);
3242
3243 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
3244
3245 if(native_get_picture(mCameraControlFd, &mCrop) == false) {
3246 LOGE("receiveRawSnapshot X: native_get_picture failed!");
3247 return;
3248 }
3249
3250 //Create a Ashmem heap to copy data from PMem heap for application layer
3251 if(mRawSnapshotAshmemHeap != NULL){
3252 LOGV("receiveRawSnapshot: clearing old mRawSnapShotAshmemHeap.");
3253 mRawSnapshotAshmemHeap.clear();
3254 }
3255 mRawSnapshotAshmemHeap = new AshmemPool(
3256 mRawSnapShotPmemHeap->mBufferSize,
3257 mRawSnapShotPmemHeap->mNumBuffers,
3258 mRawSnapShotPmemHeap->mFrameSize,
3259 "raw ashmem snapshot camera"
3260 );
3261
3262 if(!mRawSnapshotAshmemHeap->initialized()){
3263 LOGE("receiveRawSnapshot X: error initializing mRawSnapshotHeap");
3264 deinitRawSnapshot();
3265 return;
3266 }
3267
3268 memcpy(mRawSnapshotAshmemHeap->mHeap->base(),
3269 mRawSnapShotPmemHeap->mHeap->base(),
3270 mRawSnapShotPmemHeap->mHeap->getSize());
3271
3272 mDataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mRawSnapshotAshmemHeap->mBuffers[0],
3273 mCallbackCookie);
3274
3275 }
3276
3277 //cleanup
3278 deinitRawSnapshot();
3279
3280 LOGV("receiveRawSnapshot X");
3281}
3282
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003283void QualcommCameraHardware::receiveRawPicture()
3284{
3285 LOGV("receiveRawPicture: E");
3286
3287 Mutex::Autolock cbLock(&mCallbackLock);
3288 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_RAW_IMAGE)) {
3289 if(native_get_picture(mCameraControlFd, &mCrop) == false) {
3290 LOGE("getPicture failed!");
3291 return;
3292 }
3293 mCrop.in1_w &= ~1;
3294 mCrop.in1_h &= ~1;
3295 mCrop.in2_w &= ~1;
3296 mCrop.in2_h &= ~1;
3297
3298 // By the time native_get_picture returns, picture is taken. Call
3299 // shutter callback if cam config thread has not done that.
3300 notifyShutter(&mCrop);
3301
3302 // Crop the image if zoomed.
3303 if (mCrop.in2_w != 0 && mCrop.in2_h != 0) {
3304 crop_yuv420(mCrop.out2_w, mCrop.out2_h, mCrop.in2_w, mCrop.in2_h,
3305 (uint8_t *)mRawHeap->mHeap->base());
3306 crop_yuv420(mCrop.out1_w, mCrop.out1_h, mCrop.in1_w, mCrop.in1_h,
3307 (uint8_t *)mThumbnailHeap->mHeap->base());
3308 // We do not need jpeg encoder to upscale the image. Set the new
3309 // dimension for encoder.
3310 mDimension.orig_picture_dx = mCrop.in2_w;
3311 mDimension.orig_picture_dy = mCrop.in2_h;
3312 mDimension.thumbnail_width = mCrop.in1_w;
3313 mDimension.thumbnail_height = mCrop.in1_h;
3314 memset(&mCrop, 0, sizeof(mCrop));
3315 }
3316
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003317 if( mUseOverlay && (mOverlay != NULL) ) {
3318 mOverlay->setFd(mPostViewHeap->mHeap->getHeapID());
3319 if( zoomCropInfo.w !=0 && zoomCropInfo.h !=0) {
3320 LOGD(" zoomCropInfo non-zero, setting crop ");
3321 mOverlay->setCrop(zoomCropInfo.x, zoomCropInfo.y,
3322 zoomCropInfo.w, zoomCropInfo.h);
3323 }
3324 LOGD(" Queueing Postview for display ");
3325 mOverlay->queueBuffer((void *)0);
3326 }
3327
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003328 mDataCallback(CAMERA_MSG_RAW_IMAGE, mDisplayHeap->mBuffers[0],
3329 mCallbackCookie);
3330 }
3331 else LOGV("Raw-picture callback was canceled--skipping.");
3332
3333 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
3334 mJpegSize = 0;
3335 if (LINK_jpeg_encoder_init()) {
3336 if(native_jpeg_encode()) {
3337 LOGV("receiveRawPicture: X (success)");
3338 return;
3339 }
3340 LOGE("jpeg encoding failed");
3341 }
3342 else LOGE("receiveRawPicture X: jpeg_encoder_init failed.");
3343 }
3344 else LOGV("JPEG callback is NULL, not encoding image.");
3345 deinitRaw();
3346 LOGV("receiveRawPicture: X");
3347}
3348
3349void QualcommCameraHardware::receiveJpegPictureFragment(
3350 uint8_t *buff_ptr, uint32_t buff_size)
3351{
3352 uint32_t remaining = mJpegHeap->mHeap->virtualSize();
3353 remaining -= mJpegSize;
3354 uint8_t *base = (uint8_t *)mJpegHeap->mHeap->base();
3355
3356 LOGV("receiveJpegPictureFragment size %d", buff_size);
3357 if (buff_size > remaining) {
3358 LOGE("receiveJpegPictureFragment: size %d exceeds what "
3359 "remains in JPEG heap (%d), truncating",
3360 buff_size,
3361 remaining);
3362 buff_size = remaining;
3363 }
3364 memcpy(base + mJpegSize, buff_ptr, buff_size);
3365 mJpegSize += buff_size;
3366}
3367
3368void QualcommCameraHardware::receiveJpegPicture(void)
3369{
3370 LOGV("receiveJpegPicture: E image (%d uint8_ts out of %d)",
3371 mJpegSize, mJpegHeap->mBufferSize);
3372 Mutex::Autolock cbLock(&mCallbackLock);
3373
3374 int index = 0, rc;
3375
3376 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
3377 // The reason we do not allocate into mJpegHeap->mBuffers[offset] is
3378 // that the JPEG image's size will probably change from one snapshot
3379 // to the next, so we cannot reuse the MemoryBase object.
3380 sp<MemoryBase> buffer = new
3381 MemoryBase(mJpegHeap->mHeap,
3382 index * mJpegHeap->mBufferSize +
3383 0,
3384 mJpegSize);
3385 mDataCallback(CAMERA_MSG_COMPRESSED_IMAGE, buffer, mCallbackCookie);
3386 buffer = NULL;
3387 }
3388 else LOGV("JPEG callback was cancelled--not delivering image.");
3389
3390 LINK_jpeg_encoder_join();
3391 deinitRaw();
3392
3393 LOGV("receiveJpegPicture: X callback done.");
3394}
3395
3396bool QualcommCameraHardware::previewEnabled()
3397{
3398 return mCameraRunning && mDataCallback && (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME);
3399}
3400
3401status_t QualcommCameraHardware::setPreviewSize(const CameraParameters& params)
3402{
3403 int width, height;
3404 params.getPreviewSize(&width, &height);
3405 LOGV("requested preview size %d x %d", width, height);
3406
3407 // Validate the preview size
3408 for (size_t i = 0; i < PREVIEW_SIZE_COUNT; ++i) {
3409 if (width == preview_sizes[i].width
3410 && height == preview_sizes[i].height) {
3411 mParameters.setPreviewSize(width, height);
3412 mDimension.display_width = width;
3413 mDimension.display_height = height;
3414 return NO_ERROR;
3415 }
3416 }
3417 LOGE("Invalid preview size requested: %dx%d", width, height);
3418 return BAD_VALUE;
3419}
3420
3421status_t QualcommCameraHardware::setPictureSize(const CameraParameters& params)
3422{
3423 int width, height;
3424 params.getPictureSize(&width, &height);
3425 LOGV("requested picture size %d x %d", width, height);
3426
3427 // Validate the picture size
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -08003428 for (int i = 0; i < supportedPictureSizesCount; ++i) {
3429 if (width == picture_sizes_ptr[i].width
3430 && height == picture_sizes_ptr[i].height) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003431 mParameters.setPictureSize(width, height);
3432 mDimension.picture_width = width;
3433 mDimension.picture_height = height;
3434 return NO_ERROR;
3435 }
3436 }
3437 LOGE("Invalid picture size requested: %dx%d", width, height);
3438 return BAD_VALUE;
3439}
3440
3441status_t QualcommCameraHardware::setJpegQuality(const CameraParameters& params) {
3442 status_t rc = NO_ERROR;
3443 int quality = params.getInt(CameraParameters::KEY_JPEG_QUALITY);
3444 if (quality > 0 && quality <= 100) {
3445 mParameters.set(CameraParameters::KEY_JPEG_QUALITY, quality);
3446 } else {
3447 LOGE("Invalid jpeg quality=%d", quality);
3448 rc = BAD_VALUE;
3449 }
3450
3451 quality = params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY);
3452 if (quality > 0 && quality <= 100) {
3453 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, quality);
3454 } else {
3455 LOGE("Invalid jpeg thumbnail quality=%d", quality);
3456 rc = BAD_VALUE;
3457 }
3458 return rc;
3459}
3460
3461status_t QualcommCameraHardware::setEffect(const CameraParameters& params)
3462{
3463 const char *str = params.get(CameraParameters::KEY_EFFECT);
3464 if (str != NULL) {
3465 int32_t value = attr_lookup(effects, sizeof(effects) / sizeof(str_map), str);
3466 if (value != NOT_FOUND) {
Mohan Kandra93f1bfb2009-12-15 16:55:33 -08003467 if(!strcmp(sensorType->name, "2mp") && (value != CAMERA_EFFECT_OFF)
3468 &&(value != CAMERA_EFFECT_MONO) && (value != CAMERA_EFFECT_NEGATIVE)
3469 &&(value != CAMERA_EFFECT_SOLARIZE) && (value != CAMERA_EFFECT_SEPIA)) {
3470 LOGE("Special effect parameter is not supported for this sensor");
3471 return NO_ERROR;
3472 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003473 mParameters.set(CameraParameters::KEY_EFFECT, str);
3474 bool ret = native_set_parm(CAMERA_SET_PARM_EFFECT, sizeof(value),
3475 (void *)&value);
3476 return ret ? NO_ERROR : UNKNOWN_ERROR;
3477 }
3478 }
3479 LOGE("Invalid effect value: %s", (str == NULL) ? "NULL" : str);
3480 return BAD_VALUE;
3481}
3482
Apurva Rajguru55562b02009-12-03 12:25:35 -08003483status_t QualcommCameraHardware::setAutoExposure(const CameraParameters& params)
3484{
Mohan Kandra93f1bfb2009-12-15 16:55:33 -08003485 if(!strcmp(sensorType->name, "2mp")) {
3486 LOGE("Auto Exposure not supported for this sensor");
3487 return NO_ERROR;
3488 }
Apurva Rajguru55562b02009-12-03 12:25:35 -08003489 const char *str = params.get(CameraParameters::KEY_AUTO_EXPOSURE);
3490 if (str != NULL) {
3491 int32_t value = attr_lookup(autoexposure, sizeof(autoexposure) / sizeof(str_map), str);
3492 if (value != NOT_FOUND) {
3493 mParameters.set(CameraParameters::KEY_AUTO_EXPOSURE, str);
3494 bool ret = native_set_parm(CAMERA_SET_PARM_EXPOSURE, sizeof(value),
3495 (void *)&value);
3496 return ret ? NO_ERROR : UNKNOWN_ERROR;
3497 }
3498 }
3499 LOGE("Invalid auto exposure value: %s", (str == NULL) ? "NULL" : str);
3500 return BAD_VALUE;
3501}
3502
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003503status_t QualcommCameraHardware::setSharpness(const CameraParameters& params)
3504{
3505 if(!strcmp(sensorType->name, "2mp")) {
3506 LOGE("Sharpness not supported for this sensor");
3507 return NO_ERROR;
3508 }
3509 int sharpness = params.getInt(CameraParameters::KEY_SHARPNESS);
3510 if((sharpness < CAMERA_MIN_SHARPNESS
3511 || sharpness > CAMERA_MAX_SHARPNESS))
3512 return UNKNOWN_ERROR;
Srinivasan Kannan551fd262010-01-14 17:48:30 -08003513
3514 LOGV("setting sharpness %d", sharpness);
3515 mParameters.set(CameraParameters::KEY_SHARPNESS, sharpness);
3516 bool ret = native_set_parm(CAMERA_SET_PARM_SHARPNESS, sizeof(sharpness),
3517 (void *)&sharpness);
3518 return ret ? NO_ERROR : UNKNOWN_ERROR;
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003519}
3520
3521status_t QualcommCameraHardware::setContrast(const CameraParameters& params)
3522{
3523 if(!strcmp(sensorType->name, "2mp")) {
3524 LOGE("Contrast not supported for this sensor");
3525 return NO_ERROR;
3526 }
3527 int contrast = params.getInt(CameraParameters::KEY_CONTRAST);
3528 if((contrast < CAMERA_MIN_CONTRAST)
3529 || (contrast > CAMERA_MAX_CONTRAST))
3530 return UNKNOWN_ERROR;
Srinivasan Kannan551fd262010-01-14 17:48:30 -08003531
3532 LOGV("setting contrast %d", contrast);
3533 mParameters.set(CameraParameters::KEY_CONTRAST, contrast);
3534 bool ret = native_set_parm(CAMERA_SET_PARM_CONTRAST, sizeof(contrast),
3535 (void *)&contrast);
3536 return ret ? NO_ERROR : UNKNOWN_ERROR;
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003537}
3538
3539status_t QualcommCameraHardware::setSaturation(const CameraParameters& params)
3540{
3541 if(!strcmp(sensorType->name, "2mp")) {
3542 LOGE("Saturation not supported for this sensor");
3543 return NO_ERROR;
3544 }
3545 int saturation = params.getInt(CameraParameters::KEY_SATURATION);
3546 if((saturation < CAMERA_MIN_SATURATION)
3547 || (saturation > CAMERA_MAX_SATURATION))
3548 return UNKNOWN_ERROR;
Srinivasan Kannan551fd262010-01-14 17:48:30 -08003549
3550 LOGV("setting saturation %d", saturation);
3551 mParameters.set(CameraParameters::KEY_SATURATION, saturation);
3552 bool ret = native_set_parm(CAMERA_SET_PARM_SATURATION, sizeof(saturation),
3553 (void *)&saturation);
3554 return ret ? NO_ERROR : UNKNOWN_ERROR;
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003555}
3556
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303557status_t QualcommCameraHardware::setBrightness(const CameraParameters& params) {
3558 int brightness = params.getInt("luma-adaptation");
3559 if (mBrightness != brightness) {
3560 LOGV(" new brightness value : %d ", brightness);
3561 mBrightness = brightness;
3562
3563 bool ret = native_set_parm(CAMERA_SET_PARM_BRIGHTNESS, sizeof(mBrightness),
3564 (void *)&mBrightness);
3565 return ret ? NO_ERROR : UNKNOWN_ERROR;
3566 } else {
3567 return NO_ERROR;
3568 }
3569}
3570
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003571status_t QualcommCameraHardware::setWhiteBalance(const CameraParameters& params)
3572{
3573 const char *str = params.get(CameraParameters::KEY_WHITE_BALANCE);
3574 if (str != NULL) {
3575 int32_t value = attr_lookup(whitebalance, sizeof(whitebalance) / sizeof(str_map), str);
3576 if (value != NOT_FOUND) {
3577 mParameters.set(CameraParameters::KEY_WHITE_BALANCE, str);
3578 bool ret = native_set_parm(CAMERA_SET_PARM_WB, sizeof(value),
3579 (void *)&value);
3580 return ret ? NO_ERROR : UNKNOWN_ERROR;
3581 }
3582 }
3583 LOGE("Invalid whitebalance value: %s", (str == NULL) ? "NULL" : str);
3584 return BAD_VALUE;
3585}
3586
3587status_t QualcommCameraHardware::setFlash(const CameraParameters& params)
3588{
3589 if (!mSensorInfo.flash_enabled) {
3590 LOGV("%s: flash not supported", __FUNCTION__);
3591 return NO_ERROR;
3592 }
3593
3594 const char *str = params.get(CameraParameters::KEY_FLASH_MODE);
3595 if (str != NULL) {
3596 int32_t value = attr_lookup(flash, sizeof(flash) / sizeof(str_map), str);
3597 if (value != NOT_FOUND) {
3598 mParameters.set(CameraParameters::KEY_FLASH_MODE, str);
3599 bool ret = native_set_parm(CAMERA_SET_PARM_LED_MODE,
3600 sizeof(value), (void *)&value);
3601 return ret ? NO_ERROR : UNKNOWN_ERROR;
3602 }
3603 }
3604 LOGE("Invalid flash mode value: %s", (str == NULL) ? "NULL" : str);
3605 return BAD_VALUE;
3606}
3607
3608status_t QualcommCameraHardware::setAntibanding(const CameraParameters& params)
3609{
Srinivasan Kannan2229d272010-01-05 14:58:28 -08003610 if(!strcmp(sensorType->name, "2mp")) {
3611 LOGE("Parameter AntiBanding is not supported for this sensor");
3612 return NO_ERROR;
3613 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003614 const char *str = params.get(CameraParameters::KEY_ANTIBANDING);
3615 if (str != NULL) {
3616 int value = (camera_antibanding_type)attr_lookup(
3617 antibanding, sizeof(antibanding) / sizeof(str_map), str);
3618 if (value != NOT_FOUND) {
3619 camera_antibanding_type temp = (camera_antibanding_type) value;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003620 mParameters.set(CameraParameters::KEY_ANTIBANDING, str);
Srinivasan Kannan2229d272010-01-05 14:58:28 -08003621 bool ret;
3622 if (temp == CAMERA_ANTIBANDING_AUTO) {
3623 ret = native_set_parm(CAMERA_ENABLE_AFD,
3624 0, NULL);
3625 } else {
3626 ret = native_set_parm(CAMERA_SET_PARM_ANTIBANDING,
3627 sizeof(camera_antibanding_type), (void *)&temp);
3628 }
3629 return ret ? NO_ERROR : UNKNOWN_ERROR;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003630 }
3631 }
3632 LOGE("Invalid antibanding value: %s", (str == NULL) ? "NULL" : str);
3633 return BAD_VALUE;
3634}
3635
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303636status_t QualcommCameraHardware::setLensshadeValue(const CameraParameters& params)
3637{
Mohan Kandra93f1bfb2009-12-15 16:55:33 -08003638 if(!strcmp(sensorType->name, "2mp")) {
3639 LOGE("Parameter Rolloff is not supported for this sensor");
3640 return NO_ERROR;
3641 }
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303642 const char *str = params.get(CameraParameters::KEY_LENSSHADE);
3643 if (str != NULL) {
3644 int value = attr_lookup(lensshade,
3645 sizeof(lensshade) / sizeof(str_map), str);
3646 if (value != NOT_FOUND) {
3647 int8_t temp = (int8_t)value;
3648 mParameters.set(CameraParameters::KEY_LENSSHADE, str);
3649 native_set_parm(CAMERA_SET_PARM_ROLLOFF, sizeof(int8_t), (void *)&temp);
3650 return NO_ERROR;
3651 }
3652 }
3653 LOGE("Invalid lensShade value: %s", (str == NULL) ? "NULL" : str);
3654 return BAD_VALUE;
3655}
3656
3657status_t QualcommCameraHardware::setISOValue(const CameraParameters& params) {
3658 const char *str = params.get(CameraParameters::KEY_ISO_MODE);
3659 if (str != NULL) {
3660 int value = (camera_iso_mode_type)attr_lookup(
3661 iso, sizeof(iso) / sizeof(str_map), str);
3662 if (value != NOT_FOUND) {
3663 camera_iso_mode_type temp = (camera_iso_mode_type) value;
3664 mParameters.set(CameraParameters::KEY_ISO_MODE, str);
3665 native_set_parm(CAMERA_SET_PARM_ISO, sizeof(camera_iso_mode_type), (void *)&temp);
3666 return NO_ERROR;
3667 }
3668 }
3669 LOGE("Invalid Iso value: %s", (str == NULL) ? "NULL" : str);
3670 return BAD_VALUE;
3671}
3672
3673
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003674status_t QualcommCameraHardware::setGpsLocation(const CameraParameters& params)
3675{
3676 const char *latitude = params.get(CameraParameters::KEY_GPS_LATITUDE);
3677 if (latitude) {
3678 mParameters.set(CameraParameters::KEY_GPS_LATITUDE, latitude);
3679 }
3680
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08003681 const char *latitudeRef = params.get(CameraParameters::KEY_GPS_LATITUDE_REF);
3682 if (latitudeRef) {
3683 mParameters.set(CameraParameters::KEY_GPS_LATITUDE_REF, latitudeRef);
3684 }
3685
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003686 const char *longitude = params.get(CameraParameters::KEY_GPS_LONGITUDE);
3687 if (longitude) {
3688 mParameters.set(CameraParameters::KEY_GPS_LONGITUDE, longitude);
3689 }
3690
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08003691 const char *longitudeRef = params.get(CameraParameters::KEY_GPS_LONGITUDE_REF);
3692 if (longitudeRef) {
3693 mParameters.set(CameraParameters::KEY_GPS_LONGITUDE_REF, longitudeRef);
3694 }
3695
3696 const char *altitudeRef = params.get(CameraParameters::KEY_GPS_ALTITUDE_REF);
3697 if (altitudeRef) {
3698 mParameters.set(CameraParameters::KEY_GPS_ALTITUDE_REF, altitudeRef);
3699 }
3700
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003701 const char *altitude = params.get(CameraParameters::KEY_GPS_ALTITUDE);
3702 if (altitude) {
3703 mParameters.set(CameraParameters::KEY_GPS_ALTITUDE, altitude);
3704 }
3705
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08003706 const char *status = params.get(CameraParameters::KEY_GPS_STATUS);
3707 if (status) {
3708 mParameters.set(CameraParameters::KEY_GPS_STATUS, status);
3709 }
3710
3711 const char *dateTime = params.get(CameraParameters::KEY_EXIF_DATETIME);
3712 if (dateTime) {
3713 mParameters.set(CameraParameters::KEY_EXIF_DATETIME, dateTime);
3714 }
3715
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003716 const char *timestamp = params.get(CameraParameters::KEY_GPS_TIMESTAMP);
3717 if (timestamp) {
3718 mParameters.set(CameraParameters::KEY_GPS_TIMESTAMP, timestamp);
3719 }
3720 return NO_ERROR;
3721}
3722
3723status_t QualcommCameraHardware::setRotation(const CameraParameters& params)
3724{
3725 status_t rc = NO_ERROR;
3726 int rotation = params.getInt(CameraParameters::KEY_ROTATION);
3727 if (rotation != NOT_FOUND) {
3728 if (rotation == 0 || rotation == 90 || rotation == 180
3729 || rotation == 270) {
3730 mParameters.set(CameraParameters::KEY_ROTATION, rotation);
3731 } else {
3732 LOGE("Invalid rotation value: %d", rotation);
3733 rc = BAD_VALUE;
3734 }
3735 }
3736 return rc;
3737}
3738
3739status_t QualcommCameraHardware::setZoom(const CameraParameters& params)
3740{
3741 status_t rc = NO_ERROR;
3742 // No matter how many different zoom values the driver can provide, HAL
3743 // provides applictations the same number of zoom levels. The maximum driver
3744 // zoom value depends on sensor output (VFE input) and preview size (VFE
3745 // output) because VFE can only crop and cannot upscale. If the preview size
3746 // is bigger, the maximum zoom ratio is smaller. However, we want the
3747 // zoom ratio of each zoom level is always the same whatever the preview
3748 // size is. Ex: zoom level 1 is always 1.2x, zoom level 2 is 1.44x, etc. So,
3749 // we need to have a fixed maximum zoom value and do read it from the
3750 // driver.
Mohan Kandra284966d2010-01-05 13:39:15 -08003751 static const int ZOOM_STEP = 1;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003752 int32_t zoom_level = params.getInt("zoom");
3753
Mohan Kandra284966d2010-01-05 13:39:15 -08003754 LOGV("Set zoom=%d", zoom_level);
3755 if(zoom_level >= 0 && zoom_level <= mMaxZoom) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003756 mParameters.set("zoom", zoom_level);
3757 int32_t zoom_value = ZOOM_STEP * zoom_level;
3758 bool ret = native_set_parm(CAMERA_SET_PARM_ZOOM,
3759 sizeof(zoom_value), (void *)&zoom_value);
3760 rc = ret ? NO_ERROR : UNKNOWN_ERROR;
3761 } else {
3762 rc = BAD_VALUE;
3763 }
3764
3765 return rc;
3766}
3767
3768status_t QualcommCameraHardware::setFocusMode(const CameraParameters& params)
3769{
3770 const char *str = params.get(CameraParameters::KEY_FOCUS_MODE);
3771 if (str != NULL) {
3772 int32_t value = attr_lookup(focus_modes,
3773 sizeof(focus_modes) / sizeof(str_map), str);
3774 if (value != NOT_FOUND) {
3775 mParameters.set(CameraParameters::KEY_FOCUS_MODE, str);
3776 // Focus step is reset to infinity when preview is started. We do
3777 // not need to do anything now.
3778 return NO_ERROR;
3779 }
3780 }
3781 LOGE("Invalid focus mode value: %s", (str == NULL) ? "NULL" : str);
3782 return BAD_VALUE;
3783}
3784
3785status_t QualcommCameraHardware::setOrientation(const CameraParameters& params)
3786{
3787 const char *str = params.get("orientation");
3788
3789 if (str != NULL) {
3790 if (strcmp(str, "portrait") == 0 || strcmp(str, "landscape") == 0) {
3791 // Camera service needs this to decide if the preview frames and raw
3792 // pictures should be rotated.
3793 mParameters.set("orientation", str);
3794 } else {
3795 LOGE("Invalid orientation value: %s", str);
3796 return BAD_VALUE;
3797 }
3798 }
3799 return NO_ERROR;
3800}
3801
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08003802status_t QualcommCameraHardware::setPictureFormat(const CameraParameters& params)
3803{
3804 const char * str = params.get(CameraParameters::KEY_PICTURE_FORMAT);
3805
3806 if(str != NULL){
3807 int32_t value = attr_lookup(picture_formats,
3808 sizeof(picture_formats) / sizeof(str_map), str);
3809 if(value != NOT_FOUND){
3810 mParameters.set(CameraParameters::KEY_PICTURE_FORMAT, str);
3811 } else {
3812 LOGE("Invalid Picture Format value: %s", str);
3813 return BAD_VALUE;
3814 }
3815 }
3816 return NO_ERROR;
3817}
3818
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003819QualcommCameraHardware::MemPool::MemPool(int buffer_size, int num_buffers,
3820 int frame_size,
3821 const char *name) :
3822 mBufferSize(buffer_size),
3823 mNumBuffers(num_buffers),
3824 mFrameSize(frame_size),
3825 mBuffers(NULL), mName(name)
3826{
3827 int page_size_minus_1 = getpagesize() - 1;
3828 mAlignedBufferSize = (buffer_size + page_size_minus_1) & (~page_size_minus_1);
3829}
3830
3831void QualcommCameraHardware::MemPool::completeInitialization()
3832{
3833 // If we do not know how big the frame will be, we wait to allocate
3834 // the buffers describing the individual frames until we do know their
3835 // size.
3836
3837 if (mFrameSize > 0) {
3838 mBuffers = new sp<MemoryBase>[mNumBuffers];
3839 for (int i = 0; i < mNumBuffers; i++) {
3840 mBuffers[i] = new
3841 MemoryBase(mHeap,
3842 i * mAlignedBufferSize,
3843 mFrameSize);
3844 }
3845 }
3846}
3847
3848QualcommCameraHardware::AshmemPool::AshmemPool(int buffer_size, int num_buffers,
3849 int frame_size,
3850 const char *name) :
3851 QualcommCameraHardware::MemPool(buffer_size,
3852 num_buffers,
3853 frame_size,
3854 name)
3855{
3856 LOGV("constructing MemPool %s backed by ashmem: "
3857 "%d frames @ %d uint8_ts, "
3858 "buffer size %d",
3859 mName,
3860 num_buffers, frame_size, buffer_size);
3861
3862 int page_mask = getpagesize() - 1;
3863 int ashmem_size = buffer_size * num_buffers;
3864 ashmem_size += page_mask;
3865 ashmem_size &= ~page_mask;
3866
3867 mHeap = new MemoryHeapBase(ashmem_size);
3868
3869 completeInitialization();
3870}
3871
3872static bool register_buf(int camfd,
3873 int size,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08003874 int frame_size,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003875 int pmempreviewfd,
3876 uint32_t offset,
3877 uint8_t *buf,
3878 int pmem_type,
3879 bool vfe_can_write,
3880 bool register_buffer = true);
3881
3882QualcommCameraHardware::PmemPool::PmemPool(const char *pmem_pool,
3883 int flags,
3884 int camera_control_fd,
3885 int pmem_type,
3886 int buffer_size, int num_buffers,
3887 int frame_size,
3888 const char *name) :
3889 QualcommCameraHardware::MemPool(buffer_size,
3890 num_buffers,
3891 frame_size,
3892 name),
3893 mPmemType(pmem_type),
3894 mCameraControlFd(dup(camera_control_fd))
3895{
3896 LOGV("constructing MemPool %s backed by pmem pool %s: "
3897 "%d frames @ %d bytes, buffer size %d",
3898 mName,
3899 pmem_pool, num_buffers, frame_size,
3900 buffer_size);
3901
3902 LOGV("%s: duplicating control fd %d --> %d",
3903 __FUNCTION__,
3904 camera_control_fd, mCameraControlFd);
3905
3906 // Make a new mmap'ed heap that can be shared across processes.
3907 // mAlignedBufferSize is already in 4k aligned. (do we need total size necessary to be in power of 2??)
3908 mAlignedSize = mAlignedBufferSize * num_buffers;
3909
3910 sp<MemoryHeapBase> masterHeap =
3911 new MemoryHeapBase(pmem_pool, mAlignedSize, flags);
3912
3913 if (masterHeap->getHeapID() < 0) {
3914 LOGE("failed to construct master heap for pmem pool %s", pmem_pool);
3915 masterHeap.clear();
3916 return;
3917 }
3918
3919 sp<MemoryHeapPmem> pmemHeap = new MemoryHeapPmem(masterHeap, flags);
3920 if (pmemHeap->getHeapID() >= 0) {
3921 pmemHeap->slap();
3922 masterHeap.clear();
3923 mHeap = pmemHeap;
3924 pmemHeap.clear();
3925
3926 mFd = mHeap->getHeapID();
3927 if (::ioctl(mFd, PMEM_GET_SIZE, &mSize)) {
3928 LOGE("pmem pool %s ioctl(PMEM_GET_SIZE) error %s (%d)",
3929 pmem_pool,
3930 ::strerror(errno), errno);
3931 mHeap.clear();
3932 return;
3933 }
3934
3935 LOGV("pmem pool %s ioctl(fd = %d, PMEM_GET_SIZE) is %ld",
3936 pmem_pool,
3937 mFd,
3938 mSize.len);
Mohan Kandra284966d2010-01-05 13:39:15 -08003939 LOGD("mBufferSize=%d, mAlignedBufferSize=%d\n", mBufferSize, mAlignedBufferSize);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003940 // Unregister preview buffers with the camera drivers. Allow the VFE to write
3941 // to all preview buffers except for the last one.
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003942 // Only Register the preview, snapshot and thumbnail buffers with the kernel.
Mohan Kandrad9efed92010-01-15 19:08:39 -08003943 if( (strcmp("postview", mName) != 0) ){
3944 int num_buf = num_buffers;
3945 if(!strcmp("preview", mName)) num_buf = kPreviewBufferCount;
3946 LOGE("num_buffers = %d", num_buf);
3947 for (int cnt = 0; cnt < num_buf; ++cnt) {
Sravankb4f5f1c2010-01-21 11:06:17 +05303948 int active = 1;
3949 if(pmem_type == MSM_PMEM_VIDEO){
3950 active = (cnt<ACTIVE_VIDEO_BUFFERS);
3951 LOGV(" pmempool creating video buffers : active %d ", active);
3952 }
3953 else if (pmem_type == MSM_PMEM_PREVIEW){
3954 active = (cnt < (num_buf-1));
3955 }
Mohan Kandra284966d2010-01-05 13:39:15 -08003956 register_buf(mCameraControlFd,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003957 mBufferSize,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08003958 mFrameSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003959 mHeap->getHeapID(),
3960 mAlignedBufferSize * cnt,
3961 (uint8_t *)mHeap->base() + mAlignedBufferSize * cnt,
3962 pmem_type,
Sravankb4f5f1c2010-01-21 11:06:17 +05303963 active);
Mohan Kandra284966d2010-01-05 13:39:15 -08003964 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003965 }
3966
3967 completeInitialization();
3968 }
3969 else LOGE("pmem pool %s error: could not create master heap!",
3970 pmem_pool);
3971}
3972
3973QualcommCameraHardware::PmemPool::~PmemPool()
3974{
3975 LOGV("%s: %s E", __FUNCTION__, mName);
3976 if (mHeap != NULL) {
3977 // Unregister preview buffers with the camera drivers.
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003978 // Only Unregister the preview, snapshot and thumbnail
3979 // buffers with the kernel.
Mohan Kandrad9efed92010-01-15 19:08:39 -08003980 if( (strcmp("postview", mName) != 0) ){
3981 int num_buffers = mNumBuffers;
3982 if(!strcmp("preview", mName)) num_buffers = kPreviewBufferCount;
3983 for (int cnt = 0; cnt < num_buffers; ++cnt) {
Mohan Kandra284966d2010-01-05 13:39:15 -08003984 register_buf(mCameraControlFd,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003985 mBufferSize,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08003986 mFrameSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003987 mHeap->getHeapID(),
3988 mAlignedBufferSize * cnt,
3989 (uint8_t *)mHeap->base() + mAlignedBufferSize * cnt,
3990 mPmemType,
3991 false,
3992 false /* unregister */);
Mohan Kandra284966d2010-01-05 13:39:15 -08003993 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003994 }
3995 }
3996 LOGV("destroying PmemPool %s: closing control fd %d",
3997 mName,
3998 mCameraControlFd);
3999 close(mCameraControlFd);
4000 LOGV("%s: %s X", __FUNCTION__, mName);
4001}
4002
4003QualcommCameraHardware::MemPool::~MemPool()
4004{
4005 LOGV("destroying MemPool %s", mName);
4006 if (mFrameSize > 0)
4007 delete [] mBuffers;
4008 mHeap.clear();
4009 LOGV("destroying MemPool %s completed", mName);
4010}
4011
4012static bool register_buf(int camfd,
4013 int size,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08004014 int frame_size,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004015 int pmempreviewfd,
4016 uint32_t offset,
4017 uint8_t *buf,
4018 int pmem_type,
4019 bool vfe_can_write,
4020 bool register_buffer)
4021{
4022 struct msm_pmem_info pmemBuf;
4023
4024 pmemBuf.type = pmem_type;
4025 pmemBuf.fd = pmempreviewfd;
4026 pmemBuf.offset = offset;
4027 pmemBuf.len = size;
4028 pmemBuf.vaddr = buf;
4029 pmemBuf.y_off = 0;
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08004030 pmemBuf.cbcr_off = PAD_TO_WORD(frame_size * 2 / 3);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004031 pmemBuf.active = vfe_can_write;
4032
4033 LOGV("register_buf: camfd = %d, reg = %d buffer = %p",
4034 camfd, !register_buffer, buf);
4035 if (ioctl(camfd,
4036 register_buffer ?
4037 MSM_CAM_IOCTL_REGISTER_PMEM :
4038 MSM_CAM_IOCTL_UNREGISTER_PMEM,
4039 &pmemBuf) < 0) {
4040 LOGE("register_buf: MSM_CAM_IOCTL_(UN)REGISTER_PMEM fd %d error %s",
4041 camfd,
4042 strerror(errno));
4043 return false;
4044 }
4045 return true;
4046}
4047
4048status_t QualcommCameraHardware::MemPool::dump(int fd, const Vector<String16>& args) const
4049{
4050 const size_t SIZE = 256;
4051 char buffer[SIZE];
4052 String8 result;
4053 snprintf(buffer, 255, "QualcommCameraHardware::AshmemPool::dump\n");
4054 result.append(buffer);
4055 if (mName) {
4056 snprintf(buffer, 255, "mem pool name (%s)\n", mName);
4057 result.append(buffer);
4058 }
4059 if (mHeap != 0) {
4060 snprintf(buffer, 255, "heap base(%p), size(%d), flags(%d), device(%s)\n",
4061 mHeap->getBase(), mHeap->getSize(),
4062 mHeap->getFlags(), mHeap->getDevice());
4063 result.append(buffer);
4064 }
4065 snprintf(buffer, 255,
4066 "buffer size (%d), number of buffers (%d), frame size(%d)",
4067 mBufferSize, mNumBuffers, mFrameSize);
4068 result.append(buffer);
4069 write(fd, result.string(), result.size());
4070 return NO_ERROR;
4071}
4072
4073static void receive_camframe_callback(struct msm_frame *frame)
4074{
4075 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4076 if (obj != 0) {
4077 obj->receivePreviewFrame(frame);
4078 }
4079}
4080
4081static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size)
4082{
4083 LOGV("receive_jpeg_fragment_callback E");
4084 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4085 if (obj != 0) {
4086 obj->receiveJpegPictureFragment(buff_ptr, buff_size);
4087 }
4088 LOGV("receive_jpeg_fragment_callback X");
4089}
4090
4091static void receive_jpeg_callback(jpeg_event_t status)
4092{
4093 LOGV("receive_jpeg_callback E (completion status %d)", status);
4094 if (status == JPEG_EVENT_DONE) {
4095 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4096 if (obj != 0) {
4097 obj->receiveJpegPicture();
4098 }
4099 }
4100 LOGV("receive_jpeg_callback X");
4101}
Sravankb4f5f1c2010-01-21 11:06:17 +05304102// 720p : video frame calbback from camframe
4103static void receive_camframe_video_callback(struct msm_frame *frame)
4104{
4105 LOGV("receive_camframe_video_callback E");
4106 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4107 if (obj != 0) {
4108 obj->receiveRecordingFrame(frame);
4109 }
4110 LOGV("receive_camframe_video_callback X");
4111}
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004112
4113void QualcommCameraHardware::setCallbacks(notify_callback notify_cb,
4114 data_callback data_cb,
4115 data_callback_timestamp data_cb_timestamp,
4116 void* user)
4117{
4118 Mutex::Autolock lock(mLock);
4119 mNotifyCallback = notify_cb;
4120 mDataCallback = data_cb;
4121 mDataCallbackTimestamp = data_cb_timestamp;
4122 mCallbackCookie = user;
4123}
4124
4125void QualcommCameraHardware::enableMsgType(int32_t msgType)
4126{
4127 Mutex::Autolock lock(mLock);
4128 mMsgEnabled |= msgType;
4129}
4130
4131void QualcommCameraHardware::disableMsgType(int32_t msgType)
4132{
4133 Mutex::Autolock lock(mLock);
4134 mMsgEnabled &= ~msgType;
4135}
4136
4137bool QualcommCameraHardware::msgTypeEnabled(int32_t msgType)
4138{
4139 return (mMsgEnabled & msgType);
4140}
4141
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08004142bool QualcommCameraHardware::useOverlay(void)
4143{
Mohan Kandra284966d2010-01-05 13:39:15 -08004144 if(!strcmp(mDeviceName,"msm7630_surf")) {
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08004145 /* Only 7x30 supports Overlay */
4146 mUseOverlay = TRUE;
4147 } else
4148 mUseOverlay = FALSE;
4149
4150 LOGV(" Using Overlay : %s ", mUseOverlay ? "YES" : "NO" );
4151 return mUseOverlay;
4152}
4153
4154status_t QualcommCameraHardware::setOverlay(const sp<Overlay> &Overlay)
4155{
4156 if( Overlay != NULL) {
4157 LOGV(" Valid overlay object ");
4158 mOverlayLock.lock();
4159 mOverlay = Overlay;
4160 mOverlayLock.unlock();
4161 } else {
4162 LOGE(" Overlay object NULL. returning ");
Mohan Kandrad9efed92010-01-15 19:08:39 -08004163 mOverlay = NULL;
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08004164 return UNKNOWN_ERROR;
4165 }
4166 return NO_ERROR;
4167}
Kiran Kumar H N215cac42009-12-08 01:53:46 -08004168
4169void QualcommCameraHardware::receive_camframetimeout(void) {
4170 LOGV("receive_camframetimeout: E");
4171 Mutex::Autolock l(&mCamframeTimeoutLock);
4172 camframe_timeout_flag = TRUE;
4173 LOGV("receive_camframetimeout: X");
4174}
4175
4176static void receive_camframetimeout_callback(void) {
4177 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4178 if (obj != 0) {
4179 obj->receive_camframetimeout();
4180 }
4181}
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08004182
4183void QualcommCameraHardware::storePreviewFrameForPostview(void) {
4184 LOGV(" storePreviewFrameForPostview : E ");
4185
4186 /* Since there is restriction on the maximum overlay dimensions
4187 * that can be created, we use the last preview frame as postview
4188 * for 7x30. */
4189 LOGV(" Copying the preview buffer to postview buffer %d ",
4190 mPreviewFrameSize);
4191 if( mPostViewHeap != NULL && mLastQueuedFrame != NULL) {
4192 memcpy(mPostViewHeap->mHeap->base(),
4193 (uint8_t *)mLastQueuedFrame, mPreviewFrameSize );
4194 } else
4195 LOGE(" Failed to store Preview frame. No Postview ");
4196
4197 LOGV(" storePreviewFrameForPostview : X ");
4198}
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004199}; // namespace android