【问题标题】:Knowing resolution of AVCaptureSession's session presets了解 AVCaptureSession 会话预设的分辨率
【发布时间】:2011-12-09 01:50:58
【问题描述】:

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

captureSession.sessionPreset = AVCaptureSessionPresetMedium;

相当标准的东西。但是,我想提前知道由于此预设而获得的视频分辨率(尤其是因为取决于设备,它会有所不同)。我知道网上有表格你可以查一下(比如这里:http://cmgresearch.blogspot.com/2010/10/augmented-reality-on-iphone-with-ios40.html)。但我希望能够以编程方式获得它,这样我就不仅仅依赖于幻数。

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

[captureSession resolutionForPreset:AVCaptureSessionPresetMedium];

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

【问题讨论】:

  • 嗨,您找到解决方案了吗?我也在搜索相同的

标签: ios avfoundation core-video


【解决方案1】:

我不是 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 示例项目。看看那个代码(我现在没时间做)。

【讨论】:

  • 不幸的是,这只是在视频开始拍摄后设置的,所以仍然没有好处(虽然给了你一点)。
  • 是的,我没试过。可惜没有这样的 API。谢谢你的点:)
  • 是的,您必须先调用 [captureSession startRunning]。这适用于我的情况。如果您只想阅读预设是什么,我想您必须设置一个捕获会话并立即将其终止。
  • 上面的代码对我有用——在[capSession commitConfiguration]之后调用它,它在前后摄像头之间切换时有效。多么愚蠢的信息寻宝游戏!
【解决方案2】:

仅供参考,我在此附上 Apple 的官方回复。


这是 Bug ID# 13201137 的后续。

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

包含的代码有几个问题:

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 全球开发者关系

【讨论】:

  • 最好使用 AVCaptureInputPortFormatDescriptionDidChangeNotification 作为获取 formatDescription 和尺寸的地方。
【解决方案3】:

您可以在捕获开始之前以编程方式从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
}

【讨论】:

  • 这可以缩短为只让 formatDescription = .activeFormat.formatDescription let dimensions = CMVideoFormatDescriptionGetDimensions(formatDescription) print(dimensions)
【解决方案4】:

According to Apple,没有 API。很臭,我也遇到过同样的问题。

【讨论】:

  • 没有 API,但有一种方法可以在捕获开始之前以编程方式发现视频分辨率。在这里回答:stackoverflow.com/a/35470937/144088
  • @Crashalot 我在想那么 snapchat 是怎么做到的?因为在 snapchat 中,相机处于全屏状态,没有拉伸/缩放问题。当我将故事保存到图库时,图像/视频尺寸(对于 iPhone X)为 1122x2208。谢谢
【解决方案5】:

您是否可以提供每个 iPhone 型号的所有可能预设分辨率的列表,并检查应用程序在哪个设备型号上运行? - 使用类似的东西...

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

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

【讨论】:

  • 我正在考虑这样做,但苹果文档只列出了 iPhone 4。
【解决方案6】:

如果预设为.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 的答案是指定预设的好方法。 我的方式很适合主动预设。

【讨论】:

    【解决方案7】:

    做你想做的事(获取已知的视频或图像格式)的最佳方法是设置捕获设备的格式。

    首先找到你要使用的采集设备:

           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 等。

    希望对你有帮助

    【讨论】:

      【解决方案8】:

      Apple 正在为 iPhone 摄像头使用 4:3 的比例。

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

      左图中,宽度固定为300px,高度通过设置4:3的比例获取,为400px。

      右图中,高度固定为300px,宽度通过设置3:4的比例获取,为225px。

      【讨论】:

        猜你喜欢
        • 2016-09-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-06-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-07-23
        相关资源
        最近更新 更多