Commit b14629e5 authored by Martin Storsjö's avatar Martin Storsjö

rtmp: Make the input FLV parser handle data cut at any point

This makes the RTMP writing code able to handle FLV data
fed in arbitrarily small or large chunks, with multiple
consecutive packets in one write call, or having the FLV
packet header split over numerous write calls.

When used in conjunction with the flv muxer, the AVIO buffer
size still needs to be large enough to fit the initial metadata
packet though, since the size of that packet is written with a
seekback.
Signed-off-by: 's avatarMartin Storsjö <martin@martin.st>
parent fe476e5a
......@@ -72,6 +72,8 @@ typedef struct RTMPContext {
uint32_t bytes_read; ///< number of bytes read from server
uint32_t last_bytes_read; ///< number of bytes read last reported to server
int skip_bytes; ///< number of bytes to skip from the input FLV stream in the next write call
uint8_t flv_header[11]; ///< partial incoming flv packet header
int flv_header_bytes; ///< number of initialized bytes in flv_header
} RTMPContext;
#define PLAYER_KEY_OPEN_PART_LEN 30 ///< length of partial key used for first client digest signing
......@@ -880,6 +882,7 @@ static int rtmp_open(URLContext *s, const char *uri, int flags)
rt->flv_size = 0;
rt->flv_data = NULL;
rt->flv_off = 0;
rt->skip_bytes = 13;
}
s->max_packet_size = rt->stream->max_packet_size;
......@@ -926,34 +929,29 @@ static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
uint32_t ts;
const uint8_t *buf_temp = buf;
do {
if (rt->skip_bytes) {
int skip = FFMIN(rt->skip_bytes, size);
int skip = FFMIN(rt->skip_bytes, size_temp);
buf_temp += skip;
size_temp -= skip;
rt->skip_bytes -= skip;
if (size_temp <= 0)
return size;
continue;
}
if (!rt->flv_off && size_temp < 11) {
av_log(s, AV_LOG_DEBUG, "FLV packet too small %d\n", size);
return 0;
}
if (rt->flv_header_bytes < 11) {
const uint8_t *header = rt->flv_header;
int copy = FFMIN(11 - rt->flv_header_bytes, size_temp);
bytestream_get_buffer(&buf_temp, rt->flv_header + rt->flv_header_bytes, copy);
rt->flv_header_bytes += copy;
size_temp -= copy;
if (rt->flv_header_bytes < 11)
break;
do {
if (!rt->flv_off) {
//skip flv header
if (buf_temp[0] == 'F' && buf_temp[1] == 'L' && buf_temp[2] == 'V') {
buf_temp += 9 + 4;
size_temp -= 9 + 4;
}
pkttype = bytestream_get_byte(&buf_temp);
pktsize = bytestream_get_be24(&buf_temp);
ts = bytestream_get_be24(&buf_temp);
ts |= bytestream_get_byte(&buf_temp) << 24;
bytestream_get_be24(&buf_temp);
size_temp -= 11;
pkttype = bytestream_get_byte(&header);
pktsize = bytestream_get_be24(&header);
ts = bytestream_get_be24(&header);
ts |= bytestream_get_byte(&header) << 24;
bytestream_get_be24(&header);
rt->flv_size = pktsize;
//force 12bytes header
......@@ -984,18 +982,13 @@ static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
}
if (rt->flv_off == rt->flv_size) {
if (size_temp < 4) {
rt->skip_bytes = 4 - size_temp;
buf_temp += size_temp;
size_temp = 0;
} else {
bytestream_get_be32(&buf_temp);
size_temp -= 4;
}
rt->skip_bytes = 4;
ff_rtmp_packet_write(rt->stream, &rt->out_pkt, rt->chunk_size, rt->prev_pkt[1]);
ff_rtmp_packet_destroy(&rt->out_pkt);
rt->flv_size = 0;
rt->flv_off = 0;
rt->flv_header_bytes = 0;
}
} while (buf_temp - buf < size);
return size;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment