1 /*
2 * Copyright (c) 2024-2024 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 "external_window.h"
18 #include "native_avbuffer.h"
19 #include "sample_callback.h"
20 #include "camera_log.h"
21
22 namespace OHOS {
23 namespace CameraStandard {
24
~AudioEncoder()25 AudioEncoder::~AudioEncoder()
26 {
27 MEDIA_INFO_LOG("~AudioEncoder enter");
28 Release();
29 }
30
Create(const std::string & codecMime)31 int32_t AudioEncoder::Create(const std::string &codecMime)
32 {
33 std::lock_guard<std::mutex> lock(encoderMutex_);
34 encoder_ = OH_AudioCodec_CreateByMime(codecMime.data(), true);
35 CHECK_AND_RETURN_RET_LOG(encoder_ != nullptr, 1, "Create failed");
36 return 0;
37 }
38
Config()39 int32_t AudioEncoder::Config()
40 {
41 std::lock_guard<std::mutex> lock(encoderMutex_);
42 CHECK_AND_RETURN_RET_LOG(encoder_ != nullptr, 1, "Encoder is null");
43 std::unique_lock<std::mutex> contextLock(contextMutex_);
44 context_ = new CodecUserData;
45 // Configure audio encoder
46 int32_t ret = Configure();
47 CHECK_AND_RETURN_RET_LOG(ret == 0, 1, "Configure failed");
48 // SetCallback for audio encoder
49 ret = SetCallback(context_);
50 CHECK_AND_RETURN_RET_LOG(ret == 0, 1, "Set callback failed");
51 contextLock.unlock();
52 // Prepare audio encoder
53 ret = OH_AudioCodec_Prepare(encoder_);
54 CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, 1, "Prepare failed, ret: %{public}d", ret);
55
56 return 0;
57 }
58
Start()59 int32_t AudioEncoder::Start()
60 {
61 std::lock_guard<std::mutex> lock(encoderMutex_);
62 CHECK_AND_RETURN_RET_LOG(encoder_ != nullptr, 1, "Encoder is null");
63 int ret = OH_AudioCodec_Start(encoder_);
64 CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, 1, "Start failed, ret: %{public}d", ret);
65 isStarted_ = true;
66 return 0;
67 }
68
PushInputData(sptr<CodecAVBufferInfo> info)69 int32_t AudioEncoder::PushInputData(sptr<CodecAVBufferInfo> info)
70 {
71 std::lock_guard<std::mutex> lock(encoderMutex_);
72 CHECK_AND_RETURN_RET_LOG(encoder_ != nullptr, 1, "Encoder is null");
73 int32_t ret = AV_ERR_OK;
74 ret = OH_AVBuffer_SetBufferAttr(info->buffer, &info->attr);
75 CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, 1, "Set avbuffer attr failed, ret: %{public}d", ret);
76 ret = OH_AudioCodec_PushInputBuffer(encoder_, info->bufferIndex);
77 CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, 1, "Push input data failed, ret: %{public}d", ret);
78 return 0;
79 }
80
FreeOutputData(uint32_t bufferIndex)81 int32_t AudioEncoder::FreeOutputData(uint32_t bufferIndex)
82 {
83 std::lock_guard<std::mutex> lock(encoderMutex_);
84 CHECK_AND_RETURN_RET_LOG(encoder_ != nullptr, 1, "Encoder is null");
85 MEDIA_INFO_LOG("FreeOutputData bufferIndex: %{public}u", bufferIndex);
86 int32_t ret = OH_AudioCodec_FreeOutputBuffer(encoder_, bufferIndex);
87 CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, 1,
88 "Free output data failed, ret: %{public}d", ret);
89 return 0;
90 }
91
Stop()92 int32_t AudioEncoder::Stop()
93 {
94 CAMERA_SYNC_TRACE;
95 std::lock_guard<std::mutex> lock(encoderMutex_);
96 CHECK_AND_RETURN_RET_LOG(encoder_ != nullptr, 1, "Encoder is null");
97 int ret = OH_AudioCodec_Stop(encoder_);
98 CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, 1, "Stop failed, ret: %{public}d", ret);
99 isStarted_ = false;
100 return 0;
101 }
102
Release()103 int32_t AudioEncoder::Release()
104 {
105 CAMERA_SYNC_TRACE;
106 {
107 std::lock_guard<std::mutex> lock(encoderMutex_);
108 if (encoder_ != nullptr) {
109 OH_AudioCodec_Destroy(encoder_);
110 encoder_ = nullptr;
111 }
112 }
113 isStarted_ = false;
114 return 0;
115 }
116
RestartAudioCodec()117 void AudioEncoder::RestartAudioCodec()
118 {
119 CAMERA_SYNC_TRACE;
120 Release();
121 Create(OH_AVCODEC_MIMETYPE_AUDIO_AAC);
122 Config();
123 Start();
124 }
125
EnqueueBuffer(sptr<AudioRecord> audioRecord)126 bool AudioEncoder::EnqueueBuffer(sptr<AudioRecord> audioRecord)
127 {
128 CAMERA_SYNC_TRACE;
129 uint8_t* buffer = audioRecord->GetAudioBuffer();
130 CHECK_ERROR_RETURN_RET_LOG(buffer == nullptr, false, "Enqueue audio buffer is empty");
131 int enqueueRetryCount = 3;
132 while (enqueueRetryCount > 0) {
133 enqueueRetryCount--;
134 std::unique_lock<std::mutex> contextLock(contextMutex_);
135 CHECK_AND_RETURN_RET_LOG(context_ != nullptr, false, "AudioEncoder has been released");
136 std::unique_lock<std::mutex> lock(context_->inputMutex_);
137 bool condRet = context_->inputCond_.wait_for(lock, std::chrono::milliseconds(BUFFER_ENCODE_EXPIREATION_TIME),
138 [this]() { return !isStarted_ || !context_->inputBufferInfoQueue_.empty(); });
139 CHECK_AND_CONTINUE_LOG(!context_->inputBufferInfoQueue_.empty(),
140 "Buffer queue is empty, continue, cond ret: %{public}d", condRet);
141 sptr<CodecAVBufferInfo> bufferInfo = context_->inputBufferInfoQueue_.front();
142 context_->inputBufferInfoQueue_.pop();
143 context_->inputFrameCount_++;
144 bufferInfo->attr.pts = audioRecord->GetTimeStamp();
145 bufferInfo->attr.size = DEFAULT_MAX_INPUT_SIZE;
146 bufferInfo->attr.flags = AVCODEC_BUFFER_FLAGS_NONE;
147 auto bufferAddr = OH_AVBuffer_GetAddr(bufferInfo->buffer);
148 int32_t bufferCap = OH_AVBuffer_GetCapacity(bufferInfo->buffer);
149 errno_t cpyRet = memcpy_s(bufferAddr, bufferCap, buffer, DEFAULT_MAX_INPUT_SIZE);
150 CHECK_AND_RETURN_RET_LOG(cpyRet == 0, false, "encoder memcpy_s failed. %{public}d", cpyRet);
151 lock.unlock();
152 contextLock.unlock();
153 int32_t ret = PushInputData(bufferInfo);
154 CHECK_AND_RETURN_RET_LOG(ret == 0, false, "Push data failed");
155 MEDIA_DEBUG_LOG("Success frame id is : %{public}s", audioRecord->GetFrameId().c_str());
156 return true;
157 }
158 MEDIA_ERR_LOG("Failed frame id is : %{public}s", audioRecord->GetFrameId().c_str());
159 return false;
160 }
161
EncodeAudioBuffer(sptr<AudioRecord> audioRecord)162 bool AudioEncoder::EncodeAudioBuffer(sptr<AudioRecord> audioRecord)
163 {
164 CAMERA_SYNC_TRACE;
165 {
166 std::lock_guard<std::mutex> lock(encoderMutex_);
167 if (encoder_ == nullptr) {
168 return false;
169 }
170 }
171 audioRecord->SetStatusReadyConvertStatus();
172 if (!EnqueueBuffer(audioRecord)) {
173 return false;
174 }
175 int retryCount = 2;
176 while (retryCount > 0) {
177 retryCount--;
178 std::unique_lock<std::mutex> contextLock(contextMutex_);
179 CHECK_AND_RETURN_RET_LOG(context_ != nullptr, false, "AudioEncoder has been released");
180 std::unique_lock<std::mutex> lock(context_->outputMutex_);
181 bool condRet = context_->outputCond_.wait_for(lock, std::chrono::milliseconds(AUDIO_ENCODE_EXPIREATION_TIME),
182 [this]() { return !isStarted_ || !context_->outputBufferInfoQueue_.empty(); });
183 CHECK_AND_CONTINUE_LOG(!context_->outputBufferInfoQueue_.empty(),
184 "Buffer queue is empty, continue, cond ret: %{public}d", condRet);
185 sptr<CodecAVBufferInfo> bufferInfo = context_->outputBufferInfoQueue_.front();
186 context_->outputBufferInfoQueue_.pop();
187 context_->outputFrameCount_++;
188 MEDIA_DEBUG_LOG("Out buffer count: %{public}u, size: %{public}d, flag: %{public}u, pts:%{public}" PRId64,
189 context_->outputFrameCount_, bufferInfo->attr.size, bufferInfo->attr.flags, bufferInfo->attr.pts);
190 lock.unlock();
191 contextLock.unlock();
192 OH_AVBuffer *audioBuffer = bufferInfo->GetCopyAVBuffer();
193 audioRecord->CacheEncodedBuffer(audioBuffer);
194 int32_t ret = FreeOutputData(bufferInfo->bufferIndex);
195 CHECK_AND_BREAK_LOG(ret == 0, "FreeOutputData failed");
196 MEDIA_DEBUG_LOG("Success frame id is : %{public}s", audioRecord->GetFrameId().c_str());
197 audioRecord->SetEncodedResult(true);
198 return true;
199 }
200 MEDIA_ERR_LOG("Failed frame id is : %{public}s", audioRecord->GetFrameId().c_str());
201 return false;
202 }
203
EncodeAudioBuffer(vector<sptr<AudioRecord>> audioRecords)204 bool AudioEncoder::EncodeAudioBuffer(vector<sptr<AudioRecord>> audioRecords)
205 {
206 CAMERA_SYNC_TRACE;
207 std::lock_guard<std::mutex> lock(serialMutex_);
208 MEDIA_INFO_LOG("EncodeAudioBuffer enter");
209 if (!isStarted_.load()) {
210 RestartAudioCodec();
211 }
212 bool isSuccess = true;
213 for (sptr<AudioRecord> audioRecord : audioRecords) {
214 if (!audioRecord->IsEncoded() && !EncodeAudioBuffer(audioRecord)) {
215 isSuccess = false;
216 MEDIA_ERR_LOG("Failed frame id is : %{public}s", audioRecord->GetFrameId().c_str());
217 }
218 }
219 return isSuccess;
220 }
221
222
SetCallback(sptr<CodecUserData> codecUserData)223 int32_t AudioEncoder::SetCallback(sptr<CodecUserData> codecUserData)
224 {
225 int32_t ret = OH_AudioCodec_RegisterCallback(encoder_,
226 {SampleCallback::OnCodecError, SampleCallback::OnOutputFormatChanged,
227 SampleCallback::OnInputBufferAvailable, SampleCallback::OnOutputBufferAvailable},
228 static_cast<void *>(codecUserData));
229 CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, 1, "Set callback failed, ret: %{public}d", ret);
230 return 0;
231 }
232
Configure()233 int32_t AudioEncoder::Configure()
234 {
235 OH_AVFormat *format = OH_AVFormat_Create();
236 CHECK_AND_RETURN_RET_LOG(format != nullptr, 1, "AVFormat create failed");
237
238 OH_AVFormat_SetIntValue(format, OH_MD_KEY_AUD_CHANNEL_COUNT, DEFAULT_CHANNEL_COUNT);
239 OH_AVFormat_SetIntValue(format, OH_MD_KEY_AUD_SAMPLE_RATE, DEFAULT_SAMPLERATE);
240 OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, DEFAULT_BITRATE);
241 OH_AVFormat_SetIntValue(format, OH_MD_KEY_AUDIO_SAMPLE_FORMAT, SAMPLE_FORMAT);
242 OH_AVFormat_SetLongValue(format, OH_MD_KEY_CHANNEL_LAYOUT, CHANNEL_LAYOUT);
243 OH_AVFormat_SetIntValue(format, OH_MD_KEY_MAX_INPUT_SIZE, DEFAULT_MAX_INPUT_SIZE);
244 int ret = OH_AudioCodec_Configure(encoder_, format);
245 OH_AVFormat_Destroy(format);
246 format = nullptr;
247 CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, 1, "Config failed, ret: %{public}d", ret);
248 return 0;
249 }
250 } // CameraStandard
251 } // OHOS