首页 > 代码库 > undefined reference to `av_close_input_file' 原因分析

undefined reference to `av_close_input_file' 原因分析

这是使用libdlna0.2.4ffmpeg2.4.2搭配遇到的问题

 

以下是本人自己分析出错原因的分析,内容比较长,写得也比较随意。如果只是想找解决方法,我先在这总结一下:

ffmpeg2.4.2默认是不支持av_close_input_file函数的了,换成了avformat_close_input函数


解决方法是使用ffmpeg2.2.9版本(更久的版本没测试过),

或者坚持要使用ffmpeg2.4.2版本的话,只需将

…/ffmpeg-2.4.2/libavformat/version.h文件中一点点内容进行修改:

-------------------------------------------

 32 #defineLIBAVFORMAT_VERSION_MAJOR 56

 33 #define LIBAVFORMAT_VERSION_MINOR  4

 34 #define LIBAVFORMAT_VERSION_MICRO 101

-------------------------------------------

修改成:

 32 #defineLIBAVFORMAT_VERSION_MAJOR 55


以下开始我的分析过程:

--------------------------------------------------------------------------------------------------------------------


编译libdlna时候遇到的问题

 

执行make的出错信息:

--------------------------------------------------------------

gcc test-libdlna.c-W -Wall -Wno-unused-but-set-variable -D_LARGEFILE_SOURCE-D_FILE_OFFSET_BITS=64 -D_REENTRANT -O3 -Isrc -Lsrc -ldlna -lavformat -pthread -lavcodec -lswresample -lavutil -lrt-lm -o test-libdlna

src/libdlna.so:undefined reference to `av_close_input_file‘

src/libdlna.so:undefined reference to `av_find_stream_info‘

collect2: ldreturned 1 exit status

make: ***[test-libdlna] Error 1

--------------------------------------------------------------

 

先看下libdlna.so是如何编译出来的:

分析src/Makefile文件:

----------------------------------------------------

LIBNAME = libdlna

LIBNAME_SHARED =${LIBNAME}.so

 

lib_shared:lib_shared_info_pre $(LOBJS) lib_shared_info_post

        $(CC) -shared-Wl,-soname,$(LIBNAME_MAJOR) $(LOBJS) \

          $(LDFLAGS) $(EXTRALIBS) -o$(LIBNAME_VERSION)

        $(LN) -sf $(LIBNAME_VERSION)$(LIBNAME_MAJOR)

        $(LN) -sf $(LIBNAME_MAJOR)$(LIBNAME_SHARED)

----------------------------------------------------

 

对应输出信息中的:

---------------------------------------------------------------------------------------------------------------------------------------------

gcc -shared-Wl,-soname,libdlna.so.0 profiles.lo containers.lo image_jpeg.lo image_png.loaudio_aac.lo audio_ac3.lo audio_amr.lo audio_atrac3.lo audio_g726.loaudio_lpcm.lo audio_mp2.lo audio_mp3.lo audio_wma.lo av_mpeg1.lo av_mpeg2.loav_mpeg4_part2.lo av_mpeg4_part10.lo av_wmv9.lo upnp_dms.lo \

           -pthread -lavformat -lavcodec-lswresample -lavutil -lrt -lm -o libdlna.so.0.2.4

ln -sflibdlna.so.0.2.4 libdlna.so.0

ln -sf libdlna.so.0libdlna.so

---------------------------------------------------------------------------------------------------------------------------------------------

 

想知道av_close_input_filelibdlna.so出现之前是在哪个库中定义的,

那么先查看下函数av_close_input_file在哪里有被使用:

------------------------------------------------------------

$ grep -rn"av_close_input_file" ./src/

Binary file./src/libdlna.so matches

Binary file./src/profiles.lo matches

Binary file./src/profiles.o matches

Binary file./src/libdlna.so.0.2.4 matches

./src/profiles.c:337:  av_close_input_file (ctx);

Binary file./src/libdlna.a matches

Binary file./src/libdlna.so.0 matches

------------------------------------------------------------

还不能直接看出在哪里,但是可以看出被profiles.c文件调用了

 

./src/profiles.c

------------------------------------------------------------

 22 #include <stdlib.h>

 23 #include <string.h>

 24

 25 #include "dlna_internals.h"

 26 #include"profiles.h"

 27 #include "containers.h"

337   av_close_input_file(ctx);

338   free (codecs);

339   return profile;

340 }

------------------------------------------------------------

 

看下头文件:

./src/profiles.h

------------------------------------------------------------

 25 #include <libavcodec/avcodec.h>

 26 #include <libavformat/avformat.h>

 27

 28 #include "dlna_internals.h"

 29 #include "containers.h"

------------------------------------------------------------

看到这里,应该可以猜测出av_close_input_file是在avcodec.h或者avformat.h(编译安装ffmpeg时生成的)中定义的

 

grep可以发现是在avformat.h

/usr/local/include/libavformat/avformat.h

----------------------------------------------------------------------

2173 #ifFF_API_CLOSE_INPUT_FILE

