1 /*
2 * Copyright (c) 2023-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 #include "media_codec.h"
16 #include <shared_mutex>
17 #include "common/log.h"
18 #include "osal/task/autolock.h"
19 #include "plugin/plugin_manager_v2.h"
20 #include "osal/utils/dump_buffer.h"
21 #include "avcodec_trace.h"
22 #include "bundle_mgr_interface.h"
23 #include "iservice_registry.h"
24 #include "system_ability_definition.h"
25
26 namespace {
27 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_DOMAIN_AUDIO, "MediaCodec" };
28 const std::string INPUT_BUFFER_QUEUE_NAME = "MediaCodecInputBufferQueue";
29 constexpr int32_t DEFAULT_BUFFER_NUM = 8;
30 constexpr int32_t TIME_OUT_MS = 50;
31 constexpr uint32_t API_SUPPORT_AUDIO_FORMAT_CHANGED = 15;
32 constexpr uint32_t INVALID_API_VERSION = 0;
33 constexpr uint32_t API_VERSION_MOD = 1000;
34 const std::string DUMP_PARAM = "a";
35 const std::string DUMP_FILE_NAME = "player_audio_decoder_output.pcm";
36 } // namespace
37
38 namespace OHOS {
39 namespace Media {
40 class InputBufferAvailableListener : public IConsumerListener {
41 public:
InputBufferAvailableListener(MediaCodec * mediaCodec)42 explicit InputBufferAvailableListener(MediaCodec *mediaCodec)
43 {
44 mediaCodec_ = mediaCodec;
45 }
46
OnBufferAvailable()47 void OnBufferAvailable() override
48 {
49 mediaCodec_->ProcessInputBuffer();
50 }
51
52 private:
53 MediaCodec *mediaCodec_;
54 };
55
MediaCodec()56 MediaCodec::MediaCodec()
57 : codecPlugin_(nullptr),
58 inputBufferQueue_(nullptr),
59 inputBufferQueueProducer_(nullptr),
60 inputBufferQueueConsumer_(nullptr),
61 outputBufferQueueProducer_(nullptr),
62 isEncoder_(false),
63 isSurfaceMode_(false),
64 isBufferMode_(false),
65 outputBufferCapacity_(0),
66 state_(CodecState::UNINITIALIZED)
67 {
68 }
69
~MediaCodec()70 MediaCodec::~MediaCodec()
71 {
72 state_ = CodecState::UNINITIALIZED;
73 outputBufferCapacity_ = 0;
74 if (codecPlugin_) {
75 codecPlugin_ = nullptr;
76 }
77 if (inputBufferQueue_) {
78 inputBufferQueue_ = nullptr;
79 }
80 if (inputBufferQueueProducer_) {
81 inputBufferQueueProducer_ = nullptr;
82 }
83 if (inputBufferQueueConsumer_) {
84 inputBufferQueueConsumer_ = nullptr;
85 }
86 if (outputBufferQueueProducer_) {
87 outputBufferQueueProducer_ = nullptr;
88 }
89 }
90
Init(const std::string & mime,bool isEncoder)91 int32_t MediaCodec::Init(const std::string &mime, bool isEncoder)
92 {
93 AutoLock lock(stateMutex_);
94 MediaAVCodec::AVCodecTrace trace("MediaCodec::Init");
95 MEDIA_LOG_I("Init enter, mime: " PUBLIC_LOG_S, mime.c_str());
96 if (state_ != CodecState::UNINITIALIZED) {
97 MEDIA_LOG_E("Init failed, state = %{public}s .", StateToString(state_).data());
98 return (int32_t)Status::ERROR_INVALID_STATE;
99 }
100 MEDIA_LOG_I("state from %{public}s to INITIALIZING", StateToString(state_).data());
101 state_ = CodecState::INITIALIZING;
102 Plugins::PluginType type;
103 if (isEncoder) {
104 type = Plugins::PluginType::AUDIO_ENCODER;
105 } else {
106 type = Plugins::PluginType::AUDIO_DECODER;
107 }
108 codecPlugin_ = CreatePlugin(mime, type);
109 if (codecPlugin_ != nullptr) {
110 MEDIA_LOG_I("codecPlugin_->Init()");
111 auto ret = codecPlugin_->Init();
112 FALSE_RETURN_V_MSG_E(ret == Status::OK, (int32_t)ret, "pluign init failed");
113 state_ = CodecState::INITIALIZED;
114 } else {
115 MEDIA_LOG_I("createPlugin failed");
116 return (int32_t)Status::ERROR_INVALID_PARAMETER;
117 }
118 return (int32_t)Status::OK;
119 }
120
Init(const std::string & name)121 int32_t MediaCodec::Init(const std::string &name)
122 {
123 AutoLock lock(stateMutex_);
124 MEDIA_LOG_I("Init enter, name: " PUBLIC_LOG_S, name.c_str());
125 MediaAVCodec::AVCodecTrace trace("MediaCodec::Init");
126 if (state_ != CodecState::UNINITIALIZED) {
127 MEDIA_LOG_E("Init failed, state = %{public}s .", StateToString(state_).data());
128 return (int32_t)Status::ERROR_INVALID_STATE;
129 }
130 MEDIA_LOG_I("state from %{public}s to INITIALIZING", StateToString(state_).data());
131 state_ = CodecState::INITIALIZING;
132 auto plugin = Plugins::PluginManagerV2::Instance().CreatePluginByName(name);
133 FALSE_RETURN_V_MSG_E(plugin != nullptr, (int32_t)Status::ERROR_INVALID_PARAMETER, "create pluign failed");
134 codecPlugin_ = std::reinterpret_pointer_cast<Plugins::CodecPlugin>(plugin);
135 Status ret = codecPlugin_->Init();
136 FALSE_RETURN_V_MSG_E(ret == Status::OK, (int32_t)Status::ERROR_INVALID_PARAMETER, "pluign init failed");
137 state_ = CodecState::INITIALIZED;
138 return (int32_t)Status::OK;
139 }
140
CreatePlugin(const std::string & mime,Plugins::PluginType pluginType)141 std::shared_ptr<Plugins::CodecPlugin> MediaCodec::CreatePlugin(const std::string &mime, Plugins::PluginType pluginType)
142 {
143 auto plugin = Plugins::PluginManagerV2::Instance().CreatePluginByMime(pluginType, mime);
144 if (plugin == nullptr) {
145 return nullptr;
146 }
147 return std::reinterpret_pointer_cast<Plugins::CodecPlugin>(plugin);
148 }
149
Configure(const std::shared_ptr<Meta> & meta)150 int32_t MediaCodec::Configure(const std::shared_ptr<Meta> &meta)
151 {
152 MEDIA_LOG_I("MediaCodec::configure in");
153 AutoLock lock(stateMutex_);
154 MediaAVCodec::AVCodecTrace trace("MediaCodec::Configure");
155 FALSE_RETURN_V(state_ == CodecState::INITIALIZED, (int32_t)Status::ERROR_INVALID_STATE);
156 auto ret = codecPlugin_->SetParameter(meta);
157 FALSE_RETURN_V(ret == Status::OK, (int32_t)ret);
158 ret = codecPlugin_->SetDataCallback(this);
159 FALSE_RETURN_V(ret == Status::OK, (int32_t)ret);
160 state_ = CodecState::CONFIGURED;
161 return (int32_t)Status::OK;
162 }
163
SetOutputBufferQueue(const sptr<AVBufferQueueProducer> & bufferQueueProducer)164 int32_t MediaCodec::SetOutputBufferQueue(const sptr<AVBufferQueueProducer> &bufferQueueProducer)
165 {
166 AutoLock lock(stateMutex_);
167 MediaAVCodec::AVCodecTrace trace("MediaCodec::SetOutputBufferQueue");
168 FALSE_RETURN_V(state_ == CodecState::INITIALIZED || state_ == CodecState::CONFIGURED,
169 (int32_t)Status::ERROR_INVALID_STATE);
170 outputBufferQueueProducer_ = bufferQueueProducer;
171 isBufferMode_ = true;
172 return (int32_t)Status::OK;
173 }
174
SetCodecCallback(const std::shared_ptr<CodecCallback> & codecCallback)175 int32_t MediaCodec::SetCodecCallback(const std::shared_ptr<CodecCallback> &codecCallback)
176 {
177 AutoLock lock(stateMutex_);
178 FALSE_RETURN_V(state_ == CodecState::INITIALIZED || state_ == CodecState::CONFIGURED,
179 (int32_t)Status::ERROR_INVALID_STATE);
180 FALSE_RETURN_V_MSG_E(codecCallback != nullptr, (int32_t)Status::ERROR_INVALID_PARAMETER,
181 "codecCallback is nullptr");
182 codecCallback_ = codecCallback;
183 auto ret = codecPlugin_->SetDataCallback(this);
184 FALSE_RETURN_V(ret == Status::OK, (int32_t)ret);
185 return (int32_t)Status::OK;
186 }
187
SetCodecCallback(const std::shared_ptr<AudioBaseCodecCallback> & codecCallback)188 int32_t MediaCodec::SetCodecCallback(const std::shared_ptr<AudioBaseCodecCallback> &codecCallback)
189 {
190 AutoLock lock(stateMutex_);
191 FALSE_RETURN_V(state_ == CodecState::INITIALIZED || state_ == CodecState::CONFIGURED,
192 (int32_t)Status::ERROR_INVALID_STATE);
193 FALSE_RETURN_V_MSG_E(codecCallback != nullptr, (int32_t)Status::ERROR_INVALID_PARAMETER,
194 "codecCallback is nullptr");
195 mediaCodecCallback_ = codecCallback;
196 uint32_t apiVersion = GetApiVersion();
197 isSupportAudioFormatChanged_ =
198 ((apiVersion == INVALID_API_VERSION) || (apiVersion >= API_SUPPORT_AUDIO_FORMAT_CHANGED));
199 return (int32_t)Status::OK;
200 }
201
SetOutputSurface(sptr<Surface> surface)202 int32_t MediaCodec::SetOutputSurface(sptr<Surface> surface)
203 {
204 AutoLock lock(stateMutex_);
205 FALSE_RETURN_V(state_ == CodecState::INITIALIZED || state_ == CodecState::CONFIGURED,
206 (int32_t)Status::ERROR_INVALID_STATE);
207 isSurfaceMode_ = true;
208 return (int32_t)Status::OK;
209 }
210
Prepare()211 int32_t MediaCodec::Prepare()
212 {
213 MEDIA_LOG_I("Prepare enter");
214 AutoLock lock(stateMutex_);
215 MediaAVCodec::AVCodecTrace trace("MediaCodec::Prepare");
216 FALSE_RETURN_V_MSG_W(state_ != CodecState::FLUSHED, (int32_t)Status::ERROR_AGAIN,
217 "state is flushed, no need prepare");
218 FALSE_RETURN_V(state_ != CodecState::PREPARED, (int32_t)Status::OK);
219 FALSE_RETURN_V(state_ == CodecState::CONFIGURED,
220 (int32_t)Status::ERROR_INVALID_STATE);
221 if (isBufferMode_ && isSurfaceMode_) {
222 MEDIA_LOG_E("state error");
223 return (int32_t)Status::ERROR_UNKNOWN;
224 }
225 outputBufferCapacity_ = 0;
226 auto ret = (int32_t)PrepareInputBufferQueue();
227 if (ret != (int32_t)Status::OK) {
228 MEDIA_LOG_E("PrepareInputBufferQueue failed");
229 return (int32_t)ret;
230 }
231 ret = (int32_t)PrepareOutputBufferQueue();
232 if (ret != (int32_t)Status::OK) {
233 MEDIA_LOG_E("PrepareOutputBufferQueue failed");
234 return (int32_t)ret;
235 }
236 state_ = CodecState::PREPARED;
237 MEDIA_LOG_I("Prepare, ret = %{public}d", (int32_t)ret);
238 return (int32_t)Status::OK;
239 }
240
GetInputBufferQueue()241 sptr<AVBufferQueueProducer> MediaCodec::GetInputBufferQueue()
242 {
243 AutoLock lock(stateMutex_);
244 FALSE_RETURN_V(state_ == CodecState::PREPARED, sptr<AVBufferQueueProducer>());
245 if (isSurfaceMode_) {
246 return nullptr;
247 }
248 isBufferMode_ = true;
249 return inputBufferQueueProducer_;
250 }
251
GetInputSurface()252 sptr<Surface> MediaCodec::GetInputSurface()
253 {
254 AutoLock lock(stateMutex_);
255 FALSE_RETURN_V(state_ == CodecState::PREPARED, nullptr);
256 if (isBufferMode_) {
257 return nullptr;
258 }
259 isSurfaceMode_ = true;
260 return nullptr;
261 }
262
Start()263 int32_t MediaCodec::Start()
264 {
265 AutoLock lock(stateMutex_);
266 MEDIA_LOG_I("Start enter");
267 MediaAVCodec::AVCodecTrace trace("MediaCodec::Start");
268 FALSE_RETURN_V(state_ != CodecState::RUNNING, (int32_t)Status::OK);
269 FALSE_RETURN_V(state_ == CodecState::PREPARED || state_ == CodecState::FLUSHED,
270 (int32_t)Status::ERROR_INVALID_STATE);
271 state_ = CodecState::STARTING;
272 auto ret = codecPlugin_->Start();
273 FALSE_RETURN_V_MSG_E(ret == Status::OK, (int32_t)ret, "plugin start failed");
274 state_ = CodecState::RUNNING;
275 return (int32_t)ret;
276 }
277
Stop()278 int32_t MediaCodec::Stop()
279 {
280 AutoLock lock(stateMutex_);
281 MediaAVCodec::AVCodecTrace trace("MediaCodec::Stop");
282 MEDIA_LOG_I("Stop enter");
283 FALSE_RETURN_V(state_ != CodecState::PREPARED, (int32_t)Status::OK);
284 if (state_ == CodecState::UNINITIALIZED || state_ == CodecState::STOPPING || state_ == CodecState::RELEASING) {
285 MEDIA_LOG_D("Stop, state_=%{public}s", StateToString(state_).data());
286 return (int32_t)Status::OK;
287 }
288 FALSE_RETURN_V(state_ == CodecState::RUNNING || state_ == CodecState::END_OF_STREAM ||
289 state_ == CodecState::FLUSHED, (int32_t)Status::ERROR_INVALID_STATE);
290 state_ = CodecState::STOPPING;
291 auto ret = codecPlugin_->Stop();
292 MEDIA_LOG_I("codec Stop, state from %{public}s to Stop", StateToString(state_).data());
293 FALSE_RETURN_V_MSG_E(ret == Status::OK, (int32_t)ret, "plugin stop failed");
294 ClearInputBuffer();
295 state_ = CodecState::PREPARED;
296 return (int32_t)ret;
297 }
298
Flush()299 int32_t MediaCodec::Flush()
300 {
301 AutoLock lock(stateMutex_);
302 MEDIA_LOG_I("Flush enter");
303 if (state_ == CodecState::FLUSHED) {
304 MEDIA_LOG_W("Flush, state is already flushed, state_=%{public}s .", StateToString(state_).data());
305 return (int32_t)Status::OK;
306 }
307 if (state_ != CodecState::RUNNING && state_ != CodecState::END_OF_STREAM) {
308 MEDIA_LOG_E("Flush failed, state =%{public}s", StateToString(state_).data());
309 return (int32_t)Status::ERROR_INVALID_STATE;
310 }
311 MEDIA_LOG_I("Flush, state from %{public}s to FLUSHING", StateToString(state_).data());
312 state_ = CodecState::FLUSHING;
313 inputBufferQueueProducer_->Clear();
314 auto ret = codecPlugin_->Flush();
315 FALSE_RETURN_V_MSG_E(ret == Status::OK, (int32_t)ret, "plugin flush failed");
316 ClearInputBuffer();
317 state_ = CodecState::FLUSHED;
318 return (int32_t)ret;
319 }
320
Reset()321 int32_t MediaCodec::Reset()
322 {
323 AutoLock lock(stateMutex_);
324 MediaAVCodec::AVCodecTrace trace("MediaCodec::Reset");
325 MEDIA_LOG_I("Reset enter");
326 if (state_ == CodecState::UNINITIALIZED || state_ == CodecState::RELEASING) {
327 MEDIA_LOG_W("adapter reset, state is already released, state =%{public}s .", StateToString(state_).data());
328 return (int32_t)Status::OK;
329 }
330 if (state_ == CodecState::INITIALIZING) {
331 MEDIA_LOG_W("adapter reset, state is initialized, state =%{public}s .", StateToString(state_).data());
332 state_ = CodecState::INITIALIZED;
333 return (int32_t)Status::OK;
334 }
335 auto ret = codecPlugin_->Reset();
336 FALSE_RETURN_V_MSG_E(ret == Status::OK, (int32_t)ret, "plugin reset failed");
337 ClearInputBuffer();
338 state_ = CodecState::INITIALIZED;
339 return (int32_t)ret;
340 }
341
Release()342 int32_t MediaCodec::Release()
343 {
344 AutoLock lock(stateMutex_);
345 MediaAVCodec::AVCodecTrace trace("MediaCodec::Release");
346 MEDIA_LOG_I("Release enter");
347 if (state_ == CodecState::UNINITIALIZED || state_ == CodecState::RELEASING) {
348 MEDIA_LOG_W("codec Release, state isnot completely correct, state =%{public}s .", StateToString(state_).data());
349 return (int32_t)Status::OK;
350 }
351
352 if (state_ == CodecState::INITIALIZING) {
353 MEDIA_LOG_W("codec Release, state isnot completely correct, state =%{public}s .", StateToString(state_).data());
354 state_ = CodecState::RELEASING;
355 return (int32_t)Status::OK;
356 }
357 MEDIA_LOG_I("codec Release, state from %{public}s to RELEASING", StateToString(state_).data());
358 state_ = CodecState::RELEASING;
359 auto ret = codecPlugin_->Release();
360 FALSE_RETURN_V_MSG_E(ret == Status::OK, (int32_t)ret, "plugin release failed");
361 codecPlugin_ = nullptr;
362 ClearBufferQueue();
363 state_ = CodecState::UNINITIALIZED;
364 return (int32_t)ret;
365 }
366
NotifyEos()367 int32_t MediaCodec::NotifyEos()
368 {
369 AutoLock lock(stateMutex_);
370 FALSE_RETURN_V(state_ != CodecState::END_OF_STREAM, (int32_t)Status::OK);
371 FALSE_RETURN_V(state_ == CodecState::RUNNING, (int32_t)Status::ERROR_INVALID_STATE);
372 state_ = CodecState::END_OF_STREAM;
373 return (int32_t)Status::OK;
374 }
375
SetParameter(const std::shared_ptr<Meta> & parameter)376 int32_t MediaCodec::SetParameter(const std::shared_ptr<Meta> ¶meter)
377 {
378 AutoLock lock(stateMutex_);
379 FALSE_RETURN_V(parameter != nullptr, (int32_t)Status::ERROR_INVALID_PARAMETER);
380 FALSE_RETURN_V(state_ != CodecState::UNINITIALIZED && state_ != CodecState::INITIALIZED &&
381 state_ != CodecState::PREPARED, (int32_t)Status::ERROR_INVALID_STATE);
382 auto ret = codecPlugin_->SetParameter(parameter);
383 FALSE_RETURN_V_MSG_E(ret == Status::OK, (int32_t)ret, "plugin set parameter failed");
384 return (int32_t)ret;
385 }
386
SetDumpInfo(bool isDump,uint64_t instanceId)387 void MediaCodec::SetDumpInfo(bool isDump, uint64_t instanceId)
388 {
389 if (isDump && instanceId == 0) {
390 MEDIA_LOG_W("Cannot dump with instanceId 0.");
391 return;
392 }
393 dumpPrefix_ = std::to_string(instanceId);
394 isDump_ = isDump;
395 }
396
GetOutputFormat(std::shared_ptr<Meta> & parameter)397 int32_t MediaCodec::GetOutputFormat(std::shared_ptr<Meta> ¶meter)
398 {
399 AutoLock lock(stateMutex_);
400 FALSE_RETURN_V_MSG_E(state_ != CodecState::UNINITIALIZED, (int32_t)Status::ERROR_INVALID_STATE,
401 "status incorrect,get output format failed.");
402 FALSE_RETURN_V(codecPlugin_ != nullptr, (int32_t)Status::ERROR_INVALID_STATE);
403 FALSE_RETURN_V(parameter != nullptr, (int32_t)Status::ERROR_INVALID_PARAMETER);
404 auto ret = codecPlugin_->GetParameter(parameter);
405 FALSE_RETURN_V_MSG_E(ret == Status::OK, (int32_t)ret, "plugin get parameter failed");
406 return (int32_t)ret;
407 }
408
AttachBufffer()409 Status MediaCodec::AttachBufffer()
410 {
411 MEDIA_LOG_I("AttachBufffer enter");
412 int inputBufferNum = DEFAULT_BUFFER_NUM;
413 MemoryType memoryType;
414 #ifndef MEDIA_OHOS
415 memoryType = MemoryType::VIRTUAL_MEMORY;
416 #else
417 memoryType = MemoryType::SHARED_MEMORY;
418 #endif
419 if (inputBufferQueue_ == nullptr) {
420 inputBufferQueue_ = AVBufferQueue::Create(inputBufferNum, memoryType, INPUT_BUFFER_QUEUE_NAME);
421 }
422 FALSE_RETURN_V_MSG_E(inputBufferQueue_ != nullptr, Status::ERROR_UNKNOWN,
423 "inputBufferQueue_ is nullptr");
424 inputBufferQueueProducer_ = inputBufferQueue_->GetProducer();
425 std::shared_ptr<Meta> inputBufferConfig = std::make_shared<Meta>();
426 FALSE_RETURN_V_MSG_E(codecPlugin_ != nullptr, Status::ERROR_UNKNOWN, "codecPlugin_ is nullptr");
427 auto ret = codecPlugin_->GetParameter(inputBufferConfig);
428 FALSE_RETURN_V_MSG_E(ret == Status::OK, ret, "attachBufffer failed, plugin get param error");
429 int32_t capacity = 0;
430 FALSE_RETURN_V_MSG_E(inputBufferConfig != nullptr, Status::ERROR_UNKNOWN,
431 "inputBufferConfig is nullptr");
432 FALSE_RETURN_V(inputBufferConfig->Get<Tag::AUDIO_MAX_INPUT_SIZE>(capacity),
433 Status::ERROR_INVALID_PARAMETER);
434 for (int i = 0; i < inputBufferNum; i++) {
435 std::shared_ptr<AVAllocator> avAllocator;
436 #ifndef MEDIA_OHOS
437 MEDIA_LOG_D("CreateVirtualAllocator,i=%{public}d capacity=%{public}d", i, capacity);
438 avAllocator = AVAllocatorFactory::CreateVirtualAllocator();
439 #else
440 MEDIA_LOG_D("CreateSharedAllocator,i=%{public}d capacity=%{public}d", i, capacity);
441 avAllocator = AVAllocatorFactory::CreateSharedAllocator(MemoryFlag::MEMORY_READ_WRITE);
442 #endif
443 std::shared_ptr<AVBuffer> inputBuffer = AVBuffer::CreateAVBuffer(avAllocator, capacity);
444 FALSE_RETURN_V_MSG_E(inputBuffer != nullptr, Status::ERROR_UNKNOWN,
445 "inputBuffer is nullptr");
446 FALSE_RETURN_V_MSG_E(inputBufferQueueProducer_ != nullptr, Status::ERROR_UNKNOWN,
447 "inputBufferQueueProducer_ is nullptr");
448 inputBufferQueueProducer_->AttachBuffer(inputBuffer, false);
449 MEDIA_LOG_I("Attach intput buffer. index: %{public}d, bufferId: %{public}" PRIu64,
450 i, inputBuffer->GetUniqueId());
451 inputBufferVector_.push_back(inputBuffer);
452 }
453 return Status::OK;
454 }
455
AttachDrmBufffer(std::shared_ptr<AVBuffer> & drmInbuf,std::shared_ptr<AVBuffer> & drmOutbuf,uint32_t size)456 Status MediaCodec::AttachDrmBufffer(std::shared_ptr<AVBuffer> &drmInbuf, std::shared_ptr<AVBuffer> &drmOutbuf,
457 uint32_t size)
458 {
459 MEDIA_LOG_D("AttachDrmBufffer");
460 std::shared_ptr<AVAllocator> avAllocator;
461 avAllocator = AVAllocatorFactory::CreateSharedAllocator(MemoryFlag::MEMORY_READ_WRITE);
462 FALSE_RETURN_V_MSG_E(avAllocator != nullptr, Status::ERROR_UNKNOWN,
463 "avAllocator is nullptr");
464
465 drmInbuf = AVBuffer::CreateAVBuffer(avAllocator, size);
466 FALSE_RETURN_V_MSG_E(drmInbuf != nullptr, Status::ERROR_UNKNOWN,
467 "drmInbuf is nullptr");
468 FALSE_RETURN_V_MSG_E(drmInbuf->memory_ != nullptr, Status::ERROR_UNKNOWN,
469 "drmInbuf->memory_ is nullptr");
470 drmInbuf->memory_->SetSize(size);
471
472 drmOutbuf = AVBuffer::CreateAVBuffer(avAllocator, size);
473 FALSE_RETURN_V_MSG_E(drmOutbuf != nullptr, Status::ERROR_UNKNOWN,
474 "drmOutbuf is nullptr");
475 FALSE_RETURN_V_MSG_E(drmOutbuf->memory_ != nullptr, Status::ERROR_UNKNOWN,
476 "drmOutbuf->memory_ is nullptr");
477 drmOutbuf->memory_->SetSize(size);
478 return Status::OK;
479 }
480
DrmAudioCencDecrypt(std::shared_ptr<AVBuffer> & filledInputBuffer)481 Status MediaCodec::DrmAudioCencDecrypt(std::shared_ptr<AVBuffer> &filledInputBuffer)
482 {
483 MEDIA_LOG_D("DrmAudioCencDecrypt enter");
484 Status ret = Status::OK;
485
486 // 1. allocate drm buffer
487 uint32_t bufSize = static_cast<uint32_t>(filledInputBuffer->memory_->GetSize());
488 if (bufSize == 0) {
489 MEDIA_LOG_D("MediaCodec DrmAudioCencDecrypt input buffer size equal 0");
490 return ret;
491 }
492 std::shared_ptr<AVBuffer> drmInBuf;
493 std::shared_ptr<AVBuffer> drmOutBuf;
494 ret = AttachDrmBufffer(drmInBuf, drmOutBuf, bufSize);
495 FALSE_RETURN_V_MSG_E(ret == Status::OK, Status::ERROR_UNKNOWN, "AttachDrmBufffer failed");
496
497 // 2. copy data to drm input buffer
498 int32_t drmRes = memcpy_s(drmInBuf->memory_->GetAddr(), bufSize,
499 filledInputBuffer->memory_->GetAddr(), bufSize);
500 FALSE_RETURN_V_MSG_E(drmRes == 0, Status::ERROR_UNKNOWN, "memcpy_s drmInBuf failed");
501 if (filledInputBuffer->meta_ != nullptr) {
502 *(drmInBuf->meta_) = *(filledInputBuffer->meta_);
503 }
504 // 4. decrypt
505 drmRes = drmDecryptor_->DrmAudioCencDecrypt(drmInBuf, drmOutBuf, bufSize);
506 FALSE_RETURN_V_MSG_E(drmRes == 0, Status::ERROR_DRM_DECRYPT_FAILED, "DrmAudioCencDecrypt return error");
507
508 // 5. copy decrypted data from drm output buffer back
509 drmRes = memcpy_s(filledInputBuffer->memory_->GetAddr(), bufSize,
510 drmOutBuf->memory_->GetAddr(), bufSize);
511 FALSE_RETURN_V_MSG_E(drmRes == 0, Status::ERROR_UNKNOWN, "memcpy_s drmOutBuf failed");
512 return Status::OK;
513 }
514
HandleAudioCencDecryptError()515 void MediaCodec::HandleAudioCencDecryptError()
516 {
517 MEDIA_LOG_E("MediaCodec DrmAudioCencDecrypt failed.");
518 auto realPtr = mediaCodecCallback_.lock();
519 if (realPtr != nullptr) {
520 realPtr->OnError(CodecErrorType::CODEC_DRM_DECRYTION_FAILED,
521 static_cast<int32_t>(Status::ERROR_DRM_DECRYPT_FAILED));
522 }
523 }
524
PrepareInputBufferQueue()525 int32_t MediaCodec::PrepareInputBufferQueue()
526 {
527 MEDIA_LOG_I("PrepareInputBufferQueue enter");
528 std::vector<std::shared_ptr<AVBuffer>> inputBuffers;
529 MediaAVCodec::AVCodecTrace trace("MediaCodec::PrepareInputBufferQueue");
530 FALSE_RETURN_V_MSG_E(codecPlugin_ != nullptr, (int32_t)Status::ERROR_UNKNOWN, "codecPlugin_ is nullptr");
531 auto ret = codecPlugin_->GetInputBuffers(inputBuffers);
532 FALSE_RETURN_V_MSG_E(ret == Status::OK, (int32_t)ret, "pluign getInputBuffers failed");
533 if (inputBuffers.empty()) {
534 ret = AttachBufffer();
535 if (ret != Status::OK) {
536 MEDIA_LOG_E("GetParameter failed");
537 return (int32_t)ret;
538 }
539 } else {
540 if (inputBufferQueue_ == nullptr) {
541 inputBufferQueue_ =
542 AVBufferQueue::Create(inputBuffers.size(), MemoryType::HARDWARE_MEMORY, INPUT_BUFFER_QUEUE_NAME);
543 }
544 FALSE_RETURN_V_MSG_E(inputBufferQueue_ != nullptr, (int32_t)Status::ERROR_UNKNOWN,
545 "inputBufferQueue_ is nullptr");
546 inputBufferQueueProducer_ = inputBufferQueue_->GetProducer();
547 for (uint32_t i = 0; i < inputBuffers.size(); i++) {
548 inputBufferQueueProducer_->AttachBuffer(inputBuffers[i], false);
549 inputBufferVector_.push_back(inputBuffers[i]);
550 }
551 }
552 FALSE_RETURN_V_MSG_E(inputBufferQueue_ != nullptr, (int32_t)Status::ERROR_UNKNOWN, "inputBufferQueue_ is nullptr");
553 inputBufferQueueConsumer_ = inputBufferQueue_->GetConsumer();
554 sptr<IConsumerListener> listener = new InputBufferAvailableListener(this);
555 FALSE_RETURN_V_MSG_E(inputBufferQueueConsumer_ != nullptr, (int32_t)Status::ERROR_UNKNOWN,
556 "inputBufferQueueConsumer_ is nullptr");
557 inputBufferQueueConsumer_->SetBufferAvailableListener(listener);
558 return (int32_t)ret;
559 }
560
PrepareOutputBufferQueue()561 int32_t MediaCodec::PrepareOutputBufferQueue()
562 {
563 MEDIA_LOG_I("PrepareOutputBufferQueue enter");
564 std::vector<std::shared_ptr<AVBuffer>> outputBuffers;
565 MediaAVCodec::AVCodecTrace trace("MediaCodec::PrepareOutputBufferQueue");
566 FALSE_RETURN_V_MSG_E(codecPlugin_ != nullptr, (int32_t)Status::ERROR_INVALID_STATE, "codecPlugin_ is nullptr");
567 auto ret = codecPlugin_->GetOutputBuffers(outputBuffers);
568 FALSE_RETURN_V_MSG_E(ret == Status::OK, (int32_t)ret, "GetOutputBuffers failed");
569 FALSE_RETURN_V_MSG_E(outputBufferQueueProducer_ != nullptr, (int32_t)Status::ERROR_INVALID_STATE,
570 "outputBufferQueueProducer_ is nullptr");
571 if (outputBuffers.empty()) {
572 int outputBufferNum = 30;
573 std::shared_ptr<Meta> outputBufferConfig = std::make_shared<Meta>();
574 ret = codecPlugin_->GetParameter(outputBufferConfig);
575 FALSE_RETURN_V_MSG_E(ret == Status::OK, (int32_t)ret, "GetParameter failed");
576 FALSE_RETURN_V_MSG_E(outputBufferConfig != nullptr, (int32_t)Status::ERROR_INVALID_STATE,
577 "outputBufferConfig is nullptr");
578 FALSE_RETURN_V(outputBufferConfig->Get<Tag::AUDIO_MAX_OUTPUT_SIZE>(outputBufferCapacity_),
579 (int32_t)Status::ERROR_INVALID_PARAMETER);
580 for (int i = 0; i < outputBufferNum; i++) {
581 auto avAllocator = AVAllocatorFactory::CreateSharedAllocator(MemoryFlag::MEMORY_READ_WRITE);
582 std::shared_ptr<AVBuffer> outputBuffer = AVBuffer::CreateAVBuffer(avAllocator, outputBufferCapacity_);
583 FALSE_RETURN_V_MSG_E(outputBuffer != nullptr, (int32_t)Status::ERROR_INVALID_STATE,
584 "outputBuffer is nullptr");
585 if (outputBufferQueueProducer_->AttachBuffer(outputBuffer, false) == Status::OK) {
586 MEDIA_LOG_D("Attach output buffer. index: %{public}d, bufferId: %{public}" PRIu64, i,
587 outputBuffer->GetUniqueId());
588 outputBufferVector_.push_back(outputBuffer);
589 }
590 }
591 } else {
592 for (uint32_t i = 0; i < outputBuffers.size(); i++) {
593 if (outputBufferQueueProducer_->AttachBuffer(outputBuffers[i], false) == Status::OK) {
594 MEDIA_LOG_D("Attach output buffer. index: %{public}d, bufferId: %{public}" PRIu64, i,
595 outputBuffers[i]->GetUniqueId());
596 outputBufferVector_.push_back(outputBuffers[i]);
597 }
598 }
599 }
600 FALSE_RETURN_V_MSG_E(outputBufferVector_.size() > 0, (int32_t)Status::ERROR_INVALID_STATE, "Attach no buffer");
601 return (int32_t)ret;
602 }
603
ProcessInputBuffer()604 void MediaCodec::ProcessInputBuffer()
605 {
606 MEDIA_LOG_D("ProcessInputBuffer enter");
607 MediaAVCodec::AVCodecTrace trace("MediaCodec::ProcessInputBuffer");
608 Status ret;
609 uint32_t eosStatus = 0;
610 std::shared_ptr<AVBuffer> filledInputBuffer;
611 if (state_ != CodecState::RUNNING) {
612 MEDIA_LOG_E("status changed, current status is not running in ProcessInputBuffer");
613 return;
614 }
615 {
616 MediaAVCodec::AVCodecTrace traceAcquireBuffer("MediaCodec::ProcessInputBuffer-AcquireBuffer");
617 ret = inputBufferQueueConsumer_->AcquireBuffer(filledInputBuffer);
618 if (ret != Status::OK) {
619 MEDIA_LOG_E("ProcessInputBuffer AcquireBuffer fail");
620 return;
621 }
622 }
623 if (state_ != CodecState::RUNNING) {
624 MEDIA_LOG_D("ProcessInputBuffer ReleaseBuffer name:MediaCodecInputBufferQueue");
625 inputBufferQueueConsumer_->ReleaseBuffer(filledInputBuffer);
626 return;
627 }
628 const int8_t RETRY = 3; // max retry count is 3
629 int8_t retryCount = 0;
630 do {
631 if (drmDecryptor_ != nullptr) {
632 ret = DrmAudioCencDecrypt(filledInputBuffer);
633 if (ret != Status::OK) {
634 HandleAudioCencDecryptError();
635 break;
636 }
637 }
638
639 ret = codecPlugin_->QueueInputBuffer(filledInputBuffer);
640 if (ret != Status::OK) {
641 retryCount++;
642 continue;
643 }
644 } while (ret != Status::OK && retryCount < RETRY);
645
646 if (ret != Status::OK) {
647 inputBufferQueueConsumer_->ReleaseBuffer(filledInputBuffer);
648 MEDIA_LOG_E("Plugin queueInputBuffer failed.");
649 return;
650 }
651 eosStatus = filledInputBuffer->flag_;
652 do {
653 ret = HandleOutputBuffer(eosStatus);
654 } while (ret == Status::ERROR_AGAIN);
655 }
656
657 #ifdef SUPPORT_DRM
SetAudioDecryptionConfig(const sptr<DrmStandard::IMediaKeySessionService> & keySession,const bool svpFlag)658 int32_t MediaCodec::SetAudioDecryptionConfig(const sptr<DrmStandard::IMediaKeySessionService> &keySession,
659 const bool svpFlag)
660 {
661 MEDIA_LOG_I("MediaCodec::SetAudioDecryptionConfig");
662 if (drmDecryptor_ == nullptr) {
663 drmDecryptor_ = std::make_shared<MediaAVCodec::CodecDrmDecrypt>();
664 }
665 FALSE_RETURN_V_MSG_E(drmDecryptor_ != nullptr, (int32_t)Status::ERROR_NO_MEMORY, "drmDecryptor is nullptr");
666 drmDecryptor_->SetDecryptionConfig(keySession, svpFlag);
667 return (int32_t)Status::OK;
668 }
669 #else
SetAudioDecryptionConfig(const sptr<DrmStandard::IMediaKeySessionService> & keySession,const bool svpFlag)670 int32_t MediaCodec::SetAudioDecryptionConfig(const sptr<DrmStandard::IMediaKeySessionService> &keySession,
671 const bool svpFlag)
672 {
673 MEDIA_LOG_I("MediaCodec::SetAudioDecryptionConfig, Not support");
674 (void)keySession;
675 (void)svpFlag;
676 return (int32_t)Status::OK;
677 }
678 #endif
679
ChangePlugin(const std::string & mime,bool isEncoder,const std::shared_ptr<Meta> & meta)680 Status MediaCodec::ChangePlugin(const std::string &mime, bool isEncoder, const std::shared_ptr<Meta> &meta)
681 {
682 Status ret = Status::OK;
683 Plugins::PluginType type;
684 if (isEncoder) {
685 type = Plugins::PluginType::AUDIO_ENCODER;
686 } else {
687 type = Plugins::PluginType::AUDIO_DECODER;
688 }
689 if (codecPlugin_ != nullptr) {
690 codecPlugin_->Release();
691 codecPlugin_ = nullptr;
692 }
693 codecPlugin_ = CreatePlugin(mime, type);
694 if (codecPlugin_ != nullptr) {
695 ret = codecPlugin_->SetParameter(meta);
696 MEDIA_LOG_I("codecPlugin SetParameter ret %{public}d", ret);
697 ret = codecPlugin_->Init();
698 MEDIA_LOG_I("codecPlugin Init ret %{public}d", ret);
699 ret = codecPlugin_->SetDataCallback(this);
700 MEDIA_LOG_I("codecPlugin SetDataCallback ret %{public}d", ret);
701 PrepareInputBufferQueue();
702 PrepareOutputBufferQueue();
703 if (state_ == CodecState::RUNNING) {
704 ret = codecPlugin_->Start();
705 MEDIA_LOG_I("codecPlugin Start ret %{public}d", ret);
706 }
707 } else {
708 MEDIA_LOG_I("createPlugin failed");
709 return Status::ERROR_INVALID_PARAMETER;
710 }
711 return ret;
712 }
713
HandleOutputBuffer(uint32_t eosStatus)714 Status MediaCodec::HandleOutputBuffer(uint32_t eosStatus)
715 {
716 MEDIA_LOG_D("HandleOutputBuffer enter");
717 MediaAVCodec::AVCodecTrace trace("MediaCodec::HandleOutputBuffer");
718 Status ret = Status::OK;
719 std::shared_ptr<AVBuffer> emptyOutputBuffer;
720 AVBufferConfig avBufferConfig;
721 {
722 MediaAVCodec::AVCodecTrace traceRequestBuffer("MediaCodec::HandleOutputBuffer-RequestBuffer");
723 do {
724 ret = outputBufferQueueProducer_->RequestBuffer(emptyOutputBuffer, avBufferConfig, TIME_OUT_MS);
725 } while (ret != Status::OK && state_ == CodecState::RUNNING);
726 }
727 if (emptyOutputBuffer) {
728 emptyOutputBuffer->flag_ = eosStatus;
729 } else if (state_ != CodecState::RUNNING) {
730 return Status::OK;
731 } else {
732 return Status::ERROR_NULL_POINTER;
733 }
734 FALSE_RETURN_V_MSG_E(codecPlugin_ != nullptr, Status::ERROR_INVALID_STATE, "plugin is null");
735 ret = codecPlugin_->QueueOutputBuffer(emptyOutputBuffer);
736 if (ret == Status::ERROR_NOT_ENOUGH_DATA) {
737 MEDIA_LOG_D("QueueOutputBuffer ERROR_NOT_ENOUGH_DATA");
738 outputBufferQueueProducer_->PushBuffer(emptyOutputBuffer, false);
739 } else if (ret == Status::ERROR_AGAIN) {
740 MEDIA_LOG_D("The output data is not completely read, needs to be read again");
741 } else if (ret == Status::END_OF_STREAM) {
742 MEDIA_LOG_D("HandleOutputBuffer END_OF_STREAM");
743 } else if (ret != Status::OK) {
744 MEDIA_LOG_E("QueueOutputBuffer error");
745 outputBufferQueueProducer_->PushBuffer(emptyOutputBuffer, false);
746 }
747 return ret;
748 }
749
OnInputBufferDone(const std::shared_ptr<AVBuffer> & inputBuffer)750 void MediaCodec::OnInputBufferDone(const std::shared_ptr<AVBuffer> &inputBuffer)
751 {
752 MediaAVCodec::AVCodecTrace trace("MediaCodec::OnInputBufferDone");
753 Status ret = inputBufferQueueConsumer_->ReleaseBuffer(inputBuffer);
754 MEDIA_LOG_D("0x%{public}06" PRIXPTR " OnInputBufferDone, buffer->pts" PUBLIC_LOG_D64,
755 FAKE_POINTER(this), inputBuffer->pts_);
756 FALSE_RETURN_MSG(ret == Status::OK, "OnInputBufferDone fail");
757 }
758
OnOutputBufferDone(const std::shared_ptr<AVBuffer> & outputBuffer)759 void MediaCodec::OnOutputBufferDone(const std::shared_ptr<AVBuffer> &outputBuffer)
760 {
761 MediaAVCodec::AVCodecTrace trace("MediaCodec::OnOutputBufferDone");
762 if (isDump_) {
763 DumpAVBufferToFile(DUMP_PARAM, dumpPrefix_ + DUMP_FILE_NAME, outputBuffer);
764 }
765 Status ret = outputBufferQueueProducer_->PushBuffer(outputBuffer, true);
766 auto realPtr = mediaCodecCallback_.lock();
767 if (realPtr != nullptr) {
768 realPtr->OnOutputBufferDone(outputBuffer);
769 }
770 MEDIA_LOG_D("0x%{public}06" PRIXPTR " OnOutputBufferDone, buffer->pts" PUBLIC_LOG_D64,
771 FAKE_POINTER(this), outputBuffer->pts_);
772 FALSE_RETURN_MSG(ret == Status::OK, "OnOutputBufferDone fail");
773 }
774
ClearBufferQueue()775 void MediaCodec::ClearBufferQueue()
776 {
777 MEDIA_LOG_I("ClearBufferQueue called.");
778 if (inputBufferQueueProducer_ != nullptr) {
779 for (const auto &buffer : inputBufferVector_) {
780 inputBufferQueueProducer_->DetachBuffer(buffer);
781 }
782 inputBufferVector_.clear();
783 inputBufferQueueProducer_->SetQueueSize(0);
784 }
785 if (outputBufferQueueProducer_ != nullptr) {
786 for (const auto &buffer : outputBufferVector_) {
787 outputBufferQueueProducer_->DetachBuffer(buffer);
788 }
789 outputBufferVector_.clear();
790 outputBufferQueueProducer_->SetQueueSize(0);
791 }
792 }
793
ClearInputBuffer()794 void MediaCodec::ClearInputBuffer()
795 {
796 MediaAVCodec::AVCodecTrace trace("MediaCodec::ClearInputBuffer");
797 MEDIA_LOG_D("ClearInputBuffer enter");
798 if (!inputBufferQueueConsumer_) {
799 return;
800 }
801 std::shared_ptr<AVBuffer> filledInputBuffer;
802 Status ret = Status::OK;
803 while (ret == Status::OK) {
804 ret = inputBufferQueueConsumer_->AcquireBuffer(filledInputBuffer);
805 if (ret != Status::OK) {
806 MEDIA_LOG_I("clear input Buffer");
807 return;
808 }
809 inputBufferQueueConsumer_->ReleaseBuffer(filledInputBuffer);
810 }
811 }
812
OnEvent(const std::shared_ptr<Plugins::PluginEvent> event)813 void MediaCodec::OnEvent(const std::shared_ptr<Plugins::PluginEvent> event)
814 {
815 if (event->type != Plugins::PluginEventType::AUDIO_OUTPUT_FORMAT_CHANGED) {
816 return;
817 }
818
819 if (!isSupportAudioFormatChanged_) {
820 MEDIA_LOG_W("receive audio format changed but api version is low");
821 return;
822 }
823
824 auto realPtr = mediaCodecCallback_.lock();
825 if (realPtr != nullptr) {
826 std::shared_ptr<Meta> format = std::make_shared<Meta>(AnyCast<Meta>(event->param));
827 realPtr->OnOutputFormatChanged(format);
828 } else {
829 MEDIA_LOG_E("receive AUDIO_OUTPUT_FORMAT_CHANGED, but lock callback fail");
830 }
831 }
832
StateToString(CodecState state)833 std::string MediaCodec::StateToString(CodecState state)
834 {
835 std::map<CodecState, std::string> stateStrMap = {
836 {CodecState::UNINITIALIZED, " UNINITIALIZED"},
837 {CodecState::INITIALIZED, " INITIALIZED"},
838 {CodecState::FLUSHED, " FLUSHED"},
839 {CodecState::RUNNING, " RUNNING"},
840 {CodecState::INITIALIZING, " INITIALIZING"},
841 {CodecState::STARTING, " STARTING"},
842 {CodecState::STOPPING, " STOPPING"},
843 {CodecState::FLUSHING, " FLUSHING"},
844 {CodecState::RESUMING, " RESUMING"},
845 {CodecState::RELEASING, " RELEASING"},
846 };
847 return stateStrMap[state];
848 }
849
OnDumpInfo(int32_t fd)850 void MediaCodec::OnDumpInfo(int32_t fd)
851 {
852 MEDIA_LOG_D("MediaCodec::OnDumpInfo called.");
853 if (fd < 0) {
854 MEDIA_LOG_E("MediaCodec::OnDumpInfo fd is invalid.");
855 return;
856 }
857 std::string dumpString;
858 dumpString += "MediaCodec plugin name: " + codecPluginName_ + "\n";
859 dumpString += "MediaCodec buffer size is:" + std::to_string(inputBufferQueue_->GetQueueSize()) + "\n";
860 int ret = write(fd, dumpString.c_str(), dumpString.size());
861 if (ret < 0) {
862 MEDIA_LOG_E("MediaCodec::OnDumpInfo write failed.");
863 return;
864 }
865 }
866
GetApiVersion()867 uint32_t MediaCodec::GetApiVersion()
868 {
869 uint32_t apiVersion = INVALID_API_VERSION;
870 OHOS::sptr<OHOS::ISystemAbilityManager> systemAbilityManager =
871 OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
872 OHOS::sptr<OHOS::IRemoteObject> remoteObject =
873 systemAbilityManager->CheckSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
874 sptr<AppExecFwk::IBundleMgr> iBundleMgr = OHOS::iface_cast<AppExecFwk::IBundleMgr>(remoteObject);
875 if (iBundleMgr == nullptr) {
876 MEDIA_LOG_W("GetApiVersion IBundleMgr is nullptr");
877 return apiVersion;
878 }
879 AppExecFwk::BundleInfo bundleInfo;
880 if (iBundleMgr->GetBundleInfoForSelf(0, bundleInfo) == ERR_OK) {
881 apiVersion = bundleInfo.targetVersion % API_VERSION_MOD;
882 MEDIA_LOG_I("GetApiVersion targetVersion: %{public}u", bundleInfo.targetVersion);
883 } else {
884 MEDIA_LOG_W("GetApiVersion failed, call by SA or test maybe");
885 }
886 return apiVersion;
887 }
888
889 } // namespace Media
890 } // namespace OHOS
891