WebRTC视频码率控制(二)—— QP检测

2023-10-27

WebRTC在视频编码过程中会进行QP检测,目的是让视频质量维持在可接受范围的前提下,调节整体视频表现,如分辨率、帧率。这里要注意的是,QP检测机制只是利用QP分析结果对分辨率、帧率进行调节,并不对编码QP做直接调整。说句题外话,通常编码器也不会对外提供QP设置接口,QP主要是由帧率、码率、复杂度等因素计算得到,这部分内容将会另写文章分享。

QP检测的主体代码在quality_scaler.cc的QualityScaler类中,后者作为observer注册到VideoStreamEncoder中,VideoStreamEncoder内完成了相关流程的控制。

1.初始化与配置

与CPU使用度检测类似,初始化过程发生在编码器重新创建的时候(流初始化,或者编码格式变化):

void VideoStreamEncoder::ReconfigureEncoder() {
  // ...
  ConfigureQualityScaler(info);
}
​
void VideoStreamEncoder::ConfigureQualityScaler(
    const VideoEncoder::EncoderInfo& encoder_info) {
  RTC_DCHECK_RUN_ON(&encoder_queue_);
  const auto scaling_settings = encoder_info.scaling_settings;
  // 允许进行QP检测的主要条件是,degradation_preference允许调整分辨率
  // 换句话说,摄像头流允许,而共享屏幕不允许。
  const bool quality_scaling_allowed =
      IsResolutionScalingEnabled(degradation_preference_) &&
      scaling_settings.thresholds;
​
  if (quality_scaling_allowed) {
    if (quality_scaler_ == nullptr) {
      //...
      AdaptationObserverInterface* observer = this;
      quality_scaler_ = std::make_unique<QualityScaler>(
          &encoder_queue_, observer,
          experimental_thresholds ? *experimental_thresholds
                                  : *(scaling_settings.thresholds));
      has_seen_first_significant_bwe_change_ = false;
      initial_framedrop_ = 0;
    }
  } else {
    quality_scaler_.reset(nullptr);
    initial_framedrop_ = kMaxInitialFramedrop;
  }
  // ...
}

经过初始化后,QP阈值的下限、上限默认分别为:24、37。

2.检测的开启与终止

在QualityScaler构造时开启检测,在所创建的线程中默认每2秒检测一次:

QualityScaler::QualityScaler(rtc::TaskQueue* task_queue,
                             AdaptationObserverInterface* observer,
                             VideoEncoder::QpThresholds thresholds,
                             int64_t sampling_period_ms) {
  // ...
  check_qp_task_ = RepeatingTaskHandle::DelayedStart(
    task_queue->Get(), TimeDelta::ms(GetSamplingPeriodMs()), [this]() {
      CheckQp();
      return TimeDelta::ms(GetSamplingPeriodMs());
    });
  // ...
}

与此相应,在QualityScaler析构时终止检测:

QualityScaler::~QualityScaler() {
  RTC_DCHECK_RUN_ON(&task_checker_);
  check_qp_task_.Stop();
}

3.样本数据采集

每帧编码结束后,都会记录QP。这里的QP指的是帧级QP,准确地说是指last_slice_qp,当为单Slice编码时,二者相同。

// 传入回调参数EncodedImage中携带的QP
VideoStreamEncoder::RunPostEncode(EncodedImage encoded_image,
                                  int64_t time_sent_us, ...) {
  // ...
    if (quality_scaler_ && encoded_image.qp_ >= 0)
      quality_scaler_->ReportQp(encoded_image.qp_, time_sent_us);
  // ...
}
​
void QualityScaler::ReportQp(int qp, int64_t time_sent_us) {
  // ...
  average_qp_.AddSample(qp);
  if (qp_smoother_high_)
    qp_smoother_high_->Add(qp, time_sent_us);
  if (qp_smoother_low_)
    qp_smoother_low_->Add(qp, time_sent_us);
}

4.计算过程

由上可知,QP检测到后,分别被添加到三个数据集 average_qp、qp_smoother_high、qp_smoother_low_ 中,在样本数据添加后立即完成滤波计算。其中average_qp使用滑窗滤波rtc::MovingAverage,qp_smoother_high和qp_smoother_low_ 使用指数滤波rtc::ExpFilter,均起到平滑数据的作用。

5.反馈调节

在定时检测中完成反馈:

