1 /*
2  * Copyright (C) 2024 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 #define HST_LOG_TAG "ReferenceParserManager"
17 
18 #include <unistd.h>
19 #include <dlfcn.h>
20 #include "common/log.h"
21 #include "reference_parser_manager.h"
22 
23 namespace {
24 const std::string REFERENCE_LIB_PATH = "libav_codec_reference_parser.z.so";
25 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_DEMUXER, "HiStreamer"};
26 }
27 
28 namespace OHOS {
29 namespace Media {
30 namespace Plugins {
31 void *ReferenceParserManager::handler_ = nullptr;
32 ReferenceParserManager::CreateFunc ReferenceParserManager::createFunc_ = nullptr;
33 ReferenceParserManager::DestroyFunc ReferenceParserManager::destroyFunc_ = nullptr;
34 std::mutex ReferenceParserManager::mtx_;
35 
~ReferenceParserManager()36 ReferenceParserManager::~ReferenceParserManager()
37 {
38     if (referenceParser_) {
39         destroyFunc_(referenceParser_);
40         referenceParser_ = nullptr;
41     }
42 }
43 
Init()44 bool ReferenceParserManager::Init()
45 {
46     std::lock_guard<std::mutex> lock(mtx_);
47     if (!handler_) {
48         if (!CheckSymbol(LoadPluginFile(REFERENCE_LIB_PATH))) {
49             MEDIA_LOG_E("Load reference parser failed");
50             return false;
51         }
52     }
53     return true;
54 }
55 
Create(CodecType codecType,std::vector<uint32_t> & IFramePos)56 std::shared_ptr<ReferenceParserManager> ReferenceParserManager::Create(CodecType codecType,
57                                                                        std::vector<uint32_t> &IFramePos)
58 {
59     std::shared_ptr<ReferenceParserManager> loader = std::make_shared<ReferenceParserManager>();
60     if (!loader->Init()) {
61         return nullptr;
62     }
63     loader->referenceParser_ = loader->createFunc_(codecType, IFramePos);
64     if (!loader->referenceParser_) {
65         MEDIA_LOG_E("CreateFunc_ fail");
66         return nullptr;
67     }
68     return loader;
69 }
70 
ParserNalUnits(uint8_t * nalData,int32_t nalDataSize,uint32_t frameId,int64_t dts)71 Status ReferenceParserManager::ParserNalUnits(uint8_t *nalData, int32_t nalDataSize, uint32_t frameId, int64_t dts)
72 {
73     FALSE_RETURN_V_MSG_E(referenceParser_ != nullptr, Status::ERROR_NULL_POINTER, "Reference parser is nullptr");
74     return referenceParser_->ParserNalUnits(nalData, nalDataSize, frameId, dts);
75 }
76 
ParserExtraData(uint8_t * extraData,int32_t extraDataSize)77 Status ReferenceParserManager::ParserExtraData(uint8_t *extraData, int32_t extraDataSize)
78 {
79     FALSE_RETURN_V_MSG_E(referenceParser_ != nullptr, Status::ERROR_NULL_POINTER, "Reference parser is nullptr");
80     return referenceParser_->ParserExtraData(extraData, extraDataSize);
81 }
82 
ParserSdtpData(uint8_t * sdtpData,int32_t sdtpDataSize)83 Status ReferenceParserManager::ParserSdtpData(uint8_t *sdtpData, int32_t sdtpDataSize)
84 {
85     FALSE_RETURN_V_MSG_E(referenceParser_ != nullptr, Status::ERROR_NULL_POINTER, "Reference parser is nullptr");
86     return referenceParser_->ParserSdtpData(sdtpData, sdtpDataSize);
87 }
88 
GetFrameLayerInfo(uint32_t frameId,FrameLayerInfo & frameLayerInfo)89 Status ReferenceParserManager::GetFrameLayerInfo(uint32_t frameId, FrameLayerInfo &frameLayerInfo)
90 {
91     FALSE_RETURN_V_MSG_E(referenceParser_ != nullptr, Status::ERROR_NULL_POINTER, "Reference parser is nullptr");
92     return referenceParser_->GetFrameLayerInfo(frameId, frameLayerInfo);
93 }
94 
GetFrameLayerInfo(int64_t dts,FrameLayerInfo & frameLayerInfo)95 Status ReferenceParserManager::GetFrameLayerInfo(int64_t dts, FrameLayerInfo &frameLayerInfo)
96 {
97     FALSE_RETURN_V_MSG_E(referenceParser_ != nullptr, Status::ERROR_NULL_POINTER, "Reference parser is nullptr");
98     return referenceParser_->GetFrameLayerInfo(dts, frameLayerInfo);
99 }
100 
GetGopLayerInfo(uint32_t gopId,GopLayerInfo & gopLayerInfo)101 Status ReferenceParserManager::GetGopLayerInfo(uint32_t gopId, GopLayerInfo &gopLayerInfo)
102 {
103     FALSE_RETURN_V_MSG_E(referenceParser_ != nullptr, Status::ERROR_NULL_POINTER, "Reference parser is nullptr");
104     return referenceParser_->GetGopLayerInfo(gopId, gopLayerInfo);
105 }
106 
LoadPluginFile(const std::string & path)107 void *ReferenceParserManager::LoadPluginFile(const std::string &path)
108 {
109     FALSE_RETURN_V_MSG_E(path.length() > 0, nullptr, "Path is invalid");
110     auto ptr = ::dlopen(path.c_str(), RTLD_NOW | RTLD_LOCAL);
111     if (ptr == nullptr) {
112         MEDIA_LOG_E("Dlopen failed due to %{public}s", ::dlerror());
113     }
114     handler_ = ptr;
115     return ptr;
116 }
117 
CheckSymbol(void * handler)118 bool ReferenceParserManager::CheckSymbol(void *handler)
119 {
120     if (handler) {
121         std::string createFuncName = "CreateRefParser";
122         std::string destroyFuncName = "DestroyRefParser";
123         CreateFunc createFunc = nullptr;
124         DestroyFunc destroyFunc = nullptr;
125         createFunc = (CreateFunc)(::dlsym(handler, createFuncName.c_str()));
126         destroyFunc = (DestroyFunc)(::dlsym(handler, destroyFuncName.c_str()));
127         if (createFunc && destroyFunc) {
128             MEDIA_LOG_D("CreateFuncName %{public}s", createFuncName.c_str());
129             MEDIA_LOG_D("DestroyFuncName %{public}s", destroyFuncName.c_str());
130             createFunc_ = createFunc;
131             destroyFunc_ = destroyFunc;
132             return true;
133         }
134     }
135     return false;
136 }
137 } // namespace Plugins
138 } // namespace Media
139 } // namespace OHOS