Android 5.0 Camera系统源码分析(3):Camera预览流程控制流

1. 前言

本文分析的是Android系统源码,从frameworks层到hal层,记录了Camera进入预览模式的重点代码,主要为控制流程的代码,有关图像buffer的传递暂不涉及,硬件平台基于mt6735。由于某些函数比较复杂,在贴出代码时会适当对其进行简化。

2. APP层

这里将分析app层令Camera进入预览模式的两个重点api:setPreviewDisplay和startPreview

mCamera.setPreviewDisplay(mSurfaceHolder);
mCamera.startPreview();

3. setPreviewDisplay函数分析

预览图像最终是要在lcd上显示的,想要在lcd上显示图像就需要用到Surface 。填充Surface有两种方法,一种是注册callback函数,预览数据将在callback函数中返回,得到数据后再把它送到Surface里面;另一种是在开始预览之前就为底层设置好Surface,底层获取数据后直接把数据送到Surface里面,为底层设置好Surface就是setPreviewDisplay的作用,

3.1 frameworks层

先来看frameworks层的实现

public final void setPreviewDisplay(SurfaceHolder holder) throws IOException {
    if (holder != null) {
        setPreviewSurface(holder.getSurface());
    } else {
        setPreviewSurface((Surface)null);
    }    
}

setPreviewSurface是一个jni函数,它的实现在android_hardware_Camera.cpp中

static void android_hardware_Camera_setPreviewSurface(JNIEnv *env, jobject thiz, jobject jSurface)
{
    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");
    }    
}
// pass the buffered IGraphicBufferProducer to the camera service 
status_t Camera::setPreviewTarget(const sp<IGraphicBufferProducer>& bufferProducer) 
{ 
    sp <ICamera> c = mCamera; 
    return c->setPreviewTarget(bufferProducer); 
} 
// set the buffer consumer that the preview will use 
status_t CameraClient::setPreviewTarget( 
        const sp<IGraphicBufferProducer>& bufferProducer) { 
    sp<IBinder> binder; 
    sp<ANativeWindow> window; 
    if (bufferProducer != 0) { 
        binder = bufferProducer->asBinder(); 
        window = new Surface(bufferProducer, /*controlledByApp*/ true); 
    } 
    return setPreviewWindow(binder, window); 
}

ANativeWindow顾名思义“本地窗口”,Surface类继承了ANativeWindow类。按照网上的说法,ANativeWindow类是连接OpenGL和Android窗口系统的桥梁,即OpenGL需要通过ANativeWindow类来间接地操作Android窗口系统。但我们接下来要操作ANativeWindow的不是OpenGL,而是CameraClient

status_t CameraClient::setPreviewWindow(const sp<IBinder>& binder, 
        const sp<ANativeWindow>& window) {
    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()) { 
        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); 
        } 
    } 
    return result; 
}
/** Set the ANativeWindow to which preview frames are sent */ 
status_t setPreviewWindow(const sp<ANativeWindow>& buf) 
{ 
    mPreviewWindow = buf; 
    mHalPreviewWindow.user = this; 
    return mDevice->ops->set_preview_window(mDevice, 
               buf.get() ? &mHalPreviewWindow.nw : 0); 
}

ANativeWindow最终保存在mPreviewWindow变量中,而传到Hal层的则是mHalPreviewWindow.nw 操作集,Hal层将通过它来间接的操作mPreviewWindow。

Created with Raphaël 2.1.0 app app Camera.java Camera.java
  • 9
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值