Fixed video capture orientation for RTCMTLVideoView webrtc - ios

I have an iOS app that only supports portrait when rotating the device the video captured by the RTCMTLVideoView rotates to landscape orientation, even when the rest of the UI stays in portrait.
So far the only solution that I found is to listen for the UIDeviceOrientationDidChangeNotification notification
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:nil];
and disabling it
- (void)orientationChanged:(NSNotification *)notification{
NSLog(#"orientation changed");
[[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
}
Is there any way to prevent this behaviour and keep it locked to portrait without this ugly workaround?

The problem in my case was that the video captured with the front camera was no mirrored.
I fixed the issue flipping the RTCMTLVideoView
self.myRTCMTLVideoView.transform = CGAffineTransformMakeScale(-1.0, 1.0)

The answer assumes usage of the latest stable M70 branch of WebRTC at the moment, as it's a moving target and API of its internal classes changes frequently.
Looks like RTCMTLVideoView is still work in progress and doesn't handle all scenarios appropriately. It has a rotationOverride property, but no documentation or example on how to use it. There is a similar question on Google Groups, which hasn't yet received attention, I encourage you to participate in discussion there, so WebRTC developers would know about that issue relevancy and made actions to fix it.
In the meantime, I suggest to switch to RTCEAGLVideoView which should work fine in that case.

Related

Detect AirPlay Mirroring in iOS application

I have an iOS app built in XCode with Objective C mainly for iPads.
Basically I want to detect inside my application of AirPlay Mirroring is active, so mainly if the device is mirroring to another screen.
I searched all around stackoverflow but I couldn't find what I needed for this.
Some answers said that I have to use UIScreenDidConnectNotification for this.
The thing is that I have to call a function if the mirroring is active or when mirroring is activated, also when mirroring is stopped. So I think I need a listener for the mirroring changes.
Can you please help me?
I am relatively new to iOS development so please don't get upset if I may not know all things.:)
Some answers I've found :
https://stackoverflow.com/a/30319663/2866662
https://stackoverflow.com/a/22321926/2866662
https://stackoverflow.com/a/9027616/2866662
https://stackoverflow.com/a/10576262/2866662
Thanks!
Here's how you can call any function by subscribing to the notification, you can do it in viewDidLoad or where you find necessary:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(receiveAirPlayNotification:)
name: UIScreenDidConnectNotification
object:nil];
And to receive it:
- (void) receiveAirPlayNotification:(NSNotification *) notification
{
//Do whatever you want here, or call another function
NSLog(#"Received Notification - %#", notification);
[self doMyThing];
}

How can I tell when UIImagePickerController is done switching cameras?

I am encountering an issue where if I try to take a picture with UIImagePickerController immediately after switching the cameraDevice from back to front camera or vice versa I get an error:
UIImagePickerController: ignoring request to take picture; camera is changing modes.
I have tried subscribing to the AVCaptureSession* events from NSNotificationCenter, but none of the capture session ready notifications are fired when the camera device changes. Is there a way to determine that the camera is ready again after switching cameras in UIImagePickerController?
Check out the code below:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(cameraIsReady:)
AVCaptureSessionInterruptionEndedNotification object:nil];
You would use this to kick off the code you want once the cameras are ready.
If you post your code, I can come back and edit in further help for you.

iPad App Crashes on Orientation change

I am developing an iPad app. I allow both landscape and portrait mode. My UI is fine in portrait mode but when I change it to landscape mode, my UI gets messed up. I saw some SO posts related to this and I added following code in initWith... in my UIView.
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(abc)
name:UIDeviceOrientationDidChangeNotification
object:nil];
My UI is working fine in portrait mode after doing this. When I change it to landscape mode, my UI is fine. But after I change it back into portrait mode, my app crashes. I read some posts on SO related to app crashing an got to know about instruments. I enabled zombies and found that a message is being sent to already released object and this message is coming from NSNotificationCenter.
Is there something else that I need to handle apart from registering my device ? Also, is there any way where in I can change the implementation from UIView to UIViewController and implement the methods that UIViewController has regarding device orientation ? Please let me know the steps I need to follow in order to get this done. Thanks!
Where are you registering for the notifications? You need to remove the observer when you are about to change orientations (either in prepForSegue or willAnimateRotationToInterfaceOrientation depending on however you've got your setup) in order prevent messaging a no longer valid object. You also don't want to pile up several notifications if your registering in viewDidAppear/viewWillAppear.
Remove the observer using:
[[NSNotificationCenter defaultCenter] removeObserver:self];//removes all notifications for that object (the way I've used it before)
or if you want to be specific, do something like:
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceOrientationDidChangeNotification object:[UIDevice currentDevice];//remove just that notification
The UIViewController class has several methods that deal with changes in orientation. See the docs for a discussion of those methods.
One method you should look into is viewWillLayoutSubviews. This is a common place to perform manual view layout. This is called anytime the view controller's orientation changes.
Using these methods is much more common than registering for device orientation change notifications. Based on your statements about the crash, a possible issue is that you never remove the observer that you add. For every call to addObserver there must be a corresponding call to removeObserver. Otherwise the observer is called even if it has long gone away. And this results in the crash you describe.

Detecting device rotation when UIImagePicker is presented view

I am using the UIImagePickerController class and my buttons are in the camera overlay.
I would like to adjust the orientation of my camera buttons dynamically depending on device orientation the way Apple's Camera.app does. I understand that UIImagePickerController is portrait mode only and should not be subclassed. Still, I would like to be able to trap and respond to the device rotation viewController events.
Is there any clean way to do this? The viewController which presents the UIImagePickerController no longer responds to events once the picker is presented.
There seem a few related questions on this topic but none that clarify if what I want to do is possible or not. Compounding confusion, there seems to be some differences with UIImagePickerController functionality between iOS versions. I am developing this on iOS6/iPhone4 but would like to be compatible with iOS5.
Here is a clean way to do it, tested on iPhone4s/iOS5.1 and iPhone3G/iOS6.1
I am using Apple's PhotoPicker sample and making a couple of small changes. I expect you can adapt this approach for your project. The basic idea is to use notifications to trigger a method every time we rotate. If that method is in the overlay's view controller, it can carry on manipulating the overlay while the imagePicker is showing.
In OverlayViewController.m add this into initWithNibName
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
NSNotificationCenter* notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter addObserver:self
selector:#selector(didChangeOrientation)
name:#"UIDeviceOrientationDidChangeNotification"
object:nil];
These notifications continue to be sent while the pickerController is showing. So here, in the overlay's view controller, you can continue to play with the interface, for example:
- (void) didChangeOrientation
{
if (UIDeviceOrientationIsPortrait([[UIDevice currentDevice] orientation])) {
self.cancelButton.image =[UIImage imageNamed:#"portait_image.png"];
} else {
self.cancelButton.image =[UIImage imageNamed:#"landscape_image.png"];
}
}
you will need to kill the notification and remove the observer in viewDidUnload:
[[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] removeObserver:self];
Note the way this app is designed: the overlayViewController acts like a wrapper around imagePickerController. So you invoke the imagePicker through the overlayViewController:
[self presentModalViewController:self.overlayViewController.imagePickerController animated:YES];
The overlayViewController acts as the delegate for imagePickerController, and in turn has delegate methods to relay information back to the invoking view controller.
An alternative is not to use UIImagePickerController at all, but to use AVFoundation media capture instead which gives you much more fine-grained control over the picture-taking process, at the expense of (slightly) greater complexity.

iPad OpenGL Screen Rotation Problems (Multitasking bar and Popups not Rotating)

I'm building an application for the iPad using OpenGL and have issues with screen rotation. The application itself works fine and displays correctly in all four orientations, but other elements only partially respond to the device rotation.
OpenGL handles the rotation of the application using transformation matrices. That all works fine. The default images also display at the correct rotation.
The multitask bar, however, is not rotating as it should. It appears on the side that the application was opened in. So if I open the application then double tap the home button it is on the correct side, but after rotating the device it remains on the same side until the application is closed and reopened. When this bar is revealed the OpenGL application rotates to match the bar's position.
Dialogue boxes, such as the 'sign into game center' popup are also not correctly rotated. They seem to appear in the standard portrait orientation.
I'm not sure if there are any other specific details necessary to identify the problem but any suggestions are very much appreciated.
I seem to have put together a solution looking at snippets in some other threads. I think it's fixed the problem.
I have a main class which controls most of my application. It was already registered to receive device rotation notifications like this:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(orientationChanged:) name:#"UIDeviceOrientationDidChangeNotification" object:nil];
I added a few lines to the orientation handler function to manually set the status bar location:
- (void) updateOrientation {
if ([[UIDevice currentDevice] orientation] < 5 && [[UIDevice currentDevice] orientation]>0) {
orientation = [[UIDevice currentDevice] orientation];
[UIApplication sharedApplication].statusBarOrientation = orientation;
}
}
The conditional limits the handler to respond only to landscape and portrait orientations and not face up and face down.
If anybody has a better solution I'd still like to hear it, otherwise, hope this can help someone else.

Resources