1 /*
2 * Copyright (c) 2023-2023 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 MEDIA_PIPELINE
17
18 #include <sys/time.h>
19 #include "filter/filter_factory.h"
20 #include "plugin/plugin_time.h"
21 #include "avcodec_errors.h"
22 #include "common/log.h"
23 #include "common/media_core.h"
24 #include "avcodec_info.h"
25 #include "avcodec_common.h"
26 #include "avcodec_errors.h"
27 #include "avcodec_list.h"
28 #include "video_decoder_adapter.h"
29 #include "decoder_surface_filter.h"
30 #include "osal/utils/util.h"
31 #include "parameters.h"
32
33 namespace {
34 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_DOMAIN_SYSTEM_PLAYER, "DecoderSurfaceFilter" };
35 }
36
37 namespace OHOS {
38 namespace Media {
39 namespace Pipeline {
40 static const int64_t PLAY_RANGE_DEFAULT_VALUE = -1;
41 static const int64_t MICROSECONDS_CONVERT_UNIT = 1000; // ms change to us
42 static const uint32_t PREROLL_WAIT_TIME = 1000; // Lock wait for 1000ms.
43
44 static AutoRegisterFilter<DecoderSurfaceFilter> g_registerDecoderSurfaceFilter("builtin.player.videodecoder",
__anon27cc4c170202(const std::string& name, const FilterType type) 45 FilterType::FILTERTYPE_VDEC, [](const std::string& name, const FilterType type) {
46 return std::make_shared<DecoderSurfaceFilter>(name, FilterType::FILTERTYPE_VDEC);
47 });
48
49 static const bool IS_FILTER_ASYNC = system::GetParameter("persist.media_service.async_filter", "1") == "1";
50
51 static const std::string VIDEO_INPUT_BUFFER_QUEUE_NAME = "VideoDecoderInputBufferQueue";
52
53 class DecoderSurfaceFilterLinkCallback : public FilterLinkCallback {
54 public:
DecoderSurfaceFilterLinkCallback(std::shared_ptr<DecoderSurfaceFilter> decoderSurfaceFilter)55 explicit DecoderSurfaceFilterLinkCallback(std::shared_ptr<DecoderSurfaceFilter> decoderSurfaceFilter)
56 : decoderSurfaceFilter_(decoderSurfaceFilter) {}
57
58 ~DecoderSurfaceFilterLinkCallback() = default;
59
OnLinkedResult(const sptr<AVBufferQueueProducer> & queue,std::shared_ptr<Meta> & meta)60 void OnLinkedResult(const sptr<AVBufferQueueProducer> &queue, std::shared_ptr<Meta> &meta) override
61 {
62 MEDIA_LOG_I("OnLinkedResult enter.");
63 decoderSurfaceFilter_->OnLinkedResult(queue, meta);
64 }
65
OnUnlinkedResult(std::shared_ptr<Meta> & meta)66 void OnUnlinkedResult(std::shared_ptr<Meta> &meta) override
67 {
68 decoderSurfaceFilter_->OnUnlinkedResult(meta);
69 }
70
OnUpdatedResult(std::shared_ptr<Meta> & meta)71 void OnUpdatedResult(std::shared_ptr<Meta> &meta) override
72 {
73 decoderSurfaceFilter_->OnUpdatedResult(meta);
74 }
75 private:
76 std::shared_ptr<DecoderSurfaceFilter> decoderSurfaceFilter_;
77 };
78
79 const std::unordered_map<VideoScaleType, OHOS::ScalingMode> SCALEMODE_MAP = {
80 { VideoScaleType::VIDEO_SCALE_TYPE_FIT, OHOS::SCALING_MODE_SCALE_TO_WINDOW },
81 { VideoScaleType::VIDEO_SCALE_TYPE_FIT_CROP, OHOS::SCALING_MODE_SCALE_CROP},
82 };
83
84 class FilterMediaCodecCallback : public OHOS::MediaAVCodec::MediaCodecCallback {
85 public:
FilterMediaCodecCallback(std::shared_ptr<DecoderSurfaceFilter> decoderSurfaceFilter)86 explicit FilterMediaCodecCallback(std::shared_ptr<DecoderSurfaceFilter> decoderSurfaceFilter)
87 : decoderSurfaceFilter_(decoderSurfaceFilter) {}
88
89 ~FilterMediaCodecCallback() = default;
90
OnError(MediaAVCodec::AVCodecErrorType errorType,int32_t errorCode)91 void OnError(MediaAVCodec::AVCodecErrorType errorType, int32_t errorCode) override
92 {
93 if (auto decoderSurfaceFilter = decoderSurfaceFilter_.lock()) {
94 decoderSurfaceFilter->OnError(errorType, errorCode);
95 } else {
96 MEDIA_LOG_I("invalid decoderSurfaceFilter");
97 }
98 }
99
OnOutputFormatChanged(const MediaAVCodec::Format & format)100 void OnOutputFormatChanged(const MediaAVCodec::Format &format) override
101 {
102 if (auto decoderSurfaceFilter = decoderSurfaceFilter_.lock()) {
103 decoderSurfaceFilter->OnOutputFormatChanged(format);
104 } else {
105 MEDIA_LOG_I("invalid decoderSurfaceFilter");
106 }
107 }
108
OnInputBufferAvailable(uint32_t index,std::shared_ptr<AVBuffer> buffer)109 void OnInputBufferAvailable(uint32_t index, std::shared_ptr<AVBuffer> buffer) override
110 {
111 }
112
OnOutputBufferAvailable(uint32_t index,std::shared_ptr<AVBuffer> buffer)113 void OnOutputBufferAvailable(uint32_t index, std::shared_ptr<AVBuffer> buffer) override
114 {
115 if (auto decoderSurfaceFilter = decoderSurfaceFilter_.lock()) {
116 decoderSurfaceFilter->DrainOutputBuffer(index, buffer);
117 } else {
118 MEDIA_LOG_I("invalid decoderSurfaceFilter");
119 }
120 }
121
122 private:
123 std::weak_ptr<DecoderSurfaceFilter> decoderSurfaceFilter_;
124 };
125
126 class AVBufferAvailableListener : public OHOS::Media::IConsumerListener {
127 public:
AVBufferAvailableListener(std::shared_ptr<DecoderSurfaceFilter> decoderSurfaceFilter)128 explicit AVBufferAvailableListener(std::shared_ptr<DecoderSurfaceFilter> decoderSurfaceFilter)
129 {
130 decoderSurfaceFilter_ = decoderSurfaceFilter;
131 }
132 ~AVBufferAvailableListener() = default;
133
OnBufferAvailable()134 void OnBufferAvailable()
135 {
136 if (auto decoderSurfaceFilter = decoderSurfaceFilter_.lock()) {
137 decoderSurfaceFilter->HandleInputBuffer();
138 } else {
139 MEDIA_LOG_I("invalid videoDecoder");
140 }
141 }
142
143 private:
144 std::weak_ptr<DecoderSurfaceFilter> decoderSurfaceFilter_;
145 };
146
DecoderSurfaceFilter(const std::string & name,FilterType type)147 DecoderSurfaceFilter::DecoderSurfaceFilter(const std::string& name, FilterType type)
148 : Filter(name, type, IS_FILTER_ASYNC)
149 {
150 videoDecoder_ = std::make_shared<VideoDecoderAdapter>();
151 videoSink_ = std::make_shared<VideoSink>();
152 filterType_ = type;
153 }
154
~DecoderSurfaceFilter()155 DecoderSurfaceFilter::~DecoderSurfaceFilter()
156 {
157 MEDIA_LOG_I("~DecoderSurfaceFilter() enter.");
158 if (!IS_FILTER_ASYNC && !isThreadExit_) {
159 isThreadExit_ = true;
160 condBufferAvailable_.notify_all();
161 if (readThread_ != nullptr && readThread_->joinable()) {
162 readThread_->join();
163 readThread_ = nullptr;
164 }
165 }
166 videoDecoder_->Release();
167 MEDIA_LOG_I("~DecoderSurfaceFilter() exit.");
168 }
169
OnError(MediaAVCodec::AVCodecErrorType errorType,int32_t errorCode)170 void DecoderSurfaceFilter::OnError(MediaAVCodec::AVCodecErrorType errorType, int32_t errorCode)
171 {
172 MEDIA_LOG_E("AVCodec error happened. ErrorType: %{public}d, errorCode: %{public}d",
173 static_cast<int32_t>(errorType), errorCode);
174 if (eventReceiver_ != nullptr) {
175 eventReceiver_->OnEvent({"DecoderSurfaceFilter", EventType::EVENT_ERROR, MSERR_EXT_API9_IO});
176 }
177 }
178
Init(const std::shared_ptr<EventReceiver> & receiver,const std::shared_ptr<FilterCallback> & callback)179 void DecoderSurfaceFilter::Init(const std::shared_ptr<EventReceiver> &receiver,
180 const std::shared_ptr<FilterCallback> &callback)
181 {
182 MEDIA_LOG_I("Init enter.");
183 eventReceiver_ = receiver;
184 filterCallback_ = callback;
185 videoSink_->SetEventReceiver(eventReceiver_);
186 FALSE_RETURN(videoDecoder_ != nullptr);
187 videoDecoder_->SetEventReceiver(eventReceiver_);
188 }
189
Configure(const std::shared_ptr<Meta> & parameter)190 Status DecoderSurfaceFilter::Configure(const std::shared_ptr<Meta> ¶meter)
191 {
192 MEDIA_LOG_I("Configure enter.");
193 configureParameter_ = parameter;
194 configFormat_.SetMeta(configureParameter_);
195 Status ret = videoDecoder_->Configure(configFormat_);
196 std::shared_ptr<MediaAVCodec::MediaCodecCallback> mediaCodecCallback
197 = std::make_shared<FilterMediaCodecCallback>(shared_from_this());
198 videoDecoder_->SetCallback(mediaCodecCallback);
199 return ret;
200 }
201
DoInitAfterLink()202 Status DecoderSurfaceFilter::DoInitAfterLink()
203 {
204 Status ret;
205 // create secure decoder for drm.
206 MEDIA_LOG_I("DoInit enter the codecMimeType_ is %{public}s", codecMimeType_.c_str());
207 if (videoDecoder_ != nullptr) {
208 videoDecoder_->SetCallingInfo(appUid_, appPid_, bundleName_, instanceId_);
209 }
210 if (isDrmProtected_ && svpFlag_) {
211 MEDIA_LOG_D("DecoderSurfaceFilter will create secure decoder for drm-protected videos");
212 std::string baseName = GetCodecName(codecMimeType_);
213 FALSE_RETURN_V_MSG(!baseName.empty(),
214 Status::ERROR_INVALID_PARAMETER, "get name by mime failed.");
215 std::string secureDecoderName = baseName + ".secure";
216 MEDIA_LOG_D("DecoderSurfaceFilter will create secure decoder %{public}s", secureDecoderName.c_str());
217 ret = videoDecoder_->Init(MediaAVCodec::AVCodecType::AVCODEC_TYPE_VIDEO_DECODER, false, secureDecoderName);
218 } else {
219 ret = videoDecoder_->Init(MediaAVCodec::AVCodecType::AVCODEC_TYPE_VIDEO_DECODER, true, codecMimeType_);
220 }
221
222 if (ret != Status::OK && eventReceiver_ != nullptr) {
223 MEDIA_LOG_E("Init decoder fail ret = %{public}d", ret);
224 eventReceiver_->OnEvent({"decoderSurface", EventType::EVENT_ERROR, MSERR_UNSUPPORT_VID_DEC_TYPE});
225 return Status::ERROR_UNSUPPORTED_FORMAT;
226 }
227
228 ret = Configure(meta_);
229 if (ret != Status::OK) {
230 eventReceiver_->OnEvent({"decoderSurface", EventType::EVENT_ERROR, MSERR_UNSUPPORT_VID_SRC_TYPE});
231 return Status::ERROR_UNSUPPORTED_FORMAT;
232 }
233 ParseDecodeRateLimit();
234 videoDecoder_->SetOutputSurface(videoSurface_);
235 if (isDrmProtected_) {
236 videoDecoder_->SetDecryptConfig(keySessionServiceProxy_, svpFlag_);
237 }
238 videoSink_->SetParameter(meta_);
239 return Status::OK;
240 }
241
DoPrepare()242 Status DecoderSurfaceFilter::DoPrepare()
243 {
244 MEDIA_LOG_I("Prepare enter.");
245 if (onLinkedResultCallback_ != nullptr) {
246 videoDecoder_->PrepareInputBufferQueue();
247 sptr<IConsumerListener> listener = new AVBufferAvailableListener(shared_from_this());
248 sptr<Media::AVBufferQueueConsumer> inputBufferQueueConsumer = videoDecoder_->GetBufferQueueConsumer();
249 inputBufferQueueConsumer->SetBufferAvailableListener(listener);
250 onLinkedResultCallback_->OnLinkedResult(videoDecoder_->GetBufferQueueProducer(), meta_);
251 }
252 isRenderStarted_ = false;
253 return Status::OK;
254 }
255
HandleInputBuffer()256 Status DecoderSurfaceFilter::HandleInputBuffer()
257 {
258 ProcessInputBuffer();
259 return Status::OK;
260 }
261
DoStart()262 Status DecoderSurfaceFilter::DoStart()
263 {
264 MEDIA_LOG_I("Start enter.");
265 if (isPaused_.load()) {
266 MEDIA_LOG_I("DoStart after pause to execute resume.");
267 return DoResume();
268 }
269 if (!IS_FILTER_ASYNC) {
270 isThreadExit_ = false;
271 isPaused_ = false;
272 readThread_ = std::make_unique<std::thread>(&DecoderSurfaceFilter::RenderLoop, this);
273 pthread_setname_np(readThread_->native_handle(), "RenderLoop");
274 }
275 return videoDecoder_->Start();
276 }
277
DoPause()278 Status DecoderSurfaceFilter::DoPause()
279 {
280 MEDIA_LOG_I("Pause enter.");
281 isPaused_ = true;
282 isFirstFrameAfterResume_ = false;
283 if (!IS_FILTER_ASYNC) {
284 condBufferAvailable_.notify_all();
285 }
286 videoSink_->ResetSyncInfo();
287 latestPausedTime_ = latestBufferTime_;
288 if (videoDecoder_ != nullptr) {
289 videoDecoder_->ResetRenderTime();
290 }
291 return Status::OK;
292 }
293
DoPauseDragging()294 Status DecoderSurfaceFilter::DoPauseDragging()
295 {
296 MEDIA_LOG_I("DoPauseDragging enter.");
297 DoPause();
298 {
299 std::unique_lock<std::mutex> lock(mutex_);
300 if (!outputBufferMap_.empty()) {
301 MEDIA_LOG_E("DoPauseDragging outputBufferMap_ size = %{public}zu", outputBufferMap_.size());
302 for (auto it = outputBufferMap_.begin(); it != outputBufferMap_.end(); ++it) {
303 videoDecoder_->ReleaseOutputBuffer(it->first, false);
304 }
305 outputBufferMap_.clear();
306 }
307 }
308 return Status::OK;
309 }
310
DoResume()311 Status DecoderSurfaceFilter::DoResume()
312 {
313 MEDIA_LOG_I("Resume enter.");
314 refreshTotalPauseTime_ = true;
315 isPaused_ = false;
316 isFirstFrameAfterResume_ = true;
317 if (!IS_FILTER_ASYNC) {
318 condBufferAvailable_.notify_all();
319 }
320 videoDecoder_->Start();
321 return Status::OK;
322 }
323
DoResumeDragging()324 Status DecoderSurfaceFilter::DoResumeDragging()
325 {
326 MEDIA_LOG_I("DoResumeDragging enter.");
327 refreshTotalPauseTime_ = true;
328 isPaused_ = false;
329 if (!IS_FILTER_ASYNC) {
330 condBufferAvailable_.notify_all();
331 }
332 videoDecoder_->Start();
333 return Status::OK;
334 }
335
DoStop()336 Status DecoderSurfaceFilter::DoStop()
337 {
338 MEDIA_LOG_I("Stop enter.");
339 latestBufferTime_ = HST_TIME_NONE;
340 latestPausedTime_ = HST_TIME_NONE;
341 totalPausedTime_ = 0;
342 refreshTotalPauseTime_ = false;
343 isPaused_ = false;
344 playRangeStartTime_ = PLAY_RANGE_DEFAULT_VALUE;
345 playRangeEndTime_ = PLAY_RANGE_DEFAULT_VALUE;
346
347 timeval tv;
348 gettimeofday(&tv, 0);
349 stopTime_ = (int64_t)tv.tv_sec * 1000000 + (int64_t)tv.tv_usec; // 1000000 means transfering from s to us.
350 videoSink_->ResetSyncInfo();
351 auto ret = videoDecoder_->Stop();
352 if (!IS_FILTER_ASYNC && !isThreadExit_.load()) {
353 isThreadExit_ = true;
354 condBufferAvailable_.notify_all();
355 if (readThread_ != nullptr && readThread_->joinable()) {
356 readThread_->join();
357 readThread_ = nullptr;
358 }
359 }
360 return ret;
361 }
362
DoFlush()363 Status DecoderSurfaceFilter::DoFlush()
364 {
365 MEDIA_LOG_I("Flush enter.");
366 videoDecoder_->Flush();
367 {
368 std::lock_guard<std::mutex> lock(mutex_);
369 outputBuffers_.clear();
370 outputBufferMap_.clear();
371 }
372 videoSink_->ResetSyncInfo();
373 return Status::OK;
374 }
375
DoRelease()376 Status DecoderSurfaceFilter::DoRelease()
377 {
378 MEDIA_LOG_I("Release enter.");
379 videoDecoder_->Release();
380 return Status::OK;
381 }
382
DoPreroll()383 Status DecoderSurfaceFilter::DoPreroll()
384 {
385 MEDIA_LOG_I("DoPreroll enter.");
386 std::lock_guard<std::mutex> lock(prerollMutex_);
387 Status ret = Status::OK;
388 FALSE_RETURN_V_MSG(!inPreroll_.load(), Status::OK, "DoPreroll in preroll now.");
389 inPreroll_.store(true);
390 prerollDone_.store(false);
391 eosNext_.store(false);
392 if (isPaused_.load()) {
393 ret = DoResume();
394 } else {
395 ret = DoStart();
396 }
397 if (ret != Status::OK) {
398 MEDIA_LOG_E("video decoder start failed, ret = %{public}d", ret);
399 eventReceiver_->OnEvent({"decoderSurface", EventType::EVENT_ERROR,
400 MSERR_VID_DEC_FAILED});
401 }
402 Filter::StartFilterTask();
403 return ret;
404 }
405
DoWaitPrerollDone(bool render)406 Status DecoderSurfaceFilter::DoWaitPrerollDone(bool render)
407 {
408 MEDIA_LOG_I("DoWaitPrerollDone enter.");
409 std::unique_lock<std::mutex> lock(prerollMutex_);
410 FALSE_RETURN_V(inPreroll_.load(), Status::OK);
411 if (prerollDone_.load() || isInterruptNeeded_.load()) {
412 MEDIA_LOG_I("Receive preroll frame before DoWaitPrerollDone.");
413 } else {
414 prerollDoneCond_.wait_for(lock, std::chrono::milliseconds(PREROLL_WAIT_TIME),
415 [this] () { return prerollDone_.load() || isInterruptNeeded_.load(); });
416 }
417 Filter::PauseFilterTask();
418 DoPause();
419 if (!prerollDone_.load()) {
420 MEDIA_LOG_E("No preroll frame received!");
421 inPreroll_.store(false);
422 prerollDone_.store(true);
423 eosNext_.store(false);
424 return Status::OK;
425 }
426 std::unique_lock<std::mutex> bufferLock(mutex_);
427 if (render && !eosNext_.load() && !outputBuffers_.empty()) {
428 std::pair<int, std::shared_ptr<AVBuffer>> nextTask = std::move(outputBuffers_.front());
429 outputBuffers_.pop_front();
430 videoDecoder_->ReleaseOutputBuffer(nextTask.first, true);
431 }
432 eosNext_.store(false);
433 if (!outputBuffers_.empty()) {
434 Filter::ProcessOutputBuffer(1, 0);
435 }
436 inPreroll_.store(false);
437 return Status::OK;
438 }
439
DoSetPlayRange(int64_t start,int64_t end)440 Status DecoderSurfaceFilter::DoSetPlayRange(int64_t start, int64_t end)
441 {
442 MEDIA_LOG_I("DoSetPlayRange enter.");
443 playRangeStartTime_ = start;
444 playRangeEndTime_ = end;
445 return Status::OK;
446 }
447
ConvertMediaScaleType(VideoScaleType scaleType)448 static OHOS::ScalingMode ConvertMediaScaleType(VideoScaleType scaleType)
449 {
450 if (SCALEMODE_MAP.find(scaleType) == SCALEMODE_MAP.end()) {
451 return OHOS::SCALING_MODE_SCALE_CROP;
452 }
453 return SCALEMODE_MAP.at(scaleType);
454 }
455
SetParameter(const std::shared_ptr<Meta> & parameter)456 void DecoderSurfaceFilter::SetParameter(const std::shared_ptr<Meta> ¶meter)
457 {
458 MEDIA_LOG_I("SetParameter enter parameter is valid: %{public}i", parameter != nullptr);
459 Format format;
460 if (parameter->Find(Tag::VIDEO_SCALE_TYPE) != parameter->end()) {
461 int32_t scaleType;
462 parameter->Get<Tag::VIDEO_SCALE_TYPE>(scaleType);
463 int32_t codecScalingMode = static_cast<int32_t>(ConvertMediaScaleType(static_cast<VideoScaleType>(scaleType)));
464 format.PutIntValue(Tag::VIDEO_SCALE_TYPE, codecScalingMode);
465 configFormat_.PutIntValue(Tag::VIDEO_SCALE_TYPE, codecScalingMode);
466 }
467 if (parameter->Find(Tag::VIDEO_FRAME_RATE) != parameter->end()) {
468 double rate = 0.0;
469 parameter->Get<Tag::VIDEO_FRAME_RATE>(rate);
470 if (rate < 0) {
471 if (configFormat_.GetDoubleValue(Tag::VIDEO_FRAME_RATE, rate)) {
472 MEDIA_LOG_W("rate is invalid, get frame rate from the original resource: %{public}f", rate);
473 }
474 }
475 if (rate <= 0) {
476 rate = 30.0; // 30.0 is the hisi default frame rate.
477 }
478 format.PutDoubleValue(Tag::VIDEO_FRAME_RATE, rate);
479 }
480 // cannot set parameter when codec at [ CONFIGURED / INITIALIZED ] state
481 auto ret = videoDecoder_->SetParameter(format);
482 if (ret == MediaAVCodec::AVCS_ERR_INVALID_STATE) {
483 MEDIA_LOG_W("SetParameter at invalid state");
484 videoDecoder_->Reset();
485 if (!IS_FILTER_ASYNC && !isThreadExit_.load()) {
486 Stop();
487 }
488 videoDecoder_->Configure(configFormat_);
489 videoDecoder_->SetOutputSurface(videoSurface_);
490 if (isDrmProtected_) {
491 videoDecoder_->SetDecryptConfig(keySessionServiceProxy_, svpFlag_);
492 }
493 }
494 videoDecoder_->SetParameter(format);
495 }
496
GetLagInfo(int32_t & lagTimes,int32_t & maxLagDuration,int32_t & avgLagDuration)497 Status DecoderSurfaceFilter::GetLagInfo(int32_t& lagTimes, int32_t& maxLagDuration, int32_t& avgLagDuration)
498 {
499 FALSE_RETURN_V(videoSink_ != nullptr, Status::ERROR_INVALID_OPERATION);
500 videoSink_->GetLagInfo(lagTimes, maxLagDuration, avgLagDuration);
501 return Status::OK;
502 }
503
GetParameter(std::shared_ptr<Meta> & parameter)504 void DecoderSurfaceFilter::GetParameter(std::shared_ptr<Meta> ¶meter)
505 {
506 MEDIA_LOG_I("GetParameter enter parameter is valid: %{public}i", parameter != nullptr);
507 }
508
SetCallingInfo(int32_t appUid,int32_t appPid,const std::string & bundleName,uint64_t instanceId)509 void DecoderSurfaceFilter::SetCallingInfo(int32_t appUid, int32_t appPid, const std::string& bundleName,
510 uint64_t instanceId)
511 {
512 appUid_ = appUid;
513 appPid_ = appPid;
514 bundleName_ = bundleName;
515 instanceId_ = instanceId;
516 }
517
SetInterruptState(bool isInterruptNeeded)518 void DecoderSurfaceFilter::SetInterruptState(bool isInterruptNeeded)
519 {
520 std::lock_guard<std::mutex> lock(prerollMutex_);
521 isInterruptNeeded_ = isInterruptNeeded;
522 prerollDoneCond_.notify_all();
523 }
524
LinkNext(const std::shared_ptr<Filter> & nextFilter,StreamType outType)525 Status DecoderSurfaceFilter::LinkNext(const std::shared_ptr<Filter> &nextFilter, StreamType outType)
526 {
527 MEDIA_LOG_I("LinkNext enter, nextFilter is valid: %{public}i, outType: %{public}u",
528 nextFilter != nullptr, static_cast<uint32_t>(outType));
529 return Status::OK;
530 }
531
UpdateNext(const std::shared_ptr<Filter> & nextFilter,StreamType outType)532 Status DecoderSurfaceFilter::UpdateNext(const std::shared_ptr<Filter> &nextFilter, StreamType outType)
533 {
534 return Status::OK;
535 }
536
UnLinkNext(const std::shared_ptr<Filter> & nextFilter,StreamType outType)537 Status DecoderSurfaceFilter::UnLinkNext(const std::shared_ptr<Filter> &nextFilter, StreamType outType)
538 {
539 return Status::OK;
540 }
541
GetFilterType()542 FilterType DecoderSurfaceFilter::GetFilterType()
543 {
544 return filterType_;
545 }
546
GetCodecName(std::string mimeType)547 std::string DecoderSurfaceFilter::GetCodecName(std::string mimeType)
548 {
549 MEDIA_LOG_I("GetCodecName.");
550 std::string codecName;
551 auto codeclist = MediaAVCodec::AVCodecListFactory::CreateAVCodecList();
552 if (codeclist == nullptr) {
553 MEDIA_LOG_E("GetCodecName failed due to codeclist nullptr.");
554 return codecName;
555 }
556 MediaAVCodec::Format format;
557 format.PutStringValue("codec_mime", mimeType);
558 codecName = codeclist->FindDecoder(format);
559 return codecName;
560 }
561
OnLinked(StreamType inType,const std::shared_ptr<Meta> & meta,const std::shared_ptr<FilterLinkCallback> & callback)562 Status DecoderSurfaceFilter::OnLinked(StreamType inType, const std::shared_ptr<Meta> &meta,
563 const std::shared_ptr<FilterLinkCallback> &callback)
564 {
565 MEDIA_LOG_I("OnLinked enter.");
566 meta_ = meta;
567 FALSE_RETURN_V_MSG(meta->GetData(Tag::MIME_TYPE, codecMimeType_),
568 Status::ERROR_INVALID_PARAMETER, "get mime failed.");
569 onLinkedResultCallback_ = callback;
570 return Status::OK;
571 }
572
OnUpdated(StreamType inType,const std::shared_ptr<Meta> & meta,const std::shared_ptr<FilterLinkCallback> & callback)573 Status DecoderSurfaceFilter::OnUpdated(StreamType inType, const std::shared_ptr<Meta> &meta,
574 const std::shared_ptr<FilterLinkCallback> &callback)
575 {
576 return Status::OK;
577 }
578
OnUnLinked(StreamType inType,const std::shared_ptr<FilterLinkCallback> & callback)579 Status DecoderSurfaceFilter::OnUnLinked(StreamType inType, const std::shared_ptr<FilterLinkCallback>& callback)
580 {
581 return Status::OK;
582 }
583
OnLinkedResult(const sptr<AVBufferQueueProducer> & outputBufferQueue,std::shared_ptr<Meta> & meta)584 void DecoderSurfaceFilter::OnLinkedResult(const sptr<AVBufferQueueProducer> &outputBufferQueue,
585 std::shared_ptr<Meta> &meta)
586 {
587 MEDIA_LOG_I("OnLinkedResult enter.");
588 }
589
OnUpdatedResult(std::shared_ptr<Meta> & meta)590 void DecoderSurfaceFilter::OnUpdatedResult(std::shared_ptr<Meta> &meta)
591 {
592 }
593
OnUnlinkedResult(std::shared_ptr<Meta> & meta)594 void DecoderSurfaceFilter::OnUnlinkedResult(std::shared_ptr<Meta> &meta)
595 {
596 }
597
DoProcessOutputBuffer(int recvArg,bool dropFrame,bool byIdx,uint32_t idx,int64_t renderTime)598 Status DecoderSurfaceFilter::DoProcessOutputBuffer(int recvArg, bool dropFrame, bool byIdx, uint32_t idx,
599 int64_t renderTime)
600 {
601 MEDIA_LOG_D("DoProcessOutputBuffer idx " PUBLIC_LOG_U32 " renderTime " PUBLIC_LOG_D64, idx, renderTime);
602 FALSE_RETURN_V(!dropFrame, Status::OK);
603 uint32_t index = idx;
604 std::shared_ptr<AVBuffer> outputBuffer = nullptr;
605 bool acquireRes = AcquireNextRenderBuffer(byIdx, index, outputBuffer);
606 FALSE_RETURN_V(acquireRes, Status::OK);
607 ReleaseOutputBuffer(index, recvArg, outputBuffer, renderTime);
608 return Status::OK;
609 }
610
AcquireNextRenderBuffer(bool byIdx,uint32_t & index,std::shared_ptr<AVBuffer> & outBuffer)611 bool DecoderSurfaceFilter::AcquireNextRenderBuffer(bool byIdx, uint32_t &index, std::shared_ptr<AVBuffer> &outBuffer)
612 {
613 std::unique_lock<std::mutex> lock(mutex_);
614 if (!byIdx) {
615 FALSE_RETURN_V(!outputBuffers_.empty(), false);
616 std::pair<int, std::shared_ptr<AVBuffer>> task = std::move(outputBuffers_.front());
617 outputBuffers_.pop_front();
618 FALSE_RETURN_V(task.first >= 0, false);
619 index = static_cast<uint32_t>(task.first);
620 outBuffer = task.second;
621 if (isFirstFrameAfterResume_) {
622 videoSink_->UpdateTimeAnchorActually(outBuffer);
623 isFirstFrameAfterResume_ = false;
624 }
625 if (!outputBuffers_.empty()) {
626 std::pair<int, std::shared_ptr<AVBuffer>> nextTask = outputBuffers_.front();
627 RenderNextOutput(nextTask.first, nextTask.second);
628 }
629 return true;
630 }
631 FALSE_RETURN_V(outputBufferMap_.find(index) != outputBufferMap_.end(), false);
632 outBuffer = outputBufferMap_[index];
633 outputBufferMap_.erase(index);
634 return true;
635 }
636
ReleaseOutputBuffer(int index,bool render,const std::shared_ptr<AVBuffer> & outBuffer,int64_t renderTime)637 Status DecoderSurfaceFilter::ReleaseOutputBuffer(int index, bool render, const std::shared_ptr<AVBuffer> &outBuffer,
638 int64_t renderTime)
639 {
640 if (!isRenderStarted_.load() && render && !(outBuffer->flag_ & (uint32_t)(Plugins::AVBufferFlag::EOS))
641 && !isInSeekContinous_) {
642 isRenderStarted_ = true;
643 if (eventReceiver_ != nullptr) {
644 eventReceiver_->OnEvent({"video_sink", EventType::EVENT_VIDEO_RENDERING_START, Status::OK});
645 }
646 }
647 if ((playRangeEndTime_ != PLAY_RANGE_DEFAULT_VALUE) &&
648 (outBuffer->pts_ > playRangeEndTime_ * MICROSECONDS_CONVERT_UNIT)) {
649 MEDIA_LOG_I("ReleaseBuffer for eos, SetPlayRange start: " PUBLIC_LOG_D64 ", end: " PUBLIC_LOG_D64,
650 playRangeStartTime_, playRangeEndTime_);
651 if (eventReceiver_ != nullptr) {
652 Event event {
653 .srcFilter = "VideoSink",
654 .type = EventType::EVENT_COMPLETE,
655 };
656 eventReceiver_->OnEvent(event);
657 }
658 return Status::OK;
659 }
660 if (renderTime > 0L && render) {
661 videoDecoder_->RenderOutputBufferAtTime(index, renderTime);
662 } else if (outBuffer->pts_ < 0) {
663 MEDIA_LOG_W("Avoid render video frame with pts=" PUBLIC_LOG_D64, outBuffer->pts_);
664 videoDecoder_->ReleaseOutputBuffer(index, false);
665 } else {
666 videoDecoder_->ReleaseOutputBuffer(index, render);
667 }
668 if (!isInSeekContinous_) {
669 videoSink_->SetLastPts(outBuffer->pts_);
670 }
671 if ((outBuffer->flag_ & (uint32_t)(Plugins::AVBufferFlag::EOS)) && !isInSeekContinous_) {
672 ResetSeekInfo();
673 MEDIA_LOG_I("ReleaseBuffer for eos, index: %{public}u, bufferid: %{public}" PRIu64
674 ", pts: %{public}" PRIu64", flag: %{public}u", index, outBuffer->GetUniqueId(),
675 outBuffer->pts_, outBuffer->flag_);
676 if (eventReceiver_ != nullptr) {
677 Event event {
678 .srcFilter = "VideoSink",
679 .type = EventType::EVENT_COMPLETE,
680 };
681 eventReceiver_->OnEvent(event);
682 }
683 }
684 return Status::OK;
685 }
686
DoProcessInputBuffer(int recvArg,bool dropFrame)687 Status DecoderSurfaceFilter::DoProcessInputBuffer(int recvArg, bool dropFrame)
688 {
689 videoDecoder_->AquireAvailableInputBuffer();
690 return Status::OK;
691 }
692
CalculateNextRender(uint32_t index,std::shared_ptr<AVBuffer> & outputBuffer)693 int64_t DecoderSurfaceFilter::CalculateNextRender(uint32_t index, std::shared_ptr<AVBuffer> &outputBuffer)
694 {
695 int64_t waitTime = -1;
696 MEDIA_LOG_D("DrainOutputBuffer not seeking and render. pts: " PUBLIC_LOG_D64, outputBuffer->pts_);
697 videoSink_->SetFirstPts(outputBuffer->pts_);
698 waitTime = videoSink_->DoSyncWrite(outputBuffer);
699 return waitTime;
700 }
701
702 // async filter should call this function
RenderNextOutput(uint32_t index,std::shared_ptr<AVBuffer> & outputBuffer)703 void DecoderSurfaceFilter::RenderNextOutput(uint32_t index, std::shared_ptr<AVBuffer> &outputBuffer)
704 {
705 if (isInSeekContinous_) {
706 Filter::ProcessOutputBuffer(false, 0);
707 return;
708 }
709 int64_t waitTime = CalculateNextRender(index, outputBuffer);
710 MEDIA_LOG_D("RenderNextOutput enter. pts: " PUBLIC_LOG_D64" waitTime: " PUBLIC_LOG_D64,
711 outputBuffer->pts_, waitTime);
712 Filter::ProcessOutputBuffer(waitTime >= 0, waitTime);
713 }
714
ConsumeVideoFrame(uint32_t index,bool isRender,int64_t renderTimeNs)715 void DecoderSurfaceFilter::ConsumeVideoFrame(uint32_t index, bool isRender, int64_t renderTimeNs)
716 {
717 MEDIA_LOG_D("ConsumeVideoFrame idx " PUBLIC_LOG_U32 " renderTimeNs " PUBLIC_LOG_D64, index, renderTimeNs);
718 Filter::ProcessOutputBuffer(isRender, 0, true, index, renderTimeNs);
719 }
720
DrainOutputBuffer(uint32_t index,std::shared_ptr<AVBuffer> & outputBuffer)721 void DecoderSurfaceFilter::DrainOutputBuffer(uint32_t index, std::shared_ptr<AVBuffer> &outputBuffer)
722 {
723 std::unique_lock<std::mutex> lock(mutex_);
724 FALSE_RETURN_NOLOG(!DrainSeekContinuous(index, outputBuffer));
725 FALSE_RETURN_NOLOG(!DrainSeekClosest(index, outputBuffer));
726 FALSE_RETURN_NOLOG(!DrainPreroll(index, outputBuffer));
727 if (IS_FILTER_ASYNC && outputBuffers_.empty()) {
728 RenderNextOutput(index, outputBuffer);
729 }
730 outputBuffers_.push_back(make_pair(index, outputBuffer));
731 if (!IS_FILTER_ASYNC) {
732 condBufferAvailable_.notify_one();
733 }
734 }
735
RenderLoop()736 void DecoderSurfaceFilter::RenderLoop()
737 {
738 while (true) {
739 std::pair<int, std::shared_ptr<AVBuffer>> nextTask;
740 {
741 std::unique_lock<std::mutex> lock(mutex_);
742 condBufferAvailable_.wait(lock, [this] {
743 return (!outputBuffers_.empty() && !isPaused_.load()) || isThreadExit_.load();
744 });
745 if (isThreadExit_) {
746 MEDIA_LOG_I("Exit RenderLoop read thread.");
747 break;
748 }
749 nextTask = std::move(outputBuffers_.front());
750 outputBuffers_.pop_front();
751 }
752 int64_t waitTime = CalculateNextRender(nextTask.first, nextTask.second);
753 MEDIA_LOG_D("RenderLoop enter. pts: " PUBLIC_LOG_D64" waitTime:" PUBLIC_LOG_D64,
754 nextTask.second->pts_, waitTime);
755 if (waitTime > 0) {
756 OSAL::SleepFor(waitTime / 1000); // 1000 convert to ms
757 }
758 ReleaseOutputBuffer(nextTask.first, waitTime >= 0, nextTask.second, -1);
759 }
760 }
761
DrainSeekContinuous(uint32_t index,std::shared_ptr<AVBuffer> & outputBuffer)762 bool DecoderSurfaceFilter::DrainSeekContinuous(uint32_t index, std::shared_ptr<AVBuffer> &outputBuffer)
763 {
764 FALSE_RETURN_V_NOLOG(isInSeekContinous_, false);
765 bool isEOS = outputBuffer->flag_ & (uint32_t)(Plugins::AVBufferFlag::EOS);
766 FALSE_RETURN_V_NOLOG(!isEOS, false);
767 outputBufferMap_.insert(std::make_pair(index, outputBuffer));
768 std::shared_ptr<VideoFrameReadyCallback> videoFrameReadyCallback = nullptr;
769 {
770 std::unique_lock<std::mutex> draggingLock(draggingMutex_);
771 FALSE_RETURN_V_NOLOG(videoFrameReadyCallback_ != nullptr, false);
772 MEDIA_LOG_D("[drag_debug]DrainSeekContinuous dts: " PUBLIC_LOG_D64 ", pts: " PUBLIC_LOG_D64
773 " bufferIdx: " PUBLIC_LOG_D32,
774 outputBuffer->dts_, outputBuffer->pts_, index);
775 videoFrameReadyCallback = videoFrameReadyCallback_;
776 }
777 FALSE_RETURN_V_NOLOG(videoFrameReadyCallback != nullptr, false);
778 videoFrameReadyCallback->ConsumeVideoFrame(outputBuffer, index);
779 return true;
780 }
781
DrainPreroll(uint32_t index,std::shared_ptr<AVBuffer> & outputBuffer)782 bool DecoderSurfaceFilter::DrainPreroll(uint32_t index, std::shared_ptr<AVBuffer> &outputBuffer)
783 {
784 FALSE_RETURN_V_NOLOG(inPreroll_.load(), false);
785 if (prerollDone_.load()) {
786 outputBuffers_.push_back(make_pair(index, outputBuffer));
787 return true;
788 }
789 std::lock_guard<std::mutex> lock(prerollMutex_);
790 FALSE_RETURN_V_NOLOG(inPreroll_.load() && !prerollDone_.load(), false);
791 outputBuffers_.push_back(make_pair(index, outputBuffer));
792 bool isEOS = outputBuffer->flag_ & (uint32_t)(Plugins::AVBufferFlag::EOS);
793 eosNext_.store(isEOS);
794 prerollDone_.store(true);
795 MEDIA_LOG_I("receive preroll output, pts: " PUBLIC_LOG_D64 " bufferIdx: " PUBLIC_LOG_D32,
796 outputBuffer->pts_, index);
797 prerollDoneCond_.notify_all();
798 return true;
799 }
800
DrainSeekClosest(uint32_t index,std::shared_ptr<AVBuffer> & outputBuffer)801 bool DecoderSurfaceFilter::DrainSeekClosest(uint32_t index, std::shared_ptr<AVBuffer> &outputBuffer)
802 {
803 FALSE_RETURN_V_NOLOG(isSeek_, false);
804 bool isEOS = outputBuffer->flag_ & (uint32_t)(Plugins::AVBufferFlag::EOS);
805 if (outputBuffer->pts_ < seekTimeUs_ && !isEOS) {
806 videoDecoder_->ReleaseOutputBuffer(index, false);
807 return true;
808 }
809 MEDIA_LOG_I("Seek arrive target video pts: " PUBLIC_LOG_D64, seekTimeUs_);
810 isSeek_ = false;
811 return false;
812 }
813
SetVideoSurface(sptr<Surface> videoSurface)814 Status DecoderSurfaceFilter::SetVideoSurface(sptr<Surface> videoSurface)
815 {
816 if (!videoSurface) {
817 MEDIA_LOG_W("videoSurface is null");
818 return Status::ERROR_INVALID_PARAMETER;
819 }
820 videoSurface_ = videoSurface;
821 if (videoDecoder_ != nullptr) {
822 MEDIA_LOG_I("videoDecoder_ SetOutputSurface in");
823 int32_t res = videoDecoder_->SetOutputSurface(videoSurface_);
824 if (res != OHOS::MediaAVCodec::AVCodecServiceErrCode::AVCS_ERR_OK) {
825 MEDIA_LOG_E("videoDecoder_ SetOutputSurface error, result is " PUBLIC_LOG_D32, res);
826 return Status::ERROR_UNKNOWN;
827 }
828 }
829 MEDIA_LOG_I("SetVideoSurface success");
830 return Status::OK;
831 }
832
SetSyncCenter(std::shared_ptr<MediaSyncManager> syncCenter)833 void DecoderSurfaceFilter::SetSyncCenter(std::shared_ptr<MediaSyncManager> syncCenter)
834 {
835 MEDIA_LOG_I("SetSyncCenter enter");
836 FALSE_RETURN(videoDecoder_ != nullptr);
837 videoSink_->SetSyncCenter(syncCenter);
838 }
839
SetDecryptConfig(const sptr<DrmStandard::IMediaKeySessionService> & keySessionProxy,bool svp)840 Status DecoderSurfaceFilter::SetDecryptConfig(const sptr<DrmStandard::IMediaKeySessionService> &keySessionProxy,
841 bool svp)
842 {
843 MEDIA_LOG_I("SetDecryptConfig enter.");
844 if (keySessionProxy == nullptr) {
845 MEDIA_LOG_E("SetDecryptConfig keySessionProxy is nullptr.");
846 return Status::ERROR_INVALID_PARAMETER;
847 }
848 isDrmProtected_ = true;
849 keySessionServiceProxy_ = keySessionProxy;
850 svpFlag_ = svp;
851 return Status::OK;
852 }
853
SetSeekTime(int64_t seekTimeUs)854 void DecoderSurfaceFilter::SetSeekTime(int64_t seekTimeUs)
855 {
856 MEDIA_LOG_I("SetSeekTime enter.");
857 isSeek_ = true;
858 seekTimeUs_ = seekTimeUs;
859 }
860
ResetSeekInfo()861 void DecoderSurfaceFilter::ResetSeekInfo()
862 {
863 MEDIA_LOG_I("ResetSeekInfo enter.");
864 isSeek_ = false;
865 seekTimeUs_ = 0;
866 }
867
ParseDecodeRateLimit()868 void DecoderSurfaceFilter::ParseDecodeRateLimit()
869 {
870 MEDIA_LOG_I("ParseDecodeRateLimit entered.");
871 std::shared_ptr<MediaAVCodec::AVCodecList> codecList = MediaAVCodec::AVCodecListFactory::CreateAVCodecList();
872 if (codecList == nullptr) {
873 MEDIA_LOG_E("create avcodeclist failed.");
874 return;
875 }
876 int32_t height = 0;
877 bool ret = meta_->GetData(Tag::VIDEO_HEIGHT, height);
878 FALSE_RETURN_MSG(ret || height <= 0, "failed to get video height");
879 int32_t width = 0;
880 ret = meta_->GetData(Tag::VIDEO_WIDTH, width);
881 FALSE_RETURN_MSG(ret || width <= 0, "failed to get video width");
882
883 MediaAVCodec::CapabilityData *capabilityData = codecList->GetCapability(codecMimeType_, false,
884 MediaAVCodec::AVCodecCategory::AVCODEC_NONE);
885 std::shared_ptr<MediaAVCodec::VideoCaps> videoCap = std::make_shared<MediaAVCodec::VideoCaps>(capabilityData);
886 FALSE_RETURN_MSG(videoCap != nullptr, "failed to get videoCap instance");
887 const MediaAVCodec::Range &frameRange = videoCap->GetSupportedFrameRatesFor(width, height);
888 rateUpperLimit_ = frameRange.maxVal;
889 if (rateUpperLimit_ > 0) {
890 meta_->SetData(Tag::VIDEO_DECODER_RATE_UPPER_LIMIT, rateUpperLimit_);
891 }
892 }
893
GetDecRateUpperLimit()894 int32_t DecoderSurfaceFilter::GetDecRateUpperLimit()
895 {
896 return rateUpperLimit_;
897 }
898
SetBitrateStart()899 void DecoderSurfaceFilter::SetBitrateStart()
900 {
901 bitrateChange_++;
902 }
903
OnOutputFormatChanged(const MediaAVCodec::Format & format)904 void DecoderSurfaceFilter::OnOutputFormatChanged(const MediaAVCodec::Format &format)
905 {
906 AutoLock lock(formatChangeMutex_);
907 int32_t width = 0;
908 format.GetIntValue("video_picture_width", width);
909 int32_t height = 0;
910 format.GetIntValue("video_picture_height", height);
911 MEDIA_LOG_I("OnOutputFormatChanged curW=" PUBLIC_LOG_D32 " curH=" PUBLIC_LOG_D32 " nextW=" PUBLIC_LOG_D32
912 " nextH=" PUBLIC_LOG_D32, surfaceWidth_, surfaceHeight_, width, height);
913 if (width <= 0 || height <= 0) {
914 MEDIA_LOG_W("invaild video size");
915 return;
916 }
917 if (surfaceWidth_ == 0 || surfaceWidth_ == 0) {
918 MEDIA_LOG_I("receive first output Format");
919 surfaceWidth_ = width;
920 surfaceHeight_ = height;
921 return;
922 }
923 if (surfaceWidth_ == width && surfaceHeight_ == height) {
924 MEDIA_LOG_W("receive the same output Format");
925 return;
926 }
927 surfaceWidth_ = width;
928 surfaceHeight_ = height;
929
930 MEDIA_LOG_I("ReportVideoSizeChange videoWidth: " PUBLIC_LOG_D32 " videoHeight: "
931 PUBLIC_LOG_D32, surfaceWidth_, surfaceHeight_);
932 std::pair<int32_t, int32_t> videoSize {surfaceWidth_, surfaceHeight_};
933 eventReceiver_->OnEvent({"DecoderSurfaceFilter", EventType::EVENT_RESOLUTION_CHANGE, videoSize});
934 }
935
OnDumpInfo(int32_t fd)936 void DecoderSurfaceFilter::OnDumpInfo(int32_t fd)
937 {
938 MEDIA_LOG_D("DecoderSurfaceFilter::OnDumpInfo called.");
939 if (videoDecoder_ != nullptr) {
940 videoDecoder_->OnDumpInfo(fd);
941 }
942 }
943
RegisterVideoFrameReadyCallback(std::shared_ptr<VideoFrameReadyCallback> & callback)944 void DecoderSurfaceFilter::RegisterVideoFrameReadyCallback(std::shared_ptr<VideoFrameReadyCallback> &callback)
945 {
946 std::unique_lock<std::mutex> draggingLock(draggingMutex_);
947 isInSeekContinous_ = true;
948 if (callback != nullptr) {
949 videoFrameReadyCallback_ = callback;
950 }
951 }
952
DeregisterVideoFrameReadyCallback()953 void DecoderSurfaceFilter::DeregisterVideoFrameReadyCallback()
954 {
955 std::unique_lock<std::mutex> draggingLock(draggingMutex_);
956 isInSeekContinous_ = false;
957 videoFrameReadyCallback_ = nullptr;
958 }
959
StartSeekContinous()960 Status DecoderSurfaceFilter::StartSeekContinous()
961 {
962 isInSeekContinous_ = true;
963 return Status::OK;
964 }
965
StopSeekContinous()966 Status DecoderSurfaceFilter::StopSeekContinous()
967 {
968 isInSeekContinous_ = false;
969 return Status::OK;
970 }
971 } // namespace Pipeline
972 } // namespace MEDIA
973 } // namespace OHOS
974