AV Foundation ⑯ 视频处理与CMSampleBuffer

视频处理

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

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

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

  • captureOutput:didOutputSampleBuffer:fromConnection:

    每当有一个新的视频帧写入时该方法就会被调用。数据会基于视频数据输出的 videoSettings 属性进行解码或重新编码

  • captureOutput:didDropSampleBuffer:fromConnection:

    每当有一个迟到的视频帧被丢弃时该方法就会被调用。通常是因为在 didOutputSampleBuffer 调用中消耗了太多处理时间就会调用该方法。

    这两个方法最重要的参数与 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 形式的元数据协议。 其提供了读取和写入底层元数据的基础架构,比如可交互图片文件格式标签。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,753评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,668评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,090评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,010评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,054评论 6 395
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,806评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,484评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,380评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,873评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,021评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,158评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,838评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,499评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,044评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,159评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,449评论 3 374
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,136评论 2 356

推荐阅读更多精彩内容