FFplay跳转时间点播放

FFmpeg 的社群来了,想加入微信社群的朋友请购买《FFmpeg原理》VIP版 电子书,里有更高级的内容与答疑服务。


播放器的最常用的功能之一 就是快进快退,快进快退的本质就是让 mp4文件 跳转到另一个时间点来播放。

FFplay 播放器有两种方式可以让 mp4文件 跳转到另一个时间点来播放。

1,在命令行里里使用 -ss 参数,如下,跳到到第 60 秒的地方开始播放。

ffplay -x 400 -ss 60 -i juren.mp4

2,在播放过程中,按上下左右减,进行快进后退操作。

上面这两种跳转时间点播放的方式,其实都是调 avformat_seek_file() 来实现的,都是在 read_thread() 线程函数里面进行 seek 操作的。


先来讲解命令行的 -ss 的原理,代码如下:

可以看到,是用 opt_seek() 函数来接受 -ss 参数的,代码如下:

提示:更多命令行参数解析的细节,请阅读《parse_options命令行参数解析

可以看到,最后赋值到了 全局变量 start_time,然后 start_time 变量会在 read_thread() 函数入口不远的地方被使用,如下:

注意,上面的 seek 是在 for(;;) {...} 循环之前的。


接着讲一下播放过程中 快进后退的实现。当按下 ↓ 键的时候,就会后退进 60s ,看一下代码实现:

从上图可以发现,有两种 seek 方式,一种是按时间 seek (默认),一种是 按字节 seek。

如果是按字节 seek,就会把时间转成字节位置。

无论是字节 seek,还是时间 seek,都是绝对的。例如绝对时间 跟 绝对位置。

frame_queue_last_pos() 获取当前视频流,或者音频流播放到哪个字节位置了,再加上 incr (相对)。

get_master_clock() 获取当前主时钟播放到第几秒了,然后再加上 incr (相对)。

最后调 stream_seek() 记录要跳转的位置,注意 stream_seek() 只是记录一下位置,并不会进行跳转操作。

那 is->seek_req 跟 is->seek_pos 会在哪里被使用呢?在 read_thread() 里面。

在播放一个 mp4 文件的时候,read_thread() 会一直阻塞在 for(;;) {...} 循环里面,不断调 av_read_frame() 读取 AVPacket 出来。如下:

但是在 调 av_read_frame() 之前,会检测一下 is->seek_req 是否为 1,为 1 代表有 seek 请求发生,如下:

上图中,avformat_seek_file() 之后,就需要用 packet_queue_flush() 清空之前队列里面的缓存,还有刷新序列号。序列号的内容请看《FFplay序列号分析

seek 之后还会更新外部时钟,因为外部时钟就是预定的播放时刻,跳转的就是预定的播放时刻。

if (is->seek_flags & AVSEEK_FLAG_BYTE) {
    set_clock(&is->extclk, NAN, 0);
} else {
    set_clock(&is->extclk, seek_target / (double)AV_TIME_BASE, 0);
}

FFplay跳转时间点播放 分析完毕。

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Loken2020

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

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

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

打赏作者

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

抵扣说明:

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

余额充值