去掉录制部分,优化播放直播流部分
**#define QUEUE_BUFFER_SIZE 10 // 队列缓冲个数(设置3时,播放不连续) #define MIN_SIZE_PER_FRAME 2048 // 每帧最小数据长度
BOOL audioQueueUsed[QUEUE_BUFFER_SIZE]; AudioQueueBufferRef pBuffer[QUEUE_BUFFER_SIZE];
@interface QueuePlayer () { AudioQueueRef _playQueue; } // config是外界传入参数的集合 *@property (nonatomic, strong) CCAudioConfig config; // 所有缓存位是否空闲 @property (nonatomic, assign) BOOL empty;
@end
@implementation QueuePlayer
*- (instancetype)initWithConfig:(CCAudioConfig )config { self = [super init]; if (self) { _empty = YES; _config = config;
AudioStreamBasicDescription ASBD;
**ASBD.mSampleRate = config.sampleRate;**
ASBD.mFormatID = kAudioFormatLinearPCM;
ASBD.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;
**ASBD.mChannelsPerFrame = (int32_t)config.channelCount;**
ASBD.mFramesPerPacket = 1;
ASBD.mBitsPerChannel = 16;
ASBD.mBytesPerFrame = (ASBD.mBitsPerChannel / 8) * ASBD.mChannelsPerFrame;
ASBD.mBytesPerPacket = ASBD.mBytesPerFrame * ASBD.mFramesPerPacket;
OSStatus status = AudioQueueNewOutput(&ASBD, queueOutputCallback, (__bridge void *_Nullable)(self), nil, nil, 0, &_playQueue);
if (status != noErr) {
NSLog(@"AudioQueueNewOutput error = %d", (int)status);
}
AudioQueueSetParameter(_playQueue, kAudioQueueParam_Volume, 1.0);
for (int i = 0; i < QUEUE_BUFFER_SIZE; i++) {
AudioQueueAllocateBuffer(_playQueue, MIN_SIZE_PER_FRAME, pBuffer + i);
}
}
return self;
}
-
(void)dealloc { if (_playQueue != NULL) { AudioQueueStop(_playQueue, YES); AudioQueueDispose(_playQueue, YES); _playQueue = NULL; } }
-
(void)start { NSLog(@"%s", func); AudioQueueStart(_playQueue, 0); AudioQueueSetParameter(_playQueue, kAudioQueueParam_Volume, 1.0); }
-
(void)stop { NSLog(@"%s", func); AudioQueueStop(_playQueue, 0); }
*- (void)playPCMData:(NSData )data { AudioQueueBufferRef theBuffer = NULL; for (int i = 0; i < QUEUE_BUFFER_SIZE; i++) { if (audioQueueUsed[i]) { continue; } theBuffer = pBuffer[i]; @synchronized (self) { audioQueueUsed[i] = YES; } memcpy(theBuffer->mAudioData, data.bytes, data.length); theBuffer->mAudioDataByteSize = (UInt32)data.length; AudioQueueEnqueueBuffer(_playQueue, theBuffer, 0, nil);
// 每次充填后都调start,避免填充失败,导致没有callback
**[self start];**
break;
}
}
**- (void)setEmpty:(BOOL)empty { if (_empty == empty) return; _empty = empty;
NSLog(@"%s empty=%d", __func__, empty);
if (empty) {
// 所有缓存位空闲时,就停止播放,适用于退到后台无流情况
[self stop];
}
}**
static void queueOutputCallback(void *__nullable inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer) { QueuePlayer *player = (__bridge QueuePlayer *)inUserData;
NSMutableString *str = [NSMutableString string];
BOOL empty = YES;
for (int i = 0; i < QUEUE_BUFFER_SIZE; i++) {
if (inBuffer == pBuffer[i]) {
@synchronized (player) {
audioQueueUsed[i] = NO;
NSLog(@"-[QueuePlayer %s] buff(%d)使用完成", __func__, i);
}
}
// 检查流缓存使用情况
**if (audioQueueUsed[i] == YES) {
empty = NO;
[str appendFormat:@"1"];
} else {
[str appendFormat:@"0"];
}
}
NSLog(@"-[QueuePlayer %s] buff使用情况:%@", __func__, str);
player.empty = empty;**
}
@end