/// RFC3016 RTP Payload Format for MPEG-4 Audio/Visual Streams
/// RFC6416 RTP Payload Format for MPEG-4 Audio/Visual Streams

#include "rtp-packet.h"
#include "rtp-profile.h"
#include "rtp-payload-helper.h"
#include "rtp-payload-internal.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <errno.h>

static int rtp_decode_mp4a_latm(void *p, const void *packet, int bytes)
{
    int len;
    const uint8_t *ptr, *pend;
    struct rtp_packet_t pkt;
    struct rtp_payload_helper_t *helper;

    helper = (struct rtp_payload_helper_t *)p;
    if (!helper || 0 != rtp_packet_deserialize(&pkt, packet, bytes) || pkt.payloadlen < 4)
        return -EINVAL;

    rtp_payload_check(helper, &pkt);

    // save payload
    if (0 == helper->size) {
        ptr = (const uint8_t *)pkt.payload;
        for (pend = ptr + pkt.payloadlen; ptr < pend; ptr += len) {
            // ISO/IEC 14496-3:200X(E)
            // Table 1.44 - Syntax of PayloadLengthInfo() (p84)
            // Table 1.45 - Syntax of PayloadMux()
            for (len = 0; ptr < pend; ptr++) {
                len += *ptr;
                if (255 != *ptr) {
                    ++ptr;
                    break;
                }
            }

            if (ptr + len > pend) {
                assert(0);
                // helper->size = 0;
                helper->lost = 1;
                // helper->flags |= RTP_PAYLOAD_FLAG_PACKET_LOST;
                return -1; // invalid packet
            }

            // TODO: add ADTS/ASC ???
            pkt.payload = ptr;
            pkt.payloadlen = len;
            rtp_payload_write(helper, &pkt);

            if (ptr + len < pend || pkt.rtp.m) {
                rtp_payload_onframe(helper);
            }
        }
    } else {
        // RFC6416 6.3. Fragmentation of MPEG-4 Audio Bitstream (p17)
        // It is RECOMMENDED to put one audioMuxElement in each RTP packet. If
        // the size of an audioMuxElement can be kept small enough that the size
        // of the RTP packet containing it does not exceed the size of the Path
        // MTU, this will be no problem.If it cannot, the audioMuxElement
        // SHALL be fragmented and spread across multiple packets.
        rtp_payload_write(helper, &pkt);
        if (pkt.rtp.m) {
            rtp_payload_onframe(helper);
        }
    }

    return helper->lost ? 0 : 1; // packet handled
}

struct rtp_payload_decode_t *rtp_mp4a_latm_decode()
{
    static struct rtp_payload_decode_t unpacker = {
        rtp_payload_helper_create,
        rtp_payload_helper_destroy,
        rtp_decode_mp4a_latm,
    };

    return &unpacker;
}
