/*
* time status related function source file
*
* Copyright (c) 1999 Mark Taylor
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/* $Id: timestatus.c,v 1.40 2005/02/25 01:21:54 robert Exp $ */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
/* Hope it works now, otherwise complain or flame ;-)
*/
#if 1
# define SPEED_CHAR "x" /* character x */
# define SPEED_MULT 1.
#else
# define SPEED_CHAR "%%"
# define SPEED_MULT 100.
#endif
#include <assert.h>
#include <time.h>
#include "lame.h"
#include "main.h"
#include "lametime.h"
#include "timestatus.h"
#if defined(BRHIST)
# include "brhist.h"
#endif
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif
typedef struct {
double last_time; /* result of last call to clock */
double elapsed_time; /* total time */
double estimated_time; /* estimated total duration time [s] */
double speed_index; /* speed relative to realtime coding [100%] */
} timestatus_t;
/*
* Calculates from the input (see below) the following values:
* - total estimated time
* - a speed index
*/
static void
ts_calc_times(timestatus_t * const tstime, /* tstime->elapsed_time: elapsed time */
const int sample_freq, /* sample frequency [Hz/kHz] */
const int frameNum, /* Number of the current Frame */
const int totalframes, /* total umber of Frames */
const int framesize)
{ /* Size of a frame [bps/kbps] */
assert(sample_freq >= 8000 && sample_freq <= 48000);
if (frameNum > 0 && tstime->elapsed_time > 0) {
tstime->estimated_time = tstime->elapsed_time * totalframes / frameNum;
tstime->speed_index = framesize * frameNum / (sample_freq * tstime->elapsed_time);
}
else {
tstime->estimated_time = 0.;
tstime->speed_index = 0.;
}
}
/* Decomposes a given number of seconds into a easy to read hh:mm:ss format
* padded with an additional character
*/
static void
ts_time_decompose(const unsigned long time_in_sec, const char padded_char)
{
const unsigned long hour = time_in_sec / 3600;
const unsigned int min = time_in_sec / 60 % 60;
const unsigned int sec = time_in_sec % 60;
if (hour == 0)
fprintf(stderr, " %2u:%02u%c", min, sec, padded_char);
else if (hour < 100)
fprintf(stderr, "%2lu:%02u:%02u%c", hour, min, sec, padded_char);
else
fprintf(stderr, "%6lu h%c", hour, padded_char);
}
void
timestatus(int samp_rate, int frameNum, int totalframes, int framesize)
{
static timestatus_t real_time;
static timestatus_t proc_time;
int percent;
static int init = 0; /* What happens here? A work around instead of a bug fix ??? */
double tmx, delta;
if (totalframes < frameNum) {
totalframes = frameNum;
}
if (frameNum == 0) {
real_time.last_time = GetRealTime();
proc_time.last_time = GetCPUTime();
real_time.elapsed_time = 0;
proc_time.elapsed_time = 0;
}
/* we need rollover protection for GetCPUTime, and maybe GetRealTime(): */
tmx = GetRealTime();
delta = tmx - real_time.last_time;
if (delta < 0)
delta = 0; /* ignore, clock has rolled over */
real_time.elapsed_time += delta;
real_time.last_time = tmx;
tmx = GetCPUTime();
delta = tmx - proc_time.last_time;
if (delta < 0)
delta = 0; /* ignore, clock has rolled over */
proc_time.elapsed_time += delta;
proc_time.last_time = tmx;
if (frameNum == 0 && init == 0) {
fprintf(stderr,
"\r"
" Frame | CPU time/estim | REAL time/estim | play/CPU | ETA \n"
" 0/ ( 0%%)| 0:00/ : | 0:00/ : | " SPEED_CHAR
"| : \r"
/* , Console_IO.str_clreoln, Console_IO.str_clreoln */ );
init = 1;
return;
}
/* reset init counter for next time we are called with frameNum==0 */
if (frameNum > 0)
init = 0;
ts_calc_times(&real_time, samp_rate, frameNum, totalframes, framesize);
ts_calc_times(&proc_time, samp_rate, frameNum, totalframes, framesize);
if (frameNum < totalframes) {
percent = (int) (100. * frameNum / totalframes + 0.5);
}
else {
percent = 100;
}
fprintf(stderr, "\r%6i/%-6i", frameNum, totalframes);
fprintf(stderr, percent < 100 ? " (%2d%%)|" : "(%3.3d%%)|", percent);
ts_time_decompose((unsigned long) proc_time.elapsed_time, '/');
ts_time_decompose((unsigned long) proc_time.estimated_time, '|');
ts_time_decompose((unsigned long) real_time.elapsed_time, '/');
ts_time_decompose((unsigned long) real_time.estimated_time, '|');
fprintf(stderr, proc_time.speed_index <= 1. ?
"%9.4f" SPEED_CHAR "|" : "%#9.5g" SPEED_CHAR "|", SPEED_MULT * proc_time.speed_index);
ts_time_decompose((unsigned long) (real_time.estimated_time - real_time.elapsed_time), ' ');
fflush(stderr);
}
void
timestatus_finish(void)
{
fprintf(stderr, "\n");
fflush(stderr);
}
void
timestatus_klemm(const lame_global_flags * const gfp)
{
static double last_time = 0.;
if (silent <= 0)
if (lame_get_frameNum(gfp) == 0 ||
lame_get_frameNum(gfp) == 9 ||
GetRealTime() - last_time >= update_interval || GetRealTime() - last_time < 0) {
#ifdef BRHIST
brhist_jump_back();
#endif
timestatus(lame_get_out_samplerate(gfp),
lame_get_frameNum(gfp), lame_get_totalframes(gfp), lame_get_framesize(gfp));
#ifdef BRHIST
if (brhist) {
brhist_disp(gfp);
}
#endif
last_time = GetRealTime(); /* from now! disp_time seconds */
}
}
/* these functions are used in get_audio.c */
void
decoder_progress(const lame_global_flags * const gfp, const mp3data_struct * const mp3data)
{
static int last;
fprintf(stderr, "\rFrame#%6i/%-6i %3i kbps",
mp3data->framenum, mp3data->totalframes, mp3data->bitrate);
/* Programmed with a single frame hold delay */
/* Attention: static data */
/* MP2 Playback is still buggy. */
/* "'00' subbands 4-31 in intensity_stereo, bound==4" */
/* is this really intensity_stereo or is it MS stereo? */
if (mp3data->mode == JOINT_STEREO) {
int curr = mp3data->mode_ext;
fprintf(stderr, " %s %c",
curr & 2 ? last & 2 ? " MS " : "LMSR" : last & 2 ? "LMSR" : "L R",
curr & 1 ? last & 1 ? 'I' : 'i' : last & 1 ? 'i' : ' ');
last = curr;
}
else {
fprintf(stderr, " ");
last = 0;
}
/* fprintf ( stderr, "%s", Console_IO.str_clreoln ); */
fprintf(stderr, " \b\b\b\b\b\b\b\b");
fflush(stderr);
}
void
decoder_progress_finish(const lame_global_flags * const gfp)
{
fprintf(stderr, "\n");
}