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