SkeyeExPlayer(Windows)开发系列之快放慢放的实现

本文详细介绍了SkeyeExPlayer在音视频同步机制下的快放慢放实现。通过调整音频的采样率实现音频的快慢放,以此达到视频的同步播放效果。当只有视频时,通过修改视频帧率来控制播放速度。
摘要由CSDN通过智能技术生成

在讲解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;
				}
			}

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SwordTwelve

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值