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