Skip to content

Commit e54cc26

Browse files
committed
AppImage: use scripts from master
This version preloads libva drivers from system if possible. see #165
1 parent 0a2bd24 commit e54cc26

File tree

5 files changed

+246
-90
lines changed

5 files changed

+246
-90
lines changed

.github/scripts/Linux/prepare.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ sudo add-apt-repository ppa:savoury1/vlc3 # new x265
2020
sudo sed -n 'p; /^deb /s/^deb /deb-src /p' -i /etc/apt/sources.list # for build-dep ffmpeg
2121
sudo apt update
2222
sudo apt -y upgrade
23+
sudo apt install appstream # appstreamcli for mkappimage AppStream validation
2324
sudo apt install libcppunit-dev
2425
sudo apt --no-install-recommends install nvidia-cuda-toolkit
2526
sudo apt install libglew-dev freeglut3-dev libgl1-mesa-dev

.github/workflows/ccpp.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ jobs:
115115
- name: check libc/libstdc++ ABI
116116
run: .github/scripts/Linux/check_abi.sh 2.27 3.4.22 1.3.9 bin/* lib/ultragrid/*
117117
- name: Create AppImage
118-
run: APPIMAGE=`data/scripts/Linux-AppImage/create-appimage.sh https://github.com/$GITHUB_REPOSITORY/releases/download/continuous/UltraGrid-$CHANNEL-x86_64.AppImage.zsync` && mv $APPIMAGE UltraGrid-$VERSION-x86_64.AppImage
118+
run: data/scripts/Linux-AppImage/create-appimage.sh https://github.com/$GITHUB_REPOSITORY/releases/download/continuous/UltraGrid-$CHANNEL-x86_64.AppImage.zsync
119119
- name: Check AppImage
120120
run: |
121121
docker build -f .github/scripts/Linux/utils/Dockerfile.ubuntu -t aitest-ubuntu .

data/scripts/Linux-AppImage/AppRun

Lines changed: 158 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,142 +1,248 @@
11
#!/bin/sh -eu
22

3+
# defaults
4+
use_bundled_libva_default=0
5+
36
# if not run from AppImage (eg. extracted), use default values
47
APPIMAGE=${APPIMAGE-none}
58
ARGV0=${ARGV0-$0}
69

7-
DIR=`dirname $0`
8-
export LD_LIBRARY_PATH=$DIR/usr/lib${LD_LIBRARY_PATH:+":$LD_LIBRARY_PATH"}
10+
DIR=$(dirname "$0")
11+
AI_LIB_PATH=$DIR/usr/lib
12+
export LD_LIBRARY_PATH="$AI_LIB_PATH"${LD_LIBRARY_PATH:+":$LD_LIBRARY_PATH"}
13+
LD_PRELOAD=${LD_PRELOAD-}
914
# there is an issue with running_from_path() which evaluates this executable
1015
# as being system-installed
1116
#export PATH=$DIR/usr/bin:$PATH
12-
export QT_QPA_FONTDIR=$DIR/usr/lib/fonts
13-
export QT_PLUGIN_PATH=$DIR/usr/lib/qt5/plugins
14-
export QT_QPA_PLATFORM_PLUGIN_PATH=$QT_PLUGIN_PATH/platforms
15-
if [ -d "$DIR/usr/lib/va" ] && [ -z "${LIBVA_DRIVERS_PATH:-}" ]; then
16-
export LIBVA_DRIVERS_PATH=$DIR/usr/lib/va
17-
fi
17+
export QT_QPA_FONTDIR="$DIR/usr/share/fonts"
18+
export UG_FONT_DIR="$DIR/usr/share/fonts"
19+
QT_PLUGIN_PATH=$(set -- "$DIR"/usr/lib/qt?/plugins; echo "$1")
20+
export QT_PLUGIN_PATH
21+
export QT_QPA_PLATFORM_PLUGIN_PATH="$QT_PLUGIN_PATH/platforms"
22+
bold=$(tput bold || true)
23+
red=$(tput setaf 1 || true)
24+
reset=$(tput sgr0 || true)
25+
26+
get_tools() {
27+
find "$DIR/usr/bin" -mindepth 1 -exec basename {} \; | tr '\n' ' '
28+
}
1829

1930
usage() {
2031
printf "usage:\n"
21-
printf "\t$ARGV0 [--gui [args]]\n"
32+
printf "\t${bold}${red}%s${reset} ${bold}[--gui [args]]${reset}\n" "$ARGV0"
2233
printf "\t\tinvokes GUI\n"
2334
printf "\n"
24-
printf "\t$ARGV0 --appimage-help\n"
35+
printf "\t${bold}${red}%s${reset} ${bold}--appimage-help${reset}\n" "$ARGV0"
2536
printf "\t\tprints AppImage related options\n"
2637
printf "\n"
27-
printf "\t$ARGV0 -h|--help|--fullhelp\n"
28-
printf "\t\tprints this help (extended version with --fullhelp)\n"
38+
printf "\t${bold}${red}%s${reset} ${bold}-h | --help | --fullhelp${reset}\n" "$ARGV0"
39+
printf "\t\tprints this help (extended version with ${bold}--fullhelp${reset})\n"
2940
printf "\n"
30-
printf "\t$ARGV0 -m|--man [uv|hd-rum-transcode]\n"
41+
printf "\t${bold}${red}%s${reset} ${bold}-m|--man [uv|hd-rum-transcode]${reset}\n" "$ARGV0"
3142
printf "\t\tprints manual page\n"
3243
printf "\n"
33-
printf "\t$ARGV0 -u|--update [args]\n"
44+
printf "\t${bold}${red}%s${reset} ${bold}-u|--update [args]${reset}\n" "$ARGV0"
3445
printf "\t\tupdates AppImage (args will be passed to appimageupdatetool)\n"
3546
printf "\n"
36-
printf "\t$ARGV0 --tool uv --help\n"
47+
printf "\t${bold}${red}%s${reset} ${bold}-o|--tool uv --help${reset}\n" "$ARGV0"
3748
printf "\t\tprints command-line UltraGrid help\n"
3849
printf "\n"
39-
printf "\t$ARGV0 --tool <t> [args]\n"
50+
printf "\t${bold}${red}%s${reset} ${bold}-o|--tool <t> [args]${reset}\n" "$ARGV0"
4051
printf "\t\tinvokes specified tool\n"
41-
printf "\t\ttool may be: $(ls $DIR/usr/bin | tr '\n' ' ')\n"
52+
printf "\t\ttool may be one of: ${bold}%s${reset}\n" "$(get_tools)"
4253
printf "\n"
43-
printf "\t$ARGV0 args\n"
54+
printf "\t${bold}${red}%s${reset} ${bold}args${reset}\n" "$ARGV0"
4455
printf "\t\tinvokes command-line UltraGrid\n"
4556
printf "\n"
4657
}
4758

4859
usage_aux() {
4960
printf "environment variables:\n"
50-
printf "\tULTRAGRID_AUTOUPDATE: 1 - try to autoupdate; 0 - disable update advice\n"
51-
printf "\tULTRAGRID_USE_FIREJAIL: run the UltraGrid executable with firejail. If\n"
52-
printf "\t the variable contains printf a profile path\n"
53-
printf "\t (ends with '.profile'), it will be used.\n"
61+
printf "\tULTRAGRID_AUTOUPDATE: 1 - try to autoupdate; 0 - disable update advice\n"
62+
printf "\tULTRAGRID_BUNDLED_LIBVA: 1 - use bundled libva; 0 - use system libva (if available), default %d\n" $use_bundled_libva_default
63+
printf "\tULTRAGRID_USE_FIREJAIL: run the UltraGrid executable with firejail. If\n"
64+
printf "\t the variable contains printf a profile path\n"
65+
printf "\t (ends with '.profile'), it will be used.\n"
5466
printf "\n"
5567
}
5668

5769
update_notify_days=90
5870
## Print update hint if UG binary is older than $update_notify_days days, if $ULTRAGRID_AUTOUPDATE=1 triggers update.
5971
handle_updates() {
60-
if [ $APPIMAGE = none ]; then
72+
if [ "$APPIMAGE" = none ]; then
6173
return
6274
fi
63-
if [ -n ${ULTRAGRID_AUTOUPDATE-""} ]; then
64-
if [ $ULTRAGRID_AUTOUPDATE -eq 1 ]; then
65-
$DIR/appimageupdatetool $APPIMAGE
75+
if [ -n "${ULTRAGRID_AUTOUPDATE-}" ]; then
76+
if [ "$ULTRAGRID_AUTOUPDATE" -eq 1 ]; then
77+
"$DIR/appimageupdatetool" "$APPIMAGE"
6678
fi
6779
return
6880
fi
69-
if expr $APPIMAGE : '.*continuous' > /dev/null; then
81+
if expr "$APPIMAGE" : '.*continuous' > /dev/null; then
7082
update_notify_days=30
7183
fi
72-
APPIMAGE_MTIME=$(stat --format=%Y $APPIMAGE)
84+
APPIMAGE_MTIME=$(stat -c %Y "$APPIMAGE")
7385
CURR_TIMESTAMP=$(date +%s)
74-
if [ $CURR_TIMESTAMP -lt $(($APPIMAGE_MTIME + $update_notify_days * 24 * 60 * 60)) ]; then
86+
if [ "$CURR_TIMESTAMP" -lt $((APPIMAGE_MTIME + update_notify_days * 24 * 60 * 60)) ]; then
7587
return
7688
fi
77-
printf "UltraGrid binary older than $update_notify_days days, consider checking updates:\n"
89+
printf "UltraGrid binary older than %d days, consider checking updates:\n" $update_notify_days
7890
printf "\n"
79-
printf "$ARGV0 -u\n"
91+
printf "%s -u\n" "$ARGV0"
8092
printf "\t- updates AppImage\n"
81-
printf "$ARGV0 -u -j; [ \$? -eq 1 ] && echo Update available || echo No update available\n"
93+
printf "%s -u -j; [ \$? -eq 1 ] && echo Update available || echo No update available\n" "$ARGV0"
8294
printf "\t- check for update without actually updating\n"
83-
printf "$ARGV0 -u -h\n"
95+
printf "%s -u -h\n" "$ARGV0"
8496
printf "\t- prints update options\n"
8597
printf "\n"
8698
printf "Hint: you can set environment variable ULTRAGRID_AUTOUPDATE to 1 for automatic update or 0 to suppress the above message.\n"
8799
printf "\n"
88100
}
89101

102+
get_dynamic_loader() {
103+
LOADER_LIST='/lib64/ld-linux-*so* /lib/ld-linux-*so* /lib*/ld-linux-*so*'
104+
for LOADER in $LOADER_LIST; do
105+
for n in $LOADER; do
106+
if [ -x "$n" ]; then
107+
echo "$n"
108+
return
109+
fi
110+
done
111+
done
112+
}
113+
114+
## Tries to find system libva. If found it is preloaded (+libva-drm+libva-x11)
115+
## @retval 0 if preloaded; 1 otherwise
116+
set_libva_ld_preload() {
117+
if [ ! -f "$AI_LIB_PATH/ultragrid/ultragrid_vcompress_libavcodec.so" ]; then
118+
return 1
119+
fi
120+
LOADER=$(get_dynamic_loader)
121+
if [ ! -x "$LOADER" ]; then
122+
return 1
123+
fi
124+
AI_LIBAVCODEC_LIB=$(LD_TRACE_LOADED_OBJECTS=1 "$LOADER" "$AI_LIB_PATH/ultragrid/ultragrid_vcompress_libavcodec.so" | grep libavcodec.so | grep -v 'not found' | awk '{print $3}')
125+
if [ -z "$AI_LIBAVCODEC_LIB" ]; then
126+
return 1
127+
fi
128+
S_LD_LIBRARY_PATH=$LD_LIBRARY_PATH
129+
LD_LIBRARY_PATH=
130+
LIBVA_LIB=$(LD_TRACE_LOADED_OBJECTS=1 "$LOADER" "$AI_LIBAVCODEC_LIB" | grep libva.so | grep -v 'not found' | awk '{print $3}')
131+
LD_LIBRARY_PATH=$S_LD_LIBRARY_PATH
132+
if [ -z "$LIBVA_LIB" ]; then
133+
return 1
134+
fi
135+
libva_libs=$LIBVA_LIB
136+
# add also libva-drm, libva-x11 if present
137+
for n in libva-drm libva-x11; do
138+
NAME=$(echo "$LIBVA_LIB" | sed s/libva/$n/)
139+
if [ -f "$NAME" ]; then
140+
libva_libs=$libva_libs:$NAME
141+
fi
142+
done
143+
export LD_PRELOAD="$libva_libs${LD_PRELOAD:+:$LD_PRELOAD}"
144+
return 0
145+
}
146+
147+
## Tries to set LD_PRELOAD to system libva (see set_libva_ld_preload()). If failed, sets path to bundled libva drivers.
148+
setup_vaapi() {
149+
ULTRAGRID_BUNDLED_LIBVA=${ULTRAGRID_BUNDLED_LIBVA:-$use_bundled_libva_default}
150+
if [ "$ULTRAGRID_BUNDLED_LIBVA" -ne 1 ]; then
151+
if ! set_libva_ld_preload; then
152+
echo "${bold}${red}Could not set system libva, using bundled libraries instead!${reset}" >&2
153+
ULTRAGRID_BUNDLED_LIBVA=1
154+
fi
155+
fi
156+
if [ "$ULTRAGRID_BUNDLED_LIBVA" -eq 1 ]; then
157+
if [ -d "$DIR/usr/lib/va" ] && [ -z "${LIBVA_DRIVERS_PATH:-}" ]; then
158+
export LIBVA_DRIVERS_PATH="$AI_LIB_PATH/va"
159+
fi
160+
fi
161+
}
162+
163+
## Parse params to get whitelists that may be needed to add
164+
## @todo spaces inside paths doesn't work
165+
get_firejail_whitelist() {
166+
separator=''
167+
playback_path=$(echo "$@" | sed -n 's/.*--playback \([^ :]*\).*/\1/p')
168+
if [ -n "$playback_path" ]; then
169+
printf -- "$separator--whitelist=%s" "$playback_path"
170+
separator=' '
171+
fi
172+
# print every argument of "filename=" or "file=" pattern
173+
for n in "$@"; do
174+
file_path=$(echo "$n" | sed -n -e 's/.*filename=\([^:]*\).*/\1/p' -e 's/.*file=\([^:]*\).*/\1/p')
175+
if [ -n "$file_path" ]; then
176+
printf -- "$separator--whitelist=%s" "$file_path"
177+
separator=' '
178+
fi
179+
done
180+
if [ -z "$separator" ]; then
181+
printf -- "--private"
182+
fi
183+
}
184+
185+
setup_vaapi
186+
# shellcheck source=/dev/null
187+
. "$DIR/scripts/jack_preload.sh"
188+
90189
RUN=
91-
if [ -n "${ULTRAGRID_USE_FIREJAIL-}" ]; then
190+
if [ -n "${ULTRAGRID_USE_FIREJAIL-}" ] && [ "$ULTRAGRID_USE_FIREJAIL" != 0 ] && [ "$ULTRAGRID_USE_FIREJAIL" != no ]; then
92191
command -v firejail >/dev/null || { echo "Firejail not present in system!"; exit 1; }
93-
if expr $ULTRAGRID_USE_FIREJAIL : '.*\.profile' >/dev/null; then
192+
if expr "$ULTRAGRID_USE_FIREJAIL" : '.*\.profile' >/dev/null; then
94193
FIREJAIL_OPTS="--profile=$ULTRAGRID_USE_FIREJAIL"
95194
else
96-
FIREJAIL_OPTS="--caps.drop=all --ipc-namespace --nonewprivs --noroot --protocol=unix,inet,inet6,netlink --seccomp --shell=none --disable-mnt --private-bin=none --private-opt=none --private --read-only=/tmp --writable-var"
97-
FIREJAIL_OPTS="$FIREJAIL_OPTS --private-etc=alsa,group,hostname,ld.so.conf,ld.so.cache,ld.so.conf.d,nsswitch.conf,passwd,resolv.conf"
195+
FJ_TMPDIR=${TMPDIR-/tmp/ultragrid-$(id -u)}
196+
FIREJAIL_OPTS="--caps.drop=all --ipc-namespace --nonewprivs --noroot --protocol=unix,inet,inet6,netlink --seccomp --shell=none --disable-mnt --private-bin=none --private-opt=none --read-only=/tmp --mkdir=$FJ_TMPDIR --read-write=$FJ_TMPDIR --writable-var"
197+
FIREJAIL_OPTS="$FIREJAIL_OPTS $(get_firejail_whitelist "$@") --private-etc=alsa,group,hostname,ld.so.conf,ld.so.cache,ld.so.conf.d,nsswitch.conf,passwd,resolv.conf --ignore=novideo"
98198
fi
99199
if firejail --version | grep -iq "d-\{0,1\}bus.*enabled"; then
100200
FIREJAIL_OPTS="$FIREJAIL_OPTS --dbus-user=none --dbus-system=none"
101201
fi
102202
if firejail --help | grep -q -- --keep-var-tmp; then
103203
FIREJAIL_OPTS="$FIREJAIL_OPTS --keep-var-tmp"
104204
fi
105-
RUN="firejail --env=LD_LIBRARY_PATH=${LD_LIBRARY_PATH} $FIREJAIL_OPTS "
205+
RUN="firejail --env=LD_PRELOAD=${LD_PRELOAD} --env=LD_LIBRARY_PATH=${LD_LIBRARY_PATH}${FJ_TMPDIR+ --env=TMPDIR=${FJ_TMPDIR}} --env=UG_FONT_DIR=${UG_FONT_DIR} $FIREJAIL_OPTS "
106206
fi
107207

