Shaka Player Embedded
video_renderer_common.cc
Go to the documentation of this file.
1 // Copyright 2019 Google LLC
2 //
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 // https://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 
16 
17 #include <algorithm>
18 
19 namespace shaka {
20 namespace media {
21 
22 namespace {
23 
25 constexpr const double kMinVideoDelay = 1.0 / 120;
26 
28 constexpr const double kMaxVideoDelay = 1.0 / 15;
29 
30 } // namespace
31 
33  : mutex_("VideoRendererCommon"),
34  player_(nullptr),
35  input_(nullptr),
36  quality_(),
37  fill_mode_(VideoFillMode::MaintainRatio),
38  prev_time_(-1) {}
39 
41  if (player_)
42  player_->RemoveClient(this);
43 }
44 
46  return fill_mode_.load(std::memory_order_relaxed);
47 }
48 
50  std::shared_ptr<DecodedFrame>* frame) {
51  std::unique_lock<Mutex> lock(mutex_);
52 
53  if (!player_ || !input_ ||
55  // If we are seeking, don't draw anything. If the caller doesn't clear
56  // the display, we will still show the frame before the seek.
57  return kMinVideoDelay;
58  }
59 
60  const double time = player_->CurrentTime();
61  auto ideal_frame = input_->GetFrame(time, FrameLocation::Near);
62  if (!ideal_frame)
63  return kMinVideoDelay;
64 
65  // TODO: Consider changing effective playback rate to speed up video when
66  // behind. This makes playback smoother at the cost of being more
67  // complicated and sacrificing AV sync.
68 
69  *frame = ideal_frame;
70 
71  auto next_frame = input_->GetFrame(ideal_frame->pts, FrameLocation::After);
72  const double total_delay = next_frame ? next_frame->pts - time : 0;
73  const double delay =
74  std::max(std::min(total_delay, kMaxVideoDelay), kMinVideoDelay);
75 
76  if (prev_time_ >= 0) {
77  const size_t count =
78  input_->CountFramesBetween(prev_time_, ideal_frame->pts);
79  quality_.dropped_video_frames += count;
80  quality_.total_video_frames += count;
81  if (ideal_frame->pts != prev_time_)
82  quality_.total_video_frames++;
83  } else {
84  quality_.total_video_frames++;
85  }
86  prev_time_ = ideal_frame->pts;
87 
88  return delay;
89 }
90 
91 void VideoRendererCommon::OnSeeking() {
92  std::unique_lock<Mutex> lock(mutex_);
93  prev_time_ = -1;
94 }
95 
97  std::unique_lock<Mutex> lock(mutex_);
98  if (player_)
99  player_->RemoveClient(this);
100 
101  player_ = player;
102  if (player)
103  player->AddClient(this);
104 }
105 
107  std::unique_lock<Mutex> lock(mutex_);
108  input_ = stream;
109 }
110 
112  std::unique_lock<Mutex> lock(mutex_);
113  input_ = nullptr;
114 }
115 
117  std::unique_lock<Mutex> lock(mutex_);
118  return quality_;
119 }
120 
122  fill_mode_.store(mode, std::memory_order_relaxed);
123  return true;
124 }
125 
126 } // namespace media
127 } // namespace shaka
virtual VideoPlaybackState PlaybackState() const =0
virtual void AddClient(Client *client) const =0
VideoFillMode
Definition: utils.h:41
std::shared_ptr< shaka::media::DecodedFrame > frame
double GetCurrentFrame(std::shared_ptr< DecodedFrame > *frame)
virtual void RemoveClient(Client *client) const =0
struct VideoPlaybackQuality VideoPlaybackQuality() const override
void SetPlayer(const MediaPlayer *player) override
virtual double CurrentTime() const =0
void Attach(const DecodedStream *stream) override
bool SetVideoFillMode(VideoFillMode mode) override
std::shared_ptr< T > GetFrame(double time, FrameLocation kind=FrameLocation::After) const
Definition: streams.h:192
size_t CountFramesBetween(double start, double end) const
Definition: streams.cc:237