diff --git a/AUTHORS b/AUTHORS index c5be022..80089e6 100644 --- a/AUTHORS +++ b/AUTHORS @@ -6,3 +6,4 @@ Sony Group Corporation Hidenori Matsubayashi (hidenori.matsubayashi@gmail.com) +Makoto Sato (makoto.sato@atmark-techno.com) diff --git a/packages/video_player/CHANGELOG.md b/packages/video_player/CHANGELOG.md index 2dd7c2d..b20e05f 100644 --- a/packages/video_player/CHANGELOG.md +++ b/packages/video_player/CHANGELOG.md @@ -1,3 +1,6 @@ +## 0.9.7 +* Improve playback performance if GstEGLImage is avalable. + ## 0.9.6 * Update for video_player_platform_interface v5.1.1 / video_player v2.4.7 / flutter 3.3.0 diff --git a/packages/video_player/README.md b/packages/video_player/README.md index 220c451..95245fa 100644 --- a/packages/video_player/README.md +++ b/packages/video_player/README.md @@ -44,3 +44,10 @@ playbin uri= video-sink="videoconvert ! video/x-raw,format=RGBA ! fakesink #### e.g. customization for i.MX 8M platforms: playbin uri= video-sink="imxvideoconvert_g2d ! video/x-raw,format=RGBA ! fakesink" + +### Enable GstEGLImage +If GstEGLImage is enabled on your target device, adding the following code to `/elinux/CMakeLists.txt` may improve playback performance. +``` +add_definitions(-DUSE_EGL_IMAGE_DMABUF) +set(USE_EGL_IMAGE_DMABUF "on") +``` diff --git a/packages/video_player/elinux/CMakeLists.txt b/packages/video_player/elinux/CMakeLists.txt index b1c8a08..b398f43 100644 --- a/packages/video_player/elinux/CMakeLists.txt +++ b/packages/video_player/elinux/CMakeLists.txt @@ -9,6 +9,9 @@ set(PLUGIN_NAME "video_player_elinux_plugin") find_package(PkgConfig) pkg_check_modules(GLIB REQUIRED glib-2.0) pkg_check_modules(GSTREAMER REQUIRED gstreamer-1.0) +if(USE_EGL_IMAGE_DMABUF) +pkg_check_modules(GSTREAMER_GL REQUIRED gstreamer-gl-1.0) +endif() add_library(${PLUGIN_NAME} SHARED "video_player_elinux_plugin.cc" @@ -27,12 +30,24 @@ target_include_directories(${PLUGIN_NAME} ${GLIB_INCLUDE_DIRS} ${GSTREAMER_INCLUDE_DIRS} ) +if(USE_EGL_IMAGE_DMABUF) +target_include_directories(${PLUGIN_NAME} + PRIVATE + ${GSTREAMER_GL_INCLUDE_DIRS} +) +endif() target_link_libraries(${PLUGIN_NAME} PRIVATE ${GLIB_LIBRARIES} ${GSTREAMER_LIBRARIES} ) +if(USE_EGL_IMAGE_DMABUF) +target_link_libraries(${PLUGIN_NAME} + PRIVATE + ${GSTREAMER_GL_LIBRARIES} +) +endif() # List of absolute paths to libraries that should be bundled with the plugin set(video_player_elinux_bundled_libraries diff --git a/packages/video_player/elinux/gst_video_player.cc b/packages/video_player/elinux/gst_video_player.cc index cb3fa99..02339e8 100644 --- a/packages/video_player/elinux/gst_video_player.cc +++ b/packages/video_player/elinux/gst_video_player.cc @@ -35,6 +35,9 @@ GstVideoPlayer::GstVideoPlayer( } GstVideoPlayer::~GstVideoPlayer() { +#ifdef USE_EGL_IMAGE_DMABUF + UnrefEGLImage(); +#endif // USE_EGL_IMAGE_DMABUF Stop(); DestroyPipeline(); } @@ -167,6 +170,45 @@ int64_t GstVideoPlayer::GetCurrentPosition() { return position / GST_MSECOND; } +#ifdef USE_EGL_IMAGE_DMABUF +void* GstVideoPlayer::GetEGLImage(void* egl_display, void* egl_context) { + std::shared_lock lock(mutex_buffer_); + if (!gst_.buffer) { + return nullptr; + } + + GstMemory* memory = gst_buffer_peek_memory(gst_.buffer, 0); + if (gst_is_dmabuf_memory(memory)) { + UnrefEGLImage(); + + gint fd = gst_dmabuf_memory_get_fd(memory); + gst_gl_display_egl_ = + gst_gl_display_egl_new_with_egl_display(reinterpret_cast(egl_display)); + gst_gl_ctx_ = gst_gl_context_new_wrapped( + GST_GL_DISPLAY_CAST(gst_gl_display_egl_), reinterpret_cast(egl_context), + GST_GL_PLATFORM_EGL, GST_GL_API_GLES2); + + gst_gl_context_activate(gst_gl_ctx_, TRUE); + + gst_egl_image_ = + gst_egl_image_from_dmabuf(gst_gl_ctx_, fd, &gst_video_info_, 0, 0); + return reinterpret_cast(gst_egl_image_get_image(gst_egl_image_)); + } + return nullptr; +} + +void GstVideoPlayer::UnrefEGLImage() { + if (gst_egl_image_) { + gst_egl_image_unref(gst_egl_image_); + gst_object_unref(gst_gl_ctx_); + gst_object_unref(gst_gl_display_egl_); + gst_egl_image_ = NULL; + gst_gl_ctx_ = NULL; + gst_gl_display_egl_ = NULL; + } +} +#endif // USE_EGL_IMAGE_DMABUF + const uint8_t* GstVideoPlayer::GetFrameBuffer() { std::shared_lock lock(mutex_buffer_); if (!gst_.buffer) { @@ -346,6 +388,14 @@ void GstVideoPlayer::GetVideoSize(int32_t& width, int32_t& height) { gst_structure_get_int(structure, "width", &width); gst_structure_get_int(structure, "height", &height); + +#ifdef USE_EGL_IMAGE_DMABUF + gboolean res = gst_video_info_from_caps(&gst_video_info_, caps); + if (!res) { + std::cerr << "Failed to get a gst_video_info" << std::endl; + return; + } +#endif // USE_EGL_IMAGE_DMABUF } // static diff --git a/packages/video_player/elinux/gst_video_player.h b/packages/video_player/elinux/gst_video_player.h index aa94728..bded954 100644 --- a/packages/video_player/elinux/gst_video_player.h +++ b/packages/video_player/elinux/gst_video_player.h @@ -7,6 +7,13 @@ #include +#ifdef USE_EGL_IMAGE_DMABUF +#include +#include +#include +#include +#endif // USE_EGL_IMAGE_DMABUF + #include #include #include @@ -33,6 +40,9 @@ class GstVideoPlayer { int64_t GetDuration(); int64_t GetCurrentPosition(); const uint8_t* GetFrameBuffer(); +#ifdef USE_EGL_IMAGE_DMABUF + void* GetEGLImage(void* egl_display, void* egl_context); +#endif // USE_EGL_IMAGE_DMABUF int32_t GetWidth() const { return width_; }; int32_t GetHeight() const { return height_; }; @@ -56,6 +66,9 @@ class GstVideoPlayer { void DestroyPipeline(); void Preroll(); void GetVideoSize(int32_t& width, int32_t& height); +#ifdef USE_EGL_IMAGE_DMABUF + void UnrefEGLImage(); +#endif // USE_EGL_IMAGE_DMABUF GstVideoElements gst_; std::string uri_; @@ -70,6 +83,13 @@ class GstVideoPlayer { std::mutex mutex_event_completed_; std::shared_mutex mutex_buffer_; std::unique_ptr stream_handler_; + +#ifdef USE_EGL_IMAGE_DMABUF + GstVideoInfo gst_video_info_; + GstEGLImage* gst_egl_image_ = NULL; + GstGLContext* gst_gl_ctx_ = NULL; + GstGLDisplayEGL* gst_gl_display_egl_ = NULL; +#endif // USE_EGL_IMAGE_DMABUF }; #endif // PACKAGES_VIDEO_PLAYER_VIDEO_PLAYER_ELINUX_GST_VIDEO_PLAYER_H_ diff --git a/packages/video_player/elinux/video_player_elinux_plugin.cc b/packages/video_player/elinux/video_player_elinux_plugin.cc index 60ee309..a703e31 100644 --- a/packages/video_player/elinux/video_player_elinux_plugin.cc +++ b/packages/video_player/elinux/video_player_elinux_plugin.cc @@ -86,6 +86,9 @@ class VideoPlayerPlugin : public flutter::Plugin { std::unique_ptr player; std::unique_ptr texture; std::unique_ptr buffer; +#ifdef USE_EGL_IMAGE_DMABUF + std::unique_ptr egl_image; +#endif // USE_EGL_IMAGE_DMABUF std::unique_ptr> event_channel; std::unique_ptr> event_sink; @@ -293,6 +296,20 @@ void VideoPlayerPlugin::HandleCreateMethodCall( } auto instance = std::make_unique(); +#ifdef USE_EGL_IMAGE_DMABUF + instance->egl_image = std::make_unique(); + instance->texture = + std::make_unique(flutter::EGLImageTexture( + [instance = instance.get()]( + size_t width, size_t height, void* egl_display, + void* egl_context) -> const FlutterDesktopEGLImage* { + instance->egl_image->width = instance->player->GetWidth(); + instance->egl_image->height = instance->player->GetHeight(); + instance->egl_image->egl_image = + instance->player->GetEGLImage(egl_display, egl_context); + return instance->egl_image.get(); + })); +#else instance->buffer = std::make_unique(); instance->texture = std::make_unique(flutter::PixelBufferTexture( @@ -303,6 +320,7 @@ void VideoPlayerPlugin::HandleCreateMethodCall( instance->buffer->buffer = instance->player->GetFrameBuffer(); return instance->buffer.get(); })); +#endif // USE_EGL_IMAGE_DMABUF const auto texture_id = texture_registrar_->RegisterTexture(instance->texture.get()); instance->texture_id = texture_id; diff --git a/packages/video_player/pubspec.yaml b/packages/video_player/pubspec.yaml index 9189d7c..3a74ac4 100644 --- a/packages/video_player/pubspec.yaml +++ b/packages/video_player/pubspec.yaml @@ -1,6 +1,6 @@ name: video_player_elinux description: Flutter plugin for displaying inline video with other Flutter widgets on Embedded Linux. -version: 0.9.6 +version: 0.9.7 homepage: https://github.com/sony/flutter-elinux-plugins repository: https://github.com/sony/flutter-elinux-plugins/tree/main/packages/video_player