Skip to content

Add gstreamer video player #228

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 22 commits into from
Feb 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
.vscode
compile_commands.json
.clang-format
out
build
build_debug
build_release
build
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "third_party/backward-cpp"]
path = third_party/backward-cpp
url = https://github.com/bombela/backward-cpp.git
134 changes: 102 additions & 32 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
#
# MIT License
#
# Copyright (c) 2020 Joel Winarske
# Original work Copyright (c) 2020 Joel Winarske
# Modified work Copyright 2021 Hannes Winkler
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
Expand Down Expand Up @@ -29,13 +30,23 @@ if(NOT CMAKE_BUILD_TYPE)
message(STATUS "CMAKE_BUILD_TYPE not set, defaulting to Release.")
endif()

project(flutter-pi LANGUAGES C VERSION "1.0.0")
project(flutter-pi LANGUAGES C CXX VERSION "1.0.0")

message(STATUS "Generator .............. ${CMAKE_GENERATOR}")
message(STATUS "Build Type ............. ${CMAKE_BUILD_TYPE}")

option(OMXPLAYER_SUPPORTS_RUNTIME_ROTATION "Whether omxplayer supports runtime rotation." OFF)
option(BUILD_TEXT_INPUT_PLUGIN "Include the text input plugin in the finished binary. Enables text input (to flutter text fields, for example) via attached keyboards." ON)
option(BUILD_RAW_KEYBOARD_PLUGIN "Include the raw keyboard plugin in the finished binary. Enables raw keycode listening in flutter via the flutter RawKeyboard interface." ON)
option(BUILD_TEST_PLUGIN "Include the test plugin in the finished binary. Allows testing platform channel communication." OFF)
option(BUILD_OMXPLAYER_VIDEO_PLAYER_PLUGIN "Include the omxplayer_video_player plugin in the finished binary. Allows for hardware accelerated video playback in flutter using omxplayer." OFF)
option(BUILD_GSTREAMER_VIDEO_PLAYER_PLUGIN "Include the gstreamer_video_player plugin in the finished binary. Allows for more stable, hardware accelerated video playback in flutter using gstreamer." ON)
option(DUMP_ENGINE_LAYERS "True if flutter-pi should dump the list of rendering layers that the flutter engine sends to flutter-pi on each draw." OFF)
option(ENABLE_TSAN "True to build & link with -fsanitize=thread" OFF)
option(ENABLE_ASAN "True to build & link with -fsanitize=address" OFF)
option(ENABLE_UBSAN "True to build & link with -fsanitize=undefined" OFF)
option(ENABLE_MTRACE "True if flutter-pi should call GNU mtrace() on startup." OFF)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

if(NOT FLUTTER_EMBEDDER_HEADER)

Expand Down Expand Up @@ -84,6 +95,7 @@ else()
endif()

include(ExternalProject)
include(CheckCCompilerFlag)

set(ENV{PKG_CONFIG_PATH} ${PKG_CONFIG_PATH})
message(STATUS "PKG_CONFIG_PATH ........ $ENV{PKG_CONFIG_PATH}")
Expand All @@ -98,41 +110,23 @@ pkg_check_modules(LIBINPUT REQUIRED libinput)
pkg_check_modules(LIBXKBCOMMON REQUIRED xkbcommon)
pkg_check_modules(LIBUDEV REQUIRED libudev)

set(BUILD_TEXT_INPUT_PLUGIN ON CACHE BOOL "Include the text input plugin in the finished binary. Enables text input (to flutter text fields, for example) via attached keyboards.")
set(BUILD_RAW_KEYBOARD_PLUGIN ON CACHE BOOL "Include the raw keyboard plugin in the finished binary. Enables raw keycode listening in flutter via the flutter RawKeyboard interface.")
set(BUILD_TEST_PLUGIN OFF CACHE BOOL "Include the test plugin in the finished binary. Allows testing platform channel communication.")
set(BUILD_OMXPLAYER_VIDEO_PLAYER_PLUGIN ON CACHE BOOL "Include the omxplayer_video_player plugin in the finished binary. Allows for hardware accelerated video playback in flutter using omxplayer.")

