一直抽不出時(shí)間來調(diào)試這個(gè)BUG。 沒想到cnblogs已經(jīng)有人解決。謝謝分享。
原址:http://www.cnblogs.com/yueang/archive/2013/02/18/2915186.html
研究過twilove的faplayer代碼的人應(yīng)該都知道,faplayer代碼中使用了兩個(gè)播放器程序,一個(gè)是android自帶的播放器作為默認(rèn)的播放器,另外一個(gè)就是使用了vlc代碼的播放器。之前寫過一篇相關(guān)的文章:
采用faplayer播放EPUB書中的mp4視頻
這次要講的問題就是在使用faplayer中的vlc代碼的時(shí)候,之前在2.3系統(tǒng)上正常,后來升級的4.04的時(shí)候發(fā)現(xiàn)只有聲音沒有圖像,這個(gè)問題后來解決了,解決的過程下篇日志再說,這次要說的是系統(tǒng)升級的4.1之后,發(fā)現(xiàn)只有圖像又沒有聲音了!!!(尼瑪能靠點(diǎn)譜不?)由于faplayer早已停止更新了,所以這個(gè)問題只能自己想辦法搞定。最終在我的“不懈努力下”,問題終于搞定了,在解決問題的過程中我覺得有些東西是比較有意思也值得記錄下來的,因此寫了這篇文章.
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ù)出了問題,我們來看看這個(gè)函數(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 }
嗯,看來這個(gè)函數(shù)的內(nèi)容是從so庫中查找相應(yīng)的函數(shù)地址,然后把地址賦值給對應(yīng)的函數(shù)指針,那么類似“_ZN7android11AudioSystem19getOutputFrameCountEPii”這樣的字符串就是函數(shù)在so庫中的簽名了。我們看看這個(gè)字符串所代表的函數(shù)的簽名:
1 // _ZN7android11AudioSystem19getOutputFrameCountEPii 2 typedef int (*AudioSystem_getOutputFrameCount)( int *, int );
為什么這樣的函數(shù)在so中會有這樣奇怪的代號呢?這方面的知識有一篇文章講的很好: C++的函數(shù)重載
了解了這個(gè)后我就在猜想:應(yīng)該是某個(gè)或是某幾個(gè)函數(shù)的簽名在4.1中發(fā)生了改變,導(dǎo)致找不到才出的錯(cuò),于是我這樣修改程序:
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”這個(gè)簽名現(xiàn)在在libmedia.so中找不到了,那么現(xiàn)在這個(gè)函數(shù)的簽名是什么呢?要想弄清楚這個(gè),我們需要弄清楚怎么查看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 ...
看上去挺像那么回事的是吧?其實(shí)在仔細(xì)查找其中的內(nèi)容后,沒有發(fā)現(xiàn)任何跟“_ZN7android11AudioSystem16getOutputLatencyEPji”相關(guān)的代碼,別說這個(gè)空函數(shù)了,連已經(jīng)證明加載成功的函數(shù)的簽名也沒有找到,這是為什么呢?
這時(shí)候我就想到,android系統(tǒng)中的庫文件都是在arm-linux環(huán)境下編譯的,屬于交叉編譯,而我們使用的命令都是在x86架構(gòu)下的指令,他解析的符號類型會不會也是x86的指令呢?為了弄清楚這個(gè)問題,我需要安裝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)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
