diff --git a/include/FLAC/encoder.h b/include/FLAC/encoder.h index 902c279b..decef04c 100644 --- a/include/FLAC/encoder.h +++ b/include/FLAC/encoder.h @@ -42,6 +42,7 @@ typedef enum { FLAC__ENCODER_BLOCK_SIZE_TOO_SMALL_FOR_LPC_ORDER, FLAC__ENCODER_NOT_STREAMABLE, FLAC__ENCODER_FRAMING_ERROR, + FLAC__ENCODER_INVALID_SEEK_TABLE, FLAC__ENCODER_FATAL_ERROR_WHILE_ENCODING, FLAC__ENCODER_FATAL_ERROR_WHILE_WRITING, /* that is, the write_callback returned an error */ FLAC__ENCODER_MEMORY_ALLOCATION_ERROR @@ -69,7 +70,8 @@ typedef struct { bool do_exhaustive_model_search; /* 0 => use estimated bits per residual for scoring, 1 => generate all, take shortest */ unsigned rice_optimization_level; /* 0 => estimate Rice parameter based on residual variance, 1-8 => partition residual, use parameter for each */ uint64 total_samples_estimate; /* may be 0 if unknown. this will be a placeholder in the metadata block until the actual total is calculated */ - unsigned padding; /* size of PADDING block to add; 0 => do not add a PADDING block */ + const FLAC__StreamMetaData_SeekTable *seek_table; /* optional seek_table to prepend, 0 => no seek table */ + unsigned padding; /* size of PADDING block to add (goes after seek table); 0 => do not add a PADDING block */ } FLAC__Encoder; diff --git a/src/libFLAC/encoder.c b/src/libFLAC/encoder.c index 3505fca1..82623ace 100644 --- a/src/libFLAC/encoder.c +++ b/src/libFLAC/encoder.c @@ -22,6 +22,7 @@ #include /* for malloc() */ #include /* for memcpy() */ #include "FLAC/encoder.h" +#include "FLAC/seek_table.h" #include "private/bitbuffer.h" #include "private/bitmath.h" #include "private/crc.h" @@ -265,6 +266,7 @@ FLAC__EncoderState FLAC__encoder_init(FLAC__Encoder *encoder, FLAC__EncoderWrite { unsigned i; FLAC__StreamMetaData padding; + FLAC__StreamMetaData seek_table; assert(sizeof(int) >= 4); /* we want to die right away if this is not true */ assert(encoder != 0); @@ -400,7 +402,7 @@ FLAC__EncoderState FLAC__encoder_init(FLAC__Encoder *encoder, FLAC__EncoderWrite return encoder->state = FLAC__ENCODER_FRAMING_ERROR; encoder->guts->metadata.type = FLAC__METADATA_TYPE_STREAMINFO; - encoder->guts->metadata.is_last = (encoder->padding == 0); + encoder->guts->metadata.is_last = (encoder->seek_table == 0 && encoder->padding == 0); encoder->guts->metadata.length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH; encoder->guts->metadata.data.stream_info.min_blocksize = encoder->blocksize; /* this encoder uses the same blocksize for the whole stream */ encoder->guts->metadata.data.stream_info.max_blocksize = encoder->blocksize; @@ -415,6 +417,17 @@ FLAC__EncoderState FLAC__encoder_init(FLAC__Encoder *encoder, FLAC__EncoderWrite if(!FLAC__add_metadata_block(&encoder->guts->metadata, &encoder->guts->frame)) return encoder->state = FLAC__ENCODER_FRAMING_ERROR; + if(0 != encoder->seek_table) { + if(!FLAC__seek_table_is_valid(encoder->seek_table)) + return encoder->state = FLAC__ENCODER_INVALID_SEEK_TABLE; + seek_table.type = FLAC__METADATA_TYPE_SEEKTABLE; + seek_table.is_last = (encoder->padding == 0); + seek_table.length = encoder->seek_table->num_points * FLAC__STREAM_METADATA_SEEKPOINT_LEN; + seek_table.data.seek_table = *encoder->seek_table; + if(!FLAC__add_metadata_block(&seek_table, &encoder->guts->frame)) + return encoder->state = FLAC__ENCODER_FRAMING_ERROR; + } + /* add a PADDING block if requested */ if(encoder->padding > 0) { padding.type = FLAC__METADATA_TYPE_PADDING; diff --git a/src/libFLAC/encoder_framing.c b/src/libFLAC/encoder_framing.c index cf998a80..7390e894 100644 --- a/src/libFLAC/encoder_framing.c +++ b/src/libFLAC/encoder_framing.c @@ -81,6 +81,16 @@ bool FLAC__add_metadata_block(const FLAC__StreamMetaData *metadata, FLAC__BitBuf if(!FLAC__bitbuffer_write_zeroes(bb, metadata->length * 8)) return false; break; + case FLAC__METADATA_TYPE_SEEKTABLE: + for(i = 0; i < metadata->data.seek_table.num_points; i++) { + if(!FLAC__bitbuffer_write_raw_uint64(bb, metadata->data.seek_table.points[i].sample_number, FLAC__STREAM_METADATA_SEEKPOINT_SAMPLE_NUMBER_LEN)) + return false; + if(!FLAC__bitbuffer_write_raw_uint64(bb, metadata->data.seek_table.points[i].stream_offset, FLAC__STREAM_METADATA_SEEKPOINT_STREAM_OFFSET_LEN)) + return false; + if(!FLAC__bitbuffer_write_raw_uint32(bb, metadata->data.seek_table.points[i].frame_samples, FLAC__STREAM_METADATA_SEEKPOINT_FRAME_SAMPLES_LEN)) + return false; + } + break; default: assert(0); }