diff options
-rw-r--r-- | pjmedia/include/pjmedia-codec/amr_helper.h | 97 | ||||
-rw-r--r-- | pjmedia/src/pjmedia-codec/ipp_codecs.c | 90 |
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; |