timestatus.c 14 KB

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