From: Josh Coalson Date: Sat, 3 Aug 2002 21:56:15 +0000 (+0000) Subject: add verify mode to all encoders X-Git-Tag: 1.2.0~1701 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=d86e03bc63b19a32ac982787c6a585f4e36c55a4;p=platform%2Fupstream%2Fflac.git add verify mode to all encoders --- diff --git a/include/FLAC++/encoder.h b/include/FLAC++/encoder.h index c5e1709..4db20ee 100644 --- a/include/FLAC++/encoder.h +++ b/include/FLAC++/encoder.h @@ -23,6 +23,7 @@ #include "FLAC/file_encoder.h" #include "FLAC/seekable_stream_encoder.h" #include "FLAC/stream_encoder.h" +#include "decoder.h" // =============================================================== // @@ -97,6 +98,7 @@ namespace FLAC { bool is_valid() const; inline operator bool() const { return is_valid(); } + bool set_verify(bool value); bool set_streamable_subset(bool value); bool set_do_mid_side_stereo(bool value); bool set_loose_mid_side_stereo(bool value); @@ -116,6 +118,8 @@ namespace FLAC { bool set_metadata(::FLAC__StreamMetadata **metadata, unsigned num_blocks); State get_state() const; + Decoder::Stream::State get_verify_decoder_state() const; + bool get_verify() const; bool get_streamable_subset() const; bool get_do_mid_side_stereo() const; bool get_loose_mid_side_stereo() const; @@ -187,6 +191,7 @@ namespace FLAC { bool is_valid() const; inline operator bool() const { return is_valid(); } + bool set_verify(bool value); bool set_streamable_subset(bool value); bool set_do_mid_side_stereo(bool value); bool set_loose_mid_side_stereo(bool value); @@ -207,6 +212,8 @@ namespace FLAC { State get_state() const; Stream::State get_stream_encoder_state() const; + Decoder::Stream::State get_verify_decoder_state() const; + bool get_verify() const; bool get_streamable_subset() const; bool get_do_mid_side_stereo() const; bool get_loose_mid_side_stereo() const; @@ -278,6 +285,7 @@ namespace FLAC { bool is_valid() const; inline operator bool() const { return is_valid(); } + bool set_verify(bool value); bool set_streamable_subset(bool value); bool set_do_mid_side_stereo(bool value); bool set_loose_mid_side_stereo(bool value); @@ -300,6 +308,8 @@ namespace FLAC { State get_state() const; SeekableStream::State get_seekable_stream_encoder_state() const; Stream::State get_stream_encoder_state() const; + Decoder::Stream::State get_verify_decoder_state() const; + bool get_verify() const; bool get_streamable_subset() const; bool get_do_mid_side_stereo() const; bool get_loose_mid_side_stereo() const; diff --git a/include/FLAC/file_encoder.h b/include/FLAC/file_encoder.h index bf43114..20aa322 100644 --- a/include/FLAC/file_encoder.h +++ b/include/FLAC/file_encoder.h @@ -184,6 +184,19 @@ void FLAC__file_encoder_delete(FLAC__FileEncoder *encoder); ***********************************************************************/ /** This is inherited from FLAC__SeekableStreamEncoder; see + * FLAC__seekable_stream_encoder_set_verify(). + * + * \default \c true + * \param encoder An encoder instance to set. + * \param value See above. + * \assert + * \code encoder != NULL \endcode + * \retval FLAC__bool + * \c false if the encoder is already initialized, else \c true. + */ +FLAC__bool FLAC__file_encoder_set_verify(FLAC__FileEncoder *encoder, FLAC__bool value); + +/** This is inherited from FLAC__SeekableStreamEncoder; see * FLAC__seekable_stream_encoder_set_streamable_subset(). * * \default \c true @@ -504,6 +517,32 @@ FLAC__SeekableStreamEncoderState FLAC__file_encoder_get_seekable_stream_encoder_ */ FLAC__StreamEncoderState FLAC__file_encoder_get_stream_encoder_state(const FLAC__FileEncoder *encoder); +/** Get the state of the underlying stream encoder's verify decoder. + * Useful when the file encoder state is + * \c FLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR and the seekable stream + * encoder state is \c FLAC__SEEKABLE_STREAM_ENCODER_STREAM_ENCODER_ERROR and + * the stream encoder state is \c FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR. + * + * \param encoder An encoder instance to query. + * \assert + * \code encoder != NULL \endcode + * \retval FLAC__StreamEncoderState + * The stream encoder state. + */ +FLAC__StreamDecoderState FLAC__file_encoder_get_verify_decoder_state(const FLAC__FileEncoder *encoder); + +/** Get the "verify" flag. + * This is inherited from FLAC__SeekableStreamEncoder; see + * FLAC__seekable_stream_encoder_get_verify(). + * + * \param encoder An encoder instance to query. + * \assert + * \code encoder != NULL \endcode + * \retval FLAC__bool + * See FLAC__file_encoder_set_verify(). + */ +FLAC__bool FLAC__file_encoder_get_verify(const FLAC__FileEncoder *encoder); + /** Get the "streamable subset" flag. * This is inherited from FLAC__SeekableStreamEncoder; see * FLAC__seekable_stream_encoder_get_streamable_subset(). diff --git a/include/FLAC/seekable_stream_encoder.h b/include/FLAC/seekable_stream_encoder.h index 8fb9ad4..164fbfd 100644 --- a/include/FLAC/seekable_stream_encoder.h +++ b/include/FLAC/seekable_stream_encoder.h @@ -196,6 +196,19 @@ void FLAC__seekable_stream_encoder_delete(FLAC__SeekableStreamEncoder *encoder); ***********************************************************************/ /** This is inherited from FLAC__StreamEncoder; see + * FLAC__stream_encoder_set_verify(). + * + * \default \c true + * \param encoder An encoder instance to set. + * \param value See above. + * \assert + * \code encoder != NULL \endcode + * \retval FLAC__bool + * \c false if the encoder is already initialized, else \c true. + */ +FLAC__bool FLAC__seekable_stream_encoder_set_verify(FLAC__SeekableStreamEncoder *encoder, FLAC__bool value); + +/** This is inherited from FLAC__StreamEncoder; see * FLAC__stream_encoder_set_streamable_subset(). * * \default \c true @@ -504,6 +517,31 @@ FLAC__SeekableStreamEncoderState FLAC__seekable_stream_encoder_get_state(const F */ FLAC__StreamEncoderState FLAC__seekable_stream_encoder_get_stream_encoder_state(const FLAC__SeekableStreamEncoder *encoder); +/** Get the state of the underlying stream encoder's verify decoder. + * Useful when the seekable stream encoder state is + * \c FLAC__SEEKABLE_STREAM_ENCODER_STREAM_ENCODER_ERROR and the + * stream encoder state is \c FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR. + * + * \param encoder An encoder instance to query. + * \assert + * \code encoder != NULL \endcode + * \retval FLAC__StreamEncoderState + * The stream encoder state. + */ +FLAC__StreamDecoderState FLAC__seekable_stream_encoder_get_verify_decoder_state(const FLAC__SeekableStreamEncoder *encoder); + +/** Get the "verify" flag. + * This is inherited from FLAC__StreamEncoder; see + * FLAC__stream_encoder_get_verify(). + * + * \param encoder An encoder instance to query. + * \assert + * \code encoder != NULL \endcode + * \retval FLAC__bool + * See FLAC__seekable_stream_encoder_set_verify(). + */ +FLAC__bool FLAC__seekable_stream_encoder_get_verify(const FLAC__SeekableStreamEncoder *encoder); + /** Get the "streamable subset" flag. * This is inherited from FLAC__StreamEncoder; see * FLAC__stream_encoder_get_streamable_subset(). diff --git a/include/FLAC/stream_encoder.h b/include/FLAC/stream_encoder.h index e761517..b36738a 100644 --- a/include/FLAC/stream_encoder.h +++ b/include/FLAC/stream_encoder.h @@ -21,6 +21,7 @@ #define FLAC__STREAM_ENCODER_H #include "format.h" +#include "stream_decoder.h" #ifdef __cplusplus extern "C" { @@ -176,6 +177,16 @@ typedef enum { FLAC__STREAM_ENCODER_OK = 0, /**< The encoder is in the normal OK state. */ + FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR, + /**< An error occurred in the underlying verify stream decoder; + * check FLAC__stream_encoder_get_verify_decoder_state(). + */ + + FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA, + /**< The verify decoder detected a mismatch between the original + * audio signal and the decoded audio signal. + */ + FLAC__STREAM_ENCODER_INVALID_CALLBACK, /**< The encoder was initialized before setting all the required callbacks. */ @@ -316,6 +327,22 @@ void FLAC__stream_encoder_delete(FLAC__StreamEncoder *encoder); * ***********************************************************************/ +/** Set the "verify" flag. If \c true, the encoder will verify it's own + * encoded output by feeding it through an internal decoder and comparing + * the original signal against the decoded signal. If a mismatch occurs, + * the process call will return \c false. Note that this will slow the + * encoding process by the extra time required for decoding and comparison. + * + * \default \c false + * \param encoder An encoder instance to set. + * \param value Flag value (see above). + * \assert + * \code encoder != NULL \endcode + * \retval FLAC__bool + * \c false if the encoder is already initialized, else \c true. + */ +FLAC__bool FLAC__stream_encoder_set_verify(FLAC__StreamEncoder *encoder, FLAC__bool value); + /** Set the "streamable subset" flag. If \c true, the encoder will comply * with the subset (see the format specification) and will check the * settings during FLAC__stream_encoder_init() to see if all settings @@ -652,6 +679,28 @@ FLAC__bool FLAC__stream_encoder_set_client_data(FLAC__StreamEncoder *encoder, vo */ FLAC__StreamEncoderState FLAC__stream_encoder_get_state(const FLAC__StreamEncoder *encoder); +/** Get the state of the verify stream decoder. + * Useful when the stream encoder state is + * \c FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR. + * + * \param encoder An encoder instance to query. + * \assert + * \code encoder != NULL \endcode + * \retval FLAC__StreamDecoderState + * The verify stream decoder state. + */ +FLAC__StreamDecoderState FLAC__stream_encoder_get_verify_decoder_state(const FLAC__StreamEncoder *encoder); + +/** Get the "verify" flag. + * + * \param encoder An encoder instance to query. + * \assert + * \code encoder != NULL \endcode + * \retval FLAC__bool + * See FLAC__stream_encoder_set_verify(). + */ +FLAC__bool FLAC__stream_encoder_get_verify(const FLAC__StreamEncoder *encoder); + /** Get the "streamable subset" flag. * * \param encoder An encoder instance to query. diff --git a/src/libFLAC++/file_encoder.cc b/src/libFLAC++/file_encoder.cc index 5723ae9..7ef1b8f 100644 --- a/src/libFLAC++/file_encoder.cc +++ b/src/libFLAC++/file_encoder.cc @@ -40,6 +40,12 @@ namespace FLAC { return 0 != encoder_; } + bool File::set_verify(bool value) + { + FLAC__ASSERT(is_valid()); + return (bool)::FLAC__file_encoder_set_verify(encoder_, value); + } + bool File::set_streamable_subset(bool value) { FLAC__ASSERT(is_valid()); @@ -166,6 +172,18 @@ namespace FLAC { return Stream::State(::FLAC__file_encoder_get_stream_encoder_state(encoder_)); } + Decoder::Stream::State File::get_verify_decoder_state() const + { + FLAC__ASSERT(is_valid()); + return Decoder::Stream::State(::FLAC__file_encoder_get_verify_decoder_state(encoder_)); + } + + bool File::get_verify() const + { + FLAC__ASSERT(is_valid()); + return (bool)::FLAC__file_encoder_get_verify(encoder_); + } + bool File::get_streamable_subset() const { FLAC__ASSERT(is_valid()); diff --git a/src/libFLAC++/seekable_stream_encoder.cc b/src/libFLAC++/seekable_stream_encoder.cc index de21a2e..6231c5d 100644 --- a/src/libFLAC++/seekable_stream_encoder.cc +++ b/src/libFLAC++/seekable_stream_encoder.cc @@ -40,6 +40,12 @@ namespace FLAC { return 0 != encoder_; } + bool SeekableStream::set_verify(bool value) + { + FLAC__ASSERT(is_valid()); + return (bool)::FLAC__seekable_stream_encoder_set_verify(encoder_, value); + } + bool SeekableStream::set_streamable_subset(bool value) { FLAC__ASSERT(is_valid()); @@ -154,6 +160,18 @@ namespace FLAC { return Stream::State(::FLAC__seekable_stream_encoder_get_stream_encoder_state(encoder_)); } + Decoder::Stream::State SeekableStream::get_verify_decoder_state() const + { + FLAC__ASSERT(is_valid()); + return Decoder::Stream::State(::FLAC__seekable_stream_encoder_get_verify_decoder_state(encoder_)); + } + + bool SeekableStream::get_verify() const + { + FLAC__ASSERT(is_valid()); + return (bool)::FLAC__seekable_stream_encoder_get_verify(encoder_); + } + bool SeekableStream::get_streamable_subset() const { FLAC__ASSERT(is_valid()); diff --git a/src/libFLAC++/stream_encoder.cc b/src/libFLAC++/stream_encoder.cc index 6c99858..4cca397 100644 --- a/src/libFLAC++/stream_encoder.cc +++ b/src/libFLAC++/stream_encoder.cc @@ -40,6 +40,12 @@ namespace FLAC { return 0 != encoder_; } + bool Stream::set_verify(bool value) + { + FLAC__ASSERT(is_valid()); + return (bool)::FLAC__stream_encoder_set_verify(encoder_, value); + } + bool Stream::set_streamable_subset(bool value) { FLAC__ASSERT(is_valid()); @@ -148,6 +154,18 @@ namespace FLAC { return State(::FLAC__stream_encoder_get_state(encoder_)); } + Decoder::Stream::State Stream::get_verify_decoder_state() const + { + FLAC__ASSERT(is_valid()); + return Decoder::Stream::State(::FLAC__stream_encoder_get_verify_decoder_state(encoder_)); + } + + bool Stream::get_verify() const + { + FLAC__ASSERT(is_valid()); + return (bool)::FLAC__stream_encoder_get_verify(encoder_); + } + bool Stream::get_streamable_subset() const { FLAC__ASSERT(is_valid()); diff --git a/src/libFLAC/file_encoder.c b/src/libFLAC/file_encoder.c index 01bf3c4..e6c5cbd 100644 --- a/src/libFLAC/file_encoder.c +++ b/src/libFLAC/file_encoder.c @@ -83,20 +83,24 @@ FLAC__FileEncoder *FLAC__file_encoder_new() if(encoder == 0) { return 0; } + memset(encoder, 0, sizeof(FLAC__FileEncoder)); + encoder->protected_ = (FLAC__FileEncoderProtected*)malloc(sizeof(FLAC__FileEncoderProtected)); if(encoder->protected_ == 0) { free(encoder); return 0; } + memset(encoder->protected_, 0, sizeof(FLAC__FileEncoderProtected)); + encoder->private_ = (FLAC__FileEncoderPrivate*)malloc(sizeof(FLAC__FileEncoderPrivate)); if(encoder->private_ == 0) { free(encoder->protected_); free(encoder); return 0; } + memset(encoder->private_, 0, sizeof(FLAC__FileEncoderPrivate)); encoder->private_->seekable_stream_encoder = FLAC__seekable_stream_encoder_new(); - if(0 == encoder->private_->seekable_stream_encoder) { free(encoder->private_); free(encoder->protected_); @@ -195,6 +199,17 @@ void FLAC__file_encoder_finish(FLAC__FileEncoder *encoder) encoder->protected_->state = FLAC__FILE_ENCODER_UNINITIALIZED; } +FLAC__bool FLAC__file_encoder_set_verify(FLAC__FileEncoder *encoder, FLAC__bool value) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + FLAC__ASSERT(0 != encoder->private_->seekable_stream_encoder); + if(encoder->protected_->state != FLAC__FILE_ENCODER_UNINITIALIZED) + return false; + return FLAC__seekable_stream_encoder_set_verify(encoder->private_->seekable_stream_encoder, value); +} + FLAC__bool FLAC__file_encoder_set_streamable_subset(FLAC__FileEncoder *encoder, FLAC__bool value) { FLAC__ASSERT(0 != encoder); @@ -445,6 +460,20 @@ FLAC__StreamEncoderState FLAC__file_encoder_get_stream_encoder_state(const FLAC_ return FLAC__seekable_stream_encoder_get_stream_encoder_state(encoder->private_->seekable_stream_encoder); } +FLAC__StreamDecoderState FLAC__file_encoder_get_verify_decoder_state(const FLAC__FileEncoder *encoder) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + return FLAC__seekable_stream_encoder_get_verify_decoder_state(encoder->private_->seekable_stream_encoder); +} + +FLAC__bool FLAC__file_encoder_get_verify(const FLAC__FileEncoder *encoder) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + return FLAC__seekable_stream_encoder_get_verify(encoder->private_->seekable_stream_encoder); +} + FLAC__bool FLAC__file_encoder_get_streamable_subset(const FLAC__FileEncoder *encoder) { FLAC__ASSERT(0 != encoder); @@ -561,7 +590,12 @@ FLAC__bool FLAC__file_encoder_process(FLAC__FileEncoder *encoder, const FLAC__in { FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); - return FLAC__seekable_stream_encoder_process(encoder->private_->seekable_stream_encoder, buffer, samples); + if(!FLAC__seekable_stream_encoder_process(encoder->private_->seekable_stream_encoder, buffer, samples)) { + encoder->protected_->state = FLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR; + return false; + } + else + return true; } /* 'samples' is channel-wide samples, e.g. for 1 second at 44100Hz, 'samples' = 44100 regardless of the number of channels */ @@ -569,7 +603,12 @@ FLAC__bool FLAC__file_encoder_process_interleaved(FLAC__FileEncoder *encoder, co { FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); - return FLAC__seekable_stream_encoder_process_interleaved(encoder->private_->seekable_stream_encoder, buffer, samples); + if(!FLAC__seekable_stream_encoder_process_interleaved(encoder->private_->seekable_stream_encoder, buffer, samples)) { + encoder->protected_->state = FLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR; + return false; + } + else + return true; } diff --git a/src/libFLAC/include/protected/stream_encoder.h b/src/libFLAC/include/protected/stream_encoder.h index 9f2d6a4..5561163 100644 --- a/src/libFLAC/include/protected/stream_encoder.h +++ b/src/libFLAC/include/protected/stream_encoder.h @@ -24,6 +24,7 @@ typedef struct FLAC__StreamEncoderProtected { FLAC__StreamEncoderState state; + FLAC__bool verify; FLAC__bool streamable_subset; FLAC__bool do_mid_side_stereo; FLAC__bool loose_mid_side_stereo; diff --git a/src/libFLAC/seekable_stream_encoder.c b/src/libFLAC/seekable_stream_encoder.c index 04f3e87..65bb64f 100644 --- a/src/libFLAC/seekable_stream_encoder.c +++ b/src/libFLAC/seekable_stream_encoder.c @@ -98,20 +98,24 @@ FLAC__SeekableStreamEncoder *FLAC__seekable_stream_encoder_new() if(encoder == 0) { return 0; } + memset(encoder, 0, sizeof(FLAC__SeekableStreamEncoder)); + encoder->protected_ = (FLAC__SeekableStreamEncoderProtected*)malloc(sizeof(FLAC__SeekableStreamEncoderProtected)); if(encoder->protected_ == 0) { free(encoder); return 0; } + memset(encoder->protected_, 0, sizeof(FLAC__SeekableStreamEncoderProtected)); + encoder->private_ = (FLAC__SeekableStreamEncoderPrivate*)malloc(sizeof(FLAC__SeekableStreamEncoderPrivate)); if(encoder->private_ == 0) { free(encoder->protected_); free(encoder); return 0; } + memset(encoder->private_, 0, sizeof(FLAC__SeekableStreamEncoderPrivate)); encoder->private_->stream_encoder = FLAC__stream_encoder_new(); - if(0 == encoder->private_->stream_encoder) { free(encoder->private_); free(encoder->protected_); @@ -204,6 +208,17 @@ void FLAC__seekable_stream_encoder_finish(FLAC__SeekableStreamEncoder *encoder) encoder->protected_->state = FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED; } +FLAC__bool FLAC__seekable_stream_encoder_set_verify(FLAC__SeekableStreamEncoder *encoder, FLAC__bool value) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + FLAC__ASSERT(0 != encoder->private_->stream_encoder); + if(encoder->protected_->state != FLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED) + return false; + return FLAC__stream_encoder_set_verify(encoder->private_->stream_encoder, value); +} + FLAC__bool FLAC__seekable_stream_encoder_set_streamable_subset(FLAC__SeekableStreamEncoder *encoder, FLAC__bool value) { FLAC__ASSERT(0 != encoder); @@ -440,13 +455,27 @@ FLAC__SeekableStreamEncoderState FLAC__seekable_stream_encoder_get_state(const F return encoder->protected_->state; } -FLAC__SeekableStreamEncoderState FLAC__seekable_stream_encoder_get_stream_encoder_state(const FLAC__SeekableStreamEncoder *encoder) +FLAC__StreamEncoderState FLAC__seekable_stream_encoder_get_stream_encoder_state(const FLAC__SeekableStreamEncoder *encoder) { FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); return FLAC__stream_encoder_get_state(encoder->private_->stream_encoder); } +FLAC__StreamDecoderState FLAC__seekable_stream_encoder_get_verify_decoder_state(const FLAC__SeekableStreamEncoder *encoder) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + return FLAC__stream_encoder_get_verify_decoder_state(encoder->private_->stream_encoder); +} + +FLAC__bool FLAC__seekable_stream_encoder_get_verify(const FLAC__SeekableStreamEncoder *encoder) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + return FLAC__stream_encoder_get_verify(encoder->private_->stream_encoder); +} + FLAC__bool FLAC__seekable_stream_encoder_get_streamable_subset(const FLAC__SeekableStreamEncoder *encoder) { FLAC__ASSERT(0 != encoder); @@ -563,7 +592,12 @@ FLAC__bool FLAC__seekable_stream_encoder_process(FLAC__SeekableStreamEncoder *en { FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); - return FLAC__stream_encoder_process(encoder->private_->stream_encoder, buffer, samples); + if(!FLAC__stream_encoder_process(encoder->private_->stream_encoder, buffer, samples)) { + encoder->protected_->state = FLAC__SEEKABLE_STREAM_ENCODER_STREAM_ENCODER_ERROR; + return false; + } + else + return true; } /* 'samples' is channel-wide samples, e.g. for 1 second at 44100Hz, 'samples' = 44100 regardless of the number of channels */ @@ -571,7 +605,12 @@ FLAC__bool FLAC__seekable_stream_encoder_process_interleaved(FLAC__SeekableStrea { FLAC__ASSERT(0 != encoder); FLAC__ASSERT(0 != encoder->private_); - return FLAC__stream_encoder_process_interleaved(encoder->private_->stream_encoder, buffer, samples); + if(!FLAC__stream_encoder_process_interleaved(encoder->private_->stream_encoder, buffer, samples)) { + encoder->protected_->state = FLAC__SEEKABLE_STREAM_ENCODER_STREAM_ENCODER_ERROR; + return false; + } + else + return true; } /*********************************************************************** diff --git a/src/libFLAC/stream_encoder.c b/src/libFLAC/stream_encoder.c index c1c9ccd..14f9139 100644 --- a/src/libFLAC/stream_encoder.c +++ b/src/libFLAC/stream_encoder.c @@ -21,6 +21,7 @@ #include /* for malloc() */ #include /* for memcpy() */ #include "FLAC/assert.h" +#include "FLAC/stream_decoder.h" #include "protected/stream_encoder.h" #include "private/bitbuffer.h" #include "private/bitmath.h" @@ -42,6 +43,26 @@ #endif #define max(x,y) ((x)>(y)?(x):(y)) +typedef struct { + FLAC__int32 *data[FLAC__MAX_CHANNELS]; + unsigned size; /* of each data[] in samples */ + unsigned tail; +} verify_input_fifo; + +typedef struct { + const FLAC__byte *data; + unsigned capacity; + unsigned bytes; +} verify_output; + +typedef enum { + ENCODER_IN_MAGIC = 0, + ENCODER_IN_METADATA = 1, + ENCODER_IN_AUDIO = 2 +} EncoderStateHint; + +/*@@@@ function for getting the error_stats */ + /*********************************************************************** * * Private class method prototypes @@ -51,7 +72,7 @@ static void set_defaults_(FLAC__StreamEncoder *encoder); static void free_(FLAC__StreamEncoder *encoder); static FLAC__bool resize_buffers_(FLAC__StreamEncoder *encoder, unsigned new_size); -static FLAC__bool write_bitbuffer_(FLAC__StreamEncoder *encoder); +static FLAC__bool write_bitbuffer_(FLAC__StreamEncoder *encoder, unsigned samples); static FLAC__bool process_frame_(FLAC__StreamEncoder *encoder, FLAC__bool is_last_frame); static FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_last_frame); static FLAC__bool process_subframe_(FLAC__StreamEncoder *encoder, unsigned min_partition_order, unsigned max_partition_order, FLAC__bool precompute_partition_sums, FLAC__bool verbatim_only, const FLAC__FrameHeader *frame_header, unsigned subframe_bps, const FLAC__int32 integer_signal[], const FLAC__real real_signal[], FLAC__Subframe *subframe[2], FLAC__int32 *residual[2], unsigned *best_subframe, unsigned *best_bits); @@ -71,6 +92,13 @@ static FLAC__bool set_partitioned_rice_(const FLAC__uint32 abs_residual[], const static FLAC__bool set_partitioned_rice_with_precompute_(const FLAC__uint32 abs_residual[], const FLAC__uint64 abs_residual_partition_sums[], const unsigned raw_bits_per_partition[], const unsigned residual_samples, const unsigned predictor_order, const unsigned suggested_rice_parameter, const unsigned rice_parameter_search_dist, const unsigned partition_order, const FLAC__bool search_for_escapes, unsigned parameters[], unsigned raw_bits[], unsigned *bits); #endif static unsigned get_wasted_bits_(FLAC__int32 signal[], unsigned samples); +/* verify-related routines: */ +static void append_to_verify_fifo_(verify_input_fifo *fifo, const FLAC__int32 * const input[], unsigned input_offset, unsigned channels, unsigned wide_samples); +static void append_to_verify_fifo_interleaved_(verify_input_fifo *fifo, const FLAC__int32 input[], unsigned input_offset, unsigned channels, unsigned wide_samples); +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); /*********************************************************************** * @@ -136,6 +164,24 @@ typedef struct FLAC__StreamEncoderPrivate { */ FLAC__real lp_coeff[FLAC__MAX_LPC_ORDER][FLAC__MAX_LPC_ORDER]; /* from process_subframe_() */ unsigned parameters[2][1 << FLAC__MAX_RICE_PARTITION_ORDER], raw_bits[2][1 << FLAC__MAX_RICE_PARTITION_ORDER]; /* from find_best_partition_order_() */ + /* + * The data for the verify section + */ + struct { + FLAC__StreamDecoder *decoder; + EncoderStateHint state_hint; + FLAC__bool needs_magic_hack; + verify_input_fifo input_fifo; + verify_output output; + struct { + FLAC__uint64 absolute_sample; + unsigned frame_number; + unsigned channel; + unsigned sample; + FLAC__int32 expected; + FLAC__int32 got; + } error_stats; + } verify; } FLAC__StreamEncoderPrivate; /*********************************************************************** @@ -146,6 +192,8 @@ typedef struct FLAC__StreamEncoderPrivate { const char * const FLAC__StreamEncoderStateString[] = { "FLAC__STREAM_ENCODER_OK", + "FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR", + "FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA", "FLAC__STREAM_ENCODER_INVALID_CALLBACK", "FLAC__STREAM_ENCODER_INVALID_NUMBER_OF_CHANNELS", "FLAC__STREAM_ENCODER_INVALID_BITS_PER_SAMPLE", @@ -175,7 +223,7 @@ const char * const FLAC__StreamEncoderWriteStatusString[] = { * * Class constructor/destructor * - ***********************************************************************/ + */ FLAC__StreamEncoder *FLAC__stream_encoder_new() { FLAC__StreamEncoder *encoder; @@ -186,17 +234,23 @@ FLAC__StreamEncoder *FLAC__stream_encoder_new() if(encoder == 0) { return 0; } + memset(encoder, 0, sizeof(FLAC__StreamEncoder)); + encoder->protected_ = (FLAC__StreamEncoderProtected*)malloc(sizeof(FLAC__StreamEncoderProtected)); if(encoder->protected_ == 0) { free(encoder); return 0; } + memset(encoder->protected_, 0, sizeof(FLAC__StreamEncoderProtected)); + encoder->private_ = (FLAC__StreamEncoderPrivate*)malloc(sizeof(FLAC__StreamEncoderPrivate)); if(encoder->private_ == 0) { free(encoder->protected_); free(encoder); return 0; } + memset(encoder->private_, 0, sizeof(FLAC__StreamEncoderPrivate)); + encoder->private_->frame = FLAC__bitbuffer_new(); if(encoder->private_->frame == 0) { free(encoder->private_); @@ -220,6 +274,8 @@ void FLAC__stream_encoder_delete(FLAC__StreamEncoder *encoder) FLAC__ASSERT(0 != encoder->private_->frame); free_(encoder); + if(encoder->protected_->verify && 0 != encoder->private_->verify.decoder) + FLAC__stream_decoder_delete(encoder->private_->verify.decoder); FLAC__bitbuffer_delete(encoder->private_->frame); free(encoder->private_); free(encoder->protected_); @@ -426,16 +482,53 @@ FLAC__StreamEncoderState FLAC__stream_encoder_init(FLAC__StreamEncoder *encoder) return encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR; /* + * Set up the verify stuff if necessary + */ + if(encoder->protected_->verify) { + /* + * First, set up the fifo which will hold the + * original signal to compare against + */ + encoder->private_->verify.input_fifo.size = encoder->protected_->blocksize; + for(i = 0; i < encoder->protected_->channels; i++) { + if(0 == (encoder->private_->verify.input_fifo.data[i] = (FLAC__int32*)malloc(sizeof(FLAC__int32) * encoder->private_->verify.input_fifo.size))) + return encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR; + } + encoder->private_->verify.input_fifo.tail = 0; + + /* + * Now set up a stream decoder for verification + */ + encoder->private_->verify.decoder = FLAC__stream_decoder_new(); + if(0 == encoder->private_->verify.decoder) + return encoder->protected_->state = FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR; + + FLAC__stream_decoder_set_read_callback(encoder->private_->verify.decoder, verify_read_callback_); + FLAC__stream_decoder_set_write_callback(encoder->private_->verify.decoder, verify_write_callback_); + FLAC__stream_decoder_set_metadata_callback(encoder->private_->verify.decoder, verify_metadata_callback_); + FLAC__stream_decoder_set_error_callback(encoder->private_->verify.decoder, verify_error_callback_); + FLAC__stream_decoder_set_client_data(encoder->private_->verify.decoder, encoder); + if(FLAC__stream_decoder_init(encoder->private_->verify.decoder) != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA) + return encoder->protected_->state = FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR; + } + + /* * write the stream header */ + if(encoder->protected_->verify) + encoder->private_->verify.state_hint = ENCODER_IN_MAGIC; if(!FLAC__bitbuffer_write_raw_uint32(encoder->private_->frame, FLAC__STREAM_SYNC, FLAC__STREAM_SYNC_LEN)) return encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR; - if(!write_bitbuffer_(encoder)) - return encoder->protected_->state = FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_WRITING; + if(!write_bitbuffer_(encoder, 0)) { + /* the above function sets the state for us in case of an error */ + return encoder->protected_->state; + } /* * write the STREAMINFO metadata block */ + if(encoder->protected_->verify) + encoder->private_->verify.state_hint = ENCODER_IN_METADATA; encoder->private_->metadata.type = FLAC__METADATA_TYPE_STREAMINFO; encoder->private_->metadata.is_last = (encoder->protected_->num_metadata_blocks == 0); encoder->private_->metadata.length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH; @@ -455,8 +548,10 @@ FLAC__StreamEncoderState FLAC__stream_encoder_init(FLAC__StreamEncoder *encoder) } if(!FLAC__add_metadata_block(&encoder->private_->metadata, encoder->private_->frame)) return encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR; - if(!write_bitbuffer_(encoder)) - return encoder->protected_->state = FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_WRITING; + if(!write_bitbuffer_(encoder, 0)) { + /* the above function sets the state for us in case of an error */ + return encoder->protected_->state; + } /* * Now that the STREAMINFO block is written, we can init this to an @@ -477,10 +572,15 @@ FLAC__StreamEncoderState FLAC__stream_encoder_init(FLAC__StreamEncoder *encoder) } if(!FLAC__add_metadata_block(encoder->protected_->metadata[i], encoder->private_->frame)) return encoder->protected_->state = FLAC__STREAM_ENCODER_FRAMING_ERROR; - if(!write_bitbuffer_(encoder)) - return encoder->protected_->state = FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_WRITING; + if(!write_bitbuffer_(encoder, 0)) { + /* the above function sets the state for us in case of an error */ + return encoder->protected_->state; + } } + if(encoder->protected_->verify) + encoder->private_->verify.state_hint = ENCODER_IN_AUDIO; + return encoder->protected_->state; } @@ -496,12 +596,24 @@ void FLAC__stream_encoder_finish(FLAC__StreamEncoder *encoder) MD5Final(encoder->private_->metadata.data.stream_info.md5sum, &encoder->private_->md5context); encoder->private_->metadata_callback(encoder, &encoder->private_->metadata, encoder->private_->client_data); + if(encoder->protected_->verify && 0 != encoder->private_->verify.decoder) + FLAC__stream_decoder_finish(encoder->private_->verify.decoder); + free_(encoder); set_defaults_(encoder); encoder->protected_->state = FLAC__STREAM_ENCODER_UNINITIALIZED; } +FLAC__bool FLAC__stream_encoder_set_verify(FLAC__StreamEncoder *encoder, FLAC__bool value) +{ + FLAC__ASSERT(0 != encoder); + if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED) + return false; + encoder->protected_->verify = value; + return true; +} + FLAC__bool FLAC__stream_encoder_set_streamable_subset(FLAC__StreamEncoder *encoder, FLAC__bool value) { FLAC__ASSERT(0 != encoder); @@ -701,6 +813,21 @@ FLAC__StreamEncoderState FLAC__stream_encoder_get_state(const FLAC__StreamEncode return encoder->protected_->state; } +FLAC__StreamDecoderState FLAC__stream_encoder_get_verify_decoder_state(const FLAC__StreamEncoder *encoder) +{ + FLAC__ASSERT(0 != encoder); + if(encoder->protected_->verify) + return FLAC__stream_decoder_get_state(encoder->private_->verify.decoder); + else + return FLAC__STREAM_DECODER_UNINITIALIZED; +} + +FLAC__bool FLAC__stream_encoder_get_verify(const FLAC__StreamEncoder *encoder) +{ + FLAC__ASSERT(0 != encoder); + return encoder->protected_->verify; +} + FLAC__bool FLAC__stream_encoder_get_streamable_subset(const FLAC__StreamEncoder *encoder) { FLAC__ASSERT(0 != encoder); @@ -809,6 +936,9 @@ FLAC__bool FLAC__stream_encoder_process(FLAC__StreamEncoder *encoder, const FLAC j = 0; if(encoder->protected_->do_mid_side_stereo && channels == 2) { do { + if(encoder->protected_->verify) + append_to_verify_fifo_(&encoder->private_->verify.input_fifo, buffer, j, channels, min(blocksize-encoder->private_->current_sample_number, samples-j)); + for(i = encoder->private_->current_sample_number; i < blocksize && j < samples; i++, j++) { x = mid = side = buffer[0][j]; encoder->private_->integer_signal[0][i] = x; @@ -833,6 +963,9 @@ FLAC__bool FLAC__stream_encoder_process(FLAC__StreamEncoder *encoder, const FLAC } else { do { + if(encoder->protected_->verify) + append_to_verify_fifo_(&encoder->private_->verify.input_fifo, buffer, j, channels, min(blocksize-encoder->private_->current_sample_number, samples-j)); + for(i = encoder->private_->current_sample_number; i < blocksize && j < samples; i++, j++) { for(channel = 0; channel < channels; channel++) { x = buffer[channel][j]; @@ -851,7 +984,6 @@ FLAC__bool FLAC__stream_encoder_process(FLAC__StreamEncoder *encoder, const FLAC return true; } -/* 'samples' is channel-wide samples, e.g. for 1 second at 44100Hz, 'samples' = 44100 regardless of the number of channels */ FLAC__bool FLAC__stream_encoder_process_interleaved(FLAC__StreamEncoder *encoder, const FLAC__int32 buffer[], unsigned samples) { unsigned i, j, k, channel; @@ -864,6 +996,9 @@ FLAC__bool FLAC__stream_encoder_process_interleaved(FLAC__StreamEncoder *encoder j = k = 0; if(encoder->protected_->do_mid_side_stereo && channels == 2) { do { + if(encoder->protected_->verify) + append_to_verify_fifo_interleaved_(&encoder->private_->verify.input_fifo, buffer, j, channels, min(blocksize-encoder->private_->current_sample_number, samples-j)); + for(i = encoder->private_->current_sample_number; i < blocksize && j < samples; i++, j++) { x = mid = side = buffer[k++]; encoder->private_->integer_signal[0][i] = x; @@ -888,6 +1023,9 @@ FLAC__bool FLAC__stream_encoder_process_interleaved(FLAC__StreamEncoder *encoder } else { do { + if(encoder->protected_->verify) + append_to_verify_fifo_interleaved_(&encoder->private_->verify.input_fifo, buffer, j, channels, min(blocksize-encoder->private_->current_sample_number, samples-j)); + for(i = encoder->private_->current_sample_number; i < blocksize && j < samples; i++, j++) { for(channel = 0; channel < channels; channel++) { x = buffer[k++]; @@ -916,6 +1054,7 @@ void set_defaults_(FLAC__StreamEncoder *encoder) { FLAC__ASSERT(0 != encoder); + encoder->protected_->verify = false; encoder->protected_->streamable_subset = true; encoder->protected_->do_mid_side_stereo = false; encoder->protected_->loose_mid_side_stereo = false; @@ -993,6 +1132,14 @@ void free_(FLAC__StreamEncoder *encoder) free(encoder->private_->raw_bits_per_partition_unaligned); encoder->private_->raw_bits_per_partition_unaligned = 0; } + if(encoder->protected_->verify) { + for(i = 0; i < encoder->protected_->channels; i++) { + if(0 != encoder->private_->verify.input_fifo.data[i]) { + free(encoder->private_->verify.input_fifo.data[i]); + encoder->private_->verify.input_fifo.data[i] = 0; + } + } + } FLAC__bitbuffer_free(encoder->private_->frame); } @@ -1049,7 +1196,7 @@ FLAC__bool resize_buffers_(FLAC__StreamEncoder *encoder, unsigned new_size) return ok; } -FLAC__bool write_bitbuffer_(FLAC__StreamEncoder *encoder) +FLAC__bool write_bitbuffer_(FLAC__StreamEncoder *encoder, unsigned samples) { const FLAC__byte *buffer; unsigned bytes; @@ -1058,19 +1205,39 @@ FLAC__bool write_bitbuffer_(FLAC__StreamEncoder *encoder) FLAC__bitbuffer_get_buffer(encoder->private_->frame, &buffer, &bytes); - if(encoder->private_->write_callback(encoder, buffer, bytes, 0, encoder->private_->current_frame_number, encoder->private_->client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) + if(encoder->protected_->verify) { + encoder->private_->verify.output.data = buffer; + encoder->private_->verify.output.bytes = bytes; + if(encoder->private_->verify.state_hint == ENCODER_IN_MAGIC) { + encoder->private_->verify.needs_magic_hack = true; + } + else { + if(!FLAC__stream_decoder_process_single(encoder->private_->verify.decoder)) { + FLAC__bitbuffer_release_buffer(encoder->private_->frame); + if(encoder->protected_->state != FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA) + encoder->protected_->state = FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR; + return false; + } + } + } + + if(encoder->private_->write_callback(encoder, buffer, bytes, samples, encoder->private_->current_frame_number, encoder->private_->client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) { + encoder->protected_->state = FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_WRITING; return false; + } FLAC__bitbuffer_release_buffer(encoder->private_->frame); + if(samples > 0) { + encoder->private_->metadata.data.stream_info.min_framesize = min(bytes, encoder->private_->metadata.data.stream_info.min_framesize); + encoder->private_->metadata.data.stream_info.max_framesize = max(bytes, encoder->private_->metadata.data.stream_info.max_framesize); + } + return true; } FLAC__bool process_frame_(FLAC__StreamEncoder *encoder, FLAC__bool is_last_frame) { - const FLAC__byte *buffer; - unsigned bytes; - FLAC__ASSERT(encoder->protected_->state == FLAC__STREAM_ENCODER_OK); /* @@ -1106,12 +1273,10 @@ FLAC__bool process_frame_(FLAC__StreamEncoder *encoder, FLAC__bool is_last_frame /* * Write it */ - FLAC__bitbuffer_get_buffer(encoder->private_->frame, &buffer, &bytes); - if(encoder->private_->write_callback(encoder, buffer, bytes, encoder->protected_->blocksize, encoder->private_->current_frame_number, encoder->private_->client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) { - encoder->protected_->state = FLAC__STREAM_ENCODER_FATAL_ERROR_WHILE_WRITING; + if(!write_bitbuffer_(encoder, encoder->protected_->blocksize)) { + /* the above function sets the state for us in case of an error */ return false; } - FLAC__bitbuffer_release_buffer(encoder->private_->frame); /* * Get ready for the next frame @@ -1119,8 +1284,6 @@ FLAC__bool process_frame_(FLAC__StreamEncoder *encoder, FLAC__bool is_last_frame encoder->private_->current_sample_number = 0; encoder->private_->current_frame_number++; encoder->private_->metadata.data.stream_info.total_samples += (FLAC__uint64)encoder->protected_->blocksize; - encoder->private_->metadata.data.stream_info.min_framesize = min(bytes, encoder->private_->metadata.data.stream_info.min_framesize); - encoder->private_->metadata.data.stream_info.max_framesize = max(bytes, encoder->private_->metadata.data.stream_info.max_framesize); return true; } @@ -2137,3 +2300,112 @@ unsigned get_wasted_bits_(FLAC__int32 signal[], unsigned samples) return shift; } + +void append_to_verify_fifo_(verify_input_fifo *fifo, const FLAC__int32 * const input[], unsigned input_offset, unsigned channels, unsigned wide_samples) +{ + unsigned channel; + + for(channel = 0; channel < channels; channel++) + memcpy(&fifo->data[channel][fifo->tail], &input[channel][input_offset], sizeof(FLAC__int32) * wide_samples); + + fifo->tail += wide_samples; + + FLAC__ASSERT(fifo->tail <= fifo->size); +} + +void append_to_verify_fifo_interleaved_(verify_input_fifo *fifo, const FLAC__int32 input[], unsigned input_offset, unsigned channels, unsigned wide_samples) +{ + unsigned channel; + unsigned sample, wide_sample; + unsigned tail = fifo->tail; + + sample = input_offset * channels; + for(wide_sample = 0; wide_sample < wide_samples; wide_sample++) { + for(channel = 0; channel < channels; channel++) + fifo->data[channel][tail] = input[sample++]; + tail++; + } + fifo->tail = tail; + + FLAC__ASSERT(fifo->tail <= fifo->size); +} + +FLAC__StreamDecoderReadStatus verify_read_callback_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data) +{ + FLAC__StreamEncoder *encoder = (FLAC__StreamEncoder*)client_data; + const unsigned encoded_bytes = encoder->private_->verify.output.bytes; + (void)decoder; + + if(encoder->private_->verify.needs_magic_hack) { + FLAC__ASSERT(*bytes >= FLAC__STREAM_SYNC_LENGTH); + *bytes = FLAC__STREAM_SYNC_LENGTH; + memcpy(buffer, FLAC__STREAM_SYNC_STRING, *bytes); + encoder->private_->verify.needs_magic_hack = false; + } + else { + if(encoded_bytes == 0) { + //@@@@ underflow happened, should we do something else here? is this an assert failure? + return FLAC__STREAM_DECODER_READ_STATUS_ABORT; + } + else if(encoded_bytes < *bytes) + *bytes = encoded_bytes; + memcpy(buffer, encoder->private_->verify.output.data, *bytes); + encoder->private_->verify.output.data += *bytes; + encoder->private_->verify.output.bytes -= *bytes; + } + + return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; +} + +FLAC__StreamDecoderWriteStatus verify_write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data) +{ + FLAC__StreamEncoder *encoder = (FLAC__StreamEncoder *)client_data; + unsigned channel; + const unsigned channels = FLAC__stream_decoder_get_channels(decoder); + const unsigned blocksize = frame->header.blocksize; + const unsigned bytes_per_block = sizeof(FLAC__int32) * blocksize; + + for(channel = 0; channel < channels; channel++) { + if(0 != memcmp(buffer[channel], encoder->private_->verify.input_fifo.data[channel], bytes_per_block)) { + unsigned i, sample = 0; + FLAC__int32 expect = 0, got = 0; + + for(i = 0; i < blocksize; i++) { + if(buffer[channel][i] != encoder->private_->verify.input_fifo.data[channel][i]) { + sample = i; + expect = (FLAC__int32)encoder->private_->verify.input_fifo.data[channel][i]; + got = (FLAC__int32)buffer[channel][i]; + break; + } + } + FLAC__ASSERT(i < blocksize); + FLAC__ASSERT(frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER); + encoder->private_->verify.error_stats.absolute_sample = frame->header.number.sample_number + sample; + encoder->private_->verify.error_stats.frame_number = frame->header.number.sample_number / blocksize; + encoder->private_->verify.error_stats.channel = channel; + encoder->private_->verify.error_stats.sample = sample; + encoder->private_->verify.error_stats.expected = expect; + encoder->private_->verify.error_stats.got = got; + encoder->protected_->state = FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA; + return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; + } + } + /* dequeue the frame from the fifo */ + for(channel = 0; channel < channels; channel++) { + memmove(&encoder->private_->verify.input_fifo.data[channel][0], &encoder->private_->verify.input_fifo.data[channel][blocksize], encoder->private_->verify.input_fifo.tail - blocksize); + } + encoder->private_->verify.input_fifo.tail -= 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) +{ + FLAC__StreamEncoder *encoder = (FLAC__StreamEncoder*)client_data; + (void)decoder, (void)status; + encoder->protected_->state = FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR; +} diff --git a/src/test_libFLAC++/encoders.cc b/src/test_libFLAC++/encoders.cc index 854ed70..dc44490 100644 --- a/src/test_libFLAC++/encoders.cc +++ b/src/test_libFLAC++/encoders.cc @@ -180,6 +180,11 @@ static bool test_stream_encoder() } printf("OK\n"); + printf("testing set_verify()... "); + if(!encoder->set_verify(true)) + return encoder->die("returned false"); + printf("OK\n"); + printf("testing set_streamable_subset()... "); if(!encoder->set_streamable_subset(true)) return encoder->die("returned false"); @@ -274,6 +279,13 @@ static bool test_stream_encoder() FLAC::Encoder::Stream::State state = encoder->get_state(); printf("returned state = %u (%s)... OK\n", (unsigned)((::FLAC__StreamEncoderState)state), state.as_cstring()); + printf("testing get_verify()... "); + if(encoder->get_verify() != true) { + printf("FAILED, expected true, got false\n"); + return false; + } + printf("OK\n"); + printf("testing get_streamable_subset()... "); if(encoder->get_streamable_subset() != true) { printf("FAILED, expected true, got false\n"); @@ -450,6 +462,10 @@ bool SeekableStreamEncoder::die(const char *msg) const if(state == ::FLAC__SEEKABLE_STREAM_ENCODER_STREAM_ENCODER_ERROR) { FLAC::Encoder::Stream::State state_ = get_stream_encoder_state(); printf(" stream encoder state = %u (%s)\n", (unsigned)((::FLAC__StreamEncoderState)state_), state_.as_cstring()); + if(state_ == ::FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR) { + FLAC::Decoder::Stream::State dstate = get_verify_decoder_state(); + printf(" verify decoder state = %u (%s)\n", (unsigned)((::FLAC__StreamDecoderState)dstate), dstate.as_cstring()); + } } return false; @@ -479,6 +495,11 @@ static bool test_seekable_stream_encoder() } printf("OK\n"); + printf("testing set_verify()... "); + if(!encoder->set_verify(true)) + return encoder->die("returned false"); + printf("OK\n"); + printf("testing set_streamable_subset()... "); if(!encoder->set_streamable_subset(true)) return encoder->die("returned false"); @@ -577,6 +598,17 @@ static bool test_seekable_stream_encoder() FLAC::Encoder::Stream::State state_ = encoder->get_stream_encoder_state(); printf("returned state = %u (%s)... OK\n", (unsigned)((::FLAC__StreamEncoderState)state_), state_.as_cstring()); + printf("testing get_verify_decoder_state()... "); + FLAC::Decoder::Stream::State dstate = encoder->get_verify_decoder_state(); + printf("returned state = %u (%s)... OK\n", (unsigned)((::FLAC__StreamDecoderState)dstate), dstate.as_cstring()); + + printf("testing get_verify()... "); + if(encoder->get_verify() != true) { + printf("FAILED, expected true, got false\n"); + return false; + } + printf("OK\n"); + printf("testing get_streamable_subset()... "); if(encoder->get_streamable_subset() != true) { printf("FAILED, expected true, got false\n"); @@ -746,6 +778,10 @@ bool FileEncoder::die(const char *msg) const if(state_ == ::FLAC__SEEKABLE_STREAM_ENCODER_STREAM_ENCODER_ERROR) { FLAC::Encoder::Stream::State state__ = get_stream_encoder_state(); printf(" stream encoder state = %u (%s)\n", (unsigned)((::FLAC__StreamEncoderState)state__), state__.as_cstring()); + if(state__ == ::FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR) { + FLAC::Decoder::Stream::State dstate = get_verify_decoder_state(); + printf(" verify decoder state = %u (%s)\n", (unsigned)((::FLAC__StreamDecoderState)dstate), dstate.as_cstring()); + } } } @@ -776,6 +812,11 @@ static bool test_file_encoder() } printf("OK\n"); + printf("testing set_verify()... "); + if(!encoder->set_verify(true)) + return encoder->die("returned false"); + printf("OK\n"); + printf("testing set_streamable_subset()... "); if(!encoder->set_streamable_subset(true)) return encoder->die("returned false"); @@ -883,6 +924,17 @@ static bool test_file_encoder() FLAC::Encoder::Stream::State state__ = encoder->get_stream_encoder_state(); printf("returned state = %u (%s)... OK\n", (unsigned)((::FLAC__StreamEncoderState)state__), state__.as_cstring()); + printf("testing get_verify_decoder_state()... "); + FLAC::Decoder::Stream::State dstate = encoder->get_verify_decoder_state(); + printf("returned state = %u (%s)... OK\n", (unsigned)((::FLAC__StreamDecoderState)dstate), dstate.as_cstring()); + + printf("testing get_verify()... "); + if(encoder->get_verify() != true) { + printf("FAILED, expected true, got false\n"); + return false; + } + printf("OK\n"); + printf("testing get_streamable_subset()... "); if(encoder->get_streamable_subset() != true) { printf("FAILED, expected true, got false\n"); diff --git a/src/test_libFLAC++/file_utils.c b/src/test_libFLAC++/file_utils.c index a460d4b..6a14468 100644 --- a/src/test_libFLAC++/file_utils.c +++ b/src/test_libFLAC++/file_utils.c @@ -113,6 +113,7 @@ FLAC__bool file_utils__generate_flacfile(const char *output_filename, unsigned * return false; } + FLAC__stream_encoder_set_verify(encoder, true); FLAC__stream_encoder_set_streamable_subset(encoder, true); FLAC__stream_encoder_set_do_mid_side_stereo(encoder, false); FLAC__stream_encoder_set_loose_mid_side_stereo(encoder, false); diff --git a/src/test_libFLAC/encoders.c b/src/test_libFLAC/encoders.c index 5660b82..6b2d501 100644 --- a/src/test_libFLAC/encoders.c +++ b/src/test_libFLAC/encoders.c @@ -57,7 +57,11 @@ static FLAC__bool die_ss_(const char *msg, const FLAC__SeekableStreamEncoder *en printf(", state = %u (%s)\n", (unsigned)state, FLAC__SeekableStreamEncoderStateString[state]); if(state == FLAC__SEEKABLE_STREAM_ENCODER_STREAM_ENCODER_ERROR) { FLAC__StreamEncoderState state_ = FLAC__seekable_stream_encoder_get_stream_encoder_state(encoder); - printf(" stream encoder state = %u (%s)\n", (unsigned)state, FLAC__StreamEncoderStateString[state_]); + printf(" stream encoder state = %u (%s)\n", (unsigned)state_, FLAC__StreamEncoderStateString[state_]); + if(state_ == FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR) { + FLAC__StreamDecoderState dstate = FLAC__seekable_stream_encoder_get_verify_decoder_state(encoder); + printf(" verify decoder state = %u (%s)\n", (unsigned)dstate, FLAC__StreamDecoderStateString[dstate]); + } } return false; @@ -75,10 +79,14 @@ static FLAC__bool die_f_(const char *msg, const FLAC__FileEncoder *encoder) printf(", state = %u (%s)\n", (unsigned)state, FLAC__FileEncoderStateString[state]); if(state == FLAC__FILE_ENCODER_SEEKABLE_STREAM_ENCODER_ERROR) { FLAC__SeekableStreamEncoderState state_ = FLAC__file_encoder_get_seekable_stream_encoder_state(encoder); - printf(" seekable stream encoder state = %u (%s)\n", (unsigned)state, FLAC__SeekableStreamEncoderStateString[state_]); + printf(" seekable stream encoder state = %u (%s)\n", (unsigned)state_, FLAC__SeekableStreamEncoderStateString[state_]); if(state_ == FLAC__SEEKABLE_STREAM_ENCODER_STREAM_ENCODER_ERROR) { FLAC__StreamEncoderState state__ = FLAC__file_encoder_get_stream_encoder_state(encoder); - printf(" stream encoder state = %u (%s)\n", (unsigned)state, FLAC__StreamEncoderStateString[state__]); + printf(" stream encoder state = %u (%s)\n", (unsigned)state__, FLAC__StreamEncoderStateString[state__]); + if(state__ == FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR) { + FLAC__StreamDecoderState dstate = FLAC__file_encoder_get_verify_decoder_state(encoder); + printf(" verify decoder state = %u (%s)\n", (unsigned)dstate, FLAC__StreamDecoderStateString[dstate]); + } } } @@ -187,6 +195,7 @@ static FLAC__bool test_stream_encoder() { FLAC__StreamEncoder *encoder; FLAC__StreamEncoderState state; + FLAC__StreamDecoderState dstate; FLAC__int32 samples[1024]; FLAC__int32 *samples_array[1] = { samples }; unsigned i; @@ -201,6 +210,11 @@ static FLAC__bool test_stream_encoder() } printf("OK\n"); + printf("testing FLAC__stream_encoder_set_verify()... "); + if(!FLAC__stream_encoder_set_verify(encoder, true)) + return die_s_("returned false", encoder); + printf("OK\n"); + printf("testing FLAC__stream_encoder_set_streamable_subset()... "); if(!FLAC__stream_encoder_set_streamable_subset(encoder, true)) return die_s_("returned false", encoder); @@ -310,6 +324,17 @@ static FLAC__bool test_stream_encoder() state = FLAC__stream_encoder_get_state(encoder); printf("returned state = %u (%s)... OK\n", (unsigned)state, FLAC__StreamEncoderStateString[state]); + printf("testing FLAC__stream_encoder_get_verify_decoder_state()... "); + dstate = FLAC__stream_encoder_get_verify_decoder_state(encoder); + printf("returned state = %u (%s)... OK\n", (unsigned)dstate, FLAC__StreamDecoderStateString[dstate]); + + printf("testing FLAC__stream_encoder_get_verify()... "); + if(FLAC__stream_encoder_get_verify(encoder) != true) { + printf("FAILED, expected true, got false\n"); + return false; + } + printf("OK\n"); + printf("testing FLAC__stream_encoder_get_streamable_subset()... "); if(FLAC__stream_encoder_get_streamable_subset(encoder) != true) { printf("FAILED, expected true, got false\n"); @@ -463,6 +488,8 @@ static FLAC__bool test_seekable_stream_encoder() { FLAC__SeekableStreamEncoder *encoder; FLAC__SeekableStreamEncoderState state; + FLAC__StreamEncoderState state_; + FLAC__StreamDecoderState dstate; FLAC__int32 samples[1024]; FLAC__int32 *samples_array[1] = { samples }; unsigned i; @@ -477,6 +504,11 @@ static FLAC__bool test_seekable_stream_encoder() } printf("OK\n"); + printf("testing FLAC__seekable_stream_encoder_set_verify()... "); + if(!FLAC__seekable_stream_encoder_set_verify(encoder, true)) + return die_ss_("returned false", encoder); + printf("OK\n"); + printf("testing FLAC__seekable_stream_encoder_set_streamable_subset()... "); if(!FLAC__seekable_stream_encoder_set_streamable_subset(encoder, true)) return die_ss_("returned false", encoder); @@ -586,6 +618,21 @@ static FLAC__bool test_seekable_stream_encoder() state = FLAC__seekable_stream_encoder_get_state(encoder); printf("returned state = %u (%s)... OK\n", (unsigned)state, FLAC__SeekableStreamEncoderStateString[state]); + printf("testing FLAC__seekable_stream_encoder_get_stream_encoder_state()... "); + state_ = FLAC__seekable_stream_encoder_get_stream_encoder_state(encoder); + printf("returned state = %u (%s)... OK\n", (unsigned)state_, FLAC__StreamEncoderStateString[state_]); + + printf("testing FLAC__seekable_stream_encoder_get_verify_decoder_state()... "); + dstate = FLAC__seekable_stream_encoder_get_verify_decoder_state(encoder); + printf("returned state = %u (%s)... OK\n", (unsigned)dstate, FLAC__StreamDecoderStateString[dstate]); + + printf("testing FLAC__seekable_stream_encoder_get_verify()... "); + if(FLAC__seekable_stream_encoder_get_verify(encoder) != true) { + printf("FAILED, expected true, got false\n"); + return false; + } + printf("OK\n"); + printf("testing FLAC__seekable_stream_encoder_get_streamable_subset()... "); if(FLAC__seekable_stream_encoder_get_streamable_subset(encoder) != true) { printf("FAILED, expected true, got false\n"); @@ -732,6 +779,9 @@ static FLAC__bool test_file_encoder() { FLAC__FileEncoder *encoder; FLAC__FileEncoderState state; + FLAC__SeekableStreamEncoderState state_; + FLAC__StreamEncoderState state__; + FLAC__StreamDecoderState dstate; FLAC__int32 samples[1024]; FLAC__int32 *samples_array[1] = { samples }; unsigned i; @@ -746,6 +796,11 @@ static FLAC__bool test_file_encoder() } printf("OK\n"); + printf("testing FLAC__file_encoder_set_verify()... "); + if(!FLAC__file_encoder_set_verify(encoder, true)) + return die_f_("returned false", encoder); + printf("OK\n"); + printf("testing FLAC__file_encoder_set_streamable_subset()... "); if(!FLAC__file_encoder_set_streamable_subset(encoder, true)) return die_f_("returned false", encoder); @@ -855,6 +910,25 @@ static FLAC__bool test_file_encoder() state = FLAC__file_encoder_get_state(encoder); printf("returned state = %u (%s)... OK\n", (unsigned)state, FLAC__FileEncoderStateString[state]); + printf("testing FLAC__file_encoder_get_seekable_stream_encoder_state()... "); + state_ = FLAC__file_encoder_get_seekable_stream_encoder_state(encoder); + printf("returned state = %u (%s)... OK\n", (unsigned)state_, FLAC__SeekableStreamEncoderStateString[state_]); + + printf("testing FLAC__file_encoder_get_stream_encoder_state()... "); + state__ = FLAC__file_encoder_get_stream_encoder_state(encoder); + printf("returned state = %u (%s)... OK\n", (unsigned)state__, FLAC__StreamEncoderStateString[state__]); + + printf("testing FLAC__file_encoder_get_verify_decoder_state()... "); + dstate = FLAC__file_encoder_get_verify_decoder_state(encoder); + printf("returned state = %u (%s)... OK\n", (unsigned)dstate, FLAC__StreamDecoderStateString[dstate]); + + printf("testing FLAC__file_encoder_get_verify()... "); + if(FLAC__file_encoder_get_verify(encoder) != true) { + printf("FAILED, expected true, got false\n"); + return false; + } + printf("OK\n"); + printf("testing FLAC__file_encoder_get_streamable_subset()... "); if(FLAC__file_encoder_get_streamable_subset(encoder) != true) { printf("FAILED, expected true, got false\n"); diff --git a/src/test_libFLAC/file_utils.c b/src/test_libFLAC/file_utils.c index a460d4b..6a14468 100644 --- a/src/test_libFLAC/file_utils.c +++ b/src/test_libFLAC/file_utils.c @@ -113,6 +113,7 @@ FLAC__bool file_utils__generate_flacfile(const char *output_filename, unsigned * return false; } + FLAC__stream_encoder_set_verify(encoder, true); FLAC__stream_encoder_set_streamable_subset(encoder, true); FLAC__stream_encoder_set_do_mid_side_stereo(encoder, false); FLAC__stream_encoder_set_loose_mid_side_stereo(encoder, false);