mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-29 05:40:27 -04:00
spa: libcamera: source: process requests on data loop
Since `impl::requestComplete()` runs in an internal libcamera thread, extra care
would need to be taken to validate all accesses to common data structures. For
example, the function might call `spa_libcamera_buffer_recycle()`, which accesses
`impl::ctrls`, which would be unsafe because it could read or modified at the same
time on the data thread. So move the processing of requests to the data loop.
(cherry picked from commit 019a5c130f)
This commit is contained in:
parent
3ca1e20b3d
commit
8ed8f21100
1 changed files with 62 additions and 59 deletions
|
|
@ -1020,6 +1020,63 @@ void handle_completed_request(struct impl *impl, libcamera::Request *request)
|
|||
impl, request, request_id, static_cast<unsigned int>(request->status()),
|
||||
request->sequence());
|
||||
|
||||
if (request->status() == libcamera::Request::Status::RequestCancelled) {
|
||||
spa_log_trace(impl->log, "%p: request %p[%" PRIu64 "] cancelled",
|
||||
impl, request, request_id);
|
||||
request->reuse(libcamera::Request::ReuseFlag::ReuseBuffers);
|
||||
SPA_FLAG_SET(b->flags, BUFFER_FLAG_OUTSTANDING);
|
||||
spa_libcamera_buffer_recycle(impl, port, b->id);
|
||||
return;
|
||||
}
|
||||
|
||||
const FrameBuffer *buffer = request->findBuffer(port->streamConfig.stream());
|
||||
if (buffer == nullptr) {
|
||||
spa_log_warn(impl->log, "%p: request %p[%" PRIu64 "] has no buffer for stream %p",
|
||||
impl, request, request_id, port->streamConfig.stream());
|
||||
return;
|
||||
}
|
||||
|
||||
const FrameMetadata &fmd = buffer->metadata();
|
||||
|
||||
if (impl->clock) {
|
||||
double target = (double)port->info.rate.num / port->info.rate.denom;
|
||||
double corr;
|
||||
|
||||
if (impl->dll.bw == 0.0) {
|
||||
spa_dll_set_bw(&impl->dll, SPA_DLL_BW_MAX, port->info.rate.denom, port->info.rate.denom);
|
||||
impl->clock->next_nsec = fmd.timestamp;
|
||||
corr = 1.0;
|
||||
} else {
|
||||
double diff = ((double)impl->clock->next_nsec - (double)fmd.timestamp) / SPA_NSEC_PER_SEC;
|
||||
double error = port->info.rate.denom * (diff - target);
|
||||
corr = spa_dll_update(&impl->dll, SPA_CLAMPD(error, -128., 128.));
|
||||
}
|
||||
/* FIXME, we should follow the driver clock and target_ values.
|
||||
* for now we ignore and use our own. */
|
||||
impl->clock->target_rate = port->rate;
|
||||
impl->clock->target_duration = 1;
|
||||
|
||||
impl->clock->nsec = fmd.timestamp;
|
||||
impl->clock->rate = port->rate;
|
||||
impl->clock->position = fmd.sequence;
|
||||
impl->clock->duration = 1;
|
||||
impl->clock->delay = 0;
|
||||
impl->clock->rate_diff = corr;
|
||||
impl->clock->next_nsec += (uint64_t) (target * SPA_NSEC_PER_SEC * corr);
|
||||
}
|
||||
|
||||
if (b->h) {
|
||||
b->h->flags = 0;
|
||||
if (fmd.status != libcamera::FrameMetadata::Status::FrameSuccess)
|
||||
b->h->flags |= SPA_META_HEADER_FLAG_CORRUPTED;
|
||||
b->h->offset = 0;
|
||||
b->h->seq = fmd.sequence;
|
||||
b->h->pts = fmd.timestamp;
|
||||
b->h->dts_offset = 0;
|
||||
}
|
||||
|
||||
request->reuse(libcamera::Request::ReuseFlag::ReuseBuffers);
|
||||
|
||||
spa_list_append(&port->queue, &b->link);
|
||||
|
||||
spa_io_buffers *io = port->io;
|
||||
|
|
@ -1231,66 +1288,12 @@ spa_libcamera_alloc_buffers(struct impl *impl, struct port *port,
|
|||
void impl::requestComplete(libcamera::Request *request)
|
||||
{
|
||||
struct impl *impl = this;
|
||||
struct port *port = &impl->out_ports[0];
|
||||
Stream *stream = port->streamConfig.stream();
|
||||
uint32_t index, buffer_id;
|
||||
struct buffer *b;
|
||||
uint32_t index;
|
||||
|
||||
spa_log_debug(impl->log, "request complete");
|
||||
|
||||
buffer_id = request->cookie();
|
||||
b = &port->buffers[buffer_id];
|
||||
|
||||
if ((request->status() == Request::RequestCancelled)) {
|
||||
spa_log_debug(impl->log, "Request was cancelled");
|
||||
request->reuse(libcamera::Request::ReuseFlag::ReuseBuffers);
|
||||
SPA_FLAG_SET(b->flags, BUFFER_FLAG_OUTSTANDING);
|
||||
spa_libcamera_buffer_recycle(impl, port, b->id);
|
||||
return;
|
||||
}
|
||||
FrameBuffer *buffer = request->findBuffer(stream);
|
||||
if (buffer == nullptr) {
|
||||
spa_log_warn(impl->log, "unknown buffer");
|
||||
return;
|
||||
}
|
||||
const FrameMetadata &fmd = buffer->metadata();
|
||||
|
||||
if (impl->clock) {
|
||||
double target = (double)port->info.rate.num / port->info.rate.denom;
|
||||
double corr;
|
||||
|
||||
if (impl->dll.bw == 0.0) {
|
||||
spa_dll_set_bw(&impl->dll, SPA_DLL_BW_MAX, port->info.rate.denom, port->info.rate.denom);
|
||||
impl->clock->next_nsec = fmd.timestamp;
|
||||
corr = 1.0;
|
||||
} else {
|
||||
double diff = ((double)impl->clock->next_nsec - (double)fmd.timestamp) / SPA_NSEC_PER_SEC;
|
||||
double error = port->info.rate.denom * (diff - target);
|
||||
corr = spa_dll_update(&impl->dll, SPA_CLAMPD(error, -128., 128.));
|
||||
}
|
||||
/* FIXME, we should follow the driver clock and target_ values.
|
||||
* for now we ignore and use our own. */
|
||||
impl->clock->target_rate = port->rate;
|
||||
impl->clock->target_duration = 1;
|
||||
|
||||
impl->clock->nsec = fmd.timestamp;
|
||||
impl->clock->rate = port->rate;
|
||||
impl->clock->position = fmd.sequence;
|
||||
impl->clock->duration = 1;
|
||||
impl->clock->delay = 0;
|
||||
impl->clock->rate_diff = corr;
|
||||
impl->clock->next_nsec += (uint64_t) (target * SPA_NSEC_PER_SEC * corr);
|
||||
}
|
||||
if (b->h) {
|
||||
b->h->flags = 0;
|
||||
if (fmd.status != FrameMetadata::Status::FrameSuccess)
|
||||
b->h->flags |= SPA_META_HEADER_FLAG_CORRUPTED;
|
||||
b->h->offset = 0;
|
||||
b->h->seq = fmd.sequence;
|
||||
b->h->pts = fmd.timestamp;
|
||||
b->h->dts_offset = 0;
|
||||
}
|
||||
request->reuse(libcamera::Request::ReuseFlag::ReuseBuffers);
|
||||
spa_log_trace(impl->log, "%p: request %p[%" PRIu64 "] completed status:%u seq:%" PRIu32,
|
||||
impl, request, request->cookie(),
|
||||
static_cast<unsigned int>(request->status()),
|
||||
request->sequence());
|
||||
|
||||
spa_ringbuffer_get_write_index(&impl->completed_requests_rb, &index);
|
||||
impl->completed_requests[index & MASK_BUFFERS] = request;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue