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 &timestamp, 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