mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-30 19:18:31 +00:00
gst/rtpmanager/gstrtpsession.*: Distribute synchronisation parameters to the session manager so that it can generate ...
Original commit message from CVS: * gst/rtpmanager/gstrtpsession.c: (stop_rtcp_thread), (gst_rtp_session_change_state), (gst_rtp_session_event_send_rtp_sink): * gst/rtpmanager/gstrtpsession.h: Distribute synchronisation parameters to the session manager so that it can generate correct SR packets for lip-sync. * gst/rtpmanager/rtpsession.c: (rtp_session_set_base_time), (rtp_session_set_timestamp_sync), (session_start_rtcp): * gst/rtpmanager/rtpsession.h: Add methods for setting sync parameters. Set correct RTP time in SR packets using the sync params. * gst/rtpmanager/rtpsource.c: (rtp_source_send_rtp): * gst/rtpmanager/rtpsource.h: Record last RTP <-> GST timestamp so that we can use them to convert NTP to RTP timestamps in SR packets.
This commit is contained in:
parent
c0a64d008a
commit
9f597336b5
7 changed files with 165 additions and 8 deletions
20
ChangeLog
20
ChangeLog
|
@ -1,3 +1,23 @@
|
||||||
|
2007-08-28 Wim Taymans <wim.taymans@gmail.com>
|
||||||
|
|
||||||
|
* gst/rtpmanager/gstrtpsession.c: (stop_rtcp_thread),
|
||||||
|
(gst_rtp_session_change_state),
|
||||||
|
(gst_rtp_session_event_send_rtp_sink):
|
||||||
|
* gst/rtpmanager/gstrtpsession.h:
|
||||||
|
Distribute synchronisation parameters to the session manager so that it
|
||||||
|
can generate correct SR packets for lip-sync.
|
||||||
|
|
||||||
|
* gst/rtpmanager/rtpsession.c: (rtp_session_set_base_time),
|
||||||
|
(rtp_session_set_timestamp_sync), (session_start_rtcp):
|
||||||
|
* gst/rtpmanager/rtpsession.h:
|
||||||
|
Add methods for setting sync parameters.
|
||||||
|
Set correct RTP time in SR packets using the sync params.
|
||||||
|
|
||||||
|
* gst/rtpmanager/rtpsource.c: (rtp_source_send_rtp):
|
||||||
|
* gst/rtpmanager/rtpsource.h:
|
||||||
|
Record last RTP <-> GST timestamp so that we can use them to convert NTP
|
||||||
|
to RTP timestamps in SR packets.
|
||||||
|
|
||||||
2007-08-28 Wim Taymans <wim.taymans@gmail.com>
|
2007-08-28 Wim Taymans <wim.taymans@gmail.com>
|
||||||
|
|
||||||
* gst/rtpmanager/gstrtpbin.c: (gst_rtp_bin_clear_pt_map):
|
* gst/rtpmanager/gstrtpbin.c: (gst_rtp_bin_clear_pt_map):
|
||||||
|
|
|
@ -648,8 +648,10 @@ gst_rtp_session_change_state (GstElement * element, GstStateChange transition)
|
||||||
{
|
{
|
||||||
GstStateChangeReturn res;
|
GstStateChangeReturn res;
|
||||||
GstRtpSession *rtpsession;
|
GstRtpSession *rtpsession;
|
||||||
|
GstRtpSessionPrivate *priv;
|
||||||
|
|
||||||
rtpsession = GST_RTP_SESSION (element);
|
rtpsession = GST_RTP_SESSION (element);
|
||||||
|
priv = rtpsession->priv;
|
||||||
|
|
||||||
switch (transition) {
|
switch (transition) {
|
||||||
case GST_STATE_CHANGE_NULL_TO_READY:
|
case GST_STATE_CHANGE_NULL_TO_READY:
|
||||||
|
@ -660,6 +662,7 @@ gst_rtp_session_change_state (GstElement * element, GstStateChange transition)
|
||||||
break;
|
break;
|
||||||
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
|
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
|
||||||
stop_rtcp_thread (rtpsession);
|
stop_rtcp_thread (rtpsession);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -668,9 +671,17 @@ gst_rtp_session_change_state (GstElement * element, GstStateChange transition)
|
||||||
|
|
||||||
switch (transition) {
|
switch (transition) {
|
||||||
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
|
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
|
||||||
|
{
|
||||||
|
GstClockTime base_time;
|
||||||
|
|
||||||
|
base_time = GST_ELEMENT_CAST (rtpsession)->base_time;
|
||||||
|
|
||||||
|
rtp_session_set_base_time (priv->session, base_time);
|
||||||
|
|
||||||
if (!start_rtcp_thread (rtpsession))
|
if (!start_rtcp_thread (rtpsession))
|
||||||
goto failed_thread;
|
goto failed_thread;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
|
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
|
||||||
break;
|
break;
|
||||||
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
||||||
|
@ -960,6 +971,40 @@ gst_rtp_session_event_send_rtp_sink (GstPad * pad, GstEvent * event)
|
||||||
GST_DEBUG_OBJECT (rtpsession, "received event");
|
GST_DEBUG_OBJECT (rtpsession, "received event");
|
||||||
|
|
||||||
switch (GST_EVENT_TYPE (event)) {
|
switch (GST_EVENT_TYPE (event)) {
|
||||||
|
case GST_EVENT_NEWSEGMENT:
|
||||||
|
{
|
||||||
|
gboolean update;
|
||||||
|
gdouble rate, arate;
|
||||||
|
GstFormat format;
|
||||||
|
gint64 start, stop, time;
|
||||||
|
GstSegment *segment;
|
||||||
|
|
||||||
|
segment = &rtpsession->send_rtp_seg;
|
||||||
|
|
||||||
|
/* the newsegment event is needed to convert the RTP timestamp to
|
||||||
|
* running_time, which is needed to generate a mapping from RTP to NTP
|
||||||
|
* timestamps in SR reports */
|
||||||
|
gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
|
||||||
|
&start, &stop, &time);
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (rtpsession,
|
||||||
|
"configured NEWSEGMENT update %d, rate %lf, applied rate %lf, "
|
||||||
|
"format GST_FORMAT_TIME, "
|
||||||
|
"%" GST_TIME_FORMAT " -- %" GST_TIME_FORMAT
|
||||||
|
", time %" GST_TIME_FORMAT ", accum %" GST_TIME_FORMAT,
|
||||||
|
update, rate, arate, GST_TIME_ARGS (segment->start),
|
||||||
|
GST_TIME_ARGS (segment->stop), GST_TIME_ARGS (segment->time),
|
||||||
|
GST_TIME_ARGS (segment->accum));
|
||||||
|
|
||||||
|
gst_segment_set_newsegment_full (segment, update, rate,
|
||||||
|
arate, format, start, stop, time);
|
||||||
|
|
||||||
|
rtp_session_set_timestamp_sync (priv->session, start);
|
||||||
|
|
||||||
|
/* push event forward */
|
||||||
|
ret = gst_pad_push_event (rtpsession->send_rtp_src, event);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
ret = gst_pad_push_event (rtpsession->send_rtp_src, event);
|
ret = gst_pad_push_event (rtpsession->send_rtp_src, event);
|
||||||
break;
|
break;
|
||||||
|
@ -991,7 +1036,6 @@ gst_rtp_session_chain_send_rtp (GstPad * pad, GstBuffer * buffer)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Create sinkpad to receive RTP packets from senders. This will also create a
|
/* Create sinkpad to receive RTP packets from senders. This will also create a
|
||||||
* srcpad for the RTP packets.
|
* srcpad for the RTP packets.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -45,6 +45,7 @@ struct _GstRtpSession {
|
||||||
GstPad *recv_rtp_sink;
|
GstPad *recv_rtp_sink;
|
||||||
GstPad *recv_rtcp_sink;
|
GstPad *recv_rtcp_sink;
|
||||||
GstPad *send_rtp_sink;
|
GstPad *send_rtp_sink;
|
||||||
|
GstSegment send_rtp_seg;
|
||||||
|
|
||||||
GstPad *recv_rtp_src;
|
GstPad *recv_rtp_src;
|
||||||
GstPad *sync_src;
|
GstPad *sync_src;
|
||||||
|
|
|
@ -1048,8 +1048,8 @@ ignore:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* A Sender report contains statistics about how the sender is doing. This
|
/* A Sender report contains statistics about how the sender is doing. This
|
||||||
* includes timing informataion about the relation between RTP and NTP
|
* includes timing informataion such as the relation between RTP and NTP
|
||||||
* timestamps is it using and the number of packets/bytes it sent to us.
|
* timestamps and the number of packets/bytes it sent to us.
|
||||||
*
|
*
|
||||||
* In this report is also included a set of report blocks related to how this
|
* In this report is also included a set of report blocks related to how this
|
||||||
* sender is receiving data (in case we (or somebody else) is also sending stuff
|
* sender is receiving data (in case we (or somebody else) is also sending stuff
|
||||||
|
@ -1429,6 +1429,36 @@ invalid_packet:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* rtp_session_set_send_sync
|
||||||
|
* @sess: an #RTPSession
|
||||||
|
* @base_time: the clock base time
|
||||||
|
* @start_time: the timestamp start time
|
||||||
|
*
|
||||||
|
* Establish a relation between the times returned by the get_time callback and
|
||||||
|
* the buffer timestamps. This information is used to convert the NTP times to
|
||||||
|
* RTP timestamps.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
rtp_session_set_base_time (RTPSession * sess, GstClockTime base_time)
|
||||||
|
{
|
||||||
|
g_return_if_fail (RTP_IS_SESSION (sess));
|
||||||
|
|
||||||
|
RTP_SESSION_LOCK (sess);
|
||||||
|
sess->base_time = base_time;
|
||||||
|
RTP_SESSION_UNLOCK (sess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rtp_session_set_timestamp_sync (RTPSession * sess, GstClockTime start_timestamp)
|
||||||
|
{
|
||||||
|
g_return_if_fail (RTP_IS_SESSION (sess));
|
||||||
|
|
||||||
|
RTP_SESSION_LOCK (sess);
|
||||||
|
sess->start_timestamp = start_timestamp;
|
||||||
|
RTP_SESSION_UNLOCK (sess);
|
||||||
|
}
|
||||||
|
|
||||||
static GstClockTime
|
static GstClockTime
|
||||||
calculate_rtcp_interval (RTPSession * sess, gboolean deterministic,
|
calculate_rtcp_interval (RTPSession * sess, gboolean deterministic,
|
||||||
gboolean first)
|
gboolean first)
|
||||||
|
@ -1575,16 +1605,56 @@ session_start_rtcp (RTPSession * sess, ReportData * data)
|
||||||
if (RTP_SOURCE_IS_SENDER (own)) {
|
if (RTP_SOURCE_IS_SENDER (own)) {
|
||||||
guint64 ntptime;
|
guint64 ntptime;
|
||||||
guint32 rtptime;
|
guint32 rtptime;
|
||||||
|
GstClockTime running_time;
|
||||||
|
GstClockTimeDiff diff;
|
||||||
|
|
||||||
/* we are a sender, create SR */
|
/* we are a sender, create SR */
|
||||||
GST_DEBUG ("create SR for SSRC %08x", own->ssrc);
|
GST_DEBUG ("create SR for SSRC %08x", own->ssrc);
|
||||||
gst_rtcp_buffer_add_packet (data->rtcp, GST_RTCP_TYPE_SR, packet);
|
gst_rtcp_buffer_add_packet (data->rtcp, GST_RTCP_TYPE_SR, packet);
|
||||||
|
|
||||||
/* convert clock time to NTP time */
|
/* use the sync params to interpollate the date->time member to rtptime. We
|
||||||
|
* use the last sent timestamp and rtptime as reference points. We assume
|
||||||
|
* that the slope of the rtptime vs timestamp curve is 1, which is certainly
|
||||||
|
* sufficient for the frequency at which we report SR and the rate we send
|
||||||
|
* out RTP packets. */
|
||||||
|
rtptime = own->last_rtptime;
|
||||||
|
GST_DEBUG ("last_timestamp %" GST_TIME_FORMAT ", last_rtptime %"
|
||||||
|
G_GUINT32_FORMAT, GST_TIME_ARGS (own->last_timestamp), rtptime);
|
||||||
|
|
||||||
|
if (own->clock_rate != -1) {
|
||||||
|
/* Start by calculating the running_time of the timestamp, this is a result
|
||||||
|
* in nanoseconds. */
|
||||||
|
running_time =
|
||||||
|
(own->last_timestamp - sess->start_timestamp) + sess->base_time;
|
||||||
|
|
||||||
|
/* get the diff with the SR time */
|
||||||
|
diff = GST_CLOCK_DIFF (running_time, data->time);
|
||||||
|
|
||||||
|
/* now translate the diff to RTP time, handle positive and negative cases.
|
||||||
|
* If there is no diff, we already set rtptime correctly above. */
|
||||||
|
if (diff > 0) {
|
||||||
|
GST_DEBUG ("running_time %" GST_TIME_FORMAT ", diff %" GST_TIME_FORMAT,
|
||||||
|
GST_TIME_ARGS (running_time), GST_TIME_ARGS (diff));
|
||||||
|
rtptime += gst_util_uint64_scale (diff, own->clock_rate, GST_SECOND);
|
||||||
|
} else {
|
||||||
|
diff = -diff;
|
||||||
|
GST_DEBUG ("running_time %" GST_TIME_FORMAT ", diff -%" GST_TIME_FORMAT,
|
||||||
|
GST_TIME_ARGS (running_time), GST_TIME_ARGS (diff));
|
||||||
|
rtptime -= gst_util_uint64_scale (diff, own->clock_rate, GST_SECOND);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
GST_WARNING ("no clock-rate, cannot interpollate rtp time");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* convert clock time to NTP time. upper 32 bits should contain the seconds
|
||||||
|
* and the lower 32 bits, the fractions of a second. */
|
||||||
ntptime = gst_util_uint64_scale (data->time, (1LL << 32), GST_SECOND);
|
ntptime = gst_util_uint64_scale (data->time, (1LL << 32), GST_SECOND);
|
||||||
|
/* conversion from unix timestamp (seconds since 1970) to NTP (seconds
|
||||||
|
* since 1900). FIXME nothing says that the time is in unix timestamps. */
|
||||||
ntptime += (2208988800LL << 32);
|
ntptime += (2208988800LL << 32);
|
||||||
|
|
||||||
rtptime = 0;
|
GST_DEBUG ("NTP %08x:%08x, RTP %" G_GUINT32_FORMAT,
|
||||||
|
(guint32) (ntptime >> 32), (guint32) (ntptime & 0xffffffff), rtptime);
|
||||||
|
|
||||||
/* fill in sender report info, FIXME RTP timestamps missing */
|
/* fill in sender report info, FIXME RTP timestamps missing */
|
||||||
gst_rtcp_packet_sr_set_sender_info (packet, own->ssrc,
|
gst_rtcp_packet_sr_set_sender_info (packet, own->ssrc,
|
||||||
|
|
|
@ -189,6 +189,10 @@ struct _RTPSession {
|
||||||
gpointer user_data;
|
gpointer user_data;
|
||||||
|
|
||||||
RTPSessionStats stats;
|
RTPSessionStats stats;
|
||||||
|
|
||||||
|
/* for mapping RTP time to NTP time */
|
||||||
|
GstClockTime start_timestamp;
|
||||||
|
GstClockTime base_time;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -251,7 +255,8 @@ GstFlowReturn rtp_session_process_rtcp (RTPSession *sess, GstBuffer
|
||||||
|
|
||||||
/* processing packets for sending */
|
/* processing packets for sending */
|
||||||
GstFlowReturn rtp_session_send_rtp (RTPSession *sess, GstBuffer *buffer);
|
GstFlowReturn rtp_session_send_rtp (RTPSession *sess, GstBuffer *buffer);
|
||||||
|
void rtp_session_set_base_time (RTPSession *sess, GstClockTime base_time);
|
||||||
|
void rtp_session_set_timestamp_sync (RTPSession *sess, GstClockTime start_timestamp);
|
||||||
/* stopping the session */
|
/* stopping the session */
|
||||||
GstFlowReturn rtp_session_send_bye (RTPSession *sess, const gchar *reason);
|
GstFlowReturn rtp_session_send_bye (RTPSession *sess, const gchar *reason);
|
||||||
|
|
||||||
|
|
|
@ -456,6 +456,7 @@ rtp_source_send_rtp (RTPSource * src, GstBuffer * buffer)
|
||||||
{
|
{
|
||||||
GstFlowReturn result = GST_FLOW_OK;
|
GstFlowReturn result = GST_FLOW_OK;
|
||||||
guint len;
|
guint len;
|
||||||
|
GstClockTime timestamp;
|
||||||
|
|
||||||
g_return_val_if_fail (RTP_IS_SOURCE (src), GST_FLOW_ERROR);
|
g_return_val_if_fail (RTP_IS_SOURCE (src), GST_FLOW_ERROR);
|
||||||
g_return_val_if_fail (GST_IS_BUFFER (buffer), GST_FLOW_ERROR);
|
g_return_val_if_fail (GST_IS_BUFFER (buffer), GST_FLOW_ERROR);
|
||||||
|
@ -469,18 +470,32 @@ rtp_source_send_rtp (RTPSource * src, GstBuffer * buffer)
|
||||||
src->stats.packets_sent++;
|
src->stats.packets_sent++;
|
||||||
src->stats.octets_sent += len;
|
src->stats.octets_sent += len;
|
||||||
|
|
||||||
|
/* we keep track of the last received RTP timestamp and the corresponding
|
||||||
|
* GStreamer timestamp so that we can convert NTP time to RTP time when
|
||||||
|
* sending SR reports */
|
||||||
|
src->last_rtptime = gst_rtp_buffer_get_timestamp (buffer);
|
||||||
|
|
||||||
|
/* the timestamp can be undefined, in that case we use any previously
|
||||||
|
* received timestamp */
|
||||||
|
timestamp = GST_BUFFER_TIMESTAMP (buffer);
|
||||||
|
if (timestamp != -1)
|
||||||
|
src->last_timestamp = timestamp;
|
||||||
|
|
||||||
/* push packet */
|
/* push packet */
|
||||||
if (src->callbacks.push_rtp) {
|
if (src->callbacks.push_rtp) {
|
||||||
guint32 ssrc;
|
guint32 ssrc;
|
||||||
|
|
||||||
ssrc = gst_rtp_buffer_get_ssrc (buffer);
|
ssrc = gst_rtp_buffer_get_ssrc (buffer);
|
||||||
if (ssrc != src->ssrc) {
|
if (ssrc != src->ssrc) {
|
||||||
GST_DEBUG ("updating SSRC from %u to %u", ssrc, src->ssrc);
|
/* the SSRC of the packet is not correct, make a writable buffer and
|
||||||
|
* update the SSRC. This could involve a complete copy of the packet when
|
||||||
|
* it is not writable. Usually the payloader will use caps negotiation to
|
||||||
|
* get the correct SSRC. */
|
||||||
buffer = gst_buffer_make_writable (buffer);
|
buffer = gst_buffer_make_writable (buffer);
|
||||||
|
|
||||||
|
GST_DEBUG ("updating SSRC from %u to %u", ssrc, src->ssrc);
|
||||||
gst_rtp_buffer_set_ssrc (buffer, src->ssrc);
|
gst_rtp_buffer_set_ssrc (buffer, src->ssrc);
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_DEBUG ("pushing RTP packet %" G_GUINT64_FORMAT,
|
GST_DEBUG ("pushing RTP packet %" G_GUINT64_FORMAT,
|
||||||
src->stats.packets_sent);
|
src->stats.packets_sent);
|
||||||
result = src->callbacks.push_rtp (src, buffer, src->user_data);
|
result = src->callbacks.push_rtp (src, buffer, src->user_data);
|
||||||
|
|
|
@ -139,6 +139,8 @@ struct _RTPSource {
|
||||||
GstClockTime bye_time;
|
GstClockTime bye_time;
|
||||||
GstClockTime last_activity;
|
GstClockTime last_activity;
|
||||||
GstClockTime last_rtp_activity;
|
GstClockTime last_rtp_activity;
|
||||||
|
GstClockTime last_timestamp;
|
||||||
|
GstClockTime last_rtptime;
|
||||||
|
|
||||||
GQueue *packets;
|
GQueue *packets;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue