summaryrefslogtreecommitdiff
path: root/pjmedia
diff options
context:
space:
mode:
authorNanang Izzuddin <nanang@teluu.com>2009-07-15 17:55:16 +0000
committerNanang Izzuddin <nanang@teluu.com>2009-07-15 17:55:16 +0000
commitc7b0bd5a2320cc342474e5713adb00f92532aa23 (patch)
tree7bc8fc89542dd5b2bbe0f6e53071b62b2c03ec06 /pjmedia
parentbbc250ce57fcd09e4b894fc0d706a8079ee5f4dc (diff)
Ticket #919:
- Added default ilbc mode into codec passthrough setting. - Added iLBC mode 'negotiation' in iLBC codec_open(). - Updated stream_create() to prioritize codec_open(), that may update the codec params, over stream initializations involving codec params. git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@2834 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjmedia')
-rw-r--r--pjmedia/include/pjmedia-codec/passthrough.h1
-rw-r--r--pjmedia/src/pjmedia-codec/ilbc.c49
-rw-r--r--pjmedia/src/pjmedia-codec/passthrough.c97
-rw-r--r--pjmedia/src/pjmedia/stream.c36
4 files changed, 129 insertions, 54 deletions
diff --git a/pjmedia/include/pjmedia-codec/passthrough.h b/pjmedia/include/pjmedia-codec/passthrough.h
index 7b237c3c..c4f94a91 100644
--- a/pjmedia/include/pjmedia-codec/passthrough.h
+++ b/pjmedia/include/pjmedia-codec/passthrough.h
@@ -58,6 +58,7 @@ typedef struct pjmedia_codec_passthrough_setting
to be enabled. */
pjmedia_format *fmts; /**< Encoding formats to be
enabled. */
+ unsigned ilbc_mode; /**< iLBC default mode. */
} pjmedia_codec_passthrough_setting;
diff --git a/pjmedia/src/pjmedia-codec/ilbc.c b/pjmedia/src/pjmedia-codec/ilbc.c
index c60d4285..1c7fd1fe 100644
--- a/pjmedia/src/pjmedia-codec/ilbc.c
+++ b/pjmedia/src/pjmedia-codec/ilbc.c
@@ -376,7 +376,9 @@ static pj_status_t ilbc_codec_open(pjmedia_codec *codec,
{
struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)codec;
pj_status_t status;
- unsigned i, dec_fmtp_mode = 0, enc_fmtp_mode = 0;
+ unsigned i;
+ pj_uint16_t dec_fmtp_mode = DEFAULT_MODE,
+ enc_fmtp_mode = DEFAULT_MODE;
pj_assert(ilbc_codec != NULL);
pj_assert(ilbc_codec->enc_ready == PJ_FALSE &&
@@ -386,7 +388,7 @@ static pj_status_t ilbc_codec_open(pjmedia_codec *codec,
for (i = 0; i < attr->setting.dec_fmtp.cnt; ++i) {
if (pj_stricmp(&attr->setting.dec_fmtp.param[i].name, &STR_MODE) == 0)
{
- dec_fmtp_mode = (unsigned)
+ dec_fmtp_mode = (pj_uint16_t)
pj_strtoul(&attr->setting.dec_fmtp.param[i].val);
break;
}
@@ -400,30 +402,31 @@ static pj_status_t ilbc_codec_open(pjmedia_codec *codec,
for (i = 0; i < attr->setting.enc_fmtp.cnt; ++i) {
if (pj_stricmp(&attr->setting.enc_fmtp.param[i].name, &STR_MODE) == 0)
{
- enc_fmtp_mode = (unsigned)
+ enc_fmtp_mode = (pj_uint16_t)
pj_strtoul(&attr->setting.enc_fmtp.param[i].val);
break;
}
}
- /* The enc mode must be set in the attribute
- * (from the mode parameter in fmtp attribute in the SDP
- * received from remote)
- */
- if (enc_fmtp_mode == 0)
- enc_fmtp_mode = dec_fmtp_mode;
-
- PJ_ASSERT_RETURN(enc_fmtp_mode==20 ||
- enc_fmtp_mode==30, PJMEDIA_CODEC_EINMODE);
+ PJ_ASSERT_RETURN(enc_fmtp_mode==20 || enc_fmtp_mode==30,
+ PJMEDIA_CODEC_EINMODE);
- /* Update enc_ptime in the param */
+ /* Both sides of a bi-directional session MUST use the same "mode" value.
+ * In this point, possible values are only 20 or 30, so when encoder and
+ * decoder modes are not same, just use the default mode, it is 30.
+ */
if (enc_fmtp_mode != dec_fmtp_mode) {
- attr->info.enc_ptime = (pj_uint16_t)enc_fmtp_mode;
- } else {
- attr->info.enc_ptime = 0;
+ enc_fmtp_mode = dec_fmtp_mode = DEFAULT_MODE;
+ PJ_LOG(4,(ilbc_codec->obj_name,
+ "Normalized iLBC encoder and decoder modes to %d",
+ DEFAULT_MODE));
}
- /* Create enc */
+ /* Update some attributes based on negotiated mode. */
+ attr->info.avg_bps = (dec_fmtp_mode == 30? 13333 : 15200);
+ attr->info.frm_ptime = dec_fmtp_mode;
+
+ /* Create encoder */
ilbc_codec->enc_frame_size = initEncode(&ilbc_codec->enc, enc_fmtp_mode);
ilbc_codec->enc_samples_per_frame = CLOCK_RATE * enc_fmtp_mode / 1000;
ilbc_codec->enc_ready = PJ_TRUE;
@@ -432,14 +435,7 @@ static pj_status_t ilbc_codec_open(pjmedia_codec *codec,
ilbc_codec->dec_samples_per_frame = initDecode(&ilbc_codec->dec,
dec_fmtp_mode,
attr->setting.penh);
- if (dec_fmtp_mode == 20)
- ilbc_codec->dec_frame_size = 38;
- else if (dec_fmtp_mode == 30)
- ilbc_codec->dec_frame_size = 50;
- else {
- pj_assert(!"Invalid iLBC mode");
- ilbc_codec->dec_frame_size = ilbc_codec->enc_frame_size;
- }
+ ilbc_codec->dec_frame_size = (dec_fmtp_mode == 20? 38 : 50);
ilbc_codec->dec_ready = PJ_TRUE;
/* Save plc flags */
@@ -459,8 +455,7 @@ static pj_status_t ilbc_codec_open(pjmedia_codec *codec,
pj_set_timestamp32(&ilbc_codec->last_tx, 0, 0);
PJ_LOG(5,(ilbc_codec->obj_name,
- "iLBC codec opened, encoder mode=%d, decoder mode=%d",
- enc_fmtp_mode, dec_fmtp_mode));
+ "iLBC codec opened, mode=%d", dec_fmtp_mode));
return PJ_SUCCESS;
}
diff --git a/pjmedia/src/pjmedia-codec/passthrough.c b/pjmedia/src/pjmedia-codec/passthrough.c
index e1572f48..c96e921d 100644
--- a/pjmedia/src/pjmedia-codec/passthrough.c
+++ b/pjmedia/src/pjmedia-codec/passthrough.c
@@ -114,6 +114,10 @@ typedef struct codec_private {
int codec_idx; /**< Codec index. */
void *codec_setting; /**< Specific codec setting. */
pj_uint16_t avg_frame_size; /**< Average of frame size. */
+ unsigned samples_per_frame; /**< Samples per frame, for iLBC
+ this can be 240 or 160, can
+ only be known after codec is
+ opened. */
} codec_private_t;
@@ -380,6 +384,23 @@ PJ_DEF(pj_status_t) pjmedia_codec_passthrough_init2(
codec_desc[i].enabled = enabled;
}
+
+#if PJMEDIA_HAS_PASSTHROUGH_CODEC_ILBC
+ /* Update iLBC codec description based on default mode setting. */
+ for (i = 0; i < PJ_ARRAY_SIZE(codec_desc); ++i) {
+ if (codec_desc[i].enabled &&
+ codec_desc[i].fmt_id == PJMEDIA_FORMAT_ILBC)
+ {
+ codec_desc[i].samples_per_frame =
+ (setting->ilbc_mode == 20? 160 : 240);
+ codec_desc[i].def_bitrate =
+ (setting->ilbc_mode == 20? 15200 : 13333);
+ pj_strset2(&codec_desc[i].dec_fmtp.param[0].val,
+ (setting->ilbc_mode == 20? "20" : "30"));
+ break;
+ }
+ }
+#endif
}
return pjmedia_codec_passthrough_init(endpt);
@@ -645,8 +666,11 @@ static pj_status_t codec_open( pjmedia_codec *codec,
pool = codec_data->pool;
- /* Get bitstream size */
- i = attr->info.avg_bps * desc->samples_per_frame;
+ /* Cache samples per frame value */
+ codec_data->samples_per_frame = desc->samples_per_frame;
+
+ /* Calculate bitstream size */
+ i = attr->info.avg_bps * codec_data->samples_per_frame;
j = desc->clock_rate << 3;
codec_data->avg_frame_size = (pj_uint16_t)(i / j);
if (i % j) ++codec_data->avg_frame_size;
@@ -694,6 +718,63 @@ static pj_status_t codec_open( pjmedia_codec *codec,
}
#endif
+#if PJMEDIA_HAS_PASSTHROUGH_CODEC_ILBC
+ {
+ enum { DEFAULT_MODE = 30 };
+ static pj_str_t STR_MODE = {"mode", 4};
+ pj_uint16_t dec_fmtp_mode = DEFAULT_MODE,
+ enc_fmtp_mode = DEFAULT_MODE;
+
+ /* Get decoder mode */
+ for (i = 0; i < attr->setting.dec_fmtp.cnt; ++i) {
+ if (pj_stricmp(&attr->setting.dec_fmtp.param[i].name, &STR_MODE) == 0)
+ {
+ dec_fmtp_mode = (pj_uint16_t)
+ pj_strtoul(&attr->setting.dec_fmtp.param[i].val);
+ break;
+ }
+ }
+
+ /* Decoder mode must be set */
+ PJ_ASSERT_RETURN(dec_fmtp_mode == 20 || dec_fmtp_mode == 30,
+ PJMEDIA_CODEC_EINMODE);
+
+ /* Get encoder mode */
+ for (i = 0; i < attr->setting.enc_fmtp.cnt; ++i) {
+ if (pj_stricmp(&attr->setting.enc_fmtp.param[i].name, &STR_MODE) == 0)
+ {
+ enc_fmtp_mode = (pj_uint16_t)
+ pj_strtoul(&attr->setting.enc_fmtp.param[i].val);
+ break;
+ }
+ }
+
+ PJ_ASSERT_RETURN(enc_fmtp_mode==20 || enc_fmtp_mode==30,
+ PJMEDIA_CODEC_EINMODE);
+
+ /* Both sides of a bi-directional session MUST use the same "mode" value.
+ * In this point, possible values are only 20 or 30, so when encoder and
+ * decoder modes are not same, just use the default mode, it is 30.
+ */
+ if (enc_fmtp_mode != dec_fmtp_mode) {
+ enc_fmtp_mode = dec_fmtp_mode = DEFAULT_MODE;
+ PJ_LOG(4,(pool->obj_name,
+ "Normalized iLBC encoder and decoder modes to %d",
+ DEFAULT_MODE));
+ }
+
+ /* Update some attributes based on negotiated mode. */
+ attr->info.avg_bps = (dec_fmtp_mode == 30? 13333 : 15200);
+ attr->info.frm_ptime = dec_fmtp_mode;
+
+ /* Override average frame size */
+ codec_data->avg_frame_size = (dec_fmtp_mode == 30? 50 : 38);
+
+ /* Override samples per frame */
+ codec_data->samples_per_frame = (dec_fmtp_mode == 30? 240 : 160);
+ }
+#endif
+
return PJ_SUCCESS;
}
@@ -745,7 +826,8 @@ static pj_status_t codec_parse( pjmedia_codec *codec,
frames[count].type = PJMEDIA_FRAME_TYPE_AUDIO;
frames[count].buf = pkt;
frames[count].size = codec_data->avg_frame_size;
- frames[count].timestamp.u64 = ts->u64 + count*desc->samples_per_frame;
+ frames[count].timestamp.u64 = ts->u64 +
+ count * codec_data->samples_per_frame;
pkt = (pj_uint8_t*)pkt + codec_data->avg_frame_size;
pkt_size -= codec_data->avg_frame_size;
@@ -757,7 +839,8 @@ static pj_status_t codec_parse( pjmedia_codec *codec,
frames[count].type = PJMEDIA_FRAME_TYPE_AUDIO;
frames[count].buf = pkt;
frames[count].size = pkt_size;
- frames[count].timestamp.u64 = ts->u64 + count*desc->samples_per_frame;
+ frames[count].timestamp.u64 = ts->u64 +
+ count * codec_data->samples_per_frame;
++count;
}
@@ -854,7 +937,7 @@ static pj_status_t codec_decode( pjmedia_codec *codec,
pjmedia_frame_ext_append_subframe(output_, input_.buf,
(pj_uint16_t)(input_.size << 3),
- (pj_uint16_t)desc->samples_per_frame);
+ (pj_uint16_t)codec_data->samples_per_frame);
output->timestamp = input->timestamp;
return PJ_SUCCESS;
@@ -863,7 +946,7 @@ static pj_status_t codec_decode( pjmedia_codec *codec,
pjmedia_frame_ext_append_subframe(output_, input->buf,
(pj_uint16_t)(input->size << 3),
- (pj_uint16_t)desc->samples_per_frame);
+ (pj_uint16_t)codec_data->samples_per_frame);
output->timestamp = input->timestamp;
return PJ_SUCCESS;
@@ -883,7 +966,7 @@ static pj_status_t codec_recover( pjmedia_codec *codec,
PJ_UNUSED_ARG(output_buf_len);
pjmedia_frame_ext_append_subframe(output_, NULL, 0,
- (pj_uint16_t)desc->samples_per_frame);
+ (pj_uint16_t)codec_data->samples_per_frame);
return PJ_SUCCESS;
}
diff --git a/pjmedia/src/pjmedia/stream.c b/pjmedia/src/pjmedia/stream.c
index d103979a..35b6dc90 100644
--- a/pjmedia/src/pjmedia/stream.c
+++ b/pjmedia/src/pjmedia/stream.c
@@ -1673,20 +1673,6 @@ PJ_DEF(pj_status_t) pjmedia_stream_create( pjmedia_endpt *endpt,
stream->port.info.clock_rate = info->fmt.clock_rate;
stream->port.info.channel_count = info->fmt.channel_cnt;
stream->port.port_data.pdata = stream;
- if (info->param==NULL || info->param->info.fmt_id == PJMEDIA_FORMAT_L16) {
- stream->port.info.format.id = PJMEDIA_FORMAT_L16;
-
- stream->port.put_frame = &put_frame;
- stream->port.get_frame = &get_frame;
- } else {
- stream->port.info.format.id = info->param->info.fmt_id;
- stream->port.info.format.bitrate = info->param->info.avg_bps;
- stream->port.info.format.vad = (info->param->setting.vad != 0);
-
- stream->port.put_frame = &put_frame;
- stream->port.get_frame = &get_frame_ext;
- }
-
/* Init stream: */
stream->endpt = endpt;
@@ -1745,7 +1731,12 @@ PJ_DEF(pj_status_t) pjmedia_stream_create( pjmedia_endpt *endpt,
if (stream->codec_param.setting.frm_per_pkt < 1)
stream->codec_param.setting.frm_per_pkt = 1;
- /* Set additional info. */
+ /* Open the codec. */
+ status = stream->codec->op->open(stream->codec, &stream->codec_param);
+ if (status != PJ_SUCCESS)
+ goto err_cleanup;
+
+ /* Set additional info and callbacks. */
stream->port.info.bits_per_sample = 16;
stream->port.info.samples_per_frame = info->fmt.clock_rate *
stream->codec_param.info.channel_cnt *
@@ -1762,11 +1753,16 @@ PJ_DEF(pj_status_t) pjmedia_stream_create( pjmedia_endpt *endpt,
++stream->port.info.bytes_per_frame;
}
- /* Open the codec: */
-
- status = stream->codec->op->open(stream->codec, &stream->codec_param);
- if (status != PJ_SUCCESS)
- goto err_cleanup;
+ stream->port.info.format.id = stream->codec_param.info.fmt_id;
+ if (stream->codec_param.info.fmt_id == PJMEDIA_FORMAT_L16) {
+ stream->port.put_frame = &put_frame;
+ stream->port.get_frame = &get_frame;
+ } else {
+ stream->port.info.format.bitrate = stream->codec_param.info.avg_bps;
+ stream->port.info.format.vad = (stream->codec_param.setting.vad != 0);
+ stream->port.put_frame = &put_frame;
+ stream->port.get_frame = &get_frame_ext;
+ }
/* If encoder and decoder's ptime are asymmetric, then we need to
* create buffer on the encoder side. This could happen for example