Add missing config.h includes
[flac.git] / src / test_libFLAC++ / encoders.cpp
1 /* test_libFLAC++ - Unit tester for libFLAC++
2  * Copyright (C) 2002-2009  Josh Coalson
3  * Copyright (C) 2011-2013  Xiph.Org Foundation
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include "encoders.h"
25 #include "FLAC/assert.h"
26 #include "FLAC++/encoder.h"
27 #include "share/grabbag.h"
28 extern "C" {
29 #include "test_libs_common/file_utils_flac.h"
30 #include "test_libs_common/metadata_utils.h"
31 }
32 #include <errno.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include "share/compat.h"
37
38 typedef enum {
39         LAYER_STREAM = 0, /* FLAC__stream_encoder_init_stream() without seeking */
40         LAYER_SEEKABLE_STREAM, /* FLAC__stream_encoder_init_stream() with seeking */
41         LAYER_FILE, /* FLAC__stream_encoder_init_FILE() */
42         LAYER_FILENAME /* FLAC__stream_encoder_init_file() */
43 } Layer;
44
45 static const char * const LayerString[] = {
46         "Stream",
47         "Seekable Stream",
48         "FILE*",
49         "Filename"
50 };
51
52 static ::FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_, cuesheet_, picture_, unknown_;
53 static ::FLAC__StreamMetadata *metadata_sequence_[] = { &vorbiscomment_, &padding_, &seektable_, &application1_, &application2_, &cuesheet_, &picture_, &unknown_ };
54 static const unsigned num_metadata_ = sizeof(metadata_sequence_) / sizeof(metadata_sequence_[0]);
55
56 static const char *flacfilename(bool is_ogg)
57 {
58         return is_ogg? "metadata.oga" : "metadata.flac";
59 }
60
61 static bool die_(const char *msg)
62 {
63         printf("ERROR: %s\n", msg);
64         return false;
65 }
66
67 static bool die_s_(const char *msg, const FLAC::Encoder::Stream *encoder)
68 {
69         FLAC::Encoder::Stream::State state = encoder->get_state();
70
71         if(msg)
72                 printf("FAILED, %s", msg);
73         else
74                 printf("FAILED");
75
76         printf(", state = %u (%s)\n", (unsigned)((::FLAC__StreamEncoderState)state), state.as_cstring());
77         if(state == ::FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR) {
78                 FLAC::Decoder::Stream::State dstate = encoder->get_verify_decoder_state();
79                 printf("      verify decoder state = %u (%s)\n", (unsigned)((::FLAC__StreamDecoderState)dstate), dstate.as_cstring());
80         }
81
82         return false;
83 }
84
85 static void init_metadata_blocks_()
86 {
87         mutils__init_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_);
88 }
89
90 static void free_metadata_blocks_()
91 {
92         mutils__free_metadata_blocks(&streaminfo_, &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_, &cuesheet_, &picture_, &unknown_);
93 }
94
95 class StreamEncoder : public FLAC::Encoder::Stream {
96 public:
97         Layer layer_;
98         FILE *file_;
99
100         StreamEncoder(Layer layer): FLAC::Encoder::Stream(), layer_(layer), file_(0) { }
101         ~StreamEncoder() { }
102
103         // from FLAC::Encoder::Stream
104         ::FLAC__StreamEncoderReadStatus read_callback(FLAC__byte buffer[], size_t *bytes);
105         ::FLAC__StreamEncoderWriteStatus write_callback(const FLAC__byte buffer[], size_t bytes, unsigned samples, unsigned current_frame);
106         ::FLAC__StreamEncoderSeekStatus seek_callback(FLAC__uint64 absolute_byte_offset);
107         ::FLAC__StreamEncoderTellStatus tell_callback(FLAC__uint64 *absolute_byte_offset);
108         void metadata_callback(const ::FLAC__StreamMetadata *metadata);
109 };
110
111 ::FLAC__StreamEncoderReadStatus StreamEncoder::read_callback(FLAC__byte buffer[], size_t *bytes)
112 {
113         if(*bytes > 0) {
114                 *bytes = fread(buffer, sizeof(FLAC__byte), *bytes, file_);
115                 if(ferror(file_))
116                         return ::FLAC__STREAM_ENCODER_READ_STATUS_ABORT;
117                 else if(*bytes == 0)
118                         return ::FLAC__STREAM_ENCODER_READ_STATUS_END_OF_STREAM;
119                 else
120                         return ::FLAC__STREAM_ENCODER_READ_STATUS_CONTINUE;
121         }
122         else
123                 return ::FLAC__STREAM_ENCODER_READ_STATUS_ABORT;
124 }
125
126 ::FLAC__StreamEncoderWriteStatus StreamEncoder::write_callback(const FLAC__byte buffer[], size_t bytes, unsigned samples, unsigned current_frame)
127 {
128         (void)samples, (void)current_frame;
129
130         if(fwrite(buffer, 1, bytes, file_) != bytes)
131                 return ::FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
132         else
133                 return ::FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
134 }
135
136 ::FLAC__StreamEncoderSeekStatus StreamEncoder::seek_callback(FLAC__uint64 absolute_byte_offset)
137 {
138         if(layer_==LAYER_STREAM)
139                 return ::FLAC__STREAM_ENCODER_SEEK_STATUS_UNSUPPORTED;
140         else if(fseeko(file_, (FLAC__off_t)absolute_byte_offset, SEEK_SET) < 0)
141                 return FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR;
142         else
143                 return FLAC__STREAM_ENCODER_SEEK_STATUS_OK;
144 }
145
146 ::FLAC__StreamEncoderTellStatus StreamEncoder::tell_callback(FLAC__uint64 *absolute_byte_offset)
147 {
148         FLAC__off_t pos;
149         if(layer_==LAYER_STREAM)
150                 return ::FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED;
151         else if((pos = ftello(file_)) < 0)
152                 return FLAC__STREAM_ENCODER_TELL_STATUS_ERROR;
153         else {
154                 *absolute_byte_offset = (FLAC__uint64)pos;
155                 return FLAC__STREAM_ENCODER_TELL_STATUS_OK;
156         }
157 }
158
159 void StreamEncoder::metadata_callback(const ::FLAC__StreamMetadata *metadata)
160 {
161         (void)metadata;
162 }
163
164 class FileEncoder : public FLAC::Encoder::File {
165 public:
166         Layer layer_;
167
168         FileEncoder(Layer layer): FLAC::Encoder::File(), layer_(layer) { }
169         ~FileEncoder() { }
170
171         // from FLAC::Encoder::File
172         void progress_callback(FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate);
173 };
174
175 void FileEncoder::progress_callback(FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate)
176 {
177         (void)bytes_written, (void)samples_written, (void)frames_written, (void)total_frames_estimate;
178 }
179
180 static FLAC::Encoder::Stream *new_by_layer(Layer layer)
181 {
182         if(layer < LAYER_FILE)
183                 return new StreamEncoder(layer);
184         else
185                 return new FileEncoder(layer);
186 }
187
188 static bool test_stream_encoder(Layer layer, bool is_ogg)
189 {
190         FLAC::Encoder::Stream *encoder;
191         ::FLAC__StreamEncoderInitStatus init_status;
192         FILE *file = 0;
193         FLAC__int32 samples[1024];
194         FLAC__int32 *samples_array[1] = { samples };
195         unsigned i;
196
197         printf("\n+++ libFLAC++ unit test: FLAC::Encoder::%s (layer: %s, format: %s)\n\n", layer<LAYER_FILE? "Stream":"File", LayerString[layer], is_ogg? "Ogg FLAC":"FLAC");
198
199         printf("allocating encoder instance... ");
200         encoder = new_by_layer(layer);
201         if(0 == encoder) {
202                 printf("FAILED, new returned NULL\n");
203                 return false;
204         }
205         printf("OK\n");
206
207         printf("testing is_valid()... ");
208         if(!encoder->is_valid()) {
209                 printf("FAILED, returned false\n");
210                 return false;
211         }
212         printf("OK\n");
213
214         if(is_ogg) {
215                 printf("testing set_ogg_serial_number()... ");
216                 if(!encoder->set_ogg_serial_number(file_utils__ogg_serial_number))
217                         return die_s_("returned false", encoder);
218                 printf("OK\n");
219         }
220
221         printf("testing set_verify()... ");
222         if(!encoder->set_verify(true))
223                 return die_s_("returned false", encoder);
224         printf("OK\n");
225
226         printf("testing set_streamable_subset()... ");
227         if(!encoder->set_streamable_subset(true))
228                 return die_s_("returned false", encoder);
229         printf("OK\n");
230
231         printf("testing set_channels()... ");
232         if(!encoder->set_channels(streaminfo_.data.stream_info.channels))
233                 return die_s_("returned false", encoder);
234         printf("OK\n");
235
236         printf("testing set_bits_per_sample()... ");
237         if(!encoder->set_bits_per_sample(streaminfo_.data.stream_info.bits_per_sample))
238                 return die_s_("returned false", encoder);
239         printf("OK\n");
240
241         printf("testing set_sample_rate()... ");
242         if(!encoder->set_sample_rate(streaminfo_.data.stream_info.sample_rate))
243                 return die_s_("returned false", encoder);
244         printf("OK\n");
245
246         printf("testing set_compression_level()... ");
247         if(!encoder->set_compression_level((unsigned)(-1)))
248                 return die_s_("returned false", encoder);
249         printf("OK\n");
250
251         printf("testing set_blocksize()... ");
252         if(!encoder->set_blocksize(streaminfo_.data.stream_info.min_blocksize))
253                 return die_s_("returned false", encoder);
254         printf("OK\n");
255
256         printf("testing set_do_mid_side_stereo()... ");
257         if(!encoder->set_do_mid_side_stereo(false))
258                 return die_s_("returned false", encoder);
259         printf("OK\n");
260
261         printf("testing set_loose_mid_side_stereo()... ");
262         if(!encoder->set_loose_mid_side_stereo(false))
263                 return die_s_("returned false", encoder);
264         printf("OK\n");
265
266         printf("testing set_max_lpc_order()... ");
267         if(!encoder->set_max_lpc_order(0))
268                 return die_s_("returned false", encoder);
269         printf("OK\n");
270
271         printf("testing set_qlp_coeff_precision()... ");
272         if(!encoder->set_qlp_coeff_precision(0))
273                 return die_s_("returned false", encoder);
274         printf("OK\n");
275
276         printf("testing set_do_qlp_coeff_prec_search()... ");
277         if(!encoder->set_do_qlp_coeff_prec_search(false))
278                 return die_s_("returned false", encoder);
279         printf("OK\n");
280
281         printf("testing set_do_escape_coding()... ");
282         if(!encoder->set_do_escape_coding(false))
283                 return die_s_("returned false", encoder);
284         printf("OK\n");
285
286         printf("testing set_do_exhaustive_model_search()... ");
287         if(!encoder->set_do_exhaustive_model_search(false))
288                 return die_s_("returned false", encoder);
289         printf("OK\n");
290
291         printf("testing set_min_residual_partition_order()... ");
292         if(!encoder->set_min_residual_partition_order(0))
293                 return die_s_("returned false", encoder);
294         printf("OK\n");
295
296         printf("testing set_max_residual_partition_order()... ");
297         if(!encoder->set_max_residual_partition_order(0))
298                 return die_s_("returned false", encoder);
299         printf("OK\n");
300
301         printf("testing set_rice_parameter_search_dist()... ");
302         if(!encoder->set_rice_parameter_search_dist(0))
303                 return die_s_("returned false", encoder);
304         printf("OK\n");
305
306         printf("testing set_total_samples_estimate()... ");
307         if(!encoder->set_total_samples_estimate(streaminfo_.data.stream_info.total_samples))
308                 return die_s_("returned false", encoder);
309         printf("OK\n");
310
311         printf("testing set_metadata()... ");
312         if(!encoder->set_metadata(metadata_sequence_, num_metadata_))
313                 return die_s_("returned false", encoder);
314         printf("OK\n");
315
316         if(layer < LAYER_FILENAME) {
317                 printf("opening file for FLAC output... ");
318                 file = ::flac_fopen(flacfilename(is_ogg), "w+b");
319                 if(0 == file) {
320                         printf("ERROR (%s)\n", strerror(errno));
321                         return false;
322                 }
323                 printf("OK\n");
324                 if(layer < LAYER_FILE)
325                         dynamic_cast<StreamEncoder*>(encoder)->file_ = file;
326         }
327
328         switch(layer) {
329                 case LAYER_STREAM:
330                 case LAYER_SEEKABLE_STREAM:
331                         printf("testing init%s()... ", is_ogg? "_ogg":"");
332                         init_status = is_ogg? encoder->init_ogg() : encoder->init();
333                         break;
334                 case LAYER_FILE:
335                         printf("testing init%s()... ", is_ogg? "_ogg":"");
336                         init_status = is_ogg?
337                                 dynamic_cast<FLAC::Encoder::File*>(encoder)->init_ogg(file) :
338                                 dynamic_cast<FLAC::Encoder::File*>(encoder)->init(file);
339                         break;
340                 case LAYER_FILENAME:
341                         printf("testing init%s()... ", is_ogg? "_ogg":"");
342                         init_status = is_ogg?
343                                 dynamic_cast<FLAC::Encoder::File*>(encoder)->init_ogg(flacfilename(is_ogg)) :
344                                 dynamic_cast<FLAC::Encoder::File*>(encoder)->init(flacfilename(is_ogg));
345                         break;
346                 default:
347                         die_("internal error 001");
348                         return false;
349         }
350         if(init_status != ::FLAC__STREAM_ENCODER_INIT_STATUS_OK)
351                 return die_s_(0, encoder);
352         printf("OK\n");
353
354         printf("testing get_state()... ");
355         FLAC::Encoder::Stream::State state = encoder->get_state();
356         printf("returned state = %u (%s)... OK\n", (unsigned)((::FLAC__StreamEncoderState)state), state.as_cstring());
357
358         printf("testing get_verify_decoder_state()... ");
359         FLAC::Decoder::Stream::State dstate = encoder->get_verify_decoder_state();
360         printf("returned state = %u (%s)... OK\n", (unsigned)((::FLAC__StreamDecoderState)dstate), dstate.as_cstring());
361
362         {
363                 FLAC__uint64 absolute_sample;
364                 unsigned frame_number;
365                 unsigned channel;
366                 unsigned sample;
367                 FLAC__int32 expected;
368                 FLAC__int32 got;
369
370                 printf("testing get_verify_decoder_error_stats()... ");
371                 encoder->get_verify_decoder_error_stats(&absolute_sample, &frame_number, &channel, &sample, &expected, &got);
372                 printf("OK\n");
373         }
374
375         printf("testing get_verify()... ");
376         if(encoder->get_verify() != true) {
377                 printf("FAILED, expected true, got false\n");
378                 return false;
379         }
380         printf("OK\n");
381
382         printf("testing get_streamable_subset()... ");
383         if(encoder->get_streamable_subset() != true) {
384                 printf("FAILED, expected true, got false\n");
385                 return false;
386         }
387         printf("OK\n");
388
389         printf("testing get_do_mid_side_stereo()... ");
390         if(encoder->get_do_mid_side_stereo() != false) {
391                 printf("FAILED, expected false, got true\n");
392                 return false;
393         }
394         printf("OK\n");
395
396         printf("testing get_loose_mid_side_stereo()... ");
397         if(encoder->get_loose_mid_side_stereo() != false) {
398                 printf("FAILED, expected false, got true\n");
399                 return false;
400         }
401         printf("OK\n");
402
403         printf("testing get_channels()... ");
404         if(encoder->get_channels() != streaminfo_.data.stream_info.channels) {
405                 printf("FAILED, expected %u, got %u\n", streaminfo_.data.stream_info.channels, encoder->get_channels());
406                 return false;
407         }
408         printf("OK\n");
409
410         printf("testing get_bits_per_sample()... ");
411         if(encoder->get_bits_per_sample() != streaminfo_.data.stream_info.bits_per_sample) {
412                 printf("FAILED, expected %u, got %u\n", streaminfo_.data.stream_info.bits_per_sample, encoder->get_bits_per_sample());
413                 return false;
414         }
415         printf("OK\n");
416
417         printf("testing get_sample_rate()... ");
418         if(encoder->get_sample_rate() != streaminfo_.data.stream_info.sample_rate) {
419                 printf("FAILED, expected %u, got %u\n", streaminfo_.data.stream_info.sample_rate, encoder->get_sample_rate());
420                 return false;
421         }
422         printf("OK\n");
423
424         printf("testing get_blocksize()... ");
425         if(encoder->get_blocksize() != streaminfo_.data.stream_info.min_blocksize) {
426                 printf("FAILED, expected %u, got %u\n", streaminfo_.data.stream_info.min_blocksize, encoder->get_blocksize());
427                 return false;
428         }
429         printf("OK\n");
430
431         printf("testing get_max_lpc_order()... ");
432         if(encoder->get_max_lpc_order() != 0) {
433                 printf("FAILED, expected %u, got %u\n", 0, encoder->get_max_lpc_order());
434                 return false;
435         }
436         printf("OK\n");
437
438         printf("testing get_qlp_coeff_precision()... ");
439         (void)encoder->get_qlp_coeff_precision();
440         /* we asked the encoder to auto select this so we accept anything */
441         printf("OK\n");
442
443         printf("testing get_do_qlp_coeff_prec_search()... ");
444         if(encoder->get_do_qlp_coeff_prec_search() != false) {
445                 printf("FAILED, expected false, got true\n");
446                 return false;
447         }
448         printf("OK\n");
449
450         printf("testing get_do_escape_coding()... ");
451         if(encoder->get_do_escape_coding() != false) {
452                 printf("FAILED, expected false, got true\n");
453                 return false;
454         }
455         printf("OK\n");
456
457         printf("testing get_do_exhaustive_model_search()... ");
458         if(encoder->get_do_exhaustive_model_search() != false) {
459                 printf("FAILED, expected false, got true\n");
460                 return false;
461         }
462         printf("OK\n");
463
464         printf("testing get_min_residual_partition_order()... ");
465         if(encoder->get_min_residual_partition_order() != 0) {
466                 printf("FAILED, expected %u, got %u\n", 0, encoder->get_min_residual_partition_order());
467                 return false;
468         }
469         printf("OK\n");
470
471         printf("testing get_max_residual_partition_order()... ");
472         if(encoder->get_max_residual_partition_order() != 0) {
473                 printf("FAILED, expected %u, got %u\n", 0, encoder->get_max_residual_partition_order());
474                 return false;
475         }
476         printf("OK\n");
477
478         printf("testing get_rice_parameter_search_dist()... ");
479         if(encoder->get_rice_parameter_search_dist() != 0) {
480                 printf("FAILED, expected %u, got %u\n", 0, encoder->get_rice_parameter_search_dist());
481                 return false;
482         }
483         printf("OK\n");
484
485         printf("testing get_total_samples_estimate()... ");
486         if(encoder->get_total_samples_estimate() != streaminfo_.data.stream_info.total_samples) {
487                 printf("FAILED, expected %" PRIu64 ", got %" PRIu64 "\n", streaminfo_.data.stream_info.total_samples, encoder->get_total_samples_estimate());
488                 return false;
489         }
490         printf("OK\n");
491
492         /* init the dummy sample buffer */
493         for(i = 0; i < sizeof(samples) / sizeof(FLAC__int32); i++)
494                 samples[i] = i & 7;
495
496         printf("testing process()... ");
497         if(!encoder->process(samples_array, sizeof(samples) / sizeof(FLAC__int32)))
498                 return die_s_("returned false", encoder);
499         printf("OK\n");
500
501         printf("testing process_interleaved()... ");
502         if(!encoder->process_interleaved(samples, sizeof(samples) / sizeof(FLAC__int32)))
503                 return die_s_("returned false", encoder);
504         printf("OK\n");
505
506         printf("testing finish()... ");
507         if(!encoder->finish()) {
508                 state = encoder->get_state();
509                 printf("FAILED, returned false, state = %u (%s)\n", (unsigned)((::FLAC__StreamEncoderState)state), state.as_cstring());
510                 return false;
511         }
512         printf("OK\n");
513
514         if(layer < LAYER_FILE)
515                 ::fclose(dynamic_cast<StreamEncoder*>(encoder)->file_);
516
517         printf("freeing encoder instance... ");
518         delete encoder;
519         printf("OK\n");
520
521         printf("\nPASSED!\n");
522
523         return true;
524 }
525
526 bool test_encoders()
527 {
528         FLAC__bool is_ogg = false;
529
530         while(1) {
531                 init_metadata_blocks_();
532
533                 if(!test_stream_encoder(LAYER_STREAM, is_ogg))
534                         return false;
535
536                 if(!test_stream_encoder(LAYER_SEEKABLE_STREAM, is_ogg))
537                         return false;
538
539                 if(!test_stream_encoder(LAYER_FILE, is_ogg))
540                         return false;
541
542                 if(!test_stream_encoder(LAYER_FILENAME, is_ogg))
543                         return false;
544
545                 (void) grabbag__file_remove_file(flacfilename(is_ogg));
546
547                 free_metadata_blocks_();
548
549                 if(!FLAC_API_SUPPORTS_OGG_FLAC || is_ogg)
550                         break;
551                 is_ogg = true;
552         }
553
554         return true;
555 }