• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifdef SUPPORT_AVPLAYER_DRM
25 #include "imedia_key_session_service.h"
26 #endif
27 
28 namespace {
29 const std::string REFERENCE_LIB_PATH = std::string(DRAGGING_PLAYER_PATH);
30 const std::string FILESEPARATOR = "/";
31 const std::string REFERENCE_LIB_NAME = "libvideo_dragging_player.z.so";
32 const std::string REFENCE_LIB_ABSOLUTE_PATH = REFERENCE_LIB_PATH + FILESEPARATOR + REFERENCE_LIB_NAME;
33 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_PLAYER, "DraggingPlayerAgent"};
34 }
35 
36 namespace OHOS {
37 namespace Media {
38 using namespace Pipeline;
39 
40 void *DraggingPlayerAgent::handler_ = nullptr;
41 DraggingPlayerAgent::CreateFunc DraggingPlayerAgent::createFunc_ = nullptr;
42 DraggingPlayerAgent::DestroyFunc DraggingPlayerAgent::destroyFunc_ = nullptr;
43 DraggingPlayerAgent::CheckSupportedFunc DraggingPlayerAgent::checkSupportedFunc_ = nullptr;
44 bool DraggingPlayerAgent::loaded_ = false;
45 std::mutex DraggingPlayerAgent::mtx_;
46 
47 class VideoStreamReadyCallbackImpl : public VideoStreamReadyCallback {
48 public:
VideoStreamReadyCallbackImpl(const std::shared_ptr<DraggingDelegator> draggingDelegator)49     explicit VideoStreamReadyCallbackImpl(const std::shared_ptr<DraggingDelegator> draggingDelegator)
50         : draggingDelegator_(draggingDelegator) {}
IsVideoStreamDiscardable(const std::shared_ptr<AVBuffer> buffer)51     bool IsVideoStreamDiscardable(const std::shared_ptr<AVBuffer> buffer) override
52     {
53         auto draggingDelegator = draggingDelegator_.lock();
54         FALSE_RETURN_V_MSG(draggingDelegator != nullptr && buffer != nullptr, false, "invalid parameter");
55         return draggingDelegator->IsVideoStreamDiscardable(buffer);
56     }
57 private:
58     std::weak_ptr<DraggingDelegator> draggingDelegator_;
59 };
60 
61 class VideoFrameReadyCallbackImpl : public VideoFrameReadyCallback {
62 public:
VideoFrameReadyCallbackImpl(const std::shared_ptr<DraggingDelegator> draggingDelegator)63     explicit VideoFrameReadyCallbackImpl(const std::shared_ptr<DraggingDelegator> draggingDelegator)
64         : draggingDelegator_(draggingDelegator) {}
ConsumeVideoFrame(const std::shared_ptr<AVBuffer> buffer,uint32_t bufferIndex)65     void ConsumeVideoFrame(const std::shared_ptr<AVBuffer> buffer, uint32_t bufferIndex) override
66     {
67         auto draggingDelegator = draggingDelegator_.lock();
68         FALSE_RETURN_MSG(draggingDelegator != nullptr && buffer != nullptr, "invalid parameter");
69         draggingDelegator->ConsumeVideoFrame(buffer, bufferIndex);
70     }
71 private:
72     std::weak_ptr<DraggingDelegator> draggingDelegator_;
73 };
74 
Create(const shared_ptr<OHOS::Media::Pipeline::Pipeline> pipeline,const shared_ptr<DemuxerFilter> demuxer,const shared_ptr<DecoderSurfaceFilter> decoder,const string & playerId)75 shared_ptr<DraggingPlayerAgent> DraggingPlayerAgent::Create(
76     const shared_ptr<OHOS::Media::Pipeline::Pipeline> pipeline,
77     const shared_ptr<DemuxerFilter> demuxer,
78     const shared_ptr<DecoderSurfaceFilter> decoder,
79     const string &playerId)
80 {
81     FALSE_RETURN_V_MSG_E(demuxer != nullptr && decoder != nullptr, nullptr, "Invalid demuxer filter instance.");
82     shared_ptr<DraggingPlayerAgent> agent = make_shared<DraggingPlayerAgent>(pipeline, demuxer, decoder, playerId);
83     FALSE_RETURN_V(DraggingPlayerAgent::LoadSymbol(), agent);
84     FALSE_RETURN_V(DraggingPlayerAgent::IsDraggingSupported(demuxer, decoder), agent);
85     agent->draggingMode_ = DraggingMode::DRAGGING_CONTINUOUS;
86     return agent;
87 }
88 
IsDraggingSupported(const shared_ptr<DemuxerFilter> demuxer,const shared_ptr<DecoderSurfaceFilter> decoder)89 bool DraggingPlayerAgent::IsDraggingSupported(const shared_ptr<DemuxerFilter> demuxer,
90     const shared_ptr<DecoderSurfaceFilter> decoder)
91 {
92     FALSE_RETURN_V_MSG_E(demuxer != nullptr && decoder != nullptr, false, "demuxer or decoder is null");
93     FALSE_RETURN_V_MSG_E(demuxer->IsLocalFd(), false, "source is not local fd");
94     FALSE_RETURN_V_MSG_E(LoadSymbol() && checkSupportedFunc_ != nullptr, false, "no so");
95     return checkSupportedFunc_(demuxer.get(), decoder.get());
96 }
97 
DraggingPlayerAgent(const shared_ptr<OHOS::Media::Pipeline::Pipeline> pipeline,const shared_ptr<DemuxerFilter> demuxer,const shared_ptr<DecoderSurfaceFilter> decoder,const string & playerId)98 DraggingPlayerAgent::DraggingPlayerAgent(
99     const shared_ptr<OHOS::Media::Pipeline::Pipeline> pipeline,
100     const shared_ptr<DemuxerFilter> demuxer,
101     const shared_ptr<DecoderSurfaceFilter> decoder,
102     const string &playerId)
103     : pipeline_(pipeline), demuxer_(demuxer), decoder_(decoder), playerId_(playerId)
104 {
105 }
106 
~DraggingPlayerAgent()107 DraggingPlayerAgent::~DraggingPlayerAgent()
108 {
109     if (!isReleased_) {
110         Release();
111     }
112     if (delegator_ != nullptr) {
113         delegator_ = nullptr;
114     }
115 }
116 
Init()117 Status DraggingPlayerAgent::Init()
118 {
119     FALSE_RETURN_V_MSG_E(demuxer_ != nullptr && decoder_ != nullptr,
120         Status::ERROR_INVALID_PARAMETER, "Invalid demuxer filter instance.");
121     delegator_ = DraggingDelegatorFactory::CreateDelegator(pipeline_, demuxer_, decoder_, playerId_, draggingMode_);
122     FALSE_RETURN_V_MSG_E(delegator_ != nullptr, Status::ERROR_INVALID_DATA, "delegator_ is null");
123     return Status::OK;
124 }
125 
UpdateSeekPos(int64_t seekMs)126 void DraggingPlayerAgent::UpdateSeekPos(int64_t seekMs)
127 {
128     FALSE_RETURN_MSG(delegator_ != nullptr, "delegator_ is null");
129     delegator_->UpdateSeekPos(seekMs);
130 }
131 
Release()132 void DraggingPlayerAgent::Release()
133 {
134     std::unique_lock<std::mutex> lock(draggingMutex_);
135     delegator_->Release();
136     isReleased_ = true;
137 }
138 
GetDraggingMode()139 DraggingMode DraggingPlayerAgent::GetDraggingMode()
140 {
141     return draggingMode_;
142 }
143 
LoadLibrary()144 void *DraggingPlayerAgent::LoadLibrary()
145 {
146     char path[PATH_MAX] = {0x00};
147     const char *inputPath = REFENCE_LIB_ABSOLUTE_PATH.c_str();
148     if (strlen(inputPath) > PATH_MAX || realpath(inputPath, path) == nullptr) {
149         MEDIA_LOG_E("dlopen failed due to Invalid path");
150         return nullptr;
151     }
152     auto ptr = ::dlopen(path, RTLD_NOW | RTLD_LOCAL);
153     FALSE_RETURN_V_MSG_E(ptr != nullptr, nullptr, "dlopen failed due to %{public}s", ::dlerror());
154     handler_ = ptr;
155     return ptr;
156 }
157 
CheckSymbol(void * handler)158 bool DraggingPlayerAgent::CheckSymbol(void *handler)
159 {
160     FALSE_RETURN_V_MSG_E(handler != nullptr, false, "handler is nullptr");
161     std::string createFuncName = "CreateDraggingPlayer";
162     std::string destroyFuncName = "DestroyDraggingPlayer";
163     std::string checkSupportedFuncName = "IsDraggingSupported";
164     CreateFunc createFunc = nullptr;
165     DestroyFunc destroyFunc = nullptr;
166     CheckSupportedFunc checkSupportedFunc = nullptr;
167     createFunc = (CreateFunc)(::dlsym(handler, createFuncName.c_str()));
168     destroyFunc = (DestroyFunc)(::dlsym(handler, destroyFuncName.c_str()));
169     checkSupportedFunc = (CheckSupportedFunc)(::dlsym(handler, checkSupportedFuncName.c_str()));
170     FALSE_RETURN_V_MSG_E(checkSupportedFunc != nullptr, false, "check supported func is nullptr");
171     checkSupportedFunc_ = checkSupportedFunc;
172     FALSE_RETURN_V_MSG_E(createFunc != nullptr && destroyFunc != nullptr, false, "create or destroy func is nullptr");
173     MEDIA_LOG_I("CheckSymbol:  createFuncName %{public}s, destroyFuncName %{public}s", createFuncName.c_str(),
174         destroyFuncName.c_str());
175     createFunc_ = createFunc;
176     destroyFunc_ = destroyFunc;
177     return true;
178 }
179 
LoadSymbol()180 bool DraggingPlayerAgent::LoadSymbol()
181 {
182     lock_guard<mutex> lock(mtx_);
183     FALSE_RETURN_V_MSG_E(!loaded_ || handler_ != nullptr, false, "loaded but no handler");
184     FALSE_RETURN_V_NOLOG(handler_ == nullptr, true);
185     loaded_ = true;
186     FALSE_RETURN_V_MSG_E(CheckSymbol(LoadLibrary()), false, "Load Reference parser so fail");
187     return true;
188 }
189 
CreateDelegator(const shared_ptr<OHOS::Media::Pipeline::Pipeline> pipeline,const shared_ptr<DemuxerFilter> demuxer,const shared_ptr<DecoderSurfaceFilter> decoder,const string & playerId,DraggingMode & draggingMode)190 shared_ptr<DraggingDelegator> DraggingDelegatorFactory::CreateDelegator(
191     const shared_ptr<OHOS::Media::Pipeline::Pipeline> pipeline,
192     const shared_ptr<DemuxerFilter> demuxer,
193     const shared_ptr<DecoderSurfaceFilter> decoder,
194     const string &playerId,
195     DraggingMode &draggingMode)
196 {
197     FALSE_RETURN_V_MSG_E(draggingMode != DraggingMode::DRAGGING_NONE, nullptr, "Invalid draggingMode.");
198     shared_ptr<DraggingDelegator> delegator = nullptr;
199     if (draggingMode == DraggingMode::DRAGGING_CONTINUOUS) {
200         shared_ptr<DraggingDelegator> delegator
201             = SeekContinuousDelegator::Create(pipeline, demuxer, decoder, playerId);
202         FALSE_RETURN_V_NOLOG(delegator == nullptr, delegator);
203     }
204     draggingMode = DraggingMode::DRAGGING_CLOSEST;
205     return SeekClosestDelegator::Create(pipeline, demuxer, decoder, playerId);
206 }
207 
Create(const shared_ptr<OHOS::Media::Pipeline::Pipeline> pipeline,const shared_ptr<DemuxerFilter> demuxer,const shared_ptr<DecoderSurfaceFilter> decoder,const string & playerId)208 shared_ptr<SeekContinuousDelegator> SeekContinuousDelegator::Create(
209     const shared_ptr<OHOS::Media::Pipeline::Pipeline> pipeline,
210     const shared_ptr<DemuxerFilter> demuxer,
211     const shared_ptr<DecoderSurfaceFilter> decoder,
212     const string &playerId)
213 {
214     shared_ptr<SeekContinuousDelegator> delegator
215         = make_shared<SeekContinuousDelegator>(pipeline, demuxer, decoder, playerId);
216     FALSE_RETURN_V_MSG_E(delegator != nullptr && delegator->draggingPlayer_ != nullptr,
217         nullptr, "delegator is nullptr");
218     Status ret = delegator->Init();
219     if (ret != Status::OK) {
220         delegator = nullptr;
221     }
222     return delegator;
223 }
224 
SeekContinuousDelegator(const shared_ptr<OHOS::Media::Pipeline::Pipeline> pipeline,const shared_ptr<DemuxerFilter> demuxer,const shared_ptr<DecoderSurfaceFilter> decoder,const string & playerId)225 SeekContinuousDelegator::SeekContinuousDelegator(
226     const shared_ptr<OHOS::Media::Pipeline::Pipeline> pipeline,
227     const shared_ptr<DemuxerFilter> demuxer,
228     const shared_ptr<DecoderSurfaceFilter> decoder,
229     const string &playerId)
230     : DraggingDelegator(pipeline, demuxer, decoder, playerId)
231 {
232     if (DraggingPlayerAgent::createFunc_ != nullptr) {
233         draggingPlayer_ = DraggingPlayerAgent::createFunc_();
234     }
235 }
236 
~SeekContinuousDelegator()237 SeekContinuousDelegator::~SeekContinuousDelegator()
238 {
239     if (!isReleased_) {
240         Release();
241     }
242     PipeLineThreadPool::GetInstance().DestroyThread(threadName_);
243     if (draggingPlayer_ != nullptr) {
244         DraggingPlayerAgent::destroyFunc_(draggingPlayer_);
245         draggingPlayer_ = nullptr;
246     }
247 }
248 
Init()249 Status SeekContinuousDelegator::Init()
250 {
251     MEDIA_LOG_I("SeekContinuousDelegator::Init");
252     FALSE_RETURN_V_MSG_E(demuxer_ != nullptr && decoder_ != nullptr,
253         Status::ERROR_INVALID_PARAMETER, "Invalid demuxer filter instance.");
254     Status ret = draggingPlayer_->Init(demuxer_, decoder_);
255     FALSE_RETURN_V_MSG_E(ret == Status::OK, ret, "SeekContinuousDelegator::Init failed");
256     videoStreamReadyCb_ = std::make_shared<VideoStreamReadyCallbackImpl>(shared_from_this());
257     demuxer_->RegisterVideoStreamReadyCallback(videoStreamReadyCb_);
258     videoFrameReadyCb_ = std::make_shared<VideoFrameReadyCallbackImpl>(shared_from_this());
259     decoder_->RegisterVideoFrameReadyCallback(videoFrameReadyCb_);
260     threadName_ = "DraggingTask_" + playerId_;
261     monitorTask_ = std::make_unique<Task>("draggingThread", threadName_, TaskType::GLOBAL, TaskPriority::NORMAL, false);
262     monitorTask_->Start();
263     return Status::OK;
264 }
265 
UpdateSeekPos(int64_t seekMs)266 void SeekContinuousDelegator::UpdateSeekPos(int64_t seekMs)
267 {
268     std::unique_lock<std::mutex> lock(draggingMutex_);
269     FALSE_RETURN(draggingPlayer_ != nullptr);
270     seekCnt_.fetch_add(1);
271     draggingPlayer_->UpdateSeekPos(seekMs);
272     if (monitorTask_ != nullptr) {
273         int64_t seekCnt = seekCnt_.load();
274         lock.unlock();
275         monitorTask_->SubmitJob([this, seekCnt]() { StopDragging(seekCnt); }, 33333); // 33333 means 33333us, 33ms
276     }
277 }
278 
Release()279 void SeekContinuousDelegator::Release()
280 {
281     MEDIA_LOG_I("SeekContinuousDelegator::Release");
282     if (monitorTask_) {
283         monitorTask_->Stop();
284     }
285     std::unique_lock<std::mutex> lock(draggingMutex_);
286     if (draggingPlayer_ != nullptr) {
287         draggingPlayer_->Release();
288     }
289     if (demuxer_ != nullptr) {
290         auto res = demuxer_->PauseDragging();
291         FALSE_LOG_MSG(res == Status::OK, "PauseDragging failed");
292         demuxer_->DeregisterVideoStreamReadyCallback();
293     }
294     if (decoder_ != nullptr) {
295         decoder_->DeregisterVideoFrameReadyCallback();
296     }
297     isReleased_ = true;
298 }
299 
ConsumeVideoFrame(const std::shared_ptr<AVBuffer> avBuffer,uint32_t bufferIndex)300 void SeekContinuousDelegator::ConsumeVideoFrame(const std::shared_ptr<AVBuffer> avBuffer, uint32_t bufferIndex)
301 {
302     FALSE_RETURN(draggingPlayer_ != nullptr);
303     draggingPlayer_->ConsumeVideoFrame(avBuffer, bufferIndex);
304 }
305 
IsVideoStreamDiscardable(const std::shared_ptr<AVBuffer> avBuffer)306 bool SeekContinuousDelegator::IsVideoStreamDiscardable(const std::shared_ptr<AVBuffer> avBuffer)
307 {
308     FALSE_RETURN_V_MSG_E(draggingPlayer_ != nullptr, false, "Invalid draggingPlayer_ instance.");
309     return draggingPlayer_->IsVideoStreamDiscardable(avBuffer);
310 }
311 
StopDragging(int64_t seekCnt)312 void SeekContinuousDelegator::StopDragging(int64_t seekCnt)
313 {
314     std::unique_lock<std::mutex> lock(draggingMutex_);
315     FALSE_RETURN(!isReleased_);
316     FALSE_RETURN(draggingPlayer_ != nullptr);
317     FALSE_RETURN_NOLOG(seekCnt_.load() == seekCnt);
318     draggingPlayer_->StopDragging();
319 }
320 
Create(const shared_ptr<OHOS::Media::Pipeline::Pipeline> pipeline,const shared_ptr<DemuxerFilter> demuxer,const shared_ptr<DecoderSurfaceFilter> decoder,const string & playerId)321 shared_ptr<SeekClosestDelegator> SeekClosestDelegator::Create(
322     const shared_ptr<OHOS::Media::Pipeline::Pipeline> pipeline,
323     const shared_ptr<DemuxerFilter> demuxer,
324     const shared_ptr<DecoderSurfaceFilter> decoder,
325     const string &playerId)
326 {
327     shared_ptr<SeekClosestDelegator> delegator
328         = make_shared<SeekClosestDelegator>(pipeline, demuxer, decoder, playerId);
329     FALSE_RETURN_V_MSG_E(delegator != nullptr, delegator, "delegator is nullptr");
330     Status ret = delegator->Init();
331     if (ret != Status::OK) {
332         delegator = nullptr;
333     }
334     return delegator;
335 }
336 
SeekClosestDelegator(const shared_ptr<OHOS::Media::Pipeline::Pipeline> pipeline,const shared_ptr<DemuxerFilter> demuxer,const shared_ptr<DecoderSurfaceFilter> decoder,const std::string & playerId)337 SeekClosestDelegator::SeekClosestDelegator(
338     const shared_ptr<OHOS::Media::Pipeline::Pipeline> pipeline,
339     const shared_ptr<DemuxerFilter> demuxer,
340     const shared_ptr<DecoderSurfaceFilter> decoder,
341     const std::string &playerId)
342     : DraggingDelegator(pipeline, demuxer, decoder, playerId)
343 {
344 }
345 
~SeekClosestDelegator()346 SeekClosestDelegator::~SeekClosestDelegator()
347 {
348     if (!isReleased_) {
349         Release();
350     }
351     PipeLineThreadPool::GetInstance().DestroyThread(threadName_);
352 }
353 
Init()354 Status SeekClosestDelegator::Init()
355 {
356     MEDIA_LOG_I("SeekClosestDelegator::Init");
357     threadName_ = "SeekTask_" + playerId_;
358     seekTask_ = std::make_unique<Task>("seekThread", threadName_, TaskType::GLOBAL, TaskPriority::NORMAL, false);
359     seekTask_->Start();
360     return Status::OK;
361 }
362 
UpdateSeekPos(int64_t seekMs)363 void SeekClosestDelegator::UpdateSeekPos(int64_t seekMs)
364 {
365     lock_guard<mutex> lock(queueMutex_);
366     seekTimeMsQue_.push_back(seekMs);
367     if (seekTimeMsQue_.size() == 1) {
368         seekTask_->SubmitJob([this]() { SeekJob(); });
369     }
370 }
371 
Release()372 void SeekClosestDelegator::Release()
373 {
374     MEDIA_LOG_I("SeekClosestDelegator::Release");
375     if (seekTask_) {
376         seekTask_->Stop();
377     }
378     int64_t lastSeekTimeMs = -1;
379     {
380         lock_guard<mutex> lock(queueMutex_);
381         if (seekTimeMsQue_.size() > 0) {
382             lastSeekTimeMs = seekTimeMsQue_.back();
383             seekTimeMsQue_.clear();
384         }
385     }
386     DoSeek(lastSeekTimeMs);
387     isReleased_ = true;
388 }
389 
SeekJob()390 void SeekClosestDelegator::SeekJob()
391 {
392     int64_t seekTimeMs = -1;
393     {
394         lock_guard<mutex> lock(queueMutex_);
395         if (seekTimeMsQue_.size() <= 0) {
396             return;
397         }
398         seekTimeMs = seekTimeMsQue_.back();
399         seekTimeMsQue_.clear();
400     }
401     DoSeek(seekTimeMs);
402 }
403 
DoSeek(int64_t seekTimeMs)404 void SeekClosestDelegator::DoSeek(int64_t seekTimeMs)
405 {
406     FALSE_RETURN_MSG(seekTimeMs >= 0, "invalid seekTimeMs");
407     FALSE_RETURN_MSG(pipeline_ != nullptr && demuxer_ != nullptr && decoder_ != nullptr, "key objects is null");
408     lock_guard<mutex> lock(seekClosestMutex_);
409     FALSE_RETURN_MSG(seekTimeMs != curSeekTimeMs_, "the same seek time with last seek;");
410     curSeekTimeMs_ = seekTimeMs;
411     int64_t seekTimeUs = 0;
412     FALSE_RETURN_MSG(Plugins::Us2HstTime(seekTimeMs, seekTimeUs), "cast seekTime ms to us failed");
413     pipeline_->Flush();
414     decoder_->SetSeekTime(seekTimeUs);
415     int64_t realSeekTimeMs = seekTimeMs;
416     Status res = demuxer_->SeekTo(seekTimeMs, Plugins::SeekMode::SEEK_CLOSEST_INNER, realSeekTimeMs);
417     FALSE_RETURN_MSG(res == Status::OK, "demuxer seekto error.");
418     pipeline_->Preroll(true);
419 }
420 }  // namespace Media
421 }  // namespace OHOS