Ejemplo n.º 1
0
static int mpegts_handle_packet(AVFormatContext *ctx, PayloadContext *data,
                                AVStream *st, AVPacket *pkt, uint32_t *timestamp,
                                const uint8_t *buf, int len, uint16_t seq,
                                int flags)
{
    int ret;

    // We don't want to use the RTP timestamps at all. If the mpegts demuxer
    // doesn't set any pts/dts, the generic rtpdec code shouldn't try to
    // fill it in either, since the mpegts and RTP timestamps are in totally
    // different ranges.
    *timestamp = RTP_NOTS_VALUE;

    if (!data->ts)
        return AVERROR(EINVAL);

    if (!buf) {
        if (data->read_buf_index >= data->read_buf_size)
            return AVERROR(EAGAIN);
        ret = ff_mpegts_parse_packet(data->ts, pkt, data->buf + data->read_buf_index,
                                     data->read_buf_size - data->read_buf_index);
        if (ret < 0)
            return AVERROR(EAGAIN);
        data->read_buf_index += ret;
        if (data->read_buf_index < data->read_buf_size)
            return 1;
        else
            return 0;
    }

    ret = ff_mpegts_parse_packet(data->ts, pkt, buf, len);
    /* The only error that can be returned from ff_mpegts_parse_packet
     * is "no more data to return from the provided buffer", so return
     * AVERROR(EAGAIN) for all errors */
    if (ret < 0)
        return AVERROR(EAGAIN);
    if (ret < len) {
        data->read_buf_size = FFMIN(len - ret, sizeof(data->buf));
        memcpy(data->buf, buf + ret, data->read_buf_size);
        data->read_buf_index = 0;
        return 1;
    }
    return 0;
}
Ejemplo n.º 2
0
static int rtp_parse_one_packet(RTPDemuxContext *s, AVPacket *pkt,
                     uint8_t **bufptr, int len)
{
    uint8_t* buf = bufptr ? *bufptr : NULL;
    int ret, flags = 0;
    uint32_t timestamp;
    int rv= 0;

    if (!buf) {
        /* If parsing of the previous packet actually returned 0 or an error,
         * there's nothing more to be parsed from that packet, but we may have
         * indicated that we can return the next enqueued packet. */
        if (s->prev_ret <= 0)
            return rtp_parse_queued_packet(s, pkt);
        /* return the next packets, if any */
        if(s->st && s->parse_packet) {
            /* timestamp should be overwritten by parse_packet, if not,
             * the packet is left with pts == AV_NOPTS_VALUE */
            timestamp = RTP_NOTS_VALUE;
            rv= s->parse_packet(s->ic, s->dynamic_protocol_context,
                                s->st, pkt, &timestamp, NULL, 0, flags);
            finalize_packet(s, pkt, timestamp);
            return rv;
        } else {
            // TODO: Move to a dynamic packet handler (like above)
            if (s->read_buf_index >= s->read_buf_size)
                return AVERROR(EAGAIN);
            ret = ff_mpegts_parse_packet(s->ts, pkt, s->buf + s->read_buf_index,
                                      s->read_buf_size - s->read_buf_index);
            if (ret < 0)
                return AVERROR(EAGAIN);
            s->read_buf_index += ret;
            if (s->read_buf_index < s->read_buf_size)
                return 1;
            else
                return 0;
        }
    }

    if (len < 12)
        return -1;

    if ((buf[0] & 0xc0) != (RTP_VERSION << 6))
        return -1;
    if (buf[1] >= RTCP_SR && buf[1] <= RTCP_APP) {
        return rtcp_parse_packet(s, buf, len);
    }

    if ((s->seq == 0 && !s->queue) || s->queue_size <= 1) {
        /* First packet, or no reordering */
        return rtp_parse_packet_internal(s, pkt, buf, len);
    } else {
        uint16_t seq = AV_RB16(buf + 2);
        int16_t diff = seq - s->seq;
        if (diff < 0) {
            /* Packet older than the previously emitted one, drop */
            av_log(s->st ? s->st->codec : NULL, AV_LOG_WARNING,
                   "RTP: dropping old packet received too late\n");
            return -1;
        } else if (diff <= 1) {
            /* Correct packet */
            rv = rtp_parse_packet_internal(s, pkt, buf, len);
            return rv;
        } else {
            /* Still missing some packet, enqueue this one. */
            enqueue_packet(s, buf, len);
            *bufptr = NULL;
            /* Return the first enqueued packet if the queue is full,
             * even if we're missing something */
            if (s->queue_len >= s->queue_size)
                return rtp_parse_queued_packet(s, pkt);
            return -1;
        }
    }
}
Ejemplo n.º 3
0
static int rtp_parse_packet_internal(RTPDemuxContext *s, AVPacket *pkt,
                                     const uint8_t *buf, int len)
{
    unsigned int ssrc, h;
    int payload_type, seq, ret, flags = 0;
    int ext;
    AVStream *st;
    uint32_t timestamp;
    int rv= 0;

    ext = buf[0] & 0x10;
    payload_type = buf[1] & 0x7f;
    if (buf[1] & 0x80)
        flags |= RTP_FLAG_MARKER;
    seq  = AV_RB16(buf + 2);
    timestamp = AV_RB32(buf + 4);
    ssrc = AV_RB32(buf + 8);
    /* store the ssrc in the RTPDemuxContext */
    s->ssrc = ssrc;

    /* NOTE: we can handle only one payload type */
    if (s->payload_type != payload_type)
        return -1;

    st = s->st;
    // only do something with this if all the rtp checks pass...
    if(!rtp_valid_packet_in_sequence(&s->statistics, seq))
    {
        av_log(st?st->codec:NULL, AV_LOG_ERROR, "RTP: PT=%02x: bad cseq %04x expected=%04x\n",
               payload_type, seq, ((s->seq + 1) & 0xffff));
        return -1;
    }

    if (buf[0] & 0x20) {
        int padding = buf[len - 1];
        if (len >= 12 + padding)
            len -= padding;
    }

    s->seq = seq;
    len -= 12;
    buf += 12;

    /* RFC 3550 Section 5.3.1 RTP Header Extension handling */
    if (ext) {
        if (len < 4)
            return -1;
        /* calculate the header extension length (stored as number
         * of 32-bit words) */
        ext = (AV_RB16(buf + 2) + 1) << 2;

        if (len < ext)
            return -1;
        // skip past RTP header extension
        len -= ext;
        buf += ext;
    }

    if (!st) {
        /* specific MPEG2TS demux support */
        ret = ff_mpegts_parse_packet(s->ts, pkt, buf, len);
        /* The only error that can be returned from ff_mpegts_parse_packet
         * is "no more data to return from the provided buffer", so return
         * AVERROR(EAGAIN) for all errors */
        if (ret < 0)
            return AVERROR(EAGAIN);
        if (ret < len) {
            s->read_buf_size = len - ret;
            memcpy(s->buf, buf + ret, s->read_buf_size);
            s->read_buf_index = 0;
            return 1;
        }
        return 0;
    } else if (s->parse_packet) {
        rv = s->parse_packet(s->ic, s->dynamic_protocol_context,
                             s->st, pkt, &timestamp, buf, len, flags);
    } else {
        // at this point, the RTP header has been stripped;  This is ASSUMING that there is only 1 CSRC, which in't wise.
        switch(st->codec->codec_id) {
        case CODEC_ID_MP2:
        case CODEC_ID_MP3:
            /* better than nothing: skip mpeg audio RTP header */
            if (len <= 4)
                return -1;
            h = AV_RB32(buf);
            len -= 4;
            buf += 4;
            av_new_packet(pkt, len);
            memcpy(pkt->data, buf, len);
            break;
        case CODEC_ID_MPEG1VIDEO:
        case CODEC_ID_MPEG2VIDEO:
            /* better than nothing: skip mpeg video RTP header */
            if (len <= 4)
                return -1;
            h = AV_RB32(buf);
            buf += 4;
            len -= 4;
            if (h & (1 << 26)) {
                /* mpeg2 */
                if (len <= 4)
                    return -1;
                buf += 4;
                len -= 4;
            }
            av_new_packet(pkt, len);
            memcpy(pkt->data, buf, len);
            break;
        default:
            av_new_packet(pkt, len);
            memcpy(pkt->data, buf, len);
            break;
        }

        pkt->stream_index = st->index;
    }

    // now perform timestamp things....
    finalize_packet(s, pkt, timestamp);

    return rv;
}
Ejemplo n.º 4
0
/**
 * Parse an RTP or RTCP packet directly sent as a buffer.
 * @param s RTP parse context.
 * @param pkt returned packet
 * @param buf input buffer or NULL to read the next packets
 * @param len buffer len
 * @return 0 if a packet is returned, 1 if a packet is returned and more can follow
 * (use buf as NULL to read the next). -1 if no packet (error or no more packet).
 */
