Torque3D/Engine/lib/flac/src/libFLAC/stream_decoder.c
marauder2k7 a745fc3757 Initial commit
added libraries:
opus
flac
libsndfile

updated:
libvorbis
libogg
openal

- Everything works as expected for now. Bare in mind libsndfile needed the check for whether or not it could find the xiph libraries removed in order for this to work.
2024-03-21 17:33:47 +00:00

3731 lines
145 KiB
C

/* libFLAC - Free Lossless Audio Codec library
* Copyright (C) 2000-2009 Josh Coalson
* Copyright (C) 2011-2023 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/types.h> /* for off_t */
#include <sys/stat.h> /* for stat() */
#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/cpu.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__CPUInfo cpuinfo;
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__bool (*local_bitreader_read_rice_signed_block)(FLAC__BitReader *br, int vals[], uint32_t nvals, uint32_t parameter);
} 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
FLAC__cpu_info(&decoder->private_->cpuinfo);
decoder->private_->local_bitreader_read_rice_signed_block = FLAC__bitreader_read_rice_signed_block;
#ifdef FLAC__BMI2_SUPPORTED
if (decoder->private_->cpuinfo.x86.bmi2) {
decoder->private_->local_bitreader_read_rice_signed_block = FLAC__bitreader_read_rice_signed_block_bmi2;
}
#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,
is_ogg
);
}
FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_FILE(
FLAC__StreamDecoder *decoder,
FILE *file,
FLAC__StreamDecoderWriteCallback write_callback,
FLAC__StreamDecoderMetadataCallback metadata_callback,
FLAC__StreamDecoderErrorCallback error_callback,
void *client_data
)
{
return init_FILE_internal_(decoder, file, write_callback, metadata_callback, error_callback, client_data, /*is_ogg=*/false);
}
FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_ogg_FILE(
FLAC__StreamDecoder *decoder,
FILE *file,
FLAC__StreamDecoderWriteCallback write_callback,
FLAC__StreamDecoderMetadataCallback metadata_callback,
FLAC__StreamDecoderErrorCallback error_callback,
void *client_data
)
{
return init_FILE_internal_(decoder, file, write_callback, metadata_callback, error_callback, client_data, /*is_ogg=*/true);
}
static FLAC__StreamDecoderInitStatus init_file_internal_(
FLAC__StreamDecoder *decoder,
const char *filename,
FLAC__StreamDecoderWriteCallback write_callback,
FLAC__StreamDecoderMetadataCallback metadata_callback,
FLAC__StreamDecoderErrorCallback error_callback,
void *client_data,
FLAC__bool is_ogg
)
{
FILE *file;
FLAC__ASSERT(0 != decoder);
/*
* To make sure that our file does not go unclosed after an error, we
* have to do the same entrance checks here that are later performed
* in FLAC__stream_decoder_init_FILE() before the FILE* is assigned.
*/
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;
file = filename? flac_fopen(filename, "rb") : stdin;
if(0 == file)
return FLAC__STREAM_DECODER_INIT_STATUS_ERROR_OPENING_FILE;
return init_FILE_internal_(decoder, file, write_callback, metadata_callback, error_callback, client_data, is_ogg);
}
FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_file(
FLAC__StreamDecoder *decoder,
const char *filename,
FLAC__StreamDecoderWriteCallback write_callback,
FLAC__StreamDecoderMetadataCallback metadata_callback,
FLAC__StreamDecoderErrorCallback error_callback,
void *client_data
)
{
return init_file_internal_(decoder, filename, write_callback, metadata_callback, error_callback, client_data, /*is_ogg=*/false);
}
FLAC_API FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_ogg_file(
FLAC__StreamDecoder *decoder,
const char *filename,
FLAC__StreamDecoderWriteCallback write_callback,
FLAC__StreamDecoderMetadataCallback metadata_callback,
FLAC__StreamDecoderErrorCallback error_callback,
void *client_data
)
{
return init_file_internal_(decoder, filename, write_callback, metadata_callback, error_callback, client_data, /*is_ogg=*/true);
}
FLAC_API FLAC__bool FLAC__stream_decoder_finish(FLAC__StreamDecoder *decoder)
{
FLAC__bool md5_failed = false;
uint32_t i;
FLAC__ASSERT(0 != decoder);
FLAC__ASSERT(0 != decoder->private_);
FLAC__ASSERT(0 != decoder->protected_);
if(decoder->protected_->state == FLAC__STREAM_DECODER_UNINITIALIZED)
return true;
/* see the comment in FLAC__stream_decoder_reset() as to why we
* always call FLAC__MD5Final()
*/
FLAC__MD5Final(decoder->private_->computed_md5sum, &decoder->private_->md5context);
free(decoder->private_->seek_table.data.seek_table.points);
decoder->private_->seek_table.data.seek_table.points = 0;
decoder->private_->has_seek_table = false;
FLAC__bitreader_free(decoder->private_->input);
for(i = 0; i < FLAC__MAX_CHANNELS; i++) {
/* WATCHOUT:
* FLAC__lpc_restore_signal_asm_ia32_mmx() and ..._intrin_sseN()
* require that the output arrays have a buffer of up to 3 zeroes
* in front (at negative indices) for alignment purposes;
* we use 4 to keep the data well-aligned.
*/
if(0 != decoder->private_->output[i]) {
free(decoder->private_->output[i]-4);
decoder->private_->output[i] = 0;
}
if(0 != decoder->private_->residual_unaligned[i]) {
free(decoder->private_->residual_unaligned[i]);
decoder->private_->residual_unaligned[i] = decoder->private_->residual[i] = 0;
}
}
if(0 != decoder->private_->side_subframe) {
free(decoder->private_->side_subframe);
decoder->private_->side_subframe = 0;
}
decoder->private_->output_capacity = 0;
decoder->private_->output_channels = 0;
#if FLAC__HAS_OGG
if(decoder->private_->is_ogg)
FLAC__ogg_decoder_aspect_finish(&decoder->protected_->ogg_decoder_aspect);
#endif
if(0 != decoder->private_->file) {
if(decoder->private_->file != stdin)
fclose(decoder->private_->file);
decoder->private_->file = 0;
}
if(decoder->private_->do_md5_checking) {
if(memcmp(decoder->private_->stream_info.data.stream_info.md5sum, decoder->private_->computed_md5sum, 16))
md5_failed = true;
}
decoder->private_->is_seeking = false;
set_defaults_(decoder);
decoder->protected_->state = FLAC__STREAM_DECODER_UNINITIALIZED;
return !md5_failed;
}
FLAC_API FLAC__bool FLAC__stream_decoder_set_ogg_serial_number(FLAC__StreamDecoder *decoder, long value)
{
FLAC__ASSERT(0 != decoder);
FLAC__ASSERT(0 != decoder->private_);
FLAC__ASSERT(0 != decoder->protected_);
if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED)
return false;
#if FLAC__HAS_OGG
/* can't check decoder->private_->is_ogg since that's not set until init time */
FLAC__ogg_decoder_aspect_set_serial_number(&decoder->protected_->ogg_decoder_aspect, value);
return true;
#else
(void)value;
return false;
#endif
}
FLAC_API FLAC__bool FLAC__stream_decoder_set_md5_checking(FLAC__StreamDecoder *decoder, FLAC__bool value)
{
FLAC__ASSERT(0 != decoder);
FLAC__ASSERT(0 != decoder->protected_);
if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED)
return false;
decoder->protected_->md5_checking = value;
return true;
}
FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_respond(FLAC__StreamDecoder *decoder, FLAC__MetadataType type)
{
FLAC__ASSERT(0 != decoder);
FLAC__ASSERT(0 != decoder->private_);
FLAC__ASSERT(0 != decoder->protected_);
FLAC__ASSERT((uint32_t)type <= FLAC__MAX_METADATA_TYPE_CODE);
/* double protection */
if((uint32_t)type > FLAC__MAX_METADATA_TYPE_CODE)
return false;
if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED)
return false;
decoder->private_->metadata_filter[type] = true;
if(type == FLAC__METADATA_TYPE_APPLICATION)
decoder->private_->metadata_filter_ids_count = 0;
return true;
}
FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_respond_application(FLAC__StreamDecoder *decoder, const FLAC__byte id[4])
{
FLAC__ASSERT(0 != decoder);
FLAC__ASSERT(0 != decoder->private_);
FLAC__ASSERT(0 != decoder->protected_);
FLAC__ASSERT(0 != id);
if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED)
return false;
if(decoder->private_->metadata_filter[FLAC__METADATA_TYPE_APPLICATION])
return true;
FLAC__ASSERT(0 != decoder->private_->metadata_filter_ids);
if(decoder->private_->metadata_filter_ids_count == decoder->private_->metadata_filter_ids_capacity) {
if(0 == (decoder->private_->metadata_filter_ids = safe_realloc_mul_2op_(decoder->private_->metadata_filter_ids, decoder->private_->metadata_filter_ids_capacity, /*times*/2))) {
decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
return false;
}
decoder->private_->metadata_filter_ids_capacity *= 2;
}
memcpy(decoder->private_->metadata_filter_ids + decoder->private_->metadata_filter_ids_count * (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), id, (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
decoder->private_->metadata_filter_ids_count++;
return true;
}
FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_respond_all(FLAC__StreamDecoder *decoder)
{
uint32_t i;
FLAC__ASSERT(0 != decoder);
FLAC__ASSERT(0 != decoder->private_);
FLAC__ASSERT(0 != decoder->protected_);
if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED)
return false;
for(i = 0; i < sizeof(decoder->private_->metadata_filter) / sizeof(decoder->private_->metadata_filter[0]); i++)
decoder->private_->metadata_filter[i] = true;
decoder->private_->metadata_filter_ids_count = 0;
return true;
}
FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_ignore(FLAC__StreamDecoder *decoder, FLAC__MetadataType type)
{
FLAC__ASSERT(0 != decoder);
FLAC__ASSERT(0 != decoder->private_);
FLAC__ASSERT(0 != decoder->protected_);
FLAC__ASSERT((uint32_t)type <= FLAC__MAX_METADATA_TYPE_CODE);
/* double protection */
if((uint32_t)type > FLAC__MAX_METADATA_TYPE_CODE)
return false;
if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED)
return false;
decoder->private_->metadata_filter[type] = false;
if(type == FLAC__METADATA_TYPE_APPLICATION)
decoder->private_->metadata_filter_ids_count = 0;
return true;
}
FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_ignore_application(FLAC__StreamDecoder *decoder, const FLAC__byte id[4])
{
FLAC__ASSERT(0 != decoder);
FLAC__ASSERT(0 != decoder->private_);
FLAC__ASSERT(0 != decoder->protected_);
FLAC__ASSERT(0 != id);
if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED)
return false;
if(!decoder->private_->metadata_filter[FLAC__METADATA_TYPE_APPLICATION])
return true;
FLAC__ASSERT(0 != decoder->private_->metadata_filter_ids);
if(decoder->private_->metadata_filter_ids_count == decoder->private_->metadata_filter_ids_capacity) {
if(0 == (decoder->private_->metadata_filter_ids = safe_realloc_mul_2op_(decoder->private_->metadata_filter_ids, decoder->private_->metadata_filter_ids_capacity, /*times*/2))) {
decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
return false;
}
decoder->private_->metadata_filter_ids_capacity *= 2;
}
memcpy(decoder->private_->metadata_filter_ids + decoder->private_->metadata_filter_ids_count * (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), id, (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8));
decoder->private_->metadata_filter_ids_count++;
return true;
}
FLAC_API FLAC__bool FLAC__stream_decoder_set_metadata_ignore_all(FLAC__StreamDecoder *decoder)
{
FLAC__ASSERT(0 != decoder);
FLAC__ASSERT(0 != decoder->private_);
FLAC__ASSERT(0 != decoder->protected_);
if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED)
return false;
memset(decoder->private_->metadata_filter, 0, sizeof(decoder->private_->metadata_filter));
decoder->private_->metadata_filter_ids_count = 0;
return true;
}
FLAC_API FLAC__StreamDecoderState FLAC__stream_decoder_get_state(const FLAC__StreamDecoder *decoder)
{
FLAC__ASSERT(0 != decoder);
FLAC__ASSERT(0 != decoder->protected_);
return decoder->protected_->state;
}
FLAC_API const char *FLAC__stream_decoder_get_resolved_state_string(const FLAC__StreamDecoder *decoder)
{
return FLAC__StreamDecoderStateString[decoder->protected_->state];
}
FLAC_API FLAC__bool FLAC__stream_decoder_get_md5_checking(const FLAC__StreamDecoder *decoder)
{
FLAC__ASSERT(0 != decoder);
FLAC__ASSERT(0 != decoder->protected_);
return decoder->protected_->md5_checking;
}
FLAC_API FLAC__uint64 FLAC__stream_decoder_get_total_samples(const FLAC__StreamDecoder *decoder)
{
FLAC__ASSERT(0 != decoder);
FLAC__ASSERT(0 != decoder->protected_);
return decoder->private_->has_stream_info? decoder->private_->stream_info.data.stream_info.total_samples : 0;
}
FLAC_API uint32_t FLAC__stream_decoder_get_channels(const FLAC__StreamDecoder *decoder)
{
FLAC__ASSERT(0 != decoder);
FLAC__ASSERT(0 != decoder->protected_);
return decoder->protected_->channels;
}
FLAC_API FLAC__ChannelAssignment FLAC__stream_decoder_get_channel_assignment(const FLAC__StreamDecoder *decoder)
{
FLAC__ASSERT(0 != decoder);
FLAC__ASSERT(0 != decoder->protected_);
return decoder->protected_->channel_assignment;
}
FLAC_API uint32_t FLAC__stream_decoder_get_bits_per_sample(const FLAC__StreamDecoder *decoder)
{
FLAC__ASSERT(0 != decoder);
FLAC__ASSERT(0 != decoder->protected_);
return decoder->protected_->bits_per_sample;
}
FLAC_API uint32_t FLAC__stream_decoder_get_sample_rate(const FLAC__StreamDecoder *decoder)
{
FLAC__ASSERT(0 != decoder);
FLAC__ASSERT(0 != decoder->protected_);
return decoder->protected_->sample_rate;
}
FLAC_API uint32_t FLAC__stream_decoder_get_blocksize(const FLAC__StreamDecoder *decoder)
{
FLAC__ASSERT(0 != decoder);
FLAC__ASSERT(0 != decoder->protected_);
return decoder->protected_->blocksize;
}
FLAC_API FLAC__bool FLAC__stream_decoder_get_decode_position(const FLAC__StreamDecoder *decoder, FLAC__uint64 *position)
{
FLAC__ASSERT(0 != decoder);
FLAC__ASSERT(0 != decoder->private_);
FLAC__ASSERT(0 != position);
if(FLAC__HAS_OGG && decoder->private_->is_ogg)
return false;
if(0 == decoder->private_->tell_callback)
return false;
if(decoder->private_->tell_callback(decoder, position, decoder->private_->client_data) != FLAC__STREAM_DECODER_TELL_STATUS_OK)
return false;
/* should never happen since all FLAC frames and metadata blocks are byte aligned, but check just in case */
if(!FLAC__bitreader_is_consumed_byte_aligned(decoder->private_->input))
return false;
FLAC__ASSERT(*position >= FLAC__stream_decoder_get_input_bytes_unconsumed(decoder));
*position -= FLAC__stream_decoder_get_input_bytes_unconsumed(decoder);
return true;
}
FLAC_API const void *FLAC__stream_decoder_get_client_data(FLAC__StreamDecoder *decoder)
{
return decoder->private_->client_data;
}
FLAC_API FLAC__bool FLAC__stream_decoder_flush(FLAC__StreamDecoder *decoder)
{
FLAC__ASSERT(0 != decoder);
FLAC__ASSERT(0 != decoder->private_);
FLAC__ASSERT(0 != decoder->protected_);
if(!decoder->private_->internal_reset_hack && decoder->protected_->state == FLAC__STREAM_DECODER_UNINITIALIZED)
return false;
decoder->private_->samples_decoded = 0;
decoder->private_->do_md5_checking = false;
decoder->private_->last_seen_framesync = 0;
decoder->private_->last_frame_is_set = false;
#if FLAC__HAS_OGG
if(decoder->private_->is_ogg)
FLAC__ogg_decoder_aspect_flush(&decoder->protected_->ogg_decoder_aspect);
#endif
if(!FLAC__bitreader_clear(decoder->private_->input)) {
decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
return false;
}
decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
return true;
}
FLAC_API FLAC__bool FLAC__stream_decoder_reset(FLAC__StreamDecoder *decoder)
{
FLAC__ASSERT(0 != decoder);
FLAC__ASSERT(0 != decoder->private_);
FLAC__ASSERT(0 != decoder->protected_);
if(!FLAC__stream_decoder_flush(decoder)) {
/* above call sets the state for us */
return false;
}
#if FLAC__HAS_OGG
/*@@@ could go in !internal_reset_hack block below */
if(decoder->private_->is_ogg)
FLAC__ogg_decoder_aspect_reset(&decoder->protected_->ogg_decoder_aspect);
#endif
/* Rewind if necessary. If FLAC__stream_decoder_init() is calling us,
* (internal_reset_hack) don't try to rewind since we are already at
* the beginning of the stream and don't want to fail if the input is
* not seekable.
*/
if(!decoder->private_->internal_reset_hack) {
if(decoder->private_->file == stdin)
return false; /* can't rewind stdin, reset fails */
if(decoder->private_->seek_callback && decoder->private_->seek_callback(decoder, 0, decoder->private_->client_data) == FLAC__STREAM_DECODER_SEEK_STATUS_ERROR)
return false; /* seekable and seek fails, reset fails */
}
decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_METADATA;
decoder->private_->has_stream_info = false;
free(decoder->private_->seek_table.data.seek_table.points);
decoder->private_->seek_table.data.seek_table.points = 0;
decoder->private_->has_seek_table = false;
decoder->private_->do_md5_checking = decoder->protected_->md5_checking;
/*
* This goes in reset() and not flush() because according to the spec, a
* fixed-blocksize stream must stay that way through the whole stream.
*/
decoder->private_->fixed_block_size = decoder->private_->next_fixed_block_size = 0;
/* We initialize the FLAC__MD5Context even though we may never use it. This
* is because md5 checking may be turned on to start and then turned off if
* a seek occurs. So we init the context here and finalize it in
* FLAC__stream_decoder_finish() to make sure things are always cleaned up
* properly.
*/
if(!decoder->private_->internal_reset_hack) {
/* Only finish MD5 context when it has been initialized
* (i.e. when internal_reset_hack is not set) */
FLAC__MD5Final(decoder->private_->computed_md5sum, &decoder->private_->md5context);
}
else
decoder->private_->internal_reset_hack = false;
FLAC__MD5Init(&decoder->private_->md5context);
decoder->private_->first_frame_offset = 0;
decoder->private_->unparseable_frame_count = 0;
decoder->private_->last_seen_framesync = 0;
decoder->private_->last_frame_is_set = false;
return true;
}
FLAC_API FLAC__bool FLAC__stream_decoder_process_single(FLAC__StreamDecoder *decoder)
{
FLAC__bool got_a_frame;
FLAC__ASSERT(0 != decoder);
FLAC__ASSERT(0 != decoder->protected_);
while(1) {
switch(decoder->protected_->state) {
case FLAC__STREAM_DECODER_SEARCH_FOR_METADATA:
if(!find_metadata_(decoder))
return false; /* above function sets the status for us */
break;
case FLAC__STREAM_DECODER_READ_METADATA:
if(!read_metadata_(decoder))
return false; /* above function sets the status for us */
else
return true;
case FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC:
if(!frame_sync_(decoder))
return true; /* above function sets the status for us */
break;
case FLAC__STREAM_DECODER_READ_FRAME:
if(!read_frame_(decoder, &got_a_frame, /*do_full_decode=*/true))
return false; /* above function sets the status for us */
if(got_a_frame)
return true; /* above function sets the status for us */
break;
case FLAC__STREAM_DECODER_END_OF_STREAM:
case FLAC__STREAM_DECODER_ABORTED:
return true;
default:
return false;
}
}
}
FLAC_API FLAC__bool FLAC__stream_decoder_process_until_end_of_metadata(FLAC__StreamDecoder *decoder)
{
FLAC__ASSERT(0 != decoder);
FLAC__ASSERT(0 != decoder->protected_);
while(1) {
switch(decoder->protected_->state) {
case FLAC__STREAM_DECODER_SEARCH_FOR_METADATA:
if(!find_metadata_(decoder))
return false; /* above function sets the status for us */
break;
case FLAC__STREAM_DECODER_READ_METADATA:
if(!read_metadata_(decoder))
return false; /* above function sets the status for us */
break;
case FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC:
case FLAC__STREAM_DECODER_READ_FRAME:
case FLAC__STREAM_DECODER_END_OF_STREAM:
case FLAC__STREAM_DECODER_ABORTED:
return true;
default:
return false;
}
}
}
FLAC_API FLAC__bool FLAC__stream_decoder_process_until_end_of_stream(FLAC__StreamDecoder *decoder)
{
FLAC__bool dummy;
FLAC__ASSERT(0 != decoder);
FLAC__ASSERT(0 != decoder->protected_);
while(1) {
switch(decoder->protected_->state) {
case FLAC__STREAM_DECODER_SEARCH_FOR_METADATA:
if(!find_metadata_(decoder))
return false; /* above function sets the status for us */
break;
case FLAC__STREAM_DECODER_READ_METADATA:
if(!read_metadata_(decoder))
return false; /* above function sets the status for us */
break;
case FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC:
if(!frame_sync_(decoder))
return true; /* above function sets the status for us */
break;
case FLAC__STREAM_DECODER_READ_FRAME:
if(!read_frame_(decoder, &dummy, /*do_full_decode=*/true))
return false; /* above function sets the status for us */
break;
case FLAC__STREAM_DECODER_END_OF_STREAM:
case FLAC__STREAM_DECODER_ABORTED:
return true;
default:
return false;
}
}
}
FLAC_API FLAC__bool FLAC__stream_decoder_skip_single_frame(FLAC__StreamDecoder *decoder)
{
FLAC__bool got_a_frame;
FLAC__ASSERT(0 != decoder);
FLAC__ASSERT(0 != decoder->protected_);
while(1) {
switch(decoder->protected_->state) {
case FLAC__STREAM_DECODER_SEARCH_FOR_METADATA:
case FLAC__STREAM_DECODER_READ_METADATA:
return false; /* above function sets the status for us */
case FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC:
if(!frame_sync_(decoder))
return true; /* above function sets the status for us */
break;
case FLAC__STREAM_DECODER_READ_FRAME:
if(!read_frame_(decoder, &got_a_frame, /*do_full_decode=*/false))
return false; /* above function sets the status for us */
if(got_a_frame)
return true; /* above function sets the status for us */
break;
case FLAC__STREAM_DECODER_END_OF_STREAM:
case FLAC__STREAM_DECODER_ABORTED:
return true;
default:
return false;
}
}
}
FLAC_API FLAC__bool FLAC__stream_decoder_seek_absolute(FLAC__StreamDecoder *decoder, FLAC__uint64 sample)
{
FLAC__uint64 length;
FLAC__ASSERT(0 != decoder);
if(
decoder->protected_->state != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA &&
decoder->protected_->state != FLAC__STREAM_DECODER_READ_METADATA &&
decoder->protected_->state != FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC &&
decoder->protected_->state != FLAC__STREAM_DECODER_READ_FRAME &&
decoder->protected_->state != FLAC__STREAM_DECODER_END_OF_STREAM
)
return false;
if(0 == decoder->private_->seek_callback)
return false;
FLAC__ASSERT(decoder->private_->seek_callback);
FLAC__ASSERT(decoder->private_->tell_callback);
FLAC__ASSERT(decoder->private_->length_callback);
FLAC__ASSERT(decoder->private_->eof_callback);
if(FLAC__stream_decoder_get_total_samples(decoder) > 0 && sample >= FLAC__stream_decoder_get_total_samples(decoder))
return false;
decoder->private_->is_seeking = true;
/* turn off md5 checking if a seek is attempted */
decoder->private_->do_md5_checking = false;
/* get the file length (currently our algorithm needs to know the length so it's also an error to get FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED) */
if(decoder->private_->length_callback(decoder, &length, decoder->private_->client_data) != FLAC__STREAM_DECODER_LENGTH_STATUS_OK) {
decoder->private_->is_seeking = false;
return false;
}
/* if we haven't finished processing the metadata yet, do that so we have the STREAMINFO, SEEK_TABLE, and first_frame_offset */
if(
decoder->protected_->state == FLAC__STREAM_DECODER_SEARCH_FOR_METADATA ||
decoder->protected_->state == FLAC__STREAM_DECODER_READ_METADATA
) {
if(!FLAC__stream_decoder_process_until_end_of_metadata(decoder)) {
/* above call sets the state for us */
decoder->private_->is_seeking = false;
return false;
}
/* check this again in case we didn't know total_samples the first time */
if(FLAC__stream_decoder_get_total_samples(decoder) > 0 && sample >= FLAC__stream_decoder_get_total_samples(decoder)) {
decoder->private_->is_seeking = false;
return false;
}
}
{
const FLAC__bool ok =
#if FLAC__HAS_OGG
decoder->private_->is_ogg?
seek_to_absolute_sample_ogg_(decoder, length, sample) :
#endif
seek_to_absolute_sample_(decoder, length, sample)
;
decoder->private_->is_seeking = false;
return ok;
}
}
/***********************************************************************
*
* Protected class methods
*
***********************************************************************/
uint32_t FLAC__stream_decoder_get_input_bytes_unconsumed(const FLAC__StreamDecoder *decoder)
{
FLAC__ASSERT(0 != decoder);
FLAC__ASSERT(FLAC__bitreader_is_consumed_byte_aligned(decoder->private_->input));
FLAC__ASSERT(!(FLAC__bitreader_get_input_bits_unconsumed(decoder->private_->input) & 7));
return FLAC__bitreader_get_input_bits_unconsumed(decoder->private_->input) / 8;
}
/***********************************************************************
*
* Private class methods
*
***********************************************************************/
void set_defaults_(FLAC__StreamDecoder *decoder)
{
decoder->private_->is_ogg = false;
decoder->private_->read_callback = 0;
decoder->private_->seek_callback = 0;
decoder->private_->tell_callback = 0;
decoder->private_->length_callback = 0;
decoder->private_->eof_callback = 0;
decoder->private_->write_callback = 0;
decoder->private_->metadata_callback = 0;
decoder->private_->error_callback = 0;
decoder->private_->client_data = 0;
memset(decoder->private_->metadata_filter, 0, sizeof(decoder->private_->metadata_filter));
decoder->private_->metadata_filter[FLAC__METADATA_TYPE_STREAMINFO] = true;
decoder->private_->metadata_filter_ids_count = 0;
decoder->protected_->md5_checking = false;
#if FLAC__HAS_OGG
FLAC__ogg_decoder_aspect_set_defaults(&decoder->protected_->ogg_decoder_aspect);
#endif
}
/*
* This will forcibly set stdin to binary mode (for OSes that require it)
*/
FILE *get_binary_stdin_(void)
{
/* if something breaks here it is probably due to the presence or
* absence of an underscore before the identifiers 'setmode',
* 'fileno', and/or 'O_BINARY'; check your system header files.
*/
#if defined _MSC_VER || defined __MINGW32__
_setmode(_fileno(stdin), _O_BINARY);
#elif defined __EMX__
setmode(fileno(stdin), O_BINARY);
#endif
return stdin;
}
FLAC__bool allocate_output_(FLAC__StreamDecoder *decoder, uint32_t size, uint32_t channels, uint32_t bps)
{
uint32_t i;
FLAC__int32 *tmp;
if(size <= decoder->private_->output_capacity && channels <= decoder->private_->output_channels &&
(bps < 32 || decoder->private_->side_subframe != 0))
return true;
/* simply using realloc() is not practical because the number of channels may change mid-stream */
for(i = 0; i < FLAC__MAX_CHANNELS; i++) {
if(0 != decoder->private_->output[i]) {
free(decoder->private_->output[i]-4);
decoder->private_->output[i] = 0;
}
if(0 != decoder->private_->residual_unaligned[i]) {
free(decoder->private_->residual_unaligned[i]);
decoder->private_->residual_unaligned[i] = decoder->private_->residual[i] = 0;
}
}
if(0 != decoder->private_->side_subframe) {
free(decoder->private_->side_subframe);
decoder->private_->side_subframe = 0;
}
for(i = 0; i < channels; i++) {
/* WATCHOUT:
* FLAC__lpc_restore_signal_asm_ia32_mmx() and ..._intrin_sseN()
* require that the output arrays have a buffer of up to 3 zeroes
* in front (at negative indices) for alignment purposes;
* we use 4 to keep the data well-aligned.
*/
tmp = safe_malloc_muladd2_(sizeof(FLAC__int32), /*times (*/size, /*+*/4/*)*/);
if(tmp == 0) {
decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
return false;
}
memset(tmp, 0, sizeof(FLAC__int32)*4);
decoder->private_->output[i] = tmp + 4;
if(!FLAC__memory_alloc_aligned_int32_array(size, &decoder->private_->residual_unaligned[i], &decoder->private_->residual[i])) {
decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
return false;
}
}
if(bps == 32) {
decoder->private_->side_subframe = safe_malloc_mul_2op_p(sizeof(FLAC__int64), /*times (*/size);
if(decoder->private_->side_subframe == NULL) {
decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
return false;
}
}
decoder->private_->output_capacity = size;
decoder->private_->output_channels = channels;
return true;
}
FLAC__bool has_id_filtered_(FLAC__StreamDecoder *decoder, FLAC__byte *id)
{
size_t i;
FLAC__ASSERT(0 != decoder);
FLAC__ASSERT(0 != decoder->private_);
for(i = 0; i < decoder->private_->metadata_filter_ids_count; i++)
if(0 == memcmp(decoder->private_->metadata_filter_ids + i * (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8), id, (FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8)))
return true;
return false;
}
FLAC__bool find_metadata_(FLAC__StreamDecoder *decoder)
{
FLAC__uint32 x;
uint32_t i, id;
FLAC__bool first = true;
FLAC__ASSERT(FLAC__bitreader_is_consumed_byte_aligned(decoder->private_->input));
for(i = id = 0; i < 4; ) {
if(decoder->private_->cached) {
x = (FLAC__uint32)decoder->private_->lookahead;
decoder->private_->cached = false;
}
else {
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, 8))
return false; /* read_callback_ sets the state for us */
}
if(x == FLAC__STREAM_SYNC_STRING[i]) {
first = true;
i++;
id = 0;
continue;
}
if(id >= 3)
return false;
if(x == ID3V2_TAG_[id]) {
id++;
i = 0;
if(id == 3) {
if(!skip_id3v2_tag_(decoder))
return false; /* skip_id3v2_tag_ sets the state for us */
}
continue;
}
id = 0;
if(x == 0xff) { /* MAGIC NUMBER for the first 8 frame sync bits */
decoder->private_->header_warmup[0] = (FLAC__byte)x;
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, 8))
return false; /* read_callback_ sets the state for us */
/* we have to check if we just read two 0xff's in a row; the second may actually be the beginning of the sync code */
/* else we have to check if the second byte is the end of a sync code */
if(x == 0xff) { /* MAGIC NUMBER for the first 8 frame sync bits */
decoder->private_->lookahead = (FLAC__byte)x;
decoder->private_->cached = true;
}
else if(x >> 1 == 0x7c) { /* MAGIC NUMBER for the last 6 sync bits and reserved 7th bit */
decoder->private_->header_warmup[1] = (FLAC__byte)x;
decoder->protected_->state = FLAC__STREAM_DECODER_READ_FRAME;
return true;
}
}
i = 0;
if(first) {
send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC);
first = false;
}
}
decoder->protected_->state = FLAC__STREAM_DECODER_READ_METADATA;
return true;
}
FLAC__bool read_metadata_(FLAC__StreamDecoder *decoder)
{
FLAC__bool is_last;
FLAC__uint32 i, x, type, length;
FLAC__ASSERT(FLAC__bitreader_is_consumed_byte_aligned(decoder->private_->input));
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_IS_LAST_LEN))
return false; /* read_callback_ sets the state for us */
is_last = x? true : false;
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &type, FLAC__STREAM_METADATA_TYPE_LEN))
return false; /* read_callback_ sets the state for us */
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &length, FLAC__STREAM_METADATA_LENGTH_LEN))
return false; /* read_callback_ sets the state for us */
if(type == FLAC__METADATA_TYPE_STREAMINFO) {
if(!read_metadata_streaminfo_(decoder, is_last, length))
return false;
decoder->private_->has_stream_info = true;
if(0 == memcmp(decoder->private_->stream_info.data.stream_info.md5sum, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16))
decoder->private_->do_md5_checking = false;
if(!decoder->private_->is_seeking && decoder->private_->metadata_filter[FLAC__METADATA_TYPE_STREAMINFO] && decoder->private_->metadata_callback)
decoder->private_->metadata_callback(decoder, &decoder->private_->stream_info, decoder->private_->client_data);
}
else if(type == FLAC__METADATA_TYPE_SEEKTABLE) {
/* just in case we already have a seek table, and reading the next one fails: */
decoder->private_->has_seek_table = false;
if(length > 0) {
if(!read_metadata_seektable_(decoder, is_last, length))
return false;
decoder->private_->has_seek_table = true;
if(!decoder->private_->is_seeking && decoder->private_->metadata_filter[FLAC__METADATA_TYPE_SEEKTABLE] && decoder->private_->metadata_callback)
decoder->private_->metadata_callback(decoder, &decoder->private_->seek_table, decoder->private_->client_data);
}
}
else {
FLAC__bool skip_it = !decoder->private_->metadata_filter[type];
uint32_t real_length = length;
FLAC__StreamMetadata block;
memset(&block, 0, sizeof(block));
block.is_last = is_last;
block.type = (FLAC__MetadataType)type;
block.length = length;
if(type == FLAC__METADATA_TYPE_APPLICATION) {
if(!FLAC__bitreader_read_byte_block_aligned_no_crc(decoder->private_->input, block.data.application.id, FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8))
return false; /* read_callback_ sets the state for us */
if(real_length < FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8) { /* underflow check */
decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;/*@@@@@@ maybe wrong error? need to resync?*/
return false;
}
real_length -= FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8;
if(decoder->private_->metadata_filter_ids_count > 0 && has_id_filtered_(decoder, block.data.application.id))
skip_it = !skip_it;
}
if(skip_it) {
if(!FLAC__bitreader_skip_byte_block_aligned_no_crc(decoder->private_->input, real_length))
return false; /* read_callback_ sets the state for us */
}
else {
FLAC__bool ok = true;
FLAC__bitreader_set_limit(decoder->private_->input, real_length*8);
switch(type) {
case FLAC__METADATA_TYPE_PADDING:
/* skip the padding bytes */
if(!FLAC__bitreader_skip_byte_block_aligned_no_crc(decoder->private_->input, real_length))
ok = false; /* read_callback_ sets the state for us */
break;
case FLAC__METADATA_TYPE_APPLICATION:
/* remember, we read the ID already */
if(real_length > 0) {
if(0 == (block.data.application.data = malloc(real_length))) {
decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
ok = false;
}
else if(!FLAC__bitreader_read_byte_block_aligned_no_crc(decoder->private_->input, block.data.application.data, real_length))
ok = false; /* read_callback_ sets the state for us */
}
else
block.data.application.data = 0;
break;
case FLAC__METADATA_TYPE_VORBIS_COMMENT:
if(!read_metadata_vorbiscomment_(decoder, &block.data.vorbis_comment, real_length))
ok = false;
break;
case FLAC__METADATA_TYPE_CUESHEET:
if(!read_metadata_cuesheet_(decoder, &block.data.cue_sheet))
ok = false;
break;
case FLAC__METADATA_TYPE_PICTURE:
if(!read_metadata_picture_(decoder, &block.data.picture))
ok = false;
break;
case FLAC__METADATA_TYPE_STREAMINFO:
case FLAC__METADATA_TYPE_SEEKTABLE:
FLAC__ASSERT(0);
break;
default:
if(real_length > 0) {
if(0 == (block.data.unknown.data = malloc(real_length))) {
decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
ok = false;
}
else if(!FLAC__bitreader_read_byte_block_aligned_no_crc(decoder->private_->input, block.data.unknown.data, real_length))
ok = false; /* read_callback_ sets the state for us */
}
else
block.data.unknown.data = 0;
break;
}
if(FLAC__bitreader_limit_remaining(decoder->private_->input) > 0) {
/* Content in metadata block didn't fit in block length
* We cannot know whether the length or the content was
* corrupt, so stop parsing metadata */
send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_METADATA);
if(decoder->protected_->state == FLAC__STREAM_DECODER_READ_METADATA)
decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
ok = false;
}
FLAC__bitreader_remove_limit(decoder->private_->input);
if(ok && !decoder->private_->is_seeking && decoder->private_->metadata_callback)
decoder->private_->metadata_callback(decoder, &block, decoder->private_->client_data);
/* now we have to free any malloc()ed data in the block */
switch(type) {
case FLAC__METADATA_TYPE_PADDING:
break;
case FLAC__METADATA_TYPE_APPLICATION:
if(0 != block.data.application.data)
free(block.data.application.data);
break;
case FLAC__METADATA_TYPE_VORBIS_COMMENT:
if(0 != block.data.vorbis_comment.vendor_string.entry)
free(block.data.vorbis_comment.vendor_string.entry);
if(block.data.vorbis_comment.num_comments > 0)
for(i = 0; i < block.data.vorbis_comment.num_comments; i++)
if(0 != block.data.vorbis_comment.comments[i].entry)
free(block.data.vorbis_comment.comments[i].entry);
if(0 != block.data.vorbis_comment.comments)
free(block.data.vorbis_comment.comments);
break;
case FLAC__METADATA_TYPE_CUESHEET:
if(block.data.cue_sheet.num_tracks > 0 && 0 != block.data.cue_sheet.tracks)
for(i = 0; i < block.data.cue_sheet.num_tracks; i++)
if(0 != block.data.cue_sheet.tracks[i].indices)
free(block.data.cue_sheet.tracks[i].indices);
if(0 != block.data.cue_sheet.tracks)
free(block.data.cue_sheet.tracks);
break;
case FLAC__METADATA_TYPE_PICTURE:
if(0 != block.data.picture.mime_type)
free(block.data.picture.mime_type);
if(0 != block.data.picture.description)
free(block.data.picture.description);
if(0 != block.data.picture.data)
free(block.data.picture.data);
break;
case FLAC__METADATA_TYPE_STREAMINFO:
case FLAC__METADATA_TYPE_SEEKTABLE:
FLAC__ASSERT(0);
default:
if(0 != block.data.unknown.data)
free(block.data.unknown.data);
break;
}
if(!ok) /* anything that unsets "ok" should also make sure decoder->protected_->state is updated */
return false;
}
}
if(is_last) {
/* if this fails, it's OK, it's just a hint for the seek routine */
if(!FLAC__stream_decoder_get_decode_position(decoder, &decoder->private_->first_frame_offset))
decoder->private_->first_frame_offset = 0;
decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
}
return true;
}
FLAC__bool read_metadata_streaminfo_(FLAC__StreamDecoder *decoder, FLAC__bool is_last, uint32_t length)
{
FLAC__uint32 x;
uint32_t bits, used_bits = 0;
FLAC__ASSERT(FLAC__bitreader_is_consumed_byte_aligned(decoder->private_->input));
decoder->private_->stream_info.type = FLAC__METADATA_TYPE_STREAMINFO;
decoder->private_->stream_info.is_last = is_last;
decoder->private_->stream_info.length = length;
bits = FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN;
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, bits))
return false; /* read_callback_ sets the state for us */
decoder->private_->stream_info.data.stream_info.min_blocksize = x;
used_bits += bits;
bits = FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN;
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN))
return false; /* read_callback_ sets the state for us */
decoder->private_->stream_info.data.stream_info.max_blocksize = x;
used_bits += bits;
bits = FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN;
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN))
return false; /* read_callback_ sets the state for us */
decoder->private_->stream_info.data.stream_info.min_framesize = x;
used_bits += bits;
bits = FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN;
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN))
return false; /* read_callback_ sets the state for us */
decoder->private_->stream_info.data.stream_info.max_framesize = x;
used_bits += bits;
bits = FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN;
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN))
return false; /* read_callback_ sets the state for us */
decoder->private_->stream_info.data.stream_info.sample_rate = x;
used_bits += bits;
bits = FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN;
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN))
return false; /* read_callback_ sets the state for us */
decoder->private_->stream_info.data.stream_info.channels = x+1;
used_bits += bits;
bits = FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN;
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN))
return false; /* read_callback_ sets the state for us */
decoder->private_->stream_info.data.stream_info.bits_per_sample = x+1;
used_bits += bits;
bits = FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN;
if(!FLAC__bitreader_read_raw_uint64(decoder->private_->input, &decoder->private_->stream_info.data.stream_info.total_samples, FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN))
return false; /* read_callback_ sets the state for us */
used_bits += bits;
if(!FLAC__bitreader_read_byte_block_aligned_no_crc(decoder->private_->input, decoder->private_->stream_info.data.stream_info.md5sum, 16))
return false; /* read_callback_ sets the state for us */
used_bits += 16*8;
/* skip the rest of the block */
FLAC__ASSERT(used_bits % 8 == 0);
if (length < (used_bits / 8))
return false; /* read_callback_ sets the state for us */
length -= (used_bits / 8);
if(!FLAC__bitreader_skip_byte_block_aligned_no_crc(decoder->private_->input, length))
return false; /* read_callback_ sets the state for us */
return true;
}
FLAC__bool read_metadata_seektable_(FLAC__StreamDecoder *decoder, FLAC__bool is_last, uint32_t length)
{
FLAC__uint32 i, x;
FLAC__uint64 xx;
FLAC__ASSERT(FLAC__bitreader_is_consumed_byte_aligned(decoder->private_->input));
decoder->private_->seek_table.type = FLAC__METADATA_TYPE_SEEKTABLE;
decoder->private_->seek_table.is_last = is_last;
decoder->private_->seek_table.length = length;
if(length % FLAC__STREAM_METADATA_SEEKPOINT_LENGTH) {
FLAC__bitreader_limit_invalidate(decoder->private_->input);
return false;
}
decoder->private_->seek_table.data.seek_table.num_points = length / FLAC__STREAM_METADATA_SEEKPOINT_LENGTH;
/* use realloc since we may pass through here several times (e.g. after seeking) */
if(0 == (decoder->private_->seek_table.data.seek_table.points = safe_realloc_mul_2op_(decoder->private_->seek_table.data.seek_table.points, decoder->private_->seek_table.data.seek_table.num_points, /*times*/sizeof(FLAC__StreamMetadata_SeekPoint)))) {
decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
return false;
}
for(i = 0; i < decoder->private_->seek_table.data.seek_table.num_points; i++) {
if(!FLAC__bitreader_read_raw_uint64(decoder->private_->input, &xx, FLAC__STREAM_METADATA_SEEKPOINT_SAMPLE_NUMBER_LEN))
return false; /* read_callback_ sets the state for us */
decoder->private_->seek_table.data.seek_table.points[i].sample_number = xx;
if(!FLAC__bitreader_read_raw_uint64(decoder->private_->input, &xx, FLAC__STREAM_METADATA_SEEKPOINT_STREAM_OFFSET_LEN))
return false; /* read_callback_ sets the state for us */
decoder->private_->seek_table.data.seek_table.points[i].stream_offset = xx;
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_SEEKPOINT_FRAME_SAMPLES_LEN))
return false; /* read_callback_ sets the state for us */
decoder->private_->seek_table.data.seek_table.points[i].frame_samples = x;
}
length -= (decoder->private_->seek_table.data.seek_table.num_points * FLAC__STREAM_METADATA_SEEKPOINT_LENGTH);
FLAC__ASSERT(length == 0);
return true;
}
FLAC__bool read_metadata_vorbiscomment_(FLAC__StreamDecoder *decoder, FLAC__StreamMetadata_VorbisComment *obj, uint32_t length)
{
FLAC__uint32 i;
FLAC__ASSERT(FLAC__bitreader_is_consumed_byte_aligned(decoder->private_->input));
/* read vendor string */
if (length >= 8) {
length -= 8; /* vendor string length + num comments entries alone take 8 bytes */
FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN == 32);
if (!FLAC__bitreader_read_uint32_little_endian(decoder->private_->input, &obj->vendor_string.length))
return false; /* read_callback_ sets the state for us */
if (length < obj->vendor_string.length) {
obj->vendor_string.length = 0;
obj->vendor_string.entry = 0;
goto skip;
}
else
length -= obj->vendor_string.length;
if (0 == (obj->vendor_string.entry = safe_malloc_add_2op_(obj->vendor_string.length, /*+*/1))) {
decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
return false;
}
if (!FLAC__bitreader_read_byte_block_aligned_no_crc(decoder->private_->input, obj->vendor_string.entry, obj->vendor_string.length))
return false; /* read_callback_ sets the state for us */
obj->vendor_string.entry[obj->vendor_string.length] = '\0';
/* read num comments */
FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN == 32);
if (!FLAC__bitreader_read_uint32_little_endian(decoder->private_->input, &obj->num_comments))
return false; /* read_callback_ sets the state for us */
/* read comments */
if (obj->num_comments > 100000) {
/* Possibly malicious file. */
obj->num_comments = 0;
return false;
}
if (obj->num_comments > 0) {
if (0 == (obj->comments = safe_malloc_mul_2op_p(obj->num_comments, /*times*/sizeof(FLAC__StreamMetadata_VorbisComment_Entry)))) {
obj->num_comments = 0;
decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
return false;
}
for (i = 0; i < obj->num_comments; i++) {
/* Initialize here just to make sure. */
obj->comments[i].length = 0;
obj->comments[i].entry = 0;
FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN == 32);
if (length < 4) {
obj->num_comments = i;
goto skip;
}
else
length -= 4;
if (!FLAC__bitreader_read_uint32_little_endian(decoder->private_->input, &obj->comments[i].length)) {
obj->num_comments = i;
return false; /* read_callback_ sets the state for us */
}
if (length < obj->comments[i].length) {
obj->num_comments = i;
FLAC__bitreader_limit_invalidate(decoder->private_->input);
return false;
}
else
length -= obj->comments[i].length;
if (0 == (obj->comments[i].entry = safe_malloc_add_2op_(obj->comments[i].length, /*+*/1))) {
decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
obj->num_comments = i;
return false;
}
memset (obj->comments[i].entry, 0, obj->comments[i].length) ;
if (!FLAC__bitreader_read_byte_block_aligned_no_crc(decoder->private_->input, obj->comments[i].entry, obj->comments[i].length)) {
/* Current i-th entry is bad, so we delete it. */
free (obj->comments[i].entry) ;
obj->comments[i].entry = NULL ;
obj->num_comments = i;
goto skip;
}
obj->comments[i].entry[obj->comments[i].length] = '\0';
}
}
}
else {
FLAC__bitreader_limit_invalidate(decoder->private_->input);
return false;
}
skip:
if (length > 0) {
/* length > 0 can only happen on files with invalid data in comments */
if(obj->num_comments < 1) {
free(obj->comments);
obj->comments = NULL;
}
FLAC__bitreader_limit_invalidate(decoder->private_->input);
return false;
}
return true;
}
FLAC__bool read_metadata_cuesheet_(FLAC__StreamDecoder *decoder, FLAC__StreamMetadata_CueSheet *obj)
{
FLAC__uint32 i, j, x;
FLAC__ASSERT(FLAC__bitreader_is_consumed_byte_aligned(decoder->private_->input));
memset(obj, 0, sizeof(FLAC__StreamMetadata_CueSheet));
FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN % 8 == 0);
if(!FLAC__bitreader_read_byte_block_aligned_no_crc(decoder->private_->input, (FLAC__byte*)obj->media_catalog_number, FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN/8))
return false; /* read_callback_ sets the state for us */
if(!FLAC__bitreader_read_raw_uint64(decoder->private_->input, &obj->lead_in, FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN))
return false; /* read_callback_ sets the state for us */
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN))
return false; /* read_callback_ sets the state for us */
obj->is_cd = x? true : false;
if(!FLAC__bitreader_skip_bits_no_crc(decoder->private_->input, FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN))
return false; /* read_callback_ sets the state for us */
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN))
return false; /* read_callback_ sets the state for us */
obj->num_tracks = x;
if(obj->num_tracks > 0) {
if(0 == (obj->tracks = safe_calloc_(obj->num_tracks, sizeof(FLAC__StreamMetadata_CueSheet_Track)))) {
decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
return false;
}
for(i = 0; i < obj->num_tracks; i++) {
FLAC__StreamMetadata_CueSheet_Track *track = &obj->tracks[i];
if(!FLAC__bitreader_read_raw_uint64(decoder->private_->input, &track->offset, FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN))
return false; /* read_callback_ sets the state for us */
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN))
return false; /* read_callback_ sets the state for us */
track->number = (FLAC__byte)x;
FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN % 8 == 0);
if(!FLAC__bitreader_read_byte_block_aligned_no_crc(decoder->private_->input, (FLAC__byte*)track->isrc, FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN/8))
return false; /* read_callback_ sets the state for us */
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN))
return false; /* read_callback_ sets the state for us */
track->type = x;
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN))
return false; /* read_callback_ sets the state for us */
track->pre_emphasis = x;
if(!FLAC__bitreader_skip_bits_no_crc(decoder->private_->input, FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN))
return false; /* read_callback_ sets the state for us */
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN))
return false; /* read_callback_ sets the state for us */
track->num_indices = (FLAC__byte)x;
if(track->num_indices > 0) {
if(0 == (track->indices = safe_calloc_(track->num_indices, sizeof(FLAC__StreamMetadata_CueSheet_Index)))) {
decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
return false;
}
for(j = 0; j < track->num_indices; j++) {
FLAC__StreamMetadata_CueSheet_Index *indx = &track->indices[j];
if(!FLAC__bitreader_read_raw_uint64(decoder->private_->input, &indx->offset, FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN))
return false; /* read_callback_ sets the state for us */
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN))
return false; /* read_callback_ sets the state for us */
indx->number = (FLAC__byte)x;
if(!FLAC__bitreader_skip_bits_no_crc(decoder->private_->input, FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN))
return false; /* read_callback_ sets the state for us */
}
}
}
}
else { /* obj->num_tracks == 0 */
FLAC__bitreader_limit_invalidate(decoder->private_->input);
return false;
}
return true;
}
FLAC__bool read_metadata_picture_(FLAC__StreamDecoder *decoder, FLAC__StreamMetadata_Picture *obj)
{
FLAC__uint32 x;
FLAC__ASSERT(FLAC__bitreader_is_consumed_byte_aligned(decoder->private_->input));
/* read type */
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_PICTURE_TYPE_LEN))
return false; /* read_callback_ sets the state for us */
if(x < FLAC__STREAM_METADATA_PICTURE_TYPE_UNDEFINED)
obj->type = x;
else
obj->type = FLAC__STREAM_METADATA_PICTURE_TYPE_OTHER;
/* read MIME type */
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN))
return false; /* read_callback_ sets the state for us */
if(FLAC__bitreader_limit_remaining(decoder->private_->input) < x){
FLAC__bitreader_limit_invalidate(decoder->private_->input);
return false;
}
if(0 == (obj->mime_type = safe_malloc_add_2op_(x, /*+*/1))) {
decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
return false;
}
if(x > 0) {
if(!FLAC__bitreader_read_byte_block_aligned_no_crc(decoder->private_->input, (FLAC__byte*)obj->mime_type, x))
return false; /* read_callback_ sets the state for us */
}
obj->mime_type[x] = '\0';
/* read description */
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN))
return false; /* read_callback_ sets the state for us */
if(FLAC__bitreader_limit_remaining(decoder->private_->input) < x){
FLAC__bitreader_limit_invalidate(decoder->private_->input);
return false;
}
if(0 == (obj->description = safe_malloc_add_2op_(x, /*+*/1))) {
decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
return false;
}
if(x > 0) {
if(!FLAC__bitreader_read_byte_block_aligned_no_crc(decoder->private_->input, obj->description, x))
return false; /* read_callback_ sets the state for us */
}
obj->description[x] = '\0';
/* read width */
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &obj->width, FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN))
return false; /* read_callback_ sets the state for us */
/* read height */
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &obj->height, FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN))
return false; /* read_callback_ sets the state for us */
/* read depth */
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &obj->depth, FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN))
return false; /* read_callback_ sets the state for us */
/* read colors */
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &obj->colors, FLAC__STREAM_METADATA_PICTURE_COLORS_LEN))
return false; /* read_callback_ sets the state for us */
/* read data */
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &(obj->data_length), FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN))
return false; /* read_callback_ sets the state for us */
if(FLAC__bitreader_limit_remaining(decoder->private_->input) < obj->data_length){
FLAC__bitreader_limit_invalidate(decoder->private_->input);
return false;
}
if(0 == (obj->data = safe_malloc_(obj->data_length))) {
decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
return false;
}
if(obj->data_length > 0) {
if(!FLAC__bitreader_read_byte_block_aligned_no_crc(decoder->private_->input, obj->data, obj->data_length))
return false; /* read_callback_ sets the state for us */
}
return true;
}
FLAC__bool skip_id3v2_tag_(FLAC__StreamDecoder *decoder)
{
FLAC__uint32 x;
uint32_t i, skip;
/* skip the version and flags bytes */
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, 24))
return false; /* read_callback_ sets the state for us */
/* get the size (in bytes) to skip */
skip = 0;
for(i = 0; i < 4; i++) {
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, 8))
return false; /* read_callback_ sets the state for us */
skip <<= 7;
skip |= (x & 0x7f);
}
/* skip the rest of the tag */
if(!FLAC__bitreader_skip_byte_block_aligned_no_crc(decoder->private_->input, skip))
return false; /* read_callback_ sets the state for us */
return true;
}
FLAC__bool frame_sync_(FLAC__StreamDecoder *decoder)
{
FLAC__uint32 x;
FLAC__bool first = true;
/* make sure we're byte aligned */
if(!FLAC__bitreader_is_consumed_byte_aligned(decoder->private_->input)) {
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__bitreader_bits_left_for_byte_alignment(decoder->private_->input)))
return false; /* read_callback_ sets the state for us */
}
while(1) {
if(decoder->private_->cached) {
x = (FLAC__uint32)decoder->private_->lookahead;
decoder->private_->cached = false;
}
else {
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, 8))
return false; /* read_callback_ sets the state for us */
}
if(x == 0xff) { /* MAGIC NUMBER for the first 8 frame sync bits */
decoder->private_->header_warmup[0] = (FLAC__byte)x;
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, 8))
return false; /* read_callback_ sets the state for us */
/* we have to check if we just read two 0xff's in a row; the second may actually be the beginning of the sync code */
/* else we have to check if the second byte is the end of a sync code */
if(x == 0xff) { /* MAGIC NUMBER for the first 8 frame sync bits */
decoder->private_->lookahead = (FLAC__byte)x;
decoder->private_->cached = true;
}
else if(x >> 1 == 0x7c) { /* MAGIC NUMBER for the last 6 sync bits and reserved 7th bit */
decoder->private_->header_warmup[1] = (FLAC__byte)x;
decoder->protected_->state = FLAC__STREAM_DECODER_READ_FRAME;
/* Save location so we can rewind in case the frame turns
* out to be invalid after the header */
FLAC__bitreader_set_framesync_location(decoder->private_->input);
if(!FLAC__stream_decoder_get_decode_position(decoder, &decoder->private_->last_seen_framesync))
decoder->private_->last_seen_framesync = 0;
return true;
}
}
if(first) {
send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC);
first = false;
}
}
return true;
}
FLAC__bool read_frame_(FLAC__StreamDecoder *decoder, FLAC__bool *got_a_frame, FLAC__bool do_full_decode)
{
uint32_t channel;
uint32_t i;
uint32_t frame_crc; /* the one we calculate from the input stream */
FLAC__uint32 x;
*got_a_frame = false;
decoder->private_->side_subframe_in_use = false;
/* init the CRC */
frame_crc = 0;
frame_crc = FLAC__CRC16_UPDATE(decoder->private_->header_warmup[0], frame_crc);
frame_crc = FLAC__CRC16_UPDATE(decoder->private_->header_warmup[1], frame_crc);
FLAC__bitreader_reset_read_crc16(decoder->private_->input, (FLAC__uint16)frame_crc);
if(!read_frame_header_(decoder))
return false;
if(decoder->protected_->state == FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC) /* means we didn't sync on a valid header */
return true;
if(!allocate_output_(decoder, decoder->private_->frame.header.blocksize, decoder->private_->frame.header.channels, decoder->private_->frame.header.bits_per_sample))
return false;
for(channel = 0; channel < decoder->private_->frame.header.channels; channel++) {
/*
* first figure the correct bits-per-sample of the subframe
*/
uint32_t bps = decoder->private_->frame.header.bits_per_sample;
switch(decoder->private_->frame.header.channel_assignment) {
case FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT:
/* no adjustment needed */
break;
case FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE:
FLAC__ASSERT(decoder->private_->frame.header.channels == 2);
if(channel == 1)
bps++;
break;
case FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE:
FLAC__ASSERT(decoder->private_->frame.header.channels == 2);
if(channel == 0)
bps++;
break;
case FLAC__CHANNEL_ASSIGNMENT_MID_SIDE:
FLAC__ASSERT(decoder->private_->frame.header.channels == 2);
if(channel == 1)
bps++;
break;
default:
FLAC__ASSERT(0);
}
/*
* now read it
*/
if(!read_subframe_(decoder, channel, bps, do_full_decode)){
/* read_callback_ sets the state for us */
if(decoder->protected_->state == FLAC__STREAM_DECODER_END_OF_STREAM)
break;
else
return false;
}
if(decoder->protected_->state != FLAC__STREAM_DECODER_READ_FRAME)
break;
}
if(decoder->protected_->state != FLAC__STREAM_DECODER_END_OF_STREAM)
if(!read_zero_padding_(decoder))
return false;
/*
* Read the frame CRC-16 from the footer and check
*/
if(decoder->protected_->state == FLAC__STREAM_DECODER_READ_FRAME) {
frame_crc = FLAC__bitreader_get_read_crc16(decoder->private_->input);
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, FLAC__FRAME_FOOTER_CRC_LEN)) {
/* read_callback_ sets the state for us */
if(decoder->protected_->state != FLAC__STREAM_DECODER_END_OF_STREAM)
return false;
}
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
}
if(decoder->protected_->state == FLAC__STREAM_DECODER_READ_FRAME && frame_crc == x) {
#endif
if(do_full_decode) {
/* Undo any special channel coding */
undo_channel_coding(decoder);
/* Check whether decoded data actually fits bps */
for(channel = 0; channel < decoder->private_->frame.header.channels; channel++) {
for(i = 0; i < decoder->private_->frame.header.blocksize; i++) {
int shift_bits = 32 - decoder->private_->frame.header.bits_per_sample;
/* Check whether shift_bits MSBs are 'empty' by shifting up and down */
if((decoder->private_->output[channel][i] < (INT32_MIN >> shift_bits)) ||
(decoder->private_->output[channel][i] > (INT32_MAX >> shift_bits))) {
/* Bad frame, emit error */
send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH);
decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
break;
}
}
}
}
}
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
else if (decoder->protected_->state == FLAC__STREAM_DECODER_READ_FRAME) {
/* Bad frame, emit error */
send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH);
decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
}
#endif
/* Check whether frames are missing, if so, add silence to compensate */
if(decoder->private_->last_frame_is_set && decoder->protected_->state == FLAC__STREAM_DECODER_READ_FRAME && !decoder->private_->is_seeking && do_full_decode) {
FLAC__ASSERT(decoder->private_->frame.header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER);
FLAC__ASSERT(decoder->private_->last_frame.header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER);
if(decoder->private_->last_frame.header.number.sample_number + decoder->private_->last_frame.header.blocksize < decoder->private_->frame.header.number.sample_number) {
uint32_t padding_samples_needed = decoder->private_->frame.header.number.sample_number - (decoder->private_->last_frame.header.number.sample_number + decoder->private_->last_frame.header.blocksize);
/* Do some extra validation to assure last frame an current frame
* header are both valid before adding silence inbetween
* Technically both frames could be valid with differing sample_rates,
* channels and bits_per_sample, but it is quite rare */
if(decoder->private_->last_frame.header.sample_rate == decoder->private_->frame.header.sample_rate &&
decoder->private_->last_frame.header.channels == decoder->private_->frame.header.channels &&
decoder->private_->last_frame.header.bits_per_sample == decoder->private_->frame.header.bits_per_sample &&
decoder->private_->last_frame.header.blocksize >= 16) {
FLAC__Frame empty_frame;
FLAC__int32 * empty_buffer[FLAC__MAX_CHANNELS] = {NULL};
empty_frame.header = decoder->private_->last_frame.header;
empty_frame.footer.crc = 0;
for(i = 0; i < empty_frame.header.channels; i++) {
empty_buffer[i] = safe_calloc_(empty_frame.header.blocksize, sizeof(FLAC__int32));
if(empty_buffer[i] == NULL) {
for(i = 0; i < empty_frame.header.channels; i++)
if(empty_buffer[i] != NULL)
free(empty_buffer[i]);
decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
return false;
}
}
/* No repairs larger than 5 seconds or 50 frames are made, to not
* unexpectedly create enormous files when one of the headers was
* corrupt after all */
if(padding_samples_needed > (5*empty_frame.header.sample_rate))
padding_samples_needed = 5*empty_frame.header.sample_rate;
if(padding_samples_needed > (50*empty_frame.header.blocksize))
padding_samples_needed = 50*empty_frame.header.blocksize;
while(padding_samples_needed){
empty_frame.header.number.sample_number += empty_frame.header.blocksize;
if(padding_samples_needed < empty_frame.header.blocksize)
empty_frame.header.blocksize = padding_samples_needed;
padding_samples_needed -= empty_frame.header.blocksize;
decoder->protected_->blocksize = empty_frame.header.blocksize;
FLAC__ASSERT(empty_frame.header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER);
decoder->private_->samples_decoded = empty_frame.header.number.sample_number + empty_frame.header.blocksize;
for(channel = 0; channel < empty_frame.header.channels; channel++) {
empty_frame.subframes[channel].type = FLAC__SUBFRAME_TYPE_CONSTANT;
empty_frame.subframes[channel].data.constant.value = 0;
empty_frame.subframes[channel].wasted_bits = 0;
}
if(write_audio_frame_to_client_(decoder, &empty_frame, (const FLAC__int32 * const *)empty_buffer) != FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE) {
decoder->protected_->state = FLAC__STREAM_DECODER_ABORTED;
for(i = 0; i < empty_frame.header.channels; i++)
if(empty_buffer[i] != NULL)
free(empty_buffer[i]);
return false;
}
}
for(i = 0; i < empty_frame.header.channels; i++)
if(empty_buffer[i] != NULL)
free(empty_buffer[i]);
}
}
}
if(decoder->protected_->state == FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC || decoder->protected_->state == FLAC__STREAM_DECODER_END_OF_STREAM) {
/* Got corruption, rewind if possible. Return value of seek
* isn't checked, if the seek fails the decoder will continue anyway */
if(!FLAC__bitreader_rewind_to_after_last_seen_framesync(decoder->private_->input)){
#ifndef NDEBUG
fprintf(stderr, "Rewinding, seeking necessary\n");
#endif
if(decoder->private_->seek_callback && decoder->private_->last_seen_framesync){
/* Last framesync isn't in bitreader anymore, rewind with seek if possible */
#ifndef NDEBUG
FLAC__uint64 current_decode_position;
if(FLAC__stream_decoder_get_decode_position(decoder, &current_decode_position))
fprintf(stderr, "Bitreader was %" PRIu64 " bytes short\n", current_decode_position-decoder->private_->last_seen_framesync);
#endif
if(decoder->private_->seek_callback(decoder, decoder->private_->last_seen_framesync, decoder->private_->client_data) == FLAC__STREAM_DECODER_SEEK_STATUS_ERROR) {
decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR;
return false;
}
if(!FLAC__bitreader_clear(decoder->private_->input)) {
decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
return false;
}
}
}
#ifndef NDEBUG
else{
fprintf(stderr, "Rewinding, seeking not necessary\n");
}
#endif
}
else {
*got_a_frame = true;
/* we wait to update fixed_block_size until here, when we're sure we've got a proper frame and hence a correct blocksize */
if(decoder->private_->next_fixed_block_size)
decoder->private_->fixed_block_size = decoder->private_->next_fixed_block_size;
/* put the latest values into the public section of the decoder instance */
decoder->protected_->channels = decoder->private_->frame.header.channels;
decoder->protected_->channel_assignment = decoder->private_->frame.header.channel_assignment;
decoder->protected_->bits_per_sample = decoder->private_->frame.header.bits_per_sample;
decoder->protected_->sample_rate = decoder->private_->frame.header.sample_rate;
decoder->protected_->blocksize = decoder->private_->frame.header.blocksize;
FLAC__ASSERT(decoder->private_->frame.header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER);
decoder->private_->samples_decoded = decoder->private_->frame.header.number.sample_number + decoder->private_->frame.header.blocksize;
/* write it */
if(do_full_decode) {
if(write_audio_frame_to_client_(decoder, &decoder->private_->frame, (const FLAC__int32 * const *)decoder->private_->output) != FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE) {
decoder->protected_->state = FLAC__STREAM_DECODER_ABORTED;
return false;
}
}
}
decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
return true;
}
FLAC__bool read_frame_header_(FLAC__StreamDecoder *decoder)
{
FLAC__uint32 x;
FLAC__uint64 xx;
uint32_t i, blocksize_hint = 0, sample_rate_hint = 0;
FLAC__byte crc8, raw_header[16]; /* MAGIC NUMBER based on the maximum frame header size, including CRC */
uint32_t raw_header_len;
FLAC__bool is_unparseable = false;
FLAC__ASSERT(FLAC__bitreader_is_consumed_byte_aligned(decoder->private_->input));
/* init the raw header with the saved bits from synchronization */
raw_header[0] = decoder->private_->header_warmup[0];
raw_header[1] = decoder->private_->header_warmup[1];
raw_header_len = 2;
/* check to make sure that reserved bit is 0 */
if(raw_header[1] & 0x02) /* MAGIC NUMBER */
is_unparseable = true;
/*
* Note that along the way as we read the header, we look for a sync
* code inside. If we find one it would indicate that our original
* sync was bad since there cannot be a sync code in a valid header.
*
* Three kinds of things can go wrong when reading the frame header:
* 1) We may have sync'ed incorrectly and not landed on a frame header.
* If we don't find a sync code, it can end up looking like we read
* a valid but unparseable header, until getting to the frame header
* CRC. Even then we could get a false positive on the CRC.
* 2) We may have sync'ed correctly but on an unparseable frame (from a
* future encoder).
* 3) We may be on a damaged frame which appears valid but unparseable.
*
* For all these reasons, we try and read a complete frame header as
* long as it seems valid, even if unparseable, up until the frame
* header CRC.
*/
/*
* read in the raw header as bytes so we can CRC it, and parse it on the way
*/
for(i = 0; i < 2; i++) {
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, 8))
return false; /* read_callback_ sets the state for us */
if(x == 0xff) { /* MAGIC NUMBER for the first 8 frame sync bits */
/* if we get here it means our original sync was erroneous since the sync code cannot appear in the header */
decoder->private_->lookahead = (FLAC__byte)x;
decoder->private_->cached = true;
send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER);
decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
return true;
}
raw_header[raw_header_len++] = (FLAC__byte)x;
}
switch(x = raw_header[2] >> 4) {
case 0:
is_unparseable = true;
break;
case 1:
decoder->private_->frame.header.blocksize = 192;
break;
case 2:
case 3:
case 4:
case 5:
decoder->private_->frame.header.blocksize = 576 << (x-2);
break;
case 6:
case 7:
blocksize_hint = x;
break;
case 8:
case 9:
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
decoder->private_->frame.header.blocksize = 256 << (x-8);
break;
default:
FLAC__ASSERT(0);
break;
}
switch(x = raw_header[2] & 0x0f) {
case 0:
if(decoder->private_->has_stream_info)
decoder->private_->frame.header.sample_rate = decoder->private_->stream_info.data.stream_info.sample_rate;
else
is_unparseable = true;
break;
case 1:
decoder->private_->frame.header.sample_rate = 88200;
break;
case 2:
decoder->private_->frame.header.sample_rate = 176400;
break;
case 3:
decoder->private_->frame.header.sample_rate = 192000;
break;
case 4:
decoder->private_->frame.header.sample_rate = 8000;
break;
case 5:
decoder->private_->frame.header.sample_rate = 16000;
break;
case 6:
decoder->private_->frame.header.sample_rate = 22050;
break;
case 7:
decoder->private_->frame.header.sample_rate = 24000;
break;
case 8:
decoder->private_->frame.header.sample_rate = 32000;
break;
case 9:
decoder->private_->frame.header.sample_rate = 44100;
break;
case 10:
decoder->private_->frame.header.sample_rate = 48000;
break;
case 11:
decoder->private_->frame.header.sample_rate = 96000;
break;
case 12:
case 13:
case 14:
sample_rate_hint = x;
break;
case 15:
send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER);
decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
return true;
default:
FLAC__ASSERT(0);
}
x = (uint32_t)(raw_header[3] >> 4);
if(x & 8) {
decoder->private_->frame.header.channels = 2;
switch(x & 7) {
case 0:
decoder->private_->frame.header.channel_assignment = FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE;
break;
case 1:
decoder->private_->frame.header.channel_assignment = FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE;
break;
case 2:
decoder->private_->frame.header.channel_assignment = FLAC__CHANNEL_ASSIGNMENT_MID_SIDE;
break;
default:
is_unparseable = true;
break;
}
}
else {
decoder->private_->frame.header.channels = (uint32_t)x + 1;
decoder->private_->frame.header.channel_assignment = FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT;
}
switch(x = (uint32_t)(raw_header[3] & 0x0e) >> 1) {
case 0:
if(decoder->private_->has_stream_info)
decoder->private_->frame.header.bits_per_sample = decoder->private_->stream_info.data.stream_info.bits_per_sample;
else
is_unparseable = true;
break;
case 1:
decoder->private_->frame.header.bits_per_sample = 8;
break;
case 2:
decoder->private_->frame.header.bits_per_sample = 12;
break;
case 3:
is_unparseable = true;
break;
case 4:
decoder->private_->frame.header.bits_per_sample = 16;
break;
case 5:
decoder->private_->frame.header.bits_per_sample = 20;
break;
case 6:
decoder->private_->frame.header.bits_per_sample = 24;
break;
case 7:
decoder->private_->frame.header.bits_per_sample = 32;
break;
default:
FLAC__ASSERT(0);
break;
}
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
/* check to make sure that reserved bit is 0 */
if(raw_header[3] & 0x01) /* MAGIC NUMBER */
is_unparseable = true;
#endif
/* read the frame's starting sample number (or frame number as the case may be) */
if(
raw_header[1] & 0x01 ||
/*@@@ this clause is a concession to the old way of doing variable blocksize; the only known implementation is flake and can probably be removed without inconveniencing anyone */
(decoder->private_->has_stream_info && decoder->private_->stream_info.data.stream_info.min_blocksize != decoder->private_->stream_info.data.stream_info.max_blocksize)
) { /* variable blocksize */
if(!FLAC__bitreader_read_utf8_uint64(decoder->private_->input, &xx, raw_header, &raw_header_len))
return false; /* read_callback_ sets the state for us */
if(xx == FLAC__U64L(0xffffffffffffffff)) { /* i.e. non-UTF8 code... */
decoder->private_->lookahead = raw_header[raw_header_len-1]; /* back up as much as we can */
decoder->private_->cached = true;
send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER);
decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
return true;
}
decoder->private_->frame.header.number_type = FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER;
decoder->private_->frame.header.number.sample_number = xx;
}
else { /* fixed blocksize */
if(!FLAC__bitreader_read_utf8_uint32(decoder->private_->input, &x, raw_header, &raw_header_len))
return false; /* read_callback_ sets the state for us */
if(x == 0xffffffff) { /* i.e. non-UTF8 code... */
decoder->private_->lookahead = raw_header[raw_header_len-1]; /* back up as much as we can */
decoder->private_->cached = true;
send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER);
decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
return true;
}
decoder->private_->frame.header.number_type = FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER;
decoder->private_->frame.header.number.frame_number = x;
}
if(blocksize_hint) {
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, 8))
return false; /* read_callback_ sets the state for us */
raw_header[raw_header_len++] = (FLAC__byte)x;
if(blocksize_hint == 7) {
FLAC__uint32 _x;
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &_x, 8))
return false; /* read_callback_ sets the state for us */
raw_header[raw_header_len++] = (FLAC__byte)_x;
x = (x << 8) | _x;
}
decoder->private_->frame.header.blocksize = x+1;
if(decoder->private_->frame.header.blocksize > 65535) { /* invalid blocksize (65536) specified */
decoder->private_->lookahead = raw_header[raw_header_len-1]; /* back up as much as we can */
decoder->private_->cached = true;
send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER);
decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
return true;
}
}
if(sample_rate_hint) {
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, 8))
return false; /* read_callback_ sets the state for us */
raw_header[raw_header_len++] = (FLAC__byte)x;
if(sample_rate_hint != 12) {
FLAC__uint32 _x;
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &_x, 8))
return false; /* read_callback_ sets the state for us */
raw_header[raw_header_len++] = (FLAC__byte)_x;
x = (x << 8) | _x;
}
if(sample_rate_hint == 12)
decoder->private_->frame.header.sample_rate = x*1000;
else if(sample_rate_hint == 13)
decoder->private_->frame.header.sample_rate = x;
else
decoder->private_->frame.header.sample_rate = x*10;
}
/* read the CRC-8 byte */
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, 8))
return false; /* read_callback_ sets the state for us */
crc8 = (FLAC__byte)x;
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
if(FLAC__crc8(raw_header, raw_header_len) != crc8) {
send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER);
decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
return true;
}
#endif
/* calculate the sample number from the frame number if needed */
decoder->private_->next_fixed_block_size = 0;
if(decoder->private_->frame.header.number_type == FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER) {
x = decoder->private_->frame.header.number.frame_number;
decoder->private_->frame.header.number_type = FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER;
if(decoder->private_->fixed_block_size)
decoder->private_->frame.header.number.sample_number = (FLAC__uint64)decoder->private_->fixed_block_size * (FLAC__uint64)x;
else if(decoder->private_->has_stream_info) {
if(decoder->private_->stream_info.data.stream_info.min_blocksize == decoder->private_->stream_info.data.stream_info.max_blocksize) {
decoder->private_->frame.header.number.sample_number = (FLAC__uint64)decoder->private_->stream_info.data.stream_info.min_blocksize * (FLAC__uint64)x;
decoder->private_->next_fixed_block_size = decoder->private_->stream_info.data.stream_info.max_blocksize;
}
else
is_unparseable = true;
}
else if(x == 0) {
decoder->private_->frame.header.number.sample_number = 0;
decoder->private_->next_fixed_block_size = decoder->private_->frame.header.blocksize;
}
else {
/* can only get here if the stream has invalid frame numbering and no STREAMINFO, so assume it's not the last (possibly short) frame */
decoder->private_->frame.header.number.sample_number = (FLAC__uint64)decoder->private_->frame.header.blocksize * (FLAC__uint64)x;
}
}
if(is_unparseable) {
send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM);
decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
return true;
}
return true;
}
FLAC__bool read_subframe_(FLAC__StreamDecoder *decoder, uint32_t channel, uint32_t bps, FLAC__bool do_full_decode)
{
FLAC__uint32 x;
FLAC__bool wasted_bits;
uint32_t i;
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &x, 8)) /* MAGIC NUMBER */
return false; /* read_callback_ sets the state for us */
wasted_bits = (x & 1);
x &= 0xfe;
if(wasted_bits) {
uint32_t u;
if(!FLAC__bitreader_read_unary_unsigned(decoder->private_->input, &u))
return false; /* read_callback_ sets the state for us */
decoder->private_->frame.subframes[channel].wasted_bits = u+1;
if (decoder->private_->frame.subframes[channel].wasted_bits >= bps) {
send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC);
decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
return true;
}
bps -= decoder->private_->frame.subframes[channel].wasted_bits;
}
else
decoder->private_->frame.subframes[channel].wasted_bits = 0;
/*
* Lots of magic numbers here
*/
if(x & 0x80) {
send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC);
decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
return true;
}
else if(x == 0) {
if(!read_subframe_constant_(decoder, channel, bps, do_full_decode))
return false;
}
else if(x == 2) {
if(!read_subframe_verbatim_(decoder, channel, bps, do_full_decode))
return false;
}
else if(x < 16) {
send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM);
decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
return true;
}
else if(x <= 24) {
uint32_t predictor_order = (x>>1)&7;
if(decoder->private_->frame.header.blocksize <= predictor_order){
send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC);
decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
return true;
}
if(!read_subframe_fixed_(decoder, channel, bps, predictor_order, do_full_decode))
return false;
if(decoder->protected_->state == FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC) /* means bad sync or got corruption */
return true;
}
else if(x < 64) {
send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM);
decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
return true;
}
else {
uint32_t predictor_order = ((x>>1)&31)+1;
if(decoder->private_->frame.header.blocksize <= predictor_order){
send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC);
decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
return true;
}
if(!read_subframe_lpc_(decoder, channel, bps, predictor_order, do_full_decode))
return false;
if(decoder->protected_->state == FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC) /* means bad sync or got corruption */
return true;
}
if(wasted_bits && do_full_decode) {
x = decoder->private_->frame.subframes[channel].wasted_bits;
if((bps + x) < 33) {
for(i = 0; i < decoder->private_->frame.header.blocksize; i++) {
uint32_t val = decoder->private_->output[channel][i];
decoder->private_->output[channel][i] = (val << x);
}
}
else {
/* When there are wasted bits, bps is never 33 and so
* side_subframe is never already in use */
FLAC__ASSERT(!decoder->private_->side_subframe_in_use);
decoder->private_->side_subframe_in_use = true;
for(i = 0; i < decoder->private_->frame.header.blocksize; i++) {
uint64_t val = decoder->private_->output[channel][i];
decoder->private_->side_subframe[i] = (val << x);
}
}
}
return true;
}
FLAC__bool read_subframe_constant_(FLAC__StreamDecoder *decoder, uint32_t channel, uint32_t bps, FLAC__bool do_full_decode)
{
FLAC__Subframe_Constant *subframe = &decoder->private_->frame.subframes[channel].data.constant;
FLAC__int64 x;
uint32_t i;
decoder->private_->frame.subframes[channel].type = FLAC__SUBFRAME_TYPE_CONSTANT;
if(!FLAC__bitreader_read_raw_int64(decoder->private_->input, &x, bps))
return false; /* read_callback_ sets the state for us */
subframe->value = x;
/* decode the subframe */
if(do_full_decode) {
if(bps <= 32) {
FLAC__int32 *output = decoder->private_->output[channel];
for(i = 0; i < decoder->private_->frame.header.blocksize; i++)
output[i] = x;
} else {
FLAC__int64 *output = decoder->private_->side_subframe;
decoder->private_->side_subframe_in_use = true;
for(i = 0; i < decoder->private_->frame.header.blocksize; i++)
output[i] = x;
}
}
return true;
}
FLAC__bool read_subframe_fixed_(FLAC__StreamDecoder *decoder, uint32_t channel, uint32_t bps, const uint32_t order, FLAC__bool do_full_decode)
{
FLAC__Subframe_Fixed *subframe = &decoder->private_->frame.subframes[channel].data.fixed;
FLAC__int64 i64;
FLAC__uint32 u32;
uint32_t u;
decoder->private_->frame.subframes[channel].type = FLAC__SUBFRAME_TYPE_FIXED;
subframe->residual = decoder->private_->residual[channel];
subframe->order = order;
/* read warm-up samples */
for(u = 0; u < order; u++) {
if(!FLAC__bitreader_read_raw_int64(decoder->private_->input, &i64, bps))
return false; /* read_callback_ sets the state for us */
subframe->warmup[u] = i64;
}
/* read entropy coding method info */
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &u32, FLAC__ENTROPY_CODING_METHOD_TYPE_LEN))
return false; /* read_callback_ sets the state for us */
subframe->entropy_coding_method.type = (FLAC__EntropyCodingMethodType)u32;
switch(subframe->entropy_coding_method.type) {
case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE:
case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2:
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &u32, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN))
return false; /* read_callback_ sets the state for us */
if((decoder->private_->frame.header.blocksize >> u32 < order) ||
(decoder->private_->frame.header.blocksize % (1 << u32) > 0)) {
send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC);
decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
return true;
}
subframe->entropy_coding_method.data.partitioned_rice.order = u32;
subframe->entropy_coding_method.data.partitioned_rice.contents = &decoder->private_->partitioned_rice_contents[channel];
break;
default:
send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM);
decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
return true;
}
/* read residual */
switch(subframe->entropy_coding_method.type) {
case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE:
case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2:
if(!read_residual_partitioned_rice_(decoder, order, subframe->entropy_coding_method.data.partitioned_rice.order, &decoder->private_->partitioned_rice_contents[channel], decoder->private_->residual[channel], /*is_extended=*/subframe->entropy_coding_method.type == FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2))
return false;
break;
default:
FLAC__ASSERT(0);
}
/* decode the subframe */
if(do_full_decode) {
if(bps < 33){
uint32_t i;
for(i = 0; i < order; i++)
decoder->private_->output[channel][i] = subframe->warmup[i];
if(bps+order <= 32)
FLAC__fixed_restore_signal(decoder->private_->residual[channel], decoder->private_->frame.header.blocksize-order, order, decoder->private_->output[channel]+order);
else
FLAC__fixed_restore_signal_wide(decoder->private_->residual[channel], decoder->private_->frame.header.blocksize-order, order, decoder->private_->output[channel]+order);
}
else {
decoder->private_->side_subframe_in_use = true;
memcpy(decoder->private_->side_subframe, subframe->warmup, sizeof(FLAC__int64) * order);
FLAC__fixed_restore_signal_wide_33bit(decoder->private_->residual[channel], decoder->private_->frame.header.blocksize-order, order, decoder->private_->side_subframe+order);
}
}
return true;
}
FLAC__bool read_subframe_lpc_(FLAC__StreamDecoder *decoder, uint32_t channel, uint32_t bps, const uint32_t order, FLAC__bool do_full_decode)
{
FLAC__Subframe_LPC *subframe = &decoder->private_->frame.subframes[channel].data.lpc;
FLAC__int32 i32;
FLAC__int64 i64;
FLAC__uint32 u32;
uint32_t u;
decoder->private_->frame.subframes[channel].type = FLAC__SUBFRAME_TYPE_LPC;
subframe->residual = decoder->private_->residual[channel];
subframe->order = order;
/* read warm-up samples */
for(u = 0; u < order; u++) {
if(!FLAC__bitreader_read_raw_int64(decoder->private_->input, &i64, bps))
return false; /* read_callback_ sets the state for us */
subframe->warmup[u] = i64;
}
/* read qlp coeff precision */
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &u32, FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN))
return false; /* read_callback_ sets the state for us */
if(u32 == (1u << FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN) - 1) {
send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC);
decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
return true;
}
subframe->qlp_coeff_precision = u32+1;
/* read qlp shift */
if(!FLAC__bitreader_read_raw_int32(decoder->private_->input, &i32, FLAC__SUBFRAME_LPC_QLP_SHIFT_LEN))
return false; /* read_callback_ sets the state for us */
if(i32 < 0) {
send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC);
decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
return true;
}
subframe->quantization_level = i32;
/* read quantized lp coefficiencts */
for(u = 0; u < order; u++) {
if(!FLAC__bitreader_read_raw_int32(decoder->private_->input, &i32, subframe->qlp_coeff_precision))
return false; /* read_callback_ sets the state for us */
subframe->qlp_coeff[u] = i32;
}
/* read entropy coding method info */
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &u32, FLAC__ENTROPY_CODING_METHOD_TYPE_LEN))
return false; /* read_callback_ sets the state for us */
subframe->entropy_coding_method.type = (FLAC__EntropyCodingMethodType)u32;
switch(subframe->entropy_coding_method.type) {
case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE:
case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2:
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &u32, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN))
return false; /* read_callback_ sets the state for us */
if((decoder->private_->frame.header.blocksize >> u32 < order) ||
(decoder->private_->frame.header.blocksize % (1 << u32) > 0)) {
send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC);
decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
return true;
}
subframe->entropy_coding_method.data.partitioned_rice.order = u32;
subframe->entropy_coding_method.data.partitioned_rice.contents = &decoder->private_->partitioned_rice_contents[channel];
break;
default:
send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM);
decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
return true;
}
/* read residual */
switch(subframe->entropy_coding_method.type) {
case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE:
case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2:
if(!read_residual_partitioned_rice_(decoder, order, subframe->entropy_coding_method.data.partitioned_rice.order, &decoder->private_->partitioned_rice_contents[channel], decoder->private_->residual[channel], /*is_extended=*/subframe->entropy_coding_method.type == FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2))
return false;
break;
default:
FLAC__ASSERT(0);
}
/* decode the subframe */
if(do_full_decode) {
if(bps <= 32) {
uint32_t i;
for(i = 0; i < order; i++)
decoder->private_->output[channel][i] = subframe->warmup[i];
if(FLAC__lpc_max_residual_bps(bps, subframe->qlp_coeff, order, subframe->quantization_level) <= 32 &&
FLAC__lpc_max_prediction_before_shift_bps(bps, subframe->qlp_coeff, order) <= 32)
FLAC__lpc_restore_signal(decoder->private_->residual[channel], decoder->private_->frame.header.blocksize-order, subframe->qlp_coeff, order, subframe->quantization_level, decoder->private_->output[channel]+order);
else
FLAC__lpc_restore_signal_wide(decoder->private_->residual[channel], decoder->private_->frame.header.blocksize-order, subframe->qlp_coeff, order, subframe->quantization_level, decoder->private_->output[channel]+order);
}
else {
decoder->private_->side_subframe_in_use = true;
memcpy(decoder->private_->side_subframe, subframe->warmup, sizeof(FLAC__int64) * order);
FLAC__lpc_restore_signal_wide_33bit(decoder->private_->residual[channel], decoder->private_->frame.header.blocksize-order, subframe->qlp_coeff, order, subframe->quantization_level, decoder->private_->side_subframe+order);
}
}
return true;
}
FLAC__bool read_subframe_verbatim_(FLAC__StreamDecoder *decoder, uint32_t channel, uint32_t bps, FLAC__bool do_full_decode)
{
FLAC__Subframe_Verbatim *subframe = &decoder->private_->frame.subframes[channel].data.verbatim;
uint32_t i;
decoder->private_->frame.subframes[channel].type = FLAC__SUBFRAME_TYPE_VERBATIM;
if(bps < 33) {
FLAC__int32 x, *residual = decoder->private_->residual[channel];
subframe->data_type = FLAC__VERBATIM_SUBFRAME_DATA_TYPE_INT32;
subframe->data.int32 = residual;
for(i = 0; i < decoder->private_->frame.header.blocksize; i++) {
if(!FLAC__bitreader_read_raw_int32(decoder->private_->input, &x, bps))
return false; /* read_callback_ sets the state for us */
residual[i] = x;
}
/* decode the subframe */
if(do_full_decode)
memcpy(decoder->private_->output[channel], subframe->data.int32, sizeof(FLAC__int32) * decoder->private_->frame.header.blocksize);
}
else {
FLAC__int64 x, *side = decoder->private_->side_subframe;
subframe->data_type = FLAC__VERBATIM_SUBFRAME_DATA_TYPE_INT64;
subframe->data.int64 = side;
decoder->private_->side_subframe_in_use = true;
for(i = 0; i < decoder->private_->frame.header.blocksize; i++) {
if(!FLAC__bitreader_read_raw_int64(decoder->private_->input, &x, bps))
return false; /* read_callback_ sets the state for us */
side[i] = x;
}
}
return true;
}
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)
{
FLAC__uint32 rice_parameter;
int i;
uint32_t partition, sample, u;
const uint32_t partitions = 1u << partition_order;
const uint32_t partition_samples = decoder->private_->frame.header.blocksize >> partition_order;
const uint32_t plen = is_extended? FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_PARAMETER_LEN : FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN;
const uint32_t pesc = is_extended? FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_ESCAPE_PARAMETER : FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER;
/* invalid predictor and partition orders mush be handled in the callers */
FLAC__ASSERT(partition_order > 0? partition_samples >= predictor_order : decoder->private_->frame.header.blocksize >= predictor_order);
if(!FLAC__format_entropy_coding_method_partitioned_rice_contents_ensure_size(partitioned_rice_contents, flac_max(6u, partition_order))) {
decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
return false;
}
sample = 0;
for(partition = 0; partition < partitions; partition++) {
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &rice_parameter, plen))
return false; /* read_callback_ sets the state for us */
partitioned_rice_contents->parameters[partition] = rice_parameter;
if(rice_parameter < pesc) {
partitioned_rice_contents->raw_bits[partition] = 0;
u = (partition == 0) ? partition_samples - predictor_order : partition_samples;
if(!decoder->private_->local_bitreader_read_rice_signed_block(decoder->private_->input, residual + sample, u, rice_parameter)){
if(decoder->protected_->state == FLAC__STREAM_DECODER_READ_FRAME) {
/* no error was set, read_callback_ didn't set it, so
* invalid rice symbol was found */
send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC);
decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
return true;
}
else
return false; /* read_callback_ sets the state for us */
}
sample += u;
}
else {
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &rice_parameter, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_RAW_LEN))
return false; /* read_callback_ sets the state for us */
partitioned_rice_contents->raw_bits[partition] = rice_parameter;
if(rice_parameter == 0) {
for(u = (partition == 0)? predictor_order : 0; u < partition_samples; u++, sample++)
residual[sample] = 0;
}
else{
for(u = (partition == 0)? predictor_order : 0; u < partition_samples; u++, sample++) {
if(!FLAC__bitreader_read_raw_int32(decoder->private_->input, &i, rice_parameter))
return false; /* read_callback_ sets the state for us */
residual[sample] = i;
}
}
}
}
return true;
}
FLAC__bool read_zero_padding_(FLAC__StreamDecoder *decoder)
{
if(!FLAC__bitreader_is_consumed_byte_aligned(decoder->private_->input)) {
FLAC__uint32 zero = 0;
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &zero, FLAC__bitreader_bits_left_for_byte_alignment(decoder->private_->input)))
return false; /* read_callback_ sets the state for us */
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
if(zero != 0) {
send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC);
decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
}
#endif
}
return true;
}
FLAC__bool read_callback_(FLAC__byte buffer[], size_t *bytes, void *client_data)
{
FLAC__StreamDecoder *decoder = (FLAC__StreamDecoder *)client_data;
if(
#if FLAC__HAS_OGG
/* see [1] HACK NOTE below for why we don't call the eof_callback when decoding Ogg FLAC */
!decoder->private_->is_ogg &&
#endif
decoder->private_->eof_callback && decoder->private_->eof_callback(decoder, decoder->private_->client_data)
) {
*bytes = 0;
decoder->protected_->state = FLAC__STREAM_DECODER_END_OF_STREAM;
return false;
}
else if(*bytes > 0) {
/* While seeking, it is possible for our seek to land in the
* middle of audio data that looks exactly like a frame header
* from a future version of an encoder. When that happens, our
* error callback will get an
* FLAC__STREAM_DECODER_UNPARSEABLE_STREAM and increment its
* unparseable_frame_count. But there is a remote possibility
* that it is properly synced at such a "future-codec frame",
* so to make sure, we wait to see many "unparseable" errors in
* a row before bailing out.
*/
if(decoder->private_->is_seeking && decoder->private_->unparseable_frame_count > 20) {
decoder->protected_->state = FLAC__STREAM_DECODER_ABORTED;
return false;
}
else {
const FLAC__StreamDecoderReadStatus status =
#if FLAC__HAS_OGG
decoder->private_->is_ogg?
read_callback_ogg_aspect_(decoder, buffer, bytes) :
#endif
decoder->private_->read_callback(decoder, buffer, bytes, decoder->private_->client_data)
;
if(status == FLAC__STREAM_DECODER_READ_STATUS_ABORT) {
decoder->protected_->state = FLAC__STREAM_DECODER_ABORTED;
return false;
}
else if(*bytes == 0) {
if(
status == FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM ||
(
#if FLAC__HAS_OGG
/* see [1] HACK NOTE below for why we don't call the eof_callback when decoding Ogg FLAC */
!decoder->private_->is_ogg &&
#endif
decoder->private_->eof_callback && decoder->private_->eof_callback(decoder, decoder->private_->client_data)
)
) {
decoder->protected_->state = FLAC__STREAM_DECODER_END_OF_STREAM;
return false;
}
else
return true;
}
else
return true;
}
}
else {
/* abort to avoid a deadlock */
decoder->protected_->state = FLAC__STREAM_DECODER_ABORTED;
return false;
}
/* [1] @@@ HACK NOTE: The end-of-stream checking has to be hacked around
* for Ogg FLAC. This is because the ogg decoder aspect can lose sync
* and at the same time hit the end of the stream (for example, seeking
* to a point that is after the beginning of the last Ogg page). There
* is no way to report an Ogg sync loss through the callbacks (see note
* in read_callback_ogg_aspect_()) so it returns CONTINUE with *bytes==0.
* So to keep the decoder from stopping at this point we gate the call
* to the eof_callback and let the Ogg decoder aspect set the
* end-of-stream state when it is needed.
*/
}
#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && !defined(FUZZING_BUILD_MODE_FLAC_SANITIZE_SIGNED_INTEGER_OVERFLOW)
/* The attribute below is to silence the undefined sanitizer of oss-fuzz.
* Because fuzzing feeds bogus predictors and residual samples to the
* decoder, having overflows in this section is unavoidable. Also,
* because the calculated values are audio path only, there is no
* potential for security problems */
__attribute__((no_sanitize("signed-integer-overflow")))
#endif
void undo_channel_coding(FLAC__StreamDecoder *decoder) {
uint32_t i;
switch(decoder->private_->frame.header.channel_assignment) {
case FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT:
/* do nothing */
break;
case FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE:
FLAC__ASSERT(decoder->private_->frame.header.channels == 2);
FLAC__ASSERT(decoder->private_->side_subframe_in_use != /* logical XOR */ (decoder->private_->frame.header.bits_per_sample < 32));
for(i = 0; i < decoder->private_->frame.header.blocksize; i++)
if(decoder->private_->side_subframe_in_use)
decoder->private_->output[1][i] = decoder->private_->output[0][i] - decoder->private_->side_subframe[i];
else
decoder->private_->output[1][i] = decoder->private_->output[0][i] - decoder->private_->output[1][i];
break;
case FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE:
FLAC__ASSERT(decoder->private_->frame.header.channels == 2);
FLAC__ASSERT(decoder->private_->side_subframe_in_use != /* logical XOR */ (decoder->private_->frame.header.bits_per_sample < 32));
for(i = 0; i < decoder->private_->frame.header.blocksize; i++)
if(decoder->private_->side_subframe_in_use)
decoder->private_->output[0][i] = decoder->private_->output[1][i] + decoder->private_->side_subframe[i];
else
decoder->private_->output[0][i] += decoder->private_->output[1][i];
break;
case FLAC__CHANNEL_ASSIGNMENT_MID_SIDE:
FLAC__ASSERT(decoder->private_->frame.header.channels == 2);
FLAC__ASSERT(decoder->private_->side_subframe_in_use != /* logical XOR */ (decoder->private_->frame.header.bits_per_sample < 32));
for(i = 0; i < decoder->private_->frame.header.blocksize; i++) {
if(!decoder->private_->side_subframe_in_use){
FLAC__int32 mid, side;
mid = decoder->private_->output[0][i];
side = decoder->private_->output[1][i];
mid = ((uint32_t) mid) << 1;
mid |= (side & 1); /* i.e. if 'side' is odd... */
decoder->private_->output[0][i] = (mid + side) >> 1;
decoder->private_->output[1][i] = (mid - side) >> 1;
}
else { /* bps == 32 */
FLAC__int64 mid;
mid = ((uint64_t)decoder->private_->output[0][i]) << 1;
mid |= (decoder->private_->side_subframe[i] & 1); /* i.e. if 'side' is odd... */
decoder->private_->output[0][i] = (mid + decoder->private_->side_subframe[i]) >> 1;
decoder->private_->output[1][i] = (mid - decoder->private_->side_subframe[i]) >> 1;
}
}
break;
default:
FLAC__ASSERT(0);
break;
}
}
#if FLAC__HAS_OGG
FLAC__StreamDecoderReadStatus read_callback_ogg_aspect_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes)
{
switch(FLAC__ogg_decoder_aspect_read_callback_wrapper(&decoder->protected_->ogg_decoder_aspect, buffer, bytes, read_callback_proxy_, decoder, decoder->private_->client_data)) {
case FLAC__OGG_DECODER_ASPECT_READ_STATUS_OK:
return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
/* we don't really have a way to handle lost sync via read
* callback so we'll let it pass and let the underlying
* FLAC decoder catch the error
*/
case FLAC__OGG_DECODER_ASPECT_READ_STATUS_LOST_SYNC:
return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
case FLAC__OGG_DECODER_ASPECT_READ_STATUS_END_OF_STREAM:
return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
case FLAC__OGG_DECODER_ASPECT_READ_STATUS_NOT_FLAC:
case FLAC__OGG_DECODER_ASPECT_READ_STATUS_UNSUPPORTED_MAPPING_VERSION:
case FLAC__OGG_DECODER_ASPECT_READ_STATUS_ABORT:
case FLAC__OGG_DECODER_ASPECT_READ_STATUS_ERROR:
case FLAC__OGG_DECODER_ASPECT_READ_STATUS_MEMORY_ALLOCATION_ERROR:
return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
default:
FLAC__ASSERT(0);
/* double protection */
return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
}
}
FLAC__OggDecoderAspectReadStatus read_callback_proxy_(const void *void_decoder, FLAC__byte buffer[], size_t *bytes, void *client_data)
{
FLAC__StreamDecoder *decoder = (FLAC__StreamDecoder*)void_decoder;
switch(decoder->private_->read_callback(decoder, buffer, bytes, client_data)) {
case FLAC__STREAM_DECODER_READ_STATUS_CONTINUE:
return FLAC__OGG_DECODER_ASPECT_READ_STATUS_OK;
case FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM:
return FLAC__OGG_DECODER_ASPECT_READ_STATUS_END_OF_STREAM;
case FLAC__STREAM_DECODER_READ_STATUS_ABORT:
return FLAC__OGG_DECODER_ASPECT_READ_STATUS_ABORT;
default:
/* double protection: */
FLAC__ASSERT(0);
return FLAC__OGG_DECODER_ASPECT_READ_STATUS_ABORT;
}
}
#endif
FLAC__StreamDecoderWriteStatus write_audio_frame_to_client_(FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[])
{
decoder->private_->last_frame = *frame; /* save the frame */
decoder->private_->last_frame_is_set = true;
if(decoder->private_->is_seeking) {
FLAC__uint64 this_frame_sample = frame->header.number.sample_number;
FLAC__uint64 next_frame_sample = this_frame_sample + (FLAC__uint64)frame->header.blocksize;
FLAC__uint64 target_sample = decoder->private_->target_sample;
FLAC__ASSERT(frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER);
#if FLAC__HAS_OGG
decoder->private_->got_a_frame = true;
#endif
if(this_frame_sample <= target_sample && target_sample < next_frame_sample) { /* we hit our target frame */
uint32_t delta = (uint32_t)(target_sample - this_frame_sample);
/* kick out of seek mode */
decoder->private_->is_seeking = false;
/* shift out the samples before target_sample */
if(delta > 0) {
uint32_t channel;
const FLAC__int32 *newbuffer[FLAC__MAX_CHANNELS];
for(channel = 0; channel < frame->header.channels; channel++) {
newbuffer[channel] = buffer[channel] + delta;
decoder->private_->last_frame.subframes[channel].type = FLAC__SUBFRAME_TYPE_VERBATIM;
decoder->private_->last_frame.subframes[channel].data.verbatim.data_type = FLAC__VERBATIM_SUBFRAME_DATA_TYPE_INT32;
decoder->private_->last_frame.subframes[channel].data.verbatim.data.int32 = newbuffer[channel];
}
decoder->private_->last_frame.header.blocksize -= delta;
decoder->private_->last_frame.header.number.sample_number += (FLAC__uint64)delta;
/* write the relevant samples */
return decoder->private_->write_callback(decoder, &decoder->private_->last_frame, newbuffer, decoder->private_->client_data);
}
else {
/* write the relevant samples */
return decoder->private_->write_callback(decoder, frame, buffer, decoder->private_->client_data);
}
}
else {
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
}
}
else {
/*
* If we never got STREAMINFO, turn off MD5 checking to save
* cycles since we don't have a sum to compare to anyway
*/
if(!decoder->private_->has_stream_info)
decoder->private_->do_md5_checking = false;
if(decoder->private_->do_md5_checking) {
if(!FLAC__MD5Accumulate(&decoder->private_->md5context, buffer, frame->header.channels, frame->header.blocksize, (frame->header.bits_per_sample+7) / 8))
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
}
return decoder->private_->write_callback(decoder, frame, buffer, decoder->private_->client_data);
}
}
void send_error_to_client_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status)
{
if(!decoder->private_->is_seeking)
decoder->private_->error_callback(decoder, status, decoder->private_->client_data);
else if(status == FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM)
decoder->private_->unparseable_frame_count++;
}
FLAC__bool seek_to_absolute_sample_(FLAC__StreamDecoder *decoder, FLAC__uint64 stream_length, FLAC__uint64 target_sample)
{
FLAC__uint64 first_frame_offset = decoder->private_->first_frame_offset, lower_bound, upper_bound, lower_bound_sample, upper_bound_sample, this_frame_sample;
FLAC__int64 pos = -1;
int i;
uint32_t approx_bytes_per_frame;
FLAC__bool first_seek = true, seek_from_lower_bound = false;
const FLAC__uint64 total_samples = FLAC__stream_decoder_get_total_samples(decoder);
const uint32_t min_blocksize = decoder->private_->stream_info.data.stream_info.min_blocksize;
const uint32_t max_blocksize = decoder->private_->stream_info.data.stream_info.max_blocksize;
const uint32_t max_framesize = decoder->private_->stream_info.data.stream_info.max_framesize;
const uint32_t min_framesize = decoder->private_->stream_info.data.stream_info.min_framesize;
/* take these from the current frame in case they've changed mid-stream */
uint32_t channels = FLAC__stream_decoder_get_channels(decoder);
uint32_t bps = FLAC__stream_decoder_get_bits_per_sample(decoder);
const FLAC__StreamMetadata_SeekTable *seek_table = decoder->private_->has_seek_table? &decoder->private_->seek_table.data.seek_table : 0;
/* use values from stream info if we didn't decode a frame */
if(channels == 0)
channels = decoder->private_->stream_info.data.stream_info.channels;
if(bps == 0)
bps = decoder->private_->stream_info.data.stream_info.bits_per_sample;
/* we are just guessing here */
if(max_framesize > 0)
approx_bytes_per_frame = (max_framesize + min_framesize) / 2 + 1;
/*
* Check if it's a known fixed-blocksize stream. Note that though
* the spec doesn't allow zeroes in the STREAMINFO block, we may
* never get a STREAMINFO block when decoding so the value of
* min_blocksize might be zero.
*/
else if(min_blocksize == max_blocksize && min_blocksize > 0) {
/* note there are no () around 'bps/8' to keep precision up since it's an integer calculation */
approx_bytes_per_frame = min_blocksize * channels * bps/8 + 64;
}
else
approx_bytes_per_frame = 4096 * channels * bps/8 + 64;
/*
* First, we set an upper and lower bound on where in the
* stream we will search. For now we take the current position
* as one bound and, depending on where the target position lies,
* the beginning of the first frame or the end of the stream as
* the other bound.
*/
lower_bound = first_frame_offset;
lower_bound_sample = 0;
upper_bound = stream_length;
upper_bound_sample = total_samples > 0 ? total_samples : target_sample /*estimate it*/;
if(decoder->protected_->state == FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC &&
decoder->private_->samples_decoded != 0) {
if(target_sample < decoder->private_->samples_decoded) {
if(FLAC__stream_decoder_get_decode_position(decoder, &upper_bound))
upper_bound_sample = decoder->private_->samples_decoded;
} else {
if(FLAC__stream_decoder_get_decode_position(decoder, &lower_bound))
lower_bound_sample = decoder->private_->samples_decoded;
}
}
/*
* Now we refine the bounds if we have a seektable with
* suitable points. Note that according to the spec they
* must be ordered by ascending sample number.
*
* Note: to protect against invalid seek tables we will ignore points
* that have frame_samples==0 or sample_number>=total_samples. Also,
* because math is limited to 64-bit ints, seekpoints with an offset
* larger than 2^63 (8 exbibyte) are rejected.
*/
if(seek_table) {
FLAC__uint64 new_lower_bound = lower_bound;
FLAC__uint64 new_upper_bound = upper_bound;
FLAC__uint64 new_lower_bound_sample = lower_bound_sample;
FLAC__uint64 new_upper_bound_sample = upper_bound_sample;
/* find the closest seek point <= target_sample, if it exists */
for(i = (int)seek_table->num_points - 1; i >= 0; i--) {
if(
seek_table->points[i].sample_number != FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER &&
seek_table->points[i].frame_samples > 0 && /* defense against bad seekpoints */
(total_samples <= 0 || seek_table->points[i].sample_number < total_samples) && /* defense against bad seekpoints */
seek_table->points[i].sample_number <= target_sample
)
break;
}
if(i >= 0) { /* i.e. we found a suitable seek point... */
new_lower_bound = first_frame_offset + seek_table->points[i].stream_offset;
new_lower_bound_sample = seek_table->points[i].sample_number;
}
/* find the closest seek point > target_sample, if it exists */
for(i = 0; i < (int)seek_table->num_points; i++) {
if(
seek_table->points[i].sample_number != FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER &&
seek_table->points[i].frame_samples > 0 && /* defense against bad seekpoints */
(total_samples <= 0 || seek_table->points[i].sample_number < total_samples) && /* defense against bad seekpoints */
seek_table->points[i].sample_number > target_sample
)
break;
}
if(i < (int)seek_table->num_points) { /* i.e. we found a suitable seek point... */
new_upper_bound = first_frame_offset + seek_table->points[i].stream_offset;
new_upper_bound_sample = seek_table->points[i].sample_number;
}
/* final protection against unsorted seek tables; keep original values if bogus */
if(new_upper_bound >= new_lower_bound) {
lower_bound = new_lower_bound;
upper_bound = new_upper_bound;
lower_bound_sample = new_lower_bound_sample;
upper_bound_sample = new_upper_bound_sample;
}
}
FLAC__ASSERT(upper_bound_sample >= lower_bound_sample);
/* there are 2 insidious ways that the following equality occurs, which
* we need to fix:
* 1) total_samples is 0 (unknown) and target_sample is 0
* 2) total_samples is 0 (unknown) and target_sample happens to be
* exactly equal to the last seek point in the seek table; this
* means there is no seek point above it, and upper_bound_samples
* remains equal to the estimate (of target_samples) we made above
* in either case it does not hurt to move upper_bound_sample up by 1
*/
if(upper_bound_sample == lower_bound_sample)
upper_bound_sample++;
decoder->private_->target_sample = target_sample;
while(1) {
/* check whether decoder is still valid so bad state isn't overwritten
* with seek error */
if(decoder->protected_->state == FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR ||
decoder->protected_->state == FLAC__STREAM_DECODER_ABORTED)
return false;
/* check if the bounds are still ok */
if (lower_bound_sample >= upper_bound_sample ||
lower_bound > upper_bound ||
upper_bound >= INT64_MAX) {
decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR;
return false;
}
if(seek_from_lower_bound) {
pos = lower_bound;
}
else {
#ifndef FLAC__INTEGER_ONLY_LIBRARY
pos = (FLAC__int64)lower_bound + (FLAC__int64)((double)(target_sample - lower_bound_sample) / (double)(upper_bound_sample - lower_bound_sample) * (double)(upper_bound - lower_bound)) - approx_bytes_per_frame;
#else
/* a little less accurate: */
if(upper_bound - lower_bound < 0xffffffff)
pos = (FLAC__int64)lower_bound + (FLAC__int64)(((target_sample - lower_bound_sample) * (upper_bound - lower_bound)) / (upper_bound_sample - lower_bound_sample)) - approx_bytes_per_frame;
else { /* @@@ WATCHOUT, ~2TB limit */
FLAC__uint64 ratio = (1<<16) / (upper_bound_sample - lower_bound_sample);
pos = (FLAC__int64)lower_bound + (FLAC__int64)((((target_sample - lower_bound_sample)>>8) * ((upper_bound - lower_bound)>>8) * ratio)) - approx_bytes_per_frame;
}
#endif
}
if(pos >= (FLAC__int64)upper_bound)
pos = (FLAC__int64)upper_bound - 1;
if(pos < (FLAC__int64)lower_bound)
pos = (FLAC__int64)lower_bound;
if(decoder->private_->seek_callback(decoder, (FLAC__uint64)pos, decoder->private_->client_data) != FLAC__STREAM_DECODER_SEEK_STATUS_OK) {
decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR;
return false;
}
if(!FLAC__stream_decoder_flush(decoder)) {
/* above call sets the state for us */
return false;
}
/* Now we need to get a frame. First we need to reset our
* unparseable_frame_count; if we get too many unparseable
* frames in a row, the read callback will return
* FLAC__STREAM_DECODER_READ_STATUS_ABORT, causing
* FLAC__stream_decoder_process_single() to return false.
*/
decoder->private_->unparseable_frame_count = 0;
if(!FLAC__stream_decoder_process_single(decoder) || decoder->protected_->state == FLAC__STREAM_DECODER_ABORTED || 0 == decoder->private_->samples_decoded) {
/* No frame could be decoded */
if(decoder->protected_->state != FLAC__STREAM_DECODER_ABORTED && decoder->private_->eof_callback(decoder, decoder->private_->client_data) && !seek_from_lower_bound){
/* decoder has hit end of stream while processing corrupt
* frame. To remedy this, try decoding a frame at the lower
* bound so the seek after that hopefully ends up somewhere
* else */
seek_from_lower_bound = true;
continue;
}
else {
decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR;
return false;
}
}
seek_from_lower_bound = false;
/* our write callback will change the state when it gets to the target frame */
/* actually, we could have got_a_frame if our decoder is at FLAC__STREAM_DECODER_END_OF_STREAM so we need to check for that also */
if(!decoder->private_->is_seeking)
break;
FLAC__ASSERT(decoder->private_->last_frame.header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER);
this_frame_sample = decoder->private_->last_frame.header.number.sample_number;
if(this_frame_sample + decoder->private_->last_frame.header.blocksize >= upper_bound_sample && !first_seek) {
if (pos == (FLAC__int64)lower_bound) {
/* can't move back any more than the first frame, something is fatally wrong */
decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR;
return false;
}
/* our last move backwards wasn't big enough, try again */
approx_bytes_per_frame = approx_bytes_per_frame? approx_bytes_per_frame * 2 : 16;
continue;
}
/* allow one seek over upper bound, so we can get a correct upper_bound_sample for streams with unknown total_samples */
first_seek = false;
/* make sure we are not seeking in corrupted stream */
if (this_frame_sample < lower_bound_sample) {
decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR;
return false;
}
/* we need to narrow the search */
if(target_sample < this_frame_sample) {
upper_bound_sample = this_frame_sample + decoder->private_->last_frame.header.blocksize;
/*@@@@@@ what will decode position be if at end of stream? */
if(!FLAC__stream_decoder_get_decode_position(decoder, &upper_bound)) {
decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR;
return false;
}
approx_bytes_per_frame = (uint32_t)(2 * (upper_bound - pos) / 3 + 16);
}
else { /* target_sample >= this_frame_sample + this frame's blocksize */
lower_bound_sample = this_frame_sample + decoder->private_->last_frame.header.blocksize;
if(!FLAC__stream_decoder_get_decode_position(decoder, &lower_bound)) {
decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR;
return false;
}
approx_bytes_per_frame = (uint32_t)(2 * (lower_bound - pos) / 3 + 16);
}
}
return true;
}
#if FLAC__HAS_OGG
FLAC__bool seek_to_absolute_sample_ogg_(FLAC__StreamDecoder *decoder, FLAC__uint64 stream_length, FLAC__uint64 target_sample)
{
FLAC__uint64 left_pos = 0, right_pos = stream_length;
FLAC__uint64 left_sample = 0, right_sample = FLAC__stream_decoder_get_total_samples(decoder);
FLAC__uint64 this_frame_sample = (FLAC__uint64)0 - 1;
FLAC__uint64 pos = 0; /* only initialized to avoid compiler warning */
FLAC__bool did_a_seek;
uint32_t iteration = 0;
/* In the first iterations, we will calculate the target byte position
* by the distance from the target sample to left_sample and
* right_sample (let's call it "proportional search"). After that, we
* will switch to binary search.
*/
uint32_t BINARY_SEARCH_AFTER_ITERATION = 2;
/* We will switch to a linear search once our current sample is less
* than this number of samples ahead of the target sample
*/
static const FLAC__uint64 LINEAR_SEARCH_WITHIN_SAMPLES = FLAC__MAX_BLOCK_SIZE * 2;
/* If the total number of samples is unknown, use a large value, and
* force binary search immediately.
*/
if(right_sample == 0) {
right_sample = (FLAC__uint64)(-1);
BINARY_SEARCH_AFTER_ITERATION = 0;
}
decoder->private_->target_sample = target_sample;
for( ; ; iteration++) {
/* Do sanity checks on bounds */
if(right_pos <= left_pos || right_pos - left_pos < 9) {
/* FLAC frame is at least 9 byte in size */
decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR;
return false;
}
if (iteration == 0 || this_frame_sample > target_sample || target_sample - this_frame_sample > LINEAR_SEARCH_WITHIN_SAMPLES) {
if (iteration >= BINARY_SEARCH_AFTER_ITERATION) {
pos = (right_pos + left_pos) / 2;
}
else {
#ifndef FLAC__INTEGER_ONLY_LIBRARY
pos = (FLAC__uint64)((double)(target_sample - left_sample) / (double)(right_sample - left_sample) * (double)(right_pos - left_pos));
#else
/* a little less accurate: */
if ((target_sample-left_sample <= 0xffffffff) && (right_pos-left_pos <= 0xffffffff))
pos = (FLAC__int64)(((target_sample-left_sample) * (right_pos-left_pos)) / (right_sample-left_sample));
else /* @@@ WATCHOUT, ~2TB limit */
pos = (FLAC__int64)((((target_sample-left_sample)>>8) * ((right_pos-left_pos)>>8)) / ((right_sample-left_sample)>>16));
#endif
/* @@@ TODO: might want to limit pos to some distance
* before EOF, to make sure we land before the last frame,
* thereby getting a this_frame_sample and so having a better
* estimate.
*/
}
/* physical seek */
if(decoder->private_->seek_callback((FLAC__StreamDecoder*)decoder, (FLAC__uint64)pos, decoder->private_->client_data) != FLAC__STREAM_DECODER_SEEK_STATUS_OK) {
decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR;
return false;
}
if(!FLAC__stream_decoder_flush(decoder)) {
/* above call sets the state for us */
return false;
}
did_a_seek = true;
}
else
did_a_seek = false;
decoder->private_->got_a_frame = false;
if(!FLAC__stream_decoder_process_single(decoder) ||
decoder->protected_->state == FLAC__STREAM_DECODER_ABORTED) {
decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR;
return false;
}
if(!decoder->private_->got_a_frame) {
if(did_a_seek) {
/* this can happen if we seek to a point after the last frame; we drop
* to binary search right away in this case to avoid any wasted
* iterations of proportional search.
*/
right_pos = pos;
BINARY_SEARCH_AFTER_ITERATION = 0;
}
else {
/* this can probably only happen if total_samples is unknown and the
* target_sample is past the end of the stream
*/
decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR;
return false;
}
}
/* our write callback will change the state when it gets to the target frame */
else if(!decoder->private_->is_seeking) {
break;
}
else {
this_frame_sample = decoder->private_->last_frame.header.number.sample_number;
FLAC__ASSERT(decoder->private_->last_frame.header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER);
if (did_a_seek) {
if (this_frame_sample <= target_sample) {
/* The 'equal' case should not happen, since
* FLAC__stream_decoder_process_single()
* should recognize that it has hit the
* target sample and we would exit through
* the 'break' above.
*/
FLAC__ASSERT(this_frame_sample != target_sample);
left_sample = this_frame_sample;
/* sanity check to avoid infinite loop */
if (left_pos == pos) {
decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR;
return false;
}
left_pos = pos;
}
else {
right_sample = this_frame_sample;
/* sanity check to avoid infinite loop */
if (right_pos == pos) {
decoder->protected_->state = FLAC__STREAM_DECODER_SEEK_ERROR;
return false;
}
right_pos = pos;
}
}
}
}
return true;
}
#endif
FLAC__StreamDecoderReadStatus file_read_callback_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data)
{
(void)client_data;
if(*bytes > 0) {
*bytes = fread(buffer, sizeof(FLAC__byte), *bytes, decoder->private_->file);
if(ferror(decoder->private_->file))
return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
else if(*bytes == 0)
return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
else
return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
}
else
return FLAC__STREAM_DECODER_READ_STATUS_ABORT; /* abort to avoid a deadlock */
}
FLAC__StreamDecoderSeekStatus file_seek_callback_(const FLAC__StreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data)
{
(void)client_data;
if(decoder->private_->file == stdin)
return FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED;
else if(fseeko(decoder->private_->file, (FLAC__off_t)absolute_byte_offset, SEEK_SET) < 0)
return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
else
return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
}
FLAC__StreamDecoderTellStatus file_tell_callback_(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
{
FLAC__off_t pos;
(void)client_data;
if(decoder->private_->file == stdin)
return FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED;
else if((pos = ftello(decoder->private_->file)) < 0)
return FLAC__STREAM_DECODER_TELL_STATUS_ERROR;
else {
*absolute_byte_offset = (FLAC__uint64)pos;
return FLAC__STREAM_DECODER_TELL_STATUS_OK;
}
}
FLAC__StreamDecoderLengthStatus file_length_callback_(const FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data)
{
struct flac_stat_s filestats;
(void)client_data;
if(decoder->private_->file == stdin)
return FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED;
#ifndef FLAC__USE_FILELENGTHI64
if(flac_fstat(fileno(decoder->private_->file), &filestats) != 0)
#else
filestats.st_size = _filelengthi64(fileno(decoder->private_->file));
if(filestats.st_size < 0)
#endif
return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR;
else {
*stream_length = (FLAC__uint64)filestats.st_size;
return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
}
}
FLAC__bool file_eof_callback_(const FLAC__StreamDecoder *decoder, void *client_data)
{
(void)client_data;
return feof(decoder->private_->file)? true : false;
}