diff options
author | Martin Storsjö <martin@martin.st> | 2011-09-21 23:21:30 +0300 |
---|---|---|
committer | Martin Storsjö <martin@martin.st> | 2011-09-22 10:36:16 +0300 |
commit | b14629e5eafb34dd71702aa42863388438060cd1 (patch) | |
tree | a5663535e9c629252af8c9158661bddbd27afc66 /libavformat | |
parent | fe476e5a9b5a1e56e53f1fa62374778fa00ec1fd (diff) | |
download | ffmpeg-b14629e5eafb34dd71702aa42863388438060cd1.tar.gz |
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: Martin Storsjö <martin@martin.st>
Diffstat (limited to 'libavformat')
-rw-r--r-- | libavformat/rtmpproto.c | 61 |
1 files changed, 27 insertions, 34 deletions
diff --git a/libavformat/rtmpproto.c b/libavformat/rtmpproto.c index a8be052fa0..093d21a585 100644 --- a/libavformat/rtmpproto.c +++ b/libavformat/rtmpproto.c @@ -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; - if (rt->skip_bytes) { - int skip = FFMIN(rt->skip_bytes, size); - buf_temp += skip; - size_temp -= skip; - rt->skip_bytes -= skip; - if (size_temp <= 0) - return size; - } - - if (!rt->flv_off && size_temp < 11) { - av_log(s, AV_LOG_DEBUG, "FLV packet too small %d\n", size); - return 0; - } - 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; - } + if (rt->skip_bytes) { + int skip = FFMIN(rt->skip_bytes, size_temp); + buf_temp += skip; + size_temp -= skip; + rt->skip_bytes -= skip; + continue; + } + + 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; - 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; |