luckfox-pico-sdk/media/samples/simple_test/simple_ai_bind_aenc.c
luckfox-eng29 8f34c2760d project:build.sh: Added fastboot support; custom modifications to U-Boot and kernel implemented using patches.
project:cfg:BoardConfig_IPC: Added fastboot BoardConfig file and firmware post-scripts, distinguishing between
the BoardConfigs for Luckfox Pico Pro and Luckfox Pico Max. project:app: Added fastboot_client and rk_smart_door
for quick boot applications; updated rkipc app to adapt to the latest media library. media:samples: Added more
usage examples. media:rockit: Fixed bugs; removed support for retrieving data frames from VPSS. media:isp:
Updated rkaiq library and related tools to support connection to RKISP_Tuner. sysdrv:Makefile: Added support for
compiling drv_ko on Luckfox Pico Ultra W using Ubuntu; added support for custom root filesystem.
sysdrv:tools:board: Updated Buildroot optional mirror sources, updated some software versions, and stored device
tree files and configuration files that undergo multiple modifications for U-Boot and kernel separately.
sysdrv:source:mcu: Used RISC-V MCU SDK with RT-Thread system, mainly for initializing camera AE during quick
boot. sysdrv:source:uboot: Added support for fastboot; added high baud rate DDR bin for serial firmware upgrades.
sysdrv:source:kernel: Upgraded to version 5.10.160; increased NPU frequency for RV1106G3; added support for
fastboot.

Signed-off-by: luckfox-eng29 <eng29@luckfox.com>
2024-10-14 09:47:04 +08:00

