avformat: rtsp: handle interleaved pending packets

Fixes the behavior when calling ff_rtsp_read_reply again after it
was called at another place with return_on_interleaved_data set to
true. Before, it would result in completely corrupting the internal
state as the $ interleaved packet marker would have already been read
which the next run of ff_rtsp_read_reply would look for but never find
it, trying to read packet data as RTSP message.
This commit is contained in:
Marvin Scholz
2025-10-05 23:08:01 +02:00
parent 44065ea878
commit 6d8950f046
3 changed files with 18 additions and 0 deletions

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);