0604b74caf79ebae86a03cb014fb49bfbaa2735b
[flac.git] / src / test_libOggFLAC++ / encoders.cpp
1 /* test_libOggFLAC++ - Unit tester for libOggFLAC++
2  * Copyright (C) 2002,2003  Josh Coalson
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17  */
18
19 #include "encoders.h"
20 extern "C" {
21 #include "file_utils.h"
22 }
23 #include "FLAC/assert.h"
24 #include "OggFLAC++/encoder.h"
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28
29 static ::FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_;
30 static ::FLAC__StreamMetadata *metadata_sequence_[] = { &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_ };
31 static const unsigned num_metadata_ = 5;
32
33 static void *malloc_or_die_(size_t size)
34 {
35         void *x = malloc(size);
36         if(0 == x) {
37                 fprintf(stderr, "ERROR: out of memory allocating %u bytes\n", (unsigned)size);
38                 exit(1);
39         }
40         return x;
41 }
42
43 static void init_metadata_blocks_()
44 {
45         /*
46                 most of the actual numbers and data in the blocks don't matter,
47                 we just want to make sure the encoder encodes them correctly
48
49                 remember, the metadata interface gets tested after the encoders,
50                 so we do all the metadata manipulation here without it.
51         */
52
53         /* min/max_framesize and md5sum don't get written at first, so we have to leave them 0 */
54         streaminfo_.is_last = false;
55         streaminfo_.type = ::FLAC__METADATA_TYPE_STREAMINFO;
56         streaminfo_.length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
57         streaminfo_.data.stream_info.min_blocksize = 576;
58         streaminfo_.data.stream_info.max_blocksize = 576;
59         streaminfo_.data.stream_info.min_framesize = 0;
60         streaminfo_.data.stream_info.max_framesize = 0;
61         streaminfo_.data.stream_info.sample_rate = 44100;
62         streaminfo_.data.stream_info.channels = 1;
63         streaminfo_.data.stream_info.bits_per_sample = 8;
64         streaminfo_.data.stream_info.total_samples = 0;
65         memset(streaminfo_.data.stream_info.md5sum, 0, 16);
66
67         padding_.is_last = false;
68         padding_.type = ::FLAC__METADATA_TYPE_PADDING;
69         padding_.length = 1234;
70
71         seektable_.is_last = false;
72         seektable_.type = ::FLAC__METADATA_TYPE_SEEKTABLE;
73         seektable_.data.seek_table.num_points = 2;
74         seektable_.length = seektable_.data.seek_table.num_points * FLAC__STREAM_METADATA_SEEKPOINT_LENGTH;
75         seektable_.data.seek_table.points = (::FLAC__StreamMetadata_SeekPoint*)malloc_or_die_(seektable_.data.seek_table.num_points * sizeof(::FLAC__StreamMetadata_SeekPoint));
76         seektable_.data.seek_table.points[0].sample_number = 0;
77         seektable_.data.seek_table.points[0].stream_offset = 0;
78         seektable_.data.seek_table.points[0].frame_samples = streaminfo_.data.stream_info.min_blocksize;
79         seektable_.data.seek_table.points[1].sample_number = ::FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER;
80         seektable_.data.seek_table.points[1].stream_offset = 1000;
81         seektable_.data.seek_table.points[1].frame_samples = streaminfo_.data.stream_info.min_blocksize;
82
83         application1_.is_last = false;
84         application1_.type = ::FLAC__METADATA_TYPE_APPLICATION;
85         application1_.length = 8;
86         memcpy(application1_.data.application.id, "\xfe\xdc\xba\x98", 4);
87         application1_.data.application.data = (FLAC__byte*)malloc_or_die_(4);
88         memcpy(application1_.data.application.data, "\xf0\xe1\xd2\xc3", 4);
89
90         application2_.is_last = false;
91         application2_.type = ::FLAC__METADATA_TYPE_APPLICATION;
92         application2_.length = 4;
93         memcpy(application2_.data.application.id, "\x76\x54\x32\x10", 4);
94         application2_.data.application.data = 0;
95
96         vorbiscomment_.is_last = true;
97         vorbiscomment_.type = ::FLAC__METADATA_TYPE_VORBIS_COMMENT;
98         vorbiscomment_.length = (4 + 8) + 4 + (4 + 5) + (4 + 0);
99         vorbiscomment_.data.vorbis_comment.vendor_string.length = 8;
100         vorbiscomment_.data.vorbis_comment.vendor_string.entry = (FLAC__byte*)malloc_or_die_(8);
101         memcpy(vorbiscomment_.data.vorbis_comment.vendor_string.entry, "flac 1.x", 8);
102         vorbiscomment_.data.vorbis_comment.num_comments = 2;
103         vorbiscomment_.data.vorbis_comment.comments = (::FLAC__StreamMetadata_VorbisComment_Entry*)malloc_or_die_(vorbiscomment_.data.vorbis_comment.num_comments * sizeof(::FLAC__StreamMetadata_VorbisComment_Entry));
104         vorbiscomment_.data.vorbis_comment.comments[0].length = 5;
105         vorbiscomment_.data.vorbis_comment.comments[0].entry = (FLAC__byte*)malloc_or_die_(5);
106         memcpy(vorbiscomment_.data.vorbis_comment.comments[0].entry, "ab=cd", 5);
107         vorbiscomment_.data.vorbis_comment.comments[1].length = 0;
108         vorbiscomment_.data.vorbis_comment.comments[1].entry = 0;
109 }
110
111 static void free_metadata_blocks_()
112 {
113         free(seektable_.data.seek_table.points);
114         free(application1_.data.application.data);
115         free(vorbiscomment_.data.vorbis_comment.vendor_string.entry);
116         free(vorbiscomment_.data.vorbis_comment.comments[0].entry);
117         free(vorbiscomment_.data.vorbis_comment.comments);
118 }
119
120 class StreamEncoder : public OggFLAC::Encoder::Stream {
121 public:
122         StreamEncoder(): OggFLAC::Encoder::Stream() { }
123         ~StreamEncoder() { }
124
125         // from OggFLAC::Encoder::Stream
126         ::FLAC__StreamEncoderWriteStatus write_callback(const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame);
127
128         bool die(const char *msg = 0) const;
129 };
130
131 ::FLAC__StreamEncoderWriteStatus StreamEncoder::write_callback(const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame)
132 {
133         (void)buffer, (void)bytes, (void)samples, (void)current_frame;
134
135         return ::FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
136 }
137
138 bool StreamEncoder::die(const char *msg) const
139 {
140         State state = get_state();
141
142         if(msg)
143                 printf("FAILED, %s", msg);
144         else
145                 printf("FAILED");
146
147         printf(", state = %u (%s)\n", (unsigned)((::OggFLAC__StreamEncoderState)state), state.as_cstring());
148         if(state == ::OggFLAC__STREAM_ENCODER_FLAC_STREAM_ENCODER_ERROR) {
149                 FLAC::Encoder::Stream::State state_ = get_FLAC_stream_encoder_state();
150                 printf("      FLAC stream encoder state = %u (%s)\n", (unsigned)((::FLAC__StreamEncoderState)state_), state_.as_cstring());
151                 if(state_ == ::FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR) {
152                         FLAC::Decoder::Stream::State dstate = get_verify_decoder_state();
153                         printf("      verify decoder state = %u (%s)\n", (unsigned)((::FLAC__StreamDecoderState)dstate), dstate.as_cstring());
154                 }
155         }
156
157         return false;
158 }
159
160 static bool test_stream_encoder()
161 {
162         StreamEncoder *encoder;
163         FLAC__int32 samples[1024];
164         FLAC__int32 *samples_array[1] = { samples };
165         unsigned i;
166
167         printf("\n+++ libOggFLAC++ unit test: OggFLAC::Encoder::Stream\n\n");
168
169         printf("allocating encoder instance... ");
170         encoder = new StreamEncoder();
171         if(0 == encoder) {
172                 printf("FAILED, new returned NULL\n");
173                 return false;
174         }
175         printf("OK\n");
176
177         printf("testing is_valid()... ");
178         if(!encoder->is_valid()) {
179                 printf("FAILED, returned false\n");
180                 return false;
181         }
182         printf("OK\n");
183
184         printf("testing set_serial_number()... ");
185         if(!encoder->set_serial_number(file_utils__serial_number))
186                 return encoder->die("returned false");
187         printf("OK\n");
188
189         printf("testing set_verify()... ");
190         if(!encoder->set_verify(true))
191                 return encoder->die("returned false");
192         printf("OK\n");
193
194         printf("testing set_streamable_subset()... ");
195         if(!encoder->set_streamable_subset(true))
196                 return encoder->die("returned false");
197         printf("OK\n");
198
199         printf("testing set_do_mid_side_stereo()... ");
200         if(!encoder->set_do_mid_side_stereo(false))
201                 return encoder->die("returned false");
202         printf("OK\n");
203
204         printf("testing set_loose_mid_side_stereo()... ");
205         if(!encoder->set_loose_mid_side_stereo(false))
206                 return encoder->die("returned false");
207         printf("OK\n");
208
209         printf("testing set_channels()... ");
210         if(!encoder->set_channels(streaminfo_.data.stream_info.channels))
211                 return encoder->die("returned false");
212         printf("OK\n");
213
214         printf("testing set_bits_per_sample()... ");
215         if(!encoder->set_bits_per_sample(streaminfo_.data.stream_info.bits_per_sample))
216                 return encoder->die("returned false");
217         printf("OK\n");
218
219         printf("testing set_sample_rate()... ");
220         if(!encoder->set_sample_rate(streaminfo_.data.stream_info.sample_rate))
221                 return encoder->die("returned false");
222         printf("OK\n");
223
224         printf("testing set_blocksize()... ");
225         if(!encoder->set_blocksize(streaminfo_.data.stream_info.min_blocksize))
226                 return encoder->die("returned false");
227         printf("OK\n");
228
229         printf("testing set_max_lpc_order()... ");
230         if(!encoder->set_max_lpc_order(0))
231                 return encoder->die("returned false");
232         printf("OK\n");
233
234         printf("testing set_qlp_coeff_precision()... ");
235         if(!encoder->set_qlp_coeff_precision(0))
236                 return encoder->die("returned false");
237         printf("OK\n");
238
239         printf("testing set_do_qlp_coeff_prec_search()... ");
240         if(!encoder->set_do_qlp_coeff_prec_search(false))
241                 return encoder->die("returned false");
242         printf("OK\n");
243
244         printf("testing set_do_escape_coding()... ");
245         if(!encoder->set_do_escape_coding(false))
246                 return encoder->die("returned false");
247         printf("OK\n");
248
249         printf("testing set_do_exhaustive_model_search()... ");
250         if(!encoder->set_do_exhaustive_model_search(false))
251                 return encoder->die("returned false");
252         printf("OK\n");
253
254         printf("testing set_min_residual_partition_order()... ");
255         if(!encoder->set_min_residual_partition_order(0))
256                 return encoder->die("returned false");
257         printf("OK\n");
258
259         printf("testing set_max_residual_partition_order()... ");
260         if(!encoder->set_max_residual_partition_order(0))
261                 return encoder->die("returned false");
262         printf("OK\n");
263
264         printf("testing set_rice_parameter_search_dist()... ");
265         if(!encoder->set_rice_parameter_search_dist(0))
266                 return encoder->die("returned false");
267         printf("OK\n");
268
269         printf("testing set_total_samples_estimate()... ");
270         if(!encoder->set_total_samples_estimate(streaminfo_.data.stream_info.total_samples))
271                 return encoder->die("returned false");
272         printf("OK\n");
273
274         printf("testing set_metadata()... ");
275         if(!encoder->set_metadata(metadata_sequence_, num_metadata_))
276                 return encoder->die("returned false");
277         printf("OK\n");
278
279         printf("testing init()... ");
280         if(encoder->init() != ::OggFLAC__STREAM_ENCODER_OK)
281                 return encoder->die();
282         printf("OK\n");
283
284         printf("testing get_state()... ");
285         OggFLAC::Encoder::Stream::State state = encoder->get_state();
286         printf("returned state = %u (%s)... OK\n", (unsigned)((::OggFLAC__StreamEncoderState)state), state.as_cstring());
287
288         printf("testing get_FLAC_stream_encoder_state()... ");
289         FLAC::Encoder::Stream::State state_ = encoder->get_FLAC_stream_encoder_state();
290         printf("returned state = %u (%s)... OK\n", (unsigned)((::FLAC__StreamEncoderState)state_), state_.as_cstring());
291
292         printf("testing get_verify_decoder_state()... ");
293         FLAC::Decoder::Stream::State dstate = encoder->get_verify_decoder_state();
294         printf("returned state = %u (%s)... OK\n", (unsigned)((::FLAC__StreamDecoderState)dstate), dstate.as_cstring());
295
296         {
297                 FLAC__uint64 absolute_sample;
298                 unsigned frame_number;
299                 unsigned channel;
300                 unsigned sample;
301                 FLAC__int32 expected;
302                 FLAC__int32 got;
303
304                 printf("testing get_verify_decoder_error_stats()... ");
305                 encoder->get_verify_decoder_error_stats(&absolute_sample, &frame_number, &channel, &sample, &expected, &got);
306                 printf("OK\n");
307         }
308
309         printf("testing get_verify()... ");
310         if(encoder->get_verify() != true) {
311                 printf("FAILED, expected true, got false\n");
312                 return false;
313         }
314         printf("OK\n");
315
316         printf("testing get_streamable_subset()... ");
317         if(encoder->get_streamable_subset() != true) {
318                 printf("FAILED, expected true, got false\n");
319                 return false;
320         }
321         printf("OK\n");
322
323         printf("testing get_do_mid_side_stereo()... ");
324         if(encoder->get_do_mid_side_stereo() != false) {
325                 printf("FAILED, expected false, got true\n");
326                 return false;
327         }
328         printf("OK\n");
329
330         printf("testing get_loose_mid_side_stereo()... ");
331         if(encoder->get_loose_mid_side_stereo() != false) {
332                 printf("FAILED, expected false, got true\n");
333                 return false;
334         }
335         printf("OK\n");
336
337         printf("testing get_channels()... ");
338         if(encoder->get_channels() != streaminfo_.data.stream_info.channels) {
339                 printf("FAILED, expected %u, got %u\n", streaminfo_.data.stream_info.channels, encoder->get_channels());
340                 return false;
341         }
342         printf("OK\n");
343
344         printf("testing get_bits_per_sample()... ");
345         if(encoder->get_bits_per_sample() != streaminfo_.data.stream_info.bits_per_sample) {
346                 printf("FAILED, expected %u, got %u\n", streaminfo_.data.stream_info.bits_per_sample, encoder->get_bits_per_sample());
347                 return false;
348         }
349         printf("OK\n");
350
351         printf("testing get_sample_rate()... ");
352         if(encoder->get_sample_rate() != streaminfo_.data.stream_info.sample_rate) {
353                 printf("FAILED, expected %u, got %u\n", streaminfo_.data.stream_info.sample_rate, encoder->get_sample_rate());
354                 return false;
355         }
356         printf("OK\n");
357
358         printf("testing get_blocksize()... ");
359         if(encoder->get_blocksize() != streaminfo_.data.stream_info.min_blocksize) {
360                 printf("FAILED, expected %u, got %u\n", streaminfo_.data.stream_info.min_blocksize, encoder->get_blocksize());
361                 return false;
362         }
363         printf("OK\n");
364
365         printf("testing get_max_lpc_order()... ");
366         if(encoder->get_max_lpc_order() != 0) {
367                 printf("FAILED, expected %u, got %u\n", 0, encoder->get_max_lpc_order());
368                 return false;
369         }
370         printf("OK\n");
371
372         printf("testing get_qlp_coeff_precision()... ");
373         (void)encoder->get_qlp_coeff_precision();
374         /* we asked the encoder to auto select this so we accept anything */
375         printf("OK\n");
376
377         printf("testing get_do_qlp_coeff_prec_search()... ");
378         if(encoder->get_do_qlp_coeff_prec_search() != false) {
379                 printf("FAILED, expected false, got true\n");
380                 return false;
381         }
382         printf("OK\n");
383
384         printf("testing get_do_escape_coding()... ");
385         if(encoder->get_do_escape_coding() != false) {
386                 printf("FAILED, expected false, got true\n");
387                 return false;
388         }
389         printf("OK\n");
390
391         printf("testing get_do_exhaustive_model_search()... ");
392         if(encoder->get_do_exhaustive_model_search() != false) {
393                 printf("FAILED, expected false, got true\n");
394                 return false;
395         }
396         printf("OK\n");
397
398         printf("testing get_min_residual_partition_order()... ");
399         if(encoder->get_min_residual_partition_order() != 0) {
400                 printf("FAILED, expected %u, got %u\n", 0, encoder->get_min_residual_partition_order());
401                 return false;
402         }
403         printf("OK\n");
404
405         printf("testing get_max_residual_partition_order()... ");
406         if(encoder->get_max_residual_partition_order() != 0) {
407                 printf("FAILED, expected %u, got %u\n", 0, encoder->get_max_residual_partition_order());
408                 return false;
409         }
410         printf("OK\n");
411
412         printf("testing get_rice_parameter_search_dist()... ");
413         if(encoder->get_rice_parameter_search_dist() != 0) {
414                 printf("FAILED, expected %u, got %u\n", 0, encoder->get_rice_parameter_search_dist());
415                 return false;
416         }
417         printf("OK\n");
418
419         printf("testing get_total_samples_estimate()... ");
420         if(encoder->get_total_samples_estimate() != streaminfo_.data.stream_info.total_samples) {
421                 printf("FAILED, expected %llu, got %llu\n", streaminfo_.data.stream_info.total_samples, encoder->get_total_samples_estimate());
422                 return false;
423         }
424         printf("OK\n");
425
426         /* init the dummy sample buffer */
427         for(i = 0; i < sizeof(samples) / sizeof(FLAC__int32); i++)
428                 samples[i] = i & 7;
429
430         printf("testing process()... ");
431         if(!encoder->process(samples_array, sizeof(samples) / sizeof(FLAC__int32)))
432                 return encoder->die("returned false");
433         printf("OK\n");
434
435         printf("testing process_interleaved()... ");
436         if(!encoder->process_interleaved(samples, sizeof(samples) / sizeof(FLAC__int32)))
437                 return encoder->die("returned false");
438         printf("OK\n");
439
440         printf("testing finish()... ");
441         encoder->finish();
442         printf("OK\n");
443
444         printf("freeing encoder instance... ");
445         delete encoder;
446         printf("OK\n");
447
448         printf("\nPASSED!\n");
449
450         return true;
451 }
452
453 bool test_encoders()
454 {
455         init_metadata_blocks_();
456
457         if(!test_stream_encoder())
458                 return false;
459
460         free_metadata_blocks_();
461
462         return true;
463 }