/*
 *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "normal_test.h"

#include <time.h>
#include <sstream>
#include <string.h>

#include "gtest/gtest.h"
#include "testsupport/fileutils.h"

NormalTest::NormalTest()
:
Test("Normal Test 1", "A test of normal execution of the codec"),
_testNo(1),
_lengthEncFrame(0),
_appendNext(false)
{
}

NormalTest::NormalTest(std::string name, std::string description,
                       unsigned int testNo)
:
Test(name, description),
_requestKeyFrame(false),
_testNo(testNo),
_lengthEncFrame(0),
_appendNext(false)
{
}

NormalTest::NormalTest(std::string name, std::string description,
                       WebRtc_UWord32 bitRate, unsigned int testNo)
:
Test(name, description, bitRate),
_requestKeyFrame(false),
_testNo(testNo),
_lengthEncFrame(0),
_appendNext(false)
{
}

void
NormalTest::Setup()
{
    Test::Setup();
    std::stringstream ss;
    std::string strTestNo;
    ss << _testNo;
    ss >> strTestNo;

    // Check if settings exist. Otherwise use defaults.
    if (_outname == "")
    {
        _outname = webrtc::test::OutputPath() + "out_normaltest" + strTestNo +
            ".yuv";
    }

    if (_encodedName == "")
    {
        _encodedName = webrtc::test::OutputPath() + "encoded_normaltest" +
            strTestNo + ".yuv";
    }
    
    if ((_sourceFile = fopen(_inname.c_str(), "rb")) == NULL)
    {
        printf("Cannot read file %s.\n", _inname.c_str());
        exit(1);
    }

    if ((_encodedFile = fopen(_encodedName.c_str(), "wb")) == NULL)
    {
        printf("Cannot write encoded file.\n");
        exit(1);
    }

    char mode[3] = "wb";
    if (_appendNext)
    {
        strncpy(mode, "ab", 3);
    }

    if ((_decodedFile = fopen(_outname.c_str(), mode)) == NULL)
    {
        printf("Cannot write file %s.\n", _outname.c_str());
        exit(1);
    }

    _appendNext = true;
}

void
NormalTest::Teardown()
{
    Test::Teardown();
    fclose(_sourceFile);
    fclose(_decodedFile);
}

void
NormalTest::Perform()
{
    _inname = webrtc::test::ProjectRootPath() + "resources/foreman_cif.yuv";
    CodecSettings(352, 288, 30, _bitRate);
    Setup();

    _inputVideoBuffer.VerifyAndAllocate(_lengthSourceFrame);
    _decodedVideoBuffer.VerifyAndAllocate(_lengthSourceFrame);
    _encodedVideoBuffer.VerifyAndAllocate(_lengthSourceFrame);
    
    _encoder->InitEncode(&_inst, 1, 1460);
    CodecSpecific_InitBitrate();
    _decoder->InitDecode(&_inst,1);

    _totalEncodeTime = _totalDecodeTime = 0;
    _framecnt = 0;
    _sumEncBytes = 0;
    _lengthEncFrame = 0;
    int decodeLength = 0;
    while (!Encode())
    {
        DoPacketLoss();
        _encodedVideoBuffer.UpdateLength(_encodedVideoBuffer.GetLength());
        fwrite(_encodedVideoBuffer.GetBuffer(), 1, _encodedVideoBuffer.GetLength(), _encodedFile);
        decodeLength = Decode();
        if (decodeLength < 0)
        {
            fprintf(stderr,"\n\nError in decoder: %d\n\n", decodeLength);
            exit(EXIT_FAILURE);
        }
        fwrite(_decodedVideoBuffer.GetBuffer(), 1, decodeLength, _decodedFile);
        CodecSpecific_InitBitrate();
        _framecnt++;
    }

    // Ensure we empty the decoding queue.
    while (decodeLength > 0)
    {
        decodeLength = Decode();
        if (decodeLength < 0)
        {
            fprintf(stderr,"\n\nError in decoder: %d\n\n", decodeLength);
            exit(EXIT_FAILURE);
        }
        fwrite(_decodedVideoBuffer.GetBuffer(), 1, decodeLength, _decodedFile);
    }

    double actualBitRate = ActualBitRate(_framecnt) / 1000.0;
    double avgEncTime = _totalEncodeTime / _framecnt;
    double avgDecTime = _totalDecodeTime / _framecnt;
    printf("Actual bitrate: %f kbps\n", actualBitRate);
    printf("Average encode time: %f s\n", avgEncTime);
    printf("Average decode time: %f s\n", avgDecTime);
    (*_log) << "Actual bitrate: " << actualBitRate << " kbps\tTarget: " << _bitRate << " kbps" << std::endl;
    (*_log) << "Average encode time: " << avgEncTime << " s" << std::endl;
    (*_log) << "Average decode time: " << avgDecTime << " s" << std::endl;

    _inputVideoBuffer.Free();
    _encodedVideoBuffer.Reset();
    _decodedVideoBuffer.Free();

    _encoder->Release();
    _decoder->Release();

    Teardown();
}

bool
NormalTest::Encode()
{
    _lengthEncFrame = 0;
    EXPECT_GT(fread(_sourceBuffer, 1, _lengthSourceFrame, _sourceFile), 0u);
    if (feof(_sourceFile) != 0)
    {
        return true;
    }
    _inputVideoBuffer.CopyBuffer(_lengthSourceFrame, _sourceBuffer);
    _inputVideoBuffer.SetTimeStamp(_framecnt);

    // This multiple attempt ridiculousness is to accomodate VP7:
    // 1. The wrapper can unilaterally reduce the framerate for low bitrates.
    // 2. The codec inexplicably likes to reject some frames. Perhaps there
    //    is a good reason for this...
    int encodingAttempts = 0;
    double starttime = 0;
    double endtime = 0;
    while (_lengthEncFrame == 0)
    {
        starttime = clock()/(double)CLOCKS_PER_SEC;

        _inputVideoBuffer.SetWidth(_inst.width);
        _inputVideoBuffer.SetHeight(_inst.height);
        //_lengthEncFrame = _encoder->Encode(_inputVideoBuffer, _encodedVideoBuffer, _frameInfo,
        //  _inst.frameRate, _requestKeyFrame && !(_framecnt%50));

        endtime = clock()/(double)CLOCKS_PER_SEC;

        _encodedVideoBuffer.SetCaptureHeight(_inst.height);
        _encodedVideoBuffer.SetCaptureWidth(_inst.width);
        if (_lengthEncFrame < 0)
        {
            (*_log) << "Error in encoder: " << _lengthEncFrame << std::endl;
            fprintf(stderr,"\n\nError in encoder: %d\n\n", _lengthEncFrame);
            exit(EXIT_FAILURE);
        }
        _sumEncBytes += _lengthEncFrame;

        encodingAttempts++;
        if (encodingAttempts > 50)
        {
            (*_log) << "Unable to encode frame: " << _framecnt << std::endl;
            fprintf(stderr,"\n\nUnable to encode frame: %d\n\n", _framecnt);
            exit(EXIT_FAILURE);
        }
    }
    _totalEncodeTime += endtime - starttime;

    if (encodingAttempts > 1)
    {
        (*_log) << encodingAttempts << " attempts required to encode frame: " <<
            _framecnt + 1 << std::endl;
        fprintf(stderr,"\n%d attempts required to encode frame: %d\n", encodingAttempts,
            _framecnt + 1);
    }
        
    return false;
}

int
NormalTest::Decode(int lossValue)
{
    _encodedVideoBuffer.SetWidth(_inst.width);
    _encodedVideoBuffer.SetHeight(_inst.height);
    int lengthDecFrame = 0;
    //int lengthDecFrame = _decoder->Decode(_encodedVideoBuffer, _decodedVideoBuffer);
    //_totalDecodeTime += (double)((clock()/(double)CLOCKS_PER_SEC) - starttime);
    if (lengthDecFrame < 0)
    {
        return lengthDecFrame;
    }
    _encodedVideoBuffer.Reset();
    _encodedVideoBuffer.UpdateLength(0);
    return lengthDecFrame;
}

