Skip to content

Commit

Permalink
don't just pass 0 for samples in Ogg/FLAC callback
Browse files Browse the repository at this point in the history
This is a fix for #661
  • Loading branch information
njlarsson authored and ktmf01 committed Aug 27, 2024
1 parent 8e6498d commit 1880f21
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 8 deletions.
15 changes: 10 additions & 5 deletions include/FLAC/stream_encoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -538,11 +538,16 @@ typedef FLAC__StreamEncoderReadStatus (*FLAC__StreamEncoderReadCallback)(const F
* callback is being called to write metadata.
*
* \note
* Unlike when writing to native FLAC, when writing to Ogg FLAC the
* write callback will be called twice when writing each audio
* frame; once for the page header, and once for the page body.
* When writing the page header, the \a samples argument to the
* write callback will be \c 0.
* Unlike when writing to native FLAC, when writing to Ogg FLAC the write
* callback will be called at least twice when writing each audio frame; once
* for the page header and once for the page body, possibly repeating this
* pair of calls several times in a batch with the same value of
* \a current_frame. When writing the page header, as well as in all but the
* first page body write of the batch, the \a samples argument to the write
* callback will be \c 0. The full number of samples of the batch will be
* passed in the first page body write. Furthermore, it is possible that a few
* of these samples are retained in an internal Ogg encoding buffer and not
* actually encoded until the next batch.
*
* \note In general, FLAC__StreamEncoder functions which change the
* state should not be called on the \a encoder while in the callback.
Expand Down
1 change: 1 addition & 0 deletions src/libFLAC/include/private/ogg_encoder_aspect.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ typedef struct FLAC__OggEncoderAspect {
FLAC__bool seen_magic; /* true if we've seen the fLaC magic in the write callback yet */
FLAC__bool is_first_packet;
FLAC__uint64 samples_written;
uint32_t samples_in_submit_buffer;
} FLAC__OggEncoderAspect;

void FLAC__ogg_encoder_aspect_set_serial_number(FLAC__OggEncoderAspect *aspect, long value);
Expand Down
13 changes: 10 additions & 3 deletions src/libFLAC/ogg_encoder_aspect.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ FLAC__bool FLAC__ogg_encoder_aspect_init(FLAC__OggEncoderAspect *aspect)
aspect->seen_magic = false;
aspect->is_first_packet = true;
aspect->samples_written = 0;
aspect->samples_in_submit_buffer = 0;

return true;
}
Expand Down Expand Up @@ -192,21 +193,27 @@ FLAC__StreamEncoderWriteStatus FLAC__ogg_encoder_aspect_write_callback_wrapper(F
if(ogg_stream_packetin(&aspect->stream_state, &packet) != 0)
return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;

/*@@@ can't figure out a way to pass a useful number for 'samples' to the write_callback, so we'll just pass 0 */
/* For a batch of write_callback calls associated with the same current_frame, pass the number of samples in the
* first non-metadata page body call, and then set to zero in case there are more iterations of the while loop (so
* as not to give the impression of more samples being processed).
*/
aspect->samples_in_submit_buffer += samples;
if(is_metadata) {
while(ogg_stream_flush(&aspect->stream_state, &aspect->page) != 0) {
if(write_callback(encoder, aspect->page.header, aspect->page.header_len, 0, current_frame, client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK)
return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
if(write_callback(encoder, aspect->page.body, aspect->page.body_len, 0, current_frame, client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK)
if(write_callback(encoder, aspect->page.body, aspect->page.body_len, aspect->samples_in_submit_buffer, current_frame, client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK)
return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
aspect->samples_in_submit_buffer = 0;
}
}
else {
while(ogg_stream_pageout(&aspect->stream_state, &aspect->page) != 0) {
if(write_callback(encoder, aspect->page.header, aspect->page.header_len, 0, current_frame, client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK)
return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
if(write_callback(encoder, aspect->page.body, aspect->page.body_len, 0, current_frame, client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK)
if(write_callback(encoder, aspect->page.body, aspect->page.body_len, aspect->samples_in_submit_buffer, current_frame, client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK)
return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
aspect->samples_in_submit_buffer = 0;
}
}
}
Expand Down

0 comments on commit 1880f21

Please sign in to comment.