开发者论坛
标题:
OpenHarmony之 Wi-Fi Display介绍
[打印本页]
作者:
admin
时间:
2024-6-27 16:20
标题:
OpenHarmony之 Wi-Fi Display介绍
[md]**Wi-Fi Display****是什么?**
Wi-Fi Display(缩写为WFD)经常和Miracast联系在一起。实际上,Miracast是Wi-Fi联盟(Wi-Fi Alliance)对支持WFD功能的设备的认证F名称。通过Miracast认证的设备将在最大程度内保持对WFD功能的支持和兼容。所以WFD是一个Miracast的规范。
# WFD涉及的协议和技术
![image.png](data/attachment/forum/202406/27/161414mr58ra7z0k50j02x.png "image.png")
从图中可以发现,WFD主要涉及以下几个技术:
1.音视频编解码
2.视频格式muxer和demuxer
3.RTP封包与解包
4.TCP,UDP网络
5.Wi-Fi p2p
6.UIBC(用户反向控制)
至于音视频采集和渲染是否带内,需要看具体实现。
首先WFD实际就是一个基于Wi-Fi p2p和C/S架构的流媒体程序。
服务端是source(投屏端),客户端是sink(被投端)
# WFD工作原理
下面是一个WFD的简单工作流程:
source端:
设备发现--->选择sink设备--->建立连接--->协商媒体信息--->传输音视频数据
sink端:
等待设备发现 ---> 处理源设备的连接 --->协商媒体信息--->接收音视频数据
# WFD开源实现(基于castengine\_WFD)
source端由于篇幅过长,就不介绍了,感兴趣的可以自己去研究源码,source主要流程:
1.初始化并使能p2p
2.发现p2p设备
3.连接sink设备后,会建立rtsp server(tcp监听端口7236),创建音视频传输的udp等。
4.source端采集手机画面然后进行编解码后通过rtp传输到sink。
接下来主要讲解下sink端流程:
目前我们已经大概了解了WFD工作原理了,作为sink端肯定是需要等待source端设备发现,但是这个前提是需要先开启p2p,如何开启呢?
castengine\_Wi-Fi\_display/tests/demo/wfd/wfd\_demo.cpp
![image.png](data/attachment/forum/202406/27/161440s2aawal2f5fieagx.png "image.png")
这里Init函数主要是创建一个wfd sink,并且设置一些连接相关的回调函数。
client\_->Start()函数里就是使能Wi-Fi p2p了,这样source端才能发现设备。
castengine\_wifi\_display\\services\\impl\\scene\\wfd\\wfd\_sink\_scene.cpp
![image.png](data/attachment/forum/202406/27/161501wueuufbu7a31brej.png "image.png")
最终上面的Start会调用到这里,这里首先先获取p2p当前状态,然后会开启p2p。
如果此时source端已经选择了sink设备,这时候p2p连接建立后sink端怎么知道呢?
这个就要回到刚才的Init函数了,Init里会设置listener,然后通过回调获取状态。
castengine\_wifi\_display\\tests\\demo\\wfd\\wfd\_demo.cpp
![image.png](data/attachment/forum/202406/27/161522qyhg18w0ss09gh9g.png "image.png")
可以看到这里处理了miracast设备的连接与断开。
如果此时miracast设备连接了,接下来该做什么呢?
显然,从上图中的demo里可以看到接下来就是播放投屏端的音视频数据了。由于demo为了简单,所以这里直接设置了媒体格式,而不是协商,但是这并不影响我们分析流程。接下来看sink端如何播放显示音视频数据。
1. 调用AppendSurface
2. 调用Play
AppendSurface函数主要工作:
```
1. 创建了视频解码器
2. 创建了视频播放线程
3. 等待用户播放
Play函数主要工作:
1. 根据需要创建音频解码器
2. 创建音频播放线程
3. 设置播放状态为正在播放
AppendSurface具体工作流程如下:
从用户APP调用AppendSurface开始,通过IPC调用,最终这个函数会调用到下面
castengine\_wifi\_display\\services\\mediaplayer\\src\\media\_controller.cpp
![image.png](data/attachment/forum/202406/27/161550ep699e7g6vcdvg2c.png "image.png")
videoPlayController->Start(dispatcher)实现如下
castengine\_wifi\_display\\services\\mediaplayer\\src\\video\_play\_controller.cpp
![image.png](data/attachment/forum/202406/27/161610yozj2b3c727tt2q2.png "image.png")
可以看到这里会打开视频解码器,并且创建视频播放线程。并且videoPlayController->Start(dispatcher)的执行是通过isPlaying\_变量控制。
接下来看下播放线程里主要做了什么工作
![image.png](data/attachment/forum/202406/27/161630ticcvfzvwn9zhi3z.png "image.png")
```可以看到播放线程主要做两件事:
1. 读取投屏端发过来的视频数据
2. 处理视频数据
![image.png](data/attachment/forum/202406/27/161649m5s5505u4xucgcxo.png "image.png")
这里解码视频数据。怎么把数据送给解码器解码呢?
castengine\_wifi\_display\\services\\codec\\src\\video\_sink\_decoder.cpp
![image.png](data/attachment/forum/202406/27/161714w2msqztr0rmf2556.png "image.png")
可以看到先是拿到一块解码器的可用输入buffer,然后送去解码。
那么解码后的数据从哪里拿到呢?
其实是通过回调来拿到解码后数据
![image.png](data/attachment/forum/202406/27/161742linpnsiqkznszzjy.png "image.png")
当解码器初始化的时候会设置一些回调用。具体可以看代码。
最后这里会调用OnVideoDataDecoded,把解码后的数据拿去渲染。
castengine\_wifi\_display\\services\\mediaplayer\\src\\video\_play\_controller.cpp
![image.png](data/attachment/forum/202406/27/161803nttbtwzc3bz4zco4.png "image.png")
这里OnVideoDataDecoded回调拿到数据后就开始渲染视频数据到surface上。
Play具体工作流程如下:
从用户APP调用Play开始,通过IPC调用,最终这个函数会调用到下面
![image.png](data/attachment/forum/202406/27/161827jotlziohiihzvczi.png "image.png")
可以看到最主要的工作就是:
1. 开启音频播放线程
2. 让音视频播放线程工作,通过置为isPlaying\_到true控制。
# 总结:
以上就是WFD的sink端大概工作流程,其实就是一个Wi-Fi p2p和一个视频播放器的结合。
# 参考链接
[
https://gitee.com/openharmony/castengine
\_wifi\_display?\_from=gitee\_search](
https://gitee.com/openharmony/ca ... ?_from=gitee_search
)
```
[/md]
作者:
admin
时间:
2024-7-5 11:13
提示:
该帖被管理员或版主屏蔽
作者:
yeyao2
时间:
2024-7-8 20:59
2131231231231
作者:
yeyao2
时间:
2024-7-8 20:59
2131231231231
作者:
yeyao2
时间:
2024-7-8 20:59
回复
yeyao2
: 3333333
欢迎光临 开发者论坛 (https://oh-test.qingcheng100.cn/)
Powered by Discuz! X3.5