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