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_encoder.h"
17d5a2a63bSopenharmony_ci#include "media_log.h"
18d5a2a63bSopenharmony_ci#include "securec.h"
19d5a2a63bSopenharmony_ci
20d5a2a63bSopenharmony_cinamespace OHOS {
21d5a2a63bSopenharmony_cinamespace Audio {
22d5a2a63bSopenharmony_ciusing namespace OHOS::Media;
23d5a2a63bSopenharmony_ci
24d5a2a63bSopenharmony_ciconstexpr uint32_t AUDIO_READ_STREAM_TIME_OUT_MS = 1000; /* 1S */
25d5a2a63bSopenharmony_ci
26d5a2a63bSopenharmony_ciconstexpr uint32_t AUDIO_CHANNEL_MONO = 1;
27d5a2a63bSopenharmony_ciconstexpr uint32_t AUDIO_CHANNEL_STEREO = 2;
28d5a2a63bSopenharmony_ci
29d5a2a63bSopenharmony_ciAudioEncoder::AudioEncoder()
30d5a2a63bSopenharmony_ci    :initialized_(false),
31d5a2a63bSopenharmony_ci    encHandle_(nullptr),
32d5a2a63bSopenharmony_ci    started_(false)
33d5a2a63bSopenharmony_ci{
34d5a2a63bSopenharmony_ci    for (int i = 0; i < AUDIO_ENC_PARAM_NUM; i++) {
35d5a2a63bSopenharmony_ci        encAttr_[i] = {};
36d5a2a63bSopenharmony_ci    }
37d5a2a63bSopenharmony_ci    CodecInit();
38d5a2a63bSopenharmony_ci    MEDIA_INFO_LOG("AudioEncoder ctor");
39d5a2a63bSopenharmony_ci}
40d5a2a63bSopenharmony_ci
41d5a2a63bSopenharmony_ciAudioEncoder::~AudioEncoder()
42d5a2a63bSopenharmony_ci{
43d5a2a63bSopenharmony_ci    if (initialized_) {
44d5a2a63bSopenharmony_ci        Release();
45d5a2a63bSopenharmony_ci    }
46d5a2a63bSopenharmony_ci    MEDIA_INFO_LOG("AudioEncoder dtor");
47d5a2a63bSopenharmony_ci}
48d5a2a63bSopenharmony_ci
49d5a2a63bSopenharmony_cistatic bool IsAudioCodecFormatSupported(AudioCodecFormat format)
50d5a2a63bSopenharmony_ci{
51d5a2a63bSopenharmony_ci    if ((format < AAC_LC) || (format > G726)) {
52d5a2a63bSopenharmony_ci        MEDIA_ERR_LOG("Invalid format:%d", format);
53d5a2a63bSopenharmony_ci        return false;
54d5a2a63bSopenharmony_ci    }
55d5a2a63bSopenharmony_ci    return true;
56d5a2a63bSopenharmony_ci}
57d5a2a63bSopenharmony_ci
58d5a2a63bSopenharmony_cistatic bool IsAudioSampleRateSupported(AudioCodecFormat format, uint32_t sampleRate)
59d5a2a63bSopenharmony_ci{
60d5a2a63bSopenharmony_ci    if (format == G711A || format == G711U || format == G726) {
61d5a2a63bSopenharmony_ci        if (sampleRate != 8000) { // 8000 G711/G726 only support 8kHz
62d5a2a63bSopenharmony_ci            MEDIA_ERR_LOG("Invalid sampleRate:%d, G711/G726 only support 8kHz", sampleRate);
63d5a2a63bSopenharmony_ci            return false;
64d5a2a63bSopenharmony_ci        }
65d5a2a63bSopenharmony_ci    }
66d5a2a63bSopenharmony_ci    return true;
67d5a2a63bSopenharmony_ci}
68d5a2a63bSopenharmony_ci
69d5a2a63bSopenharmony_cistatic AvCodecMime GetMimeFromAudioCodecFormat(AudioCodecFormat format)
70d5a2a63bSopenharmony_ci{
71d5a2a63bSopenharmony_ci    switch (format) {
72d5a2a63bSopenharmony_ci        case AAC_LC:
73d5a2a63bSopenharmony_ci        case AAC_HE_V1:
74d5a2a63bSopenharmony_ci        case AAC_HE_V2:
75d5a2a63bSopenharmony_ci        case AAC_LD:
76d5a2a63bSopenharmony_ci        case AAC_ELD:
77d5a2a63bSopenharmony_ci            return MEDIA_MIMETYPE_AUDIO_AAC;
78d5a2a63bSopenharmony_ci        case G711A:
79d5a2a63bSopenharmony_ci            return MEDIA_MIMETYPE_AUDIO_G711A;
80d5a2a63bSopenharmony_ci        case G711U:
81d5a2a63bSopenharmony_ci            return MEDIA_MIMETYPE_AUDIO_G711U;
82d5a2a63bSopenharmony_ci        case G726:
83d5a2a63bSopenharmony_ci            return MEDIA_MIMETYPE_AUDIO_G726;
84d5a2a63bSopenharmony_ci        default:
85d5a2a63bSopenharmony_ci            MEDIA_ERR_LOG("Invalid format:0x%x", format);
86d5a2a63bSopenharmony_ci            return MEDIA_MIMETYPE_INVALID;
87d5a2a63bSopenharmony_ci    }
88d5a2a63bSopenharmony_ci}
89d5a2a63bSopenharmony_ci
90d5a2a63bSopenharmony_cistatic Profile GetProfileFromAudioCodecFormat(AudioCodecFormat format)
91d5a2a63bSopenharmony_ci{
92d5a2a63bSopenharmony_ci    switch (format) {
93d5a2a63bSopenharmony_ci        case AAC_LC:
94d5a2a63bSopenharmony_ci            return AAC_LC_PROFILE;
95d5a2a63bSopenharmony_ci        case AAC_HE_V1:
96d5a2a63bSopenharmony_ci            return AAC_HE_V1_PROFILE;
97d5a2a63bSopenharmony_ci        case AAC_HE_V2:
98d5a2a63bSopenharmony_ci            return AAC_HE_V2_PROFILE;
99d5a2a63bSopenharmony_ci        case AAC_LD:
100d5a2a63bSopenharmony_ci            return AAC_LD_PROFILE;
101d5a2a63bSopenharmony_ci        case AAC_ELD:
102d5a2a63bSopenharmony_ci            return AAC_ELD_PROFILE;
103d5a2a63bSopenharmony_ci        default:
104d5a2a63bSopenharmony_ci            MEDIA_ERR_LOG("Invalid format: 0x%x", format);
105d5a2a63bSopenharmony_ci            return AAC_LC_PROFILE;
106d5a2a63bSopenharmony_ci    }
107d5a2a63bSopenharmony_ci}
108d5a2a63bSopenharmony_ci
109d5a2a63bSopenharmony_cistatic AudioSoundMode ConvertSoundMode(uint32_t channelCount)
110d5a2a63bSopenharmony_ci{
111d5a2a63bSopenharmony_ci    switch (channelCount) {
112d5a2a63bSopenharmony_ci        case AUDIO_CHANNEL_MONO:
113d5a2a63bSopenharmony_ci            return AUD_SOUND_MODE_MONO;
114d5a2a63bSopenharmony_ci        case AUDIO_CHANNEL_STEREO:
115d5a2a63bSopenharmony_ci            return AUD_SOUND_MODE_STEREO;
116d5a2a63bSopenharmony_ci        default:
117d5a2a63bSopenharmony_ci            MEDIA_ERR_LOG("Invalid soundMode:%u", channelCount);
118d5a2a63bSopenharmony_ci            return AUD_SOUND_MODE_MONO;
119d5a2a63bSopenharmony_ci    }
120d5a2a63bSopenharmony_ci}
121d5a2a63bSopenharmony_ci
122d5a2a63bSopenharmony_civoid AudioEncoder::setEncAttrValue(const AudioEncodeConfig &config)
123d5a2a63bSopenharmony_ci{
124d5a2a63bSopenharmony_ci    uint32_t paramIndex = 0;
125d5a2a63bSopenharmony_ci    domainKind_ = AUDIO_ENCODER;
126d5a2a63bSopenharmony_ci    encAttr_[paramIndex].key = KEY_CODEC_TYPE;
127d5a2a63bSopenharmony_ci    encAttr_[paramIndex].val = &domainKind_;
128d5a2a63bSopenharmony_ci    encAttr_[paramIndex].size = sizeof(CodecType);
129d5a2a63bSopenharmony_ci    paramIndex++;
130d5a2a63bSopenharmony_ci    codecMime_ = GetMimeFromAudioCodecFormat(config.audioFormat);
131d5a2a63bSopenharmony_ci    encAttr_[paramIndex].key = KEY_MIMETYPE;
132d5a2a63bSopenharmony_ci    encAttr_[paramIndex].val = &codecMime_;
133d5a2a63bSopenharmony_ci    encAttr_[paramIndex].size = sizeof(AvCodecMime);
134d5a2a63bSopenharmony_ci    paramIndex++;
135d5a2a63bSopenharmony_ci    profile_ = GetProfileFromAudioCodecFormat(config.audioFormat);
136d5a2a63bSopenharmony_ci    encAttr_[paramIndex].key = KEY_AUDIO_PROFILE;
137d5a2a63bSopenharmony_ci    encAttr_[paramIndex].val = &profile_;
138d5a2a63bSopenharmony_ci    encAttr_[paramIndex].size = sizeof(Profile);
139d5a2a63bSopenharmony_ci    paramIndex++;
140d5a2a63bSopenharmony_ci    sampleRate_ = config.sampleRate;
141d5a2a63bSopenharmony_ci    encAttr_[paramIndex].key = KEY_AUDIO_SAMPLE_RATE;
142d5a2a63bSopenharmony_ci    encAttr_[paramIndex].val = &sampleRate_;
143d5a2a63bSopenharmony_ci    encAttr_[paramIndex].size = sizeof(uint32_t);
144d5a2a63bSopenharmony_ci    paramIndex++;
145d5a2a63bSopenharmony_ci    bitRate_ = config.bitRate;
146d5a2a63bSopenharmony_ci    encAttr_[paramIndex].key = KEY_BITRATE;
147d5a2a63bSopenharmony_ci    encAttr_[paramIndex].val = &bitRate_;
148d5a2a63bSopenharmony_ci    encAttr_[paramIndex].size = sizeof(uint32_t);
149d5a2a63bSopenharmony_ci    paramIndex++;
150d5a2a63bSopenharmony_ci    soundMode_ = ConvertSoundMode(config.channelCount);
151d5a2a63bSopenharmony_ci    encAttr_[paramIndex].key = KEY_AUDIO_SOUND_MODE;
152d5a2a63bSopenharmony_ci    encAttr_[paramIndex].val = &soundMode_;
153d5a2a63bSopenharmony_ci    encAttr_[paramIndex].size = sizeof(AudioSoundMode);
154d5a2a63bSopenharmony_ci    paramIndex++;
155d5a2a63bSopenharmony_ci    ptNumPerFrm_ = AUDIO_POINT_NUM;
156d5a2a63bSopenharmony_ci    encAttr_[paramIndex].key = KEY_AUDIO_POINTS_PER_FRAME;
157d5a2a63bSopenharmony_ci    encAttr_[paramIndex].val = &ptNumPerFrm_;
158d5a2a63bSopenharmony_ci    encAttr_[paramIndex].size = sizeof(uint32_t);
159d5a2a63bSopenharmony_ci    paramIndex++;
160d5a2a63bSopenharmony_ci    bufSize_ = AUDIO_FRAME_NUM_IN_BUF;
161d5a2a63bSopenharmony_ci    encAttr_[paramIndex].key = KEY_BUFFERSIZE;
162d5a2a63bSopenharmony_ci    encAttr_[paramIndex].val = &bufSize_;
163d5a2a63bSopenharmony_ci    encAttr_[paramIndex].size = sizeof(uint32_t);
164d5a2a63bSopenharmony_ci}
165d5a2a63bSopenharmony_ci
166d5a2a63bSopenharmony_ciint32_t AudioEncoder::InitAudioEncoderAttr(const AudioEncodeConfig &config)
167d5a2a63bSopenharmony_ci{
168d5a2a63bSopenharmony_ci    if (!IsAudioCodecFormatSupported(config.audioFormat)) {
169d5a2a63bSopenharmony_ci        MEDIA_ERR_LOG("audioFormat:0x%x is not support", config.audioFormat);
170d5a2a63bSopenharmony_ci        return ERR_INVALID_PARAM;
171d5a2a63bSopenharmony_ci    }
172d5a2a63bSopenharmony_ci    if (!IsAudioSampleRateSupported(config.audioFormat, config.sampleRate)) {
173d5a2a63bSopenharmony_ci        MEDIA_ERR_LOG("audioFormat:%d is not support sampleRate:%d", config.audioFormat, config.sampleRate);
174d5a2a63bSopenharmony_ci        return ERR_INVALID_PARAM;
175d5a2a63bSopenharmony_ci    }
176d5a2a63bSopenharmony_ci    setEncAttrValue(config);
177d5a2a63bSopenharmony_ci
178d5a2a63bSopenharmony_ci    return SUCCESS;
179d5a2a63bSopenharmony_ci}
180d5a2a63bSopenharmony_ci
181d5a2a63bSopenharmony_ciint32_t AudioEncoder::Initialize(const AudioEncodeConfig &config)
182d5a2a63bSopenharmony_ci{
183d5a2a63bSopenharmony_ci    int32_t ret = InitAudioEncoderAttr(config);
184d5a2a63bSopenharmony_ci    if (ret != SUCCESS) {
185d5a2a63bSopenharmony_ci        MEDIA_ERR_LOG("InitAudioEncoderAttr failed:%d", ret);
186d5a2a63bSopenharmony_ci        return ret;
187d5a2a63bSopenharmony_ci    }
188d5a2a63bSopenharmony_ci    ret = CodecCreateByType(domainKind_, codecMime_, &encHandle_);
189d5a2a63bSopenharmony_ci    if (ret != SUCCESS) {
190d5a2a63bSopenharmony_ci        MEDIA_ERR_LOG("CodecCreateByType failed:0x%x", ret);
191d5a2a63bSopenharmony_ci        return ret;
192d5a2a63bSopenharmony_ci    }
193d5a2a63bSopenharmony_ci    ret = CodecSetParameter(encHandle_, encAttr_, AUDIO_ENC_PARAM_NUM);
194d5a2a63bSopenharmony_ci    if (ret != SUCCESS) {
195d5a2a63bSopenharmony_ci        CodecDestroy(encHandle_);
196d5a2a63bSopenharmony_ci        MEDIA_ERR_LOG("CodecSetParameter failed:0x%x", ret);
197d5a2a63bSopenharmony_ci        return ret;
198d5a2a63bSopenharmony_ci    }
199d5a2a63bSopenharmony_ci    initialized_ = true;
200d5a2a63bSopenharmony_ci    return SUCCESS;
201d5a2a63bSopenharmony_ci}
202d5a2a63bSopenharmony_ci
203d5a2a63bSopenharmony_ciint32_t AudioEncoder::BindSource(uint32_t deviceId)
204d5a2a63bSopenharmony_ci{
205d5a2a63bSopenharmony_ci    Param params[1];
206d5a2a63bSopenharmony_ci    (void)memset_s(params, sizeof(params), 0x00, sizeof(params));
207d5a2a63bSopenharmony_ci    params[0].key = KEY_DEVICE_ID;
208d5a2a63bSopenharmony_ci    params[0].val = reinterpret_cast<void *>(&deviceId);
209d5a2a63bSopenharmony_ci    params[0].size = sizeof(uint32_t);
210d5a2a63bSopenharmony_ci    int32_t ret = CodecSetParameter(encHandle_, params, sizeof(params) / sizeof(params[0]));
211d5a2a63bSopenharmony_ci    if (ret != SUCCESS) {
212d5a2a63bSopenharmony_ci        MEDIA_ERR_LOG("CodecSetDevice:0x%x", ret);
213d5a2a63bSopenharmony_ci        return ret;
214d5a2a63bSopenharmony_ci    }
215d5a2a63bSopenharmony_ci    return SUCCESS;
216d5a2a63bSopenharmony_ci}
217d5a2a63bSopenharmony_ci
218d5a2a63bSopenharmony_ciint32_t AudioEncoder::GetMute(bool &muted)
219d5a2a63bSopenharmony_ci{
220d5a2a63bSopenharmony_ci    (void)muted;
221d5a2a63bSopenharmony_ci    return ERR_UNKNOWN;
222d5a2a63bSopenharmony_ci}
223d5a2a63bSopenharmony_ci
224d5a2a63bSopenharmony_ciint32_t AudioEncoder::SetMute(bool muted)
225d5a2a63bSopenharmony_ci{
226d5a2a63bSopenharmony_ci    (void)muted;
227d5a2a63bSopenharmony_ci    return ERR_UNKNOWN;
228d5a2a63bSopenharmony_ci}
229d5a2a63bSopenharmony_ci
230d5a2a63bSopenharmony_ciint32_t AudioEncoder::Start()
231d5a2a63bSopenharmony_ci{
232d5a2a63bSopenharmony_ci    if (!initialized_) {
233d5a2a63bSopenharmony_ci        MEDIA_ERR_LOG("not initialized");
234d5a2a63bSopenharmony_ci        return ERR_ILLEGAL_STATE;
235d5a2a63bSopenharmony_ci    }
236d5a2a63bSopenharmony_ci    int32_t ret = CodecStart(encHandle_);
237d5a2a63bSopenharmony_ci    if (ret != SUCCESS) {
238d5a2a63bSopenharmony_ci        MEDIA_ERR_LOG("CodecStart failed:0x%x", ret);
239d5a2a63bSopenharmony_ci        return ret;
240d5a2a63bSopenharmony_ci    }
241d5a2a63bSopenharmony_ci    started_ = true;
242d5a2a63bSopenharmony_ci    return ret;
243d5a2a63bSopenharmony_ci}
244d5a2a63bSopenharmony_ci
245d5a2a63bSopenharmony_ciint32_t AudioEncoder::ReadStream(AudioStream &stream, bool isBlockingRead)
246d5a2a63bSopenharmony_ci{
247d5a2a63bSopenharmony_ci    if (!started_) {
248d5a2a63bSopenharmony_ci        MEDIA_ERR_LOG("Codec not Started");
249d5a2a63bSopenharmony_ci        return ERR_INVALID_READ;
250d5a2a63bSopenharmony_ci    }
251d5a2a63bSopenharmony_ci    if (stream.buffer == nullptr || stream.bufferLen == 0) {
252d5a2a63bSopenharmony_ci        MEDIA_ERR_LOG("stream.buffer is nullptr");
253d5a2a63bSopenharmony_ci        return ERR_INVALID_READ;
254d5a2a63bSopenharmony_ci    }
255d5a2a63bSopenharmony_ci    uint32_t timeoutMs;
256d5a2a63bSopenharmony_ci    if (isBlockingRead) {
257d5a2a63bSopenharmony_ci        timeoutMs = AUDIO_READ_STREAM_TIME_OUT_MS;
258d5a2a63bSopenharmony_ci    } else {
259d5a2a63bSopenharmony_ci        timeoutMs = 0;
260d5a2a63bSopenharmony_ci    }
261d5a2a63bSopenharmony_ci    AudioBufferInfo outInfo;
262d5a2a63bSopenharmony_ci    int32_t ret = CodecDequeueOutput(encHandle_, timeoutMs, nullptr, (CodecBuffer *)&outInfo);
263d5a2a63bSopenharmony_ci    if (ret != SUCCESS && outInfo.info.buffer[0].buf == 0) {
264d5a2a63bSopenharmony_ci        MEDIA_ERR_LOG("CodecDequeueOutput failed:0x%x", ret);
265d5a2a63bSopenharmony_ci        return ERR_INVALID_READ;
266d5a2a63bSopenharmony_ci    }
267d5a2a63bSopenharmony_ci    int32_t readLen = 0;
268d5a2a63bSopenharmony_ci    errno_t retCopy = memcpy_s(stream.buffer, stream.bufferLen, (void *)outInfo.info.buffer[0].buf,
269d5a2a63bSopenharmony_ci                               outInfo.info.buffer[0].length);
270d5a2a63bSopenharmony_ci    if (retCopy != EOK) {
271d5a2a63bSopenharmony_ci        MEDIA_ERR_LOG("memcpy_s failed, timeStamp:%lld, retCopy:0x%x", outInfo.info.timeStamp, retCopy);
272d5a2a63bSopenharmony_ci        return ERR_INVALID_OPERATION;
273d5a2a63bSopenharmony_ci    } else {
274d5a2a63bSopenharmony_ci        readLen = outInfo.info.buffer[0].length;
275d5a2a63bSopenharmony_ci    }
276d5a2a63bSopenharmony_ci    stream.timeStamp = outInfo.info.timeStamp;
277d5a2a63bSopenharmony_ci    (void)CodecQueueOutput(encHandle_, (CodecBuffer *)&outInfo, timeoutMs, -1);
278d5a2a63bSopenharmony_ci    return readLen;
279d5a2a63bSopenharmony_ci}
280d5a2a63bSopenharmony_ci
281d5a2a63bSopenharmony_ciint32_t AudioEncoder::Stop()
282d5a2a63bSopenharmony_ci{
283d5a2a63bSopenharmony_ci    MEDIA_DEBUG_LOG("AudioEncoder::Stop");
284d5a2a63bSopenharmony_ci    if (!started_) {
285d5a2a63bSopenharmony_ci        MEDIA_ERR_LOG("Codec not Start");
286d5a2a63bSopenharmony_ci    }
287d5a2a63bSopenharmony_ci    return CodecStop(encHandle_);
288d5a2a63bSopenharmony_ci}
289d5a2a63bSopenharmony_ci
290d5a2a63bSopenharmony_ciint32_t AudioEncoder::Release()
291d5a2a63bSopenharmony_ci{
292d5a2a63bSopenharmony_ci    MEDIA_DEBUG_LOG("AudioEncoder::Release");
293d5a2a63bSopenharmony_ci    if (!initialized_) {
294d5a2a63bSopenharmony_ci        MEDIA_ERR_LOG("Codec not initialized");
295d5a2a63bSopenharmony_ci    }
296d5a2a63bSopenharmony_ci    if (encHandle_ != nullptr) {
297d5a2a63bSopenharmony_ci        CodecDestroy(encHandle_);
298d5a2a63bSopenharmony_ci        encHandle_ = nullptr;
299d5a2a63bSopenharmony_ci    }
300d5a2a63bSopenharmony_ci    initialized_ = false;
301d5a2a63bSopenharmony_ci    return SUCCESS;
302d5a2a63bSopenharmony_ci}
303d5a2a63bSopenharmony_ci}  // namespace Audio
304d5a2a63bSopenharmony_ci}  // namespace OHOS
305