• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 * Copyright (c) 2023-2025 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 #include "video_sink.h"
17 
18 #include <algorithm>
19 
20 #include "common/log.h"
21 #include "media_sync_manager.h"
22 #include "osal/task/jobutils.h"
23 #include "syspara/parameters.h"
24 
25 namespace {
26 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_DOMAIN_SYSTEM_PLAYER, "VideoSink" };
27 constexpr int64_t LAG_LIMIT_TIME = 100;
28 constexpr int32_t DROP_FRAME_CONTINUOUSLY_MAX_CNT = 2;
29 constexpr int32_t MAX_ADVANCE_US = 80000;
30 }
31 
32 namespace OHOS {
33 namespace Media {
34 namespace Pipeline {
GetvideoLatencyFixDelay()35 int64_t GetvideoLatencyFixDelay()
36 {
37     constexpr uint64_t defaultValue = 0;
38     static uint64_t fixDelay = OHOS::system::GetUintParameter("debug.media_service.video_sync_fix_delay", defaultValue);
39     MEDIA_LOG_I_SHORT("video_sync_fix_delay, pid:%{public}d, fixdelay: " PUBLIC_LOG_U64, getprocpid(), fixDelay);
40     return (int64_t)fixDelay;
41 }
42 
43 /// Video Key Frame Flag
44 constexpr int BUFFER_FLAG_KEY_FRAME = 0x00000002;
45 
46 constexpr int64_t WAIT_TIME_US_THRESHOLD = 1500000; // max sleep time 1.5s
47 
48 constexpr int64_t SINK_TIME_US_THRESHOLD = 100000; // max sink time 100ms
49 
50 constexpr int64_t PER_SINK_TIME_THRESHOLD_MAX = 33000; // max per sink time 33ms(30Hz)
51 
52 constexpr int64_t PER_SINK_TIME_THRESHOLD_MIN = 8333; // min per sink time 8.33ms(120Hz)
53 
54 // Video Sync Start Frame
55 constexpr int VIDEO_SINK_START_FRAME = 4;
56 
57 constexpr int64_t WAIT_TIME_US_THRESHOLD_WARNING = 40000; // warning threshold 40ms
58 
59 constexpr int64_t WAIT_TIME_US_THRESHOLD_RENDER = 70000; // warning threshold render 70ms
60 
61 constexpr int64_t DELTA_TIME_THRESHOLD = 5000; // max delta time 5ms
62 
63 constexpr int64_t US_PER_SECOND = 1000000; // 1000 * 1000 us per second
64 
VideoSink()65 VideoSink::VideoSink()
66 {
67     refreshTime_ = 0;
68     syncerPriority_ = IMediaSynchronizer::VIDEO_SINK;
69     fixDelay_ = GetvideoLatencyFixDelay();
70     enableRenderAtTime_ = system::GetParameter("debug.media_service.enable_renderattime", "1") == "1";
71     renderAdvanceThreshold_ = static_cast<int64_t>
72         (system::GetIntParameter("debug.media_service.renderattime_advance", MAX_ADVANCE_US));
73     MEDIA_LOG_I_SHORT("VideoSink ctor called...");
74 }
75 
~VideoSink()76 VideoSink::~VideoSink()
77 {
78     MEDIA_LOG_I_SHORT("dtor");
79     this->eventReceiver_ = nullptr;
80 }
81 
UpdateTimeAnchorIfNeeded(int64_t nowCt,int64_t waitTime,const std::shared_ptr<OHOS::Media::AVBuffer> & buffer)82 void VideoSink::UpdateTimeAnchorIfNeeded(int64_t nowCt, int64_t waitTime,
83     const std::shared_ptr<OHOS::Media::AVBuffer>& buffer)
84 {
85     auto syncCenter = syncCenter_.lock();
86     FALSE_RETURN(syncCenter != nullptr && buffer != nullptr);
87     syncCenter->SetLastVideoBufferPts(buffer->pts_ - firstPts_);
88     syncCenter->SetLastVideoBufferAbsPts(buffer->pts_);
89     if (!needUpdateTimeAnchor_) {
90         return;
91     }
92     uint64_t latency = 0;
93     (void)GetLatency(latency);
94     Pipeline::IMediaSyncCenter::IMediaTime iMediaTime = {buffer->pts_ - firstPts_, buffer->pts_, buffer->duration_};
95     syncCenter->UpdateTimeAnchor(nowCt + waitTime, latency, iMediaTime, this);
96     needUpdateTimeAnchor_ = false;
97 }
98 
UpdateTimeAnchorActually(const std::shared_ptr<OHOS::Media::AVBuffer> & buffer,int64_t renderDelay)99 void VideoSink::UpdateTimeAnchorActually(const std::shared_ptr<OHOS::Media::AVBuffer>& buffer, int64_t renderDelay)
100 {
101     auto syncCenter = syncCenter_.lock();
102     FALSE_RETURN(syncCenter != nullptr && buffer != nullptr);
103     syncCenter->SetLastVideoBufferPts(buffer->pts_ - firstPts_);
104     int64_t ct4Buffer = syncCenter->GetClockTimeNow() + (renderDelay > 0 ? renderDelay : 0);
105     uint64_t latency = 0;
106     (void)GetLatency(latency);
107     Pipeline::IMediaSyncCenter::IMediaTime iMediaTime = {buffer->pts_ - firstPts_, buffer->pts_, buffer->duration_};
108     syncCenter->UpdateTimeAnchor(ct4Buffer, latency, iMediaTime, this);
109 }
110 
DoSyncWrite(const std::shared_ptr<OHOS::Media::AVBuffer> & buffer)111 int64_t VideoSink::DoSyncWrite(const std::shared_ptr<OHOS::Media::AVBuffer>& buffer)
112 {
113     FALSE_RETURN_V(buffer != nullptr, 0);
114     int64_t waitTime = 0;
115     bool render = !isMuted_;
116     auto syncCenter = syncCenter_.lock();
117     if ((buffer->flag_ & BUFFER_FLAG_EOS) == 0) {
118         int64_t nowCt = syncCenter ? syncCenter->GetClockTimeNow() : 0;
119         if (isFirstFrame_ && !needDropOnMute_.load()) {
120             FALSE_RETURN_V(syncCenter != nullptr, false);
121             isFirstFrame_ = false;
122             firstFrameClockTime_  = nowCt;
123             firstFramePts_ = buffer->pts_;
124         } else {
125             waitTime = CheckBufferLatenessMayWait(buffer);
126         }
127         UpdateTimeAnchorIfNeeded(nowCt, waitTime, buffer);
128         lagDetector_.CalcLag(buffer);
129         ReportPts(buffer->pts_);
130         lastBufferRelativePts_ = buffer->pts_ - firstPts_;
131     } else {
132         MEDIA_LOG_I_SHORT("Video sink EOS");
133         if (syncCenter) {
134             syncCenter->ReportEos(this);
135         }
136         return -1;
137     }
138     if ((render && waitTime >= 0) || dropFrameContinuouslyCnt_.load() >= DROP_FRAME_CONTINUOUSLY_MAX_CNT) {
139         dropFrameContinuouslyCnt_.store(0);
140         needDropOnMute_.store(false);
141         renderFrameCnt_++;
142         MEDIA_LOG_D("VideoSink::DoSyncWrite waitTime is " PUBLIC_LOG_D64, waitTime);
143         return waitTime > 0 ? waitTime : 0;
144     }
145     if (!needDropOnMute_.load()) {
146         dropFrameContinuouslyCnt_.fetch_add(1);
147     }
148     discardFrameCnt_++;
149     PerfRecord(waitTime);
150     return -1;
151 }
152 
ReportPts(int64_t nowPts)153 void VideoSink::ReportPts(int64_t nowPts)
154 {
155     if (nowPts < lastPts_) {
156         MEDIA_LOG_W("video pts is not increasing, last pts: " PUBLIC_LOG_D64 ", current pts: " PUBLIC_LOG_D64,
157             lastPts_, nowPts);
158     }
159 }
160 
SetPerfRecEnabled(bool isPerfRecEnabled)161 Status VideoSink::SetPerfRecEnabled(bool isPerfRecEnabled)
162 {
163     isPerfRecEnabled_ = isPerfRecEnabled;
164     return Status::OK;
165 }
166 
PerfRecord(int64_t waitTime)167 void VideoSink::PerfRecord(int64_t waitTime)
168 {
169     FALSE_RETURN_NOLOG(isPerfRecEnabled_);
170     FALSE_RETURN_MSG(eventReceiver_ != nullptr, "Report perf failed, callback is nullptr");
171     FALSE_RETURN_NOLOG(perfRecorder_.Record(Plugins::Us2Ms(waitTime)) == PerfRecorder::FULL);
172     eventReceiver_->OnDfxEvent({ "VSINK", DfxEventType::DFX_INFO_PERF_REPORT, perfRecorder_.GetMainPerfData() });
173     perfRecorder_.Reset();
174 }
175 
ResetSyncInfo()176 void VideoSink::ResetSyncInfo()
177 {
178     ResetPrerollReported();
179     renderFrameCnt_ = 0;
180     dropFrameContinuouslyCnt_ = 0;
181     isFirstFrame_ = true;
182     lastBufferRelativePts_ = HST_TIME_NONE;
183     lastBufferAnchoredClockTime_ = HST_TIME_NONE;
184     seekFlag_ = false;
185     lastPts_ = HST_TIME_NONE;
186     lastClockTime_ = HST_TIME_NONE;
187     needUpdateTimeAnchor_ = true;
188     lagDetector_.Reset();
189     perfRecorder_.Reset();
190 }
191 
GetLatency(uint64_t & nanoSec)192 Status VideoSink::GetLatency(uint64_t& nanoSec)
193 {
194     nanoSec = 10; // 10 ns
195     return Status::OK;
196 }
197 
SetSeekFlag()198 void VideoSink::SetSeekFlag()
199 {
200     seekFlag_ = true;
201 }
202 
SetLastPts(int64_t lastPts,int64_t renderDelay)203 void VideoSink::SetLastPts(int64_t lastPts, int64_t renderDelay)
204 {
205     lastPts_ = lastPts;
206     auto syncCenter = syncCenter_.lock();
207     if (syncCenter != nullptr) {
208         lastClockTime_ = syncCenter->GetClockTimeNow() + (renderDelay > 0 ? renderDelay : 0);
209     }
210 }
211 
CalcBufferDiff(const std::shared_ptr<OHOS::Media::AVBuffer> & buffer,int64_t bufferAnchoredClockTime,int64_t currentClockTime,float playbackRate)212 int64_t VideoSink::CalcBufferDiff(const std::shared_ptr<OHOS::Media::AVBuffer>& buffer, int64_t bufferAnchoredClockTime,
213     int64_t currentClockTime, float playbackRate)
214 {
215     uint64_t latency = 0;
216     GetLatency(latency);
217     //  the diff between the current clock time and the buffer's
218     //  anchored clock time, adjusted by latency and a fixed delay
219     auto anchorDiff = currentClockTime + (int64_t) latency - bufferAnchoredClockTime + fixDelay_;
220     //  the diff between the actual duration of the previous video frame and the theoretically calculated duration
221     //  based on the PTS, considering the playback rate
222     auto videoDiff = (currentClockTime - lastClockTime_)
223         - static_cast<int64_t>((buffer->pts_ - lastPts_) / AdjustPlaybackRate(playbackRate));
224     // render time per frame reduced by initialVideoWaitPeriod_
225     auto thresholdAdjustedVideoDiff = videoDiff - initialVideoWaitPeriod_;
226 
227     auto diff = anchorDiff;
228     if (discardFrameCnt_ + renderFrameCnt_ < VIDEO_SINK_START_FRAME) {
229         float ptsDiffWithSpeed = static_cast<float>(buffer->pts_ - firstFramePts_) / AdjustPlaybackRate(playbackRate);
230         diff = (currentClockTime - firstFrameClockTime_) - static_cast<int64_t>(ptsDiffWithSpeed);
231         MEDIA_LOG_I("VideoSink first few times diff is " PUBLIC_LOG_D64 " us speed %{public}.3f", diff, playbackRate);
232     } else if (diff < 0 && videoDiff < SINK_TIME_US_THRESHOLD && diff < thresholdAdjustedVideoDiff) {
233         diff = thresholdAdjustedVideoDiff;
234     }
235     MEDIA_LOG_D("VS ct4Bf:" PUBLIC_LOG_D64 " diff:" PUBLIC_LOG_D64 " nowCt:" PUBLIC_LOG_D64,
236         bufferAnchoredClockTime, diff, currentClockTime);
237     return diff;
238 }
239 
CheckBufferLatenessMayWait(const std::shared_ptr<OHOS::Media::AVBuffer> & buffer)240 int64_t VideoSink::CheckBufferLatenessMayWait(const std::shared_ptr<OHOS::Media::AVBuffer>& buffer)
241 {
242     InitWaitPeriod();
243     auto syncCenter = syncCenter_.lock();
244     FALSE_RETURN_V(buffer != nullptr, true);
245     FALSE_RETURN_V(syncCenter != nullptr, true);
246 
247     auto relativePts = buffer->pts_ - firstPts_;
248     auto bufferAnchoredClockTime = syncCenter->GetAnchoredClockTime(relativePts);
249     MEDIA_LOG_D("VideoSink cur pts: " PUBLIC_LOG_D64 " us, bufferAnchoredClockTime: " PUBLIC_LOG_D64
250         " us, buf_pts: " PUBLIC_LOG_D64 " us, fixDelay: " PUBLIC_LOG_D64 " us", relativePts,
251         bufferAnchoredClockTime, buffer->pts_, fixDelay_);
252     FALSE_RETURN_V(bufferAnchoredClockTime != Plugins::HST_TIME_NONE, 0);
253 
254     if (lastBufferAnchoredClockTime_ != HST_TIME_NONE && seekFlag_ == false) {
255         int64_t currentBufferRelativeClockTime = lastBufferAnchoredClockTime_ + relativePts - lastBufferRelativePts_;
256         int64_t deltaTime = bufferAnchoredClockTime - currentBufferRelativeClockTime;
257         deltaTimeAccu_ = SmoothDeltaTime(deltaTimeAccu_, deltaTime);
258         if (std::abs(deltaTimeAccu_) < DELTA_TIME_THRESHOLD) {
259             bufferAnchoredClockTime = currentBufferRelativeClockTime;
260         }
261         MEDIA_LOG_D("lastBfTime:" PUBLIC_LOG_D64" us, lastPts:" PUBLIC_LOG_D64,
262             lastBufferAnchoredClockTime_, lastBufferRelativePts_);
263     } else {
264         seekFlag_ = (seekFlag_ == true) ? false : seekFlag_;
265     }
266 
267     auto diff = CalcBufferDiff(buffer, bufferAnchoredClockTime,
268         syncCenter->GetClockTimeNow(), syncCenter->GetPlaybackRate());
269 
270     bool tooLate = false;
271     int64_t waitTimeUs = 0;
272     if (diff < 0) { // buffer is early, diff < 0 or 0 < diff < 40ms(25Hz) render it
273         waitTimeUs = 0 - diff;
274         RenderAtTimeLog(waitTimeUs);
275         if (waitTimeUs > WAIT_TIME_US_THRESHOLD && !needDropOnMute_.load()) {
276             waitTimeUs = WAIT_TIME_US_THRESHOLD;
277         }
278     } else if (diff > 0 && Plugins::HstTime2Ms(diff * HST_USECOND) > 40) { // > 40ms, buffer is late
279         tooLate = true;
280         MEDIA_LOG_D_SHORT("buffer is too late");
281     }
282     lastBufferAnchoredClockTime_ = bufferAnchoredClockTime;
283     bool dropFlag = tooLate && ((buffer->flag_ & BUFFER_FLAG_KEY_FRAME) == 0); // buffer is too late, drop it
284     return dropFlag ? -1 : waitTimeUs;
285 }
286 
RenderAtTimeLog(int64_t waitTimeUs)287 void VideoSink::RenderAtTimeLog(int64_t waitTimeUs)
288 {
289     if (enableRenderAtTime_) {
290         MEDIA_LOG_I_FALSE_D((waitTimeUs >= WAIT_TIME_US_THRESHOLD_RENDER + renderAdvanceThreshold_),
291             "enableRenderAtTime is true, buffer is too early waitTimeUs: " PUBLIC_LOG_D64, waitTimeUs);
292     } else {
293         MEDIA_LOG_I_FALSE_D((waitTimeUs >= WAIT_TIME_US_THRESHOLD_WARNING),
294             "buffer is too early waitTimeUs: " PUBLIC_LOG_D64, waitTimeUs);
295     }
296 }
297 
SetSyncCenter(std::shared_ptr<Pipeline::MediaSyncManager> syncCenter)298 void VideoSink::SetSyncCenter(std::shared_ptr<Pipeline::MediaSyncManager> syncCenter)
299 {
300     MEDIA_LOG_D_SHORT("VideoSink::SetSyncCenter");
301     syncCenter_ = syncCenter;
302     MediaSynchronousSink::Init();
303 }
304 
InitWaitPeriod()305 void VideoSink::InitWaitPeriod()
306 {
307     FALSE_RETURN_NOLOG(initialVideoWaitPeriod_ <= 0);
308     initialVideoWaitPeriod_ = PER_SINK_TIME_THRESHOLD_MAX;
309     auto syncCenter = syncCenter_.lock();
310     FALSE_RETURN_NOLOG(syncCenter != nullptr);
311     double initialVideoFrameRate = syncCenter->GetInitialVideoFrameRate();
312     MEDIA_LOG_I("VideoSink initialFrameRate is " PUBLIC_LOG_D64, static_cast<int64_t>(initialVideoFrameRate));
313     FALSE_RETURN_NOLOG(initialVideoFrameRate > 1e-9); // frameRate > 0
314     initialVideoWaitPeriod_ = static_cast<int64_t>(US_PER_SECOND
315                                                    / (2 * initialVideoFrameRate)); // max delay 2 times frame interval
316     MEDIA_LOG_I("VideoSink intial initialVideoWaitPerild_ is >> " PUBLIC_LOG_D64, initialVideoWaitPeriod_);
317     initialVideoWaitPeriod_ = std::min(initialVideoWaitPeriod_, PER_SINK_TIME_THRESHOLD_MAX);
318     initialVideoWaitPeriod_ = std::max(initialVideoWaitPeriod_, PER_SINK_TIME_THRESHOLD_MIN);
319     MEDIA_LOG_I("VideoSink final initialVideoWaitPerild_ is << " PUBLIC_LOG_D64, initialVideoWaitPeriod_);
320 }
321 
SetEventReceiver(const std::shared_ptr<EventReceiver> & receiver)322 void VideoSink::SetEventReceiver(const std::shared_ptr<EventReceiver> &receiver)
323 {
324     this->eventReceiver_ = receiver;
325     lagDetector_.SetEventReceiver(receiver);
326 }
327 
SetFirstPts(int64_t pts)328 void VideoSink::SetFirstPts(int64_t pts)
329 {
330     auto syncCenter = syncCenter_.lock();
331     if (firstPts_ == HST_TIME_NONE) {
332         if (syncCenter && syncCenter->GetMediaStartPts() != HST_TIME_NONE) {
333             firstPts_ = syncCenter->GetMediaStartPts();
334         } else {
335             firstPts_ = pts;
336         }
337         MEDIA_LOG_I("video DoSyncWrite set firstPts = " PUBLIC_LOG_D64, firstPts_);
338     }
339 }
340 
SetParameter(const std::shared_ptr<Meta> & meta)341 Status VideoSink::SetParameter(const std::shared_ptr<Meta>& meta)
342 {
343     UpdateMediaTimeRange(meta);
344     return Status::OK;
345 }
346 
AdjustPlaybackRate(float playbackRate)347 float VideoSink::AdjustPlaybackRate(float playbackRate)
348 {
349     static constexpr float MIN_PLAYBACK_RATE = 1e-9;
350     if (std::fabs(playbackRate) < MIN_PLAYBACK_RATE) {
351         return 1.0f;
352     }
353     return playbackRate;
354 }
355 
SmoothDeltaTime(int64_t accumulatedDeltaTime,int64_t currentDeltaTime)356 int64_t VideoSink::SmoothDeltaTime(int64_t accumulatedDeltaTime, int64_t currentDeltaTime)
357 {
358     static constexpr int64_t SMOOTHING_FACTOR = 9;
359     return (accumulatedDeltaTime * SMOOTHING_FACTOR + currentDeltaTime) / (SMOOTHING_FACTOR + 1);
360 }
361 
GetLagInfo(int32_t & lagTimes,int32_t & maxLagDuration,int32_t & avgLagDuration)362 Status VideoSink::GetLagInfo(int32_t& lagTimes, int32_t& maxLagDuration, int32_t& avgLagDuration)
363 {
364     lagDetector_.GetLagInfo(lagTimes, maxLagDuration, avgLagDuration);
365     return Status::OK;
366 }
367 
CalcLag(std::shared_ptr<AVBuffer> buffer)368 bool VideoSink::VideoLagDetector::CalcLag(std::shared_ptr<AVBuffer> buffer)
369 {
370     FALSE_RETURN_V(!(buffer->flag_ & (uint32_t)(Plugins::AVBufferFlag::EOS)), false);
371     auto systemTimeMsNow = Plugins::GetCurrentMillisecond();
372     auto systemTimeMsDiff = systemTimeMsNow - lastSystemTimeMs_;
373     auto bufferTimeUsNow = Plugins::Us2Ms(buffer->pts_);
374     auto bufferTimeMsDiff = bufferTimeUsNow - lastBufferTimeMs_;
375     auto lagTimeMs = systemTimeMsDiff - bufferTimeMsDiff;
376     bool isVideoLag = lastSystemTimeMs_ > 0 && lagTimeMs >= LAG_LIMIT_TIME;
377     MEDIA_LOG_I_FALSE_D(isVideoLag,
378         "prePts " PUBLIC_LOG_D64 " curPts " PUBLIC_LOG_D64 " ptsDiff " PUBLIC_LOG_D64 " tDiff " PUBLIC_LOG_D64,
379         lastBufferTimeMs_, bufferTimeUsNow, bufferTimeMsDiff, systemTimeMsDiff);
380     lastSystemTimeMs_ = systemTimeMsNow;
381     lastBufferTimeMs_ = bufferTimeUsNow;
382     if (isVideoLag) {
383         ResolveLagEvent(lagTimeMs);
384     }
385     return isVideoLag;
386 }
387 
SetEventReceiver(const std::shared_ptr<EventReceiver> eventReceiver)388 void VideoSink::VideoLagDetector::SetEventReceiver(const std::shared_ptr<EventReceiver> eventReceiver)
389 {
390     eventReceiver_ = eventReceiver;
391 }
392 
ResolveLagEvent(const int64_t & lagTimeMs)393 void VideoSink::VideoLagDetector::ResolveLagEvent(const int64_t &lagTimeMs)
394 {
395     lagTimes_++;
396     maxLagDuration_ = std::max(maxLagDuration_, lagTimeMs);
397     totalLagDuration_ += lagTimeMs;
398     FALSE_RETURN(eventReceiver_ != nullptr);
399     eventReceiver_->OnDfxEvent({"VideoSink", DfxEventType::DFX_INFO_PLAYER_VIDEO_LAG, lagTimeMs});
400 }
401 
GetLagInfo(int32_t & lagTimes,int32_t & maxLagDuration,int32_t & avgLagDuration)402 void VideoSink::VideoLagDetector::GetLagInfo(int32_t& lagTimes, int32_t& maxLagDuration, int32_t& avgLagDuration)
403 {
404     lagTimes = lagTimes_;
405     maxLagDuration = static_cast<int32_t>(maxLagDuration_);
406     if (lagTimes_ != 0) {
407         avgLagDuration = static_cast<int32_t>(totalLagDuration_ / lagTimes_);
408     } else {
409         avgLagDuration = 0;
410     }
411 }
412 
Reset()413 void VideoSink::VideoLagDetector::Reset()
414 {
415     lagTimes_ = 0;
416     maxLagDuration_ = 0;
417     lastSystemTimeMs_ = 0;
418     lastBufferTimeMs_ = 0;
419     totalLagDuration_ = 0;
420 }
421 
SetMediaMuted(bool isMuted)422 void VideoSink::SetMediaMuted(bool isMuted)
423 {
424     if (isMuted) {
425         needDropOnMute_.store(true);
426         dropFrameContinuouslyCnt_.store(0);
427         if (discardFrameCnt_ < VIDEO_SINK_START_FRAME) {
428             discardFrameCnt_ = VIDEO_SINK_START_FRAME;
429         }
430     }
431     isMuted_ = isMuted;
432 }
433 } // namespace Pipeline
434 } // namespace MEDIA
435 } // namespace OHOS
436