Skip to content

Quick Start

Get ACL Pack running in your Android arm64-v8a or Linux aarch64 project in 5 minutes.

Prerequisites

Common

  • C++17 compiler (commercial libacl.a builds with -std=c++17; your project must also be ≥ C++17)
  • An ACL Pack SDK zip for your platform (Android or Linux — sold separately)
  • license.dat shipped with the SDK (every tier, including Trial, requires it)

Android target

  • Android NDK 26.1+ (Clang toolchain)
  • arm64-v8a target device or emulator

Linux target

  • gcc-aarch64-linux-gnu 9+ (Ubuntu 20.04 ships 9.4) or an equivalent clang cross toolchain
  • aarch64 glibc target system (Jetson / RK3588 / Raspberry Pi 4+ / any ARM64 SBC running a glibc Linux distro)

Android arm64-v8a

1. Add to Your Project

Copy the SDK files into your project:

your_project/
  include/acl/                ← Copy from SDK
  lib/arm64-v8a/libacl.a      ← Copy from SDK
  your_code.cpp

2. Build Setup

Android.mk

makefile
LOCAL_PATH := $(call my-dir)

# ACL Pack static library
include $(CLEAR_VARS)
LOCAL_MODULE := acl
LOCAL_SRC_FILES := lib/$(TARGET_ARCH_ABI)/libacl.a
include $(PREBUILT_STATIC_LIBRARY)

# Your module
include $(CLEAR_VARS)
LOCAL_MODULE := your_module
LOCAL_SRC_FILES := your_code.cpp
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_STATIC_LIBRARIES := acl
LOCAL_LDLIBS := -lm
include $(BUILD_SHARED_LIBRARY)

Or CMake

cmake
add_library(acl STATIC IMPORTED)
set_target_properties(acl PROPERTIES
    IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/lib/${ANDROID_ABI}/libacl.a)

target_include_directories(your_target PRIVATE ${CMAKE_SOURCE_DIR}/include)
target_link_libraries(your_target acl m)

Or direct NDK command

bash
$NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android25-clang++ \
    -O2 -std=c++17 -Iinclude -o demo demo.cpp lib/arm64-v8a/libacl.a -lm

3. Initialize

cpp
#include <acl/acl.h>

// Call once at app startup. Every tier (Trial included) ships with its
// own license file — pass the path you received with the SDK.
int ret = acl::init("/path/to/license.dat");
if (ret != 0) {
    // Handle license error (see <acl/err.h> for codes)
}

The full init signature also accepts an optional Android JNIEnv* and jobject (application context) for installations that bind license state to the running JVM. Leave them at the default nullptr for plain native use:

cpp
namespace acl {
    int init(const char* licensePath, JNIEnv* env = nullptr, jobject context = nullptr);
    const char* version();   // returns "1.0.3"
}

Linux aarch64

1. Add to Your Project

Copy the SDK files into your project:

your_project/
  include/acl/                      ← Copy from SDK
  lib/linux-aarch64/libacl.a        ← Copy from SDK
  your_code.cpp

2. Build Setup

Direct cross-compile command (simplest)

bash
aarch64-linux-gnu-g++ \
    -O2 -std=c++17 -Iinclude \
    -o demo demo.cpp lib/linux-aarch64/libacl.a \
    -lm -lpthread

Or CMake with a toolchain file

Create toolchains/linux-aarch64.cmake:

cmake
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR aarch64)
set(CMAKE_C_COMPILER   aarch64-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER aarch64-linux-gnu-g++)
add_compile_options(-march=armv8-a)

Then in your CMakeLists.txt:

cmake
add_library(acl STATIC IMPORTED)
set_target_properties(acl PROPERTIES
    IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/lib/linux-aarch64/libacl.a)

target_include_directories(your_target PRIVATE ${CMAKE_SOURCE_DIR}/include)
target_link_libraries(your_target acl m pthread)

Configure with:

bash
cmake -DCMAKE_TOOLCHAIN_FILE=toolchains/linux-aarch64.cmake -DCMAKE_BUILD_TYPE=Release ..

3. Initialize

cpp
#include <acl/acl.h>

// Call once at app startup.
int ret = acl::init("/path/to/license.dat");
if (ret != 0) {
    // Handle license error (see <acl/err.h> for codes)
}

Linux builds can ignore the JNIEnv* / jobject parameters (default nullptr) — just pass the license path. The signature is identical to Android:

cpp
namespace acl {
    int init(const char* licensePath, JNIEnv* env = nullptr, jobject context = nullptr);
    const char* version();   // returns "1.0.3"
}

Your First API Call

Trial tier

