mirror of
https://github.com/claunia/flac.git
synced 2025-12-16 18:54:26 +00:00
use new file encoder from libFLAC, still needs fixes for Ogg support
This commit is contained in:
@@ -31,7 +31,7 @@
|
||||
#include "encode.h"
|
||||
#include "file.h"
|
||||
#ifdef FLAC__HAS_OGG
|
||||
#include "ogg/ogg.h"
|
||||
#include "OggFLAC/stream_encoder.h"
|
||||
#endif
|
||||
|
||||
#ifdef min
|
||||
@@ -42,44 +42,6 @@
|
||||
/* this MUST be >= 588 so that sector aligning can take place with one read */
|
||||
#define CHUNK_OF_SAMPLES 2048
|
||||
|
||||
typedef enum {
|
||||
FLAC__VERIFY_OK,
|
||||
FLAC__VERIFY_FAILED_IN_FRAME,
|
||||
FLAC__VERIFY_FAILED_IN_METADATA
|
||||
} verify_code;
|
||||
|
||||
static const char *verify_code_string[] = {
|
||||
"FLAC__VERIFY_OK",
|
||||
"FLAC__VERIFY_FAILED_IN_FRAME",
|
||||
"FLAC__VERIFY_FAILED_IN_METADATA"
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
ENCODER_IN_MAGIC = 0,
|
||||
ENCODER_IN_METADATA = 1,
|
||||
ENCODER_IN_AUDIO = 2
|
||||
} EncodeState;
|
||||
|
||||
typedef struct {
|
||||
FLAC__int32 *original[FLAC__MAX_CHANNELS];
|
||||
unsigned size; /* of each original[] in samples */
|
||||
unsigned tail; /* in wide samples */
|
||||
const FLAC__byte *encoded_signal;
|
||||
unsigned encoded_signal_capacity;
|
||||
unsigned encoded_bytes;
|
||||
EncodeState encode_state;
|
||||
FLAC__bool needs_magic_hack;
|
||||
verify_code result;
|
||||
FLAC__StreamDecoder *decoder;
|
||||
} verify_fifo_struct;
|
||||
|
||||
#ifdef FLAC__HAS_OGG
|
||||
typedef struct {
|
||||
ogg_stream_state os;
|
||||
ogg_page og;
|
||||
} ogg_info_struct;
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
const char *inbasefilename;
|
||||
FILE *fout;
|
||||
@@ -93,12 +55,12 @@ typedef struct {
|
||||
FLAC__uint64 samples_written;
|
||||
FLAC__uint64 stream_offset; /* i.e. number of bytes before the first byte of the the first frame's header */
|
||||
unsigned current_frame;
|
||||
verify_fifo_struct verify_fifo;
|
||||
FLAC__StreamMetadata *seek_table;
|
||||
unsigned first_seek_point_to_check;
|
||||
FLAC__bool verify_failed;
|
||||
#ifdef FLAC__HAS_OGG
|
||||
FLAC__bool use_ogg;
|
||||
ogg_info_struct ogg;
|
||||
OggFLAC__StreamEncoder *ogg_encoder;
|
||||
#endif
|
||||
} encoder_wrapper_struct;
|
||||
|
||||
@@ -116,14 +78,9 @@ static FLAC__int32 *input[FLAC__MAX_CHANNELS];
|
||||
static FLAC__bool init(encoder_wrapper_struct *encoder_wrapper);
|
||||
static FLAC__bool init_encoder(encode_options_t options, unsigned channels, unsigned bps, unsigned sample_rate, encoder_wrapper_struct *encoder_wrapper);
|
||||
static FLAC__bool convert_to_seek_table(char *requested_seek_points, int num_requested_seek_points, FLAC__uint64 stream_samples, FLAC__StreamMetadata *seek_table);
|
||||
static void format_input(FLAC__int32 *dest[], unsigned wide_samples, FLAC__bool is_big_endian, FLAC__bool is_unsigned_samples, unsigned channels, unsigned bps, encoder_wrapper_struct *encoder_wrapper);
|
||||
static void append_to_verify_fifo(encoder_wrapper_struct *encoder_wrapper, const FLAC__int32 * const input[], unsigned channels, unsigned wide_samples);
|
||||
static void format_input(FLAC__int32 *dest[], unsigned wide_samples, FLAC__bool is_big_endian, FLAC__bool is_unsigned_samples, unsigned channels, unsigned bps);
|
||||
static FLAC__StreamEncoderWriteStatus write_callback(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data);
|
||||
static void metadata_callback(const FLAC__StreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data);
|
||||
static FLAC__StreamDecoderReadStatus verify_read_callback(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
|
||||
static FLAC__StreamDecoderWriteStatus verify_write_callback(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
|
||||
static void verify_metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
|
||||
static void verify_error_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
|
||||
static void print_stats(const encoder_wrapper_struct *encoder_wrapper);
|
||||
static FLAC__bool read_little_endian_uint16(FILE *f, FLAC__uint16 *val, FLAC__bool eof_ok, const char *fn);
|
||||
static FLAC__bool read_little_endian_uint32(FILE *f, FLAC__uint32 *val, FLAC__bool eof_ok, const char *fn);
|
||||
@@ -157,8 +114,10 @@ flac__encode_aif(FILE *infile, long infilesize, const char *infilename, const ch
|
||||
encoder_wrapper.outfilename = outfilename;
|
||||
encoder_wrapper.seek_table = FLAC__metadata_object_new(FLAC__METADATA_TYPE_SEEKTABLE);
|
||||
encoder_wrapper.first_seek_point_to_check = 0;
|
||||
encoder_wrapper.verify_failed = false;
|
||||
#ifdef FLAC__HAS_OGG
|
||||
encoder_wrapper.use_ogg = options.common.use_ogg;
|
||||
encoder_wrapper.ogg_encoder = 0;
|
||||
#endif
|
||||
|
||||
if(0 == encoder_wrapper.seek_table) {
|
||||
@@ -361,16 +320,14 @@ flac__encode_aif(FILE *infile, long infilesize, const char *infilename, const ch
|
||||
|
||||
if(!init_encoder(options.common, channels, bps, sample_rate, &encoder_wrapper))
|
||||
status= ERROR;
|
||||
else
|
||||
encoder_wrapper.verify_fifo.encode_state = ENCODER_IN_AUDIO;
|
||||
}
|
||||
|
||||
/* first do any samples in the reservoir */
|
||||
if(status==NORMAL && options.common.sector_align && *options.common.align_reservoir_samples>0U) {
|
||||
append_to_verify_fifo(&encoder_wrapper, (const FLAC__int32 *const *)options.common.align_reservoir, channels, *options.common.align_reservoir_samples);
|
||||
|
||||
if(!FLAC__stream_encoder_process(encoder_wrapper.encoder, (const FLAC__int32 *const *)options.common.align_reservoir, *options.common.align_reservoir_samples)) {
|
||||
fprintf(stderr, "%s: ERROR during encoding, state = %d:%s\n", encoder_wrapper.inbasefilename, FLAC__stream_encoder_get_state(encoder_wrapper.encoder), FLAC__StreamEncoderStateString[FLAC__stream_encoder_get_state(encoder_wrapper.encoder)]);
|
||||
encoder_wrapper.verify_failed = (FLAC__stream_encoder_get_state(encoder_wrapper.encoder) == FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA);
|
||||
status= ERROR;
|
||||
}
|
||||
}
|
||||
@@ -406,10 +363,11 @@ flac__encode_aif(FILE *infile, long infilesize, const char *infilename, const ch
|
||||
}
|
||||
else {
|
||||
unsigned int frames= bytes_read/bytes_per_frame;
|
||||
format_input(input, frames, true, false, channels, bps, &encoder_wrapper);
|
||||
format_input(input, frames, true, false, channels, bps);
|
||||
|
||||
if(!FLAC__stream_encoder_process(encoder_wrapper.encoder, (const FLAC__int32 *const *)input, frames)) {
|
||||
fprintf(stderr, "%s: ERROR during encoding, state = %d:%s\n", encoder_wrapper.inbasefilename, FLAC__stream_encoder_get_state(encoder_wrapper.encoder), FLAC__StreamEncoderStateString[FLAC__stream_encoder_get_state(encoder_wrapper.encoder)]);
|
||||
encoder_wrapper.verify_failed = (FLAC__stream_encoder_get_state(encoder_wrapper.encoder) == FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA);
|
||||
status= ERROR;
|
||||
}
|
||||
else
|
||||
@@ -429,10 +387,10 @@ flac__encode_aif(FILE *infile, long infilesize, const char *infilename, const ch
|
||||
info_align_zero= pad_frames;
|
||||
for(i= 0U; i<channels; ++i)
|
||||
memset(input[i], 0, pad_frames*(bps>>3));
|
||||
append_to_verify_fifo(&encoder_wrapper, (const FLAC__int32 *const *)input, channels, pad_frames);
|
||||
|
||||
if(!FLAC__stream_encoder_process(encoder_wrapper.encoder, (const FLAC__int32 *const *)input, pad_frames)) {
|
||||
fprintf(stderr, "%s: ERROR during encoding, state = %d:%s\n", encoder_wrapper.inbasefilename, FLAC__stream_encoder_get_state(encoder_wrapper.encoder), FLAC__StreamEncoderStateString[FLAC__stream_encoder_get_state(encoder_wrapper.encoder)]);
|
||||
encoder_wrapper.verify_failed = (FLAC__stream_encoder_get_state(encoder_wrapper.encoder) == FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA);
|
||||
status= ERROR;
|
||||
}
|
||||
}
|
||||
@@ -450,7 +408,7 @@ flac__encode_aif(FILE *infile, long infilesize, const char *infilename, const ch
|
||||
fprintf(stderr, "%s: WARNING: unexpected EOF; read %u bytes; expected %u samples, got %u samples\n", encoder_wrapper.inbasefilename, (unsigned int)bytes_read, (unsigned int)encoder_wrapper.total_samples_to_encode, (unsigned int)encoder_wrapper.samples_written);
|
||||
else {
|
||||
info_align_carry= *options.common.align_reservoir_samples;
|
||||
format_input(options.common.align_reservoir, *options.common.align_reservoir_samples, true, false, channels, bps, &encoder_wrapper);
|
||||
format_input(options.common.align_reservoir, *options.common.align_reservoir_samples, true, false, channels, bps);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -502,10 +460,6 @@ flac__encode_aif(FILE *infile, long infilesize, const char *infilename, const ch
|
||||
if(encoder_wrapper.encoder) {
|
||||
FLAC__stream_encoder_finish(encoder_wrapper.encoder);
|
||||
FLAC__stream_encoder_delete(encoder_wrapper.encoder);
|
||||
#ifdef FLAC__HAS_OGG
|
||||
if(encoder_wrapper.use_ogg)
|
||||
ogg_stream_clear(&encoder_wrapper.ogg.os);
|
||||
#endif
|
||||
}
|
||||
if(encoder_wrapper.verbose && encoder_wrapper.total_samples_to_encode > 0) {
|
||||
if(status==DONE)
|
||||
@@ -516,10 +470,8 @@ flac__encode_aif(FILE *infile, long infilesize, const char *infilename, const ch
|
||||
if(0 != encoder_wrapper.seek_table)
|
||||
FLAC__metadata_object_delete(encoder_wrapper.seek_table);
|
||||
if(options.common.verify) {
|
||||
FLAC__stream_decoder_finish(encoder_wrapper.verify_fifo.decoder);
|
||||
FLAC__stream_decoder_delete(encoder_wrapper.verify_fifo.decoder);
|
||||
if(encoder_wrapper.verify_fifo.result != FLAC__VERIFY_OK) {
|
||||
fprintf(stderr, "Verify FAILED! (%s) Do not trust %s\n", verify_code_string[encoder_wrapper.verify_fifo.result], outfilename);
|
||||
if(encoder_wrapper.verify_failed) {
|
||||
fprintf(stderr, "Verify FAILED! Do not trust %s\n", outfilename);
|
||||
status= MISMATCH;
|
||||
}
|
||||
}
|
||||
@@ -563,8 +515,10 @@ int flac__encode_wav(FILE *infile, long infilesize, const char *infilename, cons
|
||||
encoder_wrapper.outfilename = outfilename;
|
||||
encoder_wrapper.seek_table = FLAC__metadata_object_new(FLAC__METADATA_TYPE_SEEKTABLE);
|
||||
encoder_wrapper.first_seek_point_to_check = 0;
|
||||
encoder_wrapper.verify_failed = false;
|
||||
#ifdef FLAC__HAS_OGG
|
||||
encoder_wrapper.use_ogg = options.common.use_ogg;
|
||||
encoder_wrapper.ogg_encoder = 0;
|
||||
#endif
|
||||
(void)infilesize;
|
||||
(void)lookahead;
|
||||
@@ -716,16 +670,13 @@ int flac__encode_wav(FILE *infile, long infilesize, const char *infilename, cons
|
||||
if(!init_encoder(options.common, channels, bps, sample_rate, &encoder_wrapper))
|
||||
goto wav_abort_;
|
||||
|
||||
encoder_wrapper.verify_fifo.encode_state = ENCODER_IN_AUDIO;
|
||||
|
||||
/*
|
||||
* first do any samples in the reservoir
|
||||
*/
|
||||
if(options.common.sector_align && *options.common.align_reservoir_samples > 0) {
|
||||
append_to_verify_fifo(&encoder_wrapper, (const FLAC__int32 * const *)options.common.align_reservoir, channels, *options.common.align_reservoir_samples);
|
||||
|
||||
if(!FLAC__stream_encoder_process(encoder_wrapper.encoder, (const FLAC__int32 * const *)options.common.align_reservoir, *options.common.align_reservoir_samples)) {
|
||||
fprintf(stderr, "%s: ERROR during encoding, state = %d:%s\n", encoder_wrapper.inbasefilename, FLAC__stream_encoder_get_state(encoder_wrapper.encoder), FLAC__StreamEncoderStateString[FLAC__stream_encoder_get_state(encoder_wrapper.encoder)]);
|
||||
encoder_wrapper.verify_failed = (FLAC__stream_encoder_get_state(encoder_wrapper.encoder) == FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA);
|
||||
goto wav_abort_;
|
||||
}
|
||||
}
|
||||
@@ -765,10 +716,11 @@ int flac__encode_wav(FILE *infile, long infilesize, const char *infilename, cons
|
||||
}
|
||||
else {
|
||||
unsigned wide_samples = bytes_read / bytes_per_wide_sample;
|
||||
format_input(input, wide_samples, false, is_unsigned_samples, channels, bps, &encoder_wrapper);
|
||||
format_input(input, wide_samples, false, is_unsigned_samples, channels, bps);
|
||||
|
||||
if(!FLAC__stream_encoder_process(encoder_wrapper.encoder, (const FLAC__int32 * const *)input, wide_samples)) {
|
||||
fprintf(stderr, "%s: ERROR during encoding, state = %d:%s\n", encoder_wrapper.inbasefilename, FLAC__stream_encoder_get_state(encoder_wrapper.encoder), FLAC__StreamEncoderStateString[FLAC__stream_encoder_get_state(encoder_wrapper.encoder)]);
|
||||
encoder_wrapper.verify_failed = (FLAC__stream_encoder_get_state(encoder_wrapper.encoder) == FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA);
|
||||
goto wav_abort_;
|
||||
}
|
||||
data_bytes -= bytes_read;
|
||||
@@ -789,10 +741,10 @@ int flac__encode_wav(FILE *infile, long infilesize, const char *infilename, cons
|
||||
data_bytes = wide_samples * (bps >> 3);
|
||||
for(channel = 0; channel < channels; channel++)
|
||||
memset(input[channel], 0, data_bytes);
|
||||
append_to_verify_fifo(&encoder_wrapper, (const FLAC__int32 * const *)input, channels, wide_samples);
|
||||
|
||||
if(!FLAC__stream_encoder_process(encoder_wrapper.encoder, (const FLAC__int32 * const *)input, wide_samples)) {
|
||||
fprintf(stderr, "%s: ERROR during encoding, state = %d:%s\n", encoder_wrapper.inbasefilename, FLAC__stream_encoder_get_state(encoder_wrapper.encoder), FLAC__StreamEncoderStateString[FLAC__stream_encoder_get_state(encoder_wrapper.encoder)]);
|
||||
encoder_wrapper.verify_failed = (FLAC__stream_encoder_get_state(encoder_wrapper.encoder) == FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA);
|
||||
goto wav_abort_;
|
||||
}
|
||||
}
|
||||
@@ -811,7 +763,7 @@ int flac__encode_wav(FILE *infile, long infilesize, const char *infilename, cons
|
||||
}
|
||||
else {
|
||||
info_align_carry = *options.common.align_reservoir_samples;
|
||||
format_input(options.common.align_reservoir, *options.common.align_reservoir_samples, false, is_unsigned_samples, channels, bps, &encoder_wrapper);
|
||||
format_input(options.common.align_reservoir, *options.common.align_reservoir_samples, false, is_unsigned_samples, channels, bps);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -860,10 +812,6 @@ int flac__encode_wav(FILE *infile, long infilesize, const char *infilename, cons
|
||||
if(encoder_wrapper.encoder) {
|
||||
FLAC__stream_encoder_finish(encoder_wrapper.encoder);
|
||||
FLAC__stream_encoder_delete(encoder_wrapper.encoder);
|
||||
#ifdef FLAC__HAS_OGG
|
||||
if(encoder_wrapper.use_ogg)
|
||||
ogg_stream_clear(&encoder_wrapper.ogg.os);
|
||||
#endif
|
||||
}
|
||||
if(encoder_wrapper.verbose && encoder_wrapper.total_samples_to_encode > 0) {
|
||||
print_stats(&encoder_wrapper);
|
||||
@@ -872,10 +820,8 @@ int flac__encode_wav(FILE *infile, long infilesize, const char *infilename, cons
|
||||
if(0 != encoder_wrapper.seek_table)
|
||||
FLAC__metadata_object_delete(encoder_wrapper.seek_table);
|
||||
if(options.common.verify) {
|
||||
FLAC__stream_decoder_finish(encoder_wrapper.verify_fifo.decoder);
|
||||
FLAC__stream_decoder_delete(encoder_wrapper.verify_fifo.decoder);
|
||||
if(encoder_wrapper.verify_fifo.result != FLAC__VERIFY_OK) {
|
||||
fprintf(stderr, "Verify FAILED! (%s) Do not trust %s\n", verify_code_string[encoder_wrapper.verify_fifo.result], outfilename);
|
||||
if(encoder_wrapper.verify_failed) {
|
||||
fprintf(stderr, "Verify FAILED! Do not trust %s\n", outfilename);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -892,18 +838,12 @@ wav_abort_:
|
||||
if(encoder_wrapper.encoder) {
|
||||
FLAC__stream_encoder_finish(encoder_wrapper.encoder);
|
||||
FLAC__stream_encoder_delete(encoder_wrapper.encoder);
|
||||
#ifdef FLAC__HAS_OGG
|
||||
if(encoder_wrapper.use_ogg)
|
||||
ogg_stream_clear(&encoder_wrapper.ogg.os);
|
||||
#endif
|
||||
}
|
||||
if(0 != encoder_wrapper.seek_table)
|
||||
FLAC__metadata_object_delete(encoder_wrapper.seek_table);
|
||||
if(options.common.verify) {
|
||||
FLAC__stream_decoder_finish(encoder_wrapper.verify_fifo.decoder);
|
||||
FLAC__stream_decoder_delete(encoder_wrapper.verify_fifo.decoder);
|
||||
if(encoder_wrapper.verify_fifo.result != FLAC__VERIFY_OK) {
|
||||
fprintf(stderr, "Verify FAILED! (%s) Do not trust %s\n", verify_code_string[encoder_wrapper.verify_fifo.result], outfilename);
|
||||
if(encoder_wrapper.verify_failed) {
|
||||
fprintf(stderr, "Verify FAILED! Do not trust %s\n", outfilename);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -937,8 +877,10 @@ int flac__encode_raw(FILE *infile, long infilesize, const char *infilename, cons
|
||||
encoder_wrapper.outfilename = outfilename;
|
||||
encoder_wrapper.seek_table = FLAC__metadata_object_new(FLAC__METADATA_TYPE_SEEKTABLE);
|
||||
encoder_wrapper.first_seek_point_to_check = 0;
|
||||
encoder_wrapper.verify_failed = false;
|
||||
#ifdef FLAC__HAS_OGG
|
||||
encoder_wrapper.use_ogg = options.common.use_ogg;
|
||||
encoder_wrapper.ogg_encoder = 0;
|
||||
#endif
|
||||
|
||||
if(0 == encoder_wrapper.seek_table) {
|
||||
@@ -1013,16 +955,13 @@ int flac__encode_raw(FILE *infile, long infilesize, const char *infilename, cons
|
||||
if(!init_encoder(options.common, options.channels, options.bps, options.sample_rate, &encoder_wrapper))
|
||||
goto raw_abort_;
|
||||
|
||||
encoder_wrapper.verify_fifo.encode_state = ENCODER_IN_AUDIO;
|
||||
|
||||
/*
|
||||
* first do any samples in the reservoir
|
||||
*/
|
||||
if(options.common.sector_align && *options.common.align_reservoir_samples > 0) {
|
||||
append_to_verify_fifo(&encoder_wrapper, (const FLAC__int32 * const *)options.common.align_reservoir, options.channels, *options.common.align_reservoir_samples);
|
||||
|
||||
if(!FLAC__stream_encoder_process(encoder_wrapper.encoder, (const FLAC__int32 * const *)options.common.align_reservoir, *options.common.align_reservoir_samples)) {
|
||||
fprintf(stderr, "%s: ERROR during encoding, state = %d:%s\n", encoder_wrapper.inbasefilename, FLAC__stream_encoder_get_state(encoder_wrapper.encoder), FLAC__StreamEncoderStateString[FLAC__stream_encoder_get_state(encoder_wrapper.encoder)]);
|
||||
encoder_wrapper.verify_failed = (FLAC__stream_encoder_get_state(encoder_wrapper.encoder) == FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA);
|
||||
goto raw_abort_;
|
||||
}
|
||||
}
|
||||
@@ -1070,10 +1009,11 @@ int flac__encode_raw(FILE *infile, long infilesize, const char *infilename, cons
|
||||
}
|
||||
else {
|
||||
unsigned wide_samples = bytes_read / bytes_per_wide_sample;
|
||||
format_input(input, wide_samples, options.is_big_endian, options.is_unsigned_samples, options.channels, options.bps, &encoder_wrapper);
|
||||
format_input(input, wide_samples, options.is_big_endian, options.is_unsigned_samples, options.channels, options.bps);
|
||||
|
||||
if(!FLAC__stream_encoder_process(encoder_wrapper.encoder, (const FLAC__int32 * const *)input, wide_samples)) {
|
||||
fprintf(stderr, "%s: ERROR during encoding, state = %d:%s\n", encoder_wrapper.inbasefilename, FLAC__stream_encoder_get_state(encoder_wrapper.encoder), FLAC__StreamEncoderStateString[FLAC__stream_encoder_get_state(encoder_wrapper.encoder)]);
|
||||
encoder_wrapper.verify_failed = (FLAC__stream_encoder_get_state(encoder_wrapper.encoder) == FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA);
|
||||
goto raw_abort_;
|
||||
}
|
||||
}
|
||||
@@ -1092,10 +1032,10 @@ int flac__encode_raw(FILE *infile, long infilesize, const char *infilename, cons
|
||||
data_bytes = wide_samples * (options.bps >> 3);
|
||||
for(channel = 0; channel < options.channels; channel++)
|
||||
memset(input[channel], 0, data_bytes);
|
||||
append_to_verify_fifo(&encoder_wrapper, (const FLAC__int32 * const *)input, options.channels, wide_samples);
|
||||
|
||||
if(!FLAC__stream_encoder_process(encoder_wrapper.encoder, (const FLAC__int32 * const *)input, wide_samples)) {
|
||||
fprintf(stderr, "%s: ERROR during encoding, state = %d:%s\n", encoder_wrapper.inbasefilename, FLAC__stream_encoder_get_state(encoder_wrapper.encoder), FLAC__StreamEncoderStateString[FLAC__stream_encoder_get_state(encoder_wrapper.encoder)]);
|
||||
encoder_wrapper.verify_failed = (FLAC__stream_encoder_get_state(encoder_wrapper.encoder) == FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA);
|
||||
goto raw_abort_;
|
||||
}
|
||||
}
|
||||
@@ -1113,7 +1053,7 @@ int flac__encode_raw(FILE *infile, long infilesize, const char *infilename, cons
|
||||
}
|
||||
else {
|
||||
info_align_carry = *options.common.align_reservoir_samples;
|
||||
format_input(options.common.align_reservoir, *options.common.align_reservoir_samples, false, options.is_unsigned_samples, options.channels, options.bps, &encoder_wrapper);
|
||||
format_input(options.common.align_reservoir, *options.common.align_reservoir_samples, false, options.is_unsigned_samples, options.channels, options.bps);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1122,10 +1062,6 @@ int flac__encode_raw(FILE *infile, long infilesize, const char *infilename, cons
|
||||
if(encoder_wrapper.encoder) {
|
||||
FLAC__stream_encoder_finish(encoder_wrapper.encoder);
|
||||
FLAC__stream_encoder_delete(encoder_wrapper.encoder);
|
||||
#ifdef FLAC__HAS_OGG
|
||||
if(encoder_wrapper.use_ogg)
|
||||
ogg_stream_clear(&encoder_wrapper.ogg.os);
|
||||
#endif
|
||||
}
|
||||
if(encoder_wrapper.verbose && encoder_wrapper.total_samples_to_encode > 0) {
|
||||
print_stats(&encoder_wrapper);
|
||||
@@ -1134,10 +1070,8 @@ int flac__encode_raw(FILE *infile, long infilesize, const char *infilename, cons
|
||||
if(0 != encoder_wrapper.seek_table)
|
||||
FLAC__metadata_object_delete(encoder_wrapper.seek_table);
|
||||
if(options.common.verify) {
|
||||
FLAC__stream_decoder_finish(encoder_wrapper.verify_fifo.decoder);
|
||||
FLAC__stream_decoder_delete(encoder_wrapper.verify_fifo.decoder);
|
||||
if(encoder_wrapper.verify_fifo.result != FLAC__VERIFY_OK) {
|
||||
fprintf(stderr, "Verify FAILED! (%s) Do not trust %s\n", verify_code_string[encoder_wrapper.verify_fifo.result], outfilename);
|
||||
if(encoder_wrapper.verify_failed) {
|
||||
fprintf(stderr, "Verify FAILED! Do not trust %s\n", outfilename);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -1154,18 +1088,12 @@ raw_abort_:
|
||||
if(encoder_wrapper.encoder) {
|
||||
FLAC__stream_encoder_finish(encoder_wrapper.encoder);
|
||||
FLAC__stream_encoder_delete(encoder_wrapper.encoder);
|
||||
#ifdef FLAC__HAS_OGG
|
||||
if(encoder_wrapper.use_ogg)
|
||||
ogg_stream_clear(&encoder_wrapper.ogg.os);
|
||||
#endif
|
||||
}
|
||||
if(0 != encoder_wrapper.seek_table)
|
||||
FLAC__metadata_object_delete(encoder_wrapper.seek_table);
|
||||
if(options.common.verify) {
|
||||
FLAC__stream_decoder_finish(encoder_wrapper.verify_fifo.decoder);
|
||||
FLAC__stream_decoder_delete(encoder_wrapper.verify_fifo.decoder);
|
||||
if(encoder_wrapper.verify_fifo.result != FLAC__VERIFY_OK) {
|
||||
fprintf(stderr, "Verify FAILED! (%s) Do not trust %s\n", verify_code_string[encoder_wrapper.verify_fifo.result], outfilename);
|
||||
if(encoder_wrapper.verify_failed) {
|
||||
fprintf(stderr, "Verify FAILED! Do not trust %s\n", outfilename);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -1191,58 +1119,18 @@ FLAC__bool init(encoder_wrapper_struct *encoder_wrapper)
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef FLAC__HAS_OGG
|
||||
if(encoder_wrapper->use_ogg) {
|
||||
if(ogg_stream_init(&encoder_wrapper->ogg.os, 0) != 0) {
|
||||
fprintf(stderr, "%s: ERROR initializing the Ogg stream\n", encoder_wrapper->inbasefilename);
|
||||
FLAC__stream_encoder_delete(encoder_wrapper->encoder);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
FLAC__bool init_encoder(encode_options_t options, unsigned channels, unsigned bps, unsigned sample_rate, encoder_wrapper_struct *encoder_wrapper)
|
||||
{
|
||||
unsigned i, num_metadata;
|
||||
unsigned num_metadata;
|
||||
FLAC__StreamMetadata padding;
|
||||
FLAC__StreamMetadata *metadata[2];
|
||||
|
||||
if(channels != 2)
|
||||
options.do_mid_side = options.loose_mid_side = false;
|
||||
|
||||
if(encoder_wrapper->verify) {
|
||||
/* set up the fifo which will hold the original signal to compare against */
|
||||
encoder_wrapper->verify_fifo.size = options.blocksize + CHUNK_OF_SAMPLES;
|
||||
for(i = 0; i < channels; i++) {
|
||||
if(0 == (encoder_wrapper->verify_fifo.original[i] = (FLAC__int32*)malloc(sizeof(FLAC__int32) * encoder_wrapper->verify_fifo.size))) {
|
||||
fprintf(stderr, "%s: ERROR allocating verify buffers\n", encoder_wrapper->inbasefilename);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
encoder_wrapper->verify_fifo.tail = 0;
|
||||
encoder_wrapper->verify_fifo.encode_state = ENCODER_IN_MAGIC;
|
||||
encoder_wrapper->verify_fifo.result = FLAC__VERIFY_OK;
|
||||
|
||||
/* set up a stream decoder for verification */
|
||||
encoder_wrapper->verify_fifo.decoder = FLAC__stream_decoder_new();
|
||||
if(0 == encoder_wrapper->verify_fifo.decoder) {
|
||||
fprintf(stderr, "%s: ERROR creating the verify decoder instance\n", encoder_wrapper->inbasefilename);
|
||||
return false;
|
||||
}
|
||||
FLAC__stream_decoder_set_read_callback(encoder_wrapper->verify_fifo.decoder, verify_read_callback);
|
||||
FLAC__stream_decoder_set_write_callback(encoder_wrapper->verify_fifo.decoder, verify_write_callback);
|
||||
FLAC__stream_decoder_set_metadata_callback(encoder_wrapper->verify_fifo.decoder, verify_metadata_callback);
|
||||
FLAC__stream_decoder_set_error_callback(encoder_wrapper->verify_fifo.decoder, verify_error_callback);
|
||||
FLAC__stream_decoder_set_client_data(encoder_wrapper->verify_fifo.decoder, encoder_wrapper);
|
||||
if(FLAC__stream_decoder_init(encoder_wrapper->verify_fifo.decoder) != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA) {
|
||||
fprintf(stderr, "%s: ERROR initializing decoder, state = %d:%s\n", encoder_wrapper->inbasefilename, FLAC__stream_decoder_get_state(encoder_wrapper->verify_fifo.decoder), FLAC__StreamDecoderStateString[FLAC__stream_decoder_get_state(encoder_wrapper->verify_fifo.decoder)]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(!convert_to_seek_table(options.requested_seek_points, options.num_requested_seek_points, encoder_wrapper->total_samples_to_encode, encoder_wrapper->seek_table)) {
|
||||
fprintf(stderr, "%s: ERROR allocating memory for seek table\n", encoder_wrapper->inbasefilename);
|
||||
return false;
|
||||
@@ -1260,6 +1148,7 @@ FLAC__bool init_encoder(encode_options_t options, unsigned channels, unsigned bp
|
||||
metadata[num_metadata++] = &padding;
|
||||
}
|
||||
|
||||
FLAC__stream_encoder_set_verify(encoder_wrapper->encoder, options.verify);
|
||||
FLAC__stream_encoder_set_streamable_subset(encoder_wrapper->encoder, !options.lax);
|
||||
FLAC__stream_encoder_set_do_mid_side_stereo(encoder_wrapper->encoder, options.do_mid_side);
|
||||
FLAC__stream_encoder_set_loose_mid_side_stereo(encoder_wrapper->encoder, options.loose_mid_side);
|
||||
@@ -1283,6 +1172,7 @@ FLAC__bool init_encoder(encode_options_t options, unsigned channels, unsigned bp
|
||||
|
||||
if(FLAC__stream_encoder_init(encoder_wrapper->encoder) != FLAC__STREAM_ENCODER_OK) {
|
||||
fprintf(stderr, "%s: ERROR initializing encoder, state = %d:%s\n", encoder_wrapper->inbasefilename, FLAC__stream_encoder_get_state(encoder_wrapper->encoder), FLAC__StreamEncoderStateString[FLAC__stream_encoder_get_state(encoder_wrapper->encoder)]);
|
||||
encoder_wrapper->verify_failed = (FLAC__stream_encoder_get_state(encoder_wrapper->encoder) == FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1358,7 +1248,7 @@ FLAC__bool convert_to_seek_table(char *requested_seek_points, int num_requested_
|
||||
return true;
|
||||
}
|
||||
|
||||
void format_input(FLAC__int32 *dest[], unsigned wide_samples, FLAC__bool is_big_endian, FLAC__bool is_unsigned_samples, unsigned channels, unsigned bps, encoder_wrapper_struct *encoder_wrapper)
|
||||
void format_input(FLAC__int32 *dest[], unsigned wide_samples, FLAC__bool is_big_endian, FLAC__bool is_unsigned_samples, unsigned channels, unsigned bps)
|
||||
{
|
||||
unsigned wide_sample, sample, channel, byte;
|
||||
|
||||
@@ -1426,19 +1316,6 @@ void format_input(FLAC__int32 *dest[], unsigned wide_samples, FLAC__bool is_big_
|
||||
else {
|
||||
FLAC__ASSERT(0);
|
||||
}
|
||||
|
||||
append_to_verify_fifo(encoder_wrapper, (const FLAC__int32 * const *)dest, channels, wide_samples);
|
||||
}
|
||||
|
||||
void append_to_verify_fifo(encoder_wrapper_struct *encoder_wrapper, const FLAC__int32 * const input[], unsigned channels, unsigned wide_samples)
|
||||
{
|
||||
if(encoder_wrapper->verify) {
|
||||
unsigned channel;
|
||||
for(channel = 0; channel < channels; channel++)
|
||||
memcpy(&encoder_wrapper->verify_fifo.original[channel][encoder_wrapper->verify_fifo.tail], input[channel], sizeof(FLAC__int32) * wide_samples);
|
||||
encoder_wrapper->verify_fifo.tail += wide_samples;
|
||||
FLAC__ASSERT(encoder_wrapper->verify_fifo.tail <= encoder_wrapper->verify_fifo.size);
|
||||
}
|
||||
}
|
||||
|
||||
FLAC__StreamEncoderWriteStatus write_callback(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data)
|
||||
@@ -1484,66 +1361,10 @@ FLAC__StreamEncoderWriteStatus write_callback(const FLAC__StreamEncoder *encoder
|
||||
if(samples && encoder_wrapper->verbose && encoder_wrapper->total_samples_to_encode > 0 && !(current_frame & mask))
|
||||
print_stats(encoder_wrapper);
|
||||
|
||||
if(encoder_wrapper->verify) {
|
||||
encoder_wrapper->verify_fifo.encoded_signal = buffer;
|
||||
encoder_wrapper->verify_fifo.encoded_bytes = bytes;
|
||||
if(encoder_wrapper->verify_fifo.encode_state > ENCODER_IN_MAGIC) {
|
||||
if(!FLAC__stream_decoder_process_single(encoder_wrapper->verify_fifo.decoder)) {
|
||||
encoder_wrapper->verify_fifo.result = encoder_wrapper->verify_fifo.encode_state > ENCODER_IN_METADATA? FLAC__VERIFY_FAILED_IN_FRAME : FLAC__VERIFY_FAILED_IN_METADATA;
|
||||
|
||||
return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
|
||||
}
|
||||
}
|
||||
else {
|
||||
encoder_wrapper->verify_fifo.encode_state = ENCODER_IN_METADATA;
|
||||
encoder_wrapper->verify_fifo.needs_magic_hack = true;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef FLAC__HAS_OGG
|
||||
if(encoder_wrapper->use_ogg) {
|
||||
ogg_packet op;
|
||||
|
||||
memset(&op, 0, sizeof(op));
|
||||
op.packet = (unsigned char *)buffer;
|
||||
op.granulepos = encoder_wrapper->samples_written - 1;
|
||||
/*@@@ WATCHOUT:
|
||||
* this depends on the behavior of libFLAC that we will get one
|
||||
* write_callback first with all the metadata (and 'samples'
|
||||
* will be 0), then one write_callback for each frame.
|
||||
*/
|
||||
op.packetno = (samples == 0? -1 : (int)encoder_wrapper->current_frame);
|
||||
op.bytes = bytes;
|
||||
|
||||
if (encoder_wrapper->bytes_written == bytes)
|
||||
op.b_o_s = 1;
|
||||
|
||||
if (encoder_wrapper->total_samples_to_encode == encoder_wrapper->samples_written)
|
||||
op.e_o_s = 1;
|
||||
|
||||
ogg_stream_packetin(&encoder_wrapper->ogg.os, &op);
|
||||
|
||||
while(ogg_stream_pageout(&encoder_wrapper->ogg.os, &encoder_wrapper->ogg.og) != 0) {
|
||||
int written;
|
||||
written = fwrite(encoder_wrapper->ogg.og.header, 1, encoder_wrapper->ogg.og.header_len, encoder_wrapper->fout);
|
||||
if (written != encoder_wrapper->ogg.og.header_len)
|
||||
return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
|
||||
|
||||
written = fwrite(encoder_wrapper->ogg.og.body, 1, encoder_wrapper->ogg.og.body_len, encoder_wrapper->fout);
|
||||
if (written != encoder_wrapper->ogg.og.body_len)
|
||||
return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
|
||||
}
|
||||
|
||||
if(fwrite(buffer, sizeof(FLAC__byte), bytes, encoder_wrapper->fout) == bytes)
|
||||
return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if(fwrite(buffer, sizeof(FLAC__byte), bytes, encoder_wrapper->fout) == bytes)
|
||||
return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
|
||||
else
|
||||
return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
|
||||
}
|
||||
return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
|
||||
}
|
||||
|
||||
void metadata_callback(const FLAC__StreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data)
|
||||
@@ -1656,83 +1477,18 @@ end_:
|
||||
return;
|
||||
}
|
||||
|
||||
FLAC__StreamDecoderReadStatus verify_read_callback(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
|
||||
{
|
||||
encoder_wrapper_struct *encoder_wrapper = (encoder_wrapper_struct *)client_data;
|
||||
const unsigned encoded_bytes = encoder_wrapper->verify_fifo.encoded_bytes;
|
||||
(void)decoder;
|
||||
|
||||
if(encoder_wrapper->verify_fifo.needs_magic_hack) {
|
||||
FLAC__ASSERT(*bytes >= FLAC__STREAM_SYNC_LENGTH);
|
||||
*bytes = FLAC__STREAM_SYNC_LENGTH;
|
||||
memcpy(buffer, FLAC__STREAM_SYNC_STRING, *bytes);
|
||||
encoder_wrapper->verify_fifo.needs_magic_hack = false;
|
||||
}
|
||||
else {
|
||||
//@@@ if(encoded_bytes == 0)? need some check for underflow so we don't deadlock
|
||||
if(encoded_bytes < *bytes)
|
||||
*bytes = encoded_bytes;
|
||||
memcpy(buffer, encoder_wrapper->verify_fifo.encoded_signal, *bytes);
|
||||
encoder_wrapper->verify_fifo.encoded_signal += *bytes;
|
||||
encoder_wrapper->verify_fifo.encoded_bytes -= *bytes;
|
||||
}
|
||||
|
||||
return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
|
||||
}
|
||||
|
||||
#if 0
|
||||
FLAC__StreamDecoderWriteStatus verify_write_callback(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
|
||||
{
|
||||
encoder_wrapper_struct *encoder_wrapper = (encoder_wrapper_struct *)client_data;
|
||||
unsigned channel, l, r;
|
||||
const unsigned channels = FLAC__stream_decoder_get_channels(decoder);
|
||||
const unsigned bytes_per_block = sizeof(FLAC__int32) * FLAC__stream_decoder_get_blocksize(decoder);
|
||||
|
||||
for(channel = 0; channel < channels; channel++) {
|
||||
if(0 != memcmp(buffer[channel], encoder_wrapper->verify_fifo.original[channel], bytes_per_block)) {
|
||||
unsigned sample = 0;
|
||||
int expect = 0, got = 0;
|
||||
fprintf(stderr, "\n%s: ERROR: mismatch in decoded data, verify FAILED!\n", encoder_wrapper->inbasefilename);
|
||||
fprintf(stderr, " Please submit a bug report to\n");
|
||||
fprintf(stderr, " http://sourceforge.net/bugs/?func=addbug&group_id=13478\n");
|
||||
fprintf(stderr, " Make sure to include an email contact in the comment and/or use the\n");
|
||||
fprintf(stderr, " \"Monitor\" feature to monitor the bug status.\n");
|
||||
for(l = 0, r = FLAC__stream_decoder_get_blocksize(decoder); l < r; l++) {
|
||||
if(buffer[channel][l] != encoder_wrapper->verify_fifo.original[channel][l]) {
|
||||
sample = l;
|
||||
expect = (int)encoder_wrapper->verify_fifo.original[channel][l];
|
||||
got = (int)buffer[channel][l];
|
||||
break;
|
||||
}
|
||||
}
|
||||
FLAC__ASSERT(l < r);
|
||||
FLAC__ASSERT(frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER);
|
||||
fprintf(stderr, " Absolute sample=%u, frame=%u, channel=%u, sample=%u, expected %d, got %d\n", (unsigned)frame->header.number.sample_number + sample, (unsigned)frame->header.number.sample_number / FLAC__stream_decoder_get_blocksize(decoder), channel, sample, expect, got); /*@@@ WATCHOUT: 4GB limit */
|
||||
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
|
||||
}
|
||||
}
|
||||
/* dequeue the frame from the fifo */
|
||||
for(channel = 0; channel < channels; channel++) {
|
||||
for(l = 0, r = frame->header.blocksize; r < encoder_wrapper->verify_fifo.tail; l++, r++) {
|
||||
encoder_wrapper->verify_fifo.original[channel][l] = encoder_wrapper->verify_fifo.original[channel][r];
|
||||
}
|
||||
}
|
||||
encoder_wrapper->verify_fifo.tail -= frame->header.blocksize;
|
||||
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
|
||||
}
|
||||
|
||||
void verify_metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
|
||||
{
|
||||
(void)decoder;
|
||||
(void)metadata;
|
||||
(void)client_data;
|
||||
}
|
||||
|
||||
void verify_error_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
|
||||
{
|
||||
encoder_wrapper_struct *encoder_wrapper = (encoder_wrapper_struct *)client_data;
|
||||
(void)decoder;
|
||||
fprintf(stderr, "\n%s: ERROR: verification decoder returned error %d:%s\n", encoder_wrapper->inbasefilename, status, FLAC__StreamDecoderErrorStatusString[status]);
|
||||
fprintf(stderr, " Absolute sample=%u, frame=%u, channel=%u, sample=%u, expected %d, got %d\n", (unsigned)frame->header.number.sample_number + sample, (unsigned)frame->header.number.sample_number / FLAC__stream_decoder_get_blocksize(decoder), channel, sample, expect, got);
|
||||
}
|
||||
#endif
|
||||
|
||||
void print_stats(const encoder_wrapper_struct *encoder_wrapper)
|
||||
{
|
||||
@@ -1748,7 +1504,7 @@ void print_stats(const encoder_wrapper_struct *encoder_wrapper)
|
||||
if(encoder_wrapper->samples_written == encoder_wrapper->total_samples_to_encode) {
|
||||
fprintf(stderr, "\r%s:%s wrote %u bytes, ratio=%0.3f",
|
||||
encoder_wrapper->inbasefilename,
|
||||
encoder_wrapper->verify? (encoder_wrapper->verify_fifo.result == FLAC__VERIFY_OK? " Verify OK," : " Verify FAILED!") : "",
|
||||
encoder_wrapper->verify? (encoder_wrapper->verify_failed? " Verify FAILED!" : " Verify OK,") : "",
|
||||
(unsigned)encoder_wrapper->bytes_written,
|
||||
ratio
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user