DOUAudioStreamer 中kqueue的应用
DOUAudioStreamer是一个基于Core Audio的流式音频播放器,其中的DOUAudioEventLoop通过kqueue来控制音频的各种状态。
kqueue简介(详情请看官方manual)
kqueue的功能类似epoll,多用于后台多个socket连接时的I/O复用,注册感兴趣的event,把描述符链表交给内核,然后就等待。一旦有某个或多个事件发生,内核就把 一个只包含有发生了事件的描述符的链表通知给进程,由此避免了每次函数返回的时候都要去遍历整个链表(相较与select和poll)。尽管对于只打开了几个描述符的进程而言这点改进算不得什么,但对于那些打开了几千个文件描述符的程序来说,这种性能改进就相当显著了。
在DOUAudioStreamer中kqueue系统调用生成一个之关联的唯一的描述符,通过kevent来注册和监听音频播放的各种状态的变化,以及变化后(即感兴趣的event发生后)的各种处理。
typedef NS_ENUM(uint64_t, event_type) {
event_play, //播放
event_pause, //暂停
event_stop, //停止
event_seek, //手动选择播放位置
event_streamer_changed, //更换了streamer
event_provider_events,
event_finalizing, //dealloc中发送event,正在释放
#if TARGET_OS_IPHONE
event_interruption_begin,
event_interruption_end,
event_old_device_unavailable, //最后一步
#endif /* TARGET_OS_IPHONE */ event_first = event_play,
#if TARGET_OS_IPHONE
event_last = event_old_device_unavailable,
#else /* TARGET_OS_IPHONE */
event_last = event_finalizing,
#endif /* TARGET_OS_IPHONE */ event_timeout
};
init中初始化过程中的_setupAudioSession(也可以[AVAudioSession sharedInstance] 来设置)
AudioSessionInitialize(NULL, NULL, audio_session_interruption_listener, (__bridge void *)self); //注册被其他应用打断,或其他应用音频播放停止后的处理
//设置MediaPlayback属性可在后台播放声音,也可以避免一些不插耳机时无声的问题
UInt32 audioCategory = kAudioSessionCategory_MediaPlayback;
AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(audioCategory), &audioCategory); AudioSessionAddPropertyListener(kAudioSessionProperty_AudioRouteChange, audio_route_change_listener, (__bridge void *)self); AudioSessionSetActive(TRUE);
kevent相关的操作
/**
* 官方manual中
The EV_SET() macro is provided for ease of initializing a kevent structure.
EVFILT_USER
Establishes a user event identified by ident which is not associated with any kernel mechanism but is triggered by user level code.
*
*
**/ //相当于register各种感兴趣事件
- (void)_enableEvents
{
for (uint64_t event = event_first; event <= event_last; ++event) {
struct kevent kev;
/**从event_play到event_old_device_unavailable,监听 EV_ADD--添加event,EV_ENABLE--事件被触发后允许返回,EV_CLEAR--返回事件后,重新设置event的状态 **/
EV_SET(&kev, event, EVFILT_USER, EV_ADD | EV_ENABLE | EV_CLEAR, , , NULL);
kevent(_kq, &kev, , NULL, , NULL);
}
} - (void)_sendEvent:(event_type)event
{
[self _sendEvent:event userData:NULL];
} - (void)_sendEvent:(event_type)event userData:(void *)userData
{
struct kevent kev;
//EVFILT_USER通过NOTE_TRIGGER来触发
EV_SET(&kev, event, EVFILT_USER, , NOTE_TRIGGER, , userData);
kevent(_kq, &kev, , NULL, , NULL);
} - (event_type)_waitForEvent
{
return [self _waitForEventWithTimeout:NSUIntegerMax];
}
//kevent监听着感兴趣的事件,一有可用事件就返回事件类型
- (event_type)_waitForEventWithTimeout:(NSUInteger)timeout
{
struct timespec _ts;
struct timespec *ts = NULL;
if (timeout != NSUIntegerMax) {
ts = &_ts; ts->tv_sec = timeout / ;
ts->tv_nsec = (timeout % ) * ;
} while () {
struct kevent kev;
int n = kevent(_kq, NULL, , &kev, , ts);
if (n > ) {
if (kev.filter == EVFILT_USER &&
kev.ident >= event_first &&
kev.ident <= event_last) {
_lastKQUserData = kev.udata;
return kev.ident;
}
}
else {
break;
}
} return event_timeout;
}
最后 _waitForEventWithTimeout / _waitForEvent 被 event_loop_main线程方法中的_eventLoop不断调用,通过_waitForEvent返回的event_type来继续在_handleEvent中处理各种状态需要的操作;
另外_handleEvent中用的是if-else,switch语句是不是性能更好一点,
DOUAudioStreamer 中kqueue的应用的更多相关文章
- DOUAudioStreamer 中的DOUAudioFileProvider理解笔记
概览 DOUAudioFileProvider读取音频文件local,ipod-library,remote audiofile(通过DOUSimpleHTTPRequest封装的CFHTTPMess ...
- Python Twisted、Reactor
catalogue . Twisted理论基础 . 异步编程模式与Reactor . Twisted网络编程 . reactor进程管理编程 . Twisted并发连接 1. Twisted理论基础 ...
- 【转】Python Twisted介绍
Python Twisted介绍 作者:Jessica McKellar 原文链接 Twisted是用Python实现的基于事件驱动的网络引擎框架.Twisted诞生于2000年初,在当时的网络游戏开 ...
- Python Twisted介绍
原文链接:http://www.aosabook.org/en/twisted.html 作者:Jessica McKellar Twisted是用Python实现的基于事件驱动的网络引擎框架.Twi ...
- Linux系统时间与RTC时间【转】
http://bbs.chinaunix.net/forum.php?mod=viewthread&tid=3637782 Linux的RTC驱动相对还是比较简单的,可以将它作为一个普通的字符 ...
- Python开源框架
info:更多Django信息url:https://www.oschina.net/p/djangodetail: Django 是 Python 编程语言驱动的一个开源模型-视图-控制器(MVC) ...
- kqueue例子
网络服务器通常都使用epoll进行异步IO处理,而开发者通常使用mac,为了方便开发,我把自己的handy库移植到了mac平台上.移植过程中,网上居然没有搜到kqueue的使用例子,让我惊讶不已.为了 ...
- 可扩展的事件复用技术:epoll和kqueue
通常来说我喜欢Linux更甚于BSD系统,但是我真的想在Linux上拥有BSD的kqueue功能. 什么是事件复用技术 假设你有一个简单的web服务器,并且那里已经打开了两个socket连接.当服务器 ...
- 在Mac OS X Yosemite 10.10.3 中搭建第一个 ASP.NET 5 Web 项目
终于有时间在 Mac 上安装一下 ASP.NET 5,网上有许多教程,但是多数的时间比较早了,版本不是最新,搭着 Build 2015 的春风,我也实践一下 Mac OS X 上的 ASP.NET 5 ...
随机推荐
- 一个 Vue + Node + MongoDB 博客系统
源码 耗时半载(半个月)的大项目终于完成了.这是一个博客系统,使用 Vue 做前端框架,Node + express 做后端,数据库使用的是 MongoDB.实现了用户注册.用户登录.博客管理(文章的 ...
- 你想要的都在这里,ASP.NET Core MVC四种枚举绑定方式
前言 本节我们来讲讲在ASP.NET Core MVC又为我们提供了哪些方便,之前我们探讨过在ASP.NET MVC中下拉框绑定方式,这节我们来再来重点看看枚举绑定的方式,充分实现你所能想到的场景,满 ...
- CSS3 基础知识[转载minsong的博客]
CSS3 基础知识1.边框 1.1 圆角 border-radius:5px 0 0 5px; 1.2 阴影 box-shadow:2px 3px 4px 5px rgba(0,0,0 ...
- linux 中的搜索命令
which 查看可执行文件的位置. whereis 查看文件位置. locate 配合数据库查看文件位置. find 实际搜索硬盘查询文件名称. grep 查找文件内容 一般不常用find命令,因为f ...
- 关于制作C语言头文件的思考
我们接触的第一个c语言代码是这个: #include<stdio.h> main() { printf("Hello World"); } 这是最简单的c代码,然而,它 ...
- iOS关于Cookie验证登录状态
1.第一次进入应用,登录获取Cookie,此时如果用到的是AFN去获取接口数据,Cookie已经写入了,所以无需处理,每次请求的时候,会自动将该cookie传给后台去验证 2.将Cookie缓存到本地 ...
- Android学习资料整理
1.官方网站 http://developer.android.com/index.html http://android-developers.blogspot.com/ 2.Android Des ...
- hdu2571 命运 简单DP
简单dp 状态方程很好想,主要是初始化.... 代码: #include<iostream> #include<cstdlib> #include<cstdio> ...
- JavaScript作用域问题
最近在研究JavaScript,遇到了好多问题,之前还是挺清楚JavaScript作用域的,今天突然发懵了,求哪个大神给讲解一下? 谢谢!
- Linux与堆栈概念
在学习C/C++编程的时候,老师都会反复灌输一些概念.比如程序内变量在堆栈上的分配,栈是由高地址到低地址,堆是由低地址到高地址等等,然后画出这样一幅经典概念图: 图片来自:http://blog.cs ...