Jumhyn
Jumhyn

Reputation: 6777

AVPlayerLayer flashes black on AVPlayer.replaceCurrentItem(with:)

I have an AVPlayer object that I am using to play a video. When the user taps a button, the video is swapped out for a different video, which continues playing. Just using replaceCurrentItem(with:) is resulting in a few tenths of a second of a black frame appearing on my AVPlayerLayer that is displaying the video content.

I have code in place to render an image at the current frame before the AVPlayerItem is swapped out, to bridge the gap before the new AVPlayerItem has a frame ready to display, but the black frame is blocking this image from view. Is there any way to control what the AVPlayerLayer will render before it has actual video data to display?

Alternatively, is there a way to be notified that the AVPlayerLayer (or the AVPlayerItem has actually begun displaying video data? Observing for when the state of the item becomes .readyToPlay triggers too early, hiding the image at that point still leaves the black frame visible.

Upvotes: 3

Views: 1741

Answers (1)

Kentaro Okuda
Kentaro Okuda

Reputation: 1592

I had the same flash problem with my macOS app. I resolved it by renewing AVPlayerLayer each time I play a new file.

I have an AVPlayer subclass. The function below removes AVPlayerLayer from its super layer and add a new layer to the view.

class MyVideoPlayer: AVPlayer {

    func addLayer(view: NSView) {
        view.layer!.sublayers?
            .filter { $0 is AVPlayerLayer }
            .forEach { $0.removeFromSuperlayer() }
        let layer = AVPlayerLayer.init(player: self)
        layer.videoGravity = AVLayerVideoGravity.resize
        layer.frame = view.bounds
        view.layer!.addSublayer(layer)
    }

}

In my ViewController, I call this before I play a video content.

myVideoPlayer.addLayer(view: self.view)

Upvotes: 1

Related Questions