/*
 * 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_TAG "XINGSEEKER"
#include <utils/Log.h>

#include "XINGSeeker.h"
#include <media/stagefright/foundation/avc_utils.h>

#include <media/stagefright/foundation/ByteUtils.h>

#include <media/MediaExtractorPluginApi.h>
#include <media/MediaExtractorPluginHelper.h>

namespace android {

XINGSeeker::XINGSeeker()
    : mDurationUs(-1),
      mSizeBytes(0),
      mEncoderDelay(0),
      mEncoderPadding(0),
      mTOCValid(false) {
}

bool XINGSeeker::getDuration(int64_t *durationUs) {
    if (mDurationUs < 0) {
        return false;
    }

    *durationUs = mDurationUs;

    return true;
}

bool XINGSeeker::getOffsetForTime(int64_t *timeUs, off64_t *pos) {
    if (mSizeBytes == 0 || mDurationUs < 0) {
        return false;
    }

    float percent = (float)(*timeUs) * 100 / mDurationUs;
    float fx;
    if( percent <= 0.0f ) {
        fx = 0.0f;
    } else if( percent >= 100.0f ) {
        fx = 256.0f;
    } else if (mTOCValid) {
        int a = (int)percent;
        float fa, fb;
        if ( a == 0 ) {
            fa = 0.0f;
        } else {
            fa = (float)mTOC[a-1];
        }
        if ( a < 99 ) {
            fb = (float)mTOC[a];
        } else {
            fb = 256.0f;
        }
        fx = fa + (fb-fa)*(percent-a);
    } else {
        fx = percent * 2.56f;
    }

    *pos = (int)((1.0f/256.0f)*fx*mSizeBytes) + mFirstFramePos;

    return true;
}

// static
XINGSeeker *XINGSeeker::CreateFromSource(
        DataSourceHelper *source, off64_t first_frame_pos) {

    uint8_t buffer[4];
    int offset = first_frame_pos;
    if (source->readAt(offset, &buffer, 4) < 4) { // get header
        return NULL;
    }
    offset += 4;

    int header = U32_AT(buffer);;
    size_t xingframesize = 0;
    int sampling_rate = 0;
    int num_channels;
    int samples_per_frame = 0;
    if (!GetMPEGAudioFrameSize(header, &xingframesize, &sampling_rate, &num_channels,
                               NULL, &samples_per_frame)) {
        return NULL;
    }
    uint8_t version = (buffer[1] >> 3) & 3;

    // determine offset of XING header
    if(version & 1) { // mpeg1
        if (num_channels != 1) offset += 32;
        else offset += 17;
    } else { // mpeg 2 or 2.5
        if (num_channels != 1) offset += 17;
        else offset += 9;
    }

    int xingbase = offset;

    if (source->readAt(offset, &buffer, 4) < 4) { // XING header ID
        return NULL;
    }
    offset += 4;
    // Check XING ID
    if ((buffer[0] != 'X') || (buffer[1] != 'i')
                || (buffer[2] != 'n') || (buffer[3] != 'g')) {
        if ((buffer[0] != 'I') || (buffer[1] != 'n')
                    || (buffer[2] != 'f') || (buffer[3] != 'o')) {
            return NULL;
        }
    }

    if (source->readAt(offset, &buffer, 4) < 4) { // flags
        return NULL;
    }
    offset += 4;
    uint32_t flags = U32_AT(buffer);

    XINGSeeker *seeker = new XINGSeeker;
    seeker->mFirstFramePos = first_frame_pos + xingframesize;

    if (flags & 0x0001) {  // Frames field is present
        if (source->readAt(offset, buffer, 4) < 4) {
            delete seeker;
            return NULL;
        }
        int32_t frames = U32_AT(buffer);
        // only update mDurationUs if the calculated duration is valid (non zero)
        // otherwise, leave duration at -1 so that getDuration() and getOffsetForTime()
        // return false when called, to indicate that this xing tag does not have the
        // requested information
        if (frames) {
            seeker->mDurationUs = (int64_t)frames * samples_per_frame * 1000000LL / sampling_rate;
        }
        offset += 4;
    }
    if (flags & 0x0002) {  // Bytes field is present
        if (source->readAt(offset, buffer, 4) < 4) {
            delete seeker;
            return NULL;
        }
        seeker->mSizeBytes = U32_AT(buffer);
        offset += 4;
    }
    if (flags & 0x0004) {  // TOC field is present
        if (source->readAt(offset + 1, seeker->mTOC, 99) < 99) {
            delete seeker;
            return NULL;
        }
        seeker->mTOCValid = true;
        offset += 100;
    }

#if 0
    if (flags & 0x0008) {  // Quality indicator field is present
        if (source->readAt(offset, buffer, 4) < 4) {
            delete seeker;
            return NULL;
        }
        // do something with the quality indicator
        offset += 4;
    }

    if (source->readAt(xingbase + 0xaf - 0x24, &buffer, 1) < 1) { // encoding flags
        delete seeker;
        return false;
    }

    ALOGV("nogap preceding: %s, nogap continued in next: %s",
              (buffer[0] & 0x80) ? "true" : "false",
              (buffer[0] & 0x40) ? "true" : "false");
#endif

    if (source->readAt(xingbase + 0xb1 - 0x24, &buffer, 3) == 3) {
        seeker->mEncoderDelay = (buffer[0] << 4) + (buffer[1] >> 4);
        seeker->mEncoderPadding = ((buffer[1] & 0xf) << 8) + buffer[2];
    }

    return seeker;
}

int32_t XINGSeeker::getEncoderDelay() {
    return mEncoderDelay;
}

int32_t XINGSeeker::getEncoderPadding() {
    return mEncoderPadding;
}

}  // namespace android

