草庐IT

AV Foundation ⑯ 视频处理与CMSampleBuffer

_涼城 2023-03-28 原文

视频处理

    使用 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 形式的元数据协议。 其提供了读取和写入底层元数据的基础架构,比如可交互图片文件格式标签。

有关AV Foundation ⑯ 视频处理与CMSampleBuffer的更多相关文章

  1. ruby - 如何指定 Rack 处理程序 - 2

    Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

  2. 动漫制作技巧如何制作动漫视频 - 2

    动漫制作技巧是很多新人想了解的问题,今天小编就来解答与大家分享一下动漫制作流程,为了帮助有兴趣的同学理解,大多数人会选择动漫培训机构,那么今天小编就带大家来看看动漫制作要掌握哪些技巧?一、动漫作品首先完成草图设计和原型制作。设计草图要有目的、有对象、有步骤、要形象、要简单、符合实际。设计图要一致性,以保证制作的顺利进行。二、原型制作是根据设计图纸和制作材料,可以是手绘也可以是3d软件创建。在此步骤中,要注意的问题是色彩和平面布局。三、动漫制作制作完成后,加工成型。完成不同的表现形式后,就要对设计稿进行加工处理,使加工的难易度降低,并得到一些基本准确的概念,以便于后续的大样、准确的尺寸制定。四、

  3. python ffmpeg 使用 pyav 转换 一组图像 到 视频 - 2

    2022/8/4更新支持加入水印水印必须包含透明图像,并且水印图像大小要等于原图像的大小pythonconvert_image_to_video.py-f30-mwatermark.pngim_dirout.mkv2022/6/21更新让命令行参数更加易用新的命令行使用方法pythonconvert_image_to_video.py-f30im_dirout.mkvFFMPEG命令行转换一组JPG图像到视频时,是将这组图像视为MJPG流。我需要转换一组PNG图像到视频,FFMPEG就不认了。pyav内置了ffmpeg库,不需要系统带有ffmpeg工具因此我使用ffmpeg的python包装p

  4. TimeSformer:抛弃CNN的Transformer视频理解框架 - 2

    Transformers开始在视频识别领域的“猪突猛进”,各种改进和魔改层出不穷。由此作者将开启VideoTransformer系列的讲解,本篇主要介绍了FBAI团队的TimeSformer,这也是第一篇使用纯Transformer结构在视频识别上的文章。如果觉得有用,就请点赞、收藏、关注!paper:https://arxiv.org/abs/2102.05095code(offical):https://github.com/facebookresearch/TimeSformeraccept:ICML2021author:FacebookAI一、前言Transformers(VIT)在图

  5. Ruby-vips 图像处理库。有什么好的使用示例吗? - 2

    我对图像处理完全陌生。我对JPEG内部是什么以及它是如何工作一无所知。我想知道,是否可以在某处找到执行以下简单操作的ruby​​代码:打开jpeg文件。遍历每个像素并将其颜色设置为fx绿色。将结果写入另一个文件。我对如何使用ruby​​-vips库实现这一点特别感兴趣https://github.com/ender672/ruby-vips我的目标-学习如何使用ruby​​-vips执行基本的图像处理操作(Gamma校正、亮度、色调……)任何指向比“helloworld”更复杂的工作示例的链接——比如ruby​​-vips的github页面上的链接,我们将不胜感激!如果有ruby​​-

  6. ruby - Faye WebSocket,关闭处理程序被触发后重新连接到套接字 - 2

    我有一个super简单的脚本,它几乎包含了FayeWebSocketGitHub页面上用于处理关闭连接的内容:ws=Faye::WebSocket::Client.new(url,nil,:headers=>headers)ws.on:opendo|event|p[:open]#sendpingcommand#sendtestcommand#ws.send({command:'test'}.to_json)endws.on:messagedo|event|#hereistheentrypointfordatacomingfromtheserver.pJSON.parse(event.d

  7. ruby - 如何使用 Ruby HTTP::Net 处理 404 错误? - 2

    我正在尝试解析网页,但有时会收到404错误。这是我用来获取网页的代码:result=Net::HTTP::getURI.parse(URI.escape(url))如何测试result是否为404错误代码? 最佳答案 像这样重写你的代码:uri=URI.parse(url)result=Net::HTTP.start(uri.host,uri.port){|http|http.get(uri.path)}putsresult.codeputsresult.body这将打印状态码和正文。

  8. ruby-on-rails - 使用 Ruby 正确处理 Stripe 错误和异常以实现一次性收费 - 2

    我查看了Stripedocumentationonerrors,但我仍然无法正确处理/重定向这些错误。基本上无论发生什么,我都希望他们返回到edit操作(通过edit_profile_path)并向他们显示一条消息(无论成功与否)。我在edit操作上有一个表单,它可以POST到update操作。使用有效的信用卡可以正常工作(费用在Stripe仪表板中)。我正在使用Stripe.js。classExtrasController5000,#amountincents:currency=>"usd",:card=>token,:description=>current_user.email)

  9. ruby - 如何更改此正则表达式以从未指定 v 参数的 Youtube URL 获取 Youtube 视频 ID? - 2

    目前我正在使用这个正则表达式从YoutubeURL中提取视频ID:url.match(/v=([^&]*)/)[1]我怎样才能改变它,以便它也可以从这个没有v参数的YoutubeURL获取视频ID:http://www.youtube.com/user/SHAYTARDS#p/u/9/Xc81AajGUMU感谢阅读。编辑:我正在使用ruby​​1.8.7 最佳答案 对于Ruby1.8.7,这就可以了。url_1='http://www.youtube.com/watch?v=8WVTOUh53QY&feature=feedf'url

  10. ruby-on-rails - Rails 处理 .Erb 与 Nils - 2

    当profile为nil时,总是让我感到悲伤...我该怎么办? 最佳答案 在View中使用变量之前,始终检查变量是否为nil。我确信这个问题有更优雅的解决方案,但这应该能让您入门。 关于ruby-on-rails-Rails处理.Erb与Nils,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/2709605/

随机推荐