js css html收藏

AV Foundation ⑯ 视频处理与CMSampleBuf

2022-06-12  本文已影响0人  _涼城

视频处理

    使用 AVCaptureMovieFileOutput 虽然可以便捷的捕捉视频数据,但是它无法同视频数据进行交互,而交互又是许多场景所需要的功能。当需要使用底层控制时,就会用到框架提供的最底层的视频捕捉输出 AVCaptureVideoDataOutput

    AVCaptureVideoDataOutput 是一个 AVCaptureOutput 的子类,可以直接访问摄像头传感器捕捉到的视频帧。这是一个强大的功能,因为这样我们就完全控制了视频数据的格式、时间和元数据,可以按照需求操作视频内容。大部分情况下,处理过程都是使用 OpenGL ESCore Image,有时, Quartz 也可以满足一些简单的处理要求。

    使用 AVCaptureVideoDataOutput 输出的对象需要通过 AVCapatureVideoDataOutputSampleBufferDelegate 协议包含视频数据,其定义了下面两个方法

    这两个方法最重要的参数与 sample buffer 相关。 sample bufferCMSampleBuffer 对象的形式提供。

CMSampleBuffer

    CMSampleBuffer 是一个由 Core Media 框架提供的 Core Foundation 风格的框架,用于在媒体管道中传输数字样板。 CMSampleBuffer 的角色是将基础的样本数据进行封装并提供格式和时间信息,还会加上所有在转换和处理数据时用到的元数据。

样本数据

    CMSampleBuffer 中会包含一个 CVPixelBuffer,它是带有单个视频帧原始像素数据的 Core Video 对象。下面示例展示了如何直接操作 CVPixelBuffer 的内容为捕捉到的图片 buffer 应用一个灰度效果:

const int BYTES_PER_PIXEL = 4;
CMSampleBuffer sampleBuffer1 = <#sample buffer#>
//获取基本的 CVPixelBuffer,其保存的是像素数据
CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
//获取相应内存块的锁
CVPixelBufferLockBaseAddress(pixelBuffer, 0);
//确定宽高
size_t bufferWidth = CVPixelBufferGetWidth(pixelBuffer);
size_t bufferHeight = CVPixelBufferGetHeight(pixelBuffer);
// 获取基址指针
unsigned char *pixel = (unsigned char *)CVPixelBufferGetBaseAddress(pixelBuffer);
unsigned char grayPixel;
//遍历像素点
for(int row = 0; row < bufferHeight; row++){
    for(int column = 0; column < bufferWidth; column++){
        //执行灰度平均
        grayPixel = (pixel[0] + pixel[1] + pixel[2]) / 3;
        pixel[0] = pixel[1] =  pixel[2] = grayPixel;
        pixel += BYTES_PER_PIXEL;
    }
}
//释放锁
CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);

格式描述

    除了原始媒体样本外, CMSampleBuffer 还提供了以 CMFormatDescription 对象的形式来访问样本的格式信息。 CMFormatDescription.h 定义了大量函数用于访问媒体样本的更多细节。在头文件中带有 CMFormatDescription 前缀的函数一般可以用于所有的媒体类型,还有前缀为 CMVideoFormaDescriptionCMAuidoFormatDescription 的函数分别适用于获取视频和音频的细节。下面是使用 CMFormatDescription 来区别音频和视频数据的一个示例:

CMFormatDescriptionRef formatDescription = CMSampleBufferGetFormatDescription(sampleBuffer);
CMMediaType mediaType = CMFormatDescriptionGetMediaType(formatDescription);
if(mediaType == kCMMediaType_Video){
    CVPixelBufferRef pixelBuffer =   CMSampleBufferGetImageBuffer(sampleBuffer);
}else if(mediaType == kCMMediaType_Video){
    CMBlockBufferRef blockBuffer = CMSampleBufferGetDataBuffer(sampleBuffer);
}

时间信息

    CMSampleBuffer 还定义了关于媒体样本的时间信息。可以分别使用 CMSampleBufferGetPresentationTimeStamp 函数和 CMSampleBufferGetDecodeTimeStamp 函数提取时间信息来得到原始的表示时间戳和解码时间戳。

附加的元数据

     Core Media 还在 CMAttachment.h 中定义了一个 CMAttachment 形式的元数据协议。 其提供了读取和写入底层元数据的基础架构,比如可交互图片文件格式标签。

上一篇下一篇

猜你喜欢

热点阅读