Home | History | Annotate | Download | only in filters
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef MEDIA_FILTERS_VIDEO_RENDERER_IMPL_H_
      6 #define MEDIA_FILTERS_VIDEO_RENDERER_IMPL_H_
      7 
      8 #include <deque>
      9 
     10 #include "base/memory/ref_counted.h"
     11 #include "base/memory/scoped_ptr.h"
     12 #include "base/memory/scoped_vector.h"
     13 #include "base/memory/weak_ptr.h"
     14 #include "base/synchronization/condition_variable.h"
     15 #include "base/synchronization/lock.h"
     16 #include "base/threading/platform_thread.h"
     17 #include "media/base/decryptor.h"
     18 #include "media/base/demuxer_stream.h"
     19 #include "media/base/media_log.h"
     20 #include "media/base/pipeline_status.h"
     21 #include "media/base/video_decoder.h"
     22 #include "media/base/video_frame.h"
     23 #include "media/base/video_renderer.h"
     24 #include "media/filters/decoder_stream.h"
     25 
     26 namespace base {
     27 class SingleThreadTaskRunner;
     28 }
     29 
     30 namespace media {
     31 
     32 // VideoRendererImpl creates its own thread for the sole purpose of timing frame
     33 // presentation.  It handles reading from the VideoFrameStream and stores the
     34 // results in a queue of decoded frames and executing a callback when a frame is
     35 // ready for rendering.
     36 class MEDIA_EXPORT VideoRendererImpl
     37     : public VideoRenderer,
     38       public base::PlatformThread::Delegate {
     39  public:
     40   typedef base::Callback<void(const scoped_refptr<VideoFrame>&)> PaintCB;
     41 
     42   // |decoders| contains the VideoDecoders to use when initializing.
     43   //
     44   // |paint_cb| is executed on the video frame timing thread whenever a new
     45   // frame is available for painting.
     46   //
     47   // Implementors should avoid doing any sort of heavy work in this method and
     48   // instead post a task to a common/worker thread to handle rendering.  Slowing
     49   // down the video thread may result in losing synchronization with audio.
     50   //
     51   // Setting |drop_frames_| to true causes the renderer to drop expired frames.
     52   VideoRendererImpl(
     53       const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
     54       ScopedVector<VideoDecoder> decoders,
     55       const SetDecryptorReadyCB& set_decryptor_ready_cb,
     56       const PaintCB& paint_cb,
     57       bool drop_frames,
     58       const scoped_refptr<MediaLog>& media_log);
     59   virtual ~VideoRendererImpl();
     60 
     61   // VideoRenderer implementation.
     62   virtual void Initialize(DemuxerStream* stream,
     63                           bool low_delay,
     64                           const PipelineStatusCB& init_cb,
     65                           const StatisticsCB& statistics_cb,
     66                           const BufferingStateCB& buffering_state_cb,
     67                           const base::Closure& ended_cb,
     68                           const PipelineStatusCB& error_cb,
     69                           const TimeDeltaCB& get_time_cb) OVERRIDE;
     70   virtual void Flush(const base::Closure& callback) OVERRIDE;
     71   virtual void StartPlayingFrom(base::TimeDelta timestamp) OVERRIDE;
     72 
     73   // PlatformThread::Delegate implementation.
     74   virtual void ThreadMain() OVERRIDE;
     75 
     76  private:
     77   // Callback for |video_frame_stream_| initialization.
     78   void OnVideoFrameStreamInitialized(bool success);
     79 
     80   // Callback for |video_frame_stream_| to deliver decoded video frames and
     81   // report video decoding status.
     82   void FrameReady(VideoFrameStream::Status status,
     83                   const scoped_refptr<VideoFrame>& frame);
     84 
     85   // Helper method for adding a frame to |ready_frames_|.
     86   void AddReadyFrame_Locked(const scoped_refptr<VideoFrame>& frame);
     87 
     88   // Helper method that schedules an asynchronous read from the
     89   // |video_frame_stream_| as long as there isn't a pending read and we have
     90   // capacity.
     91   void AttemptRead();
     92   void AttemptRead_Locked();
     93 
     94   // Called when VideoFrameStream::Reset() completes.
     95   void OnVideoFrameStreamResetDone();
     96 
     97   // Runs |paint_cb_| with the next frame from |ready_frames_|.
     98   //
     99   // A read is scheduled to replace the frame.
    100   void PaintNextReadyFrame_Locked();
    101 
    102   // Drops the next frame from |ready_frames_| and runs |statistics_cb_|.
    103   //
    104   // A read is scheduled to replace the frame.
    105   void DropNextReadyFrame_Locked();
    106 
    107   // Returns true if the renderer has enough data for playback purposes.
    108   // Note that having enough data may be due to reaching end of stream.
    109   bool HaveEnoughData_Locked();
    110   void TransitionToHaveEnough_Locked();
    111 
    112   // Runs |statistics_cb_| with |frames_decoded_| and |frames_dropped_|, resets
    113   // them to 0, and then waits on |frame_available_| for up to the
    114   // |wait_duration|.
    115   void UpdateStatsAndWait_Locked(base::TimeDelta wait_duration);
    116 
    117   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
    118 
    119   // Used for accessing data members.
    120   base::Lock lock_;
    121 
    122   // Provides video frames to VideoRendererImpl.
    123   scoped_ptr<VideoFrameStream> video_frame_stream_;
    124 
    125   // Flag indicating low-delay mode.
    126   bool low_delay_;
    127 
    128   // Queue of incoming frames yet to be painted.
    129   typedef std::deque<scoped_refptr<VideoFrame> > VideoFrameQueue;
    130   VideoFrameQueue ready_frames_;
    131 
    132   // Keeps track of whether we received the end of stream buffer and finished
    133   // rendering.
    134   bool received_end_of_stream_;
    135   bool rendered_end_of_stream_;
    136 
    137   // Used to signal |thread_| as frames are added to |frames_|.  Rule of thumb:
    138   // always check |state_| to see if it was set to STOPPED after waking up!
    139   base::ConditionVariable frame_available_;
    140 
    141   // Important detail: being in kPlaying doesn't imply that video is being
    142   // rendered. Rather, it means that the renderer is ready to go. The actual
    143   // rendering of video is controlled by time advancing via |get_time_cb_|.
    144   //
    145   //   kUninitialized
    146   //         | Initialize()
    147   //         |
    148   //         V
    149   //    kInitializing
    150   //         | Decoders initialized
    151   //         |
    152   //         V            Decoders reset
    153   //      kFlushed <------------------ kFlushing
    154   //         | StartPlayingFrom()         ^
    155   //         |                            |
    156   //         |                            | Flush()
    157   //         `---------> kPlaying --------'
    158   enum State {
    159     kUninitialized,
    160     kInitializing,
    161     kFlushing,
    162     kFlushed,
    163     kPlaying
    164   };
    165   State state_;
    166 
    167   // Video thread handle.
    168   base::PlatformThreadHandle thread_;
    169 
    170   // Keep track of the outstanding read on the VideoFrameStream. Flushing can
    171   // only complete once the read has completed.
    172   bool pending_read_;
    173 
    174   bool drop_frames_;
    175 
    176   BufferingState buffering_state_;
    177 
    178   // Playback operation callbacks.
    179   base::Closure flush_cb_;
    180 
    181   // Event callbacks.
    182   PipelineStatusCB init_cb_;
    183   StatisticsCB statistics_cb_;
    184   BufferingStateCB buffering_state_cb_;
    185   base::Closure ended_cb_;
    186   PipelineStatusCB error_cb_;
    187   TimeDeltaCB get_time_cb_;
    188 
    189   base::TimeDelta start_timestamp_;
    190 
    191   // Embedder callback for notifying a new frame is available for painting.
    192   PaintCB paint_cb_;
    193 
    194   // The timestamp of the last frame removed from the |ready_frames_| queue,
    195   // either for calling |paint_cb_| or for dropping. Set to kNoTimestamp()
    196   // during flushing.
    197   base::TimeDelta last_timestamp_;
    198 
    199   // The timestamp of the last successfully painted frame. Set to kNoTimestamp()
    200   // during flushing.
    201   base::TimeDelta last_painted_timestamp_;
    202 
    203   // Keeps track of the number of frames decoded and dropped since the
    204   // last call to |statistics_cb_|. These must be accessed under lock.
    205   int frames_decoded_;
    206   int frames_dropped_;
    207 
    208   bool is_shutting_down_;
    209 
    210   // NOTE: Weak pointers must be invalidated before all other member variables.
    211   base::WeakPtrFactory<VideoRendererImpl> weak_factory_;
    212 
    213   DISALLOW_COPY_AND_ASSIGN(VideoRendererImpl);
    214 };
    215 
    216 }  // namespace media
    217 
    218 #endif  // MEDIA_FILTERS_VIDEO_RENDERER_IMPL_H_
    219