AudioToolbox--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);
- }
来源:http://blog.csdn.net/tigerleap/article/details/7628105
AudioToolbox--AudioQueue实现流播放接口的更多相关文章
- 抛开flash,自己开发实现C++ RTMP直播流播放器
抛开flash,自己开发实现C++ RTMP直播流播放器 众所周知,RTMP是以flash为客户端播放器的直播协议,主要应用在B/S形式的场景中.本人研究并用C++开发实现了RTMP直播流协议的播放器 ...
- JavaCV 学习(二):使用 JavaCV + FFmpeg 制作拉流播放器
一.前言 在 Android 音视频开发学习思路 中,我们不断的学习和了解音视频相关的知识,随着知识点不断的学习,我们现在应该做的事情,就是将知识点不断的串联起来.这样才能得到更深层次的领悟.通过整理 ...
- C#推送RTMP到SRS通过VLC进行取流播放!!
前面一篇文章简单的介绍了下如何利用SRS自带的播放地址进行观看RTMP直播流,也就是说是使用SRS的内置demo进行Test,但是进行视频直播肯定不可能使用那样的去开发,不开源的东西肯定不好用.由于在 ...
- QT | 聊聊QT与直播流播放——从QMediaPlayer到Qt-AV
[原创文章,转载请注明来源,方便查看本文更新] 这段时间需要用QT开发一个播放直播流的功能,能够播放各种格式的直播流,并且CPU占用率不要太高(可以占用GPU),这些是我们的目标. 直播流推流的技术进 ...
- [JavaScript,Java,C#,C++,Ruby,Perl,PHP,Python][转]流式接口(Fluent interface)
原文:https://en.m.wikipedia.org/wiki/Fluent_interface(英文,完整) 转载:https://zh.wikipedia.org/wiki/流式接口(中文, ...
- 用C#做一个 拉流播放器
做拉流播放器第一个想到就是,.,..FFmpeg没错 我也是用强大的他它来做的.但是我用的不是 cmd 调用 而是用的强大的FFmpeg.AutoGen FFmpeg.AutoGen 这个是C# 一 ...
- c# 基于RTMP推流 PC+移动端 拉流播放
网上关于直播相关的文章很多,但是讲解还是不够系统,对于刚刚接触直播开发的朋友实施起来会浪费不少时间.下面结合我自己的经验, 介绍一下直播方面的实战经验. 分成两个部分 第一部分是标题中介绍的基于RTM ...
- 利用Docker挂载Nginx-rtmp(服务器直播流分发)+FFmpeg(推流)+Vue.js结合Video.js(播放器流播放)来实现实时网络直播
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_75 众所周知,在视频直播领域,有不同的商家提供各种的商业解决方案,其中比较靠谱的服务商有阿里云直播,腾讯云直播,以及又拍云和网易云 ...
- iOS音频播放之AudioQueue(一):播放本地音乐
AudioQueue简单介绍 AudioStreamer说明 AudioQueue具体解释 AudioQueue工作原理 AudioQueue主要接口 AudioQueueNewOutput Audi ...
随机推荐
- 015 vue的项目
一:搭建项目 1.框架 在原有的基础上 src: 2.index.html <!DOCTYPE html> <html lang="en"> <hea ...
- 解决pytesseract.pytesseract.TesseractNotFoundError: tesseract is not installed or it's not in your path问题
解决方案: 找到python的安装路径下的pytesseract: 例如我的是 C:\develop\Python\Lib\site-packages\pytesseract .用文本编辑器打开 ...
- 禁用 Ubuntu 18.04 Files 的 Type Ahead search 功能
. . . . . Ubuntu 的文件浏览器(Files)提供了一个搜索的功能,叫做“Type Ahead search”.即我们在文件浏览器中输入某个文件的名字时,Files 并不是将焦点定位在某 ...
- 大数据 -- Cloudera Manager(简称CM)+CDH构建大数据平台
一.Cloudera Manager介绍 Cloudera Manager(简称CM)是Cloudera公司开发的一款大数据集群安装部署利器,这款利器具有集群自动化安装.中心化管理.集群监控.报警等功 ...
- [ ceph ] CEPH 部署完整版(CentOS 7 + luminous)
1. 前言 拜读了 胖哥的(el7+jewel)完整部署 受益匪浅,目前 CEPH 已经更新到 M 版本,配置方面或多或少都有了变动,本博文就做一个 ceph luminous 版本完整的配置安装. ...
- python获取https并且写文件日志
# -*- coding: utf-8 -*- import os import os.path import shutil import chardet import urllib.request ...
- OSI七层与TCP/IP四层(小结)
OSI 七层模型 我们一般使用的网络数据传输由下而上共有七层,分别为物理层.数据链路层.网络层.传输层.会话层.表示层.应用层,也被依次称为 OSI 第一层.第二层.⋯⋯. 第七层. 各层功能简介 1 ...
- 无限用teamviewer的一种方法,虚拟机中装teamviewer
可以使用window 多用户可以同时远程登陆的特性(win服务器版自动支持多用户同时远程登陆,非服务器版需要其他方法开启) 1.在window建立两个用户,如a,b. 2安装虚拟机vmware,安装操 ...
- 启动Tomcat时报异常org.apache.catalina.core.ContainerBase.startInternal A child container failed during start
之前Tomcat一直运行正常,重启之后一直报以下错误信息: 13-Jun-2019 19:46:13.000 SEVERE [Catalina-startStop-1] org.apache.cata ...
- Redis实现实时热点查询
Redis内存淘汰 定义: 指的是用户存储的一些键被可以被Redis主动地从实例中删除,从而产生读miss的情况 机制存在原因: Redis最常见的两种应用场景为缓存和持久存储 首先要明确的一个问题是 ...