1 /*
2 * Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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 "loop_back_demo.h"
17 #include <thread>
18 #include "audio_capturer.h"
19 #include "audio_errors.h"
20 #include "audio_info.h"
21 #include "audio_log.h"
22 #include "audio_renderer.h"
23 using namespace OHOS::AudioStandard;
24
25 namespace OHOS {
26 namespace AudioStandard {
LoopBackDemo()27 LoopBackDemo::LoopBackDemo(){};
~LoopBackDemo()28 LoopBackDemo::~LoopBackDemo()
29 {
30 audioCapturer_->Release();
31 audioRenderer_->Release();
32 }
33
InitializeCapturerOptions(AudioStandard::AudioCapturerOptions &capturerOptions)34 void LoopBackDemo::InitializeCapturerOptions(AudioStandard::AudioCapturerOptions &capturerOptions)
35 {
36 capturerOptions.streamInfo.samplingRate = AudioSamplingRate::SAMPLE_RATE_44100;
37 capturerOptions.streamInfo.encoding = AudioEncodingType::ENCODING_PCM;
38 capturerOptions.streamInfo.format = AudioSampleFormat::SAMPLE_S16LE;
39 capturerOptions.streamInfo.channels = AudioChannel::STEREO;
40 capturerOptions.capturerInfo.sourceType = SourceType::SOURCE_TYPE_MIC;
41 capturerOptions.capturerInfo.capturerFlags = 0;
42 return;
43 }
44
InitAudioCapturer()45 int32_t LoopBackDemo::InitAudioCapturer()
46 {
47 InitializeCapturerOptions(capturerOptions_);
48 audioCapturer_ = AudioCapturer::Create(capturerOptions_);
49 if (audioCapturer_ == nullptr) {
50 AUDIO_INFO_LOG("loopback: create capture fail");
51 return -1;
52 }
53 AUDIO_INFO_LOG("loopback: create capture success");
54 return 0;
55 }
56
StartCapture()57 int32_t LoopBackDemo::StartCapture()
58 {
59 InitAudioCapturer();
60 if (audioCapturer_ == nullptr) {
61 AUDIO_INFO_LOG("loopback: start capture fail - invalid capturer");
62 return -1;
63 }
64 if (isRunningCapture_) {
65 return -1;
66 }
67
68 int32_t ret = 0;
69 bool isStarted = audioCapturer_->Start();
70 if (!isStarted) {
71 AUDIO_INFO_LOG("loopback: start capture fail");
72 return -1;
73 }
74
75 ret = audioCapturer_->GetBufferSize(bufferLen_);
76 if (ret < AudioStandard::SUCCESS) {
77 bufferLen_ = 0;
78 AUDIO_INFO_LOG("loopback: get capture buffer fail - GetBufferSize fail ret:%{public}d", ret);
79 return -1;
80 }
81 isRunningCapture_ = true;
82 AUDIO_INFO_LOG("loopback: audio capture start successful");
83 return 0;
84 }
85
InitializeRenderOptions(AudioRendererParams &rendererParams)86 void LoopBackDemo::InitializeRenderOptions(AudioRendererParams &rendererParams)
87 {
88 rendererParams.sampleFormat = SAMPLE_S16LE;
89 rendererParams.sampleRate = SAMPLE_RATE_44100;
90 rendererParams.channelCount = STEREO;
91 rendererParams.encodingType = ENCODING_PCM;
92 return;
93 }
94
InitAudioRenderer()95 int32_t LoopBackDemo::InitAudioRenderer()
96 {
97 audioRenderer_ = AudioRenderer::Create(AudioStreamType::STREAM_MUSIC);
98 if (!audioRenderer_) {
99 AUDIO_INFO_LOG("loopback: Prepare audioRenderer_ is NULL");
100 return -1;
101 }
102 InitializeRenderOptions(rendererParams_);
103 int res = audioRenderer_->SetParams(rendererParams_);
104 AUDIO_INFO_LOG("loopback: Prepare audioRenderer_ success.");
105 return res;
106 }
107
StartRender()108 int32_t LoopBackDemo::StartRender()
109 {
110 int ret = 0;
111 ret = InitAudioRenderer();
112 if (ret < 0)
113 AUDIO_INFO_LOG("loopback: init audioRenderer_ fail");
114 if (!audioRenderer_) {
115 AUDIO_INFO_LOG("loopback: audioRenderer_ is NULL");
116 return -1;
117 }
118 bool isStarted = audioRenderer_->Start();
119 if (!isStarted) {
120 AUDIO_INFO_LOG("loopback: Start audioRenderer_ fail");
121 return -1;
122 }
123 isRunningRender_ = true;
124 AUDIO_INFO_LOG("loopback: audio render start successful");
125 return 0;
126 }
127
loopback()128 void LoopBackDemo::loopback()
129 {
130 StartCapture();
131 StartRender();
132
133 uint8_t *frame = (uint8_t *)malloc(bufferLen_ * 2);
134 if (frame == nullptr) {
135 return;
136 }
137 while (isRunningCapture_ && isRunningRender_) {
138 int temp = audioCapturer_->Read(*frame, bufferLen_, isBlockingRead_);
139 audioRenderer_->Write(frame, temp);
140 }
141 return;
142 }
CaptureThreadWorker()143 void LoopBackDemo::CaptureThreadWorker() {}
RendererThread()144 void LoopBackDemo::RendererThread() {}
145
GetPermission()146 bool LoopBackDemo::GetPermission()
147 {
148 uint64_t tokenId;
149 const char *perms[2];
150 perms[0] = "ohos.permission.CAMERA";
151 perms[1] = "ohos.permission.MICROPHONE";
152 NativeTokenInfoParams infoInstance = {
153 .dcapsNum = 0,
154 .permsNum = 2,
155 .aclsNum = 0,
156 .dcaps = NULL,
157 .perms = perms,
158 .acls = NULL,
159 .processName = "loop_back_demo",
160 .aplStr = "system_basic",
161 };
162 tokenId = GetAccessTokenId(&infoInstance);
163 if (tokenId == 0) {
164 AUDIO_INFO_LOG("GetCameraPermission GetAccessTokenId failed");
165 return false;
166 }
167 SetSelfTokenID(tokenId);
168 OHOS::Security::AccessToken::AccessTokenKit::ReloadNativeTokenInfo();
169 return true;
170 }
171 } // namespace AudioStandard
172 } // namespace OHOS
173
main()174 int main()
175 {
176 AUDIO_INFO_LOG("loopback: begin");
177 LoopBackDemo *test = new LoopBackDemo();
178 test->GetPermission();
179 setuid(1041); // audio - 1041
180 test->loopback();
181 // TestCmdVector();
182 AUDIO_INFO_LOG("loopback: exit demo!");
183 return 0;
184 }