chromium/chromecast/media/cma/backend/desktop/media_pipeline_backend_desktop.cc

// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chromecast/media/cma/backend/desktop/media_pipeline_backend_desktop.h"

#include "base/check_op.h"
#include "base/time/time.h"
#include "chromecast/media/cma/backend/desktop/audio_decoder_desktop.h"
#include "chromecast/media/cma/backend/desktop/video_decoder_desktop.h"
#include "media/base/timestamp_constants.h"

namespace chromecast {
namespace media {

MediaPipelineBackendDesktop::MediaPipelineBackendDesktop()
    : state_(kStateUninitialized), rate_(1.0f) {}

MediaPipelineBackendDesktop::~MediaPipelineBackendDesktop() {}

MediaPipelineBackend::AudioDecoder*
MediaPipelineBackendDesktop::CreateAudioDecoder() {
  DCHECK_EQ(kStateUninitialized, state_);
  DCHECK(!audio_decoder_);
  audio_decoder_ = std::make_unique<AudioDecoderDesktop>();
  return audio_decoder_.get();
}

MediaPipelineBackend::VideoDecoder*
MediaPipelineBackendDesktop::CreateVideoDecoder() {
  DCHECK_EQ(kStateUninitialized, state_);
  DCHECK(!video_decoder_);
  video_decoder_ = std::make_unique<VideoDecoderDesktop>();
  return video_decoder_.get();
}

bool MediaPipelineBackendDesktop::Initialize() {
  DCHECK_EQ(kStateUninitialized, state_);
  state_ = kStateInitialized;
  return true;
}

bool MediaPipelineBackendDesktop::Start(int64_t start_pts) {
  DCHECK_EQ(kStateInitialized, state_);
  if (!audio_decoder_ && !video_decoder_)
    return false;

  if (audio_decoder_) {
    audio_decoder_->Start(base::Microseconds(start_pts));
    audio_decoder_->SetPlaybackRate(rate_);
  }
  if (video_decoder_) {
    video_decoder_->Start(base::Microseconds(start_pts));
    video_decoder_->SetPlaybackRate(rate_);
  }
  state_ = kStatePlaying;
  return true;
}

void MediaPipelineBackendDesktop::Stop() {
  DCHECK(state_ == kStatePlaying || state_ == kStatePaused);
  if (audio_decoder_)
    audio_decoder_->Stop();
  if (video_decoder_)
    video_decoder_->Stop();
  state_ = kStateInitialized;
}

bool MediaPipelineBackendDesktop::Pause() {
  DCHECK_EQ(kStatePlaying, state_);
  if (audio_decoder_)
    audio_decoder_->SetPlaybackRate(0.0f);
  if (video_decoder_)
    video_decoder_->SetPlaybackRate(0.0f);
  state_ = kStatePaused;
  return true;
}

bool MediaPipelineBackendDesktop::Resume() {
  DCHECK_EQ(kStatePaused, state_);
  if (audio_decoder_)
    audio_decoder_->SetPlaybackRate(rate_);
  if (video_decoder_)
    video_decoder_->SetPlaybackRate(rate_);
  state_ = kStatePlaying;
  return true;
}

int64_t MediaPipelineBackendDesktop::GetCurrentPts() {
  base::TimeDelta current_pts = ::media::kNoTimestamp;

  if (audio_decoder_ && video_decoder_) {
    current_pts = std::min(audio_decoder_->GetCurrentPts(),
                           video_decoder_->GetCurrentPts());
  } else if (audio_decoder_) {
    current_pts = audio_decoder_->GetCurrentPts();
  } else if (video_decoder_) {
    current_pts = video_decoder_->GetCurrentPts();
  }

  return current_pts.InMicroseconds();
}

bool MediaPipelineBackendDesktop::SetPlaybackRate(float rate) {
  DCHECK_GT(rate, 0.0f);
  rate_ = rate;

  if (state_ == kStatePlaying) {
    if (audio_decoder_)
      audio_decoder_->SetPlaybackRate(rate_);
    if (video_decoder_)
      video_decoder_->SetPlaybackRate(rate_);
  }

  return true;
}

}  // namespace media
}  // namespace chromecast