魏名华

不要偷懒,做更好的自己

Nothing


No Welcome Message

Douaudiostreamer

播放流程

UI -> DOUAudioStreamer

ViewController->ViewController: viewWillAppear
ViewController->ViewController: resetStreamer
ViewController->ViewController: 清空流cancelStreamer
Note right of ViewController:  <DOUAudioFile>)audioFile
ViewController->DOUAudioStreamer: 初始化AudioStreamer
DOUAudioStreamer->DOUAudioFileProvider: 初始化FileProvider:_audioFile
DOUAudioFileProvider->DOUAudioStreamer: 计算缓存bufferingRatio
ViewController->DOUAudioStreamer: play
ViewController->ViewController: 更新缓存updateBufferingStatus
ViewController->ViewController: setupHintForStreamer
ViewController->DOUAudioStreamer: 设置下一曲setHintWithAudioFile
DOUAudioStreamer->DOUAudioFileProvider: setHintWithAudioFile

DOUAudioStreamer内部实现

DOUAudioStreamer->DOUAudioStreamer: play
DOUAudioStreamer->DOUAudioEventLoop: setCurrentStreamer
Note right of DOUAudioEventLoop:  单例
Note right of DOUAudioEventLoop:  初始化持有DOUAudioRenderer
DOUAudioStreamer->DOUAudioEventLoop: play
DOUAudioEventLoop->DOUAudioEventLoop: _sendEvent:event_play
DOUAudioEventLoop->DOUAudioEventLoop: _handleEvent:withStreamer:
DOUAudioEventLoop->DOUAudioRenderer: setInterrupted:NO
Note right of DOUAudioEventLoop:  播放,暂停等都通过_renderer实现

音频文件种类

DOUAudioStreamer->DOUAudioFileProvider: fileProviderWithAudioFile
Note right of DOUAudioFileProvider:  网络音频
DOUAudioFileProvider->_DOUAudioRemoteFileProvider: _initWithAudioFile
Note right of DOUAudioFileProvider:  本地文件
DOUAudioFileProvider->_DOUAudioLocalFileProvider: _initWithAudioFile
Note right of DOUAudioFileProvider:  ipod-library
DOUAudioFileProvider->_DOUAudioMediaLibraryFileProvider: _initWithAudioFile

文件流下载

_DOUAudioRemoteFileProvider->_DOUAudioRemoteFileProvider: _initWithAudioFile
_DOUAudioRemoteFileProvider->_DOUAudioRemoteFileProvider: _openAudioFileStream
_DOUAudioRemoteFileProvider->_DOUAudioRemoteFileProvider: _openAudioFileStreamWithFileTypeHint
Note right of _DOUAudioRemoteFileProvider: AudioFileStreamOpen
_DOUAudioRemoteFileProvider->_DOUAudioRemoteFileProvider: _createRequest
_DOUAudioRemoteFileProvider->DOUSimpleHTTPRequest: requestWithURL
Note right of DOUSimpleHTTPRequest: 请求通过Block回调给provider
DOUSimpleHTTPRequest->_DOUAudioRemoteFileProvider: _requestDidReceiveData
Note right of _DOUAudioRemoteFileProvider: AudioFileStreamParseBytes
_DOUAudioRemoteFileProvider->_DOUAudioRemoteFileProvider: _openAudioFileStreamWithFileTypeHint
Note right of _DOUAudioRemoteFileProvider: AudioFileStreamOpen

AudioFileStreamOpen: Creates and opens a new audio file stream parser.

播放

DOUAudioEventLoop->DOUAudioEventLoop: _eventLoop
DOUAudioEventLoop->DOUAudioEventLoop: _handleStreamer
DOUAudioStreamer->DOUAudioDecoder: decodeOnce
DOUAudioDecoder->DOUAudioLPCM: writeBytes
DOUAudioDecoder->DOUAudioLPCM: readBytes
DOUAudioEventLoop->DOUAudioRenderer: renderBytes
Note right of DOUAudioRenderer: AudioOutputUnitStart
DOUAudioRenderer->DOUAudioRenderer: initWithBufferTime
DOUAudioRenderer->DOUAudioRenderer: _setupPropertyListenerForDefaultOutputDevice
Note right of DOUAudioRenderer: AudioObjectAddPropertyListener
DOUAudioRenderer->DOUAudioRenderer: property_listener_default_output_device
DOUAudioRenderer->DOUAudioRenderer: _handlePropertyListenerForDefaultOutputDevice
Note right of DOUAudioRenderer: AudioOutputUnitStart

DOUAudioFileProvider

seek爆音,跟其他没关系,重要的是DOUAudioDecoder的decodeOnce方法里面,decodingContext.outputPos是正确的,但是_decodingContext.outputBuffer到底是怎么回事呢?

DOUAudioFileProvider

文件缓存

+ (NSString *)_cachedPathForAudioFileURL:(NSURL *)audioFileURL
{
  NSString *filename = [NSString stringWithFormat:@"douas-%@.tmp", [self _sha256ForAudioFileURL:audioFileURL]];
  return [NSTemporaryDirectory() stringByAppendingPathComponent:filename];
}

DOUAudioStreamer

初始化,接收音频文件audioFile <DOUAudioFile>
+ (instancetype)streamerWithAudioFile:(id <DOUAudioFile>)audioFile
{
  return [[[self class] alloc] initWithAudioFile:audioFile];
}

- (instancetype)initWithAudioFile:(id <DOUAudioFile>)audioFile
{
  self = [super init];
  if (self) {
    _audioFile = audioFile;
    _status = DOUAudioStreamerIdle;

    _fileProvider = [DOUAudioFileProvider fileProviderWithAudioFile:_audioFile]; // 初始化_fileProvider
    if (_fileProvider == nil) {
      return nil;
    }

    _bufferingRatio = (double)[_fileProvider receivedLength] / [_fileProvider expectedLength];
  }

  return self;
}