Mat*_*ing 5 cocoa-touch objective-c avfoundation
这是我的目标:我想将.3gp电影文件加载到AVURLAsset中.然后我想拍摄视频轨道并将输出帧泵入OpenGL ES纹理.这将是视频播放.然后我想继续利用AVFoundation来播放音频.这个框架相当广泛,所以我希望能有一些老练的帮助.
实际上我有两个部分分别工作,但当我尝试同时做两件事时总会出错.这是我目前的尝试,简而言之(为简洁起见省略了所有错误处理):
我将.3gp文件加载到AVURLAsset并加载轨道:
NSURL* fileURL = [[NSBundle mainBundle] URLForResource:someName withExtension:someExtension];
AVURLAsset* asset = [AVURLAsset URLAssetWithURL:fileURL options:nil];
[asset loadValuesAsynchronouslyForKeys:[NSArray arrayWithObject:@"tracks"] completionHandler:^ {/* More Code */}];
Run Code Online (Sandbox Code Playgroud)
在完成处理程序中,我获得了对音频和视频轨道的引用:
// Tracks loaded, grab the audio and video tracks.
AVAssetTrack* videoTrack = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
AVAssetTrack* audioTrack = [[asset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
Run Code Online (Sandbox Code Playgroud)
接下来,我创建了单独的AVMutableComposition,它只包含音轨和视频轨道.我不确定这是否完全必要,但它似乎是一个好主意,它似乎也有效:
// Make a composition with the video track.
AVMutableComposition* videoComposition = [AVMutableComposition composition];
AVMutableCompositionTrack* videoCompositionTrack = [videoComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
[videoCompositionTrack insertTimeRange:[videoTrack timeRange] ofTrack:videoTrack atTime:CMTimeMake(0, 1) error:nil];
// Make a composition with the audio track.
AVMutableComposition* audioComposition = [AVMutableComposition composition];
AVMutableCompositionTrack* audioCompositionTrack = [audioComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
[audioCompositionTrack insertTimeRange:[audioTrack timeRange] ofTrack:audioTrack atTime:CMTimeMake(0, 1) error:nil];
Run Code Online (Sandbox Code Playgroud)
现在我详细介绍如何处理每个轨道.我非常有信心,我有处理视频轨道的唯一方法,即为视频合成创建AVAssetReader,并添加使用视频合成轨道创建的AVAssetTrackReaderOutput.通过保持对该轨道输出的引用,我可以调用其-copyNextSampleBuffer
方法来获取将视频输出泵入OpenGL ES纹理所需的信息.这本身就足够好了:
// Create Asset Reader and Output for the video track.
NSDictionary* settings = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:kCVPixelFormatType_32BGRA] forKey:(NSString *)kCVPixelBufferPixelFormatTypeKey];
_assetReader = [[AVAssetReader assetReaderWithAsset:vComposition error:nil] retain];
_videoTrackOutput = [[AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:vCompositionTrack outputSettings:settings] retain];
[_assetReader addOutput:_videoTrackOutput];
[_assetReader startReading];
Run Code Online (Sandbox Code Playgroud)
似乎破坏了整个事情的是试图以任何方式播放音频.我不确定采用哪种方法来保留剩余的音轨.只是坚持AVFoundation的领域,我看到两种可能的方法.第一种是使用AVPlayer播放音频合成:
// Create a player for the audio.
AVPlayerItem* audioPlayerItem = [AVPlayerItem playerItemWithAsset:aComposition];
AVPlayer* audioPlayer = [[AVPlayer playerWithPlayerItem:audioPlayerItem] retain];
[audioPlayer play];
Run Code Online (Sandbox Code Playgroud)
这是有效的,因为我可以听到所需的音频.不幸的是,创建此播放器可确保视频合成的AVAssetReaderTrackOutput在调用时失败并出现神秘错误-copyNextSampleBuffer
:
AVAssetReaderStatusFailed
错误域= AVFoundationErrorDomain代码= -11800"操作无法完成"UserInfo = 0x456e50 {NSLocalizedFailureReason =发生未知错误(-12785),NSUnderlyingError = 0x486570"操作无法完成.(OSStatus错误-12785.) ",NSLocalizedDescription =操作无法完成}
我对他们如何互相干扰感到困惑,但无论如何,这种方法似乎都是死路一条.
我考虑用于音频播放的另一个选项是AVAudioPlayer类,但我无法使用AVAsset作为起点.我尝试将其-initWithData:error:
方法与通过聚合CMSampleBufferRefs的内容而构建的NSData 一起使用,其方法与我在视频轨道上使用的方法相同,但似乎没有正确格式化.
在这一点上,我觉得我在盲目地挥舞着,如果有人能告诉我这种方法是否可行,我会非常喜欢它.如果不是,我当然会欣赏一个可行的.
为每个轨道创建 AVMutableCompositions (基本上是新的 AVAssets)对我来说似乎很绕,我只是在音轨上使用 AVAssetReader 。另外,您的 videoComposition 似乎没有在任何地方使用,那么为什么要创建它呢?
无论如何,要使任一解决方案发挥作用,请将音频会话类别设置为kAudioSessionCategory_MediaPlayback
并启用kAudioSessionProperty_OverrideCategoryMixWithOthers
。
我从未找到任何文档来解释为什么这是必要的。
归档时间: |
|
查看次数: |
2748 次 |
最近记录: |