blob: 3376e188555e6f875f171846c62dce3700b604e1 [file] [log] [blame]
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001/*
2** Copyright 2008, Google Inc.
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303** Copyright (c) 2009, Code Aurora Forum. All rights reserved.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18//#define LOG_NDEBUG 0
Mohan Kandrabad0eaa2010-02-04 15:11:54 -080019#define LOG_NIDEBUG 0
Priya Komarlingamb85535d2009-11-30 13:06:01 -080020#define LOG_TAG "QualcommCameraHardware"
21#include <utils/Log.h>
22
23#include "QualcommCameraHardware.h"
24
25#include <utils/Errors.h>
26#include <utils/threads.h>
27#include <binder/MemoryHeapPmem.h>
28#include <utils/String16.h>
29#include <sys/types.h>
30#include <sys/stat.h>
31#include <unistd.h>
Sravankb4f5f1c2010-01-21 11:06:17 +053032#include <fcntl.h>
Apurva Rajguru8d1773b2009-12-02 14:21:23 -080033#include <cutils/properties.h>
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -080034#include <math.h>
Priya Komarlingamb85535d2009-11-30 13:06:01 -080035#if HAVE_ANDROID_OS
36#include <linux/android_pmem.h>
37#endif
38#include <linux/ioctl.h>
39#include <ui/CameraParameters.h>
40
Mohan Kandra284966d2010-01-05 13:39:15 -080041#include "linux/msm_mdp.h"
42#include <linux/fb.h>
43
Priya Komarlingamb85535d2009-11-30 13:06:01 -080044#define LIKELY(exp) __builtin_expect(!!(exp), 1)
45#define UNLIKELY(exp) __builtin_expect(!!(exp), 0)
46
47extern "C" {
48#include <fcntl.h>
49#include <time.h>
50#include <pthread.h>
51#include <stdio.h>
52#include <string.h>
53#include <unistd.h>
54#include <termios.h>
55#include <assert.h>
56#include <stdlib.h>
57#include <ctype.h>
58#include <signal.h>
59#include <errno.h>
60#include <sys/mman.h>
61#include <sys/system_properties.h>
62#include <sys/time.h>
63#include <stdlib.h>
64
65#include <media/msm_camera.h>
66
67#include <camera.h>
68#include <camframe.h>
69#include <mm-still/jpeg/jpege.h>
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -080070#include <jpeg_encoder.h>
Priya Komarlingamb85535d2009-11-30 13:06:01 -080071
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -080072#define DEFAULT_PICTURE_WIDTH 1024
73#define DEFAULT_PICTURE_HEIGHT 768
Priya Komarlingamb85535d2009-11-30 13:06:01 -080074#define THUMBNAIL_BUFFER_SIZE (THUMBNAIL_WIDTH * THUMBNAIL_HEIGHT * 3/2)
75#define MAX_ZOOM_LEVEL 5
76#define NOT_FOUND -1
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,
Srinivasan Kannan5701a942010-04-15 16:17:21 -070091 int exif_table_numEntries, int jpegPadding);
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 Kannan9c14ead2010-02-22 17:15:58 -0800163#define DEFAULT_PREVIEW_WIDTH 800
164#define DEFAULT_PREVIEW_HEIGHT 480
165
166/*
167 * Modifying preview size requires modification
168 * in bitmasks for boardproperties
169 */
170
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800171static const camera_size_type preview_sizes[] = {
Srinivasan Kannanfa7edae2009-12-16 18:02:01 -0800172 { 1280, 720 }, // 720P, reserved
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800173 { 800, 480 }, // WVGA
Srinivasan Kannan613301c2010-02-10 17:08:53 -0800174 { 768, 432 },
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800175 { 720, 480 },
176 { 640, 480 }, // VGA
177 { 576, 432 },
178 { 480, 320 }, // HVGA
179 { 384, 288 },
180 { 352, 288 }, // CIF
181 { 320, 240 }, // QVGA
182 { 240, 160 }, // SQVGA
183 { 176, 144 }, // QCIF
184};
185#define PREVIEW_SIZE_COUNT (sizeof(preview_sizes)/sizeof(camera_size_type))
186
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -0800187static camera_size_type supportedPreviewSizes[PREVIEW_SIZE_COUNT];
188static unsigned int previewSizeCount;
189
190board_property boardProperties[] = {
191 {TARGET_MSM7625, 0x00000fff},
192 {TARGET_MSM7627, 0x000006ff},
193 {TARGET_MSM7630, 0x00000fff},
194 {TARGET_QSD8250, 0x00000fff}
195};
196
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800197//static const camera_size_type* picture_sizes;
198//static int PICTURE_SIZE_COUNT;
199/* TODO
200 * Ideally this should be a populated by lower layers.
201 * But currently this is no API to do that at lower layer.
202 * Hence populating with default sizes for now. This needs
203 * to be changed once the API is supported.
204 */
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800205//sorted on column basis
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800206static const camera_size_type picture_sizes[] = {
207 { 2592, 1944 }, // 5MP
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800208 { 2048, 1536 }, // 3MP QXGA
209 { 1920, 1080 }, //HD1080
210 { 1600, 1200 }, // 2MP UXGA
211 { 1280, 768 }, //WXGA
212 { 1280, 720 }, //HD720
213 { 1024, 768}, // 1MP XGA
214 { 800, 600 }, //SVGA
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800215 { 800, 480 }, // WVGA
216 { 640, 480 }, // VGA
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800217 { 352, 288 }, //CIF
218 { 320, 240 }, // QVGA
219 { 176, 144 } // QCIF
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800220};
221static int PICTURE_SIZE_COUNT = sizeof(picture_sizes)/sizeof(camera_size_type);
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800222static const camera_size_type * picture_sizes_ptr;
223static int supportedPictureSizesCount;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800224
Srinivasan Kannan80d878f2009-12-18 15:06:02 -0800225#ifdef Q12
226#undef Q12
227#endif
228
229#define Q12 4096
230
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -0800231static const target_map targetList [] = {
232 { "msm7625", TARGET_MSM7625 },
233 { "msm7627", TARGET_MSM7627 },
234 { "qsd8250", TARGET_QSD8250 },
235 { "msm7630", TARGET_MSM7630 }
236};
237static targetType mCurrentTarget = TARGET_MAX;
238
Srinivasan Kannan80d878f2009-12-18 15:06:02 -0800239typedef struct {
240 uint32_t aspect_ratio;
241 uint32_t width;
242 uint32_t height;
243} thumbnail_size_type;
244
245static thumbnail_size_type thumbnail_sizes[] = {
246 { 7281, 512, 288 }, //1.777778
247 { 6826, 480, 288 }, //1.666667
Kiran Kumar H Nb49af212010-02-17 15:12:17 -0800248 { 6144, 432, 288 }, //1.5
Srinivasan Kannan80d878f2009-12-18 15:06:02 -0800249 { 5461, 512, 384 }, //1.333333
250 { 5006, 352, 288 }, //1.222222
251};
252#define THUMBNAIL_SIZE_COUNT (sizeof(thumbnail_sizes)/sizeof(thumbnail_size_type))
253#define DEFAULT_THUMBNAIL_SETTING 2
254#define THUMBNAIL_WIDTH_STR "512"
255#define THUMBNAIL_HEIGHT_STR "384"
256#define THUMBNAIL_SMALL_HEIGHT 144
257
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800258static int attr_lookup(const str_map arr[], int len, const char *name)
259{
260 if (name) {
261 for (int i = 0; i < len; i++) {
262 if (!strcmp(arr[i].desc, name))
263 return arr[i].val;
264 }
265 }
266 return NOT_FOUND;
267}
268
269// round to the next power of two
270static inline unsigned clp2(unsigned x)
271{
272 x = x - 1;
273 x = x | (x >> 1);
274 x = x | (x >> 2);
275 x = x | (x >> 4);
276 x = x | (x >> 8);
277 x = x | (x >>16);
278 return x + 1;
279}
280
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -0800281static int exif_table_numEntries = 0;
282#define MAX_EXIF_TABLE_ENTRIES 7
283exif_tags_info_t exif_data[MAX_EXIF_TABLE_ENTRIES];
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -0800284static zoom_crop_info zoomCropInfo;
285static void *mLastQueuedFrame = NULL;
Apurva Rajguruc73c1722010-04-15 17:39:11 -0700286#define RECORD_BUFFERS_7x30 8
287#define RECORD_BUFFERS_8x50 6
288static int kRecordBufferCount;
289
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -0800290
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800291namespace android {
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800292
293static const int PICTURE_FORMAT_JPEG = 1;
294static const int PICTURE_FORMAT_RAW = 2;
295
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800296// from aeecamera.h
297static const str_map whitebalance[] = {
298 { CameraParameters::WHITE_BALANCE_AUTO, CAMERA_WB_AUTO },
299 { CameraParameters::WHITE_BALANCE_INCANDESCENT, CAMERA_WB_INCANDESCENT },
300 { CameraParameters::WHITE_BALANCE_FLUORESCENT, CAMERA_WB_FLUORESCENT },
301 { CameraParameters::WHITE_BALANCE_DAYLIGHT, CAMERA_WB_DAYLIGHT },
302 { CameraParameters::WHITE_BALANCE_CLOUDY_DAYLIGHT, CAMERA_WB_CLOUDY_DAYLIGHT }
303};
304
305// from camera_effect_t. This list must match aeecamera.h
306static const str_map effects[] = {
307 { CameraParameters::EFFECT_NONE, CAMERA_EFFECT_OFF },
308 { CameraParameters::EFFECT_MONO, CAMERA_EFFECT_MONO },
309 { CameraParameters::EFFECT_NEGATIVE, CAMERA_EFFECT_NEGATIVE },
310 { CameraParameters::EFFECT_SOLARIZE, CAMERA_EFFECT_SOLARIZE },
311 { CameraParameters::EFFECT_SEPIA, CAMERA_EFFECT_SEPIA },
312 { CameraParameters::EFFECT_POSTERIZE, CAMERA_EFFECT_POSTERIZE },
313 { CameraParameters::EFFECT_WHITEBOARD, CAMERA_EFFECT_WHITEBOARD },
314 { CameraParameters::EFFECT_BLACKBOARD, CAMERA_EFFECT_BLACKBOARD },
315 { CameraParameters::EFFECT_AQUA, CAMERA_EFFECT_AQUA }
316};
317
318// from qcamera/common/camera.h
Apurva Rajguru55562b02009-12-03 12:25:35 -0800319static const str_map autoexposure[] = {
320 { CameraParameters::AUTO_EXPOSURE_FRAME_AVG, CAMERA_AEC_FRAME_AVERAGE },
321 { CameraParameters::AUTO_EXPOSURE_CENTER_WEIGHTED, CAMERA_AEC_CENTER_WEIGHTED },
322 { CameraParameters::AUTO_EXPOSURE_SPOT_METERING, CAMERA_AEC_SPOT_METERING }
323};
324
325// from qcamera/common/camera.h
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800326static const str_map antibanding[] = {
327 { CameraParameters::ANTIBANDING_OFF, CAMERA_ANTIBANDING_OFF },
328 { CameraParameters::ANTIBANDING_50HZ, CAMERA_ANTIBANDING_50HZ },
329 { CameraParameters::ANTIBANDING_60HZ, CAMERA_ANTIBANDING_60HZ },
330 { CameraParameters::ANTIBANDING_AUTO, CAMERA_ANTIBANDING_AUTO }
331};
332
333/* Mapping from MCC to antibanding type */
334struct country_map {
335 uint32_t country_code;
336 camera_antibanding_type type;
337};
338
339static struct country_map country_numeric[] = {
340 { 202, CAMERA_ANTIBANDING_50HZ }, // Greece
341 { 204, CAMERA_ANTIBANDING_50HZ }, // Netherlands
342 { 206, CAMERA_ANTIBANDING_50HZ }, // Belgium
343 { 208, CAMERA_ANTIBANDING_50HZ }, // France
344 { 212, CAMERA_ANTIBANDING_50HZ }, // Monaco
345 { 213, CAMERA_ANTIBANDING_50HZ }, // Andorra
346 { 214, CAMERA_ANTIBANDING_50HZ }, // Spain
347 { 216, CAMERA_ANTIBANDING_50HZ }, // Hungary
348 { 219, CAMERA_ANTIBANDING_50HZ }, // Croatia
349 { 220, CAMERA_ANTIBANDING_50HZ }, // Serbia
350 { 222, CAMERA_ANTIBANDING_50HZ }, // Italy
351 { 226, CAMERA_ANTIBANDING_50HZ }, // Romania
352 { 228, CAMERA_ANTIBANDING_50HZ }, // Switzerland
353 { 230, CAMERA_ANTIBANDING_50HZ }, // Czech Republic
354 { 231, CAMERA_ANTIBANDING_50HZ }, // Slovakia
355 { 232, CAMERA_ANTIBANDING_50HZ }, // Austria
356 { 234, CAMERA_ANTIBANDING_50HZ }, // United Kingdom
357 { 235, CAMERA_ANTIBANDING_50HZ }, // United Kingdom
358 { 238, CAMERA_ANTIBANDING_50HZ }, // Denmark
359 { 240, CAMERA_ANTIBANDING_50HZ }, // Sweden
360 { 242, CAMERA_ANTIBANDING_50HZ }, // Norway
361 { 244, CAMERA_ANTIBANDING_50HZ }, // Finland
362 { 246, CAMERA_ANTIBANDING_50HZ }, // Lithuania
363 { 247, CAMERA_ANTIBANDING_50HZ }, // Latvia
364 { 248, CAMERA_ANTIBANDING_50HZ }, // Estonia
365 { 250, CAMERA_ANTIBANDING_50HZ }, // Russian Federation
366 { 255, CAMERA_ANTIBANDING_50HZ }, // Ukraine
367 { 257, CAMERA_ANTIBANDING_50HZ }, // Belarus
368 { 259, CAMERA_ANTIBANDING_50HZ }, // Moldova
369 { 260, CAMERA_ANTIBANDING_50HZ }, // Poland
370 { 262, CAMERA_ANTIBANDING_50HZ }, // Germany
371 { 266, CAMERA_ANTIBANDING_50HZ }, // Gibraltar
372 { 268, CAMERA_ANTIBANDING_50HZ }, // Portugal
373 { 270, CAMERA_ANTIBANDING_50HZ }, // Luxembourg
374 { 272, CAMERA_ANTIBANDING_50HZ }, // Ireland
375 { 274, CAMERA_ANTIBANDING_50HZ }, // Iceland
376 { 276, CAMERA_ANTIBANDING_50HZ }, // Albania
377 { 278, CAMERA_ANTIBANDING_50HZ }, // Malta
378 { 280, CAMERA_ANTIBANDING_50HZ }, // Cyprus
379 { 282, CAMERA_ANTIBANDING_50HZ }, // Georgia
380 { 283, CAMERA_ANTIBANDING_50HZ }, // Armenia
381 { 284, CAMERA_ANTIBANDING_50HZ }, // Bulgaria
382 { 286, CAMERA_ANTIBANDING_50HZ }, // Turkey
383 { 288, CAMERA_ANTIBANDING_50HZ }, // Faroe Islands
384 { 290, CAMERA_ANTIBANDING_50HZ }, // Greenland
385 { 293, CAMERA_ANTIBANDING_50HZ }, // Slovenia
386 { 294, CAMERA_ANTIBANDING_50HZ }, // Macedonia
387 { 295, CAMERA_ANTIBANDING_50HZ }, // Liechtenstein
388 { 297, CAMERA_ANTIBANDING_50HZ }, // Montenegro
389 { 302, CAMERA_ANTIBANDING_60HZ }, // Canada
390 { 310, CAMERA_ANTIBANDING_60HZ }, // United States of America
391 { 311, CAMERA_ANTIBANDING_60HZ }, // United States of America
392 { 312, CAMERA_ANTIBANDING_60HZ }, // United States of America
393 { 313, CAMERA_ANTIBANDING_60HZ }, // United States of America
394 { 314, CAMERA_ANTIBANDING_60HZ }, // United States of America
395 { 315, CAMERA_ANTIBANDING_60HZ }, // United States of America
396 { 316, CAMERA_ANTIBANDING_60HZ }, // United States of America
397 { 330, CAMERA_ANTIBANDING_60HZ }, // Puerto Rico
398 { 334, CAMERA_ANTIBANDING_60HZ }, // Mexico
399 { 338, CAMERA_ANTIBANDING_50HZ }, // Jamaica
400 { 340, CAMERA_ANTIBANDING_50HZ }, // Martinique
401 { 342, CAMERA_ANTIBANDING_50HZ }, // Barbados
402 { 346, CAMERA_ANTIBANDING_60HZ }, // Cayman Islands
403 { 350, CAMERA_ANTIBANDING_60HZ }, // Bermuda
404 { 352, CAMERA_ANTIBANDING_50HZ }, // Grenada
405 { 354, CAMERA_ANTIBANDING_60HZ }, // Montserrat
406 { 362, CAMERA_ANTIBANDING_50HZ }, // Netherlands Antilles
407 { 363, CAMERA_ANTIBANDING_60HZ }, // Aruba
408 { 364, CAMERA_ANTIBANDING_60HZ }, // Bahamas
409 { 365, CAMERA_ANTIBANDING_60HZ }, // Anguilla
410 { 366, CAMERA_ANTIBANDING_50HZ }, // Dominica
411 { 368, CAMERA_ANTIBANDING_60HZ }, // Cuba
412 { 370, CAMERA_ANTIBANDING_60HZ }, // Dominican Republic
413 { 372, CAMERA_ANTIBANDING_60HZ }, // Haiti
414 { 401, CAMERA_ANTIBANDING_50HZ }, // Kazakhstan
415 { 402, CAMERA_ANTIBANDING_50HZ }, // Bhutan
416 { 404, CAMERA_ANTIBANDING_50HZ }, // India
417 { 405, CAMERA_ANTIBANDING_50HZ }, // India
418 { 410, CAMERA_ANTIBANDING_50HZ }, // Pakistan
419 { 413, CAMERA_ANTIBANDING_50HZ }, // Sri Lanka
420 { 414, CAMERA_ANTIBANDING_50HZ }, // Myanmar
421 { 415, CAMERA_ANTIBANDING_50HZ }, // Lebanon
422 { 416, CAMERA_ANTIBANDING_50HZ }, // Jordan
423 { 417, CAMERA_ANTIBANDING_50HZ }, // Syria
424 { 418, CAMERA_ANTIBANDING_50HZ }, // Iraq
425 { 419, CAMERA_ANTIBANDING_50HZ }, // Kuwait
426 { 420, CAMERA_ANTIBANDING_60HZ }, // Saudi Arabia
427 { 421, CAMERA_ANTIBANDING_50HZ }, // Yemen
428 { 422, CAMERA_ANTIBANDING_50HZ }, // Oman
429 { 424, CAMERA_ANTIBANDING_50HZ }, // United Arab Emirates
430 { 425, CAMERA_ANTIBANDING_50HZ }, // Israel
431 { 426, CAMERA_ANTIBANDING_50HZ }, // Bahrain
432 { 427, CAMERA_ANTIBANDING_50HZ }, // Qatar
433 { 428, CAMERA_ANTIBANDING_50HZ }, // Mongolia
434 { 429, CAMERA_ANTIBANDING_50HZ }, // Nepal
435 { 430, CAMERA_ANTIBANDING_50HZ }, // United Arab Emirates
436 { 431, CAMERA_ANTIBANDING_50HZ }, // United Arab Emirates
437 { 432, CAMERA_ANTIBANDING_50HZ }, // Iran
438 { 434, CAMERA_ANTIBANDING_50HZ }, // Uzbekistan
439 { 436, CAMERA_ANTIBANDING_50HZ }, // Tajikistan
440 { 437, CAMERA_ANTIBANDING_50HZ }, // Kyrgyz Rep
441 { 438, CAMERA_ANTIBANDING_50HZ }, // Turkmenistan
442 { 440, CAMERA_ANTIBANDING_60HZ }, // Japan
443 { 441, CAMERA_ANTIBANDING_60HZ }, // Japan
444 { 452, CAMERA_ANTIBANDING_50HZ }, // Vietnam
445 { 454, CAMERA_ANTIBANDING_50HZ }, // Hong Kong
446 { 455, CAMERA_ANTIBANDING_50HZ }, // Macao
447 { 456, CAMERA_ANTIBANDING_50HZ }, // Cambodia
448 { 457, CAMERA_ANTIBANDING_50HZ }, // Laos
449 { 460, CAMERA_ANTIBANDING_50HZ }, // China
450 { 466, CAMERA_ANTIBANDING_60HZ }, // Taiwan
451 { 470, CAMERA_ANTIBANDING_50HZ }, // Bangladesh
452 { 472, CAMERA_ANTIBANDING_50HZ }, // Maldives
453 { 502, CAMERA_ANTIBANDING_50HZ }, // Malaysia
454 { 505, CAMERA_ANTIBANDING_50HZ }, // Australia
455 { 510, CAMERA_ANTIBANDING_50HZ }, // Indonesia
456 { 514, CAMERA_ANTIBANDING_50HZ }, // East Timor
457 { 515, CAMERA_ANTIBANDING_60HZ }, // Philippines
458 { 520, CAMERA_ANTIBANDING_50HZ }, // Thailand
459 { 525, CAMERA_ANTIBANDING_50HZ }, // Singapore
460 { 530, CAMERA_ANTIBANDING_50HZ }, // New Zealand
461 { 535, CAMERA_ANTIBANDING_60HZ }, // Guam
462 { 536, CAMERA_ANTIBANDING_50HZ }, // Nauru
463 { 537, CAMERA_ANTIBANDING_50HZ }, // Papua New Guinea
464 { 539, CAMERA_ANTIBANDING_50HZ }, // Tonga
465 { 541, CAMERA_ANTIBANDING_50HZ }, // Vanuatu
466 { 542, CAMERA_ANTIBANDING_50HZ }, // Fiji
467 { 544, CAMERA_ANTIBANDING_60HZ }, // American Samoa
468 { 545, CAMERA_ANTIBANDING_50HZ }, // Kiribati
469 { 546, CAMERA_ANTIBANDING_50HZ }, // New Caledonia
470 { 548, CAMERA_ANTIBANDING_50HZ }, // Cook Islands
471 { 602, CAMERA_ANTIBANDING_50HZ }, // Egypt
472 { 603, CAMERA_ANTIBANDING_50HZ }, // Algeria
473 { 604, CAMERA_ANTIBANDING_50HZ }, // Morocco
474 { 605, CAMERA_ANTIBANDING_50HZ }, // Tunisia
475 { 606, CAMERA_ANTIBANDING_50HZ }, // Libya
476 { 607, CAMERA_ANTIBANDING_50HZ }, // Gambia
477 { 608, CAMERA_ANTIBANDING_50HZ }, // Senegal
478 { 609, CAMERA_ANTIBANDING_50HZ }, // Mauritania
479 { 610, CAMERA_ANTIBANDING_50HZ }, // Mali
480 { 611, CAMERA_ANTIBANDING_50HZ }, // Guinea
481 { 613, CAMERA_ANTIBANDING_50HZ }, // Burkina Faso
482 { 614, CAMERA_ANTIBANDING_50HZ }, // Niger
483 { 616, CAMERA_ANTIBANDING_50HZ }, // Benin
484 { 617, CAMERA_ANTIBANDING_50HZ }, // Mauritius
485 { 618, CAMERA_ANTIBANDING_50HZ }, // Liberia
486 { 619, CAMERA_ANTIBANDING_50HZ }, // Sierra Leone
487 { 620, CAMERA_ANTIBANDING_50HZ }, // Ghana
488 { 621, CAMERA_ANTIBANDING_50HZ }, // Nigeria
489 { 622, CAMERA_ANTIBANDING_50HZ }, // Chad
490 { 623, CAMERA_ANTIBANDING_50HZ }, // Central African Republic
491 { 624, CAMERA_ANTIBANDING_50HZ }, // Cameroon
492 { 625, CAMERA_ANTIBANDING_50HZ }, // Cape Verde
493 { 627, CAMERA_ANTIBANDING_50HZ }, // Equatorial Guinea
494 { 631, CAMERA_ANTIBANDING_50HZ }, // Angola
495 { 633, CAMERA_ANTIBANDING_50HZ }, // Seychelles
496 { 634, CAMERA_ANTIBANDING_50HZ }, // Sudan
497 { 636, CAMERA_ANTIBANDING_50HZ }, // Ethiopia
498 { 637, CAMERA_ANTIBANDING_50HZ }, // Somalia
499 { 638, CAMERA_ANTIBANDING_50HZ }, // Djibouti
500 { 639, CAMERA_ANTIBANDING_50HZ }, // Kenya
501 { 640, CAMERA_ANTIBANDING_50HZ }, // Tanzania
502 { 641, CAMERA_ANTIBANDING_50HZ }, // Uganda
503 { 642, CAMERA_ANTIBANDING_50HZ }, // Burundi
504 { 643, CAMERA_ANTIBANDING_50HZ }, // Mozambique
505 { 645, CAMERA_ANTIBANDING_50HZ }, // Zambia
506 { 646, CAMERA_ANTIBANDING_50HZ }, // Madagascar
507 { 647, CAMERA_ANTIBANDING_50HZ }, // France
508 { 648, CAMERA_ANTIBANDING_50HZ }, // Zimbabwe
509 { 649, CAMERA_ANTIBANDING_50HZ }, // Namibia
510 { 650, CAMERA_ANTIBANDING_50HZ }, // Malawi
511 { 651, CAMERA_ANTIBANDING_50HZ }, // Lesotho
512 { 652, CAMERA_ANTIBANDING_50HZ }, // Botswana
513 { 653, CAMERA_ANTIBANDING_50HZ }, // Swaziland
514 { 654, CAMERA_ANTIBANDING_50HZ }, // Comoros
515 { 655, CAMERA_ANTIBANDING_50HZ }, // South Africa
516 { 657, CAMERA_ANTIBANDING_50HZ }, // Eritrea
517 { 702, CAMERA_ANTIBANDING_60HZ }, // Belize
518 { 704, CAMERA_ANTIBANDING_60HZ }, // Guatemala
519 { 706, CAMERA_ANTIBANDING_60HZ }, // El Salvador
520 { 708, CAMERA_ANTIBANDING_60HZ }, // Honduras
521 { 710, CAMERA_ANTIBANDING_60HZ }, // Nicaragua
522 { 712, CAMERA_ANTIBANDING_60HZ }, // Costa Rica
523 { 714, CAMERA_ANTIBANDING_60HZ }, // Panama
524 { 722, CAMERA_ANTIBANDING_50HZ }, // Argentina
525 { 724, CAMERA_ANTIBANDING_60HZ }, // Brazil
526 { 730, CAMERA_ANTIBANDING_50HZ }, // Chile
527 { 732, CAMERA_ANTIBANDING_60HZ }, // Colombia
528 { 734, CAMERA_ANTIBANDING_60HZ }, // Venezuela
529 { 736, CAMERA_ANTIBANDING_50HZ }, // Bolivia
530 { 738, CAMERA_ANTIBANDING_60HZ }, // Guyana
531 { 740, CAMERA_ANTIBANDING_60HZ }, // Ecuador
532 { 742, CAMERA_ANTIBANDING_50HZ }, // French Guiana
533 { 744, CAMERA_ANTIBANDING_50HZ }, // Paraguay
534 { 746, CAMERA_ANTIBANDING_60HZ }, // Suriname
535 { 748, CAMERA_ANTIBANDING_50HZ }, // Uruguay
536 { 750, CAMERA_ANTIBANDING_50HZ }, // Falkland Islands
537};
538
539#define country_number (sizeof(country_numeric) / sizeof(country_map))
540
541/* Look up pre-sorted antibanding_type table by current MCC. */
542static camera_antibanding_type camera_get_location(void) {
543 char value[PROP_VALUE_MAX];
544 char country_value[PROP_VALUE_MAX];
545 uint32_t country_code, count;
546 memset(value, 0x00, sizeof(value));
547 memset(country_value, 0x00, sizeof(country_value));
548 if (!__system_property_get("gsm.operator.numeric", value)) {
549 return CAMERA_ANTIBANDING_60HZ;
550 }
551 memcpy(country_value, value, 3);
552 country_code = atoi(country_value);
553 LOGD("value:%s, country value:%s, country code:%d\n",
554 value, country_value, country_code);
555 int left = 0;
556 int right = country_number - 1;
557 while (left <= right) {
558 int index = (left + right) >> 1;
559 if (country_numeric[index].country_code == country_code)
560 return country_numeric[index].type;
561 else if (country_numeric[index].country_code > country_code)
562 right = index - 1;
563 else
564 left = index + 1;
565 }
566 return CAMERA_ANTIBANDING_60HZ;
567}
568
569// from camera.h, led_mode_t
570static const str_map flash[] = {
571 { CameraParameters::FLASH_MODE_OFF, LED_MODE_OFF },
572 { CameraParameters::FLASH_MODE_AUTO, LED_MODE_AUTO },
573 { CameraParameters::FLASH_MODE_ON, LED_MODE_ON }
574};
575
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530576// from mm-camera/common/camera.h.
577static const str_map iso[] = {
578 { CameraParameters::ISO_AUTO, CAMERA_ISO_AUTO},
579 { CameraParameters::ISO_HJR, CAMERA_ISO_DEBLUR},
580 { CameraParameters::ISO_100, CAMERA_ISO_100},
581 { CameraParameters::ISO_200, CAMERA_ISO_200},
582 { CameraParameters::ISO_400, CAMERA_ISO_400},
Mohan Kandra61db0d02010-04-28 18:28:30 -0700583 { CameraParameters::ISO_800, CAMERA_ISO_800 },
584 { CameraParameters::ISO_1600, CAMERA_ISO_1600 }
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530585};
586
587
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800588#define DONT_CARE 0
589static const str_map focus_modes[] = {
Srinivasan Kannan71229622009-12-04 12:05:58 -0800590 { CameraParameters::FOCUS_MODE_AUTO, AF_MODE_AUTO},
591 { CameraParameters::FOCUS_MODE_INFINITY, DONT_CARE },
592 { CameraParameters::FOCUS_MODE_NORMAL, AF_MODE_NORMAL },
593 { CameraParameters::FOCUS_MODE_MACRO, AF_MODE_MACRO }
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800594};
595
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530596static const str_map lensshade[] = {
597 { CameraParameters::LENSSHADE_ENABLE, TRUE },
598 { CameraParameters::LENSSHADE_DISABLE, FALSE }
599};
600
Srinivasan Kannan71229622009-12-04 12:05:58 -0800601struct SensorType {
602 const char *name;
603 int rawPictureWidth;
604 int rawPictureHeight;
605 bool hasAutoFocusSupport;
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800606 int max_supported_snapshot_width;
607 int max_supported_snapshot_height;
Apurva Rajguruffe264a2010-03-09 13:50:53 -0800608 int bitMask;
Srinivasan Kannan71229622009-12-04 12:05:58 -0800609};
610
611static SensorType sensorTypes[] = {
Apurva Rajguruffe264a2010-03-09 13:50:53 -0800612 { "5mp", 2608, 1960, true, 2592, 1944,0x00000fff },
613 { "3mp", 2064, 1544, false, 2048, 1536,0x000007ff },
614 { "2mp", 3200, 1200, false, 1600, 1200,0x000007ff } };
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800615
Srinivasan Kannan71229622009-12-04 12:05:58 -0800616
617static SensorType * sensorType;
618
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800619static const str_map picture_formats[] = {
620 {CameraParameters::PIXEL_FORMAT_JPEG, PICTURE_FORMAT_JPEG},
621 {CameraParameters::PIXEL_FORMAT_RAW, PICTURE_FORMAT_RAW}
622};
623
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800624static bool parameter_string_initialized = false;
625static String8 preview_size_values;
626static String8 picture_size_values;
627static String8 antibanding_values;
628static String8 effect_values;
Apurva Rajguru55562b02009-12-03 12:25:35 -0800629static String8 autoexposure_values;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800630static String8 whitebalance_values;
631static String8 flash_values;
632static String8 focus_mode_values;
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530633static String8 iso_values;
634static String8 lensshade_values;
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800635static String8 picture_format_values;
636
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800637static String8 create_sizes_str(const camera_size_type *sizes, int len) {
638 String8 str;
639 char buffer[32];
640
641 if (len > 0) {
642 sprintf(buffer, "%dx%d", sizes[0].width, sizes[0].height);
643 str.append(buffer);
644 }
645 for (int i = 1; i < len; i++) {
646 sprintf(buffer, ",%dx%d", sizes[i].width, sizes[i].height);
647 str.append(buffer);
648 }
649 return str;
650}
651
652static String8 create_values_str(const str_map *values, int len) {
653 String8 str;
654
655 if (len > 0) {
656 str.append(values[0].desc);
657 }
658 for (int i = 1; i < len; i++) {
659 str.append(",");
660 str.append(values[i].desc);
661 }
662 return str;
663}
664
Sravankb4f5f1c2010-01-21 11:06:17 +0530665extern "C" {
666//------------------------------------------------------------------------
667// : 720p busyQ funcitons
668// --------------------------------------------------------------------
669static struct fifo_queue g_busy_frame_queue =
670 {0, 0, 0, PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER};
671};
672/*===========================================================================
673 * FUNCTION cam_frame_wait_video
674 *
675 * DESCRIPTION this function waits a video in the busy queue
676 * ===========================================================================*/
677
678static void cam_frame_wait_video (void)
679{
680 LOGV("cam_frame_wait_video E ");
681 if ((g_busy_frame_queue.num_of_frames) <=0){
682 pthread_cond_wait(&(g_busy_frame_queue.wait), &(g_busy_frame_queue.mut));
683 }
684 LOGV("cam_frame_wait_video X");
685 return;
686}
687
688/*===========================================================================
689 * FUNCTION cam_frame_flush_video
690 *
691 * DESCRIPTION this function deletes all the buffers in busy queue
692 * ===========================================================================*/
693void cam_frame_flush_video (void)
694{
695 LOGV("cam_frame_flush_video: in n = %d\n", g_busy_frame_queue.num_of_frames);
696 pthread_mutex_lock(&(g_busy_frame_queue.mut));
697
698 while (g_busy_frame_queue.front)
699 {
700 //dequeue from the busy queue
701 struct fifo_node *node = dequeue (&g_busy_frame_queue);
702 if(node)
703 free(node);
704
705 LOGV("cam_frame_flush_video: node \n");
706 }
707 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
708 LOGV("cam_frame_flush_video: out n = %d\n", g_busy_frame_queue.num_of_frames);
709 return ;
710}
711/*===========================================================================
712 * FUNCTION cam_frame_get_video
713 *
714 * DESCRIPTION this function returns a video frame from the head
715 * ===========================================================================*/
716static struct msm_frame * cam_frame_get_video()
717{
718 struct msm_frame *p = NULL;
719 LOGV("cam_frame_get_video... in\n");
720 LOGV("cam_frame_get_video... got lock\n");
721 if (g_busy_frame_queue.front)
722 {
723 //dequeue
724 struct fifo_node *node = dequeue (&g_busy_frame_queue);
725 if (node)
726 {
727 p = (struct msm_frame *)node->f;
728 free (node);
729 }
730 LOGV("cam_frame_get_video... out = %x\n", p->buffer);
731 }
732 return p;
733}
734
735/*===========================================================================
736 * FUNCTION cam_frame_post_video
737 *
738 * DESCRIPTION this function add a busy video frame to the busy queue tails
739 * ===========================================================================*/
740static void cam_frame_post_video (struct msm_frame *p)
741{
742 if (!p)
743 {
744 LOGE("post video , buffer is null");
745 return;
746 }
747 LOGV("cam_frame_post_video... in = %x\n", (unsigned int)(p->buffer));
748 pthread_mutex_lock(&(g_busy_frame_queue.mut));
749 LOGV("post_video got lock. q count before enQ %d", g_busy_frame_queue.num_of_frames);
750 //enqueue to busy queue
751 struct fifo_node *node = (struct fifo_node *)malloc (sizeof (struct fifo_node));
752 if (node)
753 {
754 LOGV(" post video , enqueing in busy queue");
755 node->f = p;
756 node->next = NULL;
757 enqueue (&g_busy_frame_queue, node);
758 LOGV("post_video got lock. q count after enQ %d", g_busy_frame_queue.num_of_frames);
759 }
760 else
761 {
762 LOGE("cam_frame_post_video error... out of memory\n");
763 }
764
765 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
766 pthread_cond_signal(&(g_busy_frame_queue.wait));
767
768 LOGV("cam_frame_post_video... out = %x\n", p->buffer);
769
770 return;
771}
772
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -0800773void QualcommCameraHardware::storeTargetType(void) {
774 char mDeviceName[PROPERTY_VALUE_MAX];
775 property_get("ro.product.device",mDeviceName," ");
776 mCurrentTarget = TARGET_MAX;
777 for( int i = 0; i < TARGET_MAX ; i++) {
778 if( !strncmp(mDeviceName, targetList[i].targetStr, 7)) {
779 mCurrentTarget = targetList[i].targetEnum;
780 break;
781 }
782 }
783 LOGV(" Storing the current target type as %d ", mCurrentTarget );
784 return;
785}
786
Sravankb4f5f1c2010-01-21 11:06:17 +0530787//-------------------------------------------------------------------------------------
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800788static Mutex singleton_lock;
789static bool singleton_releasing;
790static Condition singleton_wait;
791
792static void receive_camframe_callback(struct msm_frame *frame);
Sravankb4f5f1c2010-01-21 11:06:17 +0530793static void receive_camframe_video_callback(struct msm_frame *frame); // 720p
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800794static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size);
795static void receive_jpeg_callback(jpeg_event_t status);
796static void receive_shutter_callback(common_crop_t *crop);
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800797static void receive_camframetimeout_callback(void);
Mohan Kandra284966d2010-01-05 13:39:15 -0800798static int fb_fd = -1;
799static int32_t mMaxZoom = 0;
800static bool native_get_maxzoom(int camfd, void *pZm);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800801
Mohan Kandrad9efed92010-01-15 19:08:39 -0800802static int dstOffset = 0;
803
Brian Steuer07704892009-12-18 18:07:33 -0800804static int camerafd;
805pthread_t w_thread;
806
807void *opencamerafd(void *data) {
808 camerafd = open(MSM_CAMERA_CONTROL, O_RDWR);
809 return NULL;
810}
811
Mohan Kandrad9efed92010-01-15 19:08:39 -0800812/* When using MDP zoom, double the preview buffers. The usage of these
813 * buffers is as follows:
814 * 1. As all the buffers comes under a single FD, and at initial registration,
815 * this FD will be passed to surface flinger, surface flinger can have access
816 * to all the buffers when needed.
817 * 2. Only "kPreviewBufferCount" buffers (SrcSet) will be registered with the
818 * camera driver to receive preview frames. The remaining buffers (DstSet),
819 * will be used at HAL and by surface flinger only when crop information
820 * is present in the frame.
821 * 3. When there is no crop information, there will be no call to MDP zoom,
822 * and the buffers in SrcSet will be passed to surface flinger to display.
823 * 4. With crop information present, MDP zoom will be called, and the final
824 * data will be placed in a buffer from DstSet, and this buffer will be given
825 * to surface flinger to display.
826 */
827#define NUM_MORE_BUFS 2
828
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800829QualcommCameraHardware::QualcommCameraHardware()
830 : mParameters(),
831 mCameraRunning(false),
832 mPreviewInitialized(false),
833 mFrameThreadRunning(false),
Mohan Kandra156d0ac2010-01-25 16:59:17 -0800834 mVideoThreadRunning(false),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800835 mSnapshotThreadRunning(false),
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800836 mSnapshotFormat(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800837 mReleasedRecordingFrame(false),
838 mPreviewFrameSize(0),
839 mRawSize(0),
840 mCameraControlFd(-1),
841 mAutoFocusThreadRunning(false),
842 mAutoFocusFd(-1),
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800843 mBrightness(0),
Apurva Rajguruf12d9d22010-04-05 16:47:12 -0700844 mHJR(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800845 mInPreviewCallback(false),
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800846 mUseOverlay(0),
847 mOverlay(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800848 mMsgEnabled(0),
849 mNotifyCallback(0),
850 mDataCallback(0),
851 mDataCallbackTimestamp(0),
Mohan Kandra740cfce2010-01-07 12:58:24 -0800852 mCallbackCookie(0),
853 mDebugFps(0)
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800854{
Brian Steuer07704892009-12-18 18:07:33 -0800855
856 // Start opening camera device in a separate thread/ Since this
857 // initializes the sensor hardware, this can take a long time. So,
858 // start the process here so it will be ready by the time it's
859 // needed.
860 if ((pthread_create(&w_thread, NULL, opencamerafd, NULL)) != 0) {
861 LOGE("Camera open thread creation failed");
862 }
863
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800864 memset(&mDimension, 0, sizeof(mDimension));
865 memset(&mCrop, 0, sizeof(mCrop));
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -0800866 memset(&zoomCropInfo, 0, sizeof(zoom_crop_info));
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -0800867 storeTargetType();
Mohan Kandra740cfce2010-01-07 12:58:24 -0800868 char value[PROPERTY_VALUE_MAX];
869 property_get("persist.debug.sf.showfps", value, "0");
870 mDebugFps = atoi(value);
Apurva Rajguruc73c1722010-04-15 17:39:11 -0700871 if( mCurrentTarget == TARGET_MSM7630 ) {
Sravankb4f5f1c2010-01-21 11:06:17 +0530872 kPreviewBufferCountActual = kPreviewBufferCount;
Apurva Rajguruc73c1722010-04-15 17:39:11 -0700873 kRecordBufferCount = RECORD_BUFFERS_7x30;
874 recordframes = new msm_frame[kRecordBufferCount];
875 }
876 else {
Sravankb4f5f1c2010-01-21 11:06:17 +0530877 kPreviewBufferCountActual = kPreviewBufferCount + NUM_MORE_BUFS;
Apurva Rajguruc73c1722010-04-15 17:39:11 -0700878 if( mCurrentTarget == TARGET_QSD8250 ) {
879 kRecordBufferCount = RECORD_BUFFERS_8x50;
880 recordframes = new msm_frame[kRecordBufferCount];
881 }
882 }
Srinivasan Kannan5701a942010-04-15 16:17:21 -0700883
884 switch(mCurrentTarget){
885 case TARGET_MSM7627:
886 jpegPadding = 8;
887 break;
888 case TARGET_QSD8250:
889 case TARGET_MSM7630:
890 jpegPadding = 0;
891 break;
892 default:
893 jpegPadding = 0;
894 break;
895 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800896 LOGV("constructor EX");
897}
898
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800899
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -0800900void QualcommCameraHardware::filterPreviewSizes(){
901
Apurva Rajguruffe264a2010-03-09 13:50:53 -0800902 unsigned int boardMask = 0;
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -0800903 int prop = 0;
904 for(prop=0;prop<sizeof(boardProperties)/sizeof(board_property);prop++){
905 if(mCurrentTarget == boardProperties[prop].target){
Apurva Rajguruffe264a2010-03-09 13:50:53 -0800906 boardMask = boardProperties[prop].previewSizeMask;
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -0800907 break;
908 }
909 }
910
Apurva Rajguruffe264a2010-03-09 13:50:53 -0800911 int bitMask = boardMask & sensorType->bitMask;
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -0800912 if(bitMask){
913 unsigned int mask = 1<<(PREVIEW_SIZE_COUNT-1);
914 previewSizeCount=0;
915 unsigned int i = 0;
916 while(mask){
917 if(mask&bitMask)
918 supportedPreviewSizes[previewSizeCount++] =
919 preview_sizes[i];
920 i++;
921 mask = mask >> 1;
922 }
923 }
924}
925
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800926//filter Picture sizes based on max width and height
927void QualcommCameraHardware::filterPictureSizes(){
928 int i;
929 for(i=0;i<PICTURE_SIZE_COUNT;i++){
930 if(((picture_sizes[i].width <=
931 sensorType->max_supported_snapshot_width) &&
932 (picture_sizes[i].height <=
933 sensorType->max_supported_snapshot_height))){
934 picture_sizes_ptr = picture_sizes + i;
935 supportedPictureSizesCount = PICTURE_SIZE_COUNT - i ;
936 return ;
937 }
938 }
939}
940
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800941void QualcommCameraHardware::initDefaultParameters()
942{
943 LOGV("initDefaultParameters E");
944
945 // Initialize constant parameter strings. This will happen only once in the
946 // lifetime of the mediaserver process.
947 if (!parameter_string_initialized) {
Srinivasan Kannan71229622009-12-04 12:05:58 -0800948 findSensorType();
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800949 antibanding_values = create_values_str(
950 antibanding, sizeof(antibanding) / sizeof(str_map));
951 effect_values = create_values_str(
952 effects, sizeof(effects) / sizeof(str_map));
Apurva Rajguru55562b02009-12-03 12:25:35 -0800953 autoexposure_values = create_values_str(
954 autoexposure, sizeof(autoexposure) / sizeof(str_map));
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800955 whitebalance_values = create_values_str(
956 whitebalance, sizeof(whitebalance) / sizeof(str_map));
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -0800957
958 //filter preview sizes
959 filterPreviewSizes();
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800960 preview_size_values = create_sizes_str(
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -0800961 supportedPreviewSizes, previewSizeCount);
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800962 //filter picture sizes
963 filterPictureSizes();
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800964 picture_size_values = create_sizes_str(
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800965 picture_sizes_ptr, supportedPictureSizesCount);
966
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800967 flash_values = create_values_str(
968 flash, sizeof(flash) / sizeof(str_map));
Srinivasan Kannan71229622009-12-04 12:05:58 -0800969 if(sensorType->hasAutoFocusSupport){
970 focus_mode_values = create_values_str(
971 focus_modes, sizeof(focus_modes) / sizeof(str_map));
972 }
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530973 iso_values = create_values_str(
974 iso,sizeof(iso)/sizeof(str_map));
975 lensshade_values = create_values_str(
976 lensshade,sizeof(lensshade)/sizeof(str_map));
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800977 picture_format_values = create_values_str(
978 picture_formats, sizeof(picture_formats)/sizeof(str_map));
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800979 parameter_string_initialized = true;
980 }
981
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -0800982 mParameters.setPreviewSize(DEFAULT_PREVIEW_WIDTH, DEFAULT_PREVIEW_HEIGHT);
983 mDimension.display_width = DEFAULT_PREVIEW_WIDTH;
984 mDimension.display_height = DEFAULT_PREVIEW_HEIGHT;
985
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800986 mParameters.setPreviewFrameRate(15);
987 mParameters.setPreviewFormat("yuv420sp"); // informative
988
989 mParameters.setPictureSize(DEFAULT_PICTURE_WIDTH, DEFAULT_PICTURE_HEIGHT);
990 mParameters.setPictureFormat("jpeg"); // informative
991
Mohan Kandra785619a2010-02-01 21:52:42 -0800992 mParameters.set(CameraParameters::KEY_JPEG_QUALITY, "85"); // max quality
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800993 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH,
994 THUMBNAIL_WIDTH_STR); // informative
995 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT,
996 THUMBNAIL_HEIGHT_STR); // informative
Srinivasan Kannan80d878f2009-12-18 15:06:02 -0800997 mDimension.ui_thumbnail_width =
998 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].width;
999 mDimension.ui_thumbnail_height =
1000 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001001 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, "90");
1002
1003 mParameters.set(CameraParameters::KEY_ANTIBANDING,
Mohan Kandra785619a2010-02-01 21:52:42 -08001004 CameraParameters::ANTIBANDING_OFF);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001005 mParameters.set(CameraParameters::KEY_EFFECT,
1006 CameraParameters::EFFECT_NONE);
Apurva Rajguru55562b02009-12-03 12:25:35 -08001007 mParameters.set(CameraParameters::KEY_AUTO_EXPOSURE,
1008 CameraParameters::AUTO_EXPOSURE_FRAME_AVG);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001009 mParameters.set(CameraParameters::KEY_WHITE_BALANCE,
1010 CameraParameters::WHITE_BALANCE_AUTO);
1011 mParameters.set(CameraParameters::KEY_FOCUS_MODE,
1012 CameraParameters::FOCUS_MODE_AUTO);
Priya Komarlingam044c7b52010-01-22 18:21:23 -08001013 mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS,
1014 "yuv420sp");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001015
1016 mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES,
1017 preview_size_values.string());
1018 mParameters.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES,
1019 picture_size_values.string());
1020 mParameters.set(CameraParameters::KEY_SUPPORTED_ANTIBANDING,
1021 antibanding_values);
1022 mParameters.set(CameraParameters::KEY_SUPPORTED_EFFECTS, effect_values);
Apurva Rajguru55562b02009-12-03 12:25:35 -08001023 mParameters.set(CameraParameters::KEY_SUPPORTED_AUTO_EXPOSURE, autoexposure_values);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001024 mParameters.set(CameraParameters::KEY_SUPPORTED_WHITE_BALANCE,
1025 whitebalance_values);
1026 mParameters.set(CameraParameters::KEY_SUPPORTED_FOCUS_MODES,
1027 focus_mode_values);
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001028 mParameters.set(CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS,
1029 picture_format_values);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001030
1031 if (mSensorInfo.flash_enabled) {
1032 mParameters.set(CameraParameters::KEY_FLASH_MODE,
1033 CameraParameters::FLASH_MODE_OFF);
1034 mParameters.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES,
1035 flash_values);
1036 }
1037
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08001038 mParameters.set(CameraParameters::KEY_MAX_SHARPNESS,
1039 CAMERA_MAX_SHARPNESS);
1040 mParameters.set(CameraParameters::KEY_MAX_CONTRAST,
1041 CAMERA_MAX_CONTRAST);
1042 mParameters.set(CameraParameters::KEY_MAX_SATURATION,
1043 CAMERA_MAX_SATURATION);
1044
Apurva Rajguru07185952010-01-22 15:40:07 -08001045 mParameters.set("luma-adaptation", "3");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001046 mParameters.set("zoom-supported", "true");
1047 mParameters.set("max-zoom", MAX_ZOOM_LEVEL);
1048 mParameters.set("zoom", 0);
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001049 mParameters.set(CameraParameters::KEY_PICTURE_FORMAT,
1050 CameraParameters::PIXEL_FORMAT_JPEG);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001051
Kiran Kumar H N595970b2010-01-12 10:41:09 -08001052 mParameters.set(CameraParameters::KEY_SHARPNESS,
1053 CAMERA_DEF_SHARPNESS);
1054 mParameters.set(CameraParameters::KEY_CONTRAST,
1055 CAMERA_DEF_CONTRAST);
1056 mParameters.set(CameraParameters::KEY_SATURATION,
1057 CAMERA_DEF_SATURATION);
1058
Nishant Panditc8c1ee72009-12-03 16:24:02 +05301059 mParameters.set(CameraParameters::KEY_ISO_MODE,
1060 CameraParameters::ISO_AUTO);
1061 mParameters.set(CameraParameters::KEY_LENSSHADE,
1062 CameraParameters::LENSSHADE_ENABLE);
1063 mParameters.set(CameraParameters::KEY_SUPPORTED_ISO_MODES,
1064 iso_values);
1065 mParameters.set(CameraParameters::KEY_SUPPORTED_LENSSHADE_MODES,
1066 lensshade_values);
1067
Priyanka Kharat67cfe532010-03-29 17:28:22 -07001068 if (setParameters(mParameters) != NO_ERROR) {
1069 LOGE("Failed to set default parameters?!");
1070 }
1071
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08001072 mUseOverlay = useOverlay();
1073
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001074 /* Initialize the camframe_timeout_flag*/
1075 Mutex::Autolock l(&mCamframeTimeoutLock);
1076 camframe_timeout_flag = FALSE;
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08001077 mPostViewHeap = NULL;
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001078
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001079 LOGV("initDefaultParameters X");
1080}
1081
Srinivasan Kannan71229622009-12-04 12:05:58 -08001082void QualcommCameraHardware::findSensorType(){
1083 mDimension.picture_width = DEFAULT_PICTURE_WIDTH;
1084 mDimension.picture_height = DEFAULT_PICTURE_HEIGHT;
1085 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
1086 sizeof(cam_ctrl_dimension_t), &mDimension);
1087 if (ret) {
1088 unsigned int i;
1089 for (i = 0; i < sizeof(sensorTypes) / sizeof(SensorType); i++) {
1090 if (sensorTypes[i].rawPictureHeight
1091 == mDimension.raw_picture_height) {
1092 sensorType = sensorTypes + i;
1093 return;
1094 }
1095 }
1096 }
1097 //default to 5 mp
1098 sensorType = sensorTypes;
1099 return;
1100}
1101
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001102#define ROUND_TO_PAGE(x) (((x)+0xfff)&~0xfff)
1103
1104bool QualcommCameraHardware::startCamera()
1105{
1106 LOGV("startCamera E");
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08001107 if( mCurrentTarget == TARGET_MAX ) {
1108 LOGE(" Unable to determine the target type. Camera will not work ");
1109 return false;
1110 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001111#if DLOPEN_LIBMMCAMERA
1112 libmmcamera = ::dlopen("liboemcamera.so", RTLD_NOW);
1113 LOGV("loading liboemcamera at %p", libmmcamera);
1114 if (!libmmcamera) {
1115 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
1116 return false;
1117 }
1118
1119 *(void **)&LINK_cam_frame =
1120 ::dlsym(libmmcamera, "cam_frame");
1121 *(void **)&LINK_camframe_terminate =
1122 ::dlsym(libmmcamera, "camframe_terminate");
1123
1124 *(void **)&LINK_jpeg_encoder_init =
1125 ::dlsym(libmmcamera, "jpeg_encoder_init");
1126
1127 *(void **)&LINK_jpeg_encoder_encode =
1128 ::dlsym(libmmcamera, "jpeg_encoder_encode");
1129
1130 *(void **)&LINK_jpeg_encoder_join =
1131 ::dlsym(libmmcamera, "jpeg_encoder_join");
1132
1133 *(void **)&LINK_mmcamera_camframe_callback =
1134 ::dlsym(libmmcamera, "mmcamera_camframe_callback");
1135
1136 *LINK_mmcamera_camframe_callback = receive_camframe_callback;
1137
1138 *(void **)&LINK_mmcamera_jpegfragment_callback =
1139 ::dlsym(libmmcamera, "mmcamera_jpegfragment_callback");
1140
1141 *LINK_mmcamera_jpegfragment_callback = receive_jpeg_fragment_callback;
1142
1143 *(void **)&LINK_mmcamera_jpeg_callback =
1144 ::dlsym(libmmcamera, "mmcamera_jpeg_callback");
1145
1146 *LINK_mmcamera_jpeg_callback = receive_jpeg_callback;
1147
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001148 *(void **)&LINK_camframe_timeout_callback =
1149 ::dlsym(libmmcamera, "camframe_timeout_callback");
1150
1151 *LINK_camframe_timeout_callback = receive_camframetimeout_callback;
1152
Sravankb4f5f1c2010-01-21 11:06:17 +05301153 // 720 p new recording functions
1154 *(void **)&LINK_cam_frame_flush_free_video = ::dlsym(libmmcamera, "cam_frame_flush_free_video");
1155
1156 *(void **)&LINK_camframe_free_video = ::dlsym(libmmcamera, "cam_frame_add_free_video");
1157
1158 *(void **)&LINK_camframe_video_callback = ::dlsym(libmmcamera, "mmcamera_camframe_videocallback");
1159 *LINK_camframe_video_callback = receive_camframe_video_callback;
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08001160
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001161 *(void **)&LINK_mmcamera_shutter_callback =
1162 ::dlsym(libmmcamera, "mmcamera_shutter_callback");
1163
1164 *LINK_mmcamera_shutter_callback = receive_shutter_callback;
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08001165
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001166 *(void**)&LINK_jpeg_encoder_setMainImageQuality =
1167 ::dlsym(libmmcamera, "jpeg_encoder_setMainImageQuality");
Kiran Kumar H N8861f302010-01-05 12:01:41 -08001168
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001169 *(void**)&LINK_jpeg_encoder_setThumbnailQuality =
1170 ::dlsym(libmmcamera, "jpeg_encoder_setThumbnailQuality");
1171
1172 *(void**)&LINK_jpeg_encoder_setRotation =
1173 ::dlsym(libmmcamera, "jpeg_encoder_setRotation");
1174
Kiran Kumar H N8861f302010-01-05 12:01:41 -08001175/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001176 *(void**)&LINK_jpeg_encoder_setLocation =
1177 ::dlsym(libmmcamera, "jpeg_encoder_setLocation");
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001178*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001179 *(void **)&LINK_cam_conf =
1180 ::dlsym(libmmcamera, "cam_conf");
1181
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001182/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001183 *(void **)&LINK_default_sensor_get_snapshot_sizes =
1184 ::dlsym(libmmcamera, "default_sensor_get_snapshot_sizes");
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001185*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001186 *(void **)&LINK_launch_cam_conf_thread =
1187 ::dlsym(libmmcamera, "launch_cam_conf_thread");
1188
1189 *(void **)&LINK_release_cam_conf_thread =
1190 ::dlsym(libmmcamera, "release_cam_conf_thread");
1191
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001192/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001193 *(void **)&LINK_zoom_crop_upscale =
1194 ::dlsym(libmmcamera, "zoom_crop_upscale");
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001195*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001196
1197#else
1198 mmcamera_camframe_callback = receive_camframe_callback;
1199 mmcamera_jpegfragment_callback = receive_jpeg_fragment_callback;
1200 mmcamera_jpeg_callback = receive_jpeg_callback;
1201 mmcamera_shutter_callback = receive_shutter_callback;
1202#endif // DLOPEN_LIBMMCAMERA
1203
1204 /* The control thread is in libcamera itself. */
Brian Steuer07704892009-12-18 18:07:33 -08001205 if (pthread_join(w_thread, NULL) != 0) {
1206 LOGE("Camera open thread exit failed");
1207 return false;
1208 }
1209 mCameraControlFd = camerafd;
1210
Kiran Kumar H N585bc362010-01-19 13:04:44 -08001211 if (mCameraControlFd < 0) {
1212 LOGE("startCamera X: %s open failed: %s!",
1213 MSM_CAMERA_CONTROL,
1214 strerror(errno));
1215 return false;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001216 }
1217
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08001218 if( mCurrentTarget != TARGET_MSM7630 ){
Mohan Kandra284966d2010-01-05 13:39:15 -08001219 fb_fd = open("/dev/graphics/fb0", O_RDWR);
1220 if (fb_fd < 0) {
1221 LOGE("startCamera: fb0 open failed: %s!", strerror(errno));
1222 return FALSE;
1223 }
1224 }
1225
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001226 /* This will block until the control thread is launched. After that, sensor
1227 * information becomes available.
1228 */
1229
1230 if (LINK_launch_cam_conf_thread()) {
1231 LOGE("failed to launch the camera config thread");
1232 return false;
1233 }
1234
1235 memset(&mSensorInfo, 0, sizeof(mSensorInfo));
1236 if (ioctl(mCameraControlFd,
1237 MSM_CAM_IOCTL_GET_SENSOR_INFO,
1238 &mSensorInfo) < 0)
1239 LOGW("%s: cannot retrieve sensor info!", __FUNCTION__);
1240 else
1241 LOGI("%s: camsensor name %s, flash %d", __FUNCTION__,
1242 mSensorInfo.name, mSensorInfo.flash_enabled);
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001243/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001244 picture_sizes = LINK_default_sensor_get_snapshot_sizes(&PICTURE_SIZE_COUNT);
1245 if (!picture_sizes || !PICTURE_SIZE_COUNT) {
1246 LOGE("startCamera X: could not get snapshot sizes");
1247 return false;
1248 }
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001249*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001250 LOGV("startCamera X");
1251 return true;
1252}
1253
1254status_t QualcommCameraHardware::dump(int fd,
1255 const Vector<String16>& args) const
1256{
1257 const size_t SIZE = 256;
1258 char buffer[SIZE];
1259 String8 result;
1260
1261 // Dump internal primitives.
1262 result.append("QualcommCameraHardware::dump");
1263 snprintf(buffer, 255, "mMsgEnabled (%d)\n", mMsgEnabled);
1264 result.append(buffer);
1265 int width, height;
1266 mParameters.getPreviewSize(&width, &height);
1267 snprintf(buffer, 255, "preview width(%d) x height (%d)\n", width, height);
1268 result.append(buffer);
1269 mParameters.getPictureSize(&width, &height);
1270 snprintf(buffer, 255, "raw width(%d) x height (%d)\n", width, height);
1271 result.append(buffer);
1272 snprintf(buffer, 255,
1273 "preview frame size(%d), raw size (%d), jpeg size (%d) "
1274 "and jpeg max size (%d)\n", mPreviewFrameSize, mRawSize,
1275 mJpegSize, mJpegMaxSize);
1276 result.append(buffer);
1277 write(fd, result.string(), result.size());
1278
1279 // Dump internal objects.
Mohan Kandrad9efed92010-01-15 19:08:39 -08001280 if (mPreviewHeap != 0) {
1281 mPreviewHeap->dump(fd, args);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001282 }
1283 if (mRawHeap != 0) {
1284 mRawHeap->dump(fd, args);
1285 }
1286 if (mJpegHeap != 0) {
1287 mJpegHeap->dump(fd, args);
1288 }
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001289 if(mRawSnapshotAshmemHeap != 0 ){
1290 mRawSnapshotAshmemHeap->dump(fd, args);
1291 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001292 mParameters.dump(fd, args);
1293 return NO_ERROR;
1294}
1295
Mohan Kandra284966d2010-01-05 13:39:15 -08001296static bool native_get_maxzoom(int camfd, void *pZm)
1297{
1298 LOGV("native_get_maxzoom E");
1299
1300 struct msm_ctrl_cmd ctrlCmd;
1301 int32_t *pZoom = (int32_t *)pZm;
1302
1303 ctrlCmd.type = CAMERA_GET_PARM_MAXZOOM;
1304 ctrlCmd.timeout_ms = 5000;
1305 ctrlCmd.length = sizeof(int32_t);
1306 ctrlCmd.value = pZoom;
1307 ctrlCmd.resp_fd = camfd;
1308
1309 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1310 LOGE("native_get_maxzoom: ioctl fd %d error %s",
1311 camfd,
1312 strerror(errno));
1313 return false;
1314 }
Brian Steuerb62adbd2010-02-02 14:47:08 -08001315 LOGD("ctrlCmd.value = %d", *(int32_t *)ctrlCmd.value);
Mohan Kandra284966d2010-01-05 13:39:15 -08001316 memcpy(pZoom, (int32_t *)ctrlCmd.value, sizeof(int32_t));
1317
1318 LOGV("native_get_maxzoom X");
1319 return true;
1320}
1321
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001322static bool native_set_afmode(int camfd, isp3a_af_mode_t af_type)
1323{
1324 int rc;
1325 struct msm_ctrl_cmd ctrlCmd;
1326
1327 ctrlCmd.timeout_ms = 5000;
1328 ctrlCmd.type = CAMERA_SET_PARM_AUTO_FOCUS;
1329 ctrlCmd.length = sizeof(af_type);
1330 ctrlCmd.value = &af_type;
1331 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1332
1333 if ((rc = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0)
1334 LOGE("native_set_afmode: ioctl fd %d error %s\n",
1335 camfd,
1336 strerror(errno));
1337
1338 LOGV("native_set_afmode: ctrlCmd.status == %d\n", ctrlCmd.status);
1339 return rc >= 0 && ctrlCmd.status == CAMERA_EXIT_CB_DONE;
1340}
1341
1342static bool native_cancel_afmode(int camfd, int af_fd)
1343{
1344 int rc;
1345 struct msm_ctrl_cmd ctrlCmd;
1346
1347 ctrlCmd.timeout_ms = 0;
1348 ctrlCmd.type = CAMERA_AUTO_FOCUS_CANCEL;
1349 ctrlCmd.length = 0;
1350 ctrlCmd.value = NULL;
1351 ctrlCmd.resp_fd = -1; // there's no response fd
1352
1353 if ((rc = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND_2, &ctrlCmd)) < 0)
1354 {
1355 LOGE("native_cancel_afmode: ioctl fd %d error %s\n",
1356 camfd,
1357 strerror(errno));
1358 return false;
1359 }
1360
1361 return true;
1362}
1363
1364static bool native_start_preview(int camfd)
1365{
1366 struct msm_ctrl_cmd ctrlCmd;
1367
1368 ctrlCmd.timeout_ms = 5000;
1369 ctrlCmd.type = CAMERA_START_PREVIEW;
1370 ctrlCmd.length = 0;
1371 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1372
1373 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1374 LOGE("native_start_preview: MSM_CAM_IOCTL_CTRL_COMMAND fd %d error %s",
1375 camfd,
1376 strerror(errno));
1377 return false;
1378 }
1379
1380 return true;
1381}
1382
1383static bool native_get_picture (int camfd, common_crop_t *crop)
1384{
1385 struct msm_ctrl_cmd ctrlCmd;
1386
1387 ctrlCmd.timeout_ms = 5000;
1388 ctrlCmd.length = sizeof(common_crop_t);
1389 ctrlCmd.value = crop;
1390
1391 if(ioctl(camfd, MSM_CAM_IOCTL_GET_PICTURE, &ctrlCmd) < 0) {
1392 LOGE("native_get_picture: MSM_CAM_IOCTL_GET_PICTURE fd %d error %s",
1393 camfd,
1394 strerror(errno));
1395 return false;
1396 }
1397
1398 LOGV("crop: in1_w %d", crop->in1_w);
1399 LOGV("crop: in1_h %d", crop->in1_h);
1400 LOGV("crop: out1_w %d", crop->out1_w);
1401 LOGV("crop: out1_h %d", crop->out1_h);
1402
1403 LOGV("crop: in2_w %d", crop->in2_w);
1404 LOGV("crop: in2_h %d", crop->in2_h);
1405 LOGV("crop: out2_w %d", crop->out2_w);
1406 LOGV("crop: out2_h %d", crop->out2_h);
1407
1408 LOGV("crop: update %d", crop->update_flag);
1409
1410 return true;
1411}
1412
1413static bool native_stop_preview(int camfd)
1414{
1415 struct msm_ctrl_cmd ctrlCmd;
1416 ctrlCmd.timeout_ms = 5000;
1417 ctrlCmd.type = CAMERA_STOP_PREVIEW;
1418 ctrlCmd.length = 0;
1419 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1420
1421 if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1422 LOGE("native_stop_preview: ioctl fd %d error %s",
1423 camfd,
1424 strerror(errno));
1425 return false;
1426 }
1427
1428 return true;
1429}
1430
1431static bool native_prepare_snapshot(int camfd)
1432{
1433 int ioctlRetVal = true;
1434 struct msm_ctrl_cmd ctrlCmd;
1435
1436 ctrlCmd.timeout_ms = 1000;
1437 ctrlCmd.type = CAMERA_PREPARE_SNAPSHOT;
1438 ctrlCmd.length = 0;
1439 ctrlCmd.value = NULL;
1440 ctrlCmd.resp_fd = camfd;
1441
1442 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1443 LOGE("native_prepare_snapshot: ioctl fd %d error %s",
1444 camfd,
1445 strerror(errno));
1446 return false;
1447 }
1448 return true;
1449}
1450
1451static bool native_start_snapshot(int camfd)
1452{
1453 struct msm_ctrl_cmd ctrlCmd;
1454
1455 ctrlCmd.timeout_ms = 5000;
1456 ctrlCmd.type = CAMERA_START_SNAPSHOT;
1457 ctrlCmd.length = 0;
1458 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1459
1460 if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1461 LOGE("native_start_snapshot: ioctl fd %d error %s",
1462 camfd,
1463 strerror(errno));
1464 return false;
1465 }
1466
1467 return true;
1468}
1469
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001470static bool native_start_raw_snapshot(int camfd)
1471{
1472 int ret;
1473 struct msm_ctrl_cmd ctrlCmd;
1474
1475 ctrlCmd.timeout_ms = 1000;
1476 ctrlCmd.type = CAMERA_START_RAW_SNAPSHOT;
1477 ctrlCmd.length = 0;
1478 ctrlCmd.value = NULL;
1479 ctrlCmd.resp_fd = camfd;
1480
1481 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1482 LOGE("native_start_raw_snapshot: ioctl failed. ioctl return value "\
1483 "is %d \n", ret);
1484 return false;
1485 }
1486 return true;
1487}
1488
1489
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001490static bool native_stop_snapshot (int camfd)
1491{
1492 struct msm_ctrl_cmd ctrlCmd;
1493
1494 ctrlCmd.timeout_ms = 0;
1495 ctrlCmd.type = CAMERA_STOP_SNAPSHOT;
1496 ctrlCmd.length = 0;
1497 ctrlCmd.resp_fd = -1;
1498
1499 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND_2, &ctrlCmd) < 0) {
1500 LOGE("native_stop_snapshot: ioctl fd %d error %s",
1501 camfd,
1502 strerror(errno));
1503 return false;
1504 }
1505
1506 return true;
1507}
Sravankb4f5f1c2010-01-21 11:06:17 +05301508/*===========================================================================
1509 * FUNCTION - native_start_recording -
1510 *
1511 * DESCRIPTION:
1512 *==========================================================================*/
1513static bool native_start_recording(int camfd)
1514{
1515 int ret;
1516 struct msm_ctrl_cmd ctrlCmd;
1517
1518 ctrlCmd.timeout_ms = 1000;
1519 ctrlCmd.type = CAMERA_START_RECORDING;
1520 ctrlCmd.length = 0;
1521 ctrlCmd.value = NULL;
1522 ctrlCmd.resp_fd = camfd;
1523
1524 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1525 LOGE("native_start_recording: ioctl failed. ioctl return value "\
1526 "is %d \n", ret);
1527 return false;
1528 }
Mohan Kandraf1ebf982010-02-02 15:25:43 -08001529 LOGV("native_start_recording: ioctl good. ioctl return value is %d \n",ret);
Sravankb4f5f1c2010-01-21 11:06:17 +05301530
1531 /* TODO: Check status of postprocessing if there is any,
1532 * PP status should be in ctrlCmd */
1533
1534 return true;
1535}
1536
1537/*===========================================================================
1538 * FUNCTION - native_stop_recording -
1539 *
1540 * DESCRIPTION:
1541 *==========================================================================*/
1542static bool native_stop_recording(int camfd)
1543{
1544 int ret;
1545 struct msm_ctrl_cmd ctrlCmd;
Kiran Kumar H Nb49af212010-02-17 15:12:17 -08001546 LOGV("in native_stop_recording ");
Sravankb4f5f1c2010-01-21 11:06:17 +05301547 ctrlCmd.timeout_ms = 1000;
1548 ctrlCmd.type = CAMERA_STOP_RECORDING;
1549 ctrlCmd.length = 0;
1550 ctrlCmd.value = NULL;
1551 ctrlCmd.resp_fd = camfd;
1552
1553 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1554 LOGE("native_stop_video: ioctl failed. ioctl return value is %d \n",
1555 ret);
1556 return false;
1557 }
1558 LOGV("in native_stop_recording returned %d", ret);
1559 return true;
1560}
1561/*===========================================================================
1562 * FUNCTION - native_start_video -
1563 *
1564 * DESCRIPTION:
1565 *==========================================================================*/
1566static bool native_start_video(int camfd)
1567{
1568 int ret;
1569 struct msm_ctrl_cmd ctrlCmd;
1570
1571 ctrlCmd.timeout_ms = 1000;
1572 ctrlCmd.type = CAMERA_START_VIDEO;
1573 ctrlCmd.length = 0;
1574 ctrlCmd.value = NULL;
1575 ctrlCmd.resp_fd = camfd;
1576
1577 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1578 LOGE("native_start_video: ioctl failed. ioctl return value is %d \n",
1579 ret);
1580 return false;
1581 }
1582
1583 /* TODO: Check status of postprocessing if there is any,
1584 * PP status should be in ctrlCmd */
1585
1586 return true;
1587}
1588
1589/*===========================================================================
1590 * FUNCTION - native_stop_video -
1591 *
1592 * DESCRIPTION:
1593 *==========================================================================*/
1594static bool native_stop_video(int camfd)
1595{
1596 int ret;
1597 struct msm_ctrl_cmd ctrlCmd;
1598
1599 ctrlCmd.timeout_ms = 1000;
1600 ctrlCmd.type = CAMERA_STOP_VIDEO;
1601 ctrlCmd.length = 0;
1602 ctrlCmd.value = NULL;
1603 ctrlCmd.resp_fd = camfd;
1604
1605 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1606 LOGE("native_stop_video: ioctl failed. ioctl return value is %d \n",
1607 ret);
1608 return false;
1609 }
1610
1611 return true;
1612}
1613/*==========================================================================*/
1614
1615static cam_frame_start_parms frame_parms;
1616static int recordingState = 0;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001617
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001618static rat_t latitude[3];
1619static rat_t longitude[3];
1620static char lonref[2];
1621static char latref[2];
1622static char dateTime[20];
1623static rat_t altitude;
1624
1625static void addExifTag(exif_tag_id_t tagid, exif_tag_type_t type,
1626 uint32_t count, uint8_t copy, void *data) {
1627
1628 if(exif_table_numEntries == MAX_EXIF_TABLE_ENTRIES) {
1629 LOGE("Number of entries exceeded limit");
1630 return;
1631 }
1632
1633 int index = exif_table_numEntries;
1634 exif_data[index].tag_id = tagid;
1635 exif_data[index].tag_entry.type = type;
1636 exif_data[index].tag_entry.count = count;
1637 exif_data[index].tag_entry.copy = copy;
1638 if((type == EXIF_RATIONAL) && (count > 1))
1639 exif_data[index].tag_entry.data._rats = (rat_t *)data;
1640 if((type == EXIF_RATIONAL) && (count == 1))
1641 exif_data[index].tag_entry.data._rat = *(rat_t *)data;
1642 else if(type == EXIF_ASCII)
1643 exif_data[index].tag_entry.data._ascii = (char *)data;
1644 else if(type == EXIF_BYTE)
1645 exif_data[index].tag_entry.data._byte = *(uint8_t *)data;
1646
1647 // Increase number of entries
1648 exif_table_numEntries++;
1649}
1650
1651static void parseLatLong(const char *latlonString, int *pDegrees,
1652 int *pMinutes, int *pSeconds ) {
1653
1654 double value = atof(latlonString);
1655 value = fabs(value);
1656 int degrees = (int) value;
1657
1658 double remainder = value - degrees;
1659 int minutes = (int) (remainder * 60);
1660 int seconds = (int) (((remainder * 60) - minutes) * 60 * 1000);
1661
1662 *pDegrees = degrees;
1663 *pMinutes = minutes;
1664 *pSeconds = seconds;
1665}
1666
1667static void setLatLon(exif_tag_id_t tag, const char *latlonString) {
1668
1669 int degrees, minutes, seconds;
1670
1671 parseLatLong(latlonString, &degrees, &minutes, &seconds);
1672
1673 rat_t value[3] = { {degrees, 1},
1674 {minutes, 1},
1675 {seconds, 1000} };
1676
1677 if(tag == EXIFTAGID_GPS_LATITUDE) {
1678 memcpy(latitude, value, sizeof(latitude));
1679 addExifTag(EXIFTAGID_GPS_LATITUDE, EXIF_RATIONAL, 3,
1680 1, (void *)latitude);
1681 } else {
1682 memcpy(longitude, value, sizeof(longitude));
1683 addExifTag(EXIFTAGID_GPS_LONGITUDE, EXIF_RATIONAL, 3,
1684 1, (void *)longitude);
1685 }
1686}
1687
1688void QualcommCameraHardware::setGpsParameters() {
1689 const char *str = NULL;
1690
1691 //Set Latitude
1692 str = mParameters.get(CameraParameters::KEY_GPS_LATITUDE);
1693 if(str != NULL) {
1694 setLatLon(EXIFTAGID_GPS_LATITUDE, str);
1695 //set Latitude Ref
1696 str = NULL;
1697 str = mParameters.get(CameraParameters::KEY_GPS_LATITUDE_REF);
1698 if(str != NULL) {
1699 strncpy(latref, str, 1);
1700 latref[1] = '\0';
1701 addExifTag(EXIFTAGID_GPS_LATITUDE_REF, EXIF_ASCII, 2,
1702 1, (void *)latref);
1703 }
1704 }
1705
1706 //set Longitude
1707 str = NULL;
1708 str = mParameters.get(CameraParameters::KEY_GPS_LONGITUDE);
1709 if(str != NULL) {
1710 setLatLon(EXIFTAGID_GPS_LONGITUDE, str);
1711 //set Longitude Ref
1712 str = NULL;
1713 str = mParameters.get(CameraParameters::KEY_GPS_LONGITUDE_REF);
1714 if(str != NULL) {
1715 strncpy(lonref, str, 1);
1716 lonref[1] = '\0';
1717 addExifTag(EXIFTAGID_GPS_LONGITUDE_REF, EXIF_ASCII, 2,
1718 1, (void *)lonref);
1719 }
1720 }
1721
1722 //set Altitude
1723 str = NULL;
1724 str = mParameters.get(CameraParameters::KEY_GPS_ALTITUDE);
1725 if(str != NULL) {
1726 int value = atoi(str);
1727 rat_t alt_value = {value, 1000};
1728 memcpy(&altitude, &alt_value, sizeof(altitude));
1729 addExifTag(EXIFTAGID_GPS_ALTITUDE, EXIF_RATIONAL, 1,
1730 1, (void *)&altitude);
1731 //set AltitudeRef
1732 int ref = mParameters.getInt(CameraParameters::KEY_GPS_ALTITUDE_REF);
1733 if( !(ref < 0 || ref > 1) )
1734 addExifTag(EXIFTAGID_GPS_ALTITUDE_REF, EXIF_BYTE, 1,
1735 1, (void *)&ref);
1736 }
1737
1738
1739}
1740
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001741bool QualcommCameraHardware::native_jpeg_encode(void)
1742{
1743 int jpeg_quality = mParameters.getInt("jpeg-quality");
1744 if (jpeg_quality >= 0) {
1745 LOGV("native_jpeg_encode, current jpeg main img quality =%d",
1746 jpeg_quality);
1747 if(!LINK_jpeg_encoder_setMainImageQuality(jpeg_quality)) {
1748 LOGE("native_jpeg_encode set jpeg-quality failed");
1749 return false;
1750 }
1751 }
1752
1753 int thumbnail_quality = mParameters.getInt("jpeg-thumbnail-quality");
1754 if (thumbnail_quality >= 0) {
1755 LOGV("native_jpeg_encode, current jpeg thumbnail quality =%d",
1756 thumbnail_quality);
1757 if(!LINK_jpeg_encoder_setThumbnailQuality(thumbnail_quality)) {
1758 LOGE("native_jpeg_encode set thumbnail-quality failed");
1759 return false;
1760 }
1761 }
1762
1763 int rotation = mParameters.getInt("rotation");
1764 if (rotation >= 0) {
1765 LOGV("native_jpeg_encode, rotation = %d", rotation);
1766 if(!LINK_jpeg_encoder_setRotation(rotation)) {
1767 LOGE("native_jpeg_encode set rotation failed");
1768 return false;
1769 }
1770 }
1771
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001772// jpeg_set_location();
1773 if(mParameters.getInt(CameraParameters::KEY_GPS_STATUS) == 1) {
1774 setGpsParameters();
1775 }
1776 //set TimeStamp
1777 const char *str = mParameters.get(CameraParameters::KEY_EXIF_DATETIME);
1778 if(str != NULL) {
1779 strncpy(dateTime, str, 19);
1780 dateTime[19] = '\0';
1781 addExifTag(EXIFTAGID_EXIF_DATE_TIME_ORIGINAL, EXIF_ASCII,
1782 20, 1, (void *)dateTime);
1783 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001784
1785 if (!LINK_jpeg_encoder_encode(&mDimension,
1786 (uint8_t *)mThumbnailHeap->mHeap->base(),
1787 mThumbnailHeap->mHeap->getHeapID(),
1788 (uint8_t *)mRawHeap->mHeap->base(),
1789 mRawHeap->mHeap->getHeapID(),
Srinivasan Kannan5701a942010-04-15 16:17:21 -07001790 &mCrop, exif_data, exif_table_numEntries,
1791 jpegPadding/2)) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001792 LOGE("native_jpeg_encode: jpeg_encoder_encode failed.");
1793 return false;
1794 }
1795 return true;
1796}
1797
1798bool QualcommCameraHardware::native_set_parm(
1799 cam_ctrl_type type, uint16_t length, void *value)
1800{
1801 struct msm_ctrl_cmd ctrlCmd;
1802
1803 ctrlCmd.timeout_ms = 5000;
1804 ctrlCmd.type = (uint16_t)type;
1805 ctrlCmd.length = length;
1806 // FIXME: this will be put in by the kernel
1807 ctrlCmd.resp_fd = mCameraControlFd;
1808 ctrlCmd.value = value;
1809
1810 LOGV("%s: fd %d, type %d, length %d", __FUNCTION__,
1811 mCameraControlFd, type, length);
1812 if (ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0 ||
1813 ctrlCmd.status != CAM_CTRL_SUCCESS) {
1814 LOGE("%s: error (%s): fd %d, type %d, length %d, status %d",
1815 __FUNCTION__, strerror(errno),
1816 mCameraControlFd, type, length, ctrlCmd.status);
1817 return false;
1818 }
1819 return true;
1820}
1821
1822void QualcommCameraHardware::jpeg_set_location()
1823{
1824 bool encode_location = true;
1825 camera_position_type pt;
1826
1827#define PARSE_LOCATION(what,type,fmt,desc) do { \
1828 pt.what = 0; \
1829 const char *what##_str = mParameters.get("gps-"#what); \
1830 LOGV("GPS PARM %s --> [%s]", "gps-"#what, what##_str); \
1831 if (what##_str) { \
1832 type what = 0; \
1833 if (sscanf(what##_str, fmt, &what) == 1) \
1834 pt.what = what; \
1835 else { \
1836 LOGE("GPS " #what " %s could not" \
1837 " be parsed as a " #desc, what##_str); \
1838 encode_location = false; \
1839 } \
1840 } \
1841 else { \
1842 LOGV("GPS " #what " not specified: " \
1843 "defaulting to zero in EXIF header."); \
1844 encode_location = false; \
1845 } \
1846 } while(0)
1847
1848 PARSE_LOCATION(timestamp, long, "%ld", "long");
1849 if (!pt.timestamp) pt.timestamp = time(NULL);
1850 PARSE_LOCATION(altitude, short, "%hd", "short");
1851 PARSE_LOCATION(latitude, double, "%lf", "double float");
1852 PARSE_LOCATION(longitude, double, "%lf", "double float");
1853
1854#undef PARSE_LOCATION
1855
1856 if (encode_location) {
1857 LOGD("setting image location ALT %d LAT %lf LON %lf",
1858 pt.altitude, pt.latitude, pt.longitude);
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001859/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001860 if (!LINK_jpeg_encoder_setLocation(&pt)) {
1861 LOGE("jpeg_set_location: LINK_jpeg_encoder_setLocation failed.");
1862 }
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001863*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001864 }
1865 else LOGV("not setting image location");
1866}
1867
1868void QualcommCameraHardware::runFrameThread(void *data)
1869{
1870 LOGV("runFrameThread E");
1871
1872 int cnt;
1873
1874#if DLOPEN_LIBMMCAMERA
1875 // We need to maintain a reference to libqcamera.so for the duration of the
1876 // frame thread, because we do not know when it will exit relative to the
1877 // lifetime of this object. We do not want to dlclose() libqcamera while
1878 // LINK_cam_frame is still running.
1879 void *libhandle = ::dlopen("liboemcamera.so", RTLD_NOW);
1880 LOGV("FRAME: loading libqcamera at %p", libhandle);
1881 if (!libhandle) {
1882 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
1883 }
1884 if (libhandle)
1885#endif
1886 {
1887 LINK_cam_frame(data);
1888 }
1889
Mohan Kandrad9efed92010-01-15 19:08:39 -08001890 mPreviewHeap.clear();
Mohan Kandraf1ebf982010-02-02 15:25:43 -08001891 if(( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250))
Sravankb4f5f1c2010-01-21 11:06:17 +05301892 mRecordHeap.clear();
1893
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001894#if DLOPEN_LIBMMCAMERA
1895 if (libhandle) {
1896 ::dlclose(libhandle);
1897 LOGV("FRAME: dlclose(libqcamera)");
1898 }
1899#endif
1900
1901 mFrameThreadWaitLock.lock();
1902 mFrameThreadRunning = false;
1903 mFrameThreadWait.signal();
1904 mFrameThreadWaitLock.unlock();
1905
1906 LOGV("runFrameThread X");
1907}
1908
Sravankb4f5f1c2010-01-21 11:06:17 +05301909void QualcommCameraHardware::runVideoThread(void *data)
1910{
1911 LOGD("runVideoThread E");
1912 msm_frame* vframe = NULL;
1913
1914 while(true) {
1915 pthread_mutex_lock(&(g_busy_frame_queue.mut));
1916
Srinivasan Kannanfc3915c2010-03-18 10:54:40 -07001917 // Exit the thread , in case of stop recording..
1918 mVideoThreadWaitLock.lock();
1919 if(mVideoThreadExit){
1920 LOGV("Exiting video thread..");
1921 mVideoThreadWaitLock.unlock();
1922 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
1923 break;
1924 }
1925 mVideoThreadWaitLock.unlock();
1926
Kiran Kumar H Nb49af212010-02-17 15:12:17 -08001927 LOGV("in video_thread : wait for video frame ");
Sravankb4f5f1c2010-01-21 11:06:17 +05301928 // check if any frames are available in busyQ and give callback to
1929 // services/video encoder
1930 cam_frame_wait_video();
1931 LOGV("video_thread, wait over..");
1932
1933 // Exit the thread , in case of stop recording..
1934 mVideoThreadWaitLock.lock();
1935 if(mVideoThreadExit){
Kiran Kumar H Nb49af212010-02-17 15:12:17 -08001936 LOGV("Exiting video thread..");
Sravankb4f5f1c2010-01-21 11:06:17 +05301937 mVideoThreadWaitLock.unlock();
1938 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
1939 break;
1940 }
1941 mVideoThreadWaitLock.unlock();
1942
1943 // Get the video frame to be encoded
1944 vframe = cam_frame_get_video ();
Apurva Rajgurud9b0b302010-02-19 11:22:56 -08001945 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
Sravankb4f5f1c2010-01-21 11:06:17 +05301946 LOGV("in video_thread : got video frame ");
1947
Mohan Kandrabad0eaa2010-02-04 15:11:54 -08001948 if (UNLIKELY(mDebugFps)) {
1949 debugShowVideoFPS();
1950 }
1951
Sravankb4f5f1c2010-01-21 11:06:17 +05301952 if(vframe != NULL) {
1953 // Find the offset within the heap of the current buffer.
1954 LOGV("Got video frame : buffer %d base %d ", vframe->buffer, mRecordHeap->mHeap->base());
1955 ssize_t offset =
1956 (ssize_t)vframe->buffer - (ssize_t)mRecordHeap->mHeap->base();
1957 LOGV("offset = %d , alignsize = %d , offset later = %d", offset, mRecordHeap->mAlignedBufferSize, (offset / mRecordHeap->mAlignedBufferSize));
1958
1959 offset /= mRecordHeap->mAlignedBufferSize;
Mohan Kandra1307f312010-04-29 10:18:42 -07001960 /* Extract the timestamp of this frame */
1961 nsecs_t timeStamp = nsecs_t(vframe->ts.tv_sec)*1000000000LL + vframe->ts.tv_nsec;
Sravankb4f5f1c2010-01-21 11:06:17 +05301962
1963 // dump frames for test purpose
1964#ifdef DUMP_VIDEO_FRAMES
1965 static int frameCnt = 0;
1966 if (frameCnt >= 11 && frameCnt <= 13 ) {
1967 char buf[128];
1968 sprintf(buf, "/data/%d_v.yuv", frameCnt);
1969 int file_fd = open(buf, O_RDWR | O_CREAT, 0777);
1970 LOGV("dumping video frame %d", frameCnt);
1971 if (file_fd < 0) {
1972 LOGE("cannot open file\n");
1973 }
1974 else
1975 {
1976 write(file_fd, (const void *)vframe->buffer,
1977 vframe->cbcr_off * 3 / 2);
1978 }
1979 close(file_fd);
1980 }
1981 frameCnt++;
1982#endif
1983 // Enable IF block to give frames to encoder , ELSE block for just simulation
1984#if 1
1985 LOGV("in video_thread : got video frame, before if check giving frame to services/encoder");
1986 mCallbackLock.lock();
1987 int msgEnabled = mMsgEnabled;
1988 data_callback_timestamp rcb = mDataCallbackTimestamp;
1989 void *rdata = mCallbackCookie;
1990 mCallbackLock.unlock();
1991
1992 if(rcb != NULL && (msgEnabled & CAMERA_MSG_VIDEO_FRAME) ) {
1993 LOGV("in video_thread : got video frame, giving frame to services/encoder");
Mohan Kandra1307f312010-04-29 10:18:42 -07001994 rcb(timeStamp, CAMERA_MSG_VIDEO_FRAME, mRecordHeap->mBuffers[offset], rdata);
Sravankb4f5f1c2010-01-21 11:06:17 +05301995 }
1996#else
1997 // 720p output2 : simulate release frame here:
1998 LOGE("in video_thread simulation , releasing the video frame");
1999 LINK_camframe_free_video(vframe);
2000#endif
2001
2002 } else LOGE("in video_thread get frame returned null");
2003
Sravankb4f5f1c2010-01-21 11:06:17 +05302004
2005 } // end of while loop
Mohan Kandra156d0ac2010-01-25 16:59:17 -08002006
2007 mVideoThreadWaitLock.lock();
2008 mVideoThreadRunning = false;
2009 mVideoThreadWait.signal();
2010 mVideoThreadWaitLock.unlock();
2011
Sravankb4f5f1c2010-01-21 11:06:17 +05302012 LOGV("runVideoThread X");
2013}
2014
2015void *video_thread(void *user)
2016{
2017 LOGV("video_thread E");
2018 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
2019 if (obj != 0) {
2020 obj->runVideoThread(user);
2021 }
2022 else LOGE("not starting video thread: the object went away!");
2023 LOGV("video_thread X");
2024 return NULL;
2025}
2026
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002027void *frame_thread(void *user)
2028{
2029 LOGD("frame_thread E");
2030 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
2031 if (obj != 0) {
2032 obj->runFrameThread(user);
2033 }
2034 else LOGW("not starting frame thread: the object went away!");
2035 LOGD("frame_thread X");
2036 return NULL;
2037}
2038
2039bool QualcommCameraHardware::initPreview()
2040{
2041 // See comments in deinitPreview() for why we have to wait for the frame
2042 // thread here, and why we can't use pthread_join().
Sravankb4f5f1c2010-01-21 11:06:17 +05302043 int videoWidth, videoHeight;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002044 mParameters.getPreviewSize(&previewWidth, &previewHeight);
Sravankb4f5f1c2010-01-21 11:06:17 +05302045
2046 videoWidth = previewWidth; // temporary , should be configurable later
2047 videoHeight = previewHeight;
2048 LOGV("initPreview E: preview size=%dx%d videosize = %d x %d", previewWidth, previewHeight, videoWidth, videoHeight );
2049
Mohan Kandraf1ebf982010-02-02 15:25:43 -08002050 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05302051 mDimension.video_width = videoWidth;
Kiran Kumar H N7ac84e32010-02-01 10:58:47 -08002052 mDimension.video_width = CEILING16(mDimension.video_width);
Sravankb4f5f1c2010-01-21 11:06:17 +05302053 mDimension.video_height = videoHeight;
Sravank64461e82010-02-25 15:10:09 +05302054 // for 720p , preview can be 768X432
2055 previewWidth = mDimension.display_width;
2056 previewHeight= mDimension.display_height;
Sravankb4f5f1c2010-01-21 11:06:17 +05302057 LOGV("initPreview : preview size=%dx%d videosize = %d x %d", previewWidth, previewHeight, mDimension.video_width, mDimension.video_height );
2058 }
2059
2060
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002061 mFrameThreadWaitLock.lock();
2062 while (mFrameThreadRunning) {
2063 LOGV("initPreview: waiting for old frame thread to complete.");
2064 mFrameThreadWait.wait(mFrameThreadWaitLock);
2065 LOGV("initPreview: old frame thread completed.");
2066 }
2067 mFrameThreadWaitLock.unlock();
2068
2069 mSnapshotThreadWaitLock.lock();
2070 while (mSnapshotThreadRunning) {
2071 LOGV("initPreview: waiting for old snapshot thread to complete.");
2072 mSnapshotThreadWait.wait(mSnapshotThreadWaitLock);
2073 LOGV("initPreview: old snapshot thread completed.");
2074 }
2075 mSnapshotThreadWaitLock.unlock();
2076
2077 int cnt = 0;
2078 mPreviewFrameSize = previewWidth * previewHeight * 3/2;
Mohan Kandrad9efed92010-01-15 19:08:39 -08002079 dstOffset = 0;
2080 mPreviewHeap = new PmemPool("/dev/pmem_adsp",
Mohan Kandra284966d2010-01-05 13:39:15 -08002081 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
2082 mCameraControlFd,
Sravankb4f5f1c2010-01-21 11:06:17 +05302083 MSM_PMEM_PREVIEW, //MSM_PMEM_OUTPUT2,
Mohan Kandra284966d2010-01-05 13:39:15 -08002084 mPreviewFrameSize,
Mohan Kandrad9efed92010-01-15 19:08:39 -08002085 kPreviewBufferCountActual,
Mohan Kandra284966d2010-01-05 13:39:15 -08002086 mPreviewFrameSize,
Mohan Kandrad9efed92010-01-15 19:08:39 -08002087 "preview");
Mohan Kandra284966d2010-01-05 13:39:15 -08002088
Mohan Kandrad9efed92010-01-15 19:08:39 -08002089 if (!mPreviewHeap->initialized()) {
2090 mPreviewHeap.clear();
Mohan Kandra284966d2010-01-05 13:39:15 -08002091 LOGE("initPreview X: could not initialize Camera preview heap.");
2092 return false;
2093 }
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002094 if( mCurrentTarget == TARGET_MSM7630 ) {
Srinivasan Kannan613301c2010-02-10 17:08:53 -08002095 mPostViewHeap.clear();
Kiran Kumar H N595970b2010-01-12 10:41:09 -08002096 if(mPostViewHeap == NULL) {
2097 LOGV(" Allocating Postview heap ");
2098 /* mPostViewHeap should be declared only for 7630 target */
2099 mPostViewHeap =
2100 new PmemPool("/dev/pmem_adsp",
2101 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
2102 mCameraControlFd,
Sravankb4f5f1c2010-01-21 11:06:17 +05302103 MSM_PMEM_PREVIEW, //MSM_PMEM_OUTPUT2,
Kiran Kumar H N595970b2010-01-12 10:41:09 -08002104 mPreviewFrameSize,
2105 1,
2106 mPreviewFrameSize,
2107 "postview");
Mohan Kandra284966d2010-01-05 13:39:15 -08002108
Kiran Kumar H N595970b2010-01-12 10:41:09 -08002109 if (!mPostViewHeap->initialized()) {
2110 mPostViewHeap.clear();
2111 LOGE(" Failed to initialize Postview Heap");
2112 return false;
2113 }
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002114 }
Mohan Kandraf1ebf982010-02-02 15:25:43 -08002115 }
2116
2117 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250) ) {
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002118
2119 // Allocate video buffers after allocating preview buffers.
Sravankb4f5f1c2010-01-21 11:06:17 +05302120 initRecord();
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002121 }
Sravankb4f5f1c2010-01-21 11:06:17 +05302122
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002123 // mDimension will be filled with thumbnail_width, thumbnail_height,
2124 // orig_picture_dx, and orig_picture_dy after this function call. We need to
2125 // keep it for jpeg_encoder_encode.
2126 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
2127 sizeof(cam_ctrl_dimension_t), &mDimension);
2128
2129 if (ret) {
2130 for (cnt = 0; cnt < kPreviewBufferCount; cnt++) {
Mohan Kandrad9efed92010-01-15 19:08:39 -08002131 frames[cnt].fd = mPreviewHeap->mHeap->getHeapID();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002132 frames[cnt].buffer =
Mohan Kandrad9efed92010-01-15 19:08:39 -08002133 (uint32_t)mPreviewHeap->mHeap->base() + mPreviewHeap->mAlignedBufferSize * cnt;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002134 frames[cnt].y_off = 0;
2135 frames[cnt].cbcr_off = previewWidth * previewHeight;
Sravankb4f5f1c2010-01-21 11:06:17 +05302136 frames[cnt].path = OUTPUT_TYPE_P; // MSM_FRAME_ENC;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002137 }
2138
2139 mFrameThreadWaitLock.lock();
2140 pthread_attr_t attr;
2141 pthread_attr_init(&attr);
2142 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
Sravankb4f5f1c2010-01-21 11:06:17 +05302143
2144 frame_parms.frame = frames[kPreviewBufferCount - 1];
Apurva Rajguruc73c1722010-04-15 17:39:11 -07002145
2146 if( mCurrentTarget == TARGET_MSM7630 || mCurrentTarget == TARGET_QSD8250 )
2147 frame_parms.video_frame = recordframes[kPreviewBufferCount - 1];
2148 else
2149 frame_parms.video_frame = frames[kPreviewBufferCount - 1];
Sravankb4f5f1c2010-01-21 11:06:17 +05302150
2151 LOGV ("initpreview before cam_frame thread carete , video frame buffer=%lu fd=%d y_off=%d cbcr_off=%d \n",
2152 (unsigned long)frame_parms.video_frame.buffer, frame_parms.video_frame.fd, frame_parms.video_frame.y_off,
2153 frame_parms.video_frame.cbcr_off);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002154 mFrameThreadRunning = !pthread_create(&mFrameThread,
2155 &attr,
2156 frame_thread,
Sravankb4f5f1c2010-01-21 11:06:17 +05302157 (void*)&(frame_parms));
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002158 ret = mFrameThreadRunning;
2159 mFrameThreadWaitLock.unlock();
2160 }
2161
2162 LOGV("initPreview X: %d", ret);
2163 return ret;
2164}
2165
2166void QualcommCameraHardware::deinitPreview(void)
2167{
2168 LOGI("deinitPreview E");
2169
2170 // When we call deinitPreview(), we signal to the frame thread that it
2171 // needs to exit, but we DO NOT WAIT for it to complete here. The problem
2172 // is that deinitPreview is sometimes called from the frame-thread's
2173 // callback, when the refcount on the Camera client reaches zero. If we
2174 // called pthread_join(), we would deadlock. So, we just call
2175 // LINK_camframe_terminate() in deinitPreview(), which makes sure that
2176 // after the preview callback returns, the camframe thread will exit. We
2177 // could call pthread_join() in initPreview() to join the last frame
2178 // thread. However, we would also have to call pthread_join() in release
2179 // as well, shortly before we destroy the object; this would cause the same
2180 // deadlock, since release(), like deinitPreview(), may also be called from
2181 // the frame-thread's callback. This we have to make the frame thread
2182 // detached, and use a separate mechanism to wait for it to complete.
2183
Kiran Kumar H N7ac84e32010-02-01 10:58:47 -08002184 LINK_camframe_terminate();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002185 LOGI("deinitPreview X");
2186}
2187
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002188bool QualcommCameraHardware::initRawSnapshot()
2189{
2190 LOGV("initRawSnapshot E");
2191
2192 //get width and height from Dimension Object
2193 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
2194 sizeof(cam_ctrl_dimension_t), &mDimension);
2195
2196 if(!ret){
2197 LOGE("initRawSnapshot X: failed to set dimension");
2198 return false;
2199 }
2200 int rawSnapshotSize = mDimension.raw_picture_height *
2201 mDimension.raw_picture_width;
2202
2203 LOGV("raw_snapshot_buffer_size = %d, raw_picture_height = %d, "\
2204 "raw_picture_width = %d",
2205 rawSnapshotSize, mDimension.raw_picture_height,
2206 mDimension.raw_picture_width);
2207
2208 if (mRawSnapShotPmemHeap != NULL) {
2209 LOGV("initRawSnapshot: clearing old mRawSnapShotPmemHeap.");
2210 mRawSnapShotPmemHeap.clear();
2211 }
2212
2213 //Pmem based pool for Camera Driver
2214 mRawSnapShotPmemHeap = new PmemPool("/dev/pmem_adsp",
Dinesh Gargeecf1a62010-04-19 16:31:30 -07002215 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002216 mCameraControlFd,
2217 MSM_PMEM_RAW_MAINIMG,
2218 rawSnapshotSize,
2219 1,
2220 rawSnapshotSize,
2221 "raw pmem snapshot camera");
2222
2223 if (!mRawSnapShotPmemHeap->initialized()) {
2224 mRawSnapShotPmemHeap.clear();
2225 LOGE("initRawSnapshot X: error initializing mRawSnapshotHeap");
2226 return false;
2227 }
2228 LOGV("initRawSnapshot X");
2229 return true;
2230
2231}
2232
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002233bool QualcommCameraHardware::initRaw(bool initJpegHeap)
2234{
2235 int rawWidth, rawHeight;
Apurva Rajguru8d1773b2009-12-02 14:21:23 -08002236
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002237 mParameters.getPictureSize(&rawWidth, &rawHeight);
2238 LOGV("initRaw E: picture size=%dx%d", rawWidth, rawHeight);
2239
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08002240 int thumbnailBufferSize;
2241 //Thumbnail height should be smaller than Picture height
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002242 if (rawHeight > (int)thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height){
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08002243 mDimension.ui_thumbnail_width =
2244 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].width;
2245 mDimension.ui_thumbnail_height =
2246 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height;
2247 uint32_t pictureAspectRatio = (uint32_t)((rawWidth * Q12) / rawHeight);
2248 uint32_t i;
2249 for(i = 0; i < THUMBNAIL_SIZE_COUNT; i++ )
2250 {
2251 if(thumbnail_sizes[i].aspect_ratio == pictureAspectRatio)
2252 {
2253 mDimension.ui_thumbnail_width = thumbnail_sizes[i].width;
2254 mDimension.ui_thumbnail_height = thumbnail_sizes[i].height;
2255 break;
2256 }
2257 }
2258 }
2259 else{
2260 mDimension.ui_thumbnail_height = THUMBNAIL_SMALL_HEIGHT;
2261 mDimension.ui_thumbnail_width =
2262 (THUMBNAIL_SMALL_HEIGHT * rawWidth)/ rawHeight;
2263 }
2264
2265 LOGV("Thumbnail Size Width %d Height %d",
2266 mDimension.ui_thumbnail_width,
2267 mDimension.ui_thumbnail_height);
2268
2269 thumbnailBufferSize = mDimension.ui_thumbnail_width *
2270 mDimension.ui_thumbnail_height * 3 / 2;
2271
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002272 // mDimension will be filled with thumbnail_width, thumbnail_height,
2273 // orig_picture_dx, and orig_picture_dy after this function call. We need to
2274 // keep it for jpeg_encoder_encode.
2275 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
2276 sizeof(cam_ctrl_dimension_t), &mDimension);
2277 if(!ret) {
2278 LOGE("initRaw X: failed to set dimension");
2279 return false;
2280 }
2281
2282 if (mJpegHeap != NULL) {
2283 LOGV("initRaw: clearing old mJpegHeap.");
2284 mJpegHeap.clear();
2285 }
2286
2287 // Snapshot
2288 mRawSize = rawWidth * rawHeight * 3 / 2;
Apurva Rajguru8d1773b2009-12-02 14:21:23 -08002289
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002290 if( mCurrentTarget == TARGET_MSM7627 )
Apurva Rajguru8d1773b2009-12-02 14:21:23 -08002291 mJpegMaxSize = CEILING16(rawWidth) * CEILING16(rawHeight) * 3 / 2;
2292 else
2293 mJpegMaxSize = rawWidth * rawHeight * 3 / 2;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002294
2295 LOGV("initRaw: initializing mRawHeap.");
2296 mRawHeap =
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002297 new PmemPool("/dev/pmem_adsp",
Dinesh Gargeecf1a62010-04-19 16:31:30 -07002298 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002299 mCameraControlFd,
2300 MSM_PMEM_MAINIMG,
2301 mJpegMaxSize,
2302 kRawBufferCount,
2303 mRawSize,
2304 "snapshot camera");
2305
2306 if (!mRawHeap->initialized()) {
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002307 LOGE("initRaw X failed ");
2308 mRawHeap.clear();
2309 LOGE("initRaw X: error initializing mRawHeap");
2310 return false;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002311 }
2312
2313 LOGV("do_mmap snapshot pbuf = %p, pmem_fd = %d",
2314 (uint8_t *)mRawHeap->mHeap->base(), mRawHeap->mHeap->getHeapID());
2315
2316 // Jpeg
2317
2318 if (initJpegHeap) {
2319 LOGV("initRaw: initializing mJpegHeap.");
2320 mJpegHeap =
2321 new AshmemPool(mJpegMaxSize,
2322 kJpegBufferCount,
2323 0, // we do not know how big the picture will be
2324 "jpeg");
2325
2326 if (!mJpegHeap->initialized()) {
2327 mJpegHeap.clear();
2328 mRawHeap.clear();
2329 LOGE("initRaw X failed: error initializing mJpegHeap.");
2330 return false;
2331 }
2332
2333 // Thumbnails
2334
2335 mThumbnailHeap =
2336 new PmemPool("/dev/pmem_adsp",
Dinesh Gargeecf1a62010-04-19 16:31:30 -07002337 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002338 mCameraControlFd,
2339 MSM_PMEM_THUMBNAIL,
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08002340 thumbnailBufferSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002341 1,
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08002342 thumbnailBufferSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002343 "thumbnail");
2344
2345 if (!mThumbnailHeap->initialized()) {
2346 mThumbnailHeap.clear();
2347 mJpegHeap.clear();
2348 mRawHeap.clear();
2349 LOGE("initRaw X failed: error initializing mThumbnailHeap.");
2350 return false;
2351 }
2352 }
2353
2354 LOGV("initRaw X");
2355 return true;
2356}
2357
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002358
2359void QualcommCameraHardware::deinitRawSnapshot()
2360{
2361 LOGV("deinitRawSnapshot E");
2362 mRawSnapShotPmemHeap.clear();
2363 mRawSnapshotAshmemHeap.clear();
2364 LOGV("deinitRawSnapshot X");
2365}
2366
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002367void QualcommCameraHardware::deinitRaw()
2368{
2369 LOGV("deinitRaw E");
2370
2371 mThumbnailHeap.clear();
2372 mJpegHeap.clear();
2373 mRawHeap.clear();
2374 mDisplayHeap.clear();
2375
2376 LOGV("deinitRaw X");
2377}
2378
2379void QualcommCameraHardware::release()
2380{
2381 LOGD("release E");
2382 Mutex::Autolock l(&mLock);
2383
2384#if DLOPEN_LIBMMCAMERA
2385 if (libmmcamera == NULL) {
2386 LOGE("ERROR: multiple release!");
2387 return;
2388 }
2389#else
2390#warning "Cannot detect multiple release when not dlopen()ing libqcamera!"
2391#endif
2392
2393 int cnt, rc;
2394 struct msm_ctrl_cmd ctrlCmd;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002395 if (mCameraRunning) {
2396 if(mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME)) {
2397 mRecordFrameLock.lock();
2398 mReleasedRecordingFrame = true;
2399 mRecordWait.signal();
2400 mRecordFrameLock.unlock();
2401 }
2402 stopPreviewInternal();
2403 }
2404
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002405 if( mCurrentTarget == TARGET_MSM7630 ) {
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002406 mPostViewHeap.clear();
2407 mPostViewHeap = NULL;
2408 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002409 LINK_jpeg_encoder_join();
2410 deinitRaw();
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002411 deinitRawSnapshot();
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002412 {
2413 Mutex::Autolock l(&mCamframeTimeoutLock);
2414 if(!camframe_timeout_flag) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002415
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002416 ctrlCmd.timeout_ms = 5000;
2417 ctrlCmd.length = 0;
2418 ctrlCmd.type = (uint16_t)CAMERA_EXIT;
2419 ctrlCmd.resp_fd = mCameraControlFd; // FIXME: this will be put in by the kernel
2420 if (ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0)
2421 LOGE("ioctl CAMERA_EXIT fd %d error %s",
2422 mCameraControlFd, strerror(errno));
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002423
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002424 }
2425 }
Kiran Kumar H N7ac84e32010-02-01 10:58:47 -08002426 LINK_release_cam_conf_thread();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002427 close(mCameraControlFd);
2428 mCameraControlFd = -1;
Mohan Kandra284966d2010-01-05 13:39:15 -08002429 if(fb_fd >= 0) {
2430 close(fb_fd);
2431 fb_fd = -1;
2432 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002433#if DLOPEN_LIBMMCAMERA
2434 if (libmmcamera) {
2435 ::dlclose(libmmcamera);
2436 LOGV("dlclose(libqcamera)");
2437 libmmcamera = NULL;
2438 }
2439#endif
2440
2441 Mutex::Autolock lock(&singleton_lock);
2442 singleton_releasing = true;
2443
2444 LOGD("release X");
2445}
2446
2447QualcommCameraHardware::~QualcommCameraHardware()
2448{
2449 LOGD("~QualcommCameraHardware E");
2450 Mutex::Autolock lock(&singleton_lock);
Apurva Rajguruc73c1722010-04-15 17:39:11 -07002451
2452 if( mCurrentTarget == TARGET_MSM7630 || mCurrentTarget == TARGET_QSD8250 ) {
2453 delete [] recordframes;
2454 recordframes = NULL;
2455 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002456 singleton.clear();
2457 singleton_releasing = false;
2458 singleton_wait.signal();
2459 LOGD("~QualcommCameraHardware X");
2460}
2461
2462sp<IMemoryHeap> QualcommCameraHardware::getRawHeap() const
2463{
2464 LOGV("getRawHeap");
2465 return mDisplayHeap != NULL ? mDisplayHeap->mHeap : NULL;
2466}
2467
2468sp<IMemoryHeap> QualcommCameraHardware::getPreviewHeap() const
2469{
2470 LOGV("getPreviewHeap");
Mohan Kandrad9efed92010-01-15 19:08:39 -08002471 return mPreviewHeap != NULL ? mPreviewHeap->mHeap : NULL;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002472}
2473
2474status_t QualcommCameraHardware::startPreviewInternal()
2475{
Sravankb4f5f1c2010-01-21 11:06:17 +05302476 LOGV("in startPreviewInternal : E");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002477 if(mCameraRunning) {
2478 LOGV("startPreview X: preview already running.");
2479 return NO_ERROR;
2480 }
2481
2482 if (!mPreviewInitialized) {
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002483 mLastQueuedFrame = NULL;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002484 mPreviewInitialized = initPreview();
2485 if (!mPreviewInitialized) {
2486 LOGE("startPreview X initPreview failed. Not starting preview.");
2487 return UNKNOWN_ERROR;
2488 }
2489 }
2490
Srinivasan Kannan74712c92010-04-07 13:36:48 -07002491 {
2492 Mutex::Autolock cameraRunningLock(&mCameraRunningLock);
2493 if(( mCurrentTarget != TARGET_MSM7630 ) &&
2494 (mCurrentTarget != TARGET_QSD8250))
2495 mCameraRunning = native_start_preview(mCameraControlFd);
2496 else
2497 mCameraRunning = native_start_video(mCameraControlFd);
2498 }
Sravankb4f5f1c2010-01-21 11:06:17 +05302499
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002500 if(!mCameraRunning) {
2501 deinitPreview();
2502 mPreviewInitialized = false;
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08002503 mOverlay = NULL;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002504 LOGE("startPreview X: native_start_preview failed!");
2505 return UNKNOWN_ERROR;
2506 }
2507
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08002508 //Reset the Gps Information
2509 exif_table_numEntries = 0;
Mohan Kandra284966d2010-01-05 13:39:15 -08002510
2511 if(native_get_maxzoom(mCameraControlFd, (void *)&mMaxZoom) == true){
Brian Steuerb62adbd2010-02-02 14:47:08 -08002512 LOGD("Maximum zoom value is %d", mMaxZoom);
Mohan Kandra284966d2010-01-05 13:39:15 -08002513 mParameters.set("zoom-supported", "true");
2514 } else {
2515 LOGE("Failed to get maximum zoom value...setting max zoom to zero");
2516 mParameters.set("zoom-supported", "false");
2517 mMaxZoom = 0;
2518 }
2519 mParameters.set("max-zoom",mMaxZoom);
2520
Sravankb4f5f1c2010-01-21 11:06:17 +05302521 LOGV("startPreviewInternal X");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002522 return NO_ERROR;
2523}
2524
2525status_t QualcommCameraHardware::startPreview()
2526{
2527 LOGV("startPreview E");
2528 Mutex::Autolock l(&mLock);
2529 return startPreviewInternal();
2530}
2531
2532void QualcommCameraHardware::stopPreviewInternal()
2533{
2534 LOGV("stopPreviewInternal E: %d", mCameraRunning);
2535 if (mCameraRunning) {
2536 // Cancel auto focus.
2537 {
2538 if (mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS)) {
2539 cancelAutoFocusInternal();
2540 }
2541 }
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002542
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002543 Mutex::Autolock l(&mCamframeTimeoutLock);
Srinivasan Kannan74712c92010-04-07 13:36:48 -07002544 {
2545 Mutex::Autolock cameraRunningLock(&mCameraRunningLock);
2546 if(!camframe_timeout_flag) {
2547 if (( mCurrentTarget != TARGET_MSM7630 ) &&
2548 (mCurrentTarget != TARGET_QSD8250))
2549 mCameraRunning = !native_stop_preview(mCameraControlFd);
2550 else
2551 mCameraRunning = !native_stop_video(mCameraControlFd);
2552 } else {
2553 /* This means that the camframetimeout was issued.
2554 * But we did not issue native_stop_preview(), so we
2555 * need to update mCameraRunning to indicate that
2556 * Camera is no longer running. */
2557 mCameraRunning = 0;
2558 }
2559 }
Sravankb4f5f1c2010-01-21 11:06:17 +05302560
Kiran Kumar H Nac2f4952009-12-17 01:16:53 -08002561 if (!mCameraRunning && mPreviewInitialized) {
2562 deinitPreview();
Mohan Kandraf1ebf982010-02-02 15:25:43 -08002563 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250)) {
Mohan Kandra156d0ac2010-01-25 16:59:17 -08002564 mVideoThreadWaitLock.lock();
2565 LOGV("in stopPreviewInternal: making mVideoThreadExit 1");
2566 mVideoThreadExit = 1;
2567 mVideoThreadWaitLock.unlock();
2568 // 720p : signal the video thread , and check in video thread if stop is called, if so exit video thread.
2569 pthread_mutex_lock(&(g_busy_frame_queue.mut));
2570 pthread_cond_signal(&(g_busy_frame_queue.wait));
2571 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
Mohan Kandra1ade9a82010-03-02 10:11:26 -08002572 /* Flush the Busy Q */
2573 cam_frame_flush_video();
2574 /* Flush the Free Q */
2575 LINK_cam_frame_flush_free_video();
Mohan Kandra156d0ac2010-01-25 16:59:17 -08002576 }
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002577 mPreviewInitialized = false;
2578 }
Kiran Kumar H Nac2f4952009-12-17 01:16:53 -08002579 else LOGE("stopPreviewInternal: failed to stop preview");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002580 }
2581 LOGV("stopPreviewInternal X: %d", mCameraRunning);
2582}
2583
2584void QualcommCameraHardware::stopPreview()
2585{
2586 LOGV("stopPreview: E");
2587 Mutex::Autolock l(&mLock);
2588 {
2589 if (mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME))
2590 return;
2591 }
2592 stopPreviewInternal();
2593 LOGV("stopPreview: X");
2594}
2595
2596void QualcommCameraHardware::runAutoFocus()
2597{
2598 bool status = true;
2599 void *libhandle = NULL;
Srinivasan Kannan71229622009-12-04 12:05:58 -08002600 isp3a_af_mode_t afMode;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002601
2602 mAutoFocusThreadLock.lock();
2603 // Skip autofocus if focus mode is infinity.
Srinivasan Kannan74712c92010-04-07 13:36:48 -07002604 if ((mParameters.get(CameraParameters::KEY_FOCUS_MODE) == 0)
2605 || (strcmp(mParameters.get(CameraParameters::KEY_FOCUS_MODE),
2606 CameraParameters::FOCUS_MODE_INFINITY) == 0)) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002607 goto done;
2608 }
2609
2610 mAutoFocusFd = open(MSM_CAMERA_CONTROL, O_RDWR);
2611 if (mAutoFocusFd < 0) {
2612 LOGE("autofocus: cannot open %s: %s",
2613 MSM_CAMERA_CONTROL,
2614 strerror(errno));
2615 mAutoFocusThreadRunning = false;
2616 mAutoFocusThreadLock.unlock();
2617 return;
2618 }
2619
2620#if DLOPEN_LIBMMCAMERA
2621 // We need to maintain a reference to libqcamera.so for the duration of the
2622 // AF thread, because we do not know when it will exit relative to the
2623 // lifetime of this object. We do not want to dlclose() libqcamera while
2624 // LINK_cam_frame is still running.
2625 libhandle = ::dlopen("liboemcamera.so", RTLD_NOW);
2626 LOGV("AF: loading libqcamera at %p", libhandle);
2627 if (!libhandle) {
2628 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
2629 close(mAutoFocusFd);
2630 mAutoFocusFd = -1;
2631 mAutoFocusThreadRunning = false;
2632 mAutoFocusThreadLock.unlock();
2633 return;
2634 }
2635#endif
2636
Srinivasan Kannan71229622009-12-04 12:05:58 -08002637 afMode = (isp3a_af_mode_t)attr_lookup(focus_modes,
2638 sizeof(focus_modes) / sizeof(str_map),
2639 mParameters.get(CameraParameters::KEY_FOCUS_MODE));
2640
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002641 /* This will block until either AF completes or is cancelled. */
Srinivasan Kannan71229622009-12-04 12:05:58 -08002642 LOGV("af start (fd %d mode %d)", mAutoFocusFd, afMode);
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08002643 status_t err;
2644 err = mAfLock.tryLock();
2645 if(err == NO_ERROR) {
Srinivasan Kannan74712c92010-04-07 13:36:48 -07002646 {
2647 Mutex::Autolock cameraRunningLock(&mCameraRunningLock);
2648 if(mCameraRunning){
2649 LOGV("Start AF");
2650 status = native_set_afmode(mAutoFocusFd, afMode);
2651 }else{
2652 LOGV("As Camera preview is not running, AF not issued");
2653 status = false;
2654 }
2655 }
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08002656 mAfLock.unlock();
2657 }
2658 else{
2659 //AF Cancel would have acquired the lock,
2660 //so, no need to perform any AF
Srinivasan Kannan99e82422010-02-28 15:32:16 -08002661 LOGV("As Cancel auto focus is in progress, auto focus request "
2662 "is ignored");
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08002663 status = FALSE;
2664 }
2665
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002666 LOGV("af done: %d", (int)status);
2667 close(mAutoFocusFd);
2668 mAutoFocusFd = -1;
2669
2670done:
2671 mAutoFocusThreadRunning = false;
2672 mAutoFocusThreadLock.unlock();
2673
2674 mCallbackLock.lock();
2675 bool autoFocusEnabled = mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS);
2676 notify_callback cb = mNotifyCallback;
2677 void *data = mCallbackCookie;
2678 mCallbackLock.unlock();
2679 if (autoFocusEnabled)
2680 cb(CAMERA_MSG_FOCUS, status, 0, data);
2681
2682#if DLOPEN_LIBMMCAMERA
2683 if (libhandle) {
2684 ::dlclose(libhandle);
2685 LOGV("AF: dlclose(libqcamera)");
2686 }
2687#endif
2688}
2689
2690status_t QualcommCameraHardware::cancelAutoFocusInternal()
2691{
2692 LOGV("cancelAutoFocusInternal E");
2693
Srinivasan Kannan71229622009-12-04 12:05:58 -08002694 if(!sensorType->hasAutoFocusSupport){
2695 LOGV("cancelAutoFocusInternal X");
2696 return NO_ERROR;
2697 }
2698
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002699#if 0
2700 if (mAutoFocusFd < 0) {
2701 LOGV("cancelAutoFocusInternal X: not in progress");
2702 return NO_ERROR;
2703 }
2704#endif
2705
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08002706 status_t rc = NO_ERROR;
2707 status_t err;
2708 err = mAfLock.tryLock();
2709 if(err == NO_ERROR) {
2710 //Got Lock, means either AF hasn't started or
2711 // AF is done. So no need to cancel it, just change the state
Srinivasan Kannan99e82422010-02-28 15:32:16 -08002712 LOGV("As Auto Focus is not in progress, Cancel Auto Focus "
2713 "is ignored");
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08002714 mAfLock.unlock();
2715 }
2716 else {
2717 //AF is in Progess, So cancel it
2718 LOGV("Lock busy...cancel AF");
2719 rc = native_cancel_afmode(mCameraControlFd, mAutoFocusFd) ?
2720 NO_ERROR :
2721 UNKNOWN_ERROR;
2722 }
2723
2724
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002725
2726 LOGV("cancelAutoFocusInternal X: %d", rc);
2727 return rc;
2728}
2729
2730void *auto_focus_thread(void *user)
2731{
2732 LOGV("auto_focus_thread E");
2733 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
2734 if (obj != 0) {
2735 obj->runAutoFocus();
2736 }
2737 else LOGW("not starting autofocus: the object went away!");
2738 LOGV("auto_focus_thread X");
2739 return NULL;
2740}
2741
2742status_t QualcommCameraHardware::autoFocus()
2743{
2744 LOGV("autoFocus E");
2745 Mutex::Autolock l(&mLock);
2746
Srinivasan Kannan71229622009-12-04 12:05:58 -08002747 if(!sensorType->hasAutoFocusSupport){
Srinivasan Kannandf085222009-12-09 18:31:00 -08002748 bool status = false;
2749 mCallbackLock.lock();
2750 bool autoFocusEnabled = mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS);
2751 notify_callback cb = mNotifyCallback;
2752 void *data = mCallbackCookie;
2753 mCallbackLock.unlock();
2754 if (autoFocusEnabled)
2755 cb(CAMERA_MSG_FOCUS, status, 0, data);
Srinivasan Kannan71229622009-12-04 12:05:58 -08002756 LOGV("autoFocus X");
2757 return NO_ERROR;
2758 }
2759
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002760 if (mCameraControlFd < 0) {
2761 LOGE("not starting autofocus: main control fd %d", mCameraControlFd);
2762 return UNKNOWN_ERROR;
2763 }
2764
2765 {
2766 mAutoFocusThreadLock.lock();
2767 if (!mAutoFocusThreadRunning) {
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08002768 if (native_prepare_snapshot(mCameraControlFd) == FALSE) {
2769 LOGE("native_prepare_snapshot failed!\n");
2770 mAutoFocusThreadLock.unlock();
2771 return UNKNOWN_ERROR;
2772 }
2773
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002774 // Create a detached thread here so that we don't have to wait
2775 // for it when we cancel AF.
2776 pthread_t thr;
2777 pthread_attr_t attr;
2778 pthread_attr_init(&attr);
2779 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2780 mAutoFocusThreadRunning =
2781 !pthread_create(&thr, &attr,
2782 auto_focus_thread, NULL);
2783 if (!mAutoFocusThreadRunning) {
2784 LOGE("failed to start autofocus thread");
2785 mAutoFocusThreadLock.unlock();
2786 return UNKNOWN_ERROR;
2787 }
2788 }
2789 mAutoFocusThreadLock.unlock();
2790 }
2791
2792 LOGV("autoFocus X");
2793 return NO_ERROR;
2794}
2795
2796status_t QualcommCameraHardware::cancelAutoFocus()
2797{
2798 LOGV("cancelAutoFocus E");
2799 Mutex::Autolock l(&mLock);
2800
2801 int rc = NO_ERROR;
2802 if (mCameraRunning && mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS)) {
2803 rc = cancelAutoFocusInternal();
2804 }
2805
2806 LOGV("cancelAutoFocus X");
2807 return rc;
2808}
2809
2810void QualcommCameraHardware::runSnapshotThread(void *data)
2811{
2812 LOGV("runSnapshotThread E");
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002813 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
2814 if (native_start_snapshot(mCameraControlFd))
2815 receiveRawPicture();
2816 else
2817 LOGE("main: native_start_snapshot failed!");
2818 } else if(mSnapshotFormat == PICTURE_FORMAT_RAW){
2819 if(native_start_raw_snapshot(mCameraControlFd)){
2820 receiveRawSnapshot();
2821 } else {
2822 LOGE("main: native_start_raw_snapshot failed!");
2823 }
2824 }
2825
2826 mSnapshotFormat = 0;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002827
2828 mSnapshotThreadWaitLock.lock();
2829 mSnapshotThreadRunning = false;
2830 mSnapshotThreadWait.signal();
2831 mSnapshotThreadWaitLock.unlock();
2832
2833 LOGV("runSnapshotThread X");
2834}
2835
2836void *snapshot_thread(void *user)
2837{
2838 LOGD("snapshot_thread E");
2839 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
2840 if (obj != 0) {
2841 obj->runSnapshotThread(user);
2842 }
2843 else LOGW("not starting snapshot thread: the object went away!");
2844 LOGD("snapshot_thread X");
2845 return NULL;
2846}
2847
2848status_t QualcommCameraHardware::takePicture()
2849{
2850 LOGV("takePicture(%d)", mMsgEnabled);
2851 Mutex::Autolock l(&mLock);
2852
2853 // Wait for old snapshot thread to complete.
2854 mSnapshotThreadWaitLock.lock();
2855 while (mSnapshotThreadRunning) {
2856 LOGV("takePicture: waiting for old snapshot thread to complete.");
2857 mSnapshotThreadWait.wait(mSnapshotThreadWaitLock);
2858 LOGV("takePicture: old snapshot thread completed.");
2859 }
2860
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002861 if( mCurrentTarget == TARGET_MSM7630 ) {
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002862 /* Store the last frame queued for preview. This
2863 * shall be used as postview */
2864 storePreviewFrameForPostview();
2865 }
2866
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002867 //mSnapshotFormat is protected by mSnapshotThreadWaitLock
2868 if(mParameters.getPictureFormat() != 0 &&
2869 !strcmp(mParameters.getPictureFormat(),
2870 CameraParameters::PIXEL_FORMAT_RAW))
2871 mSnapshotFormat = PICTURE_FORMAT_RAW;
2872 else
2873 mSnapshotFormat = PICTURE_FORMAT_JPEG;
2874
2875 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
2876 if(!native_prepare_snapshot(mCameraControlFd)) {
2877 mSnapshotThreadWaitLock.unlock();
2878 return UNKNOWN_ERROR;
2879 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002880 }
2881
2882 stopPreviewInternal();
2883
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002884 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
2885 if (!initRaw(mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE))) {
2886 LOGE("initRaw failed. Not taking picture.");
2887 mSnapshotThreadWaitLock.unlock();
2888 return UNKNOWN_ERROR;
2889 }
2890 } else if(mSnapshotFormat == PICTURE_FORMAT_RAW ){
2891 if(!initRawSnapshot()){
2892 LOGE("initRawSnapshot failed. Not taking picture.");
2893 mSnapshotThreadWaitLock.unlock();
2894 return UNKNOWN_ERROR;
2895 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002896 }
2897
2898 mShutterLock.lock();
2899 mShutterPending = true;
2900 mShutterLock.unlock();
2901
2902 pthread_attr_t attr;
2903 pthread_attr_init(&attr);
2904 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2905 mSnapshotThreadRunning = !pthread_create(&mSnapshotThread,
2906 &attr,
2907 snapshot_thread,
2908 NULL);
2909 mSnapshotThreadWaitLock.unlock();
2910
2911 LOGV("takePicture: X");
2912 return mSnapshotThreadRunning ? NO_ERROR : UNKNOWN_ERROR;
2913}
2914
2915status_t QualcommCameraHardware::cancelPicture()
2916{
2917 status_t rc;
2918 LOGV("cancelPicture: E");
2919 rc = native_stop_snapshot(mCameraControlFd) ? NO_ERROR : UNKNOWN_ERROR;
2920 LOGV("cancelPicture: X: %d", rc);
2921 return rc;
2922}
2923
2924status_t QualcommCameraHardware::setParameters(const CameraParameters& params)
2925{
2926 LOGV("setParameters: E params = %p", &params);
2927
2928 Mutex::Autolock l(&mLock);
2929 status_t rc, final_rc = NO_ERROR;
2930
2931 if ((rc = setPreviewSize(params))) final_rc = rc;
2932 if ((rc = setPictureSize(params))) final_rc = rc;
2933 if ((rc = setJpegQuality(params))) final_rc = rc;
2934 if ((rc = setAntibanding(params))) final_rc = rc;
Apurva Rajguru55562b02009-12-03 12:25:35 -08002935 if ((rc = setAutoExposure(params))) final_rc = rc;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002936 if ((rc = setWhiteBalance(params))) final_rc = rc;
Vamshidhar Kondrae7b9b5a2010-02-25 15:40:37 +05302937 if ((rc = setEffect(params))) final_rc = rc;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002938 if ((rc = setFlash(params))) final_rc = rc;
2939 if ((rc = setGpsLocation(params))) final_rc = rc;
2940 if ((rc = setRotation(params))) final_rc = rc;
2941 if ((rc = setZoom(params))) final_rc = rc;
2942 if ((rc = setFocusMode(params))) final_rc = rc;
2943 if ((rc = setOrientation(params))) final_rc = rc;
Nishant Panditc8c1ee72009-12-03 16:24:02 +05302944 if ((rc = setBrightness(params))) final_rc = rc;
2945 if ((rc = setLensshadeValue(params))) final_rc = rc;
2946 if ((rc = setISOValue(params))) final_rc = rc;
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002947 if ((rc = setPictureFormat(params))) final_rc = rc;
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08002948 if ((rc = setSharpness(params))) final_rc = rc;
2949 if ((rc = setContrast(params))) final_rc = rc;
2950 if ((rc = setSaturation(params))) final_rc = rc;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002951
2952 LOGV("setParameters: X");
2953 return final_rc;
2954}
2955
2956CameraParameters QualcommCameraHardware::getParameters() const
2957{
2958 LOGV("getParameters: EX");
2959 return mParameters;
2960}
2961
2962status_t QualcommCameraHardware::sendCommand(int32_t command, int32_t arg1,
2963 int32_t arg2)
2964{
2965 LOGV("sendCommand: EX");
2966 return BAD_VALUE;
2967}
2968
2969extern "C" sp<CameraHardwareInterface> openCameraHardware()
2970{
2971 LOGV("openCameraHardware: call createInstance");
2972 return QualcommCameraHardware::createInstance();
2973}
2974
2975wp<QualcommCameraHardware> QualcommCameraHardware::singleton;
2976
2977// If the hardware already exists, return a strong pointer to the current
2978// object. If not, create a new hardware object, put it in the singleton,
2979// and return it.
2980sp<CameraHardwareInterface> QualcommCameraHardware::createInstance()
2981{
2982 LOGD("createInstance: E");
2983
2984 Mutex::Autolock lock(&singleton_lock);
2985
2986 // Wait until the previous release is done.
2987 while (singleton_releasing) {
2988 LOGD("Wait for previous release.");
2989 singleton_wait.wait(singleton_lock);
2990 }
2991
2992 if (singleton != 0) {
2993 sp<CameraHardwareInterface> hardware = singleton.promote();
2994 if (hardware != 0) {
2995 LOGD("createInstance: X return existing hardware=%p", &(*hardware));
2996 return hardware;
2997 }
2998 }
2999
3000 {
3001 struct stat st;
3002 int rc = stat("/dev/oncrpc", &st);
3003 if (rc < 0) {
3004 LOGD("createInstance: X failed to create hardware: %s", strerror(errno));
3005 return NULL;
3006 }
3007 }
3008
3009 QualcommCameraHardware *cam = new QualcommCameraHardware();
3010 sp<QualcommCameraHardware> hardware(cam);
3011 singleton = hardware;
3012
3013 if (!cam->startCamera()) {
3014 LOGE("%s: startCamera failed!", __FUNCTION__);
3015 return NULL;
3016 }
3017
3018 cam->initDefaultParameters();
3019 LOGD("createInstance: X created hardware=%p", &(*hardware));
3020 return hardware;
3021}
3022
3023// For internal use only, hence the strong pointer to the derived type.
3024sp<QualcommCameraHardware> QualcommCameraHardware::getInstance()
3025{
3026 sp<CameraHardwareInterface> hardware = singleton.promote();
3027 if (hardware != 0) {
3028 // LOGV("getInstance: X old instance of hardware");
3029 return sp<QualcommCameraHardware>(static_cast<QualcommCameraHardware*>(hardware.get()));
3030 } else {
3031 LOGV("getInstance: X new instance of hardware");
3032 return sp<QualcommCameraHardware>();
3033 }
3034}
Sravankb4f5f1c2010-01-21 11:06:17 +05303035void QualcommCameraHardware::receiveRecordingFrame(struct msm_frame *frame)
3036{
3037 LOGV("receiveRecordingFrame E");
3038 // post busy frame
3039 if (frame)
3040 {
3041 cam_frame_post_video (frame);
3042 }
3043 else LOGE("in receiveRecordingFrame frame is NULL");
3044 LOGV("receiveRecordingFrame X");
3045}
3046
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003047
Mohan Kandrad9efed92010-01-15 19:08:39 -08003048bool QualcommCameraHardware::native_zoom_image(int fd, int srcOffset, int dstOffSet, common_crop_t *crop)
Mohan Kandra284966d2010-01-05 13:39:15 -08003049{
3050 int result = 0;
3051 struct mdp_blit_req *e;
3052 struct timeval td1, td2;
3053
Mohan Kandra284966d2010-01-05 13:39:15 -08003054 /* Initialize yuv structure */
3055 zoomImage.list.count = 1;
3056
3057 e = &zoomImage.list.req[0];
3058
3059 e->src.width = previewWidth;
3060 e->src.height = previewHeight;
3061 e->src.format = MDP_Y_CBCR_H2V2;
Mohan Kandrad9efed92010-01-15 19:08:39 -08003062 e->src.offset = srcOffset;
3063 e->src.memory_id = fd;
Mohan Kandra284966d2010-01-05 13:39:15 -08003064
3065 e->dst.width = previewWidth;
3066 e->dst.height = previewHeight;
3067 e->dst.format = MDP_Y_CBCR_H2V2;
Mohan Kandrad9efed92010-01-15 19:08:39 -08003068 e->dst.offset = dstOffSet;
3069 e->dst.memory_id = fd;
Mohan Kandra284966d2010-01-05 13:39:15 -08003070
3071 e->transp_mask = 0xffffffff;
3072 e->flags = 0;
3073 e->alpha = 0xff;
3074 if (crop->in2_w != 0 || crop->in2_h != 0) {
3075 e->src_rect.x = (crop->out2_w - crop->in2_w + 1) / 2 - 1;
3076 e->src_rect.y = (crop->out2_h - crop->in2_h + 1) / 2 - 1;
3077 e->src_rect.w = crop->in2_w;
3078 e->src_rect.h = crop->in2_h;
3079 } else {
3080 e->src_rect.x = 0;
3081 e->src_rect.y = 0;
3082 e->src_rect.w = previewWidth;
3083 e->src_rect.h = previewHeight;
3084 }
Mohan Kandrad9efed92010-01-15 19:08:39 -08003085 //LOGV(" native_zoom : SRC_RECT : x,y = %d,%d \t w,h = %d, %d",
3086 // e->src_rect.x, e->src_rect.y, e->src_rect.w, e->src_rect.h);
Mohan Kandra284966d2010-01-05 13:39:15 -08003087
3088 e->dst_rect.x = 0;
3089 e->dst_rect.y = 0;
3090 e->dst_rect.w = previewWidth;
3091 e->dst_rect.h = previewHeight;
3092
3093 result = ioctl(fb_fd, MSMFB_BLIT, &zoomImage.list);
3094 if (result < 0) {
3095 LOGE("MSM_FBIOBLT failed! line=%d\n", __LINE__);
3096 return FALSE;
3097 }
3098 return TRUE;
3099}
3100
Mohan Kandrabad0eaa2010-02-04 15:11:54 -08003101void QualcommCameraHardware::debugShowPreviewFPS() const
Mohan Kandra740cfce2010-01-07 12:58:24 -08003102{
3103 static int mFrameCount;
3104 static int mLastFrameCount = 0;
3105 static nsecs_t mLastFpsTime = 0;
3106 static float mFps = 0;
3107 mFrameCount++;
3108 nsecs_t now = systemTime();
3109 nsecs_t diff = now - mLastFpsTime;
3110 if (diff > ms2ns(250)) {
3111 mFps = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
Mohan Kandrabad0eaa2010-02-04 15:11:54 -08003112 LOGI("Preview Frames Per Second: %.4f", mFps);
Mohan Kandra740cfce2010-01-07 12:58:24 -08003113 mLastFpsTime = now;
3114 mLastFrameCount = mFrameCount;
3115 }
3116}
3117
Mohan Kandrabad0eaa2010-02-04 15:11:54 -08003118void QualcommCameraHardware::debugShowVideoFPS() const
3119{
3120 static int mFrameCount;
3121 static int mLastFrameCount = 0;
3122 static nsecs_t mLastFpsTime = 0;
3123 static float mFps = 0;
3124 mFrameCount++;
3125 nsecs_t now = systemTime();
3126 nsecs_t diff = now - mLastFpsTime;
3127 if (diff > ms2ns(250)) {
3128 mFps = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
3129 LOGI("Video Frames Per Second: %.4f", mFps);
3130 mLastFpsTime = now;
3131 mLastFrameCount = mFrameCount;
3132 }
3133}
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003134void QualcommCameraHardware::receivePreviewFrame(struct msm_frame *frame)
3135{
3136// LOGV("receivePreviewFrame E");
3137
3138 if (!mCameraRunning) {
3139 LOGE("ignoring preview callback--camera has been stopped");
3140 return;
3141 }
3142
Mohan Kandra740cfce2010-01-07 12:58:24 -08003143 if (UNLIKELY(mDebugFps)) {
Mohan Kandrabad0eaa2010-02-04 15:11:54 -08003144 debugShowPreviewFPS();
Mohan Kandra740cfce2010-01-07 12:58:24 -08003145 }
3146
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003147 mCallbackLock.lock();
3148 int msgEnabled = mMsgEnabled;
3149 data_callback pcb = mDataCallback;
3150 void *pdata = mCallbackCookie;
3151 data_callback_timestamp rcb = mDataCallbackTimestamp;
3152 void *rdata = mCallbackCookie;
3153 mCallbackLock.unlock();
3154
3155 // Find the offset within the heap of the current buffer.
Mohan Kandra284966d2010-01-05 13:39:15 -08003156 ssize_t offset_addr =
Mohan Kandrad9efed92010-01-15 19:08:39 -08003157 (ssize_t)frame->buffer - (ssize_t)mPreviewHeap->mHeap->base();
3158 ssize_t offset = offset_addr / mPreviewHeap->mAlignedBufferSize;
Mohan Kandra284966d2010-01-05 13:39:15 -08003159
3160 common_crop_t *crop = (common_crop_t *) (frame->cropinfo);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003161
3162 mInPreviewCallback = true;
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003163 if(mUseOverlay) {
3164 if(mOverlay != NULL) {
3165 mOverlayLock.lock();
Mohan Kandrad9efed92010-01-15 19:08:39 -08003166 mOverlay->setFd(mPreviewHeap->mHeap->getHeapID());
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003167 if (crop->in2_w != 0 || crop->in2_h != 0) {
3168 zoomCropInfo.x = (crop->out2_w - crop->in2_w + 1) / 2 - 1;
3169 zoomCropInfo.y = (crop->out2_h - crop->in2_h + 1) / 2 - 1;
3170 zoomCropInfo.w = crop->in2_w;
3171 zoomCropInfo.h = crop->in2_h;
3172 mOverlay->setCrop(zoomCropInfo.x, zoomCropInfo.y,
3173 zoomCropInfo.w, zoomCropInfo.h);
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08003174 } else {
3175 // Reset zoomCropInfo variables. This will ensure that
3176 // stale values wont be used for postview
3177 zoomCropInfo.w = crop->in2_w;
3178 zoomCropInfo.h = crop->in2_h;
3179 }
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003180 mOverlay->queueBuffer((void *)offset_addr);
3181 mLastQueuedFrame = (void *)frame->buffer;
3182 mOverlayLock.unlock();
3183 }
Mohan Kandra284966d2010-01-05 13:39:15 -08003184 } else {
Mohan Kandrad9efed92010-01-15 19:08:39 -08003185 if (crop->in2_w != 0 || crop->in2_h != 0) {
3186 dstOffset = (dstOffset + 1) % NUM_MORE_BUFS;
3187 offset = kPreviewBufferCount + dstOffset;
3188 ssize_t dstOffset_addr = offset * mPreviewHeap->mAlignedBufferSize;
3189 if( !native_zoom_image(mPreviewHeap->mHeap->getHeapID(),
3190 offset_addr, dstOffset_addr, crop)) {
3191 LOGE(" Error while doing MDP zoom ");
Kiran Kumar H N1ece71c2010-03-30 10:31:21 -07003192 offset = offset_addr / mPreviewHeap->mAlignedBufferSize;
Mohan Kandrad9efed92010-01-15 19:08:39 -08003193 }
3194 }
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08003195 }
Mohan Kandrad9efed92010-01-15 19:08:39 -08003196 if (pcb != NULL && (msgEnabled & CAMERA_MSG_PREVIEW_FRAME))
3197 pcb(CAMERA_MSG_PREVIEW_FRAME, mPreviewHeap->mBuffers[offset],
3198 pdata);
3199
Sravankb4f5f1c2010-01-21 11:06:17 +05303200 // If output is NOT enabled (targets otherthan 7x30 currently..)
Mohan Kandraf1ebf982010-02-02 15:25:43 -08003201 if( (mCurrentTarget != TARGET_MSM7630 ) && (mCurrentTarget != TARGET_QSD8250)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05303202 if(rcb != NULL && (msgEnabled & CAMERA_MSG_VIDEO_FRAME)) {
3203 rcb(systemTime(), CAMERA_MSG_VIDEO_FRAME, mPreviewHeap->mBuffers[offset], rdata);
3204 Mutex::Autolock rLock(&mRecordFrameLock);
3205 if (mReleasedRecordingFrame != true) {
3206 LOGV("block waiting for frame release");
3207 mRecordWait.wait(mRecordFrameLock);
3208 LOGV("frame released, continuing");
3209 }
3210 mReleasedRecordingFrame = false;
3211 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003212 }
3213 mInPreviewCallback = false;
3214
3215// LOGV("receivePreviewFrame X");
3216}
3217
Sravankb4f5f1c2010-01-21 11:06:17 +05303218
3219bool QualcommCameraHardware::initRecord()
3220{
Apurva Rajguruc73c1722010-04-15 17:39:11 -07003221 char *pmem_region;
3222
Sravankb4f5f1c2010-01-21 11:06:17 +05303223 LOGV("initREcord E");
3224
3225 mRecordFrameSize = (mDimension.video_width * mDimension.video_height *3)/2;
Apurva Rajguruc73c1722010-04-15 17:39:11 -07003226
3227 if( mCurrentTarget == TARGET_QSD8250 )
3228 pmem_region = "/dev/pmem_smipool";
3229 else
3230 pmem_region = "/dev/pmem_adsp";
3231
3232 mRecordHeap = new PmemPool(pmem_region,
Sravankb4f5f1c2010-01-21 11:06:17 +05303233 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
3234 mCameraControlFd,
3235 MSM_PMEM_VIDEO,
3236 mRecordFrameSize,
3237 kRecordBufferCount,
3238 mRecordFrameSize,
3239 "record");
Apurva Rajguruc73c1722010-04-15 17:39:11 -07003240
Sravankb4f5f1c2010-01-21 11:06:17 +05303241 if (!mRecordHeap->initialized()) {
3242 mRecordHeap.clear();
3243 LOGE("initRecord X: could not initialize record heap.");
3244 return false;
3245 }
3246 for (int cnt = 0; cnt < kRecordBufferCount; cnt++) {
3247 recordframes[cnt].fd = mRecordHeap->mHeap->getHeapID();
3248 recordframes[cnt].buffer =
3249 (uint32_t)mRecordHeap->mHeap->base() + mRecordHeap->mAlignedBufferSize * cnt;
3250 recordframes[cnt].y_off = 0;
3251 recordframes[cnt].cbcr_off = mDimension.video_width * mDimension.video_height;
3252 recordframes[cnt].path = OUTPUT_TYPE_V;
3253
3254 LOGV ("initRecord : record heap , video buffers buffer=%lu fd=%d y_off=%d cbcr_off=%d \n",
3255 (unsigned long)recordframes[cnt].buffer, recordframes[cnt].fd, recordframes[cnt].y_off,
3256 recordframes[cnt].cbcr_off);
3257 }
3258
3259 // initial setup : buffers 1,2,3 with kernel , 4 with camframe , 5,6,7,8 in free Q
3260 // flush the busy Q
3261 cam_frame_flush_video();
3262
Mohan Kandra156d0ac2010-01-25 16:59:17 -08003263 mVideoThreadWaitLock.lock();
3264 while (mVideoThreadRunning) {
3265 LOGV("initRecord: waiting for old video thread to complete.");
3266 mVideoThreadWait.wait(mVideoThreadWaitLock);
3267 LOGV("initRecord : old video thread completed.");
3268 }
3269 mVideoThreadWaitLock.unlock();
3270
Sravankdf7a9202010-02-08 15:02:51 +05303271 // flush free queue and add 5,6,7,8 buffers.
3272 LINK_cam_frame_flush_free_video();
3273 for(int i=ACTIVE_VIDEO_BUFFERS+1;i <kRecordBufferCount; i++)
3274 LINK_camframe_free_video(&recordframes[i]);
Sravankb4f5f1c2010-01-21 11:06:17 +05303275 LOGV("initREcord X");
3276
3277 return true;
3278}
3279
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003280status_t QualcommCameraHardware::startRecording()
3281{
3282 LOGV("startRecording E");
Sravankb4f5f1c2010-01-21 11:06:17 +05303283 int ret;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003284 Mutex::Autolock l(&mLock);
3285 mReleasedRecordingFrame = false;
Sravankb4f5f1c2010-01-21 11:06:17 +05303286 if( (ret=startPreviewInternal())== NO_ERROR){
Mohan Kandraf1ebf982010-02-02 15:25:43 -08003287 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05303288 LOGV(" in startREcording : calling native_start_recording");
3289 native_start_recording(mCameraControlFd);
3290 recordingState = 1;
Sravank64461e82010-02-25 15:10:09 +05303291 // Remove the left out frames in busy Q and them in free Q.
3292 // this should be done before starting video_thread so that,
3293 // frames in previous recording are flushed out.
3294 LOGV("frames in busy Q = %d", g_busy_frame_queue.num_of_frames);
3295 while((g_busy_frame_queue.num_of_frames) >0){
3296 msm_frame* vframe = cam_frame_get_video ();
3297 LINK_camframe_free_video(vframe);
3298 }
3299 LOGV("frames in busy Q = %d after deQueing", g_busy_frame_queue.num_of_frames);
3300
Sravankdf7a9202010-02-08 15:02:51 +05303301 // Start video thread and wait for busy frames to be encoded, this thread
3302 // should be closed in stopRecording
3303 mVideoThreadWaitLock.lock();
3304 mVideoThreadExit = 0;
3305 pthread_attr_t attr;
3306 pthread_attr_init(&attr);
3307 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
3308 mVideoThreadRunning = pthread_create(&mVideoThread,
3309 &attr,
3310 video_thread,
3311 NULL);
3312 mVideoThreadWaitLock.unlock();
3313 // Remove the left out frames in busy Q and them in free Q.
Sravankb4f5f1c2010-01-21 11:06:17 +05303314 }
3315 }
3316 return ret;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003317}
3318
3319void QualcommCameraHardware::stopRecording()
3320{
3321 LOGV("stopRecording: E");
3322 Mutex::Autolock l(&mLock);
3323 {
3324 mRecordFrameLock.lock();
3325 mReleasedRecordingFrame = true;
3326 mRecordWait.signal();
3327 mRecordFrameLock.unlock();
3328
Sravankdf7a9202010-02-08 15:02:51 +05303329 if(mDataCallback && !(mCurrentTarget == TARGET_QSD8250) &&
3330 (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003331 LOGV("stopRecording: X, preview still in progress");
3332 return;
3333 }
3334 }
Sravankb4f5f1c2010-01-21 11:06:17 +05303335 // If output2 enabled, exit video thread, invoke stop recording ioctl
Mohan Kandraf1ebf982010-02-02 15:25:43 -08003336 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05303337 mVideoThreadWaitLock.lock();
3338 mVideoThreadExit = 1;
3339 mVideoThreadWaitLock.unlock();
3340 native_stop_recording(mCameraControlFd);
Srinivasan Kannanfc3915c2010-03-18 10:54:40 -07003341
3342 pthread_mutex_lock(&(g_busy_frame_queue.mut));
3343 pthread_cond_signal(&(g_busy_frame_queue.wait));
3344 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
Sravankb4f5f1c2010-01-21 11:06:17 +05303345 }
3346 else // for other targets where output2 is not enabled
3347 stopPreviewInternal();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003348
Sravankb4f5f1c2010-01-21 11:06:17 +05303349 recordingState = 0; // recording not started
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003350 LOGV("stopRecording: X");
3351}
3352
3353void QualcommCameraHardware::releaseRecordingFrame(
3354 const sp<IMemory>& mem __attribute__((unused)))
3355{
3356 LOGV("releaseRecordingFrame E");
3357 Mutex::Autolock rLock(&mRecordFrameLock);
3358 mReleasedRecordingFrame = true;
3359 mRecordWait.signal();
Sravankb4f5f1c2010-01-21 11:06:17 +05303360
3361 // Ff 7x30 : add the frame to the free camframe queue
Mohan Kandraf1ebf982010-02-02 15:25:43 -08003362 if( (mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05303363 ssize_t offset;
3364 size_t size;
3365 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
3366 msm_frame* releaseframe = NULL;
3367 LOGV(" in release recording frame : heap base %d offset %d buffer %d ", heap->base(), offset, heap->base() + offset );
3368 int cnt;
3369 for (cnt = 0; cnt < kRecordBufferCount; cnt++) {
3370 if((unsigned int)recordframes[cnt].buffer == (unsigned int)(heap->base()+ offset)){
3371 LOGV("in release recording frame found match , releasing buffer %d", (unsigned int)recordframes[cnt].buffer);
3372 releaseframe = &recordframes[cnt];
3373 break;
3374 }
3375 }
3376 if(cnt < kRecordBufferCount) {
3377 // do this only if frame thread is running
3378 mFrameThreadWaitLock.lock();
3379 if(mFrameThreadRunning )
3380 LINK_camframe_free_video(releaseframe);
3381
3382 mFrameThreadWaitLock.unlock();
3383 } else {
3384 LOGE("in release recordingframe XXXXX error , buffer not found");
3385 for (int i=0; i< kRecordBufferCount; i++) {
3386 LOGE(" recordframes[%d].buffer = %d", i, (unsigned int)recordframes[i].buffer);
3387 }
3388 }
3389 }
3390
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003391 LOGV("releaseRecordingFrame X");
3392}
3393
3394bool QualcommCameraHardware::recordingEnabled()
3395{
3396 return mCameraRunning && mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME);
3397}
3398
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08003399void QualcommCameraHardware::notifyShutter(common_crop_t *crop, bool mPlayShutterSoundOnly)
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003400{
3401 mShutterLock.lock();
3402 image_rect_type size;
3403
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08003404 if(mPlayShutterSoundOnly) {
3405 /* At this point, invoke Notify Callback to play shutter sound only.
3406 * We want to call notify callback again when we have the
3407 * yuv picture ready. This is to reduce blanking at the time
3408 * of displaying postview frame. Using ext2 to indicate whether
3409 * to play shutter sound only or register the postview buffers.
3410 */
3411 mNotifyCallback(CAMERA_MSG_SHUTTER, 0, mPlayShutterSoundOnly,
3412 mCallbackCookie);
3413 mShutterLock.unlock();
3414 return;
3415 }
3416
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003417 if (mShutterPending && mNotifyCallback && (mMsgEnabled & CAMERA_MSG_SHUTTER)) {
3418 LOGV("out2_w=%d, out2_h=%d, in2_w=%d, in2_h=%d",
3419 crop->out2_w, crop->out2_h, crop->in2_w, crop->in2_h);
3420 LOGV("out1_w=%d, out1_h=%d, in1_w=%d, in1_h=%d",
3421 crop->out1_w, crop->out1_h, crop->in1_w, crop->in1_h);
3422
3423 // To workaround a bug in MDP which happens if either
3424 // dimension > 2048, we display the thumbnail instead.
3425 mDisplayHeap = mRawHeap;
3426 if (crop->in1_w == 0 || crop->in1_h == 0) {
3427 // Full size
3428 size.width = mDimension.picture_width;
3429 size.height = mDimension.picture_height;
3430 if (size.width > 2048 || size.height > 2048) {
3431 size.width = mDimension.ui_thumbnail_width;
3432 size.height = mDimension.ui_thumbnail_height;
3433 mDisplayHeap = mThumbnailHeap;
3434 }
3435 } else {
3436 // Cropped
Srinivasan Kannan5701a942010-04-15 16:17:21 -07003437 size.width = (crop->in2_w + jpegPadding) & ~1;
3438 size.height = (crop->in2_h + jpegPadding) & ~1;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003439 if (size.width > 2048 || size.height > 2048) {
Srinivasan Kannan5701a942010-04-15 16:17:21 -07003440 size.width = (crop->in1_w + jpegPadding) & ~1;
3441 size.height = (crop->in1_h + jpegPadding) & ~1;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003442 mDisplayHeap = mThumbnailHeap;
3443 }
3444 }
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08003445 /* Now, invoke Notify Callback to unregister preview buffer
3446 * and register postview buffer with surface flinger. Set ext2
3447 * as 0 to indicate not to play shutter sound.
3448 */
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003449 mNotifyCallback(CAMERA_MSG_SHUTTER, (int32_t)&size, 0,
3450 mCallbackCookie);
3451 mShutterPending = false;
3452 }
3453 mShutterLock.unlock();
3454}
3455
3456static void receive_shutter_callback(common_crop_t *crop)
3457{
3458 LOGV("receive_shutter_callback: E");
3459 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
3460 if (obj != 0) {
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08003461 /* Just play shutter sound at this time */
3462 obj->notifyShutter(crop, TRUE);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003463 }
3464 LOGV("receive_shutter_callback: X");
3465}
3466
3467// Crop the picture in place.
3468static void crop_yuv420(uint32_t width, uint32_t height,
3469 uint32_t cropped_width, uint32_t cropped_height,
3470 uint8_t *image)
3471{
3472 uint32_t i, x, y;
3473 uint8_t* chroma_src, *chroma_dst;
3474
3475 // Calculate the start position of the cropped area.
3476 x = (width - cropped_width) / 2;
3477 y = (height - cropped_height) / 2;
3478 x &= ~1;
3479 y &= ~1;
3480
3481 // Copy luma component.
3482 for(i = 0; i < cropped_height; i++)
3483 memcpy(image + i * cropped_width,
3484 image + width * (y + i) + x,
3485 cropped_width);
3486
3487 chroma_src = image + width * height;
3488 chroma_dst = image + cropped_width * cropped_height;
3489
3490 // Copy chroma components.
3491 cropped_height /= 2;
3492 y /= 2;
3493 for(i = 0; i < cropped_height; i++)
3494 memcpy(chroma_dst + i * cropped_width,
3495 chroma_src + width * (y + i) + x,
3496 cropped_width);
3497}
3498
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08003499
3500void QualcommCameraHardware::receiveRawSnapshot(){
3501 LOGV("receiveRawSnapshot E");
3502
3503 Mutex::Autolock cbLock(&mCallbackLock);
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08003504 /* Issue notifyShutter with mPlayShutterSoundOnly as TRUE */
3505 notifyShutter(&mCrop, TRUE);
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08003506
3507 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
3508
3509 if(native_get_picture(mCameraControlFd, &mCrop) == false) {
3510 LOGE("receiveRawSnapshot X: native_get_picture failed!");
3511 return;
3512 }
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08003513 /* Its necessary to issue another notifyShutter here with
3514 * mPlayShutterSoundOnly as FALSE, since that is when the
3515 * preview buffers are unregistered with the surface flinger.
3516 * That is necessary otherwise the preview memory wont be
3517 * deallocated.
3518 */
3519 notifyShutter(&mCrop, FALSE);
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08003520
3521 //Create a Ashmem heap to copy data from PMem heap for application layer
3522 if(mRawSnapshotAshmemHeap != NULL){
3523 LOGV("receiveRawSnapshot: clearing old mRawSnapShotAshmemHeap.");
3524 mRawSnapshotAshmemHeap.clear();
3525 }
3526 mRawSnapshotAshmemHeap = new AshmemPool(
3527 mRawSnapShotPmemHeap->mBufferSize,
3528 mRawSnapShotPmemHeap->mNumBuffers,
3529 mRawSnapShotPmemHeap->mFrameSize,
3530 "raw ashmem snapshot camera"
3531 );
3532
3533 if(!mRawSnapshotAshmemHeap->initialized()){
3534 LOGE("receiveRawSnapshot X: error initializing mRawSnapshotHeap");
3535 deinitRawSnapshot();
3536 return;
3537 }
3538
3539 memcpy(mRawSnapshotAshmemHeap->mHeap->base(),
3540 mRawSnapShotPmemHeap->mHeap->base(),
3541 mRawSnapShotPmemHeap->mHeap->getSize());
Nishant Panditb861be52010-03-02 16:43:49 +05303542 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE))
3543 mDataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mRawSnapshotAshmemHeap->mBuffers[0],
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08003544 mCallbackCookie);
3545
3546 }
3547
3548 //cleanup
3549 deinitRawSnapshot();
3550
3551 LOGV("receiveRawSnapshot X");
3552}
3553
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003554void QualcommCameraHardware::receiveRawPicture()
3555{
3556 LOGV("receiveRawPicture: E");
3557
3558 Mutex::Autolock cbLock(&mCallbackLock);
3559 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_RAW_IMAGE)) {
3560 if(native_get_picture(mCameraControlFd, &mCrop) == false) {
3561 LOGE("getPicture failed!");
3562 return;
3563 }
3564 mCrop.in1_w &= ~1;
3565 mCrop.in1_h &= ~1;
3566 mCrop.in2_w &= ~1;
3567 mCrop.in2_h &= ~1;
3568
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003569
3570 // Crop the image if zoomed.
Srinivasan Kannan5701a942010-04-15 16:17:21 -07003571 if (mCrop.in2_w != 0 && mCrop.in2_h != 0 &&
3572 ((mCrop.in2_w + jpegPadding) < mCrop.out2_w) &&
3573 ((mCrop.in2_h + jpegPadding) < mCrop.out2_h) &&
3574 ((mCrop.in1_w + jpegPadding) < mCrop.out1_w) &&
3575 ((mCrop.in1_h + jpegPadding) < mCrop.out1_h) ) {
3576
3577 // By the time native_get_picture returns, picture is taken. Call
3578 // shutter callback if cam config thread has not done that.
3579 notifyShutter(&mCrop, FALSE);
3580 crop_yuv420(mCrop.out2_w, mCrop.out2_h, (mCrop.in2_w + jpegPadding), (mCrop.in2_h + jpegPadding),
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003581 (uint8_t *)mRawHeap->mHeap->base());
Srinivasan Kannan5701a942010-04-15 16:17:21 -07003582 crop_yuv420(mCrop.out1_w, mCrop.out1_h, (mCrop.in1_w + jpegPadding), (mCrop.in1_h + jpegPadding),
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003583 (uint8_t *)mThumbnailHeap->mHeap->base());
Srinivasan Kannan5701a942010-04-15 16:17:21 -07003584
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003585 // We do not need jpeg encoder to upscale the image. Set the new
3586 // dimension for encoder.
Srinivasan Kannan5701a942010-04-15 16:17:21 -07003587 mDimension.orig_picture_dx = mCrop.in2_w + jpegPadding;
3588 mDimension.orig_picture_dy = mCrop.in2_h + jpegPadding;
3589 mDimension.thumbnail_width = mCrop.in1_w + jpegPadding;
3590 mDimension.thumbnail_height = mCrop.in1_h + jpegPadding;
3591 }else {
3592 memset(&mCrop, 0 ,sizeof(mCrop));
3593 // By the time native_get_picture returns, picture is taken. Call
3594 // shutter callback if cam config thread has not done that.
3595 notifyShutter(&mCrop, FALSE);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003596 }
3597
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003598 if( mUseOverlay && (mOverlay != NULL) ) {
3599 mOverlay->setFd(mPostViewHeap->mHeap->getHeapID());
3600 if( zoomCropInfo.w !=0 && zoomCropInfo.h !=0) {
3601 LOGD(" zoomCropInfo non-zero, setting crop ");
3602 mOverlay->setCrop(zoomCropInfo.x, zoomCropInfo.y,
3603 zoomCropInfo.w, zoomCropInfo.h);
3604 }
3605 LOGD(" Queueing Postview for display ");
3606 mOverlay->queueBuffer((void *)0);
3607 }
Nishant Panditb861be52010-03-02 16:43:49 +05303608 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_RAW_IMAGE))
3609 mDataCallback(CAMERA_MSG_RAW_IMAGE, mDisplayHeap->mBuffers[0],
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003610 mCallbackCookie);
3611 }
3612 else LOGV("Raw-picture callback was canceled--skipping.");
3613
3614 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
3615 mJpegSize = 0;
3616 if (LINK_jpeg_encoder_init()) {
3617 if(native_jpeg_encode()) {
3618 LOGV("receiveRawPicture: X (success)");
3619 return;
3620 }
3621 LOGE("jpeg encoding failed");
3622 }
3623 else LOGE("receiveRawPicture X: jpeg_encoder_init failed.");
3624 }
3625 else LOGV("JPEG callback is NULL, not encoding image.");
3626 deinitRaw();
3627 LOGV("receiveRawPicture: X");
3628}
3629
3630void QualcommCameraHardware::receiveJpegPictureFragment(
3631 uint8_t *buff_ptr, uint32_t buff_size)
3632{
3633 uint32_t remaining = mJpegHeap->mHeap->virtualSize();
3634 remaining -= mJpegSize;
3635 uint8_t *base = (uint8_t *)mJpegHeap->mHeap->base();
3636
3637 LOGV("receiveJpegPictureFragment size %d", buff_size);
3638 if (buff_size > remaining) {
3639 LOGE("receiveJpegPictureFragment: size %d exceeds what "
3640 "remains in JPEG heap (%d), truncating",
3641 buff_size,
3642 remaining);
3643 buff_size = remaining;
3644 }
3645 memcpy(base + mJpegSize, buff_ptr, buff_size);
3646 mJpegSize += buff_size;
3647}
3648
3649void QualcommCameraHardware::receiveJpegPicture(void)
3650{
3651 LOGV("receiveJpegPicture: E image (%d uint8_ts out of %d)",
3652 mJpegSize, mJpegHeap->mBufferSize);
3653 Mutex::Autolock cbLock(&mCallbackLock);
3654
3655 int index = 0, rc;
3656
3657 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
3658 // The reason we do not allocate into mJpegHeap->mBuffers[offset] is
3659 // that the JPEG image's size will probably change from one snapshot
3660 // to the next, so we cannot reuse the MemoryBase object.
3661 sp<MemoryBase> buffer = new
3662 MemoryBase(mJpegHeap->mHeap,
3663 index * mJpegHeap->mBufferSize +
3664 0,
3665 mJpegSize);
3666 mDataCallback(CAMERA_MSG_COMPRESSED_IMAGE, buffer, mCallbackCookie);
3667 buffer = NULL;
3668 }
3669 else LOGV("JPEG callback was cancelled--not delivering image.");
3670
3671 LINK_jpeg_encoder_join();
3672 deinitRaw();
3673
3674 LOGV("receiveJpegPicture: X callback done.");
3675}
3676
3677bool QualcommCameraHardware::previewEnabled()
3678{
Kiran Kumar H N280d4de2010-05-05 13:40:15 -07003679 /* If overlay is used the message CAMERA_MSG_PREVIEW_FRAME would
3680 * be disabled at CameraService layer. Hence previewEnabled would
3681 * return FALSE even though preview is running. Hence check for
3682 * mOverlay not being NULL to ensure that previewEnabled returns
3683 * accurate information.
3684 */
3685 return mCameraRunning && mDataCallback &&
3686 ((mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME) || (mOverlay != NULL));
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003687}
3688
3689status_t QualcommCameraHardware::setPreviewSize(const CameraParameters& params)
3690{
3691 int width, height;
3692 params.getPreviewSize(&width, &height);
3693 LOGV("requested preview size %d x %d", width, height);
3694
3695 // Validate the preview size
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -08003696 for (size_t i = 0; i < previewSizeCount; ++i) {
3697 if (width == supportedPreviewSizes[i].width
3698 && height == supportedPreviewSizes[i].height) {
Sravank64461e82010-02-25 15:10:09 +05303699 // 720p , preview can be 768X432 (currently for 7x30 and 8k
3700 // targets)
3701 if(width == 1280 && height == 720 &&
3702 ((mCurrentTarget == TARGET_MSM7630) || (mCurrentTarget == TARGET_QSD8250))){
3703 LOGD("change preview resolution to 768X432 since recording is in 720p");
3704 mDimension.display_width = preview_sizes[2].width;
3705 mDimension.display_height= preview_sizes[2].height;
3706 }else {
3707 mDimension.display_width = width;
3708 mDimension.display_height= height;
3709 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003710 mParameters.setPreviewSize(width, height);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003711 return NO_ERROR;
3712 }
3713 }
3714 LOGE("Invalid preview size requested: %dx%d", width, height);
3715 return BAD_VALUE;
3716}
3717
3718status_t QualcommCameraHardware::setPictureSize(const CameraParameters& params)
3719{
3720 int width, height;
3721 params.getPictureSize(&width, &height);
3722 LOGV("requested picture size %d x %d", width, height);
3723
3724 // Validate the picture size
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -08003725 for (int i = 0; i < supportedPictureSizesCount; ++i) {
3726 if (width == picture_sizes_ptr[i].width
3727 && height == picture_sizes_ptr[i].height) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003728 mParameters.setPictureSize(width, height);
3729 mDimension.picture_width = width;
3730 mDimension.picture_height = height;
3731 return NO_ERROR;
3732 }
3733 }
Kiran Kumar H Nb49af212010-02-17 15:12:17 -08003734 /* Dimension not among the ones in the list. Check if
3735 * its a valid dimension, if it is, then configure the
3736 * camera accordingly. else reject it.
3737 */
3738 if( isValidDimension(width, height) ) {
3739 mParameters.setPictureSize(width, height);
3740 mDimension.picture_width = width;
3741 mDimension.picture_height = height;
3742 return NO_ERROR;
3743 } else
3744 LOGE("Invalid picture size requested: %dx%d", width, height);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003745 return BAD_VALUE;
3746}
3747
3748status_t QualcommCameraHardware::setJpegQuality(const CameraParameters& params) {
3749 status_t rc = NO_ERROR;
3750 int quality = params.getInt(CameraParameters::KEY_JPEG_QUALITY);
3751 if (quality > 0 && quality <= 100) {
3752 mParameters.set(CameraParameters::KEY_JPEG_QUALITY, quality);
3753 } else {
3754 LOGE("Invalid jpeg quality=%d", quality);
3755 rc = BAD_VALUE;
3756 }
3757
3758 quality = params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY);
3759 if (quality > 0 && quality <= 100) {
3760 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, quality);
3761 } else {
3762 LOGE("Invalid jpeg thumbnail quality=%d", quality);
3763 rc = BAD_VALUE;
3764 }
3765 return rc;
3766}
3767
3768status_t QualcommCameraHardware::setEffect(const CameraParameters& params)
3769{
Apurva Rajguru7360db42010-04-09 16:37:36 -07003770
3771 const char *str_wb = mParameters.get(CameraParameters::KEY_WHITE_BALANCE);
3772 int32_t value_wb = attr_lookup(whitebalance, sizeof(whitebalance) / sizeof(str_map), str_wb);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003773 const char *str = params.get(CameraParameters::KEY_EFFECT);
Apurva Rajguru7360db42010-04-09 16:37:36 -07003774
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003775 if (str != NULL) {
3776 int32_t value = attr_lookup(effects, sizeof(effects) / sizeof(str_map), str);
3777 if (value != NOT_FOUND) {
Mohan Kandra93f1bfb2009-12-15 16:55:33 -08003778 if(!strcmp(sensorType->name, "2mp") && (value != CAMERA_EFFECT_OFF)
3779 &&(value != CAMERA_EFFECT_MONO) && (value != CAMERA_EFFECT_NEGATIVE)
3780 &&(value != CAMERA_EFFECT_SOLARIZE) && (value != CAMERA_EFFECT_SEPIA)) {
3781 LOGE("Special effect parameter is not supported for this sensor");
3782 return NO_ERROR;
3783 }
Apurva Rajguru7360db42010-04-09 16:37:36 -07003784
3785 if(((value == CAMERA_EFFECT_MONO) || (value == CAMERA_EFFECT_NEGATIVE)
3786 || (value == CAMERA_EFFECT_AQUA) || (value == CAMERA_EFFECT_SEPIA))
3787 && (value_wb != CAMERA_WB_AUTO)) {
3788 LOGE("Color Effect value will not be set " \
3789 "when the whitebalance selected is %s", str_wb);
3790 return NO_ERROR;
3791 }
3792 else {
3793 mParameters.set(CameraParameters::KEY_EFFECT, str);
3794 bool ret = native_set_parm(CAMERA_SET_PARM_EFFECT, sizeof(value),
3795 (void *)&value);
3796 return ret ? NO_ERROR : UNKNOWN_ERROR;
3797 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003798 }
3799 }
3800 LOGE("Invalid effect value: %s", (str == NULL) ? "NULL" : str);
3801 return BAD_VALUE;
3802}
3803
Apurva Rajguru55562b02009-12-03 12:25:35 -08003804status_t QualcommCameraHardware::setAutoExposure(const CameraParameters& params)
3805{
Mohan Kandra93f1bfb2009-12-15 16:55:33 -08003806 if(!strcmp(sensorType->name, "2mp")) {
3807 LOGE("Auto Exposure not supported for this sensor");
3808 return NO_ERROR;
3809 }
Apurva Rajguru55562b02009-12-03 12:25:35 -08003810 const char *str = params.get(CameraParameters::KEY_AUTO_EXPOSURE);
3811 if (str != NULL) {
3812 int32_t value = attr_lookup(autoexposure, sizeof(autoexposure) / sizeof(str_map), str);
3813 if (value != NOT_FOUND) {
3814 mParameters.set(CameraParameters::KEY_AUTO_EXPOSURE, str);
3815 bool ret = native_set_parm(CAMERA_SET_PARM_EXPOSURE, sizeof(value),
3816 (void *)&value);
3817 return ret ? NO_ERROR : UNKNOWN_ERROR;
3818 }
3819 }
3820 LOGE("Invalid auto exposure value: %s", (str == NULL) ? "NULL" : str);
3821 return BAD_VALUE;
3822}
3823
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003824status_t QualcommCameraHardware::setSharpness(const CameraParameters& params)
3825{
3826 if(!strcmp(sensorType->name, "2mp")) {
3827 LOGE("Sharpness not supported for this sensor");
3828 return NO_ERROR;
3829 }
3830 int sharpness = params.getInt(CameraParameters::KEY_SHARPNESS);
3831 if((sharpness < CAMERA_MIN_SHARPNESS
3832 || sharpness > CAMERA_MAX_SHARPNESS))
3833 return UNKNOWN_ERROR;
Srinivasan Kannan551fd262010-01-14 17:48:30 -08003834
3835 LOGV("setting sharpness %d", sharpness);
3836 mParameters.set(CameraParameters::KEY_SHARPNESS, sharpness);
3837 bool ret = native_set_parm(CAMERA_SET_PARM_SHARPNESS, sizeof(sharpness),
3838 (void *)&sharpness);
3839 return ret ? NO_ERROR : UNKNOWN_ERROR;
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003840}
3841
3842status_t QualcommCameraHardware::setContrast(const CameraParameters& params)
3843{
3844 if(!strcmp(sensorType->name, "2mp")) {
3845 LOGE("Contrast not supported for this sensor");
3846 return NO_ERROR;
3847 }
3848 int contrast = params.getInt(CameraParameters::KEY_CONTRAST);
3849 if((contrast < CAMERA_MIN_CONTRAST)
3850 || (contrast > CAMERA_MAX_CONTRAST))
3851 return UNKNOWN_ERROR;
Srinivasan Kannan551fd262010-01-14 17:48:30 -08003852
3853 LOGV("setting contrast %d", contrast);
3854 mParameters.set(CameraParameters::KEY_CONTRAST, contrast);
3855 bool ret = native_set_parm(CAMERA_SET_PARM_CONTRAST, sizeof(contrast),
3856 (void *)&contrast);
3857 return ret ? NO_ERROR : UNKNOWN_ERROR;
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003858}
3859
3860status_t QualcommCameraHardware::setSaturation(const CameraParameters& params)
3861{
3862 if(!strcmp(sensorType->name, "2mp")) {
3863 LOGE("Saturation not supported for this sensor");
3864 return NO_ERROR;
3865 }
Srinivasan Kannan551fd262010-01-14 17:48:30 -08003866
Kiran Kumar H Nf87cf862010-01-27 14:34:34 -08003867 const char *str = params.get(CameraParameters::KEY_EFFECT);
3868 int32_t value = attr_lookup(effects, sizeof(effects) / sizeof(str_map), str);
3869
3870 if( (value != CAMERA_EFFECT_MONO) && (value != CAMERA_EFFECT_NEGATIVE)
3871 && (value != CAMERA_EFFECT_AQUA) && (value != CAMERA_EFFECT_SEPIA)) {
3872
3873 int saturation = params.getInt(CameraParameters::KEY_SATURATION);
3874 if((saturation < CAMERA_MIN_SATURATION)
3875 || (saturation > CAMERA_MAX_SATURATION))
3876 return UNKNOWN_ERROR;
3877
3878 LOGV("setting saturation %d", saturation);
3879 mParameters.set(CameraParameters::KEY_SATURATION, saturation);
3880 bool ret = native_set_parm(CAMERA_SET_PARM_SATURATION, sizeof(saturation),
3881 (void *)&saturation);
3882 return ret ? NO_ERROR : UNKNOWN_ERROR;
3883 } else {
3884 LOGE(" Saturation value will not be set " \
3885 "when the effect selected is %s", str);
3886 return NO_ERROR;
3887 }
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003888}
3889
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303890status_t QualcommCameraHardware::setBrightness(const CameraParameters& params) {
3891 int brightness = params.getInt("luma-adaptation");
3892 if (mBrightness != brightness) {
3893 LOGV(" new brightness value : %d ", brightness);
3894 mBrightness = brightness;
3895
3896 bool ret = native_set_parm(CAMERA_SET_PARM_BRIGHTNESS, sizeof(mBrightness),
3897 (void *)&mBrightness);
3898 return ret ? NO_ERROR : UNKNOWN_ERROR;
3899 } else {
3900 return NO_ERROR;
3901 }
3902}
3903
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003904status_t QualcommCameraHardware::setWhiteBalance(const CameraParameters& params)
3905{
Apurva Rajguru7360db42010-04-09 16:37:36 -07003906
3907 const char *str_effect = mParameters.get(CameraParameters::KEY_EFFECT);
3908 int32_t value_effect = attr_lookup(effects, sizeof(effects) / sizeof(str_map), str_effect);
3909
3910 if( (value_effect != CAMERA_EFFECT_MONO) && (value_effect != CAMERA_EFFECT_NEGATIVE)
3911 && (value_effect != CAMERA_EFFECT_AQUA) && (value_effect != CAMERA_EFFECT_SEPIA)) {
3912 const char *str = params.get(CameraParameters::KEY_WHITE_BALANCE);
3913
3914 if (str != NULL) {
3915 int32_t value = attr_lookup(whitebalance, sizeof(whitebalance) / sizeof(str_map), str);
3916 if (value != NOT_FOUND) {
3917 mParameters.set(CameraParameters::KEY_WHITE_BALANCE, str);
3918 bool ret = native_set_parm(CAMERA_SET_PARM_WB, sizeof(value),
3919 (void *)&value);
3920 return ret ? NO_ERROR : UNKNOWN_ERROR;
3921 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003922 }
Apurva Rajguru7360db42010-04-09 16:37:36 -07003923 LOGE("Invalid whitebalance value: %s", (str == NULL) ? "NULL" : str);
3924 return BAD_VALUE;
3925 } else {
3926 LOGE("Whitebalance value will not be set " \
3927 "when the effect selected is %s", str_effect);
3928 return NO_ERROR;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003929 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003930}
3931
3932status_t QualcommCameraHardware::setFlash(const CameraParameters& params)
3933{
3934 if (!mSensorInfo.flash_enabled) {
3935 LOGV("%s: flash not supported", __FUNCTION__);
3936 return NO_ERROR;
3937 }
3938
3939 const char *str = params.get(CameraParameters::KEY_FLASH_MODE);
3940 if (str != NULL) {
3941 int32_t value = attr_lookup(flash, sizeof(flash) / sizeof(str_map), str);
3942 if (value != NOT_FOUND) {
3943 mParameters.set(CameraParameters::KEY_FLASH_MODE, str);
3944 bool ret = native_set_parm(CAMERA_SET_PARM_LED_MODE,
3945 sizeof(value), (void *)&value);
3946 return ret ? NO_ERROR : UNKNOWN_ERROR;
3947 }
3948 }
3949 LOGE("Invalid flash mode value: %s", (str == NULL) ? "NULL" : str);
3950 return BAD_VALUE;
3951}
3952
3953status_t QualcommCameraHardware::setAntibanding(const CameraParameters& params)
3954{
Srinivasan Kannan2229d272010-01-05 14:58:28 -08003955 if(!strcmp(sensorType->name, "2mp")) {
3956 LOGE("Parameter AntiBanding is not supported for this sensor");
3957 return NO_ERROR;
3958 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003959 const char *str = params.get(CameraParameters::KEY_ANTIBANDING);
3960 if (str != NULL) {
3961 int value = (camera_antibanding_type)attr_lookup(
3962 antibanding, sizeof(antibanding) / sizeof(str_map), str);
3963 if (value != NOT_FOUND) {
3964 camera_antibanding_type temp = (camera_antibanding_type) value;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003965 mParameters.set(CameraParameters::KEY_ANTIBANDING, str);
Srinivasan Kannan2229d272010-01-05 14:58:28 -08003966 bool ret;
3967 if (temp == CAMERA_ANTIBANDING_AUTO) {
3968 ret = native_set_parm(CAMERA_ENABLE_AFD,
3969 0, NULL);
3970 } else {
3971 ret = native_set_parm(CAMERA_SET_PARM_ANTIBANDING,
3972 sizeof(camera_antibanding_type), (void *)&temp);
3973 }
3974 return ret ? NO_ERROR : UNKNOWN_ERROR;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003975 }
3976 }
3977 LOGE("Invalid antibanding value: %s", (str == NULL) ? "NULL" : str);
3978 return BAD_VALUE;
3979}
3980
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303981status_t QualcommCameraHardware::setLensshadeValue(const CameraParameters& params)
3982{
Mohan Kandrace6bf562010-04-26 13:00:19 -07003983 if( (!strcmp(sensorType->name, "2mp")) ||
3984 (!strcmp(mSensorInfo.name, "vx6953")) ||
3985 (!strcmp(mSensorInfo.name, "VX6953")) ) {
Mohan Kandra1307f312010-04-29 10:18:42 -07003986 LOGI("Parameter Rolloff is not supported for this sensor");
Mohan Kandra93f1bfb2009-12-15 16:55:33 -08003987 return NO_ERROR;
3988 }
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303989 const char *str = params.get(CameraParameters::KEY_LENSSHADE);
3990 if (str != NULL) {
3991 int value = attr_lookup(lensshade,
3992 sizeof(lensshade) / sizeof(str_map), str);
3993 if (value != NOT_FOUND) {
3994 int8_t temp = (int8_t)value;
3995 mParameters.set(CameraParameters::KEY_LENSSHADE, str);
3996 native_set_parm(CAMERA_SET_PARM_ROLLOFF, sizeof(int8_t), (void *)&temp);
3997 return NO_ERROR;
3998 }
3999 }
4000 LOGE("Invalid lensShade value: %s", (str == NULL) ? "NULL" : str);
4001 return BAD_VALUE;
4002}
4003
4004status_t QualcommCameraHardware::setISOValue(const CameraParameters& params) {
Apurva Rajguruf12d9d22010-04-05 16:47:12 -07004005 int8_t temp_hjr;
Nishant Panditc8c1ee72009-12-03 16:24:02 +05304006 const char *str = params.get(CameraParameters::KEY_ISO_MODE);
4007 if (str != NULL) {
4008 int value = (camera_iso_mode_type)attr_lookup(
4009 iso, sizeof(iso) / sizeof(str_map), str);
4010 if (value != NOT_FOUND) {
4011 camera_iso_mode_type temp = (camera_iso_mode_type) value;
Apurva Rajguruf12d9d22010-04-05 16:47:12 -07004012 if (value == CAMERA_ISO_DEBLUR) {
4013 temp_hjr = true;
4014 native_set_parm(CAMERA_SET_PARM_HJR, sizeof(int8_t), (void*)&temp_hjr);
4015 mHJR = value;
4016 }
4017 else {
4018 if (mHJR == CAMERA_ISO_DEBLUR) {
4019 temp_hjr = false;
4020 native_set_parm(CAMERA_SET_PARM_HJR, sizeof(int8_t), (void*)&temp_hjr);
4021 mHJR = value;
4022 }
4023 }
4024
Nishant Panditc8c1ee72009-12-03 16:24:02 +05304025 mParameters.set(CameraParameters::KEY_ISO_MODE, str);
4026 native_set_parm(CAMERA_SET_PARM_ISO, sizeof(camera_iso_mode_type), (void *)&temp);
4027 return NO_ERROR;
4028 }
4029 }
4030 LOGE("Invalid Iso value: %s", (str == NULL) ? "NULL" : str);
4031 return BAD_VALUE;
4032}
4033
4034
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004035status_t QualcommCameraHardware::setGpsLocation(const CameraParameters& params)
4036{
4037 const char *latitude = params.get(CameraParameters::KEY_GPS_LATITUDE);
4038 if (latitude) {
4039 mParameters.set(CameraParameters::KEY_GPS_LATITUDE, latitude);
4040 }
4041
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08004042 const char *latitudeRef = params.get(CameraParameters::KEY_GPS_LATITUDE_REF);
4043 if (latitudeRef) {
4044 mParameters.set(CameraParameters::KEY_GPS_LATITUDE_REF, latitudeRef);
4045 }
4046
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004047 const char *longitude = params.get(CameraParameters::KEY_GPS_LONGITUDE);
4048 if (longitude) {
4049 mParameters.set(CameraParameters::KEY_GPS_LONGITUDE, longitude);
4050 }
4051
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08004052 const char *longitudeRef = params.get(CameraParameters::KEY_GPS_LONGITUDE_REF);
4053 if (longitudeRef) {
4054 mParameters.set(CameraParameters::KEY_GPS_LONGITUDE_REF, longitudeRef);
4055 }
4056
4057 const char *altitudeRef = params.get(CameraParameters::KEY_GPS_ALTITUDE_REF);
4058 if (altitudeRef) {
4059 mParameters.set(CameraParameters::KEY_GPS_ALTITUDE_REF, altitudeRef);
4060 }
4061
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004062 const char *altitude = params.get(CameraParameters::KEY_GPS_ALTITUDE);
4063 if (altitude) {
4064 mParameters.set(CameraParameters::KEY_GPS_ALTITUDE, altitude);
4065 }
4066
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08004067 const char *status = params.get(CameraParameters::KEY_GPS_STATUS);
4068 if (status) {
4069 mParameters.set(CameraParameters::KEY_GPS_STATUS, status);
4070 }
4071
4072 const char *dateTime = params.get(CameraParameters::KEY_EXIF_DATETIME);
4073 if (dateTime) {
4074 mParameters.set(CameraParameters::KEY_EXIF_DATETIME, dateTime);
4075 }
4076
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004077 const char *timestamp = params.get(CameraParameters::KEY_GPS_TIMESTAMP);
4078 if (timestamp) {
4079 mParameters.set(CameraParameters::KEY_GPS_TIMESTAMP, timestamp);
4080 }
4081 return NO_ERROR;
4082}
4083
4084status_t QualcommCameraHardware::setRotation(const CameraParameters& params)
4085{
4086 status_t rc = NO_ERROR;
4087 int rotation = params.getInt(CameraParameters::KEY_ROTATION);
4088 if (rotation != NOT_FOUND) {
4089 if (rotation == 0 || rotation == 90 || rotation == 180
4090 || rotation == 270) {
4091 mParameters.set(CameraParameters::KEY_ROTATION, rotation);
4092 } else {
4093 LOGE("Invalid rotation value: %d", rotation);
4094 rc = BAD_VALUE;
4095 }
4096 }
4097 return rc;
4098}
4099
4100status_t QualcommCameraHardware::setZoom(const CameraParameters& params)
4101{
4102 status_t rc = NO_ERROR;
4103 // No matter how many different zoom values the driver can provide, HAL
4104 // provides applictations the same number of zoom levels. The maximum driver
4105 // zoom value depends on sensor output (VFE input) and preview size (VFE
4106 // output) because VFE can only crop and cannot upscale. If the preview size
4107 // is bigger, the maximum zoom ratio is smaller. However, we want the
4108 // zoom ratio of each zoom level is always the same whatever the preview
4109 // size is. Ex: zoom level 1 is always 1.2x, zoom level 2 is 1.44x, etc. So,
4110 // we need to have a fixed maximum zoom value and do read it from the
4111 // driver.
Mohan Kandra284966d2010-01-05 13:39:15 -08004112 static const int ZOOM_STEP = 1;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004113 int32_t zoom_level = params.getInt("zoom");
4114
Mohan Kandra284966d2010-01-05 13:39:15 -08004115 LOGV("Set zoom=%d", zoom_level);
4116 if(zoom_level >= 0 && zoom_level <= mMaxZoom) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004117 mParameters.set("zoom", zoom_level);
4118 int32_t zoom_value = ZOOM_STEP * zoom_level;
4119 bool ret = native_set_parm(CAMERA_SET_PARM_ZOOM,
4120 sizeof(zoom_value), (void *)&zoom_value);
4121 rc = ret ? NO_ERROR : UNKNOWN_ERROR;
4122 } else {
4123 rc = BAD_VALUE;
4124 }
4125
4126 return rc;
4127}
4128
4129status_t QualcommCameraHardware::setFocusMode(const CameraParameters& params)
4130{
4131 const char *str = params.get(CameraParameters::KEY_FOCUS_MODE);
4132 if (str != NULL) {
4133 int32_t value = attr_lookup(focus_modes,
4134 sizeof(focus_modes) / sizeof(str_map), str);
4135 if (value != NOT_FOUND) {
4136 mParameters.set(CameraParameters::KEY_FOCUS_MODE, str);
4137 // Focus step is reset to infinity when preview is started. We do
4138 // not need to do anything now.
4139 return NO_ERROR;
4140 }
4141 }
4142 LOGE("Invalid focus mode value: %s", (str == NULL) ? "NULL" : str);
4143 return BAD_VALUE;
4144}
4145
4146status_t QualcommCameraHardware::setOrientation(const CameraParameters& params)
4147{
4148 const char *str = params.get("orientation");
4149
4150 if (str != NULL) {
4151 if (strcmp(str, "portrait") == 0 || strcmp(str, "landscape") == 0) {
4152 // Camera service needs this to decide if the preview frames and raw
4153 // pictures should be rotated.
4154 mParameters.set("orientation", str);
4155 } else {
4156 LOGE("Invalid orientation value: %s", str);
4157 return BAD_VALUE;
4158 }
4159 }
4160 return NO_ERROR;
4161}
4162
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08004163status_t QualcommCameraHardware::setPictureFormat(const CameraParameters& params)
4164{
4165 const char * str = params.get(CameraParameters::KEY_PICTURE_FORMAT);
4166
4167 if(str != NULL){
4168 int32_t value = attr_lookup(picture_formats,
4169 sizeof(picture_formats) / sizeof(str_map), str);
4170 if(value != NOT_FOUND){
4171 mParameters.set(CameraParameters::KEY_PICTURE_FORMAT, str);
4172 } else {
4173 LOGE("Invalid Picture Format value: %s", str);
4174 return BAD_VALUE;
4175 }
4176 }
4177 return NO_ERROR;
4178}
4179
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004180QualcommCameraHardware::MemPool::MemPool(int buffer_size, int num_buffers,
4181 int frame_size,
4182 const char *name) :
4183 mBufferSize(buffer_size),
4184 mNumBuffers(num_buffers),
4185 mFrameSize(frame_size),
4186 mBuffers(NULL), mName(name)
4187{
4188 int page_size_minus_1 = getpagesize() - 1;
4189 mAlignedBufferSize = (buffer_size + page_size_minus_1) & (~page_size_minus_1);
4190}
4191
4192void QualcommCameraHardware::MemPool::completeInitialization()
4193{
4194 // If we do not know how big the frame will be, we wait to allocate
4195 // the buffers describing the individual frames until we do know their
4196 // size.
4197
4198 if (mFrameSize > 0) {
4199 mBuffers = new sp<MemoryBase>[mNumBuffers];
4200 for (int i = 0; i < mNumBuffers; i++) {
4201 mBuffers[i] = new
4202 MemoryBase(mHeap,
4203 i * mAlignedBufferSize,
4204 mFrameSize);
4205 }
4206 }
4207}
4208
4209QualcommCameraHardware::AshmemPool::AshmemPool(int buffer_size, int num_buffers,
4210 int frame_size,
4211 const char *name) :
4212 QualcommCameraHardware::MemPool(buffer_size,
4213 num_buffers,
4214 frame_size,
4215 name)
4216{
4217 LOGV("constructing MemPool %s backed by ashmem: "
4218 "%d frames @ %d uint8_ts, "
4219 "buffer size %d",
4220 mName,
4221 num_buffers, frame_size, buffer_size);
4222
4223 int page_mask = getpagesize() - 1;
4224 int ashmem_size = buffer_size * num_buffers;
4225 ashmem_size += page_mask;
4226 ashmem_size &= ~page_mask;
4227
4228 mHeap = new MemoryHeapBase(ashmem_size);
4229
4230 completeInitialization();
4231}
4232
4233static bool register_buf(int camfd,
4234 int size,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08004235 int frame_size,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004236 int pmempreviewfd,
4237 uint32_t offset,
4238 uint8_t *buf,
4239 int pmem_type,
4240 bool vfe_can_write,
4241 bool register_buffer = true);
4242
4243QualcommCameraHardware::PmemPool::PmemPool(const char *pmem_pool,
4244 int flags,
4245 int camera_control_fd,
4246 int pmem_type,
4247 int buffer_size, int num_buffers,
4248 int frame_size,
4249 const char *name) :
4250 QualcommCameraHardware::MemPool(buffer_size,
4251 num_buffers,
4252 frame_size,
4253 name),
4254 mPmemType(pmem_type),
4255 mCameraControlFd(dup(camera_control_fd))
4256{
4257 LOGV("constructing MemPool %s backed by pmem pool %s: "
4258 "%d frames @ %d bytes, buffer size %d",
4259 mName,
4260 pmem_pool, num_buffers, frame_size,
4261 buffer_size);
4262
4263 LOGV("%s: duplicating control fd %d --> %d",
4264 __FUNCTION__,
4265 camera_control_fd, mCameraControlFd);
4266
4267 // Make a new mmap'ed heap that can be shared across processes.
4268 // mAlignedBufferSize is already in 4k aligned. (do we need total size necessary to be in power of 2??)
4269 mAlignedSize = mAlignedBufferSize * num_buffers;
4270
4271 sp<MemoryHeapBase> masterHeap =
4272 new MemoryHeapBase(pmem_pool, mAlignedSize, flags);
4273
4274 if (masterHeap->getHeapID() < 0) {
4275 LOGE("failed to construct master heap for pmem pool %s", pmem_pool);
4276 masterHeap.clear();
4277 return;
4278 }
4279
4280 sp<MemoryHeapPmem> pmemHeap = new MemoryHeapPmem(masterHeap, flags);
4281 if (pmemHeap->getHeapID() >= 0) {
4282 pmemHeap->slap();
4283 masterHeap.clear();
4284 mHeap = pmemHeap;
4285 pmemHeap.clear();
4286
4287 mFd = mHeap->getHeapID();
4288 if (::ioctl(mFd, PMEM_GET_SIZE, &mSize)) {
4289 LOGE("pmem pool %s ioctl(PMEM_GET_SIZE) error %s (%d)",
4290 pmem_pool,
4291 ::strerror(errno), errno);
4292 mHeap.clear();
4293 return;
4294 }
4295
4296 LOGV("pmem pool %s ioctl(fd = %d, PMEM_GET_SIZE) is %ld",
4297 pmem_pool,
4298 mFd,
4299 mSize.len);
Mohan Kandra284966d2010-01-05 13:39:15 -08004300 LOGD("mBufferSize=%d, mAlignedBufferSize=%d\n", mBufferSize, mAlignedBufferSize);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004301 // Unregister preview buffers with the camera drivers. Allow the VFE to write
4302 // to all preview buffers except for the last one.
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08004303 // Only Register the preview, snapshot and thumbnail buffers with the kernel.
Mohan Kandrad9efed92010-01-15 19:08:39 -08004304 if( (strcmp("postview", mName) != 0) ){
4305 int num_buf = num_buffers;
4306 if(!strcmp("preview", mName)) num_buf = kPreviewBufferCount;
Brian Steuerb62adbd2010-02-02 14:47:08 -08004307 LOGD("num_buffers = %d", num_buf);
Mohan Kandrad9efed92010-01-15 19:08:39 -08004308 for (int cnt = 0; cnt < num_buf; ++cnt) {
Sravankb4f5f1c2010-01-21 11:06:17 +05304309 int active = 1;
4310 if(pmem_type == MSM_PMEM_VIDEO){
4311 active = (cnt<ACTIVE_VIDEO_BUFFERS);
4312 LOGV(" pmempool creating video buffers : active %d ", active);
4313 }
4314 else if (pmem_type == MSM_PMEM_PREVIEW){
4315 active = (cnt < (num_buf-1));
4316 }
Mohan Kandra284966d2010-01-05 13:39:15 -08004317 register_buf(mCameraControlFd,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004318 mBufferSize,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08004319 mFrameSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004320 mHeap->getHeapID(),
4321 mAlignedBufferSize * cnt,
4322 (uint8_t *)mHeap->base() + mAlignedBufferSize * cnt,
4323 pmem_type,
Sravankb4f5f1c2010-01-21 11:06:17 +05304324 active);
Mohan Kandra284966d2010-01-05 13:39:15 -08004325 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004326 }
4327
4328 completeInitialization();
4329 }
4330 else LOGE("pmem pool %s error: could not create master heap!",
4331 pmem_pool);
4332}
4333
4334QualcommCameraHardware::PmemPool::~PmemPool()
4335{
4336 LOGV("%s: %s E", __FUNCTION__, mName);
4337 if (mHeap != NULL) {
4338 // Unregister preview buffers with the camera drivers.
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08004339 // Only Unregister the preview, snapshot and thumbnail
4340 // buffers with the kernel.
Mohan Kandrad9efed92010-01-15 19:08:39 -08004341 if( (strcmp("postview", mName) != 0) ){
4342 int num_buffers = mNumBuffers;
4343 if(!strcmp("preview", mName)) num_buffers = kPreviewBufferCount;
4344 for (int cnt = 0; cnt < num_buffers; ++cnt) {
Mohan Kandra284966d2010-01-05 13:39:15 -08004345 register_buf(mCameraControlFd,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004346 mBufferSize,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08004347 mFrameSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004348 mHeap->getHeapID(),
4349 mAlignedBufferSize * cnt,
4350 (uint8_t *)mHeap->base() + mAlignedBufferSize * cnt,
4351 mPmemType,
4352 false,
4353 false /* unregister */);
Mohan Kandra284966d2010-01-05 13:39:15 -08004354 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004355 }
4356 }
4357 LOGV("destroying PmemPool %s: closing control fd %d",
4358 mName,
4359 mCameraControlFd);
4360 close(mCameraControlFd);
4361 LOGV("%s: %s X", __FUNCTION__, mName);
4362}
4363
4364QualcommCameraHardware::MemPool::~MemPool()
4365{
4366 LOGV("destroying MemPool %s", mName);
4367 if (mFrameSize > 0)
4368 delete [] mBuffers;
4369 mHeap.clear();
4370 LOGV("destroying MemPool %s completed", mName);
4371}
4372
4373static bool register_buf(int camfd,
4374 int size,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08004375 int frame_size,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004376 int pmempreviewfd,
4377 uint32_t offset,
4378 uint8_t *buf,
4379 int pmem_type,
4380 bool vfe_can_write,
4381 bool register_buffer)
4382{
4383 struct msm_pmem_info pmemBuf;
4384
4385 pmemBuf.type = pmem_type;
4386 pmemBuf.fd = pmempreviewfd;
4387 pmemBuf.offset = offset;
4388 pmemBuf.len = size;
4389 pmemBuf.vaddr = buf;
4390 pmemBuf.y_off = 0;
Srinivasan Kannanb36a4fe2010-01-29 19:34:09 -08004391
4392 if(pmem_type == MSM_PMEM_RAW_MAINIMG)
4393 pmemBuf.cbcr_off = 0;
4394 else
4395 pmemBuf.cbcr_off = PAD_TO_WORD(frame_size * 2 / 3);
4396
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004397 pmemBuf.active = vfe_can_write;
4398
4399 LOGV("register_buf: camfd = %d, reg = %d buffer = %p",
4400 camfd, !register_buffer, buf);
4401 if (ioctl(camfd,
4402 register_buffer ?
4403 MSM_CAM_IOCTL_REGISTER_PMEM :
4404 MSM_CAM_IOCTL_UNREGISTER_PMEM,
4405 &pmemBuf) < 0) {
4406 LOGE("register_buf: MSM_CAM_IOCTL_(UN)REGISTER_PMEM fd %d error %s",
4407 camfd,
4408 strerror(errno));
4409 return false;
4410 }
4411 return true;
4412}
4413
4414status_t QualcommCameraHardware::MemPool::dump(int fd, const Vector<String16>& args) const
4415{
4416 const size_t SIZE = 256;
4417 char buffer[SIZE];
4418 String8 result;
4419 snprintf(buffer, 255, "QualcommCameraHardware::AshmemPool::dump\n");
4420 result.append(buffer);
4421 if (mName) {
4422 snprintf(buffer, 255, "mem pool name (%s)\n", mName);
4423 result.append(buffer);
4424 }
4425 if (mHeap != 0) {
4426 snprintf(buffer, 255, "heap base(%p), size(%d), flags(%d), device(%s)\n",
4427 mHeap->getBase(), mHeap->getSize(),
4428 mHeap->getFlags(), mHeap->getDevice());
4429 result.append(buffer);
4430 }
4431 snprintf(buffer, 255,
4432 "buffer size (%d), number of buffers (%d), frame size(%d)",
4433 mBufferSize, mNumBuffers, mFrameSize);
4434 result.append(buffer);
4435 write(fd, result.string(), result.size());
4436 return NO_ERROR;
4437}
4438
4439static void receive_camframe_callback(struct msm_frame *frame)
4440{
4441 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4442 if (obj != 0) {
4443 obj->receivePreviewFrame(frame);
4444 }
4445}
4446
4447static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size)
4448{
4449 LOGV("receive_jpeg_fragment_callback E");
4450 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4451 if (obj != 0) {
4452 obj->receiveJpegPictureFragment(buff_ptr, buff_size);
4453 }
4454 LOGV("receive_jpeg_fragment_callback X");
4455}
4456
4457static void receive_jpeg_callback(jpeg_event_t status)
4458{
4459 LOGV("receive_jpeg_callback E (completion status %d)", status);
4460 if (status == JPEG_EVENT_DONE) {
4461 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4462 if (obj != 0) {
4463 obj->receiveJpegPicture();
4464 }
4465 }
4466 LOGV("receive_jpeg_callback X");
4467}
Sravankb4f5f1c2010-01-21 11:06:17 +05304468// 720p : video frame calbback from camframe
4469static void receive_camframe_video_callback(struct msm_frame *frame)
4470{
4471 LOGV("receive_camframe_video_callback E");
4472 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4473 if (obj != 0) {
4474 obj->receiveRecordingFrame(frame);
4475 }
4476 LOGV("receive_camframe_video_callback X");
4477}
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004478
4479void QualcommCameraHardware::setCallbacks(notify_callback notify_cb,
4480 data_callback data_cb,
4481 data_callback_timestamp data_cb_timestamp,
4482 void* user)
4483{
4484 Mutex::Autolock lock(mLock);
4485 mNotifyCallback = notify_cb;
4486 mDataCallback = data_cb;
4487 mDataCallbackTimestamp = data_cb_timestamp;
4488 mCallbackCookie = user;
4489}
4490
4491void QualcommCameraHardware::enableMsgType(int32_t msgType)
4492{
4493 Mutex::Autolock lock(mLock);
4494 mMsgEnabled |= msgType;
4495}
4496
4497void QualcommCameraHardware::disableMsgType(int32_t msgType)
4498{
4499 Mutex::Autolock lock(mLock);
4500 mMsgEnabled &= ~msgType;
4501}
4502
4503bool QualcommCameraHardware::msgTypeEnabled(int32_t msgType)
4504{
4505 return (mMsgEnabled & msgType);
4506}
4507
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08004508bool QualcommCameraHardware::useOverlay(void)
4509{
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08004510 if( mCurrentTarget == TARGET_MSM7630 ) {
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08004511 /* Only 7x30 supports Overlay */
4512 mUseOverlay = TRUE;
4513 } else
4514 mUseOverlay = FALSE;
4515
4516 LOGV(" Using Overlay : %s ", mUseOverlay ? "YES" : "NO" );
4517 return mUseOverlay;
4518}
4519
4520status_t QualcommCameraHardware::setOverlay(const sp<Overlay> &Overlay)
4521{
4522 if( Overlay != NULL) {
4523 LOGV(" Valid overlay object ");
4524 mOverlayLock.lock();
4525 mOverlay = Overlay;
4526 mOverlayLock.unlock();
4527 } else {
Apurva Rajguruc73c1722010-04-15 17:39:11 -07004528 LOGV(" Overlay object NULL. returning ");
Mohan Kandrad9efed92010-01-15 19:08:39 -08004529 mOverlay = NULL;
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08004530 return UNKNOWN_ERROR;
4531 }
4532 return NO_ERROR;
4533}
Kiran Kumar H N215cac42009-12-08 01:53:46 -08004534
4535void QualcommCameraHardware::receive_camframetimeout(void) {
4536 LOGV("receive_camframetimeout: E");
4537 Mutex::Autolock l(&mCamframeTimeoutLock);
Mohan Kandra1307f312010-04-29 10:18:42 -07004538 LOGE(" Camframe timed out. Not receiving any frames from camera driver ");
Kiran Kumar H N215cac42009-12-08 01:53:46 -08004539 camframe_timeout_flag = TRUE;
4540 LOGV("receive_camframetimeout: X");
4541}
4542
4543static void receive_camframetimeout_callback(void) {
4544 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4545 if (obj != 0) {
4546 obj->receive_camframetimeout();
4547 }
4548}
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08004549
4550void QualcommCameraHardware::storePreviewFrameForPostview(void) {
4551 LOGV(" storePreviewFrameForPostview : E ");
4552
4553 /* Since there is restriction on the maximum overlay dimensions
4554 * that can be created, we use the last preview frame as postview
4555 * for 7x30. */
4556 LOGV(" Copying the preview buffer to postview buffer %d ",
4557 mPreviewFrameSize);
4558 if( mPostViewHeap != NULL && mLastQueuedFrame != NULL) {
4559 memcpy(mPostViewHeap->mHeap->base(),
4560 (uint8_t *)mLastQueuedFrame, mPreviewFrameSize );
4561 } else
4562 LOGE(" Failed to store Preview frame. No Postview ");
4563
4564 LOGV(" storePreviewFrameForPostview : X ");
4565}
Kiran Kumar H Nb49af212010-02-17 15:12:17 -08004566
4567bool QualcommCameraHardware::isValidDimension(int width, int height) {
4568 bool retVal = FALSE;
4569 /* This function checks if a given resolution is valid or not.
4570 * A particular resolution is considered valid if it satisfies
4571 * the following conditions:
4572 * 1. width & height should be multiple of 16.
4573 * 2. width & height should be less than/equal to the dimensions
4574 * supported by the camera sensor.
4575 * 3. the aspect ratio is a valid aspect ratio and is among the
4576 * commonly used aspect ratio as determined by the thumbnail_sizes
4577 * data structure.
4578 */
4579
4580 if( (width == CEILING16(width)) && (height == CEILING16(height))
4581 && (width <= sensorType->max_supported_snapshot_width)
4582 && (height <= sensorType->max_supported_snapshot_height) )
4583 {
4584 uint32_t pictureAspectRatio = (uint32_t)((width * Q12)/height);
4585 for(int i = 0; i < THUMBNAIL_SIZE_COUNT; i++ ) {
4586 if(thumbnail_sizes[i].aspect_ratio == pictureAspectRatio) {
4587 retVal = TRUE;
4588 break;
4589 }
4590 }
4591 }
4592 return retVal;
4593}
Kiran Kumar H N4dd45a62010-02-26 15:56:33 -08004594status_t QualcommCameraHardware::getBufferInfo(sp<IMemory>& Frame, size_t *alignedSize) {
4595 status_t ret;
4596 LOGV(" getBufferInfo : E ");
Vamshidhar Kondrab362be62010-03-22 19:07:29 +05304597 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250) )
4598 {
4599 if( mRecordHeap != NULL){
4600 LOGV(" Setting valid buffer information ");
4601 Frame = mRecordHeap->mBuffers[0];
4602 if( alignedSize != NULL) {
4603 *alignedSize = mRecordHeap->mAlignedBufferSize;
4604 LOGV(" HAL : alignedSize = %d ", *alignedSize);
4605 ret = NO_ERROR;
4606 } else {
4607 LOGE(" HAL : alignedSize is NULL. Cannot update alignedSize ");
4608 ret = UNKNOWN_ERROR;
4609 }
Kiran Kumar H N4dd45a62010-02-26 15:56:33 -08004610 } else {
Vamshidhar Kondrab362be62010-03-22 19:07:29 +05304611 LOGE(" RecordHeap is null. Buffer information wont be updated ");
4612 Frame = NULL;
4613 ret = UNKNOWN_ERROR;
4614 }
Kiran Kumar H N4dd45a62010-02-26 15:56:33 -08004615 } else {
Vamshidhar Kondrab362be62010-03-22 19:07:29 +05304616 if(mPreviewHeap != NULL) {
4617 LOGV(" Setting valid buffer information ");
4618 Frame = mPreviewHeap->mBuffers[0];
4619 if( alignedSize != NULL) {
4620 *alignedSize = mPreviewHeap->mAlignedBufferSize;
4621 LOGV(" HAL : alignedSize = %d ", *alignedSize);
4622 ret = NO_ERROR;
4623 } else {
4624 LOGE(" HAL : alignedSize is NULL. Cannot update alignedSize ");
4625 ret = UNKNOWN_ERROR;
4626 }
4627 } else {
4628 LOGE(" PreviewHeap is null. Buffer information wont be updated ");
4629 Frame = NULL;
4630 ret = UNKNOWN_ERROR;
4631 }
Kiran Kumar H N4dd45a62010-02-26 15:56:33 -08004632 }
4633 LOGV(" getBufferInfo : X ");
4634 return ret;
4635}
Kiran Kumar H Nb49af212010-02-17 15:12:17 -08004636
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004637}; // namespace android