FFmpeg被声明为已否决的解决方案
参考雷神的最简单的打印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
FFmpeg被声明为已否决的解决方案的更多相关文章
- FFmpeg 被声明为已否决 deprecated(2018 精)
不用再取消SDL检查,不用再添加#pragma warning(disable :4996),下面才是正确的解决方法!! 以下是一些常见的deprecated问题,遇到下述没有列出的问题,可以打开相应 ...
- [转载] FFmpeg 错误 C4996: ‘avcodec_alloc_frame’: 被声明为已否决 解决方法
在 Visual Studio 2013 下编写 FFmpeg 程序时出错,错误如下: 出错代码如下: 解决方法为:将 avcodec_alloc_frame() 替换为 av_frame_alloc ...
- error C4996: 'GetVersionExW': 被声明为已否决
1.Project Properties > Configuration Properties > C/C++ > General > SDL checks关掉 其他方法:2. ...
- vs2013编译过程中,错误 59 error C4996: 'GetVersionExW': 被声明为已否决
好几次碰到这个错误,必须mark 一下!!!!!Project Properties > Configuration Properties > C/C++ > General > ...
- VS提示“项目文件" "已被重命名或已不在解决方案中”的解决办法 .
多个项目的源码在一个源代码中,其中,有一个源代码废弃不可用了.删除后,再次生成解决方案时出现了问题“项目文件" "已被重命名或已不在解决方案中”. 解决方法是: 1.找到主项目,右 ...
- Mac安装文件已勾选“允许任何来源”,还是提示“文件已损坏”的解决方案
Mac安装文件已勾选"允许任何来源",还是提示"文件已损坏"的解决方案 打开终端,在终端中粘贴下面命令:[sudo xattr -r -d com.apple. ...
- Genymotion关于【启动后player.exe已停止运行】解决方案总结
1. 你硬盘空间不足,或是暂存区不够,请少执行一些程序或关掉一些p2p的程序,或是到控制面板卸载一些不必要的程序.最好的建议是定期进行硬盘清理,确保不浪费多余空间 ---以上来源(http://www ...
- vs2012 它已停止工作 - 解决方案
最近学习<Windows多媒体编程>本课程, 蛋疼, 学校原来是MFC... 然后安装vs2012. 后来又在几个插件.. 在这个问题. 开业,提示 vs2012 它已停止工作. wa ...
- vue2.3时使用手机调试,提示媒体已断开的解决方案
参考链接:http://www.xitonghe.com/jiaocheng/windows7-9623.html 1.在当前版本vue下开发,发现只能在localhost时调试,不能使用电脑的ip, ...
随机推荐
- $CF24D\ Broken Robot\ DP+$高斯消元
Luogu Description 你收到的礼物是一个非常聪明的机器人,行走在一块长方形的木板上.不幸的是,你知道它是坏的,表现得相当奇怪(随机).该板由n行和m列的单元格组成.机器人最初是在i行和j ...
- 无聊读论文:视觉注意力模型RARE2012
Riche, N., Mancas, M., Duvinage, M., Mibulumukini, M., Gosselin, B., & Dutoit, T. (2013). RARE20 ...
- MinGW-W64下载与安装
安装方案 1 下载安装包,MinGW-w64 - for 32 and 64 bit Windows,然后直接以管理员安装即可,但是这个方案在部分电脑可能不行,会提示 cannot download ...
- 吴恩达机器学习笔记 - cost function and gradient descent
一.简介 cost fuction是用来判断机器预算值和实际值得误差,一般来说训练机器学习的目的就是希望将这个cost function减到最小.本文会介绍如何找到这个最小值. 二.线性回归的cost ...
- linux文件通配符
* #匹配任意字符 ? #匹配任意单个字符 ~ #当前用户家目录 ~user #用户user的家目录 ~+ #当前工作目录 ~- #前一个工作目录 [0-9] #匹配的数字范围 [a-z] #匹配小写 ...
- cogs 647. [Youdao2010] 有道搜索框 Trie树 字典树
647. [Youdao2010] 有道搜索框 ★☆ 输入文件:youdao.in 输出文件:youdao.out 简单对比时间限制:1 s 内存限制:128 MB [问题描述] 在有 ...
- [bzoj4825] [loj#2018] [Hnoi2017] 单旋
Description \(H\) 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(\(splay\))是一种数据 结构,因为代码好写,功能多,效率高,掌握这种数据结构 ...
- [bzoj4444] [loj#2007] [洛谷P4155] [Scoi2015] 国旗计划
Description \(A\) 国正在开展一项伟大的计划--国旗计划.这项计划的内容是边防战士手举国旗环绕边境线奔袭一圈.这项计划需要多名边防战士以接力的形式共同完成,为此,国土安全局已经挑选了 ...
- pikachu漏洞练习之sql注入
这里因为实验的时候只记录了一部分所以就展示一部分 1.1.1数字型注入 (1)看到界面发现是查询id功能,没有在url里看到有传参所以应该是post方法提交数据. (2)进行sql注入之前我们最好是先 ...
- Ubuntu16手动安装OpenStack——nova篇。。转
前言: 本文转自https://www.voidking.com/dev-ubuntu16-manual-openstack-nova/ ,过程非常的详细,作者也说本实验最终失败,因为课程要求我们只要 ...