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;
}

雖然足夠的簡單,可是仍是報了」被聲明爲已否決」的erroride

在網上搜索到了解決方案:將VS的SDL檢查關閉函數


這樣error被下降爲warning C4996編碼

這樣的解決方案是很冒險的。根據報錯g:\coding\poet\ffmpegstudy\study.cpp(44): warning C4996: 'AVStream::codec': 被聲明爲已否決spa

咱們定位到所在代碼:指針

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,頗有可能在將來的版本中就刪除了。code

因此咱們最好的解決方案就是使用新的被推薦使用的函數、結構體等。orm

修改版(開啓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

相關文章
相關標籤/搜索