Qt+FFmpeg+opengl从零制作视频播放器-2.环境搭建

1.环境介绍

Qt5.9.0+VS2017+ffmpeg4.4.3,这里版本均使用64位版本。

Qt的版本大于我这个版本都行。

opengl3.3,Qt已经封装好了QOpenGLWidget,直接使用Qt的就行。

Qt版本下载:Index of /archive/qt

2.ffmpeg下载

Releases · BtbN/FFmpeg-Builds · GitHub

解压后,里面的文件如下图所示,包含静态库、动态库、头文件。

3.VS安装QT插件

打开VS,选择工具->扩展和更新。

选择联机->搜索Qt Visual Studio Tools,点击下载, 自动安装插件。

安装完成之后,重启VS,在工具栏就会看见Qt VS Tools字样

 点击 Qt VS Tools->Qt Options->add,添加自己的Qt版本。

4.配置ffmpeg

 选择Qt Widgets Application,新建VideoPlayer工程。

 新建3rd目录。

将目录 2ffmpeg下载的文件解压出来,将所有文件拷贝到3rd目录下。

右键打开配置环境

常规->输出目录->修改生成程序目录

调试->工作目录->修改  

C/C++->附加包含目录->修改  

链接器->附加库目录->修改 

5.运行程序

#include <QApplication>
#include <iostream>
#include "MainWindow.h"

#pragma execution_character_set("utf-8")

extern "C"
{
#include "libavformat/avformat.h"
#include "libavutil/dict.h"
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
	//MainWindow w;
	//w.show();
	setlocale(LC_ALL,"zh_CN.UTF-8");
	AVFormatContext *pFormatCtx = NULL;
	AVCodecContext *pCodecCtx = NULL;
	AVCodec *pCodec;
	AVDictionaryEntry *dict = NULL;

	int iHour, iMinute, iSecond, iTotalSeconds;//HH:MM:SS
	int videoIndex, audioIndex;

	char fileName[] = "F:/1920x1080.mp4";

	if (avformat_open_input(&pFormatCtx, fileName, NULL, NULL) != 0)//打开输入视频文件
	{
		printf("Couldn't open input stream.\n");
		return -1;
	}

	if (avformat_find_stream_info(pFormatCtx, NULL) < 0)
	{
		printf("Couldn't find stream information.\n");
		return -1;
	}

	videoIndex = -1;
	for (int i = 0; i < pFormatCtx->nb_streams; i++)
	{
		if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)//查找音频
		{
			videoIndex = i;
			break;
		}
	}
	if (videoIndex == -1)
	{
		printf("Couldn't find a video stream.\n");
		return -1;
	}

	pCodecCtx = avcodec_alloc_context3(NULL);
	if (pCodecCtx == NULL)
	{
		printf("Could not allocate AVCodecContext\n");
		return -1;
	}
	avcodec_parameters_to_context(pCodecCtx, pFormatCtx->streams[videoIndex]->codecpar);

	pCodec = avcodec_find_decoder(pCodecCtx->codec_id);	//指向AVCodec的指针.查找解码器
	if (pCodec == NULL)
	{
		printf("Codec not found.\n");
		return -1;
	}
	//打开解码器
	if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0)
	{
		printf("Could not open codec.\n");
		return -1;
	}

	audioIndex = -1;
	for (int i = 0; i < pFormatCtx->nb_streams; i++)
	{
		if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
		{
			audioIndex = i;
			break;
		}
	}
	if (audioIndex == -1)
	{
		printf("Couldn't find a audio stream.\n");
		return -1;
	}

	//打印结构体信息
	puts("AVFormatContext信息:");
	puts("---------------------------------------------");
	iTotalSeconds = (int)pFormatCtx->duration/ 1000000;
	iHour = iTotalSeconds / 3600;//小时
	iMinute = iTotalSeconds % 3600 / 60;//分钟
	iSecond = iTotalSeconds % 60;//秒
	printf("持续时间:%02d:%02d:%02d\n", iHour, iMinute, iSecond);
	printf("平均混合码率:%d kb/s\n", pFormatCtx->bit_rate / 1000);
	printf("视音频个数:%d\n", pFormatCtx->nb_streams);
	puts("---------------------------------------------");

	puts("AVInputFormat信息:");
	puts("---------------------------------------------");
	printf("封装格式名称:%s\n", pFormatCtx->iformat->name);
	printf("封装格式长名称:%s\n", pFormatCtx->iformat->long_name);
	printf("封装格式扩展名:%s\n", pFormatCtx->iformat->extensions);
	printf("封装格式ID:%d\n", pFormatCtx->iformat->raw_codec_id);
	puts("---------------------------------------------");

	puts("AVStream信息:");
	puts("---------------------------------------------");
	printf("视频流标识符:%d\n", pFormatCtx->streams[videoIndex]->index);
	printf("音频流标识符:%d\n", pFormatCtx->streams[audioIndex]->index);
	printf("视频流长度:%d微秒\n", pFormatCtx->streams[videoIndex]->duration);
	printf("音频流长度:%d微秒\n", pFormatCtx->streams[audioIndex]->duration);
	puts("---------------------------------------------");

	puts("AVCodecContext信息:");
	puts("---------------------------------------------");
	printf("视频码率:%d kb/s\n", pCodecCtx->bit_rate / 1000);
	printf("视频大小:%d * %d\n", pCodecCtx->width, pCodecCtx->height);
	puts("---------------------------------------------");

	puts("AVCodec信息:");
	puts("---------------------------------------------");
	printf("视频编码格式:%s\n", pCodec->name);
	printf("视频编码详细格式:%s\n", pCodec->long_name);
	puts("---------------------------------------------");

	printf("视频时长:%d微秒\n", pFormatCtx->streams[videoIndex]->duration);
	printf("音频时长:%d微秒\n", pFormatCtx->streams[audioIndex]->duration);
	printf("音频采样率:%d\n", pFormatCtx->streams[audioIndex]->codecpar->sample_rate);
	printf("音频信道数目:%d\n", pFormatCtx->streams[audioIndex]->codecpar->channels);

	puts("AVFormatContext元数据:");
	puts("---------------------------------------------");
	while (dict = av_dict_get(pFormatCtx->metadata, "", dict, AV_DICT_IGNORE_SUFFIX))
	{
		printf("[%s] = %s\n", dict->key, dict->value);
	}
	puts("---------------------------------------------");

	puts("AVStream视频元数据:");
	puts("---------------------------------------------");
	dict = NULL;
	while (dict = av_dict_get(pFormatCtx->streams[videoIndex]->metadata, "", dict, AV_DICT_IGNORE_SUFFIX))
	{
		printf("[%s] = %s\n", dict->key, dict->value);
	}
	puts("---------------------------------------------");

	puts("AVStream音频元数据:");
	puts("---------------------------------------------");
	dict = NULL;
	while (dict = av_dict_get(pFormatCtx->streams[audioIndex]->metadata, "", dict, AV_DICT_IGNORE_SUFFIX))
	{
		printf("[%s] = %s\n", dict->key, dict->value);
	}
	puts("---------------------------------------------");


	av_dump_format(pFormatCtx, -1, fileName, 0);
	printf("\n\n编译信息:\n%s\n\n", avcodec_configuration());

	avcodec_free_context(&pCodecCtx);
	//avcodec_close(pCodecCtx);
	avformat_close_input(&pFormatCtx);
	system("pause");
    return a.exec();
}

