基于QT和FFmpeg实现自己的视频播放器FFMediaPlayer(一)——项目总览

news2025/5/18 17:58:11

在音视频开发的学习过程中,开发一款视频播放器是FFmpeg进阶的最好实战方法。本文将基于 QT 和 FFmpeg 着手实现自定义视频播放器 FFMediaPlayer,作为系列文章的开篇,我们先来整体了解项目的设计思路、架构与配置。

一、软件设计五大原则​

在软件项目开发过程中,我们应该尽可能遵循以下 5 个重要的软件设计原则,确保项目具有良好的可维护性、可扩展性和稳定性。​

  • 单一职责原则(SRP):每个类或模块只负责一项单一的功能。在 FFMediaPlayer 中,将视频解码、音频解码、界面渲染、用户交互等功能分别封装到不同的类中。例如,专门创建一个FF_Video类负责调用 FFmpeg 进FF_Audio类处理音频解码,避免功能混杂导致代码臃肿难以维护。​

  • 开放封闭原则(OCP):软件实体(类、模块、函数等)应该对扩展开放,对修改封闭。当我们需要为 FFMediaPlayer 添加新的视频格式支持或特殊播放功能时,通过创建新的类或继承现有类来实现扩展,而不是直接修改已有的稳定代码。比如,后续如果要支持新的视频编码格式,可以继承现有的FF_Decode类,重写解码相关方法。​

  • 里氏替换原则(LSP):所有引用基类的地方必须能透明地使用其子类的对象。在设计 FFMediaPlayer 的类层次结构时,确保子类能够完全替代父类的功能,并且不会出现功能异常。例如,在播放控制相关的类中,子类继承父类的播放、暂停、停止等方法,必须保证这些方法在子类中的行为符合父类的预期。​

  • 接口隔离原则(ISP):客户端不应该依赖它不需要的接口。在 FFMediaPlayer 项目中,将复杂的功能接口拆分成多个小的、特定的接口。比如,将视频播放控制接口与内部解封装解码接口分离,避免一个接口过于庞大,使类只实现自己需要的接口,提高代码的灵活性和可维护性。​

  • 依赖倒置原则(DIP):高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象。在 FFMediaPlayer 中,高层的播放逻辑模块不直接依赖 FFmpeg 底层的具体解码函数,而是通过定义抽象的解码接口,让底层的解码类去实现这些接口,这样可以降低模块之间的耦合度,方便后续替换底层实现。

如果严格遵守以上原则会导致代码封装复杂,我希望平衡代码开发和维护的难度,所以不会严格遵守以上原则。

 二、项目类图

为了更清晰地展示 FFMediaPlayer 项目的架构和类之间的关系,下面通过类图进行呈现:

上述类图从功能维度将 FFMediaPlayer 的核心架构拆解为左右两大核心板块,形成 “窗口交互层” 与 “解封装解码层” 的清晰分工。在左侧窗口交互部分,FF_Mdia_player作为整个播放器的主窗口中枢,通过模块化集成的方式,将负责视频画面渲染的FF_Video_Widget、提供播放进度与控制功能的FF_Slider等组件有机整合,构建出直观的用户交互界面。

右侧解封装解码部分以FF_Demux_Thread为核心枢纽,它犹如整个音视频处理流水线的总指挥,通过精准调度FF_Demux解封装器以及并行运作的FF_Video_Thread视频解码线程、FF_Audio_Thread音频解码线程,实现媒体文件的高效解析与数据提取。在视频处理链路中,FF_Video_Widget专注于视频帧的渲染工作,通过抽象的纯虚函数类FF_Video_CallFF_Video_Thread建立松耦合通信,确保解码后的视频数据能实时流畅地呈现在界面上;音频处理部分则由FF_Audio_Play负责音频播放,同样依托纯虚函数类FF_Audio_CallFF_Audio_Thread对接,保证音频解码与播放的无缝衔接 。这种架构设计既实现了前后端功能的清晰分离,又通过抽象接口保障了各模块间的灵活协作与可扩展性。

三、项目配置​

3.1 开发环境​

  • 操作系统:Windows 11 / Ubuntu 20.04(未来会移植到Ubuntu系统,开发主要再Windows下进行)​
  • 开发工具:Qt 6.7.3  +  VS 2022
  • 编译器:msvc2022_64

