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