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