set(FLUTTER_PI_SRC
add_executable(flutter-pi
src/flutter-pi.c
src/platformchannel.c
src/pluginregistry.c
src/texture_registry.c
src/compositor.c
src/modesetting.c
src/collection.c
src/platformchannel.c
src/pluginregistry.c
src/texture_registry.c
src/compositor.c
src/modesetting.c
src/collection.c
src/cursor.c
src/keyboard.c
src/user_input.c
src/locales.c
src/plugins/services.c
src/notifier_listener.c
src/pixel_format.c
src/plugins/services.c
)

if (BUILD_TEXT_INPUT_PLUGIN)
list(APPEND FLUTTER_PI_SRC src/plugins/text_input.c)
endif()
if (BUILD_RAW_KEYBOARD_PLUGIN)
list(APPEND FLUTTER_PI_SRC src/plugins/raw_keyboard.c)
endif()
if (BUILD_TEST_PLUGIN)
list(APPEND FLUTTER_PI_SRC src/plugins/testplugin.c)
endif()
if (BUILD_OMXPLAYER_VIDEO_PLAYER_PLUGIN)
list(APPEND FLUTTER_PI_SRC src/plugins/omxplayer_video_player.c)
endif()

add_executable(flutter-pi ${FLUTTER_PI_SRC})

target_link_libraries(flutter-pi
${DRM_LDFLAGS}
${GBM_LDFLAGS}
Expand All @@ -142,7 +136,7 @@ target_link_libraries(flutter-pi
${LIBINPUT_LDFLAGS}
${LIBUDEV_LDFLAGS}
${LIBXKBCOMMON_LDFLAGS}
pthread dl rt m
pthread dl rt m atomic
)

target_include_directories(flutter-pi PRIVATE
Expand All @@ -168,27 +162,103 @@ target_compile_options(flutter-pi PRIVATE
${LIBINPUT_CFLAGS}
${LIBUDEV_CFLAGS}
${LIBXKBCOMMON_CFLAGS}
$<$<CONFIG:DEBUG>:-O0 -ggdb -DDEBUG>
$<$<CONFIG:Debug>:-O0 -Wall -Wextra -Wno-unused-function -Wno-sign-compare -Wno-missing-field-initializers -Werror -ggdb -DDEBUG>
$<$<CONFIG:RelWithDebInfo>:-O2 -Wall -Wextra -Wno-unused-function -Wno-sign-compare -Wno-missing-field-initializers -ggdb>
$<$<CONFIG:Release>:-O2 -Wall -Wextra -Wno-unused-function -Wno-sign-compare -Wno-missing-field-initializers -ggdb>
)

# TODO: Just unconditionally define those, make them optional later
target_compile_definitions(flutter-pi PRIVATE HAS_KMS HAS_EGL HAS_GBM HAS_FBDEV)

# TODO: We actually don't need the compile definitions anymore, except for
# text input and raw keyboard plugin (because those have special treatment
# in flutter-pi.c)
if (BUILD_TEXT_INPUT_PLUGIN)
target_sources(flutter-pi PRIVATE src/plugins/text_input.c)
target_compile_definitions(flutter-pi PRIVATE "BUILD_TEXT_INPUT_PLUGIN")
endif()
if (BUILD_RAW_KEYBOARD_PLUGIN)
target_sources(flutter-pi PRIVATE src/plugins/raw_keyboard.c)
target_compile_definitions(flutter-pi PRIVATE "BUILD_RAW_KEYBOARD_PLUGIN")
endif()
if (BUILD_TEST_PLUGIN)
target_sources(flutter-pi PRIVATE src/plugins/testplugin.c)
target_compile_definitions(flutter-pi PRIVATE "BUILD_TEST_PLUGIN")
endif()
if (BUILD_OMXPLAYER_VIDEO_PLAYER_PLUGIN)
target_sources(flutter-pi PRIVATE src/plugins/omxplayer_video_player.c)
target_compile_definitions(flutter-pi PRIVATE "BUILD_OMXPLAYER_VIDEO_PLAYER_PLUGIN")
endif()
if (OMXPLAYER_SUPPORTS_RUNTIME_ROTATION)
target_compile_definitions(flutter-pi PRIVATE "OMXPLAYER_SUPPORTS_RUNTIME_ROTATION")
endif()
if (BUILD_GSTREAMER_VIDEO_PLAYER_PLUGIN)
pkg_check_modules(LIBGSTREAMER REQUIRED gstreamer-1.0)
pkg_check_modules(LIBGSTREAMER_PLUGINS_BASE REQUIRED gstreamer-plugins-base-1.0)
pkg_check_modules(LIBGSTREAMER_APP REQUIRED gstreamer-app-1.0)
pkg_check_modules(LIBGSTREAMER_ALLOCATORS REQUIRED gstreamer-allocators-1.0)
pkg_check_modules(LIBGSTREAMER_VIDEO REQUIRED gstreamer-video-1.0)

target_sources(flutter-pi PRIVATE
src/plugins/gstreamer_video_player/plugin.c
src/plugins/gstreamer_video_player/player.c
src/plugins/gstreamer_video_player/frame.c
)
target_compile_definitions(flutter-pi PRIVATE "BUILD_GSTREAMER_VIDEO_PLAYER_PLUGIN")
target_link_libraries(flutter-pi
${LIBGSTREAMER_LDFLAGS}
${LIBGSTREAMER_PLUGINS_BASE_LDFLAGS}
${LIBGSTREAMER_APP_LDFLAGS}
${LIBGSTREAMER_ALLOCATORS_LDFLAGS}
${LIBGSTREAMER_VIDEO_LDFLAGS}
)
target_include_directories(flutter-pi PRIVATE
${LIBGSTREAMER_INCLUDE_DIRS}
${LIBGSTREAMER_PLUGINS_BASE_INCLUDE_DIRS}
${LIBGSTREAMER_APP_INCLUDE_DIRS}
${LIBGSTREAMER_ALLOCATORS_INCLUDE_DIRS}
${LIBGSTREAMER_VIDEO_INCLUDE_DIRS}
)
target_compile_options(flutter-pi PRIVATE
${LIBGSTREAMER_CFLAGS}
${LIBGSTREAMER_PLUGINS_BASE_CFLAGS}
${LIBGSTREAMER_APP_CFLAGS}
${LIBGSTREAMER_ALLOCATORS_CFLAGS}
${LIBGSTREAMER_VIDEO_CFLAGS}
)
endif()

# Needed so dart VM can actually resolve symbols in the same
# executable.
target_link_options(flutter-pi PRIVATE
-rdynamic
)

if (ENABLE_TSAN)
target_link_options(flutter-pi PRIVATE -fsanitize=thread)
target_compile_options(flutter-pi PRIVATE -fsanitize=thread)
endif()
if (ENABLE_ASAN)
# when we use asan, we need to force linking against the C++ stdlib.
# If we don't link against it, and load a dynamic library that's linked against the C++ stdlib (like the flutter engine),
# and something in the dynamically loaded library triggers asan, it'll throw an error because it hasn't
# intercepted stdc++ yet.
# Also disable --as-needed so we _actually_ link against c++, even though we don't use any symbols from it.
target_link_libraries(flutter-pi stdc++)
target_link_options(flutter-pi PRIVATE -fsanitize=address -fno-omit-frame-pointer -Wl,--no-as-needed)
target_compile_options(flutter-pi PRIVATE -fsanitize=address)

check_c_compiler_flag(-static-libasan HAS_STATIC_LIBASAN)
if (HAS_STATIC_LIBASAN)
target_link_options(flutter-pi PRIVATE -static-libasan)
endif()
endif()
if (ENABLE_UBSAN)
target_link_options(flutter-pi PRIVATE -fsanitize=undefined)
target_compile_options(flutter-pi PRIVATE -fsanitize=undefined)
endif()
if (ENABLE_MTRACE)
target_compile_definitions(flutter-pi PRIVATE "ENABLE_MTRACE")
endif()

install(TARGETS flutter-pi RUNTIME DESTINATION bin)
35 changes: 26 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
## 📰 NEWS
- The new latest flutter gallery commit for flutter 2.8 is `9eb785c`
- There's now a `#custom-embedders` channel on the [flutter discord](https://github.com/flutter/flutter/wiki/Chat) which you can use if you have any questions regarding flutter-pi or generally, anything related to embedding the engine for which you don't want to open issue about or write an email.
- There's now a new video player based on gstreamer. See [gstreamer video player](#gstreamer-video-player) section.
- The new latest flutter gallery commit for flutter 2.10 is `5da082d`

# flutter-pi
A light-weight Flutter Engine Embedder for Raspberry Pi. Inspired by https://github.com/chinmaygarde/flutter_from_scratch.
Flutter-pi also runs without X11, so you don't need to boot into Raspbian Desktop & have X11 and LXDE load up; just boot into the command-line.

You can now **theoretically** run every flutter app you want using flutter-pi, including apps using packages & plugins, just that you'd have to build the platform side of the plugins you'd like to use yourself.

_The difference between packages and plugins is that packages don't include any native code, they are just pure Dart. Plugins (like the [connectivity plugin](https://github.com/flutter/plugins/tree/master/packages/connectivity)) include platform-specific code._
_The difference between packages and plugins is that packages don't include any native code, they are just pure Dart. Plugins (like the [shared_preferences plugin](https://github.com/flutter/plugins/tree/main/packages/shared_preferences)) include platform-specific code._

## 🖥️ Supported Platforms
Although flutter-pi is only tested on a Rasberry Pi 4 2GB, it should work fine on other linux platforms, with the following conditions:
Expand All @@ -30,9 +30,11 @@ If you encounter issues running flutter-pi on any of the supported platforms lis
2.2 [Building the Asset bundle](#building-the-asset-bundle)
2.3 [Building the `app.so` (for running your app in Release/Profile mode)](#building-the-appso-for-running-your-app-in-releaseprofile-mode)
2.4 [Running your App with flutter-pi](#running-your-app-with-flutter-pi)
2.5 [gstreamer video player](#gstreamer-video-player)
3. **[Performance](#-performance)**
3.1 [Graphics Performance](#graphics-performance)
3.2 [Touchscreen latency](#touchscreen-latency)
4. **[Discord](#-discord)**

## 🛠 Building flutter-pi on the Raspberry Pi
- If you want to update flutter-pi, you check out the latest commit using `git pull && git checkout origin/master` and continue with [compiling](#compiling), step 2.
Expand All @@ -51,8 +53,13 @@ If you encounter issues running flutter-pi on any of the supported platforms lis
</details>

2. Install cmake, graphics, system libraries and fonts:
```bash
sudo apt install cmake libgl1-mesa-dev libgles2-mesa-dev libegl1-mesa-dev libdrm-dev libgbm-dev ttf-mscorefonts-installer fontconfig libsystemd-dev libinput-dev libudev-dev libxkbcommon-dev
```shell
$ sudo apt install cmake libgl1-mesa-dev libgles2-mesa-dev libegl1-mesa-dev libdrm-dev libgbm-dev ttf-mscorefonts-installer fontconfig libsystemd-dev libinput-dev libudev-dev libxkbcommon-dev
```

If you want to use the [gstreamer video player](#gstreamer-video-player), install these too:
```shell
$ sudo apt install libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-ugly gstreamer1.0-plugins-bad gstreamer1.0-libav
```
<details>
<summary>More Info</summary>
Expand Down Expand Up @@ -152,7 +159,7 @@ If you encounter issues running flutter-pi on any of the supported platforms lis
```bash
git clone https://github.com/flutter/gallery.git flutter_gallery
cd flutter_gallery
git checkout 9eb785c
git checkout 5da082d
flutter build bundle
rsync -a ./build/flutter_assets/ pi@raspberrypi:/home/pi/flutter_gallery/
```
Expand All @@ -161,8 +168,8 @@ rsync -a ./build/flutter_assets/ pi@raspberrypi:/home/pi/flutter_gallery/
<details>
<summary>More information</summary>

- flutter_gallery is developed against flutter master. `9eb785c` is currently the latest flutter gallery
commit working with flutter stable (2.8).
- flutter_gallery is developed against flutter master. `5da082d82e2da9f57e396b5a1302dc924c81f83d` is currently the latest flutter gallery
commit working with flutter stable.
</details>

### Building the `app.so` (for running your app in Release/Profile mode)
Expand Down Expand Up @@ -219,7 +226,7 @@ rsync -a ./build/flutter_assets/ pi@raspberrypi:/home/pi/flutter_gallery/
git clone https://github.com/flutter/gallery.git flutter_gallery
git clone --depth 1 https://github.com/ardera/flutter-engine-binaries-for-arm.git engine-binaries
cd flutter_gallery
git checkout 633be8a
git checkout 5da082d82e2da9f57e396b5a1302dc924c81f83d
flutter build bundle
C:\flutter\bin\cache\dart-sdk\bin\dart.exe ^
C:\flutter\bin\cache\dart-sdk\bin\snapshots\frontend_server.dart.snapshot ^
Expand Down Expand Up @@ -323,6 +330,13 @@ of the flutter app you're trying to run.

`[flutter engine options...]` will be passed as commandline arguments to the flutter engine. You can find a list of commandline options for the flutter engine [Here](https://github.com/flutter/engine/blob/master/shell/common/switches.h).

### gstreamer video player
Gstreamer video player is a newer video player based on gstreamer. The older video player (omxplayer_video_player) was based on deprecated omxplayer and it was kind of a hack. So I recommend using the gstreamer one instead.

To use the gstreamer video player, just rebuild flutter-pi (delete your build folder and reconfigure) and make sure the necessary gstreamer packages are installed. (See [dependencies](#dependencies))

And then, just use the stuff in the official [video_player](https://pub.dev/packages/video_player) package. (`VideoPlayer`, `VideoPlayerController`, etc, there's nothing specific you need to do on the dart-side)

## 📊 Performance
### Graphics Performance
Graphics performance is actually pretty good. With most of the apps inside the `flutter SDK -> examples -> catalog` directory I get smooth 50-60fps on the Pi 4 2GB and Pi 3 A+.
Expand All @@ -331,3 +345,6 @@ Graphics performance is actually pretty good. With most of the apps inside the `
Due to the way the touchscreen driver works in raspbian, there's some delta between an actual touch of the touchscreen and a touch event arriving at userspace. The touchscreen driver in the raspbian kernel actually just repeatedly polls some buffer shared with the firmware running on the VideoCore, and the videocore repeatedly polls the touchscreen. (both at 60Hz) So on average, there's a delay of 17ms (minimum 0ms, maximum 34ms). Actually, the firmware is polling correctly at ~60Hz, but the linux driver is not because there's a bug. The linux side actually polls at 25Hz, which makes touch applications look terrible. (When you drag something in a touch application, but the application only gets new touch data at 25Hz, it'll look like the application itself is _redrawing_ at 25Hz, making it look very laggy) The github issue for this raspberry pi kernel bug is [here](https://github.com/raspberrypi/linux/issues/3777). Leave a like on the issue if you'd like to see this fixed in the kernel.

This is why I created my own (userspace) touchscreen driver, for improved latency & polling rate. See [this repo](https://github.com/ardera/raspberrypi-fast-ts) for details. The driver is very easy to use and the difference is noticeable, flutter apps look and feel a lot better with this driver.

## 💬 Discord
There a `#custom-embedders` channel on the [flutter discord](https://github.com/flutter/flutter/wiki/Chat) which you can use if you have any questions regarding flutter-pi or generally, anything related to embedding the engine for which you don't want to open issue about or write an email.
Loading