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