Trial ships only 2 fixed-parameter entry points (declared in <acl/api.h> under the acl::trial:: namespace): bilinear 2× downscale — in _cpp and _neon variants. Inputs must be exactly 1920×1280 uint8 single-channel; other sizes return ACL_ERR_RESOLUTION_LIMIT (-1006). Output carries an "ACL Pack Trial" watermark.
The general-purpose API shown below applies to the Starter / Pro / Business tiers.

NEON simplified (fixed 3x3 / 5x5 / 11x11 kernels, fastest path)

cpp
#include <acl/api.h>   // all operator declarations live here

// 3x3 Gaussian blur on a 640x480 grayscale image
uint8_t* src = /* your image data */;
uint8_t* dst = new uint8_t[640 * 480];

int result = acl::neon::filter::gaussianBlur3x3(src, dst, 640, 480);
if (result != 0) {
    // Handle error (e.g. ACL_ERR_INVAL = -2 for bad parameters)
}

delete[] dst;

Full signature (all kernel sizes follow the same pattern):

cpp
int gaussianBlur3x3(const uint8_t* srcImage, uint8_t* dstImage,
                    int width, int height,
                    int srcStride = 0, int dstStride = 0,
                    uint8_t constant = 0,
                    acl::BorderType bt = acl::BorderType::BORDER_REFLECT_101);

Matching NEON entries (1-channel uint8):

  • gaussianBlur3x3, gaussianBlur5x5, gaussianBlur11x11 — same signature, different kernel size
  • gaussianBlur3x3_3ch, gaussianBlur5x5_3ch — 3-channel variants (RGB / BGR)
  • gaussianBlur(src, dst, w, h, srcStride, dstStride, kRadiusX, kRadiusY, sigmaX=0, sigmaY=0, constant=0, bt=BORDER_REFLECT_101) — generic entry for arbitrary radius / sigma (1-channel uint8 only; internally dispatches to the 3x3 / 5x5 / 11x11 fast paths when sigma=0 and the kernel size matches, otherwise falls back to sepFilter2D)

CPP generic (arbitrary radius / sigma)

cpp
#include <acl/api.h>   // same single header — scalar entry lives under acl::filter::

// 5x5 Gaussian blur with custom sigma on a 640x480 grayscale image
uint8_t* src = /* your image data */;
uint8_t* dst = new uint8_t[640 * 480];

int result = acl::filter::gaussianBlur<uint8_t, uint8_t>(
    src, dst,
    640, 480,       // width, height
    1,              // cn (channels, 1 = grayscale)
    0, 0,           // srcStride, dstStride (0 = contiguous)
    2, 2,           // kRadiusX, kRadiusY (2 = 5x5 kernel)
    1.5, 1.5,       // sigmaX, sigmaY (double)
    nullptr,        // constant (nullptr = default BORDER fill value)
    acl::BorderType::BORDER_REFLECT_101  // bt
);

delete[] dst;

The CPP variant is a portable scalar path — functionally equivalent to NEON but not vectorized.

Key Concepts

Stride

Stride is the row size in bytes. For contiguous memory, stride = width * channels * sizeof(type). Pass 0 for auto-detect.

NEON vs CPP Tier

  • acl::neon::* — ARM NEON vectorized, best performance, ARM64 only (both Android arm64-v8a and Linux aarch64)
  • acl::{module}::* — Portable C++ scalar, functionally equivalent to NEON, used for functional verification or non-vectorized fallback paths

Single header, two namespaces

Every operator declaration ships in one header — <acl/api.h>. You always #include <acl/api.h>; the namespace tells you which implementation you're calling:

  • acl::neon::{module}::op(...) → NEON vectorized
  • acl::{module}::op(...) → portable scalar (note: the namespace does not include a cpp:: segment, even though we internally call this path "the CPP layer")

Utility modules (math, utils, memory::AutoBuffer, …) are the exception and sit under acl::{module}:: (e.g. acl::memory::) without a neon:: prefix.

Kernel Radius

ACL Pack uses radius, not full kernel size:

  • Radius 1 = 3x3 kernel
  • Radius 2 = 5x5 kernel
  • Radius 3 = 7x7 kernel

Error Codes

CodeMacroMeaning
0ACL_OKSuccess
-1ACL_ERR_GENERICUnclassified failure
-2ACL_ERR_INVALInvalid argument (null pointer, zero size, out-of-range enum)
-3ACL_ERR_NOMEMOut of memory / allocation failed
-4ACL_ERR_NOSUPUnsupported type / parameter combination
-5ACL_ERR_IOFile / port open or I/O failure
-1005ACL_ERR_NOT_LICENSEDOperator not available in the current tier
-1006ACL_ERR_RESOLUTION_LIMITResolution does not match the Trial fixed size (1920×1280)

Full error-code definitions: <acl/err.h> or the API Reference.

Next Steps