iOS音视频编解码

编解码协议H264(视频)和AAC(音频)有软编解码和硬编解码。

网络传输都是用的大端序(高地址低字节),H264网络传输的startcode是数据的length,不是0x00000001。NALU 有两种格式:Annex B 和 AVCC。Annex B 格式startcode以 0x 00 00 01 或 0x 00 00 00 01 开头, AVCC 格式以 NALU 的长度开头。

AAC也有两种传输格式:ADTS和ADIF

  • ADIF:Audio Data Interchange Format 音频数据交换格式。这种格式的特征是可以确定的找到这个音频数据的开始,不需进行在音频数据流中间开始的解码,即它的解码必须在明确定义的开始处进行。故这种格式常用在磁盘文件中。
  • ADTS:Audio Data Transport Stream 音频数据传输流。这种格式的特征是它是一个有同步字的比特流,解码可以在这个流中任何位置开始。它的特征类似于mp3数据流格式。

软编码:使用CPU进行编码。编码框架ffmpeg+x264。

  • https://www.jianshu.com/p/e631b041e96d
  • https://www.jianshu.com/p/3de01105d735

硬编码:不使用CPU进行编码,使用显卡(GPU)进行硬件加速。 专用的DSP、FPGA、ASIC芯片等硬件进行编码。ios上硬编码框架Video ToolBox和AudioToolbox。

  • Intel硬编码使用Intel处理器内部集成的显卡进行硬件加速,qsv加速方法便对应着Intel硬编码。Intel硬编码对H.264加速效果明显,且不需要安装额外库(仅使用相应的ffmpeg命令)。
  • NVIDIA硬编码使用英伟达的显卡对视频编码进行加速。CUDA加速方法对应着NVIDIA硬编码。使用英伟达硬编码之前需要安装CUDA与英伟达的必要驱动。安装好两个环境后就可以使用NVIDIA的硬编码了。英伟达关于视频的编解码提供了两个相关的 SDK:NVENC(硬编码)和NVCUVID(硬解码),前者负责硬件编码,二后者负责硬件解码。CUDA支持Windows、Linux、MacOS三种主流操作系统。https://blog.csdn.net/qq_29350001/article/details/75144665(CUDA详解)
  • FFmpeg中也支持了硬编码,集成了显示视频处理模块。在命令行中使用 ffmpeg -hwaccels 可以查看ffmpeg支持的硬件加速方法。
    FFMPEG 目前存在一个编码器 nvenc 是对于NVIDIA的 NVENC 的封装,通过使用它可以和 FFMPEG 无缝的整合起来。不过 FFMPEG 只存在 NVENC 的接口,不存在 NVCUVID(解码器) 的封装。如果需要实现相关的解码器可能需要自己实现 FFMPEG 接口。FFMPEG实现了对于 Intel QSV 的封装。
  • DXVA是微软定制的视频加速规范、在Linux 平台上则是由NVIDIA提供的VDPAU和Intel提供的VAAPI加速规范。

在不同平台上可通过不同API使用Intel GPU的硬件加速能力。目前主要由两套API:VAAPI以及libmfx。VAAPI (视频加速API,Video Acceleration API)包含一套开源的库(LibVA) 以及API规范, 用于硬件加速下的视频编解码以及处理,只有Linux上的驱动提供支持。libmfx。Intel Media SDK中的API规范,支持视频编解码以及媒体处理。支持Windows以及Linux。除了Intel自己的API,在Windows系统上还有其他API可使用Intel GPU的硬件加速能力,这些API属于Windows标准,由Intel显卡驱动实现。DXVA2 / D3D11VA。标准Windows API,支持通过Intel显卡驱动进行视频编解码,FFmpeg有对应实现。Media Foundation。标准Windows API,支持通过Intel显卡驱动进行视频编解码,FFmpeg不支持该API。https://blog.jianchihu.net/intel-gpu-hw-video-codec-develop.html

目前的主流GPU加速平台:

  INTEL、AMD、NVIDIA

目前主流的GPU平台开发框架:

  • CUDA:NVIDIA的封闭编程框架,通过框架可以调用GPU计算资源
  • AMD APP:AMD为自己的GPU提出的一套通用并行编程框架,标准开放,通过在CPU、GPU同时支持OpenCL框架,进行计算力融合。
  • OpenCL:开放计算语言,为异构平台编写程序的该框架,异构平台可包含CPU、GPU以及其他计算处理器,目标是使相同的运算能支持不同平台硬件加速。
  • Inel QuickSync:集成于Intel显卡中的专用视频编解码模块。

https://www.jianshu.com/p/8423724dffc1
https://blog.csdn.net/haowei0926/article/details/56012139

