diff --git a/.github/workflows/action.yml b/.github/workflows/action.yml index 30e0e6b268..b9e09c1cb1 100644 --- a/.github/workflows/action.yml +++ b/.github/workflows/action.yml @@ -69,13 +69,13 @@ jobs: if: startsWith(matrix.os,'macos') && !startsWith(matrix.build-system,'cmake') run: | brew update - brew install automake pkg-config libogg libtool + brew install automake pkg-config libogg libtool vorbis-tools oggz - name: Install Linux dependencies if: startsWith(matrix.os,'ubuntu') run: | sudo apt-get update - sudo apt-get install -y libtool-bin libogg-dev + sudo apt-get install -y libtool-bin libogg-dev vorbis-tools oggz-tools - name: Install Windows dependencies if: startsWith(matrix.os,'windows') diff --git a/.github/workflows/distcheck.yml b/.github/workflows/distcheck.yml index db1eac9da6..9ed3375d1d 100644 --- a/.github/workflows/distcheck.yml +++ b/.github/workflows/distcheck.yml @@ -21,7 +21,7 @@ jobs: - name: Install Linux dependencies run: | sudo apt-get update - sudo apt-get install -y libtool-bin libogg-dev doxygen libxml2-utils w3c-sgml-lib pandoc abi-compliance-checker + sudo apt-get install -y libtool-bin libogg-dev doxygen libxml2-utils w3c-sgml-lib pandoc abi-compliance-checker vorbis-tools oggz-tools - name: Build with Autotools run: | diff --git a/src/libFLAC/include/private/ogg_decoder_aspect.h b/src/libFLAC/include/private/ogg_decoder_aspect.h index e225595ec6..d5979d8e76 100644 --- a/src/libFLAC/include/private/ogg_decoder_aspect.h +++ b/src/libFLAC/include/private/ogg_decoder_aspect.h @@ -41,7 +41,8 @@ typedef struct FLAC__OggDecoderAspect_LinkDetails { long serial_number; - FLAC__off_t size; + FLAC__off_t start_byte; + FLAC__off_t end_byte; uint64_t samples; } FLAC__OggDecoderAspect_LinkDetails; @@ -105,6 +106,6 @@ typedef enum { typedef FLAC__OggDecoderAspectReadStatus (*FLAC__OggDecoderAspectReadCallbackProxy)(const void *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data); -FLAC__OggDecoderAspectReadStatus FLAC__ogg_decoder_aspect_read_callback_wrapper(FLAC__OggDecoderAspect *aspect, FLAC__byte buffer[], size_t *bytes, FLAC__OggDecoderAspectReadCallbackProxy read_callback, const FLAC__StreamDecoder *decoder, void *client_data); +FLAC__OggDecoderAspectReadStatus FLAC__ogg_decoder_aspect_read_callback_wrapper(FLAC__OggDecoderAspect *aspect, FLAC__byte buffer[], size_t *bytes, FLAC__OggDecoderAspectReadCallbackProxy read_callback, FLAC__StreamDecoderTellCallback tell_callback, const FLAC__StreamDecoder *decoder, void *client_data); #endif diff --git a/src/libFLAC/ogg_decoder_aspect.c b/src/libFLAC/ogg_decoder_aspect.c index 8d423c66eb..45f3ec621e 100644 --- a/src/libFLAC/ogg_decoder_aspect.c +++ b/src/libFLAC/ogg_decoder_aspect.c @@ -137,20 +137,18 @@ FLAC__OggDecoderAspect_TargetLink * FLAC__ogg_decoder_aspect_get_target_link(FLA uint32_t current_link = 0; uint32_t total_samples = 0; - uint32_t position = 0; while(current_link < aspect->number_of_links_indexed) { total_samples += aspect->linkdetails[current_link].samples; if(target_sample < total_samples) { aspect->target_link.serial_number = aspect->linkdetails[current_link].serial_number; - aspect->target_link.start_byte = position; + aspect->target_link.start_byte = aspect->linkdetails[current_link].start_byte; aspect->target_link.samples_in_preceding_links = total_samples - aspect->linkdetails[current_link].samples; - aspect->target_link.end_byte = position + aspect->linkdetails[current_link].size; + aspect->target_link.end_byte = aspect->linkdetails[current_link].end_byte; aspect->target_link.samples_this_link = aspect->linkdetails[current_link].samples; aspect->target_link.linknumber = current_link; return &aspect->target_link; } - position += aspect->linkdetails[current_link].size; current_link++; } return NULL; @@ -171,7 +169,7 @@ void FLAC__ogg_decoder_aspect_set_seek_parameters(FLAC__OggDecoderAspect *aspect } -FLAC__OggDecoderAspectReadStatus FLAC__ogg_decoder_aspect_read_callback_wrapper(FLAC__OggDecoderAspect *aspect, FLAC__byte buffer[], size_t *bytes, FLAC__OggDecoderAspectReadCallbackProxy read_callback, const FLAC__StreamDecoder *decoder, void *client_data) +FLAC__OggDecoderAspectReadStatus FLAC__ogg_decoder_aspect_read_callback_wrapper(FLAC__OggDecoderAspect *aspect, FLAC__byte buffer[], size_t *bytes, FLAC__OggDecoderAspectReadCallbackProxy read_callback, FLAC__StreamDecoderTellCallback tell_callback, const FLAC__StreamDecoder *decoder, void *client_data) { static const size_t OGG_BYTES_CHUNK = 8192; const size_t bytes_requested = *bytes; @@ -234,8 +232,13 @@ FLAC__OggDecoderAspectReadStatus FLAC__ogg_decoder_aspect_read_callback_wrapper( else { aspect->end_of_link = true; if(aspect->current_linknumber >= aspect->number_of_links_indexed) { + FLAC__uint64 tell_offset; aspect->linkdetails[aspect->current_linknumber].samples = aspect->working_packet.granulepos; aspect->linkdetails[aspect->current_linknumber].serial_number = aspect->serial_number; + if(tell_callback != 0) { + if(tell_callback(decoder, &tell_offset, client_data) == FLAC__STREAM_DECODER_TELL_STATUS_OK) + aspect->linkdetails[aspect->current_linknumber].end_byte = tell_offset - aspect->sync_state.fill + aspect->sync_state.returned; + } aspect->number_of_links_indexed++; } if(!aspect->is_seeking) @@ -305,6 +308,7 @@ FLAC__OggDecoderAspectReadStatus FLAC__ogg_decoder_aspect_read_callback_wrapper( * of the whole links is done, while this code does advance processing */ if(aspect->current_linknumber >= aspect->number_of_links_detected) { FLAC__OggDecoderAspect_LinkDetails * tmpptr = NULL; + FLAC__uint64 tell_offset; aspect->number_of_links_detected = aspect->current_linknumber + 1; /* reallocate in chunks of 4 */ @@ -315,15 +319,17 @@ FLAC__OggDecoderAspectReadStatus FLAC__ogg_decoder_aspect_read_callback_wrapper( aspect->linkdetails = tmpptr; } memset(&aspect->linkdetails[aspect->current_linknumber], 0, sizeof(FLAC__OggDecoderAspect_LinkDetails)); + if(tell_callback != 0) { + if(tell_callback(decoder, &tell_offset, client_data) == FLAC__STREAM_DECODER_TELL_STATUS_OK) + aspect->linkdetails[aspect->current_linknumber].start_byte = tell_offset - aspect->sync_state.fill + aspect->sync_state.returned + - aspect->working_page.header_len - aspect->working_page.body_len; + } } } } if(ogg_stream_pagein(&aspect->stream_state, &aspect->working_page) == 0) { aspect->have_working_page = true; aspect->have_working_packet = false; - if(aspect->current_linknumber >= aspect->number_of_links_indexed) { - aspect->linkdetails[aspect->current_linknumber].size += aspect->working_page.header_len + aspect->working_page.body_len; - } } /* else do nothing, could be a page from another stream */ } diff --git a/src/libFLAC/stream_decoder.c b/src/libFLAC/stream_decoder.c index 4754cc2005..1b868d0c56 100644 --- a/src/libFLAC/stream_decoder.c +++ b/src/libFLAC/stream_decoder.c @@ -3286,7 +3286,7 @@ void undo_channel_coding(FLAC__StreamDecoder *decoder) { #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)) { + switch(FLAC__ogg_decoder_aspect_read_callback_wrapper(&decoder->protected_->ogg_decoder_aspect, buffer, bytes, read_callback_proxy_, decoder->private_->tell_callback, 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 diff --git a/test/test_seeking.sh b/test/test_seeking.sh index 07ec302b50..10c12532be 100755 --- a/test/test_seeking.sh +++ b/test/test_seeking.sh @@ -150,6 +150,24 @@ if [ $has_ogg = "yes" ] ; then die "ERROR: during test_seeking" fi + if command -v oggz > /dev/null ; then + if command -v oggenc > /dev/null ; then + oggenc -Q --skeleton -o small-vorbis.oga small.flac + oggenc -Q --skeleton -o small2-vorbis.oga small.flac + oggz merge -o small-merged.oga small-vorbis.oga small.oga + oggz merge -o small2-merged.oga small2-vorbis.oga small2.oga + cat small2-merged.oga small-merged.oga > chained-merged.oga + cat noise-secondhalf.raw noise.raw > chained.raw + + echo "testing chained-merged.oga:" + echo run_test_seeking chained-merged.oga $small_seek_count $chained_samples chained.raw + if run_test_seeking chained-merged.oga $small_seek_count $chained_samples chained.raw ; then : ; else + die "ERROR: during test_seeking" + fi + + fi + fi + fi rm -f tiny.flac tiny.oga small.flac small.oga tiny-s.flac small-s.flac