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