summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRiza Sulistyo <riza@teluu.com>2016-08-05 07:26:18 +0000
committerRiza Sulistyo <riza@teluu.com>2016-08-05 07:26:18 +0000
commita95fd7ee553a5b1774d263e5be91c859719189da (patch)
tree403218b2176d57bc7dd2d3098d40e555dae25d16
parent32479fea1f498f051e64570c5280cd77746b14e3 (diff)
Re #1910: Implement option to regularly send video keyframe in the beginning of video call session.
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@5410 74dad513-b988-da41-8d7b-12977e46ad98
-rw-r--r--pjmedia/include/pjmedia/config.h19
-rw-r--r--pjmedia/include/pjmedia/vid_stream.h33
-rw-r--r--pjmedia/src/pjmedia/vid_stream.c37
-rw-r--r--pjsip/include/pjsua-lib/pjsua.h7
-rw-r--r--pjsip/include/pjsua2/account.hpp15
-rw-r--r--pjsip/src/pjsua-lib/pjsua_core.c1
-rw-r--r--pjsip/src/pjsua-lib/pjsua_vid.c3
-rw-r--r--pjsip/src/pjsua2/account.cpp8
8 files changed, 123 insertions, 0 deletions
diff --git a/pjmedia/include/pjmedia/config.h b/pjmedia/include/pjmedia/config.h
index 817fba89..cbcd08fb 100644
--- a/pjmedia/include/pjmedia/config.h
+++ b/pjmedia/include/pjmedia/config.h
@@ -1330,6 +1330,25 @@
# define PJMEDIA_HAS_DTMF_FLASH 1
#endif
+/**
+ * Specify the number of keyframe needed to be sent after the stream is
+ * created. Setting this to 0 will disable it.
+ *
+ * Default : 5
+ */
+#ifndef PJMEDIA_VID_STREAM_START_KEYFRAME_CNT
+# define PJMEDIA_VID_STREAM_START_KEYFRAME_CNT 5
+#endif
+
+/**
+ * Specify the interval to send keyframe after the stream is created, in msec.
+ *
+ * Default : 1000
+ */
+#ifndef PJMEDIA_VID_STREAM_START_KEYFRAME_INTERVAL_MSEC
+# define PJMEDIA_VID_STREAM_START_KEYFRAME_INTERVAL_MSEC 1000
+#endif
+
/**
* @}
diff --git a/pjmedia/include/pjmedia/vid_stream.h b/pjmedia/include/pjmedia/vid_stream.h
index c812d37d..cd756f1e 100644
--- a/pjmedia/include/pjmedia/vid_stream.h
+++ b/pjmedia/include/pjmedia/vid_stream.h
@@ -117,6 +117,28 @@ typedef struct pjmedia_vid_stream_rc_config
} pjmedia_vid_stream_rc_config;
+/**
+ * Structure of configuration settings for video stream sending keyframe
+ * after it is created.
+ */
+typedef struct pjmedia_vid_stream_sk_config
+{
+ /**
+ * The number of keyframe to be sent after the stream is created.
+ *
+ * Default: PJMEDIA_VID_STREAM_START_KEYFRAME_CNT
+ */
+ unsigned count;
+
+ /**
+ * The keyframe sending interval after the stream is created.
+ *
+ * Default: PJMEDIA_VID_STREAM_START_KEYFRAME_INTERVAL_MSEC
+ */
+ unsigned interval;
+
+} pjmedia_vid_stream_sk_config;
+
/**
* This structure describes video stream information. Each video stream
@@ -165,6 +187,9 @@ typedef struct pjmedia_vid_stream_info
pjmedia_vid_stream_rc_config rc_cfg;
/**< Stream send rate control settings. */
+
+ pjmedia_vid_stream_sk_config sk_cfg;
+ /**< Stream send keyframe settings. */
} pjmedia_vid_stream_info;
@@ -201,6 +226,14 @@ pjmedia_vid_stream_info_from_sdp(pjmedia_vid_stream_info *si,
PJ_DECL(void)
pjmedia_vid_stream_rc_config_default(pjmedia_vid_stream_rc_config *cfg);
+/**
+ * Initialize the video stream send keyframe with default settings.
+ *
+ * @param cfg Video stream send keyframe structure to be initialized.
+ */
+PJ_DECL(void)
+pjmedia_vid_stream_sk_config_default(pjmedia_vid_stream_sk_config *cfg);
+
/*
* Opaque declaration for video stream.
diff --git a/pjmedia/src/pjmedia/vid_stream.c b/pjmedia/src/pjmedia/vid_stream.c
index 69891ffb..c586018f 100644
--- a/pjmedia/src/pjmedia/vid_stream.c
+++ b/pjmedia/src/pjmedia/vid_stream.c
@@ -154,6 +154,13 @@ struct pjmedia_vid_stream
frame assembly. */
pj_bool_t force_keyframe;/**< Forced to encode keyframe? */
+ unsigned num_keyframe; /**< The number of keyframe needed
+ to be sent, after the stream
+ is created. */
+ pj_timestamp last_keyframe_tx;
+ /**< Timestamp of the last
+ keyframe. */
+
#if defined(PJMEDIA_STREAM_ENABLE_KA) && PJMEDIA_STREAM_ENABLE_KA!=0
pj_bool_t use_ka; /**< Stream keep-alive with non-
@@ -850,6 +857,23 @@ static pj_status_t put_frame(pjmedia_port *port,
frame_out.buf = ((char*)channel->buf) + sizeof(pjmedia_rtp_hdr);
frame_out.size = 0;
+ /* Check if need to send keyframe. */
+ if (stream->num_keyframe) {
+ unsigned elapse_time;
+ pj_timestamp now;
+
+ pj_get_timestamp(&now);
+
+ elapse_time = pj_elapsed_msec(&stream->last_keyframe_tx, &now);
+
+ if (elapse_time > stream->info.sk_cfg.interval)
+ {
+ stream->force_keyframe = PJ_TRUE;
+ if (--stream->num_keyframe)
+ stream->last_keyframe_tx = now;
+ }
+ }
+
/* Init encoding option */
pj_bzero(&enc_opt, sizeof(enc_opt));
if (stream->force_keyframe) {
@@ -1459,6 +1483,7 @@ PJ_DEF(pj_status_t) pjmedia_vid_stream_create(
#if defined(PJMEDIA_STREAM_ENABLE_KA) && PJMEDIA_STREAM_ENABLE_KA!=0
stream->use_ka = info->use_ka;
#endif
+ stream->num_keyframe = info->sk_cfg.count;
/* Build random RTCP CNAME. CNAME has user@host format */
stream->cname.ptr = p = (char*) pj_pool_alloc(pool, 20);
@@ -2009,4 +2034,16 @@ pjmedia_vid_stream_rc_config_default(pjmedia_vid_stream_rc_config *cfg)
}
+/*
+ * Initialize the video stream send keyframe with default settings.
+ */
+PJ_DEF(void)
+pjmedia_vid_stream_sk_config_default(pjmedia_vid_stream_sk_config *cfg)
+{
+ pj_bzero(cfg, sizeof(*cfg));
+ cfg->count = PJMEDIA_VID_STREAM_START_KEYFRAME_CNT;
+ cfg->interval = PJMEDIA_VID_STREAM_START_KEYFRAME_INTERVAL_MSEC;
+}
+
+
#endif /* PJMEDIA_HAS_VIDEO */
diff --git a/pjsip/include/pjsua-lib/pjsua.h b/pjsip/include/pjsua-lib/pjsua.h
index e75636ca..279ede7f 100644
--- a/pjsip/include/pjsua-lib/pjsua.h
+++ b/pjsip/include/pjsua-lib/pjsua.h
@@ -3306,6 +3306,13 @@ typedef struct pjsua_acc_config
pjmedia_vid_stream_rc_config vid_stream_rc_cfg;
/**
+ * Specify the send keyframe config for video stream.
+ *
+ * Default: see #pjmedia_vid_stream_sk_config
+ */
+ pjmedia_vid_stream_sk_config vid_stream_sk_cfg;
+
+ /**
* Media transport config.
*/
pjsua_transport_config rtp_cfg;
diff --git a/pjsip/include/pjsua2/account.hpp b/pjsip/include/pjsua2/account.hpp
index acb78165..fedfa595 100644
--- a/pjsip/include/pjsua2/account.hpp
+++ b/pjsip/include/pjsua2/account.hpp
@@ -831,6 +831,21 @@ struct AccountVideoConfig : public PersistentObject
*/
unsigned rateControlBandwidth;
+ /**
+ * The number of keyframe to be sent after the stream is created.
+ *
+ * Default: PJMEDIA_VID_STREAM_START_KEYFRAME_CNT
+ */
+ unsigned startKeyframeCount;
+
+ /**
+ * The keyframe sending interval after the stream is created.
+ *
+ * Default: PJMEDIA_VID_STREAM_START_KEYFRAME_INTERVAL_MSEC
+ */
+ unsigned startKeyframeInterval;
+
+
public:
/**
* Read this object from a container node.
diff --git a/pjsip/src/pjsua-lib/pjsua_core.c b/pjsip/src/pjsua-lib/pjsua_core.c
index e3bc4e9f..7725be81 100644
--- a/pjsip/src/pjsua-lib/pjsua_core.c
+++ b/pjsip/src/pjsua-lib/pjsua_core.c
@@ -277,6 +277,7 @@ PJ_DEF(void) pjsua_acc_config_default(pjsua_acc_config *cfg)
cfg->vid_rend_dev = PJMEDIA_VID_DEFAULT_RENDER_DEV;
#if PJMEDIA_HAS_VIDEO
pjmedia_vid_stream_rc_config_default(&cfg->vid_stream_rc_cfg);
+ pjmedia_vid_stream_sk_config_default(&cfg->vid_stream_sk_cfg);
#endif
pjsua_transport_config_default(&cfg->rtp_cfg);
diff --git a/pjsip/src/pjsua-lib/pjsua_vid.c b/pjsip/src/pjsua-lib/pjsua_vid.c
index 42506b84..ed3e94e8 100644
--- a/pjsip/src/pjsua-lib/pjsua_vid.c
+++ b/pjsip/src/pjsua-lib/pjsua_vid.c
@@ -911,6 +911,9 @@ pj_status_t pjsua_vid_channel_update(pjsua_call_media *call_med,
/* Set rate control config from account setting */
si->rc_cfg = acc->cfg.vid_stream_rc_cfg;
+ /* Set send keyframe config from account setting */
+ si->sk_cfg = acc->cfg.vid_stream_sk_cfg;
+
#if defined(PJMEDIA_STREAM_ENABLE_KA) && PJMEDIA_STREAM_ENABLE_KA!=0
/* Enable/disable stream keep-alive and NAT hole punch. */
si->use_ka = pjsua_var.acc[call->acc_id].cfg.use_stream_ka;
diff --git a/pjsip/src/pjsua2/account.cpp b/pjsip/src/pjsua2/account.cpp
index 2160afa4..d36affeb 100644
--- a/pjsip/src/pjsua2/account.cpp
+++ b/pjsip/src/pjsua2/account.cpp
@@ -277,6 +277,8 @@ void AccountVideoConfig::readObject(const ContainerNode &node) throw(Error)
NODE_READ_NUM_T ( this_node, pjmedia_vid_dev_index, defaultRenderDevice);
NODE_READ_NUM_T ( this_node, pjmedia_vid_stream_rc_method, rateControlMethod);
NODE_READ_UNSIGNED( this_node, rateControlBandwidth);
+ NODE_READ_UNSIGNED( this_node, startKeyframeCount);
+ NODE_READ_UNSIGNED( this_node, startKeyframeInterval);
}
void AccountVideoConfig::writeObject(ContainerNode &node) const throw(Error)
@@ -290,6 +292,8 @@ void AccountVideoConfig::writeObject(ContainerNode &node) const throw(Error)
NODE_WRITE_NUM_T ( this_node, pjmedia_vid_dev_index, defaultRenderDevice);
NODE_WRITE_NUM_T ( this_node, pjmedia_vid_stream_rc_method, rateControlMethod);
NODE_WRITE_UNSIGNED( this_node, rateControlBandwidth);
+ NODE_WRITE_UNSIGNED( this_node, startKeyframeCount);
+ NODE_WRITE_UNSIGNED( this_node, startKeyframeInterval);
}
///////////////////////////////////////////////////////////////////////////////
@@ -433,6 +437,8 @@ void AccountConfig::toPj(pjsua_acc_config &ret) const
ret.vid_rend_dev = videoConfig.defaultRenderDevice;
ret.vid_stream_rc_cfg.method= videoConfig.rateControlMethod;
ret.vid_stream_rc_cfg.bandwidth = videoConfig.rateControlBandwidth;
+ ret.vid_stream_sk_cfg.count = videoConfig.startKeyframeCount;
+ ret.vid_stream_sk_cfg.interval = videoConfig.startKeyframeInterval;
}
/* Initialize from pjsip. */
@@ -598,6 +604,8 @@ void AccountConfig::fromPj(const pjsua_acc_config &prm,
videoConfig.defaultRenderDevice = prm.vid_rend_dev;
videoConfig.rateControlMethod = prm.vid_stream_rc_cfg.method;
videoConfig.rateControlBandwidth = prm.vid_stream_rc_cfg.bandwidth;
+ videoConfig.startKeyframeCount = prm.vid_stream_sk_cfg.count;
+ videoConfig.startKeyframeInterval = prm.vid_stream_sk_cfg.interval;
}
void AccountConfig::readObject(const ContainerNode &node) throw(Error)