diff options
author | hubbe <hubbe@chromium.org> | 2014-08-28 16:33:53 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-08-28 23:35:29 +0000 |
commit | af6f467869648ac5e54a738bbaf43f4f1cf22842 (patch) | |
tree | 47d51786f1d1dca506a07af7d3a8e6902cde07e6 | |
parent | 99ae5386b85f81eb7ae3d811c240535b721017b8 (diff) | |
download | chromium_src-af6f467869648ac5e54a738bbaf43f4f1cf22842.zip chromium_src-af6f467869648ac5e54a738bbaf43f4f1cf22842.tar.gz chromium_src-af6f467869648ac5e54a738bbaf43f4f1cf22842.tar.bz2 |
Move common code and variables from audio/video sender to frame sender.
More cleanup to come.
BUG=406622
Review URL: https://codereview.chromium.org/514263002
Cr-Commit-Position: refs/heads/master@{#292496}
-rw-r--r-- | media/cast/sender/audio_sender.cc | 48 | ||||
-rw-r--r-- | media/cast/sender/audio_sender.h | 42 | ||||
-rw-r--r-- | media/cast/sender/frame_sender.cc | 45 | ||||
-rw-r--r-- | media/cast/sender/frame_sender.h | 43 | ||||
-rw-r--r-- | media/cast/sender/video_sender.cc | 49 | ||||
-rw-r--r-- | media/cast/sender/video_sender.h | 42 |
6 files changed, 90 insertions, 179 deletions
diff --git a/media/cast/sender/audio_sender.cc b/media/cast/sender/audio_sender.cc index 4bf93b3..040bc62 100644 --- a/media/cast/sender/audio_sender.cc +++ b/media/cast/sender/audio_sender.cc @@ -16,7 +16,6 @@ namespace cast { namespace { const int kNumAggressiveReportsSentAtStart = 100; -const int kMinSchedulingDelayMs = 1; // TODO(miu): This should be specified in AudioSenderConfig, but currently it is // fixed to 100 FPS (i.e., 10 ms per frame), and AudioEncoder assumes this as @@ -37,12 +36,8 @@ AudioSender::AudioSender(scoped_refptr<CastEnvironment> cast_environment, kAudioFrameRate * 2.0, // We lie to increase max outstanding frames. audio_config.target_playout_delay), configured_encoder_bitrate_(audio_config.bitrate), - num_aggressive_rtcp_reports_sent_(0), - last_sent_frame_id_(0), - latest_acked_frame_id_(0), - duplicate_ack_counter_(0), - cast_initialization_status_(STATUS_AUDIO_UNINITIALIZED), weak_factory_(this) { + cast_initialization_status_ = STATUS_AUDIO_UNINITIALIZED; VLOG(1) << "max_unacked_frames " << max_unacked_frames_; DCHECK_GT(max_unacked_frames_, 0); @@ -76,7 +71,6 @@ AudioSender::AudioSender(scoped_refptr<CastEnvironment> cast_environment, base::Bind(&AudioSender::OnReceivedCastFeedback, weak_factory_.GetWeakPtr()), base::Bind(&AudioSender::OnReceivedRtt, weak_factory_.GetWeakPtr())); - memset(frame_id_to_rtp_timestamp_, 0, sizeof(frame_id_to_rtp_timestamp_)); } AudioSender::~AudioSender() {} @@ -149,37 +143,6 @@ void AudioSender::SendEncodedAudioFrame( transport_sender_->InsertCodedAudioFrame(*encoded_frame); } -void AudioSender::ScheduleNextResendCheck() { - DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); - DCHECK(!last_send_time_.is_null()); - base::TimeDelta time_to_next = - last_send_time_ - cast_environment_->Clock()->NowTicks() + - target_playout_delay_; - time_to_next = std::max( - time_to_next, base::TimeDelta::FromMilliseconds(kMinSchedulingDelayMs)); - cast_environment_->PostDelayedTask( - CastEnvironment::MAIN, - FROM_HERE, - base::Bind(&AudioSender::ResendCheck, weak_factory_.GetWeakPtr()), - time_to_next); -} - -void AudioSender::ResendCheck() { - DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); - DCHECK(!last_send_time_.is_null()); - const base::TimeDelta time_since_last_send = - cast_environment_->Clock()->NowTicks() - last_send_time_; - if (time_since_last_send > target_playout_delay_) { - if (latest_acked_frame_id_ == last_sent_frame_id_) { - // Last frame acked, no point in doing anything - } else { - VLOG(1) << "ACK timeout; last acked frame: " << latest_acked_frame_id_; - ResendForKickstart(); - } - } - ScheduleNextResendCheck(); -} - void AudioSender::OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback) { DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); @@ -257,14 +220,5 @@ bool AudioSender::AreTooManyFramesInFlight() const { return frames_in_flight >= max_unacked_frames_; } -void AudioSender::ResendForKickstart() { - DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); - DCHECK(!last_send_time_.is_null()); - VLOG(1) << "Resending last packet of frame " << last_sent_frame_id_ - << " to kick-start."; - last_send_time_ = cast_environment_->Clock()->NowTicks(); - transport_sender_->ResendFrameForKickstart(ssrc_, last_sent_frame_id_); -} - } // namespace cast } // namespace media diff --git a/media/cast/sender/audio_sender.h b/media/cast/sender/audio_sender.h index e07b892..4ca539b 100644 --- a/media/cast/sender/audio_sender.h +++ b/media/cast/sender/audio_sender.h @@ -55,15 +55,6 @@ class AudioSender : public FrameSender, void OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback); private: - // Schedule and execute periodic checks for re-sending packets. If no - // acknowledgements have been received for "too long," AudioSender will - // speculatively re-send certain packets of an unacked frame to kick-start - // re-transmission. This is a last resort tactic to prevent the session from - // getting stuck after a long outage. - void ScheduleNextResendCheck(); - void ResendCheck(); - void ResendForKickstart(); - // Returns true if there are too many frames in flight, as defined by the // configured target playout delay plus simple logic. When this is true, // InsertAudio() will silenty drop frames instead of sending them to the audio @@ -77,39 +68,6 @@ class AudioSender : public FrameSender, scoped_ptr<AudioEncoder> audio_encoder_; const int configured_encoder_bitrate_; - // Counts how many RTCP reports are being "aggressively" sent (i.e., one per - // frame) at the start of the session. Once a threshold is reached, RTCP - // reports are instead sent at the configured interval + random drift. - int num_aggressive_rtcp_reports_sent_; - - // This is "null" until the first frame is sent. Thereafter, this tracks the - // last time any frame was sent or re-sent. - base::TimeTicks last_send_time_; - - // The ID of the last frame sent. Logic throughout AudioSender assumes this - // can safely wrap-around. This member is invalid until - // |!last_send_time_.is_null()|. - uint32 last_sent_frame_id_; - - // The ID of the latest (not necessarily the last) frame that has been - // acknowledged. Logic throughout AudioSender assumes this can safely - // wrap-around. This member is invalid until |!last_send_time_.is_null()|. - uint32 latest_acked_frame_id_; - - // Counts the number of duplicate ACK that are being received. When this - // number reaches a threshold, the sender will take this as a sign that the - // receiver hasn't yet received the first packet of the next frame. In this - // case, AudioSender will trigger a re-send of the next frame. - int duplicate_ack_counter_; - - // If this sender is ready for use, this is STATUS_AUDIO_INITIALIZED. - CastInitializationStatus cast_initialization_status_; - - // This is a "good enough" mapping for finding the RTP timestamp associated - // with a video frame. The key is the lowest 8 bits of frame id (which is - // what is sent via RTCP). This map is used for logging purposes. - RtpTimestamp frame_id_to_rtp_timestamp_[256]; - // NOTE: Weak pointers must be invalidated before all other member variables. base::WeakPtrFactory<AudioSender> weak_factory_; diff --git a/media/cast/sender/frame_sender.cc b/media/cast/sender/frame_sender.cc index b531a06..61f8b1a 100644 --- a/media/cast/sender/frame_sender.cc +++ b/media/cast/sender/frame_sender.cc @@ -24,9 +24,14 @@ FrameSender::FrameSender(scoped_refptr<CastEnvironment> cast_environment, rtt_available_(false), rtcp_interval_(rtcp_interval), max_frame_rate_(max_frame_rate), + num_aggressive_rtcp_reports_sent_(0), + last_sent_frame_id_(0), + latest_acked_frame_id_(0), + duplicate_ack_counter_(0), weak_factory_(this) { SetTargetPlayoutDelay(playout_delay); send_target_playout_delay_ = false; + memset(frame_id_to_rtp_timestamp_, 0, sizeof(frame_id_to_rtp_timestamp_)); } FrameSender::~FrameSender() { @@ -84,5 +89,45 @@ void FrameSender::SetTargetPlayoutDelay( send_target_playout_delay_ = true; } +void FrameSender::ResendCheck() { + DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); + DCHECK(!last_send_time_.is_null()); + const base::TimeDelta time_since_last_send = + cast_environment_->Clock()->NowTicks() - last_send_time_; + if (time_since_last_send > target_playout_delay_) { + if (latest_acked_frame_id_ == last_sent_frame_id_) { + // Last frame acked, no point in doing anything + } else { + VLOG(1) << "ACK timeout; last acked frame: " << latest_acked_frame_id_; + ResendForKickstart(); + } + } + ScheduleNextResendCheck(); +} + +void FrameSender::ScheduleNextResendCheck() { + DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); + DCHECK(!last_send_time_.is_null()); + base::TimeDelta time_to_next = + last_send_time_ - cast_environment_->Clock()->NowTicks() + + target_playout_delay_; + time_to_next = std::max( + time_to_next, base::TimeDelta::FromMilliseconds(kMinSchedulingDelayMs)); + cast_environment_->PostDelayedTask( + CastEnvironment::MAIN, + FROM_HERE, + base::Bind(&FrameSender::ResendCheck, weak_factory_.GetWeakPtr()), + time_to_next); +} + +void FrameSender::ResendForKickstart() { + DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); + DCHECK(!last_send_time_.is_null()); + VLOG(1) << "Resending last packet of frame " << last_sent_frame_id_ + << " to kick-start."; + last_send_time_ = cast_environment_->Clock()->NowTicks(); + transport_sender_->ResendFrameForKickstart(ssrc_, last_sent_frame_id_); +} + } // namespace cast } // namespace media diff --git a/media/cast/sender/frame_sender.h b/media/cast/sender/frame_sender.h index 5da392796..09211da 100644 --- a/media/cast/sender/frame_sender.h +++ b/media/cast/sender/frame_sender.h @@ -74,6 +74,15 @@ class FrameSender { base::TimeDelta max_rtt_; protected: + // Schedule and execute periodic checks for re-sending packets. If no + // acknowledgements have been received for "too long," AudioSender will + // speculatively re-send certain packets of an unacked frame to kick-start + // re-transmission. This is a last resort tactic to prevent the session from + // getting stuck after a long outage. + void ScheduleNextResendCheck(); + void ResendCheck(); + void ResendForKickstart(); + const base::TimeDelta rtcp_interval_; // The total amount of time between a frame's capture/recording on the sender @@ -94,6 +103,40 @@ class FrameSender { // new frames shall halt. int max_unacked_frames_; + // Counts how many RTCP reports are being "aggressively" sent (i.e., one per + // frame) at the start of the session. Once a threshold is reached, RTCP + // reports are instead sent at the configured interval + random drift. + int num_aggressive_rtcp_reports_sent_; + + // This is "null" until the first frame is sent. Thereafter, this tracks the + // last time any frame was sent or re-sent. + base::TimeTicks last_send_time_; + + // The ID of the last frame sent. Logic throughout AudioSender assumes this + // can safely wrap-around. This member is invalid until + // |!last_send_time_.is_null()|. + uint32 last_sent_frame_id_; + + // The ID of the latest (not necessarily the last) frame that has been + // acknowledged. Logic throughout AudioSender assumes this can safely + // wrap-around. This member is invalid until |!last_send_time_.is_null()|. + uint32 latest_acked_frame_id_; + + // Counts the number of duplicate ACK that are being received. When this + // number reaches a threshold, the sender will take this as a sign that the + // receiver hasn't yet received the first packet of the next frame. In this + // case, VideoSender will trigger a re-send of the next frame. + int duplicate_ack_counter_; + + // If this sender is ready for use, this is STATUS_AUDIO_INITIALIZED or + // STATUS_VIDEO_INITIALIZED. + CastInitializationStatus cast_initialization_status_; + + // This is a "good enough" mapping for finding the RTP timestamp associated + // with a video frame. The key is the lowest 8 bits of frame id (which is + // what is sent via RTCP). This map is used for logging purposes. + RtpTimestamp frame_id_to_rtp_timestamp_[256]; + private: // NOTE: Weak pointers must be invalidated before all other member variables. base::WeakPtrFactory<FrameSender> weak_factory_; diff --git a/media/cast/sender/video_sender.cc b/media/cast/sender/video_sender.cc index f0e3a14..3fc5f6c 100644 --- a/media/cast/sender/video_sender.cc +++ b/media/cast/sender/video_sender.cc @@ -20,7 +20,6 @@ namespace media { namespace cast { const int kNumAggressiveReportsSentAtStart = 100; -const int kMinSchedulingDelayMs = 1; namespace { @@ -51,17 +50,13 @@ VideoSender::VideoSender( video_config.max_frame_rate, video_config.target_playout_delay), fixed_bitrate_(GetFixedBitrate(video_config)), - num_aggressive_rtcp_reports_sent_(0), frames_in_encoder_(0), - last_sent_frame_id_(0), - latest_acked_frame_id_(0), - duplicate_ack_counter_(0), congestion_control_(cast_environment->Clock(), video_config.max_bitrate, video_config.min_bitrate, max_unacked_frames_), - cast_initialization_status_(STATUS_VIDEO_UNINITIALIZED), weak_factory_(this) { + cast_initialization_status_ = STATUS_VIDEO_UNINITIALIZED; VLOG(1) << "max_unacked_frames is " << max_unacked_frames_ << " for target_playout_delay=" << target_playout_delay_.InMilliseconds() << " ms" @@ -92,8 +87,6 @@ VideoSender::VideoSender( base::Bind(&VideoSender::OnReceivedCastFeedback, weak_factory_.GetWeakPtr()), base::Bind(&VideoSender::OnReceivedRtt, weak_factory_.GetWeakPtr())); - - memset(frame_id_to_rtp_timestamp_, 0, sizeof(frame_id_to_rtp_timestamp_)); } VideoSender::~VideoSender() { @@ -223,37 +216,6 @@ void VideoSender::SendEncodedVideoFrame( transport_sender_->InsertCodedVideoFrame(*encoded_frame); } -void VideoSender::ResendCheck() { - DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); - DCHECK(!last_send_time_.is_null()); - const base::TimeDelta time_since_last_send = - cast_environment_->Clock()->NowTicks() - last_send_time_; - if (time_since_last_send > target_playout_delay_) { - if (latest_acked_frame_id_ == last_sent_frame_id_) { - // Last frame acked, no point in doing anything - } else { - VLOG(1) << "ACK timeout; last acked frame: " << latest_acked_frame_id_; - ResendForKickstart(); - } - } - ScheduleNextResendCheck(); -} - -void VideoSender::ScheduleNextResendCheck() { - DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); - DCHECK(!last_send_time_.is_null()); - base::TimeDelta time_to_next = - last_send_time_ - cast_environment_->Clock()->NowTicks() + - target_playout_delay_; - time_to_next = std::max( - time_to_next, base::TimeDelta::FromMilliseconds(kMinSchedulingDelayMs)); - cast_environment_->PostDelayedTask( - CastEnvironment::MAIN, - FROM_HERE, - base::Bind(&VideoSender::ResendCheck, weak_factory_.GetWeakPtr()), - time_to_next); -} - void VideoSender::OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback) { DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); @@ -352,14 +314,5 @@ bool VideoSender::AreTooManyFramesInFlight() const { return frames_in_flight >= max_unacked_frames_; } -void VideoSender::ResendForKickstart() { - DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); - DCHECK(!last_send_time_.is_null()); - VLOG(1) << "Resending last packet of frame " << last_sent_frame_id_ - << " to kick-start."; - last_send_time_ = cast_environment_->Clock()->NowTicks(); - transport_sender_->ResendFrameForKickstart(ssrc_, last_sent_frame_id_); -} - } // namespace cast } // namespace media diff --git a/media/cast/sender/video_sender.h b/media/cast/sender/video_sender.h index ebada4d..5fe3261 100644 --- a/media/cast/sender/video_sender.h +++ b/media/cast/sender/video_sender.h @@ -61,15 +61,6 @@ class VideoSender : public FrameSender, void OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback); private: - // Schedule and execute periodic checks for re-sending packets. If no - // acknowledgements have been received for "too long," VideoSender will - // speculatively re-send certain packets of an unacked frame to kick-start - // re-transmission. This is a last resort tactic to prevent the session from - // getting stuck after a long outage. - void ScheduleNextResendCheck(); - void ResendCheck(); - void ResendForKickstart(); - // Returns true if there are too many frames in flight, as defined by the // configured target playout delay plus simple logic. When this is true, // InsertRawVideoFrame() will silenty drop frames instead of sending them to @@ -89,47 +80,14 @@ class VideoSender : public FrameSender, // a hardware-based encoder. scoped_ptr<VideoEncoder> video_encoder_; - // Counts how many RTCP reports are being "aggressively" sent (i.e., one per - // frame) at the start of the session. Once a threshold is reached, RTCP - // reports are instead sent at the configured interval + random drift. - int num_aggressive_rtcp_reports_sent_; - // The number of frames currently being processed in |video_encoder_|. int frames_in_encoder_; - // This is "null" until the first frame is sent. Thereafter, this tracks the - // last time any frame was sent or re-sent. - base::TimeTicks last_send_time_; - - // The ID of the last frame sent. Logic throughout VideoSender assumes this - // can safely wrap-around. This member is invalid until - // |!last_send_time_.is_null()|. - uint32 last_sent_frame_id_; - - // The ID of the latest (not necessarily the last) frame that has been - // acknowledged. Logic throughout VideoSender assumes this can safely - // wrap-around. This member is invalid until |!last_send_time_.is_null()|. - uint32 latest_acked_frame_id_; - - // Counts the number of duplicate ACK that are being received. When this - // number reaches a threshold, the sender will take this as a sign that the - // receiver hasn't yet received the first packet of the next frame. In this - // case, VideoSender will trigger a re-send of the next frame. - int duplicate_ack_counter_; - // When we get close to the max number of un-acked frames, we set lower // the bitrate drastically to ensure that we catch up. Without this we // risk getting stuck in a catch-up state forever. CongestionControl congestion_control_; - // If this sender is ready for use, this is STATUS_VIDEO_INITIALIZED. - CastInitializationStatus cast_initialization_status_; - - // This is a "good enough" mapping for finding the RTP timestamp associated - // with a video frame. The key is the lowest 8 bits of frame id (which is - // what is sent via RTCP). This map is used for logging purposes. - RtpTimestamp frame_id_to_rtp_timestamp_[256]; - // NOTE: Weak pointers must be invalidated before all other member variables. base::WeakPtrFactory<VideoSender> weak_factory_; |