一直抽不出时间来调试这个BUG。 没想到cnblogs已经有人解决。谢谢分享。
原址:http://www.cnblogs.com/yueang/archive/2013/02/18/2915186.html
研究过twilove的faplayer代码的人应该都知道,faplayer代码中使用了两个播放器程序,一个是android自带的播放器作为默认的播放器,另外一个就是使用了vlc代码的播放器。之前写过一篇相关的文章:
采用faplayer播放EPUB书中的mp4视频
这次要讲的问题就是在使用faplayer中的vlc代码的时候,之前在2.3系统上正常,后来升级的4.04的时候发现只有声音没有图像,这个问题后来解决了,解决的过程下篇日志再说,这次要说的是系统升级的4.1之后,发现只有图像又没有声音了!!!(尼玛能靠点谱不?)由于faplayer早已停止更新了,所以这个问题只能自己想办法搞定。最终在我的“不懈努力下”,问题终于搞定了,在解决问题的过程中我觉得有些东西是比较有意思也值得记录下来的,因此写了这篇文章.
01-15 14:31:50.960: D/faplayer(1622): [0x67389ef8]main audio output: using audio output module "dummy"
1
p_library =
InitLibrary(p_this);
2
if
(!
p_library) {
3
msg_Err(VLC_OBJECT(p_this),
"
Could not initialize libmedia.so!
"
);
4
return
VLC_EGENERIC;
5
}
看来是InitLibrary函数出了问题,我们来看看这个函数的内容:
1
void
*
InitLibrary() {
2
void
*
p_library;
3
4
p_library = dlopen(
"
libmedia.so
"
, RTLD_NOW);
5
if
(!
p_library)
6
return
NULL;
7
as_getOutputFrameCount = (AudioSystem_getOutputFrameCount)(dlsym(p_library,
"
_ZN7android11AudioSystem19getOutputFrameCountEPii
"
));
8
as_getOutputLatency = (AudioSystem_getOutputLatency)(dlsym(p_library,
"
_ZN7android11AudioSystem16getOutputLatencyEPji
"
));
9
as_getOutputSamplingRate = (AudioSystem_getOutputSamplingRate)(dlsym(p_library,
"
_ZN7android11AudioSystem21getOutputSamplingRateEPii
"
));
10
at_getMinFrameCount = (AudioTrack_getMinFrameCount)(dlsym(p_library,
"
_ZN7android10AudioTrack16getMinFrameCountEPiij
"
));
11
at_ctor = (AudioTrack_ctor)(dlsym(p_library,
"
_ZN7android10AudioTrackC1EijiiijPFviPvS1_ES1_ii
"
));
12
at_ctor_legacy = (AudioTrack_ctor_legacy)(dlsym(p_library,
"
_ZN7android10AudioTrackC1EijiiijPFviPvS1_ES1_i
"
));
13
at_dtor = (AudioTrack_dtor)(dlsym(p_library,
"
_ZN7android10AudioTrackD1Ev
"
));
14
at_initCheck = (AudioTrack_initCheck)(dlsym(p_library,
"
_ZNK7android10AudioTrack9initCheckEv
"
));
15
at_start = (AudioTrack_start)(dlsym(p_library,
"
_ZN7android10AudioTrack5startEv
"
));
16
at_stop = (AudioTrack_stop)(dlsym(p_library,
"
_ZN7android10AudioTrack4stopEv
"
));
17
at_write = (AudioTrack_write)(dlsym(p_library,
"
_ZN7android10AudioTrack5writeEPKvj
"
));
18
at_flush = (AudioTrack_flush)(dlsym(p_library,
"
_ZN7android10AudioTrack5flushEv
"
));
19
//
need the first 3 or the last 1
20
if
(!((as_getOutputFrameCount && as_getOutputLatency && as_getOutputSamplingRate) ||
at_getMinFrameCount)) {
21
dlclose(p_library);
22
return
NULL;
23
}
24
//
need all in the list
25
if
(!((at_ctor || at_ctor_legacy) && at_dtor && at_initCheck && at_start && at_stop && at_write &&
at_flush)) {
26
dlclose(p_library);
27
return
NULL;
28
}
29
return
p_library;
30
}
嗯,看来这个函数的内容是从so库中查找相应的函数地址,然后把地址赋值给对应的函数指针,那么类似“_ZN7android11AudioSystem19getOutputFrameCountEPii”这样的字符串就是函数在so库中的签名了。我们看看这个字符串所代表的函数的签名:
1
//
_ZN7android11AudioSystem19getOutputFrameCountEPii
2
typedef
int
(*AudioSystem_getOutputFrameCount)(
int
*,
int
);
为什么这样的函数在so中会有这样奇怪的代号呢?这方面的知识有一篇文章讲的很好: C++的函数重载
了解了这个后我就在猜想:应该是某个或是某几个函数的签名在4.1中发生了改变,导致找不到才出的错,于是我这样修改程序:
1
void
*
InitLibrary() {
2
void
*
p_library;
3
4
p_library = dlopen(
"
libmedia.so
"
, RTLD_NOW);
5
if
(!
p_library)
6
return
NULL;
7
as_getOutputFrameCount = (AudioSystem_getOutputFrameCount)(dlsym(p_library,
"
_ZN7android11AudioSystem19getOutputFrameCountEPii
"
));
8
as_getOutputLatency = (AudioSystem_getOutputLatency)(dlsym(p_library,
"
_ZN7android11AudioSystem16getOutputLatencyEPji
"
));
9
as_getOutputSamplingRate = (AudioSystem_getOutputSamplingRate)(dlsym(p_library,
"
_ZN7android11AudioSystem21getOutputSamplingRateEPii
"
));
10
at_getMinFrameCount = (AudioTrack_getMinFrameCount)(dlsym(p_library,
"
_ZN7android10AudioTrack16getMinFrameCountEPiij
"
));
11
at_ctor = (AudioTrack_ctor)(dlsym(p_library,
"
_ZN7android10AudioTrackC1EijiiijPFviPvS1_ES1_ii
"
));
12
at_ctor_legacy = (AudioTrack_ctor_legacy)(dlsym(p_library,
"
_ZN7android10AudioTrackC1EijiiijPFviPvS1_ES1_i
"
));
13
at_dtor = (AudioTrack_dtor)(dlsym(p_library,
"
_ZN7android10AudioTrackD1Ev
"
));
14
at_initCheck = (AudioTrack_initCheck)(dlsym(p_library,
"
_ZNK7android10AudioTrack9initCheckEv
"
));
15
at_start = (AudioTrack_start)(dlsym(p_library,
"
_ZN7android10AudioTrack5startEv
"
));
16
at_stop = (AudioTrack_stop)(dlsym(p_library,
"
_ZN7android10AudioTrack4stopEv
"
));
17
at_write = (AudioTrack_write)(dlsym(p_library,
"
_ZN7android10AudioTrack5writeEPKvj
"
));
18
at_flush = (AudioTrack_flush)(dlsym(p_library,
"
_ZN7android10AudioTrack5flushEv
"
));
19
//
need the first 3 or the last 1
20
if
(!((as_getOutputFrameCount && as_getOutputLatency && as_getOutputSamplingRate) ||
at_getMinFrameCount)) {
21
msg_Err(VLC_OBJECT(p_this),
"
interface error 1
"
);
22
if
(!
as_getOutputFrameCount) {
23
msg_Err(VLC_OBJECT(p_this),
"
error1
"
);
24
}
25
if
(!
as_getOutputLatency) {
26
msg_Err(VLC_OBJECT(p_this),
"
error2
"
);
27
}
28
if
(!
as_getOutputSamplingRate) {
29
msg_Err(VLC_OBJECT(p_this),
"
error3
"
);
30
}
31
if
(!
at_getMinFrameCount)
32
{
33
msg_Err(VLC_OBJECT(p_this),
"
error4
"
);
34
}
35
dlclose(p_library);
36
return
NULL;
37
}
38
//
need all in the list
39
if
(!((at_ctor || at_ctor_legacy) && at_dtor && at_initCheck && at_start && at_stop && at_write &&
at_flush)) {
40
msg_Err(VLC_OBJECT(p_this),
"
interface error 2
"
);
41
dlclose(p_library);
42
return
NULL;
43
}
44
return
p_library;
45
}
查看日志后,发现是“error2” 也就是as_getOutputLatency为空,那说明“_ZN7android11AudioSystem16getOutputLatencyEPji”这个签名现在在libmedia.so中找不到了,那么现在这个函数的签名是什么呢?要想弄清楚这个,我们需要弄清楚怎么查看libmedia.so中函数的签名。
在网上查询方法后,在终端上使用readelf -s libmedia.so,结果是一长串符号列表,类似下面的内容:
1
root@ubuntu:/mnt/hgfs/share/
4.1
.
2
# readelf -
s libmedia.so
2
3
Symbol table
'
.dynsym
'
contains
1918
entries:
4
Num: Value Size Type Bind Vis Ndx Name
5
0
:
00000000
0
NOTYPE LOCAL DEFAULT UND
6
1
:
00037069
4
FUNC GLOBAL DEFAULT
7
_ZN7android10AudioTrack16
7
2
:
00000000
0
FUNC GLOBAL DEFAULT UND __aeabi_unwind_cpp_pr0
8
3
: 0003706d
2
FUNC GLOBAL DEFAULT
7
_ZTv0_n16_N7android10Audi
9
4
: 0003706d
2
FUNC GLOBAL DEFAULT
7
_ZN7android10AudioTrack16
10
5
: 0003706f
12
FUNC GLOBAL DEFAULT
7
_ZTv0_n12_N7android10Audi
11
6
: 0003707d
68
FUNC GLOBAL DEFAULT
7
_ZN7android10AudioTrack16
12
7
:
00000000
0
FUNC GLOBAL DEFAULT UND pthread_cond_destroy
13
8
:
00000000
0
FUNC GLOBAL DEFAULT UND pthread_mutex_destroy
14
9
:
00000000
0
FUNC GLOBAL DEFAULT UND _ZN7android6ThreadD2Ev
15
10
:
00000000
0
FUNC GLOBAL DEFAULT UND _ZN7android7RefBaseD2Ev
16
11
: 000370c1
12
FUNC GLOBAL DEFAULT
7
_ZTv0_n12_N7android10Audi
17
12
: 000370cd
18
FUNC GLOBAL DEFAULT
7
_ZN7android10AudioTrack16
18
13
:
00000000
0
FUNC GLOBAL DEFAULT UND _ZdlPv
19
14
:
00000000
0
FUNC GLOBAL DEFAULT UND pthread_mutex_lock
20
15
:
00000000
0
FUNC GLOBAL DEFAULT UND __aeabi_unwind_cpp_pr1
21
16
:
00000000
0
FUNC GLOBAL DEFAULT UND pthread_mutex_unlock
22
17
:
00000000
0
FUNC GLOBAL DEFAULT UND __aeabi_idiv
23
18
:
00000000
0
FUNC GLOBAL DEFAULT UND __aeabi_uidiv
24
19
: 000370ed
98
FUNC GLOBAL DEFAULT
7
_ZN7android10AudioTrack16
25
20
: 0003f015
52
FUNC GLOBAL DEFAULT
7
_ZN7android11AudioSystem2
26
21
: 0003efdd
52
FUNC GLOBAL DEFAULT
7
_ZN7android11AudioSystem1
27
22
: 0003efa9
52
FUNC GLOBAL DEFAULT
7
_ZN7android11AudioSystem1
28
23
: 0003714f
62
FUNC GLOBAL DEFAULT
7
_ZN7android10AudioTrackC2
29
24
:
00000000
0
FUNC GLOBAL DEFAULT UND pthread_mutex_init
30
25
: 0003718d
80
FUNC GLOBAL DEFAULT
7
_ZN7android10AudioTrackC1
31
26
:
00000000
0
FUNC GLOBAL DEFAULT UND _ZN7android7RefBaseC2Ev
32
27
: 000371
dd
4
FUNC GLOBAL DEFAULT
7
_ZNK7android10AudioTrack9
33
28
: 000371e1
4
FUNC GLOBAL DEFAULT
7
_ZNK7android10AudioTrack7
34
29
: 000371e5
4
FUNC GLOBAL DEFAULT
7
_ZNK7android10AudioTrack1
35
30
: 000371e9
4
FUNC GLOBAL DEFAULT
7
_ZNK7android10AudioTrack6
36
31
: 000371ed
6
FUNC GLOBAL DEFAULT
7
_ZNK7android10AudioTrack1
37
32
: 000371f3
6
FUNC GLOBAL DEFAULT
7
_ZNK7android10AudioTrack1
38
33
: 000371f9
44
FUNC GLOBAL DEFAULT
7
_ZNK7android10AudioTrack9
39
34
:
00037225
4
FUNC GLOBAL DEFAULT
7
_ZN7android10AudioTrack12
40
35
:
00037229
32
FUNC GLOBAL DEFAULT
7
_ZNK7android10AudioTrack7
41
36
:
00037249
48
FUNC GLOBAL DEFAULT
7
_ZN7android10AudioTrack7f
42
37
:
00000000
0
FUNC GLOBAL DEFAULT UND pthread_cond_signal
43
38
:
00037279
30
FUNC GLOBAL DEFAULT
7
_ZN7android10AudioTrack5f
44
39
:
00037297
52
FUNC GLOBAL DEFAULT
7
_ZN7android10AudioTrack5p
45
40
: 000372cb
22
FUNC GLOBAL DEFAULT
7
_ZN7android10AudioTrack4m
46
41
: 000372e1
12
FUNC GLOBAL DEFAULT
7
_ZNK7android10AudioTrack5
47
42
: 000372ed
144
FUNC GLOBAL DEFAULT
7
_ZN7android10AudioTrack9s
48
43
: 0003737d
14
FUNC GLOBAL DEFAULT
7
_ZNK7android10AudioTrack9
49
44
: 0003738d
96
FUNC GLOBAL DEFAULT
7
_ZN7android10AudioTrack21
50
45
: 000373ed
8
FUNC GLOBAL DEFAULT
7
_ZNK7android10AudioTrack2
51
46
: 000373f5
74
FUNC GLOBAL DEFAULT
7
_ZN7android10AudioTrack13
52
47
: 0003743f
40
FUNC GLOBAL DEFAULT
7
_ZNK7android10AudioTrack1
53
48
:
00037469
188
FUNC GLOBAL DEFAULT
7
_ZN7android10AudioTrack9s
54
49
:
00000000
0
FUNC GLOBAL DEFAULT UND __android_log_print
55
50
:
00037525
48
FUNC GLOBAL DEFAULT
7
_ZN7android10AudioTrack7s
56
51
:
00037555
22
FUNC GLOBAL DEFAULT
7
_ZN7android10AudioTrack17
57
52
: 0003756b
16
FUNC GLOBAL DEFAULT
7
_ZNK7android10AudioTrack1
58
53
: 0003757b
16
FUNC GLOBAL DEFAULT
7
_ZNK7android10AudioTrack2
59
54
: 0003758b
94
FUNC GLOBAL DEFAULT
7
_ZN7android10AudioTrack11
60
55
:
00000000
0
FUNC GLOBAL DEFAULT UND android_atomic_or
61
56
: 000375e9
50
FUNC GLOBAL DEFAULT
7
_ZN7android10AudioTrack11
62
...
看上去挺像那么回事的是吧?其实在仔细查找其中的内容后,没有发现任何跟“_ZN7android11AudioSystem16getOutputLatencyEPji”相关的代码,别说这个空函数了,连已经证明加载成功的函数的签名也没有找到,这是为什么呢?
这时候我就想到,android系统中的库文件都是在arm-linux环境下编译的,属于交叉编译,而我们使用的命令都是在x86架构下的指令,他解析的符号类型会不会也是x86的指令呢?为了弄清楚这个问题,我需要安装arm-linux的开发工具,在参考了这几篇文章后,我成功的安装了arm-linux工具链。
使用arm-2008q3-72-arm-none-linux-gnueabi-i686-pc-linux-gnu交叉编译成功在板子上运行
然后使用命令:arm-none-linux-gnueabi-objdump -d libmedia.so:
1
root@ubuntu:/mnt/hgfs/share/
4.1
.
2
# arm-none-linux-gnueabi-objdump -
d libmedia.so
2
3
libmedia.so:
file
format elf32-
littlearm
4
5
Disassembly of section .plt:
6
7
00036358
<.plt>
:
8
36358
: e52de004 push {lr} ; (str lr, [sp, #-
4
]!
)
9
3635c: e59fe004 ldr lr, [pc, #
4
] ;
36368
<_ZN7android10AudioTrack16AudioTrackThread10readyToRunEv-
0xd00
>
10
36360
: e08fe00e add lr, pc, lr
11
36364
: e5bef008 ldr pc, [lr, #
8
]!
12
... ...
13
37058
: e5bcffa0 ldr pc, [ip, #
4000
]!
14
3705c: e28fc600 add ip, pc, #
0
;
0x0
15
37060
: e28cca38 add ip, ip, #
229376
;
0x38000
16
37064
: e5bcff98 ldr pc, [ip, #
3992
]!
17
Disassembly of section .text:
18
19
00037068
<_ZN7android10AudioTrack16AudioTrackThread10readyToRunEv>
:
20
37068
:
2000
movs r0, #
0
21
3706a:
4770
bx lr
22
23
0003706c <_ZN7android10AudioTrack16AudioTrackThread10onFirstRefEv>
:
24
3706c:
4770
bx lr
25
26
0003706e <_ZTv0_n12_N7android10AudioTrack16AudioTrackThreadD1Ev>
:
27
3706e:
6801
ldr r1, [r0, #
0
]
28
37070
: f851 3c0c ldr.
w
r3, [r1, #-
12
]
29
37074
: 18c0 adds r0, r0, r3
30
37076
: f000 b801 b.
w
3707c <_ZN7android10AudioTrack16AudioTrackThreadD1Ev>
31
...
结果是上面这样的代码。把结果输出到文件中,进行查找:
1
root@ubuntu:/mnt/hgfs/share/
4.1
.
2
# arm-none-linux-gnueabi-objdump -d libmedia.so >
libmedia.txt
2
root@ubuntu:/mnt/hgfs/share/
4.1
.
2
#
ls
3
4.0
.
4
4.0
.
4
.txt
4.1
.
2
.txt a.txt lib libmedia_jni.so libmedia_native.so libmediaplayerservice.so libmedia.so libmedia.txt
4
root@ubuntu:/mnt/hgfs/share/
4.1
.
2
# gedit libmedia.txt
5
root@ubuntu:/mnt/hgfs/share/
4.1
.
2
#
grep
getOutputLatency libmedia.txt
6
3710c: f007 ff4c bl 3efa8 <_ZN7android11AudioSystem16getOutputLatencyEPj19audio_stream_type_t>
7
0003efa8 <_ZN7android11AudioSystem16getOutputLatencyEPj19audio_stream_type_t>
:
8
3efc4: b130 cbz r0, 3efd4 <_ZN7android11AudioSystem16getOutputLatencyEPj19audio_stream_type_t+
0x2c
>
可知getOutputLatency函数的符号由“_ZN7android11AudioSystem16getOutputLatencyEPji”变为“_ZN7android11AudioSystem16getOutputLatencyEPj19audio_stream_type_t”,于是我们这样修改代码:
1
as_getOutputLatency = (AudioSystem_getOutputLatency)(dlsym(p_library,
"
_ZN7android11AudioSystem16getOutputLatencyEPji
"
));
2
3
//
edit by yueang
4
if
(!
as_getOutputLatency) {
5
as_getOutputLatency = (AudioSystem_getOutputLatency)(dlsym(p_library,
"
_ZN7android11AudioSystem16getOutputLatencyEPj19audio_stream_type_t
"
));
6
}
7
//
edit by yueang end
然后编译运行,问题解决!

