FFmpeg暂停、逐帧和音量

暂停、逐帧和音量

播放、暂停

  • 画面要停止
    • 画面停留在最后一帧
  • 声音要停止
    • ⾳频回调接⼝请求数据帧时直接填0
  • 读取数据是否要停⽌?
    • ⾳视频包缓存队列满时进⼊休眠。
  • 暂停->继续 :时钟的恢复
  • 暂停:toggle_pause()

暂停/继续切换状态

函数调⽤关系如下:

c 复制代码
main() -->
event_loop() -->
toggle_pause() -->
stream_toggle_pause()

stream_toggle_pause()实现状态翻转:

c 复制代码
static void stream_toggle_pause(VideoState *is)
{
    if (is->paused) {
        // 这里表示当前是暂停状态,将切换到继续播放状态。
        // 在继续播放之前,先将暂停期间流逝的时间加到frame_timer中
        is->frame_timer += av_gettime_relative() / 1000000.0 - is->vidclk.last_updated;
        if (is->read_pause_return != AVERROR(ENOSYS)) {
            is->vidclk.paused = 0;
        }
        set_clock(&is->vidclk, get_clock(&is->vidclk), is->vidclk.serial);
    }
    set_clock(&is->extclk, get_clock(&is->extclk), is->extclk.serial);
    is->paused = is->audclk.paused = is->vidclk.paused = is->extclk.paused = !is->paused;
}

暂停状态下的视频播放

在video_refresh()函数中有如下代码:

c 复制代码
static void video_refresh(void *opaque, double *remaining_time)
{
    // 视频播放
    if (is->video_st) {
        // 暂停处理:不停播放上一帧
        if (is->paused)
            goto display;
    }
}

在暂停状态下,实际就是不停播放上⼀帧(最后⼀帧)图像。画⾯不更新。

暂停状态下的音频播放

sdl_audio_callback->audio_decode_frame

c 复制代码
static int audio_decode_frame(VideoState *is)
{
    int data_size, resampled_data_size;
    int64_t dec_channel_layout;
    av_unused double audio_clock0;
    int wanted_nb_samples;
    Frame *af;
    if (is->paused)
        return -1; // 暂停返回-1, 但这⾥返回-1并不会导致程序结束。
    ....
}

逐帧、调音量、静音

  • 逐帧播放的本质是,播放⼀帧图像,然后暂停。
  • 涉及到的函数和变量:
    • step_to_next_frame()
    • is->step=1 时单步播放一帧,然后 paused
  • 逐帧播放流程
    • 按s键,如果当前处于暂停则启动播放;
    • 播放⼀帧数据然后进⼊暂停状态

逐帧播放是⽤户每按⼀次s键,播放器播放⼀帧画现。

逐帧播放实现的⽅法是:每次按了s键,就将状态切换为播放,播放⼀帧画⾯后,将状态切换为暂停。

函数调⽤关系如下:

c 复制代码
main() -->
event_loop() -->
step_to_next_frame() -->
stream_toggle_pause()

实现代码如下:

c 复制代码
static void step_to_next_frame(VideoState *is)
{
    /* if the stream is paused unpause it, then step */
    if (is->paused)
        stream_toggle_pause(is); // 如果停止状态则切换
    is->step = 1; // 切换到逐帧模式
}

static void video_refresh(void* opaque, double* remaining_time) {

    if (is->video_st) {

        if (is->step && !is->paused)
            stream_toggle_pause(is); // 逐帧播放模式下,播放一帧暂停
    }
}

调音量

音量控制的本质:控制采样点的幅值

  • 静音:将采样点数值设置为 0
  • 音量+:提升幅值
  • 音量-:降低幅值

降低音量

ffplay 控制音量的方式:

  • 最大音量:输出解码后的原始数据
  • 静音:输出数值为 0 的数据
    • toggle_mute()
  • 改变音量:通过 SDL_MixAudioFormat 改变编码后数据的幅值
    • update_volume()

静音

c 复制代码
static void toggle_mute(VideoState *is)
{
    is->muted = !is->muted;
}

参考资料:https://github.com/0voice

相关推荐
小徐敲java20 小时前
视频推流服务器与FFmpeg 安装配置
服务器·ffmpeg·音视频
假装我不帅1 天前
ffmpeg操作mp3去除封面信息
ffmpeg
封奚泽优3 天前
下载网页中的.m3u8视频文件
ffmpeg
Vertira3 天前
win10/10 下载并安装ffmpeg.exe 的官方详细方法 (已解决)
ffmpeg
xmRao3 天前
Qt+FFmpeg 实现音频重采样
qt·ffmpeg·音视频
Evonso4 天前
静态编译的ffmpeg用法
ffmpeg
_chirs6 天前
编译不依赖动态库的FFMPEG(麒麟国防 V10)
arm开发·ffmpeg
熊猫钓鱼>_>6 天前
从零到一:打造“抗造” Electron 录屏神器的故事
前端·javascript·ffmpeg·electron·node·录屏·record
UpYoung!6 天前
【格式转换工具】专业级多媒体格式转换解决方案——Freemake Video Converter 完全指南:轻量化视频剪辑媒体格式转换
ffmpeg·短视频·实用工具·开源工具·多媒体格式转换·运维必备·视频转换格式
试剂小课堂 Pro7 天前
Ald-PEG-Ald:丙醛与聚乙二醇两端连接的对称分子
java·c语言·c++·python·ffmpeg