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