Initial RK1 media-center image project

This commit is contained in:
2026-08-17 18:42:29 +00:00
commit 5fe41e79e9
81 changed files with 5725 additions and 0 deletions
+226
View File
@@ -0,0 +1,226 @@
#!/usr/bin/env bash
set -Eeuo pipefail
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
# shellcheck source=lib.sh
. "${SCRIPT_DIR}/lib.sh"
LOCK_FILE="${RKMEDIA_ROOT}/sources.lock.json"
WORK_DIR="${RKMEDIA_ROOT}/out/work"
SOURCE_DIR="${RKMEDIA_ROOT}/out/sources"
OUTPUT_DIR="${RKMEDIA_ROOT}/out"
JOBS="$(nproc)"
FETCH=1
PACKAGE_VERSION="$(tr -d '[:space:]' < "${RKMEDIA_ROOT}/VERSION")"
RUNTIME_PREFIX=/opt/rkmedia
usage() {
cat <<'EOF'
Usage: build-media.sh [options]
--source-dir DIR Locked source checkouts (default: out/sources)
--work-dir DIR Build work directory (default: out/work)
--output-dir DIR Package output directory (default: out)
--jobs N Parallel jobs (default: nproc)
--no-fetch Require sources to exist; never access the network
--version VERSION Debian package version (default: VERSION file)
EOF
}
while (($#)); do
case "$1" in
--source-dir) [[ $# -ge 2 ]] || die "--source-dir requires a directory"; SOURCE_DIR="$2"; shift 2 ;;
--work-dir) [[ $# -ge 2 ]] || die "--work-dir requires a directory"; WORK_DIR="$2"; shift 2 ;;
--output-dir) [[ $# -ge 2 ]] || die "--output-dir requires a directory"; OUTPUT_DIR="$2"; shift 2 ;;
--jobs) [[ $# -ge 2 ]] || die "--jobs requires a number"; JOBS="$2"; shift 2 ;;
--no-fetch) FETCH=0; shift ;;
--version) [[ $# -ge 2 ]] || die "--version requires a value"; PACKAGE_VERSION="$2"; shift 2 ;;
-h|--help) usage; exit 0 ;;
*) die "unknown argument: $1" ;;
esac
done
[[ "${JOBS}" =~ ^[1-9][0-9]*$ ]] || die "--jobs must be a positive integer"
[[ "${PACKAGE_VERSION}" =~ ^[0-9A-Za-z.+:~-]+$ ]] || die "invalid Debian package version: ${PACKAGE_VERSION}"
require_arm64_trixie
for command_name in cmake git jq meson ninja pkg-config make patch readelf strip; do
need_command "${command_name}"
done
SOURCE_DIR="$(absolute_path "${SOURCE_DIR}")"
WORK_DIR="$(absolute_path "${WORK_DIR}")"
OUTPUT_DIR="$(absolute_path "${OUTPUT_DIR}")"
mkdir -p -- "${SOURCE_DIR}" "${WORK_DIR}" "${OUTPUT_DIR}"
if ((FETCH)); then
"${SCRIPT_DIR}/fetch-sources.sh" --lock "${LOCK_FILE}" --dest "${SOURCE_DIR}"
fi
while IFS=$'\t' read -r name commit; do
dir="${SOURCE_DIR}/${name}"
[[ -d "${dir}/.git" ]] || die "missing locked source: ${dir}"
[[ "$(git -C "${dir}" rev-parse HEAD)" == "${commit}" ]] || die "source commit mismatch: ${name}"
done < <(jq -r '.sources[] | select(.build == true) | [.name, .commit] | @tsv' "${LOCK_FILE}")
BUILD_ROOT="${WORK_DIR}/build"
BUILD_PREFIX="${WORK_DIR}/prefix"
STAGE_DIR="${WORK_DIR}/stage"
reset_child_dir "${WORK_DIR}" "${BUILD_ROOT}"
reset_child_dir "${WORK_DIR}" "${BUILD_PREFIX}"
reset_child_dir "${WORK_DIR}" "${STAGE_DIR}"
export SOURCE_DATE_EPOCH
SOURCE_DATE_EPOCH="$(jq -er '.source_date_epoch' "${LOCK_FILE}")"
export CFLAGS="${CFLAGS:--O2 -pipe -ffile-prefix-map=${WORK_DIR}=. -fdebug-prefix-map=${WORK_DIR}=.}"
export CXXFLAGS="${CXXFLAGS:--O2 -pipe -ffile-prefix-map=${WORK_DIR}=. -fdebug-prefix-map=${WORK_DIR}=.}"
export LDFLAGS="${LDFLAGS:-}"
log "building MPP"
cmake -S "${SOURCE_DIR}/mpp" -B "${BUILD_ROOT}/mpp" -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX="${BUILD_PREFIX}" \
-DCMAKE_INSTALL_LIBDIR=lib \
-DBUILD_SHARED_LIBS=ON \
-DBUILD_TEST=OFF
cmake --build "${BUILD_ROOT}/mpp" --parallel "${JOBS}"
cmake --install "${BUILD_ROOT}/mpp"
log "building RGA"
meson setup "${BUILD_ROOT}/rga" "${SOURCE_DIR}/rga" \
--prefix="${BUILD_PREFIX}" \
--libdir=lib \
--buildtype=release \
--default-library=shared \
-Dcpp_args=-fpermissive \
-Dlibdrm=false \
-Dlibrga_demo=false
meson compile -C "${BUILD_ROOT}/rga" -j "${JOBS}"
meson install -C "${BUILD_ROOT}/rga"
log "building dav1d"
meson setup "${BUILD_ROOT}/dav1d" "${SOURCE_DIR}/dav1d" \
--prefix="${BUILD_PREFIX}" \
--libdir=lib \
--buildtype=release \
--default-library=shared \
-Denable_tools=false \
-Denable_tests=false \
-Denable_examples=false \
-Denable_docs=false
meson compile -C "${BUILD_ROOT}/dav1d" -j "${JOBS}"
meson install -C "${BUILD_ROOT}/dav1d"
export PKG_CONFIG_PATH="${BUILD_PREFIX}/lib/pkgconfig${PKG_CONFIG_PATH:+:${PKG_CONFIG_PATH}}"
export LD_LIBRARY_PATH="${BUILD_PREFIX}/lib${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}"
log "building FFmpeg-Rockchip"
mkdir -p -- "${BUILD_ROOT}/ffmpeg"
pushd "${BUILD_ROOT}/ffmpeg" >/dev/null
"${SOURCE_DIR}/ffmpeg-rockchip/configure" \
--prefix="${BUILD_PREFIX}" \
--libdir="${BUILD_PREFIX}/lib" \
--enable-shared \
--disable-static \
--disable-debug \
--disable-doc \
--enable-pic \
--enable-gpl \
--enable-version3 \
--enable-libdrm \
--enable-rkmpp \
--enable-rkrga \
--enable-libdav1d \
--extra-cflags="-I${BUILD_PREFIX}/include" \
--extra-ldflags="-L${BUILD_PREFIX}/lib -Wl,-rpath,${RUNTIME_PREFIX}/lib"
make -j "${JOBS}"
make install
popd >/dev/null
FFMPEG_BUILD="${BUILD_PREFIX}/bin/ffmpeg"
for decoder in h264_rkmpp hevc_rkmpp vp9_rkmpp av1_rkmpp mjpeg_rkmpp; do
"${FFMPEG_BUILD}" -hide_banner -decoders 2>/dev/null | awk '{print $2}' | grep -Fxq "${decoder}" \
|| die "FFmpeg is missing decoder ${decoder}"
done
for encoder in h264_rkmpp hevc_rkmpp mjpeg_rkmpp; do
"${FFMPEG_BUILD}" -hide_banner -encoders 2>/dev/null | awk '{print $2}' | grep -Fxq "${encoder}" \
|| die "FFmpeg is missing encoder ${encoder}"
done
for filter in scale_rkrga vpp_rkrga overlay_rkrga; do
"${FFMPEG_BUILD}" -hide_banner -filters 2>/dev/null | awk '{print $2}' | grep -Fxq "${filter}" \
|| die "FFmpeg is missing filter ${filter}"
done
log "building libdisplay-info"
meson setup "${BUILD_ROOT}/libdisplay-info" "${SOURCE_DIR}/libdisplay-info" \
--prefix="${BUILD_PREFIX}" \
--libdir=lib \
--buildtype=release \
--default-library=shared
meson compile -C "${BUILD_ROOT}/libdisplay-info" -j "${JOBS}"
meson install -C "${BUILD_ROOT}/libdisplay-info"
log "building Kodi for GBM/GLES with external FFmpeg-Rockchip"
cmake -S "${SOURCE_DIR}/kodi" -B "${BUILD_ROOT}/kodi" -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX="${RUNTIME_PREFIX}" \
-DCMAKE_INSTALL_RPATH="${RUNTIME_PREFIX}/lib" \
-DCMAKE_BUILD_RPATH="${BUILD_PREFIX}/lib" \
-DCMAKE_PREFIX_PATH="${BUILD_PREFIX}" \
-DCORE_PLATFORM_NAME=gbm \
-DAPP_RENDER_SYSTEM=gles \
-DENABLE_INTERNAL_FFMPEG=OFF \
-DFFMPEG_PATH="${BUILD_PREFIX}" \
-DENABLE_INTERNAL_FMT=ON \
-DENABLE_INTERNAL_FLATBUFFERS=ON
cmake --build "${BUILD_ROOT}/kodi" --parallel "${JOBS}"
mkdir -p -- "${STAGE_DIR}${RUNTIME_PREFIX}"
cp -a -- "${BUILD_PREFIX}/." "${STAGE_DIR}${RUNTIME_PREFIX}/"
DESTDIR="${STAGE_DIR}" cmake --install "${BUILD_ROOT}/kodi"
log "adding runtime integration and source provenance"
cp -a -- "${RKMEDIA_ROOT}/packaging/rootfs/." "${STAGE_DIR}/"
mkdir -p -- "${STAGE_DIR}/usr/bin" "${STAGE_DIR}/usr/share/doc/rk1-media-stack/licenses"
ln -sfn /opt/rkmedia/bin/ffmpeg-rk "${STAGE_DIR}/usr/bin/ffmpeg-rk"
ln -sfn /opt/rkmedia/bin/ffprobe-rk "${STAGE_DIR}/usr/bin/ffprobe-rk"
ln -sfn /opt/rkmedia/bin/kodi-rk "${STAGE_DIR}/usr/bin/kodi-rk"
install -m 0644 "${LOCK_FILE}" "${STAGE_DIR}/usr/share/doc/rk1-media-stack/sources.lock.json"
while IFS=$'\t' read -r name license_path; do
source_license="${SOURCE_DIR}/${name}/${license_path}"
destination="${STAGE_DIR}/usr/share/doc/rk1-media-stack/licenses/${name}"
[[ -e "${source_license}" ]] || die "locked license path is missing: ${name}/${license_path}"
mkdir -p -- "${destination}"
cp -a -- "${source_license}" "${destination}/"
done < <(jq -r '.sources[] | select(.build == true) as $source | $source.license_files[] | [$source.name, .] | @tsv' "${LOCK_FILE}")
rm -rf -- \
"${STAGE_DIR}${RUNTIME_PREFIX}/include" \
"${STAGE_DIR}${RUNTIME_PREFIX}/lib/pkgconfig" \
"${STAGE_DIR}${RUNTIME_PREFIX}/share/pkgconfig"
find "${STAGE_DIR}${RUNTIME_PREFIX}" -type f \( -name '*.a' -o -name '*.la' \) -delete
while IFS= read -r -d '' candidate; do
if file --brief "${candidate}" | grep -q '^ELF '; then
strip --strip-unneeded "${candidate}" || die "failed to strip ${candidate}"
fi
done < <(find "${STAGE_DIR}${RUNTIME_PREFIX}" -type f -print0)
for required in \
"${STAGE_DIR}${RUNTIME_PREFIX}/bin/ffmpeg" \
"${STAGE_DIR}${RUNTIME_PREFIX}/bin/ffprobe" \
"${STAGE_DIR}${RUNTIME_PREFIX}/bin/kodi" \
"${STAGE_DIR}/usr/lib/systemd/system/kodi-rk.service"; do
[[ -e "${required}" ]] || die "staged runtime file is missing: ${required}"
done
if find "${STAGE_DIR}${RUNTIME_PREFIX}" -type f -exec grep -IlF "${WORK_DIR}" {} + | grep -q .; then
die "build path leaked into a staged text file"
fi
"${SCRIPT_DIR}/package-media.sh" \
--stage "${STAGE_DIR}" \
--output-dir "${OUTPUT_DIR}" \
--version "${PACKAGE_VERSION}"
log "media build complete"