在新開(kāi)發(fā)的對(duì)講機(jī)項(xiàng)目中,遇到了對(duì)講無(wú)聲問(wèn)題篇亭,該問(wèn)題直接影響使用缠捌。
一、分析現(xiàn)象
測(cè)試時(shí)暗赶,會(huì)出現(xiàn)一方說(shuō)話鄙币,另一方?jīng)]有聽(tīng)到聲音,但是對(duì)方可以聽(tīng)到信令的聲音蹂随,說(shuō)明網(wǎng)絡(luò)鏈路是通的。
做出如下猜測(cè):
- 音頻數(shù)據(jù)沒(méi)有發(fā)出去因惭,定位對(duì)講端問(wèn)題
- 音頻數(shù)據(jù)發(fā)出去了岳锁,接收端沒(méi)有收到,定位服務(wù)器問(wèn)題
- 音頻數(shù)據(jù)發(fā)出去了蹦魔,但是沒(méi)有播放出來(lái)激率,定位接收端播放問(wèn)題
二咳燕、初步定位問(wèn)題位置
使用展訊的Logel_for_TD工具,抓取cap包
步驟:打開(kāi)Logel_for_TD工具乒躺,點(diǎn)擊Option->Device Configuration
確保CAP LOG勾選上招盲,之后點(diǎn)擊開(kāi)始,復(fù)現(xiàn)問(wèn)題后嘉冒,保存Log文件曹货。使用Wireshark工具打開(kāi)cap包,可以看到數(shù)據(jù)包的詳細(xì)信息讳推。
經(jīng)過(guò)對(duì)比發(fā)現(xiàn)顶籽,無(wú)聲log的CAP包如下:
而有聲的CAP如卻是這樣的:
容易得出結(jié)論,有聲時(shí)會(huì)發(fā)送數(shù)據(jù)包大小為116字節(jié)的UDP包進(jìn)行傳送银觅,無(wú)聲時(shí)則沒(méi)有礼饱,故定位問(wèn)題為按下PTT鍵時(shí),沒(méi)有發(fā)送音頻數(shù)據(jù)
三究驴、進(jìn)一步分析镊绪,為什么沒(méi)有發(fā)送UDP數(shù)據(jù)包
沒(méi)有發(fā)送UDP數(shù)據(jù)包可以有以下幾種原因:
- 沒(méi)有獲取到音頻數(shù)據(jù),可能是沒(méi)有啟動(dòng)錄音或者錄音器異常導(dǎo)致采集音頻失敗
- 獲取到了音頻數(shù)據(jù)洒忧,但是沒(méi)有執(zhí)行數(shù)據(jù)發(fā)送流程
- 有數(shù)據(jù)镰吆,且執(zhí)行了發(fā)送,由于網(wǎng)絡(luò)原因沒(méi)有發(fā)送成功
因?yàn)長(zhǎng)ogel_for_TD抓取的cap包為送到網(wǎng)卡的數(shù)據(jù)跑慕,所以基本可以排除網(wǎng)絡(luò)問(wèn)題万皿,并且通過(guò)Logel_for_TD監(jiān)測(cè)復(fù)現(xiàn)問(wèn)題時(shí)的網(wǎng)絡(luò)環(huán)境,-93dbm左右核行,良好牢硅。
故只剩下1,2兩種可能芝雪,沒(méi)有音頻數(shù)據(jù)或者沒(méi)有執(zhí)行發(fā)送流程减余。
四、確認(rèn)音頻數(shù)據(jù)是否獲取成功
通過(guò)BND平臺(tái)的debug版本進(jìn)行測(cè)試惩系,從log中看出在問(wèn)題復(fù)現(xiàn)時(shí)位岔,獲取到的音頻數(shù)據(jù)為0,故確認(rèn)是錄音的問(wèn)題堡牡。
五抒抬、分析錄音模塊
5.1 測(cè)試用例測(cè)試錄音器是否存在問(wèn)題
對(duì)講APK使用的原生的方案。調(diào)用opensl_es庫(kù)采集和播放音頻晤柄。參考frameworks/wilhelm/tests/examples/slesTestRecBuffQueue.cpp
該文件中詳細(xì)敘述了如何使用:
/* Audio Record Test
First run the program from shell:
# slesTest_recBuffQueue /sdcard/myrec.raw 4
These use adb on host to retrive the file:
% adb pull /sdcard/myrec.raw myrec.raw
How to examine the output with Audacity:
Project / Import raw data
Select myrec.raw file, then click Open button
Choose these options:
Signed 16-bit PCM
Little-endian
1 Channel (Mono)
Sample rate 22050 Hz
Click Import button
*/
在編譯該模塊后擦剑,把生成的可執(zhí)行文件push到system/bin目錄下再按上述測(cè)試即可
通過(guò)數(shù)十次的測(cè)試,錄音均正常。
5.2 dump音頻數(shù)據(jù)
在復(fù)現(xiàn)問(wèn)題時(shí)執(zhí)行dump命令
adb root
adb remount
adb shell
setprop media.dump.path /data/local/media/
setprop media.dump.switch 0x3ff
/data/local/media/目錄下生成dump_record_after_vbc.pcm和dump_record_after_express為錄音時(shí)的數(shù)據(jù)
可以使用AudacityPortable(提取碼:qo80)工具播放裸數(shù)據(jù)惠勒,對(duì)比發(fā)現(xiàn)赚抡,無(wú)聲時(shí)的pcm數(shù)據(jù)為0,進(jìn)一步確認(rèn)了是錄音問(wèn)題。
5.3 是否為硬件問(wèn)題
通過(guò)向展訊提供PCB原理圖纠屋,分析結(jié)論硬件電路沒(méi)有問(wèn)題
5.4 是否為音頻參數(shù)問(wèn)題
使用AudioTester
(提取碼:y7rv )獲取Music參數(shù)涂臣,交與展訊分析
正在分析中。售担。赁遗。
5.5 分析是否為錄音流程問(wèn)題
5.5.1 BSP分析
通過(guò)抓取對(duì)比log發(fā)現(xiàn),有聲和無(wú)聲的log有所不同(PS:這種問(wèn)題一定要抓對(duì)比log)
分析如下:
對(duì)比正常log灼舍,采集聲音異常時(shí)吼和,錄音流程沒(méi)有發(fā)起,因此無(wú)法錄到聲音骑素。
按鍵提示音結(jié)束后炫乓,上層下發(fā)sprd_voip_start=false,準(zhǔn)備結(jié)束voip流程献丑,緊接著錄音應(yīng)用要下發(fā)in_read命令末捣,從而進(jìn)入do_input_standby,結(jié)束voip流程的同時(shí)開(kāi)啟錄音流程创橄。但異常時(shí)一直沒(méi)有下發(fā)in_read箩做,導(dǎo)致audio_hw中錄音流程沒(méi)有發(fā)起。
異常log中沒(méi)有這個(gè)log:in_read sco stop and do standby
正常流程如下:
07-22 15:29:11.176 146 330 D AudioPolicyManagerSPRD: stopOutput() outputDesc->mRefCount[AudioSystem::VOICE_CALL] 1
07-22 15:29:11.176 146 329 D AudioPolicyService: AudioCommandThread() processing set parameters string sprd_voip_start=false, io 0
07-22 15:29:11.176 146 329 V AudioFlinger: setParameters(): io 0, keyvalue sprd_voip_start=false, calling pid 146
07-22 15:29:11.176 146 329 W audio_hw_primary: adev_set_parameters, kvpairs : sprd_voip_start=false
07-22 15:29:11.176 146 329 I audio_hw_primary: adev_set_parameters, voip turn off by output
07-22 15:29:11.176 146 364 D audio_hw_primary: sco:out_write stop and do standby
07-22 15:29:11.176 146 364 V audio_hw_primary: do_output_standby in
07-22 15:29:11.176 146 364 W audio_hw_primary: do_output_standby.mode:0
07-22 15:29:11.176 146 364 V audio_hw_primary: do_output_standby in out
07-22 15:29:11.176 146 364 E audio_hw_primary: out_write: drop data and sleep,out->is_voip is 0, adev->voip_state is 1,adev->voip_start is 0
07-22 15:29:11.196 146 1504 D audio_hw_primary: : in_read sco stop and do standby
07-22 15:29:11.196 146 1504 V audio_hw_primary: do_input_standby, standby=0, in_devices=0x80000004
07-22 15:29:11.196 146 1504 I audio_hw_primary: do_input_standby, fmUlDlHandle=0x00000000, fm_uldl=0x00000000, pcm = 0xb887b328
07-22 15:29:11.226 146 1504 W audio_hw_primary: start_input_stream in mode:0 devices:80000004 call_start:0, is_voip:0, is_bt_sco:0
07-22 15:29:11.226 146 1504 E audio_hw_primary: select_devices_signal starting... adev->out_devices 0x1 adev->in_devices 0x80000004
07-22 15:29:11.226 146 359 V audio_hw_primary: do_select_devices E
07-22 15:29:11.226 146 1504 I audio_hw_primary: select_devices_signal finished.
07-22 15:29:11.226 146 1504 E audio_hw_primary: start_input_stream pcm_open_0
07-22 15:29:11.236 146 1504 W audio_hw_primary: rec_mode(3), sample_rate(8000)
07-22 15:29:11.236 146 1504 W audio_hw_primary: extendArraySize=118, eq_size=52, dp_size=38
07-22 15:29:11.236 146 1504 I audio_hw_primary: record process module created is successful.
**請(qǐng)上層同事協(xié)助客戶排查妥畏,是否客戶自身應(yīng)用流程有問(wèn)題邦邦。**
5.5.2 流程分析
//這里在1秒鐘之內(nèi)start和stop了output這次output對(duì)應(yīng)的stream 是0
STREAM_VOICE_CALL = 0;
07-22 15:34:30.126 146 146 D AudioPolicyManagerSPRD: startOutput() output 2, stream 0, session 13
07-22 15:34:30.766 146 308 D AudioPolicyManagerSPRD: stopOutput() output 2, stream 0, session 13
07-22 15:34:30.766 146 307 W audio_hw_primary: adev_set_parameters, kvpairs : sprd_voip_start=false
這次聲音導(dǎo)致voip關(guān)閉了,正常的對(duì)講最好是將voip打開(kāi)
打開(kāi)voip的方法就是在audiorecord和和播錄音的那個(gè)player的流類(lèi)型要設(shè)置成STREAM_VOICE_CALL 而且這個(gè)player要跟record一起stop醉蚁。
根據(jù)展訊建議燃辖,播放Tone音不使用STREAM_VOICE_CALL,我測(cè)試去掉了TONE音网棍,但是問(wèn)題依然存在黔龟。