[SimplePlayer] 3. 视频帧同步
Frame Rate
帧率代表的是每一秒所播放的视频图像数目。通常,视频都会有固定的帧率,具体点地说是每一帧的时间间隔都是一样的,这种情况简称为CFR(Constant Frame Rate);另外一种情况就是每一帧的时间间隔不一定相同,即可变帧率,简称为VFR(Variable Frame Rate),现在也有些录像设备支持录制VFR视频了,在录制具有大量静止场景的视频时,采用VFR能降低录制出来的视频的容量大小。
PTS
通过上文对帧率的描述,我们知道在进行视频播放时,每一帧都应该有自己的播放时刻。不过视频文件中不会直接存放帧的播放时刻,为了保证精度以及节省存储空间,文件中会存储每一帧的PTS(Presentation Time Stamp)以及一个名为time base的参数,PTS是整数,而time base是小数,通过PTS与time base相乘,就能得到视频的播放时刻,单位为秒。大部分的视频格式都支持存放帧的PTS,而在播放的时候,通过对PTS进行计算就能使得视频的每一帧都在合适的时间显示。通常,第一帧的PTS为0。
同步流程
视频帧有固定的输出时间的话,意味着在解码完成一帧之后,需要进行等待,等到合适的时间才能进行帧的显示。
上图为一个视频帧的解码、显示循环。在解码完成一帧后,需要获得当前时间以及当前帧的显示时间,两者的时间差就是需要睡眠的时长。
不过由于我们常用的操作系统为非实时系统,因此如果希望执行短时间的休眠,调用sleep通常不会得到非常满意的结果。解决方法就是通过多次休眠更短的时间段,并在被唤醒过后检查是否已经超时,超时即可进行视频帧的输出。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | //Decode video frame avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet); if (frameFinished){ memcpy(Display.YPlane, pFrame->data[0], bufsize); memcpy(Display.UPlane, pFrame->data[1], bufsize/4); memcpy(Display.VPlane, pFrame->data[2], bufsize/4); vs.frame_last_pts = vs.frame_cur_pts; vs.frame_cur_pts = pFrame->pts * time_base * 1000000; pts_delay = vs.frame_cur_pts - vs.frame_last_pts; vs.cur_display_time = vs.last_display_time + pts_delay; //vs.last_frame_displayed = 0; if (!vs.is_first_frame){ time = av_gettime_relative(); delay = vs.cur_display_time - time; while (delay > 0){ if (delay > 10000) vs.sleep_time = 10000; else vs.sleep_time = delay; av_usleep(vs.sleep_time); time = av_gettime_relative(); delay = vs.cur_display_time - time; } vs.last_display_time = time; DisplayFrame(&Display); //vs.last_frame_displayed = 1; } else { vs.last_display_time = av_gettime_relative(); DisplayFrame(&Display); vs.is_first_frame = 0; //vs.last_frame_displated = 1; } SDL_PumpEvents(); } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架