当前位置:   article > 正文

使用live555客户端源码遇到的问题及解决方法_live555 推送rtsp相机无响应

live555 推送rtsp相机无响应

使用live555客户端源码拉rtsp流遇到两个问题,正常测试拉取海康摄像头没问题;

1.拉有些厂商的rtsp流会间隔一段时间断开连接;

2.与大华摄像头建立连接时,发送DESCRIBE命令后很长时间服务器端才返回;

问题一:

问题描述:rtsp流间隔一段时间后总是中断,因为有断开重连机制,所以画面一直是卡住,然后正常播放一段时间,这样循环。

原因描述:由于没有与服务器端建立心跳导致;有些服务器会检测心跳,有的不会,当检测心跳时长时间超过一定值后,服务器端会断开连接; 

解决方法:定期发送心跳GET_PARAMETER;

代码:

  1. TaskToken m_HeartBeatCommandTask;
  2. Boolean bsupportGetParamter = False;
  3. RTSPClient * XXXX::StartRTSPClient(char const * rtspURL)
  4. {
  5. RTSPClient * pRtspClient = NULL;
  6. pRtspClient = myRTSPClient::createNew(*env, rtspURL, 1, NULL);
  7. if (pRtspClient)
  8. {
  9. pRtspClient->sendOptionsCommand(continueAfterOption);
  10. }
  11. return pRtspClient;
  12. }
  13. int XXXX::StopRTSPClient(RTSPClient * rtspClient)
  14. {
  15. bsupportGetParamter = False;
  16. env->taskScheduler().unscheduleDelayedTask(m_HeartBeatCommandTask);
  17. m_HeartBeatCommandTask = NULL;
  18. return 0;
  19. }
  20. void XXXX::continueAfterOption()
  21. {
  22. /*...............*/
  23. bsupportGetParamter = RTSPOptionIsSupported("GET_PARAMETER", "");
  24. sendDescribeCommand(continueAfterDESCRIBE);
  25. /*...............*/
  26. }
  27. void XXXX::continueAfterDESCRIBE(RTSPClient* rtspClient)
  28. {
  29. /*...............*/
  30. setupNextSubsession(rtspClient);
  31. /*...............*/
  32. }
  33. void XXXX::setupNextSubsession(RTSPClient* rtspClient)
  34. {
  35. /*...............*/
  36. //对ServerMediaSubsession发送SETUP命令,收到回复后回调continueAfterSETUP函数
  37. rtspClient->sendSetupCommand(*scs.subsession, continueAfterSETUP, False, True);
  38. /*...............*/
  39. // 成功与所有的ServerMediaSubsession建立了连接,现在发送PLAY命令
  40. rtspClient->sendPlayCommand(*scs.session, continueAfterPLAY, scs.session->absStartTime(), scs.session->absEndTime());
  41. /*...............*/
  42. }
  43. void XXXX::continueAfterSETUP(RTSPClient* rtspClient, )
  44. {
  45. /*...............*/
  46. //调用setupNextSubsession函数与下一个ServerMediaSubsession建立连接,
  47. //在setupNextSubsession函数中,会检查是否与所有的ServerMediaSubsession都建立了连接,
  48. //全部建立连接之后则发送PLAY命令请求开始传送数据,收到回复则调用continueAfterPLAY函数
  49. setupNextSubsession(rtspClient);
  50. }
  51. void XXXX::continueAfterPLAY(RTSPClient* rtspClient, int resultCode, char* resultString) {
  52. /*...............*/
  53. //发送play命令之后,设置定时发送心跳
  54. scheduleHeartBeatCommand(rtspClient);
  55. }
  56. void XXXX::continueAfterHeartBeatOption(RTSPClient* rtspClient)
  57. {
  58. scheduleHeartBeatCommand(rtspClient);
  59. }
  60. void XXXX::scheduleHeartBeatCommand(RTSPClient* rtspClient)
  61. {
  62. // 获取超时时间,设置超时一半的时间发送心跳
  63. unsigned delayMax = rtspClient->sessionTimeoutParameter();
  64. int64_t uSecondsToDelay = delayMax;
  65. uSecondsToDelay = uSecondsToDelay * 500000;
  66. m_HeartBeatCommandTask = env->taskScheduler().scheduleDelayedTask(uSecondsToDelay, sendHeartBeatCommand, rtspClient);
  67. }
  68. void XXXX::sendHeartBeatCommand(void* clientData)
  69. {
  70. // 支持GET_PARAMETER参数的话就发送GET_PARAMETER,不支持发送option
  71. // 发送成功之后在通过回调continueAfterHeartBeatOption重新设置定时,这样就进入了循环,一直在发送心跳
  72. if (bsupportGetParamter)
  73. {
  74. sendGetParameterCommand((*rtspClient->scs.session), continueAfterHeartBeatOption, NULL);
  75. }
  76. else
  77. {
  78. sendOptionsCommand(continueAfterHeartBeatOption);
  79. }
  80. }

问题二:

问题描述:发送option后收到回应,再次发送DESCRIBE后隔10s左右收到回应,建立连接时间较长;

 原因描述:使用live555 接收 有鉴权功能的IPC中的RTSP服务时 RTSP play 之前会有很长时间的延时 大概10秒左右;原因是我们的rtsp的url 可能是 这种形式的rtsp:\\usr:password@192.xxx.xxx.xxx\streamname;也就是说rtsp的url 是包含用户名和密码的。

借鉴连接:https://blog.csdn.net/u013008311/article/details/81585827

解决方法:RTSPClient 实例使用时sendDescribeCommand 使用

sendDescribeCommand(describecallback,Authenticator*);

修改之前代码:

  1. // 假设rtspURL的格式rtsp:\\usr:password@192.xxx.xxx.xxx\streamname
  2. RTSPClient * pRtspClient = NULL;
  3. pRtspClient = ourRTSPClient::createNew(*env, rtspURL, 1, NULL);
  4. if (pRtspClient)
  5. {
  6. pRtspClient->sendOptionsCommand(continueAfterOption);
  7. }

修改之后:

  1. // 先将rtsp:\\usr:password@192.xxx.xxx.xxx\streamname解析一下,
  2. // pUnauthorizedPath 的格式为rtsp:\\192.xxx.xxx.xxx\streamname
  3. char* pUsername = NULL;
  4. char* pPassword = NULL;
  5. char* pUnauthorizedPath = NULL;
  6. ParseRTSPURL(rtspURL, pUsername, pPassword, pUnauthorizedPath);
  7. if (pUsername != NULL && pPassword != NULL)
  8. pRtspClient = ourRTSPClient::createNew(*env, pUnauthorizedPath, 1, NULL);
  9. else
  10. pRtspClient = ourRTSPClient::createNew(*env, rtspURL, 1, NULL);
  11. if (pRtspClient)
  12. {
  13. if (pUsername != NULL && pPassword != NULL)
  14. {
  15. Authenticator authenticator(pUsername, pPassword, False);
  16. pRtspClient->sendOptionsCommand(continueAfterOption, &authenticator);
  17. }
  18. else
  19. {
  20. pRtspClient->sendOptionsCommand(continueAfterOption);
  21. }
  22. }

ParseRTSPURL()函数链接:https://blog.csdn.net/m0_37684310/article/details/89713900

 

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号