summaryrefslogtreecommitdiff
path: root/pjmedia
diff options
context:
space:
mode:
authorNanang Izzuddin <nanang@teluu.com>2010-06-11 13:38:42 +0000
committerNanang Izzuddin <nanang@teluu.com>2010-06-11 13:38:42 +0000
commit478d7fed9b2d5713500c91dd296356b7ea939502 (patch)
tree8e2b057e5f4838a51e5ab954cf3e683f830ebb69 /pjmedia
parentf58cd5dab31fb33928ff092f534b4145873c8dad (diff)
Close #1072:
- Added API pjmedia_codec_g722_set_pcm_shift() to enable configurable level-adjusment setting. - Also added macro PJMEDIA_G722_DEFAULT_PCM_SHIFT (default value is 2) to accomplish 14-16 bit PCM conversion for G722 input/output. - Added a feature in G722 to stop level-adjusment/PCM-shifting when clipping occured, compile-time configurable via PJMEDIA_G722_STOP_PCM_SHIFT_ON_CLIPPING macro. git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@3202 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjmedia')
-rw-r--r--pjmedia/include/pjmedia-codec/config.h34
-rw-r--r--pjmedia/include/pjmedia-codec/g722.h15
-rw-r--r--pjmedia/src/pjmedia-codec/g722.c48
-rw-r--r--pjmedia/src/pjmedia-codec/g722/g722_dec.c5
-rw-r--r--pjmedia/src/pjmedia-codec/g722/g722_enc.c2
5 files changed, 99 insertions, 5 deletions
diff --git a/pjmedia/include/pjmedia-codec/config.h b/pjmedia/include/pjmedia-codec/config.h
index 79322bb2..3dbb5c56 100644
--- a/pjmedia/include/pjmedia-codec/config.h
+++ b/pjmedia/include/pjmedia-codec/config.h
@@ -98,6 +98,40 @@
/**
+ * Default G.722 codec encoder and decoder level adjustment. The G.722
+ * specifies that it uses 14 bit PCM for input and output, while PJMEDIA
+ * normally uses 16 bit PCM, so the conversion is done by applying
+ * level adjustment. If the value is non-zero, then PCM input samples to
+ * the encoder will be shifted right by this value, and similarly PCM
+ * output samples from the decoder will be shifted left by this value.
+ *
+ * This can be changed at run-time after initialization by calling
+ * #pjmedia_codec_g722_set_pcm_shift().
+ *
+ * Default: 2.
+ */
+#ifndef PJMEDIA_G722_DEFAULT_PCM_SHIFT
+# define PJMEDIA_G722_DEFAULT_PCM_SHIFT 2
+#endif
+
+
+/**
+ * Specifies whether G.722 PCM shifting should be stopped when clipping
+ * detected in the decoder. Enabling this feature can be useful when
+ * talking to G.722 implementation that uses 16 bit PCM for G.722 input/
+ * output (for any reason it seems to work) and the PCM shifting causes
+ * audio clipping.
+ *
+ * See also #PJMEDIA_G722_DEFAULT_PCM_SHIFT.
+ *
+ * Default: enabled.
+ */
+#ifndef PJMEDIA_G722_STOP_PCM_SHIFT_ON_CLIPPING
+# define PJMEDIA_G722_STOP_PCM_SHIFT_ON_CLIPPING 1
+#endif
+
+
+/**
* Enable the features provided by Intel IPP libraries, for example
* codecs such as G.729, G.723.1, G.726, G.728, G.722.1, and AMR.
*
diff --git a/pjmedia/include/pjmedia-codec/g722.h b/pjmedia/include/pjmedia-codec/g722.h
index 71a5bb5b..594d5a5e 100644
--- a/pjmedia/include/pjmedia-codec/g722.h
+++ b/pjmedia/include/pjmedia-codec/g722.h
@@ -78,6 +78,21 @@ PJ_DECL(pj_status_t) pjmedia_codec_g722_init(pjmedia_endpt *endpt);
PJ_DECL(pj_status_t) pjmedia_codec_g722_deinit(void);
+/**
+ * Set the G.722 codec encoder and decoder level adjustment.
+ * If the value is non-zero, then PCM input samples to the encoder will
+ * be shifted right by this value, and similarly PCM output samples from
+ * the decoder will be shifted left by this value.
+ *
+ * Default value is PJMEDIA_G722_DEFAULT_PCM_SHIFT.
+ *
+ * @param val The value
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_codec_g722_set_pcm_shift(unsigned val);
+
+
PJ_END_DECL
diff --git a/pjmedia/src/pjmedia-codec/g722.c b/pjmedia/src/pjmedia-codec/g722.c
index 04135f6c..842612c9 100644
--- a/pjmedia/src/pjmedia-codec/g722.c
+++ b/pjmedia/src/pjmedia-codec/g722.c
@@ -133,6 +133,7 @@ static struct g722_codec_factory
pj_pool_t *pool;
pj_mutex_t *mutex;
pjmedia_codec codec_list;
+ unsigned pcm_shift;
} g722_codec_factory;
@@ -141,6 +142,8 @@ struct g722_data
{
g722_enc_t encoder;
g722_dec_t decoder;
+ unsigned pcm_shift;
+ pj_int16_t pcm_clip_mask;
pj_bool_t plc_enabled;
pj_bool_t vad_enabled;
pjmedia_silence_det *vad;
@@ -167,6 +170,7 @@ PJ_DEF(pj_status_t) pjmedia_codec_g722_init( pjmedia_endpt *endpt )
g722_codec_factory.base.op = &g722_factory_op;
g722_codec_factory.base.factory_data = NULL;
g722_codec_factory.endpt = endpt;
+ g722_codec_factory.pcm_shift = PJMEDIA_G722_DEFAULT_PCM_SHIFT;
g722_codec_factory.pool = pjmedia_endpt_create_pool(endpt, "g722", 1000,
1000);
@@ -240,6 +244,17 @@ PJ_DEF(pj_status_t) pjmedia_codec_g722_deinit(void)
return status;
}
+
+/*
+ * Set level adjustment.
+ */
+PJ_DEF(pj_status_t) pjmedia_codec_g722_set_pcm_shift(unsigned val)
+{
+ g722_codec_factory.pcm_shift = val;
+ return PJ_SUCCESS;
+}
+
+
/*
* Check if factory can allocate the specified codec.
*/
@@ -446,6 +461,9 @@ static pj_status_t g722_codec_open(pjmedia_codec *codec,
g722_data->vad_enabled = (attr->setting.vad != 0);
g722_data->plc_enabled = (attr->setting.plc != 0);
+ g722_data->pcm_shift = g722_codec_factory.pcm_shift;
+ g722_data->pcm_clip_mask = (pj_int16_t)(1<<g722_codec_factory.pcm_shift)-1;
+ g722_data->pcm_clip_mask <<= (16-g722_codec_factory.pcm_shift);
TRACE_((THIS_FILE, "G722 codec opened: vad=%d, plc=%d",
g722_data->vad_enabled, g722_data->plc_enabled));
@@ -565,6 +583,17 @@ static pj_status_t g722_codec_encode(pjmedia_codec *codec,
}
}
+ /* Adjust input signal level from 16-bit to 14-bit */
+ if (g722_data->pcm_shift) {
+ pj_int16_t *p, *end;
+
+ p = (pj_int16_t*)input->buf;
+ end = p + input->size;
+ while (p < end) {
+ *p++ >>= g722_data->pcm_shift;
+ }
+ }
+
/* Encode to temporary buffer */
output->size = output_buf_len;
status = g722_enc_encode(&g722_data->encoder, (pj_int16_t*)input->buf,
@@ -623,6 +652,25 @@ static pj_status_t g722_codec_decode(pjmedia_codec *codec,
}
pj_assert(output->size == SAMPLES_PER_FRAME);
+
+ /* Adjust input signal level from 14-bit to 16-bit */
+ if (g722_data->pcm_shift) {
+ pj_int16_t *p, *end;
+
+ p = (pj_int16_t*)output->buf;
+ end = p + output->size;
+ while (p < end) {
+#if PJMEDIA_G722_STOP_PCM_SHIFT_ON_CLIPPING
+ /* If there is clipping, stop the PCM shifting */
+ if (*p & g722_data->pcm_clip_mask) {
+ g722_data->pcm_shift = 0;
+ break;
+ }
+#endif
+ *p++ <<= g722_data->pcm_shift;
+ }
+ }
+
output->size = SAMPLES_PER_FRAME * 2;
output->type = PJMEDIA_FRAME_TYPE_AUDIO;
output->timestamp = input->timestamp;
diff --git a/pjmedia/src/pjmedia-codec/g722/g722_dec.c b/pjmedia/src/pjmedia-codec/g722/g722_dec.c
index 887fcb93..1579d06e 100644
--- a/pjmedia/src/pjmedia-codec/g722/g722_dec.c
+++ b/pjmedia/src/pjmedia-codec/g722/g722_dec.c
@@ -504,7 +504,6 @@ PJ_DEF(pj_status_t) g722_dec_decode( g722_dec_t *dec,
unsigned i;
int ilowr, ylow, rlow, dlowt;
int ihigh, rhigh, dhigh;
- int pcm1, pcm2;
pj_uint8_t *in_ = (pj_uint8_t*) in;
PJ_ASSERT_RETURN(dec && in && in_size && out && nsamples, PJ_EINVAL);
@@ -529,9 +528,7 @@ PJ_DEF(pj_status_t) g722_dec_decode( g722_dec_t *dec,
dec->shigh = block4h (dec, dhigh) ;
/* rhigh <= output high band pcm */
- rx_qmf(dec, rlow, rhigh, &pcm1, &pcm2);
- out[i*2] = (pj_int16_t)(pcm1 << 2);
- out[i*2+1] = (pj_int16_t)(pcm2 << 2);
+ rx_qmf(dec, rlow, rhigh, &out[i*2], &out[i*2+1]);
}
*nsamples = in_size << 1;
diff --git a/pjmedia/src/pjmedia-codec/g722/g722_enc.c b/pjmedia/src/pjmedia-codec/g722/g722_enc.c
index b4ca63ce..d4b5ab87 100644
--- a/pjmedia/src/pjmedia-codec/g722/g722_enc.c
+++ b/pjmedia/src/pjmedia-codec/g722/g722_enc.c
@@ -543,7 +543,7 @@ PJ_DEF(pj_status_t) g722_enc_encode( g722_enc_t *enc,
PJ_ASSERT_RETURN(*out_size >= (nsamples >> 1), PJ_ETOOSMALL);
for(i = 0; i < nsamples; i += 2) {
- tx_qmf(enc, in[i]>>2, in[i+1]>>2, &xlow, &xhigh);
+ tx_qmf(enc, in[i], in[i+1], &xlow, &xhigh);
/* low band encoder */
ilow = block1l (xlow, enc->slow, enc->detlow) ;