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