在AVFoundation AVSampleBufferDisplayLayer中循环播放视频

时间:2015-02-19 20:50:29

标签: ios objective-c video avfoundation avplayer

我正在尝试在AVSampleBufferDisplayLayer上循环播放视频。我可以毫无问题地让它玩一次。但是,当我尝试循环它时,它不会继续播放。

根据AVFoundation to reproduce a video loop的答案,没有办法倒回AVAssetReader,所以我重新创建它。 (我确实看到Looping a video with AVFoundation AVPlayer?的答案,但AVPlayer是更全功能。我正在读取文件,但仍想要AVSampleBufferDisplayLayer。)

一个假设是我需要停止一些H264标题,但我不知道这是否有帮助(以及如何)。另一个原因是它与CMTimebase有关,但我尝试了几件事无济于事。

以下代码,基于Apple关于直接访问视频编码的WWDC演讲:

- (void)viewDidLoad {
    [super viewDidLoad];

    NSString *filepath = [[NSBundle mainBundle] pathForResource:@"sample-mp4" ofType:@"mp4"];
    NSURL *fileURL = [NSURL fileURLWithPath:filepath];
    AVAsset *asset = [AVURLAsset URLAssetWithURL:fileURL options:nil];

    UIView *view = self.view;

    self.videoLayer = [[AVSampleBufferDisplayLayer alloc] init];
    self.videoLayer.bounds = view.bounds;
    self.videoLayer.position = CGPointMake(CGRectGetMidX(view.bounds), CGRectGetMidY(view.bounds));
    self.videoLayer.videoGravity = AVLayerVideoGravityResizeAspect;
    self.videoLayer.backgroundColor = [[UIColor greenColor] CGColor];

    CMTimebaseRef controlTimebase;
    CMTimebaseCreateWithMasterClock( CFAllocatorGetDefault(), CMClockGetHostTimeClock(), &controlTimebase );

    self.videoLayer.controlTimebase = controlTimebase;
    CMTimebaseSetTime(self.videoLayer.controlTimebase, CMTimeMake(5, 1));
    CMTimebaseSetRate(self.videoLayer.controlTimebase, 1.0);

    [[view layer] addSublayer:_videoLayer];

    dispatch_queue_t assetQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); //??? right queue?


    __block AVAssetReader *assetReaderVideo = [self createAssetReader:asset];
    __block AVAssetReaderTrackOutput *outVideo = [assetReaderVideo outputs][0];
    if( [assetReaderVideo startReading] )
    {
        [_videoLayer requestMediaDataWhenReadyOnQueue: assetQueue usingBlock: ^{
            while( [_videoLayer isReadyForMoreMediaData] )
            {
                CMSampleBufferRef sampleVideo;
                if ( ([assetReaderVideo status] == AVAssetReaderStatusReading) && ( sampleVideo = [outVideo copyNextSampleBuffer]) ) {
                    [_videoLayer enqueueSampleBuffer:sampleVideo];
                    CFRelease(sampleVideo);
                    CMTimeShow(CMTimebaseGetTime(_videoLayer.controlTimebase));
                }
                else {

                    [_videoLayer stopRequestingMediaData];
                    //CMTimebaseSetTime(_videoLayer.controlTimebase, CMTimeMake(5, 1));
                    //CMTimebaseSetRate(self.videoLayer.controlTimebase, 1.0);
                    //CMTimeShow(CMTimebaseGetTime(_videoLayer.controlTimebase));
                    assetReaderVideo = [self createAssetReader:asset];
                    outVideo = [assetReaderVideo outputs][0];
                    [assetReaderVideo startReading];
                    //sampleVideo = [outVideo copyNextSampleBuffer];

                    //[_videoLayer enqueueSampleBuffer:sampleVideo];
                }
            }
        }];
    }
}

-(AVAssetReader *)createAssetReader:(AVAsset*)asset {
    NSError *error=nil;

    AVAssetReader *assetReaderVideo = [[AVAssetReader alloc] initWithAsset:asset error:&error];

    NSArray *videoTracks = [asset tracksWithMediaType:AVMediaTypeVideo];
    AVAssetReaderTrackOutput *outVideo = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:videoTracks[0] outputSettings:nil]; //dic];
    [outVideo res]

    [assetReaderVideo addOutput:outVideo];
    return assetReaderVideo;
}

非常感谢。

1 个答案:

答案 0 :(得分:0)

尝试使用swift进行循环,然后使用swift文件桥接objective-c文件。谷歌有许多桥接和循环的答案,所以只需用swift谷歌。