AMR: WIP
Change-Id: I09e3c6cc8139d7be042278775b8de0b223513d53
This commit is contained in:
parent
9319514041
commit
71dce2a4e4
|
@ -35,7 +35,7 @@ const int g_remote_port = 9000;
|
|||
const int g_local_port = 8000;
|
||||
|
||||
/* codec; can be OSMO_TRAU16_FT_FR or OSMO_TRAU16_FT_EFR */
|
||||
const enum osmo_trau_frame_type g_ftype = OSMO_TRAU16_FT_EFR;
|
||||
const enum osmo_trau_frame_type g_ftype = OSMO_TRAU16_FT_AMR;
|
||||
|
||||
/***********************************************************************
|
||||
* END CONFIGURATION
|
||||
|
@ -114,21 +114,35 @@ static void sync_frame_out_cb(void *user_data, const ubit_t *bits, unsigned int
|
|||
if (g_local_loop) {
|
||||
/* Mirror back to other sub-slot */
|
||||
struct sc_state *peer = opposite_schan(sc);
|
||||
if (peer) {
|
||||
struct msgb *msg = msgb_alloc(2*40*8, "mirror");
|
||||
if (!peer)
|
||||
return;
|
||||
|
||||
struct msgb *msg = msgb_alloc(2*40*8, "mirror");
|
||||
|
||||
if (fr.type == OSMO_TRAU16_FT_AMR) {
|
||||
//fr.c_bits[12-1] = FIXME; /* Req/Ind flag; use from UL */
|
||||
fr.c_bits[13-1] = 1; /* UFT: no errors */
|
||||
memset(&fr.c_bits[14-1], 0, 3); /* Config_Prot: no TFO */
|
||||
memset(&fr.c_bits[17-1], 0, 2); /* Message_No: no TFO */
|
||||
fr.c_bits[19-1] = 1; /* Reserved */
|
||||
fr.c_bits[20-1] = 1; /* Reserved */
|
||||
|
||||
} else {
|
||||
fr.c_bits[12-1] = 1; /* C12 = good u-link frame */
|
||||
memset(&fr.c_bits[13-1], 1, 3); /* C13..C15: spare */
|
||||
fr.c_bits[16-1] = 1; /* C16 = SP[eech]; no DTX */
|
||||
memset(&fr.c_bits[6-1], 0, 6); /* C6..C11: tie alignment */
|
||||
fr.dir = OSMO_TRAU_DIR_DL;
|
||||
rc = osmo_trau_frame_encode(msgb_data(msg), 2*40*8, &fr);
|
||||
OSMO_ASSERT(rc >= 0);
|
||||
msgb_put(msg, rc);
|
||||
osmo_i460_mux_enqueue(peer->i460_sc, msg);
|
||||
}
|
||||
fr.dir = OSMO_TRAU_DIR_DL;
|
||||
rc = osmo_trau_frame_encode(msgb_data(msg), 2*40*8, &fr);
|
||||
OSMO_ASSERT(rc >= 0);
|
||||
msgb_put(msg, rc);
|
||||
osmo_i460_mux_enqueue(peer->i460_sc, msg);
|
||||
} else {
|
||||
/* Convert to RTP */
|
||||
if (fr.type != OSMO_TRAU16_FT_FR && fr.type != OSMO_TRAU16_FT_EFR)
|
||||
if (fr.type != OSMO_TRAU16_FT_FR &&
|
||||
fr.type != OSMO_TRAU16_FT_EFR &&
|
||||
fr.type != OSMO_TRAU16_FT_AMR)
|
||||
goto skip;
|
||||
|
||||
uint8_t rtpbuf[35];
|
||||
|
|
|
@ -24,6 +24,11 @@
|
|||
|
||||
struct osmo_trau2rtp_state {
|
||||
enum osmo_trau_frame_type type;
|
||||
struct {
|
||||
enum osmo_amr_type last_cmi;
|
||||
enum osmo_amr_type last_cmr;
|
||||
bool cmi_cmr_phase;
|
||||
} amr;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include <osmocom/core/crc8gen.h>
|
||||
#include <osmocom/codec/codec.h>
|
||||
#include <osmocom/netif/amr.h>
|
||||
|
||||
#include <osmocom/trau/trau_frame.h>
|
||||
#include <osmocom/trau/trau_rtp.h>
|
||||
|
@ -489,103 +490,199 @@ static int rtp2trau_efr(struct osmo_trau_frame *tf, const uint8_t *data, size_t
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static inline memcpy_inc(uint8_t *out, const uint8_t *in, size_t len, unsigned int *idx)
|
||||
/* memcpy + increment index */
|
||||
static inline void memcpy_inc(uint8_t *out, const uint8_t *in, size_t len, unsigned int *idx)
|
||||
{
|
||||
memcpy_inc(out, in, len);
|
||||
memcpy(out, in, len);
|
||||
*idx += len;
|
||||
}
|
||||
|
||||
#define S_FROM_D(sbits, dbits, d_from, d_to, idx) \
|
||||
memcpy_inc(sbits + idx, dbits + (d_from-1), d_to - (d_from-1), &idx)
|
||||
|
||||
/* extract the AMR s-bits (codec parameters) from the TRAU frame D-bits */
|
||||
static int amr_speech_extract_sbits(ubit_t *s_bits, const struct osmo_trau_frame *tf,
|
||||
enum osmo_amr_mode mode)
|
||||
enum osmo_amr_type mode)
|
||||
{
|
||||
unsigned int s_idx = 0;
|
||||
|
||||
switch (mode) {
|
||||
case AMR_4_75:
|
||||
memcpy_inc(s_bits + s_idx, tf->d_bits + 44, 67 - 44, &s_idx);
|
||||
memcpy_inc(s_bits + s_idx, tf->d_bits + 67, 92 - 67, &s_idx);
|
||||
memcpy_inc(s_bits + s_idx, tf->d_bits + 95, 108 - 95, &s_idx);
|
||||
memcpy_inc(s_bits + s_idx, tf->d_bits + 111, 132 - 111, &s_idx);
|
||||
memcpy_inc(s_bits + s_idx, tf->d_bits + 135, 148 - 135, &s_idx);
|
||||
S_FROM_D(s_bits, tf->d_bits, 45, 67, s_idx);
|
||||
S_FROM_D(s_bits, tf->d_bits, 68, 92, s_idx);
|
||||
S_FROM_D(s_bits, tf->d_bits, 96, 108, s_idx);
|
||||
S_FROM_D(s_bits, tf->d_bits, 112, 132, s_idx);
|
||||
S_FROM_D(s_bits, tf->d_bits, 136, 148, s_idx);
|
||||
break;
|
||||
case AMR_5_15:
|
||||
memcpy_inc(s_bits + s_idx, tf->d_bits + 46, 96 - 46, &s_idx);
|
||||
memcpy_inc(s_bits + s_idx, tf->d_bits + 69, 92 - 69, &s_idx);
|
||||
memcpy_inc(s_bits + s_idx, tf->d_bits + 95, 114 - 95, &s_idx);
|
||||
memcpy_inc(s_bits + s_idx, tf->d_bits + 117, 136 - 117, &s_idx);
|
||||
memcpy_inc(s_bits + s_idx, tf->d_bits + 139, 158 - 139, &s_idx);
|
||||
S_FROM_D(s_bits, tf->d_bits, 47, 69, s_idx);
|
||||
S_FROM_D(s_bits, tf->d_bits, 70, 92, s_idx);
|
||||
S_FROM_D(s_bits, tf->d_bits, 96, 114, s_idx);
|
||||
S_FROM_D(s_bits, tf->d_bits, 118, 136, s_idx);
|
||||
S_FROM_D(s_bits, tf->d_bits, 140, 158, s_idx);
|
||||
break;
|
||||
case AMR_5_90:
|
||||
memcpy_inc(s_bits + s_idx, tf->d_bits + 41, 67 - 41, &s_idx);
|
||||
memcpy_inc(s_bits + s_idx, tf->d_bits + 67, 92 - 67, &s_idx);
|
||||
memcpy_inc(s_bits + s_idx, tf->d_bits + 95, 116 - 95, &s_idx);
|
||||
memcpy_inc(s_bits + s_idx, tf->d_bits + 119, 144 - 119, &s_idx);
|
||||
memcpy_inc(s_bits + s_idx, tf->d_bits + 147, 168 - 147, &s_idx);
|
||||
S_FROM_D(s_bits, tf->d_bits, 42, 67, s_idx);
|
||||
S_FROM_D(s_bits, tf->d_bits, 68, 92, s_idx);
|
||||
S_FROM_D(s_bits, tf->d_bits, 96, 116, s_idx);
|
||||
S_FROM_D(s_bits, tf->d_bits, 120, 144, s_idx);
|
||||
S_FROM_D(s_bits, tf->d_bits, 148, 168, s_idx);
|
||||
break;
|
||||
case AMR_6_70:
|
||||
memcpy_inc(s_bits + s_idx, tf->d_bits + 37, 63 - 37, &s_idx);
|
||||
memcpy_inc(s_bits + s_idx, tf->d_bits + 63, 92 - 63, &s_idx);
|
||||
memcpy_inc(s_bits + s_idx, tf->d_bits + 95, 120 - 95, &s_idx);
|
||||
memcpy_inc(s_bits + s_idx, tf->d_bits + 123, 152 - 123, &s_idx);
|
||||
memcpy_inc(s_bits + s_idx, tf->d_bits + 155, 180 - 155, &s_idx);
|
||||
S_FROM_D(s_bits, tf->d_bits, 38, 63, s_idx);
|
||||
S_FROM_D(s_bits, tf->d_bits, 64, 92, s_idx);
|
||||
S_FROM_D(s_bits, tf->d_bits, 96, 120, s_idx);
|
||||
S_FROM_D(s_bits, tf->d_bits, 124, 152, s_idx);
|
||||
S_FROM_D(s_bits, tf->d_bits, 156, 180, s_idx);
|
||||
break;
|
||||
case AMR_7_40:
|
||||
memcpy_inc(s_bits + s_idx, tf->d_bits + 34, 60 - 34, &s_idx);
|
||||
memcpy_inc(s_bits + s_idx, tf->d_bits + 60, 92 - 60, &s_idx);
|
||||
memcpy_inc(s_bits + s_idx, tf->d_bits + 95, 124 - 95, &s_idx);
|
||||
memcpy_inc(s_bits + s_idx, tf->d_bits + 127, 159 - 127, &s_idx);
|
||||
memcpy_inc(s_bits + s_idx, tf->d_bits + 162, 191 - 162, &s_idx);
|
||||
S_FROM_D(s_bits, tf->d_bits, 35, 60, s_idx);
|
||||
S_FROM_D(s_bits, tf->d_bits, 61, 92, s_idx);
|
||||
S_FROM_D(s_bits, tf->d_bits, 96, 124, s_idx);
|
||||
S_FROM_D(s_bits, tf->d_bits, 128, 159, s_idx);
|
||||
S_FROM_D(s_bits, tf->d_bits, 163, 191, s_idx);
|
||||
break;
|
||||
case AMR_7_95:
|
||||
memcpy_inc(s_bits + s_idx, tf->d_bits + 31, 58 - 31, &s_idx);
|
||||
memcpy_inc(s_bits + s_idx, tf->d_bits + 58, 92 - 58, &s_idx);
|
||||
memcpy_inc(s_bits + s_idx, tf->d_bits + 95, 127 - 95, &s_idx);
|
||||
memcpy_inc(s_bits + s_idx, tf->d_bits + 130, 164 - 130, &s_idx);
|
||||
memcpy_inc(s_bits + s_idx, tf->d_bits + 167, 199 - 167, &s_idx);
|
||||
S_FROM_D(s_bits, tf->d_bits, 32, 58, s_idx);
|
||||
S_FROM_D(s_bits, tf->d_bits, 59, 92, s_idx);
|
||||
S_FROM_D(s_bits, tf->d_bits, 96, 127, s_idx);
|
||||
S_FROM_D(s_bits, tf->d_bits, 131, 164, s_idx);
|
||||
S_FROM_D(s_bits, tf->d_bits, 168, 199, s_idx);
|
||||
break;
|
||||
case AMR_10_2:
|
||||
memcpy_inc(s_bits + s_idx, tf->d_bits + 20, 46 - 20, &s_idx); /* D21..D46 */
|
||||
memcpy_inc(s_bits + s_idx, tf->d_bits + 46, 92 - 46, &s_idx);
|
||||
memcpy_inc(s_bits + s_idx, tf->d_bits + 95, 138 - 95, &s_idx);
|
||||
memcpy_inc(s_bits + s_idx, tf->d_bits + 141, 187 - 141, &s_idx);
|
||||
memcpy_inc(s_bits + s_idx, tf->d_bits + 190, 233 - 190, &s_idx);
|
||||
S_FROM_D(s_bits, tf->d_bits, 21, 46, s_idx);
|
||||
S_FROM_D(s_bits, tf->d_bits, 47, 92, s_idx);
|
||||
S_FROM_D(s_bits, tf->d_bits, 96, 138, s_idx);
|
||||
S_FROM_D(s_bits, tf->d_bits, 142, 187, s_idx);
|
||||
S_FROM_D(s_bits, tf->d_bits, 191, 233, s_idx);
|
||||
break;
|
||||
case AMR_12_2:
|
||||
memcpy_inc(s_bits + s_idx, tf->d_bits + 0, 38 - 0, &s_idx); /* D1..D38 */
|
||||
memcpy_inc(s_bits + s_idx, tf->d_bits + 38, 91 - 38, &s_idx); /* D39..D91 */
|
||||
memcpy_inc(s_bits + s_idx, tf->d_bits + 94, 144 - 94, &s_idx); /* D95..D144 */
|
||||
memcpy_inc(s_bits + s_idx, tf->d_bits + 147, 200 - 147, &s_idx);/* D148..D200 */
|
||||
memcpy_inc(s_bits + s_idx, tf->d_bits + 203, 253 - 203, &s_idx);/* D204..D253 */
|
||||
S_FROM_D(s_bits, tf->d_bits, 1, 38, s_idx); /* D1..D38 */
|
||||
S_FROM_D(s_bits, tf->d_bits, 39, 91, s_idx); /* D39..D91 */
|
||||
S_FROM_D(s_bits, tf->d_bits, 95, 144, s_idx); /* D95..D144 */
|
||||
S_FROM_D(s_bits, tf->d_bits, 148, 200, s_idx); /* D148..D200 */
|
||||
S_FROM_D(s_bits, tf->d_bits, 204, 253, s_idx); /* D204..D253 */
|
||||
break;
|
||||
default:
|
||||
osmo_panic("unknown AMR speech mode: %u", mode);
|
||||
break;
|
||||
}
|
||||
|
||||
return s_idx;
|
||||
}
|
||||
|
||||
/* TS 48.060 Section 5.5.1.2.2 */
|
||||
static int trau2rtp_16(uint8_t *out, const struct osmo_trau_frame *tf, enum osmo_amr_mode last_cmi)
|
||||
#define D_FROM_S(dbits, sbits, d_from, d_to, idx) \
|
||||
memcpy_inc(dbits + (d_from-1), sbits + idx, d_to - (d_from-1), &idx)
|
||||
|
||||
/* encode the AMR TRAU frame D-bits from the s-bits (codec parameters) */
|
||||
static int amr_speech_encode_sbits(struct osmo_trau_frame *tf, const ubit_t *s_bits, enum osmo_amr_type mode)
|
||||
{
|
||||
enum osmo_amr_mode mode = last_cmi;
|
||||
uint8_t frame_class = tf->c_bits[21] << 1 | tf->c_bits[20];
|
||||
uint8_t cmr_cmi = tf->c_bits[23] << 2 | tf->c_bits[24] << 1 | tf->cb_bits[25];
|
||||
uint8_t no_speech_cls;
|
||||
uint8_t s_bits[242];
|
||||
uint8_t d_bits[242];
|
||||
unsigned int s_idx = 0;
|
||||
ubit_t rif = FIXME;
|
||||
|
||||
switch (mode) {
|
||||
case AMR_4_75:
|
||||
D_FROM_S(tf->d_bits, s_bits, 45, 67, s_idx);
|
||||
D_FROM_S(tf->d_bits, s_bits, 68, 92, s_idx);
|
||||
D_FROM_S(tf->d_bits, s_bits, 96, 108, s_idx);
|
||||
D_FROM_S(tf->d_bits, s_bits, 112, 132, s_idx);
|
||||
D_FROM_S(tf->d_bits, s_bits, 136, 148, s_idx);
|
||||
break;
|
||||
case AMR_5_15:
|
||||
D_FROM_S(tf->d_bits, s_bits, 47, 69, s_idx);
|
||||
D_FROM_S(tf->d_bits, s_bits, 70, 92, s_idx);
|
||||
D_FROM_S(tf->d_bits, s_bits, 96, 114, s_idx);
|
||||
D_FROM_S(tf->d_bits, s_bits, 118, 136, s_idx);
|
||||
D_FROM_S(tf->d_bits, s_bits, 140, 158, s_idx);
|
||||
break;
|
||||
case AMR_5_90:
|
||||
D_FROM_S(tf->d_bits, s_bits, 42, 67, s_idx);
|
||||
D_FROM_S(tf->d_bits, s_bits, 68, 92, s_idx);
|
||||
D_FROM_S(tf->d_bits, s_bits, 96, 116, s_idx);
|
||||
D_FROM_S(tf->d_bits, s_bits, 124, 152, s_idx);
|
||||
D_FROM_S(tf->d_bits, s_bits, 156, 180, s_idx);
|
||||
break;
|
||||
case AMR_6_70:
|
||||
D_FROM_S(tf->d_bits, s_bits, 38, 63, s_idx);
|
||||
D_FROM_S(tf->d_bits, s_bits, 64, 92, s_idx);
|
||||
D_FROM_S(tf->d_bits, s_bits, 96, 120, s_idx);
|
||||
D_FROM_S(tf->d_bits, s_bits, 124, 152, s_idx);
|
||||
D_FROM_S(tf->d_bits, s_bits, 156, 180, s_idx);
|
||||
break;
|
||||
case AMR_7_40:
|
||||
D_FROM_S(tf->d_bits, s_bits, 35, 60, s_idx);
|
||||
D_FROM_S(tf->d_bits, s_bits, 61, 92, s_idx);
|
||||
D_FROM_S(tf->d_bits, s_bits, 96, 124, s_idx);
|
||||
D_FROM_S(tf->d_bits, s_bits, 128, 159, s_idx);
|
||||
D_FROM_S(tf->d_bits, s_bits, 163, 191, s_idx);
|
||||
break;
|
||||
case AMR_7_95:
|
||||
D_FROM_S(tf->d_bits, s_bits, 32, 58, s_idx);
|
||||
D_FROM_S(tf->d_bits, s_bits, 59, 92, s_idx);
|
||||
D_FROM_S(tf->d_bits, s_bits, 96, 127, s_idx);
|
||||
D_FROM_S(tf->d_bits, s_bits, 131, 164, s_idx);
|
||||
D_FROM_S(tf->d_bits, s_bits, 168, 199, s_idx);
|
||||
break;
|
||||
case AMR_10_2:
|
||||
D_FROM_S(tf->d_bits, s_bits, 21, 46, s_idx);
|
||||
D_FROM_S(tf->d_bits, s_bits, 47, 92, s_idx);
|
||||
D_FROM_S(tf->d_bits, s_bits, 96, 138, s_idx);
|
||||
D_FROM_S(tf->d_bits, s_bits, 142, 187, s_idx);
|
||||
D_FROM_S(tf->d_bits, s_bits, 191, 233, s_idx);
|
||||
break;
|
||||
case AMR_12_2:
|
||||
D_FROM_S(tf->d_bits, s_bits, 1, 38, s_idx);
|
||||
D_FROM_S(tf->d_bits, s_bits, 39, 91, s_idx);
|
||||
D_FROM_S(tf->d_bits, s_bits, 95, 144, s_idx);
|
||||
D_FROM_S(tf->d_bits, s_bits, 148, 200, s_idx);
|
||||
D_FROM_S(tf->d_bits, s_bits, 204, 253, s_idx);
|
||||
default:
|
||||
osmo_panic("unknown AMR speech mode: %u", mode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Frame_Classification as per TS 48.060 Section 5.5.1.2.1 */
|
||||
enum amr_frame_class {
|
||||
AMR_FCLS_SPEECH_GOOD = 3,
|
||||
AMR_FCLS_SPEECH_DEGRADED = 2,
|
||||
AMR_FCLS_SPEECH_BAD = 1,
|
||||
AMR_FCLS_NO_SPEECH = 0,
|
||||
};
|
||||
|
||||
/* TS 48.060 Section 5.5.1.2.2 */
|
||||
static int trau2rtp_16(uint8_t *out, const struct osmo_trau_frame *tf, struct osmo_trau2rtp_state *st)
|
||||
{
|
||||
uint8_t frame_class = (tf->c_bits[21-1] << 1) | tf->c_bits[20-1];
|
||||
uint8_t cmr_cmi = (tf->c_bits[23-1] << 2) | (tf->c_bits[24-1] << 1) | tf->c_bits[25-1];
|
||||
ubit_t rif = tf->c_bits[12-1]; /* Request (1) or Indication (0) Flag */
|
||||
uint8_t tac_pac = (tf->c_bits[6-1] << 5) | (tf->c_bits[7-1] << 4) | (tf->c_bits[8-1] << 3) |
|
||||
(tf->c_bits[9-1] << 2) | (tf->c_bits[10-1] << 1) | tf->c_bits[11-1];
|
||||
uint8_t no_speech_cls;
|
||||
uint8_t s_bits[244];
|
||||
uint8_t d_bits[244];
|
||||
bool bad_frame = false;
|
||||
int n_sbits = 0;
|
||||
|
||||
if (tf->type != OSMO_TRAU16_FT_AMR)
|
||||
return -EINVAL;
|
||||
|
||||
if (rif == 0)
|
||||
mode = cmr_cmi;
|
||||
if (rif == 0) {
|
||||
/* peer (BTS) tells us CMI */
|
||||
st->amr.last_cmi = cmr_cmi;
|
||||
} else {
|
||||
/* peer (BTS) tells us CMR */
|
||||
st->amr.last_cmr = cmr_cmi;
|
||||
}
|
||||
|
||||
if (tac_pac == 0x3d) {
|
||||
/* FIXME: BTS requests us to invert CMI/CMR phase in downlink */
|
||||
}
|
||||
|
||||
switch (frame_class) {
|
||||
case 0: // no speech
|
||||
no_speech_cls = tf->d_bits[32] << 2 | tf->d_bits[33] << 1 | tf->d_bits[34];
|
||||
cmi_abs = tf->d_bits[35] << 2 | tf->d_bits[36] < 1 || tf->d_bits[37];
|
||||
cmr_abs = tf->d_bits[38] << 2 | tf->d_bits[39] < 1 || tf->d_bits[40];
|
||||
case AMR_FCLS_NO_SPEECH:
|
||||
no_speech_cls = (tf->d_bits[32-1] << 2) | (tf->d_bits[33-1] << 1) | tf->d_bits[34-1];
|
||||
st->amr.last_cmi = (tf->d_bits[35-1] << 2) | (tf->d_bits[36-1] < 1) || tf->d_bits[37-1];
|
||||
st->amr.last_cmr = (tf->d_bits[38-1] << 2) | (tf->d_bits[39-1] < 1) || tf->d_bits[40-1];
|
||||
switch (no_speech_cls) {
|
||||
case 7: // sid first
|
||||
break;
|
||||
|
@ -597,25 +694,89 @@ static int trau2rtp_16(uint8_t *out, const struct osmo_trau_frame *tf, enum osmo
|
|||
break;
|
||||
case 0: // no_data
|
||||
break;
|
||||
/* TOOD: PAB to be treated as PAC */
|
||||
/* TODO: Time Alignment Extension (TAE) */
|
||||
}
|
||||
break;
|
||||
case 1: // speech bad
|
||||
case AMR_FCLS_SPEECH_BAD:
|
||||
bad_frame = true;
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
case AMR_FCLS_SPEECH_GOOD:
|
||||
case AMR_FCLS_SPEECH_DEGRADED:
|
||||
/* Extract the s-bits from the TRAU frame */
|
||||
amr_speech_extract_sbits(s_bits, tf, mode);
|
||||
n_sbits = amr_speech_extract_sbits(s_bits, tf, st->amr.last_cmi);
|
||||
/* Convert the s-bits to d-bits */
|
||||
osmo_amr_s_to_d(d_bits, s_bits, mode);
|
||||
osmo_amr_s_to_d(d_bits, s_bits, n_sbits, st->amr.last_cmi);
|
||||
break;
|
||||
}
|
||||
|
||||
/* generate octet-aligned RTP AMR header / RFC4867 */
|
||||
struct amr_hdr *amrh = (struct amr_hdr *) out;
|
||||
amrh->pad1 = 0;
|
||||
amrh->cmr = st->amr.last_cmr;
|
||||
amrh->pad2 = 0;
|
||||
amrh->q = !bad_frame;
|
||||
amrh->ft = st->amr.last_cmi;
|
||||
amrh->f = 0;
|
||||
|
||||
/* return number of bytes generated */
|
||||
return osmo_ubit2pbit(out + sizeof(*amrh), d_bits, n_sbits) + sizeof(*amrh);
|
||||
}
|
||||
|
||||
int trau2rtp_amr(uint8_t *out, const struct osmo_trau_frame *tf, enum osmo_amr_mode last_cmi))
|
||||
static int rtp2trau_amr(struct osmo_trau_frame *tf, const uint8_t *data, size_t data_len,
|
||||
struct osmo_trau2rtp_state *st)
|
||||
{
|
||||
struct amr_hdr *amrh = (struct amr_hdr *) data;
|
||||
ubit_t s_bits[244];
|
||||
|
||||
if (data_len < sizeof(*amrh))
|
||||
return -EIO;
|
||||
|
||||
if (data_len > FIXME)
|
||||
data_len = FIXM;
|
||||
|
||||
/* C1..C5: AMR */
|
||||
tf->c_bits[1-1] = 0;
|
||||
tf->c_bits[2-1] = 0;
|
||||
tf->c_bits[3-1] = 1;
|
||||
tf->c_bits[4-1] = 1;
|
||||
tf->c_bits[5-1] = 0;
|
||||
|
||||
/* C6..C11: TAF: TAC / PAC */
|
||||
memset(&tf->c_bits[6-1], 0, 6);
|
||||
|
||||
|
||||
//tf->c_bits[12-1] = ; /* RIF */
|
||||
tf->c_bits[13-1] = 1; /* UFE */
|
||||
memset(&tf->c_bits[14-1], 0, 3); /* Config_Prot */
|
||||
memset(&tf->c_bits[17-1], 0, 3); /* Message_No */
|
||||
tf->c_bits[19-1] = 1; /* spare */
|
||||
tf->c_bits[20-1] = 1; /* spare */
|
||||
|
||||
#if 0
|
||||
tf->c_bits[21-1]
|
||||
tf->c_bits[22-1]
|
||||
|
||||
/* CMI (RIF=0) or CMR (RIF=1) */
|
||||
tf->c_bits[23-1]
|
||||
tf->c_bits[24-1]
|
||||
tf->c_bits[25-1]
|
||||
#endif
|
||||
|
||||
/* TODO: convert s-bits to d-bits */
|
||||
osmo_pbit2ubit(s_bits, data + sizeof(*amrh), data_len-sizeof(*amrh));
|
||||
amr_speech_encode_sbits(tf, s_bits, mode)
|
||||
|
||||
/* TODO: compute CRC */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int trau2rtp_amr(uint8_t *out, size_t out_len, const struct osmo_trau_frame *tf, struct osmo_trau2rtp_state *st)
|
||||
{
|
||||
switch (tf->type) {
|
||||
case OSMO_TRAU16_FT_AMR:
|
||||
return trau2rtp_16(out, tf, last_cmi);
|
||||
return trau2rtp_16(out, tf, st);
|
||||
case OSMO_TRAU8_AMR_LOW:
|
||||
case OSMO_TRAU8_AMR_6k7:
|
||||
case OSMO_TRAU8_AMR_7k4:
|
||||
|
@ -623,7 +784,6 @@ int trau2rtp_amr(uint8_t *out, const struct osmo_trau_frame *tf, enum osmo_amr_m
|
|||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int osmo_trau2rtp(uint8_t *out, size_t out_len, const struct osmo_trau_frame *tf,
|
||||
struct osmo_trau2rtp_state *st)
|
||||
|
@ -635,6 +795,8 @@ int osmo_trau2rtp(uint8_t *out, size_t out_len, const struct osmo_trau_frame *tf
|
|||
return trau2rtp_efr(out, out_len, tf);
|
||||
case OSMO_TRAU16_FT_HR:
|
||||
return trau2rtp_hr16(out, out_len, tf);
|
||||
case OSMO_TRAU16_FT_AMR:
|
||||
return trau2rtp_amr(out, out_len, tf, st);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -650,6 +812,8 @@ int osmo_rtp2trau(struct osmo_trau_frame *tf, const uint8_t *rtp, size_t rtp_len
|
|||
return rtp2trau_efr(tf, rtp, rtp_len);
|
||||
case OSMO_TRAU16_FT_HR:
|
||||
return rtp2trau_hr16(tf, rtp, rtp_len);
|
||||
case OSMO_TRAU16_FT_AMR:
|
||||
//return rtp2trau_amr(tf, rtp, rtp_len, st);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue