/*
 * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.

 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of The Linux Foundation nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#define LOG_NDDEBUG 0
#define __STDC_FORMAT_MACROS 1
#include <inttypes.h>

#include "profiler.h"

#ifdef DEBUG_CALC_FPS


ANDROID_SINGLETON_STATIC_INSTANCE(qdutils::CalcFps) ;

namespace qdutils {

CalcFps::CalcFps() {
    debug_fps_level = 0;
    Init();
}

CalcFps::~CalcFps() {
}

void CalcFps::Init() {
    char prop[PROPERTY_VALUE_MAX];
    property_get("debug.gr.calcfps", prop, "0");
    debug_fps_level = atoi(prop);
    if (debug_fps_level > MAX_DEBUG_FPS_LEVEL) {
        ALOGW("out of range value for debug.gr.calcfps, using 0");
        debug_fps_level = 0;
    }

    ALOGD("DEBUG_CALC_FPS: %d", debug_fps_level);
    populate_debug_fps_metadata();
}

void CalcFps::Fps() {
    if (debug_fps_level > 0)
        calc_fps(ns2us(systemTime()));
}

void CalcFps::populate_debug_fps_metadata(void)
{
    char prop[PROPERTY_VALUE_MAX];

    /*defaults calculation of fps to based on number of frames*/
    property_get("debug.gr.calcfps.type", prop, "0");
    debug_fps_metadata.type = (debug_fps_metadata_t::DfmType) atoi(prop);

    /*defaults to 1000ms*/
    property_get("debug.gr.calcfps.timeperiod", prop, "1000");
    debug_fps_metadata.time_period = atoi(prop);

    property_get("debug.gr.calcfps.period", prop, "10");
    debug_fps_metadata.period = atoi(prop);

    if (debug_fps_metadata.period > MAX_FPS_CALC_PERIOD_IN_FRAMES) {
        debug_fps_metadata.period = MAX_FPS_CALC_PERIOD_IN_FRAMES;
    }

    /* default ignorethresh_us: 500 milli seconds */
    property_get("debug.gr.calcfps.ignorethresh_us", prop, "500000");
    debug_fps_metadata.ignorethresh_us = atoi(prop);

    debug_fps_metadata.framearrival_steps =
        (unsigned int)(debug_fps_metadata.ignorethresh_us / 16666);

    if (debug_fps_metadata.framearrival_steps > MAX_FRAMEARRIVAL_STEPS) {
        debug_fps_metadata.framearrival_steps = MAX_FRAMEARRIVAL_STEPS;
        debug_fps_metadata.ignorethresh_us =
            debug_fps_metadata.framearrival_steps * 16666;
    }

    /* 2ms margin of error for the gettimeofday */
    debug_fps_metadata.margin_us = 2000;

    for (unsigned int i = 0; i < MAX_FRAMEARRIVAL_STEPS; i++)
        debug_fps_metadata.accum_framearrivals[i] = 0;

    debug_fps_metadata.curr_frame = 0;

    ALOGD("period: %u", debug_fps_metadata.period);
    ALOGD("ignorethresh_us: %" PRId64, debug_fps_metadata.ignorethresh_us);
}

void CalcFps::print_fps(float fps)
{
    if (debug_fps_metadata_t::DFM_FRAMES == debug_fps_metadata.type)
        ALOGD("FPS for last %d frames: %3.2f", debug_fps_metadata.period, fps);
    else
        ALOGD("FPS for last (%f ms, %d frames): %3.2f",
              debug_fps_metadata.time_elapsed,
              debug_fps_metadata.curr_frame, fps);

    debug_fps_metadata.curr_frame = 0;
    debug_fps_metadata.time_elapsed = 0.0;

    if (debug_fps_level > 1) {
        ALOGD("Frame Arrival Distribution:");
        for (unsigned int i = 0;
             i < ((debug_fps_metadata.framearrival_steps / 6) + 1);
             i++) {
            ALOGD("%" PRId64" %" PRId64" %" PRId64" %" PRId64" %" PRId64" %" PRId64,
                  debug_fps_metadata.accum_framearrivals[i*6],
                  debug_fps_metadata.accum_framearrivals[i*6+1],
                  debug_fps_metadata.accum_framearrivals[i*6+2],
                  debug_fps_metadata.accum_framearrivals[i*6+3],
                  debug_fps_metadata.accum_framearrivals[i*6+4],
                  debug_fps_metadata.accum_framearrivals[i*6+5]);
        }

        /* We are done with displaying, now clear the stats */
        for (unsigned int i = 0;
             i < debug_fps_metadata.framearrival_steps;
             i++)
            debug_fps_metadata.accum_framearrivals[i] = 0;
    }
    return;
}

void CalcFps::calc_fps(nsecs_t currtime_us)
{
    static nsecs_t oldtime_us = 0;

    nsecs_t diff = currtime_us - oldtime_us;

    oldtime_us = currtime_us;

    if (debug_fps_metadata_t::DFM_FRAMES == debug_fps_metadata.type &&
        diff > debug_fps_metadata.ignorethresh_us) {
        return;
    }

    if (debug_fps_metadata.curr_frame < MAX_FPS_CALC_PERIOD_IN_FRAMES) {
        debug_fps_metadata.framearrivals[debug_fps_metadata.curr_frame] = diff;
    }

    debug_fps_metadata.curr_frame++;

    if (debug_fps_level > 1) {
        unsigned int currstep =
            (unsigned int)(diff + debug_fps_metadata.margin_us) / 16666;

        if (currstep < debug_fps_metadata.framearrival_steps) {
            debug_fps_metadata.accum_framearrivals[currstep-1]++;
        }
    }

    if (debug_fps_metadata_t::DFM_FRAMES == debug_fps_metadata.type) {
        if (debug_fps_metadata.curr_frame == debug_fps_metadata.period) {
            /* time to calculate and display FPS */
            nsecs_t sum = 0;
            for (unsigned int i = 0; i < debug_fps_metadata.period; i++)
                sum += debug_fps_metadata.framearrivals[i];
            print_fps(float(float(debug_fps_metadata.period * 1000000) /
                                                              (float)sum));
        }
    }
    else if (debug_fps_metadata_t::DFM_TIME == debug_fps_metadata.type) {
        debug_fps_metadata.time_elapsed += (float)((float)diff/1000.0);
        if (debug_fps_metadata.time_elapsed >= debug_fps_metadata.time_period) {
            float fps = float(1000.0 * debug_fps_metadata.curr_frame/
                                            debug_fps_metadata.time_elapsed);
            print_fps(fps);
        }
    }
    return;
}
};//namespace qomutils
#endif
