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