3.2 库依赖​

  • QT:版本 6.7.3,用于构建图形用户界面,实现视频播放的界面展示、用户交互等功能。通过 QT 的信号与槽机制,可以方便地处理用户操作和播放状态的更新。​
  • FFmpeg:版本 4.2.1,作为强大的音视频处理库,提供视频解码、音频解码、格式解析等核心功能。在项目中,需要链接 FFmpeg 的多个库文件,如libavcodec、libavformat、libavutil、libswscale、libswresample等。

3.3 新项目创建

打开vs2022,创建一个QT项目

 我们只编译DeBug版本,不配置Release版本,qt导入多媒体库和openGL库

 创建一个基于QWidget的类,注意由于Ubuntu下大小写敏感,我们选择生成小写文件名

 项目生成后直接运行,输出空白窗口,配置完成

 通过以上对软件设计原则、项目类图和项目配置的介绍,相信你对 FFMediaPlayer 项目已经有了一个初步的整体认识。后续系列文章将深入讲解视频解码、音频处理、界面渲染等具体功能的实现,敬请期待!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2378669.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【HCIA】浮动路由

前言 我们通常会在出口路由器配置静态路由去规定流量进入互联网默认应该去往哪里。那么,如果有两个运营商的路由器都能为我们提供上网服务,我们应该如何配置默认路由呢?浮动路由又是怎么一回事呢? 文章目录 前言1. 网络拓扑图2. …

使用instance着色

本节我们学习使用instance着色器进行着色 //拾取var handler new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);handler.setInputAction(function(movement){console.log(movement);var pickedObject viewer.scene.pick(movement.position);if(Cesium.defined(picke…

【NLP 72、Prompt、Agent、MCP、function calling】

命运把我们带到哪里,就是哪里 —— 25.5.13 一、Prompt 1.User Prompt 用户提示词 当我们与大模型进行对话时,我们向大模型发送的消息,称作User Prompt,也就是用户提示词,一般就是我们提出的问题或者想说的话 但是我们…

Mysql数据库之集群进阶

一、日志管理 5.7版本自定义路径时的文件需要自己提前创建好文件,不会自动创建,否则启动mysql会报错 错误日志 rpm包(yum) /var/log/mysql.log 默认错误日志 ###查询日志路径 [rootdb01 ~]# mysqladmin -uroot -pEgon123 variables | grep -w log_e…

临床决策支持系统的提示工程优化路径深度解析

引言 随着人工智能技术在医疗领域的迅猛发展,临床决策支持系统(CDSS)正经历从传统规则引擎向智能提示工程的范式转变。在这一背景下,如何构建既符合循证医学原则又能适应个体化医疗需求的CDSS成为医学人工智能领域的核心挑战。本报告深入剖析了临床决策支持系统中提示工程的…

苹果新一代车载系统CarPlay Ultra来袭,全屏接管+ChatGPT助力,智能驾驶要“起飞”

AITOP100获悉,苹果又搞出大动作啦!正式推出了新一代车载系统——CarPlay Ultra。这次,苹果可是下了狠功夫,把iPhone和汽车的所有显示屏深度整合到了一起,还首次把ChatGPT引入到了驾驶体验当中。这系统可不简单&#xf…

无线信道的噪声与干扰

目录 1. 无线信道(wireless channel)与电磁波 2.1 电磁波的传输(无线信道传输) 2.2 视线(line of sight)传播与天线高度 2. 信道的数学模型 2.1 调制信道模型 2.1.1 加性噪声/加性干扰 2.1.2 乘性噪声/乘性干扰 2.1.3 随参信道/恒参信道 2.2 编码信道模型 2.3 小结 …

MySQL 8.0 OCP 1Z0-908 101-110题

