Android2.2平台上支持多camera

转自:http://blog.csdn.net/wxzking/archive/2011/03/05/6225143.aspx

 

Android2.2及其以前的版本都不支持多cameraAndroid2.3中,camera的硬件接口中增加了对多camera的支持。由于某些原因,不能直接移植Android2.3,但又要支持多camera,所以只能参考Android2.3版本,在2.2上添加接口,支持多camera

接下来,我将从application层开始,贯穿framework,直到hardware层,逐层介绍如何去支持多camera

一、Application层支持多camera

1camera.java文件

首先是Packages/apps/camera/src/com/android/camera/camera.java文件,它是camera应用程序的主体。另外在Framework/base/core/java/android/hardware/下也有一个camera.java文件,它应该是frameworkapplication之间的接口文件。请不要将这两个文件混淆。在applicationcamera.java中,我添加如下的code

Import了一个新类,叫做CameraInfo,用它来存储camera的信息,其定义在文件Framework/base/core/java/android/hardware/camera.java中。

CODE:

import android.hardware.Camera.CameraInfo;

增加两个私有变量,CODE如下:

// multiple cameras support
private int mNumberOfCameras;
private int mCameraId;

mNumberOfCameras用来记录手机上camera的数量,可以通过函数CameraHolder.instance().getNumberOfCameras()来获得;mCameraId用来记录某个cameraIDcameraID可以从CameraInfo中获取。

当我们获取了camera的总数后,可以通过函数CameraHolder.instance().getCameraInfo(),逐个去获取每个camera的信息,选择自己想要的camera,然后通过函数CameraHolder.instance().setCameraId()去设置当前要用的camera

这里需要说明的是,在Android2.3中,只增加了getNumberOfCameras()getCameraInfo()这两个接口,同时修改了CameraHolder.instance().open()接口,该接口对应底层的connect()。我为了坚持Android2.2的所有接口不变的原则,只移植了这两个接口,没有修改connect(),但同时增加了另一个接口setCameraId()。通过setCameraId()告诉cameraHAL层,当前所要的camera,如果不调用该接口,系统就按照Android2.2原来的配置运行。好了,下面我们继续描述code

我修改了onCreate()函数,CODE如下:

@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);

setContentView(R.layout.camera);
mSurfaceView = (SurfaceView) findViewById(R.id.camera_preview);

mPreferences = PreferenceManager.getDefaultSharedPreferences(this);
CameraSettings.upgradePreferences(mPreferences);

mNumberOfCameras = CameraHolder.instance().getNumberOfCameras();
for(int I = 0; I < mNumberOfCameras; I++)

{

    CameraInfo info = CameraHolder.instance().getCameraInfo()[I];

    If(CameraInfo.CAMERA_FACING_FRONT == info.facing)

    {

        mCameraId = I;

        break;

    }

}

CameraHolder.instance().setCameraId(mCameraId);

mQuickCapture = getQuickCaptureSettings();

……

至此Packages/apps/camera/src/com/android/camera/camera.java文件修改完毕,接下来我们修改Packages/apps/camera/src/com/android/camera/CameraHolder.javacamera.java是通过调用CameraHolder.java的接口来实现功能的。

2CameraHolder.java文件

CameraHolder.java文件中,同样得import CameraInfo类。CODE如下:

import android.hardware.Camera.CameraInfo;

添加三个私有变量:

private int mNumberOfCameras;
private int mCameraId = -1;
private CameraInfo[] mInfo;

这三个变量的意义一目了然,不做多讲。

修改了CameraHolder()函数:

