AWLive 源码解读(视频编解码)

视频编解码

视频编码

  1. 根据视频的宽高和编码格式创建编码器并设置编码器的一些属性
  2. 根据收到的CVPixelBufferRef 开始编码
  3. 在编码后的数据中分离出 sps&pps&nalu,
    1. 获取 sps&pps (Annex B或者 AVCC)
      • Annex B 格式 : 0x00000001(4字节) + sps + 0x00000001(4字节) + pps + 0x00000001(4字节) + NALU 数据 + 0x00000001(4字节) + NALU 数据 + … + 0x00000001(4字节) + NALU 数据
      • AVCC 格式 : dict[@“SampleDescriptionExtensionAtoms”][@“avcC”] + NALULen0(4字节) + NALU数据(NALULen0字节) + NALULen1(4字节) + NALU数据(NALULen1字节) + … + NALULenx(4字节) + NALU数据(NALULenx字节)
    2. 获取nalu
  4. 然后推流或者保存本地
  5. 完成后关闭推流器

[关键代码如下] :

// - 创建编码器
-(void)open{
   
    /* 配置编码器, 这里并不是立刻开始编码, 只是配置编码器
     1. 分配器  传 NULL
     2. 分辨率的 width
     3. 分辨率的 height
     4. 编码类型 kCMVideoCodecType_H264
     5. 编码规范 NULL
     6. 源像素缓冲区 NULL
     7. 压缩数据分配器 NULL
     8. 编码完成的回调
     9. self, 将 self 桥接过去
     10. VTCompressionSessionRef  &_vEnSession
     */
    OSStatus status = VTCompressionSessionCreate(NULL, (int32_t)(self.videoConfig.pushStreamWidth), (int32_t)self.videoConfig.pushStreamHeight, kCMVideoCodecType_H264, NULL, NULL, NULL, vtCompressionSessionCallback, (__bridge void * _Nullable)(self), &_vEnSession);
    
    /** 编码器创建成功 配置编码器的参数 */
    if (status == noErr) {
   
        // 设置参数
        // ProfileLevel,h264的协议等级,不同的清晰度使用不同的ProfileLevel。  kVTProfileLevel_H264_Baseline_AutoLevel 表示舍弃 B 帧
        VTSessionSetProperty(_vEnSession, kVTCompressionPropertyKey_ProfileLevel, kVTProfileLevel_H264_Main_AutoLevel);
        
        // 设置码率 通常设置为 宽 * 高 * 3 * 4 * 8;
//        int bitrate = width * height * 8 * 3 * 4;
//        CFNumberRef bitrateRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &bitrateRef);
//        VTSessionSetProperty(_vEnSession, kVTCompressionPropertyKey_AverageBitRate, bitrate);
        VTSessionSetProperty(_vEnSession, kVTCompressionPropertyKey_AverageBitRate, (__bridge CFTypeRef)@(self.videoConfig.bitrate));

        // 设置实时编码
        VTSessionSetProperty(_vEnSession, kVTCompressionPropertyKey_RealTime, kCFBooleanTrue);
        // 关闭重排Frame,因为有了B帧(双向预测帧,根据前后的图像计算出本帧)后,编码顺序可能跟显示顺序不同。此参数可以关闭B帧。
        VTSessionSetProperty(_vEnSession, kVTCompressionPropertyKey_AllowFrameReordering, kCFBooleanFalse);
        
        // 关键帧最大间隔(GOP) 这里是 2s。
        VTSessionSetProperty(_vEnSession, kVTCompressionPropertyKey_MaxKeyFrameInterval, (__bridge CFTypeRef)@(self.videoConfig.fps * 2));
        
        // 关于B帧 P帧 和I帧,请参考:http://blog.csdn.net/abcjennifer/article/details/6577934
        //编码器参数设置完毕,准备开始,随时来数据,随时编码
        status = VTCompressionSessionPrepareToEncodeFrames(_vEnSession);
        if (status != noErr) {
   
            [self onErrorWithCode:AWEncoderErrorCodeVTSessionPrepareFailed des:@"硬编码vtsession prepare失败"];
        }
    }else{
   
        [self onErrorWithCode:AWEncoderErrorCodeVTSessionCreateFailed des:@"硬编码vtsession创建失败"];
    }
}

// - 编码数据
-(void)encodeSample(CMSampleBufferRef)sampleBuffer{
   
    if (!_vEnSession) {
   
        return NULL;
    }
    uint32_t ptsMs = self.manager
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值