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, &para->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, &para, 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, &para, 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, &para, 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, &para,
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, &para, 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, &para, 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 &timestamp, 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, &para, 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, &para, 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, &para, 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, &para, 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, &para, 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