【FFMPEG系列】之查看FFMPEG版本号

  ffmpeg编译后执行可执行文件会提示各组件库的版本信息,这些版本信息从何而来是本文关注的重点

1、ffmpeg版本信息一探
1.1 windows下示例

  (1)假设你在windows下编译了ffmpeg,执行ffmpeg.exe便会出现下图所示的信息,图中列出了ffmpeg各组件的版本信息;

  (2)版本信息从何而来?
  打开ffmpeg.c文件,main函数调用了 ‘show_banner(argc, argv, options);’ 此函数原理很简单,调用了一些现有的宏,这些宏在一些头文件中,例如’libavcodec/version.h’ 中,就含有某个宏表示libavcodec的版本信息;

  (3)windows下编译的动态库命名带有版本信息(如’avdevice-57.dll,57为版本)又从何而来?
  1>、在ffmpeg的早期版本中,如ffmpeg2.5,在./configure之后会产生config,mak文件,ffmpeg各组件的版本信息就在此文件中,如’libavcodec_VERSION_MAJOR=56,脚本编译动态库的时候,动态库的名字会加上此宏。
  2>、在ffmpeg比较新的版本中,如ffmpeg3.4,在./configure之后也会产生一些mak文件,譬如 ffbuild/ 目录下的library.mak文件,其中的’-include $(SUBDIR)lib$(NAME).version 其实是将各组件目录下含版本信息的文件例如’libavcodec/libavcodec.version 包含进来,接着使用’LIBMAJOR := $(lib$(NAME)_VERSION_MAJOR)读取版本信息;然后在链接的时候(’$(SUBDIR)$(SLIBNAME_WITH_MAJOR): $(OBJS) $(SLIBOBJS) $(SUBDIR)lib$(NAME).ver)生成类似’avdevice-57.dll的命名;

2、通过动态库加载的方式获取版本号
2.1 新建名为symbol.c的文件,内容为:
#include <stdio.h>
#include <stdlib.h>

#ifdef WIN32
#include <windows.h>
//#include <wtypes.h>
//#include <winbase.h>
#else
#include <dlfcn.h>
#endif

//将版本信息转换成具体的数字
//#define AV_VERSION_INT(a,b,c) ((a)<<16 | (b)<<8 | (c))
void transport_version(unsigned int version_num, char *pname)
{
    int version_major, version_minor, version_micro;

    version_major = (version_num >> 16) & 0xff;
    version_minor = (version_num >> 8) & 0xff;
    version_micro = (version_num) & 0xff;

    printf("%s: %d, %d, %d\n", pname, version_major, version_minor, version_micro);
}

//需要从so或dll文件中导出的函数声明
typedef unsigned (*avcodec_version_fuc)(void);

//动态库名字加路径
char *psoavutil = "libavutil.so";
char *psoavcodec = "libavcodec.so";
char *psoavformat = "libavformat.so";
char *psoavdevice = "libavdevice.so";
char *psoavfilter = "libavfilter.so";
char *psoavscale = "libswscale.so";

char *pdllavutil = "libavutil.dll";
char *pdllavcodec = "libavcodec.dll";
char *pdllavformat = "libavformat.dll";
char *pdllavdevice = "libavdevice.dll";
char *pdllavfilter = "libavfilter.dll";
char *pdllavscale = "libswscale.dll";

#ifdef WIN32
void get_lib_version(char *pdllname, char *function)
{
    HINSTANCE pdllHandle;
    avcodec_version_fuc avcodec_version = NULL;//函数指针
    
    pdllHandle = LoadLibrary(pdllname);
    if (pdllHandle == NULL){
        printf("Cant open %s\n", pdllHandle);
        return;
    }

    avcodec_version = (avcodec_version_fuc)GetProcAddress(pdllHandle, function);
    if(avcodec_version == NULL){
       printf("Cant load symbol %s\n", function);
       FreeLibrary(pdllHandle);
       return;
    }
    transport_version(avcodec_version(),function);

    //关闭so文件
    FreeLibrary(pdllHandle);
}



