Make image_streamer work on the orin
Add the packages to the rootfs and link against them. Also, fix
anything that image_streamer used to require which doesn't make sense
this year.
Change-Id: I77d56bee1cc74c67153cbbefc72d2cb3c56b7c80
Signed-off-by: Austin Schuh <austin.linux@gmail.com>
diff --git a/frc971/orin/build_rootfs.py b/frc971/orin/build_rootfs.py
index 3e6fab5..e6dba6d 100755
--- a/frc971/orin/build_rootfs.py
+++ b/frc971/orin/build_rootfs.py
@@ -2,6 +2,7 @@
from __future__ import annotations
import apt_pkg
+import sys
import collections
import contextlib
import datetime
@@ -33,7 +34,7 @@
check=True,
stdout=subprocess.PIPE)
device = result.stdout.decode('utf-8').strip()
- print("Mounted", image, "to", repr(device))
+ print("Mounted", image, "to", repr(device), file=sys.stderr)
try:
yield device
finally:
@@ -81,14 +82,14 @@
missing_deps.append(dep)
if len(missing_deps) > 0:
- print("Missing dependencies, please install:")
- print("sudo apt-get install", " ".join(missing_deps))
+ print("Missing dependencies, please install:", file=sys.stderr)
+ print("sudo apt-get install", " ".join(missing_deps), file=sys.stderr)
exit()
def make_image(image):
"""Makes an image and creates an xfs filesystem on it."""
- print("--> Creating NEW image ", f"{image}")
+ print("--> Creating NEW image ", f"{image}", file=sys.stderr)
result = subprocess.run([
"dd", "if=/dev/zero", f"of={image}", "bs=1", "count=0",
"seek=8589934592"
@@ -133,7 +134,7 @@
def copyfile(owner, permissions, file):
"""Copies a file from contents/{file} with the provided owner and permissions."""
- print("copyfile", owner, permissions, file)
+ print("copyfile", owner, permissions, file, file=sys.stderr)
subprocess.run(["sudo", "cp", f"contents/{file}", f"{PARTITION}/{file}"],
check=True)
subprocess.run(["sudo", "chmod", permissions, f"{PARTITION}/{file}"],
@@ -143,7 +144,7 @@
def target_mkdir(owner_group, permissions, folder):
"""Creates a directory recursively with the provided permissions and ownership."""
- print("target_mkdir", owner_group, permissions, folder)
+ print("target_mkdir", owner_group, permissions, folder, file=sys.stderr)
owner, group = owner_group.split(':')
target(
["install", "-d", "-m", permissions, "-o", owner, "-g", group, folder])
@@ -200,7 +201,9 @@
for package in new_packages:
if package.name in existing_packages and existing_packages[
package.name] == package.version:
- print('Skipping', package)
+ print('Skipping existing package: ',
+ package.name,
+ file=sys.stderr)
continue
subprocess.run([
@@ -279,6 +282,10 @@
if other.operator is None:
return True
+ # libz1 is special and doesn't have a version... Don't stress it for now until we learn why.
+ if self.operator is None and self.name == 'libz1':
+ return True
+
vc = apt_pkg.version_compare(self.version, other.version)
if vc < 0:
return other.operator in ('<=', '<<')
@@ -389,8 +396,6 @@
break
elif ext == '.so':
found_so = True
- else:
- found_so = False
if found_so:
result.append(file)
@@ -412,6 +417,7 @@
self.package = package
self.libs = []
self.cflags = []
+ self.requires = []
for line in contents.split('\n'):
line = line.strip()
# Parse everything so we learn if a new field shows up we don't
@@ -439,9 +445,20 @@
elif line.startswith('Cflags.private:'):
pass
elif line.startswith('Requires:'):
- pass
+ # Parse a Requires line of the form:
+ # Requires: glib-2.0 >= 2.56.0, gobject-2.0
+ self.requires += [
+ f.split()[0] for f in self.expand(
+ line.removeprefix('Requires:').strip()).split(',') if f
+ ]
elif line.startswith('Requires.private:'):
- pass
+ # Parse a Requires.private line of the form:
+ # Requires.private: gmodule-2.0
+ self.requires += [
+ f.split()[0] for f in self.expand(
+ line.removeprefix('Requires.private:').strip()).split(
+ ',') if f
+ ]
elif line.startswith('Libs.private:'):
pass
elif line.startswith('Conflicts:'):
@@ -533,7 +550,7 @@
self.directories.add(file)
except PermissionError:
# Assume it is a file...
- print("Failed to read", file)
+ print("Failed to read", file, file=sys.stderr)
pass
# Directories are all the things before the last /
@@ -554,8 +571,13 @@
continue
if f in self.files:
- print("Duplicate file", repr(f), ' current', package,
- ' already', self.files[f])
+ print("Duplicate file",
+ repr(f),
+ ' current',
+ package,
+ ' already',
+ self.files[f],
+ file=sys.stderr)
if not f.startswith('/usr/share'):
assert (f not in self.files)
self.files[f] = package
@@ -695,15 +717,25 @@
filesystem = Filesystem(partition)
packages_to_eval = [
+ filesystem.packages['libglib2.0-dev'],
filesystem.packages['libopencv-dev'],
filesystem.packages['libc6-dev'],
filesystem.packages['libstdc++-12-dev'],
filesystem.packages['libnpp-11-8-dev'],
+ filesystem.packages['gstreamer1.0-dev'],
+ filesystem.packages['orc-dev'],
+ filesystem.packages['libgstrtp-1.0-0'],
+ filesystem.packages['gstreamer1.0-plugins-bad-dev'],
]
+ # Now, we want to figure out what the dependencies of each of the packages are.
+ # Generate the dependency tree starting from an initial list of packages.
+ # Then, figure out how to link the .so's in.
+
# Recursively walk the tree using dijkstra's algorithm to generate targets
# for each set of headers.
- print('Walking tree for', [p.name.name for p in packages_to_eval])
+ print('Walking tree for', [p.name.name for p in packages_to_eval],
+ file=sys.stderr)
rules = []
objs_to_eval = []
@@ -778,11 +810,11 @@
resolved_deps.sort()
rule_name = obj[1:].replace('/', '_')
rule_deps = ''.join([
- ' ":{}",\n'.format(d[1:].replace('/', '_'))
+ ' ":{}-lib",\n'.format(d[1:].replace('/', '_'))
for d in resolved_deps if d not in skip_set
])
rules.append(
- f'cc_library(\n name = "{rule_name}",\n srcs = ["{obj[1:]}"],\n deps = [\n{rule_deps} ],\n)'
+ f'cc_library(\n name = "{rule_name}-lib",\n srcs = ["{obj[1:]}"],\n deps = [\n{rule_deps} ],\n)'
)
standard_includes = set()
@@ -797,9 +829,6 @@
for f in contents.libs if f.startswith('-l')
]
- if contents.package not in packages_visited_set:
- continue
-
includes = []
for flag in contents.cflags:
if flag.startswith('-I/') and flag.removeprefix(
@@ -808,9 +837,10 @@
rule_deps = ''.join(
sorted([
- ' ":' + l[1:].replace('/', '_') + '",\n'
+ ' ":' + l[1:].replace('/', '_') + '-lib",\n'
for l in resolved_libraries
- ] + [f' ":{contents.package.name.name}-headers",\n']))
+ ] + [f' ":{contents.package.name.name}-headers",\n'] +
+ [f' ":{dep}",\n' for dep in contents.requires]))
includes.sort()
if len(includes) > 0:
includes_string = ' includes = ["' + '", "'.join(
@@ -818,20 +848,15 @@
else:
includes_string = ''
rules.append(
- f'cc_library(\n name = "{pkg}",\n{includes_string} visibility = ["//visibility:public"],\n deps = [\n{rule_deps} ],\n)'
+ f'# pkgconf -> {pkg}\ncc_library(\n name = "{pkg}",\n{includes_string} visibility = ["//visibility:public"],\n deps = [\n{rule_deps} ],\n)'
)
# Look up which package this is from to include the headers
# Depend on all the libraries
# Parse -I -> includes
except FileNotFoundError:
- print('Failed to instantiate package', repr(pkg))
+ print('Failed to instantiate package', repr(pkg), file=sys.stderr)
pass
- # Now, we want to figure out what the dependencies of opencv-dev are.
- # Generate the dependency tree starting from an initial list of packages.
-
- # Then, figure out how to link the .so's in. Sometimes, multiple libraries exist per .deb, one target for all?
-
with open("orin_debian_rootfs.BUILD.template", "r") as file:
template = jinja2.Template(file.read())
@@ -862,7 +887,7 @@
def do_package(partition):
tarball = datetime.date.today().strftime(
f"{os.getcwd()}/%Y-%m-%d-bookworm-arm64-nvidia-rootfs.tar")
- print(tarball)
+ print(tarball, file=sys.stderr)
subprocess.run([
"sudo",
@@ -947,14 +972,16 @@
check_required_deps(REQUIRED_DEPS)
if not os.path.exists(YOCTO):
- print("ERROR: Must have YOCTO directory properly specified to run")
- print("See https://github.com/frc971/meta-frc971/tree/main for info")
+ print("ERROR: Must have YOCTO directory properly specified to run",
+ file=sys.stderr)
+ print("See https://github.com/frc971/meta-frc971/tree/main for info",
+ file=sys.stderr)
exit()
if not check_buildifier():
print(
- "ERROR: Need to have buildifier in the path. Please resolve this."
- )
+ "ERROR: Need to have buildifier in the path. Please resolve this.",
+ file=sys.stderr)
exit()
new_image = not os.path.exists(IMAGE)
@@ -1037,7 +1064,8 @@
"trace-cmd", "clinfo", "jq", "strace", "sysstat", "lm-sensors",
"can-utils", "xfsprogs", "bridge-utils", "net-tools", "apt-file",
"parted", "xxd", "file", "pkexec", "libxkbfile1", "gdb", "autossh",
- "smartmontools", "nvme-cli", "libgtk-3.0"
+ "smartmontools", "nvme-cli", "libgtk-3.0", "eog", "psmisc",
+ "libsrtp2-1"
])
target(["apt-get", "clean"])
@@ -1047,12 +1075,15 @@
target(["usermod", "-a", "-G", "dialout", "pi"])
virtual_packages = [
+ 'glib-2.0-dev',
'libglib-2.0-0',
'libglvnd',
'libgtk-3-0',
+ 'libxcb-dev',
'libxcb-glx',
- 'wayland',
'libz1',
+ 'wayland',
+ 'wayland-dev',
]
install_virtual_packages(virtual_packages)
@@ -1084,11 +1115,12 @@
if not already_installed:
packages_to_remove.append(key)
- print("Removing", packages_to_remove)
+ print("Removing", packages_to_remove, file=sys.stderr)
if len(packages_to_remove) > 0:
target(['dpkg', '--purge'] + packages_to_remove)
print("Installing",
- [package.name for package in yocto_packages_to_install])
+ [package.name for package in yocto_packages_to_install],
+ file=sys.stderr)
install_packages(yocto_packages_to_install, packages)
@@ -1121,22 +1153,45 @@
'libcurand-11-8',
'libcurand-11-8-dev',
'libcurand-11-8-stubs',
- 'cuda-nvcc-11-8',
'tegra-cmake-overrides',
'cuda-target-environment',
'libnpp-11-8',
'libnpp-11-8-stubs',
'libnpp-11-8-dev',
'cuda-cccl-11-8',
- 'cuda-nvcc-11-8',
+ 'cuda-nvcc-11-8', # This one isn't in our yocto packages, but we need it
'cuda-nvcc-headers-11-8',
'nsight-systems-cli',
'nsight-systems-cli-qdstrmimporter',
'tegra-tools-jetson-clocks',
+ # Added to support gstreamer1.0-dev, etc, for image_streamer
+ 'libgstfft-1.0-0',
+ 'libgstgl-1.0-0',
+ 'libgstrtsp-1.0-0',
+ 'libgstsdp-1.0-0',
+ 'libgstadaptivedemux-1.0-0',
+ 'libgstbadaudio-1.0-0',
+ 'libgstbasecamerabinsrc-1.0-0',
+ 'libgstcodecs-1.0-0',
+ 'libgstinsertbin-1.0-0',
+ 'libgstisoff-1.0-0',
+ 'libgstmpegts-1.0-0',
+ 'libgstphotography-1.0-0',
+ 'libgstplay-1.0-0',
+ 'libgstplayer-1.0-0',
+ 'libgstsctp-1.0-0',
+ 'libgsttranscoder-1.0-0',
+ 'libgsturidownloader-1.0-0',
+ 'libgstvulkan-1.0-0',
+ 'libgstwayland-1.0-0',
+ 'libgstwebrtc-1.0-0',
'gstreamer1.0',
'gstreamer1.0-plugins-base',
+ 'gstreamer1.0-plugins-bad',
+ 'gstreamer1.0-dev',
+ 'gstreamer1.0-plugins-base-dev',
+ 'gstreamer1.0-plugins-bad-dev',
'libgstallocators-1.0-0',
- 'liborc',
'libgstvideo-1.0-0',
'libnvdsbufferpool1.0.0',
'gstreamer1.0-plugins-nvarguscamerasrc',
@@ -1157,11 +1212,28 @@
'libgstcodecparsers-1.0-0',
'libgstriff-1.0-0',
'liborc-0.4-0',
+ 'liborc-test-0.4-0',
+ 'orc-dev',
+ 'orc',
'libgstaudio-1.0-0',
'libgsttag-1.0-0',
'gstreamer1.0-plugins-good-rtp',
'libgstrtp-1.0-0',
'gstreamer1.0-plugins-good-udp',
+ 'gstreamer1.0-plugins-bad-srtp',
+ 'gstreamer1.0-plugins-base-app',
+ 'gstreamer1.0-plugins-base-videoconvert',
+ 'gstreamer1.0-plugins-bad-dtls',
+ 'gstreamer1.0-plugins-good-video4linux2',
+ 'libcrypto3',
+ 'libssl3',
+ 'gstreamer1.0-plugins-ugly-x264',
+ 'gstreamer1.0-plugins-bad-webrtc',
+ 'libgstwebrtc-1.0-0',
+ 'libx264-163',
+ 'libnice',
+ 'gstreamer1.0-plugins-good-rtpmanager',
+ 'gstreamer1.0-plugins-ugly-asf',
# Yocto's doesn't work with gstreamer, and we don't actually care
# hugely. opencv seems to work.
'libv4l',
@@ -1173,6 +1245,17 @@
'v4l-utils',
]
+ for desired_package in yocto_package_names:
+ found_package = False
+ for yocto_package in yocto_packages:
+ if desired_package == yocto_package.name:
+ found_package = True
+ if not found_package:
+ print("Couldn't find package",
+ desired_package,
+ " for installation",
+ file=sys.stderr)
+
install_packages([
package for package in yocto_packages
if package.name in yocto_package_names
@@ -1204,6 +1287,7 @@
"libopencv-flann406",
"libopencv-highgui406",
"libopencv-imgcodecs406",
+ "gstreamer1.0-nice",
"libopencv-imgproc406",
"libopencv-ml406",
"libopencv-objdetect406",
@@ -1254,6 +1338,7 @@
copyfile("root:root", "644", "etc/systemd/network/80-canc.network")
copyfile("root:root", "644", "etc/udev/rules.d/nvidia.rules")
copyfile("root:root", "644", "etc/udev/rules.d/can.rules")
+ copyfile("root:root", "644", "etc/udev/rules.d/camera.rules")
copyfile("root:root", "644",
"lib/systemd/system/nvargus-daemon.service")
target(["/root/bin/change_hostname.sh", "orin-971-1"])
@@ -1266,6 +1351,12 @@
# Set up HW clock to use /dev/rtc0 and install hwclock service
target(["ln", "-sf", "/dev/rtc0", "/dev/rtc"])
+ target(["rm", "/usr/lib/gstreamer-1.0/libgstnice.so"])
+ target([
+ "ln", "-s",
+ "/usr/lib/aarch64-linux-gnu/gstreamer-1.0/libgstnice.so",
+ "/usr/lib/gstreamer-1.0/"
+ ])
target_unescaped(
"sed -i s/ATTR{hctosys}==\\\"1\\\"/ATTR{hctosys}==\\\"0\\\"/ /lib/udev/rules.d/50-udev-default.rules"
)