/* INTEL CONFIDENTIAL
* Copyright (c) 2009 Intel Corporation.  All rights reserved.
*
* The source code contained or described herein and all documents
* related to the source code ("Material") are owned by Intel
* Corporation or its suppliers or licensors.  Title to the
* Material remains with Intel Corporation or its suppliers and
* licensors.  The Material contains trade secrets and proprietary
* and confidential information of Intel or its suppliers and
* licensors. The Material is protected by worldwide copyright and
* trade secret laws and treaty provisions.  No part of the Material
* may be used, copied, reproduced, modified, published, uploaded,
* posted, transmitted, distributed, or disclosed in any way without
* Intel's prior express written permission.
*
* No license under any patent, copyright, trade secret or other
* intellectual property right is granted to or conferred upon you
* by disclosure or delivery of the Materials, either expressly, by
* implication, inducement, estoppel or otherwise. Any license
* under such intellectual property rights must be express and
* approved by Intel in writing.
*
*/



#include "AsfHeaderParser.h"
#include "AsfDataParser.h"
#include "AsfIndexParser.h"
#include "AsfStreamParser.h"
#include <string.h>


AsfStreamParser::AsfStreamParser(void)
    : mDataPacketSize(0),
      mTimeOffsetMs(0),
      mHeaderParsed(false) {
    mHeaderParser = new AsfHeaderParser;
    mDataParser = new AsfDataParser;
    mSimpleIndexParser = NULL;
}

AsfStreamParser::~AsfStreamParser(void) {
    delete mHeaderParser;
    delete mDataParser;
    delete mSimpleIndexParser;
}

bool AsfStreamParser::isSimpleIndexObject(uint8_t *guid) {
    GUID *id = (GUID *)guid;
    return (*id == ASF_Simple_Index_Object);
}

bool AsfStreamParser::isHeaderObject(uint8_t *guid) {
    GUID *id = (GUID *)guid;
    return (*id == ASF_Header_Object);
}

int AsfStreamParser::parseHeaderObject(uint8_t *buffer, uint32_t size) {
    int status = mHeaderParser->parse(buffer, size);
    if (status != ASF_PARSER_SUCCESS) {
        return status;
    }

    mDataPacketSize = mHeaderParser->getDataPacketSize();
    mTimeOffsetMs = mHeaderParser->getTimeOffset() / ASF_SCALE_MS_TO_100NANOSEC;

    if (mTimeOffsetMs == 0) {
        // offset of PTS in milliseconds due to buffering
        mTimeOffsetMs = mHeaderParser->getPreroll();
    }
    mHeaderParsed = true;
    return ASF_PARSER_SUCCESS;
}

AsfAudioStreamInfo* AsfStreamParser::getAudioInfo() const {
    return mHeaderParser->getAudioInfo();
}

AsfVideoStreamInfo* AsfStreamParser::getVideoInfo() const {
    return mHeaderParser->getVideoInfo();
}

AsfFileMediaInfo* AsfStreamParser::getFileInfo() const {
    return mHeaderParser->getFileInfo();
}

uint64_t AsfStreamParser::getDuration() {
    return mHeaderParser->getDuration();
}

uint32_t AsfStreamParser::getDataPacketSize() {
    return mHeaderParser->getDataPacketSize();
}

bool AsfStreamParser::hasVideo() {
    return mHeaderParser->hasVideo();
}

bool AsfStreamParser::hasAudio() {
    return mHeaderParser->hasAudio();
}

int AsfStreamParser::parseDataObjectHeader(uint8_t *buffer, uint32_t size) {
    if (mHeaderParsed == false) {
        return ASF_PARSER_INVALID_STATE;
    }
    return mDataParser->parseHeader(buffer, size);
}

