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