运行结果 

6.ffmpeg库下载

https://download.csdn.net/download/wzz953200463/88883243

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

鸿蒙即将抛弃Android,你还不来学习一下?

前言 最近移动开发圈子里&#xff0c;鸿蒙可谓出尽了风头&#xff0c;先是宣布即将正式发布的 Harmony OS Next 将完全剥离 Android 代码&#xff0c;也就是不再兼容 Android&#xff0c;化身为纯血的鸿蒙&#xff0c;紧接着又启动了鸿蒙生态千帆启航&#xff0c;伴随着的是众…

【论文阅读】(2006)Dual-Optimal Inequalities for Stabilized Column Generation

文章目录 摘要一、介绍二、对偶最优不等式&#xff08;Dual-Optimal Inequalities&#xff09;三、确定P的最优原始解四、二元切割下料问题4.1 约束聚合4.2 相等约束4.3 计算结果 五、切割下料问题5.1 计算结果 六、三元组的深度对偶最优不等式&#xff08;Deep Dual-Optimal I…

『Linux从入门到精通』第 ㉕ 期 - System V 共享内存

文章目录 &#x1f490;专栏导读&#x1f490;文章导读&#x1f427;共享内存原理&#x1f427;共享内存相关函数&#x1f426;key 与 shmid 区别 &#x1f427;代码实例 &#x1f490;专栏导读 &#x1f338;作者简介&#xff1a;花想云 &#xff0c;在读本科生一枚&#xff0…

9.WEB渗透测试-Linux基础知识-Linux用户权限管理(上)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a; 易锦网校会员专享课 上一个内容&#xff1a;8.WEB渗透测试-Linux基础知识-Linux基础操作&#xff08;二&#xff09;-CSDN博客 用户管…

详细分析Linux内存知识并释放内存

目录 前言1. 基本知识1.1 free1.2 cat /proc/meminfo1.3 slabtop 2. 清空内存 前言 本篇文章主要分析内存 如果是磁盘空间&#xff0c;推荐阅读&#xff1a;服务器出现根目录磁盘满了解决方法 1. 基本知识 在Linux系统中&#xff0c;查看内存的基本知识包括以下几个方面&…

Nginx配置php起WoWSimpleRegistration服务

