注意:这个项目的整个代码库是如此之大,以至于发布任何有意义的内容都会使这个问题过于本地化,我试图将任何代码提炼到最基本的内容。我不指望有人直接解决我的问题,但我会投票给那些我认为有帮助或有趣的答案。
此项目使用修改版本的 AudioStreamer 来播放保存到本地设备 (iPhone) 的音频文件。
流是使用以下代码在当前循环上设置和调度的(据我所知,与标准 AudioStreamer 项目没有改变):
CFStreamClientContext context = {0, self, NULL, NULL, NULL};
CFReadStreamSetClient(
stream,
kCFStreamEventHasBytesAvailable | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered,
ASReadStreamCallBack,
&context);
CFReadStreamScheduleWithRunLoop(stream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
ASReadStreamCallBack
调用:
- (void)handleReadFromStream:(CFReadStreamRef)aStream
eventType:(CFStreamEventType)eventType
在 AudioStreamer 对象上,在使用以下代码读取流之前,这一切都可以正常工作:
BOOL hasBytes = NO; //Added for debugging
hasBytes = CFReadStreamHasBytesAvailable(stream);
length = CFReadStreamRead(stream, bytes, kAQDefaultBufSize);
hasBytes
YES
但是当CFReadStreamRead
调用时,执行停止,应用程序不会崩溃,它只是停止刺激,CFReadStreamRead
调用以下的任何断点都不会命中,并且不会再次调用ASReadStreamCallBack
。
我不知道是什么原因导致这种情况,我最好的猜测是线程正在终止?但是如何和为什么是我问的原因。
以前有人见过这种行为吗?我如何追踪它,关于如何解决它的想法将非常受欢迎!
通过评论请求的其他信息
- 这是100%可重复的
-
CFReadStreamHasBytesAvailable
是我添加的用于调试,但删除它不起作用
首先,我假设CFReadStreamScheduleWithRunLoop()
与CFReadStreamRead()
在同一线程上运行?
此线程是否正在处理其运行循环?不这样做是我的主要怀疑。您在此线程上有类似 CFRunLoopRun()
或等效的调用吗?
通常没有理由生成一个单独的线程来异步读取流,所以我对你的线程设计有点困惑。这里真的涉及后台线程吗?此外,通常CFReadStreamRead()
会在客户端回调中(当您收到 kCFStreamEventHasBytesAvailable
事件(它似乎在链接代码中)时),但您建议从不调用ASReadStreamCallBack
。你是如何修改音频流的?
流指针可能只是以某种方式损坏。 如果字节可用,CFReadStreamRead 当然不应该阻塞(对于本地文件,它肯定不会阻塞超过几毫秒)。 能否提供用于创建流的代码?
或者,CFReadStreams 异步发送消息,但有可能(但不太可能)阻塞,因为未处理运行循环。
如果你愿意,我已经上传了我的AudioPlayer,灵感来自Matt在 https://code.google.com/p/audjustable/托管的AudioStreamer。 它支持本地文件(以及HTTP)。 我认为它可以满足您的需求(不仅仅是来自HTTP的流文件)。