《精通Android 5 多媒体开发》——第6章,第6.2节分析硬件抽象层
本节书摘来自异步社区《精通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所示。
![](https://yqfile.alicdn.com/70a0cec0326e3dd64bfdc55c8a59ee9244247a20.png)
(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节分析硬件抽象层相关推荐
- 《精通Android 5 多媒体开发》——第6章,第6.1节视频系统结构
本节书摘来自异步社区<精通Android 5 多媒体开发>一书中的第6章,第6.1节视频系统结构,作者 王石磊,更多章节内容可以访问云栖社区"异步社区"公众号查看 6. ...
- 《精通Android 5 多媒体开发》——第22章,第22.3节开发一个屏保程序
本节书摘来自异步社区<精通Android 5 多媒体开发>一书中的第22章,第22.3节开发一个屏保程序,作者 王石磊,更多章节内容可以访问云栖社区"异步社区"公众号查 ...
- 《精通Android 5 多媒体开发》——第1章,第1.1节智能手机系统介绍
本节书摘来自异步社区<精通Android 5 多媒体开发>一书中的第1章,第1.1节1.1 智能手机系统介绍,作者 王石磊,更多章节内容可以访问云栖社区"异步社区"公众 ...
- 《精通Android 5 多媒体开发》——第6章,第6.3节实现Overlay硬件抽象层
本节书摘来自异步社区<精通Android 5 多媒体开发>一书中的第6章,第6.3节实现Overlay硬件抽象层,作者 王石磊,更多章节内容可以访问云栖社区"异步社区" ...
- 黄开宁:搞多媒体开发要掌握好信号处理、统计和数理分析
尽管有WebRTC和FFmpeg这样的超级工具,但多媒体开发的核心难点的难度并没有因此降低,这需要开发者掌握牢固的基础知识.LiveVideoStack专访了即构科技音视频技术资深架构师黄开宁,他对学 ...
- Web前端开发笔记——第二章 HTML语言 第二节 基本标签
目录 前言 一.标题标签 二.段落标签和段内换行 三.预留格式标签 四.行内组合标签 五.水平线标签 六.注释标签 七.空格字符 例题(创建一个网页) 结语 前言 本节主要讲解HTML的一些基本标签. ...
- Web前端开发笔记——第二章 HTML语言 第九节 框架标签、脚本标签
目录 一.框架标签 (一)显示目标页面 (二)规定大小的框架 (三)规定边框的框架 二.脚本标签 结语 一.框架标签 (一)显示目标页面 <iframe></iframe>标签 ...
- Web前端开发笔记——第二章 HTML语言 第一节 标签、元素、属性
目录 一.什么是HTML? 二.标签 (一)标签.元素的定义 (二)标签的嵌套 (三)标签的属性 (四)父元素.子元素.兄弟元素 三.HTML DOM树 结语 一.什么是HTML? HTML语言,即超 ...
- Web前端开发笔记——第二章 HTML语言 第四节 超链接标签
目录 前言 一.超链接标签 (一)链接其它子网页 (二)链接其它站点 (三)虚拟超链接 二.从当前页面链接到指定位置 三.链接的访问情况 四.在新窗口中打开链接 例题 结语 前言 本节介绍超链接标签即 ...
最新文章
- SAP MM 采购申请评估价格不能为0?
- 无线传输系统功率LCC功率补偿系统设计
- C51汇编伪指令 CSEG DSEG
- Android第二十期 - 微信的主体构架
- python six库_six库 解决python2的项目如何能够完全迁移到python3
- Ubuntu16.04下面壁纸切换软件variety设置
- equals 和 hashCode 到底有什么联系?一文告诉你
- Angular实现图片点击缩放组件
- Nmap配合Masscan实现高效率扫描资产
- 初学者没有搞明白的GOROOT,GOPATH,GOBIN,project目录
- 如何通过破解hash来获取管理员密码(转)
- Mysql学习总结(24)——MySQL多表查询合并结果和内连接查询
- atitit.安全的签名摘要 算法attilax总结
- oracle中怎么sqlprompt,自定义sqlplus登录过后的sqlprompt
- shell教你如何批量解压缩——unzip命令
- 为什么Word打印预览的跟实际的不一样呢
- 我想吃掉你的胰脏--影片--观后感
- c# Pdf文件加密和解密
- android app如何后台自启动,商家骑手端允许后台运行APP设置方法(安卓)
- 洛阳理工学院linux实验报告,谁来给我抄实验报告啊!这一张又一张写得。。。。...
热门文章
- Ubuntu 10.04下安装Google拼音输入法
- Rstudio中ADF检验代码
- Photoshop (PS软件下载) 2019 香嘛?
- 学生用计算机怎么打出abc,Φ直径符号怎么打?多种方法教你直径符号怎么输入!...
- Tier 与 Layer 的区别
- BlinkCounter(眨眼计数器)
- 女子偷师男子学校,变身区块链开发工程师,却说: “这次女人不会再缺席了!”...
- 【医疗健康项目】传智健康项目(五)
- 4个影响缓存命中率的因素,你知道几个?
- Prefab优化:向预制体打出最有效的组合拳