Vitaliy Zarubin
1 year ago
5 changed files with 171 additions and 141 deletions
@ -0,0 +1,124 @@
|
||||
/**
|
||||
* SPDX-FileCopyrightText: Copyright 2023 Open Mobile Platform LLC <community@omp.ru> |
||||
* SPDX-License-Identifier: BSD-3-Clause |
||||
*/ |
||||
#include <embedder_texture/camera_pixel_buffer.h> |
||||
|
||||
CameraPixelBuffer::CameraPixelBuffer(TextureRegistrar *plugin) : m_plugin(plugin) |
||||
{ |
||||
Aurora::StreamCamera::CameraManager *manager = StreamCameraManager(); |
||||
|
||||
if (manager->getNumberOfCameras()) |
||||
{ |
||||
Aurora::StreamCamera::CameraInfo info; |
||||
|
||||
if (manager->getCameraInfo(0, info)) // Camera ID = 0
|
||||
{ |
||||
std::vector<Aurora::StreamCamera::CameraCapability> caps; |
||||
|
||||
if (manager->queryCapabilities(info.id, caps)) |
||||
{ |
||||
m_cap = caps.at(1); |
||||
m_camera = manager->openCamera(info.id); |
||||
m_camera->setListener(this); |
||||
} |
||||
} |
||||
} |
||||
}; |
||||
|
||||
int64_t CameraPixelBuffer::Register() |
||||
{ |
||||
m_textureId = m_plugin->RegisterTexture(TextureType::Pixels, [this](size_t width, size_t height) { |
||||
if (this->m_buffer) { |
||||
return TextureVariant(FlutterPixelBuffer{ this->m_buffer->buffer } ); |
||||
} |
||||
return TextureVariant(FlutterPixelBuffer{}); |
||||
}); |
||||
|
||||
m_camera->startCapture(m_cap); |
||||
|
||||
return m_textureId; |
||||
} |
||||
|
||||
void CameraPixelBuffer::Unregister() |
||||
{ |
||||
m_plugin->UnregisterTexture(m_textureId); |
||||
m_camera->stopCapture(); |
||||
m_buffer = nullptr; |
||||
} |
||||
|
||||
void CameraPixelBuffer::onCameraFrame(std::shared_ptr<Aurora::StreamCamera::GraphicBuffer> buffer) |
||||
{ |
||||
auto frame = buffer->mapYCbCr(); |
||||
|
||||
QSize size(frame->width, frame->height); |
||||
QImage* image = new QImage(size, QImage::Format_ARGB32); |
||||
|
||||
this->planarYuv420ToArgb(frame->y, frame->cb, frame->cr, |
||||
frame->yStride, frame->cStride, frame->cStride, |
||||
frame->chromaStep, |
||||
reinterpret_cast<quint32 *>(image->bits()), |
||||
frame->width, frame->height); |
||||
|
||||
uint8_t *pixels = static_cast<uint8_t *>(image->bits()); |
||||
|
||||
this->m_buffer = new FlutterPixelBuffer { pixels }; |
||||
|
||||
m_plugin->MarkTextureAvailable(m_textureId); |
||||
} |
||||
|
||||
void CameraPixelBuffer::onCameraError(const std::string &errorDescription) |
||||
{ |
||||
std::cout << "onCameraError" << std::endl; |
||||
} |
||||
|
||||
void CameraPixelBuffer::onCameraParameterChanged(Aurora::StreamCamera::CameraParameter parameter, const std::string &value)
|
||||
{ |
||||
std::cout << "onCameraParameterChanged" << std::endl; |
||||
} |
||||
|
||||
quint32 CameraPixelBuffer::yuvToArgb(qint32 y, qint32 rv, qint32 guv, qint32 bu, qint32 a = 255) |
||||
{ |
||||
qint32 yy = (y - 16) * 298; |
||||
|
||||
return (a << 24) |
||||
| qBound(0, (yy + rv) >> 8, 255) << 16 |
||||
| qBound(0, (yy - guv) >> 8, 255) << 8 |
||||
| qBound(0, (yy + bu) >> 8, 255); |
||||
} |
||||
|
||||
void CameraPixelBuffer::planarYuv420ToArgb(const uchar *y, const uchar *u, const uchar *v, |
||||
qint32 yStride, qint32 uStride, qint32 vStride, |
||||
qint32 uvPixelStride, quint32 *rgb, qint32 width, qint32 height) |
||||
{ |
||||
quint32 *rgb0 = rgb; |
||||
quint32 *rgb1 = rgb + width; |
||||
|
||||
for (qint32 j = 0; j < height; j += 2) { |
||||
const uchar *lineY0 = y; |
||||
const uchar *lineY1 = y + yStride; |
||||
const uchar *lineU = u; |
||||
const uchar *lineV = v; |
||||
|
||||
for (qint32 i = 0; i < width; i += 2) { |
||||
const qint32 uu = *lineU - 128; |
||||
const qint32 vv = *lineV - 128; |
||||
const qint32 rv = 409 * vv + 128; |
||||
const qint32 guv = 100 * uu + 208 * vv + 128; |
||||
const qint32 bu = 516 * uu + 128; |
||||
|
||||
lineU += uvPixelStride; |
||||
lineV += uvPixelStride; |
||||
*rgb0++ = yuvToArgb(*lineY0++, rv, guv, bu); |
||||
*rgb0++ = yuvToArgb(*lineY0++, rv, guv, bu); |
||||
*rgb1++ = yuvToArgb(*lineY1++, rv, guv, bu); |
||||
*rgb1++ = yuvToArgb(*lineY1++, rv, guv, bu); |
||||
} |
||||
|
||||
y += yStride << 1; |
||||
u += uStride; |
||||
v += vStride; |
||||
rgb0 += width; |
||||
rgb1 += width; |
||||
} |
||||
} |
@ -0,0 +1,39 @@
|
||||
/**
|
||||
* SPDX-FileCopyrightText: Copyright 2023 Open Mobile Platform LLC <community@omp.ru> |
||||
* SPDX-License-Identifier: BSD-3-Clause |
||||
*/ |
||||
#ifndef CAMERA_PIXEL_BUFFER_H |
||||
#define CAMERA_PIXEL_BUFFER_H |
||||
|
||||
#include <flutter/plugin-interface.h> |
||||
#include <streamcamera/streamcamera.h> |
||||
|
||||
#include <QtCore> |
||||
#include <QImage> |
||||
|
||||
class CameraPixelBuffer : public Aurora::StreamCamera::CameraListener |
||||
{ |
||||
|
||||
public: |
||||
CameraPixelBuffer(TextureRegistrar *plugin); |
||||
|
||||
void onCameraError(const std::string &errorDescription) override; |
||||
void onCameraParameterChanged(Aurora::StreamCamera::CameraParameter, const std::string &value) override; |
||||
void onCameraFrame(std::shared_ptr<Aurora::StreamCamera::GraphicBuffer> buffer) override; |
||||
|
||||
int64_t Register(); |
||||
void Unregister(); |
||||
|
||||
private: |
||||
quint32 yuvToArgb(qint32 y, qint32 rv, qint32 guv, qint32 bu, qint32 a); |
||||
void planarYuv420ToArgb(const uchar *y, const uchar *u, const uchar *v, qint32 yStride, qint32 uStride, qint32 vStride, qint32 uvPixelStride, quint32 *rgb, qint32 width, qint32 height); |
||||
|
||||
private: |
||||
int64_t m_textureId; |
||||
TextureRegistrar *m_plugin; |
||||
FlutterPixelBuffer *m_buffer; |
||||
Aurora::StreamCamera::CameraCapability m_cap; |
||||
std::shared_ptr<Aurora::StreamCamera::Camera> m_camera; |
||||
}; |
||||
|
||||
#endif /* CAMERA_PIXEL_BUFFER_H */ |
Loading…
Reference in new issue