海思平臺播放AAC音訊
阿新 • • 發佈:2019-01-01
利用海思sdk的sample修改了一個播AAC的小程式
程式碼
主程式voice_player.c:
/******************************************************************************
A simple program of Hisilicon HI3516 audio input/output/encoder/decoder implementation.
Copyright (C), 2010-2011, Hisilicon Tech. Co., Ltd.
******************************************************************************
Modification: 2011-2 Created
******************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <pthread.h>
#include <errno.h>
#include <signal.h>
//#include "hi_comm_vb.h"
#include "audio_aac_adp.h"
#define TEST_AIO_ID 0
#define AIO_WORK_MODE AIO_MODE_I2S_MASTER
static PAYLOAD_TYPE_E gs_enPayloadType = PT_AAC;
static AAC_TYPE_E gs_enAacType = AAC_TYPE_AACLC;
static AAC_BPS_E gs_enAacBps = AAC_BPS_24K;
static HI_BOOL gs_bUserGetMode = HI_FALSE;
//static HI_BOOL gs_bMicIn = HI_FALSE;
//static HI_U32 g_InnerCodecInput = 1; /*0-micin 1-linein 2-micind 3-lineind*/
//static HI_U32 g_InnerCodecOutput = 0; /*0-lineout 1-leftd 2-rightd*/
#define SAMPLE_DBG(s32Ret)\
do{\
printf("s32Ret=%#x,fuc:%s,line:%d\n", s32Ret, __FUNCTION__, __LINE__);\
}while(0)
/******************************************************************************
* function : PT Number to String
******************************************************************************/
static char* SAMPLE_AUDIO_Pt2Str(PAYLOAD_TYPE_E enType)
{
if (PT_AAC == enType) return "aac";
else return "data";
}
/******************************************************************************
* function : Open Aenc File
******************************************************************************/
static FILE * SAMPLE_AUDIO_OpenAencFile(AENC_CHN AeChn, PAYLOAD_TYPE_E enType)
{
FILE *pfd;
HI_CHAR aszFileName[128];
/* create file for save stream*/
snprintf(aszFileName, sizeof(aszFileName), "audio_chn%d.%s", AeChn, SAMPLE_AUDIO_Pt2Str(enType));
pfd = fopen(aszFileName, "w+");
if (NULL == pfd)
{
printf("%s: open file %s failed\n", __FUNCTION__, aszFileName);
return NULL;
}
printf("open stream file:\"%s\" for aenc ok\n", aszFileName);
return pfd;
}
/******************************************************************************
* function : Open Adec File
******************************************************************************/
static FILE *SAMPLE_AUDIO_OpenAdecFile(char *filename)
{
FILE *pfd;
pfd = fopen(filename, "rb");
if (NULL == pfd)
{
printf("%s: open file %s failed\n", __FUNCTION__, filename);
return NULL;
}
printf("open stream file:\"%s\" for adec ok\n", filename);
return pfd;
}
/******************************************************************************
* function : Start Aenc
******************************************************************************/
HI_S32 SAMPLE_AUDIO_StartAenc(HI_S32 s32AencChnCnt, AIO_ATTR_S *pstAioAttr, PAYLOAD_TYPE_E enType)
{
AENC_CHN AeChn;
HI_S32 s32Ret, i;
AENC_CHN_ATTR_S stAencAttr;
AENC_ATTR_AAC_S stAencAac;
/* set AENC chn attr */
stAencAttr.enType = enType;
stAencAttr.u32BufSize = 30;
stAencAttr.u32PtNumPerFrm = pstAioAttr->u32PtNumPerFrm;
if (PT_AAC == stAencAttr.enType)
{
stAencAttr.pValue = &stAencAac;
stAencAac.enAACType = gs_enAacType;
stAencAac.enBitRate = gs_enAacBps;
stAencAac.enBitWidth = AUDIO_BIT_WIDTH_16;
stAencAac.enSmpRate = pstAioAttr->enSamplerate;
stAencAac.enSoundMode = pstAioAttr->enSoundmode;
stAencAac.enTransType = AAC_TRANS_TYPE_ADTS;
stAencAac.s16BandWidth = 0;
}
else
{
printf("%s: invalid aenc payload type:%d\n", __FUNCTION__, stAencAttr.enType);
return HI_FAILURE;
}
for (i=0; i<s32AencChnCnt; i++)
{
AeChn = i;
/* create aenc chn*/
s32Ret = HI_MPI_AENC_CreateChn(AeChn, &stAencAttr);
if (s32Ret != HI_SUCCESS)
{
printf("%s: HI_MPI_AENC_CreateChn(%d) failed with %#x!\n", __FUNCTION__,
AeChn, s32Ret);
return HI_FAILURE;
}
}
return HI_SUCCESS;
}
/******************************************************************************
* function : Start Adec
******************************************************************************/
HI_S32 SAMPLE_AUDIO_StartAdec(ADEC_CHN AdChn, PAYLOAD_TYPE_E enType)
{
HI_S32 s32Ret;
ADEC_CHN_ATTR_S stAdecAttr;
ADEC_ATTR_AAC_S stAdecAac;
stAdecAttr.enType = enType;
stAdecAttr.u32BufSize = 20;
stAdecAttr.enMode = ADEC_MODE_STREAM;/* propose use pack mode in your app */
if (PT_AAC == stAdecAttr.enType)
{
stAdecAttr.pValue = &stAdecAac;
stAdecAttr.enMode = ADEC_MODE_STREAM; /* aac should be stream mode */
stAdecAac.enTransType = AAC_TRANS_TYPE_ADTS;
}
else
{
printf("%s: invalid aenc payload type:%d\n", __FUNCTION__, stAdecAttr.enType);
return HI_FAILURE;
}
/* create adec chn*/
s32Ret = HI_MPI_ADEC_CreateChn(AdChn, &stAdecAttr);
if (s32Ret)
{
printf("%s: HI_MPI_ADEC_CreateChn(%d) failed with %#x!\n", __FUNCTION__,\
AdChn,s32Ret);
return s32Ret;
}
return 0;
}
/******************************************************************************
* function : file -> ADec -> Ao
******************************************************************************/
HI_S32 SAMPLE_AUDIO_AdecAo(char *filename, AIO_ATTR_S *pstAioAttr)
{
HI_S32 s32Ret;
#ifdef AO_DEV
AUDIO_DEV AoDev = AO_DEV;
#else
AUDIO_DEV AoDev = TEST_AIO_ID;
#endif
AO_CHN AoChn = 0;
ADEC_CHN AdChn = 0;
HI_S32 s32AoChnCnt;
FILE *pfd = NULL;
if (NULL == pstAioAttr)
{
printf("%s: input piont is invalid!\n", __FUNCTION__);
return HI_FAILURE;
}
s32Ret = SAMPLE_COMM_AUDIO_CfgAcodec(pstAioAttr);
if (HI_SUCCESS != s32Ret)
{
SAMPLE_DBG(s32Ret);
goto ADECAO_ERR3;
}
s32Ret = SAMPLE_AUDIO_StartAdec(AdChn, gs_enPayloadType);
if (s32Ret != HI_SUCCESS)
{
SAMPLE_DBG(s32Ret);
goto ADECAO_ERR3;
}
s32AoChnCnt = pstAioAttr->u32ChnCnt;
s32Ret = SAMPLE_COMM_AUDIO_StartAo(AoDev, s32AoChnCnt, pstAioAttr, AUDIO_SAMPLE_RATE_BUTT, HI_FALSE, NULL, 0);
if (s32Ret != HI_SUCCESS)
{
SAMPLE_DBG(s32Ret);
goto ADECAO_ERR2;
}
s32Ret = SAMPLE_COMM_AUDIO_AoBindAdec(AoDev, AoChn, AdChn);
if (s32Ret != HI_SUCCESS)
{
SAMPLE_DBG(s32Ret);
goto ADECAO_ERR1;
}
pfd = SAMPLE_AUDIO_OpenAdecFile(filename);
if (!pfd)
{
SAMPLE_DBG(HI_FAILURE);
goto ADECAO_ERR0;
}
s32Ret = SAMPLE_COMM_AUDIO_CreatTrdFileAdec (AdChn, pfd);
if (s32Ret != HI_SUCCESS)
{
SAMPLE_DBG(s32Ret);
goto ADECAO_ERR0;
}
printf("bind adec:%d to ao(%d,%d) ok \n", AdChn, AoDev, AoChn);
//SAMPLE_COMM_AUDIO_DestoryTrdFileAdec(AdChn);
ADECAO_ERR0:
s32Ret |= SAMPLE_COMM_AUDIO_AoUnbindAdec(AoDev, AoChn, AdChn);
ADECAO_ERR1:
s32Ret |= SAMPLE_COMM_AUDIO_StopAo(AoDev, s32AoChnCnt, HI_FALSE, HI_FALSE);
ADECAO_ERR2:
s32Ret |= SAMPLE_COMM_AUDIO_StopAdec(AdChn);
ADECAO_ERR3:
return s32Ret;
}
/******************************************************************************
* function : to process abnormal case
******************************************************************************/
void SAMPLE_AUDIO_HandleSig(HI_S32 signo)
{
if (SIGINT == signo || SIGTSTP == signo)
{
SAMPLE_COMM_AUDIO_DestoryAllTrd();
SAMPLE_COMM_SYS_Exit();
printf("\033[0;31mprogram exit abnormally!\033[0;39m\n");
}
exit(0);
}
/******************************************************************************
* function : main
******************************************************************************/
HI_S32 main(int argc, char *argv[])
{
char ch;
HI_S32 s32Ret= HI_SUCCESS;
AIO_ATTR_S stAioAttr;
/* init stAio. all of cases will use it */
memset(&stAioAttr, 0, sizeof(AIO_ATTR_S));
stAioAttr.enBitwidth = AUDIO_BIT_WIDTH_16;
stAioAttr.enWorkmode = AIO_WORK_MODE;
stAioAttr.enSoundmode = AUDIO_SOUND_MODE_MONO;
stAioAttr.u32EXFlag = 0;
stAioAttr.u32FrmNum = 30;
stAioAttr.u32ChnCnt = 1;
#ifdef HI_ACODEC_TYPE_TLV320AIC31
stAioAttr.u32ClkSel = 1;
#else
stAioAttr.u32ClkSel = 0;
#endif
stAioAttr.enSamplerate = AUDIO_SAMPLE_RATE_8000;
stAioAttr.u32PtNumPerFrm = (AAC_TYPE_AACLC == gs_enAacType) ? 1024 : 2048;
//signal(SIGINT, SAMPLE_AUDIO_HandleSig);
//signal(SIGTERM, SAMPLE_AUDIO_HandleSig);
s32Ret = SAMPLE_COMM_SYS_Init();
if (HI_SUCCESS != s32Ret)
{
printf("%s: system init failed with %d!\n", __FUNCTION__, s32Ret);
return HI_FAILURE;
}
/* register aac encoder and decoder */
HI_MPI_ADEC_AacInit ();
s32Ret = SAMPLE_AUDIO_AdecAo(argv[1],&stAioAttr);/* read audio stream from file,decode and send AO*/
if (s32Ret != HI_SUCCESS)
{
}
SAMPLE_COMM_SYS_Exit();
return HI_SUCCESS;
}
什麼標註了幾個關鍵的點。
sample_comm_audio.c部分程式碼:
/******************************************************************************
* function : Create the thread to get stream from file and send to adec
******************************************************************************/
HI_S32 SAMPLE_COMM_AUDIO_CreatTrdFileAdec (ADEC_CHN AdChn, FILE *pAdcFd)
{
SAMPLE_ADEC_S *pstAdec = NULL;
if (NULL == pAdcFd)
{
return HI_FAILURE;
}
pstAdec = &gs_stSampleAdec[AdChn];
pstAdec->AdChn = AdChn;
pstAdec->pfd = pAdcFd;
pstAdec->bStart = HI_TRUE;
//pthread_create(&pstAdec->stAdPid, 0, SAMPLE_COMM_AUDIO_AdecProc, pstAdec);
SAMPLE_COMM_AUDIO_AdecProc(pstAdec);
return HI_SUCCESS;
}
/******************************************************************************
* function : get stream from file, and send it to Adec
******************************************************************************/
void *SAMPLE_COMM_AUDIO_AdecProc(SAMPLE_ADEC_S *pstAdec)
{
HI_S32 s32Ret;
AUDIO_STREAM_S stAudioStream;
HI_U32 u32Len = 2048;
HI_U32 u32ReadLen;
HI_S32 s32AdecChn;
HI_U8 *pu8AudioStream = NULL;
SAMPLE_ADEC_S *pstAdecCtl = (SAMPLE_ADEC_S *)pstAdec;
AO_CHN_STATE_S pstStatus;
FILE *pfd = pstAdecCtl->pfd;
s32AdecChn = pstAdecCtl->AdChn;
pu8AudioStream = (HI_U8*)malloc(sizeof(HI_U8)*MAX_AUDIO_STREAM_LEN);
if (NULL == pu8AudioStream)
{
printf("%s: malloc failed!\n", __FUNCTION__);
return NULL;
}
while (HI_TRUE == pstAdecCtl->bStart)
{
/* read from file */
stAudioStream.pStream = pu8AudioStream;
u32ReadLen = fread(stAudioStream.pStream, 1, u32Len, pfd);
if (u32ReadLen <= 0)
{
/*
s32Ret = HI_MPI_ADEC_SendEndOfStream(s32AdecChn, HI_FALSE);
if (HI_SUCCESS != s32Ret)
{
printf("%s: HI_MPI_ADEC_SendEndOfStream failed!\n", __FUNCTION__);
}
fseek(pfd, 0, SEEK_SET);
*/
printf("u32ReadLen <= 0 break! s32Ret:%d \n",s32Ret);
break;
}
/* here only demo adec streaming sending mode, but pack sending mode is commended */
stAudioStream.u32Len = u32ReadLen;
s32Ret = HI_MPI_ADEC_SendStream(s32AdecChn, &stAudioStream, HI_TRUE);
if(HI_SUCCESS != s32Ret)
{
printf("%s: HI_MPI_ADEC_SendStream(%d) failed with %#x!\n",\
__FUNCTION__, s32AdecChn, s32Ret);
//break;
}
usleep(1000*10);
}
while (HI_TRUE == pstAdecCtl->bStart)
{
s32Ret = HI_MPI_AO_QueryChnStat(0, 0,&pstStatus);
//printf("pstStatus.u32ChnBusyNum: %d\n",pstStatus.u32ChnBusyNum);
if(pstStatus.u32ChnBusyNum < 1)
{
s32Ret = HI_MPI_ADEC_SendEndOfStream(s32AdecChn, HI_FALSE);
if (HI_SUCCESS != s32Ret)
{
printf("%s: HI_MPI_ADEC_SendEndOfStream failed!\n", __FUNCTION__);
}
break;
}
sleep(1);
}
free(pu8AudioStream);
pu8AudioStream = NULL;
fclose(pfd);
pstAdecCtl->bStart = HI_FALSE;
return NULL;
}
注意播放時要查詢
AO 通道中當前的音訊資料緩存狀態,等到快取為空時再停止播放,不然只能播一部分,不能播完。編譯
上makefile
include config.mk
LOCAL_SRC_CFILES := \
voice_player.c \
src/audio_aac_adp.c \
src/sample_comm_audio.c \
src/sample_comm_sys.c
LOCAL_MODULE := voice_player
LOCAL_CFLAGS := -D__LINUX__
PREFIX := arm-hisiv300-linux-
LOCAL_SHARED_LIBRARIES := pthread \
LOCAL_C_INCLUDES := ./include \
./ \
LOCAL_LDFLAGS := lib/libaacdec.so \
lib/libmpi.so \
lib/libisp.so \
lib/libive.so \
lib/libVoiceEngine.so \
lib/libupvqe.so \
lib/libdnvqe.so \
lib/lib_hidefog.so \
lib/libaacenc.so \
include exec_rules.mk
只看makefile的話應該就能看出我的目錄結構吧!
水一波@[email protected]~