• 播放器缓存队列bug解决方案


    背景

    我在开发一个播放器的缓存队列时,遇到一个bug,导致包和帧无法被下一个模块读取

    找了半天,原来是队列中的包和帧数据要进行内容的刷新暂存

    包数据和帧数据不能直接放入队列

    //入队,包进队列
    int AVPacketQueue::Push(AVPacket *val,int timeout)
    {
        //加作用域互斥锁:资源同一时间只能有一个线程访问,作用域结束自动释放锁
        //std::lock_guard lock(mutex_);
    
        std::unique_lock<std::mutex> lock(mutex_);//这里必须要加手动作用域互斥锁,因为wait_for需要作用域
    
    
        //因为是包队列-双链表
        //如果队满了,等待timeout时间
        if(duration_cur>=duration_MAX) {
            // 等待pop或者超时唤醒
            cond_.wait_for(lock, std::chrono::milliseconds(timeout), [this] {
                return duration_cur<duration_MAX;
            });
        }
    
        //如果依然队满,就直接返回-1
        if(duration_cur>=duration_MAX){
            return -1;
        }
    
        //入队:出现问题的代码,这里是直接把包指针存放到队列中了,但是在ffmpeg中不能直接存放,必须要先搞一个新包,然后刷新暂存数据
        queue_.push(val);
    
        //增加队列缓存时间,强转成ms
        long ms = static_cast<long>(av_rescale(val->duration, 1000, AV_TIME_BASE));
    
        this->duration_cur+=ms;
    
        cond_.notify_one();//条件变量:通知其他线程可以继续执行
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    解决方案

    //入队,包进队列
    int AVPacketQueue::Push(AVPacket *val,int timeout)
    {
        //加作用域互斥锁:资源同一时间只能有一个线程访问,作用域结束自动释放锁
        //std::lock_guard lock(mutex_);
    
        std::unique_lock<std::mutex> lock(mutex_);//这里必须要加手动作用域互斥锁,因为wait_for需要作用域
    
    
        //因为是包队列-双链表
        //如果队满了,等待timeout时间
        if(duration_cur>=duration_MAX) {
            // 等待pop或者超时唤醒
            cond_.wait_for(lock, std::chrono::milliseconds(timeout), [this] {
                return duration_cur<duration_MAX;
            });
        }
    
        //如果依然队满,就直接返回-1
        if(duration_cur>=duration_MAX){
            return -1;
        }
    
        //入队:一定注意,必须要重新申请空间,不然会指向同一段地址,而且后面要释放对应的数据包av_packet_free
        AVPacket *tmp_packet = av_packet_alloc();
        av_packet_move_ref(tmp_packet, val);
        queue_.push(tmp_packet);
    
        //增加队列缓存时间,强转成ms
        long ms = static_cast<long>(av_rescale(val->duration, 1000, AV_TIME_BASE));
    
        this->duration_cur+=ms;
    
        cond_.notify_one();//条件变量:通知其他线程可以继续执行
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
  • 相关阅读:
    【毕业设计】基于单片机的室内环境温湿度检测系统 - 物联网 嵌入式 stm32
    PX4模块设计之三十七:MulticopterRateControl模块
    Java学习笔记(二十四)
    尝试了一下csdn编程挑战赛
    法语翻译器在线翻译器
    游标查询的使用场景
    JSON(及其在ajax前后端交互的过程)小识
    [直播自学]-[汇川easy320]搞起来(2)看文档
    76. 最小覆盖子串
    Apollo预测模块启动及调试
  • 原文地址:https://blog.csdn.net/qq_43537701/article/details/133888437