int rtp_parse_packet(RTPDemuxContext *s, AVPacket *pkt,
                     const uint8_t *buf, int len)
{
    unsigned int ssrc, h;
    int payload_type, seq, ret, flags = 0;
    AVStream *st;
    uint32_t timestamp;
    int rv= 0;

    if (!buf) {
        /* return the next packets, if any */
        if(s->st && s->parse_packet) {
            timestamp= 0; ///< Should not be used if buf is NULL, but should be set to the timestamp of the packet returned....
            rv= s->parse_packet(s->ic, s->dynamic_protocol_context,
                                s->st, pkt, &timestamp, NULL, 0, flags);
            finalize_packet(s, pkt, timestamp);
            return rv;
        } else {
            // TODO: Move to a dynamic packet handler (like above)
            if (s->read_buf_index >= s->read_buf_size)
                return -1;
            ret = ff_mpegts_parse_packet(s->ts, pkt, s->buf + s->read_buf_index,
                                      s->read_buf_size - s->read_buf_index);
            if (ret < 0)
                return -1;
            s->read_buf_index += ret;
            if (s->read_buf_index < s->read_buf_size)
                return 1;
            else
                return 0;
        }
    }

    if (len < 12)
        return -1;

    if ((buf[0] & 0xc0) != (RTP_VERSION << 6))
        return -1;
    if (buf[1] >= 200 && buf[1] <= 204) {
        rtcp_parse_packet(s, buf, len);
        return -1;
    }
    payload_type = buf[1] & 0x7f;
    if (buf[1] & 0x80)
        flags |= RTP_FLAG_MARKER;
    seq  = AV_RB16(buf + 2);
    timestamp = AV_RB32(buf + 4);
    ssrc = AV_RB32(buf + 8);
    /* store the ssrc in the RTPDemuxContext */
    s->ssrc = ssrc;

    /* NOTE: we can handle only one payload type */
    if (s->payload_type != payload_type)
        return -1;

    st = s->st;
    // only do something with this if all the rtp checks pass...
    if(!rtp_valid_packet_in_sequence(&s->statistics, seq))
    {
        av_log(st?st->codec:NULL, AV_LOG_ERROR, "RTP: PT=%02x: bad cseq %04x expected=%04x\n",
               payload_type, seq, ((s->seq + 1) & 0xffff));
        return -1;
    }

    s->seq = seq;
    len -= 12;
    buf += 12;

    if (!st) {
        /* specific MPEG2TS demux support */
        ret = ff_mpegts_parse_packet(s->ts, pkt, buf, len);
        if (ret < 0)
            return -1;
        if (ret < len) {
            s->read_buf_size = len - ret;
            memcpy(s->buf, buf + ret, s->read_buf_size);
            s->read_buf_index = 0;
            return 1;
        }
        return 0;
    } else if (s->parse_packet) {
        rv = s->parse_packet(s->ic, s->dynamic_protocol_context,
                             s->st, pkt, &timestamp, buf, len, flags);
    } else {
        // at this point, the RTP header has been stripped;  This is ASSUMING that there is only 1 CSRC, which in't wise.
        switch(st->codec->codec_id) {
        case CODEC_ID_MP2:
        case CODEC_ID_MP3:
            /* better than nothing: skip mpeg audio RTP header */
            if (len <= 4)
                return -1;
            h = AV_RB32(buf);
            len -= 4;
            buf += 4;
            av_new_packet(pkt, len);
            memcpy(pkt->data, buf, len);
            break;
        case CODEC_ID_MPEG1VIDEO:
        case CODEC_ID_MPEG2VIDEO:
            /* better than nothing: skip mpeg video RTP header */
            if (len <= 4)
                return -1;
            h = AV_RB32(buf);
            buf += 4;
            len -= 4;
            if (h & (1 << 26)) {
                /* mpeg2 */
                if (len <= 4)
                    return -1;
                buf += 4;
                len -= 4;
            }
            av_new_packet(pkt, len);
            memcpy(pkt->data, buf, len);
            break;
            // moved from below, verbatim.  this is because this section handles packets, and the lower switch handles
            // timestamps.
            // TODO: Put this into a dynamic packet handler...
        case CODEC_ID_AAC:
            if (rtp_parse_mp4_au(s, buf))
                return -1;
            {
                RTPPayloadData *infos = s->rtp_payload_data;
                if (infos == NULL)
                    return -1;
                buf += infos->au_headers_length_bytes + 2;
                len -= infos->au_headers_length_bytes + 2;

                /* XXX: Fixme we only handle the case where rtp_parse_mp4_au define
                    one au_header */
                av_new_packet(pkt, infos->au_headers[0].size);
                memcpy(pkt->data, buf, infos->au_headers[0].size);
                buf += infos->au_headers[0].size;
                len -= infos->au_headers[0].size;
            }
            s->read_buf_size = len;
            rv= 0;
            break;
        default:
            av_new_packet(pkt, len);
            memcpy(pkt->data, buf, len);
            break;
        }

        pkt->stream_index = st->index;
    }

    // now perform timestamp things....
    finalize_packet(s, pkt, timestamp);

    return rv;
}