blob: 35a231eaf8306e12667c36a6ef36b8c03014b979 [file] [log] [blame]
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001/*
2** Copyright 2008, Google Inc.
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303** Copyright (c) 2009, Code Aurora Forum. All rights reserved.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18//#define LOG_NDEBUG 0
Mohan Kandrabad0eaa2010-02-04 15:11:54 -080019#define LOG_NIDEBUG 0
Priya Komarlingamb85535d2009-11-30 13:06:01 -080020#define LOG_TAG "QualcommCameraHardware"
21#include <utils/Log.h>
22
23#include "QualcommCameraHardware.h"
24
25#include <utils/Errors.h>
26#include <utils/threads.h>
27#include <binder/MemoryHeapPmem.h>
28#include <utils/String16.h>
29#include <sys/types.h>
30#include <sys/stat.h>
31#include <unistd.h>
Sravankb4f5f1c2010-01-21 11:06:17 +053032#include <fcntl.h>
Apurva Rajguru8d1773b2009-12-02 14:21:23 -080033#include <cutils/properties.h>
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -080034#include <math.h>
Priya Komarlingamb85535d2009-11-30 13:06:01 -080035#if HAVE_ANDROID_OS
36#include <linux/android_pmem.h>
37#endif
38#include <linux/ioctl.h>
39#include <ui/CameraParameters.h>
40
Mohan Kandra284966d2010-01-05 13:39:15 -080041#include "linux/msm_mdp.h"
42#include <linux/fb.h>
43
Priya Komarlingamb85535d2009-11-30 13:06:01 -080044#define LIKELY(exp) __builtin_expect(!!(exp), 1)
45#define UNLIKELY(exp) __builtin_expect(!!(exp), 0)
46
47extern "C" {
48#include <fcntl.h>
49#include <time.h>
50#include <pthread.h>
51#include <stdio.h>
52#include <string.h>
53#include <unistd.h>
54#include <termios.h>
55#include <assert.h>
56#include <stdlib.h>
57#include <ctype.h>
58#include <signal.h>
59#include <errno.h>
60#include <sys/mman.h>
61#include <sys/system_properties.h>
62#include <sys/time.h>
63#include <stdlib.h>
64
65#include <media/msm_camera.h>
66
67#include <camera.h>
68#include <camframe.h>
69#include <mm-still/jpeg/jpege.h>
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -080070#include <jpeg_encoder.h>
Priya Komarlingamb85535d2009-11-30 13:06:01 -080071
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -080072#define DEFAULT_PICTURE_WIDTH 1024
73#define DEFAULT_PICTURE_HEIGHT 768
Priya Komarlingamb85535d2009-11-30 13:06:01 -080074#define THUMBNAIL_BUFFER_SIZE (THUMBNAIL_WIDTH * THUMBNAIL_HEIGHT * 3/2)
75#define MAX_ZOOM_LEVEL 5
76#define NOT_FOUND -1
77
Sravankb4f5f1c2010-01-21 11:06:17 +053078// Number of video buffers held by kernal (initially 1,2 &3)
79#define ACTIVE_VIDEO_BUFFERS 3
80
Priya Komarlingamb85535d2009-11-30 13:06:01 -080081#if DLOPEN_LIBMMCAMERA
82#include <dlfcn.h>
83
84void* (*LINK_cam_conf)(void *data);
85void* (*LINK_cam_frame)(void *data);
86bool (*LINK_jpeg_encoder_init)();
87void (*LINK_jpeg_encoder_join)();
88bool (*LINK_jpeg_encoder_encode)(const cam_ctrl_dimension_t *dimen,
89 const uint8_t *thumbnailbuf, int thumbnailfd,
90 const uint8_t *snapshotbuf, int snapshotfd,
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -080091 common_crop_t *scaling_parms, exif_tags_info_t *exif_data,
92 int exif_table_numEntries);
Kiran Kumar H N7ac84e32010-02-01 10:58:47 -080093void (*LINK_camframe_terminate)(void);
Sravankb4f5f1c2010-01-21 11:06:17 +053094//for 720p
95// Function to add a video buffer to free Q
96void (*LINK_camframe_free_video)(struct msm_frame *frame);
97// Function pointer , called by camframe when a video frame is available.
98void (**LINK_camframe_video_callback)(struct msm_frame * frame);
99// To flush free Q in cam frame.
100void (*LINK_cam_frame_flush_free_video)(void);
101
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800102int8_t (*LINK_jpeg_encoder_setMainImageQuality)(uint32_t quality);
103int8_t (*LINK_jpeg_encoder_setThumbnailQuality)(uint32_t quality);
104int8_t (*LINK_jpeg_encoder_setRotation)(uint32_t rotation);
105int8_t (*LINK_jpeg_encoder_setLocation)(const camera_position_type *location);
106const struct camera_size_type *(*LINK_default_sensor_get_snapshot_sizes)(int *len);
107int (*LINK_launch_cam_conf_thread)(void);
108int (*LINK_release_cam_conf_thread)(void);
109int8_t (*LINK_zoom_crop_upscale)(uint32_t width, uint32_t height,
110 uint32_t cropped_width, uint32_t cropped_height, uint8_t *img_buf);
111
112// callbacks
113void (**LINK_mmcamera_camframe_callback)(struct msm_frame *frame);
114void (**LINK_mmcamera_jpegfragment_callback)(uint8_t *buff_ptr,
115 uint32_t buff_size);
116void (**LINK_mmcamera_jpeg_callback)(jpeg_event_t status);
117void (**LINK_mmcamera_shutter_callback)(common_crop_t *crop);
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800118void (**LINK_camframe_timeout_callback)(void);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800119#else
120#define LINK_cam_conf cam_conf
121#define LINK_cam_frame cam_frame
122#define LINK_jpeg_encoder_init jpeg_encoder_init
123#define LINK_jpeg_encoder_join jpeg_encoder_join
124#define LINK_jpeg_encoder_encode jpeg_encoder_encode
125#define LINK_camframe_terminate camframe_terminate
126#define LINK_jpeg_encoder_setMainImageQuality jpeg_encoder_setMainImageQuality
127#define LINK_jpeg_encoder_setThumbnailQuality jpeg_encoder_setThumbnailQuality
128#define LINK_jpeg_encoder_setRotation jpeg_encoder_setRotation
129#define LINK_jpeg_encoder_setLocation jpeg_encoder_setLocation
130#define LINK_default_sensor_get_snapshot_sizes default_sensor_get_snapshot_sizes
131#define LINK_launch_cam_conf_thread launch_cam_conf_thread
132#define LINK_release_cam_conf_thread release_cam_conf_thread
133#define LINK_zoom_crop_upscale zoom_crop_upscale
134extern void (*mmcamera_camframe_callback)(struct msm_frame *frame);
135extern void (*mmcamera_jpegfragment_callback)(uint8_t *buff_ptr,
136 uint32_t buff_size);
137extern void (*mmcamera_jpeg_callback)(jpeg_event_t status);
138extern void (*mmcamera_shutter_callback)(common_crop_t *crop);
139#endif
140
141} // extern "C"
142
143#ifndef HAVE_CAMERA_SIZE_TYPE
144struct camera_size_type {
145 int width;
146 int height;
147};
148#endif
149
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -0800150typedef struct crop_info_struct {
151 uint32_t x;
152 uint32_t y;
153 uint32_t w;
154 uint32_t h;
155} zoom_crop_info;
156
Mohan Kandra740cfce2010-01-07 12:58:24 -0800157union zoomimage
Mohan Kandra284966d2010-01-05 13:39:15 -0800158{
159 char d[sizeof(struct mdp_blit_req_list) + sizeof(struct mdp_blit_req) * 1];
160 struct mdp_blit_req_list list;
161} zoomImage;
162
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800163//Default to WVGA
Srinivasan 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
Srinivasan Kannan613301c2010-02-10 17:08:53 -0800168 { 768, 432 },
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800169 { 720, 480 },
170 { 640, 480 }, // VGA
171 { 576, 432 },
172 { 480, 320 }, // HVGA
173 { 384, 288 },
174 { 352, 288 }, // CIF
175 { 320, 240 }, // QVGA
176 { 240, 160 }, // SQVGA
177 { 176, 144 }, // QCIF
178};
179#define PREVIEW_SIZE_COUNT (sizeof(preview_sizes)/sizeof(camera_size_type))
180
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800181//static const camera_size_type* picture_sizes;
182//static int PICTURE_SIZE_COUNT;
183/* TODO
184 * Ideally this should be a populated by lower layers.
185 * But currently this is no API to do that at lower layer.
186 * Hence populating with default sizes for now. This needs
187 * to be changed once the API is supported.
188 */
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800189//sorted on column basis
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800190static const camera_size_type picture_sizes[] = {
191 { 2592, 1944 }, // 5MP
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800192 { 2048, 1536 }, // 3MP QXGA
193 { 1920, 1080 }, //HD1080
194 { 1600, 1200 }, // 2MP UXGA
195 { 1280, 768 }, //WXGA
196 { 1280, 720 }, //HD720
197 { 1024, 768}, // 1MP XGA
198 { 800, 600 }, //SVGA
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800199 { 800, 480 }, // WVGA
200 { 640, 480 }, // VGA
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800201 { 352, 288 }, //CIF
202 { 320, 240 }, // QVGA
203 { 176, 144 } // QCIF
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800204};
205static int PICTURE_SIZE_COUNT = sizeof(picture_sizes)/sizeof(camera_size_type);
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800206static const camera_size_type * picture_sizes_ptr;
207static int supportedPictureSizesCount;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800208
Srinivasan Kannan80d878f2009-12-18 15:06:02 -0800209#ifdef Q12
210#undef Q12
211#endif
212
213#define Q12 4096
214
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -0800215static const target_map targetList [] = {
216 { "msm7625", TARGET_MSM7625 },
217 { "msm7627", TARGET_MSM7627 },
218 { "qsd8250", TARGET_QSD8250 },
219 { "msm7630", TARGET_MSM7630 }
220};
221static targetType mCurrentTarget = TARGET_MAX;
222
Srinivasan Kannan80d878f2009-12-18 15:06:02 -0800223typedef struct {
224 uint32_t aspect_ratio;
225 uint32_t width;
226 uint32_t height;
227} thumbnail_size_type;
228
229static thumbnail_size_type thumbnail_sizes[] = {
230 { 7281, 512, 288 }, //1.777778
231 { 6826, 480, 288 }, //1.666667
Kiran Kumar H Nb49af212010-02-17 15:12:17 -0800232 { 6144, 432, 288 }, //1.5
Srinivasan Kannan80d878f2009-12-18 15:06:02 -0800233 { 5461, 512, 384 }, //1.333333
234 { 5006, 352, 288 }, //1.222222
235};
236#define THUMBNAIL_SIZE_COUNT (sizeof(thumbnail_sizes)/sizeof(thumbnail_size_type))
237#define DEFAULT_THUMBNAIL_SETTING 2
238#define THUMBNAIL_WIDTH_STR "512"
239#define THUMBNAIL_HEIGHT_STR "384"
240#define THUMBNAIL_SMALL_HEIGHT 144
241
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800242static int attr_lookup(const str_map arr[], int len, const char *name)
243{
244 if (name) {
245 for (int i = 0; i < len; i++) {
246 if (!strcmp(arr[i].desc, name))
247 return arr[i].val;
248 }
249 }
250 return NOT_FOUND;
251}
252
253// round to the next power of two
254static inline unsigned clp2(unsigned x)
255{
256 x = x - 1;
257 x = x | (x >> 1);
258 x = x | (x >> 2);
259 x = x | (x >> 4);
260 x = x | (x >> 8);
261 x = x | (x >>16);
262 return x + 1;
263}
264
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -0800265static int exif_table_numEntries = 0;
266#define MAX_EXIF_TABLE_ENTRIES 7
267exif_tags_info_t exif_data[MAX_EXIF_TABLE_ENTRIES];
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -0800268static zoom_crop_info zoomCropInfo;
269static void *mLastQueuedFrame = NULL;
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -0800270
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800271namespace android {
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800272
273static const int PICTURE_FORMAT_JPEG = 1;
274static const int PICTURE_FORMAT_RAW = 2;
275
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800276// from aeecamera.h
277static const str_map whitebalance[] = {
278 { CameraParameters::WHITE_BALANCE_AUTO, CAMERA_WB_AUTO },
279 { CameraParameters::WHITE_BALANCE_INCANDESCENT, CAMERA_WB_INCANDESCENT },
280 { CameraParameters::WHITE_BALANCE_FLUORESCENT, CAMERA_WB_FLUORESCENT },
281 { CameraParameters::WHITE_BALANCE_DAYLIGHT, CAMERA_WB_DAYLIGHT },
282 { CameraParameters::WHITE_BALANCE_CLOUDY_DAYLIGHT, CAMERA_WB_CLOUDY_DAYLIGHT }
283};
284
285// from camera_effect_t. This list must match aeecamera.h
286static const str_map effects[] = {
287 { CameraParameters::EFFECT_NONE, CAMERA_EFFECT_OFF },
288 { CameraParameters::EFFECT_MONO, CAMERA_EFFECT_MONO },
289 { CameraParameters::EFFECT_NEGATIVE, CAMERA_EFFECT_NEGATIVE },
290 { CameraParameters::EFFECT_SOLARIZE, CAMERA_EFFECT_SOLARIZE },
291 { CameraParameters::EFFECT_SEPIA, CAMERA_EFFECT_SEPIA },
292 { CameraParameters::EFFECT_POSTERIZE, CAMERA_EFFECT_POSTERIZE },
293 { CameraParameters::EFFECT_WHITEBOARD, CAMERA_EFFECT_WHITEBOARD },
294 { CameraParameters::EFFECT_BLACKBOARD, CAMERA_EFFECT_BLACKBOARD },
295 { CameraParameters::EFFECT_AQUA, CAMERA_EFFECT_AQUA }
296};
297
298// from qcamera/common/camera.h
Apurva Rajguru55562b02009-12-03 12:25:35 -0800299static const str_map autoexposure[] = {
300 { CameraParameters::AUTO_EXPOSURE_FRAME_AVG, CAMERA_AEC_FRAME_AVERAGE },
301 { CameraParameters::AUTO_EXPOSURE_CENTER_WEIGHTED, CAMERA_AEC_CENTER_WEIGHTED },
302 { CameraParameters::AUTO_EXPOSURE_SPOT_METERING, CAMERA_AEC_SPOT_METERING }
303};
304
305// from qcamera/common/camera.h
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800306static const str_map antibanding[] = {
307 { CameraParameters::ANTIBANDING_OFF, CAMERA_ANTIBANDING_OFF },
308 { CameraParameters::ANTIBANDING_50HZ, CAMERA_ANTIBANDING_50HZ },
309 { CameraParameters::ANTIBANDING_60HZ, CAMERA_ANTIBANDING_60HZ },
310 { CameraParameters::ANTIBANDING_AUTO, CAMERA_ANTIBANDING_AUTO }
311};
312
313/* Mapping from MCC to antibanding type */
314struct country_map {
315 uint32_t country_code;
316 camera_antibanding_type type;
317};
318
319static struct country_map country_numeric[] = {
320 { 202, CAMERA_ANTIBANDING_50HZ }, // Greece
321 { 204, CAMERA_ANTIBANDING_50HZ }, // Netherlands
322 { 206, CAMERA_ANTIBANDING_50HZ }, // Belgium
323 { 208, CAMERA_ANTIBANDING_50HZ }, // France
324 { 212, CAMERA_ANTIBANDING_50HZ }, // Monaco
325 { 213, CAMERA_ANTIBANDING_50HZ }, // Andorra
326 { 214, CAMERA_ANTIBANDING_50HZ }, // Spain
327 { 216, CAMERA_ANTIBANDING_50HZ }, // Hungary
328 { 219, CAMERA_ANTIBANDING_50HZ }, // Croatia
329 { 220, CAMERA_ANTIBANDING_50HZ }, // Serbia
330 { 222, CAMERA_ANTIBANDING_50HZ }, // Italy
331 { 226, CAMERA_ANTIBANDING_50HZ }, // Romania
332 { 228, CAMERA_ANTIBANDING_50HZ }, // Switzerland
333 { 230, CAMERA_ANTIBANDING_50HZ }, // Czech Republic
334 { 231, CAMERA_ANTIBANDING_50HZ }, // Slovakia
335 { 232, CAMERA_ANTIBANDING_50HZ }, // Austria
336 { 234, CAMERA_ANTIBANDING_50HZ }, // United Kingdom
337 { 235, CAMERA_ANTIBANDING_50HZ }, // United Kingdom
338 { 238, CAMERA_ANTIBANDING_50HZ }, // Denmark
339 { 240, CAMERA_ANTIBANDING_50HZ }, // Sweden
340 { 242, CAMERA_ANTIBANDING_50HZ }, // Norway
341 { 244, CAMERA_ANTIBANDING_50HZ }, // Finland
342 { 246, CAMERA_ANTIBANDING_50HZ }, // Lithuania
343 { 247, CAMERA_ANTIBANDING_50HZ }, // Latvia
344 { 248, CAMERA_ANTIBANDING_50HZ }, // Estonia
345 { 250, CAMERA_ANTIBANDING_50HZ }, // Russian Federation
346 { 255, CAMERA_ANTIBANDING_50HZ }, // Ukraine
347 { 257, CAMERA_ANTIBANDING_50HZ }, // Belarus
348 { 259, CAMERA_ANTIBANDING_50HZ }, // Moldova
349 { 260, CAMERA_ANTIBANDING_50HZ }, // Poland
350 { 262, CAMERA_ANTIBANDING_50HZ }, // Germany
351 { 266, CAMERA_ANTIBANDING_50HZ }, // Gibraltar
352 { 268, CAMERA_ANTIBANDING_50HZ }, // Portugal
353 { 270, CAMERA_ANTIBANDING_50HZ }, // Luxembourg
354 { 272, CAMERA_ANTIBANDING_50HZ }, // Ireland
355 { 274, CAMERA_ANTIBANDING_50HZ }, // Iceland
356 { 276, CAMERA_ANTIBANDING_50HZ }, // Albania
357 { 278, CAMERA_ANTIBANDING_50HZ }, // Malta
358 { 280, CAMERA_ANTIBANDING_50HZ }, // Cyprus
359 { 282, CAMERA_ANTIBANDING_50HZ }, // Georgia
360 { 283, CAMERA_ANTIBANDING_50HZ }, // Armenia
361 { 284, CAMERA_ANTIBANDING_50HZ }, // Bulgaria
362 { 286, CAMERA_ANTIBANDING_50HZ }, // Turkey
363 { 288, CAMERA_ANTIBANDING_50HZ }, // Faroe Islands
364 { 290, CAMERA_ANTIBANDING_50HZ }, // Greenland
365 { 293, CAMERA_ANTIBANDING_50HZ }, // Slovenia
366 { 294, CAMERA_ANTIBANDING_50HZ }, // Macedonia
367 { 295, CAMERA_ANTIBANDING_50HZ }, // Liechtenstein
368 { 297, CAMERA_ANTIBANDING_50HZ }, // Montenegro
369 { 302, CAMERA_ANTIBANDING_60HZ }, // Canada
370 { 310, CAMERA_ANTIBANDING_60HZ }, // United States of America
371 { 311, CAMERA_ANTIBANDING_60HZ }, // United States of America
372 { 312, CAMERA_ANTIBANDING_60HZ }, // United States of America
373 { 313, CAMERA_ANTIBANDING_60HZ }, // United States of America
374 { 314, CAMERA_ANTIBANDING_60HZ }, // United States of America
375 { 315, CAMERA_ANTIBANDING_60HZ }, // United States of America
376 { 316, CAMERA_ANTIBANDING_60HZ }, // United States of America
377 { 330, CAMERA_ANTIBANDING_60HZ }, // Puerto Rico
378 { 334, CAMERA_ANTIBANDING_60HZ }, // Mexico
379 { 338, CAMERA_ANTIBANDING_50HZ }, // Jamaica
380 { 340, CAMERA_ANTIBANDING_50HZ }, // Martinique
381 { 342, CAMERA_ANTIBANDING_50HZ }, // Barbados
382 { 346, CAMERA_ANTIBANDING_60HZ }, // Cayman Islands
383 { 350, CAMERA_ANTIBANDING_60HZ }, // Bermuda
384 { 352, CAMERA_ANTIBANDING_50HZ }, // Grenada
385 { 354, CAMERA_ANTIBANDING_60HZ }, // Montserrat
386 { 362, CAMERA_ANTIBANDING_50HZ }, // Netherlands Antilles
387 { 363, CAMERA_ANTIBANDING_60HZ }, // Aruba
388 { 364, CAMERA_ANTIBANDING_60HZ }, // Bahamas
389 { 365, CAMERA_ANTIBANDING_60HZ }, // Anguilla
390 { 366, CAMERA_ANTIBANDING_50HZ }, // Dominica
391 { 368, CAMERA_ANTIBANDING_60HZ }, // Cuba
392 { 370, CAMERA_ANTIBANDING_60HZ }, // Dominican Republic
393 { 372, CAMERA_ANTIBANDING_60HZ }, // Haiti
394 { 401, CAMERA_ANTIBANDING_50HZ }, // Kazakhstan
395 { 402, CAMERA_ANTIBANDING_50HZ }, // Bhutan
396 { 404, CAMERA_ANTIBANDING_50HZ }, // India
397 { 405, CAMERA_ANTIBANDING_50HZ }, // India
398 { 410, CAMERA_ANTIBANDING_50HZ }, // Pakistan
399 { 413, CAMERA_ANTIBANDING_50HZ }, // Sri Lanka
400 { 414, CAMERA_ANTIBANDING_50HZ }, // Myanmar
401 { 415, CAMERA_ANTIBANDING_50HZ }, // Lebanon
402 { 416, CAMERA_ANTIBANDING_50HZ }, // Jordan
403 { 417, CAMERA_ANTIBANDING_50HZ }, // Syria
404 { 418, CAMERA_ANTIBANDING_50HZ }, // Iraq
405 { 419, CAMERA_ANTIBANDING_50HZ }, // Kuwait
406 { 420, CAMERA_ANTIBANDING_60HZ }, // Saudi Arabia
407 { 421, CAMERA_ANTIBANDING_50HZ }, // Yemen
408 { 422, CAMERA_ANTIBANDING_50HZ }, // Oman
409 { 424, CAMERA_ANTIBANDING_50HZ }, // United Arab Emirates
410 { 425, CAMERA_ANTIBANDING_50HZ }, // Israel
411 { 426, CAMERA_ANTIBANDING_50HZ }, // Bahrain
412 { 427, CAMERA_ANTIBANDING_50HZ }, // Qatar
413 { 428, CAMERA_ANTIBANDING_50HZ }, // Mongolia
414 { 429, CAMERA_ANTIBANDING_50HZ }, // Nepal
415 { 430, CAMERA_ANTIBANDING_50HZ }, // United Arab Emirates
416 { 431, CAMERA_ANTIBANDING_50HZ }, // United Arab Emirates
417 { 432, CAMERA_ANTIBANDING_50HZ }, // Iran
418 { 434, CAMERA_ANTIBANDING_50HZ }, // Uzbekistan
419 { 436, CAMERA_ANTIBANDING_50HZ }, // Tajikistan
420 { 437, CAMERA_ANTIBANDING_50HZ }, // Kyrgyz Rep
421 { 438, CAMERA_ANTIBANDING_50HZ }, // Turkmenistan
422 { 440, CAMERA_ANTIBANDING_60HZ }, // Japan
423 { 441, CAMERA_ANTIBANDING_60HZ }, // Japan
424 { 452, CAMERA_ANTIBANDING_50HZ }, // Vietnam
425 { 454, CAMERA_ANTIBANDING_50HZ }, // Hong Kong
426 { 455, CAMERA_ANTIBANDING_50HZ }, // Macao
427 { 456, CAMERA_ANTIBANDING_50HZ }, // Cambodia
428 { 457, CAMERA_ANTIBANDING_50HZ }, // Laos
429 { 460, CAMERA_ANTIBANDING_50HZ }, // China
430 { 466, CAMERA_ANTIBANDING_60HZ }, // Taiwan
431 { 470, CAMERA_ANTIBANDING_50HZ }, // Bangladesh
432 { 472, CAMERA_ANTIBANDING_50HZ }, // Maldives
433 { 502, CAMERA_ANTIBANDING_50HZ }, // Malaysia
434 { 505, CAMERA_ANTIBANDING_50HZ }, // Australia
435 { 510, CAMERA_ANTIBANDING_50HZ }, // Indonesia
436 { 514, CAMERA_ANTIBANDING_50HZ }, // East Timor
437 { 515, CAMERA_ANTIBANDING_60HZ }, // Philippines
438 { 520, CAMERA_ANTIBANDING_50HZ }, // Thailand
439 { 525, CAMERA_ANTIBANDING_50HZ }, // Singapore
440 { 530, CAMERA_ANTIBANDING_50HZ }, // New Zealand
441 { 535, CAMERA_ANTIBANDING_60HZ }, // Guam
442 { 536, CAMERA_ANTIBANDING_50HZ }, // Nauru
443 { 537, CAMERA_ANTIBANDING_50HZ }, // Papua New Guinea
444 { 539, CAMERA_ANTIBANDING_50HZ }, // Tonga
445 { 541, CAMERA_ANTIBANDING_50HZ }, // Vanuatu
446 { 542, CAMERA_ANTIBANDING_50HZ }, // Fiji
447 { 544, CAMERA_ANTIBANDING_60HZ }, // American Samoa
448 { 545, CAMERA_ANTIBANDING_50HZ }, // Kiribati
449 { 546, CAMERA_ANTIBANDING_50HZ }, // New Caledonia
450 { 548, CAMERA_ANTIBANDING_50HZ }, // Cook Islands
451 { 602, CAMERA_ANTIBANDING_50HZ }, // Egypt
452 { 603, CAMERA_ANTIBANDING_50HZ }, // Algeria
453 { 604, CAMERA_ANTIBANDING_50HZ }, // Morocco
454 { 605, CAMERA_ANTIBANDING_50HZ }, // Tunisia
455 { 606, CAMERA_ANTIBANDING_50HZ }, // Libya
456 { 607, CAMERA_ANTIBANDING_50HZ }, // Gambia
457 { 608, CAMERA_ANTIBANDING_50HZ }, // Senegal
458 { 609, CAMERA_ANTIBANDING_50HZ }, // Mauritania
459 { 610, CAMERA_ANTIBANDING_50HZ }, // Mali
460 { 611, CAMERA_ANTIBANDING_50HZ }, // Guinea
461 { 613, CAMERA_ANTIBANDING_50HZ }, // Burkina Faso
462 { 614, CAMERA_ANTIBANDING_50HZ }, // Niger
463 { 616, CAMERA_ANTIBANDING_50HZ }, // Benin
464 { 617, CAMERA_ANTIBANDING_50HZ }, // Mauritius
465 { 618, CAMERA_ANTIBANDING_50HZ }, // Liberia
466 { 619, CAMERA_ANTIBANDING_50HZ }, // Sierra Leone
467 { 620, CAMERA_ANTIBANDING_50HZ }, // Ghana
468 { 621, CAMERA_ANTIBANDING_50HZ }, // Nigeria
469 { 622, CAMERA_ANTIBANDING_50HZ }, // Chad
470 { 623, CAMERA_ANTIBANDING_50HZ }, // Central African Republic
471 { 624, CAMERA_ANTIBANDING_50HZ }, // Cameroon
472 { 625, CAMERA_ANTIBANDING_50HZ }, // Cape Verde
473 { 627, CAMERA_ANTIBANDING_50HZ }, // Equatorial Guinea
474 { 631, CAMERA_ANTIBANDING_50HZ }, // Angola
475 { 633, CAMERA_ANTIBANDING_50HZ }, // Seychelles
476 { 634, CAMERA_ANTIBANDING_50HZ }, // Sudan
477 { 636, CAMERA_ANTIBANDING_50HZ }, // Ethiopia
478 { 637, CAMERA_ANTIBANDING_50HZ }, // Somalia
479 { 638, CAMERA_ANTIBANDING_50HZ }, // Djibouti
480 { 639, CAMERA_ANTIBANDING_50HZ }, // Kenya
481 { 640, CAMERA_ANTIBANDING_50HZ }, // Tanzania
482 { 641, CAMERA_ANTIBANDING_50HZ }, // Uganda
483 { 642, CAMERA_ANTIBANDING_50HZ }, // Burundi
484 { 643, CAMERA_ANTIBANDING_50HZ }, // Mozambique
485 { 645, CAMERA_ANTIBANDING_50HZ }, // Zambia
486 { 646, CAMERA_ANTIBANDING_50HZ }, // Madagascar
487 { 647, CAMERA_ANTIBANDING_50HZ }, // France
488 { 648, CAMERA_ANTIBANDING_50HZ }, // Zimbabwe
489 { 649, CAMERA_ANTIBANDING_50HZ }, // Namibia
490 { 650, CAMERA_ANTIBANDING_50HZ }, // Malawi
491 { 651, CAMERA_ANTIBANDING_50HZ }, // Lesotho
492 { 652, CAMERA_ANTIBANDING_50HZ }, // Botswana
493 { 653, CAMERA_ANTIBANDING_50HZ }, // Swaziland
494 { 654, CAMERA_ANTIBANDING_50HZ }, // Comoros
495 { 655, CAMERA_ANTIBANDING_50HZ }, // South Africa
496 { 657, CAMERA_ANTIBANDING_50HZ }, // Eritrea
497 { 702, CAMERA_ANTIBANDING_60HZ }, // Belize
498 { 704, CAMERA_ANTIBANDING_60HZ }, // Guatemala
499 { 706, CAMERA_ANTIBANDING_60HZ }, // El Salvador
500 { 708, CAMERA_ANTIBANDING_60HZ }, // Honduras
501 { 710, CAMERA_ANTIBANDING_60HZ }, // Nicaragua
502 { 712, CAMERA_ANTIBANDING_60HZ }, // Costa Rica
503 { 714, CAMERA_ANTIBANDING_60HZ }, // Panama
504 { 722, CAMERA_ANTIBANDING_50HZ }, // Argentina
505 { 724, CAMERA_ANTIBANDING_60HZ }, // Brazil
506 { 730, CAMERA_ANTIBANDING_50HZ }, // Chile
507 { 732, CAMERA_ANTIBANDING_60HZ }, // Colombia
508 { 734, CAMERA_ANTIBANDING_60HZ }, // Venezuela
509 { 736, CAMERA_ANTIBANDING_50HZ }, // Bolivia
510 { 738, CAMERA_ANTIBANDING_60HZ }, // Guyana
511 { 740, CAMERA_ANTIBANDING_60HZ }, // Ecuador
512 { 742, CAMERA_ANTIBANDING_50HZ }, // French Guiana
513 { 744, CAMERA_ANTIBANDING_50HZ }, // Paraguay
514 { 746, CAMERA_ANTIBANDING_60HZ }, // Suriname
515 { 748, CAMERA_ANTIBANDING_50HZ }, // Uruguay
516 { 750, CAMERA_ANTIBANDING_50HZ }, // Falkland Islands
517};
518
519#define country_number (sizeof(country_numeric) / sizeof(country_map))
520
521/* Look up pre-sorted antibanding_type table by current MCC. */
522static camera_antibanding_type camera_get_location(void) {
523 char value[PROP_VALUE_MAX];
524 char country_value[PROP_VALUE_MAX];
525 uint32_t country_code, count;
526 memset(value, 0x00, sizeof(value));
527 memset(country_value, 0x00, sizeof(country_value));
528 if (!__system_property_get("gsm.operator.numeric", value)) {
529 return CAMERA_ANTIBANDING_60HZ;
530 }
531 memcpy(country_value, value, 3);
532 country_code = atoi(country_value);
533 LOGD("value:%s, country value:%s, country code:%d\n",
534 value, country_value, country_code);
535 int left = 0;
536 int right = country_number - 1;
537 while (left <= right) {
538 int index = (left + right) >> 1;
539 if (country_numeric[index].country_code == country_code)
540 return country_numeric[index].type;
541 else if (country_numeric[index].country_code > country_code)
542 right = index - 1;
543 else
544 left = index + 1;
545 }
546 return CAMERA_ANTIBANDING_60HZ;
547}
548
549// from camera.h, led_mode_t
550static const str_map flash[] = {
551 { CameraParameters::FLASH_MODE_OFF, LED_MODE_OFF },
552 { CameraParameters::FLASH_MODE_AUTO, LED_MODE_AUTO },
553 { CameraParameters::FLASH_MODE_ON, LED_MODE_ON }
554};
555
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530556// from mm-camera/common/camera.h.
557static const str_map iso[] = {
558 { CameraParameters::ISO_AUTO, CAMERA_ISO_AUTO},
559 { CameraParameters::ISO_HJR, CAMERA_ISO_DEBLUR},
560 { CameraParameters::ISO_100, CAMERA_ISO_100},
561 { CameraParameters::ISO_200, CAMERA_ISO_200},
562 { CameraParameters::ISO_400, CAMERA_ISO_400},
563 { CameraParameters::ISO_800, CAMERA_ISO_800 }
564};
565
566
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800567#define DONT_CARE 0
568static const str_map focus_modes[] = {
Srinivasan Kannan71229622009-12-04 12:05:58 -0800569 { CameraParameters::FOCUS_MODE_AUTO, AF_MODE_AUTO},
570 { CameraParameters::FOCUS_MODE_INFINITY, DONT_CARE },
571 { CameraParameters::FOCUS_MODE_NORMAL, AF_MODE_NORMAL },
572 { CameraParameters::FOCUS_MODE_MACRO, AF_MODE_MACRO }
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800573};
574
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530575static const str_map lensshade[] = {
576 { CameraParameters::LENSSHADE_ENABLE, TRUE },
577 { CameraParameters::LENSSHADE_DISABLE, FALSE }
578};
579
Srinivasan Kannan71229622009-12-04 12:05:58 -0800580struct SensorType {
581 const char *name;
582 int rawPictureWidth;
583 int rawPictureHeight;
584 bool hasAutoFocusSupport;
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800585 int max_supported_snapshot_width;
586 int max_supported_snapshot_height;
Srinivasan Kannan71229622009-12-04 12:05:58 -0800587};
588
589static SensorType sensorTypes[] = {
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800590 { "5mp", 2608, 1960, true, 2592, 1944 },
591 { "3mp", 2064, 1544, false, 2048, 1536 },
592 { "2mp", 3200, 1200, false, 1600, 1200 } };
593
Srinivasan Kannan71229622009-12-04 12:05:58 -0800594
595static SensorType * sensorType;
596
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800597static const str_map picture_formats[] = {
598 {CameraParameters::PIXEL_FORMAT_JPEG, PICTURE_FORMAT_JPEG},
599 {CameraParameters::PIXEL_FORMAT_RAW, PICTURE_FORMAT_RAW}
600};
601
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800602static bool parameter_string_initialized = false;
603static String8 preview_size_values;
604static String8 picture_size_values;
605static String8 antibanding_values;
606static String8 effect_values;
Apurva Rajguru55562b02009-12-03 12:25:35 -0800607static String8 autoexposure_values;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800608static String8 whitebalance_values;
609static String8 flash_values;
610static String8 focus_mode_values;
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530611static String8 iso_values;
612static String8 lensshade_values;
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800613static String8 picture_format_values;
614
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800615
616static String8 create_sizes_str(const camera_size_type *sizes, int len) {
617 String8 str;
618 char buffer[32];
619
620 if (len > 0) {
621 sprintf(buffer, "%dx%d", sizes[0].width, sizes[0].height);
622 str.append(buffer);
623 }
624 for (int i = 1; i < len; i++) {
625 sprintf(buffer, ",%dx%d", sizes[i].width, sizes[i].height);
626 str.append(buffer);
627 }
628 return str;
629}
630
631static String8 create_values_str(const str_map *values, int len) {
632 String8 str;
633
634 if (len > 0) {
635 str.append(values[0].desc);
636 }
637 for (int i = 1; i < len; i++) {
638 str.append(",");
639 str.append(values[i].desc);
640 }
641 return str;
642}
643
Sravankb4f5f1c2010-01-21 11:06:17 +0530644extern "C" {
645//------------------------------------------------------------------------
646// : 720p busyQ funcitons
647// --------------------------------------------------------------------
648static struct fifo_queue g_busy_frame_queue =
649 {0, 0, 0, PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER};
650};
651/*===========================================================================
652 * FUNCTION cam_frame_wait_video
653 *
654 * DESCRIPTION this function waits a video in the busy queue
655 * ===========================================================================*/
656
657static void cam_frame_wait_video (void)
658{
659 LOGV("cam_frame_wait_video E ");
660 if ((g_busy_frame_queue.num_of_frames) <=0){
661 pthread_cond_wait(&(g_busy_frame_queue.wait), &(g_busy_frame_queue.mut));
662 }
663 LOGV("cam_frame_wait_video X");
664 return;
665}
666
667/*===========================================================================
668 * FUNCTION cam_frame_flush_video
669 *
670 * DESCRIPTION this function deletes all the buffers in busy queue
671 * ===========================================================================*/
672void cam_frame_flush_video (void)
673{
674 LOGV("cam_frame_flush_video: in n = %d\n", g_busy_frame_queue.num_of_frames);
675 pthread_mutex_lock(&(g_busy_frame_queue.mut));
676
677 while (g_busy_frame_queue.front)
678 {
679 //dequeue from the busy queue
680 struct fifo_node *node = dequeue (&g_busy_frame_queue);
681 if(node)
682 free(node);
683
684 LOGV("cam_frame_flush_video: node \n");
685 }
686 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
687 LOGV("cam_frame_flush_video: out n = %d\n", g_busy_frame_queue.num_of_frames);
688 return ;
689}
690/*===========================================================================
691 * FUNCTION cam_frame_get_video
692 *
693 * DESCRIPTION this function returns a video frame from the head
694 * ===========================================================================*/
695static struct msm_frame * cam_frame_get_video()
696{
697 struct msm_frame *p = NULL;
698 LOGV("cam_frame_get_video... in\n");
699 LOGV("cam_frame_get_video... got lock\n");
700 if (g_busy_frame_queue.front)
701 {
702 //dequeue
703 struct fifo_node *node = dequeue (&g_busy_frame_queue);
704 if (node)
705 {
706 p = (struct msm_frame *)node->f;
707 free (node);
708 }
709 LOGV("cam_frame_get_video... out = %x\n", p->buffer);
710 }
711 return p;
712}
713
714/*===========================================================================
715 * FUNCTION cam_frame_post_video
716 *
717 * DESCRIPTION this function add a busy video frame to the busy queue tails
718 * ===========================================================================*/
719static void cam_frame_post_video (struct msm_frame *p)
720{
721 if (!p)
722 {
723 LOGE("post video , buffer is null");
724 return;
725 }
726 LOGV("cam_frame_post_video... in = %x\n", (unsigned int)(p->buffer));
727 pthread_mutex_lock(&(g_busy_frame_queue.mut));
728 LOGV("post_video got lock. q count before enQ %d", g_busy_frame_queue.num_of_frames);
729 //enqueue to busy queue
730 struct fifo_node *node = (struct fifo_node *)malloc (sizeof (struct fifo_node));
731 if (node)
732 {
733 LOGV(" post video , enqueing in busy queue");
734 node->f = p;
735 node->next = NULL;
736 enqueue (&g_busy_frame_queue, node);
737 LOGV("post_video got lock. q count after enQ %d", g_busy_frame_queue.num_of_frames);
738 }
739 else
740 {
741 LOGE("cam_frame_post_video error... out of memory\n");
742 }
743
744 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
745 pthread_cond_signal(&(g_busy_frame_queue.wait));
746
747 LOGV("cam_frame_post_video... out = %x\n", p->buffer);
748
749 return;
750}
751
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -0800752void QualcommCameraHardware::storeTargetType(void) {
753 char mDeviceName[PROPERTY_VALUE_MAX];
754 property_get("ro.product.device",mDeviceName," ");
755 mCurrentTarget = TARGET_MAX;
756 for( int i = 0; i < TARGET_MAX ; i++) {
757 if( !strncmp(mDeviceName, targetList[i].targetStr, 7)) {
758 mCurrentTarget = targetList[i].targetEnum;
759 break;
760 }
761 }
762 LOGV(" Storing the current target type as %d ", mCurrentTarget );
763 return;
764}
765
Sravankb4f5f1c2010-01-21 11:06:17 +0530766//-------------------------------------------------------------------------------------
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800767static Mutex singleton_lock;
768static bool singleton_releasing;
769static Condition singleton_wait;
770
771static void receive_camframe_callback(struct msm_frame *frame);
Sravankb4f5f1c2010-01-21 11:06:17 +0530772static void receive_camframe_video_callback(struct msm_frame *frame); // 720p
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800773static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size);
774static void receive_jpeg_callback(jpeg_event_t status);
775static void receive_shutter_callback(common_crop_t *crop);
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800776static void receive_camframetimeout_callback(void);
Mohan Kandra284966d2010-01-05 13:39:15 -0800777static int fb_fd = -1;
778static int32_t mMaxZoom = 0;
779static bool native_get_maxzoom(int camfd, void *pZm);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800780
Mohan Kandrad9efed92010-01-15 19:08:39 -0800781static int dstOffset = 0;
782
Brian Steuer07704892009-12-18 18:07:33 -0800783static int camerafd;
784pthread_t w_thread;
785
786void *opencamerafd(void *data) {
787 camerafd = open(MSM_CAMERA_CONTROL, O_RDWR);
788 return NULL;
789}
790
Mohan Kandrad9efed92010-01-15 19:08:39 -0800791/* When using MDP zoom, double the preview buffers. The usage of these
792 * buffers is as follows:
793 * 1. As all the buffers comes under a single FD, and at initial registration,
794 * this FD will be passed to surface flinger, surface flinger can have access
795 * to all the buffers when needed.
796 * 2. Only "kPreviewBufferCount" buffers (SrcSet) will be registered with the
797 * camera driver to receive preview frames. The remaining buffers (DstSet),
798 * will be used at HAL and by surface flinger only when crop information
799 * is present in the frame.
800 * 3. When there is no crop information, there will be no call to MDP zoom,
801 * and the buffers in SrcSet will be passed to surface flinger to display.
802 * 4. With crop information present, MDP zoom will be called, and the final
803 * data will be placed in a buffer from DstSet, and this buffer will be given
804 * to surface flinger to display.
805 */
806#define NUM_MORE_BUFS 2
807
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800808QualcommCameraHardware::QualcommCameraHardware()
809 : mParameters(),
810 mCameraRunning(false),
811 mPreviewInitialized(false),
812 mFrameThreadRunning(false),
Mohan Kandra156d0ac2010-01-25 16:59:17 -0800813 mVideoThreadRunning(false),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800814 mSnapshotThreadRunning(false),
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800815 mSnapshotFormat(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800816 mReleasedRecordingFrame(false),
817 mPreviewFrameSize(0),
818 mRawSize(0),
819 mCameraControlFd(-1),
820 mAutoFocusThreadRunning(false),
821 mAutoFocusFd(-1),
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800822 mBrightness(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800823 mInPreviewCallback(false),
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800824 mUseOverlay(0),
825 mOverlay(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800826 mMsgEnabled(0),
827 mNotifyCallback(0),
828 mDataCallback(0),
829 mDataCallbackTimestamp(0),
Mohan Kandra740cfce2010-01-07 12:58:24 -0800830 mCallbackCookie(0),
831 mDebugFps(0)
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800832{
Brian Steuer07704892009-12-18 18:07:33 -0800833
834 // Start opening camera device in a separate thread/ Since this
835 // initializes the sensor hardware, this can take a long time. So,
836 // start the process here so it will be ready by the time it's
837 // needed.
838 if ((pthread_create(&w_thread, NULL, opencamerafd, NULL)) != 0) {
839 LOGE("Camera open thread creation failed");
840 }
841
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800842 memset(&mDimension, 0, sizeof(mDimension));
843 memset(&mCrop, 0, sizeof(mCrop));
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -0800844 memset(&zoomCropInfo, 0, sizeof(zoom_crop_info));
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -0800845 storeTargetType();
Mohan Kandra740cfce2010-01-07 12:58:24 -0800846 char value[PROPERTY_VALUE_MAX];
847 property_get("persist.debug.sf.showfps", value, "0");
848 mDebugFps = atoi(value);
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -0800849 if( mCurrentTarget == TARGET_MSM7630 )
Sravankb4f5f1c2010-01-21 11:06:17 +0530850 kPreviewBufferCountActual = kPreviewBufferCount;
851 else
852 kPreviewBufferCountActual = kPreviewBufferCount + NUM_MORE_BUFS;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800853 LOGV("constructor EX");
854}
855
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800856
857//filter Picture sizes based on max width and height
858void QualcommCameraHardware::filterPictureSizes(){
859 int i;
860 for(i=0;i<PICTURE_SIZE_COUNT;i++){
861 if(((picture_sizes[i].width <=
862 sensorType->max_supported_snapshot_width) &&
863 (picture_sizes[i].height <=
864 sensorType->max_supported_snapshot_height))){
865 picture_sizes_ptr = picture_sizes + i;
866 supportedPictureSizesCount = PICTURE_SIZE_COUNT - i ;
867 return ;
868 }
869 }
870}
871
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800872void QualcommCameraHardware::initDefaultParameters()
873{
874 LOGV("initDefaultParameters E");
875
876 // Initialize constant parameter strings. This will happen only once in the
877 // lifetime of the mediaserver process.
878 if (!parameter_string_initialized) {
Srinivasan Kannan71229622009-12-04 12:05:58 -0800879 findSensorType();
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800880 antibanding_values = create_values_str(
881 antibanding, sizeof(antibanding) / sizeof(str_map));
882 effect_values = create_values_str(
883 effects, sizeof(effects) / sizeof(str_map));
Apurva Rajguru55562b02009-12-03 12:25:35 -0800884 autoexposure_values = create_values_str(
885 autoexposure, sizeof(autoexposure) / sizeof(str_map));
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800886 whitebalance_values = create_values_str(
887 whitebalance, sizeof(whitebalance) / sizeof(str_map));
888 preview_size_values = create_sizes_str(
889 preview_sizes, PREVIEW_SIZE_COUNT);
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800890 //filter picture sizes
891 filterPictureSizes();
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800892 picture_size_values = create_sizes_str(
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800893 picture_sizes_ptr, supportedPictureSizesCount);
894
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800895 flash_values = create_values_str(
896 flash, sizeof(flash) / sizeof(str_map));
Srinivasan Kannan71229622009-12-04 12:05:58 -0800897 if(sensorType->hasAutoFocusSupport){
898 focus_mode_values = create_values_str(
899 focus_modes, sizeof(focus_modes) / sizeof(str_map));
900 }
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530901 iso_values = create_values_str(
902 iso,sizeof(iso)/sizeof(str_map));
903 lensshade_values = create_values_str(
904 lensshade,sizeof(lensshade)/sizeof(str_map));
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800905 picture_format_values = create_values_str(
906 picture_formats, sizeof(picture_formats)/sizeof(str_map));
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800907 parameter_string_initialized = true;
908 }
909
910 const camera_size_type *ps = &preview_sizes[DEFAULT_PREVIEW_SETTING];
911 mParameters.setPreviewSize(ps->width, ps->height);
912 mDimension.display_width = ps->width;
913 mDimension.display_height = ps->height;
914 mParameters.setPreviewFrameRate(15);
915 mParameters.setPreviewFormat("yuv420sp"); // informative
916
917 mParameters.setPictureSize(DEFAULT_PICTURE_WIDTH, DEFAULT_PICTURE_HEIGHT);
918 mParameters.setPictureFormat("jpeg"); // informative
919
Mohan Kandra785619a2010-02-01 21:52:42 -0800920 mParameters.set(CameraParameters::KEY_JPEG_QUALITY, "85"); // max quality
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800921 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH,
922 THUMBNAIL_WIDTH_STR); // informative
923 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT,
924 THUMBNAIL_HEIGHT_STR); // informative
Srinivasan Kannan80d878f2009-12-18 15:06:02 -0800925 mDimension.ui_thumbnail_width =
926 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].width;
927 mDimension.ui_thumbnail_height =
928 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800929 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, "90");
930
931 mParameters.set(CameraParameters::KEY_ANTIBANDING,
Mohan Kandra785619a2010-02-01 21:52:42 -0800932 CameraParameters::ANTIBANDING_OFF);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800933 mParameters.set(CameraParameters::KEY_EFFECT,
934 CameraParameters::EFFECT_NONE);
Apurva Rajguru55562b02009-12-03 12:25:35 -0800935 mParameters.set(CameraParameters::KEY_AUTO_EXPOSURE,
936 CameraParameters::AUTO_EXPOSURE_FRAME_AVG);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800937 mParameters.set(CameraParameters::KEY_WHITE_BALANCE,
938 CameraParameters::WHITE_BALANCE_AUTO);
939 mParameters.set(CameraParameters::KEY_FOCUS_MODE,
940 CameraParameters::FOCUS_MODE_AUTO);
Priya Komarlingam044c7b52010-01-22 18:21:23 -0800941 mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS,
942 "yuv420sp");
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800943
944 mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES,
945 preview_size_values.string());
946 mParameters.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES,
947 picture_size_values.string());
948 mParameters.set(CameraParameters::KEY_SUPPORTED_ANTIBANDING,
949 antibanding_values);
950 mParameters.set(CameraParameters::KEY_SUPPORTED_EFFECTS, effect_values);
Apurva Rajguru55562b02009-12-03 12:25:35 -0800951 mParameters.set(CameraParameters::KEY_SUPPORTED_AUTO_EXPOSURE, autoexposure_values);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800952 mParameters.set(CameraParameters::KEY_SUPPORTED_WHITE_BALANCE,
953 whitebalance_values);
954 mParameters.set(CameraParameters::KEY_SUPPORTED_FOCUS_MODES,
955 focus_mode_values);
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800956 mParameters.set(CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS,
957 picture_format_values);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800958
959 if (mSensorInfo.flash_enabled) {
960 mParameters.set(CameraParameters::KEY_FLASH_MODE,
961 CameraParameters::FLASH_MODE_OFF);
962 mParameters.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES,
963 flash_values);
964 }
965
Srinivasan Kannanbddfd502010-01-03 17:27:36 -0800966 mParameters.set(CameraParameters::KEY_MAX_SHARPNESS,
967 CAMERA_MAX_SHARPNESS);
968 mParameters.set(CameraParameters::KEY_MAX_CONTRAST,
969 CAMERA_MAX_CONTRAST);
970 mParameters.set(CameraParameters::KEY_MAX_SATURATION,
971 CAMERA_MAX_SATURATION);
972
Apurva Rajguru07185952010-01-22 15:40:07 -0800973 mParameters.set("luma-adaptation", "3");
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800974 mParameters.set("zoom-supported", "true");
975 mParameters.set("max-zoom", MAX_ZOOM_LEVEL);
976 mParameters.set("zoom", 0);
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800977 mParameters.set(CameraParameters::KEY_PICTURE_FORMAT,
978 CameraParameters::PIXEL_FORMAT_JPEG);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800979
Kiran Kumar H N595970b2010-01-12 10:41:09 -0800980 mParameters.set(CameraParameters::KEY_SHARPNESS,
981 CAMERA_DEF_SHARPNESS);
982 mParameters.set(CameraParameters::KEY_CONTRAST,
983 CAMERA_DEF_CONTRAST);
984 mParameters.set(CameraParameters::KEY_SATURATION,
985 CAMERA_DEF_SATURATION);
986
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530987 mParameters.set(CameraParameters::KEY_ISO_MODE,
988 CameraParameters::ISO_AUTO);
989 mParameters.set(CameraParameters::KEY_LENSSHADE,
990 CameraParameters::LENSSHADE_ENABLE);
991 mParameters.set(CameraParameters::KEY_SUPPORTED_ISO_MODES,
992 iso_values);
993 mParameters.set(CameraParameters::KEY_SUPPORTED_LENSSHADE_MODES,
994 lensshade_values);
995
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800996 if (setParameters(mParameters) != NO_ERROR) {
997 LOGE("Failed to set default parameters?!");
998 }
999
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08001000 mUseOverlay = useOverlay();
1001
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001002 /* Initialize the camframe_timeout_flag*/
1003 Mutex::Autolock l(&mCamframeTimeoutLock);
1004 camframe_timeout_flag = FALSE;
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08001005 mPostViewHeap = NULL;
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001006
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001007 LOGV("initDefaultParameters X");
1008}
1009
Srinivasan Kannan71229622009-12-04 12:05:58 -08001010void QualcommCameraHardware::findSensorType(){
1011 mDimension.picture_width = DEFAULT_PICTURE_WIDTH;
1012 mDimension.picture_height = DEFAULT_PICTURE_HEIGHT;
1013 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
1014 sizeof(cam_ctrl_dimension_t), &mDimension);
1015 if (ret) {
1016 unsigned int i;
1017 for (i = 0; i < sizeof(sensorTypes) / sizeof(SensorType); i++) {
1018 if (sensorTypes[i].rawPictureHeight
1019 == mDimension.raw_picture_height) {
1020 sensorType = sensorTypes + i;
1021 return;
1022 }
1023 }
1024 }
1025 //default to 5 mp
1026 sensorType = sensorTypes;
1027 return;
1028}
1029
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001030#define ROUND_TO_PAGE(x) (((x)+0xfff)&~0xfff)
1031
1032bool QualcommCameraHardware::startCamera()
1033{
1034 LOGV("startCamera E");
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08001035 if( mCurrentTarget == TARGET_MAX ) {
1036 LOGE(" Unable to determine the target type. Camera will not work ");
1037 return false;
1038 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001039#if DLOPEN_LIBMMCAMERA
1040 libmmcamera = ::dlopen("liboemcamera.so", RTLD_NOW);
1041 LOGV("loading liboemcamera at %p", libmmcamera);
1042 if (!libmmcamera) {
1043 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
1044 return false;
1045 }
1046
1047 *(void **)&LINK_cam_frame =
1048 ::dlsym(libmmcamera, "cam_frame");
1049 *(void **)&LINK_camframe_terminate =
1050 ::dlsym(libmmcamera, "camframe_terminate");
1051
1052 *(void **)&LINK_jpeg_encoder_init =
1053 ::dlsym(libmmcamera, "jpeg_encoder_init");
1054
1055 *(void **)&LINK_jpeg_encoder_encode =
1056 ::dlsym(libmmcamera, "jpeg_encoder_encode");
1057
1058 *(void **)&LINK_jpeg_encoder_join =
1059 ::dlsym(libmmcamera, "jpeg_encoder_join");
1060
1061 *(void **)&LINK_mmcamera_camframe_callback =
1062 ::dlsym(libmmcamera, "mmcamera_camframe_callback");
1063
1064 *LINK_mmcamera_camframe_callback = receive_camframe_callback;
1065
1066 *(void **)&LINK_mmcamera_jpegfragment_callback =
1067 ::dlsym(libmmcamera, "mmcamera_jpegfragment_callback");
1068
1069 *LINK_mmcamera_jpegfragment_callback = receive_jpeg_fragment_callback;
1070
1071 *(void **)&LINK_mmcamera_jpeg_callback =
1072 ::dlsym(libmmcamera, "mmcamera_jpeg_callback");
1073
1074 *LINK_mmcamera_jpeg_callback = receive_jpeg_callback;
1075
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001076 *(void **)&LINK_camframe_timeout_callback =
1077 ::dlsym(libmmcamera, "camframe_timeout_callback");
1078
1079 *LINK_camframe_timeout_callback = receive_camframetimeout_callback;
1080
Sravankb4f5f1c2010-01-21 11:06:17 +05301081 // 720 p new recording functions
1082 *(void **)&LINK_cam_frame_flush_free_video = ::dlsym(libmmcamera, "cam_frame_flush_free_video");
1083
1084 *(void **)&LINK_camframe_free_video = ::dlsym(libmmcamera, "cam_frame_add_free_video");
1085
1086 *(void **)&LINK_camframe_video_callback = ::dlsym(libmmcamera, "mmcamera_camframe_videocallback");
1087 *LINK_camframe_video_callback = receive_camframe_video_callback;
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001088/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001089 *(void **)&LINK_mmcamera_shutter_callback =
1090 ::dlsym(libmmcamera, "mmcamera_shutter_callback");
1091
1092 *LINK_mmcamera_shutter_callback = receive_shutter_callback;
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001093*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001094 *(void**)&LINK_jpeg_encoder_setMainImageQuality =
1095 ::dlsym(libmmcamera, "jpeg_encoder_setMainImageQuality");
Kiran Kumar H N8861f302010-01-05 12:01:41 -08001096
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001097 *(void**)&LINK_jpeg_encoder_setThumbnailQuality =
1098 ::dlsym(libmmcamera, "jpeg_encoder_setThumbnailQuality");
1099
1100 *(void**)&LINK_jpeg_encoder_setRotation =
1101 ::dlsym(libmmcamera, "jpeg_encoder_setRotation");
1102
Kiran Kumar H N8861f302010-01-05 12:01:41 -08001103/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001104 *(void**)&LINK_jpeg_encoder_setLocation =
1105 ::dlsym(libmmcamera, "jpeg_encoder_setLocation");
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001106*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001107 *(void **)&LINK_cam_conf =
1108 ::dlsym(libmmcamera, "cam_conf");
1109
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001110/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001111 *(void **)&LINK_default_sensor_get_snapshot_sizes =
1112 ::dlsym(libmmcamera, "default_sensor_get_snapshot_sizes");
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001113*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001114 *(void **)&LINK_launch_cam_conf_thread =
1115 ::dlsym(libmmcamera, "launch_cam_conf_thread");
1116
1117 *(void **)&LINK_release_cam_conf_thread =
1118 ::dlsym(libmmcamera, "release_cam_conf_thread");
1119
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001120/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001121 *(void **)&LINK_zoom_crop_upscale =
1122 ::dlsym(libmmcamera, "zoom_crop_upscale");
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001123*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001124
1125#else
1126 mmcamera_camframe_callback = receive_camframe_callback;
1127 mmcamera_jpegfragment_callback = receive_jpeg_fragment_callback;
1128 mmcamera_jpeg_callback = receive_jpeg_callback;
1129 mmcamera_shutter_callback = receive_shutter_callback;
1130#endif // DLOPEN_LIBMMCAMERA
1131
1132 /* The control thread is in libcamera itself. */
Brian Steuer07704892009-12-18 18:07:33 -08001133 if (pthread_join(w_thread, NULL) != 0) {
1134 LOGE("Camera open thread exit failed");
1135 return false;
1136 }
1137 mCameraControlFd = camerafd;
1138
Kiran Kumar H N585bc362010-01-19 13:04:44 -08001139 if (mCameraControlFd < 0) {
1140 LOGE("startCamera X: %s open failed: %s!",
1141 MSM_CAMERA_CONTROL,
1142 strerror(errno));
1143 return false;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001144 }
1145
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08001146 if( mCurrentTarget != TARGET_MSM7630 ){
Mohan Kandra284966d2010-01-05 13:39:15 -08001147 fb_fd = open("/dev/graphics/fb0", O_RDWR);
1148 if (fb_fd < 0) {
1149 LOGE("startCamera: fb0 open failed: %s!", strerror(errno));
1150 return FALSE;
1151 }
1152 }
1153
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001154 /* This will block until the control thread is launched. After that, sensor
1155 * information becomes available.
1156 */
1157
1158 if (LINK_launch_cam_conf_thread()) {
1159 LOGE("failed to launch the camera config thread");
1160 return false;
1161 }
1162
1163 memset(&mSensorInfo, 0, sizeof(mSensorInfo));
1164 if (ioctl(mCameraControlFd,
1165 MSM_CAM_IOCTL_GET_SENSOR_INFO,
1166 &mSensorInfo) < 0)
1167 LOGW("%s: cannot retrieve sensor info!", __FUNCTION__);
1168 else
1169 LOGI("%s: camsensor name %s, flash %d", __FUNCTION__,
1170 mSensorInfo.name, mSensorInfo.flash_enabled);
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001171/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001172 picture_sizes = LINK_default_sensor_get_snapshot_sizes(&PICTURE_SIZE_COUNT);
1173 if (!picture_sizes || !PICTURE_SIZE_COUNT) {
1174 LOGE("startCamera X: could not get snapshot sizes");
1175 return false;
1176 }
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001177*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001178 LOGV("startCamera X");
1179 return true;
1180}
1181
1182status_t QualcommCameraHardware::dump(int fd,
1183 const Vector<String16>& args) const
1184{
1185 const size_t SIZE = 256;
1186 char buffer[SIZE];
1187 String8 result;
1188
1189 // Dump internal primitives.
1190 result.append("QualcommCameraHardware::dump");
1191 snprintf(buffer, 255, "mMsgEnabled (%d)\n", mMsgEnabled);
1192 result.append(buffer);
1193 int width, height;
1194 mParameters.getPreviewSize(&width, &height);
1195 snprintf(buffer, 255, "preview width(%d) x height (%d)\n", width, height);
1196 result.append(buffer);
1197 mParameters.getPictureSize(&width, &height);
1198 snprintf(buffer, 255, "raw width(%d) x height (%d)\n", width, height);
1199 result.append(buffer);
1200 snprintf(buffer, 255,
1201 "preview frame size(%d), raw size (%d), jpeg size (%d) "
1202 "and jpeg max size (%d)\n", mPreviewFrameSize, mRawSize,
1203 mJpegSize, mJpegMaxSize);
1204 result.append(buffer);
1205 write(fd, result.string(), result.size());
1206
1207 // Dump internal objects.
Mohan Kandrad9efed92010-01-15 19:08:39 -08001208 if (mPreviewHeap != 0) {
1209 mPreviewHeap->dump(fd, args);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001210 }
1211 if (mRawHeap != 0) {
1212 mRawHeap->dump(fd, args);
1213 }
1214 if (mJpegHeap != 0) {
1215 mJpegHeap->dump(fd, args);
1216 }
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001217 if(mRawSnapshotAshmemHeap != 0 ){
1218 mRawSnapshotAshmemHeap->dump(fd, args);
1219 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001220 mParameters.dump(fd, args);
1221 return NO_ERROR;
1222}
1223
Mohan Kandra284966d2010-01-05 13:39:15 -08001224static bool native_get_maxzoom(int camfd, void *pZm)
1225{
1226 LOGV("native_get_maxzoom E");
1227
1228 struct msm_ctrl_cmd ctrlCmd;
1229 int32_t *pZoom = (int32_t *)pZm;
1230
1231 ctrlCmd.type = CAMERA_GET_PARM_MAXZOOM;
1232 ctrlCmd.timeout_ms = 5000;
1233 ctrlCmd.length = sizeof(int32_t);
1234 ctrlCmd.value = pZoom;
1235 ctrlCmd.resp_fd = camfd;
1236
1237 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1238 LOGE("native_get_maxzoom: ioctl fd %d error %s",
1239 camfd,
1240 strerror(errno));
1241 return false;
1242 }
Brian Steuerb62adbd2010-02-02 14:47:08 -08001243 LOGD("ctrlCmd.value = %d", *(int32_t *)ctrlCmd.value);
Mohan Kandra284966d2010-01-05 13:39:15 -08001244 memcpy(pZoom, (int32_t *)ctrlCmd.value, sizeof(int32_t));
1245
1246 LOGV("native_get_maxzoom X");
1247 return true;
1248}
1249
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001250static bool native_set_afmode(int camfd, isp3a_af_mode_t af_type)
1251{
1252 int rc;
1253 struct msm_ctrl_cmd ctrlCmd;
1254
1255 ctrlCmd.timeout_ms = 5000;
1256 ctrlCmd.type = CAMERA_SET_PARM_AUTO_FOCUS;
1257 ctrlCmd.length = sizeof(af_type);
1258 ctrlCmd.value = &af_type;
1259 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1260
1261 if ((rc = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0)
1262 LOGE("native_set_afmode: ioctl fd %d error %s\n",
1263 camfd,
1264 strerror(errno));
1265
1266 LOGV("native_set_afmode: ctrlCmd.status == %d\n", ctrlCmd.status);
1267 return rc >= 0 && ctrlCmd.status == CAMERA_EXIT_CB_DONE;
1268}
1269
1270static bool native_cancel_afmode(int camfd, int af_fd)
1271{
1272 int rc;
1273 struct msm_ctrl_cmd ctrlCmd;
1274
1275 ctrlCmd.timeout_ms = 0;
1276 ctrlCmd.type = CAMERA_AUTO_FOCUS_CANCEL;
1277 ctrlCmd.length = 0;
1278 ctrlCmd.value = NULL;
1279 ctrlCmd.resp_fd = -1; // there's no response fd
1280
1281 if ((rc = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND_2, &ctrlCmd)) < 0)
1282 {
1283 LOGE("native_cancel_afmode: ioctl fd %d error %s\n",
1284 camfd,
1285 strerror(errno));
1286 return false;
1287 }
1288
1289 return true;
1290}
1291
1292static bool native_start_preview(int camfd)
1293{
1294 struct msm_ctrl_cmd ctrlCmd;
1295
1296 ctrlCmd.timeout_ms = 5000;
1297 ctrlCmd.type = CAMERA_START_PREVIEW;
1298 ctrlCmd.length = 0;
1299 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1300
1301 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1302 LOGE("native_start_preview: MSM_CAM_IOCTL_CTRL_COMMAND fd %d error %s",
1303 camfd,
1304 strerror(errno));
1305 return false;
1306 }
1307
1308 return true;
1309}
1310
1311static bool native_get_picture (int camfd, common_crop_t *crop)
1312{
1313 struct msm_ctrl_cmd ctrlCmd;
1314
1315 ctrlCmd.timeout_ms = 5000;
1316 ctrlCmd.length = sizeof(common_crop_t);
1317 ctrlCmd.value = crop;
1318
1319 if(ioctl(camfd, MSM_CAM_IOCTL_GET_PICTURE, &ctrlCmd) < 0) {
1320 LOGE("native_get_picture: MSM_CAM_IOCTL_GET_PICTURE fd %d error %s",
1321 camfd,
1322 strerror(errno));
1323 return false;
1324 }
1325
1326 LOGV("crop: in1_w %d", crop->in1_w);
1327 LOGV("crop: in1_h %d", crop->in1_h);
1328 LOGV("crop: out1_w %d", crop->out1_w);
1329 LOGV("crop: out1_h %d", crop->out1_h);
1330
1331 LOGV("crop: in2_w %d", crop->in2_w);
1332 LOGV("crop: in2_h %d", crop->in2_h);
1333 LOGV("crop: out2_w %d", crop->out2_w);
1334 LOGV("crop: out2_h %d", crop->out2_h);
1335
1336 LOGV("crop: update %d", crop->update_flag);
1337
1338 return true;
1339}
1340
1341static bool native_stop_preview(int camfd)
1342{
1343 struct msm_ctrl_cmd ctrlCmd;
1344 ctrlCmd.timeout_ms = 5000;
1345 ctrlCmd.type = CAMERA_STOP_PREVIEW;
1346 ctrlCmd.length = 0;
1347 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1348
1349 if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1350 LOGE("native_stop_preview: ioctl fd %d error %s",
1351 camfd,
1352 strerror(errno));
1353 return false;
1354 }
1355
1356 return true;
1357}
1358
1359static bool native_prepare_snapshot(int camfd)
1360{
1361 int ioctlRetVal = true;
1362 struct msm_ctrl_cmd ctrlCmd;
1363
1364 ctrlCmd.timeout_ms = 1000;
1365 ctrlCmd.type = CAMERA_PREPARE_SNAPSHOT;
1366 ctrlCmd.length = 0;
1367 ctrlCmd.value = NULL;
1368 ctrlCmd.resp_fd = camfd;
1369
1370 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1371 LOGE("native_prepare_snapshot: ioctl fd %d error %s",
1372 camfd,
1373 strerror(errno));
1374 return false;
1375 }
1376 return true;
1377}
1378
1379static bool native_start_snapshot(int camfd)
1380{
1381 struct msm_ctrl_cmd ctrlCmd;
1382
1383 ctrlCmd.timeout_ms = 5000;
1384 ctrlCmd.type = CAMERA_START_SNAPSHOT;
1385 ctrlCmd.length = 0;
1386 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1387
1388 if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1389 LOGE("native_start_snapshot: ioctl fd %d error %s",
1390 camfd,
1391 strerror(errno));
1392 return false;
1393 }
1394
1395 return true;
1396}
1397
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001398static bool native_start_raw_snapshot(int camfd)
1399{
1400 int ret;
1401 struct msm_ctrl_cmd ctrlCmd;
1402
1403 ctrlCmd.timeout_ms = 1000;
1404 ctrlCmd.type = CAMERA_START_RAW_SNAPSHOT;
1405 ctrlCmd.length = 0;
1406 ctrlCmd.value = NULL;
1407 ctrlCmd.resp_fd = camfd;
1408
1409 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1410 LOGE("native_start_raw_snapshot: ioctl failed. ioctl return value "\
1411 "is %d \n", ret);
1412 return false;
1413 }
1414 return true;
1415}
1416
1417
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001418static bool native_stop_snapshot (int camfd)
1419{
1420 struct msm_ctrl_cmd ctrlCmd;
1421
1422 ctrlCmd.timeout_ms = 0;
1423 ctrlCmd.type = CAMERA_STOP_SNAPSHOT;
1424 ctrlCmd.length = 0;
1425 ctrlCmd.resp_fd = -1;
1426
1427 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND_2, &ctrlCmd) < 0) {
1428 LOGE("native_stop_snapshot: ioctl fd %d error %s",
1429 camfd,
1430 strerror(errno));
1431 return false;
1432 }
1433
1434 return true;
1435}
Sravankb4f5f1c2010-01-21 11:06:17 +05301436/*===========================================================================
1437 * FUNCTION - native_start_recording -
1438 *
1439 * DESCRIPTION:
1440 *==========================================================================*/
1441static bool native_start_recording(int camfd)
1442{
1443 int ret;
1444 struct msm_ctrl_cmd ctrlCmd;
1445
1446 ctrlCmd.timeout_ms = 1000;
1447 ctrlCmd.type = CAMERA_START_RECORDING;
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_recording: ioctl failed. ioctl return value "\
1454 "is %d \n", ret);
1455 return false;
1456 }
Mohan Kandraf1ebf982010-02-02 15:25:43 -08001457 LOGV("native_start_recording: ioctl good. ioctl return value is %d \n",ret);
Sravankb4f5f1c2010-01-21 11:06:17 +05301458
1459 /* TODO: Check status of postprocessing if there is any,
1460 * PP status should be in ctrlCmd */
1461
1462 return true;
1463}
1464
1465/*===========================================================================
1466 * FUNCTION - native_stop_recording -
1467 *
1468 * DESCRIPTION:
1469 *==========================================================================*/
1470static bool native_stop_recording(int camfd)
1471{
1472 int ret;
1473 struct msm_ctrl_cmd ctrlCmd;
Kiran Kumar H Nb49af212010-02-17 15:12:17 -08001474 LOGV("in native_stop_recording ");
Sravankb4f5f1c2010-01-21 11:06:17 +05301475 ctrlCmd.timeout_ms = 1000;
1476 ctrlCmd.type = CAMERA_STOP_RECORDING;
1477 ctrlCmd.length = 0;
1478 ctrlCmd.value = NULL;
1479 ctrlCmd.resp_fd = camfd;
1480
1481 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1482 LOGE("native_stop_video: ioctl failed. ioctl return value is %d \n",
1483 ret);
1484 return false;
1485 }
1486 LOGV("in native_stop_recording returned %d", ret);
1487 return true;
1488}
1489/*===========================================================================
1490 * FUNCTION - native_start_video -
1491 *
1492 * DESCRIPTION:
1493 *==========================================================================*/
1494static bool native_start_video(int camfd)
1495{
1496 int ret;
1497 struct msm_ctrl_cmd ctrlCmd;
1498
1499 ctrlCmd.timeout_ms = 1000;
1500 ctrlCmd.type = CAMERA_START_VIDEO;
1501 ctrlCmd.length = 0;
1502 ctrlCmd.value = NULL;
1503 ctrlCmd.resp_fd = camfd;
1504
1505 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1506 LOGE("native_start_video: ioctl failed. ioctl return value is %d \n",
1507 ret);
1508 return false;
1509 }
1510
1511 /* TODO: Check status of postprocessing if there is any,
1512 * PP status should be in ctrlCmd */
1513
1514 return true;
1515}
1516
1517/*===========================================================================
1518 * FUNCTION - native_stop_video -
1519 *
1520 * DESCRIPTION:
1521 *==========================================================================*/
1522static bool native_stop_video(int camfd)
1523{
1524 int ret;
1525 struct msm_ctrl_cmd ctrlCmd;
1526
1527 ctrlCmd.timeout_ms = 1000;
1528 ctrlCmd.type = CAMERA_STOP_VIDEO;
1529 ctrlCmd.length = 0;
1530 ctrlCmd.value = NULL;
1531 ctrlCmd.resp_fd = camfd;
1532
1533 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1534 LOGE("native_stop_video: ioctl failed. ioctl return value is %d \n",
1535 ret);
1536 return false;
1537 }
1538
1539 return true;
1540}
1541/*==========================================================================*/
1542
1543static cam_frame_start_parms frame_parms;
1544static int recordingState = 0;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001545
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001546static rat_t latitude[3];
1547static rat_t longitude[3];
1548static char lonref[2];
1549static char latref[2];
1550static char dateTime[20];
1551static rat_t altitude;
1552
1553static void addExifTag(exif_tag_id_t tagid, exif_tag_type_t type,
1554 uint32_t count, uint8_t copy, void *data) {
1555
1556 if(exif_table_numEntries == MAX_EXIF_TABLE_ENTRIES) {
1557 LOGE("Number of entries exceeded limit");
1558 return;
1559 }
1560
1561 int index = exif_table_numEntries;
1562 exif_data[index].tag_id = tagid;
1563 exif_data[index].tag_entry.type = type;
1564 exif_data[index].tag_entry.count = count;
1565 exif_data[index].tag_entry.copy = copy;
1566 if((type == EXIF_RATIONAL) && (count > 1))
1567 exif_data[index].tag_entry.data._rats = (rat_t *)data;
1568 if((type == EXIF_RATIONAL) && (count == 1))
1569 exif_data[index].tag_entry.data._rat = *(rat_t *)data;
1570 else if(type == EXIF_ASCII)
1571 exif_data[index].tag_entry.data._ascii = (char *)data;
1572 else if(type == EXIF_BYTE)
1573 exif_data[index].tag_entry.data._byte = *(uint8_t *)data;
1574
1575 // Increase number of entries
1576 exif_table_numEntries++;
1577}
1578
1579static void parseLatLong(const char *latlonString, int *pDegrees,
1580 int *pMinutes, int *pSeconds ) {
1581
1582 double value = atof(latlonString);
1583 value = fabs(value);
1584 int degrees = (int) value;
1585
1586 double remainder = value - degrees;
1587 int minutes = (int) (remainder * 60);
1588 int seconds = (int) (((remainder * 60) - minutes) * 60 * 1000);
1589
1590 *pDegrees = degrees;
1591 *pMinutes = minutes;
1592 *pSeconds = seconds;
1593}
1594
1595static void setLatLon(exif_tag_id_t tag, const char *latlonString) {
1596
1597 int degrees, minutes, seconds;
1598
1599 parseLatLong(latlonString, &degrees, &minutes, &seconds);
1600
1601 rat_t value[3] = { {degrees, 1},
1602 {minutes, 1},
1603 {seconds, 1000} };
1604
1605 if(tag == EXIFTAGID_GPS_LATITUDE) {
1606 memcpy(latitude, value, sizeof(latitude));
1607 addExifTag(EXIFTAGID_GPS_LATITUDE, EXIF_RATIONAL, 3,
1608 1, (void *)latitude);
1609 } else {
1610 memcpy(longitude, value, sizeof(longitude));
1611 addExifTag(EXIFTAGID_GPS_LONGITUDE, EXIF_RATIONAL, 3,
1612 1, (void *)longitude);
1613 }
1614}
1615
1616void QualcommCameraHardware::setGpsParameters() {
1617 const char *str = NULL;
1618
1619 //Set Latitude
1620 str = mParameters.get(CameraParameters::KEY_GPS_LATITUDE);
1621 if(str != NULL) {
1622 setLatLon(EXIFTAGID_GPS_LATITUDE, str);
1623 //set Latitude Ref
1624 str = NULL;
1625 str = mParameters.get(CameraParameters::KEY_GPS_LATITUDE_REF);
1626 if(str != NULL) {
1627 strncpy(latref, str, 1);
1628 latref[1] = '\0';
1629 addExifTag(EXIFTAGID_GPS_LATITUDE_REF, EXIF_ASCII, 2,
1630 1, (void *)latref);
1631 }
1632 }
1633
1634 //set Longitude
1635 str = NULL;
1636 str = mParameters.get(CameraParameters::KEY_GPS_LONGITUDE);
1637 if(str != NULL) {
1638 setLatLon(EXIFTAGID_GPS_LONGITUDE, str);
1639 //set Longitude Ref
1640 str = NULL;
1641 str = mParameters.get(CameraParameters::KEY_GPS_LONGITUDE_REF);
1642 if(str != NULL) {
1643 strncpy(lonref, str, 1);
1644 lonref[1] = '\0';
1645 addExifTag(EXIFTAGID_GPS_LONGITUDE_REF, EXIF_ASCII, 2,
1646 1, (void *)lonref);
1647 }
1648 }
1649
1650 //set Altitude
1651 str = NULL;
1652 str = mParameters.get(CameraParameters::KEY_GPS_ALTITUDE);
1653 if(str != NULL) {
1654 int value = atoi(str);
1655 rat_t alt_value = {value, 1000};
1656 memcpy(&altitude, &alt_value, sizeof(altitude));
1657 addExifTag(EXIFTAGID_GPS_ALTITUDE, EXIF_RATIONAL, 1,
1658 1, (void *)&altitude);
1659 //set AltitudeRef
1660 int ref = mParameters.getInt(CameraParameters::KEY_GPS_ALTITUDE_REF);
1661 if( !(ref < 0 || ref > 1) )
1662 addExifTag(EXIFTAGID_GPS_ALTITUDE_REF, EXIF_BYTE, 1,
1663 1, (void *)&ref);
1664 }
1665
1666
1667}
1668
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001669bool QualcommCameraHardware::native_jpeg_encode(void)
1670{
1671 int jpeg_quality = mParameters.getInt("jpeg-quality");
1672 if (jpeg_quality >= 0) {
1673 LOGV("native_jpeg_encode, current jpeg main img quality =%d",
1674 jpeg_quality);
1675 if(!LINK_jpeg_encoder_setMainImageQuality(jpeg_quality)) {
1676 LOGE("native_jpeg_encode set jpeg-quality failed");
1677 return false;
1678 }
1679 }
1680
1681 int thumbnail_quality = mParameters.getInt("jpeg-thumbnail-quality");
1682 if (thumbnail_quality >= 0) {
1683 LOGV("native_jpeg_encode, current jpeg thumbnail quality =%d",
1684 thumbnail_quality);
1685 if(!LINK_jpeg_encoder_setThumbnailQuality(thumbnail_quality)) {
1686 LOGE("native_jpeg_encode set thumbnail-quality failed");
1687 return false;
1688 }
1689 }
1690
1691 int rotation = mParameters.getInt("rotation");
1692 if (rotation >= 0) {
1693 LOGV("native_jpeg_encode, rotation = %d", rotation);
1694 if(!LINK_jpeg_encoder_setRotation(rotation)) {
1695 LOGE("native_jpeg_encode set rotation failed");
1696 return false;
1697 }
1698 }
1699
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001700// jpeg_set_location();
1701 if(mParameters.getInt(CameraParameters::KEY_GPS_STATUS) == 1) {
1702 setGpsParameters();
1703 }
1704 //set TimeStamp
1705 const char *str = mParameters.get(CameraParameters::KEY_EXIF_DATETIME);
1706 if(str != NULL) {
1707 strncpy(dateTime, str, 19);
1708 dateTime[19] = '\0';
1709 addExifTag(EXIFTAGID_EXIF_DATE_TIME_ORIGINAL, EXIF_ASCII,
1710 20, 1, (void *)dateTime);
1711 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001712
1713 if (!LINK_jpeg_encoder_encode(&mDimension,
1714 (uint8_t *)mThumbnailHeap->mHeap->base(),
1715 mThumbnailHeap->mHeap->getHeapID(),
1716 (uint8_t *)mRawHeap->mHeap->base(),
1717 mRawHeap->mHeap->getHeapID(),
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001718 &mCrop, exif_data, exif_table_numEntries)) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001719 LOGE("native_jpeg_encode: jpeg_encoder_encode failed.");
1720 return false;
1721 }
1722 return true;
1723}
1724
1725bool QualcommCameraHardware::native_set_parm(
1726 cam_ctrl_type type, uint16_t length, void *value)
1727{
1728 struct msm_ctrl_cmd ctrlCmd;
1729
1730 ctrlCmd.timeout_ms = 5000;
1731 ctrlCmd.type = (uint16_t)type;
1732 ctrlCmd.length = length;
1733 // FIXME: this will be put in by the kernel
1734 ctrlCmd.resp_fd = mCameraControlFd;
1735 ctrlCmd.value = value;
1736
1737 LOGV("%s: fd %d, type %d, length %d", __FUNCTION__,
1738 mCameraControlFd, type, length);
1739 if (ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0 ||
1740 ctrlCmd.status != CAM_CTRL_SUCCESS) {
1741 LOGE("%s: error (%s): fd %d, type %d, length %d, status %d",
1742 __FUNCTION__, strerror(errno),
1743 mCameraControlFd, type, length, ctrlCmd.status);
1744 return false;
1745 }
1746 return true;
1747}
1748
1749void QualcommCameraHardware::jpeg_set_location()
1750{
1751 bool encode_location = true;
1752 camera_position_type pt;
1753
1754#define PARSE_LOCATION(what,type,fmt,desc) do { \
1755 pt.what = 0; \
1756 const char *what##_str = mParameters.get("gps-"#what); \
1757 LOGV("GPS PARM %s --> [%s]", "gps-"#what, what##_str); \
1758 if (what##_str) { \
1759 type what = 0; \
1760 if (sscanf(what##_str, fmt, &what) == 1) \
1761 pt.what = what; \
1762 else { \
1763 LOGE("GPS " #what " %s could not" \
1764 " be parsed as a " #desc, what##_str); \
1765 encode_location = false; \
1766 } \
1767 } \
1768 else { \
1769 LOGV("GPS " #what " not specified: " \
1770 "defaulting to zero in EXIF header."); \
1771 encode_location = false; \
1772 } \
1773 } while(0)
1774
1775 PARSE_LOCATION(timestamp, long, "%ld", "long");
1776 if (!pt.timestamp) pt.timestamp = time(NULL);
1777 PARSE_LOCATION(altitude, short, "%hd", "short");
1778 PARSE_LOCATION(latitude, double, "%lf", "double float");
1779 PARSE_LOCATION(longitude, double, "%lf", "double float");
1780
1781#undef PARSE_LOCATION
1782
1783 if (encode_location) {
1784 LOGD("setting image location ALT %d LAT %lf LON %lf",
1785 pt.altitude, pt.latitude, pt.longitude);
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001786/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001787 if (!LINK_jpeg_encoder_setLocation(&pt)) {
1788 LOGE("jpeg_set_location: LINK_jpeg_encoder_setLocation failed.");
1789 }
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001790*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001791 }
1792 else LOGV("not setting image location");
1793}
1794
1795void QualcommCameraHardware::runFrameThread(void *data)
1796{
1797 LOGV("runFrameThread E");
1798
1799 int cnt;
1800
1801#if DLOPEN_LIBMMCAMERA
1802 // We need to maintain a reference to libqcamera.so for the duration of the
1803 // frame thread, because we do not know when it will exit relative to the
1804 // lifetime of this object. We do not want to dlclose() libqcamera while
1805 // LINK_cam_frame is still running.
1806 void *libhandle = ::dlopen("liboemcamera.so", RTLD_NOW);
1807 LOGV("FRAME: loading libqcamera at %p", libhandle);
1808 if (!libhandle) {
1809 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
1810 }
1811 if (libhandle)
1812#endif
1813 {
1814 LINK_cam_frame(data);
1815 }
1816
Mohan Kandrad9efed92010-01-15 19:08:39 -08001817 mPreviewHeap.clear();
Mohan Kandraf1ebf982010-02-02 15:25:43 -08001818 if(( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250))
Sravankb4f5f1c2010-01-21 11:06:17 +05301819 mRecordHeap.clear();
1820
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001821#if DLOPEN_LIBMMCAMERA
1822 if (libhandle) {
1823 ::dlclose(libhandle);
1824 LOGV("FRAME: dlclose(libqcamera)");
1825 }
1826#endif
1827
1828 mFrameThreadWaitLock.lock();
1829 mFrameThreadRunning = false;
1830 mFrameThreadWait.signal();
1831 mFrameThreadWaitLock.unlock();
1832
1833 LOGV("runFrameThread X");
1834}
1835
Sravankb4f5f1c2010-01-21 11:06:17 +05301836void QualcommCameraHardware::runVideoThread(void *data)
1837{
1838 LOGD("runVideoThread E");
1839 msm_frame* vframe = NULL;
1840
1841 while(true) {
1842 pthread_mutex_lock(&(g_busy_frame_queue.mut));
1843
Kiran Kumar H Nb49af212010-02-17 15:12:17 -08001844 LOGV("in video_thread : wait for video frame ");
Sravankb4f5f1c2010-01-21 11:06:17 +05301845 // check if any frames are available in busyQ and give callback to
1846 // services/video encoder
1847 cam_frame_wait_video();
1848 LOGV("video_thread, wait over..");
1849
1850 // Exit the thread , in case of stop recording..
1851 mVideoThreadWaitLock.lock();
1852 if(mVideoThreadExit){
Kiran Kumar H Nb49af212010-02-17 15:12:17 -08001853 LOGV("Exiting video thread..");
Sravankb4f5f1c2010-01-21 11:06:17 +05301854 mVideoThreadWaitLock.unlock();
1855 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
1856 break;
1857 }
1858 mVideoThreadWaitLock.unlock();
1859
1860 // Get the video frame to be encoded
1861 vframe = cam_frame_get_video ();
Apurva Rajgurud9b0b302010-02-19 11:22:56 -08001862 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
Sravankb4f5f1c2010-01-21 11:06:17 +05301863 LOGV("in video_thread : got video frame ");
1864
Mohan Kandrabad0eaa2010-02-04 15:11:54 -08001865 if (UNLIKELY(mDebugFps)) {
1866 debugShowVideoFPS();
1867 }
1868
Sravankb4f5f1c2010-01-21 11:06:17 +05301869 if(vframe != NULL) {
1870 // Find the offset within the heap of the current buffer.
1871 LOGV("Got video frame : buffer %d base %d ", vframe->buffer, mRecordHeap->mHeap->base());
1872 ssize_t offset =
1873 (ssize_t)vframe->buffer - (ssize_t)mRecordHeap->mHeap->base();
1874 LOGV("offset = %d , alignsize = %d , offset later = %d", offset, mRecordHeap->mAlignedBufferSize, (offset / mRecordHeap->mAlignedBufferSize));
1875
1876 offset /= mRecordHeap->mAlignedBufferSize;
1877
1878 // dump frames for test purpose
1879#ifdef DUMP_VIDEO_FRAMES
1880 static int frameCnt = 0;
1881 if (frameCnt >= 11 && frameCnt <= 13 ) {
1882 char buf[128];
1883 sprintf(buf, "/data/%d_v.yuv", frameCnt);
1884 int file_fd = open(buf, O_RDWR | O_CREAT, 0777);
1885 LOGV("dumping video frame %d", frameCnt);
1886 if (file_fd < 0) {
1887 LOGE("cannot open file\n");
1888 }
1889 else
1890 {
1891 write(file_fd, (const void *)vframe->buffer,
1892 vframe->cbcr_off * 3 / 2);
1893 }
1894 close(file_fd);
1895 }
1896 frameCnt++;
1897#endif
1898 // Enable IF block to give frames to encoder , ELSE block for just simulation
1899#if 1
1900 LOGV("in video_thread : got video frame, before if check giving frame to services/encoder");
1901 mCallbackLock.lock();
1902 int msgEnabled = mMsgEnabled;
1903 data_callback_timestamp rcb = mDataCallbackTimestamp;
1904 void *rdata = mCallbackCookie;
1905 mCallbackLock.unlock();
1906
1907 if(rcb != NULL && (msgEnabled & CAMERA_MSG_VIDEO_FRAME) ) {
1908 LOGV("in video_thread : got video frame, giving frame to services/encoder");
1909 rcb(systemTime(), CAMERA_MSG_VIDEO_FRAME, mRecordHeap->mBuffers[offset], rdata);
1910 Mutex::Autolock rLock(&mRecordFrameLock);
1911 if (mReleasedRecordingFrame != true) {
1912 LOGV("block waiting for frame release");
1913 mRecordWait.wait(mRecordFrameLock);
1914 LOGV("video frame released, continuing");
1915 }
1916 mReleasedRecordingFrame = false;
1917 }
1918#else
1919 // 720p output2 : simulate release frame here:
1920 LOGE("in video_thread simulation , releasing the video frame");
1921 LINK_camframe_free_video(vframe);
1922#endif
1923
1924 } else LOGE("in video_thread get frame returned null");
1925
Sravankb4f5f1c2010-01-21 11:06:17 +05301926
1927 } // end of while loop
Mohan Kandra156d0ac2010-01-25 16:59:17 -08001928
1929 mVideoThreadWaitLock.lock();
1930 mVideoThreadRunning = false;
1931 mVideoThreadWait.signal();
1932 mVideoThreadWaitLock.unlock();
1933
Sravankb4f5f1c2010-01-21 11:06:17 +05301934 LOGV("runVideoThread X");
1935}
1936
1937void *video_thread(void *user)
1938{
1939 LOGV("video_thread E");
1940 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
1941 if (obj != 0) {
1942 obj->runVideoThread(user);
1943 }
1944 else LOGE("not starting video thread: the object went away!");
1945 LOGV("video_thread X");
1946 return NULL;
1947}
1948
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001949void *frame_thread(void *user)
1950{
1951 LOGD("frame_thread E");
1952 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
1953 if (obj != 0) {
1954 obj->runFrameThread(user);
1955 }
1956 else LOGW("not starting frame thread: the object went away!");
1957 LOGD("frame_thread X");
1958 return NULL;
1959}
1960
1961bool QualcommCameraHardware::initPreview()
1962{
1963 // See comments in deinitPreview() for why we have to wait for the frame
1964 // thread here, and why we can't use pthread_join().
Sravankb4f5f1c2010-01-21 11:06:17 +05301965 int videoWidth, videoHeight;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001966 mParameters.getPreviewSize(&previewWidth, &previewHeight);
Sravankb4f5f1c2010-01-21 11:06:17 +05301967
1968 videoWidth = previewWidth; // temporary , should be configurable later
1969 videoHeight = previewHeight;
1970 LOGV("initPreview E: preview size=%dx%d videosize = %d x %d", previewWidth, previewHeight, videoWidth, videoHeight );
1971
Mohan Kandraf1ebf982010-02-02 15:25:43 -08001972 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05301973 mDimension.video_width = videoWidth;
Kiran Kumar H N7ac84e32010-02-01 10:58:47 -08001974 mDimension.video_width = CEILING16(mDimension.video_width);
Sravankb4f5f1c2010-01-21 11:06:17 +05301975 mDimension.video_height = videoHeight;
1976 LOGV("initPreview : preview size=%dx%d videosize = %d x %d", previewWidth, previewHeight, mDimension.video_width, mDimension.video_height );
1977 }
1978
1979
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001980 mFrameThreadWaitLock.lock();
1981 while (mFrameThreadRunning) {
1982 LOGV("initPreview: waiting for old frame thread to complete.");
1983 mFrameThreadWait.wait(mFrameThreadWaitLock);
1984 LOGV("initPreview: old frame thread completed.");
1985 }
1986 mFrameThreadWaitLock.unlock();
1987
1988 mSnapshotThreadWaitLock.lock();
1989 while (mSnapshotThreadRunning) {
1990 LOGV("initPreview: waiting for old snapshot thread to complete.");
1991 mSnapshotThreadWait.wait(mSnapshotThreadWaitLock);
1992 LOGV("initPreview: old snapshot thread completed.");
1993 }
1994 mSnapshotThreadWaitLock.unlock();
1995
1996 int cnt = 0;
1997 mPreviewFrameSize = previewWidth * previewHeight * 3/2;
Mohan Kandrad9efed92010-01-15 19:08:39 -08001998 dstOffset = 0;
1999 mPreviewHeap = new PmemPool("/dev/pmem_adsp",
Mohan Kandra284966d2010-01-05 13:39:15 -08002000 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
2001 mCameraControlFd,
Sravankb4f5f1c2010-01-21 11:06:17 +05302002 MSM_PMEM_PREVIEW, //MSM_PMEM_OUTPUT2,
Mohan Kandra284966d2010-01-05 13:39:15 -08002003 mPreviewFrameSize,
Mohan Kandrad9efed92010-01-15 19:08:39 -08002004 kPreviewBufferCountActual,
Mohan Kandra284966d2010-01-05 13:39:15 -08002005 mPreviewFrameSize,
Mohan Kandrad9efed92010-01-15 19:08:39 -08002006 "preview");
Mohan Kandra284966d2010-01-05 13:39:15 -08002007
Mohan Kandrad9efed92010-01-15 19:08:39 -08002008 if (!mPreviewHeap->initialized()) {
2009 mPreviewHeap.clear();
Mohan Kandra284966d2010-01-05 13:39:15 -08002010 LOGE("initPreview X: could not initialize Camera preview heap.");
2011 return false;
2012 }
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002013 if( mCurrentTarget == TARGET_MSM7630 ) {
Srinivasan Kannan613301c2010-02-10 17:08:53 -08002014 mPostViewHeap.clear();
Kiran Kumar H N595970b2010-01-12 10:41:09 -08002015 if(mPostViewHeap == NULL) {
2016 LOGV(" Allocating Postview heap ");
2017 /* mPostViewHeap should be declared only for 7630 target */
2018 mPostViewHeap =
2019 new PmemPool("/dev/pmem_adsp",
2020 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
2021 mCameraControlFd,
Sravankb4f5f1c2010-01-21 11:06:17 +05302022 MSM_PMEM_PREVIEW, //MSM_PMEM_OUTPUT2,
Kiran Kumar H N595970b2010-01-12 10:41:09 -08002023 mPreviewFrameSize,
2024 1,
2025 mPreviewFrameSize,
2026 "postview");
Mohan Kandra284966d2010-01-05 13:39:15 -08002027
Kiran Kumar H N595970b2010-01-12 10:41:09 -08002028 if (!mPostViewHeap->initialized()) {
2029 mPostViewHeap.clear();
2030 LOGE(" Failed to initialize Postview Heap");
2031 return false;
2032 }
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002033 }
Mohan Kandraf1ebf982010-02-02 15:25:43 -08002034 }
2035
2036 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250) ) {
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002037
2038 // Allocate video buffers after allocating preview buffers.
Sravankb4f5f1c2010-01-21 11:06:17 +05302039 initRecord();
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002040 }
Sravankb4f5f1c2010-01-21 11:06:17 +05302041
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002042 // mDimension will be filled with thumbnail_width, thumbnail_height,
2043 // orig_picture_dx, and orig_picture_dy after this function call. We need to
2044 // keep it for jpeg_encoder_encode.
2045 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
2046 sizeof(cam_ctrl_dimension_t), &mDimension);
2047
2048 if (ret) {
2049 for (cnt = 0; cnt < kPreviewBufferCount; cnt++) {
Mohan Kandrad9efed92010-01-15 19:08:39 -08002050 frames[cnt].fd = mPreviewHeap->mHeap->getHeapID();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002051 frames[cnt].buffer =
Mohan Kandrad9efed92010-01-15 19:08:39 -08002052 (uint32_t)mPreviewHeap->mHeap->base() + mPreviewHeap->mAlignedBufferSize * cnt;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002053 frames[cnt].y_off = 0;
2054 frames[cnt].cbcr_off = previewWidth * previewHeight;
Sravankb4f5f1c2010-01-21 11:06:17 +05302055 frames[cnt].path = OUTPUT_TYPE_P; // MSM_FRAME_ENC;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002056 }
2057
2058 mFrameThreadWaitLock.lock();
2059 pthread_attr_t attr;
2060 pthread_attr_init(&attr);
2061 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
Sravankb4f5f1c2010-01-21 11:06:17 +05302062
2063 frame_parms.frame = frames[kPreviewBufferCount - 1];
2064 frame_parms.video_frame = recordframes[kPreviewBufferCount - 1];
2065
2066 LOGV ("initpreview before cam_frame thread carete , video frame buffer=%lu fd=%d y_off=%d cbcr_off=%d \n",
2067 (unsigned long)frame_parms.video_frame.buffer, frame_parms.video_frame.fd, frame_parms.video_frame.y_off,
2068 frame_parms.video_frame.cbcr_off);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002069 mFrameThreadRunning = !pthread_create(&mFrameThread,
2070 &attr,
2071 frame_thread,
Sravankb4f5f1c2010-01-21 11:06:17 +05302072 (void*)&(frame_parms));
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002073 ret = mFrameThreadRunning;
2074 mFrameThreadWaitLock.unlock();
2075 }
2076
2077 LOGV("initPreview X: %d", ret);
2078 return ret;
2079}
2080
2081void QualcommCameraHardware::deinitPreview(void)
2082{
2083 LOGI("deinitPreview E");
2084
2085 // When we call deinitPreview(), we signal to the frame thread that it
2086 // needs to exit, but we DO NOT WAIT for it to complete here. The problem
2087 // is that deinitPreview is sometimes called from the frame-thread's
2088 // callback, when the refcount on the Camera client reaches zero. If we
2089 // called pthread_join(), we would deadlock. So, we just call
2090 // LINK_camframe_terminate() in deinitPreview(), which makes sure that
2091 // after the preview callback returns, the camframe thread will exit. We
2092 // could call pthread_join() in initPreview() to join the last frame
2093 // thread. However, we would also have to call pthread_join() in release
2094 // as well, shortly before we destroy the object; this would cause the same
2095 // deadlock, since release(), like deinitPreview(), may also be called from
2096 // the frame-thread's callback. This we have to make the frame thread
2097 // detached, and use a separate mechanism to wait for it to complete.
2098
Kiran Kumar H N7ac84e32010-02-01 10:58:47 -08002099 LINK_camframe_terminate();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002100 LOGI("deinitPreview X");
2101}
2102
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002103bool QualcommCameraHardware::initRawSnapshot()
2104{
2105 LOGV("initRawSnapshot E");
2106
2107 //get width and height from Dimension Object
2108 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
2109 sizeof(cam_ctrl_dimension_t), &mDimension);
2110
2111 if(!ret){
2112 LOGE("initRawSnapshot X: failed to set dimension");
2113 return false;
2114 }
2115 int rawSnapshotSize = mDimension.raw_picture_height *
2116 mDimension.raw_picture_width;
2117
2118 LOGV("raw_snapshot_buffer_size = %d, raw_picture_height = %d, "\
2119 "raw_picture_width = %d",
2120 rawSnapshotSize, mDimension.raw_picture_height,
2121 mDimension.raw_picture_width);
2122
2123 if (mRawSnapShotPmemHeap != NULL) {
2124 LOGV("initRawSnapshot: clearing old mRawSnapShotPmemHeap.");
2125 mRawSnapShotPmemHeap.clear();
2126 }
2127
2128 //Pmem based pool for Camera Driver
2129 mRawSnapShotPmemHeap = new PmemPool("/dev/pmem_adsp",
2130 MemoryHeapBase::READ_ONLY,
2131 mCameraControlFd,
2132 MSM_PMEM_RAW_MAINIMG,
2133 rawSnapshotSize,
2134 1,
2135 rawSnapshotSize,
2136 "raw pmem snapshot camera");
2137
2138 if (!mRawSnapShotPmemHeap->initialized()) {
2139 mRawSnapShotPmemHeap.clear();
2140 LOGE("initRawSnapshot X: error initializing mRawSnapshotHeap");
2141 return false;
2142 }
2143 LOGV("initRawSnapshot X");
2144 return true;
2145
2146}
2147
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002148bool QualcommCameraHardware::initRaw(bool initJpegHeap)
2149{
2150 int rawWidth, rawHeight;
Apurva Rajguru8d1773b2009-12-02 14:21:23 -08002151
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002152 mParameters.getPictureSize(&rawWidth, &rawHeight);
2153 LOGV("initRaw E: picture size=%dx%d", rawWidth, rawHeight);
2154
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08002155 int thumbnailBufferSize;
2156 //Thumbnail height should be smaller than Picture height
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002157 if (rawHeight > (int)thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height){
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08002158 mDimension.ui_thumbnail_width =
2159 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].width;
2160 mDimension.ui_thumbnail_height =
2161 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height;
2162 uint32_t pictureAspectRatio = (uint32_t)((rawWidth * Q12) / rawHeight);
2163 uint32_t i;
2164 for(i = 0; i < THUMBNAIL_SIZE_COUNT; i++ )
2165 {
2166 if(thumbnail_sizes[i].aspect_ratio == pictureAspectRatio)
2167 {
2168 mDimension.ui_thumbnail_width = thumbnail_sizes[i].width;
2169 mDimension.ui_thumbnail_height = thumbnail_sizes[i].height;
2170 break;
2171 }
2172 }
2173 }
2174 else{
2175 mDimension.ui_thumbnail_height = THUMBNAIL_SMALL_HEIGHT;
2176 mDimension.ui_thumbnail_width =
2177 (THUMBNAIL_SMALL_HEIGHT * rawWidth)/ rawHeight;
2178 }
2179
2180 LOGV("Thumbnail Size Width %d Height %d",
2181 mDimension.ui_thumbnail_width,
2182 mDimension.ui_thumbnail_height);
2183
2184 thumbnailBufferSize = mDimension.ui_thumbnail_width *
2185 mDimension.ui_thumbnail_height * 3 / 2;
2186
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002187 // mDimension will be filled with thumbnail_width, thumbnail_height,
2188 // orig_picture_dx, and orig_picture_dy after this function call. We need to
2189 // keep it for jpeg_encoder_encode.
2190 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
2191 sizeof(cam_ctrl_dimension_t), &mDimension);
2192 if(!ret) {
2193 LOGE("initRaw X: failed to set dimension");
2194 return false;
2195 }
2196
2197 if (mJpegHeap != NULL) {
2198 LOGV("initRaw: clearing old mJpegHeap.");
2199 mJpegHeap.clear();
2200 }
2201
2202 // Snapshot
2203 mRawSize = rawWidth * rawHeight * 3 / 2;
Apurva Rajguru8d1773b2009-12-02 14:21:23 -08002204
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002205 if( mCurrentTarget == TARGET_MSM7627 )
Apurva Rajguru8d1773b2009-12-02 14:21:23 -08002206 mJpegMaxSize = CEILING16(rawWidth) * CEILING16(rawHeight) * 3 / 2;
2207 else
2208 mJpegMaxSize = rawWidth * rawHeight * 3 / 2;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002209
2210 LOGV("initRaw: initializing mRawHeap.");
2211 mRawHeap =
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002212 new PmemPool("/dev/pmem_adsp",
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002213 MemoryHeapBase::READ_ONLY,
2214 mCameraControlFd,
2215 MSM_PMEM_MAINIMG,
2216 mJpegMaxSize,
2217 kRawBufferCount,
2218 mRawSize,
2219 "snapshot camera");
2220
2221 if (!mRawHeap->initialized()) {
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002222 LOGE("initRaw X failed ");
2223 mRawHeap.clear();
2224 LOGE("initRaw X: error initializing mRawHeap");
2225 return false;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002226 }
2227
2228 LOGV("do_mmap snapshot pbuf = %p, pmem_fd = %d",
2229 (uint8_t *)mRawHeap->mHeap->base(), mRawHeap->mHeap->getHeapID());
2230
2231 // Jpeg
2232
2233 if (initJpegHeap) {
2234 LOGV("initRaw: initializing mJpegHeap.");
2235 mJpegHeap =
2236 new AshmemPool(mJpegMaxSize,
2237 kJpegBufferCount,
2238 0, // we do not know how big the picture will be
2239 "jpeg");
2240
2241 if (!mJpegHeap->initialized()) {
2242 mJpegHeap.clear();
2243 mRawHeap.clear();
2244 LOGE("initRaw X failed: error initializing mJpegHeap.");
2245 return false;
2246 }
2247
2248 // Thumbnails
2249
2250 mThumbnailHeap =
2251 new PmemPool("/dev/pmem_adsp",
2252 MemoryHeapBase::READ_ONLY,
2253 mCameraControlFd,
2254 MSM_PMEM_THUMBNAIL,
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08002255 thumbnailBufferSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002256 1,
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08002257 thumbnailBufferSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002258 "thumbnail");
2259
2260 if (!mThumbnailHeap->initialized()) {
2261 mThumbnailHeap.clear();
2262 mJpegHeap.clear();
2263 mRawHeap.clear();
2264 LOGE("initRaw X failed: error initializing mThumbnailHeap.");
2265 return false;
2266 }
2267 }
2268
2269 LOGV("initRaw X");
2270 return true;
2271}
2272
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002273
2274void QualcommCameraHardware::deinitRawSnapshot()
2275{
2276 LOGV("deinitRawSnapshot E");
2277 mRawSnapShotPmemHeap.clear();
2278 mRawSnapshotAshmemHeap.clear();
2279 LOGV("deinitRawSnapshot X");
2280}
2281
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002282void QualcommCameraHardware::deinitRaw()
2283{
2284 LOGV("deinitRaw E");
2285
2286 mThumbnailHeap.clear();
2287 mJpegHeap.clear();
2288 mRawHeap.clear();
2289 mDisplayHeap.clear();
2290
2291 LOGV("deinitRaw X");
2292}
2293
2294void QualcommCameraHardware::release()
2295{
2296 LOGD("release E");
2297 Mutex::Autolock l(&mLock);
2298
2299#if DLOPEN_LIBMMCAMERA
2300 if (libmmcamera == NULL) {
2301 LOGE("ERROR: multiple release!");
2302 return;
2303 }
2304#else
2305#warning "Cannot detect multiple release when not dlopen()ing libqcamera!"
2306#endif
2307
2308 int cnt, rc;
2309 struct msm_ctrl_cmd ctrlCmd;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002310 if (mCameraRunning) {
2311 if(mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME)) {
2312 mRecordFrameLock.lock();
2313 mReleasedRecordingFrame = true;
2314 mRecordWait.signal();
2315 mRecordFrameLock.unlock();
2316 }
2317 stopPreviewInternal();
2318 }
2319
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002320 if( mCurrentTarget == TARGET_MSM7630 ) {
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002321 mPostViewHeap.clear();
2322 mPostViewHeap = NULL;
2323 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002324 LINK_jpeg_encoder_join();
2325 deinitRaw();
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002326 deinitRawSnapshot();
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002327 {
2328 Mutex::Autolock l(&mCamframeTimeoutLock);
2329 if(!camframe_timeout_flag) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002330
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002331 ctrlCmd.timeout_ms = 5000;
2332 ctrlCmd.length = 0;
2333 ctrlCmd.type = (uint16_t)CAMERA_EXIT;
2334 ctrlCmd.resp_fd = mCameraControlFd; // FIXME: this will be put in by the kernel
2335 if (ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0)
2336 LOGE("ioctl CAMERA_EXIT fd %d error %s",
2337 mCameraControlFd, strerror(errno));
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002338
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002339 }
2340 }
Kiran Kumar H N7ac84e32010-02-01 10:58:47 -08002341 LINK_release_cam_conf_thread();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002342 close(mCameraControlFd);
2343 mCameraControlFd = -1;
Mohan Kandra284966d2010-01-05 13:39:15 -08002344 if(fb_fd >= 0) {
2345 close(fb_fd);
2346 fb_fd = -1;
2347 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002348#if DLOPEN_LIBMMCAMERA
2349 if (libmmcamera) {
2350 ::dlclose(libmmcamera);
2351 LOGV("dlclose(libqcamera)");
2352 libmmcamera = NULL;
2353 }
2354#endif
2355
2356 Mutex::Autolock lock(&singleton_lock);
2357 singleton_releasing = true;
2358
2359 LOGD("release X");
2360}
2361
2362QualcommCameraHardware::~QualcommCameraHardware()
2363{
2364 LOGD("~QualcommCameraHardware E");
2365 Mutex::Autolock lock(&singleton_lock);
2366 singleton.clear();
2367 singleton_releasing = false;
2368 singleton_wait.signal();
2369 LOGD("~QualcommCameraHardware X");
2370}
2371
2372sp<IMemoryHeap> QualcommCameraHardware::getRawHeap() const
2373{
2374 LOGV("getRawHeap");
2375 return mDisplayHeap != NULL ? mDisplayHeap->mHeap : NULL;
2376}
2377
2378sp<IMemoryHeap> QualcommCameraHardware::getPreviewHeap() const
2379{
2380 LOGV("getPreviewHeap");
Mohan Kandrad9efed92010-01-15 19:08:39 -08002381 return mPreviewHeap != NULL ? mPreviewHeap->mHeap : NULL;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002382}
2383
2384status_t QualcommCameraHardware::startPreviewInternal()
2385{
Sravankb4f5f1c2010-01-21 11:06:17 +05302386 LOGV("in startPreviewInternal : E");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002387 if(mCameraRunning) {
2388 LOGV("startPreview X: preview already running.");
2389 return NO_ERROR;
2390 }
2391
2392 if (!mPreviewInitialized) {
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002393 mLastQueuedFrame = NULL;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002394 mPreviewInitialized = initPreview();
2395 if (!mPreviewInitialized) {
2396 LOGE("startPreview X initPreview failed. Not starting preview.");
2397 return UNKNOWN_ERROR;
2398 }
2399 }
2400
Mohan Kandraf1ebf982010-02-02 15:25:43 -08002401 if(( mCurrentTarget != TARGET_MSM7630 ) && (mCurrentTarget != TARGET_QSD8250))
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002402 mCameraRunning = native_start_preview(mCameraControlFd);
Sravankb4f5f1c2010-01-21 11:06:17 +05302403 else
2404 mCameraRunning = native_start_video(mCameraControlFd);
2405
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002406 if(!mCameraRunning) {
2407 deinitPreview();
2408 mPreviewInitialized = false;
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08002409 mOverlay = NULL;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002410 LOGE("startPreview X: native_start_preview failed!");
2411 return UNKNOWN_ERROR;
2412 }
2413
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08002414 //Reset the Gps Information
2415 exif_table_numEntries = 0;
Mohan Kandra284966d2010-01-05 13:39:15 -08002416
2417 if(native_get_maxzoom(mCameraControlFd, (void *)&mMaxZoom) == true){
Brian Steuerb62adbd2010-02-02 14:47:08 -08002418 LOGD("Maximum zoom value is %d", mMaxZoom);
Mohan Kandra284966d2010-01-05 13:39:15 -08002419 mParameters.set("zoom-supported", "true");
2420 } else {
2421 LOGE("Failed to get maximum zoom value...setting max zoom to zero");
2422 mParameters.set("zoom-supported", "false");
2423 mMaxZoom = 0;
2424 }
2425 mParameters.set("max-zoom",mMaxZoom);
2426
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08002427 //Initialize AF state to AF_NOTSTARTED
2428 mAfLock.lock();
2429 mAfState = AF_NOTSTARTED;
2430 mAfLock.unlock();
2431
Sravankb4f5f1c2010-01-21 11:06:17 +05302432 LOGV("startPreviewInternal X");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002433 return NO_ERROR;
2434}
2435
2436status_t QualcommCameraHardware::startPreview()
2437{
2438 LOGV("startPreview E");
2439 Mutex::Autolock l(&mLock);
2440 return startPreviewInternal();
2441}
2442
2443void QualcommCameraHardware::stopPreviewInternal()
2444{
2445 LOGV("stopPreviewInternal E: %d", mCameraRunning);
2446 if (mCameraRunning) {
2447 // Cancel auto focus.
2448 {
2449 if (mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS)) {
2450 cancelAutoFocusInternal();
2451 }
2452 }
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002453
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002454 Mutex::Autolock l(&mCamframeTimeoutLock);
2455 if(!camframe_timeout_flag) {
Mohan Kandraf1ebf982010-02-02 15:25:43 -08002456 if (( mCurrentTarget != TARGET_MSM7630 ) && (mCurrentTarget != TARGET_QSD8250))
Sravankb4f5f1c2010-01-21 11:06:17 +05302457 mCameraRunning = !native_stop_preview(mCameraControlFd);
2458 else
2459 mCameraRunning = !native_stop_video(mCameraControlFd);
2460
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002461 } else {
2462 /* This means that the camframetimeout was issued.
2463 * But we did not issue native_stop_preview(), so we
Kiran Kumar H Nac2f4952009-12-17 01:16:53 -08002464 * need to update mCameraRunning to indicate that
2465 * Camera is no longer running. */
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002466 mCameraRunning = 0;
Kiran Kumar H Nac2f4952009-12-17 01:16:53 -08002467 }
2468 if (!mCameraRunning && mPreviewInitialized) {
2469 deinitPreview();
Mohan Kandraf1ebf982010-02-02 15:25:43 -08002470 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250)) {
Mohan Kandra156d0ac2010-01-25 16:59:17 -08002471 mVideoThreadWaitLock.lock();
2472 LOGV("in stopPreviewInternal: making mVideoThreadExit 1");
2473 mVideoThreadExit = 1;
2474 mVideoThreadWaitLock.unlock();
2475 // 720p : signal the video thread , and check in video thread if stop is called, if so exit video thread.
2476 pthread_mutex_lock(&(g_busy_frame_queue.mut));
2477 pthread_cond_signal(&(g_busy_frame_queue.wait));
2478 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
2479 }
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002480 mPreviewInitialized = false;
2481 }
Kiran Kumar H Nac2f4952009-12-17 01:16:53 -08002482 else LOGE("stopPreviewInternal: failed to stop preview");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002483 }
2484 LOGV("stopPreviewInternal X: %d", mCameraRunning);
2485}
2486
2487void QualcommCameraHardware::stopPreview()
2488{
2489 LOGV("stopPreview: E");
2490 Mutex::Autolock l(&mLock);
2491 {
2492 if (mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME))
2493 return;
2494 }
2495 stopPreviewInternal();
2496 LOGV("stopPreview: X");
2497}
2498
2499void QualcommCameraHardware::runAutoFocus()
2500{
2501 bool status = true;
2502 void *libhandle = NULL;
Srinivasan Kannan71229622009-12-04 12:05:58 -08002503 isp3a_af_mode_t afMode;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002504
2505 mAutoFocusThreadLock.lock();
2506 // Skip autofocus if focus mode is infinity.
2507 if (strcmp(mParameters.get(CameraParameters::KEY_FOCUS_MODE),
2508 CameraParameters::FOCUS_MODE_INFINITY) == 0) {
2509 goto done;
2510 }
2511
2512 mAutoFocusFd = open(MSM_CAMERA_CONTROL, O_RDWR);
2513 if (mAutoFocusFd < 0) {
2514 LOGE("autofocus: cannot open %s: %s",
2515 MSM_CAMERA_CONTROL,
2516 strerror(errno));
2517 mAutoFocusThreadRunning = false;
2518 mAutoFocusThreadLock.unlock();
2519 return;
2520 }
2521
2522#if DLOPEN_LIBMMCAMERA
2523 // We need to maintain a reference to libqcamera.so for the duration of the
2524 // AF thread, because we do not know when it will exit relative to the
2525 // lifetime of this object. We do not want to dlclose() libqcamera while
2526 // LINK_cam_frame is still running.
2527 libhandle = ::dlopen("liboemcamera.so", RTLD_NOW);
2528 LOGV("AF: loading libqcamera at %p", libhandle);
2529 if (!libhandle) {
2530 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
2531 close(mAutoFocusFd);
2532 mAutoFocusFd = -1;
2533 mAutoFocusThreadRunning = false;
2534 mAutoFocusThreadLock.unlock();
2535 return;
2536 }
2537#endif
2538
Srinivasan Kannan71229622009-12-04 12:05:58 -08002539 afMode = (isp3a_af_mode_t)attr_lookup(focus_modes,
2540 sizeof(focus_modes) / sizeof(str_map),
2541 mParameters.get(CameraParameters::KEY_FOCUS_MODE));
2542
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002543 /* This will block until either AF completes or is cancelled. */
Srinivasan Kannan71229622009-12-04 12:05:58 -08002544 LOGV("af start (fd %d mode %d)", mAutoFocusFd, afMode);
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08002545 status_t err;
2546 err = mAfLock.tryLock();
2547 if(err == NO_ERROR) {
2548 //Got Lock, so start AF if required.
2549 if(mAfState != AF_CANCELLED) {
2550 mAfState = AF_STARTED;
2551 LOGV("Start AF");
2552 status = native_set_afmode(mAutoFocusFd, afMode);
2553 } else {
2554 status = FALSE;
2555 }
2556 mAfLock.unlock();
2557 }
2558 else{
2559 //AF Cancel would have acquired the lock,
2560 //so, no need to perform any AF
2561 LOGV("Failed to obtain Lock...is busy");
2562 status = FALSE;
2563 }
2564
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002565 LOGV("af done: %d", (int)status);
2566 close(mAutoFocusFd);
2567 mAutoFocusFd = -1;
2568
2569done:
2570 mAutoFocusThreadRunning = false;
2571 mAutoFocusThreadLock.unlock();
2572
2573 mCallbackLock.lock();
2574 bool autoFocusEnabled = mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS);
2575 notify_callback cb = mNotifyCallback;
2576 void *data = mCallbackCookie;
2577 mCallbackLock.unlock();
2578 if (autoFocusEnabled)
2579 cb(CAMERA_MSG_FOCUS, status, 0, data);
2580
2581#if DLOPEN_LIBMMCAMERA
2582 if (libhandle) {
2583 ::dlclose(libhandle);
2584 LOGV("AF: dlclose(libqcamera)");
2585 }
2586#endif
2587}
2588
2589status_t QualcommCameraHardware::cancelAutoFocusInternal()
2590{
2591 LOGV("cancelAutoFocusInternal E");
2592
Srinivasan Kannan71229622009-12-04 12:05:58 -08002593 if(!sensorType->hasAutoFocusSupport){
2594 LOGV("cancelAutoFocusInternal X");
2595 return NO_ERROR;
2596 }
2597
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002598#if 0
2599 if (mAutoFocusFd < 0) {
2600 LOGV("cancelAutoFocusInternal X: not in progress");
2601 return NO_ERROR;
2602 }
2603#endif
2604
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08002605 status_t rc = NO_ERROR;
2606 status_t err;
2607 err = mAfLock.tryLock();
2608 if(err == NO_ERROR) {
2609 //Got Lock, means either AF hasn't started or
2610 // AF is done. So no need to cancel it, just change the state
2611 LOGV("Change AF State to Cancelled");
2612 mAfState = AF_CANCELLED;
2613 mAfLock.unlock();
2614 }
2615 else {
2616 //AF is in Progess, So cancel it
2617 LOGV("Lock busy...cancel AF");
2618 rc = native_cancel_afmode(mCameraControlFd, mAutoFocusFd) ?
2619 NO_ERROR :
2620 UNKNOWN_ERROR;
2621 }
2622
2623
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002624
2625 LOGV("cancelAutoFocusInternal X: %d", rc);
2626 return rc;
2627}
2628
2629void *auto_focus_thread(void *user)
2630{
2631 LOGV("auto_focus_thread E");
2632 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
2633 if (obj != 0) {
2634 obj->runAutoFocus();
2635 }
2636 else LOGW("not starting autofocus: the object went away!");
2637 LOGV("auto_focus_thread X");
2638 return NULL;
2639}
2640
2641status_t QualcommCameraHardware::autoFocus()
2642{
2643 LOGV("autoFocus E");
2644 Mutex::Autolock l(&mLock);
2645
Srinivasan Kannan71229622009-12-04 12:05:58 -08002646 if(!sensorType->hasAutoFocusSupport){
Srinivasan Kannandf085222009-12-09 18:31:00 -08002647 bool status = false;
2648 mCallbackLock.lock();
2649 bool autoFocusEnabled = mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS);
2650 notify_callback cb = mNotifyCallback;
2651 void *data = mCallbackCookie;
2652 mCallbackLock.unlock();
2653 if (autoFocusEnabled)
2654 cb(CAMERA_MSG_FOCUS, status, 0, data);
Srinivasan Kannan71229622009-12-04 12:05:58 -08002655 LOGV("autoFocus X");
2656 return NO_ERROR;
2657 }
2658
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002659 if (mCameraControlFd < 0) {
2660 LOGE("not starting autofocus: main control fd %d", mCameraControlFd);
2661 return UNKNOWN_ERROR;
2662 }
2663
2664 {
2665 mAutoFocusThreadLock.lock();
2666 if (!mAutoFocusThreadRunning) {
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08002667 if (native_prepare_snapshot(mCameraControlFd) == FALSE) {
2668 LOGE("native_prepare_snapshot failed!\n");
2669 mAutoFocusThreadLock.unlock();
2670 return UNKNOWN_ERROR;
2671 }
2672
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002673 // Create a detached thread here so that we don't have to wait
2674 // for it when we cancel AF.
2675 pthread_t thr;
2676 pthread_attr_t attr;
2677 pthread_attr_init(&attr);
2678 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2679 mAutoFocusThreadRunning =
2680 !pthread_create(&thr, &attr,
2681 auto_focus_thread, NULL);
2682 if (!mAutoFocusThreadRunning) {
2683 LOGE("failed to start autofocus thread");
2684 mAutoFocusThreadLock.unlock();
2685 return UNKNOWN_ERROR;
2686 }
2687 }
2688 mAutoFocusThreadLock.unlock();
2689 }
2690
2691 LOGV("autoFocus X");
2692 return NO_ERROR;
2693}
2694
2695status_t QualcommCameraHardware::cancelAutoFocus()
2696{
2697 LOGV("cancelAutoFocus E");
2698 Mutex::Autolock l(&mLock);
2699
2700 int rc = NO_ERROR;
2701 if (mCameraRunning && mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS)) {
2702 rc = cancelAutoFocusInternal();
2703 }
2704
2705 LOGV("cancelAutoFocus X");
2706 return rc;
2707}
2708
2709void QualcommCameraHardware::runSnapshotThread(void *data)
2710{
2711 LOGV("runSnapshotThread E");
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002712 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
2713 if (native_start_snapshot(mCameraControlFd))
2714 receiveRawPicture();
2715 else
2716 LOGE("main: native_start_snapshot failed!");
2717 } else if(mSnapshotFormat == PICTURE_FORMAT_RAW){
2718 if(native_start_raw_snapshot(mCameraControlFd)){
2719 receiveRawSnapshot();
2720 } else {
2721 LOGE("main: native_start_raw_snapshot failed!");
2722 }
2723 }
2724
2725 mSnapshotFormat = 0;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002726
2727 mSnapshotThreadWaitLock.lock();
2728 mSnapshotThreadRunning = false;
2729 mSnapshotThreadWait.signal();
2730 mSnapshotThreadWaitLock.unlock();
2731
2732 LOGV("runSnapshotThread X");
2733}
2734
2735void *snapshot_thread(void *user)
2736{
2737 LOGD("snapshot_thread E");
2738 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
2739 if (obj != 0) {
2740 obj->runSnapshotThread(user);
2741 }
2742 else LOGW("not starting snapshot thread: the object went away!");
2743 LOGD("snapshot_thread X");
2744 return NULL;
2745}
2746
2747status_t QualcommCameraHardware::takePicture()
2748{
2749 LOGV("takePicture(%d)", mMsgEnabled);
2750 Mutex::Autolock l(&mLock);
2751
2752 // Wait for old snapshot thread to complete.
2753 mSnapshotThreadWaitLock.lock();
2754 while (mSnapshotThreadRunning) {
2755 LOGV("takePicture: waiting for old snapshot thread to complete.");
2756 mSnapshotThreadWait.wait(mSnapshotThreadWaitLock);
2757 LOGV("takePicture: old snapshot thread completed.");
2758 }
2759
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002760 if( mCurrentTarget == TARGET_MSM7630 ) {
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002761 /* Store the last frame queued for preview. This
2762 * shall be used as postview */
2763 storePreviewFrameForPostview();
2764 }
2765
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002766 //mSnapshotFormat is protected by mSnapshotThreadWaitLock
2767 if(mParameters.getPictureFormat() != 0 &&
2768 !strcmp(mParameters.getPictureFormat(),
2769 CameraParameters::PIXEL_FORMAT_RAW))
2770 mSnapshotFormat = PICTURE_FORMAT_RAW;
2771 else
2772 mSnapshotFormat = PICTURE_FORMAT_JPEG;
2773
2774 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
2775 if(!native_prepare_snapshot(mCameraControlFd)) {
2776 mSnapshotThreadWaitLock.unlock();
2777 return UNKNOWN_ERROR;
2778 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002779 }
2780
2781 stopPreviewInternal();
2782
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002783 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
2784 if (!initRaw(mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE))) {
2785 LOGE("initRaw failed. Not taking picture.");
2786 mSnapshotThreadWaitLock.unlock();
2787 return UNKNOWN_ERROR;
2788 }
2789 } else if(mSnapshotFormat == PICTURE_FORMAT_RAW ){
2790 if(!initRawSnapshot()){
2791 LOGE("initRawSnapshot failed. Not taking picture.");
2792 mSnapshotThreadWaitLock.unlock();
2793 return UNKNOWN_ERROR;
2794 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002795 }
2796
2797 mShutterLock.lock();
2798 mShutterPending = true;
2799 mShutterLock.unlock();
2800
2801 pthread_attr_t attr;
2802 pthread_attr_init(&attr);
2803 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2804 mSnapshotThreadRunning = !pthread_create(&mSnapshotThread,
2805 &attr,
2806 snapshot_thread,
2807 NULL);
2808 mSnapshotThreadWaitLock.unlock();
2809
2810 LOGV("takePicture: X");
2811 return mSnapshotThreadRunning ? NO_ERROR : UNKNOWN_ERROR;
2812}
2813
2814status_t QualcommCameraHardware::cancelPicture()
2815{
2816 status_t rc;
2817 LOGV("cancelPicture: E");
2818 rc = native_stop_snapshot(mCameraControlFd) ? NO_ERROR : UNKNOWN_ERROR;
2819 LOGV("cancelPicture: X: %d", rc);
2820 return rc;
2821}
2822
2823status_t QualcommCameraHardware::setParameters(const CameraParameters& params)
2824{
2825 LOGV("setParameters: E params = %p", &params);
2826
2827 Mutex::Autolock l(&mLock);
2828 status_t rc, final_rc = NO_ERROR;
2829
2830 if ((rc = setPreviewSize(params))) final_rc = rc;
2831 if ((rc = setPictureSize(params))) final_rc = rc;
2832 if ((rc = setJpegQuality(params))) final_rc = rc;
2833 if ((rc = setAntibanding(params))) final_rc = rc;
2834 if ((rc = setEffect(params))) final_rc = rc;
Apurva Rajguru55562b02009-12-03 12:25:35 -08002835 if ((rc = setAutoExposure(params))) final_rc = rc;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002836 if ((rc = setWhiteBalance(params))) final_rc = rc;
2837 if ((rc = setFlash(params))) final_rc = rc;
2838 if ((rc = setGpsLocation(params))) final_rc = rc;
2839 if ((rc = setRotation(params))) final_rc = rc;
2840 if ((rc = setZoom(params))) final_rc = rc;
2841 if ((rc = setFocusMode(params))) final_rc = rc;
2842 if ((rc = setOrientation(params))) final_rc = rc;
Nishant Panditc8c1ee72009-12-03 16:24:02 +05302843 if ((rc = setBrightness(params))) final_rc = rc;
2844 if ((rc = setLensshadeValue(params))) final_rc = rc;
2845 if ((rc = setISOValue(params))) final_rc = rc;
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002846 if ((rc = setPictureFormat(params))) final_rc = rc;
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08002847 if ((rc = setSharpness(params))) final_rc = rc;
2848 if ((rc = setContrast(params))) final_rc = rc;
2849 if ((rc = setSaturation(params))) final_rc = rc;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002850
2851 LOGV("setParameters: X");
2852 return final_rc;
2853}
2854
2855CameraParameters QualcommCameraHardware::getParameters() const
2856{
2857 LOGV("getParameters: EX");
2858 return mParameters;
2859}
2860
2861status_t QualcommCameraHardware::sendCommand(int32_t command, int32_t arg1,
2862 int32_t arg2)
2863{
2864 LOGV("sendCommand: EX");
2865 return BAD_VALUE;
2866}
2867
2868extern "C" sp<CameraHardwareInterface> openCameraHardware()
2869{
2870 LOGV("openCameraHardware: call createInstance");
2871 return QualcommCameraHardware::createInstance();
2872}
2873
2874wp<QualcommCameraHardware> QualcommCameraHardware::singleton;
2875
2876// If the hardware already exists, return a strong pointer to the current
2877// object. If not, create a new hardware object, put it in the singleton,
2878// and return it.
2879sp<CameraHardwareInterface> QualcommCameraHardware::createInstance()
2880{
2881 LOGD("createInstance: E");
2882
2883 Mutex::Autolock lock(&singleton_lock);
2884
2885 // Wait until the previous release is done.
2886 while (singleton_releasing) {
2887 LOGD("Wait for previous release.");
2888 singleton_wait.wait(singleton_lock);
2889 }
2890
2891 if (singleton != 0) {
2892 sp<CameraHardwareInterface> hardware = singleton.promote();
2893 if (hardware != 0) {
2894 LOGD("createInstance: X return existing hardware=%p", &(*hardware));
2895 return hardware;
2896 }
2897 }
2898
2899 {
2900 struct stat st;
2901 int rc = stat("/dev/oncrpc", &st);
2902 if (rc < 0) {
2903 LOGD("createInstance: X failed to create hardware: %s", strerror(errno));
2904 return NULL;
2905 }
2906 }
2907
2908 QualcommCameraHardware *cam = new QualcommCameraHardware();
2909 sp<QualcommCameraHardware> hardware(cam);
2910 singleton = hardware;
2911
2912 if (!cam->startCamera()) {
2913 LOGE("%s: startCamera failed!", __FUNCTION__);
2914 return NULL;
2915 }
2916
2917 cam->initDefaultParameters();
2918 LOGD("createInstance: X created hardware=%p", &(*hardware));
2919 return hardware;
2920}
2921
2922// For internal use only, hence the strong pointer to the derived type.
2923sp<QualcommCameraHardware> QualcommCameraHardware::getInstance()
2924{
2925 sp<CameraHardwareInterface> hardware = singleton.promote();
2926 if (hardware != 0) {
2927 // LOGV("getInstance: X old instance of hardware");
2928 return sp<QualcommCameraHardware>(static_cast<QualcommCameraHardware*>(hardware.get()));
2929 } else {
2930 LOGV("getInstance: X new instance of hardware");
2931 return sp<QualcommCameraHardware>();
2932 }
2933}
Sravankb4f5f1c2010-01-21 11:06:17 +05302934void QualcommCameraHardware::receiveRecordingFrame(struct msm_frame *frame)
2935{
2936 LOGV("receiveRecordingFrame E");
2937 // post busy frame
2938 if (frame)
2939 {
2940 cam_frame_post_video (frame);
2941 }
2942 else LOGE("in receiveRecordingFrame frame is NULL");
2943 LOGV("receiveRecordingFrame X");
2944}
2945
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002946
Mohan Kandrad9efed92010-01-15 19:08:39 -08002947bool QualcommCameraHardware::native_zoom_image(int fd, int srcOffset, int dstOffSet, common_crop_t *crop)
Mohan Kandra284966d2010-01-05 13:39:15 -08002948{
2949 int result = 0;
2950 struct mdp_blit_req *e;
2951 struct timeval td1, td2;
2952
Mohan Kandra284966d2010-01-05 13:39:15 -08002953 /* Initialize yuv structure */
2954 zoomImage.list.count = 1;
2955
2956 e = &zoomImage.list.req[0];
2957
2958 e->src.width = previewWidth;
2959 e->src.height = previewHeight;
2960 e->src.format = MDP_Y_CBCR_H2V2;
Mohan Kandrad9efed92010-01-15 19:08:39 -08002961 e->src.offset = srcOffset;
2962 e->src.memory_id = fd;
Mohan Kandra284966d2010-01-05 13:39:15 -08002963
2964 e->dst.width = previewWidth;
2965 e->dst.height = previewHeight;
2966 e->dst.format = MDP_Y_CBCR_H2V2;
Mohan Kandrad9efed92010-01-15 19:08:39 -08002967 e->dst.offset = dstOffSet;
2968 e->dst.memory_id = fd;
Mohan Kandra284966d2010-01-05 13:39:15 -08002969
2970 e->transp_mask = 0xffffffff;
2971 e->flags = 0;
2972 e->alpha = 0xff;
2973 if (crop->in2_w != 0 || crop->in2_h != 0) {
2974 e->src_rect.x = (crop->out2_w - crop->in2_w + 1) / 2 - 1;
2975 e->src_rect.y = (crop->out2_h - crop->in2_h + 1) / 2 - 1;
2976 e->src_rect.w = crop->in2_w;
2977 e->src_rect.h = crop->in2_h;
2978 } else {
2979 e->src_rect.x = 0;
2980 e->src_rect.y = 0;
2981 e->src_rect.w = previewWidth;
2982 e->src_rect.h = previewHeight;
2983 }
Mohan Kandrad9efed92010-01-15 19:08:39 -08002984 //LOGV(" native_zoom : SRC_RECT : x,y = %d,%d \t w,h = %d, %d",
2985 // e->src_rect.x, e->src_rect.y, e->src_rect.w, e->src_rect.h);
Mohan Kandra284966d2010-01-05 13:39:15 -08002986
2987 e->dst_rect.x = 0;
2988 e->dst_rect.y = 0;
2989 e->dst_rect.w = previewWidth;
2990 e->dst_rect.h = previewHeight;
2991
2992 result = ioctl(fb_fd, MSMFB_BLIT, &zoomImage.list);
2993 if (result < 0) {
2994 LOGE("MSM_FBIOBLT failed! line=%d\n", __LINE__);
2995 return FALSE;
2996 }
2997 return TRUE;
2998}
2999
Mohan Kandrabad0eaa2010-02-04 15:11:54 -08003000void QualcommCameraHardware::debugShowPreviewFPS() const
Mohan Kandra740cfce2010-01-07 12:58:24 -08003001{
3002 static int mFrameCount;
3003 static int mLastFrameCount = 0;
3004 static nsecs_t mLastFpsTime = 0;
3005 static float mFps = 0;
3006 mFrameCount++;
3007 nsecs_t now = systemTime();
3008 nsecs_t diff = now - mLastFpsTime;
3009 if (diff > ms2ns(250)) {
3010 mFps = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
Mohan Kandrabad0eaa2010-02-04 15:11:54 -08003011 LOGI("Preview Frames Per Second: %.4f", mFps);
Mohan Kandra740cfce2010-01-07 12:58:24 -08003012 mLastFpsTime = now;
3013 mLastFrameCount = mFrameCount;
3014 }
3015}
3016
Mohan Kandrabad0eaa2010-02-04 15:11:54 -08003017void QualcommCameraHardware::debugShowVideoFPS() const
3018{
3019 static int mFrameCount;
3020 static int mLastFrameCount = 0;
3021 static nsecs_t mLastFpsTime = 0;
3022 static float mFps = 0;
3023 mFrameCount++;
3024 nsecs_t now = systemTime();
3025 nsecs_t diff = now - mLastFpsTime;
3026 if (diff > ms2ns(250)) {
3027 mFps = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
3028 LOGI("Video Frames Per Second: %.4f", mFps);
3029 mLastFpsTime = now;
3030 mLastFrameCount = mFrameCount;
3031 }
3032}
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003033void QualcommCameraHardware::receivePreviewFrame(struct msm_frame *frame)
3034{
3035// LOGV("receivePreviewFrame E");
3036
3037 if (!mCameraRunning) {
3038 LOGE("ignoring preview callback--camera has been stopped");
3039 return;
3040 }
3041
Mohan Kandra740cfce2010-01-07 12:58:24 -08003042 if (UNLIKELY(mDebugFps)) {
Mohan Kandrabad0eaa2010-02-04 15:11:54 -08003043 debugShowPreviewFPS();
Mohan Kandra740cfce2010-01-07 12:58:24 -08003044 }
3045
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003046 mCallbackLock.lock();
3047 int msgEnabled = mMsgEnabled;
3048 data_callback pcb = mDataCallback;
3049 void *pdata = mCallbackCookie;
3050 data_callback_timestamp rcb = mDataCallbackTimestamp;
3051 void *rdata = mCallbackCookie;
3052 mCallbackLock.unlock();
3053
3054 // Find the offset within the heap of the current buffer.
Mohan Kandra284966d2010-01-05 13:39:15 -08003055 ssize_t offset_addr =
Mohan Kandrad9efed92010-01-15 19:08:39 -08003056 (ssize_t)frame->buffer - (ssize_t)mPreviewHeap->mHeap->base();
3057 ssize_t offset = offset_addr / mPreviewHeap->mAlignedBufferSize;
Mohan Kandra284966d2010-01-05 13:39:15 -08003058
3059 common_crop_t *crop = (common_crop_t *) (frame->cropinfo);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003060
3061 mInPreviewCallback = true;
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003062 if(mUseOverlay) {
3063 if(mOverlay != NULL) {
3064 mOverlayLock.lock();
Mohan Kandrad9efed92010-01-15 19:08:39 -08003065 mOverlay->setFd(mPreviewHeap->mHeap->getHeapID());
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003066 if (crop->in2_w != 0 || crop->in2_h != 0) {
3067 zoomCropInfo.x = (crop->out2_w - crop->in2_w + 1) / 2 - 1;
3068 zoomCropInfo.y = (crop->out2_h - crop->in2_h + 1) / 2 - 1;
3069 zoomCropInfo.w = crop->in2_w;
3070 zoomCropInfo.h = crop->in2_h;
3071 mOverlay->setCrop(zoomCropInfo.x, zoomCropInfo.y,
3072 zoomCropInfo.w, zoomCropInfo.h);
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08003073 } else {
3074 // Reset zoomCropInfo variables. This will ensure that
3075 // stale values wont be used for postview
3076 zoomCropInfo.w = crop->in2_w;
3077 zoomCropInfo.h = crop->in2_h;
3078 }
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003079 mOverlay->queueBuffer((void *)offset_addr);
3080 mLastQueuedFrame = (void *)frame->buffer;
3081 mOverlayLock.unlock();
3082 }
Mohan Kandra284966d2010-01-05 13:39:15 -08003083 } else {
Mohan Kandrad9efed92010-01-15 19:08:39 -08003084 if (crop->in2_w != 0 || crop->in2_h != 0) {
3085 dstOffset = (dstOffset + 1) % NUM_MORE_BUFS;
3086 offset = kPreviewBufferCount + dstOffset;
3087 ssize_t dstOffset_addr = offset * mPreviewHeap->mAlignedBufferSize;
3088 if( !native_zoom_image(mPreviewHeap->mHeap->getHeapID(),
3089 offset_addr, dstOffset_addr, crop)) {
3090 LOGE(" Error while doing MDP zoom ");
3091 }
3092 }
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08003093 }
Mohan Kandrad9efed92010-01-15 19:08:39 -08003094 if (pcb != NULL && (msgEnabled & CAMERA_MSG_PREVIEW_FRAME))
3095 pcb(CAMERA_MSG_PREVIEW_FRAME, mPreviewHeap->mBuffers[offset],
3096 pdata);
3097
Sravankb4f5f1c2010-01-21 11:06:17 +05303098 // If output2 enabled, Start Recording if recording is enabled by Services
Mohan Kandraf1ebf982010-02-02 15:25:43 -08003099 if( ((mCurrentTarget == TARGET_MSM7630) || (mCurrentTarget == TARGET_QSD8250)) && recordingEnabled() ) {
Sravankb4f5f1c2010-01-21 11:06:17 +05303100 if(!recordingState){
3101 recordingState = 1; // recording started
3102 LOGV(" in receivePreviewframe : recording enabled calling startRecording ");
3103 startRecording();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003104 }
Sravankb4f5f1c2010-01-21 11:06:17 +05303105 }
3106
3107 // If output is NOT enabled (targets otherthan 7x30 currently..)
Mohan Kandraf1ebf982010-02-02 15:25:43 -08003108 if( (mCurrentTarget != TARGET_MSM7630 ) && (mCurrentTarget != TARGET_QSD8250)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05303109 if(rcb != NULL && (msgEnabled & CAMERA_MSG_VIDEO_FRAME)) {
3110 rcb(systemTime(), CAMERA_MSG_VIDEO_FRAME, mPreviewHeap->mBuffers[offset], rdata);
3111 Mutex::Autolock rLock(&mRecordFrameLock);
3112 if (mReleasedRecordingFrame != true) {
3113 LOGV("block waiting for frame release");
3114 mRecordWait.wait(mRecordFrameLock);
3115 LOGV("frame released, continuing");
3116 }
3117 mReleasedRecordingFrame = false;
3118 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003119 }
3120 mInPreviewCallback = false;
3121
3122// LOGV("receivePreviewFrame X");
3123}
3124
Sravankb4f5f1c2010-01-21 11:06:17 +05303125
3126bool QualcommCameraHardware::initRecord()
3127{
3128 LOGV("initREcord E");
3129
3130 mRecordFrameSize = (mDimension.video_width * mDimension.video_height *3)/2;
3131 mRecordHeap = new PmemPool("/dev/pmem_adsp",
3132 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
3133 mCameraControlFd,
3134 MSM_PMEM_VIDEO,
3135 mRecordFrameSize,
3136 kRecordBufferCount,
3137 mRecordFrameSize,
3138 "record");
3139 if (!mRecordHeap->initialized()) {
3140 mRecordHeap.clear();
3141 LOGE("initRecord X: could not initialize record heap.");
3142 return false;
3143 }
3144 for (int cnt = 0; cnt < kRecordBufferCount; cnt++) {
3145 recordframes[cnt].fd = mRecordHeap->mHeap->getHeapID();
3146 recordframes[cnt].buffer =
3147 (uint32_t)mRecordHeap->mHeap->base() + mRecordHeap->mAlignedBufferSize * cnt;
3148 recordframes[cnt].y_off = 0;
3149 recordframes[cnt].cbcr_off = mDimension.video_width * mDimension.video_height;
3150 recordframes[cnt].path = OUTPUT_TYPE_V;
3151
3152 LOGV ("initRecord : record heap , video buffers buffer=%lu fd=%d y_off=%d cbcr_off=%d \n",
3153 (unsigned long)recordframes[cnt].buffer, recordframes[cnt].fd, recordframes[cnt].y_off,
3154 recordframes[cnt].cbcr_off);
3155 }
3156
3157 // initial setup : buffers 1,2,3 with kernel , 4 with camframe , 5,6,7,8 in free Q
3158 // flush the busy Q
3159 cam_frame_flush_video();
3160
Mohan Kandra156d0ac2010-01-25 16:59:17 -08003161 mVideoThreadWaitLock.lock();
3162 while (mVideoThreadRunning) {
3163 LOGV("initRecord: waiting for old video thread to complete.");
3164 mVideoThreadWait.wait(mVideoThreadWaitLock);
3165 LOGV("initRecord : old video thread completed.");
3166 }
3167 mVideoThreadWaitLock.unlock();
3168
Sravankdf7a9202010-02-08 15:02:51 +05303169 // flush free queue and add 5,6,7,8 buffers.
3170 LINK_cam_frame_flush_free_video();
3171 for(int i=ACTIVE_VIDEO_BUFFERS+1;i <kRecordBufferCount; i++)
3172 LINK_camframe_free_video(&recordframes[i]);
Sravankb4f5f1c2010-01-21 11:06:17 +05303173 LOGV("initREcord X");
3174
3175 return true;
3176}
3177
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003178status_t QualcommCameraHardware::startRecording()
3179{
3180 LOGV("startRecording E");
Sravankb4f5f1c2010-01-21 11:06:17 +05303181 int ret;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003182 Mutex::Autolock l(&mLock);
3183 mReleasedRecordingFrame = false;
Sravankb4f5f1c2010-01-21 11:06:17 +05303184 if( (ret=startPreviewInternal())== NO_ERROR){
Mohan Kandraf1ebf982010-02-02 15:25:43 -08003185 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05303186 LOGV(" in startREcording : calling native_start_recording");
3187 native_start_recording(mCameraControlFd);
3188 recordingState = 1;
Sravankdf7a9202010-02-08 15:02:51 +05303189 // Start video thread and wait for busy frames to be encoded, this thread
3190 // should be closed in stopRecording
3191 mVideoThreadWaitLock.lock();
3192 mVideoThreadExit = 0;
3193 pthread_attr_t attr;
3194 pthread_attr_init(&attr);
3195 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
3196 mVideoThreadRunning = pthread_create(&mVideoThread,
3197 &attr,
3198 video_thread,
3199 NULL);
3200 mVideoThreadWaitLock.unlock();
3201 // Remove the left out frames in busy Q and them in free Q.
3202 LOGV("frames in busy Q = %d", g_busy_frame_queue.num_of_frames);
3203 while((g_busy_frame_queue.num_of_frames) >0){
3204 msm_frame* vframe = cam_frame_get_video ();
3205 LINK_camframe_free_video(vframe);
3206 }
3207 LOGV("frames in busy Q = %d after deQueing", g_busy_frame_queue.num_of_frames);
Sravankb4f5f1c2010-01-21 11:06:17 +05303208 }
3209 }
3210 return ret;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003211}
3212
3213void QualcommCameraHardware::stopRecording()
3214{
3215 LOGV("stopRecording: E");
3216 Mutex::Autolock l(&mLock);
3217 {
3218 mRecordFrameLock.lock();
3219 mReleasedRecordingFrame = true;
3220 mRecordWait.signal();
3221 mRecordFrameLock.unlock();
3222
Sravankdf7a9202010-02-08 15:02:51 +05303223 if(mDataCallback && !(mCurrentTarget == TARGET_QSD8250) &&
3224 (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003225 LOGV("stopRecording: X, preview still in progress");
3226 return;
3227 }
3228 }
Sravankb4f5f1c2010-01-21 11:06:17 +05303229 // If output2 enabled, exit video thread, invoke stop recording ioctl
Mohan Kandraf1ebf982010-02-02 15:25:43 -08003230 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05303231 mVideoThreadWaitLock.lock();
3232 mVideoThreadExit = 1;
3233 mVideoThreadWaitLock.unlock();
3234 native_stop_recording(mCameraControlFd);
3235 }
3236 else // for other targets where output2 is not enabled
3237 stopPreviewInternal();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003238
Sravankb4f5f1c2010-01-21 11:06:17 +05303239 recordingState = 0; // recording not started
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003240 LOGV("stopRecording: X");
3241}
3242
3243void QualcommCameraHardware::releaseRecordingFrame(
3244 const sp<IMemory>& mem __attribute__((unused)))
3245{
3246 LOGV("releaseRecordingFrame E");
3247 Mutex::Autolock rLock(&mRecordFrameLock);
3248 mReleasedRecordingFrame = true;
3249 mRecordWait.signal();
Sravankb4f5f1c2010-01-21 11:06:17 +05303250
3251 // Ff 7x30 : add the frame to the free camframe queue
Mohan Kandraf1ebf982010-02-02 15:25:43 -08003252 if( (mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05303253 ssize_t offset;
3254 size_t size;
3255 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
3256 msm_frame* releaseframe = NULL;
3257 LOGV(" in release recording frame : heap base %d offset %d buffer %d ", heap->base(), offset, heap->base() + offset );
3258 int cnt;
3259 for (cnt = 0; cnt < kRecordBufferCount; cnt++) {
3260 if((unsigned int)recordframes[cnt].buffer == (unsigned int)(heap->base()+ offset)){
3261 LOGV("in release recording frame found match , releasing buffer %d", (unsigned int)recordframes[cnt].buffer);
3262 releaseframe = &recordframes[cnt];
3263 break;
3264 }
3265 }
3266 if(cnt < kRecordBufferCount) {
3267 // do this only if frame thread is running
3268 mFrameThreadWaitLock.lock();
3269 if(mFrameThreadRunning )
3270 LINK_camframe_free_video(releaseframe);
3271
3272 mFrameThreadWaitLock.unlock();
3273 } else {
3274 LOGE("in release recordingframe XXXXX error , buffer not found");
3275 for (int i=0; i< kRecordBufferCount; i++) {
3276 LOGE(" recordframes[%d].buffer = %d", i, (unsigned int)recordframes[i].buffer);
3277 }
3278 }
3279 }
3280
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003281 LOGV("releaseRecordingFrame X");
3282}
3283
3284bool QualcommCameraHardware::recordingEnabled()
3285{
3286 return mCameraRunning && mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME);
3287}
3288
3289void QualcommCameraHardware::notifyShutter(common_crop_t *crop)
3290{
3291 mShutterLock.lock();
3292 image_rect_type size;
3293
3294 if (mShutterPending && mNotifyCallback && (mMsgEnabled & CAMERA_MSG_SHUTTER)) {
3295 LOGV("out2_w=%d, out2_h=%d, in2_w=%d, in2_h=%d",
3296 crop->out2_w, crop->out2_h, crop->in2_w, crop->in2_h);
3297 LOGV("out1_w=%d, out1_h=%d, in1_w=%d, in1_h=%d",
3298 crop->out1_w, crop->out1_h, crop->in1_w, crop->in1_h);
3299
3300 // To workaround a bug in MDP which happens if either
3301 // dimension > 2048, we display the thumbnail instead.
3302 mDisplayHeap = mRawHeap;
3303 if (crop->in1_w == 0 || crop->in1_h == 0) {
3304 // Full size
3305 size.width = mDimension.picture_width;
3306 size.height = mDimension.picture_height;
3307 if (size.width > 2048 || size.height > 2048) {
3308 size.width = mDimension.ui_thumbnail_width;
3309 size.height = mDimension.ui_thumbnail_height;
3310 mDisplayHeap = mThumbnailHeap;
3311 }
3312 } else {
3313 // Cropped
3314 size.width = crop->in2_w & ~1;
3315 size.height = crop->in2_h & ~1;
3316 if (size.width > 2048 || size.height > 2048) {
3317 size.width = crop->in1_w & ~1;
3318 size.height = crop->in1_h & ~1;
3319 mDisplayHeap = mThumbnailHeap;
3320 }
3321 }
3322
3323 mNotifyCallback(CAMERA_MSG_SHUTTER, (int32_t)&size, 0,
3324 mCallbackCookie);
3325 mShutterPending = false;
3326 }
3327 mShutterLock.unlock();
3328}
3329
3330static void receive_shutter_callback(common_crop_t *crop)
3331{
3332 LOGV("receive_shutter_callback: E");
3333 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
3334 if (obj != 0) {
3335 obj->notifyShutter(crop);
3336 }
3337 LOGV("receive_shutter_callback: X");
3338}
3339
3340// Crop the picture in place.
3341static void crop_yuv420(uint32_t width, uint32_t height,
3342 uint32_t cropped_width, uint32_t cropped_height,
3343 uint8_t *image)
3344{
3345 uint32_t i, x, y;
3346 uint8_t* chroma_src, *chroma_dst;
3347
3348 // Calculate the start position of the cropped area.
3349 x = (width - cropped_width) / 2;
3350 y = (height - cropped_height) / 2;
3351 x &= ~1;
3352 y &= ~1;
3353
3354 // Copy luma component.
3355 for(i = 0; i < cropped_height; i++)
3356 memcpy(image + i * cropped_width,
3357 image + width * (y + i) + x,
3358 cropped_width);
3359
3360 chroma_src = image + width * height;
3361 chroma_dst = image + cropped_width * cropped_height;
3362
3363 // Copy chroma components.
3364 cropped_height /= 2;
3365 y /= 2;
3366 for(i = 0; i < cropped_height; i++)
3367 memcpy(chroma_dst + i * cropped_width,
3368 chroma_src + width * (y + i) + x,
3369 cropped_width);
3370}
3371
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08003372
3373void QualcommCameraHardware::receiveRawSnapshot(){
3374 LOGV("receiveRawSnapshot E");
3375
3376 Mutex::Autolock cbLock(&mCallbackLock);
3377
3378 notifyShutter(&mCrop);
3379
3380 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
3381
3382 if(native_get_picture(mCameraControlFd, &mCrop) == false) {
3383 LOGE("receiveRawSnapshot X: native_get_picture failed!");
3384 return;
3385 }
3386
3387 //Create a Ashmem heap to copy data from PMem heap for application layer
3388 if(mRawSnapshotAshmemHeap != NULL){
3389 LOGV("receiveRawSnapshot: clearing old mRawSnapShotAshmemHeap.");
3390 mRawSnapshotAshmemHeap.clear();
3391 }
3392 mRawSnapshotAshmemHeap = new AshmemPool(
3393 mRawSnapShotPmemHeap->mBufferSize,
3394 mRawSnapShotPmemHeap->mNumBuffers,
3395 mRawSnapShotPmemHeap->mFrameSize,
3396 "raw ashmem snapshot camera"
3397 );
3398
3399 if(!mRawSnapshotAshmemHeap->initialized()){
3400 LOGE("receiveRawSnapshot X: error initializing mRawSnapshotHeap");
3401 deinitRawSnapshot();
3402 return;
3403 }
3404
3405 memcpy(mRawSnapshotAshmemHeap->mHeap->base(),
3406 mRawSnapShotPmemHeap->mHeap->base(),
3407 mRawSnapShotPmemHeap->mHeap->getSize());
3408
3409 mDataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mRawSnapshotAshmemHeap->mBuffers[0],
3410 mCallbackCookie);
3411
3412 }
3413
3414 //cleanup
3415 deinitRawSnapshot();
3416
3417 LOGV("receiveRawSnapshot X");
3418}
3419
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003420void QualcommCameraHardware::receiveRawPicture()
3421{
3422 LOGV("receiveRawPicture: E");
3423
3424 Mutex::Autolock cbLock(&mCallbackLock);
3425 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_RAW_IMAGE)) {
3426 if(native_get_picture(mCameraControlFd, &mCrop) == false) {
3427 LOGE("getPicture failed!");
3428 return;
3429 }
3430 mCrop.in1_w &= ~1;
3431 mCrop.in1_h &= ~1;
3432 mCrop.in2_w &= ~1;
3433 mCrop.in2_h &= ~1;
3434
3435 // By the time native_get_picture returns, picture is taken. Call
3436 // shutter callback if cam config thread has not done that.
3437 notifyShutter(&mCrop);
3438
3439 // Crop the image if zoomed.
3440 if (mCrop.in2_w != 0 && mCrop.in2_h != 0) {
3441 crop_yuv420(mCrop.out2_w, mCrop.out2_h, mCrop.in2_w, mCrop.in2_h,
3442 (uint8_t *)mRawHeap->mHeap->base());
3443 crop_yuv420(mCrop.out1_w, mCrop.out1_h, mCrop.in1_w, mCrop.in1_h,
3444 (uint8_t *)mThumbnailHeap->mHeap->base());
3445 // We do not need jpeg encoder to upscale the image. Set the new
3446 // dimension for encoder.
3447 mDimension.orig_picture_dx = mCrop.in2_w;
3448 mDimension.orig_picture_dy = mCrop.in2_h;
3449 mDimension.thumbnail_width = mCrop.in1_w;
3450 mDimension.thumbnail_height = mCrop.in1_h;
3451 memset(&mCrop, 0, sizeof(mCrop));
3452 }
3453
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003454 if( mUseOverlay && (mOverlay != NULL) ) {
3455 mOverlay->setFd(mPostViewHeap->mHeap->getHeapID());
3456 if( zoomCropInfo.w !=0 && zoomCropInfo.h !=0) {
3457 LOGD(" zoomCropInfo non-zero, setting crop ");
3458 mOverlay->setCrop(zoomCropInfo.x, zoomCropInfo.y,
3459 zoomCropInfo.w, zoomCropInfo.h);
3460 }
3461 LOGD(" Queueing Postview for display ");
3462 mOverlay->queueBuffer((void *)0);
3463 }
3464
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003465 mDataCallback(CAMERA_MSG_RAW_IMAGE, mDisplayHeap->mBuffers[0],
3466 mCallbackCookie);
3467 }
3468 else LOGV("Raw-picture callback was canceled--skipping.");
3469
3470 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
3471 mJpegSize = 0;
3472 if (LINK_jpeg_encoder_init()) {
3473 if(native_jpeg_encode()) {
3474 LOGV("receiveRawPicture: X (success)");
3475 return;
3476 }
3477 LOGE("jpeg encoding failed");
3478 }
3479 else LOGE("receiveRawPicture X: jpeg_encoder_init failed.");
3480 }
3481 else LOGV("JPEG callback is NULL, not encoding image.");
3482 deinitRaw();
3483 LOGV("receiveRawPicture: X");
3484}
3485
3486void QualcommCameraHardware::receiveJpegPictureFragment(
3487 uint8_t *buff_ptr, uint32_t buff_size)
3488{
3489 uint32_t remaining = mJpegHeap->mHeap->virtualSize();
3490 remaining -= mJpegSize;
3491 uint8_t *base = (uint8_t *)mJpegHeap->mHeap->base();
3492
3493 LOGV("receiveJpegPictureFragment size %d", buff_size);
3494 if (buff_size > remaining) {
3495 LOGE("receiveJpegPictureFragment: size %d exceeds what "
3496 "remains in JPEG heap (%d), truncating",
3497 buff_size,
3498 remaining);
3499 buff_size = remaining;
3500 }
3501 memcpy(base + mJpegSize, buff_ptr, buff_size);
3502 mJpegSize += buff_size;
3503}
3504
3505void QualcommCameraHardware::receiveJpegPicture(void)
3506{
3507 LOGV("receiveJpegPicture: E image (%d uint8_ts out of %d)",
3508 mJpegSize, mJpegHeap->mBufferSize);
3509 Mutex::Autolock cbLock(&mCallbackLock);
3510
3511 int index = 0, rc;
3512
3513 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
3514 // The reason we do not allocate into mJpegHeap->mBuffers[offset] is
3515 // that the JPEG image's size will probably change from one snapshot
3516 // to the next, so we cannot reuse the MemoryBase object.
3517 sp<MemoryBase> buffer = new
3518 MemoryBase(mJpegHeap->mHeap,
3519 index * mJpegHeap->mBufferSize +
3520 0,
3521 mJpegSize);
3522 mDataCallback(CAMERA_MSG_COMPRESSED_IMAGE, buffer, mCallbackCookie);
3523 buffer = NULL;
3524 }
3525 else LOGV("JPEG callback was cancelled--not delivering image.");
3526
3527 LINK_jpeg_encoder_join();
3528 deinitRaw();
3529
3530 LOGV("receiveJpegPicture: X callback done.");
3531}
3532
3533bool QualcommCameraHardware::previewEnabled()
3534{
3535 return mCameraRunning && mDataCallback && (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME);
3536}
3537
3538status_t QualcommCameraHardware::setPreviewSize(const CameraParameters& params)
3539{
3540 int width, height;
3541 params.getPreviewSize(&width, &height);
3542 LOGV("requested preview size %d x %d", width, height);
3543
3544 // Validate the preview size
3545 for (size_t i = 0; i < PREVIEW_SIZE_COUNT; ++i) {
3546 if (width == preview_sizes[i].width
3547 && height == preview_sizes[i].height) {
3548 mParameters.setPreviewSize(width, height);
3549 mDimension.display_width = width;
3550 mDimension.display_height = height;
3551 return NO_ERROR;
3552 }
3553 }
3554 LOGE("Invalid preview size requested: %dx%d", width, height);
3555 return BAD_VALUE;
3556}
3557
3558status_t QualcommCameraHardware::setPictureSize(const CameraParameters& params)
3559{
3560 int width, height;
3561 params.getPictureSize(&width, &height);
3562 LOGV("requested picture size %d x %d", width, height);
3563
3564 // Validate the picture size
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -08003565 for (int i = 0; i < supportedPictureSizesCount; ++i) {
3566 if (width == picture_sizes_ptr[i].width
3567 && height == picture_sizes_ptr[i].height) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003568 mParameters.setPictureSize(width, height);
3569 mDimension.picture_width = width;
3570 mDimension.picture_height = height;
3571 return NO_ERROR;
3572 }
3573 }
Kiran Kumar H Nb49af212010-02-17 15:12:17 -08003574 /* Dimension not among the ones in the list. Check if
3575 * its a valid dimension, if it is, then configure the
3576 * camera accordingly. else reject it.
3577 */
3578 if( isValidDimension(width, height) ) {
3579 mParameters.setPictureSize(width, height);
3580 mDimension.picture_width = width;
3581 mDimension.picture_height = height;
3582 return NO_ERROR;
3583 } else
3584 LOGE("Invalid picture size requested: %dx%d", width, height);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003585 return BAD_VALUE;
3586}
3587
3588status_t QualcommCameraHardware::setJpegQuality(const CameraParameters& params) {
3589 status_t rc = NO_ERROR;
3590 int quality = params.getInt(CameraParameters::KEY_JPEG_QUALITY);
3591 if (quality > 0 && quality <= 100) {
3592 mParameters.set(CameraParameters::KEY_JPEG_QUALITY, quality);
3593 } else {
3594 LOGE("Invalid jpeg quality=%d", quality);
3595 rc = BAD_VALUE;
3596 }
3597
3598 quality = params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY);
3599 if (quality > 0 && quality <= 100) {
3600 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, quality);
3601 } else {
3602 LOGE("Invalid jpeg thumbnail quality=%d", quality);
3603 rc = BAD_VALUE;
3604 }
3605 return rc;
3606}
3607
3608status_t QualcommCameraHardware::setEffect(const CameraParameters& params)
3609{
3610 const char *str = params.get(CameraParameters::KEY_EFFECT);
3611 if (str != NULL) {
3612 int32_t value = attr_lookup(effects, sizeof(effects) / sizeof(str_map), str);
3613 if (value != NOT_FOUND) {
Mohan Kandra93f1bfb2009-12-15 16:55:33 -08003614 if(!strcmp(sensorType->name, "2mp") && (value != CAMERA_EFFECT_OFF)
3615 &&(value != CAMERA_EFFECT_MONO) && (value != CAMERA_EFFECT_NEGATIVE)
3616 &&(value != CAMERA_EFFECT_SOLARIZE) && (value != CAMERA_EFFECT_SEPIA)) {
3617 LOGE("Special effect parameter is not supported for this sensor");
3618 return NO_ERROR;
3619 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003620 mParameters.set(CameraParameters::KEY_EFFECT, str);
3621 bool ret = native_set_parm(CAMERA_SET_PARM_EFFECT, sizeof(value),
3622 (void *)&value);
3623 return ret ? NO_ERROR : UNKNOWN_ERROR;
3624 }
3625 }
3626 LOGE("Invalid effect value: %s", (str == NULL) ? "NULL" : str);
3627 return BAD_VALUE;
3628}
3629
Apurva Rajguru55562b02009-12-03 12:25:35 -08003630status_t QualcommCameraHardware::setAutoExposure(const CameraParameters& params)
3631{
Mohan Kandra93f1bfb2009-12-15 16:55:33 -08003632 if(!strcmp(sensorType->name, "2mp")) {
3633 LOGE("Auto Exposure not supported for this sensor");
3634 return NO_ERROR;
3635 }
Apurva Rajguru55562b02009-12-03 12:25:35 -08003636 const char *str = params.get(CameraParameters::KEY_AUTO_EXPOSURE);
3637 if (str != NULL) {
3638 int32_t value = attr_lookup(autoexposure, sizeof(autoexposure) / sizeof(str_map), str);
3639 if (value != NOT_FOUND) {
3640 mParameters.set(CameraParameters::KEY_AUTO_EXPOSURE, str);
3641 bool ret = native_set_parm(CAMERA_SET_PARM_EXPOSURE, sizeof(value),
3642 (void *)&value);
3643 return ret ? NO_ERROR : UNKNOWN_ERROR;
3644 }
3645 }
3646 LOGE("Invalid auto exposure value: %s", (str == NULL) ? "NULL" : str);
3647 return BAD_VALUE;
3648}
3649
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003650status_t QualcommCameraHardware::setSharpness(const CameraParameters& params)
3651{
3652 if(!strcmp(sensorType->name, "2mp")) {
3653 LOGE("Sharpness not supported for this sensor");
3654 return NO_ERROR;
3655 }
3656 int sharpness = params.getInt(CameraParameters::KEY_SHARPNESS);
3657 if((sharpness < CAMERA_MIN_SHARPNESS
3658 || sharpness > CAMERA_MAX_SHARPNESS))
3659 return UNKNOWN_ERROR;
Srinivasan Kannan551fd262010-01-14 17:48:30 -08003660
3661 LOGV("setting sharpness %d", sharpness);
3662 mParameters.set(CameraParameters::KEY_SHARPNESS, sharpness);
3663 bool ret = native_set_parm(CAMERA_SET_PARM_SHARPNESS, sizeof(sharpness),
3664 (void *)&sharpness);
3665 return ret ? NO_ERROR : UNKNOWN_ERROR;
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003666}
3667
3668status_t QualcommCameraHardware::setContrast(const CameraParameters& params)
3669{
3670 if(!strcmp(sensorType->name, "2mp")) {
3671 LOGE("Contrast not supported for this sensor");
3672 return NO_ERROR;
3673 }
3674 int contrast = params.getInt(CameraParameters::KEY_CONTRAST);
3675 if((contrast < CAMERA_MIN_CONTRAST)
3676 || (contrast > CAMERA_MAX_CONTRAST))
3677 return UNKNOWN_ERROR;
Srinivasan Kannan551fd262010-01-14 17:48:30 -08003678
3679 LOGV("setting contrast %d", contrast);
3680 mParameters.set(CameraParameters::KEY_CONTRAST, contrast);
3681 bool ret = native_set_parm(CAMERA_SET_PARM_CONTRAST, sizeof(contrast),
3682 (void *)&contrast);
3683 return ret ? NO_ERROR : UNKNOWN_ERROR;
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003684}
3685
3686status_t QualcommCameraHardware::setSaturation(const CameraParameters& params)
3687{
3688 if(!strcmp(sensorType->name, "2mp")) {
3689 LOGE("Saturation not supported for this sensor");
3690 return NO_ERROR;
3691 }
Srinivasan Kannan551fd262010-01-14 17:48:30 -08003692
Kiran Kumar H Nf87cf862010-01-27 14:34:34 -08003693 const char *str = params.get(CameraParameters::KEY_EFFECT);
3694 int32_t value = attr_lookup(effects, sizeof(effects) / sizeof(str_map), str);
3695
3696 if( (value != CAMERA_EFFECT_MONO) && (value != CAMERA_EFFECT_NEGATIVE)
3697 && (value != CAMERA_EFFECT_AQUA) && (value != CAMERA_EFFECT_SEPIA)) {
3698
3699 int saturation = params.getInt(CameraParameters::KEY_SATURATION);
3700 if((saturation < CAMERA_MIN_SATURATION)
3701 || (saturation > CAMERA_MAX_SATURATION))
3702 return UNKNOWN_ERROR;
3703
3704 LOGV("setting saturation %d", saturation);
3705 mParameters.set(CameraParameters::KEY_SATURATION, saturation);
3706 bool ret = native_set_parm(CAMERA_SET_PARM_SATURATION, sizeof(saturation),
3707 (void *)&saturation);
3708 return ret ? NO_ERROR : UNKNOWN_ERROR;
3709 } else {
3710 LOGE(" Saturation value will not be set " \
3711 "when the effect selected is %s", str);
3712 return NO_ERROR;
3713 }
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003714}
3715
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303716status_t QualcommCameraHardware::setBrightness(const CameraParameters& params) {
3717 int brightness = params.getInt("luma-adaptation");
3718 if (mBrightness != brightness) {
3719 LOGV(" new brightness value : %d ", brightness);
3720 mBrightness = brightness;
3721
3722 bool ret = native_set_parm(CAMERA_SET_PARM_BRIGHTNESS, sizeof(mBrightness),
3723 (void *)&mBrightness);
3724 return ret ? NO_ERROR : UNKNOWN_ERROR;
3725 } else {
3726 return NO_ERROR;
3727 }
3728}
3729
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003730status_t QualcommCameraHardware::setWhiteBalance(const CameraParameters& params)
3731{
3732 const char *str = params.get(CameraParameters::KEY_WHITE_BALANCE);
3733 if (str != NULL) {
3734 int32_t value = attr_lookup(whitebalance, sizeof(whitebalance) / sizeof(str_map), str);
3735 if (value != NOT_FOUND) {
3736 mParameters.set(CameraParameters::KEY_WHITE_BALANCE, str);
3737 bool ret = native_set_parm(CAMERA_SET_PARM_WB, sizeof(value),
3738 (void *)&value);
3739 return ret ? NO_ERROR : UNKNOWN_ERROR;
3740 }
3741 }
3742 LOGE("Invalid whitebalance value: %s", (str == NULL) ? "NULL" : str);
3743 return BAD_VALUE;
3744}
3745
3746status_t QualcommCameraHardware::setFlash(const CameraParameters& params)
3747{
3748 if (!mSensorInfo.flash_enabled) {
3749 LOGV("%s: flash not supported", __FUNCTION__);
3750 return NO_ERROR;
3751 }
3752
3753 const char *str = params.get(CameraParameters::KEY_FLASH_MODE);
3754 if (str != NULL) {
3755 int32_t value = attr_lookup(flash, sizeof(flash) / sizeof(str_map), str);
3756 if (value != NOT_FOUND) {
3757 mParameters.set(CameraParameters::KEY_FLASH_MODE, str);
3758 bool ret = native_set_parm(CAMERA_SET_PARM_LED_MODE,
3759 sizeof(value), (void *)&value);
3760 return ret ? NO_ERROR : UNKNOWN_ERROR;
3761 }
3762 }
3763 LOGE("Invalid flash mode value: %s", (str == NULL) ? "NULL" : str);
3764 return BAD_VALUE;
3765}
3766
3767status_t QualcommCameraHardware::setAntibanding(const CameraParameters& params)
3768{
Srinivasan Kannan2229d272010-01-05 14:58:28 -08003769 if(!strcmp(sensorType->name, "2mp")) {
3770 LOGE("Parameter AntiBanding is not supported for this sensor");
3771 return NO_ERROR;
3772 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003773 const char *str = params.get(CameraParameters::KEY_ANTIBANDING);
3774 if (str != NULL) {
3775 int value = (camera_antibanding_type)attr_lookup(
3776 antibanding, sizeof(antibanding) / sizeof(str_map), str);
3777 if (value != NOT_FOUND) {
3778 camera_antibanding_type temp = (camera_antibanding_type) value;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003779 mParameters.set(CameraParameters::KEY_ANTIBANDING, str);
Srinivasan Kannan2229d272010-01-05 14:58:28 -08003780 bool ret;
3781 if (temp == CAMERA_ANTIBANDING_AUTO) {
3782 ret = native_set_parm(CAMERA_ENABLE_AFD,
3783 0, NULL);
3784 } else {
3785 ret = native_set_parm(CAMERA_SET_PARM_ANTIBANDING,
3786 sizeof(camera_antibanding_type), (void *)&temp);
3787 }
3788 return ret ? NO_ERROR : UNKNOWN_ERROR;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003789 }
3790 }
3791 LOGE("Invalid antibanding value: %s", (str == NULL) ? "NULL" : str);
3792 return BAD_VALUE;
3793}
3794
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303795status_t QualcommCameraHardware::setLensshadeValue(const CameraParameters& params)
3796{
Mohan Kandra93f1bfb2009-12-15 16:55:33 -08003797 if(!strcmp(sensorType->name, "2mp")) {
3798 LOGE("Parameter Rolloff is not supported for this sensor");
3799 return NO_ERROR;
3800 }
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303801 const char *str = params.get(CameraParameters::KEY_LENSSHADE);
3802 if (str != NULL) {
3803 int value = attr_lookup(lensshade,
3804 sizeof(lensshade) / sizeof(str_map), str);
3805 if (value != NOT_FOUND) {
3806 int8_t temp = (int8_t)value;
3807 mParameters.set(CameraParameters::KEY_LENSSHADE, str);
3808 native_set_parm(CAMERA_SET_PARM_ROLLOFF, sizeof(int8_t), (void *)&temp);
3809 return NO_ERROR;
3810 }
3811 }
3812 LOGE("Invalid lensShade value: %s", (str == NULL) ? "NULL" : str);
3813 return BAD_VALUE;
3814}
3815
3816status_t QualcommCameraHardware::setISOValue(const CameraParameters& params) {
3817 const char *str = params.get(CameraParameters::KEY_ISO_MODE);
3818 if (str != NULL) {
3819 int value = (camera_iso_mode_type)attr_lookup(
3820 iso, sizeof(iso) / sizeof(str_map), str);
3821 if (value != NOT_FOUND) {
3822 camera_iso_mode_type temp = (camera_iso_mode_type) value;
3823 mParameters.set(CameraParameters::KEY_ISO_MODE, str);
3824 native_set_parm(CAMERA_SET_PARM_ISO, sizeof(camera_iso_mode_type), (void *)&temp);
3825 return NO_ERROR;
3826 }
3827 }
3828 LOGE("Invalid Iso value: %s", (str == NULL) ? "NULL" : str);
3829 return BAD_VALUE;
3830}
3831
3832
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003833status_t QualcommCameraHardware::setGpsLocation(const CameraParameters& params)
3834{
3835 const char *latitude = params.get(CameraParameters::KEY_GPS_LATITUDE);
3836 if (latitude) {
3837 mParameters.set(CameraParameters::KEY_GPS_LATITUDE, latitude);
3838 }
3839
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08003840 const char *latitudeRef = params.get(CameraParameters::KEY_GPS_LATITUDE_REF);
3841 if (latitudeRef) {
3842 mParameters.set(CameraParameters::KEY_GPS_LATITUDE_REF, latitudeRef);
3843 }
3844
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003845 const char *longitude = params.get(CameraParameters::KEY_GPS_LONGITUDE);
3846 if (longitude) {
3847 mParameters.set(CameraParameters::KEY_GPS_LONGITUDE, longitude);
3848 }
3849
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08003850 const char *longitudeRef = params.get(CameraParameters::KEY_GPS_LONGITUDE_REF);
3851 if (longitudeRef) {
3852 mParameters.set(CameraParameters::KEY_GPS_LONGITUDE_REF, longitudeRef);
3853 }
3854
3855 const char *altitudeRef = params.get(CameraParameters::KEY_GPS_ALTITUDE_REF);
3856 if (altitudeRef) {
3857 mParameters.set(CameraParameters::KEY_GPS_ALTITUDE_REF, altitudeRef);
3858 }
3859
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003860 const char *altitude = params.get(CameraParameters::KEY_GPS_ALTITUDE);
3861 if (altitude) {
3862 mParameters.set(CameraParameters::KEY_GPS_ALTITUDE, altitude);
3863 }
3864
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08003865 const char *status = params.get(CameraParameters::KEY_GPS_STATUS);
3866 if (status) {
3867 mParameters.set(CameraParameters::KEY_GPS_STATUS, status);
3868 }
3869
3870 const char *dateTime = params.get(CameraParameters::KEY_EXIF_DATETIME);
3871 if (dateTime) {
3872 mParameters.set(CameraParameters::KEY_EXIF_DATETIME, dateTime);
3873 }
3874
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003875 const char *timestamp = params.get(CameraParameters::KEY_GPS_TIMESTAMP);
3876 if (timestamp) {
3877 mParameters.set(CameraParameters::KEY_GPS_TIMESTAMP, timestamp);
3878 }
3879 return NO_ERROR;
3880}
3881
3882status_t QualcommCameraHardware::setRotation(const CameraParameters& params)
3883{
3884 status_t rc = NO_ERROR;
3885 int rotation = params.getInt(CameraParameters::KEY_ROTATION);
3886 if (rotation != NOT_FOUND) {
3887 if (rotation == 0 || rotation == 90 || rotation == 180
3888 || rotation == 270) {
3889 mParameters.set(CameraParameters::KEY_ROTATION, rotation);
3890 } else {
3891 LOGE("Invalid rotation value: %d", rotation);
3892 rc = BAD_VALUE;
3893 }
3894 }
3895 return rc;
3896}
3897
3898status_t QualcommCameraHardware::setZoom(const CameraParameters& params)
3899{
3900 status_t rc = NO_ERROR;
3901 // No matter how many different zoom values the driver can provide, HAL
3902 // provides applictations the same number of zoom levels. The maximum driver
3903 // zoom value depends on sensor output (VFE input) and preview size (VFE
3904 // output) because VFE can only crop and cannot upscale. If the preview size
3905 // is bigger, the maximum zoom ratio is smaller. However, we want the
3906 // zoom ratio of each zoom level is always the same whatever the preview
3907 // size is. Ex: zoom level 1 is always 1.2x, zoom level 2 is 1.44x, etc. So,
3908 // we need to have a fixed maximum zoom value and do read it from the
3909 // driver.
Mohan Kandra284966d2010-01-05 13:39:15 -08003910 static const int ZOOM_STEP = 1;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003911 int32_t zoom_level = params.getInt("zoom");
3912
Mohan Kandra284966d2010-01-05 13:39:15 -08003913 LOGV("Set zoom=%d", zoom_level);
3914 if(zoom_level >= 0 && zoom_level <= mMaxZoom) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003915 mParameters.set("zoom", zoom_level);
3916 int32_t zoom_value = ZOOM_STEP * zoom_level;
3917 bool ret = native_set_parm(CAMERA_SET_PARM_ZOOM,
3918 sizeof(zoom_value), (void *)&zoom_value);
3919 rc = ret ? NO_ERROR : UNKNOWN_ERROR;
3920 } else {
3921 rc = BAD_VALUE;
3922 }
3923
3924 return rc;
3925}
3926
3927status_t QualcommCameraHardware::setFocusMode(const CameraParameters& params)
3928{
3929 const char *str = params.get(CameraParameters::KEY_FOCUS_MODE);
3930 if (str != NULL) {
3931 int32_t value = attr_lookup(focus_modes,
3932 sizeof(focus_modes) / sizeof(str_map), str);
3933 if (value != NOT_FOUND) {
3934 mParameters.set(CameraParameters::KEY_FOCUS_MODE, str);
3935 // Focus step is reset to infinity when preview is started. We do
3936 // not need to do anything now.
3937 return NO_ERROR;
3938 }
3939 }
3940 LOGE("Invalid focus mode value: %s", (str == NULL) ? "NULL" : str);
3941 return BAD_VALUE;
3942}
3943
3944status_t QualcommCameraHardware::setOrientation(const CameraParameters& params)
3945{
3946 const char *str = params.get("orientation");
3947
3948 if (str != NULL) {
3949 if (strcmp(str, "portrait") == 0 || strcmp(str, "landscape") == 0) {
3950 // Camera service needs this to decide if the preview frames and raw
3951 // pictures should be rotated.
3952 mParameters.set("orientation", str);
3953 } else {
3954 LOGE("Invalid orientation value: %s", str);
3955 return BAD_VALUE;
3956 }
3957 }
3958 return NO_ERROR;
3959}
3960
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08003961status_t QualcommCameraHardware::setPictureFormat(const CameraParameters& params)
3962{
3963 const char * str = params.get(CameraParameters::KEY_PICTURE_FORMAT);
3964
3965 if(str != NULL){
3966 int32_t value = attr_lookup(picture_formats,
3967 sizeof(picture_formats) / sizeof(str_map), str);
3968 if(value != NOT_FOUND){
3969 mParameters.set(CameraParameters::KEY_PICTURE_FORMAT, str);
3970 } else {
3971 LOGE("Invalid Picture Format value: %s", str);
3972 return BAD_VALUE;
3973 }
3974 }
3975 return NO_ERROR;
3976}
3977
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003978QualcommCameraHardware::MemPool::MemPool(int buffer_size, int num_buffers,
3979 int frame_size,
3980 const char *name) :
3981 mBufferSize(buffer_size),
3982 mNumBuffers(num_buffers),
3983 mFrameSize(frame_size),
3984 mBuffers(NULL), mName(name)
3985{
3986 int page_size_minus_1 = getpagesize() - 1;
3987 mAlignedBufferSize = (buffer_size + page_size_minus_1) & (~page_size_minus_1);
3988}
3989
3990void QualcommCameraHardware::MemPool::completeInitialization()
3991{
3992 // If we do not know how big the frame will be, we wait to allocate
3993 // the buffers describing the individual frames until we do know their
3994 // size.
3995
3996 if (mFrameSize > 0) {
3997 mBuffers = new sp<MemoryBase>[mNumBuffers];
3998 for (int i = 0; i < mNumBuffers; i++) {
3999 mBuffers[i] = new
4000 MemoryBase(mHeap,
4001 i * mAlignedBufferSize,
4002 mFrameSize);
4003 }
4004 }
4005}
4006
4007QualcommCameraHardware::AshmemPool::AshmemPool(int buffer_size, int num_buffers,
4008 int frame_size,
4009 const char *name) :
4010 QualcommCameraHardware::MemPool(buffer_size,
4011 num_buffers,
4012 frame_size,
4013 name)
4014{
4015 LOGV("constructing MemPool %s backed by ashmem: "
4016 "%d frames @ %d uint8_ts, "
4017 "buffer size %d",
4018 mName,
4019 num_buffers, frame_size, buffer_size);
4020
4021 int page_mask = getpagesize() - 1;
4022 int ashmem_size = buffer_size * num_buffers;
4023 ashmem_size += page_mask;
4024 ashmem_size &= ~page_mask;
4025
4026 mHeap = new MemoryHeapBase(ashmem_size);
4027
4028 completeInitialization();
4029}
4030
4031static bool register_buf(int camfd,
4032 int size,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08004033 int frame_size,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004034 int pmempreviewfd,
4035 uint32_t offset,
4036 uint8_t *buf,
4037 int pmem_type,
4038 bool vfe_can_write,
4039 bool register_buffer = true);
4040
4041QualcommCameraHardware::PmemPool::PmemPool(const char *pmem_pool,
4042 int flags,
4043 int camera_control_fd,
4044 int pmem_type,
4045 int buffer_size, int num_buffers,
4046 int frame_size,
4047 const char *name) :
4048 QualcommCameraHardware::MemPool(buffer_size,
4049 num_buffers,
4050 frame_size,
4051 name),
4052 mPmemType(pmem_type),
4053 mCameraControlFd(dup(camera_control_fd))
4054{
4055 LOGV("constructing MemPool %s backed by pmem pool %s: "
4056 "%d frames @ %d bytes, buffer size %d",
4057 mName,
4058 pmem_pool, num_buffers, frame_size,
4059 buffer_size);
4060
4061 LOGV("%s: duplicating control fd %d --> %d",
4062 __FUNCTION__,
4063 camera_control_fd, mCameraControlFd);
4064
4065 // Make a new mmap'ed heap that can be shared across processes.
4066 // mAlignedBufferSize is already in 4k aligned. (do we need total size necessary to be in power of 2??)
4067 mAlignedSize = mAlignedBufferSize * num_buffers;
4068
4069 sp<MemoryHeapBase> masterHeap =
4070 new MemoryHeapBase(pmem_pool, mAlignedSize, flags);
4071
4072 if (masterHeap->getHeapID() < 0) {
4073 LOGE("failed to construct master heap for pmem pool %s", pmem_pool);
4074 masterHeap.clear();
4075 return;
4076 }
4077
4078 sp<MemoryHeapPmem> pmemHeap = new MemoryHeapPmem(masterHeap, flags);
4079 if (pmemHeap->getHeapID() >= 0) {
4080 pmemHeap->slap();
4081 masterHeap.clear();
4082 mHeap = pmemHeap;
4083 pmemHeap.clear();
4084
4085 mFd = mHeap->getHeapID();
4086 if (::ioctl(mFd, PMEM_GET_SIZE, &mSize)) {
4087 LOGE("pmem pool %s ioctl(PMEM_GET_SIZE) error %s (%d)",
4088 pmem_pool,
4089 ::strerror(errno), errno);
4090 mHeap.clear();
4091 return;
4092 }
4093
4094 LOGV("pmem pool %s ioctl(fd = %d, PMEM_GET_SIZE) is %ld",
4095 pmem_pool,
4096 mFd,
4097 mSize.len);
Mohan Kandra284966d2010-01-05 13:39:15 -08004098 LOGD("mBufferSize=%d, mAlignedBufferSize=%d\n", mBufferSize, mAlignedBufferSize);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004099 // Unregister preview buffers with the camera drivers. Allow the VFE to write
4100 // to all preview buffers except for the last one.
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08004101 // Only Register the preview, snapshot and thumbnail buffers with the kernel.
Mohan Kandrad9efed92010-01-15 19:08:39 -08004102 if( (strcmp("postview", mName) != 0) ){
4103 int num_buf = num_buffers;
4104 if(!strcmp("preview", mName)) num_buf = kPreviewBufferCount;
Brian Steuerb62adbd2010-02-02 14:47:08 -08004105 LOGD("num_buffers = %d", num_buf);
Mohan Kandrad9efed92010-01-15 19:08:39 -08004106 for (int cnt = 0; cnt < num_buf; ++cnt) {
Sravankb4f5f1c2010-01-21 11:06:17 +05304107 int active = 1;
4108 if(pmem_type == MSM_PMEM_VIDEO){
4109 active = (cnt<ACTIVE_VIDEO_BUFFERS);
4110 LOGV(" pmempool creating video buffers : active %d ", active);
4111 }
4112 else if (pmem_type == MSM_PMEM_PREVIEW){
4113 active = (cnt < (num_buf-1));
4114 }
Mohan Kandra284966d2010-01-05 13:39:15 -08004115 register_buf(mCameraControlFd,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004116 mBufferSize,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08004117 mFrameSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004118 mHeap->getHeapID(),
4119 mAlignedBufferSize * cnt,
4120 (uint8_t *)mHeap->base() + mAlignedBufferSize * cnt,
4121 pmem_type,
Sravankb4f5f1c2010-01-21 11:06:17 +05304122 active);
Mohan Kandra284966d2010-01-05 13:39:15 -08004123 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004124 }
4125
4126 completeInitialization();
4127 }
4128 else LOGE("pmem pool %s error: could not create master heap!",
4129 pmem_pool);
4130}
4131
4132QualcommCameraHardware::PmemPool::~PmemPool()
4133{
4134 LOGV("%s: %s E", __FUNCTION__, mName);
4135 if (mHeap != NULL) {
4136 // Unregister preview buffers with the camera drivers.
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08004137 // Only Unregister the preview, snapshot and thumbnail
4138 // buffers with the kernel.
Mohan Kandrad9efed92010-01-15 19:08:39 -08004139 if( (strcmp("postview", mName) != 0) ){
4140 int num_buffers = mNumBuffers;
4141 if(!strcmp("preview", mName)) num_buffers = kPreviewBufferCount;
4142 for (int cnt = 0; cnt < num_buffers; ++cnt) {
Mohan Kandra284966d2010-01-05 13:39:15 -08004143 register_buf(mCameraControlFd,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004144 mBufferSize,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08004145 mFrameSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004146 mHeap->getHeapID(),
4147 mAlignedBufferSize * cnt,
4148 (uint8_t *)mHeap->base() + mAlignedBufferSize * cnt,
4149 mPmemType,
4150 false,
4151 false /* unregister */);
Mohan Kandra284966d2010-01-05 13:39:15 -08004152 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004153 }
4154 }
4155 LOGV("destroying PmemPool %s: closing control fd %d",
4156 mName,
4157 mCameraControlFd);
4158 close(mCameraControlFd);
4159 LOGV("%s: %s X", __FUNCTION__, mName);
4160}
4161
4162QualcommCameraHardware::MemPool::~MemPool()
4163{
4164 LOGV("destroying MemPool %s", mName);
4165 if (mFrameSize > 0)
4166 delete [] mBuffers;
4167 mHeap.clear();
4168 LOGV("destroying MemPool %s completed", mName);
4169}
4170
4171static bool register_buf(int camfd,
4172 int size,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08004173 int frame_size,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004174 int pmempreviewfd,
4175 uint32_t offset,
4176 uint8_t *buf,
4177 int pmem_type,
4178 bool vfe_can_write,
4179 bool register_buffer)
4180{
4181 struct msm_pmem_info pmemBuf;
4182
4183 pmemBuf.type = pmem_type;
4184 pmemBuf.fd = pmempreviewfd;
4185 pmemBuf.offset = offset;
4186 pmemBuf.len = size;
4187 pmemBuf.vaddr = buf;
4188 pmemBuf.y_off = 0;
Srinivasan Kannanb36a4fe2010-01-29 19:34:09 -08004189
4190 if(pmem_type == MSM_PMEM_RAW_MAINIMG)
4191 pmemBuf.cbcr_off = 0;
4192 else
4193 pmemBuf.cbcr_off = PAD_TO_WORD(frame_size * 2 / 3);
4194
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004195 pmemBuf.active = vfe_can_write;
4196
4197 LOGV("register_buf: camfd = %d, reg = %d buffer = %p",
4198 camfd, !register_buffer, buf);
4199 if (ioctl(camfd,
4200 register_buffer ?
4201 MSM_CAM_IOCTL_REGISTER_PMEM :
4202 MSM_CAM_IOCTL_UNREGISTER_PMEM,
4203 &pmemBuf) < 0) {
4204 LOGE("register_buf: MSM_CAM_IOCTL_(UN)REGISTER_PMEM fd %d error %s",
4205 camfd,
4206 strerror(errno));
4207 return false;
4208 }
4209 return true;
4210}
4211
4212status_t QualcommCameraHardware::MemPool::dump(int fd, const Vector<String16>& args) const
4213{
4214 const size_t SIZE = 256;
4215 char buffer[SIZE];
4216 String8 result;
4217 snprintf(buffer, 255, "QualcommCameraHardware::AshmemPool::dump\n");
4218 result.append(buffer);
4219 if (mName) {
4220 snprintf(buffer, 255, "mem pool name (%s)\n", mName);
4221 result.append(buffer);
4222 }
4223 if (mHeap != 0) {
4224 snprintf(buffer, 255, "heap base(%p), size(%d), flags(%d), device(%s)\n",
4225 mHeap->getBase(), mHeap->getSize(),
4226 mHeap->getFlags(), mHeap->getDevice());
4227 result.append(buffer);
4228 }
4229 snprintf(buffer, 255,
4230 "buffer size (%d), number of buffers (%d), frame size(%d)",
4231 mBufferSize, mNumBuffers, mFrameSize);
4232 result.append(buffer);
4233 write(fd, result.string(), result.size());
4234 return NO_ERROR;
4235}
4236
4237static void receive_camframe_callback(struct msm_frame *frame)
4238{
4239 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4240 if (obj != 0) {
4241 obj->receivePreviewFrame(frame);
4242 }
4243}
4244
4245static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size)
4246{
4247 LOGV("receive_jpeg_fragment_callback E");
4248 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4249 if (obj != 0) {
4250 obj->receiveJpegPictureFragment(buff_ptr, buff_size);
4251 }
4252 LOGV("receive_jpeg_fragment_callback X");
4253}
4254
4255static void receive_jpeg_callback(jpeg_event_t status)
4256{
4257 LOGV("receive_jpeg_callback E (completion status %d)", status);
4258 if (status == JPEG_EVENT_DONE) {
4259 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4260 if (obj != 0) {
4261 obj->receiveJpegPicture();
4262 }
4263 }
4264 LOGV("receive_jpeg_callback X");
4265}
Sravankb4f5f1c2010-01-21 11:06:17 +05304266// 720p : video frame calbback from camframe
4267static void receive_camframe_video_callback(struct msm_frame *frame)
4268{
4269 LOGV("receive_camframe_video_callback E");
4270 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4271 if (obj != 0) {
4272 obj->receiveRecordingFrame(frame);
4273 }
4274 LOGV("receive_camframe_video_callback X");
4275}
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004276
4277void QualcommCameraHardware::setCallbacks(notify_callback notify_cb,
4278 data_callback data_cb,
4279 data_callback_timestamp data_cb_timestamp,
4280 void* user)
4281{
4282 Mutex::Autolock lock(mLock);
4283 mNotifyCallback = notify_cb;
4284 mDataCallback = data_cb;
4285 mDataCallbackTimestamp = data_cb_timestamp;
4286 mCallbackCookie = user;
4287}
4288
4289void QualcommCameraHardware::enableMsgType(int32_t msgType)
4290{
4291 Mutex::Autolock lock(mLock);
4292 mMsgEnabled |= msgType;
4293}
4294
4295void QualcommCameraHardware::disableMsgType(int32_t msgType)
4296{
4297 Mutex::Autolock lock(mLock);
4298 mMsgEnabled &= ~msgType;
4299}
4300
4301bool QualcommCameraHardware::msgTypeEnabled(int32_t msgType)
4302{
4303 return (mMsgEnabled & msgType);
4304}
4305
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08004306bool QualcommCameraHardware::useOverlay(void)
4307{
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08004308 if( mCurrentTarget == TARGET_MSM7630 ) {
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08004309 /* Only 7x30 supports Overlay */
4310 mUseOverlay = TRUE;
4311 } else
4312 mUseOverlay = FALSE;
4313
4314 LOGV(" Using Overlay : %s ", mUseOverlay ? "YES" : "NO" );
4315 return mUseOverlay;
4316}
4317
4318status_t QualcommCameraHardware::setOverlay(const sp<Overlay> &Overlay)
4319{
4320 if( Overlay != NULL) {
4321 LOGV(" Valid overlay object ");
4322 mOverlayLock.lock();
4323 mOverlay = Overlay;
4324 mOverlayLock.unlock();
4325 } else {
4326 LOGE(" Overlay object NULL. returning ");
Mohan Kandrad9efed92010-01-15 19:08:39 -08004327 mOverlay = NULL;
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08004328 return UNKNOWN_ERROR;
4329 }
4330 return NO_ERROR;
4331}
Kiran Kumar H N215cac42009-12-08 01:53:46 -08004332
4333void QualcommCameraHardware::receive_camframetimeout(void) {
4334 LOGV("receive_camframetimeout: E");
4335 Mutex::Autolock l(&mCamframeTimeoutLock);
Kiran Kumar H N7ac84e32010-02-01 10:58:47 -08004336 LOGD(" Camframe timed out. Not receiving any frames from camera driver ");
Kiran Kumar H N215cac42009-12-08 01:53:46 -08004337 camframe_timeout_flag = TRUE;
4338 LOGV("receive_camframetimeout: X");
4339}
4340
4341static void receive_camframetimeout_callback(void) {
4342 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4343 if (obj != 0) {
4344 obj->receive_camframetimeout();
4345 }
4346}
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08004347
4348void QualcommCameraHardware::storePreviewFrameForPostview(void) {
4349 LOGV(" storePreviewFrameForPostview : E ");
4350
4351 /* Since there is restriction on the maximum overlay dimensions
4352 * that can be created, we use the last preview frame as postview
4353 * for 7x30. */
4354 LOGV(" Copying the preview buffer to postview buffer %d ",
4355 mPreviewFrameSize);
4356 if( mPostViewHeap != NULL && mLastQueuedFrame != NULL) {
4357 memcpy(mPostViewHeap->mHeap->base(),
4358 (uint8_t *)mLastQueuedFrame, mPreviewFrameSize );
4359 } else
4360 LOGE(" Failed to store Preview frame. No Postview ");
4361
4362 LOGV(" storePreviewFrameForPostview : X ");
4363}
Kiran Kumar H Nb49af212010-02-17 15:12:17 -08004364
4365bool QualcommCameraHardware::isValidDimension(int width, int height) {
4366 bool retVal = FALSE;
4367 /* This function checks if a given resolution is valid or not.
4368 * A particular resolution is considered valid if it satisfies
4369 * the following conditions:
4370 * 1. width & height should be multiple of 16.
4371 * 2. width & height should be less than/equal to the dimensions
4372 * supported by the camera sensor.
4373 * 3. the aspect ratio is a valid aspect ratio and is among the
4374 * commonly used aspect ratio as determined by the thumbnail_sizes
4375 * data structure.
4376 */
4377
4378 if( (width == CEILING16(width)) && (height == CEILING16(height))
4379 && (width <= sensorType->max_supported_snapshot_width)
4380 && (height <= sensorType->max_supported_snapshot_height) )
4381 {
4382 uint32_t pictureAspectRatio = (uint32_t)((width * Q12)/height);
4383 for(int i = 0; i < THUMBNAIL_SIZE_COUNT; i++ ) {
4384 if(thumbnail_sizes[i].aspect_ratio == pictureAspectRatio) {
4385 retVal = TRUE;
4386 break;
4387 }
4388 }
4389 }
4390 return retVal;
4391}
4392
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004393}; // namespace android