知道AVCaptureSession的会话预设的解决方案

时间:2011-10-17 07:06:27

标签: ios avfoundation core-video

我正在iOS中访问相机并使用会话预设:

captureSession.sessionPreset = AVCaptureSessionPresetMedium;

非常标准的东西。但是,我想提前知道由于这个预设而我将获得的视频分辨率(特别是因为取决于设备它会有所不同)。我知道有在线表格可以查看(例如:http://cmgresearch.blogspot.com/2010/10/augmented-reality-on-iphone-with-ios40.html)。但是我希望能够以编程方式获得这个,这样我就不仅仅依赖于幻数了。

所以,像这样(理论上):

[captureSession resolutionForPreset:AVCaptureSessionPresetMedium];

可能返回{宽度:360,高度:480}的CGSize。我还没有找到任何这样的API,到目前为止我不得不求助于等待获取我的第一个捕获的图像然后查询它(由于我的程序流程中的其他原因并不好)。

8 个答案:

答案 0 :(得分:22)

我不是AVFoundation专业人士,但我认为要走的路是:

captureSession.sessionPreset = AVCaptureSessionPresetMedium;
AVCaptureInput *input = [captureSession.inputs objectAtIndex:0]; // maybe search the input in array
AVCaptureInputPort *port = [input.ports objectAtIndex:0];
CMFormatDescriptionRef formatDescription = port.formatDescription;
CMVideoDimensions dimensions = CMVideoFormatDescriptionGetDimensions(formatDescription);

我不确定最后一步,我自己也没试过。刚刚在文档中发现并认为它应该有用。

在Xcode中搜索CMVideoDimensions,您将找到RosyWriter示例项目。看看那段代码(我现在没有时间去做)。

答案 1 :(得分:7)

仅供参考,我在此附上Apple的正式回复。


这是Bug ID#13201137的后续行动。

Engineering已根据以下信息确定此问题的行为符合预期:

包含的代码有几个问题:

1)AVCaptureSession没有输入。 2)AVCaptureSession没有输出。

如果没有至少一个输入(使用[AVCaptureSession addInput:]添加到会话中)和兼容输出(使用[AVCaptureSession addOutput:]添加),则不会有活动连接,因此会话实际上不会运行在输入设备中。它不需要 - 没有输出可以提供任何相机数据。

3)JAViewController类假定[AVCaptureSession startRunning]返回后视频端口的-formatDescription属性将为非零值。

一旦startRunning返回,无法保证使用新的相机格式更新格式说明。 -startRunning启动摄像机并在摄像机完全启动并运行时返回,但不等待视频帧主动流过捕获管道,这时格式描述将被更新。

你只是查询太快了。如果你等了几毫秒,它就会在那里。但正确的方法是监听AVCaptureInputPortFormatDescriptionDidChangeNotification。

4)你的JAViewController类在retrieveCameraInfo中创建一个PVCameraInfo对象并向它询问一个问题,然后让它超出范围,在那里它被释放并解除分配。

因此,会话的运行时间不足以满足您的维度请求。你太快停了相机。

我们认为这个问题已经结束。如果您对此问题有任何疑问或疑虑,请直接更新您的报告(http://bugreport.apple.com)。

感谢您抽出宝贵时间将此问题通知我们。

最诚挚的问候,

开发人员错误报告小组 Apple全球开发者关系

答案 2 :(得分:5)

您可以在捕获开始之前以编程方式从activeFormat获取分辨率,但不是在添加输入和输出之前:https://developer.apple.com/library/ios/documentation/AVFoundation/Reference/AVCaptureDevice_Class/index.html#//apple_ref/occ/instp/AVCaptureDevice/activeFormat

private func getCaptureResolution() -> CGSize {
    // Define default resolution
    var resolution = CGSize(width: 0, height: 0)

    // Get cur video device
    let curVideoDevice = useBackCamera ? backCameraDevice : frontCameraDevice

    // Set if video portrait orientation
    let portraitOrientation = orientation == .Portrait || orientation == .PortraitUpsideDown

    // Get video dimensions
    if let formatDescription = curVideoDevice?.activeFormat.formatDescription {
        let dimensions = CMVideoFormatDescriptionGetDimensions(formatDescription)
        resolution = CGSize(width: CGFloat(dimensions.width), height: CGFloat(dimensions.height))
        if (portraitOrientation) {
            resolution = CGSize(width: resolution.height, height: resolution.width)
        }
    }

    // Return resolution
    return resolution
}

答案 3 :(得分:3)

您可以为每个iPhone型号提供所有可预设分辨率的列表,并检查该应用运行的设备型号? - 使用这样的东西......

[[UIDevice currentDevice] platformType]   // ex: UIDevice4GiPhone
[[UIDevice currentDevice] platformString] // ex: @"iPhone 4G"

但是,您必须更新每个较新设备型号的列表。希望这会有所帮助:)

