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