Portrait videos no longer retain aspect ratio in iOS 14

Viewed 486

Using version Texture 3.0.0 with XCode 12 and iOS 14, a problem that appears only on iOS 14 devices, is that portrait videos load with the wrong resolution (it may seem that they swap their width with their height).

Auto play works fine, but manual play does not. Portrait videos are broken, but landscape videos are not. The issue is that the gravity applied seems to stretch the video using the wrong width/height for portrait videos.

Sample app below (using a public portrait video I uploaded):

//
//  ViewController.swift
//  test video
//
//  Created by Ericos Georgiades on 22/09/2020.
//

import UIKit
import AVFoundation
import AsyncDisplayKit

class ViewController: UIViewController {

    
    @IBOutlet weak var videoView: UIView!
    private let videoNode = ASVideoNode();
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        videoNode.gravity = AVLayerVideoGravity.resizeAspectFill.rawValue;
        videoNode.muted = true;
        videoNode.shouldAutorepeat = true;
        videoNode.shouldAutoplay = false; // works if true
        videoView.addSubnode(videoNode);
        videoNode.frame = videoView.frame;
        
        let asset = AVAsset(url: URL(string: "https://storage.googleapis.com/pao-uat-6b24c.appspot.com/users/0QhK2lnaQ49BftJTRQ46/spots/7q0Q2TjiIyHyrNTBbJOO/media/WaMnS8Np5vkTcIV0rGyJ/WaMnS8Np5vkTcIV0rGyJ?alt=media&token=75542345-06cc-4e37-a422-1ff2a1cf47c2")!)
        videoNode.asset = asset

        DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
            self.videoNode.play();
        }
    }
}

I have yet to figure out if this is a bug with the library or if this is possible to resolve in Swift without a library fix (or if its needed at all).

Also posted as a bug on https://github.com/TextureGroup/Texture/issues/1918

1 Answers

Try to call didExitPreloadState() before play():

...
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
      self.videoNode.didExitPreloadState()
      self.videoNode.play();
}
...

In the sample they set the asset immediately before play(). The setter of the asset calls didExitPreloadState() internally (see here).

Related