FFMPEG 符 工 关于 RTSP问题解答

问题原因:由于rtsp发送视频数据完成后,不会主动断开连接,
         rtp接收数据会一直receive again,导致死循环。
解决方案:在rtsp协议中加超时机制,一段时间没有收到数据,超时退出
存在问题:这样在没有收到数据做超时退出,可能导致退出不及时,不够
精确,需要优化处理(通过时常或文件大小,需要权衡)。
---
 .../av/LibPlayer/amffmpeg/libavformat/avio.c       | 32 ++++++++++++++--------
 .../av/LibPlayer/amffmpeg/libavformat/aviobuf.c    |  4 ++-
 .../av/LibPlayer/amffmpeg/libavformat/rtsp.c       |  7 +++--
 .../av/LibPlayer/amffmpeg/libavformat/rtspdec.c    |  1 +
 .../av/LibPlayer/amffmpeg/libavformat/url.h        |  1 +
 5 files changed, 30 insertions(+), 15 deletions(-)
 mode change 100644 => 100755 vendor/amlogic/frameworks/av/LibPlayer/amffmpeg/libavformat/avio.c
 mode change 100644 => 100755 vendor/amlogic/frameworks/av/LibPlayer/amffmpeg/libavformat/aviobuf.c
 mode change 100644 => 100755 vendor/amlogic/frameworks/av/LibPlayer/amffmpeg/libavformat/rtsp.c
 mode change 100644 => 100755 vendor/amlogic/frameworks/av/LibPlayer/amffmpeg/libavformat/rtspdec.c
 mode change 100644 => 100755 vendor/amlogic/frameworks/av/LibPlayer/amffmpeg/libavformat/url.h

参考之前写的文档 :  主要知道读调用过程: 

aviobuf.c  (avio_read) -> avio.c  (retry_transfer_wrapper) ->  rtsp.c (ff_rtsp_fetch_packet) 

主要思路是修改返回值为AVERROR_EOF 。 超时时间时候。 

关键点: ff_rtsp_fetch_packet  

