diff options
author | Max <msuraev@sysmocom.de> | 2016-09-30 19:09:04 +0200 |
---|---|---|
committer | Max <msuraev@sysmocom.de> | 2016-09-30 19:09:04 +0200 |
commit | 067ef3f1ce1b7474a553bb8e54ff1543c4012828 (patch) | |
tree | dd96bd6d72a529de7fb27956f4d5e38008a25ceb /src/common/msg_utils.c | |
parent | 9959f45d90166331dc8196c603184888bbe7f1e8 (diff) |
DTX: move ONSET detection into separate function
Move code from tch.c (lc15, sysmo) into generic function which:
- check if talkspurt is happening
- cache SID if necessary or invalidate cache
- fill in CMR & CMI prefix
This also fixes the problem when SID FIRST was cached without sending
just like SID UPDATE instead of being sent right away.
Change-Id: I6c7016a54749abadeef4fd4f5b6f750b256fb916
Diffstat (limited to 'src/common/msg_utils.c')
-rw-r--r-- | src/common/msg_utils.c | 57 |
1 files changed, 55 insertions, 2 deletions
diff --git a/src/common/msg_utils.c b/src/common/msg_utils.c index 5c6bbbea..99a211fd 100644 --- a/src/common/msg_utils.c +++ b/src/common/msg_utils.c @@ -29,7 +29,7 @@ #include <osmocom/trau/osmo_ortp.h> #include <arpa/inet.h> - +#include <errno.h> static int check_fom(struct abis_om_hdr *omh, size_t len) { @@ -99,7 +99,7 @@ void lchan_set_marker(bool t, struct gsm_lchan *lchan) } } -/* store the last SID frame in lchan context */ + /*! \brief Store the last SID frame in lchan context * \param[in] lchan Logical channel on which we check scheduling * \param[in] l1_payload buffer with SID data @@ -126,6 +126,59 @@ void save_last_sid(struct gsm_lchan *lchan, const uint8_t *l1_payload, memcpy(lchan->tch.last_sid.buf + amr, l1_payload, copy_len); } +/*! \brief Check current and cached SID to decide if talkspurt takes place + * \param[in] lchan Logical channel on which we check scheduling + * \param[in] rtp_pl buffer with RTP data + * \param[in] rtp_pl_len length of rtp_pl + * \param[in] fn Frame Number for which we check scheduling + * \param[in] l1_payload buffer where CMR and CMI prefix should be added + * \param[out] ft_out Frame Type to be populated after decoding + * \returns 0 if frame should be send immediately (2 byte CMR,CMI prefix added: + * caller must adjust length as necessary), + * 1 if ONSET event is detected + * negative if no sending is necessary (either error or cached SID + * UPDATE) + */ +int dtx_amr_check_onset(struct gsm_lchan *lchan, const uint8_t *rtp_pl, + size_t rtp_pl_len, uint32_t fn, uint8_t *l1_payload, + uint8_t *ft_out) +{ + uint8_t cmr; + enum osmo_amr_type ft; + enum osmo_amr_quality bfi; + int8_t sti, cmi; + osmo_amr_rtp_dec(rtp_pl, rtp_pl_len, &cmr, &cmi, &ft, &bfi, &sti); + *ft_out = ft; /* only needed for old sysmo firmware */ + + if (ft == AMR_SID) { + save_last_sid(lchan, rtp_pl, rtp_pl_len, fn, sti, cmr, cmi); + if (sti) /* SID_UPDATE should be cached and send later */ + return -EAGAIN; + else { /* SID_FIRST - cached and send right away */ + amr_set_mode_pref(l1_payload, &lchan->tch.amr_mr, cmi, + cmr); + return 0; + } + } + + if (ft != AMR_NO_DATA && !osmo_amr_is_speech(ft)) { + LOGP(DRTP, LOGL_ERROR, "unsupported AMR FT 0x%02x\n", ft); + return -ENOTSUP; + } + + if (osmo_amr_is_speech(ft)) { + if (lchan->tch.last_sid.len) { /* force ONSET */ + lchan->tch.last_sid.len = 0; + return 1; + } + /* We received AMR SPEECH frame - invalidate saved SID */ + lchan->tch.last_sid.len = 0; + amr_set_mode_pref(l1_payload, &lchan->tch.amr_mr, cmi, cmr); + } + + return 0; +} + /*! \brief Check if enough time has passed since last SID (if any) to repeat it * \param[in] lchan Logical channel on which we check scheduling * \param[in] fn Frame Number for which we check scheduling |