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 
setEncAttrValue(const AudioEncodeConfig & config)122 void 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 
InitAudioEncoderAttr(const AudioEncodeConfig & config)166 int32_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 
Initialize(const AudioEncodeConfig & config)181 int32_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 
BindSource(uint32_t deviceId)203 int32_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 
GetMute(bool & muted)218 int32_t AudioEncoder::GetMute(bool &muted)
219 {
220     (void)muted;
221     return ERR_UNKNOWN;
222 }
223 
SetMute(bool muted)224 int32_t AudioEncoder::SetMute(bool muted)
225 {
226     (void)muted;
227     return ERR_UNKNOWN;
228 }
229 
Start()230 int32_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 
ReadStream(AudioStream & stream,bool isBlockingRead)245 int32_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 
Stop()281 int32_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 
Release()290 int32_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