• 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_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), &timestamp, 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