• 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 "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