mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-31 22:25:38 -04:00
spa: use clock info
Use the port clock io area to get timing info and use this as the time in the graph when we wake up.
This commit is contained in:
parent
2b1b356455
commit
d3c203b744
10 changed files with 134 additions and 15 deletions
|
|
@ -56,6 +56,11 @@ extern "C" {
|
|||
#define SPA_TYPE_PARAM_IO__Prop SPA_TYPE_PARAM_IO_BASE "Prop"
|
||||
#define SPA_TYPE_PARAM_IO_PROP_BASE SPA_TYPE_PARAM_IO__Prop ":"
|
||||
|
||||
/** enumerate clock io areas */
|
||||
#define SPA_TYPE_PARAM_ID_IO__Clock SPA_TYPE_PARAM_ID_IO_BASE "Clock"
|
||||
/* an io area to exchange clock information */
|
||||
#define SPA_TYPE_PARAM_IO__Clock SPA_TYPE_PARAM_IO_BASE "Clock"
|
||||
|
||||
struct spa_type_param_io {
|
||||
uint32_t id; /**< id to configure the io area */
|
||||
uint32_t size; /**< size of io area */
|
||||
|
|
@ -66,6 +71,8 @@ struct spa_type_param_io {
|
|||
uint32_t idPropsIn; /**< id to enumerate input properties io */
|
||||
uint32_t idPropsOut; /**< id to enumerate output properties io */
|
||||
uint32_t Prop; /**< object type of property area */
|
||||
uint32_t idClock; /**< id to enumerate clock io */
|
||||
uint32_t Clock; /**< object type of clock io area */
|
||||
};
|
||||
|
||||
static inline void
|
||||
|
|
@ -82,6 +89,8 @@ spa_type_param_io_map(struct spa_type_map *map,
|
|||
type->idPropsIn = spa_type_map_get_id(map, SPA_TYPE_PARAM_ID_IO_PROPS__In);
|
||||
type->idPropsOut = spa_type_map_get_id(map, SPA_TYPE_PARAM_ID_IO_PROPS__Out);
|
||||
type->Prop = spa_type_map_get_id(map, SPA_TYPE_PARAM_IO__Prop);
|
||||
type->idClock = spa_type_map_get_id(map, SPA_TYPE_PARAM_ID_IO__Clock);
|
||||
type->Clock = spa_type_map_get_id(map, SPA_TYPE_PARAM_IO__Clock);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -317,7 +317,9 @@ impl_node_port_enum_params(struct spa_node *node,
|
|||
uint32_t list[] = { t->param.idEnumFormat,
|
||||
t->param.idFormat,
|
||||
t->param.idBuffers,
|
||||
t->param.idMeta };
|
||||
t->param.idMeta,
|
||||
t->param_io.idBuffers,
|
||||
t->param_io.idClock, };
|
||||
|
||||
if (*index < SPA_N_ELEMENTS(list))
|
||||
param = spa_pod_builder_object(&b, id, t->param.List,
|
||||
|
|
@ -375,6 +377,42 @@ impl_node_port_enum_params(struct spa_node *node,
|
|||
return 0;
|
||||
}
|
||||
}
|
||||
else if (id == t->param_io.idBuffers) {
|
||||
switch (*index) {
|
||||
case 0:
|
||||
param = spa_pod_builder_object(&b,
|
||||
id, t->param_io.Buffers,
|
||||
":", t->param_io.id, "I", t->io.Buffers,
|
||||
":", t->param_io.size, "i", sizeof(struct spa_io_buffers));
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (id == t->param_io.idControl) {
|
||||
switch (*index) {
|
||||
case 0:
|
||||
param = spa_pod_builder_object(&b,
|
||||
id, t->param_io.Control,
|
||||
":", t->param_io.id, "I", t->io.ControlRange,
|
||||
":", t->param_io.size, "i", sizeof(struct spa_io_control_range));
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (id == t->param_io.idClock) {
|
||||
switch (*index) {
|
||||
case 0:
|
||||
param = spa_pod_builder_object(&b,
|
||||
id, t->param_io.Clock,
|
||||
":", t->param_io.id, "I", t->io.Clock,
|
||||
":", t->param_io.size, "i", sizeof(struct spa_io_clock));
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
return -ENOENT;
|
||||
|
||||
|
|
|
|||
|
|
@ -401,6 +401,30 @@ impl_node_port_enum_params(struct spa_node *node,
|
|||
return 0;
|
||||
}
|
||||
}
|
||||
else if (id == t->param_io.idBuffers) {
|
||||
switch (*index) {
|
||||
case 0:
|
||||
param = spa_pod_builder_object(&b,
|
||||
id, t->param_io.Buffers,
|
||||
":", t->param_io.id, "I", t->io.Buffers,
|
||||
":", t->param_io.size, "i", sizeof(struct spa_io_buffers));
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (id == t->param_io.idClock) {
|
||||
switch (*index) {
|
||||
case 0:
|
||||
param = spa_pod_builder_object(&b,
|
||||
id, t->param_io.Clock,
|
||||
":", t->param_io.id, "I", t->io.Clock,
|
||||
":", t->param_io.size, "i", sizeof(struct spa_io_clock));
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
return -ENOENT;
|
||||
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ extern "C" {
|
|||
#include <spa/node/node.h>
|
||||
#include <spa/node/io.h>
|
||||
#include <spa/param/buffers.h>
|
||||
#include <spa/param/io.h>
|
||||
#include <spa/param/meta.h>
|
||||
#include <spa/param/audio/format-utils.h>
|
||||
|
||||
|
|
@ -82,6 +83,7 @@ struct type {
|
|||
struct spa_type_format_audio format_audio;
|
||||
struct spa_type_param_buffers param_buffers;
|
||||
struct spa_type_param_meta param_meta;
|
||||
struct spa_type_param_io param_io;
|
||||
};
|
||||
|
||||
static inline void init_type(struct type *type, struct spa_type_map *map)
|
||||
|
|
@ -108,6 +110,7 @@ static inline void init_type(struct type *type, struct spa_type_map *map)
|
|||
spa_type_format_audio_map(map, &type->format_audio);
|
||||
spa_type_param_buffers_map(map, &type->param_buffers);
|
||||
spa_type_param_meta_map(map, &type->param_meta);
|
||||
spa_type_param_io_map(map, &type->param_io);
|
||||
}
|
||||
|
||||
struct state {
|
||||
|
|
|
|||
|
|
@ -158,6 +158,7 @@ struct port {
|
|||
|
||||
bool have_format;
|
||||
struct spa_video_info current_format;
|
||||
struct spa_fraction rate;
|
||||
|
||||
int fd;
|
||||
bool opened;
|
||||
|
|
@ -178,9 +179,7 @@ struct port {
|
|||
|
||||
struct spa_port_info info;
|
||||
struct spa_io_buffers *io;
|
||||
|
||||
int64_t last_ticks;
|
||||
int64_t last_monotonic;
|
||||
struct spa_io_clock *clock;
|
||||
};
|
||||
|
||||
struct impl {
|
||||
|
|
@ -562,6 +561,30 @@ static int impl_node_port_enum_params(struct spa_node *node,
|
|||
else if (id == t->param_io.idPropsIn) {
|
||||
return spa_v4l2_enum_controls(this, index, filter, result, builder);
|
||||
}
|
||||
else if (id == t->param_io.idBuffers) {
|
||||
switch (*index) {
|
||||
case 0:
|
||||
param = spa_pod_builder_object(&b,
|
||||
id, t->param_io.Buffers,
|
||||
":", t->param_io.id, "I", t->io.Buffers,
|
||||
":", t->param_io.size, "i", sizeof(struct spa_io_buffers));
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (id == t->param_io.idClock) {
|
||||
switch (*index) {
|
||||
case 0:
|
||||
param = spa_pod_builder_object(&b,
|
||||
id, t->param_io.Clock,
|
||||
":", t->param_io.id, "I", t->io.Clock,
|
||||
":", t->param_io.size, "i", sizeof(struct spa_io_clock));
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
return -ENOENT;
|
||||
|
||||
|
|
@ -767,6 +790,9 @@ static int impl_node_port_set_io(struct spa_node *node,
|
|||
if (id == t->io.Buffers) {
|
||||
port->io = data;
|
||||
}
|
||||
else if (id == t->io.Clock) {
|
||||
port->clock = data;
|
||||
}
|
||||
else if ((control = find_control(port, id))) {
|
||||
if (data && size >= sizeof(struct spa_pod_double))
|
||||
control->io = &SPA_POD_VALUE(struct spa_pod_double, data);
|
||||
|
|
|
|||
|
|
@ -911,6 +911,7 @@ static int spa_v4l2_set_format(struct impl *this, struct spa_video_info *format,
|
|||
SPA_PORT_INFO_FLAG_PHYSICAL |
|
||||
SPA_PORT_INFO_FLAG_TERMINAL;
|
||||
port->info.rate = streamparm.parm.capture.timeperframe.denominator;
|
||||
port->rate = *framerate;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1156,14 +1157,13 @@ static int mmap_read(struct impl *this)
|
|||
if (xioctl(port->fd, VIDIOC_DQBUF, &buf) < 0)
|
||||
return -errno;
|
||||
|
||||
port->last_ticks = (int64_t) buf.timestamp.tv_sec * SPA_USEC_PER_SEC +
|
||||
(uint64_t) buf.timestamp.tv_usec;
|
||||
pts = port->last_ticks * 1000;
|
||||
pts = SPA_TIMEVAL_TO_TIME(&buf.timestamp);
|
||||
|
||||
if (buf.flags & V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC)
|
||||
port->last_monotonic = pts;
|
||||
else
|
||||
port->last_monotonic = SPA_TIME_INVALID;
|
||||
if (port->clock) {
|
||||
port->clock->nsec = pts;
|
||||
port->clock->rate = port->rate;
|
||||
port->clock->position = buf.sequence;
|
||||
}
|
||||
|
||||
b = &port->buffers[buf.index];
|
||||
if (b->h) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue