Move the actual data parsing and the queued stream selection
in separate functions.
---
Before I continue chopping that function in smaller bits I want your opinion.
The plan is to further reshape this quite complex loop so at least it is easier
to see what's happening.
Then I'd add move the receive buffer size as an option and possibly keep the
networking side in a separate thread to avoid overruns when the bitrate is much
larger than the current design expects.
libavformat/rtsp.c | 106 ++++++++++++++++++++++++++++++++---------------------
libavformat/rtsp.h | 1 +
2 files changed, 66 insertions(+), 41 deletions(-)
diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c
index 7e59857..15ea393 100644
--- a/libavformat/rtsp.c
+++ b/libavformat/rtsp.c
@@ -2043,11 +2043,68 @@ static int pick_stream(AVFormatContext *s, RTSPStream
**rtsp_st,
return AVERROR(EAGAIN);
}
+static int64_t parse_packet(RTSPState *rt, AVPacket *pkt)
+{
+ int ret;
+
+ if (rt->transport == RTSP_TRANSPORT_RDT) {
+ ret = ff_rdt_parse_packet(rt->cur_transport_priv, pkt, NULL, 0);
+ } else if (rt->transport == RTSP_TRANSPORT_RTP) {
+ ret = ff_rtp_parse_packet(rt->cur_transport_priv, pkt, NULL, 0);
+ } else if (CONFIG_RTPDEC && rt->ts) {
+ ret = ff_mpegts_parse_packet(rt->ts, pkt,
+ rt->recvbuf + rt->recvbuf_pos,
+ rt->recvbuf_len - rt->recvbuf_pos);
+ if (ret >= 0) {
+ rt->recvbuf_pos += ret;
+ ret = rt->recvbuf_pos < rt->recvbuf_len;
+ }
+ } else
+ ret = -1;
+
+ if (ret == 0) {
+ rt->cur_transport_priv = NULL;
+ return 0;
+ } else if (ret == 1)
+ return 0;
+
+ return ret;
+}
+
+static int select_queue_stream(AVFormatContext *s)
+{
+ RTSPState *rt = s->priv_data;
+ int i;
+ int64_t wait_end;
+ int64_t first_queue_time = 0;
+
+ for (i = 0; i < rt->nb_rtsp_streams; i++) {
+ RTPDemuxContext *rtpctx = rt->rtsp_streams[i]->transport_priv;
+ int64_t queue_time;
+ if (!rtpctx)
+ continue;
+ queue_time = ff_rtp_queued_packet_time(rtpctx);
+ if (queue_time && (queue_time - first_queue_time < 0 ||
+ !first_queue_time)) {
+ first_queue_time = queue_time;
+ rt->first_queue_st = rt->rtsp_streams[i];
+ }
+ }
+ if (first_queue_time) {
+ wait_end = first_queue_time + s->max_delay;
+ } else {
+ wait_end = 0;
+ rt->first_queue_st = NULL;
+ }
+
+ return wait_end;
+}
+
int ff_rtsp_fetch_packet(AVFormatContext *s, AVPacket *pkt)
{
RTSPState *rt = s->priv_data;
int ret, len;
- RTSPStream *rtsp_st, *first_queue_st = NULL;
+ RTSPStream *rtsp_st;
int64_t wait_end = 0;
if (rt->nb_byes == rt->nb_rtsp_streams)
@@ -2055,49 +2112,16 @@ int ff_rtsp_fetch_packet(AVFormatContext *s, AVPacket
*pkt)
/* get next frames from the same RTP packet */
if (rt->cur_transport_priv) {
- if (rt->transport == RTSP_TRANSPORT_RDT) {
- ret = ff_rdt_parse_packet(rt->cur_transport_priv, pkt, NULL, 0);
- } else if (rt->transport == RTSP_TRANSPORT_RTP) {
- ret = ff_rtp_parse_packet(rt->cur_transport_priv, pkt, NULL, 0);
- } else if (CONFIG_RTPDEC && rt->ts) {
- ret = ff_mpegts_parse_packet(rt->ts, pkt, rt->recvbuf +
rt->recvbuf_pos, rt->recvbuf_len - rt->recvbuf_pos);
- if (ret >= 0) {
- rt->recvbuf_pos += ret;
- ret = rt->recvbuf_pos < rt->recvbuf_len;
- }
- } else
- ret = -1;
- if (ret == 0) {
- rt->cur_transport_priv = NULL;
- return 0;
- } else if (ret == 1) {
+ ret = parse_packet(rt, pkt);
+ if (ret == 0)
return 0;
- } else
+ else
rt->cur_transport_priv = NULL;
}
redo:
if (rt->transport == RTSP_TRANSPORT_RTP) {
- int i;
- int64_t first_queue_time = 0;
- for (i = 0; i < rt->nb_rtsp_streams; i++) {
- RTPDemuxContext *rtpctx = rt->rtsp_streams[i]->transport_priv;
- int64_t queue_time;
- if (!rtpctx)
- continue;
- queue_time = ff_rtp_queued_packet_time(rtpctx);
- if (queue_time && (queue_time - first_queue_time < 0 ||
- !first_queue_time)) {
- first_queue_time = queue_time;
- first_queue_st = rt->rtsp_streams[i];
- }
- }
- if (first_queue_time) {
- wait_end = first_queue_time + s->max_delay;
- } else {
- wait_end = 0;
- first_queue_st = NULL;
- }
+ wait_end = select_queue_stream(s);
}
/* read next RTP packet */
@@ -2121,7 +2145,7 @@ redo:
ff_rtp_check_and_send_back_rr(rtsp_st->transport_priv,
rtsp_st->rtp_handle, NULL, len);
break;
case RTSP_LOWER_TRANSPORT_CUSTOM:
- if (first_queue_st && rt->transport == RTSP_TRANSPORT_RTP &&
+ if (rt->first_queue_st && rt->transport == RTSP_TRANSPORT_RTP &&
wait_end && wait_end < av_gettime_relative())
len = AVERROR(EAGAIN);
else
@@ -2131,11 +2155,11 @@ redo:
ff_rtp_check_and_send_back_rr(rtsp_st->transport_priv, NULL,
s->pb, len);
break;
}
- if (len == AVERROR(EAGAIN) && first_queue_st &&
+ if (len == AVERROR(EAGAIN) && rt->first_queue_st &&
rt->transport == RTSP_TRANSPORT_RTP) {
av_log(s, AV_LOG_WARNING,
"max delay reached. need to consume packet\n");
- rtsp_st = first_queue_st;
+ rtsp_st = rt->first_queue_st;
ret = ff_rtp_parse_packet(rtsp_st->transport_priv, pkt, NULL, 0);
goto end;
}
diff --git a/libavformat/rtsp.h b/libavformat/rtsp.h
index ff5b532..70ef286 100644
--- a/libavformat/rtsp.h
+++ b/libavformat/rtsp.h
@@ -223,6 +223,7 @@ typedef struct RTSPState {
int nb_rtsp_streams;
struct RTSPStream **rtsp_streams; /**< streams in this session */
+ struct RTSPStream *first_queue_st;
/** indicator of whether we are currently receiving data from the
* server. Basically this isn't more than a simple cache of the
--
2.9.2
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel