1 /*
2  * Copyright (c) 2020-2021 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_impl.h"
17 
18 #include <sys/select.h>
19 
20 #include "audio_source.h"
21 #include "audio_encoder.h"
22 #include "media_log.h"
23 
24 namespace OHOS {
25 namespace Audio {
26 using namespace OHOS::Media;
27 
28 const uint64_t TIME_CONVERSION_US_S = 1000000; /* us to s */
29 const uint64_t TIME_CONVERSION_NS_US = 1000; /* ns  to us  */
30 
31 #define CHK_NULL_RETURN(ptr, ret) \
32     do { \
33         if ((ptr) == nullptr) { \
34             MEDIA_ERR_LOG("ptr null"); \
35             return (ret); \
36         } \
37     } while (0)
38 
AudioCapturerImpl()39 AudioCapturerImpl::AudioCapturerImpl()
40     :audioSource_(new(std::nothrow) AudioSource()),
41      audioEncoder_(nullptr)
42 {
43     MEDIA_DEBUG_LOG("ctor");
44 }
45 
~AudioCapturerImpl()46 AudioCapturerImpl::~AudioCapturerImpl()
47 {
48     if (status_ != RELEASED) {
49         Release();
50     }
51     MEDIA_ERR_LOG("dtor");
52 }
53 
GetMinFrameCount(int32_t sampleRate,int32_t channelCount,AudioCodecFormat audioFormat,size_t & frameCount)54 bool AudioCapturerImpl::GetMinFrameCount(int32_t sampleRate, int32_t channelCount, AudioCodecFormat audioFormat,
55     size_t &frameCount)
56 {
57     return AudioSource::GetMinFrameCount(sampleRate, channelCount, audioFormat, frameCount);
58 }
59 
GetFrameCount()60 uint64_t AudioCapturerImpl::GetFrameCount()
61 {
62     CHK_NULL_RETURN(audioSource_, 0);
63     std::lock_guard<std::mutex> lock(mutex_);
64     if (status_ == INITIALIZED || status_ == RELEASED) {
65         MEDIA_ERR_LOG("check state:%u failed", status_);
66         return 0;
67     }
68     return audioSource_->GetFrameCount();
69 }
70 
GetStatus()71 State AudioCapturerImpl::GetStatus()
72 {
73     std::lock_guard<std::mutex> lock(mutex_);
74     return status_;
75 }
76 
GetTimestamp(Timestamp & timestamp,Timestamp::Timebase base)77 bool AudioCapturerImpl::GetTimestamp(Timestamp &timestamp, Timestamp::Timebase base)
78 {
79     std::lock_guard<std::mutex> lock(mutex_);
80     if (status_ == RELEASED) {
81         MEDIA_ERR_LOG("check state:%u failed", status_);
82         return false;
83     }
84     timestamp = timestamp_;
85     return true;
86 }
87 
FillSourceConfig(AudioSourceConfig & sourceConfig,const AudioCapturerInfo & info,uint32_t deviceId)88 static void FillSourceConfig(AudioSourceConfig &sourceConfig, const AudioCapturerInfo &info, uint32_t deviceId)
89 {
90     sourceConfig.deviceId = deviceId;
91     sourceConfig.audioFormat = info.audioFormat;
92     sourceConfig.sampleRate = info.sampleRate;
93     sourceConfig.channelCount = info.channelCount;
94     sourceConfig.interleaved = false;
95     sourceConfig.bitWidth = info.bitWidth;
96     sourceConfig.streamUsage = info.streamType;
97 }
98 
FillEncConfig(AudioEncodeConfig & encodeConfig,const AudioCapturerInfo & info)99 static void FillEncConfig(AudioEncodeConfig &encodeConfig, const AudioCapturerInfo &info)
100 {
101     encodeConfig.audioFormat = info.audioFormat;
102     encodeConfig.bitRate = info.bitRate;
103     encodeConfig.sampleRate = info.sampleRate;
104     encodeConfig.channelCount = info.channelCount;
105     encodeConfig.bitWidth = info.bitWidth;
106 }
107 
SetCapturerInfo(const AudioCapturerInfo info)108 int32_t AudioCapturerImpl::SetCapturerInfo(const AudioCapturerInfo info)
109 {
110     CHK_NULL_RETURN(audioSource_, ERROR);
111     std::lock_guard<std::mutex> lock(mutex_);
112     if (status_ != INITIALIZED) {
113         MEDIA_ERR_LOG("check state:%u failed", status_);
114         return ERR_ILLEGAL_STATE;
115     }
116     std::vector<AudioDeviceDesc> devices;
117     int32_t ret = audioSource_->EnumDeviceBySourceType(info.inputSource, devices);
118     if (ret != SUCCESS || devices.empty()) {
119         MEDIA_ERR_LOG("EnumDeviceBySourceType failed inputSource:%d", info.inputSource);
120         return ret;
121     }
122     MEDIA_INFO_LOG("info.sampleRate:%d", info.sampleRate);
123     AudioSourceConfig sourceConfig;
124     FillSourceConfig(sourceConfig, info, devices[0].deviceId);
125     ret = audioSource_->Initialize(sourceConfig);
126     if (ret != SUCCESS) {
127         MEDIA_ERR_LOG("Initialize failed inputSource:%d", info.inputSource);
128         return ret;
129     }
130     if (info.audioFormat != PCM && info.audioFormat != AUDIO_DEFAULT) {
131         AudioEncodeConfig encodeConfig;
132         FillEncConfig(encodeConfig, info);
133         MEDIA_INFO_LOG("audioEncoder_ bitRate:%d", info.bitRate);
134         std::unique_ptr<AudioEncoder> audioEncoder(new(std::nothrow) AudioEncoder());
135         audioEncoder_ = std::move(audioEncoder);
136         if (audioEncoder_ == nullptr) {
137             MEDIA_ERR_LOG("new AudioEncoder failed inputSource:%d", info.inputSource);
138             return ERR_UNKNOWN;
139         }
140         ret = audioEncoder_->Initialize(encodeConfig);
141         if (ret != SUCCESS) {
142             MEDIA_ERR_LOG("Initialize failed inputSource:%d", info.inputSource);
143             (void)audioSource_->Release();
144             return ret;
145         }
146     }
147     info_ = info;
148     status_ = PREPARED;
149     MEDIA_INFO_LOG("Set Capturer Info SUCCESS");
150     return SUCCESS;
151 }
152 
GetCapturerInfo(AudioCapturerInfo & info)153 int32_t AudioCapturerImpl::GetCapturerInfo(AudioCapturerInfo &info)
154 {
155     std::lock_guard<std::mutex> lock(mutex_);
156     if (status_ == RELEASED) {
157         MEDIA_ERR_LOG("check state:%u failed", status_);
158         return ERR_INVALID_OPERATION;
159     }
160     info = info_;
161     return SUCCESS;
162 }
163 
Record()164 bool AudioCapturerImpl::Record()
165 {
166     CHK_NULL_RETURN(audioSource_, false);
167     std::lock_guard<std::mutex> lock(mutex_);
168     if (status_ != PREPARED && status_ != STOPPED) {
169         MEDIA_ERR_LOG("not PREPARED or STOPPED status:%u", status_);
170         return false;
171     }
172     int32_t ret = audioSource_->Start();
173     if (ret != SUCCESS) {
174         MEDIA_ERR_LOG("audioSource_ Start failed:0x%x", ret);
175         return false;
176     }
177     if (audioEncoder_ != nullptr) {
178         uint32_t deviceId = 0;
179         ret = audioSource_->GetCurrentDeviceId(deviceId);
180         if (ret != SUCCESS) {
181             MEDIA_ERR_LOG("audioSource_ GetCurrentDevice failed:0x%x", ret);
182             return false;
183         }
184         inputDeviceId_ = deviceId;
185         ret = audioEncoder_->BindSource(deviceId);
186         if (ret != SUCCESS) {
187             MEDIA_ERR_LOG("audioEncoder_ BindSource failed:0x%x", ret);
188             return false;
189         }
190         ret = audioEncoder_->Start();
191         if (ret != SUCCESS) {
192             MEDIA_ERR_LOG("audioEncoder_ Start failed:0x%x", ret);
193             return false;
194         }
195     }
196     status_ = RECORDING;
197     MEDIA_INFO_LOG("Start Audio Capturer SUCCESS");
198     return true;
199 }
200 
Read(uint8_t * buffer,size_t userSize,bool isBlockingRead)201 int32_t AudioCapturerImpl::Read(uint8_t *buffer, size_t userSize, bool isBlockingRead)
202 {
203     if (buffer == nullptr || !userSize) {
204         MEDIA_ERR_LOG("Invalid buffer or userSize:%u", userSize);
205         return ERR_INVALID_READ;
206     }
207     CHK_NULL_RETURN(audioSource_, ERROR);
208 
209     if (status_ != RECORDING) {
210         MEDIA_ERR_LOG("ILLEGAL_STATE  status_:%u", status_);
211         return ERR_INVALID_READ;
212     }
213     int32_t readLen = ERR_INVALID_READ;
214     if (info_.audioFormat == PCM || info_.audioFormat == AUDIO_DEFAULT) {
215         AudioFrame frame;
216         frame.buffer = buffer;
217         frame.bufferLen = userSize;
218         readLen = audioSource_->ReadFrame(frame, isBlockingRead);
219         if (readLen == ERR_INVALID_READ) {
220             MEDIA_ERR_LOG("audioSource_ ReadFrame fail,ret:0x%x", readLen);
221             return ERR_INVALID_READ;
222         }
223         timestamp_.time.tv_sec = frame.time.tvSec;
224         timestamp_.time.tv_nsec = frame.time.tvNSec;
225     } else {
226         AudioStream stream;
227         stream.buffer = buffer;
228         stream.bufferLen = userSize;
229 
230         if (audioEncoder_ == nullptr) {
231             MEDIA_ERR_LOG("audioEncoder_ ReadStream fail, audioEncoder_ value is nullptr");
232             return ERR_INVALID_READ;
233         }
234 
235         readLen = audioEncoder_->ReadStream(stream, isBlockingRead);
236         if (readLen == ERR_INVALID_READ) {
237             MEDIA_ERR_LOG("audioEncoder_ ReadStream fail,ret:0x%x", readLen);
238             return ERR_INVALID_READ;
239         }
240         timestamp_.time.tv_sec = static_cast<time_t>(stream.timeStamp / TIME_CONVERSION_US_S);
241         timestamp_.time.tv_nsec = static_cast<time_t>((stream.timeStamp -
242             timestamp_.time.tv_sec * TIME_CONVERSION_US_S) * TIME_CONVERSION_NS_US);
243     }
244     return readLen;
245 }
246 
StopInternal()247 bool AudioCapturerImpl::StopInternal()
248 {
249     CHK_NULL_RETURN(audioSource_, false);
250     int32_t ret;
251     if (audioEncoder_ != nullptr) {
252         MEDIA_INFO_LOG("audioEncoder Stop");
253         ret = audioEncoder_->Stop();
254         if (ret != SUCCESS) {
255             MEDIA_DEBUG_LOG("audioEncoder_ stop fail,ret:0x%x", ret);
256             return false;
257         }
258     }
259     MEDIA_INFO_LOG("audioSource Stop");
260     ret = audioSource_->Stop();
261     if (ret != SUCCESS) {
262         MEDIA_ERR_LOG("audioSource_ stop fail,ret:0x%x", ret);
263         return false;
264     }
265     MEDIA_INFO_LOG("Stop Audio Capturer SUCCESS");
266     status_ = STOPPED;
267     return true;
268 }
269 
Stop()270 bool AudioCapturerImpl::Stop()
271 {
272     std::lock_guard<std::mutex> lock(mutex_);
273     if (status_ != RECORDING) {
274         MEDIA_ERR_LOG("not RECORDING status:%u", status_);
275         return false;
276     }
277     return StopInternal();
278 }
279 
Release()280 bool AudioCapturerImpl::Release()
281 {
282     std::lock_guard<std::mutex> lock(mutex_);
283     if (status_ == RELEASED) {
284         MEDIA_ERR_LOG("ILLEGAL_STATE status_:%u", status_);
285         return false;
286     }
287     if (status_ == INITIALIZED) {
288         status_ = RELEASED;
289         return true;
290     }
291     if (status_ == RECORDING) {
292         if (!StopInternal()) {
293             MEDIA_ERR_LOG("StopInternal err");
294             return false;
295         }
296     }
297     int32_t ret;
298     if (audioEncoder_ != nullptr) {
299         ret = audioEncoder_->Release();
300         if (ret != SUCCESS) {
301             MEDIA_ERR_LOG("audioEncoder_ Release failed:0x%x", ret);
302             return false;
303         }
304     }
305     ret = (audioSource_ != nullptr) ? audioSource_->Release() : SUCCESS;
306     if (ret != SUCCESS) {
307         MEDIA_ERR_LOG("audioSource_ Release failed:0x%x", ret);
308         return false;
309     }
310     status_ = RELEASED;
311     MEDIA_INFO_LOG("Release Audio Capturer SUCCESS");
312     return true;
313 }
314 }  // namespace Audio
315 }  // namespace OHOS
316