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 }