Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AVAsset Orientation/Rotation issue

Tried to use Ray great tutorial to fix the orientation issue.

left - how the video should look(portrait), right - unwanted rotated result

enter image description here

Code used

   func setUpVideoNew()
    {

        let originalVideoTrack = asset.tracksWithMediaType(AVMediaTypeVideo)[0]
        let composition = AVMutableComposition()
        let videoTrack = composition.addMutableTrackWithMediaType(AVMediaTypeVideo, preferredTrackID: 1)
        let timeRange = originalVideoTrack.timeRange
        do {
            try videoTrack.insertTimeRange(timeRange, ofTrack: originalVideoTrack, atTime: kCMTimeZero)
        } catch {

        }
        let mainInstruction = AVMutableVideoCompositionInstruction()
        mainInstruction.timeRange = timeRange

        let firstlayerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: videoTrack)
        let firstAssetTrack = originalVideoTrack


        //MARK - Fix Rotation
        var firstAssetOrientation_ = UIImageOrientation.Up

        var isFirstAssetPortrait_ = false

        var firstTransform = videoTrack.preferredTransform;
        if firstTransform.a == 0 && firstTransform.b == 1.0 && firstTransform.c == -1.0 && firstTransform.d == 0 {
            firstAssetOrientation_ = UIImageOrientation.Right;
            isFirstAssetPortrait_ = true;
        }
        if (firstTransform.a == 0 && firstTransform.b == -1.0 && firstTransform.c == 1.0 && firstTransform.d == 0) {
            firstAssetOrientation_ =  UIImageOrientation.Left;
            isFirstAssetPortrait_ = true;
        }
        if (firstTransform.a == 1.0 && firstTransform.b == 0 && firstTransform.c == 0 && firstTransform.d == 1.0) {
            firstAssetOrientation_ =  UIImageOrientation.Up;
        }
        if (firstTransform.a == -1.0 && firstTransform.b == 0 && firstTransform.c == 0 && firstTransform.d == -1.0) {
            firstAssetOrientation_ = UIImageOrientation.Down;
        }

        firstlayerInstruction.setTransform(asset.preferredTransform, atTime: kCMTimeZero)
        mainInstruction.layerInstructions = [firstlayerInstruction]


        let videoComposition = AVMutableVideoComposition()
        videoComposition.frameDuration = CMTimeMake(1, 30)
        videoComposition.instructions = [mainInstruction]

        var naturalSizeFirst = CGSize()

        if(isFirstAssetPortrait_){
            naturalSizeFirst = CGSizeMake(videoTrack.naturalSize.height, videoTrack.naturalSize.width);
        } else {
            naturalSizeFirst = videoTrack.naturalSize;
        }
        videoComposition.renderSize = naturalSizeFirst
        let playerItem = AVPlayerItem(asset: composition)
        playerItem.videoComposition = videoComposition
        player = AVPlayer(playerItem: playerItem)
        let playerLayer = AVPlayerLayer(player: player)
        print(videoPreview.frame)
        print(videoPreview.bounds)
        playerLayer.frame = self.videoPreview.bounds

        player.play()
        self.videoPreview.layer.addSublayer(playerLayer)



    }

Any suggestions?

like image 730
Roi Mulia Avatar asked Feb 24 '16 14:02

Roi Mulia


2 Answers

You should register for a notification for when the status bar changes orientation, like so:

    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("statusBarOrientationChange:"), name: UIApplicationDidChangeStatusBarOrientationNotification, object: nil)

After that, a switch statement for this would read like so, for editing the dimensions of your AVLayer:

    switch (UIApplication.sharedApplication().statusBarOrientation){
        case .Unknown :
        case .PortraitUpsideDown :
        case .Portrait
        case .LandscapeLeft :
        case .LandscapeRight :
    }

When you get to the right orientation, you will need to apply a CGAffineTransform like so:

asset.transform = CGAffineTransformMake(M_PI * (180) / 180.0)

Hope this is helpful!

like image 81
dokun1 Avatar answered Sep 23 '22 01:09

dokun1


If the issue is with rotating the iPhone in the entire app: Make sure that your app has the correct supported interface orientations in your Info.plist file. Pop into Info.plist, and check the bottom two arrays (Supported Interface Orientations and Supported Interface Orientations (iPad). Ensure they both have all four orientations added. If they do not, mouse over Supported Interface Orientations, press the drop-down arrow, and press the + sign that appears over "Supported Interface Orientations" and add any missing orientations. Do the same to the ""Supported Interface Orientations (iPad)" array.

adding supported interface orientations in Info.Plist

If this does not work, it could be an issue with just the video. Check out the question and accepted answer here: How to fix video orientation issue in iOS. And here's a great way to convert objective-c to swift: https://objectivec2swift.com/#/converter/code.

If your app does not rotate, and you want the video only to rotate:

Put this in your views you would like to lock in portrait mode:

override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
 return UIInterfaceOrientationMask.Portrait
}

Then, in your video view:

override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
 return UIInterfaceOrientationMask.All
}

For good measure - you may want this on both views as well:

override func shouldAutorotate() -> Bool {
 return true
}

Source: how to lock portrait orientation for only main view using swift.

like image 30
owlswipe Avatar answered Sep 21 '22 01:09

owlswipe