private CameraHolder() {
HandlerThread ht = new HandlerThread("CameraHolder");
ht.start();
mHandler = new MyHandler(ht.getLooper());
mNumberOfCameras = android.hardware.Camera.getNumberOfCameras();
mInfo = new CameraInfo[mNumberOfCameras];
for (int i = 0; i < mNumberOfCameras; i++) {
mInfo[i] = new CameraInfo();
android.hardware.Camera.getCameraInfo(i, mInfo[i]);

}

CameraHolder()中调用android.hardware.Camera.getNumberOfCameras()获取了camera的总数,赋值给mNumberOfCameras,同时创建了相应数目的CameraInfo数组,并通过函数android.hardware.Camera.getCameraInfo()camera的信息都存储在mInfo中。同时增加了下面三个接口函数:
public int getNumberOfCameras() {
return mNumberOfCameras;
}

public CameraInfo[] getCameraInfo() {
return mInfo;

public int setCameraId(int cameraId) {
return android.hardware.Camera.setCameraId(cameraId);
}

application中,修改上述两个文件即可。下面我们将描述framework中的修改。

 

 

二、Framework层支持多camera

1Camera.java文件

首先看一下文件Framework/base/core/java/android/hardware/camera.java

添加了三个接口函数,分别为getNumberOfCameras()getCameraInfo()setCameraId(),它们的CODE如下:

/**
* Returns the number of physical cameras available on this device.
*/
public native static int getNumberOfCameras();

/**
* Returns the information about a particular camera.
* If {@link #getNumberOfCameras()} returns N, the valid id is 0 to N-1.
*/
public native static void getCameraInfo(int cameraId, CameraInfo cameraInfo);

public native static int setCameraId(int cameraId);

同时定义了CameraInfo类,在applicationCameraHolder.javaCamera.java这两个文件中引用了该类。其CODE如下:

/**
* Information about a camera
*/
public static class CameraInfo {
/**
* The facing of the camera is opposite to that of the screen.
*/
public static final int CAMERA_FACING_BACK = 0;

/**
* The facing of the camera is the same as that of the screen.
*/
public static final int CAMERA_FACING_FRONT = 1;

/**
* The direction that the camera faces to. It should be
* CAMERA_FACING_BACK or CAMERA_FACING_FRONT.
*/
public int facing;

 

/**
* The orientation of the camera image. The value is the angle that the
* camera image needs to be rotated clockwise so it shows correctly on
* the display in its natural orientation. It should be 0, 90, 180, or 270.
*
* For example, suppose a device has a naturally tall screen. The
* back-facing camera sensor is mounted in landscape. You are looking at
* the screen. If the top side of the camera sensor is aligned with the
* right edge of the screen in natural orientation, the value should be

* 90. If the top side of a front-facing camera sensor is aligned with
* the right of the screen, the value should be 270.
*
* @see #setDisplayOrientation(int)
* @see #setRotation(int)
* @see #setPreviewSize(int, int)
* @see #setPictureSize(int, int)
* @see #setJpegThumbnailSize(int, int)
*/
public int orientation;
};

 

2android_hardware_camera.cpp文件

下面介绍Framework/base/core/jni/android_hardwrea_camera.cpp,该文件为JNI文件。

首先在结构体fields_t中添加了两个成员:facingorientation,其具体定义为:

struct fields_t {
jfieldID context;
jfieldID surface;
jfieldID facing;
jfieldID orientation; 
jmethodID post_event;
};

接下来定义了三个函数,分别为android_hardware_Camera_getNumberOfCameras()android_hardware_Camera_getCameraInfo()android_hardware_Camera_setCameraId()。其CODE如下:

static jint android_hardware_Camera_getNumberOfCameras(JNIEnv *env, jobject thiz)
{
return Camera::getNumberOfCameras();
}

static void android_hardware_Camera_getCameraInfo(JNIEnv *env, jobject thiz,
jint cameraId, jobject info_obj)
{
CameraInfo cameraInfo;
status_t rc = Camera::getCameraInfo(cameraId, &cameraInfo);
if (rc != NO_ERROR) {
jniThrowException(env, "java/lang/RuntimeException",
"Fail to get camera info");
return;
}
env->SetIntField(info_obj, fields.facing, cameraInfo.facing);
env->SetIntField(info_obj, fields.orientation, cameraInfo.orientation);
}

static jint android_hardware_Camera_setCameraId(JNIEnv *env, jobject thiz,jint cameraId)
{
return Camera::setCameraId(cameraId);
}

同时修改了JNINativeMethod,将上述三个函数的信息添加进去。

static JNINativeMethod camMethods[] = {
{ "getNumberOfCameras",
"()I",
(void *)android_hardware_Camera_getNumberOfCameras },
{ "getCameraInfo",
"(ILandroid/hardware/Camera$CameraInfo;)V",
(void*)android_hardware_Camera_getCameraInfo },
{ "setCameraId",
"(I)I",
(void *)android_hardware_Camera_setCameraId }, 
{ "native_setup",
"(Ljava/lang/Object;)V",
(void*)android_hardware_Camera_native_setup },
{ "native_release",
"()V",
(void*)android_hardware_Camera_release },

 

修改了函数register_android_hardware_Camera(),将结构体CameraInfo的两个成员添加到了fields_to_find。其CODE如下:

// Get all the required offsets in java class and register native functions
int register_android_hardware_Camera(JNIEnv *env)
{
field fields_to_find[] = {
{ "android/hardware/Camera", "mNativeContext", "I", &fields.context },
{ "android/view/Surface", "mSurface", "I", &fields.surface },
{ "android/hardware/Camera$CameraInfo", "facing", "I", &fields.facing },
{ "android/hardware/Camera$CameraInfo", "orientation", "I", &fields.orientation }, 
};

3Camera.h文件

Framework/base/include/camera/camera.hFrameworkCamera.javaandroid_hardware_camera.cpp的接口文件。

首先定义了结构体CameraInfo,其具体定义如下:

enum {

    CAMERA_FACING_BACK = 0, /* The facing of the camera is opposite to that of the screen. */

    CAMERA_FACING_FRONT = 1 /* The facing of the camera is the same as that of the screen. */

};

 

struct CameraInfo {

 

    /**

     * The direction that the camera faces to. It should be

     * CAMERA_FACING_BACK or CAMERA_FACING_FRONT.

     */

    int facing;

 

    /**

     * The orientation of the camera image. The value is the angle that the

     * camera image needs to be rotated clockwise so it shows correctly on

     * the display in its natural orientation. It should be 0, 90, 180, or 270.

     *

     * For example, suppose a device has a naturally tall screen. The

     * back-facing camera sensor is mounted in landscape. You are looking at

     * the screen. If the top side of the camera sensor is aligned with the

     * right edge of the screen in natural orientation, the value should be

     * 90. If the top side of a front-facing camera sensor is aligned with

     * the right of the screen, the value should be 270.

     */

    int orientation;

};

在Camera类中增加了三个成员函数,其定义如下:

static int32_t getNumberOfCameras();
static status_t getCameraInfo(int cameraId, struct CameraInfo* cameraInfo);
static int32_t setCameraId(int cameraId);

 

4Camera.cpp

Framework/base/libs/camera/camera.cpp是对Camera.h文件的实现。它实现了下面三个函数,其CODE如下:

int32_t Camera::getNumberOfCameras()
{
const sp<ICameraService>& cs = getCameraService();
if (cs == 0) return 0;
return cs->getNumberOfCameras();
}

status_t Camera::getCameraInfo(int cameraId,
struct CameraInfo* cameraInfo) {
const sp<ICameraService>& cs = getCameraService();
if (cs == 0) return UNKNOWN_ERROR;
return cs->getCameraInfo(cameraId, cameraInfo);
}
int32_t Camera::setCameraId(int cameraId)
{
const sp<ICameraService>& cs = getCameraService();
if (cs == 0) return 0;
return cs->setCameraId(cameraId);
}

它调用ICameraService.h中的三个接口,下面对ICameraService.h作以介绍。(待续)

 

 

5ICameraService.h文件

Framework/base/include/camera/ICameraService.hCameraService对外的接口文件。

首先增加了三个宏定义,如下:

class ICameraService : public IInterface
{
public:
enum {
GET_NUMBER_OF_CAMERAS = IBinder::FIRST_CALL_TRANSACTION,
GET_CAMERA_INFO,
CONNECT,
SET_CAMERA_ID
};

GET_NUMBER_OF_CAMERASGET_CAMERA_INFOSET_CAMERA_ID对应于那三个函数接口。

接下来,定义了三个纯虚函数,CODE如下:
public:
DECLARE_META_INTERFACE(CameraService);
virtual int32_t getNumberOfCameras() = 0;
virtual status_t getCameraInfo(int cameraId,
struct CameraInfo* cameraInfo) = 0;
virtual int32_t setCameraId(int cameraId) = 0; 
virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient) = 0;
};

6ICameraService.cpp文件

Framework/base/libs/camera/ICameraService.cpp是对ICameraService.h文件的实现。

它对下面三个函数进行了定义:

// get number of cameras available

    virtual int32_t getNumberOfCameras()

    {

        Parcel data, reply;

        data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());

        remote()->transact(BnCameraService::GET_NUMBER_OF_CAMERAS, data, &reply);

        return reply.readInt32();

    }

 

    // get information about a camera

    virtual status_t getCameraInfo(int cameraId,

                                   struct CameraInfo* cameraInfo) {

        Parcel data, reply;

        data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());

        data.writeInt32(cameraId);

        remote()->transact(BnCameraService::GET_CAMERA_INFO, data, &reply);

        cameraInfo->facing = reply.readInt32();

        cameraInfo->orientation = reply.readInt32();

        return reply.readInt32();

    }

    virtual int32_t setCameraId(int cameraId)

    {

        Parcel data, reply;

        data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());

    data.writeInt32(cameraId);

        remote()->transact(BnCameraService::SET_CAMERA_ID, data, &reply);

        return reply.readInt32();

    }

 

