From ebc117cdc46148f878af0cf0bdd09b2829b2626f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?William=20B=C3=A9rub=C3=A9?= Date: Fri, 30 Aug 2024 07:15:30 -0400 Subject: [PATCH] Starting to work on AK3918 support --- README.md | 1 + src/hal/plus/ak_aud.h | 61 +++++++++++++++++++++++ src/hal/plus/ak_common.h | 13 +++++ src/hal/plus/ak_venc.h | 105 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 180 insertions(+) create mode 100644 src/hal/plus/ak_aud.h create mode 100644 src/hal/plus/ak_common.h create mode 100644 src/hal/plus/ak_venc.h diff --git a/README.md b/README.md index b987aed..47ffb75 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ In spite of these design choices, Divinus boasts numerous features that cater to | SoC Family | Audio Stream | JPEG Snapshot | fMP4 Stream | RTSP Stream | On-Screen Display* | |-------------------------|:------------:|:-------------:|:-----------:|:-----------:|:------------------:| +| AK3918 | ↻ | ↻ | ↻ | ↻ | ↻ | | CV181x[^1] | ↻ | ↻ | ↻ | ↻ | ↻ | | GM813x[^2] | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | | Hi3516AV100[^3] | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | diff --git a/src/hal/plus/ak_aud.h b/src/hal/plus/ak_aud.h new file mode 100644 index 0000000..8a7b50e --- /dev/null +++ b/src/hal/plus/ak_aud.h @@ -0,0 +1,61 @@ +#pragma once + +#include "ak_common.h" + +typedef struct { + unsigned int rate; + unsigned int bit; + unsigned int chnNum; +} ak_aud_cnf; + +typedef struct { + unsigned char *data; + unsigned int length; + unsigned long long timestamp; + unsigned long sequence; +} ak_aud_frm; + +typedef struct { + void *handle; + + int (*fnDisableDevice)(void *device); + void* (*fnEnableDevice)(ak_aud_cnf *config); + + int (*fnSetVolume)(void *device, int level); + + int (*fnFreeFrame)(void *device, ak_aud_frm *frame); + int (*fnGetFrame)(void *device, ak_aud_frm *frame, int millis); +} ak_aud_impl; + +static int ak_aud_load(ak_aud_impl *aud_lib) { + if (!(aud_lib->handle = dlopen("libplat_ai.so", RTLD_LAZY | RTLD_GLOBAL))) + HAL_ERROR("ak_aud", "Failed to load library!\nError: %s\n", dlerror()); + + if (!(aud_lib->fnDisableDevice = (int(*)(void* device)) + hal_symbol_load("ak_aud", aud_lib->handle, "ak_ai_close"))) + return EXIT_FAILURE; + + if (!(aud_lib->fnEnableDevice = (void*(*)(ak_aud_cnf *config)) + hal_symbol_load("ak_aud", aud_lib->handle, "ak_ai_open"))) + return EXIT_FAILURE; + + if (!(aud_lib->fnSetVolume = (int(*)(void *device, int level)) + hal_symbol_load("ak_aud", aud_lib->handle, "ak_ai_set_volume"))) + return EXIT_FAILURE; + + if (!(aud_lib->fnFreeFrame = (int(*)(void *device, ak_aud_frm *frame)) + hal_symbol_load("ak_aud", aud_lib->handle, "ak_ai_release_frame"))) + return EXIT_FAILURE; + + if (!(aud_lib->fnGetFrame = (int(*)(void *device, ak_aud_frm *frame, int millis)) + hal_symbol_load("ak_aud", aud_lib->handle, "ak_ai_get_frame"))) + return EXIT_FAILURE; + + return EXIT_SUCCESS; +} + +static void ak_aud_unload(ak_aud_impl *aud_lib) { + if (aud_lib->handle) dlclose(aud_lib->handle); + aud_lib->handle = NULL; + memset(aud_lib, 0, sizeof(*aud_lib)); +} \ No newline at end of file diff --git a/src/hal/plus/ak_common.h b/src/hal/plus/ak_common.h new file mode 100644 index 0000000..8baa217 --- /dev/null +++ b/src/hal/plus/ak_common.h @@ -0,0 +1,13 @@ +#pragma once + +#include +#include +#include + +#include "../symbols.h" +#include "../types.h" + +typedef struct { + int width; + int height; +} ak_common_dim; \ No newline at end of file diff --git a/src/hal/plus/ak_venc.h b/src/hal/plus/ak_venc.h new file mode 100644 index 0000000..0cb5f1d --- /dev/null +++ b/src/hal/plus/ak_venc.h @@ -0,0 +1,105 @@ +#pragma once + +#include "ak_common.h" + +typedef enum { + AK_VENC_CODEC_H264, + AK_VENC_CODEC_MJPG, + AK_VENC_CODEC_H265 +} ak_venc_codec; + +typedef enum { + AK_VENC_NALU_PSLICE, + AK_VENC_NALU_ISLICE, + AK_VENC_NALU_BSLICE, + AK_VENC_NALU_PISLICE +} ak_venc_nalu; + +typedef enum { + AK_VENC_OUT_RECORD, + AK_VENC_OUT_MAINSTRM, + AK_VENC_OUT_SUBSTRM, + AK_VENC_OUT_SNAP, + AK_VENC_OUT_END +} ak_venc_out; + +typedef enum { + AK_VENC_PROF_MAIN, + AK_VENC_PROF_HIGH, + AK_VENC_PROF_BASELINE, + AK_VENC_PROF_HEVC_MAIN, + AK_VENC_PROF_HEVC_MAINSTILL, + AK_VENC_PROF_END +} ak_venc_prof; + +typedef struct { + unsigned long width; + unsigned long height; + long minQual; + long maxQual; + long dstFps; + long gop; + long maxBitrate; + ak_venc_prof profile; + int subChnOn; + ak_venc_out output; + int vbrModeOn; + ak_venc_codec codec; +} ak_venc_cnf; + +typedef struct { + unsigned char *data; + unsigned int length; + unsigned long long timestamp; + unsigned long sequence; + ak_venc_nalu naluType; +} ak_venc_strm; + +typedef struct { + void *handle; + + void* (*fnBindChannel)(void *input, void *output); + int (*fnDisableChannel)(void *channel); + void* (*fnEnableChannel)(ak_venc_cnf *config); + int (*fnUnbindChannel)(void *bind); + + int (*fnFreeStream)(void *bind, ak_venc_strm *stream); + int (*fnGetStream)(void *bind, ak_venc_strm *stream); +} ak_venc_impl; + +static int ak_venc_load(ak_venc_impl *venc_lib) { + if (!(venc_lib->handle = dlopen("libmpi_venc.so", RTLD_LAZY | RTLD_GLOBAL))) + HAL_ERROR("ak_venc", "Failed to load library!\nError: %s\n", dlerror()); + + if (!(venc_lib->fnBindChannel = (void*(*)(void *input, void *output)) + hal_symbol_load("ak_venc", venc_lib->handle, "ak_venc_request_stream"))) + return EXIT_FAILURE; + + if (!(venc_lib->fnDisableChannel = (int(*)(void* channel)) + hal_symbol_load("ak_venc", venc_lib->handle, "ak_venc_close"))) + return EXIT_FAILURE; + + if (!(venc_lib->fnEnableChannel = (void*(*)(ak_venc_cnf *config)) + hal_symbol_load("ak_venc", venc_lib->handle, "ak_venc_open"))) + return EXIT_FAILURE; + + if (!(venc_lib->fnUnbindChannel = (int(*)(void *bind)) + hal_symbol_load("ak_venc", venc_lib->handle, "ak_venc_cancel_stream"))) + return EXIT_FAILURE; + + if (!(venc_lib->fnFreeStream = (int(*)(void *bind, ak_venc_strm *stream)) + hal_symbol_load("ak_venc", venc_lib->handle, "ak_venc_release_stream"))) + return EXIT_FAILURE; + + if (!(venc_lib->fnGetStream = (int(*)(void *bind, ak_venc_strm *stream)) + hal_symbol_load("ak_venc", venc_lib->handle, "ak_venc_get_stream"))) + return EXIT_FAILURE; + + return EXIT_SUCCESS; +} + +static void ak_venc_unload(ak_venc_impl *venc_lib) { + if (venc_lib->handle) dlclose(venc_lib->handle); + venc_lib->handle = NULL; + memset(venc_lib, 0, sizeof(*venc_lib)); +} \ No newline at end of file