FFmpeg中实现对多媒体信息的获取与打印av_dump_format

本文介绍如何使用FFmpeg库中的函数来解析音视频文件的基本信息,包括注册编解码器、打开并读取音视频文件头信息及打印媒体格式详情。

获取mediainfo

首先调用av_register_all将所有的编码器和解码器注册好

来看下具体的注册实现

void av_register_all(void)
{
    ff_thread_once(&av_format_next_init, av_format_init_next);
}
// 看下av_format_init_next的实现
// 可以看到函数内部是实现了将编码器和解码器使用指针进行串联的操作
// 如果有输出或者输入列表,将输出或输入列表也进行串联
static void av_format_init_next(void)
{
    AVOutputFormat *prevout = NULL, *out;
    AVInputFormat *previn = NULL, *in;

    ff_mutex_lock(&avpriv_register_devices_mutex);
	// 编码器串联
    for (int i = 0; (out = (AVOutputFormat*)muxer_list[i]); i++) {
        if (prevout)
            prevout->next = out;
        prevout = out;
    }
	//实现输出列表的串联
    if (outdev_list) {
        for (int i = 0; (out = (AVOutputFormat*)outdev_list[i]); i++) {
            if (prevout)
                prevout->next = out;
            prevout = out;
        }
    }
	//实现解码器的串联
    for (int i = 0; (in = (AVInputFormat*)demuxer_list[i]); i++) {
        if (previn)
            previn->next = in;
        previn = in;
    }
	//实现输入列表的串联
    if (indev_list) {
        for (int i = 0; (in = (AVInputFormat*)indev_list[i]); i++) {
            if (previn)
                previn->next = in;
            previn = in;
        }
    }

    ff_mutex_unlock(&avpriv_register_devices_mutex);
}

调用avformat_open_input

调用 avformat_open_input根据输入的音视频内容构造 AVFormatContext结构体,函数功能如下:

/**
	打开一个流,并读取头部信息
 * Open an input stream and read the header. The codecs are not opened.
 * The stream must be closed with avformat_close_input().
 *  ps可以用户提供,如果为NULL该函数会进行内存申请
 * @param ps Pointer to user-supplied AVFormatContext (allocated by avformat_alloc_context).
 *           May be a pointer to NULL, in which case an AVFormatContext is allocated by this
 *           function and written into ps.
 *           Note that a user-supplied AVFormatContext will be freed on failure.
  指向要打开的多媒体文件
 * @param url URL of the stream to open.
   不指定,使用自动侦测
 * @param fmt If non-NULL, this parameter forces a specific input format.
 *            Otherwise the format is autodetected.
 * @param options  A dictionary filled with AVFormatContext and demuxer-private options.
 *                 On return this parameter will be destroyed and replaced with a dict containing
 *                 options that were not found. May be NULL.
 *
 * @return 0 on success, a negative AVERROR on failure.
 *
 * @note If you want to use custom IO, preallocate the format context and set its pb field.
 */
int avformat_open_input(AVFormatContext **ps, const char *url, ff_const59 AVInputFormat *fmt, AVDictionary **options);

调用av_dump_format打印文件信息

/**
 * Print detailed information about the input or output format, such as
 * duration, bitrate, streams, container, programs, metadata, side data,
 * codec and time base.
 *
 * @param ic        the context to analyze
 * @param index     index of the stream to dump information about
 * @param url       the URL to print, such as source or destination file
 * @param is_output Select whether the specified context is an input(0) or output(1)
 */
void av_dump_format(AVFormatContext *ic,
                    int index,
                    const char *url,
                    int is_output);

调用av_dump_format(pFmtCtx, 0, pSrcName, 0);实现对基本信息的打印,这里为了方便观看,可以自己实现一个函数,对多媒体数据进行打印。

这为了更好理解媒体信息记录的格式,自己实现了一个简单的打印接口,仅用于参考

//
// Created by andrew on 2020/11/8.
//

#include <iostream>
#include <string>
extern "C" {
#include <libavformat/avformat.h>
#include <libavutil/log.h>
#include <libavutil/dict.h>
}
using namespace std;

// 声明一下 因为原函数是在.c中声明的结构体
struct AVDictionary {
    int count;
    AVDictionaryEntry *elems;
};

// 打印媒体信息的简单示例
void my_av_input_dump_format(AVFormatContext *ic, int index,
                    const char *url, int is_output){

    string pSrt = (is_output != 0) ? "output":"input";
    cout << "音视频输入输出类型:" << pSrt <<endl;
    cout << "index = " << index << endl;
    if(is_output){
        cout << "fromat name:" << ic->oformat->name << endl;
    }else
        cout << "fromat name:" << ic->iformat->name << endl;
    // url
    cout << "from :" << url << endl;

    //ic->metadata
    int i = 0;
    i =  ic->metadata->count;
    for (i = 0; i < ic->metadata->count; i++){
        cout << "    " <<ic->metadata->elems[i].key << ":" <<ic->metadata->elems[i].value << endl;
    }
}

int main(int argc, char *argv[]){

//    设置日志等级
    av_log_set_level(AV_LOG_DEBUG);
    if(argc< 2)
    {
        av_log(NULL, AV_LOG_ERROR, "you should input media file!\n");
        return -1;
    }
//    所有获取音视频信息都要首先注册
    av_register_all();
    int errCode = -1;
    AVFormatContext *pFmtCtx = NULL;
    const char *pSrcName = argv[1];
    if((errCode = avformat_open_input(&pFmtCtx, pSrcName, NULL, NULL)) < 0){
        av_log(NULL, AV_LOG_ERROR, "avformat open input failed.\n");
        exit(1);
    }
    //官方接口
//    av_dump_format(pFmtCtx, 0, pSrcName, 0);
    my_av_input_dump_format(pFmtCtx, 0, pSrcName, 0);
    //释放资源
    avformat_close_input(&pFmtCtx);

    return 0;
}

执行输出结果:

音视频输入输出类型:input
index = 0
fromat name:mov,mp4,m4a,3gp,3g2,mj2
from :/work/test/test.mp4
    major_brand:isom
    minor_version:512
    compatible_brands:isomiso2avc1mp41
    track:0
    artist:段奥娟
    album:
    comment:163 key(Don't modify):ZWxeTBkln0EQUjdDVUZQXrJzMh33POt0FgWTvjgge2X8BzXmyZaXb9C8+H2VGrdLG7XRTMrkXzzfV9VNH7sp0KlFimbjkVbsWksXY5YrzqFNXeJX1gvrBWCV+m3aYddkvy0HxucdcxCoCrYsrnzxL97sgxi0M2VHh6PREC3j6Uz4hfWkIMGhul9aszAuzEvbUUIQXSZRHgpkVW3g3oTEwqY5CexOWMIgIZAjlFIMxafAnGU8ujxA+ufq/l/r+dQMW9OmRQVt2n4Gz1t83TrPZg==
    title:元気满分
    encoder:Lavf57.71.100
[AVIOContext @ 0x55bf28f2d080] Statistics: 200364 bytes read, 0 seeks
libgcov profiling error:/work/ffmpeg_doc/cmake-build-debug-coverage/src/CMakeFiles/ffmpeg_mediainfo.dir/ffmpeg_avformat/ffmpeg_mediainfo.cpp.gcda:overwriting an existing profile data with a different timestamp

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

andrewbytecoder

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值