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 24namespace OHOS { 25namespace Audio { 26using namespace OHOS::Media; 27 28const uint64_t TIME_CONVERSION_US_S = 1000000; /* us to s */ 29const 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 39AudioCapturerImpl::AudioCapturerImpl() 40 :audioSource_(new(std::nothrow) AudioSource()), 41 audioEncoder_(nullptr) 42{ 43 MEDIA_DEBUG_LOG("ctor"); 44} 45 46AudioCapturerImpl::~AudioCapturerImpl() 47{ 48 if (status_ != RELEASED) { 49 Release(); 50 } 51 MEDIA_ERR_LOG("dtor"); 52} 53 54bool 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 60uint64_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 71State AudioCapturerImpl::GetStatus() 72{ 73 std::lock_guard<std::mutex> lock(mutex_); 74 return status_; 75} 76 77bool 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 88static 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 99static 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 108int32_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 153int32_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 164bool 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 201int32_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 247bool 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 270bool 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 280bool 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