Question

I need to reproduce a video indefinitely (restarting the video when it ends) in my OpenGL application. To do so I'm trying to utilize AV foundation. I created an AVAssetReader and an AVAssetReaderTrackOutput and I utilize the copyNextSampleBuffer method to get CMSampleBufferRef and create an OpenGL texture for each frame.

    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];

And in -update method of my GLKViewController I call the following:

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];
}

All work fine until the AVAssetReader is in the reading status but when it finished reading and I tried to restart the AVAssetReading with a new call [_assetReader startReading], the application crash without output. What I'm doing wrong? It is correct to restart an AVAssetReading when it complete his reading?

Was it helpful?

Solution

AVAssetReader doesn't support seeking or restarting, it is essentially a sequential decoder. You have to create a new AVAssetReader object to read the same samples again.

OTHER TIPS

Thanks Costique! Your suggestion brings me back on the problem. I finally restarted the reading by creating a new AVAssetReader. However in order to do that I noted that a new AVAssetReaderTrackOutput must be created and added to the new AVAssetReader e.g.

[newAssetReader addOutput:newTrackOutput]; 
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top