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 "audio_codec_adapter.h"
17 #include <malloc.h>
18 #include "avcodec_trace.h"
19 #include "avcodec_errors.h"
20 #include "avcodec_log.h"
21 #include "media_description.h"
22 
23 namespace {
24 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_AUDIO, "AvCodec-AudioCodecAdapter"};
25 constexpr uint8_t LOGD_FREQUENCY = 5;
26 } // namespace
27 
28 namespace OHOS {
29 namespace MediaAVCodec {
AudioCodecAdapter(const std::string & name)30 AudioCodecAdapter::AudioCodecAdapter(const std::string &name) : state_(CodecState::RELEASED), name_(name) {}
31 
~AudioCodecAdapter()32 AudioCodecAdapter::~AudioCodecAdapter()
33 {
34     if (worker_) {
35         worker_->Release();
36         worker_.reset();
37         worker_ = nullptr;
38     }
39     callback_ = nullptr;
40     if (audioCodec) {
41         audioCodec->Release();
42         audioCodec.reset();
43         audioCodec = nullptr;
44     }
45     state_ = CodecState::RELEASED;
46     (void)mallopt(M_FLUSH_THREAD_CACHE, 0);
47 }
48 
SetCallback(const std::shared_ptr<AVCodecCallback> & callback)49 int32_t AudioCodecAdapter::SetCallback(const std::shared_ptr<AVCodecCallback> &callback)
50 {
51     AVCODEC_SYNC_TRACE;
52     if (state_ != CodecState::RELEASED && state_ != CodecState::INITIALIZED && state_ != CodecState::INITIALIZING) {
53         AVCODEC_LOGE("SetCallback failed, state = %{public}s .", stateToString(state_).data());
54         return AVCodecServiceErrCode::AVCS_ERR_INVALID_STATE;
55     }
56     if (!callback) {
57         AVCODEC_LOGE("SetCallback failed, callback is nullptr.");
58         return AVCodecServiceErrCode::AVCS_ERR_INVALID_VAL;
59     }
60     callback_ = callback;
61     AVCODEC_LOGD("SetCallback success");
62     return AVCodecServiceErrCode::AVCS_ERR_OK;
63 }
64 
Init(Media::Meta & callerInfo)65 int32_t AudioCodecAdapter::Init(Media::Meta &callerInfo)
66 {
67     if (state_ != CodecState::RELEASED) {
68         AVCODEC_LOGE("Configure failed, state = %{public}s .", stateToString(state_).data());
69         return AVCodecServiceErrCode::AVCS_ERR_INVALID_STATE;
70     }
71 
72     state_ = CodecState::INITIALIZING;
73     auto ret = doInit();
74     if (ret != AVCodecServiceErrCode::AVCS_ERR_OK) {
75         return ret;
76     }
77 
78     if (state_ != CodecState::INITIALIZED) {
79         AVCODEC_LOGE("Configure failed, state =%{public}s", stateToString(state_).data());
80         return AVCodecServiceErrCode::AVCS_ERR_INVALID_STATE;
81     }
82     return AVCodecServiceErrCode::AVCS_ERR_OK;
83 }
84 
Configure(const Format & format)85 int32_t AudioCodecAdapter::Configure(const Format &format)
86 {
87     AVCODEC_SYNC_TRACE;
88     if (!format.ContainKey(MediaDescriptionKey::MD_KEY_CHANNEL_COUNT)) {
89         AVCODEC_LOGE("Configure failed, missing channel count key in format.");
90         return AVCodecServiceErrCode::AVCS_ERR_CONFIGURE_MISMATCH_CHANNEL_COUNT;
91     }
92 
93     if (!format.ContainKey(MediaDescriptionKey::MD_KEY_SAMPLE_RATE)) {
94         AVCODEC_LOGE("Configure failed,missing sample rate key in format.");
95         return AVCodecServiceErrCode::AVCS_ERR_MISMATCH_SAMPLE_RATE;
96     }
97 
98     int32_t ret = doConfigure(format);
99     AVCODEC_LOGD("Configure exit");
100     return ret;
101 }
102 
Start()103 int32_t AudioCodecAdapter::Start()
104 {
105     AVCODEC_LOGD("Start enter");
106     if (!callback_) {
107         AVCODEC_LOGE("adapter start error, callback not initialized .");
108         return AVCodecServiceErrCode::AVCS_ERR_UNKNOWN;
109     }
110 
111     if (!audioCodec) {
112         AVCODEC_LOGE("adapter start error, audio codec not initialized .");
113         return AVCodecServiceErrCode::AVCS_ERR_UNKNOWN;
114     }
115 
116     if (state_ == CodecState::FLUSHED) {
117         AVCODEC_LOGI("Start, doResume");
118         return doResume();
119     }
120 
121     if (state_ != CodecState::CONFIGURED) {
122         AVCODEC_LOGE("Start is incorrect, state = %{public}s .", stateToString(state_).data());
123         return AVCodecServiceErrCode::AVCS_ERR_INVALID_STATE;
124     }
125     AVCODEC_LOGI("state %{public}s to STARTING then RUNNING", stateToString(state_).data());
126     state_ = CodecState::STARTING;
127     auto ret = doStart();
128     return ret;
129 }
130 
Stop()131 int32_t AudioCodecAdapter::Stop()
132 {
133     AVCODEC_SYNC_TRACE;
134     AVCODEC_LOGD("stop enter");
135     if (!callback_) {
136         AVCODEC_LOGE("Stop failed, call back not initialized.");
137         return AVCodecServiceErrCode::AVCS_ERR_UNKNOWN;
138     }
139     if (state_ == CodecState::INITIALIZED || state_ == CodecState::RELEASED || state_ == CodecState::STOPPING ||
140         state_ == CodecState::RELEASING || state_ == CodecState::CONFIGURED) {
141         AVCODEC_LOGD("Stop, state_=%{public}s", stateToString(state_).data());
142         return AVCodecServiceErrCode::AVCS_ERR_OK;
143     }
144     state_ = CodecState::STOPPING;
145     auto ret = doStop();
146     AVCODEC_LOGI("state %{public}s to INITIALIZED", stateToString(state_).data());
147     state_ = CodecState::CONFIGURED;
148     return ret;
149 }
150 
Flush()151 int32_t AudioCodecAdapter::Flush()
152 {
153     AVCODEC_SYNC_TRACE;
154     AVCODEC_LOGD("adapter Flush enter");
155     if (!callback_) {
156         AVCODEC_LOGE("adapter flush error, call back not initialized .");
157         return AVCodecServiceErrCode::AVCS_ERR_UNKNOWN;
158     }
159     if (state_ == CodecState::FLUSHED) {
160         AVCODEC_LOGW("Flush, state is already flushed, state_=%{public}s .", stateToString(state_).data());
161         return AVCodecServiceErrCode::AVCS_ERR_OK;
162     }
163     if (state_ != CodecState::RUNNING) {
164         callback_->OnError(AVCodecErrorType::AVCODEC_ERROR_INTERNAL, AVCodecServiceErrCode::AVCS_ERR_INVALID_STATE);
165         AVCODEC_LOGE("Flush failed, state =%{public}s", stateToString(state_).data());
166         return AVCodecServiceErrCode::AVCS_ERR_INVALID_STATE;
167     }
168     AVCODEC_LOGI("state %{public}s to FLUSHING then FLUSHED", stateToString(state_).data());
169     state_ = CodecState::FLUSHING;
170     auto ret = doFlush();
171     return ret;
172 }
173 
Reset()174 int32_t AudioCodecAdapter::Reset()
175 {
176     AVCODEC_SYNC_TRACE;
177     AVCODEC_LOGD("adapter Reset enter");
178     int32_t status = AVCodecServiceErrCode::AVCS_ERR_OK;
179     if (worker_) {
180         worker_->Release();
181         worker_.reset();
182         worker_ = nullptr;
183     }
184     if (audioCodec) {
185         status = audioCodec->Reset();
186         AVCODEC_LOGI("state %{public}s to INITIALIZED",  stateToString(state_).data());
187         state_ = CodecState::INITIALIZED;
188     } else {
189         auto ret = doInit();
190         CHECK_AND_RETURN_RET_LOG(ret == AVCodecServiceErrCode::AVCS_ERR_OK, ret, "unknown error.");
191     }
192     return status;
193 }
194 
Release()195 int32_t AudioCodecAdapter::Release()
196 {
197     AVCODEC_SYNC_TRACE;
198     AVCODEC_LOGD("adapter Release enter");
199     if (state_ == CodecState::RELEASED || state_ == CodecState::RELEASING) {
200         AVCODEC_LOGW("adapter Release, state isnot completely correct, state =%{public}s .",
201                      stateToString(state_).data());
202         return AVCodecServiceErrCode::AVCS_ERR_OK;
203     }
204 
205     if (state_ == CodecState::INITIALIZING) {
206         AVCODEC_LOGW("adapter Release, state isnot completely correct, state =%{public}s .",
207                      stateToString(state_).data());
208         state_ = CodecState::RELEASING;
209         return AVCodecServiceErrCode::AVCS_ERR_OK;
210     }
211 
212     if (state_ == CodecState::STARTING || state_ == CodecState::RUNNING || state_ == CodecState::STOPPING) {
213         AVCODEC_LOGE("adapter Release, state is running, state =%{public}s .", stateToString(state_).data());
214     }
215     AVCODEC_LOGI("state %{public}s to RELEASING then RELEASED", stateToString(state_).data());
216     state_ = CodecState::RELEASING;
217     auto ret = doRelease();
218     return ret;
219 }
220 
NotifyEos()221 int32_t AudioCodecAdapter::NotifyEos()
222 {
223     AVCODEC_SYNC_TRACE;
224     Flush();
225     return AVCodecServiceErrCode::AVCS_ERR_OK;
226 }
227 
SetParameter(const Format & format)228 int32_t AudioCodecAdapter::SetParameter(const Format &format)
229 {
230     AVCODEC_SYNC_TRACE;
231     (void)format;
232     return AVCodecServiceErrCode::AVCS_ERR_OK;
233 }
234 
GetOutputFormat(Format & format)235 int32_t AudioCodecAdapter::GetOutputFormat(Format &format)
236 {
237     AVCODEC_SYNC_TRACE;
238     if (audioCodec == nullptr) {
239         AVCODEC_LOGE("Codec not init or nullptr");
240         return AVCodecServiceErrCode::AVCS_ERR_NO_MEMORY;
241     }
242     format = audioCodec->GetFormat();
243     if (!format.ContainKey(MediaDescriptionKey::MD_KEY_CODEC_NAME)) {
244         format.PutStringValue(MediaDescriptionKey::MD_KEY_CODEC_NAME, name_);
245     }
246     return AVCodecServiceErrCode::AVCS_ERR_OK;
247 }
248 
QueueInputBuffer(uint32_t index,const AVCodecBufferInfo & info,AVCodecBufferFlag flag)249 int32_t AudioCodecAdapter::QueueInputBuffer(uint32_t index, const AVCodecBufferInfo &info, AVCodecBufferFlag flag)
250 {
251     AVCODEC_SYNC_TRACE;
252     AVCODEC_LOGD_LIMIT(LOGD_FREQUENCY, "adapter %{public}s queue buffer enter,index:%{public}u",
253         name_.data(), index);
254     if (!audioCodec) {
255         AVCODEC_LOGE("adapter QueueInputBuffer error, audio codec not initialized .");
256         return AVCodecServiceErrCode::AVCS_ERR_UNKNOWN;
257     }
258     if (!callback_) {
259         AVCODEC_LOGE("adapter queue input buffer error,index:%{public}u, call back not initialized .", index);
260         return AVCodecServiceErrCode::AVCS_ERR_UNKNOWN;
261     }
262     if (info.size < 0) {
263         AVCODEC_LOGE("size could not less than 0,size value:%{public}d.", info.size);
264         return AVCodecServiceErrCode::AVCS_ERR_INVALID_VAL;
265     }
266 
267     if (info.offset < 0) {
268         AVCODEC_LOGE("offset could not less than 0,offset value:%{public}d.", info.offset);
269         return AVCodecServiceErrCode::AVCS_ERR_INVALID_VAL;
270     }
271     auto result = worker_->GetInputBufferInfo(index);
272     if (result == nullptr) {
273         AVCODEC_LOGE("getMemory failed");
274         return AVCodecServiceErrCode::AVCS_ERR_NO_MEMORY;
275     }
276 
277     if (result->GetStatus() != BufferStatus::OWEN_BY_CLIENT) {
278         AVCODEC_LOGE("GetStatus failed");
279         return AVCodecServiceErrCode::AVCS_ERR_UNKNOWN;
280     }
281 
282     if (result->CheckIsUsing()) {
283         AVCODEC_LOGE("input buffer now is already QueueInputBuffer,please don't do it again.");
284         return AVCodecServiceErrCode::AVCS_ERR_UNKNOWN;
285     }
286 
287     if ((uint32_t) info.size > result->GetBufferSize()) {
288         AVCODEC_LOGE("Size could not lager than buffersize, please check input size %{public}d.", info.size);
289         return AVCodecServiceErrCode::AVCS_ERR_INVALID_VAL;
290     }
291 
292     result->SetUsing();
293     result->SetBufferAttr(info);
294     if (flag == AVCodecBufferFlag::AVCODEC_BUFFER_FLAG_EOS) {
295         result->SetEos(true);
296     }
297     worker_->PushInputData(index);
298     return AVCodecServiceErrCode::AVCS_ERR_OK;
299 }
300 
ReleaseOutputBuffer(uint32_t index)301 int32_t AudioCodecAdapter::ReleaseOutputBuffer(uint32_t index)
302 {
303     AVCODEC_SYNC_TRACE;
304     AVCODEC_LOGD_LIMIT(LOGD_FREQUENCY, "adapter %{public}s release buffer,index:%{public}u", name_.data(), index);
305     if (!callback_) {
306         AVCODEC_LOGE("adapter release buffer error,index:%{public}u, call back not initialized .", index);
307         return AVCodecServiceErrCode::AVCS_ERR_UNKNOWN;
308     }
309     if (!audioCodec) {
310         AVCODEC_LOGE("adapter release buffer error, audio codec not initialized .");
311         return AVCodecServiceErrCode::AVCS_ERR_UNKNOWN;
312     }
313 
314     auto outBufferInfo = worker_->GetOutputBufferInfo(index);
315     if (outBufferInfo == nullptr) {
316         AVCODEC_LOGE("release buffer failed,index=%{public}u error", index);
317         return AVCodecServiceErrCode::AVCS_ERR_NO_MEMORY;
318     }
319 
320     if (outBufferInfo->GetStatus() != BufferStatus::OWEN_BY_CLIENT) {
321         AVCODEC_LOGE("output buffer status now is IDLE, could not released");
322         return AVCodecServiceErrCode::AVCS_ERR_UNKNOWN;
323     }
324 
325     auto outBuffer = worker_->GetOutputBuffer();
326     if (outBuffer == nullptr) {
327         AVCODEC_LOGE("release buffer failed,index=%{public}u error", index);
328         return AVCodecServiceErrCode::AVCS_ERR_NO_MEMORY;
329     }
330     bool result = outBuffer->ReleaseBuffer(index);
331     if (!result) {
332         AVCODEC_LOGE("release buffer failed");
333         return AVCodecServiceErrCode::AVCS_ERR_NO_MEMORY;
334     }
335 
336     return AVCodecServiceErrCode::AVCS_ERR_OK;
337 }
338 
doInit()339 int32_t AudioCodecAdapter::doInit()
340 {
341     AVCODEC_SYNC_TRACE;
342     if (name_.empty()) {
343         state_ = CodecState::RELEASED;
344         AVCODEC_LOGE("doInit failed, because name is empty");
345         return AVCodecServiceErrCode::AVCS_ERR_UNKNOWN;
346     }
347 
348     AVCODEC_LOGD("adapter doInit, codec name:%{public}s", name_.data());
349     audioCodec = AudioBaseCodec::make_sharePtr(name_);
350     if (audioCodec == nullptr) {
351         state_ = CodecState::RELEASED;
352         AVCODEC_LOGE("Initlize failed, because create codec failed. name: %{public}s.", name_.data());
353         return AVCodecServiceErrCode::AVCS_ERR_UNKNOWN;
354     }
355     AVCODEC_LOGI("adapter doInit, state from %{public}s to INITIALIZED",
356         stateToString(state_).data());
357     state_ = CodecState::INITIALIZED;
358     return AVCodecServiceErrCode::AVCS_ERR_OK;
359 }
360 
doConfigure(const Format & format)361 int32_t AudioCodecAdapter::doConfigure(const Format &format)
362 {
363     AVCODEC_SYNC_TRACE;
364     if (state_ != CodecState::INITIALIZED) {
365         AVCODEC_LOGE("adapter configure failed because state is incorrect,state:%{public}d.",
366                      static_cast<int>(state_.load()));
367         state_ = CodecState::RELEASED;
368         AVCODEC_LOGE("state_=%{public}s", stateToString(state_).data());
369         return AVCodecServiceErrCode::AVCS_ERR_INVALID_STATE;
370     }
371     (void)mallopt(M_SET_THREAD_CACHE, M_THREAD_CACHE_DISABLE);
372     (void)mallopt(M_DELAYED_FREE, M_DELAYED_FREE_DISABLE);
373     int32_t ret = audioCodec->Init(format);
374     if (ret != AVCodecServiceErrCode::AVCS_ERR_OK) {
375         AVCODEC_LOGE("configure failed, because codec init failed,error:%{public}d.", static_cast<int>(ret));
376         return ret;
377     }
378     state_ = CodecState::CONFIGURED;
379     return ret;
380 }
381 
doStart()382 int32_t AudioCodecAdapter::doStart()
383 {
384     AVCODEC_SYNC_TRACE;
385     if (state_ != CodecState::STARTING) {
386         AVCODEC_LOGE("doStart failed, state = %{public}s", stateToString(state_).data());
387         return AVCodecServiceErrCode::AVCS_ERR_INVALID_STATE;
388     }
389 
390     AVCODEC_LOGD("adapter doStart, state from %{public}s to RUNNING", stateToString(state_).data());
391     state_ = CodecState::RUNNING;
392     worker_ = std::make_shared<AudioCodecWorker>(audioCodec, callback_);
393     worker_->Start();
394     return AVCodecServiceErrCode::AVCS_ERR_OK;
395 }
396 
doResume()397 int32_t AudioCodecAdapter::doResume()
398 {
399     AVCODEC_SYNC_TRACE;
400     AVCODEC_LOGD("adapter doResume, state from %{public}s to RESUMING", stateToString(state_).data());
401     state_ = CodecState::RESUMING;
402     worker_->Resume();
403     AVCODEC_LOGD("adapter doResume, state from %{public}s to RUNNING", stateToString(state_).data());
404     state_ = CodecState::RUNNING;
405     return AVCodecServiceErrCode::AVCS_ERR_OK;
406 }
407 
doStop()408 int32_t AudioCodecAdapter::doStop()
409 {
410     AVCODEC_SYNC_TRACE;
411     if (state_ == CodecState::RELEASING) {
412         AVCODEC_LOGW("adapter doStop, state is already release, state_=%{public}s .", stateToString(state_).data());
413         return AVCodecServiceErrCode::AVCS_ERR_OK;
414     }
415 
416     if (state_ != CodecState::STOPPING) {
417         AVCODEC_LOGE("doStop failed, state =%{public}s", stateToString(state_).data());
418         return AVCodecServiceErrCode::AVCS_ERR_INVALID_STATE;
419     }
420     worker_->Stop();
421     int32_t status = audioCodec->Flush();
422     if (status != AVCodecServiceErrCode::AVCS_ERR_OK) {
423         AVCODEC_LOGE("flush status=%{public}d", static_cast<int>(status));
424         return AVCodecServiceErrCode::AVCS_ERR_INVALID_STATE;
425     }
426     return AVCodecServiceErrCode::AVCS_ERR_OK;
427 }
428 
doFlush()429 int32_t AudioCodecAdapter::doFlush()
430 {
431     AVCODEC_SYNC_TRACE;
432     if (state_ != CodecState::FLUSHING) {
433         AVCODEC_LOGE("doFlush failed, state_=%{public}s", stateToString(state_).data());
434         return AVCodecServiceErrCode::AVCS_ERR_INVALID_STATE;
435     }
436     worker_->Pause();
437     int32_t status = audioCodec->Flush();
438     state_ = CodecState::FLUSHED;
439     if (status != AVCodecServiceErrCode::AVCS_ERR_OK) {
440         AVCODEC_LOGE("status=%{public}d", static_cast<int>(status));
441         return AVCodecServiceErrCode::AVCS_ERR_INVALID_STATE;
442     }
443     return AVCodecServiceErrCode::AVCS_ERR_OK;
444 }
445 
doRelease()446 int32_t AudioCodecAdapter::doRelease()
447 {
448     AVCODEC_SYNC_TRACE;
449     if (state_ == CodecState::RELEASED) {
450         AVCODEC_LOGW("adapter doRelease, state already released, state_=%{public}s.", stateToString(state_).data());
451         return AVCodecServiceErrCode::AVCS_ERR_OK;
452     }
453     if (worker_ != nullptr) {
454         worker_->Release();
455         worker_.reset();
456         worker_ = nullptr;
457     }
458     if (audioCodec != nullptr) {
459         audioCodec->Release();
460         audioCodec.reset();
461         audioCodec = nullptr;
462     }
463     AVCODEC_LOGD_LIMIT(LOGD_FREQUENCY, "adapter doRelease, state from %{public}s to RELEASED",
464         stateToString(state_).data());
465     state_ = CodecState::RELEASED;
466     return AVCodecServiceErrCode::AVCS_ERR_OK;
467 }
468 
stateToString(CodecState state)469 std::string_view AudioCodecAdapter::stateToString(CodecState state)
470 {
471     std::map<CodecState, std::string_view> stateStrMap = {
472         {CodecState::RELEASED, " RELEASED"},         {CodecState::INITIALIZED, " INITIALIZED"},
473         {CodecState::FLUSHED, " FLUSHED"},           {CodecState::RUNNING, " RUNNING"},
474         {CodecState::INITIALIZING, " INITIALIZING"}, {CodecState::STARTING, " STARTING"},
475         {CodecState::STOPPING, " STOPPING"},         {CodecState::FLUSHING, " FLUSHING"},
476         {CodecState::RESUMING, " RESUMING"},         {CodecState::RELEASING, " RELEASING"},
477         {CodecState::CONFIGURED, " CONFIGURED"},
478     };
479     return stateStrMap[state];
480 }
481 } // namespace MediaAVCodec
482 } // namespace OHOS