我们经常需要知道一个媒体文件所包含的媒体流的信息,比如文件格式、播放时长、码率、视音频编码格式,视频分辨率,帧率,音频属性等信息。如何使用FFmpeg API获取这些信息呢?下面我会给出一个完善的类,这个类封装了FFmpeg读取文件信息的相关的API,读者只需要调类的方法就可以获得相关的信息。
这个类能够读取媒体文件的哪些信息呢?假如我们给出一个媒体文件(MP4,AVI,MKV。。。),里面至少要包含一个音频轨或视频轨,则调用该类的方法可以获得的信息如下:
- 媒体容器封装格式
- 文件播放时长
- 文件平均码率(视频+音频)
- 视频属性(编码器名称、视频分辨率、帧率、视频帧数、编码码率)
- 音频属性(编码器名称、采样率、声道数、编码码率)
我自己写了一个工具来调用这个类,能够批量获取一个目录里的媒体文件的信息,看下图:
(这个工具的源码读者可以从我的资源里下载)
下面先附上这个类(FFMediaInfoReader)的代码,后面再逐个部分讲解一下。
类头文件代码:
#ifndef _FFMediaInfoReader_H
#define _FFMediaInfoReader_H
#include <string>
using namespace std;
#ifdef __cplusplus
extern "C" {
#endif
#ifdef HAVE_AV_CONFIG_H
#undef HAVE_AV_CONFIG_H
#endif
#include "./include/libavcodec/avcodec.h"
#include "./include/libavutil/mathematics.h"
#include "./include/libavutil/avutil.h"
#include "./include/libswscale/swscale.h"
#include "./include/libavutil/fifo.h"
#include "./include/libavformat/avformat.h"
#include "./include/libavutil/opt.h"
#include "./include/libavutil/error.h"
#include "./include/libavutil/pixfmt.h"
#include "./include/libswresample/swresample.h"
#ifdef __cplusplus
}
#endif
#pragma comment( lib, "avcodec.lib")
#pragma comment( lib, "avutil.lib")
#pragma comment( lib, "avformat.lib")
#pragma comment(lib, "swresample.lib")
#pragma comment( lib, "swscale.lib" )
#define PIX_FMT_BGR24 AV_PIX_FMT_BGR24
#define PIX_FMT_YUV420P AV_PIX_FMT_YUV420P
#define nullptr NULL
class FFMediaInfoReader
{
public:
FFMediaInfoReader();
virtual ~FFMediaInfoReader();
BOOL OpenFileStream(const char* szFilePath);
void CloseFileStream();
//获取视频分辨率
void GetVideoSize(int & width, int & height)
{
width = m_width;
height = m_height;
}
string GetMediaFormatName(); //获取媒体封装格式描述
//获取媒体轨道数目
int GetTrackNum()
{
int n = 0;
if(HasVideoTrack())
n += 1;
if(HasAudioTrack())
n += 1;
return n;
}
//是否有视频流
bool HasVideoTrack()
{
if( m_videoStreamIndex == -1)
return false;
if(m_width > 0 && m_height > 0)
return true;
return false;
}
//是否有音频流
bool HasAudioTrack()
{
if(m_audioStreamIndex == -1)
return false;
return true;
}
//获取视频帧数
int GetVideoFrameNumber()
{
return m_video_frame_count;
}
//获取文件总的码率
int GetFormatBitrate()
{
if(m_inputAVFormatCxt == NULL)
return -1;
return m_inputAVFormatCxt->bit_rate;
}
//文件播放时长(单位:秒)
int GetFileDuration()
{
if(m_inputAVFormatCxt == NULL)
return -1;
return (m_inputAVFormatCxt->duration)/1000000; //以微秒为单位,转换为秒为单位
}
string GetVideoCodecName()
{
return m_vcodec_name;
}
string GetAudioCodecName()
{
return m_acodec_name;
}
private:
BOOL openMediaFile();
void closeMediaFile();
private:
string m_filePath;
AVFormatContext* m_inputAVFormatCxt;
int m_videoStreamIndex;
int m_audioStreamIndex;
string m_vcodec_name;
string m_acodec_name;
char m_tmpErrString[64];
bool m_stop_status;
BOOL m_bInited;
int m_width, m_height; //视频分辨率
int m_video_frame_count; //视频总帧数
int m_frame_rate; //视频帧率
int m_audio_samplerate;
int m_audio_channels;
};
#endif // _FFMediaInfoReader_H
源文件代码:
#include "stdafx.h"
#include "FFMediaInfoReader.h"
#include <sstream>
//#include <mmsystem.h>
string to_string(int n)
{
std::ostringstream stm;
string str;
stm << n;
str = stm.str();
//std::cout << str << std::endl;
return str;
}
//
FFMediaInfoReader::FFMediaInfoReader()
{
m_stop_status