blob: 90bac6b60f5c265622494d70f15e14c463cd74cd [file] [log] [blame]
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001/*
2** Copyright 2008, Google Inc.
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303** Copyright (c) 2009, Code Aurora Forum. All rights reserved.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18//#define LOG_NDEBUG 0
19#define LOG_TAG "QualcommCameraHardware"
20#include <utils/Log.h>
21
22#include "QualcommCameraHardware.h"
23
24#include <utils/Errors.h>
25#include <utils/threads.h>
26#include <binder/MemoryHeapPmem.h>
27#include <utils/String16.h>
28#include <sys/types.h>
29#include <sys/stat.h>
30#include <unistd.h>
Sravankb4f5f1c2010-01-21 11:06:17 +053031#include <fcntl.h>
Apurva Rajguru8d1773b2009-12-02 14:21:23 -080032#include <cutils/properties.h>
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -080033#include <math.h>
Priya Komarlingamb85535d2009-11-30 13:06:01 -080034#if HAVE_ANDROID_OS
35#include <linux/android_pmem.h>
36#endif
37#include <linux/ioctl.h>
38#include <ui/CameraParameters.h>
39
Mohan Kandra284966d2010-01-05 13:39:15 -080040#include "linux/msm_mdp.h"
41#include <linux/fb.h>
42
Priya Komarlingamb85535d2009-11-30 13:06:01 -080043#define LIKELY(exp) __builtin_expect(!!(exp), 1)
44#define UNLIKELY(exp) __builtin_expect(!!(exp), 0)
45
46extern "C" {
47#include <fcntl.h>
48#include <time.h>
49#include <pthread.h>
50#include <stdio.h>
51#include <string.h>
52#include <unistd.h>
53#include <termios.h>
54#include <assert.h>
55#include <stdlib.h>
56#include <ctype.h>
57#include <signal.h>
58#include <errno.h>
59#include <sys/mman.h>
60#include <sys/system_properties.h>
61#include <sys/time.h>
62#include <stdlib.h>
63
64#include <media/msm_camera.h>
65
66#include <camera.h>
67#include <camframe.h>
68#include <mm-still/jpeg/jpege.h>
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -080069#include <jpeg_encoder.h>
Priya Komarlingamb85535d2009-11-30 13:06:01 -080070
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -080071#define DEFAULT_PICTURE_WIDTH 1024
72#define DEFAULT_PICTURE_HEIGHT 768
Priya Komarlingamb85535d2009-11-30 13:06:01 -080073#define THUMBNAIL_BUFFER_SIZE (THUMBNAIL_WIDTH * THUMBNAIL_HEIGHT * 3/2)
74#define MAX_ZOOM_LEVEL 5
75#define NOT_FOUND -1
76
Sravankb4f5f1c2010-01-21 11:06:17 +053077// Number of video buffers held by kernal (initially 1,2 &3)
78#define ACTIVE_VIDEO_BUFFERS 3
79
Priya Komarlingamb85535d2009-11-30 13:06:01 -080080#if DLOPEN_LIBMMCAMERA
81#include <dlfcn.h>
82
83void* (*LINK_cam_conf)(void *data);
84void* (*LINK_cam_frame)(void *data);
85bool (*LINK_jpeg_encoder_init)();
86void (*LINK_jpeg_encoder_join)();
87bool (*LINK_jpeg_encoder_encode)(const cam_ctrl_dimension_t *dimen,
88 const uint8_t *thumbnailbuf, int thumbnailfd,
89 const uint8_t *snapshotbuf, int snapshotfd,
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -080090 common_crop_t *scaling_parms, exif_tags_info_t *exif_data,
91 int exif_table_numEntries);
Kiran Kumar H N7ac84e32010-02-01 10:58:47 -080092void (*LINK_camframe_terminate)(void);
Sravankb4f5f1c2010-01-21 11:06:17 +053093//for 720p
94// Function to add a video buffer to free Q
95void (*LINK_camframe_free_video)(struct msm_frame *frame);
96// Function pointer , called by camframe when a video frame is available.
97void (**LINK_camframe_video_callback)(struct msm_frame * frame);
98// To flush free Q in cam frame.
99void (*LINK_cam_frame_flush_free_video)(void);
100
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800101int8_t (*LINK_jpeg_encoder_setMainImageQuality)(uint32_t quality);
102int8_t (*LINK_jpeg_encoder_setThumbnailQuality)(uint32_t quality);
103int8_t (*LINK_jpeg_encoder_setRotation)(uint32_t rotation);
104int8_t (*LINK_jpeg_encoder_setLocation)(const camera_position_type *location);
105const struct camera_size_type *(*LINK_default_sensor_get_snapshot_sizes)(int *len);
106int (*LINK_launch_cam_conf_thread)(void);
107int (*LINK_release_cam_conf_thread)(void);
108int8_t (*LINK_zoom_crop_upscale)(uint32_t width, uint32_t height,
109 uint32_t cropped_width, uint32_t cropped_height, uint8_t *img_buf);
110
111// callbacks
112void (**LINK_mmcamera_camframe_callback)(struct msm_frame *frame);
113void (**LINK_mmcamera_jpegfragment_callback)(uint8_t *buff_ptr,
114 uint32_t buff_size);
115void (**LINK_mmcamera_jpeg_callback)(jpeg_event_t status);
116void (**LINK_mmcamera_shutter_callback)(common_crop_t *crop);
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800117void (**LINK_camframe_timeout_callback)(void);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800118#else
119#define LINK_cam_conf cam_conf
120#define LINK_cam_frame cam_frame
121#define LINK_jpeg_encoder_init jpeg_encoder_init
122#define LINK_jpeg_encoder_join jpeg_encoder_join
123#define LINK_jpeg_encoder_encode jpeg_encoder_encode
124#define LINK_camframe_terminate camframe_terminate
125#define LINK_jpeg_encoder_setMainImageQuality jpeg_encoder_setMainImageQuality
126#define LINK_jpeg_encoder_setThumbnailQuality jpeg_encoder_setThumbnailQuality
127#define LINK_jpeg_encoder_setRotation jpeg_encoder_setRotation
128#define LINK_jpeg_encoder_setLocation jpeg_encoder_setLocation
129#define LINK_default_sensor_get_snapshot_sizes default_sensor_get_snapshot_sizes
130#define LINK_launch_cam_conf_thread launch_cam_conf_thread
131#define LINK_release_cam_conf_thread release_cam_conf_thread
132#define LINK_zoom_crop_upscale zoom_crop_upscale
133extern void (*mmcamera_camframe_callback)(struct msm_frame *frame);
134extern void (*mmcamera_jpegfragment_callback)(uint8_t *buff_ptr,
135 uint32_t buff_size);
136extern void (*mmcamera_jpeg_callback)(jpeg_event_t status);
137extern void (*mmcamera_shutter_callback)(common_crop_t *crop);
138#endif
139
140} // extern "C"
141
142#ifndef HAVE_CAMERA_SIZE_TYPE
143struct camera_size_type {
144 int width;
145 int height;
146};
147#endif
148
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -0800149typedef struct crop_info_struct {
150 uint32_t x;
151 uint32_t y;
152 uint32_t w;
153 uint32_t h;
154} zoom_crop_info;
155
Mohan Kandra740cfce2010-01-07 12:58:24 -0800156union zoomimage
Mohan Kandra284966d2010-01-05 13:39:15 -0800157{
158 char d[sizeof(struct mdp_blit_req_list) + sizeof(struct mdp_blit_req) * 1];
159 struct mdp_blit_req_list list;
160} zoomImage;
161
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800162//Default to WVGA
Srinivasan Kannanfa7edae2009-12-16 18:02:01 -0800163#define DEFAULT_PREVIEW_SETTING 1
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800164static const camera_size_type preview_sizes[] = {
Srinivasan Kannanfa7edae2009-12-16 18:02:01 -0800165 { 1280, 720 }, // 720P, reserved
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800166 { 800, 480 }, // WVGA
167 { 720, 480 },
168 { 640, 480 }, // VGA
169 { 576, 432 },
170 { 480, 320 }, // HVGA
171 { 384, 288 },
172 { 352, 288 }, // CIF
173 { 320, 240 }, // QVGA
174 { 240, 160 }, // SQVGA
175 { 176, 144 }, // QCIF
176};
177#define PREVIEW_SIZE_COUNT (sizeof(preview_sizes)/sizeof(camera_size_type))
178
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800179//static const camera_size_type* picture_sizes;
180//static int PICTURE_SIZE_COUNT;
181/* TODO
182 * Ideally this should be a populated by lower layers.
183 * But currently this is no API to do that at lower layer.
184 * Hence populating with default sizes for now. This needs
185 * to be changed once the API is supported.
186 */
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800187//sorted on column basis
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800188static const camera_size_type picture_sizes[] = {
189 { 2592, 1944 }, // 5MP
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800190 { 2048, 1536 }, // 3MP QXGA
191 { 1920, 1080 }, //HD1080
192 { 1600, 1200 }, // 2MP UXGA
193 { 1280, 768 }, //WXGA
194 { 1280, 720 }, //HD720
195 { 1024, 768}, // 1MP XGA
196 { 800, 600 }, //SVGA
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800197 { 800, 480 }, // WVGA
198 { 640, 480 }, // VGA
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800199 { 352, 288 }, //CIF
200 { 320, 240 }, // QVGA
201 { 176, 144 } // QCIF
Apurva Rajguru1db0c392009-11-30 21:39:04 -0800202};
203static int PICTURE_SIZE_COUNT = sizeof(picture_sizes)/sizeof(camera_size_type);
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800204static const camera_size_type * picture_sizes_ptr;
205static int supportedPictureSizesCount;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800206
Srinivasan Kannan80d878f2009-12-18 15:06:02 -0800207#ifdef Q12
208#undef Q12
209#endif
210
211#define Q12 4096
212
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -0800213static const target_map targetList [] = {
214 { "msm7625", TARGET_MSM7625 },
215 { "msm7627", TARGET_MSM7627 },
216 { "qsd8250", TARGET_QSD8250 },
217 { "msm7630", TARGET_MSM7630 }
218};
219static targetType mCurrentTarget = TARGET_MAX;
220
Srinivasan Kannan80d878f2009-12-18 15:06:02 -0800221typedef struct {
222 uint32_t aspect_ratio;
223 uint32_t width;
224 uint32_t height;
225} thumbnail_size_type;
226
227static thumbnail_size_type thumbnail_sizes[] = {
228 { 7281, 512, 288 }, //1.777778
229 { 6826, 480, 288 }, //1.666667
230 { 5461, 512, 384 }, //1.333333
231 { 5006, 352, 288 }, //1.222222
232};
233#define THUMBNAIL_SIZE_COUNT (sizeof(thumbnail_sizes)/sizeof(thumbnail_size_type))
234#define DEFAULT_THUMBNAIL_SETTING 2
235#define THUMBNAIL_WIDTH_STR "512"
236#define THUMBNAIL_HEIGHT_STR "384"
237#define THUMBNAIL_SMALL_HEIGHT 144
238
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800239static int attr_lookup(const str_map arr[], int len, const char *name)
240{
241 if (name) {
242 for (int i = 0; i < len; i++) {
243 if (!strcmp(arr[i].desc, name))
244 return arr[i].val;
245 }
246 }
247 return NOT_FOUND;
248}
249
250// round to the next power of two
251static inline unsigned clp2(unsigned x)
252{
253 x = x - 1;
254 x = x | (x >> 1);
255 x = x | (x >> 2);
256 x = x | (x >> 4);
257 x = x | (x >> 8);
258 x = x | (x >>16);
259 return x + 1;
260}
261
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -0800262static int exif_table_numEntries = 0;
263#define MAX_EXIF_TABLE_ENTRIES 7
264exif_tags_info_t exif_data[MAX_EXIF_TABLE_ENTRIES];
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -0800265static zoom_crop_info zoomCropInfo;
266static void *mLastQueuedFrame = NULL;
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -0800267
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800268namespace android {
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800269
270static const int PICTURE_FORMAT_JPEG = 1;
271static const int PICTURE_FORMAT_RAW = 2;
272
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800273// from aeecamera.h
274static const str_map whitebalance[] = {
275 { CameraParameters::WHITE_BALANCE_AUTO, CAMERA_WB_AUTO },
276 { CameraParameters::WHITE_BALANCE_INCANDESCENT, CAMERA_WB_INCANDESCENT },
277 { CameraParameters::WHITE_BALANCE_FLUORESCENT, CAMERA_WB_FLUORESCENT },
278 { CameraParameters::WHITE_BALANCE_DAYLIGHT, CAMERA_WB_DAYLIGHT },
279 { CameraParameters::WHITE_BALANCE_CLOUDY_DAYLIGHT, CAMERA_WB_CLOUDY_DAYLIGHT }
280};
281
282// from camera_effect_t. This list must match aeecamera.h
283static const str_map effects[] = {
284 { CameraParameters::EFFECT_NONE, CAMERA_EFFECT_OFF },
285 { CameraParameters::EFFECT_MONO, CAMERA_EFFECT_MONO },
286 { CameraParameters::EFFECT_NEGATIVE, CAMERA_EFFECT_NEGATIVE },
287 { CameraParameters::EFFECT_SOLARIZE, CAMERA_EFFECT_SOLARIZE },
288 { CameraParameters::EFFECT_SEPIA, CAMERA_EFFECT_SEPIA },
289 { CameraParameters::EFFECT_POSTERIZE, CAMERA_EFFECT_POSTERIZE },
290 { CameraParameters::EFFECT_WHITEBOARD, CAMERA_EFFECT_WHITEBOARD },
291 { CameraParameters::EFFECT_BLACKBOARD, CAMERA_EFFECT_BLACKBOARD },
292 { CameraParameters::EFFECT_AQUA, CAMERA_EFFECT_AQUA }
293};
294
295// from qcamera/common/camera.h
Apurva Rajguru55562b02009-12-03 12:25:35 -0800296static const str_map autoexposure[] = {
297 { CameraParameters::AUTO_EXPOSURE_FRAME_AVG, CAMERA_AEC_FRAME_AVERAGE },
298 { CameraParameters::AUTO_EXPOSURE_CENTER_WEIGHTED, CAMERA_AEC_CENTER_WEIGHTED },
299 { CameraParameters::AUTO_EXPOSURE_SPOT_METERING, CAMERA_AEC_SPOT_METERING }
300};
301
302// from qcamera/common/camera.h
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800303static const str_map antibanding[] = {
304 { CameraParameters::ANTIBANDING_OFF, CAMERA_ANTIBANDING_OFF },
305 { CameraParameters::ANTIBANDING_50HZ, CAMERA_ANTIBANDING_50HZ },
306 { CameraParameters::ANTIBANDING_60HZ, CAMERA_ANTIBANDING_60HZ },
307 { CameraParameters::ANTIBANDING_AUTO, CAMERA_ANTIBANDING_AUTO }
308};
309
310/* Mapping from MCC to antibanding type */
311struct country_map {
312 uint32_t country_code;
313 camera_antibanding_type type;
314};
315
316static struct country_map country_numeric[] = {
317 { 202, CAMERA_ANTIBANDING_50HZ }, // Greece
318 { 204, CAMERA_ANTIBANDING_50HZ }, // Netherlands
319 { 206, CAMERA_ANTIBANDING_50HZ }, // Belgium
320 { 208, CAMERA_ANTIBANDING_50HZ }, // France
321 { 212, CAMERA_ANTIBANDING_50HZ }, // Monaco
322 { 213, CAMERA_ANTIBANDING_50HZ }, // Andorra
323 { 214, CAMERA_ANTIBANDING_50HZ }, // Spain
324 { 216, CAMERA_ANTIBANDING_50HZ }, // Hungary
325 { 219, CAMERA_ANTIBANDING_50HZ }, // Croatia
326 { 220, CAMERA_ANTIBANDING_50HZ }, // Serbia
327 { 222, CAMERA_ANTIBANDING_50HZ }, // Italy
328 { 226, CAMERA_ANTIBANDING_50HZ }, // Romania
329 { 228, CAMERA_ANTIBANDING_50HZ }, // Switzerland
330 { 230, CAMERA_ANTIBANDING_50HZ }, // Czech Republic
331 { 231, CAMERA_ANTIBANDING_50HZ }, // Slovakia
332 { 232, CAMERA_ANTIBANDING_50HZ }, // Austria
333 { 234, CAMERA_ANTIBANDING_50HZ }, // United Kingdom
334 { 235, CAMERA_ANTIBANDING_50HZ }, // United Kingdom
335 { 238, CAMERA_ANTIBANDING_50HZ }, // Denmark
336 { 240, CAMERA_ANTIBANDING_50HZ }, // Sweden
337 { 242, CAMERA_ANTIBANDING_50HZ }, // Norway
338 { 244, CAMERA_ANTIBANDING_50HZ }, // Finland
339 { 246, CAMERA_ANTIBANDING_50HZ }, // Lithuania
340 { 247, CAMERA_ANTIBANDING_50HZ }, // Latvia
341 { 248, CAMERA_ANTIBANDING_50HZ }, // Estonia
342 { 250, CAMERA_ANTIBANDING_50HZ }, // Russian Federation
343 { 255, CAMERA_ANTIBANDING_50HZ }, // Ukraine
344 { 257, CAMERA_ANTIBANDING_50HZ }, // Belarus
345 { 259, CAMERA_ANTIBANDING_50HZ }, // Moldova
346 { 260, CAMERA_ANTIBANDING_50HZ }, // Poland
347 { 262, CAMERA_ANTIBANDING_50HZ }, // Germany
348 { 266, CAMERA_ANTIBANDING_50HZ }, // Gibraltar
349 { 268, CAMERA_ANTIBANDING_50HZ }, // Portugal
350 { 270, CAMERA_ANTIBANDING_50HZ }, // Luxembourg
351 { 272, CAMERA_ANTIBANDING_50HZ }, // Ireland
352 { 274, CAMERA_ANTIBANDING_50HZ }, // Iceland
353 { 276, CAMERA_ANTIBANDING_50HZ }, // Albania
354 { 278, CAMERA_ANTIBANDING_50HZ }, // Malta
355 { 280, CAMERA_ANTIBANDING_50HZ }, // Cyprus
356 { 282, CAMERA_ANTIBANDING_50HZ }, // Georgia
357 { 283, CAMERA_ANTIBANDING_50HZ }, // Armenia
358 { 284, CAMERA_ANTIBANDING_50HZ }, // Bulgaria
359 { 286, CAMERA_ANTIBANDING_50HZ }, // Turkey
360 { 288, CAMERA_ANTIBANDING_50HZ }, // Faroe Islands
361 { 290, CAMERA_ANTIBANDING_50HZ }, // Greenland
362 { 293, CAMERA_ANTIBANDING_50HZ }, // Slovenia
363 { 294, CAMERA_ANTIBANDING_50HZ }, // Macedonia
364 { 295, CAMERA_ANTIBANDING_50HZ }, // Liechtenstein
365 { 297, CAMERA_ANTIBANDING_50HZ }, // Montenegro
366 { 302, CAMERA_ANTIBANDING_60HZ }, // Canada
367 { 310, CAMERA_ANTIBANDING_60HZ }, // United States of America
368 { 311, CAMERA_ANTIBANDING_60HZ }, // United States of America
369 { 312, CAMERA_ANTIBANDING_60HZ }, // United States of America
370 { 313, CAMERA_ANTIBANDING_60HZ }, // United States of America
371 { 314, CAMERA_ANTIBANDING_60HZ }, // United States of America
372 { 315, CAMERA_ANTIBANDING_60HZ }, // United States of America
373 { 316, CAMERA_ANTIBANDING_60HZ }, // United States of America
374 { 330, CAMERA_ANTIBANDING_60HZ }, // Puerto Rico
375 { 334, CAMERA_ANTIBANDING_60HZ }, // Mexico
376 { 338, CAMERA_ANTIBANDING_50HZ }, // Jamaica
377 { 340, CAMERA_ANTIBANDING_50HZ }, // Martinique
378 { 342, CAMERA_ANTIBANDING_50HZ }, // Barbados
379 { 346, CAMERA_ANTIBANDING_60HZ }, // Cayman Islands
380 { 350, CAMERA_ANTIBANDING_60HZ }, // Bermuda
381 { 352, CAMERA_ANTIBANDING_50HZ }, // Grenada
382 { 354, CAMERA_ANTIBANDING_60HZ }, // Montserrat
383 { 362, CAMERA_ANTIBANDING_50HZ }, // Netherlands Antilles
384 { 363, CAMERA_ANTIBANDING_60HZ }, // Aruba
385 { 364, CAMERA_ANTIBANDING_60HZ }, // Bahamas
386 { 365, CAMERA_ANTIBANDING_60HZ }, // Anguilla
387 { 366, CAMERA_ANTIBANDING_50HZ }, // Dominica
388 { 368, CAMERA_ANTIBANDING_60HZ }, // Cuba
389 { 370, CAMERA_ANTIBANDING_60HZ }, // Dominican Republic
390 { 372, CAMERA_ANTIBANDING_60HZ }, // Haiti
391 { 401, CAMERA_ANTIBANDING_50HZ }, // Kazakhstan
392 { 402, CAMERA_ANTIBANDING_50HZ }, // Bhutan
393 { 404, CAMERA_ANTIBANDING_50HZ }, // India
394 { 405, CAMERA_ANTIBANDING_50HZ }, // India
395 { 410, CAMERA_ANTIBANDING_50HZ }, // Pakistan
396 { 413, CAMERA_ANTIBANDING_50HZ }, // Sri Lanka
397 { 414, CAMERA_ANTIBANDING_50HZ }, // Myanmar
398 { 415, CAMERA_ANTIBANDING_50HZ }, // Lebanon
399 { 416, CAMERA_ANTIBANDING_50HZ }, // Jordan
400 { 417, CAMERA_ANTIBANDING_50HZ }, // Syria
401 { 418, CAMERA_ANTIBANDING_50HZ }, // Iraq
402 { 419, CAMERA_ANTIBANDING_50HZ }, // Kuwait
403 { 420, CAMERA_ANTIBANDING_60HZ }, // Saudi Arabia
404 { 421, CAMERA_ANTIBANDING_50HZ }, // Yemen
405 { 422, CAMERA_ANTIBANDING_50HZ }, // Oman
406 { 424, CAMERA_ANTIBANDING_50HZ }, // United Arab Emirates
407 { 425, CAMERA_ANTIBANDING_50HZ }, // Israel
408 { 426, CAMERA_ANTIBANDING_50HZ }, // Bahrain
409 { 427, CAMERA_ANTIBANDING_50HZ }, // Qatar
410 { 428, CAMERA_ANTIBANDING_50HZ }, // Mongolia
411 { 429, CAMERA_ANTIBANDING_50HZ }, // Nepal
412 { 430, CAMERA_ANTIBANDING_50HZ }, // United Arab Emirates
413 { 431, CAMERA_ANTIBANDING_50HZ }, // United Arab Emirates
414 { 432, CAMERA_ANTIBANDING_50HZ }, // Iran
415 { 434, CAMERA_ANTIBANDING_50HZ }, // Uzbekistan
416 { 436, CAMERA_ANTIBANDING_50HZ }, // Tajikistan
417 { 437, CAMERA_ANTIBANDING_50HZ }, // Kyrgyz Rep
418 { 438, CAMERA_ANTIBANDING_50HZ }, // Turkmenistan
419 { 440, CAMERA_ANTIBANDING_60HZ }, // Japan
420 { 441, CAMERA_ANTIBANDING_60HZ }, // Japan
421 { 452, CAMERA_ANTIBANDING_50HZ }, // Vietnam
422 { 454, CAMERA_ANTIBANDING_50HZ }, // Hong Kong
423 { 455, CAMERA_ANTIBANDING_50HZ }, // Macao
424 { 456, CAMERA_ANTIBANDING_50HZ }, // Cambodia
425 { 457, CAMERA_ANTIBANDING_50HZ }, // Laos
426 { 460, CAMERA_ANTIBANDING_50HZ }, // China
427 { 466, CAMERA_ANTIBANDING_60HZ }, // Taiwan
428 { 470, CAMERA_ANTIBANDING_50HZ }, // Bangladesh
429 { 472, CAMERA_ANTIBANDING_50HZ }, // Maldives
430 { 502, CAMERA_ANTIBANDING_50HZ }, // Malaysia
431 { 505, CAMERA_ANTIBANDING_50HZ }, // Australia
432 { 510, CAMERA_ANTIBANDING_50HZ }, // Indonesia
433 { 514, CAMERA_ANTIBANDING_50HZ }, // East Timor
434 { 515, CAMERA_ANTIBANDING_60HZ }, // Philippines
435 { 520, CAMERA_ANTIBANDING_50HZ }, // Thailand
436 { 525, CAMERA_ANTIBANDING_50HZ }, // Singapore
437 { 530, CAMERA_ANTIBANDING_50HZ }, // New Zealand
438 { 535, CAMERA_ANTIBANDING_60HZ }, // Guam
439 { 536, CAMERA_ANTIBANDING_50HZ }, // Nauru
440 { 537, CAMERA_ANTIBANDING_50HZ }, // Papua New Guinea
441 { 539, CAMERA_ANTIBANDING_50HZ }, // Tonga
442 { 541, CAMERA_ANTIBANDING_50HZ }, // Vanuatu
443 { 542, CAMERA_ANTIBANDING_50HZ }, // Fiji
444 { 544, CAMERA_ANTIBANDING_60HZ }, // American Samoa
445 { 545, CAMERA_ANTIBANDING_50HZ }, // Kiribati
446 { 546, CAMERA_ANTIBANDING_50HZ }, // New Caledonia
447 { 548, CAMERA_ANTIBANDING_50HZ }, // Cook Islands
448 { 602, CAMERA_ANTIBANDING_50HZ }, // Egypt
449 { 603, CAMERA_ANTIBANDING_50HZ }, // Algeria
450 { 604, CAMERA_ANTIBANDING_50HZ }, // Morocco
451 { 605, CAMERA_ANTIBANDING_50HZ }, // Tunisia
452 { 606, CAMERA_ANTIBANDING_50HZ }, // Libya
453 { 607, CAMERA_ANTIBANDING_50HZ }, // Gambia
454 { 608, CAMERA_ANTIBANDING_50HZ }, // Senegal
455 { 609, CAMERA_ANTIBANDING_50HZ }, // Mauritania
456 { 610, CAMERA_ANTIBANDING_50HZ }, // Mali
457 { 611, CAMERA_ANTIBANDING_50HZ }, // Guinea
458 { 613, CAMERA_ANTIBANDING_50HZ }, // Burkina Faso
459 { 614, CAMERA_ANTIBANDING_50HZ }, // Niger
460 { 616, CAMERA_ANTIBANDING_50HZ }, // Benin
461 { 617, CAMERA_ANTIBANDING_50HZ }, // Mauritius
462 { 618, CAMERA_ANTIBANDING_50HZ }, // Liberia
463 { 619, CAMERA_ANTIBANDING_50HZ }, // Sierra Leone
464 { 620, CAMERA_ANTIBANDING_50HZ }, // Ghana
465 { 621, CAMERA_ANTIBANDING_50HZ }, // Nigeria
466 { 622, CAMERA_ANTIBANDING_50HZ }, // Chad
467 { 623, CAMERA_ANTIBANDING_50HZ }, // Central African Republic
468 { 624, CAMERA_ANTIBANDING_50HZ }, // Cameroon
469 { 625, CAMERA_ANTIBANDING_50HZ }, // Cape Verde
470 { 627, CAMERA_ANTIBANDING_50HZ }, // Equatorial Guinea
471 { 631, CAMERA_ANTIBANDING_50HZ }, // Angola
472 { 633, CAMERA_ANTIBANDING_50HZ }, // Seychelles
473 { 634, CAMERA_ANTIBANDING_50HZ }, // Sudan
474 { 636, CAMERA_ANTIBANDING_50HZ }, // Ethiopia
475 { 637, CAMERA_ANTIBANDING_50HZ }, // Somalia
476 { 638, CAMERA_ANTIBANDING_50HZ }, // Djibouti
477 { 639, CAMERA_ANTIBANDING_50HZ }, // Kenya
478 { 640, CAMERA_ANTIBANDING_50HZ }, // Tanzania
479 { 641, CAMERA_ANTIBANDING_50HZ }, // Uganda
480 { 642, CAMERA_ANTIBANDING_50HZ }, // Burundi
481 { 643, CAMERA_ANTIBANDING_50HZ }, // Mozambique
482 { 645, CAMERA_ANTIBANDING_50HZ }, // Zambia
483 { 646, CAMERA_ANTIBANDING_50HZ }, // Madagascar
484 { 647, CAMERA_ANTIBANDING_50HZ }, // France
485 { 648, CAMERA_ANTIBANDING_50HZ }, // Zimbabwe
486 { 649, CAMERA_ANTIBANDING_50HZ }, // Namibia
487 { 650, CAMERA_ANTIBANDING_50HZ }, // Malawi
488 { 651, CAMERA_ANTIBANDING_50HZ }, // Lesotho
489 { 652, CAMERA_ANTIBANDING_50HZ }, // Botswana
490 { 653, CAMERA_ANTIBANDING_50HZ }, // Swaziland
491 { 654, CAMERA_ANTIBANDING_50HZ }, // Comoros
492 { 655, CAMERA_ANTIBANDING_50HZ }, // South Africa
493 { 657, CAMERA_ANTIBANDING_50HZ }, // Eritrea
494 { 702, CAMERA_ANTIBANDING_60HZ }, // Belize
495 { 704, CAMERA_ANTIBANDING_60HZ }, // Guatemala
496 { 706, CAMERA_ANTIBANDING_60HZ }, // El Salvador
497 { 708, CAMERA_ANTIBANDING_60HZ }, // Honduras
498 { 710, CAMERA_ANTIBANDING_60HZ }, // Nicaragua
499 { 712, CAMERA_ANTIBANDING_60HZ }, // Costa Rica
500 { 714, CAMERA_ANTIBANDING_60HZ }, // Panama
501 { 722, CAMERA_ANTIBANDING_50HZ }, // Argentina
502 { 724, CAMERA_ANTIBANDING_60HZ }, // Brazil
503 { 730, CAMERA_ANTIBANDING_50HZ }, // Chile
504 { 732, CAMERA_ANTIBANDING_60HZ }, // Colombia
505 { 734, CAMERA_ANTIBANDING_60HZ }, // Venezuela
506 { 736, CAMERA_ANTIBANDING_50HZ }, // Bolivia
507 { 738, CAMERA_ANTIBANDING_60HZ }, // Guyana
508 { 740, CAMERA_ANTIBANDING_60HZ }, // Ecuador
509 { 742, CAMERA_ANTIBANDING_50HZ }, // French Guiana
510 { 744, CAMERA_ANTIBANDING_50HZ }, // Paraguay
511 { 746, CAMERA_ANTIBANDING_60HZ }, // Suriname
512 { 748, CAMERA_ANTIBANDING_50HZ }, // Uruguay
513 { 750, CAMERA_ANTIBANDING_50HZ }, // Falkland Islands
514};
515
516#define country_number (sizeof(country_numeric) / sizeof(country_map))
517
518/* Look up pre-sorted antibanding_type table by current MCC. */
519static camera_antibanding_type camera_get_location(void) {
520 char value[PROP_VALUE_MAX];
521 char country_value[PROP_VALUE_MAX];
522 uint32_t country_code, count;
523 memset(value, 0x00, sizeof(value));
524 memset(country_value, 0x00, sizeof(country_value));
525 if (!__system_property_get("gsm.operator.numeric", value)) {
526 return CAMERA_ANTIBANDING_60HZ;
527 }
528 memcpy(country_value, value, 3);
529 country_code = atoi(country_value);
530 LOGD("value:%s, country value:%s, country code:%d\n",
531 value, country_value, country_code);
532 int left = 0;
533 int right = country_number - 1;
534 while (left <= right) {
535 int index = (left + right) >> 1;
536 if (country_numeric[index].country_code == country_code)
537 return country_numeric[index].type;
538 else if (country_numeric[index].country_code > country_code)
539 right = index - 1;
540 else
541 left = index + 1;
542 }
543 return CAMERA_ANTIBANDING_60HZ;
544}
545
546// from camera.h, led_mode_t
547static const str_map flash[] = {
548 { CameraParameters::FLASH_MODE_OFF, LED_MODE_OFF },
549 { CameraParameters::FLASH_MODE_AUTO, LED_MODE_AUTO },
550 { CameraParameters::FLASH_MODE_ON, LED_MODE_ON }
551};
552
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530553// from mm-camera/common/camera.h.
554static const str_map iso[] = {
555 { CameraParameters::ISO_AUTO, CAMERA_ISO_AUTO},
556 { CameraParameters::ISO_HJR, CAMERA_ISO_DEBLUR},
557 { CameraParameters::ISO_100, CAMERA_ISO_100},
558 { CameraParameters::ISO_200, CAMERA_ISO_200},
559 { CameraParameters::ISO_400, CAMERA_ISO_400},
560 { CameraParameters::ISO_800, CAMERA_ISO_800 }
561};
562
563
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800564#define DONT_CARE 0
565static const str_map focus_modes[] = {
Srinivasan Kannan71229622009-12-04 12:05:58 -0800566 { CameraParameters::FOCUS_MODE_AUTO, AF_MODE_AUTO},
567 { CameraParameters::FOCUS_MODE_INFINITY, DONT_CARE },
568 { CameraParameters::FOCUS_MODE_NORMAL, AF_MODE_NORMAL },
569 { CameraParameters::FOCUS_MODE_MACRO, AF_MODE_MACRO }
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800570};
571
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530572static const str_map lensshade[] = {
573 { CameraParameters::LENSSHADE_ENABLE, TRUE },
574 { CameraParameters::LENSSHADE_DISABLE, FALSE }
575};
576
Srinivasan Kannan71229622009-12-04 12:05:58 -0800577struct SensorType {
578 const char *name;
579 int rawPictureWidth;
580 int rawPictureHeight;
581 bool hasAutoFocusSupport;
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800582 int max_supported_snapshot_width;
583 int max_supported_snapshot_height;
Srinivasan Kannan71229622009-12-04 12:05:58 -0800584};
585
586static SensorType sensorTypes[] = {
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800587 { "5mp", 2608, 1960, true, 2592, 1944 },
588 { "3mp", 2064, 1544, false, 2048, 1536 },
589 { "2mp", 3200, 1200, false, 1600, 1200 } };
590
Srinivasan Kannan71229622009-12-04 12:05:58 -0800591
592static SensorType * sensorType;
593
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800594static const str_map picture_formats[] = {
595 {CameraParameters::PIXEL_FORMAT_JPEG, PICTURE_FORMAT_JPEG},
596 {CameraParameters::PIXEL_FORMAT_RAW, PICTURE_FORMAT_RAW}
597};
598
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800599static bool parameter_string_initialized = false;
600static String8 preview_size_values;
601static String8 picture_size_values;
602static String8 antibanding_values;
603static String8 effect_values;
Apurva Rajguru55562b02009-12-03 12:25:35 -0800604static String8 autoexposure_values;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800605static String8 whitebalance_values;
606static String8 flash_values;
607static String8 focus_mode_values;
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530608static String8 iso_values;
609static String8 lensshade_values;
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800610static String8 picture_format_values;
611
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800612
613static String8 create_sizes_str(const camera_size_type *sizes, int len) {
614 String8 str;
615 char buffer[32];
616
617 if (len > 0) {
618 sprintf(buffer, "%dx%d", sizes[0].width, sizes[0].height);
619 str.append(buffer);
620 }
621 for (int i = 1; i < len; i++) {
622 sprintf(buffer, ",%dx%d", sizes[i].width, sizes[i].height);
623 str.append(buffer);
624 }
625 return str;
626}
627
628static String8 create_values_str(const str_map *values, int len) {
629 String8 str;
630
631 if (len > 0) {
632 str.append(values[0].desc);
633 }
634 for (int i = 1; i < len; i++) {
635 str.append(",");
636 str.append(values[i].desc);
637 }
638 return str;
639}
640
Sravankb4f5f1c2010-01-21 11:06:17 +0530641extern "C" {
642//------------------------------------------------------------------------
643// : 720p busyQ funcitons
644// --------------------------------------------------------------------
645static struct fifo_queue g_busy_frame_queue =
646 {0, 0, 0, PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER};
647};
648/*===========================================================================
649 * FUNCTION cam_frame_wait_video
650 *
651 * DESCRIPTION this function waits a video in the busy queue
652 * ===========================================================================*/
653
654static void cam_frame_wait_video (void)
655{
656 LOGV("cam_frame_wait_video E ");
657 if ((g_busy_frame_queue.num_of_frames) <=0){
658 pthread_cond_wait(&(g_busy_frame_queue.wait), &(g_busy_frame_queue.mut));
659 }
660 LOGV("cam_frame_wait_video X");
661 return;
662}
663
664/*===========================================================================
665 * FUNCTION cam_frame_flush_video
666 *
667 * DESCRIPTION this function deletes all the buffers in busy queue
668 * ===========================================================================*/
669void cam_frame_flush_video (void)
670{
671 LOGV("cam_frame_flush_video: in n = %d\n", g_busy_frame_queue.num_of_frames);
672 pthread_mutex_lock(&(g_busy_frame_queue.mut));
673
674 while (g_busy_frame_queue.front)
675 {
676 //dequeue from the busy queue
677 struct fifo_node *node = dequeue (&g_busy_frame_queue);
678 if(node)
679 free(node);
680
681 LOGV("cam_frame_flush_video: node \n");
682 }
683 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
684 LOGV("cam_frame_flush_video: out n = %d\n", g_busy_frame_queue.num_of_frames);
685 return ;
686}
687/*===========================================================================
688 * FUNCTION cam_frame_get_video
689 *
690 * DESCRIPTION this function returns a video frame from the head
691 * ===========================================================================*/
692static struct msm_frame * cam_frame_get_video()
693{
694 struct msm_frame *p = NULL;
695 LOGV("cam_frame_get_video... in\n");
696 LOGV("cam_frame_get_video... got lock\n");
697 if (g_busy_frame_queue.front)
698 {
699 //dequeue
700 struct fifo_node *node = dequeue (&g_busy_frame_queue);
701 if (node)
702 {
703 p = (struct msm_frame *)node->f;
704 free (node);
705 }
706 LOGV("cam_frame_get_video... out = %x\n", p->buffer);
707 }
708 return p;
709}
710
711/*===========================================================================
712 * FUNCTION cam_frame_post_video
713 *
714 * DESCRIPTION this function add a busy video frame to the busy queue tails
715 * ===========================================================================*/
716static void cam_frame_post_video (struct msm_frame *p)
717{
718 if (!p)
719 {
720 LOGE("post video , buffer is null");
721 return;
722 }
723 LOGV("cam_frame_post_video... in = %x\n", (unsigned int)(p->buffer));
724 pthread_mutex_lock(&(g_busy_frame_queue.mut));
725 LOGV("post_video got lock. q count before enQ %d", g_busy_frame_queue.num_of_frames);
726 //enqueue to busy queue
727 struct fifo_node *node = (struct fifo_node *)malloc (sizeof (struct fifo_node));
728 if (node)
729 {
730 LOGV(" post video , enqueing in busy queue");
731 node->f = p;
732 node->next = NULL;
733 enqueue (&g_busy_frame_queue, node);
734 LOGV("post_video got lock. q count after enQ %d", g_busy_frame_queue.num_of_frames);
735 }
736 else
737 {
738 LOGE("cam_frame_post_video error... out of memory\n");
739 }
740
741 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
742 pthread_cond_signal(&(g_busy_frame_queue.wait));
743
744 LOGV("cam_frame_post_video... out = %x\n", p->buffer);
745
746 return;
747}
748
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -0800749void QualcommCameraHardware::storeTargetType(void) {
750 char mDeviceName[PROPERTY_VALUE_MAX];
751 property_get("ro.product.device",mDeviceName," ");
752 mCurrentTarget = TARGET_MAX;
753 for( int i = 0; i < TARGET_MAX ; i++) {
754 if( !strncmp(mDeviceName, targetList[i].targetStr, 7)) {
755 mCurrentTarget = targetList[i].targetEnum;
756 break;
757 }
758 }
759 LOGV(" Storing the current target type as %d ", mCurrentTarget );
760 return;
761}
762
Sravankb4f5f1c2010-01-21 11:06:17 +0530763//-------------------------------------------------------------------------------------
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800764static Mutex singleton_lock;
765static bool singleton_releasing;
766static Condition singleton_wait;
767
768static void receive_camframe_callback(struct msm_frame *frame);
Sravankb4f5f1c2010-01-21 11:06:17 +0530769static void receive_camframe_video_callback(struct msm_frame *frame); // 720p
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800770static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size);
771static void receive_jpeg_callback(jpeg_event_t status);
772static void receive_shutter_callback(common_crop_t *crop);
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800773static void receive_camframetimeout_callback(void);
Mohan Kandra284966d2010-01-05 13:39:15 -0800774static int fb_fd = -1;
775static int32_t mMaxZoom = 0;
776static bool native_get_maxzoom(int camfd, void *pZm);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800777
Mohan Kandrad9efed92010-01-15 19:08:39 -0800778static int dstOffset = 0;
779
780/* When using MDP zoom, double the preview buffers. The usage of these
781 * buffers is as follows:
782 * 1. As all the buffers comes under a single FD, and at initial registration,
783 * this FD will be passed to surface flinger, surface flinger can have access
784 * to all the buffers when needed.
785 * 2. Only "kPreviewBufferCount" buffers (SrcSet) will be registered with the
786 * camera driver to receive preview frames. The remaining buffers (DstSet),
787 * will be used at HAL and by surface flinger only when crop information
788 * is present in the frame.
789 * 3. When there is no crop information, there will be no call to MDP zoom,
790 * and the buffers in SrcSet will be passed to surface flinger to display.
791 * 4. With crop information present, MDP zoom will be called, and the final
792 * data will be placed in a buffer from DstSet, and this buffer will be given
793 * to surface flinger to display.
794 */
795#define NUM_MORE_BUFS 2
796
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800797QualcommCameraHardware::QualcommCameraHardware()
798 : mParameters(),
799 mCameraRunning(false),
800 mPreviewInitialized(false),
801 mFrameThreadRunning(false),
Mohan Kandra156d0ac2010-01-25 16:59:17 -0800802 mVideoThreadRunning(false),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800803 mSnapshotThreadRunning(false),
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800804 mSnapshotFormat(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800805 mReleasedRecordingFrame(false),
806 mPreviewFrameSize(0),
807 mRawSize(0),
808 mCameraControlFd(-1),
809 mAutoFocusThreadRunning(false),
810 mAutoFocusFd(-1),
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800811 mBrightness(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800812 mInPreviewCallback(false),
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800813 mUseOverlay(0),
814 mOverlay(0),
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800815 mMsgEnabled(0),
816 mNotifyCallback(0),
817 mDataCallback(0),
818 mDataCallbackTimestamp(0),
Mohan Kandra740cfce2010-01-07 12:58:24 -0800819 mCallbackCookie(0),
820 mDebugFps(0)
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800821{
822 memset(&mDimension, 0, sizeof(mDimension));
823 memset(&mCrop, 0, sizeof(mCrop));
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -0800824 memset(&zoomCropInfo, 0, sizeof(zoom_crop_info));
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -0800825 storeTargetType();
Mohan Kandra740cfce2010-01-07 12:58:24 -0800826 char value[PROPERTY_VALUE_MAX];
827 property_get("persist.debug.sf.showfps", value, "0");
828 mDebugFps = atoi(value);
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -0800829 if( mCurrentTarget == TARGET_MSM7630 )
Sravankb4f5f1c2010-01-21 11:06:17 +0530830 kPreviewBufferCountActual = kPreviewBufferCount;
831 else
832 kPreviewBufferCountActual = kPreviewBufferCount + NUM_MORE_BUFS;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800833 LOGV("constructor EX");
834}
835
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800836
837//filter Picture sizes based on max width and height
838void QualcommCameraHardware::filterPictureSizes(){
839 int i;
840 for(i=0;i<PICTURE_SIZE_COUNT;i++){
841 if(((picture_sizes[i].width <=
842 sensorType->max_supported_snapshot_width) &&
843 (picture_sizes[i].height <=
844 sensorType->max_supported_snapshot_height))){
845 picture_sizes_ptr = picture_sizes + i;
846 supportedPictureSizesCount = PICTURE_SIZE_COUNT - i ;
847 return ;
848 }
849 }
850}
851
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800852void QualcommCameraHardware::initDefaultParameters()
853{
854 LOGV("initDefaultParameters E");
855
856 // Initialize constant parameter strings. This will happen only once in the
857 // lifetime of the mediaserver process.
858 if (!parameter_string_initialized) {
Srinivasan Kannan71229622009-12-04 12:05:58 -0800859 findSensorType();
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800860 antibanding_values = create_values_str(
861 antibanding, sizeof(antibanding) / sizeof(str_map));
862 effect_values = create_values_str(
863 effects, sizeof(effects) / sizeof(str_map));
Apurva Rajguru55562b02009-12-03 12:25:35 -0800864 autoexposure_values = create_values_str(
865 autoexposure, sizeof(autoexposure) / sizeof(str_map));
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800866 whitebalance_values = create_values_str(
867 whitebalance, sizeof(whitebalance) / sizeof(str_map));
868 preview_size_values = create_sizes_str(
869 preview_sizes, PREVIEW_SIZE_COUNT);
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800870 //filter picture sizes
871 filterPictureSizes();
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800872 picture_size_values = create_sizes_str(
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -0800873 picture_sizes_ptr, supportedPictureSizesCount);
874
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800875 flash_values = create_values_str(
876 flash, sizeof(flash) / sizeof(str_map));
Srinivasan Kannan71229622009-12-04 12:05:58 -0800877 if(sensorType->hasAutoFocusSupport){
878 focus_mode_values = create_values_str(
879 focus_modes, sizeof(focus_modes) / sizeof(str_map));
880 }
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530881 iso_values = create_values_str(
882 iso,sizeof(iso)/sizeof(str_map));
883 lensshade_values = create_values_str(
884 lensshade,sizeof(lensshade)/sizeof(str_map));
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800885 picture_format_values = create_values_str(
886 picture_formats, sizeof(picture_formats)/sizeof(str_map));
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800887 parameter_string_initialized = true;
888 }
889
890 const camera_size_type *ps = &preview_sizes[DEFAULT_PREVIEW_SETTING];
891 mParameters.setPreviewSize(ps->width, ps->height);
892 mDimension.display_width = ps->width;
893 mDimension.display_height = ps->height;
894 mParameters.setPreviewFrameRate(15);
895 mParameters.setPreviewFormat("yuv420sp"); // informative
896
897 mParameters.setPictureSize(DEFAULT_PICTURE_WIDTH, DEFAULT_PICTURE_HEIGHT);
898 mParameters.setPictureFormat("jpeg"); // informative
899
900 mParameters.set(CameraParameters::KEY_JPEG_QUALITY, "100"); // max quality
901 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH,
902 THUMBNAIL_WIDTH_STR); // informative
903 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT,
904 THUMBNAIL_HEIGHT_STR); // informative
Srinivasan Kannan80d878f2009-12-18 15:06:02 -0800905 mDimension.ui_thumbnail_width =
906 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].width;
907 mDimension.ui_thumbnail_height =
908 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height;
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800909 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, "90");
910
911 mParameters.set(CameraParameters::KEY_ANTIBANDING,
912 CameraParameters::ANTIBANDING_AUTO);
913 mParameters.set(CameraParameters::KEY_EFFECT,
914 CameraParameters::EFFECT_NONE);
Apurva Rajguru55562b02009-12-03 12:25:35 -0800915 mParameters.set(CameraParameters::KEY_AUTO_EXPOSURE,
916 CameraParameters::AUTO_EXPOSURE_FRAME_AVG);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800917 mParameters.set(CameraParameters::KEY_WHITE_BALANCE,
918 CameraParameters::WHITE_BALANCE_AUTO);
919 mParameters.set(CameraParameters::KEY_FOCUS_MODE,
920 CameraParameters::FOCUS_MODE_AUTO);
Priya Komarlingam044c7b52010-01-22 18:21:23 -0800921 mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS,
922 "yuv420sp");
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800923
924 mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES,
925 preview_size_values.string());
926 mParameters.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES,
927 picture_size_values.string());
928 mParameters.set(CameraParameters::KEY_SUPPORTED_ANTIBANDING,
929 antibanding_values);
930 mParameters.set(CameraParameters::KEY_SUPPORTED_EFFECTS, effect_values);
Apurva Rajguru55562b02009-12-03 12:25:35 -0800931 mParameters.set(CameraParameters::KEY_SUPPORTED_AUTO_EXPOSURE, autoexposure_values);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800932 mParameters.set(CameraParameters::KEY_SUPPORTED_WHITE_BALANCE,
933 whitebalance_values);
934 mParameters.set(CameraParameters::KEY_SUPPORTED_FOCUS_MODES,
935 focus_mode_values);
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800936 mParameters.set(CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS,
937 picture_format_values);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800938
939 if (mSensorInfo.flash_enabled) {
940 mParameters.set(CameraParameters::KEY_FLASH_MODE,
941 CameraParameters::FLASH_MODE_OFF);
942 mParameters.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES,
943 flash_values);
944 }
945
Srinivasan Kannanbddfd502010-01-03 17:27:36 -0800946 mParameters.set(CameraParameters::KEY_MAX_SHARPNESS,
947 CAMERA_MAX_SHARPNESS);
948 mParameters.set(CameraParameters::KEY_MAX_CONTRAST,
949 CAMERA_MAX_CONTRAST);
950 mParameters.set(CameraParameters::KEY_MAX_SATURATION,
951 CAMERA_MAX_SATURATION);
952
Apurva Rajguru07185952010-01-22 15:40:07 -0800953 mParameters.set("luma-adaptation", "3");
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800954 mParameters.set("zoom-supported", "true");
955 mParameters.set("max-zoom", MAX_ZOOM_LEVEL);
956 mParameters.set("zoom", 0);
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -0800957 mParameters.set(CameraParameters::KEY_PICTURE_FORMAT,
958 CameraParameters::PIXEL_FORMAT_JPEG);
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800959
Kiran Kumar H N595970b2010-01-12 10:41:09 -0800960 mParameters.set(CameraParameters::KEY_SHARPNESS,
961 CAMERA_DEF_SHARPNESS);
962 mParameters.set(CameraParameters::KEY_CONTRAST,
963 CAMERA_DEF_CONTRAST);
964 mParameters.set(CameraParameters::KEY_SATURATION,
965 CAMERA_DEF_SATURATION);
966
Nishant Panditc8c1ee72009-12-03 16:24:02 +0530967 mParameters.set(CameraParameters::KEY_ISO_MODE,
968 CameraParameters::ISO_AUTO);
969 mParameters.set(CameraParameters::KEY_LENSSHADE,
970 CameraParameters::LENSSHADE_ENABLE);
971 mParameters.set(CameraParameters::KEY_SUPPORTED_ISO_MODES,
972 iso_values);
973 mParameters.set(CameraParameters::KEY_SUPPORTED_LENSSHADE_MODES,
974 lensshade_values);
975
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800976 if (setParameters(mParameters) != NO_ERROR) {
977 LOGE("Failed to set default parameters?!");
978 }
979
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -0800980 mUseOverlay = useOverlay();
981
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800982 /* Initialize the camframe_timeout_flag*/
983 Mutex::Autolock l(&mCamframeTimeoutLock);
984 camframe_timeout_flag = FALSE;
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -0800985 mPostViewHeap = NULL;
Kiran Kumar H N215cac42009-12-08 01:53:46 -0800986
Priya Komarlingamb85535d2009-11-30 13:06:01 -0800987 LOGV("initDefaultParameters X");
988}
989
Srinivasan Kannan71229622009-12-04 12:05:58 -0800990void QualcommCameraHardware::findSensorType(){
991 mDimension.picture_width = DEFAULT_PICTURE_WIDTH;
992 mDimension.picture_height = DEFAULT_PICTURE_HEIGHT;
993 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
994 sizeof(cam_ctrl_dimension_t), &mDimension);
995 if (ret) {
996 unsigned int i;
997 for (i = 0; i < sizeof(sensorTypes) / sizeof(SensorType); i++) {
998 if (sensorTypes[i].rawPictureHeight
999 == mDimension.raw_picture_height) {
1000 sensorType = sensorTypes + i;
1001 return;
1002 }
1003 }
1004 }
1005 //default to 5 mp
1006 sensorType = sensorTypes;
1007 return;
1008}
1009
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001010#define ROUND_TO_PAGE(x) (((x)+0xfff)&~0xfff)
1011
1012bool QualcommCameraHardware::startCamera()
1013{
1014 LOGV("startCamera E");
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08001015 if( mCurrentTarget == TARGET_MAX ) {
1016 LOGE(" Unable to determine the target type. Camera will not work ");
1017 return false;
1018 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001019#if DLOPEN_LIBMMCAMERA
1020 libmmcamera = ::dlopen("liboemcamera.so", RTLD_NOW);
1021 LOGV("loading liboemcamera at %p", libmmcamera);
1022 if (!libmmcamera) {
1023 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
1024 return false;
1025 }
1026
1027 *(void **)&LINK_cam_frame =
1028 ::dlsym(libmmcamera, "cam_frame");
1029 *(void **)&LINK_camframe_terminate =
1030 ::dlsym(libmmcamera, "camframe_terminate");
1031
1032 *(void **)&LINK_jpeg_encoder_init =
1033 ::dlsym(libmmcamera, "jpeg_encoder_init");
1034
1035 *(void **)&LINK_jpeg_encoder_encode =
1036 ::dlsym(libmmcamera, "jpeg_encoder_encode");
1037
1038 *(void **)&LINK_jpeg_encoder_join =
1039 ::dlsym(libmmcamera, "jpeg_encoder_join");
1040
1041 *(void **)&LINK_mmcamera_camframe_callback =
1042 ::dlsym(libmmcamera, "mmcamera_camframe_callback");
1043
1044 *LINK_mmcamera_camframe_callback = receive_camframe_callback;
1045
1046 *(void **)&LINK_mmcamera_jpegfragment_callback =
1047 ::dlsym(libmmcamera, "mmcamera_jpegfragment_callback");
1048
1049 *LINK_mmcamera_jpegfragment_callback = receive_jpeg_fragment_callback;
1050
1051 *(void **)&LINK_mmcamera_jpeg_callback =
1052 ::dlsym(libmmcamera, "mmcamera_jpeg_callback");
1053
1054 *LINK_mmcamera_jpeg_callback = receive_jpeg_callback;
1055
Kiran Kumar H N215cac42009-12-08 01:53:46 -08001056 *(void **)&LINK_camframe_timeout_callback =
1057 ::dlsym(libmmcamera, "camframe_timeout_callback");
1058
1059 *LINK_camframe_timeout_callback = receive_camframetimeout_callback;
1060
Sravankb4f5f1c2010-01-21 11:06:17 +05301061 // 720 p new recording functions
1062 *(void **)&LINK_cam_frame_flush_free_video = ::dlsym(libmmcamera, "cam_frame_flush_free_video");
1063
1064 *(void **)&LINK_camframe_free_video = ::dlsym(libmmcamera, "cam_frame_add_free_video");
1065
1066 *(void **)&LINK_camframe_video_callback = ::dlsym(libmmcamera, "mmcamera_camframe_videocallback");
1067 *LINK_camframe_video_callback = receive_camframe_video_callback;
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001068/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001069 *(void **)&LINK_mmcamera_shutter_callback =
1070 ::dlsym(libmmcamera, "mmcamera_shutter_callback");
1071
1072 *LINK_mmcamera_shutter_callback = receive_shutter_callback;
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001073*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001074 *(void**)&LINK_jpeg_encoder_setMainImageQuality =
1075 ::dlsym(libmmcamera, "jpeg_encoder_setMainImageQuality");
Kiran Kumar H N8861f302010-01-05 12:01:41 -08001076
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001077 *(void**)&LINK_jpeg_encoder_setThumbnailQuality =
1078 ::dlsym(libmmcamera, "jpeg_encoder_setThumbnailQuality");
1079
1080 *(void**)&LINK_jpeg_encoder_setRotation =
1081 ::dlsym(libmmcamera, "jpeg_encoder_setRotation");
1082
Kiran Kumar H N8861f302010-01-05 12:01:41 -08001083/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001084 *(void**)&LINK_jpeg_encoder_setLocation =
1085 ::dlsym(libmmcamera, "jpeg_encoder_setLocation");
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001086*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001087 *(void **)&LINK_cam_conf =
1088 ::dlsym(libmmcamera, "cam_conf");
1089
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001090/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001091 *(void **)&LINK_default_sensor_get_snapshot_sizes =
1092 ::dlsym(libmmcamera, "default_sensor_get_snapshot_sizes");
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001093*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001094 *(void **)&LINK_launch_cam_conf_thread =
1095 ::dlsym(libmmcamera, "launch_cam_conf_thread");
1096
1097 *(void **)&LINK_release_cam_conf_thread =
1098 ::dlsym(libmmcamera, "release_cam_conf_thread");
1099
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001100/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001101 *(void **)&LINK_zoom_crop_upscale =
1102 ::dlsym(libmmcamera, "zoom_crop_upscale");
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001103*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001104
1105#else
1106 mmcamera_camframe_callback = receive_camframe_callback;
1107 mmcamera_jpegfragment_callback = receive_jpeg_fragment_callback;
1108 mmcamera_jpeg_callback = receive_jpeg_callback;
1109 mmcamera_shutter_callback = receive_shutter_callback;
1110#endif // DLOPEN_LIBMMCAMERA
1111
1112 /* The control thread is in libcamera itself. */
1113 mCameraControlFd = open(MSM_CAMERA_CONTROL, O_RDWR);
Kiran Kumar H N585bc362010-01-19 13:04:44 -08001114 if (mCameraControlFd < 0) {
1115 LOGE("startCamera X: %s open failed: %s!",
1116 MSM_CAMERA_CONTROL,
1117 strerror(errno));
1118 return false;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001119 }
1120
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08001121 if( mCurrentTarget != TARGET_MSM7630 ){
Mohan Kandra284966d2010-01-05 13:39:15 -08001122 fb_fd = open("/dev/graphics/fb0", O_RDWR);
1123 if (fb_fd < 0) {
1124 LOGE("startCamera: fb0 open failed: %s!", strerror(errno));
1125 return FALSE;
1126 }
1127 }
1128
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001129 /* This will block until the control thread is launched. After that, sensor
1130 * information becomes available.
1131 */
1132
1133 if (LINK_launch_cam_conf_thread()) {
1134 LOGE("failed to launch the camera config thread");
1135 return false;
1136 }
1137
1138 memset(&mSensorInfo, 0, sizeof(mSensorInfo));
1139 if (ioctl(mCameraControlFd,
1140 MSM_CAM_IOCTL_GET_SENSOR_INFO,
1141 &mSensorInfo) < 0)
1142 LOGW("%s: cannot retrieve sensor info!", __FUNCTION__);
1143 else
1144 LOGI("%s: camsensor name %s, flash %d", __FUNCTION__,
1145 mSensorInfo.name, mSensorInfo.flash_enabled);
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001146/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001147 picture_sizes = LINK_default_sensor_get_snapshot_sizes(&PICTURE_SIZE_COUNT);
1148 if (!picture_sizes || !PICTURE_SIZE_COUNT) {
1149 LOGE("startCamera X: could not get snapshot sizes");
1150 return false;
1151 }
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001152*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001153 LOGV("startCamera X");
1154 return true;
1155}
1156
1157status_t QualcommCameraHardware::dump(int fd,
1158 const Vector<String16>& args) const
1159{
1160 const size_t SIZE = 256;
1161 char buffer[SIZE];
1162 String8 result;
1163
1164 // Dump internal primitives.
1165 result.append("QualcommCameraHardware::dump");
1166 snprintf(buffer, 255, "mMsgEnabled (%d)\n", mMsgEnabled);
1167 result.append(buffer);
1168 int width, height;
1169 mParameters.getPreviewSize(&width, &height);
1170 snprintf(buffer, 255, "preview width(%d) x height (%d)\n", width, height);
1171 result.append(buffer);
1172 mParameters.getPictureSize(&width, &height);
1173 snprintf(buffer, 255, "raw width(%d) x height (%d)\n", width, height);
1174 result.append(buffer);
1175 snprintf(buffer, 255,
1176 "preview frame size(%d), raw size (%d), jpeg size (%d) "
1177 "and jpeg max size (%d)\n", mPreviewFrameSize, mRawSize,
1178 mJpegSize, mJpegMaxSize);
1179 result.append(buffer);
1180 write(fd, result.string(), result.size());
1181
1182 // Dump internal objects.
Mohan Kandrad9efed92010-01-15 19:08:39 -08001183 if (mPreviewHeap != 0) {
1184 mPreviewHeap->dump(fd, args);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001185 }
1186 if (mRawHeap != 0) {
1187 mRawHeap->dump(fd, args);
1188 }
1189 if (mJpegHeap != 0) {
1190 mJpegHeap->dump(fd, args);
1191 }
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001192 if(mRawSnapshotAshmemHeap != 0 ){
1193 mRawSnapshotAshmemHeap->dump(fd, args);
1194 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001195 mParameters.dump(fd, args);
1196 return NO_ERROR;
1197}
1198
Mohan Kandra284966d2010-01-05 13:39:15 -08001199static bool native_get_maxzoom(int camfd, void *pZm)
1200{
1201 LOGV("native_get_maxzoom E");
1202
1203 struct msm_ctrl_cmd ctrlCmd;
1204 int32_t *pZoom = (int32_t *)pZm;
1205
1206 ctrlCmd.type = CAMERA_GET_PARM_MAXZOOM;
1207 ctrlCmd.timeout_ms = 5000;
1208 ctrlCmd.length = sizeof(int32_t);
1209 ctrlCmd.value = pZoom;
1210 ctrlCmd.resp_fd = camfd;
1211
1212 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1213 LOGE("native_get_maxzoom: ioctl fd %d error %s",
1214 camfd,
1215 strerror(errno));
1216 return false;
1217 }
1218 LOGE("ctrlCmd.value = %d", *(int32_t *)ctrlCmd.value);
1219 memcpy(pZoom, (int32_t *)ctrlCmd.value, sizeof(int32_t));
1220
1221 LOGV("native_get_maxzoom X");
1222 return true;
1223}
1224
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001225static bool native_set_afmode(int camfd, isp3a_af_mode_t af_type)
1226{
1227 int rc;
1228 struct msm_ctrl_cmd ctrlCmd;
1229
1230 ctrlCmd.timeout_ms = 5000;
1231 ctrlCmd.type = CAMERA_SET_PARM_AUTO_FOCUS;
1232 ctrlCmd.length = sizeof(af_type);
1233 ctrlCmd.value = &af_type;
1234 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1235
1236 if ((rc = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0)
1237 LOGE("native_set_afmode: ioctl fd %d error %s\n",
1238 camfd,
1239 strerror(errno));
1240
1241 LOGV("native_set_afmode: ctrlCmd.status == %d\n", ctrlCmd.status);
1242 return rc >= 0 && ctrlCmd.status == CAMERA_EXIT_CB_DONE;
1243}
1244
1245static bool native_cancel_afmode(int camfd, int af_fd)
1246{
1247 int rc;
1248 struct msm_ctrl_cmd ctrlCmd;
1249
1250 ctrlCmd.timeout_ms = 0;
1251 ctrlCmd.type = CAMERA_AUTO_FOCUS_CANCEL;
1252 ctrlCmd.length = 0;
1253 ctrlCmd.value = NULL;
1254 ctrlCmd.resp_fd = -1; // there's no response fd
1255
1256 if ((rc = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND_2, &ctrlCmd)) < 0)
1257 {
1258 LOGE("native_cancel_afmode: ioctl fd %d error %s\n",
1259 camfd,
1260 strerror(errno));
1261 return false;
1262 }
1263
1264 return true;
1265}
1266
1267static bool native_start_preview(int camfd)
1268{
1269 struct msm_ctrl_cmd ctrlCmd;
1270
1271 ctrlCmd.timeout_ms = 5000;
1272 ctrlCmd.type = CAMERA_START_PREVIEW;
1273 ctrlCmd.length = 0;
1274 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1275
1276 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1277 LOGE("native_start_preview: MSM_CAM_IOCTL_CTRL_COMMAND fd %d error %s",
1278 camfd,
1279 strerror(errno));
1280 return false;
1281 }
1282
1283 return true;
1284}
1285
1286static bool native_get_picture (int camfd, common_crop_t *crop)
1287{
1288 struct msm_ctrl_cmd ctrlCmd;
1289
1290 ctrlCmd.timeout_ms = 5000;
1291 ctrlCmd.length = sizeof(common_crop_t);
1292 ctrlCmd.value = crop;
1293
1294 if(ioctl(camfd, MSM_CAM_IOCTL_GET_PICTURE, &ctrlCmd) < 0) {
1295 LOGE("native_get_picture: MSM_CAM_IOCTL_GET_PICTURE fd %d error %s",
1296 camfd,
1297 strerror(errno));
1298 return false;
1299 }
1300
1301 LOGV("crop: in1_w %d", crop->in1_w);
1302 LOGV("crop: in1_h %d", crop->in1_h);
1303 LOGV("crop: out1_w %d", crop->out1_w);
1304 LOGV("crop: out1_h %d", crop->out1_h);
1305
1306 LOGV("crop: in2_w %d", crop->in2_w);
1307 LOGV("crop: in2_h %d", crop->in2_h);
1308 LOGV("crop: out2_w %d", crop->out2_w);
1309 LOGV("crop: out2_h %d", crop->out2_h);
1310
1311 LOGV("crop: update %d", crop->update_flag);
1312
1313 return true;
1314}
1315
1316static bool native_stop_preview(int camfd)
1317{
1318 struct msm_ctrl_cmd ctrlCmd;
1319 ctrlCmd.timeout_ms = 5000;
1320 ctrlCmd.type = CAMERA_STOP_PREVIEW;
1321 ctrlCmd.length = 0;
1322 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1323
1324 if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1325 LOGE("native_stop_preview: ioctl fd %d error %s",
1326 camfd,
1327 strerror(errno));
1328 return false;
1329 }
1330
1331 return true;
1332}
1333
1334static bool native_prepare_snapshot(int camfd)
1335{
1336 int ioctlRetVal = true;
1337 struct msm_ctrl_cmd ctrlCmd;
1338
1339 ctrlCmd.timeout_ms = 1000;
1340 ctrlCmd.type = CAMERA_PREPARE_SNAPSHOT;
1341 ctrlCmd.length = 0;
1342 ctrlCmd.value = NULL;
1343 ctrlCmd.resp_fd = camfd;
1344
1345 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1346 LOGE("native_prepare_snapshot: ioctl fd %d error %s",
1347 camfd,
1348 strerror(errno));
1349 return false;
1350 }
1351 return true;
1352}
1353
1354static bool native_start_snapshot(int camfd)
1355{
1356 struct msm_ctrl_cmd ctrlCmd;
1357
1358 ctrlCmd.timeout_ms = 5000;
1359 ctrlCmd.type = CAMERA_START_SNAPSHOT;
1360 ctrlCmd.length = 0;
1361 ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
1362
1363 if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
1364 LOGE("native_start_snapshot: ioctl fd %d error %s",
1365 camfd,
1366 strerror(errno));
1367 return false;
1368 }
1369
1370 return true;
1371}
1372
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08001373static bool native_start_raw_snapshot(int camfd)
1374{
1375 int ret;
1376 struct msm_ctrl_cmd ctrlCmd;
1377
1378 ctrlCmd.timeout_ms = 1000;
1379 ctrlCmd.type = CAMERA_START_RAW_SNAPSHOT;
1380 ctrlCmd.length = 0;
1381 ctrlCmd.value = NULL;
1382 ctrlCmd.resp_fd = camfd;
1383
1384 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1385 LOGE("native_start_raw_snapshot: ioctl failed. ioctl return value "\
1386 "is %d \n", ret);
1387 return false;
1388 }
1389 return true;
1390}
1391
1392
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001393static bool native_stop_snapshot (int camfd)
1394{
1395 struct msm_ctrl_cmd ctrlCmd;
1396
1397 ctrlCmd.timeout_ms = 0;
1398 ctrlCmd.type = CAMERA_STOP_SNAPSHOT;
1399 ctrlCmd.length = 0;
1400 ctrlCmd.resp_fd = -1;
1401
1402 if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND_2, &ctrlCmd) < 0) {
1403 LOGE("native_stop_snapshot: ioctl fd %d error %s",
1404 camfd,
1405 strerror(errno));
1406 return false;
1407 }
1408
1409 return true;
1410}
Sravankb4f5f1c2010-01-21 11:06:17 +05301411/*===========================================================================
1412 * FUNCTION - native_start_recording -
1413 *
1414 * DESCRIPTION:
1415 *==========================================================================*/
1416static bool native_start_recording(int camfd)
1417{
1418 int ret;
1419 struct msm_ctrl_cmd ctrlCmd;
1420
1421 ctrlCmd.timeout_ms = 1000;
1422 ctrlCmd.type = CAMERA_START_RECORDING;
1423 ctrlCmd.length = 0;
1424 ctrlCmd.value = NULL;
1425 ctrlCmd.resp_fd = camfd;
1426
1427 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1428 LOGE("native_start_recording: ioctl failed. ioctl return value "\
1429 "is %d \n", ret);
1430 return false;
1431 }
1432 LOGV("native_start_video: ioctl good. ioctl return value is %d \n",ret);
1433
1434 /* TODO: Check status of postprocessing if there is any,
1435 * PP status should be in ctrlCmd */
1436
1437 return true;
1438}
1439
1440/*===========================================================================
1441 * FUNCTION - native_stop_recording -
1442 *
1443 * DESCRIPTION:
1444 *==========================================================================*/
1445static bool native_stop_recording(int camfd)
1446{
1447 int ret;
1448 struct msm_ctrl_cmd ctrlCmd;
1449LOGE("in native_stop_recording ");
1450 ctrlCmd.timeout_ms = 1000;
1451 ctrlCmd.type = CAMERA_STOP_RECORDING;
1452 ctrlCmd.length = 0;
1453 ctrlCmd.value = NULL;
1454 ctrlCmd.resp_fd = camfd;
1455
1456 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1457 LOGE("native_stop_video: ioctl failed. ioctl return value is %d \n",
1458 ret);
1459 return false;
1460 }
1461 LOGV("in native_stop_recording returned %d", ret);
1462 return true;
1463}
1464/*===========================================================================
1465 * FUNCTION - native_start_video -
1466 *
1467 * DESCRIPTION:
1468 *==========================================================================*/
1469static bool native_start_video(int camfd)
1470{
1471 int ret;
1472 struct msm_ctrl_cmd ctrlCmd;
1473
1474 ctrlCmd.timeout_ms = 1000;
1475 ctrlCmd.type = CAMERA_START_VIDEO;
1476 ctrlCmd.length = 0;
1477 ctrlCmd.value = NULL;
1478 ctrlCmd.resp_fd = camfd;
1479
1480 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1481 LOGE("native_start_video: ioctl failed. ioctl return value is %d \n",
1482 ret);
1483 return false;
1484 }
1485
1486 /* TODO: Check status of postprocessing if there is any,
1487 * PP status should be in ctrlCmd */
1488
1489 return true;
1490}
1491
1492/*===========================================================================
1493 * FUNCTION - native_stop_video -
1494 *
1495 * DESCRIPTION:
1496 *==========================================================================*/
1497static bool native_stop_video(int camfd)
1498{
1499 int ret;
1500 struct msm_ctrl_cmd ctrlCmd;
1501
1502 ctrlCmd.timeout_ms = 1000;
1503 ctrlCmd.type = CAMERA_STOP_VIDEO;
1504 ctrlCmd.length = 0;
1505 ctrlCmd.value = NULL;
1506 ctrlCmd.resp_fd = camfd;
1507
1508 if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
1509 LOGE("native_stop_video: ioctl failed. ioctl return value is %d \n",
1510 ret);
1511 return false;
1512 }
1513
1514 return true;
1515}
1516/*==========================================================================*/
1517
1518static cam_frame_start_parms frame_parms;
1519static int recordingState = 0;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001520
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001521static rat_t latitude[3];
1522static rat_t longitude[3];
1523static char lonref[2];
1524static char latref[2];
1525static char dateTime[20];
1526static rat_t altitude;
1527
1528static void addExifTag(exif_tag_id_t tagid, exif_tag_type_t type,
1529 uint32_t count, uint8_t copy, void *data) {
1530
1531 if(exif_table_numEntries == MAX_EXIF_TABLE_ENTRIES) {
1532 LOGE("Number of entries exceeded limit");
1533 return;
1534 }
1535
1536 int index = exif_table_numEntries;
1537 exif_data[index].tag_id = tagid;
1538 exif_data[index].tag_entry.type = type;
1539 exif_data[index].tag_entry.count = count;
1540 exif_data[index].tag_entry.copy = copy;
1541 if((type == EXIF_RATIONAL) && (count > 1))
1542 exif_data[index].tag_entry.data._rats = (rat_t *)data;
1543 if((type == EXIF_RATIONAL) && (count == 1))
1544 exif_data[index].tag_entry.data._rat = *(rat_t *)data;
1545 else if(type == EXIF_ASCII)
1546 exif_data[index].tag_entry.data._ascii = (char *)data;
1547 else if(type == EXIF_BYTE)
1548 exif_data[index].tag_entry.data._byte = *(uint8_t *)data;
1549
1550 // Increase number of entries
1551 exif_table_numEntries++;
1552}
1553
1554static void parseLatLong(const char *latlonString, int *pDegrees,
1555 int *pMinutes, int *pSeconds ) {
1556
1557 double value = atof(latlonString);
1558 value = fabs(value);
1559 int degrees = (int) value;
1560
1561 double remainder = value - degrees;
1562 int minutes = (int) (remainder * 60);
1563 int seconds = (int) (((remainder * 60) - minutes) * 60 * 1000);
1564
1565 *pDegrees = degrees;
1566 *pMinutes = minutes;
1567 *pSeconds = seconds;
1568}
1569
1570static void setLatLon(exif_tag_id_t tag, const char *latlonString) {
1571
1572 int degrees, minutes, seconds;
1573
1574 parseLatLong(latlonString, &degrees, &minutes, &seconds);
1575
1576 rat_t value[3] = { {degrees, 1},
1577 {minutes, 1},
1578 {seconds, 1000} };
1579
1580 if(tag == EXIFTAGID_GPS_LATITUDE) {
1581 memcpy(latitude, value, sizeof(latitude));
1582 addExifTag(EXIFTAGID_GPS_LATITUDE, EXIF_RATIONAL, 3,
1583 1, (void *)latitude);
1584 } else {
1585 memcpy(longitude, value, sizeof(longitude));
1586 addExifTag(EXIFTAGID_GPS_LONGITUDE, EXIF_RATIONAL, 3,
1587 1, (void *)longitude);
1588 }
1589}
1590
1591void QualcommCameraHardware::setGpsParameters() {
1592 const char *str = NULL;
1593
1594 //Set Latitude
1595 str = mParameters.get(CameraParameters::KEY_GPS_LATITUDE);
1596 if(str != NULL) {
1597 setLatLon(EXIFTAGID_GPS_LATITUDE, str);
1598 //set Latitude Ref
1599 str = NULL;
1600 str = mParameters.get(CameraParameters::KEY_GPS_LATITUDE_REF);
1601 if(str != NULL) {
1602 strncpy(latref, str, 1);
1603 latref[1] = '\0';
1604 addExifTag(EXIFTAGID_GPS_LATITUDE_REF, EXIF_ASCII, 2,
1605 1, (void *)latref);
1606 }
1607 }
1608
1609 //set Longitude
1610 str = NULL;
1611 str = mParameters.get(CameraParameters::KEY_GPS_LONGITUDE);
1612 if(str != NULL) {
1613 setLatLon(EXIFTAGID_GPS_LONGITUDE, str);
1614 //set Longitude Ref
1615 str = NULL;
1616 str = mParameters.get(CameraParameters::KEY_GPS_LONGITUDE_REF);
1617 if(str != NULL) {
1618 strncpy(lonref, str, 1);
1619 lonref[1] = '\0';
1620 addExifTag(EXIFTAGID_GPS_LONGITUDE_REF, EXIF_ASCII, 2,
1621 1, (void *)lonref);
1622 }
1623 }
1624
1625 //set Altitude
1626 str = NULL;
1627 str = mParameters.get(CameraParameters::KEY_GPS_ALTITUDE);
1628 if(str != NULL) {
1629 int value = atoi(str);
1630 rat_t alt_value = {value, 1000};
1631 memcpy(&altitude, &alt_value, sizeof(altitude));
1632 addExifTag(EXIFTAGID_GPS_ALTITUDE, EXIF_RATIONAL, 1,
1633 1, (void *)&altitude);
1634 //set AltitudeRef
1635 int ref = mParameters.getInt(CameraParameters::KEY_GPS_ALTITUDE_REF);
1636 if( !(ref < 0 || ref > 1) )
1637 addExifTag(EXIFTAGID_GPS_ALTITUDE_REF, EXIF_BYTE, 1,
1638 1, (void *)&ref);
1639 }
1640
1641
1642}
1643
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001644bool QualcommCameraHardware::native_jpeg_encode(void)
1645{
1646 int jpeg_quality = mParameters.getInt("jpeg-quality");
1647 if (jpeg_quality >= 0) {
1648 LOGV("native_jpeg_encode, current jpeg main img quality =%d",
1649 jpeg_quality);
1650 if(!LINK_jpeg_encoder_setMainImageQuality(jpeg_quality)) {
1651 LOGE("native_jpeg_encode set jpeg-quality failed");
1652 return false;
1653 }
1654 }
1655
1656 int thumbnail_quality = mParameters.getInt("jpeg-thumbnail-quality");
1657 if (thumbnail_quality >= 0) {
1658 LOGV("native_jpeg_encode, current jpeg thumbnail quality =%d",
1659 thumbnail_quality);
1660 if(!LINK_jpeg_encoder_setThumbnailQuality(thumbnail_quality)) {
1661 LOGE("native_jpeg_encode set thumbnail-quality failed");
1662 return false;
1663 }
1664 }
1665
1666 int rotation = mParameters.getInt("rotation");
1667 if (rotation >= 0) {
1668 LOGV("native_jpeg_encode, rotation = %d", rotation);
1669 if(!LINK_jpeg_encoder_setRotation(rotation)) {
1670 LOGE("native_jpeg_encode set rotation failed");
1671 return false;
1672 }
1673 }
1674
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001675// jpeg_set_location();
1676 if(mParameters.getInt(CameraParameters::KEY_GPS_STATUS) == 1) {
1677 setGpsParameters();
1678 }
1679 //set TimeStamp
1680 const char *str = mParameters.get(CameraParameters::KEY_EXIF_DATETIME);
1681 if(str != NULL) {
1682 strncpy(dateTime, str, 19);
1683 dateTime[19] = '\0';
1684 addExifTag(EXIFTAGID_EXIF_DATE_TIME_ORIGINAL, EXIF_ASCII,
1685 20, 1, (void *)dateTime);
1686 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001687
1688 if (!LINK_jpeg_encoder_encode(&mDimension,
1689 (uint8_t *)mThumbnailHeap->mHeap->base(),
1690 mThumbnailHeap->mHeap->getHeapID(),
1691 (uint8_t *)mRawHeap->mHeap->base(),
1692 mRawHeap->mHeap->getHeapID(),
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08001693 &mCrop, exif_data, exif_table_numEntries)) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001694 LOGE("native_jpeg_encode: jpeg_encoder_encode failed.");
1695 return false;
1696 }
1697 return true;
1698}
1699
1700bool QualcommCameraHardware::native_set_parm(
1701 cam_ctrl_type type, uint16_t length, void *value)
1702{
1703 struct msm_ctrl_cmd ctrlCmd;
1704
1705 ctrlCmd.timeout_ms = 5000;
1706 ctrlCmd.type = (uint16_t)type;
1707 ctrlCmd.length = length;
1708 // FIXME: this will be put in by the kernel
1709 ctrlCmd.resp_fd = mCameraControlFd;
1710 ctrlCmd.value = value;
1711
1712 LOGV("%s: fd %d, type %d, length %d", __FUNCTION__,
1713 mCameraControlFd, type, length);
1714 if (ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0 ||
1715 ctrlCmd.status != CAM_CTRL_SUCCESS) {
1716 LOGE("%s: error (%s): fd %d, type %d, length %d, status %d",
1717 __FUNCTION__, strerror(errno),
1718 mCameraControlFd, type, length, ctrlCmd.status);
1719 return false;
1720 }
1721 return true;
1722}
1723
1724void QualcommCameraHardware::jpeg_set_location()
1725{
1726 bool encode_location = true;
1727 camera_position_type pt;
1728
1729#define PARSE_LOCATION(what,type,fmt,desc) do { \
1730 pt.what = 0; \
1731 const char *what##_str = mParameters.get("gps-"#what); \
1732 LOGV("GPS PARM %s --> [%s]", "gps-"#what, what##_str); \
1733 if (what##_str) { \
1734 type what = 0; \
1735 if (sscanf(what##_str, fmt, &what) == 1) \
1736 pt.what = what; \
1737 else { \
1738 LOGE("GPS " #what " %s could not" \
1739 " be parsed as a " #desc, what##_str); \
1740 encode_location = false; \
1741 } \
1742 } \
1743 else { \
1744 LOGV("GPS " #what " not specified: " \
1745 "defaulting to zero in EXIF header."); \
1746 encode_location = false; \
1747 } \
1748 } while(0)
1749
1750 PARSE_LOCATION(timestamp, long, "%ld", "long");
1751 if (!pt.timestamp) pt.timestamp = time(NULL);
1752 PARSE_LOCATION(altitude, short, "%hd", "short");
1753 PARSE_LOCATION(latitude, double, "%lf", "double float");
1754 PARSE_LOCATION(longitude, double, "%lf", "double float");
1755
1756#undef PARSE_LOCATION
1757
1758 if (encode_location) {
1759 LOGD("setting image location ALT %d LAT %lf LON %lf",
1760 pt.altitude, pt.latitude, pt.longitude);
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001761/* Disabling until support is available.
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001762 if (!LINK_jpeg_encoder_setLocation(&pt)) {
1763 LOGE("jpeg_set_location: LINK_jpeg_encoder_setLocation failed.");
1764 }
Apurva Rajguru1db0c392009-11-30 21:39:04 -08001765*/
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001766 }
1767 else LOGV("not setting image location");
1768}
1769
1770void QualcommCameraHardware::runFrameThread(void *data)
1771{
1772 LOGV("runFrameThread E");
1773
1774 int cnt;
1775
1776#if DLOPEN_LIBMMCAMERA
1777 // We need to maintain a reference to libqcamera.so for the duration of the
1778 // frame thread, because we do not know when it will exit relative to the
1779 // lifetime of this object. We do not want to dlclose() libqcamera while
1780 // LINK_cam_frame is still running.
1781 void *libhandle = ::dlopen("liboemcamera.so", RTLD_NOW);
1782 LOGV("FRAME: loading libqcamera at %p", libhandle);
1783 if (!libhandle) {
1784 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
1785 }
1786 if (libhandle)
1787#endif
1788 {
1789 LINK_cam_frame(data);
1790 }
1791
Mohan Kandrad9efed92010-01-15 19:08:39 -08001792 mPreviewHeap.clear();
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08001793 if( mCurrentTarget == TARGET_MSM7630 )
Sravankb4f5f1c2010-01-21 11:06:17 +05301794 mRecordHeap.clear();
1795
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001796#if DLOPEN_LIBMMCAMERA
1797 if (libhandle) {
1798 ::dlclose(libhandle);
1799 LOGV("FRAME: dlclose(libqcamera)");
1800 }
1801#endif
1802
1803 mFrameThreadWaitLock.lock();
1804 mFrameThreadRunning = false;
1805 mFrameThreadWait.signal();
1806 mFrameThreadWaitLock.unlock();
1807
1808 LOGV("runFrameThread X");
1809}
1810
Sravankb4f5f1c2010-01-21 11:06:17 +05301811void QualcommCameraHardware::runVideoThread(void *data)
1812{
1813 LOGD("runVideoThread E");
1814 msm_frame* vframe = NULL;
1815
1816 while(true) {
1817 pthread_mutex_lock(&(g_busy_frame_queue.mut));
1818
1819 LOGE("in video_thread : wait for video frame ");
1820 // check if any frames are available in busyQ and give callback to
1821 // services/video encoder
1822 cam_frame_wait_video();
1823 LOGV("video_thread, wait over..");
1824
1825 // Exit the thread , in case of stop recording..
1826 mVideoThreadWaitLock.lock();
1827 if(mVideoThreadExit){
1828 LOGE("Exiting video thread..");
1829 mVideoThreadWaitLock.unlock();
1830 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
1831 break;
1832 }
1833 mVideoThreadWaitLock.unlock();
1834
1835 // Get the video frame to be encoded
1836 vframe = cam_frame_get_video ();
1837 LOGV("in video_thread : got video frame ");
1838
1839 if(vframe != NULL) {
1840 // Find the offset within the heap of the current buffer.
1841 LOGV("Got video frame : buffer %d base %d ", vframe->buffer, mRecordHeap->mHeap->base());
1842 ssize_t offset =
1843 (ssize_t)vframe->buffer - (ssize_t)mRecordHeap->mHeap->base();
1844 LOGV("offset = %d , alignsize = %d , offset later = %d", offset, mRecordHeap->mAlignedBufferSize, (offset / mRecordHeap->mAlignedBufferSize));
1845
1846 offset /= mRecordHeap->mAlignedBufferSize;
1847
1848 // dump frames for test purpose
1849#ifdef DUMP_VIDEO_FRAMES
1850 static int frameCnt = 0;
1851 if (frameCnt >= 11 && frameCnt <= 13 ) {
1852 char buf[128];
1853 sprintf(buf, "/data/%d_v.yuv", frameCnt);
1854 int file_fd = open(buf, O_RDWR | O_CREAT, 0777);
1855 LOGV("dumping video frame %d", frameCnt);
1856 if (file_fd < 0) {
1857 LOGE("cannot open file\n");
1858 }
1859 else
1860 {
1861 write(file_fd, (const void *)vframe->buffer,
1862 vframe->cbcr_off * 3 / 2);
1863 }
1864 close(file_fd);
1865 }
1866 frameCnt++;
1867#endif
1868 // Enable IF block to give frames to encoder , ELSE block for just simulation
1869#if 1
1870 LOGV("in video_thread : got video frame, before if check giving frame to services/encoder");
1871 mCallbackLock.lock();
1872 int msgEnabled = mMsgEnabled;
1873 data_callback_timestamp rcb = mDataCallbackTimestamp;
1874 void *rdata = mCallbackCookie;
1875 mCallbackLock.unlock();
1876
1877 if(rcb != NULL && (msgEnabled & CAMERA_MSG_VIDEO_FRAME) ) {
1878 LOGV("in video_thread : got video frame, giving frame to services/encoder");
1879 rcb(systemTime(), CAMERA_MSG_VIDEO_FRAME, mRecordHeap->mBuffers[offset], rdata);
1880 Mutex::Autolock rLock(&mRecordFrameLock);
1881 if (mReleasedRecordingFrame != true) {
1882 LOGV("block waiting for frame release");
1883 mRecordWait.wait(mRecordFrameLock);
1884 LOGV("video frame released, continuing");
1885 }
1886 mReleasedRecordingFrame = false;
1887 }
1888#else
1889 // 720p output2 : simulate release frame here:
1890 LOGE("in video_thread simulation , releasing the video frame");
1891 LINK_camframe_free_video(vframe);
1892#endif
1893
1894 } else LOGE("in video_thread get frame returned null");
1895
1896 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
1897
1898 } // end of while loop
Mohan Kandra156d0ac2010-01-25 16:59:17 -08001899
1900 mVideoThreadWaitLock.lock();
1901 mVideoThreadRunning = false;
1902 mVideoThreadWait.signal();
1903 mVideoThreadWaitLock.unlock();
1904
Sravankb4f5f1c2010-01-21 11:06:17 +05301905 LOGV("runVideoThread X");
1906}
1907
1908void *video_thread(void *user)
1909{
1910 LOGV("video_thread E");
1911 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
1912 if (obj != 0) {
1913 obj->runVideoThread(user);
1914 }
1915 else LOGE("not starting video thread: the object went away!");
1916 LOGV("video_thread X");
1917 return NULL;
1918}
1919
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001920void *frame_thread(void *user)
1921{
1922 LOGD("frame_thread E");
1923 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
1924 if (obj != 0) {
1925 obj->runFrameThread(user);
1926 }
1927 else LOGW("not starting frame thread: the object went away!");
1928 LOGD("frame_thread X");
1929 return NULL;
1930}
1931
1932bool QualcommCameraHardware::initPreview()
1933{
1934 // See comments in deinitPreview() for why we have to wait for the frame
1935 // thread here, and why we can't use pthread_join().
Sravankb4f5f1c2010-01-21 11:06:17 +05301936 int videoWidth, videoHeight;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001937 mParameters.getPreviewSize(&previewWidth, &previewHeight);
Sravankb4f5f1c2010-01-21 11:06:17 +05301938
1939 videoWidth = previewWidth; // temporary , should be configurable later
1940 videoHeight = previewHeight;
1941 LOGV("initPreview E: preview size=%dx%d videosize = %d x %d", previewWidth, previewHeight, videoWidth, videoHeight );
1942
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08001943 if( mCurrentTarget == TARGET_MSM7630 ) {
Sravankb4f5f1c2010-01-21 11:06:17 +05301944 mDimension.video_width = videoWidth;
Kiran Kumar H N7ac84e32010-02-01 10:58:47 -08001945 mDimension.video_width = CEILING16(mDimension.video_width);
Sravankb4f5f1c2010-01-21 11:06:17 +05301946 mDimension.video_height = videoHeight;
1947 LOGV("initPreview : preview size=%dx%d videosize = %d x %d", previewWidth, previewHeight, mDimension.video_width, mDimension.video_height );
1948 }
1949
1950
Priya Komarlingamb85535d2009-11-30 13:06:01 -08001951 mFrameThreadWaitLock.lock();
1952 while (mFrameThreadRunning) {
1953 LOGV("initPreview: waiting for old frame thread to complete.");
1954 mFrameThreadWait.wait(mFrameThreadWaitLock);
1955 LOGV("initPreview: old frame thread completed.");
1956 }
1957 mFrameThreadWaitLock.unlock();
1958
1959 mSnapshotThreadWaitLock.lock();
1960 while (mSnapshotThreadRunning) {
1961 LOGV("initPreview: waiting for old snapshot thread to complete.");
1962 mSnapshotThreadWait.wait(mSnapshotThreadWaitLock);
1963 LOGV("initPreview: old snapshot thread completed.");
1964 }
1965 mSnapshotThreadWaitLock.unlock();
1966
1967 int cnt = 0;
1968 mPreviewFrameSize = previewWidth * previewHeight * 3/2;
Mohan Kandrad9efed92010-01-15 19:08:39 -08001969 dstOffset = 0;
1970 mPreviewHeap = new PmemPool("/dev/pmem_adsp",
Mohan Kandra284966d2010-01-05 13:39:15 -08001971 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
1972 mCameraControlFd,
Sravankb4f5f1c2010-01-21 11:06:17 +05301973 MSM_PMEM_PREVIEW, //MSM_PMEM_OUTPUT2,
Mohan Kandra284966d2010-01-05 13:39:15 -08001974 mPreviewFrameSize,
Mohan Kandrad9efed92010-01-15 19:08:39 -08001975 kPreviewBufferCountActual,
Mohan Kandra284966d2010-01-05 13:39:15 -08001976 mPreviewFrameSize,
Mohan Kandrad9efed92010-01-15 19:08:39 -08001977 "preview");
Mohan Kandra284966d2010-01-05 13:39:15 -08001978
Mohan Kandrad9efed92010-01-15 19:08:39 -08001979 if (!mPreviewHeap->initialized()) {
1980 mPreviewHeap.clear();
Mohan Kandra284966d2010-01-05 13:39:15 -08001981 LOGE("initPreview X: could not initialize Camera preview heap.");
1982 return false;
1983 }
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08001984 if( mCurrentTarget == TARGET_MSM7630 ) {
Kiran Kumar H N595970b2010-01-12 10:41:09 -08001985 if(mPostViewHeap == NULL) {
1986 LOGV(" Allocating Postview heap ");
1987 /* mPostViewHeap should be declared only for 7630 target */
1988 mPostViewHeap =
1989 new PmemPool("/dev/pmem_adsp",
1990 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
1991 mCameraControlFd,
Sravankb4f5f1c2010-01-21 11:06:17 +05301992 MSM_PMEM_PREVIEW, //MSM_PMEM_OUTPUT2,
Kiran Kumar H N595970b2010-01-12 10:41:09 -08001993 mPreviewFrameSize,
1994 1,
1995 mPreviewFrameSize,
1996 "postview");
Mohan Kandra284966d2010-01-05 13:39:15 -08001997
Kiran Kumar H N595970b2010-01-12 10:41:09 -08001998 if (!mPostViewHeap->initialized()) {
1999 mPostViewHeap.clear();
2000 LOGE(" Failed to initialize Postview Heap");
2001 return false;
2002 }
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002003 }
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002004
2005 // Allocate video buffers after allocating preview buffers.
Sravankb4f5f1c2010-01-21 11:06:17 +05302006 initRecord();
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002007 }
Sravankb4f5f1c2010-01-21 11:06:17 +05302008
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002009 // mDimension will be filled with thumbnail_width, thumbnail_height,
2010 // orig_picture_dx, and orig_picture_dy after this function call. We need to
2011 // keep it for jpeg_encoder_encode.
2012 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
2013 sizeof(cam_ctrl_dimension_t), &mDimension);
2014
2015 if (ret) {
2016 for (cnt = 0; cnt < kPreviewBufferCount; cnt++) {
Mohan Kandrad9efed92010-01-15 19:08:39 -08002017 frames[cnt].fd = mPreviewHeap->mHeap->getHeapID();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002018 frames[cnt].buffer =
Mohan Kandrad9efed92010-01-15 19:08:39 -08002019 (uint32_t)mPreviewHeap->mHeap->base() + mPreviewHeap->mAlignedBufferSize * cnt;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002020 frames[cnt].y_off = 0;
2021 frames[cnt].cbcr_off = previewWidth * previewHeight;
Sravankb4f5f1c2010-01-21 11:06:17 +05302022 frames[cnt].path = OUTPUT_TYPE_P; // MSM_FRAME_ENC;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002023 }
2024
2025 mFrameThreadWaitLock.lock();
2026 pthread_attr_t attr;
2027 pthread_attr_init(&attr);
2028 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
Sravankb4f5f1c2010-01-21 11:06:17 +05302029
2030 frame_parms.frame = frames[kPreviewBufferCount - 1];
2031 frame_parms.video_frame = recordframes[kPreviewBufferCount - 1];
2032
2033 LOGV ("initpreview before cam_frame thread carete , video frame buffer=%lu fd=%d y_off=%d cbcr_off=%d \n",
2034 (unsigned long)frame_parms.video_frame.buffer, frame_parms.video_frame.fd, frame_parms.video_frame.y_off,
2035 frame_parms.video_frame.cbcr_off);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002036 mFrameThreadRunning = !pthread_create(&mFrameThread,
2037 &attr,
2038 frame_thread,
Sravankb4f5f1c2010-01-21 11:06:17 +05302039 (void*)&(frame_parms));
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002040 ret = mFrameThreadRunning;
2041 mFrameThreadWaitLock.unlock();
2042 }
2043
2044 LOGV("initPreview X: %d", ret);
2045 return ret;
2046}
2047
2048void QualcommCameraHardware::deinitPreview(void)
2049{
2050 LOGI("deinitPreview E");
2051
2052 // When we call deinitPreview(), we signal to the frame thread that it
2053 // needs to exit, but we DO NOT WAIT for it to complete here. The problem
2054 // is that deinitPreview is sometimes called from the frame-thread's
2055 // callback, when the refcount on the Camera client reaches zero. If we
2056 // called pthread_join(), we would deadlock. So, we just call
2057 // LINK_camframe_terminate() in deinitPreview(), which makes sure that
2058 // after the preview callback returns, the camframe thread will exit. We
2059 // could call pthread_join() in initPreview() to join the last frame
2060 // thread. However, we would also have to call pthread_join() in release
2061 // as well, shortly before we destroy the object; this would cause the same
2062 // deadlock, since release(), like deinitPreview(), may also be called from
2063 // the frame-thread's callback. This we have to make the frame thread
2064 // detached, and use a separate mechanism to wait for it to complete.
2065
Kiran Kumar H N7ac84e32010-02-01 10:58:47 -08002066 LINK_camframe_terminate();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002067 LOGI("deinitPreview X");
2068}
2069
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002070bool QualcommCameraHardware::initRawSnapshot()
2071{
2072 LOGV("initRawSnapshot E");
2073
2074 //get width and height from Dimension Object
2075 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
2076 sizeof(cam_ctrl_dimension_t), &mDimension);
2077
2078 if(!ret){
2079 LOGE("initRawSnapshot X: failed to set dimension");
2080 return false;
2081 }
2082 int rawSnapshotSize = mDimension.raw_picture_height *
2083 mDimension.raw_picture_width;
2084
2085 LOGV("raw_snapshot_buffer_size = %d, raw_picture_height = %d, "\
2086 "raw_picture_width = %d",
2087 rawSnapshotSize, mDimension.raw_picture_height,
2088 mDimension.raw_picture_width);
2089
2090 if (mRawSnapShotPmemHeap != NULL) {
2091 LOGV("initRawSnapshot: clearing old mRawSnapShotPmemHeap.");
2092 mRawSnapShotPmemHeap.clear();
2093 }
2094
2095 //Pmem based pool for Camera Driver
2096 mRawSnapShotPmemHeap = new PmemPool("/dev/pmem_adsp",
2097 MemoryHeapBase::READ_ONLY,
2098 mCameraControlFd,
2099 MSM_PMEM_RAW_MAINIMG,
2100 rawSnapshotSize,
2101 1,
2102 rawSnapshotSize,
2103 "raw pmem snapshot camera");
2104
2105 if (!mRawSnapShotPmemHeap->initialized()) {
2106 mRawSnapShotPmemHeap.clear();
2107 LOGE("initRawSnapshot X: error initializing mRawSnapshotHeap");
2108 return false;
2109 }
2110 LOGV("initRawSnapshot X");
2111 return true;
2112
2113}
2114
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002115bool QualcommCameraHardware::initRaw(bool initJpegHeap)
2116{
2117 int rawWidth, rawHeight;
Apurva Rajguru8d1773b2009-12-02 14:21:23 -08002118
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002119 mParameters.getPictureSize(&rawWidth, &rawHeight);
2120 LOGV("initRaw E: picture size=%dx%d", rawWidth, rawHeight);
2121
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08002122 int thumbnailBufferSize;
2123 //Thumbnail height should be smaller than Picture height
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002124 if (rawHeight > (int)thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height){
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08002125 mDimension.ui_thumbnail_width =
2126 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].width;
2127 mDimension.ui_thumbnail_height =
2128 thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height;
2129 uint32_t pictureAspectRatio = (uint32_t)((rawWidth * Q12) / rawHeight);
2130 uint32_t i;
2131 for(i = 0; i < THUMBNAIL_SIZE_COUNT; i++ )
2132 {
2133 if(thumbnail_sizes[i].aspect_ratio == pictureAspectRatio)
2134 {
2135 mDimension.ui_thumbnail_width = thumbnail_sizes[i].width;
2136 mDimension.ui_thumbnail_height = thumbnail_sizes[i].height;
2137 break;
2138 }
2139 }
2140 }
2141 else{
2142 mDimension.ui_thumbnail_height = THUMBNAIL_SMALL_HEIGHT;
2143 mDimension.ui_thumbnail_width =
2144 (THUMBNAIL_SMALL_HEIGHT * rawWidth)/ rawHeight;
2145 }
2146
2147 LOGV("Thumbnail Size Width %d Height %d",
2148 mDimension.ui_thumbnail_width,
2149 mDimension.ui_thumbnail_height);
2150
2151 thumbnailBufferSize = mDimension.ui_thumbnail_width *
2152 mDimension.ui_thumbnail_height * 3 / 2;
2153
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002154 // mDimension will be filled with thumbnail_width, thumbnail_height,
2155 // orig_picture_dx, and orig_picture_dy after this function call. We need to
2156 // keep it for jpeg_encoder_encode.
2157 bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
2158 sizeof(cam_ctrl_dimension_t), &mDimension);
2159 if(!ret) {
2160 LOGE("initRaw X: failed to set dimension");
2161 return false;
2162 }
2163
2164 if (mJpegHeap != NULL) {
2165 LOGV("initRaw: clearing old mJpegHeap.");
2166 mJpegHeap.clear();
2167 }
2168
2169 // Snapshot
2170 mRawSize = rawWidth * rawHeight * 3 / 2;
Apurva Rajguru8d1773b2009-12-02 14:21:23 -08002171
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002172 if( mCurrentTarget == TARGET_MSM7627 )
Apurva Rajguru8d1773b2009-12-02 14:21:23 -08002173 mJpegMaxSize = CEILING16(rawWidth) * CEILING16(rawHeight) * 3 / 2;
2174 else
2175 mJpegMaxSize = rawWidth * rawHeight * 3 / 2;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002176
2177 LOGV("initRaw: initializing mRawHeap.");
2178 mRawHeap =
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002179 new PmemPool("/dev/pmem_adsp",
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002180 MemoryHeapBase::READ_ONLY,
2181 mCameraControlFd,
2182 MSM_PMEM_MAINIMG,
2183 mJpegMaxSize,
2184 kRawBufferCount,
2185 mRawSize,
2186 "snapshot camera");
2187
2188 if (!mRawHeap->initialized()) {
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002189 LOGE("initRaw X failed ");
2190 mRawHeap.clear();
2191 LOGE("initRaw X: error initializing mRawHeap");
2192 return false;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002193 }
2194
2195 LOGV("do_mmap snapshot pbuf = %p, pmem_fd = %d",
2196 (uint8_t *)mRawHeap->mHeap->base(), mRawHeap->mHeap->getHeapID());
2197
2198 // Jpeg
2199
2200 if (initJpegHeap) {
2201 LOGV("initRaw: initializing mJpegHeap.");
2202 mJpegHeap =
2203 new AshmemPool(mJpegMaxSize,
2204 kJpegBufferCount,
2205 0, // we do not know how big the picture will be
2206 "jpeg");
2207
2208 if (!mJpegHeap->initialized()) {
2209 mJpegHeap.clear();
2210 mRawHeap.clear();
2211 LOGE("initRaw X failed: error initializing mJpegHeap.");
2212 return false;
2213 }
2214
2215 // Thumbnails
2216
2217 mThumbnailHeap =
2218 new PmemPool("/dev/pmem_adsp",
2219 MemoryHeapBase::READ_ONLY,
2220 mCameraControlFd,
2221 MSM_PMEM_THUMBNAIL,
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08002222 thumbnailBufferSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002223 1,
Srinivasan Kannan80d878f2009-12-18 15:06:02 -08002224 thumbnailBufferSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002225 "thumbnail");
2226
2227 if (!mThumbnailHeap->initialized()) {
2228 mThumbnailHeap.clear();
2229 mJpegHeap.clear();
2230 mRawHeap.clear();
2231 LOGE("initRaw X failed: error initializing mThumbnailHeap.");
2232 return false;
2233 }
2234 }
2235
2236 LOGV("initRaw X");
2237 return true;
2238}
2239
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002240
2241void QualcommCameraHardware::deinitRawSnapshot()
2242{
2243 LOGV("deinitRawSnapshot E");
2244 mRawSnapShotPmemHeap.clear();
2245 mRawSnapshotAshmemHeap.clear();
2246 LOGV("deinitRawSnapshot X");
2247}
2248
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002249void QualcommCameraHardware::deinitRaw()
2250{
2251 LOGV("deinitRaw E");
2252
2253 mThumbnailHeap.clear();
2254 mJpegHeap.clear();
2255 mRawHeap.clear();
2256 mDisplayHeap.clear();
2257
2258 LOGV("deinitRaw X");
2259}
2260
2261void QualcommCameraHardware::release()
2262{
2263 LOGD("release E");
2264 Mutex::Autolock l(&mLock);
2265
2266#if DLOPEN_LIBMMCAMERA
2267 if (libmmcamera == NULL) {
2268 LOGE("ERROR: multiple release!");
2269 return;
2270 }
2271#else
2272#warning "Cannot detect multiple release when not dlopen()ing libqcamera!"
2273#endif
2274
2275 int cnt, rc;
2276 struct msm_ctrl_cmd ctrlCmd;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002277 if (mCameraRunning) {
2278 if(mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME)) {
2279 mRecordFrameLock.lock();
2280 mReleasedRecordingFrame = true;
2281 mRecordWait.signal();
2282 mRecordFrameLock.unlock();
2283 }
2284 stopPreviewInternal();
2285 }
2286
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002287 if( mCurrentTarget == TARGET_MSM7630 ) {
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002288 mPostViewHeap.clear();
2289 mPostViewHeap = NULL;
2290 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002291 LINK_jpeg_encoder_join();
2292 deinitRaw();
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002293 deinitRawSnapshot();
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002294 {
2295 Mutex::Autolock l(&mCamframeTimeoutLock);
2296 if(!camframe_timeout_flag) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002297
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002298 ctrlCmd.timeout_ms = 5000;
2299 ctrlCmd.length = 0;
2300 ctrlCmd.type = (uint16_t)CAMERA_EXIT;
2301 ctrlCmd.resp_fd = mCameraControlFd; // FIXME: this will be put in by the kernel
2302 if (ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0)
2303 LOGE("ioctl CAMERA_EXIT fd %d error %s",
2304 mCameraControlFd, strerror(errno));
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002305
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002306 }
2307 }
Kiran Kumar H N7ac84e32010-02-01 10:58:47 -08002308 LINK_release_cam_conf_thread();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002309 close(mCameraControlFd);
2310 mCameraControlFd = -1;
Mohan Kandra284966d2010-01-05 13:39:15 -08002311 if(fb_fd >= 0) {
2312 close(fb_fd);
2313 fb_fd = -1;
2314 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002315#if DLOPEN_LIBMMCAMERA
2316 if (libmmcamera) {
2317 ::dlclose(libmmcamera);
2318 LOGV("dlclose(libqcamera)");
2319 libmmcamera = NULL;
2320 }
2321#endif
2322
2323 Mutex::Autolock lock(&singleton_lock);
2324 singleton_releasing = true;
2325
2326 LOGD("release X");
2327}
2328
2329QualcommCameraHardware::~QualcommCameraHardware()
2330{
2331 LOGD("~QualcommCameraHardware E");
2332 Mutex::Autolock lock(&singleton_lock);
2333 singleton.clear();
2334 singleton_releasing = false;
2335 singleton_wait.signal();
2336 LOGD("~QualcommCameraHardware X");
2337}
2338
2339sp<IMemoryHeap> QualcommCameraHardware::getRawHeap() const
2340{
2341 LOGV("getRawHeap");
2342 return mDisplayHeap != NULL ? mDisplayHeap->mHeap : NULL;
2343}
2344
2345sp<IMemoryHeap> QualcommCameraHardware::getPreviewHeap() const
2346{
2347 LOGV("getPreviewHeap");
Mohan Kandrad9efed92010-01-15 19:08:39 -08002348 return mPreviewHeap != NULL ? mPreviewHeap->mHeap : NULL;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002349}
2350
2351status_t QualcommCameraHardware::startPreviewInternal()
2352{
Sravankb4f5f1c2010-01-21 11:06:17 +05302353 LOGV("in startPreviewInternal : E");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002354 if(mCameraRunning) {
2355 LOGV("startPreview X: preview already running.");
2356 return NO_ERROR;
2357 }
2358
2359 if (!mPreviewInitialized) {
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002360 mLastQueuedFrame = NULL;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002361 mPreviewInitialized = initPreview();
2362 if (!mPreviewInitialized) {
2363 LOGE("startPreview X initPreview failed. Not starting preview.");
2364 return UNKNOWN_ERROR;
2365 }
2366 }
2367
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002368 if( mCurrentTarget != TARGET_MSM7630 )
2369 mCameraRunning = native_start_preview(mCameraControlFd);
Sravankb4f5f1c2010-01-21 11:06:17 +05302370 else
2371 mCameraRunning = native_start_video(mCameraControlFd);
2372
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002373 if(!mCameraRunning) {
2374 deinitPreview();
2375 mPreviewInitialized = false;
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08002376 mOverlay = NULL;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002377 LOGE("startPreview X: native_start_preview failed!");
2378 return UNKNOWN_ERROR;
2379 }
2380
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08002381 //Reset the Gps Information
2382 exif_table_numEntries = 0;
Mohan Kandra284966d2010-01-05 13:39:15 -08002383
2384 if(native_get_maxzoom(mCameraControlFd, (void *)&mMaxZoom) == true){
2385 LOGE("Maximum zoom value is %d", mMaxZoom);
2386 mParameters.set("zoom-supported", "true");
2387 } else {
2388 LOGE("Failed to get maximum zoom value...setting max zoom to zero");
2389 mParameters.set("zoom-supported", "false");
2390 mMaxZoom = 0;
2391 }
2392 mParameters.set("max-zoom",mMaxZoom);
2393
Sravankb4f5f1c2010-01-21 11:06:17 +05302394 LOGV("startPreviewInternal X");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002395 return NO_ERROR;
2396}
2397
2398status_t QualcommCameraHardware::startPreview()
2399{
2400 LOGV("startPreview E");
2401 Mutex::Autolock l(&mLock);
2402 return startPreviewInternal();
2403}
2404
2405void QualcommCameraHardware::stopPreviewInternal()
2406{
2407 LOGV("stopPreviewInternal E: %d", mCameraRunning);
2408 if (mCameraRunning) {
2409 // Cancel auto focus.
2410 {
2411 if (mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS)) {
2412 cancelAutoFocusInternal();
2413 }
2414 }
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002415
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002416 Mutex::Autolock l(&mCamframeTimeoutLock);
2417 if(!camframe_timeout_flag) {
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002418 if ( mCurrentTarget != TARGET_MSM7630 )
Sravankb4f5f1c2010-01-21 11:06:17 +05302419 mCameraRunning = !native_stop_preview(mCameraControlFd);
2420 else
2421 mCameraRunning = !native_stop_video(mCameraControlFd);
2422
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002423 } else {
2424 /* This means that the camframetimeout was issued.
2425 * But we did not issue native_stop_preview(), so we
Kiran Kumar H Nac2f4952009-12-17 01:16:53 -08002426 * need to update mCameraRunning to indicate that
2427 * Camera is no longer running. */
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002428 mCameraRunning = 0;
Kiran Kumar H Nac2f4952009-12-17 01:16:53 -08002429 }
2430 if (!mCameraRunning && mPreviewInitialized) {
2431 deinitPreview();
Mohan Kandra156d0ac2010-01-25 16:59:17 -08002432 if( mCurrentTarget == TARGET_MSM7630 ){
2433 mVideoThreadWaitLock.lock();
2434 LOGV("in stopPreviewInternal: making mVideoThreadExit 1");
2435 mVideoThreadExit = 1;
2436 mVideoThreadWaitLock.unlock();
2437 // 720p : signal the video thread , and check in video thread if stop is called, if so exit video thread.
2438 pthread_mutex_lock(&(g_busy_frame_queue.mut));
2439 pthread_cond_signal(&(g_busy_frame_queue.wait));
2440 pthread_mutex_unlock(&(g_busy_frame_queue.mut));
2441 }
Kiran Kumar H N215cac42009-12-08 01:53:46 -08002442 mPreviewInitialized = false;
2443 }
Kiran Kumar H Nac2f4952009-12-17 01:16:53 -08002444 else LOGE("stopPreviewInternal: failed to stop preview");
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002445 }
2446 LOGV("stopPreviewInternal X: %d", mCameraRunning);
2447}
2448
2449void QualcommCameraHardware::stopPreview()
2450{
2451 LOGV("stopPreview: E");
2452 Mutex::Autolock l(&mLock);
2453 {
2454 if (mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME))
2455 return;
2456 }
2457 stopPreviewInternal();
2458 LOGV("stopPreview: X");
2459}
2460
2461void QualcommCameraHardware::runAutoFocus()
2462{
2463 bool status = true;
2464 void *libhandle = NULL;
Srinivasan Kannan71229622009-12-04 12:05:58 -08002465 isp3a_af_mode_t afMode;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002466
2467 mAutoFocusThreadLock.lock();
2468 // Skip autofocus if focus mode is infinity.
2469 if (strcmp(mParameters.get(CameraParameters::KEY_FOCUS_MODE),
2470 CameraParameters::FOCUS_MODE_INFINITY) == 0) {
2471 goto done;
2472 }
2473
2474 mAutoFocusFd = open(MSM_CAMERA_CONTROL, O_RDWR);
2475 if (mAutoFocusFd < 0) {
2476 LOGE("autofocus: cannot open %s: %s",
2477 MSM_CAMERA_CONTROL,
2478 strerror(errno));
2479 mAutoFocusThreadRunning = false;
2480 mAutoFocusThreadLock.unlock();
2481 return;
2482 }
2483
2484#if DLOPEN_LIBMMCAMERA
2485 // We need to maintain a reference to libqcamera.so for the duration of the
2486 // AF thread, because we do not know when it will exit relative to the
2487 // lifetime of this object. We do not want to dlclose() libqcamera while
2488 // LINK_cam_frame is still running.
2489 libhandle = ::dlopen("liboemcamera.so", RTLD_NOW);
2490 LOGV("AF: loading libqcamera at %p", libhandle);
2491 if (!libhandle) {
2492 LOGE("FATAL ERROR: could not dlopen liboemcamera.so: %s", dlerror());
2493 close(mAutoFocusFd);
2494 mAutoFocusFd = -1;
2495 mAutoFocusThreadRunning = false;
2496 mAutoFocusThreadLock.unlock();
2497 return;
2498 }
2499#endif
2500
Srinivasan Kannan71229622009-12-04 12:05:58 -08002501 afMode = (isp3a_af_mode_t)attr_lookup(focus_modes,
2502 sizeof(focus_modes) / sizeof(str_map),
2503 mParameters.get(CameraParameters::KEY_FOCUS_MODE));
2504
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002505 /* This will block until either AF completes or is cancelled. */
Srinivasan Kannan71229622009-12-04 12:05:58 -08002506 LOGV("af start (fd %d mode %d)", mAutoFocusFd, afMode);
2507 status = native_set_afmode(mAutoFocusFd, afMode);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002508 LOGV("af done: %d", (int)status);
2509 close(mAutoFocusFd);
2510 mAutoFocusFd = -1;
2511
2512done:
2513 mAutoFocusThreadRunning = false;
2514 mAutoFocusThreadLock.unlock();
2515
2516 mCallbackLock.lock();
2517 bool autoFocusEnabled = mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS);
2518 notify_callback cb = mNotifyCallback;
2519 void *data = mCallbackCookie;
2520 mCallbackLock.unlock();
2521 if (autoFocusEnabled)
2522 cb(CAMERA_MSG_FOCUS, status, 0, data);
2523
2524#if DLOPEN_LIBMMCAMERA
2525 if (libhandle) {
2526 ::dlclose(libhandle);
2527 LOGV("AF: dlclose(libqcamera)");
2528 }
2529#endif
2530}
2531
2532status_t QualcommCameraHardware::cancelAutoFocusInternal()
2533{
2534 LOGV("cancelAutoFocusInternal E");
2535
Srinivasan Kannan71229622009-12-04 12:05:58 -08002536 if(!sensorType->hasAutoFocusSupport){
2537 LOGV("cancelAutoFocusInternal X");
2538 return NO_ERROR;
2539 }
2540
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002541#if 0
2542 if (mAutoFocusFd < 0) {
2543 LOGV("cancelAutoFocusInternal X: not in progress");
2544 return NO_ERROR;
2545 }
2546#endif
2547
2548 status_t rc = native_cancel_afmode(mCameraControlFd, mAutoFocusFd) ?
2549 NO_ERROR :
2550 UNKNOWN_ERROR;
2551
2552 LOGV("cancelAutoFocusInternal X: %d", rc);
2553 return rc;
2554}
2555
2556void *auto_focus_thread(void *user)
2557{
2558 LOGV("auto_focus_thread E");
2559 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
2560 if (obj != 0) {
2561 obj->runAutoFocus();
2562 }
2563 else LOGW("not starting autofocus: the object went away!");
2564 LOGV("auto_focus_thread X");
2565 return NULL;
2566}
2567
2568status_t QualcommCameraHardware::autoFocus()
2569{
2570 LOGV("autoFocus E");
2571 Mutex::Autolock l(&mLock);
2572
Srinivasan Kannan71229622009-12-04 12:05:58 -08002573 if(!sensorType->hasAutoFocusSupport){
Srinivasan Kannandf085222009-12-09 18:31:00 -08002574 bool status = false;
2575 mCallbackLock.lock();
2576 bool autoFocusEnabled = mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS);
2577 notify_callback cb = mNotifyCallback;
2578 void *data = mCallbackCookie;
2579 mCallbackLock.unlock();
2580 if (autoFocusEnabled)
2581 cb(CAMERA_MSG_FOCUS, status, 0, data);
Srinivasan Kannan71229622009-12-04 12:05:58 -08002582 LOGV("autoFocus X");
2583 return NO_ERROR;
2584 }
2585
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002586 if (mCameraControlFd < 0) {
2587 LOGE("not starting autofocus: main control fd %d", mCameraControlFd);
2588 return UNKNOWN_ERROR;
2589 }
2590
2591 {
2592 mAutoFocusThreadLock.lock();
2593 if (!mAutoFocusThreadRunning) {
2594 // Create a detached thread here so that we don't have to wait
2595 // for it when we cancel AF.
2596 pthread_t thr;
2597 pthread_attr_t attr;
2598 pthread_attr_init(&attr);
2599 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2600 mAutoFocusThreadRunning =
2601 !pthread_create(&thr, &attr,
2602 auto_focus_thread, NULL);
2603 if (!mAutoFocusThreadRunning) {
2604 LOGE("failed to start autofocus thread");
2605 mAutoFocusThreadLock.unlock();
2606 return UNKNOWN_ERROR;
2607 }
2608 }
2609 mAutoFocusThreadLock.unlock();
2610 }
2611
2612 LOGV("autoFocus X");
2613 return NO_ERROR;
2614}
2615
2616status_t QualcommCameraHardware::cancelAutoFocus()
2617{
2618 LOGV("cancelAutoFocus E");
2619 Mutex::Autolock l(&mLock);
2620
2621 int rc = NO_ERROR;
2622 if (mCameraRunning && mNotifyCallback && (mMsgEnabled & CAMERA_MSG_FOCUS)) {
2623 rc = cancelAutoFocusInternal();
2624 }
2625
2626 LOGV("cancelAutoFocus X");
2627 return rc;
2628}
2629
2630void QualcommCameraHardware::runSnapshotThread(void *data)
2631{
2632 LOGV("runSnapshotThread E");
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002633 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
2634 if (native_start_snapshot(mCameraControlFd))
2635 receiveRawPicture();
2636 else
2637 LOGE("main: native_start_snapshot failed!");
2638 } else if(mSnapshotFormat == PICTURE_FORMAT_RAW){
2639 if(native_start_raw_snapshot(mCameraControlFd)){
2640 receiveRawSnapshot();
2641 } else {
2642 LOGE("main: native_start_raw_snapshot failed!");
2643 }
2644 }
2645
2646 mSnapshotFormat = 0;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002647
2648 mSnapshotThreadWaitLock.lock();
2649 mSnapshotThreadRunning = false;
2650 mSnapshotThreadWait.signal();
2651 mSnapshotThreadWaitLock.unlock();
2652
2653 LOGV("runSnapshotThread X");
2654}
2655
2656void *snapshot_thread(void *user)
2657{
2658 LOGD("snapshot_thread E");
2659 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
2660 if (obj != 0) {
2661 obj->runSnapshotThread(user);
2662 }
2663 else LOGW("not starting snapshot thread: the object went away!");
2664 LOGD("snapshot_thread X");
2665 return NULL;
2666}
2667
2668status_t QualcommCameraHardware::takePicture()
2669{
2670 LOGV("takePicture(%d)", mMsgEnabled);
2671 Mutex::Autolock l(&mLock);
2672
2673 // Wait for old snapshot thread to complete.
2674 mSnapshotThreadWaitLock.lock();
2675 while (mSnapshotThreadRunning) {
2676 LOGV("takePicture: waiting for old snapshot thread to complete.");
2677 mSnapshotThreadWait.wait(mSnapshotThreadWaitLock);
2678 LOGV("takePicture: old snapshot thread completed.");
2679 }
2680
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002681 if( mCurrentTarget == TARGET_MSM7630 ) {
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002682 /* Store the last frame queued for preview. This
2683 * shall be used as postview */
2684 storePreviewFrameForPostview();
2685 }
2686
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002687 //mSnapshotFormat is protected by mSnapshotThreadWaitLock
2688 if(mParameters.getPictureFormat() != 0 &&
2689 !strcmp(mParameters.getPictureFormat(),
2690 CameraParameters::PIXEL_FORMAT_RAW))
2691 mSnapshotFormat = PICTURE_FORMAT_RAW;
2692 else
2693 mSnapshotFormat = PICTURE_FORMAT_JPEG;
2694
2695 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
2696 if(!native_prepare_snapshot(mCameraControlFd)) {
2697 mSnapshotThreadWaitLock.unlock();
2698 return UNKNOWN_ERROR;
2699 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002700 }
2701
2702 stopPreviewInternal();
2703
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002704 if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
2705 if (!initRaw(mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE))) {
2706 LOGE("initRaw failed. Not taking picture.");
2707 mSnapshotThreadWaitLock.unlock();
2708 return UNKNOWN_ERROR;
2709 }
2710 } else if(mSnapshotFormat == PICTURE_FORMAT_RAW ){
2711 if(!initRawSnapshot()){
2712 LOGE("initRawSnapshot failed. Not taking picture.");
2713 mSnapshotThreadWaitLock.unlock();
2714 return UNKNOWN_ERROR;
2715 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002716 }
2717
2718 mShutterLock.lock();
2719 mShutterPending = true;
2720 mShutterLock.unlock();
2721
2722 pthread_attr_t attr;
2723 pthread_attr_init(&attr);
2724 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2725 mSnapshotThreadRunning = !pthread_create(&mSnapshotThread,
2726 &attr,
2727 snapshot_thread,
2728 NULL);
2729 mSnapshotThreadWaitLock.unlock();
2730
2731 LOGV("takePicture: X");
2732 return mSnapshotThreadRunning ? NO_ERROR : UNKNOWN_ERROR;
2733}
2734
2735status_t QualcommCameraHardware::cancelPicture()
2736{
2737 status_t rc;
2738 LOGV("cancelPicture: E");
2739 rc = native_stop_snapshot(mCameraControlFd) ? NO_ERROR : UNKNOWN_ERROR;
2740 LOGV("cancelPicture: X: %d", rc);
2741 return rc;
2742}
2743
2744status_t QualcommCameraHardware::setParameters(const CameraParameters& params)
2745{
2746 LOGV("setParameters: E params = %p", &params);
2747
2748 Mutex::Autolock l(&mLock);
2749 status_t rc, final_rc = NO_ERROR;
2750
2751 if ((rc = setPreviewSize(params))) final_rc = rc;
2752 if ((rc = setPictureSize(params))) final_rc = rc;
2753 if ((rc = setJpegQuality(params))) final_rc = rc;
2754 if ((rc = setAntibanding(params))) final_rc = rc;
2755 if ((rc = setEffect(params))) final_rc = rc;
Apurva Rajguru55562b02009-12-03 12:25:35 -08002756 if ((rc = setAutoExposure(params))) final_rc = rc;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002757 if ((rc = setWhiteBalance(params))) final_rc = rc;
2758 if ((rc = setFlash(params))) final_rc = rc;
2759 if ((rc = setGpsLocation(params))) final_rc = rc;
2760 if ((rc = setRotation(params))) final_rc = rc;
2761 if ((rc = setZoom(params))) final_rc = rc;
2762 if ((rc = setFocusMode(params))) final_rc = rc;
2763 if ((rc = setOrientation(params))) final_rc = rc;
Nishant Panditc8c1ee72009-12-03 16:24:02 +05302764 if ((rc = setBrightness(params))) final_rc = rc;
2765 if ((rc = setLensshadeValue(params))) final_rc = rc;
2766 if ((rc = setISOValue(params))) final_rc = rc;
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08002767 if ((rc = setPictureFormat(params))) final_rc = rc;
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08002768 if ((rc = setSharpness(params))) final_rc = rc;
2769 if ((rc = setContrast(params))) final_rc = rc;
2770 if ((rc = setSaturation(params))) final_rc = rc;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002771
2772 LOGV("setParameters: X");
2773 return final_rc;
2774}
2775
2776CameraParameters QualcommCameraHardware::getParameters() const
2777{
2778 LOGV("getParameters: EX");
2779 return mParameters;
2780}
2781
2782status_t QualcommCameraHardware::sendCommand(int32_t command, int32_t arg1,
2783 int32_t arg2)
2784{
2785 LOGV("sendCommand: EX");
2786 return BAD_VALUE;
2787}
2788
2789extern "C" sp<CameraHardwareInterface> openCameraHardware()
2790{
2791 LOGV("openCameraHardware: call createInstance");
2792 return QualcommCameraHardware::createInstance();
2793}
2794
2795wp<QualcommCameraHardware> QualcommCameraHardware::singleton;
2796
2797// If the hardware already exists, return a strong pointer to the current
2798// object. If not, create a new hardware object, put it in the singleton,
2799// and return it.
2800sp<CameraHardwareInterface> QualcommCameraHardware::createInstance()
2801{
2802 LOGD("createInstance: E");
2803
2804 Mutex::Autolock lock(&singleton_lock);
2805
2806 // Wait until the previous release is done.
2807 while (singleton_releasing) {
2808 LOGD("Wait for previous release.");
2809 singleton_wait.wait(singleton_lock);
2810 }
2811
2812 if (singleton != 0) {
2813 sp<CameraHardwareInterface> hardware = singleton.promote();
2814 if (hardware != 0) {
2815 LOGD("createInstance: X return existing hardware=%p", &(*hardware));
2816 return hardware;
2817 }
2818 }
2819
2820 {
2821 struct stat st;
2822 int rc = stat("/dev/oncrpc", &st);
2823 if (rc < 0) {
2824 LOGD("createInstance: X failed to create hardware: %s", strerror(errno));
2825 return NULL;
2826 }
2827 }
2828
2829 QualcommCameraHardware *cam = new QualcommCameraHardware();
2830 sp<QualcommCameraHardware> hardware(cam);
2831 singleton = hardware;
2832
2833 if (!cam->startCamera()) {
2834 LOGE("%s: startCamera failed!", __FUNCTION__);
2835 return NULL;
2836 }
2837
2838 cam->initDefaultParameters();
2839 LOGD("createInstance: X created hardware=%p", &(*hardware));
2840 return hardware;
2841}
2842
2843// For internal use only, hence the strong pointer to the derived type.
2844sp<QualcommCameraHardware> QualcommCameraHardware::getInstance()
2845{
2846 sp<CameraHardwareInterface> hardware = singleton.promote();
2847 if (hardware != 0) {
2848 // LOGV("getInstance: X old instance of hardware");
2849 return sp<QualcommCameraHardware>(static_cast<QualcommCameraHardware*>(hardware.get()));
2850 } else {
2851 LOGV("getInstance: X new instance of hardware");
2852 return sp<QualcommCameraHardware>();
2853 }
2854}
Sravankb4f5f1c2010-01-21 11:06:17 +05302855void QualcommCameraHardware::receiveRecordingFrame(struct msm_frame *frame)
2856{
2857 LOGV("receiveRecordingFrame E");
2858 // post busy frame
2859 if (frame)
2860 {
2861 cam_frame_post_video (frame);
2862 }
2863 else LOGE("in receiveRecordingFrame frame is NULL");
2864 LOGV("receiveRecordingFrame X");
2865}
2866
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002867
Mohan Kandrad9efed92010-01-15 19:08:39 -08002868bool QualcommCameraHardware::native_zoom_image(int fd, int srcOffset, int dstOffSet, common_crop_t *crop)
Mohan Kandra284966d2010-01-05 13:39:15 -08002869{
2870 int result = 0;
2871 struct mdp_blit_req *e;
2872 struct timeval td1, td2;
2873
Mohan Kandra284966d2010-01-05 13:39:15 -08002874 /* Initialize yuv structure */
2875 zoomImage.list.count = 1;
2876
2877 e = &zoomImage.list.req[0];
2878
2879 e->src.width = previewWidth;
2880 e->src.height = previewHeight;
2881 e->src.format = MDP_Y_CBCR_H2V2;
Mohan Kandrad9efed92010-01-15 19:08:39 -08002882 e->src.offset = srcOffset;
2883 e->src.memory_id = fd;
Mohan Kandra284966d2010-01-05 13:39:15 -08002884
2885 e->dst.width = previewWidth;
2886 e->dst.height = previewHeight;
2887 e->dst.format = MDP_Y_CBCR_H2V2;
Mohan Kandrad9efed92010-01-15 19:08:39 -08002888 e->dst.offset = dstOffSet;
2889 e->dst.memory_id = fd;
Mohan Kandra284966d2010-01-05 13:39:15 -08002890
2891 e->transp_mask = 0xffffffff;
2892 e->flags = 0;
2893 e->alpha = 0xff;
2894 if (crop->in2_w != 0 || crop->in2_h != 0) {
2895 e->src_rect.x = (crop->out2_w - crop->in2_w + 1) / 2 - 1;
2896 e->src_rect.y = (crop->out2_h - crop->in2_h + 1) / 2 - 1;
2897 e->src_rect.w = crop->in2_w;
2898 e->src_rect.h = crop->in2_h;
2899 } else {
2900 e->src_rect.x = 0;
2901 e->src_rect.y = 0;
2902 e->src_rect.w = previewWidth;
2903 e->src_rect.h = previewHeight;
2904 }
Mohan Kandrad9efed92010-01-15 19:08:39 -08002905 //LOGV(" native_zoom : SRC_RECT : x,y = %d,%d \t w,h = %d, %d",
2906 // e->src_rect.x, e->src_rect.y, e->src_rect.w, e->src_rect.h);
Mohan Kandra284966d2010-01-05 13:39:15 -08002907
2908 e->dst_rect.x = 0;
2909 e->dst_rect.y = 0;
2910 e->dst_rect.w = previewWidth;
2911 e->dst_rect.h = previewHeight;
2912
2913 result = ioctl(fb_fd, MSMFB_BLIT, &zoomImage.list);
2914 if (result < 0) {
2915 LOGE("MSM_FBIOBLT failed! line=%d\n", __LINE__);
2916 return FALSE;
2917 }
2918 return TRUE;
2919}
2920
Mohan Kandra740cfce2010-01-07 12:58:24 -08002921void QualcommCameraHardware::debugShowFPS() const
2922{
2923 static int mFrameCount;
2924 static int mLastFrameCount = 0;
2925 static nsecs_t mLastFpsTime = 0;
2926 static float mFps = 0;
2927 mFrameCount++;
2928 nsecs_t now = systemTime();
2929 nsecs_t diff = now - mLastFpsTime;
2930 if (diff > ms2ns(250)) {
2931 mFps = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
2932 LOGI("Frames Per Second: %.4f", mFps);
2933 mLastFpsTime = now;
2934 mLastFrameCount = mFrameCount;
2935 }
2936}
2937
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002938void QualcommCameraHardware::receivePreviewFrame(struct msm_frame *frame)
2939{
2940// LOGV("receivePreviewFrame E");
2941
2942 if (!mCameraRunning) {
2943 LOGE("ignoring preview callback--camera has been stopped");
2944 return;
2945 }
2946
Mohan Kandra740cfce2010-01-07 12:58:24 -08002947 if (UNLIKELY(mDebugFps)) {
2948 debugShowFPS();
2949 }
2950
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002951 mCallbackLock.lock();
2952 int msgEnabled = mMsgEnabled;
2953 data_callback pcb = mDataCallback;
2954 void *pdata = mCallbackCookie;
2955 data_callback_timestamp rcb = mDataCallbackTimestamp;
2956 void *rdata = mCallbackCookie;
2957 mCallbackLock.unlock();
2958
2959 // Find the offset within the heap of the current buffer.
Mohan Kandra284966d2010-01-05 13:39:15 -08002960 ssize_t offset_addr =
Mohan Kandrad9efed92010-01-15 19:08:39 -08002961 (ssize_t)frame->buffer - (ssize_t)mPreviewHeap->mHeap->base();
2962 ssize_t offset = offset_addr / mPreviewHeap->mAlignedBufferSize;
Mohan Kandra284966d2010-01-05 13:39:15 -08002963
2964 common_crop_t *crop = (common_crop_t *) (frame->cropinfo);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08002965
2966 mInPreviewCallback = true;
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002967 if(mUseOverlay) {
2968 if(mOverlay != NULL) {
2969 mOverlayLock.lock();
Mohan Kandrad9efed92010-01-15 19:08:39 -08002970 mOverlay->setFd(mPreviewHeap->mHeap->getHeapID());
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002971 if (crop->in2_w != 0 || crop->in2_h != 0) {
2972 zoomCropInfo.x = (crop->out2_w - crop->in2_w + 1) / 2 - 1;
2973 zoomCropInfo.y = (crop->out2_h - crop->in2_h + 1) / 2 - 1;
2974 zoomCropInfo.w = crop->in2_w;
2975 zoomCropInfo.h = crop->in2_h;
2976 mOverlay->setCrop(zoomCropInfo.x, zoomCropInfo.y,
2977 zoomCropInfo.w, zoomCropInfo.h);
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08002978 } else {
2979 // Reset zoomCropInfo variables. This will ensure that
2980 // stale values wont be used for postview
2981 zoomCropInfo.w = crop->in2_w;
2982 zoomCropInfo.h = crop->in2_h;
2983 }
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08002984 mOverlay->queueBuffer((void *)offset_addr);
2985 mLastQueuedFrame = (void *)frame->buffer;
2986 mOverlayLock.unlock();
2987 }
Mohan Kandra284966d2010-01-05 13:39:15 -08002988 } else {
Mohan Kandrad9efed92010-01-15 19:08:39 -08002989 if (crop->in2_w != 0 || crop->in2_h != 0) {
2990 dstOffset = (dstOffset + 1) % NUM_MORE_BUFS;
2991 offset = kPreviewBufferCount + dstOffset;
2992 ssize_t dstOffset_addr = offset * mPreviewHeap->mAlignedBufferSize;
2993 if( !native_zoom_image(mPreviewHeap->mHeap->getHeapID(),
2994 offset_addr, dstOffset_addr, crop)) {
2995 LOGE(" Error while doing MDP zoom ");
2996 }
2997 }
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08002998 }
Mohan Kandrad9efed92010-01-15 19:08:39 -08002999 if (pcb != NULL && (msgEnabled & CAMERA_MSG_PREVIEW_FRAME))
3000 pcb(CAMERA_MSG_PREVIEW_FRAME, mPreviewHeap->mBuffers[offset],
3001 pdata);
3002
Sravankb4f5f1c2010-01-21 11:06:17 +05303003 // If output2 enabled, Start Recording if recording is enabled by Services
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08003004 if( (mCurrentTarget == TARGET_MSM7630) && recordingEnabled() ) {
Sravankb4f5f1c2010-01-21 11:06:17 +05303005 if(!recordingState){
3006 recordingState = 1; // recording started
3007 LOGV(" in receivePreviewframe : recording enabled calling startRecording ");
3008 startRecording();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003009 }
Sravankb4f5f1c2010-01-21 11:06:17 +05303010 }
3011
3012 // If output is NOT enabled (targets otherthan 7x30 currently..)
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08003013 if( mCurrentTarget != TARGET_MSM7630 ) {
Sravankb4f5f1c2010-01-21 11:06:17 +05303014 if(rcb != NULL && (msgEnabled & CAMERA_MSG_VIDEO_FRAME)) {
3015 rcb(systemTime(), CAMERA_MSG_VIDEO_FRAME, mPreviewHeap->mBuffers[offset], rdata);
3016 Mutex::Autolock rLock(&mRecordFrameLock);
3017 if (mReleasedRecordingFrame != true) {
3018 LOGV("block waiting for frame release");
3019 mRecordWait.wait(mRecordFrameLock);
3020 LOGV("frame released, continuing");
3021 }
3022 mReleasedRecordingFrame = false;
3023 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003024 }
3025 mInPreviewCallback = false;
3026
3027// LOGV("receivePreviewFrame X");
3028}
3029
Sravankb4f5f1c2010-01-21 11:06:17 +05303030
3031bool QualcommCameraHardware::initRecord()
3032{
3033 LOGV("initREcord E");
3034
3035 mRecordFrameSize = (mDimension.video_width * mDimension.video_height *3)/2;
3036 mRecordHeap = new PmemPool("/dev/pmem_adsp",
3037 MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,
3038 mCameraControlFd,
3039 MSM_PMEM_VIDEO,
3040 mRecordFrameSize,
3041 kRecordBufferCount,
3042 mRecordFrameSize,
3043 "record");
3044 if (!mRecordHeap->initialized()) {
3045 mRecordHeap.clear();
3046 LOGE("initRecord X: could not initialize record heap.");
3047 return false;
3048 }
3049 for (int cnt = 0; cnt < kRecordBufferCount; cnt++) {
3050 recordframes[cnt].fd = mRecordHeap->mHeap->getHeapID();
3051 recordframes[cnt].buffer =
3052 (uint32_t)mRecordHeap->mHeap->base() + mRecordHeap->mAlignedBufferSize * cnt;
3053 recordframes[cnt].y_off = 0;
3054 recordframes[cnt].cbcr_off = mDimension.video_width * mDimension.video_height;
3055 recordframes[cnt].path = OUTPUT_TYPE_V;
3056
3057 LOGV ("initRecord : record heap , video buffers buffer=%lu fd=%d y_off=%d cbcr_off=%d \n",
3058 (unsigned long)recordframes[cnt].buffer, recordframes[cnt].fd, recordframes[cnt].y_off,
3059 recordframes[cnt].cbcr_off);
3060 }
3061
3062 // initial setup : buffers 1,2,3 with kernel , 4 with camframe , 5,6,7,8 in free Q
3063 // flush the busy Q
3064 cam_frame_flush_video();
3065
Mohan Kandra156d0ac2010-01-25 16:59:17 -08003066 mVideoThreadWaitLock.lock();
3067 while (mVideoThreadRunning) {
3068 LOGV("initRecord: waiting for old video thread to complete.");
3069 mVideoThreadWait.wait(mVideoThreadWaitLock);
3070 LOGV("initRecord : old video thread completed.");
3071 }
3072 mVideoThreadWaitLock.unlock();
3073
Sravankb4f5f1c2010-01-21 11:06:17 +05303074 // Start video thread and wait for busy frames to be encoded.
3075 mVideoThreadWaitLock.lock();
3076 mVideoThreadExit = 0;
3077 pthread_attr_t attr;
3078 pthread_attr_init(&attr);
3079 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
Mohan Kandra156d0ac2010-01-25 16:59:17 -08003080 mVideoThreadRunning = pthread_create(&mVideoThread,
Sravankb4f5f1c2010-01-21 11:06:17 +05303081 &attr,
3082 video_thread,
3083 NULL);
3084 mVideoThreadWaitLock.unlock();
3085 LOGV("initREcord X");
3086
3087 return true;
3088}
3089
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003090status_t QualcommCameraHardware::startRecording()
3091{
3092 LOGV("startRecording E");
Sravankb4f5f1c2010-01-21 11:06:17 +05303093 int ret;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003094 Mutex::Autolock l(&mLock);
3095 mReleasedRecordingFrame = false;
Sravankb4f5f1c2010-01-21 11:06:17 +05303096 if( (ret=startPreviewInternal())== NO_ERROR){
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08003097 if( mCurrentTarget == TARGET_MSM7630 ) {
Sravankb4f5f1c2010-01-21 11:06:17 +05303098 // flush free queue and add 5,6,7,8 buffers.
3099 LINK_cam_frame_flush_free_video();
3100 for(int i=ACTIVE_VIDEO_BUFFERS+1;i <kRecordBufferCount; i++)
3101 LINK_camframe_free_video(&recordframes[i]);
3102
3103 LOGV(" in startREcording : calling native_start_recording");
3104 native_start_recording(mCameraControlFd);
3105 recordingState = 1;
3106 }
3107 }
3108 return ret;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003109}
3110
3111void QualcommCameraHardware::stopRecording()
3112{
3113 LOGV("stopRecording: E");
3114 Mutex::Autolock l(&mLock);
3115 {
3116 mRecordFrameLock.lock();
3117 mReleasedRecordingFrame = true;
3118 mRecordWait.signal();
3119 mRecordFrameLock.unlock();
3120
3121 if(mDataCallback && (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)) {
3122 LOGV("stopRecording: X, preview still in progress");
3123 return;
3124 }
3125 }
Sravankb4f5f1c2010-01-21 11:06:17 +05303126 // If output2 enabled, exit video thread, invoke stop recording ioctl
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08003127 if( mCurrentTarget == TARGET_MSM7630 ) {
Sravankb4f5f1c2010-01-21 11:06:17 +05303128 mVideoThreadWaitLock.lock();
3129 mVideoThreadExit = 1;
3130 mVideoThreadWaitLock.unlock();
3131 native_stop_recording(mCameraControlFd);
3132 }
3133 else // for other targets where output2 is not enabled
3134 stopPreviewInternal();
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003135
Sravankb4f5f1c2010-01-21 11:06:17 +05303136 recordingState = 0; // recording not started
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003137 LOGV("stopRecording: X");
3138}
3139
3140void QualcommCameraHardware::releaseRecordingFrame(
3141 const sp<IMemory>& mem __attribute__((unused)))
3142{
3143 LOGV("releaseRecordingFrame E");
3144 Mutex::Autolock rLock(&mRecordFrameLock);
3145 mReleasedRecordingFrame = true;
3146 mRecordWait.signal();
Sravankb4f5f1c2010-01-21 11:06:17 +05303147
3148 // Ff 7x30 : add the frame to the free camframe queue
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08003149 if( mCurrentTarget == TARGET_MSM7630 ) {
Sravankb4f5f1c2010-01-21 11:06:17 +05303150 ssize_t offset;
3151 size_t size;
3152 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
3153 msm_frame* releaseframe = NULL;
3154 LOGV(" in release recording frame : heap base %d offset %d buffer %d ", heap->base(), offset, heap->base() + offset );
3155 int cnt;
3156 for (cnt = 0; cnt < kRecordBufferCount; cnt++) {
3157 if((unsigned int)recordframes[cnt].buffer == (unsigned int)(heap->base()+ offset)){
3158 LOGV("in release recording frame found match , releasing buffer %d", (unsigned int)recordframes[cnt].buffer);
3159 releaseframe = &recordframes[cnt];
3160 break;
3161 }
3162 }
3163 if(cnt < kRecordBufferCount) {
3164 // do this only if frame thread is running
3165 mFrameThreadWaitLock.lock();
3166 if(mFrameThreadRunning )
3167 LINK_camframe_free_video(releaseframe);
3168
3169 mFrameThreadWaitLock.unlock();
3170 } else {
3171 LOGE("in release recordingframe XXXXX error , buffer not found");
3172 for (int i=0; i< kRecordBufferCount; i++) {
3173 LOGE(" recordframes[%d].buffer = %d", i, (unsigned int)recordframes[i].buffer);
3174 }
3175 }
3176 }
3177
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003178 LOGV("releaseRecordingFrame X");
3179}
3180
3181bool QualcommCameraHardware::recordingEnabled()
3182{
3183 return mCameraRunning && mDataCallbackTimestamp && (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME);
3184}
3185
3186void QualcommCameraHardware::notifyShutter(common_crop_t *crop)
3187{
3188 mShutterLock.lock();
3189 image_rect_type size;
3190
3191 if (mShutterPending && mNotifyCallback && (mMsgEnabled & CAMERA_MSG_SHUTTER)) {
3192 LOGV("out2_w=%d, out2_h=%d, in2_w=%d, in2_h=%d",
3193 crop->out2_w, crop->out2_h, crop->in2_w, crop->in2_h);
3194 LOGV("out1_w=%d, out1_h=%d, in1_w=%d, in1_h=%d",
3195 crop->out1_w, crop->out1_h, crop->in1_w, crop->in1_h);
3196
3197 // To workaround a bug in MDP which happens if either
3198 // dimension > 2048, we display the thumbnail instead.
3199 mDisplayHeap = mRawHeap;
3200 if (crop->in1_w == 0 || crop->in1_h == 0) {
3201 // Full size
3202 size.width = mDimension.picture_width;
3203 size.height = mDimension.picture_height;
3204 if (size.width > 2048 || size.height > 2048) {
3205 size.width = mDimension.ui_thumbnail_width;
3206 size.height = mDimension.ui_thumbnail_height;
3207 mDisplayHeap = mThumbnailHeap;
3208 }
3209 } else {
3210 // Cropped
3211 size.width = crop->in2_w & ~1;
3212 size.height = crop->in2_h & ~1;
3213 if (size.width > 2048 || size.height > 2048) {
3214 size.width = crop->in1_w & ~1;
3215 size.height = crop->in1_h & ~1;
3216 mDisplayHeap = mThumbnailHeap;
3217 }
3218 }
3219
3220 mNotifyCallback(CAMERA_MSG_SHUTTER, (int32_t)&size, 0,
3221 mCallbackCookie);
3222 mShutterPending = false;
3223 }
3224 mShutterLock.unlock();
3225}
3226
3227static void receive_shutter_callback(common_crop_t *crop)
3228{
3229 LOGV("receive_shutter_callback: E");
3230 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
3231 if (obj != 0) {
3232 obj->notifyShutter(crop);
3233 }
3234 LOGV("receive_shutter_callback: X");
3235}
3236
3237// Crop the picture in place.
3238static void crop_yuv420(uint32_t width, uint32_t height,
3239 uint32_t cropped_width, uint32_t cropped_height,
3240 uint8_t *image)
3241{
3242 uint32_t i, x, y;
3243 uint8_t* chroma_src, *chroma_dst;
3244
3245 // Calculate the start position of the cropped area.
3246 x = (width - cropped_width) / 2;
3247 y = (height - cropped_height) / 2;
3248 x &= ~1;
3249 y &= ~1;
3250
3251 // Copy luma component.
3252 for(i = 0; i < cropped_height; i++)
3253 memcpy(image + i * cropped_width,
3254 image + width * (y + i) + x,
3255 cropped_width);
3256
3257 chroma_src = image + width * height;
3258 chroma_dst = image + cropped_width * cropped_height;
3259
3260 // Copy chroma components.
3261 cropped_height /= 2;
3262 y /= 2;
3263 for(i = 0; i < cropped_height; i++)
3264 memcpy(chroma_dst + i * cropped_width,
3265 chroma_src + width * (y + i) + x,
3266 cropped_width);
3267}
3268
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08003269
3270void QualcommCameraHardware::receiveRawSnapshot(){
3271 LOGV("receiveRawSnapshot E");
3272
3273 Mutex::Autolock cbLock(&mCallbackLock);
3274
3275 notifyShutter(&mCrop);
3276
3277 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
3278
3279 if(native_get_picture(mCameraControlFd, &mCrop) == false) {
3280 LOGE("receiveRawSnapshot X: native_get_picture failed!");
3281 return;
3282 }
3283
3284 //Create a Ashmem heap to copy data from PMem heap for application layer
3285 if(mRawSnapshotAshmemHeap != NULL){
3286 LOGV("receiveRawSnapshot: clearing old mRawSnapShotAshmemHeap.");
3287 mRawSnapshotAshmemHeap.clear();
3288 }
3289 mRawSnapshotAshmemHeap = new AshmemPool(
3290 mRawSnapShotPmemHeap->mBufferSize,
3291 mRawSnapShotPmemHeap->mNumBuffers,
3292 mRawSnapShotPmemHeap->mFrameSize,
3293 "raw ashmem snapshot camera"
3294 );
3295
3296 if(!mRawSnapshotAshmemHeap->initialized()){
3297 LOGE("receiveRawSnapshot X: error initializing mRawSnapshotHeap");
3298 deinitRawSnapshot();
3299 return;
3300 }
3301
3302 memcpy(mRawSnapshotAshmemHeap->mHeap->base(),
3303 mRawSnapShotPmemHeap->mHeap->base(),
3304 mRawSnapShotPmemHeap->mHeap->getSize());
3305
3306 mDataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mRawSnapshotAshmemHeap->mBuffers[0],
3307 mCallbackCookie);
3308
3309 }
3310
3311 //cleanup
3312 deinitRawSnapshot();
3313
3314 LOGV("receiveRawSnapshot X");
3315}
3316
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003317void QualcommCameraHardware::receiveRawPicture()
3318{
3319 LOGV("receiveRawPicture: E");
3320
3321 Mutex::Autolock cbLock(&mCallbackLock);
3322 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_RAW_IMAGE)) {
3323 if(native_get_picture(mCameraControlFd, &mCrop) == false) {
3324 LOGE("getPicture failed!");
3325 return;
3326 }
3327 mCrop.in1_w &= ~1;
3328 mCrop.in1_h &= ~1;
3329 mCrop.in2_w &= ~1;
3330 mCrop.in2_h &= ~1;
3331
3332 // By the time native_get_picture returns, picture is taken. Call
3333 // shutter callback if cam config thread has not done that.
3334 notifyShutter(&mCrop);
3335
3336 // Crop the image if zoomed.
3337 if (mCrop.in2_w != 0 && mCrop.in2_h != 0) {
3338 crop_yuv420(mCrop.out2_w, mCrop.out2_h, mCrop.in2_w, mCrop.in2_h,
3339 (uint8_t *)mRawHeap->mHeap->base());
3340 crop_yuv420(mCrop.out1_w, mCrop.out1_h, mCrop.in1_w, mCrop.in1_h,
3341 (uint8_t *)mThumbnailHeap->mHeap->base());
3342 // We do not need jpeg encoder to upscale the image. Set the new
3343 // dimension for encoder.
3344 mDimension.orig_picture_dx = mCrop.in2_w;
3345 mDimension.orig_picture_dy = mCrop.in2_h;
3346 mDimension.thumbnail_width = mCrop.in1_w;
3347 mDimension.thumbnail_height = mCrop.in1_h;
3348 memset(&mCrop, 0, sizeof(mCrop));
3349 }
3350
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003351 if( mUseOverlay && (mOverlay != NULL) ) {
3352 mOverlay->setFd(mPostViewHeap->mHeap->getHeapID());
3353 if( zoomCropInfo.w !=0 && zoomCropInfo.h !=0) {
3354 LOGD(" zoomCropInfo non-zero, setting crop ");
3355 mOverlay->setCrop(zoomCropInfo.x, zoomCropInfo.y,
3356 zoomCropInfo.w, zoomCropInfo.h);
3357 }
3358 LOGD(" Queueing Postview for display ");
3359 mOverlay->queueBuffer((void *)0);
3360 }
3361
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003362 mDataCallback(CAMERA_MSG_RAW_IMAGE, mDisplayHeap->mBuffers[0],
3363 mCallbackCookie);
3364 }
3365 else LOGV("Raw-picture callback was canceled--skipping.");
3366
3367 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
3368 mJpegSize = 0;
3369 if (LINK_jpeg_encoder_init()) {
3370 if(native_jpeg_encode()) {
3371 LOGV("receiveRawPicture: X (success)");
3372 return;
3373 }
3374 LOGE("jpeg encoding failed");
3375 }
3376 else LOGE("receiveRawPicture X: jpeg_encoder_init failed.");
3377 }
3378 else LOGV("JPEG callback is NULL, not encoding image.");
3379 deinitRaw();
3380 LOGV("receiveRawPicture: X");
3381}
3382
3383void QualcommCameraHardware::receiveJpegPictureFragment(
3384 uint8_t *buff_ptr, uint32_t buff_size)
3385{
3386 uint32_t remaining = mJpegHeap->mHeap->virtualSize();
3387 remaining -= mJpegSize;
3388 uint8_t *base = (uint8_t *)mJpegHeap->mHeap->base();
3389
3390 LOGV("receiveJpegPictureFragment size %d", buff_size);
3391 if (buff_size > remaining) {
3392 LOGE("receiveJpegPictureFragment: size %d exceeds what "
3393 "remains in JPEG heap (%d), truncating",
3394 buff_size,
3395 remaining);
3396 buff_size = remaining;
3397 }
3398 memcpy(base + mJpegSize, buff_ptr, buff_size);
3399 mJpegSize += buff_size;
3400}
3401
3402void QualcommCameraHardware::receiveJpegPicture(void)
3403{
3404 LOGV("receiveJpegPicture: E image (%d uint8_ts out of %d)",
3405 mJpegSize, mJpegHeap->mBufferSize);
3406 Mutex::Autolock cbLock(&mCallbackLock);
3407
3408 int index = 0, rc;
3409
3410 if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
3411 // The reason we do not allocate into mJpegHeap->mBuffers[offset] is
3412 // that the JPEG image's size will probably change from one snapshot
3413 // to the next, so we cannot reuse the MemoryBase object.
3414 sp<MemoryBase> buffer = new
3415 MemoryBase(mJpegHeap->mHeap,
3416 index * mJpegHeap->mBufferSize +
3417 0,
3418 mJpegSize);
3419 mDataCallback(CAMERA_MSG_COMPRESSED_IMAGE, buffer, mCallbackCookie);
3420 buffer = NULL;
3421 }
3422 else LOGV("JPEG callback was cancelled--not delivering image.");
3423
3424 LINK_jpeg_encoder_join();
3425 deinitRaw();
3426
3427 LOGV("receiveJpegPicture: X callback done.");
3428}
3429
3430bool QualcommCameraHardware::previewEnabled()
3431{
3432 return mCameraRunning && mDataCallback && (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME);
3433}
3434
3435status_t QualcommCameraHardware::setPreviewSize(const CameraParameters& params)
3436{
3437 int width, height;
3438 params.getPreviewSize(&width, &height);
3439 LOGV("requested preview size %d x %d", width, height);
3440
3441 // Validate the preview size
3442 for (size_t i = 0; i < PREVIEW_SIZE_COUNT; ++i) {
3443 if (width == preview_sizes[i].width
3444 && height == preview_sizes[i].height) {
3445 mParameters.setPreviewSize(width, height);
3446 mDimension.display_width = width;
3447 mDimension.display_height = height;
3448 return NO_ERROR;
3449 }
3450 }
3451 LOGE("Invalid preview size requested: %dx%d", width, height);
3452 return BAD_VALUE;
3453}
3454
3455status_t QualcommCameraHardware::setPictureSize(const CameraParameters& params)
3456{
3457 int width, height;
3458 params.getPictureSize(&width, &height);
3459 LOGV("requested picture size %d x %d", width, height);
3460
3461 // Validate the picture size
Srinivasan Kannan3b9e8df2009-12-05 12:21:46 -08003462 for (int i = 0; i < supportedPictureSizesCount; ++i) {
3463 if (width == picture_sizes_ptr[i].width
3464 && height == picture_sizes_ptr[i].height) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003465 mParameters.setPictureSize(width, height);
3466 mDimension.picture_width = width;
3467 mDimension.picture_height = height;
3468 return NO_ERROR;
3469 }
3470 }
3471 LOGE("Invalid picture size requested: %dx%d", width, height);
3472 return BAD_VALUE;
3473}
3474
3475status_t QualcommCameraHardware::setJpegQuality(const CameraParameters& params) {
3476 status_t rc = NO_ERROR;
3477 int quality = params.getInt(CameraParameters::KEY_JPEG_QUALITY);
3478 if (quality > 0 && quality <= 100) {
3479 mParameters.set(CameraParameters::KEY_JPEG_QUALITY, quality);
3480 } else {
3481 LOGE("Invalid jpeg quality=%d", quality);
3482 rc = BAD_VALUE;
3483 }
3484
3485 quality = params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY);
3486 if (quality > 0 && quality <= 100) {
3487 mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, quality);
3488 } else {
3489 LOGE("Invalid jpeg thumbnail quality=%d", quality);
3490 rc = BAD_VALUE;
3491 }
3492 return rc;
3493}
3494
3495status_t QualcommCameraHardware::setEffect(const CameraParameters& params)
3496{
3497 const char *str = params.get(CameraParameters::KEY_EFFECT);
3498 if (str != NULL) {
3499 int32_t value = attr_lookup(effects, sizeof(effects) / sizeof(str_map), str);
3500 if (value != NOT_FOUND) {
Mohan Kandra93f1bfb2009-12-15 16:55:33 -08003501 if(!strcmp(sensorType->name, "2mp") && (value != CAMERA_EFFECT_OFF)
3502 &&(value != CAMERA_EFFECT_MONO) && (value != CAMERA_EFFECT_NEGATIVE)
3503 &&(value != CAMERA_EFFECT_SOLARIZE) && (value != CAMERA_EFFECT_SEPIA)) {
3504 LOGE("Special effect parameter is not supported for this sensor");
3505 return NO_ERROR;
3506 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003507 mParameters.set(CameraParameters::KEY_EFFECT, str);
3508 bool ret = native_set_parm(CAMERA_SET_PARM_EFFECT, sizeof(value),
3509 (void *)&value);
3510 return ret ? NO_ERROR : UNKNOWN_ERROR;
3511 }
3512 }
3513 LOGE("Invalid effect value: %s", (str == NULL) ? "NULL" : str);
3514 return BAD_VALUE;
3515}
3516
Apurva Rajguru55562b02009-12-03 12:25:35 -08003517status_t QualcommCameraHardware::setAutoExposure(const CameraParameters& params)
3518{
Mohan Kandra93f1bfb2009-12-15 16:55:33 -08003519 if(!strcmp(sensorType->name, "2mp")) {
3520 LOGE("Auto Exposure not supported for this sensor");
3521 return NO_ERROR;
3522 }
Apurva Rajguru55562b02009-12-03 12:25:35 -08003523 const char *str = params.get(CameraParameters::KEY_AUTO_EXPOSURE);
3524 if (str != NULL) {
3525 int32_t value = attr_lookup(autoexposure, sizeof(autoexposure) / sizeof(str_map), str);
3526 if (value != NOT_FOUND) {
3527 mParameters.set(CameraParameters::KEY_AUTO_EXPOSURE, str);
3528 bool ret = native_set_parm(CAMERA_SET_PARM_EXPOSURE, sizeof(value),
3529 (void *)&value);
3530 return ret ? NO_ERROR : UNKNOWN_ERROR;
3531 }
3532 }
3533 LOGE("Invalid auto exposure value: %s", (str == NULL) ? "NULL" : str);
3534 return BAD_VALUE;
3535}
3536
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003537status_t QualcommCameraHardware::setSharpness(const CameraParameters& params)
3538{
3539 if(!strcmp(sensorType->name, "2mp")) {
3540 LOGE("Sharpness not supported for this sensor");
3541 return NO_ERROR;
3542 }
3543 int sharpness = params.getInt(CameraParameters::KEY_SHARPNESS);
3544 if((sharpness < CAMERA_MIN_SHARPNESS
3545 || sharpness > CAMERA_MAX_SHARPNESS))
3546 return UNKNOWN_ERROR;
Srinivasan Kannan551fd262010-01-14 17:48:30 -08003547
3548 LOGV("setting sharpness %d", sharpness);
3549 mParameters.set(CameraParameters::KEY_SHARPNESS, sharpness);
3550 bool ret = native_set_parm(CAMERA_SET_PARM_SHARPNESS, sizeof(sharpness),
3551 (void *)&sharpness);
3552 return ret ? NO_ERROR : UNKNOWN_ERROR;
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003553}
3554
3555status_t QualcommCameraHardware::setContrast(const CameraParameters& params)
3556{
3557 if(!strcmp(sensorType->name, "2mp")) {
3558 LOGE("Contrast not supported for this sensor");
3559 return NO_ERROR;
3560 }
3561 int contrast = params.getInt(CameraParameters::KEY_CONTRAST);
3562 if((contrast < CAMERA_MIN_CONTRAST)
3563 || (contrast > CAMERA_MAX_CONTRAST))
3564 return UNKNOWN_ERROR;
Srinivasan Kannan551fd262010-01-14 17:48:30 -08003565
3566 LOGV("setting contrast %d", contrast);
3567 mParameters.set(CameraParameters::KEY_CONTRAST, contrast);
3568 bool ret = native_set_parm(CAMERA_SET_PARM_CONTRAST, sizeof(contrast),
3569 (void *)&contrast);
3570 return ret ? NO_ERROR : UNKNOWN_ERROR;
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003571}
3572
3573status_t QualcommCameraHardware::setSaturation(const CameraParameters& params)
3574{
3575 if(!strcmp(sensorType->name, "2mp")) {
3576 LOGE("Saturation not supported for this sensor");
3577 return NO_ERROR;
3578 }
Srinivasan Kannan551fd262010-01-14 17:48:30 -08003579
Kiran Kumar H Nf87cf862010-01-27 14:34:34 -08003580 const char *str = params.get(CameraParameters::KEY_EFFECT);
3581 int32_t value = attr_lookup(effects, sizeof(effects) / sizeof(str_map), str);
3582
3583 if( (value != CAMERA_EFFECT_MONO) && (value != CAMERA_EFFECT_NEGATIVE)
3584 && (value != CAMERA_EFFECT_AQUA) && (value != CAMERA_EFFECT_SEPIA)) {
3585
3586 int saturation = params.getInt(CameraParameters::KEY_SATURATION);
3587 if((saturation < CAMERA_MIN_SATURATION)
3588 || (saturation > CAMERA_MAX_SATURATION))
3589 return UNKNOWN_ERROR;
3590
3591 LOGV("setting saturation %d", saturation);
3592 mParameters.set(CameraParameters::KEY_SATURATION, saturation);
3593 bool ret = native_set_parm(CAMERA_SET_PARM_SATURATION, sizeof(saturation),
3594 (void *)&saturation);
3595 return ret ? NO_ERROR : UNKNOWN_ERROR;
3596 } else {
3597 LOGE(" Saturation value will not be set " \
3598 "when the effect selected is %s", str);
3599 return NO_ERROR;
3600 }
Srinivasan Kannanbddfd502010-01-03 17:27:36 -08003601}
3602
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303603status_t QualcommCameraHardware::setBrightness(const CameraParameters& params) {
3604 int brightness = params.getInt("luma-adaptation");
3605 if (mBrightness != brightness) {
3606 LOGV(" new brightness value : %d ", brightness);
3607 mBrightness = brightness;
3608
3609 bool ret = native_set_parm(CAMERA_SET_PARM_BRIGHTNESS, sizeof(mBrightness),
3610 (void *)&mBrightness);
3611 return ret ? NO_ERROR : UNKNOWN_ERROR;
3612 } else {
3613 return NO_ERROR;
3614 }
3615}
3616
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003617status_t QualcommCameraHardware::setWhiteBalance(const CameraParameters& params)
3618{
3619 const char *str = params.get(CameraParameters::KEY_WHITE_BALANCE);
3620 if (str != NULL) {
3621 int32_t value = attr_lookup(whitebalance, sizeof(whitebalance) / sizeof(str_map), str);
3622 if (value != NOT_FOUND) {
3623 mParameters.set(CameraParameters::KEY_WHITE_BALANCE, str);
3624 bool ret = native_set_parm(CAMERA_SET_PARM_WB, sizeof(value),
3625 (void *)&value);
3626 return ret ? NO_ERROR : UNKNOWN_ERROR;
3627 }
3628 }
3629 LOGE("Invalid whitebalance value: %s", (str == NULL) ? "NULL" : str);
3630 return BAD_VALUE;
3631}
3632
3633status_t QualcommCameraHardware::setFlash(const CameraParameters& params)
3634{
3635 if (!mSensorInfo.flash_enabled) {
3636 LOGV("%s: flash not supported", __FUNCTION__);
3637 return NO_ERROR;
3638 }
3639
3640 const char *str = params.get(CameraParameters::KEY_FLASH_MODE);
3641 if (str != NULL) {
3642 int32_t value = attr_lookup(flash, sizeof(flash) / sizeof(str_map), str);
3643 if (value != NOT_FOUND) {
3644 mParameters.set(CameraParameters::KEY_FLASH_MODE, str);
3645 bool ret = native_set_parm(CAMERA_SET_PARM_LED_MODE,
3646 sizeof(value), (void *)&value);
3647 return ret ? NO_ERROR : UNKNOWN_ERROR;
3648 }
3649 }
3650 LOGE("Invalid flash mode value: %s", (str == NULL) ? "NULL" : str);
3651 return BAD_VALUE;
3652}
3653
3654status_t QualcommCameraHardware::setAntibanding(const CameraParameters& params)
3655{
Srinivasan Kannan2229d272010-01-05 14:58:28 -08003656 if(!strcmp(sensorType->name, "2mp")) {
3657 LOGE("Parameter AntiBanding is not supported for this sensor");
3658 return NO_ERROR;
3659 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003660 const char *str = params.get(CameraParameters::KEY_ANTIBANDING);
3661 if (str != NULL) {
3662 int value = (camera_antibanding_type)attr_lookup(
3663 antibanding, sizeof(antibanding) / sizeof(str_map), str);
3664 if (value != NOT_FOUND) {
3665 camera_antibanding_type temp = (camera_antibanding_type) value;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003666 mParameters.set(CameraParameters::KEY_ANTIBANDING, str);
Srinivasan Kannan2229d272010-01-05 14:58:28 -08003667 bool ret;
3668 if (temp == CAMERA_ANTIBANDING_AUTO) {
3669 ret = native_set_parm(CAMERA_ENABLE_AFD,
3670 0, NULL);
3671 } else {
3672 ret = native_set_parm(CAMERA_SET_PARM_ANTIBANDING,
3673 sizeof(camera_antibanding_type), (void *)&temp);
3674 }
3675 return ret ? NO_ERROR : UNKNOWN_ERROR;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003676 }
3677 }
3678 LOGE("Invalid antibanding value: %s", (str == NULL) ? "NULL" : str);
3679 return BAD_VALUE;
3680}
3681
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303682status_t QualcommCameraHardware::setLensshadeValue(const CameraParameters& params)
3683{
Mohan Kandra93f1bfb2009-12-15 16:55:33 -08003684 if(!strcmp(sensorType->name, "2mp")) {
3685 LOGE("Parameter Rolloff is not supported for this sensor");
3686 return NO_ERROR;
3687 }
Nishant Panditc8c1ee72009-12-03 16:24:02 +05303688 const char *str = params.get(CameraParameters::KEY_LENSSHADE);
3689 if (str != NULL) {
3690 int value = attr_lookup(lensshade,
3691 sizeof(lensshade) / sizeof(str_map), str);
3692 if (value != NOT_FOUND) {
3693 int8_t temp = (int8_t)value;
3694 mParameters.set(CameraParameters::KEY_LENSSHADE, str);
3695 native_set_parm(CAMERA_SET_PARM_ROLLOFF, sizeof(int8_t), (void *)&temp);
3696 return NO_ERROR;
3697 }
3698 }
3699 LOGE("Invalid lensShade value: %s", (str == NULL) ? "NULL" : str);
3700 return BAD_VALUE;
3701}
3702
3703status_t QualcommCameraHardware::setISOValue(const CameraParameters& params) {
3704 const char *str = params.get(CameraParameters::KEY_ISO_MODE);
3705 if (str != NULL) {
3706 int value = (camera_iso_mode_type)attr_lookup(
3707 iso, sizeof(iso) / sizeof(str_map), str);
3708 if (value != NOT_FOUND) {
3709 camera_iso_mode_type temp = (camera_iso_mode_type) value;
3710 mParameters.set(CameraParameters::KEY_ISO_MODE, str);
3711 native_set_parm(CAMERA_SET_PARM_ISO, sizeof(camera_iso_mode_type), (void *)&temp);
3712 return NO_ERROR;
3713 }
3714 }
3715 LOGE("Invalid Iso value: %s", (str == NULL) ? "NULL" : str);
3716 return BAD_VALUE;
3717}
3718
3719
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003720status_t QualcommCameraHardware::setGpsLocation(const CameraParameters& params)
3721{
3722 const char *latitude = params.get(CameraParameters::KEY_GPS_LATITUDE);
3723 if (latitude) {
3724 mParameters.set(CameraParameters::KEY_GPS_LATITUDE, latitude);
3725 }
3726
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08003727 const char *latitudeRef = params.get(CameraParameters::KEY_GPS_LATITUDE_REF);
3728 if (latitudeRef) {
3729 mParameters.set(CameraParameters::KEY_GPS_LATITUDE_REF, latitudeRef);
3730 }
3731
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003732 const char *longitude = params.get(CameraParameters::KEY_GPS_LONGITUDE);
3733 if (longitude) {
3734 mParameters.set(CameraParameters::KEY_GPS_LONGITUDE, longitude);
3735 }
3736
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08003737 const char *longitudeRef = params.get(CameraParameters::KEY_GPS_LONGITUDE_REF);
3738 if (longitudeRef) {
3739 mParameters.set(CameraParameters::KEY_GPS_LONGITUDE_REF, longitudeRef);
3740 }
3741
3742 const char *altitudeRef = params.get(CameraParameters::KEY_GPS_ALTITUDE_REF);
3743 if (altitudeRef) {
3744 mParameters.set(CameraParameters::KEY_GPS_ALTITUDE_REF, altitudeRef);
3745 }
3746
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003747 const char *altitude = params.get(CameraParameters::KEY_GPS_ALTITUDE);
3748 if (altitude) {
3749 mParameters.set(CameraParameters::KEY_GPS_ALTITUDE, altitude);
3750 }
3751
Apurva Rajguru66bdd7f2009-12-10 19:28:02 -08003752 const char *status = params.get(CameraParameters::KEY_GPS_STATUS);
3753 if (status) {
3754 mParameters.set(CameraParameters::KEY_GPS_STATUS, status);
3755 }
3756
3757 const char *dateTime = params.get(CameraParameters::KEY_EXIF_DATETIME);
3758 if (dateTime) {
3759 mParameters.set(CameraParameters::KEY_EXIF_DATETIME, dateTime);
3760 }
3761
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003762 const char *timestamp = params.get(CameraParameters::KEY_GPS_TIMESTAMP);
3763 if (timestamp) {
3764 mParameters.set(CameraParameters::KEY_GPS_TIMESTAMP, timestamp);
3765 }
3766 return NO_ERROR;
3767}
3768
3769status_t QualcommCameraHardware::setRotation(const CameraParameters& params)
3770{
3771 status_t rc = NO_ERROR;
3772 int rotation = params.getInt(CameraParameters::KEY_ROTATION);
3773 if (rotation != NOT_FOUND) {
3774 if (rotation == 0 || rotation == 90 || rotation == 180
3775 || rotation == 270) {
3776 mParameters.set(CameraParameters::KEY_ROTATION, rotation);
3777 } else {
3778 LOGE("Invalid rotation value: %d", rotation);
3779 rc = BAD_VALUE;
3780 }
3781 }
3782 return rc;
3783}
3784
3785status_t QualcommCameraHardware::setZoom(const CameraParameters& params)
3786{
3787 status_t rc = NO_ERROR;
3788 // No matter how many different zoom values the driver can provide, HAL
3789 // provides applictations the same number of zoom levels. The maximum driver
3790 // zoom value depends on sensor output (VFE input) and preview size (VFE
3791 // output) because VFE can only crop and cannot upscale. If the preview size
3792 // is bigger, the maximum zoom ratio is smaller. However, we want the
3793 // zoom ratio of each zoom level is always the same whatever the preview
3794 // size is. Ex: zoom level 1 is always 1.2x, zoom level 2 is 1.44x, etc. So,
3795 // we need to have a fixed maximum zoom value and do read it from the
3796 // driver.
Mohan Kandra284966d2010-01-05 13:39:15 -08003797 static const int ZOOM_STEP = 1;
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003798 int32_t zoom_level = params.getInt("zoom");
3799
Mohan Kandra284966d2010-01-05 13:39:15 -08003800 LOGV("Set zoom=%d", zoom_level);
3801 if(zoom_level >= 0 && zoom_level <= mMaxZoom) {
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003802 mParameters.set("zoom", zoom_level);
3803 int32_t zoom_value = ZOOM_STEP * zoom_level;
3804 bool ret = native_set_parm(CAMERA_SET_PARM_ZOOM,
3805 sizeof(zoom_value), (void *)&zoom_value);
3806 rc = ret ? NO_ERROR : UNKNOWN_ERROR;
3807 } else {
3808 rc = BAD_VALUE;
3809 }
3810
3811 return rc;
3812}
3813
3814status_t QualcommCameraHardware::setFocusMode(const CameraParameters& params)
3815{
3816 const char *str = params.get(CameraParameters::KEY_FOCUS_MODE);
3817 if (str != NULL) {
3818 int32_t value = attr_lookup(focus_modes,
3819 sizeof(focus_modes) / sizeof(str_map), str);
3820 if (value != NOT_FOUND) {
3821 mParameters.set(CameraParameters::KEY_FOCUS_MODE, str);
3822 // Focus step is reset to infinity when preview is started. We do
3823 // not need to do anything now.
3824 return NO_ERROR;
3825 }
3826 }
3827 LOGE("Invalid focus mode value: %s", (str == NULL) ? "NULL" : str);
3828 return BAD_VALUE;
3829}
3830
3831status_t QualcommCameraHardware::setOrientation(const CameraParameters& params)
3832{
3833 const char *str = params.get("orientation");
3834
3835 if (str != NULL) {
3836 if (strcmp(str, "portrait") == 0 || strcmp(str, "landscape") == 0) {
3837 // Camera service needs this to decide if the preview frames and raw
3838 // pictures should be rotated.
3839 mParameters.set("orientation", str);
3840 } else {
3841 LOGE("Invalid orientation value: %s", str);
3842 return BAD_VALUE;
3843 }
3844 }
3845 return NO_ERROR;
3846}
3847
Srinivasan Kannan39dae8e2009-12-03 15:52:34 -08003848status_t QualcommCameraHardware::setPictureFormat(const CameraParameters& params)
3849{
3850 const char * str = params.get(CameraParameters::KEY_PICTURE_FORMAT);
3851
3852 if(str != NULL){
3853 int32_t value = attr_lookup(picture_formats,
3854 sizeof(picture_formats) / sizeof(str_map), str);
3855 if(value != NOT_FOUND){
3856 mParameters.set(CameraParameters::KEY_PICTURE_FORMAT, str);
3857 } else {
3858 LOGE("Invalid Picture Format value: %s", str);
3859 return BAD_VALUE;
3860 }
3861 }
3862 return NO_ERROR;
3863}
3864
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003865QualcommCameraHardware::MemPool::MemPool(int buffer_size, int num_buffers,
3866 int frame_size,
3867 const char *name) :
3868 mBufferSize(buffer_size),
3869 mNumBuffers(num_buffers),
3870 mFrameSize(frame_size),
3871 mBuffers(NULL), mName(name)
3872{
3873 int page_size_minus_1 = getpagesize() - 1;
3874 mAlignedBufferSize = (buffer_size + page_size_minus_1) & (~page_size_minus_1);
3875}
3876
3877void QualcommCameraHardware::MemPool::completeInitialization()
3878{
3879 // If we do not know how big the frame will be, we wait to allocate
3880 // the buffers describing the individual frames until we do know their
3881 // size.
3882
3883 if (mFrameSize > 0) {
3884 mBuffers = new sp<MemoryBase>[mNumBuffers];
3885 for (int i = 0; i < mNumBuffers; i++) {
3886 mBuffers[i] = new
3887 MemoryBase(mHeap,
3888 i * mAlignedBufferSize,
3889 mFrameSize);
3890 }
3891 }
3892}
3893
3894QualcommCameraHardware::AshmemPool::AshmemPool(int buffer_size, int num_buffers,
3895 int frame_size,
3896 const char *name) :
3897 QualcommCameraHardware::MemPool(buffer_size,
3898 num_buffers,
3899 frame_size,
3900 name)
3901{
3902 LOGV("constructing MemPool %s backed by ashmem: "
3903 "%d frames @ %d uint8_ts, "
3904 "buffer size %d",
3905 mName,
3906 num_buffers, frame_size, buffer_size);
3907
3908 int page_mask = getpagesize() - 1;
3909 int ashmem_size = buffer_size * num_buffers;
3910 ashmem_size += page_mask;
3911 ashmem_size &= ~page_mask;
3912
3913 mHeap = new MemoryHeapBase(ashmem_size);
3914
3915 completeInitialization();
3916}
3917
3918static bool register_buf(int camfd,
3919 int size,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08003920 int frame_size,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003921 int pmempreviewfd,
3922 uint32_t offset,
3923 uint8_t *buf,
3924 int pmem_type,
3925 bool vfe_can_write,
3926 bool register_buffer = true);
3927
3928QualcommCameraHardware::PmemPool::PmemPool(const char *pmem_pool,
3929 int flags,
3930 int camera_control_fd,
3931 int pmem_type,
3932 int buffer_size, int num_buffers,
3933 int frame_size,
3934 const char *name) :
3935 QualcommCameraHardware::MemPool(buffer_size,
3936 num_buffers,
3937 frame_size,
3938 name),
3939 mPmemType(pmem_type),
3940 mCameraControlFd(dup(camera_control_fd))
3941{
3942 LOGV("constructing MemPool %s backed by pmem pool %s: "
3943 "%d frames @ %d bytes, buffer size %d",
3944 mName,
3945 pmem_pool, num_buffers, frame_size,
3946 buffer_size);
3947
3948 LOGV("%s: duplicating control fd %d --> %d",
3949 __FUNCTION__,
3950 camera_control_fd, mCameraControlFd);
3951
3952 // Make a new mmap'ed heap that can be shared across processes.
3953 // mAlignedBufferSize is already in 4k aligned. (do we need total size necessary to be in power of 2??)
3954 mAlignedSize = mAlignedBufferSize * num_buffers;
3955
3956 sp<MemoryHeapBase> masterHeap =
3957 new MemoryHeapBase(pmem_pool, mAlignedSize, flags);
3958
3959 if (masterHeap->getHeapID() < 0) {
3960 LOGE("failed to construct master heap for pmem pool %s", pmem_pool);
3961 masterHeap.clear();
3962 return;
3963 }
3964
3965 sp<MemoryHeapPmem> pmemHeap = new MemoryHeapPmem(masterHeap, flags);
3966 if (pmemHeap->getHeapID() >= 0) {
3967 pmemHeap->slap();
3968 masterHeap.clear();
3969 mHeap = pmemHeap;
3970 pmemHeap.clear();
3971
3972 mFd = mHeap->getHeapID();
3973 if (::ioctl(mFd, PMEM_GET_SIZE, &mSize)) {
3974 LOGE("pmem pool %s ioctl(PMEM_GET_SIZE) error %s (%d)",
3975 pmem_pool,
3976 ::strerror(errno), errno);
3977 mHeap.clear();
3978 return;
3979 }
3980
3981 LOGV("pmem pool %s ioctl(fd = %d, PMEM_GET_SIZE) is %ld",
3982 pmem_pool,
3983 mFd,
3984 mSize.len);
Mohan Kandra284966d2010-01-05 13:39:15 -08003985 LOGD("mBufferSize=%d, mAlignedBufferSize=%d\n", mBufferSize, mAlignedBufferSize);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08003986 // Unregister preview buffers with the camera drivers. Allow the VFE to write
3987 // to all preview buffers except for the last one.
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08003988 // Only Register the preview, snapshot and thumbnail buffers with the kernel.
Mohan Kandrad9efed92010-01-15 19:08:39 -08003989 if( (strcmp("postview", mName) != 0) ){
3990 int num_buf = num_buffers;
3991 if(!strcmp("preview", mName)) num_buf = kPreviewBufferCount;
3992 LOGE("num_buffers = %d", num_buf);
3993 for (int cnt = 0; cnt < num_buf; ++cnt) {
Sravankb4f5f1c2010-01-21 11:06:17 +05303994 int active = 1;
3995 if(pmem_type == MSM_PMEM_VIDEO){
3996 active = (cnt<ACTIVE_VIDEO_BUFFERS);
3997 LOGV(" pmempool creating video buffers : active %d ", active);
3998 }
3999 else if (pmem_type == MSM_PMEM_PREVIEW){
4000 active = (cnt < (num_buf-1));
4001 }
Mohan Kandra284966d2010-01-05 13:39:15 -08004002 register_buf(mCameraControlFd,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004003 mBufferSize,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08004004 mFrameSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004005 mHeap->getHeapID(),
4006 mAlignedBufferSize * cnt,
4007 (uint8_t *)mHeap->base() + mAlignedBufferSize * cnt,
4008 pmem_type,
Sravankb4f5f1c2010-01-21 11:06:17 +05304009 active);
Mohan Kandra284966d2010-01-05 13:39:15 -08004010 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004011 }
4012
4013 completeInitialization();
4014 }
4015 else LOGE("pmem pool %s error: could not create master heap!",
4016 pmem_pool);
4017}
4018
4019QualcommCameraHardware::PmemPool::~PmemPool()
4020{
4021 LOGV("%s: %s E", __FUNCTION__, mName);
4022 if (mHeap != NULL) {
4023 // Unregister preview buffers with the camera drivers.
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08004024 // Only Unregister the preview, snapshot and thumbnail
4025 // buffers with the kernel.
Mohan Kandrad9efed92010-01-15 19:08:39 -08004026 if( (strcmp("postview", mName) != 0) ){
4027 int num_buffers = mNumBuffers;
4028 if(!strcmp("preview", mName)) num_buffers = kPreviewBufferCount;
4029 for (int cnt = 0; cnt < num_buffers; ++cnt) {
Mohan Kandra284966d2010-01-05 13:39:15 -08004030 register_buf(mCameraControlFd,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004031 mBufferSize,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08004032 mFrameSize,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004033 mHeap->getHeapID(),
4034 mAlignedBufferSize * cnt,
4035 (uint8_t *)mHeap->base() + mAlignedBufferSize * cnt,
4036 mPmemType,
4037 false,
4038 false /* unregister */);
Mohan Kandra284966d2010-01-05 13:39:15 -08004039 }
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004040 }
4041 }
4042 LOGV("destroying PmemPool %s: closing control fd %d",
4043 mName,
4044 mCameraControlFd);
4045 close(mCameraControlFd);
4046 LOGV("%s: %s X", __FUNCTION__, mName);
4047}
4048
4049QualcommCameraHardware::MemPool::~MemPool()
4050{
4051 LOGV("destroying MemPool %s", mName);
4052 if (mFrameSize > 0)
4053 delete [] mBuffers;
4054 mHeap.clear();
4055 LOGV("destroying MemPool %s completed", mName);
4056}
4057
4058static bool register_buf(int camfd,
4059 int size,
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08004060 int frame_size,
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004061 int pmempreviewfd,
4062 uint32_t offset,
4063 uint8_t *buf,
4064 int pmem_type,
4065 bool vfe_can_write,
4066 bool register_buffer)
4067{
4068 struct msm_pmem_info pmemBuf;
4069
4070 pmemBuf.type = pmem_type;
4071 pmemBuf.fd = pmempreviewfd;
4072 pmemBuf.offset = offset;
4073 pmemBuf.len = size;
4074 pmemBuf.vaddr = buf;
4075 pmemBuf.y_off = 0;
Srinivasan Kannan63bfcea2009-12-18 17:32:12 -08004076 pmemBuf.cbcr_off = PAD_TO_WORD(frame_size * 2 / 3);
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004077 pmemBuf.active = vfe_can_write;
4078
4079 LOGV("register_buf: camfd = %d, reg = %d buffer = %p",
4080 camfd, !register_buffer, buf);
4081 if (ioctl(camfd,
4082 register_buffer ?
4083 MSM_CAM_IOCTL_REGISTER_PMEM :
4084 MSM_CAM_IOCTL_UNREGISTER_PMEM,
4085 &pmemBuf) < 0) {
4086 LOGE("register_buf: MSM_CAM_IOCTL_(UN)REGISTER_PMEM fd %d error %s",
4087 camfd,
4088 strerror(errno));
4089 return false;
4090 }
4091 return true;
4092}
4093
4094status_t QualcommCameraHardware::MemPool::dump(int fd, const Vector<String16>& args) const
4095{
4096 const size_t SIZE = 256;
4097 char buffer[SIZE];
4098 String8 result;
4099 snprintf(buffer, 255, "QualcommCameraHardware::AshmemPool::dump\n");
4100 result.append(buffer);
4101 if (mName) {
4102 snprintf(buffer, 255, "mem pool name (%s)\n", mName);
4103 result.append(buffer);
4104 }
4105 if (mHeap != 0) {
4106 snprintf(buffer, 255, "heap base(%p), size(%d), flags(%d), device(%s)\n",
4107 mHeap->getBase(), mHeap->getSize(),
4108 mHeap->getFlags(), mHeap->getDevice());
4109 result.append(buffer);
4110 }
4111 snprintf(buffer, 255,
4112 "buffer size (%d), number of buffers (%d), frame size(%d)",
4113 mBufferSize, mNumBuffers, mFrameSize);
4114 result.append(buffer);
4115 write(fd, result.string(), result.size());
4116 return NO_ERROR;
4117}
4118
4119static void receive_camframe_callback(struct msm_frame *frame)
4120{
4121 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4122 if (obj != 0) {
4123 obj->receivePreviewFrame(frame);
4124 }
4125}
4126
4127static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size)
4128{
4129 LOGV("receive_jpeg_fragment_callback E");
4130 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4131 if (obj != 0) {
4132 obj->receiveJpegPictureFragment(buff_ptr, buff_size);
4133 }
4134 LOGV("receive_jpeg_fragment_callback X");
4135}
4136
4137static void receive_jpeg_callback(jpeg_event_t status)
4138{
4139 LOGV("receive_jpeg_callback E (completion status %d)", status);
4140 if (status == JPEG_EVENT_DONE) {
4141 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4142 if (obj != 0) {
4143 obj->receiveJpegPicture();
4144 }
4145 }
4146 LOGV("receive_jpeg_callback X");
4147}
Sravankb4f5f1c2010-01-21 11:06:17 +05304148// 720p : video frame calbback from camframe
4149static void receive_camframe_video_callback(struct msm_frame *frame)
4150{
4151 LOGV("receive_camframe_video_callback E");
4152 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4153 if (obj != 0) {
4154 obj->receiveRecordingFrame(frame);
4155 }
4156 LOGV("receive_camframe_video_callback X");
4157}
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004158
4159void QualcommCameraHardware::setCallbacks(notify_callback notify_cb,
4160 data_callback data_cb,
4161 data_callback_timestamp data_cb_timestamp,
4162 void* user)
4163{
4164 Mutex::Autolock lock(mLock);
4165 mNotifyCallback = notify_cb;
4166 mDataCallback = data_cb;
4167 mDataCallbackTimestamp = data_cb_timestamp;
4168 mCallbackCookie = user;
4169}
4170
4171void QualcommCameraHardware::enableMsgType(int32_t msgType)
4172{
4173 Mutex::Autolock lock(mLock);
4174 mMsgEnabled |= msgType;
4175}
4176
4177void QualcommCameraHardware::disableMsgType(int32_t msgType)
4178{
4179 Mutex::Autolock lock(mLock);
4180 mMsgEnabled &= ~msgType;
4181}
4182
4183bool QualcommCameraHardware::msgTypeEnabled(int32_t msgType)
4184{
4185 return (mMsgEnabled & msgType);
4186}
4187
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08004188bool QualcommCameraHardware::useOverlay(void)
4189{
Kiran Kumar H N8ff7b982010-01-25 13:54:39 -08004190 if( mCurrentTarget == TARGET_MSM7630 ) {
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08004191 /* Only 7x30 supports Overlay */
4192 mUseOverlay = TRUE;
4193 } else
4194 mUseOverlay = FALSE;
4195
4196 LOGV(" Using Overlay : %s ", mUseOverlay ? "YES" : "NO" );
4197 return mUseOverlay;
4198}
4199
4200status_t QualcommCameraHardware::setOverlay(const sp<Overlay> &Overlay)
4201{
4202 if( Overlay != NULL) {
4203 LOGV(" Valid overlay object ");
4204 mOverlayLock.lock();
4205 mOverlay = Overlay;
4206 mOverlayLock.unlock();
4207 } else {
4208 LOGE(" Overlay object NULL. returning ");
Mohan Kandrad9efed92010-01-15 19:08:39 -08004209 mOverlay = NULL;
Kiran Kumar H N5efb3ff2009-12-07 01:02:44 -08004210 return UNKNOWN_ERROR;
4211 }
4212 return NO_ERROR;
4213}
Kiran Kumar H N215cac42009-12-08 01:53:46 -08004214
4215void QualcommCameraHardware::receive_camframetimeout(void) {
4216 LOGV("receive_camframetimeout: E");
4217 Mutex::Autolock l(&mCamframeTimeoutLock);
Kiran Kumar H N7ac84e32010-02-01 10:58:47 -08004218 LOGD(" Camframe timed out. Not receiving any frames from camera driver ");
Kiran Kumar H N215cac42009-12-08 01:53:46 -08004219 camframe_timeout_flag = TRUE;
4220 LOGV("receive_camframetimeout: X");
4221}
4222
4223static void receive_camframetimeout_callback(void) {
4224 sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
4225 if (obj != 0) {
4226 obj->receive_camframetimeout();
4227 }
4228}
Kiran Kumar H N326cc4c2010-01-08 12:29:26 -08004229
4230void QualcommCameraHardware::storePreviewFrameForPostview(void) {
4231 LOGV(" storePreviewFrameForPostview : E ");
4232
4233 /* Since there is restriction on the maximum overlay dimensions
4234 * that can be created, we use the last preview frame as postview
4235 * for 7x30. */
4236 LOGV(" Copying the preview buffer to postview buffer %d ",
4237 mPreviewFrameSize);
4238 if( mPostViewHeap != NULL && mLastQueuedFrame != NULL) {
4239 memcpy(mPostViewHeap->mHeap->base(),
4240 (uint8_t *)mLastQueuedFrame, mPreviewFrameSize );
4241 } else
4242 LOGE(" Failed to store Preview frame. No Postview ");
4243
4244 LOGV(" storePreviewFrameForPostview : X ");
4245}
Priya Komarlingamb85535d2009-11-30 13:06:01 -08004246}; // namespace android