diff --git a/packages/embedder_texture/aurora/CMakeLists.txt b/packages/embedder_texture/aurora/CMakeLists.txt index 26381d9..28ff6df 100644 --- a/packages/embedder_texture/aurora/CMakeLists.txt +++ b/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) diff --git a/packages/embedder_texture/aurora/camera_pixel_buffer.cpp b/packages/embedder_texture/aurora/camera_pixel_buffer.cpp new file mode 100644 index 0000000..8ecae54 --- /dev/null +++ b/packages/embedder_texture/aurora/camera_pixel_buffer.cpp @@ -0,0 +1,124 @@ +/** + * SPDX-FileCopyrightText: Copyright 2023 Open Mobile Platform LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +#include + +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 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 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(image->bits()), + frame->width, frame->height); + + uint8_t *pixels = static_cast(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; + } +} diff --git a/packages/embedder_texture/aurora/embedder_texture_plugin.cpp b/packages/embedder_texture/aurora/embedder_texture_plugin.cpp index dbe405a..5d688fb 100644 --- a/packages/embedder_texture/aurora/embedder_texture_plugin.cpp +++ b/packages/embedder_texture/aurora/embedder_texture_plugin.cpp @@ -10,6 +10,8 @@ void EmbedderTexturePlugin::RegisterWithRegistrar(PluginRegistrar ®istrar) { 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 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([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(image->bits()), - frame->width, frame->height); - - uint8_t *pixels = static_cast(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("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; - } -} diff --git a/packages/embedder_texture/aurora/include/embedder_texture/camera_pixel_buffer.h b/packages/embedder_texture/aurora/include/embedder_texture/camera_pixel_buffer.h new file mode 100644 index 0000000..ccbcb8d --- /dev/null +++ b/packages/embedder_texture/aurora/include/embedder_texture/camera_pixel_buffer.h @@ -0,0 +1,39 @@ +/** + * SPDX-FileCopyrightText: Copyright 2023 Open Mobile Platform LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef CAMERA_PIXEL_BUFFER_H +#define CAMERA_PIXEL_BUFFER_H + +#include +#include + +#include +#include + +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 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 m_camera; +}; + +#endif /* CAMERA_PIXEL_BUFFER_H */ diff --git a/packages/embedder_texture/aurora/include/embedder_texture/embedder_texture_plugin.h b/packages/embedder_texture/aurora/include/embedder_texture/embedder_texture_plugin.h index d00ffb6..d56876c 100644 --- a/packages/embedder_texture/aurora/include/embedder_texture/embedder_texture_plugin.h +++ b/packages/embedder_texture/aurora/include/embedder_texture/embedder_texture_plugin.h @@ -6,15 +6,8 @@ #define EMBEDDER_TEXTURE_PLUGIN_H #include -#include -#include - -#include -#include -#include -#include -#include +#include #ifdef PLUGIN_IMPL #define PLUGIN_EXPORT __attribute__((visibility("default"))) @@ -22,31 +15,6 @@ #define PLUGIN_EXPORT #endif -typedef std::function 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 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 m_camera; - std::shared_ptr 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 */