[FFmpeg-devel] [PATCH] RTMP client support for lavf

Michael Niedermayer michaelni
Thu Jul 30 03:10:23 CEST 2009


On Wed, Jul 29, 2009 at 09:26:05AM +0300, Kostya wrote:

[...]

> +int ff_rtmp_packet_read(URLContext *h, RTMPPacket *p,
> +                        int chunk_size, RTMPPacket *prev_pkt)
> +{
> +    uint8_t hdr, t, buf[16];
> +    int channel_id, timestamp, data_size, offset = 0;
> +    uint32_t extra = 0;
> +    uint8_t type;
> +
> +    if (url_read(h, &hdr, 1) != 1) {
> +        return AVERROR(EIO);
> +    }
> +    channel_id = hdr & 0x3F;
> +
> +    hdr >>= 6;
> +    if (hdr == RTMP_PS_ONEBYTE) {
> +        //todo
> +        return -1;
> +    } else {
> +        if (url_read_complete(h, buf, 3) != 3)
> +            return AVERROR(EIO);
> +        timestamp = AV_RB24(buf);
> +        if (hdr != RTMP_PS_FOURBYTES) {
> +            if (url_read_complete(h, buf, 3) != 3)
> +                return AVERROR(EIO);
> +            data_size = AV_RB24(buf);
> +            if (url_read_complete(h, &type, 1) != 1)
> +                return AVERROR(EIO);
> +            if (hdr == RTMP_PS_TWELVEBYTES) {
> +                if (url_read_complete(h, buf, 4) != 4)
> +                    return AVERROR(EIO);
> +                extra = AV_RL32(buf);
> +            } else {
> +                extra = prev_pkt[channel_id].extra;
> +            }
> +        } else {
> +            data_size = prev_pkt[channel_id].data_size;
> +            type      = prev_pkt[channel_id].type;
> +            extra     = prev_pkt[channel_id].extra;
> +        }

data_size = prev_pkt[channel_id].data_size;
type      = prev_pkt[channel_id].type;
extra     = prev_pkt[channel_id].extra;

if()
      data_size = AV_RB24(buf);
...


> +    }
> +    if (ff_rtmp_packet_create(p, channel_id, type, timestamp, data_size))
> +        return -1;
> +    p->extra = extra;
> +    // save history
> +    prev_pkt[channel_id].channel_id = channel_id;
> +    prev_pkt[channel_id].type       = type;
> +    prev_pkt[channel_id].data_size  = data_size;
> +    prev_pkt[channel_id].timestamp  = timestamp;
> +    prev_pkt[channel_id].extra      = extra;
> +    while (data_size > 0) {
> +        int toread = FFMIN(data_size, chunk_size);
> +        if (url_read_complete(h, p->data + offset, toread) != toread) {
> +            ff_rtmp_packet_destroy(p);
> +            return AVERROR(EIO);
> +        }
> +        data_size -= chunk_size;
> +        offset    += chunk_size;
> +        if (data_size > 0) {
> +            url_read_complete(h, &t, 1); //marker
> +            if (t != (0xC0 + channel_id))
> +                return -1;
> +        }
> +    }
> +    return 0;
> +}
> +

[...]

> +int ff_amf_get_field_value(const uint8_t *data, const uint8_t *data_end,
> +                           const uint8_t *name, uint8_t *dst, int dst_size)
> +{
> +    int namelen = strlen(name);
> +    int len;
> +
> +    if (data >= data_end - 3)

i assume you meant

3 >= data_end - data
?

because as written if data_end is NULL+2, this wouldnt work



> +        return -1;
> +    if (*data++ != AMF_DATA_TYPE_OBJECT)
> +        return -1;
> +    for (;;) {
> +        int size = bytestream_get_be16(&data);
> +        if (!size)
> +            break;

> +        data += size;

this can overflow


> +        if (data >= data_end)
> +            return -1;
> +        if (size == namelen && !memcmp(data-size, name, namelen)) {
> +            switch (*data++) {
> +            case AMF_DATA_TYPE_NUMBER:
> +                snprintf(dst, dst_size, "%g", av_int2dbl(AV_RB64(data)));
> +                return 0;
> +            case AMF_DATA_TYPE_BOOL:
> +                snprintf(dst, dst_size, "%s", *data ? "true" : "false");
> +                return 0;
> +            case AMF_DATA_TYPE_STRING:
> +                len = bytestream_get_be16(&data);
> +                av_strlcpy(dst, data, FFMIN(len+1, dst_size));
> +                return 0;
> +            default:
> +                return -1;
> +            }

the return 0 can be factored out


> +        }
> +        len = ff_amf_tag_size(data, data_end);
> +        if (len < 0 || data + len >= data_end)
> +            return -1;

again overflow
and there are more ...

> +        data += len;
> +    }
> +    return -1;
> +}
[...]

> +/**
> + * structure for holding RTMP packets
> + */
> +typedef struct RTMPPacket {
> +    uint8_t        channel_id; ///< RTMP channel ID (nothing to do with audio/video channels though)
> +    RTMPPacketType type;       ///< packet payload type
> +    uint32_t       timestamp;  ///< packet timestamp increment to the previous one (in milliseconds)

id call it timestamp_delta or _diff if its not a absolute timestamp


[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

Good people do not need laws to tell them to act responsibly, while bad
people will find a way around the laws. -- Plato
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20090730/8e0ba7c0/attachment.pgp>



More information about the ffmpeg-devel mailing list