Android WifiDisplay分析三:RTSP交互以及数据传输.docx_第1页
Android WifiDisplay分析三:RTSP交互以及数据传输.docx_第2页
Android WifiDisplay分析三:RTSP交互以及数据传输.docx_第3页
Android WifiDisplay分析三:RTSP交互以及数据传输.docx_第4页
Android WifiDisplay分析三:RTSP交互以及数据传输.docx_第5页
已阅读5页,还剩8页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

前面我们分析到WifiDisplaySource会调用ANetworkSession的接口去创建一个socket,并在这个socket上监听是否有客户端的连接请求。先来看看Wifi Display规范的一些流程图:从之前的一篇文章中,当ANetworkSession创建好RTSP的listen socket后,就会把它加入到selelct中等待对方的连接,那我们首先来看ANetworkSession的threadLoop方法:javaview plaincopy1. voidANetworkSession:threadLoop()2. 3. intres=select(maxFd+1,&rs,&ws,NULL,NULL/*tv*/);4. 5. 6. Mutex:AutolockautoLock(mLock);7. 8. ListspsessionsToAdd;9. 10. for(size_ti=mSessions.size();res0&i-0;)11. constsp&session=mSessions.valueAt(i);12. 13. ints=session-socket();14. 15. if(sisRTSPServer()|session-isTCPDatagramServer()25. structsockaddr_inremoteAddr;26. socklen_tremoteAddrLen=sizeof(remoteAddr);27. 28. intclientSocket=accept(29. s,(structsockaddr*)&remoteAddr,&remoteAddrLen);30. 31. if(clientSocket=0)32. status_terr=MakeSocketNonBlocking(clientSocket);33. 34. if(err!=OK)35. 36. else37. in_addr_taddr=ntohl(remoteAddr.sin_addr.s_addr);38. 39. ALOGI(incomingconnectionfrom%d.%d.%d.%d:%d40. (socket%d),41. (addr24),42. (addr16)&0xff,43. (addr8)&0xff,44. addr&0xff,45. ntohs(remoteAddr.sin_port),46. clientSocket);47. 48. spclientSession=49. newSession(50. mNextSessionID+,51. Session:CONNECTED,52. clientSocket,53. session-getNotificationMessage();54. 55. clientSession-setMode(56. session-isRTSPServer()57. ?Session:MODE_RTSP58. :Session:MODE_DATAGRAM);59. 60. sessionsToAdd.push_back(clientSession);61. 62. else63. ALOGE(acceptreturnederror%d(%s),64. errno,strerror(errno);65. 66. 67. 68. 69. while(!sessionsToAdd.empty()70. spsession=*sessionsToAdd.begin();71. sessionsToAdd.erase(sessionsToAdd.begin();72. 73. mSessions.add(session-sessionID(),session);74. 75. ALOGI(addedclientSession%d,session-sessionID();76. 77. 上面在selelct循环中,首先只有刚创建的RTSP的listen socket,接着如果有客户端的连接请求,就会跳出select语句,然后调用accept去接收对方的连接。接着会去创建一个新的Session会话,我们去看它的构造函数:javaview plaincopy1. ANetworkSession:Session:Session(2. int32_tsessionID,3. Statestate,4. ints,5. constspify)6. :mSessionID(sessionID),7. mState(state),8. mMode(MODE_DATAGRAM),9. mSocket(s),10. mNotify(notify),11. mSawReceiveFailure(false),12. mSawSendFailure(false),13. mUDPRetries(kMaxUDPRetries),14. mLastStallReportUs(-1ll)15. if(mState=CONNECTED)16. structsockaddr_inlocalAddr;17. socklen_tlocalAddrLen=sizeof(localAddr);18. 19. intres=getsockname(20. mSocket,(structsockaddr*)&localAddr,&localAddrLen);21. CHECK_GE(res,0);22. 23. structsockaddr_inremoteAddr;24. socklen_tremoteAddrLen=sizeof(remoteAddr);25. 26. res=getpeername(27. mSocket,(structsockaddr*)&remoteAddr,&remoteAddrLen);28. CHECK_GE(res,0);29. 30. spmsg=mNotify-dup();31. msg-setInt32(sessionID,mSessionID);32. msg-setInt32(reason,kWhatClientConnected);33. msg-setString(server-ip,localAddrString.c_str();34. msg-setInt32(server-port,ntohs(localAddr.sin_port);35. msg-setString(client-ip,remoteAddrString.c_str();36. msg-setInt32(client-port,ntohs(remoteAddr.sin_port);37. msg-post();38. 39. 这里的状态mState为CONNECTED,所以会构建一个AMessage并post出去,由前一章的知识,我们知道这里的mNotify是一个kWhatRTSPNotify消息,会在WifiDisplaySource调用createRTSPServer时传进来的一个参数,所以这里创建的AMessage最终还是会被WifiDisplaySource去处理,跳过中间AMessage、ALooperRoster、ALooper的调用关系,我们直接到WifiDisplaySource的onMessageReceived去看如何处理:javaview plaincopy1. casekWhatRTSPNotify:2. 3. int32_treason;4. CHECK(msg-findInt32(reason,&reason);5. 6. switch(reason)7. caseANetworkSession:kWhatError:8. 9. 10. break;11. 12. 13. caseANetworkSession:kWhatClientConnected:14. 15. int32_tsessionID;16. CHECK(msg-findInt32(sessionID,&sessionID);17. 18. if(mClientSessionID0)19. ALOGW(Aclienttriedtoconnect,butwealready20. haveone.);21. 22. mNetSession-destroySession(sessionID);23. break;24. 25. 26. CHECK_EQ(mState,AWAITING_CLIENT_CONNECTION);27. 28. CHECK(msg-findString(client-ip,&mClientInfo.mRemoteIP);29. CHECK(msg-findString(server-ip,&mClientInfo.mLocalIP);30. 31. if(mClientInfo.mRemoteIP=mClientInfo.mLocalIP)32. /Disallowconnectionsfromthelocalinterface33. /forsecurityreasons.34. mNetSession-destroySession(sessionID);35. break;36. 37. 38. CHECK(msg-findInt32(39. server-port,&mClientInfo.mLocalPort);40. mClientInfo.mPlaybackSessionID=-1;41. 42. mClientSessionID=sessionID;43. 44. ALOGI(Wenowhaveaclient(%d)connected.,sessionID);45. 46. mState=AWAITING_CLIENT_SETUP;47. 48. status_terr=sendM1(sessionID);49. CHECK_EQ(err,(status_t)OK);50. break;51. 52. 53. caseANetworkSession:kWhatData:54. 55. 56. break;57. 58. 59. caseANetworkSession:kWhatNetworkStall:60. 61. break;62. 63. 64. default:65. TRESPASS();66. 67. break;68. 这里的reason是kWhatClientConnected,跳过前面不必要的case语句。如果先前已经连上其它的Sink device,这里就先断开之前的连接;如果没有,将新的SessionID赋予给mClientSessionID,并更改状态为AWAITING_CLIENT_SETUP,接着去看sendM1消息,这时候就要开始WifiDisplay M1M7消息的发送了。下面列举M1M7消息的格式,有兴趣的可以去对照代码分析,我们后面着重分析M6(SetUp)和M7(Play)两个消息。M1 reqeust:OPTIONS * RTSP/1.0Date: Tue, 29 Fri 2014 02:41:24 +0000Server: stagefright/1.2 (Linux;Android4.4)CSeq: 1Require: org.wfa.wfd1.0M1 respose:RTSP/1.0 200 OKCSeq: 1Date: Fri, Jan 01 2014 09:02:37 GMTPublic: org.wfa.wfd1.0, GET_PARAMETER, SET_PARAMETERM2 request:OPTIONS * RTSP/1.0CSeq: 2Require: org.wfa.wfd1.0M2 response:RTSP/1.0 200 OKDate: Tue, 29 Fri 2014 02:41:25 +0000Server: stagefright/1.2 (Linux;Android 4.3)CSeq: 2Public: org.wfa.wfd1.0, SETUP, TEARDOWN, PLAY, PAUSE, GET_PARAMETER, SET_PARAMETERM3 request:GET_PARAMETER rtsp:/localhost/wfd1.0 RTSP/1.0Date: Tue, 29 Fri 2014 02:41:25 +0000Server: stagefright/1.2 (Linux;Android 4.3)CSeq: 2Content-Type: text/parametersContent-Length: 83wfd_content_protectionwfd_video_formatswfd_audio_codecswfd_client_rtp_portsM3 response:RTSP/1.0 200 OKCSeq: 2Content-Length: 124Content-Type: text/parameterswfd_audio_codecs: LPCM 00000003 00, AAC 00000007 00wfd_video_formats: 00 00 02 02 0000FFFF 0FFFFFFF 00000FFF 00 0000 0000 01 none nonewfd_content_protection: nonewfd_client_rtp_ports: RTP/AVP/UDP;unicast 19990 0 mode=playM4 request:SET_PARAMETER rtsp:/localhost/wfd1.0 RTSP/1.0Date: Tue, 29 Fri 2014 02:41:25 +0000Server: stagefright/1.2 (Linux;Android 4.3)CSeq: 3Content-Type: text/parametersContent-Length: 247wfd_video_formats: 00 00 02 02 00000020 00000000 00000000 00 0000 0000 00 none nonewfd_audio_codecs: AAC 00000001 00wfd_presentation_URL: rtsp:/00/wfd1.0/streamid=0 nonewfd_client_rtp_ports: RTP/AVP/UDP;unicast 19990 0 mode=playM4 response:RTSP/1.0 200 OKCSeq: 3M5 request:SET_PARAMETER rtsp:/localhost/wfd1.0 RTSP/1.0Date: Tue, 29 Fri 2014 02:41:25 +0000Server: stagefright/1.2 (Linux;Android 4.3)CSeq: 4Content-Type: text/parametersContent-Length: 27wfd_trigger_method: SETUPM5 response:RTSP/1.0 200 OKCSeq: 4M6 request:SETUP rtsp:/00/wfd1.0/streamid=0 RTSP/1.0CSeq: 3Transport: RTP/AVP/UDP;unicast;client_port=19990M6 response:RTSP/1.0 200 OKDate: Tue, 29 Fri 2014 02:41:25 +0000Server: stagefright/1.2 (Linux;Android 4.3)CSeq: 3Session: 988982966;timeout=30Transport: RTP/AVP/UDP;unicast;client_port=19990;server_port=22220我们先来看处理M6 request的方法,代码在onSetupRequest中:javaview plaincopy1. status_tWifiDisplaySource:onSetupRequest(2. int32_tsessionID,3. int32_tcseq,4. constsp&data)5. CHECK_EQ(sessionID,mClientSessionID);6. if(mClientInfo.mPlaybackSessionID!=-1)7. sendErrorResponse(sessionID,400BadRequest,cseq);8. returnERROR_MALFORMED;9. 10. 11. int32_tplaybackSessionID=makeUniquePlaybackSessionID();12. 13. spnotify=newAMessage(kWhatPlaybackSessionNotify,id();14. notify-setInt32(playbackSessionID,playbackSessionID);15. notify-setInt32(sessionID,sessionID);16. 17. spplaybackSession=18. newPlaybackSession(19. mNetSession,notify,mInterfaceAddr,mHDCP,mMediaPath.c_str();20. 21. looper()-registerHandler(playbackSession);22. 23. AStringuri;24. data-getRequestField(1,&uri);25. 26. if(strncasecmp(rtsp:/,uri.c_str(),7)27. sendErrorResponse(sessionID,400BadRequest,cseq);28. returnERROR_MALFORMED;29. 30. 31. if(!(uri.startsWith(rtsp:/)&uri.endsWith(/wfd1.0/streamid=0)32. sendErrorResponse(sessionID,404Notfound,cseq);33. returnERROR_MALFORMED;34. 35. 36. RTPSender:TransportModertcpMode=RTPSender:TRANSPORT_UDP;37. if(clientRtcpinit(42. mClientInfo.mRemoteIP.c_str(),43. clientRtp,44. rtpMode,45. clientRtcp,46. rtcpMode,47. mSinkSupportsAudio,48. mUsingPCMAudio,49. mSinkSupportsVideo,50. mChosenVideoResolutionType,51. mChosenVideoResolutionIndex,52. mChosenVideoProfile,53. mChosenVideoLevel);54. 55. if(err!=OK)56. looper()-unregisterHandler(playbackSession-id();57. playbackSession.clear();58. 59. 60. mClientInfo.mPlaybackSessionID=playbackSessionID;61. mClientInfo.mPlaybackSession=playbackSession;62. 63. mState=AWAITING_CLI

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论