博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
《精通Android 5 多媒体开发》——第6章,第6.2节分析硬件抽象层
阅读量:7185 次
发布时间:2019-06-29

本文共 7056 字,大约阅读时间需要 23 分钟。

本节书摘来自异步社区《精通Android 5 多媒体开发》一书中的第6章,第6.2节分析硬件抽象层,作者 王石磊,更多章节内容可以访问云栖社区“异步社区”公众号查看

6.2 分析硬件抽象层

精通Android 5 多媒体开发
Overlay系统的硬件抽象层是一个硬件模块。在本节的内容中,将简要介绍Overlay系统的硬件抽象层的基本知识,为后面的知识做好铺垫。

6.2.1 Overlay系统硬件抽象层的接口

在如下文件中定义Overlay系统硬件抽象层的接口。

hardware/qcom/display/liboverlay/overlay.h

在文件overlay.h中,主要定义了data device和control device两个结构。并提供针对data device和control device的函数open()和函数close()。文件overlay.h的代码结构如图6-3所示。

70a0cec0326e3dd64bfdc55c8a59ee9244247a20

(1)定义Overlay控制设备和Overlay数据设备,它们的名称被定义为如下两个字符串。

#define OVERLAY_HARDWARE_CONTROL  "control"#define OVERLAY_HARDWARE_DATA    "data"

(2)定义一个枚举enum,也定义了所有支援的Format,FrameBuffer会根据Format 和width、height来决定Buffer(FrameBuffer里面用来显示的Buffer)的大小。定义enum的代码如下所示。