void get_ffmpeg_version(char *psoname, char *function)
{
    HINSTANCE pdllHandle;
    char *avcodec_version = NULL;//函数指针
    
    pdllHandle = LoadLibrary(pdllname);
    if (pdllHandle == NULL){
        printf("Cant open %s\n", pdllHandle);
        return;
    }

    avcodec_version = (avcodec_version_fuc)GetProcAddress(pdllHandle, function);
    if(avcodec_version == NULL){
       printf("Cant load symbol %s\n", function);
       FreeLibrary(pdllHandle);
       return;
    }
    printf("%s\n", avcodec_version);

    //关闭so文件
    FreeLibrary(pdllHandle);
}

//windows动态加载方法
void main(int argc, char *argv[])
{
    get_lib_version(pdllavutil, "avutil_version");
    get_lib_version(pdllavcodec, "avcodec_version");
    get_lib_version(pdllavformat, "avformat_version");
    get_lib_version(pdllavdevice, "avdevice_version");
    get_lib_version(pdllavfilter, "avfilter_version");
    get_lib_version(pdllavscale, "swscale_version");
    get_ffmpeg_version(pdllavcodec, "av_codec_ffversion");
}

#else
void get_lib_version(char *psoname, char *function)
{
    void *psoHandle;
    avcodec_version_fuc avcodec_version = NULL;//函数指针
    
    psoHandle = dlopen(psoname, RTLD_NOW | RTLD_GLOBAL);
    if (psoHandle == NULL){
        printf("Cant open %s\n", psoHandle);
        return;
    }

    avcodec_version = dlsym(psoHandle, function);
    if(avcodec_version == NULL){
       printf("Cant load symbol %s\n", function);
       dlclose(psoHandle);
       return;
    }
    transport_version(avcodec_version(),function);

    //关闭so文件
    dlclose(psoHandle);
}


void get_ffmpeg_version(char *psoname, char *function)
{
    void *psoHandle;
    char *avcodec_version = NULL;//函数指针
    
    psoHandle = dlopen(psoname, RTLD_NOW | RTLD_GLOBAL);
    if (psoHandle == NULL){
        printf("Cant open %s\n", psoHandle);
        return;
    }

    avcodec_version = dlsym(psoHandle, function);
    if(avcodec_version == NULL){
       printf("Cant load symbol %s\n", function);
       dlclose(psoHandle);
       return;
    }
    printf("%s\n", avcodec_version);

    //关闭so文件
    dlclose(psoHandle);
}

//linux动态加载方法
void main(int argc, char *argv[])
{
    get_lib_version(psoavutil, "avutil_version");
    get_lib_version(psoavcodec, "avcodec_version");
    get_lib_version(psoavformat, "avformat_version");
    get_lib_version(psoavdevice, "avdevice_version");
    get_lib_version(psoavfilter, "avfilter_version");
    get_lib_version(psoavscale, "swscale_version");
    get_ffmpeg_version(psoavcodec, "av_codec_ffversion");
}
#endif

2.2 新建Linux下的makefile脚本(Makefile)
src = $(wildcard *.c)
obj = $(src:.c:.o)

CC = gcc
LDFALGS = -lm -ldl

demo:$(obj)
	$(CC) -o $@ $^ $(LDFALGS)

.PHONY:clean
clean:
	rm -f $(obj) demo

编译方法,将.c代码跟makefile放在同一路径下,之后make就行

2.3 新建windows的makefile脚本(Makefile.vc)
src = $(wildcard *.c)
obj = $(src:.c:.o)

CC = cl
LD = link
LDFALGS = -debug
CFLAGS = -DWIN32

.PHONY: all

all:clean demo.exe


demo.exe:$(obj)
	$(LD) -libpath:./ $(LDFALGS) -PDB:./demo.pdb $(obj) -debug -out:./$@

%.o:%.c
	$(CC) $(CFLAGS) -Fo$@ -c $< 

.PHONY:clean
clean:
	rm -f $(obj) demo.exe

编译方法,将.c代码跟Makefile.vc放在同一路径下,之后make -f Makefile.vc就行

动态库加载的代码参考1:https://blog.csdn.net/eydwyz/article/details/74932628
动态库加载的代码参考2:https://www.cnblogs.com/marblemm/p/7804056.html

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值