Esempio n. 1
0
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;

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

    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);
            }
        }
    }
    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_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;
	enum RTMPPacketType type;
	int size = 0;

	if (ffurl_read(h, &hdr, 1) != 1)
		return AVERROR(EIO);
	size++;
	channel_id = hdr & 0x3F;

	if (channel_id < 2)   //special case for channel number >= 64
	{
		buf[1] = 0;
		if (ffurl_read_complete(h, buf, channel_id + 1) != channel_id + 1)
			return AVERROR(EIO);
		size += channel_id + 1;
		channel_id = AV_RL16(buf) + 64;
	}
	data_size = prev_pkt[channel_id].data_size;
	type      = prev_pkt[channel_id].type;
	extra     = prev_pkt[channel_id].extra;

	hdr >>= 6;
	if (hdr == RTMP_PS_ONEBYTE)
	{
		timestamp = prev_pkt[channel_id].ts_delta;
	}
	else
	{
		if (ffurl_read_complete(h, buf, 3) != 3)
			return AVERROR(EIO);
		size += 3;
		timestamp = AV_RB24(buf);
		if (hdr != RTMP_PS_FOURBYTES)
		{
			if (ffurl_read_complete(h, buf, 3) != 3)
				return AVERROR(EIO);
			size += 3;
			data_size = AV_RB24(buf);
			if (ffurl_read_complete(h, buf, 1) != 1)
				return AVERROR(EIO);
			size++;
			type = buf[0];
			if (hdr == RTMP_PS_TWELVEBYTES)
			{
				if (ffurl_read_complete(h, buf, 4) != 4)
					return AVERROR(EIO);
				size += 4;
				extra = AV_RL32(buf);
			}
		}
		if (timestamp == 0xFFFFFF)
		{
			if (ffurl_read_complete(h, buf, 4) != 4)
				return AVERROR(EIO);
			timestamp = AV_RB32(buf);
		}
	}
	if (hdr != RTMP_PS_TWELVEBYTES)
		timestamp += prev_pkt[channel_id].timestamp;

	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].ts_delta   = timestamp - prev_pkt[channel_id].timestamp;
	prev_pkt[channel_id].timestamp  = timestamp;
	prev_pkt[channel_id].extra      = extra;
	while (data_size > 0)
	{
		int toread = FFMIN(data_size, chunk_size);
		if (ffurl_read_complete(h, p->data + offset, toread) != toread)
		{
			ff_rtmp_packet_destroy(p);
			return AVERROR(EIO);
		}
		data_size -= chunk_size;
		offset    += chunk_size;
		size      += chunk_size;
		if (data_size > 0)
		{
			ffurl_read_complete(h, &t, 1); //marker
			size++;
			if (t != (0xC0 + channel_id))
				return -1;
		}
	}
	return size;
}
Esempio n. 3
0
static int rtmp_packet_read_one_chunk(URLContext *h, RTMPPacket *p,
                                      int chunk_size, RTMPPacket **prev_pkt_ptr,
                                      int *nb_prev_pkt, uint8_t hdr)
{

    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;
    int ret, toread;
    RTMPPacket *prev_pkt;

    written++;
    channel_id = hdr & 0x3F;

    if (channel_id < 2) { //special case for channel number >= 64
        buf[1] = 0;
        if (ffurl_read_complete(h, buf, channel_id + 1) != channel_id + 1)
            return AVERROR(EIO);
        written += channel_id + 1;
        channel_id = AV_RL16(buf) + 64;
    }
    if ((ret = ff_rtmp_check_alloc_array(prev_pkt_ptr, nb_prev_pkt,
                                         channel_id)) < 0)
        return ret;
    prev_pkt = *prev_pkt_ptr;
    size  = prev_pkt[channel_id].size;
    type  = prev_pkt[channel_id].type;
    extra = prev_pkt[channel_id].extra;

    hdr >>= 6; // header size indicator
    if (hdr == RTMP_PS_ONEBYTE) {
        ts_field = prev_pkt[channel_id].ts_field;
    } else {
        if (ffurl_read_complete(h, buf, 3) != 3)
            return AVERROR(EIO);
        written += 3;
        ts_field = AV_RB24(buf);
        if (hdr != RTMP_PS_FOURBYTES) {
            if (ffurl_read_complete(h, buf, 3) != 3)
                return AVERROR(EIO);
            written += 3;
            size = AV_RB24(buf);
            if (ffurl_read_complete(h, buf, 1) != 1)
                return AVERROR(EIO);
            written++;
            type = buf[0];
            if (hdr == RTMP_PS_TWELVEBYTES) {
                if (ffurl_read_complete(h, buf, 4) != 4)
                    return AVERROR(EIO);
                written += 4;
                extra = AV_RL32(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;

    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_field   = ts_field;
        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_field      = prev->ts_field;
        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].extra      = extra;
    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;
}