范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

FFmpeg入门学习03缓存队列的实现

  1、前言
  在之前的文章中实现了打开视频文件并进行解封装的功能,解封装之后即可进行解码操作。 为使解码过程不会受到解封装过程进展的影响,解封装和解码一般并行操作,两者之间通过缓存数据进行交互。
  2、背景2.1 线程安全队列
  由于 STL 中的容器是非线程安全的,因此要实现解封装和解码的并行操作需要实现一个线程安全的队列。 由于 std::deque 可以方便的在头尾进行数据的读写,此处选用 std::deque 来简单实现一个线程安全的队列。 2.2 AVPacket 和 AVFrame
  在 FFmpeg 中解码前和解码后的数据分别使用 AVPacket 和 AVFrame 进行存储。 AVPacket 及 AVFrame 是采用引用计数的方式进行内部资源的管理,在对缓存数据进行读写时要特别注意数据的释放问题,以避免内存泄漏。 2.3 成员函数模板特例化
  由于 AVPacket 和 AVFrame 资源管理的接口不同,为避免特例化类的所有成员,仅把相关方法通过类的成员函数模板特化来实现。 3、缓存队列的实现3.1 概述
  此处实现的缓存队列仅满足对 AVPacket 和 AVFrame 的管理,且读写两个并发操作互相不受影响即可。 3.2 接口设计template  class Queue { private:     std::deque    queue;     mutable std::mutex   mutex;//访问互斥信号量     int       maxSize{0};//最大容量 public:     Queue() = default;     explicit Queue(int m_size ): maxSize(m_size){}     ~Queue() = default;          bool    IsEmpty() const;//判断队列是否为空     int     size() const;//当前元素个数     bool    IsFull() const;//判断队列是否已满     void    pushBack( T* t );//尾部添加元素     void    pushFront( T* t );//头部添加元素     T *     front();//读取首元素     T *     back();//读取尾元素     T *     operator[](int i);//按下标读取元素     void    popBack();//删除尾元素     void    popFront();//删除首元素     void    clear();//清空队列 };3.2 通用方法实现
  为实现基本的线程安全保存,所有的成员方法必须加锁,实现如下: bool    IsEmpty() const {       std::unique_lock lock(mutex);       return queue.empty(); }//判断队列是否为空 int     size() const {       std::unique_lock lock(mutex);       return queue.size(); }//当前元素个数 bool    IsFull() const {       std::unique_lock lock(mutex);       return maxSize <= queue.size(); }//判断队列是否已满 void    pushBack( T* t ) {       std::unique_lock lock(mutex);       queue.push_back(t); }//尾部添加元素 void    pushFront( T* t ) {       std::unique_lock lock(mutex);       queue.push_front(t); }//头部添加元素3.3 成员函数模板特例化
  涉及到数据读取、删除等资源管理相关操作,要进行成员函数模板特例化实现,以 front() 方法的实现为例: 成员函数实现为模板 T *     front()  {     return  frontImpl(); }//读取首元素 private:     template      void    popFrontImpl();进行 AVPacket 特例化 template <> void popFrontImpl() {     std::unique_lock lock(mutex);     if (!queue.empty())     {           auto packet = queue.front();           av_packet_unref(packet);           av_packet_free(&packet);           queue.pop_front();     } }进行 AVFrame 特例化 template <> void popFrontImpl() {       std::unique_lock lock(mutex);       if (!queue.empty())       {           auto frame = queue.front();           av_frame_unref(frame);           av_frame_free(&frame);           queue.pop_front();       } }4、缓存队列使用示例
  C++音视频学习资料免费获取方法:关注音视频开发T哥  ,点击「链接」即可免费获取2023年最新 C++音视频开发进阶独家免费学习大礼包! 4.1 完善 FFmpegPlayer 类
  在 FFmpegPlayer 类中增加两个成员,用于保存音视频解封装后的数据包: class FFmpegPlayer { public:     explicit FFmpegPlayer(const char* m_url);     ~FFmpegPlayer(); public:     bool        openFile();//打开文件     void        startDecode();//开启循环解码     void        abortDecode();//中断解码 private:     int         readOnePacket();//读一个包     int         readPacket();//循环读包 private:     std::string       url;//文件路径     AVFormatContext*  formatContext = nullptr;//封装格式上下文     AVPacket          packet{}; //用于读包      std::thread *     read_thread = nullptr;//数据读取线程     bool              abort_request{false};//强制结束     bool              readEof{false};//读包结束      int               video_index{-1};//视频流索引     int               audio_index{-1};//音频流索引     Queue*  video_packet_Queue{ nullptr };//视频 packet 队列     Queue*  audio_packet_Queue{ nullptr };//视频 packet 队列  };
  4.2 初始化队列大小
  在 FFmpegPlayer 类构造函数中初始化两个缓存队列,代码如下: FFmpegPlayer::FFmpegPlayer(const char *m_url):         url(m_url) ,         video_packet_Queue(new Queue(20)),         audio_packet_Queue(new Queue(20)) {      }4.2 完善 readPacket() 方法
  使用 av_packet_move_ref 方法转移对资源的引用、以保证资源的正确释放,代码如下: int FFmpegPlayer::readPacket()  {     while(true)     {         if( abort_request ) break;//用户退出         std::shared_ptr pktClear(&packet, [](AVPacket *p)         {             av_packet_unref(p);         });//用来确保每次 av_read_frame 后 pkt 缓存被清理了          int ret = readOnePacket();         if( ret == 0 )         {             if (packet.stream_index == video_index && !video_packet_Queue->IsFull() )             {                 AVPacket* m_packet =  av_packet_alloc();                 av_packet_move_ref(m_packet,&packet);                 video_packet_Queue->pushBack(m_packet);                  std::cout << "video_packet_Queue size " << video_packet_Queue->size() << std::endl;             }             else  if (packet.stream_index == audio_index && !audio_packet_Queue->IsFull())             {                 AVPacket* m_packet =  av_packet_alloc();                 av_packet_move_ref(m_packet,&packet);                 audio_packet_Queue->pushBack(m_packet);                  std::cout << "audio_packet_Queue size " << audio_packet_Queue->size() << std::endl;             }         }      }     return 0; }4.3 代码运行示例
  文件打开成功后,调用解复用接口,代码如下: #include "FFmpegPlayer.h" int main() {      const char  * url = "C:LzcWorkCodetest.mkv";     FFmpegPlayer * player = new FFmpegPlayer(url);     if( player->openFile())     {         std::cout << "文件打开成功!"<startDecode();     }          system("pause");     return 0; }
  运行结果如下:
  原文链接:FFmpeg 入门学习 03--缓存队列的实现

球鞋推荐李宁之光!全城10!性价比之王!细节质感无眠配色,源自于无眠之队,致敬不眠不休的韦德团队。况且在棉花糖配色之前,无眠配色就已经在韦德之道各个鞋款彰显不一样的特色了。这双全城10无眠采用黑白灰主色调,加上粉色点缀,多地再现倒奶杀牛!原奶收购价跌至低点,为何消费者还是喝不到便宜奶?奶荒涨价养殖扩群原奶过剩倒奶杀牛的周期故事仍在原奶行业重复上演。据财联社报道,供应持续增加,但消费需求不足导致原奶阶段性过剩。截至2022年底,原奶价格已较两年前高点下降6。据北京天府可乐的落幕莫再让商业运营的薄弱埋没好产品曾芷莹(重庆大学)来不及听到新年钟声的敲响,12月29日,重庆第五中级人民法院就发布了中国天府可乐集团公司(重庆)的破产清算公告。在可口可乐和百事可乐还没有彻底打入国内低端市场的那游戏行业2023年度策略供给推动行业复苏,需求仍有成长空间(报告出品方作者东北证券,宋雨翔,章驰)1。2022回顾游戏行业收入利润下滑,龙头估值处于低位1。1。游戏行业收入下滑,移动端下滑快于PC端游戏行业收入下滑明显,移动游戏显著承压。硅谷的奇迹,从炒掉一个奇葩老板开始A如今的人,是有可能这样生活的早上,iPhone手机的闹铃把老王从梦中叫醒,提醒他有一个邮件要回复。他打开内置英特尔(Intel)芯片的苹果(Apple)电脑,上了谷歌(GoogliPhone14烧屏不断?烧屏的灵动岛对比小米11,真有大家当初吹的好已经记不得是从什么时候开始,似乎大家就总觉得,iPhone系列机型的体验和售后,就一定比我们的国产手机更强了?说句实话,就从我个人的体验上来说,在前几年的话iPhone系列机型的体盘点搭载索尼IMX600传感器的手机,共25款1华为MateRS保时捷设计搭载麒麟970处理器,采用台积电10nm的制程工艺,全球首款内置独立NPU的智能手机AI计算平台,大型文件处理手到擒来,各类计算任务游刃有余正面是一块62022年第4季度企业所得税预缴申报实操全流程,不会的,收藏备用2023年1月要进行季度申报,是个大征期!财务人员要对2022年第四季度企业所得税预缴申报!在此对企业所得税季度预缴申报有疑问的,下面是给大家整理了详细第四季度企业所得税预缴申报实银行理财涨回来了?银行理财市场要真正回暖必须有三大特征财经新势力新春季最近,一些人非常兴奋地说,我的银行理财涨回来了。现实中也确实看到一些银行理财产品净值出现回升。目前多只理财产品的净值已企稳回升,部分现金管理类产品已由此前的年化收益降息降准?央行放水?为什么我们工资没涨?收入更追不上房价呢?首先降息,指的是降低利息,不论存款或是贷款利息降低了,有的人敢贷了,有的人不愿意存了,总而言之,市面上的钱变多了。疫情一来LPR变动记录其次降准,指的是降低存款准备金率,通俗的讲,80亿到185亿,蚂蚁消金增资扩股落定,释放哪些信号?时隔一年,蚂蚁消费金融公司的增资扩股方案终于尘埃落定。近日,重庆银保监局发布关于同意重庆蚂蚁消费金融有限公司增加注册资本及调整股权结构的批复(以下简称批复),同意重庆蚂蚁消费金融有
说走就走的旅行黔绿滇蓝走云贵险峻的山水环境避免了外族的侵略,山与山的阻隔使得迁徙而至的部落可以自由繁衍生息,渐渐地便造就了多元的民族文化。加之云贵地区纳入中国版图的时间较晚,受汉文化影响迟,由此,云贵高原成为福州周边游地铁6号线就可以到,长乐南山公园游玩攻略自从福州地铁6号线开通以后,赶海沙滩成了大家周末最喜欢的游玩项目,不过,长乐除了看海,还隐藏着一座惊喜的公园,南山生态公园,地铁直达!南山公园主入口南山公园主入口是在南山生态公园北浓情金秋畅游城固旅游线路来啦十一小长假自驾游出游寻找你的诗和远方离离暑云散袅袅凉风起百般景物堪图画与春夏相比秋冬出游更显心境悠闲心心念念的国庆长假即将到来你有没有听到自己那蠢蠢欲动的心跳?它是在说出发!文小旅星空市集汉服大秀多种花式玩法,国庆不用愁了!锵锵锵锵锵您的国庆假期pro即将上线!还没想好这七天假期去哪儿玩的小伙伴,看过来!三水源旅游度假区准备了超级丰富的花式玩法有的吃有的看有的玩有的学全方位满足你的出行需求!欢度国庆节拒绝消费主义裹挟,年轻人背起帆布包如今,越来越多的年轻人开始放下各种带有大牌标志的手袋,背上了各种各样的帆布包。是什么让他们返璞归真,选择朴实无华的帆布袋呢?记者在采访中发现,年轻人使用的帆布袋并不同于各种免费发放女生穿着制服,为什么会变得诱惑?近两年来,网上播放的电视剧大部分都是军旅片,神圣的军装制服加上精致的容貌,以及帅气的外表,精神又利落简直不要太撩人了!不仅如此,女主也是英姿飒爽,好看极了。比如电视剧特战荣耀里面的Dior最新系列,从自然与历史中看到女性力量就在昨晚,巴黎时装周的第一场重磅大秀Dior2023春夏成衣系列发布会在巴黎杜乐丽花园隆重举办,同时也通过线上直播方式,让全球观众共赏新一季视觉盛宴。迪奥中国品牌大使刘雨昕,迪奥中被韩国小姐姐的穿搭圈粉,没有大长腿也能很美,普通人可以照搬伴随着时尚圈的不断发展,我们每个人的穿搭都需要与时俱进,我们要明白当下流行的趋势是什么,也要知道自身的优劣势,可能我们没有大长腿,但只要你会穿,仍然可以散发出独特的气质,接下来我们见证2500多年历史,石家庄市区最大公园即将开园奋进新时代美丽石家庄头条带你乐享河北河北文旅看图识景这么近那么美周末到河北东垣古城遗址是石家庄市区内最古老的城垣遗址,距今已有2500多年,是石家庄城市的根脉。依托东垣古城遗址而建一棵2500岁的树,一刻金色浪漫乡村度假研学游线路简介重庆市巴南区二圣镇集体村以万亩梨园白象山茶园及云林天乡四季花海为载体,大力发展生态休闲游。王良故居及纪念馆所在地綦江区中华村人文底蕴深厚,境内有凤冠石綦风士气山东济宁值得推荐的十个旅游景点,孔府孔林孔庙在其中曲阜孔庙文庙之首,至圣先师的灵魂祭坛曲阜孔庙,又称阙里至圣庙,位于曲阜市中心鼓楼西侧300米处,是祭祀中国古代著名思想家和教育家孔子的祠庙。始建于鲁哀公十七年(前478年),历代增