350 lines
15 KiB
Bash
350 lines
15 KiB
Bash
#!/usr/bin/env bash
|
|
#
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
#
|
|
# Copyright (c) 2026 AMLOGIC
|
|
#
|
|
# gst-aml-vendor build script for AMLbian
|
|
# Cross-compiles vendor gst plugins (amlv4l2h264dec et al) from aml-comp
|
|
# sources, packages a .deb into BUILD_DEBS. The install side lives in
|
|
# lib/function-img.sh as install_gst_aml_vendor_deb, mirroring libencoder.
|
|
|
|
# ==============================================================================
|
|
# Section 2: Default Configuration
|
|
# ==============================================================================
|
|
# BOARD and ARCH are set (often readonly) by the armbian framework before this
|
|
# script is sourced -- do not reassign. DEB_VERSION is our own variable.
|
|
|
|
DEB_VERSION="${GST_AML_VENDOR_VERSION:-1.0.0}"
|
|
|
|
# Cross-compile toolchain prefix; inherits from framework if already set.
|
|
: "${CROSS_COMPILE:=aarch64-linux-gnu-}"
|
|
|
|
# Kernel source sub-directory inside aml-comp (provides vendor DRM uapi headers).
|
|
: "${AML_KERNEL_SUBDIR:=aml-6.12}"
|
|
|
|
# libsecmem prebuilt sub-path inside aml-comp/multimedia/libmediadrm/libsecmem-bin/prebuilt/
|
|
: "${LIBSECMEM_VERSION:=${PLATFORM_TDK_VERSION:-v4.4.0}}"
|
|
: "${LIBSECMEM_ARCH_DIR:=aarch64.lp64.}"
|
|
|
|
# ==============================================================================
|
|
# Section 4: Build Functions
|
|
# ==============================================================================
|
|
|
|
function __gst_aml_vendor_prepare_source {
|
|
local rootfs="$1" comp_dir="$2" work="$3"
|
|
local _gnu_triplet="${CROSS_COMPILE%%-}"
|
|
|
|
# dev headers/.pc files needed for cross-compile. --force-overwrite: vendor
|
|
# aml-libgles ships a libgbm that collides with Debian libgbm1 pulled in via
|
|
# libgstreamer-plugins-base1.0-dev.
|
|
mount_chroot "$rootfs"
|
|
chroot "$rootfs" /bin/bash -c "
|
|
export DEBIAN_FRONTEND=noninteractive TMPDIR=/tmp
|
|
apt-get update -y
|
|
apt-get install -y --no-install-recommends \
|
|
-o Dpkg::Options::=--force-overwrite \
|
|
libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev \
|
|
libdrm-dev libgudev-1.0-dev libv4l-dev pkg-config
|
|
"
|
|
local rc=$?
|
|
umount_chroot "$rootfs"
|
|
[[ $rc -eq 0 ]] || return 1
|
|
|
|
# Vendor DRM uapi headers + libsecmem prebuilt blob.
|
|
install -m 0644 -D \
|
|
"${comp_dir}/kernel/${AML_KERNEL_SUBDIR}/common_drivers/include/uapi/amlogic/drm/meson_drm.h" \
|
|
"${rootfs}/usr/include/meson_drm.h"
|
|
mkdir -p "${rootfs}/usr/include/drm"
|
|
cp -a "${comp_dir}/kernel/${AML_KERNEL_SUBDIR}/include/uapi/drm/." "${rootfs}/usr/include/drm/"
|
|
|
|
local secmem="${comp_dir}/multimedia/libmediadrm/libsecmem-bin/prebuilt"
|
|
install -m 0644 -D "${secmem}/${LIBSECMEM_VERSION}/${LIBSECMEM_ARCH_DIR}/libsecmem.so" \
|
|
"${rootfs}/usr/lib/${_gnu_triplet}/libsecmem.so"
|
|
cp -a "${secmem}/noarch/include/." "${rootfs}/usr/include/"
|
|
mkdir -p "${rootfs}/usr/lib/${_gnu_triplet}/pkgconfig"
|
|
cp -a "${secmem}/noarch/pkgconfig/." \
|
|
"${rootfs}/usr/lib/${_gnu_triplet}/pkgconfig/"
|
|
|
|
# Stage three vendor source subtrees.
|
|
rm -rf "${work}" && mkdir -p "${work}/src"
|
|
cp -r "${comp_dir}/multimedia/gst-aml-drmbufferpool1/gst-aml-drmbufferpool-1.0" "${work}/src/drmbufferpool"
|
|
cp -r "${comp_dir}/multimedia/gst-aml-drm-plugins1/gst-aml-drm-plugins-1.0/src/secmem" "${work}/src/secmem"
|
|
cp -r "${comp_dir}/multimedia/gst-plugin-aml-v4l2dec" "${work}/src/v4l2dec"
|
|
|
|
# Vendor version_config.sh needs git history we don't have; pre-write the
|
|
# generated headers and disable the script.
|
|
cat > "${work}/src/drmbufferpool/src/bufferpool/aml_version.h" <<'EOF'
|
|
#ifndef AML_VERSION_H
|
|
#define AML_VERSION_H
|
|
static const char* gst_drmbufferpool_version __attribute__((used)) =
|
|
"MM-module-name:gst-plugin-drmbufferpool,version:1.1-amlbian";
|
|
#endif
|
|
EOF
|
|
cat > "${work}/src/v4l2dec/src/aml_version.h" <<'EOF'
|
|
#ifndef AML_VERSION_H
|
|
#define AML_VERSION_H
|
|
static const char* gst_amlv4l2_version __attribute__((used)) =
|
|
"MM-module-name:gst-plugin-aml-v4l2dec,version:1.1-amlbian";
|
|
#endif
|
|
EOF
|
|
chmod -x "${work}/src/drmbufferpool/version_config.sh" \
|
|
"${work}/src/v4l2dec/version_config.sh" 2>/dev/null || true
|
|
|
|
# aml_gst_shim.o: two yocto-only buffer pool symbols not in Debian gst 1.22.
|
|
# Linked into libgstamlv4l2.so via LDFLAGS; hidden visibility keeps them
|
|
# out of the exported symbol space.
|
|
cat > "${work}/aml_gst_shim.c" <<'EOF'
|
|
#include <limits.h>
|
|
typedef void GstBufferPool;
|
|
typedef int gboolean;
|
|
__attribute__((visibility("hidden")))
|
|
int gst_buffer_pool_get_outstanding_num(GstBufferPool *p) { (void)p; return INT_MAX; }
|
|
__attribute__((visibility("hidden")))
|
|
gboolean gst_buffer_pool_increase_max_num(GstBufferPool *p, unsigned int n) {
|
|
(void)p; (void)n; return 1;
|
|
}
|
|
EOF
|
|
# libsecmem.so DT_NEEDED's libmediahal_resman.so (closed source, no blob);
|
|
# no-op stubs are enough for non-secure decode.
|
|
cat > "${work}/libmediahal_resman_stub.c" <<'EOF'
|
|
#include <stddef.h>
|
|
int resman_init(int a, int b) { (void)a; (void)b; return 0; }
|
|
int resman_close(int a) { (void)a; return 0; }
|
|
int resman_query(int a, int b, void *c) { (void)a; (void)b; (void)c; return -1; }
|
|
int resman_acquire_para(int a, void *b) { (void)a; (void)b; return -1; }
|
|
int resman_acquire_wait(int a) { (void)a; return -1; }
|
|
int resman_release(int a) { (void)a; return 0; }
|
|
int resman_resource_support(int a) { (void)a; return 0; }
|
|
int resman_setappinfo(int a, void *b) { (void)a; (void)b; return 0; }
|
|
int resman_support(int a) { (void)a; return 0; }
|
|
EOF
|
|
cat > "${work}/libteec_stub.c" <<'EOF'
|
|
#include <stddef.h>
|
|
unsigned int TEEC_InitializeContext(const char *n, void *c) { (void)n; (void)c; return 0xFFFF0008U; }
|
|
void TEEC_FinalizeContext(void *c) { (void)c; }
|
|
unsigned int TEEC_OpenSession(void *c, void *s, const void *d, unsigned int m,
|
|
const void *p, void *o, unsigned int *e)
|
|
{ (void)c; (void)s; (void)d; (void)m; (void)p; (void)o;
|
|
if (e) *e = 0; return 0xFFFF0008U; }
|
|
void TEEC_CloseSession(void *s) { (void)s; }
|
|
unsigned int TEEC_InvokeCommand(void *s, unsigned int c, void *p, unsigned int *e)
|
|
{ (void)s; (void)c; (void)p; if (e) *e = 0; return 0xFFFF0008U; }
|
|
unsigned int TEEC_AllocateSharedMemory(void *c, void *m) { (void)c; (void)m; return 0xFFFF0008U; }
|
|
void TEEC_ReleaseSharedMemory(void *m) { (void)m; }
|
|
EOF
|
|
}
|
|
|
|
function __gst_aml_vendor_build {
|
|
local work="$1" rootfs="$2"
|
|
local _gnu_triplet="${CROSS_COMPILE%%-}"
|
|
local libdir="$rootfs/usr/lib/${_gnu_triplet}"
|
|
local _build_triplet
|
|
_build_triplet="$(gcc -dumpmachine)"
|
|
|
|
if [[ ! -f "$libdir/libmediahal_resman.so" && ! -f "$rootfs/usr/lib/libmediahal_resman.so" ]]; then
|
|
${CROSS_COMPILE}gcc -shared -fPIC -O2 \
|
|
-Wl,-soname,libmediahal_resman.so \
|
|
-o "$libdir/libmediahal_resman.so" "$work/libmediahal_resman_stub.c"
|
|
GST_AML_VENDOR_BUNDLE_RESMAN=1
|
|
fi
|
|
if [[ ! -f "$libdir/libteec.so.2" && ! -f "$rootfs/usr/lib/libteec.so.2" && ! -f "$rootfs/usr/lib/libteec.so.2.0.0" ]]; then
|
|
${CROSS_COMPILE}gcc -shared -fPIC -O2 \
|
|
-Wl,-soname,libteec.so.2 \
|
|
-o "$libdir/libteec.so.2" "$work/libteec_stub.c"
|
|
ln -sf libteec.so.2 "$libdir/libteec.so"
|
|
GST_AML_VENDOR_BUNDLE_LIBTEEC=1
|
|
fi
|
|
${CROSS_COMPILE}gcc -fPIC -O2 -c \
|
|
-o "$work/aml_gst_shim.o" "$work/aml_gst_shim.c"
|
|
|
|
export CC=${CROSS_COMPILE}gcc
|
|
export AR=${CROSS_COMPILE}ar
|
|
export STRIP=${CROSS_COMPILE}strip
|
|
export PKG_CONFIG=pkg-config
|
|
export PKG_CONFIG_SYSROOT_DIR="$rootfs"
|
|
export PKG_CONFIG_LIBDIR="$rootfs/usr/lib/${_gnu_triplet}/pkgconfig:$rootfs/usr/share/pkgconfig:$rootfs/usr/lib/pkgconfig"
|
|
unset PKG_CONFIG_PATH
|
|
|
|
# drmbufferpool + drmallocator (autotools)
|
|
( cd "$work/src/drmbufferpool" && mkdir -p m4 build-aux && autoreconf -fi \
|
|
&& ./configure --host=${_gnu_triplet} --build=${_build_triplet} \
|
|
--prefix=/usr --libdir=/usr/lib/${_gnu_triplet} \
|
|
--with-sysroot="$rootfs" \
|
|
CFLAGS="--sysroot=$rootfs" CPPFLAGS="--sysroot=$rootfs" \
|
|
LDFLAGS="--sysroot=$rootfs" \
|
|
&& make -j"$(nproc)" \
|
|
&& make install DESTDIR="$rootfs" ) || return 1
|
|
|
|
# secmemallocator (single .c)
|
|
local CFLAGS_PKG LIBS_PKG
|
|
CFLAGS_PKG=$(pkg-config --cflags gstreamer-1.0 gstreamer-base-1.0 \
|
|
gstreamer-allocators-1.0 libsecmem) || return 1
|
|
LIBS_PKG=$(pkg-config --libs gstreamer-1.0 gstreamer-base-1.0 \
|
|
gstreamer-allocators-1.0 libsecmem) || return 1
|
|
( cd "$work/src/secmem" \
|
|
&& ${CROSS_COMPILE}gcc -shared -fPIC -O2 --sysroot="$rootfs" \
|
|
$CFLAGS_PKG gstsecmemallocator.c $LIBS_PKG \
|
|
-Wl,-soname,libgstsecmemallocator.so.0 \
|
|
-o "$libdir/libgstsecmemallocator.so.0.0.0" ) || return 1
|
|
ln -sf libgstsecmemallocator.so.0.0.0 "$libdir/libgstsecmemallocator.so.0"
|
|
ln -sf libgstsecmemallocator.so.0.0.0 "$libdir/libgstsecmemallocator.so"
|
|
install -m 0644 -D "$work/src/secmem/gstsecmemallocator.h" \
|
|
"$rootfs/usr/include/gstreamer-1.0/gst/allocators/gstsecmemallocator.h"
|
|
cat > "$libdir/pkgconfig/gstsecmemallocator.pc" <<EOF
|
|
prefix=/usr
|
|
libdir=/usr/lib/${_gnu_triplet}
|
|
includedir=/usr/include/gstreamer-1.0
|
|
Name: gstsecmemallocator
|
|
Description: Amlogic gst secmem allocator
|
|
Version: 1.0
|
|
Libs: -L\${libdir} -lgstsecmemallocator
|
|
Cflags: -I\${includedir}
|
|
EOF
|
|
|
|
# v4l2dec (autotools). All deps live in $rootfs so libtool relink works.
|
|
# aml_gst_shim.o linked in directly (vs a separate libaml_gst_shim.so).
|
|
( cd "$work/src/v4l2dec" && mkdir -p m4 build-aux && autoreconf -fi \
|
|
&& ./configure --host=${_gnu_triplet} --build=${_build_triplet} \
|
|
--prefix=/usr --libdir=/usr/lib/${_gnu_triplet} \
|
|
--with-sysroot="$rootfs" \
|
|
CFLAGS="--sysroot=$rootfs" CPPFLAGS="--sysroot=$rootfs" \
|
|
LDFLAGS="--sysroot=$rootfs -L$libdir $work/aml_gst_shim.o" \
|
|
&& make TARGET_DIR="$rootfs" -j"$(nproc)" \
|
|
&& make install TARGET_DIR="$rootfs" DESTDIR="$rootfs" ) || return 1
|
|
|
|
[[ -f "$libdir/gstreamer-1.0/libgstamlv4l2.so" ]] || {
|
|
echo "v4l2dec install MISSING plugin"; return 1; }
|
|
}
|
|
|
|
function __gst_aml_vendor_create_deb {
|
|
local rootfs="$1" build_root="$2"
|
|
local _gnu_triplet="${CROSS_COMPILE%%-}"
|
|
local pkg_name="gst-aml-vendor"
|
|
local deb_dir="${build_root}/deb/${pkg_name}-${DEB_VERSION}"
|
|
local rdir="$rootfs/usr/lib/${_gnu_triplet}"
|
|
local idir="${deb_dir}/usr/lib/${_gnu_triplet}"
|
|
|
|
rm -rf "${build_root}/deb"
|
|
mkdir -p "${deb_dir}/DEBIAN" "$idir/gstreamer-1.0"
|
|
|
|
[[ "$GST_AML_VENDOR_BUNDLE_RESMAN" ]] && \
|
|
install -m 0755 "$rdir/libmediahal_resman.so" "$idir/"
|
|
if [[ "$GST_AML_VENDOR_BUNDLE_LIBTEEC" ]]; then
|
|
install -m 0755 "$rdir/libteec.so.2" "$idir/"
|
|
ln -sf libteec.so.2 "$idir/libteec.so"
|
|
fi
|
|
install -m 0644 "$rdir/libsecmem.so" "$idir/"
|
|
local lib
|
|
for lib in libgstdrmbufferpool libgstdrmallocator libgstsecmemallocator; do
|
|
cp -a "$rdir/${lib}.so.0.0.0" "$idir/"
|
|
ln -sf "${lib}.so.0.0.0" "$idir/${lib}.so.0"
|
|
ln -sf "${lib}.so.0.0.0" "$idir/${lib}.so"
|
|
done
|
|
install -m 0755 "$rdir/gstreamer-1.0/libgstamlv4l2.so" "$idir/gstreamer-1.0/"
|
|
|
|
cat > "${deb_dir}/DEBIAN/control" <<EOF
|
|
Package: ${pkg_name}
|
|
Version: ${DEB_VERSION}
|
|
Architecture: ${ARCH}
|
|
Maintainer: Armbian Build <[email protected]>
|
|
Section: libs
|
|
Priority: optional
|
|
Depends: libc6, libgstreamer1.0-0, libgstreamer-plugins-base1.0-0, libdrm2, libgudev-1.0-0, libv4l-0
|
|
Description: Amlogic vendor GStreamer plugins (amlv4l2h264dec et al)
|
|
Vendor GStreamer plugins for hardware video decode on Amlogic SoCs.
|
|
EOF
|
|
|
|
cat > "${deb_dir}/DEBIAN/postinst" <<'EOF'
|
|
#!/bin/sh
|
|
set -e
|
|
if [ "$1" = "configure" ]; then
|
|
command -v ldconfig >/dev/null 2>&1 && ldconfig
|
|
rm -f /root/.cache/gstreamer-1.0/registry.* 2>/dev/null || true
|
|
fi
|
|
EOF
|
|
chmod 0755 "${deb_dir}/DEBIAN/postinst"
|
|
|
|
( cd "${build_root}/deb" && dpkg-deb --build "${pkg_name}-${DEB_VERSION}" )
|
|
local out="${BUILD_DEBS:-${SRC}/output}"
|
|
mkdir -p "${out}"
|
|
mv "${build_root}/deb/${pkg_name}-${DEB_VERSION}.deb" \
|
|
"${out}/linux-${pkg_name}-${BOARD}-amlbian_${DEB_VERSION}_${ARCH}.deb"
|
|
}
|
|
|
|
function __gst_aml_vendor_cleanup_rootfs {
|
|
local rootfs="$1"
|
|
local _gnu_triplet="${CROSS_COMPILE%%-}"
|
|
mount_chroot "$rootfs"
|
|
# `remove` not `autoremove` -- autoremove greedily purges packages it
|
|
# considers orphans, including PACKAGE_LIST_AML runtime libs.
|
|
# Do NOT apt-get remove dev packages here: subsequent build steps
|
|
# (venc, jpeg, dma-allocator, gfx2d, conv) still need libdrm-dev,
|
|
# libgstreamer-plugins-base1.0-dev, pkg-config headers/pc-files.
|
|
# Only clean the apt cache to reclaim space.
|
|
chroot "$rootfs" /bin/bash -c "
|
|
export DEBIAN_FRONTEND=noninteractive
|
|
apt-get clean
|
|
rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*.deb
|
|
" || true
|
|
umount_chroot "$rootfs"
|
|
|
|
# Compile-only artifacts (headers + .pc). The .so files stay -- dpkg
|
|
# owns them now via the .deb just installed.
|
|
local rdir="$rootfs/usr/lib/${_gnu_triplet}"
|
|
rm -f "$rdir/pkgconfig/libsecmem.pc" \
|
|
"$rdir/pkgconfig/gstsecmemallocator.pc" \
|
|
"$rootfs/usr/include/secmem.h" \
|
|
"$rootfs/usr/include/secmem-ca.h" \
|
|
"$rootfs/usr/include/meson_drm.h" \
|
|
"$rootfs/usr/include/gstreamer-1.0/gst/allocators/gstsecmemallocator.h" 2>/dev/null
|
|
rm -rf "$rootfs/usr/include/drm" 2>/dev/null
|
|
}
|
|
|
|
# ==============================================================================
|
|
# Section 5: Main
|
|
# ==============================================================================
|
|
|
|
function amlbian_build_gst_aml_vendor {
|
|
is_unit_enabled "gst-aml-vendor" || {
|
|
display_alert "[SKIP] >> gst-aml-vendor disable in BUILD_UNITS" "" "info"
|
|
return 0
|
|
}
|
|
local rootfs="${ROOTFS_TEMP:-${SDCARD:-}}"
|
|
[[ -d "${rootfs}" ]] || { display_alert "GST-AML-VENDOR" "no rootfs" "err"; return 1; }
|
|
|
|
display_alert "AMLOGIC: Building gst-aml-vendor ${DEB_VERSION} ${BOARD} ${ARCH}" "info"
|
|
|
|
local comp_dir="$(amlbian_get_aml_comp_dir)"
|
|
local build_root="${SRC:-/tmp}/.tmp/gst-aml-vendor-build-${ARCH}"
|
|
local work="${build_root}/work"
|
|
local out="${BUILD_DEBS:-${SRC}/output}"
|
|
local build_log="${out}/gst-aml-vendor-build.log"
|
|
rm -rf "${build_root}" && mkdir -p "${work}" "${out}"
|
|
|
|
local rc
|
|
(
|
|
set -x
|
|
__gst_aml_vendor_prepare_source "$rootfs" "$comp_dir" "$work" || exit 1
|
|
__gst_aml_vendor_build "$work" "$rootfs" || exit 1
|
|
__gst_aml_vendor_create_deb "$rootfs" "$build_root" || exit 1
|
|
__gst_aml_vendor_cleanup_rootfs "$rootfs" || true
|
|
) > "$build_log" 2>&1
|
|
rc=$?
|
|
rm -rf "$work"
|
|
|
|
if [[ $rc -ne 0 ]]; then
|
|
display_alert "GST-AML-VENDOR" "build FAILED -- log: $build_log" "err"
|
|
return 1
|
|
fi
|
|
display_alert "AMLOGIC: gst-aml-vendor build completed" "$out" "info"
|
|
return 0
|
|
}
|
|
|
|
# Build runs in docker phase (needs rootfs as sysroot), so this script does
|
|
# NOT auto-invoke; install_gst_aml_vendor_deb in lib/function-img.sh drives it.
|
|
|
|
# ==============================================================================
|
|
# End of build-gst-aml-vendor.sh
|
|
# ==============================================================================
|