OpenHarmony 分布式屏幕示例

前言

大家有华为手机的同学应该对华为超级终端中那个可以控制其他鸿蒙设备的功能印象深刻吧

今天我就来详细讲解一下 HarmonyOS 底层的 OpenHarmonyOS 的分布式屏幕(distributedhardware_distributed_screen)

有兴趣的同学可以去看看官方的代码仓库

[distributedhardware_distributed_screen: Distributed Screen | 分布式屏幕]

工作原理

什么是分布式屏幕

分布式屏幕介绍

硬件互联 设备能够与其他具有屏幕的设备交互

  • 手机使用电视的屏幕进行观影
  • 电脑使用平板的屏幕作为拓展屏幕使用
  • 手机使用车载屏进行导航
  • 等等 ···

设备与设备间的硬件将被虚拟化一个硬件池 从而相互调用

20221218142057

分布式屏幕提供的系统能力 如下图

分布式屏幕模型介绍

系统架构如下图

显示系统模型

原理介绍

还是继续放图了

  • 分布式屏幕服务会根据远端设备屏幕信息在本地创建虚拟Screen
  • 分布式屏幕基于”Display-Screen”映射模型设置编解码参数和远端显示的区域
  • 在屏幕映射的过程中 虚拟Screen 的屏幕数据被编码后通过 分布式软总线 进行数据传输
  • 远端屏幕在收到解码视频流后 进行显示渲染输出

开发流程-代码片段

如何使应用接入或使用分布式屏幕

镜像投屏

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 获取 screen 列表
std::vector<sptr<Screen>> allScreen = ScreenManager::GetInstance().GetAllScreens();

// 选择待镜像的远程目标 screen
uint64_t remoteScreenId = selectRemoteScreenId(allScreens);
/* selectRemoteScreenId由个人自定义实现 遍历allScreens信息筛选远程目标
* 接口说明
* IsReal 返回true时 代表为本地screen / false为远程screen
* GetName 当返回screen的id 包含远程设备信息
* GetId 返回screenId
*/

// 选择待镜像的本地screen
sptr<Display> defaultDisplay = DisplayManager::GetInstance().GetDefaultDisplay();
uint64_t localScreenId = defaultDisplay->GetScreenId();

// 调用接口并启动镜像投屏
std::vector<uint64_t> mirrorIds;
mirrorIds.push_back(remoteScreenId);
ScreenManager::GetInstance().MakeMirror(localScreenId, mirrorIds);

// 停止
std::vector<uint64_t> stopMirrorIds;
stopMirrorIds.push_back(remoteScreenId);
ScreenManager::GetInstance().RemoveVirtualScreenFromGroup(stopMirrorIds);

拓展投屏

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 获取 screen列表
std::vector<sptr<Screen>> allScreens = ScreenManager::GetInstance().GetAllScreens();

// 选择待投射的远程目标
uint64_t remoteScreenId = selectRemoteScreenId(allScreens);
/* selectRemoteScreenId由个人自定义实现 遍历allScreens信息筛选远程目标
* 接口说明
* IsReal 返回true时 代表为本地screen / false为远程screen
* GetName 当返回screen的id 包含远程设备信息
* GetId 返回screenId
*/

// 选择待拓展的本地screen
sptr<Display> defaultDisplay = DisplayManager::GetInstance().GetDefaultDisplay();
uint64_t localScreenId = defaultDisplay->GetScreenId();

// 拓展屏幕与本地屏幕的位置关系
std::vector<ExpandOption> options = {
{localScreenId, 0, 0},
{remoteScreenId, defaultDisplay->GetWidth(), 0}
};

// 调用结构启动拓展投屏
ScreenManager::GetInstance().MakeExpand(options);

// 停止投屏
std::vector<uint64_t> stopExpandIds;
stopExpandIds.push_back(remoteScreenId);
screenManager::GetInstance().RemoveVirualScreenFromGroup(stopExpandIds);

Github 仓库

h.265版本将在我的github仓库提交测试

link: MagicstMagoo/distributedhardware_distributed_screen at h265-vstream