上一篇文章android Camera API1+HAL1 open camera流程 & Android M已经跟踪了open camera在framework层的整个流程,这篇文章主要分析StartPreview的流程。
很多博主分析camera流程的相关流程都是从java接口层一鼓作气分析到hal层,这样分析的好处是流程连贯。但整个分析流程则非常长,贴上代码的话,文章也变得异常的长,让人望而生畏,失去阅读的欲望。
对hal层的分析对于很多读者来说是不关心的,我打算将framework层和hal层的流程分开分析,framework层各芯片厂商都是一致的,分析的文章也更具普适性。目前分析流程的文章只针对framework层的代码,必要时捎带讲述下hal层的和framework层的接口部分。后续的文章会单独分析下TI 和高通hal层内部流程和架构。
闲言少叙,还是从官方示例开始分析,以下是一段官方示例
/** A basic Camera preview class */
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, now tell the camera where to draw the preview.
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
Log.d(TAG, "Error setting camera preview: " + e.getMessage());
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// empty. Take care of releasing the Camera preview in your activity.
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
if (mHolder.getSurface() == null){
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e){
// ignore: tried to stop a non-existent preview
}
// set preview size and make any resize, rotate or
// reformatting changes here
// start preview with new settings
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e){
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
}
打开camera后,我们需要预览画面,这就需要一个surface作为画布,将创建的surface传递到hal层,供hal往surface里填充数据,进而显示camera采集画面。
开始预览之前,需要先设置预览
public final void setPreviewDisplay(SurfaceHolder holder) throws IOException {
if (holder != null) {
setPreviewSurface(holder.getSurface());
} else {
setPreviewSurface((Surface)null);
}
}
public native final void setPreviewSurface(Surface surface) throws IOException;
从SurfaceHolder中获取到一个surface,作为setPreviewSurface的参数传递下去,setPreviewSurface是一个native函数,直接调用到JNI层。
{ "setPreviewSurface",
"(Landroid/view/Surface;)V",
(void *)android_hardware_Camera_setPreviewSurface },
static void android_hardware_Camera_setPreviewSurface(JNIEnv *env, jobject thiz, jobject jSurface)
{
ALOGV("setPreviewSurface");
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(); 0-1
}
}
if (camera->setPreviewTarget(gbp) != NO_ERROR) { 0-2
jniThrowException(env, "java/io/IOException", "setPreviewTexture failed");
}
}
Surface(c++层)其实是对IGraphicBufferProducer的一个封装,后续和buffer打交道的其实是Surface类里面的sp
变量。0-1
获取surface内部的IGraphicBufferProducer指针,0-2
将该指针传递到native层去。
// 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; 1-1
if (c == 0) return NO_INIT;
ALOGD_IF(bufferProducer == 0, "app passed NULL surface");
return c->setPreviewTarget(bufferProducer); 1-2
}
1-1
处的mCamera是一个BpCamera指针,这在上一篇文章中有交代过,1-2
将会调用到ICamera.cpp中去。
class BpCamera: public BpInterface<ICamera>
{
public:
// pass the buffered IGraphicBufferProducer to the camera service
status_t setPreviewTarget(const sp<IGraphicBufferProducer>& bufferProducer)
{
ALOGV("setPreviewTarget");
Parcel data, reply;
data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
sp<IBinder> b(IInterface::asBinder(bufferProducer));
data.writeStrongBinder(b);
remote()->transact(SET_PREVIEW_TARGET, data, &reply);
return reply.readInt32();
}
---
status_t BnCamera::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
......
case SET_PREVIEW_TARGET: {
ALOGV("SET_PREVIEW_TARGET");
CHECK_INTERFACE(ICamera, data, reply);
sp<IGraphicBufferProducer> st =
interface_cast<IGraphicBufferProducer>(data.readStrongBinder());
reply->writeInt32(setPreviewTarget(st));
return NO_ERROR;
} break;
这部分就是一个常规的Binder RPC调用,代码相对比较简单。上篇文章交代过,CameraClient类继承并实现了BnCamera类,所以此处接下来会调用到CameraClient类中。
// set the buffer consumer that the preview will use
status_t CameraClient::setPreviewTarget(
const sp<IGraphicBufferProducer>& bufferProducer) {
LOG1("setPreviewTarget(%p) (pid %d)", bufferProducer.get(),
getCallingPid());
sp<IBinder> binder;
sp<ANativeWindow> window;
if (bufferProducer != 0) {
binder = IInterface::asBinder(bufferProducer);
// 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); 1-3
}
return setPreviewWindow(binder, window);
}
1-3
利用上层传下来的Surface里的IGraphicBufferProducer新建一个本地Surface实例window,Surface只是一个辅助工具类,后续hal层通过这个新建的window去duqueue 、queue buffer等操作,完成对显示buffer的填充。
status_t CameraClient::setPreviewWindow(const sp<IBinder>& binder,
const sp<ANativeWindow>& window) {
Mutex::Autolock lock(mLock);
status_t result = checkPidAndHardware();
if (result != NO_ERROR) return result;
// return if no change in surface.
if (binder == mSurface) {
return NO_ERROR;
}
if (window != 0) {
result = native_window_api_connect(window.get(), NATIVE_WINDOW_API_CAMERA);
if (result != NO_ERROR) {
ALOGE("native_window_api_connect failed: %s (%d)", strerror(-result),
result);
return result;
}
}
// If preview has been already started, register preview buffers now.
if (mHardware->previewEnabled()) { // 第一次设置setPreview不会走进这里
if (window != 0) {
native_window_set_scaling_mode(window.get(),
NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
native_window_set_buffers_transform(window.get(), mOrientation);
result = mHardware->setPreviewWindow(window);
}
}
if (result == NO_ERROR) {
// Everything has succeeded. Disconnect the old window and remember the
// new window.
disconnectWindow(mPreviewWindow);
mSurface = binder;
mPreviewWindow = window; 1-4
} else {
// Something went wrong after we connected to the new window, so
// disconnect here.
disconnectWindow(window);
}
return result;
}
此setPreviewWindow函数在preview没有enable的时候,只会走进1-4
中,将新建的window保存在CameraClient的成员mPreviewWindow中,这一步并没有真正的setPreviewWindow下去。
java接口层Camera.java中没有定义startPreview函数,只是申明了一下本地定义的public native final void startPreview();
接下来直接查看JNI中的相应函数。
{ "startPreview",
"()V",
(void *)android_hardware_Camera_startPreview },
static void android_hardware_Camera_startPreview(JNIEnv *env, jobject thiz)
{
ALOGV("startPreview");
sp<Camera> camera = get_native_camera(env, thiz, NULL);
if (camera == 0) return;
if (camera->startPreview() != NO_ERROR) {
jniThrowRuntimeException(env, "startPreview failed");
return;
}
}
class BpCamera: public BpInterface<ICamera>
{
public:
// start preview mode, must call setPreviewTarget first
status_t startPreview()
{
ALOGV("startPreview");
Parcel data, reply;
data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
remote()->transact(START_PREVIEW, data, &reply);
return reply.readInt32();
}
status_t BnCamera::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch(code) {
case START_PREVIEW: {
ALOGV("START_PREVIEW");
CHECK_INTERFACE(ICamera, data, reply);
reply->writeInt32(startPreview());
return NO_ERROR;
} break;
// start preview mode
status_t CameraClient::startPreview() {
LOG1("startPreview (pid %d)", getCallingPid());
return startCameraMode(CAMERA_PREVIEW_MODE);
}
// start preview or recording
status_t CameraClient::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();
.....
}
status_t CameraClient::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);
}
mHardware->setPreviewWindow(mPreviewWindow); 2-1
result = mHardware->startPreview(); 2-2
if (result == NO_ERROR) {
mCameraService->updateProxyDeviceState(
ICameraServiceProxy::CAMERA_STATE_ACTIVE,
String8::format("%d", mCameraId));
}
return result;
}
2-1
这里才是真正的设置window到hal层
/** Set the ANativeWindow to which preview frames are sent */
status_t setPreviewWindow(const sp<ANativeWindow>& buf)
{
ALOGV("%s(%s) buf %p", __FUNCTION__, mName.string(), buf.get());
if (mDevice->ops->set_preview_window) {
mPreviewWindow = buf; 2-3
mHalPreviewWindow.user = this; 2-4
ALOGV("%s &mHalPreviewWindow %p mHalPreviewWindow.user %p", __FUNCTION__,
&mHalPreviewWindow, mHalPreviewWindow.user);
return mDevice->ops->set_preview_window(mDevice,
buf.get() ? &mHalPreviewWindow.nw : 0); 2-5
}
return INVALID_OPERATION;
}
2-3
将在CameraClient里新建的一个ANativeWindow保存在CameraHardwareInterface内部,不继续传递到hal层去,因为和ANativeWindow相关的dequeue、queue buffer等相关的接口也是在CameraHardwareInterface内部定义的,这是显示方面的接口,这些接口后续会被hal层回调,所以这个ANativeWindow没必要传递到hal层去。
static ANativeWindow *__to_anw(void *user)
{
CameraHardwareInterface *__this =
reinterpret_cast<CameraHardwareInterface *>(user);
return __this->mPreviewWindow.get(); 2-6
}
#define anw(n) __to_anw(((struct camera_preview_window *)n)->user) 2-7
static int __dequeue_buffer(struct preview_stream_ops* w, 2-8
buffer_handle_t** buffer, int *stride)
{
int rc;
ANativeWindow *a = anw(w);
ANativeWindowBuffer* anb;
rc = native_window_dequeue_buffer_and_wait(a, &anb);
if (!rc) {
*buffer = &anb->handle;
*stride = anb->stride;
}
return rc;
}
static int __enqueue_buffer(struct preview_stream_ops* w,
buffer_handle_t* buffer)
{
ANativeWindow *a = anw(w);
return a->queueBuffer(a,
container_of(buffer, ANativeWindowBuffer, handle), -1);
}
2-4
将CameraHardwareInterface实例指针保存在其内部struct camera_preview_window mHalPreviewWindow
变量的user中,2-5
中将mHalPreviewWindow.nw的地址传递到hal层去,nw变量在camera_preview_window结构体里是第一个成员,其地址也就是变量mHalPreviewWindow的地址(上一篇文章也讲述了两处类似的做法)。将这个nw地址传递到hal层,后续hal层回调时在函数实参中依然会带着这个nw的地址(如2-8
),这样就方便从中提取mHalPreviewWindow,进一步提取2-4
的CameraHardwareInterface实例指针(如2-7
)和获取2-3
中的mPreviewWindow(如2-6
)。
struct camera_preview_window {
struct preview_stream_ops nw;
void *user;
};
typedef struct preview_stream_ops {
int (*dequeue_buffer)(struct preview_stream_ops* w,
buffer_handle_t** buffer, int *stride);
int (*enqueue_buffer)(struct preview_stream_ops* w,
buffer_handle_t* buffer);
......
}
继续分析2-2
mHardware->startPreview()
/**
* Start preview mode.
*/
status_t startPreview()
{
ALOGV("%s(%s)", __FUNCTION__, mName.string());
if (mDevice->ops->start_preview)
return mDevice->ops->start_preview(mDevice);
return INVALID_OPERATION;
}
这里继续调用到hal层去了,hal层具体的startPreview的内部逻辑是因芯片产商的不同而各异的,在此先不跟踪进去,先点到为止。
至此,framework层的startPreview流程就基本跟踪完了,相对于open camera来说,简单了很多,毕竟这只是一个指令的控制流。
startPreview的流程调用如下图
stop preview的流程和start preview的流程大致相同,在此就不分析了,贴上流程图
下一篇文章将分析拍照的控制流和数据流的回调