参考
官方文档
Camera架构
/devices/camera
Camera API
/training/camera
博客
Android源码笔记——Camera系统架构
Android Camera 四 Camera HAL 分析
概述
Camera框架(旧)
Android系统架构
CameraServicq启动
/system/core/rootdir/
service media /system/bin/mediaserver
class main
user media
group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm
ioprio rt 4
- 1
- 2
- 3
- 4
- 5
启动mediaserver服务
frameworks/av/media/mediaserver/main_mediaserver.cpp
int main(int argc, char** argv)
{
......
} else {
// all other services
if (doLog) {
prctl(PR_SET_PDEATHSIG, SIGKILL); // if parent dies before me, kill me also
setpgid(0, 0); // but if I die first, don't kill my parent
}
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm = defaultServiceManager();
ALOGI("ServiceManager: %p", sm.get());
AudioFlinger::instantiate();
MediaPlayerService::instantiate();
CameraService::instantiate();
AudioPolicyService::instantiate();
registerExtensions();
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
启动CameraService服务
Camera 层次结构
Camera代码流程主要文件
open()
frameworks/base/core/java/android/hardware/
public static Camera open() {
int numberOfCameras = getNumberOfCameras();
CameraInfo cameraInfo = new CameraInfo();
for (int i = 0; i < numberOfCameras; i++) {
getCameraInfo(i, cameraInfo);
if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) {
return new Camera(i);
}
}
return null;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
构造Camera对象,默认是后置摄像头
Camera(int cameraId) {
...
native_setup(new WeakReference<Camera>(this), cameraId, packageName);
}
- 1
- 2
- 3
- 4
调用native方法进行设置
private native final void native_setup(Object camera_this, int cameraId,
String packageName);
- 1
- 2
JNI方法实现
frameworks/base/core/jni/android_hardware_Camera.cpp
// connect to camera service
static void android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
jobject weak_this, jint cameraId, jstring clientPackageName)
{
// Convert jstring to String16
const char16_t *rawClientName = env->GetStringChars(clientPackageName, NULL);
jsize rawClientNameLen = env->GetStringLength(clientPackageName);
String16 clientName(rawClientName, rawClientNameLen);
env->ReleaseStringChars(clientPackageName, rawClientName);
sp<Camera> camera = Camera::connect(cameraId, clientName,
Camera::USE_CALLING_UID);
if (camera == NULL) {
jniThrowRuntimeException(env, "Fail to connect to camera service");
return;
}
// make sure camera hardware is alive
if (camera->getStatus() != NO_ERROR) {
jniThrowRuntimeException(env, "Camera initialization failed");
return;
}
jclass clazz = env->GetObjectClass(thiz);
if (clazz == NULL) {
jniThrowRuntimeException(env, "Can't find android/hardware/Camera");
return;
}
// We use a weak reference so the Camera object can be garbage collected.
// The reference is only used as a proxy for callbacks.
sp<JNICameraContext> context = new JNICameraContext(env, weak_this, clazz, camera);
context->incStrong((void*)android_hardware_Camera_native_setup);
camera->setListener(context);
// save context in opaque field
env->SetIntField(thiz, fields.context, (int)context.get());
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
连接到camera service
frameworks/av/camera/
sp<Camera> Camera::connect(int cameraId, const String16& clientPackageName,
int clientUid)
{
return CameraBaseT::connect(cameraId, clientPackageName, clientUid);
}
- 1
- 2
- 3
- 4
- 5
Camera基础CameraBase
Camera::Camera(int cameraId)
: CameraBase(cameraId)
{
}
- 1
- 2
- 3
- 4
查看CameraBase的connect方法
frameworks/av/camera/
template <typename TCam, typename TCamTraits>
sp<TCam> CameraBase<TCam, TCamTraits>::connect(int cameraId,
const String16& clientPackageName,
int clientUid)
{
ALOGV("%s: connect", __FUNCTION__);
sp<TCam> c = new TCam(cameraId);
sp<TCamCallbacks> cl = c;
status_t status = NO_ERROR;
const sp<ICameraService>& cs = getCameraService();
if (cs != 0) {
TCamConnectService fnConnectService = TCamTraits::fnConnectService;
status = (cs.get()->*fnConnectService)(cl, cameraId, clientPackageName, clientUid,
/*out*/ c->mCamera);
}
if (status == OK && c->mCamera != 0) {
c->mCamera->asBinder()->linkToDeath(c);
c->mStatus = NO_ERROR;
} else {
ALOGW("An error occurred while connecting to camera: %d", cameraId);
c.clear();
}
return c;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
Binder调用
getCameraService返回服务的Ibinder
调用service的connect函数
status_t CameraService::connect(
const sp<ICameraClient>& cameraClient,
int cameraId,
const String16& clientPackageName,
int clientUid,
/*out*/
sp<ICamera>& device) {
String8 clientName8(clientPackageName);
int callingPid = getCallingPid();
LOG1("CameraService::connect E (pid %d \"%s\", id %d)", callingPid,
clientName8.string(), cameraId);
status_t status = validateConnect(cameraId, /*inout*/clientUid);
if (status != OK) {
return status;
}
sp<Client> client;
{
Mutex::Autolock lock(mServiceLock);
sp<BasicClient> clientTmp;
if (!canConnectUnsafe(cameraId, clientPackageName,
cameraClient->asBinder(),
/*out*/clientTmp)) {
return -EBUSY;
} else if (client.get() != NULL) {
device = static_cast<Client*>(clientTmp.get());
return OK;
}
int facing = -1;
int deviceVersion = getDeviceVersion(cameraId, &facing);
// If there are other non-exclusive users of the camera,
// this will tear them down before we can reuse the camera
if (isValidCameraId(cameraId)) {
// transition from PRESENT -> NOT_AVAILABLE
updateStatus(ICameraServiceListener::STATUS_NOT_AVAILABLE,
cameraId);
}
switch(deviceVersion) {
case CAMERA_DEVICE_API_VERSION_1_0:
client = new CameraClient(this, cameraClient,
clientPackageName, cameraId,
facing, callingPid, clientUid, getpid());
break;
case CAMERA_DEVICE_API_VERSION_2_0:
case CAMERA_DEVICE_API_VERSION_2_1:
case CAMERA_DEVICE_API_VERSION_3_0:
client = new Camera2Client(this, cameraClient,
clientPackageName, cameraId,
facing, callingPid, clientUid, getpid(),
deviceVersion);
break;
case -1:
ALOGE("Invalid camera id %d", cameraId);
return BAD_VALUE;
default:
ALOGE("Unknown camera device HAL version: %d", deviceVersion);
return INVALID_OPERATION;
}
status_t status = connectFinishUnsafe(client, client->getRemote());
if (status != OK) {
// this is probably not recoverable.. maybe the client can try again
// OK: we can only get here if we were originally in PRESENT state
updateStatus(ICameraServiceListener::STATUS_PRESENT, cameraId);
return status;
}
mClient[cameraId] = client;
LOG1("CameraService::connect X (id %d, this pid is %d)", cameraId,
getpid());
}
// important: release the mutex here so the client can call back
// into the service from its destructor (can be at the end of the call)
device = client;
return OK;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
根据Api选择
创建CameraClient
status_t status = connectFinishUnsafe(client, client->getRemote());
connectFinishUnsafe()对Client进行初始话操作
status_t CameraService::connectFinishUnsafe(const sp<BasicClient>& client,
const sp<IBinder>& remoteCallback) {
status_t status = client->initialize(mModule);
if (status != OK) {
return status;
}
remoteCallback->linkToDeath(this);
return OK;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
status_t status = client->initialize(mModule);
status_t Camera2Client::initialize(camera_module_t *module)
{
ATRACE_CALL();
ALOGV("%s: Initializing client for camera %d", __FUNCTION__, mCameraId);
status_t res;
res = Camera2ClientBase::initialize(module);
if (res != OK) {
return res;
}
{
SharedParameters::Lock l(mParameters);
res = l.mParameters.initialize(&(mDevice->info()));
if (res != OK) {
ALOGE("%s: Camera %d: unable to build defaults: %s (%d)",
__FUNCTION__, mCameraId, strerror(-res), res);
return NO_INIT;
}
}
String8 threadName;
mStreamingProcessor = new StreamingProcessor(this);
threadName = String8::format("C2-%d-StreamProc",
mCameraId);
mStreamingProcessor->run(threadName.string());
mFrameProcessor = new FrameProcessor(mDevice, this);
threadName = String8::format("C2-%d-FrameProc",
mCameraId);
mFrameProcessor->run(threadName.string());
mCaptureSequencer = new CaptureSequencer(this);
threadName = String8::format("C2-%d-CaptureSeq",
mCameraId);
mCaptureSequencer->run(threadName.string());
mJpegProcessor = new JpegProcessor(this, mCaptureSequencer);
threadName = String8::format("C2-%d-JpegProc",
mCameraId);
mJpegProcessor->run(threadName.string());
switch (mDeviceVersion) {
case CAMERA_DEVICE_API_VERSION_2_0: {
sp<ZslProcessor> zslProc =
new ZslProcessor(this, mCaptureSequencer);
mZslProcessor = zslProc;
mZslProcessorThread = zslProc;
break;
}
case CAMERA_DEVICE_API_VERSION_3_0:{
sp<ZslProcessor3> zslProc =
new ZslProcessor3(this, mCaptureSequencer);
mZslProcessor = zslProc;
mZslProcessorThread = zslProc;
break;
}
default:
break;
}
threadName = String8::format("C2-%d-ZslProc",
mCameraId);
mZslProcessorThread->run(threadName.string());
mCallbackProcessor = new CallbackProcessor(this);
threadName = String8::format("C2-%d-CallbkProc",
mCameraId);
mCallbackProcessor->run(threadName.string());
if (gLogLevel >= 1) {
SharedParameters::Lock l(mParameters);
ALOGD("%s: Default parameters converted from camera %d:", __FUNCTION__,
mCameraId);
ALOGD("%s", l.mParameters.paramsFlattened.string());
}
return OK;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
创建StreamingProcessor对象
mStreamingProcessor = new StreamingProcessor(this);
res = Camera2ClientBase::initialize(module);
调用Camera2ClientBase的初始化函数
template <typename TClientBase>
status_t Camera2ClientBase<TClientBase>::initialize(camera_module_t *module) {
ATRACE_CALL();
ALOGV("%s: Initializing client for camera %d", __FUNCTION__,
TClientBase::mCameraId);
status_t res;
// Verify ops permissions
res = TClientBase::startCameraOps();
if (res != OK) {
return res;
}
if (mDevice == NULL) {
ALOGE("%s: Camera %d: No device connected",
__FUNCTION__, TClientBase::mCameraId);
return NO_INIT;
}
res = mDevice->initialize(module);
if (res != OK) {
ALOGE("%s: Camera %d: unable to initialize device: %s (%d)",
__FUNCTION__, TClientBase::mCameraId, strerror(-res), res);
return res;
}
res = mDevice->setNotifyCallback(this);
return OK;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
Camera2Device initialize进行初始化
status_t Camera2Device::initialize(camera_module_t *module)
{
ATRACE_CALL();
ALOGV("%s: Initializing device for camera %d", __FUNCTION__, mId);
ALOGI("%s pid=(%d)", __FUNCTION__, getpid());
if (mHal2Device != NULL) {
ALOGE("%s: Already initialized!", __FUNCTION__);
return INVALID_OPERATION;
}
status_t res;
char name[10];
snprintf(name, sizeof(name), "%d", mId);
camera2_device_t *device;
res = module->common.methods->open(&module->common, name,
reinterpret_cast<hw_device_t**>(&device));
if (res != OK) {
ALOGE("%s: Could not open camera %d: %s (%d)", __FUNCTION__,
mId, strerror(-res), res);
return res;
}
if (device->common.version != CAMERA_DEVICE_API_VERSION_2_0) {
ALOGE("%s: Could not open camera %d: "
"Camera device is not version %x, reports %x instead",
__FUNCTION__, mId, CAMERA_DEVICE_API_VERSION_2_0,
device->common.version);
device->common.close(&device->common);
return BAD_VALUE;
}
camera_info info;
res = module->get_camera_info(mId, &info);
if (res != OK ) return res;
if (info.device_version != device->common.version) {
ALOGE("%s: HAL reporting mismatched camera_info version (%x)"
" and device version (%x).", __FUNCTION__,
device->common.version, info.device_version);
device->common.close(&device->common);
return BAD_VALUE;
}
res = mRequestQueue.setConsumerDevice(device);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to connect request queue to device: %s (%d)",
__FUNCTION__, mId, strerror(-res), res);
device->common.close(&device->common);
return res;
}
res = mFrameQueue.setProducerDevice(device);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to connect frame queue to device: %s (%d)",
__FUNCTION__, mId, strerror(-res), res);
device->common.close(&device->common);
return res;
}
res = device->ops->get_metadata_vendor_tag_ops(device, &mVendorTagOps);
if (res != OK ) {
ALOGE("%s: Camera %d: Unable to retrieve tag ops from device: %s (%d)",
__FUNCTION__, mId, strerror(-res), res);
device->common.close(&device->common);
return res;
}
res = set_camera_metadata_vendor_tag_ops(mVendorTagOps);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to set tag ops: %s (%d)",
__FUNCTION__, mId, strerror(-res), res);
device->common.close(&device->common);
return res;
}
res = device->ops->set_notify_callback(device, notificationCallback,
NULL);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to initialize notification callback!",
__FUNCTION__, mId);
device->common.close(&device->common);
return res;
}
mDeviceInfo = info.static_camera_characteristics;
mHal2Device = device;
return OK;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
打开摄像头设备
res = module->->open(&module->common, name,
reinterpret_cast<hw_device_t**>(&device));
mModule是HAL层的接口
camera_module结构体
hardware/libhardware/include/hardware/camera_common.h
typedef struct camera_module {
hw_module_t common;
}
- 1
- 2
- 3
hw_module_t结构体
hardware/libhardware/include/hardware/
typedef struct hw_module_t {
/** Modules methods */
struct hw_module_methods_t* methods;
} hw_module_t;
typedef struct hw_module_methods_t {
/** Open a specific device */
int (*open)(const struct hw_module_t* module, const char* id,
struct hw_device_t** device);
} hw_module_methods_t;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
函数指针
camera_common函数实现
原生实现方案
hardware/qcom/camera/QCamera2/HAL/
static hw_module_t camera_common = {
tag: HARDWARE_MODULE_TAG,
module_api_version: CAMERA_MODULE_API_VERSION_1_0,
hal_api_version: HARDWARE_HAL_API_VERSION,
id: CAMERA_HARDWARE_MODULE_ID,
name: "QCamera Module",
author: "Qualcomm Innovation Center Inc",
methods: &qcamera::QCamera2Factory::mModuleMethods,
dso: NULL,
reserved: {0},
};```
methods: &qcamera::QCamera2Factory::mModuleMethods
hardware/qcom/camera/QCamera2/HAL/QCamera2Factory.cpp
```cpp
//打开带有其ID的摄像头设备
int QCamera2Factory::cameraDeviceOpen(int camera_id,
struct hw_device_t **hw_device)
{
int rc = NO_ERROR;
if (camera_id < 0 || camera_id >= mNumOfCameras)
return BAD_VALUE;
QCamera2HardwareInterface *hw = new QCamera2HardwareInterface(camera_id);
if (!hw) {
ALOGE("Allocation of hardware interface failed");
return NO_MEMORY;
}
rc = hw->openCamera(hw_device);
if (rc != NO_ERROR) {
delete hw;
}
return rc;
}
int QCamera2Factory::camera_device_open(
const struct hw_module_t *module, const char *id,
struct hw_device_t **hw_device)
{
if (module != &HAL_MODULE_INFO_SYM.common) {
ALOGE("Invalid module. Trying to open %p, expect %p",
module, &HAL_MODULE_INFO_SYM.common);
return INVALID_OPERATION;
}
if (!id) {
ALOGE("Invalid camera id");
return BAD_VALUE;
}
return gQCamera2Factory.cameraDeviceOpen(atoi(id), hw_device);
}
struct hw_module_methods_t QCamera2Factory::mModuleMethods = {
open: QCamera2Factory::camera_device_open,
};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
打开摄像头设备
hw->openCamera(hw_device)
hardware/qcom/camera/QCamera2/HAL/
int QCamera2HardwareInterface::openCamera(struct hw_device_t **hw_device)
{
int rc = NO_ERROR;
if (mCameraOpened) {
*hw_device = NULL;
return PERMISSION_DENIED;
}
rc = openCamera();
if (rc == NO_ERROR)
*hw_device = &mCameraDevice.common;
else
*hw_device = NULL;
return rc;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
hardware/qcom/camera/QCamera2/stack/mm-camera-interface/src/mm_camera.c
int32_t mm_camera_open(mm_camera_obj_t *my_obj)
{
char dev_name[MM_CAMERA_DEV_NAME_LEN];
int32_t rc = 0;
int8_t n_try=MM_CAMERA_DEV_OPEN_TRIES;
uint8_t sleep_msec=MM_CAMERA_DEV_OPEN_RETRY_SLEEP;
unsigned int cam_idx = 0;
CDBG("%s: begin\n", __func__);
snprintf(dev_name, sizeof(dev_name), "/dev/%s",
mm_camera_util_get_dev_name(my_obj->my_hdl));
sscanf(dev_name, "/dev/video%u", &cam_idx);
CDBG_HIGH("%s: dev name = %s, cam_idx = %d", __func__, dev_name, cam_idx);
do{
n_try--;
my_obj->ctrl_fd = open(dev_name, O_RDWR | O_NONBLOCK);
CDBG("%s: ctrl_fd = %d, errno == %d", __func__, my_obj->ctrl_fd, errno);
if((my_obj->ctrl_fd > 0) || (errno != EIO) || (n_try <= 0 )) {
CDBG_HIGH("%s: opened, break out while loop", __func__);
break;
}
CDBG_HIGH("%s:failed with I/O error retrying after %d milli-seconds",
__func__, sleep_msec);
usleep(sleep_msec * 1000);
}while (n_try > 0);
if (my_obj->ctrl_fd <= 0) {
CDBG_ERROR("%s: cannot open control fd of '%s' (%s)\n",
__func__, dev_name, strerror(errno));
rc = -1;
goto on_error;
}
/* open domain socket*/
n_try = MM_CAMERA_DEV_OPEN_TRIES;
do {
n_try--;
my_obj->ds_fd = mm_camera_socket_create(cam_idx, MM_CAMERA_SOCK_TYPE_UDP);
CDBG("%s: ds_fd = %d, errno = %d", __func__, my_obj->ds_fd, errno);
if((my_obj->ds_fd > 0) || (n_try <= 0 )) {
CDBG("%s: opened, break out while loop", __func__);
break;
}
CDBG("%s:failed with I/O error retrying after %d milli-seconds",
__func__, sleep_msec);
usleep(sleep_msec * 1000);
} while (n_try > 0);
if (my_obj->ds_fd <= 0) {
CDBG_ERROR("%s: cannot open domain socket fd of '%s'(%s)\n",
__func__, dev_name, strerror(errno));
rc = -1;
goto on_error;
}
pthread_mutex_init(&my_obj->msg_lock, NULL);
pthread_mutex_init(&my_obj->cb_lock, NULL);
pthread_mutex_init(&my_obj->evt_lock, NULL);
pthread_cond_init(&my_obj->evt_cond, NULL);
CDBG("%s : Launch evt Thread in Cam Open",__func__);
mm_camera_cmd_thread_launch(&my_obj->evt_thread,
mm_camera_dispatch_app_event,
(void *)my_obj);
/* launch event poll thread
* we will add evt fd into event poll thread upon user first register for evt */
CDBG("%s : Launch evt Poll Thread in Cam Open", __func__);
mm_camera_poll_thread_launch(&my_obj->evt_poll_thread,
MM_CAMERA_POLL_TYPE_EVT);
mm_camera_evt_sub(my_obj, TRUE);
CDBG("%s: end (rc = %d)\n", __func__, rc);
/* we do not need to unlock cam_lock here before return
* because for open, it's done within intf_lock */
return rc;
on_error:
if (my_obj->ctrl_fd > 0) {
close(my_obj->ctrl_fd);
my_obj->ctrl_fd = 0;
}
if (my_obj->ds_fd > 0) {
mm_camera_socket_close(my_obj->ds_fd);
my_obj->ds_fd = 0;
}
/* we do not need to unlock cam_lock here before return
* because for open, it's done within intf_lock */
return rc;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
芯片厂商
AIO/hardware/imx/mx6/libcamera2/
static struct hw_module_methods_t camera_module_methods = {
open: camera_device_open
};
- 1
- 2
- 3
hardware/imx/mx6/libcamera2/
介绍Hal层到kernel
/qq_38907791/article/details/88731109
setPreviewDisplay
frameworks/base/core/java/android/hardware/
public final void setPreviewDisplay(SurfaceHolder holder) throws IOException {
if (holder != null) {
setPreviewDisplay(holder.getSurface());
} else {
setPreviewDisplay((Surface)null);
}
}
private native final void setPreviewDisplay(Surface surface) throws IOException;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
static void android_hardware_Camera_setPreviewDisplay(JNIEnv *env, jobject thiz, jobject jSurface)
{
ALOGV("setPreviewDisplay");
sp<Camera> camera = get_native_camera(env, thiz, NULL);
if (camera == 0) return;
sp<IGraphicBufferProducer> gbp;
sp<Surface> surface;
if (jSurface) {
surface = android_view_Surface_getSurface(env, jSurface);
if (surface != NULL) {
gbp = surface->getIGraphicBufferProducer();
}
}
if (camera->setPreviewTarget(gbp) != NO_ERROR) {
jniThrowException(env, "java/io/IOException", "setPreviewTexture failed");
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
// pass the buffered IGraphicBufferProducer to the camera service
status_t Camera::setPreviewTarget(const sp<IGraphicBufferProducer>& bufferProducer)
{
ALOGV("setPreviewTarget(%p)", bufferProducer.get());
sp <ICamera> c = mCamera;
if (c == 0) return NO_INIT;
ALOGD_IF(bufferProducer == 0, "app passed NULL surface");
return c->setPreviewTarget(bufferProducer);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
status_t Camera2Client::setPreviewTarget(
const sp<IGraphicBufferProducer>& bufferProducer) {
ATRACE_CALL();
ALOGV("%s: E", __FUNCTION__);
Mutex::Autolock icl(mBinderSerializationLock);
status_t res;
if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
sp<IBinder> binder;
sp<ANativeWindow> window;
if (bufferProducer != 0) {
binder = bufferProducer->asBinder();
// Using controlledByApp flag to ensure that the buffer queue remains in
// async mode for the old camera API, where many applications depend
// on that behavior.
window = new Surface(bufferProducer, /*controlledByApp*/ true);
}
return setPreviewWindowL(binder, window);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
将bufferProducer封装到window
status_t Camera2Client::setPreviewWindowL(const sp<IBinder>& binder,
sp<ANativeWindow> window) {
ATRACE_CALL();
status_t res;
ALOGI("%s: start",__FUNCTION__);
if (binder == mPreviewSurface) {
ALOGI("%s: Camera %d: New window is same as old window",
__FUNCTION__, mCameraId);
return NO_ERROR;
}
Parameters::State state;
{
SharedParameters::Lock l(mParameters);
state = l.mParameters.state;
}
switch (state) {
case Parameters::DISCONNECTED:
case Parameters::RECORD:
case Parameters::STILL_CAPTURE:
case Parameters::VIDEO_SNAPSHOT:
ALOGE("%s: Camera %d: Cannot set preview display while in state %s",
__FUNCTION__, mCameraId,
Parameters::getStateName(state));
return INVALID_OPERATION;
case Parameters::STOPPED:
case Parameters::WAITING_FOR_PREVIEW_WINDOW:
// OK
break;
case Parameters::PREVIEW:
// Already running preview - need to stop and create a new stream
res = stopStream();
if (res != OK) {
ALOGE("%s: Unable to stop preview to swap windows: %s (%d)",
__FUNCTION__, strerror(-res), res);
return res;
}
state = Parameters::WAITING_FOR_PREVIEW_WINDOW;
break;
}
mPreviewSurface = binder;
res = mStreamingProcessor->setPreviewWindow(window);
if (res != OK) {
ALOGE("%s: Unable to set new preview window: %s (%d)",
__FUNCTION__, strerror(-res), res);
return res;
}
if (state == Parameters::WAITING_FOR_PREVIEW_WINDOW) {
SharedParameters::Lock l(mParameters);
l.mParameters.state = state;
ALOGI("%s: state->%d",__FUNCTION__, state);
return startPreviewL(l.mParameters, false);
}
ALOGI("%s: end ok",__FUNCTION__);
return OK;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
如果已经在预览模式则先停止预览模式,setPreviewWindow然后开启预览
res = mStreamingProcessor->setPreviewWindow(window);
window在启动预览时使用
startPreview()
AIO/frameworks/av/camera/
// start preview mode
status_t Camera::startPreview()
{
ALOGV("startPreview");
sp <ICamera> c = mCamera;
if (c == 0) return NO_INIT;
return c->startPreview();
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
frameworks/av/services/camera/libcameraservice/api1/
status_t Camera2Client::startPreview() {
ATRACE_CALL();
ALOGI("%s: E", __FUNCTION__);
Mutex::Autolock icl(mBinderSerializationLock);
status_t res;
if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
SharedParameters::Lock l(mParameters);
return startPreviewL(l.mParameters, false);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
status_t Camera2Client::startPreviewL(Parameters ¶ms, bool restart) {
ATRACE_CALL();
status_t res;
ALOGI("%s: state == %d, restart = %d", __FUNCTION__, params.state, restart);
if ( (params.state == Parameters::PREVIEW ||
params.state == Parameters::RECORD ||
params.state == Parameters::VIDEO_SNAPSHOT)
&& !restart) {
// Succeed attempt to re-enter a streaming state
ALOGI("%s: Camera %d: Preview already active, ignoring restart",
__FUNCTION__, mCameraId);
return OK;
}
if (params.state > Parameters::PREVIEW && !restart) {
ALOGE("%s: Can't start preview in state %s",
__FUNCTION__,
Parameters::getStateName(params.state));
return INVALID_OPERATION;
}
if (!mStreamingProcessor->haveValidPreviewWindow()) {
params.state = Parameters::WAITING_FOR_PREVIEW_WINDOW;
return OK;
}
params.state = Parameters::STOPPED;
int lastPreviewStreamId = mStreamingProcessor->getPreviewStreamId();
res = mStreamingProcessor->updatePreviewStream(params);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to update preview stream: %s (%d)",
__FUNCTION__, mCameraId, strerror(-res), res);
return res;
}
bool previewStreamChanged = mStreamingProcessor->getPreviewStreamId() != lastPreviewStreamId;
//我们可以等待创建JPEG输出流,直到第一次实际使用(第一次takePicture调用)。
//但是,这将大大增加HAL3设备上的首次捕获延迟,并且可能会增加某些HAL2设备上的捕获延迟。
//因此,在预览开始时无条件创建它。 缺点是,对于从未拍照的应用程序,这会增加分配内存的消耗。
// TODO: Find a better compromise, though this likely would involve HAL
// changes.
res = updateProcessorStream(mJpegProcessor, params);
if (res != OK) {
ALOGE("%s: Camera %d: Can't pre-configure still image "
"stream: %s (%d)",
__FUNCTION__, mCameraId, strerror(-res), res);
return res;
}
Vector<int32_t> outputStreams;
bool callbacksEnabled = (params.previewCallbackFlags &
CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK) ||
params.previewCallbackSurface;
if (callbacksEnabled) {
// Can't have recording stream hanging around when enabling callbacks,
// since it exceeds the max stream count on some devices.
if (mStreamingProcessor->getRecordingStreamId() != NO_STREAM) {
ALOGV("%s: Camera %d: Clearing out recording stream before "
"creating callback stream", __FUNCTION__, mCameraId);
res = mStreamingProcessor->stopStream();
if (res != OK) {
ALOGE("%s: Camera %d: Can't stop streaming to delete "
"recording stream", __FUNCTION__, mCameraId);
return res;
}
res = mStreamingProcessor->deleteRecordingStream();
if (res != OK) {
ALOGE("%s: Camera %d: Unable to delete recording stream before "
"enabling callbacks: %s (%d)", __FUNCTION__, mCameraId,
strerror(-res), res);
return res;
}
}
res = mCallbackProcessor->updateStream(params);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to update callback stream: %s (%d)",
__FUNCTION__, mCameraId, strerror(-res), res);
return res;
}
outputStreams.push(getCallbackStreamId());
} else if (previewStreamChanged && mCallbackProcessor->getStreamId() != NO_STREAM) {
/**
* Delete the unused callback stream when preview stream is changed and
* preview is not enabled. Don't need stop preview stream as preview is in
* STOPPED state now.
*/
ALOGV("%s: Camera %d: Delete unused preview callback stream.", __FUNCTION__, mCameraId);
res = mCallbackProcessor->deleteStream();
if (res != OK) {
ALOGE("%s: Camera %d: Unable to delete callback stream %s (%d)",
__FUNCTION__, mCameraId, strerror(-res), res);
return res;
}
}
if (params.zslMode && !params.recordingHint) {
res = updateProcessorStream(mZslProcessor, params);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to update ZSL stream: %s (%d)",
__FUNCTION__, mCameraId, strerror(-res), res);
return res;
}
outputStreams.push(getZslStreamId());
}
outputStreams.push(getPreviewStreamId());
if (!params.recordingHint) {
if (!restart) {
res = mStreamingProcessor->updatePreviewRequest(params);
if (res != OK) {
ALOGE("%s: Camera %d: Can't set up preview request: "
"%s (%d)", __FUNCTION__, mCameraId,
strerror(-res), res);
return res;
}
}
res = mStreamingProcessor->startStream(StreamingProcessor::PREVIEW,
outputStreams);
} else {
if (!restart) {
res = mStreamingProcessor->updateRecordingRequest(params);
if (res != OK) {
ALOGE("%s: Camera %d: Can't set up preview request with "
"record hint: %s (%d)", __FUNCTION__, mCameraId,
strerror(-res), res);
return res;
}
}
res = mStreamingProcessor->startStream(StreamingProcessor::RECORD,
outputStreams);
}
if (res != OK) {
ALOGE("%s: Camera %d: Unable to start streaming preview: %s (%d)",
__FUNCTION__, mCameraId, strerror(-res), res);
return res;
}
params.state = Parameters::PREVIEW;
return OK;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
创建和分配缓冲区域
res = mStreamingProcessor->updatePreviewStream(params);
frameworks/av/services/camera/libcameraservice/api1/client2/
status_t StreamingProcessor::updatePreviewStream(const Parameters ¶ms) {
ATRACE_CALL();
Mutex::Autolock m(mMutex);
status_t res;
sp<CameraDeviceBase> device = mDevice.promote();
if (device == 0) {
ALOGE("%s: Camera %d: Device does not exist", __FUNCTION__, mId);
return INVALID_OPERATION;
}
if (mPreviewStreamId != NO_STREAM) {
// Check if stream parameters have to change
uint32_t currentWidth, currentHeight;
res = device->getStreamInfo(mPreviewStreamId,
¤tWidth, ¤tHeight, 0);
if (res != OK) {
ALOGE("%s: Camera %d: Error querying preview stream info: "
"%s (%d)", __FUNCTION__, mId, strerror(-res), res);
return res;
}
if (currentWidth != (uint32_t)params.previewWidth ||
currentHeight != (uint32_t)params.previewHeight) {
ALOGV("%s: Camera %d: Preview size switch: %d x %d -> %d x %d",
__FUNCTION__, mId, currentWidth, currentHeight,
params.previewWidth, params.previewHeight);
res = device->waitUntilDrained();
if (res != OK) {
ALOGE("%s: Camera %d: Error waiting for preview to drain: "
"%s (%d)", __FUNCTION__, mId, strerror(-res), res);
return res;
}
res = device->deleteStream(mPreviewStreamId);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to delete old output stream "
"for preview: %s (%d)", __FUNCTION__, mId,
strerror(-res), res);
return res;
}
mPreviewStreamId = NO_STREAM;
}
}
if (mPreviewStreamId == NO_STREAM) {
res = device->createStream(mPreviewWindow,
params.previewWidth, params.previewHeight,
CAMERA2_HAL_PIXEL_FORMAT_OPAQUE, 0,
&mPreviewStreamId);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to create preview stream: %s (%d)",
__FUNCTION__, mId, strerror(-res), res);
return res;
}
}
res = device->setStreamTransform(mPreviewStreamId,
params.previewTransform);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to set preview stream transform: "
"%s (%d)", __FUNCTION__, mId, strerror(-res), res);
return res;
}
return OK;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
status_t Camera2Device::createStream(sp<ANativeWindow> consumer,
uint32_t width, uint32_t height, int format, size_t size, int *id) {
ATRACE_CALL();
status_t res;
ALOGV("%s: E", __FUNCTION__);
sp<StreamAdapter> stream = new StreamAdapter(mHal2Device);
res = stream->connectToDevice(consumer, width, height, format, size);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to create stream (%d x %d, format %x):"
"%s (%d)",
__FUNCTION__, mId, width, height, format, strerror(-res), res);
return res;
}
*id = stream->getId();
mStreams.push_back(stream);
return OK;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
status_t Camera2Device::StreamAdapter::connectToDevice(
sp<ANativeWindow> consumer,
uint32_t width, uint32_t height, int format, size_t size) {
......
res = mHal2Device->ops->allocate_stream(mHal2Device,
mWidth, mHeight, mFormatRequested, getStreamOps(),
&id, &formatActual, &usage, &maxBuffers);
if (res != OK) {
ALOGE("%s: Device stream allocation failed: %s (%d)",
__FUNCTION__, strerror(-res), res);
return res;
}
......
ALOGV("%s: Registering %d buffers with camera HAL", __FUNCTION__, mTotalBuffers);
res = mHal2Device->ops->register_stream_buffers(mHal2Device,
mId,
mTotalBuffers,
buffers);
if (res != OK) {
ALOGE("%s: Unable to register buffers with HAL device for stream %d",
__FUNCTION__, mId);
} else {
mState = ACTIVE;
}
......
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
HAL层
allocate_stream 创建流
register_stream_buffers 注册流