参考雷神的最简单的打印Hello World的程序:

#include <stdio.h>
#include <string.h> 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 = "bad.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]/*视音频流*/->codec->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的指针
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]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
{
audioIndex = i;
break;
}
}
if (audioIndex == -1)
{
printf("Couldn't find a audio stream.\n");
return -1;
} //打印结构体信息 puts("AVFormatContext信息:");
puts("---------------------------------------------");
printf("文件名:%s\n", pFormatCtx->filename);
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]->codec->sample_rate);
printf("音频信道数目:%d\n", pFormatCtx->streams[audioIndex]->codec->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_close(pCodecCtx);
avformat_close_input(&pFormatCtx);
return 0;
}

虽然足够的简单,但是还是报了”被声明为已否决”的error

在网上搜索到了解决方案:将VS的SDL检查关闭

这样error被降低为warning C4996

这样的解决方案是很冒险的。根据报错g:\coding\poet\ffmpegstudy\study.cpp(44): warning C4996: 'AVStream::codec': 被声明为已否决

我们定位到所在代码:

if (pFormatCtx->streams[i]/*视音频流*/->codec->codec_type == AVMEDIA_TYPE_VIDEO)//查找音频
{
videoIndex = i;
break;
}
#if FF_API_LAVF_AVCTX
/**
* @deprecated use the codecpar struct instead
*/
attribute_deprecated
AVCodecContext *codec;
#endif

AVStream的codec成员不再推荐使用,反而要求使用codecpar。

从而我们知道FFmpeg中所谓的“被声明为已否决”就是因为函数或者结构体属性被标示为attribute_deprecated,很有可能在未来的版本中就删除了。

所以我们最好的解决方案就是使用新的被推荐使用的函数、结构体等。

修改版(开启SDL检查也没有error与warning):

#include <stdio.h>
#include <string.h> 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 = "bad.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("---------------------------------------------");
printf("文件名:%s\n", pFormatCtx->filename);
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);
return 0;
}

参考自:ffplay.c

最新文章

  1. Django数据导入
  2. Linux服务器高并发实践经历
  3. XSS常用技巧
  4. php生成唯一订单号
  5. windows python文件拷贝到linux上执行问题
  6. 将数据库备份到AZURE blob storage
  7. Visual Studio 2010添加新项缺失[ADO.NET 实体数据模型]解决方法
  8. 关于c#中的Timer控件的简单用法
  9. PHP之ThinkPHP模板标签操作
  10. IOS 动画专题 --iOS核心动画
  11. TFS发布计划发送到钉钉消息群
  12. hihoCoder 1044 : 状态压缩·一 状压dp
  13. SpringMVC 环境搭建(HelloWorld)
  14. c#调用野狗云 rest api
  15. Ubuntu下基于Virtualenv构建Python开发环境
  16. ORM概念
  17. 关于栈和队列的一点点小知识-----C++自带函数
  18. kafka+docker+python
  19. jsp中文乱码解决办法
  20. j2ee高级开发技术课程第四周

热门文章

  1. 「洛谷P1233」木棍加工 解题报告
  2. Java和JavaScript之间的区别
  3. 《图解机器学习-杉山将著》读书笔记---CH4
  4. 在Winform界面中使用DevExpress的TreeList实现节点过滤查询的两种方式
  5. Winform在控件内实现简单画笔功能
  6. 小白学Java:老师!泛型我懂了!
  7. (1)解锁 MongoDB replica set核心姿势
  8. 一键部署k8s 、docker 工具集——最新版本
  9. JVM系列七(JIT 即时编译器).
  10. ST表竞赛模板