ios audioqueue 流播放接口

AudioMedia_ios.h

//
//  AudioMedia_ios.h
//  mmsplayer
//
//  Created by Weiny on 12-4-4.
//  Copyright (c) 2012年 Weiny Zhou. All rights reserved.
//

#ifndef mmsplayer_AudioMedia_ios_h
#define mmsplayer_AudioMedia_ios_h
#include "wdef.h"

typedef void* wAudio;

#ifdef __cplusplus
extern "C"
{
#endif
    wAudio audio_open(int sample,int nchannles,int bits,int nFrameSize);//初始化声音接口
    int audio_play(wAudio audio);//播放
	int audio_pause(wAudio audio);
    int audio_wirte(wAudio audio,unsigned char* pcm,size_t count,int64_t dts);//写入音频数据
    int audio_stop(wAudio audio);//停止
    int audio_close(wAudio audio);//关闭
#ifdef __cplusplus
};
#endif    
    
#endif


AudioMedia_ios.c

//
//  AudioMedia_ios.cpp
//  mmsplayer
//
//  Created by Weiny on 12-4-4.
//  Copyright (c) 2012年 Weiny Zhou. All rights reserved.
//

#include "AudioMedia_ios.h"
#include <AudioToolbox/AudioQueue.h>
#include "system/thread.h"
#include "base/wlist.h"
#include "system/lx_lock.h"
#define AUDIO_LIST_COUNT 3
#define AUDIO_BUFFER_SECONDS  1
typedef struct WAudio_Ios
{

	int playRequested;
	int framesize;
	Wlock mlock,mdecdonelock,mqueuelock;
	wlist_t mAudiolist;//声音队列
	wlist_func mlistfunc;

    AudioQueueRef queue;//player list
    AudioQueueBufferRef mBuffers[AUDIO_LIST_COUNT];
    AudioStreamBasicDescription mDataFormat;
	AudioQueueBufferRef emptyAudioBuffer;//空音频队列
	
}WAudio_Ios;
typedef struct  
{
	void* data;
	size_t size;
    int64_t dst;
}WAudio_item;

