本节书摘来自异步社区《精通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所示。


(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 deviceint (*initialize)(struct overlay_data_device_t *dev,overlay_handle_t handle);

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

 openint (*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>& 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<OverlayRef> mOverlayRef;overlay_data_device_t *mOverlayData;status_t mStatus;
};

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

《精通Android 5 多媒体开发》——第6章,第6.2节分析硬件抽象层相关推荐

  1. 《精通Android 5 多媒体开发》——第6章,第6.1节视频系统结构

    本节书摘来自异步社区<精通Android 5 多媒体开发>一书中的第6章,第6.1节视频系统结构,作者 王石磊,更多章节内容可以访问云栖社区"异步社区"公众号查看 6. ...

  2. 《精通Android 5 多媒体开发》——第22章,第22.3节开发一个屏保程序

    本节书摘来自异步社区<精通Android 5 多媒体开发>一书中的第22章,第22.3节开发一个屏保程序,作者 王石磊,更多章节内容可以访问云栖社区"异步社区"公众号查 ...

  3. 《精通Android 5 多媒体开发》——第1章,第1.1节智能手机系统介绍

    本节书摘来自异步社区<精通Android 5 多媒体开发>一书中的第1章,第1.1节1.1 智能手机系统介绍,作者 王石磊,更多章节内容可以访问云栖社区"异步社区"公众 ...

  4. 《精通Android 5 多媒体开发》——第6章,第6.3节实现Overlay硬件抽象层

    本节书摘来自异步社区<精通Android 5 多媒体开发>一书中的第6章,第6.3节实现Overlay硬件抽象层,作者 王石磊,更多章节内容可以访问云栖社区"异步社区" ...

  5. 黄开宁:搞多媒体开发要掌握好信号处理、统计和数理分析

    尽管有WebRTC和FFmpeg这样的超级工具,但多媒体开发的核心难点的难度并没有因此降低,这需要开发者掌握牢固的基础知识.LiveVideoStack专访了即构科技音视频技术资深架构师黄开宁,他对学 ...

  6. Web前端开发笔记——第二章 HTML语言 第二节 基本标签

    目录 前言 一.标题标签 二.段落标签和段内换行 三.预留格式标签 四.行内组合标签 五.水平线标签 六.注释标签 七.空格字符 例题(创建一个网页) 结语 前言 本节主要讲解HTML的一些基本标签. ...

  7. Web前端开发笔记——第二章 HTML语言 第九节 框架标签、脚本标签

    目录 一.框架标签 (一)显示目标页面 (二)规定大小的框架 (三)规定边框的框架 二.脚本标签 结语 一.框架标签 (一)显示目标页面 <iframe></iframe>标签 ...

  8. Web前端开发笔记——第二章 HTML语言 第一节 标签、元素、属性

    目录 一.什么是HTML? 二.标签 (一)标签.元素的定义 (二)标签的嵌套 (三)标签的属性 (四)父元素.子元素.兄弟元素 三.HTML DOM树 结语 一.什么是HTML? HTML语言,即超 ...

  9. Web前端开发笔记——第二章 HTML语言 第四节 超链接标签

    目录 前言 一.超链接标签 (一)链接其它子网页 (二)链接其它站点 (三)虚拟超链接 二.从当前页面链接到指定位置 三.链接的访问情况 四.在新窗口中打开链接 例题 结语 前言 本节介绍超链接标签即 ...

最新文章

  1. SAP MM 采购申请评估价格不能为0?
  2. 无线传输系统功率LCC功率补偿系统设计
  3. C51汇编伪指令 CSEG DSEG
  4. Android第二十期 - 微信的主体构架
  5. python six库_six库 解决python2的项目如何能够完全迁移到python3
  6. Ubuntu16.04下面壁纸切换软件variety设置
  7. equals 和 hashCode 到底有什么联系?一文告诉你
  8. Angular实现图片点击缩放组件
  9. Nmap配合Masscan实现高效率扫描资产
  10. 初学者没有搞明白的GOROOT,GOPATH,GOBIN,project目录
  11. 如何通过破解hash来获取管理员密码(转)
  12. Mysql学习总结(24)——MySQL多表查询合并结果和内连接查询
  13. atitit.安全的签名摘要 算法attilax总结
  14. oracle中怎么sqlprompt,自定义sqlplus登录过后的sqlprompt
  15. shell教你如何批量解压缩——unzip命令
  16. 为什么Word打印预览的跟实际的不一样呢
  17. 我想吃掉你的胰脏--影片--观后感
  18. c# Pdf文件加密和解密
  19. android app如何后台自启动,商家骑手端允许后台运行APP设置方法(安卓)
  20. 洛阳理工学院linux实验报告,谁来给我抄实验报告啊!这一张又一张写得。。。。...

热门文章

  1. Ubuntu 10.04下安装Google拼音输入法
  2. Rstudio中ADF检验代码
  3. Photoshop (PS软件下载) 2019 香嘛?
  4. 学生用计算机怎么打出abc,Φ直径符号怎么打?多种方法教你直径符号怎么输入!...
  5. Tier 与 Layer 的区别
  6. BlinkCounter(眨眼计数器)
  7. 女子偷师男子学校,变身区块链开发工程师,却说: “这次女人不会再缺席了!”...
  8. 【医疗健康项目】传智健康项目(五)
  9. 4个影响缓存命中率的因素,你知道几个?
  10. Prefab优化:向预制体打出最有效的组合拳