How to display AVPictureInPictureController? - ios

I'm trying to play video using AVPictureInPictureController which was introduced recently in IOS9, using this code :
AVPlayer *_AVPlayer = [AVPlayer playerWithURL:url];
AVPlayerLayer *_layer = [AVPlayerLayer playerLayerWithPlayer:_AVPlayer];
_layer.frame = [[UIApplication sharedApplication] delegate].window.bounds;
AVPictureInPictureController *_AVPictureInPictureController = [[AVPictureInPictureController alloc] initWithPlayerLayer:_layer];
_AVPictureInPictureController.delegate = self;
But how can I display the _AVPictureInPictureController in the screen??
I tried
[self presentViewController:_AVPictureInPictureController animated:YES completion:nil];
and
[self presentMoviePlayerViewControllerAnimated:_AVPictureInPictureController];
But it didn't work ):
Also I tried
[self.view.layer addSublayer: layer];
But i shows only AVPlayer on the screen without buttons or controls ..
I used to work with MPMoviePlayerViewController but as it is formally deprecated in iOS 9, I can't use it any more ..
So could You help me to display the _AVPictureInPictureController !!
Thanks in advance

As i checking the documentation about AVPictureInPictureController and also Apple sample code in Swift about AVPictureInPictureController. there is not player. in doc you need to create a Button. and that you need to check for the current video is sported AVPictureInPictureController or not like following.
Fist you need to set up AVAudioSessionCategoryPlayback. you need to do the Xcode Capabilities view for your project, select Audio and AirPlay in the Background Modes section.
In to you app delegate you need to set following code:
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
[[AVAudioSession sharedInstance] setActive: YES error: nil];
Now You need to do code for playing video using AVPlayer using following code:
- (void)viewDidLoad {
[super viewDidLoad];
NSString *path = [[NSBundle mainBundle] pathForResource:#"samplemovie" ofType:#"mov"];
NSURL *url = [NSURL fileURLWithPath:path];
self.AVPlayer = [AVPlayer playerWithURL:url];
self.layer = [AVPlayerLayer playerLayerWithPlayer:_AVPlayer];
//_layer.frame = [[UIApplication sharedApplication] delegate].window.bounds;
[self.layer setFrame:CGRectMake(0, 0, self.view.frame.size.width-100, self.view.frame.size.height-72)];
[self.layer setVideoGravity:AVLayerVideoGravityResize];
[self.view.layer addSublayer:_layer];
[_AVPlayer play];
[self setupSuport]; //Here you need to check that `AVPictureInPictureController` is supported or not with another method
}
-(void)setupSuport
{
if([AVPictureInPictureController isPictureInPictureSupported])
{
_AVPictureInPictureController = [[AVPictureInPictureController alloc] initWithPlayerLayer:_layer];
_AVPictureInPictureController.delegate = self;
}
else
{
// not supported PIP start button desable here
}
}
Here is The button toggle code for PIP if supported:
-(IBAction)actionPIPStart:(UIButton*)sender
{
if (_AVPictureInPictureController.pictureInPictureActive) {
[_AVPictureInPictureController stopPictureInPicture];
}
else {
[_AVPictureInPictureController startPictureInPicture];
}
}
You can get now check with its delegate:
- (void)pictureInPictureController:(AVPictureInPictureController *)pictureInPictureController restoreUserInterfaceForPictureInPictureStopWithCompletionHandler:(void (^)(BOOL restored))completionHandler;
- (void)pictureInPictureControllerDidStopPictureInPicture:(AVPictureInPictureController *)pictureInPictureController;
- (void)pictureInPictureControllerDidStartPictureInPicture:(AVPictureInPictureController *)pictureInPictureController;
- (void)pictureInPictureControllerWillStopPictureInPicture:(AVPictureInPictureController *)pictureInPictureController;
- (void)pictureInPictureController:(AVPictureInPictureController *)pictureInPictureController failedToStartPictureInPictureWithError:(NSError *)error;
- (void)pictureInPictureControllerWillStartPictureInPicture:(AVPictureInPictureController *)pictureInPictureController;
NOTE: Above code is just for sample and might be your video screen not be full fill in screen of device.
Hope that information helps to you and might be your issue goign to be solve for more deep read apple doc. AVPictureInPictureController

Just use AVPlayerViewController instread, for details please check https://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/AdoptingMultitaskingOniPad/QuickStartForPictureInPicture.html

Related

Xcode Objective-C IOS - How to play two videos next to each other?

I want to play two videos next to each other.
When building Mac apps I did this by using a AVPlayer object.
It is a view that you could place inside of your ViewController.
But when I tried to find the AVPlayer object in the object library in an IOS project it didn't show up. Only the AVKit Player View Controller did.
But the AVKit Player View Controller always plays videos full screen in a separate ViewController. I have searched the internet to find a way to display two videos next to each other but so far, I have not found anything useful.
So my question is: Is there any way that I can display two videos next to each other in an IOS application?
// ViewController.h
#import AVFoundation;
#import AVKit;
#property(nonatomic, readonly) AVPlayerItem *currentItem;
// ViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
i=0;
[self videoPlay:[_passdataArr valueForKey:#"videoUrl"]];
}
-(void)videoPlay:(NSArray*)links
{
NSLog(#"1");
//create an AVPlayer
_detailView.hidden=YES;
// NSMutableArray *videolinksArr=[[NSMutableArray alloc] init];
// videolinksArr=_videoLinkArr;
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"%#",links]];
// create a player view controller
player = [AVPlayer playerWithURL:url];
AVPlayerViewController *controller = [[AVPlayerViewController alloc] init];
[self addChildViewController:controller];
[self.view addSubview:controller.view];
controller.view.frame = self.bgimg.frame;
controller.player = player;
controller.showsPlaybackControls = YES;
player.closedCaptionDisplayEnabled = NO;
[player pause];
[player play];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(AllVideoPlay:) name:AVPlayerItemDidPlayToEndTimeNotification object:_currentItem];
}
-(void)AllVideoPlay:(NSNotification*)aNotification
{
NSLog(#"2");
NSArray *temp = _videoLinkArr[i];
[self videoPlay:temp];
i++;
}
But the AVKit Player View Controller always plays videos full screen in a separate ViewController
That's false. If you want the movie view to appear as a subview, make the AVPlayerViewController a child view controller. Start with the Container View Controller in the storyboard and make an Embed segue to an AVPlayerViewController.
Or, you could use AVPlayer without an AVPlayerViewController (in code).
AVPlayer has been available on iOS since iOS 4. AVPlayer is a controller object that manages the playback of media assets with no UI elements directly tied to it, which is why it is not located in the IB object library. Rather you can build your own UI using AVPlayerLayer our use Apple's standard AVPlayerViewController, which includes default controls and standard playback behavior. The fastest way to get two videos playing side-by-side is to embed two instances of AVPlayerViewController inside another view controller. If you are using storyboards your code could be as short as:
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.destinationViewController isKindOfClass:[AVPlayerViewController class]] && [segue.identifier isEqualToString:#"First Player"])
{
AVPlayerViewController *avPlayerViewController = (AVPlayerViewController *)segue.destinationViewController;
avPlayerViewController.player = [AVPlayer playerWithURL: [NSURL URLWithString:#"http://devstreaming.apple.com/videos/wwdc/2016/703rx8zlfedjfom6l93/703/hls_vod_mvp.m3u8"]];
[avPlayerViewController.player play];
} else if ([segue.destinationViewController isKindOfClass:[AVPlayerViewController class]] && [segue.identifier isEqualToString:#"Second Player"])
{
AVPlayerViewController *avPlayerViewController = (AVPlayerViewController *)segue.destinationViewController;
avPlayerViewController.player = [AVPlayer playerWithURL: [NSURL URLWithString:#"http://devstreaming.apple.com/videos/wwdc/2016/703rx8zlfedjfom6l93/704/hls_vod_mvp.m3u8"]];
[avPlayerViewController.player play];
}
}
#end
Or something similar. Where most of the work is done by two container views and embed segues to two AVPlayerViewControllers If you are looking to have custom video UI, you can look at Apple's PIP sample code where they show how you can use key value observing to a video player with custom UI.

Why does my audio play before the Sprite Kit scene transition?

In this code, Audio is a class where all things concerning AVAudioPlayer are handled. Currently there is some music playing. I want to have this fade out completely in 1 second and then play another song. Simultaneously, I want a new scene to appear. So I want the new song to start right as the transition (also lasting 1 second) ends. However, I find myself always waiting for the music to stop, before the scene transition starts. I've tried many ways, with and without selectors, with and without the various sleep functions, but without any luck. I've also tried to use stopMusic instead of transitionMusic and then use playMusic: in the new scene, but I always find myself waiting for stopMusic to finish before the transition starts.
Here's a part of the first scene, which is run if a certain button on the screen is pressed:
Audio *musicPlayer = [[Audio alloc] init];
NewScene *newScene = [NewScene sceneWithSize:self.size];
SKTransition *reveal = [SKTransition pushWithDirection:SKTransitionDirectionLeft duration:1.0];
reveal.pausesOutgoingScene = NO;
reveal.pausesIncomingScene = NO;
[self.view presentScene:newScene transition:reveal];
[musicPlayer transitionMusic:#"NewSong"];
The method transitionMusic: is as follows:
-(void)transitionMusic:(NSString *)fileName {
[self performSelectorOnMainThread:#selector(stopMusic) withObject:nil waitUntilDone:YES];
[self playMusic:fileName];
}
And stopMusic and playMusic: are:
-(void)stopMusic {
while(BGM.volume > 0.05) {
[BGM setVolume:(BGM.volume - 0.05)];
[NSThread sleepForTimeInterval:0.05];
}
[BGM stop];
}
-(void)playMusic:(NSString *)fileName {
NSURL * backgroundMusicURL = [[NSBundle mainBundle] URLForResource:[NSString stringWithFormat:#"%#",fileName] withExtension:#"caf"];
BGM = [[AVAudioPlayer alloc] initWithContentsOfURL:backgroundMusicURL error:nil];
[BGM setNumberOfLoops:-1];
[BGM setVolume:1.0];
[BGM prepareToPlay];
[BGM play];
}
Also, BGM is a static audioplayer declared in Audio.h. Can anyone point out what I'm doing wrong?
Your musicPlayer player object is dependent on your old scene. You need to create a singleton to handle your transition music independently from one scene to another.
BoxesOfBabies.com has a good tutorial on how to set up a singleton and use it to Control Music Across Multiple SKScene.
EDIT:
In your SKScene:
#import "MySingleton"
#implementation MainScene
{
MySingleton *_mySingleton;
}
In your init method:
_mySingleton = [MySingleton sharedInstance];
To start playing audio in any of your scenes:
[_mySingleton startPlayingSong1];
or
[_mySingleton startPlayingSong2];
whatever methods you have in your singleton.

Play video in fullscreen while click playbutton

I have video play play. I'm displaying the video in center of the view adjusting of CGRectMake. But when i click the play button i need to play video in full screen mode automatically without pressing maximize icon. Is it possible?
MPMoviePlayerController *moviePlayerController = [[MPMoviePlayerController alloc] initWithContentURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"solar" ofType:#"mp4"]]];
[[moviePlayerController view] setFrame:CGRectMake(172, 210, 680, 400)];
[moviePlayerController setShouldAutoplay:NO];
[moviePlayerController setControlStyle:MPMovieControlStyleEmbedded];
[[moviePlayerController backgroundView] setBackgroundColor:[UIColor clearColor]];
[moviePlayerController prepareToPlay];
[self.view addSubview:moviePlayerController.view];
Set MoviePlayer to FullScreen by below method
mpviewController.moviePlayer.controlStyle = MPMovieControlStyleFullscreen;
[self presentModalViewController:mpviewController animated:NO];
This will embed your video to your iOS app:
Add MediaPlayer.framework
Add your video to the root of your project
In your .h file add the following
#property(nonatomic, strong) MPMoviePlayerViewController *moviePlayer; - Put this under #interface ViewController :UIViewController;
in your .m file, add the following
#synthesize moviePlayer; -Put this under #implementation ViewController
NSString *videoPath = [[NSBundle mainBundle] pathForResource:#"your video name" ofType:#"mp4"];
NSURL *videoURL = [NSURL fileURLWithPath:videoPath];
moviePlayer = [[MPMoviePlayerViewController alloc] initWithContentURL:videoURL];
[self presentMoviePlayerViewControllerAnimated:moviePlayer];
First try to use add observer pattern to know when movie player begins
to play at that time switch it to full screen mode. I am giving you
the link just check it. It may help you . In this link the observer
pattern is used for checking whether the player is enter on fullscreen
and in selector method what he wants to do he did. So u can also use
same methodology and instead of checking for fullscreen u should check
for play begin and on selector method set it to full screen..
MPMoviePlayerController stops working in full screen mode // portrait orientation // iOS 7

MPMoviePlayerController shows blank screen or crashes app

I have a UIViewController subclass called videoPlayerViewController.
In storyboard I dragged out a UIViewController. I set the class correctly in Storyboard.
I put a button on the screen. When I click the button, it executes the method playVideo:.
- (IBAction)playVideo:(id)sender
{
NSURL *movieURL = [NSURL URLWithString:#"http://www.ebookfrenzy.com/ios_book/movie/movie.mov"];
MPMoviePlayerController *player =
[[MPMoviePlayerController alloc] initWithContentURL: movieURL];
[player prepareToPlay];
[player.view setFrame: self.view.bounds]; // player's frame must match parent's
[self.view addSubview: player.view];
[player play];
}
I get a black screen that does nothing.
This is the simplest version of the code I've had in this method over the last 6 hours.
I've tried every StackOverflow answer out there.
I just want to play a video that I stream from the internet.
If I set:
player.movieSourceType = MPMovieSourceTypeStreaming;
the screen reads "loading" for a second, and then crashes.
What exactly am I doing wrong?
I understand there are so many MPMoviePlayerController questions out there, and to just ask a general "How does it work" question seems ludicrous. I've been at this almost 6 hours now and no Google/Stack Overflow/Apple Documentation search has made this work.
I used your provided code but created a MoviePlayerController property named mcp in the header file that I assigned to player to after creating it. That worked for me. The movie loaded and played just fine.
In the .h file:
#property (strong, nonatomic) MPMoviePlayerController *mcp;
In the .m file:
- (IBAction)playVideo:(id)sender
{
NSURL *movieURL = [NSURL URLWithString:#"http://www.ebookfrenzy.com/ios_book/movie/movie.mov"];
MPMoviePlayerController *player = [[MPMoviePlayerController alloc] initWithContentURL: movieURL];
[player prepareToPlay];
[player.view setFrame: self.view.bounds]; // player's frame must match parent's
_mcp = player;
[self.view addSubview: _mcp.view];
[_mcp play];
}

iOS: MPMoviePlayer won't play

Using the code at the bottom of this post I can successfully display a movie. However I need to now use moviePlayer as a property rather than a local variable. So by adding the following in the header file:
#property (retain, nonatomic) MPMoviePlayerController *mPlayer;
...and synthesizing it as:
#synthesize mPlayer = _mPlayer
Here's the original code. This works fine. All I change is the initialisation line where instead of using a local variable I use the property. A
MPMoviePlayerController * mPlayer = [[[MPMoviePlayerController alloc] initWithContentURL:videoURL] autorelease];
mPlayer.shouldAutoplay=YES;
[self.welcomeImage setUserInteractionEnabled:YES];
[mPlayer.view setFrame: self.welcomeImage.bounds]; // player's frame must match parent's
[self.welcomeImage addSubview:mPlayer.view];
mPlayer.scalingMode = MPMovieScalingModeAspectFit;
mPlayer.controlStyle = MPMovieControlStyleEmbedded;
[mPlayer prepareToPlay];
[mPlayer play];
I just get a black box, no controls or video. What am I doing wrong?
Your not using your synthesized property. Change mPlayer to _mPlayer.
_mPlayer = [[[MPMoviePlayerController alloc] initWithContentURL:videoURL] autorelease];
_mPlayer.shouldAutoplay=YES;
[self.welcomeImage setUserInteractionEnabled:YES];
[_mPlayer.view setFrame: self.welcomeImage.bounds]; // player's frame must match parent's
[self.welcomeImage addSubview:_mPlayer.view];
_mPlayer.scalingMode = MPMovieScalingModeAspectFit;
_mPlayer.controlStyle = MPMovieControlStyleEmbedded;
[_mPlayer prepareToPlay];
[mPlayer play];
This should work as long your videoURL is valid.

Resources