转自:http://blog.csdn.net/wxzking/archive/2011/03/05/6225143.aspx
Android2.2及其以前的版本都不支持多camera。Android2.3中,camera的硬件接口中增加了对多camera的支持。由于某些原因,不能直接移植Android2.3,但又要支持多camera,所以只能参考Android2.3版本,在2.2上添加接口,支持多camera。
接下来,我将从application层开始,贯穿framework,直到hardware层,逐层介绍如何去支持多camera。
一、Application层支持多camera
1、camera.java文件
首先是Packages/apps/camera/src/com/android/camera/camera.java文件,它是camera应用程序的主体。另外在Framework/base/core/java/android/hardware/下也有一个camera.java文件,它应该是framework与application之间的接口文件。请不要将这两个文件混淆。在application的camera.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用来记录某个camera的ID,camera的ID可以从CameraInfo中获取。
当我们获取了camera的总数后,可以通过函数CameraHolder.instance().getCameraInfo(),逐个去获取每个camera的信息,选择自己想要的camera,然后通过函数CameraHolder.instance().setCameraId()去设置当前要用的camera。
这里需要说明的是,在Android2.3中,只增加了getNumberOfCameras()和getCameraInfo()这两个接口,同时修改了CameraHolder.instance().open()接口,该接口对应底层的connect()。我为了坚持Android2.2的所有接口不变的原则,只移植了这两个接口,没有修改connect(),但同时增加了另一个接口setCameraId()。通过setCameraId()告诉camera的HAL层,当前所要的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.java。camera.java是通过调用CameraHolder.java的接口来实现功能的。
2、CameraHolder.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
1、Camera.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类,在application层CameraHolder.java和Camera.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;
};
2、android_hardware_camera.cpp文件
下面介绍Framework/base/core/jni/android_hardwrea_camera.cpp,该文件为JNI文件。
首先在结构体fields_t中添加了两个成员:facing和orientation,其具体定义为:
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 },
};
3、Camera.h文件
Framework/base/include/camera/camera.h是Framework里Camera.java和android_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);
4、Camera.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作以介绍。(待续)
5、ICameraService.h文件
Framework/base/include/camera/ICameraService.h是CameraService对外的接口文件。
首先增加了三个宏定义,如下:
class ICameraService : public IInterface
{
public:
enum {
GET_NUMBER_OF_CAMERAS = IBinder::FIRST_CALL_TRANSACTION,
GET_CAMERA_INFO,
CONNECT,
SET_CAMERA_ID
};
GET_NUMBER_OF_CAMERAS,GET_CAMERA_INFO和SET_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;
};
6、ICameraService.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);
}
}
这里通过Binder与CameraService.cpp进行通信。下面介绍CameraService相关的文件。
7、CameraService.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中。
8、CameraService.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
1、CameraHardwareInterface.h文件
Frameworks/base/include/camera/CameraHardwareInterface.h是Camera 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);
对这三个接口的实现,就是硬件平台移植工作者需要做的事情了,这里只做简单的介绍。
2、XXCameraHardwareInterface.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 QQ:1226062415 | Init draft. |
|
|
|
|
|
|
|
|
|
|
|
|