mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-17 03:35:21 +00:00
rtponviftimestamp: use stream time for timestamp
The Onvif Streaming Specification specifies that the NTP timestamps in the Onvif extension header indicaes the absolute UTC time associated with the access unit. But by using running time we can not achieve that, since a frame's running time depends on the played interval, whether a non-flushing is done, etc. Instead we have to use the stream time. https://bugzilla.gnome.org/show_bug.cgi?id=757688
This commit is contained in:
parent
6f6fe37ed9
commit
4c482befbd
2 changed files with 81 additions and 5 deletions
|
@ -499,10 +499,10 @@ handle_buffer (GstRtpOnvifTimestamp * self, GstBuffer * buf)
|
|||
|
||||
/* NTP timestamp */
|
||||
if (GST_BUFFER_DTS_IS_VALID (buf)) {
|
||||
time = gst_segment_to_running_time (&self->segment, GST_FORMAT_TIME,
|
||||
time = gst_segment_to_stream_time (&self->segment, GST_FORMAT_TIME,
|
||||
GST_BUFFER_DTS (buf));
|
||||
} else if (GST_BUFFER_PTS_IS_VALID (buf)) {
|
||||
time = gst_segment_to_running_time (&self->segment, GST_FORMAT_TIME,
|
||||
time = gst_segment_to_stream_time (&self->segment, GST_FORMAT_TIME,
|
||||
GST_BUFFER_PTS (buf));
|
||||
} else {
|
||||
GST_ERROR_OBJECT (self,
|
||||
|
@ -511,7 +511,7 @@ handle_buffer (GstRtpOnvifTimestamp * self, GstBuffer * buf)
|
|||
}
|
||||
|
||||
if (time == GST_CLOCK_TIME_NONE) {
|
||||
GST_ERROR_OBJECT (self, "Failed to get running time");
|
||||
GST_ERROR_OBJECT (self, "Failed to get stream time");
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ event_probe (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
|
|||
{
|
||||
GstEvent *event = GST_PAD_PROBE_INFO_EVENT (info);
|
||||
|
||||
GST_DEBUG ("got %s", GST_EVENT_TYPE_NAME (event));
|
||||
GST_INFO ("got %" GST_PTR_FORMAT, event);
|
||||
myreceivedevents = g_list_append (myreceivedevents, gst_event_ref (event));
|
||||
|
||||
return GST_PAD_PROBE_OK;
|
||||
|
@ -679,13 +679,88 @@ GST_START_TEST (test_non_serialized_events)
|
|||
|
||||
GST_END_TEST;
|
||||
|
||||
static void
|
||||
do_ntp_time (GstClockTime buffer_time, gint segment_start, gint segment_base)
|
||||
{
|
||||
GstSegment segment;
|
||||
GstBuffer *buffer;
|
||||
GstRTPBuffer rtpbuffer = GST_RTP_BUFFER_INIT;
|
||||
guint8 *data;
|
||||
guint64 expected_ntp_time;
|
||||
guint64 timestamp;
|
||||
|
||||
/* create a segment that controls the behavior
|
||||
* by changing segment.start and segment.base we affect the stream time and
|
||||
* running time respectively */
|
||||
gst_segment_init (&segment, GST_FORMAT_TIME);
|
||||
segment.start = segment_start;
|
||||
segment.base = segment_base;
|
||||
gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment));
|
||||
|
||||
expected_ntp_time = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME,
|
||||
buffer_time);
|
||||
expected_ntp_time += NTP_OFFSET;
|
||||
expected_ntp_time = gst_util_uint64_scale (expected_ntp_time,
|
||||
(G_GINT64_CONSTANT (1) << 32), GST_SECOND);
|
||||
|
||||
buffer = create_rtp_buffer (buffer_time, FALSE);
|
||||
fail_unless_equals_int (gst_pad_push (mysrcpad, buffer), GST_FLOW_OK);
|
||||
fail_unless_equals_int (g_list_length (buffers), 1);
|
||||
|
||||
buffer = g_list_last (buffers)->data;
|
||||
|
||||
/* get the extension header */
|
||||
fail_unless (gst_rtp_buffer_map (buffer, GST_MAP_READWRITE, &rtpbuffer));
|
||||
fail_unless (gst_rtp_buffer_get_extension_data (&rtpbuffer, NULL,
|
||||
(gpointer) & data, NULL));
|
||||
|
||||
/* ...and read the NTP timestamp and verify that it's the expected one */
|
||||
timestamp = GST_READ_UINT64_BE (data);
|
||||
fail_unless_equals_uint64 (timestamp, expected_ntp_time);
|
||||
|
||||
gst_rtp_buffer_unmap (&rtpbuffer);
|
||||
gst_check_drop_buffers ();
|
||||
}
|
||||
|
||||
GST_START_TEST (test_ntp_time)
|
||||
{
|
||||
/* we do not need buffer caching, so do not set the e-bit */
|
||||
g_object_set (element, "set-e-bit", FALSE, NULL);
|
||||
/* set an ntp offset suitable for testing */
|
||||
g_object_set (element, "ntp-offset", NTP_OFFSET, NULL);
|
||||
|
||||
ASSERT_SET_STATE (element, GST_STATE_PLAYING, GST_STATE_CHANGE_SUCCESS);
|
||||
|
||||
/* push initial events */
|
||||
gst_check_setup_events (mysrcpad, element, NULL, GST_FORMAT_TIME);
|
||||
|
||||
/* first test with a "clean" segment */
|
||||
do_ntp_time (GST_MSECOND, 0, 0);
|
||||
do_ntp_time (GST_SECOND + GST_MSECOND, 0, 0);
|
||||
|
||||
/* verify that changing the running time does not affect the ntp time stamps */
|
||||
do_ntp_time (GST_MSECOND, 0, GST_SECOND);
|
||||
do_ntp_time (GST_SECOND + GST_MSECOND, 0, GST_SECOND);
|
||||
|
||||
/* changing the segment.start affects the stream time, verify that the element
|
||||
* handles it correctly */
|
||||
do_ntp_time (GST_MSECOND, GST_MSECOND / 2, 0);
|
||||
do_ntp_time (GST_SECOND + GST_MSECOND, GST_MSECOND / 2, 0);
|
||||
|
||||
/* and finally change both of them and verify that all's fine */
|
||||
do_ntp_time (GST_MSECOND, GST_MSECOND / 2, GST_SECOND);
|
||||
do_ntp_time (GST_SECOND + GST_MSECOND, GST_MSECOND / 2, GST_SECOND);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
static Suite *
|
||||
onviftimestamp_suite (void)
|
||||
{
|
||||
Suite *s = suite_create ("onviftimestamp");
|
||||
TCase *tc_general, *tc_events;
|
||||
|
||||
tc_general = tcase_create ("apply");
|
||||
tc_general = tcase_create ("general");
|
||||
suite_add_tcase (s, tc_general);
|
||||
tcase_add_checked_fixture (tc_general, setup, cleanup);
|
||||
|
||||
|
@ -696,6 +771,7 @@ onviftimestamp_suite (void)
|
|||
tcase_add_test (tc_general, test_reusable_element_no_e_bit);
|
||||
tcase_add_test (tc_general, test_reusable_element_e_bit);
|
||||
tcase_add_test (tc_general, test_ntp_offset_event);
|
||||
tcase_add_test (tc_general, test_ntp_time);
|
||||
|
||||
tc_events = tcase_create ("events");
|
||||
suite_add_tcase (s, tc_events);
|
||||
|
|
Loading…
Reference in a new issue