mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-10-09 21:14:02 +00:00
[mod_silk] Bound decode loop to the codec's frame limit (#3116)
`switch_silk_decode()` ran its `do`/`while` decode loop while the SDK kept reporting more internal frames, advancing the output pointer each pass with no cap. The destination is a fixed-size PCM buffer, so a stream reporting more internal frames than a conformant packet can carry let the accumulated write run past its end. Stop after `MAX_INPUT_FRAMES` internal frames, the most a conformant SILK packet can hold, so the accumulated PCM stays within the destination regardless of the bitstream. Declare the per-pass sample count inside the loop so it resets to zero each iteration, and advance the output pointer and length only when it is positive. A pass that writes no samples, including a tolerated FEC payload error that leaves the count untouched, then contributes nothing instead of advancing on a stale count from an earlier pass or on a negative value.
This commit is contained in:
1 parent
2c8802e64b
commit
bc1e992dab
1 file changed
+16
-5
@@ -328,13 +328,13 @@ static switch_status_t switch_silk_decode(switch_codec_t *codec,
|
||||
uint32_t encoded_rate, void *decoded_data, uint32_t *decoded_data_len, uint32_t *decoded_rate, unsigned int *flag)
|
||||
{
|
||||
struct silk_context *context = codec->private_info;
|
||||
SKP_int16 ret, len;
|
||||
int16_t *target = decoded_data;
|
||||
switch_core_session_t *session = codec->session;
|
||||
switch_jb_t *jb = NULL;
|
||||
SKP_int lost_flag = (*flag & SFF_PLC);
|
||||
switch_bool_t did_lbrr = SWITCH_FALSE;
|
||||
int i;
|
||||
int decoded_frames = 0;
|
||||
|
||||
*decoded_data_len = 0;
|
||||
|
||||
@@ -368,6 +368,8 @@ static switch_status_t switch_silk_decode(switch_codec_t *codec,
|
||||
}
|
||||
|
||||
do {
|
||||
SKP_int16 ret, len = 0;
|
||||
|
||||
ret = (SKP_int16)SKP_Silk_SDK_Decode(context->dec_state,
|
||||
&context->decoder_object,
|
||||
lost_flag,
|
||||
@@ -379,12 +381,21 @@ static switch_status_t switch_silk_decode(switch_codec_t *codec,
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SKP_Silk_Decode returned %d!\n", ret);
|
||||
printSilkError(ret);
|
||||
/* if FEC was activated, we can ignore bit errors*/
|
||||
if (! (ret == SKP_SILK_DEC_PAYLOAD_ERROR && did_lbrr))
|
||||
return SWITCH_STATUS_FALSE;
|
||||
if (! (ret == SKP_SILK_DEC_PAYLOAD_ERROR && did_lbrr)) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
target += len;
|
||||
*decoded_data_len += (len * 2);
|
||||
if (len > 0) {
|
||||
target += len;
|
||||
*decoded_data_len += (len * 2);
|
||||
}
|
||||
|
||||
/* A conformant SILK packet decodes to at most MAX_INPUT_FRAMES internal frames; stop there so
|
||||
the accumulated PCM cannot run past the destination buffer regardless of the bitstream. */
|
||||
if (++decoded_frames >= MAX_INPUT_FRAMES) {
|
||||
break;
|
||||
}
|
||||
} while (context->decoder_object.moreInternalDecoderFrames);
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
|
||||
Reference in new issue
Block a user