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