108-
if [ $# -eq 0 -o x"${1-}" = x"--gui" ]; then
208+
if [ $# -eq 0 ] || [ "${1-}" = "--gui" ]; then
109209
handle_updates
110-
[ $# -eq 0 ] && usage || shift
111-
if [ -x $DIR/usr/bin/uv-qt ]; then
112-
$DIR/usr/bin/uv-qt --with-uv $DIR/usr/bin/uv "$@"
210+
if [ $# -eq 0 ]; then usage; else shift; fi
211+
if [ -x "$DIR/usr/bin/uv-qt" ]; then
212+
"$DIR/usr/bin/uv-qt" --with-uv "$DIR/usr/bin/uv" "$@"
113213
else
114214
echo "GUI was not compiled in!" >&2
115215
exit 1
116216
fi
117-
elif [ x"$1" = x"--tool" ]; then
217+
elif [ "$1" = "-o" ] || [ "$1" = "--tool" ]; then
118218
handle_updates
119219
TOOL=$2
120220
shift 2
121-
${RUN}$DIR/usr/bin/$TOOL "$@"
122-
elif [ x"$1" = x"-h" -o x"$1" = x"--help" ]; then
221+
if [ "$TOOL" = help ]; then
222+
printf "available tools: ${bold}%s${reset}\n" "$(get_tools)"
223+
exit 0
224+
fi
225+
# shellcheck disable=SC2086
226+
${RUN}"$DIR/usr/bin/$TOOL" "$@"
227+
elif [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
123228
usage
124229
exit 0
125-
elif [ x"$1" = x"--fullhelp" ]; then
230+
elif [ "$1" = "--fullhelp" ]; then
126231
usage
127232
usage_aux
128233
exit 0
129-
elif [ x"$1" = x"-m" -o x"$1" = x"--man" ]; then
234+
elif [ "$1" = "-m" ] || [ "$1" = "--man" ]; then
130235
PAGE=${2:-uv}
131-
cat $DIR/usr/share/man/man1/$PAGE.1 | man -l -
132-
elif [ x"$1" = x"-u" -o x"$1" = x"--update" ]; then
236+
man -l "$DIR/usr/share/man/man1/$PAGE.1"
237+
elif [ "$1" = "-u" ] || [ "$1" = "--update" ]; then
133238
shift
134239
unset LD_LIBRARY_PATH
135-
touch $APPIMAGE # update AppImage mtime to avoid update notices if there are no updates avalable but were checked for
136-
$DIR/appimageupdatetool ${1+"$@" }$APPIMAGE
240+
touch "$APPIMAGE" # update AppImage mtime to avoid update notices if there are no updates avalable but were checked for
241+
"$DIR/appimageupdatetool" ${1+"$@" }"$APPIMAGE"
137242
else
138243
handle_updates
139-
${RUN}$DIR/usr/bin/uv "$@"
244+
# shellcheck disable=SC2086
245+
${RUN}"$DIR/usr/bin/uv" "$@"
140246
fi
141247

142248
exit $?

0 commit comments

Comments
 (0)