[libav-devel] [PATCH 1/4] rtmppkt: handle extended timestamp field even for one-byte header

Martin Panter vadmium+rtmp at gmail.com
Thu Mar 6 01:34:56 CET 2014


Hello Martin,

I have tested these four patches on the ABC stream, and verified it
fixes the issue. Also, good catch for my mistake in the write
function; your version looks good to me.

On 5 March 2014 14:11, Martin Storsjö <martin at martin.st> wrote:
> From: Martin Panter <vadmium at gmail.com>

I can live with you using my email address like this for these
patches, though I do avoid posting it like that in general.

> 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:
>
> ffplay rtmp://cp81899.live.edgefcs.net/live/news24-med@28772
> ---
>  libavformat/rtmppkt.c | 20 +++++++++++---------
>  libavformat/rtmppkt.h |  2 +-
>  2 files changed, 12 insertions(+), 10 deletions(-)
>
> diff --git a/libavformat/rtmppkt.c b/libavformat/rtmppkt.c
> index 81621b1..fb3726b 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
> diff --git a/libavformat/rtmppkt.h b/libavformat/rtmppkt.h
> index 7121d7e..3ccc6b4 100644
> --- a/libavformat/rtmppkt.h
> +++ b/libavformat/rtmppkt.h
> @@ -78,7 +78,7 @@ typedef struct RTMPPacket {
>      int            channel_id; ///< RTMP channel ID (nothing to do with audio/video channels though)
>      RTMPPacketType type;       ///< packet payload type
>      uint32_t       timestamp;  ///< packet full timestamp
> -    uint32_t       ts_delta;   ///< timestamp increment to the previous one in milliseconds (latter only for media packets)
> +    uint32_t       ts_delta;   ///< 24-bit timestamp or increment to the previous one, in milliseconds (latter only for media packets). Clipped to a maximum of 0xFFFFFF, indicating an extended timestamp field.
>      uint32_t       extra;      ///< probably an additional channel ID used during streaming data
>      uint8_t        *data;      ///< packet payload
>      int            size;       ///< packet payload size
> --
> 1.8.3.4 (Apple Git-47)


More information about the libav-devel mailing list