store the last SID frame of a given LCHAN so we can repeat it

repeating the last SID frame is required during 20ms intervals where we
don't get a new SID update (SID RTP frames are valid up to 160ms)
This commit is contained in:
Harald Welte 2011-09-07 12:42:15 +02:00
parent e5d082f356
commit f49e3dd3af
1 changed files with 50 additions and 2 deletions

View File

@ -264,8 +264,9 @@ int get_amr_mode_idx(const struct amr_multirate_conf *amr_mrc, uint8_t cmi)
*/
static int rtppayload_to_l1_amr(uint8_t *l1_payload, uint8_t *rtp_payload,
uint8_t payload_len,
struct amr_multirate_conf *amr_mrc)
struct gsm_lchan *lchan)
{
struct amr_multirate_conf *amr_mrc = &lchan->tch.amr_mr;
uint8_t ft = (rtp_payload[1] >> 3) & 0xf;
uint8_t cmr = rtp_payload[0] >> 4;
uint8_t cmi, sti;
@ -343,6 +344,15 @@ static int rtppayload_to_l1_amr(uint8_t *l1_payload, uint8_t *rtp_payload,
/* lower 4 bit of first FR2 byte contains FT */
l1_payload[2] |= ft;
if (ft == AMR_FT_SID_AMR) {
/* store the last SID frame in lchan context */
unsigned int copy_len;
copy_len = OSMO_MIN(payload_len+1,
ARRAY_SIZE(lchan->tch.last_sid.buf));
lchan->tch.last_sid.len = copy_len;
memcpy(lchan->tch.last_sid.buf, l1_payload, copy_len);
}
return payload_len+1;
}
@ -396,7 +406,7 @@ void bts_model_rtp_rx_cb(struct osmo_rtp_socket *rs, uint8_t *rtp_pl,
case GSM48_CMODE_SPEECH_AMR:
*payload_type = GsmL1_TchPlType_Amr;
rc = rtppayload_to_l1_amr(l1_payload, rtp_pl,
rtp_pl_len, &lchan->tch.amr_mr);
rtp_pl_len, lchan);
break;
default:
/* we don't support CSD modes */
@ -519,3 +529,41 @@ err_payload_match:
get_value_string(femtobts_tch_pl_names, payload_type));
return -EINVAL;
}
struct msgb *gen_empty_tch_msg(struct gsm_lchan *lchan)
{
struct msgb *msg = l1p_msgb_alloc();
GsmL1_Prim_t *l1p = msgb_l1prim(msg);
GsmL1_PhDataReq_t *data_req = &l1p->u.phDataReq;
GsmL1_MsgUnitParam_t *msu_param = &data_req->msgUnitParam;
uint8_t *payload_type = &msu_param->u8Buffer[0];
uint8_t *l1_payload = &msu_param->u8Buffer[1];
switch (lchan->tch_mode) {
case GSM48_CMODE_SPEECH_AMR:
*payload_type = GsmL1_TchPlType_Amr;
if (lchan->tch.last_sid.len) {
memcpy(l1_payload, lchan->tch.last_sid.buf,
lchan->tch.last_sid.len);
msu_param->u8Size = lchan->tch.last_sid.len+1;
} else {
/* FIXME: decide if we should send SPEECH_BAD or
* SID_BAD */
#if 0
*payload_type = GsmL1_TchPlType_Amr_SidBad;
memset(l1_payload, 0xFF, 5);
msu_param->u8Size = 5 + 3;
#else
/* send an all-zero SID */
msu_param->u8Size = 8;
#endif
}
break;
default:
msgb_free(msg);
msg = NULL;
break;
}
return msg;
}