Sigrid Solveig HaflínudóttirlibFLAC: update 1.3.4 → 1.4.0ccc41834 years agoHistory
3685 lines · 143.2 KB · C
RawDownload
/* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009  Josh Coalson * Copyright (C) 2011-2022  Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * - Neither the name of the Xiph.org Foundation nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H#  include <config.h>#endif #include <stdio.h>#include <stdlib.h> /* for malloc() */#include <string.h> /* for memset/memcpy() */#include <sys/stat.h> /* for stat() */#include <sys/types.h> /* for off_t */#include "share/compat.h"#include "FLAC/assert.h"#include "share/alloc.h"#include "protected/stream_decoder.h"#include "private/bitreader.h"#include "private/bitmath.h"#include "private/crc.h"#include "private/fixed.h"#include "private/format.h"#include "private/lpc.h"#include "private/md5.h"#include "private/memory.h"#include "private/macros.h"  /* technically this should be in an "export.c" but this is convenient enough */FLAC_API int FLAC_API_SUPPORTS_OGG_FLAC = FLAC__HAS_OGG;  /*********************************************************************** * * Private static data * ***********************************************************************/ static const FLAC__byte ID3V2_TAG_[3] = { 'I', 'D', '3' }; /*********************************************************************** * * Private class method prototypes * ***********************************************************************/ static void set_defaults_(FLAC__StreamDecoder *decoder);static FILE *get_binary_stdin_(void);static FLAC__bool allocate_output_(FLAC__StreamDecoder *decoder, uint32_t size, uint32_t channels, uint32_t bps);static FLAC__bool has_id_filtered_(FLAC__StreamDecoder *decoder, FLAC__byte *id);static FLAC__bool find_metadata_(FLAC__StreamDecoder *decoder);static FLAC__bool read_metadata_(FLAC__StreamDecoder *decoder);static FLAC__bool read_metadata_streaminfo_(FLAC__StreamDecoder *decoder, FLAC__bool is_last, uint32_t length);static FLAC__bool read_metadata_seektable_(FLAC__StreamDecoder *decoder, FLAC__bool is_last, uint32_t length);static FLAC__bool read_metadata_vorbiscomment_(FLAC__StreamDecoder *decoder, FLAC__StreamMetadata_VorbisComment *obj, uint32_t length);static FLAC__bool read_metadata_cuesheet_(FLAC__StreamDecoder *decoder, FLAC__StreamMetadata_CueSheet *obj);static FLAC__bool read_metadata_picture_(FLAC__StreamDecoder *decoder, FLAC__StreamMetadata_Picture *obj);static FLAC__bool skip_id3v2_tag_(FLAC__StreamDecoder *decoder);static FLAC__bool frame_sync_(FLAC__StreamDecoder *decoder);static FLAC__bool read_frame_(FLAC__StreamDecoder *decoder, FLAC__bool *got_a_frame, FLAC__bool do_full_decode);static FLAC__bool read_frame_header_(FLAC__StreamDecoder *decoder);static FLAC__bool read_subframe_(FLAC__StreamDecoder *decoder, uint32_t channel, uint32_t bps, FLAC__bool do_full_decode);static FLAC__bool read_subframe_constant_(FLAC__StreamDecoder *decoder, uint32_t channel, uint32_t bps, FLAC__bool do_full_decode);static FLAC__bool read_subframe_fixed_(FLAC__StreamDecoder *decoder, uint32_t channel, uint32_t bps, const uint32_t order, FLAC__bool do_full_decode);static FLAC__bool read_subframe_lpc_(FLAC__StreamDecoder *decoder, uint32_t channel, uint32_t bps, const uint32_t order, FLAC__bool do_full_decode);static FLAC__bool read_subframe_verbatim_(FLAC__StreamDecoder *decoder, uint32_t channel, uint32_t bps, FLAC__bool do_full_decode);static FLAC__bool read_residual_partitioned_rice_(FLAC__StreamDecoder *decoder, uint32_t predictor_order, uint32_t partition_order, FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents, FLAC__int32 *residual, FLAC__bool is_extended);static FLAC__bool read_zero_padding_(FLAC__StreamDecoder *decoder);static void       undo_channel_coding(FLAC__StreamDecoder *decoder);static FLAC__bool read_callback_(FLAC__byte buffer[], size_t *bytes, void *client_data);#if FLAC__HAS_OGGstatic FLAC__StreamDecoderReadStatus read_callback_ogg_aspect_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes);static FLAC__OggDecoderAspectReadStatus read_callback_proxy_(const void *void_decoder, FLAC__byte buffer[], size_t *bytes, void *client_data);#endifstatic FLAC__StreamDecoderWriteStatus write_audio_frame_to_client_(FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[]);static void send_error_to_client_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status);static FLAC__bool seek_to_absolute_sample_(FLAC__StreamDecoder *decoder, FLAC__uint64 stream_length, FLAC__uint64 target_sample);#if FLAC__HAS_OGGstatic FLAC__bool seek_to_absolute_sample_ogg_(FLAC__StreamDecoder *decoder, FLAC__uint64 stream_length, FLAC__uint64 target_sample);#endifstatic FLAC__StreamDecoderReadStatus file_read_callback_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data);static FLAC__StreamDecoderSeekStatus file_seek_callback_(const FLAC__StreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data);static FLAC__StreamDecoderTellStatus file_tell_callback_(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data);static FLAC__StreamDecoderLengthStatus file_length_callback_(const FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data);static FLAC__bool file_eof_callback_(const FLAC__StreamDecoder *decoder, void *client_data); /*********************************************************************** * * Private class data * ***********************************************************************/ typedef struct FLAC__StreamDecoderPrivate {	FLAC__bool is_ogg;	FLAC__StreamDecoderReadCallback read_callback;	FLAC__StreamDecoderSeekCallback seek_callback;	FLAC__StreamDecoderTellCallback tell_callback;	FLAC__StreamDecoderLengthCallback length_callback;	FLAC__StreamDecoderEofCallback eof_callback;	FLAC__StreamDecoderWriteCallback write_callback;	FLAC__StreamDecoderMetadataCallback metadata_callback;	FLAC__StreamDecoderErrorCallback error_callback;	void *client_data;	FILE *file; /* only used if FLAC__stream_decoder_init_file()/FLAC__stream_decoder_init_file() called, else NULL */	FLAC__BitReader *input;	FLAC__int32 *output[FLAC__MAX_CHANNELS];	FLAC__int32 *residual[FLAC__MAX_CHANNELS]; /* WATCHOUT: these are the aligned pointers; the real pointers that should be free()'d are residual_unaligned[] below */	FLAC__int64 *side_subframe;	FLAC__bool side_subframe_in_use;	FLAC__EntropyCodingMethod_PartitionedRiceContents partitioned_rice_contents[FLAC__MAX_CHANNELS];	uint32_t output_capacity, output_channels;	FLAC__uint32 fixed_block_size, next_fixed_block_size;	FLAC__uint64 samples_decoded;	FLAC__bool has_stream_info, has_seek_table;	FLAC__StreamMetadata stream_info;	FLAC__StreamMetadata seek_table;	FLAC__bool metadata_filter[128]; /* MAGIC number 128 == total number of metadata block types == 1 << 7 */	FLAC__byte *metadata_filter_ids;	size_t metadata_filter_ids_count, metadata_filter_ids_capacity; /* units for both are IDs, not bytes */	FLAC__Frame frame;	FLAC__bool cached; /* true if there is a byte in lookahead */	FLAC__byte header_warmup[2]; /* contains the sync code and reserved bits */	FLAC__byte lookahead; /* temp storage when we need to look ahead one byte in the stream */	/* unaligned (original) pointers to allocated data */	FLAC__int32 *residual_unaligned[FLAC__MAX_CHANNELS];	FLAC__bool do_md5_checking; /* initially gets protected_->md5_checking but is turned off after a seek or if the metadata has a zero MD5 */	FLAC__bool internal_reset_hack; /* used only during init() so we can call reset to set up the decoder without rewinding the input */	FLAC__bool is_seeking;	FLAC__MD5Context md5context;	FLAC__byte computed_md5sum[16]; /* this is the sum we computed from the decoded data */	/* (the rest of these are only used for seeking) */	FLAC__Frame last_frame; /* holds the info of the last frame we decoded or seeked to */	FLAC__bool last_frame_is_set;	FLAC__uint64 first_frame_offset; /* hint to the seek routine of where in the stream the first audio frame starts */	FLAC__uint64 last_seen_framesync; /* if tell callback works, the location of the last seen frame sync code, to rewind to if needed */	FLAC__uint64 target_sample;	uint32_t unparseable_frame_count; /* used to tell whether we're decoding a future version of FLAC or just got a bad sync */	FLAC__bool got_a_frame; /* hack needed in Ogg FLAC seek routine to check when process_single() actually writes a frame */} FLAC__StreamDecoderPrivate; /*********************************************************************** * * Public static class data * ***********************************************************************/ FLAC_API const char * const FLAC__StreamDecoderStateString[] = {	"FLAC__STREAM_DECODER_SEARCH_FOR_METADATA",	"FLAC__STREAM_DECODER_READ_METADATA",	"FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC",	"FLAC__STREAM_DECODER_READ_FRAME",	"FLAC__STREAM_DECODER_END_OF_STREAM",	"FLAC__STREAM_DECODER_OGG_ERROR",	"FLAC__STREAM_DECODER_SEEK_ERROR",	"FLAC__STREAM_DECODER_ABORTED",	"FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR",	"FLAC__STREAM_DECODER_UNINITIALIZED"}; FLAC_API const char * const FLAC__StreamDecoderInitStatusString[] = {	"FLAC__STREAM_DECODER_INIT_STATUS_OK",	"FLAC__STREAM_DECODER_INIT_STATUS_UNSUPPORTED_CONTAINER",	"FLAC__STREAM_DECODER_INIT_STATUS_INVALID_CALLBACKS",	"FLAC__STREAM_DECODER_INIT_STATUS_MEMORY_ALLOCATION_ERROR",	"FLAC__STREAM_DECODER_INIT_STATUS_ERROR_OPENING_FILE",	"FLAC__STREAM_DECODER_INIT_STATUS_ALREADY_INITIALIZED"}; FLAC_API const char * const FLAC__StreamDecoderReadStatusString[] = {	"FLAC__STREAM_DECODER_READ_STATUS_CONTINUE",	"FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM",	"FLAC__STREAM_DECODER_READ_STATUS_ABORT"}; FLAC_API const char * const FLAC__StreamDecoderSeekStatusString[] = {	"FLAC__STREAM_DECODER_SEEK_STATUS_OK",	"FLAC__STREAM_DECODER_SEEK_STATUS_ERROR",	"FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED"}; FLAC_API const char * const FLAC__StreamDecoderTellStatusString[] = {	"FLAC__STREAM_DECODER_TELL_STATUS_OK",	"FLAC__STREAM_DECODER_TELL_STATUS_ERROR",	"FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED"}; FLAC_API const char * const FLAC__StreamDecoderLengthStatusString[] = {	"FLAC__STREAM_DECODER_LENGTH_STATUS_OK",	"FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR",	"FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED"}; FLAC_API const char * const FLAC__StreamDecoderWriteStatusString[] = {	"FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE",	"FLAC__STREAM_DECODER_WRITE_STATUS_ABORT"}; FLAC_API const char * const FLAC__StreamDecoderErrorStatusString[] = {	"FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC",	"FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER",	"FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH",	"FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM",	"FLAC__STREAM_DECODER_ERROR_STATUS_BAD_METADATA"}; /*********************************************************************** * * Class constructor/destructor * ***********************************************************************/FLAC_API FLAC__StreamDecoder *FLAC__stream_decoder_new(void){	FLAC__StreamDecoder *decoder;	uint32_t i; 	FLAC__ASSERT(sizeof(int) >= 4); /* we want to die right away if this is not true */ 	decoder = calloc(1, sizeof(FLAC__StreamDecoder));	if(decoder == 0) {		return 0;	} 	decoder->protected_ = calloc(1, sizeof(FLAC__StreamDecoderProtected));	if(decoder->protected_ == 0) {		free(decoder);		return 0;	} 	decoder->private_ = calloc(1, sizeof(FLAC__StreamDecoderPrivate));	if(decoder->private_ == 0) {		free(decoder->protected_);		free(decoder);		return 0;	} 	decoder->private_->input = FLAC__bitreader_new();	if(decoder->private_->input == 0) {		free(decoder->private_);		free(decoder->protected_);		free(decoder);		return 0;	} 	decoder->private_->metadata_filter_ids_capacity = 16;	if(0 == (decoder->private_->metadata_filter_ids = malloc((FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) * decoder->private_->metadata_filter_ids_capacity))) {		FLAC__bitreader_delete(decoder->private_->input);		free(decoder->private_);		free(decoder->protected_);		free(decoder);		return 0;	} 	for(i = 0; i < FLAC__MAX_CHANNELS; i++) {		decoder->private_->output[i] = 0;		decoder->private_->residual_unaligned[i] = decoder->private_->residual[i] = 0;	} 	decoder->private_->side_subframe = 0; 	decoder->private_->output_capacity = 0;	decoder->private_->output_channels = 0;	decoder->private_->has_seek_table = false; 	for(i = 0; i < FLAC__MAX_CHANNELS; i++)		FLAC__format_entropy_coding_method_partitioned_rice_contents_init(&decoder->private_->partitioned_rice_contents[i]); 	decoder->private_->file = 0; 	set_defaults_(decoder); 	decoder->protected_->state = FLAC__STREAM_DECODER_UNINITIALIZED; 	return decoder;} FLAC_API void FLAC__stream_decoder_delete(FLAC__StreamDecoder *decoder){	uint32_t i; 	if (decoder == NULL)		return ; 	FLAC__ASSERT(0 != decoder->protected_);	FLAC__ASSERT(0 != decoder->private_);	FLAC__ASSERT(0 != decoder->private_->input); 	(void)FLAC__stream_decoder_finish(decoder); 	if(0 != decoder->private_->metadata_filter_ids)		free(decoder->private_->metadata_filter_ids); 	FLAC__bitreader_delete(decoder->private_->input); 	for(i = 0; i < FLAC__MAX_CHANNELS; i++)		FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(&decoder->private_->partitioned_rice_contents[i]); 	free(decoder->private_);	free(decoder->protected_);	free(decoder);} /*********************************************************************** * * Public class methods * ***********************************************************************/ static FLAC__StreamDecoderInitStatus init_stream_internal_(	FLAC__StreamDecoder *decoder,	FLAC__StreamDecoderReadCallback read_callback,	FLAC__StreamDecoderSeekCallback seek_callback,	FLAC__StreamDecoderTellCallback tell_callback,	FLAC__StreamDecoderLengthCallback length_callback,	FLAC__StreamDecoderEofCallback eof_callback,	FLAC__StreamDecoderWriteCallback write_callback,	FLAC__StreamDecoderMetadataCallback metadata_callback,	FLAC__StreamDecoderErrorCallback error_callback,	void *client_data,	FLAC__bool is_ogg){	FLAC__ASSERT(0 != decoder); 	if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED)		return FLAC__STREAM_DECODER_INIT_STATUS_ALREADY_INITIALIZED; 	if(FLAC__HAS_OGG == 0 && is_ogg)		return FLAC__STREAM_DECODER_INIT_STATUS_UNSUPPORTED_CONTAINER; 	if(		0 == read_callback ||		0 == write_callback ||		0 == error_callback ||		(seek_callback && (0 == tell_callback || 0 == length_callback || 0 == eof_callback))	)		return FLAC__STREAM_DECODER_INIT_STATUS_INVALID_CALLBACKS; #if FLAC__HAS_OGG	decoder->private_->is_ogg = is_ogg;	if(is_ogg && !FLAC__ogg_decoder_aspect_init(&decoder->protected_->ogg_decoder_aspect))		return decoder->protected_->initstate = FLAC__STREAM_DECODER_INIT_STATUS_ERROR_OPENING_FILE;#endif 	/* from here on, errors are fatal */ 	if(!FLAC__bitreader_init(decoder->private_->input, read_callback_, decoder)) {		decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;		return FLAC__STREAM_DECODER_INIT_STATUS_MEMORY_ALLOCATION_ERROR;	} 	decoder->private_->read_callback = read_callback;	decoder->private_->seek_callback = seek_callback;	decoder->private_->tell_callback = tell_callback;	decoder->private_->length_callback = length_callback;	decoder->private_->eof_callback = eof_callback;	decoder->private_->write_callback = write_callback;	decoder->private_->metadata_callback = metadata_callback;	decoder->private_->error_callback = error_callback;	decoder->private_->client_data = client_data;	decoder->private_->fixed_block_size = decoder->private_->next_fixed_block_size = 0;	decoder->private_->samples_decoded = 0;	decoder->private_->has_stream_info = false;	decoder->private_->cached = false; 	decoder->private_->do_md5_checking = decoder->protected_->md5_checking;	decoder->private_->is_seeking = false; 	decoder->private_->internal_reset_hack = true; /* so the following reset does not try to rewind the input */	if(!FLAC__stream_decoder_reset(decoder)) {		/* above call sets the state for us */		return FLAC__STREAM_DECODER_INIT_STATUS_MEMORY_ALLOCATION_ERROR;	} 	return FLAC__STREAM_DECODER_INIT_STATUS_OK;} FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_stream(	FLAC__StreamDecoder *decoder,	FLAC__StreamDecoderReadCallback read_callback,	FLAC__StreamDecoderSeekCallback seek_callback,	FLAC__StreamDecoderTellCallback tell_callback,	FLAC__StreamDecoderLengthCallback length_callback,	FLAC__StreamDecoderEofCallback eof_callback,	FLAC__StreamDecoderWriteCallback write_callback,	FLAC__StreamDecoderMetadataCallback metadata_callback,	FLAC__StreamDecoderErrorCallback error_callback,	void *client_data){	return init_stream_internal_(		decoder,		read_callback,		seek_callback,		tell_callback,		length_callback,		eof_callback,		write_callback,		metadata_callback,		error_callback,		client_data,		/*is_ogg=*/false	);} FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_ogg_stream(	FLAC__StreamDecoder *decoder,	FLAC__StreamDecoderReadCallback read_callback,	FLAC__StreamDecoderSeekCallback seek_callback,	FLAC__StreamDecoderTellCallback tell_callback,	FLAC__StreamDecoderLengthCallback length_callback,	FLAC__StreamDecoderEofCallback eof_callback,	FLAC__StreamDecoderWriteCallback write_callback,	FLAC__StreamDecoderMetadataCallback metadata_callback,	FLAC__StreamDecoderErrorCallback error_callback,	void *client_data){	return init_stream_internal_(		decoder,		read_callback,		seek_callback,		tell_callback,		length_callback,		eof_callback,		write_callback,		metadata_callback,		error_callback,		client_data,		/*is_ogg=*/true	);} static FLAC__StreamDecoderInitStatus init_FILE_internal_(	FLAC__StreamDecoder *decoder,	FILE *file,	FLAC__StreamDecoderWriteCallback write_callback,	FLAC__StreamDecoderMetadataCallback metadata_callback,	FLAC__StreamDecoderErrorCallback error_callback,	void *client_data,	FLAC__bool is_ogg){	FLAC__ASSERT(0 != decoder);	FLAC__ASSERT(0 != file); 	if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED)		return decoder->protected_->initstate = FLAC__STREAM_DECODER_INIT_STATUS_ALREADY_INITIALIZED; 	if(0 == write_callback || 0 == error_callback)		return decoder->protected_->initstate = FLAC__STREAM_DECODER_INIT_STATUS_INVALID_CALLBACKS; 	/*	 * To make sure that our file does not go unclosed after an error, we	 * must assign the FILE pointer before any further error can occur in	 * this routine.	 */	if(file == stdin)		file = get_binary_stdin_(); /* just to be safe */ 	decoder->private_->file = file; 	return init_stream_internal_(		decoder,		file_read_callback_,		decoder->private_->file == stdin? 0: file_seek_callback_,		decoder->private_->file == stdin? 0: file_tell_callback_,		decoder->private_->file == stdin? 0: file_length_callback_,		file_eof_callback_,		write_callback,		metadata_callback,		error_callback,		client_data,

Lines 1–500 of 3685.