3、ffplay同步时钟源码分析

ffplay同步时钟源码分析

同步时钟用于音视频同步(A-V sync)

A-V同步可以选择以音频同步、视频同步、外部时钟同步

一、数据结构

typedef struct Clock {
    double pts;           /* 渲染时间,单位秒 */
    double pts_drift;     /* 渲染时间-当前更新时间。这个写法真奇葩?^~^*/
    double last_updated; /* 上一次pts更新的时间 */
    double speed;       /* 倍速播放 */
    int serial;           /* clock is based on a packet with this serial */
    int paused; /* 暂停标识 */
    int *queue_serial;    /* 指向PacketQueue的serial指针 */
} Clock;

二、操作函数

/* 获取clock的pts */
static double get_clock(Clock *c)
{
    if (*c->queue_serial != c->serial){
        //时钟序列号改变,发生PacketQueu Flush,例如快进等原因,返回NAN标示当前时钟无效
        return NAN;
    }
    if (c->paused) {
        return c->pts;
    } else {
        double time = av_gettime_relative() / 1000000.0;
        //c->pts_drift + time 等价于 c->pts+(time - c->last_updated)表示当前的pts
        //(这个写法真是奇葩,真不知道pts_drift这个字段来干啥?
        //直接time - c->last_updated不是更易懂么?
        // 推导过程:由函数set_clock_at(...) 可知c->pts_drift记录的是更新pts时与时间的差值,这里在加上当前time可知即为当前的pts)
        //最后减去(time - c->last_updated) * (1.0 - c->speed)倍速播放值 
        return c->pts_drift + time - (time - c->last_updated) * (1.0 - c->speed);
    }
}

static void set_clock_at(Clock *c, double pts, int serial, double time)
{
    c->pts = pts;
    c->last_updated = time;
    c->pts_drift = c->pts - time;
    c->serial = serial;
}

static void set_clock(Clock *c, double pts, int serial)
{
    double time = av_gettime_relative() / 1000000.0;
    set_clock_at(c, pts, serial, time);
}

你可能感兴趣的:(视频播放器)