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