#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; #endifAVStream的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