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 "avcodec_mime_type.h"
23 #include "codec_server.h"
24 #include "qos.h"
25
26 namespace {
27 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_AUDIO, "AVCodecAudioCodecImpl"};
28 constexpr int32_t DEFAULT_BUFFER_NUM = 4;
29 constexpr const char *INPUT_BUFFER_QUEUE_NAME = "AVCodecAudioCodecImpl";
30 const std::string_view ASYNC_HANDLE_INPUT = "OS_ACodecIn";
31 const std::string_view ASYNC_OUTPUT_FRAME = "OS_ACodecOut";
32 constexpr uint8_t LOGD_FREQUENCY = 5;
33 constexpr uint8_t TIME_OUT_MS = 50;
34 constexpr uint32_t DEFAULT_TRY_DECODE_TIME = 1000;
35 constexpr uint32_t MAX_INDEX = 1000000000;
36 constexpr int64_t MILLISECONDS = 100;
37 } // namespace
38
39 namespace OHOS {
40 namespace MediaAVCodec {
41
AudioCodecConsumerListener(AVCodecAudioCodecImpl * impl)42 AudioCodecConsumerListener::AudioCodecConsumerListener(AVCodecAudioCodecImpl *impl)
43 {
44 impl_ = impl;
45 }
46
OnBufferAvailable()47 void AudioCodecConsumerListener::OnBufferAvailable()
48 {
49 impl_->Notify();
50 }
51
Init(AVCodecType type,bool isMimeType,const std::string & name)52 int32_t AVCodecAudioCodecImpl::Init(AVCodecType type, bool isMimeType, const std::string &name)
53 {
54 AVCODEC_SYNC_TRACE;
55
56 bool enableOuter = isMimeType
57 ? AVCodecMimeType::CheckAudioCodecMimeSupportOuter(name, type == AVCODEC_TYPE_AUDIO_ENCODER)
58 : AVCodecCodecName::CheckAudioCodecNameSupportOuter(name);
59 if (!enableOuter) {
60 AVCODEC_LOGW("AVCodecAudioCodecImpl: %{public}s not support", name.c_str());
61 return AVCS_ERR_UNSUPPORT;
62 }
63
64 Format format;
65 codecService_ = CodecServer::Create();
66 CHECK_AND_RETURN_RET_LOG(codecService_ != nullptr, AVCS_ERR_UNKNOWN, "failed to create codec service");
67
68 implBufferQueue_ = Media::AVBufferQueue::Create(DEFAULT_BUFFER_NUM, Media::MemoryType::SHARED_MEMORY,
69 INPUT_BUFFER_QUEUE_NAME);
70 CHECK_AND_RETURN_RET_LOG(implBufferQueue_ != nullptr, AVCS_ERR_NO_MEMORY, "failed to create buffer queue");
71
72 inputTask_ = std::make_unique<TaskThread>(ASYNC_HANDLE_INPUT);
73 CHECK_AND_RETURN_RET_LOG(inputTask_ != nullptr, AVCS_ERR_NO_MEMORY, "failed to create input task");
74 outputTask_ = std::make_unique<TaskThread>(ASYNC_OUTPUT_FRAME);
75 CHECK_AND_RETURN_RET_LOG(outputTask_ != nullptr, AVCS_ERR_NO_MEMORY, "failed to create output task");
76
77 return codecService_->Init(type, isMimeType, name, *format.GetMeta(), API_VERSION::API_VERSION_11);
78 }
79
AVCodecAudioCodecImpl()80 AVCodecAudioCodecImpl::AVCodecAudioCodecImpl()
81 {
82 AVCODEC_LOGI("AVCodecAudioCodecImpl:0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
83 }
84
~AVCodecAudioCodecImpl()85 AVCodecAudioCodecImpl::~AVCodecAudioCodecImpl()
86 {
87 codecService_ = nullptr;
88 AVCODEC_LOGI("AVCodecAudioCodecImpl:0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
89 }
90
Configure(const Format & format)91 int32_t AVCodecAudioCodecImpl::Configure(const Format &format)
92 {
93 AVCODEC_SYNC_TRACE;
94 CHECK_AND_RETURN_RET_LOG(codecService_ != nullptr, AVCS_ERR_INVALID_STATE, "service died");
95 auto meta = const_cast<Format &>(format).GetMeta();
96 inputBufferSize_ = 0;
97
98 int32_t syncMode = 0;
99 format.GetIntValue(Media::Tag::AV_CODEC_ENABLE_SYNC_MODE, syncMode);
100 isSyncMode_.store(syncMode == 1);
101 AVCODEC_LOGI("AVCodecAudioCodecImpl:0x%{public}06" PRIXPTR " sync mode:%{public}d", FAKE_POINTER(this), syncMode);
102 if (isSyncMode_.load()) {
103 std::shared_ptr<AVCodecInnerCallback> innerCallback = std::make_shared<AVCodecInnerCallback>(this);
104 codecService_->SetCallback(innerCallback);
105 }
106 return codecService_->Configure(meta);
107 }
108
Prepare()109 int32_t AVCodecAudioCodecImpl::Prepare()
110 {
111 AVCODEC_SYNC_TRACE;
112 CHECK_AND_RETURN_RET_LOG(codecService_ != nullptr, AVCS_ERR_INVALID_STATE, "service died");
113
114 implProducer_ = implBufferQueue_->GetProducer();
115 codecService_->SetOutputBufferQueue(implProducer_);
116 int32_t ret = codecService_->Prepare();
117 CHECK_AND_RETURN_RET_LOG_LIMIT(ret != AVCS_ERR_TRY_AGAIN, AVCS_ERR_OK,
118 LOGD_FREQUENCY, "no need prepare");
119 CHECK_AND_RETURN_RET_LOG(ret == 0, AVCS_ERR_INVALID_STATE, "prepare fail, ret:%{public}d", ret);
120
121 implConsumer_ = implBufferQueue_->GetConsumer();
122 mediaCodecProducer_ = codecService_->GetInputBufferQueue();
123 CHECK_AND_RETURN_RET_LOG(mediaCodecProducer_ != nullptr, AVCS_ERR_INVALID_VAL, "mediaCodecProducer_ is nullptr");
124
125 sptr<Media::IConsumerListener> comsumerListener = new AudioCodecConsumerListener(this);
126 implConsumer_->SetBufferAvailableListener(comsumerListener);
127
128 outputTask_->RegisterHandler([this] { ConsumerOutputBuffer(); });
129 if (!isSyncMode_.load()) {
130 inputTask_->RegisterHandler([this] { ProduceInputBuffer(); });
131 }
132 return AVCS_ERR_OK;
133 }
134
Start()135 int32_t AVCodecAudioCodecImpl::Start()
136 {
137 AVCODEC_SYNC_TRACE;
138 CHECK_AND_RETURN_RET_LOG(Prepare() == AVCS_ERR_OK, AVCS_ERR_INVALID_STATE, "Prepare failed");
139 CHECK_AND_RETURN_RET_LOG(codecService_ != nullptr, AVCS_ERR_INVALID_STATE, "service died");
140 int32_t ret = codecService_->Start();
141 CHECK_AND_RETURN_RET_LOG(ret == 0, ret, "Start failed, ret:%{public}d", ret);
142 isRunning_ = true;
143 indexInput_ = 0;
144 indexOutput_ = 0;
145 if (!isSyncMode_.load()) {
146 if (inputTask_) {
147 inputTask_->Start();
148 } else {
149 AVCODEC_LOGE("Start failed, inputTask_ is nullptr, please check the inputTask_.");
150 ret = AVCS_ERR_UNKNOWN;
151 }
152 }
153 if (outputTask_) {
154 outputTask_->Start();
155 } else {
156 AVCODEC_LOGE("Start failed, outputTask_ is nullptr, please check the outputTask_.");
157 ret = AVCS_ERR_UNKNOWN;
158 }
159 AVCODEC_LOGI("Instances:0x%{public}06" PRIXPTR " Start, ret = %{public}d", FAKE_POINTER(this), ret);
160 return ret;
161 }
162
Stop()163 int32_t AVCodecAudioCodecImpl::Stop()
164 {
165 AVCODEC_SYNC_TRACE;
166 AVCODEC_LOGI("Instances:0x%{public}06" PRIXPTR " Stop", FAKE_POINTER(this));
167 CHECK_AND_RETURN_RET_LOG(codecService_ != nullptr, AVCS_ERR_INVALID_STATE, "service died");
168 StopTaskAsync();
169 int32_t ret = codecService_->Stop();
170 StopTask();
171 ClearCache();
172 ReturnInputBuffer();
173 return ret;
174 }
175
Flush()176 int32_t AVCodecAudioCodecImpl::Flush()
177 {
178 AVCODEC_SYNC_TRACE;
179 AVCODEC_LOGI("Instances:0x%{public}06" PRIXPTR " Flush", FAKE_POINTER(this));
180 CHECK_AND_RETURN_RET_LOG(codecService_ != nullptr, AVCS_ERR_INVALID_STATE, "service died");
181 PauseTaskAsync();
182 int32_t ret = codecService_->Flush();
183 PauseTask();
184 ClearCache();
185 ReturnInputBuffer();
186 return ret;
187 }
188
Reset()189 int32_t AVCodecAudioCodecImpl::Reset()
190 {
191 AVCODEC_SYNC_TRACE;
192 AVCODEC_LOGI("Instances:0x%{public}06" PRIXPTR " Reset", FAKE_POINTER(this));
193 CHECK_AND_RETURN_RET_LOG(codecService_ != nullptr, AVCS_ERR_INVALID_STATE, "service died");
194 StopTaskAsync();
195 int32_t ret = codecService_->Reset();
196 StopTask();
197 ClearCache();
198 ClearInputBuffer();
199 inputBufferSize_ = 0;
200 isSyncMode_.store(false);
201 return ret;
202 }
203
Release()204 int32_t AVCodecAudioCodecImpl::Release()
205 {
206 AVCODEC_SYNC_TRACE;
207 AVCODEC_LOGI("Instances:0x%{public}06" PRIXPTR " Release", FAKE_POINTER(this));
208 CHECK_AND_RETURN_RET_LOG(codecService_ != nullptr, AVCS_ERR_INVALID_STATE, "service died");
209 Stop();
210 int32_t ret = codecService_->Release();
211 inputBufferSize_ = 0;
212 return ret;
213 }
214
QueueInputBuffer(uint32_t index)215 int32_t AVCodecAudioCodecImpl::QueueInputBuffer(uint32_t index)
216 {
217 AVCODEC_SYNC_TRACE;
218 CHECK_AND_RETURN_RET_LOG(codecService_ != nullptr, AVCS_ERR_INVALID_STATE, "service died");
219 CHECK_AND_RETURN_RET_LOG(mediaCodecProducer_ != nullptr, AVCS_ERR_INVALID_STATE,
220 "mediaCodecProducer_ is nullptr");
221 CHECK_AND_RETURN_RET_LOG(codecService_->CheckRunning(), AVCS_ERR_INVALID_STATE, "CheckRunning is not running");
222 std::shared_ptr<AVBuffer> buffer;
223 {
224 std::unique_lock lock(inputMutex_);
225 auto it = inputBufferObjMap_.find(index);
226 if (it == inputBufferObjMap_.end()) {
227 AVCODEC_LOGE("Index:%{public}d does not exist", index);
228 return AVCS_ERR_INVALID_VAL;
229 }
230 buffer = it->second;
231 inputBufferObjMap_.erase(index);
232 }
233 CHECK_AND_RETURN_RET_LOG(buffer != nullptr, AVCS_ERR_INVALID_STATE, "buffer not found");
234 if (!(buffer->flag_ & AVCODEC_BUFFER_FLAG_EOS) && buffer->GetConfig().size <= 0) {
235 AVCODEC_LOGE("buffer size is 0,please fill audio buffer in");
236 return AVCS_ERR_UNKNOWN;
237 }
238 {
239 std::unique_lock lock(outputMutex_2);
240 inputIndexQueue.emplace(buffer);
241 }
242 outputCondition_.notify_one();
243 return AVCS_ERR_OK;
244 }
245
246 #ifdef SUPPORT_DRM
SetAudioDecryptionConfig(const sptr<DrmStandard::IMediaKeySessionService> & keySession,const bool svpFlag)247 int32_t AVCodecAudioCodecImpl::SetAudioDecryptionConfig(const sptr<DrmStandard::IMediaKeySessionService> &keySession,
248 const bool svpFlag)
249 {
250 AVCODEC_SYNC_TRACE;
251 CHECK_AND_RETURN_RET_LOG(codecService_ != nullptr, AVCS_ERR_INVALID_STATE, "service died");
252 return codecService_->SetAudioDecryptionConfig(keySession, svpFlag);
253 }
254 #else
SetAudioDecryptionConfig(const sptr<DrmStandard::IMediaKeySessionService> & keySession,const bool svpFlag)255 int32_t AVCodecAudioCodecImpl::SetAudioDecryptionConfig(const sptr<DrmStandard::IMediaKeySessionService> &keySession,
256 const bool svpFlag)
257 {
258 (void)keySession;
259 (void)svpFlag;
260 return 0;
261 }
262 #endif
263
GetOutputFormat(Format & format)264 int32_t AVCodecAudioCodecImpl::GetOutputFormat(Format &format)
265 {
266 AVCODEC_SYNC_TRACE;
267 CHECK_AND_RETURN_RET_LOG(codecService_ != nullptr, AVCS_ERR_INVALID_STATE, "service died");
268 std::shared_ptr<Media::Meta> parameter = std::make_shared<Media::Meta>();
269 int32_t ret = codecService_->GetOutputFormat(parameter);
270 CHECK_AND_RETURN_RET_LOG(ret == 0, ret, "GetOutputFormat fail, ret:%{public}d", ret);
271 format.SetMeta(parameter);
272 return ret;
273 }
274
ReleaseOutputBuffer(uint32_t index)275 int32_t AVCodecAudioCodecImpl::ReleaseOutputBuffer(uint32_t index)
276 {
277 AVCODEC_SYNC_TRACE;
278 CHECK_AND_RETURN_RET_LOG(codecService_ != nullptr, AVCS_ERR_INVALID_STATE, "service died");
279 std::shared_ptr<AVBuffer> buffer;
280 {
281 std::unique_lock lock(outputMutex_);
282 auto it = outputBufferObjMap_.find(index);
283 CHECK_AND_RETURN_RET_LOG(it != outputBufferObjMap_.end(), AVCS_ERR_INVALID_VAL,
284 "Index does not exist");
285 buffer = it->second;
286 outputBufferObjMap_.erase(index);
287 }
288 CHECK_AND_RETURN_RET_LOG(buffer != nullptr, AVCS_ERR_INVALID_STATE, "buffer is nullptr");
289 if (buffer->flag_ == AVCODEC_BUFFER_FLAG_EOS) {
290 AVCODEC_LOGI("EOS detected, QueueInputBuffer set eos status.");
291 codecService_->NotifyEos();
292 }
293
294 Media::Status ret = implConsumer_->ReleaseBuffer(buffer);
295 return StatusToAVCodecServiceErrCode(ret);
296 }
297
SetParameter(const Format & format)298 int32_t AVCodecAudioCodecImpl::SetParameter(const Format &format)
299 {
300 AVCODEC_SYNC_TRACE;
301 CHECK_AND_RETURN_RET_LOG(codecService_ != nullptr, AVCS_ERR_INVALID_STATE, "service died");
302 auto meta = const_cast<Format &>(format).GetMeta();
303 inputBufferSize_ = 0;
304 return codecService_->SetParameter(meta);
305 }
306
SetCallback(const std::shared_ptr<MediaCodecCallback> & callback)307 int32_t AVCodecAudioCodecImpl::SetCallback(const std::shared_ptr<MediaCodecCallback> &callback)
308 {
309 AVCODEC_SYNC_TRACE;
310 CHECK_AND_RETURN_RET_LOG(codecService_ != nullptr, AVCS_ERR_INVALID_STATE, "service died");
311 CHECK_AND_RETURN_RET_LOG(callback != nullptr, AVCS_ERR_INVALID_VAL, "callback is nullptr");
312 callback_ = callback;
313 std::shared_ptr<AVCodecInnerCallback> innerCallback = std::make_shared<AVCodecInnerCallback>(this);
314 return codecService_->SetCallback(innerCallback);
315 }
316
Notify()317 void AVCodecAudioCodecImpl::Notify()
318 {
319 bufferConsumerAvailableCount_++;
320 // The medicCodec has filled the buffer with the output data in this producer.
321 // Notify the ProduceInputBuffer thread that it can continue fetching data from the user.
322 inputCondition_.notify_one();
323 outputCondition_.notify_one();
324 }
325
GetInputBufferSize()326 int32_t AVCodecAudioCodecImpl::GetInputBufferSize()
327 {
328 if (inputBufferSize_ > 0) {
329 return inputBufferSize_;
330 }
331 int32_t capacity = 0;
332 CHECK_AND_RETURN_RET_LOG(codecService_ != nullptr, capacity, "codecService_ is nullptr");
333 std::shared_ptr<Media::Meta> bufferConfig = std::make_shared<Media::Meta>();
334 CHECK_AND_RETURN_RET_LOG(bufferConfig != nullptr, capacity, "bufferConfig is nullptr");
335 int32_t ret = codecService_->GetOutputFormat(bufferConfig);
336 CHECK_AND_RETURN_RET_LOG(ret == 0, capacity, "GetOutputFormat fail");
337 CHECK_AND_RETURN_RET_LOG(bufferConfig->Get<Media::Tag::AUDIO_MAX_INPUT_SIZE>(capacity), capacity,
338 "get max input buffer size fail");
339 inputBufferSize_ = capacity;
340 return capacity;
341 }
342
ProduceInputBuffer()343 void AVCodecAudioCodecImpl::ProduceInputBuffer()
344 {
345 AVCODEC_SYNC_TRACE;
346 if (indexInput_ == 0) {
347 auto ret = SetThreadQos(OHOS::QOS::QosLevel::QOS_USER_INTERACTIVE);
348 AVCODEC_LOGD("set OS_ACodecIn thread qos, ret = %{public}d", ret);
349 }
350 AVCODEC_LOGD_LIMIT(LOGD_FREQUENCY, "produceInputBuffer enter");
351 if (!isRunning_) {
352 usleep(DEFAULT_TRY_DECODE_TIME);
353 AVCODEC_LOGE("ProduceInputBuffer isRunning_ false");
354 return;
355 }
356 Media::Status ret = Media::Status::OK;
357 Media::AVBufferConfig avBufferConfig;
358 avBufferConfig.size = GetInputBufferSize();
359 std::unique_lock lock2(inputMutex2_);
360 while (isRunning_) {
361 std::shared_ptr<AVBuffer> emptyBuffer = nullptr;
362 CHECK_AND_CONTINUE_LOG(mediaCodecProducer_ != nullptr, "mediaCodecProducer_ is nullptr");
363 ret = mediaCodecProducer_->RequestBuffer(emptyBuffer, avBufferConfig, TIME_OUT_MS);
364 if (ret != Media::Status::OK) {
365 AVCODEC_LOGD_LIMIT(LOGD_FREQUENCY, "produceInputBuffer RequestBuffer fail, ret=%{public}d", ret);
366 break;
367 }
368 CHECK_AND_CONTINUE_LOG(emptyBuffer != nullptr, "buffer is nullptr");
369 {
370 std::unique_lock lock1(inputMutex_);
371 inputBufferObjMap_[indexInput_] = emptyBuffer;
372 }
373 CHECK_AND_CONTINUE_LOG(callback_ != nullptr, "callback is nullptr");
374 callback_->OnInputBufferAvailable(indexInput_, emptyBuffer);
375 indexInput_ = (indexInput_ >= MAX_INDEX) ? 0 : ++indexInput_;
376 }
377 if (!isRunning_) {
378 AVCODEC_LOGI("ProduceInputBuffer exit");
379 return;
380 }
381
382 inputCondition_.wait_for(lock2, std::chrono::milliseconds(MILLISECONDS),
383 [this] { return ((mediaCodecProducer_->GetQueueSize() > 0) || !isRunning_); });
384 AVCODEC_LOGD_LIMIT(LOGD_FREQUENCY, "produceInputBuffer exit");
385 }
386
ConsumerOutputBuffer()387 void AVCodecAudioCodecImpl::ConsumerOutputBuffer()
388 {
389 AVCODEC_SYNC_TRACE;
390 if (indexOutput_ == 0) {
391 auto ret = SetThreadQos(OHOS::QOS::QosLevel::QOS_USER_INTERACTIVE);
392 AVCODEC_LOGD("set OS_ACodecOut thread qos, ret = %{public}d", ret);
393 }
394 AVCODEC_LOGD_LIMIT(LOGD_FREQUENCY, "ConsumerOutputBuffer enter");
395 if (!isRunning_) {
396 usleep(DEFAULT_TRY_DECODE_TIME);
397 AVCODEC_LOGE("Consumer isRunning_ false");
398 return;
399 }
400
401 while (isRunning_) {
402 std::unique_lock lock2(outputMutex_2);
403 if (inputIndexQueue.empty()) {
404 break;
405 }
406 std::shared_ptr<AVBuffer> buffer;
407 buffer = inputIndexQueue.front();
408 inputIndexQueue.pop();
409 lock2.unlock();
410
411 Media::Status ret = mediaCodecProducer_->PushBuffer(buffer, true);
412 if (ret != Media::Status::OK) {
413 AVCODEC_LOGW("ConsumerOutputBuffer PushBuffer fail, ret=%{public}d", ret);
414 break;
415 }
416 inputCondition_.notify_all();
417 }
418 if (!isRunning_) {
419 AVCODEC_LOGI("ConsumerOutputBuffer exit");
420 return;
421 }
422 std::unique_lock lock2(outputMutex_2);
423 outputCondition_.wait_for(lock2, std::chrono::milliseconds(MILLISECONDS),
424 [this] { return ((!inputIndexQueue.empty()) || !isRunning_); });
425 AVCODEC_LOGD_LIMIT(LOGD_FREQUENCY, "ConsumerOutputBuffer exit");
426 }
427
ClearCache()428 void AVCodecAudioCodecImpl::ClearCache()
429 {
430 std::unique_lock lock(outputMutex_);
431 for (auto iter = outputBufferObjMap_.begin(); iter != outputBufferObjMap_.end();) {
432 std::shared_ptr<AVBuffer> buffer;
433 buffer = iter->second;
434 iter = outputBufferObjMap_.erase(iter);
435 implConsumer_->ReleaseBuffer(buffer);
436 }
437 }
438
ReturnInputBuffer()439 void AVCodecAudioCodecImpl::ReturnInputBuffer()
440 {
441 {
442 std::unique_lock lock(inputMutex_);
443 for (const auto &inputMap : inputBufferObjMap_) {
444 mediaCodecProducer_->PushBuffer(inputMap.second, false);
445 }
446 inputBufferObjMap_.clear();
447 }
448 std::unique_lock lock(outputMutex_2);
449 while (!inputIndexQueue.empty()) {
450 std::shared_ptr<AVBuffer> buffer;
451 buffer = inputIndexQueue.front();
452 inputIndexQueue.pop();
453 lock.unlock();
454 mediaCodecProducer_->PushBuffer(buffer, false);
455 lock.lock();
456 }
457 }
458
ClearInputBuffer()459 void AVCodecAudioCodecImpl::ClearInputBuffer()
460 {
461 {
462 std::unique_lock lock(inputMutex_);
463 inputBufferObjMap_.clear();
464 }
465 std::unique_lock lock(outputMutex_2);
466 while (!inputIndexQueue.empty()) {
467 inputIndexQueue.pop();
468 }
469 }
470
StopTaskAsync()471 void AVCodecAudioCodecImpl::StopTaskAsync()
472 {
473 isRunning_ = false;
474 // stop input/output thread faster
475 ClearCache();
476 ReturnInputBuffer();
477 {
478 std::lock_guard lock(inputMutex2_);
479 inputCondition_.notify_one();
480 }
481 {
482 std::lock_guard lock(outputMutex_2);
483 outputCondition_.notify_one();
484 }
485 if (inputTask_) {
486 inputTask_->StopAsync();
487 }
488 if (outputTask_) {
489 outputTask_->StopAsync();
490 }
491 }
492
PauseTaskAsync()493 void AVCodecAudioCodecImpl::PauseTaskAsync()
494 {
495 isRunning_ = false;
496 // stop input/output thread faster
497 ClearCache();
498 ReturnInputBuffer();
499 {
500 std::lock_guard lock(inputMutex2_);
501 inputCondition_.notify_one();
502 }
503 {
504 std::lock_guard lock(outputMutex_2);
505 outputCondition_.notify_one();
506 }
507 if (inputTask_) {
508 inputTask_->PauseAsync();
509 }
510 if (outputTask_) {
511 outputTask_->PauseAsync();
512 }
513 }
514
StopTask()515 void AVCodecAudioCodecImpl::StopTask()
516 {
517 if (inputTask_) {
518 inputTask_->Stop();
519 }
520 if (outputTask_) {
521 outputTask_->Stop();
522 }
523 }
524
PauseTask()525 void AVCodecAudioCodecImpl::PauseTask()
526 {
527 if (inputTask_) {
528 inputTask_->Pause();
529 }
530 if (outputTask_) {
531 outputTask_->Pause();
532 }
533 }
534
QueryInputBuffer(uint32_t * index,int64_t timeoutUs)535 int32_t AVCodecAudioCodecImpl::QueryInputBuffer(uint32_t *index, int64_t timeoutUs)
536 {
537 if (index == nullptr) {
538 AVCODEC_LOGE("input nullptr index");
539 return AVCS_ERR_INVALID_VAL;
540 }
541 if (!isRunning_.load()) {
542 AVCODEC_LOGE("not start");
543 return AVCS_ERR_INVALID_STATE;
544 }
545 if (!isSyncMode_.load()) {
546 AVCODEC_LOGE("not in sync mode");
547 return AVCS_ERR_INVALID_OPERATION;
548 }
549 AVCODEC_SYNC_TRACE;
550 Media::AVBufferConfig avBufferConfig;
551 avBufferConfig.size = GetInputBufferSize();
552 std::unique_lock lock2(inputMutex2_);
553 CHECK_AND_RETURN_RET_LOG(mediaCodecProducer_ != nullptr, AVCS_ERR_INVALID_VAL, "mediaCodecProducer_ is nullptr");
554 std::shared_ptr<AVBuffer> emptyBuffer = nullptr;
555 Status ret = mediaCodecProducer_->RequestBufferWaitUs(emptyBuffer, avBufferConfig, timeoutUs);
556 if (ret == Media::Status::ERROR_WAIT_TIMEOUT) {
557 AVCODEC_LOGW("produceInputBuffer RequestBuffer wait:%{public}" PRId64 " us timeout", timeoutUs);
558 return AVCS_ERR_TRY_AGAIN;
559 } else if (ret != Media::Status::OK) {
560 AVCODEC_LOGE("produceInputBuffer RequestBuffer fail, ret=%{public}d", ret);
561 return AVCS_ERR_INVALID_VAL;
562 }
563 if (emptyBuffer == nullptr) {
564 AVCODEC_LOGE("buffer is nullptr");
565 return AVCS_ERR_INVALID_VAL;
566 }
567 std::unique_lock lock1(inputMutex_);
568 inputBufferObjMap_[indexInput_] = emptyBuffer;
569 *index = indexInput_;
570 AVCODEC_LOGD("new input buffer index:%{public}d", *index);
571 indexInput_ = (indexInput_ >= MAX_INDEX) ? 0 : ++indexInput_;
572 return AVCS_ERR_OK;
573 }
574
GetInputBuffer(uint32_t index)575 std::shared_ptr<AVBuffer> AVCodecAudioCodecImpl::GetInputBuffer(uint32_t index)
576 {
577 if (!isSyncMode_.load() || !isRunning_.load()) {
578 AVCODEC_LOGE("not start or not in sync mode, %{public}d, %{public}d", isSyncMode_.load(), isRunning_.load());
579 return nullptr;
580 }
581 AVCODEC_SYNC_TRACE;
582 std::unique_lock lock(inputMutex_);
583 std::shared_ptr<AVBuffer> buffer;
584 auto it = inputBufferObjMap_.find(index);
585 if (it == inputBufferObjMap_.end()) {
586 AVCODEC_LOGE("Index:%{public}d does not exist", index);
587 return nullptr;
588 }
589 buffer = it->second;
590 CHECK_AND_RETURN_RET_LOG(buffer != nullptr, nullptr, "buffer not found");
591 return buffer;
592 }
593
QueryOutputBuffer(uint32_t * index,int64_t timeoutUs)594 int32_t AVCodecAudioCodecImpl::QueryOutputBuffer(uint32_t *index, int64_t timeoutUs)
595 {
596 if (index == nullptr) {
597 AVCODEC_LOGE("input nullptr index");
598 return AVCS_ERR_INVALID_VAL;
599 }
600 if (!isRunning_.load()) {
601 AVCODEC_LOGE("not start");
602 return AVCS_ERR_INVALID_STATE;
603 }
604 if (!isSyncMode_.load()) {
605 AVCODEC_LOGE("not in sync mode");
606 return AVCS_ERR_INVALID_OPERATION;
607 }
608 AVCODEC_SYNC_TRACE;
609 std::unique_lock lock(syncOutputMutex_);
610 if (syncOutputQueue_.empty() && timeoutUs != 0) {
611 if (timeoutUs < 0) {
612 syncOutCond_.wait(lock, [this] { return !syncOutputQueue_.empty(); });
613 } else {
614 auto timeout = std::chrono::microseconds(timeoutUs);
615 syncOutCond_.wait_for(lock, timeout, [this] { return !syncOutputQueue_.empty(); });
616 }
617 }
618 if (syncOutputQueue_.empty()) {
619 AVCODEC_LOGW("output RequestBuffer wait:%{public}" PRId64 " us timeout", timeoutUs);
620 return AVCS_ERR_TRY_AGAIN;
621 }
622 std::shared_ptr<OutputInfo> out = syncOutputQueue_.front();
623 syncOutputQueue_.pop();
624 if (out->type_ == OUTPUT_STREAM_CHANGED) {
625 return AVCS_ERR_STREAM_CHANGED;
626 }
627 std::lock_guard mapLock(outputMutex_);
628 *index = indexOutput_;
629 outputBufferObjMap_[indexOutput_] = out->buffer_;
630 indexOutput_ = (indexOutput_ >= MAX_INDEX) ? 0 : ++indexOutput_;
631 return AVCS_ERR_OK;
632 }
633
GetOutputBuffer(uint32_t index)634 std::shared_ptr<AVBuffer> AVCodecAudioCodecImpl::GetOutputBuffer(uint32_t index)
635 {
636 if (!isSyncMode_.load() || !isRunning_.load()) {
637 AVCODEC_LOGE("not start or not in sync mode, %{public}d, %{public}d", isSyncMode_.load(), isRunning_.load());
638 return nullptr;
639 }
640 AVCODEC_SYNC_TRACE;
641 std::lock_guard mapLock(outputMutex_);
642 if (outputBufferObjMap_.find(index) == outputBufferObjMap_.end()) {
643 AVCODEC_LOGE("not find output buffer index:%{public}d", index);
644 return nullptr;
645 }
646 return outputBufferObjMap_[index];
647 }
648
AVCodecInnerCallback(AVCodecAudioCodecImpl * impl)649 AVCodecAudioCodecImpl::AVCodecInnerCallback::AVCodecInnerCallback(AVCodecAudioCodecImpl *impl) : impl_(impl) {}
650
OnError(AVCodecErrorType errorType,int32_t errorCode)651 void AVCodecAudioCodecImpl::AVCodecInnerCallback::OnError(AVCodecErrorType errorType, int32_t errorCode)
652 {
653 if (impl_->callback_) {
654 impl_->callback_->OnError(errorType, errorCode);
655 }
656 }
657
OnOutputFormatChanged(const Format & format)658 void AVCodecAudioCodecImpl::AVCodecInnerCallback::OnOutputFormatChanged(const Format &format)
659 {
660 if (!impl_->isSyncMode_.load() && impl_->callback_) {
661 impl_->callback_->OnOutputFormatChanged(format);
662 }
663 if (!impl_->isSyncMode_.load()) {
664 AVCODEC_LOGE("receive format changed, but impl callback is nullptr");
665 return;
666 }
667 AVCODEC_SYNC_TRACE;
668 std::lock_guard lock(impl_->syncOutputMutex_);
669 std::shared_ptr<OutputInfo> out = std::make_shared<OutputInfo>(format);
670 impl_->syncOutputQueue_.push(out);
671 impl_->syncOutCond_.notify_all();
672 }
673
OnInputBufferAvailable(uint32_t index,std::shared_ptr<AVBuffer> buffer)674 void AVCodecAudioCodecImpl::AVCodecInnerCallback::OnInputBufferAvailable(uint32_t index,
675 std::shared_ptr<AVBuffer> buffer)
676 {
677 (void)index;
678 (void)buffer;
679 }
680
OnOutputBufferAvailable(uint32_t index,std::shared_ptr<AVBuffer> buffer)681 void AVCodecAudioCodecImpl::AVCodecInnerCallback::OnOutputBufferAvailable(uint32_t index,
682 std::shared_ptr<AVBuffer> buffer)
683 {
684 std::shared_ptr<AVBuffer> outputBuffer;
685 if (!impl_->isSyncMode_.load()) {
686 if (impl_->callback_) {
687 Media::Status ret = impl_->implConsumer_->AcquireBuffer(outputBuffer);
688 if (ret != Media::Status::OK) {
689 AVCODEC_LOGE("Consumer AcquireBuffer fail,ret=%{public}d", ret);
690 return;
691 }
692 {
693 std::unique_lock lock(impl_->outputMutex_);
694 impl_->outputBufferObjMap_[impl_->indexOutput_] = outputBuffer;
695 }
696 impl_->callback_->OnOutputBufferAvailable(impl_->indexOutput_, outputBuffer);
697 impl_->indexOutput_ = (impl_->indexOutput_ >= MAX_INDEX) ? 0 : ++impl_->indexOutput_;
698 }
699 return;
700 }
701
702 AVCODEC_SYNC_TRACE;
703 Media::Status ret = impl_->implConsumer_->AcquireBuffer(outputBuffer);
704 if (ret != Media::Status::OK) {
705 AVCODEC_LOGE("In sync mode Consumer AcquireBuffer fail,ret=%{public}d", ret);
706 return;
707 }
708 std::lock_guard lock(impl_->syncOutputMutex_);
709 std::shared_ptr<OutputInfo> out = std::make_shared<OutputInfo>(outputBuffer);
710 impl_->syncOutputQueue_.push(out);
711 impl_->syncOutCond_.notify_all();
712 }
713
714 } // namespace MediaAVCodec
715 } // namespace OHOS
716