Initial rotation of my local video

Hi there,

I’m using an iPhone in .portrait mode. When subscribing to my video and not handling any orientation then its initially show as rotated to .landscapeLeft. I assume this is the internal default orientation.

Is this the expected behaviour or am I doing something wrong?

Of course I’m observing orientation change, and call rotateMyVideo accordingly, which works fine. But I’m not sure when to initially set the orientation before any orientation change happens.

Before joining and onSessionJoin callback won’t update the video. And onUserVideoStatusChanged does work until I stop/start my video, then it’s in landscape mode again.

Should rotateMyVideo be called every time I subscribe to my video? Or is there a way to keep the orientation I’ve set?

Unfortunately I’ve encountered a related issue of the late rotation of the local video.

A user subscribes to another participant’s video onUserJoin. Then for a short time the landscape video shows up, then the correctly rotated portrait one.

Beside that the aspect ratio is not recomputed, so the video on the receiver’ side shows up as letterbox (black bars). The video was subscribed with .panAndScan.

After toggling the video on the sender’s side the video shows up on the receiver correctly in portrait mode with the correct aspect.

I am grateful for any advice. Thanks! :pray:

Hey @blindgaenger.

Thanks for using the dev forum!

At what point in your ViewControllers lifecycle are you handling the SDK views?

Thanks!
Michael

Hi Michael,

That’s the right but a tough question as I’m using the SDK in a React Native module. So there is no separate ViewController and the UIView encapsulates all the logic.

The UIView is subscribed to the sharedInstance’s delegate events. These are the callbacks I’m using.

func onSessionJoin() {
  // subscribe in onUserVideoStatusChanged as video could be off or unavailable
}

func onSessionLeave() {
  if let user = self.user {
    unsubscribeVideo(user: user)
  }
}

func onUserVideoStatusChanged() {
  if let myself = observable.getMySelf(),
    let isVideoEnabled = myself.videoStatus()?.on {
    if isVideoEnabled {
      updateVideoOrientation()
      subscribeVideo(user: myself)
    } else {
      unsubscribeVideo(user: myself)
    }
  }
}

Of course the view is instantiated before joining a session. I’m planing to show the local video preview in the very same view. But I need to know when it’s safe to switch from preview to live video.

Hey @blindgaenger,

I see. In a native implementation of the video SDK, the rotation can be incorrect if the view is set up when the ViewController is loaded instead of when the ViewController appears. I am not to sure how reactnative manages this pattern but if it is possible to set up the view later that may help.

It should be safe after onSessionJoin has been called.

Thanks!
Michael

Hi @Michael_Condon ,

Thanks for your reply!

I had another look at the ZoomInstantSample application on how the video subscription was implemented. There is a deadline of 200 ms on the main thread used between creating+subscribing the view and adding it as subview. I’m not 100% convinced that’s the proper way, but at least the video shows up consistently on my local device.

Using the very same code the remote device is not always picking up the video, though. And the rotation is in landscape mode again if I toggle the video, although the initial rotation works.

I think I’ve missed an important aspect of the whole flow. Is there a stripped down example on how and when the views should be subscribed, rotated, released?

Hey @blindgaenger,

Yes, I would put this code in viewDidAppear:

if let usersVideoCanvas = user.getVideoCanvas() {
    // Set video aspect.
    let videoAspect = ZoomInstantSDKVideoAspect.panAndScan

    // Subscribe User's videoCanvas to render their video stream.
    usersVideoCanvas.subscribe(with: view, andAspectMode: videoAspect)
}

Thanks!
Michael

Hi @Michael_Condon ,

Thanks for your answer!

After some research seems there is no way to hook into viewDidAppear without a view controller. React Native’s approach is that the views are solely controlled from JavaScript, so I refactored my current approach and gave the control back to JS. Downside are a couple of milliseconds delay as the events have to pass the React Native bridge.

So the first problem with the local view got solved. But the remote view still uses the aspect ratio from before the rotation, although it shows up correctly. After toggling the video the aspect ratio gets fixed (recalculated?).

Hope you’ve got any ideas on that. Further is there a way to inspect the “internal” dimensions of a view for debugging?

Cheers,
Bernd

Hey @blindgaenger,

I would try and call setVideoAspect again for the remote view. As to where, I am not entirely sure since I do not know how reactnative handles the views lifecycle.

Thanks!
Michael

Hi @Michael_Condon ,

I really appreciate you sticking with this topic. :bowing_man:

The local video works correctly now with the following code in the UIView. Even without calling rotateMyVideo upfront.

override func layoutSubviews() {
  self.frame = self.frame
  self.bounds = self.bounds
}

Unfortunately, I have not been able to solve the video aspect for remote users yet. It’s clearly a problem of when React Native sets the view’s frame. I will try to figure this out.

Thanks again!

Cheers,
Bernd

Hey @blindgaenger,

You are very welcome :slight_smile:
Please let me know what you find.

Thanks!
Michael