Browse Source

[texture] Add CameraPixelBuffer class

embedder_texture
Vitaliy Zarubin 1 year ago
parent
commit
c4556091dc
  1. 1
      packages/embedder_texture/aurora/CMakeLists.txt
  2. 124
      packages/embedder_texture/aurora/camera_pixel_buffer.cpp
  3. 106
      packages/embedder_texture/aurora/embedder_texture_plugin.cpp
  4. 39
      packages/embedder_texture/aurora/include/embedder_texture/camera_pixel_buffer.h
  5. 42
      packages/embedder_texture/aurora/include/embedder_texture/embedder_texture_plugin.h

1
packages/embedder_texture/aurora/CMakeLists.txt

@ -23,6 +23,7 @@ pkg_check_modules(SC REQUIRED IMPORTED_TARGET streamcamera)
add_library(${PLUGIN_NAME} SHARED
embedder_texture_plugin.cpp
camera_pixel_buffer.cpp
)
set_target_properties(${PLUGIN_NAME} PROPERTIES CXX_VISIBILITY_PRESET hidden)

124
packages/embedder_texture/aurora/camera_pixel_buffer.cpp

@ -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;
}
}

106
packages/embedder_texture/aurora/embedder_texture_plugin.cpp

@ -10,6 +10,8 @@ void EmbedderTexturePlugin::RegisterWithRegistrar(PluginRegistrar &registrar)
{
TextureRegistrar *plugin = registrar.GetRegisterTexture();
m_cameraPixelBuffer = new CameraPixelBuffer(plugin);
registrar.RegisterMethodChannel("embedder_texture",
MethodCodecType::Standard,
[this, plugin](const MethodCall &call) { this->onMethodCall(call, plugin); });
@ -33,57 +35,7 @@ void EmbedderTexturePlugin::onMethodCall(const MethodCall &call, TextureRegistra
void EmbedderTexturePlugin::onCreate(const MethodCall &call, TextureRegistrar *plugin)
{
auto textureId = 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{});
});
Aurora::StreamCamera::CameraManager *manager = StreamCameraManager();
if (manager->getNumberOfCameras())
{
Aurora::StreamCamera::CameraInfo info;
if (manager->getCameraInfo(0, info))
{
std::vector<Aurora::StreamCamera::CameraCapability> caps;
if (manager->queryCapabilities(info.id, caps))
{
const Aurora::StreamCamera::CameraCapability cap = caps.at(1);
m_camera = manager->openCamera(info.id);
m_listener = std::make_shared<AuroraCameraListener>([this, plugin, textureId](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 };
plugin->MarkTextureAvailable(textureId);
});
m_camera->setListener(m_listener.get());
m_camera->startCapture(cap);
}
}
}
auto textureId = m_cameraPixelBuffer->Register();
call.SendSuccessResponse(textureId);
}
@ -92,11 +44,7 @@ void EmbedderTexturePlugin::onRemove(const MethodCall &call, TextureRegistrar *p
{
auto textureId = call.GetArgument<Encodable::Int>("textureId");
plugin->UnregisterTexture(textureId);
m_camera->stopCapture();
m_camera = nullptr;
m_buffer = nullptr;
m_cameraPixelBuffer->Unregister();
call.SendSuccessResponse(true);
}
@ -105,49 +53,3 @@ void EmbedderTexturePlugin::unimplemented(const MethodCall &call)
{
call.SendSuccessResponse(nullptr);
}
quint32 EmbedderTexturePlugin::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 EmbedderTexturePlugin::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;
}
}

39
packages/embedder_texture/aurora/include/embedder_texture/camera_pixel_buffer.h

@ -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 */

42
packages/embedder_texture/aurora/include/embedder_texture/embedder_texture_plugin.h

@ -6,15 +6,8 @@
#define EMBEDDER_TEXTURE_PLUGIN_H
#include <flutter/plugin-interface.h>
#include <streamcamera/streamcamera.h>
#include <functional>
#include <QtCore>
#include <QCamera>
#include <QCameraInfo>
#include <QMediaRecorder>
#include <QCameraImageCapture>
#include <embedder_texture/camera_pixel_buffer.h>
#ifdef PLUGIN_IMPL
#define PLUGIN_EXPORT __attribute__((visibility("default")))
@ -22,31 +15,6 @@
#define PLUGIN_EXPORT
#endif
typedef std::function<void(Aurora::StreamCamera::GraphicBuffer *buffer)> ListenerHandler;
class AuroraCameraListener : public Aurora::StreamCamera::CameraListener
{
public:
AuroraCameraListener(const ListenerHandler &callback) : m_callback(callback) {
};
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
{
m_callback(buffer.get());
}
private:
ListenerHandler m_callback;
};
class PLUGIN_EXPORT EmbedderTexturePlugin final : public PluginInterface
{
public:
@ -58,12 +26,8 @@ private:
void onRemove(const MethodCall &call, TextureRegistrar *plugin);
void unimplemented(const MethodCall &call);
FlutterPixelBuffer *m_buffer;
std::shared_ptr<Aurora::StreamCamera::Camera> m_camera;
std::shared_ptr<AuroraCameraListener> m_listener;
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:
CameraPixelBuffer *m_cameraPixelBuffer;
};
#endif /* EMBEDDER_TEXTURE_PLUGIN_H */

Loading…
Cancel
Save