blob: f30941c6a5ab651334cad25ce0656357dc5d4891 [file] [log] [blame]
Josh Coalsona86f8702002-08-20 04:03:24 +00001/* test_libOggFLAC++ - Unit tester for libOggFLAC++
2 * Copyright (C) 2002 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"
20extern "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
29static ::FLAC__StreamMetadata streaminfo_, padding_, seektable_, application1_, application2_, vorbiscomment_;
30static ::FLAC__StreamMetadata *metadata_sequence_[] = { &padding_, &seektable_, &application1_, &application2_, &vorbiscomment_ };
31static const unsigned num_metadata_ = 5;
32
33static 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
43static 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 */
Josh Coalson765ff502002-08-27 05:46:11 +000054 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;
Josh Coalsona86f8702002-08-20 04:03:24 +000065 memset(streaminfo_.data.stream_info.md5sum, 0, 16);
66
Josh Coalson765ff502002-08-27 05:46:11 +000067 padding_.is_last = false;
68 padding_.type = ::FLAC__METADATA_TYPE_PADDING;
69 padding_.length = 1234;
Josh Coalsona86f8702002-08-20 04:03:24 +000070
Josh Coalson765ff502002-08-27 05:46:11 +000071 seektable_.is_last = false;
72 seektable_.type = ::FLAC__METADATA_TYPE_SEEKTABLE;
Josh Coalsona86f8702002-08-20 04:03:24 +000073 seektable_.data.seek_table.num_points = 2;
Josh Coalson765ff502002-08-27 05:46:11 +000074 seektable_.length = seektable_.data.seek_table.num_points * FLAC__STREAM_METADATA_SEEKPOINT_LENGTH;
Josh Coalsona86f8702002-08-20 04:03:24 +000075 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
Josh Coalson765ff502002-08-27 05:46:11 +000083 application1_.is_last = false;
84 application1_.type = ::FLAC__METADATA_TYPE_APPLICATION;
85 application1_.length = 8;
Josh Coalsona86f8702002-08-20 04:03:24 +000086 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
Josh Coalson765ff502002-08-27 05:46:11 +000090 application2_.is_last = false;
91 application2_.type = ::FLAC__METADATA_TYPE_APPLICATION;
92 application2_.length = 4;
Josh Coalsona86f8702002-08-20 04:03:24 +000093 memcpy(application2_.data.application.id, "\x76\x54\x32\x10", 4);
94 application2_.data.application.data = 0;
95
Josh Coalson765ff502002-08-27 05:46:11 +000096 vorbiscomment_.is_last = true;
97 vorbiscomment_.type = ::FLAC__METADATA_TYPE_VORBIS_COMMENT;
98 vorbiscomment_.length = (4 + 8) + 4 + (4 + 5) + (4 + 0);
Josh Coalsona86f8702002-08-20 04:03:24 +000099 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
111static 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
120class StreamEncoder : public OggFLAC::Encoder::Stream {
121public:
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
138bool 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
160static 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_verify()... ");
185 if(!encoder->set_verify(true))
186 return encoder->die("returned false");
187 printf("OK\n");
188
189 printf("testing set_streamable_subset()... ");
190 if(!encoder->set_streamable_subset(true))
191 return encoder->die("returned false");
192 printf("OK\n");
193
194 printf("testing set_do_mid_side_stereo()... ");
195 if(!encoder->set_do_mid_side_stereo(false))
196 return encoder->die("returned false");
197 printf("OK\n");
198
199 printf("testing set_loose_mid_side_stereo()... ");
200 if(!encoder->set_loose_mid_side_stereo(false))
201 return encoder->die("returned false");
202 printf("OK\n");
203
204 printf("testing set_channels()... ");
205 if(!encoder->set_channels(streaminfo_.data.stream_info.channels))
206 return encoder->die("returned false");
207 printf("OK\n");
208
209 printf("testing set_bits_per_sample()... ");
210 if(!encoder->set_bits_per_sample(streaminfo_.data.stream_info.bits_per_sample))
211 return encoder->die("returned false");
212 printf("OK\n");
213
214 printf("testing set_sample_rate()... ");
215 if(!encoder->set_sample_rate(streaminfo_.data.stream_info.sample_rate))
216 return encoder->die("returned false");
217 printf("OK\n");
218
219 printf("testing set_blocksize()... ");
220 if(!encoder->set_blocksize(streaminfo_.data.stream_info.min_blocksize))
221 return encoder->die("returned false");
222 printf("OK\n");
223
224 printf("testing set_max_lpc_order()... ");
225 if(!encoder->set_max_lpc_order(0))
226 return encoder->die("returned false");
227 printf("OK\n");
228
229 printf("testing set_qlp_coeff_precision()... ");
230 if(!encoder->set_qlp_coeff_precision(0))
231 return encoder->die("returned false");
232 printf("OK\n");
233
234 printf("testing set_do_qlp_coeff_prec_search()... ");
235 if(!encoder->set_do_qlp_coeff_prec_search(false))
236 return encoder->die("returned false");
237 printf("OK\n");
238
239 printf("testing set_do_escape_coding()... ");
240 if(!encoder->set_do_escape_coding(false))
241 return encoder->die("returned false");
242 printf("OK\n");
243
244 printf("testing set_do_exhaustive_model_search()... ");
245 if(!encoder->set_do_exhaustive_model_search(false))
246 return encoder->die("returned false");
247 printf("OK\n");
248
249 printf("testing set_min_residual_partition_order()... ");
250 if(!encoder->set_min_residual_partition_order(0))
251 return encoder->die("returned false");
252 printf("OK\n");
253
254 printf("testing set_max_residual_partition_order()... ");
255 if(!encoder->set_max_residual_partition_order(0))
256 return encoder->die("returned false");
257 printf("OK\n");
258
259 printf("testing set_rice_parameter_search_dist()... ");
260 if(!encoder->set_rice_parameter_search_dist(0))
261 return encoder->die("returned false");
262 printf("OK\n");
263
264 printf("testing set_total_samples_estimate()... ");
265 if(!encoder->set_total_samples_estimate(streaminfo_.data.stream_info.total_samples))
266 return encoder->die("returned false");
267 printf("OK\n");
268
269 printf("testing set_metadata()... ");
270 if(!encoder->set_metadata(metadata_sequence_, num_metadata_))
271 return encoder->die("returned false");
272 printf("OK\n");
273
274 printf("testing init()... ");
275 if(encoder->init() != ::OggFLAC__STREAM_ENCODER_OK)
276 return encoder->die();
277 printf("OK\n");
278
279 printf("testing get_state()... ");
280 OggFLAC::Encoder::Stream::State state = encoder->get_state();
281 printf("returned state = %u (%s)... OK\n", (unsigned)((::OggFLAC__StreamEncoderState)state), state.as_cstring());
282
283 printf("testing get_FLAC_stream_encoder_state()... ");
284 FLAC::Encoder::Stream::State state_ = encoder->get_FLAC_stream_encoder_state();
285 printf("returned state = %u (%s)... OK\n", (unsigned)((::FLAC__StreamEncoderState)state_), state_.as_cstring());
286
287 printf("testing get_verify_decoder_state()... ");
288 FLAC::Decoder::Stream::State dstate = encoder->get_verify_decoder_state();
289 printf("returned state = %u (%s)... OK\n", (unsigned)((::FLAC__StreamDecoderState)dstate), dstate.as_cstring());
290
291 {
292 FLAC__uint64 absolute_sample;
293 unsigned frame_number;
294 unsigned channel;
295 unsigned sample;
296 FLAC__int32 expected;
297 FLAC__int32 got;
298
299 printf("testing get_verify_decoder_error_stats()... ");
300 encoder->get_verify_decoder_error_stats(&absolute_sample, &frame_number, &channel, &sample, &expected, &got);
301 printf("OK\n");
302 }
303
304 printf("testing get_verify()... ");
305 if(encoder->get_verify() != true) {
306 printf("FAILED, expected true, got false\n");
307 return false;
308 }
309 printf("OK\n");
310
311 printf("testing get_streamable_subset()... ");
312 if(encoder->get_streamable_subset() != true) {
313 printf("FAILED, expected true, got false\n");
314 return false;
315 }
316 printf("OK\n");
317
318 printf("testing get_do_mid_side_stereo()... ");
319 if(encoder->get_do_mid_side_stereo() != false) {
320 printf("FAILED, expected false, got true\n");
321 return false;
322 }
323 printf("OK\n");
324
325 printf("testing get_loose_mid_side_stereo()... ");
326 if(encoder->get_loose_mid_side_stereo() != false) {
327 printf("FAILED, expected false, got true\n");
328 return false;
329 }
330 printf("OK\n");
331
332 printf("testing get_channels()... ");
333 if(encoder->get_channels() != streaminfo_.data.stream_info.channels) {
334 printf("FAILED, expected %u, got %u\n", streaminfo_.data.stream_info.channels, encoder->get_channels());
335 return false;
336 }
337 printf("OK\n");
338
339 printf("testing get_bits_per_sample()... ");
340 if(encoder->get_bits_per_sample() != streaminfo_.data.stream_info.bits_per_sample) {
341 printf("FAILED, expected %u, got %u\n", streaminfo_.data.stream_info.bits_per_sample, encoder->get_bits_per_sample());
342 return false;
343 }
344 printf("OK\n");
345
346 printf("testing get_sample_rate()... ");
347 if(encoder->get_sample_rate() != streaminfo_.data.stream_info.sample_rate) {
348 printf("FAILED, expected %u, got %u\n", streaminfo_.data.stream_info.sample_rate, encoder->get_sample_rate());
349 return false;
350 }
351 printf("OK\n");
352
353 printf("testing get_blocksize()... ");
354 if(encoder->get_blocksize() != streaminfo_.data.stream_info.min_blocksize) {
355 printf("FAILED, expected %u, got %u\n", streaminfo_.data.stream_info.min_blocksize, encoder->get_blocksize());
356 return false;
357 }
358 printf("OK\n");
359
360 printf("testing get_max_lpc_order()... ");
361 if(encoder->get_max_lpc_order() != 0) {
362 printf("FAILED, expected %u, got %u\n", 0, encoder->get_max_lpc_order());
363 return false;
364 }
365 printf("OK\n");
366
367 printf("testing get_qlp_coeff_precision()... ");
368 (void)encoder->get_qlp_coeff_precision();
369 /* we asked the encoder to auto select this so we accept anything */
370 printf("OK\n");
371
372 printf("testing get_do_qlp_coeff_prec_search()... ");
373 if(encoder->get_do_qlp_coeff_prec_search() != false) {
374 printf("FAILED, expected false, got true\n");
375 return false;
376 }
377 printf("OK\n");
378
379 printf("testing get_do_escape_coding()... ");
380 if(encoder->get_do_escape_coding() != false) {
381 printf("FAILED, expected false, got true\n");
382 return false;
383 }
384 printf("OK\n");
385
386 printf("testing get_do_exhaustive_model_search()... ");
387 if(encoder->get_do_exhaustive_model_search() != false) {
388 printf("FAILED, expected false, got true\n");
389 return false;
390 }
391 printf("OK\n");
392
393 printf("testing get_min_residual_partition_order()... ");
394 if(encoder->get_min_residual_partition_order() != 0) {
395 printf("FAILED, expected %u, got %u\n", 0, encoder->get_min_residual_partition_order());
396 return false;
397 }
398 printf("OK\n");
399
400 printf("testing get_max_residual_partition_order()... ");
401 if(encoder->get_max_residual_partition_order() != 0) {
402 printf("FAILED, expected %u, got %u\n", 0, encoder->get_max_residual_partition_order());
403 return false;
404 }
405 printf("OK\n");
406
407 printf("testing get_rice_parameter_search_dist()... ");
408 if(encoder->get_rice_parameter_search_dist() != 0) {
409 printf("FAILED, expected %u, got %u\n", 0, encoder->get_rice_parameter_search_dist());
410 return false;
411 }
412 printf("OK\n");
413
414 printf("testing get_total_samples_estimate()... ");
415 if(encoder->get_total_samples_estimate() != streaminfo_.data.stream_info.total_samples) {
416 printf("FAILED, expected %llu, got %llu\n", streaminfo_.data.stream_info.total_samples, encoder->get_total_samples_estimate());
417 return false;
418 }
419 printf("OK\n");
420
421 /* init the dummy sample buffer */
422 for(i = 0; i < sizeof(samples) / sizeof(FLAC__int32); i++)
423 samples[i] = i & 7;
424
425 printf("testing process()... ");
426 if(!encoder->process(samples_array, sizeof(samples) / sizeof(FLAC__int32)))
427 return encoder->die("returned false");
428 printf("OK\n");
429
430 printf("testing process_interleaved()... ");
431 if(!encoder->process_interleaved(samples, sizeof(samples) / sizeof(FLAC__int32)))
432 return encoder->die("returned false");
433 printf("OK\n");
434
435 printf("testing finish()... ");
436 encoder->finish();
437 printf("OK\n");
438
439 printf("freeing encoder instance... ");
440 delete encoder;
441 printf("OK\n");
442
443 printf("\nPASSED!\n");
444
445 return true;
446}
447
448bool test_encoders()
449{
450 init_metadata_blocks_();
451
452 if(!test_stream_encoder())
453 return false;
454
455 free_metadata_blocks_();
456
457 return true;
458}