diff --git a/gst/onvif/gstrtponviftimestamp.c b/gst/onvif/gstrtponviftimestamp.c index b539c83aa0..a71d0d7bb4 100644 --- a/gst/onvif/gstrtponviftimestamp.c +++ b/gst/onvif/gstrtponviftimestamp.c @@ -30,6 +30,8 @@ #include "gstrtponviftimestamp.h" +#define GST_NTP_OFFSET_EVENT_NAME "GstNtpOffset" + #define DEFAULT_NTP_OFFSET GST_CLOCK_TIME_NONE #define DEFAULT_CSEQ 0 #define DEFAULT_SET_E_BIT FALSE @@ -43,9 +45,9 @@ static GstFlowReturn gst_rtp_onvif_timestamp_chain_list (GstPad * pad, GstObject * parent, GstBufferList * list); static GstFlowReturn handle_and_push_buffer (GstRtpOnvifTimestamp * self, - GstBuffer * buf, gboolean end_contiguous); + GstBuffer * buf); static GstFlowReturn handle_and_push_buffer_list (GstRtpOnvifTimestamp * self, - GstBufferList * list, gboolean end_contiguous); + GstBufferList * list); static GstStaticPadTemplate sink_template_factory = GST_STATIC_PAD_TEMPLATE ("sink", @@ -119,8 +121,7 @@ gst_rtp_onvif_timestamp_set_property (GObject * object, /* send cached buffer or list, and events, if present */ static GstFlowReturn -send_cached_buffer_and_events (GstRtpOnvifTimestamp * self, - gboolean end_contiguous) +send_cached_buffer_and_events (GstRtpOnvifTimestamp * self) { GstFlowReturn ret = GST_FLOW_OK; @@ -128,12 +129,12 @@ send_cached_buffer_and_events (GstRtpOnvifTimestamp * self, if (self->buffer) { GST_DEBUG_OBJECT (self, "pushing %" GST_PTR_FORMAT, self->buffer); - ret = handle_and_push_buffer (self, self->buffer, end_contiguous); + ret = handle_and_push_buffer (self, self->buffer); self->buffer = NULL; } if (self->list) { GST_DEBUG_OBJECT (self, "pushing %" GST_PTR_FORMAT, self->list); - ret = handle_and_push_buffer_list (self, self->list, end_contiguous); + ret = handle_and_push_buffer_list (self, self->list); self->list = NULL; } @@ -200,19 +201,11 @@ gst_rtp_onvif_timestamp_change_state (GstElement * element, 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; - } + self->ntp_offset = self->prop_ntp_offset; + GST_DEBUG_OBJECT (self, "ntp-offset: %" GST_TIME_FORMAT, + GST_TIME_ARGS (self->ntp_offset)); + self->set_d_bit = FALSE; + self->set_e_bit = FALSE; break; default: break; @@ -281,6 +274,32 @@ gst_rtp_onvif_timestamp_class_init (GstRtpOnvifTimestampClass * klass) 0, "ONVIF NTP timestamps RTP extension"); } +static gboolean +parse_event_ntp_offset (GstRtpOnvifTimestamp * self, GstEvent * event, + GstClockTime * offset, gboolean * discont) +{ + const GstStructure *structure = gst_event_get_structure (event); + GstClockTime event_offset; + gboolean event_discont; + + if (!gst_structure_get_clock_time (structure, "ntp-offset", &event_offset)) { + GST_ERROR_OBJECT (self, "no ntp-offset in %" GST_PTR_FORMAT, event); + return FALSE; + } + if (!gst_structure_get_boolean (structure, "discont", &event_discont)) { + GST_ERROR_OBJECT (self, "no discontinue in %" GST_PTR_FORMAT, event); + return FALSE; + } + + if (offset) + *offset = event_offset; + + if (discont) + *discont = event_discont; + + return TRUE; +} + static gboolean gst_rtp_onvif_timestamp_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) @@ -293,11 +312,30 @@ gst_rtp_onvif_timestamp_sink_event (GstPad * pad, GstObject * parent, /* handle serialized events, which, should not be enqueued */ switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_CUSTOM_DOWNSTREAM: + /* if the "set-e-bit" property is set, an offset event might mark the + * stream as discontinued. We need to check if the currently cached buffer + * needs the e-bit before it's pushed */ + if (self->prop_set_e_bit && + gst_event_has_name (event, GST_NTP_OFFSET_EVENT_NAME)) { + gboolean discont; + if (parse_event_ntp_offset (self, event, NULL, &discont)) { + GST_DEBUG_OBJECT (self, "stream %s discontinued", + (discont ? "is" : "is not")); + self->set_e_bit = discont; + } else { + drop = TRUE; + ret = FALSE; + goto out; + } + } + break; case GST_EVENT_EOS: { GstFlowReturn res; /* Push pending buffers, if any */ - res = send_cached_buffer_and_events (self, TRUE); + self->set_e_bit = TRUE; + res = send_cached_buffer_and_events (self); if (res != GST_FLOW_OK) { drop = TRUE; ret = FALSE; @@ -307,6 +345,8 @@ gst_rtp_onvif_timestamp_sink_event (GstPad * pad, GstObject * parent, } case GST_EVENT_FLUSH_STOP: purge_cached_buffer_and_events (self); + self->set_d_bit = FALSE; + self->set_e_bit = FALSE; gst_segment_init (&self->segment, GST_FORMAT_UNDEFINED); break; default: @@ -323,6 +363,25 @@ gst_rtp_onvif_timestamp_sink_event (GstPad * pad, GstObject * parent, /* handle rest of the events */ switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_CUSTOM_DOWNSTREAM: + /* update the ntp-offset after any cached buffer/buffer list has been + * pushed. the d-bit of the next buffer/buffer list should be set if + * the stream is discontinued */ + if (gst_event_has_name (event, GST_NTP_OFFSET_EVENT_NAME)) { + GstClockTime offset; + gboolean discont; + if (parse_event_ntp_offset (self, event, &offset, &discont)) { + GST_DEBUG_OBJECT (self, "new ntp-offset: %" GST_TIME_FORMAT + ", stream %s discontinued", GST_TIME_ARGS (offset), + (discont ? "is" : "is not")); + self->ntp_offset = offset; + self->set_d_bit = discont; + } else { + ret = FALSE; + } + drop = TRUE; + } + break; case GST_EVENT_SEGMENT: gst_event_copy_segment (event, &self->segment); break; @@ -371,8 +430,7 @@ gst_rtp_onvif_timestamp_init (GstRtpOnvifTimestamp * self) #define EXTENSION_SIZE 3 static gboolean -handle_buffer (GstRtpOnvifTimestamp * self, GstBuffer * buf, - gboolean end_contiguous) +handle_buffer (GstRtpOnvifTimestamp * self, GstBuffer * buf) { GstRTPBuffer rtp = GST_RTP_BUFFER_INIT; guint8 *data; @@ -398,12 +456,17 @@ handle_buffer (GstRtpOnvifTimestamp * self, GstBuffer * buf, self->ntp_offset = real_time - running_time; + GST_DEBUG_OBJECT (self, "new ntp-offset: %" GST_TIME_FORMAT, + GST_TIME_ARGS (self->ntp_offset)); + gst_object_unref (clock); } else { + GST_ELEMENT_ERROR (self, STREAM, FAILED, ("No ntp-offset present"), + ("Can not guess ntp-offset with no clock.")); /* Received a buffer in PAUSED, so we can't guess the match * between the running time and the NTP clock yet. */ - return TRUE; + return FALSE; } } @@ -474,15 +537,17 @@ handle_buffer (GstRtpOnvifTimestamp * self, GstBuffer * buf, } /* Set E if the next buffer has DISCONT */ - if (end_contiguous) { + if (self->set_e_bit) { GST_DEBUG_OBJECT (self, "set E flag"); field |= (1 << 6); + self->set_e_bit = FALSE; } /* Set D if the buffer has the DISCONT flag */ - if (GST_BUFFER_IS_DISCONT (buf)) { + if (self->set_d_bit) { GST_DEBUG_OBJECT (self, "set D flag"); field |= (1 << 5); + self->set_d_bit = FALSE; } GST_WRITE_UINT8 (data + 8, field); @@ -499,10 +564,9 @@ done: /* @buf: (transfer full) */ static GstFlowReturn -handle_and_push_buffer (GstRtpOnvifTimestamp * self, GstBuffer * buf, - gboolean end_contiguous) +handle_and_push_buffer (GstRtpOnvifTimestamp * self, GstBuffer * buf) { - if (!handle_buffer (self, buf, end_contiguous)) { + if (!handle_buffer (self, buf)) { gst_buffer_unref (buf); return GST_FLOW_ERROR; } @@ -519,11 +583,11 @@ gst_rtp_onvif_timestamp_chain (GstPad * pad, GstObject * parent, if (!self->prop_set_e_bit) { /* Modify and push this buffer right away */ - return handle_and_push_buffer (self, buf, FALSE); + return handle_and_push_buffer (self, buf); } /* send any previously cached item(s), this leaves an empty queue */ - result = send_cached_buffer_and_events (self, GST_BUFFER_IS_DISCONT (buf)); + result = send_cached_buffer_and_events (self); /* enqueue the new item, as the only item in the queue */ self->buffer = buf; @@ -532,14 +596,13 @@ gst_rtp_onvif_timestamp_chain (GstPad * pad, GstObject * parent, /* @buf: (transfer full) */ static GstFlowReturn -handle_and_push_buffer_list (GstRtpOnvifTimestamp * self, - GstBufferList * list, gboolean end_contiguous) +handle_and_push_buffer_list (GstRtpOnvifTimestamp * self, GstBufferList * list) { GstBuffer *buf; /* Set the extension on the *first* buffer */ buf = gst_buffer_list_get (list, 0); - if (!handle_buffer (self, buf, end_contiguous)) { + if (!handle_buffer (self, buf)) { gst_buffer_list_unref (list); return GST_FLOW_ERROR; } @@ -555,16 +618,14 @@ gst_rtp_onvif_timestamp_chain_list (GstPad * pad, GstObject * parent, GstBufferList * list) { GstRtpOnvifTimestamp *self = GST_RTP_ONVIF_TIMESTAMP (parent); - GstBuffer *buf; GstFlowReturn result = GST_FLOW_OK; if (!self->prop_set_e_bit) { - return handle_and_push_buffer_list (self, list, FALSE); + return handle_and_push_buffer_list (self, list); } /* send any previously cached item(s), this leaves an empty queue */ - buf = gst_buffer_list_get (list, 0); - result = send_cached_buffer_and_events (self, GST_BUFFER_IS_DISCONT (buf)); + result = send_cached_buffer_and_events (self); /* enqueue the new item, as the only item in the queue */ self->list = list; diff --git a/gst/onvif/gstrtponviftimestamp.h b/gst/onvif/gstrtponviftimestamp.h index b8e2b8e3ed..1fb3199968 100644 --- a/gst/onvif/gstrtponviftimestamp.h +++ b/gst/onvif/gstrtponviftimestamp.h @@ -52,7 +52,13 @@ struct _GstRtpOnvifTimestamp { guint prop_cseq; gboolean prop_set_e_bit; + /* currently used ntp-offset + *(can be changed runtime with a GstNtpOffset event) + */ GstClockTime ntp_offset; + /* a GstNtpOffset event might mark the stream as discontinued */ + gboolean set_d_bit; + gboolean set_e_bit; GstSegment segment; /* Buffer waiting to be handled, only used if prop_set_e_bit is TRUE */ diff --git a/tests/check/elements/rtponviftimestamp.c b/tests/check/elements/rtponviftimestamp.c index 077220e627..4ece89526b 100644 --- a/tests/check/elements/rtponviftimestamp.c +++ b/tests/check/elements/rtponviftimestamp.c @@ -46,6 +46,7 @@ static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", #define NTP_OFFSET ((guint64) 1245) #define TIMESTAMP ((GstClockTime)42) +#define CSEQ 0x78 #define COMPARE TRUE #define NO_COMPARE FALSE @@ -60,6 +61,17 @@ event_probe (GstPad * pad, GstPadProbeInfo * info, gpointer user_data) return GST_PAD_PROBE_OK; } +static GstEvent * +create_ntp_offset_event (GstClockTime ntp_offset, gboolean discont) +{ + GstStructure *structure; + + structure = gst_structure_new ("GstNtpOffset", "ntp-offset", G_TYPE_UINT64, + ntp_offset, "discont", G_TYPE_BOOLEAN, discont, NULL); + + return gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, structure); +} + static GstEvent * create_event (GstEventType type) { @@ -204,8 +216,7 @@ check_buffer_equal (GstBuffer * buf, GstBuffer * expected) /* Create a RTP buffer without the extension */ static GstBuffer * -create_rtp_buffer (GstClockTime timestamp, gboolean clean_point, - gboolean discont) +create_rtp_buffer (GstClockTime timestamp, gboolean clean_point) { GstBuffer *buffer_in; GstRTPBuffer rtpbuffer_in = GST_RTP_BUFFER_INIT; @@ -215,8 +226,6 @@ create_rtp_buffer (GstClockTime timestamp, gboolean clean_point, if (!clean_point) GST_BUFFER_FLAG_SET (buffer_in, GST_BUFFER_FLAG_DELTA_UNIT); - if (discont) - GST_BUFFER_FLAG_SET (buffer_in, GST_BUFFER_FLAG_DISCONT); fail_unless (gst_rtp_buffer_map (buffer_in, GST_MAP_READ, &rtpbuffer_in)); fail_if (gst_rtp_buffer_get_extension (&rtpbuffer_in)); @@ -241,7 +250,7 @@ convert_to_ntp (GstClockTime t) /* Create a copy of @buffer_in having the RTP extension */ static GstBuffer * create_extension_buffer (GstBuffer * buffer_in, gboolean clean_point, - gboolean end_contiguous, gboolean discont) + gboolean end_contiguous, gboolean discont, guint64 ntp_offset, guint8 cseq) { GstBuffer *buffer_out; GstRTPBuffer rtpbuffer_out = GST_RTP_BUFFER_INIT; @@ -260,7 +269,8 @@ create_extension_buffer (GstBuffer * buffer_in, gboolean clean_point, (gpointer) & data, NULL)); /* NTP timestamp */ - GST_WRITE_UINT64_BE (data, convert_to_ntp (buffer_in->pts + NTP_OFFSET)); + GST_WRITE_UINT64_BE (data, convert_to_ntp (GST_BUFFER_PTS (buffer_in) + + ntp_offset)); /* C E D mbz */ if (clean_point) @@ -273,7 +283,7 @@ create_extension_buffer (GstBuffer * buffer_in, gboolean clean_point, GST_WRITE_UINT8 (data + 8, flags); /* CSeq */ - GST_WRITE_UINT8 (data + 9, 0x78); + GST_WRITE_UINT8 (data + 9, cseq); memset (data + 10, 0, 4); @@ -283,7 +293,7 @@ create_extension_buffer (GstBuffer * buffer_in, gboolean clean_point, } static void -do_one_buffer_test_apply (gboolean clean_point, gboolean discont) +do_one_buffer_test_apply (gboolean clean_point) { GstBuffer *buffer_in, *buffer_out; @@ -292,8 +302,9 @@ do_one_buffer_test_apply (gboolean clean_point, gboolean discont) ASSERT_SET_STATE (element, GST_STATE_PLAYING, GST_STATE_CHANGE_SUCCESS); - buffer_in = create_rtp_buffer (TIMESTAMP, clean_point, discont); - buffer_out = create_extension_buffer (buffer_in, clean_point, FALSE, discont); + buffer_in = create_rtp_buffer (TIMESTAMP, clean_point); + buffer_out = create_extension_buffer (buffer_in, clean_point, FALSE, FALSE, + NTP_OFFSET, CSEQ); /* push initial events */ gst_check_setup_events (mysrcpad, element, NULL, GST_FORMAT_TIME); @@ -318,24 +329,26 @@ do_two_buffers_test_apply (gboolean end_contiguous) ASSERT_SET_STATE (element, GST_STATE_PLAYING, GST_STATE_CHANGE_SUCCESS); - buffer_in = create_rtp_buffer (TIMESTAMP, FALSE, FALSE); + buffer_in = create_rtp_buffer (TIMESTAMP, FALSE); buffer_out = create_extension_buffer (buffer_in, FALSE, end_contiguous, - FALSE); + FALSE, NTP_OFFSET, CSEQ); /* push initial events */ gst_check_setup_events (mysrcpad, element, NULL, GST_FORMAT_TIME); /* Push buffer */ - fail_unless (gst_pad_push (mysrcpad, buffer_in) == GST_FLOW_OK, - "failed pushing buffer"); + fail_unless_equals_int (gst_pad_push (mysrcpad, buffer_in), GST_FLOW_OK); /* The buffer hasn't been pushed it as the element is waiting for the next * buffer. */ fail_unless_equals_int (g_list_length (buffers), 0); - /* A second buffer is pushed, it has the DISCONT flag if we want that the - * first one has the 'E' bit set. */ - buffer_in = create_rtp_buffer (TIMESTAMP + 1, FALSE, end_contiguous); + /* push an ntp-offset event to trigger a discontinuty */ + fail_unless (gst_pad_push_event (mysrcpad, + create_ntp_offset_event (NTP_OFFSET, end_contiguous))); + + /* A second buffer is pushed */ + buffer_in = create_rtp_buffer (TIMESTAMP + 1, FALSE); fail_unless_equals_int (gst_pad_push (mysrcpad, buffer_in), GST_FLOW_OK); @@ -352,8 +365,9 @@ do_two_buffers_test_apply (gboolean end_contiguous) /* The second buffer has been pushed out */ fail_unless_equals_int (g_list_length (buffers), 2); - /* Latest buffer always has the 'E' flag */ - buffer_out = create_extension_buffer (buffer_in, FALSE, TRUE, end_contiguous); + /* Last buffer always has the 'E' flag */ + buffer_out = create_extension_buffer (buffer_in, FALSE, TRUE, end_contiguous, + NTP_OFFSET, CSEQ); node = g_list_last (buffers); check_buffer_equal ((GstBuffer *) node->data, buffer_out); gst_buffer_unref (buffer_out); @@ -361,23 +375,9 @@ do_two_buffers_test_apply (gboolean end_contiguous) ASSERT_SET_STATE (element, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS); } -GST_START_TEST (test_apply_discont) -{ - do_one_buffer_test_apply (FALSE, TRUE); -} - -GST_END_TEST; - -GST_START_TEST (test_apply_not_discont) -{ - do_one_buffer_test_apply (FALSE, FALSE); -} - -GST_END_TEST; - GST_START_TEST (test_apply_clean_point) { - do_one_buffer_test_apply (TRUE, FALSE); + do_one_buffer_test_apply (TRUE); } GST_END_TEST; @@ -409,7 +409,7 @@ GST_START_TEST (test_flushing) gst_check_setup_events (mysrcpad, element, NULL, GST_FORMAT_TIME); /* create and push the first buffer */ - buffer = create_rtp_buffer (TIMESTAMP, TRUE, FALSE); + buffer = create_rtp_buffer (TIMESTAMP, TRUE); fail_unless_equals_int (gst_pad_push (mysrcpad, buffer), GST_FLOW_OK); /* no buffers should have made it through */ @@ -423,7 +423,7 @@ GST_START_TEST (test_flushing) gst_check_setup_events (mysrcpad, element, NULL, GST_FORMAT_TIME); /* create and push a second buffer */ - buffer = create_rtp_buffer (TIMESTAMP + 1, TRUE, FALSE); + buffer = create_rtp_buffer (TIMESTAMP + 1, TRUE); fail_unless_equals_int (gst_pad_push (mysrcpad, buffer), GST_FLOW_OK); /* still no buffers should have made it through (the first one should have @@ -446,15 +446,15 @@ GST_START_TEST (test_reusable_element_no_e_bit) gst_check_setup_events (mysrcpad, element, NULL, GST_FORMAT_TIME); /* create and push the first buffer */ - buffer = create_rtp_buffer (TIMESTAMP, TRUE, FALSE); + buffer = create_rtp_buffer (TIMESTAMP, TRUE); fail_unless_equals_int (gst_pad_push (mysrcpad, buffer), GST_FLOW_OK); /* create and push a second buffer */ - buffer = create_rtp_buffer (TIMESTAMP + 1, TRUE, FALSE); + buffer = create_rtp_buffer (TIMESTAMP + 1, TRUE); fail_unless_equals_int (gst_pad_push (mysrcpad, buffer), GST_FLOW_OK); /* create and push a third buffer */ - buffer = create_rtp_buffer (TIMESTAMP + 2, TRUE, FALSE); + buffer = create_rtp_buffer (TIMESTAMP + 2, TRUE); fail_unless_equals_int (gst_pad_push (mysrcpad, buffer), GST_FLOW_OK); ASSERT_SET_STATE (element, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS); @@ -465,15 +465,15 @@ GST_START_TEST (test_reusable_element_no_e_bit) gst_check_setup_events (mysrcpad, element, NULL, GST_FORMAT_TIME); /* create and push the first buffer */ - buffer = create_rtp_buffer (TIMESTAMP, TRUE, FALSE); + buffer = create_rtp_buffer (TIMESTAMP, TRUE); fail_unless_equals_int (gst_pad_push (mysrcpad, buffer), GST_FLOW_OK); /* create and push a second buffer */ - buffer = create_rtp_buffer (TIMESTAMP + 1, TRUE, FALSE); + buffer = create_rtp_buffer (TIMESTAMP + 1, TRUE); fail_unless_equals_int (gst_pad_push (mysrcpad, buffer), GST_FLOW_OK); /* create and push a third buffer */ - buffer = create_rtp_buffer (TIMESTAMP + 2, TRUE, FALSE); + buffer = create_rtp_buffer (TIMESTAMP + 2, TRUE); fail_unless_equals_int (gst_pad_push (mysrcpad, buffer), GST_FLOW_OK); ASSERT_SET_STATE (element, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS); @@ -496,15 +496,15 @@ GST_START_TEST (test_reusable_element_e_bit) gst_check_setup_events (mysrcpad, element, NULL, GST_FORMAT_TIME); /* create and push the first buffer */ - buffer = create_rtp_buffer (TIMESTAMP, TRUE, FALSE); + buffer = create_rtp_buffer (TIMESTAMP, TRUE); fail_unless_equals_int (gst_pad_push (mysrcpad, buffer), GST_FLOW_OK); /* create and push a second buffer */ - buffer = create_rtp_buffer (TIMESTAMP + 1, TRUE, FALSE); + buffer = create_rtp_buffer (TIMESTAMP + 1, TRUE); fail_unless_equals_int (gst_pad_push (mysrcpad, buffer), GST_FLOW_OK); /* create and push a third buffer */ - buffer = create_rtp_buffer (TIMESTAMP + 2, TRUE, FALSE); + buffer = create_rtp_buffer (TIMESTAMP + 2, TRUE); fail_unless_equals_int (gst_pad_push (mysrcpad, buffer), GST_FLOW_OK); ASSERT_SET_STATE (element, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS); @@ -515,15 +515,15 @@ GST_START_TEST (test_reusable_element_e_bit) gst_check_setup_events (mysrcpad, element, NULL, GST_FORMAT_TIME); /* create and push the first buffer */ - buffer = create_rtp_buffer (TIMESTAMP, TRUE, FALSE); + buffer = create_rtp_buffer (TIMESTAMP, TRUE); fail_unless_equals_int (gst_pad_push (mysrcpad, buffer), GST_FLOW_OK); /* create and push a second buffer */ - buffer = create_rtp_buffer (TIMESTAMP + 1, TRUE, FALSE); + buffer = create_rtp_buffer (TIMESTAMP + 1, TRUE); fail_unless_equals_int (gst_pad_push (mysrcpad, buffer), GST_FLOW_OK); /* create and push a third buffer */ - buffer = create_rtp_buffer (TIMESTAMP + 2, TRUE, FALSE); + buffer = create_rtp_buffer (TIMESTAMP + 2, TRUE); fail_unless_equals_int (gst_pad_push (mysrcpad, buffer), GST_FLOW_OK); ASSERT_SET_STATE (element, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS); @@ -533,6 +533,57 @@ GST_START_TEST (test_reusable_element_e_bit) GST_END_TEST; +GST_START_TEST (test_ntp_offset_event) +{ + GstBuffer *buffer_in, *buffer1_out, *buffer2_out; + GList *node; + + /* set the e-bit, so the element use caching */ + g_object_set (element, "set-e-bit", TRUE, NULL); + + ASSERT_SET_STATE (element, GST_STATE_PLAYING, GST_STATE_CHANGE_SUCCESS); + gst_check_setup_events (mysrcpad, element, NULL, GST_FORMAT_TIME); + + /* push an ntp-offset event */ + fail_unless (gst_pad_push_event (mysrcpad, + create_ntp_offset_event (NTP_OFFSET, FALSE))); + + /* create and push the first buffer */ + buffer_in = create_rtp_buffer (TIMESTAMP, TRUE); + buffer1_out = create_extension_buffer (buffer_in, TRUE, TRUE, FALSE, + NTP_OFFSET, 0); + fail_unless_equals_int (gst_pad_push (mysrcpad, buffer_in), GST_FLOW_OK); + + /* push a new ntp offset */ + fail_unless (gst_pad_push_event (mysrcpad, + create_ntp_offset_event (2 * NTP_OFFSET, TRUE))); + + /* create and push a second buffer (last) */ + buffer_in = create_rtp_buffer (TIMESTAMP + 1, TRUE); + buffer2_out = create_extension_buffer (buffer_in, TRUE, TRUE, TRUE, + 2 * NTP_OFFSET, 0); + fail_unless_equals_int (gst_pad_push (mysrcpad, buffer_in), GST_FLOW_OK); + + /* the first buffer should have been pushed now */ + fail_unless_equals_int (g_list_length (buffers), 1); + node = g_list_last (buffers); + check_buffer_equal ((GstBuffer *) node->data, buffer1_out); + gst_buffer_unref (buffer1_out); + + /* push EOS */ + fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ())); + + /* the second buffer has now been pushed */ + fail_unless_equals_int (g_list_length (buffers), 2); + node = g_list_last (buffers); + check_buffer_equal ((GstBuffer *) node->data, buffer2_out); + gst_buffer_unref (buffer2_out); + + ASSERT_SET_STATE (element, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS); +} + +GST_END_TEST; + GST_START_TEST (test_serialized_events) { GstBuffer *buffer; @@ -552,7 +603,7 @@ GST_START_TEST (test_serialized_events) check_and_clear_events (1, NO_COMPARE); /* create and push the first buffer, which should be cached */ - buffer = create_rtp_buffer (TIMESTAMP, TRUE, FALSE); + buffer = create_rtp_buffer (TIMESTAMP, TRUE); fail_unless_equals_int (gst_pad_push (mysrcpad, buffer), GST_FLOW_OK); fail_unless_equals_int (g_list_length (buffers), 0); /* serialized events should be queued when there's a buffer cached */ @@ -564,7 +615,7 @@ GST_START_TEST (test_serialized_events) /* receiving a new buffer should let the first through, along with the * queued serialized events */ - buffer = create_rtp_buffer (TIMESTAMP, TRUE, FALSE); + buffer = create_rtp_buffer (TIMESTAMP, TRUE); fail_unless_equals_int (gst_pad_push (mysrcpad, buffer), GST_FLOW_OK); fail_unless_equals_int (g_list_length (buffers), 1); check_and_clear_events (2, COMPARE); @@ -601,7 +652,7 @@ GST_START_TEST (test_non_serialized_events) check_and_clear_events (1, COMPARE); /* create and push the first buffer, which should be cached */ - buffer = create_rtp_buffer (TIMESTAMP, TRUE, FALSE); + buffer = create_rtp_buffer (TIMESTAMP, TRUE); fail_unless_equals_int (gst_pad_push (mysrcpad, buffer), GST_FLOW_OK); fail_unless_equals_int (g_list_length (buffers), 0); /* non-serialized events should be forwarded regardless of whether @@ -638,14 +689,13 @@ onviftimestamp_suite (void) suite_add_tcase (s, tc_general); tcase_add_checked_fixture (tc_general, setup, cleanup); - tcase_add_test (tc_general, test_apply_discont); - tcase_add_test (tc_general, test_apply_not_discont); tcase_add_test (tc_general, test_apply_clean_point); tcase_add_test (tc_general, test_apply_no_e_bit); tcase_add_test (tc_general, test_apply_e_bit); tcase_add_test (tc_general, test_flushing); 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); tc_events = tcase_create ("events"); suite_add_tcase (s, tc_events);