On 17/09/13 14:38, Martin Storsjö wrote:
> From: Josh Allmann <[email protected]>
> 
> A given packet won't always come in contiguously; sometimes
> they may be broken up on chunk boundaries by packets of another
> channel.
> 
> This support primarily involves tracking information about the
> data that's been read, so the reader can pick up where it left
> off for a given channel.
> 
> As a side effect, we no longer over-report the bytes read if
> (toread = MIN(size, chunk_size)) == size
> ---
>  libavformat/rtmppkt.c   |   89 
> ++++++++++++++++++++++++++++++++---------------
>  libavformat/rtmppkt.h   |    2 ++
>  libavformat/rtmpproto.c |    5 ++-
>  3 files changed, 67 insertions(+), 29 deletions(-)
> 
> diff --git a/libavformat/rtmppkt.c b/libavformat/rtmppkt.c
> index 8f39122..922ca3e 100644
> --- a/libavformat/rtmppkt.c
> +++ b/libavformat/rtmppkt.c
> @@ -140,16 +140,17 @@ int ff_rtmp_packet_read(URLContext *h, RTMPPacket *p,
>      return ff_rtmp_packet_read_internal(h, p, chunk_size, prev_pkt, hdr);
>  }
>  
> -int ff_rtmp_packet_read_internal(URLContext *h, RTMPPacket *p, int 
> chunk_size,
> -                                 RTMPPacket *prev_pkt, uint8_t hdr)
> +static int rtmp_packet_read_one_chunk(URLContext *h, RTMPPacket *p,
> +                                      int chunk_size, RTMPPacket *prev_pkt,
> +                                      uint8_t hdr)
>  {
>  
> -    uint8_t t, buf[16];
> -    int channel_id, timestamp, size, offset = 0;
> +    uint8_t buf[16];
> +    int channel_id, timestamp, size;
>      uint32_t extra = 0;
>      enum RTMPPacketType type;
>      int written = 0;
> -    int ret;
> +    int ret, toread;
>  
>      written++;
>      channel_id = hdr & 0x3F;
> @@ -198,37 +199,69 @@ int ff_rtmp_packet_read_internal(URLContext *h, 
> RTMPPacket *p, int chunk_size,
>      if (hdr != RTMP_PS_TWELVEBYTES)
>          timestamp += prev_pkt[channel_id].timestamp;
>  
> -    if ((ret = ff_rtmp_packet_create(p, channel_id, type, timestamp,
> -                                     size)) < 0)
> -        return ret;
> +    if (!prev_pkt[channel_id].read) {
> +        if ((ret = ff_rtmp_packet_create(p, channel_id, type, timestamp,
> +                                         size)) < 0)
> +            return ret;
> +        p->read = written;
> +        p->offset = 0;
> +        prev_pkt[channel_id].ts_delta   = timestamp -
> +                                          prev_pkt[channel_id].timestamp;
> +        prev_pkt[channel_id].timestamp  = timestamp;
> +    } else {
> +        // previous packet in this channel hasn't completed reading
> +        RTMPPacket *prev = &prev_pkt[channel_id];
> +        p->data          = prev->data;
> +        p->size          = prev->size;
> +        p->channel_id    = prev->channel_id;
> +        p->type          = prev->type;
> +        p->ts_delta      = prev->ts_delta;
> +        p->extra         = prev->extra;
> +        p->offset        = prev->offset;
> +        p->read          = prev->read + written;
> +        p->timestamp     = prev->timestamp;
> +        prev->data       = NULL;
> +    }
>      p->extra = extra;
>      // save history
>      prev_pkt[channel_id].channel_id = channel_id;
>      prev_pkt[channel_id].type       = type;
>      prev_pkt[channel_id].size       = size;
> -    prev_pkt[channel_id].ts_delta   = timestamp - 
> prev_pkt[channel_id].timestamp;
> -    prev_pkt[channel_id].timestamp  = timestamp;
>      prev_pkt[channel_id].extra      = extra;
> -    while (size > 0) {
> -        int toread = FFMIN(size, chunk_size);
> -        if (ffurl_read_complete(h, p->data + offset, toread) != toread) {
> -            ff_rtmp_packet_destroy(p);
> +    size = size - p->offset;
> +
> +    toread = FFMIN(size, chunk_size);
> +    if (ffurl_read_complete(h, p->data + p->offset, toread) != toread) {
> +        ff_rtmp_packet_destroy(p);
> +        return AVERROR(EIO);
> +    }
> +    size      -= toread;
> +    p->read   += toread;
> +    p->offset += toread;
> +
> +    if (size > 0) {
> +       RTMPPacket *prev = &prev_pkt[channel_id];
> +       prev->data = p->data;
> +       prev->read = p->read;
> +       prev->offset = p->offset;
> +       return AVERROR(EAGAIN);
> +    }
> +
> +    prev_pkt[channel_id].read = 0; // read complete; reset if needed
> +    return p->read;
> +}
> +
> +int ff_rtmp_packet_read_internal(URLContext *h, RTMPPacket *p, int 
> chunk_size,
> +                                 RTMPPacket *prev_pkt, uint8_t hdr)
> +{
> +    while (1) {
> +        int ret = rtmp_packet_read_one_chunk(h, p, chunk_size, prev_pkt, 
> hdr);
> +        if (ret > 0 || ret != AVERROR(EAGAIN))
> +            return ret;
> +
> +        if (ffurl_read(h, &hdr, 1) != 1)
>              return AVERROR(EIO);

Shouldn't be the other way round? first read 1 byte then the chunk ?

>  
>  int ff_rtmp_packet_write(URLContext *h, RTMPPacket *pkt,
> diff --git a/libavformat/rtmppkt.h b/libavformat/rtmppkt.h
> index e3120be..ce326d1 100644
> --- a/libavformat/rtmppkt.h
> +++ b/libavformat/rtmppkt.h
> @@ -82,6 +82,8 @@ typedef struct RTMPPacket {
>      uint32_t       extra;      ///< probably an additional channel ID used 
> during streaming data
>      uint8_t        *data;      ///< packet payload
>      int            size;       ///< packet payload size
> +    int            offset;     ///< amount of data read so far
> +    int            read;       ///< amount read, including headers
>  } RTMPPacket;
>  
>  /**
> diff --git a/libavformat/rtmpproto.c b/libavformat/rtmpproto.c
> index e9814a3..9a5ad57 100644
> --- a/libavformat/rtmpproto.c
> +++ b/libavformat/rtmpproto.c
> @@ -2309,7 +2309,7 @@ static int get_packet(URLContext *s, int for_header)
>  static int rtmp_close(URLContext *h)
>  {
>      RTMPContext *rt = h->priv_data;
> -    int ret = 0;
> +    int ret = 0, i, j;
>  
>      if (!rt->is_input) {
>          rt->flv_data = NULL;
> @@ -2320,6 +2320,9 @@ static int rtmp_close(URLContext *h)
>      }
>      if (rt->state > STATE_HANDSHAKED)
>          ret = gen_delete_stream(h, rt);
> +    for (i = 0; i < 2; i++)

Usual obnoxious question: why 2? FFARRAYELEMS() maybe?

The rest seems fine to me.

lu
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to