|
本帖最后由 欧阳 于 2013-11-26 15:18 编辑
Android Camera数据流完整分析
Android Camera,这里也算是进行以下总结
我们依旧从camera 的打开开始,逐步看看camera的数据流向,内存分配,首先打开camera的第一步,实例化camera类,onCreate被调用,在这个方法中到底做了些什么事情,也在这里做一下总结:
1.实例化FocusManager
2.开启一个CameraOpenThread用于打开camera的全部过程,mCameraOpenThread.start();
3.实例化PreferenceInflater,初始化一些参数
4.实例化TouchManager
5.实例化RotateDialogController等等等
重点是下面几行代码,之前已经不止一次提到,不在多说了
[html]
// don't set mSurfaceHolder here. We have it set ONLY within
// surfaceChanged / surfaceDestroyed, other parts of the code
// assume that when it is set, the surface is also set.
SurfaceView preview = (SurfaceView) findViewById(R.id.camera_preview);
SurfaceHolder holder = preview.getHolder();
holder.addCallback(this);
// don't set mSurfaceHolder here. We have it set ONLY within
// surfaceChanged / surfaceDestroyed, other parts of the code
// assume that when it is set, the surface is also set.
SurfaceView preview = (SurfaceView) findViewById(R.id.camera_preview);
SurfaceHolder holder = preview.getHolder();
holder.addCallback(this);另外这个方法中,还开启了一个startPreviewThread用于开始preview过程,初始化完成之后就开启preview功能
[html]
Thread mCameraPreviewThread = new Thread(new Runnable() {
public void run() {
initializeCapabilities();
startPreview(true);
}
});
Thread mCameraPreviewThread = new Thread(new Runnable() {
public void run() {
initializeCapabilities();
startPreview(true);
}
});这个线程进行初始化之后就调用了app层的startPreview方法,这里开始了万里长征的第一步
这里还是花一点时间说说camera的打开过程,从app调用到的open方法过程这之前的文章中已经讲过,在底层的open方法中完成以下工作
1.为上层调用注册调用接口
2.实例化hal层,并初始化,这个hal层初始化的过程同样之前的文章中已经详细讲过,这个初始化过程非常重要,直接影响着之后的操作
回到我们的startPreview,一步一步看看他的走向
app层---------------------------做一些基本初始化,最重要的就是setPreviewwindow这个方法了,之前也已经详细分析过了,然后调用frameworks层的方法
frameworks层 ---------------这里只是定义了startPreview这个方式,通过JNI层调用
JNI层---------------------------这里作为一个中间站,不做任何处理,转去调用下一层实现
camera client层-------------同样可以理解为一个中转站,通过binder机制接着往下走
camera server层------------初始化显示窗口属性,调用下一层
hardware interface层------转调camerahal_module中的方法
camera hal层----------------这个hal层的startPreview实现是整个preview过程中最为重要的部分,下面再说明
下面就是通过hal层分发命令通过V4LCameraAdapter或者OMXCameraAdapter与kernel driver进行交互
我们看一下server层的调用,相对较重要
[html]
status_t CameraService::Client::startPreview() {
LOG1("startPreview (pid %d)", getCallingPid());
return startCameraMode(<SPAN style="BACKGROUND-COLOR: rgb(51,255,51)">CAMERA_PREVIEW_MODE</SPAN>);
}
status_t CameraService::Client::startPreview() {
LOG1("startPreview (pid %d)", getCallingPid());
return startCameraMode(CAMERA_PREVIEW_MODE);
}[html] view plaincopyprint?// start preview or recording
status_t CameraService::Client::startCameraMode(camera_mode mode) {
LOG1("startCameraMode(%d)", mode);
Mutex::Autolock lock(mLock);
status_t result = checkPidAndHardware();
if (result != NO_ERROR) return result;
switch(mode) {
case CAMERA_PREVIEW_MODE:
if (mSurface == 0 && mPreviewWindow == 0) {
LOG1("mSurface is not set yet.");
// still able to start preview in this case.
}
<SPAN style="BACKGROUND-COLOR: rgb(51,255,51)">return startPreviewMode();</SPAN>
case CAMERA_RECORDING_MODE:
if (mSurface == 0 && mPreviewWindow == 0) {
LOGE("mSurface or mPreviewWindow must be set before startRecordingMode.");
return INVALID_OPERATION;
}
return startRecordingMode();
default:
return UNKNOWN_ERROR;
}
}
// start preview or recording
status_t CameraService::Client::startCameraMode(camera_mode mode) {
LOG1("startCameraMode(%d)", mode);
Mutex::Autolock lock(mLock);
status_t result = checkPidAndHardware();
if (result != NO_ERROR) return result;
switch(mode) {
case CAMERA_PREVIEW_MODE:
if (mSurface == 0 && mPreviewWindow == 0) {
LOG1("mSurface is not set yet.");
// still able to start preview in this case.
}
return startPreviewMode();
case CAMERA_RECORDING_MODE:
if (mSurface == 0 && mPreviewWindow == 0) {
LOGE("mSurface or mPreviewWindow must be set before startRecordingMode.");
return INVALID_OPERATION;
}
return startRecordingMode();
default:
return UNKNOWN_ERROR;
}
}[html] view plaincopyprint?status_t CameraService::Client::startPreviewMode() {
LOG1("startPreviewMode");
status_t result = NO_ERROR;
// if preview has been enabled, nothing needs to be done
if (mHardware->previewEnabled()) {
return NO_ERROR;
}
if (mPreviewWindow != 0) {
native_window_set_scaling_mode(mPreviewWindow.get(),
NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
native_window_set_buffers_transform(mPreviewWindow.get(),
mOrientation);
}
#ifdef OMAP_ENHANCEMENT
disableMsgType(CAMERA_MSG_COMPRESSED_BURST_IMAGE);
#endif
mHardware->setPreviewWindow(mPreviewWindow);
result = mHardware->startPreview();
return result;
}
status_t CameraService::Client::startPreviewMode() {
LOG1("startPreviewMode");
status_t result = NO_ERROR;
// if preview has been enabled, nothing needs to be done
if (mHardware->previewEnabled()) {
return NO_ERROR;
}
if (mPreviewWindow != 0) {
native_window_set_scaling_mode(mPreviewWindow.get(),
NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
native_window_set_buffers_transform(mPreviewWindow.get(),
mOrientation);
}
#ifdef OMAP_ENHANCEMENT
disableMsgType(CAMERA_MSG_COMPRESSED_BURST_IMAGE);
#endif
mHardware->setPreviewWindow(mPreviewWindow);
result = mHardware->startPreview();
return result;
}
在这个startPreviewMode方法中,同样对previewWindow进行了着重的初始化,这个window一直都是非常重要的,这里我一直没有说到setPreviewwindow这个方法的调用,只是因为这片文章的重点不在这里,但是不代表你可以小视他 |
|