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         int32_t ret = PushInputData(bufferInfo);
152         CHECK_AND_RETURN_RET_LOG(ret == 0, false, "Push data failed");
153         MEDIA_DEBUG_LOG("Success frame id is : %{public}s", audioRecord->GetFrameId().c_str());
154         return true;
155     }
156     MEDIA_ERR_LOG("Failed frame id is : %{public}s", audioRecord->GetFrameId().c_str());
157     return false;
158 }
159 
EncodeAudioBuffer(sptr<AudioRecord> audioRecord)160 bool AudioEncoder::EncodeAudioBuffer(sptr<AudioRecord> audioRecord)
161 {
162     CAMERA_SYNC_TRACE;
163     {
164         std::lock_guard<std::mutex> lock(encoderMutex_);
165         if (encoder_ == nullptr) {
166             return false;
167         }
168     }
169     audioRecord->SetStatusReadyConvertStatus();
170     if (!EnqueueBuffer(audioRecord)) {
171         return false;
172     }
173     int retryCount = 2;
174     while (retryCount > 0) {
175         retryCount--;
176         std::unique_lock<std::mutex> contextLock(contextMutex_);
177         CHECK_AND_RETURN_RET_LOG(context_ != nullptr, false, "AudioEncoder has been released");
178         std::unique_lock<std::mutex> lock(context_->outputMutex_);
179         bool condRet = context_->outputCond_.wait_for(lock, std::chrono::milliseconds(AUDIO_ENCODE_EXPIREATION_TIME),
180             [this]() { return !isStarted_ || !context_->outputBufferInfoQueue_.empty(); });
181         CHECK_AND_CONTINUE_LOG(!context_->outputBufferInfoQueue_.empty(),
182             "Buffer queue is empty, continue, cond ret: %{public}d", condRet);
183         sptr<CodecAVBufferInfo> bufferInfo = context_->outputBufferInfoQueue_.front();
184         context_->outputBufferInfoQueue_.pop();
185         context_->outputFrameCount_++;
186         MEDIA_DEBUG_LOG("Out buffer count: %{public}u, size: %{public}d, flag: %{public}u, pts:%{public}" PRId64,
187             context_->outputFrameCount_, bufferInfo->attr.size, bufferInfo->attr.flags, bufferInfo->attr.pts);
188         lock.unlock();
189         contextLock.unlock();
190         OH_AVBuffer *audioBuffer = bufferInfo->GetCopyAVBuffer();
191         audioRecord->CacheEncodedBuffer(audioBuffer);
192         int32_t ret = FreeOutputData(bufferInfo->bufferIndex);
193         CHECK_AND_BREAK_LOG(ret == 0, "FreeOutputData failed");
194         MEDIA_DEBUG_LOG("Success frame id is : %{public}s", audioRecord->GetFrameId().c_str());
195         audioRecord->SetEncodedResult(true);
196         return true;
197     }
198     MEDIA_ERR_LOG("Failed frame id is : %{public}s", audioRecord->GetFrameId().c_str());
199     return false;
200 }
201 
EncodeAudioBuffer(vector<sptr<AudioRecord>> audioRecords)202 bool AudioEncoder::EncodeAudioBuffer(vector<sptr<AudioRecord>> audioRecords)
203 {
204     CAMERA_SYNC_TRACE;
205     std::lock_guard<std::mutex> lock(serialMutex_);
206     MEDIA_INFO_LOG("EncodeAudioBuffer enter");
207     if (!isStarted_.load()) {
208         RestartAudioCodec();
209     }
210     bool isSuccess = true;
211     for (sptr<AudioRecord> audioRecord : audioRecords) {
212         if (!audioRecord->IsEncoded() && !EncodeAudioBuffer(audioRecord)) {
213             isSuccess = false;
214             MEDIA_ERR_LOG("Failed frame id is : %{public}s", audioRecord->GetFrameId().c_str());
215         }
216     }
217     return isSuccess;
218 }
219 
220 
SetCallback(sptr<CodecUserData> codecUserData)221 int32_t AudioEncoder::SetCallback(sptr<CodecUserData> codecUserData)
222 {
223     int32_t ret = OH_AudioCodec_RegisterCallback(encoder_,
224         {SampleCallback::OnCodecError, SampleCallback::OnOutputFormatChanged,
225         SampleCallback::OnInputBufferAvailable, SampleCallback::OnOutputBufferAvailable},
226         static_cast<void *>(codecUserData));
227     CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, 1, "Set callback failed, ret: %{public}d", ret);
228     return 0;
229 }
230 
Configure()231 int32_t AudioEncoder::Configure()
232 {
233     OH_AVFormat *format = OH_AVFormat_Create();
234     CHECK_AND_RETURN_RET_LOG(format != nullptr, 1, "AVFormat create failed");
235 
236     OH_AVFormat_SetIntValue(format, OH_MD_KEY_AUD_CHANNEL_COUNT, DEFAULT_CHANNEL_COUNT);
237     OH_AVFormat_SetIntValue(format, OH_MD_KEY_AUD_SAMPLE_RATE, DEFAULT_SAMPLERATE);
238     OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, DEFAULT_BITRATE);
239     OH_AVFormat_SetIntValue(format, OH_MD_KEY_AUDIO_SAMPLE_FORMAT, SAMPLE_FORMAT);
240     OH_AVFormat_SetLongValue(format, OH_MD_KEY_CHANNEL_LAYOUT, CHANNEL_LAYOUT);
241     OH_AVFormat_SetIntValue(format, OH_MD_KEY_MAX_INPUT_SIZE, DEFAULT_MAX_INPUT_SIZE);
242     int ret = OH_AudioCodec_Configure(encoder_, format);
243     OH_AVFormat_Destroy(format);
244     format = nullptr;
245     CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, 1, "Config failed, ret: %{public}d", ret);
246     return 0;
247 }
248 } // CameraStandard
249 } // OHOS