mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-01 22:58:50 -04:00
add clock
Add a gstreamer pinos clock that reports the time at the server
This commit is contained in:
parent
0b380dd43e
commit
f86b50d202
11 changed files with 259 additions and 72 deletions
|
|
@ -268,6 +268,7 @@ plugin_LTLIBRARIES = libgstpinos.la
|
|||
libgstpinos_la_SOURCES = \
|
||||
gst/gstburstcache.c \
|
||||
gst/gstpinos.c \
|
||||
gst/gstpinosclock.c \
|
||||
gst/gstpinosformat.c \
|
||||
gst/gstpinosdeviceprovider.c \
|
||||
gst/gstpinossrc.c \
|
||||
|
|
@ -281,7 +282,7 @@ libgstpinos_la_LIBADD = $(GST_BASE_LIBS) $(GST_LIBS) $(GLIB_LIBS) $(LIBM) -lgst
|
|||
libgstpinos_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS)
|
||||
|
||||
noinst_HEADERS = gst/gstburstcache.h gst/gstpinossrc.h \
|
||||
gst/gstpinosformat.h \
|
||||
gst/gstpinosclock.h gst/gstpinosformat.h \
|
||||
gst/gstpinossink.h gst/gstpinosdeviceprovider.h
|
||||
|
||||
###################################
|
||||
|
|
|
|||
|
|
@ -95,7 +95,8 @@ struct _PinosStreamPrivate
|
|||
GArray *buffer_ids;
|
||||
gboolean in_order;
|
||||
|
||||
gint64 last_timestamp;
|
||||
gint64 last_ticks;
|
||||
gint32 last_rate;
|
||||
gint64 last_monotonic;
|
||||
};
|
||||
|
||||
|
|
@ -637,6 +638,23 @@ send_need_input (PinosStream *stream, uint32_t port_id)
|
|||
spa_control_clear (&control);
|
||||
}
|
||||
|
||||
static void
|
||||
add_request_clock_update (PinosStream *stream, SpaControlBuilder *builder)
|
||||
{
|
||||
SpaControlCmdNodeEvent cne;
|
||||
SpaNodeEvent ne;
|
||||
SpaNodeEventRequestClockUpdate rcu;
|
||||
|
||||
cne.event = ≠
|
||||
ne.type = SPA_NODE_EVENT_TYPE_REQUEST_CLOCK_UPDATE;
|
||||
ne.data = &rcu;
|
||||
ne.size = sizeof (rcu);
|
||||
rcu.update_mask = SPA_NODE_EVENT_REQUEST_CLOCK_UPDATE_TIME;
|
||||
rcu.timestamp = 0;
|
||||
rcu.offset = 0;
|
||||
spa_control_builder_add_cmd (builder, SPA_CONTROL_CMD_NODE_EVENT, &cne);
|
||||
}
|
||||
|
||||
static void
|
||||
send_reuse_buffer (PinosStream *stream, uint32_t port_id, uint32_t buffer_id)
|
||||
{
|
||||
|
|
@ -794,6 +812,7 @@ handle_node_command (PinosStream *stream,
|
|||
|
||||
g_debug ("stream %p: start", stream);
|
||||
control_builder_init (stream, &builder);
|
||||
add_request_clock_update (stream, &builder);
|
||||
if (priv->direction == PINOS_DIRECTION_INPUT)
|
||||
add_need_input (stream, &builder, 0);
|
||||
add_state_change (stream, &builder, SPA_NODE_STATE_STREAMING);
|
||||
|
|
@ -816,8 +835,8 @@ handle_node_command (PinosStream *stream,
|
|||
case SPA_NODE_COMMAND_CLOCK_UPDATE:
|
||||
{
|
||||
SpaNodeCommandClockUpdate *cu = command->data;
|
||||
g_debug ("got clock update %"PRId64", %"PRId64, cu->timestamp, cu->monotonic_time);
|
||||
priv->last_timestamp = cu->timestamp;
|
||||
priv->last_ticks = cu->ticks;
|
||||
priv->last_rate = cu->rate;
|
||||
priv->last_monotonic = cu->monotonic_time;
|
||||
break;
|
||||
}
|
||||
|
|
@ -1050,20 +1069,9 @@ on_timeout (gpointer user_data)
|
|||
PinosStreamPrivate *priv = stream->priv;
|
||||
SpaControlBuilder builder;
|
||||
SpaControl control;
|
||||
SpaControlCmdNodeEvent cne;
|
||||
SpaNodeEvent ne;
|
||||
SpaNodeEventRequestClockUpdate rcu;
|
||||
|
||||
cne.event = ≠
|
||||
ne.type = SPA_NODE_EVENT_TYPE_REQUEST_CLOCK_UPDATE;
|
||||
ne.data = &rcu;
|
||||
ne.size = sizeof (rcu);
|
||||
rcu.update_mask = SPA_NODE_EVENT_REQUEST_CLOCK_UPDATE_TIME;
|
||||
rcu.timestamp = 0;
|
||||
rcu.offset = 0;
|
||||
|
||||
control_builder_init (stream, &builder);
|
||||
spa_control_builder_add_cmd (&builder, SPA_CONTROL_CMD_NODE_EVENT, &cne);
|
||||
add_request_clock_update (stream, &builder);
|
||||
spa_control_builder_end (&builder, &control);
|
||||
|
||||
if (spa_control_write (&control, priv->fd) < 0)
|
||||
|
|
@ -1540,6 +1548,26 @@ pinos_stream_disconnect (PinosStream *stream)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
pinos_stream_get_time (PinosStream *stream,
|
||||
PinosTime *time)
|
||||
{
|
||||
PinosStreamPrivate *priv;
|
||||
gint64 now, elapsed;
|
||||
|
||||
g_return_val_if_fail (PINOS_IS_STREAM (stream), FALSE);
|
||||
priv = stream->priv;
|
||||
g_return_val_if_fail (time, FALSE);
|
||||
|
||||
now = g_get_monotonic_time ();
|
||||
elapsed = now - (priv->last_monotonic / 1000);
|
||||
|
||||
time->ticks = priv->last_ticks + (elapsed * priv->last_rate) / G_USEC_PER_SEC;
|
||||
time->rate = priv->last_rate;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* pinos_stream_get_empty_buffer:
|
||||
* @stream: a #PinosStream
|
||||
|
|
|
|||
|
|
@ -64,6 +64,11 @@ typedef enum {
|
|||
PINOS_STREAM_MODE_RINGBUFFER = 1,
|
||||
} PinosStreamMode;
|
||||
|
||||
typedef struct {
|
||||
gint64 ticks;
|
||||
gint32 rate;
|
||||
} PinosTime;
|
||||
|
||||
/**
|
||||
* PinosStream:
|
||||
*
|
||||
|
|
@ -110,6 +115,9 @@ gboolean pinos_stream_start_allocation (PinosStream *stream,
|
|||
gboolean pinos_stream_start (PinosStream *stream);
|
||||
gboolean pinos_stream_stop (PinosStream *stream);
|
||||
|
||||
gboolean pinos_stream_get_time (PinosStream *stream,
|
||||
PinosTime *time);
|
||||
|
||||
guint pinos_stream_get_empty_buffer (PinosStream *stream);
|
||||
gboolean pinos_stream_recycle_buffer (PinosStream *stream,
|
||||
guint id);
|
||||
|
|
|
|||
88
pinos/gst/gstpinosclock.c
Normal file
88
pinos/gst/gstpinosclock.c
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) 2016 Wim Taymans <wim.taymans@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Suite 500,
|
||||
* Boston, MA 02110-1335, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <gst/gst.h>
|
||||
|
||||
#include "gstpinosclock.h"
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC (gst_pinos_clock_debug_category);
|
||||
#define GST_CAT_DEFAULT gst_pinos_clock_debug_category
|
||||
|
||||
G_DEFINE_TYPE (GstPinosClock, gst_pinos_clock, GST_TYPE_SYSTEM_CLOCK);
|
||||
|
||||
GstClock *
|
||||
gst_pinos_clock_new (PinosStream *stream)
|
||||
{
|
||||
GstPinosClock *clock;
|
||||
|
||||
clock = g_object_new (GST_TYPE_PINOS_CLOCK, NULL);
|
||||
clock->stream = stream;
|
||||
|
||||
return GST_CLOCK_CAST (clock);
|
||||
}
|
||||
|
||||
static GstClockTime
|
||||
gst_pinos_clock_get_internal_time (GstClock * clock)
|
||||
{
|
||||
GstPinosClock *pclock = (GstPinosClock *) clock;
|
||||
GstClockTime result;
|
||||
PinosTime t;
|
||||
|
||||
pinos_stream_get_time (pclock->stream, &t);
|
||||
|
||||
result = gst_util_uint64_scale_int (t.ticks, GST_SECOND, t.rate);
|
||||
GST_DEBUG ("%"PRId64", %d %"PRId64, t.ticks, t.rate, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gst_pinos_clock_finalize (GObject * object)
|
||||
{
|
||||
GstPinosClock *clock = GST_PINOS_CLOCK (object);
|
||||
|
||||
GST_DEBUG_OBJECT (clock, "finalize");
|
||||
|
||||
G_OBJECT_CLASS (gst_pinos_clock_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_pinos_clock_class_init (GstPinosClockClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GstClockClass *gstclock_class = GST_CLOCK_CLASS (klass);
|
||||
|
||||
gobject_class->finalize = gst_pinos_clock_finalize;
|
||||
|
||||
gstclock_class->get_internal_time = gst_pinos_clock_get_internal_time;
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (gst_pinos_clock_debug_category, "pinosclock", 0,
|
||||
"debug category for pinosclock object");
|
||||
}
|
||||
|
||||
static void
|
||||
gst_pinos_clock_init (GstPinosClock * clock)
|
||||
{
|
||||
GST_OBJECT_FLAG_SET (clock, GST_CLOCK_FLAG_CAN_SET_MASTER);
|
||||
}
|
||||
62
pinos/gst/gstpinosclock.h
Normal file
62
pinos/gst/gstpinosclock.h
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
/* GStreamer
|
||||
* Copyright (C) <2016> Wim Taymans <wim.taymans@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __GST_PINOS_CLOCK_H__
|
||||
#define __GST_PINOS_CLOCK_H__
|
||||
|
||||
#include <gst/gst.h>
|
||||
|
||||
#include <client/pinos.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GST_TYPE_PINOS_CLOCK \
|
||||
(gst_pinos_clock_get_type())
|
||||
#define GST_PINOS_CLOCK(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PINOS_CLOCK,GstPinosClock))
|
||||
#define GST_PINOS_CLOCK_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PINOS_CLOCK,GstPinosClockClass))
|
||||
#define GST_IS_PINOS_CLOCK(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PINOS_CLOCK))
|
||||
#define GST_IS_PINOS_CLOCK_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PINOS_CLOCK))
|
||||
#define GST_PINOS_CLOCK_GET_CLASS(klass) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS ((klass), GST_TYPE_PINOS_CLOCK, GstPinosClockClass))
|
||||
|
||||
typedef struct _GstPinosClock GstPinosClock;
|
||||
typedef struct _GstPinosClockClass GstPinosClockClass;
|
||||
|
||||
struct _GstPinosClock {
|
||||
GstSystemClock parent;
|
||||
|
||||
PinosStream *stream;
|
||||
};
|
||||
|
||||
struct _GstPinosClockClass {
|
||||
GstSystemClockClass parent_class;
|
||||
};
|
||||
|
||||
GType gst_pinos_clock_get_type (void);
|
||||
|
||||
GstClock * gst_pinos_clock_new (PinosStream *stream);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_PINOS_CLOCK_H__ */
|
||||
|
|
@ -48,6 +48,7 @@
|
|||
#include <spa/include/spa/memory.h>
|
||||
#include <spa/include/spa/buffer.h>
|
||||
|
||||
#include "gstpinosclock.h"
|
||||
|
||||
static GQuark process_mem_data_quark;
|
||||
|
||||
|
|
@ -269,6 +270,7 @@ gst_pinos_src_init (GstPinosSrc * src)
|
|||
gst_base_src_set_format (GST_BASE_SRC (src), GST_FORMAT_TIME);
|
||||
|
||||
GST_OBJECT_FLAG_SET (src, GST_ELEMENT_FLAG_PROVIDE_CLOCK);
|
||||
gst_base_src_set_live (GST_BASE_SRC (src), TRUE);
|
||||
|
||||
g_queue_init (&src->queue);
|
||||
|
||||
|
|
@ -523,30 +525,10 @@ parse_stream_properties (GstPinosSrc *pinossrc, PinosProperties *props)
|
|||
var = pinos_properties_get (props, "pinos.latency.max");
|
||||
pinossrc->max_latency = var ? (GstClockTime) atoi (var) : GST_CLOCK_TIME_NONE;
|
||||
|
||||
var = pinos_properties_get (props, "pinos.clock.type");
|
||||
if (var != NULL) {
|
||||
GST_DEBUG_OBJECT (pinossrc, "got clock type %s", var);
|
||||
if (strcmp (var, "gst.net.time.provider") == 0) {
|
||||
const gchar *address;
|
||||
gint port;
|
||||
GstClockTime base_time;
|
||||
|
||||
address = pinos_properties_get (props, "pinos.clock.address");
|
||||
port = atoi (pinos_properties_get (props, "pinos.clock.port"));
|
||||
base_time = atoll (pinos_properties_get (props, "pinos.clock.base-time"));
|
||||
|
||||
GST_DEBUG_OBJECT (pinossrc, "making net clock for %s:%d %" G_GUINT64_FORMAT, address, port, base_time);
|
||||
if (pinossrc->clock)
|
||||
gst_object_unref (pinossrc->clock);
|
||||
pinossrc->clock = gst_net_client_clock_new ("pinosclock", address, port, base_time);
|
||||
|
||||
gst_element_post_message (GST_ELEMENT_CAST (pinossrc),
|
||||
gst_message_new_clock_provide (GST_OBJECT_CAST (pinossrc),
|
||||
pinossrc->clock, TRUE));
|
||||
pinossrc->is_live = TRUE;
|
||||
pinossrc->min_latency = 100000000;
|
||||
pinossrc->max_latency = GST_CLOCK_TIME_NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
gst_pinos_src_stream_start (GstPinosSrc *pinossrc)
|
||||
|
|
@ -817,6 +799,8 @@ gst_pinos_src_query (GstBaseSrc * src, GstQuery * query)
|
|||
|
||||
switch (GST_QUERY_TYPE (query)) {
|
||||
case GST_QUERY_LATENCY:
|
||||
pinossrc->min_latency = 10000000;
|
||||
pinossrc->max_latency = GST_CLOCK_TIME_NONE;
|
||||
gst_query_set_latency (query, pinossrc->is_live, pinossrc->min_latency, pinossrc->max_latency);
|
||||
res = TRUE;
|
||||
break;
|
||||
|
|
@ -1004,6 +988,7 @@ gst_pinos_src_open (GstPinosSrc * pinossrc)
|
|||
g_signal_connect (pinossrc->stream, "add-buffer", (GCallback) on_add_buffer, pinossrc);
|
||||
g_signal_connect (pinossrc->stream, "remove-buffer", (GCallback) on_remove_buffer, pinossrc);
|
||||
g_signal_connect (pinossrc->stream, "new-buffer", (GCallback) on_new_buffer, pinossrc);
|
||||
pinossrc->clock = gst_pinos_clock_new (pinossrc->stream);
|
||||
pinos_main_loop_unlock (pinossrc->loop);
|
||||
|
||||
return TRUE;
|
||||
|
|
@ -1031,6 +1016,7 @@ gst_pinos_src_close (GstPinosSrc * pinossrc)
|
|||
g_main_context_unref (pinossrc->context);
|
||||
GST_OBJECT_LOCK (pinossrc);
|
||||
pinossrc->stream_state = PINOS_STREAM_STATE_UNCONNECTED;
|
||||
g_clear_object (&pinossrc->clock);
|
||||
g_clear_object (&pinossrc->stream);
|
||||
GST_OBJECT_UNLOCK (pinossrc);
|
||||
clear_queue (pinossrc);
|
||||
|
|
|
|||
|
|
@ -292,6 +292,29 @@ suspend_node (PinosNode *this)
|
|||
|
||||
}
|
||||
|
||||
static void
|
||||
send_clock_update (PinosNode *this)
|
||||
{
|
||||
PinosNodePrivate *priv = this->priv;
|
||||
|
||||
if (priv->clock) {
|
||||
SpaNodeCommand cmd;
|
||||
SpaNodeCommandClockUpdate cu;
|
||||
SpaResult res;
|
||||
|
||||
cmd.type = SPA_NODE_COMMAND_CLOCK_UPDATE;
|
||||
cmd.data = &cu;
|
||||
cmd.size = sizeof (cu);
|
||||
cu.change_mask = SPA_NODE_COMMAND_CLOCK_UPDATE_TIME;
|
||||
res = spa_clock_get_time (priv->clock, &cu.rate, &cu.ticks, &cu.monotonic_time);
|
||||
cu.scale = (1 << 16) | 1;
|
||||
cu.state = SPA_CLOCK_STATE_RUNNING;
|
||||
|
||||
if ((res = spa_node_send_command (this->node, &cmd)) < 0)
|
||||
g_debug ("got error %d", res);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
node_set_state (PinosNode *this,
|
||||
PinosNodeState state)
|
||||
|
|
@ -482,26 +505,9 @@ on_node_event (SpaNode *node, SpaNodeEvent *event, void *user_data)
|
|||
break;
|
||||
}
|
||||
case SPA_NODE_EVENT_TYPE_REQUEST_CLOCK_UPDATE:
|
||||
{
|
||||
SpaResult res;
|
||||
|
||||
if (priv->clock) {
|
||||
SpaNodeCommand cmd;
|
||||
SpaNodeCommandClockUpdate cu;
|
||||
|
||||
cmd.type = SPA_NODE_COMMAND_CLOCK_UPDATE;
|
||||
cmd.data = &cu;
|
||||
cmd.size = sizeof (cu);
|
||||
cu.change_mask = SPA_NODE_COMMAND_CLOCK_UPDATE_TIME;
|
||||
res = spa_clock_get_time (priv->clock, &cu.timestamp, &cu.monotonic_time);
|
||||
cu.scale = (1 << 16) | 1;
|
||||
cu.state = SPA_CLOCK_STATE_RUNNING;
|
||||
|
||||
if ((res = spa_node_send_command (this->node, &cmd)) < 0)
|
||||
g_debug ("got error %d", res);
|
||||
}
|
||||
send_clock_update (this);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
g_debug ("node %p: got event %d", this, event->type);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -107,7 +107,8 @@ struct _SpaClock {
|
|||
const SpaProps *props);
|
||||
|
||||
SpaResult (*get_time) (SpaClock *clock,
|
||||
int64_t *clock_time,
|
||||
int32_t *rate,
|
||||
int64_t *ticks,
|
||||
int64_t *monotonic_time);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -48,11 +48,12 @@ struct _SpaNodeCommand {
|
|||
/**
|
||||
* SpaNodeCommandClockUpdate:
|
||||
* @change_mask: marks which fields are updated
|
||||
* @timestamp: the new timestamp, when @change_mask = 1<<0
|
||||
* @monotonic_time: the new monotonic time associated with @timestamp, when
|
||||
* @change_mask = 1<<0
|
||||
* @rate: the number of @ticks per second
|
||||
* @ticks: the new ticks, when @change_mask = 1<<0
|
||||
* @monotonic_time: the new monotonic time in nanoseconds associated with
|
||||
* @ticks, when @change_mask = 1<<0
|
||||
* @offset: the difference between the time when this update was generated
|
||||
* and @monotonic_time
|
||||
* and @monotonic_time in nanoseconds
|
||||
* @scale: update to the speed stored as Q16.16, @change_mask = 1<<1
|
||||
* @state: the new clock state, when @change_mask = 1<<2
|
||||
*/
|
||||
|
|
@ -61,7 +62,8 @@ typedef struct {
|
|||
#define SPA_NODE_COMMAND_CLOCK_UPDATE_SCALE (1 << 1)
|
||||
#define SPA_NODE_COMMAND_CLOCK_UPDATE_STATE (1 << 2)
|
||||
uint32_t change_mask;
|
||||
int64_t timestamp;
|
||||
int32_t rate;
|
||||
int64_t ticks;
|
||||
int64_t monotonic_time;
|
||||
int64_t offset;
|
||||
int32_t scale;
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ typedef struct {
|
|||
SpaAllocParamBuffers param_buffers;
|
||||
SpaPortStatus status;
|
||||
|
||||
int64_t last_timestamp;
|
||||
int64_t last_ticks;
|
||||
int64_t last_monotonic;
|
||||
} SpaV4l2State;
|
||||
|
||||
|
|
@ -759,7 +759,8 @@ spa_v4l2_source_clock_set_props (SpaClock *clock,
|
|||
|
||||
static SpaResult
|
||||
spa_v4l2_source_clock_get_time (SpaClock *clock,
|
||||
int64_t *clock_time,
|
||||
int32_t *rate,
|
||||
int64_t *ticks,
|
||||
int64_t *monotonic_time)
|
||||
{
|
||||
SpaV4l2Source *this;
|
||||
|
|
@ -771,8 +772,10 @@ spa_v4l2_source_clock_get_time (SpaClock *clock,
|
|||
this = (SpaV4l2Source *) clock->handle;
|
||||
state = &this->state[0];
|
||||
|
||||
if (clock_time)
|
||||
*clock_time = state->last_timestamp;
|
||||
if (rate)
|
||||
*rate = 1000000;
|
||||
if (ticks)
|
||||
*ticks = state->last_ticks;
|
||||
if (monotonic_time)
|
||||
*monotonic_time = state->last_monotonic;
|
||||
|
||||
|
|
|
|||
|
|
@ -788,7 +788,8 @@ spa_v4l2_set_format (SpaV4l2Source *this, V4l2Format *f, bool try_only)
|
|||
state->info.flags = SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS |
|
||||
SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS;
|
||||
state->info.maxbuffering = -1;
|
||||
state->info.latency = -1;
|
||||
state->info.latency = (streamparm.parm.capture.timeperframe.numerator * 1000000000LL) /
|
||||
streamparm.parm.capture.timeperframe.denominator;
|
||||
|
||||
state->info.n_params = 1;
|
||||
state->info.params = state->params;
|
||||
|
|
@ -834,12 +835,13 @@ mmap_read (SpaV4l2Source *this)
|
|||
if (buf.flags & V4L2_BUF_FLAG_ERROR)
|
||||
b->header.flags |= SPA_BUFFER_FLAG_CORRUPTED;
|
||||
|
||||
state->last_ticks = (int64_t)buf.timestamp.tv_sec * 1000000 + (uint64_t)buf.timestamp.tv_usec;
|
||||
|
||||
b->header.seq = buf.sequence;
|
||||
b->header.pts = (uint64_t)buf.timestamp.tv_sec * 1000000000lu + (uint64_t)buf.timestamp.tv_usec * 1000lu;
|
||||
state->last_timestamp = b->header.pts;
|
||||
b->header.pts = state->last_ticks * 1000;
|
||||
|
||||
if (buf.flags & V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC)
|
||||
state->last_monotonic = state->last_timestamp;
|
||||
state->last_monotonic = b->header.pts;
|
||||
else
|
||||
state->last_monotonic = SPA_TIME_INVALID;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue