• 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_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 
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 
331     auto outBuffer = worker_->GetOutputBuffer();
332     if (outBuffer == nullptr) {
333         AVCODEC_LOGE("release buffer failed,index=%{public}u error", index);
334         return AVCodecServiceErrCode::AVCS_ERR_NO_MEMORY;
335     }
336     bool result = outBuffer->ReleaseBuffer(index);
337     if (!result) {
338         AVCODEC_LOGE("release buffer failed");
339         return AVCodecServiceErrCode::AVCS_ERR_NO_MEMORY;
340     }
341 
342     return AVCodecServiceErrCode::AVCS_ERR_OK;
343 }
344 
doInit()345 int32_t AudioCodecAdapter::doInit()
346 {
347     AVCODEC_SYNC_TRACE;
348     if (name_.empty()) {
349         state_ = CodecState::RELEASED;
350         AVCODEC_LOGE("doInit failed, because name is empty");
351         return AVCodecServiceErrCode::AVCS_ERR_UNKNOWN;
352     }
353 
354     AVCODEC_LOGD("adapter doInit, codec name:%{public}s", name_.data());
355     audioCodec = AudioBaseCodec::make_sharePtr(name_);
356     if (audioCodec == nullptr) {
357         state_ = CodecState::RELEASED;
358         AVCODEC_LOGE("Initlize failed, because create codec failed. name: %{public}s.", name_.data());
359         return AVCodecServiceErrCode::AVCS_ERR_UNKNOWN;
360     }
361     AVCODEC_LOGD("adapter doInit, state from %{public}s to INITIALIZED",
362         stateToString(state_).data());
363     state_ = CodecState::INITIALIZED;
364     return AVCodecServiceErrCode::AVCS_ERR_OK;
365 }
366 
doConfigure(const Format & format)367 int32_t AudioCodecAdapter::doConfigure(const Format &format)
368 {
369     AVCODEC_SYNC_TRACE;
370     if (state_ != CodecState::INITIALIZED) {
371         AVCODEC_LOGE("adapter configure failed because state is incorrect,state:%{public}d.",
372                      static_cast<int>(state_.load()));
373         state_ = CodecState::RELEASED;
374         AVCODEC_LOGE("state_=%{public}s", stateToString(state_).data());
375         return AVCodecServiceErrCode::AVCS_ERR_INVALID_STATE;
376     }
377     (void)mallopt(M_SET_THREAD_CACHE, M_THREAD_CACHE_DISABLE);
378     (void)mallopt(M_DELAYED_FREE, M_DELAYED_FREE_DISABLE);
379     int32_t ret = audioCodec->Init(format);
380     if (ret != AVCodecServiceErrCode::AVCS_ERR_OK) {
381         AVCODEC_LOGE("configure failed, because codec init failed,error:%{public}d.", static_cast<int>(ret));
382         state_ = CodecState::RELEASED;
383         return ret;
384     }
385     return ret;
386 }
387 
doStart()388 int32_t AudioCodecAdapter::doStart()
389 {
390     AVCODEC_SYNC_TRACE;
391     if (state_ != CodecState::STARTING) {
392         AVCODEC_LOGE("doStart failed, state = %{public}s", stateToString(state_).data());
393         return AVCodecServiceErrCode::AVCS_ERR_INVALID_STATE;
394     }
395 
396     AVCODEC_LOGD("adapter doStart, state from %{public}s to RUNNING", stateToString(state_).data());
397     state_ = CodecState::RUNNING;
398     worker_ = std::make_shared<AudioCodecWorker>(audioCodec, callback_);
399     worker_->Start();
400     return AVCodecServiceErrCode::AVCS_ERR_OK;
401 }
402 
doResume()403 int32_t AudioCodecAdapter::doResume()
404 {
405     AVCODEC_SYNC_TRACE;
406     AVCODEC_LOGD("adapter doResume, state from %{public}s to RESUMING", stateToString(state_).data());
407     state_ = CodecState::RESUMING;
408     worker_->Resume();
409     AVCODEC_LOGD("adapter doResume, state from %{public}s to RUNNING", stateToString(state_).data());
410     state_ = CodecState::RUNNING;
411     return AVCodecServiceErrCode::AVCS_ERR_OK;
412 }
413 
doStop()414 int32_t AudioCodecAdapter::doStop()
415 {
416     AVCODEC_SYNC_TRACE;
417     if (state_ == CodecState::RELEASING) {
418         AVCODEC_LOGW("adapter doStop, state is already release, state_=%{public}s .", stateToString(state_).data());
419         return AVCodecServiceErrCode::AVCS_ERR_OK;
420     }
421 
422     if (state_ != CodecState::STOPPING) {
423         AVCODEC_LOGE("doStop failed, state =%{public}s", stateToString(state_).data());
424         return AVCodecServiceErrCode::AVCS_ERR_INVALID_STATE;
425     }
426     worker_->Stop();
427     int32_t status = audioCodec->Flush();
428     if (status != AVCodecServiceErrCode::AVCS_ERR_OK) {
429         AVCODEC_LOGE("flush status=%{public}d", static_cast<int>(status));
430         return AVCodecServiceErrCode::AVCS_ERR_INVALID_STATE;
431     }
432     return AVCodecServiceErrCode::AVCS_ERR_OK;
433 }
434 
doFlush()435 int32_t AudioCodecAdapter::doFlush()
436 {
437     AVCODEC_SYNC_TRACE;
438     if (state_ != CodecState::FLUSHING) {
439         AVCODEC_LOGE("doFlush failed, state_=%{public}s", stateToString(state_).data());
440         return AVCodecServiceErrCode::AVCS_ERR_INVALID_STATE;
441     }
442     worker_->Pause();
443     int32_t status = audioCodec->Flush();
444     state_ = CodecState::FLUSHED;
445     if (status != AVCodecServiceErrCode::AVCS_ERR_OK) {
446         AVCODEC_LOGE("status=%{public}d", static_cast<int>(status));
447         return AVCodecServiceErrCode::AVCS_ERR_INVALID_STATE;
448     }
449     return AVCodecServiceErrCode::AVCS_ERR_OK;
450 }
451 
doRelease()452 int32_t AudioCodecAdapter::doRelease()
453 {
454     AVCODEC_SYNC_TRACE;
455     if (state_ == CodecState::RELEASED) {
456         AVCODEC_LOGW("adapter doRelease, state already released, state_=%{public}s.", stateToString(state_).data());
457         return AVCodecServiceErrCode::AVCS_ERR_OK;
458     }
459     if (worker_ != nullptr) {
460         worker_->Release();
461         worker_.reset();
462         worker_ = nullptr;
463     }
464     if (audioCodec != nullptr) {
465         audioCodec->Release();
466         audioCodec.reset();
467         audioCodec = nullptr;
468     }
469     AVCODEC_LOGD_LIMIT(LOGD_FREQUENCY, "adapter doRelease, state from %{public}s to RELEASED",
470         stateToString(state_).data());
471     state_ = CodecState::RELEASED;
472     return AVCodecServiceErrCode::AVCS_ERR_OK;
473 }
474 
stateToString(CodecState state)475 std::string_view AudioCodecAdapter::stateToString(CodecState state)
476 {
477     std::map<CodecState, std::string_view> stateStrMap = {
478         {CodecState::RELEASED, " RELEASED"},         {CodecState::INITIALIZED, " INITIALIZED"},
479         {CodecState::FLUSHED, " FLUSHED"},           {CodecState::RUNNING, " RUNNING"},
480         {CodecState::INITIALIZING, " INITIALIZING"}, {CodecState::STARTING, " STARTING"},
481         {CodecState::STOPPING, " STOPPING"},         {CodecState::FLUSHING, " FLUSHING"},
482         {CodecState::RESUMING, " RESUMING"},         {CodecState::RELEASING, " RELEASING"},
483     };
484     return stateStrMap[state];
485 }
486 } // namespace MediaAVCodec
487 } // namespace OHOS