AVFoundation重现视频循环

时间:2013-03-29 16:41:11

标签: objective-c video avfoundation avassetreader

我需要在OpenGL应用程序中无限期地重现视频(在视频结束时重新启动视频)。 为此,我正在尝试使用AV基础。 我创建了一个AVAssetReader和一个AVAssetReaderTrackOutput,我利用copyNextSampleBuffer方法获取CMSampleBufferRef并为每个帧创建一个OpenGL纹理。

    NSString *path = [[NSBundle mainBundle] pathForResource:videoFileName ofType:type];
    _url = [NSURL fileURLWithPath:path];

    //Create the AVAsset 
    _asset = [AVURLAsset assetWithURL:_url];

    //Get the asset AVAssetTrack
    NSArray *arrayAssetTrack = [_asset tracksWithMediaType:AVMediaTypeVideo];
    _assetTrackVideo = [arrayAssetTrack objectAtIndex:0];

    //create the AVAssetReaderTrackOutput
    NSDictionary *dictCompressionProperty = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:kCVPixelFormatType_32BGRA] forKey:(id) kCVPixelBufferPixelFormatTypeKey];
    _trackOutput = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:_assetTrackVideo outputSettings:dictCompressionProperty];

    //Create the AVAssetReader
    NSError *error;
    _assetReader = [[AVAssetReader alloc] initWithAsset:_asset error:&error];
    if(error){
        NSLog(@"error in AssetReader %@", error);
    }
    [_assetReader addOutput:_trackOutput];
    //_assetReader.timeRange = CMTimeRangeMake(kCMTimeZero, _asset.duration);

    //Asset reading start reading
    [_assetReader startReading];

我的GLKViewController的in -update方法我调用以下内容:

if (_assetReader.status == AVAssetReaderStatusReading){
    if (_trackOutput) {
        CMSampleBufferRef sampleBuffer = [_trackOutput copyNextSampleBuffer];
        [self createNewTextureVideoFromOutputSampleBuffer:sampleBuffer]; //create the new texture
    }
}else if (_assetReader.status == AVAssetReaderStatusCompleted) {
    NSLog(@"restart");
    [_assetReader startReading];
}

所有工作正常,直到AVAssetReader处于读取状态,但是当它完成读取并且我尝试使用新调用[_assetReader startReading]重新启动AVAssetReading时,应用程序崩溃而没有输出。 我做错了什么?在完成阅读时重新启动AVAssetReading是正确的吗?

2 个答案:

答案 0 :(得分:4)

AVAssetReader不支持搜索或重启,它本质上是一个顺序解码器。您必须创建一个新的AVAssetReader对象才能再次读取相同的样本。

答案 1 :(得分:1)

谢谢Costique!你的建议让我重新回答了这个问题。我终于通过创建一个新的AVAssetReader重新启动了读取。但是为了做到这一点,我注意到必须创建一个新的AVAssetReaderTrackOutput并添加到新的AVAssetReader e.g。

[newAssetReader addOutput:newTrackOutput];