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