diff options
Diffstat (limited to 'src/modules/bluetooth/a2dp-codec-sbc.c')
-rw-r--r-- | src/modules/bluetooth/a2dp-codec-sbc.c | 30 |
1 files changed, 22 insertions, 8 deletions
diff --git a/src/modules/bluetooth/a2dp-codec-sbc.c b/src/modules/bluetooth/a2dp-codec-sbc.c index e4c1dff01..e2db91b63 100644 --- a/src/modules/bluetooth/a2dp-codec-sbc.c +++ b/src/modules/bluetooth/a2dp-codec-sbc.c @@ -426,7 +426,11 @@ static void *init(bool for_encoding, bool for_backchannel, const uint8_t *config sbc_info->min_bitpool = config->min_bitpool; sbc_info->max_bitpool = config->max_bitpool; - /* Set minimum bitpool for source to get the maximum possible block_size */ + /* Set minimum bitpool for source to get the maximum possible block_size + * in get_block_size() function. This block_size is length of buffer used + * for decoded audio data and so is inversely proportional to frame length + * which depends on bitpool value. Bitpool is controlled by other side from + * range [min_bitpool, max_bitpool]. */ sbc_info->initial_bitpool = for_encoding ? sbc_info->max_bitpool : sbc_info->min_bitpool; set_params(sbc_info); @@ -480,9 +484,10 @@ static void reset(void *codec_info) { static size_t get_block_size(void *codec_info, size_t link_mtu) { struct sbc_info *sbc_info = (struct sbc_info *) codec_info; + size_t rtp_size = sizeof(struct rtp_header) + sizeof(struct rtp_payload); + size_t frame_count = (link_mtu - rtp_size) / sbc_info->frame_length; - return (link_mtu - sizeof(struct rtp_header) - sizeof(struct rtp_payload)) - / sbc_info->frame_length * sbc_info->codesize; + return frame_count * sbc_info->codesize; } static size_t reduce_encoder_bitrate(void *codec_info, size_t write_link_mtu) { @@ -536,8 +541,12 @@ static size_t encode_buffer(void *codec_info, uint32_t timestamp, const uint8_t if (PA_UNLIKELY(encoded <= 0)) { pa_log_error("SBC encoding error (%li)", (long) encoded); - *processed = p - input_buffer; - return 0; + break; + } + + if (PA_UNLIKELY(written < 0)) { + pa_log_error("SBC encoding error (%li)", (long) written); + break; } pa_assert_fp((size_t) encoded <= to_encode); @@ -559,6 +568,11 @@ static size_t encode_buffer(void *codec_info, uint32_t timestamp, const uint8_t pa_log_debug("Using SBC codec implementation: %s", pa_strnull(sbc_get_implementation_info(&sbc_info->sbc))); } PA_ONCE_END; + if (PA_UNLIKELY(frame_count == 0)) { + *processed = 0; + return 0; + } + /* write it to the fifo */ memset(output_buffer, 0, sizeof(*header) + sizeof(*payload)); header->v = 2; @@ -595,7 +609,7 @@ static size_t decode_buffer(void *codec_info, const uint8_t *input_buffer, size_ d = output_buffer; to_write = output_size; - while (PA_LIKELY(to_decode > 0)) { + while (PA_LIKELY(to_decode > 0 && to_write > 0)) { size_t written; ssize_t decoded; @@ -606,8 +620,7 @@ static size_t decode_buffer(void *codec_info, const uint8_t *input_buffer, size_ if (PA_UNLIKELY(decoded <= 0)) { pa_log_error("SBC decoding error (%li)", (long) decoded); - *processed = p - input_buffer; - return 0; + break; } /* Reset frame length, it can be changed due to bitpool change */ @@ -616,6 +629,7 @@ static size_t decode_buffer(void *codec_info, const uint8_t *input_buffer, size_ pa_assert_fp((size_t) decoded <= to_decode); pa_assert_fp((size_t) decoded == sbc_info->frame_length); + pa_assert_fp((size_t) written <= to_write); pa_assert_fp((size_t) written == sbc_info->codesize); p += decoded; |