From 3303defd3fa01b2698a6aa766b43deb01aee3efa Mon Sep 17 00:00:00 2001 From: Peter Turczak Date: Fri, 17 Apr 2020 08:39:09 +0100 Subject: [PATCH] chan_mobile: Add smoother to make SIP/RTP endpoints happy. In contrast to RFC 3551, section 4.2, several SIP/RTP clients misbehave severly (up to crashing). This patch adds another smoother for the audio received via bt. Therefore the audio frames sent to the core will be CHANNEL_FRAME_SIZE. ASTERISK-28832 #close Change-Id: Ic5f9e2f35868ae59cc9356afbd1388b779a1267f --- addons/chan_mobile.c | 63 +++++++++++++++++++++++++++----------------- 1 file changed, 39 insertions(+), 24 deletions(-) diff --git a/addons/chan_mobile.c b/addons/chan_mobile.c index 427977da3f..240c2d4ee6 100644 --- a/addons/chan_mobile.c +++ b/addons/chan_mobile.c @@ -132,7 +132,8 @@ struct mbl_pvt { int rfcomm_socket; /* rfcomm socket descriptor */ char rfcomm_buf[256]; char io_buf[CHANNEL_FRAME_SIZE + AST_FRIENDLY_OFFSET]; - struct ast_smoother *smoother; /* our smoother, for making 48 byte frames */ + struct ast_smoother *bt_out_smoother; /* our bt_out_smoother, for making 48 byte frames */ + struct ast_smoother *bt_in_smoother; /* our smoother, for making "normal" CHANNEL_FRAME_SIZEed byte frames */ int sco_socket; /* sco socket descriptor */ pthread_t monitor_thread; /* monitor thread handle */ int timeout; /*!< used to set the timeout for rfcomm data (may be used in the future) */ @@ -856,7 +857,8 @@ static struct ast_channel *mbl_new(int state, struct mbl_pvt *pvt, struct cidinf else pvt->do_alignment_detection = 0; - ast_smoother_reset(pvt->smoother, DEVICE_FRAME_SIZE); + ast_smoother_reset(pvt->bt_out_smoother, DEVICE_FRAME_SIZE); + ast_smoother_reset(pvt->bt_in_smoother, CHANNEL_FRAME_SIZE); ast_dsp_digitreset(pvt->dsp); chn = ast_channel_alloc(1, state, @@ -1131,23 +1133,27 @@ static struct ast_frame *mbl_read(struct ast_channel *ast) pvt->fr.delivery.tv_usec = 0; pvt->fr.data.ptr = pvt->io_buf + AST_FRIENDLY_OFFSET; - if ((r = read(pvt->sco_socket, pvt->fr.data.ptr, DEVICE_FRAME_SIZE)) == -1) { - if (errno != EAGAIN && errno != EINTR) { - ast_debug(1, "[%s] read error %d, going to wait for new connection\n", pvt->id, errno); - close(pvt->sco_socket); - pvt->sco_socket = -1; - ast_channel_set_fd(ast, 0, -1); + do { + if ((r = read(pvt->sco_socket, pvt->fr.data.ptr, DEVICE_FRAME_SIZE)) == -1) { + if (errno != EAGAIN && errno != EINTR) { + ast_debug(1, "[%s] read error %d, going to wait for new connection\n", pvt->id, errno); + close(pvt->sco_socket); + pvt->sco_socket = -1; + ast_channel_set_fd(ast, 0, -1); + } + goto e_return; } - goto e_return; - } - pvt->fr.datalen = r; - pvt->fr.samples = r / 2; + pvt->fr.datalen = r; + pvt->fr.samples = r / 2; - if (pvt->do_alignment_detection) - do_alignment_detection(pvt, pvt->fr.data.ptr, r); + if (pvt->do_alignment_detection) + do_alignment_detection(pvt, pvt->fr.data.ptr, r); - fr = ast_dsp_process(ast, pvt->dsp, &pvt->fr); + ast_smoother_feed(pvt->bt_in_smoother, &pvt->fr); + fr = ast_smoother_read(pvt->bt_in_smoother); + } while (fr == NULL); + fr = ast_dsp_process(ast, pvt->dsp, fr); ast_mutex_unlock(&pvt->lock); @@ -1174,9 +1180,9 @@ static int mbl_write(struct ast_channel *ast, struct ast_frame *frame) CHANNEL_DEADLOCK_AVOIDANCE(ast); } - ast_smoother_feed(pvt->smoother, frame); + ast_smoother_feed(pvt->bt_out_smoother, frame); - while ((f = ast_smoother_read(pvt->smoother))) { + while ((f = ast_smoother_read(pvt->bt_out_smoother))) { sco_write(pvt->sco_socket, f->data.ptr, f->datalen); } @@ -4530,16 +4536,22 @@ static struct mbl_pvt *mbl_load_device(struct ast_config *cfg, const char *cat) pvt->ring_sched_id = -1; pvt->has_sms = 1; - /* setup the smoother */ - if (!(pvt->smoother = ast_smoother_new(DEVICE_FRAME_SIZE))) { - ast_log(LOG_ERROR, "Skipping device %s. Error setting up frame smoother.\n", cat); + /* setup the bt_out_smoother */ + if (!(pvt->bt_out_smoother = ast_smoother_new(DEVICE_FRAME_SIZE))) { + ast_log(LOG_ERROR, "Skipping device %s. Error setting up frame bt_out_smoother.\n", cat); goto e_free_pvt; } + /* setup the bt_in_smoother */ + if (!(pvt->bt_in_smoother = ast_smoother_new(CHANNEL_FRAME_SIZE))) { + ast_log(LOG_ERROR, "Skipping device %s. Error setting up frame bt_in_smoother.\n", cat); + goto e_free_bt_out_smoother; + } + /* setup the dsp */ if (!(pvt->dsp = ast_dsp_new())) { ast_log(LOG_ERROR, "Skipping device %s. Error setting up dsp for dtmf detection.\n", cat); - goto e_free_smoother; + goto e_free_bt_in_smoother; } /* setup the scheduler */ @@ -4599,8 +4611,10 @@ e_free_sched: ast_sched_context_destroy(pvt->sched); e_free_dsp: ast_dsp_free(pvt->dsp); -e_free_smoother: - ast_smoother_free(pvt->smoother); +e_free_bt_in_smoother: + ast_smoother_free(pvt->bt_in_smoother); +e_free_bt_out_smoother: + ast_smoother_free(pvt->bt_out_smoother); e_free_pvt: ast_free(pvt); e_return: @@ -4732,7 +4746,8 @@ static int unload_module(void) ast_free(pvt->hfp); } - ast_smoother_free(pvt->smoother); + ast_smoother_free(pvt->bt_out_smoother); + ast_smoother_free(pvt->bt_in_smoother); ast_dsp_free(pvt->dsp); ast_sched_context_destroy(pvt->sched); ast_free(pvt);