コード例 #1
0
static struct msgb *l1_to_rtppayload_fr(uint8_t *l1_payload, uint8_t payload_len,
					struct gsm_lchan *lchan)
{
	struct msgb *msg;
	uint8_t *cur;

	msg = msgb_alloc_headroom(1024, 128, "L1C-to-RTP");
	if (!msg)
		return NULL;

#ifdef USE_L1_RTP_MODE
	/* new L1 can deliver bits like we need them */
	cur = msgb_put(msg, GSM_FR_BYTES);
	memcpy(cur, l1_payload, GSM_FR_BYTES);
#else
	/* step1: reverse the bit-order of each payload byte */
	osmo_revbytebits_buf(l1_payload, payload_len);

	cur = msgb_put(msg, GSM_FR_BYTES);

	/* step2: we need to shift the entire L1 payload by 4 bits right */
	osmo_nibble_shift_right(cur, l1_payload, GSM_FR_BITS/4);

	cur[0] |= 0xD0;
#endif /* USE_L1_RTP_MODE */

	lchan_set_marker(osmo_fr_check_sid(l1_payload, payload_len), lchan);

	return msg;
}
コード例 #2
0
ファイル: tch.c プロジェクト: osmocom/osmo-bts
static struct msgb *l1_to_rtppayload_fr(uint8_t *l1_payload, uint8_t payload_len,
					struct gsm_lchan *lchan)
{
	struct msgb *msg;
	uint8_t *cur;

	msg = msgb_alloc_headroom(1024, 128, "L1P-to-RTP");
	if (!msg)
		return NULL;

	/* new L1 can deliver bits like we need them */
	cur = msgb_put(msg, GSM_FR_BYTES);
	memcpy(cur, l1_payload, GSM_FR_BYTES);

	lchan_set_marker(osmo_fr_check_sid(l1_payload, payload_len), lchan);

	return msg;
}
コード例 #3
0
/*! \brief function for incoming RTP via TCH.req
 *  \param[in] rtp_pl buffer containing RTP payload
 *  \param[in] rtp_pl_len length of \a rtp_pl
 *  \param[in] use_cache Use cached payload instead of parsing RTP
 *  \param[in] marker RTP header Marker bit (indicates speech onset)
 *  \returns 0 if encoding result can be sent further to L1 without extra actions
 *           positive value if data is ready AND extra actions are required
 *           negative value otherwise (no data for L1 encoded)
 *
 * This function prepares a msgb with a L1 PH-DATA.req primitive and
 * queues it into lchan->dl_tch_queue.
 *
 * Note that the actual L1 primitive header is not fully initialized
 * yet, as things like the frame number, etc. are unknown at the time we
 * pre-fill the primtive.
 */
int l1if_tch_encode(struct gsm_lchan *lchan, uint8_t *data, uint8_t *len,
		    const uint8_t *rtp_pl, unsigned int rtp_pl_len, uint32_t fn,
		    bool use_cache, bool marker)
{
	uint8_t *payload_type;
	uint8_t *l1_payload, ft;
	int rc = 0;
	bool is_sid = false;

	DEBUGP(DRTP, "%s RTP IN: %s\n", gsm_lchan_name(lchan),
		osmo_hexdump(rtp_pl, rtp_pl_len));

	payload_type = &data[0];
	l1_payload = &data[1];

	switch (lchan->tch_mode) {
	case GSM48_CMODE_SPEECH_V1:
		if (lchan->type == GSM_LCHAN_TCH_F) {
			*payload_type = GsmL1_TchPlType_Fr;
			rc = rtppayload_to_l1_fr(l1_payload,
						 rtp_pl, rtp_pl_len);
			if (rc && lchan->ts->trx->bts->dtxd)
				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 && lchan->ts->trx->bts->dtxd)
				is_sid = osmo_hr_check_sid(rtp_pl, rtp_pl_len);
		}
		if (is_sid)
			dtx_cache_payload(lchan, rtp_pl, rtp_pl_len, fn, -1);
		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:
		if (use_cache) {
			*payload_type = GsmL1_TchPlType_Amr;
			rtppayload_to_l1_amr(l1_payload, lchan->tch.dtx.cache,
					     lchan->tch.dtx.len, ft);
			*len = lchan->tch.dtx.len + 1;
			return 0;
		}

		rc = dtx_dl_amr_fsm_step(lchan, rtp_pl, rtp_pl_len, fn,
					 l1_payload, marker, len, &ft);
		if (rc < 0)
			return rc;
		if (!dtx_dl_amr_enabled(lchan)) {
			*payload_type = GsmL1_TchPlType_Amr;
			rtppayload_to_l1_amr(l1_payload + 2, rtp_pl, rtp_pl_len,
					     ft);
			return 0;
		}

		/* DTX DL-specific logic below: */
		switch (lchan->tch.dtx.dl_amr_fsm->state) {
		case ST_ONSET_V:
			*payload_type = GsmL1_TchPlType_Amr_Onset;
			dtx_cache_payload(lchan, rtp_pl, rtp_pl_len, fn, 0);
			*len = 3;
			return 1;
		case ST_VOICE:
			*payload_type = GsmL1_TchPlType_Amr;
			rtppayload_to_l1_amr(l1_payload + 2, rtp_pl, rtp_pl_len,
					     ft);
			return 0;
		case ST_SID_F1:
			if (lchan->type == GSM_LCHAN_TCH_H) { /* AMR HR */
				*payload_type = GsmL1_TchPlType_Amr_SidFirstP1;
				rtppayload_to_l1_amr(l1_payload + 2, rtp_pl,
						     rtp_pl_len, ft);
				return 0;
			}
			/* AMR FR */
			*payload_type = GsmL1_TchPlType_Amr;
			rtppayload_to_l1_amr(l1_payload + 2, rtp_pl, rtp_pl_len,
					     ft);
			return 0;
		case ST_SID_F2:
			*payload_type = GsmL1_TchPlType_Amr;
			rtppayload_to_l1_amr(l1_payload + 2, rtp_pl, rtp_pl_len,
					     ft);
			return 0;
		case ST_F1_INH:
			*payload_type = GsmL1_TchPlType_Amr_SidFirstInH;
			*len = 3;
			dtx_cache_payload(lchan, rtp_pl, rtp_pl_len, fn, 0);
			return 1;
		case ST_U_INH:
			*payload_type = GsmL1_TchPlType_Amr_SidUpdateInH;
			*len = 3;
			dtx_cache_payload(lchan, rtp_pl, rtp_pl_len, fn, 0);
			return 1;
		case ST_SID_U:
			return -EAGAIN;
		case ST_FACCH:
			return -EBADMSG;
		default:
			LOGP(DRTP, LOGL_ERROR, "Unhandled DTX DL AMR FSM state "
			     "%d\n", lchan->tch.dtx.dl_amr_fsm->state);
			return -EINVAL;
		}
		break;
	default:
		/* we don't support CSD modes */
		rc = -1;
		break;
	}

	if (rc < 0) {
		LOGP(DRTP, LOGL_ERROR, "%s unable to parse RTP payload\n",
		     gsm_lchan_name(lchan));
		return -EBADMSG;
	}

	*len = rc + 1;

	DEBUGP(DRTP, "%s RTP->L1: %s\n", gsm_lchan_name(lchan),
		osmo_hexdump(data, *len));
	return 0;
}