int AsfStreamParser::parseDataPacket(uint8_t *buffer, uint32_t size, AsfPayloadDataInfo **out) {
    if (mHeaderParsed == false) {
        return ASF_PARSER_INVALID_STATE;
    }

    if (size != mDataPacketSize) {
        return ASF_PARSER_BAD_DATA;
    }

    if (out == NULL) {
        return ASF_PARSER_NULL_POINTER;
    }

    int status = mDataParser->parsePacket(buffer, size, out);
    if (status != ASF_PARSER_SUCCESS) {
        return status;
    }

    if (mTimeOffsetMs == 0) {
        return ASF_PARSER_SUCCESS;
    }

    // update presentation time stamp
    AsfPayloadDataInfo *next = *out;
    while (next) {
        if (next->presentationTime >= mTimeOffsetMs) {
            next->presentationTime -= mTimeOffsetMs;
        }
        else {
            // TODO:
            next->presentationTime = 0;
            //return ASF_PARSER_BAD_VALUE;
        }
        next = next->next;
    }
    return status;
}

void AsfStreamParser::releasePayloadDataInfo(AsfPayloadDataInfo *info) {
    mDataParser->releasePayloadDataInfo(info);
}


int AsfStreamParser::parseSimpleIndexObject(uint8_t *buffer, uint32_t size) {
    if (mHeaderParsed == false) {
        return ASF_PARSER_INVALID_STATE;
    }

    if (mHeaderParser->isSeekable() == false) {
        return ASF_PARSER_FAILED;
    }

    if (mSimpleIndexParser) {
        delete mSimpleIndexParser;
        mSimpleIndexParser = NULL;
    }

    mSimpleIndexParser = new AsfSimpleIndexParser;

    if (mSimpleIndexParser == NULL) return ASF_PARSER_FAILED;

    if (ASF_PARSER_SUCCESS != mSimpleIndexParser->parse(buffer, size)) {
        delete mSimpleIndexParser;
        mSimpleIndexParser = NULL;
        return ASF_PARSER_FAILED;
    }

    return ASF_PARSER_SUCCESS;
}

AsfSimpleIndexInfo* AsfStreamParser::getIndexInfo() const {
    if (!mSimpleIndexParser) return NULL;

    return mSimpleIndexParser->getIndexInfo();
}

int AsfStreamParser::seek(
        uint64_t seekTime,
        bool nextSync,
        uint32_t& packetNumber,
        uint64_t& targetTime) {
    if (mHeaderParsed == false) {
        return ASF_PARSER_INVALID_STATE;
    }

    if (mHeaderParser->isSeekable() == false) {
        return ASF_PARSER_FAILED;
    }

    if (mSimpleIndexParser) {
        seekTime += mHeaderParser->getPreroll()*ASF_SCALE_MS_TO_100NANOSEC;  //add preroll start time
        return mSimpleIndexParser->seek(seekTime, nextSync, packetNumber, targetTime);
    }
    else {
        // no index object, need to seek using average bitrate method

        if (mHeaderParser->hasVideo()){
            return ASF_PARSER_FAILED;
        }

        if (!mHeaderParser->hasAudio()) {
            return ASF_PARSER_FAILED;
        }

        int totalByteRate=0;
        AsfAudioStreamInfo* audioInfo = mHeaderParser->getAudioInfo();
        while (audioInfo != NULL) {
            totalByteRate += audioInfo->avgByteRate;
            audioInfo = audioInfo->next;
        }

        if (totalByteRate == 0) {
            return ASF_PARSER_FAILED;
        }

        uint32_t packetSize = mHeaderParser->getDataPacketSize();
        if (packetSize <= 0) {
            return ASF_PARSER_FAILED;
        }

        packetNumber = seekTime/10000000 * totalByteRate / packetSize;
        targetTime = seekTime;
        return ASF_PARSER_SUCCESS;
    }
}

uint32_t AsfStreamParser::getMaxObjectSize() {
    if (!mSimpleIndexParser) return NULL;
    return mSimpleIndexParser->getMaximumPacketCount() * mDataPacketSize;
}

