zoukankan      html  css  js  c++  java
  • 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);
    }


  • 相关阅读:
    PHP 内核:foreach 是如何工作的(一)
    PHP 消息队列 Kafka 使用
    PHP7 生产环境队列 Beanstalkd 正确使用姿势
    你知道Laravel ORM 中的骚操作吗
    PHP 的 interface 有什么用处
    PHP 框架 Hyperf 实现处理超时未支付订单和延时队列
    java 浅谈web系统当中的cookie和session会话机制
    如何用charles进行https抓包
    Java实现图片按修改时间排序
    java读取文本文件内容
  • 原文地址:https://www.cnblogs.com/weinyzhou/p/2750088.html
Copyright © 2011-2022 走看看