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應該就好了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章