You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GStreamer appsink设置drop=true时CPU负载过高问题求解

GStreamer appsink设置drop=true时CPU负载异常升高

问题描述

使用GStreamer的appsink组件时,设置drop=true参数后CPU负载异常升高。
以下Pipeline可正常运行:

gst-launch-1.0 -v rtspsrc location="rtsp://somelink" latency=300 ! rtph265depay ! h265parse ! avdec_h265 ! videoconvert !  appsink caps="video/x-raw,format=BGR"

上述Pipeline使用默认配置的appsink时运行正常,一旦为appsink添加drop=true配置,CPU负载会大幅升高,单核CPU占用可达100%。

源码排查

查阅appsink源码,drop逻辑相关代码如下:

if (priv->drop) {
  GstMiniObject *old;

  /* we need to drop the oldest buffer/list and try again */
  if ((old = dequeue_buffer (appsink))) {
    GST_DEBUG_OBJECT (appsink, "dropping old buffer/list %p", old);
    gst_mini_object_unref (old);
  }
}

进一步查看dequeue_buffer函数的实现:

static GstMiniObject *
dequeue_buffer (GstAppSink * appsink)
{
  GstMiniObject *obj;

  do {
    obj = dequeue_object (appsink);

    if (GST_IS_BUFFER (obj) || GST_IS_BUFFER_LIST (obj)) {
      break;
    }

    gst_mini_object_unref (obj);
  } while (TRUE);

  return obj;
}

函数内存在while (TRUE)循环逻辑,高度怀疑这是导致CPU占用过高的原因,暂未找到有效调试方法,希望确认是否有同类问题的可行解决方案。


回答

根因分析

你观察到的while(TRUE)循环确实是CPU占满的直接原因,本质是配置缺失叠加旧版本代码缺陷共同导致:

  • 配置逻辑问题:appsink的drop=true丢帧逻辑只有在内部缓冲区队列达到max-buffers阈值时才会触发,未配置max-buffers时该参数默认值为0,代表队列无长度上限,此时drop逻辑本身不会按预期丢弃旧帧,但每次新buffer入队都会触发队列检查流程。
  • 旧版本自旋bug:1.16版本之前的GStreamer中,dequeue_buffer函数在队列内没有可取出的有效buffer(队列空、或队列头部全是流事件/EOS事件等非buffer对象)时,dequeue_object会直接返回NULL,循环不会做任何等待直接进入下一轮调用,形成无意义的CPU空转,直接占满单个CPU核心。
  • 触发条件放大:如果应用层拉取appsink帧的速度慢于解码输出速度,队列内事件和buffer的排布会大幅提升空转逻辑的触发概率。

解决方案

按落地成本从低到高排序:

  • 优先补充max-buffers配置:根据帧处理延迟将该值设为1~3即可,配置后队列达到长度阈值才会触发丢帧,不会出现无意义的空队列检查,绝大多数场景下可直接解决问题,修改后pipeline的appsink片段示例如下:
    appsink caps="video/x-raw,format=BGR" drop=true max-buffers=2
    
  • 升级GStreamer版本:如果当前使用版本低于1.16,升级到1.16及以上稳定版即可,官方已在该版本修复dequeue_buffer的自旋问题,取不到buffer时会进入条件变量等待,不会空转占用CPU。
  • 优化消费逻辑:检查应用层的帧拉取代码,不要在appsink的sample拉取线程中执行耗时的图像处理、磁盘/网络IO操作,这类逻辑要放到独立工作线程执行,避免阻塞appsink的流式调度线程,减少队列堆积概率。
  • 临时规避方案:如果暂时无法升级版本或调整业务逻辑,可以去掉appsink的drop=true配置,在appsink前插入带下游丢帧能力的queue元素实现相同效果,规避appsink的逻辑bug,对应pipeline片段示例如下:
    ! queue leaky=downstream max-size-buffers=2 ! appsink caps="video/x-raw,format=BGR"
    

内容的提问来源于stack exchange,提问作者Felix F Xu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 05:18:20