rtponviftimestamp: Automatically discover the ntp-offset by default.

This only works if no packets are pushed in before the pipeline goes
to playing. So it helps to have a live source.

https://bugzilla.gnome.org/show_bug.cgi?id=731769
This commit is contained in:
Olivier Crête 2014-11-17 19:26:53 -05:00
parent 189005184c
commit 8cddfe6477
3 changed files with 60 additions and 8 deletions

View file

@ -30,7 +30,7 @@
#include "gstrtponviftimestamp.h"
#define DEFAULT_NTP_OFFSET 0
#define DEFAULT_NTP_OFFSET GST_CLOCK_TIME_NONE
#define DEFAULT_CSEQ 0
#define DEFAULT_SET_E_BIT FALSE
@ -117,6 +117,7 @@ gst_rtp_onvif_timestamp_change_state (GstElement * element,
GstStateChange transition)
{
GstRtpOnvifTimestamp *self = GST_RTP_ONVIF_TIMESTAMP (element);
GstStateChangeReturn ret;
switch (transition) {
case GST_STATE_CHANGE_PAUSED_TO_READY:
@ -126,9 +127,33 @@ gst_rtp_onvif_timestamp_change_state (GstElement * element,
break;
}
return
GST_ELEMENT_CLASS (gst_rtp_onvif_timestamp_parent_class)->change_state
ret = GST_ELEMENT_CLASS (gst_rtp_onvif_timestamp_parent_class)->change_state
(element, transition);
if (ret == GST_STATE_CHANGE_FAILURE)
return ret;
switch (transition) {
case GST_STATE_CHANGE_READY_TO_PAUSED:
if (GST_CLOCK_TIME_IS_VALID (self->prop_ntp_offset))
self->ntp_offset = self->prop_ntp_offset;
else
self->ntp_offset = GST_CLOCK_TIME_NONE;
break;
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
if (!GST_CLOCK_TIME_IS_VALID (self->prop_ntp_offset) &&
GST_ELEMENT_CLOCK (element) == NULL) {
GST_ELEMENT_ERROR (element, CORE, CLOCK, ("Missing NTP offset"),
("Set the \"ntp-offset\" property to,"
" can't guess it without a clock on the pipeline."));
return GST_STATE_CHANGE_FAILURE;
}
break;
default:
break;
}
return ret;
}
static void
@ -160,7 +185,7 @@ gst_rtp_onvif_timestamp_class_init (GstRtpOnvifTimestampClass * klass)
g_object_class_install_property (gobject_class, PROP_NTP_OFFSET,
g_param_spec_uint64 ("ntp-offset", "NTP offset",
"Offset between the pipeline running time and the absolute UTC time, "
"in seconds since 1900",
"in nano-seconds since 1900 (-1 for automatic computation)",
0, G_MAXUINT64,
DEFAULT_NTP_OFFSET, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
@ -273,6 +298,32 @@ handle_buffer (GstRtpOnvifTimestamp * self, GstBuffer * buf,
guint64 time;
guint8 field = 0;
if (!GST_CLOCK_TIME_IS_VALID (self->ntp_offset)) {
GstClock *clock = gst_element_get_clock (GST_ELEMENT (self));
if (clock) {
GstClockTime clock_time = gst_clock_get_time (clock);
guint64 real_time = g_get_real_time ();
GstClockTime running_time = clock_time -
gst_element_get_base_time (GST_ELEMENT (self));
/* convert microseconds to nanoseconds */
real_time *= 1000;
/* add constant to convert from 1970 based time to 1900 based time */
real_time += (G_GUINT64_CONSTANT (2208988800) * GST_SECOND);
self->ntp_offset = real_time - running_time;
gst_object_unref (clock);
} else {
/* Received a buffer in PAUSED, so we can't guess the match
* between the running time and the NTP clock yet.
*/
return TRUE;
}
}
if (self->segment.format != GST_FORMAT_TIME) {
GST_ELEMENT_ERROR (self, STREAM, FAILED,
("did not receive a time segment yet"), (NULL));
@ -319,7 +370,7 @@ handle_buffer (GstRtpOnvifTimestamp * self, GstBuffer * buf,
}
/* add the offset (in seconds) */
time += (self->prop_ntp_offset * GST_SECOND);
time += self->ntp_offset;
/* convert to NTP time. upper 32 bits should contain the seconds
* and the lower 32 bits, the fractions of a second. */

View file

@ -48,10 +48,12 @@ struct _GstRtpOnvifTimestamp {
/* pads */
GstPad *sinkpad,*srcpad;
guint64 prop_ntp_offset;
GstClockTime prop_ntp_offset;
guint prop_cseq;
gboolean prop_set_e_bit;
GstClockTime ntp_offset;
GstSegment segment;
gboolean received_segment;
/* Buffer waiting to be handled, only used if prop_set_e_bit is TRUE */

View file

@ -175,8 +175,7 @@ create_extension_buffer (GstBuffer * buffer_in, gboolean clean_point,
NULL);
/* NTP timestamp */
GST_WRITE_UINT64_BE (data, convert_to_ntp (buffer_in->pts + NTP_OFFSET *
GST_SECOND));
GST_WRITE_UINT64_BE (data, convert_to_ntp (buffer_in->pts + NTP_OFFSET));
/* C E D mbz */
if (clean_point)