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 "liteipc_adapter.h"
21 #include "media_log.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
46
GetInstance()47 AudioCapturer::AudioCapturerClient *AudioCapturer::AudioCapturerClient::GetInstance()
48 {
49 static AudioCapturerClient client;
50 return &client;
51 }
52
ProxyCallbackFunc(void * owner,int code,IpcIo * reply)53 static int32_t ProxyCallbackFunc(void *owner, int code, IpcIo *reply)
54 {
55 if (code != 0) {
56 MEDIA_ERR_LOG("callback error, code = %d", code);
57 return -1;
58 }
59
60 if (owner == nullptr) {
61 return -1;
62 }
63
64 CallBackPara* para = (CallBackPara*)owner;
65 AudioCapturerFuncId funcId = (AudioCapturerFuncId)para->funcId;
66 para->ret = IpcIoPopInt32(reply);
67 switch (funcId) {
68 case AUD_CAP_FUNC_CONNECT:
69 case AUD_CAP_FUNC_DISCONNECT:
70 case AUD_CAP_FUNC_SET_INFO:
71 case AUD_CAP_FUNC_START:
72 case AUD_CAP_FUNC_STOP:
73 case AUD_CAP_FUNC_RELEASE:
74 case AUD_CAP_FUNC_SET_SURFACE:
75 break;
76 case AUD_CAP_FUNC_GET_FRAME_COUNT:
77 (*(uint64_t *)para->data) = IpcIoPopUint64(reply);
78 break;
79 case AUD_CAP_FUNC_GET_STATUS:
80 (*(uint32_t *)para->data) = IpcIoPopUint32(reply);
81 break;
82 case AUD_CAP_FUNC_GET_INFO: {
83 uint32_t size = 0;
84 void *bufferAdd = IpcIoPopFlatObj(reply, &size);
85 if (bufferAdd == nullptr || size == 0) {
86 MEDIA_INFO_LOG("IpcIoPopFlatObj info failed");
87 return -1;
88 }
89 memcpy_s(para->data, sizeof(AudioCapturerInfo), bufferAdd, size);
90 break;
91 }
92 case AUD_CAP_FUNC_GET_MIN_FRAME_COUNT:
93 (*(uint32_t *)para->data) = IpcIoPopUint32(reply);
94 break;
95 default :
96 MEDIA_INFO_LOG("Callback, unkown 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
AudioCapturerClient()119 AudioCapturer::AudioCapturerClient::AudioCapturerClient()
120 {
121 OHOS_SystemInit();
122 IpcIo io;
123 uint8_t tmpData[DEFAULT_IPC_SIZE];
124 IUnknown *iUnknown = SAMGR_GetInstance()->GetDefaultFeatureApi(AUDIO_CAPTURER_SERVICE_NAME);
125 if (iUnknown == nullptr) {
126 MEDIA_ERR_LOG("iUnknown is NULL");
127 throw runtime_error("Ipc proxy GetDefaultFeatureApi failed.");
128 }
129
130 (void)iUnknown->QueryInterface(iUnknown, CLIENT_PROXY_VER, (void **)&proxy_);
131 if (proxy_ == nullptr) {
132 MEDIA_ERR_LOG("QueryInterface failed");
133 throw runtime_error("Ipc proxy init failed.");
134 }
135
136 IpcIoInit(&io, tmpData, DEFAULT_IPC_SIZE, 0);
137 CallBackPara para = {.funcId = AUD_CAP_FUNC_CONNECT, .ret = MEDIA_IPC_FAILED, .data = this};
138 int32_t ret = proxy_->Invoke(proxy_, AUD_CAP_FUNC_CONNECT, nullptr, ¶, ProxyCallbackFunc);
139 if (ret != 0) {
140 MEDIA_ERR_LOG("Connect audio capturer server failed, ret=%d", ret);
141 throw runtime_error("Ipc proxy Invoke failed.");
142 }
143
144 /* Creating a Surface and Initializing Settings */
145 MEDIA_DEBUG_LOG("InitSurface audio capturer.");
146 InitSurface();
147 /* The surface is transferred to the server for processing */
148 timeStampValid_ = false;
149 IpcIoInit(&io, tmpData, DEFAULT_IPC_SIZE, 1);
150 dynamic_cast<SurfaceImpl *>(surface_.get())->WriteIoIpcIo(io);
151 para = {.funcId = AUD_CAP_FUNC_SET_SURFACE, .ret = MEDIA_IPC_FAILED, .data = this};
152 ret = proxy_->Invoke(proxy_, AUD_CAP_FUNC_SET_SURFACE, &io, ¶, ProxyCallbackFunc);
153 if (ret != 0) {
154 MEDIA_ERR_LOG("Connect audio capturer set surface failed, ret=%d", ret);
155 throw runtime_error("Ipc proxy Invoke failed.");
156 }
157
158 MEDIA_INFO_LOG("Create audio capturer client succeed.");
159 }
160
ReleaseAllBuffer()161 void AudioCapturer::AudioCapturerClient::ReleaseAllBuffer()
162 {
163 timeStampValid_ = false;
164 while (true) {
165 SurfaceBuffer *surfaceBuf = surface_->AcquireBuffer();
166 if (surfaceBuf == nullptr) {
167 break;
168 }
169 surface_->ReleaseBuffer(surfaceBuf);
170 }
171 }
172
~AudioCapturerClient()173 AudioCapturer::AudioCapturerClient::~AudioCapturerClient()
174 {
175 IpcIo io;
176 uint8_t tmpData[DEFAULT_IPC_SIZE];
177 IpcIoInit(&io, tmpData, DEFAULT_IPC_SIZE, 0);
178 CallBackPara para = {.funcId = AUD_CAP_FUNC_DISCONNECT, .ret = MEDIA_IPC_FAILED};
179 uint32_t ret = proxy_->Invoke(proxy_, AUD_CAP_FUNC_DISCONNECT, &io, ¶, ProxyCallbackFunc);
180 if (ret != 0) {
181 MEDIA_ERR_LOG("Disconnect audioCapturer server failed, ret=%d", ret);
182 }
183
184 /* release all surface buffer */
185 ReleaseAllBuffer();
186 surface_.reset();
187 surface_ = nullptr;
188 MEDIA_INFO_LOG("dector");
189 }
190
GetMinFrameCount(int32_t sampleRate,int32_t channelCount,AudioCodecFormat audioFormat,size_t & frameCount)191 bool AudioCapturer::AudioCapturerClient::GetMinFrameCount(int32_t sampleRate, int32_t channelCount,
192 AudioCodecFormat audioFormat, size_t &frameCount)
193 {
194 AudioCapturerClient *client = AudioCapturer::AudioCapturerClient::GetInstance();
195 IpcIo io;
196 uint8_t tmpData[DEFAULT_IPC_SIZE];
197 IpcIoInit(&io, tmpData, DEFAULT_IPC_SIZE, 0);
198 IpcIoPushInt32(&io, sampleRate);
199 IpcIoPushInt32(&io, channelCount);
200 IpcIoPushFlatObj(&io, &audioFormat, sizeof(audioFormat));
201 CallBackPara para = {.funcId = AUD_CAP_FUNC_GET_MIN_FRAME_COUNT, .ret = MEDIA_IPC_FAILED, .data = &frameCount};
202 uint32_t ret = client->proxy_->Invoke(client->proxy_, AUD_CAP_FUNC_GET_MIN_FRAME_COUNT, &io, ¶,
203 ProxyCallbackFunc);
204 if (ret != 0) {
205 MEDIA_ERR_LOG("GetMinFrameCount failed, ret=%d", ret);
206 return false;
207 }
208 return (para.ret == 0) ? true : false;
209 }
210
GetFrameCount()211 uint64_t AudioCapturer::AudioCapturerClient::GetFrameCount()
212 {
213 IpcIo io;
214 uint64_t frameCount;
215 uint8_t tmpData[DEFAULT_IPC_SIZE];
216 IpcIoInit(&io, tmpData, DEFAULT_IPC_SIZE, 0);
217 CallBackPara para = {.funcId = AUD_CAP_FUNC_GET_FRAME_COUNT, .ret = MEDIA_IPC_FAILED, .data = &frameCount};
218 uint32_t ret = proxy_->Invoke(proxy_, AUD_CAP_FUNC_GET_FRAME_COUNT, &io, ¶, ProxyCallbackFunc);
219 if (ret != 0) {
220 MEDIA_ERR_LOG("GetFrameCount failed, ret=%d", ret);
221 }
222
223 return frameCount;
224 }
225
GetStatus()226 State AudioCapturer::AudioCapturerClient::GetStatus()
227 {
228 IpcIo io;
229 uint32_t state;
230 uint8_t tmpData[DEFAULT_IPC_SIZE];
231 IpcIoInit(&io, tmpData, DEFAULT_IPC_SIZE, 0);
232 CallBackPara para = {.funcId = AUD_CAP_FUNC_GET_STATUS, .ret = MEDIA_IPC_FAILED, .data = &state};
233 uint32_t ret = proxy_->Invoke(proxy_, AUD_CAP_FUNC_GET_STATUS, &io, ¶, ProxyCallbackFunc);
234 if (ret != 0) {
235 MEDIA_ERR_LOG("GetStatus failed, ret=%d", ret);
236 }
237
238 return (State)state;
239 }
240
GetAudioTime(Timestamp & timestamp,Timestamp::Timebase base)241 bool AudioCapturer::AudioCapturerClient::GetAudioTime(Timestamp ×tamp, Timestamp::Timebase base)
242 {
243 timestamp = curTimestamp_;
244 return true;
245 }
246
SetCapturerInfo(const AudioCapturerInfo info)247 int32_t AudioCapturer::AudioCapturerClient::SetCapturerInfo(const AudioCapturerInfo info)
248 {
249 IpcIo io;
250 uint8_t tmpData[DEFAULT_IPC_SIZE];
251 IpcIoInit(&io, tmpData, DEFAULT_IPC_SIZE, 0);
252 IpcIoPushFlatObj(&io, &info, sizeof(info));
253
254 CallBackPara para = {.funcId = AUD_CAP_FUNC_SET_INFO, .ret = MEDIA_IPC_FAILED};
255 int32_t ret = proxy_->Invoke(proxy_, AUD_CAP_FUNC_SET_INFO, &io, ¶, ProxyCallbackFunc);
256 if (ret != 0) {
257 MEDIA_ERR_LOG("SetCapturerInfo failed, ret=%d", ret);
258 return ret;
259 }
260 return para.ret;
261 }
262
GetCapturerInfo(AudioCapturerInfo & info)263 int32_t AudioCapturer::AudioCapturerClient::GetCapturerInfo(AudioCapturerInfo &info)
264 {
265 IpcIo io;
266 uint8_t tmpData[DEFAULT_IPC_SIZE];
267 IpcIoInit(&io, tmpData, DEFAULT_IPC_SIZE, 0);
268 CallBackPara para = {.funcId = AUD_CAP_FUNC_GET_INFO, .ret = MEDIA_IPC_FAILED};
269 int32_t ret = proxy_->Invoke(proxy_, AUD_CAP_FUNC_GET_INFO, &io, ¶, ProxyCallbackFunc);
270 if (ret != 0) {
271 MEDIA_ERR_LOG("GetCapturerInfo failed, ret=%d", ret);
272 return ret;
273 }
274 return para.ret;
275 }
276
Start()277 bool AudioCapturer::AudioCapturerClient::Start()
278 {
279 IpcIo io;
280 uint8_t tmpData[DEFAULT_IPC_SIZE];
281 IpcIoInit(&io, tmpData, DEFAULT_IPC_SIZE, 0);
282 CallBackPara para = {.funcId = AUD_CAP_FUNC_START, .ret = MEDIA_IPC_FAILED};
283 int32_t ret = proxy_->Invoke(proxy_, AUD_CAP_FUNC_START, &io, ¶, ProxyCallbackFunc);
284 if (ret != 0) {
285 MEDIA_ERR_LOG("Start failed, ret=%d", ret);
286 return ret;
287 }
288
289 return para.ret;
290 }
291
Stop()292 bool AudioCapturer::AudioCapturerClient::Stop()
293 {
294 IpcIo io;
295 uint8_t tmpData[DEFAULT_IPC_SIZE];
296 IpcIoInit(&io, tmpData, DEFAULT_IPC_SIZE, 0);
297 CallBackPara para = {.funcId = AUD_CAP_FUNC_STOP, .ret = MEDIA_IPC_FAILED};
298 int32_t ret = proxy_->Invoke(proxy_, AUD_CAP_FUNC_STOP, &io, ¶, ProxyCallbackFunc);
299 if (ret != 0) {
300 MEDIA_ERR_LOG("Stop failed, ret=%d", ret);
301 return ret;
302 }
303
304 return para.ret;
305 }
306
Release()307 bool AudioCapturer::AudioCapturerClient::Release()
308 {
309 IpcIo io;
310 uint8_t tmpData[DEFAULT_IPC_SIZE];
311 IpcIoInit(&io, tmpData, DEFAULT_IPC_SIZE, 0);
312 CallBackPara para = {.funcId = AUD_CAP_FUNC_RELEASE, .ret = MEDIA_IPC_FAILED};
313 int32_t ret = proxy_->Invoke(proxy_, AUD_CAP_FUNC_RELEASE, &io, ¶, ProxyCallbackFunc);
314 if (ret != 0) {
315 MEDIA_ERR_LOG("Release failed, ret=%d", ret);
316 return ret;
317 }
318 return para.ret;
319 }
320
Read(uint8_t * buffer,size_t userSize,bool isBlockingRead)321 int32_t AudioCapturer::AudioCapturerClient::Read(uint8_t *buffer, size_t userSize, bool isBlockingRead)
322 {
323 if (buffer == NULL || userSize == 0) {
324 return ERR_INVALID_READ;
325 }
326 int32_t readLen = ERR_INVALID_READ;
327 do {
328 SurfaceBuffer *surfaceBuf = surface_->AcquireBuffer();
329 if (surfaceBuf == nullptr) {
330 if (isBlockingRead) {
331 usleep(10000); // indicates 10000 microseconds
332 continue;
333 } else {
334 break;
335 }
336 }
337
338 uint8_t *buf = static_cast<uint8_t *> (surfaceBuf->GetVirAddr());
339 int32_t dataSize = surfaceBuf->GetSize();
340 if (dataSize - sizeof(Timestamp) > userSize) {
341 surface_->ReleaseBuffer(surfaceBuf);
342 MEDIA_ERR_LOG("input buffer size too small.");
343 break;
344 }
345
346 memcpy_s(buffer, userSize, buf + sizeof(Timestamp), dataSize - sizeof(Timestamp));
347 memcpy_s(&curTimestamp_, sizeof(Timestamp), buf, sizeof(Timestamp));
348 timeStampValid_ = true;
349
350 surface_->ReleaseBuffer(surfaceBuf);
351 readLen = dataSize - sizeof(Timestamp);
352 break;
353 } while (isBlockingRead);
354
355 return readLen;
356 }
357
OnBufferAvailable()358 void AudioCapturer::AudioCapturerClient::OnBufferAvailable()
359 {
360 if (surface_ == nullptr) {
361 MEDIA_ERR_LOG("surface is NULL");
362 return;
363 }
364 }
365
GetIClientProxy()366 IClientProxy *AudioCapturer::AudioCapturerClient::GetIClientProxy()
367 {
368 return proxy_;
369 }
370 } // namespace Audio
371 } // namespace OHOS