【问题标题】:CMVideoFormatDescriptionCreateFromH264ParameterSets throw Initialization of 'UnsafePointer<Int>' results in a dangling pointerCMVideoFormatDescriptionCreateFromH264ParameterSets throw 初始化 'UnsafePointer<Int>' 导致指针悬空
【发布时间】:2020-08-02 10:56:12
【问题描述】:

所以之前我打开了Initialization of 'UnsafePointer<Int>' results in a dangling pointer,但模组说这是重复的。

但我不认为这是重复的,因为该帖子中引用的链接无法轻松指向解决方案。因此,我必须在 3 天后打开一个新的。我尝试了上一篇文章中@bscothern 的回答,但出现了更多错误。

当前正在使用的代码就像下面来自@bscothern,它仍然抛出

无法推断通用参数“R”

var formatDesc: CMVideoFormatDescription?
func createH264FormatDescription(SPS: Array<UInt8>, PPS: Array<UInt8>) -> OSStatus {
    if formatDesc != nil { formatDesc = nil }

    let status = SPS.withUnsafeBufferPointer { SPS in
        PPS.withUnsafeBufferPointer { PPS in
            let paramSet = [SPS.baseAddress!, PPS.baseAddress!]
            let paramSizes = [SPS.count, PPS.count]
            return paramSet.withUnsafeBufferPointer { paramSet in
                paramSizes.withUnsafeBufferPointer { paramSizes in
                    CMVideoFormatDescriptionCreateFromH264ParameterSets(allocator: kCFAllocatorDefault, parameterSetCount: 2, parameterSetPointers: paramSet.baseAddress!, parameterSetSizes: paramSizes.baseAddress!, nalUnitHeaderLength: 4, formatDescriptionOut: &formatDesc)
                }
            }
        }
    }
    return status
}

上一篇文章的原始问题:

所以我有一些代码来创建 H264ParameterSets,例如:

var formatDesc: CMVideoFormatDescription?

func createH264FormatDescription(SPS: Array<UInt8>, PPS: Array<UInt8>) -> OSStatus {
    if formatDesc != nil { formatDesc = nil }

    let paramSet = [UnsafePointer<UInt8>(SPS), UnsafePointer<UInt8>(PPS)]
    let paramPointers = UnsafePointer<UnsafePointer<UInt8>>(paramSet)
    let paramSizes = UnsafePointer<Int>([SPS.count, PPS.count])

    let status = CMVideoFormatDescriptionCreateFromH264ParameterSets(allocator: kCFAllocatorDefault, parameterSetCount: 2, parameterSetPointers: paramPointers, parameterSetSizes: paramSizes, nalUnitHeaderLength: 4, formatDescriptionOut: &formatDesc)

    return status
}

从 Xcode 11.4 开始,我收到了有关 UnsafePointer() 的警告,这在以前似乎没有发生过:

Initialization of UnsafePointer<UInt8> results in a dangling pointer

Initialization of UnsafePointer<UnsafePointer<UInt8>> results in a dangling pointer

Initialization of UnsafePointer<Int> results in a dangling pointer

我不确定我们为什么会看到这个?以及如何删除警告?提前致谢。

【问题讨论】:

  • 在其他问题中,paramSet(用词不当:它是一个数组,而不是一个集合)`在你的函数中被分配为一个局部变量,并在你的函数结束时被释放,因为没有其他提供了强有力的参考。同时,通过获取指向该缓冲区的指针,您将拥有一个仅在该函数体中有效的指针。我不熟悉CMFormatDescription。它是否保留这些指针并在内部存储它们?还是只是在复制数据时暂时借用它们?
  • @Alexander-ReinstateMonica 核心媒体 API 要求我提供这样的参数,还有那些 SPS,PPS 是从视频原始数据字节中获取的。

标签: ios swift


【解决方案1】:

当你发现一些错误信息如:Generic parameter 'R' could not be inferred,可能有两种可能的原因。

  • 某处存在一些与类型相关的错误,因此 Swift 无法在该上下文中推断出实际类型 R
  • 表达式比 Swift 推断类型要复杂一些

在情况 1 中,您需要找出导致问题的实际错误在哪里。

在情况 2 中,您可以添加一些显式类型注释来帮助 Swift 推断类型。

请尝试以下方法:

    var formatDesc: CMVideoFormatDescription?
    func createH264FormatDescription(SPS sps: Array<UInt8>, PPS pps: Array<UInt8>) -> OSStatus {
        if formatDesc != nil { formatDesc = nil }

        let status = sps.withUnsafeBufferPointer { spsBP->OSStatus in //<- Specify return type explicitly.
            pps.withUnsafeBufferPointer { ppsBP in
                let paramSet = [spsBP.baseAddress!, ppsBP.baseAddress!]
                let paramSizes = [spsBP.count, ppsBP.count]
                return paramSet.withUnsafeBufferPointer { paramSetBP in
                    paramSizes.withUnsafeBufferPointer { paramSizesBP in
                        CMVideoFormatDescriptionCreateFromH264ParameterSets(allocator: kCFAllocatorDefault, parameterSetCount: 2, parameterSetPointers: paramSetBP.baseAddress!, parameterSetSizes: paramSizesBP.baseAddress!, nalUnitHeaderLength: 4, formatDescriptionOut: &formatDesc)
                    }
                }
            }
        }
        return status
    }

【讨论】:

  • 嗨@OOPer,你怎么知道spsBP有OSStatus?你能解释更多吗?我对这些嵌套块有点困惑。你能帮我清理一下头脑吗?例如嵌套块最终有返回值,如何?
  • 哎呀,我误会了。 spsBP->OSStatus 是函数类型,不是 C -&gt; 操作。我发现它是通过撕毁每个块来返回的。 withUnsafeBufferPointer 有 return 作为 body 的返回值。