美文网首页
swift 视频编码

swift 视频编码

作者: 我会回来的 | 来源:发表于2021-12-29 18:04 被阅读0次

    视频采集完成后,需要先编码,再传输,在解码,再播放(重现) 

    1 视频压缩

    第一: 创建VTCompressionSession 

    ———————————— 初始化编码器—————————————————————————— 

     //像素缓冲区选项

                    letpixelBufferOptions: [String:Any] = [

                        kCVPixelBufferPixelFormatTypeKeyasString: kCVPixelFormatType_32BGRA,

                        kCVPixelBufferWidthKeyasString: frameW,

                        kCVPixelBufferHeightKeyasString: frameH,

                        kCVPixelBufferOpenGLESCompatibilityKeyasString:true,

                        kCVPixelBufferIOSurfacePropertiesKeyasString: [:]

                    ]

    varerr: OSStatus = noErr 

     // 初始化编码器

                    err = VTCompressionSessionCreate(

                        allocator: kCFAllocatorDefault,

                        width: Int32(frameW),

                        height: Int32(frameH),

                        codecType: codecType,

                        encoderSpecification: encoderSpecificationsasNSDictionary?,

                        imageBufferAttributes: pixelBufferOptionsasNSDictionary?,

                        compressedDataAllocator:nil,

                        outputCallback: vtCallback,

                        refcon: UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque()),

                        compressionSessionOut: &sessionOut)

    第二: 配置VTCompressionSession 

    —————————————— 配置VTCompressionSession ———————————

    varerr: OSStatus = noErr 

    使用VTSessionSetProperty

    //设置编码方式

                    err = VTSessionSetProperty(

                        session,

                        key: kVTCompressionPropertyKey_ProfileLevel,

                        value: profileLevel)

    第三: 对硬件捕获到的数据进行编码 

    ————————————————对硬件捕获到的数据进行编码 ———————————————

    //进行硬编码 

                varsessionOut: VTCompressionSession?

     VTCompressionSessionPrepareToEncodeFrames(session)

    第四:VTCompressionOutputCallback 

    --------------------------------- -----帧压缩完成时调用的回调原型------------------------------------

    //////// 压缩输出回调 

    // 编码完成回调 

    // 指针对象转换

     letenc = unsafeBitCast(outputCallbackRefCon, to: VTEncode.self

    时间信息。我们可以分别使用 CMSampleBufferGetPresentationTimeStamp 和 CMSampleBufferGetDecodeTimeStamp 获得原始演示时间和解码时间的准确时间戳。

    // 获取当前帧 是否是关键帧 

    发送 SPS 和 PPS 

    CMVideoFormatDescriptionGetH264ParameterSetAtIndex  取得 SPS 和  PPS

    compressionSessionOutput  压缩会话输出

    CMBlockBufferGetDataPointer (除了关键帧 其他帧只有一个数据) 

    先找到PAT表, 通过PAT 找到PMT 的表,然后找到了TS流。

    只有视频转换TS流。  

    TS 数据包 

    TS packet 是TS流的基本组成单位

    TS packet 一般是188个字节长度,(或者是204个字节 188个字节加上16个字节(CRC校验数据 ))

    TS packet 包含4个字节的 TS header 和其余的TS数据: 

    4字节 Packet header

    184字节 Packet data 

    PID 唯一标识 ,Packet header 中PID是0x0000, data就为 DVB的PAT标

    TS  文件是传输文件,视频编码主要格式h264/mpeg4,音频为acc/MP3。

    TS流主要用于相对有错的环境下的传输和存储,如DVB

    TS流 

    先找到PAT表, 通过PAT 找到PMT 的表,然后找到了TS流。

    PAT表: 指明了 PMT表的PID值

    PMT表: 指明的是音视频流的PID值 

    pcr 是递增的, 可以将其设置为dts值, 音频数据不需要pcr 。

    Pes层 是在每一个视频/音频上加入了时间等信息,pes包内容很多, 只留下最常用的。

    转载文档: https://blog.csdn.net/shj348794/article/details/25004783  

    帧压缩时调用的回调原型  1帧后会异步调用改方法。  

    // 获取sps pps 数据 只需获取一次,保存在H264文件开头即可。   

    vps: 仅在H265编码器中才有。

    https://blog.csdn.net/weixin_34362790/article/details/91470636

    kCMSampleAttachmentKey_DependsOnOthers 通过他判断是否有I帧  

    1 准备编码器

    (1)创建session : VTCompressionSessionCreate

     (2)设置属性: VTSessionSetProperty 是否实时编码输出、是否产生B帧、设置关键帧、设置期望帧率、设置码率、最大码率值等等

     (3)准备开始编码:VTCompressionSessionPrepareToEncodeFrames  

    2  编码完成后数据处理

    (1)判断是否是关键帧

    (2)组装NALU数据: 获取编码后的h264流数据:CMBlockBufferRef dataBuffer = CMSampleBufferGetDataBuffer(sampleBuffer),通过 首地址 、单个长度、 总长度通过dataPointer指针偏移做遍历

     OSStatus statusCodeRet = CMBlockBufferGetDataPointer(dataBuffer, 0, &length, &totalLength, &dataPointer); 

    读取数据时有个大小端模式:网络传输一般都是大端模式

    sps:序列参数集 

    pps:图像参数集 

    这两个帧也是独立。

    添加startcode: 00 00 00 01 然后推流出去。

    转载: https://www.cnblogs.com/edisongz/p/7062098.html

    H.264 原始流  是由一个一个NALU组成的。

    最后输出 compressionSessionOutput  压缩会话 

    流程总结:

     1. 通过VTCompressionSessionCreate创建编码器 

      2. 通过VTSessionSetProperty设置编码器属性 

      3. 调用VTCompressionSessionPrepareToEncodeFrames 准备编码 

      4. 输入采集到的视频数据CVImageBufferRef /CVPixelBufferRef,调用VTCompressionSessionEncodeFrame进行编码 

      5. 获取到编码后的数据进行处理并组装NALU

         NALU分为两种格式:  Annex B 和 AVCC 

      6. 调用VTCompressionSessionCompleteFrames 停止编码器

      7.  调用VTCompressionSessionInvalidate销毁编码器 

    相关文章

      网友评论

          本文标题:swift 视频编码

          本文链接:https://www.haomeiwen.com/subject/wltyqrtx.html