/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//#define LOG_NDEBUG 0
#define LOG_TAG "AMPEG4AudioAssembler"

#include "AMPEG4AudioAssembler.h"

#include "ARTPSource.h"

#include <media/stagefright/foundation/hexdump.h>
#include <media/stagefright/foundation/ABitReader.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/MediaErrors.h>

#include <ctype.h>

namespace android {

static bool GetAttribute(const char *s, const char *key, AString *value) {
    value->clear();

    size_t keyLen = strlen(key);

    for (;;) {
        while (isspace(*s)) {
            ++s;
        }

        const char *colonPos = strchr(s, ';');

        size_t len =
            (colonPos == NULL) ? strlen(s) : colonPos - s;

        if (len >= keyLen + 1 && s[keyLen] == '=' && !strncmp(s, key, keyLen)) {
            value->setTo(&s[keyLen + 1], len - keyLen - 1);
            return true;
        }

        if (colonPos == NULL) {
            return false;
        }

        s = colonPos + 1;
    }
}

static sp<ABuffer> decodeHex(const AString &s) {
    if ((s.size() % 2) != 0) {
        return NULL;
    }

    size_t outLen = s.size() / 2;
    sp<ABuffer> buffer = new ABuffer(outLen);
    uint8_t *out = buffer->data();

    uint8_t accum = 0;
    for (size_t i = 0; i < s.size(); ++i) {
        char c = s.c_str()[i];
        unsigned value;
        if (c >= '0' && c <= '9') {
            value = c - '0';
        } else if (c >= 'a' && c <= 'f') {
            value = c - 'a' + 10;
        } else if (c >= 'A' && c <= 'F') {
            value = c - 'A' + 10;
        } else {
            return NULL;
        }

        accum = (accum << 4) | value;

        if (i & 1) {
            *out++ = accum;

            accum = 0;
        }
    }

    return buffer;
}

static status_t parseAudioObjectType(
        ABitReader *bits, unsigned *audioObjectType) {
    *audioObjectType = bits->getBits(5);
    if ((*audioObjectType) == 31) {
        *audioObjectType = 32 + bits->getBits(6);
    }

    return OK;
}

static status_t parseGASpecificConfig(
        ABitReader *bits,
        unsigned audioObjectType, unsigned channelConfiguration) {
    unsigned frameLengthFlag __unused = bits->getBits(1);
    unsigned dependsOnCoreCoder = bits->getBits(1);
    if (dependsOnCoreCoder) {
        /* unsigned coreCoderDelay = */bits->getBits(1);
    }
    unsigned extensionFlag = bits->getBits(1);

    if (!channelConfiguration) {
        // program_config_element
        return ERROR_UNSUPPORTED;  // XXX to be implemented
    }

    if (audioObjectType == 6 || audioObjectType == 20) {
        /* unsigned layerNr = */bits->getBits(3);
    }

    if (extensionFlag) {
        if (audioObjectType == 22) {
            /* unsigned numOfSubFrame = */bits->getBits(5);
            /* unsigned layerLength = */bits->getBits(11);
        } else if (audioObjectType == 17 || audioObjectType == 19
                || audioObjectType == 20 || audioObjectType == 23) {
            /* unsigned aacSectionDataResilienceFlag = */bits->getBits(1);
            /* unsigned aacScalefactorDataResilienceFlag = */bits->getBits(1);
            /* unsigned aacSpectralDataResilienceFlag = */bits->getBits(1);
        }

        unsigned extensionFlag3 = bits->getBits(1);
        CHECK_EQ(extensionFlag3, 0u);  // TBD in version 3
    }

    return OK;
}

static status_t parseAudioSpecificConfig(ABitReader *bits, sp<ABuffer> *asc) {
    const uint8_t *dataStart = bits->data();
    size_t totalNumBits = bits->numBitsLeft();

    unsigned audioObjectType;
    CHECK_EQ(parseAudioObjectType(bits, &audioObjectType), (status_t)OK);

    unsigned samplingFreqIndex = bits->getBits(4);
    if (samplingFreqIndex == 0x0f) {
        /* unsigned samplingFrequency = */bits->getBits(24);
    }

    unsigned channelConfiguration = bits->getBits(4);

    unsigned extensionAudioObjectType = 0;
    unsigned sbrPresent = 0;

    if (audioObjectType == 5) {
        extensionAudioObjectType = audioObjectType;
        sbrPresent = 1;
        unsigned extensionSamplingFreqIndex = bits->getBits(4);
        if (extensionSamplingFreqIndex == 0x0f) {
            /* unsigned extensionSamplingFrequency = */bits->getBits(24);
        }
        CHECK_EQ(parseAudioObjectType(bits, &audioObjectType), (status_t)OK);
    }

    CHECK((audioObjectType >= 1 && audioObjectType <= 4)
        || (audioObjectType >= 6 && audioObjectType <= 7)
        || audioObjectType == 17
        || (audioObjectType >= 19 && audioObjectType <= 23));

    CHECK_EQ(parseGASpecificConfig(
                bits, audioObjectType, channelConfiguration), (status_t)OK);

    if (audioObjectType == 17
            || (audioObjectType >= 19 && audioObjectType <= 27)) {
        unsigned epConfig = bits->getBits(2);
        if (epConfig == 2 || epConfig == 3) {
            // ErrorProtectionSpecificConfig
            return ERROR_UNSUPPORTED;  // XXX to be implemented

            if (epConfig == 3) {
                unsigned directMapping = bits->getBits(1);
                CHECK_EQ(directMapping, 1u);
            }
        }
    }

    if (extensionAudioObjectType != 5 && bits->numBitsLeft() >= 16) {
        size_t numBitsLeftAtStart = bits->numBitsLeft();

        unsigned syncExtensionType = bits->getBits(11);
        if (syncExtensionType == 0x2b7) {
            ALOGI("found syncExtension");

            CHECK_EQ(parseAudioObjectType(bits, &extensionAudioObjectType),
                     (status_t)OK);

            sbrPresent = bits->getBits(1);

            if (sbrPresent == 1) {
                unsigned extensionSamplingFreqIndex = bits->getBits(4);
                if (extensionSamplingFreqIndex == 0x0f) {
                    /* unsigned extensionSamplingFrequency = */bits->getBits(24);
                }
            }

            size_t numBitsInExtension =
                numBitsLeftAtStart - bits->numBitsLeft();

            if (numBitsInExtension & 7) {
                // Apparently an extension is always considered an even
                // multiple of 8 bits long.

                ALOGI("Skipping %zu bits after sync extension",
                     8 - (numBitsInExtension & 7));

                bits->skipBits(8 - (numBitsInExtension & 7));
            }
        } else {
            bits->putBits(syncExtensionType, 11);
        }
    }

    if (asc != NULL) {
        size_t bitpos = totalNumBits & 7;

        ABitReader bs(dataStart, (totalNumBits + 7) / 8);

        totalNumBits -= bits->numBitsLeft();

        size_t numBytes = (totalNumBits + 7) / 8;

        *asc = new ABuffer(numBytes);

        if (bitpos & 7) {
            bs.skipBits(8 - (bitpos & 7));
        }

        uint8_t *dstPtr = (*asc)->data();
        while (numBytes > 0) {
            *dstPtr++ = bs.getBits(8);
            --numBytes;
        }
    }

    return OK;
}

static status_t parseStreamMuxConfig(
        ABitReader *bits,
        unsigned *numSubFrames,
        unsigned *frameLengthType,
        ssize_t *fixedFrameLength,
        bool *otherDataPresent,
        unsigned *otherDataLenBits) {
    unsigned audioMuxVersion = bits->getBits(1);

    unsigned audioMuxVersionA = 0;
    if (audioMuxVersion == 1) {
        audioMuxVersionA = bits->getBits(1);
    }

    CHECK_EQ(audioMuxVersionA, 0u);  // otherwise future spec

    if (audioMuxVersion != 0) {
        return ERROR_UNSUPPORTED;  // XXX to be implemented;
    }
    CHECK_EQ(audioMuxVersion, 0u);  // XXX to be implemented

    unsigned allStreamsSameTimeFraming = bits->getBits(1);
    CHECK_EQ(allStreamsSameTimeFraming, 1u);  // There's only one stream.

    *numSubFrames = bits->getBits(6);
    unsigned numProgram = bits->getBits(4);
    CHECK_EQ(numProgram, 0u);  // disabled in RTP LATM

    unsigned numLayer = bits->getBits(3);
    CHECK_EQ(numLayer, 0u);  // disabled in RTP LATM

    if (audioMuxVersion == 0) {
        // AudioSpecificConfig
        CHECK_EQ(parseAudioSpecificConfig(bits, NULL /* asc */), (status_t)OK);
    } else {
        TRESPASS();  // XXX to be implemented
    }

    *frameLengthType = bits->getBits(3);
    *fixedFrameLength = -1;

    switch (*frameLengthType) {
        case 0:
        {
            /* unsigned bufferFullness = */bits->getBits(8);

            // The "coreFrameOffset" does not apply since there's only
            // a single layer.
            break;
        }

        case 1:
        {
            *fixedFrameLength = bits->getBits(9);
            break;
        }

        case 2:
        {
            return ERROR_UNSUPPORTED;
        }

        case 3:
        case 4:
        case 5:
        {
            /* unsigned CELPframeLengthTableIndex = */bits->getBits(6);
            break;
        }

        case 6:
        case 7:
        {
            /* unsigned HVXCframeLengthTableIndex = */bits->getBits(1);
            break;
        }

        default:
            break;
    }

    *otherDataPresent = bits->getBits(1);
    *otherDataLenBits = 0;
    if (*otherDataPresent) {
        if (audioMuxVersion == 1) {
            TRESPASS();  // XXX to be implemented
        } else {
            *otherDataLenBits = 0;

            unsigned otherDataLenEsc;
            do {
                (*otherDataLenBits) <<= 8;
                otherDataLenEsc = bits->getBits(1);
                unsigned otherDataLenTmp = bits->getBits(8);
                (*otherDataLenBits) += otherDataLenTmp;
            } while (otherDataLenEsc);
        }
    }

    unsigned crcCheckPresent = bits->getBits(1);
    if (crcCheckPresent) {
        /* unsigned crcCheckSum = */bits->getBits(8);
    }

    return OK;
}

sp<ABuffer> AMPEG4AudioAssembler::removeLATMFraming(const sp<ABuffer> &buffer) {
    CHECK(!mMuxConfigPresent);  // XXX to be implemented

    sp<ABuffer> out = new ABuffer(buffer->size());
    out->setRange(0, 0);

    size_t offset = 0;
    uint8_t *ptr = buffer->data();

    for (size_t i = 0; i <= mNumSubFrames; ++i) {
        // parse PayloadLengthInfo

        unsigned payloadLength = 0;

        switch (mFrameLengthType) {
            case 0:
            {
                unsigned muxSlotLengthBytes = 0;
                unsigned tmp;
                do {
                    CHECK_LT(offset, buffer->size());
                    tmp = ptr[offset++];
                    muxSlotLengthBytes += tmp;
                } while (tmp == 0xff);

                payloadLength = muxSlotLengthBytes;
                break;
            }

            case 2:
            {
                // reserved

                TRESPASS();
                break;
            }

            default:
            {
                CHECK_GE(mFixedFrameLength, 0);

                payloadLength = mFixedFrameLength;
                break;
            }
        }

        CHECK_LE(offset + payloadLength, buffer->size());

        memcpy(out->data() + out->size(), &ptr[offset], payloadLength);
        out->setRange(0, out->size() + payloadLength);

        offset += payloadLength;

        if (mOtherDataPresent) {
            // We want to stay byte-aligned.

            CHECK((mOtherDataLenBits % 8) == 0);
            CHECK_LE(offset + (mOtherDataLenBits / 8), buffer->size());
            offset += mOtherDataLenBits / 8;
        }
    }

    if (offset < buffer->size()) {
        ALOGI("ignoring %zu bytes of trailing data", buffer->size() - offset);
    }
    CHECK_LE(offset, buffer->size());

    return out;
}

AMPEG4AudioAssembler::AMPEG4AudioAssembler(
        const sp<AMessage> &notify, const AString &params)
    : mNotifyMsg(notify),
      mMuxConfigPresent(false),
      mAccessUnitRTPTime(0),
      mNextExpectedSeqNoValid(false),
      mNextExpectedSeqNo(0),
      mAccessUnitDamaged(false) {
    AString val;
    if (!GetAttribute(params.c_str(), "cpresent", &val)) {
        mMuxConfigPresent = true;
    } else if (val == "0") {
        mMuxConfigPresent = false;
    } else {
        CHECK(val == "1");
        mMuxConfigPresent = true;
    }

    CHECK(GetAttribute(params.c_str(), "config", &val));

    sp<ABuffer> config = decodeHex(val);
    CHECK(config != NULL);

    ABitReader bits(config->data(), config->size());
    status_t err = parseStreamMuxConfig(
            &bits, &mNumSubFrames, &mFrameLengthType,
            &mFixedFrameLength,
            &mOtherDataPresent, &mOtherDataLenBits);

    if (err == ERROR_UNSUPPORTED) {
        ALOGW("Failed to parse stream mux config, using default values for playback.");
        mMuxConfigPresent = false;
        mNumSubFrames = 0;
        mFrameLengthType = 0;
        mOtherDataPresent = false;
        mOtherDataLenBits = 0;
        return;
    }
    CHECK_EQ(err, (status_t)NO_ERROR);
}

AMPEG4AudioAssembler::~AMPEG4AudioAssembler() {
}

ARTPAssembler::AssemblyStatus AMPEG4AudioAssembler::assembleMore(
        const sp<ARTPSource> &source) {
    AssemblyStatus status = addPacket(source);
    if (status == MALFORMED_PACKET) {
        mAccessUnitDamaged = true;
    }
    return status;
}

ARTPAssembler::AssemblyStatus AMPEG4AudioAssembler::addPacket(
        const sp<ARTPSource> &source) {
    List<sp<ABuffer> > *queue = source->queue();

    if (queue->empty()) {
        return NOT_ENOUGH_DATA;
    }

    if (mNextExpectedSeqNoValid) {
        List<sp<ABuffer> >::iterator it = queue->begin();
        while (it != queue->end()) {
            if ((uint32_t)(*it)->int32Data() >= mNextExpectedSeqNo) {
                break;
            }

            it = queue->erase(it);
        }

        if (queue->empty()) {
            return NOT_ENOUGH_DATA;
        }
    }

    sp<ABuffer> buffer = *queue->begin();

    if (!mNextExpectedSeqNoValid) {
        mNextExpectedSeqNoValid = true;
        mNextExpectedSeqNo = (uint32_t)buffer->int32Data();
    } else if ((uint32_t)buffer->int32Data() != mNextExpectedSeqNo) {
#if VERBOSE
        LOG(VERBOSE) << "Not the sequence number I expected";
#endif

        return WRONG_SEQUENCE_NUMBER;
    }

    uint32_t rtpTime;
    CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));

    if (mPackets.size() > 0 && rtpTime != mAccessUnitRTPTime) {
        submitAccessUnit();
    }
    mAccessUnitRTPTime = rtpTime;

    mPackets.push_back(buffer);

    queue->erase(queue->begin());
    ++mNextExpectedSeqNo;

    return OK;
}

void AMPEG4AudioAssembler::submitAccessUnit() {
    CHECK(!mPackets.empty());

#if VERBOSE
    LOG(VERBOSE) << "Access unit complete (" << mPackets.size() << " packets)";
#endif

    sp<ABuffer> accessUnit = MakeCompoundFromPackets(mPackets);
    accessUnit = removeLATMFraming(accessUnit);
    CopyTimes(accessUnit, *mPackets.begin());

#if 0
    printf(mAccessUnitDamaged ? "X" : ".");
    fflush(stdout);
#endif

    if (mAccessUnitDamaged) {
        accessUnit->meta()->setInt32("damaged", true);
    }

    mPackets.clear();
    mAccessUnitDamaged = false;

    sp<AMessage> msg = mNotifyMsg->dup();
    msg->setBuffer("access-unit", accessUnit);
    msg->post();
}

void AMPEG4AudioAssembler::packetLost() {
    CHECK(mNextExpectedSeqNoValid);
    ++mNextExpectedSeqNo;

    mAccessUnitDamaged = true;
}

void AMPEG4AudioAssembler::onByeReceived() {
    sp<AMessage> msg = mNotifyMsg->dup();
    msg->setInt32("eos", true);
    msg->post();
}

}  // namespace android
