iosswiftavplayerpicture-in-picturecmsamplebuffer

iOS PictureInPicture with AVSampleBufferDisplayLayer seek forward disabled


I have an AvPictureInPictureController that should display an image while playing audio. I have created a AVSampleBufferDisplayLayer that has a CMSampleBuffer with an image and the two necessary delegates AVPictureInPictureSampleBufferPlaybackDelegate & AVPictureInPictureControllerDelegate I am setting pictureInPictureController.requiresLinearPlayback = false so the picture in picture window is showing the seek back, play/pause and seek forward buttons. Here is my function for the time range:

func pictureInPictureControllerTimeRangeForPlayback(_ pictureInPictureController: AVPictureInPictureController)
    -> CMTimeRange {
        let duration = player.state.duration

        if duration == 0 {
            return CMTimeRange(start: .negativeInfinity, duration: .positiveInfinity)
        }

        return CMTimeRange(
            start: CMTime(
                seconds: .zero,
                preferredTimescale: 10_000
            ),
            duration: CMTimeMakeWithSeconds(
                duration,
                preferredTimescale: 10_000
            )
        )
    }

My problem is, that seek forward is disabled on picture in picture. Seeking back is working just fine, also play/pause. But seek forward is disabled and I haven't figured out why this is happening. Any thoughts?

I tried to calculate the CMTimeRange differently but it is always the same behaviour.


Solution

  • I found this project https://github.com/getsidetrack/swiftui-pipify/blob/main/Sources/PipifyController.swift#L250 where the CMTimeRange is calculated from the CACurrentMediaTime() and although I am not sure why there is such a big time range calculated (like taking one week in seconds) CACurrentMediaTime() was the right hint.

    So this is how the the pictureInPictureControllerTimeRangeForPlayback looks like now:

    func pictureInPictureControllerTimeRangeForPlayback(
        _ pictureInPictureController: AVPictureInPictureController
    ) -> CMTimeRange {
        if player.duration == 0 {
            return CMTimeRange(start: .negativeInfinity, duration: .positiveInfinity)
        }
    
        let currentTime = CMTime(
            seconds: CACurrentMediaTime(),
            preferredTimescale: 60
        )
    
        let currentPosition = CMTime(
            seconds: state.position,
            preferredTimescale: 60
        )
        return CMTimeRange(
            start: currentTime - currentPosition,
            duration: CMTime(
                seconds: player.duration,
                preferredTimescale: 60
            )
        )
    }