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_source.h"
17d5a2a63bSopenharmony_ci#include "media_log.h"
18d5a2a63bSopenharmony_ci#include "securec.h"
19d5a2a63bSopenharmony_ci
20d5a2a63bSopenharmony_cinamespace OHOS {
21d5a2a63bSopenharmony_cinamespace Audio {
22d5a2a63bSopenharmony_ci#define AUDIO_RETURN_VAL_IF_NULL(condition)                                            \
23d5a2a63bSopenharmony_ci    do {                                                                               \
24d5a2a63bSopenharmony_ci        if ((condition) == nullptr) {                                                  \
25d5a2a63bSopenharmony_ci            MEDIA_ERR_LOG("" #condition " is NULL");    \
26d5a2a63bSopenharmony_ci            return ERR_ILLEGAL_STATE;                                                  \
27d5a2a63bSopenharmony_ci        }                                                                              \
28d5a2a63bSopenharmony_ci    } while (0)
29d5a2a63bSopenharmony_ci
30d5a2a63bSopenharmony_ciusing namespace OHOS::Media;
31d5a2a63bSopenharmony_cistatic AudioManager *g_audioManager = nullptr;
32d5a2a63bSopenharmony_ci
33d5a2a63bSopenharmony_ciAudioSource::AudioSource()
34d5a2a63bSopenharmony_ci    : initialized_(false),
35d5a2a63bSopenharmony_ci      started_(false),
36d5a2a63bSopenharmony_ci      audioAdapter_(nullptr),
37d5a2a63bSopenharmony_ci      audioCapture_(nullptr)
38d5a2a63bSopenharmony_ci{
39d5a2a63bSopenharmony_ci    if (g_audioManager == nullptr) {
40d5a2a63bSopenharmony_ci        g_audioManager = GetAudioManagerFuncs();
41d5a2a63bSopenharmony_ci        MEDIA_DEBUG_LOG("g_audioManager");
42d5a2a63bSopenharmony_ci    }
43d5a2a63bSopenharmony_ci    int size = 0;
44d5a2a63bSopenharmony_ci    struct AudioAdapterDescriptor *descs = nullptr;
45d5a2a63bSopenharmony_ci    g_audioManager->GetAllAdapters(g_audioManager, &descs, &size);
46d5a2a63bSopenharmony_ci    MEDIA_DEBUG_LOG("GetAllAdapters size:%d", size);
47d5a2a63bSopenharmony_ci
48d5a2a63bSopenharmony_ci    for (int index = 0; index < size; index++) {
49d5a2a63bSopenharmony_ci        struct AudioAdapterDescriptor *desc = &descs[index];
50d5a2a63bSopenharmony_ci        for (int port = 0; (desc != nullptr && port < static_cast<int>(desc->portNum)); port++) {
51d5a2a63bSopenharmony_ci            if ((desc->ports[port].dir != PORT_IN) ||
52d5a2a63bSopenharmony_ci                (g_audioManager->LoadAdapter(g_audioManager, desc, &audioAdapter_))) {
53d5a2a63bSopenharmony_ci                continue;
54d5a2a63bSopenharmony_ci            }
55d5a2a63bSopenharmony_ci            (void)audioAdapter_->InitAllPorts(audioAdapter_);
56d5a2a63bSopenharmony_ci            if (memcpy_s(&capturePort_, sizeof(struct AudioPort),
57d5a2a63bSopenharmony_ci                &desc->ports[port], sizeof(struct AudioPort))) {
58d5a2a63bSopenharmony_ci                MEDIA_WARNING_LOG("memcpy_s capturePort_ failed");
59d5a2a63bSopenharmony_ci            }
60d5a2a63bSopenharmony_ci            break;
61d5a2a63bSopenharmony_ci        }
62d5a2a63bSopenharmony_ci    }
63d5a2a63bSopenharmony_ci    MEDIA_DEBUG_LOG("LoadAdapter audioAdapter_");
64d5a2a63bSopenharmony_ci}
65d5a2a63bSopenharmony_ci
66d5a2a63bSopenharmony_ciAudioSource::~AudioSource()
67d5a2a63bSopenharmony_ci{
68d5a2a63bSopenharmony_ci    MEDIA_DEBUG_LOG("in");
69d5a2a63bSopenharmony_ci    if (initialized_) {
70d5a2a63bSopenharmony_ci        Release();
71d5a2a63bSopenharmony_ci    }
72d5a2a63bSopenharmony_ci
73d5a2a63bSopenharmony_ci    if (audioAdapter_ != nullptr) {
74d5a2a63bSopenharmony_ci        MEDIA_INFO_LOG("UnloadModule audioAdapter_");
75d5a2a63bSopenharmony_ci        if (g_audioManager == nullptr) {
76d5a2a63bSopenharmony_ci            MEDIA_ERR_LOG("~AudioSource g_audioManager is nullptr");
77d5a2a63bSopenharmony_ci            audioAdapter_ = nullptr;
78d5a2a63bSopenharmony_ci            return;
79d5a2a63bSopenharmony_ci        }
80d5a2a63bSopenharmony_ci        g_audioManager->UnloadAdapter(g_audioManager, audioAdapter_);
81d5a2a63bSopenharmony_ci        audioAdapter_ = nullptr;
82d5a2a63bSopenharmony_ci    }
83d5a2a63bSopenharmony_ci}
84d5a2a63bSopenharmony_ci
85d5a2a63bSopenharmony_ciint32_t AudioSource::InitCheck()
86d5a2a63bSopenharmony_ci{
87d5a2a63bSopenharmony_ci    if (!initialized_) {
88d5a2a63bSopenharmony_ci        MEDIA_ERR_LOG("not initialized");
89d5a2a63bSopenharmony_ci        return ERR_ILLEGAL_STATE;
90d5a2a63bSopenharmony_ci    }
91d5a2a63bSopenharmony_ci    return SUCCESS;
92d5a2a63bSopenharmony_ci}
93d5a2a63bSopenharmony_ci
94d5a2a63bSopenharmony_cibool AudioSource::GetMinFrameCount(int32_t sampleRate, int32_t channelCount,
95d5a2a63bSopenharmony_ci                                   AudioCodecFormat audioFormat, size_t &frameCount)
96d5a2a63bSopenharmony_ci{
97d5a2a63bSopenharmony_ci    if (sampleRate <= 0 || channelCount <= 0 || audioFormat < AUDIO_DEFAULT ||
98d5a2a63bSopenharmony_ci        audioFormat >= FORMAT_BUTT) {
99d5a2a63bSopenharmony_ci        MEDIA_ERR_LOG("invalid params sampleRate:%d channelCount:%d audioFormat:%d", sampleRate,
100d5a2a63bSopenharmony_ci                      channelCount, audioFormat);
101d5a2a63bSopenharmony_ci        return false;
102d5a2a63bSopenharmony_ci    }
103d5a2a63bSopenharmony_ci    frameCount = 0;
104d5a2a63bSopenharmony_ci    return true;
105d5a2a63bSopenharmony_ci}
106d5a2a63bSopenharmony_ci
107d5a2a63bSopenharmony_ciuint64_t AudioSource::GetFrameCount()
108d5a2a63bSopenharmony_ci{
109d5a2a63bSopenharmony_ci    int32_t ret;
110d5a2a63bSopenharmony_ci    if ((ret = InitCheck()) != SUCCESS) {
111d5a2a63bSopenharmony_ci        return ret;
112d5a2a63bSopenharmony_ci    }
113d5a2a63bSopenharmony_ci    AUDIO_RETURN_VAL_IF_NULL(audioCapture_);
114d5a2a63bSopenharmony_ci    uint64_t frameCount = 0;
115d5a2a63bSopenharmony_ci    ret = audioCapture_->attr.GetFrameCount(reinterpret_cast<AudioHandle>(audioCapture_), &frameCount);
116d5a2a63bSopenharmony_ci    if (ret != SUCCESS) {
117d5a2a63bSopenharmony_ci        MEDIA_ERR_LOG("attr GetFrameCount failed:0x%x ", ret);
118d5a2a63bSopenharmony_ci        return ret;
119d5a2a63bSopenharmony_ci    }
120d5a2a63bSopenharmony_ci    return frameCount;
121d5a2a63bSopenharmony_ci}
122d5a2a63bSopenharmony_ci
123d5a2a63bSopenharmony_ciint32_t AudioSource::EnumDeviceBySourceType(AudioSourceType inputSource, std::vector<AudioDeviceDesc> &devices)
124d5a2a63bSopenharmony_ci{
125d5a2a63bSopenharmony_ci    if (inputSource != AUDIO_MIC && inputSource != AUDIO_SOURCE_DEFAULT) {
126d5a2a63bSopenharmony_ci        MEDIA_ERR_LOG("AudioSource only support AUDIO_MIC");
127d5a2a63bSopenharmony_ci        return ERR_INVALID_PARAM;
128d5a2a63bSopenharmony_ci    }
129d5a2a63bSopenharmony_ci    AUDIO_RETURN_VAL_IF_NULL(audioAdapter_);
130d5a2a63bSopenharmony_ci
131d5a2a63bSopenharmony_ci    struct AudioPortCapability capability;
132d5a2a63bSopenharmony_ci    audioAdapter_->GetPortCapability(audioAdapter_, &capturePort_, &capability);
133d5a2a63bSopenharmony_ci    AudioDeviceDesc deviceDesc;
134d5a2a63bSopenharmony_ci    deviceDesc.deviceId = capability.deviceId;
135d5a2a63bSopenharmony_ci    deviceDesc.inputSourceType = AUDIO_MIC;
136d5a2a63bSopenharmony_ci    devices.push_back(deviceDesc);
137d5a2a63bSopenharmony_ci    return SUCCESS;
138d5a2a63bSopenharmony_ci}
139d5a2a63bSopenharmony_ci
140d5a2a63bSopenharmony_cistatic bool ConvertCodecFormatToAudioFormat(AudioCodecFormat codecFormat, AudioFormat *audioFormat)
141d5a2a63bSopenharmony_ci{
142d5a2a63bSopenharmony_ci    if (audioFormat == nullptr) {
143d5a2a63bSopenharmony_ci        MEDIA_ERR_LOG("audioFormat is NULL");
144d5a2a63bSopenharmony_ci        return false;
145d5a2a63bSopenharmony_ci    }
146d5a2a63bSopenharmony_ci
147d5a2a63bSopenharmony_ci    switch (codecFormat) {
148d5a2a63bSopenharmony_ci        case AUDIO_DEFAULT:
149d5a2a63bSopenharmony_ci        case PCM:
150d5a2a63bSopenharmony_ci            *audioFormat = AUDIO_FORMAT_TYPE_PCM_16_BIT;
151d5a2a63bSopenharmony_ci            break;
152d5a2a63bSopenharmony_ci        case AAC_LC:
153d5a2a63bSopenharmony_ci            *audioFormat = AUDIO_FORMAT_TYPE_AAC_LC;
154d5a2a63bSopenharmony_ci            break;
155d5a2a63bSopenharmony_ci        case AAC_LD:
156d5a2a63bSopenharmony_ci            *audioFormat = AUDIO_FORMAT_TYPE_AAC_LD;
157d5a2a63bSopenharmony_ci            break;
158d5a2a63bSopenharmony_ci        case AAC_ELD:
159d5a2a63bSopenharmony_ci            *audioFormat = AUDIO_FORMAT_TYPE_AAC_ELD;
160d5a2a63bSopenharmony_ci            break;
161d5a2a63bSopenharmony_ci        case AAC_HE_V1:
162d5a2a63bSopenharmony_ci            *audioFormat = AUDIO_FORMAT_TYPE_AAC_HE_V1;
163d5a2a63bSopenharmony_ci            break;
164d5a2a63bSopenharmony_ci        case AAC_HE_V2:
165d5a2a63bSopenharmony_ci            *audioFormat = AUDIO_FORMAT_TYPE_AAC_HE_V2;
166d5a2a63bSopenharmony_ci            break;
167d5a2a63bSopenharmony_ci        case G711A:
168d5a2a63bSopenharmony_ci            *audioFormat = AUDIO_FORMAT_TYPE_G711A;
169d5a2a63bSopenharmony_ci            break;
170d5a2a63bSopenharmony_ci        case G711U:
171d5a2a63bSopenharmony_ci            *audioFormat = AUDIO_FORMAT_TYPE_G711U;
172d5a2a63bSopenharmony_ci            break;
173d5a2a63bSopenharmony_ci        case G726:
174d5a2a63bSopenharmony_ci            *audioFormat = AUDIO_FORMAT_TYPE_G726;
175d5a2a63bSopenharmony_ci            break;
176d5a2a63bSopenharmony_ci        default: {
177d5a2a63bSopenharmony_ci            MEDIA_ERR_LOG("not support this codecFormat:%d", codecFormat);
178d5a2a63bSopenharmony_ci            return false;
179d5a2a63bSopenharmony_ci        }
180d5a2a63bSopenharmony_ci    }
181d5a2a63bSopenharmony_ci    return true;
182d5a2a63bSopenharmony_ci}
183d5a2a63bSopenharmony_ci
184d5a2a63bSopenharmony_ciint32_t AudioSource::Initialize(const AudioSourceConfig &config)
185d5a2a63bSopenharmony_ci{
186d5a2a63bSopenharmony_ci    AUDIO_RETURN_VAL_IF_NULL(audioAdapter_);
187d5a2a63bSopenharmony_ci    MEDIA_INFO_LOG("deviceId:0x%x config.sampleRate:%d", config.deviceId, config.sampleRate);
188d5a2a63bSopenharmony_ci    struct AudioDeviceDescriptor desc;
189d5a2a63bSopenharmony_ci    desc.pins = PIN_IN_MIC;
190d5a2a63bSopenharmony_ci    desc.desc = NULL;
191d5a2a63bSopenharmony_ci    struct AudioSampleAttributes attrs;
192d5a2a63bSopenharmony_ci    if (config.streamUsage == TYPE_MEDIA || config.streamUsage == TYPE_DEFAULT) {
193d5a2a63bSopenharmony_ci        attrs.type = AUDIO_IN_MEDIA;
194d5a2a63bSopenharmony_ci    } else if (config.streamUsage == TYPE_VOICE_COMMUNICATION) {
195d5a2a63bSopenharmony_ci        attrs.type = AUDIO_IN_COMMUNICATION;
196d5a2a63bSopenharmony_ci    }
197d5a2a63bSopenharmony_ci    if (config.bitWidth != BIT_WIDTH_16) {
198d5a2a63bSopenharmony_ci        MEDIA_ERR_LOG("not support bitWidth:%d, only support 16 bit width", config.bitWidth);
199d5a2a63bSopenharmony_ci        return ERR_INVALID_PARAM;
200d5a2a63bSopenharmony_ci    }
201d5a2a63bSopenharmony_ci    if (!ConvertCodecFormatToAudioFormat(config.audioFormat, &(attrs.format))) {
202d5a2a63bSopenharmony_ci        MEDIA_ERR_LOG("not support audioFormat:%d", config.audioFormat);
203d5a2a63bSopenharmony_ci        return ERR_INVALID_PARAM;
204d5a2a63bSopenharmony_ci    }
205d5a2a63bSopenharmony_ci    attrs.sampleRate = config.sampleRate;
206d5a2a63bSopenharmony_ci    attrs.channelCount = config.channelCount;
207d5a2a63bSopenharmony_ci    attrs.interleaved = config.interleaved;
208d5a2a63bSopenharmony_ci    int32_t ret = audioAdapter_->CreateCapture(audioAdapter_, &desc, &attrs, &audioCapture_);
209d5a2a63bSopenharmony_ci    if (ret != SUCCESS || audioCapture_ == nullptr) {
210d5a2a63bSopenharmony_ci        MEDIA_ERR_LOG("CreateCapture failed:0x%x", ret);
211d5a2a63bSopenharmony_ci        return ret;
212d5a2a63bSopenharmony_ci    }
213d5a2a63bSopenharmony_ci    initialized_ = true;
214d5a2a63bSopenharmony_ci    return SUCCESS;
215d5a2a63bSopenharmony_ci}
216d5a2a63bSopenharmony_ci
217d5a2a63bSopenharmony_ciint32_t AudioSource::SetInputDevice(uint32_t deviceId)
218d5a2a63bSopenharmony_ci{
219d5a2a63bSopenharmony_ci    (void)deviceId;
220d5a2a63bSopenharmony_ci    return SUCCESS;
221d5a2a63bSopenharmony_ci}
222d5a2a63bSopenharmony_ci
223d5a2a63bSopenharmony_ciint32_t AudioSource::GetCurrentDeviceId(uint32_t &deviceId)
224d5a2a63bSopenharmony_ci{
225d5a2a63bSopenharmony_ci    AUDIO_RETURN_VAL_IF_NULL(audioCapture_);
226d5a2a63bSopenharmony_ci    int32_t ret = audioCapture_->attr.GetCurrentChannelId(reinterpret_cast<AudioHandle>(audioCapture_), &deviceId);
227d5a2a63bSopenharmony_ci    if (ret != SUCCESS) {
228d5a2a63bSopenharmony_ci        MEDIA_ERR_LOG("GetCurrentChannelId failed:0x%x", ret);
229d5a2a63bSopenharmony_ci        return ret;
230d5a2a63bSopenharmony_ci    }
231d5a2a63bSopenharmony_ci    MEDIA_INFO_LOG("deviceId:0x%x", deviceId);
232d5a2a63bSopenharmony_ci    return SUCCESS;
233d5a2a63bSopenharmony_ci}
234d5a2a63bSopenharmony_ci
235d5a2a63bSopenharmony_ciint32_t AudioSource::Start()
236d5a2a63bSopenharmony_ci{
237d5a2a63bSopenharmony_ci    int32_t ret;
238d5a2a63bSopenharmony_ci    if ((ret = InitCheck()) != SUCCESS) {
239d5a2a63bSopenharmony_ci        return ret;
240d5a2a63bSopenharmony_ci    }
241d5a2a63bSopenharmony_ci
242d5a2a63bSopenharmony_ci    AUDIO_RETURN_VAL_IF_NULL(audioCapture_);
243d5a2a63bSopenharmony_ci    ret = audioCapture_->control.Start(reinterpret_cast<AudioHandle>(audioCapture_));
244d5a2a63bSopenharmony_ci    if (ret != SUCCESS) {
245d5a2a63bSopenharmony_ci        MEDIA_ERR_LOG("audioCapture_ Start failed:0x%x", ret);
246d5a2a63bSopenharmony_ci        return ret;
247d5a2a63bSopenharmony_ci    }
248d5a2a63bSopenharmony_ci    started_ = true;
249d5a2a63bSopenharmony_ci    return SUCCESS;
250d5a2a63bSopenharmony_ci}
251d5a2a63bSopenharmony_ci
252d5a2a63bSopenharmony_ciint32_t AudioSource::ReadFrame(AudioFrame &frame, bool isBlockingRead)
253d5a2a63bSopenharmony_ci{
254d5a2a63bSopenharmony_ci    if (!started_) {
255d5a2a63bSopenharmony_ci        MEDIA_ERR_LOG("AudioSource not Start");
256d5a2a63bSopenharmony_ci        return ERR_ILLEGAL_STATE;
257d5a2a63bSopenharmony_ci    }
258d5a2a63bSopenharmony_ci    AUDIO_RETURN_VAL_IF_NULL(audioCapture_);
259d5a2a63bSopenharmony_ci    uint64_t readlen = ERR_INVALID_READ;
260d5a2a63bSopenharmony_ci    int32_t ret = audioCapture_->CaptureFrame(audioCapture_, frame.buffer, frame.bufferLen, &readlen);
261d5a2a63bSopenharmony_ci    if (ret != SUCCESS) {
262d5a2a63bSopenharmony_ci        MEDIA_ERR_LOG("audioCapture_::CaptureFrame failed:0x%x", ret);
263d5a2a63bSopenharmony_ci        return ERR_INVALID_READ;
264d5a2a63bSopenharmony_ci    }
265d5a2a63bSopenharmony_ci    ret = audioCapture_->GetCapturePosition(audioCapture_, &frame.frames, &frame.time);
266d5a2a63bSopenharmony_ci    if (ret != SUCCESS) {
267d5a2a63bSopenharmony_ci        MEDIA_ERR_LOG("audioCapture_::GetCapturePosition failed:0x%x", ret);
268d5a2a63bSopenharmony_ci        return ERR_INVALID_READ;
269d5a2a63bSopenharmony_ci    }
270d5a2a63bSopenharmony_ci    return readlen;
271d5a2a63bSopenharmony_ci}
272d5a2a63bSopenharmony_ci
273d5a2a63bSopenharmony_ciint32_t AudioSource::Stop()
274d5a2a63bSopenharmony_ci{
275d5a2a63bSopenharmony_ci    MEDIA_INFO_LOG("AudioSource::Stop");
276d5a2a63bSopenharmony_ci    if (!started_) {
277d5a2a63bSopenharmony_ci        MEDIA_ERR_LOG("AudioSource not Start");
278d5a2a63bSopenharmony_ci        return ERR_ILLEGAL_STATE;
279d5a2a63bSopenharmony_ci    }
280d5a2a63bSopenharmony_ci
281d5a2a63bSopenharmony_ci    AUDIO_RETURN_VAL_IF_NULL(audioCapture_);
282d5a2a63bSopenharmony_ci    int32_t ret = audioCapture_->control.Stop(reinterpret_cast<AudioHandle>(audioCapture_));
283d5a2a63bSopenharmony_ci    if (ret != SUCCESS) {
284d5a2a63bSopenharmony_ci        MEDIA_ERR_LOG("Stop failed:0x%x", ret);
285d5a2a63bSopenharmony_ci        return ret;
286d5a2a63bSopenharmony_ci    }
287d5a2a63bSopenharmony_ci    started_ = false;
288d5a2a63bSopenharmony_ci    return SUCCESS;
289d5a2a63bSopenharmony_ci}
290d5a2a63bSopenharmony_ci
291d5a2a63bSopenharmony_ciint32_t AudioSource::Release()
292d5a2a63bSopenharmony_ci{
293d5a2a63bSopenharmony_ci    int32_t ret;
294d5a2a63bSopenharmony_ci    if ((ret = InitCheck()) != SUCCESS) {
295d5a2a63bSopenharmony_ci        return ret;
296d5a2a63bSopenharmony_ci    }
297d5a2a63bSopenharmony_ci    if (audioCapture_) {
298d5a2a63bSopenharmony_ci        audioAdapter_->DestroyCapture(audioAdapter_, audioCapture_);
299d5a2a63bSopenharmony_ci        audioCapture_ = nullptr;
300d5a2a63bSopenharmony_ci    }
301d5a2a63bSopenharmony_ci    initialized_ = false;
302d5a2a63bSopenharmony_ci    MEDIA_INFO_LOG("AudioSource Released");
303d5a2a63bSopenharmony_ci    return SUCCESS;
304d5a2a63bSopenharmony_ci}
305d5a2a63bSopenharmony_ci}  // namespace Audio
306d5a2a63bSopenharmony_ci}  // namespace OHOS
307