mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	spa: libcamera: source: remove impl::pendingRequests
				
					
				
			The handling of `impl::pendingRequests` is a bit problematic because,
for example, during startup, if `spa_libcamera_buffer_recycle()` observes
that `impl::active == false`, then it will try to append to `impl::pendingRequests`,
which is being iterated in the main thread in `spa_libcamera_stream_on()`.
That is not allowed on an `std::deque`.
So instead remove it altogether, and simply queue all requests when starting.
After `libcamera::Camera::stop()` returns, every request is guaranteed not
to be used by libcamera, and they can be freely reused, so this is safe to do.
This also removes the need for calling `spa_libcamera_buffer_recycle()` when
the buffers are set/unset on a port since that function no longer changes
anything apart from updating `buffer::flags` but `spa_libcamera_alloc_buffers()`
is modified appropriately to take care of that. And in the case of
`spa_libcamera_clear_buffers()` clearing the flag is not required because the
next `spa_libcamera_alloc_buffers()` call will reset reset the flags.
(cherry picked from commit 68627c5563)
			
			
This commit is contained in:
		
							parent
							
								
									ceb10964d3
								
							
						
					
					
						commit
						c80af0c2c0
					
				
					 1 changed files with 7 additions and 22 deletions
				
			
		| 
						 | 
					@ -6,7 +6,6 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <array>
 | 
					#include <array>
 | 
				
			||||||
#include <cstddef>
 | 
					#include <cstddef>
 | 
				
			||||||
#include <deque>
 | 
					 | 
				
			||||||
#include <limits>
 | 
					#include <limits>
 | 
				
			||||||
#include <optional>
 | 
					#include <optional>
 | 
				
			||||||
#include <type_traits>
 | 
					#include <type_traits>
 | 
				
			||||||
