搭建QT+ffmpeg+Visual Studio开发环境
1.环境介绍
本文使用的是版本 Qt5.9.2+VS2017+ffmpeg4.2.1,这里版本均使用32位版本
2.Qt版本下载
http://download.qt.io/archive/qt/
3.下载ffmpeg
打开https://ffmpeg.zeranoe.com/builds/,该网站中的FFMPEG分为3个版本:Static,Shared,Dev,都下载下来。
1.Dev:这个目录下面主要有我们需要用到的头文件和静态库。
2.Shared:这个目录下有我们运行所依赖的动态库。
4.VS安装Qt插件
打开VS,选择工具->扩展和更新。
选择联机->搜索Qt Visual Studio Tools,点击下载, 自动安装插件。
安装完成之后,重启VS,在工具栏就会看见Qt VS Tools字样
点击 Qt VS Tools->Qt Options->add,添加自己的Qt版本。
5.配置ffmpeg
首先在自己选个盘,在根目录下建立文件夹。我选择的是在E:/ffmpegTests。
紧接着在ffmpegTests文件夹下面创建如下文件夹。建立四个文件夹,分别用来存储静态库、动态库、源代码、包含头文件。
然后将下载的ffmpeg Dev目录下include文件拷贝到我们建立文件夹的include目录下。
同理,将Dev目录下lib文件拷贝到我们的lib下。
将 Shared目录下bin文件下的内容拷贝到我们的bin目录下。
6.新建VS工程
注意:这里不要勾选 为解决方案创建目录
右键打开配置环境
常规->输出目录->修改
调试->工作目录->修改
C/C++->附加包含目录->修改
链接器->附加库目录->修改
7.运行程序
在我们的bin目录下放上一个MP4文件,可以看见详细信息
#include <iostream>
extern "C"
{
#include "libavformat/avformat.h"
#include "libavutil/dict.h"
};
#pragma comment(lib, "avformat.lib")
#pragma comment(lib, "avutil.lib")
#pragma comment(lib, "avcodec.lib")
int main()
{
AVFormatContext *pFormatCtx = NULL;
AVCodecContext *pCodecCtx = NULL;
AVCodec *pCodec;
AVDictionaryEntry *dict = NULL;
int iHour, iMinute, iSecond, iTotalSeconds;//HH:MM:SS
int videoIndex, audioIndex;
char fileName[] = "可不可以.mp4";
//char *fileName = "Titanic.ts";
//注册所有组件 新版本已弃用
//av_register_all();
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 = pFormatCtx->streams[videoIndex]->codec; //指向AVCodecContext的指针
*/
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 0;
}
8.运行结果
上一篇: RTP协议分析