blob: 096c5b2ba3362f6d43e0dc8e9e09be0c4c176cb7
1 | /* |
2 | * Copyright (C) 2011 The Android Open Source Project |
3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. |
6 | * You may obtain a copy of the License at |
7 | * |
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | * |
10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. |
15 | */ |
16 | |
17 | /* |
18 | * Contains implementation of a class EmulatedCamera that encapsulates |
19 | * functionality common to all emulated cameras ("fake", "webcam", "video file", |
20 | * etc.). Instances of this class (for each emulated camera) are created during |
21 | * the construction of the EmulatedCameraFactory instance. This class serves as |
22 | * an entry point for all camera API calls that defined by camera_device_ops_t |
23 | * API. |
24 | */ |
25 | |
26 | #define LOG_NDEBUG 0 |
27 | #define LOG_TAG "EmulatedCamera_Camera" |
28 | #include <cutils/log.h> |
29 | #include <ui/Rect.h> |
30 | #include "EmulatedCamera.h" |
31 | //#include "EmulatedFakeCameraDevice.h" |
32 | #include "Converters.h" |
33 | |
34 | /* Defines whether we should trace parameter changes. */ |
35 | #define DEBUG_PARAM 1 |
36 | |
37 | namespace android { |
38 | |
39 | #if DEBUG_PARAM |
40 | /* Calculates and logs parameter changes. |
41 | * Param: |
42 | * current - Current set of camera parameters. |
43 | * new_par - String representation of new parameters. |
44 | */ |
45 | static void PrintParamDiff(const CameraParameters& current, const char* new_par); |
46 | #else |
47 | #define PrintParamDiff(current, new_par) (void(0)) |
48 | #endif /* DEBUG_PARAM */ |
49 | |
50 | /* A helper routine that adds a value to the camera parameter. |
51 | * Param: |
52 | * param - Camera parameter to add a value to. |
53 | * val - Value to add. |
54 | * Return: |
55 | * A new string containing parameter with the added value on success, or NULL on |
56 | * a failure. If non-NULL string is returned, the caller is responsible for |
57 | * freeing it with 'free'. |
58 | */ |
59 | static char* AddValue(const char* param, const char* val); |
60 | |
61 | EmulatedCamera::EmulatedCamera(int cameraId, |
62 | struct hw_module_t* module) |
63 | : EmulatedBaseCamera(cameraId, |
64 | HARDWARE_DEVICE_API_VERSION(1, 0), |
65 | &common, |
66 | module), |
67 | mPreviewWindow(), |
68 | mCallbackNotifier() |
69 | { |
70 | /* camera_device v1 fields. */ |
71 | common.close = EmulatedCamera::close; |
72 | ops = &mDeviceOps; |
73 | priv = this; |
74 | } |
75 | |
76 | EmulatedCamera::~EmulatedCamera() |
77 | { |
78 | } |
79 | |
80 | /**************************************************************************** |
81 | * Public API |
82 | ***************************************************************************/ |
83 | |
84 | status_t EmulatedCamera::Initialize() |
85 | { |
86 | /* Preview formats supported by this HAL. */ |
87 | char preview_formats[1024]; |
88 | snprintf(preview_formats, sizeof(preview_formats), "%s,%s,%s", |
89 | CameraParameters::PIXEL_FORMAT_YUV420SP, |
90 | CameraParameters::PIXEL_FORMAT_YUV420P, |
91 | CameraParameters::PIXEL_FORMAT_RGBA8888); |
92 | |
93 | /* |
94 | * Fake required parameters. |
95 | */ |
96 | |
97 | mParameters.set(CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES, "320x240,0x0"); |
98 | |
99 | mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, "512"); |
100 | mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, "384"); |
101 | mParameters.set(CameraParameters::KEY_JPEG_QUALITY, "90"); |
102 | mParameters.set(CameraParameters::KEY_FOCAL_LENGTH, "4.31"); |
103 | mParameters.set(CameraParameters::KEY_HORIZONTAL_VIEW_ANGLE, "54.8"); |
104 | mParameters.set(CameraParameters::KEY_VERTICAL_VIEW_ANGLE, "42.5"); |
105 | mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, "90"); |
106 | |
107 | /* Preview format settings used here are related to panoramic view only. It's |
108 | * not related to the preview window that works only with RGB frames, which |
109 | * is explicitly stated when set_buffers_geometry is called on the preview |
110 | * window object. */ |
111 | mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS, |
112 | preview_formats); |
113 | mParameters.setPreviewFormat(CameraParameters::PIXEL_FORMAT_YUV420SP); |
114 | |
115 | /* We don't relay on the actual frame rates supported by the camera device, |
116 | * since we will emulate them through timeouts in the emulated camera device |
117 | * worker thread. */ |
118 | mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES, |
119 | "30,24,20,15,10,5"); |
120 | mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE, "(5,30)"); |
121 | mParameters.set(CameraParameters::KEY_PREVIEW_FPS_RANGE, "5,30"); |
122 | mParameters.setPreviewFrameRate(24); |
123 | |
124 | /* Only PIXEL_FORMAT_YUV420P is accepted by video framework in emulator! */ |
125 | mParameters.set(CameraParameters::KEY_VIDEO_FRAME_FORMAT, |
126 | CameraParameters::PIXEL_FORMAT_YUV420P); |
127 | mParameters.set(CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS, |
128 | CameraParameters::PIXEL_FORMAT_JPEG); |
129 | mParameters.setPictureFormat(CameraParameters::PIXEL_FORMAT_JPEG); |
130 | |
131 | /* Set exposure compensation. */ |
132 | mParameters.set(CameraParameters::KEY_MAX_EXPOSURE_COMPENSATION, "6"); |
133 | mParameters.set(CameraParameters::KEY_MIN_EXPOSURE_COMPENSATION, "-6"); |
134 | mParameters.set(CameraParameters::KEY_EXPOSURE_COMPENSATION_STEP, "0.5"); |
135 | mParameters.set(CameraParameters::KEY_EXPOSURE_COMPENSATION, "0"); |
136 | |
137 | /* Sets the white balance modes and the device-dependent scale factors. */ |
138 | char supported_white_balance[1024]; |
139 | snprintf(supported_white_balance, sizeof(supported_white_balance), |
140 | "%s,%s,%s,%s", |
141 | CameraParameters::WHITE_BALANCE_AUTO, |
142 | CameraParameters::WHITE_BALANCE_INCANDESCENT, |
143 | CameraParameters::WHITE_BALANCE_DAYLIGHT, |
144 | CameraParameters::WHITE_BALANCE_TWILIGHT); |
145 | mParameters.set(CameraParameters::KEY_SUPPORTED_WHITE_BALANCE, |
146 | supported_white_balance); |
147 | mParameters.set(CameraParameters::KEY_WHITE_BALANCE, |
148 | CameraParameters::WHITE_BALANCE_AUTO); |
149 | getCameraDevice()->initializeWhiteBalanceModes( |
150 | CameraParameters::WHITE_BALANCE_AUTO, 1.0f, 1.0f); |
151 | getCameraDevice()->initializeWhiteBalanceModes( |
152 | CameraParameters::WHITE_BALANCE_INCANDESCENT, 1.38f, 0.60f); |
153 | getCameraDevice()->initializeWhiteBalanceModes( |
154 | CameraParameters::WHITE_BALANCE_DAYLIGHT, 1.09f, 0.92f); |
155 | getCameraDevice()->initializeWhiteBalanceModes( |
156 | CameraParameters::WHITE_BALANCE_TWILIGHT, 0.92f, 1.22f); |
157 | getCameraDevice()->setWhiteBalanceMode(CameraParameters::WHITE_BALANCE_AUTO); |
158 | |
159 | /* Not supported features |
160 | */ |
161 | mParameters.set(CameraParameters::KEY_SUPPORTED_FOCUS_MODES, |
162 | CameraParameters::FOCUS_MODE_FIXED); |
163 | mParameters.set(CameraParameters::KEY_FOCUS_MODE, |
164 | CameraParameters::FOCUS_MODE_FIXED); |
165 | |
166 | return NO_ERROR; |
167 | } |
168 | |
169 | void EmulatedCamera::onNextFrameAvailable(const void* frame, |
170 | nsecs_t timestamp, |
171 | EmulatedCameraDevice* camera_dev) |
172 | { |
173 | /* Notify the preview window first. */ |
174 | mPreviewWindow.onNextFrameAvailable(frame, timestamp, camera_dev); |
175 | |
176 | /* Notify callback notifier next. */ |
177 | mCallbackNotifier.onNextFrameAvailable(frame, timestamp, camera_dev); |
178 | } |
179 | |
180 | void EmulatedCamera::onCameraDeviceError(int err) |
181 | { |
182 | /* Errors are reported through the callback notifier */ |
183 | mCallbackNotifier.onCameraDeviceError(err); |
184 | } |
185 | |
186 | /**************************************************************************** |
187 | * Camera API implementation. |
188 | ***************************************************************************/ |
189 | |
190 | status_t EmulatedCamera::connectCamera(hw_device_t** device) |
191 | { |
192 | ALOGV("%s", __FUNCTION__); |
193 | |
194 | status_t res = EINVAL; |
195 | EmulatedCameraDevice* const camera_dev = getCameraDevice(); |
196 | ALOGE_IF(camera_dev == NULL, "%s: No camera device instance.", __FUNCTION__); |
197 | |
198 | if (camera_dev != NULL) { |
199 | /* Connect to the camera device. */ |
200 | res = getCameraDevice()->connectDevice(); |
201 | if (res == NO_ERROR) { |
202 | *device = &common; |
203 | } |
204 | } |
205 | |
206 | return -res; |
207 | } |
208 | |
209 | status_t EmulatedCamera::closeCamera() |
210 | { |
211 | ALOGV("%s", __FUNCTION__); |
212 | |
213 | return cleanupCamera(); |
214 | } |
215 | |
216 | status_t EmulatedCamera::getCameraInfo(struct camera_info* info) |
217 | { |
218 | ALOGV("%s", __FUNCTION__); |
219 | |
220 | const char* valstr = NULL; |
221 | |
222 | valstr = mParameters.get(EmulatedCamera::FACING_KEY); |
223 | if (valstr != NULL) { |
224 | if (strcmp(valstr, EmulatedCamera::FACING_FRONT) == 0) { |
225 | info->facing = CAMERA_FACING_FRONT; |
226 | } |
227 | else if (strcmp(valstr, EmulatedCamera::FACING_BACK) == 0) { |
228 | info->facing = CAMERA_FACING_BACK; |
229 | } |
230 | } else { |
231 | info->facing = CAMERA_FACING_BACK; |
232 | } |
233 | |
234 | valstr = mParameters.get(EmulatedCamera::ORIENTATION_KEY); |
235 | if (valstr != NULL) { |
236 | info->orientation = atoi(valstr); |
237 | } else { |
238 | info->orientation = 0; |
239 | } |
240 | |
241 | return EmulatedBaseCamera::getCameraInfo(info); |
242 | } |
243 | |
244 | status_t EmulatedCamera::setPreviewWindow(struct preview_stream_ops* window) |
245 | { |
246 | /* Callback should return a negative errno. */ |
247 | return -mPreviewWindow.setPreviewWindow(window, |
248 | mParameters.getPreviewFrameRate()); |
249 | } |
250 | |
251 | void EmulatedCamera::setCallbacks(camera_notify_callback notify_cb, |
252 | camera_data_callback data_cb, |
253 | camera_data_timestamp_callback data_cb_timestamp, |
254 | camera_request_memory get_memory, |
255 | void* user) |
256 | { |
257 | mCallbackNotifier.setCallbacks(notify_cb, data_cb, data_cb_timestamp, |
258 | get_memory, user); |
259 | } |
260 | |
261 | void EmulatedCamera::enableMsgType(int32_t msg_type) |
262 | { |
263 | mCallbackNotifier.enableMessage(msg_type); |
264 | } |
265 | |
266 | void EmulatedCamera::disableMsgType(int32_t msg_type) |
267 | { |
268 | mCallbackNotifier.disableMessage(msg_type); |
269 | } |
270 | |
271 | int EmulatedCamera::isMsgTypeEnabled(int32_t msg_type) |
272 | { |
273 | return mCallbackNotifier.isMessageEnabled(msg_type); |
274 | } |
275 | |
276 | status_t EmulatedCamera::startPreview() |
277 | { |
278 | /* Callback should return a negative errno. */ |
279 | return -doStartPreview(); |
280 | } |
281 | |
282 | void EmulatedCamera::stopPreview() |
283 | { |
284 | doStopPreview(); |
285 | } |
286 | |
287 | int EmulatedCamera::isPreviewEnabled() |
288 | { |
289 | return mPreviewWindow.isPreviewEnabled(); |
290 | } |
291 | |
292 | status_t EmulatedCamera::storeMetaDataInBuffers(int enable) |
293 | { |
294 | /* Callback should return a negative errno. */ |
295 | return -mCallbackNotifier.storeMetaDataInBuffers(enable); |
296 | } |
297 | |
298 | status_t EmulatedCamera::startRecording() |
299 | { |
300 | /* Callback should return a negative errno. */ |
301 | return -mCallbackNotifier.enableVideoRecording(mParameters.getPreviewFrameRate()); |
302 | } |
303 | |
304 | void EmulatedCamera::stopRecording() |
305 | { |
306 | mCallbackNotifier.disableVideoRecording(); |
307 | } |
308 | |
309 | int EmulatedCamera::isRecordingEnabled() |
310 | { |
311 | return mCallbackNotifier.isVideoRecordingEnabled(); |
312 | } |
313 | |
314 | void EmulatedCamera::releaseRecordingFrame(const void* opaque) |
315 | { |
316 | mCallbackNotifier.releaseRecordingFrame(opaque); |
317 | } |
318 | |
319 | status_t EmulatedCamera::setAutoFocus() |
320 | { |
321 | ALOGV("%s", __FUNCTION__); |
322 | |
323 | /* TODO: Future enhancements. */ |
324 | return NO_ERROR; |
325 | } |
326 | |
327 | status_t EmulatedCamera::cancelAutoFocus() |
328 | { |
329 | ALOGV("%s", __FUNCTION__); |
330 | |
331 | /* TODO: Future enhancements. */ |
332 | return NO_ERROR; |
333 | } |
334 | |
335 | status_t EmulatedCamera::takePicture() |
336 | { |
337 | ALOGV("%s", __FUNCTION__); |
338 | |
339 | status_t res; |
340 | int width, height; |
341 | uint32_t org_fmt; |
342 | |
343 | /* Collect frame info for the picture. */ |
344 | mParameters.getPictureSize(&width, &height); |
345 | const char* pix_fmt = mParameters.getPictureFormat(); |
346 | if (strcmp(pix_fmt, CameraParameters::PIXEL_FORMAT_YUV420P) == 0) { |
347 | org_fmt = V4L2_PIX_FMT_YUV420; |
348 | } else if (strcmp(pix_fmt, CameraParameters::PIXEL_FORMAT_RGBA8888) == 0) { |
349 | org_fmt = V4L2_PIX_FMT_RGB32; |
350 | } else if (strcmp(pix_fmt, CameraParameters::PIXEL_FORMAT_YUV420SP) == 0) { |
351 | org_fmt = V4L2_PIX_FMT_NV21; |
352 | } else if (strcmp(pix_fmt, CameraParameters::PIXEL_FORMAT_JPEG) == 0) { |
353 | /* We only have JPEG converted for NV21 format. */ |
354 | org_fmt = V4L2_PIX_FMT_NV21; |
355 | } else { |
356 | ALOGE("%s: Unsupported pixel format %s", __FUNCTION__, pix_fmt); |
357 | return EINVAL; |
358 | } |
359 | /* Get JPEG quality. */ |
360 | int jpeg_quality = mParameters.getInt(CameraParameters::KEY_JPEG_QUALITY); |
361 | if (jpeg_quality <= 0) { |
362 | jpeg_quality = 90; /* Fall back to default. */ |
363 | } |
364 | |
365 | /* |
366 | * Make sure preview is not running, and device is stopped before taking |
367 | * picture. |
368 | */ |
369 | |
370 | const bool preview_on = mPreviewWindow.isPreviewEnabled(); |
371 | if (preview_on) { |
372 | doStopPreview(); |
373 | } |
374 | |
375 | /* Camera device should have been stopped when the shutter message has been |
376 | * enabled. */ |
377 | EmulatedCameraDevice* const camera_dev = getCameraDevice(); |
378 | if (camera_dev->isStarted()) { |
379 | ALOGW("%s: Camera device is started", __FUNCTION__); |
380 | camera_dev->stopDeliveringFrames(); |
381 | camera_dev->stopDevice(); |
382 | } |
383 | |
384 | /* |
385 | * Take the picture now. |
386 | */ |
387 | |
388 | /* Start camera device for the picture frame. */ |
389 | ALOGD("Starting camera for picture: %.4s(%s)[%dx%d]", |
390 | reinterpret_cast<const char*>(&org_fmt), pix_fmt, width, height); |
391 | res = camera_dev->startDevice(width, height, org_fmt); |
392 | if (res != NO_ERROR) { |
393 | if (preview_on) { |
394 | doStartPreview(); |
395 | } |
396 | return res; |
397 | } |
398 | |
399 | /* Deliver one frame only. */ |
400 | mCallbackNotifier.setJpegQuality(jpeg_quality); |
401 | mCallbackNotifier.setTakingPicture(true); |
402 | res = camera_dev->startDeliveringFrames(true); |
403 | if (res != NO_ERROR) { |
404 | mCallbackNotifier.setTakingPicture(false); |
405 | if (preview_on) { |
406 | doStartPreview(); |
407 | } |
408 | } |
409 | return res; |
410 | } |
411 | |
412 | status_t EmulatedCamera::cancelPicture() |
413 | { |
414 | ALOGV("%s", __FUNCTION__); |
415 | |
416 | return NO_ERROR; |
417 | } |
418 | |
419 | status_t EmulatedCamera::setParameters(const char* parms) |
420 | { |
421 | ALOGV("%s", __FUNCTION__); |
422 | PrintParamDiff(mParameters, parms); |
423 | |
424 | CameraParameters new_param; |
425 | String8 str8_param(parms); |
426 | new_param.unflatten(str8_param); |
427 | |
428 | /* |
429 | * Check for new exposure compensation parameter. |
430 | */ |
431 | int new_exposure_compensation = new_param.getInt( |
432 | CameraParameters::KEY_EXPOSURE_COMPENSATION); |
433 | const int min_exposure_compensation = new_param.getInt( |
434 | CameraParameters::KEY_MIN_EXPOSURE_COMPENSATION); |
435 | const int max_exposure_compensation = new_param.getInt( |
436 | CameraParameters::KEY_MAX_EXPOSURE_COMPENSATION); |
437 | |
438 | // Checks if the exposure compensation change is supported. |
439 | if ((min_exposure_compensation != 0) || (max_exposure_compensation != 0)) { |
440 | if (new_exposure_compensation > max_exposure_compensation) { |
441 | new_exposure_compensation = max_exposure_compensation; |
442 | } |
443 | if (new_exposure_compensation < min_exposure_compensation) { |
444 | new_exposure_compensation = min_exposure_compensation; |
445 | } |
446 | |
447 | const int current_exposure_compensation = mParameters.getInt( |
448 | CameraParameters::KEY_EXPOSURE_COMPENSATION); |
449 | if (current_exposure_compensation != new_exposure_compensation) { |
450 | const float exposure_value = new_exposure_compensation * |
451 | new_param.getFloat( |
452 | CameraParameters::KEY_EXPOSURE_COMPENSATION_STEP); |
453 | |
454 | getCameraDevice()->setExposureCompensation( |
455 | exposure_value); |
456 | } |
457 | } |
458 | |
459 | const char* new_white_balance = new_param.get( |
460 | CameraParameters::KEY_WHITE_BALANCE); |
461 | const char* supported_white_balance = new_param.get( |
462 | CameraParameters::KEY_SUPPORTED_WHITE_BALANCE); |
463 | |
464 | if ((supported_white_balance != NULL) && (new_white_balance != NULL) && |
465 | (strstr(supported_white_balance, new_white_balance) != NULL)) { |
466 | |
467 | const char* current_white_balance = mParameters.get( |
468 | CameraParameters::KEY_WHITE_BALANCE); |
469 | if ((current_white_balance == NULL) || |
470 | (strcmp(current_white_balance, new_white_balance) != 0)) { |
471 | ALOGV("Setting white balance to %s", new_white_balance); |
472 | getCameraDevice()->setWhiteBalanceMode(new_white_balance); |
473 | } |
474 | } |
475 | |
476 | mParameters = new_param; |
477 | |
478 | return NO_ERROR; |
479 | } |
480 | |
481 | /* A dumb variable indicating "no params" / error on the exit from |
482 | * EmulatedCamera::getParameters(). */ |
483 | static char lNoParam = '\0'; |
484 | char* EmulatedCamera::getParameters() |
485 | { |
486 | String8 params(mParameters.flatten()); |
487 | char* ret_str = |
488 | reinterpret_cast<char*>(malloc(sizeof(char) * (params.length()+1))); |
489 | memset(ret_str, 0, params.length()+1); |
490 | if (ret_str != NULL) { |
491 | strncpy(ret_str, params.string(), params.length()+1); |
492 | return ret_str; |
493 | } else { |
494 | ALOGE("%s: Unable to allocate string for %s", __FUNCTION__, params.string()); |
495 | /* Apparently, we can't return NULL fron this routine. */ |
496 | return &lNoParam; |
497 | } |
498 | } |
499 | |
500 | void EmulatedCamera::putParameters(char* params) |
501 | { |
502 | /* This method simply frees parameters allocated in getParameters(). */ |
503 | if (params != NULL && params != &lNoParam) { |
504 | free(params); |
505 | } |
506 | } |
507 | |
508 | status_t EmulatedCamera::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) |
509 | { |
510 | ALOGV("%s: cmd = %d, arg1 = %d, arg2 = %d", __FUNCTION__, cmd, arg1, arg2); |
511 | |
512 | /* TODO: Future enhancements. */ |
513 | return 0; |
514 | } |
515 | |
516 | void EmulatedCamera::releaseCamera() |
517 | { |
518 | ALOGV("%s", __FUNCTION__); |
519 | |
520 | cleanupCamera(); |
521 | } |
522 | |
523 | status_t EmulatedCamera::dumpCamera(int fd) |
524 | { |
525 | ALOGV("%s", __FUNCTION__); |
526 | |
527 | /* TODO: Future enhancements. */ |
528 | return -EINVAL; |
529 | } |
530 | |
531 | /**************************************************************************** |
532 | * Preview management. |
533 | ***************************************************************************/ |
534 | |
535 | status_t EmulatedCamera::doStartPreview() |
536 | { |
537 | ALOGV("%s", __FUNCTION__); |
538 | |
539 | EmulatedCameraDevice* camera_dev = getCameraDevice(); |
540 | if (camera_dev->isStarted()) { |
541 | camera_dev->stopDeliveringFrames(); |
542 | camera_dev->stopDevice(); |
543 | } |
544 | |
545 | status_t res = mPreviewWindow.startPreview(); |
546 | if (res != NO_ERROR) { |
547 | return res; |
548 | } |
549 | |
550 | /* Make sure camera device is connected. */ |
551 | if (!camera_dev->isConnected()) { |
552 | res = camera_dev->connectDevice(); |
553 | if (res != NO_ERROR) { |
554 | mPreviewWindow.stopPreview(); |
555 | return res; |
556 | } |
557 | } |
558 | |
559 | int width, height; |
560 | /* Lets see what should we use for frame width, and height. */ |
561 | if (mParameters.get(CameraParameters::KEY_VIDEO_SIZE) != NULL) { |
562 | mParameters.getVideoSize(&width, &height); |
563 | } else { |
564 | mParameters.getPreviewSize(&width, &height); |
565 | } |
566 | /* Lets see what should we use for the frame pixel format. Note that there |
567 | * are two parameters that define pixel formats for frames sent to the |
568 | * application via notification callbacks: |
569 | * - KEY_VIDEO_FRAME_FORMAT, that is used when recording video, and |
570 | * - KEY_PREVIEW_FORMAT, that is used for preview frame notification. |
571 | * We choose one or the other, depending on "recording-hint" property set by |
572 | * the framework that indicating intention: video, or preview. */ |
573 | const char* pix_fmt = NULL; |
574 | const char* is_video = mParameters.get(EmulatedCamera::RECORDING_HINT_KEY); |
575 | if (is_video == NULL) { |
576 | is_video = CameraParameters::FALSE; |
577 | } |
578 | if (strcmp(is_video, CameraParameters::TRUE) == 0) { |
579 | /* Video recording is requested. Lets see if video frame format is set. */ |
580 | pix_fmt = mParameters.get(CameraParameters::KEY_VIDEO_FRAME_FORMAT); |
581 | } |
582 | /* If this was not video recording, or video frame format is not set, lets |
583 | * use preview pixel format for the main framebuffer. */ |
584 | if (pix_fmt == NULL) { |
585 | pix_fmt = mParameters.getPreviewFormat(); |
586 | } |
587 | if (pix_fmt == NULL) { |
588 | ALOGE("%s: Unable to obtain video format", __FUNCTION__); |
589 | mPreviewWindow.stopPreview(); |
590 | return EINVAL; |
591 | } |
592 | |
593 | /* Convert framework's pixel format to the FOURCC one. */ |
594 | uint32_t org_fmt; |
595 | if (strcmp(pix_fmt, CameraParameters::PIXEL_FORMAT_YUV420P) == 0) { |
596 | org_fmt = V4L2_PIX_FMT_YUV420; |
597 | } else if (strcmp(pix_fmt, CameraParameters::PIXEL_FORMAT_RGBA8888) == 0) { |
598 | org_fmt = V4L2_PIX_FMT_RGB32; |
599 | } else if (strcmp(pix_fmt, CameraParameters::PIXEL_FORMAT_YUV420SP) == 0) { |
600 | org_fmt = V4L2_PIX_FMT_NV21; |
601 | } else { |
602 | ALOGE("%s: Unsupported pixel format %s", __FUNCTION__, pix_fmt); |
603 | mPreviewWindow.stopPreview(); |
604 | return EINVAL; |
605 | } |
606 | ALOGD("Starting camera: %dx%d -> %.4s(%s)", |
607 | width, height, reinterpret_cast<const char*>(&org_fmt), pix_fmt); |
608 | res = camera_dev->startDevice(width, height, org_fmt); |
609 | if (res != NO_ERROR) { |
610 | mPreviewWindow.stopPreview(); |
611 | return res; |
612 | } |
613 | |
614 | res = camera_dev->startDeliveringFrames(false); |
615 | if (res != NO_ERROR) { |
616 | camera_dev->stopDevice(); |
617 | mPreviewWindow.stopPreview(); |
618 | } |
619 | |
620 | return res; |
621 | } |
622 | |
623 | status_t EmulatedCamera::doStopPreview() |
624 | { |
625 | ALOGV("%s", __FUNCTION__); |
626 | |
627 | status_t res = NO_ERROR; |
628 | if (mPreviewWindow.isPreviewEnabled()) { |
629 | /* Stop the camera. */ |
630 | if (getCameraDevice()->isStarted()) { |
631 | getCameraDevice()->stopDeliveringFrames(); |
632 | res = getCameraDevice()->stopDevice(); |
633 | } |
634 | |
635 | if (res == NO_ERROR) { |
636 | /* Disable preview as well. */ |
637 | mPreviewWindow.stopPreview(); |
638 | } |
639 | } |
640 | |
641 | return NO_ERROR; |
642 | } |
643 | |
644 | /**************************************************************************** |
645 | * Private API. |
646 | ***************************************************************************/ |
647 | |
648 | status_t EmulatedCamera::cleanupCamera() |
649 | { |
650 | status_t res = NO_ERROR; |
651 | |
652 | /* If preview is running - stop it. */ |
653 | res = doStopPreview(); |
654 | if (res != NO_ERROR) { |
655 | return -res; |
656 | } |
657 | |
658 | /* Stop and disconnect the camera device. */ |
659 | EmulatedCameraDevice* const camera_dev = getCameraDevice(); |
660 | if (camera_dev != NULL) { |
661 | if (camera_dev->isStarted()) { |
662 | camera_dev->stopDeliveringFrames(); |
663 | res = camera_dev->stopDevice(); |
664 | if (res != NO_ERROR) { |
665 | return -res; |
666 | } |
667 | } |
668 | if (camera_dev->isConnected()) { |
669 | res = camera_dev->disconnectDevice(); |
670 | if (res != NO_ERROR) { |
671 | return -res; |
672 | } |
673 | } |
674 | } |
675 | |
676 | mCallbackNotifier.cleanupCBNotifier(); |
677 | |
678 | return NO_ERROR; |
679 | } |
680 | |
681 | /**************************************************************************** |
682 | * Camera API callbacks as defined by camera_device_ops structure. |
683 | * |
684 | * Callbacks here simply dispatch the calls to an appropriate method inside |
685 | * EmulatedCamera instance, defined by the 'dev' parameter. |
686 | ***************************************************************************/ |
687 | |
688 | int EmulatedCamera::set_preview_window(struct camera_device* dev, |
689 | struct preview_stream_ops* window) |
690 | { |
691 | EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv); |
692 | if (ec == NULL) { |
693 | ALOGE("%s: Unexpected NULL camera device", __FUNCTION__); |
694 | return -EINVAL; |
695 | } |
696 | return ec->setPreviewWindow(window); |
697 | } |
698 | |
699 | void EmulatedCamera::set_callbacks( |
700 | struct camera_device* dev, |
701 | camera_notify_callback notify_cb, |
702 | camera_data_callback data_cb, |
703 | camera_data_timestamp_callback data_cb_timestamp, |
704 | camera_request_memory get_memory, |
705 | void* user) |
706 | { |
707 | EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv); |
708 | if (ec == NULL) { |
709 | ALOGE("%s: Unexpected NULL camera device", __FUNCTION__); |
710 | return; |
711 | } |
712 | ec->setCallbacks(notify_cb, data_cb, data_cb_timestamp, get_memory, user); |
713 | } |
714 | |
715 | void EmulatedCamera::enable_msg_type(struct camera_device* dev, int32_t msg_type) |
716 | { |
717 | EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv); |
718 | if (ec == NULL) { |
719 | ALOGE("%s: Unexpected NULL camera device", __FUNCTION__); |
720 | return; |
721 | } |
722 | ec->enableMsgType(msg_type); |
723 | } |
724 | |
725 | void EmulatedCamera::disable_msg_type(struct camera_device* dev, int32_t msg_type) |
726 | { |
727 | EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv); |
728 | if (ec == NULL) { |
729 | ALOGE("%s: Unexpected NULL camera device", __FUNCTION__); |
730 | return; |
731 | } |
732 | ec->disableMsgType(msg_type); |
733 | } |
734 | |
735 | int EmulatedCamera::msg_type_enabled(struct camera_device* dev, int32_t msg_type) |
736 | { |
737 | EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv); |
738 | if (ec == NULL) { |
739 | ALOGE("%s: Unexpected NULL camera device", __FUNCTION__); |
740 | return -EINVAL; |
741 | } |
742 | return ec->isMsgTypeEnabled(msg_type); |
743 | } |
744 | |
745 | int EmulatedCamera::start_preview(struct camera_device* dev) |
746 | { |
747 | EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv); |
748 | if (ec == NULL) { |
749 | ALOGE("%s: Unexpected NULL camera device", __FUNCTION__); |
750 | return -EINVAL; |
751 | } |
752 | return ec->startPreview(); |
753 | } |
754 | |
755 | void EmulatedCamera::stop_preview(struct camera_device* dev) |
756 | { |
757 | EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv); |
758 | if (ec == NULL) { |
759 | ALOGE("%s: Unexpected NULL camera device", __FUNCTION__); |
760 | return; |
761 | } |
762 | ec->stopPreview(); |
763 | } |
764 | |
765 | int EmulatedCamera::preview_enabled(struct camera_device* dev) |
766 | { |
767 | EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv); |
768 | if (ec == NULL) { |
769 | ALOGE("%s: Unexpected NULL camera device", __FUNCTION__); |
770 | return -EINVAL; |
771 | } |
772 | return ec->isPreviewEnabled(); |
773 | } |
774 | |
775 | int EmulatedCamera::store_meta_data_in_buffers(struct camera_device* dev, |
776 | int enable) |
777 | { |
778 | EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv); |
779 | if (ec == NULL) { |
780 | ALOGE("%s: Unexpected NULL camera device", __FUNCTION__); |
781 | return -EINVAL; |
782 | } |
783 | return ec->storeMetaDataInBuffers(enable); |
784 | } |
785 | |
786 | int EmulatedCamera::start_recording(struct camera_device* dev) |
787 | { |
788 | EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv); |
789 | if (ec == NULL) { |
790 | ALOGE("%s: Unexpected NULL camera device", __FUNCTION__); |
791 | return -EINVAL; |
792 | } |
793 | return ec->startRecording(); |
794 | } |
795 | |
796 | void EmulatedCamera::stop_recording(struct camera_device* dev) |
797 | { |
798 | EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv); |
799 | if (ec == NULL) { |
800 | ALOGE("%s: Unexpected NULL camera device", __FUNCTION__); |
801 | return; |
802 | } |
803 | ec->stopRecording(); |
804 | } |
805 | |
806 | int EmulatedCamera::recording_enabled(struct camera_device* dev) |
807 | { |
808 | EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv); |
809 | if (ec == NULL) { |
810 | ALOGE("%s: Unexpected NULL camera device", __FUNCTION__); |
811 | return -EINVAL; |
812 | } |
813 | return ec->isRecordingEnabled(); |
814 | } |
815 | |
816 | void EmulatedCamera::release_recording_frame(struct camera_device* dev, |
817 | const void* opaque) |
818 | { |
819 | EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv); |
820 | if (ec == NULL) { |
821 | ALOGE("%s: Unexpected NULL camera device", __FUNCTION__); |
822 | return; |
823 | } |
824 | ec->releaseRecordingFrame(opaque); |
825 | } |
826 | |
827 | int EmulatedCamera::auto_focus(struct camera_device* dev) |
828 | { |
829 | EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv); |
830 | if (ec == NULL) { |
831 | ALOGE("%s: Unexpected NULL camera device", __FUNCTION__); |
832 | return -EINVAL; |
833 | } |
834 | return ec->setAutoFocus(); |
835 | } |
836 | |
837 | int EmulatedCamera::cancel_auto_focus(struct camera_device* dev) |
838 | { |
839 | EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv); |
840 | if (ec == NULL) { |
841 | ALOGE("%s: Unexpected NULL camera device", __FUNCTION__); |
842 | return -EINVAL; |
843 | } |
844 | return ec->cancelAutoFocus(); |
845 | } |
846 | |
847 | int EmulatedCamera::take_picture(struct camera_device* dev) |
848 | { |
849 | EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv); |
850 | if (ec == NULL) { |
851 | ALOGE("%s: Unexpected NULL camera device", __FUNCTION__); |
852 | return -EINVAL; |
853 | } |
854 | return ec->takePicture(); |
855 | } |
856 | |
857 | int EmulatedCamera::cancel_picture(struct camera_device* dev) |
858 | { |
859 | EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv); |
860 | if (ec == NULL) { |
861 | ALOGE("%s: Unexpected NULL camera device", __FUNCTION__); |
862 | return -EINVAL; |
863 | } |
864 | return ec->cancelPicture(); |
865 | } |
866 | |
867 | int EmulatedCamera::set_parameters(struct camera_device* dev, const char* parms) |
868 | { |
869 | EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv); |
870 | if (ec == NULL) { |
871 | ALOGE("%s: Unexpected NULL camera device", __FUNCTION__); |
872 | return -EINVAL; |
873 | } |
874 | return ec->setParameters(parms); |
875 | } |
876 | |
877 | char* EmulatedCamera::get_parameters(struct camera_device* dev) |
878 | { |
879 | EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv); |
880 | if (ec == NULL) { |
881 | ALOGE("%s: Unexpected NULL camera device", __FUNCTION__); |
882 | return NULL; |
883 | } |
884 | return ec->getParameters(); |
885 | } |
886 | |
887 | void EmulatedCamera::put_parameters(struct camera_device* dev, char* params) |
888 | { |
889 | EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv); |
890 | if (ec == NULL) { |
891 | ALOGE("%s: Unexpected NULL camera device", __FUNCTION__); |
892 | return; |
893 | } |
894 | ec->putParameters(params); |
895 | } |
896 | |
897 | int EmulatedCamera::send_command(struct camera_device* dev, |
898 | int32_t cmd, |
899 | int32_t arg1, |
900 | int32_t arg2) |
901 | { |
902 | EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv); |
903 | if (ec == NULL) { |
904 | ALOGE("%s: Unexpected NULL camera device", __FUNCTION__); |
905 | return -EINVAL; |
906 | } |
907 | return ec->sendCommand(cmd, arg1, arg2); |
908 | } |
909 | |
910 | void EmulatedCamera::release(struct camera_device* dev) |
911 | { |
912 | EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv); |
913 | if (ec == NULL) { |
914 | ALOGE("%s: Unexpected NULL camera device", __FUNCTION__); |
915 | return; |
916 | } |
917 | ec->releaseCamera(); |
918 | } |
919 | |
920 | int EmulatedCamera::dump(struct camera_device* dev, int fd) |
921 | { |
922 | EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv); |
923 | if (ec == NULL) { |
924 | ALOGE("%s: Unexpected NULL camera device", __FUNCTION__); |
925 | return -EINVAL; |
926 | } |
927 | return ec->dumpCamera(fd); |
928 | } |
929 | |
930 | int EmulatedCamera::close(struct hw_device_t* device) |
931 | { |
932 | EmulatedCamera* ec = |
933 | reinterpret_cast<EmulatedCamera*>(reinterpret_cast<struct camera_device*>(device)->priv); |
934 | if (ec == NULL) { |
935 | ALOGE("%s: Unexpected NULL camera device", __FUNCTION__); |
936 | return -EINVAL; |
937 | } |
938 | return ec->closeCamera(); |
939 | } |
940 | |
941 | /**************************************************************************** |
942 | * Static initializer for the camera callback API |
943 | ****************************************************************************/ |
944 | |
945 | camera_device_ops_t EmulatedCamera::mDeviceOps = { |
946 | EmulatedCamera::set_preview_window, |
947 | EmulatedCamera::set_callbacks, |
948 | EmulatedCamera::enable_msg_type, |
949 | EmulatedCamera::disable_msg_type, |
950 | EmulatedCamera::msg_type_enabled, |
951 | EmulatedCamera::start_preview, |
952 | EmulatedCamera::stop_preview, |
953 | EmulatedCamera::preview_enabled, |
954 | EmulatedCamera::store_meta_data_in_buffers, |
955 | EmulatedCamera::start_recording, |
956 | EmulatedCamera::stop_recording, |
957 | EmulatedCamera::recording_enabled, |
958 | EmulatedCamera::release_recording_frame, |
959 | EmulatedCamera::auto_focus, |
960 | EmulatedCamera::cancel_auto_focus, |
961 | EmulatedCamera::take_picture, |
962 | EmulatedCamera::cancel_picture, |
963 | EmulatedCamera::set_parameters, |
964 | EmulatedCamera::get_parameters, |
965 | EmulatedCamera::put_parameters, |
966 | EmulatedCamera::send_command, |
967 | EmulatedCamera::release, |
968 | EmulatedCamera::dump |
969 | }; |
970 | |
971 | /**************************************************************************** |
972 | * Common keys |
973 | ***************************************************************************/ |
974 | |
975 | const char EmulatedCamera::FACING_KEY[] = "prop-facing"; |
976 | const char EmulatedCamera::ORIENTATION_KEY[] = "prop-orientation"; |
977 | const char EmulatedCamera::RECORDING_HINT_KEY[] = "recording-hint"; |
978 | |
979 | /**************************************************************************** |
980 | * Common string values |
981 | ***************************************************************************/ |
982 | |
983 | const char EmulatedCamera::FACING_BACK[] = "back"; |
984 | const char EmulatedCamera::FACING_FRONT[] = "front"; |
985 | |
986 | /**************************************************************************** |
987 | * Helper routines |
988 | ***************************************************************************/ |
989 | |
990 | static char* AddValue(const char* param, const char* val) |
991 | { |
992 | const size_t len1 = strlen(param); |
993 | const size_t len2 = strlen(val); |
994 | char* ret = reinterpret_cast<char*>(malloc(len1 + len2 + 2)); |
995 | ALOGE_IF(ret == NULL, "%s: Memory failure", __FUNCTION__); |
996 | if (ret != NULL) { |
997 | memcpy(ret, param, len1); |
998 | ret[len1] = ','; |
999 | memcpy(ret + len1 + 1, val, len2); |
1000 | ret[len1 + len2 + 1] = '\0'; |
1001 | } |
1002 | return ret; |
1003 | } |
1004 | |
1005 | /**************************************************************************** |
1006 | * Parameter debugging helpers |
1007 | ***************************************************************************/ |
1008 | |
1009 | #if DEBUG_PARAM |
1010 | static void PrintParamDiff(const CameraParameters& current, |
1011 | const char* new_par) |
1012 | { |
1013 | char tmp[2048]; |
1014 | const char* wrk = new_par; |
1015 | |
1016 | /* Divided with ';' */ |
1017 | const char* next = strchr(wrk, ';'); |
1018 | while (next != NULL) { |
1019 | snprintf(tmp, sizeof(tmp), "%.*s", (int)(intptr_t)(next-wrk), wrk); |
1020 | /* in the form key=value */ |
1021 | char* val = strchr(tmp, '='); |
1022 | if (val != NULL) { |
1023 | *val = '\0'; val++; |
1024 | const char* in_current = current.get(tmp); |
1025 | if (in_current != NULL) { |
1026 | if (strcmp(in_current, val)) { |
1027 | ALOGD("=== Value changed: %s: %s -> %s", tmp, in_current, val); |
1028 | } |
1029 | } else { |
1030 | ALOGD("+++ New parameter: %s=%s", tmp, val); |
1031 | } |
1032 | } else { |
1033 | ALOGW("No value separator in %s", tmp); |
1034 | } |
1035 | wrk = next + 1; |
1036 | next = strchr(wrk, ';'); |
1037 | } |
1038 | } |
1039 | #endif /* DEBUG_PARAM */ |
1040 | |
1041 | }; /* namespace android */ |
1042 |