} // namespace
+class BitrateAggregator {
+ public:
+ explicit BitrateAggregator(BitrateStatisticsObserver* bitrate_callback)
+ : callback_(bitrate_callback),
+ total_bitrate_observer_(*this),
+ retransmit_bitrate_observer_(*this),
+ ssrc_(0) {}
+
+ void OnStatsUpdated() const {
+ if (callback_)
+ callback_->Notify(total_bitrate_observer_.statistics(),
+ retransmit_bitrate_observer_.statistics(),
+ ssrc_);
+ }
+
+ Bitrate::Observer* total_bitrate_observer() {
+ return &total_bitrate_observer_;
+ }
+ Bitrate::Observer* retransmit_bitrate_observer() {
+ return &retransmit_bitrate_observer_;
+ }
+
+ void set_ssrc(uint32_t ssrc) { ssrc_ = ssrc; }
+
+ private:
+ // We assume that these observers are called on the same thread, which is
+ // true for RtpSender as they are called on the Process thread.
+ class BitrateObserver : public Bitrate::Observer {
+ public:
+ explicit BitrateObserver(const BitrateAggregator& aggregator)
+ : aggregator_(aggregator) {}
+
+ // Implements Bitrate::Observer.
+ virtual void BitrateUpdated(const BitrateStatistics& stats) OVERRIDE {
+ statistics_ = stats;
+ aggregator_.OnStatsUpdated();
+ }
+
+ BitrateStatistics statistics() const { return statistics_; }
+
+ private:
+ BitrateStatistics statistics_;
+ const BitrateAggregator& aggregator_;
+ };
+
+ BitrateStatisticsObserver* const callback_;
+ BitrateObserver total_bitrate_observer_;
+ BitrateObserver retransmit_bitrate_observer_;
+ uint32_t ssrc_;
+};
+
RTPSender::RTPSender(const int32_t id,
const bool audio,
Clock* clock,
FrameCountObserver* frame_count_observer,
SendSideDelayObserver* send_side_delay_observer)
: clock_(clock),
- bitrate_sent_(clock, this),
+ // TODO(holmer): Remove this conversion when we remove the use of
+ // TickTime.
+ clock_delta_ms_(clock_->TimeInMilliseconds() -
+ TickTime::MillisecondTimestamp()),
+ bitrates_(new BitrateAggregator(bitrate_callback)),
+ total_bitrate_sent_(clock, bitrates_->total_bitrate_observer()),
id_(id),
audio_configured_(audio),
audio_(NULL),
video_(NULL),
paced_sender_(paced_sender),
+ last_capture_time_ms_sent_(0),
send_critsect_(CriticalSectionWrapper::CreateCriticalSection()),
transport_(transport),
sending_media_(true), // Default to sending media.
// NACK.
nack_byte_count_times_(),
nack_byte_count_(),
- nack_bitrate_(clock, NULL),
+ nack_bitrate_(clock, bitrates_->retransmit_bitrate_observer()),
packet_history_(clock),
// Statistics
statistics_crit_(CriticalSectionWrapper::CreateCriticalSection()),
rtp_stats_callback_(NULL),
- bitrate_callback_(bitrate_callback),
frame_count_observer_(frame_count_observer),
send_side_delay_observer_(send_side_delay_observer),
// RTP variables
srand(static_cast<uint32_t>(clock_->TimeInMilliseconds()));
ssrc_ = ssrc_db_.CreateSSRC(); // Can't be 0.
ssrc_rtx_ = ssrc_db_.CreateSSRC(); // Can't be 0.
+ bitrates_->set_ssrc(ssrc_);
// Random start, 16 bits. Can't be 0.
sequence_number_rtx_ = static_cast<uint16_t>(rand() + 1) & 0x7FFF;
sequence_number_ = static_cast<uint16_t>(rand() + 1) & 0x7FFF;
}
uint16_t RTPSender::ActualSendBitrateKbit() const {
- return (uint16_t)(bitrate_sent_.BitrateNow() / 1000);
+ return (uint16_t)(total_bitrate_sent_.BitrateNow() / 1000);
}
uint32_t RTPSender::VideoBitrateSent() const {
}
// Convert from TickTime to Clock since capture_time_ms is based on
// TickTime.
- // TODO(holmer): Remove this conversion when we remove the use of TickTime.
- int64_t clock_delta_ms = clock_->TimeInMilliseconds() -
- TickTime::MillisecondTimestamp();
- if (!paced_sender_->SendPacket(PacedSender::kHighPriority,
- header.ssrc,
- header.sequenceNumber,
- capture_time_ms + clock_delta_ms,
- length - header.headerLength,
- true)) {
+ int64_t corrected_capture_tims_ms = capture_time_ms + clock_delta_ms_;
+ if (!paced_sender_->SendPacket(
+ PacedSender::kHighPriority, header.ssrc, header.sequenceNumber,
+ corrected_capture_tims_ms, length - header.headerLength, true)) {
// We can't send the packet right now.
// We will be called when it is time.
return length;
RtpUtility::RtpHeaderParser rtp_parser(buffer, length);
RTPHeader rtp_header;
rtp_parser.Parse(rtp_header);
+ if (!is_retransmit && rtp_header.markerBit) {
+ TRACE_EVENT_ASYNC_END0("webrtc_rtp", "PacedSend", capture_time_ms);
+ }
+
TRACE_EVENT_INSTANT2("webrtc_rtp", "PrepareAndSendPacket",
"timestamp", rtp_header.timestamp,
"seqnum", rtp_header.sequenceNumber);
counters = &rtp_stats_;
}
- bitrate_sent_.Update(size);
+ total_bitrate_sent_.Update(size);
++counters->packets;
if (IsFecPacket(buffer, header)) {
++counters->fec_packets;
}
if (paced_sender_ && storage != kDontStore) {
- int64_t clock_delta_ms = clock_->TimeInMilliseconds() -
- TickTime::MillisecondTimestamp();
+ // Correct offset between implementations of millisecond time stamps in
+ // TickTime and Clock.
+ int64_t corrected_time_ms = capture_time_ms + clock_delta_ms_;
if (!paced_sender_->SendPacket(priority, rtp_header.ssrc,
- rtp_header.sequenceNumber,
- capture_time_ms + clock_delta_ms,
+ rtp_header.sequenceNumber, corrected_time_ms,
payload_length, false)) {
+ if (last_capture_time_ms_sent_ == 0 ||
+ corrected_time_ms > last_capture_time_ms_sent_) {
+ last_capture_time_ms_sent_ = corrected_time_ms;
+ TRACE_EVENT_ASYNC_BEGIN1("webrtc_rtp", "PacedSend", corrected_time_ms,
+ "capture_time_ms", corrected_time_ms);
+ }
// We can't send the packet right now.
// We will be called when it is time.
return 0;
uint32_t length = payload_length + rtp_header_length;
if (!SendPacketToNetwork(buffer, length))
return -1;
- assert(payload_length - rtp_header.paddingLength > 0);
{
CriticalSectionScoped lock(send_critsect_);
media_has_been_sent_ = true;
void RTPSender::ProcessBitrate() {
CriticalSectionScoped cs(send_critsect_);
- bitrate_sent_.Process();
+ total_bitrate_sent_.Process();
nack_bitrate_.Process();
if (audio_configured_) {
return;
// Generate a new SSRC.
ssrc_db_.ReturnSSRC(ssrc_);
ssrc_ = ssrc_db_.CreateSSRC(); // Can't be 0.
+ bitrates_->set_ssrc(ssrc_);
}
// Don't initialize seq number if SSRC passed externally.
if (!sequence_number_forced_ && !ssrc_forced_) {
return 0;
}
ssrc_ = ssrc_db_.CreateSSRC(); // Can't be 0.
+ bitrates_->set_ssrc(ssrc_);
return ssrc_;
}
ssrc_db_.ReturnSSRC(ssrc_);
ssrc_db_.RegisterSSRC(ssrc);
ssrc_ = ssrc;
+ bitrates_->set_ssrc(ssrc_);
if (!sequence_number_forced_) {
sequence_number_ =
rand() / (RAND_MAX / MAX_INIT_RTP_SEQ_NUMBER); // NOLINT
return rtp_stats_callback_;
}
-uint32_t RTPSender::BitrateSent() const { return bitrate_sent_.BitrateLast(); }
-
-void RTPSender::BitrateUpdated(const BitrateStatistics& stats) {
- uint32_t ssrc;
- {
- CriticalSectionScoped ssrc_lock(send_critsect_);
- ssrc = ssrc_;
- }
- if (bitrate_callback_) {
- bitrate_callback_->Notify(stats, ssrc);
- }
+uint32_t RTPSender::BitrateSent() const {
+ return total_bitrate_sent_.BitrateLast();
}
void RTPSender::SetRtpState(const RtpState& rtp_state) {