Android 4.2 Wifi Display核心分析 (一)

本文深入探讨Android 4.2中WifiDisplay设备连接和数据流建立的流程。从Source端的初始化、建立RTSP连接,到Sink端的响应,分析了ANetworkSession线程如何管理和通信。重点关注了RTSP服务端创建、客户端连接请求以及数据交换的关键步骤,揭示了Wi-Fi显示技术在Android系统中的实现原理。
摘要由CSDN通过智能技术生成
转载

        主要介绍了有关WifiDisplay设备连接和建立数据流的流程,这一回将接着向底层前进。由于涉及的内容较多,这里仅仅理清一个大概的头绪,细节的部分将不再展开,如果有什么错误的地方我会及时更正。

       当Source端通过RemoteDisplay.cpp的构造函数注册了Wifidisplay处理线程,并且ANetworkSession初始化 了通信所用的数据管道并且开始监听数据流变化后,Source端将通过函数mSource->start(iface)开始建立RTSP连接并且向 Sink端传递数据流。接下来,将具体分析其流程。mSource->start(iface)的具体实现在以下文件,

 frameworks/av/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp

  1. status_t WifiDisplaySource::start(const char *iface) {  
  2.     CHECK_EQ(mState, INITIALIZED);  
  3.   
  4.     sp<AMessage> msg = new AMessage(kWhatStart, id());  
  5.     msg->setString("iface", iface);  
  6.   
  7.     sp<AMessage> response;  
  8.     status_t err = msg->postAndAwaitResponse(&response);  
  9.   
  10.     if (err != OK) {  
  11.         return err;  
  12.     }  
  13.   
  14.     if (!response->findInt32("err", &err)) {  
  15.         err = OK;  
  16.     }  
  17.   
  18.     return err;  
  19. }  

该函数首先通过CHECK_EQ来判断当前Source端状态是否为 INITIALIZED,如果是将通过 AMessage创建 标识为kWhatStart的消息,用于在onMessageReceived处理分支中进行匹 配,msg->setString(“iface”,iface)用于在传递消息过程中携带网络地址端口信息, msg->postAndAwaitResponse用于返回相应结果。这种方式在Android的流媒体类中相当常见,是一种异步消息处理框架。 与该框架相关的类主要有ALooper、AHandler、ALooperRoster等,具体请见这里

接下来,我们来看看当Source端接收到kWhatStart的消息后做何种处理,

  1. void WifiDisplaySource::onMessageReceived(const sp<AMessage> &msg) {  
  2.     switch (msg->what()) {  
  3.         case kWhatStart:  
  4.         {  
  5.             uint32_t replyID;  
  6.             CHECK(msg->senderAwaitsResponse(&replyID));  
  7.   
  8.             AString iface;  
  9.             CHECK(msg->findString("iface", &iface));  
  10.   
  11.             status_t err = OK;  
  12.   
  13.             ssize_t colonPos = iface.find(":");  //寻找“:”所在位置  
  14.   
  15.             unsigned long port;  
  16.   
  17.             if (colonPos >= 0) {  
  18.                 const char *s = iface.c_str() + colonPos + 1;  
  19.   
  20.                 char *end;  
  21.                 port = strtoul(s, &end, 10);  //得到port号  
  22.   
  23.                 if (end == s || *end != '\0' || port > 65535) {  
  24.                     err = -EINVAL;  
  25.                 } else {  
  26.                     iface.erase(colonPos, iface.size() - colonPos);    
  27.                 }  
  28.             } else {  
  29.                 port = kWifiDisplayDefaultPort;  
  30.             }  
  31.   
  32.             if (err == OK) {  
  33.                 if (inet_aton(iface.c_str(), &mInterfaceAddr) != 0) {  //将IP地址转化为32位的网络序列IP地址  
  34.                     sp<AMessage> notify = new AMessage(kWhatRTSPNotify, id());//建立标识为 kWhatRTSPNotify的消息作为参数传递  
  35.   
  36.                     err = mNetSession->createRTSPServer(  
  37.                             mInterfaceAddr, port, notify, &mSessionID);  
  38.                 } else {  
  39.                     err = -EINVAL;  
  40.                 }  
  41.             }  
  42.   
  43.             if (err == OK) {  
  44.                 mState = AWAITING_CLIENT_CONNECTION;  
  45.             }  
  46.   
  47.             sp<AMessage> response = new AMessage;  
  48.             response->setInt32("err", err);  
  49.             response->postReply(replyID);  
  50.             break;  
  51.         }  
  52.       ...  
  53.    }  
  54. }  

首先,可以看到当Source端接收到消息标识为 kWhatStart的消息后,消息指针msg会通过函数msg->senderAwaitsResponse(&replyID)获取对 应于postAndAwaitResponse函数的响应标识,并把处理中的错误信息作为消息载体通过 response->postReply(replyID)传递回start(iface)函数。然后,该处理函数将接收到的网络地址端口信息 iface拆分为IP地址和端口两个部分,并且利用 createRTSPServer创建RTSP服务端,函数会返回相应的Session编号。如果RTSP服务端创建成功,则将Source端状态更改为 AWAITING_CLIENT_CONNECTION,表示等待客户端连接。

 接着看创建RTSP服务端具体做了哪些动作,

frameworks/av/media/libstagefright/wifi-display/ANetworkSession.cpp

  1. status_t ANetworkSession::createRTSPServer(  
  2.         const struct in_addr &addr, unsigned port,  
  3.         const sp<AMessage> notify, int32_t *sessionID) {  
  4.     return createClientOrServer(  
  5.             kModeCreateRTSPServer,  
  6.             &addr,  
  7.             port,  
  8.             NULL /* remoteHost */,  
  9.             0 /* remotePort */,  
  10.             notify,  
  11.             sessionID);  
  12. }  

可以看到函数createRTSPServer具体又调用了 cre

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值