chromium/chromecast/media/cma/backend/video_decoder_for_mixer.h

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

#ifndef CHROMECAST_MEDIA_CMA_BACKEND_VIDEO_DECODER_FOR_MIXER_H_
#define CHROMECAST_MEDIA_CMA_BACKEND_VIDEO_DECODER_FOR_MIXER_H_

#include <memory>

#include "chromecast/public/media/media_pipeline_backend.h"
#include "chromecast/public/media/media_pipeline_device_params.h"

namespace chromecast {
namespace media {

// This class represents a video decoder that exposes additional functionality
// that allows a caller to control the rate and state of the video playback
// with enough granularity to be able to sync it to the audio.
//
// The default implementation of this is in VideoDecoderNull. On no-video
// platforms, that implementation is used.
//
// On video platforms that need to use the mixer, you may override this class
// and link in an implementation of VideoDecoderForMixer::Create.
class VideoDecoderForMixer : public MediaPipelineBackend::VideoDecoder {
 public:
  class Observer {
   public:
    // Notifies the observer that the video playback is ready to start. After
    // this is called, SetPts may be reliably called to start playback at the
    // desired time.
    virtual void VideoReadyToPlay() = 0;

   protected:
    virtual ~Observer() {}
  };

  static std::unique_ptr<VideoDecoderForMixer> Create(
      const MediaPipelineDeviceParams& params);

  // On some platforms, graphics needs to be initialized before this component
  // will function appropriately in tests. Add the initialization here if
  // necessary.
  static void InitializeGraphicsForTesting();

  ~VideoDecoderForMixer() override {}

  // Initializes the VideoDecoderForMixer. Called after allocation and before
  // Start is called. Gives the implementation a chance to initialize any
  // resources.
  virtual bool Initialize() = 0;

  // Sets the observer to be notified when the video is ready to play.
  virtual void SetObserver(Observer* observer) = 0;

  // When called, playback is expected to start from |start_pts|.
  //
  // start_pts: the pts to start playing at.
  // need_avsync: deprecated. Don't use or implement.
  // TODO(almasrymina): remove deprecated.
  virtual bool Start(int64_t start_pts, bool need_avsync) = 0;

  // Stop playback.
  virtual void Stop() = 0;

  // Pause playback. The video decoder must retain its playback rate after
  // resume.
  virtual bool Pause() = 0;

  // Resume playback. The video decoder must resume playback at the same
  // playback rate prior to pausing.
  virtual bool Resume() = 0;

  // Returns the current video PTS. This will typically be the pts of the last
  // video frame displayed.
  virtual bool GetCurrentPts(int64_t* timestamp, int64_t* pts) const = 0;

  // Set the playback rate. This is used to sync the audio to the video. This
  // call will change the rate of play of video in the following manner:
  //
  // rate = 1.0 -> 1 second of video pts is played for each 1 second of
  // wallclock time.
  // rate = 1.5 -> 1.5 seconds of video pts is played for each 1 second of
  // wallclock time.
  // etc.
  virtual bool SetPlaybackRate(float rate) = 0;

  // Sets the current pts to the provided value. If |pts| is greater than the
  // current pts, all video frames in between will be dropped. If |pts| is less
  // than the current pts, all video frames in this pts range will be repeated.
  // Implementation is encouraged to smooth out this transition, such that
  // minimal jitter in the video is shown, but that is not necessary.
  virtual bool SetPts(int64_t timestamp, int64_t pts) = 0;

  // Returns number of frames dropped since the last call to Start(). This is
  // used to estimate video playback smoothness.
  // This is different from VideoDecoder::Statistics::dropped_frames. That
  // value is the number of *decoded* dropped frames. The value returned here
  // must be the total number of dropped frames, whether the frames have been
  // decoded or not.
  virtual int64_t GetDroppedFrames() = 0;

  // Returns number of frames repeated since the last call to Start(). This is
  // used to estimate video playback smoothness. Note that repeated frames could
  // be due to changes in the rate of playback, setting the PTS, or simply due
  // to frame rate conversion. This number should be the sum of all of these
  // factors.
  //
  // For example, if the current OutputRefreshRate is 60hz, and the current
  // content frame rate is 24fps, it is expected to repeat 36fps.
  virtual int64_t GetRepeatedFrames() = 0;

  // Returns the output refresh rate on this platform, in mHz (millihertz). On
  // display devices, this will be the display refresh rate. On HDMI devices,
  // this will be the refresh rate of the HDMI connection.
  virtual int64_t GetOutputRefreshRate() = 0;

  // Returns the current content refresh rate in mHz (millihertz).
  virtual int64_t GetCurrentContentRefreshRate() = 0;
};

}  // namespace media
}  // namespace chromecast

#endif  // CHROMECAST_MEDIA_CMA_BACKEND_VIDEO_DECODER_FOR_MIXER_H_