ios中的硬编码文档
ios上硬编码框架Video ToolBox和AudioToolbox。Video ToolBox是一个底层框架,可以直接访问硬件编码器和解码器。 它提供视频压缩和解压缩服务,并在CoreVideo像素缓冲区中存储的光栅raster图像格式之间进行转换。 这些服务以会话对象(压缩,解压缩和像素传输)的形式提供,它们以Core Foundation(CF)类型呈现。 不需要直接访问硬件编码器和解码器的应用程序App就不需要直接使用VideoToolbox。iOS 8.0及以上苹果开放了VideoToolbox框架来实现H264硬编码(H264是一种编解码协议,有多种编解码器能编解码H264,这里是利用硬件进行编解码,FFmpeg中可以利用硬编解码和软编解码)。

  • CVPixelBufferRef/CVImageBufferRef:存放编码前和解码后的图像数据(未压缩的数据),这两个是相同的对象。
  • CMTime:时间戳相关,时间以64-bit/32-bit的形式出现
  • CMBlockBufferRef:编码后输出的数据(压缩后的数据)
  • CMFormatDescriptionRef/CMVideoFormatDescriptionRef:图像存储方式,编解码器等格式描述。这两个是相同的对象。
  • CMSampleBufferRef:存放编解码前后的视频图像的容器数据,iOS中表示一帧音频/视频数据
  • CMSampleBuffer 可能是一个压缩的数据,也可能是一个未压缩的数据。取决于 CMSampleBuffer 里面是 CMBlockBuffer(压缩后) 还是 CVPixelBuffer(未压缩)。

