| Index: webrtc/modules/video_coding/video_coding_impl.h | 
| diff --git a/webrtc/modules/video_coding/video_coding_impl.h b/webrtc/modules/video_coding/video_coding_impl.h | 
| index 5e547df07ae472c3a09236e61afb701b3a4a6b96..d6e722db3e04ee9e13a6d84d56fd79d578fbbada 100644 | 
| --- a/webrtc/modules/video_coding/video_coding_impl.h | 
| +++ b/webrtc/modules/video_coding/video_coding_impl.h | 
| @@ -35,6 +35,7 @@ | 
|  | 
| namespace webrtc { | 
|  | 
| +class ProcessThread; | 
| class VideoBitrateAllocator; | 
| class VideoBitrateAllocationObserver; | 
|  | 
| @@ -150,7 +151,7 @@ class VideoReceiver : public Module { | 
| VCMTiming* timing, | 
| NackSender* nack_sender = nullptr, | 
| KeyFrameRequestSender* keyframe_request_sender = nullptr); | 
| -  ~VideoReceiver(); | 
| +  ~VideoReceiver() override; | 
|  | 
| int32_t RegisterReceiveCodec(const VideoCodec* receiveCodec, | 
| int32_t numberOfCores, | 
| @@ -168,8 +169,10 @@ class VideoReceiver : public Module { | 
|  | 
| int32_t Decode(const webrtc::VCMEncodedFrame* frame); | 
|  | 
| -  // Called on the decoder thread when thread is exiting. | 
| -  void DecodingStopped(); | 
| +#if defined(WEBRTC_ANDROID) | 
| +  // See https://bugs.chromium.org/p/webrtc/issues/detail?id=7361 | 
| +  void PollDecodedFrames(); | 
| +#endif | 
|  | 
| int32_t IncomingPacket(const uint8_t* incomingPayload, | 
| size_t payloadLength, | 
| @@ -195,39 +198,66 @@ class VideoReceiver : public Module { | 
|  | 
| int64_t TimeUntilNextProcess() override; | 
| void Process() override; | 
| +  void ProcessThreadAttached(ProcessThread* process_thread) override; | 
|  | 
| void TriggerDecoderShutdown(); | 
| +  void DecoderThreadStarting(); | 
| +  void DecoderThreadStopped(); | 
|  | 
| protected: | 
| -  int32_t Decode(const webrtc::VCMEncodedFrame& frame) | 
| -      EXCLUSIVE_LOCKS_REQUIRED(receive_crit_); | 
| +  int32_t Decode(const webrtc::VCMEncodedFrame& frame); | 
| int32_t RequestKeyFrame(); | 
|  | 
| private: | 
| +  // Used for DCHECKing thread correctness. | 
| +  // In build where DCHECKs are enabled, will return false before | 
| +  // DecoderThreadStarting is called, then true until DecoderThreadStopped | 
| +  // is called. | 
| +  // In builds where DCHECKs aren't enabled, it will return true. | 
| +  bool IsDecoderThreadRunning(); | 
| + | 
| rtc::ThreadChecker construction_thread_; | 
| +  rtc::ThreadChecker decoder_thread_; | 
| +  rtc::ThreadChecker module_thread_; | 
| Clock* const clock_; | 
| rtc::CriticalSection process_crit_; | 
| -  rtc::CriticalSection receive_crit_; | 
| VCMTiming* _timing; | 
| VCMReceiver _receiver; | 
| VCMDecodedFrameCallback _decodedFrameCallback; | 
| -  VCMFrameTypeCallback* _frameTypeCallback GUARDED_BY(process_crit_); | 
| -  VCMReceiveStatisticsCallback* _receiveStatsCallback GUARDED_BY(process_crit_); | 
| -  VCMPacketRequestCallback* _packetRequestCallback GUARDED_BY(process_crit_); | 
|  | 
| -  VCMFrameBuffer _frameFromFile; | 
| +  // These callbacks are set on the construction thread before being attached | 
| +  // to the module thread or decoding started, so a lock is not required. | 
| +  VCMFrameTypeCallback* _frameTypeCallback; | 
| +  VCMReceiveStatisticsCallback* _receiveStatsCallback; | 
| +  VCMPacketRequestCallback* _packetRequestCallback; | 
| + | 
| +  // Used on both the module and decoder thread. | 
| bool _scheduleKeyRequest GUARDED_BY(process_crit_); | 
| bool drop_frames_until_keyframe_ GUARDED_BY(process_crit_); | 
| -  size_t max_nack_list_size_ GUARDED_BY(process_crit_); | 
| - | 
| -  VCMCodecDataBase _codecDataBase GUARDED_BY(receive_crit_); | 
| -  EncodedImageCallback* pre_decode_image_callback_; | 
|  | 
| -  VCMProcessTimer _receiveStatsTimer; | 
| -  VCMProcessTimer _retransmissionTimer; | 
| -  VCMProcessTimer _keyRequestTimer; | 
| -  QpParser qp_parser_; | 
| -  ThreadUnsafeOneTimeEvent first_frame_received_; | 
| +  // Modified on the construction thread while not attached to the process | 
| +  // thread.  Once attached to the process thread, its value is only read | 
| +  // so a lock is not required. | 
| +  size_t max_nack_list_size_; | 
| + | 
| +  // Callbacks are set before the decoder thread starts. | 
| +  // Once the decoder thread has been started, usage of |_codecDataBase| moves | 
| +  // over to the decoder thread. | 
| +  VCMCodecDataBase _codecDataBase; | 
| +  EncodedImageCallback* const pre_decode_image_callback_; | 
| + | 
| +  VCMProcessTimer _receiveStatsTimer ACCESS_ON(module_thread_); | 
| +  VCMProcessTimer _retransmissionTimer ACCESS_ON(module_thread_); | 
| +  VCMProcessTimer _keyRequestTimer ACCESS_ON(module_thread_); | 
| +  QpParser qp_parser_ ACCESS_ON(decoder_thread_); | 
| +  ThreadUnsafeOneTimeEvent first_frame_received_ ACCESS_ON(decoder_thread_); | 
| +  // Modified on the construction thread. Can be read without a lock and assumed | 
| +  // to be non-null on the module and decoder threads. | 
| +  ProcessThread* process_thread_ = nullptr; | 
| +  bool is_attached_to_process_thread_ ACCESS_ON(construction_thread_) = false; | 
| +#if RTC_DCHECK_IS_ON | 
| +  bool decoder_thread_is_running_ = false; | 
| +#endif | 
| }; | 
|  | 
| }  // namespace vcm | 
|  |