Fixes crashes like: daemon.err asterisk[5087]: Assertion failed: enc->streams == NULL (src/opusenc.c: ope_encoder_drain: 839) Signed-off-by: Andre Heider <a.heider@gmail.com>lilik-openwrt-22.03
@ -0,0 +1,27 @@ | |||||
From 205552370e058d99452fd34983942e10f2db6dff Mon Sep 17 00:00:00 2001 | |||||
From: Mark Harris <mark.hsj@gmail.com> | |||||
Date: Mon, 28 Dec 2020 12:58:17 -0800 | |||||
Subject: [PATCH] Fix ope_encoder_drain() assertion failure | |||||
If the stream is drained without writing any audio and the frame size is | |||||
smaller than the encoder latency, the assertion (enc->streams == NULL) | |||||
would fail because pad_samples was computed using an incorrect value of | |||||
enc->global_granule_offset before it was set in init_stream(), causing | |||||
the padding to be insufficient to drain the stream. | |||||
--- | |||||
src/opusenc.c | 2 +- | |||||
1 file changed, 1 insertion(+), 1 deletion(-) | |||||
--- a/src/opusenc.c | |||||
+++ b/src/opusenc.c | |||||
@@ -808,9 +808,9 @@ int ope_encoder_drain(OggOpusEnc *enc) { | |||||
if (enc->unrecoverable) return enc->unrecoverable; | |||||
/* Check if it's already been drained. */ | |||||
if (enc->streams == NULL) return OPE_TOO_LATE; | |||||
+ if (!enc->streams->stream_is_init) init_stream(enc); | |||||
if (enc->re) resampler_drain = speex_resampler_get_output_latency(enc->re); | |||||
pad_samples = MAX(LPC_PADDING, enc->global_granule_offset + enc->frame_size + resampler_drain + 1); | |||||
- if (!enc->streams->stream_is_init) init_stream(enc); | |||||
shift_buffer(enc); | |||||
assert(enc->buffer_end + pad_samples <= BUFFER_SAMPLES); | |||||
memset(&enc->buffer[enc->channels*enc->buffer_end], 0, pad_samples*enc->channels*sizeof(enc->buffer[0])); |
@ -0,0 +1,78 @@ | |||||
From 6d46f2d7f7617852bab7cbb2f7cae8350b99204e Mon Sep 17 00:00:00 2001 | |||||
From: Mark Harris <mark.hsj@gmail.com> | |||||
Date: Mon, 28 Dec 2020 17:01:39 -0800 | |||||
Subject: [PATCH] Fix use of uninitialized fields | |||||
enc->streams->end_granule used uninitialized in encode_buffer() if the | |||||
stream contains no audio (opusenc_example /dev/null out.opus). | |||||
enc->frame_size_request used uninitialized in encode_buffer() if the | |||||
frame size was not explicitly set. | |||||
enc->callbacks used uninitialized if the encoder is created with | |||||
ope_encoder_create_callbacks() and callbacks is NULL. | |||||
--- | |||||
src/opusenc.c | 23 +++++++++++++++++------ | |||||
1 file changed, 17 insertions(+), 6 deletions(-) | |||||
--- a/src/opusenc.c | |||||
+++ b/src/opusenc.c | |||||
@@ -361,8 +361,7 @@ static void stream_destroy(EncStream *st | |||||
free(stream); | |||||
} | |||||
-/* Create a new OggOpus file (callback-based). */ | |||||
-OggOpusEnc *ope_encoder_create_callbacks(const OpusEncCallbacks *callbacks, void *user_data, | |||||
+static OggOpusEnc *ope_encoder_create_callbacks_impl(const OpusEncCallbacks *callbacks, void *user_data, | |||||
OggOpusComments *comments, opus_int32 rate, int channels, int family, int *error) { | |||||
OggOpusEnc *enc=NULL; | |||||
int ret; | |||||
@@ -395,11 +394,11 @@ OggOpusEnc *ope_encoder_create_callbacks | |||||
enc->oggp = NULL; | |||||
/* Not initializing anything is an unrecoverable error. */ | |||||
enc->unrecoverable = family == -1 ? OPE_TOO_LATE : 0; | |||||
- enc->pull_api = 0; | |||||
enc->packet_callback = NULL; | |||||
enc->rate = rate; | |||||
enc->channels = channels; | |||||
enc->frame_size = 960; | |||||
+ enc->frame_size_request = OPUS_FRAMESIZE_20_MS; | |||||
enc->decision_delay = 96000; | |||||
enc->max_ogg_delay = 48000; | |||||
enc->chaining_keyframe = NULL; | |||||
@@ -447,8 +446,12 @@ OggOpusEnc *ope_encoder_create_callbacks | |||||
if (callbacks != NULL) | |||||
{ | |||||
enc->callbacks = *callbacks; | |||||
+ enc->pull_api = 0; | |||||
+ } else { | |||||
+ enc->pull_api = 1; | |||||
} | |||||
enc->streams->user_data = user_data; | |||||
+ enc->streams->end_granule = 0; | |||||
if (error) *error = OPE_OK; | |||||
return enc; | |||||
fail: | |||||
@@ -462,11 +465,19 @@ fail: | |||||
return NULL; | |||||
} | |||||
+/* Create a new OggOpus stream (callback-based). */ | |||||
+OggOpusEnc *ope_encoder_create_callbacks(const OpusEncCallbacks *callbacks, void *user_data, | |||||
+ OggOpusComments *comments, opus_int32 rate, int channels, int family, int *error) { | |||||
+ if (callbacks == NULL) { | |||||
+ if (error) *error = OPE_BAD_ARG; | |||||
+ return NULL; | |||||
+ } | |||||
+ return ope_encoder_create_callbacks_impl(callbacks, user_data, comments, rate, channels, family, error); | |||||
+} | |||||
+ | |||||
/* Create a new OggOpus stream, pulling one page at a time. */ | |||||
OggOpusEnc *ope_encoder_create_pull(OggOpusComments *comments, opus_int32 rate, int channels, int family, int *error) { | |||||
- OggOpusEnc *enc = ope_encoder_create_callbacks(NULL, NULL, comments, rate, channels, family, error); | |||||
- if (enc) enc->pull_api = 1; | |||||
- return enc; | |||||
+ return ope_encoder_create_callbacks_impl(NULL, NULL, comments, rate, channels, family, error); | |||||
} | |||||
int ope_encoder_deferred_init_with_mapping(OggOpusEnc *enc, int family, int streams, |
@ -0,0 +1,47 @@ | |||||
From 427d61131a1af5eed48d5428e723ab4602b56cc1 Mon Sep 17 00:00:00 2001 | |||||
From: Mark Harris <mark.hsj@gmail.com> | |||||
Date: Tue, 29 Dec 2020 01:43:37 -0800 | |||||
Subject: [PATCH] Fix use of uninitialized serialno | |||||
Also do not crash if OPE_GET_SERIALNO_REQUEST is used after draining. | |||||
--- | |||||
src/opusenc.c | 14 +++++++++++--- | |||||
1 file changed, 11 insertions(+), 3 deletions(-) | |||||
--- a/src/opusenc.c | |||||
+++ b/src/opusenc.c | |||||
@@ -356,6 +356,11 @@ fail: | |||||
return NULL; | |||||
} | |||||
+static void stream_generate_serialno(EncStream *stream) { | |||||
+ stream->serialno = rand(); | |||||
+ stream->serialno_is_set = 1; | |||||
+} | |||||
+ | |||||
static void stream_destroy(EncStream *stream) { | |||||
if (stream->comment) free(stream->comment); | |||||
free(stream); | |||||
@@ -512,9 +517,7 @@ int ope_encoder_deferred_init_with_mappi | |||||
static void init_stream(OggOpusEnc *enc) { | |||||
assert(!enc->streams->stream_is_init); | |||||
- if (!enc->streams->serialno_is_set) { | |||||
- enc->streams->serialno = rand(); | |||||
- } | |||||
+ if (!enc->streams->serialno_is_set) stream_generate_serialno(enc->streams); | |||||
if (enc->oggp != NULL) oggp_chain(enc->oggp, enc->streams->serialno); | |||||
else { | |||||
@@ -1071,6 +1074,11 @@ int ope_encoder_ctl(OggOpusEnc *enc, int | |||||
case OPE_GET_SERIALNO_REQUEST: | |||||
{ | |||||
opus_int32 *value = va_arg(ap, opus_int32*); | |||||
+ if (!enc->last_stream) { | |||||
+ ret = OPE_TOO_LATE; | |||||
+ break; | |||||
+ } | |||||
+ if (!enc->last_stream->serialno_is_set) stream_generate_serialno(enc->last_stream); | |||||
*value = enc->last_stream->serialno; | |||||
} | |||||
break; |