乐趣区

关于go:SkeyeExPlayerWindows开发系列之快放慢放的实现

在解说 SkeyeExPlayer 快加快放之前,咱们首先要解说下 SkeyeExPlayer 的音视频同步机制,咱们采纳视频同步音频的形式进行工夫戳同步,无音频状况下视频自同步;视频自同步的状况比较简单这里就不做形容,上面咱们着重解说下音视频同步存在时的快加快放并如何放弃音视频同步。

1. 音视频同步原理
首先,音频解码后获取到的 PCM 原始数据应用 waveout 间接进行播放,并记录以后播放工夫戳,音频在任何时候都是失常播放,不做同步操作;
而后,视频工夫戳来同步音频工夫戳:

            DWORD   tickcur  = GetTickCount();
            int     tickdiff = tickcur - c->ticklast;
            int64_t avdiff   = apts - vpts - c->tickavdiff;
            c->ticklast = tickcur;
            if (apts == -1 && vpts != -1&&c->play_speed>0) // 无音频状况做非凡解决
            {c->tickframe = 100000/(c->framerate*c->play_speed);
                if (c->play_speed != 100)// 倍速播放时变速放慢
                {if (tickdiff - c->tickframe >  2) c->ticksleep-=2;
                    if (tickdiff - c->tickframe < -2) c->ticksleep+=2;
                }
            }

            {if (tickdiff - c->tickframe >  2) c->ticksleep--;
                if (tickdiff - c->tickframe < -2) c->ticksleep++;
            }
            if (apts != -1 && vpts != -1) {if (avdiff > 5) c->ticksleep-=2;
                if (avdiff <-5) c->ticksleep+=2;
            }
            if (c->ticksleep < 0) c->ticksleep = 0;
            if (c->ticksleep > 0) 
                Sleep(c->ticksleep);

同步大抵流程如上段代码所示,首先,计算音频工夫戳和视频工夫戳以及以后工夫戳和上一次工夫戳的差值,而后,依据帧率计算以后帧和上一帧的差值,从而得出视频帧显示的工夫是快于音频还是慢于音频,而在上面进行调整,进而实现音视频的动静东同步:

 if (apts != -1 && vpts != -1)
  {if (avdiff > 5) c->ticksleep-=2;
     if (avdiff <-5) c->ticksleep+=2;
 }

2. 快加快放实现
从下面的同步原理咱们理解到,音频快的时候视频为了同步也跟着快,反之亦然;所以,为了实现快加快放,咱们能够通过调整音频播放的快慢即可实现:

            int sample_rate = 44100 * 100 / player_speed_cur;
            player->swr_context = swr_alloc_set_opts(NULL, AV_CH_LAYOUT_STEREO, AV_SAMPLE_FMT_S16, sample_rate,
                player->chan_layout, player->sample_fmt, player->sample_rate, 0, NULL);
            swr_init(player->swr_context);

而音频的快加快放则通过批改音频的采样率即可实现;

3. 单视频的快加快放

上文曾经说到,单视频的状况下,则不能通过视频同步音频的逻辑来解决视频播放的逻辑,而只能通过视频的帧率来进行播放快慢的调整:
            if (apts == -1 && vpts != -1&&c->play_speed>0) // 无音频状况做非凡解决
            {c->tickframe = 100000/(c->framerate*c->play_speed);
                if (c->play_speed != 100)// 倍速播放时变速放慢
                {if (tickdiff - c->tickframe >  2) c->ticksleep-=2;
                    if (tickdiff - c->tickframe < -2) c->ticksleep+=2;
                }
            }

如上代码段所示,如果音频不存在,则视频的快加快放则通过批改实时帧率来实现。

退出移动版