| // Copyright 2013 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef MEDIA_CAST_VIDEO_SENDER_VIDEO_SENDER_H_ |
| #define MEDIA_CAST_VIDEO_SENDER_VIDEO_SENDER_H_ |
| |
| #include "base/callback.h" |
| #include "base/memory/ref_counted.h" |
| #include "base/memory/scoped_ptr.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/threading/non_thread_safe.h" |
| #include "base/time/tick_clock.h" |
| #include "base/time/time.h" |
| #include "media/cast/cast_config.h" |
| #include "media/cast/cast_environment.h" |
| #include "media/cast/congestion_control/congestion_control.h" |
| #include "media/cast/rtcp/rtcp.h" |
| #include "media/cast/rtp_sender/rtp_sender.h" |
| |
| namespace crypto { |
| class Encryptor; |
| } |
| |
| namespace media { |
| class VideoFrame; |
| } |
| |
| namespace media { |
| namespace cast { |
| |
| class VideoEncoder; |
| class LocalRtcpVideoSenderFeedback; |
| class LocalRtpVideoSenderStatistics; |
| class LocalVideoEncoderCallback; |
| class PacedPacketSender; |
| |
| // Not thread safe. Only called from the main cast thread. |
| // This class owns all objects related to sending video, objects that create RTP |
| // packets, congestion control, video encoder, parsing and sending of |
| // RTCP packets. |
| // Additionally it posts a bunch of delayed tasks to the main thread for various |
| // timeouts. |
| class VideoSender : public base::NonThreadSafe, |
| public base::SupportsWeakPtr<VideoSender> { |
| public: |
| VideoSender(scoped_refptr<CastEnvironment> cast_environment, |
| const VideoSenderConfig& video_config, |
| VideoEncoderController* const video_encoder_controller, |
| PacedPacketSender* const paced_packet_sender); |
| |
| virtual ~VideoSender(); |
| |
| // The video_frame must be valid until the closure callback is called. |
| // The closure callback is called from the video encoder thread as soon as |
| // the encoder is done with the frame; it does not mean that the encoded frame |
| // has been sent out. |
| void InsertRawVideoFrame( |
| const scoped_refptr<media::VideoFrame>& video_frame, |
| const base::TimeTicks& capture_time); |
| |
| // The video_frame must be valid until the closure callback is called. |
| // The closure callback is called from the main thread as soon as |
| // the cast sender is done with the frame; it does not mean that the encoded |
| // frame has been sent out. |
| void InsertCodedVideoFrame(const EncodedVideoFrame* video_frame, |
| const base::TimeTicks& capture_time, |
| const base::Closure callback); |
| |
| // Only called from the main cast thread. |
| void IncomingRtcpPacket(const uint8* packet, size_t length, |
| const base::Closure callback); |
| |
| protected: |
| // Protected for testability. |
| void OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback); |
| |
| private: |
| friend class LocalRtcpVideoSenderFeedback; |
| |
| // Schedule when we should send the next RTPC report, |
| // via a PostDelayedTask to the main cast thread. |
| void ScheduleNextRtcpReport(); |
| void SendRtcpReport(); |
| |
| // Schedule when we should check that we have received an acknowledgment, or a |
| // loss report from our remote peer. If we have not heard back from our remote |
| // peer we speculatively resend our oldest unacknowledged frame (the whole |
| // frame). Note for this to happen we need to lose all pending packets (in |
| // normal operation 3 full frames), hence this is the last resort to prevent |
| // us getting stuck after a long outage. |
| void ScheduleNextResendCheck(); |
| void ResendCheck(); |
| |
| // Monitor how many frames that are silently dropped by the video sender |
| // per time unit. |
| void ScheduleNextSkippedFramesCheck(); |
| void SkippedFramesCheck(); |
| |
| void SendEncodedVideoFrame(const EncodedVideoFrame* video_frame, |
| const base::TimeTicks& capture_time); |
| void ResendFrame(uint32 resend_frame_id); |
| void ReceivedAck(uint32 acked_frame_id); |
| void UpdateFramesInFlight(); |
| |
| void SendEncodedVideoFrameMainThread( |
| scoped_ptr<EncodedVideoFrame> video_frame, |
| const base::TimeTicks& capture_time); |
| |
| void InitializeTimers(); |
| |
| // Caller must allocate the destination |encrypted_video_frame| the data |
| // member will be resized to hold the encrypted size. |
| bool EncryptVideoFrame(const EncodedVideoFrame& encoded_frame, |
| EncodedVideoFrame* encrypted_video_frame); |
| |
| const base::TimeDelta rtp_max_delay_; |
| const int max_frame_rate_; |
| |
| scoped_refptr<CastEnvironment> cast_environment_; |
| scoped_ptr<LocalRtcpVideoSenderFeedback> rtcp_feedback_; |
| scoped_ptr<LocalRtpVideoSenderStatistics> rtp_video_sender_statistics_; |
| scoped_ptr<VideoEncoder> video_encoder_; |
| scoped_ptr<Rtcp> rtcp_; |
| scoped_ptr<RtpSender> rtp_sender_; |
| VideoEncoderController* video_encoder_controller_; |
| uint8 max_unacked_frames_; |
| scoped_ptr<crypto::Encryptor> encryptor_; |
| std::string iv_mask_; |
| int last_acked_frame_id_; |
| int last_sent_frame_id_; |
| int duplicate_ack_; |
| base::TimeTicks last_send_time_; |
| base::TimeTicks last_checked_skip_count_time_; |
| int last_skip_count_; |
| CongestionControl congestion_control_; |
| |
| bool initialized_; |
| base::WeakPtrFactory<VideoSender> weak_factory_; |
| |
| DISALLOW_COPY_AND_ASSIGN(VideoSender); |
| }; |
| |
| } // namespace cast |
| } // namespace media |
| |
| #endif // MEDIA_CAST_VIDEO_SENDER_VIDEO_SENDER_H_ |
| |