• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *      time status related function source file
3  *
4  *      Copyright (c) 1999 Mark Taylor
5  *                    2010 Robert Hegemann
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22 
23 /* $Id$ */
24 
25 #ifdef HAVE_CONFIG_H
26 # include <config.h>
27 #endif
28 
29 
30 #if 1
31 # define SPEED_CHAR     "x" /* character x */
32 # define SPEED_MULT     1.
33 #else
34 # define SPEED_CHAR     "%%"
35 # define SPEED_MULT     100.
36 #endif
37 
38 #include <assert.h>
39 #include <time.h>
40 #include <string.h>
41 #include <stdlib.h>
42 
43 #include "lame.h"
44 #include "main.h"
45 #include "lametime.h"
46 #include "timestatus.h"
47 #include "brhist.h"
48 #include "console.h"
49 
50 #ifdef WITH_DMALLOC
51 #include <dmalloc.h>
52 #endif
53 
54 typedef struct time_status_struct {
55     double  last_time;       /* result of last call to clock */
56     double  elapsed_time;    /* total time */
57     double  estimated_time;  /* estimated total duration time [s] */
58     double  speed_index;     /* speed relative to realtime coding [100%] */
59 } timestatus_t;
60 
61 static struct EncoderProgress {
62     timestatus_t real_time;
63     timestatus_t proc_time;
64     double  last_time;
65     int     last_frame_num;
66     int     time_status_init;
67 } global_encoder_progress;
68 
69 
70 /*
71  *  Calculates from the input (see below) the following values:
72  *    - total estimated time
73  *    - a speed index
74  */
75 
76 static void
ts_calc_times(timestatus_t * const tstime,const int sample_freq,const int frameNum,const int totalframes,const int framesize)77 ts_calc_times(timestatus_t * const tstime, /* tstime->elapsed_time: elapsed time */
78               const int sample_freq, /* sample frequency [Hz/kHz]  */
79               const int frameNum, /* Number of the current Frame */
80               const int totalframes, /* total umber of Frames */
81               const int framesize)
82 {                       /* Size of a frame [bps/kbps] */
83     assert(sample_freq >= 8000 && sample_freq <= 48000);
84 
85     if (frameNum > 0 && tstime->elapsed_time > 0) {
86         tstime->estimated_time = tstime->elapsed_time * totalframes / frameNum;
87         tstime->speed_index = framesize * frameNum / (sample_freq * tstime->elapsed_time);
88     }
89     else {
90         tstime->estimated_time = 0.;
91         tstime->speed_index = 0.;
92     }
93 }
94 
95 /* Decomposes a given number of seconds into a easy to read hh:mm:ss format
96  * padded with an additional character
97  */
98 
99 static void
ts_time_decompose(const double x,const char padded_char)100 ts_time_decompose(const double x, const char padded_char)
101 {
102     const unsigned long time_in_sec = (unsigned long)x;
103     const unsigned long hour = time_in_sec / 3600;
104     const unsigned int min = time_in_sec / 60 % 60;
105     const unsigned int sec = time_in_sec % 60;
106 
107     if (hour == 0)
108         console_printf("   %2u:%02u%c", min, sec, padded_char);
109     else if (hour < 100)
110         console_printf("%2lu:%02u:%02u%c", hour, min, sec, padded_char);
111     else
112         console_printf("%6lu h%c", hour, padded_char);
113 }
114 
115 static void
timestatus(const lame_global_flags * const gfp)116 timestatus(const lame_global_flags * const gfp)
117 {
118     timestatus_t* real_time = &global_encoder_progress.real_time;
119     timestatus_t* proc_time = &global_encoder_progress.proc_time;
120     int     percent;
121     double  tmx, delta;
122     int samp_rate     = lame_get_out_samplerate(gfp)
123       , frameNum      = lame_get_frameNum(gfp)
124       , totalframes   = lame_get_totalframes(gfp)
125       , framesize     = lame_get_framesize(gfp)
126       ;
127 
128     if (totalframes < frameNum) {
129         totalframes = frameNum;
130     }
131     if (global_encoder_progress.time_status_init == 0) {
132         real_time->last_time = GetRealTime();
133         proc_time->last_time = GetCPUTime();
134         real_time->elapsed_time = 0;
135         proc_time->elapsed_time = 0;
136     }
137 
138     /* we need rollover protection for GetCPUTime, and maybe GetRealTime(): */
139     tmx = GetRealTime();
140     delta = tmx - real_time->last_time;
141     if (delta < 0)
142         delta = 0;      /* ignore, clock has rolled over */
143     real_time->elapsed_time += delta;
144     real_time->last_time = tmx;
145 
146 
147     tmx = GetCPUTime();
148     delta = tmx - proc_time->last_time;
149     if (delta < 0)
150         delta = 0;      /* ignore, clock has rolled over */
151     proc_time->elapsed_time += delta;
152     proc_time->last_time = tmx;
153 
154     if (global_encoder_progress.time_status_init == 0) {
155         console_printf("\r"
156                        "    Frame          |  CPU time/estim | REAL time/estim | play/CPU |    ETA \n"
157                        "     0/       ( 0%%)|    0:00/     :  |    0:00/     :  |         "
158                        SPEED_CHAR "|     :  \r"
159                        /* , Console_IO.str_clreoln, Console_IO.str_clreoln */ );
160         global_encoder_progress.time_status_init = 1;
161         return;
162     }
163 
164     ts_calc_times(real_time, samp_rate, frameNum, totalframes, framesize);
165     ts_calc_times(proc_time, samp_rate, frameNum, totalframes, framesize);
166 
167     if (frameNum < totalframes) {
168         percent = (int) (100. * frameNum / totalframes + 0.5);
169     }
170     else {
171         percent = 100;
172     }
173 
174     console_printf("\r%6i/%-6i", frameNum, totalframes);
175     console_printf(percent < 100 ? " (%2d%%)|" : "(%3.3d%%)|", percent);
176     ts_time_decompose(proc_time->elapsed_time, '/');
177     ts_time_decompose(proc_time->estimated_time, '|');
178     ts_time_decompose(real_time->elapsed_time, '/');
179     ts_time_decompose(real_time->estimated_time, '|');
180     console_printf(proc_time->speed_index <= 1. ?
181                    "%9.4f" SPEED_CHAR "|" : "%#9.5g" SPEED_CHAR "|",
182                    SPEED_MULT * proc_time->speed_index);
183     ts_time_decompose((real_time->estimated_time - real_time->elapsed_time), ' ');
184 }
185 
186 static void
timestatus_finish(void)187 timestatus_finish(void)
188 {
189     console_printf("\n");
190 }
191 
192 
193 static void
brhist_init_package(lame_global_flags const * gf)194 brhist_init_package(lame_global_flags const* gf)
195 {
196     if (global_ui_config.brhist) {
197         if (brhist_init(gf, lame_get_VBR_min_bitrate_kbps(gf), lame_get_VBR_max_bitrate_kbps(gf))) {
198             /* fail to initialize */
199             global_ui_config.brhist = 0;
200         }
201     }
202     else {
203         brhist_init(gf, 128, 128); /* Dirty hack */
204     }
205 }
206 
207 
208 void
encoder_progress_begin(lame_global_flags const * gf,char const * inPath,char const * outPath)209 encoder_progress_begin( lame_global_flags const* gf
210                       , char              const* inPath
211                       , char              const* outPath
212                       )
213 {
214     brhist_init_package(gf);
215     global_encoder_progress.time_status_init = 0;
216     global_encoder_progress.last_time = 0;
217     global_encoder_progress.last_frame_num = 0;
218     if (global_ui_config.silent < 9) {
219         size_t pw = console_getwidth()-14;
220         char* i_file = 0;
221         char* o_file = 0;
222 #if defined( _WIN32 ) && !defined(__MINGW32__)
223         inPath = i_file = utf8ToConsole8Bit(inPath);
224         outPath = o_file = utf8ToConsole8Bit(outPath);
225 #endif
226         lame_print_config(gf); /* print useful information about options being used */
227 
228         console_printf("Encoding %s%s to %s\n",
229                        strcmp(inPath, "-") ? inPath : "<stdin>",
230                        strlen(inPath) + strlen(outPath) < pw ? "" : "\n     ",
231                        strcmp(outPath, "-") ? outPath : "<stdout>");
232 
233         free(i_file);
234         free(o_file);
235 
236         console_printf("Encoding as %g kHz ", 1.e-3 * lame_get_out_samplerate(gf));
237 
238         {
239             static const char *mode_names[2][4] = {
240                 {"stereo", "j-stereo", "dual-ch", "single-ch"},
241                 {"stereo", "force-ms", "dual-ch", "single-ch"}
242             };
243             switch (lame_get_VBR(gf)) {
244             case vbr_rh:
245                 console_printf("%s MPEG-%u%s Layer III VBR(q=%g) qval=%i\n",
246                                mode_names[lame_get_force_ms(gf)][lame_get_mode(gf)],
247                                2 - lame_get_version(gf),
248                                lame_get_out_samplerate(gf) < 16000 ? ".5" : "",
249                                lame_get_VBR_quality(gf),
250                                lame_get_quality(gf));
251                 break;
252             case vbr_mt:
253             case vbr_mtrh:
254                 console_printf("%s MPEG-%u%s Layer III VBR(q=%g)\n",
255                                mode_names[lame_get_force_ms(gf)][lame_get_mode(gf)],
256                                2 - lame_get_version(gf),
257                                lame_get_out_samplerate(gf) < 16000 ? ".5" : "",
258                                lame_get_VBR_quality(gf));
259                 break;
260             case vbr_abr:
261                 console_printf("%s MPEG-%u%s Layer III (%gx) average %d kbps qval=%i\n",
262                                mode_names[lame_get_force_ms(gf)][lame_get_mode(gf)],
263                                2 - lame_get_version(gf),
264                                lame_get_out_samplerate(gf) < 16000 ? ".5" : "",
265                                0.1 * (int) (10. * lame_get_compression_ratio(gf) + 0.5),
266                                lame_get_VBR_mean_bitrate_kbps(gf),
267                                lame_get_quality(gf));
268                 break;
269             default:
270                 console_printf("%s MPEG-%u%s Layer III (%gx) %3d kbps qval=%i\n",
271                                mode_names[lame_get_force_ms(gf)][lame_get_mode(gf)],
272                                2 - lame_get_version(gf),
273                                lame_get_out_samplerate(gf) < 16000 ? ".5" : "",
274                                0.1 * (int) (10. * lame_get_compression_ratio(gf) + 0.5),
275                                lame_get_brate(gf),
276                                lame_get_quality(gf));
277                 break;
278             }
279         }
280 
281         if (global_ui_config.silent <= -10) {
282             lame_print_internals(gf);
283         }
284     }
285 }
286 
287 void
encoder_progress(lame_global_flags const * gf)288 encoder_progress( lame_global_flags const* gf )
289 {
290     if (global_ui_config.silent <= 0) {
291         int const frames = lame_get_frameNum(gf);
292         int const frames_diff = frames - global_encoder_progress.last_frame_num;
293         if (global_ui_config.update_interval <= 0) {     /*  most likely --disptime x not used */
294             if (frames_diff < 100 && frames_diff != 0) {  /*  true, most of the time */
295                 return;
296             }
297             global_encoder_progress.last_frame_num = (frames/100)*100;
298         }
299         else {
300             if (frames != 0 && frames != 9) {
301                 double const act = GetRealTime();
302                 double const dif = act - global_encoder_progress.last_time;
303                 if (dif >= 0 && dif < global_ui_config.update_interval) {
304                     return;
305                 }
306             }
307             global_encoder_progress.last_time = GetRealTime(); /* from now! disp_time seconds */
308         }
309         if (global_ui_config.brhist) {
310             brhist_jump_back();
311         }
312         timestatus(gf);
313         if (global_ui_config.brhist) {
314             brhist_disp(gf);
315         }
316         console_flush();
317     }
318 }
319 
320 void
encoder_progress_end(lame_global_flags const * gf)321 encoder_progress_end( lame_global_flags const* gf )
322 {
323     if (global_ui_config.silent <= 0) {
324         if (global_ui_config.brhist) {
325             brhist_jump_back();
326         }
327         timestatus(gf);
328         if (global_ui_config.brhist) {
329             brhist_disp(gf);
330         }
331         timestatus_finish();
332     }
333 }
334 
335 
336 /* these functions are used in get_audio.c */
337 static struct DecoderProgress {
338     int     last_mode_ext;
339     int     frames_total;
340     int     frame_ctr;
341     int     framesize;
342     unsigned long samples;
343 } global_decoder_progress;
344 
345 static
calcEndPadding(unsigned long samples,int pcm_samples_per_frame)346 unsigned long calcEndPadding(unsigned long samples, int pcm_samples_per_frame)
347 {
348     unsigned long end_padding;
349     samples += 576;
350     end_padding = pcm_samples_per_frame - (samples % pcm_samples_per_frame);
351     if (end_padding < 576)
352         end_padding += pcm_samples_per_frame;
353     return end_padding;
354 }
355 
356 static
calcNumBlocks(unsigned long samples,int pcm_samples_per_frame)357 unsigned long calcNumBlocks(unsigned long samples, int pcm_samples_per_frame)
358 {
359     unsigned long end_padding;
360     samples += 576;
361     end_padding = pcm_samples_per_frame - (samples % pcm_samples_per_frame);
362     if (end_padding < 576)
363         end_padding += pcm_samples_per_frame;
364     return (samples + end_padding) / pcm_samples_per_frame;
365 }
366 
367 DecoderProgress
decoder_progress_init(unsigned long n,int framesize)368 decoder_progress_init(unsigned long n, int framesize)
369 {
370     DecoderProgress dp = &global_decoder_progress;
371     dp->last_mode_ext =0;
372     dp->frames_total = 0;
373     dp->frame_ctr = 0;
374     dp->framesize = framesize;
375     dp->samples = 0;
376     if (n != (0ul-1ul)) {
377         if (framesize == 576 || framesize == 1152) {
378             dp->frames_total = calcNumBlocks(n, framesize);
379             dp->samples = 576 + calcEndPadding(n, framesize);
380         }
381         else if (framesize > 0) {
382             dp->frames_total = n / framesize;
383         }
384         else {
385             dp->frames_total = n;
386         }
387     }
388     return dp;
389 }
390 
391 static void
addSamples(DecoderProgress dp,int iread)392 addSamples(DecoderProgress dp, int iread)
393 {
394     dp->samples += iread;
395     dp->frame_ctr += dp->samples / dp->framesize;
396     dp->samples %= dp->framesize;
397     if (dp->frames_total < dp->frame_ctr) {
398         dp->frames_total = dp->frame_ctr;
399     }
400 }
401 
402 void
decoder_progress(DecoderProgress dp,const mp3data_struct * mp3data,int iread)403 decoder_progress(DecoderProgress dp, const mp3data_struct * mp3data, int iread)
404 {
405     addSamples(dp, iread);
406 
407     console_printf("\rFrame#%6i/%-6i %3i kbps",
408                    dp->frame_ctr, dp->frames_total, mp3data->bitrate);
409 
410     /* Programmed with a single frame hold delay */
411     /* Attention: static data */
412 
413     /* MP2 Playback is still buggy. */
414     /* "'00' subbands 4-31 in intensity_stereo, bound==4" */
415     /* is this really intensity_stereo or is it MS stereo? */
416 
417     if (mp3data->mode == JOINT_STEREO) {
418         int     curr = mp3data->mode_ext;
419         int     last = dp->last_mode_ext;
420         console_printf("  %s  %c",
421                        (curr & 2) ? (last & 2) ? " MS " : "LMSR" : (last & 2) ? "LMSR" : "L  R",
422                        (curr & 1) ? (last & 1) ? 'I' : 'i' : (last & 1) ? 'i' : ' ');
423         dp->last_mode_ext = curr;
424     }
425     else {
426         console_printf("         ");
427         dp->last_mode_ext = 0;
428     }
429 /*    console_printf ("%s", Console_IO.str_clreoln ); */
430     console_printf("        \b\b\b\b\b\b\b\b");
431     console_flush();
432 }
433 
434 void
decoder_progress_finish(DecoderProgress dp)435 decoder_progress_finish(DecoderProgress dp)
436 {
437     (void) dp;
438     console_printf("\n");
439 }
440