1

I wrote a H.264 decoder that works great. However for performance reasons, I'm trying to hard code in the PPS and SPS parameters (they never change).

For reference this is what they look like as a base 10 [UInt8]:

  • SPS [103, 66, 0, 40, 244, 5, 1, 236, 128]
  • PPS [104, 206, 9, 136]

What's bizarre is that when I decode the PPS and SPS parameters from frames that I receive and use those to create the format description and decompression session, it works great; but when I hard code them in, it doesn't work and I get VT error -12909 (bad data) when I try to decompress frames. As far as I can tell, the byte arrays are the exact same.

To hard code them in, I just wrote my createFormatDescription like this:

func createFormatDescription(sps: [UInt8]?, pps: [UInt8]?) -> Bool {
    self.formatDesc = nil

    let sps = sps ?? [103, 66, 0, 40, 244, 5, 1, 236, 128] as [UInt8]
    let pps = pps ?? [104, 206, 9, 136] as [UInt8]

    let pointerSPS = UnsafePointer<UInt8>(sps)
    let pointerPPS = UnsafePointer<UInt8>(pps)

    let dataParamArray = [pointerSPS, pointerPPS]
    let parameterSetPointers = UnsafePointer<UnsafePointer<UInt8>>(dataParamArray)

    let sizeParamArray = [sps.count, pps.count]
    let parameterSetSizes = UnsafePointer<Int>(sizeParamArray)

    let status = CMVideoFormatDescriptionCreateFromH264ParameterSets(kCFAllocatorDefault, 2, parameterSetPointers, parameterSetSizes, 4, &formatDesc)

    if status == noErr {
        print("===== Format description created")
        return true
    } else {
        return false
    }
}

And call this in my init() method. Other than that, I made no changes; frames are being interpreted in the exact same way.

For reference, here is what my VT callback looks like:

private var callback: VTDecompressionOutputCallback = {(
    decompressionOutputRefCon: UnsafeMutableRawPointer?,
    sourceFrameRefCon: UnsafeMutableRawPointer?,
    status: OSStatus,
    infoFlags: VTDecodeInfoFlags,
    imageBuffer: CVPixelBuffer?,
    presentationTimeStamp: CMTime,
    duration: CMTime) in
    let decoder: VideoFrameDecoder = Unmanaged<VideoFrameDecoder>.fromOpaque(decompressionOutputRefCon!).takeUnretainedValue()
    if imageBuffer != nil && status == noErr {
        decoder.imageDecompressed(image: imageBuffer!)
    } else {
        decoder.delegate?.frameDecodingFailed()
        print("***** FAILED TO DECOMPRESS. VT ERROR \(status)")
    }
}

Pretty basic. And just to reiterate, I'm always getting "VT ERROR -12909"

Philip S
  • 502
  • 6
  • 18
  • I know this is late, but can you describe the `videoDecoderSpecification` and `destinationImageBufferAttributes` arguments you to `VTDecompressionSessionCreate` and how you create the sample buffer you pass to `VTDecompressionSessionDecodeFrame`? – Rhythmic Fistman Jan 29 '19 at 22:11

0 Answers0