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

Michael Niedermayer michaelni
Fri Jul 24 03:08:32 CEST 2009


On Thu, Jul 23, 2009 at 06:34:13AM +0300, Kostya wrote:
> On Wed, Jul 22, 2009 at 12:01:46PM +0200, Michael Niedermayer wrote:
> > On Wed, Jul 22, 2009 at 07:58:05AM +0300, Kostya wrote:
> > > On Tue, Jul 21, 2009 at 11:30:26PM +0200, Michael Niedermayer wrote:
> > > > On Tue, Jul 21, 2009 at 11:04:09AM +0300, Kostya wrote:
> > > > > On Mon, Jul 20, 2009 at 05:05:41PM +0200, Michael Niedermayer wrote:
> > > > > > On Sat, Jul 18, 2009 at 08:01:17PM +0300, Kostya wrote:
> > > > > > > On Sat, Jul 18, 2009 at 11:29:34AM +0200, Michael Niedermayer wrote:
> > > > > > > > On Fri, Jul 17, 2009 at 06:38:46PM +0300, Kostya wrote:
[...]

> +/**
> + * Parses received packet and may perform some action depending on packet contents.
> + * @return 0 for no errors, -1 for serious errors which prevent further
> + *         communications, positive values for uncritical errors
> + */
> +static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
> +{
> +    int i, t;
> +
> +    switch (pkt->type) {
> +    case RTMP_PT_CHUNK_SIZE:
> +        if (pkt->data_size != 4) {
> +            av_log(LOG_CONTEXT, AV_LOG_ERROR,
> +                   "Chunk size change packet is not 4 bytes long (%d)\n", pkt->data_size);
> +            return -1;
> +        }
> +        rt->chunk_size = AV_RB32(pkt->data);
> +        if (rt->chunk_size <= 0) {
> +            av_log(LOG_CONTEXT, AV_LOG_ERROR, "Incorrect chunk size %d\n", rt->chunk_size);
> +            return -1;
> +        }
> +        av_log(LOG_CONTEXT, AV_LOG_DEBUG, "New chunk size = %d\n", rt->chunk_size);
> +        break;
> +    case RTMP_PT_PING:
> +        t = AV_RB16(pkt->data);
> +        if (t == 6)
> +            gen_pong(s, rt, pkt);
> +        break;
> +    case RTMP_PT_INVOKE:
> +        if (!memcmp(pkt->data, "\002\000\006_error", 9)) {
> +            uint8_t tmpstr[256];
> +
> +            if (!ff_amf_find_field(pkt->data + 9, pkt->data + pkt->data_size,
> +                                   "description", tmpstr, sizeof(tmpstr)))
> +                av_log(LOG_CONTEXT, AV_LOG_ERROR, "Server error: %s\n",tmpstr);
> +            return -1;
> +        }
> +        if (!memcmp(pkt->data, "\002\000\007_result", 10)) {
> +            switch (rt->state) {
> +            case STATE_HANDSHAKED:
> +                gen_create_stream(s, rt);
> +                rt->state = STATE_CONNECTING;
> +                break;
> +            case STATE_CONNECTING:
> +                //extract a number from result
> +                if (pkt->data[10] || pkt->data[19] != 5 || pkt->data[20]) {
> +                    av_log(LOG_CONTEXT, AV_LOG_WARNING, "Unexpected reply on connect()\n");
> +                } else {
> +                    rt->main_channel_id = (int) av_int2dbl(AV_RB64(pkt->data + 21));
> +                }
> +                gen_play(s, rt);
> +                rt->state = STATE_READY;
> +                break;
> +            }
> +        }
> +        if (!memcmp(pkt->data, "\002\000\010onStatus", 11)) {

else if
also shouldnt there be checks against receiving the wrong thing in the wrong
state?


[...]
> +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;
> +        }
> +    }
> +    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);
> +        int r;
> +        if ((r = url_read_complete(h, p->data + offset, toread)) != toread) {

r seems unused


[...]
> +/**
> + * Creates new RTMP packet with given attributes.
> + *
> + * @param pkt        packet
> + * @param channel_id packet channel ID
> + * @param type       packet type
> + * @param timestamp  packet timestamp
> + * @param size       packet size
> + * @return zero on success, negative value otherwise
> + */
> +int ff_rtmp_packet_create(RTMPPacket *pkt, int channel_id, RTMPPacketType type,
> +                          int timestamp, int size);
> +
> +/**
> + * Frees RTMP packet.
> + *
> + * @param pkt packet
> + */
> +void ff_rtmp_packet_destroy(RTMPPacket *pkt);
> +

> +/**
> + * Reads RTMP packet.

reads from where?


> + *
> + * @param h          reader context
> + * @param p          packet
> + * @param chunk_size current chunk size
> + * @param prev_pkt   previously read packet headers for all channels
> + *                   (may be needed for restoring incomplete packet header)
> + * @return zero on success, negative value otherwise
> + */
> +int ff_rtmp_packet_read(URLContext *h, RTMPPacket *p,
> +                        int chunk_size, RTMPPacket *prev_pkt);
> +
> +/**
> + * Sends RTMP packet.

sends to where?
i think you could be a little bit more verbose ...


> + *
> + * @param h          reader context
> + * @param p          packet to send
> + * @param chunk_size current chunk size
> + * @param prev_pkt   previously sent packet headers for all channels
> + *                   (may be used for packet header compressing)
> + * @return zero on success, negative value otherwise
> + */
> +int ff_rtmp_packet_write(URLContext *h, RTMPPacket *p,
> +                         int chunk_size, RTMPPacket *prev_pkt);
> +
> +/**
> + * @defgroup amffuncs functions used to work with AMF format (which is also used in .flv)
> + * @see amf_* funcs in libavformat/flvdec.c
> + * @{
> + */
> +

> +/**
> + * Calculates number of bytes needed to skip first AMF entry in data.
> + *
> + * @param data input data
> + * @param data_end input buffer end
> + * @return number of bytes used by first AMF entry
> + */
> +int ff_amf_skip_data(const uint8_t *data, const uint8_t *data_end);
> +

the function name is misleading becauase it does not "skip data"
rather it finds the size of the next element


> +/**
> + * Retrieves value of given AMF object field in string form.
> + *
> + * @param data     AMF object data
> + * @param data_end input buffer end
> + * @param name     name of field to retrieve
> + * @param dst      buffer for storing result
> + * @param dst_size output buffer size
> + * @return 0 if search and retrieval succeeded, negative value otherwise
> + */
> +int ff_amf_find_field(const uint8_t *data, const uint8_t *data_end,
> +                      const uint8_t *name, uint8_t *dst, int dst_size);

if i interpret the doxy correctly 
read_field_as_string seems a better name


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

Thouse who are best at talking, realize last or never when they are wrong.
-------------- 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/20090724/2727398a/attachment.pgp>



More information about the ffmpeg-devel mailing list