| Index: media/cast/video_receiver/video_receiver.h | 
| diff --git a/media/cast/video_receiver/video_receiver.h b/media/cast/video_receiver/video_receiver.h | 
| index b0c636faab9671b8ad2d4106f5880e6b18a6e3bf..7f3ca232faca55d3d3e323d067beb98e42607f7c 100644 | 
| --- a/media/cast/video_receiver/video_receiver.h | 
| +++ b/media/cast/video_receiver/video_receiver.h | 
| @@ -16,6 +16,7 @@ | 
| #include "media/cast/cast_config.h" | 
| #include "media/cast/cast_environment.h" | 
| #include "media/cast/cast_receiver.h" | 
| +#include "media/cast/framer/framer.h" | 
| #include "media/cast/rtcp/receiver_rtcp_event_subscriber.h" | 
| #include "media/cast/rtcp/rtcp.h" | 
| #include "media/cast/rtp_receiver/rtp_receiver.h" | 
| @@ -23,70 +24,94 @@ | 
| #include "media/cast/transport/utility/transport_encryption_handler.h" | 
|  | 
| namespace media { | 
| + | 
| +class VideoFrame; | 
| + | 
| namespace cast { | 
|  | 
| -class Framer; | 
| -class LocalRtpVideoFeedback; | 
| -class PeerVideoReceiver; | 
| -class Rtcp; | 
| -class RtpReceiverStatistics; | 
| class VideoDecoder; | 
|  | 
| -// Callback used by the video receiver to inform the audio receiver of the new | 
| -// delay used to compute the playout and render times. | 
| -typedef base::Callback<void(base::TimeDelta)> SetTargetDelayCallback; | 
| - | 
| -// Should only be called from the Main cast thread. | 
| -class VideoReceiver : public base::NonThreadSafe, | 
| -                      public base::SupportsWeakPtr<VideoReceiver>, | 
| -                      public RtpReceiver { | 
| +// VideoReceiver receives packets out-of-order while clients make requests for | 
| +// complete frames in-order.  (A frame consists of one or more packets.) | 
| +// | 
| +// VideoReceiver also includes logic for computing the playout time for each | 
| +// frame, accounting for a constant targeted playout delay.  The purpose of the | 
| +// playout delay is to provide a fixed window of time between the capture event | 
| +// on the sender and the playout on the receiver.  This is important because | 
| +// each step of the pipeline (i.e., encode frame, then transmit/retransmit from | 
| +// the sender, then receive and re-order packets on the receiver, then decode | 
| +// frame) can vary in duration and is typically very hard to predict. | 
| +// Heuristics will determine when the targeted playout delay is insufficient in | 
| +// the current environment; and the receiver can then increase the playout | 
| +// delay, notifying the sender, to account for the extra variance. | 
| +// TODO(miu): Make the last sentence true.  http://crbug.com/360111 | 
| +// | 
| +// Two types of frames can be requested: 1) A frame of decoded video data; or 2) | 
| +// a frame of still-encoded video data, to be passed into an external video | 
| +// decoder.  Each request for a frame includes a callback which VideoReceiver | 
| +// guarantees will be called at some point in the future.  Clients should | 
| +// generally limit the number of outstanding requests (perhaps to just one or | 
| +// two).  When VideoReceiver is destroyed, any outstanding requests will be | 
| +// immediately invoked with a NULL frame. | 
| +// | 
| +// This class is not thread safe.  Should only be called from the Main cast | 
| +// thread. | 
| +class VideoReceiver : public RtpReceiver, | 
| +                      public RtpPayloadFeedback, | 
| +                      public base::NonThreadSafe, | 
| +                      public base::SupportsWeakPtr<VideoReceiver> { | 
| public: | 
| VideoReceiver(scoped_refptr<CastEnvironment> cast_environment, | 
| const VideoReceiverConfig& video_config, | 
| -                transport::PacedPacketSender* const packet_sender, | 
| -                const SetTargetDelayCallback& target_delay_cb); | 
| +                transport::PacedPacketSender* const packet_sender); | 
|  | 
| virtual ~VideoReceiver(); | 
|  | 
| -  // Request a raw frame. Will return frame via callback when available. | 
| +  // Request a decoded video frame. | 
| +  // | 
| +  // The given |callback| is guaranteed to be run at some point in the future, | 
| +  // even if to respond with NULL at shutdown time. | 
| void GetRawVideoFrame(const VideoFrameDecodedCallback& callback); | 
|  | 
| -  // Request an encoded frame. Will return frame via callback when available. | 
| +  // Request an encoded video frame. | 
| +  // | 
| +  // The given |callback| is guaranteed to be run at some point in the future, | 
| +  // even if to respond with NULL at shutdown time. | 
| void GetEncodedVideoFrame(const VideoFrameEncodedCallback& callback); | 
|  | 
| -  // Insert a RTP packet to the video receiver. | 
| +  // Deliver another packet, possibly a duplicate, and possibly out-of-order. | 
| void IncomingPacket(scoped_ptr<Packet> packet); | 
|  | 
| + protected: | 
| +  friend class VideoReceiverTest;  // Invoked OnReceivedPayloadData(). | 
| + | 
| virtual void OnReceivedPayloadData(const uint8* payload_data, | 
| size_t payload_size, | 
| const RtpCastHeader& rtp_header) OVERRIDE; | 
|  | 
| - protected: | 
| -  void DecodeVideoFrameThread( | 
| -      scoped_ptr<transport::EncodedVideoFrame> encoded_frame, | 
| -      const base::TimeTicks render_time, | 
| -      const VideoFrameDecodedCallback& frame_decoded_callback); | 
| +  // RtpPayloadFeedback implementation. | 
| +  virtual void CastFeedback(const RtcpCastMessage& cast_message) OVERRIDE; | 
|  | 
| private: | 
| -  friend class LocalRtpVideoFeedback; | 
| - | 
| -  void CastFeedback(const RtcpCastMessage& cast_message); | 
| - | 
| -  void DecodeVideoFrame(const VideoFrameDecodedCallback& callback, | 
| -                        scoped_ptr<transport::EncodedVideoFrame> encoded_frame, | 
| -                        const base::TimeTicks& render_time); | 
| - | 
| -  bool DecryptVideoFrame(scoped_ptr<transport::EncodedVideoFrame>* video_frame); | 
| - | 
| -  bool PullEncodedVideoFrame( | 
| -      bool next_frame, | 
| -      scoped_ptr<transport::EncodedVideoFrame>* encoded_frame, | 
| -      base::TimeTicks* render_time); | 
| - | 
| -  void PlayoutTimeout(); | 
| +  // Processes ready-to-consume packets from |framer_|, decrypting each packet's | 
| +  // payload data, and then running the enqueued callbacks in order (one for | 
| +  // each packet).  This method may post a delayed task to re-invoke itself in | 
| +  // the future to wait for missing/incomplete frames. | 
| +  void EmitAvailableEncodedFrames(); | 
| + | 
| +  // Clears the |is_waiting_for_consecutive_frame_| flag and invokes | 
| +  // EmitAvailableEncodedFrames(). | 
| +  void EmitAvailableEncodedFramesAfterWaiting(); | 
| + | 
| +  // Feeds an EncodedVideoFrame into |video_decoder_|.  GetRawVideoFrame() uses | 
| +  // this as a callback for GetEncodedVideoFrame(). | 
| +  void DecodeEncodedVideoFrame( | 
| +      const VideoFrameDecodedCallback& callback, | 
| +      scoped_ptr<transport::EncodedVideoFrame> encoded_frame, | 
| +      const base::TimeTicks& playout_time); | 
|  | 
| -  // Returns Render time based on current time and the rtp timestamp. | 
| -  base::TimeTicks GetRenderTime(base::TimeTicks now, uint32 rtp_timestamp); | 
| +  // Return the playout time based on the current time and rtp timestamp. | 
| +  base::TimeTicks GetPlayoutTime(base::TimeTicks now, uint32 rtp_timestamp); | 
|  | 
| void InitializeTimers(); | 
|  | 
| @@ -102,32 +127,45 @@ class VideoReceiver : public base::NonThreadSafe, | 
| // Actually send the next RTCP report. | 
| void SendNextRtcpReport(); | 
|  | 
| -  // Update the target delay based on past information. Will also update the | 
| -  // rtcp module and the audio receiver. | 
| -  void UpdateTargetDelay(); | 
| - | 
| -  scoped_ptr<VideoDecoder> video_decoder_; | 
| -  scoped_refptr<CastEnvironment> cast_environment_; | 
| +  // Receives a VideoFrame from |video_decoder_|, logs the event, and passes the | 
| +  // data on by running the given |callback|.  This method is static to ensure | 
| +  // it can be called after a VideoReceiver instance is destroyed. | 
| +  // DecodeEncodedVideoFrame() uses this as a callback for | 
| +  // VideoDecoder::DecodeFrame(). | 
| +  static void EmitRawVideoFrame( | 
| +      const scoped_refptr<CastEnvironment>& cast_environment, | 
| +      const VideoFrameDecodedCallback& callback, | 
| +      uint32 frame_id, | 
| +      uint32 rtp_timestamp, | 
| +      const base::TimeTicks& playout_time, | 
| +      const scoped_refptr<VideoFrame>& video_frame, | 
| +      bool is_continuous); | 
| + | 
| +  const scoped_refptr<CastEnvironment> cast_environment_; | 
|  | 
| // Subscribes to raw events. | 
| // Processes raw audio events to be sent over to the cast sender via RTCP. | 
| ReceiverRtcpEventSubscriber event_subscriber_; | 
|  | 
| -  scoped_ptr<Framer> framer_; | 
| const transport::VideoCodec codec_; | 
| -  base::TimeDelta target_delay_delta_; | 
| -  base::TimeDelta frame_delay_; | 
| -  scoped_ptr<LocalRtpVideoFeedback> incoming_payload_feedback_; | 
| -  scoped_ptr<Rtcp> rtcp_; | 
| +  const base::TimeDelta target_delay_delta_; | 
| +  const base::TimeDelta expected_frame_duration_; | 
| +  Framer framer_; | 
| +  scoped_ptr<VideoDecoder> video_decoder_; | 
| +  Rtcp rtcp_; | 
| base::TimeDelta time_offset_;  // Sender-receiver offset estimation. | 
| int time_offset_counter_; | 
| -  transport::TransportEncryptionHandler decryptor_; | 
| -  std::list<VideoFrameEncodedCallback> queued_encoded_callbacks_; | 
| bool time_incoming_packet_updated_; | 
| base::TimeTicks time_incoming_packet_; | 
| uint32 incoming_rtp_timestamp_; | 
| -  base::TimeTicks last_render_time_; | 
| -  SetTargetDelayCallback target_delay_cb_; | 
| +  transport::TransportEncryptionHandler decryptor_; | 
| + | 
| +  // Outstanding callbacks to run to deliver on client requests for frames. | 
| +  std::list<VideoFrameEncodedCallback> frame_request_queue_; | 
| + | 
| +  // True while there's an outstanding task to re-invoke | 
| +  // EmitAvailableEncodedFrames(). | 
| +  bool is_waiting_for_consecutive_frame_; | 
|  | 
| // This mapping allows us to log kVideoAckSent as a frame event. In addition | 
| // it allows the event to be transmitted via RTCP. | 
|  |