<p>laforge <strong>submitted</strong> this change.</p><p><a href="https://gerrit.osmocom.org/c/osmo-bts/+/17221">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  laforge: Looks good to me, approved
  pespin: Looks good to me, but someone else must approve
  Jenkins Builder: Verified

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">dtx: add detection of AMR DTX frames for osmo-bts-trx<br><br>Currently we do not detect any of the DTX frames (SID_FIRST, SID_UPDATE<br>etc.) Detecting and tagging those frames as is_sub is important for<br>measurement processing. Also the RTP marker bit must be set on each<br>ONSET frame.<br><br> - Add detection of DTX frames<br> - Tag DTX frames as is_sub and set frame type to AMR_SID<br> - Set RTP marker bit when ONSET frames are received<br><br>Change-Id: I5afe730fff2fa3199a5913b0de4f5c7b23a39f31<br>Depends: libosmocore I2bbdb39ea20461ca08b2e6f1a33532cb55cd5195<br>Related: OS#2978<br>---<br>M include/osmo-bts/scheduler.h<br>M include/osmo-bts/scheduler_backend.h<br>M src/common/scheduler.c<br>M src/osmo-bts-trx/scheduler_trx.c<br>4 files changed, 107 insertions(+), 13 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/osmo-bts/scheduler.h b/include/osmo-bts/scheduler.h</span><br><span>index fed3f04..c026411 100644</span><br><span>--- a/include/osmo-bts/scheduler.h</span><br><span>+++ b/include/osmo-bts/scheduler.h</span><br><span>@@ -106,6 +106,7 @@</span><br><span>    uint8_t                 ul_cmr;         /* current uplink CMR index */</span><br><span>       uint8_t                 dl_cmr;         /* current downlink CMR index */</span><br><span>     uint8_t                 amr_loop;       /* if AMR loop is enabled */</span><br><span style="color: hsl(120, 100%, 40%);">+  uint8_t                 amr_last_dtx;   /* last received dtx frame type */</span><br><span> </span><br><span>       /* TCH/H */</span><br><span>  uint8_t                 dl_ongoing_facch; /* FACCH/H on downlink */</span><br><span>diff --git a/include/osmo-bts/scheduler_backend.h b/include/osmo-bts/scheduler_backend.h</span><br><span>index 201b48c..cfbe7f2 100644</span><br><span>--- a/include/osmo-bts/scheduler_backend.h</span><br><span>+++ b/include/osmo-bts/scheduler_backend.h</span><br><span>@@ -53,7 +53,8 @@</span><br><span> </span><br><span> int _sched_compose_tch_ind(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,</span><br><span>                        enum trx_chan_type chan, uint8_t *tch, uint8_t tch_len,</span><br><span style="color: hsl(0, 100%, 40%);">-                         int16_t ta_offs_256bits, uint16_t ber10k, float rssi);</span><br><span style="color: hsl(120, 100%, 40%);">+                        int16_t ta_offs_256bits, uint16_t ber10k, float rssi,</span><br><span style="color: hsl(120, 100%, 40%);">+                         uint8_t is_sub);</span><br><span> </span><br><span> ubit_t *tx_idle_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,</span><br><span>      enum trx_chan_type chan, uint8_t bid, uint16_t *nbits);</span><br><span>diff --git a/src/common/scheduler.c b/src/common/scheduler.c</span><br><span>index fc4f11e..be3ae42 100644</span><br><span>--- a/src/common/scheduler.c</span><br><span>+++ b/src/common/scheduler.c</span><br><span>@@ -739,7 +739,8 @@</span><br><span> </span><br><span> int _sched_compose_tch_ind(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,</span><br><span>                          enum trx_chan_type chan, uint8_t *tch, uint8_t tch_len,</span><br><span style="color: hsl(0, 100%, 40%);">-                         int16_t ta_offs_256bits, uint16_t ber10k, float rssi)</span><br><span style="color: hsl(120, 100%, 40%);">+                         int16_t ta_offs_256bits, uint16_t ber10k, float rssi,</span><br><span style="color: hsl(120, 100%, 40%);">+                         uint8_t is_sub)</span><br><span> {</span><br><span>      struct msgb *msg;</span><br><span>    struct osmo_phsap_prim *l1sap;</span><br><span>@@ -758,6 +759,7 @@</span><br><span>         l1sap->u.tch.rssi = (int8_t) (rssi);</span><br><span>      l1sap->u.tch.ber10k = ber10k;</span><br><span>     l1sap->u.tch.ta_offs_256bits = ta_offs_256bits;</span><br><span style="color: hsl(120, 100%, 40%);">+    l1sap->u.tch.is_sub = is_sub & 1;</span><br><span> </span><br><span>         msg->l2h = msgb_put(msg, tch_len);</span><br><span>        if (tch_len)</span><br><span>diff --git a/src/osmo-bts-trx/scheduler_trx.c b/src/osmo-bts-trx/scheduler_trx.c</span><br><span>index f17354a..8c3dd64 100644</span><br><span>--- a/src/osmo-bts-trx/scheduler_trx.c</span><br><span>+++ b/src/osmo-bts-trx/scheduler_trx.c</span><br><span>@@ -37,6 +37,8 @@</span><br><span> #include <osmocom/core/bits.h></span><br><span> #include <osmocom/gsm/a5.h></span><br><span> #include <osmocom/coding/gsm0503_coding.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/coding/gsm0503_amr_dtx.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> </span><br><span> #include <osmo-bts/gsm_data.h></span><br><span> #include <osmo-bts/logging.h></span><br><span>@@ -400,7 +402,7 @@</span><br><span> </span><br><span>                     /* Note: RSSI is set to 0 to indicate to the higher</span><br><span>                   * layers that this is a faked tch_ind */</span><br><span style="color: hsl(0, 100%, 40%);">-                       _sched_compose_tch_ind(l1t, tn, fn, chan, tch_data, len, toa256, 10000, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+                   _sched_compose_tch_ind(l1t, tn, fn, chan, tch_data, len, toa256, 10000, 0, 0);</span><br><span>               }</span><br><span>    }</span><br><span> </span><br><span>@@ -1138,6 +1140,8 @@</span><br><span>                get_lchan_by_chan_nr(l1t->trx, trx_chan_desc[chan].chan_nr | bi->tn);</span><br><span>  unsigned int fn_begin;</span><br><span>       uint16_t ber10k;</span><br><span style="color: hsl(120, 100%, 40%);">+      uint8_t is_sub = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+   uint8_t ft;</span><br><span> </span><br><span>      /* handle rach, if handover rach detection is turned on */</span><br><span>   if (chan_state->ho_rach_detect == 1)</span><br><span>@@ -1200,21 +1204,65 @@</span><br><span>             * the first FN 4,13,21 defines that CMR is included in frame.</span><br><span>                * NOTE: A frame ends 7 FN after start.</span><br><span>               */</span><br><span style="color: hsl(0, 100%, 40%);">-             rc = gsm0503_tch_afs_decode(tch_data + 2, *bursts_p,</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                /* The AFS_ONSET frame itself does not result into an RTP frame</span><br><span style="color: hsl(120, 100%, 40%);">+                * since it only contains a recognition pattern that marks the</span><br><span style="color: hsl(120, 100%, 40%);">+                 * end of the DTX interval. To mark the end of the DTX interval</span><br><span style="color: hsl(120, 100%, 40%);">+                * in the RTP stream as well, the voice frame after the</span><br><span style="color: hsl(120, 100%, 40%);">+                * AFS_ONSET frame is used. */</span><br><span style="color: hsl(120, 100%, 40%);">+                if (chan_state->amr_last_dtx == AFS_ONSET)</span><br><span style="color: hsl(120, 100%, 40%);">+                 lchan_set_marker(false, lchan);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+             /* we store tch_data + 2 header bytes, the amr variable set to</span><br><span style="color: hsl(120, 100%, 40%);">+                 * 2 will allow us to skip the first 2 bytes in case we did</span><br><span style="color: hsl(120, 100%, 40%);">+            * receive an FACCH frame instead of a voice frame (we do not</span><br><span style="color: hsl(120, 100%, 40%);">+          * know this before we actually decode the frame) */</span><br><span style="color: hsl(120, 100%, 40%);">+          amr = 2;</span><br><span style="color: hsl(120, 100%, 40%);">+              rc = gsm0503_tch_afs_decode_dtx(tch_data + amr, *bursts_p,</span><br><span>                   (((bi->fn + 26 - 7) % 26) >> 2) & 1, chan_state->codec,</span><br><span>                      chan_state->codecs, &chan_state->ul_ft,</span><br><span style="color: hsl(0, 100%, 40%);">-                       &chan_state->ul_cmr, &n_errors, &n_bits_total);</span><br><span style="color: hsl(120, 100%, 40%);">+                        &chan_state->ul_cmr, &n_errors, &n_bits_total, &chan_state->amr_last_dtx);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+            /* Tag all frames that are not regular AMR voice frames as</span><br><span style="color: hsl(120, 100%, 40%);">+             * SUB-Frames */</span><br><span style="color: hsl(120, 100%, 40%);">+              if (chan_state->amr_last_dtx != AMR_OTHER) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       LOGL1S(DL1P, LOGL_DEBUG, l1t, bi->tn, chan, bi->fn,</span><br><span style="color: hsl(120, 100%, 40%);">+                            "Received AMR SID frame: %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                             gsm0503_amr_dtx_frame_name(chan_state->amr_last_dtx));</span><br><span style="color: hsl(120, 100%, 40%);">+                      is_sub = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+           }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           /* The occurrence of the following frames indicates that we</span><br><span style="color: hsl(120, 100%, 40%);">+            * are either at the beginning or in the middle of a talk</span><br><span style="color: hsl(120, 100%, 40%);">+              * spurt. We update the SID status accordingly, but we do</span><br><span style="color: hsl(120, 100%, 40%);">+              * not want the marker to be set, since this must only</span><br><span style="color: hsl(120, 100%, 40%);">+                 * happen when the talk spurt is over (see above) */</span><br><span style="color: hsl(120, 100%, 40%);">+          switch (chan_state->amr_last_dtx) {</span><br><span style="color: hsl(120, 100%, 40%);">+                case AFS_SID_FIRST:</span><br><span style="color: hsl(120, 100%, 40%);">+           case AFS_SID_UPDATE:</span><br><span style="color: hsl(120, 100%, 40%);">+          case AFS_SID_UPDATE_CN:</span><br><span style="color: hsl(120, 100%, 40%);">+                       lchan_set_marker(true, lchan);</span><br><span style="color: hsl(120, 100%, 40%);">+                        lchan->rtp_tx_marker = false;</span><br><span style="color: hsl(120, 100%, 40%);">+                      break;</span><br><span style="color: hsl(120, 100%, 40%);">+                }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>          if (rc)</span><br><span>                      trx_loop_amr_input(l1t,</span><br><span>                              trx_chan_desc[chan].chan_nr | bi->tn, chan_state,</span><br><span>                                 n_errors, n_bits_total);</span><br><span style="color: hsl(0, 100%, 40%);">-                amr = 2; /* we store tch_data + 2 header bytes */</span><br><span>            /* only good speech frames get rtp header */</span><br><span>                 if (rc != GSM_MACBLOCK_LEN && rc >= 4) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   if (chan_state->amr_last_dtx == AMR_OTHER) {</span><br><span style="color: hsl(120, 100%, 40%);">+                               ft = chan_state->codec[chan_state->ul_cmr];</span><br><span style="color: hsl(120, 100%, 40%);">+                     } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                              /* SID frames will always get Frame Type Index 8 (AMR_SID) */</span><br><span style="color: hsl(120, 100%, 40%);">+                         ft = AMR_SID;</span><br><span style="color: hsl(120, 100%, 40%);">+                 }</span><br><span>                    rc = osmo_amr_rtp_enc(tch_data,</span><br><span>                              chan_state->codec[chan_state->ul_cmr],</span><br><span style="color: hsl(0, 100%, 40%);">-                            chan_state->codec[chan_state->ul_ft], AMR_GOOD);</span><br><span style="color: hsl(120, 100%, 40%);">+                                ft, AMR_GOOD);</span><br><span>               }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>          break;</span><br><span>       default:</span><br><span>             LOGL1S(DL1P, LOGL_ERROR, l1t, bi->tn, chan, bi->fn,</span><br><span>@@ -1308,7 +1356,7 @@</span><br><span> compose_l1sap:</span><br><span>  fn_begin = gsm0502_fn_remap(bi->fn, FN_REMAP_TCH_F);</span><br><span>      return _sched_compose_tch_ind(l1t, bi->tn, fn_begin, chan,</span><br><span style="color: hsl(0, 100%, 40%);">-                                 tch_data, rc, bi->toa256, ber10k, bi->rssi);</span><br><span style="color: hsl(120, 100%, 40%);">+                                    tch_data, rc, bi->toa256, ber10k, bi->rssi, is_sub);</span><br><span> }</span><br><span> </span><br><span> /*! \brief a single TCH/H burst was received by the PHY, process it */</span><br><span>@@ -1336,6 +1384,8 @@</span><br><span>  int fn_is_odd = (((bi->fn + 26 - 10) % 26) >> 2) & 1;</span><br><span>   unsigned int fn_begin;</span><br><span>       uint16_t ber10k;</span><br><span style="color: hsl(120, 100%, 40%);">+      uint8_t is_sub = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+   uint8_t ft;</span><br><span> </span><br><span>      /* handle RACH, if handover RACH detection is turned on */</span><br><span>   if (chan_state->ho_rach_detect == 1)</span><br><span>@@ -1409,21 +1459,61 @@</span><br><span>             * in frame, the first FN 4,13,21 or 5,14,22 defines that CMR</span><br><span>                 * is included in frame.</span><br><span>              */</span><br><span style="color: hsl(0, 100%, 40%);">-             rc = gsm0503_tch_ahs_decode(tch_data + 2, *bursts_p,</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                /* See comment in function rx_tchf_fn() */</span><br><span style="color: hsl(120, 100%, 40%);">+            switch (chan_state->amr_last_dtx) {</span><br><span style="color: hsl(120, 100%, 40%);">+                case AHS_ONSET:</span><br><span style="color: hsl(120, 100%, 40%);">+               case AHS_SID_FIRST_INH:</span><br><span style="color: hsl(120, 100%, 40%);">+               case AHS_SID_UPDATE_INH:</span><br><span style="color: hsl(120, 100%, 40%);">+                      lchan_set_marker(false, lchan);</span><br><span style="color: hsl(120, 100%, 40%);">+                       break;</span><br><span style="color: hsl(120, 100%, 40%);">+                }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           /* See comment in function rx_tchf_fn() */</span><br><span style="color: hsl(120, 100%, 40%);">+            amr = 2;</span><br><span style="color: hsl(120, 100%, 40%);">+              rc = gsm0503_tch_ahs_decode_dtx(tch_data + amr, *bursts_p,</span><br><span>                   fn_is_odd, fn_is_odd, chan_state->codec,</span><br><span>                  chan_state->codecs, &chan_state->ul_ft,</span><br><span style="color: hsl(0, 100%, 40%);">-                       &chan_state->ul_cmr, &n_errors, &n_bits_total);</span><br><span style="color: hsl(120, 100%, 40%);">+                        &chan_state->ul_cmr, &n_errors, &n_bits_total, &chan_state->amr_last_dtx);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+            /* Tag all frames that are not regular AMR voice frames</span><br><span style="color: hsl(120, 100%, 40%);">+                  as SUB-Frames */</span><br><span style="color: hsl(120, 100%, 40%);">+           if (chan_state->amr_last_dtx != AMR_OTHER) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       LOGL1S(DL1P, LOGL_DEBUG, l1t, bi->tn, chan, bi->fn,</span><br><span style="color: hsl(120, 100%, 40%);">+                            "Received AMR SID frame: %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                             gsm0503_amr_dtx_frame_name(chan_state->amr_last_dtx));</span><br><span style="color: hsl(120, 100%, 40%);">+                      is_sub = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+           }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           /* See comment in function rx_tchf_fn() */</span><br><span style="color: hsl(120, 100%, 40%);">+            switch (chan_state->amr_last_dtx) {</span><br><span style="color: hsl(120, 100%, 40%);">+                case AHS_SID_FIRST_P1:</span><br><span style="color: hsl(120, 100%, 40%);">+                case AHS_SID_FIRST_P2:</span><br><span style="color: hsl(120, 100%, 40%);">+                case AHS_SID_UPDATE:</span><br><span style="color: hsl(120, 100%, 40%);">+          case AHS_SID_UPDATE_CN:</span><br><span style="color: hsl(120, 100%, 40%);">+                       lchan_set_marker(true, lchan);</span><br><span style="color: hsl(120, 100%, 40%);">+                        lchan->rtp_tx_marker = false;</span><br><span style="color: hsl(120, 100%, 40%);">+                      break;</span><br><span style="color: hsl(120, 100%, 40%);">+                }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>          if (rc)</span><br><span>                      trx_loop_amr_input(l1t,</span><br><span>                              trx_chan_desc[chan].chan_nr | bi->tn, chan_state,</span><br><span>                                 n_errors, n_bits_total);</span><br><span style="color: hsl(0, 100%, 40%);">-                amr = 2; /* we store tch_data + 2 two */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>           /* only good speech frames get rtp header */</span><br><span>                 if (rc != GSM_MACBLOCK_LEN && rc >= 4) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   if (chan_state->amr_last_dtx == AMR_OTHER) {</span><br><span style="color: hsl(120, 100%, 40%);">+                               ft = chan_state->codec[chan_state->ul_cmr];</span><br><span style="color: hsl(120, 100%, 40%);">+                     } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                              /* SID frames will always get Frame Type Index 8 (AMR_SID) */</span><br><span style="color: hsl(120, 100%, 40%);">+                         ft = AMR_SID;</span><br><span style="color: hsl(120, 100%, 40%);">+                 }</span><br><span>                    rc = osmo_amr_rtp_enc(tch_data,</span><br><span>                              chan_state->codec[chan_state->ul_cmr],</span><br><span style="color: hsl(0, 100%, 40%);">-                            chan_state->codec[chan_state->ul_ft], AMR_GOOD);</span><br><span style="color: hsl(120, 100%, 40%);">+                                ft, AMR_GOOD);</span><br><span>               }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>          break;</span><br><span>       default:</span><br><span>             LOGL1S(DL1P, LOGL_ERROR, l1t, bi->tn, chan, bi->fn,</span><br><span>@@ -1529,7 +1619,7 @@</span><br><span>    else</span><br><span>                 fn_begin = gsm0502_fn_remap(bi->fn, FN_REMAP_TCH_H1);</span><br><span>     return _sched_compose_tch_ind(l1t, bi->tn, fn_begin, chan,</span><br><span style="color: hsl(0, 100%, 40%);">-                                 tch_data, rc, bi->toa256, ber10k, bi->rssi);</span><br><span style="color: hsl(120, 100%, 40%);">+                                    tch_data, rc, bi->toa256, ber10k, bi->rssi, is_sub);</span><br><span> }</span><br><span> </span><br><span> /* schedule all frames of all TRX for given FN */</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-bts/+/17221">change 17221</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/c/osmo-bts/+/17221"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmo-bts </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I5afe730fff2fa3199a5913b0de4f5c7b23a39f31 </div>
<div style="display:none"> Gerrit-Change-Number: 17221 </div>
<div style="display:none"> Gerrit-PatchSet: 7 </div>
<div style="display:none"> Gerrit-Owner: dexter <pmaier@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder </div>
<div style="display:none"> Gerrit-Reviewer: dexter <pmaier@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: fixeria <axilirator@gmail.com> </div>
<div style="display:none"> Gerrit-Reviewer: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-Reviewer: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>