1 /* OggEnc
2 **
3 ** This program is distributed under the GNU General Public License, version 2.
4 ** A copy of this license is included with this source.
5 **
6 ** Copyright 2000-2002, Michael Smith <msmith@xiph.org>
7 **
8 ** Portions from Vorbize, (c) Kenneth Arnold <kcarnold-xiph@arnoldnet.net>
9 ** and libvorbis examples, (c) Monty <monty@xiph.org>
10 **/
11
12 #ifdef HAVE_CONFIG_H
13 #include <config.h>
14 #endif
15
16 #include <stdlib.h>
17 #include <stdio.h>
18 #include <math.h>
19 #include <string.h>
20 #include <time.h>
21
22 #include "platform.h"
23 #include <vorbis/vorbisenc.h>
24 #include "encode.h"
25 #include "i18n.h"
26 #include "skeleton.h"
27
28 #ifdef HAVE_KATE
29 #include "lyrics.h"
30 #include <kate/oggkate.h>
31 #endif
32
33 #define READSIZE 1024
34
35
36 int oe_write_page(ogg_page *page, FILE *fp);
37
38 #define SETD(toset) \
39 do {\
40 if(sscanf(opts[i].val, "%lf", &dval) != 1)\
41 fprintf(stderr, "For option %s, couldn't read value %s as double\n",\
42 opts[i].arg, opts[i].val);\
43 else\
44 toset = dval;\
45 } while(0)
46
47 #define SETL(toset) \
48 do {\
49 if(sscanf(opts[i].val, "%ld", &lval) != 1)\
50 fprintf(stderr, "For option %s, couldn't read value %s as integer\n",\
51 opts[i].arg, opts[i].val);\
52 else\
53 toset = lval;\
54 } while(0)
55
set_advanced_encoder_options(adv_opt * opts,int count,vorbis_info * vi)56 static void set_advanced_encoder_options(adv_opt *opts, int count,
57 vorbis_info *vi)
58 {
59 #ifdef OV_ECTL_RATEMANAGE2_GET
60 int manage = 0;
61 struct ovectl_ratemanage2_arg ai;
62 int i;
63 double dval;
64 long lval;
65
66 vorbis_encode_ctl(vi, OV_ECTL_RATEMANAGE2_GET, &ai);
67
68 for(i=0; i < count; i++) {
69 if(opts[i].val)
70 fprintf(stderr, _("Setting advanced encoder option \"%s\" to %s\n"),
71 opts[i].arg, opts[i].val);
72 else
73 fprintf(stderr, _("Setting advanced encoder option \"%s\"\n"),
74 opts[i].arg);
75
76 if(!strcmp(opts[i].arg, "bitrate_average_damping")) {
77 SETD(ai.bitrate_average_damping);
78 manage = 1;
79 }
80 else if(!strcmp(opts[i].arg, "bitrate_average")) {
81 SETL(ai.bitrate_average_kbps);
82 manage = 1;
83 }
84 else if(!strcmp(opts[i].arg, "bit_reservoir_bias")) {
85 SETD(ai.bitrate_limit_reservoir_bias);
86 manage = 1;
87 }
88 else if(!strcmp(opts[i].arg, "bit_reservoir_bits")) {
89 SETL(ai.bitrate_limit_reservoir_bits);
90 manage = 1;
91 }
92 else if(!strcmp(opts[i].arg, "bitrate_hard_min")) {
93 SETL(ai.bitrate_limit_min_kbps);
94 manage = 1;
95 }
96 else if(!strcmp(opts[i].arg, "bitrate_hard_max")) {
97 SETL(ai.bitrate_limit_max_kbps);
98 manage = 1;
99 }
100 else if(!strcmp(opts[i].arg, "disable_coupling")) {
101 int val=0;
102 vorbis_encode_ctl(vi, OV_ECTL_COUPLING_SET, &val);
103 }
104 else if(!strcmp(opts[i].arg, "impulse_noisetune")) {
105 double val;
106 SETD(val);
107 vorbis_encode_ctl(vi, OV_ECTL_IBLOCK_SET, &val);
108 }
109 else if(!strcmp(opts[i].arg, "lowpass_frequency")) {
110 double prev, new;
111 SETD(new);
112 vorbis_encode_ctl(vi, OV_ECTL_LOWPASS_GET, &prev);
113 vorbis_encode_ctl(vi, OV_ECTL_LOWPASS_SET, &new);
114 fprintf(stderr, _("Changed lowpass frequency from %f kHz to %f kHz\n"), prev, new);
115 }
116 else {
117 fprintf(stderr, _("Unrecognised advanced option \"%s\"\n"),
118 opts[i].arg);
119 }
120 }
121
122 if(manage) {
123 if(vorbis_encode_ctl(vi, OV_ECTL_RATEMANAGE2_SET, &ai)) {
124 fprintf(stderr, _("Failed to set advanced rate management parameters\n"));
125 }
126 }
127 #else
128 fprintf(stderr,_( "This version of libvorbisenc cannot set advanced rate management parameters\n"));
129 #endif
130 }
131
add_fishead_packet(ogg_stream_state * os)132 static void add_fishead_packet (ogg_stream_state *os) {
133
134 fishead_packet fp;
135
136 memset(&fp, 0, sizeof(fp));
137 fp.ptime_n = 0;
138 fp.ptime_d = 1000;
139 fp.btime_n = 0;
140 fp.btime_d = 1000;
141
142 add_fishead_to_stream(os, &fp);
143 }
144
145 /*
146 * Adds the fishead packets in the skeleton output stream
147 */
add_vorbis_fisbone_packet(ogg_stream_state * os,oe_enc_opt * opt)148 static void add_vorbis_fisbone_packet (ogg_stream_state *os, oe_enc_opt *opt) {
149
150 fisbone_packet fp;
151
152 memset(&fp, 0, sizeof(fp));
153 fp.serial_no = opt->serialno;
154 fp.nr_header_packet = 3;
155 fp.granule_rate_n = opt->rate;
156 fp.granule_rate_d = 1;
157 fp.start_granule = 0;
158 fp.preroll = 2;
159 fp.granule_shift = 0;
160
161 add_message_header_field(&fp, "Content-Type", "audio/vorbis");
162
163 add_fisbone_to_stream(os, &fp);
164 }
165
166 #ifdef HAVE_KATE
add_kate_fisbone_packet(ogg_stream_state * os,oe_enc_opt * opt,kate_info * ki)167 static void add_kate_fisbone_packet (ogg_stream_state *os, oe_enc_opt *opt, kate_info *ki) {
168
169 fisbone_packet fp;
170
171 memset(&fp, 0, sizeof(fp));
172 fp.serial_no = opt->kate_serialno;
173 fp.nr_header_packet = ki->num_headers;
174 fp.granule_rate_n = ki->gps_numerator;
175 fp.granule_rate_d = ki->gps_denominator;
176 fp.start_granule = 0;
177 fp.preroll = 0;
178 fp.granule_shift = ki->granule_shift;
179
180 add_message_header_field(&fp, "Content-Type", "application/x-kate");
181
182 add_fisbone_to_stream(os, &fp);
183 }
184 #endif
185
186 #ifdef HAVE_KATE
add_kate_karaoke_style(kate_info * ki,unsigned char r,unsigned char g,unsigned char b,unsigned char a)187 static void add_kate_karaoke_style(kate_info *ki,unsigned char r,unsigned char g,unsigned char b,unsigned char a)
188 {
189 kate_style *ks;
190 int ret;
191
192 if (!ki) return;
193
194 ks=(kate_style*)malloc(sizeof(kate_style));
195 kate_style_init(ks);
196 ks->text_color.r = r;
197 ks->text_color.g = g;
198 ks->text_color.b = b;
199 ks->text_color.a = a;
200 ret=kate_info_add_style(ki,ks);
201 if (ret<0) {
202 fprintf(stderr, _("WARNING: failed to add Kate karaoke style\n"));
203 }
204 }
205 #endif
206
oe_encode(oe_enc_opt * opt)207 int oe_encode(oe_enc_opt *opt)
208 {
209
210 ogg_stream_state os;
211 ogg_stream_state so; /* stream for skeleton bitstream */
212 ogg_stream_state ko; /* stream for kate bitstream */
213 ogg_page og;
214 ogg_packet op;
215
216 vorbis_dsp_state vd;
217 vorbis_block vb;
218 vorbis_info vi;
219
220 #ifdef HAVE_KATE
221 kate_info ki;
222 kate_comment kc;
223 kate_state k;
224 oe_lyrics *lyrics=NULL;
225 size_t lyrics_index=0;
226 double vorbis_time = 0.0;
227 #endif
228
229 long samplesdone=0;
230 int eos;
231 long bytes_written = 0, packetsdone=0;
232 double time_elapsed;
233 int ret=0;
234 TIMER *timer;
235 int result;
236
237 if(opt->channels > 255) {
238 fprintf(stderr, _("255 channels should be enough for anyone. (Sorry, but Vorbis doesn't support more)\n"));
239 return 1;
240 }
241
242 /* get start time. */
243 timer = timer_start();
244
245 if(!opt->managed && (opt->min_bitrate>=0 || opt->max_bitrate>=0)){
246 fprintf(stderr, _("Requesting a minimum or maximum bitrate requires --managed\n"));
247 return 1;
248 }
249
250 /* if we had no quality or bitrate spec at all from the user, use
251 the default quality with no management --Monty 20020711 */
252 if(opt->bitrate < 0 && opt->min_bitrate < 0 && opt->max_bitrate < 0){
253 opt->quality_set=1;
254 }
255
256 opt->start_encode(opt->infilename, opt->filename, opt->bitrate, opt->quality,
257 opt->quality_set, opt->managed, opt->min_bitrate, opt->max_bitrate);
258
259 /* Have vorbisenc choose a mode for us */
260 vorbis_info_init(&vi);
261
262 if(opt->quality_set > 0){
263 if(vorbis_encode_setup_vbr(&vi, opt->channels, opt->rate, opt->quality)){
264 fprintf(stderr, _("Mode initialisation failed: invalid parameters for quality\n"));
265 vorbis_info_clear(&vi);
266 return 1;
267 }
268
269 /* do we have optional hard bitrate restrictions? */
270 if(opt->max_bitrate > 0 || opt->min_bitrate > 0){
271 #ifdef OV_ECTL_RATEMANAGE2_GET
272 long bitrate;
273 struct ovectl_ratemanage2_arg ai;
274
275 vorbis_encode_ctl(&vi, OV_ECTL_RATEMANAGE2_GET, &ai);
276
277 /* libvorbis 1.1 (and current svn) doesn't actually fill this in,
278 which looks like a bug. It'll then reject it when we call the
279 SET version below. So, fill it in with the values that libvorbis
280 would have used to fill in this structure if we were using the
281 bitrate-oriented setup functions. Unfortunately, some of those
282 values are dependent on the bitrate, and libvorbis has no way to
283 get a nominal bitrate from a quality value. Well, except by doing
284 a full setup... So, we do that.
285 Also, note that this won't work correctly unless you have
286 version 1.1.1 or later of libvorbis.
287 */
288
289 {
290 vorbis_info vi2;
291 vorbis_info_init(&vi2);
292 vorbis_encode_setup_vbr(&vi2, opt->channels, opt->rate, opt->quality);
293 vorbis_encode_setup_init(&vi2);
294 bitrate = vi2.bitrate_nominal;
295 vorbis_info_clear(&vi2);
296 }
297
298 ai.bitrate_average_kbps = bitrate/1000;
299 ai.bitrate_average_damping = 1.5;
300 ai.bitrate_limit_reservoir_bits = bitrate * 2;
301 ai.bitrate_limit_reservoir_bias = .1;
302
303 /* And now the ones we actually wanted to set */
304 ai.bitrate_limit_min_kbps=opt->min_bitrate;
305 ai.bitrate_limit_max_kbps=opt->max_bitrate;
306 ai.management_active=1;
307
308 if(vorbis_encode_ctl(&vi, OV_ECTL_RATEMANAGE2_SET, &ai) == 0)
309 fprintf(stderr, _("Set optional hard quality restrictions\n"));
310 else {
311 fprintf(stderr, _("Failed to set bitrate min/max in quality mode\n"));
312 vorbis_info_clear(&vi);
313 return 1;
314 }
315 #else
316 fprintf(stderr, _("This version of libvorbisenc cannot set advanced rate management parameters\n"));
317 return 1;
318 #endif
319 }
320
321
322 }else {
323 if(vorbis_encode_setup_managed(&vi, opt->channels, opt->rate,
324 opt->max_bitrate>0?opt->max_bitrate*1000:-1,
325 opt->bitrate*1000,
326 opt->min_bitrate>0?opt->min_bitrate*1000:-1)){
327 fprintf(stderr, _("Mode initialisation failed: invalid parameters for bitrate\n"));
328 vorbis_info_clear(&vi);
329 return 1;
330 }
331 }
332
333 #ifdef OV_ECTL_RATEMANAGE2_SET
334 if(opt->managed && opt->bitrate < 0)
335 {
336 struct ovectl_ratemanage2_arg ai;
337 vorbis_encode_ctl(&vi, OV_ECTL_RATEMANAGE2_GET, &ai);
338 ai.bitrate_average_kbps=-1;
339 vorbis_encode_ctl(&vi, OV_ECTL_RATEMANAGE2_SET, &ai);
340 }
341 else if(!opt->managed)
342 {
343 /* Turn off management entirely (if it was turned on). */
344 vorbis_encode_ctl(&vi, OV_ECTL_RATEMANAGE2_SET, NULL);
345 }
346 #endif
347
348 set_advanced_encoder_options(opt->advopt, opt->advopt_count, &vi);
349
350 vorbis_encode_setup_init(&vi);
351
352
353 /* Now, set up the analysis engine, stream encoder, and other
354 preparation before the encoding begins.
355 */
356
357 vorbis_analysis_init(&vd,&vi);
358 vorbis_block_init(&vd,&vb);
359
360 #ifdef HAVE_KATE
361 if (opt->lyrics) {
362 /* load lyrics */
363 lyrics=load_lyrics(opt->lyrics);
364 /* if it fails, don't do anything else for lyrics */
365 if (!lyrics) {
366 opt->lyrics = NULL;
367 } else {
368 /* init kate for encoding */
369 kate_info_init(&ki);
370 kate_info_set_category(&ki, "LRC");
371 if (opt->lyrics_language)
372 kate_info_set_language(&ki, opt->lyrics_language);
373 else
374 fprintf(stderr, _("WARNING: no language specified for %s\n"), opt->lyrics);
375 kate_comment_init(&kc);
376 kate_encode_init(&k,&ki);
377
378 /* if we're in karaoke mode (we have syllable level timing info),
379 add style info in case some graphical player is used */
380 add_kate_karaoke_style(&ki, 255, 255, 255, 255);
381 add_kate_karaoke_style(&ki, 255, 128, 128, 255);
382 }
383 }
384 #endif
385
386 ogg_stream_init(&os, opt->serialno);
387 if (opt->with_skeleton)
388 ogg_stream_init(&so, opt->skeleton_serialno);
389 if (opt->lyrics)
390 ogg_stream_init(&ko, opt->kate_serialno);
391
392 /* create the skeleton fishead packet and output it */
393 if (opt->with_skeleton) {
394 add_fishead_packet(&so);
395 if ((ret = flush_ogg_stream_to_file(&so, opt->out))) {
396 opt->error(_("Failed writing fishead packet to output stream\n"));
397 goto cleanup;
398 }
399 }
400
401 /* Now, build the three header packets and send through to the stream
402 output stage (but defer actual file output until the main encode loop) */
403
404 {
405 ogg_packet header_main;
406 ogg_packet header_comments;
407 ogg_packet header_codebooks;
408
409 /* Build the packets */
410 vorbis_analysis_headerout(&vd,opt->comments,
411 &header_main,&header_comments,&header_codebooks);
412
413 /* And stream them out */
414 /* output the vorbis bos first, then the kate bos, then the fisbone packets */
415 ogg_stream_packetin(&os,&header_main);
416 while((result = ogg_stream_flush(&os, &og)))
417 {
418 if(!result) break;
419 ret = oe_write_page(&og, opt->out);
420 if(ret != og.header_len + og.body_len)
421 {
422 opt->error(_("Failed writing header to output stream\n"));
423 ret = 1;
424 goto cleanup; /* Bail and try to clean up stuff */
425 }
426 }
427
428 #ifdef HAVE_KATE
429 if (opt->lyrics) {
430 ogg_packet kate_op;
431 ret = kate_ogg_encode_headers(&k, &kc, &kate_op);
432 if (ret < 0) {
433 opt->error(_("Failed encoding Kate header\n"));
434 goto cleanup;
435 }
436 ogg_stream_packetin(&ko,&kate_op);
437 while((result = ogg_stream_flush(&ko, &og)))
438 {
439 if(!result) break;
440 ret = oe_write_page(&og, opt->out);
441 if(ret != og.header_len + og.body_len)
442 {
443 opt->error(_("Failed writing header to output stream\n"));
444 ret = 1;
445 goto cleanup; /* Bail and try to clean up stuff */
446 }
447 }
448 ogg_packet_clear(&kate_op);
449 }
450 #endif
451
452 if (opt->with_skeleton) {
453 add_vorbis_fisbone_packet(&so, opt);
454 if ((ret = flush_ogg_stream_to_file(&so, opt->out))) {
455 opt->error(_("Failed writing fisbone header packet to output stream\n"));
456 goto cleanup;
457 }
458 #ifdef HAVE_KATE
459 if (opt->lyrics) {
460 add_kate_fisbone_packet(&so, opt, &ki);
461 if ((ret = flush_ogg_stream_to_file(&so, opt->out))) {
462 opt->error(_("Failed writing fisbone header packet to output stream\n"));
463 goto cleanup;
464 }
465 }
466 #endif
467 }
468
469 /* write the next Vorbis headers */
470 ogg_stream_packetin(&os,&header_comments);
471 ogg_stream_packetin(&os,&header_codebooks);
472
473 while((result = ogg_stream_flush(&os, &og)))
474 {
475 if(!result) break;
476 ret = oe_write_page(&og, opt->out);
477 if(ret != og.header_len + og.body_len)
478 {
479 opt->error(_("Failed writing header to output stream\n"));
480 ret = 1;
481 goto cleanup; /* Bail and try to clean up stuff */
482 }
483 }
484 }
485
486 /* build kate headers if requested */
487 #ifdef HAVE_KATE
488 if (opt->lyrics) {
489 while (kate_ogg_encode_headers(&k,&kc,&op)==0) {
490 ogg_stream_packetin(&ko,&op);
491 ogg_packet_clear(&op);
492 }
493 while((result = ogg_stream_flush(&ko, &og)))
494 {
495 if(!result) break;
496 ret = oe_write_page(&og, opt->out);
497 if(ret != og.header_len + og.body_len)
498 {
499 opt->error(_("Failed writing header to output stream\n"));
500 ret = 1;
501 goto cleanup; /* Bail and try to clean up stuff */
502 }
503 }
504 }
505 #endif
506
507 if (opt->with_skeleton) {
508 add_eos_packet_to_stream(&so);
509 if ((ret = flush_ogg_stream_to_file(&so, opt->out))) {
510 opt->error(_("Failed writing skeleton eos packet to output stream\n"));
511 goto cleanup;
512 }
513 }
514
515 eos = 0;
516
517 /* Main encode loop - continue until end of file */
518 while(!eos)
519 {
520 float **buffer = vorbis_analysis_buffer(&vd, READSIZE);
521 long samples_read = opt->read_samples(opt->readdata,
522 buffer, READSIZE);
523
524 if(samples_read ==0)
525 /* Tell the library that we wrote 0 bytes - signalling the end */
526 vorbis_analysis_wrote(&vd,0);
527 else
528 {
529 samplesdone += samples_read;
530
531 /* Call progress update every 40 pages */
532 if(packetsdone>=40)
533 {
534 double time;
535
536 packetsdone = 0;
537 time = timer_time(timer);
538
539 opt->progress_update(opt->filename, opt->total_samples_per_channel,
540 samplesdone, time);
541 }
542
543 /* Tell the library how many samples (per channel) we wrote
544 into the supplied buffer */
545 vorbis_analysis_wrote(&vd, samples_read);
546 }
547
548 /* While we can get enough data from the library to analyse, one
549 block at a time... */
550 while(vorbis_analysis_blockout(&vd,&vb)==1)
551 {
552
553 /* Do the main analysis, creating a packet */
554 vorbis_analysis(&vb, NULL);
555 vorbis_bitrate_addblock(&vb);
556
557 while(vorbis_bitrate_flushpacket(&vd, &op))
558 {
559 /* Add packet to bitstream */
560 ogg_stream_packetin(&os,&op);
561 packetsdone++;
562
563 /* If we've gone over a page boundary, we can do actual output,
564 so do so (for however many pages are available) */
565
566 while(!eos)
567 {
568 int result = ogg_stream_pageout(&os,&og);
569 if(!result) break;
570
571 /* now that we have a new Vorbis page, we scan lyrics for any that is due */
572 #ifdef HAVE_KATE
573 if (opt->lyrics && ogg_page_granulepos(&og)>=0) {
574 vorbis_time = vorbis_granule_time(&vd, ogg_page_granulepos(&og));
575 const oe_lyrics_item *item;
576 while ((item = get_lyrics(lyrics, vorbis_time, &lyrics_index))) {
577 ogg_packet kate_op;
578 if (item->km) {
579 ret = kate_encode_set_style_index(&k, 0);
580 if (ret < 0) {
581 opt->error(_("Failed encoding karaoke style - continuing anyway\n"));
582 }
583 ret = kate_encode_set_secondary_style_index(&k, 1);
584 if (ret < 0) {
585 opt->error(_("Failed encoding karaoke style - continuing anyway\n"));
586 }
587 ret = kate_encode_add_motion(&k, item->km, 0);
588 if (ret < 0) {
589 opt->error(_("Failed encoding karaoke motion - continuing anyway\n"));
590 }
591 }
592 ret = kate_ogg_encode_text(&k, item->t0, item->t1, item->text, strlen(item->text)+1, &kate_op);
593 if (ret < 0) {
594 opt->error(_("Failed encoding lyrics - continuing anyway\n"));
595 }
596 else {
597 ogg_stream_packetin(&ko, &kate_op);
598 ogg_packet_clear(&kate_op);
599 while (1) {
600 ogg_page ogk;
601 int result=ogg_stream_flush(&ko,&ogk);
602 if (!result) break;
603 ret = oe_write_page(&ogk, opt->out);
604 if(ret != ogk.header_len + ogk.body_len)
605 {
606 opt->error(_("Failed writing data to output stream\n"));
607 ret = 1;
608 goto cleanup; /* Bail */
609 }
610 else
611 bytes_written += ret;
612 }
613 }
614 }
615 }
616 #endif
617
618 ret = oe_write_page(&og, opt->out);
619 if(ret != og.header_len + og.body_len)
620 {
621 opt->error(_("Failed writing data to output stream\n"));
622 ret = 1;
623 goto cleanup; /* Bail */
624 }
625 else
626 bytes_written += ret;
627
628 if(ogg_page_eos(&og))
629 eos = 1;
630 }
631 }
632 }
633 }
634
635 /* if encoding lyrics, signal EOS and cleanup the kate state */
636 #ifdef HAVE_KATE
637 if (opt->lyrics) {
638 ogg_packet kate_op;
639 ret = kate_ogg_encode_finish(&k, vorbis_time, &kate_op);
640 if (ret < 0) {
641 opt->error(_("Failed encoding Kate EOS packet\n"));
642 }
643 else {
644 ogg_stream_packetin(&ko,&kate_op);
645 packetsdone++;
646 ogg_packet_clear(&kate_op);
647
648 eos = 0;
649 while(!eos)
650 {
651 int result = ogg_stream_pageout(&ko,&og);
652 if(!result) break;
653
654 ret = oe_write_page(&og, opt->out);
655 if(ret != og.header_len + og.body_len)
656 {
657 opt->error(_("Failed writing data to output stream\n"));
658 ret = 1;
659 goto cleanup; /* Bail */
660 }
661 else
662 bytes_written += ret;
663
664 if(ogg_page_eos(&og))
665 eos = 1;
666 }
667 }
668 }
669 #endif
670
671 ret = 0; /* Success. Set return value to 0 since other things reuse it
672 * for nefarious purposes. */
673
674 /* Cleanup time */
675 cleanup:
676
677 #ifdef HAVE_KATE
678 if (opt->lyrics) {
679 ogg_stream_clear(&ko);
680 kate_clear(&k);
681 kate_info_clear(&ki);
682 kate_comment_clear(&kc);
683 free_lyrics(lyrics);
684 }
685 #endif
686
687 if (opt->with_skeleton)
688 ogg_stream_clear(&so);
689
690 ogg_stream_clear(&os);
691
692 vorbis_block_clear(&vb);
693 vorbis_dsp_clear(&vd);
694 vorbis_info_clear(&vi);
695
696 time_elapsed = timer_time(timer);
697 opt->end_encode(opt->filename, time_elapsed, opt->rate, samplesdone, bytes_written);
698
699 timer_clear(timer);
700
701 return ret;
702 }
703
update_statistics_full(char * fn,long total,long done,double time)704 void update_statistics_full(char *fn, long total, long done, double time)
705 {
706 static char *spinner="|/-\\";
707 static int spinpoint = 0;
708 double remain_time;
709 int minutes=0,seconds=0;
710
711 remain_time = time/((double)done/(double)total) - time;
712 minutes = ((int)remain_time)/60;
713 seconds = (int)(remain_time - (double)((int)remain_time/60)*60);
714
715 fprintf(stderr, "\r");
716 fprintf(stderr, _("\t[%5.1f%%] [%2dm%.2ds remaining] %c "),
717 done*100.0/total, minutes, seconds, spinner[spinpoint++%4]);
718 }
719
update_statistics_notime(char * fn,long total,long done,double time)720 void update_statistics_notime(char *fn, long total, long done, double time)
721 {
722 static char *spinner="|/-\\";
723 static int spinpoint =0;
724
725 fprintf(stderr, "\r");
726 fprintf(stderr, _("\tEncoding [%2dm%.2ds so far] %c "),
727 ((int)time)/60, (int)(time - (double)((int)time/60)*60),
728 spinner[spinpoint++%4]);
729 }
730
oe_write_page(ogg_page * page,FILE * fp)731 int oe_write_page(ogg_page *page, FILE *fp)
732 {
733 int written;
734 written = fwrite(page->header,1,page->header_len, fp);
735 written += fwrite(page->body,1,page->body_len, fp);
736
737 return written;
738 }
739
final_statistics(char * fn,double time,int rate,long samples,long bytes)740 void final_statistics(char *fn, double time, int rate, long samples, long bytes)
741 {
742 double speed_ratio;
743 if(fn)
744 fprintf(stderr, _("\n\nDone encoding file \"%s\"\n"), fn);
745 else
746 fprintf(stderr, _("\n\nDone encoding.\n"));
747
748 speed_ratio = (double)samples / (double)rate / time;
749
750 fprintf(stderr, _("\n\tFile length: %dm %04.1fs\n"),
751 (int)(samples/rate/60),
752 samples/rate -
753 floor(samples/rate/60)*60);
754 fprintf(stderr, _("\tElapsed time: %dm %04.1fs\n"),
755 (int)(time/60),
756 time - floor(time/60)*60);
757 fprintf(stderr, _("\tRate: %.4f\n"), speed_ratio);
758 fprintf(stderr, _("\tAverage bitrate: %.1f kb/s\n\n"),
759 8./1000.*((double)bytes/((double)samples/(double)rate)));
760 }
761
final_statistics_null(char * fn,double time,int rate,long samples,long bytes)762 void final_statistics_null(char *fn, double time, int rate, long samples,
763 long bytes)
764 {
765 /* Don't do anything, this is just a placeholder function for quiet mode */
766 }
767
update_statistics_null(char * fn,long total,long done,double time)768 void update_statistics_null(char *fn, long total, long done, double time)
769 {
770 /* So is this */
771 }
772
encode_error(char * errmsg)773 void encode_error(char *errmsg)
774 {
775 fprintf(stderr, "\n%s\n", errmsg);
776 }
777
print_brconstraints(int min,int max)778 static void print_brconstraints(int min, int max)
779 {
780 if(min > 0 && max > 0)
781 fprintf(stderr, _("(min %d kbps, max %d kbps)"), min,max);
782 else if(min > 0)
783 fprintf(stderr, _("(min %d kbps, no max)"), min);
784 else if(max > 0)
785 fprintf(stderr, _("(no min, max %d kbps)"), max);
786 else
787 fprintf(stderr, _("(no min or max)"));
788 }
789
start_encode_full(char * fn,char * outfn,int bitrate,float quality,int qset,int managed,int min,int max)790 void start_encode_full(char *fn, char *outfn, int bitrate, float quality, int qset,
791 int managed, int min, int max)
792 {
793 if(bitrate>0){
794 if(managed>0){
795 fprintf(stderr, _("Encoding %s%s%s to \n "
796 "%s%s%s \nat average bitrate %d kbps "),
797 fn?"\"":"", fn?fn:_("standard input"), fn?"\"":"",
798 outfn?"\"":"", outfn?outfn:_("standard output"), outfn?"\"":"",
799 bitrate);
800 print_brconstraints(min,max);
801 fprintf(stderr, ", \nusing full bitrate management engine\n");
802 } else {
803 fprintf(stderr, _("Encoding %s%s%s to \n %s%s%s \nat approximate bitrate %d kbps (VBR encoding enabled)\n"),
804 fn?"\"":"", fn?fn:_("standard input"), fn?"\"":"",
805 outfn?"\"":"", outfn?outfn:_("standard output"), outfn?"\"":"",
806 bitrate);
807 }
808 }else{
809 if(qset>0){
810 if(managed>0){
811 fprintf(stderr, _("Encoding %s%s%s to \n %s%s%s \nat quality level %2.2f using constrained VBR "),
812 fn?"\"":"", fn?fn:_("standard input"), fn?"\"":"",
813 outfn?"\"":"", outfn?outfn:_("standard output"), outfn?"\"":"",
814 quality * 10);
815 print_brconstraints(min,max);
816 fprintf(stderr, "\n");
817 }else{
818 fprintf(stderr, _("Encoding %s%s%s to \n %s%s%s \nat quality %2.2f\n"),
819 fn?"\"":"", fn?fn:_("standard input"), fn?"\"":"",
820 outfn?"\"":"", outfn?outfn:_("standard output"), outfn?"\"":"",
821 quality * 10);
822 }
823 }else{
824 fprintf(stderr, _("Encoding %s%s%s to \n %s%s%s \nusing bitrate management "),
825 fn?"\"":"", fn?fn:_("standard input"), fn?"\"":"",
826 outfn?"\"":"", outfn?outfn:_("standard output"), outfn?"\"":"");
827 print_brconstraints(min,max);
828 fprintf(stderr, "\n");
829 }
830 }
831 }
832
start_encode_null(char * fn,char * outfn,int bitrate,float quality,int qset,int managed,int min,int max)833 void start_encode_null(char *fn, char *outfn, int bitrate, float quality, int qset,
834 int managed, int min, int max)
835 {
836 }
837