mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-29 05:01:23 +00:00
unixfdsink: Take segment into account when converting timestamps
Also rename `calculate_timestamp()` to `to_monotonic()` and `from_monotonic()` which better describe what it does. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6747>
This commit is contained in:
parent
5593a3c698
commit
e62adb4d12
3 changed files with 117 additions and 10 deletions
|
@ -428,12 +428,22 @@ send_command_to_all (GstUnixFdSink * self, CommandType type, GUnixFDList * fds,
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstClockTime
|
static GstClockTime
|
||||||
calculate_timestamp (GstClockTime timestamp, GstClockTime base_time,
|
to_monotonic (GstClockTime timestamp, const GstSegment * segment,
|
||||||
GstClockTime latency, GstClockTimeDiff clock_diff)
|
GstClockTime base_time, GstClockTime latency, GstClockTimeDiff clock_diff)
|
||||||
{
|
{
|
||||||
if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
|
if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
|
||||||
/* Convert running time to pipeline clock time */
|
/* Convert running time to pipeline clock time */
|
||||||
timestamp += base_time;
|
gint res =
|
||||||
|
gst_segment_to_running_time_full (segment, GST_FORMAT_TIME, timestamp,
|
||||||
|
×tamp);
|
||||||
|
if (res == 0)
|
||||||
|
return GST_CLOCK_TIME_NONE;
|
||||||
|
else if (res > 0)
|
||||||
|
timestamp += base_time;
|
||||||
|
else if (base_time > timestamp)
|
||||||
|
timestamp = base_time - timestamp;
|
||||||
|
else
|
||||||
|
timestamp = 0;
|
||||||
if (GST_CLOCK_TIME_IS_VALID (latency))
|
if (GST_CLOCK_TIME_IS_VALID (latency))
|
||||||
timestamp += latency;
|
timestamp += latency;
|
||||||
/* Convert to system monotonic clock time */
|
/* Convert to system monotonic clock time */
|
||||||
|
@ -485,11 +495,11 @@ gst_unix_fd_sink_render (GstBaseSink * bsink, GstBuffer * buffer)
|
||||||
* id so we know which buffer to unref. */
|
* id so we know which buffer to unref. */
|
||||||
new_buffer->id = (guint64) buffer;
|
new_buffer->id = (guint64) buffer;
|
||||||
new_buffer->pts =
|
new_buffer->pts =
|
||||||
calculate_timestamp (GST_BUFFER_PTS (buffer), base_time, latency,
|
to_monotonic (GST_BUFFER_PTS (buffer),
|
||||||
clock_diff);
|
&GST_BASE_SINK_CAST (self)->segment, base_time, latency, clock_diff);
|
||||||
new_buffer->dts =
|
new_buffer->dts =
|
||||||
calculate_timestamp (GST_BUFFER_DTS (buffer), base_time, latency,
|
to_monotonic (GST_BUFFER_DTS (buffer),
|
||||||
clock_diff);
|
&GST_BASE_SINK_CAST (self)->segment, base_time, latency, clock_diff);
|
||||||
new_buffer->duration = GST_BUFFER_DURATION (buffer);
|
new_buffer->duration = GST_BUFFER_DURATION (buffer);
|
||||||
new_buffer->offset = GST_BUFFER_OFFSET (buffer);
|
new_buffer->offset = GST_BUFFER_OFFSET (buffer);
|
||||||
new_buffer->offset_end = GST_BUFFER_OFFSET_END (buffer);
|
new_buffer->offset_end = GST_BUFFER_OFFSET_END (buffer);
|
||||||
|
@ -498,6 +508,15 @@ gst_unix_fd_sink_render (GstBaseSink * bsink, GstBuffer * buffer)
|
||||||
new_buffer->n_memory = n_memory;
|
new_buffer->n_memory = n_memory;
|
||||||
new_buffer->n_meta = n_meta;
|
new_buffer->n_meta = n_meta;
|
||||||
|
|
||||||
|
if ((GST_BUFFER_PTS_IS_VALID (buffer)
|
||||||
|
&& !GST_CLOCK_TIME_IS_VALID (new_buffer->pts))
|
||||||
|
|| (GST_BUFFER_DTS_IS_VALID (buffer)
|
||||||
|
&& !GST_CLOCK_TIME_IS_VALID (new_buffer->dts))) {
|
||||||
|
GST_ERROR_OBJECT (self,
|
||||||
|
"Could not convert buffer timestamp to running time");
|
||||||
|
return GST_FLOW_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
gboolean dmabuf_count = 0;
|
gboolean dmabuf_count = 0;
|
||||||
GUnixFDList *fds = g_unix_fd_list_new ();
|
GUnixFDList *fds = g_unix_fd_list_new ();
|
||||||
for (int i = 0; i < n_memory; i++) {
|
for (int i = 0; i < n_memory; i++) {
|
||||||
|
|
|
@ -282,7 +282,7 @@ gst_unix_fd_src_unlock_stop (GstBaseSrc * bsrc)
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstClockTime
|
static GstClockTime
|
||||||
calculate_timestamp (GstClockTime timestamp, GstClockTime base_time,
|
from_monotonic (GstClockTime timestamp, GstClockTime base_time,
|
||||||
GstClockTimeDiff clock_diff)
|
GstClockTimeDiff clock_diff)
|
||||||
{
|
{
|
||||||
if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
|
if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
|
||||||
|
@ -369,9 +369,9 @@ again:
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_BUFFER_PTS (*outbuf) =
|
GST_BUFFER_PTS (*outbuf) =
|
||||||
calculate_timestamp (new_buffer->pts, base_time, clock_diff);
|
from_monotonic (new_buffer->pts, base_time, clock_diff);
|
||||||
GST_BUFFER_DTS (*outbuf) =
|
GST_BUFFER_DTS (*outbuf) =
|
||||||
calculate_timestamp (new_buffer->dts, base_time, clock_diff);
|
from_monotonic (new_buffer->dts, base_time, clock_diff);
|
||||||
GST_BUFFER_DURATION (*outbuf) = new_buffer->duration;
|
GST_BUFFER_DURATION (*outbuf) = new_buffer->duration;
|
||||||
GST_BUFFER_OFFSET (*outbuf) = new_buffer->offset;
|
GST_BUFFER_OFFSET (*outbuf) = new_buffer->offset;
|
||||||
GST_BUFFER_OFFSET_END (*outbuf) = new_buffer->offset_end;
|
GST_BUFFER_OFFSET_END (*outbuf) = new_buffer->offset_end;
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
#include <gst/check/gstcheck.h>
|
#include <gst/check/gstcheck.h>
|
||||||
|
#include <gst/app/app.h>
|
||||||
#include <glib/gstdio.h>
|
#include <glib/gstdio.h>
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -134,6 +135,92 @@ GST_START_TEST (test_unixfd_videotestsrc)
|
||||||
|
|
||||||
GST_END_TEST;
|
GST_END_TEST;
|
||||||
|
|
||||||
|
GST_START_TEST (test_unixfd_segment)
|
||||||
|
{
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
/* Ensure we don't have socket from previous failed test */
|
||||||
|
gchar *socket_path =
|
||||||
|
g_strdup_printf ("%s/unixfd-test-socket", g_get_user_runtime_dir ());
|
||||||
|
if (g_file_test (socket_path, G_FILE_TEST_EXISTS)) {
|
||||||
|
g_unlink (socket_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
GstCaps *caps = gst_caps_new_empty_simple ("video/x-raw");
|
||||||
|
|
||||||
|
/* Setup service */
|
||||||
|
gchar *pipeline_str =
|
||||||
|
g_strdup_printf
|
||||||
|
("appsrc name=src format=time handle-segment-change=true ! unixfdsink socket-path=%s sync=false async=false",
|
||||||
|
socket_path);
|
||||||
|
GstElement *pipeline_service = gst_parse_launch (pipeline_str, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
fail_unless (gst_element_set_state (pipeline_service,
|
||||||
|
GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS);
|
||||||
|
GstElement *appsrc = gst_bin_get_by_name (GST_BIN (pipeline_service), "src");
|
||||||
|
gst_object_unref (appsrc);
|
||||||
|
g_free (pipeline_str);
|
||||||
|
|
||||||
|
/* Setup client */
|
||||||
|
pipeline_str =
|
||||||
|
g_strdup_printf
|
||||||
|
("unixfdsrc socket-path=%s ! appsink name=sink sync=false async=false",
|
||||||
|
socket_path);
|
||||||
|
GstElement *pipeline_client = gst_parse_launch (pipeline_str, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
fail_unless (gst_element_set_state (pipeline_client,
|
||||||
|
GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS);
|
||||||
|
GstElement *appsink = gst_bin_get_by_name (GST_BIN (pipeline_client), "sink");
|
||||||
|
gst_object_unref (appsink);
|
||||||
|
g_free (pipeline_str);
|
||||||
|
|
||||||
|
/* Send a buffer with PTS=30s */
|
||||||
|
GstSegment segment;
|
||||||
|
gst_segment_init (&segment, GST_FORMAT_TIME);
|
||||||
|
GstBuffer *buf = gst_buffer_new ();
|
||||||
|
GST_BUFFER_PTS (buf) = 30 * GST_SECOND;
|
||||||
|
GstSample *sample = gst_sample_new (buf, caps, &segment, NULL);
|
||||||
|
gst_app_src_push_sample (GST_APP_SRC (appsrc), sample);
|
||||||
|
gst_sample_unref (sample);
|
||||||
|
gst_buffer_unref (buf);
|
||||||
|
|
||||||
|
/* Wait for it */
|
||||||
|
sample = gst_app_sink_pull_sample (GST_APP_SINK (appsink));
|
||||||
|
buf = gst_sample_get_buffer (sample);
|
||||||
|
GstClockTime first_pts = GST_BUFFER_PTS (buf);
|
||||||
|
gst_sample_unref (sample);
|
||||||
|
|
||||||
|
/* Send a buffer with PTS=1s but with 30s offset in the segment */
|
||||||
|
segment.base = 30 * GST_SECOND;
|
||||||
|
buf = gst_buffer_new ();
|
||||||
|
GST_BUFFER_PTS (buf) = 1 * GST_SECOND;
|
||||||
|
sample = gst_sample_new (buf, caps, &segment, NULL);
|
||||||
|
gst_app_src_push_sample (GST_APP_SRC (appsrc), sample);
|
||||||
|
gst_sample_unref (sample);
|
||||||
|
gst_buffer_unref (buf);
|
||||||
|
|
||||||
|
/* Wait for it */
|
||||||
|
sample = gst_app_sink_pull_sample (GST_APP_SINK (appsink));
|
||||||
|
buf = gst_sample_get_buffer (sample);
|
||||||
|
GstClockTime second_pts = GST_BUFFER_PTS (buf);
|
||||||
|
gst_sample_unref (sample);
|
||||||
|
|
||||||
|
/* They should be 1s appart */
|
||||||
|
fail_unless_equals_uint64 (second_pts - first_pts, GST_SECOND);
|
||||||
|
|
||||||
|
/* Teardown */
|
||||||
|
fail_unless (gst_element_set_state (pipeline_client,
|
||||||
|
GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS);
|
||||||
|
fail_unless (gst_element_set_state (pipeline_service,
|
||||||
|
GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS);
|
||||||
|
gst_object_unref (pipeline_service);
|
||||||
|
gst_object_unref (pipeline_client);
|
||||||
|
g_free (socket_path);
|
||||||
|
gst_caps_unref (caps);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
static Suite *
|
static Suite *
|
||||||
unixfd_suite (void)
|
unixfd_suite (void)
|
||||||
{
|
{
|
||||||
|
@ -142,6 +229,7 @@ unixfd_suite (void)
|
||||||
|
|
||||||
suite_add_tcase (s, tc);
|
suite_add_tcase (s, tc);
|
||||||
tcase_add_test (tc, test_unixfd_videotestsrc);
|
tcase_add_test (tc, test_unixfd_videotestsrc);
|
||||||
|
tcase_add_test (tc, test_unixfd_segment);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue