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