海思平台播放AAC音频

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

水一波@_@~






猜你喜欢

转载自blog.csdn.net/qq_29214249/article/details/78275842