Pau*_*ouh 30 iphone objective-c avfoundation video-streaming ios
我的主要目标是从服务器流式传输视频,并在流式传输时逐帧剪切(以便OpenGL可以使用它).为此,我使用了我在互联网上随处可见的代码(我记得它来自Apple的GLVideoFrame示例代码):
NSArray * tracks = [asset tracks];
NSLog(@"%d", tracks.count);
for(AVAssetTrack* track in tracks) {
NSLog(@"type: %@", [track mediaType]);
initialFPS = track.nominalFrameRate;
width = (GLuint)track.naturalSize.width;
height = (GLuint)track.naturalSize.height;
NSError * error = nil;
// _movieReader is a member variable
@try {
self._movieReader = [[[AVAssetReader alloc] initWithAsset:asset error:&error] autorelease];
}
@catch (NSException *exception) {
NSLog(@"%@ -- %@", [exception name], [exception reason]);
NSLog(@"skipping track");
continue;
}
if (error)
{
NSLog(@"CODE:%d\nDOMAIN:%@\nDESCRIPTION:%@\nFAILURE_REASON:%@", [error code], [error domain], error.localizedDescription, [error localizedFailureReason]);
continue;
}
NSString* key = (NSString*)kCVPixelBufferPixelFormatTypeKey;
NSNumber* value = [NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA];
NSDictionary* videoSettings = [NSDictionary dictionaryWithObject:value forKey:key];
[_movieReader addOutput:[AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:track
outputSettings:videoSettings]];
[_movieReader startReading];
[self performSelectorOnMainThread:@selector(frameStarter) withObject:nil waitUntilDone:NO];
}
Run Code Online (Sandbox Code Playgroud)
但我总是得到这个例外[[AVAssetReader alloc] initWithAsset:error:].
NSInvalidArgumentException -- *** -[AVAssetReader initWithAsset:error:] Cannot initialize an instance of AVAssetReader with an asset at non-local URL 'http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8'
Run Code Online (Sandbox Code Playgroud)
所以我的两个问题是:
AVAssetReader必须有本地URL?它可以用于流式传输(就像其他AVFoundation类一样)吗?AVFoundation方法不起作用,那么流式传输视频并同时拆分帧的其他建议是什么?非常感谢你的帮助.
Dev*_*hen 36
@Cocoanetics,由于低代表我无法发表评论.但你所说的似乎并不完全正确.AVFoundation似乎没有区分本地和非本地文件,因为它在使用的KIND文件或协议之间.使用mp4/mov与通过m3u8使用HTTP Live流协议之间有一个非常明显的区别,但使用本地或远程mp4的差异有点模糊.
为了扩展上述内容:
a)如果你的"远程"资产是M3U8(也就是说,你正在使用HTTP'直播'流媒体),那么就没有任何机会了.无论M3U8是在本地文件系统中还是在远程服务器上,由于多种原因,AVAssetReader和所有与AVAsset相关的功能都不起作用.However, AVPlayer, AVPlayerItem etc would work just fine.
b)如果是MP4/MOV,则需要进一步调查.Local MP4/MOV's work flawlessly.在远程MP4/MOV的情况下,我能够创建(或从AVPlayerItem或AVPlayer或AVAssetTracks中检索)AVURLAsset,我有时能够成功初始化AVAssetReader(我将扩展'有时'同样,不久).但是,copyNextSampleBuffer always returns nil in case of remote MP4's.由于UPTO调用copyNextSampleBuffer的工作有几点,我不是100%肯定:
i)copyNextSampleBuffer不能用于远程mp4,在所有其他步骤成功之后,是预期/预期的功能.
ii)"其他步骤"似乎对远程MP4起作用是苹果公司实施的一个意外,当我们点击copyNextSampleBuffer .............时,这种不兼容性就会突然出现.这些"其他步骤"是什么,我将很快详述.
iii)尝试为远程MP4调用copyNextSampleBuffer时,我做错了什么.
所以@Paula你可以尝试用远程MOV/MP4进一步调查.
作为参考,以下是我尝试从视频中捕获帧的方法:
一个)
直接从视频URL创建AVURLAsset.
使用[asset tracksWithMediaType:AVMediaTypeVideo]检索视频轨道
使用视频轨道作为源准备AVAssetReaderTrackOutput.
使用AVURLAsset创建AVAssetReader.
将AVAssetReaderTrackOutput添加到AVAssetReader和startReading.
使用copyNextSampleBuffer检索图像.
b)
从视频URL创建AVPlayerItem,然后从中创建AVPlayer(或直接从URL创建AVPlayer).
检索AVPlayer的'asset'属性并使用"loadValuesAsynchronouslyForKeys:"加载其'track'.
将AVMediaTypeVideo类型的轨道分开(或者在加载轨道后简单地在资产上调用tracksWithMediaType:),并使用视频轨道创建AVAssetReaderTrackOutput.
使用AVPlayer的"资产","startReading"创建AVAssetReader,然后使用copyNextSampleBuffer检索图像.
C)
直接从视频URL创建AVPlayerItem + AVPlayer或AVPlayer.
KVO AVPlayerItem的'tracks'属性,加载曲目后,将AVMediaTypeVideo类型的AVAssetTracks分开.
从AVPlayerItem/AVPlayer/AVAssetTrack的'asset'属性中检索AVAsset.
其余步骤与方法(b)类似.
d)
直接从视频URL创建AVPlayerItem + AVPlayer或AVPlayer.
KVO AVPlayerItem的'tracks'属性,加载曲目后,将AVMediaTypeVideo类型分开.
创建AVMutableComposition,并初始化AVMediaTypeVideo类型的关联AVMutableCompositionTrack.
将之前检索到的视频轨道中的相应CMTimeRange插入此AVMutableCompositionTrack.
与(b)和(c)类似,现在创建AVAssetReader和AVAssetReaderTrackOutput,但区别在于您使用AVMutableComposition作为初始化AVAssetReader的基本AVAsset,并使用AVMutableCompositionTrack作为AVAssetReaderTrackOutput的基本AVAssetTrack.
'startReading'并使用copyNextSampleBuffer从AVAssetReader获取帧.
PS:我尝试在这里接近(d)来解决直接从AVPlayerItem或AVPlayer检索到的AVAsset没有表现的事实.所以我想从我手头的AVAssetTracks创建一个新的AVAsset.不可否认,也许是没有意义的(如果不是最初的AVAsset,最终还是会从哪里获取赛道信息!)但是无论如何都值得绝望.
以下是不同类型文件的结果摘要:
1)本地MOV/MP4 - 所有4种方法都能完美运行.
2)远程MOV/MP4 - 在方法(b)到(d)中正确检索资产和轨道,AVAssetReader也被初始化,但copyNextSampleBuffer总是返回nil.在(a)的情况下,AVAssetReader本身的创建失败,出现'未知错误'NSOSStatusErrorDomain -12407.
3)本地M3U8(通过应用程序内/本地HTTP服务器访问) - 方法(a),(b)和(c)失败,因为试图获得任何形状或形式的AVURLAsset/AVAsset通过M3U8传输的文件是傻瓜差事.
在(a)的情况下,根本不创建资产,并且AVURLAsset上的initWithURL:调用失败,并显示"未知错误"AVFoundationErrorDomain -11800.
在(b)和(c)的情况下,从AVPlayer/AVPlayerItem或AVAssetTracks中检索AVURLAsset会返回SOME对象,但访问它上面的'tracks'属性总是返回一个空数组.
在(d)的情况下,我能够成功检索和隔离视频轨道,但在尝试创建AVMutableCompositionTrack时,尝试将CMTimeRange从源轨道插入到AVMutableCompositionTrack时失败,并显示"未知错误" NSOSStatusErrorDomain -12780.
4)远程M3U8的行为与本地M3U8完全相同.
我没有完全了解为什么这些差异存在,或者不能被Apple减轻.但是你去吧.
| 归档时间: |
|
| 查看次数: |
18508 次 |
| 最近记录: |