Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decode chained ogg streams, attempt #3 #735

Merged
merged 18 commits into from
Sep 27, 2024
Merged
Changes from 1 commit
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Add capability to decode chained stream to libFLAC
philippe44 authored and ktmf01 committed Sep 26, 2024
commit 09aa150faab39e14e714d61c16ec66cbc564d69a
7 changes: 6 additions & 1 deletion src/libFLAC/include/private/ogg_decoder_aspect.h
Original file line number Diff line number Diff line change
@@ -49,6 +49,8 @@ typedef struct FLAC__OggDecoderAspect {
uint32_t version_major, version_minor;
FLAC__bool need_serial_number;
FLAC__bool end_of_stream;
FLAC__bool page_eos;
FLAC__bool decode_chained_stream;
FLAC__bool have_working_page; /* only if true will the following vars be valid */
ogg_page working_page;
FLAC__bool have_working_packet; /* only if true will the following vars be valid */
@@ -60,7 +62,10 @@ void FLAC__ogg_decoder_aspect_set_defaults(FLAC__OggDecoderAspect *aspect);
FLAC__bool FLAC__ogg_decoder_aspect_init(FLAC__OggDecoderAspect *aspect);
void FLAC__ogg_decoder_aspect_finish(FLAC__OggDecoderAspect *aspect);
void FLAC__ogg_decoder_aspect_flush(FLAC__OggDecoderAspect *aspect);
void FLAC__ogg_decoder_aspect_reset(FLAC__OggDecoderAspect *aspect);
void FLAC__ogg_decoder_aspect_reset(FLAC__OggDecoderAspect* aspect);
FLAC__bool FLAC__ogg_decoder_aspect_page_eos(FLAC__OggDecoderAspect* aspect, bool reset);
void FLAC__ogg_decoder_aspect_set_decode_chained_stream(FLAC__OggDecoderAspect* aspect, FLAC__bool value);
FLAC__bool FLAC__ogg_decoder_aspect_get_decode_chained_stream(FLAC__OggDecoderAspect* aspect);

typedef enum {
FLAC__OGG_DECODER_ASPECT_READ_STATUS_OK = 0,
32 changes: 31 additions & 1 deletion src/libFLAC/ogg_decoder_aspect.c
Original file line number Diff line number Diff line change
@@ -63,6 +63,7 @@ FLAC__bool FLAC__ogg_decoder_aspect_init(FLAC__OggDecoderAspect *aspect)

aspect->end_of_stream = false;
aspect->have_working_page = false;
aspect->page_eos = false;

return true;
}
@@ -82,6 +83,7 @@ void FLAC__ogg_decoder_aspect_set_serial_number(FLAC__OggDecoderAspect *aspect,
void FLAC__ogg_decoder_aspect_set_defaults(FLAC__OggDecoderAspect *aspect)
{
aspect->use_first_serial_number = true;
aspect->decode_chained_stream = false;
}

void FLAC__ogg_decoder_aspect_flush(FLAC__OggDecoderAspect *aspect)
@@ -90,6 +92,7 @@ void FLAC__ogg_decoder_aspect_flush(FLAC__OggDecoderAspect *aspect)
(void)ogg_sync_reset(&aspect->sync_state);
aspect->end_of_stream = false;
aspect->have_working_page = false;
aspect->page_eos = false;
}

void FLAC__ogg_decoder_aspect_reset(FLAC__OggDecoderAspect *aspect)
@@ -100,6 +103,23 @@ void FLAC__ogg_decoder_aspect_reset(FLAC__OggDecoderAspect *aspect)
aspect->need_serial_number = true;
}

FLAC__bool FLAC__ogg_decoder_aspect_page_eos(FLAC__OggDecoderAspect* aspect, bool reset)
{
bool page_eos = aspect->page_eos;
if (reset) aspect->page_eos = false;
return page_eos;
}

void FLAC__ogg_decoder_aspect_set_decode_chained_stream(FLAC__OggDecoderAspect* aspect, FLAC__bool value)
{
aspect->decode_chained_stream = value;
}

