Commit af6f4678 authored by hubbe's avatar hubbe Committed by Commit bot

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}
parent 99ae5386
......@@ -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
......@@ -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_;
......
......@@ -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
......@@ -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_;
......
......@@ -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
......@@ -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_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment