diff --git a/example/lib/packages/embedder_texture/page.dart b/example/lib/packages/embedder_texture/page.dart index 4f68ba0..39e2718 100644 --- a/example/lib/packages/embedder_texture/page.dart +++ b/example/lib/packages/embedder_texture/page.dart @@ -40,7 +40,7 @@ class _EmbedderTexturePageState extends AppState { child: Center( child: EmbedderTexture( width: 320, - height: 320, + height: 240, ), ), ); diff --git a/packages/embedder_texture/aurora/CMakeLists.txt b/packages/embedder_texture/aurora/CMakeLists.txt index d543439..26381d9 100644 --- a/packages/embedder_texture/aurora/CMakeLists.txt +++ b/packages/embedder_texture/aurora/CMakeLists.txt @@ -15,6 +15,8 @@ set(CMAKE_CXX_FLAGS "-Wall -Wextra -Wno-psabi") set(CMAKE_CXX_FLAGS_RELEASE "-O3") find_package(PkgConfig REQUIRED) +find_package(Qt5 COMPONENTS Core Multimedia REQUIRED) + pkg_check_modules(FlutterEmbedder REQUIRED IMPORTED_TARGET flutter-embedder) pkg_check_modules(GLES REQUIRED IMPORTED_TARGET glesv2) pkg_check_modules(SC REQUIRED IMPORTED_TARGET streamcamera) @@ -25,6 +27,7 @@ add_library(${PLUGIN_NAME} SHARED set_target_properties(${PLUGIN_NAME} PROPERTIES CXX_VISIBILITY_PRESET hidden) target_link_libraries(${PLUGIN_NAME} PRIVATE PkgConfig::FlutterEmbedder PkgConfig::GLES PkgConfig::SC) +target_link_libraries(${PLUGIN_NAME} PUBLIC Qt5::Core Qt5::Multimedia) target_include_directories(${PLUGIN_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) target_compile_definitions(${PLUGIN_NAME} PRIVATE PLUGIN_IMPL) diff --git a/packages/embedder_texture/aurora/embedder_texture_plugin.cpp b/packages/embedder_texture/aurora/embedder_texture_plugin.cpp index 0b533fd..dbe405a 100644 --- a/packages/embedder_texture/aurora/embedder_texture_plugin.cpp +++ b/packages/embedder_texture/aurora/embedder_texture_plugin.cpp @@ -6,38 +6,6 @@ #include #include -#include - -typedef std::function ListenerHandler; - -class AuroraCameraListener : public Aurora::StreamCamera::CameraListener -{ - -public: - AuroraCameraListener(const ListenerHandler &callback) : m_callback(callback) { - std::cout << "constructor" << std::endl; - }; - - void onCameraError(const std::string &errorDescription) override { - std::cout << "onCameraFrame: " << errorDescription << std::endl; - } - - void onCameraParameterChanged(Aurora::StreamCamera::CameraParameter, const std::string &value) override { - std::cout << "onCameraFrame: " << value << std::endl; - } - - void onCameraFrame(std::shared_ptr buffer) override - { - std::cout << "onCameraFrame" << std::endl; - - m_callback(buffer.get()); - } - -private: - ListenerHandler m_callback; - -}; - void EmbedderTexturePlugin::RegisterWithRegistrar(PluginRegistrar ®istrar) { TextureRegistrar *plugin = registrar.GetRegisterTexture(); @@ -47,19 +15,6 @@ void EmbedderTexturePlugin::RegisterWithRegistrar(PluginRegistrar ®istrar) [this, plugin](const MethodCall &call) { this->onMethodCall(call, plugin); }); } -// FlutterPixelBuffer EmbedderTexturePlugin::getBuffer() { -// uint8_t pixels[] = -// { -// 1, 0, 0, -// 0, 1, 0, -// 0, 0, 1, -// }; - -// std::cout << logger::detail::thin("[" + std::string(tag) + "] ") << message << std::endl; - -// return FlutterPixelBuffer { pixels }; -// } - void EmbedderTexturePlugin::onMethodCall(const MethodCall &call, TextureRegistrar *plugin) { const auto &method = call.GetMethod(); @@ -81,9 +36,11 @@ void EmbedderTexturePlugin::onCreate(const MethodCall &call, TextureRegistrar *p auto textureId = plugin->RegisterTexture(TextureType::Pixels, [this](size_t width, size_t height) { - std::cout << "get callback" << std::endl; + if (this->m_buffer) { + return TextureVariant(FlutterPixelBuffer{ this->m_buffer->buffer } ); + } - return TextureVariant(this->m_buffer); + return TextureVariant(FlutterPixelBuffer{}); }); Aurora::StreamCamera::CameraManager *manager = StreamCameraManager(); @@ -92,7 +49,7 @@ void EmbedderTexturePlugin::onCreate(const MethodCall &call, TextureRegistrar *p { Aurora::StreamCamera::CameraInfo info; - if (manager->getCameraInfo(1, info)) + if (manager->getCameraInfo(0, info)) { std::vector caps; @@ -100,28 +57,30 @@ void EmbedderTexturePlugin::onCreate(const MethodCall &call, TextureRegistrar *p { const Aurora::StreamCamera::CameraCapability cap = caps.at(1); - auto camera = manager->openCamera(info.id); + m_camera = manager->openCamera(info.id); + + m_listener = std::make_shared([this, plugin, textureId](Aurora::StreamCamera::GraphicBuffer *buffer) { + + auto frame = buffer->mapYCbCr(); - auto listener = std::make_unique([=](Aurora::StreamCamera::GraphicBuffer *buffer) { + QSize size(frame->width, frame->height); + QImage* image = new QImage(size, QImage::Format_ARGB32); - uint8_t pixels[] = - { - 1, 0, 0, - 0, 1, 0, - 0, 0, 1, - }; + this->planarYuv420ToArgb(frame->y, frame->cb, frame->cr, + frame->yStride, frame->cStride, frame->cStride, + frame->chromaStep, + reinterpret_cast(image->bits()), + frame->width, frame->height); - m_buffer = FlutterPixelBuffer { pixels }; + uint8_t *pixels = static_cast(image->bits()); - std::cout << "MarkTextureAvailable" << std::endl; + this->m_buffer = new FlutterPixelBuffer { pixels }; plugin->MarkTextureAvailable(textureId); }); - camera->setListener(listener.get()); - - std::cout << info.id << std::endl; - std::cout << camera->startCapture(cap) << std::endl; + m_camera->setListener(m_listener.get()); + m_camera->startCapture(cap); } } } @@ -135,6 +94,10 @@ void EmbedderTexturePlugin::onRemove(const MethodCall &call, TextureRegistrar *p plugin->UnregisterTexture(textureId); + m_camera->stopCapture(); + m_camera = nullptr; + m_buffer = nullptr; + call.SendSuccessResponse(true); } @@ -142,3 +105,49 @@ 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/embedder_texture_plugin.h b/packages/embedder_texture/aurora/include/embedder_texture/embedder_texture_plugin.h index f4c5f09..d00ffb6 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 @@ -8,12 +8,45 @@ #include #include +#include + +#include +#include +#include +#include +#include + #ifdef PLUGIN_IMPL #define PLUGIN_EXPORT __attribute__((visibility("default"))) #else #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: @@ -25,7 +58,12 @@ private: void onRemove(const MethodCall &call, TextureRegistrar *plugin); void unimplemented(const MethodCall &call); - FlutterPixelBuffer m_buffer; + 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); }; #endif /* EMBEDDER_TEXTURE_PLUGIN_H */