美文网首页
音视频流媒体开发【三十六】FFmpeg+QT播放器5-其他功能

音视频流媒体开发【三十六】FFmpeg+QT播放器5-其他功能

作者: AlanGe | 来源:发表于2023-03-29 21:36 被阅读0次

    音视频流媒体开发-目录

    5-stream_open和stream_close

    进⼀步掌握:

    • ijkmp_prepare_async处理逻辑
    • ijkmp_stop处理逻辑

    stream_open

    stream_open主要⼯作内容:
    • 初始化SDL以允许⾳频输出;
    • 初始化帧Frame队列
    • 初始化包Packet队列
    • 初始化时钟Clock
    • 初始化⾳量
    • 创建解复⽤读取线程read_thread
    • 创建视频刷新线程video_refresh_thread

    这⾥需要注意的是我们只是列举了主要的逻辑,还有其他逻辑在后续不断优化的时候添加。

    stream_close

    stream_close主要⼯作内容:
    • 请求关闭read_thread线程
    • 关闭解复⽤器
    • 关闭stream,⽐如调⽤stream_component_close,该函数实现的时候涉及到:
      • 关闭解码线程
      • 释放解码器资源
      • 关闭对应的⾳频、视频设备
    • 消耗包队列
    • 消耗帧队列
      释放其他资源

    6-解复⽤、数据读取read_thread设计

    read_thread线程

    实现解复⽤

    stream_component_open

    打开对应的解码器并做初始化
    创建和启动解码线程
    初始化⾳频或视频输出设备

    stream_component_close

    关闭解码器线程
    释放解码器资源
    关闭⾳频或视频输出设备

    7-解码线程Decoder封装

    • stream_component_open
      • decoder_init
      • decoder_start
    • stream_component_close
      • decoder_abort
      • decoder_destroy

    int audio_thread(void* arg); // ffplayer

    int video_thread(void* arg);// ffplayer

    8-⾳频输出

    我们采⽤SDL作为⾳频输出。


    • ⾳频设备初始化
    • ⾳频设备输出回调函数
    • 重采样
    • buffer管理

    9-视频渲染输出

    ⽬前使⽤qt输出, ui模块需要传⼊qt输出画⾯的回调。

    重点内容

    1. 创建视频刷新线程video_refresh_thread,然后调⽤输出画⾯的回调函数。
    2. 设置视频刷新回调函数 从MainWind-> IjkMediaPlayer -> FFPlayer
    3. av_read_frame的video packet发给video packet queue
    4. 在DisplayWind 渲染画⾯
    5. 在调⽤stream_component_close的时候记得关闭 视频刷新线程video_refresh_thread

    10-基本的⾳视频同步

    难点

    • ⾳视频同步采⽤以⾳频为基准的⽅式。
    • ⾳频维系时间轴 视频时间戳怎么去对⽐⾳频时钟?
    • NaN(Not a Number,⾮数)是计算机科学中数值数据类型的⼀类值,表示未定义或不可表示的值。常在浮点数运 算中使⽤。

    步骤

    1. 时钟结构设计和API设计
    // 这⾥讲的系统时钟 是通过av_gettime_relative()获取到的时钟,单位为微妙
    typedef struct Clock {
        double pts;            // 时钟基础, 当前帧(待播放)显示时间戳,播放后,当前帧变成上⼀帧
        // 当前pts与当前系统时钟的差值, audio、video对于该值是独⽴的
        double pts_drift;      // clock base minus time at which we updated the clock
        // 当前时钟(如视频时钟)最后⼀次更新时间,也可称当前时钟时间
        double last_updated;   // 最后⼀次更新的系统时钟
    } Clock;
    
    1. stream_open中初始化时钟init_clock(&vidclk); init_clock(&audclk);
    2. 设置audio的时钟,在audio_decode_frame设置audio_clock, 然后在sdl_audio_callback设置audio时钟set_clock(&is->audclk, is->audio_clock);
    3. video时间戳⽐对audio时钟,在video_refresh
    // 对⽐audio的时间戳
    double diff = vp->pts - get_master_clock();
    std::cout << __FUNCTION__ << "vp->pts:" << vp->pts << " - af->pts:" <<
    get_master_clock() << ", diff:" << diff << std::endl;
    if(diff > 0) {
        *remaining_time = FFMIN(*remaining_time, diff);
        return;
    }
    

    练习

    • 实现控制⽂件的⼤⼩
    • 实现暂停功能
    • 实现seek功能

    相关文章

      网友评论

          本文标题:音视频流媒体开发【三十六】FFmpeg+QT播放器5-其他功能

          本文链接:https://www.haomeiwen.com/subject/mtxqddtx.html