/// RFC2250 3. Encapsulation of MPEG Elementary Streams (p4)

#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>

#define MPEG2VIDEO_EXTENSION_HEADER 0x04

static int rtp_decode_mpeg2es(void *p, const void *packet, int bytes)
{
    int n;
    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;

    if (RTP_PAYLOAD_MP3 != pkt.rtp.pt && RTP_PAYLOAD_MPV != pkt.rtp.pt) {
        assert(0);
        return -EINVAL;
    }

    rtp_payload_check(helper, &pkt);

    // save payload
    if (!helper->lost) {
        n = 4; // skip 3.4 MPEG Video-specific header
        if (RTP_PAYLOAD_MPV == pkt.rtp.pt && (((uint8_t *)pkt.payload)[4] & MPEG2VIDEO_EXTENSION_HEADER))
            n += 4; // 3.4.1 MPEG-2 Video-specific header extension

        assert(pkt.payloadlen > 4);
        if (pkt.payload && pkt.payloadlen > n) {
            pkt.payload = (uint8_t *)pkt.payload + n;
            pkt.payloadlen -= n;
            rtp_payload_write(helper, &pkt);
        }
    }

    // M bit: For video, set to 1 on packet containing MPEG frame end code, 0 otherwise.
    //        For audio, set to 1 on first packet of a "talk-spurt," 0 otherwise.
    if (pkt.rtp.m && RTP_PAYLOAD_MPV == pkt.rtp.pt) {
        rtp_payload_onframe(helper);
    }

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

struct rtp_payload_decode_t *rtp_mpeg1or2es_decode()
{
    static struct rtp_payload_decode_t unpacker = {
        rtp_payload_helper_create,
        rtp_payload_helper_destroy,
        rtp_decode_mpeg2es,
    };

    return &unpacker;
}
