Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS 10 - AVPlayer shows black screen when playing video

Here I have a method that adds the video layer to the UIView that I have setup in IB:

 -(void)loadPlayer{
        self.asset = [AVAsset assetWithURL:url];

        AVPlayerItem *item = [AVPlayerItem playerItemWithAsset:self.asset];

        self.player = [AVPlayer playerWithPlayerItem:item];
        self.playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.player];
        self.playerLayer.contentsGravity = AVLayerVideoGravityResizeAspect;
        self.player.actionAtItemEnd = AVPlayerActionAtItemEndNone;

        item.videoComposition = [AVVideoComposition videoCompositionWithPropertiesOfAsset:self.asset];

        [self.player pause];
        [self.player addObserver:self forKeyPath:@"status" options:0 context:nil];

        dispatch_async(dispatch_get_main_queue(), ^{
            [self.videoLayer.layer addSublayer:self.playerLayer];
        });
}

The above method gets called in the viewDidAppear of the View Controller, so each time the current View Controller loads, the video should start to play.

Here I check for the player status and play the asset if ready:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
                        change:(NSDictionary *)change context:(void *)context {
    if (object == self.player && [keyPath isEqualToString:@"status"]) {
        if (self.player.status == AVPlayerStatusReadyToPlay) {
            [self.player play];
        }
    }
}

The problem is that the view did appear, the video starts playing, but only the audio, not video. All I get is black screen in the place of video. Audio is playing back fine, but it does not seem to render the video frames for some reason unknown.

This happens only on iOS 10 devices, the same code when run on a iOS 9 devices, works like a charm. The video shows up as expected.

Is there anything that is changed in the AVFoundation framework for iOS 10 in terms of AVPlayer or so? Or is there anything that I am missing here, coz iOS 9 plays it good.

If anyone has faced this issue, and if you have solved it, please post your solution. It would be helpful.

Thanks.


THE SOLUTION

Thanks for your replies! I just found that, for some reason in iOS 10 the viewDidLayoutSubviews did not get called as it was in iOS 9. Actually I was setting the player layer's frame in the viewDidLayoutSubviews method. Since it didn't get called, I was not able to see the player on screen. What I did was, set the player layer's frame in the loadPlayer method above. And it works fine. Hope this helps someone.

This is the line of code that I moved from viewDidLayoutSubviews to my loadPlayer method and it worked:

self.playerLayer.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
like image 802
badhanganesh Avatar asked Oct 27 '16 11:10

badhanganesh


2 Answers

You need to retain your instance of AVPlayerItem i.e. as a property or an instance variable. The reference to the movie player is lost if you do not retain it. Even some time this rubish happens in ARC as well.Please make it property.

like image 143
Matloob Hasnain Avatar answered Oct 17 '22 21:10

Matloob Hasnain


In my case this problem was because i started playing simultaneously with UIView.animate with view.layoutIfNeeded() in animation block.

The fix for that is to not animate layout changes when not needed and not animate when starting playing video.

like image 24
Nik Kov Avatar answered Oct 17 '22 19:10

Nik Kov