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 ×tamp, 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