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