Qt5.9.0+VS2017+ffmpeg4.4.3,这里版本均使用64位版本。
Qt的版本大于我这个版本都行。
opengl3.3,Qt已经封装好了QOpenGLWidget,直接使用Qt的就行。
Qt版本下载:Index of /archive/qt
Releases · BtbN/FFmpeg-Builds · GitHub
解压后,里面的文件如下图所示,包含静态库、动态库、头文件。
打开VS,选择工具->扩展和更新。
选择联机->搜索Qt Visual Studio Tools,点击下载, 自动安装插件。
安装完成之后,重启VS,在工具栏就会看见Qt VS Tools字样
点击 Qt VS Tools->Qt Options->add,添加自己的Qt版本。
选择Qt Widgets Application,新建VideoPlayer工程。
新建3rd目录。
将目录 2ffmpeg下载的文件解压出来,将所有文件拷贝到3rd目录下。
右键打开配置环境
常规->输出目录->修改生成程序目录
调试->工作目录->修改
C/C++->附加包含目录->修改
链接器->附加库目录->修改
- #include
- #include
- #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();
- }
运行结果