然后又在函数BnCameraService::onTransact()中做了修改:

status_t BnCameraService::onTransact(

    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)

{

    switch(code) {

        case GET_NUMBER_OF_CAMERAS: {

            CHECK_INTERFACE(ICameraService, data, reply);

            reply->writeInt32(getNumberOfCameras());

            return NO_ERROR;

        } break;

        case GET_CAMERA_INFO: {

            CHECK_INTERFACE(ICameraService, data, reply);

            CameraInfo cameraInfo;

            memset(&cameraInfo, 0, sizeof(cameraInfo));

            status_t result = getCameraInfo(data.readInt32(), &cameraInfo);

            reply->writeInt32(cameraInfo.facing);

            reply->writeInt32(cameraInfo.orientation);

            reply->writeInt32(result);

            return NO_ERROR;

        } break;

        case SET_CAMERA_ID: {

            CHECK_INTERFACE(ICameraService, data, reply);

            reply->writeInt32(setCameraId(data.readInt32()));

            return NO_ERROR;

        } break;    

        case CONNECT: {

            CHECK_INTERFACE(ICameraService, data, reply);

            sp<ICameraClient> cameraClient = interface_cast<ICameraClient>(data.readStrongBinder());

            sp<ICamera> camera = connect(cameraClient);

            reply->writeStrongBinder(camera->asBinder());

            return NO_ERROR;

        } break;

        default:

            return BBinder::onTransact(code, data, reply, flags);

    }

}

