Skip to content

Commit 51f0806

Browse files
author
Benjamin Moody
committed
decoder: Avoid unnecessary locking in main decoder loop.
When decoding a large number of frames in a row, we don't need to check for Python errors after every call to FLAC__stream_decoder_process_single. (If an error does occur, the read callback should cause libFLAC to abort as soon as possible.) By moving all of the Python API calls out of the loop, we can avoid re-acquiring the GIL or critical-section lock on every iteration.
1 parent 87fe12e commit 51f0806

File tree

1 file changed

+18
-15
lines changed

1 file changed

+18
-15
lines changed

src/_plibflacmodule.c

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -941,7 +941,7 @@ static PyObject *
941941
Decoder_read(DecoderObject *self, PyObject *args)
942942
{
943943
Py_ssize_t limit;
944-
FLAC__bool ok;
944+
FLAC__bool ok = 1;
945945
FLAC__StreamDecoderState state;
946946
PyObject *memview, *arrays[FLAC__MAX_CHANNELS] = {0}, *result = NULL;
947947
Py_ssize_t out_count, new_size;
@@ -970,30 +970,33 @@ Decoder_read(DecoderObject *self, PyObject *args)
970970
self->buf_count -= out_count;
971971
}
972972

973-
while (self->out_remaining > 0 && self->buf_count == 0) {
974-
BEGIN_PROCESSING();
973+
BEGIN_PROCESSING();
975974

975+
while (self->out_remaining > 0 && self->buf_count == 0) {
976976
ok = FLAC__stream_decoder_process_single(self->decoder);
977977

978978
state = FLAC__stream_decoder_get_state(self->decoder);
979979
if (state == FLAC__STREAM_DECODER_ABORTED)
980980
FLAC__stream_decoder_flush(self->decoder);
981981

982-
END_PROCESSING();
983-
984-
if (PyErr_Occurred())
985-
goto fail;
986-
987982
if ((state == FLAC__STREAM_DECODER_END_OF_STREAM ||
988-
state == FLAC__STREAM_DECODER_ABORTED))
983+
state == FLAC__STREAM_DECODER_ABORTED ||
984+
!ok))
989985
break;
986+
}
990987

991-
if (!ok) {
992-
PyErr_Format(get_error_type(self->module),
993-
"process_single failed (state = %s)",
994-
FLAC__StreamDecoderStateString[state]);
995-
goto fail;
996-
}
988+
END_PROCESSING();
989+
990+
if (PyErr_Occurred())
991+
goto fail;
992+
993+
if ((state != FLAC__STREAM_DECODER_END_OF_STREAM &&
994+
state != FLAC__STREAM_DECODER_ABORTED &&
995+
!ok)) {
996+
PyErr_Format(get_error_type(self->module),
997+
"process_single failed (state = %s)",
998+
FLAC__StreamDecoderStateString[state]);
999+
goto fail;
9971000
}
9981001

9991002
if (self->out_count == 0) {

0 commit comments

Comments
 (0)