Android camera 默认显示黑白的问题

在初次接触 android 的时候就注意到通过模拟器,相机预览的时候只能显示黑白电影。这些天总算有点空闲时间了,决定研究下这个。 关于 android camera 的构造不再说了,模拟器上使用用的是一个虚拟的 Camera-----FakeCamera 这个大家应该都知道。

首先初略的了解一下 camera preview 图像显示的原理。 Camera application 初始化的时候会创建一个 surfaceview ,从 camera device 接收到的数据就可以通过它显示在屏幕上。内部处理的流程是很复杂的,下面我只给出一个从初始化到绘图函数调用的流程。

Surface 初始化:

Android_view_surface:: Surface_init--> SurfaceComposerClient::CreateSurface-->

SurfaceFlinger:: createSurface--> Android_view_surface:: setSurface

 

 

Camera 数据缓冲区 Heap 初始化:

CameraHardwareStub::initHeapLocked--> new MemoryBase--> new FakeCamera

 

 

Heap 缓冲区注册到 surface:

Android_hardware_camera:: android_hardware_Camera_setPreviewDisplay-->

Camera:: setPreviewDisplay--> CameraService::Client::setPreviewDisplay-->

CameraService::Client::registerPreviewBuffers--> LayerBuffer::registerBuffers

 

 

FakeCamera 原始数据的传递与绘图:

CameraHardwareStub::previewThread--> CameraService::Client::previewCallback-->

CameraService::Client::postPreviewFrame--> ISurface:: postBuffer-->

LayerBuffer::postBuffer--> LayerBuffer::BufferSource::postBuffer-->

LayerBase::invalidate--> SurfaceFlinger::signalEvent--> SurfaceFlinger::threadLoop-->

SurfaceFlinger::handleRepaint--> LayerBase::draw-->

LayerBuffer::BufferSource::onDraw--> LayerBase::drawWithOpenGL

 

FakeCamera 得到数据为 Yuv422, 原以为是库里某个地方绘图的时候出问题,但 LayerBuffer::OnDraw 往下走很复杂的:

                       t.format == GGL_PIXEL_FORMAT_YCbCr_420_SP) {
                // just show the Y plane of YUV buffers。 不明白为什么google这么做。。。。。

但要解决预览为黑白电影的问题应该就比较简单了。只要我们将 YUV 数据转换为 RGB 丢给 cameraService 就可以了。用以下的代码替代 ccrgb16toyuv_wo_colorkey

int32_t ccrgb16toyuv_wo_colorkey (uint8_t *rgb16,uint8_t *yuv422,uint32_t *param,uint8_t *table[])

{

       int32_t width_dst = param[0];

    int32_t height_dst = param[1];

       memcpy(yuv422, rgb16, width_dst*height_dst*2);

}

CameraService 中改动:

status_t CameraService::Client::registerPreviewBuffers ()

{

   。。。。。。。。。。。。。。。。。。。。。。。

    ISurface::BufferHeap buffers(w, h, w, h,

                                PIXEL_FORMAT_RGB_565 ,

//PIXEL_FORMAT_YCbCr_420_SP,

                                 transform,

                                 0,

                                 mHardware->getPreviewHeap());

 

   status_t ret = mSurface->registerBuffers(buffers);

    if (ret != NO_ERROR) {

        LOGE("registerBuffers failed with status %d", ret);

    }

    return ret;

}

PIXEL_FORMAT_RGB_565 替换 PIXEL_FORMAT_YCbCr_420_SP 。这样就可以了。不妨动手试一试吧,看看是不是预览视频变为彩色的了。

对于实际的 camera device 出来的数据如果是 yuv 的话,也可以通过算法将 yuv 转换为 RGB ,这样做并不会导致转换效率降低,因为即使将 yuv 得数据丢到 surfaceflinger 中,最终还是会转换为 BMp

你可能感兴趣的:(android,算法,Google,table,application,DST)