From 9b4a014ea852de194e1d6d5ac268d6e421bfd284 Mon Sep 17 00:00:00 2001 From: Josh Coalson Date: Fri, 2 Aug 2002 06:30:31 +0000 Subject: [PATCH] use new seektable template functions, fix verify logic to work with revamped decoder process calls --- src/flac/encode.c | 233 ++++++++++++++++++++++------------------------ 1 file changed, 111 insertions(+), 122 deletions(-) diff --git a/src/flac/encode.c b/src/flac/encode.c index e1f5ecc7..7a5c18be 100644 --- a/src/flac/encode.c +++ b/src/flac/encode.c @@ -54,6 +54,12 @@ static const char *verify_code_string[] = { "FLAC__VERIFY_FAILED_IN_METADATA" }; +typedef enum { + ENCODER_IN_MAGIC = 0, + ENCODER_IN_METADATA = 1, + ENCODER_IN_AUDIO = 2 +} EncodeState; + typedef struct { FLAC__int32 *original[FLAC__MAX_CHANNELS]; unsigned size; /* of each original[] in samples */ @@ -61,7 +67,8 @@ typedef struct { const FLAC__byte *encoded_signal; unsigned encoded_signal_capacity; unsigned encoded_bytes; - FLAC__bool into_frames; + EncodeState encode_state; + FLAC__bool needs_magic_hack; verify_code result; FLAC__StreamDecoder *decoder; } verify_fifo_struct; @@ -87,7 +94,7 @@ typedef struct { FLAC__uint64 stream_offset; /* i.e. number of bytes before the first byte of the the first frame's header */ unsigned current_frame; verify_fifo_struct verify_fifo; - FLAC__StreamMetadata_SeekTable seek_table; + FLAC__StreamMetadata *seek_table; unsigned first_seek_point_to_check; #ifdef FLAC__HAS_OGG FLAC__bool use_ogg; @@ -108,9 +115,7 @@ static FLAC__int32 *input[FLAC__MAX_CHANNELS]; /* local routines */ static FLAC__bool init(encoder_wrapper_struct *encoder_wrapper); static FLAC__bool init_encoder(encode_options_t options, unsigned channels, unsigned bps, unsigned sample_rate, encoder_wrapper_struct *encoder_wrapper); -static FLAC__bool convert_to_seek_table(char *requested_seek_points, int num_requested_seek_points, FLAC__uint64 stream_samples, unsigned blocksize, FLAC__StreamMetadata_SeekTable *seek_table); -static void append_point_to_seek_table(FLAC__StreamMetadata_SeekTable *seek_table, FLAC__uint64 sample, FLAC__uint64 stream_samples, FLAC__uint64 blocksize); -static int seekpoint_compare(const FLAC__StreamMetadata_SeekPoint *l, const FLAC__StreamMetadata_SeekPoint *r); +static FLAC__bool convert_to_seek_table(char *requested_seek_points, int num_requested_seek_points, FLAC__uint64 stream_samples, FLAC__StreamMetadata *seek_table); static void format_input(FLAC__int32 *dest[], unsigned wide_samples, FLAC__bool is_big_endian, FLAC__bool is_unsigned_samples, unsigned channels, unsigned bps, encoder_wrapper_struct *encoder_wrapper); static void append_to_verify_fifo(encoder_wrapper_struct *encoder_wrapper, const FLAC__int32 * const input[], unsigned channels, unsigned wide_samples); static FLAC__StreamEncoderWriteStatus write_callback(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data); @@ -150,12 +155,17 @@ flac__encode_aif(FILE *infile, long infilesize, const char *infilename, const ch encoder_wrapper.stream_offset = 0; encoder_wrapper.inbasefilename = flac__file_get_basename(infilename); encoder_wrapper.outfilename = outfilename; - encoder_wrapper.seek_table.points = 0; + encoder_wrapper.seek_table = FLAC__metadata_object_new(FLAC__METADATA_TYPE_SEEKTABLE); encoder_wrapper.first_seek_point_to_check = 0; #ifdef FLAC__HAS_OGG encoder_wrapper.use_ogg = options.common.use_ogg; #endif + if(0 == encoder_wrapper.seek_table) { + fprintf(stderr, "%s: ERROR allocating memory for seek table\n", encoder_wrapper.inbasefilename); + return 1; + } + (void)infilesize; /* silence compiler warning about unused parameter */ (void)lookahead; /* silence compiler warning about unused parameter */ (void)lookahead_length; /* silence compiler warning about unused parameter */ @@ -352,7 +362,7 @@ flac__encode_aif(FILE *infile, long infilesize, const char *infilename, const ch if(!init_encoder(options.common, channels, bps, sample_rate, &encoder_wrapper)) status= ERROR; else - encoder_wrapper.verify_fifo.into_frames = true; + encoder_wrapper.verify_fifo.encode_state = ENCODER_IN_AUDIO; } /* first do any samples in the reservoir */ @@ -503,8 +513,8 @@ flac__encode_aif(FILE *infile, long infilesize, const char *infilename, const ch fprintf(stderr, "\n"); } - if(0 != encoder_wrapper.seek_table.points) - free(encoder_wrapper.seek_table.points); + if(0 != encoder_wrapper.seek_table) + FLAC__metadata_object_delete(encoder_wrapper.seek_table); if(options.common.verify) { FLAC__stream_decoder_finish(encoder_wrapper.verify_fifo.decoder); FLAC__stream_decoder_delete(encoder_wrapper.verify_fifo.decoder); @@ -551,7 +561,7 @@ int flac__encode_wav(FILE *infile, long infilesize, const char *infilename, cons encoder_wrapper.stream_offset = 0; encoder_wrapper.inbasefilename = flac__file_get_basename(infilename); encoder_wrapper.outfilename = outfilename; - encoder_wrapper.seek_table.points = 0; + encoder_wrapper.seek_table = FLAC__metadata_object_new(FLAC__METADATA_TYPE_SEEKTABLE); encoder_wrapper.first_seek_point_to_check = 0; #ifdef FLAC__HAS_OGG encoder_wrapper.use_ogg = options.common.use_ogg; @@ -560,6 +570,11 @@ int flac__encode_wav(FILE *infile, long infilesize, const char *infilename, cons (void)lookahead; (void)lookahead_length; + if(0 == encoder_wrapper.seek_table) { + fprintf(stderr, "%s: ERROR allocating memory for seek table\n", encoder_wrapper.inbasefilename); + return 1; + } + if(0 == strcmp(outfilename, "-")) { encoder_wrapper.fout = file__get_binary_stdout(); } @@ -701,7 +716,7 @@ int flac__encode_wav(FILE *infile, long infilesize, const char *infilename, cons if(!init_encoder(options.common, channels, bps, sample_rate, &encoder_wrapper)) goto wav_abort_; - encoder_wrapper.verify_fifo.into_frames = true; + encoder_wrapper.verify_fifo.encode_state = ENCODER_IN_AUDIO; /* * first do any samples in the reservoir @@ -854,8 +869,8 @@ int flac__encode_wav(FILE *infile, long infilesize, const char *infilename, cons print_stats(&encoder_wrapper); fprintf(stderr, "\n"); } - if(0 != encoder_wrapper.seek_table.points) - free(encoder_wrapper.seek_table.points); + if(0 != encoder_wrapper.seek_table) + FLAC__metadata_object_delete(encoder_wrapper.seek_table); if(options.common.verify) { FLAC__stream_decoder_finish(encoder_wrapper.verify_fifo.decoder); FLAC__stream_decoder_delete(encoder_wrapper.verify_fifo.decoder); @@ -882,8 +897,8 @@ wav_abort_: ogg_stream_clear(&encoder_wrapper.ogg.os); #endif } - if(0 != encoder_wrapper.seek_table.points) - free(encoder_wrapper.seek_table.points); + if(0 != encoder_wrapper.seek_table) + FLAC__metadata_object_delete(encoder_wrapper.seek_table); if(options.common.verify) { FLAC__stream_decoder_finish(encoder_wrapper.verify_fifo.decoder); FLAC__stream_decoder_delete(encoder_wrapper.verify_fifo.decoder); @@ -920,12 +935,17 @@ int flac__encode_raw(FILE *infile, long infilesize, const char *infilename, cons encoder_wrapper.stream_offset = 0; encoder_wrapper.inbasefilename = flac__file_get_basename(infilename); encoder_wrapper.outfilename = outfilename; - encoder_wrapper.seek_table.points = 0; + encoder_wrapper.seek_table = FLAC__metadata_object_new(FLAC__METADATA_TYPE_SEEKTABLE); encoder_wrapper.first_seek_point_to_check = 0; #ifdef FLAC__HAS_OGG encoder_wrapper.use_ogg = options.common.use_ogg; #endif + if(0 == encoder_wrapper.seek_table) { + fprintf(stderr, "%s: ERROR allocating memory for seek table\n", encoder_wrapper.inbasefilename); + return 1; + } + if(0 == strcmp(outfilename, "-")) { encoder_wrapper.fout = file__get_binary_stdout(); } @@ -993,7 +1013,7 @@ int flac__encode_raw(FILE *infile, long infilesize, const char *infilename, cons if(!init_encoder(options.common, options.channels, options.bps, options.sample_rate, &encoder_wrapper)) goto raw_abort_; - encoder_wrapper.verify_fifo.into_frames = true; + encoder_wrapper.verify_fifo.encode_state = ENCODER_IN_AUDIO; /* * first do any samples in the reservoir @@ -1111,8 +1131,8 @@ int flac__encode_raw(FILE *infile, long infilesize, const char *infilename, cons print_stats(&encoder_wrapper); fprintf(stderr, "\n"); } - if(0 != encoder_wrapper.seek_table.points) - free(encoder_wrapper.seek_table.points); + if(0 != encoder_wrapper.seek_table) + FLAC__metadata_object_delete(encoder_wrapper.seek_table); if(options.common.verify) { FLAC__stream_decoder_finish(encoder_wrapper.verify_fifo.decoder); FLAC__stream_decoder_delete(encoder_wrapper.verify_fifo.decoder); @@ -1139,8 +1159,8 @@ raw_abort_: ogg_stream_clear(&encoder_wrapper.ogg.os); #endif } - if(0 != encoder_wrapper.seek_table.points) - free(encoder_wrapper.seek_table.points); + if(0 != encoder_wrapper.seek_table) + FLAC__metadata_object_delete(encoder_wrapper.seek_table); if(options.common.verify) { FLAC__stream_decoder_finish(encoder_wrapper.verify_fifo.decoder); FLAC__stream_decoder_delete(encoder_wrapper.verify_fifo.decoder); @@ -1187,7 +1207,7 @@ FLAC__bool init(encoder_wrapper_struct *encoder_wrapper) FLAC__bool init_encoder(encode_options_t options, unsigned channels, unsigned bps, unsigned sample_rate, encoder_wrapper_struct *encoder_wrapper) { unsigned i, num_metadata; - FLAC__StreamMetadata seek_table, padding; + FLAC__StreamMetadata padding; FLAC__StreamMetadata *metadata[2]; if(channels != 2) @@ -1203,7 +1223,7 @@ FLAC__bool init_encoder(encode_options_t options, unsigned channels, unsigned bp } } encoder_wrapper->verify_fifo.tail = 0; - encoder_wrapper->verify_fifo.into_frames = false; + encoder_wrapper->verify_fifo.encode_state = ENCODER_IN_MAGIC; encoder_wrapper->verify_fifo.result = FLAC__VERIFY_OK; /* set up a stream decoder for verification */ @@ -1223,18 +1243,15 @@ FLAC__bool init_encoder(encode_options_t options, unsigned channels, unsigned bp } } - if(!convert_to_seek_table(options.requested_seek_points, options.num_requested_seek_points, encoder_wrapper->total_samples_to_encode, options.blocksize, &encoder_wrapper->seek_table)) { - fprintf(stderr, "%s: ERROR allocating seek table\n", encoder_wrapper->inbasefilename); + if(!convert_to_seek_table(options.requested_seek_points, options.num_requested_seek_points, encoder_wrapper->total_samples_to_encode, encoder_wrapper->seek_table)) { + fprintf(stderr, "%s: ERROR allocating memory for seek table\n", encoder_wrapper->inbasefilename); return false; } num_metadata = 0; - if(encoder_wrapper->seek_table.num_points > 0) { - seek_table.is_last = false; /* the encoder will set this for us */ - seek_table.type = FLAC__METADATA_TYPE_SEEKTABLE; - seek_table.length = encoder_wrapper->seek_table.num_points * FLAC__STREAM_METADATA_SEEKPOINT_LENGTH; - seek_table.data.seek_table = encoder_wrapper->seek_table; - metadata[num_metadata++] = &seek_table; + if(encoder_wrapper->seek_table->data.seek_table.num_points > 0) { + encoder_wrapper->seek_table->is_last = false; /* the encoder will set this for us */ + metadata[num_metadata++] = encoder_wrapper->seek_table; } if(options.padding > 0) { padding.is_last = false; /* the encoder will set this for us */ @@ -1275,13 +1292,10 @@ FLAC__bool init_encoder(encode_options_t options, unsigned channels, unsigned bp return true; } -FLAC__bool convert_to_seek_table(char *requested_seek_points, int num_requested_seek_points, FLAC__uint64 stream_samples, unsigned blocksize, FLAC__StreamMetadata_SeekTable *seek_table) +FLAC__bool convert_to_seek_table(char *requested_seek_points, int num_requested_seek_points, FLAC__uint64 stream_samples, FLAC__StreamMetadata *seek_table) { - unsigned i, j, real_points, placeholders; + unsigned i, real_points, placeholders; char *pt = requested_seek_points, *q; - FLAC__bool first; - - seek_table->num_points = 0; if(num_requested_seek_points == 0) return true; @@ -1314,82 +1328,36 @@ FLAC__bool convert_to_seek_table(char *requested_seek_points, int num_requested_ } pt = requested_seek_points; - /* make some space */ - if(0 == (seek_table->points = (FLAC__StreamMetadata_SeekPoint*)malloc(sizeof(FLAC__StreamMetadata_SeekPoint) * (real_points+placeholders)))) - return false; - - /* initialize the seek_table. we set frame_samples to zero to signify the points have not yet been hit by a frame write yet. */ - for(i = 0; i < real_points+placeholders; i++) { - seek_table->points[i].sample_number = FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER; - seek_table->points[i].stream_offset = 0; - seek_table->points[i].frame_samples = 0; - } - for(i = 0; i < (unsigned)num_requested_seek_points; i++) { q = strchr(pt, '<'); FLAC__ASSERT(0 != q); *q++ = '\0'; if(0 == strcmp(pt, "X")) { /* -S X */ - ; /* we append placeholders later */ + if(!FLAC__metadata_object_seektable_template_append_placeholders(seek_table, 1)) + return false; } else if(pt[strlen(pt)-1] == 'x') { /* -S #x */ if(stream_samples > 0) { /* we can only do these if we know the number of samples to encode up front */ - unsigned j, n; - n = (unsigned)atoi(pt); - for(j = 0; j < n; j++) - append_point_to_seek_table(seek_table, stream_samples * (FLAC__uint64)j / (FLAC__uint64)n, stream_samples, blocksize); + if(!FLAC__metadata_object_seektable_template_append_spaced_points(seek_table, atoi(pt), stream_samples)) + return false; } } else { /* -S # */ - append_point_to_seek_table(seek_table, (FLAC__uint64)atoi(pt), stream_samples, blocksize); + FLAC__uint64 n = (unsigned)atoi(pt); + if(!FLAC__metadata_object_seektable_template_append_point(seek_table, n)) + return false; } pt = q; } - /* sort the seekpoints */ - qsort(seek_table->points, seek_table->num_points, sizeof(FLAC__StreamMetadata_SeekPoint), (int (*)(const void *, const void *))seekpoint_compare); - - /* uniquify the seekpoints */ - first = true; - for(i = j = 0; i < seek_table->num_points; i++) { - if(!first) { - if(seek_table->points[i].sample_number == seek_table->points[j-1].sample_number) - continue; - } - first = false; - seek_table->points[j++] = seek_table->points[i]; - } - seek_table->num_points = j; - - /* append placeholders */ - for(i = 0, j = seek_table->num_points; i < placeholders; i++, j++) - seek_table->points[j].sample_number = FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER; - seek_table->num_points += placeholders; + if(!FLAC__metadata_object_seektable_template_sort(seek_table, /*compact=*/true)) + return false; return true; } -void append_point_to_seek_table(FLAC__StreamMetadata_SeekTable *seek_table, FLAC__uint64 sample, FLAC__uint64 stream_samples, FLAC__uint64 blocksize) -{ - const FLAC__uint64 target_sample = (sample / blocksize) * blocksize; - - if(stream_samples == 0 || target_sample < stream_samples) - seek_table->points[seek_table->num_points++].sample_number = target_sample; -} - -int seekpoint_compare(const FLAC__StreamMetadata_SeekPoint *l, const FLAC__StreamMetadata_SeekPoint *r) -{ - /* we don't just 'return l->sample_number - r->sample_number' since the result (FLAC__int64) might overflow an 'int' */ - if(l->sample_number == r->sample_number) - return 0; - else if(l->sample_number < r->sample_number) - return -1; - else - return 1; -} - void format_input(FLAC__int32 *dest[], unsigned wide_samples, FLAC__bool is_big_endian, FLAC__bool is_unsigned_samples, unsigned channels, unsigned bps, encoder_wrapper_struct *encoder_wrapper) { unsigned wide_sample, sample, channel, byte; @@ -1479,19 +1447,29 @@ FLAC__StreamEncoderWriteStatus write_callback(const FLAC__StreamEncoder *encoder const unsigned mask = (FLAC__stream_encoder_get_do_exhaustive_model_search(encoder) || FLAC__stream_encoder_get_do_qlp_coeff_prec_search(encoder))? 0x1f : 0x7f; /* mark the current seek point if hit (if stream_offset == 0 that means we're still writing metadata and haven't hit the first frame yet) */ - if(encoder_wrapper->stream_offset > 0 && encoder_wrapper->seek_table.num_points > 0) { - FLAC__uint64 current_sample = (FLAC__uint64)current_frame * (FLAC__uint64)FLAC__stream_encoder_get_blocksize(encoder), test_sample; + if(encoder_wrapper->stream_offset > 0 && encoder_wrapper->seek_table->data.seek_table.num_points > 0) { + /*@@@ WATCHOUT: assumes the encoder is fixed-blocksize, which will be true indefinitely: */ + const unsigned blocksize = FLAC__stream_encoder_get_blocksize(encoder); + const FLAC__uint64 frame_first_sample = (FLAC__uint64)current_frame * (FLAC__uint64)blocksize; + const FLAC__uint64 frame_last_sample = frame_first_sample + (FLAC__uint64)blocksize - 1; + FLAC__uint64 test_sample; unsigned i; - for(i = encoder_wrapper->first_seek_point_to_check; i < encoder_wrapper->seek_table.num_points; i++) { - test_sample = encoder_wrapper->seek_table.points[i].sample_number; - if(test_sample > current_sample) { + for(i = encoder_wrapper->first_seek_point_to_check; i < encoder_wrapper->seek_table->data.seek_table.num_points; i++) { + test_sample = encoder_wrapper->seek_table->data.seek_table.points[i].sample_number; + if(test_sample > frame_last_sample) { break; } - else if(test_sample == current_sample) { - encoder_wrapper->seek_table.points[i].stream_offset = encoder_wrapper->bytes_written - encoder_wrapper->stream_offset; - encoder_wrapper->seek_table.points[i].frame_samples = FLAC__stream_encoder_get_blocksize(encoder); + else if(test_sample >= frame_first_sample) { + encoder_wrapper->seek_table->data.seek_table.points[i].sample_number = frame_first_sample; + encoder_wrapper->seek_table->data.seek_table.points[i].stream_offset = encoder_wrapper->bytes_written - encoder_wrapper->stream_offset; + encoder_wrapper->seek_table->data.seek_table.points[i].frame_samples = blocksize; encoder_wrapper->first_seek_point_to_check++; - break; + /* DO NOT: "break;" and here's why: + * The seektable template may contain more than one target + * sample for any given frame; we will keep looping, generating + * duplicate seekpoints for them, and we'll clean it up later, + * just before writing the seektable back to the metadata. + */ } else { encoder_wrapper->first_seek_point_to_check++; @@ -1509,17 +1487,16 @@ FLAC__StreamEncoderWriteStatus write_callback(const FLAC__StreamEncoder *encoder if(encoder_wrapper->verify) { encoder_wrapper->verify_fifo.encoded_signal = buffer; encoder_wrapper->verify_fifo.encoded_bytes = bytes; - if(encoder_wrapper->verify_fifo.into_frames) { - if(!FLAC__stream_decoder_process_one_frame(encoder_wrapper->verify_fifo.decoder)) { - encoder_wrapper->verify_fifo.result = FLAC__VERIFY_FAILED_IN_FRAME; + if(encoder_wrapper->verify_fifo.encode_state > ENCODER_IN_MAGIC) { + if(!FLAC__stream_decoder_process_single(encoder_wrapper->verify_fifo.decoder)) { + encoder_wrapper->verify_fifo.result = encoder_wrapper->verify_fifo.encode_state > ENCODER_IN_METADATA? FLAC__VERIFY_FAILED_IN_FRAME : FLAC__VERIFY_FAILED_IN_METADATA; + return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR; } } else { - if(!FLAC__stream_decoder_process_metadata(encoder_wrapper->verify_fifo.decoder)) { - encoder_wrapper->verify_fifo.result = FLAC__VERIFY_FAILED_IN_METADATA; - return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR; - } + encoder_wrapper->verify_fifo.encode_state = ENCODER_IN_METADATA; + encoder_wrapper->verify_fifo.needs_magic_hack = true; } } @@ -1646,16 +1623,20 @@ framesize_: if(fwrite(&b, 1, 1, f) != 1) goto seektable_; seektable_: - if(encoder_wrapper->seek_table.num_points > 0) { + if(encoder_wrapper->seek_table->data.seek_table.num_points > 0) { long pos; unsigned i; + (void)FLAC__metadata_object_seektable_template_sort(encoder_wrapper->seek_table, /*compact=*/false); + + FLAC__ASSERT(FLAC__metadata_object_seektable_is_legal(encoder_wrapper->seek_table)); + /* convert any unused seek points to placeholders */ - for(i = 0; i < encoder_wrapper->seek_table.num_points; i++) { - if(encoder_wrapper->seek_table.points[i].sample_number == FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER) + for(i = 0; i < encoder_wrapper->seek_table->data.seek_table.num_points; i++) { + if(encoder_wrapper->seek_table->data.seek_table.points[i].sample_number == FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER) break; - else if(encoder_wrapper->seek_table.points[i].frame_samples == 0) - encoder_wrapper->seek_table.points[i].sample_number = FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER; + else if(encoder_wrapper->seek_table->data.seek_table.points[i].frame_samples == 0) + encoder_wrapper->seek_table->data.seek_table.points[i].sample_number = FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER; } /* the offset of the seek table data 'pos' should be after then stream sync and STREAMINFO block and SEEKTABLE header */ @@ -1663,10 +1644,10 @@ seektable_: pos += metadata->length; pos += (FLAC__STREAM_METADATA_IS_LAST_LEN + FLAC__STREAM_METADATA_TYPE_LEN + FLAC__STREAM_METADATA_LENGTH_LEN) / 8; fseek(f, pos, SEEK_SET); - for(i = 0; i < encoder_wrapper->seek_table.num_points; i++) { - if(!write_big_endian_uint64(f, encoder_wrapper->seek_table.points[i].sample_number)) goto end_; - if(!write_big_endian_uint64(f, encoder_wrapper->seek_table.points[i].stream_offset)) goto end_; - if(!write_big_endian_uint16(f, (FLAC__uint16)encoder_wrapper->seek_table.points[i].frame_samples)) goto end_; + for(i = 0; i < encoder_wrapper->seek_table->data.seek_table.num_points; i++) { + if(!write_big_endian_uint64(f, encoder_wrapper->seek_table->data.seek_table.points[i].sample_number)) goto end_; + if(!write_big_endian_uint64(f, encoder_wrapper->seek_table->data.seek_table.points[i].stream_offset)) goto end_; + if(!write_big_endian_uint16(f, (FLAC__uint16)encoder_wrapper->seek_table->data.seek_table.points[i].frame_samples)) goto end_; } } @@ -1681,14 +1662,22 @@ FLAC__StreamDecoderReadStatus verify_read_callback(const FLAC__StreamDecoder *de const unsigned encoded_bytes = encoder_wrapper->verify_fifo.encoded_bytes; (void)decoder; - if(encoded_bytes <= *bytes) { - *bytes = encoded_bytes; - memcpy(buffer, encoder_wrapper->verify_fifo.encoded_signal, *bytes); + if(encoder_wrapper->verify_fifo.needs_magic_hack) { + FLAC__ASSERT(*bytes >= FLAC__STREAM_SYNC_LENGTH); + *bytes = FLAC__STREAM_SYNC_LENGTH; + memcpy(buffer, FLAC__STREAM_SYNC_STRING, *bytes); + encoder_wrapper->verify_fifo.needs_magic_hack = false; } else { - memcpy(buffer, encoder_wrapper->verify_fifo.encoded_signal, *bytes); - encoder_wrapper->verify_fifo.encoded_signal += *bytes; - encoder_wrapper->verify_fifo.encoded_bytes -= *bytes; + if(encoded_bytes <= *bytes) { + *bytes = encoded_bytes; + memcpy(buffer, encoder_wrapper->verify_fifo.encoded_signal, *bytes); + } + else { + memcpy(buffer, encoder_wrapper->verify_fifo.encoded_signal, *bytes); + encoder_wrapper->verify_fifo.encoded_signal += *bytes; + encoder_wrapper->verify_fifo.encoded_bytes -= *bytes; + } } return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;