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