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