diff options
-rw-r--r-- | include/libcamera/camera.h | 4 | ||||
-rw-r--r-- | include/libcamera/request.h | 14 | ||||
-rw-r--r-- | src/android/camera_device.cpp | 31 | ||||
-rw-r--r-- | src/cam/buffer_writer.cpp | 5 | ||||
-rw-r--r-- | src/cam/buffer_writer.h | 3 | ||||
-rw-r--r-- | src/cam/capture.cpp | 42 | ||||
-rw-r--r-- | src/cam/capture.h | 5 | ||||
-rw-r--r-- | src/libcamera/camera.cpp | 48 | ||||
-rw-r--r-- | src/libcamera/include/pipeline_handler.h | 5 | ||||
-rw-r--r-- | src/libcamera/pipeline/ipu3/ipu3.cpp | 124 | ||||
-rw-r--r-- | src/libcamera/pipeline/rkisp1/rkisp1.cpp | 41 | ||||
-rw-r--r-- | src/libcamera/pipeline/uvcvideo.cpp | 22 | ||||
-rw-r--r-- | src/libcamera/pipeline/vimc.cpp | 22 | ||||
-rw-r--r-- | src/libcamera/pipeline_handler.cpp | 2 | ||||
-rw-r--r-- | src/libcamera/request.cpp | 30 | ||||
-rw-r--r-- | src/qcam/main_window.cpp | 44 | ||||
-rw-r--r-- | src/qcam/main_window.h | 6 | ||||
-rw-r--r-- | src/v4l2/v4l2_camera.cpp | 60 | ||||
-rw-r--r-- | src/v4l2/v4l2_camera.h | 39 | ||||
-rw-r--r-- | src/v4l2/v4l2_camera_proxy.cpp | 17 | ||||
-rw-r--r-- | test/camera/buffer_import.cpp | 19 | ||||
-rw-r--r-- | test/camera/capture.cpp | 38 | ||||
-rw-r--r-- | test/camera/statemachine.cpp | 12 |
23 files changed, 266 insertions, 367 deletions
diff --git a/include/libcamera/camera.h b/include/libcamera/camera.h index 2fd5870b..28655bec 100644 --- a/include/libcamera/camera.h +++ b/include/libcamera/camera.h @@ -19,7 +19,7 @@ namespace libcamera { -class Buffer; +class FrameBuffer; class FrameBufferAllocator; class PipelineHandler; class Request; @@ -78,7 +78,7 @@ public: const std::string &name() const; - Signal<Request *, Buffer *> bufferCompleted; + Signal<Request *, FrameBuffer *> bufferCompleted; Signal<Request *> requestCompleted; Signal<Camera *> disconnected; diff --git a/include/libcamera/request.h b/include/libcamera/request.h index b8324224..eded6831 100644 --- a/include/libcamera/request.h +++ b/include/libcamera/request.h @@ -17,9 +17,9 @@ namespace libcamera { -class Buffer; class Camera; class CameraControlValidator; +class FrameBuffer; class Stream; class Request @@ -38,9 +38,9 @@ public: ControlList &controls() { return *controls_; } ControlList &metadata() { return *metadata_; } - const std::map<Stream *, Buffer *> &buffers() const { return bufferMap_; } - int addBuffer(Stream *stream, std::unique_ptr<Buffer> buffer); - Buffer *findBuffer(Stream *stream) const; + const std::map<Stream *, FrameBuffer *> &buffers() const { return bufferMap_; } + int addBuffer(Stream *stream, FrameBuffer *buffer); + FrameBuffer *findBuffer(Stream *stream) const; uint64_t cookie() const { return cookie_; } Status status() const { return status_; } @@ -52,14 +52,14 @@ private: void complete(); - bool completeBuffer(Buffer *buffer); + bool completeBuffer(FrameBuffer *buffer); Camera *camera_; CameraControlValidator *validator_; ControlList *controls_; ControlList *metadata_; - std::map<Stream *, Buffer *> bufferMap_; - std::unordered_set<Buffer *> pending_; + std::map<Stream *, FrameBuffer *> bufferMap_; + std::unordered_set<FrameBuffer *> pending_; const uint64_t cookie_; Status status_; diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp index ebe91ea8..ab3e4488 100644 --- a/src/android/camera_device.cpp +++ b/src/android/camera_device.cpp @@ -739,13 +739,21 @@ void CameraDevice::processCaptureRequest(camera3_capture_request_t *camera3Reque * and (currently) only supported request buffer. */ const buffer_handle_t camera3Handle = *camera3Buffers[0].buffer; - std::array<int, 3> fds = { - camera3Handle->data[0], - camera3Handle->data[1], - camera3Handle->data[2], - }; - std::unique_ptr<Buffer> buffer = stream->createBuffer(fds); + std::vector<FrameBuffer::Plane> planes; + for (int i = 0; i < 3; i++) { + FrameBuffer::Plane plane; + plane.fd = FileDescriptor(camera3Handle->data[i]); + /* + * Setting length to zero here is OK as the length is only used + * to map the memory of the plane. Libcamera do not need to poke + * at the memory content queued by the HAL. + */ + plane.length = 0; + planes.push_back(std::move(plane)); + } + + FrameBuffer *buffer = new FrameBuffer(std::move(planes)); if (!buffer) { LOG(HAL, Error) << "Failed to create buffer"; delete descriptor; @@ -754,7 +762,7 @@ void CameraDevice::processCaptureRequest(camera3_capture_request_t *camera3Reque Request *request = camera_->createRequest(reinterpret_cast<uint64_t>(descriptor)); - request->addBuffer(stream, std::move(buffer)); + request->addBuffer(stream, buffer); int ret = camera_->queueRequest(request); if (ret) { @@ -771,8 +779,8 @@ error: void CameraDevice::requestComplete(Request *request) { - const std::map<Stream *, Buffer *> &buffers = request->buffers(); - Buffer *libcameraBuffer = buffers.begin()->second; + const std::map<Stream *, FrameBuffer *> &buffers = request->buffers(); + FrameBuffer *buffer = buffers.begin()->second; camera3_buffer_status status = CAMERA3_BUFFER_STATUS_OK; std::unique_ptr<CameraMetadata> resultMetadata; @@ -803,11 +811,11 @@ void CameraDevice::requestComplete(Request *request) if (status == CAMERA3_BUFFER_STATUS_OK) { notifyShutter(descriptor->frameNumber, - libcameraBuffer->metadata().timestamp); + buffer->metadata().timestamp); captureResult.partial_result = 1; resultMetadata = getResultMetadata(descriptor->frameNumber, - libcameraBuffer->metadata().timestamp); + buffer->metadata().timestamp); captureResult.result = resultMetadata->get(); } @@ -825,6 +833,7 @@ void CameraDevice::requestComplete(Request *request) callbacks_->process_capture_result(callbacks_, &captureResult); delete descriptor; + delete buffer; } void CameraDevice::notifyShutter(uint32_t frameNumber, uint64_t timestamp) diff --git a/src/cam/buffer_writer.cpp b/src/cam/buffer_writer.cpp index 41ef4b0a..1d7366c8 100644 --- a/src/cam/buffer_writer.cpp +++ b/src/cam/buffer_writer.cpp @@ -22,7 +22,7 @@ BufferWriter::BufferWriter(const std::string &pattern) { } -int BufferWriter::write(Buffer *buffer, const std::string &streamName) +int BufferWriter::write(FrameBuffer *buffer, const std::string &streamName) { std::string filename; size_t pos; @@ -43,8 +43,7 @@ int BufferWriter::write(Buffer *buffer, const std::string &streamName) if (fd == -1) return -errno; - BufferMemory *mem = buffer->mem(); - for (const FrameBuffer::Plane &plane : mem->planes()) { + for (const FrameBuffer::Plane &plane : buffer->planes()) { /* \todo Once the FrameBuffer is done cache mapped memory. */ void *data = mmap(NULL, plane.length, PROT_READ, MAP_SHARED, plane.fd.fd(), 0); diff --git a/src/cam/buffer_writer.h b/src/cam/buffer_writer.h index 7bf785d1..5917a7df 100644 --- a/src/cam/buffer_writer.h +++ b/src/cam/buffer_writer.h @@ -16,7 +16,8 @@ class BufferWriter public: BufferWriter(const std::string &pattern = "frame-#.bin"); - int write(libcamera::Buffer *buffer, const std::string &streamName); + int write(libcamera::FrameBuffer *buffer, + const std::string &streamName); private: std::string pattern_; diff --git a/src/cam/capture.cpp b/src/cam/capture.cpp index da942f56..dd078eb0 100644 --- a/src/cam/capture.cpp +++ b/src/cam/capture.cpp @@ -57,7 +57,10 @@ int Capture::run(EventLoop *loop, const OptionsParser::Options &options) writer_ = new BufferWriter(); } - ret = capture(loop); + + FrameBufferAllocator *allocator = FrameBufferAllocator::create(camera_); + + ret = capture(loop, allocator); if (options.isSet(OptFile)) { delete writer_; @@ -66,17 +69,27 @@ int Capture::run(EventLoop *loop, const OptionsParser::Options &options) camera_->freeBuffers(); + delete allocator; + return ret; } -int Capture::capture(EventLoop *loop) +int Capture::capture(EventLoop *loop, FrameBufferAllocator *allocator) { int ret; /* Identify the stream with the least number of buffers. */ unsigned int nbuffers = UINT_MAX; - for (StreamConfiguration &cfg : *config_) - nbuffers = std::min(nbuffers, cfg.bufferCount); + for (StreamConfiguration &cfg : *config_) { + ret = allocator->allocate(cfg.stream()); + if (ret < 0) { + std::cerr << "Can't allocate buffers" << std::endl; + return -ENOMEM; + } + + unsigned int allocated = allocator->buffers(cfg.stream()).size(); + nbuffers = std::min(nbuffers, allocated); + } /* * TODO: make cam tool smarter to support still capture by for @@ -93,9 +106,11 @@ int Capture::capture(EventLoop *loop) for (StreamConfiguration &cfg : *config_) { Stream *stream = cfg.stream(); - std::unique_ptr<Buffer> buffer = stream->createBuffer(i); + const std::vector<std::unique_ptr<FrameBuffer>> &buffers = + allocator->buffers(stream); + const std::unique_ptr<FrameBuffer> &buffer = buffers[i]; - ret = request->addBuffer(stream, std::move(buffer)); + ret = request->addBuffer(stream, buffer.get()); if (ret < 0) { std::cerr << "Can't set buffer for request" << std::endl; @@ -138,7 +153,7 @@ void Capture::requestComplete(Request *request) if (request->status() == Request::RequestCancelled) return; - const std::map<Stream *, Buffer *> &buffers = request->buffers(); + const std::map<Stream *, FrameBuffer *> &buffers = request->buffers(); std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now(); double fps = std::chrono::duration_cast<std::chrono::milliseconds>(now - last_).count(); @@ -151,7 +166,7 @@ void Capture::requestComplete(Request *request) for (auto it = buffers.begin(); it != buffers.end(); ++it) { Stream *stream = it->first; - Buffer *buffer = it->second; + FrameBuffer *buffer = it->second; const std::string &name = streamName_[stream]; const FrameMetadata &metadata = buffer->metadata(); @@ -185,16 +200,9 @@ void Capture::requestComplete(Request *request) for (auto it = buffers.begin(); it != buffers.end(); ++it) { Stream *stream = it->first; - Buffer *buffer = it->second; - unsigned int index = buffer->index(); - - std::unique_ptr<Buffer> newBuffer = stream->createBuffer(index); - if (!newBuffer) { - std::cerr << "Can't create buffer" << std::endl; - return; - } + FrameBuffer *buffer = it->second; - request->addBuffer(stream, std::move(newBuffer)); + request->addBuffer(stream, buffer); } camera_->queueRequest(request); diff --git a/src/cam/capture.h b/src/cam/capture.h index c692d489..9bca5661 100644 --- a/src/cam/capture.h +++ b/src/cam/capture.h @@ -10,7 +10,9 @@ #include <chrono> #include <memory> +#include <libcamera/buffer.h> #include <libcamera/camera.h> +#include <libcamera/framebuffer_allocator.h> #include <libcamera/request.h> #include <libcamera/stream.h> @@ -26,7 +28,8 @@ public: int run(EventLoop *loop, const OptionsParser::Options &options); private: - int capture(EventLoop *loop); + int capture(EventLoop *loop, + libcamera::FrameBufferAllocator *allocator); void requestComplete(libcamera::Request *request); diff --git a/src/libcamera/camera.cpp b/src/libcamera/camera.cpp index 20340167..3fe40feb 100644 --- a/src/libcamera/camera.cpp +++ b/src/libcamera/camera.cpp @@ -695,12 +695,6 @@ int Camera::configure(CameraConfiguration *config) stream->configuration_ = cfg; activeStreams_.insert(stream); - - /* - * Allocate buffer objects in the pool. - * Memory will be allocated and assigned later. - */ - stream->createBuffers(cfg.memoryType, cfg.bufferCount); } state_ = CameraConfigured; @@ -756,14 +750,6 @@ int Camera::freeBuffers() if (!stateIs(CameraPrepared)) return -EACCES; - for (Stream *stream : activeStreams_) { - /* - * All mappings must be destroyed before buffers can be freed - * by the V4L2 device that has allocated them. - */ - stream->destroyBuffers(); - } - state_ = CameraConfigured; return pipe_->freeBuffers(this, activeStreams_); @@ -834,24 +820,11 @@ int Camera::queueRequest(Request *request) for (auto const &it : request->buffers()) { Stream *stream = it.first; - Buffer *buffer = it.second; if (activeStreams_.find(stream) == activeStreams_.end()) { LOG(Camera, Error) << "Invalid request"; return -EINVAL; } - - if (stream->memoryType() == ExternalMemory) { - int index = stream->mapBuffer(buffer); - if (index < 0) { - LOG(Camera, Error) << "No buffer memory available"; - return -ENOMEM; - } - - buffer->index_ = index; - } - - buffer->mem_ = &stream->buffers()[buffer->index_]; } return pipe_->queueRequest(this, request); @@ -880,6 +853,13 @@ int Camera::start() LOG(Camera, Debug) << "Starting capture"; + for (Stream *stream : activeStreams_) { + if (allocator_ && !allocator_->buffers(stream).empty()) + continue; + + pipe_->importFrameBuffers(this, stream); + } + int ret = pipe_->start(this); if (ret) return ret; @@ -915,6 +895,13 @@ int Camera::stop() pipe_->stop(this); + for (Stream *stream : activeStreams_) { + if (allocator_ && !allocator_->buffers(stream).empty()) + continue; + + pipe_->freeFrameBuffers(this, stream); + } + return 0; } @@ -928,13 +915,6 @@ int Camera::stop() */ void Camera::requestComplete(Request *request) { - for (auto it : request->buffers()) { - Stream *stream = it.first; - Buffer *buffer = it.second; - if (stream->memoryType() == ExternalMemory) - stream->unmapBuffer(buffer); - } - requestCompleted.emit(request); delete request; } diff --git a/src/libcamera/include/pipeline_handler.h b/src/libcamera/include/pipeline_handler.h index 560be3ba..27f3852c 100644 --- a/src/libcamera/include/pipeline_handler.h +++ b/src/libcamera/include/pipeline_handler.h @@ -21,12 +21,12 @@ namespace libcamera { -class Buffer; class Camera; class CameraConfiguration; class CameraManager; class DeviceEnumerator; class DeviceMatch; +class FrameBuffer; class MediaDevice; class PipelineHandler; class Request; @@ -85,7 +85,8 @@ public: int queueRequest(Camera *camera, Request *request); - bool completeBuffer(Camera *camera, Request *request, Buffer *buffer); + bool completeBuffer(Camera *camera, Request *request, + FrameBuffer *buffer); void completeRequest(Camera *camera, Request *request); const char *name() const { return name_; } diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index b73f0f07..065f5d98 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -31,6 +31,8 @@ namespace libcamera { LOG_DEFINE_CATEGORY(IPU3) +class IPU3CameraData; + class ImgUDevice { public: @@ -44,7 +46,6 @@ public: V4L2VideoDevice *dev; unsigned int pad; std::string name; - BufferPool *pool; std::vector<std::unique_ptr<FrameBuffer>> buffers; }; @@ -71,9 +72,7 @@ public: int configureOutput(ImgUOutput *output, const StreamConfiguration &cfg); - int importOutputBuffers(ImgUOutput *output, BufferPool *pool); - int exportOutputBuffers(ImgUOutput *output, BufferPool *pool); - void freeBuffers(); + void freeBuffers(IPU3CameraData *data); int start(); int stop(); @@ -93,9 +92,6 @@ public: ImgUOutput viewfinder_; ImgUOutput stat_; /* \todo Add param video device for 3A tuning */ - - BufferPool vfPool_; - BufferPool outPool_; }; class CIO2Device @@ -156,7 +152,7 @@ public: { } - void imguOutputBufferReady(Buffer *buffer); + void imguOutputBufferReady(FrameBuffer *buffer); void imguInputBufferReady(FrameBuffer *buffer); void cio2BufferReady(FrameBuffer *buffer); @@ -691,39 +687,30 @@ int PipelineHandlerIPU3::allocateBuffers(Camera *camera, goto error; } - /* Allocate buffers for each active stream. */ - for (Stream *s : streams) { - IPU3Stream *stream = static_cast<IPU3Stream *>(s); - ImgUDevice::ImgUOutput *dev = stream->device_; - - if (stream->memoryType() == InternalMemory) - ret = imgu->exportOutputBuffers(dev, &stream->bufferPool()); - else - ret = imgu->importOutputBuffers(dev, &stream->bufferPool()); - if (ret) - goto error; - } - /* * Allocate buffers also on non-active outputs; use the same number * of buffers as the active ones. */ if (!outStream->active_) { - bufferCount = vfStream->configuration().bufferCount; - outStream->device_->pool->createBuffers(bufferCount); - ret = imgu->exportOutputBuffers(outStream->device_, - outStream->device_->pool); - if (ret) + ImgUDevice::ImgUOutput *output = outStream->device_; + + ret = output->dev->exportBuffers(bufferCount, &output->buffers); + if (ret < 0) { + LOG(IPU3, Error) << "Failed to allocate ImgU " + << output->name << " buffers"; goto error; + } } if (!vfStream->active_) { - bufferCount = outStream->configuration().bufferCount; - vfStream->device_->pool->createBuffers(bufferCount); - ret = imgu->exportOutputBuffers(vfStream->device_, - vfStream->device_->pool); - if (ret) + ImgUDevice::ImgUOutput *output = vfStream->device_; + + ret = output->dev->exportBuffers(bufferCount, &output->buffers); + if (ret < 0) { + LOG(IPU3, Error) << "Failed to allocate ImgU " + << output->name << " buffers"; goto error; + } } return 0; @@ -740,7 +727,7 @@ int PipelineHandlerIPU3::freeBuffers(Camera *camera, IPU3CameraData *data = cameraData(camera); data->cio2_.freeBuffers(); - data->imgu_->freeBuffers(); + data->imgu_->freeBuffers(data); return 0; } @@ -793,7 +780,7 @@ int PipelineHandlerIPU3::queueRequestDevice(Camera *camera, Request *request) for (auto it : request->buffers()) { IPU3Stream *stream = static_cast<IPU3Stream *>(it.first); - Buffer *buffer = it.second; + FrameBuffer *buffer = it.second; int ret = stream->device_->dev->queueBuffer(buffer); if (ret < 0) @@ -920,9 +907,9 @@ int PipelineHandlerIPU3::registerCameras() &IPU3CameraData::cio2BufferReady); data->imgu_->input_->frameBufferReady.connect(data.get(), &IPU3CameraData::imguInputBufferReady); - data->imgu_->output_.dev->bufferReady.connect(data.get(), + data->imgu_->output_.dev->frameBufferReady.connect(data.get(), &IPU3CameraData::imguOutputBufferReady); - data->imgu_->viewfinder_.dev->bufferReady.connect(data.get(), + data->imgu_->viewfinder_.dev->frameBufferReady.connect(data.get(), &IPU3CameraData::imguOutputBufferReady); /* Create and register the Camera instance. */ @@ -971,7 +958,7 @@ void IPU3CameraData::imguInputBufferReady(FrameBuffer *buffer) * * Buffers completed from the ImgU output are directed to the application. */ -void IPU3CameraData::imguOutputBufferReady(Buffer *buffer) +void IPU3CameraData::imguOutputBufferReady(FrameBuffer *buffer) { Request *request = buffer->request(); @@ -1046,7 +1033,6 @@ int ImgUDevice::init(MediaDevice *media, unsigned int index) output_.pad = PAD_OUTPUT; output_.name = "output"; - output_.pool = &outPool_; viewfinder_.dev = V4L2VideoDevice::fromEntityName(media, name_ + " viewfinder"); @@ -1056,7 +1042,6 @@ int ImgUDevice::init(MediaDevice *media, unsigned int index) viewfinder_.pad = PAD_VF; viewfinder_.name = "viewfinder"; - viewfinder_.pool = &vfPool_; stat_.dev = V4L2VideoDevice::fromEntityName(media, name_ + " 3a stat"); ret = stat_.dev->open(); @@ -1165,68 +1150,27 @@ int ImgUDevice::configureOutput(ImgUOutput *output, } /** - * \brief Export buffers from \a output to the provided \a pool - * \param[in] output The ImgU output device - * \param[in] pool The buffer pool where to export buffers - * - * Export memory buffers reserved in the video device memory associated with - * \a output id to the buffer pool provided as argument. - * - * \return 0 on success or a negative error code otherwise - */ -int ImgUDevice::exportOutputBuffers(ImgUOutput *output, BufferPool *pool) -{ - int ret = output->dev->exportBuffers(pool); - if (ret) { - LOG(IPU3, Error) << "Failed to export ImgU " - << output->name << " buffers"; - return ret; - } - - return 0; -} - -/** - * \brief Reserve buffers in \a output from the provided \a pool - * \param[in] output The ImgU output device - * \param[in] pool The buffer pool used to reserve buffers in \a output - * - * Reserve a number of buffers equal to the number of buffers in \a pool - * in the \a output device. - * - * \return 0 on success or a negative error code otherwise - */ -int ImgUDevice::importOutputBuffers(ImgUOutput *output, BufferPool *pool) -{ - int ret = output->dev->importBuffers(pool); - if (ret) { - LOG(IPU3, Error) - << "Failed to import buffer in " << output->name - << " ImgU device"; - return ret; - } - - return 0; -} - -/** * \brief Release buffers for all the ImgU video devices */ -void ImgUDevice::freeBuffers() +void ImgUDevice::freeBuffers(IPU3CameraData *data) { int ret; - ret = output_.dev->releaseBuffers(); - if (ret) - LOG(IPU3, Error) << "Failed to release ImgU output buffers"; + if (!data->outStream_.active_) { + ret = output_.dev->releaseBuffers(); + if (ret) + LOG(IPU3, Error) << "Failed to release ImgU output buffers"; + } ret = stat_.dev->releaseBuffers(); if (ret) LOG(IPU3, Error) << "Failed to release ImgU stat buffers"; - ret = viewfinder_.dev->releaseBuffers(); - if (ret) - LOG(IPU3, Error) << "Failed to release ImgU viewfinder buffers"; + if (!data->vfStream_.active_) { + ret = viewfinder_.dev->releaseBuffers(); + if (ret) + LOG(IPU3, Error) << "Failed to release ImgU viewfinder buffers"; + } ret = input_->releaseBuffers(); if (ret) diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp index ba8f93e8..d669d2de 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp @@ -51,7 +51,7 @@ struct RkISP1FrameInfo { FrameBuffer *paramBuffer; FrameBuffer *statBuffer; - Buffer *videoBuffer; + FrameBuffer *videoBuffer; bool paramFilled; bool paramDequeued; @@ -67,7 +67,6 @@ public: int destroy(unsigned int frame); RkISP1FrameInfo *find(unsigned int frame); - RkISP1FrameInfo *find(Buffer *buffer); RkISP1FrameInfo *find(FrameBuffer *buffer); RkISP1FrameInfo *find(Request *request); @@ -87,7 +86,7 @@ public: setDelay(QueueBuffers, -1, 10); } - void bufferReady(Buffer *buffer) + void bufferReady(FrameBuffer *buffer) { /* * Calculate SOE by taking the end of DMA set by the kernel and applying @@ -205,7 +204,7 @@ private: int initLinks(); int createCamera(MediaEntity *sensor); void tryCompleteRequest(Request *request); - void bufferReady(Buffer *buffer); + void bufferReady(FrameBuffer *buffer); void paramReady(FrameBuffer *buffer); void statReady(FrameBuffer *buffer); @@ -243,7 +242,7 @@ RkISP1FrameInfo *RkISP1Frames::create(unsigned int frame, Request *request, Stre } FrameBuffer *statBuffer = pipe_->availableStatBuffers_.front(); - Buffer *videoBuffer = request->findBuffer(stream); + FrameBuffer *videoBuffer = request->findBuffer(stream); if (!videoBuffer) { LOG(RkISP1, Error) << "Attempt to queue request with invalid stream"; @@ -296,26 +295,14 @@ RkISP1FrameInfo *RkISP1Frames::find(unsigned int frame) return nullptr; } -RkISP1FrameInfo *RkISP1Frames::find(Buffer *buffer) -{ - for (auto &itInfo : frameInfo_) { - RkISP1FrameInfo *info = itInfo.second; - - if (info->videoBuffer == buffer) - return info; - } - - LOG(RkISP1, Error) << "Can't locate info from buffer"; - return nullptr; -} - RkISP1FrameInfo *RkISP1Frames::find(FrameBuffer *buffer) { for (auto &itInfo : frameInfo_) { RkISP1FrameInfo *info = itInfo.second; if (info->paramBuffer == buffer || - info->statBuffer == buffer) + info->statBuffer == buffer || + info->videoBuffer == buffer) return info; } @@ -692,18 +679,9 @@ int PipelineHandlerRkISP1::allocateBuffers(Camera *camera, const std::set<Stream *> &streams) { RkISP1CameraData *data = cameraData(camera); - Stream *stream = *streams.begin(); unsigned int count = 1; int ret; - if (stream->memoryType() == InternalMemory) - ret = video_->exportBuffers(&stream->bufferPool()); - else - ret = video_->importBuffers(&stream->bufferPool()); - - if (ret) - return ret; - unsigned int maxBuffers = 0; for (const Stream *s : camera->streams()) maxBuffers = std::max(maxBuffers, s->configuration().bufferCount); @@ -769,9 +747,6 @@ int PipelineHandlerRkISP1::freeBuffers(Camera *camera, if (stat_->releaseBuffers()) LOG(RkISP1, Error) << "Failed to release stat buffers"; - if (video_->releaseBuffers()) - LOG(RkISP1, Error) << "Failed to release video buffers"; - return 0; } @@ -975,7 +950,7 @@ bool PipelineHandlerRkISP1::match(DeviceEnumerator *enumerator) if (param_->open() < 0) return false; - video_->bufferReady.connect(this, &PipelineHandlerRkISP1::bufferReady); + video_->frameBufferReady.connect(this, &PipelineHandlerRkISP1::bufferReady); stat_->frameBufferReady.connect(this, &PipelineHandlerRkISP1::statReady); param_->frameBufferReady.connect(this, &PipelineHandlerRkISP1::paramReady); @@ -1024,7 +999,7 @@ void PipelineHandlerRkISP1::tryCompleteRequest(Request *request) completeRequest(activeCamera_, request); } -void PipelineHandlerRkISP1::bufferReady(Buffer *buffer) +void PipelineHandlerRkISP1::bufferReady(FrameBuffer *buffer) { ASSERT(activeCamera_); RkISP1CameraData *data = cameraData(activeCamera_); diff --git a/src/libcamera/pipeline/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo.cpp index b72841ed..66380e29 100644 --- a/src/libcamera/pipeline/uvcvideo.cpp +++ b/src/libcamera/pipeline/uvcvideo.cpp @@ -42,7 +42,7 @@ public: } int init(MediaEntity *entity); - void bufferReady(Buffer *buffer); + void bufferReady(FrameBuffer *buffer); V4L2VideoDevice *video_; Stream stream_; @@ -225,23 +225,13 @@ void PipelineHandlerUVC::freeFrameBuffers(Camera *camera, Stream *stream) int PipelineHandlerUVC::allocateBuffers(Camera *camera, const std::set<Stream *> &streams) { - UVCCameraData *data = cameraData(camera); - Stream *stream = *streams.begin(); - const StreamConfiguration &cfg = stream->configuration(); - - LOG(UVC, Debug) << "Requesting " << cfg.bufferCount << " buffers"; - - if (stream->memoryType() == InternalMemory) - return data->video_->exportBuffers(&stream->bufferPool()); - else - return data->video_->importBuffers(&stream->bufferPool()); + return 0; } int PipelineHandlerUVC::freeBuffers(Camera *camera, const std::set<Stream *> &streams) { - UVCCameraData *data = cameraData(camera); - return data->video_->releaseBuffers(); + return 0; } int PipelineHandlerUVC::start(Camera *camera) @@ -295,7 +285,7 @@ int PipelineHandlerUVC::processControls(UVCCameraData *data, Request *request) int PipelineHandlerUVC::queueRequestDevice(Camera *camera, Request *request) { UVCCameraData *data = cameraData(camera); - Buffer *buffer = request->findBuffer(&data->stream_); + FrameBuffer *buffer = request->findBuffer(&data->stream_); if (!buffer) { LOG(UVC, Error) << "Attempt to queue request with invalid stream"; @@ -362,7 +352,7 @@ int UVCCameraData::init(MediaEntity *entity) if (ret) return ret; - video_->bufferReady.connect(this, &UVCCameraData::bufferReady); + video_->frameBufferReady.connect(this, &UVCCameraData::bufferReady); /* Initialise the supported controls. */ const ControlInfoMap &controls = video_->controls(); @@ -402,7 +392,7 @@ int UVCCameraData::init(MediaEntity *entity) return 0; } -void UVCCameraData::bufferReady(Buffer *buffer) +void UVCCameraData::bufferReady(FrameBuffer *buffer) { Request *request = buffer->request(); diff --git a/src/libcamera/pipeline/vimc.cpp b/src/libcamera/pipeline/vimc.cpp index 3fb5cacd..5e0f5c63 100644 --- a/src/libcamera/pipeline/vimc.cpp +++ b/src/libcamera/pipeline/vimc.cpp @@ -55,7 +55,7 @@ public: } int init(MediaDevice *media); - void bufferReady(Buffer *buffer); + void bufferReady(FrameBuffer *buffer); CameraSensor *sensor_; V4L2Subdevice *debayer_; @@ -291,23 +291,13 @@ void PipelineHandlerVimc::freeFrameBuffers(Camera *camera, Stream *stream) int PipelineHandlerVimc::allocateBuffers(Camera *camera, const std::set<Stream *> &streams) { - VimcCameraData *data = cameraData(camera); - Stream *stream = *streams.begin(); - const StreamConfiguration &cfg = stream->configuration(); - - LOG(VIMC, Debug) << "Requesting " << cfg.bufferCount << " buffers"; - - if (stream->memoryType() == InternalMemory) - return data->video_->exportBuffers(&stream->bufferPool()); - else - return data->video_->importBuffers(&stream->bufferPool()); + return 0; } int PipelineHandlerVimc::freeBuffers(Camera *camera, const std::set<Stream *> &streams) { - VimcCameraData *data = cameraData(camera); - return data->video_->releaseBuffers(); + return 0; } int PipelineHandlerVimc::start(Camera *camera) @@ -355,7 +345,7 @@ int PipelineHandlerVimc::processControls(VimcCameraData *data, Request *request) int PipelineHandlerVimc::queueRequestDevice(Camera *camera, Request *request) { VimcCameraData *data = cameraData(camera); - Buffer *buffer = request->findBuffer(&data->stream_); + FrameBuffer *buffer = request->findBuffer(&data->stream_); if (!buffer) { LOG(VIMC, Error) << "Attempt to queue request with invalid stream"; @@ -447,7 +437,7 @@ int VimcCameraData::init(MediaDevice *media) if (video_->open()) return -ENODEV; - video_->bufferReady.connect(this, &VimcCameraData::bufferReady); + video_->frameBufferReady.connect(this, &VimcCameraData::bufferReady); raw_ = new V4L2VideoDevice(media->getEntityByName("Raw Capture 1")); if (raw_->open()) @@ -484,7 +474,7 @@ int VimcCameraData::init(MediaDevice *media) return 0; } -void VimcCameraData::bufferReady(Buffer *buffer) +void VimcCameraData::bufferReady(FrameBuffer *buffer) { Request *request = buffer->request(); diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp index 11d68456..f6fb0974 100644 --- a/src/libcamera/pipeline_handler.cpp +++ b/src/libcamera/pipeline_handler.cpp @@ -472,7 +472,7 @@ int PipelineHandler::queueRequest(Camera *camera, Request *request) * otherwise */ bool PipelineHandler::completeBuffer(Camera *camera, Request *request, - Buffer *buffer) + FrameBuffer *buffer) { camera->bufferCompleted.emit(request, buffer); return request->completeBuffer(buffer); diff --git a/src/libcamera/request.cpp b/src/libcamera/request.cpp index 4268e314..ea33736f 100644 --- a/src/libcamera/request.cpp +++ b/src/libcamera/request.cpp @@ -75,11 +75,6 @@ Request::Request(Camera *camera, uint64_t cookie) Request::~Request() { - for (auto it : bufferMap_) { - Buffer *buffer = it.second; - delete buffer; - } - delete metadata_; delete controls_; delete validator_; @@ -106,18 +101,19 @@ Request::~Request() * \brief Retrieve the request's streams to buffers map * * Return a reference to the map that associates each Stream part of the - * request to the Buffer the Stream output should be directed to. + * request to the FrameBuffer the Stream output should be directed to. * - * \return The map of Stream to Buffer + * \return The map of Stream to FrameBuffer */ /** - * \brief Store a Buffer with its associated Stream in the Request + * \brief Add a FrameBuffer with its associated Stream to the Request * \param[in] stream The stream the buffer belongs to - * \param[in] buffer The Buffer to store in the request + * \param[in] buffer The FrameBuffer to add to the request * - * Ownership of the buffer is passed to the request. It will be deleted when - * the request is destroyed after completing. + * A reference to the buffer is stored in the request. The caller is responsible + * for ensuring that the buffer will remain valid until the request complete + * callback is called. * * A request can only contain one buffer per stream. If a buffer has already * been added to the request for the same stream, this method returns -EEXIST. @@ -126,7 +122,7 @@ Request::~Request() * \retval -EEXIST The request already contains a buffer for the stream * \retval -EINVAL The buffer does not reference a valid Stream */ -int Request::addBuffer(Stream *stream, std::unique_ptr<Buffer> buffer) +int Request::addBuffer(Stream *stream, FrameBuffer *buffer) { if (!stream) { LOG(Request, Error) << "Invalid stream reference"; @@ -135,13 +131,13 @@ int Request::addBuffer(Stream *stream, std::unique_ptr<Buffer> buffer) auto it = bufferMap_.find(stream); if (it != bufferMap_.end()) { - LOG(Request, Error) << "Buffer already set for stream"; + LOG(Request, Error) << "FrameBuffer already set for stream"; return -EEXIST; } buffer->request_ = this; - pending_.insert(buffer.get()); - bufferMap_[stream] = buffer.release(); + pending_.insert(buffer); + bufferMap_[stream] = buffer; return 0; } @@ -161,7 +157,7 @@ int Request::addBuffer(Stream *stream, std::unique_ptr<Buffer> buffer) * \return The buffer associated with the stream, or nullptr if the stream is * not part of this request */ -Buffer *Request::findBuffer(Stream *stream) const +FrameBuffer *Request::findBuffer(Stream *stream) const { auto it = bufferMap_.find(stream); if (it == bufferMap_.end()) @@ -231,7 +227,7 @@ void Request::complete() * \return True if all buffers contained in the request have completed, false * otherwise */ -bool Request::completeBuffer(Buffer *buffer) +bool Request::completeBuffer(FrameBuffer *buffer) { int ret = pending_.erase(buffer); ASSERT(ret == 1); diff --git a/src/qcam/main_window.cpp b/src/qcam/main_window.cpp index ca3464ba..701a2b9a 100644 --- a/src/qcam/main_window.cpp +++ b/src/qcam/main_window.cpp @@ -23,7 +23,7 @@ using namespace libcamera; MainWindow::MainWindow(CameraManager *cm, const OptionsParser::Options &options) - : options_(options), isCapturing_(false) + : options_(options), allocator_(nullptr), isCapturing_(false) { int ret; @@ -37,8 +37,10 @@ MainWindow::MainWindow(CameraManager *cm, const OptionsParser::Options &options) adjustSize(); ret = openCamera(cm); - if (!ret) + if (!ret) { + allocator_ = FrameBufferAllocator::create(camera_); ret = startCapture(); + } if (ret < 0) QTimer::singleShot(0, QCoreApplication::instance(), @@ -49,6 +51,7 @@ MainWindow::~MainWindow() { if (camera_) { stopCapture(); + delete allocator_; camera_->release(); camera_.reset(); } @@ -176,8 +179,14 @@ int MainWindow::startCapture() return ret; } + ret = allocator_->allocate(stream); + if (ret < 0) { + std::cerr << "Failed to allocate capture buffers" << std::endl; + return ret; + } + std::vector<Request *> requests; - for (unsigned int i = 0; i < cfg.bufferCount; ++i) { + for (const std::unique_ptr<FrameBuffer> &buffer : allocator_->buffers(stream)) { Request *request = camera_->createRequest(); if (!request) { std::cerr << "Can't create request" << std::endl; @@ -185,13 +194,7 @@ int MainWindow::startCapture() goto error; } - std::unique_ptr<Buffer> buffer = stream->createBuffer(i); - if (!buffer) { - std::cerr << "Can't create buffer " << i << std::endl; - goto error; - } - - ret = request->addBuffer(stream, std::move(buffer)); + ret = request->addBuffer(stream, buffer.get()); if (ret < 0) { std::cerr << "Can't set buffer for request" << std::endl; goto error; @@ -254,11 +257,11 @@ void MainWindow::requestComplete(Request *request) if (request->status() == Request::RequestCancelled) return; - const std::map<Stream *, Buffer *> &buffers = request->buffers(); + const std::map<Stream *, FrameBuffer *> &buffers = request->buffers(); framesCaptured_++; - Buffer *buffer = buffers.begin()->second; + FrameBuffer *buffer = buffers.begin()->second; const FrameMetadata &metadata = buffer->metadata(); double fps = metadata.timestamp - lastBufferTime_; @@ -281,28 +284,21 @@ void MainWindow::requestComplete(Request *request) for (auto it = buffers.begin(); it != buffers.end(); ++it) { Stream *stream = it->first; - Buffer *buffer = it->second; - unsigned int index = buffer->index(); - - std::unique_ptr<Buffer> newBuffer = stream->createBuffer(index); - if (!newBuffer) { - std::cerr << "Can't create buffer" << std::endl; - return; - } + FrameBuffer *buffer = it->second; - request->addBuffer(stream, std::move(newBuffer)); + request->addBuffer(stream, buffer); } camera_->queueRequest(request); } -int MainWindow::display(Buffer *buffer) +int MainWindow::display(FrameBuffer *buffer) { - if (buffer->mem()->planes().size() != 1) + if (buffer->planes().size() != 1) return -EINVAL; /* \todo Once the FrameBuffer is done cache mapped memory. */ - const FrameBuffer::Plane &plane = buffer->mem()->planes().front(); + const FrameBuffer::Plane &plane = buffer->planes().front(); void *memory = mmap(NULL, plane.length, PROT_READ, MAP_SHARED, plane.fd.fd(), 0); diff --git a/src/qcam/main_window.h b/src/qcam/main_window.h index 0786e915..05cde4ce 100644 --- a/src/qcam/main_window.h +++ b/src/qcam/main_window.h @@ -14,8 +14,10 @@ #include <QObject> #include <QTimer> +#include <libcamera/buffer.h> #include <libcamera/camera.h> #include <libcamera/camera_manager.h> +#include <libcamera/framebuffer_allocator.h> #include <libcamera/stream.h> #include "../cam/options.h" @@ -49,7 +51,7 @@ private: void stopCapture(); void requestComplete(Request *request); - int display(Buffer *buffer); + int display(FrameBuffer *buffer); QString title_; QTimer titleTimer_; @@ -57,6 +59,8 @@ private: const OptionsParser::Options &options_; std::shared_ptr<Camera> camera_; + FrameBufferAllocator *allocator_; + bool isCapturing_; std::unique_ptr<CameraConfiguration> config_; diff --git a/src/v4l2/v4l2_camera.cpp b/src/v4l2/v4l2_camera.cpp index e4a03c41..10db15d6 100644 --- a/src/v4l2/v4l2_camera.cpp +++ b/src/v4l2/v4l2_camera.cpp @@ -16,24 +16,15 @@ using namespace libcamera; LOG_DECLARE_CATEGORY(V4L2Compat); -V4L2FrameMetadata::V4L2FrameMetadata(Buffer *buffer) - : index_(buffer->index()), - bytesused_(buffer->metadata().planes[0].bytesused), - timestamp_(buffer->metadata().timestamp), - sequence_(buffer->metadata().sequence), - status_(buffer->metadata().status) -{ -} - V4L2Camera::V4L2Camera(std::shared_ptr<Camera> camera) - : camera_(camera), isRunning_(false) + : camera_(camera), isRunning_(false), bufferAllocator_(nullptr) { camera_->requestCompleted.connect(this, &V4L2Camera::requestComplete); } V4L2Camera::~V4L2Camera() { - camera_->release(); + close(); } int V4L2Camera::open() @@ -50,11 +41,16 @@ int V4L2Camera::open() return -EINVAL; } + bufferAllocator_ = FrameBufferAllocator::create(camera_); + return 0; } void V4L2Camera::close() { + delete bufferAllocator_; + bufferAllocator_ = nullptr; + camera_->release(); } @@ -63,12 +59,12 @@ void V4L2Camera::getStreamConfig(StreamConfiguration *streamConfig) *streamConfig = config_->at(0); } -std::vector<V4L2FrameMetadata> V4L2Camera::completedBuffers() +std::vector<V4L2Camera::Buffer> V4L2Camera::completedBuffers() { - std::vector<V4L2FrameMetadata> v; + std::vector<Buffer> v; bufferLock_.lock(); - for (std::unique_ptr<V4L2FrameMetadata> &metadata : completedBuffers_) + for (std::unique_ptr<Buffer> &metadata : completedBuffers_) v.push_back(*metadata.get()); completedBuffers_.clear(); bufferLock_.unlock(); @@ -83,9 +79,9 @@ void V4L2Camera::requestComplete(Request *request) /* We only have one stream at the moment. */ bufferLock_.lock(); - Buffer *buffer = request->buffers().begin()->second; - std::unique_ptr<V4L2FrameMetadata> metadata = - utils::make_unique<V4L2FrameMetadata>(buffer); + FrameBuffer *buffer = request->buffers().begin()->second; + std::unique_ptr<Buffer> metadata = + utils::make_unique<Buffer>(request->cookie(), buffer->metadata()); completedBuffers_.push_back(std::move(metadata)); bufferLock_.unlock(); @@ -126,18 +122,31 @@ int V4L2Camera::configure(StreamConfiguration *streamConfigOut, int V4L2Camera::allocBuffers(unsigned int count) { int ret = camera_->allocateBuffers(); - return ret == -EACCES ? -EBUSY : ret; + if (ret) + return ret == -EACCES ? -EBUSY : ret; + + Stream *stream = *camera_->streams().begin(); + + return bufferAllocator_->allocate(stream); } void V4L2Camera::freeBuffers() { + Stream *stream = *camera_->streams().begin(); + bufferAllocator_->free(stream); camera_->freeBuffers(); } FileDescriptor V4L2Camera::getBufferFd(unsigned int index) { Stream *stream = *camera_->streams().begin(); - return stream->buffers()[index].planes()[0].fd; + const std::vector<std::unique_ptr<FrameBuffer>> &buffers = + bufferAllocator_->buffers(stream); + + if (buffers.size() <= index) + return FileDescriptor(); + + return buffers[index]->planes()[0].fd; } int V4L2Camera::streamOn() @@ -180,21 +189,16 @@ int V4L2Camera::streamOff() int V4L2Camera::qbuf(unsigned int index) { - Stream *stream = config_->at(0).stream(); - std::unique_ptr<Buffer> buffer = stream->createBuffer(index); - if (!buffer) { - LOG(V4L2Compat, Error) << "Can't create buffer"; - return -ENOMEM; - } - std::unique_ptr<Request> request = - std::unique_ptr<Request>(camera_->createRequest()); + std::unique_ptr<Request>(camera_->createRequest(index)); if (!request) { LOG(V4L2Compat, Error) << "Can't create request"; return -ENOMEM; } - int ret = request->addBuffer(stream, std::move(buffer)); + Stream *stream = config_->at(0).stream(); + FrameBuffer *buffer = bufferAllocator_->buffers(stream)[index].get(); + int ret = request->addBuffer(stream, buffer); if (ret < 0) { LOG(V4L2Compat, Error) << "Can't set buffer for request"; return -ENOMEM; diff --git a/src/v4l2/v4l2_camera.h b/src/v4l2/v4l2_camera.h index 06eab0e1..f1f04d9e 100644 --- a/src/v4l2/v4l2_camera.h +++ b/src/v4l2/v4l2_camera.h @@ -9,50 +9,38 @@ #define __V4L2_CAMERA_H__ #include <deque> -#include <linux/videodev2.h> #include <mutex> +#include <utility> #include <libcamera/buffer.h> #include <libcamera/camera.h> #include <libcamera/file_descriptor.h> +#include <libcamera/framebuffer_allocator.h> #include "semaphore.h" using namespace libcamera; -class V4L2FrameMetadata +class V4L2Camera : public Object { public: - V4L2FrameMetadata(Buffer *buffer); - - int index() const { return index_; } - - unsigned int bytesused() const { return bytesused_; } - uint64_t timestamp() const { return timestamp_; } - unsigned int sequence() const { return sequence_; } - - FrameMetadata::Status status() const { return status_; } - -private: - int index_; + struct Buffer { + Buffer(unsigned int index, const FrameMetadata &data) + : index(index), data(data) + { + } - unsigned int bytesused_; - uint64_t timestamp_; - unsigned int sequence_; + unsigned int index; + FrameMetadata data; + }; - FrameMetadata::Status status_; -}; - -class V4L2Camera : public Object -{ -public: V4L2Camera(std::shared_ptr<Camera> camera); ~V4L2Camera(); int open(); void close(); void getStreamConfig(StreamConfiguration *streamConfig); - std::vector<V4L2FrameMetadata> completedBuffers(); + std::vector<Buffer> completedBuffers(); int configure(StreamConfiguration *streamConfigOut, const Size &size, PixelFormat pixelformat, @@ -78,9 +66,10 @@ private: bool isRunning_; std::mutex bufferLock_; + FrameBufferAllocator *bufferAllocator_; std::deque<std::unique_ptr<Request>> pendingRequests_; - std::deque<std::unique_ptr<V4L2FrameMetadata>> completedBuffers_; + std::deque<std::unique_ptr<Buffer>> completedBuffers_; }; #endif /* __V4L2_CAMERA_H__ */ diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp index 5158eac4..28e58722 100644 --- a/src/v4l2/v4l2_camera_proxy.cpp +++ b/src/v4l2/v4l2_camera_proxy.cpp @@ -187,17 +187,18 @@ void V4L2CameraProxy::querycap(std::shared_ptr<Camera> camera) void V4L2CameraProxy::updateBuffers() { - std::vector<V4L2FrameMetadata> completedBuffers = vcam_->completedBuffers(); - for (V4L2FrameMetadata &fmd : completedBuffers) { - struct v4l2_buffer &buf = buffers_[fmd.index()]; + std::vector<V4L2Camera::Buffer> completedBuffers = vcam_->completedBuffers(); + for (const V4L2Camera::Buffer &buffer : completedBuffers) { + const FrameMetadata &fmd = buffer.data; + struct v4l2_buffer &buf = buffers_[buffer.index]; - switch (fmd.status()) { + switch (fmd.status) { case FrameMetadata::FrameSuccess: - buf.bytesused = fmd.bytesused(); + buf.bytesused = fmd.planes[0].bytesused; buf.field = V4L2_FIELD_NONE; - buf.timestamp.tv_sec = fmd.timestamp() / 1000000000; - buf.timestamp.tv_usec = fmd.timestamp() % 1000000; - buf.sequence = fmd.sequence(); + buf.timestamp.tv_sec = fmd.timestamp / 1000000000; + buf.timestamp.tv_usec = fmd.timestamp % 1000000; + buf.sequence = fmd.sequence; buf.flags |= V4L2_BUF_FLAG_DONE; break; diff --git a/test/camera/buffer_import.cpp b/test/camera/buffer_import.cpp index 327db791..f506d1b2 100644 --- a/test/camera/buffer_import.cpp +++ b/test/camera/buffer_import.cpp @@ -120,7 +120,7 @@ public: } protected: - void bufferComplete(Request *request, Buffer *buffer) + void bufferComplete(Request *request, FrameBuffer *buffer) { if (buffer->metadata().status != FrameMetadata::FrameSuccess) return; @@ -133,17 +133,16 @@ protected: if (request->status() != Request::RequestComplete) return; - const std::map<Stream *, Buffer *> &buffers = request->buffers(); + const std::map<Stream *, FrameBuffer *> &buffers = request->buffers(); completeRequestsCount_++; /* Create a new request. */ Stream *stream = buffers.begin()->first; - int dmabuf = buffers.begin()->second->dmabufs()[0]; - std::unique_ptr<Buffer> buffer = stream->createBuffer({ dmabuf, -1, -1 }); + FrameBuffer *buffer = buffers.begin()->second; request = camera_->createRequest(); - request->addBuffer(stream, std::move(buffer)); + request->addBuffer(stream, buffer); camera_->queueRequest(request); } @@ -158,9 +157,6 @@ protected: return TestFail; } - StreamConfiguration &cfg = config_->at(0); - cfg.memoryType = ExternalMemory; - return TestPass; } @@ -191,17 +187,14 @@ protected: return TestFail; std::vector<Request *> requests; - for (const std::unique_ptr<FrameBuffer> &framebuffer : source.buffers()) { - int dmabuf = framebuffer->planes()[0].fd.fd(); - + for (const std::unique_ptr<FrameBuffer> &buffer : source.buffers()) { Request *request = camera_->createRequest(); if (!request) { std::cout << "Failed to create request" << std::endl; return TestFail; } - std::unique_ptr<Buffer> buffer = stream->createBuffer({ dmabuf, -1, -1 }); - if (request->addBuffer(stream, std::move(buffer))) { + if (request->addBuffer(stream, buffer.get())) { std::cout << "Failed to associating buffer with request" << std::endl; return TestFail; } diff --git a/test/camera/capture.cpp b/test/camera/capture.cpp index 0d9ffc47..de879ee4 100644 --- a/test/camera/capture.cpp +++ b/test/camera/capture.cpp @@ -26,7 +26,7 @@ protected: unsigned int completeBuffersCount_; unsigned int completeRequestsCount_; - void bufferComplete(Request *request, Buffer *buffer) + void bufferComplete(Request *request, FrameBuffer *buffer) { if (buffer->metadata().status != FrameMetadata::FrameSuccess) return; @@ -39,17 +39,16 @@ protected: if (request->status() != Request::RequestComplete) return; - const std::map<Stream *, Buffer *> &buffers = request->buffers(); + const std::map<Stream *, FrameBuffer *> &buffers = request->buffers(); completeRequestsCount_++; /* Create a new request. */ Stream *stream = buffers.begin()->first; - Buffer *buffer = buffers.begin()->second; - std::unique_ptr<Buffer> newBuffer = stream->createBuffer(buffer->index()); + FrameBuffer *buffer = buffers.begin()->second; request = camera_->createRequest(); - request->addBuffer(stream, std::move(newBuffer)); + request->addBuffer(stream, buffer); camera_->queueRequest(request); } @@ -64,9 +63,16 @@ protected: return TestFail; } + allocator_ = FrameBufferAllocator::create(camera_); + return TestPass; } + void cleanup() override + { + delete allocator_; + } + int run() override { StreamConfiguration &cfg = config_->at(0); @@ -87,21 +93,20 @@ protected: } Stream *stream = cfg.stream(); + + int ret = allocator_->allocate(stream); + if (ret < 0) + return TestFail; + std::vector<Request *> requests; - for (unsigned int i = 0; i < cfg.bufferCount; ++i) { + for (const std::unique_ptr<FrameBuffer> &buffer : allocator_->buffers(stream)) { Request *request = camera_->createRequest(); if (!request) { cout << "Failed to create request" << endl; return TestFail; } - std::unique_ptr<Buffer> buffer = stream->createBuffer(i); - if (!buffer) { - cout << "Failed to create buffer " << i << endl; - return TestFail; - } - - if (request->addBuffer(stream, std::move(buffer))) { + if (request->addBuffer(stream, buffer.get())) { cout << "Failed to associating buffer with request" << endl; return TestFail; } @@ -134,10 +139,12 @@ protected: while (timer.isRunning()) dispatcher->processEvents(); - if (completeRequestsCount_ <= cfg.bufferCount * 2) { + unsigned int nbuffers = allocator_->buffers(stream).size(); + + if (completeRequestsCount_ <= nbuffers * 2) { cout << "Failed to capture enough frames (got " << completeRequestsCount_ << " expected at least " - << cfg.bufferCount * 2 << ")" << endl; + << nbuffers * 2 << ")" << endl; return TestFail; } @@ -160,6 +167,7 @@ protected: } std::unique_ptr<CameraConfiguration> config_; + FrameBufferAllocator *allocator_; }; } /* namespace */ diff --git a/test/camera/statemachine.cpp b/test/camera/statemachine.cpp index f627b8f3..f3a7ca7c 100644 --- a/test/camera/statemachine.cpp +++ b/test/camera/statemachine.cpp @@ -185,6 +185,12 @@ protected: if (camera_->allocateBuffers()) return TestFail; + /* Use internally allocated buffers. */ + allocator_ = FrameBufferAllocator::create(camera_); + Stream *stream = *camera_->streams().begin(); + if (allocator_->allocate(stream) < 0) + return TestFail; + if (camera_->start()) return TestFail; @@ -218,8 +224,7 @@ protected: return TestFail; Stream *stream = *camera_->streams().begin(); - std::unique_ptr<Buffer> buffer = stream->createBuffer(0); - if (request->addBuffer(stream, std::move(buffer))) + if (request->addBuffer(stream, allocator_->buffers(stream)[0].get())) return TestFail; if (camera_->queueRequest(request)) @@ -229,6 +234,8 @@ protected: if (camera_->stop()) return TestFail; + delete allocator_; + if (camera_->freeBuffers()) return TestFail; @@ -283,6 +290,7 @@ protected: } std::unique_ptr<CameraConfiguration> defconf_; + FrameBufferAllocator *allocator_; }; } /* namespace */ |