这里通过BinderCameraService.cpp进行通信。下面介绍CameraService相关的文件。

7CameraService.h文件

Frameworks/base/camera/libcameraservice/CameraService.h中定义了如下三个接口函数:

 

    virtual int32_t     getNumberOfCameras();

    virtual status_t    getCameraInfo(int cameraId,

                                      struct CameraInfo* cameraInfo);

    virtual int32_t     setCameraId(int cameraId);  

其具体实现在CameraService.cpp中。

8CameraService.cpp

frameworks/base/camera/libcameraservice/CameraService.cpp调用Camera HAL层的接口,对CameraService.h中的三个新增接口做了实现。其CODE如下:

int32_t CameraService::getNumberOfCameras() {

    return HAL_getNumberOfCameras();

}

 

status_t CameraService::getCameraInfo(int cameraId,

                                      struct CameraInfo* cameraInfo) {

    int mNumberOfCameras = HAL_getNumberOfCameras();                          

    if (cameraId < 0 || cameraId >= mNumberOfCameras) {

        return BAD_VALUE;

    }

 

    HAL_getCameraInfo(cameraId, cameraInfo);

    return OK;

}

int32_t CameraService::setCameraId(int cameraId) {

    return HAL_setCameraId(cameraId);

}

下面我们将介绍Camera HAL层对多Camera的支持。(待续)

 

 

三、Camera HAL层支持多Camera

1CameraHardwareInterface.h文件

Frameworks/base/include/camera/CameraHardwareInterface.hCamera HAL层对上的接口文件。由于它的存在,上层可以不关心下层的实现,直接调用相应接口去做自己的事情。这对硬件的移植非常有利。

在这个文件中,我添加了下面三个接口:

/**

 * The functions need to be provided by the camera HAL.

 *

 * If getNumberOfCameras() returns N, the valid cameraId for getCameraInfo()

 * and openCameraHardware() is 0 to N-1.

 */

extern "C" int HAL_getNumberOfCameras();

extern "C" void HAL_getCameraInfo(int cameraId, struct CameraInfo* cameraInfo);

extern "C" int HAL_setCameraId(int cameraId);

对这三个接口的实现,就是硬件平台移植工作者需要做的事情了,这里只做简单的介绍。

2XXCameraHardwareInterface.cpp文件

XXCameraHardwareInterface.cpp是硬件移植工作者根据所用硬件平台对CameraHardwareInterface.h的实现。就上述三个接口,我们可以做如下的实现。

首先定义CameraInfo类型的结构体数组,用来存储硬件平台所支持的Camera的信息。这里只表示支持两个Camera,前面后面各一个。其具体定义如下:

static CameraInfo sCameraInfo[] = {

    {

        CAMERA_FACING_BACK,

        90,  /* orientation */

    },

    {

        CAMERA_FACING_FRONT,

        90,  /* orientation */

    }   

}; 

接下来实现那三个接口函数,具体实现如下:

extern "C" int HAL_getNumberOfCameras()

{

    return sizeof(sCameraInfo) / sizeof(sCameraInfo[0]);

}

 

extern "C" void HAL_getCameraInfo(int cameraId, struct CameraInfo* cameraInfo)

{

    memcpy(cameraInfo, &sCameraInfo[cameraId], sizeof(CameraInfo));

}

extern "C" int HAL_setCameraId(int cameraId)

{

    //设置该Camera为当前所用Camera

    return NO_ERROR;

}

 

四、总结

上述文字,就Android2.2下如何支持多Camera问题,从最上层application层到最下层Camera HAL,从流程上做了一个简单的描述。希望对刚接触Android平台下Camera的朋友能有所帮助。如果有其他问题,可以联系我。

 

 

Revision History

修订历史记录

Version

版本

Date

日期

Author

作者

Brief Description

变更简要

0.0.1

2011-03-05

Wangxiaozhe

wxiaozhe@163.com

QQ1226062415

Init draft.

 

 

 

 

 

 

 

 

 

 

 

 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值