enum {  OVERLAY_FORMAT_RGBA_8888  = HAL_PIXEL_FORMAT_RGBA_8888,  OVERLAY_FORMAT_RGB_565   = HAL_PIXEL_FORMAT_RGB_565,  OVERLAY_FORMAT_BGRA_8888  = HAL_PIXEL_FORMAT_BGRA_8888,  OVERLAY_FORMAT_YCbCr_422_SP = HAL_PIXEL_FORMAT_YCbCr_422_SP,  OVERLAY_FORMAT_YCbCr_420_SP = HAL_PIXEL_FORMAT_YCbCr_420_SP,  OVERLAY_FORMAT_YCrCb_420_SP = HAL_PIXEL_FORMAT_YCrCb_420_SP,  OVERLAY_FORMAT_YCbYCr_422_I = HAL_PIXEL_FORMAT_YCbCr_422_I,  OVERLAY_FORMAT_YCbYCr_420_I = HAL_PIXEL_FORMAT_YCbCr_420_I,  OVERLAY_FORMAT_CbYCrY_422_I = HAL_PIXEL_FORMAT_CbYCrY_422_I,  OVERLAY_FORMAT_CbYCrY_420_I = HAL_PIXEL_FORMAT_CbYCrY_420_I,  OVERLAY_FORMAT_DEFAULT   = 99  // The actual color format is determined                       // by the overlay};

(3)定义和Overlay系统相关的结构体。

在文件overlay.h中和Overlay系统相关的结构体是overlay_t和overlay_handle_t,主要代码如下所示。

typedef struct overlay_t {  uint32_t      w;            //宽  uint32_t      h;            //高  int32_t       format;         //颜色格式  uint32_t      w_stride;        //一行的内容  uint32_t      h_stride;        //一列的内容  uint32_t      reserved[3];  /* returns a reference to this overlay's handle (the caller doesn't   * take ownership) */  overlay_handle_t  (*getHandleRef)(struct overlay_t* overlay);  uint32_t      reserved_procs[7];} overlay_t;

结构体overlay_handle_t是在内部使用的结构体,用于保存Overlay硬件设备的句柄。在使用的过程中,需要从overlay_t获取overlay_handle_t。其中上一层的使用只实现结构体overlay_handle_t指针的传递,具体的操作是在Overlay的硬件抽象层中完成的。

(4)定义结构体overlay_control_device_t。此结构体定义了一个control device,里面的成员除了common 都是函数,这些函数就是我们需要去实现的,在实现的时候我们会基于这个结构体扩展出一个关于control device的context结构体,context结构体内部会扩充一些信息并且包含control device。common 每一个device都必须有,而且必须放到第一位,目的只是为了overlay_control_ device_t和hw_device_t做匹配。overlay_control_device_t的定义代码如下所示。

struct overlay_control_device_t {  struct hw_device_t common;  int (*get)(struct overlay_control_device_t *dev, int name);//建立设备  overlay_t* (*createOverlay)(struct overlay_control_device_t *dev,      uint32_t w, uint32_t h, int32_t format);//释放资源,分配的handle和control device的内存  void (*destroyOverlay)(struct overlay_control_device_t *dev,      overlay_t* overlay);//设置overlay 的显示范围。(如果是camera 的 preview, 那么 h、w 要和preview h、w 一致。)  int (*setPosition)(struct overlay_control_device_t *dev,      overlay_t* overlay,       int x, int y, uint32_t w, uint32_t h);//获取 overlay 的显示范围  int (*getPosition)(struct overlay_control_device_t *dev,      overlay_t* overlay,       int* x, int* y, uint32_t* w, uint32_t* h);  int (*setParameter)(struct overlay_control_device_t *dev,      overlay_t* overlay, int param, int value);  int (*stage)(struct overlay_control_device_t *dev, overlay_t* overlay);  int (*commit)(struct overlay_control_device_t *dev, overlay_t* overlay);};

(5)定义结构overlay_data_device_t。此结构和overlay_control_device_t类似。在具体使用上,overlay_control_device_t负责初始化、销毁和控制类的操作,overlay_data_device_t用于显示内存输出的数据操作。结构overlay_data_device_t的定义代码如下所示。

struct overlay_data_device_t {  struct hw_device_t common;//通过参数handle 来初始化 data device  int (*initialize)(struct overlay_data_device_t *dev,      overlay_handle_t handle);

//重新配置显示参数 w、h。使这两个参数生效我这里需要 close,然后重新

open  int (*resizeInput)(struct overlay_data_device_t *dev,      uint32_t w, uint32_t h);

//下面两个分别设置显示的区域和获取显示的区域,当播放的时候,需要根据坐标和宽高来定义如何显示这些数据

  int (*setCrop)(struct overlay_data_device_t *dev,      uint32_t x, uint32_t y, uint32_t w, uint32_t h) ;  int (*getCrop)(struct overlay_data_device_t *dev,    uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h) ;  int (*setParameter)(struct overlay_data_device_t *dev,      int param, int value);  int (*dequeueBuffer)(struct overlay_data_device_t *dev,         overlay_buffer_t *buf);  int (*queueBuffer)(struct overlay_data_device_t *dev,      overlay_buffer_t buffer);  void* (*getBufferAddress)(struct overlay_data_device_t *dev,      overlay_buffer_t buffer);  int (*getBufferCount)(struct overlay_data_device_t *dev);  int (*setFd)(struct overlay_data_device_t *dev, int fd);};

6.2.2 实现Overlay系统的硬件抽象层

在实现Overlay系统的硬件抽象层时,具体实现方法取决于硬件和驱动程序,根据设备需要进行处理。具体来说分为如下两种情况。

(1)FrameBuffer驱动程序方式。

在此方式下,需要先实现函数getBufferAddress(),再返回通过mmap获得FrameBuffer的指针即可。如果没有双缓冲的问题,不需要真正实现函数dequeueBuffer()和queueBuffer()。上述函数的实现文件是overlay.cpp,此文件被保存在如下目录中。

Hardware/qcom/display/liboverlay/overlay.cpp函数getBufferAddress()用于返回FrameBuffer内部显示的内存,通过mmap 获取内存地址。函数的实现代码如下所示。void* Overlay::getBufferAddress(overlay_buffer_t buffer){  if (mStatus != NO_ERROR) return NULL;  return mOverlayData->getBufferAddress(mOverlayData, buffer);}函数dequeueBuffer()和queueBuffer()的实现代码如下所示。status_t Overlay::dequeueBuffer(overlay_buffer_t* buffer){  if (mStatus != NO_ERROR) return mStatus;  return mOverlayData->dequeueBuffer(mOverlayData, buffer);}status_t Overlay::queueBuffer(overlay_buffer_t buffer){  if (mStatus != NO_ERROR) return mStatus;  return mOverlayData->queueBuffer(mOverlayData, buffer);}(2)Video for Linux 2方式。

如果使用Video for Linux 2的输出驱动,函数dequeueBuffer()和queueBuffer()和调用驱动时主要ioctl是一致的,即分别调用VIDIOC_QBUF和VIDIOC_DQBUF即可直接实现。至于其他的初始化工作,可以在initialize中进行处理。因为存在视频数据队列,所以此处处理的内容比一般的帧缓冲区要复杂,但是可以实现更高的性能。

由此可见,在某一个硬件系统中,Overlay的硬件层和Overlay系统的调用者都是特定实现的,所以只需匹配上下层代码即可实现,并不要一一满足每一个要求,各个接口可以根据具体情况来灵活使用。

6.2.3 实现接口

在Android系统中,Overlay系统提供了接口overlay,此接口用于叠加在主显示层上面的另外一个显示层。此叠加的显示层经常用作视频的输出或相机取景器的预览界面。文件Overlay.h的主要内部实现类是Overlay和OverlayRef。OverlayRef需要和Surface配合使用,通过 Isurface 可以创建出OverlayRef。RefBase的主要代码如下所示。

class Overlay : public virtual RefBase{public:  Overlay(const sp
& overlayRef);  void destroy();  //获取overlay handle,可以根据自己的需要扩展,扩展之后就有很多数据了  overlay_handle_t getHandleRef() const;  //获取framebuffer 用于显示的内存地址  status_t dequeueBuffer(overlay_buffer_t* buffer);  status_t queueBuffer(overlay_buffer_t buffer);  status_t resizeInput(uint32_t width, uint32_t height);  status_t setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h) ;  status_t getCrop(uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h) ;  status_t setParameter(int param, int value);  void* getBufferAddress(overlay_buffer_t buffer);  /*获取属性的信息*/  uint32_t getWidth() const;  uint32_t getHeight() const;  int32_t getFormat() const;  int32_t getWidthStride() const;  int32_t getHeightStride() const;  int32_t getBufferCount() const;  status_t getStatus() const;private:  virtual ~Overlay();  sp
mOverlayRef;  overlay_data_device_t *mOverlayData;  status_t mStatus;};

Overlay(const sp& overlayRef);

在上述代码中,通过surface来控制Overlay,也可以在不使用Overlay的情况下统一进行管理。此处是通过overlayRef来创建Overlay,一旦获取了Overlay就可以通过这个Overlay 来获取用来显示的Address地址,向Address中写入数据后就可以显示图像了。

转载地址:http://abfkm.baihongyu.com/

你可能感兴趣的文章
boot中 Quartz注入spring管理类失败
查看>>
性能,不是不重要,而是,它没有可维护性重要
查看>>
STP的作用和操作
查看>>
大话设计模式读书笔记4——模版方法模式
查看>>
access中求两表差集问题
查看>>
PYTHON2.Git
查看>>
OCP 11g认证052考试最新题库(带答案)-带38题
查看>>
模拟误删除InnoDB ibdata数据文件恢复
查看>>
9个offer,12家公司,35场面试,从微软到谷歌,应届计算机毕业生的2012求职之路(转)...
查看>>
asp.net core 2.2 根据PC端和移动端自动显示不同视图而不改变url地址
查看>>
LeetCode 341: Flatten Nested List Iterator
查看>>
easyui tabs页签显示在底部属性
查看>>
IIS7设置IP地址和域名限制
查看>>
Platforms/iPhoneSimulator.platform/Developer/usr/bin/g++-4.2 failed with exit code 1问题总结及解决方案...
查看>>
iOS,贝塞尔曲线(UIBezierPath)
查看>>
二维码生成类
查看>>
css 兼容性写法,CSS hack写法
查看>>
javascript新闻向上停顿1秒后继续滚动
查看>>
关于 IntelliJ IDEA 的Maven 版本修改
查看>>
1.OpenGLES——FBO方式的离屏渲染
查看>>