summaryrefslogtreecommitdiff
path: root/pjmedia
diff options
context:
space:
mode:
authorNanang Izzuddin <nanang@teluu.com>2008-10-29 10:17:02 +0000
committerNanang Izzuddin <nanang@teluu.com>2008-10-29 10:17:02 +0000
commitdf432c0c6c3d436fca47bc3a83d46b1603cea182 (patch)
tree8d6dc265ffb50eb0825e3540eec10571ccf4724e /pjmedia
parent53775f4f08beac94a79829d8d3818b3c162d88fe (diff)
Ticket #670:
- Configurable setting to enable/disable AMR bitstream reordering (sensitivity order to/from encoder bits order). - Updated AMR codec to regard in-band Change Mode Request from remote encoder. - Updated AMR settings (octet-align, etc) to be configured upon codec opening, instead of hardcoded in the encode, decode, parse. git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@2359 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjmedia')
-rw-r--r--pjmedia/include/pjmedia-codec/amr_helper.h97
-rw-r--r--pjmedia/src/pjmedia-codec/ipp_codecs.c90
2 files changed, 128 insertions, 59 deletions
diff --git a/pjmedia/include/pjmedia-codec/amr_helper.h b/pjmedia/include/pjmedia-codec/amr_helper.h
index f7fd0aa4..28057646 100644
--- a/pjmedia/include/pjmedia-codec/amr_helper.h
+++ b/pjmedia/include/pjmedia-codec/amr_helper.h
@@ -604,7 +604,7 @@ typedef struct pjmedia_codec_amr_bit_info {
pj_uint8_t frame_type; /**< AMR frame type. */
pj_int8_t mode; /**< AMR mode. */
pj_uint8_t start_bit; /**< Frame start bit. */
- pj_uint8_t good_quality:1; /**< Flag if frame contains good data. */
+ pj_uint8_t good_quality:1; /**< Flag if frame is good/degraded. */
} pjmedia_codec_amr_bit_info;
#pragma pack()
@@ -613,12 +613,14 @@ typedef struct pjmedia_codec_amr_bit_info {
* This structure describes AMR settings.
*/
typedef struct pjmedia_codec_amr_settings {
- pj_bool_t amr_nb; /**< TRUE for AMR-NB, FALSE for AMR-WB */
- pj_uint8_t CMR; /**< Change Mode Request,
- in band message from encoder. */
+ pj_bool_t amr_nb; /**< TRUE for AMR-NB, FALSE for AMR-WB. */
+ pj_bool_t reorder; /**< Reorder bitstream into descending
+ sensitivity order or vice versa. */
pj_uint8_t octet_aligned; /**< TRUE if payload is in octet-aligned mode,
FALSE if payload is in bandwidth
efficient mode. */
+ pj_uint8_t CMR; /**< Change Mode Request for remote
+ encoder. */
} pjmedia_codec_amr_settings;
@@ -630,9 +632,9 @@ typedef struct pjmedia_codec_amr_settings {
* @return AMR mode.
*/
-PJ_INLINE(int) pjmedia_codec_amr_get_mode(unsigned bitrate)
+PJ_INLINE(pj_int8_t) pjmedia_codec_amr_get_mode(unsigned bitrate)
{
- int mode = -1;
+ pj_int8_t mode = -1;
if(bitrate==4750){
mode = 0;
@@ -675,20 +677,23 @@ PJ_INLINE(int) pjmedia_codec_amr_get_mode(unsigned bitrate)
}
/**
- * Rearrange AMR bitstream from sensitivity bits order into encoder bits order.
- * This will also make the start_bit to be 0. Basically this function should be
- * called before invoking decoder.
+ * Prepare a frame before pass it to decoder. This function will do:
+ * - reorder AMR bitstream from descending sensitivity order into
+ * encoder bits order. This can be enabled/disabled via param
+ * 'setting' by setting/resetting field 'reorder'.
+ * - align left the start bit (make the start_bit to be 0).
*
* @param amr_nb Set PJ_TRUE for AMR-NB and PJ_FALSE for AMR-WB.
* @param in Input frame.
+ * @param setting Settings, see @pjmedia_codec_amr_settings.
* @param out Output frame.
*
* @return PJ_SUCCESS on success.
*/
-PJ_INLINE(pj_status_t) pjmedia_codec_amr_reorder_sens_to_enc(
- pj_bool_t amr_nb,
- const pjmedia_frame *in,
- pjmedia_frame *out)
+PJ_INLINE(pj_status_t) pjmedia_codec_amr_predecode(
+ const pjmedia_frame *in,
+ const pjmedia_codec_amr_settings *setting,
+ pjmedia_frame *out)
{
pj_int8_t amr_bits[477 + 7] = {0};
pj_int8_t *p_amr_bits = &amr_bits[0];
@@ -712,7 +717,7 @@ PJ_INLINE(pj_status_t) pjmedia_codec_amr_reorder_sens_to_enc(
*out_info = *in_info;
- if (amr_nb) {
+ if (setting->amr_nb) {
SID_FT = 8;
framelen_tbl = pjmedia_codec_amrnb_framelen;
framelenbit_tbl = pjmedia_codec_amrnb_framelenbits;
@@ -750,19 +755,27 @@ PJ_INLINE(pj_status_t) pjmedia_codec_amr_reorder_sens_to_enc(
if (in_info->frame_type < SID_FT) {
/* Speech */
- const pj_int16_t *order_map;
-
out_info->mode = in_info->frame_type;
out->size = framelen_tbl[out_info->mode];
PJ_ASSERT_RETURN(out->size <= in->size, PJMEDIA_CODEC_EFRMINLEN);
- order_map = order_maps[out_info->mode];
pj_bzero(out->buf, out->size);
- for(i = 0; i < framelenbit_tbl[out_info->mode]; ++i) {
- if (amr_bits[i]) {
- pj_uint16_t bitpos;
- bitpos = order_map[i];
- w[bitpos>>3] |= 1 << (7 - (bitpos % 8));
+
+ if (setting->reorder) {
+ const pj_int16_t *order_map;
+
+ order_map = order_maps[out_info->mode];
+ for(i = 0; i < framelenbit_tbl[out_info->mode]; ++i) {
+ if (amr_bits[i]) {
+ pj_uint16_t bitpos;
+ bitpos = order_map[i];
+ w[bitpos>>3] |= 1 << (7 - (bitpos % 8));
+ }
+ }
+ } else {
+ for(i = 0; i < framelenbit_tbl[out_info->mode]; ++i) {
+ if (amr_bits[i])
+ w[i >> 3] |= 1 << (7 - (i % 8));
}
}
@@ -772,7 +785,7 @@ PJ_INLINE(pj_status_t) pjmedia_codec_amr_reorder_sens_to_enc(
pj_uint8_t w_bitptr = 0;
pj_uint8_t FT_;
- if (amr_nb)
+ if (setting->amr_nb)
FT_ = (pj_uint8_t)((amr_bits[36] << 2) | (amr_bits[37] << 1) |
amr_bits[38]);
else
@@ -948,19 +961,33 @@ PJ_INLINE (pj_status_t) pjmedia_codec_amr_pack(
if (info->frame_type < SID_FT) {
/* Speech */
- const pj_int16_t *order_map;
-
- /* Put bits in the packet, sensitivity descending ordered */
- order_map = order_maps[info->frame_type];
if (w_bitptr == 0) *w = 0;
- for(j = 0; j < framelenbit_tbl[info->frame_type]; ++j) {
- if (amr_bits[order_map[j]])
- *w |= (1 << (7-w_bitptr));
- if (++w_bitptr == 8) {
- w_bitptr = 0;
- ++w;
- *w = 0;
+ if (setting->reorder) {
+ const pj_int16_t *order_map;
+
+ /* Put bits in the packet, sensitivity descending ordered */
+ order_map = order_maps[info->frame_type];
+ for(j = 0; j < framelenbit_tbl[info->frame_type]; ++j) {
+ if (amr_bits[order_map[j]])
+ *w |= (1 << (7-w_bitptr));
+
+ if (++w_bitptr == 8) {
+ w_bitptr = 0;
+ ++w;
+ *w = 0;
+ }
+ }
+ } else {
+ for(j = 0; j < framelenbit_tbl[info->frame_type]; ++j) {
+ if (amr_bits[j])
+ *w |= (1 << (7-w_bitptr));
+
+ if (++w_bitptr == 8) {
+ w_bitptr = 0;
+ ++w;
+ *w = 0;
+ }
}
}
@@ -1018,7 +1045,7 @@ PJ_INLINE (pj_status_t) pjmedia_codec_amr_pack(
* @param setting Settings, see @pjmedia_codec_amr_settings.
* @param frames Frames parsed.
* @param nframes Number of frames parsed.
- * @param CMR Change Mode Request message from the encoder.
+ * @param CMR Change Mode Request message for local encoder.
*
* @return PJ_SUCCESS on success.
*/
diff --git a/pjmedia/src/pjmedia-codec/ipp_codecs.c b/pjmedia/src/pjmedia-codec/ipp_codecs.c
index 57e42c5f..1f044483 100644
--- a/pjmedia/src/pjmedia-codec/ipp_codecs.c
+++ b/pjmedia/src/pjmedia-codec/ipp_codecs.c
@@ -114,6 +114,7 @@ static struct ipp_factory {
/* IPP codecs private data. */
typedef struct ipp_private {
int codec_idx; /**< Codec index. */
+ void *codec_setting; /**< Specific codec setting. */
pj_pool_t *pool; /**< Pool for each instance. */
USC_Handle enc; /**< Encoder state. */
@@ -121,12 +122,14 @@ typedef struct ipp_private {
USC_CodecInfo *info; /**< Native codec info. */
pj_uint16_t frame_size; /**< Bitstream frame size. */
- pj_bool_t plc_enabled;
- pjmedia_plc *plc;
+ pj_bool_t plc_enabled; /**< PLC enabled flag. */
+ pjmedia_plc *plc; /**< PJMEDIA PLC engine, NULL if
+ codec has internal PLC. */
- pj_bool_t vad_enabled;
- pjmedia_silence_det *vad;
- pj_timestamp last_tx;
+ pj_bool_t vad_enabled; /**< VAD enabled flag. */
+ pjmedia_silence_det *vad; /**< PJMEDIA VAD engine, NULL if
+ codec has internal VAD. */
+ pj_timestamp last_tx; /**< Timestamp of last transmit.*/
} ipp_private_t;
@@ -419,6 +422,13 @@ static pj_status_t parse_g723(ipp_private_t *codec_data, void *pkt,
#include <pjmedia-codec/amr_helper.h>
+typedef struct amr_settings_t {
+ pjmedia_codec_amr_settings enc_setting;
+ pjmedia_codec_amr_settings dec_setting;
+ pj_int8_t enc_mode;
+} amr_settings_t;
+
+
/* Rearrange AMR bitstream and convert RTP frame into USC frame:
* - make the start_bit to be 0
* - if it is speech frame, reorder bitstream from sensitivity bits order
@@ -431,17 +441,18 @@ static void predecode_amr( ipp_private_t *codec_data,
{
pjmedia_frame frame;
pjmedia_codec_amr_bit_info *info;
- pj_bool_t amr_nb;
+ pjmedia_codec_amr_settings *setting;
+
+ setting = &((amr_settings_t*)codec_data->codec_setting)->dec_setting;
- amr_nb = (ipp_codec[codec_data->codec_idx].pt == PJMEDIA_RTP_PT_AMR);
frame = *rtp_frame;
- pjmedia_codec_amr_reorder_sens_to_enc(amr_nb, rtp_frame, &frame);
+ pjmedia_codec_amr_predecode(rtp_frame, setting, &frame);
info = (pjmedia_codec_amr_bit_info*) &frame.bit_info;
usc_frame->pBuffer = frame.buf;
usc_frame->nbytes = frame.size;
if (info->mode != -1) {
- usc_frame->bitrate = amr_nb?
+ usc_frame->bitrate = setting->amr_nb?
pjmedia_codec_amrnb_bitrates[info->mode]:
pjmedia_codec_amrwb_bitrates[info->mode];
} else {
@@ -453,7 +464,7 @@ static void predecode_amr( ipp_private_t *codec_data,
if (info->good_quality)
usc_frame->frametype = 0;
else
- usc_frame->frametype = amr_nb ? 5 : 6;
+ usc_frame->frametype = setting->amr_nb ? 5 : 6;
} else if (frame.size == 5) {
/* SID */
if (info->good_quality) {
@@ -461,7 +472,7 @@ static void predecode_amr( ipp_private_t *codec_data,
STI = (((pj_uint8_t*)frame.buf)[35 >> 3] & 0x10) != 0;
usc_frame->frametype = STI? 2 : 1;
} else {
- usc_frame->frametype = amr_nb ? 6 : 7;
+ usc_frame->frametype = setting->amr_nb ? 6 : 7;
}
} else {
/* no data */
@@ -475,18 +486,16 @@ static pj_status_t pack_amr(ipp_private_t *codec_data, void *pkt,
{
enum {MAX_FRAMES_PER_PACKET = 16};
- pjmedia_codec_amr_settings setting;
pjmedia_frame frames[MAX_FRAMES_PER_PACKET];
unsigned nframes = 0;
pjmedia_codec_amr_bit_info *info;
pj_uint8_t *r; /* Read cursor */
pj_uint8_t SID_FT;
+ pjmedia_codec_amr_settings *setting;
- setting.amr_nb = ipp_codec[codec_data->codec_idx].pt == PJMEDIA_RTP_PT_AMR;
- setting.CMR = 15; /* not requesting any mode */
- setting.octet_aligned = 0;
+ setting = &((amr_settings_t*)codec_data->codec_setting)->enc_setting;
- SID_FT = (pj_uint8_t)(setting.amr_nb? 8 : 9);
+ SID_FT = (pj_uint8_t)(setting->amr_nb? 8 : 9);
/* Align pkt buf right */
r = (pj_uint8_t*)pkt + max_pkt_size - *pkt_size;
@@ -520,7 +529,7 @@ static pj_status_t pack_amr(ipp_private_t *codec_data, void *pkt,
/* Pack */
*pkt_size = max_pkt_size;
- return pjmedia_codec_amr_pack(frames, nframes, &setting, pkt, pkt_size);
+ return pjmedia_codec_amr_pack(frames, nframes, setting, pkt, pkt_size);
}
@@ -529,14 +538,24 @@ static pj_status_t parse_amr(ipp_private_t *codec_data, void *pkt,
pj_size_t pkt_size, const pj_timestamp *ts,
unsigned *frame_cnt, pjmedia_frame frames[])
{
- pjmedia_codec_amr_settings setting;
+ amr_settings_t* s = (amr_settings_t*)codec_data->codec_setting;
+ pjmedia_codec_amr_settings *setting;
+ pj_status_t status;
pj_uint8_t CMR;
- setting.amr_nb = ipp_codec[codec_data->codec_idx].pt == PJMEDIA_RTP_PT_AMR;
- setting.octet_aligned = 0;
+ setting = &s->dec_setting;
- return pjmedia_codec_amr_parse(pkt, pkt_size, ts, &setting, frames,
- frame_cnt, &CMR);
+ status = pjmedia_codec_amr_parse(pkt, pkt_size, ts, setting, frames,
+ frame_cnt, &CMR);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ /* Check Change Mode Request. */
+ if ((setting->amr_nb && CMR <= 7) || (!setting->amr_nb && CMR <= 8)) {
+ s->enc_mode = CMR;
+ }
+
+ return PJ_SUCCESS;
}
#endif /* PJMEDIA_HAS_INTEL_IPP_CODEC_AMR */
@@ -1000,6 +1019,29 @@ static pj_status_t ipp_codec_open( pjmedia_codec *codec,
codec_data->vad_enabled = (attr->setting.vad != 0);
codec_data->plc_enabled = (attr->setting.plc != 0);
+#if PJMEDIA_HAS_INTEL_IPP_CODEC_AMR
+ /* Init AMR settings */
+ if (ippc->pt == PJMEDIA_RTP_PT_AMR || ippc->pt == PJMEDIA_RTP_PT_AMRWB) {
+ amr_settings_t *s;
+
+ s = PJ_POOL_ZALLOC_T(pool, amr_settings_t);
+ codec_data->codec_setting = s;
+
+ s->enc_mode = pjmedia_codec_amr_get_mode(ippc->def_bitrate);
+ if (s->enc_mode < 0)
+ goto on_error;
+
+ s->enc_setting.amr_nb = ippc->pt == PJMEDIA_RTP_PT_AMR;
+ s->enc_setting.octet_aligned = 0;
+ s->enc_setting.reorder = PJ_TRUE;
+ s->enc_setting.CMR = 15;
+
+ s->dec_setting.amr_nb = ippc->pt == PJMEDIA_RTP_PT_AMR;
+ s->dec_setting.octet_aligned = 0;
+ s->dec_setting.reorder = PJ_TRUE;
+ }
+#endif
+
return PJ_SUCCESS;
on_error:
@@ -1161,8 +1203,8 @@ static pj_status_t ipp_codec_encode( pjmedia_codec *codec,
}
#if PJMEDIA_HAS_INTEL_IPP_CODEC_AMR
- /* For AMR: put info (frametype, degraded, last frame) in the
- * first byte
+ /* For AMR: put info (frametype, degraded, last frame, mode) in the
+ * first two octets for payload packing.
*/
if (pt == PJMEDIA_RTP_PT_AMR || pt == PJMEDIA_RTP_PT_AMRWB) {
pj_uint16_t *info = (pj_uint16_t*)bits_out;