summaryrefslogtreecommitdiff
path: root/libavformat/rtmppkt.c
diff options
context:
space:
mode:
authorMartin Panter <vadmium@gmail.com>2014-03-05 04:04:39 +0000
committerMartin Storsjö <martin@martin.st>2014-03-07 10:43:26 +0200
commit5b2ad78f97d43299adcb038c04346999fe9b196c (patch)
treeac48a732149d21f3ea0d071b414e4010aba9a921 /libavformat/rtmppkt.c
parent93d216d37a3f95190ecb9d51cf72f54ea4e04ec7 (diff)
rtmppkt: Handle extended timestamp field even for one-byte header
Related fix in "rtmpdump": https://repo.or.cz/w/rtmpdump.git/commitdiff/79459a2 Adobe's RTMP specification (21 Dec 2012), section 5.3.1.3 ("Extended Timestamp"), says "this field is present in Type 3 chunks". Type 3 chunks are those with the one-byte header size. This resolves intermittent hangs and segfaults caused by the read function, and also includes an untested fix for the write function. The read function was tested with ABC (Australia) News 24 streams, however they are probably restricted to only Australian internet addresses. Some of the packets at the start of these streams seem to contain junk timestamp fields, often requiring the extended field. Test command: avplay rtmp://cp81899.live.edgefcs.net/live/news24-med@28772 Signed-off-by: Martin Storsjö <martin@martin.st>
Diffstat (limited to 'libavformat/rtmppkt.c')
-rw-r--r--libavformat/rtmppkt.c20
1 files changed, 11 insertions, 9 deletions
diff --git a/libavformat/rtmppkt.c b/libavformat/rtmppkt.c
index 81621b1a99..fb3726bdd3 100644
--- a/libavformat/rtmppkt.c
+++ b/libavformat/rtmppkt.c
@@ -169,6 +169,7 @@ static int rtmp_packet_read_one_chunk(URLContext *h, RTMPPacket *p,
uint8_t buf[16];
int channel_id, timestamp, size;
+ uint32_t ts_field; // non-extended timestamp or delta field
uint32_t extra = 0;
enum RTMPPacketType type;
int written = 0;
@@ -195,12 +196,12 @@ static int rtmp_packet_read_one_chunk(URLContext *h, RTMPPacket *p,
hdr >>= 6;
if (hdr == RTMP_PS_ONEBYTE) {
- timestamp = prev_pkt[channel_id].ts_delta;
+ ts_field = prev_pkt[channel_id].ts_delta;
} else {
if (ffurl_read_complete(h, buf, 3) != 3)
return AVERROR(EIO);
written += 3;
- timestamp = AV_RB24(buf);
+ ts_field = AV_RB24(buf);
if (hdr != RTMP_PS_FOURBYTES) {
if (ffurl_read_complete(h, buf, 3) != 3)
return AVERROR(EIO);
@@ -217,11 +218,13 @@ static int rtmp_packet_read_one_chunk(URLContext *h, RTMPPacket *p,
extra = AV_RL32(buf);
}
}
- if (timestamp == 0xFFFFFF) {
- if (ffurl_read_complete(h, buf, 4) != 4)
- return AVERROR(EIO);
- timestamp = AV_RB32(buf);
- }
+ }
+ if (ts_field == 0xFFFFFF) {
+ if (ffurl_read_complete(h, buf, 4) != 4)
+ return AVERROR(EIO);
+ timestamp = AV_RB32(buf);
+ } else {
+ timestamp = ts_field;
}
if (hdr != RTMP_PS_TWELVEBYTES)
timestamp += prev_pkt[channel_id].timestamp;
@@ -232,8 +235,7 @@ static int rtmp_packet_read_one_chunk(URLContext *h, RTMPPacket *p,
return ret;
p->read = written;
p->offset = 0;
- prev_pkt[channel_id].ts_delta = timestamp -
- prev_pkt[channel_id].timestamp;
+ prev_pkt[channel_id].ts_delta = ts_field;
prev_pkt[channel_id].timestamp = timestamp;
} else {
// previous packet in this channel hasn't completed reading