// 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/net/rtp_sender/rtp_sender.h"
#include "media/cast/rtcp/rtcp.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_