mirror of
https://github.com/mofeng-git/One-KVM.git
synced 2026-06-14 03:32:00 +08:00
feat: 新增安卓平台支持
This commit is contained in:
219
scripts/build-android-alsa.sh
Normal file
219
scripts/build-android-alsa.sh
Normal file
@@ -0,0 +1,219 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
||||
|
||||
SOURCE_DIR=""
|
||||
OUTPUT_DIR="${PROJECT_ROOT}/dist/android-alsa"
|
||||
ANDROID_API="${ANDROID_API:-21}"
|
||||
NDK_ROOT="${ANDROID_NDK_HOME:-${ANDROID_NDK_ROOT:-}}"
|
||||
BUILD_ABIS="arm64-v8a armeabi-v7a"
|
||||
JOBS="${JOBS:-$(nproc 2>/dev/null || echo 4)}"
|
||||
ALSA_REPO="${ALSA_REPO:-https://github.com/alsa-project/alsa-lib.git}"
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage:
|
||||
scripts/build-android-alsa.sh [options]
|
||||
|
||||
Options:
|
||||
--source <dir> Existing alsa-lib source checkout. If omitted, the
|
||||
script clones it into .tmp/android-alsa-src.
|
||||
--output <dir> Output root. Default: dist/android-alsa
|
||||
--ndk <dir> Android NDK root. Defaults to ANDROID_NDK_HOME or ANDROID_NDK_ROOT.
|
||||
--api <level> Android API level. Default: 21.
|
||||
--abis <list> Space/comma separated ABI list. Default: arm64-v8a armeabi-v7a.
|
||||
-h, --help Show this help.
|
||||
|
||||
The output layout is compatible with ONE_KVM_ANDROID_ALSA_ROOT:
|
||||
<output>/arm64-v8a/include/alsa/asoundlib.h
|
||||
<output>/arm64-v8a/lib/libasound.so
|
||||
<output>/arm64-v8a/lib/pkgconfig/alsa.pc
|
||||
<output>/armeabi-v7a/include/alsa/asoundlib.h
|
||||
<output>/armeabi-v7a/lib/libasound.so
|
||||
<output>/armeabi-v7a/lib/pkgconfig/alsa.pc
|
||||
EOF
|
||||
}
|
||||
|
||||
fail() {
|
||||
echo "Error: $*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--source)
|
||||
SOURCE_DIR="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
--output)
|
||||
OUTPUT_DIR="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
--ndk)
|
||||
NDK_ROOT="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
--api)
|
||||
ANDROID_API="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
--abis)
|
||||
BUILD_ABIS="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
-h | --help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
fail "Unknown argument: $1"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
[[ -n "$NDK_ROOT" ]] || fail "--ndk or ANDROID_NDK_HOME/ANDROID_NDK_ROOT is required"
|
||||
[[ -d "$NDK_ROOT/toolchains/llvm/prebuilt" ]] || fail "Invalid NDK root: $NDK_ROOT"
|
||||
|
||||
if [[ -z "$SOURCE_DIR" ]]; then
|
||||
SOURCE_DIR="${PROJECT_ROOT}/.tmp/android-alsa-src"
|
||||
if [[ ! -d "$SOURCE_DIR/.git" ]]; then
|
||||
rm -rf "$SOURCE_DIR"
|
||||
git clone --depth 1 "$ALSA_REPO" "$SOURCE_DIR"
|
||||
fi
|
||||
fi
|
||||
|
||||
[[ -d "$SOURCE_DIR" ]] || fail "alsa-lib source not found: $SOURCE_DIR"
|
||||
[[ -f "$SOURCE_DIR/configure.ac" || -f "$SOURCE_DIR/configure" ]] || fail "alsa-lib source layout not recognized under: $SOURCE_DIR"
|
||||
|
||||
SOURCE_DIR="$(cd "$SOURCE_DIR" && pwd)"
|
||||
mkdir -p "$OUTPUT_DIR"
|
||||
OUTPUT_DIR="$(cd "$OUTPUT_DIR" && pwd)"
|
||||
|
||||
HOST_TAG="$(uname -s | tr '[:upper:]' '[:lower:]')-x86_64"
|
||||
TOOLCHAIN="${NDK_ROOT}/toolchains/llvm/prebuilt/${HOST_TAG}"
|
||||
ANDROID_TOOLCHAIN_FILE="${NDK_ROOT}/build/cmake/android.toolchain.cmake"
|
||||
[[ -d "$TOOLCHAIN/bin" ]] || fail "NDK LLVM toolchain not found: $TOOLCHAIN"
|
||||
[[ -f "$ANDROID_TOOLCHAIN_FILE" ]] || fail "NDK CMake toolchain not found: $ANDROID_TOOLCHAIN_FILE"
|
||||
command -v cmake >/dev/null 2>&1 || fail "cmake is required"
|
||||
command -v autoreconf >/dev/null 2>&1 || fail "autoreconf is required"
|
||||
|
||||
normalize_abis() {
|
||||
printf '%s\n' "$BUILD_ABIS" | tr ',' ' '
|
||||
}
|
||||
|
||||
clean_generated_source_headers() {
|
||||
rm -f \
|
||||
"$SOURCE_DIR/include/asoundlib.h" \
|
||||
"$SOURCE_DIR/include/version.h" \
|
||||
"$SOURCE_DIR/include/stamp-vh" \
|
||||
"$SOURCE_DIR/include/alsa"
|
||||
}
|
||||
|
||||
build_one() {
|
||||
local abi="$1"
|
||||
local prefix build_dir
|
||||
|
||||
case "$abi" in
|
||||
arm64-v8a | armeabi-v7a) ;;
|
||||
*) fail "Unsupported ABI: $abi" ;;
|
||||
esac
|
||||
|
||||
prefix="${OUTPUT_DIR}/${abi}"
|
||||
build_dir="${PROJECT_ROOT}/.tmp/alsa-android-build/${abi}"
|
||||
|
||||
rm -rf "$build_dir"
|
||||
mkdir -p "$build_dir" "$prefix"
|
||||
|
||||
case "$abi" in
|
||||
arm64-v8a)
|
||||
export CC="${TOOLCHAIN}/bin/aarch64-linux-android${ANDROID_API}-clang"
|
||||
export CXX="${TOOLCHAIN}/bin/aarch64-linux-android${ANDROID_API}-clang++"
|
||||
export HOST_TRIPLE="aarch64-linux-android"
|
||||
;;
|
||||
armeabi-v7a)
|
||||
export CC="${TOOLCHAIN}/bin/armv7a-linux-androideabi${ANDROID_API}-clang"
|
||||
export CXX="${TOOLCHAIN}/bin/armv7a-linux-androideabi${ANDROID_API}-clang++"
|
||||
export HOST_TRIPLE="arm-linux-androideabi"
|
||||
;;
|
||||
esac
|
||||
export AR="${TOOLCHAIN}/bin/llvm-ar"
|
||||
export RANLIB="${TOOLCHAIN}/bin/llvm-ranlib"
|
||||
export STRIP="${TOOLCHAIN}/bin/llvm-strip"
|
||||
export CFLAGS="-fPIC"
|
||||
export CXXFLAGS="-fPIC"
|
||||
|
||||
clean_generated_source_headers
|
||||
|
||||
if [[ -f "$SOURCE_DIR/config.status" || -f "$SOURCE_DIR/Makefile" ]]; then
|
||||
(
|
||||
cd "$SOURCE_DIR"
|
||||
make distclean >/dev/null 2>&1 || true
|
||||
)
|
||||
clean_generated_source_headers
|
||||
fi
|
||||
|
||||
if [[ ! -x "$SOURCE_DIR/configure" ]]; then
|
||||
(
|
||||
cd "$SOURCE_DIR"
|
||||
autoreconf -fi
|
||||
)
|
||||
fi
|
||||
|
||||
(
|
||||
cd "$build_dir"
|
||||
pcm_plugins="copy linear route mulaw alaw adpcm rate plug multi file null empty meter hooks lfloat ladspa asym iec958 softvol extplug ioplug mmap_emul"
|
||||
ctl_plugins="remap ext"
|
||||
ac_cv_header_sys_shm_h=no \
|
||||
"$SOURCE_DIR/configure" \
|
||||
--host="$HOST_TRIPLE" \
|
||||
--prefix="$prefix" \
|
||||
--enable-shared \
|
||||
--disable-static \
|
||||
--disable-python \
|
||||
--with-pcm-plugins="$pcm_plugins" \
|
||||
--with-ctl-plugins="$ctl_plugins" \
|
||||
--disable-doc \
|
||||
--disable-oss \
|
||||
--disable-seq \
|
||||
--disable-rawmidi \
|
||||
--disable-hwdep \
|
||||
--disable-usb \
|
||||
--disable-firewire \
|
||||
--disable-instr \
|
||||
--disable-alisp
|
||||
make -j"$JOBS"
|
||||
make install
|
||||
)
|
||||
|
||||
mkdir -p "$prefix/lib/pkgconfig"
|
||||
cat > "$prefix/lib/pkgconfig/alsa.pc" <<EOF
|
||||
prefix=\${pcfiledir}/../..
|
||||
exec_prefix=\${prefix}
|
||||
libdir=\${exec_prefix}/lib
|
||||
includedir=\${prefix}/include
|
||||
|
||||
Name: alsa
|
||||
Description: ALSA sound library
|
||||
Version: 1.2.15
|
||||
Libs: -L\${libdir} -lasound
|
||||
Cflags: -I\${includedir}
|
||||
EOF
|
||||
|
||||
echo "Built ALSA for ${abi}: ${prefix}"
|
||||
}
|
||||
|
||||
for abi in $(normalize_abis); do
|
||||
build_one "$abi"
|
||||
done
|
||||
|
||||
cat <<EOF
|
||||
|
||||
Done.
|
||||
|
||||
Use this when building the Android APK:
|
||||
export ONE_KVM_ANDROID_ALSA_ROOT="${OUTPUT_DIR}"
|
||||
cd android && ./gradlew :app:assembleDebug
|
||||
EOF
|
||||
296
scripts/build-android-ffmpeg-mediacodec.sh
Normal file
296
scripts/build-android-ffmpeg-mediacodec.sh
Normal file
@@ -0,0 +1,296 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
||||
|
||||
SOURCE_DIR=""
|
||||
OUTPUT_DIR="${PROJECT_ROOT}/dist/android-ffmpeg-mediacodec"
|
||||
ANDROID_API="${ANDROID_API:-21}"
|
||||
NDK_ROOT="${ANDROID_NDK_HOME:-${ANDROID_NDK_ROOT:-}}"
|
||||
BUILD_ABIS="arm64-v8a armeabi-v7a"
|
||||
JOBS="${JOBS:-$(nproc 2>/dev/null || echo 4)}"
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage:
|
||||
scripts/build-android-ffmpeg-mediacodec.sh --source <ffmpeg-source-dir> [options]
|
||||
|
||||
Required:
|
||||
--source <dir> FFmpeg source directory. For the downloaded package,
|
||||
use the extracted ffmpeg-rockchip directory.
|
||||
|
||||
Options:
|
||||
--output <dir> Output root. Default: dist/android-ffmpeg-mediacodec
|
||||
--ndk <dir> Android NDK root. Defaults to ANDROID_NDK_HOME or ANDROID_NDK_ROOT.
|
||||
--api <level> Android API level. Default: 21.
|
||||
--abis <list> Space/comma separated ABI list. Default: arm64-v8a armeabi-v7a.
|
||||
-h, --help Show this help.
|
||||
|
||||
The output layout is compatible with ONE_KVM_ANDROID_FFMPEG_ROOT:
|
||||
<output>/arm64-v8a/include
|
||||
<output>/arm64-v8a/lib
|
||||
<output>/armeabi-v7a/include
|
||||
<output>/armeabi-v7a/lib
|
||||
|
||||
Example:
|
||||
scripts/build-android-ffmpeg-mediacodec.sh \
|
||||
--source .tmp/android-ffmpeg-check/src/ffmpeg-rockchip \
|
||||
--output /opt/one-kvm/android-ffmpeg
|
||||
|
||||
export ONE_KVM_ANDROID_FFMPEG_ROOT=/opt/one-kvm/android-ffmpeg
|
||||
cd android && ./gradlew :app:assembleDebug
|
||||
EOF
|
||||
}
|
||||
|
||||
fail() {
|
||||
echo "Error: $*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--source)
|
||||
SOURCE_DIR="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
--output)
|
||||
OUTPUT_DIR="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
--ndk)
|
||||
NDK_ROOT="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
--api)
|
||||
ANDROID_API="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
--abis)
|
||||
BUILD_ABIS="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
-h | --help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
fail "Unknown argument: $1"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
[[ -n "$SOURCE_DIR" ]] || fail "--source is required"
|
||||
[[ -d "$SOURCE_DIR" ]] || fail "FFmpeg source not found: $SOURCE_DIR"
|
||||
[[ -x "$SOURCE_DIR/configure" ]] || fail "FFmpeg configure script not found under: $SOURCE_DIR"
|
||||
[[ -n "$NDK_ROOT" ]] || fail "--ndk or ANDROID_NDK_HOME/ANDROID_NDK_ROOT is required"
|
||||
[[ -d "$NDK_ROOT/toolchains/llvm/prebuilt" ]] || fail "Invalid NDK root: $NDK_ROOT"
|
||||
|
||||
SOURCE_DIR="$(cd "$SOURCE_DIR" && pwd)"
|
||||
mkdir -p "$OUTPUT_DIR"
|
||||
OUTPUT_DIR="$(cd "$OUTPUT_DIR" && pwd)"
|
||||
|
||||
HOST_TAG="$(uname -s | tr '[:upper:]' '[:lower:]')-x86_64"
|
||||
TOOLCHAIN="${NDK_ROOT}/toolchains/llvm/prebuilt/${HOST_TAG}"
|
||||
[[ -d "$TOOLCHAIN/bin" ]] || fail "NDK LLVM toolchain not found: $TOOLCHAIN"
|
||||
|
||||
normalize_abis() {
|
||||
printf '%s\n' "$BUILD_ABIS" | tr ',' ' '
|
||||
}
|
||||
|
||||
patch_android_ffmpeg_mjpeg_mediacodec() {
|
||||
local avcodec_dir="${SOURCE_DIR}/libavcodec"
|
||||
local configure_file="${SOURCE_DIR}/configure"
|
||||
local mediacodecdec="${avcodec_dir}/mediacodecdec.c"
|
||||
local allcodecs="${avcodec_dir}/allcodecs.c"
|
||||
local makefile="${avcodec_dir}/Makefile"
|
||||
|
||||
[[ -f "$mediacodecdec" ]] || fail "FFmpeg mediacodecdec.c not found: $mediacodecdec"
|
||||
[[ -f "$allcodecs" ]] || fail "FFmpeg allcodecs.c not found: $allcodecs"
|
||||
[[ -f "$makefile" ]] || fail "FFmpeg libavcodec Makefile not found: $makefile"
|
||||
[[ -f "$configure_file" ]] || fail "FFmpeg configure not found: $configure_file"
|
||||
|
||||
python3 - "$mediacodecdec" "$allcodecs" "$configure_file" "$makefile" <<'PY'
|
||||
from pathlib import Path
|
||||
import sys
|
||||
|
||||
mediacodecdec, allcodecs, configure_file, makefile = map(Path, sys.argv[1:])
|
||||
|
||||
def replace_once(path: Path, old: str, new: str) -> None:
|
||||
text = path.read_text()
|
||||
if new in text:
|
||||
return
|
||||
if old not in text:
|
||||
raise SystemExit(f"patch anchor not found in {path}: {old!r}")
|
||||
path.write_text(text.replace(old, new, 1))
|
||||
|
||||
replace_once(
|
||||
mediacodecdec,
|
||||
"CONFIG_MPEG2_MEDIACODEC_DECODER || \\\n",
|
||||
"CONFIG_MJPEG_MEDIACODEC_DECODER || \\\n"
|
||||
" CONFIG_MPEG2_MEDIACODEC_DECODER || \\\n",
|
||||
)
|
||||
replace_once(
|
||||
mediacodecdec,
|
||||
"#if CONFIG_MPEG2_MEDIACODEC_DECODER\n"
|
||||
" case AV_CODEC_ID_MPEG2VIDEO:",
|
||||
"#if CONFIG_MJPEG_MEDIACODEC_DECODER\n"
|
||||
" case AV_CODEC_ID_MJPEG:\n"
|
||||
" codec_mime = \"video/mjpeg\";\n\n"
|
||||
" ret = common_set_extradata(avctx, format);\n"
|
||||
" if (ret < 0)\n"
|
||||
" goto done;\n"
|
||||
" break;\n"
|
||||
"#endif\n"
|
||||
"#if CONFIG_MPEG2_MEDIACODEC_DECODER\n"
|
||||
" case AV_CODEC_ID_MPEG2VIDEO:",
|
||||
)
|
||||
replace_once(
|
||||
mediacodecdec,
|
||||
"#if CONFIG_MPEG2_MEDIACODEC_DECODER\n"
|
||||
"DECLARE_MEDIACODEC_VDEC(mpeg2, \"MPEG-2\", AV_CODEC_ID_MPEG2VIDEO, NULL)",
|
||||
"#if CONFIG_MJPEG_MEDIACODEC_DECODER\n"
|
||||
"DECLARE_MEDIACODEC_VDEC(mjpeg, \"MJPEG\", AV_CODEC_ID_MJPEG, NULL)\n"
|
||||
"#endif\n\n"
|
||||
"#if CONFIG_MPEG2_MEDIACODEC_DECODER\n"
|
||||
"DECLARE_MEDIACODEC_VDEC(mpeg2, \"MPEG-2\", AV_CODEC_ID_MPEG2VIDEO, NULL)",
|
||||
)
|
||||
replace_once(
|
||||
allcodecs,
|
||||
"extern const FFCodec ff_mjpeg_cuvid_decoder;",
|
||||
"extern const FFCodec ff_mjpeg_cuvid_decoder;\n"
|
||||
"extern const FFCodec ff_mjpeg_mediacodec_decoder;",
|
||||
)
|
||||
replace_once(
|
||||
configure_file,
|
||||
'mjpeg_cuvid_decoder_deps="cuvid"',
|
||||
'mjpeg_cuvid_decoder_deps="cuvid"\n'
|
||||
'mjpeg_mediacodec_decoder_deps="mediacodec"',
|
||||
)
|
||||
replace_once(
|
||||
makefile,
|
||||
"OBJS-$(CONFIG_MJPEG_RKMPP_DECODER)",
|
||||
"OBJS-$(CONFIG_MJPEG_MEDIACODEC_DECODER) += mediacodecdec.o\n"
|
||||
"OBJS-$(CONFIG_MJPEG_RKMPP_DECODER)",
|
||||
)
|
||||
PY
|
||||
}
|
||||
|
||||
abi_arch() {
|
||||
case "$1" in
|
||||
arm64-v8a) echo "aarch64" ;;
|
||||
armeabi-v7a) echo "arm" ;;
|
||||
*) fail "Unsupported ABI: $1" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
abi_cpu() {
|
||||
case "$1" in
|
||||
arm64-v8a) echo "armv8-a" ;;
|
||||
armeabi-v7a) echo "armv7-a" ;;
|
||||
*) fail "Unsupported ABI: $1" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
abi_target() {
|
||||
case "$1" in
|
||||
arm64-v8a) echo "aarch64-linux-android" ;;
|
||||
armeabi-v7a) echo "armv7a-linux-androideabi" ;;
|
||||
*) fail "Unsupported ABI: $1" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
build_one() {
|
||||
local abi="$1"
|
||||
local arch cpu target prefix build_dir cc cxx ar ranlib strip extra_cflags extra_ldflags
|
||||
|
||||
arch="$(abi_arch "$abi")"
|
||||
cpu="$(abi_cpu "$abi")"
|
||||
target="$(abi_target "$abi")"
|
||||
prefix="${OUTPUT_DIR}/${abi}"
|
||||
build_dir="${PROJECT_ROOT}/.tmp/ffmpeg-android-build/${abi}"
|
||||
cc="${TOOLCHAIN}/bin/${target}${ANDROID_API}-clang"
|
||||
cxx="${TOOLCHAIN}/bin/${target}${ANDROID_API}-clang++"
|
||||
ar="${TOOLCHAIN}/bin/llvm-ar"
|
||||
ranlib="${TOOLCHAIN}/bin/llvm-ranlib"
|
||||
strip="${TOOLCHAIN}/bin/llvm-strip"
|
||||
extra_cflags="-fPIC"
|
||||
extra_ldflags=""
|
||||
|
||||
[[ -x "$cc" ]] || fail "Missing compiler: $cc"
|
||||
|
||||
if [[ "$abi" == "armeabi-v7a" ]]; then
|
||||
extra_cflags="${extra_cflags} -march=armv7-a -mfloat-abi=softfp -mfpu=neon"
|
||||
extra_ldflags="${extra_ldflags} -Wl,--fix-cortex-a8"
|
||||
fi
|
||||
|
||||
rm -rf "$build_dir"
|
||||
mkdir -p "$build_dir" "$prefix"
|
||||
|
||||
(
|
||||
cd "$build_dir"
|
||||
"${SOURCE_DIR}/configure" \
|
||||
--prefix="$prefix" \
|
||||
--target-os=android \
|
||||
--arch="$arch" \
|
||||
--cpu="$cpu" \
|
||||
--cc="$cc" \
|
||||
--cxx="$cxx" \
|
||||
--ar="$ar" \
|
||||
--ranlib="$ranlib" \
|
||||
--strip="$strip" \
|
||||
--cross-prefix="${TOOLCHAIN}/bin/llvm-" \
|
||||
--sysroot="${TOOLCHAIN}/sysroot" \
|
||||
--enable-cross-compile \
|
||||
--enable-static \
|
||||
--disable-shared \
|
||||
--disable-programs \
|
||||
--disable-doc \
|
||||
--disable-avdevice \
|
||||
--disable-avformat \
|
||||
--disable-avfilter \
|
||||
--disable-swscale \
|
||||
--disable-swresample \
|
||||
--disable-postproc \
|
||||
--disable-network \
|
||||
--disable-everything \
|
||||
--disable-hwaccels \
|
||||
--disable-cuda-llvm \
|
||||
--disable-v4l2-m2m \
|
||||
--disable-vulkan \
|
||||
--enable-pthreads \
|
||||
--enable-jni \
|
||||
--enable-mediacodec \
|
||||
--enable-decoder=mjpeg_mediacodec \
|
||||
--enable-decoder=mjpeg \
|
||||
--enable-encoder=h264_mediacodec \
|
||||
--enable-encoder=hevc_mediacodec \
|
||||
--enable-parser=mjpeg \
|
||||
--enable-bsf=h264_metadata \
|
||||
--enable-bsf=hevc_metadata \
|
||||
--enable-protocol=file \
|
||||
--extra-cflags="$extra_cflags" \
|
||||
--extra-ldflags="$extra_ldflags"
|
||||
|
||||
make -j"$JOBS"
|
||||
make install
|
||||
)
|
||||
|
||||
echo "Built FFmpeg MediaCodec for ${abi}: ${prefix}"
|
||||
}
|
||||
|
||||
patch_android_ffmpeg_mjpeg_mediacodec
|
||||
|
||||
for abi in $(normalize_abis); do
|
||||
build_one "$abi"
|
||||
done
|
||||
|
||||
cat <<EOF
|
||||
|
||||
Done.
|
||||
|
||||
Use this when building the Android APK:
|
||||
export ONE_KVM_ANDROID_FFMPEG_ROOT="${OUTPUT_DIR}"
|
||||
cd android && ./gradlew :app:assembleDebug
|
||||
EOF
|
||||
189
scripts/build-android-libyuv.sh
Normal file
189
scripts/build-android-libyuv.sh
Normal file
@@ -0,0 +1,189 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
||||
|
||||
SOURCE_DIR=""
|
||||
OUTPUT_DIR="${PROJECT_ROOT}/dist/android-libyuv"
|
||||
JPEG_ROOT="${ONE_KVM_ANDROID_TURBOJPEG_ROOT:-${PROJECT_ROOT}/dist/android-turbojpeg}"
|
||||
ANDROID_API="${ANDROID_API:-21}"
|
||||
NDK_ROOT="${ANDROID_NDK_HOME:-${ANDROID_NDK_ROOT:-}}"
|
||||
BUILD_ABIS="arm64-v8a armeabi-v7a"
|
||||
JOBS="${JOBS:-$(nproc 2>/dev/null || echo 4)}"
|
||||
LIBYUV_REPO="${LIBYUV_REPO:-https://github.com/lemenkov/libyuv.git}"
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage:
|
||||
scripts/build-android-libyuv.sh [options]
|
||||
|
||||
Options:
|
||||
--source <dir> Existing libyuv source checkout. If omitted, the script
|
||||
clones libyuv into .tmp/android-libyuv-src.
|
||||
--output <dir> Output root. Default: dist/android-libyuv
|
||||
--ndk <dir> Android NDK root. Defaults to ANDROID_NDK_HOME or ANDROID_NDK_ROOT.
|
||||
--api <level> Android API level. Default: 21.
|
||||
--abis <list> Space/comma separated ABI list. Default: arm64-v8a armeabi-v7a.
|
||||
--jpeg-root <dir> Android libjpeg root. Defaults to ONE_KVM_ANDROID_TURBOJPEG_ROOT
|
||||
or dist/android-turbojpeg when present. Enables libyuv HAVE_JPEG.
|
||||
-h, --help Show this help.
|
||||
|
||||
The output layout is compatible with ONE_KVM_ANDROID_LIBYUV_ROOT:
|
||||
<output>/arm64-v8a/include
|
||||
<output>/arm64-v8a/lib/libyuv.a
|
||||
<output>/armeabi-v7a/include
|
||||
<output>/armeabi-v7a/lib/libyuv.a
|
||||
|
||||
Example:
|
||||
scripts/build-android-libyuv.sh --output /opt/one-kvm/android-libyuv
|
||||
|
||||
export ONE_KVM_ANDROID_LIBYUV_ROOT=/opt/one-kvm/android-libyuv
|
||||
cd android && ./gradlew :app:assembleDebug
|
||||
EOF
|
||||
}
|
||||
|
||||
fail() {
|
||||
echo "Error: $*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--source)
|
||||
SOURCE_DIR="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
--output)
|
||||
OUTPUT_DIR="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
--ndk)
|
||||
NDK_ROOT="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
--api)
|
||||
ANDROID_API="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
--abis)
|
||||
BUILD_ABIS="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
--jpeg-root)
|
||||
JPEG_ROOT="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
-h | --help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
fail "Unknown argument: $1"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
[[ -n "$NDK_ROOT" ]] || fail "--ndk or ANDROID_NDK_HOME/ANDROID_NDK_ROOT is required"
|
||||
[[ -d "$NDK_ROOT/toolchains/llvm/prebuilt" ]] || fail "Invalid NDK root: $NDK_ROOT"
|
||||
|
||||
if [[ -z "$SOURCE_DIR" ]]; then
|
||||
SOURCE_DIR="${PROJECT_ROOT}/.tmp/android-libyuv-src"
|
||||
if [[ ! -d "$SOURCE_DIR/.git" ]]; then
|
||||
rm -rf "$SOURCE_DIR"
|
||||
git clone --depth 1 "$LIBYUV_REPO" "$SOURCE_DIR"
|
||||
fi
|
||||
fi
|
||||
|
||||
[[ -d "$SOURCE_DIR" ]] || fail "libyuv source not found: $SOURCE_DIR"
|
||||
[[ -f "$SOURCE_DIR/CMakeLists.txt" ]] || fail "libyuv CMakeLists.txt not found under: $SOURCE_DIR"
|
||||
|
||||
SOURCE_DIR="$(cd "$SOURCE_DIR" && pwd)"
|
||||
mkdir -p "$OUTPUT_DIR"
|
||||
OUTPUT_DIR="$(cd "$OUTPUT_DIR" && pwd)"
|
||||
|
||||
HOST_TAG="$(uname -s | tr '[:upper:]' '[:lower:]')-x86_64"
|
||||
TOOLCHAIN="${NDK_ROOT}/toolchains/llvm/prebuilt/${HOST_TAG}"
|
||||
ANDROID_TOOLCHAIN_FILE="${NDK_ROOT}/build/cmake/android.toolchain.cmake"
|
||||
[[ -d "$TOOLCHAIN/bin" ]] || fail "NDK LLVM toolchain not found: $TOOLCHAIN"
|
||||
[[ -f "$ANDROID_TOOLCHAIN_FILE" ]] || fail "NDK CMake toolchain not found: $ANDROID_TOOLCHAIN_FILE"
|
||||
command -v cmake >/dev/null 2>&1 || fail "cmake is required"
|
||||
|
||||
normalize_abis() {
|
||||
printf '%s\n' "$BUILD_ABIS" | tr ',' ' '
|
||||
}
|
||||
|
||||
build_one() {
|
||||
local abi="$1"
|
||||
local prefix build_dir jpeg_include jpeg_library
|
||||
local -a jpeg_args
|
||||
|
||||
case "$abi" in
|
||||
arm64-v8a | armeabi-v7a | x86 | x86_64) ;;
|
||||
*) fail "Unsupported ABI: $abi" ;;
|
||||
esac
|
||||
|
||||
prefix="${OUTPUT_DIR}/${abi}"
|
||||
build_dir="${PROJECT_ROOT}/.tmp/libyuv-android-build/${abi}"
|
||||
|
||||
rm -rf "$build_dir"
|
||||
mkdir -p "$build_dir" "$prefix"
|
||||
|
||||
jpeg_include="$JPEG_ROOT/$abi/include"
|
||||
jpeg_library="$JPEG_ROOT/$abi/lib/libjpeg.a"
|
||||
jpeg_args=()
|
||||
if [[ -f "$jpeg_library" && -f "$jpeg_include/jpeglib.h" ]]; then
|
||||
jpeg_args=(
|
||||
-DJPEG_FOUND=TRUE
|
||||
-DJPEG_INCLUDE_DIR="$jpeg_include"
|
||||
-DJPEG_LIBRARY="$jpeg_library"
|
||||
-DCMAKE_C_FLAGS="-DHAVE_JPEG"
|
||||
-DCMAKE_CXX_FLAGS="-DHAVE_JPEG"
|
||||
)
|
||||
else
|
||||
echo "Warning: Android libjpeg not found for ${abi}; libyuv MJPEG APIs will be disabled." >&2
|
||||
echo " Checked: $jpeg_library and $jpeg_include/jpeglib.h" >&2
|
||||
fi
|
||||
|
||||
cmake -S "$SOURCE_DIR" -B "$build_dir" \
|
||||
-DCMAKE_TOOLCHAIN_FILE="$ANDROID_TOOLCHAIN_FILE" \
|
||||
-DANDROID_ABI="$abi" \
|
||||
-DANDROID_PLATFORM="android-${ANDROID_API}" \
|
||||
-DANDROID_STL=c++_shared \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_INSTALL_PREFIX="$prefix" \
|
||||
-DCMAKE_POSITION_INDEPENDENT_CODE=ON \
|
||||
-DBUILD_SHARED_LIBS=OFF \
|
||||
-DUNIT_TEST=OFF \
|
||||
-DTEST=OFF \
|
||||
"${jpeg_args[@]}"
|
||||
|
||||
cmake --build "$build_dir" --target yuv --parallel "$JOBS"
|
||||
|
||||
mkdir -p "$prefix/lib" "$prefix/include"
|
||||
if [[ -f "$build_dir/libyuv.a" ]]; then
|
||||
cp "$build_dir/libyuv.a" "$prefix/lib/libyuv.a"
|
||||
elif [[ -f "$build_dir/lib/libyuv.a" ]]; then
|
||||
cp "$build_dir/lib/libyuv.a" "$prefix/lib/libyuv.a"
|
||||
else
|
||||
fail "Built libyuv.a was not found under: $build_dir"
|
||||
fi
|
||||
cp -R "$SOURCE_DIR/include/." "$prefix/include/"
|
||||
|
||||
echo "Built libyuv for ${abi}: ${prefix}"
|
||||
}
|
||||
|
||||
for abi in $(normalize_abis); do
|
||||
build_one "$abi"
|
||||
done
|
||||
|
||||
cat <<EOF
|
||||
|
||||
Done.
|
||||
|
||||
Use this when building the Android APK:
|
||||
export ONE_KVM_ANDROID_LIBYUV_ROOT="${OUTPUT_DIR}"
|
||||
export ONE_KVM_ANDROID_TURBOJPEG_ROOT="${JPEG_ROOT}"
|
||||
cd android && ./gradlew :app:assembleDebug
|
||||
EOF
|
||||
186
scripts/build-android-opus.sh
Normal file
186
scripts/build-android-opus.sh
Normal file
@@ -0,0 +1,186 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
||||
|
||||
SOURCE_DIR=""
|
||||
OUTPUT_DIR="${PROJECT_ROOT}/dist/android-opus"
|
||||
ANDROID_API="${ANDROID_API:-21}"
|
||||
NDK_ROOT="${ANDROID_NDK_HOME:-${ANDROID_NDK_ROOT:-}}"
|
||||
BUILD_ABIS="arm64-v8a armeabi-v7a"
|
||||
JOBS="${JOBS:-$(nproc 2>/dev/null || echo 4)}"
|
||||
OPUS_VERSION="${OPUS_VERSION:-1.5.2}"
|
||||
OPUS_TARBALL_URL="${OPUS_TARBALL_URL:-https://downloads.xiph.org/releases/opus/opus-${OPUS_VERSION}.tar.gz}"
|
||||
OPUS_TARBALL_SHA256="${OPUS_TARBALL_SHA256:-65c1d2f78b9f2fb20082c38cbe47c951ad5839345876e46941612ee87f9a7ce1}"
|
||||
LOCAL_OPUS_TARBALL="${LOCAL_OPUS_TARBALL:-${PROJECT_ROOT}/opus-${OPUS_VERSION}.tar.gz}"
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage:
|
||||
scripts/build-android-opus.sh [options]
|
||||
|
||||
Options:
|
||||
--source <dir> Existing opus source checkout. If omitted, the script
|
||||
downloads and extracts the official source tarball
|
||||
into .tmp/android-opus-src.
|
||||
--output <dir> Output root. Default: dist/android-opus
|
||||
--ndk <dir> Android NDK root. Defaults to ANDROID_NDK_HOME or ANDROID_NDK_ROOT.
|
||||
--api <level> Android API level. Default: 21.
|
||||
--abis <list> Space/comma separated ABI list. Default: arm64-v8a armeabi-v7a.
|
||||
-h, --help Show this help.
|
||||
|
||||
The output layout is compatible with ONE_KVM_ANDROID_OPUS_ROOT:
|
||||
<output>/arm64-v8a/include/opus/opus.h
|
||||
<output>/arm64-v8a/lib/libopus.so
|
||||
<output>/armeabi-v7a/include/opus/opus.h
|
||||
<output>/armeabi-v7a/lib/libopus.so
|
||||
EOF
|
||||
}
|
||||
|
||||
fail() {
|
||||
echo "Error: $*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--source)
|
||||
SOURCE_DIR="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
--output)
|
||||
OUTPUT_DIR="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
--ndk)
|
||||
NDK_ROOT="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
--api)
|
||||
ANDROID_API="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
--abis)
|
||||
BUILD_ABIS="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
-h | --help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
fail "Unknown argument: $1"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
[[ -n "$NDK_ROOT" ]] || fail "--ndk or ANDROID_NDK_HOME/ANDROID_NDK_ROOT is required"
|
||||
[[ -d "$NDK_ROOT/toolchains/llvm/prebuilt" ]] || fail "Invalid NDK root: $NDK_ROOT"
|
||||
|
||||
if [[ -z "$SOURCE_DIR" ]]; then
|
||||
SOURCE_DIR="${PROJECT_ROOT}/.tmp/android-opus-src"
|
||||
if [[ ! -f "$SOURCE_DIR/configure" ]]; then
|
||||
rm -rf "$SOURCE_DIR"
|
||||
mkdir -p "$SOURCE_DIR"
|
||||
tarball="${PROJECT_ROOT}/.tmp/opus-${OPUS_VERSION}.tar.gz"
|
||||
if [[ -f "$LOCAL_OPUS_TARBALL" ]]; then
|
||||
cp "$LOCAL_OPUS_TARBALL" "$tarball"
|
||||
else
|
||||
command -v curl >/dev/null 2>&1 || fail "curl is required to download opus source"
|
||||
curl -fsSL "$OPUS_TARBALL_URL" -o "$tarball"
|
||||
fi
|
||||
echo "${OPUS_TARBALL_SHA256} ${tarball}" | sha256sum -c -
|
||||
tar -xzf "$tarball" -C "$SOURCE_DIR" --strip-components=1
|
||||
fi
|
||||
fi
|
||||
|
||||
[[ -d "$SOURCE_DIR" ]] || fail "opus source not found: $SOURCE_DIR"
|
||||
[[ -x "$SOURCE_DIR/configure" || -f "$SOURCE_DIR/configure.ac" ]] || fail "opus source layout not recognized under: $SOURCE_DIR"
|
||||
|
||||
SOURCE_DIR="$(cd "$SOURCE_DIR" && pwd)"
|
||||
mkdir -p "$OUTPUT_DIR"
|
||||
OUTPUT_DIR="$(cd "$OUTPUT_DIR" && pwd)"
|
||||
|
||||
HOST_TAG="$(uname -s | tr '[:upper:]' '[:lower:]')-x86_64"
|
||||
TOOLCHAIN="${NDK_ROOT}/toolchains/llvm/prebuilt/${HOST_TAG}"
|
||||
ANDROID_TOOLCHAIN_FILE="${NDK_ROOT}/build/cmake/android.toolchain.cmake"
|
||||
[[ -d "$TOOLCHAIN/bin" ]] || fail "NDK LLVM toolchain not found: $TOOLCHAIN"
|
||||
[[ -f "$ANDROID_TOOLCHAIN_FILE" ]] || fail "NDK CMake toolchain not found: $ANDROID_TOOLCHAIN_FILE"
|
||||
command -v cmake >/dev/null 2>&1 || fail "cmake is required"
|
||||
|
||||
normalize_abis() {
|
||||
printf '%s\n' "$BUILD_ABIS" | tr ',' ' '
|
||||
}
|
||||
|
||||
build_one() {
|
||||
local abi="$1"
|
||||
local prefix build_dir
|
||||
|
||||
case "$abi" in
|
||||
arm64-v8a | armeabi-v7a) ;;
|
||||
*) fail "Unsupported ABI: $abi" ;;
|
||||
esac
|
||||
|
||||
prefix="${OUTPUT_DIR}/${abi}"
|
||||
build_dir="${PROJECT_ROOT}/.tmp/opus-android-build/${abi}"
|
||||
|
||||
rm -rf "$build_dir"
|
||||
mkdir -p "$build_dir" "$prefix"
|
||||
|
||||
(
|
||||
cd "$build_dir"
|
||||
case "$abi" in
|
||||
arm64-v8a)
|
||||
export CC="${TOOLCHAIN}/bin/aarch64-linux-android${ANDROID_API}-clang"
|
||||
export CXX="${TOOLCHAIN}/bin/aarch64-linux-android${ANDROID_API}-clang++"
|
||||
export HOST_TRIPLE="aarch64-linux-android"
|
||||
;;
|
||||
armeabi-v7a)
|
||||
export CC="${TOOLCHAIN}/bin/armv7a-linux-androideabi${ANDROID_API}-clang"
|
||||
export CXX="${TOOLCHAIN}/bin/armv7a-linux-androideabi${ANDROID_API}-clang++"
|
||||
export HOST_TRIPLE="arm-linux-androideabi"
|
||||
;;
|
||||
esac
|
||||
export AR="${TOOLCHAIN}/bin/llvm-ar"
|
||||
export RANLIB="${TOOLCHAIN}/bin/llvm-ranlib"
|
||||
export STRIP="${TOOLCHAIN}/bin/llvm-strip"
|
||||
export CFLAGS="-fPIC"
|
||||
export CXXFLAGS="-fPIC"
|
||||
export LDFLAGS=""
|
||||
"$SOURCE_DIR/configure" \
|
||||
--prefix="$prefix" \
|
||||
--host="$HOST_TRIPLE" \
|
||||
--disable-static \
|
||||
--enable-shared \
|
||||
--disable-doc \
|
||||
--disable-extra-programs \
|
||||
--with-pic
|
||||
make -j"$JOBS"
|
||||
make install
|
||||
)
|
||||
|
||||
mkdir -p "$prefix/lib" "$prefix/include"
|
||||
if [[ -f "$prefix/include/opus/opus.h" ]]; then
|
||||
:
|
||||
elif [[ -f "$SOURCE_DIR/include/opus/opus.h" ]]; then
|
||||
mkdir -p "$prefix/include/opus"
|
||||
cp "$SOURCE_DIR/include/opus/opus.h" "$prefix/include/opus/opus.h"
|
||||
fi
|
||||
|
||||
echo "Built Opus for ${abi}: ${prefix}"
|
||||
}
|
||||
|
||||
for abi in $(normalize_abis); do
|
||||
build_one "$abi"
|
||||
done
|
||||
|
||||
cat <<EOF
|
||||
|
||||
Done.
|
||||
|
||||
Use this when building the Android APK:
|
||||
export ONE_KVM_ANDROID_OPUS_ROOT="${OUTPUT_DIR}"
|
||||
cd android && ./gradlew :app:assembleDebug
|
||||
EOF
|
||||
178
scripts/build-android-turbojpeg.sh
Normal file
178
scripts/build-android-turbojpeg.sh
Normal file
@@ -0,0 +1,178 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
||||
|
||||
SOURCE_DIR=""
|
||||
OUTPUT_DIR="${PROJECT_ROOT}/dist/android-turbojpeg"
|
||||
ANDROID_API="${ANDROID_API:-21}"
|
||||
NDK_ROOT="${ANDROID_NDK_HOME:-${ANDROID_NDK_ROOT:-}}"
|
||||
BUILD_ABIS="arm64-v8a armeabi-v7a"
|
||||
JOBS="${JOBS:-$(nproc 2>/dev/null || echo 4)}"
|
||||
LIBJPEG_TURBO_REPO="${LIBJPEG_TURBO_REPO:-https://github.com/libjpeg-turbo/libjpeg-turbo.git}"
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage:
|
||||
scripts/build-android-turbojpeg.sh [options]
|
||||
|
||||
Options:
|
||||
--source <dir> Existing libjpeg-turbo source checkout. If omitted,
|
||||
the script clones it into .tmp/android-turbojpeg-src.
|
||||
--output <dir> Output root. Default: dist/android-turbojpeg
|
||||
--ndk <dir> Android NDK root. Defaults to ANDROID_NDK_HOME or ANDROID_NDK_ROOT.
|
||||
--api <level> Android API level. Default: 21.
|
||||
--abis <list> Space/comma separated ABI list. Default: arm64-v8a armeabi-v7a.
|
||||
-h, --help Show this help.
|
||||
|
||||
The output layout is compatible with ONE_KVM_ANDROID_TURBOJPEG_ROOT:
|
||||
<output>/arm64-v8a/include/turbojpeg.h
|
||||
<output>/arm64-v8a/lib/libturbojpeg.a
|
||||
<output>/arm64-v8a/include/jpeglib.h
|
||||
<output>/arm64-v8a/lib/libjpeg.a
|
||||
<output>/armeabi-v7a/include/turbojpeg.h
|
||||
<output>/armeabi-v7a/lib/libturbojpeg.a
|
||||
<output>/armeabi-v7a/include/jpeglib.h
|
||||
<output>/armeabi-v7a/lib/libjpeg.a
|
||||
EOF
|
||||
}
|
||||
|
||||
fail() {
|
||||
echo "Error: $*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--source)
|
||||
SOURCE_DIR="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
--output)
|
||||
OUTPUT_DIR="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
--ndk)
|
||||
NDK_ROOT="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
--api)
|
||||
ANDROID_API="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
--abis)
|
||||
BUILD_ABIS="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
-h | --help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
fail "Unknown argument: $1"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
[[ -n "$NDK_ROOT" ]] || fail "--ndk or ANDROID_NDK_HOME/ANDROID_NDK_ROOT is required"
|
||||
[[ -d "$NDK_ROOT/toolchains/llvm/prebuilt" ]] || fail "Invalid NDK root: $NDK_ROOT"
|
||||
|
||||
if [[ -z "$SOURCE_DIR" ]]; then
|
||||
SOURCE_DIR="${PROJECT_ROOT}/.tmp/android-turbojpeg-src"
|
||||
if [[ ! -d "$SOURCE_DIR/.git" ]]; then
|
||||
rm -rf "$SOURCE_DIR"
|
||||
git clone --depth 1 "$LIBJPEG_TURBO_REPO" "$SOURCE_DIR"
|
||||
fi
|
||||
fi
|
||||
|
||||
[[ -d "$SOURCE_DIR" ]] || fail "libjpeg-turbo source not found: $SOURCE_DIR"
|
||||
[[ -f "$SOURCE_DIR/CMakeLists.txt" ]] || fail "libjpeg-turbo CMakeLists.txt not found under: $SOURCE_DIR"
|
||||
|
||||
SOURCE_DIR="$(cd "$SOURCE_DIR" && pwd)"
|
||||
mkdir -p "$OUTPUT_DIR"
|
||||
OUTPUT_DIR="$(cd "$OUTPUT_DIR" && pwd)"
|
||||
|
||||
HOST_TAG="$(uname -s | tr '[:upper:]' '[:lower:]')-x86_64"
|
||||
TOOLCHAIN="${NDK_ROOT}/toolchains/llvm/prebuilt/${HOST_TAG}"
|
||||
ANDROID_TOOLCHAIN_FILE="${NDK_ROOT}/build/cmake/android.toolchain.cmake"
|
||||
[[ -d "$TOOLCHAIN/bin" ]] || fail "NDK LLVM toolchain not found: $TOOLCHAIN"
|
||||
[[ -f "$ANDROID_TOOLCHAIN_FILE" ]] || fail "NDK CMake toolchain not found: $ANDROID_TOOLCHAIN_FILE"
|
||||
command -v cmake >/dev/null 2>&1 || fail "cmake is required"
|
||||
|
||||
normalize_abis() {
|
||||
printf '%s\n' "$BUILD_ABIS" | tr ',' ' '
|
||||
}
|
||||
|
||||
build_one() {
|
||||
local abi="$1"
|
||||
local prefix build_dir lib_path
|
||||
|
||||
case "$abi" in
|
||||
arm64-v8a | armeabi-v7a | x86 | x86_64) ;;
|
||||
*) fail "Unsupported ABI: $abi" ;;
|
||||
esac
|
||||
|
||||
prefix="${OUTPUT_DIR}/${abi}"
|
||||
build_dir="${PROJECT_ROOT}/.tmp/turbojpeg-android-build/${abi}"
|
||||
|
||||
rm -rf "$build_dir"
|
||||
mkdir -p "$build_dir" "$prefix"
|
||||
|
||||
cmake -S "$SOURCE_DIR" -B "$build_dir" \
|
||||
-DCMAKE_TOOLCHAIN_FILE="$ANDROID_TOOLCHAIN_FILE" \
|
||||
-DANDROID_ABI="$abi" \
|
||||
-DANDROID_PLATFORM="android-${ANDROID_API}" \
|
||||
-DANDROID_STL=c++_shared \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_INSTALL_PREFIX="$prefix" \
|
||||
-DCMAKE_POSITION_INDEPENDENT_CODE=ON \
|
||||
-DCMAKE_C_FLAGS="-DANDROID -Dstderr=__sF+2" \
|
||||
-DCMAKE_CXX_FLAGS="-DANDROID -Dstderr=__sF+2" \
|
||||
-DENABLE_SHARED=OFF \
|
||||
-DENABLE_STATIC=ON \
|
||||
-DWITH_TURBOJPEG=ON \
|
||||
-DWITH_JAVA=OFF \
|
||||
-DWITH_12BIT=OFF \
|
||||
-DWITH_ARITH_DEC=ON \
|
||||
-DWITH_ARITH_ENC=ON
|
||||
|
||||
cmake --build "$build_dir" --target turbojpeg-static jpeg-static --parallel "$JOBS"
|
||||
|
||||
mkdir -p "$prefix/lib" "$prefix/include"
|
||||
lib_path="$build_dir/libturbojpeg.a"
|
||||
if [[ ! -f "$lib_path" ]]; then
|
||||
lib_path="$build_dir/lib/libturbojpeg.a"
|
||||
fi
|
||||
[[ -f "$lib_path" ]] || fail "Built libturbojpeg.a was not found under: $build_dir"
|
||||
|
||||
cp "$lib_path" "$prefix/lib/libturbojpeg.a"
|
||||
lib_path="$build_dir/libjpeg.a"
|
||||
if [[ ! -f "$lib_path" ]]; then
|
||||
lib_path="$build_dir/lib/libjpeg.a"
|
||||
fi
|
||||
[[ -f "$lib_path" ]] || fail "Built libjpeg.a was not found under: $build_dir"
|
||||
|
||||
cp "$lib_path" "$prefix/lib/libjpeg.a"
|
||||
cp "$SOURCE_DIR/src/turbojpeg.h" "$prefix/include/turbojpeg.h"
|
||||
cp "$SOURCE_DIR/src/jerror.h" "$prefix/include/jerror.h"
|
||||
cp "$SOURCE_DIR/src/jmorecfg.h" "$prefix/include/jmorecfg.h"
|
||||
cp "$SOURCE_DIR/src/jpeglib.h" "$prefix/include/jpeglib.h"
|
||||
cp "$build_dir/jconfig.h" "$prefix/include/jconfig.h"
|
||||
|
||||
echo "Built TurboJPEG for ${abi}: ${prefix}"
|
||||
}
|
||||
|
||||
for abi in $(normalize_abis); do
|
||||
build_one "$abi"
|
||||
done
|
||||
|
||||
cat <<EOF
|
||||
|
||||
Done.
|
||||
|
||||
Use this when building the Android APK:
|
||||
export ONE_KVM_ANDROID_TURBOJPEG_ROOT="${OUTPUT_DIR}"
|
||||
cd android && ./gradlew :app:assembleDebug
|
||||
EOF
|
||||
Reference in New Issue
Block a user