iOS Development

ios – Video playback orientation iOS17

Spread the love


Images and the various different apps with video present playback appropriately regardless of the recording digital camera orientation. Is there a easy solution to accomplish the proper rotation for playback?

After numerous digging in stackOverflow and Apple docs I lastly bought the orientation of video playback to work – however it feels too tough for one thing that’s finished on a regular basis.

Right here is my answer – is there a greater approach?

My app is locked to panorama full display screen orientation solely. Following the scheme for video to steel rendering with filters as outlined within the WWDC22 “Show HDR video in EDR with AVFoundation and Steel”, every body of video ought to be transformed right into a CIImage for enter into CIFilters.

There are two steps:

  1. Decide the orientation of the recording digital camera
  2. Apply a corrective rotation for the playback

StackOverFlow has a number of solutions for orientation of an AVAsset – the perfect reply appears to be from Easy methods to detect if a video file was recorded in portrait orientation, or panorama in iOS the place dhallman supplies a perform to reply each UIInterfaceOrientation and AVCaptureDevicePosition. Extract AVAsset Orientation and Digital camera Place

The necessity for an app perform to find out UIInterfaceOrientation and AVCaptureDevicePosition appears mistaken – Is that this hidden within the metadata someplace? One of many different points that hobbled me is the iOS16 change to make loading of the videoTracks and the preferredTransform an async name. So on this extension of AVAsset a perform

func videoOrientation() async -> PGLDevicePosition {
    var orientation: UIInterfaceOrientation = .unknown
    var system: AVCaptureDevice.Place = .unspecified
    var myVideoTracks:[AVAssetTrack]?
    var t: CGAffineTransform = CGAffineTransformIdentity

    do {
         myVideoTracks =  attempt await loadTracks(withMediaType: .video)
    }
    catch {
        /// return init values of .unknown and .unspecificed
            return PGLDevicePosition(orientation: orientation, system: system)
        }
    if let videoTrack = myVideoTracks?.first {
        do {
             t = attempt await videoTrack.load(.preferredTransform)
        }
        catch {
            /// return init values of .unknown and .unspecificed
            return PGLDevicePosition(orientation: orientation, system: system)
        }

The async perform must wrapped right into a job equivalent to this

    func getVideoPreferredTransform(callBack: @escaping (PGLDevicePosition) -> Void ) {

    Activity {
        let devicePosition = await avPlayerItem.asset.videoOrientation()
        callBack(devicePosition)
    }
}

Now realizing the system .entrance or .again and orientation a change assertion is decide the proper CGImagePropertyOrientation for the AffineTransform for the CIImage. The change assertion is

var end result = CGImagePropertyOrientation.up
        // default
    change (imageOrientation.orientation, imageOrientation.system) {
        case (.unknown,.unspecified) :
            end result = CGImagePropertyOrientation.up
            
        case (.portrait, .entrance) :
            end result = CGImagePropertyOrientation.proper
        case (.portraitUpsideDown, .entrance):
            end result = CGImagePropertyOrientation.proper
        case (.landscapeLeft, .entrance) :
            end result = CGImagePropertyOrientation.up
        case (.landscapeRight, .entrance) :
            end result = CGImagePropertyOrientation.up

        case (.portrait, .again) :
            end result = CGImagePropertyOrientation.proper
        case (.portraitUpsideDown, .again):
            end result = CGImagePropertyOrientation.left
        case (.landscapeLeft, .again) :
            end result = CGImagePropertyOrientation.down
        case (.landscapeRight, .again) :
            end result = CGImagePropertyOrientation.up

        default:
            return end result // default .up
    }
    return end result

Lastly, the correction to the ciImage will be made. First the CIImage is transformed from the cvPixelBuffer as prompt within the WWDC22 workshop. Then rework with the proper CGImagePropertyOrientation is utilized to the CIImage.

  let sourceFrame = CIImage(cvPixelBuffer: buffer)

  let neededTransform = sourceFrame.orientationTransform(for: videoPropertyOrientation)
   videoCIFrame = sourceFrame.remodeled(by: neededTransform)

And we’re finished… Appears approach too difficult.. Is not there a less complicated approach???

Leave a Reply

Your email address will not be published. Required fields are marked *