Chromium Code Reviews| Index: webrtc/modules/rtp_rtcp/source/rtcp_sender.cc |
| diff --git a/webrtc/modules/rtp_rtcp/source/rtcp_sender.cc b/webrtc/modules/rtp_rtcp/source/rtcp_sender.cc |
| index 99292994c1f5b34f3358901f9d84d4b96bdcaa89..323a4054d92a101cad05a820b683d673693fd201 100644 |
| --- a/webrtc/modules/rtp_rtcp/source/rtcp_sender.cc |
| +++ b/webrtc/modules/rtp_rtcp/source/rtcp_sender.cc |
| @@ -76,61 +76,61 @@ RTCPSender::FeedbackState::FeedbackState() |
| module(nullptr) { |
| } |
| -struct RTCPSender::RtcpContext { |
| - RtcpContext(const FeedbackState& feedback_state, |
| - int32_t nack_size, |
| - const uint16_t* nack_list, |
| - bool repeat, |
| - uint64_t picture_id, |
| - uint8_t* buffer, |
| - uint32_t buffer_size) |
| - : feedback_state(feedback_state), |
| - nack_size(nack_size), |
| - nack_list(nack_list), |
| - repeat(repeat), |
| - picture_id(picture_id), |
| - buffer(buffer), |
| - buffer_size(buffer_size), |
| - ntp_sec(0), |
| - ntp_frac(0), |
| - position(0) {} |
| - |
| - uint8_t* AllocateData(uint32_t bytes) { |
| - RTC_DCHECK_LE(position + bytes, buffer_size); |
| - uint8_t* ptr = &buffer[position]; |
| - position += bytes; |
| - return ptr; |
| +class PacketContainer : public rtcp::Empty, |
| + public rtcp::RtcpPacket::PacketReadyCallback { |
| + public: |
| + explicit PacketContainer(Transport* transport) |
| + : transport_(transport), bytes_sent_(0) {} |
| + virtual ~PacketContainer() { |
| + for (RtcpPacket* packet : appended_packets_) |
| + delete packet; |
| } |
| - const FeedbackState& feedback_state; |
| - int32_t nack_size; |
| - const uint16_t* nack_list; |
| - bool repeat; |
| - uint64_t picture_id; |
| - uint8_t* buffer; |
| - uint32_t buffer_size; |
| - uint32_t ntp_sec; |
| - uint32_t ntp_frac; |
| - uint32_t position; |
| -}; |
| - |
| -// TODO(sprang): Once all builders use RtcpPacket, call SendToNetwork() here. |
| -class RTCPSender::PacketBuiltCallback |
| - : public rtcp::RtcpPacket::PacketReadyCallback { |
| - public: |
| - PacketBuiltCallback(RtcpContext* context) : context_(context) {} |
| - virtual ~PacketBuiltCallback() {} |
| void OnPacketReady(uint8_t* data, size_t length) override { |
| - context_->position += length; |
| + if (transport_->SendRtcp(data, length)) |
| + bytes_sent_ += length; |
| } |
| - bool BuildPacket(const rtcp::RtcpPacket& packet) { |
| - return packet.BuildExternalBuffer( |
| - &context_->buffer[context_->position], |
| - context_->buffer_size - context_->position, this); |
| + |
| + size_t SendPackets() { |
| + rtcp::Empty::Build(this); |
| + return bytes_sent_; |
| } |
| private: |
| - RtcpContext* const context_; |
| + Transport* transport_; |
| + size_t bytes_sent_; |
| +}; |
| + |
| +class RTCPSender::RtcpContext { |
| + public: |
| + RtcpContext(const FeedbackState& feedback_state, |
| + int32_t nack_size, |
| + const uint16_t* nack_list, |
| + bool repeat, |
| + uint64_t picture_id, |
| + uint32_t ntp_sec, |
| + uint32_t ntp_frac, |
| + PacketContainer* container) |
| + : feedback_state_(feedback_state), |
| + nack_size_(nack_size), |
| + nack_list_(nack_list), |
| + repeat_(repeat), |
| + picture_id_(picture_id), |
| + ntp_sec_(ntp_sec), |
| + ntp_frac_(ntp_frac), |
| + container_(container) {} |
| + |
| + virtual ~RtcpContext() {} |
| + |
| + const FeedbackState& feedback_state_; |
| + const int32_t nack_size_; |
| + const uint16_t* nack_list_; |
| + const bool repeat_; |
| + const uint64_t picture_id_; |
| + const uint32_t ntp_sec_; |
| + const uint32_t ntp_frac_; |
| + |
| + PacketContainer* const container_; |
| }; |
| RTCPSender::RTCPSender( |
| @@ -473,15 +473,15 @@ int32_t RTCPSender::AddReportBlock(const RTCPReportBlock& report_block) { |
| return 0; |
| } |
| -RTCPSender::BuildResult RTCPSender::BuildSR(RtcpContext* ctx) { |
| +rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildSR(const RtcpContext& ctx) { |
| for (int i = (RTCP_NUMBER_OF_SR - 2); i >= 0; i--) { |
| // shift old |
| last_send_report_[i + 1] = last_send_report_[i]; |
| last_rtcp_time_[i + 1] = last_rtcp_time_[i]; |
| } |
| - last_rtcp_time_[0] = Clock::NtpToMs(ctx->ntp_sec, ctx->ntp_frac); |
| - last_send_report_[0] = (ctx->ntp_sec << 16) + (ctx->ntp_frac >> 16); |
| + last_rtcp_time_[0] = Clock::NtpToMs(ctx.ntp_sec_, ctx.ntp_frac_); |
| + last_send_report_[0] = (ctx.ntp_sec_ << 16) + (ctx.ntp_frac_ >> 16); |
| // The timestamp of this RTCP packet should be estimated as the timestamp of |
| // the frame being captured at this moment. We are calculating that |
| @@ -490,67 +490,52 @@ RTCPSender::BuildResult RTCPSender::BuildSR(RtcpContext* ctx) { |
| uint32_t rtp_timestamp = |
| start_timestamp_ + last_rtp_timestamp_ + |
| (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) * |
| - (ctx->feedback_state.frequency_hz / 1000); |
| + (ctx.feedback_state_.frequency_hz / 1000); |
| - rtcp::SenderReport report; |
| - report.From(ssrc_); |
| - report.WithNtpSec(ctx->ntp_sec); |
| - report.WithNtpFrac(ctx->ntp_frac); |
| - report.WithRtpTimestamp(rtp_timestamp); |
| - report.WithPacketCount(ctx->feedback_state.packets_sent); |
| - report.WithOctetCount(ctx->feedback_state.media_bytes_sent); |
| + rtcp::SenderReport* report = new rtcp::SenderReport(); |
| + report->From(ssrc_); |
| + report->WithNtpSec(ctx.ntp_sec_); |
| + report->WithNtpFrac(ctx.ntp_frac_); |
| + report->WithRtpTimestamp(rtp_timestamp); |
| + report->WithPacketCount(ctx.feedback_state_.packets_sent); |
| + report->WithOctetCount(ctx.feedback_state_.media_bytes_sent); |
| for (auto it : report_blocks_) |
| - report.WithReportBlock(it.second); |
| - |
| - PacketBuiltCallback callback(ctx); |
| - if (!callback.BuildPacket(report)) |
| - return BuildResult::kTruncated; |
| + report->WithReportBlock(it.second); |
| report_blocks_.clear(); |
| - return BuildResult::kSuccess; |
| + |
| + return rtc::scoped_ptr<rtcp::SenderReport>(report); |
| } |
| -RTCPSender::BuildResult RTCPSender::BuildSDES(RtcpContext* ctx) { |
| +rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildSDES( |
| + const RtcpContext& ctx) { |
| size_t length_cname = cname_.length(); |
| RTC_CHECK_LT(length_cname, static_cast<size_t>(RTCP_CNAME_SIZE)); |
| - rtcp::Sdes sdes; |
| - sdes.WithCName(ssrc_, cname_); |
| + rtcp::Sdes* sdes = new rtcp::Sdes(); |
| + sdes->WithCName(ssrc_, cname_); |
| for (const auto it : csrc_cnames_) |
| - sdes.WithCName(it.first, it.second); |
| - |
| - PacketBuiltCallback callback(ctx); |
| - if (!callback.BuildPacket(sdes)) |
| - return BuildResult::kTruncated; |
| + sdes->WithCName(it.first, it.second); |
| - return BuildResult::kSuccess; |
| + return rtc::scoped_ptr<rtcp::Sdes>(sdes); |
| } |
| -RTCPSender::BuildResult RTCPSender::BuildRR(RtcpContext* ctx) { |
| - rtcp::ReceiverReport report; |
| - report.From(ssrc_); |
| +rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildRR(const RtcpContext& ctx) { |
| + rtcp::ReceiverReport* report = new rtcp::ReceiverReport(); |
| + report->From(ssrc_); |
| for (auto it : report_blocks_) |
| - report.WithReportBlock(it.second); |
| - |
| - PacketBuiltCallback callback(ctx); |
| - if (!callback.BuildPacket(report)) |
| - return BuildResult::kTruncated; |
| + report->WithReportBlock(it.second); |
| report_blocks_.clear(); |
| - |
| - return BuildResult::kSuccess; |
| + return rtc::scoped_ptr<rtcp::ReceiverReport>(report); |
| } |
| -RTCPSender::BuildResult RTCPSender::BuildPLI(RtcpContext* ctx) { |
| - rtcp::Pli pli; |
| - pli.From(ssrc_); |
| - pli.To(remote_ssrc_); |
| - |
| - PacketBuiltCallback callback(ctx); |
| - if (!callback.BuildPacket(pli)) |
| - return BuildResult::kTruncated; |
| +rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildPLI(const RtcpContext& ctx) { |
| + rtcp::Pli* pli = new rtcp::Pli(); |
| + pli->From(ssrc_); |
| + pli->To(remote_ssrc_); |
| TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), |
| "RTCPSender::PLI"); |
| @@ -558,21 +543,17 @@ RTCPSender::BuildResult RTCPSender::BuildPLI(RtcpContext* ctx) { |
| TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount", |
| ssrc_, packet_type_counter_.pli_packets); |
| - return BuildResult::kSuccess; |
| + return rtc::scoped_ptr<rtcp::Pli>(pli); |
| } |
| -RTCPSender::BuildResult RTCPSender::BuildFIR(RtcpContext* ctx) { |
| - if (!ctx->repeat) |
| +rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildFIR(const RtcpContext& ctx) { |
| + if (!ctx.repeat_) |
| ++sequence_number_fir_; // Do not increase if repetition. |
| - rtcp::Fir fir; |
| - fir.From(ssrc_); |
| - fir.To(remote_ssrc_); |
| - fir.WithCommandSeqNum(sequence_number_fir_); |
| - |
| - PacketBuiltCallback callback(ctx); |
| - if (!callback.BuildPacket(fir)) |
| - return BuildResult::kTruncated; |
| + rtcp::Fir* fir = new rtcp::Fir(); |
| + fir->From(ssrc_); |
| + fir->To(remote_ssrc_); |
| + fir->WithCommandSeqNum(sequence_number_fir_); |
| TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), |
| "RTCPSender::FIR"); |
| @@ -580,7 +561,7 @@ RTCPSender::BuildResult RTCPSender::BuildFIR(RtcpContext* ctx) { |
| TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount", |
| ssrc_, packet_type_counter_.fir_packets); |
| - return BuildResult::kSuccess; |
| + return rtc::scoped_ptr<rtcp::Fir>(fir); |
| } |
| /* |
| @@ -590,20 +571,16 @@ RTCPSender::BuildResult RTCPSender::BuildFIR(RtcpContext* ctx) { |
| | First | Number | PictureID | |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| */ |
| -RTCPSender::BuildResult RTCPSender::BuildSLI(RtcpContext* ctx) { |
| - rtcp::Sli sli; |
| - sli.From(ssrc_); |
| - sli.To(remote_ssrc_); |
| +rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildSLI(const RtcpContext& ctx) { |
| + rtcp::Sli* sli = new rtcp::Sli(); |
| + sli->From(ssrc_); |
| + sli->To(remote_ssrc_); |
| // Crop picture id to 6 least significant bits. |
| - sli.WithPictureId(ctx->picture_id & 0x3F); |
| - sli.WithFirstMb(0); |
| - sli.WithNumberOfMb(0x1FFF); // 13 bits, only ones for now. |
| - |
| - PacketBuiltCallback callback(ctx); |
| - if (!callback.BuildPacket(sli)) |
| - return BuildResult::kTruncated; |
| + sli->WithPictureId(ctx.picture_id_ & 0x3F); |
| + sli->WithFirstMb(0); |
| + sli->WithNumberOfMb(0x1FFF); // 13 bits, only ones for now. |
| - return BuildResult::kSuccess; |
| + return rtc::scoped_ptr<rtcp::Sli>(sli); |
| } |
| /* |
| @@ -618,38 +595,32 @@ RTCPSender::BuildResult RTCPSender::BuildSLI(RtcpContext* ctx) { |
| /* |
| * Note: not generic made for VP8 |
| */ |
| -RTCPSender::BuildResult RTCPSender::BuildRPSI(RtcpContext* ctx) { |
| - if (ctx->feedback_state.send_payload_type == 0xFF) |
| - return BuildResult::kError; |
| - |
| - rtcp::Rpsi rpsi; |
| - rpsi.From(ssrc_); |
| - rpsi.To(remote_ssrc_); |
| - rpsi.WithPayloadType(ctx->feedback_state.send_payload_type); |
| - rpsi.WithPictureId(ctx->picture_id); |
| - |
| - PacketBuiltCallback callback(ctx); |
| - if (!callback.BuildPacket(rpsi)) |
| - return BuildResult::kTruncated; |
| - |
| - return BuildResult::kSuccess; |
| +rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildRPSI( |
| + const RtcpContext& ctx) { |
| + if (ctx.feedback_state_.send_payload_type == 0xFF) |
| + return nullptr; |
| + |
| + rtcp::Rpsi* rpsi = new rtcp::Rpsi(); |
| + rpsi->From(ssrc_); |
| + rpsi->To(remote_ssrc_); |
| + rpsi->WithPayloadType(ctx.feedback_state_.send_payload_type); |
| + rpsi->WithPictureId(ctx.picture_id_); |
| + |
| + return rtc::scoped_ptr<rtcp::Rpsi>(rpsi); |
| } |
| -RTCPSender::BuildResult RTCPSender::BuildREMB(RtcpContext* ctx) { |
| - rtcp::Remb remb; |
| - remb.From(ssrc_); |
| +rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildREMB( |
| + const RtcpContext& ctx) { |
| + rtcp::Remb* remb = new rtcp::Remb(); |
| + remb->From(ssrc_); |
| for (uint32_t ssrc : remb_ssrcs_) |
| - remb.AppliesTo(ssrc); |
| - remb.WithBitrateBps(remb_bitrate_); |
| - |
| - PacketBuiltCallback callback(ctx); |
| - if (!callback.BuildPacket(remb)) |
| - return BuildResult::kTruncated; |
| + remb->AppliesTo(ssrc); |
| + remb->WithBitrateBps(remb_bitrate_); |
| TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), |
| "RTCPSender::REMB"); |
| - return BuildResult::kSuccess; |
| + return rtc::scoped_ptr<rtcp::Remb>(remb); |
| } |
| void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) { |
| @@ -657,9 +628,10 @@ void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) { |
| tmmbr_send_ = target_bitrate / 1000; |
| } |
| -RTCPSender::BuildResult RTCPSender::BuildTMMBR(RtcpContext* ctx) { |
| - if (ctx->feedback_state.module == NULL) |
| - return BuildResult::kError; |
| +rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBR( |
| + const RtcpContext& ctx) { |
| + if (ctx.feedback_state_.module == nullptr) |
| + return nullptr; |
| // Before sending the TMMBR check the received TMMBN, only an owner is |
| // allowed to raise the bitrate: |
| // * If the sender is an owner of the TMMBN -> send TMMBR |
| @@ -674,14 +646,14 @@ RTCPSender::BuildResult RTCPSender::BuildTMMBR(RtcpContext* ctx) { |
| // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but |
| // since RTCPreceiver is not doing the reverse we should be fine |
| int32_t lengthOfBoundingSet = |
| - ctx->feedback_state.module->BoundingSet(tmmbrOwner, candidateSet); |
| + ctx.feedback_state_.module->BoundingSet(tmmbrOwner, candidateSet); |
| if (lengthOfBoundingSet > 0) { |
| for (int32_t i = 0; i < lengthOfBoundingSet; i++) { |
| if (candidateSet->Tmmbr(i) == tmmbr_send_ && |
| candidateSet->PacketOH(i) == packet_oh_send_) { |
| - // do not send the same tuple |
| - return BuildResult::kAborted; |
| + // Do not send the same tuple. |
| + return nullptr; |
| } |
| } |
| if (!tmmbrOwner) { |
| @@ -692,124 +664,69 @@ RTCPSender::BuildResult RTCPSender::BuildTMMBR(RtcpContext* ctx) { |
| int numCandidates = lengthOfBoundingSet + 1; |
| // find bounding set |
| - TMMBRSet* boundingSet = NULL; |
| + TMMBRSet* boundingSet = nullptr; |
| int numBoundingSet = tmmbr_help_.FindTMMBRBoundingSet(boundingSet); |
| if (numBoundingSet > 0 || numBoundingSet <= numCandidates) |
| tmmbrOwner = tmmbr_help_.IsOwner(ssrc_, numBoundingSet); |
| if (!tmmbrOwner) { |
| - // did not enter bounding set, no meaning to send this request |
| - return BuildResult::kAborted; |
| + // Did not enter bounding set, no meaning to send this request. |
| + return nullptr; |
| } |
| } |
| } |
| - if (tmmbr_send_) { |
| - rtcp::Tmmbr tmmbr; |
| - tmmbr.From(ssrc_); |
| - tmmbr.To(remote_ssrc_); |
| - tmmbr.WithBitrateKbps(tmmbr_send_); |
| - tmmbr.WithOverhead(packet_oh_send_); |
| + if (!tmmbr_send_) |
| + return nullptr; |
| - PacketBuiltCallback callback(ctx); |
| - if (!callback.BuildPacket(tmmbr)) |
| - return BuildResult::kTruncated; |
| - } |
| - return BuildResult::kSuccess; |
| + rtcp::Tmmbr* tmmbr = new rtcp::Tmmbr(); |
| + tmmbr->From(ssrc_); |
| + tmmbr->To(remote_ssrc_); |
| + tmmbr->WithBitrateKbps(tmmbr_send_); |
| + tmmbr->WithOverhead(packet_oh_send_); |
| + |
| + return rtc::scoped_ptr<rtcp::Tmmbr>(tmmbr); |
| } |
| -RTCPSender::BuildResult RTCPSender::BuildTMMBN(RtcpContext* ctx) { |
| +rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBN( |
| + const RtcpContext& ctx) { |
| TMMBRSet* boundingSet = tmmbr_help_.BoundingSetToSend(); |
| - if (boundingSet == NULL) |
| - return BuildResult::kError; |
| + if (boundingSet == nullptr) |
| + return nullptr; |
| - rtcp::Tmmbn tmmbn; |
| - tmmbn.From(ssrc_); |
| + rtcp::Tmmbn* tmmbn = new rtcp::Tmmbn(); |
| + tmmbn->From(ssrc_); |
| for (uint32_t i = 0; i < boundingSet->lengthOfSet(); i++) { |
| if (boundingSet->Tmmbr(i) > 0) { |
| - tmmbn.WithTmmbr(boundingSet->Ssrc(i), boundingSet->Tmmbr(i), |
| - boundingSet->PacketOH(i)); |
| + tmmbn->WithTmmbr(boundingSet->Ssrc(i), boundingSet->Tmmbr(i), |
| + boundingSet->PacketOH(i)); |
| } |
| } |
| - PacketBuiltCallback callback(ctx); |
| - if (!callback.BuildPacket(tmmbn)) |
| - return BuildResult::kTruncated; |
| - |
| - return BuildResult::kSuccess; |
| + return rtc::scoped_ptr<rtcp::Tmmbn>(tmmbn); |
| } |
| -RTCPSender::BuildResult RTCPSender::BuildAPP(RtcpContext* ctx) { |
| - rtcp::App app; |
| - app.From(ssrc_); |
| - app.WithSubType(app_sub_type_); |
| - app.WithName(app_name_); |
| - app.WithData(app_data_.get(), app_length_); |
| +rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildAPP(const RtcpContext& ctx) { |
| + rtcp::App* app = new rtcp::App(); |
| + app->From(ssrc_); |
| + app->WithSubType(app_sub_type_); |
| + app->WithName(app_name_); |
| + app->WithData(app_data_.get(), app_length_); |
| - PacketBuiltCallback callback(ctx); |
| - if (!callback.BuildPacket(app)) |
| - return BuildResult::kTruncated; |
| - |
| - return BuildResult::kSuccess; |
| + return rtc::scoped_ptr<rtcp::App>(app); |
| } |
| -RTCPSender::BuildResult RTCPSender::BuildNACK(RtcpContext* ctx) { |
| - // sanity |
| - if (ctx->position + 16 >= IP_PACKET_SIZE) { |
| - LOG(LS_WARNING) << "Failed to build NACK."; |
| - return BuildResult::kTruncated; |
| - } |
| - |
| - // int size, uint16_t* nack_list |
| - // add nack list |
| - uint8_t FMT = 1; |
| - *ctx->AllocateData(1) = 0x80 + FMT; |
| - *ctx->AllocateData(1) = 205; |
| - |
| - *ctx->AllocateData(1) = 0; |
| - int nack_size_pos_ = ctx->position; |
| - *ctx->AllocateData(1) = 3; // setting it to one kNACK signal as default |
| - |
| - // Add our own SSRC |
| - ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_); |
| - |
| - // Add the remote SSRC |
| - ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remote_ssrc_); |
| - |
| - // Build NACK bitmasks and write them to the RTCP message. |
| - // The nack list should be sorted and not contain duplicates if one |
| - // wants to build the smallest rtcp nack packet. |
| - int numOfNackFields = 0; |
| - int maxNackFields = |
| - std::min<int>(kRtcpMaxNackFields, (IP_PACKET_SIZE - ctx->position) / 4); |
| - int i = 0; |
| - while (i < ctx->nack_size && numOfNackFields < maxNackFields) { |
| - uint16_t nack = ctx->nack_list[i++]; |
| - uint16_t bitmask = 0; |
| - while (i < ctx->nack_size) { |
| - int shift = static_cast<uint16_t>(ctx->nack_list[i] - nack) - 1; |
| - if (shift >= 0 && shift <= 15) { |
| - bitmask |= (1 << shift); |
| - ++i; |
| - } else { |
| - break; |
| - } |
| - } |
| - // Write the sequence number and the bitmask to the packet. |
| - assert(ctx->position + 4 < IP_PACKET_SIZE); |
| - ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2), nack); |
| - ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2), bitmask); |
| - numOfNackFields++; |
| - } |
| - ctx->buffer[nack_size_pos_] = static_cast<uint8_t>(2 + numOfNackFields); |
| - |
| - if (i != ctx->nack_size) |
| - LOG(LS_WARNING) << "Nack list too large for one packet."; |
| +rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildNACK( |
| + const RtcpContext& ctx) { |
| + rtcp::Nack* nack = new rtcp::Nack(); |
| + nack->From(ssrc_); |
| + nack->To(remote_ssrc_); |
| + nack->WithList(ctx.nack_list_, ctx.nack_size_); |
| // Report stats. |
| NACKStringBuilder stringBuilder; |
| - for (int idx = 0; idx < i; ++idx) { |
| - stringBuilder.PushNACK(ctx->nack_list[idx]); |
| - nack_stats_.ReportRequest(ctx->nack_list[idx]); |
| + for (int idx = 0; idx < ctx.nack_size_; ++idx) { |
| + stringBuilder.PushNACK(ctx.nack_list_[idx]); |
| + nack_stats_.ReportRequest(ctx.nack_list_[idx]); |
| } |
| packet_type_counter_.nack_requests = nack_stats_.requests(); |
| packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests(); |
| @@ -821,70 +738,59 @@ RTCPSender::BuildResult RTCPSender::BuildNACK(RtcpContext* ctx) { |
| TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount", |
| ssrc_, packet_type_counter_.nack_packets); |
| - return BuildResult::kSuccess; |
| + return rtc::scoped_ptr<rtcp::Nack>(nack); |
| } |
| -RTCPSender::BuildResult RTCPSender::BuildBYE(RtcpContext* ctx) { |
| - rtcp::Bye bye; |
| - bye.From(ssrc_); |
| +rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildBYE(const RtcpContext& ctx) { |
| + rtcp::Bye* bye = new rtcp::Bye(); |
| + bye->From(ssrc_); |
| for (uint32_t csrc : csrcs_) |
| - bye.WithCsrc(csrc); |
| - |
| - PacketBuiltCallback callback(ctx); |
| - if (!callback.BuildPacket(bye)) |
| - return BuildResult::kTruncated; |
| + bye->WithCsrc(csrc); |
| - return BuildResult::kSuccess; |
| + return rtc::scoped_ptr<rtcp::Bye>(bye); |
| } |
| -RTCPSender::BuildResult RTCPSender::BuildReceiverReferenceTime( |
| - RtcpContext* ctx) { |
| - |
| +rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildReceiverReferenceTime( |
| + const RtcpContext& ctx) { |
| if (last_xr_rr_.size() >= RTCP_NUMBER_OF_SR) |
| last_xr_rr_.erase(last_xr_rr_.begin()); |
| last_xr_rr_.insert(std::pair<uint32_t, int64_t>( |
| - RTCPUtility::MidNtp(ctx->ntp_sec, ctx->ntp_frac), |
| - Clock::NtpToMs(ctx->ntp_sec, ctx->ntp_frac))); |
| + RTCPUtility::MidNtp(ctx.ntp_sec_, ctx.ntp_frac_), |
| + Clock::NtpToMs(ctx.ntp_sec_, ctx.ntp_frac_))); |
| - rtcp::Xr xr; |
| - xr.From(ssrc_); |
| + rtcp::Xr* xr = new rtcp::Xr(); |
| + xr->From(ssrc_); |
| rtcp::Rrtr rrtr; |
| - rrtr.WithNtpSec(ctx->ntp_sec); |
| - rrtr.WithNtpFrac(ctx->ntp_frac); |
| + rrtr.WithNtpSec(ctx.ntp_sec_); |
| + rrtr.WithNtpFrac(ctx.ntp_frac_); |
| - xr.WithRrtr(&rrtr); |
| + xr->WithRrtr(&rrtr); |
| // TODO(sprang): Merge XR report sending to contain all of RRTR, DLRR, VOIP? |
| - PacketBuiltCallback callback(ctx); |
| - if (!callback.BuildPacket(xr)) |
| - return BuildResult::kTruncated; |
| - |
| - return BuildResult::kSuccess; |
| + return rtc::scoped_ptr<rtcp::Xr>(xr); |
| } |
| -RTCPSender::BuildResult RTCPSender::BuildDlrr(RtcpContext* ctx) { |
| - rtcp::Xr xr; |
| - xr.From(ssrc_); |
| +rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildDlrr( |
| + const RtcpContext& ctx) { |
| + rtcp::Xr* xr = new rtcp::Xr(); |
| + xr->From(ssrc_); |
| rtcp::Dlrr dlrr; |
| - const RtcpReceiveTimeInfo& info = ctx->feedback_state.last_xr_rr; |
| + const RtcpReceiveTimeInfo& info = ctx.feedback_state_.last_xr_rr; |
| dlrr.WithDlrrItem(info.sourceSSRC, info.lastRR, info.delaySinceLastRR); |
| - xr.WithDlrr(&dlrr); |
| - |
| - PacketBuiltCallback callback(ctx); |
| - if (!callback.BuildPacket(xr)) |
| - return BuildResult::kTruncated; |
| + xr->WithDlrr(&dlrr); |
| - return BuildResult::kSuccess; |
| + return rtc::scoped_ptr<rtcp::Xr>(xr); |
| } |
| // TODO(sprang): Add a unit test for this, or remove if the code isn't used. |
| -RTCPSender::BuildResult RTCPSender::BuildVoIPMetric(RtcpContext* ctx) { |
| - rtcp::Xr xr; |
| - xr.From(ssrc_); |
| +rtc::scoped_ptr<rtcp::RtcpPacket> RTCPSender::BuildVoIPMetric( |
| + const RtcpContext& context) { |
| + rtcp::Xr* xr = new rtcp::Xr(); |
| + xr->From(ssrc_); |
| rtcp::VoipMetric voip; |
| voip.To(remote_ssrc_); |
| @@ -909,13 +815,9 @@ RTCPSender::BuildResult RTCPSender::BuildVoIPMetric(RtcpContext* ctx) { |
| voip.JbMax(xr_voip_metric_.JBmax); |
| voip.JbAbsMax(xr_voip_metric_.JBabsMax); |
| - xr.WithVoipMetric(&voip); |
| + xr->WithVoipMetric(&voip); |
| - PacketBuiltCallback callback(ctx); |
| - if (!callback.BuildPacket(xr)) |
| - return BuildResult::kTruncated; |
| - |
| - return BuildResult::kSuccess; |
| + return rtc::scoped_ptr<rtcp::Xr>(xr); |
| } |
| int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state, |
| @@ -931,43 +833,59 @@ int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state, |
| int32_t RTCPSender::SendCompoundRTCP( |
| const FeedbackState& feedback_state, |
| - const std::set<RTCPPacketType>& packetTypes, |
| + const std::set<RTCPPacketType>& packet_types, |
| int32_t nack_size, |
| const uint16_t* nack_list, |
| bool repeat, |
| uint64_t pictureID) { |
| + PacketContainer container(transport_); |
| { |
| CriticalSectionScoped lock(critical_section_rtcp_sender_.get()); |
| if (method_ == RtcpMode::kOff) { |
| LOG(LS_WARNING) << "Can't send rtcp if it is disabled."; |
| return -1; |
| } |
| - } |
| - uint8_t rtcp_buffer[IP_PACKET_SIZE]; |
| - int rtcp_length = |
| - PrepareRTCP(feedback_state, packetTypes, nack_size, nack_list, repeat, |
| - pictureID, rtcp_buffer, IP_PACKET_SIZE); |
| - // Sanity don't send empty packets. |
| - if (rtcp_length <= 0) |
| - return -1; |
| + // We need to send our NTP even if we haven't received any reports. |
| + uint32_t ntp_sec; |
| + uint32_t ntp_frac; |
| + clock_->CurrentNtp(ntp_sec, ntp_frac); |
| + RtcpContext context(feedback_state, nack_size, nack_list, repeat, pictureID, |
| + ntp_sec, ntp_frac, &container); |
| + |
| + PrepareReport(packet_types, feedback_state); |
| + |
| + auto it = report_flags_.begin(); |
| + while (it != report_flags_.end()) { |
| + auto builder_it = builders_.find(it->type); |
| + RTC_DCHECK(builder_it != builders_.end()); |
| + if (it->is_volatile) { |
| + report_flags_.erase(it++); |
| + } else { |
| + ++it; |
| + } |
| - return SendToNetwork(rtcp_buffer, static_cast<size_t>(rtcp_length)); |
| -} |
| + BuilderFunc func = builder_it->second; |
| + rtc::scoped_ptr<rtcp::RtcpPacket> packet = (this->*func)(context); |
| + if (packet.get() == nullptr) |
| + return -1; |
| + container.Append(packet.release()); |
| + } |
| -int RTCPSender::PrepareRTCP(const FeedbackState& feedback_state, |
| - const std::set<RTCPPacketType>& packetTypes, |
| - int32_t nack_size, |
| - const uint16_t* nack_list, |
| - bool repeat, |
| - uint64_t pictureID, |
| - uint8_t* rtcp_buffer, |
| - int buffer_size) { |
| - CriticalSectionScoped lock(critical_section_rtcp_sender_.get()); |
| + if (packet_type_counter_observer_ != nullptr) { |
| + packet_type_counter_observer_->RtcpPacketTypesCounterUpdated( |
| + remote_ssrc_, packet_type_counter_); |
| + } |
| - RtcpContext context(feedback_state, nack_size, nack_list, repeat, pictureID, |
| - rtcp_buffer, buffer_size); |
| + RTC_DCHECK(AllVolatileFlagsConsumed()); |
| + } |
| + size_t bytes_sent = container.SendPackets(); |
| + return bytes_sent <= 0 ? -1 : 0; |
|
åsapersson
2015/12/03 15:53:57
size_t, bytes_sent == 0
sprang_webrtc
2015/12/03 16:02:22
Done.
|
| +} |
| + |
| +void RTCPSender::PrepareReport(const std::set<RTCPPacketType>& packetTypes, |
| + const FeedbackState& feedback_state) { |
| // Add all flags as volatile. Non volatile entries will not be overwritten |
| // and all new volatile flags added will be consumed by the end of this call. |
| SetFlags(packetTypes, true); |
| @@ -991,9 +909,6 @@ int RTCPSender::PrepareRTCP(const FeedbackState& feedback_state, |
| if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty())) |
| SetFlag(kRtcpSdes, true); |
| - // We need to send our NTP even if we haven't received any reports. |
| - clock_->CurrentNtp(context.ntp_sec, context.ntp_frac); |
| - |
| if (generate_report) { |
| if (!sending_ && xr_send_receiver_reference_time_enabled_) |
| SetFlag(kRtcpXrReceiverReferenceTime, true); |
| @@ -1027,8 +942,8 @@ int RTCPSender::PrepareRTCP(const FeedbackState& feedback_state, |
| if (!statisticians.empty()) { |
| for (auto it = statisticians.begin(); it != statisticians.end(); ++it) { |
| RTCPReportBlock report_block; |
| - if (PrepareReport(feedback_state, it->first, it->second, |
| - &report_block)) { |
| + if (PrepareReportBlock(feedback_state, it->first, it->second, |
| + &report_block)) { |
| // TODO(danilchap) AddReportBlock may fail (for 2 different reasons). |
| // Probably it shouldn't be ignored. |
| AddReportBlock(report_block); |
| @@ -1036,48 +951,12 @@ int RTCPSender::PrepareRTCP(const FeedbackState& feedback_state, |
| } |
| } |
| } |
| - |
| - auto it = report_flags_.begin(); |
| - while (it != report_flags_.end()) { |
| - auto builder = builders_.find(it->type); |
| - RTC_DCHECK(builder != builders_.end()); |
| - if (it->is_volatile) { |
| - report_flags_.erase(it++); |
| - } else { |
| - ++it; |
| - } |
| - |
| - uint32_t start_position = context.position; |
| - BuildResult result = (this->*(builder->second))(&context); |
| - switch (result) { |
| - case BuildResult::kError: |
| - return -1; |
| - case BuildResult::kTruncated: |
| - return context.position; |
| - case BuildResult::kAborted: |
| - context.position = start_position; |
| - FALLTHROUGH(); |
| - case BuildResult::kSuccess: |
| - continue; |
| - default: |
| - abort(); |
| - } |
| - } |
| - |
| - if (packet_type_counter_observer_ != NULL) { |
| - packet_type_counter_observer_->RtcpPacketTypesCounterUpdated( |
| - remote_ssrc_, packet_type_counter_); |
| - } |
| - |
| - RTC_DCHECK(AllVolatileFlagsConsumed()); |
| - |
| - return context.position; |
| } |
| -bool RTCPSender::PrepareReport(const FeedbackState& feedback_state, |
| - uint32_t ssrc, |
| - StreamStatistician* statistician, |
| - RTCPReportBlock* report_block) { |
| +bool RTCPSender::PrepareReportBlock(const FeedbackState& feedback_state, |
| + uint32_t ssrc, |
| + StreamStatistician* statistician, |
| + RTCPReportBlock* report_block) { |
| // Do we have receive statistics to send? |
| RtcpStatistics stats; |
| if (!statistician->GetStatistics(&stats, true)) |
| @@ -1115,12 +994,6 @@ bool RTCPSender::PrepareReport(const FeedbackState& feedback_state, |
| return true; |
| } |
| -int32_t RTCPSender::SendToNetwork(const uint8_t* dataBuffer, size_t length) { |
| - if (transport_->SendRtcp(dataBuffer, length)) |
| - return 0; |
| - return -1; |
| -} |
| - |
| void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) { |
| assert(csrcs.size() <= kRtpCsrcSize); |
| CriticalSectionScoped lock(critical_section_rtcp_sender_.get()); |