/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2021, Ideas on Board Oy * * image.cpp - Multi-planar image with access to pixel data */ #include "image.h" #include <assert.h> #include <errno.h> #include <iostream> #include <map> #include <string.h> #include <sys/mman.h> #include <unistd.h> using namespace libcamera; std::unique_ptr<Image> Image::fromFrameBuffer(const FrameBuffer *buffer, MapMode mode) { std::unique_ptr<Image> image{ new Image() }; assert(!buffer->planes().empty()); int mmapFlags = 0; if (mode & MapMode::ReadOnly) mmapFlags |= PROT_READ; if (mode & MapMode::WriteOnly) mmapFlags |= PROT_WRITE; struct MappedBufferInfo { uint8_t *address = nullptr; size_t mapLength = 0; size_t dmabufLength = 0; }; std::map<int, MappedBufferInfo> mappedBuffers; for (const FrameBuffer::Plane &plane : buffer->planes()) { const int fd = plane.fd.get(); if (mappedBuffers.find(fd) == mappedBuffers.end()) { const size_t length = lseek(fd, 0, SEEK_END); mappedBuffers[fd] = MappedBufferInfo{ nullptr, 0, length }; } const size_t length = mappedBuffers[fd].dmabufLength; if (plane.offset > length || plane.offset + plane.length > length) { std::cerr << "plane is out of buffer: buffer length=" << length << ", plane offset=" << plane.offset << ", plane length=" << plane.length << std::endl; return nullptr; } size_t &mapLength = mappedBuffers[fd].mapLength; mapLength = std::max(mapLength, static_cast<size_t>(plane.offset + plane.length)); } for (const FrameBuffer::Plane &plane : buffer->planes()) { const int fd = plane.fd.get(); auto &info = mappedBuffers[fd]; if (!info.address) { void *address = mmap(nullptr, info.mapLength, mmapFlags, MAP_SHARED, fd, 0); if (address == MAP_FAILED) { int error = -errno; std::cerr << "Failed to mmap plane: " << strerror(-error) << std::endl; return nullptr; } info.address = static_cast<uint8_t *>(address); image->maps_.emplace_back(info.address, info.mapLength); } image->planes_.emplace_back(info.address + plane.offset, plane.length); } return image; } Image::Image() = default; Image::~Image() { for (Span<uint8_t> &map : maps_) munmap(map.data(), map.size()); } unsigned int Image::numPlanes() const { return planes_.size(); } Span<uint8_t> Image::data(unsigned int plane) { assert(plane <= planes_.size()); return planes_[plane]; } Span<const uint8_t> Image::data(unsigned int plane) const { assert(plane <= planes_.size()); return planes_[plane]; } tils?h=v0.1.0&id=5e85157bcf156137259c57a2ebc5d5616dbb2e37'>utils</a>/<a href='/libcamera/libcamera.git/tree/utils/ipc?h=v0.1.0&id=5e85157bcf156137259c57a2ebc5d5616dbb2e37'>ipc</a>/<a href='/libcamera/libcamera.git/tree/utils/ipc/mojo?h=v0.1.0&id=5e85157bcf156137259c57a2ebc5d5616dbb2e37'>mojo</a>/<a href='/libcamera/libcamera.git/tree/utils/ipc/mojo/public?h=v0.1.0&id=5e85157bcf156137259c57a2ebc5d5616dbb2e37'>public</a>/<a href='/libcamera/libcamera.git/tree/utils/ipc/mojo/public/LICENSE?h=v0.1.0&id=5e85157bcf156137259c57a2ebc5d5616dbb2e37'>LICENSE</a></div><div class='content'>blob: 513e8a6a0a1d9a42818b02fd46b31fe88c653400 (<a href='/libcamera/libcamera.git/plain/utils/ipc/mojo/public/LICENSE?h=v0.1.0&id=5e85157bcf156137259c57a2ebc5d5616dbb2e37'>plain</a>) <table summary='blob content' class='blob'> <tr><td class='linenumbers'><pre><a id='n1' href='#n1'>1</a> <a id='n2' href='#n2'>2</a> <a id='n3' href='#n3'>3</a> <a id='n4' href='#n4'>4</a> <a id='n5' href='#n5'>5</a> <a id='n6' href='#n6'>6</a> <a id='n7' href='#n7'>7</a> <a id='n8' href='#n8'>8</a> <a id='n9' href='#n9'>9</a> <a id='n10' href='#n10'>10</a> <a id='n11' href='#n11'>11</a> <a id='n12' href='#n12'>12</a> <a id='n13' href='#n13'>13</a> <a id='n14' href='#n14'>14</a> <a id='n15' href='#n15'>15</a> <a id='n16' href='#n16'>16</a> <a id='n17' href='#n17'>17</a> <a id='n18' href='#n18'>18</a> <a id='n19' href='#n19'>19</a> <a id='n20' href='#n20'>20</a> <a id='n21' href='#n21'>21</a> <a id='n22' href='#n22'>22</a> <a id='n23' href='#n23'>23</a> <a id='n24' href='#n24'>24</a> <a id='n25' href='#n25'>25</a> <a id='n26' href='#n26'>26</a> <a id='n27' href='#n27'>27</a> </pre></td> <td class='lines'><pre><code>// Copyright 2014 The Chromium Authors // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. </code></pre></td></tr></table> </div> <!-- class=content --> <div class='footer'>generated by <a href='https://git.zx2c4.com/cgit/about/'>cgit v1.2.1</a> (<a href='https://git-scm.com/'>git 2.18.0</a>) at 2025-03-25 17:28:09 +0000</div> </div> <!-- id=cgit --> </body> </html>