答案 4 :(得分:2)

According to Apple,没有API。很糟糕,我遇到了同样的问题。

答案 5 :(得分:0)

如果预设为.photo,则返回尺寸为静态照片尺寸,而不是预览视频尺寸

如果预设不是.photo,则返回尺寸为视频尺寸,而不是捕获的照片尺寸。

if self.session.sessionPreset != .photo {
    // return video size, not captured photo size
    let format = videoDevice.activeFormat
    let formatDescription = format.formatDescription
    let dimensions = CMVideoFormatDescriptionGetDimensions(formatDescription) 
} else {
    // other way to get video size
}

@Christian Beer的答案是指定预设的好方法。 我的方式适合主动预设。

答案 6 :(得分:0)

执行所需操作(获取已知视频或图像格式)的最佳方法是设置捕获设备的格式。

首先找到您要使用的捕获设备:

       if #available(iOS 10.0, *) {
        captureDevice = defaultCamera()
    } else {
        let devices = AVCaptureDevice.devices()
        // Loop through all the capture devices on this phone
        for device in devices {
            // Make sure this particular device supports video
            if ((device as AnyObject).hasMediaType(AVMediaType.video)) {
                // Finally check the position and confirm we've got the back camera
                if((device as AnyObject).position == AVCaptureDevice.Position.back) {
                    captureDevice = device as AVCaptureDevice
                }
            }
        }
    }
    self.autoLevelWindowCenter = ALCWindow.frame
    if captureDevice != nil && currentUser != nil {
        beginSession()
    }
}




    func defaultCamera() -> AVCaptureDevice? {
    if #available(iOS 10.0, *) { // only use the wide angle camera never dual camera
        if let device = AVCaptureDevice.default(AVCaptureDevice.DeviceType.builtInWideAngleCamera,
                                                             for: AVMediaType.video,
                                                             position: .back) {
            return device
        } else {
            return nil
        }
    } else {
        return nil
    }
}

然后找到该设备可以使用的格式:

        let options = captureDevice!.formats
    var supportable = options.first as! AVCaptureDevice.Format
    for format in options {
        let testFormat = format 
        let description = testFormat.description
        if (description.contains("60 fps") && description.contains("1280x 720")){
            supportable = testFormat
        }
    }

您可以对格式进行更复杂的解析,但是您可能并不在意。

然后将设备设置为该格式:

do {
    try captureDevice?.lockForConfiguration()
    captureDevice!.activeFormat = supportable
    // setup other capture device stuff like autofocus, frame rate, ISO, shutter speed, etc.
    try captureSession.addInput(AVCaptureDeviceInput(device: captureDevice!))
    // add the device to an active CaptureSession
}

您可能想查看有关AVCaptureSession的AVFoundation文档和教程,因为您还可以对输出执行很多操作。例如,您可以使用AVAssetExportSession将结果转换为.mp4,以便可以将其发布到YouTube等上。

希望这会有所帮助

答案 7 :(得分:-1)

Apple正在以4:3的比例使用iPhone相机。

您可以通过固定AVCaptureVideoPreviewLayer的宽度或高度约束来获取捕获视频的帧大小,并将宽高比约束设置为4:3。

4:3 Ratio

在左图中,宽度固定为300px,通过设置4:3比率检索高度,为400px。

在右图中,高度固定为300px,通过设置3:4比率检索宽度,为225px。