diff options
author | Max <msuraev@sysmocom.de> | 2016-09-27 19:47:08 +0200 |
---|---|---|
committer | Max <msuraev@sysmocom.de> | 2016-09-30 18:57:00 +0200 |
commit | 9959f45d90166331dc8196c603184888bbe7f1e8 (patch) | |
tree | 1816bbd0edc32cceda96001e6d64d192dd838691 /src/osmo-bts-sysmo/tch.c | |
parent | 7dffd553df0ca48f52d6faca70aa3e9cf2760840 (diff) |
DTX: further AMR SID cache fixes (lc15, sysmo)
* consolidate AMR CMR and CMI handling in common/amr.c
* use it in save_last_sid()
* remove dead code
* properly compute RTP payload length for AMR
* use save_last_sid() for FR & HR as well
* invalidate cached SID if SPEECH frame is received
Fixes: OS #1800, #1801
Change-Id: I5a1c1ad0b0a295a50e67775a4db85f1d331755ed
Diffstat (limited to 'src/osmo-bts-sysmo/tch.c')
-rw-r--r-- | src/osmo-bts-sysmo/tch.c | 115 |
1 files changed, 33 insertions, 82 deletions
diff --git a/src/osmo-bts-sysmo/tch.c b/src/osmo-bts-sysmo/tch.c index 0e4b2dab..655884d2 100644 --- a/src/osmo-bts-sysmo/tch.c +++ b/src/osmo-bts-sysmo/tch.c @@ -282,19 +282,9 @@ static struct msgb *l1_to_rtppayload_amr(uint8_t *l1_payload, uint8_t payload_le */ static int rtppayload_to_l1_amr(uint8_t *l1_payload, const uint8_t *rtp_payload, uint8_t payload_len, - struct gsm_lchan *lchan, uint32_t fn) + struct gsm_lchan *lchan, uint8_t cmr, int8_t cmi, + uint8_t ft) { - struct amr_multirate_conf *amr_mrc = &lchan->tch.amr_mr; - enum osmo_amr_type ft; - enum osmo_amr_quality bfi; - uint8_t cmr; - int8_t sti, cmi; - uint8_t *l1_cmi_idx = l1_payload; - uint8_t *l1_cmr_idx = l1_payload+1; - int rc; - - osmo_amr_rtp_dec(rtp_payload, payload_len, &cmr, &cmi, &ft, &bfi, &sti); - #ifdef USE_L1_RTP_MODE memcpy(l1_payload+2, rtp_payload, payload_len); #else @@ -309,72 +299,9 @@ static int rtppayload_to_l1_amr(uint8_t *l1_payload, const uint8_t *rtp_payload, /* lower 4 bit of first FR2 byte contains FT */ l1_payload[2] |= ft; #endif /* USE_L1_RTP_MODE */ + amr_set_mode_pref(l1_payload, &lchan->tch.amr_mr, cmi, cmr); - /* CMI in downlink tells the L1 encoder which encoding function - * it will use, so we have to use the frame type */ - switch (ft) { - case 0: case 1: case 2: case 3: - case 4: case 5: case 6: case 7: - cmi = ft; - LOGP(DRTP, LOGL_DEBUG, "SPEECH frame with CMI %u\n", cmi); - break; - case AMR_NO_DATA: - LOGP(DRTP, LOGL_DEBUG, "SPEECH frame AMR NO_DATA\n"); - break; - case AMR_SID: - LOGP(DRTP, LOGL_DEBUG, "SID %s frame with CMI %u\n", - sti ? "UPDATE" : "FIRST", cmi); - break; - default: - LOGP(DRTP, LOGL_ERROR, "unsupported AMR FT 0x%02x\n", ft); - return -EINVAL; - break; - } - - rc = get_amr_mode_idx(amr_mrc, cmi); - if (rc < 0) { - LOGP(DRTP, LOGL_ERROR, "AMR CMI %u not part of AMR MR set\n", - cmi); - *l1_cmi_idx = 0; - } else - *l1_cmi_idx = rc; - - /* Codec Mode Request is in upper 4 bits of RTP payload header, - * and we simply copy the CMR into the CMC */ - if (cmr == 0xF) { - /* FIXME: we need some state about the last codec mode */ - *l1_cmr_idx = 0; - } else { - rc = get_amr_mode_idx(amr_mrc, cmr); - if (rc < 0) { - /* FIXME: we need some state about the last codec mode */ - LOGP(DRTP, LOGL_INFO, "RTP->L1: overriding CMR %u\n", cmr); - *l1_cmr_idx = 0; - } else - *l1_cmr_idx = rc; - } -#if 0 - /* check for bad quality indication */ - if (bfi == AMR_GOOD) { - /* obtain frame type from AMR FT */ - l1_payload[2] = ft; - } else { - /* bad quality, we should indicate that... */ - if (ft == AMR_SID) { - /* FIXME: Should we do GsmL1_TchPlType_Amr_SidBad? */ - l1_payload[2] = ft; - } else { - l1_payload[2] = ft; - } - } -#endif - - if (ft == AMR_SID) { - save_last_sid(lchan, l1_payload, payload_len, fn, sti); - return -EALREADY; - } - - return payload_len+1; + return payload_len + 2; } #define RTP_MSGB_ALLOC_SIZE 512 @@ -401,6 +328,7 @@ bool l1if_tch_encode(struct gsm_lchan *lchan, uint8_t *data, uint8_t *len, enum osmo_amr_quality bfi; int8_t sti, cmi; int rc; + bool is_sid = false; DEBUGP(DRTP, "%s RTP IN: %s\n", gsm_lchan_name(lchan), osmo_hexdump(rtp_pl, rtp_pl_len)); @@ -414,34 +342,57 @@ bool l1if_tch_encode(struct gsm_lchan *lchan, uint8_t *data, uint8_t *len, *payload_type = GsmL1_TchPlType_Fr; rc = rtppayload_to_l1_fr(l1_payload, rtp_pl, rtp_pl_len); + if (rc) + is_sid = osmo_fr_check_sid(rtp_pl, rtp_pl_len); } else{ *payload_type = GsmL1_TchPlType_Hr; rc = rtppayload_to_l1_hr(l1_payload, rtp_pl, rtp_pl_len); + if (rc) + is_sid = osmo_hr_check_sid(rtp_pl, rtp_pl_len); } + if (is_sid) + save_last_sid(lchan, rtp_pl, rtp_pl_len, fn, -1, 0, 0); break; #if defined(L1_HAS_EFR) && defined(USE_L1_RTP_MODE) case GSM48_CMODE_SPEECH_EFR: *payload_type = GsmL1_TchPlType_Efr; rc = rtppayload_to_l1_efr(l1_payload, rtp_pl, rtp_pl_len); + /* FIXME: detect and save EFR SID */ break; #endif case GSM48_CMODE_SPEECH_AMR: + osmo_amr_rtp_dec(rtp_pl, rtp_pl_len, &cmr, &cmi, &ft, &bfi, + &sti); + if (ft == AMR_SID) { + save_last_sid(lchan, rtp_pl, rtp_pl_len, fn, sti, cmr, + cmi); + return false; + } + if (ft != AMR_NO_DATA && !osmo_amr_is_speech(ft)) { + LOGP(DRTP, LOGL_ERROR, "unsupported AMR FT 0x%02x\n", + ft); + return false; + } + if (osmo_amr_is_speech(ft)) { + if (lchan->tch.last_sid.len) { /* FIXME: force ONSET */ + marker = true; + } + /* We received AMR SPEECH frame - invalidate saved SID */ + lchan->tch.last_sid.len = 0; + } if (marker) { *payload_type = GsmL1_TchPlType_Amr_Onset; rc = 0; - osmo_amr_rtp_dec(rtp_pl, rtp_pl_len, &cmr, &cmi, &ft, - &bfi, &sti); LOGP(DRTP, LOGL_ERROR, "Marker SPEECH frame AMR %s\n", get_value_string(osmo_amr_type_names, ft)); } else { *payload_type = GsmL1_TchPlType_Amr; rc = rtppayload_to_l1_amr(l1_payload, rtp_pl, - rtp_pl_len, lchan, fn); - if (-EALREADY == rc) - return false; + rtp_pl_len, lchan, cmr, cmi, + ft); } break; default: |