initial commit.
This commit is contained in:
commit
cd788ded0a
17
.clang-format
Normal file
17
.clang-format
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
BasedOnStyle: LLVM
|
||||||
|
|
||||||
|
ObjCBlockIndentWidth: 4
|
||||||
|
IndentWidth: 4
|
||||||
|
TabWidth: 4
|
||||||
|
AccessModifierOffset: -4
|
||||||
|
ColumnLimit: 130
|
||||||
|
|
||||||
|
#模板声明后换行
|
||||||
|
AlwaysBreakTemplateDeclarations: true
|
||||||
|
|
||||||
|
# 是否允许短if单行 If true, if (a) return; 可以放到同一行
|
||||||
|
AllowShortIfStatementsOnASingleLine: true
|
||||||
|
|
||||||
|
#短句 while (true) continue; 能被放到单行。
|
||||||
|
AllowShortLoopsOnASingleLine: true
|
||||||
|
AllowShortFunctionsOnASingleLine: false
|
41
.gitignore
vendored
Normal file
41
.gitignore
vendored
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
# C++ objects and libs
|
||||||
|
*.slo
|
||||||
|
*.lo
|
||||||
|
*.o
|
||||||
|
*.a
|
||||||
|
*.la
|
||||||
|
*.lai
|
||||||
|
*.so
|
||||||
|
*.dll
|
||||||
|
*.dylib
|
||||||
|
|
||||||
|
# Qt-es
|
||||||
|
object_script.*.Release
|
||||||
|
object_script.*.Debug
|
||||||
|
*_plugin_import.cpp
|
||||||
|
/.qmake.cache
|
||||||
|
/.qmake.stash
|
||||||
|
*.pro.user
|
||||||
|
*.pro.user.*
|
||||||
|
*.qbs.user
|
||||||
|
*.qbs.user.*
|
||||||
|
*.moc
|
||||||
|
moc_*.h
|
||||||
|
*.qmlc
|
||||||
|
*.jsc
|
||||||
|
Makefile*
|
||||||
|
*build-*
|
||||||
|
|
||||||
|
# Qt unit tests
|
||||||
|
target_wrapper.*
|
||||||
|
|
||||||
|
# QtCreator
|
||||||
|
*.autosave
|
||||||
|
|
||||||
|
# QtCreator Qml
|
||||||
|
*.qmlproject.user
|
||||||
|
*.qmlproject.user.*
|
||||||
|
|
||||||
|
# QtCreator CMake
|
||||||
|
CMakeLists.txt.user*
|
||||||
|
build
|
23
.vscode/c_cpp_properties.json
vendored
Normal file
23
.vscode/c_cpp_properties.json
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Linux",
|
||||||
|
"includePath": [
|
||||||
|
"${workspaceFolder}/**",
|
||||||
|
"/opt/Libraries/boost_1_84_0/include",
|
||||||
|
"${workspaceFolder}/3rdparty/arm-linux-gnueabihf/mpp/inc",
|
||||||
|
"/opt/toolchains/Libraries/opus-1.4/include",
|
||||||
|
"ThirdParty/libjpegTurbo/inc",
|
||||||
|
"ThirdParty/libalsa/inc",
|
||||||
|
"${workspaceFolder}/build/_deps/kylin-src/Universal",
|
||||||
|
"${workspaceFolder}/build/_deps/kylin-src/HttpProxy"
|
||||||
|
],
|
||||||
|
"defines": [],
|
||||||
|
"compilerPath": "/usr/bin/gcc",
|
||||||
|
"cStandard": "c17",
|
||||||
|
"cppStandard": "gnu++17",
|
||||||
|
"intelliSenseMode": "linux-gcc-x64"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version": 4
|
||||||
|
}
|
30
.vscode/launch.json
vendored
Normal file
30
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
{
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "FaceAccessDebug",
|
||||||
|
"type": "cppdbg",
|
||||||
|
"request": "launch",
|
||||||
|
"miDebuggerPath": "arm-linux-gnueabihf-gdb",
|
||||||
|
"miDebuggerServerAddress": "192.168.8.122:8080",
|
||||||
|
"program": "${workspaceFolder}/build/src/gate_face/GateFace",
|
||||||
|
"args": [],
|
||||||
|
"stopAtEntry": false,
|
||||||
|
"cwd": "${workspaceFolder}",
|
||||||
|
"environment": [],
|
||||||
|
"externalConsole": false,
|
||||||
|
"logging": {
|
||||||
|
"engineLogging": false
|
||||||
|
},
|
||||||
|
"MIMode": "gdb",
|
||||||
|
"useExtendedRemote": true,
|
||||||
|
"setupCommands": [
|
||||||
|
{
|
||||||
|
"text": "set remote exec-file /sdcard/GateFace",
|
||||||
|
"description": "设置嵌入式单板加载的程序",
|
||||||
|
"ignoreFailures": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
4
.vscode/settings.json
vendored
Normal file
4
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"editor.formatOnSaveMode": "modificationsIfAvailable",
|
||||||
|
"editor.formatOnSave": false,
|
||||||
|
}
|
32
CMakeLists.txt
Normal file
32
CMakeLists.txt
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
project(FaceAccess)
|
||||||
|
cmake_minimum_required(VERSION 3.27)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
|
set(OPENSSL_ROOT /opt/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/openssl-1.0.2q)
|
||||||
|
set(OPENSSL_INCLUDE_DIR ${OPENSSL_ROOT}/include)
|
||||||
|
|
||||||
|
set(ALSA_ROOT /opt/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/libalsa-1.1.5)
|
||||||
|
set(ALSA_INCLUDE_DIR ${ALSA_ROOT}/include)
|
||||||
|
set(ALSA_LIBRARY_DIRS ${ALSA_ROOT}/lib)
|
||||||
|
|
||||||
|
set(FFMPEG_ROOT /opt/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/ffmpeg-4.1.3)
|
||||||
|
set(FFMPEG_INCLUDE_DIR ${FFMPEG_ROOT}/include)
|
||||||
|
set(FFMPEG_LIBRARY_DIRS ${FFMPEG_ROOT}/lib)
|
||||||
|
set(FFMPEG_LIBRARY avcodec avdevice avfilter avformat avutil postproc swresample swscale)
|
||||||
|
|
||||||
|
set(MPP_ROOT /opt/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/rockchip_mpp)
|
||||||
|
set(MPP_INCLUDE_DIR ${MPP_ROOT}/include)
|
||||||
|
set(MPP_LIBRARY_DIRS ${MPP_ROOT}/rk-libs)
|
||||||
|
|
||||||
|
|
||||||
|
include(FetchContent)
|
||||||
|
FetchContent_Declare(Kylin
|
||||||
|
GIT_REPOSITORY https://gitea.amass.fun/amass/Kylin.git
|
||||||
|
)
|
||||||
|
FetchContent_MakeAvailable(Kylin)
|
||||||
|
|
||||||
|
add_subdirectory(GatePass)
|
||||||
|
add_subdirectory(Record)
|
||||||
|
add_subdirectory(VoucherVerifyServer)
|
12
GatePass/CMakeLists.txt
Normal file
12
GatePass/CMakeLists.txt
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
|
find_package(Boost REQUIRED COMPONENTS json)
|
||||||
|
|
||||||
|
add_executable(GatePass
|
||||||
|
main.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(GatePass
|
||||||
|
PRIVATE Universal
|
||||||
|
)
|
54
GatePass/main.cpp
Normal file
54
GatePass/main.cpp
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
#include "BoostLog.h"
|
||||||
|
#include <boost/asio.hpp>
|
||||||
|
#include <boost/json.hpp>
|
||||||
|
#include <chrono>
|
||||||
|
#include <iostream>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
using boost::asio::ip::udp;
|
||||||
|
|
||||||
|
int main(int argc, char const *argv[]) {
|
||||||
|
boost::log::initialize("/data/sdcard/logs/GatePass", "/data/sdcard/logs");
|
||||||
|
LOG(info) << "app start...";
|
||||||
|
std::cout << "hello word." << std::endl;
|
||||||
|
|
||||||
|
constexpr auto txt = R"({"cmd":"gate_status","status":1,"personIn":11638,"personOut":5123,"runCount":115370})";
|
||||||
|
|
||||||
|
constexpr auto txt1 = R"({"cmd":"gate_status","status":2,"personIn":-12345,"personOut":-12345,"runCount":115370})";
|
||||||
|
|
||||||
|
constexpr auto error = R"({"cmd":"fault_and_alarm","code":91})";
|
||||||
|
|
||||||
|
constexpr auto error1 = R"({"cmd":"fault_and_alarm","code":96})";
|
||||||
|
|
||||||
|
try {
|
||||||
|
// if (argc != 2) {
|
||||||
|
// std::cerr << "Usage: client <host>" << std::endl;
|
||||||
|
// return 1;
|
||||||
|
// }
|
||||||
|
|
||||||
|
udp::endpoint point(udp::v4(), 6787);
|
||||||
|
|
||||||
|
boost::asio::io_context io_context;
|
||||||
|
|
||||||
|
udp::socket socket(io_context);
|
||||||
|
socket.open(udp::v4());
|
||||||
|
|
||||||
|
socket.send_to(boost::asio::buffer(std::string(txt)), point);
|
||||||
|
LOG(info) << "udp send: " << txt;
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(150));
|
||||||
|
socket.send_to(boost::asio::buffer(std::string(error)), point);
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(150));
|
||||||
|
socket.send_to(boost::asio::buffer(std::string(error1)), point);
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(150));
|
||||||
|
socket.send_to(boost::asio::buffer(std::string(txt1)), point);
|
||||||
|
|
||||||
|
} catch (std::exception &e) {
|
||||||
|
std::cerr << e.what() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
469
Readme.md
Normal file
469
Readme.md
Normal file
@ -0,0 +1,469 @@
|
|||||||
|
|
||||||
|
```shell
|
||||||
|
amixer sset 'Master' 50% # 设置音量
|
||||||
|
mount -o remount rw /system/ # 读写挂载
|
||||||
|
keydata get mac # 操作mac
|
||||||
|
keydata set mac 6C:5C:3D:B2:27:78
|
||||||
|
keydata set hardware HW00000011C3000R -f
|
||||||
|
MAC存储位置:/data/.mac
|
||||||
|
|
||||||
|
ps -ef | egrep start-app.sh | grep -v grep | awk '{print $2}' | xargs kill -9 2 > /dev/null
|
||||||
|
|
||||||
|
ps -ef | egrep dk_uart_id_reader | grep -v grep | awk '{print $2}' | xargs kill -9 2 > /dev/null
|
||||||
|
|
||||||
|
killall start-app.sh && killall GateFace
|
||||||
|
killall dk_uart_id_reader
|
||||||
|
tail -f /sdcard/logs/b020.log
|
||||||
|
|
||||||
|
|
||||||
|
mount -o remount rw /system/ && mv /system/bin/start-app.sh /system/bin/start-app.sh.bak
|
||||||
|
mount -o remount rw /system/ && mv /system/bin/start-app.sh.bak /system/bin/start-app.sh
|
||||||
|
echo 1 > /dev/watchdog
|
||||||
|
|
||||||
|
dk_uart_id_reader
|
||||||
|
|
||||||
|
keydata set hardware HW00000011C3000U -f
|
||||||
|
keydata get hardware
|
||||||
|
|
||||||
|
|
||||||
|
/etc/init.d/S97_lunch_init
|
||||||
|
```
|
||||||
|
|
||||||
|
`script/start-app.sh`有个`write_mac()`函数生成`/data/.mac`文件。
|
||||||
|
|
||||||
|
|
||||||
|
## 隐藏页面参数设置
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
http://192.168.8.120/otherPage.php?cmd=get_other_page_params
|
||||||
|
|
||||||
|
http://192.168.8.120/otherPage.php?cmd=set_other_page_params&distanceType=1&distance=1&dynamicFeatSimTh=70&dynamicFeatImgQualityTh=90&fast_temp_sw=true&save_reg_img_sw=true&audio_out_enabled=true
|
||||||
|
```
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"cmd": "set_other_page_params",
|
||||||
|
"distanceType": 1,
|
||||||
|
"save_reg_img_sw": true,
|
||||||
|
"fast_temp_sw": true,
|
||||||
|
"dynamicFeatSimTh": 70,
|
||||||
|
"dynamicFeatImgQualityTh": 90,
|
||||||
|
"audio_out_enabled": true
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
"ret": 0,
|
||||||
|
"code": 200,
|
||||||
|
"message": "OK",
|
||||||
|
"data": {
|
||||||
|
"distanceType": 1,
|
||||||
|
"distance": 100,
|
||||||
|
"dynamicFeatSimTh": 70,
|
||||||
|
"dynamicFeatImgQualityTh": 90,
|
||||||
|
"fast_temp_sw": true,
|
||||||
|
"save_reg_img_sw": true,
|
||||||
|
"audio_out_enabled": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## FacePass平台交互
|
||||||
|
|
||||||
|
### 连接不成功,UI上图标不对
|
||||||
|
|
||||||
|
```c++
|
||||||
|
void statusbarUi::updatePlatformConnectionStatus(const int status)
|
||||||
|
{
|
||||||
|
QPixmap pm;
|
||||||
|
switch(status)
|
||||||
|
{
|
||||||
|
case UiInterfaceForBackstage::PLATFORM_CONNECTION_STATUS_DISCONNECTED:
|
||||||
|
pm.load(":/res/image/disconnect.png");
|
||||||
|
break;
|
||||||
|
case UiInterfaceForBackstage::PLATFORM_CONNECTION_STATUS_CONNECTED:
|
||||||
|
pm.load(":/res/image/display.png");
|
||||||
|
break;
|
||||||
|
case UiInterfaceForBackstage::PLATFORM_CONNECTION_STATUS_LOGGED:
|
||||||
|
pm.load(":/res/image/display.png");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
m_label_platform->setPixmap(pm.scaled(20, 20, Qt::KeepAspectRatio));
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 测试/开发帐号
|
||||||
|
|
||||||
|
设备业务服务器地址统一都为9002。
|
||||||
|
|
||||||
|
- FacePass开发地址:http://172.16.7.16/
|
||||||
|
|
||||||
|
- 账号:luocai
|
||||||
|
|
||||||
|
- 密码:.Luo19961030
|
||||||
|
|
||||||
|
- 管理员账号:admin
|
||||||
|
|
||||||
|
- 管理员密码:Reconova_123456
|
||||||
|
|
||||||
|
|
||||||
|
- 可视对讲(阳江博物馆项目):https://172.16.100.22/
|
||||||
|
- 账号:admin
|
||||||
|
- 密码:Reconova_123456
|
||||||
|
|
||||||
|
## 人脸识别函数调用
|
||||||
|
|
||||||
|
相关模块初始化:
|
||||||
|
|
||||||
|
```c++
|
||||||
|
GoThread::taskProc(); // 初始化摄像头
|
||||||
|
FaceGate::preLoad(); // 等待摄像头初始化完成
|
||||||
|
FaceGate::taskProc(); // 初始化算法
|
||||||
|
|
||||||
|
AntiSpoof4Rv1109::init();
|
||||||
|
AttrDetector4Rv1109::init()
|
||||||
|
DetectorImpl4Rv1109::init()
|
||||||
|
LandmarkDetectorRk::init()
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
classDiagram
|
||||||
|
RwRecoResult
|
||||||
|
GRecoID --|> GObject
|
||||||
|
GRecoID --* RecoIDInfo
|
||||||
|
|
||||||
|
detector
|
||||||
|
attr_detector
|
||||||
|
landmark_detector
|
||||||
|
anti_spoof
|
||||||
|
GTrackerMng *-- AntiSpoof
|
||||||
|
GTrackerMng *-- LandmarkDetector
|
||||||
|
GDetectorHeadAttr *-- AttrDetector
|
||||||
|
AntiSpoof4Rv1109 ..|> AntiSpoof
|
||||||
|
LandmarkDetectorRk ..|> LandmarkDetector
|
||||||
|
AttrDetector4Rv1109 ..|> AttrDetector
|
||||||
|
GObject <|-- GTrackerLock
|
||||||
|
GDetectorTracker *-- Detector
|
||||||
|
RecoAlgorithm *-- Detector
|
||||||
|
RecoAlgorithm *-- LandmarkDetector
|
||||||
|
|
||||||
|
ParamManage --* GoThread
|
||||||
|
UdpServer --* GoThread
|
||||||
|
GCamera --* GoThread
|
||||||
|
GDetectorTracker --* GoThread
|
||||||
|
GTrackerMng --* GoThread
|
||||||
|
GTrackerLock --* GoThread
|
||||||
|
GDetectorHeadAttr --* GoThread
|
||||||
|
GReco1vsN --* GoThread
|
||||||
|
GReco1vs1 --* GoThread
|
||||||
|
GRecoID --* GoThread
|
||||||
|
GPeInput --* GoThread
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
逻辑实现都在`src/workflow/output/decision_actuator/decision_actuator.h`
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart TB
|
||||||
|
A["ADMsg::showDisplayMsg()"]
|
||||||
|
B["View::showRecoSuccess()"]
|
||||||
|
C["GDecisionActuator::showRecoResult()"]
|
||||||
|
D["GDecisionCenter::maskProc()"]
|
||||||
|
D-->C-->B-->A
|
||||||
|
```
|
||||||
|
|
||||||
|
## 人证核验逻辑
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart TB
|
||||||
|
A-->B-->C-->D-->E-->F-->G
|
||||||
|
F-->H-->I-->J
|
||||||
|
|
||||||
|
A["UDPIDCardReader::detect()"]
|
||||||
|
B["IdReader::isNewCardAvailable()"]
|
||||||
|
C["IdReader::polling()"]
|
||||||
|
D["Peripheral::idPolling()"]
|
||||||
|
E["ReaderThread::taskProc()"]
|
||||||
|
F["ReaderThread::readerInputAvailNoti()"]
|
||||||
|
G["GPeInput::readerInputAvailCallback()"]
|
||||||
|
H["GPeInput::idReaderCallback()"]
|
||||||
|
I["GDecisionCenter::idCardReaded()"]
|
||||||
|
J["GDecisionCenter::_idCardProc()"]
|
||||||
|
```
|
||||||
|
|
||||||
|
recoUi::slotShowSceneResult()
|
||||||
|
recoUiRecognize::slotsDrawScanner()
|
||||||
|
mainUi::notifyFaceInfo()
|
||||||
|
|
||||||
|
`recoUi::slotTimer()`负责将结果页面切回待机页面
|
||||||
|
|
||||||
|
|
||||||
|
### 人证核验限制
|
||||||
|
|
||||||
|
```
|
||||||
|
http://192.168.8.127/deviceAction.php?mask_check_sw=false&no_mask_no_entry=true&mask_no_entry=false&temp_check_sw=true&temp_anomaly_no_entry=true&min=35&max=37.3&sw=false&temp_unit=0&temp_type=1&temp_audio_sw=false&temp_show_sw=true&sim_th=0&reco_distance_type=3&face_sw=true&reco_from=1&fast_access_sw=false&ic_card_sw=false&face_and_id_sw=true&yuejuma=false&succ_interval=3&fail_interval=1&helmet_sw=false&dynamic_feature=false&face_frame_sw=false&dev_local_pwd_type=1&dev_local_pwd=&health_code_sw=false&health_code_allow_stranger_sw=false&health_code_allow_access_color=1&health_code_allow_access_c19t=4&health_code_allow_access_trip=0&health_code_allow_access_abt=0&travel_card_sw=false&disable_face_sw=false&health_code_needed_tip_type=0&health_trip_fail_times=3&health_trip_need_id_sw=false&health_ui_display_time=3&access_condition=[0,1]&light_and_background=[1,1,0,0,2]&health_check_phone_num_sw=false&health_ok_display_time=3&health_white_list_free_sw=false&health_code_c19t_hours_limit=0&health_trip_show_tip_sw=false&disable_dev_setting_sw=false&temp_sensitivity=0.75&cmd=set_device&face_id_card_verify_rule={"age_limit":{"enabled":true,"precision":2,"range":[{"from":40,"to":60},{"from":30,"to":-1},{"from":-1,"to":70}]},"zone_limit":{"enabled":true,"range":["14512","78945","31103"]}}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 第三方票务平台注册
|
||||||
|
|
||||||
|
```
|
||||||
|
GDecisionCenter::ReconfirmReq
|
||||||
|
RWProtocol::sendRequestOpenDoorReconfirm()
|
||||||
|
UdpParse::voucher_verify_result_proc()
|
||||||
|
RWProtocol::voucherVerifyProc()
|
||||||
|
|
||||||
|
## 读取到身份证之后
|
||||||
|
GDecisionCenter::idCardReaded()
|
||||||
|
GRecoID::onIDCard() 保存图标
|
||||||
|
ReaderInfo 保存了nv21的图像编码
|
||||||
|
GDecisionCenter::m_idInfo 保存了nv21的图像编码
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 闸机
|
||||||
|
|
||||||
|
### 故障上报
|
||||||
|
|
||||||
|
| 功能列表 | 类别 | |
|
||||||
|
| -------------------- | ------ | -------------- |
|
||||||
|
| 闸机主机电机故障 | 故障类 | 0x21+100=133 |
|
||||||
|
| 闸机副机电机故障 | 故障类 | 0x22+100=134 |
|
||||||
|
| 闸机主机离合器故障 | 故障类 | 2003+100= 2103 |
|
||||||
|
| 闸机副机离合器故障 | 故障类 | 2004+100=2104 |
|
||||||
|
| 闸机持续开闸信号故障 | 故障类 | 0x5A+100=190 |
|
||||||
|
| 闸机红外故障 | 故障类 | 0x5B+100=191 |
|
||||||
|
| 闸机遇阻停机故障 | 故障类 | 0x0A+100=110 |
|
||||||
|
| 闸机自检失败故障 | 故障类 | 0x23+100=135 |
|
||||||
|
| 闸机固件升级失败 | 故障类 | 1001+100=1104 |
|
||||||
|
| 闸机消防告警 | 告警类 | 0x04+100=104 |
|
||||||
|
| 闸机门长久未关告警 | 告警类 | 0x5C+100=192 |
|
||||||
|
| 人员强闯告警 | 告警类 | 0x60+100=196 |
|
||||||
|
| 人员非法推杆告警 | 告警类 | 2001+100=2101 |
|
||||||
|
| 人员逆行告警 | 告警类 | 0x61+100=197 |
|
||||||
|
| 人员尾随告警 | 告警类 | 0x62+100=198 |
|
||||||
|
| 人员逗留告警 | 告警类 | 0x5F+100=195 |
|
||||||
|
|
||||||
|
### 通行记录
|
||||||
|
|
||||||
|
```protobuf
|
||||||
|
//index=593 设备上报人员通过闸机事件
|
||||||
|
message PersonAccessedReport{
|
||||||
|
Common base=1;
|
||||||
|
string alarmId=2; //消息id
|
||||||
|
int64 recordId=3; //记录id
|
||||||
|
string timestamp=4;//时间戳,格式:"yyyy-MM-dd HH:mm:ss" 举例 "2023-11-30 11:32:45"
|
||||||
|
int32 direction=5;//方向,1:进,2:出
|
||||||
|
}
|
||||||
|
|
||||||
|
//index=594 平台应答人员通过闸机事件
|
||||||
|
message ReplyPersonAccessedReport {
|
||||||
|
Common base=1;
|
||||||
|
string alarmId=2; //消息id
|
||||||
|
int64 recordId=3; //记录id
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
参考人脸通行记录
|
||||||
|
|
||||||
|
```
|
||||||
|
createAccessRecord
|
||||||
|
setAccessRecordsUploadStaByRecordIdRang
|
||||||
|
deleteAccessRecordByRecordId
|
||||||
|
getAccessRecordsNumByUploadSta
|
||||||
|
|
||||||
|
|
||||||
|
GPeInput::rs485DataProc 处理闸机进出
|
||||||
|
|
||||||
|
createGateAccessRecord
|
||||||
|
|
||||||
|
# upload thread
|
||||||
|
bool checkIfSendAccessInfoData(long long curSysSec);
|
||||||
|
int pushAccessInfoListToSrv(long long curSysSec);
|
||||||
|
int uploadAccessInfo(long long curSysSec);
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## netconfig网络管理
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
classDiagram
|
||||||
|
NetConfigThread --> NetConfig
|
||||||
|
NetConfig --> Linker
|
||||||
|
EthLinker ..|> Linker
|
||||||
|
WlanLinker ..|> Linker
|
||||||
|
SIMLinker ..|> Linker
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
wifi_connect 连接wifi耗时过长
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## UI组织
|
||||||
|
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
---
|
||||||
|
title: FaceGate UI
|
||||||
|
---
|
||||||
|
classDiagram
|
||||||
|
View *-- Backstage
|
||||||
|
View *-- mainUi
|
||||||
|
mainUi ..|> UiInterfaceForBackstage
|
||||||
|
mainUi *-- SetupUi
|
||||||
|
mainUi *-- settingUi
|
||||||
|
mainUi *-- recoUi
|
||||||
|
recoUi *-- recoUiRecognize
|
||||||
|
recoUi *-- recoUiRecognizeTypeColor
|
||||||
|
recoUi *-- recoUiRecognizeTypeAd
|
||||||
|
recoUi *-- recoUiScreensaver
|
||||||
|
recoUi *-- recoUiPassword
|
||||||
|
recoUi *-- recoUiHealthCode
|
||||||
|
recoUi *-- recoUiSceneResult
|
||||||
|
|
||||||
|
class View {
|
||||||
|
viewInitBackstage();
|
||||||
|
viewCreateUi();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
### SetupUi
|
||||||
|
|
||||||
|
仅当`/data/config/need_setup_wizard`文件存在时显示,流程完成时再删除此文件。
|
||||||
|
|
||||||
|
### settingUi
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
classDiagram
|
||||||
|
SettingUiPage --|> MyWidgetWithMainStyleColor
|
||||||
|
settingUiDevMngNetWifi --|> SettingUiPage
|
||||||
|
settingUiDevMngNetWifiAccPoint --|> SettingUiPage
|
||||||
|
SettingUiPage *-- QListWidget
|
||||||
|
myListWidget --|> QWidget
|
||||||
|
```
|
||||||
|
|
||||||
|
### recoUi
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
classDiagram
|
||||||
|
SceneMsgWidget --|> QWidget
|
||||||
|
MsgWidget --|> QWidget
|
||||||
|
recoUiSceneResult *-- SceneMsgWidget
|
||||||
|
recoUi *-- recoUiSceneResult
|
||||||
|
recoUiRecognize --|> PageAcceptMouseAndTouch
|
||||||
|
PageAcceptMouseAndTouch --|> WidgetWithBackstageInterface
|
||||||
|
recoUiRecognize *-- PersonWidget
|
||||||
|
recoUiRecognizeTypeBase *-- MsgWidget
|
||||||
|
recoUiRecognizeTypeBase --|> PageAcceptMouseAndTouch
|
||||||
|
recoUiRecognizeTypeColor --|> recoUiRecognizeTypeBase
|
||||||
|
recoUiRecognizeTypeAd --|> recoUiRecognizeTypeBase
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 硬件、固件版本说明
|
||||||
|
|
||||||
|
硬件版本说明: http://wiki.reconova.cn/pages/viewpage.action?pageId=36798802
|
||||||
|
|
||||||
|
### B045 CI构建包存放地址
|
||||||
|
|
||||||
|
```
|
||||||
|
\\172.16.2.222\瑞为版本\Test\shop\B045
|
||||||
|
```
|
||||||
|
|
||||||
|
### 测试机信息记录
|
||||||
|
|
||||||
|
扫码枪:
|
||||||
|
|
||||||
|
```
|
||||||
|
/dev/hidraw0
|
||||||
|
```
|
||||||
|
|
||||||
|
万睿面板机
|
||||||
|
|
||||||
|
```json
|
||||||
|
// MAC 6C:5C:3D:B2:27:81
|
||||||
|
{
|
||||||
|
"mt": 98,
|
||||||
|
"ct": "HWA0310722C1110W",
|
||||||
|
"mac": "6C5C3DB22781",
|
||||||
|
"id": "412d00003263",
|
||||||
|
"key": "412d9f3500c79fb3",
|
||||||
|
"sct": "b42f6f643aedaf00"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
B045 V05带屏幕
|
||||||
|
|
||||||
|
```json
|
||||||
|
{"mt": 98,"ct": "HWA0310722C1110U","mac": "6C5C3DB229A0"}
|
||||||
|
|
||||||
|
keydata set hardware HWA0310722C1110W -f
|
||||||
|
```
|
||||||
|
|
||||||
|
B033 V05裸板
|
||||||
|
|
||||||
|
```json
|
||||||
|
// MAC 6C:5C:3D:B2:27:82
|
||||||
|
|
||||||
|
{
|
||||||
|
"mt": 98,
|
||||||
|
"ct": "HW00000011C3000U",
|
||||||
|
"mac": "6C5C3DB22782",
|
||||||
|
"id": "6c5c3db22782",
|
||||||
|
"key": "6d711a5543353b5a",
|
||||||
|
"sct": "06b619feadfae838"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
B026啪啪运动裸板
|
||||||
|
|
||||||
|
```json
|
||||||
|
// keydata set hardware HW00000011C3000R -f
|
||||||
|
// keydata set mac 6C:5C:3D:B2:27:83 -f
|
||||||
|
{
|
||||||
|
"mt": 98,
|
||||||
|
"ct": "HW00000011C3000U",
|
||||||
|
"mac": "6C5C3DB22783"
|
||||||
|
}
|
||||||
|
|
||||||
|
// 带屏幕
|
||||||
|
{
|
||||||
|
"mt": 98,
|
||||||
|
"ct": "HWA0310511C1000R",
|
||||||
|
"mac": "6C5C3DB22783"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
81
Record/CMakeLists.txt
Normal file
81
Record/CMakeLists.txt
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
add_executable(Record main.cpp
|
||||||
|
RkAudio.h RkAudio.cpp
|
||||||
|
OpusCodec.h OpusCodec.cpp
|
||||||
|
FFmpegResample.h FFmpegResample.cpp
|
||||||
|
RkRecorder.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(Record
|
||||||
|
PRIVATE ${ALSA_INCLUDE_DIR}
|
||||||
|
PRIVATE ${MPP_INCLUDE_DIR}
|
||||||
|
PRIVATE ${MPP_INCLUDE_DIR}/rkmedia
|
||||||
|
PRIVATE /opt/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/opus-1.4/include
|
||||||
|
PRIVATE ${FFMPEG_INCLUDE_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_directories(Record
|
||||||
|
PRIVATE ${ALSA_LIBRARY_DIRS}
|
||||||
|
PRIVATE ${MPP_LIBRARY_DIRS}
|
||||||
|
PRIVATE ${3rdparty_ROOT}/rkap_3a/lib
|
||||||
|
PRIVATE ${FFMPEG_LIBRARY_DIRS}
|
||||||
|
PRIVATE /opt/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/opus-1.4/lib
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(Record
|
||||||
|
PRIVATE asound
|
||||||
|
PRIVATE easymedia
|
||||||
|
PRIVATE drm
|
||||||
|
PRIVATE rkaiq
|
||||||
|
PRIVATE rockchip_mpp
|
||||||
|
PRIVATE v4l2
|
||||||
|
PRIVATE v4lconvert
|
||||||
|
PRIVATE jpeg
|
||||||
|
PRIVATE png16
|
||||||
|
PRIVATE fontconfig
|
||||||
|
PRIVATE freetype
|
||||||
|
PRIVATE expat
|
||||||
|
PRIVATE rga
|
||||||
|
PRIVATE glib-2.0
|
||||||
|
PRIVATE pcre
|
||||||
|
PRIVATE opus
|
||||||
|
PRIVATE Universal
|
||||||
|
PRIVATE stdc++fs
|
||||||
|
PRIVATE RKAP_ANR
|
||||||
|
PRIVATE RKAP_Common
|
||||||
|
PRIVATE uuid
|
||||||
|
PRIVATE dl
|
||||||
|
PRIVATE z
|
||||||
|
PRIVATE ${FFMPEG_LIBRARY}
|
||||||
|
)
|
||||||
|
|
||||||
|
add_executable(rkmedia_audio_test rkmedia_audio_test.c)
|
||||||
|
|
||||||
|
target_include_directories(rkmedia_audio_test
|
||||||
|
PRIVATE ${MPP_INCLUDE_DIR}/rkmedia
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_directories(rkmedia_audio_test
|
||||||
|
PRIVATE ${MPP_LIBRARY_DIRS}
|
||||||
|
PRIVATE ${3rdparty_ROOT}/rkap_3a/lib
|
||||||
|
PRIVATE ${ALSA_LIBRARY_DIRS}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(rkmedia_audio_test
|
||||||
|
PRIVATE asound
|
||||||
|
PRIVATE easymedia
|
||||||
|
PRIVATE drm
|
||||||
|
PRIVATE rkaiq
|
||||||
|
PRIVATE rockchip_mpp
|
||||||
|
PRIVATE v4l2
|
||||||
|
PRIVATE v4lconvert
|
||||||
|
PRIVATE jpeg
|
||||||
|
PRIVATE rga
|
||||||
|
PRIVATE glib-2.0
|
||||||
|
PRIVATE pcre
|
||||||
|
# PRIVATE opus
|
||||||
|
# PRIVATE Universal
|
||||||
|
# PRIVATE stdc++fs
|
||||||
|
PRIVATE RKAP_ANR
|
||||||
|
PRIVATE RKAP_Common
|
||||||
|
PRIVATE dl
|
||||||
|
)
|
61
Record/FFmpegResample.cpp
Normal file
61
Record/FFmpegResample.cpp
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#include "FFmpegResample.h"
|
||||||
|
#include "BoostLog.h"
|
||||||
|
#include "FFmpegResample.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include <libavcodec/avcodec.h>
|
||||||
|
#include <libswresample/swresample.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
FFmpegResample::~FFmpegResample() {
|
||||||
|
if (m_buffer != nullptr) {
|
||||||
|
delete[] m_buffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FFmpegResample::initialize(int32_t sampleRateIn, int32_t channelIn, int32_t sampleRateOut, int32_t channelOut,
|
||||||
|
int32_t period) {
|
||||||
|
m_sampleRateOut = sampleRateOut;
|
||||||
|
m_channelOut = channelOut;
|
||||||
|
m_sampleRateIn = sampleRateIn;
|
||||||
|
m_channelIn = channelIn;
|
||||||
|
|
||||||
|
int64_t outChLayout = channelOut == 1 ? AV_CH_LAYOUT_MONO : AV_CH_LAYOUT_STEREO;
|
||||||
|
int64_t inChLayout = channelIn == 1 ? AV_CH_LAYOUT_MONO : AV_CH_LAYOUT_STEREO;
|
||||||
|
|
||||||
|
m_swrContext = swr_alloc_set_opts(nullptr, outChLayout, AV_SAMPLE_FMT_S16, sampleRateOut, inChLayout, AV_SAMPLE_FMT_S16,
|
||||||
|
sampleRateIn, 0, nullptr);
|
||||||
|
if (m_swrContext == nullptr) {
|
||||||
|
LOG(error) << "swr_alloc_set_opts() failed.";
|
||||||
|
}
|
||||||
|
m_buffer = new uint8_t[sampleRateOut / 1000 * period * channelOut * sizeof(int16_t)];
|
||||||
|
int status = swr_init(m_swrContext);
|
||||||
|
if (status < 0) {
|
||||||
|
LOG(error) << "swr_init() failed.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FFmpegResample::Frame FFmpegResample::resample(const uint8_t *pcm, int32_t size) {
|
||||||
|
auto begin = std::chrono::system_clock::now();
|
||||||
|
FFmpegResample::Frame ret;
|
||||||
|
// 1. 输入进来的是 1channel 16khz 16bit pcm
|
||||||
|
// 2. 重采样为 2channel 48khz 16bit pcm
|
||||||
|
// 3. 编码为 opus
|
||||||
|
|
||||||
|
int32_t inSamples = size / m_channelIn / sizeof(int16_t);
|
||||||
|
int32_t outSamples = inSamples * m_sampleRateOut / m_sampleRateIn;
|
||||||
|
uint8_t *outBuffer = buffer.data();
|
||||||
|
int samples = swr_convert(m_swrContext, &outBuffer, outSamples, &pcm, inSamples);
|
||||||
|
if (samples < 0) {
|
||||||
|
char buffer[512] = {0};
|
||||||
|
LOG(error) << "avcodec_receive_frame() failed, error: " << av_make_error_string(buffer, sizeof(buffer), samples);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - begin);
|
||||||
|
|
||||||
|
ret.data = outBuffer;
|
||||||
|
ret.byteSize = samples * m_channelOut * sizeof(int16_t);
|
||||||
|
// LOG(info) << "inSamples: " << inSamples << ", samples: " << samples << ", elapsed: " << elapsed.count();
|
||||||
|
return ret;
|
||||||
|
}
|
32
Record/FFmpegResample.h
Normal file
32
Record/FFmpegResample.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#ifndef __FFMPEGRESAMPLE_H__
|
||||||
|
#define __FFMPEGRESAMPLE_H__
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
struct SwrContext;
|
||||||
|
|
||||||
|
class FFmpegResample {
|
||||||
|
public:
|
||||||
|
class Frame {
|
||||||
|
public:
|
||||||
|
uint8_t *data = nullptr;
|
||||||
|
int32_t byteSize = 0;
|
||||||
|
};
|
||||||
|
~FFmpegResample();
|
||||||
|
void initialize(int32_t sampleRateIn, int32_t channelIn, int32_t sampleRateOut, int32_t channelOut,int32_t period);
|
||||||
|
Frame resample(const uint8_t *pcm, int32_t size);
|
||||||
|
|
||||||
|
private:
|
||||||
|
SwrContext *m_swrContext = nullptr;
|
||||||
|
uint8_t *m_buffer;
|
||||||
|
std::array<uint8_t, 48 * 20 * 2 * 2> buffer;
|
||||||
|
int32_t m_sampleRateOut = 48000;
|
||||||
|
int32_t m_channelOut = 2;
|
||||||
|
int32_t m_sampleRateIn = 16000;
|
||||||
|
int32_t m_channelIn = 1;
|
||||||
|
int32_t m_period = 20; // ms
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // __FFMPEGRESAMPLE_H__
|
68
Record/OpusCodec.cpp
Normal file
68
Record/OpusCodec.cpp
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
#include "OpusCodec.h"
|
||||||
|
#include "BoostLog.h"
|
||||||
|
|
||||||
|
namespace Opus {
|
||||||
|
|
||||||
|
bool Encoder::open(int32_t samplerate, int32_t channels, uint32_t sampleSize) {
|
||||||
|
int error = 0;
|
||||||
|
|
||||||
|
uint32_t maxFrameSize = samplerate / 1000 * 60 * sampleSize * channels; // opus最大60ms一帧编码
|
||||||
|
m_buffer.resize(maxFrameSize);
|
||||||
|
|
||||||
|
m_encoder = opus_encoder_create(samplerate, channels, OPUS_APPLICATION_AUDIO, &error);
|
||||||
|
if (error != OPUS_OK || m_encoder == nullptr) {
|
||||||
|
LOG(error) << "opus_encoder_create() failed, status: " << error;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
opus_encoder_ctl(m_encoder, OPUS_SET_VBR(0)); // 0:CBR, 1:VBR
|
||||||
|
opus_encoder_ctl(m_encoder, OPUS_SET_VBR_CONSTRAINT(true));
|
||||||
|
opus_encoder_ctl(m_encoder, OPUS_SET_BITRATE(96000));
|
||||||
|
opus_encoder_ctl(m_encoder, OPUS_SET_COMPLEXITY(8)); // 8 0~10
|
||||||
|
opus_encoder_ctl(m_encoder, OPUS_SET_SIGNAL(OPUS_SIGNAL_VOICE));
|
||||||
|
opus_encoder_ctl(m_encoder, OPUS_SET_LSB_DEPTH(16)); // 每个采样16个bit,2个byte
|
||||||
|
opus_encoder_ctl(m_encoder, OPUS_SET_DTX(0));
|
||||||
|
opus_encoder_ctl(m_encoder, OPUS_SET_INBAND_FEC(0));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Encoder::close() {
|
||||||
|
if (m_encoder != nullptr) {
|
||||||
|
opus_encoder_destroy(m_encoder);
|
||||||
|
m_encoder = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Encoder::~Encoder() {
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
const Opus::Packet Encoder::encode(const int16_t *pcm, int32_t framesize) {
|
||||||
|
Packet ret;
|
||||||
|
if (m_encoder == nullptr) return ret;
|
||||||
|
ret.byteSize = opus_encode(m_encoder, pcm, framesize, m_buffer.data(), m_buffer.size());
|
||||||
|
ret.data = m_buffer.data();
|
||||||
|
LOG(info) << "framesize: " << framesize << ", record size: " << ret.byteSize;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Decoder::open(int32_t samplerate, int32_t channels) {
|
||||||
|
|
||||||
|
int error = 0;
|
||||||
|
m_decoder = opus_decoder_create(samplerate, channels, &error);
|
||||||
|
if (error != OPUS_OK || m_decoder == NULL) {
|
||||||
|
LOG(error) << "opus_decoder_create() failed, status: " << error;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
opus_decoder_ctl(m_decoder, OPUS_SET_LSB_DEPTH(16));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t Decoder::decode(const uint8_t *data, int32_t dataSize, int16_t *pcm, int32_t pcmBuffer) {
|
||||||
|
int32_t decodedSize = opus_decode(m_decoder, data, dataSize, pcm, pcmBuffer, 0);
|
||||||
|
LOG(info) << "dataSize: " << dataSize << ", decodes frame size: " << decodedSize;
|
||||||
|
return decodedSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Opus
|
39
Record/OpusCodec.h
Normal file
39
Record/OpusCodec.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#ifndef __OPUSENCODER_H__
|
||||||
|
#define __OPUSENCODER_H__
|
||||||
|
|
||||||
|
#include "opus/opus.h"
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace Opus {
|
||||||
|
|
||||||
|
class Packet {
|
||||||
|
public:
|
||||||
|
uint8_t *data = nullptr;
|
||||||
|
uint32_t byteSize = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Encoder {
|
||||||
|
public:
|
||||||
|
~Encoder();
|
||||||
|
bool open(int32_t samplerate, int32_t channels, uint32_t sampleSize);
|
||||||
|
void close();
|
||||||
|
const Packet encode(const int16_t *pcm, int32_t framesize);
|
||||||
|
|
||||||
|
private:
|
||||||
|
OpusEncoder *m_encoder = nullptr;
|
||||||
|
std::vector<uint8_t> m_buffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Decoder {
|
||||||
|
public:
|
||||||
|
bool open(int32_t samplerate, int32_t channels);
|
||||||
|
int32_t decode(const uint8_t *data, int32_t dataSize, int16_t *pcm, int32_t pcmBuffer);
|
||||||
|
|
||||||
|
private:
|
||||||
|
OpusDecoder *m_decoder = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Opus
|
||||||
|
|
||||||
|
#endif // __OPUSENCODER_H__
|
187
Record/RkAudio.cpp
Normal file
187
Record/RkAudio.cpp
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
#include "RkAudio.h"
|
||||||
|
#include "BoostLog.h"
|
||||||
|
#include <cstring>
|
||||||
|
#include <rkmedia/rkmedia_api.h>
|
||||||
|
|
||||||
|
namespace RkAudio {
|
||||||
|
|
||||||
|
static SAMPLE_FORMAT_E rkAiFormat(Format::SampleType sampleType) {
|
||||||
|
SAMPLE_FORMAT_E ret = RK_SAMPLE_FMT_NONE;
|
||||||
|
switch (sampleType) {
|
||||||
|
case Format::SampleType::Unknown:
|
||||||
|
ret = RK_SAMPLE_FMT_NONE;
|
||||||
|
break;
|
||||||
|
case Format::SampleType::SignedInt16:
|
||||||
|
ret = RK_SAMPLE_FMT_S16;
|
||||||
|
break;
|
||||||
|
case Format::SampleType::SignedInt:
|
||||||
|
ret = RK_SAMPLE_FMT_S32;
|
||||||
|
break;
|
||||||
|
case Format::SampleType::Float:
|
||||||
|
ret = RK_SAMPLE_FMT_FLT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOG(error) << "unkonwn sample type: " << static_cast<int>(sampleType);
|
||||||
|
ret = RK_SAMPLE_FMT_NONE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
Input::Input() {
|
||||||
|
}
|
||||||
|
|
||||||
|
Input::~Input() {
|
||||||
|
if (m_channel >= 0) {
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool Input::open(const Format &format) {
|
||||||
|
bool ret = false;
|
||||||
|
// RK_MPI_SYS_DumpChn(RK_ID_AI);
|
||||||
|
m_channel = 0;
|
||||||
|
|
||||||
|
AI_CHN_ATTR_S parameter = {0};
|
||||||
|
parameter.pcAudioNode = "default";
|
||||||
|
parameter.enAiLayout = AI_LAYOUT_MIC_REF; // remove ref channel, and output mic mono
|
||||||
|
parameter.enSampleFormat = rkAiFormat(format.sampleType);
|
||||||
|
parameter.u32Channels = format.channels;
|
||||||
|
parameter.u32SampleRate = format.sampleRate;
|
||||||
|
parameter.u32NbSamples = format.sampleRate / 1000 * format.period;
|
||||||
|
|
||||||
|
int status = RK_MPI_AI_SetChnAttr(m_channel, ¶meter);
|
||||||
|
if (status) {
|
||||||
|
LOG(error) << "RK_MPI_AI_SetChnAttr() failed, status: " << status;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = RK_MPI_AI_EnableChn(m_channel);
|
||||||
|
if (status) {
|
||||||
|
LOG(error) << "RK_MPI_AI_EnableChn() failed, status: " << status;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
AI_TALKVQE_CONFIG_S config = {0};
|
||||||
|
status = RK_MPI_AI_GetTalkVqeAttr(m_channel, &config);
|
||||||
|
if (status) {
|
||||||
|
LOG(error) << "RK_MPI_AI_GetTalkVqeAttr() failed, status: " << status;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
// LOG(info) << "param file: " << config.aParamFilePath;
|
||||||
|
config.s32WorkSampleRate = format.sampleRate;
|
||||||
|
config.s32FrameSample = format.sampleRate / 1000 * format.period;
|
||||||
|
config.u32OpenMask = AI_TALKVQE_MASK_AEC | AI_TALKVQE_MASK_ANR | AI_TALKVQE_MASK_AGC;
|
||||||
|
strncpy(config.aParamFilePath, ParamFilePath, sizeof(config.aParamFilePath));
|
||||||
|
|
||||||
|
RK_MPI_AI_SetTalkVqeAttr(m_channel, &config);
|
||||||
|
fprintf(stderr, "end\n");
|
||||||
|
if (status) {
|
||||||
|
LOG(error) << "RK_MPI_AI_SetTalkVqeAttr() failed, status: " << status;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
status = RK_MPI_AI_EnableVqe(m_channel);
|
||||||
|
if (status) {
|
||||||
|
LOG(error) << "RK_MPI_AI_EnableVqe() failed, status: " << status;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = RK_MPI_AI_StartStream(0);
|
||||||
|
if (status) {
|
||||||
|
LOG(info) << "start AI failed, status: " << status;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_exit = false;
|
||||||
|
m_thread = std::thread(&Input::run, this);
|
||||||
|
ret = true;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Input::stop() {
|
||||||
|
m_exit = true;
|
||||||
|
if (m_thread.joinable()) m_thread.join();
|
||||||
|
|
||||||
|
if (m_channel >= 0) {
|
||||||
|
RK_MPI_AI_DisableVqe(m_channel);
|
||||||
|
RK_MPI_AI_DisableChn(m_channel);
|
||||||
|
m_channel = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Input::setDataCallback(const ReadCallback &callback) {
|
||||||
|
m_callback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Input::run() {
|
||||||
|
while (!m_exit) {
|
||||||
|
auto mediaBuffer = RK_MPI_SYS_GetMediaBuffer(RK_ID_AI, 0, -1);
|
||||||
|
if (!mediaBuffer) {
|
||||||
|
LOG(error) << "RK_MPI_SYS_GetMediaBuffer() failed.";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (m_callback) {
|
||||||
|
Frame frame;
|
||||||
|
frame.data = reinterpret_cast<uint8_t *>(RK_MPI_MB_GetPtr(mediaBuffer));
|
||||||
|
frame.byteSize = RK_MPI_MB_GetSize(mediaBuffer);
|
||||||
|
frame.frameSize = frame.byteSize / m_format.channels / sizeof(uint16_t);
|
||||||
|
frame.timestamp = std::chrono::system_clock::now();
|
||||||
|
m_callback(frame);
|
||||||
|
}
|
||||||
|
RK_MPI_MB_ReleaseBuffer(mediaBuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Output::Output() {
|
||||||
|
}
|
||||||
|
|
||||||
|
Output::~Output() {
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Output::open(uint32_t sampleSize, uint32_t sampleRate, uint32_t channels) {
|
||||||
|
|
||||||
|
m_channel = 0;
|
||||||
|
AO_CHN_ATTR_S parameter = {0};
|
||||||
|
parameter.pcAudioNode = "default";
|
||||||
|
parameter.enSampleFormat = RK_SAMPLE_FMT_S16;
|
||||||
|
parameter.u32NbSamples = sampleRate / 1000 * 20;
|
||||||
|
parameter.u32SampleRate = sampleRate;
|
||||||
|
parameter.u32Channels = channels;
|
||||||
|
|
||||||
|
RK_MPI_AO_SetChnAttr(m_channel, ¶meter);
|
||||||
|
RK_MPI_AO_EnableChn(m_channel);
|
||||||
|
|
||||||
|
AO_VQE_CONFIG_S config = {0};
|
||||||
|
config.s32WorkSampleRate = sampleRate;
|
||||||
|
config.s32FrameSample = parameter.u32NbSamples;
|
||||||
|
config.u32OpenMask = AO_VQE_MASK_ANR | AO_VQE_MASK_AGC;
|
||||||
|
strncpy(config.aParamFilePath, ParamFilePath, sizeof(config.aParamFilePath));
|
||||||
|
|
||||||
|
RK_MPI_AO_SetVqeAttr(m_channel, &config);
|
||||||
|
RK_MPI_AO_EnableVqe(m_channel);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Output::close() {
|
||||||
|
if (m_channel >= 0) {
|
||||||
|
RK_MPI_AO_DisableVqe(m_channel);
|
||||||
|
RK_MPI_AO_DisableChn(m_channel);
|
||||||
|
m_channel = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Output::write(const uint8_t *data, uint32_t byteSize) {
|
||||||
|
if (m_channel < 0) return;
|
||||||
|
auto buffer = RK_MPI_MB_CreateAudioBuffer(byteSize, RK_FALSE);
|
||||||
|
if (buffer != nullptr) {
|
||||||
|
memcpy(RK_MPI_MB_GetPtr(buffer), data, byteSize);
|
||||||
|
RK_MPI_MB_SetSize(buffer, byteSize);
|
||||||
|
RK_MPI_SYS_SendMediaBuffer(RK_ID_AO, m_channel, buffer);
|
||||||
|
RK_MPI_MB_ReleaseBuffer(buffer);
|
||||||
|
} else {
|
||||||
|
LOG(error) << "RK_MPI_MB_CreateAudioBuffer() failed.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace RkAudio
|
73
Record/RkAudio.h
Normal file
73
Record/RkAudio.h
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
#ifndef __RKAUDIO_H__
|
||||||
|
#define __RKAUDIO_H__
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
namespace RkAudio {
|
||||||
|
// constexpr auto ParamFilePath="/data/sdcard/rw_3a.bin";
|
||||||
|
constexpr auto ParamFilePath = "/data/sdcard/RKAP_3A_Para.bin";
|
||||||
|
|
||||||
|
class Format {
|
||||||
|
public:
|
||||||
|
enum Endian {
|
||||||
|
BigEndian,
|
||||||
|
LittleEndian,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum SampleType {
|
||||||
|
Unknown,
|
||||||
|
SignedInt16,
|
||||||
|
SignedInt,
|
||||||
|
Float,
|
||||||
|
};
|
||||||
|
SampleType sampleType = SignedInt16;
|
||||||
|
Endian byteOrder = LittleEndian;
|
||||||
|
uint32_t sampleRate = 48000;
|
||||||
|
uint32_t channels = 2;
|
||||||
|
uint32_t period = 60;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Frame {
|
||||||
|
public:
|
||||||
|
uint8_t *data = nullptr;
|
||||||
|
int32_t byteSize = 0;
|
||||||
|
int32_t frameSize = 0;
|
||||||
|
std::chrono::system_clock::time_point timestamp;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Input {
|
||||||
|
public:
|
||||||
|
using ReadCallback = std::function<void(const Frame &)>;
|
||||||
|
Input();
|
||||||
|
~Input();
|
||||||
|
void setDataCallback(const ReadCallback &callback);
|
||||||
|
bool open(const Format &format);
|
||||||
|
void stop();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void run();
|
||||||
|
|
||||||
|
private:
|
||||||
|
int32_t m_channel = -1;
|
||||||
|
bool m_exit = false;
|
||||||
|
std::thread m_thread;
|
||||||
|
ReadCallback m_callback;
|
||||||
|
Format m_format;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Output {
|
||||||
|
public:
|
||||||
|
Output();
|
||||||
|
~Output();
|
||||||
|
bool open(uint32_t sampleSize, uint32_t sampleRate, uint32_t channels);
|
||||||
|
void close();
|
||||||
|
void write(const uint8_t *data, uint32_t byteSize);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int32_t m_channel = -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace RkAudio
|
||||||
|
|
||||||
|
#endif // __RKAUDIO_H__
|
226
Record/RkRecorder.cpp
Normal file
226
Record/RkRecorder.cpp
Normal file
@ -0,0 +1,226 @@
|
|||||||
|
#include "BoostLog.h"
|
||||||
|
#include <fstream>
|
||||||
|
#include <rkmedia/rkmedia_api.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
#define VQEFILE "/data/sdcard/RKAP_3A_Para.bin"
|
||||||
|
#define ALSA_PATH "default" // get from "arecord -L"
|
||||||
|
|
||||||
|
static bool quit = false;
|
||||||
|
static void sigterm_handler(int sig) {
|
||||||
|
fprintf(stderr, "signal %d\n", sig);
|
||||||
|
quit = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<std::ofstream> ofs;
|
||||||
|
|
||||||
|
void run() {
|
||||||
|
ofs = std::make_shared<std::ofstream>("/data/sdcard/test.pcm", std::ofstream::binary);
|
||||||
|
while (!quit) {
|
||||||
|
auto mediaBuffer = RK_MPI_SYS_GetMediaBuffer(RK_ID_AI, 0, -1);
|
||||||
|
if (!mediaBuffer) {
|
||||||
|
LOG(error) << "RK_MPI_SYS_GetMediaBuffer() failed.";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
LOG(info) << "get frame, timestamp: " << RK_MPI_MB_GetTimestamp(mediaBuffer)
|
||||||
|
<< ", size: " << RK_MPI_MB_GetSize(mediaBuffer);
|
||||||
|
ofs->write((const char *)RK_MPI_MB_GetPtr(mediaBuffer), RK_MPI_MB_GetSize(mediaBuffer));
|
||||||
|
RK_MPI_MB_ReleaseBuffer(mediaBuffer);
|
||||||
|
}
|
||||||
|
ofs.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void rkDemo() {
|
||||||
|
AI_CHN_ATTR_S ai_attr;
|
||||||
|
ai_attr.pcAudioNode = "default";
|
||||||
|
ai_attr.enSampleFormat = RK_SAMPLE_FMT_S16;
|
||||||
|
ai_attr.u32NbSamples = 16 * 20;
|
||||||
|
ai_attr.u32SampleRate = 16000;
|
||||||
|
ai_attr.u32Channels = 2;
|
||||||
|
ai_attr.enAiLayout = AI_LAYOUT_REF_MIC;
|
||||||
|
int status = RK_MPI_AI_SetChnAttr(0, &ai_attr);
|
||||||
|
status |= RK_MPI_AI_EnableChn(0);
|
||||||
|
if (status) {
|
||||||
|
LOG(error) << "enable AI[0] failed, status = " << status;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AI_TALKVQE_CONFIG_S config = {0};
|
||||||
|
strcpy(config.aParamFilePath, VQEFILE);
|
||||||
|
config.s32WorkSampleRate = 16000;
|
||||||
|
config.s32FrameSample = 16 * 20;
|
||||||
|
config.u32OpenMask = AI_TALKVQE_MASK_AEC | AI_TALKVQE_MASK_ANR | AI_TALKVQE_MASK_AGC;
|
||||||
|
status = RK_MPI_AI_SetTalkVqeAttr(0, &config);
|
||||||
|
if (status) {
|
||||||
|
LOG(error) << "RK_MPI_AI_SetTalkVqeAttr() failed, status: " << status;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = RK_MPI_AI_EnableVqe(0);
|
||||||
|
if (status) {
|
||||||
|
LOG(error) << "RK_MPI_AI_EnableVqe() failed, status: " << status;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::thread thread(&run);
|
||||||
|
|
||||||
|
status = RK_MPI_AI_StartStream(0);
|
||||||
|
if (status) {
|
||||||
|
LOG(info) << "start AI failed, status: " << status;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
signal(SIGINT, sigterm_handler);
|
||||||
|
while (!quit) {
|
||||||
|
usleep(500000);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (thread.joinable()) {
|
||||||
|
thread.join();
|
||||||
|
}
|
||||||
|
|
||||||
|
RK_MPI_AI_DisableChn(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static RK_U32 g_enWorkSampleRate = 8000;
|
||||||
|
static RK_U32 g_s32VqeFrameSample = 320; // 20ms;
|
||||||
|
|
||||||
|
// #define VQEFILE "/data/sdcard/3a.bin"
|
||||||
|
int AI_VqeProcess_AO() {
|
||||||
|
AI_TALKVQE_CONFIG_S stAiVqeTalkAttr;
|
||||||
|
AI_RECORDVQE_CONFIG_S stAiVqeRecordAttr;
|
||||||
|
AO_VQE_CONFIG_S stAoVqeAttr;
|
||||||
|
MPP_CHN_S mpp_chn_ai, mpp_chn_ao;
|
||||||
|
|
||||||
|
memset(&stAiVqeTalkAttr, 0, sizeof(AI_TALKVQE_CONFIG_S));
|
||||||
|
stAiVqeTalkAttr.s32WorkSampleRate = g_enWorkSampleRate;
|
||||||
|
stAiVqeTalkAttr.s32FrameSample = g_s32VqeFrameSample;
|
||||||
|
strcpy(stAiVqeTalkAttr.aParamFilePath, VQEFILE);
|
||||||
|
stAiVqeTalkAttr.u32OpenMask = AI_TALKVQE_MASK_AEC | AI_TALKVQE_MASK_ANR | AI_TALKVQE_MASK_AGC;
|
||||||
|
// stAiVqeTalkAttr.u32OpenMask = AI_TALKVQE_MASK_AEC ;
|
||||||
|
|
||||||
|
memset(&stAoVqeAttr, 0, sizeof(AO_VQE_CONFIG_S));
|
||||||
|
stAoVqeAttr.s32WorkSampleRate = g_enWorkSampleRate;
|
||||||
|
stAoVqeAttr.s32FrameSample = g_s32VqeFrameSample;
|
||||||
|
strcpy(stAoVqeAttr.aParamFilePath, VQEFILE);
|
||||||
|
stAoVqeAttr.u32OpenMask = AO_VQE_MASK_ANR | AO_VQE_MASK_AGC;
|
||||||
|
|
||||||
|
mpp_chn_ai.enModId = RK_ID_AI;
|
||||||
|
mpp_chn_ai.s32ChnId = 0;
|
||||||
|
mpp_chn_ao.enModId = RK_ID_AO;
|
||||||
|
mpp_chn_ao.s32ChnId = 0;
|
||||||
|
|
||||||
|
AI_CHN_ATTR_S ai_attr;
|
||||||
|
ai_attr.pcAudioNode = "default";
|
||||||
|
ai_attr.enSampleFormat = RK_SAMPLE_FMT_S16;
|
||||||
|
ai_attr.u32NbSamples = 320;
|
||||||
|
ai_attr.u32SampleRate = g_enWorkSampleRate;
|
||||||
|
ai_attr.u32Channels = 1;
|
||||||
|
ai_attr.enAiLayout = AI_LAYOUT_MIC_REF; // remove ref channel, and output mic mono
|
||||||
|
|
||||||
|
AO_CHN_ATTR_S ao_attr;
|
||||||
|
ao_attr.pcAudioNode = "default";
|
||||||
|
ao_attr.enSampleFormat = RK_SAMPLE_FMT_S16;
|
||||||
|
ao_attr.u32NbSamples = 320;
|
||||||
|
ao_attr.u32SampleRate = g_enWorkSampleRate;
|
||||||
|
ao_attr.u32Channels = 1;
|
||||||
|
|
||||||
|
// 1. create AI
|
||||||
|
RK_MPI_AI_SetChnAttr(mpp_chn_ai.s32ChnId, &ai_attr);
|
||||||
|
RK_MPI_AI_EnableChn(mpp_chn_ai.s32ChnId);
|
||||||
|
|
||||||
|
RK_MPI_AI_SetTalkVqeAttr(mpp_chn_ai.s32ChnId, &stAiVqeTalkAttr);
|
||||||
|
RK_MPI_AI_EnableVqe(mpp_chn_ai.s32ChnId);
|
||||||
|
|
||||||
|
// 2. create AO
|
||||||
|
RK_MPI_AO_SetChnAttr(mpp_chn_ao.s32ChnId, &ao_attr);
|
||||||
|
RK_MPI_AO_EnableChn(mpp_chn_ao.s32ChnId);
|
||||||
|
|
||||||
|
RK_MPI_AO_SetVqeAttr(mpp_chn_ao.s32ChnId, &stAoVqeAttr);
|
||||||
|
RK_MPI_AO_EnableVqe(mpp_chn_ao.s32ChnId);
|
||||||
|
|
||||||
|
// 3. bind AI-AO
|
||||||
|
RK_MPI_SYS_Bind(&mpp_chn_ai, &mpp_chn_ao);
|
||||||
|
|
||||||
|
printf("%s initial finish\n", __func__);
|
||||||
|
signal(SIGINT, sigterm_handler);
|
||||||
|
while (!quit) {
|
||||||
|
usleep(500000);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%s exit!\n", __func__);
|
||||||
|
RK_MPI_SYS_UnBind(&mpp_chn_ai, &mpp_chn_ao);
|
||||||
|
RK_MPI_AI_DisableChn(mpp_chn_ai.s32ChnId);
|
||||||
|
RK_MPI_AO_DisableChn(mpp_chn_ao.s32ChnId);
|
||||||
|
|
||||||
|
return RK_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int AI_VqeProcess_AO1() {
|
||||||
|
AI_TALKVQE_CONFIG_S stAiVqeTalkAttr;
|
||||||
|
AI_RECORDVQE_CONFIG_S stAiVqeRecordAttr;
|
||||||
|
AO_VQE_CONFIG_S stAoVqeAttr;
|
||||||
|
MPP_CHN_S mpp_chn_ai, mpp_chn_ao;
|
||||||
|
|
||||||
|
memset(&stAiVqeTalkAttr, 0, sizeof(AI_TALKVQE_CONFIG_S));
|
||||||
|
stAiVqeTalkAttr.s32WorkSampleRate = g_enWorkSampleRate;
|
||||||
|
stAiVqeTalkAttr.s32FrameSample = g_s32VqeFrameSample;
|
||||||
|
strcpy(stAiVqeTalkAttr.aParamFilePath, VQEFILE);
|
||||||
|
stAiVqeTalkAttr.u32OpenMask = AI_TALKVQE_MASK_AEC | AI_TALKVQE_MASK_ANR | AI_TALKVQE_MASK_AGC;
|
||||||
|
|
||||||
|
memset(&stAoVqeAttr, 0, sizeof(AO_VQE_CONFIG_S));
|
||||||
|
stAoVqeAttr.s32WorkSampleRate = g_enWorkSampleRate;
|
||||||
|
stAoVqeAttr.s32FrameSample = g_s32VqeFrameSample;
|
||||||
|
strcpy(stAoVqeAttr.aParamFilePath, VQEFILE);
|
||||||
|
stAoVqeAttr.u32OpenMask = AO_VQE_MASK_ANR | AO_VQE_MASK_AGC;
|
||||||
|
|
||||||
|
RK_MPI_SYS_Init();
|
||||||
|
mpp_chn_ai.enModId = RK_ID_AI;
|
||||||
|
mpp_chn_ai.s32ChnId = 0;
|
||||||
|
mpp_chn_ao.enModId = RK_ID_AO;
|
||||||
|
mpp_chn_ao.s32ChnId = 0;
|
||||||
|
|
||||||
|
AI_CHN_ATTR_S ai_attr;
|
||||||
|
ai_attr.pcAudioNode = ALSA_PATH;
|
||||||
|
ai_attr.enSampleFormat = RK_SAMPLE_FMT_S16;
|
||||||
|
ai_attr.u32NbSamples = 640;
|
||||||
|
ai_attr.u32SampleRate = g_enWorkSampleRate;
|
||||||
|
ai_attr.u32Channels = 1;
|
||||||
|
ai_attr.enAiLayout = AI_LAYOUT_MIC_REF; // remove ref channel, and output mic mono
|
||||||
|
|
||||||
|
AO_CHN_ATTR_S ao_attr;
|
||||||
|
ao_attr.pcAudioNode = ALSA_PATH;
|
||||||
|
ao_attr.enSampleFormat = RK_SAMPLE_FMT_S16;
|
||||||
|
ao_attr.u32NbSamples = 640;
|
||||||
|
ao_attr.u32SampleRate = g_enWorkSampleRate;
|
||||||
|
ao_attr.u32Channels = 1;
|
||||||
|
|
||||||
|
// 1. create AI
|
||||||
|
RK_MPI_AI_SetChnAttr(mpp_chn_ai.s32ChnId, &ai_attr);
|
||||||
|
RK_MPI_AI_EnableChn(mpp_chn_ai.s32ChnId);
|
||||||
|
|
||||||
|
RK_MPI_AI_SetTalkVqeAttr(mpp_chn_ai.s32ChnId, &stAiVqeTalkAttr);
|
||||||
|
RK_MPI_AI_EnableVqe(mpp_chn_ai.s32ChnId);
|
||||||
|
|
||||||
|
// 2. create AO
|
||||||
|
RK_MPI_AO_SetChnAttr(mpp_chn_ao.s32ChnId, &ao_attr);
|
||||||
|
RK_MPI_AO_EnableChn(mpp_chn_ao.s32ChnId);
|
||||||
|
RK_MPI_AO_SetVqeAttr(mpp_chn_ao.s32ChnId, &stAoVqeAttr);
|
||||||
|
RK_MPI_AO_EnableVqe(mpp_chn_ao.s32ChnId);
|
||||||
|
|
||||||
|
// 3. bind AI-AO
|
||||||
|
RK_MPI_SYS_Bind(&mpp_chn_ai, &mpp_chn_ao);
|
||||||
|
|
||||||
|
printf("%s initial finish\n", __func__);
|
||||||
|
signal(SIGINT, sigterm_handler);
|
||||||
|
while (!quit) {
|
||||||
|
usleep(500000);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%s exit!\n", __func__);
|
||||||
|
RK_MPI_SYS_UnBind(&mpp_chn_ai, &mpp_chn_ao);
|
||||||
|
RK_MPI_AI_DisableChn(mpp_chn_ai.s32ChnId);
|
||||||
|
RK_MPI_AO_DisableChn(mpp_chn_ao.s32ChnId);
|
||||||
|
|
||||||
|
return RK_SUCCESS;
|
||||||
|
}
|
61
Record/main.cpp
Normal file
61
Record/main.cpp
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#include "FFmpegResample.h"
|
||||||
|
#include "OpusCodec.h"
|
||||||
|
#include <fstream>
|
||||||
|
#include <rkmedia/rkmedia_api.h>
|
||||||
|
|
||||||
|
extern int recorder_demo();
|
||||||
|
extern void rkDemo();
|
||||||
|
extern int AI_VqeProcess_AO();
|
||||||
|
extern int AI_VqeProcess_AO1();
|
||||||
|
extern void AecTest();
|
||||||
|
extern int opus_test();
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
RK_MPI_SYS_Init();
|
||||||
|
// std::ifstream ifs("/data/sdcard/test2.pcm", std::ifstream::binary);
|
||||||
|
// AlsaPcmPlayer player;
|
||||||
|
// player.open(2, 48000, 2);
|
||||||
|
|
||||||
|
// char buffer[2 * 2 * 48 * 60];
|
||||||
|
// while (ifs.read(buffer, sizeof(buffer))) {
|
||||||
|
// int size = ifs.gcount();
|
||||||
|
// player.write((const uint8_t *)buffer, size);
|
||||||
|
// }
|
||||||
|
// recorder_demo();
|
||||||
|
// rkDemo();
|
||||||
|
// AI_VqeProcess_AO();
|
||||||
|
// AI_VqeProcess_AO1();
|
||||||
|
// AecTest();
|
||||||
|
|
||||||
|
{
|
||||||
|
FFmpegResample resample;
|
||||||
|
resample.initialize(16000, 1, 48000, 2, 20);
|
||||||
|
|
||||||
|
std::ifstream ifs("/sdcard/input.pcm", std::ifstream::binary);
|
||||||
|
std::ofstream ofs("/sdcard/my_48kz.pcm", std::ifstream::binary);
|
||||||
|
char buffer[16 * 20 * 2];
|
||||||
|
while (ifs.read(buffer, sizeof(buffer))) {
|
||||||
|
auto frame = resample.resample((uint8_t *)buffer, sizeof(buffer));
|
||||||
|
if (frame.data != nullptr) {
|
||||||
|
ofs.write((char *)frame.data, frame.byteSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
FFmpegResample resample1;
|
||||||
|
resample1.initialize(48000, 2, 16000, 1, 20);
|
||||||
|
|
||||||
|
std::ifstream ifs1("/sdcard/my_48kz.pcm", std::ifstream::binary);
|
||||||
|
std::ofstream ofs1("/sdcard/my_16kz.pcm", std::ifstream::binary);
|
||||||
|
char buffer1[48 * 20 * 2 * 2];
|
||||||
|
while (ifs1.read(buffer1, sizeof(buffer1))) {
|
||||||
|
auto frame = resample1.resample((uint8_t *)buffer1, sizeof(buffer1));
|
||||||
|
if (frame.data != nullptr) {
|
||||||
|
ofs1.write((char *)frame.data, frame.byteSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
411
Record/rkmedia_audio_test.c
Normal file
411
Record/rkmedia_audio_test.c
Normal file
@ -0,0 +1,411 @@
|
|||||||
|
// Copyright 2020 Fuzhou Rockchip Electronics Co., Ltd. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <rkmedia_api.h>
|
||||||
|
#define MP3_NB_SAMPLES 1024
|
||||||
|
#define MP2_NB_SAMPLES 1152
|
||||||
|
//#define ALSA_PATH "default:CARD=rockchiprk809co" // get from "arecord -L"
|
||||||
|
#define ALSA_PATH "hw:0,0" // get from "arecord -L"
|
||||||
|
#define VQEFILE "/sdcard/RKAP_3A_Para.bin"
|
||||||
|
|
||||||
|
static bool quit = false;
|
||||||
|
static void sigterm_handler(int sig) {
|
||||||
|
fprintf(stderr, "signal %d\n", sig);
|
||||||
|
quit = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *fp = NULL;
|
||||||
|
static RK_U32 g_enWorkSampleRate = 16000;
|
||||||
|
static RK_U32 g_s32VqeFrameSample = 256; // 20ms;
|
||||||
|
static RK_U32 g_s32AiLayout = AI_LAYOUT_MIC_REF;
|
||||||
|
|
||||||
|
static void audio_packet_cb(MEDIA_BUFFER mb) {
|
||||||
|
printf("Get Audio Encoded packet:ptr:%p, fd:%d, size:%zu, mode:%d\n",
|
||||||
|
RK_MPI_MB_GetPtr(mb), RK_MPI_MB_GetFD(mb), RK_MPI_MB_GetSize(mb),
|
||||||
|
RK_MPI_MB_GetModeID(mb));
|
||||||
|
fwrite(RK_MPI_MB_GetPtr(mb), 1, RK_MPI_MB_GetSize(mb), fp);
|
||||||
|
RK_MPI_MB_ReleaseBuffer(mb);
|
||||||
|
}
|
||||||
|
|
||||||
|
static RK_VOID AI_AO() {
|
||||||
|
RK_MPI_SYS_Init();
|
||||||
|
MPP_CHN_S mpp_chn_ai, mpp_chn_ao;
|
||||||
|
mpp_chn_ai.enModId = RK_ID_AI;
|
||||||
|
mpp_chn_ai.s32ChnId = 0;
|
||||||
|
mpp_chn_ao.enModId = RK_ID_AO;
|
||||||
|
mpp_chn_ao.s32ChnId = 0;
|
||||||
|
|
||||||
|
AI_CHN_ATTR_S ai_attr;
|
||||||
|
ai_attr.pcAudioNode = ALSA_PATH;
|
||||||
|
ai_attr.enSampleFormat = RK_SAMPLE_FMT_S16;
|
||||||
|
ai_attr.u32NbSamples = 1152;
|
||||||
|
ai_attr.u32SampleRate = g_enWorkSampleRate;
|
||||||
|
ai_attr.u32Channels = 1;
|
||||||
|
ai_attr.enAiLayout = g_s32AiLayout; // chanel layout: [ref:mic]; remove
|
||||||
|
// ref, output mic mono
|
||||||
|
|
||||||
|
AO_CHN_ATTR_S ao_attr;
|
||||||
|
ao_attr.pcAudioNode = ALSA_PATH;
|
||||||
|
ao_attr.enSampleFormat = RK_SAMPLE_FMT_S16;
|
||||||
|
ao_attr.u32NbSamples = 1152;
|
||||||
|
ao_attr.u32SampleRate = g_enWorkSampleRate;
|
||||||
|
ao_attr.u32Channels = 1;
|
||||||
|
|
||||||
|
// 1. create AI
|
||||||
|
RK_MPI_AI_SetChnAttr(mpp_chn_ai.s32ChnId, &ai_attr);
|
||||||
|
RK_MPI_AI_EnableChn(mpp_chn_ai.s32ChnId);
|
||||||
|
RK_MPI_AI_SetVolume(mpp_chn_ai.s32ChnId, 100);
|
||||||
|
|
||||||
|
// 2. create AO
|
||||||
|
RK_MPI_AO_SetChnAttr(mpp_chn_ao.s32ChnId, &ao_attr);
|
||||||
|
RK_MPI_AO_EnableChn(mpp_chn_ao.s32ChnId);
|
||||||
|
RK_MPI_AO_SetVolume(mpp_chn_ao.s32ChnId, 100);
|
||||||
|
|
||||||
|
// 3. bind AI-AO
|
||||||
|
RK_MPI_SYS_Bind(&mpp_chn_ai, &mpp_chn_ao);
|
||||||
|
|
||||||
|
printf("%s initial finish\n", __func__);
|
||||||
|
signal(SIGINT, sigterm_handler);
|
||||||
|
while (!quit) {
|
||||||
|
usleep(500000);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%s exit!\n", __func__);
|
||||||
|
RK_MPI_SYS_UnBind(&mpp_chn_ai, &mpp_chn_ao);
|
||||||
|
RK_MPI_AI_DisableChn(mpp_chn_ai.s32ChnId);
|
||||||
|
RK_MPI_AO_DisableChn(mpp_chn_ao.s32ChnId);
|
||||||
|
}
|
||||||
|
|
||||||
|
static RK_VOID AI_AENC_FILE(char *file_path) {
|
||||||
|
fp = fopen(file_path, "w+");
|
||||||
|
RK_MPI_SYS_Init();
|
||||||
|
MPP_CHN_S mpp_chn_ai, mpp_chn_aenc;
|
||||||
|
mpp_chn_ai.enModId = RK_ID_AI;
|
||||||
|
mpp_chn_ai.s32ChnId = 0;
|
||||||
|
mpp_chn_aenc.enModId = RK_ID_AENC;
|
||||||
|
mpp_chn_aenc.s32ChnId = 0;
|
||||||
|
|
||||||
|
AI_CHN_ATTR_S ai_attr;
|
||||||
|
ai_attr.pcAudioNode = ALSA_PATH;
|
||||||
|
ai_attr.enSampleFormat = RK_SAMPLE_FMT_S16;
|
||||||
|
ai_attr.u32NbSamples = MP3_NB_SAMPLES;
|
||||||
|
ai_attr.u32SampleRate = g_enWorkSampleRate;
|
||||||
|
ai_attr.u32Channels = 1;
|
||||||
|
ai_attr.enAiLayout = g_s32AiLayout; // chanel layout: [ref:mic]; remove
|
||||||
|
// ref, output mic mono
|
||||||
|
|
||||||
|
AENC_CHN_ATTR_S aenc_attr;
|
||||||
|
aenc_attr.enCodecType = RK_CODEC_TYPE_MP3;
|
||||||
|
aenc_attr.u32Bitrate = 64000;
|
||||||
|
aenc_attr.u32Quality = 1;
|
||||||
|
aenc_attr.stAencMP3.u32Channels = 1;
|
||||||
|
aenc_attr.stAencMP3.u32SampleRate = g_enWorkSampleRate;
|
||||||
|
|
||||||
|
// 1. create AI
|
||||||
|
RK_MPI_AI_SetChnAttr(mpp_chn_ai.s32ChnId, &ai_attr);
|
||||||
|
RK_MPI_AI_EnableChn(mpp_chn_ai.s32ChnId);
|
||||||
|
|
||||||
|
// 2. create AENC
|
||||||
|
RK_MPI_AENC_CreateChn(mpp_chn_aenc.s32ChnId, &aenc_attr);
|
||||||
|
RK_U32 ret = RK_MPI_SYS_RegisterOutCb(&mpp_chn_aenc, audio_packet_cb);
|
||||||
|
printf("ret = %d.\n", ret);
|
||||||
|
|
||||||
|
// 3. bind AI-AENC
|
||||||
|
RK_MPI_SYS_Bind(&mpp_chn_ai, &mpp_chn_aenc);
|
||||||
|
|
||||||
|
printf("%s initial finish\n", __func__);
|
||||||
|
signal(SIGINT, sigterm_handler);
|
||||||
|
while (!quit) {
|
||||||
|
usleep(500000);
|
||||||
|
}
|
||||||
|
|
||||||
|
RK_MPI_SYS_UnBind(&mpp_chn_ai, &mpp_chn_aenc);
|
||||||
|
RK_MPI_AI_DisableChn(mpp_chn_ai.s32ChnId);
|
||||||
|
RK_MPI_AENC_DestroyChn(mpp_chn_aenc.s32ChnId);
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static RK_VOID FILE_ADEC_AO(char *file_path) {
|
||||||
|
CODEC_TYPE_E codec_type = RK_CODEC_TYPE_MP3;
|
||||||
|
RK_U32 channels = 2;
|
||||||
|
RK_U32 sample_rate = g_enWorkSampleRate;
|
||||||
|
ADEC_CHN_ATTR_S stAdecAttr;
|
||||||
|
AO_CHN_ATTR_S stAoAttr;
|
||||||
|
|
||||||
|
stAdecAttr.enCodecType = codec_type;
|
||||||
|
MPP_CHN_S mpp_chn_ao, mpp_chn_adec;
|
||||||
|
mpp_chn_ao.enModId = RK_ID_AO;
|
||||||
|
mpp_chn_ao.s32ChnId = 0;
|
||||||
|
mpp_chn_adec.enModId = RK_ID_ADEC;
|
||||||
|
mpp_chn_adec.s32ChnId = 0;
|
||||||
|
|
||||||
|
stAoAttr.u32Channels = channels;
|
||||||
|
stAoAttr.u32SampleRate = sample_rate;
|
||||||
|
stAoAttr.u32NbSamples = 1024;
|
||||||
|
stAoAttr.pcAudioNode = ALSA_PATH;
|
||||||
|
|
||||||
|
switch (codec_type) {
|
||||||
|
case RK_CODEC_TYPE_MP3:
|
||||||
|
stAoAttr.enSampleFormat = RK_SAMPLE_FMT_S16;
|
||||||
|
stAoAttr.u32NbSamples = 1024;
|
||||||
|
break;
|
||||||
|
case RK_CODEC_TYPE_MP2:
|
||||||
|
stAoAttr.enSampleFormat = RK_SAMPLE_FMT_S16;
|
||||||
|
stAoAttr.u32NbSamples = 1152;
|
||||||
|
break;
|
||||||
|
case RK_CODEC_TYPE_G711A:
|
||||||
|
stAdecAttr.stAdecG711A.u32Channels = channels;
|
||||||
|
stAdecAttr.stAdecG711A.u32SampleRate = sample_rate;
|
||||||
|
stAoAttr.enSampleFormat = RK_SAMPLE_FMT_S16;
|
||||||
|
break;
|
||||||
|
case RK_CODEC_TYPE_G711U:
|
||||||
|
stAdecAttr.stAdecG711U.u32Channels = channels;
|
||||||
|
stAdecAttr.stAdecG711U.u32SampleRate = sample_rate;
|
||||||
|
stAoAttr.enSampleFormat = RK_SAMPLE_FMT_S16;
|
||||||
|
break;
|
||||||
|
case RK_CODEC_TYPE_G726:
|
||||||
|
stAoAttr.enSampleFormat = RK_SAMPLE_FMT_S16;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("audio codec type error.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// init MPI
|
||||||
|
RK_MPI_SYS_Init();
|
||||||
|
// create ADEC
|
||||||
|
RK_MPI_ADEC_CreateChn(mpp_chn_adec.s32ChnId, &stAdecAttr);
|
||||||
|
// create AO
|
||||||
|
RK_MPI_AO_SetChnAttr(mpp_chn_ao.s32ChnId, &stAoAttr);
|
||||||
|
RK_MPI_AO_EnableChn(mpp_chn_ao.s32ChnId);
|
||||||
|
|
||||||
|
RK_MPI_SYS_Bind(&mpp_chn_adec, &mpp_chn_ao);
|
||||||
|
|
||||||
|
RK_S32 buffer_size = 20480;
|
||||||
|
FILE *read_file = fopen(file_path, "r");
|
||||||
|
if (!read_file) {
|
||||||
|
printf("ERROR: open %s failed!\n", file_path);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
quit = true;
|
||||||
|
while (quit) {
|
||||||
|
MEDIA_BUFFER mb = RK_MPI_MB_CreateAudioBuffer(buffer_size, RK_FALSE);
|
||||||
|
if (!mb) {
|
||||||
|
printf("ERROR: no space left!\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
RK_S32 s32ReadSize = fread(RK_MPI_MB_GetPtr(mb), 1, buffer_size, read_file);
|
||||||
|
|
||||||
|
RK_MPI_MB_SetSize(mb, s32ReadSize);
|
||||||
|
RK_MPI_SYS_SendMediaBuffer(RK_ID_ADEC, mpp_chn_adec.s32ChnId, mb);
|
||||||
|
RK_MPI_MB_ReleaseBuffer(mb);
|
||||||
|
if (s32ReadSize != buffer_size) {
|
||||||
|
printf("Get end of file!\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sleep(2);
|
||||||
|
{
|
||||||
|
// flush decoder
|
||||||
|
printf("start flush decoder.\n");
|
||||||
|
MEDIA_BUFFER mb = RK_MPI_MB_CreateAudioBuffer(buffer_size, RK_FALSE);
|
||||||
|
RK_MPI_MB_SetSize(mb, 0);
|
||||||
|
RK_MPI_SYS_SendMediaBuffer(RK_ID_ADEC, mpp_chn_adec.s32ChnId, mb);
|
||||||
|
RK_MPI_MB_ReleaseBuffer(mb);
|
||||||
|
printf("end flush decoder.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
sleep(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 0: close, 1: talk, 2: record */
|
||||||
|
static RK_U32 u32AiVqeType = 1;
|
||||||
|
/* 0: close, 1: open */
|
||||||
|
static RK_U32 u32AoVqeType = 1;
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* function : Ai ->VqeProcess-> Ao
|
||||||
|
******************************************************************************/
|
||||||
|
RK_S32 AI_VqeProcess_AO(RK_VOID) {
|
||||||
|
AI_TALKVQE_CONFIG_S stAiVqeTalkAttr;
|
||||||
|
AI_RECORDVQE_CONFIG_S stAiVqeRecordAttr;
|
||||||
|
AO_VQE_CONFIG_S stAoVqeAttr;
|
||||||
|
MPP_CHN_S mpp_chn_ai, mpp_chn_ao;
|
||||||
|
|
||||||
|
if (1 == u32AiVqeType) {
|
||||||
|
memset(&stAiVqeTalkAttr, 0, sizeof(AI_TALKVQE_CONFIG_S));
|
||||||
|
stAiVqeTalkAttr.s32WorkSampleRate = g_enWorkSampleRate;
|
||||||
|
stAiVqeTalkAttr.s32FrameSample = g_s32VqeFrameSample;
|
||||||
|
strcpy(stAiVqeTalkAttr.aParamFilePath, VQEFILE);
|
||||||
|
stAiVqeTalkAttr.u32OpenMask =
|
||||||
|
AI_TALKVQE_MASK_AEC | AI_TALKVQE_MASK_ANR | AI_TALKVQE_MASK_AGC;
|
||||||
|
} else if (2 == u32AiVqeType) {
|
||||||
|
memset(&stAiVqeRecordAttr, 0, sizeof(AI_RECORDVQE_CONFIG_S));
|
||||||
|
stAiVqeRecordAttr.s32WorkSampleRate = g_enWorkSampleRate;
|
||||||
|
stAiVqeRecordAttr.s32FrameSample = g_s32VqeFrameSample;
|
||||||
|
stAiVqeRecordAttr.stAnrConfig.fPostAddGain = 0;
|
||||||
|
stAiVqeRecordAttr.stAnrConfig.fGmin = -30;
|
||||||
|
stAiVqeRecordAttr.stAnrConfig.fNoiseFactor = 0.98;
|
||||||
|
stAiVqeRecordAttr.u32OpenMask = AI_RECORDVQE_MASK_ANR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (1 == u32AoVqeType) {
|
||||||
|
memset(&stAoVqeAttr, 0, sizeof(AO_VQE_CONFIG_S));
|
||||||
|
stAoVqeAttr.s32WorkSampleRate = g_enWorkSampleRate;
|
||||||
|
stAoVqeAttr.s32FrameSample = g_s32VqeFrameSample;
|
||||||
|
strcpy(stAoVqeAttr.aParamFilePath, VQEFILE);
|
||||||
|
stAoVqeAttr.u32OpenMask = AO_VQE_MASK_ANR | AO_VQE_MASK_AGC;
|
||||||
|
}
|
||||||
|
|
||||||
|
RK_MPI_SYS_Init();
|
||||||
|
mpp_chn_ai.enModId = RK_ID_AI;
|
||||||
|
mpp_chn_ai.s32ChnId = 0;
|
||||||
|
mpp_chn_ao.enModId = RK_ID_AO;
|
||||||
|
mpp_chn_ao.s32ChnId = 0;
|
||||||
|
|
||||||
|
AI_CHN_ATTR_S ai_attr;
|
||||||
|
ai_attr.pcAudioNode = ALSA_PATH;
|
||||||
|
ai_attr.enSampleFormat = RK_SAMPLE_FMT_S16;
|
||||||
|
ai_attr.u32NbSamples = 1024;
|
||||||
|
ai_attr.u32SampleRate = g_enWorkSampleRate;
|
||||||
|
ai_attr.u32Channels = 2;
|
||||||
|
ai_attr.enAiLayout = g_s32AiLayout; // remove ref channel, and output mic mono
|
||||||
|
|
||||||
|
AO_CHN_ATTR_S ao_attr;
|
||||||
|
ao_attr.pcAudioNode = ALSA_PATH;
|
||||||
|
ao_attr.enSampleFormat = RK_SAMPLE_FMT_S16;
|
||||||
|
ao_attr.u32NbSamples = 1024;
|
||||||
|
ao_attr.u32SampleRate = g_enWorkSampleRate;
|
||||||
|
ao_attr.u32Channels = 2;
|
||||||
|
|
||||||
|
// 1. create AI
|
||||||
|
RK_MPI_AI_SetChnAttr(mpp_chn_ai.s32ChnId, &ai_attr);
|
||||||
|
RK_MPI_AI_EnableChn(mpp_chn_ai.s32ChnId);
|
||||||
|
//RK_MPI_AI_SetVolume(mpp_chn_ai.s32ChnId, 100);
|
||||||
|
if (1 == u32AiVqeType) {
|
||||||
|
RK_MPI_AI_SetTalkVqeAttr(mpp_chn_ai.s32ChnId, &stAiVqeTalkAttr);
|
||||||
|
RK_MPI_AI_EnableVqe(mpp_chn_ai.s32ChnId);
|
||||||
|
} else if (2 == u32AiVqeType) {
|
||||||
|
RK_MPI_AI_SetRecordVqeAttr(mpp_chn_ai.s32ChnId, &stAiVqeRecordAttr);
|
||||||
|
RK_MPI_AI_EnableVqe(mpp_chn_ai.s32ChnId);
|
||||||
|
}
|
||||||
|
// 2. create AO
|
||||||
|
RK_MPI_AO_SetChnAttr(mpp_chn_ao.s32ChnId, &ao_attr);
|
||||||
|
RK_MPI_AO_EnableChn(mpp_chn_ao.s32ChnId);
|
||||||
|
//RK_MPI_AO_SetVolume(mpp_chn_ao.s32ChnId, 100);
|
||||||
|
if (1 == u32AoVqeType) {
|
||||||
|
RK_MPI_AO_SetVqeAttr(mpp_chn_ao.s32ChnId, &stAoVqeAttr);
|
||||||
|
RK_MPI_AO_EnableVqe(mpp_chn_ao.s32ChnId);
|
||||||
|
}
|
||||||
|
// 3. bind AI-AO
|
||||||
|
RK_MPI_SYS_Bind(&mpp_chn_ai, &mpp_chn_ao);
|
||||||
|
|
||||||
|
printf("%s initial finish\n", __func__);
|
||||||
|
signal(SIGINT, sigterm_handler);
|
||||||
|
while (!quit) {
|
||||||
|
usleep(500000);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%s exit!\n", __func__);
|
||||||
|
RK_MPI_SYS_UnBind(&mpp_chn_ai, &mpp_chn_ao);
|
||||||
|
RK_MPI_AI_DisableChn(mpp_chn_ai.s32ChnId);
|
||||||
|
RK_MPI_AO_DisableChn(mpp_chn_ao.s32ChnId);
|
||||||
|
|
||||||
|
return RK_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static RK_VOID RKMEDIA_AUDIO_Usage() {
|
||||||
|
printf("\n\n/Usage:./rkmdia_audio <index> <sampleRate> [filePath]/ "
|
||||||
|
"[nbsamples] [ailayout]\n");
|
||||||
|
printf("\tindex and its function list below\n");
|
||||||
|
printf("\t0: start AI to AO loop\n");
|
||||||
|
printf("\t1: send audio frame to AENC channel from AI, save them\n");
|
||||||
|
printf("\t2: read audio stream from file, decode and send AO\n");
|
||||||
|
printf("\t3: start AI(VQE process), then send to AO\n");
|
||||||
|
// printf("\t4: start AI to Extern Resampler\n");
|
||||||
|
printf("\n");
|
||||||
|
printf("\tsampleRate list:\n");
|
||||||
|
printf("\t0 16000 22050 24000 32000 44100 48000\n");
|
||||||
|
printf("\n");
|
||||||
|
printf("\tfilePath represents the path of audio file to be decoded, only for "
|
||||||
|
"sample 2.\n");
|
||||||
|
printf("\tdefault filePath: /userdata/out.mp2\n");
|
||||||
|
printf("\n");
|
||||||
|
printf("\tnbsamples, for example: 160 is 10ms at 16kHz\n");
|
||||||
|
printf("\n");
|
||||||
|
printf("\tailayout:\n");
|
||||||
|
printf("\t0: AI_LAYOUT_NORMAL\n");
|
||||||
|
printf("\t1: AI_LAYOUT_MIC_REF\n");
|
||||||
|
printf("\t2: AI_LAYOUT_REF_MIC\n");
|
||||||
|
printf("\t3: AI_LAYOUT_2MIC_REF_NONE\n");
|
||||||
|
printf("\t4: AI_LAYOUT_2MIC_NONE_REF\n");
|
||||||
|
printf("\t5: AI_LAYOUT_2MIC_2REF\n");
|
||||||
|
printf("\t6: AI_LAYOUT_BUTT\n");
|
||||||
|
printf("\n");
|
||||||
|
printf("\texample: ./rkmdia_audio 0 48000 480 1 /tmp/out_aiao.mp2\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
|
RK_U32 u32Index;
|
||||||
|
RK_CHAR *pFilePath = RK_NULL;
|
||||||
|
|
||||||
|
if (!(argc >= 3 && argc <= 6)) {
|
||||||
|
RKMEDIA_AUDIO_Usage();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "-?") == 0) {
|
||||||
|
RKMEDIA_AUDIO_Usage();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32Index = atoi(argv[1]);
|
||||||
|
g_enWorkSampleRate = atoi(argv[2]);
|
||||||
|
|
||||||
|
switch (argc) {
|
||||||
|
case 6:
|
||||||
|
pFilePath = argv[5];
|
||||||
|
g_s32AiLayout = atoi(argv[4]);
|
||||||
|
g_s32VqeFrameSample = atoi(argv[3]);
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
g_s32AiLayout = atoi(argv[4]);
|
||||||
|
g_s32VqeFrameSample = atoi(argv[3]);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
g_s32VqeFrameSample = atoi(argv[3]);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
pFilePath = (char *)"/tmp/out.mp2";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (u32Index) {
|
||||||
|
case 0:
|
||||||
|
AI_AO();
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
AI_AENC_FILE(pFilePath);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
FILE_ADEC_AO(pFilePath);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
AI_VqeProcess_AO();
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
26
VoucherVerifyServer/CMakeLists.txt
Normal file
26
VoucherVerifyServer/CMakeLists.txt
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
|
find_package(Boost REQUIRED COMPONENTS container url json)
|
||||||
|
|
||||||
|
add_executable(VoucherVerifyServer
|
||||||
|
main.cpp
|
||||||
|
HttpSession.h HttpSession.cpp
|
||||||
|
Listener.h Listener.cpp
|
||||||
|
ResponseUtility.h ResponseUtility.cpp
|
||||||
|
ServiceLogic.h ServiceLogic.cpp
|
||||||
|
SharedState.h SharedState.cpp
|
||||||
|
WebsocketSession.h WebsocketSession.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_directories(VoucherVerifyServer
|
||||||
|
PRIVATE ${OPENSSL_LIBRARY_DIRS}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(VoucherVerifyServer
|
||||||
|
PRIVATE Universal
|
||||||
|
PRIVATE HttpProxy
|
||||||
|
PRIVATE ${Boost_LIBRARIES}
|
||||||
|
PRIVATE ${OPENSSL_LIBRARY}
|
||||||
|
PRIVATE dl
|
||||||
|
)
|
107
VoucherVerifyServer/HttpSession.cpp
Normal file
107
VoucherVerifyServer/HttpSession.cpp
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
#include "HttpSession.h"
|
||||||
|
#include "WebsocketSession.h"
|
||||||
|
#include <boost/config.hpp>
|
||||||
|
#include <boost/url/parse_path.hpp>
|
||||||
|
#include <boost/url/url_view.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
HttpSession::HttpSession(boost::asio::ip::tcp::socket &&socket, const std::shared_ptr<SharedState> &state)
|
||||||
|
: m_stream(std::move(socket)), m_state(state) {
|
||||||
|
// m_buffer.reserve(1000 * 1000 * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HttpSession::run() {
|
||||||
|
doRead();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HttpSession::errorReply(const Request &request, boost::beast::http::status status,
|
||||||
|
boost::beast::string_view message) {
|
||||||
|
using namespace boost::beast;
|
||||||
|
// invalid route
|
||||||
|
http::response<http::string_body> res{status, request.version()};
|
||||||
|
res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
|
||||||
|
res.set(http::field::content_type, "text/html");
|
||||||
|
res.keep_alive(request.keep_alive());
|
||||||
|
res.body() = message;
|
||||||
|
res.prepare_payload();
|
||||||
|
|
||||||
|
reply(std::move(res));
|
||||||
|
}
|
||||||
|
|
||||||
|
void HttpSession::doRead() {
|
||||||
|
// Construct a new parser for each message
|
||||||
|
m_parser.emplace();
|
||||||
|
|
||||||
|
// Apply a reasonable limit to the allowed size
|
||||||
|
// of the body in bytes to prevent abuse.
|
||||||
|
m_parser->body_limit(std::numeric_limits<std::uint64_t>::max());
|
||||||
|
m_parser->header_limit(std::numeric_limits<std::uint32_t>::max());
|
||||||
|
m_buffer.clear();
|
||||||
|
|
||||||
|
// Set the timeout.
|
||||||
|
m_stream.expires_after(std::chrono::seconds(30));
|
||||||
|
boost::beast::http::async_read(
|
||||||
|
m_stream, m_buffer, *m_parser,
|
||||||
|
[self{shared_from_this()}](const boost::system::error_code &ec, std::size_t bytes_transferred) {
|
||||||
|
self->onRead(ec, bytes_transferred);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void HttpSession::onRead(boost::beast::error_code ec, std::size_t) {
|
||||||
|
using namespace boost::beast;
|
||||||
|
// This means they closed the connection
|
||||||
|
if (ec == http::error::end_of_stream) {
|
||||||
|
m_stream.socket().shutdown(boost::asio::ip::tcp::socket::shutdown_send, ec);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ec) {
|
||||||
|
if (ec == boost::asio::error::operation_aborted) return;
|
||||||
|
LOG(info) << ec << " : " << ec.message();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto &request = m_parser->get();
|
||||||
|
// See if it is a WebSocket Upgrade
|
||||||
|
if (websocket::is_upgrade(request)) {
|
||||||
|
// Create a websocket session, transferring ownership
|
||||||
|
// of both the socket and the HTTP request.
|
||||||
|
auto session = std::make_shared<WebSocketSession>(m_stream.release_socket(), m_state);
|
||||||
|
session->run(m_parser->release());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto path = boost::urls::parse_path(request.target());
|
||||||
|
if (!path) {
|
||||||
|
LOG(error) << request.target() << "failed, error: " << path.error().message();
|
||||||
|
errorReply(request, http::status::bad_request, "Illegal request-target");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
boost::urls::matches matches;
|
||||||
|
auto handler = m_state->find(*path, matches);
|
||||||
|
if (handler) {
|
||||||
|
(*handler)(*this, request, matches);
|
||||||
|
} else {
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "The resource '" << request.target() << "' was not found.";
|
||||||
|
auto message = oss.str();
|
||||||
|
errorReply(request, http::status::not_found, message);
|
||||||
|
LOG(error) << message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HttpSession::onWrite(boost::beast::error_code ec, std::size_t, bool close) {
|
||||||
|
if (ec) {
|
||||||
|
if (ec == boost::asio::error::operation_aborted) return;
|
||||||
|
std::cerr << "write: " << ec.message() << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (close) {
|
||||||
|
// This means we should close the connection, usually because
|
||||||
|
// the response indicated the "Connection: close" semantic.
|
||||||
|
m_stream.socket().shutdown(boost::asio::ip::tcp::socket::shutdown_send, ec);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read another request
|
||||||
|
doRead();
|
||||||
|
}
|
42
VoucherVerifyServer/HttpSession.h
Normal file
42
VoucherVerifyServer/HttpSession.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#ifndef HTTPSESSION_H
|
||||||
|
#define HTTPSESSION_H
|
||||||
|
|
||||||
|
#include "SharedState.h"
|
||||||
|
#include "boost/beast.hpp"
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
/** Represents an established HTTP connection
|
||||||
|
*/
|
||||||
|
class HttpSession : public std::enable_shared_from_this<HttpSession> {
|
||||||
|
void doRead();
|
||||||
|
void onRead(boost::beast::error_code ec, std::size_t);
|
||||||
|
void onWrite(boost::beast::error_code ec, std::size_t, bool close);
|
||||||
|
|
||||||
|
// void sendResponse(boost::beast::http::response<boost::beast::http::string_body> &&response);
|
||||||
|
|
||||||
|
public:
|
||||||
|
using Request = boost::beast::http::request<boost::beast::http::string_body>;
|
||||||
|
HttpSession(boost::asio::ip::tcp::socket &&socket, std::shared_ptr<SharedState> const &state);
|
||||||
|
template <typename Response>
|
||||||
|
void reply(Response &&response) {
|
||||||
|
using ResponseType = typename std::decay_t<decltype(response)>;
|
||||||
|
auto sp = std::make_shared<ResponseType>(std::forward<decltype(response)>(response));
|
||||||
|
boost::beast::http::async_write(
|
||||||
|
m_stream, *sp, [self = shared_from_this(), sp](boost::beast::error_code ec, std::size_t bytes) {
|
||||||
|
self->onWrite(ec, bytes, sp->need_eof());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
void errorReply(const Request &request, boost::beast::http::status status, boost::beast::string_view message);
|
||||||
|
|
||||||
|
void run();
|
||||||
|
|
||||||
|
private:
|
||||||
|
boost::beast::tcp_stream m_stream;
|
||||||
|
boost::beast::flat_buffer m_buffer{std::numeric_limits<std::uint32_t>::max()};
|
||||||
|
SharedStatePtr m_state;
|
||||||
|
std::optional<boost::beast::http::request_parser<boost::beast::http::string_body>> m_parser;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // HTTPSESSION_H
|
61
VoucherVerifyServer/Listener.cpp
Normal file
61
VoucherVerifyServer/Listener.cpp
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#include "Listener.h"
|
||||||
|
#include "BoostLog.h"
|
||||||
|
#include "HttpSession.h"
|
||||||
|
#include "SharedState.h"
|
||||||
|
#include <boost/asio/strand.hpp>
|
||||||
|
#include <boost/beast/core/error.hpp>
|
||||||
|
|
||||||
|
Listener::Listener(boost::asio::io_context &ioContext, const boost::asio::ip::tcp::endpoint &endpoint,
|
||||||
|
const std::shared_ptr<SharedState> &state)
|
||||||
|
: m_ioContext(ioContext), m_acceptor(ioContext), m_state(state) {
|
||||||
|
boost::beast::error_code error;
|
||||||
|
|
||||||
|
// Open the acceptor
|
||||||
|
m_acceptor.open(endpoint.protocol(), error);
|
||||||
|
if (error) {
|
||||||
|
LOG(error) << error.message();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow address reuse
|
||||||
|
m_acceptor.set_option(boost::asio::socket_base::reuse_address(true), error);
|
||||||
|
if (error) {
|
||||||
|
LOG(error) << error.message();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bind to the server address
|
||||||
|
m_acceptor.bind(endpoint, error);
|
||||||
|
if (error) {
|
||||||
|
LOG(error) << error.message();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start listening for connections
|
||||||
|
m_acceptor.listen(boost::asio::socket_base::max_listen_connections, error);
|
||||||
|
if (error) {
|
||||||
|
LOG(error) << error.message();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Listener::startAccept() {
|
||||||
|
auto client = std::make_shared<boost::asio::ip::tcp::socket>(boost::asio::make_strand(m_ioContext));
|
||||||
|
m_acceptor.async_accept(*client, [self{shared_from_this()}, client](const boost::system::error_code &ec) {
|
||||||
|
self->onAccept(ec, client);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void Listener::onAccept(boost::beast::error_code errorCode, std::shared_ptr<boost::asio::ip::tcp::socket> socket) {
|
||||||
|
if (errorCode) {
|
||||||
|
if (errorCode == boost::asio::error::operation_aborted) return;
|
||||||
|
LOG(error) << errorCode.message();
|
||||||
|
} else { // Launch a new session for this connection
|
||||||
|
if (!m_state.expired()) {
|
||||||
|
auto state = m_state.lock();
|
||||||
|
auto session = std::make_shared<HttpSession>(std::move(*socket), state);
|
||||||
|
session->run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
startAccept();
|
||||||
|
}
|
26
VoucherVerifyServer/Listener.h
Normal file
26
VoucherVerifyServer/Listener.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#ifndef __LISTENER_H__
|
||||||
|
#define __LISTENER_H__
|
||||||
|
|
||||||
|
#include <boost/asio/io_context.hpp>
|
||||||
|
#include <boost/asio/ip/tcp.hpp>
|
||||||
|
#include <boost/beast/core/error.hpp>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
class SharedState;
|
||||||
|
|
||||||
|
class Listener : public std::enable_shared_from_this<Listener> {
|
||||||
|
public:
|
||||||
|
Listener(boost::asio::io_context &ioContext, const boost::asio::ip::tcp::endpoint &endpoint,
|
||||||
|
const std::shared_ptr<SharedState> &state);
|
||||||
|
void startAccept();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void onAccept(boost::beast::error_code errorCode, std::shared_ptr<boost::asio::ip::tcp::socket> socket);
|
||||||
|
|
||||||
|
private:
|
||||||
|
boost::asio::io_context &m_ioContext;
|
||||||
|
boost::asio::ip::tcp::acceptor m_acceptor;
|
||||||
|
std::weak_ptr<SharedState> m_state;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // __LISTENER_H__
|
51
VoucherVerifyServer/ResponseUtility.cpp
Normal file
51
VoucherVerifyServer/ResponseUtility.cpp
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
#include "ResponseUtility.h"
|
||||||
|
#include "boost/beast.hpp"
|
||||||
|
|
||||||
|
namespace ResponseUtility {
|
||||||
|
|
||||||
|
std::string_view mimeType(std::string_view path) {
|
||||||
|
using boost::beast::iequals;
|
||||||
|
auto const ext = [&path] {
|
||||||
|
auto const pos = path.rfind(".");
|
||||||
|
if (pos == std::string_view::npos) return std::string_view{};
|
||||||
|
return path.substr(pos);
|
||||||
|
}();
|
||||||
|
if (iequals(ext, ".pdf")) return "Application/pdf";
|
||||||
|
if (iequals(ext, ".htm")) return "text/html";
|
||||||
|
if (iequals(ext, ".html")) return "text/html";
|
||||||
|
if (iequals(ext, ".php")) return "text/html";
|
||||||
|
if (iequals(ext, ".css")) return "text/css";
|
||||||
|
if (iequals(ext, ".txt")) return "text/plain";
|
||||||
|
if (iequals(ext, ".js")) return "application/javascript";
|
||||||
|
if (iequals(ext, ".json")) return "application/json";
|
||||||
|
if (iequals(ext, ".xml")) return "application/xml";
|
||||||
|
if (iequals(ext, ".swf")) return "application/x-shockwave-flash";
|
||||||
|
if (iequals(ext, ".flv")) return "video/x-flv";
|
||||||
|
if (iequals(ext, ".png")) return "image/png";
|
||||||
|
if (iequals(ext, ".jpe")) return "image/jpeg";
|
||||||
|
if (iequals(ext, ".jpeg")) return "image/jpeg";
|
||||||
|
if (iequals(ext, ".jpg")) return "image/jpeg";
|
||||||
|
if (iequals(ext, ".gif")) return "image/gif";
|
||||||
|
if (iequals(ext, ".bmp")) return "image/bmp";
|
||||||
|
if (iequals(ext, ".ico")) return "image/vnd.microsoft.icon";
|
||||||
|
if (iequals(ext, ".tiff")) return "image/tiff";
|
||||||
|
if (iequals(ext, ".tif")) return "image/tiff";
|
||||||
|
if (iequals(ext, ".svg")) return "image/svg+xml";
|
||||||
|
if (iequals(ext, ".svgz")) return "image/svg+xml";
|
||||||
|
return "application/text";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string pathCat(std::string_view base, std::string_view path) {
|
||||||
|
if (base.empty()) return std::string(path);
|
||||||
|
std::string result(base);
|
||||||
|
char constexpr path_separator = '/';
|
||||||
|
if (result.back() == path_separator && path.front() == path_separator) {
|
||||||
|
result.resize(result.size() - 1);
|
||||||
|
} else if (result.back() != path_separator && path.front() != path_separator) {
|
||||||
|
result.append("/");
|
||||||
|
}
|
||||||
|
result.append(path.data(), path.size());
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
} // namespace ResponseUtility
|
19
VoucherVerifyServer/ResponseUtility.h
Normal file
19
VoucherVerifyServer/ResponseUtility.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#ifndef RESPONSEUTILITY_H
|
||||||
|
#define RESPONSEUTILITY_H
|
||||||
|
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
|
namespace ResponseUtility {
|
||||||
|
/**
|
||||||
|
* @brief Return a reasonable mime type based on the extension of a file.
|
||||||
|
*/
|
||||||
|
std::string_view mimeType(std::string_view path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Append an HTTP rel-path to a local filesystem path.The returned path is normalized for the
|
||||||
|
* platform.
|
||||||
|
*/
|
||||||
|
std::string pathCat(std::string_view base, std::string_view path);
|
||||||
|
} // namespace ResponseUtility
|
||||||
|
|
||||||
|
#endif // RESPONSEUTILITY_H
|
34
VoucherVerifyServer/ServiceLogic.cpp
Normal file
34
VoucherVerifyServer/ServiceLogic.cpp
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#include "ServiceLogic.h"
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
namespace ServiceLogic {
|
||||||
|
|
||||||
|
boost::beast::http::response<boost::beast::http::string_body>
|
||||||
|
notFound(const boost::beast::http::request<boost::beast::http::string_body> &request) {
|
||||||
|
using namespace boost::beast;
|
||||||
|
http::response<http::string_body> res{http::status::not_found, request.version()};
|
||||||
|
res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
|
||||||
|
res.set(http::field::content_type, "text/html");
|
||||||
|
res.keep_alive(request.keep_alive());
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "The resource '" << request.target() << "' was not found.";
|
||||||
|
res.body() = oss.str();
|
||||||
|
res.prepare_payload();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::beast::http::response<boost::beast::http::string_body>
|
||||||
|
serverError(const boost::beast::http::request<boost::beast::http::string_body> &request,
|
||||||
|
std::string_view errorMessage) {
|
||||||
|
using namespace boost::beast;
|
||||||
|
http::response<http::string_body> res{http::status::internal_server_error, request.version()};
|
||||||
|
res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
|
||||||
|
res.set(http::field::content_type, "text/html");
|
||||||
|
res.keep_alive(request.keep_alive());
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "An error occurred: '" << errorMessage << "'";
|
||||||
|
res.body() = oss.str();
|
||||||
|
res.prepare_payload();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
} // namespace ServiceLogic
|
42
VoucherVerifyServer/ServiceLogic.h
Normal file
42
VoucherVerifyServer/ServiceLogic.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#ifndef SERVICELOGIC_H
|
||||||
|
#define SERVICELOGIC_H
|
||||||
|
|
||||||
|
#include "ResponseUtility.h"
|
||||||
|
#include "SharedState.h"
|
||||||
|
#include "StringUtility.h"
|
||||||
|
#include <boost/beast/http/message.hpp>
|
||||||
|
#include <boost/beast/http/string_body.hpp>
|
||||||
|
#include <boost/beast/http/vector_body.hpp>
|
||||||
|
#include <boost/beast/version.hpp>
|
||||||
|
#include <boost/uuid/uuid_generators.hpp>
|
||||||
|
#include <boost/uuid/uuid_io.hpp>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
using StringRequest = boost::beast::http::request<boost::beast::http::string_body>;
|
||||||
|
|
||||||
|
namespace ServiceLogic {
|
||||||
|
|
||||||
|
// Returns a not found response
|
||||||
|
boost::beast::http::response<boost::beast::http::string_body>
|
||||||
|
notFound(const boost::beast::http::request<boost::beast::http::string_body> &request);
|
||||||
|
|
||||||
|
// Returns a server error response
|
||||||
|
boost::beast::http::response<boost::beast::http::string_body>
|
||||||
|
serverError(const boost::beast::http::request<boost::beast::http::string_body> &request, std::string_view errorMessage);
|
||||||
|
|
||||||
|
template <class ResponseBody, class RequestBody>
|
||||||
|
boost::beast::http::response<ResponseBody> make_200(const boost::beast::http::request<RequestBody> &request,
|
||||||
|
typename ResponseBody::value_type body,
|
||||||
|
boost::beast::string_view content) {
|
||||||
|
boost::beast::http::response<ResponseBody> response{boost::beast::http::status::ok, request.version()};
|
||||||
|
response.set(boost::beast::http::field::server, BOOST_BEAST_VERSION_STRING);
|
||||||
|
response.set(boost::beast::http::field::content_type, content);
|
||||||
|
response.body() = body;
|
||||||
|
response.prepare_payload();
|
||||||
|
response.keep_alive(request.keep_alive());
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}; // namespace ServiceLogic
|
||||||
|
|
||||||
|
#endif // SERVICELOGIC_H
|
87
VoucherVerifyServer/SharedState.cpp
Normal file
87
VoucherVerifyServer/SharedState.cpp
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
#include "SharedState.h"
|
||||||
|
#include "HttpSession.h"
|
||||||
|
#include "ServiceLogic.h"
|
||||||
|
#include "WebsocketSession.h"
|
||||||
|
#include <boost/json/object.hpp>
|
||||||
|
#include <boost/json/serialize.hpp>
|
||||||
|
#include <boost/json/parse.hpp>
|
||||||
|
|
||||||
|
SharedState::SharedState(boost::asio::io_context &ioContext)
|
||||||
|
: m_ioContext(ioContext), m_router{std::make_shared<boost::urls::router<Handler>>()} {
|
||||||
|
|
||||||
|
m_router->insert("/", [](HttpSession &session, const Request &request, const boost::urls::matches &matches) {
|
||||||
|
// Send content message to client and wait to receive next request
|
||||||
|
session.reply(ServiceLogic::make_200<boost::beast::http::string_body>(request, "Main page\n", "text/html"));
|
||||||
|
});
|
||||||
|
|
||||||
|
m_router->insert("/device/access/valid",[](HttpSession &session, const Request &request, const boost::urls::matches &matches) {
|
||||||
|
LOG(info) << "request body: " << request.body();
|
||||||
|
auto requestValue = boost::json::parse(request.body());
|
||||||
|
auto &requestObject = requestValue.as_object();
|
||||||
|
|
||||||
|
boost::json::object root;
|
||||||
|
root["code"] = 0;
|
||||||
|
|
||||||
|
boost::json::object data;
|
||||||
|
data["sid"]=requestObject.at("sid").as_string();
|
||||||
|
data["vid"]=requestObject.at("sid").as_string();
|
||||||
|
data["pass"]=1;
|
||||||
|
data["code"]=0;
|
||||||
|
data["voucherPerson"]="amass";
|
||||||
|
data["voucherMsg"]="测试验票通过";
|
||||||
|
data["register"]=1;
|
||||||
|
data["effectTime"]="2024-01-15 00:30:35";
|
||||||
|
data["expireTime"]="2024-01-20 19:30:35";
|
||||||
|
|
||||||
|
root["data"] = std::move(data);
|
||||||
|
using namespace boost::beast;
|
||||||
|
http::response<http::string_body> res{http::status::ok, request.version()};
|
||||||
|
res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
|
||||||
|
res.set(http::field::content_type, "application/json");
|
||||||
|
res.keep_alive(request.keep_alive());
|
||||||
|
res.body() = boost::json::serialize(root);
|
||||||
|
res.prepare_payload();
|
||||||
|
session.reply(std::move(res));
|
||||||
|
});
|
||||||
|
|
||||||
|
m_router->insert(
|
||||||
|
"/device/access/report", [](HttpSession &session, const Request &request, const boost::urls::matches &matches) {
|
||||||
|
// Send content message to client and wait to receive next request
|
||||||
|
session.reply(ServiceLogic::make_200<boost::beast::http::string_body>(request, "Main page\n", "text/html"));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const SharedState::Handler *SharedState::find(boost::urls::segments_encoded_view path,
|
||||||
|
boost::urls::matches_base &matches) const noexcept {
|
||||||
|
return m_router->find(path, matches);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SharedState::join(WebSocketSession *session) {
|
||||||
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
|
sessions_.insert(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SharedState::leave(WebSocketSession *session) {
|
||||||
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
|
sessions_.erase(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SharedState::send(std::string message) {
|
||||||
|
// Put the message in a shared pointer so we can re-use it for each client
|
||||||
|
auto const ss = std::make_shared<std::string const>(std::move(message));
|
||||||
|
|
||||||
|
// Make a local list of all the weak pointers representing
|
||||||
|
// the sessions, so we can do the actual sending without
|
||||||
|
// holding the mutex:
|
||||||
|
std::vector<std::weak_ptr<WebSocketSession>> v;
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
|
v.reserve(sessions_.size());
|
||||||
|
for (auto p : sessions_) v.emplace_back(p->weak_from_this());
|
||||||
|
}
|
||||||
|
|
||||||
|
// For each session in our local list, try to acquire a strong
|
||||||
|
// pointer. If successful, then send the message on that session.
|
||||||
|
for (auto const &wp : v)
|
||||||
|
if (auto sp = wp.lock()) sp->send(ss);
|
||||||
|
}
|
50
VoucherVerifyServer/SharedState.h
Normal file
50
VoucherVerifyServer/SharedState.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#ifndef SHAREDSTATE_H
|
||||||
|
#define SHAREDSTATE_H
|
||||||
|
|
||||||
|
#include "router.hpp"
|
||||||
|
#include <boost/asio/io_context.hpp>
|
||||||
|
#include <boost/beast/http/string_body.hpp>
|
||||||
|
#include <boost/smart_ptr.hpp>
|
||||||
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
|
class HttpSession;
|
||||||
|
class WebSocketSession;
|
||||||
|
|
||||||
|
// Represents the shared server state
|
||||||
|
class SharedState : public std::enable_shared_from_this<SharedState> {
|
||||||
|
|
||||||
|
// This mutex synchronizes all access to sessions_
|
||||||
|
std::mutex mutex_;
|
||||||
|
|
||||||
|
// Keep a list of all the connected clients
|
||||||
|
std::unordered_set<WebSocketSession *> sessions_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using Request = boost::beast::http::request<boost::beast::http::string_body>;
|
||||||
|
using Handler = std::function<void(HttpSession &, const Request &, const boost::urls::matches &)>;
|
||||||
|
SharedState(boost::asio::io_context &ioContext);
|
||||||
|
|
||||||
|
const Handler *find(boost::urls::segments_encoded_view path, boost::urls::matches_base &matches) const noexcept;
|
||||||
|
|
||||||
|
void join(WebSocketSession *session);
|
||||||
|
void leave(WebSocketSession *session);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Broadcast a message to all websocket client sessions
|
||||||
|
*/
|
||||||
|
void send(std::string message);
|
||||||
|
|
||||||
|
private:
|
||||||
|
boost::asio::io_context &m_ioContext;
|
||||||
|
std::shared_ptr<boost::urls::router<Handler>> m_router;
|
||||||
|
std::string m_docRoot;
|
||||||
|
std::string m_galleryRoot = "/root/photos";
|
||||||
|
std::string m_fileRoot;
|
||||||
|
};
|
||||||
|
|
||||||
|
using SharedStatePtr = std::shared_ptr<SharedState>;
|
||||||
|
|
||||||
|
#endif // SHAREDSTATE_H
|
83
VoucherVerifyServer/WebsocketSession.cpp
Normal file
83
VoucherVerifyServer/WebsocketSession.cpp
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
#include "WebsocketSession.h"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
WebSocketSession::WebSocketSession(boost::asio::ip::tcp::socket &&socket, std::shared_ptr<SharedState> const &state)
|
||||||
|
: m_ws(std::move(socket)), m_state(state) {}
|
||||||
|
|
||||||
|
WebSocketSession::~WebSocketSession() {
|
||||||
|
// Remove this session from the list of active sessions
|
||||||
|
m_state->leave(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebSocketSession::onAccept(boost::beast::error_code ec) {
|
||||||
|
// Handle the error, if any
|
||||||
|
if (ec) {
|
||||||
|
if (ec == boost::asio::error::operation_aborted || ec == boost::beast::websocket::error::closed) return;
|
||||||
|
std::cerr << "accept: " << ec.message() << "\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add this session to the list of active sessions
|
||||||
|
m_state->join(this);
|
||||||
|
|
||||||
|
// Read a message
|
||||||
|
m_ws.async_read(m_buffer, boost::beast::bind_front_handler(&WebSocketSession::on_read, shared_from_this()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebSocketSession::on_read(boost::beast::error_code ec, std::size_t) {
|
||||||
|
// Handle the error, if any
|
||||||
|
if (ec) {
|
||||||
|
// Don't report these
|
||||||
|
if (ec == boost::asio::error::operation_aborted || ec == boost::beast::websocket::error::closed) return;
|
||||||
|
LOG(error) << "read: " << ec.message();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LOG(info) << boost::beast::buffers_to_string(m_buffer.data());
|
||||||
|
// Send to all connections
|
||||||
|
m_state->send(boost::beast::buffers_to_string(m_buffer.data()));
|
||||||
|
|
||||||
|
// Clear the buffer
|
||||||
|
m_buffer.consume(m_buffer.size());
|
||||||
|
|
||||||
|
// Read another message
|
||||||
|
m_ws.async_read(m_buffer, boost::beast::bind_front_handler(&WebSocketSession::on_read, shared_from_this()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebSocketSession::send(std::shared_ptr<std::string const> const &ss) {
|
||||||
|
// Post our work to the strand, this ensures
|
||||||
|
// that the members of `this` will not be
|
||||||
|
// accessed concurrently.
|
||||||
|
m_ws.text();
|
||||||
|
boost::asio::post(m_ws.get_executor(),
|
||||||
|
boost::beast::bind_front_handler(&WebSocketSession::onSend, shared_from_this(), ss));
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebSocketSession::onSend(std::shared_ptr<std::string const> const &ss) {
|
||||||
|
// Always add to queue
|
||||||
|
m_queue.push_back(ss);
|
||||||
|
|
||||||
|
// Are we already writing?
|
||||||
|
if (m_queue.size() > 1) return;
|
||||||
|
|
||||||
|
// We are not currently writing, so send this immediately
|
||||||
|
m_ws.async_write(boost::asio::buffer(*m_queue.front()),
|
||||||
|
boost::beast::bind_front_handler(&WebSocketSession::on_write, shared_from_this()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebSocketSession::on_write(boost::beast::error_code ec, std::size_t) {
|
||||||
|
// Handle the error, if any
|
||||||
|
if (ec) {
|
||||||
|
// Don't report these
|
||||||
|
if (ec == boost::asio::error::operation_aborted || ec == boost::beast::websocket::error::closed) return;
|
||||||
|
std::cerr << "write: " << ec.message() << "\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the string from the queue
|
||||||
|
m_queue.erase(m_queue.begin());
|
||||||
|
|
||||||
|
// Send the next message if any
|
||||||
|
if (!m_queue.empty())
|
||||||
|
m_ws.async_write(boost::asio::buffer(*m_queue.front()),
|
||||||
|
boost::beast::bind_front_handler(&WebSocketSession::on_write, shared_from_this()));
|
||||||
|
}
|
56
VoucherVerifyServer/WebsocketSession.h
Normal file
56
VoucherVerifyServer/WebsocketSession.h
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
#ifndef WEBSOCKETSESSION_H
|
||||||
|
#define WEBSOCKETSESSION_H
|
||||||
|
|
||||||
|
#include "BoostLog.h"
|
||||||
|
#include "SharedState.h"
|
||||||
|
#include <boost/beast.hpp>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class SharedState;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Represents an active WebSocket connection to the server
|
||||||
|
*/
|
||||||
|
class WebSocketSession : public std::enable_shared_from_this<WebSocketSession> {
|
||||||
|
|
||||||
|
public:
|
||||||
|
WebSocketSession(boost::asio::ip::tcp::socket &&socket, std::shared_ptr<SharedState> const &state);
|
||||||
|
|
||||||
|
~WebSocketSession();
|
||||||
|
|
||||||
|
template <class Body, class Allocator>
|
||||||
|
void run(boost::beast::http::request<Body, boost::beast::http::basic_fields<Allocator>> request) {
|
||||||
|
using namespace boost::beast::http;
|
||||||
|
using namespace boost::beast::websocket;
|
||||||
|
// Set suggested timeout settings for the websocket
|
||||||
|
m_ws.set_option(stream_base::timeout::suggested(boost::beast::role_type::server));
|
||||||
|
|
||||||
|
// Set a decorator to change the Server of the handshake
|
||||||
|
m_ws.set_option(stream_base::decorator([](response_type &response) {
|
||||||
|
response.set(field::server, std::string(BOOST_BEAST_VERSION_STRING) + " websocket-chat-multi");
|
||||||
|
}));
|
||||||
|
// LOG(info) << request.base().target(); //get path
|
||||||
|
// Accept the websocket handshake
|
||||||
|
m_ws.async_accept(request, [self{shared_from_this()}](boost::beast::error_code ec) { self->onAccept(ec); });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send a message
|
||||||
|
void send(std::shared_ptr<std::string const> const &ss);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void onAccept(boost::beast::error_code ec);
|
||||||
|
void on_read(boost::beast::error_code ec, std::size_t bytes_transferred);
|
||||||
|
void on_write(boost::beast::error_code ec, std::size_t bytes_transferred);
|
||||||
|
void onSend(std::shared_ptr<std::string const> const &ss);
|
||||||
|
|
||||||
|
private:
|
||||||
|
boost::beast::flat_buffer m_buffer;
|
||||||
|
boost::beast::websocket::stream<boost::beast::tcp_stream> m_ws;
|
||||||
|
std::shared_ptr<SharedState> m_state;
|
||||||
|
std::vector<std::shared_ptr<std::string const>> m_queue;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // WEBSOCKETSESSION_H
|
17
VoucherVerifyServer/main.cpp
Normal file
17
VoucherVerifyServer/main.cpp
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#include "BoostLog.h"
|
||||||
|
#include "IoContext.h"
|
||||||
|
#include "Listener.h"
|
||||||
|
#include "SharedState.h"
|
||||||
|
|
||||||
|
int main(int argc, char const *argv[])
|
||||||
|
{
|
||||||
|
using namespace boost::asio::ip;
|
||||||
|
boost::log::initialize("/data/sdcard/logs/VoucherVerifyServer", "/data/sdcard/logs");
|
||||||
|
auto ioContext = Amass::Singleton<IoContext>::instance<Amass::Construct>(std::thread::hardware_concurrency());
|
||||||
|
auto sharedState = Amass::Singleton<SharedState>::instance<Amass::Construct>(*ioContext->ioContext());
|
||||||
|
auto listener =
|
||||||
|
std::make_shared<Listener>(*ioContext->ioContext(), tcp::endpoint{tcp::v4(), 3392}, sharedState);
|
||||||
|
listener->startAccept();
|
||||||
|
ioContext->run<IoContext::Mode::Synchronous>();
|
||||||
|
return 0;
|
||||||
|
}
|
230
resources/build.sh
Executable file
230
resources/build.sh
Executable file
@ -0,0 +1,230 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
cross_compile=true
|
||||||
|
build_hisi=false
|
||||||
|
debug_deploy=true
|
||||||
|
TARGET_IP="172.16.103.79"
|
||||||
|
TARGET_PATH="/system/bin"
|
||||||
|
base_path=$(pwd)
|
||||||
|
libraries_root="/opt/Libraries"
|
||||||
|
if [ $base_path==/home/* ]; then
|
||||||
|
build_path=${base_path}/build
|
||||||
|
else
|
||||||
|
build_path=/tmp/build
|
||||||
|
fi
|
||||||
|
echo "build directory: $build_path"
|
||||||
|
|
||||||
|
function cmake_scan() {
|
||||||
|
if [ $cross_compile = true ]; then
|
||||||
|
toolchain_file=-DCMAKE_TOOLCHAIN_FILE=resources/cmake/toolchain.cmake
|
||||||
|
else
|
||||||
|
toolchain_file="-DCROSS_BUILD=OFF"
|
||||||
|
fi
|
||||||
|
if [ ! -d ${build_path} ]; then
|
||||||
|
mkdir ${build_path}
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $debug_deploy = true ]; then
|
||||||
|
build_debug=-DCMAKE_BUILD_TYPE=Debug
|
||||||
|
else
|
||||||
|
build_debug=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
cmake \
|
||||||
|
-G Ninja \
|
||||||
|
-S ${base_path} \
|
||||||
|
-B ${build_path} \
|
||||||
|
$build_debug \
|
||||||
|
$toolchain_file
|
||||||
|
}
|
||||||
|
|
||||||
|
function qtmoc(){
|
||||||
|
/opt/Qt/5.9.4/gcc_64/bin/moc src/qt/mainUi/mainUi.h -o src/qt/mainUi/moc_mainUi.cpp
|
||||||
|
/opt/Qt/5.9.4/gcc_64/bin/moc src/qt/utility/UiTools.h -o src/qt/utility/moc_UiTools.cpp
|
||||||
|
/opt/Qt/5.9.4/gcc_64/bin/moc src/qt/videoChatUi/CallWaittingPage.h -o src/qt/videoChatUi/moc_CallWaittingPage.cpp
|
||||||
|
/opt/Qt/5.9.4/gcc_64/bin/moc src/qt/videoChatUi/DialPadPage.h -o src/qt/videoChatUi/moc_DialPadPage.cpp
|
||||||
|
/opt/Qt/5.9.4/gcc_64/bin/moc src/qt/videoChatUi/VideoChatPage.h -o src/qt/videoChatUi/moc_VideoChatPage.cpp
|
||||||
|
/opt/Qt/5.9.4/gcc_64/bin/moc src/qt/recoUi/recoUi.h -o src/qt/recoUi/moc_recoUi.cpp
|
||||||
|
/opt/Qt/5.9.4/gcc_64/bin/moc src/qt/recoUi/recoUiRecognize.h -o src/qt/recoUi/moc_recoUiRecognize.cpp
|
||||||
|
/opt/Qt/5.9.4/gcc_64/bin/moc src/qt/utility/DndModeCountDownItem.h -o src/qt/utility/moc_DndModeCountDownItem.cpp
|
||||||
|
}
|
||||||
|
|
||||||
|
function build() {
|
||||||
|
if [ ! -f "${build_path}/CMakeCache.txt" ]; then
|
||||||
|
cmake_scan
|
||||||
|
fi
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
cmake \
|
||||||
|
--build ${build_path} \
|
||||||
|
--target all
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $cross_compile = true ]; then
|
||||||
|
deploy
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function deploy() {
|
||||||
|
# export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/system/lib
|
||||||
|
if [ -n "$1" ]; then
|
||||||
|
TARGET_IP=$1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $debug_deploy = true ]; then
|
||||||
|
TARGET_PATH="/data/sdcard"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "deploy to target $TARGET_IP, path: ${TARGET_PATH} ..."
|
||||||
|
ssh -i resources/ssh_host_rsa_key_ok root@${TARGET_IP} "mount -o remount rw /system/"
|
||||||
|
ssh -i ~/Projects/ssh_host_rsa_key_ok root@${TARGET_IP} "killall start-app.sh; pgrep -f GateFace | xargs kill -s 9"
|
||||||
|
ssh -i resources/ssh_host_rsa_key_ok root@${TARGET_IP} "pgrep -f VoucherVerifyServer | xargs kill -s 9"
|
||||||
|
ssh -i resources/ssh_host_rsa_key_ok root@${TARGET_IP} "pgrep -f Record | xargs kill -s 9"
|
||||||
|
|
||||||
|
scp -i ~/Projects/ssh_host_rsa_key_ok ${build_path}/src/gate_face/GateFace root@${TARGET_IP}:${TARGET_PATH}
|
||||||
|
# scp -i ~/Projects/ssh_host_rsa_key_ok ${build_path}/ThirdParty/librwSrvProtocol.so root@${TARGET_IP}:/system/lib/
|
||||||
|
scp -i resources/ssh_host_rsa_key_ok ${build_path}/Tools/Record/Record root@${TARGET_IP}:/sdcard/
|
||||||
|
scp -i resources/ssh_host_rsa_key_ok ${build_path}/Tools/Record/rkmedia_audio_test root@${TARGET_IP}:/sdcard/
|
||||||
|
scp -i resources/ssh_host_rsa_key_ok ./3rdparty/arm-linux-gnueabihf/mpp/rk-libs/libeasymedia.so.1.0.1 root@${TARGET_IP}:/system/lib/
|
||||||
|
|
||||||
|
ssh -i resources/ssh_host_rsa_key_ok root@${TARGET_IP} "sync"
|
||||||
|
|
||||||
|
if [ $debug_deploy != true ]; then
|
||||||
|
echo "reboot remote device."
|
||||||
|
ssh -i resources/ssh_host_rsa_key_ok root@${TARGET_IP} "reboot"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function clean() {
|
||||||
|
if [ -d ${build_path} ]; then
|
||||||
|
rm -fr ${build_path}
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function copy_ssh() {
|
||||||
|
if [ -n "$1" ]; then
|
||||||
|
TARGET_IP=$1
|
||||||
|
fi
|
||||||
|
SSH_KEY=$(cat ~/.ssh/id_rsa.pub)
|
||||||
|
echo "ssh copy id to ${TARGET_IP} ..."
|
||||||
|
# chmod 600 ./resources/ssh_host_rsa_key_ok
|
||||||
|
ssh -i ~/Projects/ssh_host_rsa_key_ok root@${TARGET_IP} "mount -o remount rw /oem/;mount -o remount rw /system/; mount -o remount rw /"
|
||||||
|
ssh -i ~/Projects/ssh_host_rsa_key_ok root@${TARGET_IP} "if [ ! -f /usr/bin/scp ]; then cp /oem/bin/scp /usr/bin/; else echo 'scp exist'; fi"
|
||||||
|
ssh -i ~/Projects/ssh_host_rsa_key_ok root@${TARGET_IP} "echo ${SSH_KEY} >> /oem/.ssh/authorized_keys"
|
||||||
|
scp -i ~/Projects/ssh_host_rsa_key_ok /mnt/e/Documents/gdb-rk root@${TARGET_IP}:/sdcard/gdb
|
||||||
|
scp -i ~/Projects/ssh_host_rsa_key_ok ./3rdparty/arm-linux-gnueabihf/mpp/rk-libs/libeasymedia.so.1.0.1 root@${TARGET_IP}:/usr/lib/
|
||||||
|
scp -i ~/Projects/ssh_host_rsa_key_ok /opt/toolchains/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/bin/gdbserver root@${TARGET_IP}:/sdcard
|
||||||
|
scp -i ~/Projects/ssh_host_rsa_key_ok /opt/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/boost_1_84_0/lib/libboost_url* root@${TARGET_IP}:/system/lib
|
||||||
|
scp -i ~/Projects/ssh_host_rsa_key_ok /opt/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/boost_1_84_0/lib/libboost_log* root@${TARGET_IP}:/system/lib
|
||||||
|
scp -i ~/Projects/ssh_host_rsa_key_ok /opt/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/boost_1_84_0/lib/libboost_program_options* root@${TARGET_IP}:/system/lib
|
||||||
|
scp -i ~/Projects/ssh_host_rsa_key_ok /opt/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/boost_1_84_0/lib/libboost_date_time* root@${TARGET_IP}:/system/lib
|
||||||
|
scp -i ~/Projects/ssh_host_rsa_key_ok /opt/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/boost_1_84_0/lib/libboost_filesystem* root@${TARGET_IP}:/system/lib
|
||||||
|
scp -i ~/Projects/ssh_host_rsa_key_ok /opt/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/boost_1_84_0/lib/libboost_thread* root@${TARGET_IP}:/system/lib
|
||||||
|
scp -i ~/Projects/ssh_host_rsa_key_ok /opt/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/boost_1_84_0/lib/libboost_regex* root@${TARGET_IP}:/system/lib
|
||||||
|
scp -i ~/Projects/ssh_host_rsa_key_ok /opt/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/boost_1_84_0/lib/libboost_chrono* root@${TARGET_IP}:/system/lib
|
||||||
|
scp -i ~/Projects/ssh_host_rsa_key_ok /opt/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/boost_1_84_0/lib/libboost_atomic* root@${TARGET_IP}:/system/lib
|
||||||
|
scp -i ~/Projects/ssh_host_rsa_key_ok /opt/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/boost_1_84_0/lib/libboost_container* root@${TARGET_IP}:/system/lib
|
||||||
|
scp -i ~/Projects/ssh_host_rsa_key_ok /opt/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/boost_1_84_0/lib/libboost_json* root@${TARGET_IP}:/system/lib
|
||||||
|
ssh -i ~/Projects/ssh_host_rsa_key_ok root@${TARGET_IP} "sync"
|
||||||
|
}
|
||||||
|
|
||||||
|
function deploy_old(){
|
||||||
|
if [ -n "$1" ]; then
|
||||||
|
TARGET_IP=$1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $debug_deploy = true ]; then
|
||||||
|
TARGET_PATH="/data/sdcard"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# qtmoc
|
||||||
|
# if [ $? -ne 0 ]; then
|
||||||
|
# exit 1
|
||||||
|
# fi
|
||||||
|
|
||||||
|
if [ $build_hisi = true ]; then
|
||||||
|
docker run --rm -v /opt:/opt -v .:$(pwd) -w $(pwd) b020_dev make server_protocol
|
||||||
|
docker run --rm -v /opt:/opt -v .:$(pwd) -w $(pwd) b020_dev make
|
||||||
|
else
|
||||||
|
# docker run --rm -v .:$(pwd) -w $(pwd) b020_dev protoc --nanopb_out=./ 3rdparty/rwSrvProtocol/PacketModel_all.proto
|
||||||
|
# make PLATFORM=rv1109 server_protocol
|
||||||
|
# if [ $? -ne 0 ]; then
|
||||||
|
# exit 1
|
||||||
|
# fi
|
||||||
|
make PLATFORM=rv1109 -j4
|
||||||
|
fi
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "deply to $TARGET_IP, path $TARGET_PATH"
|
||||||
|
ssh -i ~/Projects/ssh_host_rsa_key_ok root@${TARGET_IP} "mount -o remount rw /; mount -o remount rw /system/"
|
||||||
|
|
||||||
|
if [ $build_hisi = true ]; then
|
||||||
|
ssh -i ~/Projects/ssh_host_rsa_key_ok root@${TARGET_IP} "killall start-app.sh; killall GateFace; sleep 1"
|
||||||
|
ssh -i ~/Projects/ssh_host_rsa_key_ok root@${TARGET_IP} "killall start-app.sh; killall GateFace"
|
||||||
|
ssh -i ~/Projects/ssh_host_rsa_key_ok root@${TARGET_IP} "killall start-app.sh; killall GateFace"
|
||||||
|
else
|
||||||
|
ssh -i ~/Projects/ssh_host_rsa_key_ok root@${TARGET_IP} "killall start-app.sh; killall GateFace; killall netconfig"
|
||||||
|
fi
|
||||||
|
# scp -i ~/Projects/ssh_host_rsa_key_ok ./3rdparty/arm-linux-gnueabihf/mpp/rk-libs/libeasymedia.so.1.0.1 root@${TARGET_IP}:/usr/lib/
|
||||||
|
# scp -i ~/Projects/ssh_host_rsa_key_ok ./3rdparty/arm-linux-gnueabihf/rkap_3a/lib/libRKAP_3A.so root@${TARGET_IP}:/system/lib/
|
||||||
|
# scp -i ~/Projects/ssh_host_rsa_key_ok ./3rdparty/arm-linux-gnueabihf/rkap_3a/lib/libRKAP_Common.so root@${TARGET_IP}:/system/lib/
|
||||||
|
# scp -i ~/Projects/ssh_host_rsa_key_ok ./3rdparty/arm-linux-gnueabihf/rkap_3a/lib/libRKAP_ANR.so root@${TARGET_IP}:/system/lib/
|
||||||
|
|
||||||
|
# scp -r -i ~/Projects/ssh_host_rsa_key_ok src/web/php/*.php root@${TARGET_IP}:/system/www/web/
|
||||||
|
scp -i ~/Projects/ssh_host_rsa_key_ok ./build/GateFace root@${TARGET_IP}:$TARGET_PATH
|
||||||
|
# scp -i ~/Projects/ssh_host_rsa_key_ok ./build/netconfig root@${TARGET_IP}:$TARGET_PATH
|
||||||
|
# scp -i ~/Projects/ssh_host_rsa_key_ok ./src/netlink/libRwNetlink.so root@${TARGET_IP}:/system/lib/
|
||||||
|
|
||||||
|
|
||||||
|
if [ $build_hisi = true ]; then
|
||||||
|
echo "."
|
||||||
|
ssh -i ~/Projects/ssh_host_rsa_key_ok root@${TARGET_IP} "reboot"
|
||||||
|
else
|
||||||
|
# scp -i ~/Projects/ssh_host_rsa_key_ok ./3rdparty/arm-linux-gnueabihf/librwhscheckpw/lib/librwhscheckpw.so root@${TARGET_IP}:/system/lib/
|
||||||
|
scp -i ~/Projects/ssh_host_rsa_key_ok ./3rdparty/arm-linux-gnueabihf/rwStageProtocol/lib/librwSrvProtocol.so root@${TARGET_IP}:/system/lib/
|
||||||
|
# scp -i ~/Projects/ssh_host_rsa_key_ok ./3rdparty/arm-linux-gnueabihf/ffmepg/lib/libavdevice.so.58 root@${TARGET_IP}:/system/lib/
|
||||||
|
# scp -i ~/Projects/ssh_host_rsa_key_ok ./3rdparty/arm-linux-gnueabihf/ffmepg/lib/libavfilter.so.7 root@${TARGET_IP}:/system/lib/
|
||||||
|
# scp -i ~/Projects/ssh_host_rsa_key_ok ./3rdparty/arm-linux-gnueabihf/ffmepg/lib/libavformat.so.58 root@${TARGET_IP}:/system/lib/
|
||||||
|
# scp -i ~/Projects/ssh_host_rsa_key_ok ./3rdparty/arm-linux-gnueabihf/ffmepg/lib/libavutil.so.56 root@${TARGET_IP}:/system/lib/
|
||||||
|
# scp -i ~/Projects/ssh_host_rsa_key_ok ./3rdparty/arm-linux-gnueabihf/ffmepg/lib/libswresample.so.3 root@${TARGET_IP}:/system/lib/
|
||||||
|
fi
|
||||||
|
|
||||||
|
ssh -i ~/Projects/ssh_host_rsa_key_ok root@${TARGET_IP} "sync"
|
||||||
|
|
||||||
|
if [ $debug_deploy = false ]; then
|
||||||
|
if [ $build_hisi = false ]; then
|
||||||
|
ssh -i ~/Projects/ssh_host_rsa_key_ok root@${TARGET_IP} "echo 1 > /dev/watchdog"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function main() {
|
||||||
|
local cmd=$1
|
||||||
|
shift 1
|
||||||
|
case $cmd in
|
||||||
|
build)
|
||||||
|
build
|
||||||
|
;;
|
||||||
|
scan)
|
||||||
|
cmake_scan
|
||||||
|
;;
|
||||||
|
clean)
|
||||||
|
clean
|
||||||
|
;;
|
||||||
|
old)
|
||||||
|
deploy_old $@
|
||||||
|
;;
|
||||||
|
ssh)
|
||||||
|
copy_ssh $@
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
build
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
main $@
|
41
resources/cmake/FindQt5.cmake
Normal file
41
resources/cmake/FindQt5.cmake
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
add_library(Qt5::Core SHARED IMPORTED)
|
||||||
|
set_target_properties(Qt5::Core PROPERTIES
|
||||||
|
IMPORTED_LOCATION ${QT5_ROOT}/lib/libQt5Core.so
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES ${QT5_ROOT}/include/QtCore
|
||||||
|
)
|
||||||
|
target_include_directories(Qt5::Core
|
||||||
|
INTERFACE ${QT5_ROOT}/include
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(Qt5::Core
|
||||||
|
INTERFACE rga
|
||||||
|
INTERFACE drm
|
||||||
|
INTERFACE z
|
||||||
|
INTERFACE png16
|
||||||
|
INTERFACE pcre
|
||||||
|
INTERFACE pcre2-16
|
||||||
|
INTERFACE gthread-2.0
|
||||||
|
INTERFACE glib-2.0
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(Qt5::Gui SHARED IMPORTED)
|
||||||
|
set_target_properties(Qt5::Gui PROPERTIES
|
||||||
|
IMPORTED_LOCATION ${QT5_ROOT}/lib/libQt5Gui.so
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES ${QT5_ROOT}/include/QtGui
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(Qt5::Widgets SHARED IMPORTED)
|
||||||
|
set_target_properties(Qt5::Widgets PROPERTIES
|
||||||
|
IMPORTED_LOCATION ${QT5_ROOT}/lib/libQt5Widgets.so
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES ${QT5_ROOT}/include/QtWidgets
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(Qt5::Widgets
|
||||||
|
INTERFACE ${QT5_ROOT}/include
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(Qt5::Network SHARED IMPORTED)
|
||||||
|
set_target_properties(Qt5::Network PROPERTIES
|
||||||
|
IMPORTED_LOCATION ${QT5_ROOT}/lib/libQt5Network.so
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES ${QT5_ROOT}/include/QtNetwork
|
||||||
|
)
|
25
resources/cmake/hisi_toolchain.cmake
Normal file
25
resources/cmake/hisi_toolchain.cmake
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
set(CMAKE_SYSTEM_NAME Linux)
|
||||||
|
set(CMAKE_SYSTEM_PROCESSOR arm)
|
||||||
|
|
||||||
|
# which compilers to use for C and C++
|
||||||
|
set(CMAKE_C_COMPILER arm-himix200-linux-gcc)
|
||||||
|
set(CMAKE_CXX_COMPILER arm-himix200-linux-g++)
|
||||||
|
|
||||||
|
# where is the target environment located
|
||||||
|
# set(CMAKE_FIND_ROOT_PATH /usr/i586-mingw32msvc
|
||||||
|
# /home/alex/mingw-install)
|
||||||
|
|
||||||
|
# adjust the default behavior of the FIND_XXX() commands:
|
||||||
|
# search programs in the host environment
|
||||||
|
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||||
|
|
||||||
|
# search headers and libraries in the target environment
|
||||||
|
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||||
|
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||||
|
|
||||||
|
set(CMAKE_C_COMPILER_FORCED ON)
|
||||||
|
set(CMAKE_CXX_COMPILER_FORCED ON)
|
||||||
|
|
||||||
|
string(APPEND CMAKE_CXX_FLAGS " -mfloat-abi=softfp -mfpu=neon")
|
||||||
|
|
||||||
|
set(BOOST_ROOT /opt/toolchains/Libraries/boost_1_83_0)
|
22
resources/cmake/toolchain.cmake
Normal file
22
resources/cmake/toolchain.cmake
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
set(CMAKE_SYSTEM_NAME Linux)
|
||||||
|
set(CMAKE_SYSTEM_PROCESSOR arm)
|
||||||
|
|
||||||
|
# which compilers to use for C and C++
|
||||||
|
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
|
||||||
|
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
|
||||||
|
|
||||||
|
# where is the target environment located
|
||||||
|
# set(CMAKE_FIND_ROOT_PATH /usr/i586-mingw32msvc
|
||||||
|
# /home/alex/mingw-install)
|
||||||
|
|
||||||
|
# adjust the default behavior of the FIND_XXX() commands:
|
||||||
|
# search programs in the host environment
|
||||||
|
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||||
|
|
||||||
|
# search headers and libraries in the target environment
|
||||||
|
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||||
|
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||||
|
|
||||||
|
string(APPEND CMAKE_CXX_FLAGS " -mfloat-abi=hard -mfpu=neon")
|
||||||
|
|
||||||
|
set(BOOST_ROOT /opt/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/lib/boost_1_85_0)
|
77
resources/deploy.sh
Normal file
77
resources/deploy.sh
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
TARGET_IP="192.168.8.108"
|
||||||
|
|
||||||
|
function build() {
|
||||||
|
if [ -n "$1" ]; then
|
||||||
|
TARGET_IP=$1
|
||||||
|
fi
|
||||||
|
|
||||||
|
make PLATFORM=rv1109 server_protocol
|
||||||
|
make PLATFORM=rv1109
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "deply to $TARGET_IP"
|
||||||
|
ssh -i ~/Projects/ssh_host_rsa_key_ok root@${TARGET_IP} "mount -o remount rw /system/"
|
||||||
|
ssh -i ~/Projects/ssh_host_rsa_key_ok root@${TARGET_IP} "killall start-app.sh; pkill -f GateFace"
|
||||||
|
ssh -i ~/Projects/ssh_host_rsa_key_ok root@${TARGET_IP} "pgrep -f netconfig | xargs kill -s 9"
|
||||||
|
ssh -i ~/Projects/ssh_host_rsa_key_ok root@${TARGET_IP} "pgrep -f voucher_verify | xargs kill -s 9"
|
||||||
|
scp -r -i ~/Projects/ssh_host_rsa_key_ok src/web/php/*.php root@${TARGET_IP}:/system/www/web/
|
||||||
|
scp -i ~/Projects/ssh_host_rsa_key_ok ./build/GateFace root@${TARGET_IP}:/system/bin
|
||||||
|
scp -i ~/Projects/ssh_host_rsa_key_ok ./build/voucher_verify root@${TARGET_IP}:/system/bin
|
||||||
|
scp -i ~/Projects/ssh_host_rsa_key_ok ./src/netlink/libRwNetlink.so root@${TARGET_IP}:/system/lib
|
||||||
|
scp -i ~/Projects/ssh_host_rsa_key_ok ./build/netconfig root@${TARGET_IP}:/system/bin
|
||||||
|
scp -i ~/Projects/ssh_host_rsa_key_ok ./3rdparty/arm-linux-gnueabihf/rwStageProtocol/lib/librwSrvProtocol.so root@${TARGET_IP}:/system/lib/
|
||||||
|
|
||||||
|
ssh -i ~/Projects/ssh_host_rsa_key_ok root@${TARGET_IP} "sync"
|
||||||
|
|
||||||
|
ssh -i ~/Projects/ssh_host_rsa_key_ok root@${TARGET_IP} "echo 1 > /dev/watchdog"
|
||||||
|
}
|
||||||
|
|
||||||
|
function build_debug() {
|
||||||
|
make PLATFORM=rv1109 server_protocol
|
||||||
|
scp -r -i ~/Projects/ssh_host_rsa_key_ok 3rdparty/arm-linux-gnueabihf/rwStageProtocol/lib/librwSrvProtocol.so root@${TARGET_IP}:/system/lib/
|
||||||
|
make PLATFORM=rv1109
|
||||||
|
echo "deply to /sdcard"
|
||||||
|
ssh -i ~/Projects/ssh_host_rsa_key_ok root@${TARGET_IP} "mount -o remount rw /system/"
|
||||||
|
ssh -i ~/Projects/ssh_host_rsa_key_ok root@${TARGET_IP} "pkill -f start-app.sh & pkill -f GateFace & pkill -f dk_uart_id_reader"
|
||||||
|
scp -r -i ~/Projects/ssh_host_rsa_key_ok src/web/php/*.php root@${TARGET_IP}:/system/www/web/
|
||||||
|
scp -i ~/Projects/ssh_host_rsa_key_ok ./build/GateFace root@${TARGET_IP}:/sdcard
|
||||||
|
scp -i ~/Projects/ssh_host_rsa_key_ok ./build/ryxconnector root@${TARGET_IP}:/sdcard
|
||||||
|
ssh -i ~/Projects/ssh_host_rsa_key_ok root@${TARGET_IP} "sync"
|
||||||
|
ssh -i ~/Projects/ssh_host_rsa_key_ok root@${TARGET_IP} "amixer sset 'Master' 80%"
|
||||||
|
}
|
||||||
|
|
||||||
|
function copy_ssh() {
|
||||||
|
TARGET_IP=$1
|
||||||
|
SSH_KEY=$(cat ~/.ssh/id_rsa.pub)
|
||||||
|
echo "ssh copy id to ${TARGET_IP} ..."
|
||||||
|
ssh -i ~/Projects/ssh_host_rsa_key_ok root@${TARGET_IP} "mount -o remount rw /oem/; mount -o remount rw /"
|
||||||
|
ssh -i ~/Projects/ssh_host_rsa_key_ok root@${TARGET_IP} "if [ ! -f /usr/bin/scp ]; then cp /oem/bin/scp /usr/bin/; else echo 'scp exist'; fi"
|
||||||
|
ssh -i ~/Projects/ssh_host_rsa_key_ok root@${TARGET_IP} "echo ${SSH_KEY} >> /oem/.ssh/authorized_keys"
|
||||||
|
scp -i ~/Projects/ssh_host_rsa_key_ok /mnt/e/Documents/gdb-rk root@${TARGET_IP}:/sdcard
|
||||||
|
scp -i ~/Projects/ssh_host_rsa_key_ok /opt/toolchains/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/bin/gdbserver root@${TARGET_IP}:/sdcard
|
||||||
|
ssh -i ~/Projects/ssh_host_rsa_key_ok root@${TARGET_IP} "sync"
|
||||||
|
}
|
||||||
|
|
||||||
|
function main() {
|
||||||
|
local cmd=$1
|
||||||
|
shift 1
|
||||||
|
case $cmd in
|
||||||
|
build)
|
||||||
|
build $@
|
||||||
|
;;
|
||||||
|
debug)
|
||||||
|
build_debug
|
||||||
|
;;
|
||||||
|
ssh)
|
||||||
|
copy_ssh $@
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
build
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
main $@
|
27
resources/ssh_host_rsa_key_ok
Normal file
27
resources/ssh_host_rsa_key_ok
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
MIIEogIBAAKCAQEAnqnYt7KJAQ5bhO/MgyWUg6QV5ICWbQX/cqzxpKKPyQQuJbUz
|
||||||
|
ML2lKPz5ogsv+pn7Hgh+SvCSN6iF/9Rtr5fD5I8COZxLlWbC3fz6J+2hPtvjCvdI
|
||||||
|
sMe0PvKxUa7vsujnUzkwpBjRcHG/gBF0P6UWvZBVbtn6jwP9ufYcAI7jYMI3YBk5
|
||||||
|
PNOowdcAoRiwTe2KnJzQNj2ztUE6VFgo3U5gyoGKfxNDi8P2aMWW3xARLJHh3hbR
|
||||||
|
Ztmwz8eDWD9L2c6fn61t9yqpyCRepE33+yC7m1Jdgxx+FWQBBfExwJaSBbWXyT1f
|
||||||
|
13v4ElSJXk4zWkeB1ddv76MZqDM9kRLJB/1WcQIDAQABAoIBAArexBRBzRUfcLG4
|
||||||
|
5CAQEQ67zSwsiyHJCWlH4/5NjOBOwwKeWXV7aLdYLZomfhEDP6sdFdn4hWv+xb9z
|
||||||
|
RFiFY0xjZ9melacUtUEUNedKZoOx+OolavuBkx3E7tUT0SRGxKJ1BpoXgTHc+SvD
|
||||||
|
Bl3d56LxIolHsdzefyGgdOas43Mbf6RHbAnXA65VyYf/k7fY4GkrO8/hKTXos32R
|
||||||
|
fNV0OD8qq8+KTwgnYXBKrjbie6N5XmOS9IcLFNC8F+0PC5NO+xzOk1McnmMux7t9
|
||||||
|
EwUj8/VXAYZPFRkEZdhmdzMgs9dpT9n+L13XppJLAAGEvFySFOGjEz2HWT7Hf5qB
|
||||||
|
z/ct9ukCgYEAzjV7V82ueeUTqMM8Hm6RV8MwpJxVwUABOQ934DuBO/p8oMqy9qlA
|
||||||
|
V02oJVnA5gMhCKKSr3dZa4+JG3BubrOh9tGEcw4pXIYEAAB6qWxsyHhNPcTrjYNS
|
||||||
|
mF5TFKgfY9uJ4p2b+YKYAuwyucdQf7kNQTEz/eYHOkardfGF00dlAo8CgYEAxPlo
|
||||||
|
nCUxaWW+rPI1wiP5F0BMhxrR4H592BajQQ1i/3IBUny43rRO2Sqd0E4xQzmTaGbi
|
||||||
|
qJtBGvS0DGMHOHfJ/5ha6xPiUFk1TJuRtb5P/uwdtJe6YZHeYz/yEDu07hKdUySs
|
||||||
|
J7oXlxORxcDphmYiVlM5ARy7h3SlLZEaGocglv8CgYAJWE8gqYeQqpr7eO2Oi4A2
|
||||||
|
s/fOXe9c9KOZjGPoW4n9x9pCBy2ZFA6AZlqKZsjhI58pnwR6wzPgNf8GqU+34Jgk
|
||||||
|
cVZJSIkDUmd4AI2OhAViCGGnvPbX0O27TfsB4qSZh+d1x6K76fktmLqrxKaXQzGg
|
||||||
|
lLRAe140e+NlUu63pnKjbQKBgB6A1S9hHx7IT9fuhl6zPW7ZWUCO6bOPQyPElbGM
|
||||||
|
Rily2TuR7vsmBxPgYqIQidZ0Qxym2jDsIg/vlzZX25VmD5USXfoLkT+KIRPk/5Ka
|
||||||
|
jz7WB9+go49ajIroKy9SX7mCjnSCuFpKmj6eHDP4pPFYPbcKmkhOz8exS6cb0mQL
|
||||||
|
SwO3AoGAYhzb7EHOTDfhtJQ0d49/8jUXprrGdExs2u88Gv8WjLsLaMm9hmNzY13M
|
||||||
|
i2wkM1ZOZag1XwvznVdLoM7lt62evtnocnEIysiiNaryoPFw/NCndNNG6mealVut
|
||||||
|
1Xr3rUQS9HOYeIYW5IFUfCv7aMFnEqd6AWdvWJ69uMIt7Wgp5yo=
|
||||||
|
-----END RSA PRIVATE KEY-----
|
Loading…
Reference in New Issue
Block a user