/* 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. Load more
/* 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_OGG static 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); #endif static 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_OGG static FLAC__bool seek_to_absolute_sample_ogg_(FLAC__StreamDecoder *decoder, FLAC__uint64 stream_length, FLAC__uint64 target_sample); #endif static 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,