Skip to content

Commit

Permalink
Add support for seeking in multiplexed chained streams
Browse files Browse the repository at this point in the history
  • Loading branch information
ktmf01 committed Sep 11, 2024
1 parent 8116121 commit 87283b7
Show file tree
Hide file tree
Showing 6 changed files with 39 additions and 14 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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')
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/distcheck.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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: |
Expand Down
5 changes: 3 additions & 2 deletions src/libFLAC/include/private/ogg_decoder_aspect.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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
22 changes: 14 additions & 8 deletions src/libFLAC/ogg_decoder_aspect.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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 */
Expand All @@ -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 */
}
Expand Down
2 changes: 1 addition & 1 deletion src/libFLAC/stream_decoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
18 changes: 18 additions & 0 deletions test/test_seeking.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 87283b7

Please sign in to comment.