summaryrefslogtreecommitdiff
path: root/pjmedia/src/pjmedia
diff options
context:
space:
mode:
Diffstat (limited to 'pjmedia/src/pjmedia')
-rw-r--r--pjmedia/src/pjmedia/codec.c52
-rw-r--r--pjmedia/src/pjmedia/conference.c6
-rw-r--r--pjmedia/src/pjmedia/converter.c4
-rw-r--r--pjmedia/src/pjmedia/endpoint.c10
-rw-r--r--pjmedia/src/pjmedia/g711.c7
-rw-r--r--pjmedia/src/pjmedia/jbuf.c9
-rw-r--r--pjmedia/src/pjmedia/rtcp.c5
-rw-r--r--pjmedia/src/pjmedia/rtp.c4
-rw-r--r--pjmedia/src/pjmedia/sdp.c14
-rw-r--r--pjmedia/src/pjmedia/sdp_neg.c4
-rw-r--r--pjmedia/src/pjmedia/stream.c104
-rw-r--r--pjmedia/src/pjmedia/transport_ice.c8
-rw-r--r--pjmedia/src/pjmedia/transport_srtp.c69
-rw-r--r--pjmedia/src/pjmedia/transport_udp.c8
-rw-r--r--pjmedia/src/pjmedia/types.c6
-rw-r--r--pjmedia/src/pjmedia/vid_codec_util.c290
-rw-r--r--pjmedia/src/pjmedia/vid_port.c13
-rw-r--r--pjmedia/src/pjmedia/vid_stream.c21
-rw-r--r--pjmedia/src/pjmedia/vid_stream_info.c5
19 files changed, 447 insertions, 192 deletions
diff --git a/pjmedia/src/pjmedia/codec.c b/pjmedia/src/pjmedia/codec.c
index db8cad2..5107c8c 100644
--- a/pjmedia/src/pjmedia/codec.c
+++ b/pjmedia/src/pjmedia/codec.c
@@ -1,4 +1,4 @@
-/* $Id: codec.c 3664 2011-07-19 03:42:28Z nanang $ */
+/* $Id: codec.c 4254 2012-09-14 04:06:29Z nanang $ */
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
@@ -41,6 +41,39 @@ static void sort_codecs(pjmedia_codec_mgr *mgr);
/*
+ * Duplicate codec parameter.
+ */
+PJ_DEF(pjmedia_codec_param*) pjmedia_codec_param_clone(
+ pj_pool_t *pool,
+ const pjmedia_codec_param *src)
+{
+ pjmedia_codec_param *p;
+ unsigned i;
+
+ PJ_ASSERT_RETURN(pool && src, NULL);
+
+ p = PJ_POOL_ZALLOC_T(pool, pjmedia_codec_param);
+
+ /* Update codec param */
+ pj_memcpy(p, src, sizeof(pjmedia_codec_param));
+ for (i = 0; i < src->setting.dec_fmtp.cnt; ++i) {
+ pj_strdup(pool, &p->setting.dec_fmtp.param[i].name,
+ &src->setting.dec_fmtp.param[i].name);
+ pj_strdup(pool, &p->setting.dec_fmtp.param[i].val,
+ &src->setting.dec_fmtp.param[i].val);
+ }
+ for (i = 0; i < src->setting.enc_fmtp.cnt; ++i) {
+ pj_strdup(pool, &p->setting.enc_fmtp.param[i].name,
+ &src->setting.enc_fmtp.param[i].name);
+ pj_strdup(pool, &p->setting.enc_fmtp.param[i].val,
+ &src->setting.enc_fmtp.param[i].val);
+ }
+
+ return p;
+}
+
+
+/*
* Initialize codec manager.
*/
PJ_DEF(pj_status_t) pjmedia_codec_mgr_init (pjmedia_codec_mgr *mgr,
@@ -600,22 +633,11 @@ PJ_DEF(pj_status_t) pjmedia_codec_mgr_set_default_param(
codec_desc->param = PJ_POOL_ZALLOC_T(pool, pjmedia_codec_default_param);
p = codec_desc->param;
p->pool = pool;
- p->param = PJ_POOL_ZALLOC_T(pool, pjmedia_codec_param);
/* Update codec param */
- pj_memcpy(p->param, param, sizeof(pjmedia_codec_param));
- for (i = 0; i < param->setting.dec_fmtp.cnt; ++i) {
- pj_strdup(pool, &p->param->setting.dec_fmtp.param[i].name,
- &param->setting.dec_fmtp.param[i].name);
- pj_strdup(pool, &p->param->setting.dec_fmtp.param[i].val,
- &param->setting.dec_fmtp.param[i].val);
- }
- for (i = 0; i < param->setting.enc_fmtp.cnt; ++i) {
- pj_strdup(pool, &p->param->setting.enc_fmtp.param[i].name,
- &param->setting.enc_fmtp.param[i].name);
- pj_strdup(pool, &p->param->setting.enc_fmtp.param[i].val,
- &param->setting.enc_fmtp.param[i].val);
- }
+ p->param = pjmedia_codec_param_clone(pool, param);
+ if (!p->param)
+ return PJ_EINVAL;
pj_mutex_unlock(mgr->mutex);
diff --git a/pjmedia/src/pjmedia/conference.c b/pjmedia/src/pjmedia/conference.c
index a08e7b0..391e4e3 100644
--- a/pjmedia/src/pjmedia/conference.c
+++ b/pjmedia/src/pjmedia/conference.c
@@ -1,4 +1,4 @@
-/* $Id: conference.c 4162 2012-06-11 04:17:54Z nanang $ */
+/* $Id: conference.c 4198 2012-07-05 10:25:46Z nanang $ */
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
@@ -1810,11 +1810,11 @@ static pj_status_t get_frame(pjmedia_port *this_port,
/* Var "ci" is to count how many ports have been visited so far. */
++ci;
- /* Reset buffer (only necessary if more than one transmitter) and
+ /* Reset buffer (only necessary if the port has transmitter) and
* reset auto adjustment level for mixed signal.
*/
conf_port->mix_adj = NORMAL_LEVEL;
- if (conf_port->transmitter_cnt > 1) {
+ if (conf_port->transmitter_cnt) {
pj_bzero(conf_port->mix_buf,
conf->samples_per_frame*sizeof(conf_port->mix_buf[0]));
}
diff --git a/pjmedia/src/pjmedia/converter.c b/pjmedia/src/pjmedia/converter.c
index 50fbcc8..19a8a8c 100644
--- a/pjmedia/src/pjmedia/converter.c
+++ b/pjmedia/src/pjmedia/converter.c
@@ -1,4 +1,4 @@
-/* $Id: converter.c 4087 2012-04-26 03:39:24Z ming $ */
+/* $Id: converter.c 4412 2013-03-05 03:12:32Z riza $ */
/*
* Copyright (C) 2010-2011 Teluu Inc. (http://www.teluu.com)
*
@@ -39,7 +39,9 @@ PJ_DEF(pj_status_t) pjmedia_converter_mgr_create(pj_pool_t *pool,
pjmedia_converter_mgr **p_mgr)
{
pjmedia_converter_mgr *mgr;
+#if PJMEDIA_HAS_LIBSWSCALE && PJMEDIA_HAS_LIBAVUTIL
pj_status_t status = PJ_SUCCESS;
+#endif
mgr = PJ_POOL_ALLOC_T(pool, pjmedia_converter_mgr);
pj_list_init(&mgr->factory_list);
diff --git a/pjmedia/src/pjmedia/endpoint.c b/pjmedia/src/pjmedia/endpoint.c
index e20a5a4..b61152e 100644
--- a/pjmedia/src/pjmedia/endpoint.c
+++ b/pjmedia/src/pjmedia/endpoint.c
@@ -1,4 +1,4 @@
-/* $Id: endpoint.c 3999 2012-03-30 07:10:13Z bennylp $ */
+/* $Id: endpoint.c 4240 2012-08-31 09:03:36Z ming $ */
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
@@ -49,6 +49,10 @@ static const pj_str_t STR_SENDRECV = { "sendrecv", 8 };
pj_bool_t pjmedia_add_rtpmap_for_static_pt =
PJMEDIA_ADD_RTPMAP_FOR_STATIC_PT;
+/* Config to control use of RFC3890 TIAS */
+pj_bool_t pjmedia_add_bandwidth_tias_in_sdp =
+ PJMEDIA_ADD_BANDWIDTH_TIAS_IN_SDP;
+
/* Worker thread proc. */
@@ -551,7 +555,7 @@ PJ_DEF(pj_status_t) pjmedia_endpt_create_audio_sdp(pjmedia_endpt *endpt,
/* Put bandwidth info in media level using bandwidth modifier "TIAS"
* (RFC3890).
*/
- if (max_bitrate) {
+ if (max_bitrate && pjmedia_add_bandwidth_tias_in_sdp) {
const pj_str_t STR_BANDW_MODIFIER = { "TIAS", 4 };
pjmedia_sdp_bandw *b;
@@ -715,7 +719,7 @@ PJ_DEF(pj_status_t) pjmedia_endpt_create_video_sdp(pjmedia_endpt *endpt,
/* Put bandwidth info in media level using bandwidth modifier "TIAS"
* (RFC3890).
*/
- if (max_bitrate) {
+ if (max_bitrate && pjmedia_add_bandwidth_tias_in_sdp) {
const pj_str_t STR_BANDW_MODIFIER = { "TIAS", 4 };
pjmedia_sdp_bandw *b;
diff --git a/pjmedia/src/pjmedia/g711.c b/pjmedia/src/pjmedia/g711.c
index 0a61a47..2e3ec7b 100644
--- a/pjmedia/src/pjmedia/g711.c
+++ b/pjmedia/src/pjmedia/g711.c
@@ -1,4 +1,4 @@
-/* $Id: g711.c 3664 2011-07-19 03:42:28Z nanang $ */
+/* $Id: g711.c 4266 2012-09-26 05:55:18Z nanang $ */
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
@@ -331,7 +331,8 @@ static pj_status_t g711_alloc_codec( pjmedia_codec_factory *factory,
#if !PLC_DISABLED
/* Create PLC, always with 10ms ptime */
- status = pjmedia_plc_create(g711_factory.pool, 8000, 80,
+ status = pjmedia_plc_create(g711_factory.pool, 8000,
+ SAMPLES_PER_FRAME,
0, &codec_priv->plc);
if (status != PJ_SUCCESS) {
pj_mutex_unlock(g711_factory.mutex);
@@ -341,7 +342,7 @@ static pj_status_t g711_alloc_codec( pjmedia_codec_factory *factory,
/* Create VAD */
status = pjmedia_silence_det_create(g711_factory.pool,
- 8000, 80,
+ 8000, SAMPLES_PER_FRAME,
&codec_priv->vad);
if (status != PJ_SUCCESS) {
pj_mutex_unlock(g711_factory.mutex);
diff --git a/pjmedia/src/pjmedia/jbuf.c b/pjmedia/src/pjmedia/jbuf.c
index 74f6469..8c54074 100644
--- a/pjmedia/src/pjmedia/jbuf.c
+++ b/pjmedia/src/pjmedia/jbuf.c
@@ -1,4 +1,4 @@
-/* $Id: jbuf.c 4100 2012-04-26 16:57:47Z nanang $ */
+/* $Id: jbuf.c 4369 2013-02-21 21:55:54Z bennylp $ */
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
@@ -167,7 +167,7 @@ struct pjmedia_jbuf
/* Enabling this would log the jitter buffer state about once per
* second.
*/
-#if 1
+#if 0
# define TRACE__(args) PJ_LOG(5,args)
#else
# define TRACE__(args)
@@ -599,6 +599,7 @@ PJ_DEF(pj_status_t) pjmedia_jbuf_set_fixed( pjmedia_jbuf *jb,
jb->jb_min_prefetch = jb->jb_max_prefetch =
jb->jb_prefetch = jb->jb_init_prefetch = prefetch;
+ pjmedia_jbuf_set_discard(jb, PJMEDIA_JB_DISCARD_NONE);
return PJ_SUCCESS;
}
@@ -724,6 +725,8 @@ static void jbuf_calculate_jitter(pjmedia_jbuf *jb)
jb->jb_prefetch = jb->jb_eff_level;
if (jb->jb_prefetch < jb->jb_min_prefetch)
jb->jb_prefetch = jb->jb_min_prefetch;
+ if (jb->jb_prefetch > jb->jb_max_prefetch)
+ jb->jb_prefetch = jb->jb_max_prefetch;
}
/* Reset history */
@@ -747,6 +750,8 @@ static void jbuf_calculate_jitter(pjmedia_jbuf *jb)
jb->jb_prefetch = jb->jb_eff_level;
if (jb->jb_prefetch > jb->jb_max_prefetch)
jb->jb_prefetch = jb->jb_max_prefetch;
+ if (jb->jb_prefetch < jb->jb_min_prefetch)
+ jb->jb_prefetch = jb->jb_min_prefetch;
}
jb->jb_stable_hist = 0;
diff --git a/pjmedia/src/pjmedia/rtcp.c b/pjmedia/src/pjmedia/rtcp.c
index f57797c..fbfae13 100644
--- a/pjmedia/src/pjmedia/rtcp.c
+++ b/pjmedia/src/pjmedia/rtcp.c
@@ -1,4 +1,4 @@
-/* $Id: rtcp.c 3999 2012-03-30 07:10:13Z bennylp $ */
+/* $Id: rtcp.c 4283 2012-10-12 06:19:32Z ming $ */
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
@@ -752,7 +752,8 @@ static void parse_rtcp_bye(pjmedia_rtcp_session *sess,
/* Check and get BYE reason */
if (size > 8) {
- reason.slen = *((pj_uint8_t*)pkt+8);
+ reason.slen = PJ_MIN(sizeof(sess->stat.peer_sdes_buf_),
+ *((pj_uint8_t*)pkt+8));
pj_memcpy(sess->stat.peer_sdes_buf_, ((pj_uint8_t*)pkt+9),
reason.slen);
reason.ptr = sess->stat.peer_sdes_buf_;
diff --git a/pjmedia/src/pjmedia/rtp.c b/pjmedia/src/pjmedia/rtp.c
index 7fe6f89..c9ea53c 100644
--- a/pjmedia/src/pjmedia/rtp.c
+++ b/pjmedia/src/pjmedia/rtp.c
@@ -1,4 +1,4 @@
-/* $Id: rtp.c 3553 2011-05-05 06:14:19Z nanang $ */
+/* $Id: rtp.c 4235 2012-08-24 03:15:42Z ming $ */
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
@@ -118,8 +118,6 @@ PJ_DEF(pj_status_t) pjmedia_rtp_encode_rtp( pjmedia_rtp_session *ses,
int payload_len, int ts_len,
const void **rtphdr, int *hdrlen )
{
- PJ_UNUSED_ARG(payload_len);
-
/* Update timestamp */
ses->out_hdr.ts = pj_htonl(pj_ntohl(ses->out_hdr.ts)+ts_len);
diff --git a/pjmedia/src/pjmedia/sdp.c b/pjmedia/src/pjmedia/sdp.c
index e54bfcf..c0d43d8 100644
--- a/pjmedia/src/pjmedia/sdp.c
+++ b/pjmedia/src/pjmedia/sdp.c
@@ -1,4 +1,4 @@
-/* $Id: sdp.c 3945 2012-01-27 09:12:59Z nanang $ */
+/* $Id: sdp.c 4367 2013-02-21 20:49:19Z nanang $ */
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
@@ -1423,6 +1423,14 @@ static pj_status_t validate_sdp_conn(const pjmedia_sdp_conn *c)
/* Validate SDP session descriptor. */
PJ_DEF(pj_status_t) pjmedia_sdp_validate(const pjmedia_sdp_session *sdp)
{
+ return pjmedia_sdp_validate2(sdp, PJ_TRUE);
+}
+
+
+/* Validate SDP session descriptor. */
+PJ_DEF(pj_status_t) pjmedia_sdp_validate2(const pjmedia_sdp_session *sdp,
+ pj_bool_t strict)
+{
unsigned i;
const pj_str_t STR_RTPMAP = { "rtpmap", 6 };
@@ -1471,7 +1479,8 @@ PJ_DEF(pj_status_t) pjmedia_sdp_validate(const pjmedia_sdp_session *sdp)
*/
if (m->conn == NULL) {
if (sdp->conn == NULL)
- return PJMEDIA_SDP_EMISSINGCONN;
+ if (strict || m->desc.port != 0)
+ return PJMEDIA_SDP_EMISSINGCONN;
}
/* Verify payload type. */
@@ -1505,6 +1514,7 @@ PJ_DEF(pj_status_t) pjmedia_sdp_validate(const pjmedia_sdp_session *sdp)
return PJ_SUCCESS;
}
+
PJ_DEF(pj_status_t) pjmedia_sdp_transport_cmp( const pj_str_t *t1,
const pj_str_t *t2)
{
diff --git a/pjmedia/src/pjmedia/sdp_neg.c b/pjmedia/src/pjmedia/sdp_neg.c
index bdce18d..61e6d93 100644
--- a/pjmedia/src/pjmedia/sdp_neg.c
+++ b/pjmedia/src/pjmedia/sdp_neg.c
@@ -1,4 +1,4 @@
-/* $Id: sdp_neg.c 3980 2012-03-20 09:23:20Z ming $ */
+/* $Id: sdp_neg.c 4367 2013-02-21 20:49:19Z nanang $ */
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
@@ -138,7 +138,7 @@ PJ_DEF(pj_status_t) pjmedia_sdp_neg_create_w_remote_offer(pj_pool_t *pool,
*p_neg = NULL;
/* Validate remote offer and initial answer */
- status = pjmedia_sdp_validate(remote);
+ status = pjmedia_sdp_validate2(remote, PJ_FALSE);
if (status != PJ_SUCCESS)
return status;
diff --git a/pjmedia/src/pjmedia/stream.c b/pjmedia/src/pjmedia/stream.c
index 5c7c873..840b06c 100644
--- a/pjmedia/src/pjmedia/stream.c
+++ b/pjmedia/src/pjmedia/stream.c
@@ -1,4 +1,4 @@
-/* $Id: stream.c 4120 2012-05-12 07:18:09Z ming $ */
+/* $Id: stream.c 4336 2013-01-29 08:15:02Z ming $ */
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
@@ -73,6 +73,8 @@
# define PJMEDIA_STREAM_INC 1000
#endif
+/* Number of DTMF E bit transmissions */
+#define DTMF_EBIT_RETRANSMIT_CNT 3
/**
* Media channel.
@@ -94,6 +96,7 @@ struct dtmf
{
int event;
pj_uint32_t duration;
+ int ebit_cnt; /**< # of E bit transmissions */
};
/**
@@ -876,7 +879,7 @@ static pj_status_t get_frame_ext( pjmedia_port *port, pjmedia_frame *frame)
*/
static void create_dtmf_payload(pjmedia_stream *stream,
struct pjmedia_frame *frame_out,
- int *first, int *last)
+ int forced_last, int *first, int *last)
{
pjmedia_rtp_dtmf_event *event;
struct dtmf *digit = &stream->tx_dtmf_buf[0];
@@ -896,25 +899,33 @@ static void create_dtmf_payload(pjmedia_stream *stream,
}
digit->duration += PJMEDIA_PIA_SPF(&stream->port.info);
+ if (digit->duration >= PJMEDIA_DTMF_DURATION)
+ digit->duration = PJMEDIA_DTMF_DURATION;
event->event = (pj_uint8_t)digit->event;
event->e_vol = 10;
event->duration = pj_htons((pj_uint16_t)digit->duration);
+ if (forced_last) {
+ digit->duration = PJMEDIA_DTMF_DURATION;
+ }
if (digit->duration >= PJMEDIA_DTMF_DURATION) {
event->e_vol |= 0x80;
- *last = 1;
- /* Prepare next digit. */
- pj_mutex_lock(stream->jb_mutex);
+ if (++digit->ebit_cnt >= DTMF_EBIT_RETRANSMIT_CNT) {
+ *last = 1;
- pj_array_erase(stream->tx_dtmf_buf, sizeof(stream->tx_dtmf_buf[0]),
- stream->tx_dtmf_count, 0);
- --stream->tx_dtmf_count;
+ /* Prepare next digit. */
+ pj_mutex_lock(stream->jb_mutex);
- pj_mutex_unlock(stream->jb_mutex);
+ pj_array_erase(stream->tx_dtmf_buf, sizeof(stream->tx_dtmf_buf[0]),
+ stream->tx_dtmf_count, 0);
+ --stream->tx_dtmf_count;
+
+ pj_mutex_unlock(stream->jb_mutex);
+ }
}
frame_out->size = 4;
@@ -1217,7 +1228,7 @@ static pj_status_t put_frame_imp( pjmedia_port *port,
if (stream->tx_dtmf_count) {
int first=0, last=0;
- create_dtmf_payload(stream, &frame_out, &first, &last);
+ create_dtmf_payload(stream, &frame_out, 0, &first, &last);
/* Encapsulate into RTP packet. Note that:
* - RTP marker should be set on the beginning of a new event
@@ -1235,7 +1246,9 @@ static pj_status_t put_frame_imp( pjmedia_port *port,
* Increment the RTP timestamp of the RTP session, for next
* RTP packets.
*/
- inc_timestamp = PJMEDIA_DTMF_DURATION - rtp_ts_len;
+ inc_timestamp = PJMEDIA_DTMF_DURATION +
+ ((DTMF_EBIT_RETRANSMIT_CNT-1) * samples_per_frame)
+ - rtp_ts_len;
}
@@ -1765,7 +1778,11 @@ static void on_rx_rtp( void *data,
peer_frm_ts_diff == (frm_ts_span>>1)))
{
if (peer_frm_ts_diff < stream->rtp_rx_ts_len_per_frame)
+ {
stream->rtp_rx_ts_len_per_frame = peer_frm_ts_diff;
+ /* Done, stop the check immediately */
+ stream->rtp_rx_check_cnt = 1;
+ }
if (--stream->rtp_rx_check_cnt == 0) {
PJ_LOG(4, (THIS_FILE, "G722 codec used, remote"
@@ -1985,6 +2002,8 @@ PJ_DEF(pj_status_t) pjmedia_stream_create( pjmedia_endpt *endpt,
PJ_ASSERT_RETURN(stream != NULL, PJ_ENOMEM);
stream->own_pool = own_pool;
pj_memcpy(&stream->si, info, sizeof(*info));
+ stream->si.param = pjmedia_codec_param_clone(pool, info->param);
+ pj_strdup(pool, &stream->si.fmt.encoding_name, &info->fmt.encoding_name);
/* Init stream/port name */
name.ptr = (char*) pj_pool_alloc(pool, M);
@@ -2159,12 +2178,16 @@ PJ_DEF(pj_status_t) pjmedia_stream_create( pjmedia_endpt *endpt,
}
/* Get the frame size */
- stream->frame_size = stream->codec_param.info.max_bps *
- stream->codec_param.info.frm_ptime / 8 / 1000;
- if ((stream->codec_param.info.max_bps * stream->codec_param.info.frm_ptime)
- % 8000 != 0)
- {
- ++stream->frame_size;
+ if (stream->codec_param.info.max_rx_frame_size > 0) {
+ stream->frame_size = stream->codec_param.info.max_rx_frame_size;
+ } else {
+ stream->frame_size = stream->codec_param.info.max_bps *
+ stream->codec_param.info.frm_ptime / 8 / 1000;
+ if ((stream->codec_param.info.max_bps *
+ stream->codec_param.info.frm_ptime) % 8000 != 0)
+ {
+ ++stream->frame_size;
+ }
}
/* How many consecutive PLC frames can be generated */
@@ -2172,7 +2195,7 @@ PJ_DEF(pj_status_t) pjmedia_stream_create( pjmedia_endpt *endpt,
stream->codec_param.info.frm_ptime;
#if defined(PJMEDIA_HANDLE_G722_MPEG_BUG) && (PJMEDIA_HANDLE_G722_MPEG_BUG!=0)
- stream->rtp_rx_check_cnt = 5;
+ stream->rtp_rx_check_cnt = 50;
stream->has_g722_mpeg_bug = PJ_FALSE;
stream->rtp_rx_last_ts = 0;
stream->rtp_rx_last_cnt = 0;
@@ -2410,6 +2433,8 @@ err_cleanup:
*/
PJ_DEF(pj_status_t) pjmedia_stream_destroy( pjmedia_stream *stream )
{
+ pj_status_t status;
+
PJ_ASSERT_RETURN(stream != NULL, PJ_EINVAL);
/* Send RTCP BYE (also SDES & XR) */
@@ -2417,6 +2442,48 @@ PJ_DEF(pj_status_t) pjmedia_stream_destroy( pjmedia_stream *stream )
send_rtcp(stream, PJ_TRUE, PJ_TRUE, PJ_TRUE);
}
+ /* If we're in the middle of transmitting DTMF digit, send one last
+ * RFC 2833 RTP packet with 'End' flag set.
+ */
+ if (stream->tx_dtmf_count && stream->tx_dtmf_buf[0].duration != 0) {
+ pjmedia_frame frame_out;
+ pjmedia_channel *channel = stream->enc;
+ int first=0, last=0;
+ void *rtphdr;
+ int rtphdrlen;
+
+ pj_bzero(&frame_out, sizeof(frame_out));
+ frame_out.buf = ((char*)channel->out_pkt) + sizeof(pjmedia_rtp_hdr);
+ frame_out.size = 0;
+
+ create_dtmf_payload(stream, &frame_out, 1, &first, &last);
+
+ /* Encapsulate into RTP packet. Note that:
+ * - RTP marker should be set on the beginning of a new event
+ * - RTP timestamp is constant for the same packet.
+ */
+ status = pjmedia_rtp_encode_rtp( &channel->rtp,
+ stream->tx_event_pt, first,
+ frame_out.size, 0,
+ (const void**)&rtphdr,
+ &rtphdrlen);
+ if (status == PJ_SUCCESS) {
+ /* Copy RTP header to the beginning of packet */
+ pj_memcpy(channel->out_pkt, rtphdr, sizeof(pjmedia_rtp_hdr));
+
+ /* Send the RTP packet to the transport. */
+ status = pjmedia_transport_send_rtp(stream->transport,
+ channel->out_pkt,
+ frame_out.size +
+ sizeof(pjmedia_rtp_hdr));
+ }
+
+ if (status != PJ_SUCCESS) {
+ PJ_PERROR(4,(stream->port.info.name.ptr, status,
+ "Error sending RTP/DTMF end packet"));
+ }
+ }
+
/* Detach from transport
* MUST NOT hold stream mutex while detaching from transport, as
* it may cause deadlock. See ticket #460 for the details.
@@ -2692,6 +2759,7 @@ PJ_DEF(pj_status_t) pjmedia_stream_dial_dtmf( pjmedia_stream *stream,
stream->tx_dtmf_buf[stream->tx_dtmf_count+i].event = pt;
stream->tx_dtmf_buf[stream->tx_dtmf_count+i].duration = 0;
+ stream->tx_dtmf_buf[stream->tx_dtmf_count+i].ebit_cnt = 0;
}
if (status != PJ_SUCCESS)
diff --git a/pjmedia/src/pjmedia/transport_ice.c b/pjmedia/src/pjmedia/transport_ice.c
index 40bb71b..7c3deb2 100644
--- a/pjmedia/src/pjmedia/transport_ice.c
+++ b/pjmedia/src/pjmedia/transport_ice.c
@@ -1,4 +1,4 @@
-/* $Id: transport_ice.c 3999 2012-03-30 07:10:13Z bennylp $ */
+/* $Id: transport_ice.c 4350 2013-02-15 03:57:31Z nanang $ */
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
@@ -285,7 +285,9 @@ static void set_no_ice(struct transport_ice *tp_ice, const char *reason,
"Stopping ICE, reason=%s", reason));
}
- pj_ice_strans_stop_ice(tp_ice->ice_st);
+ if (tp_ice->ice_st) {
+ pj_ice_strans_stop_ice(tp_ice->ice_st);
+ }
tp_ice->use_ice = PJ_FALSE;
}
@@ -1541,6 +1543,8 @@ static pj_status_t transport_get_info(pjmedia_transport *tp,
ii = (pjmedia_ice_transport_info*) tsi->buffer;
pj_bzero(ii, sizeof(*ii));
+ ii->active = tp_ice->use_ice;
+
if (pj_ice_strans_has_sess(tp_ice->ice_st))
ii->role = pj_ice_strans_get_role(tp_ice->ice_st);
else
diff --git a/pjmedia/src/pjmedia/transport_srtp.c b/pjmedia/src/pjmedia/transport_srtp.c
index 1321e75..a661c37 100644
--- a/pjmedia/src/pjmedia/transport_srtp.c
+++ b/pjmedia/src/pjmedia/transport_srtp.c
@@ -1,4 +1,4 @@
-/* $Id: transport_srtp.c 3999 2012-03-30 07:10:13Z bennylp $ */
+/* $Id: transport_srtp.c 4366 2013-02-21 20:41:31Z ming $ */
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
@@ -34,10 +34,12 @@
#define THIS_FILE "transport_srtp.c"
-/* Maximum size of packet */
-#define MAX_RTP_BUFFER_LEN 1500
-#define MAX_RTCP_BUFFER_LEN 1500
-#define MAX_KEY_LEN 32
+/* Maximum size of outgoing packet */
+#define MAX_RTP_BUFFER_LEN PJMEDIA_MAX_MTU
+#define MAX_RTCP_BUFFER_LEN PJMEDIA_MAX_MTU
+
+/* Maximum SRTP crypto key length */
+#define MAX_KEY_LEN 128
/* Initial value of probation counter. When probation counter > 0,
* it means SRTP is in probation state, and it may restart when
@@ -611,19 +613,47 @@ PJ_DEF(pj_status_t) pjmedia_transport_srtp_start(
/* Declare SRTP session initialized */
srtp->session_inited = PJ_TRUE;
- PJ_LOG(5, (srtp->pool->obj_name, "TX: %s key=%s", srtp->tx_policy.name.ptr,
- octet_string_hex_string(tx->key.ptr, tx->key.slen)));
- if (srtp->tx_policy.flags) {
- PJ_LOG(5,(srtp->pool->obj_name,"TX: disable%s%s", (cr_tx_idx?"":" enc"),
- (au_tx_idx?"":" auth")));
- }
+ /* Logging stuffs */
+#if PJ_LOG_MAX_LEVEL >= 5
+ {
+ char b64[PJ_BASE256_TO_BASE64_LEN(MAX_KEY_LEN)];
+ int b64_len;
+
+ /* TX crypto and key */
+ b64_len = sizeof(b64);
+ status = pj_base64_encode((pj_uint8_t*)tx->key.ptr, tx->key.slen,
+ b64, &b64_len);
+ if (status != PJ_SUCCESS)
+ b64_len = pj_ansi_sprintf(b64, "--key too long--");
+ else
+ b64[b64_len] = '\0';
+
+ PJ_LOG(5, (srtp->pool->obj_name, "TX: %s key=%s",
+ srtp->tx_policy.name.ptr, b64));
+ if (srtp->tx_policy.flags) {
+ PJ_LOG(5,(srtp->pool->obj_name, "TX: disable%s%s",
+ (cr_tx_idx?"":" enc"),
+ (au_tx_idx?"":" auth")));
+ }
- PJ_LOG(5, (srtp->pool->obj_name, "RX: %s key=%s", srtp->rx_policy.name.ptr,
- octet_string_hex_string(rx->key.ptr, rx->key.slen)));
- if (srtp->rx_policy.flags) {
- PJ_LOG(5,(srtp->pool->obj_name,"RX: disable%s%s", (cr_rx_idx?"":" enc"),
- (au_rx_idx?"":" auth")));
+ /* RX crypto and key */
+ b64_len = sizeof(b64);
+ status = pj_base64_encode((pj_uint8_t*)rx->key.ptr, rx->key.slen,
+ b64, &b64_len);
+ if (status != PJ_SUCCESS)
+ b64_len = pj_ansi_sprintf(b64, "--key too long--");
+ else
+ b64[b64_len] = '\0';
+
+ PJ_LOG(5, (srtp->pool->obj_name, "RX: %s key=%s",
+ srtp->rx_policy.name.ptr, b64));
+ if (srtp->rx_policy.flags) {
+ PJ_LOG(5,(srtp->pool->obj_name,"RX: disable%s%s",
+ (cr_rx_idx?"":" enc"),
+ (au_rx_idx?"":" auth")));
+ }
}
+#endif
on_return:
pj_lock_release(srtp->mutex);
@@ -777,7 +807,7 @@ static pj_status_t transport_send_rtp( pjmedia_transport *tp,
if (srtp->bypass_srtp)
return pjmedia_transport_send_rtp(srtp->member_tp, pkt, size);
- if (size > sizeof(srtp->rtp_tx_buffer))
+ if (size > sizeof(srtp->rtp_tx_buffer) - 10)
return PJ_ETOOBIG;
pj_memcpy(srtp->rtp_tx_buffer, pkt, size);
@@ -791,7 +821,8 @@ static pj_status_t transport_send_rtp( pjmedia_transport *tp,
pj_lock_release(srtp->mutex);
if (err == err_status_ok) {
- status = pjmedia_transport_send_rtp(srtp->member_tp, srtp->rtp_tx_buffer, len);
+ status = pjmedia_transport_send_rtp(srtp->member_tp,
+ srtp->rtp_tx_buffer, len);
} else {
status = PJMEDIA_ERRNO_FROM_LIBSRTP(err);
}
@@ -822,7 +853,7 @@ static pj_status_t transport_send_rtcp2(pjmedia_transport *tp,
pkt, size);
}
- if (size > sizeof(srtp->rtcp_tx_buffer))
+ if (size > sizeof(srtp->rtcp_tx_buffer) - 10)
return PJ_ETOOBIG;
pj_memcpy(srtp->rtcp_tx_buffer, pkt, size);
diff --git a/pjmedia/src/pjmedia/transport_udp.c b/pjmedia/src/pjmedia/transport_udp.c
index 76f9bbb..458424d 100644
--- a/pjmedia/src/pjmedia/transport_udp.c
+++ b/pjmedia/src/pjmedia/transport_udp.c
@@ -1,4 +1,4 @@
-/* $Id: transport_udp.c 3841 2011-10-24 09:28:13Z ming $ */
+/* $Id: transport_udp.c 4197 2012-07-05 07:26:29Z nanang $ */
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
@@ -29,7 +29,7 @@
/* Maximum size of incoming RTP packet */
-#define RTP_LEN PJMEDIA_MAX_MTU
+#define RTP_LEN PJMEDIA_MAX_MRU
/* Maximum size of incoming RTCP packet */
#define RTCP_LEN 600
@@ -42,7 +42,7 @@ static const pj_str_t ID_RTP_AVP = { "RTP/AVP", 7 };
/* Pending write buffer */
typedef struct pending_write
{
- char buffer[RTP_LEN];
+ char buffer[PJMEDIA_MAX_MTU];
pj_ioqueue_op_key_t op_key;
} pending_write;
@@ -752,7 +752,7 @@ static pj_status_t transport_send_rtp( pjmedia_transport *tp,
PJ_ASSERT_RETURN(udp->attached, PJ_EINVALIDOP);
/* Check that the size is supported */
- PJ_ASSERT_RETURN(size <= RTP_LEN, PJ_ETOOBIG);
+ PJ_ASSERT_RETURN(size <= PJMEDIA_MAX_MTU, PJ_ETOOBIG);
/* Simulate packet lost on TX direction */
if (udp->tx_drop_pct) {
diff --git a/pjmedia/src/pjmedia/types.c b/pjmedia/src/pjmedia/types.c
index b280ea8..732f9b5 100644
--- a/pjmedia/src/pjmedia/types.c
+++ b/pjmedia/src/pjmedia/types.c
@@ -1,4 +1,4 @@
-/* $Id: types.c 3715 2011-08-19 09:35:25Z nanang $ */
+/* $Id: types.c 4411 2013-03-04 04:34:38Z nanang $ */
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
@@ -37,10 +37,10 @@ PJ_DEF(const char*) pjmedia_type_name(pjmedia_type t)
"unknown"
};
- pj_assert(t < PJ_ARRAY_SIZE(type_names));
+ pj_assert(t < (int)PJ_ARRAY_SIZE(type_names));
pj_assert(PJMEDIA_TYPE_UNKNOWN == 4);
- if (t < PJ_ARRAY_SIZE(type_names))
+ if (t < (int)PJ_ARRAY_SIZE(type_names))
return type_names[t];
else
return "??";
diff --git a/pjmedia/src/pjmedia/vid_codec_util.c b/pjmedia/src/pjmedia/vid_codec_util.c
index e51fff4..8cc241b 100644
--- a/pjmedia/src/pjmedia/vid_codec_util.c
+++ b/pjmedia/src/pjmedia/vid_codec_util.c
@@ -1,4 +1,4 @@
-/* $Id: vid_codec_util.c 3995 2012-03-29 10:54:01Z nanang $ */
+/* $Id: vid_codec_util.c 4362 2013-02-21 14:51:56Z nanang $ */
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
@@ -38,6 +38,14 @@
*/
#define H264_STRICT_SDP_NEGO 0
+/* Default frame rate, if not specified */
+#define DEFAULT_H264_FPS_NUM 15
+#define DEFAULT_H264_FPS_DENUM 1
+
+/* Default aspect ratio, if not specified */
+#define DEFAULT_H264_RATIO_NUM 16
+#define DEFAULT_H264_RATIO_DENUM 9
+
/* ITU resolution definition */
struct mpi_resolution_t
@@ -55,6 +63,10 @@ mpi_resolutions [] =
};
+#define CALC_H264_MB_NUM(size) (((size.w+15)/16)*((size.h+15)/16))
+#define CALC_H264_MBPS(size,fps) CALC_H264_MB_NUM(size)*fps.num/fps.denum
+
+
/* Parse fmtp value for custom resolution, e.g: "CUSTOM=800,600,2" */
static pj_status_t parse_custom_res_fmtp(const pj_str_t *fmtp_val,
pjmedia_rect_size *size,
@@ -291,6 +303,75 @@ PJ_DEF(pj_status_t) pjmedia_vid_codec_h263_apply_fmtp(
}
+/* Declaration of H.264 level info */
+typedef struct h264_level_info_t
+{
+ unsigned id; /* Level id. */
+ unsigned max_mbps; /* Max macroblocks per second. */
+ unsigned max_mb; /* Max macroblocks. */
+ unsigned max_br; /* Max bitrate (kbps). */
+} h264_level_info_t;
+
+
+/* Init H264 parameters based on profile-level-id */
+static pj_status_t init_h264_profile(const pj_str_t *profile,
+ pjmedia_vid_codec_h264_fmtp *fmtp)
+{
+ const h264_level_info_t level_info[] =
+ {
+ { 10, 1485, 99, 64 },
+ { 9, 1485, 99, 128 }, /*< level 1b */
+ { 11, 3000, 396, 192 },
+ { 12, 6000, 396, 384 },
+ { 13, 11880, 396, 768 },
+ { 20, 11880, 396, 2000 },
+ { 21, 19800, 792, 4000 },
+ { 22, 20250, 1620, 4000 },
+ { 30, 40500, 1620, 10000 },
+ { 31, 108000, 3600, 14000 },
+ { 32, 216000, 5120, 20000 },
+ { 40, 245760, 8192, 20000 },
+ { 41, 245760, 8192, 50000 },
+ { 42, 522240, 8704, 50000 },
+ { 50, 589824, 22080, 135000 },
+ { 51, 983040, 36864, 240000 },
+ };
+ unsigned i, tmp;
+ pj_str_t endst;
+ const h264_level_info_t *li = NULL;
+
+ if (profile->slen != 6)
+ return PJMEDIA_SDP_EINFMTP;
+
+ tmp = pj_strtoul2(profile, &endst, 16);
+ if (endst.slen)
+ return PJMEDIA_SDP_EINFMTP;
+
+ fmtp->profile_idc = (pj_uint8_t)((tmp >> 16) & 0xFF);
+ fmtp->profile_iop = (pj_uint8_t)((tmp >> 8) & 0xFF);
+ fmtp->level = (pj_uint8_t)(tmp & 0xFF);
+
+ for (i = 0; i < PJ_ARRAY_SIZE(level_info); ++i) {
+ if (level_info[i].id == fmtp->level) {
+ li = &level_info[i];
+ break;
+ }
+ }
+ if (li == NULL)
+ return PJMEDIA_SDP_EINFMTP;
+
+ /* Init profile level spec */
+ if (fmtp->max_br == 0)
+ fmtp->max_br = li->max_br;
+ if (fmtp->max_mbps == 0)
+ fmtp->max_mbps = li->max_mbps;
+ if (fmtp->max_fs == 0)
+ fmtp->max_fs = li->max_mb;
+
+ return PJ_SUCCESS;
+}
+
+
/* H264 fmtp parser */
PJ_DEF(pj_status_t) pjmedia_vid_codec_h264_parse_fmtp(
const pjmedia_codec_fmtp *fmtp,
@@ -305,24 +386,17 @@ PJ_DEF(pj_status_t) pjmedia_vid_codec_h264_parse_fmtp(
const pj_str_t PACKETIZATION_MODE = {"packetization-mode", 18};
const pj_str_t SPROP_PARAMETER_SETS = {"sprop-parameter-sets", 20};
unsigned i;
+ pj_status_t status;
pj_bzero(h264_fmtp, sizeof(*h264_fmtp));
for (i=0; i<fmtp->cnt; ++i) {
unsigned tmp;
if (pj_stricmp(&fmtp->param[i].name, &PROFILE_LEVEL_ID)==0) {
- pj_str_t endst;
-
- if (fmtp->param[i].val.slen != 6)
- return PJMEDIA_SDP_EINFMTP;
-
- tmp = pj_strtoul2(&fmtp->param[i].val, &endst, 16);
- if (endst.slen)
- return PJMEDIA_SDP_EINFMTP;
-
- h264_fmtp->profile_idc = (pj_uint8_t)((tmp >> 16) & 0xFF);
- h264_fmtp->profile_iop = (pj_uint8_t)((tmp >> 8) & 0xFF);
- h264_fmtp->level = (pj_uint8_t)(tmp & 0xFF);
+ /* Init H264 parameters based on level, if not set yet */
+ status = init_h264_profile(&fmtp->param[i].val, h264_fmtp);
+ if (status != PJ_SUCCESS)
+ return status;
} else if (pj_stricmp(&fmtp->param[i].name, &PACKETIZATION_MODE)==0) {
tmp = pj_strtoul(&fmtp->param[i].val);
if (tmp >= 0 && tmp <= 2)
@@ -331,19 +405,19 @@ PJ_DEF(pj_status_t) pjmedia_vid_codec_h264_parse_fmtp(
return PJMEDIA_SDP_EINFMTP;
} else if (pj_stricmp(&fmtp->param[i].name, &MAX_MBPS)==0) {
tmp = pj_strtoul(&fmtp->param[i].val);
- h264_fmtp->max_mbps = tmp;
+ h264_fmtp->max_mbps = PJ_MAX(tmp, h264_fmtp->max_mbps);
} else if (pj_stricmp(&fmtp->param[i].name, &MAX_FS)==0) {
tmp = pj_strtoul(&fmtp->param[i].val);
- h264_fmtp->max_fs = tmp;
+ h264_fmtp->max_fs = PJ_MAX(tmp, h264_fmtp->max_fs);
} else if (pj_stricmp(&fmtp->param[i].name, &MAX_CPB)==0) {
tmp = pj_strtoul(&fmtp->param[i].val);
- h264_fmtp->max_cpb = tmp;
+ h264_fmtp->max_cpb = PJ_MAX(tmp, h264_fmtp->max_cpb);
} else if (pj_stricmp(&fmtp->param[i].name, &MAX_DPB)==0) {
tmp = pj_strtoul(&fmtp->param[i].val);
- h264_fmtp->max_dpb = tmp;
+ h264_fmtp->max_dpb = PJ_MAX(tmp, h264_fmtp->max_dpb);
} else if (pj_stricmp(&fmtp->param[i].name, &MAX_BR)==0) {
tmp = pj_strtoul(&fmtp->param[i].val);
- h264_fmtp->max_br = tmp;
+ h264_fmtp->max_br = PJ_MAX(tmp, h264_fmtp->max_br);
} else if (pj_stricmp(&fmtp->param[i].name, &SPROP_PARAMETER_SETS)==0)
{
pj_str_t sps_st;
@@ -507,66 +581,80 @@ PJ_DEF(pj_status_t) pjmedia_vid_codec_h264_match_sdp(pj_pool_t *pool,
}
-/* Declaration of H.264 level info */
-typedef struct h264_level_info_t
-{
- unsigned id; /* Level id. */
- unsigned max_mbps; /* Max macroblocks per second. */
- unsigned max_mb; /* Max macroblocks. */
- unsigned bitrate; /* Max bitrate (kbps). */
- unsigned def_w; /* Default width. */
- unsigned def_h; /* Default height. */
- unsigned def_fps; /* Default fps. */
-} h264_level_info_t;
-
+/* Find greatest common divisor (GCD) */
+static unsigned gcd (unsigned a, unsigned b) {
+ unsigned c;
+ while (b) {
+ c = a % b;
+ a = b;
+ b = c;
+ }
+ return a;
+}
-/* Get H.264 level info from specified level ID */
-static pj_status_t get_h264_level_info(unsigned id, h264_level_info_t *level)
+/* Find highest resolution possible for the specified H264 fmtp and
+ * aspect ratio.
+ */
+static pj_status_t find_highest_res(pjmedia_vid_codec_h264_fmtp *fmtp,
+ const pjmedia_ratio *fps,
+ const pjmedia_ratio *ratio,
+ pjmedia_rect_size *size)
{
- unsigned i;
- const h264_level_info_t level_info[] =
- {
- { 10, 1485, 99, 64, 176, 144, 15 },
- { 9, 1485, 99, 128, 176, 144, 15 }, /*< level 1b */
- { 11, 3000, 396, 192, 320, 240, 10 },
- { 12, 6000, 396, 384, 352, 288, 15 },
- { 13, 11880, 396, 768, 352, 288, 15 },
- { 20, 11880, 396, 2000, 352, 288, 30 },
- { 21, 19800, 792, 4000, 352, 288, 30 },
- { 22, 20250, 1620, 4000, 352, 288, 30 },
- { 30, 40500, 1620, 10000, 720, 480, 30 },
- { 31, 108000, 3600, 14000, 1280, 720, 30 },
- { 32, 216000, 5120, 20000, 1280, 720, 30 },
- { 40, 245760, 8192, 20000, 1920, 1080, 30 },
- { 41, 245760, 8192, 50000, 1920, 1080, 30 },
- { 42, 522240, 8704, 50000, 1920, 1080, 30 },
- { 50, 589824, 22080, 135000, 1920, 1080, 30 },
- { 51, 983040, 36864, 240000, 1920, 1080, 30 },
- };
+ pjmedia_ratio def_ratio = { DEFAULT_H264_RATIO_NUM,
+ DEFAULT_H264_RATIO_DENUM };
+ pjmedia_ratio def_fps = { DEFAULT_H264_FPS_NUM,
+ DEFAULT_H264_FPS_DENUM };
+ pjmedia_ratio asp_ratio, the_fps;
+ unsigned max_fs, g, scale;
+
+ pj_assert(size);
+
+ /* Get the ratio, or just use default if not provided. */
+ if (ratio && ratio->num && ratio->denum) {
+ asp_ratio = *ratio;
+ } else {
+ asp_ratio = def_ratio;
+ }
- for (i = 0; i < PJ_ARRAY_SIZE(level_info); ++i) {
- if (level_info[i].id == id) {
- *level = level_info[i];
- return PJ_SUCCESS;
- }
+ /* Normalize the aspect ratio */
+ g = gcd(asp_ratio.num, asp_ratio.denum);
+ asp_ratio.num /= g;
+ asp_ratio.denum /= g;
+
+ /* Get the frame rate, or just use default if not provided. */
+ if (fps && fps->num && fps->denum) {
+ the_fps = *fps;
+ } else {
+ the_fps = def_fps;
}
- return PJ_ENOTFOUND;
-}
+ /* Calculate maximum size (in macroblocks) */
+ max_fs = fmtp->max_mbps * fps->denum / fps->num;
+ max_fs = PJ_MIN(max_fs, fmtp->max_fs);
-#define CALC_H264_MB_NUM(size) (((size.w+15)/16)*((size.h+15)/16))
-#define CALC_H264_MBPS(size,fps) CALC_H264_MB_NUM(size)*fps.num/fps.denum
+ /* Check if the specified ratio is using big numbers
+ * (not normalizable), override it with default ratio!
+ */
+ if ((int)max_fs < asp_ratio.num * asp_ratio.denum)
+ asp_ratio = def_ratio;
+
+ /* Calculate the scale factor for size */
+ scale = pj_isqrt(max_fs / asp_ratio.denum / asp_ratio.num);
+
+ /* Calculate the size, note that the frame size is in macroblock units */
+ size->w = asp_ratio.num * scale * 16;
+ size->h = asp_ratio.denum * scale * 16;
+
+ return PJ_SUCCESS;
+}
PJ_DEF(pj_status_t) pjmedia_vid_codec_h264_apply_fmtp(
pjmedia_vid_codec_param *param)
{
- const unsigned default_fps = 30;
-
if (param->dir & PJMEDIA_DIR_ENCODING) {
pjmedia_vid_codec_h264_fmtp fmtp;
pjmedia_video_format_detail *vfd;
- h264_level_info_t level_info;
pj_status_t status;
/* Get remote param */
@@ -575,36 +663,42 @@ PJ_DEF(pj_status_t) pjmedia_vid_codec_h264_apply_fmtp(
if (status != PJ_SUCCESS)
return status;
- status = get_h264_level_info(fmtp.level, &level_info);
- if (status != PJ_SUCCESS)
- return status;
-
- /* Size and fps for encoding direction must conform to H.264 level
+ /* Adjust fps, size, and bitrate to conform to H.264 level
* specified by remote SDP fmtp.
*/
vfd = pjmedia_format_get_video_format_detail(&param->enc_fmt,
PJ_TRUE);
+
+ if (vfd->fps.num == 0 || vfd->fps.denum == 0) {
+ vfd->fps.num = DEFAULT_H264_FPS_NUM;
+ vfd->fps.denum = DEFAULT_H264_FPS_DENUM;
+ }
+
if (vfd->size.w && vfd->size.h) {
unsigned mb, mbps;
- if (vfd->fps.num == 0 || vfd->fps.denum == 0) {
- vfd->fps.num = default_fps;
- vfd->fps.denum = 1;
- }
+ /* Scale down the resolution if it exceeds profile spec */
mb = CALC_H264_MB_NUM(vfd->size);
mbps = CALC_H264_MBPS(vfd->size, vfd->fps);
- if (mb > level_info.max_mb || mbps > level_info.max_mbps) {
- vfd->size.w = level_info.def_w;
- vfd->size.h = level_info.def_h;
- vfd->fps.num = level_info.def_fps;
- vfd->fps.denum = 1;
+ if (mb > fmtp.max_fs || mbps > fmtp.max_mbps) {
+ pjmedia_ratio r;
+ r.num = vfd->size.w;
+ r.denum = vfd->size.h;
+ find_highest_res(&fmtp, &vfd->fps, &r, &vfd->size);
}
} else {
- vfd->size.w = level_info.def_w;
- vfd->size.h = level_info.def_h;
- vfd->fps.num = level_info.def_fps;
- vfd->fps.denum = 1;
+ /* When not specified, just use the highest res possible*/
+ pjmedia_ratio r;
+ r.num = vfd->size.w;
+ r.denum = vfd->size.h;
+ find_highest_res(&fmtp, &vfd->fps, &r, &vfd->size);
}
+
+ /* Encoding bitrate must not be higher than H264 level spec */
+ if (vfd->avg_bps > fmtp.max_br * 1000)
+ vfd->avg_bps = fmtp.max_br * 1000;
+ if (vfd->max_bps > fmtp.max_br * 1000)
+ vfd->max_bps = fmtp.max_br * 1000;
}
if (param->dir & PJMEDIA_DIR_DECODING) {
@@ -613,7 +707,8 @@ PJ_DEF(pj_status_t) pjmedia_vid_codec_h264_apply_fmtp(
*/
pjmedia_vid_codec_h264_fmtp fmtp;
pjmedia_video_format_detail *vfd;
- h264_level_info_t level_info;
+ pjmedia_ratio r;
+ pjmedia_rect_size highest_size;
pj_status_t status;
status = pjmedia_vid_codec_h264_parse_fmtp(&param->dec_fmtp,
@@ -621,22 +716,29 @@ PJ_DEF(pj_status_t) pjmedia_vid_codec_h264_apply_fmtp(
if (status != PJ_SUCCESS)
return status;
- status = get_h264_level_info(fmtp.level, &level_info);
- if (status != PJ_SUCCESS)
- return status;
-
vfd = pjmedia_format_get_video_format_detail(&param->dec_fmt,
PJ_TRUE);
- if (vfd->size.w * vfd->size.h < level_info.def_w * level_info.def_h) {
- vfd->size.w = level_info.def_w;
- vfd->size.h = level_info.def_h;
- }
-
if (vfd->fps.num == 0 || vfd->fps.denum == 0) {
- vfd->fps.num = default_fps;
- vfd->fps.denum = 1;
+ vfd->fps.num = DEFAULT_H264_FPS_NUM;
+ vfd->fps.denum = DEFAULT_H264_FPS_DENUM;
}
+
+ /* Normalize decoding resolution, i.e: it must not be lower than
+ * the H264 profile level setting used, as this may be used by
+ * app to allocate buffer.
+ */
+ r.num = vfd->size.w;
+ r.denum = vfd->size.h;
+ find_highest_res(&fmtp, &vfd->fps, &r, &highest_size);
+ if (vfd->size.w * vfd->size.h < highest_size.w * highest_size.h)
+ vfd->size = highest_size;
+
+ /* Normalize decoding bitrate based on H264 level spec */
+ if (vfd->avg_bps < fmtp.max_br * 1000)
+ vfd->avg_bps = fmtp.max_br * 1000;
+ if (vfd->max_bps < fmtp.max_br * 1000)
+ vfd->max_bps = fmtp.max_br * 1000;
}
return PJ_SUCCESS;
diff --git a/pjmedia/src/pjmedia/vid_port.c b/pjmedia/src/pjmedia/vid_port.c
index 289e3e5..017e867 100644
--- a/pjmedia/src/pjmedia/vid_port.c
+++ b/pjmedia/src/pjmedia/vid_port.c
@@ -1,4 +1,4 @@
-/* $Id: vid_port.c 4168 2012-06-18 05:59:08Z ming $ */
+/* $Id: vid_port.c 4290 2012-11-01 03:06:33Z ming $ */
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
*
@@ -332,9 +332,7 @@ PJ_DEF(pj_status_t) pjmedia_vid_port_create( pj_pool_t *pool,
PJMEDIA_SIG_VID_PORT,
prm->vidparam.dir, &prm->vidparam.fmt);
- if (vp->stream_role == ROLE_ACTIVE) {
- need_frame_buf = PJ_TRUE;
- }
+ need_frame_buf = PJ_TRUE;
}
if (need_frame_buf) {
@@ -654,8 +652,10 @@ static pj_status_t convert_frame(pjmedia_vid_port *vp,
pj_status_t status = PJ_SUCCESS;
if (vp->conv.conv) {
- dst_frame->buf = vp->conv.conv_buf;
- dst_frame->size = vp->conv.conv_buf_size;
+ if (!dst_frame->buf || dst_frame->size < vp->conv.conv_buf_size) {
+ dst_frame->buf = vp->conv.conv_buf;
+ dst_frame->size = vp->conv.conv_buf_size;
+ }
status = pjmedia_converter_convert(vp->conv.conv,
src_frame, dst_frame);
}
@@ -922,6 +922,7 @@ static pj_status_t vid_pasv_port_put_frame(struct pjmedia_port *this_port,
pj_status_t status;
pjmedia_frame frame_;
+ pj_bzero(&frame_, sizeof(frame_));
status = convert_frame(vp, frame, &frame_);
if (status != PJ_SUCCESS)
return status;
diff --git a/pjmedia/src/pjmedia/vid_stream.c b/pjmedia/src/pjmedia/vid_stream.c
index d899408..e101d7b 100644
--- a/pjmedia/src/pjmedia/vid_stream.c
+++ b/pjmedia/src/pjmedia/vid_stream.c
@@ -1,4 +1,4 @@
-/* $Id: vid_stream.c 4123 2012-05-14 11:17:31Z ming $ */
+/* $Id: vid_stream.c 4197 2012-07-05 07:26:29Z nanang $ */
/*
* Copyright (C) 2011 Teluu Inc. (http://www.teluu.com)
*
@@ -68,6 +68,13 @@
# define PJMEDIA_VSTREAM_INC 1000
#endif
+/* Due to network MTU limitation, a picture bitstream may be splitted into
+ * several chunks for RTP delivery. The chunk number may vary depend on the
+ * picture resolution and MTU. This constant specifies the minimum chunk
+ * number to be allocated to store a picture bitstream in decoding direction.
+ */
+#define MIN_CHUNKS_PER_FRM 30
+
/* Video stream keep-alive feature is currently disabled. */
#if defined(PJMEDIA_STREAM_ENABLE_KA) && PJMEDIA_STREAM_ENABLE_KA != 0
# undef PJMEDIA_STREAM_ENABLE_KA
@@ -1357,7 +1364,6 @@ PJ_DEF(pj_status_t) pjmedia_vid_stream_create(
int frm_ptime, chunks_per_frm;
pjmedia_video_format_detail *vfd_enc, *vfd_dec;
char *p;
- unsigned dec_mtu;
pj_status_t status;
if (!pool) {
@@ -1410,9 +1416,7 @@ PJ_DEF(pj_status_t) pjmedia_vid_stream_create(
if (info->codec_param->enc_mtu > PJMEDIA_MAX_MTU)
info->codec_param->enc_mtu = PJMEDIA_MAX_MTU;
- /* MTU estimation for decoding direction */
- dec_mtu = PJMEDIA_MAX_MTU;
-
+ /* Packet size estimation for decoding direction */
vfd_enc = pjmedia_format_get_video_format_detail(
&info->codec_param->enc_fmt, PJ_TRUE);
vfd_dec = pjmedia_format_get_video_format_detail(
@@ -1528,8 +1532,9 @@ PJ_DEF(pj_status_t) pjmedia_vid_stream_create(
/* Init jitter buffer parameters: */
frm_ptime = 1000 * vfd_enc->fps.denum / vfd_enc->fps.num;
- chunks_per_frm = stream->frame_size / dec_mtu;
- if (chunks_per_frm == 0) chunks_per_frm = 1;
+ chunks_per_frm = stream->frame_size / PJMEDIA_MAX_MRU;
+ if (chunks_per_frm < MIN_CHUNKS_PER_FRM)
+ chunks_per_frm = MIN_CHUNKS_PER_FRM;
/* JB max count, default 500ms */
if (info->jb_max >= frm_ptime)
@@ -1564,7 +1569,7 @@ PJ_DEF(pj_status_t) pjmedia_vid_stream_create(
/* Create jitter buffer */
status = pjmedia_jbuf_create(pool, &stream->dec->port.info.name,
- dec_mtu + PJMEDIA_STREAM_RESV_PAYLOAD_LEN,
+ PJMEDIA_MAX_MRU,
1000 * vfd_enc->fps.denum / vfd_enc->fps.num,
jb_max, &stream->jb);
if (status != PJ_SUCCESS)
diff --git a/pjmedia/src/pjmedia/vid_stream_info.c b/pjmedia/src/pjmedia/vid_stream_info.c
index 51b688f..37dae5b 100644
--- a/pjmedia/src/pjmedia/vid_stream_info.c
+++ b/pjmedia/src/pjmedia/vid_stream_info.c
@@ -1,4 +1,4 @@
-/* $Id: vid_stream_info.c 3982 2012-03-22 09:56:52Z bennylp $ */
+/* $Id: vid_stream_info.c 4257 2012-09-17 03:11:44Z ming $ */
/*
* Copyright (C) 2011 Teluu Inc. (http://www.teluu.com)
*
@@ -22,6 +22,7 @@
#include <pj/ctype.h>
#include <pj/rand.h>
+#if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0)
static const pj_str_t ID_VIDEO = { "video", 5};
static const pj_str_t ID_IN = { "IN", 2 };
@@ -382,4 +383,4 @@ PJ_DEF(pj_status_t) pjmedia_vid_stream_info_from_sdp(
return status;
}
-
+#endif /* PJMEDIA_HAS_VIDEO */