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 "DraggingPlayerAgent"
17 
18 #include <dlfcn.h>
19 
20 #include "common/log.h"
21 #include "dragging_player_agent.h"
22 #include "osal/task/pipeline_threadpool.h"
23 
24 namespace {
25 const std::string REFERENCE_LIB_PATH = std::string(DRAGGING_PLAYER_PATH);
26 const std::string FILESEPARATOR = "/";
27 const std::string REFERENCE_LIB_NAME = "libvideo_dragging_player.z.so";
28 const std::string REFENCE_LIB_ABSOLUTE_PATH = REFERENCE_LIB_PATH + FILESEPARATOR + REFERENCE_LIB_NAME;
29 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_PLAYER, "DraggingPlayerAgent"};
30 }
31 
32 namespace OHOS {
33 namespace Media {
34 
35 void *DraggingPlayerAgent::handler_ = nullptr;
36 DraggingPlayerAgent::CreateFunc DraggingPlayerAgent::createFunc_ = nullptr;
37 DraggingPlayerAgent::DestroyFunc DraggingPlayerAgent::destroyFunc_ = nullptr;
38 std::mutex DraggingPlayerAgent::mtx_;
39 
40 class VideoStreamReadyCallbackImpl : public VideoStreamReadyCallback {
41 public:
VideoStreamReadyCallbackImpl(const std::shared_ptr<DraggingPlayerAgent> draggingPlayerAgent)42     explicit VideoStreamReadyCallbackImpl(const std::shared_ptr<DraggingPlayerAgent> draggingPlayerAgent)
43         : draggingPlayerAgent_(draggingPlayerAgent) {}
44     bool IsVideoStreamDiscardable(const std::shared_ptr<AVBuffer> buffer) override
45     {
46         auto draggingPlayerAgent = draggingPlayerAgent_.lock();
47         if (draggingPlayerAgent != nullptr && buffer != nullptr) {
48             return draggingPlayerAgent->IsVideoStreamDiscardable(buffer);
49         }
50         return false;
51     }
52 private:
53     std::weak_ptr<DraggingPlayerAgent> draggingPlayerAgent_;
54 };
55 
56 class VideoFrameReadyCallbackImpl : public VideoFrameReadyCallback {
57 public:
VideoFrameReadyCallbackImpl(const std::shared_ptr<DraggingPlayerAgent> draggingPlayerAgent)58     explicit VideoFrameReadyCallbackImpl(const std::shared_ptr<DraggingPlayerAgent> draggingPlayerAgent)
59         : draggingPlayerAgent_(draggingPlayerAgent) {}
60     void ConsumeVideoFrame(const std::shared_ptr<AVBuffer> buffer, uint32_t bufferIndex) override
61     {
62         auto draggingPlayerAgent = draggingPlayerAgent_.lock();
63         if (draggingPlayerAgent != nullptr || buffer != nullptr) {
64             return draggingPlayerAgent->ConsumeVideoFrame(buffer, bufferIndex);
65         }
66     }
67 private:
68     std::weak_ptr<DraggingPlayerAgent> draggingPlayerAgent_;
69 };
70 
Create()71 shared_ptr<DraggingPlayerAgent> DraggingPlayerAgent::Create()
72 {
73     shared_ptr<DraggingPlayerAgent> agent = make_shared<DraggingPlayerAgent>();
74     if (!agent->LoadSymbol()) {
75         return nullptr;
76     }
77     agent->draggingPlayer_ = agent->createFunc_();
78     if (agent->draggingPlayer_ == nullptr) {
79         MEDIA_LOG_E("createFunc_ fail");
80         return nullptr;
81     }
82 
83     return agent;
84 }
85 
~DraggingPlayerAgent()86 DraggingPlayerAgent::~DraggingPlayerAgent()
87 {
88     if (!isReleased_) {
89         Release();
90     }
91     PipeLineThreadPool::GetInstance().DestroyThread(threadName_);
92     if (draggingPlayer_ != nullptr) {
93         destroyFunc_(draggingPlayer_);
94         draggingPlayer_ = nullptr;
95     }
96 }
97 
Init(const shared_ptr<DemuxerFilter> &demuxer, const shared_ptr<DecoderSurfaceFilter> &decoder, std::string playerId)98 Status DraggingPlayerAgent::Init(const shared_ptr<DemuxerFilter> &demuxer,
99     const shared_ptr<DecoderSurfaceFilter> &decoder, std::string playerId)
100 {
101     FALSE_RETURN_V_MSG_E(demuxer != nullptr && decoder != nullptr,
102         Status::ERROR_INVALID_PARAMETER, "Invalid demuxer filter instance.");
103     demuxer_ = demuxer;
104     decoder_ = decoder;
105     Status ret = draggingPlayer_->Init(demuxer, decoder);
106     if (ret != Status::OK) {
107         MEDIA_LOG_E("liyudebug DraggingPlayerAgent::Init failed");
108         return ret;
109     }
110     MEDIA_LOG_I("DraggingPlayerAgent::Init register");
111     videoStreamReadyCb_ = std::make_shared<VideoStreamReadyCallbackImpl>(shared_from_this());
112     demuxer->RegisterVideoStreamReadyCallback(videoStreamReadyCb_);
113     videoFrameReadyCb_ = std::make_shared<VideoFrameReadyCallbackImpl>(shared_from_this());
114     decoder->RegisterVideoFrameReadyCallback(videoFrameReadyCb_);
115     threadName_ = "DraggingTask_" + playerId;
116     task_ = std::make_unique<Task>("draggingThread", threadName_, TaskType::GLOBAL, TaskPriority::NORMAL, false);
117     task_->Start();
118     return Status::OK;
119 }
120 
IsVideoStreamDiscardable(const std::shared_ptr<AVBuffer> avBuffer)121 bool DraggingPlayerAgent::IsVideoStreamDiscardable(const std::shared_ptr<AVBuffer> avBuffer)
122 {
123     FALSE_RETURN_V_MSG_E(draggingPlayer_ != nullptr, false, "Invalid draggingPlayer_ instance.");
124     return draggingPlayer_->IsVideoStreamDiscardable(avBuffer);
125 }
126 
ConsumeVideoFrame(const std::shared_ptr<AVBuffer> avBuffer, uint32_t bufferIndex)127 void DraggingPlayerAgent::ConsumeVideoFrame(const std::shared_ptr<AVBuffer> avBuffer, uint32_t bufferIndex)
128 {
129     FALSE_RETURN(draggingPlayer_ != nullptr);
130     draggingPlayer_->ConsumeVideoFrame(avBuffer, bufferIndex);
131 }
132 
UpdateSeekPos(int64_t seekMs)133 void DraggingPlayerAgent::UpdateSeekPos(int64_t seekMs)
134 {
135     std::unique_lock<std::mutex> lock(draggingMutex_);
136     FALSE_RETURN(draggingPlayer_ != nullptr);
137     seekCnt_.fetch_add(1);
138     draggingPlayer_->UpdateSeekPos(seekMs);
139     if (task_) {
140         int64_t seekCnt = seekCnt_.load();
141         lock.unlock();
142         task_->SubmitJob([this, seekCnt]() { StopDragging(seekCnt); }, 33333); // 33333 means 33333us, 33ms
143     }
144 }
145 
StopDragging(int64_t seekCnt)146 void DraggingPlayerAgent::StopDragging(int64_t seekCnt)
147 {
148     std::unique_lock<std::mutex> lock(draggingMutex_);
149     FALSE_RETURN(!isReleased_);
150     FALSE_RETURN(draggingPlayer_ != nullptr);
151     if (seekCnt_.load() != seekCnt) {
152         return;
153     }
154     draggingPlayer_->StopDragging();
155 }
156 
Release()157 void DraggingPlayerAgent::Release()
158 {
159     if (task_) {
160         task_->Stop();
161     }
162     std::unique_lock<std::mutex> lock(draggingMutex_);
163     if (demuxer_ != nullptr) {
164         demuxer_->DeregisterVideoStreamReadyCallback();
165     }
166     if (decoder_ != nullptr) {
167         decoder_->DeregisterVideoFrameReadyCallback();
168     }
169     if (draggingPlayer_ != nullptr) {
170         draggingPlayer_->Release();
171     }
172     isReleased_ = true;
173 }
174 
LoadLibrary()175 void *DraggingPlayerAgent::LoadLibrary()
176 {
177     char path[PATH_MAX] = {0x00};
178     const char *inputPath = REFENCE_LIB_ABSOLUTE_PATH.c_str();
179     if (strlen(inputPath) > PATH_MAX || realpath(inputPath, path) == nullptr) {
180         MEDIA_LOG_E("dlopen failed due to Invalid path");
181         return nullptr;
182     }
183     auto ptr = ::dlopen(path, RTLD_NOW | RTLD_LOCAL);
184     if (ptr == nullptr) {
185         MEDIA_LOG_E("dlopen failed due to %{public}s", ::dlerror());
186     }
187     handler_ = ptr;
188     return ptr;
189 }
190 
CheckSymbol(void *handler)191 bool DraggingPlayerAgent::CheckSymbol(void *handler)
192 {
193     if (handler) {
194         std::string createFuncName = "CreateDraggingPlayer";
195         std::string destroyFuncName = "DestroyDraggingPlayer";
196         CreateFunc createFunc = nullptr;
197         DestroyFunc destroyFunc = nullptr;
198         createFunc = (CreateFunc)(::dlsym(handler, createFuncName.c_str()));
199         destroyFunc = (DestroyFunc)(::dlsym(handler, destroyFuncName.c_str()));
200         if (createFunc && destroyFunc) {
201             MEDIA_LOG_D("CheckSymbol:  createFuncName %{public}s", createFuncName.c_str());
202             MEDIA_LOG_D("CheckSymbol:  destroyFuncName %{public}s", destroyFuncName.c_str());
203             createFunc_ = createFunc;
204             destroyFunc_ = destroyFunc;
205             return true;
206         }
207     }
208     return false;
209 }
210 
LoadSymbol()211 bool DraggingPlayerAgent::LoadSymbol()
212 {
213     lock_guard<mutex> lock(mtx_);
214     if (handler_ == nullptr) {
215         if (!CheckSymbol(LoadLibrary())) {
216             MEDIA_LOG_E("Load Reference parser so fail");
217             return false;
218         }
219     }
220     return true;
221 }
222 }  // namespace Media
223 }  // namespace OHOS