^[[33mcommit 23eb7258ef0c3ed64e130060b0935a50a7f8b04b^[[m
Author: Fu bilong <[email protected]>
Date:   Fri May 25 17:18:07 2018 +0800

    [ffmpeg] 修改rtsp播放结束不能退出问题
 

 .../av/LibPlayer/amffmpeg/libavformat/avio.c       | 35 ++++----
 .../av/LibPlayer/amffmpeg/libavformat/aviobuf.c    |  4 +-
 .../av/LibPlayer/amffmpeg/libavformat/rtsp.c       | 13 +--
 .../av/LibPlayer/amffmpeg/libavformat/rtspdec.c    |  3 +-
 .../av/LibPlayer/amplayer/player/player.c          |  6 +-
 .../av/LibPlayer/amplayer/player/player_av.c       | 18 +++--
 

分析: 先去掉之前的修改 , 在player层 中non_raw_read做。 超时返回 ret = AVERROR_EOF

--- a/vendor/amlogic/frameworks/av/LibPlayer/amplayer/player/player_av.c
+++ b/vendor/amlogic/frameworks/av/LibPlayer/amplayer/player/player_av.c
@@ -1193,11 +1193,19 @@ static int non_raw_read(play_para_t *para)
             if (AVERROR(EAGAIN) != ret) {
                 /*if the return is EAGAIN,we need to try more times*/
                 log_error("[%s:%d]av_read_frame return (%d)\n", __FUNCTION__, __LINE__, ret);
-
-                if (AVERROR(ETIMEDOUT) == ret && para->state.current_time >= para->state.full_time) {
-                    //read timeout ,if playing current time reached end time,we think it is eof
-                    ret = AVERROR_EOF;
-                }
+                               log_error("[%s:%d]av_read_frame (%s),current_time=%d,full_time=%d\n", __FUNCTION__, __LINE__,
+                                                                       para->file_name,para->state.current_time,para->state.full_time);

+
+                               if (AVERROR(ETIMEDOUT) == ret && para->state.current_time >= para->state.full_time) {
+                                       //read timeout ,if playing current time reached end time,we think it is eof
+                                       ret = AVERROR_EOF;
+                               }
+                               if (!strncmp(para->file_name, "rtsp:", strlen("rtsp:"))
+                                       &&(para->state.current_time>= para->state.full_time)){
+                                       ret = AVERROR_EOF;
+                                       log_error("[%s:%d]av_read_frame return (%d),current_time=%d,full_time=%d\n", __FUNCTION__, __LINE__,
+                                       AVERROR(ETIMEDOUT),para->state.current_time,para->state.full_time);
+                               }

                 if (av_is_segment_media(para->pFormatCtx) && ret == -(0x1fffffff)) {
                     para->playctrl_info.hls_force_exit =

^[[33mcommit d31564e495358b49749ac62cba16b588ef9d4592^[[m
Author: Fu bilong <[email protected]>
Date:   Tue Jun 5 18:19:50 2018 +0800

    [Player]待机唤醒后播放失败。

    commit:
    问题原因:待机唤醒后网络还没有连上,导致tcp/udp 连接服务器失败。
    解决方案:
        在player中打开文件失败后sleep等待网络连接上
diff --git a/vendor/amlogic/frameworks/av/LibPlayer/amplayer/player/player_ffmpeg_ctrl.c b/vendor/amlogic/frameworks/av/LibPlayer/amplayer/player/player_ffmpeg_ctrl.c
index 13d6554..7dc9f23 100644
--- a/vendor/amlogic/frameworks/av/LibPlayer/amplayer/player/player_ffmpeg_ctrl.c
+++ b/vendor/amlogic/frameworks/av/LibPlayer/amplayer/player/player_ffmpeg_ctrl.c
@@ -279,6 +279,7 @@ Retry_open:
                 goto  Retry_open;
             }
             if (retry_count-- > 0) {
+               usleep(1000 * 1000);
                 goto Retry_open;
             }
             log_print("ffmpeg error: Couldn't open input file! ret==%x\n", ret);
--
 

分析:十分简单的修改, 主要要对 player代码熟悉 

现象:

  • SEN-61: Player doesn't send SETUP after it receives SDP 

When player tries to play video and receives back Reply message on RTSP with SDP, it does not send SETUP but it again sends OPTIONS.

This prolongs start of video playout.

See attached tcpdump.

Please note that on Univision also port 553 is used for RTSP.

^[[33mcommit cd7e1291406825ff2d5d2e1245d55f81e0fcab53^[[m
Author: Fu bilong <[email protected]>
Date:   Thu Jun 7 16:27:38 2018 +0800

    [Fmpeg]fix rtsp seed two options (sdp)

    问题原因:
        在选择demux时会把 rtsp demux当做demux,
    发现describe sdp消息中是ts封装格式,rtsp demux不能当做demux
    将ts demux当做demux,从新连接服务器,两次连接导致两次options消息
    解决方案:
        将rtsp demux探测函数直接返回0,这样不会匹配rtsp demux

问题原因:rtsp启播时流程是:

C表示rtsp客户端,S表示rtsp服务端 

1.C->S:OPTION request //询问S有哪些方法可用 

1.S->C:OPTION response //S回应信息中包括提供的所有可用方法 

2.C->S:DESCRIBE request //要求得到S提供的媒体初始化描述信息 

2.S->C:DESCRIBE response //S回应媒体初始化描述信息,主要是sdp 

3.C->S:SETUP request //设置会话的属性,以及传输模式,提醒S建立会 

话 

3.S->C:SETUP response //S建立会话,返回会话标识符,以及会话相关信息 

4.C->S:PLAY request //C请求播放 

4.S->C:PLAY response //S回应该请求的信息 

S->C:发送流媒体数据 

5.C->S:TEARDOWN request //C请求关闭会话 

5.S->C:TEARDOWN response //S回应该请求 

在收到S->C:DESCRIBE response服务器回应时,信令sdp里面会包含负载类型(H264,TS等等)

当是ts类型时,需要demux,此时用的demux插件是rtsp demux,是不能解析ts流的,

这时就会设置demux为ts demux,然后失败返回(断开连接),再次用ts demux 打开,从新

走rtsp流程,这时会看到两次options与describe,两次tcp连接,对于客户服务器会对同一个

源会有限制(网络攻击),这会导致很长时间才能第二次连接。

解决办法:在探测格式是将rtsp demux屏蔽,这样不会找到

rtsp demux,会使用ts demux,不会造成重demux带来的多次连接

ff --git a/vendor/amlogic/frameworks/av/LibPlayer/amffmpeg/libavformat/rtspdec.c b/vendor/amlogic/frameworks/av/LibPlayer/amffmpeg/libavformat/rtspdec.c
index 9e32208..79a8305 100755
--- a/vendor/amlogic/frameworks/av/LibPlayer/amffmpeg/libavformat/rtspdec.c
+++ b/vendor/amlogic/frameworks/av/LibPlayer/amffmpeg/libavformat/rtspdec.c
@@ -356,9 +356,11 @@ int ff_rtsp_setup_input_streams(AVFormatContext *s, RTSPMessageHeader *reply)

 static int rtsp_probe(AVProbeData *p)
 {
+#if 0
     if (av_strstart(p->filename, "rtsp:", NULL)) {
         return AVPROBE_SCORE_MAX;
     }
+#endif
     return 0;
 }
 

分析: 主要分析log 找到原因。 比较难 

^[[33mcommit 0e96ea405df042268e77c9217ba20f497d6dc71d^[[m
Author: Fu bilong <[email protected]>
Date:   Tue Jun 12 11:26:44 2018 +0800

    [Player]待机唤醒后网络可能没有连上,这时恢复上一次播放会失败

    解决方案:在待机唤醒后播放失败,可以再次ffmpeg_open_file
    打开重复次数为10*3,相隔时间为200毫秒,意味着6s内没有成功将
    返回失败
 

分析: 休眠唤醒问题的优化 。 

从原来的 3× 1s  --》 30*0.2s

[[33mcommit ae35c8c040b8841afad68f8e243b1f3e61d0c01a^[[m
Author: Fu bilong <[email protected]>
Date:   Tue Jun 12 19:49:19 2018 +0800

    [FFmpeg]修改rtsp播放结束不能退出问题

    问题原因;rtsp流传输完成,服务器不会断开rtsp链接,
    导致播放结束不能退出
    解决方案:在播放结束后avio_read会返回错误,
    这样当做播结束,后面会根据流传输超时来判断播放是否结束
 

跟之前提交基本一样: 还是返回 AVERROR_EOF

+++ b/vendor/amlogic/frameworks/av/LibPlayer/amffmpeg/libavformat/avio.c
@@ -518,8 +518,9 @@ int ffurl_read(URLContext *h, unsigned char *buf, int size)

 int ffurl_read_complete(URLContext *h, unsigned char *buf, int size)
 {
-#define MAX_RETRY (6*60) //10S*6*60=60MIN;
-    int maxretry = MAX_RETRY;
+#define MAX_RETRY (60) //10S*6*60=60MIN;
+    int maxretry = h->rw_timeout>0?h->rw_timeout:MAX_RETRY;
 

猜你喜欢

转载自blog.csdn.net/Sam_sunbeyond/article/details/81868756