]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
chan_mobile: Add smoother to make SIP/RTP endpoints happy.
authorPeter Turczak <peter@turczak.de>
Fri, 17 Apr 2020 07:39:09 +0000 (08:39 +0100)
committerPeter Turczak <peter@turczak.de>
Mon, 27 Apr 2020 14:40:38 +0000 (09:40 -0500)
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

index 427977da3f2e19fba74e1393ae951ffa32d37a27..240c2d4ee6b1ce6d1570e91b608d35b3bc79b458 100644 (file)
@@ -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);