Q101.which two queries are examples of successful SQL injection attacks? A.SELECT id, name FROM backup_before WHERE name‘; DROP TABLE injection; --’; B. SELECT id, name FROM user WHERE id23 oR id32 OR 11; C. SELECT id, name FROM user WHERE user.id (SEL…

BBR 的 buffer 动力学观感

这周很忙,今天还加了一天班,但还是抽空实现了五一在安徽泾县山区喝着一壶酒写的 BBR ProbeRTT 的想法,没多少行代码,它真就消除了带宽锯齿,皮了个鞋👞,昨天我还在群里说了今天再说说 BBR 的&…

Spring之Bean的初始化 Bean的生命周期 全站式解析

目录 导图 步骤 第一步 实例化 第二步 属性赋值 第三步 初始化 aware 接口 BeanPostProcessor 接口 InitializingBean 和 init-method 第四步使用 第五步使用后销毁 描述一下 Bean 的 生命周期 导图 步骤 总体上可以分为五步 首先是 Bean 的实例化Bean 在进行实例…

FreeCAD源码分析: Transaction实现原理

本文阐述FreeCAD中Transaction的实现原理。 注1:限于研究水平,分析难免不当,欢迎批评指正。 注2:文章内容会不定期更新。 一、概念 Ref. from What is a Transaction? A transaction is a group of operations that have the f…

flutter缓存网络视频到本地,可离线观看

记录一下解决问题的过程,希望自己以后可以参考看看,解决更多的问题。 需求:flutter 缓存网络视频文件,可离线观看。 解决: 1,flutter APP视频播放组件调整; 2,找到视频播放组件&a…

Kotlin 中 infix 关键字的原理和使用场景

在 Kotlin 中,使用 infix 关键字修饰的函数称为中缀函数,使用是可以省略 . 和 (),允许以更自然(类似自然语言)的语法调用函数,这种特性可以使代码更具可读性。 1 infix 的原理 中缀函数必须满足以下条件&…

c++从入门到精通(五)--异常处理,命名空间,多继承与虚继承

异常处理 栈展开过程: 栈展开过程沿着嵌套函数的调用链不断查找,直到找到了与异常匹配的catch子句为止;也可能一直没找到匹配的catch,则退出主函数后查找过程终止。栈展开过程中的对象被自动销毁。 在栈展开的过程中&#xff0c…

gcc/g++常用参数

1.介绍 gcc用于编译c语言,g用于编译c 源代码生成可执行文件过程,预处理-编译-汇编-链接。https://zhuanlan.zhihu.com/p/476697014 2.常用参数说明 2.1编译过程控制 参数作用-oOutput,指定输出名字-cCompile,编译源文件生成对…

nginx配置之负载均衡

版权声明:原创作品,请勿转载! 1.实验环境准备 准备3台linux服务器(ubuntu和centos均可,本文使用centos7.9),两台web和一台负载均衡服务器,均安装nginx服务 主机名IP软件lb0110.0.0…

去年开发一款鸿蒙Next Os的window工具箱

持拖载多个鸿蒙应用 批量签名安装 运行 http://dl.lozn.top/lozn/HarmonySignAndFileManagerTool_2024-11-26.zip 同类型安卓工具箱以及其他软件下载地址汇总 http://dl.lozn.top/lozn/ 怎么个玩法呢,比如要启动某app, 拖载识别到包名 点启动他能主动读取包名 然后…

uniapp|实现获取手机摄像头权限,调用相机拍照实现人脸识别相似度对比,拍照保存至相册,多端兼容(APP/微信小程序)

基于uniapp以及微信小程序实现移动端人脸识别相似度对比,实现摄像头、相册权限获取、相机模块交互、第三方识别集成等功能,附完整代码。 目录 核心功能实现流程摄像头与相册权限申请权限拒绝后的引导策略摄像头调用拍照事件处理人脸识别集成图片预处理(Base64编码/压缩)调用…

JavaScript【7】BOM模型

1.概述: BOM(Browser Object Model,浏览器对象模型)是 JavaScript 中的一个重要概念,它提供了一系列对象来访问和操作浏览器的功能和信息。与 DOM(Document Object Model)主要关注文档结构不同&…

[强化学习的数学原理—赵世钰老师]学习笔记02-贝尔曼方程

本人为强化学习小白,为了在后续科研的过程中能够较好的结合强化学习来做相关研究,特意买了西湖大学赵世钰老师撰写的《强化学习数学原理》中文版这本书,并结合赵老师的讲解视频来学习和更深刻的理解强化学习相关概念,知识和算法技…