1 /*
2 * Copyright (C) 2023 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 "avcodec_audio_codec_impl.h"
17 #include "i_avcodec_service.h"
18 #include "avcodec_log.h"
19 #include "avcodec_errors.h"
20 #include "avcodec_trace.h"
21 #include "avcodec_codec_name.h"
22 #include "codec_server.h"
23
24 namespace {
25 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "AVCodecAudioCodecImpl"};
26 constexpr int32_t DEFAULT_BUFFER_NUM = 4;
27 constexpr const char *INPUT_BUFFER_QUEUE_NAME = "AVCodecAudioCodecImpl";
28 const std::string_view ASYNC_HANDLE_INPUT = "OS_ACodecIn";
29 const std::string_view ASYNC_OUTPUT_FRAME = "OS_ACodecOut";
30 constexpr uint8_t LOGD_FREQUENCY = 5;
31 constexpr uint8_t TIME_OUT_MS = 5;
32 constexpr uint32_t DEFAULT_TRY_DECODE_TIME = 1;
33 constexpr int64_t MILLISECONDS = 100;
34 } // namespace
35
36 namespace OHOS {
37 namespace MediaAVCodec {
38
AudioCodecConsumerListener(AVCodecAudioCodecImpl * impl)39 AudioCodecConsumerListener::AudioCodecConsumerListener(AVCodecAudioCodecImpl *impl)
40 {
41 impl_ = impl;
42 }
43
OnBufferAvailable()44 void AudioCodecConsumerListener::OnBufferAvailable()
45 {
46 impl_->Notify();
47 }
48
Init(AVCodecType type,bool isMimeType,const std::string & name)49 int32_t AVCodecAudioCodecImpl::Init(AVCodecType type, bool isMimeType, const std::string &name)
50 {
51 AVCODEC_SYNC_TRACE;
52 codecService_ = CodecServer::Create();
53 CHECK_AND_RETURN_RET_LOG(codecService_ != nullptr, AVCS_ERR_UNKNOWN, "failed to create codec service");
54
55 implBufferQueue_ = Media::AVBufferQueue::Create(DEFAULT_BUFFER_NUM, Media::MemoryType::SHARED_MEMORY,
56 INPUT_BUFFER_QUEUE_NAME);
57
58 inputTask_ = std::make_unique<TaskThread>(ASYNC_HANDLE_INPUT);
59 outputTask_ = std::make_unique<TaskThread>(ASYNC_OUTPUT_FRAME);
60
61 return codecService_->Init(type, isMimeType, name, API_VERSION::API_VERSION_11);
62 }
63
AVCodecAudioCodecImpl()64 AVCodecAudioCodecImpl::AVCodecAudioCodecImpl()
65 {
66 AVCODEC_LOGD("AVCodecAudioCodecImpl:0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
67 }
68
~AVCodecAudioCodecImpl()69 AVCodecAudioCodecImpl::~AVCodecAudioCodecImpl()
70 {
71 codecService_ = nullptr;
72 AVCODEC_LOGD("AVCodecAudioCodecImpl:0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
73 }
74
Configure(const Format & format)75 int32_t AVCodecAudioCodecImpl::Configure(const Format &format)
76 {
77 AVCODEC_SYNC_TRACE;
78 CHECK_AND_RETURN_RET_LOG(codecService_ != nullptr, AVCS_ERR_INVALID_STATE, "service died");
79 auto meta = const_cast<Format &>(format).GetMeta();
80
81 return codecService_->Configure(meta);
82 }
83
Prepare()84 int32_t AVCodecAudioCodecImpl::Prepare()
85 {
86 AVCODEC_SYNC_TRACE;
87 CHECK_AND_RETURN_RET_LOG(codecService_ != nullptr, AVCS_ERR_INVALID_STATE, "service died");
88
89 implProducer_ = implBufferQueue_->GetProducer();
90 codecService_->SetOutputBufferQueue(implProducer_);
91 int32_t ret = codecService_->Prepare();
92
93 CHECK_AND_RETURN_RET_LOG(ret == 0, AVCS_ERR_INVALID_STATE, "prepare fail, ret:%{public}d", ret);
94
95 implConsumer_ = implBufferQueue_->GetConsumer();
96 mediaCodecProducer_ = codecService_->GetInputBufferQueue();
97 CHECK_AND_RETURN_RET_LOG(mediaCodecProducer_ != nullptr, AVCS_ERR_INVALID_VAL, "mediaCodecProducer_ is nullptr");
98
99 sptr<Media::IConsumerListener> comsumerListener = new AudioCodecConsumerListener(this);
100 implConsumer_->SetBufferAvailableListener(comsumerListener);
101
102 outputTask_->RegisterHandler([this] { ConsumerOutputBuffer(); });
103 return AVCS_ERR_OK;
104 }
105
Start()106 int32_t AVCodecAudioCodecImpl::Start()
107 {
108 AVCODEC_SYNC_TRACE;
109 CHECK_AND_RETURN_RET_LOG(Prepare() == AVCS_ERR_OK, AVCS_ERR_INVALID_STATE, "Prepare failed");
110 CHECK_AND_RETURN_RET_LOG(codecService_ != nullptr, AVCS_ERR_INVALID_STATE, "service died");
111 int32_t ret = codecService_->Start();
112 isRunning_ = true;
113 indexInput_ = 0;
114 indexOutput_ = 0;
115 if (inputTask_) {
116 inputTask_->RegisterHandler([this] { ProduceInputBuffer(); });
117 inputTask_->Start();
118 } else {
119 AVCODEC_LOGE("Start failed, inputTask_ is nullptr, please check the inputTask_.");
120 ret = AVCS_ERR_UNKNOWN;
121 }
122 if (outputTask_) {
123 outputTask_->Start();
124 } else {
125 AVCODEC_LOGE("Start failed, inputTask_ is nullptr, please check the inputTask_.");
126 ret = AVCS_ERR_UNKNOWN;
127 }
128 AVCODEC_LOGI("Start,ret = %{public}d", ret);
129 return ret;
130 }
131
Stop()132 int32_t AVCodecAudioCodecImpl::Stop()
133 {
134 AVCODEC_SYNC_TRACE;
135 CHECK_AND_RETURN_RET_LOG(codecService_ != nullptr, AVCS_ERR_INVALID_STATE, "service died");
136 StopTask();
137 int32_t ret = codecService_->Stop();
138 ClearCache();
139 return ret;
140 }
141
Flush()142 int32_t AVCodecAudioCodecImpl::Flush()
143 {
144 AVCODEC_SYNC_TRACE;
145 CHECK_AND_RETURN_RET_LOG(codecService_ != nullptr, AVCS_ERR_INVALID_STATE, "service died");
146 PauseTask();
147 int32_t ret = codecService_->Flush();
148 ClearCache();
149 return ret;
150 }
151
Reset()152 int32_t AVCodecAudioCodecImpl::Reset()
153 {
154 AVCODEC_SYNC_TRACE;
155 CHECK_AND_RETURN_RET_LOG(codecService_ != nullptr, AVCS_ERR_INVALID_STATE, "service died");
156 StopTask();
157 int32_t ret = codecService_->Reset();
158 ClearCache();
159 return ret;
160 }
161
Release()162 int32_t AVCodecAudioCodecImpl::Release()
163 {
164 AVCODEC_SYNC_TRACE;
165 CHECK_AND_RETURN_RET_LOG(codecService_ != nullptr, AVCS_ERR_INVALID_STATE, "service died");
166 StopTask();
167 int32_t ret = codecService_->Release();
168 ClearCache();
169 return ret;
170 }
171
QueueInputBuffer(uint32_t index)172 int32_t AVCodecAudioCodecImpl::QueueInputBuffer(uint32_t index)
173 {
174 AVCODEC_SYNC_TRACE;
175 CHECK_AND_RETURN_RET_LOG(codecService_ != nullptr, AVCS_ERR_INVALID_STATE, "service died");
176 CHECK_AND_RETURN_RET_LOG(mediaCodecProducer_ != nullptr, AVCS_ERR_INVALID_STATE,
177 "mediaCodecProducer_ is nullptr");
178 CHECK_AND_RETURN_RET_LOG(codecService_->GetStatus(), AVCS_ERR_INVALID_STATE,
179 "GetStatus is not running");
180
181 std::shared_ptr<AVBuffer> buffer;
182 {
183 std::unique_lock lock(inputMutex_);
184 auto it = inputBufferObjMap_.find(index);
185 CHECK_AND_RETURN_RET_LOG(it != inputBufferObjMap_.end(), AVCS_ERR_INVALID_VAL,
186 "Index does not exsist");
187 buffer = it->second;
188 inputBufferObjMap_.erase(index);
189 }
190 CHECK_AND_RETURN_RET_LOG(buffer != nullptr, AVCS_ERR_INVALID_STATE, "buffer not found");
191 Media::Status ret = mediaCodecProducer_->PushBuffer(buffer, true);
192 return StatusToAVCodecServiceErrCode(ret);
193 }
194
GetOutputFormat(Format & format)195 int32_t AVCodecAudioCodecImpl::GetOutputFormat(Format &format)
196 {
197 AVCODEC_SYNC_TRACE;
198 CHECK_AND_RETURN_RET_LOG(codecService_ != nullptr, AVCS_ERR_INVALID_STATE, "service died");
199 std::shared_ptr<Media::Meta> parameter = std::make_shared<Media::Meta>();
200 int32_t ret = codecService_->GetOutputFormat(parameter);
201 CHECK_AND_RETURN_RET_LOG(ret == 0, ret, "GetOutputFormat fail, ret:%{public}d", ret);
202 format.SetMeta(parameter);
203 return ret;
204 }
205
ReleaseOutputBuffer(uint32_t index)206 int32_t AVCodecAudioCodecImpl::ReleaseOutputBuffer(uint32_t index)
207 {
208 AVCODEC_SYNC_TRACE;
209 CHECK_AND_RETURN_RET_LOG(codecService_ != nullptr, AVCS_ERR_INVALID_STATE, "service died");
210 std::shared_ptr<AVBuffer> buffer;
211 {
212 std::unique_lock lock(outputMutex_);
213 auto it = outputBufferObjMap_.find(index);
214 CHECK_AND_RETURN_RET_LOG(it != outputBufferObjMap_.end(), AVCS_ERR_INVALID_VAL,
215 "Index does not exsist");
216 buffer = it->second;
217 outputBufferObjMap_.erase(index);
218 }
219 CHECK_AND_RETURN_RET_LOG(buffer != nullptr, AVCS_ERR_INVALID_STATE, "buffer is nullptr");
220 if (buffer->flag_ == AVCODEC_BUFFER_FLAG_EOS) {
221 AVCODEC_LOGI("EOS detected, QueueInputBuffer set eos status.");
222 codecService_->NotifyEos();
223 }
224
225 Media::Status ret = implConsumer_->ReleaseBuffer(buffer);
226 return StatusToAVCodecServiceErrCode(ret);
227 }
228
SetParameter(const Format & format)229 int32_t AVCodecAudioCodecImpl::SetParameter(const Format &format)
230 {
231 AVCODEC_SYNC_TRACE;
232 CHECK_AND_RETURN_RET_LOG(codecService_ != nullptr, AVCS_ERR_INVALID_STATE, "service died");
233 auto meta = const_cast<Format &>(format).GetMeta();
234 return codecService_->SetParameter(meta);
235 }
236
SetCallback(const std::shared_ptr<MediaCodecCallback> & callback)237 int32_t AVCodecAudioCodecImpl::SetCallback(const std::shared_ptr<MediaCodecCallback> &callback)
238 {
239 AVCODEC_SYNC_TRACE;
240 CHECK_AND_RETURN_RET_LOG(codecService_ != nullptr, AVCS_ERR_INVALID_STATE, "service died");
241 CHECK_AND_RETURN_RET_LOG(callback != nullptr, AVCS_ERR_INVALID_VAL, "callback is nullptr");
242 callback_ = callback;
243 return AVCS_ERR_OK;
244 }
245
Notify()246 void AVCodecAudioCodecImpl::Notify()
247 {
248 bufferConsumerAvailableCount_++;
249 // The medicCodec has filled the buffer with the output data in this producer.
250 // Notify the ProduceInputBuffer thread that it can continue fetching data from the user.
251 inputCondition_.notify_one();
252 outputCondition_.notify_one();
253 }
254
GetInputBufferSize()255 int32_t AVCodecAudioCodecImpl::GetInputBufferSize()
256 {
257 int32_t capacity = 0;
258 CHECK_AND_RETURN_RET_LOG(codecService_ != nullptr, capacity, "codecService_ is nullptr");
259 std::shared_ptr<Media::Meta> bufferConfig = std::make_shared<Media::Meta>();
260 CHECK_AND_RETURN_RET_LOG(bufferConfig != nullptr, capacity, "bufferConfig is nullptr");
261 int32_t ret = codecService_->GetOutputFormat(bufferConfig);
262 CHECK_AND_RETURN_RET_LOG(ret == 0, capacity, "GetOutputFormat fail");
263 CHECK_AND_RETURN_RET_LOG(bufferConfig->Get<Media::Tag::AUDIO_MAX_INPUT_SIZE>(capacity), capacity,
264 "get max input buffer size fail");
265 return capacity;
266 }
267
ProduceInputBuffer()268 void AVCodecAudioCodecImpl::ProduceInputBuffer()
269 {
270 AVCODEC_SYNC_TRACE;
271 AVCODEC_LOGD_LIMIT(LOGD_FREQUENCY, "produceInputBuffer enter");
272 if (!isRunning_) {
273 usleep(DEFAULT_TRY_DECODE_TIME);
274 AVCODEC_LOGE("ProduceInputBuffer isRunning_ false");
275 return;
276 }
277 Media::Status ret = Media::Status::OK;
278 Media::AVBufferConfig avBufferConfig;
279 avBufferConfig.size = GetInputBufferSize();
280 std::unique_lock lock2(inputMutex2_);
281 while (isRunning_) {
282 std::shared_ptr<AVBuffer> emptyBuffer = nullptr;
283 CHECK_AND_CONTINUE_LOG(mediaCodecProducer_ != nullptr, "mediaCodecProducer_ is nullptr");
284 ret = mediaCodecProducer_->RequestBuffer(emptyBuffer, avBufferConfig, TIME_OUT_MS);
285 if (ret != Media::Status::OK) {
286 AVCODEC_LOGW("produceInputBuffer RequestBuffer fail, ret=%{public}d", ret);
287 break;
288 }
289 CHECK_AND_CONTINUE_LOG(emptyBuffer != nullptr, "buffer is nullptr");
290 {
291 std::unique_lock lock1(inputMutex_);
292 inputBufferObjMap_[indexInput_] = emptyBuffer;
293 }
294 CHECK_AND_CONTINUE_LOG(callback_ != nullptr, "callback is nullptr");
295 callback_->OnInputBufferAvailable(indexInput_, emptyBuffer);
296 indexInput_++;
297 }
298 inputCondition_.wait_for(lock2, std::chrono::milliseconds(MILLISECONDS),
299 [this] { return ((bufferConsumerAvailableCount_ > 0) || !isRunning_); });
300 AVCODEC_LOGD_LIMIT(LOGD_FREQUENCY, "produceInputBuffer exit");
301 }
302
ConsumerOutputBuffer()303 void AVCodecAudioCodecImpl::ConsumerOutputBuffer()
304 {
305 AVCODEC_SYNC_TRACE;
306 AVCODEC_LOGD_LIMIT(LOGD_FREQUENCY, "ConsumerOutputBuffer enter");
307 if (!isRunning_) {
308 usleep(DEFAULT_TRY_DECODE_TIME);
309 AVCODEC_LOGE("Consumer isRunning_ false");
310 return;
311 }
312 Media::Status ret = Media::Status::OK;
313 std::unique_lock lock2(outputMutex_2);
314 while (isRunning_ && (bufferConsumerAvailableCount_ > 0)) {
315 std::shared_ptr<AVBuffer> filledInputBuffer;
316 ret = implConsumer_->AcquireBuffer(filledInputBuffer);
317 if (ret != Media::Status::OK) {
318 AVCODEC_LOGE("Consumer AcquireBuffer fail,ret=%{public}d", ret);
319 break;
320 }
321 {
322 std::unique_lock lock(outputMutex_);
323 outputBufferObjMap_[indexOutput_] = filledInputBuffer;
324 }
325 callback_->OnOutputBufferAvailable(indexOutput_, filledInputBuffer);
326 indexOutput_++;
327 bufferConsumerAvailableCount_--;
328 }
329 outputCondition_.wait_for(lock2, std::chrono::milliseconds(MILLISECONDS),
330 [this] { return ((bufferConsumerAvailableCount_ > 0) || !isRunning_); });
331 AVCODEC_LOGD_LIMIT(LOGD_FREQUENCY, "ConsumerOutputBuffer exit");
332 }
333
ClearCache()334 void AVCodecAudioCodecImpl::ClearCache()
335 {
336 for (auto iter = outputBufferObjMap_.begin(); iter != outputBufferObjMap_.end();) {
337 std::shared_ptr<AVBuffer> buffer = iter->second;
338 iter = outputBufferObjMap_.erase(iter);
339 implConsumer_->ReleaseBuffer(buffer);
340 }
341 inputBufferObjMap_.clear();
342 }
343
StopTask()344 void AVCodecAudioCodecImpl::StopTask()
345 {
346 isRunning_ = false;
347 if (inputTask_) {
348 inputTask_->Stop();
349 }
350 if (outputTask_) {
351 outputTask_->Stop();
352 }
353 }
354
PauseTask()355 void AVCodecAudioCodecImpl::PauseTask()
356 {
357 isRunning_ = false;
358 if (inputTask_) {
359 inputTask_->Pause();
360 }
361 if (outputTask_) {
362 outputTask_->Pause();
363 }
364 }
365 } // namespace MediaAVCodec
366 } // namespace OHOS
367