Skip to content

Commit d69ca13

Browse files
jforbergJohan FörbergJohanHultbergStiv-workisak-jacobsson
committed
Add example program for using axoverlay2 with Skia
Change-Id: I1847448bedf02e14d0b6afbf1d6bc6ce0a8a3c3a Co-authored-by: Johan Förberg <johanfb@axis.com> Co-authored-by: Johan Hultberg <johan@hultberg.it> Co-authored-by: Stiv Abdullwahed <stiva@axis.com> Co-authored-by: Isak Jacobsson <isakj@axis.com>
1 parent 7cdaaf5 commit d69ca13

12 files changed

Lines changed: 1371 additions & 0 deletions

File tree

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
name: Build axoverlay2_skia application
2+
on:
3+
workflow_dispatch:
4+
push:
5+
paths:
6+
- 'axoverlay2-skia/**'
7+
- '!axoverlay2-skia/README.md'
8+
- '.github/workflows/axoverlay2-skia.yml'
9+
jobs:
10+
test-app:
11+
name: Test app
12+
runs-on: ubuntu-latest
13+
strategy:
14+
fail-fast: false
15+
matrix:
16+
axis-os: ["12.11.72"]
17+
arch: ["armv7hf", "aarch64"]
18+
env:
19+
EXREPO: acap-native-examples
20+
EXNAME: axoverlay2-skia
21+
steps:
22+
- uses: actions/checkout@v6
23+
- uses: docker/setup-buildx-action@v4
24+
25+
- name: Build ${{ env.EXNAME }} application
26+
env:
27+
imagetag: ${{ env.EXREPO }}_${{ env.EXNAME }}:${{ matrix.arch }}
28+
run: |
29+
cd $EXNAME
30+
docker build --no-cache --tag $imagetag --build-arg ARCH=${{ matrix.arch }} .
31+
docker cp $(docker create $imagetag):/opt/app ./build
32+
cd ..
33+
docker image rm -f $imagetag

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ The examples are organized into logical groups to help you find the most relevan
7575
- [axoverlay2](./axoverlay2/)
7676
- An example in C that illustrates how to draw icons as overlays in a stream using the modern
7777
[Overlay API](https://developer.axis.com/acap/api#overlay2-API).
78+
- [axoverlay2-skia](./axoverlay2-skia/)
79+
- An example in C++ that illustrates how to draw overlays with GPU acceleration using the the Skia graphics toolkit.
7880
- [axoverlay](./axoverlay/)
7981
- An example in C that illustrates how to draw plain boxes and text as overlays in a stream using
8082
the [Axoverlay API (Legacy)](https://developer.axis.com/acap/api#axoverlay-api-legacy).

axoverlay2-skia/Dockerfile

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
ARG ARCH=aarch64
2+
ARG VERSION=12.11.0-rc.1
3+
ARG UBUNTU_VERSION=24.04
4+
ARG REPO=axisecp
5+
ARG SDK=acap-native-sdk
6+
7+
FROM ${REPO}/${SDK}:${VERSION}-${ARCH}-ubuntu${UBUNTU_VERSION}
8+
9+
ARG BUILD_DIR=/opt/build
10+
ARG SKIA_VERSION=chrome/m137
11+
12+
#-------------------------------------------------------------------------------
13+
# Prepare build environment
14+
#-------------------------------------------------------------------------------
15+
16+
# Install build dependencies for compiling Skia. Skia is configured with GN
17+
# (generate-ninja) and built with Ninja.
18+
RUN DEBIAN_FRONTEND=noninteractive \
19+
apt-get update && apt-get install -y --no-install-recommends \
20+
generate-ninja ninja-build git && \
21+
apt-get clean && \
22+
rm -rf /var/lib/apt/lists/*
23+
24+
#-------------------------------------------------------------------------------
25+
# Download and build the Skia graphics library
26+
#
27+
# These layers only depend on SKIA_VERSION, so they are cached and reused across
28+
# rebuilds as long as the Skia version is unchanged. Editing the application
29+
# source below does not trigger a Skia rebuild.
30+
#-------------------------------------------------------------------------------
31+
32+
WORKDIR ${BUILD_DIR}/skia
33+
34+
# Clone Skia, fetch its third-party dependencies, configure with GN and build
35+
# with Ninja in a single layer.
36+
#
37+
# git-sync-deps fetches Skia's third-party dependencies. On a slow or
38+
# unreliable network this step may fail. git-sync-deps starts one thread per
39+
# dependency with no concurrency limit, which can overload the connection or
40+
# trigger server-side rate limiting (HTTP 429). If that happens, serialize the
41+
# fetches by joining each worker thread right after starting it, for example
42+
# by prepending:
43+
# sed -i 's/^\( *\)thread.start()/\1thread.start()\n\1thread.join()/' tools/git-sync-deps
44+
# git-sync-deps is idempotent and skips already fetched dependencies, so
45+
# simply re-running it also lets a partial download converge.
46+
#
47+
# Minimal Skia GN configuration with most modules disabled.
48+
#
49+
# cc, cxx: Force GN to use the SDK-provided cross compilers.
50+
# extra_cflags: Disable NEON optimisations in Skia's bundled libpng.
51+
# These are not needed here and cause linking errors.
52+
# target_cpu: Prevent GN from guessing the target CPU and injecting
53+
# the wrong -march option.
54+
# is_component_build: Produce a static Skia library.
55+
RUN git clone https://skia.googlesource.com/skia.git . \
56+
--branch ${SKIA_VERSION} --depth 1 && \
57+
python3 tools/git-sync-deps && \
58+
. /opt/axis/acapsdk/environment-setup* && \
59+
gn gen --root=. --args=" \
60+
cc=\"$CC\" \
61+
cxx=\"$CXX\" \
62+
extra_cflags=[\"-DPNG_ARM_NEON_OPT=0\"] \
63+
target_cpu=\"dont_worry_about_it\" \
64+
is_official_build=true \
65+
is_component_build=false \
66+
is_debug=false \
67+
skia_enable_ganesh=true \
68+
skia_enable_pdf=false \
69+
skia_enable_skshaper=false \
70+
skia_enable_skunicode=false \
71+
skia_enable_svg=false \
72+
skia_enable_tools=false \
73+
skia_pdf_subset_harfbuzz=false \
74+
skia_use_angle=false \
75+
skia_use_egl=true \
76+
skia_use_expat=false \
77+
skia_use_fontconfig=false \
78+
skia_use_freetype=false \
79+
skia_use_gl=true \
80+
skia_use_harfbuzz=false \
81+
skia_use_icu=false \
82+
skia_use_libjpeg_turbo_decode=false \
83+
skia_use_libjpeg_turbo_encode=false \
84+
skia_use_lua=false \
85+
skia_use_libpng_decode=false \
86+
skia_use_libpng_encode=true \
87+
skia_use_libwebp_decode=false \
88+
skia_use_libwebp_encode=false \
89+
skia_use_system_libpng=false \
90+
skia_use_system_zlib=false \
91+
skia_use_wuffs=false \
92+
skia_use_x11=false \
93+
skia_use_xps=false \
94+
skia_use_zlib=false \
95+
" build_skia && \
96+
ninja -C build_skia
97+
98+
#-------------------------------------------------------------------------------
99+
# Build the ACAP application
100+
#-------------------------------------------------------------------------------
101+
102+
WORKDIR /opt/app
103+
COPY ./app .
104+
105+
# Point the application Makefile at the prebuilt Skia headers and static
106+
# library. Skia is statically linked, so it is only needed at build time and is
107+
# kept outside the application directory to avoid bloating the package.
108+
ENV SKIA_DIR=${BUILD_DIR}/skia
109+
ENV SKIA_LIB=${BUILD_DIR}/skia/build_skia/libskia.a
110+
111+
RUN . /opt/axis/acapsdk/environment-setup* && acap-build .

axoverlay2-skia/README.md

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
*Copyright (C) 2026, Axis Communications AB, Lund, Sweden. All Rights Reserved.*
2+
3+
# ACAP application drawing video overlays with GPU acceleration
4+
5+
This README file explains how to build an ACAP application that uses the Axoverlay2 API with GPU acceleration.
6+
7+
This example shows how to leverage GPU acceleration with the [Skia 2D graphics library](https://skia.org). Graphics acceleration significantly increases throughput and power efficiency in many use cases, compared to CPU-based rendering. Skia is a popular modern open-source toolkit suitable for many applications. This example can also serve as a starting point if you wish to integrate Axoverlay with another graphics toolkit.
8+
9+
Together with this README file, you should be able to find a directory called app. That directory contains the "axoverlay2_skia" application source code which can easily be compiled and run with the help of the tools and step by step below.
10+
11+
For more information on Axoverlay2 API, please see the [Axis developer documentation](https://developer.axis.com/acap/reference/supported-apis/#axoverlay-2-api)
12+
13+
## Getting started
14+
15+
These instructions will guide you on how to execute the code. Below is the structure used in the example:
16+
17+
```sh
18+
axoverlay2_skia
19+
├── app
20+
│ ├── axoverlay2_skia.cc
21+
│ ├── axo2_wrappers.hh
22+
│ ├── gpu_error.hh
23+
│ ├── LICENSE
24+
│ ├── Makefile
25+
│ └── manifest.json
26+
├── Dockerfile
27+
└── README.md
28+
```
29+
30+
- **app/axoverlay2_skia.cc** - Application to draw overlays using axoverlay 2.0 and Skia in C++.
31+
- **app/axo2_wrappers.hh** - C++ wrappers for the axoverlay2 API.
32+
- **app/gpu_error.hh** - GPU error handling utilities.
33+
- **app/LICENSE** - Text file that lists all open source licensed source code distributed with the application.
34+
- **app/Makefile** - Build and link instructions for the application.
35+
- **app/manifest.json** - Defines the application and its configuration.
36+
- **Dockerfile** - Assembles an image that downloads and builds the Skia graphics library and the ACAP application using the ACAP Native SDK.
37+
- **README.md** - Step-by-step instructions on how to run the example.
38+
39+
### Supported devices
40+
41+
- ARTPEC-9, ARTPEC-8, and ARTPEC-7 based cameras and other video devices.
42+
- GPU support (OpenGL/EGL) must be available for application use on the device. Please refer to
43+
[Axis developer documentation](https://developer.axis.com/acap/api/api-compatibility-guide/) for details.
44+
45+
## Build the application
46+
47+
Standing in your working directory, run the following commands:
48+
49+
> [!NOTE]
50+
>
51+
> Depending on the network your local build machine is connected to, you may need to add proxy
52+
> settings for Docker. See
53+
> [Proxy in build time](https://developer.axis.com/acap/develop/proxy/#proxy-in-build-time).
54+
55+
```sh
56+
docker build --tag axoverlay2_skia --build-arg ARCH=<ARCH> .
57+
```
58+
59+
- `<ARCH>` is the architecture of the camera you are using, e.g., `aarch64` or `armv7hf`
60+
61+
> [!NOTE]
62+
>
63+
> The first build downloads and compiles the Skia graphics library, which takes a while. Subsequent
64+
> builds reuse the cached Skia layers, so rebuilds after editing the application source are fast.
65+
66+
Copy the result from the container image to a local directory `build`:
67+
68+
```sh
69+
docker cp $(docker create axoverlay2_skia):/opt/app ./build
70+
```
71+
72+
The built ACAP application is now available in the `build` directory. Depending on which SDK
73+
architecture was chosen, one of these files should be found:
74+
75+
- `Axoverlay2_example_Skia_application_1_0_0_aarch64.eap`
76+
- `Axoverlay2_example_Skia_application_1_0_0_armv7hf.eap`
77+
78+
> [!NOTE]
79+
>
80+
> For detailed information on how to build, install, and run ACAP applications, refer to the official ACAP documentation: [Build, install, and run](https://developer.axis.com/acap/develop/build-install-run/).
81+
82+
## Install and start the application
83+
84+
Browse to the application page of the Axis device:
85+
86+
```sh
87+
http://<AXIS_DEVICE_IP>/index.html#apps
88+
```
89+
90+
1. Click on the tab **Apps** in the device GUI
91+
2. Enable the **Allow unsigned apps** toggle
92+
3. Click the **(+ Add app)** button to upload the application file
93+
4. Select the newly built application package, depending on architecture:
94+
95+
- `axoverlay2_skia_1_0_0_aarch64.eap`
96+
- `axoverlay2_skia_1_0_0_armv7hf.eap`
97+
98+
5. Click **Install**
99+
6. Run the application by enabling the **Start** switch.
100+
101+
## Expected output
102+
103+
<img alt='A green smiley face superimposed on a picture of a roof' src="screenshot.jpg" width="500">
104+
105+
While the application is running, a rotating and colour-shifting icon should appear in the top-left
106+
corner of video streams.
107+
108+
The application log can be found directly at:
109+
110+
```sh
111+
http://<AXIS_DEVICE_IP>/axis-cgi/admin/systemlog.cgi?appname=axoverlay2_skia
112+
```
113+
114+
During normal operation, the application prints log entries for each connecting and disconnecting
115+
video stream:
116+
117+
```text
118+
axoverlay2_skia[2095]: Created overlay 1 on stream 1041, stream_size=3840x2160 overlay_used_size=135x135 overlay_full_size=136x136
119+
axoverlay2_skia[2095]: Removed overlay 1 from stream 1041
120+
```
121+
122+
In addition, the code contains some debug prints which may be enabled using the DEBUG flag found in
123+
axoverlay2_skia.cc.
124+
125+
## License
126+
127+
**[MIT](app/LICENSE)**

axoverlay2-skia/app/.gitignore

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/build_skia
2+
/axoverlay2_skia
3+
/skia
4+
/*.eap
5+
/package.conf
6+
/param.conf
7+
/*_LICENSE.txt
8+
/*.old
9+
/*.orig
10+
/tmp*
11+
/*.d
12+
/debug

axoverlay2-skia/app/LICENSE

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
MIT License
2+
3+
Copyright (c) 2026 Axis Communications AB
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.
22+
23+
================================================================================
24+
Third party licenses
25+
================================================================================
26+
27+
--------------------------------------------------------------------------------
28+
Skia license
29+
--------------------------------------------------------------------------------
30+
31+
Copyright (c) 2011 Google Inc. All rights reserved.
32+
33+
Redistribution and use in source and binary forms, with or without
34+
modification, are permitted provided that the following conditions are
35+
met:
36+
37+
* Redistributions of source code must retain the above copyright
38+
notice, this list of conditions and the following disclaimer.
39+
40+
* Redistributions in binary form must reproduce the above copyright
41+
notice, this list of conditions and the following disclaimer in
42+
the documentation and/or other materials provided with the
43+
distribution.
44+
45+
* Neither the name of the copyright holder nor the names of its
46+
contributors may be used to endorse or promote products derived
47+
from this software without specific prior written permission.
48+
49+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
50+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
51+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
52+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
53+
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
54+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
55+
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
56+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
57+
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
58+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
59+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

0 commit comments

Comments
 (0)