void QualityScaler::CheckQp() {
  // ...
    // Check if we should scale up or down based on QP.
  const absl::optional<int> avg_qp_high =
      qp_smoother_high_ ? qp_smoother_high_->GetAvg()
                        : average_qp_.GetAverageRoundedDown();
  const absl::optional<int> avg_qp_low =
      qp_smoother_low_ ? qp_smoother_low_->GetAvg()
                       : average_qp_.GetAverageRoundedDown();
  if (avg_qp_high && avg_qp_low) {
    if (*avg_qp_high > thresholds_.high) {
      ReportQpHigh();
      return;
    }
    if (*avg_qp_low <= thresholds_.low) {
      // QP has been low. We want to try a higher resolution.
      ReportQpLow();
      return;
    }
  }
}
​
// 当QP过低时,通过AdaptUp对编码进行升级
void QualityScaler::ReportQpLow() {
  // ...
  observer_->AdaptUp(AdaptationObserverInterface::AdaptReason::kQuality);
  // ...
}
​
// 当QP过高时,通过AdaptDown对编码进行降级
void QualityScaler::ReportQpHigh() {
  // ...
  if (observer_->AdaptDown(
          AdaptationObserverInterface::AdaptReason::kQuality)) {
    ClearSamples();
  } else {
    adapt_failed_ = true;
  }
  // ...
}

原文链接:WebRTC视频码率控制(二)-- QP检测

★文末名片可以免费领取音视频开发学习资料,内容包括(FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,srs)以及音视频学习路线图等等。

见下方!↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

WebRTC视频码率控制(二)—— QP检测 的相关文章

  • 使用 Java 的 Apache Http 摘要身份验证

    我目前正在开发一个 Java 项目 但无法使 http 摘要身份验证正常工作 我尝试使用 Apache 网站 但没有帮助 我有一个需要 HTTP 摘要身份验证的网站 DefaultHttpClient httpclient new Defa
  • java中监视目录变化

    我正在使用 WatchService 来监视目录中的更改 特别是目录中新文件的创建 下面是我的代码 package watcher import java nio file import static java nio file Stand
  • Java Logger 未记录到 Netbeans 中的输出

    我正在 Netbeans 中使用 Maven 启动一个 Java 项目 我编写了一些代码来使用 Logger 类进行日志记录 但是 日志记录似乎不起作用 在程序开始时 我运行 Logger getLogger ProjectMainClas
  • java.lang.ClassNotFoundException:javax.mail.MessagingException

    我想使用 eclipse 将电子邮件从我的 gmail 帐户发送到另一个邮件帐户 我使用 apache tomcat 7 0 34 作为我的 Web 服务器 并使用端口 8080 作为 apache 服务器 HTTP 1 1 并使用 JRE
  • Java 的支持向量机?

    我想用Java编写一个 智能监视器 它可以随时发出警报detects即将到来的性能问题 我的 Java 应用程序正在以结构化格式将数据写入日志文件
  • Thymeleaf 3 Spring 5 映射加载字符串而不是 HTML

    我正在尝试将 Spring 5 和 Thymeleaf 3 一起配置 我正在 Eclipse 上工作 我使用 全新安装 构建并使用 springboot run 运行应用程序 我已经设置了一个控制器和几个模板 但 Thymeleaf 似乎找
  • 如何在 JPQL 或 HQL 中进行限制查询?

    在 Hibernate 3 中 有没有办法在 HQL 中执行相当于以下 MySQL 限制的操作 select from a table order by a table column desc limit 0 20 如果可能的话 我不想使用
  • java inputstream 打印控制台内容

    sock new Socket www google com 80 out new BufferedOutputStream sock getOutputStream in new BufferedInputStream sock getI
  • 提供节点名或服务名,或未知 Java

    最近我尝试运行我的 Java 项目 每当我运行它并将其打开到我得到的服务器地址时 Unable to determine host name java net UnknownHostException Caused by java net
  • 在 Java 中如何找出哪个对象打开了文件?

    我需要找出答案哪个对象在我的 Java 应用程序中打开了一个文件 这是为了调试 因此欢迎使用工具或实用程序 如果发现哪个对象太具体了 这class也会很有帮助 这可能很棘手 您可以从使用分析器开始 例如VisualVM http visua
  • 如何检查某个元素是否存在于一组项目中?

    In an ifJava中的语句如何检查一个对象是否存在于一组项目中 例如 在这种情况下 我需要验证水果是苹果 橙子还是香蕉 if fruitname in APPLE ORANGES GRAPES Do something 这是一件非常微
  • 将非 Android 项目添加到 Android 项目

    我在 Eclipse 中有三个项目 Base Server 和 AndroidClient Base和Server是Java 1 7项目 而AndroidClient显然是一个android项目 基础项目具有在服务器和 Android 客户
  • Android 无法解析日期异常

    当尝试解析发送到我的 Android 客户端的日期字符串时 我得到一个无法解析的日期 这是例外 java text ParseException 无法解析的日期 2018 09 18T00 00 00Z 位于 偏移量 19 在 java t
  • 如何将 HTML 链接放入电子邮件正文中?

    我有一个可以发送邮件的应用程序 用 Java 实现 我想在邮件中放置一个 HTML 链接 但该链接显示为普通字母 而不是 HTML 链接 我怎样才能将 HTML 链接放入字符串中 我需要特殊字符吗 太感谢了 Update 大家好你们好 感谢
  • Java Swing - 如何禁用 JPanel?

    我有一些JComponents on a JPanel我想在按下 开始 按钮时禁用所有这些组件 目前 我通过以下方式显式禁用所有组件 component1 setEnabled false 但是有什么办法可以一次性禁用所有组件吗 我尝试禁用
  • 使用 HtmlUnit 定位弹出窗口

    我正在构建一个登录网站并抓取一些数据的程序 登录表单是一个弹出窗口 所以我需要访问这个www betexplorer com网站 在页面的右上角有一个登录链接 写着 登录 我单击该链接 然后出现登录弹出表单 我能够找到顶部的登录链接 但找不
  • 列表过滤器内的 Java 8 lambda 列表

    示例 JSON id 1 products id 333 status Active id 222 status Inactive id 111 status Active id 2 products id 6 status Active
  • java 中的蓝牙 (J2SE)

    我是蓝牙新手 这就是我想做的事情 我想获取连接到我的电脑上的蓝牙的设备信息并将该信息写入文件中 我应该使用哪个 api 以及如何实现 我遇到了 bluecove 但经过几次搜索 我发现 bluecove 不能在 64 位电脑上运行 我现在应
  • Android View Canvas onDraw 未执行

    我目前正在开发一个自定义视图 它在画布上绘制一些图块 这些图块是从多个文件加载的 并将在需要时加载 它们将由 AsyncTask 加载 如果它们已经加载 它们只会被绘制在画布上 这工作正常 如果加载了这些图片 AsyncTask 就会触发v
  • java'assert'和'if(){}else exit;'之间的区别

    java和java有什么区别assert and if else exit 我可以用吗if else exit代替assert 也许有点谷歌 您应该记住的主要事情是 if else 语句应该用于程序流程控制 而assert 关键字应该仅用于

