zl程序教程

您现在的位置是:首页 >  其他

当前栏目

视频播放器——外部时钟源同步

同步 视频 外部 播放器 时钟
2023-09-14 09:05:28 时间

获取视频时钟

  • 获取视频时钟,首先要获取视频帧的显示时间戳pts;在AVFrame结构体中,有一成员变量为best_effort_timestamp,该变量是 单位为数据流时间基的帧时间戳,官方解释如下:

  • frame timestamp estimated using various heuristics, in stream time base
    
    encoding: unused
    decoding: set by libavcodec, read by use

获取到该时间戳后,再将其单位由数据流时间基转换为正常时间;这里的时间基是使用AVRational结构提描述的,即分子—分母式的描述方式;这里使用 av_q2d() 函数对其进行转换,将AVRational描述的时间基转换为正常时间基。

具体流程如下:

/*pFrameRaw为解码后的YUV数据(AVFrame)*/
pFrameRaw->pts = pFrameRaw->best_effort_timestamp;
frame_pts_lf   = pFrameRaw->pts * av_q2d(pFormatCtx->streams[video_index]->time_base); 
frame_pts_ld   = frame_pts_lf * 1000;	//转换为以微妙为单位

获取外部时钟

外部时钟主要依赖于 av_gettime() 函数,官方解释如下:

Get the current time in microseconds.

通过获取从视频开始播放时的时间作为基准,就能获取到每一帧视频帧播放时,外部时钟实际度过的时间。

修正帧持续时间

知道了视频时钟和外部时钟,如果视频帧时间戳能严格与外部时钟同步,那么视频播放就能按照预定帧率、预定时长去进行。

在每一次视频帧显示前,都计算该视频帧时间戳与外部时钟的差值,通过该差值去动态校准该帧的持续时间,从而使得下一视频帧时间戳与外部时钟的差值越来越小。

根据该系统的实现要求,引入了增量式PID算法来消除视频帧时间戳与外部时钟的差值

获取视频帧时间戳与外部时钟的差值clock_diff,令时钟差值的设定值clock_diff_set为0;

将该差值送入增量式PID控制器中处理得到帧持续时间的增量delay_incre;

与延时基准值delay_basic相加得到实际延时值delay_actual作为当前帧持续时间;

延时过后,重复该操作,当PID控制器参数合理,会使得clock_diff趋向于设定值0;

简略的代码实现如下:

	/*** 解码渲染显示等操作 ***/
	if (time_flag) {
		time_offset = av_gettime();
		time_flag = 0;
	}
	now_time  = av_gettime() - time_offset;
	time_diff[0] = time_diff[1];
	time_diff[1] = time_diff[2];
	time_diff[2] = now_time - vc->frame_pts_ld;
	time_incre = kp*(time_diff[2]-time_diff[1]) + ki*time_diff[2] + 
        		 kd*(time_diff[2] - 2*time_diff[1] + time_diff[0]);
	now_delay -= time_incre;		//此处的 -=操作 等价于处理clock_diff_set=0
	printf("\r%ld, %lld\t", now_delay, time_diff[2]);
	av_usleep(now_delay);
	/*** 回到第一步重复操作, 不断收敛time_diff为0 ***/

本文福利, 免费领取C++音视频学习资料包、技术视频,内容包括(音视频开发,面试题,FFmpeg webRTC rtmp hls rtsp ffplay srs↓↓↓↓↓↓见下面↓↓文章底部点击免费领取↓↓