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