随机推荐

  • Linux操作系统之僵尸进程

    文章目录 一 什么是僵尸进程 二 僵尸进程带来的危害 三 如何解决僵尸进程 四 什么是孤儿进程 一 什么是僵尸进程 子进程先于父进程节结束 父进程没有调用wait 获取子进程的退出码 子进程此时变为僵尸进程 在每个进程退出时 内核释放所有资
  • 阿里云 linux 的nginx 配置uni-app的H5前端项目vue,后端接口阿里云。

    背景 vue项目调用接口是阿里云的 H5网站也要部署到阿里云 2个不同的服务器 需要做nginx部署与api代理 1 端口配置 首先当然是买个阿里云服务器 这里是配置是linux系统 配置访问的域名 再接着 给网站配置需要的端口 如下 配置
  • 解决Windows系统缺少MCRecvSrc.dll文件的问题

    其实很多用户玩单机游戏或者安装软件的时候就出现过这种问题 如果是新手第一时间会认为是软件或游戏出错了 其实并不是这样 其主要原因就是你电脑系统的该dll文件丢失了或没有安装一些系统软件平台所需要的动态链接库 这时你可以下载这个MCRecvS
  • 国外it的一些学习网站

    1 国外有什么好的网站推荐 https blog csdn net AndroidCC article details 55223971 2 一些比较好的国外IT网站 https blog csdn net fzy1017692329 ar
  • Matlab中dir函数使用小技巧

    想必很多小伙伴在matlab中对文件进行批处理时经常会使用dir函数吧 dir函数用于列出文件夹中的内容 使用语法如下 Matlab dir 列出当前文件夹中的文件和文件夹 当然调用方式也可以是listing dir dir name 列出
  • 用JAVA实现停车场管理系统

    该程序使用ArrayList存储停车记录 并通过switch case语句实现菜单选择功能 主要功能包括 停车 输入车牌号和进入时间 自动分配停车位编号 结算 根据停车位编号计算停车费用 计费标准为停车时长 秒 乘以每秒费用0 05元 同时
  • Qt实战 无边框窗口的实现

    本次分享 是基于Qt实现了无边框的窗口 并支持拖动缩放 最大化 最小化 关闭 双击全屏等 实现无边框其实很简单 一行代码搞定 setWindowFlag Qt FramelessWindowHint 但是 隐藏了窗口的默认边框 标题栏没了
  • Finalshell上传文件失败或者进度总为百分之零解决方法

    1 首先连接主机 然后切换到root用户 2 然后右键当前窗口的窗口名 选复制标签 3 然后再右键第一个窗口的窗口名 选断开 或者直接关闭第一个窗口 4 之后你就可以在第二个窗口正常上传文件了
  • Linux专栏(一):VMware的下载与安装

    文章目录 1 背景 2 下载VMware虚拟机 1 背景 想要学习Linux系统但又不想经历安装双系统复杂的操作 可以试试虚拟机方案 只是虚拟机方案不可以调用GPU就非常的无语 作为初学者学习还是非常不错的 注意 倘若真正转入Linux系统
  • CSS 元素垂直居中的 6种方法

    转自 http blog zhourunsheng com 2012 03 css E5 85 83 E7 B4 A0 E5 9E 82 E7 9B B4 E5 B1 85 E4 B8 AD E7 9A 84 6 E7 A7 8D E6 9
  • java基础-特性、版本、环境搭建、开发工具

    Java基础 java特性 Java三大版本 JDK JRE JVM java开发环境搭建 jdk下载与安装 环境变量配置 jdk目录介绍 hello world java程序运行机制 idea安装 idea快捷键 idea优化 百度 id
  • 博客搭建过程

    博客地址 baiyang796 top 系统 centos7 httpd PHP 7 2 mysql 5 7 wordpress 一 httpd yum y install httpd yum y install httpd manual
  • 【arduino】【hx7111】电压转换芯片(压力)

    arduino hx7111 电压转换芯片 压力 1 百度百科时间 HX711是一款专为高精度电子秤而设计的24位A D转换器芯片 与同类型其它芯片相比 该芯片集成了包括稳压电源 片内时钟振荡器等其它同类型芯片所需要的外围电路 具有集成度高
  • 去水印最新教程

    一 封装一个函数来识别要解析的类型 获取类型 get type if this url match http s v douyin com null console log 识别到 dy 链接 return dy else if this
  • Date、DateFormat、Calendar日期类

    目录 1 Date 2 DateFormat 3 Calendar 1 Date 1 所在位置 java util Date 2 两种创建对象的方法 如果调用空参构造创建对象那么对象为当前的时间 如果调用有参构造 参数是一个long类型代表
  • Java中的加号+

    在 Java 中 加号 有两个作用 进行加法运算 字符串拼接 那 如何区分代码中的 是起什么作用呢 当 左右两边操作数至少有一个为字符串时 起到字符串拼接的作用 此时若要进行数值型的运算需要加括号 当 左右两边操作数都是数值型时 使用 就进
  • html打印页面去掉页眉页脚

    去掉页脚或者页眉 核心代码
  • 深入浅出DDR系列(一)—— DDR原理

    版权声明 本文为CSDN博主 奇小葩 的原创文章 遵循CC 4 0 BY SA版权协议 转载请附上原文出处链接及本声明 原文链接 https blog csdn net u012489236 article details 10773073
  • 【从零开始的Java开发】2-8-2 CSS入门:CSS选择器、样式

    文章目录 CSS简介 CSS基础 CSS选择器 背景设置 使用外部样式表 样式 文本类样式 字体类样式 列表样式 伪类样式 CSS其他选择器 CSS选择器的优先级 CSS简介 CSS 即Cascading Style Sheets 层叠 样
  • WebRTC视频码率控制(二)—— QP检测

    WebRTC在视频编码过程中会进行QP检测 目的是让视频质量维持在可接受范围的前提下 调节整体视频表现 如分辨率 帧率 这里要注意的是 QP检测机制只是利用QP分析结果对分辨率 帧率进行调节 并不对编码QP做直接调整 说句题外话 通常编码器