作者chris1000 (矜持)
看板MacDev
标题Re: [问题] iOS播放streaming的audio
时间Wed May 9 17:05:38 2012
※ 引述《johnlinvc (阿翔)》之铭言:
: ※ 引述《chris1000 (矜持)》之铭言:
: : 想法是
: : 1. 将收到的g.726 raw data解码成raw PCM後
: : 2. 再使用audio queue servie去将PCM data enqueue并播放
: : 但是後半段播放出来的声音一直是播一小段顿一下的状况
: : ConnectionRequest.m
: : -(void) connection:(NSURLConnection *)connection
: : didRecieveData:(NSData *)data
: : {
: : int outDataSize = 0;
: : void *outDatabuf = malloc(data.length*8);
: : //将G.726编码的data 解码成raw PCM至outDatabuf
: : [G726Decoder decodeFrame:data.bytes
: : withDatasize:data.length
: : withOutData:outDatabuf
: : withOutDataSize:&outDataSize];
: : dispatch_queue_t playQueue = dispatch_queue_create("play", NULL);
: : dispatch_async(playQueue, ^(void){
: : playBuffer(outDatabuf, outDataSize);
: : free(outDatabuf);
: : });
: : dispatch_release(playQueue);
: : }
: : player.c
: : void AQCallback(void *in, AudioQueueRef inQ, AudioQueueBufferRef outQB)
: : {
: : //将pcm data目前播到的位置开始复制资料到outQB->mAudioData
: : //使用AudioQueueEnqueueBuffer(inQ, outQB, 0, NULL)来Enqueue
: : }
: : int playBuffer(void *pcm, int len)
: : {
: : //使用AudioQueueService播放pcm data
: : //1. 将AudioStreamBasicDescription初始化
: : //2. 使用AudioQueueNewOutput建立一个outputQueue,
: : // callback为AQCallback()
: : //3. 使用AudioQueueAllocateBuffer来建立3个buffer
: : //4. call 1次AQCallback()来Enqueue
: : //5. 使用AudioQueueStart开始播放
: : //6. 用一个while loop卡住直到pcm被播放完毕
: : }
: : 後面player的部分我有试过直接播一个已经存档的PCM raw data
: : 可以很顺利的播完
: : 但是拿来播stream就变成播一下顿一下播一下顿一下
: : 目前didRecieveData收到的data size大约是1000~2000不等
: : 解完码後的PCM大小是四倍,大约是4000~8000不等
: : 请问
: : 1. 是否需要将PCM raw data先丢到一个buffer,
: : 等待累积到一定程度以後再丢去player播放?
: 是
: : 2. 如果需要一个buffer来处理read/write,那麽这个buffer大小应该要多大比较好?
: : 这种buffer management有没有iOS版本的范例可以参考?
: https://github.com/michaeltyson/TPCircularBuffer
: : 3. didRecieveData是否能设定每次收下来都固定大小而不是浮动的?
: 不行
: : 4. 是否改用NSThread会比dispatch queue好?
: 不会
: : 5. 这种情况改用OpenAL会不会比较快....但是OpenAL好像都拿来作同时播放多个音效?
: 不会
: : 感谢各位看到最後<(_ _)>
: 你的问题应该是在产生太多AudioQueue了,变成下面这种状况
: receive data-> decode -> create AudioQueue -> play
: ↑ ↓
: L_______________________________________↲
: 应该是要这样才合理 (buffer big enough)
: create AudioQueue -> receive data -> decode -> add to buffer --> play
: ^ |
: L________________________↲
谢谢您的回覆,在看过几个范例後出现另外一个问题
用objective-c写的AudioQueue可能会长成下面这样:
AudioQueueNewOutput(&dataformat, BufferCallback, self, nil, nil, 0, &queue);
static void BufferCallback(void *inUserData,
AudioQueueRef inAQ,
AudioQueueBufferRef buffer){
MyPlayer *player = (MyPlayer *)inUserData;
[player dosomething];
}
在AudioQueueNewOutput传入的inUserData是self
并且在BufferCallback的地方将inUserData再转型成class
可是如果有开ARC的话,AudioQueueNewOuput中
class转型成void*需要加前置__bridge
(__birdge void*)self
BufferCallback中,void*转型成class也需要加前置__bridge
(__bridge MyPlayer *)inUserData
我这样加是编译得过
但是运行到BufferCallback的转型就...出现EXC_BAD_ACCESS
我是直接试这篇文章的的playAudio:
http://www.cnblogs.com/xuanyuanchen/archive/2012/04/17/2450169.html
请问是否因为哪边Memory management出问题? 还是ARC需要作其他的处理呢?
谢谢<(_ _)>
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 61.216.168.86
1F:→ reon:如果程式本身不是用ARC写 我是建议compiler 加参数去build 05/10 00:17
2F:→ reon:不要用refactor去转成ARC..将单档用-fno-objc-arc去build 05/10 00:19
4F:→ chris1000:感谢您的建议,请问加了-fno-objc-arc後编译仍然有错误 05/10 09:23
5F:→ chris1000:可是可以执行,这样是正常的吗? 05/10 09:23
6F:→ chris1000:另外这个程式即使把arc关掉,执行还是有问题 05/10 09:24
7F:→ chris1000:看来真的是程式本身的memory management有问题... 05/10 09:24
8F:→ reon:也有可能是framewok没加或是Other Linker Flag要加-lstdc++ 05/10 19:31
9F:推 reon:没po error code有些难猜 05/10 19:33
10F:→ chris1000:同样的code新增一个档案重写, xcode就没有错误提示了orz 05/11 00:33