| 
						 | 
					@ -156,7 +155,6 @@ struct impl {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	FrameBufferAllocator *allocator = nullptr;
 | 
						FrameBufferAllocator *allocator = nullptr;
 | 
				
			||||||
	std::vector<std::unique_ptr<libcamera::Request>> requestPool;
 | 
						std::vector<std::unique_ptr<libcamera::Request>> requestPool;
 | 
				
			||||||
	std::deque<libcamera::Request *> pendingRequests;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void requestComplete(libcamera::Request *request);
 | 
						void requestComplete(libcamera::Request *request);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -256,10 +254,7 @@ int spa_libcamera_buffer_recycle(struct impl *impl, struct port *port, uint32_t
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	Request *request = impl->requestPool[buffer_id].get();
 | 
						Request *request = impl->requestPool[buffer_id].get();
 | 
				
			||||||
	if (!impl->active) {
 | 
						if (impl->active) {
 | 
				
			||||||
		impl->pendingRequests.push_back(request);
 | 
					 | 
				
			||||||
		return 0;
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		request->controls().merge(impl->ctrls);
 | 
							request->controls().merge(impl->ctrls);
 | 
				
			||||||
		impl->ctrls.clear();
 | 
							impl->ctrls.clear();
 | 
				
			||||||
		if ((res = impl->camera->queueRequest(request)) < 0) {
 | 
							if ((res = impl->camera->queueRequest(request)) < 0) {
 | 
				
			||||||
| 
						 | 
					@ -358,10 +353,6 @@ int spa_libcamera_clear_buffers(struct impl *impl, struct port *port)
 | 
				
			||||||
		b = &port->buffers[i];
 | 
							b = &port->buffers[i];
 | 
				
			||||||
		d = b->outbuf->datas;
 | 
							d = b->outbuf->datas;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (SPA_FLAG_IS_SET(b->flags, BUFFER_FLAG_OUTSTANDING)) {
 | 
					 | 
				
			||||||
			spa_log_debug(impl->log, "queueing outstanding buffer %p", b);
 | 
					 | 
				
			||||||
			spa_libcamera_buffer_recycle(impl, port, i);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if (SPA_FLAG_IS_SET(b->flags, BUFFER_FLAG_MAPPED)) {
 | 
							if (SPA_FLAG_IS_SET(b->flags, BUFFER_FLAG_MAPPED)) {
 | 
				
			||||||
			munmap(SPA_PTROFF(b->ptr, -d[0].mapoffset, void),
 | 
								munmap(SPA_PTROFF(b->ptr, -d[0].mapoffset, void),
 | 
				
			||||||
					d[0].maxsize - d[0].mapoffset);
 | 
										d[0].maxsize - d[0].mapoffset);
 | 
				
			||||||
| 
						 | 
					@ -370,7 +361,6 @@ int spa_libcamera_clear_buffers(struct impl *impl, struct port *port)
 | 
				
			||||||
		d[0].type = SPA_ID_INVALID;
 | 
							d[0].type = SPA_ID_INVALID;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	impl->pendingRequests.clear();
 | 
					 | 
				
			||||||
	port->n_buffers = 0;
 | 
						port->n_buffers = 0;
 | 
				
			||||||
	port->ring = SPA_RINGBUFFER_INIT();
 | 
						port->ring = SPA_RINGBUFFER_INIT();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1149,7 +1139,7 @@ spa_libcamera_alloc_buffers(struct impl *impl, struct port *port,
 | 
				
			||||||
		b = &port->buffers[i];
 | 
							b = &port->buffers[i];
 | 
				
			||||||
		b->id = i;
 | 
							b->id = i;
 | 
				
			||||||
		b->outbuf = buffers[i];
 | 
							b->outbuf = buffers[i];
 | 
				
			||||||
		b->flags = BUFFER_FLAG_OUTSTANDING;
 | 
							b->flags = 0;
 | 
				
			||||||
		b->h = (struct spa_meta_header*)spa_buffer_find_meta_data(buffers[i], SPA_META_Header, sizeof(*b->h));
 | 
							b->h = (struct spa_meta_header*)spa_buffer_find_meta_data(buffers[i], SPA_META_Header, sizeof(*b->h));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		b->videotransform = (struct spa_meta_videotransform*)spa_buffer_find_meta_data(
 | 
							b->videotransform = (struct spa_meta_videotransform*)spa_buffer_find_meta_data(
 | 
				
			||||||
| 
						 | 
					@ -1222,8 +1212,6 @@ spa_libcamera_alloc_buffers(struct impl *impl, struct port *port,
 | 
				
			||||||
				return -EIO;
 | 
									return -EIO;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					 | 
				
			||||||
		spa_libcamera_buffer_recycle(impl, port, i);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	port->n_buffers = n_buffers;
 | 
						port->n_buffers = n_buffers;
 | 
				
			||||||
| 
						 | 
					@ -1351,11 +1339,12 @@ int spa_libcamera_stream_on(struct impl *impl)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	impl->camera->requestCompleted.connect(impl, &impl::requestComplete);
 | 
						impl->camera->requestCompleted.connect(impl, &impl::requestComplete);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (Request *req : impl->pendingRequests) {
 | 
						for (auto& req : impl->requestPool) {
 | 
				
			||||||
		if ((res = impl->camera->queueRequest(req)) < 0)
 | 
							req->reuse(libcamera::Request::ReuseFlag::ReuseBuffers);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ((res = impl->camera->queueRequest(req.get())) < 0)
 | 
				
			||||||
			goto err_stop_camera;
 | 
								goto err_stop_camera;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	impl->pendingRequests.clear();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	impl->dll.bw = 0.0;
 | 
						impl->dll.bw = 0.0;
 | 
				
			||||||
	impl->active = true;
 | 
						impl->active = true;
 | 
				
			||||||
| 
						 | 
					@ -1378,15 +1367,11 @@ int spa_libcamera_stream_off(struct impl *impl)
 | 
				
			||||||
	struct port *port = &impl->out_ports[0];
 | 
						struct port *port = &impl->out_ports[0];
 | 
				
			||||||
	int res;
 | 
						int res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!impl->active) {
 | 
						if (!impl->active)
 | 
				
			||||||
		for (std::unique_ptr<Request> &req : impl->requestPool)
 | 
					 | 
				
			||||||
			req->reuse(libcamera::Request::ReuseFlag::ReuseBuffers);
 | 
					 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	impl->active = false;
 | 
						impl->active = false;
 | 
				
			||||||
	spa_log_info(impl->log, "stopping camera %s", impl->camera->id().c_str());
 | 
						spa_log_info(impl->log, "stopping camera %s", impl->camera->id().c_str());
 | 
				
			||||||
	impl->pendingRequests.clear();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((res = impl->camera->stop()) < 0) {
 | 
						if ((res = impl->camera->stop()) < 0) {
 | 
				
			||||||
		spa_log_warn(impl->log, "error stopping camera %s: %s",
 | 
							spa_log_warn(impl->log, "error stopping camera %s: %s",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue