• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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