diff --git a/libavformat/rtpdec.c b/libavformat/rtpdec.c index 25fe5a73f8..debc14c90b 100644 --- a/libavformat/rtpdec.c +++ b/libavformat/rtpdec.c @@ -92,11 +92,13 @@ static int rtcp_parse_packet(RTPDemuxContext *s, const unsigned char *buf, int l buf += payload_len; len -= payload_len; break; + case RTCP_BYE: + return -RTCP_BYE; default: return -1; } } - return 0; + return -1; } #define RTP_SEQ_MOD (1<<16) @@ -451,8 +453,7 @@ int rtp_parse_packet(RTPDemuxContext *s, AVPacket *pkt, if ((buf[0] & 0xc0) != (RTP_VERSION << 6)) return -1; if (buf[1] >= RTCP_SR && buf[1] <= RTCP_APP) { - rtcp_parse_packet(s, buf, len); - return -1; + return rtcp_parse_packet(s, buf, len); } payload_type = buf[1] & 0x7f; if (buf[1] & 0x80) diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index 16997e3245..c3f4d00858 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -1226,6 +1226,7 @@ static int rtsp_read_play(AVFormatContext *s) char cmd[1024]; av_log(s, AV_LOG_DEBUG, "hello state=%d\n", rt->state); + rt->nb_byes = 0; if (!(rt->server_type == RTSP_SERVER_REAL && rt->need_subscription)) { if (rt->state == RTSP_STATE_PAUSED) { @@ -1777,6 +1778,9 @@ static int rtsp_fetch_packet(AVFormatContext *s, AVPacket *pkt) uint8_t buf[10 * RTP_MAX_PACKET_LENGTH]; RTSPStream *rtsp_st; + if (rt->nb_byes == rt->nb_rtsp_streams) + return AVERROR_EOF; + /* get next frames from the same RTP packet */ if (rt->cur_transport_priv) { if (rt->transport == RTSP_TRANSPORT_RDT) { @@ -1833,6 +1837,15 @@ static int rtsp_fetch_packet(AVFormatContext *s, AVPacket *pkt) rtpctx2->first_rtcp_ntp_time = rtpctx->first_rtcp_ntp_time; } } + if (ret == -RTCP_BYE) { + rt->nb_byes++; + + av_log(s, AV_LOG_DEBUG, "Received BYE for stream %d (%d/%d)\n", + rtsp_st->stream_index, rt->nb_byes, rt->nb_rtsp_streams); + + if (rt->nb_byes == rt->nb_rtsp_streams) + return AVERROR_EOF; + } } } if (ret < 0) diff --git a/libavformat/rtsp.h b/libavformat/rtsp.h index 49dbfdef28..c6c3972576 100644 --- a/libavformat/rtsp.h +++ b/libavformat/rtsp.h @@ -303,6 +303,11 @@ typedef struct RTSPState { /** RTSP transport mode, such as plain or tunneled. */ enum RTSPControlTransport control_transport; + + /* Number of RTCP BYE packets the RTSP session has received. + * An EOF is propagated back if nb_byes == nb_streams. + * This is reset after a seek. */ + int nb_byes; } RTSPState; /**