1 /*
2 * Copyright (c) 2023-2025 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 <iostream>
18 #include <sstream>
19 #include <ctime>
20 #include <fstream>
21 #include "avcodec_common.h"
22 #include "common/log.h"
23 #include "osal/task/autolock.h"
24 #include "plugin/plugin_manager_v2.h"
25 #include "avcodec_log.h"
26 #include "osal/utils/dump_buffer.h"
27 #include "avcodec_trace.h"
28 #include "bundle_mgr_interface.h"
29 #include "iservice_registry.h"
30 #include "system_ability_definition.h"
31 #include "param_wrapper.h"
32
33 #ifdef SUPPORT_DRM
34 #include "imedia_key_session_service.h"
35 #endif
36
37 namespace {
38 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_DOMAIN_AUDIO, "MediaCodec" };
39 const std::string INPUT_BUFFER_QUEUE_NAME = "MediaCodecInputBufferQueue";
40 constexpr int8_t RETRY = 3; // max retry count is 3
41 constexpr int32_t DEFAULT_BUFFER_NUM = 8;
42 constexpr int32_t TIME_OUT_MS = 50;
43 constexpr int32_t TIME_OUT_MS_INNER = 1;
44 constexpr uint32_t API_SUPPORT_AUDIO_FORMAT_CHANGED = 15;
45 constexpr uint32_t INVALID_API_VERSION = 0;
46 constexpr uint32_t API_VERSION_MOD = 1000;
47 const std::string DUMP_PARAM = "a";
48 const std::string DUMP_FILE_NAME = "player_audio_decoder_output.pcm";
49 const std::string DUMP_IO_LABLE = "sys.media.AVCodec.dump.enable";
50 } // namespace
51
52 namespace OHOS {
53 namespace Media {
54 class InputBufferAvailableListener : public IConsumerListener {
55 public:
InputBufferAvailableListener(std::shared_ptr<MediaCodec> mediaCodec)56 explicit InputBufferAvailableListener(std::shared_ptr<MediaCodec> mediaCodec)
57 {
58 mediaCodec_ = mediaCodec;
59 }
60
OnBufferAvailable()61 void OnBufferAvailable() override
62 {
63 auto realPtr = mediaCodec_.lock();
64 if (realPtr != nullptr) {
65 realPtr->ProcessInputBuffer();
66 } else {
67 MEDIA_LOG_W("mediacodec was released, can not process input buffer");
68 }
69 }
70
71 private:
72 std::weak_ptr<MediaCodec> mediaCodec_;
73 };
74
MediaCodec()75 MediaCodec::MediaCodec()
76 : codecPlugin_(nullptr),
77 inputBufferQueue_(nullptr),
78 inputBufferQueueProducer_(nullptr),
79 inputBufferQueueConsumer_(nullptr),
80 outputBufferQueueProducer_(nullptr),
81 isEncoder_(false),
82 isSurfaceMode_(false),
83 isBufferMode_(false),
84 outputBufferCapacity_(0),
85 state_(CodecState::UNINITIALIZED)
86 {
87 }
88
~MediaCodec()89 MediaCodec::~MediaCodec()
90 {
91 state_ = CodecState::UNINITIALIZED;
92 outputBufferCapacity_ = 0;
93 if (codecPlugin_) {
94 codecPlugin_ = nullptr;
95 }
96 if (inputBufferQueue_) {
97 inputBufferQueue_ = nullptr;
98 }
99 if (inputBufferQueueProducer_) {
100 inputBufferQueueProducer_ = nullptr;
101 }
102 if (inputBufferQueueConsumer_) {
103 inputBufferQueueConsumer_ = nullptr;
104 }
105 if (outputBufferQueueProducer_) {
106 outputBufferQueueProducer_ = nullptr;
107 }
108 }
109
Init(const std::string & mime,bool isEncoder)110 int32_t MediaCodec::Init(const std::string &mime, bool isEncoder)
111 {
112 AutoLock lock(stateMutex_);
113 MediaAVCodec::AVCodecTrace trace("MediaCodec::Init");
114 OHOS::system::GetStringParameter(DUMP_IO_LABLE, dumpIOEnable, "false");
115 MEDIA_LOG_I("Init enter, mime: " PUBLIC_LOG_S, mime.c_str());
116 if (state_ != CodecState::UNINITIALIZED) {
117 MEDIA_LOG_E("Init failed, state = %{public}s .", StateToString(state_).data());
118 return (int32_t)Status::ERROR_INVALID_STATE;
119 }
120 MEDIA_LOG_I("state from %{public}s to INITIALIZING", StateToString(state_).data());
121 state_ = CodecState::INITIALIZING;
122 Plugins::PluginType type;
123 if (isEncoder) {
124 type = Plugins::PluginType::AUDIO_ENCODER;
125 } else {
126 type = Plugins::PluginType::AUDIO_DECODER;
127 }
128 codecPlugin_ = CreatePlugin(mime, type);
129 if (codecPlugin_ != nullptr) {
130 MEDIA_LOG_I("codecPlugin_->Init()");
131 auto ret = codecPlugin_->Init();
132 FALSE_RETURN_V_MSG_E(ret == Status::OK, (int32_t)ret, "pluign init failed");
133 state_ = CodecState::INITIALIZED;
134 } else {
135 MEDIA_LOG_I("createPlugin failed");
136 state_ = CodecState::UNINITIALIZED;
137 return (int32_t)Status::ERROR_INVALID_PARAMETER;
138 }
139 return (int32_t)Status::OK;
140 }
141
Init(const std::string & name)142 int32_t MediaCodec::Init(const std::string &name)
143 {
144 AutoLock lock(stateMutex_);
145 OHOS::system::GetStringParameter(DUMP_IO_LABLE, dumpIOEnable, "false");
146 MEDIA_LOG_I("Init enter, name: " PUBLIC_LOG_S, name.c_str());
147 MediaAVCodec::AVCodecTrace trace("MediaCodec::Init");
148 if (state_ != CodecState::UNINITIALIZED) {
149 MEDIA_LOG_E("Init failed, state = %{public}s .", StateToString(state_).data());
150 return (int32_t)Status::ERROR_INVALID_STATE;
151 }
152 MEDIA_LOG_I("state from %{public}s to INITIALIZING", StateToString(state_).data());
153 state_ = CodecState::INITIALIZING;
154 auto plugin = Plugins::PluginManagerV2::Instance().CreatePluginByName(name);
155 if (plugin == nullptr) {
156 MEDIA_LOG_E("create pluign failed");
157 state_ = CodecState::UNINITIALIZED;
158 return (int32_t)Status::ERROR_INVALID_PARAMETER;
159 }
160 codecPlugin_ = std::reinterpret_pointer_cast<Plugins::CodecPlugin>(plugin);
161 if (codecPlugin_->Init() != Status::OK) {
162 MEDIA_LOG_E("pluign init failed");
163 state_ = CodecState::UNINITIALIZED;
164 return (int32_t)Status::ERROR_INVALID_PARAMETER;
165 }
166 state_ = CodecState::INITIALIZED;
167 return (int32_t)Status::OK;
168 }
169
CreatePlugin(const std::string & mime,Plugins::PluginType pluginType)170 std::shared_ptr<Plugins::CodecPlugin> MediaCodec::CreatePlugin(const std::string &mime, Plugins::PluginType pluginType)
171 {
172 auto plugin = Plugins::PluginManagerV2::Instance().CreatePluginByMime(pluginType, mime);
173 if (plugin == nullptr) {
174 return nullptr;
175 }
176 return std::reinterpret_pointer_cast<Plugins::CodecPlugin>(plugin);
177 }
178
IODump(const std::shared_ptr<Meta> & meta)179 void MediaCodec::IODump(const std::shared_ptr<Meta> &meta)
180 {
181 std::time_t t = std::time(nullptr);
182 std::tm tm = *std::localtime(&t);
183
184 std::ostringstream common;
185 common << "/data/media/";
186 common << std::put_time(&tm, "%H%M%S");
187 common << "_" << reinterpret_cast<void*>(this);
188
189 int32_t channels = 0;
190 int32_t sampleRate = 0;
191 meta->GetData(Tag::AUDIO_SAMPLE_RATE, sampleRate);
192 common << "_" << sampleRate;
193 meta->GetData(Tag::AUDIO_CHANNEL_COUNT, channels);
194 common << "_" << channels;
195
196 std::ostringstream inputStr;
197 std::ostringstream outputStr;
198 inputStr << common.str() << "_input.bin";
199 outputStr << common.str() << "_output.bin";
200
201 dumpDataInputFs_ = std::make_shared<std::ofstream>(inputStr.str(), std::ios::binary);
202 dumpDataOutputFs_ = std::make_shared<std::ofstream>(outputStr.str(), std::ios::binary);
203 }
204
Configure(const std::shared_ptr<Meta> & meta)205 int32_t MediaCodec::Configure(const std::shared_ptr<Meta> &meta)
206 {
207 MEDIA_LOG_I("MediaCodec::configure in");
208 AutoLock lock(stateMutex_);
209 MediaAVCodec::AVCodecTrace trace("MediaCodec::Configure");
210 if (dumpIOEnable == "true") {
211 IODump(meta);
212 MEDIA_LOG_I("IODump in");
213 }
214 FALSE_RETURN_V(state_ == CodecState::INITIALIZED, (int32_t)Status::ERROR_INVALID_STATE);
215 auto ret = codecPlugin_->SetParameter(meta);
216 FALSE_RETURN_V(ret == Status::OK, (int32_t)ret);
217 ret = codecPlugin_->SetDataCallback(this);
218 FALSE_RETURN_V(ret == Status::OK, (int32_t)ret);
219 state_ = CodecState::CONFIGURED;
220 return (int32_t)Status::OK;
221 }
222
SetOutputBufferQueue(const sptr<AVBufferQueueProducer> & bufferQueueProducer)223 int32_t MediaCodec::SetOutputBufferQueue(const sptr<AVBufferQueueProducer> &bufferQueueProducer)
224 {
225 AutoLock lock(stateMutex_);
226 MediaAVCodec::AVCodecTrace trace("MediaCodec::SetOutputBufferQueue");
227 FALSE_RETURN_V(state_ == CodecState::INITIALIZED || state_ == CodecState::CONFIGURED,
228 (int32_t)Status::ERROR_INVALID_STATE);
229 outputBufferQueueProducer_ = bufferQueueProducer;
230 isBufferMode_ = true;
231 return (int32_t)Status::OK;
232 }
233
SetCodecCallback(const std::shared_ptr<CodecCallback> & codecCallback)234 int32_t MediaCodec::SetCodecCallback(const std::shared_ptr<CodecCallback> &codecCallback)
235 {
236 AutoLock lock(stateMutex_);
237 FALSE_RETURN_V(state_ == CodecState::INITIALIZED || state_ == CodecState::CONFIGURED,
238 (int32_t)Status::ERROR_INVALID_STATE);
239 FALSE_RETURN_V_MSG_E(codecCallback != nullptr, (int32_t)Status::ERROR_INVALID_PARAMETER,
240 "codecCallback is nullptr");
241 codecCallback_ = codecCallback;
242 auto ret = codecPlugin_->SetDataCallback(this);
243 FALSE_RETURN_V(ret == Status::OK, (int32_t)ret);
244 return (int32_t)Status::OK;
245 }
246
SetCodecCallback(const std::shared_ptr<AudioBaseCodecCallback> & codecCallback)247 int32_t MediaCodec::SetCodecCallback(const std::shared_ptr<AudioBaseCodecCallback> &codecCallback)
248 {
249 AutoLock lock(stateMutex_);
250 FALSE_RETURN_V(state_ == CodecState::INITIALIZED || state_ == CodecState::CONFIGURED,
251 (int32_t)Status::ERROR_INVALID_STATE);
252 FALSE_RETURN_V_MSG_E(codecCallback != nullptr, (int32_t)Status::ERROR_INVALID_PARAMETER,
253 "codecCallback is nullptr");
254 mediaCodecCallback_ = codecCallback;
255 uint32_t apiVersion = GetApiVersion();
256 isSupportAudioFormatChanged_ =
257 ((apiVersion == INVALID_API_VERSION) || (apiVersion >= API_SUPPORT_AUDIO_FORMAT_CHANGED));
258 return (int32_t)Status::OK;
259 }
260
SetOutputSurface(sptr<Surface> surface)261 int32_t MediaCodec::SetOutputSurface(sptr<Surface> surface)
262 {
263 AutoLock lock(stateMutex_);
264 FALSE_RETURN_V(state_ == CodecState::INITIALIZED || state_ == CodecState::CONFIGURED,
265 (int32_t)Status::ERROR_INVALID_STATE);
266 isSurfaceMode_ = true;
267 return (int32_t)Status::OK;
268 }
269
Prepare()270 int32_t MediaCodec::Prepare()
271 {
272 MEDIA_LOG_I("Prepare enter");
273 AutoLock lock(stateMutex_);
274 MediaAVCodec::AVCodecTrace trace("MediaCodec::Prepare");
275 FALSE_RETURN_V_MSG_W(state_ != CodecState::FLUSHED, (int32_t)Status::ERROR_AGAIN,
276 "state is flushed, no need prepare");
277 FALSE_RETURN_V(state_ != CodecState::PREPARED, (int32_t)Status::OK);
278 FALSE_RETURN_V(state_ == CodecState::CONFIGURED,
279 (int32_t)Status::ERROR_INVALID_STATE);
280 if (isBufferMode_ && isSurfaceMode_) {
281 MEDIA_LOG_E("state error");
282 return (int32_t)Status::ERROR_UNKNOWN;
283 }
284 outputBufferCapacity_ = 0;
285 auto ret = (int32_t)PrepareInputBufferQueue();
286 CHECK_AND_RETURN_RET_LOG(ret == (int32_t)Status::OK, (int32_t)ret, "PrepareInputBufferQueue failed");
287 ret = (int32_t)PrepareOutputBufferQueue();
288 CHECK_AND_RETURN_RET_LOG(ret == (int32_t)Status::OK, (int32_t)ret, "PrepareOutputBufferQueue failed");
289 state_ = CodecState::PREPARED;
290 MEDIA_LOG_I("Prepare, ret = %{public}d", (int32_t)ret);
291 return (int32_t)Status::OK;
292 }
293
GetInputBufferQueue()294 sptr<AVBufferQueueProducer> MediaCodec::GetInputBufferQueue()
295 {
296 AutoLock lock(stateMutex_);
297 FALSE_RETURN_V(state_ == CodecState::PREPARED, sptr<AVBufferQueueProducer>());
298 CHECK_AND_RETURN_RET_LOG(!isSurfaceMode_, nullptr, "GetInputBufferQueue isSurfaceMode_");
299 isBufferMode_ = true;
300 return inputBufferQueueProducer_;
301 }
302
GetInputBufferQueueConsumer()303 sptr<AVBufferQueueConsumer> MediaCodec::GetInputBufferQueueConsumer()
304 {
305 AutoLock lock(stateMutex_);
306 // Case: to enable to set listener to input bufferqueue consumer. i.e. input bufferqueue updating by ChangePlugin.
307 FALSE_RETURN_V(state_ == CodecState::PREPARED || state_ == CodecState::RUNNING ||
308 state_ == CodecState::FLUSHED || state_ == CodecState::END_OF_STREAM, sptr<AVBufferQueueConsumer>());
309 CHECK_AND_RETURN_RET_LOG(!isSurfaceMode_, nullptr, "GetInputBufferQueueConsumer isSurfaceMode_");
310 isBufferMode_ = true;
311 return inputBufferQueueConsumer_;
312 }
313
GetOutputBufferQueueProducer()314 sptr<AVBufferQueueProducer> MediaCodec::GetOutputBufferQueueProducer()
315 {
316 AutoLock lock(stateMutex_);
317 // Case: to enable to set listener to output bufferqueue producer. i.e. output bufferqueue updating by ChangePlugin.
318 FALSE_RETURN_V(state_ == CodecState::PREPARED || state_ == CodecState::RUNNING ||
319 state_ == CodecState::FLUSHED || state_ == CodecState::END_OF_STREAM, sptr<AVBufferQueueProducer>());
320 CHECK_AND_RETURN_RET_LOG(!isSurfaceMode_, nullptr, "GetOutputBufferQueueProducer isSurfaceMode_");
321
322 return outputBufferQueueProducer_;
323 }
324
ProcessInputBufferInner(bool isTriggeredByOutPort,bool isFlushed)325 void MediaCodec::ProcessInputBufferInner(bool isTriggeredByOutPort, bool isFlushed)
326 {
327 uint32_t bufferStatus = static_cast<uint32_t>(InOutPortBufferStatus::INIT_IGNORE_RET);
328 ProcessInputBufferInner(isTriggeredByOutPort, isFlushed, bufferStatus);
329 }
330
ProcessInputBufferInner(bool isTriggeredByOutPort,bool isFlushed,uint32_t & bufferStatus)331 void MediaCodec::ProcessInputBufferInner(bool isTriggeredByOutPort, bool isFlushed, uint32_t &bufferStatus)
332 {
333 FALSE_RETURN_MSG_D(inputBufferQueueConsumer_ != nullptr, "inputBufferQueueConsumer is nullptr!");
334 uint32_t filledBufferSize = inputBufferQueueConsumer_->GetFilledBufferSize();
335 uint32_t eosStatus = inputBufferEosStatus_.load();
336 bool isOutAvail = isOutputBufferAvailable_.load();
337 bufferStatus = static_cast<uint32_t>(InOutPortBufferStatus::INIT_IGNORE_RET);
338 MediaAVCodec::AVCodecTrace trace(std::string("MediaCodec::ProcessInputBufferInner:") +
339 (isTriggeredByOutPort ? "1" : "0") + "," + (isFlushed ? "1" : "0") + "," + std::to_string(filledBufferSize) +
340 "," + (isOutAvail ? "1" : "0") + "," + std::to_string(eosStatus));
341 MEDIA_LOG_DD("ProcessInputBufferInnerr isTriggeredByOutPort:" PUBLIC_LOG_D32 ", isFlushed:" PUBLIC_LOG_D32
342 ", isOutAvail:" PUBLIC_LOG_D32 ", filledBufferSize:" PUBLIC_LOG_U32 ", eosStatus:" PUBLIC_LOG_U32,
343 isTriggeredByOutPort, isFlushed, isOutAvail, filledBufferSize, eosStatus);
344 FALSE_RETURN_MSG_D(!isFlushed, "ProcessInputBufferInner isFlushed true");
345 if (filledBufferSize == 0 && isOutputBufferAvailable_.load() && eosStatus == 0) {
346 bufferStatus = static_cast<uint32_t>(InOutPortBufferStatus::OUTPORT_AVAIL);
347 MEDIA_LOG_I("ProcessInputBufferInner ignore");
348 return;
349 }
350
351 Status ret = Status::OK;
352 // The last process failed to RequestBuffer from outputBufferQueueProducer, perform HandleOutputBufferInner firstly.
353 if (!isOutAvail || eosStatus != 0) {
354 CHECK_AND_RETURN_LOGD(HandleOutputBufferInner(ret, bufferStatus, filledBufferSize, eosStatus),
355 "HandleOutputBufferInner S1, ret:" PUBLIC_LOG_D32, static_cast<int32_t>(ret));
356 inputBufferEosStatus_.store(0);
357 }
358
359 bool isProcessingNeeded = false;
360 eosStatus = 0;
361 ret = Status::OK;
362 HandleInputBufferInner(eosStatus, isProcessingNeeded, ret);
363 filledBufferSize = inputBufferQueueConsumer_->GetFilledBufferSize();
364 if (!isProcessingNeeded) {
365 if (bufferStatus != static_cast<uint32_t>(InOutPortBufferStatus::INIT_IGNORE_RET)) {
366 filledBufferSize > 0 ? (bufferStatus |= static_cast<uint32_t>(InOutPortBufferStatus::INPORT_AVAIL)) :
367 (bufferStatus &= ~static_cast<uint32_t>(InOutPortBufferStatus::INPORT_AVAIL));
368 } else {
369 // Normally this case happen with low probability, assuming OutputBuffer available not make negative effect
370 bufferStatus = static_cast<uint32_t>(InOutPortBufferStatus::OUTPORT_AVAIL) |
371 (filledBufferSize > 0 ? static_cast<uint32_t>(InOutPortBufferStatus::INPORT_AVAIL) : 0);
372 }
373 MEDIA_LOG_I("HandleInputBufferInner failed, ret:" PUBLIC_LOG_D32 ", bufferStatus:" PUBLIC_LOG_U32X,
374 static_cast<int32_t>(ret), bufferStatus);
375 return;
376 }
377
378 inputBufferEosStatus_.store(eosStatus);
379 CHECK_AND_RETURN_LOGD(HandleOutputBufferInner(ret, bufferStatus, filledBufferSize, eosStatus),
380 "HandleOutputBufferInner S2, ret:" PUBLIC_LOG_D32, static_cast<int32_t>(ret));
381 inputBufferEosStatus_.store(0);
382 }
383
HandleOutputBufferInner(Status & ret,uint32_t & bufferStatus,uint32_t filledBufferSize,uint32_t eosStatus)384 bool MediaCodec::HandleOutputBufferInner(Status &ret, uint32_t &bufferStatus, uint32_t filledBufferSize,
385 uint32_t eosStatus)
386 {
387 MEDIA_TRACE_DEBUG(std::string("MediaCodec::HandleOutputBufferInner:") + std::to_string(eosStatus));
388 bool isBufferAvailable = false;
389 do {
390 isBufferAvailable = false;
391 ret = HandleOutputBufferOnce(isBufferAvailable, eosStatus, false);
392 } while (ret == Status::ERROR_AGAIN);
393
394 isOutputBufferAvailable_.store(isBufferAvailable);
395
396 bool isGoingOn = isBufferAvailable;
397 bufferStatus = (filledBufferSize > 0) ? static_cast<uint32_t>(InOutPortBufferStatus::INPORT_AVAIL) : 0;
398 if (!isBufferAvailable) {
399 bufferStatus |= (eosStatus == MediaAVCodec::AVCODEC_BUFFER_FLAG_EOS) ?
400 static_cast<uint32_t>(InOutPortBufferStatus::OUT_EOS_START) : bufferStatus;
401 } else {
402 bufferStatus |= static_cast<uint32_t>(InOutPortBufferStatus::OUTPORT_AVAIL);
403 if (eosStatus == MediaAVCodec::AVCODEC_BUFFER_FLAG_EOS) {
404 bufferStatus |= static_cast<uint32_t>(InOutPortBufferStatus::OUT_EOS_START) |
405 static_cast<uint32_t>(InOutPortBufferStatus::OUT_EOS_DONE);
406 inputBufferEosStatus_.store(0);
407 isGoingOn = false;
408 MEDIA_LOG_I("HandleOutputBufferInner OUT_EOS_DONE");
409 }
410 }
411
412 MEDIA_LOG_DD("HandleOutputBufferInner ret:" PUBLIC_LOG_D32 ", isGoingOn:" PUBLIC_LOG_D32 ", isBufferAvailable:"
413 PUBLIC_LOG_D32 ", eosStatus:" PUBLIC_LOG_U32 ", bufferStatus:" PUBLIC_LOG_U32X,
414 static_cast<int32_t>(ret), isGoingOn, isBufferAvailable, eosStatus, bufferStatus);
415
416 return isGoingOn;
417 }
418
ResetBufferStatusInfo()419 void MediaCodec::ResetBufferStatusInfo()
420 {
421 if (cachedOutputBuffer_ && outputBufferQueueProducer_) {
422 outputBufferQueueProducer_->PushBuffer(cachedOutputBuffer_, false);
423 cachedOutputBuffer_ = nullptr;
424 }
425 inputBufferEosStatus_.store(0);
426 isOutputBufferAvailable_.store(true);
427 }
428
GetInputSurface()429 sptr<Surface> MediaCodec::GetInputSurface()
430 {
431 AutoLock lock(stateMutex_);
432 FALSE_RETURN_V(state_ == CodecState::PREPARED, nullptr);
433 CHECK_AND_RETURN_RET_LOG(!isBufferMode_, nullptr, "GetInputBufferQueue isBufferMode_");
434 isSurfaceMode_ = true;
435 return nullptr;
436 }
437
Start()438 int32_t MediaCodec::Start()
439 {
440 AutoLock lock(stateMutex_);
441 MEDIA_LOG_I("Start enter");
442 MediaAVCodec::AVCodecTrace trace("MediaCodec::Start");
443 FALSE_RETURN_V(state_ != CodecState::RUNNING, (int32_t)Status::OK);
444 FALSE_RETURN_V(state_ == CodecState::PREPARED || state_ == CodecState::FLUSHED,
445 (int32_t)Status::ERROR_INVALID_STATE);
446 state_ = CodecState::STARTING;
447 auto ret = codecPlugin_->Start();
448 FALSE_RETURN_V_MSG_E(ret == Status::OK, (int32_t)ret, "plugin start failed");
449 state_ = CodecState::RUNNING;
450 return (int32_t)ret;
451 }
452
Stop()453 int32_t MediaCodec::Stop()
454 {
455 AutoLock lock(stateMutex_);
456 MediaAVCodec::AVCodecTrace trace("MediaCodec::Stop");
457 MEDIA_LOG_I("Stop enter");
458 FALSE_RETURN_V_MSG_E(codecPlugin_ != nullptr, (int32_t)Status::OK, "codecPlugin_ is nullptr");
459 FALSE_RETURN_V(state_ != CodecState::PREPARED, (int32_t)Status::OK);
460 if (state_ == CodecState::UNINITIALIZED || state_ == CodecState::STOPPING || state_ == CodecState::RELEASING) {
461 MEDIA_LOG_D("Stop, state_=%{public}s", StateToString(state_).data());
462 return (int32_t)Status::OK;
463 }
464 FALSE_RETURN_V(state_ == CodecState::RUNNING || state_ == CodecState::END_OF_STREAM ||
465 state_ == CodecState::FLUSHED, (int32_t)Status::ERROR_INVALID_STATE);
466 state_ = CodecState::STOPPING;
467 auto ret = codecPlugin_->Stop();
468 MEDIA_LOG_I("codec Stop, state from %{public}s to Stop", StateToString(state_).data());
469 FALSE_RETURN_V_MSG_E(ret == Status::OK, (int32_t)ret, "plugin stop failed");
470 ClearInputBuffer();
471 ResetBufferStatusInfo();
472 state_ = CodecState::PREPARED;
473 return (int32_t)ret;
474 }
475
Flush()476 int32_t MediaCodec::Flush()
477 {
478 AutoLock lock(stateMutex_);
479 MEDIA_LOG_I("Flush enter");
480 if (state_ == CodecState::FLUSHED) {
481 MEDIA_LOG_W("Flush, state is already flushed, state_=%{public}s .", StateToString(state_).data());
482 return (int32_t)Status::OK;
483 }
484 if (state_ != CodecState::RUNNING && state_ != CodecState::END_OF_STREAM) {
485 MEDIA_LOG_E("Flush failed, state =%{public}s", StateToString(state_).data());
486 return (int32_t)Status::ERROR_INVALID_STATE;
487 }
488 MEDIA_LOG_I("Flush, state from %{public}s to FLUSHING", StateToString(state_).data());
489 state_ = CodecState::FLUSHING;
490 inputBufferQueueProducer_->Clear();
491 auto ret = codecPlugin_->Flush();
492 FALSE_RETURN_V_MSG_E(ret == Status::OK, (int32_t)ret, "plugin flush failed");
493 ClearInputBuffer();
494 ResetBufferStatusInfo();
495 state_ = CodecState::FLUSHED;
496 return (int32_t)ret;
497 }
498
Reset()499 int32_t MediaCodec::Reset()
500 {
501 AutoLock lock(stateMutex_);
502 MediaAVCodec::AVCodecTrace trace("MediaCodec::Reset");
503 MEDIA_LOG_I("Reset enter");
504 if (state_ == CodecState::UNINITIALIZED || state_ == CodecState::RELEASING) {
505 MEDIA_LOG_W("adapter reset, state is already released, state =%{public}s .", StateToString(state_).data());
506 return (int32_t)Status::OK;
507 }
508 if (state_ == CodecState::INITIALIZING) {
509 MEDIA_LOG_W("adapter reset, state is initialized, state =%{public}s .", StateToString(state_).data());
510 state_ = CodecState::INITIALIZED;
511 return (int32_t)Status::OK;
512 }
513 auto ret = codecPlugin_->Reset();
514 FALSE_RETURN_V_MSG_E(ret == Status::OK, (int32_t)ret, "plugin reset failed");
515 ClearInputBuffer();
516 ResetBufferStatusInfo();
517 state_ = CodecState::INITIALIZED;
518 return (int32_t)ret;
519 }
520
Release()521 int32_t MediaCodec::Release()
522 {
523 AutoLock lock(stateMutex_);
524 MediaAVCodec::AVCodecTrace trace("MediaCodec::Release");
525 MEDIA_LOG_I("Release enter");
526 FALSE_RETURN_V_MSG_E(codecPlugin_ != nullptr, (int32_t)Status::OK, "codecPlugin_ is nullptr");
527 if (state_ == CodecState::UNINITIALIZED || state_ == CodecState::RELEASING) {
528 MEDIA_LOG_W("codec Release, state isnot completely correct, state =%{public}s .", StateToString(state_).data());
529 return (int32_t)Status::OK;
530 }
531
532 if (state_ == CodecState::INITIALIZING) {
533 MEDIA_LOG_W("codec Release, state isnot completely correct, state =%{public}s .", StateToString(state_).data());
534 state_ = CodecState::RELEASING;
535 return (int32_t)Status::OK;
536 }
537 MEDIA_LOG_I("codec Release, state from %{public}s to RELEASING", StateToString(state_).data());
538 state_ = CodecState::RELEASING;
539 auto ret = codecPlugin_->Release();
540 FALSE_RETURN_V_MSG_E(ret == Status::OK, (int32_t)ret, "plugin release failed");
541 codecPlugin_ = nullptr;
542 ResetBufferStatusInfo();
543 ClearBufferQueue();
544 if (dumpDataInputFs_ != nullptr && dumpDataInputFs_->is_open()) {
545 dumpDataInputFs_->flush();
546 dumpDataInputFs_->close();
547 }
548 if (dumpDataOutputFs_ != nullptr && dumpDataOutputFs_->is_open()) {
549 dumpDataOutputFs_->flush();
550 dumpDataOutputFs_->close();
551 }
552 state_ = CodecState::UNINITIALIZED;
553 return (int32_t)ret;
554 }
555
NotifyEos()556 int32_t MediaCodec::NotifyEos()
557 {
558 AutoLock lock(stateMutex_);
559 FALSE_RETURN_V(state_ != CodecState::END_OF_STREAM, (int32_t)Status::OK);
560 FALSE_RETURN_V(state_ == CodecState::RUNNING, (int32_t)Status::ERROR_INVALID_STATE);
561 state_ = CodecState::END_OF_STREAM;
562 return (int32_t)Status::OK;
563 }
564
SetParameter(const std::shared_ptr<Meta> & parameter)565 int32_t MediaCodec::SetParameter(const std::shared_ptr<Meta> ¶meter)
566 {
567 AutoLock lock(stateMutex_);
568 FALSE_RETURN_V(parameter != nullptr, (int32_t)Status::ERROR_INVALID_PARAMETER);
569 FALSE_RETURN_V(state_ != CodecState::UNINITIALIZED && state_ != CodecState::INITIALIZED &&
570 state_ != CodecState::PREPARED, (int32_t)Status::ERROR_INVALID_STATE);
571 auto ret = codecPlugin_->SetParameter(parameter);
572 FALSE_RETURN_V_MSG_E(ret == Status::OK, (int32_t)ret, "plugin set parameter failed");
573 return (int32_t)ret;
574 }
575
SetDumpInfo(bool isDump,uint64_t instanceId)576 void MediaCodec::SetDumpInfo(bool isDump, uint64_t instanceId)
577 {
578 (void)instanceId;
579 auto tid = gettid();
580 if (isDump && tid <= 0) {
581 MEDIA_LOG_W("Cannot dump with tid <= 0.");
582 return;
583 }
584 dumpPrefix_ = std::to_string(tid);
585 isDump_ = isDump;
586 }
587
GetOutputFormat(std::shared_ptr<Meta> & parameter)588 int32_t MediaCodec::GetOutputFormat(std::shared_ptr<Meta> ¶meter)
589 {
590 AutoLock lock(stateMutex_);
591 FALSE_RETURN_V_MSG_E(state_ != CodecState::UNINITIALIZED, (int32_t)Status::ERROR_INVALID_STATE,
592 "status incorrect,get output format failed.");
593 FALSE_RETURN_V(codecPlugin_ != nullptr, (int32_t)Status::ERROR_INVALID_STATE);
594 FALSE_RETURN_V(parameter != nullptr, (int32_t)Status::ERROR_INVALID_PARAMETER);
595 auto ret = codecPlugin_->GetParameter(parameter);
596 FALSE_RETURN_V_MSG_E(ret == Status::OK, (int32_t)ret, "plugin get parameter failed");
597 return (int32_t)ret;
598 }
599
AttachBufffer()600 Status MediaCodec::AttachBufffer()
601 {
602 MEDIA_LOG_I("AttachBufffer enter");
603 int inputBufferNum = DEFAULT_BUFFER_NUM;
604 MemoryType memoryType;
605 #ifndef MEDIA_OHOS
606 memoryType = MemoryType::VIRTUAL_MEMORY;
607 #else
608 memoryType = MemoryType::SHARED_MEMORY;
609 #endif
610 if (inputBufferQueue_ == nullptr) {
611 inputBufferQueue_ = AVBufferQueue::Create(inputBufferNum, memoryType, INPUT_BUFFER_QUEUE_NAME);
612 }
613 FALSE_RETURN_V_MSG_E(inputBufferQueue_ != nullptr, Status::ERROR_UNKNOWN,
614 "inputBufferQueue_ is nullptr");
615 inputBufferQueueProducer_ = inputBufferQueue_->GetProducer();
616 std::shared_ptr<Meta> inputBufferConfig = std::make_shared<Meta>();
617 FALSE_RETURN_V_MSG_E(codecPlugin_ != nullptr, Status::ERROR_UNKNOWN, "codecPlugin_ is nullptr");
618 auto ret = codecPlugin_->GetParameter(inputBufferConfig);
619 FALSE_RETURN_V_MSG_E(ret == Status::OK, ret, "attachBufffer failed, plugin get param error");
620 int32_t capacity = 0;
621 FALSE_RETURN_V_MSG_E(inputBufferConfig != nullptr, Status::ERROR_UNKNOWN,
622 "inputBufferConfig is nullptr");
623 FALSE_RETURN_V(inputBufferConfig->Get<Tag::AUDIO_MAX_INPUT_SIZE>(capacity),
624 Status::ERROR_INVALID_PARAMETER);
625 for (int i = 0; i < inputBufferNum; i++) {
626 std::shared_ptr<AVAllocator> avAllocator;
627 #ifndef MEDIA_OHOS
628 MEDIA_LOG_D("CreateVirtualAllocator,i=%{public}d capacity=%{public}d", i, capacity);
629 avAllocator = AVAllocatorFactory::CreateVirtualAllocator();
630 #else
631 MEDIA_LOG_D("CreateSharedAllocator,i=%{public}d capacity=%{public}d", i, capacity);
632 avAllocator = AVAllocatorFactory::CreateSharedAllocator(MemoryFlag::MEMORY_READ_WRITE);
633 #endif
634 std::shared_ptr<AVBuffer> inputBuffer = AVBuffer::CreateAVBuffer(avAllocator, capacity);
635 FALSE_RETURN_V_MSG_E(inputBuffer != nullptr, Status::ERROR_UNKNOWN,
636 "inputBuffer is nullptr");
637 FALSE_RETURN_V_MSG_E(inputBufferQueueProducer_ != nullptr, Status::ERROR_UNKNOWN,
638 "inputBufferQueueProducer_ is nullptr");
639 inputBufferQueueProducer_->AttachBuffer(inputBuffer, false);
640 MEDIA_LOG_I("Attach intput buffer. index: %{public}d, bufferId: %{public}" PRIu64,
641 i, inputBuffer->GetUniqueId());
642 inputBufferVector_.push_back(inputBuffer);
643 }
644 return Status::OK;
645 }
646
AttachDrmBufffer(std::shared_ptr<AVBuffer> & drmInbuf,std::shared_ptr<AVBuffer> & drmOutbuf,uint32_t size)647 Status MediaCodec::AttachDrmBufffer(std::shared_ptr<AVBuffer> &drmInbuf, std::shared_ptr<AVBuffer> &drmOutbuf,
648 uint32_t size)
649 {
650 MEDIA_LOG_D("AttachDrmBufffer");
651 std::shared_ptr<AVAllocator> avAllocator;
652 avAllocator = AVAllocatorFactory::CreateSharedAllocator(MemoryFlag::MEMORY_READ_WRITE);
653 FALSE_RETURN_V_MSG_E(avAllocator != nullptr, Status::ERROR_UNKNOWN,
654 "avAllocator is nullptr");
655
656 drmInbuf = AVBuffer::CreateAVBuffer(avAllocator, size);
657 FALSE_RETURN_V_MSG_E(drmInbuf != nullptr, Status::ERROR_UNKNOWN,
658 "drmInbuf is nullptr");
659 FALSE_RETURN_V_MSG_E(drmInbuf->memory_ != nullptr, Status::ERROR_UNKNOWN,
660 "drmInbuf->memory_ is nullptr");
661 drmInbuf->memory_->SetSize(size);
662
663 drmOutbuf = AVBuffer::CreateAVBuffer(avAllocator, size);
664 FALSE_RETURN_V_MSG_E(drmOutbuf != nullptr, Status::ERROR_UNKNOWN,
665 "drmOutbuf is nullptr");
666 FALSE_RETURN_V_MSG_E(drmOutbuf->memory_ != nullptr, Status::ERROR_UNKNOWN,
667 "drmOutbuf->memory_ is nullptr");
668 drmOutbuf->memory_->SetSize(size);
669 return Status::OK;
670 }
671
DrmAudioCencDecrypt(std::shared_ptr<AVBuffer> & filledInputBuffer)672 Status MediaCodec::DrmAudioCencDecrypt(std::shared_ptr<AVBuffer> &filledInputBuffer)
673 {
674 MEDIA_LOG_D("DrmAudioCencDecrypt enter");
675 Status ret = Status::OK;
676
677 // 1. allocate drm buffer
678 uint32_t bufSize = static_cast<uint32_t>(filledInputBuffer->memory_->GetSize());
679 if (bufSize == 0) {
680 MEDIA_LOG_D("MediaCodec DrmAudioCencDecrypt input buffer size equal 0");
681 return ret;
682 }
683 std::shared_ptr<AVBuffer> drmInBuf;
684 std::shared_ptr<AVBuffer> drmOutBuf;
685 ret = AttachDrmBufffer(drmInBuf, drmOutBuf, bufSize);
686 FALSE_RETURN_V_MSG_E(ret == Status::OK, Status::ERROR_UNKNOWN, "AttachDrmBufffer failed");
687
688 // 2. copy data to drm input buffer
689 int32_t drmRes = memcpy_s(drmInBuf->memory_->GetAddr(), bufSize,
690 filledInputBuffer->memory_->GetAddr(), bufSize);
691 FALSE_RETURN_V_MSG_E(drmRes == 0, Status::ERROR_UNKNOWN, "memcpy_s drmInBuf failed");
692 if (filledInputBuffer->meta_ != nullptr) {
693 *(drmInBuf->meta_) = *(filledInputBuffer->meta_);
694 }
695 // 4. decrypt
696 drmRes = drmDecryptor_->DrmAudioCencDecrypt(drmInBuf, drmOutBuf, bufSize);
697 FALSE_RETURN_V_MSG_E(drmRes == 0, Status::ERROR_DRM_DECRYPT_FAILED, "DrmAudioCencDecrypt return error");
698
699 // 5. copy decrypted data from drm output buffer back
700 drmRes = memcpy_s(filledInputBuffer->memory_->GetAddr(), bufSize,
701 drmOutBuf->memory_->GetAddr(), bufSize);
702 FALSE_RETURN_V_MSG_E(drmRes == 0, Status::ERROR_UNKNOWN, "memcpy_s drmOutBuf failed");
703 return Status::OK;
704 }
705
HandleAudioCencDecryptError()706 void MediaCodec::HandleAudioCencDecryptError()
707 {
708 MEDIA_LOG_E("MediaCodec DrmAudioCencDecrypt failed.");
709 auto realPtr = mediaCodecCallback_.lock();
710 if (realPtr != nullptr) {
711 realPtr->OnError(CodecErrorType::CODEC_DRM_DECRYTION_FAILED,
712 static_cast<int32_t>(Status::ERROR_DRM_DECRYPT_FAILED));
713 }
714 }
715
PrepareInputBufferQueue()716 int32_t MediaCodec::PrepareInputBufferQueue()
717 {
718 MEDIA_LOG_I("PrepareInputBufferQueue enter");
719 std::vector<std::shared_ptr<AVBuffer>> inputBuffers;
720 MediaAVCodec::AVCodecTrace trace("MediaCodec::PrepareInputBufferQueue");
721 FALSE_RETURN_V_MSG_E(codecPlugin_ != nullptr, (int32_t)Status::ERROR_UNKNOWN, "codecPlugin_ is nullptr");
722 auto ret = codecPlugin_->GetInputBuffers(inputBuffers);
723 FALSE_RETURN_V_MSG_E(ret == Status::OK, (int32_t)ret, "pluign getInputBuffers failed");
724 if (inputBuffers.empty()) {
725 ret = AttachBufffer();
726 if (ret != Status::OK) {
727 MEDIA_LOG_E("GetParameter failed");
728 return (int32_t)ret;
729 }
730 } else {
731 if (inputBufferQueue_ == nullptr) {
732 inputBufferQueue_ =
733 AVBufferQueue::Create(inputBuffers.size(), MemoryType::HARDWARE_MEMORY, INPUT_BUFFER_QUEUE_NAME);
734 }
735 FALSE_RETURN_V_MSG_E(inputBufferQueue_ != nullptr, (int32_t)Status::ERROR_UNKNOWN,
736 "inputBufferQueue_ is nullptr");
737 inputBufferQueueProducer_ = inputBufferQueue_->GetProducer();
738 for (uint32_t i = 0; i < inputBuffers.size(); i++) {
739 inputBufferQueueProducer_->AttachBuffer(inputBuffers[i], false);
740 inputBufferVector_.push_back(inputBuffers[i]);
741 }
742 }
743 FALSE_RETURN_V_MSG_E(inputBufferQueue_ != nullptr, (int32_t)Status::ERROR_UNKNOWN, "inputBufferQueue_ is nullptr");
744 inputBufferQueueConsumer_ = inputBufferQueue_->GetConsumer();
745 sptr<IConsumerListener> listener = new InputBufferAvailableListener(shared_from_this());
746 FALSE_RETURN_V_MSG_E(inputBufferQueueConsumer_ != nullptr, (int32_t)Status::ERROR_UNKNOWN,
747 "inputBufferQueueConsumer_ is nullptr");
748 inputBufferQueueConsumer_->SetBufferAvailableListener(listener);
749 return (int32_t)ret;
750 }
751
PrepareOutputBufferQueue()752 int32_t MediaCodec::PrepareOutputBufferQueue()
753 {
754 MEDIA_LOG_I("PrepareOutputBufferQueue enter");
755 std::vector<std::shared_ptr<AVBuffer>> outputBuffers;
756 MediaAVCodec::AVCodecTrace trace("MediaCodec::PrepareOutputBufferQueue");
757 FALSE_RETURN_V_MSG_E(codecPlugin_ != nullptr, (int32_t)Status::ERROR_INVALID_STATE, "codecPlugin_ is nullptr");
758 auto ret = codecPlugin_->GetOutputBuffers(outputBuffers);
759 FALSE_RETURN_V_MSG_E(ret == Status::OK, (int32_t)ret, "GetOutputBuffers failed");
760 FALSE_RETURN_V_MSG_E(outputBufferQueueProducer_ != nullptr, (int32_t)Status::ERROR_INVALID_STATE,
761 "outputBufferQueueProducer_ is nullptr");
762 if (outputBuffers.empty()) {
763 int outputBufferNum = 30;
764 std::shared_ptr<Meta> outputBufferConfig = std::make_shared<Meta>();
765 ret = codecPlugin_->GetParameter(outputBufferConfig);
766 FALSE_RETURN_V_MSG_E(ret == Status::OK, (int32_t)ret, "GetParameter failed");
767 FALSE_RETURN_V_MSG_E(outputBufferConfig != nullptr, (int32_t)Status::ERROR_INVALID_STATE,
768 "outputBufferConfig is nullptr");
769 FALSE_RETURN_V(outputBufferConfig->Get<Tag::AUDIO_MAX_OUTPUT_SIZE>(outputBufferCapacity_),
770 (int32_t)Status::ERROR_INVALID_PARAMETER);
771 for (int i = 0; i < outputBufferNum; i++) {
772 auto avAllocator = AVAllocatorFactory::CreateSharedAllocator(MemoryFlag::MEMORY_READ_WRITE);
773 std::shared_ptr<AVBuffer> outputBuffer = AVBuffer::CreateAVBuffer(avAllocator, outputBufferCapacity_);
774 FALSE_RETURN_V_MSG_E(outputBuffer != nullptr, (int32_t)Status::ERROR_INVALID_STATE,
775 "outputBuffer is nullptr");
776 if (outputBufferQueueProducer_->AttachBuffer(outputBuffer, false) == Status::OK) {
777 MEDIA_LOG_D("Attach output buffer. index: %{public}d, bufferId: %{public}" PRIu64, i,
778 outputBuffer->GetUniqueId());
779 outputBufferVector_.push_back(outputBuffer);
780 }
781 }
782 } else {
783 for (uint32_t i = 0; i < outputBuffers.size(); i++) {
784 if (outputBufferQueueProducer_->AttachBuffer(outputBuffers[i], false) == Status::OK) {
785 MEDIA_LOG_D("Attach output buffer. index: %{public}d, bufferId: %{public}" PRIu64, i,
786 outputBuffers[i]->GetUniqueId());
787 outputBufferVector_.push_back(outputBuffers[i]);
788 }
789 }
790 }
791 FALSE_RETURN_V_MSG_E(outputBufferVector_.size() > 0, (int32_t)Status::ERROR_INVALID_STATE, "Attach no buffer");
792 return (int32_t)ret;
793 }
794
ProcessInputBuffer()795 void MediaCodec::ProcessInputBuffer()
796 {
797 MEDIA_LOG_DD("ProcessInputBuffer enter");
798 MEDIA_TRACE_DEBUG("MediaCodec::ProcessInputBuffer");
799
800 bool isProcessingNeeded = false;
801 Status ret = Status::OK;
802 uint32_t eosStatus = 0;
803 HandleInputBufferInner(eosStatus, isProcessingNeeded, ret);
804 CHECK_AND_RETURN_LOG(isProcessingNeeded, "ProcessInputBuffer failed %{public}d", static_cast<int32_t>(ret));
805
806 do {
807 ret = HandleOutputBuffer(eosStatus);
808 } while (ret == Status::ERROR_AGAIN);
809 }
810
HandleInputBufferInner(uint32_t & eosStatus,bool & isProcessingNeeded,Status & ret)811 void MediaCodec::HandleInputBufferInner(uint32_t &eosStatus, bool &isProcessingNeeded, Status &ret)
812 {
813 MEDIA_TRACE_DEBUG_POSTFIX("MediaCodec::HandleInputBufferInner", "1");
814
815 std::shared_ptr<AVBuffer> filledInputBuffer;
816 if (state_ != CodecState::RUNNING) {
817 MEDIA_LOG_I("HandleInputBufferInner status changed, current status is not running");
818 ret = Status::ERROR_INVALID_STATE;
819 return;
820 }
821 {
822 MEDIA_TRACE_DEBUG_POSTFIX("MediaCodec::HandleInputBufferInner-AcquireBuffer", "2");
823 ret = inputBufferQueueConsumer_->AcquireBuffer(filledInputBuffer);
824 CHECK_AND_RETURN_LOG(ret == Status::OK && filledInputBuffer, "HandleInputBufferInner AcquireBuffer fail");
825 }
826 if (state_ != CodecState::RUNNING) {
827 MEDIA_LOG_W("HandleInputBufferInner not running, ReleaseBuffer name:MediaCodecInputBufferQueue");
828 inputBufferQueueConsumer_->ReleaseBuffer(filledInputBuffer);
829 ret = Status::ERROR_INVALID_STATE;
830 return;
831 }
832 uint32_t flag = filledInputBuffer->flag_;
833 int8_t retryCount = 0;
834 do {
835 if (drmDecryptor_ != nullptr) {
836 MediaAVCodec::AVCodecTrace trace("MediaCodec::HandleInputBufferInner-DrmAudioCencDecrypt");
837 ret = DrmAudioCencDecrypt(filledInputBuffer);
838 if (ret != Status::OK) {
839 HandleAudioCencDecryptError();
840 break;
841 }
842 }
843
844 ret = CodePluginInputBuffer(filledInputBuffer);
845 if (ret != Status::OK) {
846 retryCount++;
847 continue;
848 }
849 } while (ret != Status::OK && retryCount < RETRY && state_ == CodecState::RUNNING);
850
851 if (ret != Status::OK || state_ != CodecState::RUNNING) {
852 inputBufferQueueConsumer_->ReleaseBuffer(filledInputBuffer);
853 MEDIA_LOG_E("Plugin queueInputBuffer failed, state_:%{public}d, ret:%{public}d", state_.load(), ret);
854 return;
855 }
856 isProcessingNeeded = true;
857 eosStatus = flag;
858 }
859
860 #ifdef SUPPORT_DRM
SetAudioDecryptionConfig(const sptr<DrmStandard::IMediaKeySessionService> & keySession,const bool svpFlag)861 int32_t MediaCodec::SetAudioDecryptionConfig(const sptr<DrmStandard::IMediaKeySessionService> &keySession,
862 const bool svpFlag)
863 {
864 MEDIA_LOG_I("MediaCodec::SetAudioDecryptionConfig");
865 if (drmDecryptor_ == nullptr) {
866 drmDecryptor_ = std::make_shared<MediaAVCodec::CodecDrmDecrypt>();
867 }
868 FALSE_RETURN_V_MSG_E(drmDecryptor_ != nullptr, (int32_t)Status::ERROR_NO_MEMORY, "drmDecryptor is nullptr");
869 drmDecryptor_->SetDecryptionConfig(keySession, svpFlag);
870 return (int32_t)Status::OK;
871 }
872 #else
SetAudioDecryptionConfig(const sptr<DrmStandard::IMediaKeySessionService> & keySession,const bool svpFlag)873 int32_t MediaCodec::SetAudioDecryptionConfig(const sptr<DrmStandard::IMediaKeySessionService> &keySession,
874 const bool svpFlag)
875 {
876 MEDIA_LOG_I("MediaCodec::SetAudioDecryptionConfig, Not support");
877 (void)keySession;
878 (void)svpFlag;
879 return (int32_t)Status::OK;
880 }
881 #endif
882
ChangePlugin(const std::string & mime,bool isEncoder,const std::shared_ptr<Meta> & meta)883 Status MediaCodec::ChangePlugin(const std::string &mime, bool isEncoder, const std::shared_ptr<Meta> &meta)
884 {
885 Status ret = Status::OK;
886 Plugins::PluginType type;
887 if (isEncoder) {
888 type = Plugins::PluginType::AUDIO_ENCODER;
889 } else {
890 type = Plugins::PluginType::AUDIO_DECODER;
891 }
892
893 {
894 AutoLock pluginLock(codecPluginMutex_);
895 if (codecPlugin_ != nullptr) {
896 codecPlugin_->Release();
897 codecPlugin_ = nullptr;
898 }
899 codecPlugin_ = CreatePlugin(mime, type);
900
901 CHECK_AND_RETURN_RET_LOG(codecPlugin_ != nullptr, Status::ERROR_INVALID_PARAMETER, "createPlugin failed");
902 ret = codecPlugin_->SetParameter(meta);
903 if (ret != Status::OK) {
904 MEDIA_LOG_E("codecPlugin SetParameter ret %{public}d", ret);
905 return ret;
906 }
907 ret = codecPlugin_->Init();
908 if (ret != Status::OK) {
909 MEDIA_LOG_E("codecPlugin Init ret %{public}d", ret);
910 return ret;
911 }
912 ret = codecPlugin_->SetDataCallback(this);
913 if (ret != Status::OK) {
914 MEDIA_LOG_E("codecPlugin SetDataCallback ret %{public}d", ret);
915 return ret;
916 }
917 }
918
919 // discard undecoded data and unconsumed decoded data.
920 inputBufferQueueProducer_->Clear();
921 FALSE_RETURN_V_MSG_E(inputBufferQueue_ != nullptr, Status::ERROR_UNKNOWN, "inputBufferQueue_ is nullptr");
922 ClearInputBuffer();
923 ResetBufferStatusInfo();
924
925 AutoLock lock(stateMutex_);
926 PrepareInputBufferQueue();
927 PrepareOutputBufferQueue();
928 if (state_ == CodecState::RUNNING) {
929 ret = codecPlugin_->Start();
930 if (ret != Status::OK) {
931 MEDIA_LOG_E("codecPlugin Start ret %{public}d", ret);
932 }
933 }
934
935 return ret;
936 }
937
HandleOutputBuffer(uint32_t eosStatus)938 Status MediaCodec::HandleOutputBuffer(uint32_t eosStatus)
939 {
940 MEDIA_LOG_DD("HandleOutputBuffer enter");
941 bool isBufferAvailable = false;
942 Status ret = HandleOutputBufferOnce(isBufferAvailable, eosStatus, true);
943 MEDIA_LOG_DD("HandleOutputBuffer ret:%{public}d, isBufferAvailable:%{public}d", ret, isBufferAvailable);
944 return ret;
945 }
946
HandleOutputBufferOnce(bool & isBufferAvailable,uint32_t eosStatus,bool isSync)947 Status MediaCodec::HandleOutputBufferOnce(bool &isBufferAvailable, uint32_t eosStatus, bool isSync)
948 {
949 MEDIA_TRACE_DEBUG_POSTFIX("MediaCodec::HandleOutputBufferOnce-isSync:" + std::to_string(isSync), "1");
950 Status ret = Status::OK;
951 std::shared_ptr<AVBuffer> emptyOutputBuffer;
952 AVBufferConfig avBufferConfig;
953 if (cachedOutputBuffer_) {
954 std::swap(emptyOutputBuffer, cachedOutputBuffer_);
955 } else {
956 if (isSync) {
957 MediaAVCodec::AVCodecTrace traceRequestBuffer("MediaCodec::HandleOutputBufferOnce-RequestBuffer-sync");
958 do {
959 ret = outputBufferQueueProducer_->RequestBuffer(emptyOutputBuffer, avBufferConfig, TIME_OUT_MS);
960 } while (ret != Status::OK && state_ == CodecState::RUNNING);
961 } else {
962 MEDIA_TRACE_DEBUG_POSTFIX("MediaCodec::HandleOutputBufferOnce-RequestBuffer-async", "2");
963 ret = outputBufferQueueProducer_->RequestBuffer(emptyOutputBuffer, avBufferConfig, TIME_OUT_MS_INNER);
964 }
965 }
966
967 if (emptyOutputBuffer) {
968 emptyOutputBuffer->flag_ = eosStatus;
969 isBufferAvailable = true;
970 } else if (state_ != CodecState::RUNNING) {
971 return Status::OK;
972 } else {
973 return Status::ERROR_NULL_POINTER;
974 }
975
976 ret = CodePluginOutputBuffer(emptyOutputBuffer);
977 if (ret == Status::ERROR_NOT_ENOUGH_DATA) {
978 MEDIA_LOG_DD("HandleOutputBufferOnce QueueOutputBuffer ERROR_NOT_ENOUGH_DATA");
979 // To cache the empty OutputBuffer returned by RequestBuffer to improve performance
980 std::swap(emptyOutputBuffer, cachedOutputBuffer_);
981 } else if (ret == Status::ERROR_AGAIN) {
982 MEDIA_LOG_DD("HandleOutputBufferOnce The output data is not completely read, needs to be read again");
983 } else if (ret == Status::END_OF_STREAM) {
984 MEDIA_LOG_I("HandleOutputBufferOnce QueueOutputBuffer END_OF_STREAM");
985 } else if (ret != Status::OK) {
986 MEDIA_LOG_E("HandleOutputBufferOnce QueueOutputBuffer error");
987 outputBufferQueueProducer_->PushBuffer(emptyOutputBuffer, false);
988 }
989 return ret;
990 }
991
OnInputBufferDone(const std::shared_ptr<AVBuffer> & inputBuffer)992 void MediaCodec::OnInputBufferDone(const std::shared_ptr<AVBuffer> &inputBuffer)
993 {
994 FALSE_RETURN_MSG(inputBuffer != nullptr, "OnInputBufferDone fail, inputBuffer nullptr");
995 MediaAVCodec::AVCodecTrace trace(("MediaCodec::OnInputBufferDone:") +
996 std::to_string(inputBuffer->flag_) + "," + std::to_string(inputBuffer->pts_) +
997 "," + std::to_string(inputBuffer->duration_));
998 if (dumpIOEnable == "true" && dumpDataInputFs_) {
999 if (dumpDataInputFs_->is_open() && inputBuffer->memory_->GetAddr()) {
1000 MEDIA_LOG_DD("dumpIOE writing");
1001 dumpDataInputFs_->write(reinterpret_cast<const char*>(inputBuffer->memory_->GetAddr() +
1002 inputBuffer->memory_->GetOffset()), inputBuffer->memory_->GetSize());
1003 }
1004 }
1005 Status ret = inputBufferQueueConsumer_->ReleaseBuffer(inputBuffer);
1006 MEDIA_LOG_DD("0x%{public}06" PRIXPTR " OnInputBufferDone, buffer->pts:" PUBLIC_LOG_D64,
1007 FAKE_POINTER(this), inputBuffer->pts_);
1008 FALSE_RETURN_MSG(ret == Status::OK, "OnInputBufferDone fail");
1009 }
1010
OnOutputBufferDone(const std::shared_ptr<AVBuffer> & outputBuffer)1011 void MediaCodec::OnOutputBufferDone(const std::shared_ptr<AVBuffer> &outputBuffer)
1012 {
1013 FALSE_RETURN_MSG(outputBuffer != nullptr, "OnOutputBufferDone fail, outputBuffer nullptr");
1014 MediaAVCodec::AVCodecTrace trace(("MediaCodec::OnOutputBufferDone:") +
1015 std::to_string(outputBuffer->flag_) + "," + std::to_string(outputBuffer->pts_) +
1016 "," + std::to_string(outputBuffer->duration_));
1017 if (isDump_) {
1018 DumpAVBufferToFile(DUMP_PARAM, dumpPrefix_ + DUMP_FILE_NAME, outputBuffer);
1019 }
1020 if (dumpIOEnable == "true" && dumpDataOutputFs_) {
1021 if (dumpDataOutputFs_->is_open() && outputBuffer->memory_->GetAddr()) {
1022 MEDIA_LOG_DD("dumpIOE writing");
1023 dumpDataOutputFs_->write(reinterpret_cast<const char*>(outputBuffer->memory_->GetAddr() +
1024 outputBuffer->memory_->GetOffset()), outputBuffer->memory_->GetSize());
1025 }
1026 }
1027 Status ret = outputBufferQueueProducer_->PushBuffer(outputBuffer, true);
1028 auto realPtr = mediaCodecCallback_.lock();
1029 if (realPtr != nullptr) {
1030 realPtr->OnOutputBufferDone(outputBuffer);
1031 }
1032 MEDIA_LOG_DD("0x%{public}06" PRIXPTR " OnOutputBufferDone, buffer->pts:" PUBLIC_LOG_D64,
1033 FAKE_POINTER(this), outputBuffer->pts_);
1034 FALSE_RETURN_MSG(ret == Status::OK, "OnOutputBufferDone fail");
1035 }
1036
ClearBufferQueue()1037 void MediaCodec::ClearBufferQueue()
1038 {
1039 MEDIA_LOG_I("ClearBufferQueue called.");
1040 if (inputBufferQueueProducer_ != nullptr) {
1041 for (const auto &buffer : inputBufferVector_) {
1042 inputBufferQueueProducer_->DetachBuffer(buffer);
1043 }
1044 inputBufferVector_.clear();
1045 inputBufferQueueProducer_->SetQueueSize(0);
1046 }
1047 if (outputBufferQueueProducer_ != nullptr) {
1048 for (const auto &buffer : outputBufferVector_) {
1049 outputBufferQueueProducer_->DetachBuffer(buffer);
1050 }
1051 outputBufferVector_.clear();
1052 outputBufferQueueProducer_->SetQueueSize(0);
1053 }
1054 }
1055
ClearInputBuffer()1056 void MediaCodec::ClearInputBuffer()
1057 {
1058 MediaAVCodec::AVCodecTrace trace("MediaCodec::ClearInputBuffer");
1059 MEDIA_LOG_D("ClearInputBuffer enter");
1060 if (!inputBufferQueueConsumer_) {
1061 return;
1062 }
1063 std::shared_ptr<AVBuffer> filledInputBuffer;
1064 Status ret = Status::OK;
1065 while (ret == Status::OK) {
1066 ret = inputBufferQueueConsumer_->AcquireBuffer(filledInputBuffer);
1067 if (ret != Status::OK) {
1068 MEDIA_LOG_I("clear input Buffer");
1069 return;
1070 }
1071 inputBufferQueueConsumer_->ReleaseBuffer(filledInputBuffer);
1072 }
1073 }
1074
OnEvent(const std::shared_ptr<Plugins::PluginEvent> event)1075 void MediaCodec::OnEvent(const std::shared_ptr<Plugins::PluginEvent> event)
1076 {
1077 if (event->type != Plugins::PluginEventType::AUDIO_OUTPUT_FORMAT_CHANGED) {
1078 return;
1079 }
1080
1081 if (!isSupportAudioFormatChanged_) {
1082 MEDIA_LOG_W("receive audio format changed but api version is low");
1083 return;
1084 }
1085
1086 auto realPtr = mediaCodecCallback_.lock();
1087 if (realPtr != nullptr) {
1088 std::shared_ptr<Meta> format = std::make_shared<Meta>(AnyCast<Meta>(event->param));
1089 realPtr->OnOutputFormatChanged(format);
1090 } else {
1091 MEDIA_LOG_E("receive AUDIO_OUTPUT_FORMAT_CHANGED, but lock callback fail");
1092 }
1093 }
1094
StateToString(CodecState state)1095 std::string MediaCodec::StateToString(CodecState state)
1096 {
1097 std::map<CodecState, std::string> stateStrMap = {
1098 {CodecState::UNINITIALIZED, " UNINITIALIZED"},
1099 {CodecState::INITIALIZED, " INITIALIZED"},
1100 {CodecState::FLUSHED, " FLUSHED"},
1101 {CodecState::RUNNING, " RUNNING"},
1102 {CodecState::INITIALIZING, " INITIALIZING"},
1103 {CodecState::STARTING, " STARTING"},
1104 {CodecState::STOPPING, " STOPPING"},
1105 {CodecState::FLUSHING, " FLUSHING"},
1106 {CodecState::RESUMING, " RESUMING"},
1107 {CodecState::RELEASING, " RELEASING"},
1108 };
1109 return stateStrMap[state];
1110 }
1111
OnDumpInfo(int32_t fd)1112 void MediaCodec::OnDumpInfo(int32_t fd)
1113 {
1114 MEDIA_LOG_D("MediaCodec::OnDumpInfo called.");
1115 if (fd < 0) {
1116 MEDIA_LOG_E("MediaCodec::OnDumpInfo fd is invalid.");
1117 return;
1118 }
1119 std::string dumpString;
1120 dumpString += "MediaCodec plugin name: " + codecPluginName_ + "\n";
1121 dumpString += "MediaCodec buffer size is:" + std::to_string(inputBufferQueue_->GetQueueSize()) + "\n";
1122 int ret = write(fd, dumpString.c_str(), dumpString.size());
1123 if (ret < 0) {
1124 MEDIA_LOG_E("MediaCodec::OnDumpInfo write failed.");
1125 return;
1126 }
1127 }
1128
GetApiVersion()1129 uint32_t MediaCodec::GetApiVersion()
1130 {
1131 uint32_t apiVersion = INVALID_API_VERSION;
1132 OHOS::sptr<OHOS::ISystemAbilityManager> systemAbilityManager =
1133 OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
1134 OHOS::sptr<OHOS::IRemoteObject> remoteObject =
1135 systemAbilityManager->CheckSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
1136 sptr<AppExecFwk::IBundleMgr> iBundleMgr = OHOS::iface_cast<AppExecFwk::IBundleMgr>(remoteObject);
1137 if (iBundleMgr == nullptr) {
1138 MEDIA_LOG_W("GetApiVersion IBundleMgr is nullptr");
1139 return apiVersion;
1140 }
1141 AppExecFwk::BundleInfo bundleInfo;
1142 if (iBundleMgr->GetBundleInfoForSelf(0, bundleInfo) == ERR_OK) {
1143 apiVersion = bundleInfo.targetVersion % API_VERSION_MOD;
1144 MEDIA_LOG_I("GetApiVersion targetVersion: %{public}u", bundleInfo.targetVersion);
1145 } else {
1146 MEDIA_LOG_W("GetApiVersion failed, call by SA or test maybe");
1147 }
1148 return apiVersion;
1149 }
1150
CodePluginInputBuffer(const std::shared_ptr<AVBuffer> & inputBuffer)1151 Status MediaCodec::CodePluginInputBuffer(const std::shared_ptr<AVBuffer> &inputBuffer)
1152 {
1153 AutoLock pluginLock(codecPluginMutex_);
1154 if (codecPlugin_ != nullptr) {
1155 MEDIA_TRACE_DEBUG(std::string("MediaCodec::CodePluginInputBuffer-QueueInputBuffer:") +
1156 std::to_string(inputBuffer->flag_) + "," + std::to_string(inputBuffer->pts_) +
1157 "," + std::to_string(inputBuffer->duration_));
1158 return codecPlugin_->QueueInputBuffer(inputBuffer);
1159 } else {
1160 MEDIA_LOG_E("plugin is null");
1161 return Status::ERROR_UNKNOWN;
1162 }
1163 }
1164
CodePluginOutputBuffer(std::shared_ptr<AVBuffer> & outputBuffer)1165 Status MediaCodec::CodePluginOutputBuffer(std::shared_ptr<AVBuffer> &outputBuffer)
1166 {
1167 AutoLock pluginLock(codecPluginMutex_);
1168 FALSE_RETURN_V_MSG_E(codecPlugin_ != nullptr, Status::ERROR_INVALID_STATE, "plugin is null");
1169
1170 MEDIA_TRACE_DEBUG("MediaCodec::CodePluginOutputBuffer");
1171 return codecPlugin_->QueueOutputBuffer(outputBuffer);
1172 }
1173
1174 } // namespace Media
1175 } // namespace OHOS
1176