如何定量测量源和显示器之间的gstreamer H264延迟?
我有一个项目,我们正在使用gstreamer、x264等,通过本地网络将视频流多播到多个接收器(连接到监视器的专用计算机)。我们在视频源(摄像头)系统和显示器上都使用gstreamer 我们使用RTP、payload 96和libx264对视频流进行编码(无音频) 但现在我需要量化帧采集和显示之间(尽可能接近)的延迟 是否有人建议使用现有软件 理想情况下,我希望能够运行测试软件几个小时,以生成足够的统计数据来量化系统。这意味着我不能做一次性测试,比如将源摄像机指向显示高分辨率的接收显示监视器,然后手动计算差值 我确实意识到,使用纯软件解决方案,我将无法量化视频采集延迟(即CCD到帧缓冲区) 我可以安排源系统和显示系统上的系统时钟以高精度同步(使用PTP),因此我将能够信任系统时钟(否则我将使用一些软件跟踪系统时钟之间的差异,并将其从测试结果中删除)如何定量测量源和显示器之间的gstreamer H264延迟?,gstreamer,h.264,x264,Gstreamer,H.264,X264,我有一个项目,我们正在使用gstreamer、x264等,通过本地网络将视频流多播到多个接收器(连接到监视器的专用计算机)。我们在视频源(摄像头)系统和显示器上都使用gstreamer 我们使用RTP、payload 96和libx264对视频流进行编码(无音频) 但现在我需要量化帧采集和显示之间(尽可能接近)的延迟 是否有人建议使用现有软件 理想情况下,我希望能够运行测试软件几个小时,以生成足够的统计数据来量化系统。这意味着我不能做一次性测试,比如将源摄像机指向显示高分辨率的接收显示监视器,然
如果它有帮助,项目应用程序是用C++编写的,所以我可以使用C事件回调(如果它们可用),考虑将系统时间嵌入到自定义的报头(例如,帧XYZ中,在TTT时间编码),并在接收器上使用相同的信息来计算差异。 我编写了一个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 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插件路径
,因为我还没有安装定时过滤器
该项目需要尽可能小的延迟-理想情况下为100ms或更短。现在有了一些数字,我就可以开始微调所需的参数,以最小化延迟。我以前写过一个简单的应用程序来呈现序列号(比如mod 60)并将其显示在屏幕上。然后,您可以将相机指向监视器,并让一台客户端计算机将该流渲染到第二台监视器。用你的手机拍张照片,看看这两个数字来计算你的延迟。这个项目已经引起了我的注意,我认为它提供了一个更好的解决方案 它将当前时间的二进制表示嵌入到图像缓冲区中,并在解码时提取该二进制图像 显然,系统时钟必须同步 原则上,这是进行全屏幕对屏幕计时测试的最佳方法(至少是为了获得整体帧中的差异)。但是,您必须能够将源屏幕和接收器屏幕放在同一视野中。在我的配置中,这是不可能的-演示观看室离摄像系统有几米远。
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