• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &para, 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, &para, 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, &para, 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, &para,
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, &para, 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, &para, 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 &timestamp, 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, &para, 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, &para, 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, &para, 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, &para, 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, &para, 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