| 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.
|
|
|