AVCaptureVideoPreviewLayer 没有填满屏幕
Posted
技术标签:
【中文标题】AVCaptureVideoPreviewLayer 没有填满屏幕【英文标题】:AVCaptureVideoPreviewLayer not filling screen 【发布时间】:2013-04-26 09:59:39 【问题描述】:我阅读了大约 100 万条关于如何使 VideoPreviewLayer 填充 iPhone 的整个屏幕的帖子,但没有任何效果......也许你可以帮助我,因为我真的被卡住了。
这是我的预览层初始化:
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
// Choosing bigger preset for bigger screen.
_sessionPreset = AVCaptureSessionPreset1280x720;
else
_sessionPreset = AVCaptureSessionPresetHigh;
[self setupAVCapture];
AVCaptureSession *captureSession = _session;
AVCaptureVideoPreviewLayer *previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:captureSession];
UIView *aView = self.view;
previewLayer.frame = aView.bounds;
previewLayer.connection.videoOrientation = AVCaptureVideoOrientationLandscapeRight;
[aView.layer addSublayer:previewLayer];
这就是我的 setupAvCapture 方法:
//-- Setup Capture Session.
_session = [[AVCaptureSession alloc] init];
[_session beginConfiguration];
//-- Set preset session size.
[_session setSessionPreset:_sessionPreset];
//-- Creata a video device and input from that Device. Add the input to the capture session.
AVCaptureDevice * videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
if(videoDevice == nil)
assert(0);
//-- Add the device to the session.
NSError *error;
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:videoDevice error:&error];
if(error)
assert(0);
[_session addInput:input];
//-- Create the output for the capture session.
AVCaptureVideoDataOutput * dataOutput = [[AVCaptureVideoDataOutput alloc] init];
[dataOutput setAlwaysDiscardsLateVideoFrames:YES]; // Probably want to set this to NO when recording
//-- Set to YUV420.
[dataOutput setVideoSettings:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:kCVPixelFormatType_420YpCbCr8BiPlanarFullRange]
forKey:(id)kCVPixelBufferPixelFormatTypeKey]]; // Necessary for manual preview
// Set dispatch to be on the main thread so OpenGL can do things with the data
[dataOutput setSampleBufferDelegate:self queue:dispatch_get_main_queue()];
[_session addOutput:dataOutput];
[_session commitConfiguration];
[_session startRunning];
我已经尝试使用不同的 AVCaptureSessionPresets 和 ResizeFit 选项。但它总是看起来像这样:
http://imageshack.us/photo/my-images/707/img0013g.png/
或者如果我使用 previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;如果我记录图层的大小,则会返回正确的全屏大小。
http://imageshack.us/photo/my-images/194/img0014k.png/
【问题讨论】:
如果我设置 previewLayer.frame = CGRectMake(0, 0, 1280, 720);手动它正在工作......任何人都可以解释一下。似乎宽度/高度被翻转(纵向),但方向实际上是横向。所以我可以解决实现 _screenWidth = [UIScreen mainScreen].bounds.size.width; _screenHeight = [UIScreen mainScreen].bounds.size.height;如果(_screenHeight > _screenWidth) _screenWidth = _screenHeight; _screenHeight = [UIScreen mainScreen].bounds.size.width; 【参考方案1】:尝试:
AVCaptureVideoPreviewLayer *captureVideoPreviewLayer = [AVCaptureVideoPreviewLayer layerWithSession: self.session];
[captureVideoPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
快速更新
let previewLayer = AVCaptureVideoPreviewLayer(session: session)
previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
Swift 4.0 更新
let previewLayer = AVCaptureVideoPreviewLayer(session: session)
previewLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
【讨论】:
这在第一次加载时有效。但是在轮换时重新应用这似乎并没有必要。 也许你应该停止相机预览的旋转。在要放置的按钮的预览上创建一个透明视图,并使其旋转。我认为旋转相机预览有点有趣,上面是正确的答案。 :)【参考方案2】:如果有人遇到这个问题,你只需要抓住屏幕的边界
previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
previewLayer.frame = UIScreen.main.bounds
previewLayer.videoGravity = .resizeAspectFill
camPreview.layer.addSublayer(previewLayer)
【讨论】:
【参考方案3】: videoPreviewLayer = AVCaptureVideoPreviewLayer(session: session)
DispatchQueue.main.async
self.videoPreviewLayer?.frame = self.captureImageView.bounds
cropImageRect = captureImageView.frame
videoPreviewLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill
videoPreviewLayer?.connection?.videoOrientation = AVCaptureVideoOrientation.portrait
captureImageView.layer.addSublayer(videoPreviewLayer!)
session!.startRunning()
这对我有用。我面临的问题是,我将以下行放在主线程之外。它造成了我认为的问题。
self.videoPreviewLayer?.frame = self.captureImageView.bounds
【讨论】:
【参考方案4】:Swift 5 和 Xcode13
这对我有用
创建 AVCapturePreviewLayer
class ViewController: UIViewController
let previewLayer = AVCapturePreviewLayer()
将 PreviewLayer 添加到视图中
override func viewDidLoad()
super.viewDidLoad()
// Adds Element to the View Layer
view.layer.addSublayer(previewLayer)
使 PreviewLayer 成为 View 的完整边界
override func viewDidLayoutSubviews()
super.viewDidLayoutSubviews()
previewLayer.frame = view.bounds
【讨论】:
以上是关于AVCaptureVideoPreviewLayer 没有填满屏幕的主要内容,如果未能解决你的问题,请参考以下文章