AVAsset 是一个播放音频和视频的抽象类。
比较常用到的是它的子类 AVURLAsset ,通过 URL 实例化它。AVComposition 是用于时间编辑的。
要播放一个AVAsset实例,需要先初始化一个 AVPlayerItem 实例,使用 AVPlayerItem 去设置一些初始化状态(例如:timeRange),然后将 player item 提供给 AVPlayer 去播放。
AVAssetReader 望名知义,作用就是从 AVAsset 获取音频/视频数据。
AVAssetReader 能够让你:
- 直接从存储中读取未解码的音频/视频采样率,解码成需要渲染的形式。
- 混合 asset 的音轨和组合视频的音轨(通过使用 AVAssetReaderAudioMixOutput 和 AVAssetReaderVideoCompositionOutput)
AVAssetReaderOutput 是一个抽象类,作用是从 AVAssetReader 里读取读取单一集合里多媒体的采样率。
可以使用 AVAssetReader 的addOutput:方法向 AVAssetReader里添加 AVAssetReaderOutput 的具体实现类来读取多媒体(音频/视频)数据。
AVAssetReaderAudioMixOutput 是 AVAssetReaderOutput 的子类,作用是读取 AVAssetReader 里的一个或者多个 Asset 混合后的音频采样率。采样率能够以默认的格式读取或者转化成其他的格式。
初始化方式有两种:
CMFormatDescriptions 是 Core Foundation 的一个不可变对象,描述了各种各样的多媒体数据,包括音频、视频和混合多媒体数据。它有两种类型的API:media-type-agnostic 和 media-type-specific。具体查看 CMFormatDescriptions。
最后,放上一段播放 iPod 音频初始化的代码,仅供参考:
NSURL *asset_url = [NSURL URLWithString:ipodPath];
NSError *reader_error=nil;
_asset = [AVURLAsset URLAssetWithURL:asset_url options:nil];
if (_asset == nil || [_asset URL] == nil ) {
_errorCode = DECODE_ERROR_CODE_IPOD_PATH_ERROR;
[self callBackOnPreDecode:PRE_DECODE_STATUS_FAIL];
return ;
}
_duration = _asset.duration;
_assetReader =[AVAssetReader assetReaderWithAsset:_asset error:&reader_error];
if (reader_error) {
NSLog(@"failed to creat asset reader,reason:%@",[reader_error description]);
_errorCode = DECODE_ERROR_CODE_IPOD_DECODE_ERROR;
[self callBackOnPreDecode:PRE_DECODE_STATUS_FAIL];
return ;
}
NSArray *asset_tracks=_asset.tracks;
NSMutableArray *audio_asset_tracks = [[NSMutableArray alloc] initWithCapacity:asset_tracks.count];
for (int i=0; i< asset_tracks.count; i++) {
AVAssetTrack *track = [asset_tracks objectAtIndex:0];
if ([track.mediaType isEqualToString:AVMediaTypeAudio]) {
[audio_asset_tracks addObject:track];
}
}
if ([audio_asset_tracks count] < 1) {
NSLog(@"no tracks");
_errorCode = DECODE_ERROR_CODE_IPOD_DECODE_ERROR;
[self callBackOnPreDecode:PRE_DECODE_STATUS_FAIL];
return ;
}
_assetOutput = [AVAssetReaderAudioMixOutput assetReaderAudioMixOutputWithAudioTracks:audio_asset_tracks audioSettings:nil];
if ([_assetReader canAddOutput:_assetOutput]) {
[_assetReader addOutput:_assetOutput];
}else {
NSLog(@"the reader can not add the output");
_errorCode = DECODE_ERROR_CODE_IPOD_DECODE_ERROR;
[self callBackOnPreDecode:PRE_DECODE_STATUS_FAIL];
return ;
}
NSArray *formatDesc = ((AVAssetTrack*)[[_assetOutput audioTracks] objectAtIndex:0]).formatDescriptions;
for (unsigned int i = 0; i < [formatDesc count]; ++i) {
CMAudioFormatDescriptionRef item = (__bridge CMAudioFormatDescriptionRef)[formatDesc objectAtIndex:i];
const AudioStreamBasicDescription *asDesc = (AudioStreamBasicDescription*)CMAudioFormatDescriptionGetStreamBasicDescription(item);
if (asDesc) {
// get data
streamDesc = *asDesc;
break;
}
}
[self callBackOnPreDecode:PRE_DECODE_STATUS_SUCCESS];
_seekTime = 0;
_assetReader.timeRange = CMTimeRangeMake(CMTimeMakeWithSeconds(_seekTime, _asset.duration.timescale), kCMTimePositiveInfinity);
[_assetReader startReading];