• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_vector.h"
12 #include "base/memory/weak_ptr.h"
13 #include "base/synchronization/condition_variable.h"
14 #include "base/synchronization/lock.h"
15 #include "base/threading/platform_thread.h"
16 #include "media/base/decryptor.h"
17 #include "media/base/demuxer_stream.h"
18 #include "media/base/pipeline_status.h"
19 #include "media/base/video_decoder.h"
20 #include "media/base/video_frame.h"
21 #include "media/base/video_renderer.h"
22 #include "media/filters/decoder_stream.h"
23 
24 namespace base {
25 class SingleThreadTaskRunner;
26 }
27 
28 namespace media {
29 
30 // VideoRendererImpl creates its own thread for the sole purpose of timing frame
31 // presentation.  It handles reading from the VideoFrameStream and stores the
32 // results in a queue of decoded frames and executing a callback when a frame is
33 // ready for rendering.
34 class MEDIA_EXPORT VideoRendererImpl
35     : public VideoRenderer,
36       public base::PlatformThread::Delegate {
37  public:
38   typedef base::Callback<void(const scoped_refptr<VideoFrame>&)> PaintCB;
39 
40   // |decoders| contains the VideoDecoders to use when initializing.
41   //
42   // |paint_cb| is executed on the video frame timing thread whenever a new
43   // frame is available for painting.
44   //
45   // Implementors should avoid doing any sort of heavy work in this method and
46   // instead post a task to a common/worker thread to handle rendering.  Slowing
47   // down the video thread may result in losing synchronization with audio.
48   //
49   // Setting |drop_frames_| to true causes the renderer to drop expired frames.
50   VideoRendererImpl(
51       const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
52       ScopedVector<VideoDecoder> decoders,
53       const SetDecryptorReadyCB& set_decryptor_ready_cb,
54       const PaintCB& paint_cb,
55       bool drop_frames);
56   virtual ~VideoRendererImpl();
57 
58   // VideoRenderer implementation.
59   virtual void Initialize(DemuxerStream* stream,
60                           bool low_delay,
61                           const PipelineStatusCB& init_cb,
62                           const StatisticsCB& statistics_cb,
63                           const TimeCB& max_time_cb,
64                           const base::Closure& ended_cb,
65                           const PipelineStatusCB& error_cb,
66                           const TimeDeltaCB& get_time_cb,
67                           const TimeDeltaCB& get_duration_cb) OVERRIDE;
68   virtual void Play(const base::Closure& callback) OVERRIDE;
69   virtual void Flush(const base::Closure& callback) OVERRIDE;
70   virtual void Preroll(base::TimeDelta time,
71                        const PipelineStatusCB& cb) OVERRIDE;
72   virtual void Stop(const base::Closure& callback) OVERRIDE;
73   virtual void SetPlaybackRate(float playback_rate) OVERRIDE;
74 
75   // PlatformThread::Delegate implementation.
76   virtual void ThreadMain() OVERRIDE;
77 
78  private:
79   // Callback for |video_frame_stream_| initialization.
80   void OnVideoFrameStreamInitialized(bool success);
81 
82   // Callback for |video_frame_stream_| to deliver decoded video frames and
83   // report video decoding status.
84   void FrameReady(VideoFrameStream::Status status,
85                   const scoped_refptr<VideoFrame>& frame);
86 
87   // Helper method for adding a frame to |ready_frames_|.
88   void AddReadyFrame_Locked(const scoped_refptr<VideoFrame>& frame);
89 
90   // Helper method that schedules an asynchronous read from the
91   // |video_frame_stream_| as long as there isn't a pending read and we have
92   // capacity.
93   void AttemptRead();
94   void AttemptRead_Locked();
95 
96   // Called when VideoFrameStream::Reset() completes.
97   void OnVideoFrameStreamResetDone();
98 
99   // Calculates the duration to sleep for based on |last_timestamp_|,
100   // the next frame timestamp (may be NULL), and the provided playback rate.
101   //
102   // We don't use |playback_rate_| to avoid locking.
103   base::TimeDelta CalculateSleepDuration(
104       const scoped_refptr<VideoFrame>& next_frame,
105       float playback_rate);
106 
107   // Helper function that flushes the buffers when a Stop() or error occurs.
108   void DoStopOrError_Locked();
109 
110   // Runs |paint_cb_| with the next frame from |ready_frames_|.
111   //
112   // A read is scheduled to replace the frame.
113   void PaintNextReadyFrame_Locked();
114 
115   // Drops the next frame from |ready_frames_| and runs |statistics_cb_|.
116   //
117   // A read is scheduled to replace the frame.
118   void DropNextReadyFrame_Locked();
119 
120   void TransitionToPrerolled_Locked();
121 
122   // Returns true of all conditions have been met to transition from
123   // kPrerolling to kPrerolled.
124   bool ShouldTransitionToPrerolled_Locked();
125 
126   // Runs |statistics_cb_| with |frames_decoded_| and |frames_dropped_|, resets
127   // them to 0, and then waits on |frame_available_| for up to the
128   // |wait_duration|.
129   void UpdateStatsAndWait_Locked(base::TimeDelta wait_duration);
130 
131   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
132 
133   // Used for accessing data members.
134   base::Lock lock_;
135 
136   // Provides video frames to VideoRendererImpl.
137   VideoFrameStream video_frame_stream_;
138 
139   // Flag indicating low-delay mode.
140   bool low_delay_;
141 
142   // Queue of incoming frames yet to be painted.
143   typedef std::deque<scoped_refptr<VideoFrame> > VideoFrameQueue;
144   VideoFrameQueue ready_frames_;
145 
146   // Keeps track of whether we received the end of stream buffer and finished
147   // rendering.
148   bool received_end_of_stream_;
149   bool rendered_end_of_stream_;
150 
151   // Used to signal |thread_| as frames are added to |frames_|.  Rule of thumb:
152   // always check |state_| to see if it was set to STOPPED after waking up!
153   base::ConditionVariable frame_available_;
154 
155   // State transition Diagram of this class:
156   //       [kUninitialized]
157   //              |
158   //              | Initialize()
159   //        [kInitializing]
160   //              |
161   //              V
162   //   +------[kFlushed]<---------------OnVideoFrameStreamResetDone()
163   //   |          | Preroll() or upon               ^
164   //   |          V got first frame            [kFlushing]
165   //   |      [kPrerolling]                         ^
166   //   |          |                                 |
167   //   |          V Got enough frames               |
168   //   |      [kPrerolled]--------------------------|
169   //   |          |                Flush()          ^
170   //   |          V Play()                          |
171   //   |       [kPlaying]---------------------------|
172   //   |                           Flush()          ^ Flush()
173   //   |                                            |
174   //   +-----> [kStopped]                 [Any state other than]
175   //                                      [   kUninitialized   ]
176 
177   // Simple state tracking variable.
178   enum State {
179     kUninitialized,
180     kInitializing,
181     kPrerolled,
182     kFlushing,
183     kFlushed,
184     kPrerolling,
185     kPlaying,
186     kStopped,
187   };
188   State state_;
189 
190   // Video thread handle.
191   base::PlatformThreadHandle thread_;
192 
193   // Keep track of the outstanding read on the VideoFrameStream. Flushing can
194   // only complete once the read has completed.
195   bool pending_read_;
196 
197   bool drop_frames_;
198 
199   float playback_rate_;
200 
201   // Playback operation callbacks.
202   base::Closure flush_cb_;
203   PipelineStatusCB preroll_cb_;
204 
205   // Event callbacks.
206   PipelineStatusCB init_cb_;
207   StatisticsCB statistics_cb_;
208   TimeCB max_time_cb_;
209   base::Closure ended_cb_;
210   PipelineStatusCB error_cb_;
211   TimeDeltaCB get_time_cb_;
212   TimeDeltaCB get_duration_cb_;
213 
214   base::TimeDelta preroll_timestamp_;
215 
216   // Embedder callback for notifying a new frame is available for painting.
217   PaintCB paint_cb_;
218 
219   // The timestamp of the last frame removed from the |ready_frames_| queue,
220   // either for calling |paint_cb_| or for dropping. Set to kNoTimestamp()
221   // during flushing.
222   base::TimeDelta last_timestamp_;
223 
224   // Keeps track of the number of frames decoded and dropped since the
225   // last call to |statistics_cb_|. These must be accessed under lock.
226   int frames_decoded_;
227   int frames_dropped_;
228 
229   // NOTE: Weak pointers must be invalidated before all other member variables.
230   base::WeakPtrFactory<VideoRendererImpl> weak_factory_;
231 
232   DISALLOW_COPY_AND_ASSIGN(VideoRendererImpl);
233 };
234 
235 }  // namespace media
236 
237 #endif  // MEDIA_FILTERS_VIDEO_RENDERER_IMPL_H_
238