|  | /* | 
|  | * Copyright (C) 2011 The Android Open Source Project | 
|  | * | 
|  | * Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | * you may not use this file except in compliance with the License. | 
|  | * You may obtain a copy of the License at | 
|  | * | 
|  | *      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | * | 
|  | * Unless required by applicable law or agreed to in writing, software | 
|  | * distributed under the License is distributed on an "AS IS" BASIS, | 
|  | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | * See the License for the specific language governing permissions and | 
|  | * limitations under the License. | 
|  | */ | 
|  |  | 
|  | /* | 
|  | * Contains implementation of a class EmulatedCamera that encapsulates | 
|  | * functionality common to all emulated cameras ("fake", "webcam", "video file", | 
|  | * etc.). Instances of this class (for each emulated camera) are created during | 
|  | * the construction of the EmulatedCameraFactory instance. This class serves as | 
|  | * an entry point for all camera API calls that defined by camera_device_ops_t | 
|  | * API. | 
|  | */ | 
|  |  | 
|  | #define LOG_NDEBUG 0 | 
|  | #define LOG_TAG "EmulatedCamera_Camera" | 
|  | #include <cutils/log.h> | 
|  | #include <ui/Rect.h> | 
|  | #include "EmulatedCamera.h" | 
|  | #include "EmulatedFakeCameraDevice.h" | 
|  | #include "Converters.h" | 
|  |  | 
|  | /* Defines whether we should trace parameter changes. */ | 
|  | #define DEBUG_PARAM 1 | 
|  |  | 
|  | namespace android { | 
|  |  | 
|  | #if DEBUG_PARAM | 
|  | /* Calculates and logs parameter changes. | 
|  | * Param: | 
|  | *  current - Current set of camera parameters. | 
|  | *  new_par - String representation of new parameters. | 
|  | */ | 
|  | static void PrintParamDiff(const CameraParameters& current, const char* new_par); | 
|  | #else | 
|  | #define PrintParamDiff(current, new_par)   (void(0)) | 
|  | #endif  /* DEBUG_PARAM */ | 
|  |  | 
|  | /* A helper routine that adds a value to the camera parameter. | 
|  | * Param: | 
|  | *  param - Camera parameter to add a value to. | 
|  | *  val - Value to add. | 
|  | * Return: | 
|  | *  A new string containing parameter with the added value on success, or NULL on | 
|  | *  a failure. If non-NULL string is returned, the caller is responsible for | 
|  | *  freeing it with 'free'. | 
|  | */ | 
|  | static char* AddValue(const char* param, const char* val); | 
|  |  | 
|  | EmulatedCamera::EmulatedCamera(int cameraId, struct hw_module_t* module) | 
|  | : mPreviewWindow(), | 
|  | mCallbackNotifier(), | 
|  | mCameraID(cameraId) | 
|  | { | 
|  | /* | 
|  | * Initialize camera_device descriptor for this object. | 
|  | */ | 
|  |  | 
|  | /* Common header */ | 
|  | common.tag = HARDWARE_DEVICE_TAG; | 
|  | common.version = 0; | 
|  | common.module = module; | 
|  | common.close = EmulatedCamera::close; | 
|  |  | 
|  | /* camera_device fields. */ | 
|  | ops = &mDeviceOps; | 
|  | priv = this; | 
|  | } | 
|  |  | 
|  | EmulatedCamera::~EmulatedCamera() | 
|  | { | 
|  | } | 
|  |  | 
|  | /**************************************************************************** | 
|  | * Public API | 
|  | ***************************************************************************/ | 
|  |  | 
|  | status_t EmulatedCamera::Initialize() | 
|  | { | 
|  | /* | 
|  | * Fake required parameters. | 
|  | */ | 
|  |  | 
|  | /* Only RGBX are supported by the framework for preview window in the emulator! */ | 
|  | mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS, CameraParameters::PIXEL_FORMAT_RGBA8888); | 
|  | mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES, "60,50,25,15,10"); | 
|  | mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE, "(10,60)"); | 
|  | mParameters.set(CameraParameters::KEY_PREVIEW_FPS_RANGE, "10,60"); | 
|  | mParameters.set(CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES, "320x240,0x0"); | 
|  | mParameters.set(CameraParameters::KEY_MAX_EXPOSURE_COMPENSATION, "6"); | 
|  | mParameters.set(CameraParameters::KEY_MIN_EXPOSURE_COMPENSATION, "-6"); | 
|  | mParameters.set(CameraParameters::KEY_EXPOSURE_COMPENSATION_STEP, "0.5"); | 
|  | mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, "512"); | 
|  | mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, "384"); | 
|  | mParameters.set(CameraParameters::KEY_JPEG_QUALITY, "90"); | 
|  | mParameters.set(CameraParameters::KEY_FOCAL_LENGTH, "4.31"); | 
|  | mParameters.set(CameraParameters::KEY_HORIZONTAL_VIEW_ANGLE, "54.8"); | 
|  | mParameters.set(CameraParameters::KEY_VERTICAL_VIEW_ANGLE, "42.5"); | 
|  | mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, "90"); | 
|  |  | 
|  | /* Only RGB formats are supported by preview window in emulator. */ | 
|  | mParameters.setPreviewFormat(CameraParameters::PIXEL_FORMAT_RGBA8888); | 
|  |  | 
|  | /* We don't relay on the actual frame rates supported by the camera device, | 
|  | * since we will emulate them through timeouts in the emulated camera device | 
|  | * worker thread. */ | 
|  | mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES, | 
|  | "30,24,20,15,10,5"); | 
|  | mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE, "(5,30)"); | 
|  | mParameters.set(CameraParameters::KEY_PREVIEW_FPS_RANGE, "5,30"); | 
|  | mParameters.setPreviewFrameRate(24); | 
|  |  | 
|  | /* Only PIXEL_FORMAT_YUV420P is accepted by camera framework in emulator! */ | 
|  | mParameters.set(CameraParameters::KEY_VIDEO_FRAME_FORMAT, | 
|  | CameraParameters::PIXEL_FORMAT_YUV420P); | 
|  | mParameters.set(CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS, | 
|  | CameraParameters::PIXEL_FORMAT_JPEG); | 
|  | mParameters.setPictureFormat(CameraParameters::PIXEL_FORMAT_JPEG); | 
|  |  | 
|  | /* | 
|  | * Not supported features | 
|  | */ | 
|  |  | 
|  | mParameters.set(CameraParameters::KEY_SUPPORTED_FOCUS_MODES, CameraParameters::FOCUS_MODE_FIXED); | 
|  | mParameters.set(CameraParameters::KEY_FOCUS_MODE, CameraParameters::FOCUS_MODE_FIXED); | 
|  |  | 
|  | return NO_ERROR; | 
|  | } | 
|  |  | 
|  | void EmulatedCamera::onNextFrameAvailable(const void* frame, | 
|  | nsecs_t timestamp, | 
|  | EmulatedCameraDevice* camera_dev) | 
|  | { | 
|  | /* Notify the preview window first. */ | 
|  | mPreviewWindow.onNextFrameAvailable(frame, timestamp, camera_dev); | 
|  |  | 
|  | /* Notify callback notifier next. */ | 
|  | mCallbackNotifier.onNextFrameAvailable(frame, timestamp, camera_dev); | 
|  | } | 
|  |  | 
|  | /**************************************************************************** | 
|  | * Camera API implementation. | 
|  | ***************************************************************************/ | 
|  |  | 
|  | status_t EmulatedCamera::connectCamera(hw_device_t** device) | 
|  | { | 
|  | LOGV("%s", __FUNCTION__); | 
|  |  | 
|  | status_t res = EINVAL; | 
|  | EmulatedCameraDevice* const camera_dev = getCameraDevice(); | 
|  | LOGE_IF(camera_dev == NULL, "%s: No camera device instance.", __FUNCTION__); | 
|  |  | 
|  | if (camera_dev != NULL) { | 
|  | /* Connect to the camera device. */ | 
|  | res = getCameraDevice()->connectDevice(); | 
|  | if (res == NO_ERROR) { | 
|  | *device = &common; | 
|  | } | 
|  | } | 
|  |  | 
|  | return -res; | 
|  | } | 
|  |  | 
|  | status_t EmulatedCamera::closeCamera() | 
|  | { | 
|  | LOGV("%s", __FUNCTION__); | 
|  |  | 
|  | return cleanupCamera(); | 
|  | } | 
|  |  | 
|  | status_t EmulatedCamera::getCameraInfo(struct camera_info* info) | 
|  | { | 
|  | LOGV("%s", __FUNCTION__); | 
|  |  | 
|  | const char* valstr = NULL; | 
|  |  | 
|  | valstr = mParameters.get(EmulatedCamera::FACING_KEY); | 
|  | if (valstr != NULL) { | 
|  | if (strcmp(valstr, EmulatedCamera::FACING_FRONT) == 0) { | 
|  | info->facing = CAMERA_FACING_FRONT; | 
|  | } | 
|  | else if (strcmp(valstr, EmulatedCamera::FACING_BACK) == 0) { | 
|  | info->facing = CAMERA_FACING_BACK; | 
|  | } | 
|  | } else { | 
|  | info->facing = CAMERA_FACING_BACK; | 
|  | } | 
|  |  | 
|  | valstr = mParameters.get(EmulatedCamera::ORIENTATION_KEY); | 
|  | if (valstr != NULL) { | 
|  | info->orientation = atoi(valstr); | 
|  | } else { | 
|  | info->orientation = 0; | 
|  | } | 
|  |  | 
|  | return NO_ERROR; | 
|  | } | 
|  |  | 
|  | status_t EmulatedCamera::setPreviewWindow(struct preview_stream_ops* window) | 
|  | { | 
|  | /* Callback should return a negative errno. */ | 
|  | return -mPreviewWindow.setPreviewWindow(window, | 
|  | mParameters.getPreviewFrameRate()); | 
|  | } | 
|  |  | 
|  | void EmulatedCamera::setCallbacks(camera_notify_callback notify_cb, | 
|  | camera_data_callback data_cb, | 
|  | camera_data_timestamp_callback data_cb_timestamp, | 
|  | camera_request_memory get_memory, | 
|  | void* user) | 
|  | { | 
|  | mCallbackNotifier.setCallbacks(notify_cb, data_cb, data_cb_timestamp, | 
|  | get_memory, user); | 
|  | } | 
|  |  | 
|  | void EmulatedCamera::enableMsgType(int32_t msg_type) | 
|  | { | 
|  | mCallbackNotifier.enableMessage(msg_type); | 
|  | } | 
|  |  | 
|  | void EmulatedCamera::disableMsgType(int32_t msg_type) | 
|  | { | 
|  | mCallbackNotifier.disableMessage(msg_type); | 
|  | } | 
|  |  | 
|  | int EmulatedCamera::isMsgTypeEnabled(int32_t msg_type) | 
|  | { | 
|  | return mCallbackNotifier.isMessageEnabled(msg_type); | 
|  | } | 
|  |  | 
|  | status_t EmulatedCamera::startPreview() | 
|  | { | 
|  | /* Callback should return a negative errno. */ | 
|  | return -doStartPreview(); | 
|  | } | 
|  |  | 
|  | void EmulatedCamera::stopPreview() | 
|  | { | 
|  | doStopPreview(); | 
|  | } | 
|  |  | 
|  | int EmulatedCamera::isPreviewEnabled() | 
|  | { | 
|  | return mPreviewWindow.isPreviewEnabled(); | 
|  | } | 
|  |  | 
|  | status_t EmulatedCamera::storeMetaDataInBuffers(int enable) | 
|  | { | 
|  | /* Callback should return a negative errno. */ | 
|  | return -mCallbackNotifier.storeMetaDataInBuffers(enable); | 
|  | } | 
|  |  | 
|  | status_t EmulatedCamera::startRecording() | 
|  | { | 
|  | /* Callback should return a negative errno. */ | 
|  | return -mCallbackNotifier.enableVideoRecording(mParameters.getPreviewFrameRate()); | 
|  | } | 
|  |  | 
|  | void EmulatedCamera::stopRecording() | 
|  | { | 
|  | mCallbackNotifier.disableVideoRecording(); | 
|  | } | 
|  |  | 
|  | int EmulatedCamera::isRecordingEnabled() | 
|  | { | 
|  | return mCallbackNotifier.isVideoRecordingEnabled(); | 
|  | } | 
|  |  | 
|  | void EmulatedCamera::releaseRecordingFrame(const void* opaque) | 
|  | { | 
|  | mCallbackNotifier.releaseRecordingFrame(opaque); | 
|  | } | 
|  |  | 
|  | status_t EmulatedCamera::setAutoFocus() | 
|  | { | 
|  | LOGV("%s", __FUNCTION__); | 
|  |  | 
|  | /* TODO: Future enhancements. */ | 
|  | return NO_ERROR; | 
|  | } | 
|  |  | 
|  | status_t EmulatedCamera::cancelAutoFocus() | 
|  | { | 
|  | LOGV("%s", __FUNCTION__); | 
|  |  | 
|  | /* TODO: Future enhancements. */ | 
|  | return NO_ERROR; | 
|  | } | 
|  |  | 
|  | status_t EmulatedCamera::takePicture() | 
|  | { | 
|  | LOGV("%s", __FUNCTION__); | 
|  |  | 
|  | status_t res; | 
|  | int width, height; | 
|  | uint32_t org_fmt; | 
|  |  | 
|  | /* Collect frame info for the picture. */ | 
|  | mParameters.getPictureSize(&width, &height); | 
|  | const char* pix_fmt = mParameters.getPictureFormat(); | 
|  | if (strcmp(pix_fmt, CameraParameters::PIXEL_FORMAT_YUV420P) == 0) { | 
|  | org_fmt = V4L2_PIX_FMT_YUV420; | 
|  | } else if (strcmp(pix_fmt, CameraParameters::PIXEL_FORMAT_RGBA8888) == 0) { | 
|  | org_fmt = V4L2_PIX_FMT_RGB32; | 
|  | } else if (strcmp(pix_fmt, CameraParameters::PIXEL_FORMAT_YUV420SP) == 0) { | 
|  | org_fmt = V4L2_PIX_FMT_NV21; | 
|  | } else if (strcmp(pix_fmt, CameraParameters::PIXEL_FORMAT_JPEG) == 0) { | 
|  | /* We only have JPEG converted for NV21 format. */ | 
|  | org_fmt = V4L2_PIX_FMT_NV21; | 
|  | } else { | 
|  | LOGE("%s: Unsupported pixel format %s", __FUNCTION__, pix_fmt); | 
|  | return EINVAL; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Make sure preview is not running, and device is stopped before taking | 
|  | * picture. | 
|  | */ | 
|  |  | 
|  | const bool preview_on = mPreviewWindow.isPreviewEnabled(); | 
|  | if (preview_on) { | 
|  | doStopPreview(); | 
|  | } | 
|  |  | 
|  | /* Camera device should have been stopped when the shutter message has been | 
|  | * enabled. */ | 
|  | EmulatedCameraDevice* const camera_dev = getCameraDevice(); | 
|  | if (camera_dev->isStarted()) { | 
|  | LOGW("%s: Camera device is started", __FUNCTION__); | 
|  | camera_dev->stopDeliveringFrames(); | 
|  | camera_dev->stopDevice(); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Take the picture now. | 
|  | */ | 
|  |  | 
|  | /* Start camera device for the picture frame. */ | 
|  | LOGD("Starting camera for picture: %.4s(%s)[%dx%d]", | 
|  | reinterpret_cast<const char*>(&org_fmt), pix_fmt, width, height); | 
|  | res = camera_dev->startDevice(width, height, org_fmt); | 
|  | if (res != NO_ERROR) { | 
|  | if (preview_on) { | 
|  | doStartPreview(); | 
|  | } | 
|  | return res; | 
|  | } | 
|  |  | 
|  | /* Deliver one frame only. */ | 
|  | mCallbackNotifier.setTakingPicture(true); | 
|  | res = camera_dev->startDeliveringFrames(true); | 
|  | if (res != NO_ERROR) { | 
|  | mCallbackNotifier.setTakingPicture(false); | 
|  | if (preview_on) { | 
|  | doStartPreview(); | 
|  | } | 
|  | } | 
|  | return res; | 
|  | } | 
|  |  | 
|  | status_t EmulatedCamera::cancelPicture() | 
|  | { | 
|  | LOGV("%s", __FUNCTION__); | 
|  |  | 
|  | return NO_ERROR; | 
|  | } | 
|  |  | 
|  | status_t EmulatedCamera::setParameters(const char* parms) | 
|  | { | 
|  | LOGV("%s", __FUNCTION__); | 
|  | PrintParamDiff(mParameters, parms); | 
|  |  | 
|  | CameraParameters new_param; | 
|  | String8 str8_param(parms); | 
|  | new_param.unflatten(str8_param); | 
|  | mParameters = new_param; | 
|  |  | 
|  | /* | 
|  | * In emulation, there are certain parameters that are required by the | 
|  | * framework to be exact, and supported by the camera. Since we can't predict | 
|  | * the values of such parameters, we must dynamically update them as they | 
|  | * are set by the framework. | 
|  | */ | 
|  |  | 
|  | /* Supported preview size. */ | 
|  | const char* check = mParameters.get(CameraParameters::KEY_PREVIEW_SIZE); | 
|  | if (check != NULL) { | 
|  | const char* current = | 
|  | mParameters.get(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES); | 
|  | if (strstr(current, check) == NULL) { | 
|  | /* Required size doesn't exist in the list. Add it. */ | 
|  | char* to_add = AddValue(current, check); | 
|  | if (to_add != NULL) { | 
|  | LOGD("+++ %s: Added %s to supported preview sizes", | 
|  | __FUNCTION__, check); | 
|  | mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES, to_add); | 
|  | free(to_add); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Supported preview frame rate. */ | 
|  | check = mParameters.get(CameraParameters::KEY_PREVIEW_FRAME_RATE); | 
|  | if (check != NULL) { | 
|  | const char* current = | 
|  | mParameters.get(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES); | 
|  | if (strstr(current, check) == NULL) { | 
|  | char* to_add = AddValue(current, check); | 
|  | if (to_add != NULL) { | 
|  | LOGD("+++ %s: Added %s to supported preview frame rates", | 
|  | __FUNCTION__, check); | 
|  | mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES, to_add); | 
|  | free(to_add); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Supported picture size. */ | 
|  | check = mParameters.get(CameraParameters::KEY_PICTURE_SIZE); | 
|  | if (check != NULL) { | 
|  | const char* current = | 
|  | mParameters.get(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES); | 
|  | if (strstr(current, check) == NULL) { | 
|  | char* to_add = AddValue(current, check); | 
|  | if (to_add != NULL) { | 
|  | LOGD("+++ %s: Added %s to supported picture sizes", | 
|  | __FUNCTION__, check); | 
|  | mParameters.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES, to_add); | 
|  | free(to_add); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | return NO_ERROR; | 
|  | } | 
|  |  | 
|  | /* A dumb variable indicating "no params" / error on the exit from | 
|  | * EmulatedCamera::getParameters(). */ | 
|  | static char lNoParam = '\0'; | 
|  | char* EmulatedCamera::getParameters() | 
|  | { | 
|  | String8 params(mParameters.flatten()); | 
|  | char* ret_str = | 
|  | reinterpret_cast<char*>(malloc(sizeof(char) * (params.length()+1))); | 
|  | memset(ret_str, 0, params.length()+1); | 
|  | if (ret_str != NULL) { | 
|  | strncpy(ret_str, params.string(), params.length()+1); | 
|  | return ret_str; | 
|  | } else { | 
|  | LOGE("%s: Unable to allocate string for %s", __FUNCTION__, params.string()); | 
|  | /* Apparently, we can't return NULL fron this routine. */ | 
|  | return &lNoParam; | 
|  | } | 
|  | } | 
|  |  | 
|  | void EmulatedCamera::putParameters(char* params) | 
|  | { | 
|  | /* This method simply frees parameters allocated in getParameters(). */ | 
|  | if (params != NULL && params != &lNoParam) { | 
|  | free(params); | 
|  | } | 
|  | } | 
|  |  | 
|  | status_t EmulatedCamera::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) | 
|  | { | 
|  | LOGV("%s: cmd = %d, arg1 = %d, arg2 = %d", __FUNCTION__, cmd, arg1, arg2); | 
|  |  | 
|  | /* TODO: Future enhancements. */ | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | void EmulatedCamera::releaseCamera() | 
|  | { | 
|  | LOGV("%s", __FUNCTION__); | 
|  |  | 
|  | cleanupCamera(); | 
|  | } | 
|  |  | 
|  | status_t EmulatedCamera::dumpCamera(int fd) | 
|  | { | 
|  | LOGV("%s", __FUNCTION__); | 
|  |  | 
|  | /* TODO: Future enhancements. */ | 
|  | return -EINVAL; | 
|  | } | 
|  |  | 
|  | /**************************************************************************** | 
|  | * Preview management. | 
|  | ***************************************************************************/ | 
|  |  | 
|  | status_t EmulatedCamera::doStartPreview() | 
|  | { | 
|  | LOGV("%s", __FUNCTION__); | 
|  |  | 
|  | status_t res = mPreviewWindow.startPreview(); | 
|  | if (res != NO_ERROR) { | 
|  | return res; | 
|  | } | 
|  | if (getCameraDevice()->isStarted()) { | 
|  | return NO_ERROR; | 
|  | } | 
|  |  | 
|  | EmulatedCameraDevice* camera_dev = getCameraDevice(); | 
|  |  | 
|  | /* Make sure camera device is connected. */ | 
|  | if (!camera_dev->isConnected()) { | 
|  | res = camera_dev->connectDevice(); | 
|  | if (res != NO_ERROR) { | 
|  | mPreviewWindow.stopPreview(); | 
|  | return res; | 
|  | } | 
|  | } | 
|  |  | 
|  | int width, height; | 
|  | /* Lets see what should we use for frame width, and height. */ | 
|  | if (mParameters.get(CameraParameters::KEY_VIDEO_SIZE) != NULL) { | 
|  | mParameters.getVideoSize(&width, &height); | 
|  | } else { | 
|  | mParameters.getPreviewSize(&width, &height); | 
|  | } | 
|  | /* Lets see what should we use for the frame pixel format. */ | 
|  | const char* pix_fmt = | 
|  | mParameters.get(CameraParameters::KEY_VIDEO_FRAME_FORMAT); | 
|  | if (pix_fmt == NULL) { | 
|  | pix_fmt = mParameters.getPreviewFormat(); | 
|  | } | 
|  | if (pix_fmt == NULL) { | 
|  | LOGE("%s: Unable to obtain video format", __FUNCTION__); | 
|  | mPreviewWindow.stopPreview(); | 
|  | return EINVAL; | 
|  | } | 
|  | uint32_t org_fmt; | 
|  | if (strcmp(pix_fmt, CameraParameters::PIXEL_FORMAT_YUV420P) == 0) { | 
|  | org_fmt = V4L2_PIX_FMT_YVU420; | 
|  | } else if (strcmp(pix_fmt, CameraParameters::PIXEL_FORMAT_RGBA8888) == 0) { | 
|  | org_fmt = V4L2_PIX_FMT_RGB32; | 
|  | } else if (strcmp(pix_fmt, CameraParameters::PIXEL_FORMAT_YUV420SP) == 0) { | 
|  | org_fmt = V4L2_PIX_FMT_NV21; | 
|  | } else { | 
|  | LOGE("%s: Unsupported pixel format %s", __FUNCTION__, pix_fmt); | 
|  | mPreviewWindow.stopPreview(); | 
|  | return EINVAL; | 
|  | } | 
|  | LOGD("Starting camera: %dx%d -> %.4s", width, height, pix_fmt); | 
|  | res = camera_dev->startDevice(width, height, org_fmt); | 
|  | if (res != NO_ERROR) { | 
|  | mPreviewWindow.stopPreview(); | 
|  | return res; | 
|  | } | 
|  |  | 
|  | res = camera_dev->startDeliveringFrames(false); | 
|  | if (res != NO_ERROR) { | 
|  | camera_dev->stopDevice(); | 
|  | mPreviewWindow.stopPreview(); | 
|  | } | 
|  |  | 
|  | return res; | 
|  | } | 
|  |  | 
|  | status_t EmulatedCamera::doStopPreview() | 
|  | { | 
|  | LOGV("%s", __FUNCTION__); | 
|  |  | 
|  | status_t res = NO_ERROR; | 
|  | /* Stop the camera. */ | 
|  | if (getCameraDevice()->isStarted()) { | 
|  | getCameraDevice()->stopDeliveringFrames(); | 
|  | res = getCameraDevice()->stopDevice(); | 
|  | } | 
|  |  | 
|  | if (res == NO_ERROR) { | 
|  | /* Disable preview as well. */ | 
|  | mPreviewWindow.stopPreview(); | 
|  | } | 
|  |  | 
|  | return NO_ERROR; | 
|  | } | 
|  |  | 
|  | /**************************************************************************** | 
|  | * Private API. | 
|  | ***************************************************************************/ | 
|  |  | 
|  | status_t EmulatedCamera::cleanupCamera() | 
|  | { | 
|  | status_t res = NO_ERROR; | 
|  |  | 
|  | /* If preview is running - stop it. */ | 
|  | res = doStopPreview(); | 
|  | if (res != NO_ERROR) { | 
|  | return -res; | 
|  | } | 
|  |  | 
|  | /* Stop and disconnect the camera device. */ | 
|  | EmulatedCameraDevice* const camera_dev = getCameraDevice(); | 
|  | if (camera_dev != NULL) { | 
|  | if (camera_dev->isStarted()) { | 
|  | camera_dev->stopDeliveringFrames(); | 
|  | res = camera_dev->stopDevice(); | 
|  | if (res != NO_ERROR) { | 
|  | return -res; | 
|  | } | 
|  | } | 
|  | if (camera_dev->isConnected()) { | 
|  | res = camera_dev->disconnectDevice(); | 
|  | if (res != NO_ERROR) { | 
|  | return -res; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | mCallbackNotifier.cleanupCBNotifier(); | 
|  |  | 
|  | return NO_ERROR; | 
|  | } | 
|  |  | 
|  | /**************************************************************************** | 
|  | * Camera API callbacks as defined by camera_device_ops structure. | 
|  | * | 
|  | * Callbacks here simply dispatch the calls to an appropriate method inside | 
|  | * EmulatedCamera instance, defined by the 'dev' parameter. | 
|  | ***************************************************************************/ | 
|  |  | 
|  | int EmulatedCamera::set_preview_window(struct camera_device* dev, | 
|  | struct preview_stream_ops* window) | 
|  | { | 
|  | EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv); | 
|  | if (ec == NULL) { | 
|  | LOGE("%s: Unexpected NULL camera device", __FUNCTION__); | 
|  | return -EINVAL; | 
|  | } | 
|  | return ec->setPreviewWindow(window); | 
|  | } | 
|  |  | 
|  | void EmulatedCamera::set_callbacks( | 
|  | struct camera_device* dev, | 
|  | camera_notify_callback notify_cb, | 
|  | camera_data_callback data_cb, | 
|  | camera_data_timestamp_callback data_cb_timestamp, | 
|  | camera_request_memory get_memory, | 
|  | void* user) | 
|  | { | 
|  | EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv); | 
|  | if (ec == NULL) { | 
|  | LOGE("%s: Unexpected NULL camera device", __FUNCTION__); | 
|  | return; | 
|  | } | 
|  | ec->setCallbacks(notify_cb, data_cb, data_cb_timestamp, get_memory, user); | 
|  | } | 
|  |  | 
|  | void EmulatedCamera::enable_msg_type(struct camera_device* dev, int32_t msg_type) | 
|  | { | 
|  | EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv); | 
|  | if (ec == NULL) { | 
|  | LOGE("%s: Unexpected NULL camera device", __FUNCTION__); | 
|  | return; | 
|  | } | 
|  | ec->enableMsgType(msg_type); | 
|  | } | 
|  |  | 
|  | void EmulatedCamera::disable_msg_type(struct camera_device* dev, int32_t msg_type) | 
|  | { | 
|  | EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv); | 
|  | if (ec == NULL) { | 
|  | LOGE("%s: Unexpected NULL camera device", __FUNCTION__); | 
|  | return; | 
|  | } | 
|  | ec->disableMsgType(msg_type); | 
|  | } | 
|  |  | 
|  | int EmulatedCamera::msg_type_enabled(struct camera_device* dev, int32_t msg_type) | 
|  | { | 
|  | EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv); | 
|  | if (ec == NULL) { | 
|  | LOGE("%s: Unexpected NULL camera device", __FUNCTION__); | 
|  | return -EINVAL; | 
|  | } | 
|  | return ec->isMsgTypeEnabled(msg_type); | 
|  | } | 
|  |  | 
|  | int EmulatedCamera::start_preview(struct camera_device* dev) | 
|  | { | 
|  | EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv); | 
|  | if (ec == NULL) { | 
|  | LOGE("%s: Unexpected NULL camera device", __FUNCTION__); | 
|  | return -EINVAL; | 
|  | } | 
|  | return ec->startPreview(); | 
|  | } | 
|  |  | 
|  | void EmulatedCamera::stop_preview(struct camera_device* dev) | 
|  | { | 
|  | EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv); | 
|  | if (ec == NULL) { | 
|  | LOGE("%s: Unexpected NULL camera device", __FUNCTION__); | 
|  | return; | 
|  | } | 
|  | ec->stopPreview(); | 
|  | } | 
|  |  | 
|  | int EmulatedCamera::preview_enabled(struct camera_device* dev) | 
|  | { | 
|  | EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv); | 
|  | if (ec == NULL) { | 
|  | LOGE("%s: Unexpected NULL camera device", __FUNCTION__); | 
|  | return -EINVAL; | 
|  | } | 
|  | return ec->isPreviewEnabled(); | 
|  | } | 
|  |  | 
|  | int EmulatedCamera::store_meta_data_in_buffers(struct camera_device* dev, | 
|  | int enable) | 
|  | { | 
|  | EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv); | 
|  | if (ec == NULL) { | 
|  | LOGE("%s: Unexpected NULL camera device", __FUNCTION__); | 
|  | return -EINVAL; | 
|  | } | 
|  | return ec->storeMetaDataInBuffers(enable); | 
|  | } | 
|  |  | 
|  | int EmulatedCamera::start_recording(struct camera_device* dev) | 
|  | { | 
|  | EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv); | 
|  | if (ec == NULL) { | 
|  | LOGE("%s: Unexpected NULL camera device", __FUNCTION__); | 
|  | return -EINVAL; | 
|  | } | 
|  | return ec->startRecording(); | 
|  | } | 
|  |  | 
|  | void EmulatedCamera::stop_recording(struct camera_device* dev) | 
|  | { | 
|  | EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv); | 
|  | if (ec == NULL) { | 
|  | LOGE("%s: Unexpected NULL camera device", __FUNCTION__); | 
|  | return; | 
|  | } | 
|  | ec->stopRecording(); | 
|  | } | 
|  |  | 
|  | int EmulatedCamera::recording_enabled(struct camera_device* dev) | 
|  | { | 
|  | EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv); | 
|  | if (ec == NULL) { | 
|  | LOGE("%s: Unexpected NULL camera device", __FUNCTION__); | 
|  | return -EINVAL; | 
|  | } | 
|  | return ec->isRecordingEnabled(); | 
|  | } | 
|  |  | 
|  | void EmulatedCamera::release_recording_frame(struct camera_device* dev, | 
|  | const void* opaque) | 
|  | { | 
|  | EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv); | 
|  | if (ec == NULL) { | 
|  | LOGE("%s: Unexpected NULL camera device", __FUNCTION__); | 
|  | return; | 
|  | } | 
|  | ec->releaseRecordingFrame(opaque); | 
|  | } | 
|  |  | 
|  | int EmulatedCamera::auto_focus(struct camera_device* dev) | 
|  | { | 
|  | EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv); | 
|  | if (ec == NULL) { | 
|  | LOGE("%s: Unexpected NULL camera device", __FUNCTION__); | 
|  | return -EINVAL; | 
|  | } | 
|  | return ec->setAutoFocus(); | 
|  | } | 
|  |  | 
|  | int EmulatedCamera::cancel_auto_focus(struct camera_device* dev) | 
|  | { | 
|  | EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv); | 
|  | if (ec == NULL) { | 
|  | LOGE("%s: Unexpected NULL camera device", __FUNCTION__); | 
|  | return -EINVAL; | 
|  | } | 
|  | return ec->cancelAutoFocus(); | 
|  | } | 
|  |  | 
|  | int EmulatedCamera::take_picture(struct camera_device* dev) | 
|  | { | 
|  | EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv); | 
|  | if (ec == NULL) { | 
|  | LOGE("%s: Unexpected NULL camera device", __FUNCTION__); | 
|  | return -EINVAL; | 
|  | } | 
|  | return ec->takePicture(); | 
|  | } | 
|  |  | 
|  | int EmulatedCamera::cancel_picture(struct camera_device* dev) | 
|  | { | 
|  | EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv); | 
|  | if (ec == NULL) { | 
|  | LOGE("%s: Unexpected NULL camera device", __FUNCTION__); | 
|  | return -EINVAL; | 
|  | } | 
|  | return ec->cancelPicture(); | 
|  | } | 
|  |  | 
|  | int EmulatedCamera::set_parameters(struct camera_device* dev, const char* parms) | 
|  | { | 
|  | EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv); | 
|  | if (ec == NULL) { | 
|  | LOGE("%s: Unexpected NULL camera device", __FUNCTION__); | 
|  | return -EINVAL; | 
|  | } | 
|  | return ec->setParameters(parms); | 
|  | } | 
|  |  | 
|  | char* EmulatedCamera::get_parameters(struct camera_device* dev) | 
|  | { | 
|  | EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv); | 
|  | if (ec == NULL) { | 
|  | LOGE("%s: Unexpected NULL camera device", __FUNCTION__); | 
|  | return NULL; | 
|  | } | 
|  | return ec->getParameters(); | 
|  | } | 
|  |  | 
|  | void EmulatedCamera::put_parameters(struct camera_device* dev, char* params) | 
|  | { | 
|  | EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv); | 
|  | if (ec == NULL) { | 
|  | LOGE("%s: Unexpected NULL camera device", __FUNCTION__); | 
|  | return; | 
|  | } | 
|  | ec->putParameters(params); | 
|  | } | 
|  |  | 
|  | int EmulatedCamera::send_command(struct camera_device* dev, | 
|  | int32_t cmd, | 
|  | int32_t arg1, | 
|  | int32_t arg2) | 
|  | { | 
|  | EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv); | 
|  | if (ec == NULL) { | 
|  | LOGE("%s: Unexpected NULL camera device", __FUNCTION__); | 
|  | return -EINVAL; | 
|  | } | 
|  | return ec->sendCommand(cmd, arg1, arg2); | 
|  | } | 
|  |  | 
|  | void EmulatedCamera::release(struct camera_device* dev) | 
|  | { | 
|  | EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv); | 
|  | if (ec == NULL) { | 
|  | LOGE("%s: Unexpected NULL camera device", __FUNCTION__); | 
|  | return; | 
|  | } | 
|  | ec->releaseCamera(); | 
|  | } | 
|  |  | 
|  | int EmulatedCamera::dump(struct camera_device* dev, int fd) | 
|  | { | 
|  | EmulatedCamera* ec = reinterpret_cast<EmulatedCamera*>(dev->priv); | 
|  | if (ec == NULL) { | 
|  | LOGE("%s: Unexpected NULL camera device", __FUNCTION__); | 
|  | return -EINVAL; | 
|  | } | 
|  | return ec->dumpCamera(fd); | 
|  | } | 
|  |  | 
|  | int EmulatedCamera::close(struct hw_device_t* device) | 
|  | { | 
|  | EmulatedCamera* ec = | 
|  | reinterpret_cast<EmulatedCamera*>(reinterpret_cast<struct camera_device*>(device)->priv); | 
|  | if (ec == NULL) { | 
|  | LOGE("%s: Unexpected NULL camera device", __FUNCTION__); | 
|  | return -EINVAL; | 
|  | } | 
|  | return ec->closeCamera(); | 
|  | } | 
|  |  | 
|  | /**************************************************************************** | 
|  | * Static initializer for the camera callback API | 
|  | ****************************************************************************/ | 
|  |  | 
|  | camera_device_ops_t EmulatedCamera::mDeviceOps = { | 
|  | EmulatedCamera::set_preview_window, | 
|  | EmulatedCamera::set_callbacks, | 
|  | EmulatedCamera::enable_msg_type, | 
|  | EmulatedCamera::disable_msg_type, | 
|  | EmulatedCamera::msg_type_enabled, | 
|  | EmulatedCamera::start_preview, | 
|  | EmulatedCamera::stop_preview, | 
|  | EmulatedCamera::preview_enabled, | 
|  | EmulatedCamera::store_meta_data_in_buffers, | 
|  | EmulatedCamera::start_recording, | 
|  | EmulatedCamera::stop_recording, | 
|  | EmulatedCamera::recording_enabled, | 
|  | EmulatedCamera::release_recording_frame, | 
|  | EmulatedCamera::auto_focus, | 
|  | EmulatedCamera::cancel_auto_focus, | 
|  | EmulatedCamera::take_picture, | 
|  | EmulatedCamera::cancel_picture, | 
|  | EmulatedCamera::set_parameters, | 
|  | EmulatedCamera::get_parameters, | 
|  | EmulatedCamera::put_parameters, | 
|  | EmulatedCamera::send_command, | 
|  | EmulatedCamera::release, | 
|  | EmulatedCamera::dump | 
|  | }; | 
|  |  | 
|  | /**************************************************************************** | 
|  | * Common keys | 
|  | ***************************************************************************/ | 
|  |  | 
|  | const char EmulatedCamera::FACING_KEY[]       = "prop-facing"; | 
|  | const char EmulatedCamera::ORIENTATION_KEY[]  = "prop-orientation"; | 
|  |  | 
|  | /**************************************************************************** | 
|  | * Common string values | 
|  | ***************************************************************************/ | 
|  |  | 
|  | const char EmulatedCamera::FACING_BACK[]      = "back"; | 
|  | const char EmulatedCamera::FACING_FRONT[]     = "front"; | 
|  |  | 
|  | /**************************************************************************** | 
|  | * Helper routines | 
|  | ***************************************************************************/ | 
|  |  | 
|  | static char* AddValue(const char* param, const char* val) | 
|  | { | 
|  | const size_t len1 = strlen(param); | 
|  | const size_t len2 = strlen(val); | 
|  | char* ret = reinterpret_cast<char*>(malloc(len1 + len2 + 2)); | 
|  | LOGE_IF(ret == NULL, "%s: Memory failure", __FUNCTION__); | 
|  | if (ret != NULL) { | 
|  | memcpy(ret, param, len1); | 
|  | ret[len1] = ','; | 
|  | memcpy(ret + len1 + 1, val, len2); | 
|  | ret[len1 + len2 + 1] = '\0'; | 
|  | } | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | /**************************************************************************** | 
|  | * Parameter debugging helpers | 
|  | ***************************************************************************/ | 
|  |  | 
|  | #if DEBUG_PARAM | 
|  | static void PrintParamDiff(const CameraParameters& current, | 
|  | const char* new_par) | 
|  | { | 
|  | char tmp[2048]; | 
|  | const char* wrk = new_par; | 
|  |  | 
|  | /* Divided with ';' */ | 
|  | const char* next = strchr(wrk, ';'); | 
|  | while (next != NULL) { | 
|  | snprintf(tmp, sizeof(tmp), "%.*s", next-wrk, wrk); | 
|  | /* in the form key=value */ | 
|  | char* val = strchr(tmp, '='); | 
|  | if (val != NULL) { | 
|  | *val = '\0'; val++; | 
|  | const char* in_current = current.get(tmp); | 
|  | if (in_current != NULL) { | 
|  | if (strcmp(in_current, val)) { | 
|  | LOGD("=== Value changed: %s: %s -> %s", tmp, in_current, val); | 
|  | } | 
|  | } else { | 
|  | LOGD("+++ New parameter: %s=%s", tmp, val); | 
|  | } | 
|  | } else { | 
|  | LOGW("No value separator in %s", tmp); | 
|  | } | 
|  | wrk = next + 1; | 
|  | next = strchr(wrk, ';'); | 
|  | } | 
|  | } | 
|  | #endif  /* DEBUG_PARAM */ | 
|  |  | 
|  | }; /* namespace android */ |