文章目录
- [1. 暂停触发流程](#1. 暂停触发流程)
- [2. toggle_pause](#2. toggle_pause)
- [3. stream_toggle_pause](#3. stream_toggle_pause)
1. 暂停触发流程
1.通过SDL触发事件调用toggle_pause
2.toggle_pause调用stream_toggle_pause
3.stream_toggle_pause修改暂停变量
2. toggle_pause
c
static void toggle_pause(VideoState *is)
{
stream_toggle_pause(is);
is->step = 0;
}
3. stream_toggle_pause
c
static void stream_toggle_pause(VideoState *is)
{
// 如果当前是暂停 -> 恢复播放
// 正常播放 -> 暂停
if (is->paused) {// 当前是暂停,那这个时候进来这个函数就是要恢复播放
/* 恢复暂停状态时也需要恢复时钟,需要更新vidclk */
// 加上 暂停->恢复 经过的时间
is->frame_timer += av_gettime_relative() / 1000000.0 - is->vidclk.last_updated;
if (is->read_pause_return != AVERROR(ENOSYS)) {
is->vidclk.paused = 0;
}
// 设置时钟的意义,暂停状态下读取的是单纯pts
// 重新矫正video时钟
set_clock(&is->vidclk, get_clock(&is->vidclk), is->vidclk.serial);
}
set_clock(&is->extclk, get_clock(&is->extclk), is->extclk.serial);
// 切换 pause/resume 两种状态
is->paused = is->audclk.paused = is->vidclk.paused = is->extclk.paused = !is->paused;
printf("is->step = %d; stream_toggle_pause\n", is->step);
}
这个函数可以知道,如果当前状态是暂停的话,那么就会进入if函数
看一下if函数流程,首先我们知道我们
is->frame_timer += av_gettime_relative() / 1000000.0 - is->vidclk.last_updated;
这个就是在之前的基础上加上暂停到开始的时间
set_clock(&is->vidclk, get_clock(&is->vidclk), is->vidclk.serial);
get_clock当是暂停状态时就是获取时钟的pts
set_clock(&is->extclk, get_clock(&is->extclk), is->extclk.serial);
同理是设置外部时钟的
is->paused = is->audclk.paused = is->vidclk.paused = is->extclk.paused = !is->paused;
就是将paused取反
看一下这4个pause会影响那些函数
- video_refresh 如果是暂停并且没有强制刷新的话就不会调用该函数,什么时候强制刷新之前有说过,比如修改ffplay窗口大小
- read_thread中的pause只会对网络流有效,而其他情况下pause并不会对read_thread有影响,而是继续读数据写入到队列中
- get_master_clock中会调用get_clock,而get_clock中如果是paused状态的话就会直接返回pts
- audio_decode_frame函数会受到paused影响,会直接返回-1,然后sdl_audio_callback接受到会进行判断,然后输出静音数据,并未有暂停