2174 /**

2175  * @deprecated use avformat_close_input()

2176  * Close a media file (but not its codecs).

2177  *

2178  * @param s media file handle

2179  */

2180attribute_deprecated

2181 void av_close_input_file(AVFormatContext *s);

2182 #endif

---------------------------------------------------------------------

也只是函数av_close_input_file的声明,而不是定义

 

百度了一下才知道,一般函数的定义是在库中:

nm命令查看库avformat调用的函数:

-----------------------------------------------------

$ nm libavformat.a |grep "close_input"

         U avformat_close_input

         U avformat_close_input

         U avformat_close_input

         U avformat_close_input

         U avformat_close_input

         U avformat_close_input

         U avformat_close_input

         U avformat_close_input

0000c710 Tavformat_close_input

----------------------------------------------------

可以发现,并没有av_close_input_file,只有avformat_close_input。

 

难道编译ffmpeg的时候没有将函数av_close_input_file编译进库里面吗?

 


 

好吧

我们要回到ffmpeg源码的目录(ffmpeg-2.4.2)找一下了

---------------------------------------------------------------------------------------------------------------------

$ grep -rn"av_close_input_file" ./

./libavformat/avformat.h:2181:voidav_close_input_file(AVFormatContext *s);

./libavformat/utils.c:3534:voidav_close_input_file(AVFormatContext *s)

./doc/APIchanges:1108:  Deprecate av_close_input_file() andav_close_input_stream().

---------------------------------------------------------------------------------------------------------------------

 

看来av_close_input_file的函数声明应该是在./libavformat/utils.c文件里了。

------------------------------------------------------------------------------

3533 #ifFF_API_CLOSE_INPUT_FILE

3534 voidav_close_input_file(AVFormatContext *s)

3535 {

3536     avformat_close_input(&s);

3537 }

3538 #endif

------------------------------------------------------------------------------

 

发现还有一个文件中包含av_close_input_file

…/ffmpeg-2.4.2/doc/APIchanges

----------------------------------------------------------

1106 2011-12-12 -8bc7fe4 / 5266045 - lavf 53.25.0 / 53.17.0

1107   Add avformat_close_input().

1108   Deprecate av_close_input_file() and av_close_input_stream().

----------------------------------------------------------

难道av_close_input_file() and av_close_input_stream()已经被抛弃了???

被换成avformat_close_input()了????????????

 


看下libavformat.a库是由哪些库组成的:

…/ffmpeg-2.4.2/libavformat/Makefile

----------------------------------------------------------

  3 NAME = avformat

  4

  5 HEADERS = avformat.h                                                   \

  6          avio.h                                                       \

  7          version.h                                                    \

  8

  9 OBJS = allformats.o         \

 10       avio.o               \

 11       aviobuf.o            \

 12       cutils.o             \

 13       dump.o               \

 14       format.o             \

 15       id3v1.o              \

 16       id3v2.o              \

 17       metadata.o           \

 18       mux.o                \

 19       options.o            \

 20       os_support.o         \

 21       riff.o               \

 22       sdp.o                \

 23       seek.o               \

 24       url.o                \

 25       utils.o              \

----------------------------------------------------------

 

看下utils.o库中有没有av_close_input_file的定义:

------------------------------------

$nm utils.o |grep "close_input"

0000c710 Tavformat_close_input

-----------------------------------

没有发现该函数的定义,但之前我们看到其实av_close_input_file()就是在utils.c中定义的:

------------------------------------------------------------------

3533 #if FF_API_CLOSE_INPUT_FILE

3534 voidav_close_input_file(AVFormatContext *s)

3535 {

3536     avformat_close_input(&s);

3537 }

3538 #endif

-----------------------------------------------------------------

难道是因为FF_API_CLOSE_INPUT_FILE的值不为1

 

再研究一下哪些文件中有FF_API_CLOSE_INPUT_FILE值的定义:

--------------------------------------------------------------------------------------------------------------------

$ grep -rn"FF_API_CLOSE_INPUT_FILE" ./

./avformat.h:2173:#ifFF_API_CLOSE_INPUT_FILE

./version.h:76:#ifndefFF_API_CLOSE_INPUT_FILE

./version.h:77:#define FF_API_CLOSE_INPUT_FILE        (LIBAVFORMAT_VERSION_MAJOR < 56)

./utils.c:3533:#ifFF_API_CLOSE_INPUT_FILE

--------------------------------------------------------------------------------------------------------------------

 

…/ffmpeg-2.4.2/libavformat/version.h

-------------------------------------------

 32 #defineLIBAVFORMAT_VERSION_MAJOR 56

 33 #define LIBAVFORMAT_VERSION_MINOR  4

 34 #define LIBAVFORMAT_VERSION_MICRO 101

------------------------------------------

原来如此,ffmpeg版本在56以上就不支持av_close_input_file函数了!!!



#defineLIBAVFORMAT_VERSION_MAJOR 56

中的56改成54

 

再重新make就行了,问题解决。

 

如果还是不行的话,先执行make clean,再make应该就好了。

undefined reference to `av_close_input_file' 原因分析