硬编码的步骤 :从相机或读取视频文件输出的CVPixelBuffer(也是以CMSampleBufferRef封装形式存在)—>Encoder—>CMSampleBufferRef(编码后得到的数据封装)—>重新组装NALUs。

  1. 通过VTCompressionSessionCreate创建编码器
    VTCompressionSessionCreate(
    	    CM_NULLABLE CFAllocatorRef                          allocator,
    	    int32_t                                             width,
    	    int32_t                                             height,
    	    CMVideoCodecType                                    codecType,
    	    CM_NULLABLE CFDictionaryRef                         encoderSpecification,
    	    CM_NULLABLE CFDictionaryRef                         sourceImageBufferAttributes,
    	    CM_NULLABLE CFAllocatorRef                          compressedDataAllocator,
    	    CM_NULLABLE VTCompressionOutputCallback             outputCallback,
    	    void * CM_NULLABLE                                  outputCallbackRefCon,
    	    CM_RETURNS_RETAINED_PARAMETER CM_NULLABLE VTCompressionSessionRef * CM_NONNULL compressionSessionOut)
    	    
    	allocator:内存分配器,填NULL为默认分配器
    	width、height:视频帧像素的宽高,如果编码器不支持这个宽高的话可能会改变
    	codecType:编码类型,枚举
    	encoderSpecification:指定特定的编码器,填NULL的话由VideoToolBox自动选择
    	sourceImageBufferAttributes:源像素缓冲区的属性,如果这个参数有值的话,VideoToolBox会创建一个缓冲池,不需要缓冲池可以设置为NULL
    	compressedDataAllocator:压缩后数据的内存分配器,填NULL使用默认分配器
    	outputCallback:视频编码后输出数据回调函数
    	outputCallbackRefCon:回调函数中的自定义指针,我们通常传self,因为我们需要在C函数中调用self的方法,而C函数无法直接调self,
    	compressionSessionOut:编码器句柄,传入编码器的指针
    
  2. 通过VTSessionSetProperty设置编码器属性,是否实时编码输出、是否产生B帧、设置关键帧、设置期望帧率、设置码率、最大码率值等等。
    VTSessionSetProperty(
      // 解码会话
      CM_NONNULL VTSessionRef       session,
      // 属性 KEY
      CM_NONNULL CFStringRef        propertyKey,
      // 设置的属性值
      CM_NULLABLE CFTypeRef         propertyValue )
    kVTCompressionPropertyKey_AverageBitRate:设置编码的平均码率,单位是bps,这不是一个硬性指标,设置的码率会上下浮动。VideoToolBox框架只支持ABR模式。H264有4种码率控制方法:
    
    CBR(Constant Bit Rate)是以恒定比特率方式进行编码,有Motion发生时,由于码率恒定,只能通过增大QP来减少码字大小,图像质量变差,当场景静止时,图像质量又变好,因此图像质量不稳定。这种算法优先考虑码率(带宽)。
    VBR(Variable Bit Rate)动态比特率,其码率可以随着图像的复杂程度的不同而变化,因此其编码效率比较高,Motion发生时,马赛克很少。码率控制算法根据图像内容确定使用的比特率,图像内容比较简单则分配较少的码率(似乎码字更合适),图像内容复杂则分配较多的码字,这样既保证了质量,又兼顾带宽限制。这种算法优先考虑图像质量。
    *CVBR(Constrained VariableBit Rate),这样翻译成中文就比较难听了,它是VBR的一种改进方法。但是Constrained又体现在什么地方呢?这种算法对应的Maximum bitRate恒定或者Average BitRate恒定。这种方法的兼顾了以上两种方法的优点:在图像内容静止时,节省带宽,有Motion发生时,利用前期节省的带宽来尽可能的提高图像质量,达到同时兼顾带宽和图像质量的目的。
    ABR (Average Bit Rate) 在一定的时间范围内达到设定的码率,但是局部码率峰值可以超过设定的码率,平均码率恒定。可以作为VBR和CBR的一种折中选择。
    kVTCompressionPropertyKey_ProfileLevel:设置H264编码的画质,H264有4种Profile:BP、EP、MP、HP
    
    BP(Baseline Profile):基本画质。支持I/P 帧,只支持无交错(Progressive)和CAVLC;主要应用:可视电话,会议电视,和无线通讯等实时视频通讯领域
    EP(Extended profile):进阶画质。支持I/P/B/SP/SI 帧,只支持无交错(Progressive)和CAVLC;
    MP(Main profile):主流画质。提供I/P/B 帧,支持无交错(Progressive)和交错(Interlaced),也支持CAVLC 和CABAC 的支持;主要应用:数字广播电视和数字视频存储
    HP(High profile):高级画质。在main Profile 的基础上增加了8×8内部预测、自定义量化、 无损视频编码和更多的YUV 格式;应用于广电和存储领域
    
    Level就多了,这里不一一列举,可参考h264 profile & level,iPhone上常用的方案如下:
    
    实时直播:
    低清Baseline Level 1.3
    标清Baseline Level 3
    半高清Baseline Level 3.1
    全高清Baseline Level 4.1
    存储媒体:
    低清 Main Level 1.3
    标清 Main Level 3
    半高清 Main Level 3.1
    全高清 Main Level 4.1
    高清存储:
    半高清 High Level 3.1
    全高清 High Level 4.1
    kVTCompressionPropertyKey_RealTime:设置是否实时编码输出
    kVTCompressionPropertyKey_AllowFrameReordering:配置是否产生B帧,High profile 支持 B 帧
    kVTCompressionPropertyKey_MaxKeyFrameInterval、kVTCompressionPropertyKey_MaxKeyFrameIntervalDuration:配置I帧间隔
    
  3. 调用VTCompressionSessionPrepareToEncodeFrames准备编码
    VTCompressionSessionPrepareToEncodeFrames( CM_NONNULL VTCompressionSessionRef session )
    
    session:编码器句柄,传入编码器的指针
    
  4. 输入采集到的视频数据CVImageBufferRef /CVPixelBufferRef,调用VTCompressionSessionEncodeFrame进行编码
    VTCompressionSessionEncodeFrame(
        CM_NONNULL VTCompressionSessionRef  session,
        CM_NONNULL CVImageBufferRef         imageBuffer,
        CMTime                
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
iOS中使用FFmpeg进行音视频同步可以通过以下步骤来实现: 1. 下载FFmpeg库 你可以通过CocoaPods等方式下载FFmpeg库。在Podfile文件中添加以下代码: ```ruby pod 'FFmpeg' ``` 下载完后运行`pod install`指令安装FFmpeg库。 2. 音视频解码 使用FFmpeg库进行音视频解码。对于音频和视频,你需要分别解码它们的数据。解码后的音频和视频数据通常存储在`AVFrame`结构体中。 3. 音视频同步 音视频同步的主要难点在于如何将两个不同的时钟进行同步。通常情况下,你需要使用音频时钟来同步视频帧,因为音频时钟是相对稳定的,而视频时钟可能会因为帧率不稳定等原因而不稳定。 具体实现方法可以采用以下步骤: - 获取音频播放时间戳(PTS) - 获取视频帧显示时间戳(PTS) - 计算音视频时间差 - 根据时间差进行音视频同步 其中,音频播放时间戳可以通过audio queue的回调函数获取,视频帧显示时间戳可以通过解码后的AVFrame结构体中的`pts`字段获取,时间差可以通过两个时间戳的差值计算得到。 4. 音视频渲染 在完成音视频同步后,你需要使用OpenGL ES或者Core Graphics等技术来渲染视频帧,同时使用Audio Queue或者OpenAL等技术来播放音频帧。 需要注意的是,iOS中使用FFmpeg进行音视频同步是一个比较复杂的过程,需要一定的技术基础和经验。同时,由于FFmpeg库的复杂性和特性,可能会涉及到一些版权和法律问题。因此,建议在使用前仔细查阅相关文档和法律条款,以免出现不必要的问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值