How to resolve Android Camera Preview on Emulator show white and black square only?

转自:http://hi.baidu.com/albertchen521/blog/item/4f2900678018452eab184c8a.html

 

在初次接触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。 
----AlbertChen

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值