void wAudio_CallBack(void * in,AudioQueueRef intq,AudioQueueBufferRef outQB);
void wAudtio_fillAudioBuffer(WAudio_Ios* audio,AudioQueueBufferRef buffer);
static inline void waudio_free_back(void* lpvoid,wlist_item_ptr data)
{
	WAudio_item* item;
	INTOFUNC();
	if(!data){PRINTF_ERROR_VALUE(ERROR_INITPARAM);goto error_lab;}
	item=(WAudio_item*)data;
	SAFE_FREE(item->data);
	SAFE_FREE(item);
error_lab:
	EXITFUNC();
}
wAudio audio_open(int sample,int nchannles,int bits,int nFrameSize)
{
    WAudio_Ios* ptr=NULL;
    uint32_t err=0;
	int i=0;
    INTOFUNC();
    ptr=WOS_MALLOC_(WAudio_Ios, 1);
    if(!ptr){
        PRINTF_ERROR_VALUE(ERROR_NEWMEM);
        goto error_lab;
    }
    memset(ptr,0,sizeof(WAudio_Ios));
    ptr->mDataFormat.mSampleRate=sample;//设置采样率
	ptr->mDataFormat.mChannelsPerFrame=nchannles;
	ptr->mDataFormat.mBitsPerChannel=bits;
    ptr->mDataFormat.mFormatID=kAudioFormatLinearPCM;//设置数据格式
    ptr->mDataFormat.mFormatFlags=kLinearPCMFormatFlagIsSignedInteger|kAudioFormatFlagIsPacked;
   
    ptr->mDataFormat.mFramesPerPacket=1;
    ptr->mDataFormat.mBytesPerFrame=
		ptr->mDataFormat.mBitsPerChannel/
		ptr->mDataFormat.mChannelsPerFrame;
     ptr->mDataFormat.mBytesPerPacket=
		 ptr->mDataFormat.mBytesPerFrame*ptr->mDataFormat.
		 mFramesPerPacket;
    
    err=AudioQueueNewOutput(&ptr->mDataFormat,wAudio_CallBack, ptr, NULL, 
                            NULL/*kCFRunLoopCommonModes*/, 0
                            , &ptr->queue);
    if(err){
        WERROR_A("init audio output error,sample=%d,channles=%d,bits=%d.\n",sample,nchannles,bits);
        goto error_lab;
    }
	for (i=0;i<AUDIO_LIST_COUNT;++i)
	{
		err=AudioQueueAllocateBufferWithPacketDescriptions(ptr->queue,
			bits*AUDIO_BUFFER_SECONDS/8,
			sample*AUDIO_BUFFER_SECONDS/nFrameSize+1,ptr->mBuffers+i);
		if(err){
			WERROR_A("can't allocate audio queue buffer: %d",err);
            
			goto error_lab;
		}
	}
	ptr->mlock=lx_lock_init();
	ptr->mdecdonelock=lx_lock_init();
	ptr->mqueuelock=lx_lock_init();
	ptr->mlistfunc=wlist_getfunc();
	ptr->mAudiolist.free=waudio_free_back;
	ptr->framesize=nFrameSize;
#if 1
	err=AudioQueueStart(ptr->queue,NULL);
	if(err){
		WERROR_A("Error: Audio queue failed to start: %d", err);
		goto error_lab;
	}
    ptr->playRequested=1;
	WDEBUG_OUT("Started Audio queue.",NULL);
#endif
#if 0
    agc.FrameCount = FRAME_COUNT;  
    bufferSize = agc.FrameCount * agc.mDataFormat.mBytesPerFrame;  
    for (i=0; i<AUDIO_BUFFERS; i++)  
    {  
        err = AudioQueueAllocateBuffer(agc.queue,bufferSize,&agc.mBuffers[i]);  
        if(err) return err;  
        AQBufferCallback(&agc,agc.queue,agc.mBuffers[i]);  
    }  
    err = AudioQueueStart(agc.queue,NULL);  
    if(err) return err;  
    while (agc.playPtr<agc.sampleLen)  
    {  
        select(NULL,NULL,NULL,NULL,1.0);  
    }  
#endif
error_lab:
	if(err){
		audio_close(ptr);
		SAFE_FREE(ptr);
	}
    EXITFUNC();
    return (wAudio)ptr;
}
int audio_play(wAudio audio)
{
    int nResult=0;
    WAudio_Ios* ptr=NULL;
    INTOFUNC();
    if(!audio){
        WERROR_A("input audio is null",NULL);
        nResult=ERROR_INITPARAM;
        goto error_lab;
    }
    ptr=(WAudio_Ios*)audio;
	if(ptr->playRequested==0||ptr->playRequested==2)
	{WERROR_A("state is %d",ptr->playRequested);goto error_lab;}
	ptr->playRequested=1;
	AudioQueueStart(ptr->queue,NULL);
error_lab:
    EXITFUNC();
    return nResult;
}
int audio_pause(wAudio audio)
{
	int nResult=0;
	WAudio_Ios* ptr=NULL;
	INTOFUNC();
	if(!audio){
		WERROR_A("input audio is null",NULL);
		nResult=ERROR_INITPARAM;
		goto error_lab;
	}
	ptr=(WAudio_Ios*)audio;
	if(1!=ptr->playRequested)
	{WERROR_A("state is %d",ptr->playRequested);goto error_lab;}
	ptr->playRequested=2;
	AudioQueuePause(ptr->queue);
error_lab:
	EXITFUNC();
	return nResult;
}
int audio_wirte(wAudio audio,unsigned char* pcm,size_t count,int64_t dst)
{
    int nResult=0;
    WAudio_Ios* ptr=NULL;
	WAudio_item* item=NULL;
    INTOFUNC();
    if(!audio){
        WERROR_A("input audio is null",NULL);
        nResult=ERROR_INITPARAM;
        goto error_lab;
    }
    ptr=(WAudio_Ios*)audio;
	item=WOS_MALLOC_(WAudio_item,1);
	if(!item){
		nResult=ERROR_NEWMEM;PRINTF_ERROR_VALUE(nResult);goto error_lab;
	}
	item->data=pcm;
	item->size=count;
    item->dst=dst;
	lx_lock(ptr->mqueuelock);
	//先加入队列
	ptr->mlistfunc.push_back(&ptr->mAudiolist,item);
	//
	if(ptr->emptyAudioBuffer)
		wAudtio_fillAudioBuffer(ptr,ptr->emptyAudioBuffer);//填充空buffer
	lx_unlock(ptr->mqueuelock);
error_lab:
    EXITFUNC();
    return nResult;
}
int audio_stop(wAudio audio)
{
    int nResult=0;
    WAudio_Ios* ptr=NULL;
    INTOFUNC();
    if(!audio){
        WERROR_A("input audio is null",NULL);
        nResult=ERROR_INITPARAM;
        goto error_lab;
    }
    ptr=(WAudio_Ios*)audio;
    AudioQueueStop(ptr->queue,false);
	ptr->playRequested=0;
error_lab:
    EXITFUNC();
    return nResult;
}
int audio_close(wAudio audio)
{
    int nResult=0;
    WAudio_Ios* ptr=NULL;
    INTOFUNC();
    if(!audio){
        WERROR_A("input audio is null.",NULL);
        nResult=ERROR_INITPARAM;
        goto error_lab;
    }
    ptr=(WAudio_Ios*)audio;
	ptr->mlistfunc.clear(&ptr->mAudiolist);//清空播放队列
	lx_lock_free(ptr->mqueuelock);
	lx_lock_free(ptr->mdecdonelock);
	lx_lock_free(ptr->mlock);
    AudioQueueDispose(ptr->queue,false);
    SAFE_FREE(ptr);
error_lab:
    EXITFUNC();
    return nResult;
}
#if 0
void AQBufferCallback( void *in, AudioQueueRef inQ, AudioQueueBufferRef outQB)  
{  
    AQCallbackStruct *agc;  
    short *coreAudiobuffer;  
    short sample;  
    int i;  
    agc=(AQCallbackStruct *) in;  
    coreAudiobuffer =(short*) outQB->mAudioData;  
    printf("Sync:%i / %i \n",agc->playPtr,agc->sampleLen);  
    if (agc->FrameCount >0)   
    {  
        outQB->mAudioDataByteSize = 4*agc->FrameCount;  
        for (i=0; i<agc->FrameCount*2; i++)   
        {  
            if(agc->playPtr > agc->sampleLen || agc->playPtr<0)  
            {  
                sample =0;  
            }  
            else  
            {  
                sample = (agc->pcmBuffer[agc->playPtr]);  
            }  
            coreAudiobuffer[i] = sample;  
            coreAudiobuffer[i+1] = sample;  
            agc->playPtr++;  
        }  
        AudioQueueEnqueueBuffer(inQ,outQB,0,NULL);  
    } 
}
#endif
void wAudtio_fillAudioBuffer(WAudio_Ios* audio,AudioQueueBufferRef buffer)
{
	AudioTimeStamp bufferStartTime;
	uint32_t err;
	INTOFUNC();
	buffer->mAudioDataByteSize=0;
	buffer->mPacketDescriptionCount=0;
	if(audio->mAudiolist.size<=0){
		WERROR_A("Warning: No audio packets in queue.",NULL);
		audio->emptyAudioBuffer=buffer;
		goto error_lab;
	}
	audio->emptyAudioBuffer=NULL;
	while(audio->mAudiolist.size&&buffer->mPacketDescriptionCount <
		buffer->mPacketDescriptionCapacity)
	{
		wlist_item* item=audio->mlistfunc.pop_front(&audio->mAudiolist);
		WAudio_item* data=(WAudio_item*)item->data;
		if(buffer->mAudioDataBytesCapacity -
			buffer->mAudioDataByteSize >=data->size)
		{
            if(buffer->mAudioDataBytesCapacity==0)
            {
                bufferStartTime.mSampleTime=data->dst*audio->framesize;
                bufferStartTime.mFlags=kAudioTimeStampSampleTimeValid;
            }
			 memcpy((uint8_t *)buffer->mAudioData + buffer->mAudioDataByteSize, data->data, data->size);
			 buffer->mPacketDescriptions[buffer->mPacketDescriptionCount].mStartOffset = buffer->mAudioDataByteSize;
			 buffer->mPacketDescriptions[buffer->mPacketDescriptionCount].mDataByteSize = data->size;
			 buffer->mPacketDescriptions[buffer->mPacketDescriptionCount].mVariableFramesInPacket = audio->framesize;

			 buffer->mAudioDataByteSize += data->size;
			 ++buffer->mPacketDescriptionCount;
			 lx_lock(audio->mqueuelock);
			 audio->mlistfunc.remove(&audio->mAudiolist,0);
			 lx_unlock(audio->mqueuelock);
		}
		else
			break;
	}
	if(buffer->mPacketDescriptionCount>0)
	{
		if(err=AudioQueueEnqueueBufferWithParameters(audio->queue,
			buffer,0,NULL,0,0,0,NULL,&bufferStartTime,NULL))
			WERROR_A("Error enqueuing audio buffer: %d", err);
		//decodelock
		lx_lock(audio->mdecdonelock);
		if(!audio->playRequested&&audio->mAudiolist.size==0){
			if(err=AudioQueueStop(audio->queue,false))
				WERROR_A("Error: Failed to stop audio queue: %d", err);
			else
				WERROR_A("Stopped audio queue",NULL);
		}
		lx_unlock(audio->mdecdonelock);
		//decodeunlock
	}
error_lab:
	EXITFUNC();
}
void wAudio_CallBack(void * in,AudioQueueRef intq,AudioQueueBufferRef buffer)
{
    wAudtio_fillAudioBuffer((WAudio_Ios*)in,buffer);
}


原文地址:https://www.cnblogs.com/weinyzhou/p/4983493.html