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
20 namespace OHOS {
21 namespace Audio {
22 using namespace OHOS::Media;
23
24 constexpr uint32_t AUDIO_READ_STREAM_TIME_OUT_MS = 1000; /* 1S */
25
26 constexpr uint32_t AUDIO_CHANNEL_MONO = 1;
27 constexpr uint32_t AUDIO_CHANNEL_STEREO = 2;
28
AudioEncoder()29 AudioEncoder::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
~AudioEncoder()41 AudioEncoder::~AudioEncoder()
42 {
43 if (initialized_) {
44 Release();
45 }
46 MEDIA_INFO_LOG("AudioEncoder dtor");
47 }
48
IsAudioCodecFormatSupported(AudioCodecFormat format)49 static 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
IsAudioSampleRateSupported(AudioCodecFormat format,uint32_t sampleRate)58 static 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
GetMimeFromAudioCodecFormat(AudioCodecFormat format)69 static 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
GetProfileFromAudioCodecFormat(AudioCodecFormat format)90 static 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
ConvertSoundMode(uint32_t channelCount)109 static 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
InitAudioEncoderAttr(const AudioEncodeConfig & config)122 int32_t AudioEncoder::InitAudioEncoderAttr(const AudioEncodeConfig &config)
123 {
124 if (!IsAudioCodecFormatSupported(config.audioFormat)) {
125 MEDIA_ERR_LOG("audioFormat:0x%x is not support", config.audioFormat);
126 return ERR_INVALID_PARAM;
127 }
128 if (!IsAudioSampleRateSupported(config.audioFormat, config.sampleRate)) {
129 MEDIA_ERR_LOG("audioFormat:%d is not support sampleRate:%d", config.audioFormat, config.sampleRate);
130 return ERR_INVALID_PARAM;
131 }
132 uint32_t paramIndex = 0;
133 domainKind_ = AUDIO_ENCODER;
134 encAttr_[paramIndex].key = KEY_CODEC_TYPE;
135 encAttr_[paramIndex].val = &domainKind_;
136 encAttr_[paramIndex].size = sizeof(CodecType);
137 paramIndex++;
138 codecMime_ = GetMimeFromAudioCodecFormat(config.audioFormat);
139 encAttr_[paramIndex].key = KEY_MIMETYPE;
140 encAttr_[paramIndex].val = &codecMime_;
141 encAttr_[paramIndex].size = sizeof(AvCodecMime);
142 paramIndex++;
143 profile_ = GetProfileFromAudioCodecFormat(config.audioFormat);
144 encAttr_[paramIndex].key = KEY_AUDIO_PROFILE;
145 encAttr_[paramIndex].val = &profile_;
146 encAttr_[paramIndex].size = sizeof(Profile);
147 paramIndex++;
148 sampleRate_ = config.sampleRate;
149 encAttr_[paramIndex].key = KEY_AUDIO_SAMPLE_RATE;
150 encAttr_[paramIndex].val = &sampleRate_;
151 encAttr_[paramIndex].size = sizeof(uint32_t);
152 paramIndex++;
153 bitRate_ = config.bitRate;
154 encAttr_[paramIndex].key = KEY_BITRATE;
155 encAttr_[paramIndex].val = &bitRate_;
156 encAttr_[paramIndex].size = sizeof(uint32_t);
157 paramIndex++;
158 soundMode_ = ConvertSoundMode(config.channelCount);
159 encAttr_[paramIndex].key = KEY_AUDIO_SOUND_MODE;
160 encAttr_[paramIndex].val = &soundMode_;
161 encAttr_[paramIndex].size = sizeof(AudioSoundMode);
162 paramIndex++;
163 ptNumPerFrm_ = AUDIO_POINT_NUM;
164 encAttr_[paramIndex].key = KEY_AUDIO_POINTS_PER_FRAME;
165 encAttr_[paramIndex].val = &ptNumPerFrm_;
166 encAttr_[paramIndex].size = sizeof(uint32_t);
167 paramIndex++;
168 bufSize_ = AUDIO_FRAME_NUM_IN_BUF;
169 encAttr_[paramIndex].key = KEY_BUFFERSIZE;
170 encAttr_[paramIndex].val = &bufSize_;
171 encAttr_[paramIndex].size = sizeof(uint32_t);
172 return SUCCESS;
173 }
174
Initialize(const AudioEncodeConfig & config)175 int32_t AudioEncoder::Initialize(const AudioEncodeConfig &config)
176 {
177 int32_t ret = InitAudioEncoderAttr(config);
178 if (ret != SUCCESS) {
179 MEDIA_ERR_LOG("InitAudioEncoderAttr failed:%d", ret);
180 return ret;
181 }
182 ret = CodecCreateByType(domainKind_, codecMime_, &encHandle_);
183 if (ret != SUCCESS) {
184 MEDIA_ERR_LOG("CodecCreateByType failed:0x%x", ret);
185 return ret;
186 }
187 ret = CodecSetParameter(encHandle_, encAttr_, AUDIO_ENC_PARAM_NUM);
188 if (ret != SUCCESS) {
189 CodecDestroy(encHandle_);
190 MEDIA_ERR_LOG("CodecSetParameter failed:0x%x", ret);
191 return ret;
192 }
193 initialized_ = true;
194 return SUCCESS;
195 }
196
BindSource(uint32_t deviceId)197 int32_t AudioEncoder::BindSource(uint32_t deviceId)
198 {
199 Param params[1];
200 (void)memset_s(params, sizeof(params), 0x00, sizeof(params));
201 params[0].key = KEY_DEVICE_ID;
202 params[0].val = reinterpret_cast<void *>(&deviceId);
203 params[0].size = sizeof(uint32_t);
204 int32_t ret = CodecSetParameter(encHandle_, params, sizeof(params) / sizeof(params[0]));
205 if (ret != SUCCESS) {
206 MEDIA_ERR_LOG("CodecSetDevice:0x%x", ret);
207 return ret;
208 }
209 return SUCCESS;
210 }
211
GetMute(bool & muted)212 int32_t AudioEncoder::GetMute(bool &muted)
213 {
214 (void)muted;
215 return ERR_UNKNOWN;
216 }
217
SetMute(bool muted)218 int32_t AudioEncoder::SetMute(bool muted)
219 {
220 (void)muted;
221 return ERR_UNKNOWN;
222 }
223
Start()224 int32_t AudioEncoder::Start()
225 {
226 if (!initialized_) {
227 MEDIA_ERR_LOG("not initialized");
228 return ERR_ILLEGAL_STATE;
229 }
230 int32_t ret = CodecStart(encHandle_);
231 if (ret != SUCCESS) {
232 MEDIA_ERR_LOG("CodecStart failed:0x%x", ret);
233 return ret;
234 }
235 started_ = true;
236 return ret;
237 }
238
ReadStream(AudioStream & stream,bool isBlockingRead)239 int32_t AudioEncoder::ReadStream(AudioStream &stream, bool isBlockingRead)
240 {
241 if (!started_) {
242 MEDIA_ERR_LOG("Codec not Started");
243 return ERR_INVALID_READ;
244 }
245 if (stream.buffer == nullptr || stream.bufferLen == 0) {
246 MEDIA_ERR_LOG("stream.buffer is nullptr");
247 return ERR_INVALID_READ;
248 }
249 uint32_t timeoutMs;
250 if (isBlockingRead) {
251 timeoutMs = AUDIO_READ_STREAM_TIME_OUT_MS;
252 } else {
253 timeoutMs = 0;
254 }
255 AudioBufferInfo outInfo;
256 int32_t ret = CodecDequeueOutput(encHandle_, timeoutMs, nullptr, (CodecBuffer *)&outInfo);
257 if (ret != SUCCESS && outInfo.info.buffer[0].buf == 0) {
258 MEDIA_ERR_LOG("CodecDequeueOutput failed:0x%x", ret);
259 return ERR_INVALID_READ;
260 }
261 int32_t readLen = 0;
262 errno_t retCopy = memcpy_s(stream.buffer, stream.bufferLen, (void *)outInfo.info.buffer[0].buf,
263 outInfo.info.buffer[0].length);
264 if (retCopy != EOK) {
265 MEDIA_ERR_LOG("memcpy_s failed, timeStamp:%lld, retCopy:0x%x", outInfo.info.timeStamp, retCopy);
266 return ERR_INVALID_OPERATION;
267 } else {
268 readLen = outInfo.info.buffer[0].length;
269 }
270 stream.timeStamp = outInfo.info.timeStamp;
271 (void)CodecQueueOutput(encHandle_, (CodecBuffer *)&outInfo, timeoutMs, -1);
272 return readLen;
273 }
274
Stop()275 int32_t AudioEncoder::Stop()
276 {
277 MEDIA_DEBUG_LOG("AudioEncoder::Stop");
278 if (!started_) {
279 MEDIA_ERR_LOG("Codec not Start");
280 }
281 return CodecStop(encHandle_);
282 }
283
Release()284 int32_t AudioEncoder::Release()
285 {
286 MEDIA_DEBUG_LOG("AudioEncoder::Release");
287 if (!initialized_) {
288 MEDIA_ERR_LOG("Codec not initialized");
289 }
290 if (encHandle_ != nullptr) {
291 CodecDestroy(encHandle_);
292 encHandle_ = nullptr;
293 }
294 initialized_ = false;
295 return SUCCESS;
296 }
297 } // namespace Audio
298 } // namespace OHOS
299