1 /*
2 * Copyright (C) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "codec_server.h"
17 #include <functional>
18 #include <malloc.h>
19 #include <map>
20 #include <unistd.h>
21 #include <limits>
22 #include <vector>
23 #include "avcodec_codec_name.h"
24 #include "avcodec_dump_utils.h"
25 #include "avcodec_errors.h"
26 #include "avcodec_log.h"
27 #include "avcodec_sysevent.h"
28 #include "buffer/avbuffer.h"
29 #include "codec_ability_singleton.h"
30 #include "codec_factory.h"
31 #include "media_description.h"
32 #include "meta/meta_key.h"
33 #include "surface_type.h"
34
35 namespace {
36 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_FRAMEWORK, "CodecServer"};
37 enum DumpIndex : uint32_t {
38 DUMP_INDEX_FORWARD_CALLER_PID = 0x01'01'01'00,
39 DUMP_INDEX_FORWARD_CALLER_UID = 0x01'01'02'00,
40 DUMP_INDEX_FORWARD_CALLER_PROCESS_NAME = 0x01'01'03'00,
41 DUMP_INDEX_CALLER_PID = 0x01'01'04'00,
42 DUMP_INDEX_CALLER_UID = 0x01'01'05'00,
43 DUMP_INDEX_CALLER_PROCESS_NAME = 0x01'01'06'00,
44 DUMP_INDEX_STATUS = 0x01'01'07'00,
45 DUMP_INDEX_LAST_ERROR = 0x01'01'08'00,
46 DUMP_INDEX_CODEC_INFO_START = 0x01'02'00'00,
47 };
48 constexpr uint32_t DUMP_OFFSET_8 = 8;
49
50 const std::map<OHOS::MediaAVCodec::CodecServer::CodecStatus, std::string> CODEC_STATE_MAP = {
51 {OHOS::MediaAVCodec::CodecServer::UNINITIALIZED, "uninitialized"},
52 {OHOS::MediaAVCodec::CodecServer::INITIALIZED, "initialized"},
53 {OHOS::MediaAVCodec::CodecServer::CONFIGURED, "configured"},
54 {OHOS::MediaAVCodec::CodecServer::RUNNING, "running"},
55 {OHOS::MediaAVCodec::CodecServer::FLUSHED, "flushed"},
56 {OHOS::MediaAVCodec::CodecServer::END_OF_STREAM, "end of stream"},
57 {OHOS::MediaAVCodec::CodecServer::ERROR, "error"},
58 };
59
60 const std::vector<std::pair<std::string_view, const std::string>> VIDEO_DUMP_TABLE = {
61 {OHOS::MediaAVCodec::MediaDescriptionKey::MD_KEY_CODEC_NAME, "Codec_Name"},
62 {OHOS::MediaAVCodec::MediaDescriptionKey::MD_KEY_WIDTH, "Width"},
63 {OHOS::MediaAVCodec::MediaDescriptionKey::MD_KEY_HEIGHT, "Height"},
64 {OHOS::MediaAVCodec::MediaDescriptionKey::MD_KEY_FRAME_RATE, "Frame_Rate"},
65 {OHOS::MediaAVCodec::MediaDescriptionKey::MD_KEY_BITRATE, "Bit_Rate"},
66 {OHOS::MediaAVCodec::MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, "Pixel_Format"},
67 {OHOS::MediaAVCodec::MediaDescriptionKey::MD_KEY_SCALE_TYPE, "Scale_Type"},
68 {OHOS::MediaAVCodec::MediaDescriptionKey::MD_KEY_ROTATION_ANGLE, "Rotation_Angle"},
69 {OHOS::MediaAVCodec::MediaDescriptionKey::MD_KEY_MAX_INPUT_SIZE, "Max_Input_Size"},
70 {OHOS::MediaAVCodec::MediaDescriptionKey::MD_KEY_MAX_INPUT_BUFFER_COUNT, "Max_Input_Buffer_Count"},
71 {OHOS::MediaAVCodec::MediaDescriptionKey::MD_KEY_MAX_OUTPUT_BUFFER_COUNT, "Max_Output_Buffer_Count"},
72 };
73
74 const std::map<int32_t, const std::string> PIXEL_FORMAT_STRING_MAP = {
75 {static_cast<int32_t>(OHOS::MediaAVCodec::VideoPixelFormat::YUV420P), "YUV420P"},
76 {static_cast<int32_t>(OHOS::MediaAVCodec::VideoPixelFormat::YUVI420), "YUVI420"},
77 {static_cast<int32_t>(OHOS::MediaAVCodec::VideoPixelFormat::NV12), "NV12"},
78 {static_cast<int32_t>(OHOS::MediaAVCodec::VideoPixelFormat::NV21), "NV21"},
79 {static_cast<int32_t>(OHOS::MediaAVCodec::VideoPixelFormat::SURFACE_FORMAT), "SURFACE_FORMAT"},
80 {static_cast<int32_t>(OHOS::MediaAVCodec::VideoPixelFormat::RGBA), "RGBA"},
81 {static_cast<int32_t>(OHOS::MediaAVCodec::VideoPixelFormat::UNKNOWN), "UNKNOWN_FORMAT"},
82 };
83
84 const std::map<int32_t, const std::string> SCALE_TYPE_STRING_MAP = {
85 {OHOS::ScalingMode::SCALING_MODE_FREEZE, "Freeze"},
86 {OHOS::ScalingMode::SCALING_MODE_SCALE_TO_WINDOW, "Scale_to_window"},
87 {OHOS::ScalingMode::SCALING_MODE_SCALE_CROP, "Scale_crop"},
88 {OHOS::ScalingMode::SCALING_MODE_NO_SCALE_CROP, "No_scale_crop"},
89 };
90
GetAudioCodecName(const OHOS::MediaAVCodec::AVCodecType type,std::string & name)91 int32_t GetAudioCodecName(const OHOS::MediaAVCodec::AVCodecType type, std::string &name)
92 {
93 using namespace OHOS::MediaAVCodec;
94 if (name.compare(AVCodecCodecName::AUDIO_DECODER_API9_AAC_NAME) == 0) {
95 name = AVCodecCodecName::AUDIO_DECODER_AAC_NAME;
96 } else if (name.compare(AVCodecCodecName::AUDIO_ENCODER_API9_AAC_NAME) == 0) {
97 name = AVCodecCodecName::AUDIO_ENCODER_AAC_NAME;
98 }
99 if (name.find("Audio") != name.npos) {
100 if ((name.find("Decoder") != name.npos && type != AVCODEC_TYPE_AUDIO_DECODER) ||
101 (name.find("Encoder") != name.npos && type != AVCODEC_TYPE_AUDIO_ENCODER)) {
102 AVCODEC_LOGE("AudioCodec name:%{public}s invalid", name.c_str());
103 return AVCS_ERR_INVALID_OPERATION;
104 }
105 }
106 return AVCS_ERR_OK;
107 }
108
109 struct PostProcessingCallbackUserData {
110 std::shared_ptr<OHOS::MediaAVCodec::CodecServer> codecServer;
111 };
112
PostProcessingCallbackOnError(int32_t errorCode,void * userData)113 void PostProcessingCallbackOnError(int32_t errorCode, void* userData)
114 {
115 CHECK_AND_RETURN_LOG(userData != nullptr, "Post processing callback's userData is nullptr");
116 auto callbackUserData = static_cast<PostProcessingCallbackUserData*>(userData);
117 auto codecServer = callbackUserData->codecServer;
118 CHECK_AND_RETURN_LOG(codecServer != nullptr, "Codec server dose not exit");
119 codecServer->PostProcessingOnError(errorCode);
120 }
121
PostProcessingCallbackOnOutputBufferAvailable(uint32_t index,int32_t flag,void * userData)122 void PostProcessingCallbackOnOutputBufferAvailable(uint32_t index, int32_t flag, void* userData)
123 {
124 CHECK_AND_RETURN_LOG(userData != nullptr, "Post processing callback's userData is nullptr");
125 auto callbackUserData = static_cast<PostProcessingCallbackUserData*>(userData);
126 auto codecServer = callbackUserData->codecServer;
127 CHECK_AND_RETURN_LOG(codecServer != nullptr, "Codec server dose not exit");
128 codecServer->PostProcessingOnOutputBufferAvailable(index, flag);
129 }
130
PostProcessingCallbackOnOutputFormatChanged(const OHOS::Media::Format & format,void * userData)131 void PostProcessingCallbackOnOutputFormatChanged(const OHOS::Media::Format& format, void* userData)
132 {
133 CHECK_AND_RETURN_LOG(userData != nullptr, "Post processing callback's userData is nullptr");
134 auto callbackUserData = static_cast<PostProcessingCallbackUserData*>(userData);
135 auto codecServer = callbackUserData->codecServer;
136 CHECK_AND_RETURN_LOG(codecServer != nullptr, "Codec server dose not exit");
137 codecServer->PostProcessingOnOutputFormatChanged(format);
138 }
139 } // namespace
140
141 namespace OHOS {
142 namespace MediaAVCodec {
143 using namespace Media;
Create()144 std::shared_ptr<ICodecService> CodecServer::Create()
145 {
146 std::shared_ptr<CodecServer> server = std::make_shared<CodecServer>();
147
148 int32_t ret = server->InitServer();
149 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, nullptr, "Server init failed, ret: %{public}d!", ret);
150 return server;
151 }
152
CodecServer()153 CodecServer::CodecServer()
154 {
155 AVCODEC_LOGD("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
156 }
157
~CodecServer()158 CodecServer::~CodecServer()
159 {
160 std::unique_ptr<std::thread> thread = std::make_unique<std::thread>(&CodecServer::ExitProcessor, this);
161 CHECK_AND_RETURN_LOG(thread != nullptr, "0x%{public}06" PRIXPTR " create exit thread failed", FAKE_POINTER(this));
162 if (thread->joinable()) {
163 thread->join();
164 }
165 (void)mallopt(M_FLUSH_THREAD_CACHE, 0);
166
167 AVCODEC_LOGD("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
168 }
169
ExitProcessor()170 void CodecServer::ExitProcessor()
171 {
172 codecBase_ = nullptr;
173 }
174
InitServer()175 int32_t CodecServer::InitServer()
176 {
177 return AVCS_ERR_OK;
178 }
179
Init(AVCodecType type,bool isMimeType,const std::string & name,Meta & callerInfo,API_VERSION apiVersion)180 int32_t CodecServer::Init(AVCodecType type, bool isMimeType, const std::string &name,
181 Meta &callerInfo, API_VERSION apiVersion)
182 {
183 std::lock_guard<std::shared_mutex> lock(mutex_);
184 (void)mallopt(M_SET_THREAD_CACHE, M_THREAD_CACHE_DISABLE);
185 (void)mallopt(M_DELAYED_FREE, M_DELAYED_FREE_DISABLE);
186 codecType_ = type;
187 codecName_ = name;
188 int32_t ret = isMimeType ? InitByMime(callerInfo, apiVersion) : InitByName(callerInfo, apiVersion);
189 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret,
190 "Init failed. isMimeType:(%{public}d), name:(%{public}s), error:(%{public}d)", isMimeType,
191 name.c_str(), ret);
192 SetCallerInfo(callerInfo);
193
194 std::shared_ptr<AVCodecCallback> callback = std::make_shared<CodecBaseCallback>(shared_from_this());
195 ret = codecBase_->SetCallback(callback);
196 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "SetCallback failed.");
197
198 std::shared_ptr<MediaCodecCallback> videoCallback = std::make_shared<VCodecBaseCallback>(shared_from_this());
199 ret = codecBase_->SetCallback(videoCallback);
200 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "SetCallback failed.");
201
202 StatusChanged(INITIALIZED);
203 return AVCS_ERR_OK;
204 }
205
InitByName(Meta & callerInfo,API_VERSION apiVersion)206 int32_t CodecServer::InitByName(Meta &callerInfo, API_VERSION apiVersion)
207 {
208 int32_t ret = GetAudioCodecName(codecType_, codecName_);
209 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "CodecName get failed.");
210
211 codecBase_ = CodecFactory::Instance().CreateCodecByName(codecName_, apiVersion);
212 CHECK_AND_RETURN_RET_LOG(codecBase_ != nullptr, AVCS_ERR_NO_MEMORY, "CodecBase is nullptr.");
213 return codecBase_->Init(callerInfo);
214 }
215
InitByMime(Meta & callerInfo,API_VERSION apiVersion)216 int32_t CodecServer::InitByMime(Meta &callerInfo, API_VERSION apiVersion)
217 {
218 int32_t ret = AVCS_ERR_NO_MEMORY;
219 bool isEncoder = (codecType_ == AVCODEC_TYPE_VIDEO_ENCODER) || (codecType_ == AVCODEC_TYPE_AUDIO_ENCODER);
220 std::vector<std::string> nameArray = CodecFactory::Instance().GetCodecNameArrayByMime(codecName_, isEncoder);
221 std::vector<std::string>::iterator iter;
222 for (iter = nameArray.begin(); iter != nameArray.end(); ++iter) {
223 ret = AVCS_ERR_NO_MEMORY;
224 codecBase_ = CodecFactory::Instance().CreateCodecByName(*iter, apiVersion);
225 CHECK_AND_CONTINUE_LOG(codecBase_ != nullptr, "Skip creation failure. name:(%{public}s)", iter->c_str());
226 ret = codecBase_->Init(callerInfo);
227 CHECK_AND_CONTINUE_LOG(ret == AVCS_ERR_OK, "Skip initialization failure. name:(%{public}s)", iter->c_str());
228 codecName_ = *iter;
229 break;
230 }
231 CHECK_AND_RETURN_RET_LOG(codecBase_ != nullptr, AVCS_ERR_NO_MEMORY, "CodecBase is nullptr.");
232 return iter == nameArray.end() ? ret : AVCS_ERR_OK;
233 }
234
Configure(const Format & format)235 int32_t CodecServer::Configure(const Format &format)
236 {
237 std::lock_guard<std::shared_mutex> lock(mutex_);
238 CHECK_AND_RETURN_RET_LOG(status_ == INITIALIZED, AVCS_ERR_INVALID_STATE, "In invalid state, %{public}s",
239 GetStatusDescription(status_).data());
240 CHECK_AND_RETURN_RET_LOG(codecBase_ != nullptr, AVCS_ERR_NO_MEMORY, "Codecbase is nullptr");
241 Format config = format;
242
243 int32_t isSetParameterCb = 0;
244 format.GetIntValue(Tag::VIDEO_ENCODER_ENABLE_SURFACE_INPUT_CALLBACK, isSetParameterCb);
245 isSetParameterCb_ = isSetParameterCb != 0;
246
247 int32_t paramCheckRet = AVCS_ERR_OK;
248 if (codecType_ == AVCODEC_TYPE_VIDEO_ENCODER || codecType_ == AVCODEC_TYPE_VIDEO_DECODER) {
249 auto scenario = CodecParamChecker::CheckCodecScenario(config, codecType_, codecName_);
250 CHECK_AND_RETURN_RET_LOG(scenario != std::nullopt, AVCS_ERR_INVALID_VAL, "Failed to get codec scenario");
251 scenario_ = scenario.value();
252 paramCheckRet = CodecParamChecker::CheckConfigureValid(config, codecName_, scenario_);
253 CHECK_AND_RETURN_RET_LOG(paramCheckRet == AVCS_ERR_OK || paramCheckRet == AVCS_ERR_CODEC_PARAM_INCORRECT,
254 paramCheckRet, "Params in format is not valid.");
255 CodecScenarioInit(config);
256 }
257
258 int32_t ret = codecBase_->Configure(config);
259 if (ret != AVCS_ERR_OK) {
260 StatusChanged(ERROR);
261 return ret;
262 }
263 ret = CreatePostProcessing(config);
264 if (ret != AVCS_ERR_OK) {
265 StatusChanged(ERROR);
266 return ret;
267 }
268 StatusChanged(CONFIGURED);
269 return paramCheckRet;
270 }
271
SetCustomBuffer(std::shared_ptr<AVBuffer> buffer)272 int32_t CodecServer::SetCustomBuffer(std::shared_ptr<AVBuffer> buffer)
273 {
274 std::lock_guard<std::shared_mutex> lock(mutex_);
275 CHECK_AND_RETURN_RET_LOG(status_ == CONFIGURED, AVCS_ERR_INVALID_STATE, "In invalid state, %{public}s",
276 GetStatusDescription(status_).data());
277 CHECK_AND_RETURN_RET_LOG(codecBase_ != nullptr, AVCS_ERR_NO_MEMORY, "Codecbase is nullptr");
278 return codecBase_->SetCustomBuffer(buffer);
279 }
280
CodecScenarioInit(Format & config)281 int32_t CodecServer::CodecScenarioInit(Format &config)
282 {
283 switch (scenario_) {
284 case CodecScenario::CODEC_SCENARIO_ENC_TEMPORAL_SCALABILITY:
285 temporalScalability_ = std::make_shared<TemporalScalability>(codecName_);
286 temporalScalability_->ValidateTemporalGopParam(config);
287 if (!temporalScalability_->svcLTR_) {
288 temporalScalability_ = nullptr;
289 }
290 break;
291 default:
292 break;
293 }
294
295 return AVCS_ERR_OK;
296 }
297
StartInputParamTask()298 void CodecServer::StartInputParamTask()
299 {
300 inputParamTask_ = std::make_shared<TaskThread>("InputParamTask");
301 inputParamTask_->RegisterHandler([this] {
302 uint32_t index = temporalScalability_->GetFirstBufferIndex();
303 AVCodecBufferInfo info;
304 AVCodecBufferFlag flag = AVCODEC_BUFFER_FLAG_NONE;
305 CHECK_AND_RETURN_LOG(QueueInputBuffer(index, info, flag) == AVCS_ERR_OK, "QueueInputBuffer failed");
306 });
307 inputParamTask_->Start();
308 }
309
Start()310 int32_t CodecServer::Start()
311 {
312 SetFreeStatus(false);
313 std::lock_guard<std::shared_mutex> lock(mutex_);
314 CHECK_AND_RETURN_RET_LOG(status_ == FLUSHED || status_ == CONFIGURED, AVCS_ERR_INVALID_STATE,
315 "In invalid state, %{public}s", GetStatusDescription(status_).data());
316 CHECK_AND_RETURN_RET_LOG(codecBase_ != nullptr, AVCS_ERR_NO_MEMORY, "Codecbase is nullptr");
317 if (temporalScalability_ != nullptr && isCreateSurface_ && !isSetParameterCb_) {
318 StartInputParamTask();
319 }
320 int32_t ret = StartPostProcessing();
321 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Start post processing failed");
322 ret = codecBase_->Start();
323 if (ret != AVCS_ERR_OK) {
324 (void)StopPostProcessing();
325 StatusChanged(ERROR);
326 } else {
327 StatusChanged(RUNNING);
328 isModeConfirmed_ = true;
329 CodecDfxInfo codecDfxInfo;
330 GetCodecDfxInfo(codecDfxInfo);
331 CodecStartEventWrite(codecDfxInfo);
332 }
333 return ret;
334 }
335
Stop()336 int32_t CodecServer::Stop()
337 {
338 SetFreeStatus(true);
339 std::lock_guard<std::shared_mutex> lock(mutex_);
340 CHECK_AND_RETURN_RET_LOG(status_ == RUNNING || status_ == END_OF_STREAM || status_ == FLUSHED,
341 AVCS_ERR_INVALID_STATE, "In invalid state, %{public}s",
342 GetStatusDescription(status_).data());
343 CHECK_AND_RETURN_RET_LOG(codecBase_ != nullptr, AVCS_ERR_NO_MEMORY, "Codecbase is nullptr");
344 int32_t retPostProcessing = StopPostProcessing();
345 int32_t retCodec = codecBase_->Stop();
346 CodecStopEventWrite(caller_.pid, caller_.uid, FAKE_POINTER(this));
347 if ((retPostProcessing + retCodec) != AVCS_ERR_OK) {
348 StatusChanged(ERROR);
349 return (retCodec == AVCS_ERR_OK) ? retPostProcessing : retCodec;
350 }
351 StatusChanged(CONFIGURED);
352 return AVCS_ERR_OK;
353 }
354
Flush()355 int32_t CodecServer::Flush()
356 {
357 SetFreeStatus(true);
358 std::lock_guard<std::shared_mutex> lock(mutex_);
359 CHECK_AND_RETURN_RET_LOG(status_ == RUNNING || status_ == END_OF_STREAM, AVCS_ERR_INVALID_STATE,
360 "In invalid state, %{public}s", GetStatusDescription(status_).data());
361 CHECK_AND_RETURN_RET_LOG(codecBase_ != nullptr, AVCS_ERR_NO_MEMORY, "Codecbase is nullptr");
362 int32_t retPostProcessing = FlushPostProcessing();
363 int32_t retCodec = codecBase_->Flush();
364 CodecStopEventWrite(caller_.pid, caller_.uid, FAKE_POINTER(this));
365 if (retPostProcessing + retCodec != AVCS_ERR_OK) {
366 StatusChanged(ERROR);
367 return (retPostProcessing != AVCS_ERR_OK) ? retPostProcessing : retCodec;
368 }
369 StatusChanged(FLUSHED);
370 return AVCS_ERR_OK;
371 }
372
NotifyEos()373 int32_t CodecServer::NotifyEos()
374 {
375 std::lock_guard<std::shared_mutex> lock(mutex_);
376 CHECK_AND_RETURN_RET_LOG(status_ == RUNNING, AVCS_ERR_INVALID_STATE, "In invalid state, %{public}s",
377 GetStatusDescription(status_).data());
378 CHECK_AND_RETURN_RET_LOG(codecBase_ != nullptr, AVCS_ERR_NO_MEMORY, "Codecbase is nullptr");
379 int32_t ret = codecBase_->NotifyEos();
380 if (ret == AVCS_ERR_OK) {
381 CodecStatus newStatus = END_OF_STREAM;
382 StatusChanged(newStatus);
383 CodecStopEventWrite(caller_.pid, caller_.uid, FAKE_POINTER(this));
384 }
385 return ret;
386 }
387
Reset()388 int32_t CodecServer::Reset()
389 {
390 SetFreeStatus(true);
391 std::lock_guard<std::shared_mutex> lock(mutex_);
392 CHECK_AND_RETURN_RET_LOG(codecBase_ != nullptr, AVCS_ERR_NO_MEMORY, "Codecbase is nullptr");
393 drmDecryptor_ = nullptr;
394 if (temporalScalability_ != nullptr) {
395 if (inputParamTask_ != nullptr) {
396 temporalScalability_->SetBlockQueueActive();
397 inputParamTask_->Stop();
398 inputParamTask_ = nullptr;
399 }
400 temporalScalability_ = nullptr;
401 }
402 int32_t ret = codecBase_->Reset();
403 CodecStatus newStatus = (ret == AVCS_ERR_OK ? INITIALIZED : ERROR);
404 StatusChanged(newStatus);
405 ret = ReleasePostProcessing();
406 if (ret != AVCS_ERR_OK) {
407 StatusChanged(ERROR);
408 }
409 CodecStopEventWrite(caller_.pid, caller_.uid, FAKE_POINTER(this));
410 lastErrMsg_.clear();
411 if (ret == AVCS_ERR_OK) {
412 isSurfaceMode_ = false;
413 isModeConfirmed_ = false;
414 }
415 return ret;
416 }
417
Release()418 int32_t CodecServer::Release()
419 {
420 SetFreeStatus(true);
421 std::lock_guard<std::shared_mutex> lock(mutex_);
422 CHECK_AND_RETURN_RET_LOG(codecBase_ != nullptr, AVCS_ERR_NO_MEMORY, "Codecbase is nullptr");
423 drmDecryptor_ = nullptr;
424 if (temporalScalability_ != nullptr) {
425 if (inputParamTask_ != nullptr) {
426 temporalScalability_->SetBlockQueueActive();
427 inputParamTask_->Stop();
428 inputParamTask_ = nullptr;
429 }
430 temporalScalability_ = nullptr;
431 }
432 int32_t ret = codecBase_->Release();
433 CodecStopEventWrite(caller_.pid, caller_.uid, FAKE_POINTER(this));
434 std::unique_ptr<std::thread> thread = std::make_unique<std::thread>(&CodecServer::ExitProcessor, this);
435 if (thread && thread->joinable()) {
436 thread->join();
437 }
438 (void)ReleasePostProcessing();
439 if (ret == AVCS_ERR_OK) {
440 isSurfaceMode_ = false;
441 isModeConfirmed_ = false;
442 }
443 return ret;
444 }
445
CreateInputSurface()446 sptr<Surface> CodecServer::CreateInputSurface()
447 {
448 std::lock_guard<std::shared_mutex> lock(mutex_);
449 CHECK_AND_RETURN_RET_LOG(status_ == CONFIGURED, nullptr, "In invalid state, %{public}s",
450 GetStatusDescription(status_).data());
451 CHECK_AND_RETURN_RET_LOG(codecBase_ != nullptr, nullptr, "Codecbase is nullptr");
452 sptr<Surface> surface = codecBase_->CreateInputSurface();
453 if (surface != nullptr) {
454 isSurfaceMode_ = true;
455 isCreateSurface_ = true;
456 }
457 return surface;
458 }
459
SetInputSurface(sptr<Surface> surface)460 int32_t CodecServer::SetInputSurface(sptr<Surface> surface)
461 {
462 std::lock_guard<std::shared_mutex> lock(mutex_);
463 CHECK_AND_RETURN_RET_LOG(status_ == CONFIGURED, AVCS_ERR_INVALID_STATE, "In invalid state, %{public}s",
464 GetStatusDescription(status_).data());
465 CHECK_AND_RETURN_RET_LOG(codecBase_ != nullptr, AVCS_ERR_NO_MEMORY, "Codecbase is nullptr");
466 if (surface != nullptr) {
467 isSurfaceMode_ = true;
468 }
469 return codecBase_->SetInputSurface(surface);
470 }
471
SetOutputSurface(sptr<Surface> surface)472 int32_t CodecServer::SetOutputSurface(sptr<Surface> surface)
473 {
474 std::lock_guard<std::shared_mutex> lock(mutex_);
475 bool isBufferMode = isModeConfirmed_ && !isSurfaceMode_;
476 CHECK_AND_RETURN_RET_LOG(!isBufferMode, AVCS_ERR_INVALID_OPERATION, "In buffer mode.");
477
478 bool isValidState = isModeConfirmed_ ? isSurfaceMode_ && (status_ == CONFIGURED || status_ == RUNNING ||
479 status_ == FLUSHED || status_ == END_OF_STREAM)
480 : status_ == CONFIGURED;
481 CHECK_AND_RETURN_RET_LOG(isValidState, AVCS_ERR_INVALID_STATE, "In invalid state, %{public}s",
482 GetStatusDescription(status_).data());
483 CHECK_AND_RETURN_RET_LOG(codecBase_ != nullptr, AVCS_ERR_NO_MEMORY, "Codecbase is nullptr");
484 GSError gsRet = surface->SetSurfaceSourceType(OHSurfaceSource::OH_SURFACE_SOURCE_VIDEO);
485 EXPECT_AND_LOGW(gsRet != GSERROR_OK, "Set surface source type failed, %{public}s", GSErrorStr(gsRet).c_str());
486 int32_t ret = AVCS_ERR_OK;
487 if (postProcessing_) {
488 ret = SetOutputSurfaceForPostProcessing(surface);
489 } else {
490 ret = codecBase_->SetOutputSurface(surface);
491 }
492 isSurfaceMode_ = true;
493 #ifdef EMULATOR_ENABLED
494 Format config_emulator;
495 config_emulator.PutIntValue(Tag::VIDEO_PIXEL_FORMAT, static_cast<int32_t>(VideoPixelFormat::RGBA));
496 codecBase_->SetParameter(config_emulator);
497 #endif
498 return ret;
499 }
500
DrmVideoCencDecrypt(uint32_t index)501 int32_t CodecServer::DrmVideoCencDecrypt(uint32_t index)
502 {
503 int32_t ret = AVCS_ERR_OK;
504 if (drmDecryptor_ != nullptr) {
505 if (decryptVideoBufs_.find(index) != decryptVideoBufs_.end()) {
506 uint32_t dataSize = static_cast<uint32_t>(decryptVideoBufs_[index].inBuf->memory_->GetSize());
507 decryptVideoBufs_[index].outBuf->pts_ = decryptVideoBufs_[index].inBuf->pts_;
508 decryptVideoBufs_[index].outBuf->dts_ = decryptVideoBufs_[index].inBuf->dts_;
509 decryptVideoBufs_[index].outBuf->duration_ = decryptVideoBufs_[index].inBuf->duration_;
510 decryptVideoBufs_[index].outBuf->flag_ = decryptVideoBufs_[index].inBuf->flag_;
511 if (decryptVideoBufs_[index].inBuf->meta_ != nullptr) {
512 *(decryptVideoBufs_[index].outBuf->meta_) = *(decryptVideoBufs_[index].inBuf->meta_);
513 }
514 if (dataSize == 0) {
515 decryptVideoBufs_[index].outBuf->memory_->SetSize(dataSize);
516 return ret;
517 }
518 drmDecryptor_->SetCodecName(codecName_);
519 ret = drmDecryptor_->DrmVideoCencDecrypt(decryptVideoBufs_[index].inBuf,
520 decryptVideoBufs_[index].outBuf, dataSize);
521 decryptVideoBufs_[index].outBuf->memory_->SetSize(dataSize);
522 }
523 }
524 return ret;
525 }
526
QueueInputBuffer(uint32_t index,AVCodecBufferInfo info,AVCodecBufferFlag flag)527 int32_t CodecServer::QueueInputBuffer(uint32_t index, AVCodecBufferInfo info, AVCodecBufferFlag flag)
528 {
529 std::shared_lock<std::shared_mutex> freeLock(freeMutex_);
530 if (isFree_) {
531 AVCODEC_LOGE("In invalid state, free out");
532 return AVCS_ERR_INVALID_STATE;
533 }
534
535 int32_t ret = AVCS_ERR_OK;
536 if (flag & AVCODEC_BUFFER_FLAG_EOS) {
537 std::lock_guard<std::shared_mutex> lock(mutex_);
538 ret = QueueInputBufferIn(index, info, flag);
539 if (ret == AVCS_ERR_OK) {
540 CodecStatus newStatus = END_OF_STREAM;
541 StatusChanged(newStatus);
542 }
543 } else {
544 std::shared_lock<std::shared_mutex> lock(mutex_);
545 ret = QueueInputBufferIn(index, info, flag);
546 }
547 return ret;
548 }
549
QueueInputBufferIn(uint32_t index,AVCodecBufferInfo info,AVCodecBufferFlag flag)550 int32_t CodecServer::QueueInputBufferIn(uint32_t index, AVCodecBufferInfo info, AVCodecBufferFlag flag)
551 {
552 int32_t ret = AVCS_ERR_OK;
553 CHECK_AND_RETURN_RET_LOG(
554 status_ == RUNNING || ((isSetParameterCb_ || inputParamTask_ != nullptr) && status_ == END_OF_STREAM),
555 AVCS_ERR_INVALID_STATE, "In invalid state, %{public}s", GetStatusDescription(status_).data());
556 CHECK_AND_RETURN_RET_LOG(codecBase_ != nullptr, AVCS_ERR_NO_MEMORY, "Codecbase is nullptr");
557 if (temporalScalability_ != nullptr) {
558 temporalScalability_->ConfigureLTR(index);
559 }
560 if (videoCb_ != nullptr) {
561 ret = DrmVideoCencDecrypt(index);
562 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, AVCS_ERR_DECRYPT_FAILED, "CodecServer decrypt failed");
563 ret = codecBase_->QueueInputBuffer(index);
564 }
565 if (codecCb_ != nullptr) {
566 ret = codecBase_->QueueInputBuffer(index, info, flag);
567 }
568 return ret;
569 }
570
QueueInputBuffer(uint32_t index)571 int32_t CodecServer::QueueInputBuffer(uint32_t index)
572 {
573 (void)index;
574 return AVCS_ERR_UNSUPPORT;
575 }
576
QueueInputParameter(uint32_t index)577 int32_t CodecServer::QueueInputParameter(uint32_t index)
578 {
579 (void)index;
580 return AVCS_ERR_UNSUPPORT;
581 }
582
GetOutputFormat(Format & format)583 int32_t CodecServer::GetOutputFormat(Format &format)
584 {
585 std::lock_guard<std::shared_mutex> lock(mutex_);
586 CHECK_AND_RETURN_RET_LOG(status_ != UNINITIALIZED, AVCS_ERR_INVALID_STATE, "In invalid state, %{public}s",
587 GetStatusDescription(status_).data());
588 CHECK_AND_RETURN_RET_LOG(codecBase_ != nullptr, AVCS_ERR_NO_MEMORY, "Codecbase is nullptr");
589 if (postProcessing_) {
590 int32_t ret = codecBase_->GetOutputFormat(format);
591 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "GetOutputFormat failed");
592 return GetPostProcessingOutputFormat(format);
593 } else {
594 return codecBase_->GetOutputFormat(format);
595 }
596 }
597
CheckDrmSvpConsistency(const sptr<DrmStandard::IMediaKeySessionService> & keySession,bool svpFlag)598 int32_t CodecServer::CheckDrmSvpConsistency(const sptr<DrmStandard::IMediaKeySessionService> &keySession,
599 bool svpFlag)
600 {
601 AVCODEC_LOGI("CheckDrmSvpConsistency");
602 CHECK_AND_RETURN_RET_LOG(keySession != nullptr, AVCS_ERR_INVALID_VAL, "keySession is nullptr");
603 std::string tmpName = codecName_;
604 transform(tmpName.begin(), tmpName.end(), tmpName.begin(), ::tolower);
605
606 // check codec name when secure video path is false
607 if (svpFlag == false) {
608 if (tmpName.find(".secure") != std::string::npos) {
609 AVCODEC_LOGE("CheckDrmSvpConsistency failed, svpFlag is false but the decoder is secure!");
610 return AVCS_ERR_INVALID_VAL;
611 }
612 return AVCS_ERR_OK;
613 }
614
615 // check codec name when secure video path is true
616 if (tmpName.find(".secure") == std::string::npos) {
617 AVCODEC_LOGE("CheckDrmSvpConsistency failed, svpFlag is true but the decoder is not secure!");
618 return AVCS_ERR_INVALID_VAL;
619 }
620
621 // check session level when secure video path is true
622 #ifdef SUPPORT_DRM
623 DrmStandard::IMediaKeySessionService::ContentProtectionLevel sessionLevel;
624 int ret = keySession->GetContentProtectionLevel(&sessionLevel);
625 CHECK_AND_RETURN_RET_LOG(ret == 0, AVCS_ERR_INVALID_VAL, "GetContentProtectionLevel failed");
626 if (sessionLevel <
627 DrmStandard::IMediaKeySessionService::ContentProtectionLevel::CONTENT_PROTECTION_LEVEL_HW_CRYPTO) {
628 AVCODEC_LOGE("CheckDrmSvpConsistency failed, key session's content protection level is too low!");
629 return AVCS_ERR_INVALID_VAL;
630 }
631 #endif
632
633 return AVCS_ERR_OK;
634 }
635
636 #ifdef SUPPORT_DRM
SetDecryptConfig(const sptr<DrmStandard::IMediaKeySessionService> & keySession,const bool svpFlag)637 int32_t CodecServer::SetDecryptConfig(const sptr<DrmStandard::IMediaKeySessionService> &keySession, const bool svpFlag)
638 {
639 std::lock_guard<std::shared_mutex> lock(mutex_);
640 AVCODEC_LOGI("CodecServer::SetDecryptConfig");
641 CHECK_AND_RETURN_RET_LOG(codecBase_ != nullptr, AVCS_ERR_NO_MEMORY, "Codecbase is nullptr");
642
643 int32_t ret = CheckDrmSvpConsistency(keySession, svpFlag);
644 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, AVCS_ERR_INVALID_VAL, "check svp failed");
645
646 if (drmDecryptor_ == nullptr) {
647 drmDecryptor_ = std::make_shared<CodecDrmDecrypt>();
648 }
649 CHECK_AND_RETURN_RET_LOG(drmDecryptor_ != nullptr, AVCS_ERR_NO_MEMORY, "drmDecryptor is nullptr");
650 drmDecryptor_->SetDecryptionConfig(keySession, svpFlag);
651 return AVCS_ERR_OK;
652 }
653 #endif
654
ReleaseOutputBuffer(uint32_t index,bool render)655 int32_t CodecServer::ReleaseOutputBuffer(uint32_t index, bool render)
656 {
657 std::shared_lock<std::shared_mutex> freeLock(freeMutex_);
658 if (isFree_) {
659 AVCODEC_LOGE("In invalid state, free out");
660 return AVCS_ERR_INVALID_STATE;
661 }
662 std::shared_lock<std::shared_mutex> lock(mutex_);
663 CHECK_AND_RETURN_RET_LOG(status_ == RUNNING || status_ == END_OF_STREAM, AVCS_ERR_INVALID_STATE,
664 "In invalid state, %{public}s", GetStatusDescription(status_).data());
665
666 if (postProcessing_) {
667 return ReleaseOutputBufferOfPostProcessing(index, render);
668 } else {
669 return ReleaseOutputBufferOfCodec(index, render);
670 }
671 }
672
ReleaseOutputBufferOfCodec(uint32_t index,bool render)673 int32_t CodecServer::ReleaseOutputBufferOfCodec(uint32_t index, bool render)
674 {
675 CHECK_AND_RETURN_RET_LOG(codecBase_ != nullptr, AVCS_ERR_NO_MEMORY, "Codecbase is nullptr");
676 int32_t ret;
677 if (render) {
678 ret = codecBase_->RenderOutputBuffer(index);
679 } else {
680 ret = codecBase_->ReleaseOutputBuffer(index);
681 }
682 return ret;
683 }
684
RenderOutputBufferAtTime(uint32_t index,int64_t renderTimestampNs)685 int32_t CodecServer::RenderOutputBufferAtTime(uint32_t index, int64_t renderTimestampNs)
686 {
687 (void)renderTimestampNs;
688 std::shared_lock<std::shared_mutex> freeLock(freeMutex_);
689 if (isFree_) {
690 AVCODEC_LOGE("In invalid state, free out");
691 return AVCS_ERR_INVALID_STATE;
692 }
693 std::shared_lock<std::shared_mutex> lock(mutex_);
694 CHECK_AND_RETURN_RET_LOG(status_ == RUNNING || status_ == END_OF_STREAM, AVCS_ERR_INVALID_STATE,
695 "In invalid state, %{public}s", GetStatusDescription(status_).data());
696 CHECK_AND_RETURN_RET_LOG(codecBase_ != nullptr, AVCS_ERR_NO_MEMORY, "Codecbase is nullptr");
697 if (postProcessing_) {
698 return postProcessing_->ReleaseOutputBuffer(index, true);
699 } else {
700 return codecBase_->RenderOutputBuffer(index);
701 }
702 }
703
SetParameter(const Format & format)704 int32_t CodecServer::SetParameter(const Format &format)
705 {
706 std::lock_guard<std::shared_mutex> lock(mutex_);
707 CHECK_AND_RETURN_RET_LOG(status_ != INITIALIZED && status_ != CONFIGURED, AVCS_ERR_INVALID_STATE,
708 "In invalid state, %{public}s", GetStatusDescription(status_).data());
709 CHECK_AND_RETURN_RET_LOG(codecBase_ != nullptr, AVCS_ERR_NO_MEMORY, "Codecbase is nullptr");
710
711 if (codecType_ == AVCODEC_TYPE_VIDEO_ENCODER || codecType_ == AVCODEC_TYPE_VIDEO_DECODER) {
712 Format oldFormat;
713 int32_t ret = codecBase_->GetOutputFormat(oldFormat);
714 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, AVCS_ERR_INVALID_OPERATION, "Failed to get codec format");
715 ret = CodecParamChecker::CheckParameterValid(format, oldFormat, codecName_, scenario_);
716 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Params in format is not valid.");
717 }
718
719 return codecBase_->SetParameter(format);
720 }
721
SetCallback(const std::shared_ptr<AVCodecCallback> & callback)722 int32_t CodecServer::SetCallback(const std::shared_ptr<AVCodecCallback> &callback)
723 {
724 std::lock_guard<std::shared_mutex> cbLock(cbMutex_);
725 codecCb_ = callback;
726 return AVCS_ERR_OK;
727 }
728
SetCallback(const std::shared_ptr<MediaCodecCallback> & callback)729 int32_t CodecServer::SetCallback(const std::shared_ptr<MediaCodecCallback> &callback)
730 {
731 std::lock_guard<std::shared_mutex> cbLock(cbMutex_);
732 videoCb_ = callback;
733 return AVCS_ERR_OK;
734 }
735
SetCallback(const std::shared_ptr<MediaCodecParameterCallback> & callback)736 int32_t CodecServer::SetCallback(const std::shared_ptr<MediaCodecParameterCallback> &callback)
737 {
738 (void)callback;
739 return AVCS_ERR_UNSUPPORT;
740 }
741
SetCallback(const std::shared_ptr<MediaCodecParameterWithAttrCallback> & callback)742 int32_t CodecServer::SetCallback(const std::shared_ptr<MediaCodecParameterWithAttrCallback> &callback)
743 {
744 (void)callback;
745 return AVCS_ERR_UNSUPPORT;
746 }
747
GetInputFormat(Format & format)748 int32_t CodecServer::GetInputFormat(Format &format)
749 {
750 std::lock_guard<std::shared_mutex> lock(mutex_);
751 CHECK_AND_RETURN_RET_LOG(
752 status_ == CONFIGURED || status_ == RUNNING || status_ == FLUSHED || status_ == END_OF_STREAM,
753 AVCS_ERR_INVALID_STATE, "In invalid state, %{public}s", GetStatusDescription(status_).data());
754 CHECK_AND_RETURN_RET_LOG(codecBase_ != nullptr, AVCS_ERR_NO_MEMORY, "Codecbase is nullptr");
755 return codecBase_->GetInputFormat(format);
756 }
757
DumpInfo(int32_t fd)758 int32_t CodecServer::DumpInfo(int32_t fd)
759 {
760 CHECK_AND_RETURN_RET_LOG(fd >= 0, AVCS_ERR_OK, "Get a invalid fd");
761 CHECK_AND_RETURN_RET_LOG(codecBase_ != nullptr, AVCS_ERR_NO_MEMORY, "Codecbase is nullptr");
762 Format codecFormat;
763 int32_t ret = codecBase_->GetOutputFormat(codecFormat);
764 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Get codec format failed.");
765
766 AVCodecDumpControler dumpControler;
767 auto statusIt = CODEC_STATE_MAP.find(status_);
768 if (forwardCaller_.pid != -1 || !forwardCaller_.processName.empty()) {
769 dumpControler.AddInfo(DUMP_INDEX_FORWARD_CALLER_PID, "Forward_Caller_Pid", std::to_string(forwardCaller_.pid));
770 dumpControler.AddInfo(DUMP_INDEX_FORWARD_CALLER_UID, "Forward_Caller_Uid", std::to_string(forwardCaller_.uid));
771 dumpControler.AddInfo(DUMP_INDEX_FORWARD_CALLER_PROCESS_NAME,
772 "Forward_Caller_Process_Name", forwardCaller_.processName);
773 }
774 dumpControler.AddInfo(DUMP_INDEX_CALLER_PID, "Caller_Pid", std::to_string(caller_.pid));
775 dumpControler.AddInfo(DUMP_INDEX_CALLER_UID, "Caller_Uid", std::to_string(caller_.uid));
776 dumpControler.AddInfo(DUMP_INDEX_CALLER_PROCESS_NAME, "Caller_Process_Name", caller_.processName);
777 dumpControler.AddInfo(DUMP_INDEX_STATUS, "Status", statusIt != CODEC_STATE_MAP.end() ? statusIt->second : "");
778 dumpControler.AddInfo(DUMP_INDEX_LAST_ERROR, "Last_Error", lastErrMsg_.size() ? lastErrMsg_ : "Null");
779
780 uint32_t infoIndex = 1;
781 for (auto iter : VIDEO_DUMP_TABLE) {
782 uint32_t dumpIndex = DUMP_INDEX_CODEC_INFO_START + (infoIndex++ << DUMP_OFFSET_8);
783 if (iter.first == MediaDescriptionKey::MD_KEY_PIXEL_FORMAT) {
784 dumpControler.AddInfoFromFormatWithMapping(dumpIndex, codecFormat,
785 iter.first, iter.second, PIXEL_FORMAT_STRING_MAP);
786 } else if (iter.first == MediaDescriptionKey::MD_KEY_SCALE_TYPE) {
787 dumpControler.AddInfoFromFormatWithMapping(dumpIndex, codecFormat,
788 iter.first, iter.second, SCALE_TYPE_STRING_MAP);
789 } else {
790 dumpControler.AddInfoFromFormat(dumpIndex, codecFormat, iter.first, iter.second);
791 }
792 }
793 std::string dumpString;
794 dumpControler.GetDumpString(dumpString);
795 dumpString += codecBase_->GetHidumperInfo();
796 dumpString += "\n";
797 write(fd, dumpString.c_str(), dumpString.size());
798 return AVCS_ERR_OK;
799 }
800
SetCallerInfo(const Meta & callerInfo)801 void CodecServer::SetCallerInfo(const Meta &callerInfo)
802 {
803 (void)callerInfo.GetData(Tag::AV_CODEC_CALLER_PID, caller_.pid);
804 (void)callerInfo.GetData(Tag::AV_CODEC_CALLER_UID, caller_.uid);
805 (void)callerInfo.GetData(Tag::AV_CODEC_CALLER_PROCESS_NAME, caller_.processName);
806 (void)callerInfo.GetData(Tag::AV_CODEC_FORWARD_CALLER_PID, forwardCaller_.pid);
807 (void)callerInfo.GetData(Tag::AV_CODEC_FORWARD_CALLER_UID, forwardCaller_.uid);
808 (void)callerInfo.GetData(Tag::AV_CODEC_FORWARD_CALLER_PROCESS_NAME, forwardCaller_.processName);
809
810 if (caller_.pid == -1) {
811 caller_.pid = getprocpid();
812 caller_.uid = getuid();
813 }
814
815 EXPECT_AND_LOGI((forwardCaller_.pid >= 0) || (!forwardCaller_.processName.empty()),
816 "Forward caller pid: %{public}d, process name: %{public}s",
817 forwardCaller_.pid, forwardCaller_.processName.c_str());
818 AVCODEC_LOGI("Caller pid: %{public}d, process name: %{public}s", caller_.pid, caller_.processName.c_str());
819 }
820
GetStatusDescription(CodecStatus status)821 inline const std::string &CodecServer::GetStatusDescription(CodecStatus status)
822 {
823 if (status < UNINITIALIZED || status >= ERROR) {
824 return CODEC_STATE_MAP.at(ERROR);
825 }
826 return CODEC_STATE_MAP.at(status);
827 }
828
StatusChanged(CodecStatus newStatus)829 inline void CodecServer::StatusChanged(CodecStatus newStatus)
830 {
831 if (status_ == newStatus) {
832 return;
833 }
834 AVCODEC_LOGI("Status %{public}s -> %{public}s",
835 GetStatusDescription(status_).data(), GetStatusDescription(newStatus).data());
836 status_ = newStatus;
837 }
838
OnError(int32_t errorType,int32_t errorCode)839 void CodecServer::OnError(int32_t errorType, int32_t errorCode)
840 {
841 std::lock_guard<std::shared_mutex> lock(cbMutex_);
842 lastErrMsg_ = AVCSErrorToString(static_cast<AVCodecServiceErrCode>(errorCode));
843 FaultEventWrite(FaultType::FAULT_TYPE_INNER_ERROR, lastErrMsg_, "Codec");
844 if (videoCb_ != nullptr) {
845 videoCb_->OnError(static_cast<AVCodecErrorType>(errorType), errorCode);
846 }
847 if (codecCb_ != nullptr) {
848 codecCb_->OnError(static_cast<AVCodecErrorType>(errorType), errorCode);
849 }
850 }
851
OnOutputFormatChanged(const Format & format)852 void CodecServer::OnOutputFormatChanged(const Format &format)
853 {
854 std::lock_guard<std::shared_mutex> lock(cbMutex_);
855 if (postProcessing_) {
856 outputFormatChanged_ = format;
857 return;
858 }
859 if (videoCb_ != nullptr) {
860 videoCb_->OnOutputFormatChanged(format);
861 }
862 if (codecCb_ != nullptr) {
863 codecCb_->OnOutputFormatChanged(format);
864 }
865 }
866
OnInputBufferAvailable(uint32_t index,std::shared_ptr<AVSharedMemory> buffer)867 void CodecServer::OnInputBufferAvailable(uint32_t index, std::shared_ptr<AVSharedMemory> buffer)
868 {
869 std::shared_lock<std::shared_mutex> lock(cbMutex_);
870 if (codecCb_ == nullptr || (isCreateSurface_ && !isSetParameterCb_)) {
871 return;
872 }
873 codecCb_->OnInputBufferAvailable(index, buffer);
874 }
875
OnOutputBufferAvailable(uint32_t index,AVCodecBufferInfo info,AVCodecBufferFlag flag,std::shared_ptr<AVSharedMemory> buffer)876 void CodecServer::OnOutputBufferAvailable(uint32_t index, AVCodecBufferInfo info, AVCodecBufferFlag flag,
877 std::shared_ptr<AVSharedMemory> buffer)
878 {
879 std::shared_lock<std::shared_mutex> lock(cbMutex_);
880 if (codecCb_ == nullptr) {
881 return;
882 }
883 codecCb_->OnOutputBufferAvailable(index, info, flag, buffer);
884 }
885
OnInputBufferAvailable(uint32_t index,std::shared_ptr<AVBuffer> buffer)886 void CodecServer::OnInputBufferAvailable(uint32_t index, std::shared_ptr<AVBuffer> buffer)
887 {
888 std::shared_lock<std::shared_mutex> lock(cbMutex_);
889 if (temporalScalability_ != nullptr) {
890 temporalScalability_->StoreAVBuffer(index, buffer);
891 }
892 if (videoCb_ == nullptr || (isCreateSurface_ && !isSetParameterCb_)) {
893 return;
894 }
895 if (drmDecryptor_ != nullptr) {
896 if (decryptVideoBufs_.find(index) != decryptVideoBufs_.end()) {
897 videoCb_->OnInputBufferAvailable(index, decryptVideoBufs_[index].inBuf);
898 return;
899 }
900 DrmDecryptVideoBuf decryptVideoBuf;
901 MemoryFlag memFlag = MEMORY_READ_WRITE;
902 std::shared_ptr<AVAllocator> avAllocator = AVAllocatorFactory::CreateSharedAllocator(memFlag);
903 if (avAllocator == nullptr) {
904 AVCODEC_LOGE("CreateSharedAllocator failed");
905 return;
906 }
907 decryptVideoBuf.inBuf = AVBuffer::CreateAVBuffer(avAllocator,
908 static_cast<int32_t>(buffer->memory_->GetCapacity()));
909 if (decryptVideoBuf.inBuf == nullptr || decryptVideoBuf.inBuf->memory_ == nullptr ||
910 decryptVideoBuf.inBuf->memory_->GetCapacity() != static_cast<int32_t>(buffer->memory_->GetCapacity())) {
911 AVCODEC_LOGE("CreateAVBuffer failed");
912 return;
913 }
914 decryptVideoBuf.outBuf = buffer;
915 decryptVideoBufs_.insert({index, decryptVideoBuf});
916 videoCb_->OnInputBufferAvailable(index, decryptVideoBuf.inBuf);
917 } else {
918 videoCb_->OnInputBufferAvailable(index, buffer);
919 }
920 }
921
OnOutputBufferAvailable(uint32_t index,std::shared_ptr<AVBuffer> buffer)922 void CodecServer::OnOutputBufferAvailable(uint32_t index, std::shared_ptr<AVBuffer> buffer)
923 {
924 CHECK_AND_RETURN_LOG(buffer != nullptr, "buffer is nullptr!");
925
926 if (temporalScalability_ != nullptr && !(buffer->flag_ == AVCODEC_BUFFER_FLAG_CODEC_DATA)) {
927 temporalScalability_->SetDisposableFlag(buffer);
928 }
929
930 std::shared_lock<std::shared_mutex> lock(cbMutex_);
931 CHECK_AND_RETURN_LOG(videoCb_ != nullptr, "videoCb_ is nullptr!");
932 if (postProcessing_) {
933 /*
934 If post processing is configured, this callback flow is intercepted here. Just push the decoded buffer info
935 {index, buffer} into the decodedBufferInfoQueue_ which is monitored by another task thread. Once the queue
936 has data, the thread will pop the data from the queue and calls "CodecServer::ReleaseOutputBuffer" to flush
937 it into video processing engine. The video processing engine will automatically processing the frame
938 according to the index. The callback ipc proxy's function "videoCb_->OnOutputBufferAvailable" is called
939 later in "PostProcessingOnOutputBufferAvailable" by video processing engine when the frame is processed
940 to notify application that the frame is ready. At last, application calls
941 "OH_VideoDecoder_RenderOutputBuffer" or "OH_VideoDecoder_FreeOutputBuffer" to flush the frame.
942 */
943 (void)PushDecodedBufferInfo(index, buffer);
944 } else {
945 videoCb_->OnOutputBufferAvailable(index, buffer);
946 }
947 }
948
CodecBaseCallback(const std::shared_ptr<CodecServer> & codec)949 CodecBaseCallback::CodecBaseCallback(const std::shared_ptr<CodecServer> &codec) : codec_(codec)
950 {
951 AVCODEC_LOGD("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
952 }
953
~CodecBaseCallback()954 CodecBaseCallback::~CodecBaseCallback()
955 {
956 AVCODEC_LOGD("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
957 }
958
OnError(AVCodecErrorType errorType,int32_t errorCode)959 void CodecBaseCallback::OnError(AVCodecErrorType errorType, int32_t errorCode)
960 {
961 if (codec_ != nullptr) {
962 codec_->OnError(errorType, errorCode);
963 }
964 }
965
OnOutputFormatChanged(const Format & format)966 void CodecBaseCallback::OnOutputFormatChanged(const Format &format)
967 {
968 if (codec_ != nullptr) {
969 codec_->OnOutputFormatChanged(format);
970 }
971 }
972
OnInputBufferAvailable(uint32_t index,std::shared_ptr<AVSharedMemory> buffer)973 void CodecBaseCallback::OnInputBufferAvailable(uint32_t index, std::shared_ptr<AVSharedMemory> buffer)
974 {
975 if (codec_ != nullptr) {
976 codec_->OnInputBufferAvailable(index, buffer);
977 }
978 }
979
OnOutputBufferAvailable(uint32_t index,AVCodecBufferInfo info,AVCodecBufferFlag flag,std::shared_ptr<AVSharedMemory> buffer)980 void CodecBaseCallback::OnOutputBufferAvailable(uint32_t index, AVCodecBufferInfo info, AVCodecBufferFlag flag,
981 std::shared_ptr<AVSharedMemory> buffer)
982 {
983 if (codec_ != nullptr) {
984 codec_->OnOutputBufferAvailable(index, info, flag, buffer);
985 }
986 }
987
VCodecBaseCallback(const std::shared_ptr<CodecServer> & codec)988 VCodecBaseCallback::VCodecBaseCallback(const std::shared_ptr<CodecServer> &codec) : codec_(codec)
989 {
990 AVCODEC_LOGD("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
991 }
992
~VCodecBaseCallback()993 VCodecBaseCallback::~VCodecBaseCallback()
994 {
995 AVCODEC_LOGD("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
996 }
997
OnError(AVCodecErrorType errorType,int32_t errorCode)998 void VCodecBaseCallback::OnError(AVCodecErrorType errorType, int32_t errorCode)
999 {
1000 if (codec_ != nullptr) {
1001 codec_->OnError(errorType, errorCode);
1002 }
1003 }
1004
OnOutputFormatChanged(const Format & format)1005 void VCodecBaseCallback::OnOutputFormatChanged(const Format &format)
1006 {
1007 if (codec_ != nullptr) {
1008 codec_->OnOutputFormatChanged(format);
1009 }
1010 }
1011
OnInputBufferAvailable(uint32_t index,std::shared_ptr<AVBuffer> buffer)1012 void VCodecBaseCallback::OnInputBufferAvailable(uint32_t index, std::shared_ptr<AVBuffer> buffer)
1013 {
1014 if (codec_ != nullptr) {
1015 codec_->OnInputBufferAvailable(index, buffer);
1016 }
1017 }
1018
OnOutputBufferAvailable(uint32_t index,std::shared_ptr<AVBuffer> buffer)1019 void VCodecBaseCallback::OnOutputBufferAvailable(uint32_t index, std::shared_ptr<AVBuffer> buffer)
1020 {
1021 if (codec_ != nullptr) {
1022 codec_->OnOutputBufferAvailable(index, buffer);
1023 }
1024 }
1025
GetCodecDfxInfo(CodecDfxInfo & codecDfxInfo)1026 int32_t CodecServer::GetCodecDfxInfo(CodecDfxInfo &codecDfxInfo)
1027 {
1028 Format format;
1029 codecBase_->GetOutputFormat(format);
1030 int32_t videoPixelFormat = static_cast<int32_t>(VideoPixelFormat::UNKNOWN);
1031 format.GetIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, videoPixelFormat);
1032 videoPixelFormat = PIXEL_FORMAT_STRING_MAP.find(videoPixelFormat) != PIXEL_FORMAT_STRING_MAP.end()
1033 ? videoPixelFormat
1034 : static_cast<int32_t>(VideoPixelFormat::UNKNOWN);
1035 int32_t codecIsVendor = 0;
1036 format.GetIntValue("IS_VENDOR", codecIsVendor);
1037
1038 codecDfxInfo.clientPid = caller_.pid;
1039 codecDfxInfo.clientUid = caller_.uid;
1040 codecDfxInfo.codecInstanceId = FAKE_POINTER(this);
1041 format.GetStringValue(MediaDescriptionKey::MD_KEY_CODEC_NAME, codecDfxInfo.codecName);
1042 codecDfxInfo.codecIsVendor = codecIsVendor == 1 ? "True" : "False";
1043 codecDfxInfo.codecMode = isSurfaceMode_ ? "Surface mode" : "Buffer Mode";
1044 format.GetLongValue(MediaDescriptionKey::MD_KEY_BITRATE, codecDfxInfo.encoderBitRate);
1045 format.GetIntValue(MediaDescriptionKey::MD_KEY_WIDTH, codecDfxInfo.videoWidth);
1046 format.GetIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, codecDfxInfo.videoHeight);
1047 format.GetDoubleValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, codecDfxInfo.videoFrameRate);
1048 format.GetIntValue(MediaDescriptionKey::MD_KEY_CHANNEL_COUNT, codecDfxInfo.audioChannelCount);
1049 codecDfxInfo.videoPixelFormat =
1050 codecDfxInfo.audioChannelCount == 0 ? PIXEL_FORMAT_STRING_MAP.at(videoPixelFormat) : "";
1051 format.GetIntValue(MediaDescriptionKey::MD_KEY_SAMPLE_RATE, codecDfxInfo.audioSampleRate);
1052 return 0;
1053 }
1054
Configure(const std::shared_ptr<Media::Meta> & meta)1055 int32_t CodecServer::Configure(const std::shared_ptr<Media::Meta> &meta)
1056 {
1057 std::lock_guard<std::shared_mutex> lock(mutex_);
1058 CHECK_AND_RETURN_RET_LOG(meta != nullptr, AVCS_ERR_NO_MEMORY, "Codecbase is nullptr");
1059
1060 CHECK_AND_RETURN_RET_LOG(status_ == INITIALIZED, AVCS_ERR_INVALID_STATE, "In invalid state, %{public}s",
1061 GetStatusDescription(status_).data());
1062 CHECK_AND_RETURN_RET_LOG(codecBase_ != nullptr, AVCS_ERR_NO_MEMORY, "Codecbase is nullptr");
1063
1064 int32_t ret = codecBase_->Configure(meta);
1065
1066 CodecStatus newStatus = (ret == AVCS_ERR_OK ? CONFIGURED : ERROR);
1067 StatusChanged(newStatus);
1068 return ret;
1069 }
SetParameter(const std::shared_ptr<Media::Meta> & parameter)1070 int32_t CodecServer::SetParameter(const std::shared_ptr<Media::Meta> ¶meter)
1071 {
1072 std::lock_guard<std::shared_mutex> lock(mutex_);
1073 CHECK_AND_RETURN_RET_LOG(parameter != nullptr, AVCS_ERR_NO_MEMORY, "Codecbase is nullptr");
1074 CHECK_AND_RETURN_RET_LOG(status_ != INITIALIZED && status_ != CONFIGURED, AVCS_ERR_INVALID_STATE,
1075 "In invalid state, %{public}s", GetStatusDescription(status_).data());
1076 return codecBase_->SetParameter(parameter);
1077 }
GetOutputFormat(std::shared_ptr<Media::Meta> & parameter)1078 int32_t CodecServer::GetOutputFormat(std::shared_ptr<Media::Meta> ¶meter)
1079 {
1080 std::lock_guard<std::shared_mutex> lock(mutex_);
1081 CHECK_AND_RETURN_RET_LOG(status_ != UNINITIALIZED, AVCS_ERR_INVALID_STATE, "In invalid state, %{public}s",
1082 GetStatusDescription(status_).data());
1083 CHECK_AND_RETURN_RET_LOG(codecBase_ != nullptr, AVCS_ERR_NO_MEMORY, "codecBase is nullptr");
1084 return codecBase_->GetOutputFormat(parameter);
1085 }
1086
SetOutputBufferQueue(const sptr<Media::AVBufferQueueProducer> & bufferQueueProducer)1087 int32_t CodecServer::SetOutputBufferQueue(const sptr<Media::AVBufferQueueProducer> &bufferQueueProducer)
1088 {
1089 std::lock_guard<std::shared_mutex> lock(mutex_);
1090 CHECK_AND_RETURN_RET_LOG(bufferQueueProducer != nullptr, AVCS_ERR_NO_MEMORY, "Codecbase is nullptr");
1091 return codecBase_->SetOutputBufferQueue(bufferQueueProducer);
1092 }
Prepare()1093 int32_t CodecServer::Prepare()
1094 {
1095 std::lock_guard<std::shared_mutex> lock(mutex_);
1096 switch (codecType_) {
1097 case AVCODEC_TYPE_VIDEO_DECODER:
1098 // Post processing is only available for video decoder.
1099 return PreparePostProcessing();
1100 case AVCODEC_TYPE_VIDEO_ENCODER:
1101 return AVCS_ERR_OK;
1102 default:
1103 // Audio's interface "Prepare"
1104 return codecBase_->Prepare();
1105 }
1106 }
GetInputBufferQueue()1107 sptr<Media::AVBufferQueueProducer> CodecServer::GetInputBufferQueue()
1108 {
1109 std::lock_guard<std::shared_mutex> lock(mutex_);
1110 return codecBase_->GetInputBufferQueue();
1111 }
ProcessInputBuffer()1112 void CodecServer::ProcessInputBuffer()
1113 {
1114 std::lock_guard<std::shared_mutex> lock(mutex_);
1115 return codecBase_->ProcessInputBuffer();
1116 }
1117
1118 #ifdef SUPPORT_DRM
SetAudioDecryptionConfig(const sptr<DrmStandard::IMediaKeySessionService> & keySession,const bool svpFlag)1119 int32_t CodecServer::SetAudioDecryptionConfig(const sptr<DrmStandard::IMediaKeySessionService> &keySession,
1120 const bool svpFlag)
1121 {
1122 std::lock_guard<std::shared_mutex> lock(mutex_);
1123 AVCODEC_LOGI("CodecServer::SetAudioDecryptionConfig");
1124 CHECK_AND_RETURN_RET_LOG(codecBase_ != nullptr, AVCS_ERR_NO_MEMORY, "codecBase is nullptr");
1125 return codecBase_->SetAudioDecryptionConfig(keySession, svpFlag);
1126 }
1127 #endif
1128
CheckRunning()1129 bool CodecServer::CheckRunning()
1130 {
1131 if (status_ == CodecServer::RUNNING) {
1132 return true;
1133 }
1134 return false;
1135 }
1136
SetFreeStatus(bool isFree)1137 void CodecServer::SetFreeStatus(bool isFree)
1138 {
1139 std::lock_guard<std::shared_mutex> lock(freeMutex_);
1140 isFree_ = isFree;
1141 }
1142
CreatePostProcessing(const Format & format)1143 int32_t CodecServer::CreatePostProcessing(const Format& format)
1144 {
1145 if (codecType_ != AVCODEC_TYPE_VIDEO_DECODER) {
1146 return AVCS_ERR_OK;
1147 }
1148 int32_t colorSpaceType;
1149 if (!format.GetIntValue(MediaDescriptionKey::MD_KEY_VIDEO_DECODER_OUTPUT_COLOR_SPACE, colorSpaceType)) {
1150 return AVCS_ERR_OK;
1151 }
1152 auto capData = CodecAbilitySingleton::GetInstance().GetCapabilityByName(codecName_);
1153 CHECK_AND_RETURN_RET_LOG(capData != std::nullopt && capData->isVendor, AVCS_ERR_UNKNOWN,
1154 "Get codec capability from codec list failed");
1155 CHECK_AND_RETURN_RET_LOG(codecBase_, AVCS_ERR_UNKNOWN, "Decoder is not found");
1156 int32_t ret;
1157 postProcessing_ = PostProcessingType::Create(codecBase_, format, ret);
1158 if (postProcessing_) {
1159 AVCODEC_LOGI("Post processing is configured");
1160 }
1161 return ret;
1162 }
1163
SetCallbackForPostProcessing()1164 int32_t CodecServer::SetCallbackForPostProcessing()
1165 {
1166 using namespace std::placeholders;
1167 postProcessingCallback_.onError = std::bind(PostProcessingCallbackOnError, _1, _2);
1168 postProcessingCallback_.onOutputBufferAvailable =
1169 std::bind(PostProcessingCallbackOnOutputBufferAvailable, _1, _2, _3);
1170 postProcessingCallback_.onOutputFormatChanged = std::bind(PostProcessingCallbackOnOutputFormatChanged, _1, _2);
1171 auto userData = new PostProcessingCallbackUserData;
1172 CHECK_AND_RETURN_RET_LOG(userData != nullptr, AVCS_ERR_NO_MEMORY,
1173 "Failed to create post processing callback userdata");
1174 userData->codecServer = shared_from_this();
1175 postProcessingUserData_ = static_cast<void*>(userData);
1176 return postProcessing_->SetCallback(postProcessingCallback_, postProcessingUserData_);
1177 }
1178
ClearCallbackForPostProcessing()1179 void CodecServer::ClearCallbackForPostProcessing()
1180 {
1181 std::shared_lock<std::shared_mutex> lock(cbMutex_);
1182 postProcessingCallback_.onError = nullptr;
1183 postProcessingCallback_.onOutputBufferAvailable = nullptr;
1184 }
1185
SetOutputSurfaceForPostProcessing(sptr<Surface> surface)1186 int32_t CodecServer::SetOutputSurfaceForPostProcessing(sptr<Surface> surface)
1187 {
1188 int32_t ret = postProcessing_->SetOutputSurface(surface);
1189 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Set output surface failed");
1190 return ret;
1191 }
1192
PreparePostProcessing()1193 int32_t CodecServer::PreparePostProcessing()
1194 {
1195 if (!postProcessing_) {
1196 return AVCS_ERR_OK;
1197 }
1198
1199 int32_t ret{AVCS_ERR_OK};
1200 if (postProcessingUserData_ == nullptr) {
1201 ret = SetCallbackForPostProcessing();
1202 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Set callback for post post processing failed");
1203 }
1204
1205 if (decodedBufferInfoQueue_ == nullptr) {
1206 decodedBufferInfoQueue_ = DecodedBufferInfoQueue::Create("DecodedBufferInfoQueue");
1207 CHECK_AND_RETURN_RET_LOG(decodedBufferInfoQueue_, AVCS_ERR_NO_MEMORY,
1208 "Create decoded buffer info queue failed");
1209 }
1210
1211 if (postProcessingInputBufferInfoQueue_ == nullptr) {
1212 postProcessingInputBufferInfoQueue_ = DecodedBufferInfoQueue::Create("PostProcessingInputBufferInfoQueue");
1213 CHECK_AND_RETURN_RET_LOG(postProcessingInputBufferInfoQueue_, AVCS_ERR_NO_MEMORY,
1214 "Create post processing input buffer info queue failed");
1215 }
1216
1217 if (postProcessingOutputBufferInfoQueue_ == nullptr) {
1218 postProcessingOutputBufferInfoQueue_ = DecodedBufferInfoQueue::Create("PostProcessingOutputBufferInfoQueue");
1219 CHECK_AND_RETURN_RET_LOG(postProcessingOutputBufferInfoQueue_, AVCS_ERR_NO_MEMORY,
1220 "Create post processing output buffer info queue failed");
1221 }
1222
1223 ret = postProcessing_->Prepare();
1224 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Prepare post processing failed");
1225
1226 AVCODEC_LOGI("Post processing is prepared");
1227 return AVCS_ERR_OK;
1228 }
1229
StartPostProcessing()1230 int32_t CodecServer::StartPostProcessing()
1231 {
1232 if (!postProcessing_) {
1233 return AVCS_ERR_OK;
1234 }
1235 int32_t ret = postProcessing_->Start();
1236 if (ret != AVCS_ERR_OK) {
1237 StatusChanged(ERROR);
1238 return ret;
1239 }
1240 ret = StartPostProcessingTask();
1241 if (ret != AVCS_ERR_OK) {
1242 StatusChanged(ERROR);
1243 return ret;
1244 }
1245 AVCODEC_LOGI("Post processing is started");
1246 return ret;
1247 }
1248
StopPostProcessing()1249 int32_t CodecServer::StopPostProcessing()
1250 {
1251 DeactivatePostProcessingQueue();
1252 if (postProcessingTask_) {
1253 postProcessingTask_->Stop();
1254 }
1255 AVCODEC_LOGD("Post processing task stopped");
1256 if (postProcessing_) {
1257 int32_t ret = postProcessing_->Stop();
1258 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Stop post processing failed");
1259 }
1260 if (decodedBufferInfoQueue_) {
1261 decodedBufferInfoQueue_->Clear();
1262 }
1263 if (postProcessingInputBufferInfoQueue_) {
1264 postProcessingInputBufferInfoQueue_->Clear();
1265 }
1266 if (postProcessingOutputBufferInfoQueue_) {
1267 postProcessingOutputBufferInfoQueue_->Clear();
1268 }
1269
1270 AVCODEC_LOGD("reset frame count");
1271 decodedFrameCount_.store(0);
1272 processedFrameCount_.store(0);
1273 decoderIsEOS_.store(false);
1274
1275 AVCODEC_LOGI("Post processing is stopped");
1276 return AVCS_ERR_OK;
1277 }
1278
FlushPostProcessing()1279 int32_t CodecServer::FlushPostProcessing()
1280 {
1281 if (!postProcessing_) {
1282 return AVCS_ERR_OK;
1283 }
1284 DeactivatePostProcessingQueue();
1285 if (postProcessingTask_) {
1286 postProcessingTask_->Pause();
1287 }
1288 auto ret = postProcessing_->Flush();
1289 if (decodedBufferInfoQueue_) {
1290 decodedBufferInfoQueue_->Clear();
1291 }
1292 if (postProcessingInputBufferInfoQueue_) {
1293 postProcessingInputBufferInfoQueue_->Clear();
1294 }
1295 if (postProcessingOutputBufferInfoQueue_) {
1296 postProcessingOutputBufferInfoQueue_->Clear();
1297 }
1298
1299 AVCODEC_LOGD("reset frame count");
1300 decodedFrameCount_.store(0);
1301 processedFrameCount_.store(0);
1302 decoderIsEOS_.store(false);
1303
1304 CHECK_AND_RETURN_RET_LOG(ret == AVCS_ERR_OK, ret, "Flush post processing failed");
1305 AVCODEC_LOGI("Post processing is flushed");
1306 return AVCS_ERR_OK;
1307 }
1308
ResetPostProcessing()1309 int32_t CodecServer::ResetPostProcessing()
1310 {
1311 if (postProcessing_) {
1312 DeactivatePostProcessingQueue();
1313 if (postProcessingTask_) {
1314 postProcessingTask_->Stop();
1315 }
1316 postProcessing_->Reset();
1317 CleanPostProcessingResource();
1318 postProcessing_.reset();
1319 }
1320 AVCODEC_LOGI("Post processing is reset");
1321 return AVCS_ERR_OK;
1322 }
1323
ReleasePostProcessing()1324 int32_t CodecServer::ReleasePostProcessing()
1325 {
1326 if (postProcessing_) {
1327 DeactivatePostProcessingQueue();
1328 if (postProcessingTask_) {
1329 postProcessingTask_->Stop();
1330 }
1331 postProcessing_->Release();
1332 CleanPostProcessingResource();
1333 postProcessing_.reset();
1334 AVCODEC_LOGI("Post processing is released");
1335 }
1336
1337 if (postProcessingUserData_ != nullptr) {
1338 auto p = static_cast<PostProcessingCallbackUserData*>(postProcessingUserData_);
1339 p->codecServer.reset();
1340 delete p;
1341 postProcessingUserData_ = nullptr;
1342 }
1343
1344 return AVCS_ERR_OK;
1345 }
1346
ReleaseOutputBufferOfPostProcessing(uint32_t index,bool render)1347 int32_t CodecServer::ReleaseOutputBufferOfPostProcessing(uint32_t index, bool render)
1348 {
1349 CHECK_AND_RETURN_RET_LOG(postProcessing_, AVCS_ERR_UNKNOWN, "Post processing is null");
1350 if (index == std::numeric_limits<uint32_t>::max()) {
1351 AVCODEC_LOGD("EOS is got");
1352 return AVCS_ERR_OK;
1353 }
1354 std::shared_ptr<DecodedBufferInfo> info{nullptr};
1355 CHECK_AND_RETURN_RET_LOG(postProcessingOutputBufferInfoQueue_, AVCS_ERR_UNKNOWN, "Queue is null");
1356 auto ret = postProcessingOutputBufferInfoQueue_->PopWait(info);
1357 CHECK_AND_RETURN_RET_LOG(ret == QueueResult::OK, AVCS_ERR_UNKNOWN,
1358 "Failed to get data, %{public}s", QUEUE_RESULT_DESCRIPTION[static_cast<int32_t>(ret)]);
1359 CHECK_AND_RETURN_RET_LOG(info && info->buffer, AVCS_ERR_UNKNOWN, "Data is null");
1360 return postProcessing_->ReleaseOutputBuffer(index, render);
1361 }
1362
GetPostProcessingOutputFormat(Format & format)1363 int32_t CodecServer::GetPostProcessingOutputFormat(Format& format)
1364 {
1365 postProcessing_->GetOutputFormat(format);
1366 return AVCS_ERR_OK;
1367 }
1368
PushDecodedBufferInfo(uint32_t index,std::shared_ptr<AVBuffer> buffer)1369 int32_t CodecServer::PushDecodedBufferInfo(uint32_t index, std::shared_ptr<AVBuffer> buffer)
1370 {
1371 auto info = std::make_shared<DecodedBufferInfo>();
1372 CHECK_AND_RETURN_RET_LOG(info, AVCS_ERR_NO_MEMORY, "Failed to allocate info");
1373 info->index = index;
1374 info->buffer = buffer;
1375 CHECK_AND_RETURN_RET_LOG(decodedBufferInfoQueue_, AVCS_ERR_UNKNOWN, "Queue is null");
1376 auto ret = decodedBufferInfoQueue_->PushWait(info);
1377 CHECK_AND_RETURN_RET_LOG(ret == QueueResult::OK, AVCS_ERR_UNKNOWN, "Push data failed, %{public}s",
1378 QUEUE_RESULT_DESCRIPTION[static_cast<int32_t>(ret)]);
1379 return AVCS_ERR_OK;
1380 }
1381
PostProcessingOnError(int32_t errorCode)1382 void CodecServer::PostProcessingOnError(int32_t errorCode)
1383 {
1384 std::lock_guard<std::shared_mutex> lock(cbMutex_);
1385 if (videoCb_ == nullptr) {
1386 AVCODEC_LOGD("Missing video callback");
1387 return;
1388 }
1389 int32_t ret = VPEErrorToAVCSError(errorCode);
1390 AVCODEC_LOGD("PostProcessingOnError, errorCodec:%{public}d -> %{public}d", errorCode, ret);
1391 videoCb_->OnError(AVCodecErrorType::AVCODEC_ERROR_INTERNAL, ret);
1392 }
1393
PostProcessingOnOutputBufferAvailable(uint32_t index,int32_t flag)1394 void CodecServer::PostProcessingOnOutputBufferAvailable(uint32_t index, [[maybe_unused]] int32_t flag)
1395 {
1396 std::lock_guard<std::shared_mutex> lock(cbMutex_);
1397 if (videoCb_ == nullptr) {
1398 AVCODEC_LOGD("Missing video callback");
1399 return;
1400 }
1401 CHECK_AND_RETURN_LOG(postProcessingInputBufferInfoQueue_ && postProcessingOutputBufferInfoQueue_, "Queue is null");
1402 std::shared_ptr<DecodedBufferInfo> info{nullptr};
1403 auto ret = postProcessingInputBufferInfoQueue_->PopWait(info);
1404 CHECK_AND_RETURN_LOG(ret == QueueResult::OK, "Get data failed, %{public}s",
1405 QUEUE_RESULT_DESCRIPTION[static_cast<int32_t>(ret)]);
1406 CHECK_AND_RETURN_LOG(info && info->buffer, "Invalid data");
1407 info->index = index;
1408 ret = postProcessingOutputBufferInfoQueue_->PushWait(info);
1409 CHECK_AND_RETURN_LOG(ret == QueueResult::OK, "Push data failed, %{public}s",
1410 QUEUE_RESULT_DESCRIPTION[static_cast<int32_t>(ret)]);
1411 videoCb_->OnOutputBufferAvailable(index, info->buffer);
1412 processedFrameCount_++;
1413 }
1414
PostProcessingOnOutputFormatChanged(const Format & format)1415 void CodecServer::PostProcessingOnOutputFormatChanged(const Format& format)
1416 {
1417 std::lock_guard<std::shared_mutex> lock(cbMutex_);
1418 if (videoCb_ == nullptr) {
1419 AVCODEC_LOGD("Missing video callback");
1420 return;
1421 }
1422 int32_t width = 0;
1423 if (format.GetIntValue(Media::Tag::VIDEO_WIDTH, width)) {
1424 outputFormatChanged_.PutIntValue(Media::Tag::VIDEO_WIDTH, width);
1425 outputFormatChanged_.PutIntValue(Media::Tag::VIDEO_PIC_WIDTH, width);
1426 }
1427 int32_t height = 0;
1428 if (format.GetIntValue(Media::Tag::VIDEO_HEIGHT, height)) {
1429 outputFormatChanged_.PutIntValue(Media::Tag::VIDEO_HEIGHT, height);
1430 outputFormatChanged_.PutIntValue(Media::Tag::VIDEO_PIC_HEIGHT, height);
1431 }
1432 int32_t stride = 0;
1433 if (format.GetIntValue(Media::Tag::VIDEO_STRIDE, stride)) {
1434 outputFormatChanged_.PutIntValue(Media::Tag::VIDEO_STRIDE, stride);
1435 }
1436 int32_t sliceHeight = 0;
1437 if (format.GetIntValue(Media::Tag::VIDEO_SLICE_HEIGHT, sliceHeight)) {
1438 outputFormatChanged_.PutIntValue(Media::Tag::VIDEO_SLICE_HEIGHT, sliceHeight);
1439 }
1440 int32_t outputColorSpace = 0;
1441 if (format.GetIntValue(Media::Tag::VIDEO_DECODER_OUTPUT_COLOR_SPACE, outputColorSpace)) {
1442 outputFormatChanged_.PutIntValue(Media::Tag::VIDEO_DECODER_OUTPUT_COLOR_SPACE, outputColorSpace);
1443 }
1444 videoCb_->OnOutputFormatChanged(outputFormatChanged_);
1445 }
1446
StartPostProcessingTask()1447 int32_t CodecServer::StartPostProcessingTask()
1448 {
1449 if (!postProcessingTask_) {
1450 postProcessingTask_ = std::make_unique<TaskThread>("PostProcessing");
1451 CHECK_AND_RETURN_RET_LOG(postProcessingTask_, AVCS_ERR_UNKNOWN, "Create task post processing failed");
1452 std::function<void()> task = std::bind(&CodecServer::PostProcessingTask, this);
1453 postProcessingTask_->RegisterHandler(task);
1454 }
1455 if (decodedBufferInfoQueue_) {
1456 decodedBufferInfoQueue_->Activate();
1457 }
1458 if (postProcessingInputBufferInfoQueue_) {
1459 postProcessingInputBufferInfoQueue_->Activate();
1460 }
1461 if (postProcessingOutputBufferInfoQueue_) {
1462 postProcessingOutputBufferInfoQueue_->Activate();
1463 }
1464 postProcessingTask_->Start();
1465
1466 return AVCS_ERR_OK;
1467 }
1468
PostProcessingTask()1469 void CodecServer::PostProcessingTask()
1470 {
1471 CHECK_AND_RETURN_LOG(decodedBufferInfoQueue_ && postProcessingInputBufferInfoQueue_, "Queue is null");
1472 if (decoderIsEOS_.load() == false) {
1473 std::shared_ptr<DecodedBufferInfo> info{nullptr};
1474 auto ret = decodedBufferInfoQueue_->PopWait(info);
1475 CHECK_AND_RETURN_LOG(ret == QueueResult::OK, "Get data failed, %{public}s",
1476 QUEUE_RESULT_DESCRIPTION[static_cast<int32_t>(ret)]);
1477 CHECK_AND_RETURN_LOG(info && info->buffer, "Invalid data");
1478 ret = postProcessingInputBufferInfoQueue_->PushWait(info);
1479 CHECK_AND_RETURN_LOG(ret == QueueResult::OK, "Push data failed, %{public}s",
1480 QUEUE_RESULT_DESCRIPTION[static_cast<int32_t>(ret)]);
1481 decodedFrameCount_++;
1482 AVCODEC_LOGD("Decoded frame count = %{public}" PRIu64, decodedFrameCount_.load());
1483 if (info->buffer->flag_ == AVCODEC_BUFFER_FLAG_EOS) {
1484 AVCODEC_LOGI("index = %{public}u, EOS flag", info->index);
1485 decoderIsEOS_.store(true);
1486 } else {
1487 (void)ReleaseOutputBufferOfCodec(info->index, true);
1488 return;
1489 }
1490 }
1491
1492 if (decodedFrameCount_.load() == processedFrameCount_.load() + 1) {
1493 std::shared_ptr<DecodedBufferInfo> eosInfo{nullptr};
1494 auto eosRet = postProcessingInputBufferInfoQueue_->PopWait(eosInfo);
1495 CHECK_AND_RETURN_LOG(eosRet == QueueResult::OK, "Get data failed, %{public}s",
1496 QUEUE_RESULT_DESCRIPTION[static_cast<int32_t>(eosRet)]);
1497 CHECK_AND_RETURN_LOG(eosInfo && eosInfo->buffer, "Invalid data");
1498 if (eosInfo->buffer->flag_ != AVCODEC_BUFFER_FLAG_EOS) {
1499 AVCODEC_LOGE("The cache info is not EOS frame");
1500 std::this_thread::sleep_for(std::chrono::seconds(1)); // 1: sleep for 1s
1501 return;
1502 }
1503 AVCODEC_LOGD("EOS flag got, frame count = %{public}" PRIu64, decodedFrameCount_.load());
1504 processedFrameCount_++;
1505 std::lock_guard<std::shared_mutex> lock(cbMutex_);
1506 if (videoCb_ == nullptr) {
1507 AVCODEC_LOGD("Missing video callback");
1508 } else {
1509 videoCb_->OnOutputBufferAvailable(std::numeric_limits<uint32_t>::max(), eosInfo->buffer);
1510 return;
1511 }
1512 } else {
1513 std::this_thread::sleep_for(std::chrono::milliseconds(20)); // 20: sleep for 20ms
1514 }
1515 }
1516
DeactivatePostProcessingQueue()1517 void CodecServer::DeactivatePostProcessingQueue()
1518 {
1519 if (decodedBufferInfoQueue_) {
1520 decodedBufferInfoQueue_->Deactivate();
1521 }
1522 if (postProcessingInputBufferInfoQueue_) {
1523 postProcessingInputBufferInfoQueue_->Deactivate();
1524 }
1525 if (postProcessingOutputBufferInfoQueue_) {
1526 postProcessingOutputBufferInfoQueue_->Deactivate();
1527 }
1528 }
1529
CleanPostProcessingResource()1530 void CodecServer::CleanPostProcessingResource()
1531 {
1532 ClearCallbackForPostProcessing();
1533 if (postProcessingTask_) {
1534 postProcessingTask_.reset();
1535 }
1536 if (decodedBufferInfoQueue_) {
1537 decodedBufferInfoQueue_.reset();
1538 }
1539 if (postProcessingInputBufferInfoQueue_) {
1540 postProcessingInputBufferInfoQueue_.reset();
1541 }
1542 if (postProcessingOutputBufferInfoQueue_) {
1543 postProcessingOutputBufferInfoQueue_.reset();
1544 }
1545
1546 decodedFrameCount_.store(0);
1547 processedFrameCount_.store(0);
1548 decoderIsEOS_.store(false);
1549 }
1550
1551 } // namespace MediaAVCodec
1552 } // namespace OHOS
1553