diff --git a/windows/include/agora_rtc_engine/texture_render.h b/windows/include/agora_rtc_engine/texture_render.h index 6f2836c2f..e7e74ba11 100644 --- a/windows/include/agora_rtc_engine/texture_render.h +++ b/windows/include/agora_rtc_engine/texture_render.h @@ -21,32 +21,36 @@ class TextureRender : public agora::iris::IrisVideoFrameBufferDelegate int64_t texture_id(); - virtual void OnVideoFrameReceived(const IrisVideoFrame& video_frame, - const IrisVideoFrameBufferConfig* config, - bool resize) override; + virtual void OnVideoFrameReceived(const IrisVideoFrame &video_frame, + const IrisVideoFrameBufferConfig *config, + bool resize) override; void UpdateData(unsigned int uid, const std::string &channelId, unsigned int videoSourceType); - void Dispose(); + // Checks if texture registrar, texture id and texture are available. + bool TextureRegistered() + { + return registrar_ && texture_ && texture_id_ > -1; + } private: - // void HandleMethodCall( - // const flutter::MethodCall &method_call, - // std::unique_ptr> result); - const FlutterDesktopPixelBuffer *CopyPixelBuffer(size_t width, size_t height); public: flutter::TextureRegistrar *registrar_; agora::iris::IrisVideoFrameBufferManager *videoFrameBufferManager_; - flutter::TextureVariant texture_; std::unique_ptr> method_channel_; + int64_t texture_id_ = -1; - // std::unique_ptr> channel_; - // unsigned int uid_; - // std::string channel_id_; - std::mutex mutex_; - FlutterDesktopPixelBuffer *pixel_buffer_; + + uint32_t frame_width_ = 0; + uint32_t frame_height_ = 0; + + std::mutex buffer_mutex_; + std::vector buffer_; + std::unique_ptr texture_; + std::unique_ptr flutter_desktop_pixel_buffer_ = + nullptr; }; #endif // TEXTURE_RENDER_H_ \ No newline at end of file diff --git a/windows/texture_render.cc b/windows/texture_render.cc index 75204cb3d..dfd2fbb61 100644 --- a/windows/texture_render.cc +++ b/windows/texture_render.cc @@ -13,14 +13,18 @@ TextureRender::TextureRender(flutter::BinaryMessenger *messenger, flutter::TextureRegistrar *registrar, agora::iris::IrisVideoFrameBufferManager *videoFrameBufferManager) : registrar_(registrar), - videoFrameBufferManager_(videoFrameBufferManager), - texture_(PixelBufferTexture(std::bind(&TextureRender::CopyPixelBuffer, - this, - std::placeholders::_1, - std::placeholders::_2))), - pixel_buffer_(new FlutterDesktopPixelBuffer{nullptr, 0, 0}) + videoFrameBufferManager_(videoFrameBufferManager) { - texture_id_ = registrar_->RegisterTexture(&texture_); + // Create flutter desktop pixelbuffer texture; + texture_ = + std::make_unique(flutter::PixelBufferTexture( + [this](size_t width, + size_t height) -> const FlutterDesktopPixelBuffer * + { + return this->CopyPixelBuffer(width, height); + })); + + texture_id_ = registrar_->RegisterTexture(texture_.get()); method_channel_ = std::make_unique>( messenger, @@ -30,6 +34,21 @@ TextureRender::TextureRender(flutter::BinaryMessenger *messenger, TextureRender::~TextureRender() { + if (videoFrameBufferManager_) + { + videoFrameBufferManager_->DisableVideoFrameBuffer(this); + videoFrameBufferManager_ = nullptr; + } + + const std::lock_guard lock(buffer_mutex_); + + if (registrar_ && texture_id_ != -1) + { + registrar_->UnregisterTexture(texture_id_); + + registrar_ = nullptr; + texture_id_ = -1; + } } int64_t TextureRender::texture_id() { return texture_id_; } @@ -38,33 +57,64 @@ void TextureRender::OnVideoFrameReceived(const IrisVideoFrame &video_frame, const IrisVideoFrameBufferConfig *config, bool resize) { - std::lock_guard lock_guard(mutex_); - if (pixel_buffer_->width != video_frame.width || - pixel_buffer_->height != video_frame.height) + std::lock_guard lock_guard(buffer_mutex_); + + const uint32_t bytes_per_pixel = 4; + const uint32_t pixels_total = video_frame.width * video_frame.height; + const uint32_t data_size = pixels_total * bytes_per_pixel; + + if (buffer_.size() != data_size) { - if (pixel_buffer_->buffer) - { - delete[] pixel_buffer_->buffer; - } - pixel_buffer_->buffer = new uint8_t[video_frame.y_buffer_length]; + buffer_.resize(data_size); flutter::EncodableMap args = { {EncodableValue("width"), EncodableValue(video_frame.width)}, {EncodableValue("height"), EncodableValue(video_frame.height)}}; method_channel_->InvokeMethod("onSizeChanged", std::make_unique(EncodableValue(args))); } - memcpy((void *)pixel_buffer_->buffer, video_frame.y_buffer, - video_frame.y_buffer_length); - pixel_buffer_->width = video_frame.width; - pixel_buffer_->height = video_frame.height; - registrar_->MarkTextureFrameAvailable(texture_id_); + + std::copy(static_cast(video_frame.y_buffer), static_cast(video_frame.y_buffer) + data_size, buffer_.data()); + + frame_width_ = video_frame.width; + frame_height_ = video_frame.height; + if (TextureRegistered()) + { + registrar_->MarkTextureFrameAvailable(texture_id_); + } } const FlutterDesktopPixelBuffer * TextureRender::CopyPixelBuffer(size_t width, size_t height) { - std::lock_guard lock_guard(mutex_); - return pixel_buffer_; + std::unique_lock buffer_lock(buffer_mutex_); + + if (!TextureRegistered()) + { + return nullptr; + } + + if (!flutter_desktop_pixel_buffer_) + { + flutter_desktop_pixel_buffer_ = + std::make_unique(); + + // Unlocks mutex after texture is processed. + flutter_desktop_pixel_buffer_->release_callback = + [](void *release_context) + { + auto mutex = reinterpret_cast(release_context); + mutex->unlock(); + }; + } + + flutter_desktop_pixel_buffer_->buffer = buffer_.data(); + flutter_desktop_pixel_buffer_->width = frame_width_; + flutter_desktop_pixel_buffer_->height = frame_height_; + + // Releases unique_lock and set mutex pointer for release context. + flutter_desktop_pixel_buffer_->release_context = buffer_lock.release(); + + return flutter_desktop_pixel_buffer_.get(); } void TextureRender::UpdateData(unsigned int uid, const std::string &channelId, unsigned int videoSourceType) @@ -73,7 +123,7 @@ void TextureRender::UpdateData(unsigned int uid, const std::string &channelId, u IrisVideoFrameBufferConfig config; config.id = uid; - config.type = (IrisVideoSourceType)videoSourceType; //::kVideoSourceTypeCameraPrimary; + config.type = (IrisVideoSourceType)videoSourceType; if (!channelId.empty()) { @@ -83,29 +133,8 @@ void TextureRender::UpdateData(unsigned int uid, const std::string &channelId, u { strcpy_s(config.key, ""); } - videoFrameBufferManager_->EnableVideoFrameBuffer(buffer, &config); -} - -void TextureRender::Dispose() -{ if (videoFrameBufferManager_) { - videoFrameBufferManager_->DisableVideoFrameBuffer(this); - } - - if (texture_id_ != -1) - { - registrar_->UnregisterTexture(texture_id_); - texture_id_ = -1; - } - - if (pixel_buffer_) - { - if (pixel_buffer_->buffer) - { - delete[] pixel_buffer_->buffer; - } - delete pixel_buffer_; - pixel_buffer_ = nullptr; + videoFrameBufferManager_->EnableVideoFrameBuffer(buffer, &config); } } \ No newline at end of file diff --git a/windows/video_view_controller.cc b/windows/video_view_controller.cc index a56c879c6..dc08bc3ef 100644 --- a/windows/video_view_controller.cc +++ b/windows/video_view_controller.cc @@ -151,8 +151,6 @@ bool VideoViewController::DestroyTextureRender(int64_t textureId) auto it = renderers_.find(textureId); if (it != renderers_.end()) { - it->second.get()->Dispose(); - renderers_.erase(it); return true; }