blob: 44b8c343b43f2b8248619c728e7bd3480d09b541 [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},
583 { CameraParameters::ISO_800, CAMERA_ISO_800 }
584};
585
586
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800587#define DONT_CARE 0
588static const str_map focus_modes[] = {
Srinivasan Kannan71229622009-12-04 12:05:58 -0800589 { CameraParameters::FOCUS_MODE_AUTO, AF_MODE_AUTO},
590 { CameraParameters::FOCUS_MODE_INFINITY, DONT_CARE },
591 { CameraParameters::FOCUS_MODE_NORMAL, AF_MODE_NORMAL },
592 { CameraParameters::FOCUS_MODE_MACRO, AF_MODE_MACRO }
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800593};
594
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530595static const str_map lensshade[] = {
596 { CameraParameters::LENSSHADE_ENABLE, TRUE },
597 { CameraParameters::LENSSHADE_DISABLE, FALSE }
598};
599
Srinivasan Kannan71229622009-12-04 12:05:58 -0800600struct SensorType {
601 const char *name;
602 int rawPictureWidth;
603 int rawPictureHeight;
604 bool hasAutoFocusSupport;
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800605 int max_supported_snapshot_width;
606 int max_supported_snapshot_height;
Apurva Rajguruffe264a2010-03-09 13:50:53 -0800607 int bitMask;
Srinivasan Kannan71229622009-12-04 12:05:58 -0800608};
609
610static SensorType sensorTypes[] = {
Apurva Rajguruffe264a2010-03-09 13:50:53 -0800611 { "5mp", 2608, 1960, true, 2592, 1944,0x00000fff },
612 { "3mp", 2064, 1544, false, 2048, 1536,0x000007ff },
613 { "2mp", 3200, 1200, false, 1600, 1200,0x000007ff } };
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800614
Srinivasan Kannan71229622009-12-04 12:05:58 -0800615
616static SensorType * sensorType;
617
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800618static const str_map picture_formats[] = {
619 {CameraParameters::PIXEL_FORMAT_JPEG, PICTURE_FORMAT_JPEG},
620 {CameraParameters::PIXEL_FORMAT_RAW, PICTURE_FORMAT_RAW}
621};
622
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800623static bool parameter_string_initialized = false;
624static String8 preview_size_values;
625static String8 picture_size_values;
626static String8 antibanding_values;
627static String8 effect_values;
Apurva Rajguru55562b02009-12-03 12:25:35 -0800628static String8 autoexposure_values;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800629static String8 whitebalance_values;
630static String8 flash_values;
631static String8 focus_mode_values;
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530632static String8 iso_values;
633static String8 lensshade_values;
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800634static String8 picture_format_values;
635
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800636static String8 create_sizes_str(const camera_size_type *sizes, int len) {
637 String8 str;
638 char buffer[32];
639
640 if (len > 0) {
641 sprintf(buffer, "%dx%d", sizes[0].width, sizes[0].height);
642 str.append(buffer);
643 }
644 for (int i = 1; i < len; i++) {
645 sprintf(buffer, ",%dx%d", sizes[i].width, sizes[i].height);
646 str.append(buffer);
647 }
648 return str;
649}
650
651static String8 create_values_str(const str_map *values, int len) {
652 String8 str;
653
654 if (len > 0) {
655 str.append(values[0].desc);
656 }
657 for (int i = 1; i < len; i++) {
658 str.append(",");
659 str.append(values[i].desc);
660 }
661 return str;
662}
663
Sravankb4f5f1c2010-01-21 11:06:17 +0530664extern "C" {
665//------------------------------------------------------------------------
666// : 720p busyQ funcitons
667// --------------------------------------------------------------------
668static struct fifo_queue g_busy_frame_queue =
669 {0, 0, 0, PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER};
670};
671/*===========================================================================
672 * FUNCTION cam_frame_wait_video
673 *
674 * DESCRIPTION this function waits a video in the busy queue
675 * ===========================================================================*/
676
677static void cam_frame_wait_video (void)
678{
679 LOGV("cam_frame_wait_video E ");
680 if ((g_busy_frame_queue.num_of_frames) <=0){
681 pthread_cond_wait(&(g_busy_frame_queue.wait), &(g_busy_frame_queue.mut));
682 }
683 LOGV("cam_frame_wait_video X");
684 return;
685}
686
687/*===========================================================================
688 * FUNCTION cam_frame_flush_video
689 *
690 * DESCRIPTION this function deletes all the buffers in busy queue
691 * ===========================================================================*/
692void cam_frame_flush_video (void)
693{
694 LOGV("cam_frame_flush_video: in n = %d\n", g_busy_frame_queue.num_of_frames);
695 pthread_mutex_lock(&(g_busy_frame_queue.mut));
696
697 while (g_busy_frame_queue.front)
698 {
699 //dequeue from the busy queue
700 struct fifo_node *node = dequeue (&g_busy_frame_queue);
701 if(node)
702 free(node);
703
704 LOGV("cam_frame_flush_video: node \n");
705 }
706 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
707 LOGV("cam_frame_flush_video: out n = %d\n", g_busy_frame_queue.num_of_frames);
708 return ;
709}
710/*===========================================================================
711 * FUNCTION cam_frame_get_video
712 *
713 * DESCRIPTION this function returns a video frame from the head
714 * ===========================================================================*/
715static struct msm_frame * cam_frame_get_video()
716{
717 struct msm_frame *p = NULL;
718 LOGV("cam_frame_get_video... in\n");
719 LOGV("cam_frame_get_video... got lock\n");
720 if (g_busy_frame_queue.front)
721 {
722 //dequeue
723 struct fifo_node *node = dequeue (&g_busy_frame_queue);
724 if (node)
725 {
726 p = (struct msm_frame *)node->f;
727 free (node);
728 }
729 LOGV("cam_frame_get_video... out = %x\n", p->buffer);
730 }
731 return p;
732}
733
734/*===========================================================================
735 * FUNCTION cam_frame_post_video
736 *
737 * DESCRIPTION this function add a busy video frame to the busy queue tails
738 * ===========================================================================*/
739static void cam_frame_post_video (struct msm_frame *p)
740{
741 if (!p)
742 {
743 LOGE("post video , buffer is null");
744 return;
745 }
746 LOGV("cam_frame_post_video... in = %x\n", (unsigned int)(p->buffer));
747 pthread_mutex_lock(&(g_busy_frame_queue.mut));
748 LOGV("post_video got lock. q count before enQ %d", g_busy_frame_queue.num_of_frames);
749 //enqueue to busy queue
750 struct fifo_node *node = (struct fifo_node *)malloc (sizeof (struct fifo_node));
751 if (node)
752 {
753 LOGV(" post video , enqueing in busy queue");
754 node->f = p;
755 node->next = NULL;
756 enqueue (&g_busy_frame_queue, node);
757 LOGV("post_video got lock. q count after enQ %d", g_busy_frame_queue.num_of_frames);
758 }
759 else
760 {
761 LOGE("cam_frame_post_video error... out of memory\n");
762 }
763
764 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
765 pthread_cond_signal(&(g_busy_frame_queue.wait));
766
767 LOGV("cam_frame_post_video... out = %x\n", p->buffer);
768
769 return;
770}
771
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -0800772void QualcommCameraHardware::storeTargetType(void) {
773 char mDeviceName[PROPERTY_VALUE_MAX];
774 property_get("ro.product.device",mDeviceName," ");
775 mCurrentTarget = TARGET_MAX;
776 for( int i = 0; i < TARGET_MAX ; i++) {
777 if( !strncmp(mDeviceName, targetList[i].targetStr, 7)) {
778 mCurrentTarget = targetList[i].targetEnum;
779 break;
780 }
781 }
782 LOGV(" Storing the current target type as %d ", mCurrentTarget );
783 return;
784}
785
Sravankb4f5f1c2010-01-21 11:06:17 +0530786//-------------------------------------------------------------------------------------
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800787static Mutex singleton_lock;
788static bool singleton_releasing;
789static Condition singleton_wait;
790
791static void receive_camframe_callback(struct msm_frame *frame);
Sravankb4f5f1c2010-01-21 11:06:17 +0530792static void receive_camframe_video_callback(struct msm_frame *frame); // 720p
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800793static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size);
794static void receive_jpeg_callback(jpeg_event_t status);
795static void receive_shutter_callback(common_crop_t *crop);
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800796static void receive_camframetimeout_callback(void);
Mohan Kandra284966d2010-01-05 13:39:15 -0800797static int fb_fd = -1;
798static int32_t mMaxZoom = 0;
799static bool native_get_maxzoom(int camfd, void *pZm);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800800
Mohan Kandrad9efed92010-01-15 19:08:39 -0800801static int dstOffset = 0;
802
Brian Steuer07704892009-12-18 18:07:33 -0800803static int camerafd;
804pthread_t w_thread;
805
806void *opencamerafd(void *data) {
807 camerafd = open(MSM_CAMERA_CONTROL, O_RDWR);
808 return NULL;
809}
810
Mohan Kandrad9efed92010-01-15 19:08:39 -0800811/* When using MDP zoom, double the preview buffers. The usage of these
812 * buffers is as follows:
813 * 1. As all the buffers comes under a single FD, and at initial registration,
814 * this FD will be passed to surface flinger, surface flinger can have access
815 * to all the buffers when needed.
816 * 2. Only "kPreviewBufferCount" buffers (SrcSet) will be registered with the
817 * camera driver to receive preview frames. The remaining buffers (DstSet),
818 * will be used at HAL and by surface flinger only when crop information
819 * is present in the frame.
820 * 3. When there is no crop information, there will be no call to MDP zoom,
821 * and the buffers in SrcSet will be passed to surface flinger to display.
822 * 4. With crop information present, MDP zoom will be called, and the final
823 * data will be placed in a buffer from DstSet, and this buffer will be given
824 * to surface flinger to display.
825 */
826#define NUM_MORE_BUFS 2
827
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800828QualcommCameraHardware::QualcommCameraHardware()
829 : mParameters(),
830 mCameraRunning(false),
831 mPreviewInitialized(false),
832 mFrameThreadRunning(false),
Mohan Kandra156d0ac2010-01-25 16:59:17 -0800833 mVideoThreadRunning(false),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800834 mSnapshotThreadRunning(false),
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800835 mSnapshotFormat(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800836 mReleasedRecordingFrame(false),
837 mPreviewFrameSize(0),
838 mRawSize(0),
839 mCameraControlFd(-1),
840 mAutoFocusThreadRunning(false),
841 mAutoFocusFd(-1),
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800842 mBrightness(0),
Apurva Rajguruf12d9d22010-04-05 16:47:12 -0700843 mHJR(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800844 mInPreviewCallback(false),
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800845 mUseOverlay(0),
846 mOverlay(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800847 mMsgEnabled(0),
848 mNotifyCallback(0),
849 mDataCallback(0),
850 mDataCallbackTimestamp(0),
Mohan Kandra740cfce2010-01-07 12:58:24 -0800851 mCallbackCookie(0),
852 mDebugFps(0)
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800853{
Brian Steuer07704892009-12-18 18:07:33 -0800854
855 // Start opening camera device in a separate thread/ Since this
856 // initializes the sensor hardware, this can take a long time. So,
857 // start the process here so it will be ready by the time it's
858 // needed.
859 if ((pthread_create(&w_thread, NULL, opencamerafd, NULL)) != 0) {
860 LOGE("Camera open thread creation failed");
861 }
862
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800863 memset(&mDimension, 0, sizeof(mDimension));
864 memset(&mCrop, 0, sizeof(mCrop));
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -0800865 memset(&zoomCropInfo, 0, sizeof(zoom_crop_info));
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -0800866 storeTargetType();
Mohan Kandra740cfce2010-01-07 12:58:24 -0800867 char value[PROPERTY_VALUE_MAX];
868 property_get("persist.debug.sf.showfps", value, "0");
869 mDebugFps = atoi(value);
Apurva Rajguruc73c1722010-04-15 17:39:11 -0700870 if( mCurrentTarget == TARGET_MSM7630 ) {
Sravankb4f5f1c2010-01-21 11:06:17 +0530871 kPreviewBufferCountActual = kPreviewBufferCount;
Apurva Rajguruc73c1722010-04-15 17:39:11 -0700872 kRecordBufferCount = RECORD_BUFFERS_7x30;
873 recordframes = new msm_frame[kRecordBufferCount];
874 }
875 else {
Sravankb4f5f1c2010-01-21 11:06:17 +0530876 kPreviewBufferCountActual = kPreviewBufferCount + NUM_MORE_BUFS;
Apurva Rajguruc73c1722010-04-15 17:39:11 -0700877 if( mCurrentTarget == TARGET_QSD8250 ) {
878 kRecordBufferCount = RECORD_BUFFERS_8x50;
879 recordframes = new msm_frame[kRecordBufferCount];
880 }
881 }
Srinivasan Kannan5701a942010-04-15 16:17:21 -0700882
883 switch(mCurrentTarget){
884 case TARGET_MSM7627:
885 jpegPadding = 8;
886 break;
887 case TARGET_QSD8250:
888 case TARGET_MSM7630:
889 jpegPadding = 0;
890 break;
891 default:
892 jpegPadding = 0;
893 break;
894 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800895 LOGV("constructor EX");
896}
897
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800898
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -0800899void QualcommCameraHardware::filterPreviewSizes(){
900
Apurva Rajguruffe264a2010-03-09 13:50:53 -0800901 unsigned int boardMask = 0;
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -0800902 int prop = 0;
903 for(prop=0;prop<sizeof(boardProperties)/sizeof(board_property);prop++){
904 if(mCurrentTarget == boardProperties[prop].target){
Apurva Rajguruffe264a2010-03-09 13:50:53 -0800905 boardMask = boardProperties[prop].previewSizeMask;
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -0800906 break;
907 }
908 }
909
Apurva Rajguruffe264a2010-03-09 13:50:53 -0800910 int bitMask = boardMask & sensorType->bitMask;
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -0800911 if(bitMask){
912 unsigned int mask = 1<<(PREVIEW_SIZE_COUNT-1);
913 previewSizeCount=0;
914 unsigned int i = 0;
915 while(mask){
916 if(mask&bitMask)
917 supportedPreviewSizes[previewSizeCount++] =
918 preview_sizes[i];
919 i++;
920 mask = mask >> 1;
921 }
922 }
923}
924
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800925//filter Picture sizes based on max width and height
926void QualcommCameraHardware::filterPictureSizes(){
927 int i;
928 for(i=0;i<PICTURE_SIZE_COUNT;i++){
929 if(((picture_sizes[i].width <=
930 sensorType->max_supported_snapshot_width) &&
931 (picture_sizes[i].height <=
932 sensorType->max_supported_snapshot_height))){
933 picture_sizes_ptr = picture_sizes + i;
934 supportedPictureSizesCount = PICTURE_SIZE_COUNT - i ;
935 return ;
936 }
937 }
938}
939
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800940void QualcommCameraHardware::initDefaultParameters()
941{
942 LOGV("initDefaultParameters E");
943
944 // Initialize constant parameter strings. This will happen only once in the
945 // lifetime of the mediaserver process.
946 if (!parameter_string_initialized) {
Srinivasan Kannan71229622009-12-04 12:05:58 -0800947 findSensorType();
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800948 antibanding_values = create_values_str(
949 antibanding, sizeof(antibanding) / sizeof(str_map));
950 effect_values = create_values_str(
951 effects, sizeof(effects) / sizeof(str_map));
Apurva Rajguru55562b02009-12-03 12:25:35 -0800952 autoexposure_values = create_values_str(
953 autoexposure, sizeof(autoexposure) / sizeof(str_map));
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800954 whitebalance_values = create_values_str(
955 whitebalance, sizeof(whitebalance) / sizeof(str_map));
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -0800956
957 //filter preview sizes
958 filterPreviewSizes();
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800959 preview_size_values = create_sizes_str(
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -0800960 supportedPreviewSizes, previewSizeCount);
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800961 //filter picture sizes
962 filterPictureSizes();
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800963 picture_size_values = create_sizes_str(
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800964 picture_sizes_ptr, supportedPictureSizesCount);
965
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800966 flash_values = create_values_str(
967 flash, sizeof(flash) / sizeof(str_map));
Srinivasan Kannan71229622009-12-04 12:05:58 -0800968 if(sensorType->hasAutoFocusSupport){
969 focus_mode_values = create_values_str(
970 focus_modes, sizeof(focus_modes) / sizeof(str_map));
971 }
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530972 iso_values = create_values_str(
973 iso,sizeof(iso)/sizeof(str_map));
974 lensshade_values = create_values_str(
975 lensshade,sizeof(lensshade)/sizeof(str_map));
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800976 picture_format_values = create_values_str(
977 picture_formats, sizeof(picture_formats)/sizeof(str_map));
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800978 parameter_string_initialized = true;
979 }
980
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -0800981 mParameters.setPreviewSize(DEFAULT_PREVIEW_WIDTH, DEFAULT_PREVIEW_HEIGHT);
982 mDimension.display_width = DEFAULT_PREVIEW_WIDTH;
983 mDimension.display_height = DEFAULT_PREVIEW_HEIGHT;
984
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800985 mParameters.setPreviewFrameRate(15);
986 mParameters.setPreviewFormat("yuv420sp"); // informative
987
988 mParameters.setPictureSize(DEFAULT_PICTURE_WIDTH, DEFAULT_PICTURE_HEIGHT);
989 mParameters.setPictureFormat("jpeg"); // informative
990
Mohan Kandra785619a2010-02-01 21:52:42 -0800991 mParameters.set(CameraParameters::KEY_JPEG_QUALITY, "85"); // max quality
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800992 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH,
993 THUMBNAIL_WIDTH_STR); // informative
994 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT,
995 THUMBNAIL_HEIGHT_STR); // informative
Srinivasan Kannan80d878f2009-12-18 15:06:02 -0800996 mDimension.ui_thumbnail_width =
997 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].width;
998 mDimension.ui_thumbnail_height =
999 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001000 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, "90");
1001
1002 mParameters.set(CameraParameters::KEY_ANTIBANDING,
Mohan Kandra785619a2010-02-01 21:52:42 -08001003 CameraParameters::ANTIBANDING_OFF);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001004 mParameters.set(CameraParameters::KEY_EFFECT,
1005 CameraParameters::EFFECT_NONE);
Apurva Rajguru55562b02009-12-03 12:25:35 -08001006 mParameters.set(CameraParameters::KEY_AUTO_EXPOSURE,
1007 CameraParameters::AUTO_EXPOSURE_FRAME_AVG);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001008 mParameters.set(CameraParameters::KEY_WHITE_BALANCE,
1009 CameraParameters::WHITE_BALANCE_AUTO);
1010 mParameters.set(CameraParameters::KEY_FOCUS_MODE,
1011 CameraParameters::FOCUS_MODE_AUTO);
Priya Komarlingam044c7b52010-01-22 18:21:23 -08001012 mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS,
1013 "yuv420sp");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001014
1015 mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES,
1016 preview_size_values.string());
1017 mParameters.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES,
1018 picture_size_values.string());
1019 mParameters.set(CameraParameters::KEY_SUPPORTED_ANTIBANDING,
1020 antibanding_values);
1021 mParameters.set(CameraParameters::KEY_SUPPORTED_EFFECTS, effect_values);
Apurva Rajguru55562b02009-12-03 12:25:35 -08001022 mParameters.set(CameraParameters::KEY_SUPPORTED_AUTO_EXPOSURE, autoexposure_values);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001023 mParameters.set(CameraParameters::KEY_SUPPORTED_WHITE_BALANCE,
1024 whitebalance_values);
1025 mParameters.set(CameraParameters::KEY_SUPPORTED_FOCUS_MODES,
1026 focus_mode_values);
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001027 mParameters.set(CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS,
1028 picture_format_values);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001029
1030 if (mSensorInfo.flash_enabled) {
1031 mParameters.set(CameraParameters::KEY_FLASH_MODE,
1032 CameraParameters::FLASH_MODE_OFF);
1033 mParameters.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES,
1034 flash_values);
1035 }
1036
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08001037 mParameters.set(CameraParameters::KEY_MAX_SHARPNESS,
1038 CAMERA_MAX_SHARPNESS);
1039 mParameters.set(CameraParameters::KEY_MAX_CONTRAST,
1040 CAMERA_MAX_CONTRAST);
1041 mParameters.set(CameraParameters::KEY_MAX_SATURATION,
1042 CAMERA_MAX_SATURATION);
1043
Apurva Rajguru07185952010-01-22 15:40:07 -08001044 mParameters.set("luma-adaptation", "3");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001045 mParameters.set("zoom-supported", "true");
1046 mParameters.set("max-zoom", MAX_ZOOM_LEVEL);
1047 mParameters.set("zoom", 0);
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001048 mParameters.set(CameraParameters::KEY_PICTURE_FORMAT,
1049 CameraParameters::PIXEL_FORMAT_JPEG);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001050
Kiran Kumar H N595970b2010-01-12 10:41:09 -08001051 mParameters.set(CameraParameters::KEY_SHARPNESS,
1052 CAMERA_DEF_SHARPNESS);
1053 mParameters.set(CameraParameters::KEY_CONTRAST,
1054 CAMERA_DEF_CONTRAST);
1055 mParameters.set(CameraParameters::KEY_SATURATION,
1056 CAMERA_DEF_SATURATION);
1057
Nishant Panditc8c1ee72009-12-03 16:24:02 +05301058 mParameters.set(CameraParameters::KEY_ISO_MODE,
1059 CameraParameters::ISO_AUTO);
1060 mParameters.set(CameraParameters::KEY_LENSSHADE,
1061 CameraParameters::LENSSHADE_ENABLE);
1062 mParameters.set(CameraParameters::KEY_SUPPORTED_ISO_MODES,
1063 iso_values);
1064 mParameters.set(CameraParameters::KEY_SUPPORTED_LENSSHADE_MODES,
1065 lensshade_values);
1066
Priyanka Kharat67cfe532010-03-29 17:28:22 -07001067 if (setParameters(mParameters) != NO_ERROR) {
1068 LOGE("Failed to set default parameters?!");
1069 }
1070
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08001071 mUseOverlay = useOverlay();
1072
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001073 /* Initialize the camframe_timeout_flag*/
1074 Mutex::Autolock l(&mCamframeTimeoutLock);
1075 camframe_timeout_flag = FALSE;
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08001076 mPostViewHeap = NULL;
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001077
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001078 LOGV("initDefaultParameters X");
1079}
1080
Srinivasan Kannan71229622009-12-04 12:05:58 -08001081void QualcommCameraHardware::findSensorType(){
1082 mDimension.picture_width = DEFAULT_PICTURE_WIDTH;
1083 mDimension.picture_height = DEFAULT_PICTURE_HEIGHT;
1084 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
1085 sizeof(cam_ctrl_dimension_t), &mDimension);
1086 if (ret) {
1087 unsigned int i;
1088 for (i = 0; i < sizeof(sensorTypes) / sizeof(SensorType); i++) {
1089 if (sensorTypes[i].rawPictureHeight
1090 == mDimension.raw_picture_height) {
1091 sensorType = sensorTypes + i;
1092 return;
1093 }
1094 }
1095 }
1096 //default to 5 mp
1097 sensorType = sensorTypes;
1098 return;
1099}
1100
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001101#define ROUND_TO_PAGE(x) (((x)+0xfff)&~0xfff)
1102
1103bool QualcommCameraHardware::startCamera()
1104{
1105 LOGV("startCamera E");
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08001106 if( mCurrentTarget == TARGET_MAX ) {
1107 LOGE(" Unable to determine the target type. Camera will not work ");
1108 return false;
1109 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001110#if DLOPEN_LIBMMCAMERA
1111 libmmcamera = ::dlopen("liboemcamera.so", RTLD_NOW);
1112 LOGV("loading liboemcamera at %p", libmmcamera);
1113 if (!libmmcamera) {
1114 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
1115 return false;
1116 }
1117
1118 *(void **)&LINK_cam_frame =
1119 ::dlsym(libmmcamera, "cam_frame");
1120 *(void **)&LINK_camframe_terminate =
1121 ::dlsym(libmmcamera, "camframe_terminate");
1122
1123 *(void **)&LINK_jpeg_encoder_init =
1124 ::dlsym(libmmcamera, "jpeg_encoder_init");
1125
1126 *(void **)&LINK_jpeg_encoder_encode =
1127 ::dlsym(libmmcamera, "jpeg_encoder_encode");
1128
1129 *(void **)&LINK_jpeg_encoder_join =
1130 ::dlsym(libmmcamera, "jpeg_encoder_join");
1131
1132 *(void **)&LINK_mmcamera_camframe_callback =
1133 ::dlsym(libmmcamera, "mmcamera_camframe_callback");
1134
1135 *LINK_mmcamera_camframe_callback = receive_camframe_callback;
1136
1137 *(void **)&LINK_mmcamera_jpegfragment_callback =
1138 ::dlsym(libmmcamera, "mmcamera_jpegfragment_callback");
1139
1140 *LINK_mmcamera_jpegfragment_callback = receive_jpeg_fragment_callback;
1141
1142 *(void **)&LINK_mmcamera_jpeg_callback =
1143 ::dlsym(libmmcamera, "mmcamera_jpeg_callback");
1144
1145 *LINK_mmcamera_jpeg_callback = receive_jpeg_callback;
1146
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001147 *(void **)&LINK_camframe_timeout_callback =
1148 ::dlsym(libmmcamera, "camframe_timeout_callback");
1149
1150 *LINK_camframe_timeout_callback = receive_camframetimeout_callback;
1151
Sravankb4f5f1c2010-01-21 11:06:17 +05301152 // 720 p new recording functions
1153 *(void **)&LINK_cam_frame_flush_free_video = ::dlsym(libmmcamera, "cam_frame_flush_free_video");
1154
1155 *(void **)&LINK_camframe_free_video = ::dlsym(libmmcamera, "cam_frame_add_free_video");
1156
1157 *(void **)&LINK_camframe_video_callback = ::dlsym(libmmcamera, "mmcamera_camframe_videocallback");
1158 *LINK_camframe_video_callback = receive_camframe_video_callback;
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08001159
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001160 *(void **)&LINK_mmcamera_shutter_callback =
1161 ::dlsym(libmmcamera, "mmcamera_shutter_callback");
1162
1163 *LINK_mmcamera_shutter_callback = receive_shutter_callback;
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08001164
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001165 *(void**)&LINK_jpeg_encoder_setMainImageQuality =
1166 ::dlsym(libmmcamera, "jpeg_encoder_setMainImageQuality");
Kiran Kumar H N8861f302010-01-05 12:01:41 -08001167
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001168 *(void**)&LINK_jpeg_encoder_setThumbnailQuality =
1169 ::dlsym(libmmcamera, "jpeg_encoder_setThumbnailQuality");
1170
1171 *(void**)&LINK_jpeg_encoder_setRotation =
1172 ::dlsym(libmmcamera, "jpeg_encoder_setRotation");
1173
Kiran Kumar H N8861f302010-01-05 12:01:41 -08001174/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001175 *(void**)&LINK_jpeg_encoder_setLocation =
1176 ::dlsym(libmmcamera, "jpeg_encoder_setLocation");
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001177*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001178 *(void **)&LINK_cam_conf =
1179 ::dlsym(libmmcamera, "cam_conf");
1180
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001181/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001182 *(void **)&LINK_default_sensor_get_snapshot_sizes =
1183 ::dlsym(libmmcamera, "default_sensor_get_snapshot_sizes");
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001184*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001185 *(void **)&LINK_launch_cam_conf_thread =
1186 ::dlsym(libmmcamera, "launch_cam_conf_thread");
1187
1188 *(void **)&LINK_release_cam_conf_thread =
1189 ::dlsym(libmmcamera, "release_cam_conf_thread");
1190
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001191/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001192 *(void **)&LINK_zoom_crop_upscale =
1193 ::dlsym(libmmcamera, "zoom_crop_upscale");
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001194*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001195
1196#else
1197 mmcamera_camframe_callback = receive_camframe_callback;
1198 mmcamera_jpegfragment_callback = receive_jpeg_fragment_callback;
1199 mmcamera_jpeg_callback = receive_jpeg_callback;
1200 mmcamera_shutter_callback = receive_shutter_callback;
1201#endif // DLOPEN_LIBMMCAMERA
1202
1203 /* The control thread is in libcamera itself. */
Brian Steuer07704892009-12-18 18:07:33 -08001204 if (pthread_join(w_thread, NULL) != 0) {
1205 LOGE("Camera open thread exit failed");
1206 return false;
1207 }
1208 mCameraControlFd = camerafd;
1209
Kiran Kumar H N585bc362010-01-19 13:04:44 -08001210 if (mCameraControlFd < 0) {
1211 LOGE("startCamera X: %s open failed: %s!",
1212 MSM_CAMERA_CONTROL,
1213 strerror(errno));
1214 return false;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001215 }
1216
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08001217 if( mCurrentTarget != TARGET_MSM7630 ){
Mohan Kandra284966d2010-01-05 13:39:15 -08001218 fb_fd = open("/dev/graphics/fb0", O_RDWR);
1219 if (fb_fd < 0) {
1220 LOGE("startCamera: fb0 open failed: %s!", strerror(errno));
1221 return FALSE;
1222 }
1223 }
1224
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001225 /* This will block until the control thread is launched. After that, sensor
1226 * information becomes available.
1227 */
1228
1229 if (LINK_launch_cam_conf_thread()) {
1230 LOGE("failed to launch the camera config thread");
1231 return false;
1232 }
1233
1234 memset(&mSensorInfo, 0, sizeof(mSensorInfo));
1235 if (ioctl(mCameraControlFd,
1236 MSM_CAM_IOCTL_GET_SENSOR_INFO,
1237 &mSensorInfo) < 0)
1238 LOGW("%s: cannot retrieve sensor info!", __FUNCTION__);
1239 else
1240 LOGI("%s: camsensor name %s, flash %d", __FUNCTION__,
1241 mSensorInfo.name, mSensorInfo.flash_enabled);
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001242/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001243 picture_sizes = LINK_default_sensor_get_snapshot_sizes(&PICTURE_SIZE_COUNT);
1244 if (!picture_sizes || !PICTURE_SIZE_COUNT) {
1245 LOGE("startCamera X: could not get snapshot sizes");
1246 return false;
1247 }
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001248*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001249 LOGV("startCamera X");
1250 return true;
1251}
1252
1253status_t QualcommCameraHardware::dump(int fd,
1254 const Vector<String16>& args) const
1255{
1256 const size_t SIZE = 256;
1257 char buffer[SIZE];
1258 String8 result;
1259
1260 // Dump internal primitives.
1261 result.append("QualcommCameraHardware::dump");
1262 snprintf(buffer, 255, "mMsgEnabled (%d)\n", mMsgEnabled);
1263 result.append(buffer);
1264 int width, height;
1265 mParameters.getPreviewSize(&width, &height);
1266 snprintf(buffer, 255, "preview width(%d) x height (%d)\n", width, height);
1267 result.append(buffer);
1268 mParameters.getPictureSize(&width, &height);
1269 snprintf(buffer, 255, "raw width(%d) x height (%d)\n", width, height);
1270 result.append(buffer);
1271 snprintf(buffer, 255,
1272 "preview frame size(%d), raw size (%d), jpeg size (%d) "
1273 "and jpeg max size (%d)\n", mPreviewFrameSize, mRawSize,
1274 mJpegSize, mJpegMaxSize);
1275 result.append(buffer);
1276 write(fd, result.string(), result.size());
1277
1278 // Dump internal objects.
Mohan Kandrad9efed92010-01-15 19:08:39 -08001279 if (mPreviewHeap != 0) {
1280 mPreviewHeap->dump(fd, args);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001281 }
1282 if (mRawHeap != 0) {
1283 mRawHeap->dump(fd, args);
1284 }
1285 if (mJpegHeap != 0) {
1286 mJpegHeap->dump(fd, args);
1287 }
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001288 if(mRawSnapshotAshmemHeap != 0 ){
1289 mRawSnapshotAshmemHeap->dump(fd, args);
1290 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001291 mParameters.dump(fd, args);
1292 return NO_ERROR;
1293}
1294
Mohan Kandra284966d2010-01-05 13:39:15 -08001295static bool native_get_maxzoom(int camfd, void *pZm)
1296{
1297 LOGV("native_get_maxzoom E");
1298
1299 struct msm_ctrl_cmd ctrlCmd;
1300 int32_t *pZoom = (int32_t *)pZm;
1301
1302 ctrlCmd.type = CAMERA_GET_PARM_MAXZOOM;
1303 ctrlCmd.timeout_ms = 5000;
1304 ctrlCmd.length = sizeof(int32_t);
1305 ctrlCmd.value = pZoom;
1306 ctrlCmd.resp_fd = camfd;
1307
1308 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1309 LOGE("native_get_maxzoom: ioctl fd %d error %s",
1310 camfd,
1311 strerror(errno));
1312 return false;
1313 }
Brian Steuerb62adbd2010-02-02 14:47:08 -08001314 LOGD("ctrlCmd.value = %d", *(int32_t *)ctrlCmd.value);
Mohan Kandra284966d2010-01-05 13:39:15 -08001315 memcpy(pZoom, (int32_t *)ctrlCmd.value, sizeof(int32_t));
1316
1317 LOGV("native_get_maxzoom X");
1318 return true;
1319}
1320
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001321static bool native_set_afmode(int camfd, isp3a_af_mode_t af_type)
1322{
1323 int rc;
1324 struct msm_ctrl_cmd ctrlCmd;
1325
1326 ctrlCmd.timeout_ms = 5000;
1327 ctrlCmd.type = CAMERA_SET_PARM_AUTO_FOCUS;
1328 ctrlCmd.length = sizeof(af_type);
1329 ctrlCmd.value = &af_type;
1330 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1331
1332 if ((rc = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0)
1333 LOGE("native_set_afmode: ioctl fd %d error %s\n",
1334 camfd,
1335 strerror(errno));
1336
1337 LOGV("native_set_afmode: ctrlCmd.status == %d\n", ctrlCmd.status);
1338 return rc >= 0 && ctrlCmd.status == CAMERA_EXIT_CB_DONE;
1339}
1340
1341static bool native_cancel_afmode(int camfd, int af_fd)
1342{
1343 int rc;
1344 struct msm_ctrl_cmd ctrlCmd;
1345
1346 ctrlCmd.timeout_ms = 0;
1347 ctrlCmd.type = CAMERA_AUTO_FOCUS_CANCEL;
1348 ctrlCmd.length = 0;
1349 ctrlCmd.value = NULL;
1350 ctrlCmd.resp_fd = -1; // there's no response fd
1351
1352 if ((rc = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND_2, &ctrlCmd)) < 0)
1353 {
1354 LOGE("native_cancel_afmode: ioctl fd %d error %s\n",
1355 camfd,
1356 strerror(errno));
1357 return false;
1358 }
1359
1360 return true;
1361}
1362
1363static bool native_start_preview(int camfd)
1364{
1365 struct msm_ctrl_cmd ctrlCmd;
1366
1367 ctrlCmd.timeout_ms = 5000;
1368 ctrlCmd.type = CAMERA_START_PREVIEW;
1369 ctrlCmd.length = 0;
1370 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1371
1372 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1373 LOGE("native_start_preview: MSM_CAM_IOCTL_CTRL_COMMAND fd %d error %s",
1374 camfd,
1375 strerror(errno));
1376 return false;
1377 }
1378
1379 return true;
1380}
1381
1382static bool native_get_picture (int camfd, common_crop_t *crop)
1383{
1384 struct msm_ctrl_cmd ctrlCmd;
1385
1386 ctrlCmd.timeout_ms = 5000;
1387 ctrlCmd.length = sizeof(common_crop_t);
1388 ctrlCmd.value = crop;
1389
1390 if(ioctl(camfd, MSM_CAM_IOCTL_GET_PICTURE, &ctrlCmd) < 0) {
1391 LOGE("native_get_picture: MSM_CAM_IOCTL_GET_PICTURE fd %d error %s",
1392 camfd,
1393 strerror(errno));
1394 return false;
1395 }
1396
1397 LOGV("crop: in1_w %d", crop->in1_w);
1398 LOGV("crop: in1_h %d", crop->in1_h);
1399 LOGV("crop: out1_w %d", crop->out1_w);
1400 LOGV("crop: out1_h %d", crop->out1_h);
1401
1402 LOGV("crop: in2_w %d", crop->in2_w);
1403 LOGV("crop: in2_h %d", crop->in2_h);
1404 LOGV("crop: out2_w %d", crop->out2_w);
1405 LOGV("crop: out2_h %d", crop->out2_h);
1406
1407 LOGV("crop: update %d", crop->update_flag);
1408
1409 return true;
1410}
1411
1412static bool native_stop_preview(int camfd)
1413{
1414 struct msm_ctrl_cmd ctrlCmd;
1415 ctrlCmd.timeout_ms = 5000;
1416 ctrlCmd.type = CAMERA_STOP_PREVIEW;
1417 ctrlCmd.length = 0;
1418 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1419
1420 if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1421 LOGE("native_stop_preview: ioctl fd %d error %s",
1422 camfd,
1423 strerror(errno));
1424 return false;
1425 }
1426
1427 return true;
1428}
1429
1430static bool native_prepare_snapshot(int camfd)
1431{
1432 int ioctlRetVal = true;
1433 struct msm_ctrl_cmd ctrlCmd;
1434
1435 ctrlCmd.timeout_ms = 1000;
1436 ctrlCmd.type = CAMERA_PREPARE_SNAPSHOT;
1437 ctrlCmd.length = 0;
1438 ctrlCmd.value = NULL;
1439 ctrlCmd.resp_fd = camfd;
1440
1441 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1442 LOGE("native_prepare_snapshot: ioctl fd %d error %s",
1443 camfd,
1444 strerror(errno));
1445 return false;
1446 }
1447 return true;
1448}
1449
1450static bool native_start_snapshot(int camfd)
1451{
1452 struct msm_ctrl_cmd ctrlCmd;
1453
1454 ctrlCmd.timeout_ms = 5000;
1455 ctrlCmd.type = CAMERA_START_SNAPSHOT;
1456 ctrlCmd.length = 0;
1457 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1458
1459 if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1460 LOGE("native_start_snapshot: ioctl fd %d error %s",
1461 camfd,
1462 strerror(errno));
1463 return false;
1464 }
1465
1466 return true;
1467}
1468
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001469static bool native_start_raw_snapshot(int camfd)
1470{
1471 int ret;
1472 struct msm_ctrl_cmd ctrlCmd;
1473
1474 ctrlCmd.timeout_ms = 1000;
1475 ctrlCmd.type = CAMERA_START_RAW_SNAPSHOT;
1476 ctrlCmd.length = 0;
1477 ctrlCmd.value = NULL;
1478 ctrlCmd.resp_fd = camfd;
1479
1480 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1481 LOGE("native_start_raw_snapshot: ioctl failed. ioctl return value "\
1482 "is %d \n", ret);
1483 return false;
1484 }
1485 return true;
1486}
1487
1488
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001489static bool native_stop_snapshot (int camfd)
1490{
1491 struct msm_ctrl_cmd ctrlCmd;
1492
1493 ctrlCmd.timeout_ms = 0;
1494 ctrlCmd.type = CAMERA_STOP_SNAPSHOT;
1495 ctrlCmd.length = 0;
1496 ctrlCmd.resp_fd = -1;
1497
1498 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND_2, &ctrlCmd) < 0) {
1499 LOGE("native_stop_snapshot: ioctl fd %d error %s",
1500 camfd,
1501 strerror(errno));
1502 return false;
1503 }
1504
1505 return true;
1506}
Sravankb4f5f1c2010-01-21 11:06:17 +05301507/*===========================================================================
1508 * FUNCTION - native_start_recording -
1509 *
1510 * DESCRIPTION:
1511 *==========================================================================*/
1512static bool native_start_recording(int camfd)
1513{
1514 int ret;
1515 struct msm_ctrl_cmd ctrlCmd;
1516
1517 ctrlCmd.timeout_ms = 1000;
1518 ctrlCmd.type = CAMERA_START_RECORDING;
1519 ctrlCmd.length = 0;
1520 ctrlCmd.value = NULL;
1521 ctrlCmd.resp_fd = camfd;
1522
1523 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1524 LOGE("native_start_recording: ioctl failed. ioctl return value "\
1525 "is %d \n", ret);
1526 return false;
1527 }
Mohan Kandraf1ebf982010-02-02 15:25:43 -08001528 LOGV("native_start_recording: ioctl good. ioctl return value is %d \n",ret);
Sravankb4f5f1c2010-01-21 11:06:17 +05301529
1530 /* TODO: Check status of postprocessing if there is any,
1531 * PP status should be in ctrlCmd */
1532
1533 return true;
1534}
1535
1536/*===========================================================================
1537 * FUNCTION - native_stop_recording -
1538 *
1539 * DESCRIPTION:
1540 *==========================================================================*/
1541static bool native_stop_recording(int camfd)
1542{
1543 int ret;
1544 struct msm_ctrl_cmd ctrlCmd;
Kiran Kumar H Nb49af212010-02-17 15:12:17 -08001545 LOGV("in native_stop_recording ");
Sravankb4f5f1c2010-01-21 11:06:17 +05301546 ctrlCmd.timeout_ms = 1000;
1547 ctrlCmd.type = CAMERA_STOP_RECORDING;
1548 ctrlCmd.length = 0;
1549 ctrlCmd.value = NULL;
1550 ctrlCmd.resp_fd = camfd;
1551
1552 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1553 LOGE("native_stop_video: ioctl failed. ioctl return value is %d \n",
1554 ret);
1555 return false;
1556 }
1557 LOGV("in native_stop_recording returned %d", ret);
1558 return true;
1559}
1560/*===========================================================================
1561 * FUNCTION - native_start_video -
1562 *
1563 * DESCRIPTION:
1564 *==========================================================================*/
1565static bool native_start_video(int camfd)
1566{
1567 int ret;
1568 struct msm_ctrl_cmd ctrlCmd;
1569
1570 ctrlCmd.timeout_ms = 1000;
1571 ctrlCmd.type = CAMERA_START_VIDEO;
1572 ctrlCmd.length = 0;
1573 ctrlCmd.value = NULL;
1574 ctrlCmd.resp_fd = camfd;
1575
1576 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1577 LOGE("native_start_video: ioctl failed. ioctl return value is %d \n",
1578 ret);
1579 return false;
1580 }
1581
1582 /* TODO: Check status of postprocessing if there is any,
1583 * PP status should be in ctrlCmd */
1584
1585 return true;
1586}
1587
1588/*===========================================================================
1589 * FUNCTION - native_stop_video -
1590 *
1591 * DESCRIPTION:
1592 *==========================================================================*/
1593static bool native_stop_video(int camfd)
1594{
1595 int ret;
1596 struct msm_ctrl_cmd ctrlCmd;
1597
1598 ctrlCmd.timeout_ms = 1000;
1599 ctrlCmd.type = CAMERA_STOP_VIDEO;
1600 ctrlCmd.length = 0;
1601 ctrlCmd.value = NULL;
1602 ctrlCmd.resp_fd = camfd;
1603
1604 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1605 LOGE("native_stop_video: ioctl failed. ioctl return value is %d \n",
1606 ret);
1607 return false;
1608 }
1609
1610 return true;
1611}
1612/*==========================================================================*/
1613
1614static cam_frame_start_parms frame_parms;
1615static int recordingState = 0;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001616
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001617static rat_t latitude[3];
1618static rat_t longitude[3];
1619static char lonref[2];
1620static char latref[2];
1621static char dateTime[20];
1622static rat_t altitude;
1623
1624static void addExifTag(exif_tag_id_t tagid, exif_tag_type_t type,
1625 uint32_t count, uint8_t copy, void *data) {
1626
1627 if(exif_table_numEntries == MAX_EXIF_TABLE_ENTRIES) {
1628 LOGE("Number of entries exceeded limit");
1629 return;
1630 }
1631
1632 int index = exif_table_numEntries;
1633 exif_data[index].tag_id = tagid;
1634 exif_data[index].tag_entry.type = type;
1635 exif_data[index].tag_entry.count = count;
1636 exif_data[index].tag_entry.copy = copy;
1637 if((type == EXIF_RATIONAL) && (count > 1))
1638 exif_data[index].tag_entry.data._rats = (rat_t *)data;
1639 if((type == EXIF_RATIONAL) && (count == 1))
1640 exif_data[index].tag_entry.data._rat = *(rat_t *)data;
1641 else if(type == EXIF_ASCII)
1642 exif_data[index].tag_entry.data._ascii = (char *)data;
1643 else if(type == EXIF_BYTE)
1644 exif_data[index].tag_entry.data._byte = *(uint8_t *)data;
1645
1646 // Increase number of entries
1647 exif_table_numEntries++;
1648}
1649
1650static void parseLatLong(const char *latlonString, int *pDegrees,
1651 int *pMinutes, int *pSeconds ) {
1652
1653 double value = atof(latlonString);
1654 value = fabs(value);
1655 int degrees = (int) value;
1656
1657 double remainder = value - degrees;
1658 int minutes = (int) (remainder * 60);
1659 int seconds = (int) (((remainder * 60) - minutes) * 60 * 1000);
1660
1661 *pDegrees = degrees;
1662 *pMinutes = minutes;
1663 *pSeconds = seconds;
1664}
1665
1666static void setLatLon(exif_tag_id_t tag, const char *latlonString) {
1667
1668 int degrees, minutes, seconds;
1669
1670 parseLatLong(latlonString, &degrees, &minutes, &seconds);
1671
1672 rat_t value[3] = { {degrees, 1},
1673 {minutes, 1},
1674 {seconds, 1000} };
1675
1676 if(tag == EXIFTAGID_GPS_LATITUDE) {
1677 memcpy(latitude, value, sizeof(latitude));
1678 addExifTag(EXIFTAGID_GPS_LATITUDE, EXIF_RATIONAL, 3,
1679 1, (void *)latitude);
1680 } else {
1681 memcpy(longitude, value, sizeof(longitude));
1682 addExifTag(EXIFTAGID_GPS_LONGITUDE, EXIF_RATIONAL, 3,
1683 1, (void *)longitude);
1684 }
1685}
1686
1687void QualcommCameraHardware::setGpsParameters() {
1688 const char *str = NULL;
1689
1690 //Set Latitude
1691 str = mParameters.get(CameraParameters::KEY_GPS_LATITUDE);
1692 if(str != NULL) {
1693 setLatLon(EXIFTAGID_GPS_LATITUDE, str);
1694 //set Latitude Ref
1695 str = NULL;
1696 str = mParameters.get(CameraParameters::KEY_GPS_LATITUDE_REF);
1697 if(str != NULL) {
1698 strncpy(latref, str, 1);
1699 latref[1] = '\0';
1700 addExifTag(EXIFTAGID_GPS_LATITUDE_REF, EXIF_ASCII, 2,
1701 1, (void *)latref);
1702 }
1703 }
1704
1705 //set Longitude
1706 str = NULL;
1707 str = mParameters.get(CameraParameters::KEY_GPS_LONGITUDE);
1708 if(str != NULL) {
1709 setLatLon(EXIFTAGID_GPS_LONGITUDE, str);
1710 //set Longitude Ref
1711 str = NULL;
1712 str = mParameters.get(CameraParameters::KEY_GPS_LONGITUDE_REF);
1713 if(str != NULL) {
1714 strncpy(lonref, str, 1);
1715 lonref[1] = '\0';
1716 addExifTag(EXIFTAGID_GPS_LONGITUDE_REF, EXIF_ASCII, 2,
1717 1, (void *)lonref);
1718 }
1719 }
1720
1721 //set Altitude
1722 str = NULL;
1723 str = mParameters.get(CameraParameters::KEY_GPS_ALTITUDE);
1724 if(str != NULL) {
1725 int value = atoi(str);
1726 rat_t alt_value = {value, 1000};
1727 memcpy(&altitude, &alt_value, sizeof(altitude));
1728 addExifTag(EXIFTAGID_GPS_ALTITUDE, EXIF_RATIONAL, 1,
1729 1, (void *)&altitude);
1730 //set AltitudeRef
1731 int ref = mParameters.getInt(CameraParameters::KEY_GPS_ALTITUDE_REF);
1732 if( !(ref < 0 || ref > 1) )
1733 addExifTag(EXIFTAGID_GPS_ALTITUDE_REF, EXIF_BYTE, 1,
1734 1, (void *)&ref);
1735 }
1736
1737
1738}
1739
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001740bool QualcommCameraHardware::native_jpeg_encode(void)
1741{
1742 int jpeg_quality = mParameters.getInt("jpeg-quality");
1743 if (jpeg_quality >= 0) {
1744 LOGV("native_jpeg_encode, current jpeg main img quality =%d",
1745 jpeg_quality);
1746 if(!LINK_jpeg_encoder_setMainImageQuality(jpeg_quality)) {
1747 LOGE("native_jpeg_encode set jpeg-quality failed");
1748 return false;
1749 }
1750 }
1751
1752 int thumbnail_quality = mParameters.getInt("jpeg-thumbnail-quality");
1753 if (thumbnail_quality >= 0) {
1754 LOGV("native_jpeg_encode, current jpeg thumbnail quality =%d",
1755 thumbnail_quality);
1756 if(!LINK_jpeg_encoder_setThumbnailQuality(thumbnail_quality)) {
1757 LOGE("native_jpeg_encode set thumbnail-quality failed");
1758 return false;
1759 }
1760 }
1761
1762 int rotation = mParameters.getInt("rotation");
1763 if (rotation >= 0) {
1764 LOGV("native_jpeg_encode, rotation = %d", rotation);
1765 if(!LINK_jpeg_encoder_setRotation(rotation)) {
1766 LOGE("native_jpeg_encode set rotation failed");
1767 return false;
1768 }
1769 }
1770
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001771// jpeg_set_location();
1772 if(mParameters.getInt(CameraParameters::KEY_GPS_STATUS) == 1) {
1773 setGpsParameters();
1774 }
1775 //set TimeStamp
1776 const char *str = mParameters.get(CameraParameters::KEY_EXIF_DATETIME);
1777 if(str != NULL) {
1778 strncpy(dateTime, str, 19);
1779 dateTime[19] = '\0';
1780 addExifTag(EXIFTAGID_EXIF_DATE_TIME_ORIGINAL, EXIF_ASCII,
1781 20, 1, (void *)dateTime);
1782 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001783
1784 if (!LINK_jpeg_encoder_encode(&mDimension,
1785 (uint8_t *)mThumbnailHeap->mHeap->base(),
1786 mThumbnailHeap->mHeap->getHeapID(),
1787 (uint8_t *)mRawHeap->mHeap->base(),
1788 mRawHeap->mHeap->getHeapID(),
Srinivasan Kannan5701a942010-04-15 16:17:21 -07001789 &mCrop, exif_data, exif_table_numEntries,
1790 jpegPadding/2)) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001791 LOGE("native_jpeg_encode: jpeg_encoder_encode failed.");
1792 return false;
1793 }
1794 return true;
1795}
1796
1797bool QualcommCameraHardware::native_set_parm(
1798 cam_ctrl_type type, uint16_t length, void *value)
1799{
1800 struct msm_ctrl_cmd ctrlCmd;
1801
1802 ctrlCmd.timeout_ms = 5000;
1803 ctrlCmd.type = (uint16_t)type;
1804 ctrlCmd.length = length;
1805 // FIXME: this will be put in by the kernel
1806 ctrlCmd.resp_fd = mCameraControlFd;
1807 ctrlCmd.value = value;
1808
1809 LOGV("%s: fd %d, type %d, length %d", __FUNCTION__,
1810 mCameraControlFd, type, length);
1811 if (ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0 ||
1812 ctrlCmd.status != CAM_CTRL_SUCCESS) {
1813 LOGE("%s: error (%s): fd %d, type %d, length %d, status %d",
1814 __FUNCTION__, strerror(errno),
1815 mCameraControlFd, type, length, ctrlCmd.status);
1816 return false;
1817 }
1818 return true;
1819}
1820
1821void QualcommCameraHardware::jpeg_set_location()
1822{
1823 bool encode_location = true;
1824 camera_position_type pt;
1825
1826#define PARSE_LOCATION(what,type,fmt,desc) do { \
1827 pt.what = 0; \
1828 const char *what##_str = mParameters.get("gps-"#what); \
1829 LOGV("GPS PARM %s --> [%s]", "gps-"#what, what##_str); \
1830 if (what##_str) { \
1831 type what = 0; \
1832 if (sscanf(what##_str, fmt, &what) == 1) \
1833 pt.what = what; \
1834 else { \
1835 LOGE("GPS " #what " %s could not" \
1836 " be parsed as a " #desc, what##_str); \
1837 encode_location = false; \
1838 } \
1839 } \
1840 else { \
1841 LOGV("GPS " #what " not specified: " \
1842 "defaulting to zero in EXIF header."); \
1843 encode_location = false; \
1844 } \
1845 } while(0)
1846
1847 PARSE_LOCATION(timestamp, long, "%ld", "long");
1848 if (!pt.timestamp) pt.timestamp = time(NULL);
1849 PARSE_LOCATION(altitude, short, "%hd", "short");
1850 PARSE_LOCATION(latitude, double, "%lf", "double float");
1851 PARSE_LOCATION(longitude, double, "%lf", "double float");
1852
1853#undef PARSE_LOCATION
1854
1855 if (encode_location) {
1856 LOGD("setting image location ALT %d LAT %lf LON %lf",
1857 pt.altitude, pt.latitude, pt.longitude);
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001858/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001859 if (!LINK_jpeg_encoder_setLocation(&pt)) {
1860 LOGE("jpeg_set_location: LINK_jpeg_encoder_setLocation failed.");
1861 }
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001862*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001863 }
1864 else LOGV("not setting image location");
1865}
1866
1867void QualcommCameraHardware::runFrameThread(void *data)
1868{
1869 LOGV("runFrameThread E");
1870
1871 int cnt;
1872
1873#if DLOPEN_LIBMMCAMERA
1874 // We need to maintain a reference to libqcamera.so for the duration of the
1875 // frame thread, because we do not know when it will exit relative to the
1876 // lifetime of this object. We do not want to dlclose() libqcamera while
1877 // LINK_cam_frame is still running.
1878 void *libhandle = ::dlopen("liboemcamera.so", RTLD_NOW);
1879 LOGV("FRAME: loading libqcamera at %p", libhandle);
1880 if (!libhandle) {
1881 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
1882 }
1883 if (libhandle)
1884#endif
1885 {
1886 LINK_cam_frame(data);
1887 }
1888
Mohan Kandrad9efed92010-01-15 19:08:39 -08001889 mPreviewHeap.clear();
Mohan Kandraf1ebf982010-02-02 15:25:43 -08001890 if(( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250))
Sravankb4f5f1c2010-01-21 11:06:17 +05301891 mRecordHeap.clear();
1892
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001893#if DLOPEN_LIBMMCAMERA
1894 if (libhandle) {
1895 ::dlclose(libhandle);
1896 LOGV("FRAME: dlclose(libqcamera)");
1897 }
1898#endif
1899
1900 mFrameThreadWaitLock.lock();
1901 mFrameThreadRunning = false;
1902 mFrameThreadWait.signal();
1903 mFrameThreadWaitLock.unlock();
1904
1905 LOGV("runFrameThread X");
1906}
1907
Sravankb4f5f1c2010-01-21 11:06:17 +05301908void QualcommCameraHardware::runVideoThread(void *data)
1909{
1910 LOGD("runVideoThread E");
1911 msm_frame* vframe = NULL;
1912
1913 while(true) {
1914 pthread_mutex_lock(&(g_busy_frame_queue.mut));
1915
Srinivasan Kannanfc3915c2010-03-18 10:54:40 -07001916 // Exit the thread , in case of stop recording..
1917 mVideoThreadWaitLock.lock();
1918 if(mVideoThreadExit){
1919 LOGV("Exiting video thread..");
1920 mVideoThreadWaitLock.unlock();
1921 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
1922 break;
1923 }
1924 mVideoThreadWaitLock.unlock();
1925
Kiran Kumar H Nb49af212010-02-17 15:12:17 -08001926 LOGV("in video_thread : wait for video frame ");
Sravankb4f5f1c2010-01-21 11:06:17 +05301927 // check if any frames are available in busyQ and give callback to
1928 // services/video encoder
1929 cam_frame_wait_video();
1930 LOGV("video_thread, wait over..");
1931
1932 // Exit the thread , in case of stop recording..
1933 mVideoThreadWaitLock.lock();
1934 if(mVideoThreadExit){
Kiran Kumar H Nb49af212010-02-17 15:12:17 -08001935 LOGV("Exiting video thread..");
Sravankb4f5f1c2010-01-21 11:06:17 +05301936 mVideoThreadWaitLock.unlock();
1937 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
1938 break;
1939 }
1940 mVideoThreadWaitLock.unlock();
1941
1942 // Get the video frame to be encoded
1943 vframe = cam_frame_get_video ();
Apurva Rajgurud9b0b302010-02-19 11:22:56 -08001944 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
Sravankb4f5f1c2010-01-21 11:06:17 +05301945 LOGV("in video_thread : got video frame ");
1946
Mohan Kandrabad0eaa2010-02-04 15:11:54 -08001947 if (UNLIKELY(mDebugFps)) {
1948 debugShowVideoFPS();
1949 }
1950
Sravankb4f5f1c2010-01-21 11:06:17 +05301951 if(vframe != NULL) {
1952 // Find the offset within the heap of the current buffer.
1953 LOGV("Got video frame : buffer %d base %d ", vframe->buffer, mRecordHeap->mHeap->base());
1954 ssize_t offset =
1955 (ssize_t)vframe->buffer - (ssize_t)mRecordHeap->mHeap->base();
1956 LOGV("offset = %d , alignsize = %d , offset later = %d", offset, mRecordHeap->mAlignedBufferSize, (offset / mRecordHeap->mAlignedBufferSize));
1957
1958 offset /= mRecordHeap->mAlignedBufferSize;
1959
1960 // dump frames for test purpose
1961#ifdef DUMP_VIDEO_FRAMES
1962 static int frameCnt = 0;
1963 if (frameCnt >= 11 && frameCnt <= 13 ) {
1964 char buf[128];
1965 sprintf(buf, "/data/%d_v.yuv", frameCnt);
1966 int file_fd = open(buf, O_RDWR | O_CREAT, 0777);
1967 LOGV("dumping video frame %d", frameCnt);
1968 if (file_fd < 0) {
1969 LOGE("cannot open file\n");
1970 }
1971 else
1972 {
1973 write(file_fd, (const void *)vframe->buffer,
1974 vframe->cbcr_off * 3 / 2);
1975 }
1976 close(file_fd);
1977 }
1978 frameCnt++;
1979#endif
1980 // Enable IF block to give frames to encoder , ELSE block for just simulation
1981#if 1
1982 LOGV("in video_thread : got video frame, before if check giving frame to services/encoder");
1983 mCallbackLock.lock();
1984 int msgEnabled = mMsgEnabled;
1985 data_callback_timestamp rcb = mDataCallbackTimestamp;
1986 void *rdata = mCallbackCookie;
1987 mCallbackLock.unlock();
1988
1989 if(rcb != NULL && (msgEnabled & CAMERA_MSG_VIDEO_FRAME) ) {
1990 LOGV("in video_thread : got video frame, giving frame to services/encoder");
1991 rcb(systemTime(), CAMERA_MSG_VIDEO_FRAME, mRecordHeap->mBuffers[offset], rdata);
Sravankb4f5f1c2010-01-21 11:06:17 +05301992 }
1993#else
1994 // 720p output2 : simulate release frame here:
1995 LOGE("in video_thread simulation , releasing the video frame");
1996 LINK_camframe_free_video(vframe);
1997#endif
1998
1999 } else LOGE("in video_thread get frame returned null");
2000
Sravankb4f5f1c2010-01-21 11:06:17 +05302001
2002 } // end of while loop
Mohan Kandra156d0ac2010-01-25 16:59:17 -08002003
2004 mVideoThreadWaitLock.lock();
2005 mVideoThreadRunning = false;
2006 mVideoThreadWait.signal();
2007 mVideoThreadWaitLock.unlock();
2008
Sravankb4f5f1c2010-01-21 11:06:17 +05302009 LOGV("runVideoThread X");
2010}
2011
2012void *video_thread(void *user)
2013{
2014 LOGV("video_thread E");
2015 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
2016 if (obj != 0) {
2017 obj->runVideoThread(user);
2018 }
2019 else LOGE("not starting video thread: the object went away!");
2020 LOGV("video_thread X");
2021 return NULL;
2022}
2023
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002024void *frame_thread(void *user)
2025{
2026 LOGD("frame_thread E");
2027 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
2028 if (obj != 0) {
2029 obj->runFrameThread(user);
2030 }
2031 else LOGW("not starting frame thread: the object went away!");
2032 LOGD("frame_thread X");
2033 return NULL;
2034}
2035
2036bool QualcommCameraHardware::initPreview()
2037{
2038 // See comments in deinitPreview() for why we have to wait for the frame
2039 // thread here, and why we can't use pthread_join().
Sravankb4f5f1c2010-01-21 11:06:17 +05302040 int videoWidth, videoHeight;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002041 mParameters.getPreviewSize(&previewWidth, &previewHeight);
Sravankb4f5f1c2010-01-21 11:06:17 +05302042
2043 videoWidth = previewWidth; // temporary , should be configurable later
2044 videoHeight = previewHeight;
2045 LOGV("initPreview E: preview size=%dx%d videosize = %d x %d", previewWidth, previewHeight, videoWidth, videoHeight );
2046
Mohan Kandraf1ebf982010-02-02 15:25:43 -08002047 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05302048 mDimension.video_width = videoWidth;
Kiran Kumar H N7ac84e32010-02-01 10:58:47 -08002049 mDimension.video_width = CEILING16(mDimension.video_width);
Sravankb4f5f1c2010-01-21 11:06:17 +05302050 mDimension.video_height = videoHeight;
Sravank64461e82010-02-25 15:10:09 +05302051 // for 720p , preview can be 768X432
2052 previewWidth = mDimension.display_width;
2053 previewHeight= mDimension.display_height;
Sravankb4f5f1c2010-01-21 11:06:17 +05302054 LOGV("initPreview : preview size=%dx%d videosize = %d x %d", previewWidth, previewHeight, mDimension.video_width, mDimension.video_height );
2055 }
2056
2057
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002058 mFrameThreadWaitLock.lock();
2059 while (mFrameThreadRunning) {
2060 LOGV("initPreview: waiting for old frame thread to complete.");
2061 mFrameThreadWait.wait(mFrameThreadWaitLock);
2062 LOGV("initPreview: old frame thread completed.");
2063 }
2064 mFrameThreadWaitLock.unlock();
2065
2066 mSnapshotThreadWaitLock.lock();
2067 while (mSnapshotThreadRunning) {
2068 LOGV("initPreview: waiting for old snapshot thread to complete.");
2069 mSnapshotThreadWait.wait(mSnapshotThreadWaitLock);
2070 LOGV("initPreview: old snapshot thread completed.");
2071 }
2072 mSnapshotThreadWaitLock.unlock();
2073
2074 int cnt = 0;
2075 mPreviewFrameSize = previewWidth * previewHeight * 3/2;
Mohan Kandrad9efed92010-01-15 19:08:39 -08002076 dstOffset = 0;
2077 mPreviewHeap = new PmemPool("/dev/pmem_adsp",
Mohan Kandra284966d2010-01-05 13:39:15 -08002078 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
2079 mCameraControlFd,
Sravankb4f5f1c2010-01-21 11:06:17 +05302080 MSM_PMEM_PREVIEW, //MSM_PMEM_OUTPUT2,
Mohan Kandra284966d2010-01-05 13:39:15 -08002081 mPreviewFrameSize,
Mohan Kandrad9efed92010-01-15 19:08:39 -08002082 kPreviewBufferCountActual,
Mohan Kandra284966d2010-01-05 13:39:15 -08002083 mPreviewFrameSize,
Mohan Kandrad9efed92010-01-15 19:08:39 -08002084 "preview");
Mohan Kandra284966d2010-01-05 13:39:15 -08002085
Mohan Kandrad9efed92010-01-15 19:08:39 -08002086 if (!mPreviewHeap->initialized()) {
2087 mPreviewHeap.clear();
Mohan Kandra284966d2010-01-05 13:39:15 -08002088 LOGE("initPreview X: could not initialize Camera preview heap.");
2089 return false;
2090 }
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002091 if( mCurrentTarget == TARGET_MSM7630 ) {
Srinivasan Kannan613301c2010-02-10 17:08:53 -08002092 mPostViewHeap.clear();
Kiran Kumar H N595970b2010-01-12 10:41:09 -08002093 if(mPostViewHeap == NULL) {
2094 LOGV(" Allocating Postview heap ");
2095 /* mPostViewHeap should be declared only for 7630 target */
2096 mPostViewHeap =
2097 new PmemPool("/dev/pmem_adsp",
2098 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
2099 mCameraControlFd,
Sravankb4f5f1c2010-01-21 11:06:17 +05302100 MSM_PMEM_PREVIEW, //MSM_PMEM_OUTPUT2,
Kiran Kumar H N595970b2010-01-12 10:41:09 -08002101 mPreviewFrameSize,
2102 1,
2103 mPreviewFrameSize,
2104 "postview");
Mohan Kandra284966d2010-01-05 13:39:15 -08002105
Kiran Kumar H N595970b2010-01-12 10:41:09 -08002106 if (!mPostViewHeap->initialized()) {
2107 mPostViewHeap.clear();
2108 LOGE(" Failed to initialize Postview Heap");
2109 return false;
2110 }
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002111 }
Mohan Kandraf1ebf982010-02-02 15:25:43 -08002112 }
2113
2114 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250) ) {
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002115
2116 // Allocate video buffers after allocating preview buffers.
Sravankb4f5f1c2010-01-21 11:06:17 +05302117 initRecord();
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002118 }
Sravankb4f5f1c2010-01-21 11:06:17 +05302119
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002120 // mDimension will be filled with thumbnail_width, thumbnail_height,
2121 // orig_picture_dx, and orig_picture_dy after this function call. We need to
2122 // keep it for jpeg_encoder_encode.
2123 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
2124 sizeof(cam_ctrl_dimension_t), &mDimension);
2125
2126 if (ret) {
2127 for (cnt = 0; cnt < kPreviewBufferCount; cnt++) {
Mohan Kandrad9efed92010-01-15 19:08:39 -08002128 frames[cnt].fd = mPreviewHeap->mHeap->getHeapID();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002129 frames[cnt].buffer =
Mohan Kandrad9efed92010-01-15 19:08:39 -08002130 (uint32_t)mPreviewHeap->mHeap->base() + mPreviewHeap->mAlignedBufferSize * cnt;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002131 frames[cnt].y_off = 0;
2132 frames[cnt].cbcr_off = previewWidth * previewHeight;
Sravankb4f5f1c2010-01-21 11:06:17 +05302133 frames[cnt].path = OUTPUT_TYPE_P; // MSM_FRAME_ENC;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002134 }
2135
2136 mFrameThreadWaitLock.lock();
2137 pthread_attr_t attr;
2138 pthread_attr_init(&attr);
2139 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
Sravankb4f5f1c2010-01-21 11:06:17 +05302140
2141 frame_parms.frame = frames[kPreviewBufferCount - 1];
Apurva Rajguruc73c1722010-04-15 17:39:11 -07002142
2143 if( mCurrentTarget == TARGET_MSM7630 || mCurrentTarget == TARGET_QSD8250 )
2144 frame_parms.video_frame = recordframes[kPreviewBufferCount - 1];
2145 else
2146 frame_parms.video_frame = frames[kPreviewBufferCount - 1];
Sravankb4f5f1c2010-01-21 11:06:17 +05302147
2148 LOGV ("initpreview before cam_frame thread carete , video frame buffer=%lu fd=%d y_off=%d cbcr_off=%d \n",
2149 (unsigned long)frame_parms.video_frame.buffer, frame_parms.video_frame.fd, frame_parms.video_frame.y_off,
2150 frame_parms.video_frame.cbcr_off);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002151 mFrameThreadRunning = !pthread_create(&mFrameThread,
2152 &attr,
2153 frame_thread,
Sravankb4f5f1c2010-01-21 11:06:17 +05302154 (void*)&(frame_parms));
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002155 ret = mFrameThreadRunning;
2156 mFrameThreadWaitLock.unlock();
2157 }
2158
2159 LOGV("initPreview X: %d", ret);
2160 return ret;
2161}
2162
2163void QualcommCameraHardware::deinitPreview(void)
2164{
2165 LOGI("deinitPreview E");
2166
2167 // When we call deinitPreview(), we signal to the frame thread that it
2168 // needs to exit, but we DO NOT WAIT for it to complete here. The problem
2169 // is that deinitPreview is sometimes called from the frame-thread's
2170 // callback, when the refcount on the Camera client reaches zero. If we
2171 // called pthread_join(), we would deadlock. So, we just call
2172 // LINK_camframe_terminate() in deinitPreview(), which makes sure that
2173 // after the preview callback returns, the camframe thread will exit. We
2174 // could call pthread_join() in initPreview() to join the last frame
2175 // thread. However, we would also have to call pthread_join() in release
2176 // as well, shortly before we destroy the object; this would cause the same
2177 // deadlock, since release(), like deinitPreview(), may also be called from
2178 // the frame-thread's callback. This we have to make the frame thread
2179 // detached, and use a separate mechanism to wait for it to complete.
2180
Kiran Kumar H N7ac84e32010-02-01 10:58:47 -08002181 LINK_camframe_terminate();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002182 LOGI("deinitPreview X");
2183}
2184
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002185bool QualcommCameraHardware::initRawSnapshot()
2186{
2187 LOGV("initRawSnapshot E");
2188
2189 //get width and height from Dimension Object
2190 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
2191 sizeof(cam_ctrl_dimension_t), &mDimension);
2192
2193 if(!ret){
2194 LOGE("initRawSnapshot X: failed to set dimension");
2195 return false;
2196 }
2197 int rawSnapshotSize = mDimension.raw_picture_height *
2198 mDimension.raw_picture_width;
2199
2200 LOGV("raw_snapshot_buffer_size = %d, raw_picture_height = %d, "\
2201 "raw_picture_width = %d",
2202 rawSnapshotSize, mDimension.raw_picture_height,
2203 mDimension.raw_picture_width);
2204
2205 if (mRawSnapShotPmemHeap != NULL) {
2206 LOGV("initRawSnapshot: clearing old mRawSnapShotPmemHeap.");
2207 mRawSnapShotPmemHeap.clear();
2208 }
2209
2210 //Pmem based pool for Camera Driver
2211 mRawSnapShotPmemHeap = new PmemPool("/dev/pmem_adsp",
Dinesh Gargeecf1a62010-04-19 16:31:30 -07002212 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002213 mCameraControlFd,
2214 MSM_PMEM_RAW_MAINIMG,
2215 rawSnapshotSize,
2216 1,
2217 rawSnapshotSize,
2218 "raw pmem snapshot camera");
2219
2220 if (!mRawSnapShotPmemHeap->initialized()) {
2221 mRawSnapShotPmemHeap.clear();
2222 LOGE("initRawSnapshot X: error initializing mRawSnapshotHeap");
2223 return false;
2224 }
2225 LOGV("initRawSnapshot X");
2226 return true;
2227
2228}
2229
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002230bool QualcommCameraHardware::initRaw(bool initJpegHeap)
2231{
2232 int rawWidth, rawHeight;
Apurva Rajguru8d1773b2009-12-02 14:21:23 -08002233
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002234 mParameters.getPictureSize(&rawWidth, &rawHeight);
2235 LOGV("initRaw E: picture size=%dx%d", rawWidth, rawHeight);
2236
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08002237 int thumbnailBufferSize;
2238 //Thumbnail height should be smaller than Picture height
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002239 if (rawHeight > (int)thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height){
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08002240 mDimension.ui_thumbnail_width =
2241 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].width;
2242 mDimension.ui_thumbnail_height =
2243 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height;
2244 uint32_t pictureAspectRatio = (uint32_t)((rawWidth * Q12) / rawHeight);
2245 uint32_t i;
2246 for(i = 0; i < THUMBNAIL_SIZE_COUNT; i++ )
2247 {
2248 if(thumbnail_sizes[i].aspect_ratio == pictureAspectRatio)
2249 {
2250 mDimension.ui_thumbnail_width = thumbnail_sizes[i].width;
2251 mDimension.ui_thumbnail_height = thumbnail_sizes[i].height;
2252 break;
2253 }
2254 }
2255 }
2256 else{
2257 mDimension.ui_thumbnail_height = THUMBNAIL_SMALL_HEIGHT;
2258 mDimension.ui_thumbnail_width =
2259 (THUMBNAIL_SMALL_HEIGHT * rawWidth)/ rawHeight;
2260 }
2261
2262 LOGV("Thumbnail Size Width %d Height %d",
2263 mDimension.ui_thumbnail_width,
2264 mDimension.ui_thumbnail_height);
2265
2266 thumbnailBufferSize = mDimension.ui_thumbnail_width *
2267 mDimension.ui_thumbnail_height * 3 / 2;
2268
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002269 // mDimension will be filled with thumbnail_width, thumbnail_height,
2270 // orig_picture_dx, and orig_picture_dy after this function call. We need to
2271 // keep it for jpeg_encoder_encode.
2272 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
2273 sizeof(cam_ctrl_dimension_t), &mDimension);
2274 if(!ret) {
2275 LOGE("initRaw X: failed to set dimension");
2276 return false;
2277 }
2278
2279 if (mJpegHeap != NULL) {
2280 LOGV("initRaw: clearing old mJpegHeap.");
2281 mJpegHeap.clear();
2282 }
2283
2284 // Snapshot
2285 mRawSize = rawWidth * rawHeight * 3 / 2;
Apurva Rajguru8d1773b2009-12-02 14:21:23 -08002286
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002287 if( mCurrentTarget == TARGET_MSM7627 )
Apurva Rajguru8d1773b2009-12-02 14:21:23 -08002288 mJpegMaxSize = CEILING16(rawWidth) * CEILING16(rawHeight) * 3 / 2;
2289 else
2290 mJpegMaxSize = rawWidth * rawHeight * 3 / 2;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002291
2292 LOGV("initRaw: initializing mRawHeap.");
2293 mRawHeap =
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002294 new PmemPool("/dev/pmem_adsp",
Dinesh Gargeecf1a62010-04-19 16:31:30 -07002295 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002296 mCameraControlFd,
2297 MSM_PMEM_MAINIMG,
2298 mJpegMaxSize,
2299 kRawBufferCount,
2300 mRawSize,
2301 "snapshot camera");
2302
2303 if (!mRawHeap->initialized()) {
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002304 LOGE("initRaw X failed ");
2305 mRawHeap.clear();
2306 LOGE("initRaw X: error initializing mRawHeap");
2307 return false;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002308 }
2309
2310 LOGV("do_mmap snapshot pbuf = %p, pmem_fd = %d",
2311 (uint8_t *)mRawHeap->mHeap->base(), mRawHeap->mHeap->getHeapID());
2312
2313 // Jpeg
2314
2315 if (initJpegHeap) {
2316 LOGV("initRaw: initializing mJpegHeap.");
2317 mJpegHeap =
2318 new AshmemPool(mJpegMaxSize,
2319 kJpegBufferCount,
2320 0, // we do not know how big the picture will be
2321 "jpeg");
2322
2323 if (!mJpegHeap->initialized()) {
2324 mJpegHeap.clear();
2325 mRawHeap.clear();
2326 LOGE("initRaw X failed: error initializing mJpegHeap.");
2327 return false;
2328 }
2329
2330 // Thumbnails
2331
2332 mThumbnailHeap =
2333 new PmemPool("/dev/pmem_adsp",
Dinesh Gargeecf1a62010-04-19 16:31:30 -07002334 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002335 mCameraControlFd,
2336 MSM_PMEM_THUMBNAIL,
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08002337 thumbnailBufferSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002338 1,
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08002339 thumbnailBufferSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002340 "thumbnail");
2341
2342 if (!mThumbnailHeap->initialized()) {
2343 mThumbnailHeap.clear();
2344 mJpegHeap.clear();
2345 mRawHeap.clear();
2346 LOGE("initRaw X failed: error initializing mThumbnailHeap.");
2347 return false;
2348 }
2349 }
2350
2351 LOGV("initRaw X");
2352 return true;
2353}
2354
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002355
2356void QualcommCameraHardware::deinitRawSnapshot()
2357{
2358 LOGV("deinitRawSnapshot E");
2359 mRawSnapShotPmemHeap.clear();
2360 mRawSnapshotAshmemHeap.clear();
2361 LOGV("deinitRawSnapshot X");
2362}
2363
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002364void QualcommCameraHardware::deinitRaw()
2365{
2366 LOGV("deinitRaw E");
2367
2368 mThumbnailHeap.clear();
2369 mJpegHeap.clear();
2370 mRawHeap.clear();
2371 mDisplayHeap.clear();
2372
2373 LOGV("deinitRaw X");
2374}
2375
2376void QualcommCameraHardware::release()
2377{
2378 LOGD("release E");
2379 Mutex::Autolock l(&mLock);
2380
2381#if DLOPEN_LIBMMCAMERA
2382 if (libmmcamera == NULL) {
2383 LOGE("ERROR: multiple release!");
2384 return;
2385 }
2386#else
2387#warning "Cannot detect multiple release when not dlopen()ing libqcamera!"
2388#endif
2389
2390 int cnt, rc;
2391 struct msm_ctrl_cmd ctrlCmd;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002392 if (mCameraRunning) {
2393 if(mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME)) {
2394 mRecordFrameLock.lock();
2395 mReleasedRecordingFrame = true;
2396 mRecordWait.signal();
2397 mRecordFrameLock.unlock();
2398 }
2399 stopPreviewInternal();
2400 }
2401
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002402 if( mCurrentTarget == TARGET_MSM7630 ) {
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002403 mPostViewHeap.clear();
2404 mPostViewHeap = NULL;
2405 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002406 LINK_jpeg_encoder_join();
2407 deinitRaw();
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002408 deinitRawSnapshot();
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002409 {
2410 Mutex::Autolock l(&mCamframeTimeoutLock);
2411 if(!camframe_timeout_flag) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002412
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002413 ctrlCmd.timeout_ms = 5000;
2414 ctrlCmd.length = 0;
2415 ctrlCmd.type = (uint16_t)CAMERA_EXIT;
2416 ctrlCmd.resp_fd = mCameraControlFd; // FIXME: this will be put in by the kernel
2417 if (ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0)
2418 LOGE("ioctl CAMERA_EXIT fd %d error %s",
2419 mCameraControlFd, strerror(errno));
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002420
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002421 }
2422 }
Kiran Kumar H N7ac84e32010-02-01 10:58:47 -08002423 LINK_release_cam_conf_thread();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002424 close(mCameraControlFd);
2425 mCameraControlFd = -1;
Mohan Kandra284966d2010-01-05 13:39:15 -08002426 if(fb_fd >= 0) {
2427 close(fb_fd);
2428 fb_fd = -1;
2429 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002430#if DLOPEN_LIBMMCAMERA
2431 if (libmmcamera) {
2432 ::dlclose(libmmcamera);
2433 LOGV("dlclose(libqcamera)");
2434 libmmcamera = NULL;
2435 }
2436#endif
2437
2438 Mutex::Autolock lock(&singleton_lock);
2439 singleton_releasing = true;
2440
2441 LOGD("release X");
2442}
2443
2444QualcommCameraHardware::~QualcommCameraHardware()
2445{
2446 LOGD("~QualcommCameraHardware E");
2447 Mutex::Autolock lock(&singleton_lock);
Apurva Rajguruc73c1722010-04-15 17:39:11 -07002448
2449 if( mCurrentTarget == TARGET_MSM7630 || mCurrentTarget == TARGET_QSD8250 ) {
2450 delete [] recordframes;
2451 recordframes = NULL;
2452 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002453 singleton.clear();
2454 singleton_releasing = false;
2455 singleton_wait.signal();
2456 LOGD("~QualcommCameraHardware X");
2457}
2458
2459sp<IMemoryHeap> QualcommCameraHardware::getRawHeap() const
2460{
2461 LOGV("getRawHeap");
2462 return mDisplayHeap != NULL ? mDisplayHeap->mHeap : NULL;
2463}
2464
2465sp<IMemoryHeap> QualcommCameraHardware::getPreviewHeap() const
2466{
2467 LOGV("getPreviewHeap");
Mohan Kandrad9efed92010-01-15 19:08:39 -08002468 return mPreviewHeap != NULL ? mPreviewHeap->mHeap : NULL;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002469}
2470
2471status_t QualcommCameraHardware::startPreviewInternal()
2472{
Sravankb4f5f1c2010-01-21 11:06:17 +05302473 LOGV("in startPreviewInternal : E");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002474 if(mCameraRunning) {
2475 LOGV("startPreview X: preview already running.");
2476 return NO_ERROR;
2477 }
2478
2479 if (!mPreviewInitialized) {
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002480 mLastQueuedFrame = NULL;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002481 mPreviewInitialized = initPreview();
2482 if (!mPreviewInitialized) {
2483 LOGE("startPreview X initPreview failed. Not starting preview.");
2484 return UNKNOWN_ERROR;
2485 }
2486 }
2487
Srinivasan Kannan74712c92010-04-07 13:36:48 -07002488 {
2489 Mutex::Autolock cameraRunningLock(&mCameraRunningLock);
2490 if(( mCurrentTarget != TARGET_MSM7630 ) &&
2491 (mCurrentTarget != TARGET_QSD8250))
2492 mCameraRunning = native_start_preview(mCameraControlFd);
2493 else
2494 mCameraRunning = native_start_video(mCameraControlFd);
2495 }
Sravankb4f5f1c2010-01-21 11:06:17 +05302496
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002497 if(!mCameraRunning) {
2498 deinitPreview();
2499 mPreviewInitialized = false;
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08002500 mOverlay = NULL;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002501 LOGE("startPreview X: native_start_preview failed!");
2502 return UNKNOWN_ERROR;
2503 }
2504
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08002505 //Reset the Gps Information
2506 exif_table_numEntries = 0;
Mohan Kandra284966d2010-01-05 13:39:15 -08002507
2508 if(native_get_maxzoom(mCameraControlFd, (void *)&mMaxZoom) == true){
Brian Steuerb62adbd2010-02-02 14:47:08 -08002509 LOGD("Maximum zoom value is %d", mMaxZoom);
Mohan Kandra284966d2010-01-05 13:39:15 -08002510 mParameters.set("zoom-supported", "true");
2511 } else {
2512 LOGE("Failed to get maximum zoom value...setting max zoom to zero");
2513 mParameters.set("zoom-supported", "false");
2514 mMaxZoom = 0;
2515 }
2516 mParameters.set("max-zoom",mMaxZoom);
2517
Sravankb4f5f1c2010-01-21 11:06:17 +05302518 LOGV("startPreviewInternal X");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002519 return NO_ERROR;
2520}
2521
2522status_t QualcommCameraHardware::startPreview()
2523{
2524 LOGV("startPreview E");
2525 Mutex::Autolock l(&mLock);
2526 return startPreviewInternal();
2527}
2528
2529void QualcommCameraHardware::stopPreviewInternal()
2530{
2531 LOGV("stopPreviewInternal E: %d", mCameraRunning);
2532 if (mCameraRunning) {
2533 // Cancel auto focus.
2534 {
2535 if (mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS)) {
2536 cancelAutoFocusInternal();
2537 }
2538 }
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002539
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002540 Mutex::Autolock l(&mCamframeTimeoutLock);
Srinivasan Kannan74712c92010-04-07 13:36:48 -07002541 {
2542 Mutex::Autolock cameraRunningLock(&mCameraRunningLock);
2543 if(!camframe_timeout_flag) {
2544 if (( mCurrentTarget != TARGET_MSM7630 ) &&
2545 (mCurrentTarget != TARGET_QSD8250))
2546 mCameraRunning = !native_stop_preview(mCameraControlFd);
2547 else
2548 mCameraRunning = !native_stop_video(mCameraControlFd);
2549 } else {
2550 /* This means that the camframetimeout was issued.
2551 * But we did not issue native_stop_preview(), so we
2552 * need to update mCameraRunning to indicate that
2553 * Camera is no longer running. */
2554 mCameraRunning = 0;
2555 }
2556 }
Sravankb4f5f1c2010-01-21 11:06:17 +05302557
Kiran Kumar H Nac2f4952009-12-17 01:16:53 -08002558 if (!mCameraRunning && mPreviewInitialized) {
2559 deinitPreview();
Mohan Kandraf1ebf982010-02-02 15:25:43 -08002560 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250)) {
Mohan Kandra156d0ac2010-01-25 16:59:17 -08002561 mVideoThreadWaitLock.lock();
2562 LOGV("in stopPreviewInternal: making mVideoThreadExit 1");
2563 mVideoThreadExit = 1;
2564 mVideoThreadWaitLock.unlock();
2565 // 720p : signal the video thread , and check in video thread if stop is called, if so exit video thread.
2566 pthread_mutex_lock(&(g_busy_frame_queue.mut));
2567 pthread_cond_signal(&(g_busy_frame_queue.wait));
2568 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
Mohan Kandra1ade9a82010-03-02 10:11:26 -08002569 /* Flush the Busy Q */
2570 cam_frame_flush_video();
2571 /* Flush the Free Q */
2572 LINK_cam_frame_flush_free_video();
Mohan Kandra156d0ac2010-01-25 16:59:17 -08002573 }
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002574 mPreviewInitialized = false;
2575 }
Kiran Kumar H Nac2f4952009-12-17 01:16:53 -08002576 else LOGE("stopPreviewInternal: failed to stop preview");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002577 }
2578 LOGV("stopPreviewInternal X: %d", mCameraRunning);
2579}
2580
2581void QualcommCameraHardware::stopPreview()
2582{
2583 LOGV("stopPreview: E");
2584 Mutex::Autolock l(&mLock);
2585 {
2586 if (mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME))
2587 return;
2588 }
2589 stopPreviewInternal();
2590 LOGV("stopPreview: X");
2591}
2592
2593void QualcommCameraHardware::runAutoFocus()
2594{
2595 bool status = true;
2596 void *libhandle = NULL;
Srinivasan Kannan71229622009-12-04 12:05:58 -08002597 isp3a_af_mode_t afMode;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002598
2599 mAutoFocusThreadLock.lock();
2600 // Skip autofocus if focus mode is infinity.
Srinivasan Kannan74712c92010-04-07 13:36:48 -07002601 if ((mParameters.get(CameraParameters::KEY_FOCUS_MODE) == 0)
2602 || (strcmp(mParameters.get(CameraParameters::KEY_FOCUS_MODE),
2603 CameraParameters::FOCUS_MODE_INFINITY) == 0)) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002604 goto done;
2605 }
2606
2607 mAutoFocusFd = open(MSM_CAMERA_CONTROL, O_RDWR);
2608 if (mAutoFocusFd < 0) {
2609 LOGE("autofocus: cannot open %s: %s",
2610 MSM_CAMERA_CONTROL,
2611 strerror(errno));
2612 mAutoFocusThreadRunning = false;
2613 mAutoFocusThreadLock.unlock();
2614 return;
2615 }
2616
2617#if DLOPEN_LIBMMCAMERA
2618 // We need to maintain a reference to libqcamera.so for the duration of the
2619 // AF thread, because we do not know when it will exit relative to the
2620 // lifetime of this object. We do not want to dlclose() libqcamera while
2621 // LINK_cam_frame is still running.
2622 libhandle = ::dlopen("liboemcamera.so", RTLD_NOW);
2623 LOGV("AF: loading libqcamera at %p", libhandle);
2624 if (!libhandle) {
2625 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
2626 close(mAutoFocusFd);
2627 mAutoFocusFd = -1;
2628 mAutoFocusThreadRunning = false;
2629 mAutoFocusThreadLock.unlock();
2630 return;
2631 }
2632#endif
2633
Srinivasan Kannan71229622009-12-04 12:05:58 -08002634 afMode = (isp3a_af_mode_t)attr_lookup(focus_modes,
2635 sizeof(focus_modes) / sizeof(str_map),
2636 mParameters.get(CameraParameters::KEY_FOCUS_MODE));
2637
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002638 /* This will block until either AF completes or is cancelled. */
Srinivasan Kannan71229622009-12-04 12:05:58 -08002639 LOGV("af start (fd %d mode %d)", mAutoFocusFd, afMode);
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08002640 status_t err;
2641 err = mAfLock.tryLock();
2642 if(err == NO_ERROR) {
Srinivasan Kannan74712c92010-04-07 13:36:48 -07002643 {
2644 Mutex::Autolock cameraRunningLock(&mCameraRunningLock);
2645 if(mCameraRunning){
2646 LOGV("Start AF");
2647 status = native_set_afmode(mAutoFocusFd, afMode);
2648 }else{
2649 LOGV("As Camera preview is not running, AF not issued");
2650 status = false;
2651 }
2652 }
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08002653 mAfLock.unlock();
2654 }
2655 else{
2656 //AF Cancel would have acquired the lock,
2657 //so, no need to perform any AF
Srinivasan Kannan99e82422010-02-28 15:32:16 -08002658 LOGV("As Cancel auto focus is in progress, auto focus request "
2659 "is ignored");
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08002660 status = FALSE;
2661 }
2662
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002663 LOGV("af done: %d", (int)status);
2664 close(mAutoFocusFd);
2665 mAutoFocusFd = -1;
2666
2667done:
2668 mAutoFocusThreadRunning = false;
2669 mAutoFocusThreadLock.unlock();
2670
2671 mCallbackLock.lock();
2672 bool autoFocusEnabled = mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS);
2673 notify_callback cb = mNotifyCallback;
2674 void *data = mCallbackCookie;
2675 mCallbackLock.unlock();
2676 if (autoFocusEnabled)
2677 cb(CAMERA_MSG_FOCUS, status, 0, data);
2678
2679#if DLOPEN_LIBMMCAMERA
2680 if (libhandle) {
2681 ::dlclose(libhandle);
2682 LOGV("AF: dlclose(libqcamera)");
2683 }
2684#endif
2685}
2686
2687status_t QualcommCameraHardware::cancelAutoFocusInternal()
2688{
2689 LOGV("cancelAutoFocusInternal E");
2690
Srinivasan Kannan71229622009-12-04 12:05:58 -08002691 if(!sensorType->hasAutoFocusSupport){
2692 LOGV("cancelAutoFocusInternal X");
2693 return NO_ERROR;
2694 }
2695
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002696#if 0
2697 if (mAutoFocusFd < 0) {
2698 LOGV("cancelAutoFocusInternal X: not in progress");
2699 return NO_ERROR;
2700 }
2701#endif
2702
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08002703 status_t rc = NO_ERROR;
2704 status_t err;
2705 err = mAfLock.tryLock();
2706 if(err == NO_ERROR) {
2707 //Got Lock, means either AF hasn't started or
2708 // AF is done. So no need to cancel it, just change the state
Srinivasan Kannan99e82422010-02-28 15:32:16 -08002709 LOGV("As Auto Focus is not in progress, Cancel Auto Focus "
2710 "is ignored");
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08002711 mAfLock.unlock();
2712 }
2713 else {
2714 //AF is in Progess, So cancel it
2715 LOGV("Lock busy...cancel AF");
2716 rc = native_cancel_afmode(mCameraControlFd, mAutoFocusFd) ?
2717 NO_ERROR :
2718 UNKNOWN_ERROR;
2719 }
2720
2721
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002722
2723 LOGV("cancelAutoFocusInternal X: %d", rc);
2724 return rc;
2725}
2726
2727void *auto_focus_thread(void *user)
2728{
2729 LOGV("auto_focus_thread E");
2730 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
2731 if (obj != 0) {
2732 obj->runAutoFocus();
2733 }
2734 else LOGW("not starting autofocus: the object went away!");
2735 LOGV("auto_focus_thread X");
2736 return NULL;
2737}
2738
2739status_t QualcommCameraHardware::autoFocus()
2740{
2741 LOGV("autoFocus E");
2742 Mutex::Autolock l(&mLock);
2743
Srinivasan Kannan71229622009-12-04 12:05:58 -08002744 if(!sensorType->hasAutoFocusSupport){
Srinivasan Kannandf085222009-12-09 18:31:00 -08002745 bool status = false;
2746 mCallbackLock.lock();
2747 bool autoFocusEnabled = mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS);
2748 notify_callback cb = mNotifyCallback;
2749 void *data = mCallbackCookie;
2750 mCallbackLock.unlock();
2751 if (autoFocusEnabled)
2752 cb(CAMERA_MSG_FOCUS, status, 0, data);
Srinivasan Kannan71229622009-12-04 12:05:58 -08002753 LOGV("autoFocus X");
2754 return NO_ERROR;
2755 }
2756
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002757 if (mCameraControlFd < 0) {
2758 LOGE("not starting autofocus: main control fd %d", mCameraControlFd);
2759 return UNKNOWN_ERROR;
2760 }
2761
2762 {
2763 mAutoFocusThreadLock.lock();
2764 if (!mAutoFocusThreadRunning) {
Srinivasan Kannan572e25c2010-02-01 16:04:37 -08002765 if (native_prepare_snapshot(mCameraControlFd) == FALSE) {
2766 LOGE("native_prepare_snapshot failed!\n");
2767 mAutoFocusThreadLock.unlock();
2768 return UNKNOWN_ERROR;
2769 }
2770
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002771 // Create a detached thread here so that we don't have to wait
2772 // for it when we cancel AF.
2773 pthread_t thr;
2774 pthread_attr_t attr;
2775 pthread_attr_init(&attr);
2776 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2777 mAutoFocusThreadRunning =
2778 !pthread_create(&thr, &attr,
2779 auto_focus_thread, NULL);
2780 if (!mAutoFocusThreadRunning) {
2781 LOGE("failed to start autofocus thread");
2782 mAutoFocusThreadLock.unlock();
2783 return UNKNOWN_ERROR;
2784 }
2785 }
2786 mAutoFocusThreadLock.unlock();
2787 }
2788
2789 LOGV("autoFocus X");
2790 return NO_ERROR;
2791}
2792
2793status_t QualcommCameraHardware::cancelAutoFocus()
2794{
2795 LOGV("cancelAutoFocus E");
2796 Mutex::Autolock l(&mLock);
2797
2798 int rc = NO_ERROR;
2799 if (mCameraRunning && mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS)) {
2800 rc = cancelAutoFocusInternal();
2801 }
2802
2803 LOGV("cancelAutoFocus X");
2804 return rc;
2805}
2806
2807void QualcommCameraHardware::runSnapshotThread(void *data)
2808{
2809 LOGV("runSnapshotThread E");
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002810 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
2811 if (native_start_snapshot(mCameraControlFd))
2812 receiveRawPicture();
2813 else
2814 LOGE("main: native_start_snapshot failed!");
2815 } else if(mSnapshotFormat == PICTURE_FORMAT_RAW){
2816 if(native_start_raw_snapshot(mCameraControlFd)){
2817 receiveRawSnapshot();
2818 } else {
2819 LOGE("main: native_start_raw_snapshot failed!");
2820 }
2821 }
2822
2823 mSnapshotFormat = 0;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002824
2825 mSnapshotThreadWaitLock.lock();
2826 mSnapshotThreadRunning = false;
2827 mSnapshotThreadWait.signal();
2828 mSnapshotThreadWaitLock.unlock();
2829
2830 LOGV("runSnapshotThread X");
2831}
2832
2833void *snapshot_thread(void *user)
2834{
2835 LOGD("snapshot_thread E");
2836 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
2837 if (obj != 0) {
2838 obj->runSnapshotThread(user);
2839 }
2840 else LOGW("not starting snapshot thread: the object went away!");
2841 LOGD("snapshot_thread X");
2842 return NULL;
2843}
2844
2845status_t QualcommCameraHardware::takePicture()
2846{
2847 LOGV("takePicture(%d)", mMsgEnabled);
2848 Mutex::Autolock l(&mLock);
2849
2850 // Wait for old snapshot thread to complete.
2851 mSnapshotThreadWaitLock.lock();
2852 while (mSnapshotThreadRunning) {
2853 LOGV("takePicture: waiting for old snapshot thread to complete.");
2854 mSnapshotThreadWait.wait(mSnapshotThreadWaitLock);
2855 LOGV("takePicture: old snapshot thread completed.");
2856 }
2857
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002858 if( mCurrentTarget == TARGET_MSM7630 ) {
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002859 /* Store the last frame queued for preview. This
2860 * shall be used as postview */
2861 storePreviewFrameForPostview();
2862 }
2863
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002864 //mSnapshotFormat is protected by mSnapshotThreadWaitLock
2865 if(mParameters.getPictureFormat() != 0 &&
2866 !strcmp(mParameters.getPictureFormat(),
2867 CameraParameters::PIXEL_FORMAT_RAW))
2868 mSnapshotFormat = PICTURE_FORMAT_RAW;
2869 else
2870 mSnapshotFormat = PICTURE_FORMAT_JPEG;
2871
2872 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
2873 if(!native_prepare_snapshot(mCameraControlFd)) {
2874 mSnapshotThreadWaitLock.unlock();
2875 return UNKNOWN_ERROR;
2876 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002877 }
2878
2879 stopPreviewInternal();
2880
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002881 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
2882 if (!initRaw(mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE))) {
2883 LOGE("initRaw failed. Not taking picture.");
2884 mSnapshotThreadWaitLock.unlock();
2885 return UNKNOWN_ERROR;
2886 }
2887 } else if(mSnapshotFormat == PICTURE_FORMAT_RAW ){
2888 if(!initRawSnapshot()){
2889 LOGE("initRawSnapshot failed. Not taking picture.");
2890 mSnapshotThreadWaitLock.unlock();
2891 return UNKNOWN_ERROR;
2892 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002893 }
2894
2895 mShutterLock.lock();
2896 mShutterPending = true;
2897 mShutterLock.unlock();
2898
2899 pthread_attr_t attr;
2900 pthread_attr_init(&attr);
2901 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2902 mSnapshotThreadRunning = !pthread_create(&mSnapshotThread,
2903 &attr,
2904 snapshot_thread,
2905 NULL);
2906 mSnapshotThreadWaitLock.unlock();
2907
2908 LOGV("takePicture: X");
2909 return mSnapshotThreadRunning ? NO_ERROR : UNKNOWN_ERROR;
2910}
2911
2912status_t QualcommCameraHardware::cancelPicture()
2913{
2914 status_t rc;
2915 LOGV("cancelPicture: E");
2916 rc = native_stop_snapshot(mCameraControlFd) ? NO_ERROR : UNKNOWN_ERROR;
2917 LOGV("cancelPicture: X: %d", rc);
2918 return rc;
2919}
2920
2921status_t QualcommCameraHardware::setParameters(const CameraParameters& params)
2922{
2923 LOGV("setParameters: E params = %p", &params);
2924
2925 Mutex::Autolock l(&mLock);
2926 status_t rc, final_rc = NO_ERROR;
2927
2928 if ((rc = setPreviewSize(params))) final_rc = rc;
2929 if ((rc = setPictureSize(params))) final_rc = rc;
2930 if ((rc = setJpegQuality(params))) final_rc = rc;
2931 if ((rc = setAntibanding(params))) final_rc = rc;
Apurva Rajguru55562b02009-12-03 12:25:35 -08002932 if ((rc = setAutoExposure(params))) final_rc = rc;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002933 if ((rc = setWhiteBalance(params))) final_rc = rc;
Vamshidhar Kondrae7b9b5a2010-02-25 15:40:37 +05302934 if ((rc = setEffect(params))) final_rc = rc;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002935 if ((rc = setFlash(params))) final_rc = rc;
2936 if ((rc = setGpsLocation(params))) final_rc = rc;
2937 if ((rc = setRotation(params))) final_rc = rc;
2938 if ((rc = setZoom(params))) final_rc = rc;
2939 if ((rc = setFocusMode(params))) final_rc = rc;
2940 if ((rc = setOrientation(params))) final_rc = rc;
Nishant Panditc8c1ee72009-12-03 16:24:02 +05302941 if ((rc = setBrightness(params))) final_rc = rc;
2942 if ((rc = setLensshadeValue(params))) final_rc = rc;
2943 if ((rc = setISOValue(params))) final_rc = rc;
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002944 if ((rc = setPictureFormat(params))) final_rc = rc;
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08002945 if ((rc = setSharpness(params))) final_rc = rc;
2946 if ((rc = setContrast(params))) final_rc = rc;
2947 if ((rc = setSaturation(params))) final_rc = rc;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002948
2949 LOGV("setParameters: X");
2950 return final_rc;
2951}
2952
2953CameraParameters QualcommCameraHardware::getParameters() const
2954{
2955 LOGV("getParameters: EX");
2956 return mParameters;
2957}
2958
2959status_t QualcommCameraHardware::sendCommand(int32_t command, int32_t arg1,
2960 int32_t arg2)
2961{
2962 LOGV("sendCommand: EX");
2963 return BAD_VALUE;
2964}
2965
2966extern "C" sp<CameraHardwareInterface> openCameraHardware()
2967{
2968 LOGV("openCameraHardware: call createInstance");
2969 return QualcommCameraHardware::createInstance();
2970}
2971
2972wp<QualcommCameraHardware> QualcommCameraHardware::singleton;
2973
2974// If the hardware already exists, return a strong pointer to the current
2975// object. If not, create a new hardware object, put it in the singleton,
2976// and return it.
2977sp<CameraHardwareInterface> QualcommCameraHardware::createInstance()
2978{
2979 LOGD("createInstance: E");
2980
2981 Mutex::Autolock lock(&singleton_lock);
2982
2983 // Wait until the previous release is done.
2984 while (singleton_releasing) {
2985 LOGD("Wait for previous release.");
2986 singleton_wait.wait(singleton_lock);
2987 }
2988
2989 if (singleton != 0) {
2990 sp<CameraHardwareInterface> hardware = singleton.promote();
2991 if (hardware != 0) {
2992 LOGD("createInstance: X return existing hardware=%p", &(*hardware));
2993 return hardware;
2994 }
2995 }
2996
2997 {
2998 struct stat st;
2999 int rc = stat("/dev/oncrpc", &st);
3000 if (rc < 0) {
3001 LOGD("createInstance: X failed to create hardware: %s", strerror(errno));
3002 return NULL;
3003 }
3004 }
3005
3006 QualcommCameraHardware *cam = new QualcommCameraHardware();
3007 sp<QualcommCameraHardware> hardware(cam);
3008 singleton = hardware;
3009
3010 if (!cam->startCamera()) {
3011 LOGE("%s: startCamera failed!", __FUNCTION__);
3012 return NULL;
3013 }
3014
3015 cam->initDefaultParameters();
3016 LOGD("createInstance: X created hardware=%p", &(*hardware));
3017 return hardware;
3018}
3019
3020// For internal use only, hence the strong pointer to the derived type.
3021sp<QualcommCameraHardware> QualcommCameraHardware::getInstance()
3022{
3023 sp<CameraHardwareInterface> hardware = singleton.promote();
3024 if (hardware != 0) {
3025 // LOGV("getInstance: X old instance of hardware");
3026 return sp<QualcommCameraHardware>(static_cast<QualcommCameraHardware*>(hardware.get()));
3027 } else {
3028 LOGV("getInstance: X new instance of hardware");
3029 return sp<QualcommCameraHardware>();
3030 }
3031}
Sravankb4f5f1c2010-01-21 11:06:17 +05303032void QualcommCameraHardware::receiveRecordingFrame(struct msm_frame *frame)
3033{
3034 LOGV("receiveRecordingFrame E");
3035 // post busy frame
3036 if (frame)
3037 {
3038 cam_frame_post_video (frame);
3039 }
3040 else LOGE("in receiveRecordingFrame frame is NULL");
3041 LOGV("receiveRecordingFrame X");
3042}
3043
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003044
Mohan Kandrad9efed92010-01-15 19:08:39 -08003045bool QualcommCameraHardware::native_zoom_image(int fd, int srcOffset, int dstOffSet, common_crop_t *crop)
Mohan Kandra284966d2010-01-05 13:39:15 -08003046{
3047 int result = 0;
3048 struct mdp_blit_req *e;
3049 struct timeval td1, td2;
3050
Mohan Kandra284966d2010-01-05 13:39:15 -08003051 /* Initialize yuv structure */
3052 zoomImage.list.count = 1;
3053
3054 e = &zoomImage.list.req[0];
3055
3056 e->src.width = previewWidth;
3057 e->src.height = previewHeight;
3058 e->src.format = MDP_Y_CBCR_H2V2;
Mohan Kandrad9efed92010-01-15 19:08:39 -08003059 e->src.offset = srcOffset;
3060 e->src.memory_id = fd;
Mohan Kandra284966d2010-01-05 13:39:15 -08003061
3062 e->dst.width = previewWidth;
3063 e->dst.height = previewHeight;
3064 e->dst.format = MDP_Y_CBCR_H2V2;
Mohan Kandrad9efed92010-01-15 19:08:39 -08003065 e->dst.offset = dstOffSet;
3066 e->dst.memory_id = fd;
Mohan Kandra284966d2010-01-05 13:39:15 -08003067
3068 e->transp_mask = 0xffffffff;
3069 e->flags = 0;
3070 e->alpha = 0xff;
3071 if (crop->in2_w != 0 || crop->in2_h != 0) {
3072 e->src_rect.x = (crop->out2_w - crop->in2_w + 1) / 2 - 1;
3073 e->src_rect.y = (crop->out2_h - crop->in2_h + 1) / 2 - 1;
3074 e->src_rect.w = crop->in2_w;
3075 e->src_rect.h = crop->in2_h;
3076 } else {
3077 e->src_rect.x = 0;
3078 e->src_rect.y = 0;
3079 e->src_rect.w = previewWidth;
3080 e->src_rect.h = previewHeight;
3081 }
Mohan Kandrad9efed92010-01-15 19:08:39 -08003082 //LOGV(" native_zoom : SRC_RECT : x,y = %d,%d \t w,h = %d, %d",
3083 // e->src_rect.x, e->src_rect.y, e->src_rect.w, e->src_rect.h);
Mohan Kandra284966d2010-01-05 13:39:15 -08003084
3085 e->dst_rect.x = 0;
3086 e->dst_rect.y = 0;
3087 e->dst_rect.w = previewWidth;
3088 e->dst_rect.h = previewHeight;
3089
3090 result = ioctl(fb_fd, MSMFB_BLIT, &zoomImage.list);
3091 if (result < 0) {
3092 LOGE("MSM_FBIOBLT failed! line=%d\n", __LINE__);
3093 return FALSE;
3094 }
3095 return TRUE;
3096}
3097
Mohan Kandrabad0eaa2010-02-04 15:11:54 -08003098void QualcommCameraHardware::debugShowPreviewFPS() const
Mohan Kandra740cfce2010-01-07 12:58:24 -08003099{
3100 static int mFrameCount;
3101 static int mLastFrameCount = 0;
3102 static nsecs_t mLastFpsTime = 0;
3103 static float mFps = 0;
3104 mFrameCount++;
3105 nsecs_t now = systemTime();
3106 nsecs_t diff = now - mLastFpsTime;
3107 if (diff > ms2ns(250)) {
3108 mFps = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
Mohan Kandrabad0eaa2010-02-04 15:11:54 -08003109 LOGI("Preview Frames Per Second: %.4f", mFps);
Mohan Kandra740cfce2010-01-07 12:58:24 -08003110 mLastFpsTime = now;
3111 mLastFrameCount = mFrameCount;
3112 }
3113}
3114
Mohan Kandrabad0eaa2010-02-04 15:11:54 -08003115void QualcommCameraHardware::debugShowVideoFPS() const
3116{
3117 static int mFrameCount;
3118 static int mLastFrameCount = 0;
3119 static nsecs_t mLastFpsTime = 0;
3120 static float mFps = 0;
3121 mFrameCount++;
3122 nsecs_t now = systemTime();
3123 nsecs_t diff = now - mLastFpsTime;
3124 if (diff > ms2ns(250)) {
3125 mFps = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
3126 LOGI("Video Frames Per Second: %.4f", mFps);
3127 mLastFpsTime = now;
3128 mLastFrameCount = mFrameCount;
3129 }
3130}
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003131void QualcommCameraHardware::receivePreviewFrame(struct msm_frame *frame)
3132{
3133// LOGV("receivePreviewFrame E");
3134
3135 if (!mCameraRunning) {
3136 LOGE("ignoring preview callback--camera has been stopped");
3137 return;
3138 }
3139
Mohan Kandra740cfce2010-01-07 12:58:24 -08003140 if (UNLIKELY(mDebugFps)) {
Mohan Kandrabad0eaa2010-02-04 15:11:54 -08003141 debugShowPreviewFPS();
Mohan Kandra740cfce2010-01-07 12:58:24 -08003142 }
3143
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003144 mCallbackLock.lock();
3145 int msgEnabled = mMsgEnabled;
3146 data_callback pcb = mDataCallback;
3147 void *pdata = mCallbackCookie;
3148 data_callback_timestamp rcb = mDataCallbackTimestamp;
3149 void *rdata = mCallbackCookie;
3150 mCallbackLock.unlock();
3151
3152 // Find the offset within the heap of the current buffer.
Mohan Kandra284966d2010-01-05 13:39:15 -08003153 ssize_t offset_addr =
Mohan Kandrad9efed92010-01-15 19:08:39 -08003154 (ssize_t)frame->buffer - (ssize_t)mPreviewHeap->mHeap->base();
3155 ssize_t offset = offset_addr / mPreviewHeap->mAlignedBufferSize;
Mohan Kandra284966d2010-01-05 13:39:15 -08003156
3157 common_crop_t *crop = (common_crop_t *) (frame->cropinfo);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003158
3159 mInPreviewCallback = true;
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003160 if(mUseOverlay) {
3161 if(mOverlay != NULL) {
3162 mOverlayLock.lock();
Mohan Kandrad9efed92010-01-15 19:08:39 -08003163 mOverlay->setFd(mPreviewHeap->mHeap->getHeapID());
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003164 if (crop->in2_w != 0 || crop->in2_h != 0) {
3165 zoomCropInfo.x = (crop->out2_w - crop->in2_w + 1) / 2 - 1;
3166 zoomCropInfo.y = (crop->out2_h - crop->in2_h + 1) / 2 - 1;
3167 zoomCropInfo.w = crop->in2_w;
3168 zoomCropInfo.h = crop->in2_h;
3169 mOverlay->setCrop(zoomCropInfo.x, zoomCropInfo.y,
3170 zoomCropInfo.w, zoomCropInfo.h);
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08003171 } else {
3172 // Reset zoomCropInfo variables. This will ensure that
3173 // stale values wont be used for postview
3174 zoomCropInfo.w = crop->in2_w;
3175 zoomCropInfo.h = crop->in2_h;
3176 }
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003177 mOverlay->queueBuffer((void *)offset_addr);
3178 mLastQueuedFrame = (void *)frame->buffer;
3179 mOverlayLock.unlock();
3180 }
Mohan Kandra284966d2010-01-05 13:39:15 -08003181 } else {
Mohan Kandrad9efed92010-01-15 19:08:39 -08003182 if (crop->in2_w != 0 || crop->in2_h != 0) {
3183 dstOffset = (dstOffset + 1) % NUM_MORE_BUFS;
3184 offset = kPreviewBufferCount + dstOffset;
3185 ssize_t dstOffset_addr = offset * mPreviewHeap->mAlignedBufferSize;
3186 if( !native_zoom_image(mPreviewHeap->mHeap->getHeapID(),
3187 offset_addr, dstOffset_addr, crop)) {
3188 LOGE(" Error while doing MDP zoom ");
Kiran Kumar H N1ece71c2010-03-30 10:31:21 -07003189 offset = offset_addr / mPreviewHeap->mAlignedBufferSize;
Mohan Kandrad9efed92010-01-15 19:08:39 -08003190 }
3191 }
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08003192 }
Mohan Kandrad9efed92010-01-15 19:08:39 -08003193 if (pcb != NULL && (msgEnabled & CAMERA_MSG_PREVIEW_FRAME))
3194 pcb(CAMERA_MSG_PREVIEW_FRAME, mPreviewHeap->mBuffers[offset],
3195 pdata);
3196
Sravankb4f5f1c2010-01-21 11:06:17 +05303197 // If output is NOT enabled (targets otherthan 7x30 currently..)
Mohan Kandraf1ebf982010-02-02 15:25:43 -08003198 if( (mCurrentTarget != TARGET_MSM7630 ) && (mCurrentTarget != TARGET_QSD8250)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05303199 if(rcb != NULL && (msgEnabled & CAMERA_MSG_VIDEO_FRAME)) {
3200 rcb(systemTime(), CAMERA_MSG_VIDEO_FRAME, mPreviewHeap->mBuffers[offset], rdata);
3201 Mutex::Autolock rLock(&mRecordFrameLock);
3202 if (mReleasedRecordingFrame != true) {
3203 LOGV("block waiting for frame release");
3204 mRecordWait.wait(mRecordFrameLock);
3205 LOGV("frame released, continuing");
3206 }
3207 mReleasedRecordingFrame = false;
3208 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003209 }
3210 mInPreviewCallback = false;
3211
3212// LOGV("receivePreviewFrame X");
3213}
3214
Sravankb4f5f1c2010-01-21 11:06:17 +05303215
3216bool QualcommCameraHardware::initRecord()
3217{
Apurva Rajguruc73c1722010-04-15 17:39:11 -07003218 char *pmem_region;
3219
Sravankb4f5f1c2010-01-21 11:06:17 +05303220 LOGV("initREcord E");
3221
3222 mRecordFrameSize = (mDimension.video_width * mDimension.video_height *3)/2;
Apurva Rajguruc73c1722010-04-15 17:39:11 -07003223
3224 if( mCurrentTarget == TARGET_QSD8250 )
3225 pmem_region = "/dev/pmem_smipool";
3226 else
3227 pmem_region = "/dev/pmem_adsp";
3228
3229 mRecordHeap = new PmemPool(pmem_region,
Sravankb4f5f1c2010-01-21 11:06:17 +05303230 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
3231 mCameraControlFd,
3232 MSM_PMEM_VIDEO,
3233 mRecordFrameSize,
3234 kRecordBufferCount,
3235 mRecordFrameSize,
3236 "record");
Apurva Rajguruc73c1722010-04-15 17:39:11 -07003237
Sravankb4f5f1c2010-01-21 11:06:17 +05303238 if (!mRecordHeap->initialized()) {
3239 mRecordHeap.clear();
3240 LOGE("initRecord X: could not initialize record heap.");
3241 return false;
3242 }
3243 for (int cnt = 0; cnt < kRecordBufferCount; cnt++) {
3244 recordframes[cnt].fd = mRecordHeap->mHeap->getHeapID();
3245 recordframes[cnt].buffer =
3246 (uint32_t)mRecordHeap->mHeap->base() + mRecordHeap->mAlignedBufferSize * cnt;
3247 recordframes[cnt].y_off = 0;
3248 recordframes[cnt].cbcr_off = mDimension.video_width * mDimension.video_height;
3249 recordframes[cnt].path = OUTPUT_TYPE_V;
3250
3251 LOGV ("initRecord : record heap , video buffers buffer=%lu fd=%d y_off=%d cbcr_off=%d \n",
3252 (unsigned long)recordframes[cnt].buffer, recordframes[cnt].fd, recordframes[cnt].y_off,
3253 recordframes[cnt].cbcr_off);
3254 }
3255
3256 // initial setup : buffers 1,2,3 with kernel , 4 with camframe , 5,6,7,8 in free Q
3257 // flush the busy Q
3258 cam_frame_flush_video();
3259
Mohan Kandra156d0ac2010-01-25 16:59:17 -08003260 mVideoThreadWaitLock.lock();
3261 while (mVideoThreadRunning) {
3262 LOGV("initRecord: waiting for old video thread to complete.");
3263 mVideoThreadWait.wait(mVideoThreadWaitLock);
3264 LOGV("initRecord : old video thread completed.");
3265 }
3266 mVideoThreadWaitLock.unlock();
3267
Sravankdf7a9202010-02-08 15:02:51 +05303268 // flush free queue and add 5,6,7,8 buffers.
3269 LINK_cam_frame_flush_free_video();
3270 for(int i=ACTIVE_VIDEO_BUFFERS+1;i <kRecordBufferCount; i++)
3271 LINK_camframe_free_video(&recordframes[i]);
Sravankb4f5f1c2010-01-21 11:06:17 +05303272 LOGV("initREcord X");
3273
3274 return true;
3275}
3276
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003277status_t QualcommCameraHardware::startRecording()
3278{
3279 LOGV("startRecording E");
Sravankb4f5f1c2010-01-21 11:06:17 +05303280 int ret;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003281 Mutex::Autolock l(&mLock);
3282 mReleasedRecordingFrame = false;
Sravankb4f5f1c2010-01-21 11:06:17 +05303283 if( (ret=startPreviewInternal())== NO_ERROR){
Mohan Kandraf1ebf982010-02-02 15:25:43 -08003284 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05303285 LOGV(" in startREcording : calling native_start_recording");
3286 native_start_recording(mCameraControlFd);
3287 recordingState = 1;
Sravank64461e82010-02-25 15:10:09 +05303288 // Remove the left out frames in busy Q and them in free Q.
3289 // this should be done before starting video_thread so that,
3290 // frames in previous recording are flushed out.
3291 LOGV("frames in busy Q = %d", g_busy_frame_queue.num_of_frames);
3292 while((g_busy_frame_queue.num_of_frames) >0){
3293 msm_frame* vframe = cam_frame_get_video ();
3294 LINK_camframe_free_video(vframe);
3295 }
3296 LOGV("frames in busy Q = %d after deQueing", g_busy_frame_queue.num_of_frames);
3297
Sravankdf7a9202010-02-08 15:02:51 +05303298 // Start video thread and wait for busy frames to be encoded, this thread
3299 // should be closed in stopRecording
3300 mVideoThreadWaitLock.lock();
3301 mVideoThreadExit = 0;
3302 pthread_attr_t attr;
3303 pthread_attr_init(&attr);
3304 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
3305 mVideoThreadRunning = pthread_create(&mVideoThread,
3306 &attr,
3307 video_thread,
3308 NULL);
3309 mVideoThreadWaitLock.unlock();
3310 // Remove the left out frames in busy Q and them in free Q.
Sravankb4f5f1c2010-01-21 11:06:17 +05303311 }
3312 }
3313 return ret;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003314}
3315
3316void QualcommCameraHardware::stopRecording()
3317{
3318 LOGV("stopRecording: E");
3319 Mutex::Autolock l(&mLock);
3320 {
3321 mRecordFrameLock.lock();
3322 mReleasedRecordingFrame = true;
3323 mRecordWait.signal();
3324 mRecordFrameLock.unlock();
3325
Sravankdf7a9202010-02-08 15:02:51 +05303326 if(mDataCallback && !(mCurrentTarget == TARGET_QSD8250) &&
3327 (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003328 LOGV("stopRecording: X, preview still in progress");
3329 return;
3330 }
3331 }
Sravankb4f5f1c2010-01-21 11:06:17 +05303332 // If output2 enabled, exit video thread, invoke stop recording ioctl
Mohan Kandraf1ebf982010-02-02 15:25:43 -08003333 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05303334 mVideoThreadWaitLock.lock();
3335 mVideoThreadExit = 1;
3336 mVideoThreadWaitLock.unlock();
3337 native_stop_recording(mCameraControlFd);
Srinivasan Kannanfc3915c2010-03-18 10:54:40 -07003338
3339 pthread_mutex_lock(&(g_busy_frame_queue.mut));
3340 pthread_cond_signal(&(g_busy_frame_queue.wait));
3341 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
Sravankb4f5f1c2010-01-21 11:06:17 +05303342 }
3343 else // for other targets where output2 is not enabled
3344 stopPreviewInternal();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003345
Sravankb4f5f1c2010-01-21 11:06:17 +05303346 recordingState = 0; // recording not started
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003347 LOGV("stopRecording: X");
3348}
3349
3350void QualcommCameraHardware::releaseRecordingFrame(
3351 const sp<IMemory>& mem __attribute__((unused)))
3352{
3353 LOGV("releaseRecordingFrame E");
3354 Mutex::Autolock rLock(&mRecordFrameLock);
3355 mReleasedRecordingFrame = true;
3356 mRecordWait.signal();
Sravankb4f5f1c2010-01-21 11:06:17 +05303357
3358 // Ff 7x30 : add the frame to the free camframe queue
Mohan Kandraf1ebf982010-02-02 15:25:43 -08003359 if( (mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250)) {
Sravankb4f5f1c2010-01-21 11:06:17 +05303360 ssize_t offset;
3361 size_t size;
3362 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
3363 msm_frame* releaseframe = NULL;
3364 LOGV(" in release recording frame : heap base %d offset %d buffer %d ", heap->base(), offset, heap->base() + offset );
3365 int cnt;
3366 for (cnt = 0; cnt < kRecordBufferCount; cnt++) {
3367 if((unsigned int)recordframes[cnt].buffer == (unsigned int)(heap->base()+ offset)){
3368 LOGV("in release recording frame found match , releasing buffer %d", (unsigned int)recordframes[cnt].buffer);
3369 releaseframe = &recordframes[cnt];
3370 break;
3371 }
3372 }
3373 if(cnt < kRecordBufferCount) {
3374 // do this only if frame thread is running
3375 mFrameThreadWaitLock.lock();
3376 if(mFrameThreadRunning )
3377 LINK_camframe_free_video(releaseframe);
3378
3379 mFrameThreadWaitLock.unlock();
3380 } else {
3381 LOGE("in release recordingframe XXXXX error , buffer not found");
3382 for (int i=0; i< kRecordBufferCount; i++) {
3383 LOGE(" recordframes[%d].buffer = %d", i, (unsigned int)recordframes[i].buffer);
3384 }
3385 }
3386 }
3387
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003388 LOGV("releaseRecordingFrame X");
3389}
3390
3391bool QualcommCameraHardware::recordingEnabled()
3392{
3393 return mCameraRunning && mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME);
3394}
3395
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08003396void QualcommCameraHardware::notifyShutter(common_crop_t *crop, bool mPlayShutterSoundOnly)
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003397{
3398 mShutterLock.lock();
3399 image_rect_type size;
3400
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08003401 if(mPlayShutterSoundOnly) {
3402 /* At this point, invoke Notify Callback to play shutter sound only.
3403 * We want to call notify callback again when we have the
3404 * yuv picture ready. This is to reduce blanking at the time
3405 * of displaying postview frame. Using ext2 to indicate whether
3406 * to play shutter sound only or register the postview buffers.
3407 */
3408 mNotifyCallback(CAMERA_MSG_SHUTTER, 0, mPlayShutterSoundOnly,
3409 mCallbackCookie);
3410 mShutterLock.unlock();
3411 return;
3412 }
3413
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003414 if (mShutterPending && mNotifyCallback && (mMsgEnabled & CAMERA_MSG_SHUTTER)) {
3415 LOGV("out2_w=%d, out2_h=%d, in2_w=%d, in2_h=%d",
3416 crop->out2_w, crop->out2_h, crop->in2_w, crop->in2_h);
3417 LOGV("out1_w=%d, out1_h=%d, in1_w=%d, in1_h=%d",
3418 crop->out1_w, crop->out1_h, crop->in1_w, crop->in1_h);
3419
3420 // To workaround a bug in MDP which happens if either
3421 // dimension > 2048, we display the thumbnail instead.
3422 mDisplayHeap = mRawHeap;
3423 if (crop->in1_w == 0 || crop->in1_h == 0) {
3424 // Full size
3425 size.width = mDimension.picture_width;
3426 size.height = mDimension.picture_height;
3427 if (size.width > 2048 || size.height > 2048) {
3428 size.width = mDimension.ui_thumbnail_width;
3429 size.height = mDimension.ui_thumbnail_height;
3430 mDisplayHeap = mThumbnailHeap;
3431 }
3432 } else {
3433 // Cropped
Srinivasan Kannan5701a942010-04-15 16:17:21 -07003434 size.width = (crop->in2_w + jpegPadding) & ~1;
3435 size.height = (crop->in2_h + jpegPadding) & ~1;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003436 if (size.width > 2048 || size.height > 2048) {
Srinivasan Kannan5701a942010-04-15 16:17:21 -07003437 size.width = (crop->in1_w + jpegPadding) & ~1;
3438 size.height = (crop->in1_h + jpegPadding) & ~1;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003439 mDisplayHeap = mThumbnailHeap;
3440 }
3441 }
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08003442 /* Now, invoke Notify Callback to unregister preview buffer
3443 * and register postview buffer with surface flinger. Set ext2
3444 * as 0 to indicate not to play shutter sound.
3445 */
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003446 mNotifyCallback(CAMERA_MSG_SHUTTER, (int32_t)&size, 0,
3447 mCallbackCookie);
3448 mShutterPending = false;
3449 }
3450 mShutterLock.unlock();
3451}
3452
3453static void receive_shutter_callback(common_crop_t *crop)
3454{
3455 LOGV("receive_shutter_callback: E");
3456 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
3457 if (obj != 0) {
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08003458 /* Just play shutter sound at this time */
3459 obj->notifyShutter(crop, TRUE);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003460 }
3461 LOGV("receive_shutter_callback: X");
3462}
3463
3464// Crop the picture in place.
3465static void crop_yuv420(uint32_t width, uint32_t height,
3466 uint32_t cropped_width, uint32_t cropped_height,
3467 uint8_t *image)
3468{
3469 uint32_t i, x, y;
3470 uint8_t* chroma_src, *chroma_dst;
3471
3472 // Calculate the start position of the cropped area.
3473 x = (width - cropped_width) / 2;
3474 y = (height - cropped_height) / 2;
3475 x &= ~1;
3476 y &= ~1;
3477
3478 // Copy luma component.
3479 for(i = 0; i < cropped_height; i++)
3480 memcpy(image + i * cropped_width,
3481 image + width * (y + i) + x,
3482 cropped_width);
3483
3484 chroma_src = image + width * height;
3485 chroma_dst = image + cropped_width * cropped_height;
3486
3487 // Copy chroma components.
3488 cropped_height /= 2;
3489 y /= 2;
3490 for(i = 0; i < cropped_height; i++)
3491 memcpy(chroma_dst + i * cropped_width,
3492 chroma_src + width * (y + i) + x,
3493 cropped_width);
3494}
3495
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08003496
3497void QualcommCameraHardware::receiveRawSnapshot(){
3498 LOGV("receiveRawSnapshot E");
3499
3500 Mutex::Autolock cbLock(&mCallbackLock);
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08003501 /* Issue notifyShutter with mPlayShutterSoundOnly as TRUE */
3502 notifyShutter(&mCrop, TRUE);
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08003503
3504 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
3505
3506 if(native_get_picture(mCameraControlFd, &mCrop) == false) {
3507 LOGE("receiveRawSnapshot X: native_get_picture failed!");
3508 return;
3509 }
Kiran Kumar H Ncb54ba82010-03-09 10:27:38 -08003510 /* Its necessary to issue another notifyShutter here with
3511 * mPlayShutterSoundOnly as FALSE, since that is when the
3512 * preview buffers are unregistered with the surface flinger.
3513 * That is necessary otherwise the preview memory wont be
3514 * deallocated.
3515 */
3516 notifyShutter(&mCrop, FALSE);
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08003517
3518 //Create a Ashmem heap to copy data from PMem heap for application layer
3519 if(mRawSnapshotAshmemHeap != NULL){
3520 LOGV("receiveRawSnapshot: clearing old mRawSnapShotAshmemHeap.");
3521 mRawSnapshotAshmemHeap.clear();
3522 }
3523 mRawSnapshotAshmemHeap = new AshmemPool(
3524 mRawSnapShotPmemHeap->mBufferSize,
3525 mRawSnapShotPmemHeap->mNumBuffers,
3526 mRawSnapShotPmemHeap->mFrameSize,
3527 "raw ashmem snapshot camera"
3528 );
3529
3530 if(!mRawSnapshotAshmemHeap->initialized()){
3531 LOGE("receiveRawSnapshot X: error initializing mRawSnapshotHeap");
3532 deinitRawSnapshot();
3533 return;
3534 }
3535
3536 memcpy(mRawSnapshotAshmemHeap->mHeap->base(),
3537 mRawSnapShotPmemHeap->mHeap->base(),
3538 mRawSnapShotPmemHeap->mHeap->getSize());
Nishant Panditb861be52010-03-02 16:43:49 +05303539 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE))
3540 mDataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mRawSnapshotAshmemHeap->mBuffers[0],
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08003541 mCallbackCookie);
3542
3543 }
3544
3545 //cleanup
3546 deinitRawSnapshot();
3547
3548 LOGV("receiveRawSnapshot X");
3549}
3550
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003551void QualcommCameraHardware::receiveRawPicture()
3552{
3553 LOGV("receiveRawPicture: E");
3554
3555 Mutex::Autolock cbLock(&mCallbackLock);
3556 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_RAW_IMAGE)) {
3557 if(native_get_picture(mCameraControlFd, &mCrop) == false) {
3558 LOGE("getPicture failed!");
3559 return;
3560 }
3561 mCrop.in1_w &= ~1;
3562 mCrop.in1_h &= ~1;
3563 mCrop.in2_w &= ~1;
3564 mCrop.in2_h &= ~1;
3565
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003566
3567 // Crop the image if zoomed.
Srinivasan Kannan5701a942010-04-15 16:17:21 -07003568 if (mCrop.in2_w != 0 && mCrop.in2_h != 0 &&
3569 ((mCrop.in2_w + jpegPadding) < mCrop.out2_w) &&
3570 ((mCrop.in2_h + jpegPadding) < mCrop.out2_h) &&
3571 ((mCrop.in1_w + jpegPadding) < mCrop.out1_w) &&
3572 ((mCrop.in1_h + jpegPadding) < mCrop.out1_h) ) {
3573
3574 // By the time native_get_picture returns, picture is taken. Call
3575 // shutter callback if cam config thread has not done that.
3576 notifyShutter(&mCrop, FALSE);
3577 crop_yuv420(mCrop.out2_w, mCrop.out2_h, (mCrop.in2_w + jpegPadding), (mCrop.in2_h + jpegPadding),
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003578 (uint8_t *)mRawHeap->mHeap->base());
Srinivasan Kannan5701a942010-04-15 16:17:21 -07003579 crop_yuv420(mCrop.out1_w, mCrop.out1_h, (mCrop.in1_w + jpegPadding), (mCrop.in1_h + jpegPadding),
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003580 (uint8_t *)mThumbnailHeap->mHeap->base());
Srinivasan Kannan5701a942010-04-15 16:17:21 -07003581
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003582 // We do not need jpeg encoder to upscale the image. Set the new
3583 // dimension for encoder.
Srinivasan Kannan5701a942010-04-15 16:17:21 -07003584 mDimension.orig_picture_dx = mCrop.in2_w + jpegPadding;
3585 mDimension.orig_picture_dy = mCrop.in2_h + jpegPadding;
3586 mDimension.thumbnail_width = mCrop.in1_w + jpegPadding;
3587 mDimension.thumbnail_height = mCrop.in1_h + jpegPadding;
3588 }else {
3589 memset(&mCrop, 0 ,sizeof(mCrop));
3590 // By the time native_get_picture returns, picture is taken. Call
3591 // shutter callback if cam config thread has not done that.
3592 notifyShutter(&mCrop, FALSE);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003593 }
3594
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003595 if( mUseOverlay && (mOverlay != NULL) ) {
3596 mOverlay->setFd(mPostViewHeap->mHeap->getHeapID());
3597 if( zoomCropInfo.w !=0 && zoomCropInfo.h !=0) {
3598 LOGD(" zoomCropInfo non-zero, setting crop ");
3599 mOverlay->setCrop(zoomCropInfo.x, zoomCropInfo.y,
3600 zoomCropInfo.w, zoomCropInfo.h);
3601 }
3602 LOGD(" Queueing Postview for display ");
3603 mOverlay->queueBuffer((void *)0);
3604 }
Nishant Panditb861be52010-03-02 16:43:49 +05303605 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_RAW_IMAGE))
3606 mDataCallback(CAMERA_MSG_RAW_IMAGE, mDisplayHeap->mBuffers[0],
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003607 mCallbackCookie);
3608 }
3609 else LOGV("Raw-picture callback was canceled--skipping.");
3610
3611 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
3612 mJpegSize = 0;
3613 if (LINK_jpeg_encoder_init()) {
3614 if(native_jpeg_encode()) {
3615 LOGV("receiveRawPicture: X (success)");
3616 return;
3617 }
3618 LOGE("jpeg encoding failed");
3619 }
3620 else LOGE("receiveRawPicture X: jpeg_encoder_init failed.");
3621 }
3622 else LOGV("JPEG callback is NULL, not encoding image.");
3623 deinitRaw();
3624 LOGV("receiveRawPicture: X");
3625}
3626
3627void QualcommCameraHardware::receiveJpegPictureFragment(
3628 uint8_t *buff_ptr, uint32_t buff_size)
3629{
3630 uint32_t remaining = mJpegHeap->mHeap->virtualSize();
3631 remaining -= mJpegSize;
3632 uint8_t *base = (uint8_t *)mJpegHeap->mHeap->base();
3633
3634 LOGV("receiveJpegPictureFragment size %d", buff_size);
3635 if (buff_size > remaining) {
3636 LOGE("receiveJpegPictureFragment: size %d exceeds what "
3637 "remains in JPEG heap (%d), truncating",
3638 buff_size,
3639 remaining);
3640 buff_size = remaining;
3641 }
3642 memcpy(base + mJpegSize, buff_ptr, buff_size);
3643 mJpegSize += buff_size;
3644}
3645
3646void QualcommCameraHardware::receiveJpegPicture(void)
3647{
3648 LOGV("receiveJpegPicture: E image (%d uint8_ts out of %d)",
3649 mJpegSize, mJpegHeap->mBufferSize);
3650 Mutex::Autolock cbLock(&mCallbackLock);
3651
3652 int index = 0, rc;
3653
3654 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
3655 // The reason we do not allocate into mJpegHeap->mBuffers[offset] is
3656 // that the JPEG image's size will probably change from one snapshot
3657 // to the next, so we cannot reuse the MemoryBase object.
3658 sp<MemoryBase> buffer = new
3659 MemoryBase(mJpegHeap->mHeap,
3660 index * mJpegHeap->mBufferSize +
3661 0,
3662 mJpegSize);
3663 mDataCallback(CAMERA_MSG_COMPRESSED_IMAGE, buffer, mCallbackCookie);
3664 buffer = NULL;
3665 }
3666 else LOGV("JPEG callback was cancelled--not delivering image.");
3667
3668 LINK_jpeg_encoder_join();
3669 deinitRaw();
3670
3671 LOGV("receiveJpegPicture: X callback done.");
3672}
3673
3674bool QualcommCameraHardware::previewEnabled()
3675{
3676 return mCameraRunning && mDataCallback && (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME);
3677}
3678
3679status_t QualcommCameraHardware::setPreviewSize(const CameraParameters& params)
3680{
3681 int width, height;
3682 params.getPreviewSize(&width, &height);
3683 LOGV("requested preview size %d x %d", width, height);
3684
3685 // Validate the preview size
Srinivasan Kannan9c14ead2010-02-22 17:15:58 -08003686 for (size_t i = 0; i < previewSizeCount; ++i) {
3687 if (width == supportedPreviewSizes[i].width
3688 && height == supportedPreviewSizes[i].height) {
Sravank64461e82010-02-25 15:10:09 +05303689 // 720p , preview can be 768X432 (currently for 7x30 and 8k
3690 // targets)
3691 if(width == 1280 && height == 720 &&
3692 ((mCurrentTarget == TARGET_MSM7630) || (mCurrentTarget == TARGET_QSD8250))){
3693 LOGD("change preview resolution to 768X432 since recording is in 720p");
3694 mDimension.display_width = preview_sizes[2].width;
3695 mDimension.display_height= preview_sizes[2].height;
3696 }else {
3697 mDimension.display_width = width;
3698 mDimension.display_height= height;
3699 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003700 mParameters.setPreviewSize(width, height);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003701 return NO_ERROR;
3702 }
3703 }
3704 LOGE("Invalid preview size requested: %dx%d", width, height);
3705 return BAD_VALUE;
3706}
3707
3708status_t QualcommCameraHardware::setPictureSize(const CameraParameters& params)
3709{
3710 int width, height;
3711 params.getPictureSize(&width, &height);
3712 LOGV("requested picture size %d x %d", width, height);
3713
3714 // Validate the picture size
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -08003715 for (int i = 0; i < supportedPictureSizesCount; ++i) {
3716 if (width == picture_sizes_ptr[i].width
3717 && height == picture_sizes_ptr[i].height) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003718 mParameters.setPictureSize(width, height);
3719 mDimension.picture_width = width;
3720 mDimension.picture_height = height;
3721 return NO_ERROR;
3722 }
3723 }
Kiran Kumar H Nb49af212010-02-17 15:12:17 -08003724 /* Dimension not among the ones in the list. Check if
3725 * its a valid dimension, if it is, then configure the
3726 * camera accordingly. else reject it.
3727 */
3728 if( isValidDimension(width, height) ) {
3729 mParameters.setPictureSize(width, height);
3730 mDimension.picture_width = width;
3731 mDimension.picture_height = height;
3732 return NO_ERROR;
3733 } else
3734 LOGE("Invalid picture size requested: %dx%d", width, height);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003735 return BAD_VALUE;
3736}
3737
3738status_t QualcommCameraHardware::setJpegQuality(const CameraParameters& params) {
3739 status_t rc = NO_ERROR;
3740 int quality = params.getInt(CameraParameters::KEY_JPEG_QUALITY);
3741 if (quality > 0 && quality <= 100) {
3742 mParameters.set(CameraParameters::KEY_JPEG_QUALITY, quality);
3743 } else {
3744 LOGE("Invalid jpeg quality=%d", quality);
3745 rc = BAD_VALUE;
3746 }
3747
3748 quality = params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY);
3749 if (quality > 0 && quality <= 100) {
3750 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, quality);
3751 } else {
3752 LOGE("Invalid jpeg thumbnail quality=%d", quality);
3753 rc = BAD_VALUE;
3754 }
3755 return rc;
3756}
3757
3758status_t QualcommCameraHardware::setEffect(const CameraParameters& params)
3759{
Apurva Rajguru7360db42010-04-09 16:37:36 -07003760
3761 const char *str_wb = mParameters.get(CameraParameters::KEY_WHITE_BALANCE);
3762 int32_t value_wb = attr_lookup(whitebalance, sizeof(whitebalance) / sizeof(str_map), str_wb);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003763 const char *str = params.get(CameraParameters::KEY_EFFECT);
Apurva Rajguru7360db42010-04-09 16:37:36 -07003764
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003765 if (str != NULL) {
3766 int32_t value = attr_lookup(effects, sizeof(effects) / sizeof(str_map), str);
3767 if (value != NOT_FOUND) {
Mohan Kandra93f1bfb2009-12-15 16:55:33 -08003768 if(!strcmp(sensorType->name, "2mp") && (value != CAMERA_EFFECT_OFF)
3769 &&(value != CAMERA_EFFECT_MONO) && (value != CAMERA_EFFECT_NEGATIVE)
3770 &&(value != CAMERA_EFFECT_SOLARIZE) && (value != CAMERA_EFFECT_SEPIA)) {
3771 LOGE("Special effect parameter is not supported for this sensor");
3772 return NO_ERROR;
3773 }
Apurva Rajguru7360db42010-04-09 16:37:36 -07003774
3775 if(((value == CAMERA_EFFECT_MONO) || (value == CAMERA_EFFECT_NEGATIVE)
3776 || (value == CAMERA_EFFECT_AQUA) || (value == CAMERA_EFFECT_SEPIA))
3777 && (value_wb != CAMERA_WB_AUTO)) {
3778 LOGE("Color Effect value will not be set " \
3779 "when the whitebalance selected is %s", str_wb);
3780 return NO_ERROR;
3781 }
3782 else {
3783 mParameters.set(CameraParameters::KEY_EFFECT, str);
3784 bool ret = native_set_parm(CAMERA_SET_PARM_EFFECT, sizeof(value),
3785 (void *)&value);
3786 return ret ? NO_ERROR : UNKNOWN_ERROR;
3787 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003788 }
3789 }
3790 LOGE("Invalid effect value: %s", (str == NULL) ? "NULL" : str);
3791 return BAD_VALUE;
3792}
3793
Apurva Rajguru55562b02009-12-03 12:25:35 -08003794status_t QualcommCameraHardware::setAutoExposure(const CameraParameters& params)
3795{
Mohan Kandra93f1bfb2009-12-15 16:55:33 -08003796 if(!strcmp(sensorType->name, "2mp")) {
3797 LOGE("Auto Exposure not supported for this sensor");
3798 return NO_ERROR;
3799 }
Apurva Rajguru55562b02009-12-03 12:25:35 -08003800 const char *str = params.get(CameraParameters::KEY_AUTO_EXPOSURE);
3801 if (str != NULL) {
3802 int32_t value = attr_lookup(autoexposure, sizeof(autoexposure) / sizeof(str_map), str);
3803 if (value != NOT_FOUND) {
3804 mParameters.set(CameraParameters::KEY_AUTO_EXPOSURE, str);
3805 bool ret = native_set_parm(CAMERA_SET_PARM_EXPOSURE, sizeof(value),
3806 (void *)&value);
3807 return ret ? NO_ERROR : UNKNOWN_ERROR;
3808 }
3809 }
3810 LOGE("Invalid auto exposure value: %s", (str == NULL) ? "NULL" : str);
3811 return BAD_VALUE;
3812}
3813
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003814status_t QualcommCameraHardware::setSharpness(const CameraParameters& params)
3815{
3816 if(!strcmp(sensorType->name, "2mp")) {
3817 LOGE("Sharpness not supported for this sensor");
3818 return NO_ERROR;
3819 }
3820 int sharpness = params.getInt(CameraParameters::KEY_SHARPNESS);
3821 if((sharpness < CAMERA_MIN_SHARPNESS
3822 || sharpness > CAMERA_MAX_SHARPNESS))
3823 return UNKNOWN_ERROR;
Srinivasan Kannan551fd262010-01-14 17:48:30 -08003824
3825 LOGV("setting sharpness %d", sharpness);
3826 mParameters.set(CameraParameters::KEY_SHARPNESS, sharpness);
3827 bool ret = native_set_parm(CAMERA_SET_PARM_SHARPNESS, sizeof(sharpness),
3828 (void *)&sharpness);
3829 return ret ? NO_ERROR : UNKNOWN_ERROR;
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003830}
3831
3832status_t QualcommCameraHardware::setContrast(const CameraParameters& params)
3833{
3834 if(!strcmp(sensorType->name, "2mp")) {
3835 LOGE("Contrast not supported for this sensor");
3836 return NO_ERROR;
3837 }
3838 int contrast = params.getInt(CameraParameters::KEY_CONTRAST);
3839 if((contrast < CAMERA_MIN_CONTRAST)
3840 || (contrast > CAMERA_MAX_CONTRAST))
3841 return UNKNOWN_ERROR;
Srinivasan Kannan551fd262010-01-14 17:48:30 -08003842
3843 LOGV("setting contrast %d", contrast);
3844 mParameters.set(CameraParameters::KEY_CONTRAST, contrast);
3845 bool ret = native_set_parm(CAMERA_SET_PARM_CONTRAST, sizeof(contrast),
3846 (void *)&contrast);
3847 return ret ? NO_ERROR : UNKNOWN_ERROR;
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003848}
3849
3850status_t QualcommCameraHardware::setSaturation(const CameraParameters& params)
3851{
3852 if(!strcmp(sensorType->name, "2mp")) {
3853 LOGE("Saturation not supported for this sensor");
3854 return NO_ERROR;
3855 }
Srinivasan Kannan551fd262010-01-14 17:48:30 -08003856
Kiran Kumar H Nf87cf862010-01-27 14:34:34 -08003857 const char *str = params.get(CameraParameters::KEY_EFFECT);
3858 int32_t value = attr_lookup(effects, sizeof(effects) / sizeof(str_map), str);
3859
3860 if( (value != CAMERA_EFFECT_MONO) && (value != CAMERA_EFFECT_NEGATIVE)
3861 && (value != CAMERA_EFFECT_AQUA) && (value != CAMERA_EFFECT_SEPIA)) {
3862
3863 int saturation = params.getInt(CameraParameters::KEY_SATURATION);
3864 if((saturation < CAMERA_MIN_SATURATION)
3865 || (saturation > CAMERA_MAX_SATURATION))
3866 return UNKNOWN_ERROR;
3867
3868 LOGV("setting saturation %d", saturation);
3869 mParameters.set(CameraParameters::KEY_SATURATION, saturation);
3870 bool ret = native_set_parm(CAMERA_SET_PARM_SATURATION, sizeof(saturation),
3871 (void *)&saturation);
3872 return ret ? NO_ERROR : UNKNOWN_ERROR;
3873 } else {
3874 LOGE(" Saturation value will not be set " \
3875 "when the effect selected is %s", str);
3876 return NO_ERROR;
3877 }
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003878}
3879
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303880status_t QualcommCameraHardware::setBrightness(const CameraParameters& params) {
3881 int brightness = params.getInt("luma-adaptation");
3882 if (mBrightness != brightness) {
3883 LOGV(" new brightness value : %d ", brightness);
3884 mBrightness = brightness;
3885
3886 bool ret = native_set_parm(CAMERA_SET_PARM_BRIGHTNESS, sizeof(mBrightness),
3887 (void *)&mBrightness);
3888 return ret ? NO_ERROR : UNKNOWN_ERROR;
3889 } else {
3890 return NO_ERROR;
3891 }
3892}
3893
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003894status_t QualcommCameraHardware::setWhiteBalance(const CameraParameters& params)
3895{
Apurva Rajguru7360db42010-04-09 16:37:36 -07003896
3897 const char *str_effect = mParameters.get(CameraParameters::KEY_EFFECT);
3898 int32_t value_effect = attr_lookup(effects, sizeof(effects) / sizeof(str_map), str_effect);
3899
3900 if( (value_effect != CAMERA_EFFECT_MONO) && (value_effect != CAMERA_EFFECT_NEGATIVE)
3901 && (value_effect != CAMERA_EFFECT_AQUA) && (value_effect != CAMERA_EFFECT_SEPIA)) {
3902 const char *str = params.get(CameraParameters::KEY_WHITE_BALANCE);
3903
3904 if (str != NULL) {
3905 int32_t value = attr_lookup(whitebalance, sizeof(whitebalance) / sizeof(str_map), str);
3906 if (value != NOT_FOUND) {
3907 mParameters.set(CameraParameters::KEY_WHITE_BALANCE, str);
3908 bool ret = native_set_parm(CAMERA_SET_PARM_WB, sizeof(value),
3909 (void *)&value);
3910 return ret ? NO_ERROR : UNKNOWN_ERROR;
3911 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003912 }
Apurva Rajguru7360db42010-04-09 16:37:36 -07003913 LOGE("Invalid whitebalance value: %s", (str == NULL) ? "NULL" : str);
3914 return BAD_VALUE;
3915 } else {
3916 LOGE("Whitebalance value will not be set " \
3917 "when the effect selected is %s", str_effect);
3918 return NO_ERROR;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003919 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003920}
3921
3922status_t QualcommCameraHardware::setFlash(const CameraParameters& params)
3923{
3924 if (!mSensorInfo.flash_enabled) {
3925 LOGV("%s: flash not supported", __FUNCTION__);
3926 return NO_ERROR;
3927 }
3928
3929 const char *str = params.get(CameraParameters::KEY_FLASH_MODE);
3930 if (str != NULL) {
3931 int32_t value = attr_lookup(flash, sizeof(flash) / sizeof(str_map), str);
3932 if (value != NOT_FOUND) {
3933 mParameters.set(CameraParameters::KEY_FLASH_MODE, str);
3934 bool ret = native_set_parm(CAMERA_SET_PARM_LED_MODE,
3935 sizeof(value), (void *)&value);
3936 return ret ? NO_ERROR : UNKNOWN_ERROR;
3937 }
3938 }
3939 LOGE("Invalid flash mode value: %s", (str == NULL) ? "NULL" : str);
3940 return BAD_VALUE;
3941}
3942
3943status_t QualcommCameraHardware::setAntibanding(const CameraParameters& params)
3944{
Srinivasan Kannan2229d272010-01-05 14:58:28 -08003945 if(!strcmp(sensorType->name, "2mp")) {
3946 LOGE("Parameter AntiBanding is not supported for this sensor");
3947 return NO_ERROR;
3948 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003949 const char *str = params.get(CameraParameters::KEY_ANTIBANDING);
3950 if (str != NULL) {
3951 int value = (camera_antibanding_type)attr_lookup(
3952 antibanding, sizeof(antibanding) / sizeof(str_map), str);
3953 if (value != NOT_FOUND) {
3954 camera_antibanding_type temp = (camera_antibanding_type) value;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003955 mParameters.set(CameraParameters::KEY_ANTIBANDING, str);
Srinivasan Kannan2229d272010-01-05 14:58:28 -08003956 bool ret;
3957 if (temp == CAMERA_ANTIBANDING_AUTO) {
3958 ret = native_set_parm(CAMERA_ENABLE_AFD,
3959 0, NULL);
3960 } else {
3961 ret = native_set_parm(CAMERA_SET_PARM_ANTIBANDING,
3962 sizeof(camera_antibanding_type), (void *)&temp);
3963 }
3964 return ret ? NO_ERROR : UNKNOWN_ERROR;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003965 }
3966 }
3967 LOGE("Invalid antibanding value: %s", (str == NULL) ? "NULL" : str);
3968 return BAD_VALUE;
3969}
3970
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303971status_t QualcommCameraHardware::setLensshadeValue(const CameraParameters& params)
3972{
Mohan Kandrace6bf562010-04-26 13:00:19 -07003973 if( (!strcmp(sensorType->name, "2mp")) ||
3974 (!strcmp(mSensorInfo.name, "vx6953")) ||
3975 (!strcmp(mSensorInfo.name, "VX6953")) ) {
Mohan Kandra93f1bfb2009-12-15 16:55:33 -08003976 LOGE("Parameter Rolloff is not supported for this sensor");
3977 return NO_ERROR;
3978 }
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303979 const char *str = params.get(CameraParameters::KEY_LENSSHADE);
3980 if (str != NULL) {
3981 int value = attr_lookup(lensshade,
3982 sizeof(lensshade) / sizeof(str_map), str);
3983 if (value != NOT_FOUND) {
3984 int8_t temp = (int8_t)value;
3985 mParameters.set(CameraParameters::KEY_LENSSHADE, str);
3986 native_set_parm(CAMERA_SET_PARM_ROLLOFF, sizeof(int8_t), (void *)&temp);
3987 return NO_ERROR;
3988 }
3989 }
3990 LOGE("Invalid lensShade value: %s", (str == NULL) ? "NULL" : str);
3991 return BAD_VALUE;
3992}
3993
3994status_t QualcommCameraHardware::setISOValue(const CameraParameters& params) {
Apurva Rajguruf12d9d22010-04-05 16:47:12 -07003995 int8_t temp_hjr;
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303996 const char *str = params.get(CameraParameters::KEY_ISO_MODE);
3997 if (str != NULL) {
3998 int value = (camera_iso_mode_type)attr_lookup(
3999 iso, sizeof(iso) / sizeof(str_map), str);
4000 if (value != NOT_FOUND) {
4001 camera_iso_mode_type temp = (camera_iso_mode_type) value;
Apurva Rajguruf12d9d22010-04-05 16:47:12 -07004002 if (value == CAMERA_ISO_DEBLUR) {
4003 temp_hjr = true;
4004 native_set_parm(CAMERA_SET_PARM_HJR, sizeof(int8_t), (void*)&temp_hjr);
4005 mHJR = value;
4006 }
4007 else {
4008 if (mHJR == CAMERA_ISO_DEBLUR) {
4009 temp_hjr = false;
4010 native_set_parm(CAMERA_SET_PARM_HJR, sizeof(int8_t), (void*)&temp_hjr);
4011 mHJR = value;
4012 }
4013 }
4014
Nishant Panditc8c1ee72009-12-03 16:24:02 +05304015 mParameters.set(CameraParameters::KEY_ISO_MODE, str);
4016 native_set_parm(CAMERA_SET_PARM_ISO, sizeof(camera_iso_mode_type), (void *)&temp);
4017 return NO_ERROR;
4018 }
4019 }
4020 LOGE("Invalid Iso value: %s", (str == NULL) ? "NULL" : str);
4021 return BAD_VALUE;
4022}
4023
4024
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004025status_t QualcommCameraHardware::setGpsLocation(const CameraParameters& params)
4026{
4027 const char *latitude = params.get(CameraParameters::KEY_GPS_LATITUDE);
4028 if (latitude) {
4029 mParameters.set(CameraParameters::KEY_GPS_LATITUDE, latitude);
4030 }
4031
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08004032 const char *latitudeRef = params.get(CameraParameters::KEY_GPS_LATITUDE_REF);
4033 if (latitudeRef) {
4034 mParameters.set(CameraParameters::KEY_GPS_LATITUDE_REF, latitudeRef);
4035 }
4036
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004037 const char *longitude = params.get(CameraParameters::KEY_GPS_LONGITUDE);
4038 if (longitude) {
4039 mParameters.set(CameraParameters::KEY_GPS_LONGITUDE, longitude);
4040 }
4041
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08004042 const char *longitudeRef = params.get(CameraParameters::KEY_GPS_LONGITUDE_REF);
4043 if (longitudeRef) {
4044 mParameters.set(CameraParameters::KEY_GPS_LONGITUDE_REF, longitudeRef);
4045 }
4046
4047 const char *altitudeRef = params.get(CameraParameters::KEY_GPS_ALTITUDE_REF);
4048 if (altitudeRef) {
4049 mParameters.set(CameraParameters::KEY_GPS_ALTITUDE_REF, altitudeRef);
4050 }
4051
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004052 const char *altitude = params.get(CameraParameters::KEY_GPS_ALTITUDE);
4053 if (altitude) {
4054 mParameters.set(CameraParameters::KEY_GPS_ALTITUDE, altitude);
4055 }
4056
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08004057 const char *status = params.get(CameraParameters::KEY_GPS_STATUS);
4058 if (status) {
4059 mParameters.set(CameraParameters::KEY_GPS_STATUS, status);
4060 }
4061
4062 const char *dateTime = params.get(CameraParameters::KEY_EXIF_DATETIME);
4063 if (dateTime) {
4064 mParameters.set(CameraParameters::KEY_EXIF_DATETIME, dateTime);
4065 }
4066
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004067 const char *timestamp = params.get(CameraParameters::KEY_GPS_TIMESTAMP);
4068 if (timestamp) {
4069 mParameters.set(CameraParameters::KEY_GPS_TIMESTAMP, timestamp);
4070 }
4071 return NO_ERROR;
4072}
4073
4074status_t QualcommCameraHardware::setRotation(const CameraParameters& params)
4075{
4076 status_t rc = NO_ERROR;
4077 int rotation = params.getInt(CameraParameters::KEY_ROTATION);
4078 if (rotation != NOT_FOUND) {
4079 if (rotation == 0 || rotation == 90 || rotation == 180
4080 || rotation == 270) {
4081 mParameters.set(CameraParameters::KEY_ROTATION, rotation);
4082 } else {
4083 LOGE("Invalid rotation value: %d", rotation);
4084 rc = BAD_VALUE;
4085 }
4086 }
4087 return rc;
4088}
4089
4090status_t QualcommCameraHardware::setZoom(const CameraParameters& params)
4091{
4092 status_t rc = NO_ERROR;
4093 // No matter how many different zoom values the driver can provide, HAL
4094 // provides applictations the same number of zoom levels. The maximum driver
4095 // zoom value depends on sensor output (VFE input) and preview size (VFE
4096 // output) because VFE can only crop and cannot upscale. If the preview size
4097 // is bigger, the maximum zoom ratio is smaller. However, we want the
4098 // zoom ratio of each zoom level is always the same whatever the preview
4099 // size is. Ex: zoom level 1 is always 1.2x, zoom level 2 is 1.44x, etc. So,
4100 // we need to have a fixed maximum zoom value and do read it from the
4101 // driver.
Mohan Kandra284966d2010-01-05 13:39:15 -08004102 static const int ZOOM_STEP = 1;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004103 int32_t zoom_level = params.getInt("zoom");
4104
Mohan Kandra284966d2010-01-05 13:39:15 -08004105 LOGV("Set zoom=%d", zoom_level);
4106 if(zoom_level >= 0 && zoom_level <= mMaxZoom) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004107 mParameters.set("zoom", zoom_level);
4108 int32_t zoom_value = ZOOM_STEP * zoom_level;
4109 bool ret = native_set_parm(CAMERA_SET_PARM_ZOOM,
4110 sizeof(zoom_value), (void *)&zoom_value);
4111 rc = ret ? NO_ERROR : UNKNOWN_ERROR;
4112 } else {
4113 rc = BAD_VALUE;
4114 }
4115
4116 return rc;
4117}
4118
4119status_t QualcommCameraHardware::setFocusMode(const CameraParameters& params)
4120{
4121 const char *str = params.get(CameraParameters::KEY_FOCUS_MODE);
4122 if (str != NULL) {
4123 int32_t value = attr_lookup(focus_modes,
4124 sizeof(focus_modes) / sizeof(str_map), str);
4125 if (value != NOT_FOUND) {
4126 mParameters.set(CameraParameters::KEY_FOCUS_MODE, str);
4127 // Focus step is reset to infinity when preview is started. We do
4128 // not need to do anything now.
4129 return NO_ERROR;
4130 }
4131 }
4132 LOGE("Invalid focus mode value: %s", (str == NULL) ? "NULL" : str);
4133 return BAD_VALUE;
4134}
4135
4136status_t QualcommCameraHardware::setOrientation(const CameraParameters& params)
4137{
4138 const char *str = params.get("orientation");
4139
4140 if (str != NULL) {
4141 if (strcmp(str, "portrait") == 0 || strcmp(str, "landscape") == 0) {
4142 // Camera service needs this to decide if the preview frames and raw
4143 // pictures should be rotated.
4144 mParameters.set("orientation", str);
4145 } else {
4146 LOGE("Invalid orientation value: %s", str);
4147 return BAD_VALUE;
4148 }
4149 }
4150 return NO_ERROR;
4151}
4152
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08004153status_t QualcommCameraHardware::setPictureFormat(const CameraParameters& params)
4154{
4155 const char * str = params.get(CameraParameters::KEY_PICTURE_FORMAT);
4156
4157 if(str != NULL){
4158 int32_t value = attr_lookup(picture_formats,
4159 sizeof(picture_formats) / sizeof(str_map), str);
4160 if(value != NOT_FOUND){
4161 mParameters.set(CameraParameters::KEY_PICTURE_FORMAT, str);
4162 } else {
4163 LOGE("Invalid Picture Format value: %s", str);
4164 return BAD_VALUE;
4165 }
4166 }
4167 return NO_ERROR;
4168}
4169
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004170QualcommCameraHardware::MemPool::MemPool(int buffer_size, int num_buffers,
4171 int frame_size,
4172 const char *name) :
4173 mBufferSize(buffer_size),
4174 mNumBuffers(num_buffers),
4175 mFrameSize(frame_size),
4176 mBuffers(NULL), mName(name)
4177{
4178 int page_size_minus_1 = getpagesize() - 1;
4179 mAlignedBufferSize = (buffer_size + page_size_minus_1) & (~page_size_minus_1);
4180}
4181
4182void QualcommCameraHardware::MemPool::completeInitialization()
4183{
4184 // If we do not know how big the frame will be, we wait to allocate
4185 // the buffers describing the individual frames until we do know their
4186 // size.
4187
4188 if (mFrameSize > 0) {
4189 mBuffers = new sp<MemoryBase>[mNumBuffers];
4190 for (int i = 0; i < mNumBuffers; i++) {
4191 mBuffers[i] = new
4192 MemoryBase(mHeap,
4193 i * mAlignedBufferSize,
4194 mFrameSize);
4195 }
4196 }
4197}
4198
4199QualcommCameraHardware::AshmemPool::AshmemPool(int buffer_size, int num_buffers,
4200 int frame_size,
4201 const char *name) :
4202 QualcommCameraHardware::MemPool(buffer_size,
4203 num_buffers,
4204 frame_size,
4205 name)
4206{
4207 LOGV("constructing MemPool %s backed by ashmem: "
4208 "%d frames @ %d uint8_ts, "
4209 "buffer size %d",
4210 mName,
4211 num_buffers, frame_size, buffer_size);
4212
4213 int page_mask = getpagesize() - 1;
4214 int ashmem_size = buffer_size * num_buffers;
4215 ashmem_size += page_mask;
4216 ashmem_size &= ~page_mask;
4217
4218 mHeap = new MemoryHeapBase(ashmem_size);
4219
4220 completeInitialization();
4221}
4222
4223static bool register_buf(int camfd,
4224 int size,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08004225 int frame_size,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004226 int pmempreviewfd,
4227 uint32_t offset,
4228 uint8_t *buf,
4229 int pmem_type,
4230 bool vfe_can_write,
4231 bool register_buffer = true);
4232
4233QualcommCameraHardware::PmemPool::PmemPool(const char *pmem_pool,
4234 int flags,
4235 int camera_control_fd,
4236 int pmem_type,
4237 int buffer_size, int num_buffers,
4238 int frame_size,
4239 const char *name) :
4240 QualcommCameraHardware::MemPool(buffer_size,
4241 num_buffers,
4242 frame_size,
4243 name),
4244 mPmemType(pmem_type),
4245 mCameraControlFd(dup(camera_control_fd))
4246{
4247 LOGV("constructing MemPool %s backed by pmem pool %s: "
4248 "%d frames @ %d bytes, buffer size %d",
4249 mName,
4250 pmem_pool, num_buffers, frame_size,
4251 buffer_size);
4252
4253 LOGV("%s: duplicating control fd %d --> %d",
4254 __FUNCTION__,
4255 camera_control_fd, mCameraControlFd);
4256
4257 // Make a new mmap'ed heap that can be shared across processes.
4258 // mAlignedBufferSize is already in 4k aligned. (do we need total size necessary to be in power of 2??)
4259 mAlignedSize = mAlignedBufferSize * num_buffers;
4260
4261 sp<MemoryHeapBase> masterHeap =
4262 new MemoryHeapBase(pmem_pool, mAlignedSize, flags);
4263
4264 if (masterHeap->getHeapID() < 0) {
4265 LOGE("failed to construct master heap for pmem pool %s", pmem_pool);
4266 masterHeap.clear();
4267 return;
4268 }
4269
4270 sp<MemoryHeapPmem> pmemHeap = new MemoryHeapPmem(masterHeap, flags);
4271 if (pmemHeap->getHeapID() >= 0) {
4272 pmemHeap->slap();
4273 masterHeap.clear();
4274 mHeap = pmemHeap;
4275 pmemHeap.clear();
4276
4277 mFd = mHeap->getHeapID();
4278 if (::ioctl(mFd, PMEM_GET_SIZE, &mSize)) {
4279 LOGE("pmem pool %s ioctl(PMEM_GET_SIZE) error %s (%d)",
4280 pmem_pool,
4281 ::strerror(errno), errno);
4282 mHeap.clear();
4283 return;
4284 }
4285
4286 LOGV("pmem pool %s ioctl(fd = %d, PMEM_GET_SIZE) is %ld",
4287 pmem_pool,
4288 mFd,
4289 mSize.len);
Mohan Kandra284966d2010-01-05 13:39:15 -08004290 LOGD("mBufferSize=%d, mAlignedBufferSize=%d\n", mBufferSize, mAlignedBufferSize);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004291 // Unregister preview buffers with the camera drivers. Allow the VFE to write
4292 // to all preview buffers except for the last one.
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08004293 // Only Register the preview, snapshot and thumbnail buffers with the kernel.
Mohan Kandrad9efed92010-01-15 19:08:39 -08004294 if( (strcmp("postview", mName) != 0) ){
4295 int num_buf = num_buffers;
4296 if(!strcmp("preview", mName)) num_buf = kPreviewBufferCount;
Brian Steuerb62adbd2010-02-02 14:47:08 -08004297 LOGD("num_buffers = %d", num_buf);
Mohan Kandrad9efed92010-01-15 19:08:39 -08004298 for (int cnt = 0; cnt < num_buf; ++cnt) {
Sravankb4f5f1c2010-01-21 11:06:17 +05304299 int active = 1;
4300 if(pmem_type == MSM_PMEM_VIDEO){
4301 active = (cnt<ACTIVE_VIDEO_BUFFERS);
4302 LOGV(" pmempool creating video buffers : active %d ", active);
4303 }
4304 else if (pmem_type == MSM_PMEM_PREVIEW){
4305 active = (cnt < (num_buf-1));
4306 }
Mohan Kandra284966d2010-01-05 13:39:15 -08004307 register_buf(mCameraControlFd,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004308 mBufferSize,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08004309 mFrameSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004310 mHeap->getHeapID(),
4311 mAlignedBufferSize * cnt,
4312 (uint8_t *)mHeap->base() + mAlignedBufferSize * cnt,
4313 pmem_type,
Sravankb4f5f1c2010-01-21 11:06:17 +05304314 active);
Mohan Kandra284966d2010-01-05 13:39:15 -08004315 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004316 }
4317
4318 completeInitialization();
4319 }
4320 else LOGE("pmem pool %s error: could not create master heap!",
4321 pmem_pool);
4322}
4323
4324QualcommCameraHardware::PmemPool::~PmemPool()
4325{
4326 LOGV("%s: %s E", __FUNCTION__, mName);
4327 if (mHeap != NULL) {
4328 // Unregister preview buffers with the camera drivers.
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08004329 // Only Unregister the preview, snapshot and thumbnail
4330 // buffers with the kernel.
Mohan Kandrad9efed92010-01-15 19:08:39 -08004331 if( (strcmp("postview", mName) != 0) ){
4332 int num_buffers = mNumBuffers;
4333 if(!strcmp("preview", mName)) num_buffers = kPreviewBufferCount;
4334 for (int cnt = 0; cnt < num_buffers; ++cnt) {
Mohan Kandra284966d2010-01-05 13:39:15 -08004335 register_buf(mCameraControlFd,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004336 mBufferSize,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08004337 mFrameSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004338 mHeap->getHeapID(),
4339 mAlignedBufferSize * cnt,
4340 (uint8_t *)mHeap->base() + mAlignedBufferSize * cnt,
4341 mPmemType,
4342 false,
4343 false /* unregister */);
Mohan Kandra284966d2010-01-05 13:39:15 -08004344 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004345 }
4346 }
4347 LOGV("destroying PmemPool %s: closing control fd %d",
4348 mName,
4349 mCameraControlFd);
4350 close(mCameraControlFd);
4351 LOGV("%s: %s X", __FUNCTION__, mName);
4352}
4353
4354QualcommCameraHardware::MemPool::~MemPool()
4355{
4356 LOGV("destroying MemPool %s", mName);
4357 if (mFrameSize > 0)
4358 delete [] mBuffers;
4359 mHeap.clear();
4360 LOGV("destroying MemPool %s completed", mName);
4361}
4362
4363static bool register_buf(int camfd,
4364 int size,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08004365 int frame_size,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004366 int pmempreviewfd,
4367 uint32_t offset,
4368 uint8_t *buf,
4369 int pmem_type,
4370 bool vfe_can_write,
4371 bool register_buffer)
4372{
4373 struct msm_pmem_info pmemBuf;
4374
4375 pmemBuf.type = pmem_type;
4376 pmemBuf.fd = pmempreviewfd;
4377 pmemBuf.offset = offset;
4378 pmemBuf.len = size;
4379 pmemBuf.vaddr = buf;
4380 pmemBuf.y_off = 0;
Srinivasan Kannanb36a4fe2010-01-29 19:34:09 -08004381
4382 if(pmem_type == MSM_PMEM_RAW_MAINIMG)
4383 pmemBuf.cbcr_off = 0;
4384 else
4385 pmemBuf.cbcr_off = PAD_TO_WORD(frame_size * 2 / 3);
4386
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004387 pmemBuf.active = vfe_can_write;
4388
4389 LOGV("register_buf: camfd = %d, reg = %d buffer = %p",
4390 camfd, !register_buffer, buf);
4391 if (ioctl(camfd,
4392 register_buffer ?
4393 MSM_CAM_IOCTL_REGISTER_PMEM :
4394 MSM_CAM_IOCTL_UNREGISTER_PMEM,
4395 &pmemBuf) < 0) {
4396 LOGE("register_buf: MSM_CAM_IOCTL_(UN)REGISTER_PMEM fd %d error %s",
4397 camfd,
4398 strerror(errno));
4399 return false;
4400 }
4401 return true;
4402}
4403
4404status_t QualcommCameraHardware::MemPool::dump(int fd, const Vector<String16>& args) const
4405{
4406 const size_t SIZE = 256;
4407 char buffer[SIZE];
4408 String8 result;
4409 snprintf(buffer, 255, "QualcommCameraHardware::AshmemPool::dump\n");
4410 result.append(buffer);
4411 if (mName) {
4412 snprintf(buffer, 255, "mem pool name (%s)\n", mName);
4413 result.append(buffer);
4414 }
4415 if (mHeap != 0) {
4416 snprintf(buffer, 255, "heap base(%p), size(%d), flags(%d), device(%s)\n",
4417 mHeap->getBase(), mHeap->getSize(),
4418 mHeap->getFlags(), mHeap->getDevice());
4419 result.append(buffer);
4420 }
4421 snprintf(buffer, 255,
4422 "buffer size (%d), number of buffers (%d), frame size(%d)",
4423 mBufferSize, mNumBuffers, mFrameSize);
4424 result.append(buffer);
4425 write(fd, result.string(), result.size());
4426 return NO_ERROR;
4427}
4428
4429static void receive_camframe_callback(struct msm_frame *frame)
4430{
4431 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4432 if (obj != 0) {
4433 obj->receivePreviewFrame(frame);
4434 }
4435}
4436
4437static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size)
4438{
4439 LOGV("receive_jpeg_fragment_callback E");
4440 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4441 if (obj != 0) {
4442 obj->receiveJpegPictureFragment(buff_ptr, buff_size);
4443 }
4444 LOGV("receive_jpeg_fragment_callback X");
4445}
4446
4447static void receive_jpeg_callback(jpeg_event_t status)
4448{
4449 LOGV("receive_jpeg_callback E (completion status %d)", status);
4450 if (status == JPEG_EVENT_DONE) {
4451 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4452 if (obj != 0) {
4453 obj->receiveJpegPicture();
4454 }
4455 }
4456 LOGV("receive_jpeg_callback X");
4457}
Sravankb4f5f1c2010-01-21 11:06:17 +05304458// 720p : video frame calbback from camframe
4459static void receive_camframe_video_callback(struct msm_frame *frame)
4460{
4461 LOGV("receive_camframe_video_callback E");
4462 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4463 if (obj != 0) {
4464 obj->receiveRecordingFrame(frame);
4465 }
4466 LOGV("receive_camframe_video_callback X");
4467}
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004468
4469void QualcommCameraHardware::setCallbacks(notify_callback notify_cb,
4470 data_callback data_cb,
4471 data_callback_timestamp data_cb_timestamp,
4472 void* user)
4473{
4474 Mutex::Autolock lock(mLock);
4475 mNotifyCallback = notify_cb;
4476 mDataCallback = data_cb;
4477 mDataCallbackTimestamp = data_cb_timestamp;
4478 mCallbackCookie = user;
4479}
4480
4481void QualcommCameraHardware::enableMsgType(int32_t msgType)
4482{
4483 Mutex::Autolock lock(mLock);
4484 mMsgEnabled |= msgType;
4485}
4486
4487void QualcommCameraHardware::disableMsgType(int32_t msgType)
4488{
4489 Mutex::Autolock lock(mLock);
4490 mMsgEnabled &= ~msgType;
4491}
4492
4493bool QualcommCameraHardware::msgTypeEnabled(int32_t msgType)
4494{
4495 return (mMsgEnabled & msgType);
4496}
4497
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08004498bool QualcommCameraHardware::useOverlay(void)
4499{
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08004500 if( mCurrentTarget == TARGET_MSM7630 ) {
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08004501 /* Only 7x30 supports Overlay */
4502 mUseOverlay = TRUE;
4503 } else
4504 mUseOverlay = FALSE;
4505
4506 LOGV(" Using Overlay : %s ", mUseOverlay ? "YES" : "NO" );
4507 return mUseOverlay;
4508}
4509
4510status_t QualcommCameraHardware::setOverlay(const sp<Overlay> &Overlay)
4511{
4512 if( Overlay != NULL) {
4513 LOGV(" Valid overlay object ");
4514 mOverlayLock.lock();
4515 mOverlay = Overlay;
4516 mOverlayLock.unlock();
4517 } else {
Apurva Rajguruc73c1722010-04-15 17:39:11 -07004518 LOGV(" Overlay object NULL. returning ");
Mohan Kandrad9efed92010-01-15 19:08:39 -08004519 mOverlay = NULL;
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08004520 return UNKNOWN_ERROR;
4521 }
4522 return NO_ERROR;
4523}
Kiran Kumar H N215cac42009-12-08 01:53:46 -08004524
4525void QualcommCameraHardware::receive_camframetimeout(void) {
4526 LOGV("receive_camframetimeout: E");
4527 Mutex::Autolock l(&mCamframeTimeoutLock);
Kiran Kumar H N7ac84e32010-02-01 10:58:47 -08004528 LOGD(" Camframe timed out. Not receiving any frames from camera driver ");
Kiran Kumar H N215cac42009-12-08 01:53:46 -08004529 camframe_timeout_flag = TRUE;
4530 LOGV("receive_camframetimeout: X");
4531}
4532
4533static void receive_camframetimeout_callback(void) {
4534 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4535 if (obj != 0) {
4536 obj->receive_camframetimeout();
4537 }
4538}
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08004539
4540void QualcommCameraHardware::storePreviewFrameForPostview(void) {
4541 LOGV(" storePreviewFrameForPostview : E ");
4542
4543 /* Since there is restriction on the maximum overlay dimensions
4544 * that can be created, we use the last preview frame as postview
4545 * for 7x30. */
4546 LOGV(" Copying the preview buffer to postview buffer %d ",
4547 mPreviewFrameSize);
4548 if( mPostViewHeap != NULL && mLastQueuedFrame != NULL) {
4549 memcpy(mPostViewHeap->mHeap->base(),
4550 (uint8_t *)mLastQueuedFrame, mPreviewFrameSize );
4551 } else
4552 LOGE(" Failed to store Preview frame. No Postview ");
4553
4554 LOGV(" storePreviewFrameForPostview : X ");
4555}
Kiran Kumar H Nb49af212010-02-17 15:12:17 -08004556
4557bool QualcommCameraHardware::isValidDimension(int width, int height) {
4558 bool retVal = FALSE;
4559 /* This function checks if a given resolution is valid or not.
4560 * A particular resolution is considered valid if it satisfies
4561 * the following conditions:
4562 * 1. width & height should be multiple of 16.
4563 * 2. width & height should be less than/equal to the dimensions
4564 * supported by the camera sensor.
4565 * 3. the aspect ratio is a valid aspect ratio and is among the
4566 * commonly used aspect ratio as determined by the thumbnail_sizes
4567 * data structure.
4568 */
4569
4570 if( (width == CEILING16(width)) && (height == CEILING16(height))
4571 && (width <= sensorType->max_supported_snapshot_width)
4572 && (height <= sensorType->max_supported_snapshot_height) )
4573 {
4574 uint32_t pictureAspectRatio = (uint32_t)((width * Q12)/height);
4575 for(int i = 0; i < THUMBNAIL_SIZE_COUNT; i++ ) {
4576 if(thumbnail_sizes[i].aspect_ratio == pictureAspectRatio) {
4577 retVal = TRUE;
4578 break;
4579 }
4580 }
4581 }
4582 return retVal;
4583}
Kiran Kumar H N4dd45a62010-02-26 15:56:33 -08004584status_t QualcommCameraHardware::getBufferInfo(sp<IMemory>& Frame, size_t *alignedSize) {
4585 status_t ret;
4586 LOGV(" getBufferInfo : E ");
Vamshidhar Kondrab362be62010-03-22 19:07:29 +05304587 if( ( mCurrentTarget == TARGET_MSM7630 ) || (mCurrentTarget == TARGET_QSD8250) )
4588 {
4589 if( mRecordHeap != NULL){
4590 LOGV(" Setting valid buffer information ");
4591 Frame = mRecordHeap->mBuffers[0];
4592 if( alignedSize != NULL) {
4593 *alignedSize = mRecordHeap->mAlignedBufferSize;
4594 LOGV(" HAL : alignedSize = %d ", *alignedSize);
4595 ret = NO_ERROR;
4596 } else {
4597 LOGE(" HAL : alignedSize is NULL. Cannot update alignedSize ");
4598 ret = UNKNOWN_ERROR;
4599 }
Kiran Kumar H N4dd45a62010-02-26 15:56:33 -08004600 } else {
Vamshidhar Kondrab362be62010-03-22 19:07:29 +05304601 LOGE(" RecordHeap is null. Buffer information wont be updated ");
4602 Frame = NULL;
4603 ret = UNKNOWN_ERROR;
4604 }
Kiran Kumar H N4dd45a62010-02-26 15:56:33 -08004605 } else {
Vamshidhar Kondrab362be62010-03-22 19:07:29 +05304606 if(mPreviewHeap != NULL) {
4607 LOGV(" Setting valid buffer information ");
4608 Frame = mPreviewHeap->mBuffers[0];
4609 if( alignedSize != NULL) {
4610 *alignedSize = mPreviewHeap->mAlignedBufferSize;
4611 LOGV(" HAL : alignedSize = %d ", *alignedSize);
4612 ret = NO_ERROR;
4613 } else {
4614 LOGE(" HAL : alignedSize is NULL. Cannot update alignedSize ");
4615 ret = UNKNOWN_ERROR;
4616 }
4617 } else {
4618 LOGE(" PreviewHeap is null. Buffer information wont be updated ");
4619 Frame = NULL;
4620 ret = UNKNOWN_ERROR;
4621 }
Kiran Kumar H N4dd45a62010-02-26 15:56:33 -08004622 }
4623 LOGV(" getBufferInfo : X ");
4624 return ret;
4625}
Kiran Kumar H Nb49af212010-02-17 15:12:17 -08004626
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004627}; // namespace android