Add suport for clocks

Add a clock interface to get raw clocking information from an element
Make events and commands to request and configure clock updates.
Add support for passing events and commands in control
Set the size of the buffers in pinossrc
This commit is contained in:
Wim Taymans 2016-09-09 16:05:58 +02:00
parent a5f21576fa
commit 0b380dd43e
20 changed files with 712 additions and 268 deletions

View file

@ -115,11 +115,14 @@ typedef struct {
SpaAllocParamBuffers param_buffers;
SpaPortStatus status;
int64_t last_timestamp;
int64_t last_monotonic;
} SpaV4l2State;
struct _SpaV4l2Source {
SpaHandle handle;
SpaNode node;
SpaClock clock;
SpaV4l2SourceProps props[2];
@ -269,6 +272,7 @@ spa_v4l2_source_node_send_command (SpaNode *node,
case SPA_NODE_COMMAND_FLUSH:
case SPA_NODE_COMMAND_DRAIN:
case SPA_NODE_COMMAND_MARKER:
case SPA_NODE_COMMAND_CLOCK_UPDATE:
return SPA_RESULT_NOT_IMPLEMENTED;
}
return SPA_RESULT_OK;
@ -739,6 +743,51 @@ static const SpaNode v4l2source_node = {
spa_v4l2_source_node_port_push_event,
};
static SpaResult
spa_v4l2_source_clock_get_props (SpaClock *clock,
SpaProps **props)
{
return SPA_RESULT_NOT_IMPLEMENTED;
}
static SpaResult
spa_v4l2_source_clock_set_props (SpaClock *clock,
const SpaProps *props)
{
return SPA_RESULT_NOT_IMPLEMENTED;
}
static SpaResult
spa_v4l2_source_clock_get_time (SpaClock *clock,
int64_t *clock_time,
int64_t *monotonic_time)
{
SpaV4l2Source *this;
SpaV4l2State *state;
if (clock == NULL || clock->handle == NULL)
return SPA_RESULT_INVALID_ARGUMENTS;
this = (SpaV4l2Source *) clock->handle;
state = &this->state[0];
if (clock_time)
*clock_time = state->last_timestamp;
if (monotonic_time)
*monotonic_time = state->last_monotonic;
return SPA_RESULT_OK;
}
static const SpaClock v4l2source_clock = {
NULL,
sizeof (SpaClock),
SPA_CLOCK_STATE_STOPPED,
spa_v4l2_source_clock_get_props,
spa_v4l2_source_clock_set_props,
spa_v4l2_source_clock_get_time,
};
static SpaResult
spa_v4l2_source_get_interface (SpaHandle *handle,
uint32_t interface_id,
@ -755,6 +804,9 @@ spa_v4l2_source_get_interface (SpaHandle *handle,
case SPA_INTERFACE_ID_NODE:
*interface = &this->node;
break;
case SPA_INTERFACE_ID_CLOCK:
*interface = &this->clock;
break;
default:
return SPA_RESULT_UNKNOWN_INTERFACE;
}
@ -782,6 +834,8 @@ v4l2_source_init (const SpaHandleFactory *factory,
this = (SpaV4l2Source *) handle;
this->node = v4l2source_node;
this->node.handle = handle;
this->clock = v4l2source_clock;
this->clock.handle = handle;
this->props[1].props.n_prop_info = PROP_ID_LAST;
this->props[1].props.prop_info = prop_info;
reset_v4l2_source_props (&this->props[1]);
@ -800,6 +854,10 @@ static const SpaInterfaceInfo v4l2_source_interfaces[] =
SPA_INTERFACE_ID_NODE_NAME,
SPA_INTERFACE_ID_NODE_DESCRIPTION,
},
{ SPA_INTERFACE_ID_CLOCK,
SPA_INTERFACE_ID_CLOCK_NAME,
SPA_INTERFACE_ID_CLOCK_DESCRIPTION,
},
};
static SpaResult
@ -814,13 +872,10 @@ v4l2_source_enum_interface_info (const SpaHandleFactory *factory,
index = (*state == NULL ? 0 : *(int*)state);
switch (index) {
case 0:
*info = &v4l2_source_interfaces[index];
break;
default:
return SPA_RESULT_ENUM_END;
}
if (index < 0 || index >= SPA_N_ELEMENTS (v4l2_source_interfaces))
return SPA_RESULT_ENUM_END;
*info = &v4l2_source_interfaces[index];
*(int*)state = ++index;
return SPA_RESULT_OK;
}

View file

@ -811,6 +811,7 @@ mmap_read (SpaV4l2Source *this)
SpaV4l2State *state = &this->state[0];
struct v4l2_buffer buf;
V4l2Buffer *b;
SpaData *d;
CLEAR(buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
@ -829,8 +830,22 @@ mmap_read (SpaV4l2Source *this)
}
b = &state->alloc_buffers[buf.index];
b->header.flags = SPA_BUFFER_FLAG_NONE;
if (buf.flags & V4L2_BUF_FLAG_ERROR)
b->header.flags |= SPA_BUFFER_FLAG_CORRUPTED;
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;
if (buf.flags & V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC)
state->last_monotonic = state->last_timestamp;
else
state->last_monotonic = SPA_TIME_INVALID;
d = SPA_BUFFER_DATAS (b->outbuf);
d[0].mem.size = buf.bytesused;
b->next = state->ready;
state->ready = b;
state->ready_count++;
@ -893,7 +908,7 @@ spa_v4l2_use_buffers (SpaV4l2Source *this, SpaBuffer **buffers, uint32_t n_buffe
V4l2Buffer *b;
SpaMemoryRef *mem_ref;
SpaMemory *mem;
SpaData *d = SPA_BUFFER_DATAS (buffers[i]);
SpaData *d;
b = &state->alloc_buffers[i];
b->buffer.mem.mem = state->alloc_mem->mem;
@ -911,6 +926,12 @@ spa_v4l2_use_buffers (SpaV4l2Source *this, SpaBuffer **buffers, uint32_t n_buffe
continue;
}
if (buffers[i]->n_datas < 1) {
fprintf (stderr, "invalid memory on buffer %p\n", buffers[i]);
continue;
}
d = SPA_BUFFER_DATAS (buffers[i]);
CLEAR (b->v4l2_buffer);
b->v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
b->v4l2_buffer.memory = state->memtype;