转自:http://tassardge.blog.163.com/blog/static/172301708201123043753616/

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

更多相关文章

  1. Android访问中央气象台的天气预报API得到天气数据
  2. Android中查看和管理sqlite数据库
  3. Android SQLite 数据库存储
  4. Android 数据存储与IO (一)
  5. android的数据存储和访问 附源码
  6. 关于Android中SharedPreferences提交数据效率的调研

随机推荐

  1. linux下mysql乱码问题的解决方案
  2. 详解MySQL子查询(嵌套查询)、联结表、组合
  3. mysql索引基数概念与用法示例
  4. MySQL数据库中CAST与CONVERT函数实现类型
  5. Mysql通过存储过程分割字符串为数组
  6. mysql实现查询数据并根据条件更新到另一
  7. mysql 8.0.15 winx64安装配置方法图文教
  8. window下mysql 8.0.15 winx64安装配置方
  9. mysql 8.0.15 压缩版安装图文教程
  10. mysql 8.0.11 安装配置方法图文教程(win1