FLAC__bool FLAC__ogg_decoder_aspect_get_decode_chained_stream(FLAC__OggDecoderAspect* aspect)
{
return aspect->decode_chained_stream;
}

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)
{
static const size_t OGG_BYTES_CHUNK = 8192;
@@ -191,19 +211,29 @@ FLAC__OggDecoderAspectReadStatus FLAC__ogg_decoder_aspect_read_callback_wrapper(
}
}
}
else if (aspect->page_eos) {
/* we've now consumed all packets of the last page */
aspect->need_serial_number = true;
return *bytes ? FLAC__OGG_DECODER_ASPECT_READ_STATUS_OK :
FLAC__OGG_DECODER_ASPECT_READ_STATUS_END_OF_STREAM;
}
else {
/* try and get another page */
const int ret = ogg_sync_pageout(&aspect->sync_state, &aspect->working_page);
if (ret > 0) {
/* got a page, grab the serial number if necessary */
if(aspect->need_serial_number) {
aspect->stream_state.serialno = aspect->serial_number = ogg_page_serialno(&aspect->working_page);
aspect->serial_number = ogg_page_serialno(&aspect->working_page);
ogg_stream_reset_serialno(&aspect->stream_state, aspect->serial_number);
aspect->need_serial_number = false;
}
if(ogg_stream_pagein(&aspect->stream_state, &aspect->working_page) == 0) {
aspect->have_working_page = true;
aspect->have_working_packet = false;
}
if(aspect->decode_chained_stream && ogg_page_eos(&aspect->working_page) != 0) {
aspect->page_eos = true;
}
/* else do nothing, could be a page from another stream */
}
else if (ret == 0) {
50 changes: 44 additions & 6 deletions src/libFLAC/stream_decoder.c
Original file line number Diff line number Diff line change
@@ -112,6 +112,9 @@ static FLAC__StreamDecoderSeekStatus file_seek_callback_(const FLAC__StreamDecod
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);
#if FLAC__HAS_OGG
static void reset_decoder(FLAC__StreamDecoder* decoder);
#endif

/***********************************************************************
*
@@ -1009,8 +1012,16 @@ FLAC_API FLAC__bool FLAC__stream_decoder_process_single(FLAC__StreamDecoder *dec
else
return true;
case FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC:
if(!frame_sync_(decoder))
return true; /* above function sets the status for us */
if(!frame_sync_(decoder)) {
#if FLAC__HAS_OGG
if (decoder->private_->is_ogg &&
decoder->protected_->state == FLAC__STREAM_DECODER_END_OF_STREAM &&
FLAC__ogg_decoder_aspect_page_eos(&decoder->protected_->ogg_decoder_aspect, true))
reset_decoder(decoder);
else
#endif
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))
@@ -1070,8 +1081,16 @@ FLAC_API FLAC__bool FLAC__stream_decoder_process_until_end_of_stream(FLAC__Strea
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 */
if(!frame_sync_(decoder)) {
#if FLAC__HAS_OGG
if (decoder->private_->is_ogg &&
decoder->protected_->state == FLAC__STREAM_DECODER_END_OF_STREAM &&
FLAC__ogg_decoder_aspect_page_eos(&decoder->protected_->ogg_decoder_aspect, true))
reset_decoder(decoder);
else
#endif
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))
@@ -1098,8 +1117,16 @@ FLAC_API FLAC__bool FLAC__stream_decoder_skip_single_frame(FLAC__StreamDecoder *
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 */
if(!frame_sync_(decoder)) {
#if FLAC__HAS_OGG
if (decoder->private_->is_ogg &&
decoder->protected_->state == FLAC__STREAM_DECODER_END_OF_STREAM &&
FLAC__ogg_decoder_aspect_page_eos(&decoder->protected_->ogg_decoder_aspect, true))
reset_decoder(decoder);
else
#endif
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))
@@ -3740,3 +3767,14 @@ FLAC__bool file_eof_callback_(const FLAC__StreamDecoder *decoder, void *client_d

return feof(decoder->private_->file)? true : false;
}

#if FLAC__HAS_OGG
void reset_decoder(FLAC__StreamDecoder* decoder) {
decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_METADATA;
decoder->private_->has_stream_info = false;
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;
}
#endif