1f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#ifndef MEDIA_FILTERS_VIDEO_RENDERER_IMPL_H_ 6f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#define MEDIA_FILTERS_VIDEO_RENDERER_IMPL_H_ 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <deque> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h" 11116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/memory/scoped_ptr.h" 12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/memory/scoped_vector.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/weak_ptr.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/condition_variable.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/lock.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/platform_thread.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/base/decryptor.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/demuxer_stream.h" 191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "media/base/media_log.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/pipeline_status.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/video_decoder.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/video_frame.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/video_renderer.h" 24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "media/filters/decoder_stream.h" 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace base { 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class SingleThreadTaskRunner; 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media { 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 32f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// VideoRendererImpl creates its own thread for the sole purpose of timing frame 337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// presentation. It handles reading from the VideoFrameStream and stores the 347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// results in a queue of decoded frames and executing a callback when a frame is 357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// ready for rendering. 36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class MEDIA_EXPORT VideoRendererImpl 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : public VideoRenderer, 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public base::PlatformThread::Delegate { 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) typedef base::Callback<void(const scoped_refptr<VideoFrame>&)> PaintCB; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // |decoders| contains the VideoDecoders to use when initializing. 43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |paint_cb| is executed on the video frame timing thread whenever a new 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // frame is available for painting. 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Implementors should avoid doing any sort of heavy work in this method and 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // instead post a task to a common/worker thread to handle rendering. Slowing 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // down the video thread may result in losing synchronization with audio. 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Setting |drop_frames_| to true causes the renderer to drop expired frames. 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) VideoRendererImpl( 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ScopedVector<VideoDecoder> decoders, 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const SetDecryptorReadyCB& set_decryptor_ready_cb, 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const PaintCB& paint_cb, 571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bool drop_frames, 581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const scoped_refptr<MediaLog>& media_log); 59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) virtual ~VideoRendererImpl(); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // VideoRenderer implementation. 62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) virtual void Initialize(DemuxerStream* stream, 635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu bool low_delay, 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const PipelineStatusCB& init_cb, 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const StatisticsCB& statistics_cb, 66116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const BufferingStateCB& buffering_state_cb, 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::Closure& ended_cb, 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const PipelineStatusCB& error_cb, 691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const TimeDeltaCB& get_time_cb) OVERRIDE; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void Flush(const base::Closure& callback) OVERRIDE; 711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci virtual void StartPlayingFrom(base::TimeDelta timestamp) OVERRIDE; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // PlatformThread::Delegate implementation. 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void ThreadMain() OVERRIDE; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Callback for |video_frame_stream_| initialization. 78a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch void OnVideoFrameStreamInitialized(bool success); 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Callback for |video_frame_stream_| to deliver decoded video frames and 817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // report video decoding status. 82558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch void FrameReady(VideoFrameStream::Status status, 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const scoped_refptr<VideoFrame>& frame); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Helper method for adding a frame to |ready_frames_|. 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void AddReadyFrame_Locked(const scoped_refptr<VideoFrame>& frame); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Helper method that schedules an asynchronous read from the 897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // |video_frame_stream_| as long as there isn't a pending read and we have 907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // capacity. 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void AttemptRead(); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void AttemptRead_Locked(); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Called when VideoFrameStream::Reset() completes. 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void OnVideoFrameStreamResetDone(); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Runs |paint_cb_| with the next frame from |ready_frames_|. 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // A read is scheduled to replace the frame. 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void PaintNextReadyFrame_Locked(); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Drops the next frame from |ready_frames_| and runs |statistics_cb_|. 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // A read is scheduled to replace the frame. 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void DropNextReadyFrame_Locked(); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 107116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Returns true if the renderer has enough data for playback purposes. 108116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Note that having enough data may be due to reaching end of stream. 109116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch bool HaveEnoughData_Locked(); 110116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch void TransitionToHaveEnough_Locked(); 111a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Runs |statistics_cb_| with |frames_decoded_| and |frames_dropped_|, resets 1134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // them to 0, and then waits on |frame_available_| for up to the 1144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // |wait_duration|. 1154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) void UpdateStatsAndWait_Locked(base::TimeDelta wait_duration); 1164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<base::SingleThreadTaskRunner> task_runner_; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Used for accessing data members. 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Lock lock_; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 122f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Provides video frames to VideoRendererImpl. 123116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_ptr<VideoFrameStream> video_frame_stream_; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Flag indicating low-delay mode. 126010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) bool low_delay_; 127010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Queue of incoming frames yet to be painted. 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef std::deque<scoped_refptr<VideoFrame> > VideoFrameQueue; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VideoFrameQueue ready_frames_; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1320de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) // Keeps track of whether we received the end of stream buffer and finished 1330de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) // rendering. 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool received_end_of_stream_; 1350de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) bool rendered_end_of_stream_; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Used to signal |thread_| as frames are added to |frames_|. Rule of thumb: 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // always check |state_| to see if it was set to STOPPED after waking up! 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ConditionVariable frame_available_; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 141116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Important detail: being in kPlaying doesn't imply that video is being 142116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // rendered. Rather, it means that the renderer is ready to go. The actual 1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // rendering of video is controlled by time advancing via |get_time_cb_|. 144116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // 145116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // kUninitialized 146116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // | Initialize() 147116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // | 148116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // V 149116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // kInitializing 150116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // | Decoders initialized 151116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // | 152116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // V Decoders reset 153116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // kFlushed <------------------ kFlushing 1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // | StartPlayingFrom() ^ 155116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // | | 156116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // | | Flush() 157116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // `---------> kPlaying --------' 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enum State { 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kUninitialized, 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) kInitializing, 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kFlushing, 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kFlushed, 1635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) kPlaying 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) State state_; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Video thread handle. 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::PlatformThreadHandle thread_; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Keep track of the outstanding read on the VideoFrameStream. Flushing can 1717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // only complete once the read has completed. 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool pending_read_; 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool drop_frames_; 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 176116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch BufferingState buffering_state_; 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Playback operation callbacks. 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Closure flush_cb_; 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Event callbacks. 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PipelineStatusCB init_cb_; 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StatisticsCB statistics_cb_; 184116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch BufferingStateCB buffering_state_cb_; 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Closure ended_cb_; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PipelineStatusCB error_cb_; 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeDeltaCB get_time_cb_; 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 189116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::TimeDelta start_timestamp_; 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Embedder callback for notifying a new frame is available for painting. 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PaintCB paint_cb_; 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The timestamp of the last frame removed from the |ready_frames_| queue, 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // either for calling |paint_cb_| or for dropping. Set to kNoTimestamp() 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // during flushing. 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeDelta last_timestamp_; 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // The timestamp of the last successfully painted frame. Set to kNoTimestamp() 2006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // during flushing. 2016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) base::TimeDelta last_painted_timestamp_; 2026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 2034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Keeps track of the number of frames decoded and dropped since the 2044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // last call to |statistics_cb_|. These must be accessed under lock. 2054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) int frames_decoded_; 2064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) int frames_dropped_; 2074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bool is_shutting_down_; 2095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 21023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // NOTE: Weak pointers must be invalidated before all other member variables. 21123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) base::WeakPtrFactory<VideoRendererImpl> weak_factory_; 21223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 213f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(VideoRendererImpl); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace media 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 218f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#endif // MEDIA_FILTERS_VIDEO_RENDERER_IMPL_H_ 219