现在用ffmpeg库写播放器,求帧率(12帧/s左右),计算出每帧时间,然后掐头去尾,sleep一个延时时间。
现在的问题是,sleep延时超级不准,误差在55MS左右,而我一帧延时也才五六十MS网上找精确延时的方法,基本上都是用while循环不停的取时间,没到点就继续循环,如下面这段代码:
while( (timeGetTime()- vstart) < (unsigned long)time_delay);
但是这样的一个问题就是CPU时间占满了不知道有什么办法可以做到精确的延时,同时又降低CPU的占用率的。或者有什么其他方法可以让我的视频同步播放的也欢迎回答,多谢!我有两个设想请高手论证下:
设想一:
就是我在A之外,再另外开一个线程B,作为唤醒线程,进入延时循环后A唤醒B,将自己挂起来,B在循环中唤醒A,然后将自己挂起来,这样子让两个线程反复的唤醒另外一个线程,来利用线程的切换实现延时,不知道这样理论上可行否。设想二:
还有一个设想是用高精度定时器,A进入循环后,生成一个高精度定时器,让定时器每个最小周期将自己唤醒,醒了后检查延时时间有没有完,如果完了就干掉定时器跳出延时循环执行后面的代码,如果还没完就自己挂起自己,等待下次再被唤醒。

解决方案 »

  1.   

    你的目的是干什么?
    如果是改变帧率,ffmpeg应该有提供函数的
    另外高精度的定时器,可以用QueryPerformanceFrequency,QueryPerformanceCounter;或者ftime  
      

  2.   

    目的就是严格控制播放时间,做视频的同步
    不是改变帧率,这个以后可能会用到,现在暂时还不考虑
    QueryPerformanceFrequency,QueryPerformanceCounter;的延时代码我有,也是通过WHILE循环来延时的,同while( (timeGetTime()- vstart) < (unsigned long)time_delay);一样,不过精度更高一点而已,CPU会占满的
      

  3.   

    定时精度越高,需要的资源就越多.在while循环中用QueryPerformanceFrequency,QueryPerformanceCounter和
    Sleep实现高精度定时,可以把显示线程提升为实时优先级.这里有一个定时类可以参考.http://blog.csdn.net/dengzikun/archive/2010/08/19/5824874.aspx
      

  4.   

    刚刚还在讨论这个问题,楼主看看下面的例子,这个精度高
    #include <windows.h>
    #include <time.h>
    #include <stdio.h>
    ULONG GetTimeDis(struct tm first, struct tm second)    //计算两次时间差
    {
        return abs((first.tm_hour * 3600 + first.tm_min * 60 + first.tm_sec)
            - (second.tm_hour * 3600 + second.tm_min * 60 + second.tm_sec));
    }void Delay(ULONG ulMicroSeconds)
    {
        LARGE_INTEGER  timeStop;
        LARGE_INTEGER  timeStart;
        LARGE_INTEGER  Freq;
        ULONG  ulTimeToWait;    if (!QueryPerformanceFrequency( &Freq ))
            return;    ulTimeToWait = Freq.QuadPart * ulMicroSeconds / 1000 / 1000;    QueryPerformanceCounter ( &timeStart );    timeStop = timeStart;    while( timeStop.QuadPart - timeStart.QuadPart < ulTimeToWait )
        {
            QueryPerformanceCounter( &timeStop );
        }
    }int main(void)
    {
        struct tm timeStart, timeEnd;    _getsystime(&timeStart);//     Delay(1000 * 1000 * 3);    //3秒
        _getsystime(&timeEnd);  // 
        printf("用时:%d秒\n", GetTimeDis(timeStart, timeEnd));//     return 0;
    }
      

  5.   


    还是用的循环,一样占CPU,我现在已经找到近似的精确定时的方法了。代码贴出来,给其他人可以做个参考。/*
    *在算法上进行改进,以前是以单独每帧计算延时,这样误差会累计。
    *现在以1分钟为一个周期,进行整体延时。
    *前面的误差会被后面的误差抵消掉,所以一分钟的误差就接近一个sleep的误差
    *为了更加减小误差,这个周期数可以适当加大
    */
    int vbegin,vstart,vfinish,time_delay;//注意这里一定要用int必须为有符号型的,不可用DWORD或者UINT
    int frame_rate=12;//帧率
    int ms_per_minite=60000;//每周期毫秒数
    int frames_per_minite=frame_rate*60;//每周期帧数,
    int count=0;//循环计数器,每周期清零一次vstart=timeGetTime();//每帧开始时间
    while(//视频没播放完)
    {
    if(count%frames_per_minite==0)//计算是否到了一个周期接合点
    {
    vstart=timeGetTime();//每计时周期开始时间
    count=0;//每周期开始将计时器清零
    }

    //解码
    //显示;
    vfinish=timeGetTime();//画图完成时间
    time_delay=(count+1)*1000/frame_rate-(vfinish-vstart);
    if (time_delay>0)
    {
    Sleep(time_delay);//延迟
    }
    count++;
    }