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