1 /*
2 * Copyright (c) 2021-2022 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 "audio_capturer_server.h"
17
18 #include "audio_capturer_impl.h"
19 #include "media_errors.h"
20 #include "media_log.h"
21 #include "securec.h"
22 #include "surface.h"
23 #include "surface_impl.h"
24
25 using namespace std;
26 using namespace OHOS::Media;
27 namespace OHOS {
28 namespace Audio {
GetInstance()29 AudioCapturerServer *AudioCapturerServer::GetInstance()
30 {
31 static AudioCapturerServer mng;
32 return &mng;
33 }
34
GetAudioCapturer(pid_t pid)35 AudioCapturerImpl *AudioCapturerServer::GetAudioCapturer(pid_t pid)
36 {
37 return (pid == clientPid_) ? capturer_ : nullptr;
38 }
39
AudioCapturerServerInit()40 int32_t AudioCapturerServer::AudioCapturerServerInit()
41 {
42 return 0;
43 }
44
AcceptServer(pid_t pid,IpcIo * reply)45 void AudioCapturerServer::AcceptServer(pid_t pid, IpcIo *reply)
46 {
47 MEDIA_INFO_LOG("in");
48 if (clientPid_ == -1) {
49 capturer_ = new AudioCapturerImpl;
50 clientPid_ = pid;
51 IpcIoPushInt32(reply, MEDIA_OK);
52 } else {
53 IpcIoPushInt32(reply, MEDIA_IPC_FAILED);
54 }
55 }
56
DropServer(pid_t pid,IpcIo * reply)57 void AudioCapturerServer::DropServer(pid_t pid, IpcIo *reply)
58 {
59 MEDIA_INFO_LOG("in");
60 if (pid == clientPid_) {
61 if (dataThreadId_ != 0) {
62 threadExit_ = true;
63 pthread_join(dataThreadId_, nullptr);
64 threadExit_ = false;
65 dataThreadId_ = 0;
66 }
67 delete capturer_;
68 capturer_ = nullptr;
69 clientPid_ = -1;
70 }
71 IpcIoPushInt32(reply, MEDIA_OK);
72 }
73
ReadAudioDataProcess(void * serverStr)74 void *AudioCapturerServer::ReadAudioDataProcess(void *serverStr)
75 {
76 AudioCapturerServer *serverStore = (AudioCapturerServer *)serverStr;
77 if (serverStore == nullptr || serverStore->surface_ == nullptr) {
78 MEDIA_ERR_LOG("No available serverStore in surface.");
79 return nullptr;
80 }
81
82 MEDIA_INFO_LOG("thread work");
83 while (!serverStore->threadExit_) {
84 /* request surface buffer */
85 SurfaceBuffer *surfaceBuf = serverStore->surface_->RequestBuffer();
86 if (surfaceBuf == nullptr) {
87 usleep(20000); // indicates 20000 microseconds
88 continue;
89 }
90 uint32_t size = serverStore->surface_->GetSize();
91 void *buf = surfaceBuf->GetVirAddr();
92 uint32_t offSet = sizeof(Timestamp);
93 /* Timestamp + audio data */
94 /* read frame data, and reserve timestamp space */
95 int32_t readLen = serverStore->capturer_->Read((uint8_t *)buf + offSet, size - offSet, true);
96 if (readLen == ERR_INVALID_READ) {
97 serverStore->surface_->CancelBuffer(surfaceBuf);
98 usleep(20000); // indicates 20000 microseconds
99 continue;
100 }
101
102 Timestamp timestamp;
103 Timestamp::Timebase base = {};
104 bool ret = serverStore->capturer_->GetTimestamp(timestamp, base);
105 if (!ret) {
106 MEDIA_ERR_LOG("No readtime get.");
107 serverStore->surface_->CancelBuffer(surfaceBuf);
108 continue;
109 }
110 memcpy_s((uint8_t *)buf, sizeof(Timestamp), ×tamp, sizeof(Timestamp));
111 surfaceBuf->SetSize(sizeof(Timestamp) + readLen);
112
113 // flush buffer
114 if (serverStore->surface_->FlushBuffer(surfaceBuf) != 0) {
115 MEDIA_ERR_LOG("Flush surface buffer failed.");
116 serverStore->surface_->CancelBuffer(surfaceBuf);
117 ret = MEDIA_ERR;
118 continue;
119 }
120 }
121 MEDIA_INFO_LOG("thread exit");
122 return nullptr;
123 }
124
SetSurfaceProcess(Surface * surface)125 int32_t AudioCapturerServer::SetSurfaceProcess(Surface *surface)
126 {
127 if (surface == nullptr) {
128 MEDIA_INFO_LOG("Surface is null");
129 return -1;
130 }
131 surface_ = surface;
132
133 return 0;
134 }
135
GetMinFrameCount(IpcIo * req,IpcIo * reply)136 void AudioCapturerServer::GetMinFrameCount(IpcIo *req, IpcIo *reply)
137 {
138 int32_t sampleRate = IpcIoPopInt32(req);
139 int32_t channelCount = IpcIoPopInt32(req);
140 AudioCodecFormat audioFormat = (AudioCodecFormat)IpcIoPopInt32(req);
141 size_t frameCount;
142 bool ret = AudioCapturerImpl::GetMinFrameCount(sampleRate, channelCount, audioFormat, frameCount);
143 IpcIoPushInt32(reply, ret);
144 IpcIoPushUint32(reply, frameCount);
145 }
146
SetInfo(AudioCapturerImpl * capturer,IpcIo * req,IpcIo * reply)147 void AudioCapturerServer::SetInfo(AudioCapturerImpl *capturer, IpcIo *req, IpcIo *reply)
148 {
149 AudioCapturerInfo info;
150 uint32_t size = 0;
151 void *bufferAdd = IpcIoPopFlatObj(req, &size);
152
153 if (bufferAdd == nullptr || size == 0) {
154 MEDIA_INFO_LOG("IpcIoPopFlatObj info failed");
155 IpcIoPushInt32(reply, -1);
156 return;
157 }
158 memcpy_s(&info, sizeof(AudioCapturerInfo), bufferAdd, size);
159 int32_t ret = capturer->SetCapturerInfo(info);
160 IpcIoPushInt32(reply, ret);
161 }
162
GetInfo(AudioCapturerImpl * capturer,IpcIo * reply)163 void AudioCapturerServer::GetInfo(AudioCapturerImpl *capturer, IpcIo *reply)
164 {
165 AudioCapturerInfo info;
166 int32_t ret = capturer->GetCapturerInfo(info);
167 IpcIoPushInt32(reply, ret);
168 IpcIoPushFlatObj(reply, &info, sizeof(AudioCapturerInfo));
169 }
170
Start(AudioCapturerImpl * capturer,IpcIo * reply)171 void AudioCapturerServer::Start(AudioCapturerImpl *capturer, IpcIo *reply)
172 {
173 bool record = capturer->Record();
174 if (record) {
175 threadExit_ = false;
176 pthread_create(&dataThreadId_, nullptr, ReadAudioDataProcess, this);
177 MEDIA_INFO_LOG("create thread ReadAudioDataProcess SUCCESS");
178 }
179 IpcIoPushInt32(reply, record);
180 }
181
Stop(AudioCapturerImpl * capturer,IpcIo * reply)182 void AudioCapturerServer::Stop(AudioCapturerImpl *capturer, IpcIo *reply)
183 {
184 int32_t ret = capturer->Stop();
185 if (dataThreadId_ != 0) {
186 threadExit_ = true;
187 pthread_join(dataThreadId_, nullptr);
188 threadExit_ = false;
189 dataThreadId_ = 0;
190 }
191 IpcIoPushInt32(reply, ret);
192 }
193
GetMiniFrameCount(IpcIo * req,IpcIo * reply)194 void AudioCapturerServer::GetMiniFrameCount(IpcIo *req, IpcIo *reply)
195 {
196 uint32_t size = 0;
197 int32_t sampleRate = IpcIoPopInt32(req);
198 int32_t channelCount = IpcIoPopInt32(req);
199 AudioCodecFormat *audioFormat = (AudioCodecFormat *)IpcIoPopFlatObj(req, &size);
200
201 size_t frameCount;
202 bool ret = AudioCapturerImpl::GetMinFrameCount(sampleRate, channelCount, *audioFormat, frameCount);
203 IpcIoPushInt32(reply, ret);
204 IpcIoPushUint64(reply, frameCount);
205 }
206
GetFrameCount(AudioCapturerImpl * capturer,IpcIo * reply)207 void AudioCapturerServer::GetFrameCount(AudioCapturerImpl *capturer, IpcIo *reply)
208 {
209 uint64_t frameCount = capturer->GetFrameCount();
210 IpcIoPushInt32(reply, MEDIA_OK);
211 IpcIoPushUint64(reply, frameCount);
212 }
213
GetStatus(AudioCapturerImpl * capturer,IpcIo * reply)214 void AudioCapturerServer::GetStatus(AudioCapturerImpl *capturer, IpcIo *reply)
215 {
216 State status = capturer->GetStatus();
217 IpcIoPushInt32(reply, MEDIA_OK);
218 IpcIoPushInt32(reply, status);
219 }
220
SetSurface(IpcIo * req,IpcIo * reply)221 void AudioCapturerServer::SetSurface(IpcIo *req, IpcIo *reply)
222 {
223 Surface *surface = SurfaceImpl::GenericSurfaceByIpcIo(*req);
224 int32_t ret = SetSurfaceProcess(surface);
225 IpcIoPushInt32(reply, ret);
226 }
227
Dispatch(int32_t funcId,pid_t pid,IpcIo * req,IpcIo * reply)228 void AudioCapturerServer::Dispatch(int32_t funcId, pid_t pid, IpcIo *req, IpcIo *reply)
229 {
230 int32_t ret;
231 if (funcId == AUD_CAP_FUNC_GET_MIN_FRAME_COUNT) {
232 return;
233 }
234 if (funcId == AUD_CAP_FUNC_CONNECT) {
235 AcceptServer(pid, reply);
236 return;
237 }
238 auto capturer = GetAudioCapturer(pid);
239 if (capturer == nullptr) {
240 MEDIA_ERR_LOG("Cannot find client object.(pid=%d)", pid);
241 IpcIoPushInt32(reply, MEDIA_IPC_FAILED);
242 }
243 switch (funcId) {
244 case AUD_CAP_FUNC_DISCONNECT:
245 DropServer(pid, reply);
246 break;
247 case AUD_CAP_FUNC_GET_FRAME_COUNT:
248 GetFrameCount(capturer, reply);
249 break;
250 case AUD_CAP_FUNC_GET_STATUS:
251 GetStatus(capturer, reply);
252 break;
253 case AUD_CAP_FUNC_SET_INFO:
254 SetInfo(capturer, req, reply);
255 break;
256 case AUD_CAP_FUNC_GET_INFO:
257 GetInfo(capturer, reply);
258 break;
259 case AUD_CAP_FUNC_START:
260 Start(capturer, reply);
261 break;
262 case AUD_CAP_FUNC_STOP:
263 Stop(capturer, reply);
264 break;
265 case AUD_CAP_FUNC_RELEASE:
266 ret = capturer->Release();
267 IpcIoPushInt32(reply, ret);
268 break;
269 case AUD_CAP_FUNC_SET_SURFACE:
270 SetSurface(req, reply);
271 break;
272 case AUD_CAP_FUNC_GET_MIN_FRAME_COUNT:
273 GetMiniFrameCount(req, reply);
274 break;
275 default:
276 break;
277 }
278 }
279 } // namespace Audio
280 } // namespace OHOS