diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index 9b022f6efa..fa227ada62 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -1200,6 +1200,7 @@ int ff_rtsp_skip_packet(AVFormatContext *s) int ret, len, len1; uint8_t buf[MAX_URL_SIZE]; + rt->pending_packet = 0; ret = ffurl_read_complete(rt->rtsp_hd, buf, 3); if (ret != 3) return ret < 0 ? ret : AVERROR(EIO); @@ -1232,6 +1233,18 @@ int ff_rtsp_read_reply(AVFormatContext *s, RTSPMessageHeader *reply, int ret, content_length, line_count, request; unsigned char *content; + // If we returned on pending packet last time, + // do not try to read again, as it would corrupt + // the state due to the already consumed '$'. + if (rt->pending_packet) { + if (return_on_interleaved_data) + return 1; + + ret = ff_rtsp_skip_packet(s); + if (ret < 0) + return ret; + } + start: line_count = 0; request = 0; @@ -1254,6 +1267,7 @@ start: break; if (ch == '$' && q == buf) { if (return_on_interleaved_data) { + rt->pending_packet = 1; return 1; } else { ret = ff_rtsp_skip_packet(s); diff --git a/libavformat/rtsp.h b/libavformat/rtsp.h index c27cbe1e03..9b2ceff996 100644 --- a/libavformat/rtsp.h +++ b/libavformat/rtsp.h @@ -286,6 +286,9 @@ typedef struct RTSPState { /** The last reply of the server to a RTSP command */ char last_reply[2048]; /* XXX: allocate ? */ + /** Indicates if a packet is pending to be read (useful for interleaved reads) */ + int pending_packet; + /** RTSPStream->transport_priv of the last stream that we read a * packet from */ void *cur_transport_priv; diff --git a/libavformat/rtspdec.c b/libavformat/rtspdec.c index 0d39daa39d..ad16630d2e 100644 --- a/libavformat/rtspdec.c +++ b/libavformat/rtspdec.c @@ -902,6 +902,7 @@ redo: ret = ffurl_read_complete(rt->rtsp_hd, buf, 3); if (ret != 3) return AVERROR(EIO); + rt->pending_packet = 0; id = buf[0]; len = AV_RB16(buf + 1); av_log(s, AV_LOG_TRACE, "id=%d len=%d\n", id, len);