如何定量测量源和显示之间的gstreamer H264延迟?

时间:2014-05-26 11:54:57

标签: gstreamer h.264 x264

我有一个项目,我们正在使用gstreamer,x264等,通过本地网络将视频流多播到多个接收器(连接到监视器的专用计算机)。我们在视频源(相机)系统和显示器上使用gstreamer。

我们使用RTP,有效负载96和libx264对视频流进行编码(无音频)。

但现在我需要量化(尽可能接近)帧采集和显示之间的延迟。

有没有人有使用现有软件的建议?

理想情况下,我希望能够运行测试软件几个小时,以生成足够的统计数据来量化系统。这意味着我无法进行一次性测试,例如将接收显示器的源摄像头指向显示高分辨率并手动计算差异......

我确实意识到使用纯软件解决方案,我无法量化视频采集延迟(即CCD到帧缓冲)。

我可以安排源和显示系统上的系统时钟同步到高精度(使用PTP),所以我将能够信任系统时钟(否则我将使用一些软件来跟踪它们之间的差异系统时钟并从测试结果中删除它。)

如果它有帮助,项目应用程序是用C ++编写的,所以我可以使用C事件回调(如果它们可用),考虑将系统时间嵌入到自定义标题中(例如,框架xyz,在TTT时刻编码 - 和在接收器上使用相同的信息来计算差异。)

3 个答案:

答案 0 :(得分:1)

我之前通过编写一个简单的应用程序来渲染序列号(比如mod 60)并将它们显示在屏幕上。然后,您可以将相机对准显示器,并让其中一台客户端计算机将该流呈现给第二台显示器。用手机拍照并查看两个数字来计算延迟。

答案 1 :(得分:1)

latency-clock项目引起了我的注意,我认为它提供了更好的解决方案!

它将当前时间的二进制表示形式嵌入图像缓冲区,并在解码时提取该二进制图像。

显然必须同步系统时钟!

答案 2 :(得分:0)

我有一个解决方案: 我写了一个gstreamer过滤器插件(基于插件模板),可以在捕获帧之前节省系统时间(并在视频缓冲区上做标记),然后再将其传递到H.264编码器和网络传输上。

在接收方,我找到了标记(它为我提供了20个索引中的1个)并再次记下系统时间。

我希望将索引关联起来并比较系统时间是一个相对简单的练习。只要两个系统的时钟合理地同步(或具有已知的差异),我就应该能够计算差异(即延迟)。

发件人和收件人的filter->source设置不同,以确定过滤器的计时行为。

/* chain function
 * this function does the actual processing
 */
static GstFlowReturn
gst_my_filter_chain (GstPad * pad, GstBuffer * buf)
{
  GstMyFilter *filter;
  struct timeval nowTimeval;
  guint8* data;
  int i,j,offset;

  filter = GST_MYFILTER (GST_OBJECT_PARENT (pad));

  if (filter->startTime == 0){
      filter->startTime = GST_BUFFER_TIMESTAMP(buf);
      gettimeofday(&filter->startTimeval, NULL);
      filter->startTimeUL = (filter->startTimeval.tv_sec*1e6 + filter->startTimeval.tv_usec)/1e3; // in milliseconds?
      filter->index = 0;

      GstCaps* caps;
      gint width, height;
      const GstStructure *str;

      caps = GST_BUFFER_CAPS(buf);
      str = gst_caps_get_structure (caps, 0);
      if (!gst_structure_get_int (str, "width", &width) ||
          !gst_structure_get_int (str, "height", &height)) {
        g_print ("No width/height available\n");
      } else {
        g_print ("The video size of this set of capabilities is %dx%d\n",
               width, height);  
        filter->width=width;
        filter->height=height;
      }
  }

  gettimeofday(&nowTimeval, NULL);
  unsigned long timeNow = (nowTimeval.tv_sec*1e6 + nowTimeval.tv_usec)/1e3; // in milliseconds?

  if (filter->silent == FALSE){
    fprintf(filter->ofp, "%20lu,",
            timeNow);
  }

    data = GST_BUFFER_DATA(buf);
    if (filter->source){
      offset = filter->index % 20;
      for (i = 0; i < 10; i++){
          for (j = 0; j < 10; j++){
              data[(i+20)*filter->width+(j+offset*10)*1]=23;
          }
      }
        fprintf(filter->ofp, " %u", offset);
    } else {
        unsigned long avg;
        unsigned int min=(unsigned int)(-1UL);
        unsigned int minpos=0;
        int k=0;

        for (k=0; k < 20; k++){
            avg=0;
            i=5; // in the middle of the box row
            for (j = 0; j < 10; j++){
              avg += data[(i+20)*filter->width+(j+k*10)*1];
            }
            if (avg < min){
                min = avg;
                minpos=k;
            }
        }
        fprintf(filter->ofp, " %u", minpos);
    }

    fprintf(filter->ofp, "\n");

  filter->index++;

  /* just push out the incoming buffer without touching it */
  return gst_pad_push (filter->srcpad, buf);
}

用法如下: 发件人/服务器:

GST_DEBUG="*:2"  gst-launch-0.10 -v --gst-plugin-path=../../src/.libs  videotestsrc num-buffers=100 ! myfilter src=1 ! x264enc tune=zerolatency,speed-preset=fast ! rtph264pay ! udpsink port=3000 host=127.0.0.1

接收人/客户:

GST_DEBUG="*:2"  gst-launch-0.10 -v --gst-plugin-path=../../src/.libs udpsrc port=3000 ! "application/x-rtp, media=(string)video, encoding-name=(string)H264, payload=(int)96" ! gstrtpjitterbuffer do-lost=true !  rtph264depay  ! ffdec_h264 ! myfilter src=0 ! ffmpegcolorspace ! ximagesink

显然,在测试实现中我不会使用localhost(127.0.0.1)!!

我使用--gst-plugin-path,因为我没有安装时间过滤器。

该项目要求延迟尽可能小 - 理想情况下为100毫秒或更短。现在有了一些数字,我可以开始微调所需的参数,以最大限度地减少延迟。