WoWSimpleRegistration服务的git地址&#xff1a; GitHub - TrinityCore/WoWSimpleRegistration: Simple Registration page for TrinityCore/AzerothCore/AshamaneCore/CMangos 下载WoWSimpleRegistration 首先git下载&#xff1a; git clone https://github.com/TrinityC…

嵌入式基础知识-信号量,PV原语与前趋图

本篇来介绍信号量与PV原语的一些知识&#xff0c;并介绍其在前趋图上的应用分析。本篇的知识属于操作系统部分的通用知识&#xff0c;在嵌入式软件开发中&#xff0c;同样会用到这些知识。 1 信号量 信号量是最早出现的用来解决进程同步与互斥问题的机制&#xff08;可以把信…

基于springboot+vue的贸易行业crm系统

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

Ainx的全局配置

&#x1f4d5;作者简介&#xff1a; 过去日记&#xff0c;致力于Java、GoLang,Rust等多种编程语言&#xff0c;热爱技术&#xff0c;喜欢游戏的博主。 &#x1f4d7;本文收录于Ainx系列&#xff0c;大家有兴趣的可以看一看 &#x1f4d8;相关专栏Rust初阶教程、go语言基础系列…

华硕B660-PLUS主板开机直接BIOS解决方案

一、背景说明 采购了配件&#xff0c;换了主机&#xff0c;主板是华硕的B660&#xff0c;没有显卡。然后把原电脑的固态硬盘和机械硬盘直接移过来。结果开机直接进bios&#xff0c;就是进不了系统&#xff0c;一直进入下面这个页面。 可以读取到两块硬盘&#xff0c;但是没有…

【Windows11】相关问题与解决方案

目录 frp内网穿透windows配置开机启动设置开机自启动内存使用率只有总内存容量的一半kms激活win10无法连接任何密钥管理服务器的解决方法 frp内网穿透windows配置开机启动 参考frp内网穿透windows配置开机启动 设置开机自启动 路径在C:\Users\用户名\AppData\Roaming\Micros…

uniapp实现进度条组件

首先&#xff0c;在uniapp项目中创建一个自定义组件&#xff0c;可以命名为Progress.vue。在Progress.vue中&#xff0c;编写如下代码&#xff1a; <template><view class"progress"><view class"progress-bar" :style"{width: progr…

Matlab 机器人工具箱 符合动力学

文章目录 1 符合化表示1.1 标准DH动力学1.2 改进DH动力学 质量集中在质心1.2 改进DH动力学 质量集中在末端1.3 程序问题1.3.1 Unable to perform assignment because value of type sym is not convertible to double.1.3.2 CAT arguments dimensions not consistent.参考链接1…

YOLOv5独家原创改进:特征融合涨点篇 | 广义高效层聚合网络(GELAN) | YOLOv9

💡💡💡本文独家改进:即结合用梯度路径规划(CSPNet)和(ELAN)设计了一种广义的高效层聚合网络(GELAN),高效结合YOLOv5,实现涨点。 将GELAN添加在backbone和head处,提供多个yaml改进方法 💡💡💡在多个私有数据集和公开数据集VisDrone2019、PASCAL VOC实现…

前端学习之HTML(第一天)

什么是HTML HTML是一种用来描述网页的一种语言&#xff0c;HTML不是一种编程语言&#xff0c;而是一种标记语言。 HTML标签 HTML 标签是由尖括号包围的关键词&#xff0c;比如 <html> HTML 标签通常是成对出现的&#xff0c;比如 <b> 和 </b> 标签对中的…

【微服务-Nacos】一篇文章教你搞定Nacos部署

前面我们提到过&#xff0c;在微服务架构中&#xff0c;Nacos注册中心属于核心组件&#xff0c;通常我们会采用高性能独立服务器进行部署&#xff0c;下面我们一起来看看Nacos部署过程&#xff1a; 1、环境准备 因为Nacos是支持windows和Linux系统的&#xff0c;且服务器操作…

订单超时取消如何实现

方法1&#xff1a; DelayQueue&#xff1a;超时作为排序条件&#xff0c;轮询订单头部&#xff0c;若超市&#xff0c;出队进行超时处理 优点&#xff1a;简单 缺点&#xff1a;不能持久化&#xff0c;并发量低 方法2&#xff1a; 方法四&#xff1a;定时调度&#xff08;什…

基于Springboot的无人智慧超市管理系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的无人智慧超市管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系…

【项目实践】如何解决并发场景下数据一致性问题

1.背景 并发写场景下&#xff0c;由于微服务的系统环境复杂&#xff0c;不可避免的会出现 【机器、缓存、数据库、依赖服务】等出现问题&#xff0c;导致数据不一致的情况产生。 影响大且广&#xff1a; 1、数据不一致问题在线上可能会产生故障 2、数据不一致会导致长尾错误…

group by报错

# 报错&#xff1a;[42000][1055] Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column base.biz_org_rep.ID which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_modeonly_full_grou…