• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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> &parameter)
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> &parameter)
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