• 【音视频】ffplay源码解析-FrameQueue队列


    帧队列架构位置

    在这里插入图片描述


    结构体源码

    FrameQueue结构体

    /* 这是一个循环队列,windex是指其中的首元素,rindex是指其中的尾部元素. */
    typedef struct FrameQueue {
        Frame	queue[FRAME_QUEUE_SIZE];        // FRAME_QUEUE_SIZE  最大size, 数字太大时会占用大量的内存,需要注意该值的设置
        int		rindex;                         // 读索引。待播放时读取此帧进行播放,播放后此帧成为上一帧
        int		windex;                         // 写索引
        int		size;                           // 当前总帧数
        int		max_size;                       // 可存储最大帧数
        int		keep_last;                      // = 1说明要在队列里面保持最后一帧的数据不释放,只在销毁队列的时候才将其真正释放
        int		rindex_shown;                   // 初始化为0,配合keep_last=1使用
        SDL_mutex	*mutex;                     // 互斥量
        SDL_cond	*cond;                      // 条件变量
        PacketQueue	*pktq;                      // 数据包缓冲队列
    } FrameQueue;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    Frame结构体

    // 用于缓存解码后的数据
    typedef struct Frame {
        AVFrame		*frame;         // 指向数据帧
        AVSubtitle	sub;            // 用于字幕
        int		serial;             // 帧序列,在seek的操作时serial会变化
        double		pts;            // 时间戳,单位为秒
        double		duration;       // 该帧持续时间,单位为秒
        int64_t		pos;            // 该帧在输入文件中的字节位置
        int		width;              // 图像宽度
        int		height;             // 图像高读
        int		format;             // 对于图像为(enum AVPixelFormat),
                                    // 对于声音则为(enum AVSampleFormat)
        AVRational	sar;            // 图像的宽高比(16:9,4:3...),如果未知或未指定则为0/1
        int		uploaded;           // 用来记录该帧是否已经显示过?
        int		flip_v;             // =1则旋转180, = 0则正常播放
    } Frame;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    内存管理

    • 一个环形循环数组队列
      • 数组队列适合于事先明确了缓冲区的最⼤容量的情形
      • 避免假队空----定义一个size
    • 写端位于解码线程,读端位于播放线程
    • 锁机制—线程安全

    引申知识点—队列假队空

    概念

    如果只用一个连续数组表示一个队列,没有其他标志位

    • 队空:头指针==尾指针
    • 队满:头指针==尾指针

    则无法判断队列状态是队满还是队空

    解决办法

    一共有三种解决办法

    • 方法1:数组最后一个空间不存放元素
    • 方法2:加一个当前元素数量size
    • 方法3:加一个队满标志位flag

    队列大小设置

    因为这⾥存储的是解码后的数据,队列缓存不宜设置过⼤

    一般为限制缓存

    视频帧队列<=3

    音频帧队列<=9

    字幕帧队列<=16

    在这里插入图片描述

  • 相关阅读:
    项目持续集成配置流程
    Java HashMap 实现线程安全
    基于Spring Boot的仿豆瓣平台
    分布式存储之hash取余算法
    设计模式之工厂模式
    前端JavaScript入门到精通,javascript核心进阶ES6语法、API、js高级等基础知识和实战 —— Web APIs(五)
    链表专项之环形链表
    为什么需要线程池?什么是池化技术?
    ARM寄存器及功能介绍/R0-R15寄存器
    C语言 数据结构与算法 I
  • 原文地址:https://blog.csdn.net/qq_43537701/article/details/132943637