resize AVPlayerItem container view based on aspect ratio from video - ios

I have a container UIView called videoView. I add a AVPLayerLayer to that view. I do not know how to resize the videoView to be of the same proportions as the avplayer layer. Using videoGravity does not have the desired effect.
AVPlayerItem* playerItem = [AVPlayerItem playerItemWithURL:path];
_videoPlayer = [[AVPlayer alloc] initWithPlayerItem:playerItem];
AVPlayerLayer *layer = [AVPlayerLayer layer];
[_avplayerLayer setPlayer:_videoPlayer];
[_avplayerLayer setBackgroundColor:[UIColor whiteColor].CGColor];
[_avplayerLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
[_avplayerLayer setFrame:_videoView.bounds];
[_videoView.layer addSublayer:_avplayerLayer];
I am using autolayout, and my layout would accommodate a change in the height of _videoView.

videoGravity will not change the frame of the view, instead it fills the current frame with the video.
i think you should inspect each video's resolution before playing it and adjust videoView's height constraint (which should be an ivar and constrained to videoView's width) multiplier. videoView width should be constrained to the screen width.

Related

the position of the avplayer in a containerView is not what it should be T_T

I'm working on the Avplayer . I've got a containerView for the Avplayer and i set the frame of the Avplayer like this:
CGRect frame = CGRectMake(0, 0, 200, 400);
playerLayer.frame=frame;
[containerView.layer addSublayer:playerLayer];
But the Avplayer is not at the posiotion it should be T_T
i solve it by myself,instead of using the frame i use the playerview
with the playerview ,u can use the storyboard to make the position of the avplayer,and also the size of it.

Inserting an AVPlayerLayer below GLKView Layer

All I am trying to accomplish is to place an AVPlayerLayer behind an active OpenGL layer.
I am using a GLKViewController (with respective GLKView). I load a video with AVPlayer and establish a corresponding AVPlayerLayer. Both my GL Layer and AVPlayerLayer appear, however, regardless of what form of "insert sublayer" I call (above, below, at index, etc.), the GL Layer always appears behind the AVPlayerLayer.
_videoData = playerItem;
_videoPlayer = [[AVPlayer alloc] initWithPlayerItem:_videoData];
_playerLayer = [AVPlayerLayer playerLayerWithPlayer:_videoPlayer];
_playerLayer.frame = CGRectMake(250, 250, 300, 300);
[self.view.layer insertSublayer:_playerLayer below:self.view.layer];
Solved this by inserted a GLKViewController as a child of a UIView with the video player. After much experimentation it appears you cannot place anything (subviews or layers) behind the GL layer when using GLKViewController independently.

Crop Video Into Circle in iOS?

I am trying to crop a video, that has been taken with an iPhone camera and then place it on top of a UIImageView. I have been following this SO Question How to crop a video to a circle in iOS?. And I can now take the video and put it on top of another perviously recorded video. Now I want to have the background be a image and the foreground be the cropped video. My main issue right now is getting video cropped in the part I want cropped. I cannot post all the code here but here is where the github repo is and the class that does the modifying is called CustomVideoCompositor.m https://github.com/mayoff/stackoverflow-28258270-video-in-oval-on-video/tree/master/video. And I am having trouble editing it into the circle I want I want it to be a oval that is in the bottom half and higher than wider.
EDIT
I want to make the cut so that only things in this part of the rounded rectangle would be cropped and available.
If you want only a visual effect of cropped video, without modification of video file, you can simply add a mask to your video layer. I mean CALayer mask property.
You can create circle mask like this: draw black rectangle, then draw transparent circle on it.
You'll need to use AVPlayer as this enables you to play several videos back at once or have your video appear on top of another view. Also, by using AVPlayer and an AVPlayerLayer its easy to then make the video appear circular. (Here's a good tutorial on it to learn more: http://jacopretorius.net/2013/02/playing-video-in-ios.html)
Here's the code (for Objective-C):
In your view controller .h file:
#import <AVFoundation/AVFoundation.h>
Then in viewDidLoad:
[super viewDidLoad];
// Set up the image view first (the imageView is an IBOutlet)
self.imageView.image = [UIImage imageNamed:#"image"];
self.imageView.alpha = 0.2;
NSURL *url = [[NSBundle mainBundle] URLForResource:#"video" withExtension:#"mp4"];
AVPlayer *player = [AVPlayer playerWithURL:url];
CGFloat diameter = MIN(self.view.frame.size.width, self.view.frame.size.height) * 0.8;
AVPlayerLayer *layer = [AVPlayerLayer playerLayerWithPlayer:player];
layer.videoGravity = AVLayerVideoGravityResizeAspectFill;
layer.frame = CGRectMake((self.view.frame.size.width - diameter) / 2,
(self.view.frame.size.height - diameter) / 2,
diameter, diameter);
layer.cornerRadius = diameter / 2;
layer.masksToBounds = YES;
// Put the AVPlayerLayer on top of the image view.
[self.view.layer addSublayer:layer];
[player play];

How to get frame of subview after apply transform on mainView?

I have created mainView objcet of UIView and added one subview on it. I applied transform on mainView for reducing frame size. But frame of subview of mainView was not reduced. How to reduce the size of this subview.
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
CGFloat widthM=1200.0;
CGFloat heightM=1800.0;
UIView *mainView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, widthM, heightM)];
mainView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"te.png"]];
[self.view addSubview:mainView];
CGFloat yourDesiredWidth = 250.0;
CGFloat yourDesiredHeight = yourDesiredWidth *heightM/widthM;
CGAffineTransform scalingTransform;
scalingTransform = CGAffineTransformMakeScale(yourDesiredWidth/mainView.frame.size.width, yourDesiredHeight/mainView.frame.size.height);
mainView.transform = scalingTransform;
mainView.center = self.view.center;
NSLog(#"mainView:%#",mainView);
UIView *subMainView= [[UIView alloc] initWithFrame:CGRectMake(100, 100, 1000, 1200)];
subMainView.backgroundColor = [UIColor redColor];
[mainView addSubview:subMainView];
NSLog(#"subMainView:%#",subMainView);
}
NSlog of these views:
mainView:<UIView: 0x8878490; frame = (35 62.5; 250 375); transform = [0.208333, 0, 0, 0.208333, 0, 0]; layer = <CALayer: 0x8879140>>
subMainView:<UIView: 0x887b8c0; frame = (100 100; 1000 1200); layer = <CALayer: 0x887c160>>
Here the width of mainView is 250, the width of subview is 1000. but when i get the output in simulator, subview is occupied correctly, but it's not cross the mainView. How it is possible? How to get frame of subview with respect mainView frame after transformation?
What you're seeing is expected behavior. The frame of an UIView is relative to its parent, so it doesn't change when you apply a transformation to its superview. While the view will appear 'distorted' too, the frame won't reflect the changes since it's still at exact the same position relative to its parent.
However, I assume you would like to get the frame of the view relative to the topmost UIView. In that case UIKit offers these functions:
– [UIView convertPoint:toView:]
– [UIView convertPoint:fromView:]
– [UIView convertRect:toView:]
– [UIView convertRect:fromView:]
I applied these to your example:
CGRect frame = [[self view] convertRect:[subMainView frame] fromView:mainView];
NSLog(#"subMainView:%#", NSStringFromCGRect(frame));
And this is the output:
subMainView:{{55.8333, 83.3333}, {208.333, 250}}
In addition to s1m0n answer, the beautiful thing about applying a transform matrix to your view, is that you can keep reasoning in terms of its original coordinate system (in your case, you can handle subMainView using the non-transformed coordinate system, which is why, even though subMainView's frame is bigger than mainView's transformed frame, it still doesn't cross the parent view, as it gets automatically transformed). This means that when you have a transformed parent view (for example rotated and scaled) and you want to add a subview in a particular point relative to this parent view, you don't have to first keep track of the previous transformations in order to do so.
If you really are interested in knowing the subview's frame in terms of the transformed coordinate system, it will be enough to apply the same transformation to the subview's rectangle with:
CGRect transformedFrame = CGRectApplyAffineTransform(subMainView.frame, mainView.transform);
If you then NSLog this CGRect, you will obtain:
Transformed frame: {{20.8333, 20.8333}, {208.333, 250}}
Which, I believe, are the values that you were looking for. I hope this answers your question!

CALayer content goes out of bounds - iOS

I am trying to implement camera zoom using CGAffinetransform. Transform is fine, but when I scale it to a bigger size, it goes out of the frame I have assigned to the AVCaptureVideoPreviewLayer. I tried setting masksToBounds property to YES but it didn't help.
Can I contain it within its frame?
Edit:
What I want is that I can specify a specific area for the camera preview layer, if I apply scaling transform to it, (i.e., frame of preview layer gets expanded), the part of the layer outside of the specified area gets clipped.
You should put the layer you are scaling inside of another layer and mask that one instead (the superlayer). The same thing works with views.
I.e. You have two views / layers: clippingView and scalingView where scalingView is the subview of clippingView and clippingView is the view that actually clips to it's bounds.
[clippingView addSubview:scalingView];
clippingView.clipsToBounds = YES;
or using layers
[clippingLayer addSublayer:scalingLayer];
clippingLayer.masksToBounds = YES;
You guys are all partially right I found but I wanted to clarify.
Lets say we added something like AVCaptureVideoPreviewLayer to the view via [self.view.layer addSublayer:previewLayer]
[self clipsToBounds] does NOTHING until you are telling its primary layer to mask to bounds. [self.view.layer masksToBounds];
Just because your view has a frame and so does its layers DOES NOT MEAN IT HAS BOUNDS. If it doesnt have bounds then there is nothing to mask to. So do this self.view.layer.bounds = self.view.frame;
So heres it all together..keep in mind I did this in my own UIView class so I dont need to call self.view.
previewLayer.bounds = self.frame;
self.layer.bounds = self.frame;
self.layer.masksToBounds = YES;
previewLayer.masksToBounds = YES;
[self setBounds:self.frame];
[self clipsToBounds];
clipsToBounds property of the view to which I am adding the layer should have been set to YES.

Resources