Fake camera implementation
The code submitted here builds a camera.goldfish.so module that encapsulates a camera HAL. The major components of the camera HAL implementation are: * Generic HAL module implemented in emulated_camera_hal.cpp There is nothing much to it: just exporting the required HAL header. * EmulatedCameraFactory class that manages emulated cameras, and provides handling for camera_module_methods_ methods. There is only one object of this class, that is statically instantiated when camera.goldfish.so module is loaded. * EmulatedCamera class that implements camera_device_ops_t API. Objects of this class are instantiated during EmulatedCameraFactory construction, and they interact with objects of EmulatedCameraDevice class to get frames. * EmulatedCameraDevice class encapsulates an actual camera device. Objects of this class are contained in EmulatedCameraDevice objects, and interact with them as required by the API. The fake camera implementation is shared between EmulatedFakeCamera, and EmulatedFakeCameraDevice classes. They are pretty light. In fact, EmulatedFakeCamera is nothing more than just a placeholder for EmulatedFakeCameraDevice instance, and EmulatedFakeCameraDevice does nothing more, than just drawing a checker board with a bouncing square. Other components / routines are minor: helpers, wrappers, etc. The code is heavily commented, so there will be plenty of explanations between the lines. Change-Id: I4463e14c255c6e3b1dcca17bed5f4efde32d9879
This commit is contained in:
51
tools/emulator/system/camera/Android.mk
Normal file
51
tools/emulator/system/camera/Android.mk
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
ifndef BUILD_EMULATOR_CAMERA_HAL
|
||||||
|
BUILD_EMULATOR_CAMERA_HAL := true
|
||||||
|
|
||||||
|
LOCAL_PATH := $(call my-dir)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
|
||||||
|
LOCAL_CFLAGS += -fno-short-enums -DQEMU_HARDWARE
|
||||||
|
LOCAL_SHARED_LIBRARIES:= \
|
||||||
|
libbinder \
|
||||||
|
libutils \
|
||||||
|
libcutils \
|
||||||
|
libcamera_client \
|
||||||
|
libui \
|
||||||
|
|
||||||
|
LOCAL_SRC_FILES := \
|
||||||
|
emulated_camera_hal.cpp \
|
||||||
|
emulated_camera_factory.cpp \
|
||||||
|
emulated_camera.cpp \
|
||||||
|
emulated_camera_device.cpp \
|
||||||
|
emulated_fake_camera.cpp \
|
||||||
|
emulated_fake_camera_device.cpp \
|
||||||
|
converters.cpp \
|
||||||
|
preview_window.cpp \
|
||||||
|
callback_notifier.cpp
|
||||||
|
|
||||||
|
ifeq ($(TARGET_PRODUCT),vbox_x86)
|
||||||
|
LOCAL_MODULE := camera.vbox_x86
|
||||||
|
else
|
||||||
|
LOCAL_MODULE := camera.goldfish
|
||||||
|
endif
|
||||||
|
|
||||||
|
LOCAL_MODULE_TAGS := debug
|
||||||
|
include $(BUILD_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
endif # BUILD_EMULATOR_CAMERA_HAL
|
||||||
295
tools/emulator/system/camera/callback_notifier.cpp
Normal file
295
tools/emulator/system/camera/callback_notifier.cpp
Normal file
@@ -0,0 +1,295 @@
|
|||||||
|
/*
|
||||||
|
* 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 CallbackNotifier that manages callbacks set
|
||||||
|
* via set_callbacks, enable_msg_type, and disable_msg_type camera HAL API.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LOG_NDEBUG 0
|
||||||
|
#define LOG_TAG "EmulatedCamera_CallbackNotifier"
|
||||||
|
#include <cutils/log.h>
|
||||||
|
#include <media/stagefright/MetadataBufferType.h>
|
||||||
|
#include "emulated_camera_device.h"
|
||||||
|
#include "callback_notifier.h"
|
||||||
|
|
||||||
|
namespace android {
|
||||||
|
|
||||||
|
/* Descriptor for video frame metadata. */
|
||||||
|
struct VideoFrameMetadata
|
||||||
|
{
|
||||||
|
/* Required field that defines metadata buffer type. */
|
||||||
|
MetadataBufferType type;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO: This is taken from a sample code. It seems to work, but requires
|
||||||
|
* clarifications on what metadata structure should look like!
|
||||||
|
*/
|
||||||
|
|
||||||
|
const void* frame;
|
||||||
|
int offset;
|
||||||
|
camera_memory_t* holder;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* String representation of camera messages. */
|
||||||
|
static const char* _camera_messages[] =
|
||||||
|
{
|
||||||
|
"CAMERA_MSG_ERROR",
|
||||||
|
"CAMERA_MSG_SHUTTER",
|
||||||
|
"CAMERA_MSG_FOCUS",
|
||||||
|
"CAMERA_MSG_ZOOM",
|
||||||
|
"CAMERA_MSG_PREVIEW_FRAME",
|
||||||
|
"CAMERA_MSG_VIDEO_FRAME",
|
||||||
|
"CAMERA_MSG_POSTVIEW_FRAME",
|
||||||
|
"CAMERA_MSG_RAW_IMAGE",
|
||||||
|
"CAMERA_MSG_COMPRESSED_IMAGE",
|
||||||
|
"CAMERA_MSG_RAW_IMAGE_NOTIFY",
|
||||||
|
"CAMERA_MSG_PREVIEW_METADATA"
|
||||||
|
};
|
||||||
|
static const int _camera_messages_num = sizeof(_camera_messages) / sizeof(char*);
|
||||||
|
|
||||||
|
/* Builds an array of strings for the given set of messages.
|
||||||
|
* Param:
|
||||||
|
* msg - Messages to get strings for,
|
||||||
|
* strings - Array where to save strings
|
||||||
|
* max - Maximum number of entries in the array.
|
||||||
|
* Return:
|
||||||
|
* Number of strings saved into the 'strings' array.
|
||||||
|
*/
|
||||||
|
static int _GetMessageStrings(uint32_t msg, const char** strings, int max)
|
||||||
|
{
|
||||||
|
int index = 0;
|
||||||
|
int out = 0;
|
||||||
|
while (msg != 0 && out < max && index < _camera_messages_num) {
|
||||||
|
while ((msg & 0x1) == 0 && index < _camera_messages_num) {
|
||||||
|
msg >>= 1;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
if ((msg & 0x1) != 0 && index < _camera_messages_num) {
|
||||||
|
strings[out] = _camera_messages[index];
|
||||||
|
out++;
|
||||||
|
msg >>= 1;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Logs messages, enabled by the mask. */
|
||||||
|
static void _PrintMessages(uint32_t msg)
|
||||||
|
{
|
||||||
|
const char* strs[_camera_messages_num];
|
||||||
|
const int translated = _GetMessageStrings(msg, strs, _camera_messages_num);
|
||||||
|
for (int n = 0; n < translated; n++) {
|
||||||
|
LOGV(" %s", strs[n]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CallbackNotifier::CallbackNotifier()
|
||||||
|
: notify_cb_(NULL),
|
||||||
|
data_cb_(NULL),
|
||||||
|
data_cb_timestamp_(NULL),
|
||||||
|
get_memory_(NULL),
|
||||||
|
cb_opaque_(NULL),
|
||||||
|
last_frame_(0),
|
||||||
|
frame_after_(0),
|
||||||
|
message_enabler_(0),
|
||||||
|
video_recording_enabled_(false),
|
||||||
|
store_meta_data_in_buffers_(true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CallbackNotifier::~CallbackNotifier()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Camera API
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
void CallbackNotifier::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)
|
||||||
|
{
|
||||||
|
LOGV("%s: %p, %p, %p, %p (%p)",
|
||||||
|
__FUNCTION__, notify_cb, data_cb, data_cb_timestamp, get_memory, user);
|
||||||
|
|
||||||
|
Mutex::Autolock locker(&object_lock_);
|
||||||
|
notify_cb_ = notify_cb;
|
||||||
|
data_cb_ = data_cb;
|
||||||
|
data_cb_timestamp_ = data_cb_timestamp;
|
||||||
|
get_memory_ = get_memory;
|
||||||
|
cb_opaque_ = user;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallbackNotifier::EnableMessage(uint msg_type)
|
||||||
|
{
|
||||||
|
LOGV("%s: msg_type = 0x%x", __FUNCTION__, msg_type);
|
||||||
|
_PrintMessages(msg_type);
|
||||||
|
|
||||||
|
Mutex::Autolock locker(&object_lock_);
|
||||||
|
message_enabler_ |= msg_type;
|
||||||
|
LOGV("**** Currently enabled messages:");
|
||||||
|
_PrintMessages(message_enabler_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallbackNotifier::DisableMessage(uint msg_type)
|
||||||
|
{
|
||||||
|
LOGV("%s: msg_type = 0x%x", __FUNCTION__, msg_type);
|
||||||
|
_PrintMessages(msg_type);
|
||||||
|
|
||||||
|
Mutex::Autolock locker(&object_lock_);
|
||||||
|
message_enabler_ &= ~msg_type;
|
||||||
|
LOGV("**** Currently enabled messages:");
|
||||||
|
_PrintMessages(message_enabler_);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CallbackNotifier::IsMessageEnabled(uint msg_type)
|
||||||
|
{
|
||||||
|
Mutex::Autolock locker(&object_lock_);
|
||||||
|
return message_enabler_ & ~msg_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t CallbackNotifier::EnableVideoRecording(int fps)
|
||||||
|
{
|
||||||
|
LOGV("%s: FPS = %d", __FUNCTION__, fps);
|
||||||
|
|
||||||
|
Mutex::Autolock locker(&object_lock_);
|
||||||
|
video_recording_enabled_ = true;
|
||||||
|
last_frame_ = 0;
|
||||||
|
frame_after_ = 1000000 / fps;
|
||||||
|
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallbackNotifier::DisableVideoRecording()
|
||||||
|
{
|
||||||
|
LOGV("%s:", __FUNCTION__);
|
||||||
|
|
||||||
|
Mutex::Autolock locker(&object_lock_);
|
||||||
|
video_recording_enabled_ = false;
|
||||||
|
last_frame_ = 0;
|
||||||
|
frame_after_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CallbackNotifier::IsVideoRecordingEnabled()
|
||||||
|
{
|
||||||
|
Mutex::Autolock locker(&object_lock_);
|
||||||
|
return video_recording_enabled_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallbackNotifier::ReleaseRecordingFrame(const void* opaque)
|
||||||
|
{
|
||||||
|
LOGV("%s: frame = %p", __FUNCTION__, opaque);
|
||||||
|
|
||||||
|
if (opaque != NULL) {
|
||||||
|
const VideoFrameMetadata* meta =
|
||||||
|
reinterpret_cast<const VideoFrameMetadata*>(opaque);
|
||||||
|
if (meta->type == kMetadataBufferTypeCameraSource &&
|
||||||
|
meta->holder != NULL) {
|
||||||
|
meta->holder->release(meta->holder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t CallbackNotifier::StoreMetaDataInBuffers(bool enable)
|
||||||
|
{
|
||||||
|
LOGV("%s: %s", __FUNCTION__, enable ? "true" : "false");
|
||||||
|
|
||||||
|
Mutex::Autolock locker(&object_lock_);
|
||||||
|
store_meta_data_in_buffers_ = enable;
|
||||||
|
|
||||||
|
/* Return INVALID_OPERATION means HAL does not support metadata. So HAL will
|
||||||
|
* return actual frame data with CAMERA_MSG_VIDEO_FRRAME. Return
|
||||||
|
* INVALID_OPERATION to mean metadata is not supported. */
|
||||||
|
return INVALID_OPERATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public API
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
void CallbackNotifier::Cleanup()
|
||||||
|
{
|
||||||
|
Mutex::Autolock locker(&object_lock_);
|
||||||
|
message_enabler_ = 0;
|
||||||
|
notify_cb_ = NULL;
|
||||||
|
data_cb_ = NULL;
|
||||||
|
data_cb_timestamp_ = NULL;
|
||||||
|
get_memory_ = NULL;
|
||||||
|
cb_opaque_ = NULL;
|
||||||
|
last_frame_ = 0;
|
||||||
|
frame_after_ = 0;
|
||||||
|
video_recording_enabled_ = false;
|
||||||
|
store_meta_data_in_buffers_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallbackNotifier::OnNextFrameAvailable(const void* frame,
|
||||||
|
nsecs_t timestamp,
|
||||||
|
EmulatedCameraDevice* camera_dev)
|
||||||
|
{
|
||||||
|
Mutex::Autolock locker(&object_lock_);
|
||||||
|
|
||||||
|
if ((message_enabler_ & CAMERA_MSG_VIDEO_FRAME) != 0 &&
|
||||||
|
data_cb_timestamp_ != NULL && video_recording_enabled_ &&
|
||||||
|
IsTimeForNewVideoFrame()) {
|
||||||
|
/* Ready for new video frame. Allocate frame holder. */
|
||||||
|
camera_memory_t* holder =
|
||||||
|
get_memory_(-1, sizeof(VideoFrameMetadata), 1, NULL);
|
||||||
|
if (NULL != holder && NULL != holder->data) {
|
||||||
|
if (store_meta_data_in_buffers_) {
|
||||||
|
VideoFrameMetadata* meta =
|
||||||
|
reinterpret_cast<VideoFrameMetadata*>(holder->data);
|
||||||
|
meta->type = kMetadataBufferTypeCameraSource;
|
||||||
|
meta->frame = frame;
|
||||||
|
meta->offset = 0;
|
||||||
|
meta->holder = holder;
|
||||||
|
data_cb_timestamp_(timestamp, CAMERA_MSG_VIDEO_FRAME,
|
||||||
|
holder, 0, cb_opaque_);
|
||||||
|
/* Allocated holder will be released by release_recording_frame
|
||||||
|
* call. */
|
||||||
|
} else {
|
||||||
|
holder->data = const_cast<void*>(frame);
|
||||||
|
data_cb_timestamp_(timestamp, CAMERA_MSG_VIDEO_FRAME,
|
||||||
|
holder, 0, cb_opaque_);
|
||||||
|
holder->release(holder);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LOGE("%s: Memory failure", __FUNCTION__);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private API
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
bool CallbackNotifier::IsTimeForNewVideoFrame()
|
||||||
|
{
|
||||||
|
timeval cur_time;
|
||||||
|
gettimeofday(&cur_time, NULL);
|
||||||
|
const uint64_t cur_mks = cur_time.tv_sec * 1000000LL + cur_time.tv_usec;
|
||||||
|
if ((cur_mks - last_frame_) >= frame_after_) {
|
||||||
|
last_frame_ = cur_mks;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}; /* namespace android */
|
||||||
192
tools/emulator/system/camera/callback_notifier.h
Normal file
192
tools/emulator/system/camera/callback_notifier.h
Normal file
@@ -0,0 +1,192 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HW_EMULATOR_CAMERA_CALLBACK_NOTIFIER_H
|
||||||
|
#define HW_EMULATOR_CAMERA_CALLBACK_NOTIFIER_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Contains declaration of a class CallbackNotifier that manages callbacks set
|
||||||
|
* via set_callbacks, enable_msg_type, and disable_msg_type camera HAL API.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace android {
|
||||||
|
|
||||||
|
class EmulatedCameraDevice;
|
||||||
|
|
||||||
|
/* Manages callbacks set via set_callbacks, enable_msg_type, and disable_msg_type
|
||||||
|
* camera HAL API.
|
||||||
|
*
|
||||||
|
* Objects of this class are contained in EmulatedCamera objects, and handle
|
||||||
|
* relevant camera API callbacks.
|
||||||
|
*/
|
||||||
|
class CallbackNotifier {
|
||||||
|
public:
|
||||||
|
/* Constructs CallbackNotifier instance. */
|
||||||
|
CallbackNotifier();
|
||||||
|
|
||||||
|
/* Destructs CallbackNotifier instance. */
|
||||||
|
~CallbackNotifier();
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Camera API
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
public:
|
||||||
|
/* Actual handler for camera_device_ops_t::set_callbacks callback.
|
||||||
|
* This method is called by the containing emulated camera object when it is
|
||||||
|
* handing the camera_device_ops_t::set_callbacks callback.
|
||||||
|
*/
|
||||||
|
void 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);
|
||||||
|
|
||||||
|
/* Actual handler for camera_device_ops_t::enable_msg_type callback.
|
||||||
|
* This method is called by the containing emulated camera object when it is
|
||||||
|
* handing the camera_device_ops_t::enable_msg_type callback.
|
||||||
|
*/
|
||||||
|
void EnableMessage(uint msg_type);
|
||||||
|
|
||||||
|
/* Actual handler for camera_device_ops_t::disable_msg_type callback.
|
||||||
|
* This method is called by the containing emulated camera object when it is
|
||||||
|
* handing the camera_device_ops_t::disable_msg_type callback.
|
||||||
|
*/
|
||||||
|
void DisableMessage(uint msg_type);
|
||||||
|
|
||||||
|
/* Actual handler for camera_device_ops_t::msg_type_enabled callback.
|
||||||
|
* This method is called by the containing emulated camera object when it is
|
||||||
|
* handing the camera_device_ops_t::msg_type_enabled callback.
|
||||||
|
* Return:
|
||||||
|
* 0 if message is disabled, or non-zero value, if message is enabled.
|
||||||
|
*/
|
||||||
|
int IsMessageEnabled(uint msg_type);
|
||||||
|
|
||||||
|
/* Actual handler for camera_device_ops_t::store_meta_data_in_buffers
|
||||||
|
* callback. This method is called by the containing emulated camera object
|
||||||
|
* when it is handing the camera_device_ops_t::store_meta_data_in_buffers
|
||||||
|
* callback.
|
||||||
|
* Return:
|
||||||
|
* NO_ERROR on success, or an appropriate error status.
|
||||||
|
*/
|
||||||
|
status_t StoreMetaDataInBuffers(bool enable);
|
||||||
|
|
||||||
|
/* Enables video recording.
|
||||||
|
* This method is called by the containing emulated camera object when it is
|
||||||
|
* handing the camera_device_ops_t::start_recording callback.
|
||||||
|
* Param:
|
||||||
|
* fps - Video frame frequency. This parameter determins when a frame
|
||||||
|
* received via OnNextFrameAvailable call will be pushed through the
|
||||||
|
* callback.
|
||||||
|
* Return:
|
||||||
|
* NO_ERROR on success, or an appropriate error status.
|
||||||
|
*/
|
||||||
|
status_t EnableVideoRecording(int fps);
|
||||||
|
|
||||||
|
/* Disables video recording.
|
||||||
|
* This method is called by the containing emulated camera object when it is
|
||||||
|
* handing the camera_device_ops_t::stop_recording callback.
|
||||||
|
*/
|
||||||
|
void DisableVideoRecording();
|
||||||
|
|
||||||
|
/* Checks id video recording is enabled.
|
||||||
|
* This method is called by the containing emulated camera object when it is
|
||||||
|
* handing the camera_device_ops_t::recording_enabled callback.
|
||||||
|
* Return:
|
||||||
|
* true if video recording is enabled, or false if it is disabled.
|
||||||
|
*/
|
||||||
|
bool IsVideoRecordingEnabled();
|
||||||
|
|
||||||
|
/* Releases video frame, sent to the framework.
|
||||||
|
* This method is called by the containing emulated camera object when it is
|
||||||
|
* handing the camera_device_ops_t::release_recording_frame callback.
|
||||||
|
*/
|
||||||
|
void ReleaseRecordingFrame(const void* opaque);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public API
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
public:
|
||||||
|
/* Resets the callback notifier. */
|
||||||
|
void Cleanup();
|
||||||
|
|
||||||
|
/* Next frame is available in the camera device.
|
||||||
|
* This is a notification callback that is invoked by the camera device when
|
||||||
|
* a new frame is available.
|
||||||
|
* Note that most likely this method is called in context of a worker thread
|
||||||
|
* that camera device has created for frame capturing.
|
||||||
|
* Param:
|
||||||
|
* frame - Captured frame, or NULL if camera device didn't pull the frame
|
||||||
|
* yet. If NULL is passed in this parameter use GetCurrentFrame method
|
||||||
|
* of the camera device class to obtain the next frame. Also note that
|
||||||
|
* the size of the frame that is passed here (as well as the frame
|
||||||
|
* returned from the GetCurrentFrame method) is defined by the current
|
||||||
|
* frame settings (width + height + pixel format) for the camera device.
|
||||||
|
* timestamp - Frame's timestamp.
|
||||||
|
* camera_dev - Camera device instance that delivered the frame.
|
||||||
|
*/
|
||||||
|
void OnNextFrameAvailable(const void* frame,
|
||||||
|
nsecs_t timestamp,
|
||||||
|
EmulatedCameraDevice* camera_dev);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private API
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/* Checks if it's time to push new video frame.
|
||||||
|
* Note that this method must be called while object is locked. */
|
||||||
|
bool IsTimeForNewVideoFrame();
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Data members
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/* Locks this instance for data change. */
|
||||||
|
Mutex object_lock_;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Callbacks, registered in set_callbacks.
|
||||||
|
*/
|
||||||
|
|
||||||
|
camera_notify_callback notify_cb_;
|
||||||
|
camera_data_callback data_cb_;
|
||||||
|
camera_data_timestamp_callback data_cb_timestamp_;
|
||||||
|
camera_request_memory get_memory_;
|
||||||
|
void* cb_opaque_;
|
||||||
|
|
||||||
|
/* Timestamp (abs. microseconds) when last frame has been delivered to the
|
||||||
|
* framework. */
|
||||||
|
uint64_t last_frame_;
|
||||||
|
|
||||||
|
/* Video frequency in microseconds. */
|
||||||
|
uint32_t frame_after_;
|
||||||
|
|
||||||
|
/* Message enabler. */
|
||||||
|
uint32_t message_enabler_;
|
||||||
|
|
||||||
|
/* Video recording status. */
|
||||||
|
bool video_recording_enabled_;
|
||||||
|
|
||||||
|
/* Status of the metadata buffering. */
|
||||||
|
bool store_meta_data_in_buffers_;
|
||||||
|
};
|
||||||
|
|
||||||
|
}; /* namespace android */
|
||||||
|
|
||||||
|
#endif /* HW_EMULATOR_CAMERA_CALLBACK_NOTIFIER_H */
|
||||||
56
tools/emulator/system/camera/converters.cpp
Normal file
56
tools/emulator/system/camera/converters.cpp
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* 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 implemenation of framebuffer conversion routines.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LOG_NDEBUG 0
|
||||||
|
#define LOG_TAG "EmulatedCamera_Converter"
|
||||||
|
#include <cutils/log.h>
|
||||||
|
#include "converters.h"
|
||||||
|
|
||||||
|
namespace android {
|
||||||
|
|
||||||
|
void YV12ToRGB565(const void* yv12, void* rgb, int width, int height)
|
||||||
|
{
|
||||||
|
const int pix_total = width * height;
|
||||||
|
uint16_t* rgb_buf = reinterpret_cast<uint16_t*>(rgb);
|
||||||
|
const uint8_t* Y = reinterpret_cast<const uint8_t*>(yv12);
|
||||||
|
const uint8_t* Cb_pos = Y + pix_total;
|
||||||
|
const uint8_t* Cr_pos = Cb_pos + pix_total / 4;
|
||||||
|
const uint8_t* Cb = Cb_pos;
|
||||||
|
const uint8_t* Cr = Cr_pos;
|
||||||
|
for (int y = 0; y < height; y++) {
|
||||||
|
for (int x = 0; x < width; x += 2) {
|
||||||
|
const uint8_t nCb = *Cb; Cb++;
|
||||||
|
const uint8_t nCr = *Cr; Cr++;
|
||||||
|
*rgb_buf = YCbCrToRGB565(*Y, nCb, nCr);
|
||||||
|
Y++; rgb_buf++;
|
||||||
|
*rgb_buf = YCbCrToRGB565(*Y, nCb, nCr);
|
||||||
|
Y++; rgb_buf++;
|
||||||
|
}
|
||||||
|
if (y & 0x1) {
|
||||||
|
Cb_pos = Cb;
|
||||||
|
Cr_pos = Cr;
|
||||||
|
} else {
|
||||||
|
Cb = Cb_pos;
|
||||||
|
Cr = Cr_pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}; /* namespace android */
|
||||||
136
tools/emulator/system/camera/converters.h
Normal file
136
tools/emulator/system/camera/converters.h
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HW_EMULATOR_CAMERA_CONVERTERS_H
|
||||||
|
#define HW_EMULATOR_CAMERA_CONVERTERS_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Contains declaration of framebuffer conversion routines.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace android {
|
||||||
|
|
||||||
|
inline uint8_t clamp(int x)
|
||||||
|
{
|
||||||
|
if (x > 255) return 255;
|
||||||
|
if (x < 0) return 0;
|
||||||
|
return static_cast<uint8_t>(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* RGB565 color masks
|
||||||
|
*/
|
||||||
|
|
||||||
|
static const int kRed = 0xf800;
|
||||||
|
static const int kGreen = 0x07e0;
|
||||||
|
static const int kBlue = 0x001f;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* RGB -> YCbCr conversion constants and macros
|
||||||
|
*/
|
||||||
|
|
||||||
|
static const double kR0 = 0.299;
|
||||||
|
static const double kR1 = 0.587;
|
||||||
|
static const double kR2 = 0.114;
|
||||||
|
static const double kR3 = 0.169;
|
||||||
|
static const double kR4 = 0.331;
|
||||||
|
static const double kR5 = 0.499;
|
||||||
|
static const double kR6 = 0.499;
|
||||||
|
static const double kR7 = 0.418;
|
||||||
|
static const double kR8 = 0.0813;
|
||||||
|
|
||||||
|
#define RGB2Y(R,G,B) static_cast<uint8_t>(kR0*R + kR1*G + kR2*B)
|
||||||
|
#define RGB2Cb(R,G,B) static_cast<uint8_t>(-kR3*R - kR4*G + kR5*B + 128)
|
||||||
|
#define RGB2Cr(R,G,B) static_cast<uint8_t>(kR6*R - kR7*G - kR8*B + 128)
|
||||||
|
|
||||||
|
/* Converts RGB565 color to YCbCr */
|
||||||
|
inline void RGB565ToYCbCr(uint16_t rgb, uint8_t* y, uint8_t* Cb, uint8_t* Cr)
|
||||||
|
{
|
||||||
|
const uint32_t r = (rgb & kRed) >> 11;
|
||||||
|
const uint32_t g = (rgb & kGreen) >> 5;
|
||||||
|
const uint32_t b = rgb & kBlue;
|
||||||
|
|
||||||
|
*y = RGB2Y(r,g,b);
|
||||||
|
*Cb = RGB2Cb(r,g,b);
|
||||||
|
*Cr = RGB2Cr(r,g,b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Gets a 'Y' value for RGB565 color. */
|
||||||
|
inline uint8_t RGB565ToY(uint16_t rgb)
|
||||||
|
{
|
||||||
|
const uint32_t r = (rgb & kRed) >> 11;
|
||||||
|
const uint32_t g = (rgb & kGreen) >> 5;
|
||||||
|
const uint32_t b = rgb & kBlue;
|
||||||
|
|
||||||
|
return RGB2Y(r,g,b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* YCbCr -> RGB conversion constants and macros
|
||||||
|
*/
|
||||||
|
static const double kY0 = 1.402;
|
||||||
|
static const double kY1 = 0.344;
|
||||||
|
static const double kY2 = 0.714;
|
||||||
|
static const double kY3 = 1.772;
|
||||||
|
|
||||||
|
#define YCbCr2R(Y, Cb, Cr) clamp(Y + kY0*(Cr-128))
|
||||||
|
#define YCbCr2G(Y, Cb, Cr) clamp(Y - kY1*(Cb-128) - kY2*(Cr-128))
|
||||||
|
#define YCbCr2B(Y, Cb, Cr) clamp(Y + kY3*(Cb-128))
|
||||||
|
|
||||||
|
/* Converts YCbCr color to RGB565. */
|
||||||
|
inline uint16_t YCbCrToRGB565(uint8_t y, uint8_t Cb, uint8_t Cr)
|
||||||
|
{
|
||||||
|
const uint16_t r = YCbCr2R(y, Cb, Cr) & 0x1f;
|
||||||
|
const uint16_t g = YCbCr2G(y, Cb, Cr) & 0x3f;
|
||||||
|
const uint16_t b = YCbCr2B(y, Cb, Cr) & 0x1f;
|
||||||
|
|
||||||
|
return b | (g << 5) | (r << 11);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* YCbCr pixel descriptor. */
|
||||||
|
struct YCbCrPixel {
|
||||||
|
uint8_t Y;
|
||||||
|
uint8_t Cb;
|
||||||
|
uint8_t Cr;
|
||||||
|
|
||||||
|
inline YCbCrPixel()
|
||||||
|
: Y(0), Cb(0), Cr(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
inline explicit YCbCrPixel(uint16_t rgb565)
|
||||||
|
{
|
||||||
|
RGB565ToYCbCr(rgb565, &Y, &Cb, &Cr);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void get(uint8_t* pY, uint8_t* pCb, uint8_t* pCr) const
|
||||||
|
{
|
||||||
|
*pY = Y; *pCb = Cb; *pCr = Cr;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Converts an YV12 framebuffer to RGB565 framebuffer.
|
||||||
|
* Param:
|
||||||
|
* yv12 - YV12 framebuffer.
|
||||||
|
* rgb - RGB565 framebuffer.
|
||||||
|
* width, height - Dimensions for both framebuffers.
|
||||||
|
*/
|
||||||
|
void YV12ToRGB565(const void* yv12, void* rgb, int width, int height);
|
||||||
|
|
||||||
|
}; /* namespace android */
|
||||||
|
|
||||||
|
#endif /* HW_EMULATOR_CAMERA_CONVERTERS_H */
|
||||||
|
|
||||||
938
tools/emulator/system/camera/emulated_camera.cpp
Normal file
938
tools/emulator/system/camera/emulated_camera.cpp
Normal file
@@ -0,0 +1,938 @@
|
|||||||
|
/*
|
||||||
|
* 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 "emulated_camera.h"
|
||||||
|
#include "emulated_fake_camera_device.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)
|
||||||
|
: preview_window_(),
|
||||||
|
callback_notifier_(),
|
||||||
|
camera_id_(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 = &device_ops_;
|
||||||
|
priv = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
EmulatedCamera::~EmulatedCamera()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public API
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
status_t EmulatedCamera::Initialize()
|
||||||
|
{
|
||||||
|
LOGV("%s", __FUNCTION__);
|
||||||
|
|
||||||
|
/* Emulated camera is facing back. */
|
||||||
|
parameters_.set(EmulatedCamera::FACING_KEY, EmulatedCamera::FACING_BACK);
|
||||||
|
/* Portrait orientation. */
|
||||||
|
parameters_.set(EmulatedCamera::ORIENTATION_KEY, 90);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fake required parameters.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Only RGBX are supported by the framework for preview window in the emulator! */
|
||||||
|
parameters_.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS, CameraParameters::PIXEL_FORMAT_RGB565);
|
||||||
|
parameters_.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES, "60,50,25,15,10");
|
||||||
|
parameters_.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE, "(10,60)");
|
||||||
|
parameters_.set(CameraParameters::KEY_PREVIEW_FPS_RANGE, "10,60");
|
||||||
|
parameters_.set(CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES, "320x240,0x0");
|
||||||
|
parameters_.set(CameraParameters::KEY_MAX_EXPOSURE_COMPENSATION, "6");
|
||||||
|
parameters_.set(CameraParameters::KEY_MIN_EXPOSURE_COMPENSATION, "-6");
|
||||||
|
parameters_.set(CameraParameters::KEY_EXPOSURE_COMPENSATION_STEP, "0.5");
|
||||||
|
parameters_.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, "512");
|
||||||
|
parameters_.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, "384");
|
||||||
|
parameters_.set(CameraParameters::KEY_JPEG_QUALITY, "90");
|
||||||
|
parameters_.set(CameraParameters::KEY_FOCAL_LENGTH, "4.31");
|
||||||
|
parameters_.set(CameraParameters::KEY_HORIZONTAL_VIEW_ANGLE, "54.8");
|
||||||
|
parameters_.set(CameraParameters::KEY_VERTICAL_VIEW_ANGLE, "42.5");
|
||||||
|
parameters_.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, "90");
|
||||||
|
parameters_.setPreviewFormat(CameraParameters::PIXEL_FORMAT_RGB565);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Not supported features
|
||||||
|
*/
|
||||||
|
|
||||||
|
parameters_.set(CameraParameters::KEY_SUPPORTED_FOCUS_MODES, CameraParameters::FOCUS_MODE_FIXED);
|
||||||
|
parameters_.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. */
|
||||||
|
preview_window_.OnNextFrameAvailable(frame, timestamp, camera_dev);
|
||||||
|
|
||||||
|
/* Notify callback notifier next. */
|
||||||
|
callback_notifier_.OnNextFrameAvailable(frame, timestamp, camera_dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Camera API implementation.
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
status_t EmulatedCamera::Connect(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()->Connect();
|
||||||
|
if (res == NO_ERROR) {
|
||||||
|
*device = &common;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -res;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t EmulatedCamera::Close()
|
||||||
|
{
|
||||||
|
LOGV("%s", __FUNCTION__);
|
||||||
|
|
||||||
|
return Cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t EmulatedCamera::GetCameraInfo(struct camera_info* info)
|
||||||
|
{
|
||||||
|
LOGV("%s", __FUNCTION__);
|
||||||
|
|
||||||
|
const char* valstr = NULL;
|
||||||
|
|
||||||
|
valstr = parameters_.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 = parameters_.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 -preview_window_.SetPreviewWindow(window,
|
||||||
|
parameters_.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)
|
||||||
|
{
|
||||||
|
callback_notifier_.SetCallbacks(notify_cb, data_cb, data_cb_timestamp,
|
||||||
|
get_memory, user);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmulatedCamera::EnableMsgType(int32_t msg_type)
|
||||||
|
{
|
||||||
|
callback_notifier_.EnableMessage(msg_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmulatedCamera::DisableMsgType(int32_t msg_type)
|
||||||
|
{
|
||||||
|
callback_notifier_.DisableMessage(msg_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
int EmulatedCamera::MsgTypeEnabled(int32_t msg_type)
|
||||||
|
{
|
||||||
|
return callback_notifier_.IsMessageEnabled(msg_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t EmulatedCamera::StartPreview()
|
||||||
|
{
|
||||||
|
LOGV("%s", __FUNCTION__);
|
||||||
|
|
||||||
|
/* Callback should return a negative errno. */
|
||||||
|
return -DoStartPreview();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmulatedCamera::StopPreview()
|
||||||
|
{
|
||||||
|
LOGV("%s", __FUNCTION__);
|
||||||
|
|
||||||
|
DoStopPreview();
|
||||||
|
}
|
||||||
|
|
||||||
|
int EmulatedCamera::PreviewEnabled()
|
||||||
|
{
|
||||||
|
return preview_window_.IsEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t EmulatedCamera::StoreMetaDataInBuffers(int enable)
|
||||||
|
{
|
||||||
|
/* Callback should return a negative errno. */
|
||||||
|
return -callback_notifier_.StoreMetaDataInBuffers(enable);
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t EmulatedCamera::StartRecording()
|
||||||
|
{
|
||||||
|
/* Callback should return a negative errno. */
|
||||||
|
return -callback_notifier_.EnableVideoRecording(parameters_.getPreviewFrameRate());
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmulatedCamera::StopRecording()
|
||||||
|
{
|
||||||
|
callback_notifier_.DisableVideoRecording();
|
||||||
|
}
|
||||||
|
|
||||||
|
int EmulatedCamera::RecordingEnabled()
|
||||||
|
{
|
||||||
|
return callback_notifier_.IsVideoRecordingEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmulatedCamera::ReleaseRecordingFrame(const void* opaque)
|
||||||
|
{
|
||||||
|
callback_notifier_.ReleaseRecordingFrame(opaque);
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t EmulatedCamera::AutoFocus()
|
||||||
|
{
|
||||||
|
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__);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Before taking picture, pause the camera (pause worker thread), and pause
|
||||||
|
* the preview.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Take the picture now.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* After picture has been taken, resume the preview, and the camera (if any
|
||||||
|
* has been paused.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t EmulatedCamera::CancelPicture()
|
||||||
|
{
|
||||||
|
LOGV("%s", __FUNCTION__);
|
||||||
|
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t EmulatedCamera::SetParameters(const char* parms)
|
||||||
|
{
|
||||||
|
LOGV("%s", __FUNCTION__);
|
||||||
|
_PrintParamDiff(parameters_, parms);
|
||||||
|
|
||||||
|
CameraParameters new_param;
|
||||||
|
String8 str8_param(parms);
|
||||||
|
new_param.unflatten(str8_param);
|
||||||
|
parameters_ = 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 = parameters_.get(CameraParameters::KEY_PREVIEW_SIZE);
|
||||||
|
if (check != NULL) {
|
||||||
|
const char* current =
|
||||||
|
parameters_.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);
|
||||||
|
parameters_.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES, to_add);
|
||||||
|
free(to_add);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Supported preview frame rate. */
|
||||||
|
check = parameters_.get(CameraParameters::KEY_PREVIEW_FRAME_RATE);
|
||||||
|
if (check != NULL) {
|
||||||
|
const char* current =
|
||||||
|
parameters_.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);
|
||||||
|
parameters_.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES, to_add);
|
||||||
|
free(to_add);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Supported picture size. */
|
||||||
|
check = parameters_.get(CameraParameters::KEY_PICTURE_SIZE);
|
||||||
|
if (check != NULL) {
|
||||||
|
const char* current =
|
||||||
|
parameters_.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);
|
||||||
|
parameters_.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 _no_param = '\0';
|
||||||
|
char* EmulatedCamera::GetParameters()
|
||||||
|
{
|
||||||
|
String8 params(parameters_.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 &_no_param;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmulatedCamera::PutParameters(char* params)
|
||||||
|
{
|
||||||
|
/* This method simply frees parameters allocated in GetParameters(). */
|
||||||
|
if (params != NULL && params != &_no_param) {
|
||||||
|
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::Release()
|
||||||
|
{
|
||||||
|
LOGV("%s", __FUNCTION__);
|
||||||
|
|
||||||
|
Cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t EmulatedCamera::Dump(int fd)
|
||||||
|
{
|
||||||
|
LOGV("%s", __FUNCTION__);
|
||||||
|
|
||||||
|
/* TODO: Future enhancements. */
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Preview management.
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
status_t EmulatedCamera::DoStartPreview()
|
||||||
|
{
|
||||||
|
status_t res = preview_window_.Start();
|
||||||
|
|
||||||
|
/* Start the camera. */
|
||||||
|
if (res == NO_ERROR && !GetCameraDevice()->IsCapturing()) {
|
||||||
|
res = StartCamera();
|
||||||
|
if (res != NO_ERROR) {
|
||||||
|
/* If camera didn't start, disable the preview window. */
|
||||||
|
preview_window_.Stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t EmulatedCamera::DoStopPreview()
|
||||||
|
{
|
||||||
|
status_t res = NO_ERROR;
|
||||||
|
/* Stop the camera. */
|
||||||
|
if (GetCameraDevice()->IsCapturing()) {
|
||||||
|
res = StopCamera();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res == NO_ERROR) {
|
||||||
|
/* Disable preview as well. */
|
||||||
|
preview_window_.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t EmulatedCamera::StartCamera()
|
||||||
|
{
|
||||||
|
status_t res = EINVAL;
|
||||||
|
EmulatedCameraDevice* camera_dev = GetCameraDevice();
|
||||||
|
if (camera_dev != NULL) {
|
||||||
|
if (!camera_dev->IsConnected()) {
|
||||||
|
res = camera_dev->Connect();
|
||||||
|
if (res != NO_ERROR) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!camera_dev->IsCapturing()) {
|
||||||
|
int width, height;
|
||||||
|
/* Lets see what should we use for frame width, and height. */
|
||||||
|
if (parameters_.get(CameraParameters::KEY_VIDEO_SIZE) != NULL) {
|
||||||
|
parameters_.getVideoSize(&width, &height);
|
||||||
|
} else {
|
||||||
|
parameters_.getPreviewSize(&width, &height);
|
||||||
|
}
|
||||||
|
/* Lets see what should we use for the frame pixel format. */
|
||||||
|
const char* pix_fmt = parameters_.get(CameraParameters::KEY_VIDEO_FRAME_FORMAT);
|
||||||
|
if (pix_fmt == NULL) {
|
||||||
|
pix_fmt = parameters_.getPreviewFormat();
|
||||||
|
}
|
||||||
|
if (pix_fmt == NULL) {
|
||||||
|
LOGE("%s: Unable to obtain video format", __FUNCTION__);
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
uint32_t org_fmt;
|
||||||
|
if (strcmp(pix_fmt, CameraParameters::PIXEL_FORMAT_RGB565) == 0) {
|
||||||
|
org_fmt = V4L2_PIX_FMT_RGB565;
|
||||||
|
} else if (strcmp(pix_fmt, CameraParameters::PIXEL_FORMAT_YUV420P) == 0) {
|
||||||
|
org_fmt = V4L2_PIX_FMT_YVU420;
|
||||||
|
} else {
|
||||||
|
LOGE("%s: Unsupported pixel format %s", __FUNCTION__, pix_fmt);
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
LOGD("Starting camera: %dx%d -> %s", width, height, pix_fmt);
|
||||||
|
res = camera_dev->StartCapturing(width, height, org_fmt);
|
||||||
|
if (res != NO_ERROR) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t EmulatedCamera::StopCamera()
|
||||||
|
{
|
||||||
|
status_t res = NO_ERROR;
|
||||||
|
EmulatedCameraDevice* const camera_dev = GetCameraDevice();
|
||||||
|
if (camera_dev != NULL) {
|
||||||
|
if (camera_dev->IsCapturing()) {
|
||||||
|
res = camera_dev->StopCapturing();
|
||||||
|
if (res != NO_ERROR) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private API.
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
status_t EmulatedCamera::Cleanup()
|
||||||
|
{
|
||||||
|
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->IsCapturing()) {
|
||||||
|
res = camera_dev->StopCapturing();
|
||||||
|
if (res != NO_ERROR) {
|
||||||
|
return -res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (camera_dev->IsConnected()) {
|
||||||
|
res = camera_dev->Disconnect();
|
||||||
|
if (res != NO_ERROR) {
|
||||||
|
return -res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
callback_notifier_.Cleanup();
|
||||||
|
|
||||||
|
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->MsgTypeEnabled(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->PreviewEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
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->RecordingEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
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->AutoFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
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->Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
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->Dump(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->Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Static initializer for the camera callback API
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
camera_device_ops_t EmulatedCamera::device_ops_ = {
|
||||||
|
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 */
|
||||||
423
tools/emulator/system/camera/emulated_camera.h
Normal file
423
tools/emulator/system/camera/emulated_camera.h
Normal file
@@ -0,0 +1,423 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HW_EMULATOR_CAMERA_EMULATED_CAMERA_H
|
||||||
|
#define HW_EMULATOR_CAMERA_EMULATED_CAMERA_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Contains declaration 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <camera/CameraParameters.h>
|
||||||
|
#include "emulated_camera_device.h"
|
||||||
|
#include "preview_window.h"
|
||||||
|
#include "callback_notifier.h"
|
||||||
|
|
||||||
|
namespace android {
|
||||||
|
|
||||||
|
/* Encapsulates functionality common to all emulated cameras ("fake", "webcam",
|
||||||
|
* "file stream", etc.).
|
||||||
|
*
|
||||||
|
* Note that EmulatedCameraFactory instantiates object of this class just once,
|
||||||
|
* when EmulatedCameraFactory instance gets constructed. Connection to /
|
||||||
|
* disconnection from the actual camera device is handled by calls to Connect(),
|
||||||
|
* and Close() methods of this class that are ivoked in response to
|
||||||
|
* hw_module_methods_t::open, and camera_device::close callbacks.
|
||||||
|
*/
|
||||||
|
class EmulatedCamera : public camera_device {
|
||||||
|
public:
|
||||||
|
/* Constructs EmulatedCamera instance.
|
||||||
|
* Param:
|
||||||
|
* cameraId - Zero based camera identifier, which is an index of the camera
|
||||||
|
* instance in camera factory's array.
|
||||||
|
* module - Emulated camera HAL module descriptor.
|
||||||
|
*/
|
||||||
|
EmulatedCamera(int cameraId, struct hw_module_t* module);
|
||||||
|
|
||||||
|
/* Destructs EmulatedCamera instance. */
|
||||||
|
virtual ~EmulatedCamera();
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Abstract API
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
public:
|
||||||
|
/* Gets emulated camera device used by this instance of the emulated camera.
|
||||||
|
*/
|
||||||
|
virtual EmulatedCameraDevice* GetCameraDevice() = 0;
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public API
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
public:
|
||||||
|
/* Initializes EmulatedCamera instance.
|
||||||
|
* Return:
|
||||||
|
* NO_ERROR on success, or an appropriate error status on failure.
|
||||||
|
*/
|
||||||
|
virtual status_t Initialize();
|
||||||
|
|
||||||
|
/* Next frame is available in the camera device.
|
||||||
|
* This is a notification callback that is invoked by the camera device when
|
||||||
|
* a new frame is available.
|
||||||
|
* Note that most likely this method is called in context of a worker thread
|
||||||
|
* that camera device has created for frame capturing.
|
||||||
|
* Param:
|
||||||
|
* frame - Captured frame, or NULL if camera device didn't pull the frame
|
||||||
|
* yet. If NULL is passed in this parameter use GetCurrentFrame method
|
||||||
|
* of the camera device class to obtain the next frame. Also note that
|
||||||
|
* the size of the frame that is passed here (as well as the frame
|
||||||
|
* returned from the GetCurrentFrame method) is defined by the current
|
||||||
|
* frame settings (width + height + pixel format) for the camera device.
|
||||||
|
* timestamp - Frame's timestamp.
|
||||||
|
* camera_dev - Camera device instance that delivered the frame.
|
||||||
|
*/
|
||||||
|
virtual void OnNextFrameAvailable(const void* frame,
|
||||||
|
nsecs_t timestamp,
|
||||||
|
EmulatedCameraDevice* camera_dev);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Camera API implementation
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
public:
|
||||||
|
/* Creates connection to the emulated camera device.
|
||||||
|
* This method is called in response to hw_module_methods_t::open callback.
|
||||||
|
* NOTE: When this method is called the object is locked.
|
||||||
|
* Note that failures in this method are reported as negave EXXX statuses.
|
||||||
|
*/
|
||||||
|
virtual status_t Connect(hw_device_t** device);
|
||||||
|
|
||||||
|
/* Closes connection to the emulated camera.
|
||||||
|
* This method is called in response to camera_device::close callback.
|
||||||
|
* NOTE: When this method is called the object is locked.
|
||||||
|
* Note that failures in this method are reported as negave EXXX statuses.
|
||||||
|
*/
|
||||||
|
virtual status_t Close();
|
||||||
|
|
||||||
|
/* Gets camera information.
|
||||||
|
* This method is called in response to camera_module_t::get_camera_info
|
||||||
|
* callback.
|
||||||
|
* NOTE: When this method is called the object is locked.
|
||||||
|
* Note that failures in this method are reported as negave EXXX statuses.
|
||||||
|
*/
|
||||||
|
virtual status_t GetCameraInfo(struct camera_info* info);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Camera API implementation.
|
||||||
|
* These methods are called from the camera API callback routines.
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/* Actual handler for camera_device_ops_t::set_preview_window callback.
|
||||||
|
* NOTE: When this method is called the object is locked.
|
||||||
|
* Note that failures in this method are reported as negave EXXX statuses.
|
||||||
|
*/
|
||||||
|
virtual status_t SetPreviewWindow(struct preview_stream_ops *window);
|
||||||
|
|
||||||
|
/* Actual handler for camera_device_ops_t::set_callbacks callback.
|
||||||
|
* NOTE: When this method is called the object is locked.
|
||||||
|
*/
|
||||||
|
virtual void 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);
|
||||||
|
|
||||||
|
/* Actual handler for camera_device_ops_t::enable_msg_type callback.
|
||||||
|
* NOTE: When this method is called the object is locked.
|
||||||
|
*/
|
||||||
|
virtual void EnableMsgType(int32_t msg_type);
|
||||||
|
|
||||||
|
/* Actual handler for camera_device_ops_t::disable_msg_type callback.
|
||||||
|
* NOTE: When this method is called the object is locked.
|
||||||
|
*/
|
||||||
|
virtual void DisableMsgType(int32_t msg_type);
|
||||||
|
|
||||||
|
/* Actual handler for camera_device_ops_t::msg_type_enabled callback.
|
||||||
|
* NOTE: When this method is called the object is locked.
|
||||||
|
* Return:
|
||||||
|
* 0 if message(s) is (are) disabled, != 0 if enabled.
|
||||||
|
*/
|
||||||
|
virtual int MsgTypeEnabled(int32_t msg_type);
|
||||||
|
|
||||||
|
/* Actual handler for camera_device_ops_t::start_preview callback.
|
||||||
|
* NOTE: When this method is called the object is locked.
|
||||||
|
* Note that failures in this method are reported as negave EXXX statuses.
|
||||||
|
*/
|
||||||
|
virtual status_t StartPreview();
|
||||||
|
|
||||||
|
/* Actual handler for camera_device_ops_t::stop_preview callback.
|
||||||
|
* NOTE: When this method is called the object is locked.
|
||||||
|
*/
|
||||||
|
virtual void StopPreview();
|
||||||
|
|
||||||
|
/* Actual handler for camera_device_ops_t::preview_enabled callback.
|
||||||
|
* NOTE: When this method is called the object is locked.
|
||||||
|
* Return:
|
||||||
|
* 0 if preview is disabled, != 0 if enabled.
|
||||||
|
*/
|
||||||
|
virtual int PreviewEnabled();
|
||||||
|
|
||||||
|
/* Actual handler for camera_device_ops_t::store_meta_data_in_buffers callback.
|
||||||
|
* NOTE: When this method is called the object is locked.
|
||||||
|
* Note that failures in this method are reported as negave EXXX statuses.
|
||||||
|
*/
|
||||||
|
virtual status_t StoreMetaDataInBuffers(int enable);
|
||||||
|
|
||||||
|
/* Actual handler for camera_device_ops_t::start_recording callback.
|
||||||
|
* NOTE: When this method is called the object is locked.
|
||||||
|
* Note that failures in this method are reported as negave EXXX statuses.
|
||||||
|
*/
|
||||||
|
virtual status_t StartRecording();
|
||||||
|
|
||||||
|
/* Actual handler for camera_device_ops_t::stop_recording callback.
|
||||||
|
* NOTE: When this method is called the object is locked.
|
||||||
|
*/
|
||||||
|
virtual void StopRecording();
|
||||||
|
|
||||||
|
/* Actual handler for camera_device_ops_t::recording_enabled callback.
|
||||||
|
* NOTE: When this method is called the object is locked.
|
||||||
|
* Return:
|
||||||
|
* 0 if recording is disabled, != 0 if enabled.
|
||||||
|
*/
|
||||||
|
virtual int RecordingEnabled();
|
||||||
|
|
||||||
|
/* Actual handler for camera_device_ops_t::release_recording_frame callback.
|
||||||
|
* NOTE: When this method is called the object is locked.
|
||||||
|
*/
|
||||||
|
virtual void ReleaseRecordingFrame(const void* opaque);
|
||||||
|
|
||||||
|
/* Actual handler for camera_device_ops_t::auto_focus callback.
|
||||||
|
* NOTE: When this method is called the object is locked.
|
||||||
|
* Note that failures in this method are reported as negave EXXX statuses.
|
||||||
|
*/
|
||||||
|
virtual status_t AutoFocus();
|
||||||
|
|
||||||
|
/* Actual handler for camera_device_ops_t::cancel_auto_focus callback.
|
||||||
|
* NOTE: When this method is called the object is locked.
|
||||||
|
* Note that failures in this method are reported as negave EXXX statuses.
|
||||||
|
*/
|
||||||
|
virtual status_t CancelAutoFocus();
|
||||||
|
|
||||||
|
/* Actual handler for camera_device_ops_t::take_picture callback.
|
||||||
|
* NOTE: When this method is called the object is locked.
|
||||||
|
* Note that failures in this method are reported as negave EXXX statuses.
|
||||||
|
*/
|
||||||
|
virtual status_t TakePicture();
|
||||||
|
|
||||||
|
/* Actual handler for camera_device_ops_t::cancel_picture callback.
|
||||||
|
* NOTE: When this method is called the object is locked.
|
||||||
|
* Note that failures in this method are reported as negave EXXX statuses.
|
||||||
|
*/
|
||||||
|
virtual status_t CancelPicture();
|
||||||
|
|
||||||
|
/* Actual handler for camera_device_ops_t::set_parameters callback.
|
||||||
|
* NOTE: When this method is called the object is locked.
|
||||||
|
* Note that failures in this method are reported as negave EXXX statuses.
|
||||||
|
*/
|
||||||
|
virtual status_t SetParameters(const char* parms);
|
||||||
|
|
||||||
|
/* Actual handler for camera_device_ops_t::get_parameters callback.
|
||||||
|
* NOTE: When this method is called the object is locked.
|
||||||
|
* Return:
|
||||||
|
* Flattened parameters string. The caller will free the buffer allocated
|
||||||
|
* for the string by calling camera_device_ops_t::put_parameters callback.
|
||||||
|
*/
|
||||||
|
virtual char* GetParameters();
|
||||||
|
|
||||||
|
/* Actual handler for camera_device_ops_t::put_parameters callback.
|
||||||
|
* Called to free the string returned from camera_device_ops_t::get_parameters
|
||||||
|
* callback. There is nothing more to it: the name of the callback is just
|
||||||
|
* misleading.
|
||||||
|
* NOTE: When this method is called the object is locked.
|
||||||
|
*/
|
||||||
|
virtual void PutParameters(char* params);
|
||||||
|
|
||||||
|
/* Actual handler for camera_device_ops_t::send_command callback.
|
||||||
|
* NOTE: When this method is called the object is locked.
|
||||||
|
* Note that failures in this method are reported as negave EXXX statuses.
|
||||||
|
*/
|
||||||
|
virtual status_t SendCommand(int32_t cmd, int32_t arg1, int32_t arg2);
|
||||||
|
|
||||||
|
/* Actual handler for camera_device_ops_t::release callback.
|
||||||
|
* NOTE: When this method is called the object is locked.
|
||||||
|
*/
|
||||||
|
virtual void Release();
|
||||||
|
|
||||||
|
/* Actual handler for camera_device_ops_t::dump callback.
|
||||||
|
* NOTE: When this method is called the object is locked.
|
||||||
|
* Note that failures in this method are reported as negave EXXX statuses.
|
||||||
|
*/
|
||||||
|
virtual status_t Dump(int fd);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Preview management.
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/* Starts preview.
|
||||||
|
* Note that when this method is called preview_window_ may be NULL,
|
||||||
|
* indicating that framework has an intention to start displaying video
|
||||||
|
* frames, but didn't create the preview window yet.
|
||||||
|
* Return:
|
||||||
|
* NO_ERROR on success, or an appropriate error status on failure.
|
||||||
|
*/
|
||||||
|
virtual status_t DoStartPreview();
|
||||||
|
|
||||||
|
/* Stops preview.
|
||||||
|
* This method reverts DoStartPreview.
|
||||||
|
* Return:
|
||||||
|
* NO_ERROR on success, or an appropriate error status on failure.
|
||||||
|
*/
|
||||||
|
virtual status_t DoStopPreview();
|
||||||
|
|
||||||
|
/* Starts capturing frames
|
||||||
|
* Return:
|
||||||
|
* NO_ERROR on success, or an appropriate error status on failure.
|
||||||
|
*/
|
||||||
|
virtual status_t StartCamera();
|
||||||
|
|
||||||
|
/* Stops capturing frames.
|
||||||
|
* Return:
|
||||||
|
* NO_ERROR on success, or an appropriate error status on failure.
|
||||||
|
*/
|
||||||
|
virtual status_t StopCamera();
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private API.
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/* Cleans up camera when released. */
|
||||||
|
virtual status_t Cleanup();
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Camera API callbacks as defined by camera_device_ops structure.
|
||||||
|
* See hardware/libhardware/include/hardware/camera.h for information on
|
||||||
|
* each of these callbacks. Implemented in this class, these callbacks simply
|
||||||
|
* dispatch the call into an instance of EmulatedCamera class defined by the
|
||||||
|
* 'camera_device' parameter.
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
private:
|
||||||
|
static int set_preview_window(struct camera_device* dev,
|
||||||
|
struct preview_stream_ops* window);
|
||||||
|
|
||||||
|
static void 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);
|
||||||
|
|
||||||
|
static void enable_msg_type(struct camera_device* dev, int32_t msg_type);
|
||||||
|
|
||||||
|
static void disable_msg_type(struct camera_device* dev, int32_t msg_type);
|
||||||
|
|
||||||
|
static int msg_type_enabled(struct camera_device* dev, int32_t msg_type);
|
||||||
|
|
||||||
|
static int start_preview(struct camera_device* dev);
|
||||||
|
|
||||||
|
static void stop_preview(struct camera_device* dev);
|
||||||
|
|
||||||
|
static int preview_enabled(struct camera_device* dev);
|
||||||
|
|
||||||
|
static int store_meta_data_in_buffers(struct camera_device* dev, int enable);
|
||||||
|
|
||||||
|
static int start_recording(struct camera_device* dev);
|
||||||
|
|
||||||
|
static void stop_recording(struct camera_device* dev);
|
||||||
|
|
||||||
|
static int recording_enabled(struct camera_device* dev);
|
||||||
|
|
||||||
|
static void release_recording_frame(struct camera_device* dev,
|
||||||
|
const void* opaque);
|
||||||
|
|
||||||
|
static int auto_focus(struct camera_device* dev);
|
||||||
|
|
||||||
|
static int cancel_auto_focus(struct camera_device* dev);
|
||||||
|
|
||||||
|
static int take_picture(struct camera_device* dev);
|
||||||
|
|
||||||
|
static int cancel_picture(struct camera_device* dev);
|
||||||
|
|
||||||
|
static int set_parameters(struct camera_device* dev, const char* parms);
|
||||||
|
|
||||||
|
static char* get_parameters(struct camera_device* dev);
|
||||||
|
|
||||||
|
static void put_parameters(struct camera_device* dev, char* params);
|
||||||
|
|
||||||
|
static int send_command(struct camera_device* dev,
|
||||||
|
int32_t cmd,
|
||||||
|
int32_t arg1,
|
||||||
|
int32_t arg2);
|
||||||
|
|
||||||
|
static void release(struct camera_device* dev);
|
||||||
|
|
||||||
|
static int dump(struct camera_device* dev, int fd);
|
||||||
|
|
||||||
|
static int close(struct hw_device_t* device);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Data members
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/* Locks this instance for parameters, state, etc. change. */
|
||||||
|
Mutex object_lock_;
|
||||||
|
|
||||||
|
/* Camera parameters. */
|
||||||
|
CameraParameters parameters_;
|
||||||
|
|
||||||
|
/* Preview window. */
|
||||||
|
PreviewWindow preview_window_;
|
||||||
|
|
||||||
|
/* Callback notifier. */
|
||||||
|
CallbackNotifier callback_notifier_;
|
||||||
|
|
||||||
|
/* Zero-based ID assigned to this camera. */
|
||||||
|
int camera_id_;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/* Registered callbacks implementing camera API. */
|
||||||
|
static camera_device_ops_t device_ops_;
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Common keys
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
public:
|
||||||
|
static const char FACING_KEY[];
|
||||||
|
static const char ORIENTATION_KEY[];
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Common string values
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/* Possible values for FACING_KEY */
|
||||||
|
static const char FACING_BACK[];
|
||||||
|
static const char FACING_FRONT[];
|
||||||
|
};
|
||||||
|
|
||||||
|
}; /* namespace android */
|
||||||
|
|
||||||
|
#endif /* HW_EMULATOR_CAMERA_EMULATED_CAMERA_H */
|
||||||
70
tools/emulator/system/camera/emulated_camera_common.h
Normal file
70
tools/emulator/system/camera/emulated_camera_common.h
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HW_EMULATOR_CAMERA_EMULATED_CAMERA_COMMON_H
|
||||||
|
#define HW_EMULATOR_CAMERA_EMULATED_CAMERA_COMMON_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Contains common declarations that are used across the camera emulation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/videodev2.h>
|
||||||
|
#include <hardware/camera.h>
|
||||||
|
|
||||||
|
/* A helper class that tracks a routine execution.
|
||||||
|
* Basically, it dumps an enry message in its constructor, and an exit message
|
||||||
|
* in its destructor. Use LOGRE() macro (declared bellow) to create instances
|
||||||
|
* of this class at the beginning of the tracked routines / methods.
|
||||||
|
*/
|
||||||
|
class HWERoutineTracker {
|
||||||
|
public:
|
||||||
|
/* Constructor that prints an "entry" trace message. */
|
||||||
|
explicit HWERoutineTracker(const char* name)
|
||||||
|
: name_(name) {
|
||||||
|
LOGV("Entering %s", name_);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Destructor that prints a "leave" trace message. */
|
||||||
|
~HWERoutineTracker() {
|
||||||
|
LOGV("Leaving %s", name_);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
/* Stores the routine name. */
|
||||||
|
const char* name_;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Logs an execution of a routine / method. */
|
||||||
|
#define LOGRE() HWERoutineTracker hwertracker_##__LINE__(__FUNCTION__)
|
||||||
|
|
||||||
|
static __inline__ void Sleep(int millisec)
|
||||||
|
{
|
||||||
|
if (millisec != 0) {
|
||||||
|
timeval to;
|
||||||
|
to.tv_sec = millisec / 1000;
|
||||||
|
to.tv_usec = (millisec % 1000) * 1000;
|
||||||
|
select(0, NULL, NULL, NULL, &to);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* min / max macros
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define min(a,b) (((a) < (b)) ? (a) : (b))
|
||||||
|
#define max(a,b) (((a) > (b)) ? (a) : (b))
|
||||||
|
|
||||||
|
#endif /* HW_EMULATOR_CAMERA_EMULATED_CAMERA_COMMON_H */
|
||||||
335
tools/emulator/system/camera/emulated_camera_device.cpp
Normal file
335
tools/emulator/system/camera/emulated_camera_device.cpp
Normal file
@@ -0,0 +1,335 @@
|
|||||||
|
/*
|
||||||
|
* 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 an abstract class EmulatedCameraDevice that defines
|
||||||
|
* functionality expected from an emulated physical camera device:
|
||||||
|
* - Obtaining and setting camera parameters
|
||||||
|
* - Capturing frames
|
||||||
|
* - Streaming video
|
||||||
|
* - etc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LOG_NDEBUG 0
|
||||||
|
#define LOG_TAG "EmulatedCamera_Device"
|
||||||
|
#include <cutils/log.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include "emulated_camera_device.h"
|
||||||
|
#include "converters.h"
|
||||||
|
|
||||||
|
namespace android {
|
||||||
|
|
||||||
|
EmulatedCameraDevice::EmulatedCameraDevice(EmulatedCamera* camera_hal)
|
||||||
|
: object_lock_(),
|
||||||
|
camera_hal_(camera_hal),
|
||||||
|
current_frame_(NULL),
|
||||||
|
state_(ECDS_CONSTRUCTED)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
EmulatedCameraDevice::~EmulatedCameraDevice()
|
||||||
|
{
|
||||||
|
if (current_frame_ != NULL) {
|
||||||
|
delete[] current_frame_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Emulated camera device public API
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
status_t EmulatedCameraDevice::Initialize()
|
||||||
|
{
|
||||||
|
LOGV("%s", __FUNCTION__);
|
||||||
|
|
||||||
|
if (IsInitialized()) {
|
||||||
|
LOGW("%s: Emulated camera device is already initialized: state_ = %d",
|
||||||
|
__FUNCTION__, state_);
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Instantiate worker thread object. */
|
||||||
|
worker_thread_ = new WorkerThread(this);
|
||||||
|
if (worker_thread() == NULL) {
|
||||||
|
LOGE("%s: Unable to instantiate worker thread object", __FUNCTION__);
|
||||||
|
return ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
state_ = ECDS_INITIALIZED;
|
||||||
|
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t EmulatedCameraDevice::StartCapturing(int width,
|
||||||
|
int height,
|
||||||
|
uint32_t pix_fmt)
|
||||||
|
{
|
||||||
|
LOGV("%s", __FUNCTION__);
|
||||||
|
|
||||||
|
/* Validate pixel format, and calculate framebuffer size at the same time. */
|
||||||
|
switch (pix_fmt) {
|
||||||
|
case V4L2_PIX_FMT_YVU420:
|
||||||
|
framebuffer_size_ = (width * height * 12) / 8;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
LOGE("%s: Unknown pixel format %.4s",
|
||||||
|
__FUNCTION__, reinterpret_cast<const char*>(&pix_fmt));
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cache framebuffer info. */
|
||||||
|
frame_width_ = width;
|
||||||
|
frame_height_ = height;
|
||||||
|
pixel_format_ = pix_fmt;
|
||||||
|
total_pixels_ = width * height;
|
||||||
|
|
||||||
|
/* Allocate framebuffer. */
|
||||||
|
current_frame_ = new uint8_t[GetFrameBufferSize()];
|
||||||
|
if (current_frame_ == NULL) {
|
||||||
|
LOGE("%s: Unable to allocate framebuffer", __FUNCTION__);
|
||||||
|
return ENOMEM;
|
||||||
|
}
|
||||||
|
/* Calculate Cb/Cr panes inside the framebuffer. */
|
||||||
|
frame_Cb_ = current_frame_ + total_pixels_;
|
||||||
|
frame_Cr_ = frame_Cb_ + total_pixels_ / 4;
|
||||||
|
|
||||||
|
/* Start the camera. */
|
||||||
|
const status_t res = StartCamera();
|
||||||
|
if (res == NO_ERROR) {
|
||||||
|
LOGD("Camera device is started:\n"
|
||||||
|
" Framebuffer dimensions: %dx%d.\n"
|
||||||
|
" Pixel format: %.4s",
|
||||||
|
frame_width_, frame_height_,
|
||||||
|
reinterpret_cast<const char*>(&pixel_format_));
|
||||||
|
} else {
|
||||||
|
delete[] current_frame_;
|
||||||
|
current_frame_ = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t EmulatedCameraDevice::StopCapturing()
|
||||||
|
{
|
||||||
|
LOGV("%s", __FUNCTION__);
|
||||||
|
|
||||||
|
/* Stop the camera. */
|
||||||
|
const status_t res = StopCamera();
|
||||||
|
if (res == NO_ERROR) {
|
||||||
|
/* Release resources allocated for capturing. */
|
||||||
|
if (current_frame_ != NULL) {
|
||||||
|
delete[] current_frame_;
|
||||||
|
current_frame_ = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t EmulatedCameraDevice::GetCurrentFrame(void* buffer)
|
||||||
|
{
|
||||||
|
Mutex::Autolock locker(&object_lock_);
|
||||||
|
|
||||||
|
if (!IsCapturing() || current_frame_ == NULL) {
|
||||||
|
LOGE("%s is called on a device that is not in the capturing state",
|
||||||
|
__FUNCTION__);
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(buffer, current_frame_, GetFrameBufferSize());
|
||||||
|
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t EmulatedCameraDevice::GetCurrentPreviewFrame(void* buffer)
|
||||||
|
{
|
||||||
|
Mutex::Autolock locker(&object_lock_);
|
||||||
|
|
||||||
|
if (!IsCapturing() || current_frame_ == NULL) {
|
||||||
|
LOGE("%s is called on a device that is not in the capturing state",
|
||||||
|
__FUNCTION__);
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* In emulation the framebuffer is never RGB. */
|
||||||
|
switch (pixel_format_) {
|
||||||
|
case V4L2_PIX_FMT_YVU420:
|
||||||
|
YV12ToRGB565(current_frame_, buffer, frame_width_, frame_height_);
|
||||||
|
return NO_ERROR;
|
||||||
|
|
||||||
|
default:
|
||||||
|
LOGE("%s: Unknown pixel format %d", __FUNCTION__, pixel_format_);
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Worker thread management.
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
status_t EmulatedCameraDevice::StartWorkerThread()
|
||||||
|
{
|
||||||
|
LOGV("%s", __FUNCTION__);
|
||||||
|
|
||||||
|
if (!IsInitialized()) {
|
||||||
|
LOGE("%s: Emulated camera device is not initialized", __FUNCTION__);
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const status_t ret = worker_thread()->Start();
|
||||||
|
LOGE_IF(ret != NO_ERROR, "%s: Unable to start worker thread: %d -> %s",
|
||||||
|
__FUNCTION__, ret, strerror(ret));
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t EmulatedCameraDevice::StopWorkerThread()
|
||||||
|
{
|
||||||
|
LOGV("%s", __FUNCTION__);
|
||||||
|
|
||||||
|
if (!IsInitialized()) {
|
||||||
|
LOGE("%s: Emulated camera device is not initialized", __FUNCTION__);
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
worker_thread()->Stop();
|
||||||
|
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EmulatedCameraDevice::InWorkerThread()
|
||||||
|
{
|
||||||
|
/* This will end the thread loop, and will terminate the thread. */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Worker thread implementation.
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
status_t EmulatedCameraDevice::WorkerThread::readyToRun()
|
||||||
|
{
|
||||||
|
LOGV("Starting emulated camera device worker thread...");
|
||||||
|
|
||||||
|
LOGW_IF(thread_control_ >= 0 || control_fd_ >= 0,
|
||||||
|
"%s: Thread control FDs are opened", __FUNCTION__);
|
||||||
|
/* Create a pair of FDs that would be used to control the thread. */
|
||||||
|
int thread_fds[2];
|
||||||
|
if (pipe(thread_fds) == 0) {
|
||||||
|
thread_control_ = thread_fds[1];
|
||||||
|
control_fd_ = thread_fds[0];
|
||||||
|
LOGV("Emulated device's worker thread has been started.");
|
||||||
|
return NO_ERROR;
|
||||||
|
} else {
|
||||||
|
LOGE("%s: Unable to create thread control FDs: %d -> %s",
|
||||||
|
__FUNCTION__, errno, strerror(errno));
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t EmulatedCameraDevice::WorkerThread::Stop()
|
||||||
|
{
|
||||||
|
LOGV("Stopping emulated camera device's worker thread...");
|
||||||
|
|
||||||
|
status_t res = EINVAL;
|
||||||
|
if (thread_control_ >= 0) {
|
||||||
|
/* Send "stop" message to the thread loop. */
|
||||||
|
const ControlMessage msg = THREAD_STOP;
|
||||||
|
const int wres =
|
||||||
|
TEMP_FAILURE_RETRY(write(thread_control_, &msg, sizeof(msg)));
|
||||||
|
if (wres == sizeof(msg)) {
|
||||||
|
/* Stop the thread, and wait till it's terminated. */
|
||||||
|
res = requestExitAndWait();
|
||||||
|
if (res == NO_ERROR) {
|
||||||
|
/* Close control FDs. */
|
||||||
|
if (thread_control_ >= 0) {
|
||||||
|
close(thread_control_);
|
||||||
|
thread_control_ = -1;
|
||||||
|
}
|
||||||
|
if (control_fd_ >= 0) {
|
||||||
|
close(control_fd_);
|
||||||
|
control_fd_ = -1;
|
||||||
|
}
|
||||||
|
LOGV("Emulated camera device's worker thread has been stopped.");
|
||||||
|
} else {
|
||||||
|
LOGE("%s: requestExitAndWait failed: %d -> %s",
|
||||||
|
__FUNCTION__, res, strerror(res));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LOGE("%s: Unable to send THREAD_STOP: %d -> %s",
|
||||||
|
__FUNCTION__, errno, strerror(errno));
|
||||||
|
res = errno ? errno : EINVAL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LOGE("%s: Thread control FDs are not opened", __FUNCTION__);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
EmulatedCameraDevice::WorkerThread::SelectRes
|
||||||
|
EmulatedCameraDevice::WorkerThread::Select(int fd, int timeout)
|
||||||
|
{
|
||||||
|
fd_set fds[1];
|
||||||
|
struct timeval tv, *tvp = NULL;
|
||||||
|
|
||||||
|
const int fd_num = (fd >= 0) ? max(fd, control_fd_) + 1 :
|
||||||
|
control_fd_ + 1;
|
||||||
|
FD_ZERO(fds);
|
||||||
|
FD_SET(control_fd_, fds);
|
||||||
|
if (fd >= 0) {
|
||||||
|
FD_SET(fd, fds);
|
||||||
|
}
|
||||||
|
if (timeout) {
|
||||||
|
tv.tv_sec = timeout / 1000000;
|
||||||
|
tv.tv_usec = timeout % 1000000;
|
||||||
|
tvp = &tv;
|
||||||
|
}
|
||||||
|
int res = TEMP_FAILURE_RETRY(select(fd_num, fds, NULL, NULL, tvp));
|
||||||
|
if (res < 0) {
|
||||||
|
LOGE("%s: select returned %d and failed: %d -> %s",
|
||||||
|
__FUNCTION__, res, errno, strerror(errno));
|
||||||
|
return ERROR;
|
||||||
|
} else if (res == 0) {
|
||||||
|
/* Timeout. */
|
||||||
|
return TIMEOUT;
|
||||||
|
} else if (FD_ISSET(control_fd_, fds)) {
|
||||||
|
/* A control event. Lets read the message. */
|
||||||
|
ControlMessage msg;
|
||||||
|
res = TEMP_FAILURE_RETRY(read(control_fd_, &msg, sizeof(msg)));
|
||||||
|
if (res != sizeof(msg)) {
|
||||||
|
LOGE("%s: Unexpected message size %d, or an error %d -> %s",
|
||||||
|
__FUNCTION__, res, errno, strerror(errno));
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
/* THREAD_STOP is the only message expected here. */
|
||||||
|
if (msg == THREAD_STOP) {
|
||||||
|
LOGV("%s: THREAD_STOP message is received", __FUNCTION__);
|
||||||
|
return EXIT_THREAD;
|
||||||
|
} else {
|
||||||
|
LOGE("Unknown worker thread message %d", msg);
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Must be an FD. */
|
||||||
|
LOGW_IF(fd < 0 || !FD_ISSET(fd, fds), "%s: Undefined 'select' result",
|
||||||
|
__FUNCTION__);
|
||||||
|
return READY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}; /* namespace android */
|
||||||
434
tools/emulator/system/camera/emulated_camera_device.h
Normal file
434
tools/emulator/system/camera/emulated_camera_device.h
Normal file
@@ -0,0 +1,434 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HW_EMULATOR_CAMERA_EMULATED_CAMERA_DEVICE_H
|
||||||
|
#define HW_EMULATOR_CAMERA_EMULATED_CAMERA_DEVICE_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Contains declaration of an abstract class EmulatedCameraDevice that defines
|
||||||
|
* functionality expected from an emulated physical camera device:
|
||||||
|
* - Obtaining and setting camera device parameters
|
||||||
|
* - Capturing frames
|
||||||
|
* - Streaming video
|
||||||
|
* - etc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <utils/threads.h>
|
||||||
|
#include "emulated_camera_common.h"
|
||||||
|
|
||||||
|
namespace android {
|
||||||
|
|
||||||
|
class EmulatedCamera;
|
||||||
|
|
||||||
|
/* Encapsulates an abstract class EmulatedCameraDevice that defines functionality
|
||||||
|
* expected from an emulated physical camera device:
|
||||||
|
* - Obtaining and setting camera device parameters
|
||||||
|
* - Capturing frames
|
||||||
|
* - Streaming video
|
||||||
|
* - etc.
|
||||||
|
*/
|
||||||
|
class EmulatedCameraDevice {
|
||||||
|
public:
|
||||||
|
/* Constructs EmulatedCameraDevice instance.
|
||||||
|
* Param:
|
||||||
|
* camera_hal - Emulated camera that implements the camera HAL API, and
|
||||||
|
* manages (contains) this object.
|
||||||
|
*/
|
||||||
|
explicit EmulatedCameraDevice(EmulatedCamera* camera_hal);
|
||||||
|
|
||||||
|
/* Destructs EmulatedCameraDevice instance. */
|
||||||
|
virtual ~EmulatedCameraDevice();
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Emulated camera device abstract interface
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
public:
|
||||||
|
/* Connects to the camera device.
|
||||||
|
* This method must be called on an initialized instance of this class.
|
||||||
|
* Return:
|
||||||
|
* NO_ERROR on success, or an appropriate error status.
|
||||||
|
*/
|
||||||
|
virtual status_t Connect() = 0;
|
||||||
|
|
||||||
|
/* Disconnects from the camera device.
|
||||||
|
* Return:
|
||||||
|
* NO_ERROR on success, or an appropriate error status. If this method is
|
||||||
|
* called for already disconnected, or uninitialized instance of this class,
|
||||||
|
* a successful status must be returned from this method. If this method is
|
||||||
|
* called for an instance that is in "capturing" state, this method must
|
||||||
|
* return a failure.
|
||||||
|
*/
|
||||||
|
virtual status_t Disconnect() = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/* Starts capturing frames from the camera device.
|
||||||
|
*
|
||||||
|
* Typically, this method initializes the camera device with the settings
|
||||||
|
* requested by the framework through the camera HAL, and starts a worker
|
||||||
|
* thread that will listen to the physical device for available frames. When
|
||||||
|
* new frame becomes available, it will be cached in current_framebuffer_,
|
||||||
|
* and the containing emulated camera object will be notified via call to its
|
||||||
|
* OnNextFrameAvailable method. This method must be called on a connected
|
||||||
|
* instance of this class. If it is called on a disconnected instance, this
|
||||||
|
* method must return a failure.
|
||||||
|
* Return:
|
||||||
|
* NO_ERROR on success, or an appropriate error status.
|
||||||
|
*/
|
||||||
|
virtual status_t StartCamera() = 0;
|
||||||
|
|
||||||
|
/* Stops capturing frames from the camera device.
|
||||||
|
* Return:
|
||||||
|
* NO_ERROR on success, or an appropriate error status. If this method is
|
||||||
|
* called for an object that is not capturing frames, or is disconnected, or
|
||||||
|
* is uninitialized, a successful status must be returned from this method.
|
||||||
|
*/
|
||||||
|
virtual status_t StopCamera() = 0;
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Emulated camera device public API
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
public:
|
||||||
|
/* Initializes EmulatedCameraDevice instance.
|
||||||
|
* Derived classes should override this method in order to cache static
|
||||||
|
* properties of the physical device (list of supported pixel formats, frame
|
||||||
|
* sizes, etc.) If this method is called on an already initialized instance,
|
||||||
|
* it must return a successful status.
|
||||||
|
* Return:
|
||||||
|
* NO_ERROR on success, or an appropriate error status.
|
||||||
|
*/
|
||||||
|
virtual status_t Initialize();
|
||||||
|
|
||||||
|
/* Starts capturing frames from the camera device.
|
||||||
|
*
|
||||||
|
* Typically, this method caches desired frame parameters, and calls
|
||||||
|
* StartCamera method to start capturing video frames from the camera device.
|
||||||
|
* This method must be called on a connected instance of this class. If it is
|
||||||
|
* called on a disconnected instance, this method must return a failure.
|
||||||
|
* Return:
|
||||||
|
* NO_ERROR on success, or an appropriate error status.
|
||||||
|
*/
|
||||||
|
virtual status_t StartCapturing(int width, int height, uint32_t pix_fmt);
|
||||||
|
|
||||||
|
/* Stops capturing frames from the camera device.
|
||||||
|
*
|
||||||
|
* Typically, this method calls StopCamera method of this class, and
|
||||||
|
* uninitializes frame properties, saved in StartCapturing method of this
|
||||||
|
* class.
|
||||||
|
* This method must be called on a connected instance of this class. If it is
|
||||||
|
* called on a disconnected instance, this method must return a failure.
|
||||||
|
* Return:
|
||||||
|
* NO_ERROR on success, or an appropriate error status.
|
||||||
|
*/
|
||||||
|
virtual status_t StopCapturing();
|
||||||
|
|
||||||
|
/* Gets current fame into provided buffer.
|
||||||
|
* Typically, this method is called by the emulated camera (HAL) in response
|
||||||
|
* to a callback from the emulated camera device that gets invoked when new
|
||||||
|
* captured frame is available.
|
||||||
|
* This method must be called on an instance that is capturing frames from
|
||||||
|
* the physical device. If this method is called on an instance that is not
|
||||||
|
* capturing frames from the physical device, it must return a failure.
|
||||||
|
* Param:
|
||||||
|
* buffer - A buffer where to return the frame. Note that the buffer must be
|
||||||
|
* large enough to contain the entire frame, as defined by frame's width,
|
||||||
|
* height, and pixel format that are current for the camera device.
|
||||||
|
*/
|
||||||
|
virtual status_t GetCurrentFrame(void* buffer);
|
||||||
|
|
||||||
|
/* Gets current preview fame into provided buffer.
|
||||||
|
* Param:
|
||||||
|
* buffer - A buffer where to return the preview frame. Note that the buffer
|
||||||
|
* must be large enough to contain the entire preview frame, as defined
|
||||||
|
* by frame's width, height, and preview pixel format. Note also, that
|
||||||
|
* due to the the limitations of the camera framework in emulator, the
|
||||||
|
* preview frame is always formatted with RGB565.
|
||||||
|
*/
|
||||||
|
virtual status_t GetCurrentPreviewFrame(void* buffer);
|
||||||
|
|
||||||
|
/* Gets width of the frame obtained from the physical device. */
|
||||||
|
inline int GetFrameWidth() const
|
||||||
|
{
|
||||||
|
return frame_width_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Gets height of the frame obtained from the physical device. */
|
||||||
|
inline int GetFrameHeight() const
|
||||||
|
{
|
||||||
|
return frame_height_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Gets byte size of the current frame buffer. */
|
||||||
|
inline size_t GetFrameBufferSize() const
|
||||||
|
{
|
||||||
|
return framebuffer_size_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Gets number of pixels in the current frame buffer. */
|
||||||
|
inline int GetPixelNum() const
|
||||||
|
{
|
||||||
|
return total_pixels_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Gets pixel format of the frame that physical device streams.
|
||||||
|
* Throughout camera framework, there are three different forms of pixel
|
||||||
|
* format representation:
|
||||||
|
* - Original format, as reported by the actual camera device. Values for
|
||||||
|
* this format are declared in bionic/libc/kernel/common/linux/videodev2.h
|
||||||
|
* - String representation as defined in CameraParameters::PIXEL_FORMAT_XXX
|
||||||
|
* strings in frameworks/base/include/camera/CameraParameters.h
|
||||||
|
* - HAL_PIXEL_FORMAT_XXX format, as defined in system/core/include/system/graphics.h
|
||||||
|
* Since emulated camera device gets its data from the actual device, it gets
|
||||||
|
* pixel format in the original form. And that's the pixel format
|
||||||
|
* representation that will be returned from this method. HAL components will
|
||||||
|
* need to translate value returned from this method to the appropriate form.
|
||||||
|
* This method must be called only on connected instance of this class, since
|
||||||
|
* it's applicable only when physical device is ready to stream frames. If
|
||||||
|
* this method is called on an instance that is not connected, it must return
|
||||||
|
* a failure.
|
||||||
|
* Param:
|
||||||
|
* pix_fmt - Upon success contains the original pixel format.
|
||||||
|
* Return:
|
||||||
|
* Current framebuffer's pixel format.
|
||||||
|
*/
|
||||||
|
inline uint32_t GetOriginalPixelFormat() const
|
||||||
|
{
|
||||||
|
return pixel_format_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* State checkers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
inline bool IsInitialized() const {
|
||||||
|
/* Instance is initialized when the worker thread has been successfuly
|
||||||
|
* created (but not necessarily started). */
|
||||||
|
return worker_thread_.get() != NULL && state_ != ECDS_CONSTRUCTED;
|
||||||
|
}
|
||||||
|
inline bool IsConnected() const {
|
||||||
|
/* Instance is connected when it is initialized and its status is either
|
||||||
|
* "connected", or "capturing". */
|
||||||
|
return IsInitialized() &&
|
||||||
|
(state_ == ECDS_CONNECTED || state_ == ECDS_CAPTURING);
|
||||||
|
}
|
||||||
|
inline bool IsCapturing() const {
|
||||||
|
return IsInitialized() && state_ == ECDS_CAPTURING;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Worker thread management.
|
||||||
|
* Typicaly when emulated camera device starts capturing frames from the
|
||||||
|
* actual device, it does that in a worker thread created in StartCapturing,
|
||||||
|
* and terminated in StopCapturing. Since this is such a typical scenario,
|
||||||
|
* it makes sence to encapsulate worker thread management in the base class
|
||||||
|
* for all emulated camera devices.
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/* Starts the worker thread.
|
||||||
|
* Typically, worker thread is started from StartCamera method of this
|
||||||
|
* class.
|
||||||
|
* Return:
|
||||||
|
* NO_ERROR on success, or an appropriate error status.
|
||||||
|
*/
|
||||||
|
virtual status_t StartWorkerThread();
|
||||||
|
|
||||||
|
/* Stops the worker thread.
|
||||||
|
* Note that this method will always wait for the worker thread to terminate.
|
||||||
|
* Return:
|
||||||
|
* NO_ERROR on success, or an appropriate error status.
|
||||||
|
*/
|
||||||
|
virtual status_t StopWorkerThread();
|
||||||
|
|
||||||
|
/* Implementation of the worker thread routine.
|
||||||
|
* In the default implementation of the worker thread routine we simply
|
||||||
|
* return 'false' forcing the thread loop to exit, and the thread to
|
||||||
|
* terminate. Derived class should override that method to provide there the
|
||||||
|
* actual frame capturing functionality.
|
||||||
|
* Return:
|
||||||
|
* true To continue thread loop (this method will be called again), or false
|
||||||
|
* to exit the thread loop and to terminate the thread.
|
||||||
|
*/
|
||||||
|
virtual bool InWorkerThread();
|
||||||
|
|
||||||
|
/* Encapsulates a worker thread used by the emulated camera device.
|
||||||
|
*/
|
||||||
|
friend class WorkerThread;
|
||||||
|
class WorkerThread : public Thread {
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public API
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
public:
|
||||||
|
inline explicit WorkerThread(EmulatedCameraDevice* camera_dev)
|
||||||
|
: Thread(true), // Callbacks may involve Java calls.
|
||||||
|
camera_dev_(camera_dev),
|
||||||
|
thread_control_(-1),
|
||||||
|
control_fd_(-1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ~WorkerThread()
|
||||||
|
{
|
||||||
|
LOGW_IF(thread_control_ >= 0 || control_fd_ >= 0,
|
||||||
|
"%s: Control FDs are opened in the destructor",
|
||||||
|
__FUNCTION__);
|
||||||
|
if (thread_control_ >= 0) {
|
||||||
|
close(thread_control_);
|
||||||
|
}
|
||||||
|
if (control_fd_ >= 0) {
|
||||||
|
close(control_fd_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Starts the thread */
|
||||||
|
inline status_t Start()
|
||||||
|
{
|
||||||
|
return run(NULL, ANDROID_PRIORITY_URGENT_DISPLAY, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Overriden base class method.
|
||||||
|
* It is overriden in order to provide one-time initialization just
|
||||||
|
* prior to starting the thread routine.
|
||||||
|
*/
|
||||||
|
status_t readyToRun();
|
||||||
|
|
||||||
|
/* Stops the thread. */
|
||||||
|
status_t Stop();
|
||||||
|
|
||||||
|
/* Values returned from the Select method of this class. */
|
||||||
|
enum SelectRes {
|
||||||
|
/* A timeout has occurred. */
|
||||||
|
TIMEOUT,
|
||||||
|
/* Data are available for read on the provided FD. */
|
||||||
|
READY,
|
||||||
|
/* Thread exit request has been received. */
|
||||||
|
EXIT_THREAD,
|
||||||
|
/* An error has occurred. */
|
||||||
|
ERROR
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Select on an FD event, keeping in mind thread exit message.
|
||||||
|
* Param:
|
||||||
|
* fd - File descriptor on which to wait for an event. This
|
||||||
|
* parameter may be negative. If it is negative this method will
|
||||||
|
* only wait on a control message to the thread.
|
||||||
|
* timeout - Timeout in microseconds. 0 indicates no timeout (wait
|
||||||
|
* forever).
|
||||||
|
* Return:
|
||||||
|
* See SelectRes enum comments.
|
||||||
|
*/
|
||||||
|
SelectRes Select(int fd, int timeout);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private API
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
private:
|
||||||
|
/* Implements abstract method of the base Thread class. */
|
||||||
|
inline bool threadLoop()
|
||||||
|
{
|
||||||
|
/* Simply dispatch the call to the containing camera device. */
|
||||||
|
return camera_dev_->InWorkerThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Containing camera device object. */
|
||||||
|
EmulatedCameraDevice* camera_dev_;
|
||||||
|
|
||||||
|
/* FD that is used to send control messages into the thread. */
|
||||||
|
int thread_control_;
|
||||||
|
|
||||||
|
/* FD that thread uses to receive control messages. */
|
||||||
|
int control_fd_;
|
||||||
|
|
||||||
|
/* Enumerates control messages that can be sent into the thread. */
|
||||||
|
enum ControlMessage {
|
||||||
|
/* Stop the thread. */
|
||||||
|
THREAD_STOP
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Worker thread accessor. */
|
||||||
|
inline WorkerThread* worker_thread() const
|
||||||
|
{
|
||||||
|
return worker_thread_.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Data members
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/* Locks this instance for parameters, state, etc. change. */
|
||||||
|
Mutex object_lock_;
|
||||||
|
|
||||||
|
/* Worker thread that is used in frame capturing. */
|
||||||
|
sp<WorkerThread> worker_thread_;
|
||||||
|
|
||||||
|
/* Emulated camera object containing this instance. */
|
||||||
|
EmulatedCamera* camera_hal_;
|
||||||
|
|
||||||
|
/* Framebuffer containing the current frame. */
|
||||||
|
uint8_t* current_frame_;
|
||||||
|
|
||||||
|
/* Cb panel inside the framebuffer. */
|
||||||
|
uint8_t* frame_Cb_;
|
||||||
|
|
||||||
|
/* Cr panel inside the framebuffer. */
|
||||||
|
uint8_t* frame_Cr_;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Framebuffer properties.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Byte size of the framebuffer. */
|
||||||
|
size_t framebuffer_size_;
|
||||||
|
|
||||||
|
/* Original pixel format (one of the V4L2_PIX_FMT_XXX values, as defined in
|
||||||
|
* bionic/libc/kernel/common/linux/videodev2.h */
|
||||||
|
uint32_t pixel_format_;
|
||||||
|
|
||||||
|
/* Frame width */
|
||||||
|
int frame_width_;
|
||||||
|
|
||||||
|
/* Frame height */
|
||||||
|
int frame_height_;
|
||||||
|
|
||||||
|
/* Total number of pixels */
|
||||||
|
int total_pixels_;
|
||||||
|
|
||||||
|
/* Defines possible states of the emulated camera device object.
|
||||||
|
*/
|
||||||
|
enum EmulatedCameraDeviceState {
|
||||||
|
/* Object has been constructed. */
|
||||||
|
ECDS_CONSTRUCTED,
|
||||||
|
/* Object has been initialized. */
|
||||||
|
ECDS_INITIALIZED,
|
||||||
|
/* Object has been connected to the physical device. */
|
||||||
|
ECDS_CONNECTED,
|
||||||
|
/* Frames are being captured. */
|
||||||
|
ECDS_CAPTURING,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Object state. */
|
||||||
|
EmulatedCameraDeviceState state_;
|
||||||
|
};
|
||||||
|
|
||||||
|
}; /* namespace android */
|
||||||
|
|
||||||
|
#endif /* HW_EMULATOR_CAMERA_EMULATED_CAMERA_DEVICE_H */
|
||||||
201
tools/emulator/system/camera/emulated_camera_factory.cpp
Normal file
201
tools/emulator/system/camera/emulated_camera_factory.cpp
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
/*
|
||||||
|
* 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 EmulatedCameraFactory that manages cameras
|
||||||
|
* available for emulation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LOG_NDEBUG 0
|
||||||
|
#define LOG_TAG "EmulatedCamera_Factory"
|
||||||
|
#include <cutils/log.h>
|
||||||
|
#include "emulated_fake_camera.h"
|
||||||
|
#include "emulated_camera_factory.h"
|
||||||
|
|
||||||
|
extern camera_module_t HAL_MODULE_INFO_SYM;
|
||||||
|
|
||||||
|
/* A global instance of EmulatedCameraFactory is statically instantiated and
|
||||||
|
* initialized when camera emulation HAL is loaded.
|
||||||
|
*/
|
||||||
|
android::EmulatedCameraFactory _emulated_camera_factory;
|
||||||
|
|
||||||
|
namespace android {
|
||||||
|
|
||||||
|
EmulatedCameraFactory::EmulatedCameraFactory()
|
||||||
|
: emulated_cameras_(NULL),
|
||||||
|
emulated_camera_num_(0),
|
||||||
|
fake_camera_id_(-1),
|
||||||
|
constructed_ok_(false)
|
||||||
|
|
||||||
|
{
|
||||||
|
/* Obtain number of 'qemud' cameras from the emulator. */
|
||||||
|
const int qemud_num = GetQemudCameraNumber();
|
||||||
|
if (qemud_num < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LOGI("Emulating %d QEMUD cameras.", qemud_num);
|
||||||
|
|
||||||
|
/* ID fake camera with the number of 'qemud' cameras. */
|
||||||
|
fake_camera_id_ = qemud_num;
|
||||||
|
LOGI("Fake camera ID is %d", fake_camera_id_);
|
||||||
|
|
||||||
|
emulated_camera_num_ = qemud_num + 1; // Including the 'fake' camera.
|
||||||
|
LOGI("%d cameras are being emulated", emulated_camera_num_);
|
||||||
|
|
||||||
|
/* Allocate the array for emulated camera instances. */
|
||||||
|
emulated_cameras_ = new EmulatedCamera*[emulated_camera_num_];
|
||||||
|
if (emulated_cameras_ == NULL) {
|
||||||
|
LOGE("%s: Unable to allocate emulated camera array for %d entries",
|
||||||
|
__FUNCTION__, emulated_camera_num_);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Setup the 'qemud' cameras. */
|
||||||
|
if (!CreateQemudCameras(qemud_num)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create, and initialize the fake camera */
|
||||||
|
emulated_cameras_[fake_camera_id_] =
|
||||||
|
new EmulatedFakeCamera(fake_camera_id_, &HAL_MODULE_INFO_SYM.common);
|
||||||
|
if (emulated_cameras_[fake_camera_id_] == NULL) {
|
||||||
|
LOGE("%s: Unable to instantiate fake camera class", __FUNCTION__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (emulated_cameras_[fake_camera_id_]->Initialize() != NO_ERROR) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
constructed_ok_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
EmulatedCameraFactory::~EmulatedCameraFactory()
|
||||||
|
{
|
||||||
|
if (emulated_cameras_ != NULL) {
|
||||||
|
for (int n = 0; n < emulated_camera_num_; n++) {
|
||||||
|
if (emulated_cameras_[n] != NULL) {
|
||||||
|
delete emulated_cameras_[n];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete[] emulated_cameras_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Camera HAL API handlers.
|
||||||
|
*
|
||||||
|
* Each handler simply verifies existence of an appropriate EmulatedCamera
|
||||||
|
* instance, and dispatches the call to that instance.
|
||||||
|
*
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
int EmulatedCameraFactory::CameraDeviceOpen(int camera_id, hw_device_t** device)
|
||||||
|
{
|
||||||
|
*device = NULL;
|
||||||
|
|
||||||
|
if (!constructed_ok()) {
|
||||||
|
LOGE("%s: EmulatedCameraFactory has failed to initialize", __FUNCTION__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (camera_id >= emulated_camera_num()) {
|
||||||
|
LOGE("%s: Camera id %d is out of bounds (%d)",
|
||||||
|
__FUNCTION__, camera_id, emulated_camera_num());
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return emulated_cameras_[camera_id]->Connect(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
int EmulatedCameraFactory::GetCameraInfo(int camera_id, struct camera_info* info)
|
||||||
|
{
|
||||||
|
if (!constructed_ok()) {
|
||||||
|
LOGE("%s: EmulatedCameraFactory has failed to initialize", __FUNCTION__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (camera_id >= emulated_camera_num()) {
|
||||||
|
LOGE("%s: Camera id %d is out of bounds (%d)",
|
||||||
|
__FUNCTION__, camera_id, emulated_camera_num());
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return emulated_cameras_[camera_id]->GetCameraInfo(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Camera HAL API callbacks.
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
int EmulatedCameraFactory::device_open(const hw_module_t* module,
|
||||||
|
const char* name,
|
||||||
|
hw_device_t** device)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Simply verify the parameters, and dispatch the call inside the
|
||||||
|
* EmulatedCameraFactory instance.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (module != &HAL_MODULE_INFO_SYM.common) {
|
||||||
|
LOGE("%s: Invalid module %p expected %p",
|
||||||
|
__FUNCTION__, module, &HAL_MODULE_INFO_SYM.common);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
if (name == NULL) {
|
||||||
|
LOGE("%s: NULL name is not expected here", __FUNCTION__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _emulated_camera_factory.CameraDeviceOpen(atoi(name), device);
|
||||||
|
}
|
||||||
|
|
||||||
|
int EmulatedCameraFactory::get_number_of_cameras(void)
|
||||||
|
{
|
||||||
|
return _emulated_camera_factory.emulated_camera_num();
|
||||||
|
}
|
||||||
|
|
||||||
|
int EmulatedCameraFactory::get_camera_info(int camera_id,
|
||||||
|
struct camera_info* info)
|
||||||
|
{
|
||||||
|
return _emulated_camera_factory.GetCameraInfo(camera_id, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************************
|
||||||
|
* Internal API
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
int EmulatedCameraFactory::GetQemudCameraNumber()
|
||||||
|
{
|
||||||
|
// TODO: Implement!
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EmulatedCameraFactory::CreateQemudCameras(int num)
|
||||||
|
{
|
||||||
|
// TODO: Implement!
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************************
|
||||||
|
* Initializer for the static member structure.
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
/* Entry point for camera HAL API. */
|
||||||
|
struct hw_module_methods_t EmulatedCameraFactory::camera_module_methods_ = {
|
||||||
|
open: EmulatedCameraFactory::device_open
|
||||||
|
};
|
||||||
|
|
||||||
|
}; /* namespace android */
|
||||||
159
tools/emulator/system/camera/emulated_camera_factory.h
Normal file
159
tools/emulator/system/camera/emulated_camera_factory.h
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HW_EMULATOR_CAMERA_EMULATED_CAMERA_FACTORY_H
|
||||||
|
#define HW_EMULATOR_CAMERA_EMULATED_CAMERA_FACTORY_H
|
||||||
|
|
||||||
|
#include "emulated_camera.h"
|
||||||
|
|
||||||
|
namespace android {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Contains declaration of a class EmulatedCameraFactory that manages cameras
|
||||||
|
* available for the emulation. A global instance of this class is statically
|
||||||
|
* instantiated and initialized when camera emulation HAL is loaded.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Class EmulatedCameraFactoryManages cameras available for the emulation.
|
||||||
|
*
|
||||||
|
* When the global static instance of this class is created on the module load,
|
||||||
|
* it enumerates cameras available for the emulation by connecting to the
|
||||||
|
* emulator's 'camera' service. For every camera found out there it creates an
|
||||||
|
* instance of an appropriate class, and stores it an in array of emulated
|
||||||
|
* cameras. In addition to the cameras reported by the emulator, a fake camera
|
||||||
|
* emulator is always created, so there is always at least one camera that is
|
||||||
|
* available.
|
||||||
|
*
|
||||||
|
* Instance of this class is also used as the entry point for the camera HAL API,
|
||||||
|
* including:
|
||||||
|
* - hw_module_methods_t::open entry point
|
||||||
|
* - camera_module_t::get_number_of_cameras entry point
|
||||||
|
* - camera_module_t::get_camera_info entry point
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class EmulatedCameraFactory {
|
||||||
|
public:
|
||||||
|
/* Constructs EmulatedCameraFactory instance.
|
||||||
|
* In this constructor the factory will create and initialize a list of
|
||||||
|
* emulated cameras. All errors that occur on this constructor are reported
|
||||||
|
* via constructed_ok_ data member of this class.
|
||||||
|
*/
|
||||||
|
EmulatedCameraFactory();
|
||||||
|
|
||||||
|
/* Destructs EmulatedCameraFactory instance. */
|
||||||
|
~EmulatedCameraFactory();
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Camera HAL API handlers.
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
public:
|
||||||
|
/* Opens (connects to) a camera device.
|
||||||
|
* This method is called in response to hw_module_methods_t::open callback.
|
||||||
|
*/
|
||||||
|
int CameraDeviceOpen(int camera_id, hw_device_t** device);
|
||||||
|
|
||||||
|
/* Gets emulated camera information.
|
||||||
|
* This method is called in response to camera_module_t::get_camera_info callback.
|
||||||
|
*/
|
||||||
|
int GetCameraInfo(int camera_id, struct camera_info *info);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Camera HAL API callbacks.
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
public:
|
||||||
|
/* camera_module_t::get_number_of_cameras callback entry point. */
|
||||||
|
static int get_number_of_cameras(void);
|
||||||
|
|
||||||
|
/* camera_module_t::get_camera_info callback entry point. */
|
||||||
|
static int get_camera_info(int camera_id, struct camera_info *info);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/* hw_module_methods_t::open callback entry point. */
|
||||||
|
static int device_open(const hw_module_t* module,
|
||||||
|
const char* name,
|
||||||
|
hw_device_t** device);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public API.
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
public:
|
||||||
|
/* Gets number of emulated cameras.
|
||||||
|
*/
|
||||||
|
int emulated_camera_num() const {
|
||||||
|
return emulated_camera_num_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Checks whether or not the constructor has succeeded.
|
||||||
|
*/
|
||||||
|
bool constructed_ok() const {
|
||||||
|
return constructed_ok_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private API
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
private:
|
||||||
|
/* Gets number of cameras that are available via 'camera' service in the
|
||||||
|
* emulator.
|
||||||
|
* Return:
|
||||||
|
* Number of 'qemud' cameras reported by the 'camera' service, or -1 on
|
||||||
|
* failure.
|
||||||
|
*/
|
||||||
|
int GetQemudCameraNumber();
|
||||||
|
|
||||||
|
/* Populates emulated cameras array with cameras that are available via
|
||||||
|
* 'camera' service in the emulator. For each such camera and instance of
|
||||||
|
* the EmulatedCameraQemud will be created and added to the emulated_cameras_
|
||||||
|
* array.
|
||||||
|
* Param:
|
||||||
|
* num - Number of cameras returned by GetQemudCameraNumber method.
|
||||||
|
* Return:
|
||||||
|
* true on success, or false on failure.
|
||||||
|
*/
|
||||||
|
bool CreateQemudCameras(int num);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Data members.
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
private:
|
||||||
|
/* Array of cameras available for the emulation. */
|
||||||
|
EmulatedCamera** emulated_cameras_;
|
||||||
|
|
||||||
|
/* Number of emulated cameras (including the fake one). */
|
||||||
|
int emulated_camera_num_;
|
||||||
|
|
||||||
|
/* Fake camera ID. */
|
||||||
|
int fake_camera_id_;
|
||||||
|
|
||||||
|
/* Flags whether or not constructor has succeeded. */
|
||||||
|
bool constructed_ok_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/* Contains device open entry point, as required by HAL API. */
|
||||||
|
static struct hw_module_methods_t camera_module_methods_;
|
||||||
|
};
|
||||||
|
|
||||||
|
}; /* namespace android */
|
||||||
|
|
||||||
|
/* References the global EmulatedCameraFactory instance. */
|
||||||
|
extern android::EmulatedCameraFactory _emulated_camera_factory;
|
||||||
|
|
||||||
|
#endif /* HW_EMULATOR_CAMERA_EMULATED_CAMERA_FACTORY_H */
|
||||||
45
tools/emulator/system/camera/emulated_camera_hal.cpp
Normal file
45
tools/emulator/system/camera/emulated_camera_hal.cpp
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* 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 the camera HAL layer in the system running
|
||||||
|
* under the emulator.
|
||||||
|
*
|
||||||
|
* This file contains only required HAL header, which directs all the API calls
|
||||||
|
* to the EmulatedCameraFactory class implementation, wich is responsible for
|
||||||
|
* managing emulated cameras.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "emulated_camera_factory.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Required HAL header.
|
||||||
|
*/
|
||||||
|
camera_module_t HAL_MODULE_INFO_SYM = {
|
||||||
|
common: {
|
||||||
|
tag: HARDWARE_MODULE_TAG,
|
||||||
|
version_major: 1,
|
||||||
|
version_minor: 0,
|
||||||
|
id: CAMERA_HARDWARE_MODULE_ID,
|
||||||
|
name: "Emulated Camera Module",
|
||||||
|
author: "The Android Open Source Project",
|
||||||
|
methods: &android::EmulatedCameraFactory::camera_module_methods_,
|
||||||
|
dso: NULL,
|
||||||
|
reserved: {0},
|
||||||
|
},
|
||||||
|
get_number_of_cameras: android::EmulatedCameraFactory::get_number_of_cameras,
|
||||||
|
get_camera_info: android::EmulatedCameraFactory::get_camera_info,
|
||||||
|
};
|
||||||
81
tools/emulator/system/camera/emulated_fake_camera.cpp
Normal file
81
tools/emulator/system/camera/emulated_fake_camera.cpp
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* 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 EmulatedFakeCamera that encapsulates
|
||||||
|
* functionality of a fake camera.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LOG_NDEBUG 0
|
||||||
|
#define LOG_TAG "EmulatedCamera_FakeCamera"
|
||||||
|
#include <cutils/log.h>
|
||||||
|
#include "emulated_fake_camera.h"
|
||||||
|
|
||||||
|
namespace android {
|
||||||
|
|
||||||
|
EmulatedFakeCamera::EmulatedFakeCamera(int cameraId, struct hw_module_t* module)
|
||||||
|
: EmulatedCamera(cameraId, module),
|
||||||
|
fake_camera_dev_(this)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
EmulatedFakeCamera::~EmulatedFakeCamera()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public API overrides
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
status_t EmulatedFakeCamera::Initialize()
|
||||||
|
{
|
||||||
|
LOGV("%s", __FUNCTION__);
|
||||||
|
|
||||||
|
status_t res = fake_camera_dev_.Initialize();
|
||||||
|
if (res != NO_ERROR) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = EmulatedCamera::Initialize();
|
||||||
|
if (res != NO_ERROR) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parameters provided by the camera device.
|
||||||
|
*/
|
||||||
|
|
||||||
|
parameters_.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES, "640x480");
|
||||||
|
parameters_.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES, "640x480");
|
||||||
|
parameters_.set(CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS,
|
||||||
|
CameraParameters::PIXEL_FORMAT_YUV420P);
|
||||||
|
parameters_.set(CameraParameters::KEY_VIDEO_FRAME_FORMAT,
|
||||||
|
CameraParameters::PIXEL_FORMAT_YUV420P);
|
||||||
|
|
||||||
|
parameters_.setPreviewFrameRate(25);
|
||||||
|
parameters_.setPreviewSize(640, 480);
|
||||||
|
parameters_.setPictureSize(640, 480);
|
||||||
|
parameters_.setPictureFormat(CameraParameters::PIXEL_FORMAT_YUV420P);
|
||||||
|
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
EmulatedCameraDevice* EmulatedFakeCamera::GetCameraDevice()
|
||||||
|
{
|
||||||
|
return &fake_camera_dev_;
|
||||||
|
}
|
||||||
|
|
||||||
|
}; /* namespace android */
|
||||||
75
tools/emulator/system/camera/emulated_fake_camera.h
Normal file
75
tools/emulator/system/camera/emulated_fake_camera.h
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HW_EMULATOR_CAMERA_EMULATED_FAKE_CAMERA_H
|
||||||
|
#define HW_EMULATOR_CAMERA_EMULATED_FAKE_CAMERA_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Contains declaration of a class EmulatedFakeCamera that encapsulates
|
||||||
|
* functionality of a fake camera. This class is nothing more than a placeholder
|
||||||
|
* for EmulatedFakeCameraDevice instance.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "emulated_camera.h"
|
||||||
|
#include "emulated_fake_camera_device.h"
|
||||||
|
|
||||||
|
namespace android {
|
||||||
|
|
||||||
|
/* Encapsulates functionality of a fake camera.
|
||||||
|
* This class is nothing more than a placeholder for EmulatedFakeCameraDevice
|
||||||
|
* instance that emulates a fake camera device.
|
||||||
|
*/
|
||||||
|
class EmulatedFakeCamera : public EmulatedCamera {
|
||||||
|
public:
|
||||||
|
/* Constructs EmulatedFakeCamera instance. */
|
||||||
|
EmulatedFakeCamera(int cameraId, struct hw_module_t* module);
|
||||||
|
|
||||||
|
/* Destructs EmulatedFakeCamera instance. */
|
||||||
|
~EmulatedFakeCamera();
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* EmulatedCamera virtual overrides.
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
public:
|
||||||
|
/* Initializes EmulatedFakeCamera instance.
|
||||||
|
* The contained EmulatedFakeCameraDevice will be initialized in this method.
|
||||||
|
* Return:
|
||||||
|
* NO_ERROR on success, or an appropriate error statsu on failure.
|
||||||
|
*/
|
||||||
|
status_t Initialize();
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* EmulatedCamera abstract API implementation.
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/* Gets emulated camera device ised by this instance of the emulated camera.
|
||||||
|
*/
|
||||||
|
EmulatedCameraDevice* GetCameraDevice();
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Data memebers.
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/* Contained fake camera device object. */
|
||||||
|
EmulatedFakeCameraDevice fake_camera_dev_;
|
||||||
|
};
|
||||||
|
|
||||||
|
}; /* namespace android */
|
||||||
|
|
||||||
|
#endif /* HW_EMULATOR_CAMERA_EMULATED_FAKE_CAMERA_H */
|
||||||
260
tools/emulator/system/camera/emulated_fake_camera_device.cpp
Normal file
260
tools/emulator/system/camera/emulated_fake_camera_device.cpp
Normal file
@@ -0,0 +1,260 @@
|
|||||||
|
/*
|
||||||
|
* 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 EmulatedFakeCameraDevice that encapsulates
|
||||||
|
* fake camera device.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LOG_NDEBUG 0
|
||||||
|
#define LOG_TAG "EmulatedCamera_FakeDevice"
|
||||||
|
#include <cutils/log.h>
|
||||||
|
#include "emulated_fake_camera.h"
|
||||||
|
#include "emulated_fake_camera_device.h"
|
||||||
|
|
||||||
|
namespace android {
|
||||||
|
|
||||||
|
EmulatedFakeCameraDevice::EmulatedFakeCameraDevice(EmulatedFakeCamera* camera_hal)
|
||||||
|
: EmulatedCameraDevice(camera_hal),
|
||||||
|
last_redrawn_(0),
|
||||||
|
black_YCbCr_(0),
|
||||||
|
white_YCbCr_(0xffff),
|
||||||
|
red_YCbCr_(kRed),
|
||||||
|
green_YCbCr_(kGreen),
|
||||||
|
blue_YCbCr_(kBlue),
|
||||||
|
check_x_(0),
|
||||||
|
check_y_(0),
|
||||||
|
counter_(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
EmulatedFakeCameraDevice::~EmulatedFakeCameraDevice()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Emulated camera device abstract interface implementation.
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
status_t EmulatedFakeCameraDevice::Connect()
|
||||||
|
{
|
||||||
|
LOGV("%s", __FUNCTION__);
|
||||||
|
|
||||||
|
Mutex::Autolock locker(&object_lock_);
|
||||||
|
if (!IsInitialized()) {
|
||||||
|
LOGE("%s: Fake camera device is not initialized.", __FUNCTION__);
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
if (IsConnected()) {
|
||||||
|
LOGW("%s: Fake camera device is already connected.", __FUNCTION__);
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
state_ = ECDS_CONNECTED;
|
||||||
|
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t EmulatedFakeCameraDevice::Disconnect()
|
||||||
|
{
|
||||||
|
LOGV("%s", __FUNCTION__);
|
||||||
|
|
||||||
|
Mutex::Autolock locker(&object_lock_);
|
||||||
|
if (!IsConnected()) {
|
||||||
|
LOGW("%s: Fake camera device is already disconnected.", __FUNCTION__);
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
if (IsCapturing()) {
|
||||||
|
LOGE("%s: Cannot disconnect while in the capturing state.", __FUNCTION__);
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
state_ = ECDS_INITIALIZED;
|
||||||
|
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t EmulatedFakeCameraDevice::StartCamera()
|
||||||
|
{
|
||||||
|
LOGV("%s", __FUNCTION__);
|
||||||
|
|
||||||
|
Mutex::Autolock locker(&object_lock_);
|
||||||
|
if (!IsConnected()) {
|
||||||
|
LOGE("%s: Fake camera device is not connected.", __FUNCTION__);
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
if (IsCapturing()) {
|
||||||
|
LOGW("%s: Fake camera device is already capturing.", __FUNCTION__);
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Used in calculating Cb/Cr position when drawing the square. */
|
||||||
|
half_width_ = frame_width_ / 2;
|
||||||
|
|
||||||
|
/* Just start the worker thread: there is no real device to deal with. */
|
||||||
|
const status_t ret = StartWorkerThread();
|
||||||
|
if (ret == NO_ERROR) {
|
||||||
|
state_ = ECDS_CAPTURING;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t EmulatedFakeCameraDevice::StopCamera()
|
||||||
|
{
|
||||||
|
LOGV("%s", __FUNCTION__);
|
||||||
|
|
||||||
|
Mutex::Autolock locker(&object_lock_);
|
||||||
|
if (!IsCapturing()) {
|
||||||
|
LOGW("%s: Fake camera device is not capturing.", __FUNCTION__);
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Just stop the worker thread: there is no real device to deal with. */
|
||||||
|
const status_t ret = StopWorkerThread();
|
||||||
|
if (ret == NO_ERROR) {
|
||||||
|
state_ = ECDS_CONNECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Worker thread management overrides.
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
bool EmulatedFakeCameraDevice::InWorkerThread()
|
||||||
|
{
|
||||||
|
/* Wait till FPS timeout expires, or thread exit message is received. */
|
||||||
|
WorkerThread::SelectRes res =
|
||||||
|
worker_thread()->Select(-1, 1000000 / emulated_fps_);
|
||||||
|
if (res == WorkerThread::EXIT_THREAD) {
|
||||||
|
LOGV("%s: Worker thread has been terminated.", __FUNCTION__);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Lets see if we need to generate a new frame. */
|
||||||
|
timeval cur_time;
|
||||||
|
gettimeofday(&cur_time, NULL);
|
||||||
|
const uint64_t cur_mks = cur_time.tv_sec * 1000000LL + cur_time.tv_usec;
|
||||||
|
if ((cur_mks - last_redrawn_) >= redraw_after_) {
|
||||||
|
/*
|
||||||
|
* Time to generate a new frame.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Draw the checker board. */
|
||||||
|
DrawCheckerboard();
|
||||||
|
|
||||||
|
/* Run the square. */
|
||||||
|
int x = ((counter_ * 3) & 255);
|
||||||
|
if(x > 128) x = 255 - x;
|
||||||
|
int y = ((counter_ * 5) & 255);
|
||||||
|
if(y > 128) y = 255 - y;
|
||||||
|
const int size = frame_width_ / 10;
|
||||||
|
DrawSquare(x * size / 32, y * size / 32, (size * 5) >> 1,
|
||||||
|
(counter_ & 0x100) ? &red_YCbCr_ : &green_YCbCr_);
|
||||||
|
counter_++;
|
||||||
|
last_redrawn_ = cur_mks;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Notify the camera HAL about new frame. */
|
||||||
|
camera_hal_->OnNextFrameAvailable(current_frame_,
|
||||||
|
systemTime(SYSTEM_TIME_MONOTONIC), this);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Fake camera device private API
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
void EmulatedFakeCameraDevice::DrawCheckerboard()
|
||||||
|
{
|
||||||
|
const int size = frame_width_ / 10;
|
||||||
|
bool black = true;
|
||||||
|
|
||||||
|
if((check_x_ / size) & 1)
|
||||||
|
black = false;
|
||||||
|
if((check_y_ / size) & 1)
|
||||||
|
black = !black;
|
||||||
|
|
||||||
|
int county = check_y_ % size;
|
||||||
|
int checkxremainder = check_x_ % size;
|
||||||
|
uint8_t* Y = current_frame_;
|
||||||
|
uint8_t* Cb_pos = frame_Cb_;
|
||||||
|
uint8_t* Cr_pos = frame_Cr_;
|
||||||
|
uint8_t* Cb = Cb_pos;
|
||||||
|
uint8_t* Cr = Cr_pos;
|
||||||
|
|
||||||
|
for(int y = 0; y < frame_height_; y++) {
|
||||||
|
int countx = checkxremainder;
|
||||||
|
bool current = black;
|
||||||
|
for(int x = 0; x < frame_width_; x += 2) {
|
||||||
|
if (current) {
|
||||||
|
black_YCbCr_.get(Y, Cb, Cr);
|
||||||
|
} else {
|
||||||
|
white_YCbCr_.get(Y, Cb, Cr);
|
||||||
|
}
|
||||||
|
Y[1] = *Y;
|
||||||
|
Y += 2; Cb++; Cr++;
|
||||||
|
countx += 2;
|
||||||
|
if(countx >= size) {
|
||||||
|
countx = 0;
|
||||||
|
current = !current;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (y & 0x1) {
|
||||||
|
Cb_pos = Cb;
|
||||||
|
Cr_pos = Cr;
|
||||||
|
} else {
|
||||||
|
Cb = Cb_pos;
|
||||||
|
Cr = Cr_pos;
|
||||||
|
}
|
||||||
|
if(county++ >= size) {
|
||||||
|
county = 0;
|
||||||
|
black = !black;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
check_x_ += 3;
|
||||||
|
check_y_++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmulatedFakeCameraDevice::DrawSquare(int x,
|
||||||
|
int y,
|
||||||
|
int size,
|
||||||
|
const YCbCrPixel* color)
|
||||||
|
{
|
||||||
|
const int half_x = x / 2;
|
||||||
|
const int square_xstop = min(frame_width_, x+size);
|
||||||
|
const int square_ystop = min(frame_height_, y+size);
|
||||||
|
uint8_t* Y_pos = current_frame_ + y * frame_width_ + x;
|
||||||
|
|
||||||
|
// Draw the square.
|
||||||
|
for (; y < square_ystop; y++) {
|
||||||
|
const int iCbCr = (y / 2) * half_width_ + half_x;
|
||||||
|
uint8_t* sqCb = frame_Cb_ + iCbCr;
|
||||||
|
uint8_t* sqCr = frame_Cr_ + iCbCr;
|
||||||
|
uint8_t* sqY = Y_pos;
|
||||||
|
for (int i = x; i < square_xstop; i += 2) {
|
||||||
|
color->get(sqY, sqCb, sqCr);
|
||||||
|
sqY[1] = *sqY;
|
||||||
|
sqY += 2; sqCb++; sqCr++;
|
||||||
|
}
|
||||||
|
Y_pos += frame_width_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}; /* namespace android */
|
||||||
146
tools/emulator/system/camera/emulated_fake_camera_device.h
Normal file
146
tools/emulator/system/camera/emulated_fake_camera_device.h
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HW_EMULATOR_CAMERA_EMULATED_FAKE_CAMERA_DEVICE_H
|
||||||
|
#define HW_EMULATOR_CAMERA_EMULATED_FAKE_CAMERA_DEVICE_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Contains declaration of a class EmulatedFakeCameraDevice that encapsulates
|
||||||
|
* a fake camera device.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "converters.h"
|
||||||
|
#include "emulated_camera_device.h"
|
||||||
|
|
||||||
|
namespace android {
|
||||||
|
|
||||||
|
class EmulatedFakeCamera;
|
||||||
|
|
||||||
|
/* Encapsulates a fake camera device.
|
||||||
|
* Fake camera device emulates a camera device by providing frames containing
|
||||||
|
* a black and white checker board, moving diagonally towards the 0,0 corner.
|
||||||
|
* There is also a green, or red square that bounces inside the frame, changing
|
||||||
|
* its color when bouncing off the 0,0 corner.
|
||||||
|
*/
|
||||||
|
class EmulatedFakeCameraDevice : public EmulatedCameraDevice {
|
||||||
|
public:
|
||||||
|
/* Constructs EmulatedFakeCameraDevice instance. */
|
||||||
|
explicit EmulatedFakeCameraDevice(EmulatedFakeCamera* camera_hal);
|
||||||
|
|
||||||
|
/* Destructs EmulatedFakeCameraDevice instance. */
|
||||||
|
~EmulatedFakeCameraDevice();
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Emulated camera device abstract interface implementation.
|
||||||
|
* See declarations of these methods in EmulatedCameraDevice class for
|
||||||
|
* information on each of these methods.
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
public:
|
||||||
|
/* Connects to the camera device.
|
||||||
|
* Since there is no real device to connect to, this method does nothing, but
|
||||||
|
* changes the state.
|
||||||
|
*/
|
||||||
|
status_t Connect();
|
||||||
|
|
||||||
|
/* Disconnects from the camera device.
|
||||||
|
* Since there is no real device to disconnect from, this method does
|
||||||
|
* nothing, but changes the state.
|
||||||
|
*/
|
||||||
|
status_t Disconnect();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/* Starts capturing frames from the camera device.
|
||||||
|
* Since there is no real device to control, this method simply starts the
|
||||||
|
* worker thread, and changes the state.
|
||||||
|
*/
|
||||||
|
status_t StartCamera();
|
||||||
|
|
||||||
|
/* Stops capturing frames from the camera device.
|
||||||
|
* Since there is no real device to control, this method simply stops the
|
||||||
|
* worker thread, and changes the state.
|
||||||
|
*/
|
||||||
|
status_t StopCamera();
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Worker thread management overrides.
|
||||||
|
* See declarations of these methods in EmulatedCameraDevice class for
|
||||||
|
* information on each of these methods.
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/* Implementation of the worker thread routine.
|
||||||
|
* This method simply sleeps for a period of time defined by FPS property of
|
||||||
|
* the fake camera (simulating frame frequency), and then calls emulated
|
||||||
|
* camera's OnNextFrameAvailable method.
|
||||||
|
*/
|
||||||
|
bool InWorkerThread();
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Fake camera device private API
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
private:
|
||||||
|
/* Draws a black and white checker board in the current frame buffer. */
|
||||||
|
void DrawCheckerboard();
|
||||||
|
|
||||||
|
/* Draws a square of the given color in the current frame buffer.
|
||||||
|
* Param:
|
||||||
|
* x, y - Coordinates of the top left corner of the square in the buffer.
|
||||||
|
* size - Size of the square's side.
|
||||||
|
* color - Square's color.
|
||||||
|
*/
|
||||||
|
void DrawSquare(int x, int y, int size, const YCbCrPixel* color);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Fake camera device data members
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
private:
|
||||||
|
/* Last time (absoulte microsec) when the checker board has been redrawn. */
|
||||||
|
uint64_t last_redrawn_;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pixel colors in YCbCr format used when drawing the checker board.
|
||||||
|
*/
|
||||||
|
|
||||||
|
YCbCrPixel black_YCbCr_;
|
||||||
|
YCbCrPixel white_YCbCr_;
|
||||||
|
YCbCrPixel red_YCbCr_;
|
||||||
|
YCbCrPixel green_YCbCr_;
|
||||||
|
YCbCrPixel blue_YCbCr_;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Drawing related stuff
|
||||||
|
*/
|
||||||
|
|
||||||
|
int check_x_;
|
||||||
|
int check_y_;
|
||||||
|
int counter_;
|
||||||
|
int half_width_;
|
||||||
|
|
||||||
|
/* Emulated FPS (frames per second).
|
||||||
|
* We will emulate the "semi-high end" 50 FPS. */
|
||||||
|
static const int emulated_fps_ = 50;
|
||||||
|
|
||||||
|
/* Defines time (in microseconds) between redrawing the checker board.
|
||||||
|
* We will redraw the checker board every 15 milliseconds. */
|
||||||
|
static const uint32_t redraw_after_ = 15000;
|
||||||
|
};
|
||||||
|
|
||||||
|
}; /* namespace android */
|
||||||
|
|
||||||
|
#endif /* HW_EMULATOR_CAMERA_EMULATED_FAKE_CAMERA_DEVICE_H */
|
||||||
217
tools/emulator/system/camera/preview_window.cpp
Normal file
217
tools/emulator/system/camera/preview_window.cpp
Normal file
@@ -0,0 +1,217 @@
|
|||||||
|
/*
|
||||||
|
* 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 PreviewWindow that encapsulates
|
||||||
|
* functionality of a preview window set via set_preview_window camera HAL API.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LOG_NDEBUG 0
|
||||||
|
#define LOG_TAG "EmulatedCamera_Preview"
|
||||||
|
#include <cutils/log.h>
|
||||||
|
#include <ui/Rect.h>
|
||||||
|
#include <ui/GraphicBufferMapper.h>
|
||||||
|
#include "emulated_camera_device.h"
|
||||||
|
#include "preview_window.h"
|
||||||
|
|
||||||
|
namespace android {
|
||||||
|
|
||||||
|
PreviewWindow::PreviewWindow()
|
||||||
|
: preview_window_(NULL),
|
||||||
|
last_previewed_(0),
|
||||||
|
preview_frame_width_(0),
|
||||||
|
preview_frame_height_(0),
|
||||||
|
preview_enabled_(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
PreviewWindow::~PreviewWindow()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Camera API
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
status_t PreviewWindow::SetPreviewWindow(struct preview_stream_ops* window,
|
||||||
|
int preview_fps)
|
||||||
|
{
|
||||||
|
LOGV("%s: current: %p -> new: %p", __FUNCTION__, preview_window_, window);
|
||||||
|
|
||||||
|
status_t res = NO_ERROR;
|
||||||
|
Mutex::Autolock locker(&object_lock_);
|
||||||
|
|
||||||
|
/* Reset preview info. */
|
||||||
|
preview_frame_width_ = preview_frame_height_ = 0;
|
||||||
|
preview_after_ = 0;
|
||||||
|
last_previewed_ = 0;
|
||||||
|
|
||||||
|
if (window != NULL) {
|
||||||
|
/* The CPU will write each frame to the preview window buffer.
|
||||||
|
* Note that we delay setting preview window buffer geometry until
|
||||||
|
* frames start to come in. */
|
||||||
|
res = window->set_usage(window, GRALLOC_USAGE_SW_WRITE_OFTEN);
|
||||||
|
if (res == NO_ERROR) {
|
||||||
|
/* Set preview frequency. */
|
||||||
|
preview_after_ = 1000000 / preview_fps;
|
||||||
|
} else {
|
||||||
|
window = NULL;
|
||||||
|
res = -res; // set_usage returns a negative errno.
|
||||||
|
LOGE("%s: Error setting preview window usage %d -> %s",
|
||||||
|
__FUNCTION__, res, strerror(res));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
preview_window_ = window;
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t PreviewWindow::Start()
|
||||||
|
{
|
||||||
|
LOGV("%s", __FUNCTION__);
|
||||||
|
|
||||||
|
Mutex::Autolock locker(&object_lock_);
|
||||||
|
preview_enabled_ = true;
|
||||||
|
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PreviewWindow::Stop()
|
||||||
|
{
|
||||||
|
LOGV("%s", __FUNCTION__);
|
||||||
|
|
||||||
|
Mutex::Autolock locker(&object_lock_);
|
||||||
|
preview_enabled_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PreviewWindow::IsEnabled()
|
||||||
|
{
|
||||||
|
Mutex::Autolock locker(&object_lock_);
|
||||||
|
return preview_enabled_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public API
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
void PreviewWindow::OnNextFrameAvailable(const void* frame,
|
||||||
|
nsecs_t timestamp,
|
||||||
|
EmulatedCameraDevice* camera_dev)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
Mutex::Autolock locker(&object_lock_);
|
||||||
|
|
||||||
|
if (!preview_enabled_ || preview_window_ == NULL || !IsTimeToPreview()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure that preview window dimensions are OK with the camera device. */
|
||||||
|
if (AdjustPreviewDimensions(camera_dev)) {
|
||||||
|
/* Need to set / adjust buffer geometry for the preview window.
|
||||||
|
* Note that in the emulator preview window uses only RGB for pixel
|
||||||
|
* formats. */
|
||||||
|
LOGV("%s: Adjusting preview windows %p geometry to %dx%d",
|
||||||
|
__FUNCTION__, preview_window_, preview_frame_width_,
|
||||||
|
preview_frame_height_);
|
||||||
|
res = preview_window_->set_buffers_geometry(preview_window_,
|
||||||
|
preview_frame_width_,
|
||||||
|
preview_frame_height_,
|
||||||
|
HAL_PIXEL_FORMAT_RGB_565);
|
||||||
|
if (res != NO_ERROR) {
|
||||||
|
LOGE("%s: Error in set_buffers_geometry %d -> %s",
|
||||||
|
__FUNCTION__, -res, strerror(-res));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Push new frame to the preview window.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Dequeue preview window buffer for the frame. */
|
||||||
|
buffer_handle_t* buffer = NULL;
|
||||||
|
int stride = 0;
|
||||||
|
res = preview_window_->dequeue_buffer(preview_window_, &buffer, &stride);
|
||||||
|
if (res != NO_ERROR || buffer == NULL) {
|
||||||
|
LOGE("%s: Unable to dequeue preview window buffer: %d -> %s",
|
||||||
|
__FUNCTION__, -res, strerror(-res));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Let the preview window to lock the buffer. */
|
||||||
|
res = preview_window_->lock_buffer(preview_window_, buffer);
|
||||||
|
if (res != NO_ERROR) {
|
||||||
|
LOGE("%s: Unable to lock preview window buffer: %d -> %s",
|
||||||
|
__FUNCTION__, -res, strerror(-res));
|
||||||
|
preview_window_->cancel_buffer(preview_window_, buffer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now let the graphics framework to lock the buffer, and provide
|
||||||
|
* us with the framebuffer data address. */
|
||||||
|
void* img = NULL;
|
||||||
|
const Rect rect(preview_frame_width_, preview_frame_height_);
|
||||||
|
GraphicBufferMapper& grbuffer_mapper(GraphicBufferMapper::get());
|
||||||
|
res = grbuffer_mapper.lock(*buffer, GRALLOC_USAGE_SW_WRITE_OFTEN, rect, &img);
|
||||||
|
if (res != NO_ERROR) {
|
||||||
|
LOGE("%s: grbuffer_mapper.lock failure: %d -> %s",
|
||||||
|
__FUNCTION__, res, strerror(res));
|
||||||
|
preview_window_->cancel_buffer(preview_window_, buffer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Frames come in in YV12/NV12/NV21 format. Since preview window doesn't
|
||||||
|
* supports those formats, we need to obtain the frame in RGB565. */
|
||||||
|
res = camera_dev->GetCurrentPreviewFrame(img);
|
||||||
|
if (res == NO_ERROR) {
|
||||||
|
/* Show it. */
|
||||||
|
preview_window_->enqueue_buffer(preview_window_, buffer);
|
||||||
|
} else {
|
||||||
|
LOGE("%s: Unable to obtain preview frame: %d", __FUNCTION__, res);
|
||||||
|
preview_window_->cancel_buffer(preview_window_, buffer);
|
||||||
|
}
|
||||||
|
grbuffer_mapper.unlock(*buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PreviewWindow::AdjustPreviewDimensions(EmulatedCameraDevice* camera_dev)
|
||||||
|
{
|
||||||
|
/* Match the cached frame dimensions against the actual ones. */
|
||||||
|
if (preview_frame_width_ == camera_dev->GetFrameWidth() &&
|
||||||
|
preview_frame_height_ == camera_dev->GetFrameHeight()) {
|
||||||
|
/* They match. */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* They don't match: adjust the cache. */
|
||||||
|
preview_frame_width_ = camera_dev->GetFrameWidth();
|
||||||
|
preview_frame_height_ = camera_dev->GetFrameHeight();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PreviewWindow::IsTimeToPreview()
|
||||||
|
{
|
||||||
|
timeval cur_time;
|
||||||
|
gettimeofday(&cur_time, NULL);
|
||||||
|
const uint64_t cur_mks = cur_time.tv_sec * 1000000LL + cur_time.tv_usec;
|
||||||
|
if ((cur_mks - last_previewed_) >= preview_after_) {
|
||||||
|
last_previewed_ = cur_mks;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}; /* namespace android */
|
||||||
162
tools/emulator/system/camera/preview_window.h
Normal file
162
tools/emulator/system/camera/preview_window.h
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HW_EMULATOR_CAMERA_PREVIEW_WINDOW_H
|
||||||
|
#define HW_EMULATOR_CAMERA_PREVIEW_WINDOW_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Contains declaration of a class PreviewWindow that encapsulates functionality
|
||||||
|
* of a preview window set via set_preview_window camera HAL API.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace android {
|
||||||
|
|
||||||
|
class EmulatedCameraDevice;
|
||||||
|
|
||||||
|
/* Encapsulates functionality of a preview window set via set_preview_window
|
||||||
|
* camera HAL API.
|
||||||
|
*
|
||||||
|
* Objects of this class are contained in EmulatedCamera objects, and handle
|
||||||
|
* relevant camera API callbacks.
|
||||||
|
*/
|
||||||
|
class PreviewWindow {
|
||||||
|
public:
|
||||||
|
/* Constructs PreviewWindow instance. */
|
||||||
|
PreviewWindow();
|
||||||
|
|
||||||
|
/* Destructs PreviewWindow instance. */
|
||||||
|
~PreviewWindow();
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Camera API
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
public:
|
||||||
|
/* Actual handler for camera_device_ops_t::set_preview_window callback.
|
||||||
|
* This method is called by the containing emulated camera object when it is
|
||||||
|
* handing the camera_device_ops_t::set_preview_window callback.
|
||||||
|
* Param:
|
||||||
|
* window - Preview window to set. This parameter might be NULL, which
|
||||||
|
* indicates preview window reset.
|
||||||
|
* preview_fps - Preview's frame frequency. This parameter determins when
|
||||||
|
* a frame received via OnNextFrameAvailable call will be pushed to the
|
||||||
|
* preview window. If 'window' parameter passed to this method is NULL,
|
||||||
|
* this parameter is ignored.
|
||||||
|
* Return:
|
||||||
|
* NO_ERROR on success, or an appropriate error status.
|
||||||
|
*/
|
||||||
|
status_t SetPreviewWindow(struct preview_stream_ops* window,
|
||||||
|
int preview_fps);
|
||||||
|
|
||||||
|
/* Starts the preview.
|
||||||
|
* This method is called by the containing emulated camera object when it is
|
||||||
|
* handing the camera_device_ops_t::start_preview callback.
|
||||||
|
*/
|
||||||
|
status_t Start();
|
||||||
|
|
||||||
|
/* Stops the preview.
|
||||||
|
* This method is called by the containing emulated camera object when it is
|
||||||
|
* handing the camera_device_ops_t::start_preview callback.
|
||||||
|
*/
|
||||||
|
void Stop();
|
||||||
|
|
||||||
|
/* Checks if preview is enabled. */
|
||||||
|
bool IsEnabled();
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public API
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
public:
|
||||||
|
/* Next frame is available in the camera device.
|
||||||
|
* This is a notification callback that is invoked by the camera device when
|
||||||
|
* a new frame is available.
|
||||||
|
* Note that most likely this method is called in context of a worker thread
|
||||||
|
* that camera device has created for frame capturing.
|
||||||
|
* Param:
|
||||||
|
* frame - Captured frame, or NULL if camera device didn't pull the frame
|
||||||
|
* yet. If NULL is passed in this parameter use GetCurrentFrame method
|
||||||
|
* of the camera device class to obtain the next frame. Also note that
|
||||||
|
* the size of the frame that is passed here (as well as the frame
|
||||||
|
* returned from the GetCurrentFrame method) is defined by the current
|
||||||
|
* frame settings (width + height + pixel format) for the camera device.
|
||||||
|
* timestamp - Frame's timestamp.
|
||||||
|
* camera_dev - Camera device instance that delivered the frame.
|
||||||
|
*/
|
||||||
|
void OnNextFrameAvailable(const void* frame,
|
||||||
|
nsecs_t timestamp,
|
||||||
|
EmulatedCameraDevice* camera_dev);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private API
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/* Adjusts cached dimensions of the preview window frame according to the
|
||||||
|
* frame dimensions used by the camera device.
|
||||||
|
*
|
||||||
|
* When preview is started, it's not known (hard to define) what are going
|
||||||
|
* to be the dimensions of the frames that are going to be displayed. Plus,
|
||||||
|
* it might be possible, that such dimensions can be changed on the fly. So,
|
||||||
|
* in order to be always in sync with frame dimensions, this method is called
|
||||||
|
* for each frame passed to OnNextFrameAvailable method, in order to properly
|
||||||
|
* adjust frame dimensions, used by the preview window.
|
||||||
|
* Note that this method must be called while object is locked.
|
||||||
|
* Param:
|
||||||
|
* camera_dev - Camera device, prpviding frames displayed in the preview
|
||||||
|
* window.
|
||||||
|
* Return:
|
||||||
|
* true if cached dimensions have been adjusted, or false if cached
|
||||||
|
* dimensions match device's frame dimensions.
|
||||||
|
*/
|
||||||
|
bool AdjustPreviewDimensions(EmulatedCameraDevice* camera_dev);
|
||||||
|
|
||||||
|
/* Checks if it's the time to push new frame to the preview window.
|
||||||
|
* Note that this method must be called while object is locked. */
|
||||||
|
bool IsTimeToPreview();
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Data members
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/* Locks this instance for data changes. */
|
||||||
|
Mutex object_lock_;
|
||||||
|
|
||||||
|
/* Preview window instance. */
|
||||||
|
preview_stream_ops* preview_window_;
|
||||||
|
|
||||||
|
/* Timestamp (abs. microseconds) when last frame has been pushed to the
|
||||||
|
* preview window. */
|
||||||
|
uint64_t last_previewed_;
|
||||||
|
|
||||||
|
/* Preview frequency in microseconds. */
|
||||||
|
uint32_t preview_after_;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cached preview window frame dimensions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int preview_frame_width_;
|
||||||
|
int preview_frame_height_;
|
||||||
|
|
||||||
|
/* Preview status. */
|
||||||
|
bool preview_enabled_;
|
||||||
|
};
|
||||||
|
|
||||||
|
}; /* namespace android */
|
||||||
|
|
||||||
|
#endif /* HW_EMULATOR_CAMERA_PREVIEW_WINDOW_H */
|
||||||
Reference in New Issue
Block a user