利用海思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的话应该就能看出我的目录结构吧!
水一波@_@~