341 lines
9.2 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// ai->aenc
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/poll.h>
#include <unistd.h>
#include "rk_debug.h"
#include "rk_defines.h"
#include "rk_mpi_aenc.h"
#include "rk_mpi_ai.h"
#include "rk_mpi_amix.h"
#include "rk_mpi_mb.h"
#include "rk_mpi_sys.h"
static bool quit = false;
static void sigterm_handler(int sig) {
fprintf(stderr, "signal %d\n", sig);
quit = true;
}
static RK_U32 code_type = RK_AUDIO_ID_ADPCM_G726;
static FILE *save_file;
//声音质量增强
RK_S32 init_ai_vqe(RK_S32 s32SampleRate) {
AI_VQE_CONFIG_S stAiVqeConfig, stAiVqeConfig2;
RK_S32 result;
RK_S32 s32VqeGapMs = 16;
int s32DevId = 0;
int s32ChnIndex = 0;
const char *pVqeCfgPath = "/oem/usr/share/vqefiles/config_aivqe.json";
// Need to config enCfgMode to VQE attr even the VQE is not enabled
memset(&stAiVqeConfig, 0, sizeof(AI_VQE_CONFIG_S));
if (pVqeCfgPath != RK_NULL) {
stAiVqeConfig.enCfgMode = AIO_VQE_CONFIG_LOAD_FILE;
memcpy(stAiVqeConfig.aCfgFile, pVqeCfgPath, strlen(pVqeCfgPath));
}
if (s32VqeGapMs != 16 && s32VqeGapMs != 10) {
RK_LOGE("Invalid gap: %d, just supports 16ms or 10ms for AI VQE", s32VqeGapMs);
return RK_FAILURE;
}
stAiVqeConfig.s32WorkSampleRate = s32SampleRate;
stAiVqeConfig.s32FrameSample = s32SampleRate * s32VqeGapMs / 1000;
result = RK_MPI_AI_SetVqeAttr(s32DevId, s32ChnIndex, 0, 0, &stAiVqeConfig);
if (result != RK_SUCCESS) {
RK_LOGE("%s: SetVqeAttr(%d,%d) failed with %#x", __FUNCTION__, s32DevId,
s32ChnIndex, result);
return result;
}
result = RK_MPI_AI_GetVqeAttr(s32DevId, s32ChnIndex, &stAiVqeConfig2);
if (result != RK_SUCCESS) {
RK_LOGE("%s: SetVqeAttr(%d,%d) failed with %#x", __FUNCTION__, s32DevId,
s32ChnIndex, result);
return result;
}
result = memcmp(&stAiVqeConfig, &stAiVqeConfig2, sizeof(AI_VQE_CONFIG_S));
if (result != RK_SUCCESS) {
RK_LOGE("%s: set/get vqe config is different: %d", __FUNCTION__, result);
return result;
}
result = RK_MPI_AI_EnableVqe(s32DevId, s32ChnIndex);
if (result != RK_SUCCESS) {
RK_LOGE("%s: EnableVqe(%d,%d) failed with %#x", __FUNCTION__, s32DevId,
s32ChnIndex, result);
return result;
}
return RK_SUCCESS;
}
RK_S32 ai_set_other(RK_S32 s32SetVolume) {
printf("\n=======%s=======\n", __func__);
int s32DevId = 0;
RK_MPI_AI_SetVolume(s32DevId, s32SetVolume);
AUDIO_TRACK_MODE_E trackMode;
RK_MPI_AI_GetTrackMode(s32DevId, &trackMode);
RK_LOGI("test info : get track mode = %d", trackMode);
return 0;
}
RK_S32 open_device_ai(RK_S32 InputSampleRate, RK_S32 OutputSampleRate,
RK_S32 channel, RK_S32 u32FrameCnt) {
printf("\n=======%s=======\n", __func__);
AIO_ATTR_S aiAttr;
AI_CHN_PARAM_S pstParams;
RK_S32 result;
int aiDevId = 0;
int aiChn = 0;
memset(&aiAttr, 0, sizeof(AIO_ATTR_S));
RK_BOOL needResample = (InputSampleRate != OutputSampleRate) ? RK_TRUE : RK_FALSE;
#ifdef RV1126_RV1109
//这是RV1126 声卡打开设置RV1106设置无效可以不设置
result = RK_MPI_AMIX_SetControl(aiDevId, "Capture MIC Path", (char *)"Main Mic");
if (result != RK_SUCCESS) {
RK_LOGE("ai set Capture MIC Path fail, reason = %x", result);
goto __FAILED;
}
#endif
sprintf((char *)aiAttr.u8CardName, "%s", "hw:0,0");
// s32DeviceSampleRate 和 OutputSampleRate,OutputSampleRate
// 可以使用其他采样率,需要调用重采样函数。默认一样采样率。
aiAttr.soundCard.channels = 2;
aiAttr.soundCard.sampleRate = InputSampleRate;
aiAttr.soundCard.bitWidth = AUDIO_BIT_WIDTH_16;
aiAttr.enBitwidth = AUDIO_BIT_WIDTH_16;
aiAttr.enSamplerate = (AUDIO_SAMPLE_RATE_E)OutputSampleRate;
aiAttr.enSoundmode = AUDIO_SOUND_MODE_MONO;
aiAttr.u32PtNumPerFrm = u32FrameCnt;
//以下参数无特殊需求,无需变动,保持默认值即可
aiAttr.u32FrmNum = 4;
aiAttr.u32EXFlag = 0;
aiAttr.u32ChnCnt = 2;
result = RK_MPI_AI_SetPubAttr(aiDevId, &aiAttr);
if (result != 0) {
RK_LOGE("ai set attr fail, reason = %d", result);
goto __FAILED;
}
result = RK_MPI_AI_Enable(aiDevId);
if (result != 0) {
RK_LOGE("ai enable fail, reason = %d", result);
goto __FAILED;
}
memset(&pstParams, 0, sizeof(AI_CHN_PARAM_S));
pstParams.enLoopbackMode = AUDIO_LOOPBACK_NONE;
pstParams.s32UsrFrmDepth = 1;
result = RK_MPI_AI_SetChnParam(aiDevId, aiChn, &pstParams);
if (result != RK_SUCCESS) {
RK_LOGE("ai set channel params, aiChn = %d", aiChn);
return RK_FAILURE;
}
// init_ai_vqe(OutputSampleRate);
//左声道,无需修改
RK_MPI_AI_SetTrackMode(aiDevId, AUDIO_TRACK_FRONT_LEFT);
result = RK_MPI_AI_EnableChn(aiDevId, aiChn);
if (result != 0) {
RK_LOGE("ai enable channel fail, aiChn = %d, reason = %x", aiChn, result);
return RK_FAILURE;
}
if (needResample == RK_TRUE) {
RK_LOGI("need to resample %d -> %d", InputSampleRate, OutputSampleRate);
result =
RK_MPI_AI_EnableReSmp(aiDevId, aiChn, (AUDIO_SAMPLE_RATE_E)OutputSampleRate);
if (result != 0) {
RK_LOGE("ai enable channel fail, reason = %x, aiChn = %d", result, aiChn);
return RK_FAILURE;
}
}
ai_set_other(100);
return RK_SUCCESS;
__FAILED:
return RK_FAILURE;
}
RK_S32 init_mpi_aenc(RK_S32 s32SampleRate, RK_S32 channel) {
printf("\n=======%s=======\n", __func__);
RK_S32 s32ret = 0;
AENC_CHN_ATTR_S pstChnAttr;
RK_CODEC_ID_E enCodecId =
(RK_CODEC_ID_E)code_type; // RK_AUDIO_ID_ADPCM_G726 RK_AUDIO_ID_PCM_ALAW
AUDIO_BIT_WIDTH_E enBitwidth = AUDIO_BIT_WIDTH_16;
memset(&pstChnAttr, 0, sizeof(AENC_CHN_ATTR_S));
printf("codecId=%d\n", (int)enCodecId);
pstChnAttr.stCodecAttr.enType = enCodecId;
pstChnAttr.stCodecAttr.u32Channels = 1; // default MONO
pstChnAttr.stCodecAttr.u32SampleRate = s32SampleRate;
pstChnAttr.stCodecAttr.enBitwidth = enBitwidth;
pstChnAttr.stCodecAttr.pstResv = RK_NULL;
pstChnAttr.enType = enCodecId;
pstChnAttr.u32BufCount = 4;
pstChnAttr.u32Depth = 4;
s32ret = RK_MPI_AENC_CreateChn(0, &pstChnAttr);
if (s32ret) {
RK_LOGE("create aenc chn %d err:0x%x\n", enCodecId, s32ret);
}
return s32ret;
}
static RK_CHAR optstr[] = "?::r:o:t:c:";
static void print_usage(const RK_CHAR *name) {
printf("usage example:\n");
printf("\t%s [-r 8000] [-t g726] -o /tmp/aenc.g726\n", name);
printf("\t-r: sample rate, Default:8000\n");
printf("\t-t: --encode: encode type, Default:g726, Value:g711a, g711u, g726\n");
printf("\t-o: output path, Default:\"/tmp/aenc.g726\"\n");
}
// 编码g726的时候只支持8000 单声道所以需要设置所以需要设置track_mode为8
int main(int argc, char *argv[]) {
RK_S32 u32SampleRate = 8000;
RK_S32 u32Channel = 1;
RK_U32 u32FrameCnt = 1024;
RK_CHAR *pOutPath = (RK_CHAR *)"/tmp/aenc.g726";
RK_CHAR *pCodecName = (RK_CHAR *)"g726";
int ret = 0;
int c;
while ((c = getopt(argc, argv, optstr)) != -1) {
switch (c) {
case 'r':
u32SampleRate = atoi(optarg);
break;
case 'c':
u32Channel = atoi(optarg);
break;
case 'o':
pOutPath = optarg;
break;
case 't':
if (!strcmp(optarg, "g711a")) {
code_type = RK_AUDIO_ID_PCM_ALAW;
pCodecName = (RK_CHAR *)"g711a";
} else if (!strcmp(optarg, "g711u")) {
code_type = RK_AUDIO_ID_PCM_MULAW;
pCodecName = (RK_CHAR *)"g711u";
} else if (!strcmp(optarg, "g726")) {
code_type = RK_AUDIO_ID_ADPCM_G726;
pCodecName = (RK_CHAR *)"g726";
} else {
printf("ERROR: Invalid encoder type.\n");
return -1;
}
break;
case '?':
default:
print_usage(argv[0]);
return -1;
}
}
printf("#SampleRate: %d\n", u32SampleRate);
printf("#Channel: %d\n", u32Channel);
printf("#Frame Count: %d\n", u32FrameCnt);
printf("#CodecName:%s\n", pCodecName);
printf("#Output Path: %s\n", pOutPath);
if (pOutPath) {
save_file = fopen(pOutPath, "w");
if (!save_file) {
printf("ERROR: open file: %s fail, exit\n", pOutPath);
return 0;
}
}
signal(SIGINT, sigterm_handler);
RK_MPI_SYS_Init();
if (open_device_ai(u32SampleRate, u32SampleRate, u32Channel, u32FrameCnt))
return -1;
if (init_mpi_aenc(u32SampleRate, u32Channel))
return -1;
// ai bind aenc
MPP_CHN_S stSrcChn, stDestChn;
stSrcChn.enModId = RK_ID_AI;
stSrcChn.s32DevId = 0;
stSrcChn.s32ChnId = 0;
stDestChn.enModId = RK_ID_AENC;
stDestChn.s32DevId = 0;
stDestChn.s32ChnId = 0;
// 3. bind AI-AENC
ret = RK_MPI_SYS_Bind(&stSrcChn, &stDestChn);
if (ret) {
printf("Bind AI[0] to AENC[0] failed! ret=%d\n", ret);
return -1;
}
printf("%s initial finish\n", __func__);
AUDIO_STREAM_S pstStream;
RK_S32 eos = 0;
while (!quit) {
ret = RK_MPI_AENC_GetStream(0, &pstStream, -1);
if (ret == RK_SUCCESS) {
MB_BLK bBlk = pstStream.pMbBlk;
RK_VOID *pstFrame = RK_MPI_MB_Handle2VirAddr(bBlk);
RK_S32 frameSize = pstStream.u32Len;
RK_U64 timeStamp = pstStream.u64TimeStamp;
eos = (frameSize <= 0) ? 1 : 0;
if (pstFrame) {
RK_LOGI("get frame data = %p, size = %d, timeStamp = %llu", pstFrame,
frameSize, timeStamp);
if (save_file) {
fwrite(pstFrame, frameSize, 1, save_file);
fflush(save_file);
}
RK_MPI_AENC_ReleaseStream(0, &pstStream);
}
} else {
RK_LOGE("fail to get aenc frame.");
}
if (eos) {
RK_LOGI("get eos stream.");
break;
}
}
RK_MPI_SYS_UnBind(&stSrcChn, &stDestChn);
// RK_MPI_AI_DisableVqe(0, 0);
RK_MPI_AI_DisableChn(0, 0);
RK_MPI_AI_Disable(0);
RK_MPI_AENC_DestroyChn(0);
RK_MPI_SYS_Exit();
return 0;
}