1. 程式人生 > >海思平臺播放AAC音訊

海思平臺播放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的話應該就能看出我的目錄結構吧!

水一波@[email protected]~