Shaka Player Embedded
mse_media_player.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 #include <cmath>
19 #include <functional>
20 #include <thread>
21 
22 #include "src/media/media_utils.h"
23 #include "src/util/clock.h"
24 #include "src/util/utils.h"
25 
26 namespace shaka {
27 namespace media {
28 
30  VideoRenderer* video_renderer,
31  AudioRenderer* audio_renderer)
32  : mutex_("MseMediaPlayer"),
33  pipeline_manager_(std::bind(&MseMediaPlayer::OnStatusChanged, this,
34  std::placeholders::_1),
35  std::bind(&MseMediaPlayer::OnSeek, this),
36  &util::Clock::Instance),
37  pipeline_monitor_(std::bind(&MseMediaPlayer::GetBuffered, this),
38  std::bind(&MseMediaPlayer::GetDecoded, this),
39  std::bind(&MseMediaPlayer::ReadyStateChanged, this,
40  std::placeholders::_1),
41  &util::Clock::Instance, &pipeline_manager_),
42  old_state_(VideoPlaybackState::Initializing),
43  ready_state_(VideoReadyState::NotAttached),
44  video_(this),
45  audio_(this),
46  video_renderer_(video_renderer),
47  audio_renderer_(audio_renderer),
48  clients_(clients) {
49  video_renderer_->SetPlayer(this);
50  audio_renderer_->SetPlayer(this);
51 
52 #if 0
53  std::thread t([=]() {
54  auto printr = [](const char* prefix,
55  const std::vector<BufferedRange>& ranges) {
56  printf("%s", prefix);
57  for (auto& range : ranges)
58  printf("%.1f-%.1f ", range.start, range.end);
59  printf("\n");
60  };
61  auto print_stream = [&printr](const char* name, Source* stream) {
62  printf(" %s:\n", name);
63  printr(" Buffered: ", stream->GetBuffered());
64  printr(" Decoded: ",
65  stream->GetDecodedStream()->GetBufferedRanges());
66  };
67 
68  while (true) {
70 
71  printf("Playback State: %s\n", to_string(PlaybackState()).c_str());
72  printf(" Current time: %.1f\n", CurrentTime());
73  printf(" Duration: %.1f\n", Duration());
74  printf(" Playback rate: %.1f\n", PlaybackRate());
75  printr(" Total Buffered: ", GetBuffered());
76 
77  util::shared_lock<SharedMutex> lock(mutex_);
78  print_stream("Audio", &audio_);
79  print_stream("Video", &video_);
80  }
81  });
82  t.detach();
83 #endif
84 }
85 
87  video_renderer_->SetPlayer(nullptr);
88  audio_renderer_->SetPlayer(nullptr);
89 }
90 
92  Decoder* audio_decoder) {
93  std::unique_lock<SharedMutex> lock(mutex_);
94  video_.SetDecoder(video_decoder);
95  audio_.SetDecoder(audio_decoder);
96 }
97 
99  const MediaDecodingConfiguration& config) const {
100  if (config.type != MediaDecodingType::MediaSource ||
101  (config.video.content_type.empty() &&
102  config.audio.content_type.empty())) {
103  return MediaCapabilitiesInfo();
104  }
105 
106  util::shared_lock<SharedMutex> lock(mutex_);
108  ret.supported = ret.power_efficient = ret.smooth = true;
109  if (!config.video.content_type.empty()) {
110  auto* decoder = video_.GetDecoder();
111  if (!decoder)
112  return MediaCapabilitiesInfo();
113 
114  auto new_config = config;
115  new_config.audio.content_type = "";
116  ret = ret & decoder->DecodingInfo(new_config);
117  }
118  if (!config.audio.content_type.empty()) {
119  auto* decoder = audio_.GetDecoder();
120  if (!decoder)
121  return MediaCapabilitiesInfo();
122 
123  auto new_config = config;
124  new_config.video.content_type = "";
125  ret = ret & decoder->DecodingInfo(new_config);
126  }
127 
128  return ret;
129 }
130 
132  return video_renderer_->VideoPlaybackQuality();
133 }
134 
136  clients_->AddClient(client);
137 }
138 
140  clients_->RemoveClient(client);
141 }
142 
143 std::vector<BufferedRange> MseMediaPlayer::GetBuffered() const {
144  util::shared_lock<SharedMutex> lock(mutex_);
145  std::vector<std::vector<BufferedRange>> ranges;
146  for (auto* ptr : {&video_, &audio_}) {
147  if (ptr->IsAttached())
148  ranges.emplace_back(ptr->GetBuffered());
149  }
150  return IntersectionOfBufferedRanges(ranges);
151 }
152 
154  util::shared_lock<SharedMutex> lock(mutex_);
155  return ready_state_;
156 }
157 
159  return pipeline_manager_.GetPlaybackState();
160 }
161 
162 std::vector<std::shared_ptr<MediaTrack>> MseMediaPlayer::AudioTracks() {
163  // Track usage should be done through DefaultMediaPlayer.
164  LOG(FATAL) << "Not implemented";
165 }
166 
167 std::vector<std::shared_ptr<const MediaTrack>> MseMediaPlayer::AudioTracks()
168  const {
169  // Track usage should be done through DefaultMediaPlayer.
170  LOG(FATAL) << "Not implemented";
171 }
172 
173 std::vector<std::shared_ptr<MediaTrack>> MseMediaPlayer::VideoTracks() {
174  // Track usage should be done through DefaultMediaPlayer.
175  LOG(FATAL) << "Not implemented";
176 }
177 
178 std::vector<std::shared_ptr<const MediaTrack>> MseMediaPlayer::VideoTracks()
179  const {
180  // Track usage should be done through DefaultMediaPlayer.
181  LOG(FATAL) << "Not implemented";
182 }
183 
184 std::vector<std::shared_ptr<TextTrack>> MseMediaPlayer::TextTracks() {
185  // Track usage should be done through DefaultMediaPlayer.
186  LOG(FATAL) << "Not implemented";
187 }
188 
189 std::vector<std::shared_ptr<const TextTrack>> MseMediaPlayer::TextTracks()
190  const {
191  // Track usage should be done through DefaultMediaPlayer.
192  LOG(FATAL) << "Not implemented";
193 }
194 
195 std::shared_ptr<TextTrack> MseMediaPlayer::AddTextTrack(
196  TextTrackKind kind, const std::string& label, const std::string& language) {
197  // Track usage should be done through DefaultMediaPlayer.
198  LOG(FATAL) << "Not implemented";
199 }
200 
201 
203  return video_renderer_->SetVideoFillMode(mode);
204 }
205 
206 uint32_t MseMediaPlayer::Height() const {
207  double time = pipeline_manager_.GetCurrentTime();
208 
209  util::shared_lock<SharedMutex> lock(mutex_);
210  auto frame = video_.GetFrame(time);
211  return frame ? frame->stream_info->height : 0;
212 }
213 
214 uint32_t MseMediaPlayer::Width() const {
215  double time = pipeline_manager_.GetCurrentTime();
216 
217  util::shared_lock<SharedMutex> lock(mutex_);
218  auto frame = video_.GetFrame(time);
219  return frame ? frame->stream_info->width : 0;
220 }
221 
222 double MseMediaPlayer::Volume() const {
223  return audio_renderer_->Volume();
224 }
225 
226 void MseMediaPlayer::SetVolume(double volume) {
227  audio_renderer_->SetVolume(volume);
228 }
229 
230 bool MseMediaPlayer::Muted() const {
231  return audio_renderer_->Muted();
232 }
233 
234 void MseMediaPlayer::SetMuted(bool muted) {
235  audio_renderer_->SetMuted(muted);
236 }
237 
239  pipeline_manager_.Play();
240 }
241 
243  pipeline_manager_.Pause();
244 }
245 
247  return pipeline_manager_.GetCurrentTime();
248 }
249 
251  pipeline_manager_.SetCurrentTime(time);
252 }
253 
254 double MseMediaPlayer::Duration() const {
255  return pipeline_manager_.GetDuration();
256 }
257 
258 void MseMediaPlayer::SetDuration(double duration) {
259  pipeline_manager_.SetDuration(duration);
260 }
261 
263  return pipeline_manager_.GetPlaybackRate();
264 }
265 
267  const double old_rate = pipeline_manager_.GetPlaybackRate();
268  pipeline_manager_.SetPlaybackRate(rate);
269  clients_->OnPlaybackRateChanged(old_rate, rate);
270 }
271 
272 
273 bool MseMediaPlayer::AttachSource(const std::string& src) {
274  return false;
275 }
276 
278  {
279  std::unique_lock<SharedMutex> lock(mutex_);
281  ready_state_ = VideoReadyState::HaveNothing;
282  }
283 
284  pipeline_manager_.Reset();
285  pipeline_monitor_.Start();
286  clients_->OnAttachMse();
287  return true;
288 }
289 
290 bool MseMediaPlayer::AddMseBuffer(const std::string& mime, bool is_video,
291  const ElementaryStream* stream) {
292  {
293  std::unique_lock<SharedMutex> lock(mutex_);
294  if (is_video)
295  video_.Attach(stream);
296  else
297  audio_.Attach(stream);
298  }
299 
300  // Avoid holding the lock for interacting with the Renderers.
301  if (is_video)
302  video_renderer_->Attach(video_.GetDecodedStream());
303  else
304  audio_renderer_->Attach(audio_.GetDecodedStream());
305  return true;
306 }
307 
308 void MseMediaPlayer::LoadedMetaData(double duration) {
309  if (std::isfinite(duration) && !std::isfinite(Duration()))
310  SetDuration(duration);
311  pipeline_manager_.DoneInitializing();
312 }
313 
315  double duration = 0;
316  {
317  util::shared_lock<SharedMutex> lock(mutex_);
318  // Use the maximum duration of any stream as the total media duration.
319  // See: https://w3c.github.io/media-source/#end-of-stream-algorithm
320  for (auto* ptr : {&video_, &audio_}) {
321  if (ptr->IsAttached()) {
322  auto buffered = ptr->GetBuffered();
323  if (!buffered.empty())
324  duration = std::max(duration, buffered.back().end);
325  }
326  }
327  }
328  pipeline_manager_.SetDuration(duration);
329 }
330 
331 bool MseMediaPlayer::SetEmeImplementation(const std::string& /* key_system */,
332  eme::Implementation* implementation) {
333  std::unique_lock<SharedMutex> lock(mutex_);
334  video_.SetCdm(implementation);
335  audio_.SetCdm(implementation);
336  return true;
337 }
338 
340  // Avoid holding the lock for interacting with the Renderers.
341  audio_renderer_->Detach();
342  video_renderer_->Detach();
343  pipeline_monitor_.Stop();
344 
345  {
346  std::unique_lock<SharedMutex> lock(mutex_);
347  video_.Detach();
348  audio_.Detach();
349  ready_state_ = VideoReadyState::NotAttached;
350  }
351 
352  clients_->OnDetach();
353 }
354 
355 void MseMediaPlayer::OnStatusChanged(VideoPlaybackState state) {
356  VideoPlaybackState old_state;
357  {
358  std::unique_lock<SharedMutex> lock(mutex_);
359  old_state = old_state_;
360  old_state_ = state;
361  }
362 
363  if (state == old_state)
364  return;
365 
366  clients_->OnPlaybackStateChanged(old_state, state);
367  switch (state) {
370  if (old_state == VideoPlaybackState::Paused)
371  clients_->OnPlay();
372  break;
373 
375  // Don't raise for seeking since we get a call to OnSeek.
382  break;
383  }
384 }
385 
386 void MseMediaPlayer::ReadyStateChanged(VideoReadyState state) {
387  VideoReadyState old;
388  {
389  std::unique_lock<SharedMutex> lock(mutex_);
390  old = ready_state_;
391  ready_state_ = state;
392  }
393 
394  clients_->OnReadyStateChanged(old, state);
395 }
396 
397 void MseMediaPlayer::OnSeek() {
398  // Avoid holding the lock for interacting with the Renderers.
399  clients_->OnSeeking();
400 
401  std::unique_lock<SharedMutex> lock(mutex_);
402  video_.OnSeek();
403  audio_.OnSeek();
404 }
405 
406 void MseMediaPlayer::OnError(const std::string& error) {
407  pipeline_manager_.OnError();
408  clients_->OnError(error);
409 }
410 
411 void MseMediaPlayer::OnWaitingForKey() {
412  clients_->OnWaitingForKey();
413 }
414 
415 std::vector<BufferedRange> MseMediaPlayer::GetDecoded() const {
416  util::shared_lock<SharedMutex> lock(mutex_);
417  std::vector<std::vector<BufferedRange>> ranges;
418  for (auto* ptr : {&video_, &audio_}) {
419  if (ptr->IsAttached())
420  ranges.emplace_back(ptr->GetDecodedStream()->GetBufferedRanges());
421  }
422  return IntersectionOfBufferedRanges(ranges);
423 }
424 
425 
426 MseMediaPlayer::Source::Source(MseMediaPlayer* player)
427  : default_decoder_(Decoder::CreateDefaultDecoder()),
428  decoder_thread_(player, &decoded_frames_),
429  input_(nullptr),
430  decoder_(nullptr) {
431  decoder_thread_.SetDecoder(GetDecoder());
432 }
433 
434 MseMediaPlayer::Source::~Source() {}
435 
436 const DecodedStream* MseMediaPlayer::Source::GetDecodedStream() const {
437  return &decoded_frames_;
438 }
439 
440 Decoder* MseMediaPlayer::Source::GetDecoder() const {
441  return decoder_ ? decoder_ : default_decoder_.get();
442 }
443 
444 void MseMediaPlayer::Source::SetDecoder(Decoder* decoder) {
445  decoder_ = decoder;
446  decoder_thread_.SetDecoder(GetDecoder());
447 }
448 
449 std::vector<BufferedRange> MseMediaPlayer::Source::GetBuffered() const {
450  return input_ ? input_->GetBufferedRanges() : std::vector<BufferedRange>{};
451 }
452 
453 std::shared_ptr<DecodedFrame> MseMediaPlayer::Source::GetFrame(
454  double time) const {
455  return decoded_frames_.GetFrame(time, FrameLocation::Near);
456 }
457 
458 bool MseMediaPlayer::Source::IsAttached() const {
459  return input_;
460 }
461 
462 void MseMediaPlayer::Source::Attach(const ElementaryStream* stream) {
463  DCHECK(!IsAttached());
464  decoded_frames_.Clear();
465  decoder_thread_.Attach(stream);
466  input_ = stream;
467 }
468 
469 void MseMediaPlayer::Source::Detach() {
470  decoder_thread_.Detach();
471  input_ = nullptr;
472 }
473 
474 void MseMediaPlayer::Source::OnSeek() {
475  decoder_thread_.OnSeek();
476 }
477 
478 void MseMediaPlayer::Source::SetCdm(eme::Implementation* cdm) {
479  decoder_thread_.SetCdm(cdm);
480 }
481 
482 } // namespace media
483 } // namespace shaka
bool AttachSource(const std::string &src) override
std::vector< std::shared_ptr< MediaTrack > > VideoTracks() override
virtual VideoPlaybackState GetPlaybackState() const
void SetVolume(double volume) override
std::shared_ptr< TextTrack > AddTextTrack(TextTrackKind kind, const std::string &label, const std::string &language) override
MediaCapabilitiesInfo DecodingInfo(const MediaDecodingConfiguration &config) const override
std::vector< std::shared_ptr< TextTrack > > TextTracks() override
virtual void Detach()=0
static std::unique_ptr< Decoder > CreateDefaultDecoder()
Definition: decoder.cc:31
VideoFillMode
Definition: utils.h:41
MseMediaPlayer(ClientList *clients, VideoRenderer *video_renderer, AudioRenderer *audio_renderer)
std::shared_ptr< shaka::media::DecodedFrame > frame
const char * name
void OnPlaybackRateChanged(double old_rate, double new_rate) override
void OnReadyStateChanged(VideoReadyState old_state, VideoReadyState new_state) override
VideoPlaybackState PlaybackState() const override
virtual VideoPlaybackQuality VideoPlaybackQuality() const =0
virtual void SetPlayer(const MediaPlayer *player)=0
VideoReadyState ReadyState() const override
std::string to_string(VideoReadyState state)
Definition: media_player.cc:32
uint32_t Width() const override
bool SetEmeImplementation(const std::string &key_system, eme::Implementation *implementation) override
double PlaybackRate() const override
virtual double Volume() const =0
bool AddMseBuffer(const std::string &mime, bool is_video, const ElementaryStream *stream) override
std::vector< BufferedRange > GetBuffered() const override
virtual void SetCurrentTime(double time)
virtual double GetCurrentTime() const
double CurrentTime() const override
void OnError(const std::string &error) override
virtual bool Muted() const =0
virtual void SetDuration(double duration)
std::vector< std::shared_ptr< MediaTrack > > AudioTracks() override
virtual void SetPlaybackRate(double rate)
virtual void SetVolume(double volume)=0
void SetPlaybackRate(double rate) override
virtual double GetPlaybackRate() const
double Volume() const override
void SetCurrentTime(double time) override
void SetDecoders(Decoder *video_decoder, Decoder *audio_decoder)
bool SetVideoFillMode(VideoFillMode mode) override
virtual void SetMuted(bool muted)=0
static const Clock Instance
Definition: clock.h:29
virtual void SleepSeconds(double seconds) const
Definition: clock.cc:39
struct VideoPlaybackQuality VideoPlaybackQuality() const override
void AddClient(MediaPlayer::Client *client) const override
BufferedRanges IntersectionOfBufferedRanges(const std::vector< BufferedRanges > &sources)
Definition: media_utils.cc:144
virtual double GetDuration() const
void SetDuration(double duration) override
uint32_t Height() const override
virtual bool SetVideoFillMode(VideoFillMode mode)=0
bool Muted() const override
double Duration() const override
void OnPlaybackStateChanged(VideoPlaybackState old_state, VideoPlaybackState new_state) override
void RemoveClient(MediaPlayer::Client *client) const override
void SetMuted(bool muted) override
virtual void Attach(const DecodedStream *stream)=0
void LoadedMetaData(double duration) override