From 7f58d7f05365237b3618257c5f7cea63abb7e1b4 Mon Sep 17 00:00:00 2001 From: "hezhiqiang19@huawei.com" Date: Mon, 3 Jul 2023 21:56:52 +0800 Subject: [PATCH] add loop test Signed-off-by: hezhiqiang19@huawei.com Change-Id: I46775c1028bd47991d96446718eb1086c318ea2c --- services/audio_service/BUILD.gn | 1 + .../client/src/audio_process_in_client.cpp | 4 +- .../server/src/audio_endpoint.cpp | 9 +- .../example/audio_process_client_test.cpp | 133 ++++++++++++++++-- 4 files changed, 130 insertions(+), 17 deletions(-) diff --git a/services/audio_service/BUILD.gn b/services/audio_service/BUILD.gn index 665d48edd3..5036c7e0d6 100644 --- a/services/audio_service/BUILD.gn +++ b/services/audio_service/BUILD.gn @@ -330,6 +330,7 @@ ohos_executable("audio_process_client_test") { ] external_deps = [ + "c_utils:utils", "hiviewdfx_hilog_native:libhilog", "init:libbegetutil", ] diff --git a/services/audio_service/client/src/audio_process_in_client.cpp b/services/audio_service/client/src/audio_process_in_client.cpp index 5796448b39..9939293b75 100644 --- a/services/audio_service/client/src/audio_process_in_client.cpp +++ b/services/audio_service/client/src/audio_process_in_client.cpp @@ -330,7 +330,7 @@ int32_t AudioProcessInClientInner::ReadFromProcessClient() const CHECK_AND_RETURN_RET_LOG(audioBuffer_ != nullptr, ERR_INVALID_HANDLE, "%{public}s audio buffer is null.", __func__); uint64_t curReadPos = audioBuffer_->GetCurReadFrame(); - + Trace trace("AudioProcessInClient::ReadProcessData-<" + std::to_string(curReadPos)); BufferDesc readbufDesc = {nullptr, 0, 0}; int32_t ret = audioBuffer_->GetReadbuffer(curReadPos, readbufDesc); if (ret != SUCCESS || readbufDesc.buffer == nullptr || readbufDesc.bufLength != spanSizeInByte_ || @@ -708,7 +708,7 @@ void AudioProcessInClientInner::RecordProcessCallbackFuc() continue; } threadStatus_ = INRUNNING; - Trace traceLoop("AudioProcessInClient RecordProcessCallbackFuc InRunning"); + Trace traceLoop("AudioProcessInClient Record InRunning"); if (needReSyncPosition_ && RecordReSyncServicePos() == SUCCESS) { wakeUpTime = ClockTime::GetCurNano(); needReSyncPosition_ = false; diff --git a/services/audio_service/server/src/audio_endpoint.cpp b/services/audio_service/server/src/audio_endpoint.cpp index 800adea61b..41a9e3fbb6 100644 --- a/services/audio_service/server/src/audio_endpoint.cpp +++ b/services/audio_service/server/src/audio_endpoint.cpp @@ -956,8 +956,6 @@ int64_t AudioEndpointInner::GetPredictNextWriteTime(uint64_t posInFrame) } } int64_t nextHdiWriteTime = writeTimeModel_.GetTimeOfPos(posInFrame); - AUDIO_INFO_LOG("%{public}s end, posInFrame %{public}" PRIu64", nextHdiWriteTime %{public}" PRIu64"", - __func__, posInFrame, nextHdiWriteTime); return nextHdiWriteTime; } @@ -965,7 +963,8 @@ bool AudioEndpointInner::RecordPrepareNextLoop(uint64_t curReadPos, int64_t &wak { uint64_t nextHandlePos = curReadPos + dstSpanSizeInframe_; int64_t nextHdiWriteTime = GetPredictNextWriteTime(nextHandlePos); - wakeUpTime = nextHdiWriteTime + serverAheadReadTime_; + int64_t tempDelay = 12000000; // 12ms + wakeUpTime = nextHdiWriteTime + tempDelay; int32_t ret = dstAudioBuffer_->SetCurWriteFrame(nextHandlePos); CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, false, "%{public}s set dst buffer write frame fail, ret %{public}d.", @@ -974,8 +973,6 @@ bool AudioEndpointInner::RecordPrepareNextLoop(uint64_t curReadPos, int64_t &wak CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, false, "%{public}s set dst buffer read frame fail, ret %{public}d.", __func__, ret); - AUDIO_INFO_LOG("%{public}s end, dstAudioBuffer curReadPos %{public}" PRIu64", nextHandlePos %{public}" PRIu64", " - "wakeUpTime %{public}" PRId64"", __func__, curReadPos, nextHandlePos, wakeUpTime); return true; } @@ -1122,6 +1119,7 @@ int32_t AudioEndpointInner::WriteToSpecialProcBuf(const std::shared_ptrGetCurWriteFrame(); + Trace trace("AudioEndpoint::WriteProcessData-<" + std::to_string(curWritePos)); SpanInfo *curWriteSpan = procBuf->GetSpanInfo(curWritePos); CHECK_AND_RETURN_RET_LOG(curWriteSpan != nullptr, ERR_INVALID_HANDLE, "%{public}s get write span info of procBuf fail.", __func__); @@ -1173,6 +1171,7 @@ void AudioEndpointInner::WriteToProcessBuffers(const BufferDesc &readBuf) int32_t AudioEndpointInner::ReadFromEndpoint(uint64_t curReadPos) { + Trace trace("AudioEndpoint::ReadDstBuffer=<" + std::to_string(curReadPos)); AUDIO_DEBUG_LOG("%{public}s enter, dstAudioBuffer curReadPos %{public}" PRIu64".", __func__, curReadPos); CHECK_AND_RETURN_RET_LOG(dstAudioBuffer_ != nullptr, ERR_INVALID_HANDLE, "%{public}s dst audio buffer is null.", __func__); diff --git a/services/audio_service/test/example/audio_process_client_test.cpp b/services/audio_service/test/example/audio_process_client_test.cpp index 5f08a1c896..bf7faa10e0 100644 --- a/services/audio_service/test/example/audio_process_client_test.cpp +++ b/services/audio_service/test/example/audio_process_client_test.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include "audio_log.h" #include "audio_errors.h" @@ -48,6 +49,9 @@ namespace { CHANGE_SPK_PROCESS_VOL = 6, RELEASE_SPK_PROCESS = 7, + START_LOOP_TEST = 10, + END_LOOP_TEST = 11, + INIT_LOCAL_MIC_PROCESS = 20, INIT_REMOTE_MIC_PROCESS = 21, START_MIC_PROCESS = 22, @@ -66,8 +70,12 @@ namespace { AUTO_RUN_SPK_TEST = 2, INTERACTIVE_RUN_MIC_TEST = 3, AUTO_RUN_MIC_TEST = 4, - EXIT_PROC_TEST = 5, + INTERACTIVE_RUN_LOOP = 5, + EXIT_PROC_TEST = 6, }; + static constexpr size_t CACHE_BUFFER_SIZE = 960; + bool g_loopTest = false; + int64_t g_stampTime = 0; } class AudioProcessTest; @@ -79,6 +87,9 @@ FILE *g_micPcmFile = nullptr; mutex g_autoRunMutex; condition_variable g_autoRunCV; +unique_ptr g_byteBuffer = nullptr; +BufferDesc g_cacheBuffer = {nullptr, 0, 0}; + string ConfigSpkTest(bool isRemote); string CallStartSpk(); string CallPauseSpk(); @@ -101,6 +112,7 @@ std::map g_audioProcessTestType = { {AUTO_RUN_SPK_TEST, "Auto run spk process test"}, {INTERACTIVE_RUN_MIC_TEST, "Interactive run mic process test"}, {AUTO_RUN_MIC_TEST, "Auto run mic process test"}, + {INTERACTIVE_RUN_LOOP, "Roundtrip latency test"}, {EXIT_PROC_TEST, "Exit audio process test"}, }; @@ -114,6 +126,9 @@ std::map g_interactiveOptStrMap = { {CHANGE_SPK_PROCESS_VOL, "change spk process volume"}, {RELEASE_SPK_PROCESS, "release spk process"}, + {START_LOOP_TEST, "start loop"}, + {END_LOOP_TEST, "end loop"}, + {INIT_LOCAL_MIC_PROCESS, "call local mic init process"}, {INIT_REMOTE_MIC_PROCESS, "call remote mic init process"}, {START_MIC_PROCESS, "call start mic process"}, @@ -150,11 +165,54 @@ public: ~AudioProcessTestCallback() = default; void OnHandleData(size_t length) override; + void InitSignalBuffer(const BufferDesc &signalSoundBuffer) + { + int ret = memset_s(signalSoundBuffer.buffer, signalSoundBuffer.bufLength, 0, signalSoundBuffer.bufLength); + if (ret != EOK) { + return; + } + const int channels = 2; // 2 channels + const int samplePerChannel = 96 / channels; // 96 for 1ms + int16_t *signalData = static_cast(static_cast(signalSoundBuffer.buffer)); + int16_t bound = 10; + for (int idx = 0; idx < samplePerChannel; idx++) { + signalData[channels * idx] = bound + static_cast(sinf(2.0f * static_cast(M_PI) * idx / + samplePerChannel) * (SHRT_MAX - bound)); + for (int c = 1; c < channels; c++) { + signalData[channels * idx + c] = signalData[channels * idx]; + } + } + }; private: int32_t CaptureToFile(const BufferDesc &bufDesc); int32_t RenderFromFile(const BufferDesc &bufDesc); + void HandleWriteData(const BufferDesc &bufDesc) + { + loopCount_++; + int32_t periodCount = loopCount_ % 400; // 400 * 0.005 = 2s + + if (periodCount == 0) { + InitSignalBuffer(bufDesc); // set signal data + int64_t temp = ClockTime::GetCurNano() - g_stampTime; + std::cout << "client read-write latency:" << (temp / AUDIO_MS_PER_SECOND) << " us" << std::endl; + return; + } + + int32_t keepQuiteHold = 50; + if (periodCount > keepQuiteHold) { + return; + } + + // copy mic data in the cache buffer + int ret = memcpy_s(static_cast(bufDesc.buffer), bufDesc.bufLength, + static_cast(g_cacheBuffer.buffer), g_cacheBuffer.bufLength); + if (ret != EOK) { + AUDIO_WARNING_LOG("memcpy_s failed."); + } + }; + private: std::shared_ptr procClient_ = nullptr; int32_t loopCount_ = -1; // for loop @@ -200,6 +258,12 @@ int32_t AudioProcessTestCallback::CaptureToFile(const BufferDesc &bufDesc) size_t cnt = fwrite(bufDesc.buffer, 1, bufDesc.bufLength, g_micPcmFile); CHECK_AND_RETURN_RET_LOG(cnt == bufDesc.bufLength, ERR_WRITE_FAILED, "%{public}s fwrite fail, cnt %{public}zu, bufLength %{public}zu.", __func__, cnt, bufDesc.bufLength); + int ret = memcpy_s(static_cast(g_cacheBuffer.buffer), bufDesc.bufLength, + static_cast(bufDesc.buffer), bufDesc.bufLength); + if (ret != EOK) { + AUDIO_WARNING_LOG("memcpy_s failed."); + } + g_stampTime = ClockTime::GetCurNano(); return SUCCESS; } @@ -248,15 +312,17 @@ void AudioProcessTestCallback::OnHandleData(size_t length) CHECK_AND_RETURN_LOG(ret == SUCCESS, "%{public}s capture to file fail, ret %{public}d.", __func__, ret); } else { - ret = RenderFromFile(bufDesc); - CHECK_AND_RETURN_LOG(ret == SUCCESS, "%{public}s render from file fail, ret %{public}d.", - __func__, ret); + if (!g_loopTest) { + ret = RenderFromFile(bufDesc); + CHECK_AND_RETURN_LOG(ret == SUCCESS, "%{public}s render from file fail, ret %{public}d.", __func__, ret); + } else { + HandleWriteData(bufDesc); + } } ret = procClient_->Enqueue(bufDesc); CHECK_AND_RETURN_LOG(ret == SUCCESS, "%{public}s enqueue buf fail, clientMode %{public}d, ret %{public}d.", __func__, clientMode_, ret); - AUDIO_INFO_LOG("%{public}s enqueue end, clientMode %{public}d, bufLength %{public}zu.", - __func__, clientMode_, bufDesc.bufLength); + callBack.End(); } @@ -707,10 +773,6 @@ string CallReleaseSpk() string ConfigMicTest(bool isRemote) { - if (!isRemote) { - return "Local mic init is not supported."; - } - if (!OpenMicFile()) { cout << "Open mic file path failed!" << g_spkfilePath << endl; return "Open mic pcm file fail"; @@ -773,8 +835,49 @@ string CallReleaseMic() return "Mic release SUCCESS"; } +string StartLoopTest() +{ + std::cout << ConfigMicTest(false); + std::cout << CallStartMic(); + std::cout << endl; + + int32_t ret = g_audioProcessTest->InitSpk(0, false); + if (ret != SUCCESS) { + CallReleaseMic(); + return "init spk failed"; + } else { + std::cout << "init spk success" << endl; + } + + std::cout << CallStartSpk(); + std::cout << endl; + return "StartLoopTest success!"; +} + +string EndLoopTest() +{ + std::cout << CallReleaseSpk(); + std::cout << endl; + std::cout << CallStopMic(); + std::cout << endl; + std::cout << CallReleaseMic(); + std::cout << endl; + return "EndLooptest"; +} + +void InitCachebuffer() +{ + g_byteBuffer = std::make_unique(CACHE_BUFFER_SIZE); + g_cacheBuffer.buffer = g_byteBuffer.get(); + g_cacheBuffer.bufLength = CACHE_BUFFER_SIZE; + g_cacheBuffer.dataLength = CACHE_BUFFER_SIZE; +} + void InteractiveRun() { + if (g_loopTest) { + InitCachebuffer(); + } cout << "Interactive run process test enter." << endl; bool isInteractiveRun = true; while (isInteractiveRun) { @@ -794,6 +897,12 @@ void InteractiveRun() case INIT_REMOTE_SPK_PROCESS: cout << ConfigSpkTest(true) << endl; break; + case START_LOOP_TEST: + cout << StartLoopTest() << endl; + break; + case END_LOOP_TEST: + cout << EndLoopTest() << endl; + break; case INIT_LOCAL_MIC_PROCESS: cout << ConfigMicTest(false) << endl; break; @@ -850,6 +959,10 @@ int main() case INTERACTIVE_RUN_MIC_TEST: InteractiveRun(); break; + case INTERACTIVE_RUN_LOOP: + g_loopTest = true; + InteractiveRun(); + break; case AUTO_RUN_SPK_TEST: AutoRunSpk(); break; -- Gitee