VideoToolBox视频编码——在macOS上对获取到的视频进行编码的问题记录

2017-08-12 08:35:35来源:CSDN作者:a997013919人点击

分享

想在macOS平台上写一个将Mac摄像头上获取到的视频数据使用VideoToolBox编码后socket发送出去的服务器,但是遇到了好多问题

先是在接受数据的客户端最终渲染出来的视频中发现绿屏现象,如下图所示:


并且报-12911的错误信息,网上查了一下说是视频数据不完整的原因,

经过验证,初步排除了socket收发数据有误的可能,所以暂时将焦点放在了macOS端的工程上,

将macOS上采集到的视频进行VideoToolBox编码,编码后写入文件,存储成h.264文件,用VLC进行播放时,发现视频整体速度偏快

经过好一番折腾,终于发现有蹊跷的地方:AVCapture输出流代理

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection;
一般情况下,当在iOS环境下,默认情况下,为30 fps,意味着该函数每秒调用30次

但是在macOS端的工程上,每秒的调用并没有达到30次,有时候只有15次,有时候又是20次…

猜想正是因为这样,而编码器以为每秒还是有30帧,所以VLC进行播放时,走了30帧,以为是1秒,但是实际上不止有1秒,因此播放时会有快进的感觉。




在代理中简单打印摄像头输出数据的信息:

    CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);    CMVideoFormatDescriptionRef desc = NULL;    CMVideoFormatDescriptionCreateForImageBuffer(NULL, pixelBuffer, &desc);    CFDictionaryRef extensions = CMFormatDescriptionGetExtensions(desc);    NSLog(@"extensions = %@", extensions);
输出:

     extensions = {     CVBytesPerRow = 1924;     CVImageBufferColorPrimaries = "ITU_R_709_2";     CVImageBufferTransferFunction = "ITU_R_709_2";     CVImageBufferYCbCrMatrix = "ITU_R_709_2";      // ITU_R_709_2是HD视频的方案,一般用于YUV422,YUV至RGB的转换矩阵和SD视频(一般是ITU_R_601_4)并不相同。     Version = 2;     }
即便是在把VideoToolBox 设置成kCVPixelFormatType_420YpCbCr8BiPlanarFullRange,输出也同上,

而在iOS真机上输出的是:

    extensions = {    CVBytesPerRow = 724;    CVImageBufferChromaLocationTopField = Center;    CVImageBufferColorPrimaries = "ITU_R_709_2";    CVImageBufferTransferFunction = "ITU_R_709_2";    CVImageBufferYCbCrMatrix = "ITU_R_601_4";    Version = 2;}
这里暂时只比较CVImageBufferYCbCrMatrix不同,根据查得的资料(链接),可知,ITU_R_709_2是HD视频的方案,一般用于YUV422,说明macOS摄像头摄像头采集到的是YUV422即YUYV格式的视频,

又将AVCaptureDevice的formats打印出来:

        // 获取当前设备支持的像素格式        NSLog(@"-- videoDevice.formats = %@", videoDevice.formats);
输出:

-- videoDevice.formats = (    "<AVCaptureDeviceFormat: 0x618000000c50> 'vide'/'yuvs' enc dims = 1280x720, pres dims = 1280x720 { 1.00-30.00 fps }",    "<AVCaptureDeviceFormat: 0x618000000cf0> 'vide'/'2vuy' enc dims = 1280x720, pres dims = 1280x720 { 1.00-30.00 fps }",    "<AVCaptureDeviceFormat: 0x618000000d20> 'vide'/'420v' enc dims = 1280x720, pres dims = 1280x720 { 1.00-30.00 fps }",    "<AVCaptureDeviceFormat: 0x618000000d50> 'vide'/'yuvs' enc dims = 640x480, pres dims = 640x480 { 1.00-30.00 fps }",    "<AVCaptureDeviceFormat: 0x618000000d80> 'vide'/'2vuy' enc dims = 640x480, pres dims = 640x480 { 1.00-30.00 fps }",    "<AVCaptureDeviceFormat: 0x618000000db0> 'vide'/'420v' enc dims = 640x480, pres dims = 640x480 { 1.00-30.00 fps }",    "<AVCaptureDeviceFormat: 0x618000000de0> 'vide'/'yuvs' enc dims = 320x240, pres dims = 320x240 { 1.00-30.00 fps }",    "<AVCaptureDeviceFormat: 0x618000000e10> 'vide'/'2vuy' enc dims = 320x240, pres dims = 320x240 { 1.00-30.00 fps }",    "<AVCaptureDeviceFormat: 0x618000000e40> 'vide'/'42
(可以看到打印的信息并不完整,不知道是为什么,当打印较长的其他数据如NSData时,也有打印不完整的现象)

由如上的输出信息可知此台Mac的摄像头支持的格式为:yuvs,2vuy,420v,
那么将VideoToolBox的编码类型改成:kCVPixelFormatType_422YpCbCr8_yuvs,或者kCVPixelFormatType_422YpCbCr8

但是当再次编译运行时,实际上AVCapture的输出流代理仍然没有达到每秒调用30次…


刚刚查到可以将YUV422转成YUV420,再进行编码,但是这样依然不能改变AVCapture输出流代理调用的次数啊…

这个方法待验证




















最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台