H.264解码器无法正常工作?

时间:2018-03-20 09:02:52

标签: ios swift avfoundation h.264

我已经为这个基本h.264比特流的解码器的代码翻了一百遍,一路上调整了一些东西,没有运气。当我将输出CMSampleBuffers发送到AVSampleBufferDisplayLayer时,它们不会出现,大概是因为我解码它们的方式有问题。

我在任何地方都没有收到错误消息; AVSampleBufferDisplayLayer没有错误和" status"是" 1" (aka .rendering),CMSampleBufferIsValid()返回" true"在输出的CMSampleBuffers上,我的解码器也没有遇到任何错误。

我很难过,我希望更有经验的开发人员能够抓住我失踪的东西。

我在这里输入原始字节(typealias FrameData = [UInt8])

private func decodeFrameData(_ frameData: FrameData) -> CMSampleBuffer? {
    let bufferPointer = UnsafeMutablePointer<UInt8>(mutating: frameData)
    let size = frameData.count

    var blockBuffer: CMBlockBuffer?
    var status = CMBlockBufferCreateWithMemoryBlock(kCFAllocatorDefault,
                                                    bufferPointer,
                                                    size,
                                                    kCFAllocatorNull,
                                                    nil, 0, frameData.count,
                                                    0, &blockBuffer)

    if status != kCMBlockBufferNoErr { return nil }

    var sampleBuffer: CMSampleBuffer?
    let sampleSizeArray = [size]

    status = CMSampleBufferCreateReady(kCFAllocatorDefault,
                                       blockBuffer,
                                       formatDesc,
                                       1, 0, &sampleTimingInfo,
                                       1, sampleSizeArray,
                                       &sampleBuffer)

    if let buffer = sampleBuffer, status == kCMBlockBufferNoErr {
        let attachments: CFArray? = CMSampleBufferGetSampleAttachmentsArray(buffer, true)

        if let attachmentArray = attachments {
            let dic = unsafeBitCast(CFArrayGetValueAtIndex(attachmentArray, 0), to: CFMutableDictionary.self)

            let key = Unmanaged.passUnretained(kCMSampleAttachmentKey_DisplayImmediately).toOpaque()
            let val = Unmanaged.passUnretained(kCFBooleanTrue).toOpaque()
            CFDictionarySetValue(dic,
                                 key,
                                 val)
        }

        print("===== Successfully created sample buffer")
        return buffer
    }

    return nil
}

这就是实际解码的地方:

{{1}}

其他注意事项:

  • formatDescription包含正确的信息(mediaType =&#34; vide&#34;,mediaSubType =&#34; avc1&#34;,dimensions =&#34; 640x480&#34;)
  • 比特流I解码始终将SPS,PPS和IDR帧组合在一起,并且每20帧左右将它们作为一个大数据包发送。每隔一次,就会发送一个单独的B / P帧。

谢谢!

1 个答案:

答案 0 :(得分:0)

那段代码非常难看,所以我决定稍微触摸一下。原来这就是诀窍。那里肯定是错的。

无论如何,这是一个有效的版本。它发送解码后的&amp;解压缩帧到其委托。理想情况下,无论谁调用 interpretRawFrameData 都会返回一个可显示的框架,我将继续处理,但同时这也适用。

https://github.com/philipshen/H264Decoder