zoukankan      html  css  js  c++  java
  • 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.
    ");
    		return -1;
    	}
    
    	if (avformat_find_stream_info(pFormatCtx, NULL) < 0)
    	{
    		printf("Couldn't find stream information.
    ");
    		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.
    ");
    		return -1;
    	}
    
    	pCodecCtx = pFormatCtx->streams[videoIndex]->codec;	//指向AVCodecContext的指针
    	pCodec = avcodec_find_decoder(pCodecCtx->codec_id);	//指向AVCodec的指针.查找解码器
    	if (pCodec == NULL)
    	{
    		printf("Codec not found.
    ");
    		return -1;
    	}
    	//打开解码器
    	if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0)
    	{
    		printf("Could not open codec.
    ");
    		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.
    ");
    		return -1;
    	}
    
    	
    
    	//打印结构体信息
    
    	puts("AVFormatContext信息:");
    	puts("---------------------------------------------");
    	printf("文件名:%s
    ", pFormatCtx->filename);
    	iTotalSeconds = (int)pFormatCtx->duration/*微秒*/ / 1000000;
    	iHour = iTotalSeconds / 3600;//小时
    	iMinute = iTotalSeconds % 3600 / 60;//分钟
    	iSecond = iTotalSeconds % 60;//秒
    	printf("持续时间:%02d:%02d:%02d
    ", iHour, iMinute, iSecond);
    	printf("平均混合码率:%d kb/s
    ", pFormatCtx->bit_rate / 1000);
    	printf("视音频个数:%d
    ", pFormatCtx->nb_streams);
    	puts("---------------------------------------------");
    
    	puts("AVInputFormat信息:");
    	puts("---------------------------------------------");
    	printf("封装格式名称:%s
    ", pFormatCtx->iformat->name);
    	printf("封装格式长名称:%s
    ", pFormatCtx->iformat->long_name);
    	printf("封装格式扩展名:%s
    ", pFormatCtx->iformat->extensions);
    	printf("封装格式ID:%d
    ", pFormatCtx->iformat->raw_codec_id);
    	puts("---------------------------------------------");
    
    	puts("AVStream信息:");
    	puts("---------------------------------------------");
    	printf("视频流标识符:%d
    ", pFormatCtx->streams[videoIndex]->index);
    	printf("音频流标识符:%d
    ", pFormatCtx->streams[audioIndex]->index);
    	printf("视频流长度:%d微秒
    ", pFormatCtx->streams[videoIndex]->duration);
    	printf("音频流长度:%d微秒
    ", pFormatCtx->streams[audioIndex]->duration);
    	puts("---------------------------------------------");
    
    	puts("AVCodecContext信息:");
    	puts("---------------------------------------------");
    	printf("视频码率:%d kb/s
    ", pCodecCtx->bit_rate / 1000);
    	printf("视频大小:%d * %d
    ", pCodecCtx->width, pCodecCtx->height);
    	puts("---------------------------------------------");
    
    	puts("AVCodec信息:");
    	puts("---------------------------------------------");
    	printf("视频编码格式:%s
    ", pCodec->name);
    	printf("视频编码详细格式:%s
    ", pCodec->long_name);
    	puts("---------------------------------------------");
    
    	printf("视频时长:%d微秒
    ", pFormatCtx->streams[videoIndex]->duration);
    	printf("音频时长:%d微秒
    ", pFormatCtx->streams[audioIndex]->duration);
    	printf("音频采样率:%d
    ", pFormatCtx->streams[audioIndex]->codec->sample_rate);
    	printf("音频信道数目:%d
    ", pFormatCtx->streams[audioIndex]->codec->channels);
    
    	puts("AVFormatContext元数据:");
    	puts("---------------------------------------------");
    	while (dict = av_dict_get(pFormatCtx->metadata, "", dict, AV_DICT_IGNORE_SUFFIX))
    	{
    		printf("[%s] = %s
    ", 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
    ", 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
    ", dict->key, dict->value);
    	}
    	puts("---------------------------------------------");
    
    
    	av_dump_format(pFormatCtx, -1, fileName, 0);
    	printf("
    
    编译信息:
    %s
    
    ", avcodec_configuration());
    
    
    	avcodec_close(pCodecCtx);
    	avformat_close_input(&pFormatCtx);
    	return 0;
    }
    

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

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


    这样error被降低为warning C4996

    这样的解决方案是很冒险的。根据报错g:codingpoetffmpegstudystudy.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.
    ");
    		return -1;
    	}
    
    	if (avformat_find_stream_info(pFormatCtx, NULL) < 0)
    	{
    		printf("Couldn't find stream information.
    ");
    		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.
    ");
    		return -1;
    	}
    
    	/**
    	*  不赞成这样使用
    	*  pCodecCtx = pFormatCtx->streams[videoIndex]->codec;	//指向AVCodecContext的指针
    	*/
    
    	pCodecCtx = avcodec_alloc_context3(NULL);
    	if (pCodecCtx == NULL)
    	{
    		printf("Could not allocate AVCodecContext
    ");
    		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.
    ");
    		return -1;
    	}
    	//打开解码器
    	if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0)
    	{
    		printf("Could not open codec.
    ");
    		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.
    ");
    		return -1;
    	}
    
    	
    
    	//打印结构体信息
    
    	puts("AVFormatContext信息:");
    	puts("---------------------------------------------");
    	printf("文件名:%s
    ", pFormatCtx->filename);
    	iTotalSeconds = (int)pFormatCtx->duration/*微秒*/ / 1000000;
    	iHour = iTotalSeconds / 3600;//小时
    	iMinute = iTotalSeconds % 3600 / 60;//分钟
    	iSecond = iTotalSeconds % 60;//秒
    	printf("持续时间:%02d:%02d:%02d
    ", iHour, iMinute, iSecond);
    	printf("平均混合码率:%d kb/s
    ", pFormatCtx->bit_rate / 1000);
    	printf("视音频个数:%d
    ", pFormatCtx->nb_streams);
    	puts("---------------------------------------------");
    
    	puts("AVInputFormat信息:");
    	puts("---------------------------------------------");
    	printf("封装格式名称:%s
    ", pFormatCtx->iformat->name);
    	printf("封装格式长名称:%s
    ", pFormatCtx->iformat->long_name);
    	printf("封装格式扩展名:%s
    ", pFormatCtx->iformat->extensions);
    	printf("封装格式ID:%d
    ", pFormatCtx->iformat->raw_codec_id);
    	puts("---------------------------------------------");
    
    	puts("AVStream信息:");
    	puts("---------------------------------------------");
    	printf("视频流标识符:%d
    ", pFormatCtx->streams[videoIndex]->index);
    	printf("音频流标识符:%d
    ", pFormatCtx->streams[audioIndex]->index);
    	printf("视频流长度:%d微秒
    ", pFormatCtx->streams[videoIndex]->duration);
    	printf("音频流长度:%d微秒
    ", pFormatCtx->streams[audioIndex]->duration);
    	puts("---------------------------------------------");
    
    	puts("AVCodecContext信息:");
    	puts("---------------------------------------------");
    	printf("视频码率:%d kb/s
    ", pCodecCtx->bit_rate / 1000);
    	printf("视频大小:%d * %d
    ", pCodecCtx->width, pCodecCtx->height);
    	puts("---------------------------------------------");
    
    	puts("AVCodec信息:");
    	puts("---------------------------------------------");
    	printf("视频编码格式:%s
    ", pCodec->name);
    	printf("视频编码详细格式:%s
    ", pCodec->long_name);
    	puts("---------------------------------------------");
    
    	printf("视频时长:%d微秒
    ", pFormatCtx->streams[videoIndex]->duration);
    	printf("音频时长:%d微秒
    ", pFormatCtx->streams[audioIndex]->duration);
    	printf("音频采样率:%d
    ", pFormatCtx->streams[audioIndex]->codecpar->sample_rate);
    	printf("音频信道数目:%d
    ", pFormatCtx->streams[audioIndex]->codecpar->channels);
    
    	puts("AVFormatContext元数据:");
    	puts("---------------------------------------------");
    	while (dict = av_dict_get(pFormatCtx->metadata, "", dict, AV_DICT_IGNORE_SUFFIX))
    	{
    		printf("[%s] = %s
    ", 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
    ", 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
    ", dict->key, dict->value);
    	}
    	puts("---------------------------------------------");
    
    
    	av_dump_format(pFormatCtx, -1, fileName, 0);
    	printf("
    
    编译信息:
    %s
    
    ", avcodec_configuration());
    
    	avcodec_free_context(&pCodecCtx);
    	//avcodec_close(pCodecCtx);
    	avformat_close_input(&pFormatCtx);
    	return 0;
    }
    
    参考自:ffplay.c







    Keep it simple!
    作者:N3verL4nd
    知识共享,欢迎转载。
  • 相关阅读:
    pmtk3
    SIFT算法研究
    Kd-Tree算法原理和开源实现代码
    统计学习精要
    svm
    UIUC同学Jia-Bin Huang收集的计算机视觉代码合集
    图像识别领域的一些code
    传输媒体、表示媒体、感觉媒体、表现媒体的区别
    海明码奇偶校验
    ip和子网掩码的判断
  • 原文地址:https://www.cnblogs.com/lgh1992314/p/5834634.html
Copyright © 2011-2022 走看看