FFmpeg入门详解之70:获取音视频流信息(Metadata)

用FFmpeg获取视频流+音频流的信息(编码格式、分辨率、帧率、播放时长...)

简介

我们经常需要知道一个媒体文件所包含的媒体流的信息,比如文件格式、播放时长、码率、视音频编码格式,视频分辨率,帧率,音频属性等信息。

如何使用FFmpeg API获取这些信息呢?

媒体容器封装格式

文件播放时长

文件平均码率(视频+音频)

视频属性(编码器名称、视频分辨率、帧率、编码码率)

音频属性(编码器名称、采样率、声道数、编码码率)

avformat_open_input

avformat_find_stream_info

伪代码:

/// 数据结构:大管家婆

AVFormatContext* m_inputAVFormatCxt = NULL;

/// 打开文件

res = avformat_open_input(&m_inputAVFormatCxt, filepath, 0, NULL);

/// 查找流信息

if (avformat_find_stream_info(m_inputAVFormatCxt, 0) < 0)

av_dump_format(m_inputAVFormatCxt, 0, filepath, 0);

///avformat_close_input(&m_inputAVFormatCxt);

/// 遍历流信息:音频、视频

for (int i = 0; i < m_inputAVFormatCxt->nb_streams; i++)

{

AVStream *in_stream = m_inputAVFormatCxt->streams[i];

if (in_stream->codec->codec_type == AVMEDIA_TYPE_VIDEO)

{

}

}

///查找解码器

if (avmi->videoStreamIndex != -1)

{

AVCodecContext *avctx;

AVCodec *codec;

do

{

avctx = m_inputAVFormatCxt->streams[avmi->videoStreamIndex]->codec;

// 寻找视频解码器

codec = avcodec_find_decoder(avctx->codec_id);

}

}

获取音视频流基本信息

int ret = -1;

int i = 0;

AVFormatContext * avFmtCtx = NULL; // 大管家婆

if (avmi == NULL || filepath == NULL) {

return;

}

/// 1. 打开音视频文件或网络流

ret = avformat_open_input(&avFmtCtx, filepath, NULL, NULL);

if (ret < 0) {

printf("error avformat_open_input:%s\n", filepath);

return;

}

/// 2. 进一步读取音视频流信息

avformat_find_stream_info(avFmtCtx, NULL);

/// 3. 打印音视频流信息

av_dump_format(avFmtCtx, 0, filepath, 0);

读取总时长和总码率

/// 继续深入,读取更多的字段

avmi->duration =  avFmtCtx->duration; //时长

avmi->totalBitrate = avFmtCtx->bit_rate; //总码率

printf("duration=%lld, totalBitrate=%lld\n",

avmi->duration,

avmi->totalBitrate);

读取视频宽高帧率和音频的声道数采样率

/// 分别读取音视频流,更多的参数

//avFmtCtx->nb_streams

for (i = 0; i < avFmtCtx->nb_streams; i++) {

AVStream *avstmp =  avFmtCtx->streams[i];//拿到具体的一路流

if (avstmp->codec->codec_type == AVMEDIA_TYPE_VIDEO) {

avmi->videoStreamIndex = i;

avmi->width = avstmp->codec->width;

avmi->height = avstmp->codec->height;

/// 视频帧率:avg_frame_rate

/// fps: frames per second

if (avstmp->avg_frame_rate.num != 0

&& avstmp->avg_frame_rate.den != 0) {

avmi->frameRate = (double)avstmp->avg_frame_rate.num / (double)avstmp->avg_frame_rate.den;

}

printf("width=%d, height=%d, frameRate=%.3lf\n",

avmi->width,

avmi->height,

avmi->frameRate);

}

else if (avstmp->codec->codec_type == AVMEDIA_TYPE_AUDIO) {

avmi->audioStreamIndex = i;

avmi->channels = avstmp->codec->channels;

avmi->sampleRate = avstmp->codec->sample_rate;

printf("channels=%d, sampleRate=%d\n",

avmi->channels,

avmi->sampleRate);

}

}

读取音视频解码器的名称

///查找解码器

if (avmi->videoStreamIndex != -1)

{

AVCodecContext *avctx;

AVCodec *codec;

do

{

avctx = m_inputAVFormatCxt->streams[avmi->videoStreamIndex]->codec;

// 寻找视频解码器

codec = avcodec_find_decoder(avctx->codec_id);

}

}

猜你喜欢

转载自blog.csdn.net/teachermei/article/details/127103337