﻿#include "MP3Rtp.h"
#define MPEG12_HEADER_LEN 4

namespace mediakit {

//MPEG Audio-specific header
/*
 0               1               2               3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|             MBZ               |            Frag_offset        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
    

MP3RtpEncoder::MP3RtpEncoder(int sample_rate, int channels, int sample_bit) {
    _sample_rate = sample_rate;
    _channels = channels;
    _sample_bit = sample_bit;
}

void MP3RtpEncoder::outputRtp(const char *data, size_t len, size_t offset, bool mark, uint64_t stamp) {
    auto rtp = getRtpInfo().makeRtp(TrackAudio, nullptr, len + 4, mark, stamp);
    auto payload = rtp->data() + RtpPacket::kRtpTcpHeaderSize + RtpPacket::kRtpHeaderSize;
    payload[0] = 0;
    payload[1] = 0;
    payload[2] = offset >> 8;
    payload[3] = offset ;
    memcpy(payload + 4, data, len);
    RtpCodec::inputRtp(std::move(rtp), false);
}

bool MP3RtpEncoder::inputFrame(const Frame::Ptr &frame) {
    auto ptr = frame->data() + frame->prefixSize();
    auto size = frame->size() - frame->prefixSize();
    auto remain_size = size;
    auto max_size = getRtpInfo().getMaxSize() - MPEG12_HEADER_LEN;
    int  offset = 0;
    while (remain_size > 0) {
        if (remain_size <= max_size) {
            outputRtp(ptr, remain_size, offset, true, frame->dts());
            break;
        }
        outputRtp(ptr, max_size, offset, false, frame->dts());
        ptr += max_size;
        remain_size -= max_size;
        offset += max_size;
    }
    return true;
}

/////////////////////////////////////////////////////////////////////////////////////

MP3RtpDecoder::MP3RtpDecoder() {
    obtainFrame();
}

void MP3RtpDecoder::obtainFrame() {
    _frame = FrameImp::create();
    _frame->_codec_id = CodecMP3;
}

bool MP3RtpDecoder::inputRtp(const RtpPacket::Ptr &rtp, bool key_pos) {
    auto payload_size = rtp->getPayloadSize();
    if (payload_size <= MPEG12_HEADER_LEN) {
        return false;
    }
    auto stamp = rtp->getStampMS();
    auto ptr = rtp->getPayload();

    _frame->_buffer.append((char *)ptr + MPEG12_HEADER_LEN, payload_size - MPEG12_HEADER_LEN);
    flushData();

    _last_dts = stamp;
    return false;
}

void MP3RtpDecoder::flushData() {
    RtpCodec::inputFrame(_frame);
    obtainFrame();
}

} // namespace mediakit