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