Chromium源码中 media::VideoFrame 的3个属性(coded_size, visible_rect, natual_size)的理解

前段时间处理过一例在Chrome中视频虚拟背景图显示范围不正确的问题,在阅读Chromium源码并结合一些试验后,这里简单记录一下media::VideoFrame这个类其中的与此次问题排查相关的三个属性的含义。

media::VideoFrame的代码位于 media\base\video_frame.h(.cc),下面代码摘抄自其中(Chromium 85,branch 4183):

  // The full dimensions of the video frame data.
  const gfx::Size& coded_size() const { return layout_.coded_size(); }
  
  // A subsection of [0, 0, coded_size().width(), coded_size.height()]. This
  // can be set to "soft-apply" a cropping. It determines the pointers into
  // the data returned by visible_data().
  const gfx::Rect& visible_rect() const { return visible_rect_; }
  
  // Specifies that the |visible_rect| section of the frame is supposed to be
  // scaled to this size when being presented. This can be used to represent
  // anamorphic frames, or to "soft-apply" any custom scaling.
  const gfx::Size& natural_size() const { return natural_size_; }

OK,从注释的字面意思上看:

  • coded_size表示的是视频帧数据的全尺寸。
  • visible_rect是(0,0,coded_size.width,coded_size.height)这个显示区域的子范围(也可能是全部显示范围)。
  • natural_size表示的是视频帧按照visible_rect设置的呈现范围来缩放后的大小

我翻译的可能有点抽象,我来举个例子说明一下。

假设我们在web上通过 getUserMedia 请求的视频分辨率是 640x480:

const constraints = {
  video: {
    width: 640,
    height: 480,
    frameRate: 25
  }
}
navigator.mediaDevices.getUserMedia(constraints).then(...).catch(...);

通常情况下,media::VideoFrame的这三个属性就是:

  • coded_size : width=640, height=480
  • visible_rect : 0, 0, 640, 480
  • natural_size : width=640, height=480

OK,这个时候,似乎coded_size和natural_size一样没有什么区别。但是情况不总是这样,我们换一台摄像头,也许情况就变成了这样:

  • coded_size : width=864, height=480
  • visible_rect : 112, 0, 640, 480
  • natural_size : width=640, height=480

看明白了吗?如果没有的话,我画一张图:
在这里插入图片描述
正常情况下,我们从网页上请求640x480,Chromium采集到的原始视频帧就是640x480。但情况不总是这样,因为还要受到其他的采集属性(如颜色空间、帧率等)的影响,Chromium会根据情况,采集一个大等于你希望显示的视频宽高,然后再裁出用户期望的大小。因此,上面的图中,就很好的说明了这种关系。

OK,上面我们看到,natural_size的大小和visible_rect的大小是相同的,还有一些情况下,这两个是不同的,例如:

  • coded_size : width=1920, height=1080
  • visible_rect : 240, 0, 1440, 1080
  • natural_size : width=1280, height=960

这个时候情况就变成了这样:

在这里插入图片描述
什么意思呢?就是当你在网页上请求的视频宽高是 1280x960(这是一个4:3的显示比例),实际上Chromium会从摄像头按照1920x1080采集(这是一个16:9的显示比例),然后显示范围锁定在 (240,0, 1440, 1080) 这个区域内(1440x1080与目标分辨率1280x960的比例相同,都是4:3),最后进行缩放,由1440x1080缩放为1280x960去显示。

相信看到这里,media::VideoFrame的这三个属性的关系应该非常清楚了。不过,这个只是Chromium的做法,我发现在不同浏览器上的处理方法有所不同,例如使用相同的摄像头,相同的测试网页,在Chrome和Safari上,展现出来的摄像头显示范围是不同的,猜测Safari内部又是另外一种处理逻辑了,咱没有它的源码,无法给出科学的解释了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值