一直抽不出時間來調(diào)試這個BUG。 沒想到cnblogs已經(jīng)有人解決。謝謝分享。
原址:http://www.cnblogs.com/yueang/archive/2013/02/18/2915186.html
研究過twilove的faplayer代碼的人應(yīng)該都知道,faplayer代碼中使用了兩個播放器程序,一個是android自帶的播放器作為默認(rèn)的播放器,另外一個就是使用了vlc代碼的播放器。之前寫過一篇相關(guān)的文章:
采用faplayer播放EPUB書中的mp4視頻
這次要講的問題就是在使用faplayer中的vlc代碼的時候,之前在2.3系統(tǒng)上正常,后來升級的4.04的時候發(fā)現(xiàn)只有聲音沒有圖像,這個問題后來解決了,解決的過程下篇日志再說,這次要說的是系統(tǒng)升級的4.1之后,發(fā)現(xiàn)只有圖像又沒有聲音了!!!(尼瑪能靠點(diǎn)譜不?)由于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函數(shù)出了問題,我們來看看這個函數(shù)的內(nèi)容:
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
}
嗯,看來這個函數(shù)的內(nèi)容是從so庫中查找相應(yīng)的函數(shù)地址,然后把地址賦值給對應(yīng)的函數(shù)指針,那么類似“_ZN7android11AudioSystem19getOutputFrameCountEPii”這樣的字符串就是函數(shù)在so庫中的簽名了。我們看看這個字符串所代表的函數(shù)的簽名:
1
//
_ZN7android11AudioSystem19getOutputFrameCountEPii
2
typedef
int
(*AudioSystem_getOutputFrameCount)(
int
*,
int
);
為什么這樣的函數(shù)在so中會有這樣奇怪的代號呢?這方面的知識有一篇文章講的很好: C++的函數(shù)重載
了解了這個后我就在猜想:應(yīng)該是某個或是某幾個函數(shù)的簽名在4.1中發(fā)生了改變,導(dǎo)致找不到才出的錯,于是我這樣修改程序:
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
}
查看日志后,發(fā)現(xiàn)是“error2” 也就是as_getOutputLatency為空,那說明“_ZN7android11AudioSystem16getOutputLatencyEPji”這個簽名現(xiàn)在在libmedia.so中找不到了,那么現(xiàn)在這個函數(shù)的簽名是什么呢?要想弄清楚這個,我們需要弄清楚怎么查看libmedia.so中函數(shù)的簽名。
在網(wǎng)上查詢方法后,在終端上使用readelf -s libmedia.so,結(jié)果是一長串符號列表,類似下面的內(nèi)容:
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
...
看上去挺像那么回事的是吧?其實在仔細(xì)查找其中的內(nèi)容后,沒有發(fā)現(xiàn)任何跟“_ZN7android11AudioSystem16getOutputLatencyEPji”相關(guān)的代碼,別說這個空函數(shù)了,連已經(jīng)證明加載成功的函數(shù)的簽名也沒有找到,這是為什么呢?
這時候我就想到,android系統(tǒng)中的庫文件都是在arm-linux環(huán)境下編譯的,屬于交叉編譯,而我們使用的命令都是在x86架構(gòu)下的指令,他解析的符號類型會不會也是x86的指令呢?為了弄清楚這個問題,我需要安裝arm-linux的開發(fā)工具,在參考了這幾篇文章后,我成功的安裝了arm-linux工具鏈。
Android 開發(fā)環(huán)境建立-ARM編譯器安裝
使用arm-2008q3-72-arm-none-linux-gnueabi-i686-pc-linux-gnu交叉編譯成功在板子上運(yùn)行
然后使用命令: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
...
結(jié)果是上面這樣的代碼。把結(jié)果輸出到文件中,進(jìn)行查找:
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函數(shù)的符號由“_ZN7android11AudioSystem16getOutputLatencyEPji”變?yōu)椤癬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
然后編譯運(yùn)行,問題解決!
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元

