1/* 2 * Copyright (c) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include <benchmark/benchmark.h> 17#include <climits> 18#include <gtest/gtest.h> 19#include "hdf_base.h" 20#include "osal_mem.h" 21#include "v4_0/audio_types.h" 22#include "v4_0/iaudio_manager.h" 23#include "v4_0/iaudio_render.h" 24 25using namespace std; 26using namespace testing::ext; 27 28namespace { 29const int BUFFER_LENTH = 1024 * 16; 30const int DEEP_BUFFER_RENDER_PERIOD_SIZE = 4 * 1024; 31const int MOVE_LEFT_NUM = 8; 32const int32_t AUDIO_RENDER_CHANNELCOUNT = 2; 33const int32_t AUDIO_SAMPLE_RATE_48K = 48000; 34const int32_t MAX_AUDIO_ADAPTER_DESC = 5; 35const int32_t MMAP_SUGGEST_BUFFER_SIZE = 1920; 36const int32_t ITERATION_FREQUENCY = 100; 37const int32_t REPETITION_FREQUENCY = 3; 38 39class AudioRenderMmapBenchmarkTest : public benchmark::Fixture { 40public: 41 struct IAudioManager *manager_ = nullptr; 42 struct AudioAdapterDescriptor descs_[MAX_AUDIO_ADAPTER_DESC]; 43 struct AudioAdapterDescriptor *desc_; 44 struct IAudioAdapter *adapter_ = nullptr; 45 struct IAudioRender *render_ = nullptr; 46 struct AudioDeviceDescriptor devDescRender_ = {}; 47 struct AudioSampleAttributes attrsRender_ = {}; 48 uint32_t renderId_ = 0; 49 char *devDescriptorName_ = nullptr; 50 uint32_t size_ = MAX_AUDIO_ADAPTER_DESC; 51 virtual void SetUp(const ::benchmark::State &state); 52 virtual void TearDown(const ::benchmark::State &state); 53 void InitRenderAttrs(struct AudioSampleAttributes &attrs); 54 void InitRenderDevDesc(struct AudioDeviceDescriptor &devDesc); 55 void FreeAdapterElements(struct AudioAdapterDescriptor *dataBlock, bool freeSelf); 56 void ReleaseAllAdapterDescs(struct AudioAdapterDescriptor *descs, uint32_t descsLen); 57}; 58 59void AudioRenderMmapBenchmarkTest::InitRenderAttrs(struct AudioSampleAttributes &attrs) 60{ 61 attrs.channelCount = AUDIO_RENDER_CHANNELCOUNT; 62 attrs.sampleRate = AUDIO_SAMPLE_RATE_48K; 63 attrs.interleaved = 0; 64 attrs.type = AUDIO_MMAP_NOIRQ; 65 attrs.period = DEEP_BUFFER_RENDER_PERIOD_SIZE; 66 attrs.frameSize = AUDIO_FORMAT_TYPE_PCM_16_BIT * AUDIO_RENDER_CHANNELCOUNT / MOVE_LEFT_NUM; 67 attrs.isBigEndian = false; 68 attrs.isSignedData = true; 69 attrs.startThreshold = DEEP_BUFFER_RENDER_PERIOD_SIZE / (attrs.format * attrs.channelCount / MOVE_LEFT_NUM); 70 attrs.stopThreshold = INT_MAX; 71 attrs.silenceThreshold = BUFFER_LENTH; 72} 73 74void AudioRenderMmapBenchmarkTest::InitRenderDevDesc(struct AudioDeviceDescriptor &devDesc) 75{ 76 devDesc.pins = PIN_OUT_SPEAKER; 77 devDescriptorName_ = strdup("cardname"); 78 devDesc.desc = devDescriptorName_; 79 80 ASSERT_NE(desc_, nullptr); 81 ASSERT_NE(desc_->ports, nullptr); 82 for (uint32_t index = 0; index < desc_->portsLen; index++) { 83 if (desc_->ports[index].dir == PORT_OUT) { 84 devDesc.portId = desc_->ports[index].portId; 85 return; 86 } 87 } 88 free(devDesc.desc); 89 devDesc.desc = nullptr; 90} 91 92void AudioRenderMmapBenchmarkTest::FreeAdapterElements(struct AudioAdapterDescriptor *dataBlock, bool freeSelf) 93{ 94 if (dataBlock == nullptr) { 95 return; 96 } 97 98 OsalMemFree(dataBlock->adapterName); 99 100 OsalMemFree(dataBlock->ports); 101 102 if (freeSelf) { 103 OsalMemFree(dataBlock); 104 } 105} 106 107void AudioRenderMmapBenchmarkTest::ReleaseAllAdapterDescs(struct AudioAdapterDescriptor *descs, uint32_t descsLen) 108{ 109 if (descs == nullptr || descsLen == 0) { 110 return; 111 } 112 113 for (uint32_t i = 0; i < descsLen; i++) { 114 FreeAdapterElements(&descs[i], false); 115 } 116} 117 118void AudioRenderMmapBenchmarkTest::SetUp(const ::benchmark::State &state) 119{ 120 manager_ = IAudioManagerGet(false); 121 ASSERT_NE(manager_, nullptr); 122 123 ASSERT_EQ(HDF_SUCCESS, manager_->GetAllAdapters(manager_, descs_, &size_)); 124 ASSERT_NE(descs_, nullptr); 125 EXPECT_GE(MAX_AUDIO_ADAPTER_DESC, size_); 126 desc_ = &descs_[0]; 127 ASSERT_EQ(HDF_SUCCESS, manager_->LoadAdapter(manager_, desc_, &adapter_)); 128 ASSERT_NE(adapter_, nullptr); 129 InitRenderDevDesc(devDescRender_); 130 InitRenderAttrs(attrsRender_); 131 132 attrsRender_.format = AUDIO_FORMAT_TYPE_PCM_16_BIT; 133 int32_t ret = adapter_->CreateRender(adapter_, &devDescRender_, &attrsRender_, &render_, &renderId_); 134 if (ret != HDF_SUCCESS) { 135 attrsRender_.format = AUDIO_FORMAT_TYPE_PCM_32_BIT; 136 ASSERT_EQ(HDF_SUCCESS, adapter_->CreateRender(adapter_, &devDescRender_, &attrsRender_, &render_, &renderId_)); 137 } 138 ASSERT_NE(render_, nullptr); 139} 140 141void AudioRenderMmapBenchmarkTest::TearDown(const ::benchmark::State &state) 142{ 143 ASSERT_NE(devDescriptorName_, nullptr); 144 free(devDescriptorName_); 145 146 if (adapter_ != nullptr) { 147 adapter_->DestroyRender(adapter_, renderId_); 148 render_ = nullptr; 149 } 150 if (manager_ != nullptr) { 151 manager_->UnloadAdapter(manager_, desc_->adapterName); 152 adapter_ = nullptr; 153 ReleaseAllAdapterDescs(descs_, size_); 154 155 IAudioManagerRelease(manager_, false); 156 } 157} 158 159BENCHMARK_F(AudioRenderMmapBenchmarkTest, ReqMmapBuffer)(benchmark::State &state) 160{ 161 ASSERT_NE(render_, nullptr); 162 int32_t ret; 163 uint64_t frames = 0; 164 struct AudioTimeStamp time; 165 time.tvNSec = 0; 166 time.tvSec = 0; 167 int32_t reqSize = MMAP_SUGGEST_BUFFER_SIZE; 168 struct AudioMmapBufferDescriptor desc; 169 170 for (auto _ : state) { 171 ret = render_->ReqMmapBuffer(render_, reqSize, &desc); 172 ASSERT_TRUE(ret == HDF_SUCCESS || ret == HDF_ERR_INVALID_PARAM); 173 174 ret = render_->Start(render_); 175 ASSERT_TRUE(ret == HDF_SUCCESS || ret == HDF_FAILURE); 176 177 ret = render_->GetMmapPosition(render_, &frames, &time); 178 ASSERT_TRUE(ret == HDF_SUCCESS); 179 180 ret = render_->Stop(render_); 181 ASSERT_TRUE(ret == HDF_SUCCESS || ret == HDF_FAILURE); 182 } 183} 184 185BENCHMARK_REGISTER_F(AudioRenderMmapBenchmarkTest, ReqMmapBuffer)-> 186 Iterations(ITERATION_FREQUENCY)->Repetitions(REPETITION_FREQUENCY)->ReportAggregatesOnly(); 187} 188