/*
 * RTP packetization for Xiph audio and video
 * Copyright (c) 2010 Josh Allmann
 *
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * FFmpeg is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with FFmpeg; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include "libavutil/avassert.h"
#include "libavutil/intreadwrite.h"

#include "avformat.h"
#include "rtpenc.h"

/**
 * Packetize Xiph frames into RTP according to
 * RFC 5215 (Vorbis) and the Theora RFC draft.
 * (http://svn.xiph.org/trunk/theora/doc/draft-ietf-avt-rtp-theora-00.txt)
 */
void ff_rtp_send_xiph(AVFormatContext *s1, const uint8_t *buff, int size)
{
    RTPMuxContext *s = s1->priv_data;
    AVStream *st = s1->streams[0];
    int max_pkt_size, xdt, frag;
    uint8_t *q;

    max_pkt_size = s->max_payload_size - 6; // ident+frag+tdt/vdt+pkt_num+pkt_length

    // set xiph data type
    switch (*buff) {
    case 0x01:   // vorbis id
    case 0x05:   // vorbis setup
    case 0x80:   // theora header
    case 0x82:   // theora tables
        xdt = 1; // packed config payload
        break;
    case 0x03:   // vorbis comments
    case 0x81:   // theora comments
        xdt = 2; // comment payload
        break;
    default:
        xdt = 0; // raw data payload
        break;
    }

    // Set ident.
    // Probably need a non-fixed way of generating
    // this, but it has to be done in SDP and passed in from there.
    q = s->buf;
    *q++ = (RTP_XIPH_IDENT >> 16) & 0xff;
    *q++ = (RTP_XIPH_IDENT >>  8) & 0xff;
    *q++ = (RTP_XIPH_IDENT      ) & 0xff;

    // set fragment
    // 0 - whole frame (possibly multiple frames)
    // 1 - first fragment
    // 2 - fragment continuation
    // 3 - last fragment
    frag = size <= max_pkt_size ? 0 : 1;

    if (!frag && !xdt) { // do we have a whole frame of raw data?
        uint8_t *end_ptr = s->buf + 6 + max_pkt_size; // what we're allowed to write
        uint8_t *ptr     = s->buf_ptr + 2 + size; // what we're going to write
        int remaining    = end_ptr - ptr;

        av_assert1(s->num_frames <= s->max_frames_per_packet);
        if (s->num_frames > 0 &&
            (remaining < 0 ||
             s->num_frames == s->max_frames_per_packet ||
             av_compare_ts(s->cur_timestamp - s->timestamp, st->time_base,
                           s1->max_delay, AV_TIME_BASE_Q) >= 0)) {
            // send previous packets now; no room for new data, or too much delay
            ff_rtp_send_data(s1, s->buf, s->buf_ptr - s->buf, 0);
            s->num_frames = 0;
        }

        // buffer current frame to send later
        if (0 == s->num_frames)
            s->timestamp = s->cur_timestamp;
        s->num_frames++;

        // Set packet header. Normally, this is OR'd with frag and xdt,
        // but those are zero, so omitted here
        *q++ = s->num_frames;

        if (s->num_frames > 1)
            q = s->buf_ptr; // jump ahead if needed
        AV_WB16(q, size);
        q += 2;
        memcpy(q, buff, size);
        q += size;
        s->buf_ptr = q;

        return;
    } else if (s->num_frames) {
        // immediately send buffered frames if buffer is not raw data,
        // or if current frame is fragmented.
        ff_rtp_send_data(s1, s->buf, s->buf_ptr - s->buf, 0);
    }

    s->timestamp = s->cur_timestamp;
    s->num_frames = 0;
    s->buf_ptr = q;
    while (size > 0) {
        int len = (!frag || frag == 3) ? size : max_pkt_size;
        q = s->buf_ptr;

        // set packet headers
        *q++ = (frag << 6) | (xdt << 4); // num_frames = 0
        AV_WB16(q, len);
        q += 2;
        // set packet body
        memcpy(q, buff, len);
        q += len;
        buff += len;
        size -= len;

        ff_rtp_send_data(s1, s->buf, q - s->buf, 0);

        frag = size <= max_pkt_size ? 3 : 2;
    }
}
