Revision control
++ // Copyright (C) 2022 The Qt Company
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
++
++ #include "qqnxcameraframebuffer_p.h"
++
++ #include <limits>
++
++ template <typename T>
++ static constexpr int toInt(T value)
++ {
++ if constexpr (sizeof(T) >= sizeof(int)) {
++ if (std::is_signed_v<T>) {
++ return static_cast<int>(std::clamp<T>(value,
++ std::numeric_limits<int>::min(), std::numeric_limits<int>::max()));
++ } else {
++ return static_cast<int>(std::min<T>(value, std::numeric_limits<int>::max()));
++ }
++ } else {
++ return static_cast<int>(value);
++ }
++ }
++
++ template <typename T>
++ static constexpr QSize frameSize(const T &frame)
++ {
++ return { toInt(frame.width), toInt(frame.height) };
++ }
++
++ static constexpr QVideoFrameFormat::PixelFormat frameTypeToPixelFormat(camera_frametype_t type)
++ {
++ switch (type) {
++ case CAMERA_FRAMETYPE_NV12:
++ return QVideoFrameFormat::Format_NV12;
++ case CAMERA_FRAMETYPE_RGB8888:
++ return QVideoFrameFormat::Format_ARGB8888;
++ case CAMERA_FRAMETYPE_GRAY8:
++ return QVideoFrameFormat::Format_Y8;
++ case CAMERA_FRAMETYPE_CBYCRY:
++ return QVideoFrameFormat::Format_UYVY;
++ case CAMERA_FRAMETYPE_YCBCR420P:
++ return QVideoFrameFormat::Format_YUV420P;
++ case CAMERA_FRAMETYPE_YCBYCR:
++ return QVideoFrameFormat::Format_YUYV;
++ default:
++ break;
++ }
++
++ return QVideoFrameFormat::Format_Invalid;
++ }
++
++ static constexpr size_t bufferDataSize(const camera_frame_nv12_t &frame)
++ {
++ return frame.uv_offset + frame.uv_stride * frame.height / 2;
++ }
++
++ static constexpr size_t bufferDataSize(const camera_frame_rgb8888_t &frame)
++ {
++ return frame.stride * frame.height;
++ }
++
++ static constexpr size_t bufferDataSize(const camera_frame_gray8_t &frame)
++ {
++ return frame.stride * frame.height;
++ }
++
++ static constexpr size_t bufferDataSize(const camera_frame_cbycry_t &frame)
++ {
++ return frame.bufsize;
++ }
++
++ static constexpr size_t bufferDataSize(const camera_frame_ycbcr420p_t &frame)
++ {
++ return frame.cr_offset + frame.cr_stride * frame.height / 2;
++ }
++
++ static constexpr size_t bufferDataSize(const camera_frame_ycbycr_t &frame)
++ {
++ return frame.stride * frame.height;
++ }
++
++ static constexpr size_t bufferDataSize(const camera_buffer_t *buffer)
++ {
++ switch (buffer->frametype) {
++ case CAMERA_FRAMETYPE_NV12:
++ return bufferDataSize(buffer->framedesc.nv12);
++ case CAMERA_FRAMETYPE_RGB8888:
++ return bufferDataSize(buffer->framedesc.rgb8888);
++ case CAMERA_FRAMETYPE_GRAY8:
++ return bufferDataSize(buffer->framedesc.gray8);
++ case CAMERA_FRAMETYPE_CBYCRY:
++ return bufferDataSize(buffer->framedesc.cbycry);
++ case CAMERA_FRAMETYPE_YCBCR420P:
++ return bufferDataSize(buffer->framedesc.ycbcr420p);
++ case CAMERA_FRAMETYPE_YCBYCR:
++ return bufferDataSize(buffer->framedesc.ycbycr);
++ default:
++ break;
++ }
++
++ return 0;
++ }
++
++ static QAbstractVideoBuffer::MapData mapData(const camera_frame_nv12_t &frame,
++ unsigned char *baseAddress)
++ {
++
++ return {
++ .planeCount = 2,
++ .bytesPerLine = {
++ toInt(frame.stride),
++ toInt(frame.uv_stride)
++ },
++ .data = {
++ baseAddress,
++ baseAddress + frame.uv_offset
++ },
++ .dataSize = {
++ toInt(frame.stride * frame.height),
++ toInt(frame.uv_stride * frame.height / 2)
++ }
++ };
++ }
++
++ static QAbstractVideoBuffer::MapData mapData(const camera_frame_rgb8888_t &frame,
++ unsigned char *baseAddress)
++ {
++ return {
++ .planeCount = 1,
++ .bytesPerLine = {
++ toInt(frame.stride)
++ },
++ .data = {
++ baseAddress
++ },
++ .dataSize = {
++ toInt(frame.stride * frame.height),
++ }
++ };
++ }
++
++ static QAbstractVideoBuffer::MapData mapData(const camera_frame_gray8_t &frame,
++ unsigned char *baseAddress)
++ {
++ return {
++ .planeCount = 1,
++ .bytesPerLine = {
++ toInt(frame.stride)
++ },
++ .data = {
++ baseAddress
++ },
++ .dataSize = {
++ toInt(frame.stride * frame.height)
++ }
++ };
++ }
++
++ static QAbstractVideoBuffer::MapData mapData(const camera_frame_cbycry_t &frame,
++ unsigned char *baseAddress)
++ {
++ return {
++ .planeCount = 1,
++ .bytesPerLine = {
++ toInt(frame.stride)
++ },
++ .data = {
++ baseAddress
++ },
++ .dataSize = {
++ toInt(frame.bufsize),
++ }
++ };
++ }
++
++ static QAbstractVideoBuffer::MapData mapData(const camera_frame_ycbcr420p_t &frame,
++ unsigned char *baseAddress)
++ {
++ return {
++ .planeCount = 3,
++ .bytesPerLine = {
++ toInt(frame.y_stride),
++ frame.cb_stride,
++ frame.cr_stride,
++ },
++ .data = {
++ baseAddress,
++ baseAddress + frame.cb_offset,
++ baseAddress + frame.cr_offset,
++ },
++ .dataSize = {
++ toInt(frame.y_stride * frame.height),
++ toInt(frame.cb_stride * frame.height / 2),
++ toInt(frame.cr_stride * frame.height / 2)
++ }
++ };
++ }
++
++ static QAbstractVideoBuffer::MapData mapData(const camera_frame_ycbycr_t &frame,
++ unsigned char *baseAddress)
++ {
++ return {
++ .planeCount = 1,
++ .bytesPerLine = {
++ toInt(frame.stride)
++ },
++ .data = {
++ baseAddress
++ },
++ .dataSize = {
++ toInt(frame.stride * frame.height)
++ }
++ };
++ }
++
++ static QAbstractVideoBuffer::MapData mapData(const camera_buffer_t *buffer,
++ unsigned char *baseAddress)
++ {
++ switch (buffer->frametype) {
++ case CAMERA_FRAMETYPE_NV12:
++ return mapData(buffer->framedesc.nv12, baseAddress);
++ case CAMERA_FRAMETYPE_RGB8888:
++ return mapData(buffer->framedesc.rgb8888, baseAddress);
++ case CAMERA_FRAMETYPE_GRAY8:
++ return mapData(buffer->framedesc.gray8, baseAddress);
++ case CAMERA_FRAMETYPE_CBYCRY:
++ return mapData(buffer->framedesc.cbycry, baseAddress);
++ case CAMERA_FRAMETYPE_YCBCR420P:
++ return mapData(buffer->framedesc.ycbcr420p, baseAddress);
++ case CAMERA_FRAMETYPE_YCBYCR:
++ return mapData(buffer->framedesc.ycbycr, baseAddress);
++ default:
++ break;
++ }
++
++ return {};
++ }
++
++ static constexpr QSize frameSize(const camera_buffer_t *buffer)
++ {
++ switch (buffer->frametype) {
++ case CAMERA_FRAMETYPE_NV12:
++ return frameSize(buffer->framedesc.nv12);
++ case CAMERA_FRAMETYPE_RGB8888:
++ return frameSize(buffer->framedesc.rgb8888);
++ case CAMERA_FRAMETYPE_GRAY8:
++ return frameSize(buffer->framedesc.gray8);
++ case CAMERA_FRAMETYPE_CBYCRY:
++ return frameSize(buffer->framedesc.cbycry);
++ case CAMERA_FRAMETYPE_YCBCR420P:
++ return frameSize(buffer->framedesc.ycbcr420p);
++ case CAMERA_FRAMETYPE_YCBYCR:
++ return frameSize(buffer->framedesc.ycbycr);
++ default:
++ break;
++ }
++
++ return {};
++ }
++
++ QT_BEGIN_NAMESPACE
++
++ QQnxCameraFrameBuffer::QQnxCameraFrameBuffer(const camera_buffer_t *buffer)
++ : m_pixelFormat(::frameTypeToPixelFormat(buffer->frametype)),
++ m_dataSize(::bufferDataSize(buffer))
++ {
++ if (m_dataSize <= 0)
++ return;
++
++ m_data = std::make_unique<unsigned char[]>(m_dataSize);
++
++ memcpy(m_data.get(), buffer->framebuf, m_dataSize);
++
++ m_mapData = ::mapData(buffer, m_data.get());
++
++ m_frameSize = ::frameSize(buffer);
++ }
++
++ QAbstractVideoBuffer::MapData QQnxCameraFrameBuffer::map(QVideoFrame::MapMode)
++ {
++ return m_mapData;
++ }
++
++ void QQnxCameraFrameBuffer::unmap()
++ {
++ }
++
++ QVideoFrameFormat::PixelFormat QQnxCameraFrameBuffer::pixelFormat() const
++ {
++ return m_pixelFormat;
++ }
++
++ QSize QQnxCameraFrameBuffer::size() const
++ {
++ return m_frameSize;
++ }
++
++ QT_END_NAMESPACE