这是使用libdlna0.2.4与ffmpeg2.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_file在libdlna.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应该就好了。