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_client.h"
17
18 #include <cstdio>
19 #include "audio_capturer_server.h"
20 #include "media_log.h"
21 #include "ipc_skeleton.h"
22 #include "samgr_lite.h"
23 #include "securec.h"
24 #include "surface_impl.h"
25
OHOS_SystemInit(void)26 extern "C" void __attribute__((weak)) OHOS_SystemInit(void)
27 {
28 SAMGR_Bootstrap();
29 }
30
31 using namespace OHOS::Media;
32 using namespace std;
33 namespace OHOS {
34 namespace Audio {
35 constexpr int32_t SURFACE_QUEUE_SIZE = 5;
36 constexpr int32_t SURFACE_SIZE = 8192;
37 constexpr int32_t SURFACE_HEIGHT = 1;
38 constexpr int32_t SURFACE_WIDTH = 8192;
39
40 struct CallBackPara {
41 int funcId;
42 int32_t ret;
43 void* data;
44 };
45
GetInstance()46 AudioCapturer::AudioCapturerClient *AudioCapturer::AudioCapturerClient::GetInstance()
47 {
48 static AudioCapturerClient client;
49 return &client;
50 }
51
ProxyCallbackFunc(void * owner,int code,IpcIo * reply)52 static int32_t ProxyCallbackFunc(void *owner, int code, IpcIo *reply)
53 {
54 if (code) {
55 MEDIA_ERR_LOG("callback error, code = %d", code);
56 return -1;
57 }
58
59 if (owner == nullptr) {
60 return -1;
61 }
62
63 CallBackPara* para = static_cast<CallBackPara*>(owner);
64 AudioCapturerFuncId funcId = (AudioCapturerFuncId)para->funcId;
65 ReadInt32(reply, ¶->ret);
66 switch (funcId) {
67 case AUD_CAP_FUNC_CONNECT:
68 case AUD_CAP_FUNC_DISCONNECT:
69 case AUD_CAP_FUNC_SET_INFO:
70 case AUD_CAP_FUNC_START:
71 case AUD_CAP_FUNC_STOP:
72 case AUD_CAP_FUNC_RELEASE:
73 case AUD_CAP_FUNC_SET_SURFACE:
74 break;
75 case AUD_CAP_FUNC_GET_FRAME_COUNT:
76 ReadUint64(reply, reinterpret_cast<uint64_t*>(para->data));
77 break;
78 case AUD_CAP_FUNC_GET_STATUS:
79 ReadUint32(reply, reinterpret_cast<uint32_t*>(para->data));
80 break;
81 case AUD_CAP_FUNC_GET_INFO: {
82 uint32_t size = 0;
83 ReadUint32(reply, &size);
84 void *bufferAdd = (void*)ReadBuffer(reply, (size_t)size);
85 if (bufferAdd == nullptr || !size) {
86 MEDIA_INFO_LOG("Readbuffer info failed");
87 return -1;
88 }
89 (void)memcpy_s(para->data, sizeof(AudioCapturerInfo), bufferAdd, size);
90 break;
91 }
92 case AUD_CAP_FUNC_GET_MIN_FRAME_COUNT:
93 ReadUint32(reply, reinterpret_cast<uint32_t*>(para->data));
94 break;
95 default :
96 MEDIA_INFO_LOG("Callback, unknown funcId = %d", para->funcId);
97 break;
98 }
99 return 0;
100 }
101
InitSurface(void)102 int32_t AudioCapturer::AudioCapturerClient::InitSurface(void)
103 {
104 MEDIA_DEBUG_LOG("AudioCapturerClient InitSurface");
105 Surface *surface = Surface::CreateSurface();
106 if (surface == nullptr) {
107 return -1;
108 }
109
110 surface->RegisterConsumerListener(*this);
111 surface_.reset(surface);
112
113 surface->SetWidthAndHeight(SURFACE_WIDTH, SURFACE_HEIGHT);
114 surface->SetQueueSize(SURFACE_QUEUE_SIZE);
115 surface->SetSize(SURFACE_SIZE);
116 return 0;
117 }
118
DeleteSurface(void)119 int32_t AudioCapturer::AudioCapturerClient::DeleteSurface(void)
120 {
121 /* release all surface buffer */
122 if (surface_ == nullptr) {
123 return -1;
124 }
125 ReleaseAllBuffer();
126 surface_->UnregisterConsumerListener();
127 surface_.reset();
128 surface_ = nullptr;
129 return 0;
130 }
131
AudioCapturerClient()132 AudioCapturer::AudioCapturerClient::AudioCapturerClient()
133 {
134 OHOS_SystemInit();
135 IpcIo io;
136 uint8_t tmpData[DEFAULT_IPC_SIZE];
137 IUnknown *iUnknown = SAMGR_GetInstance()->GetDefaultFeatureApi(AUDIO_CAPTURER_SERVICE_NAME);
138 if (iUnknown == nullptr) {
139 MEDIA_ERR_LOG("iUnknown is nullptr");
140 throw runtime_error("Ipc proxy GetDefaultFeatureApi failed.");
141 }
142
143 (void)iUnknown->QueryInterface(iUnknown, CLIENT_PROXY_VER, (void **)&proxy_);
144 if (proxy_ == nullptr) {
145 MEDIA_ERR_LOG("QueryInterface failed");
146 throw runtime_error("Ipc proxy init failed.");
147 }
148
149 IpcIoInit(&io, tmpData, DEFAULT_IPC_SIZE, 0);
150 CallBackPara para = {.funcId = AUD_CAP_FUNC_CONNECT, .ret = MEDIA_IPC_FAILED, .data = this};
151 int32_t ret = proxy_->Invoke(proxy_, AUD_CAP_FUNC_CONNECT, nullptr, ¶, ProxyCallbackFunc);
152 if (ret) {
153 MEDIA_ERR_LOG("Connect audio capturer server failed, ret=%d", ret);
154 throw runtime_error("Ipc proxy Invoke failed.");
155 }
156
157 /* Creating a Surface and Initializing Settings */
158 MEDIA_DEBUG_LOG("InitSurface audio capturer.");
159 InitSurface();
160 /* The surface is transferred to the server for processing */
161 timeStampValid_ = false;
162 IpcIoInit(&io, tmpData, DEFAULT_IPC_SIZE, 1);
163 dynamic_cast<SurfaceImpl *>(surface_.get())->WriteIoIpcIo(io);
164 para = {.funcId = AUD_CAP_FUNC_SET_SURFACE, .ret = MEDIA_IPC_FAILED, .data = this};
165 ret = proxy_->Invoke(proxy_, AUD_CAP_FUNC_SET_SURFACE, &io, ¶, ProxyCallbackFunc);
166 if (ret) {
167 MEDIA_ERR_LOG("Connect audio capturer set surface failed, ret=%d", ret);
168 throw runtime_error("Ipc proxy Invoke failed.");
169 }
170
171 MEDIA_INFO_LOG("Create audio capturer client succeed.");
172 }
173
ReleaseAllBuffer()174 void AudioCapturer::AudioCapturerClient::ReleaseAllBuffer()
175 {
176 timeStampValid_ = false;
177 while (true) {
178 SurfaceBuffer *surfaceBuf = surface_->AcquireBuffer();
179 if (surfaceBuf == nullptr) {
180 break;
181 }
182 surface_->ReleaseBuffer(surfaceBuf);
183 }
184 }
185
~AudioCapturerClient()186 AudioCapturer::AudioCapturerClient::~AudioCapturerClient()
187 {
188 IpcIo io;
189 uint8_t tmpData[DEFAULT_IPC_SIZE];
190 IpcIoInit(&io, tmpData, DEFAULT_IPC_SIZE, 0);
191 CallBackPara para = {.funcId = AUD_CAP_FUNC_DISCONNECT, .ret = MEDIA_IPC_FAILED};
192 uint32_t ret = proxy_->Invoke(proxy_, AUD_CAP_FUNC_DISCONNECT, &io, ¶, ProxyCallbackFunc);
193 if (ret) {
194 MEDIA_ERR_LOG("Disconnect audioCapturer server failed, ret=%d", ret);
195 }
196
197 /* release all surface buffer */
198 if (surface_ != nullptr) {
199 DeleteSurface();
200 }
201 MEDIA_INFO_LOG("destructor");
202 }
203
GetMinFrameCount(int32_t sampleRate,int32_t channelCount,AudioCodecFormat audioFormat,size_t & frameCount)204 bool AudioCapturer::AudioCapturerClient::GetMinFrameCount(int32_t sampleRate, int32_t channelCount,
205 AudioCodecFormat audioFormat, size_t &frameCount)
206 {
207 AudioCapturerClient *client = AudioCapturer::AudioCapturerClient::GetInstance();
208 IpcIo io;
209 uint8_t tmpData[DEFAULT_IPC_SIZE];
210 IpcIoInit(&io, tmpData, DEFAULT_IPC_SIZE, 0);
211 WriteInt32(&io, sampleRate);
212 WriteInt32(&io, channelCount);
213 WriteUint32(&io, sizeof(audioFormat));
214 WriteBuffer(&io, &audioFormat, sizeof(audioFormat));
215 CallBackPara para = {.funcId = AUD_CAP_FUNC_GET_MIN_FRAME_COUNT, .ret = MEDIA_IPC_FAILED, .data = &frameCount};
216 uint32_t ret = client->proxy_->Invoke(client->proxy_, AUD_CAP_FUNC_GET_MIN_FRAME_COUNT, &io, ¶,
217 ProxyCallbackFunc);
218 if (ret) {
219 MEDIA_ERR_LOG("GetMinFrameCount failed, ret=%d", ret);
220 return false;
221 }
222 return (!para.ret) ? true : false;
223 }
224
GetFrameCount()225 uint64_t AudioCapturer::AudioCapturerClient::GetFrameCount()
226 {
227 IpcIo io;
228 uint64_t frameCount;
229 uint8_t tmpData[DEFAULT_IPC_SIZE];
230 IpcIoInit(&io, tmpData, DEFAULT_IPC_SIZE, 0);
231 CallBackPara para = {.funcId = AUD_CAP_FUNC_GET_FRAME_COUNT, .ret = MEDIA_IPC_FAILED, .data = &frameCount};
232
233 if (proxy_ == nullptr) {
234 MEDIA_ERR_LOG("GetFrameCount failed, proxy_ value is nullptr");
235 return 0;
236 }
237
238 uint32_t ret = proxy_->Invoke(proxy_, AUD_CAP_FUNC_GET_FRAME_COUNT, &io, ¶, ProxyCallbackFunc);
239 if (ret) {
240 MEDIA_ERR_LOG("GetFrameCount failed, ret=%d", ret);
241 }
242
243 return frameCount;
244 }
245
GetStatus()246 State AudioCapturer::AudioCapturerClient::GetStatus()
247 {
248 IpcIo io;
249 uint32_t state;
250 uint8_t tmpData[DEFAULT_IPC_SIZE];
251 IpcIoInit(&io, tmpData, DEFAULT_IPC_SIZE, 0);
252 CallBackPara para = {.funcId = AUD_CAP_FUNC_GET_STATUS, .ret = MEDIA_IPC_FAILED, .data = &state};
253
254 if (proxy_ == nullptr) {
255 MEDIA_ERR_LOG("GetStatus failed, proxy_ value is nullptr");
256 return (State)state;
257 }
258
259 uint32_t ret = proxy_->Invoke(proxy_, AUD_CAP_FUNC_GET_STATUS, &io, ¶, ProxyCallbackFunc);
260 if (ret) {
261 MEDIA_ERR_LOG("GetStatus failed, ret=%d", ret);
262 }
263
264 return (State)state;
265 }
266
GetAudioTime(Timestamp & timestamp,Timestamp::Timebase base)267 bool AudioCapturer::AudioCapturerClient::GetAudioTime(Timestamp ×tamp, Timestamp::Timebase base)
268 {
269 timestamp = curTimestamp_;
270 return true;
271 }
272
SetCapturerInfo(const AudioCapturerInfo info)273 int32_t AudioCapturer::AudioCapturerClient::SetCapturerInfo(const AudioCapturerInfo info)
274 {
275 IpcIo io;
276 uint8_t tmpData[DEFAULT_IPC_SIZE];
277 IpcIoInit(&io, tmpData, DEFAULT_IPC_SIZE, 0);
278 WriteUint32(&io, sizeof(info));
279 WriteBuffer(&io, &info, sizeof(info));
280 CallBackPara para = {.funcId = AUD_CAP_FUNC_SET_INFO, .ret = MEDIA_IPC_FAILED};
281
282 if (proxy_ == nullptr) {
283 MEDIA_ERR_LOG("SetCapturerInfo failed, proxy_ value is nullptr");
284 return 0;
285 }
286
287 int32_t ret = proxy_->Invoke(proxy_, AUD_CAP_FUNC_SET_INFO, &io, ¶, ProxyCallbackFunc);
288 if (ret) {
289 MEDIA_ERR_LOG("SetCapturerInfo failed, ret=%d", ret);
290 return ret;
291 }
292 return para.ret;
293 }
294
GetCapturerInfo(AudioCapturerInfo & info)295 int32_t AudioCapturer::AudioCapturerClient::GetCapturerInfo(AudioCapturerInfo &info)
296 {
297 IpcIo io;
298 uint8_t tmpData[DEFAULT_IPC_SIZE];
299 IpcIoInit(&io, tmpData, DEFAULT_IPC_SIZE, 0);
300 CallBackPara para = {.funcId = AUD_CAP_FUNC_GET_INFO, .ret = MEDIA_IPC_FAILED, .data = &info};
301
302 if (proxy_ == nullptr) {
303 MEDIA_ERR_LOG("GetCapturerInfo failed, proxy_ value is nullptr");
304 return 0;
305 }
306
307 int32_t ret = proxy_->Invoke(proxy_, AUD_CAP_FUNC_GET_INFO, &io, ¶, ProxyCallbackFunc);
308 if (ret) {
309 MEDIA_ERR_LOG("GetCapturerInfo failed, ret=%d", ret);
310 return ret;
311 }
312 return para.ret;
313 }
314
Start()315 bool AudioCapturer::AudioCapturerClient::Start()
316 {
317 IpcIo io;
318 uint8_t tmpData[DEFAULT_IPC_SIZE];
319 IpcIoInit(&io, tmpData, DEFAULT_IPC_SIZE, 0);
320 CallBackPara para = {.funcId = AUD_CAP_FUNC_START, .ret = MEDIA_IPC_FAILED};
321
322 if (proxy_ == nullptr) {
323 MEDIA_ERR_LOG("Start failed, proxy_ value is nullptr");
324 return false;
325 }
326
327 int32_t ret = proxy_->Invoke(proxy_, AUD_CAP_FUNC_START, &io, ¶, ProxyCallbackFunc);
328 if (ret) {
329 MEDIA_ERR_LOG("Start failed, ret=%d", ret);
330 return ret;
331 }
332
333 return para.ret;
334 }
335
Stop()336 bool AudioCapturer::AudioCapturerClient::Stop()
337 {
338 IpcIo io;
339 uint8_t tmpData[DEFAULT_IPC_SIZE];
340 IpcIoInit(&io, tmpData, DEFAULT_IPC_SIZE, 0);
341 CallBackPara para = {.funcId = AUD_CAP_FUNC_STOP, .ret = MEDIA_IPC_FAILED};
342
343 if (proxy_ == nullptr) {
344 MEDIA_ERR_LOG("Stop failed, proxy_ value is nullptr");
345 return false;
346 }
347
348 int32_t ret = proxy_->Invoke(proxy_, AUD_CAP_FUNC_STOP, &io, ¶, ProxyCallbackFunc);
349 if (ret) {
350 MEDIA_ERR_LOG("Stop failed, ret=%d", ret);
351 return ret;
352 }
353
354 return para.ret;
355 }
356
Release()357 bool AudioCapturer::AudioCapturerClient::Release()
358 {
359 IpcIo io;
360 uint8_t tmpData[DEFAULT_IPC_SIZE];
361 IpcIoInit(&io, tmpData, DEFAULT_IPC_SIZE, 0);
362 CallBackPara para = {.funcId = AUD_CAP_FUNC_RELEASE, .ret = MEDIA_IPC_FAILED};
363
364 if (proxy_ == nullptr) {
365 MEDIA_ERR_LOG("Release failed, proxy_ value is nullptr");
366 return false;
367 }
368
369 int32_t ret = proxy_->Invoke(proxy_, AUD_CAP_FUNC_RELEASE, &io, ¶, ProxyCallbackFunc);
370 if (ret) {
371 MEDIA_ERR_LOG("Release failed, ret=%d", ret);
372 return ret;
373 }
374
375 DeleteSurface();
376 return para.ret;
377 }
378
Read(uint8_t * buffer,size_t userSize,bool isBlockingRead)379 int32_t AudioCapturer::AudioCapturerClient::Read(uint8_t *buffer, size_t userSize, bool isBlockingRead)
380 {
381 if (buffer == nullptr || !userSize) {
382 return ERR_INVALID_READ;
383 }
384 int32_t readLen = ERR_INVALID_READ;
385 do {
386 SurfaceBuffer *surfaceBuf = surface_->AcquireBuffer();
387 if (surfaceBuf == nullptr) {
388 if (isBlockingRead) {
389 usleep(10000); // indicates 10000 microseconds
390 continue;
391 } else {
392 break;
393 }
394 }
395
396 uint8_t *buf = static_cast<uint8_t *> (surfaceBuf->GetVirAddr());
397 int32_t dataSize = surfaceBuf->GetSize();
398 if (dataSize - sizeof(Timestamp) > userSize) {
399 surface_->ReleaseBuffer(surfaceBuf);
400 MEDIA_ERR_LOG("input buffer size too small.");
401 break;
402 }
403
404 (void)memcpy_s(buffer, userSize, buf + sizeof(Timestamp), dataSize - sizeof(Timestamp));
405 (void)memcpy_s(&curTimestamp_, sizeof(Timestamp), buf, sizeof(Timestamp));
406 timeStampValid_ = true;
407
408 surface_->ReleaseBuffer(surfaceBuf);
409 readLen = dataSize - sizeof(Timestamp);
410 break;
411 } while (isBlockingRead);
412
413 return readLen;
414 }
415
OnBufferAvailable()416 void AudioCapturer::AudioCapturerClient::OnBufferAvailable()
417 {
418 if (surface_ == nullptr) {
419 MEDIA_ERR_LOG("OnBufferAvailable failed, surface_ is nullptr");
420 return;
421 }
422 }
423
GetIClientProxy()424 IClientProxy *AudioCapturer::AudioCapturerClient::GetIClientProxy()
425 {
426 return proxy_;
427 }
428 } // namespace Audio
429 } // namespace OHOS
430