| Index: media/cast/rtcp/rtcp_receiver.cc
|
| diff --git a/media/cast/rtcp/rtcp_receiver.cc b/media/cast/rtcp/rtcp_receiver.cc
|
| deleted file mode 100644
|
| index 3be8e921c4690694fa876ba8f511024717c05cfa..0000000000000000000000000000000000000000
|
| --- a/media/cast/rtcp/rtcp_receiver.cc
|
| +++ /dev/null
|
| @@ -1,564 +0,0 @@
|
| -// 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.
|
| -
|
| -#include "media/cast/rtcp/rtcp_receiver.h"
|
| -
|
| -#include "base/logging.h"
|
| -#include "media/cast/rtcp/rtcp_utility.h"
|
| -#include "media/cast/transport/cast_transport_defines.h"
|
| -
|
| -namespace {
|
| -
|
| -// A receiver frame event is identified by frame RTP timestamp, event timestamp
|
| -// and event type.
|
| -// A receiver packet event is identified by all of the above plus packet id.
|
| -// The key format is as follows:
|
| -// First uint64:
|
| -// bits 0-11: zeroes (unused).
|
| -// bits 12-15: event type ID.
|
| -// bits 16-31: packet ID if packet event, 0 otherwise.
|
| -// bits 32-63: RTP timestamp.
|
| -// Second uint64:
|
| -// bits 0-63: event TimeTicks internal value.
|
| -std::pair<uint64, uint64> GetReceiverEventKey(
|
| - uint32 frame_rtp_timestamp, const base::TimeTicks& event_timestamp,
|
| - uint8 event_type, uint16 packet_id_or_zero) {
|
| - uint64 value1 = event_type;
|
| - value1 <<= 16;
|
| - value1 |= packet_id_or_zero;
|
| - value1 <<= 32;
|
| - value1 |= frame_rtp_timestamp;
|
| - return std::make_pair(
|
| - value1, static_cast<uint64>(event_timestamp.ToInternalValue()));
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -namespace media {
|
| -namespace cast {
|
| -
|
| -RtcpReceiver::RtcpReceiver(scoped_refptr<CastEnvironment> cast_environment,
|
| - RtcpSenderFeedback* sender_feedback,
|
| - RtcpReceiverFeedback* receiver_feedback,
|
| - RtcpRttFeedback* rtt_feedback,
|
| - uint32 local_ssrc)
|
| - : ssrc_(local_ssrc),
|
| - remote_ssrc_(0),
|
| - sender_feedback_(sender_feedback),
|
| - receiver_feedback_(receiver_feedback),
|
| - rtt_feedback_(rtt_feedback),
|
| - cast_environment_(cast_environment),
|
| - receiver_event_history_size_(0) {}
|
| -
|
| -RtcpReceiver::~RtcpReceiver() {}
|
| -
|
| -void RtcpReceiver::SetRemoteSSRC(uint32 ssrc) { remote_ssrc_ = ssrc; }
|
| -
|
| -void RtcpReceiver::SetCastReceiverEventHistorySize(size_t size) {
|
| - receiver_event_history_size_ = size;
|
| -}
|
| -
|
| -void RtcpReceiver::IncomingRtcpPacket(RtcpParser* rtcp_parser) {
|
| - RtcpFieldTypes field_type = rtcp_parser->Begin();
|
| - while (field_type != kRtcpNotValidCode) {
|
| - // Each "case" is responsible for iterate the parser to the next top
|
| - // level packet.
|
| - switch (field_type) {
|
| - case kRtcpSrCode:
|
| - HandleSenderReport(rtcp_parser);
|
| - break;
|
| - case kRtcpRrCode:
|
| - HandleReceiverReport(rtcp_parser);
|
| - break;
|
| - case kRtcpSdesCode:
|
| - HandleSDES(rtcp_parser);
|
| - break;
|
| - case kRtcpByeCode:
|
| - HandleBYE(rtcp_parser);
|
| - break;
|
| - case kRtcpXrCode:
|
| - HandleXr(rtcp_parser);
|
| - break;
|
| - case kRtcpGenericRtpFeedbackNackCode:
|
| - HandleNACK(rtcp_parser);
|
| - break;
|
| - case kRtcpGenericRtpFeedbackSrReqCode:
|
| - HandleSendReportRequest(rtcp_parser);
|
| - break;
|
| - case kRtcpPayloadSpecificPliCode:
|
| - HandlePLI(rtcp_parser);
|
| - break;
|
| - case kRtcpPayloadSpecificRpsiCode:
|
| - HandleRpsi(rtcp_parser);
|
| - break;
|
| - case kRtcpPayloadSpecificFirCode:
|
| - HandleFIR(rtcp_parser);
|
| - break;
|
| - case kRtcpPayloadSpecificAppCode:
|
| - HandlePayloadSpecificApp(rtcp_parser);
|
| - break;
|
| - case kRtcpApplicationSpecificCastReceiverLogCode:
|
| - HandleApplicationSpecificCastReceiverLog(rtcp_parser);
|
| - break;
|
| - case kRtcpPayloadSpecificRembCode:
|
| - case kRtcpPayloadSpecificRembItemCode:
|
| - case kRtcpPayloadSpecificCastCode:
|
| - case kRtcpPayloadSpecificCastNackItemCode:
|
| - case kRtcpApplicationSpecificCastReceiverLogFrameCode:
|
| - case kRtcpApplicationSpecificCastReceiverLogEventCode:
|
| - case kRtcpNotValidCode:
|
| - case kRtcpReportBlockItemCode:
|
| - case kRtcpSdesChunkCode:
|
| - case kRtcpGenericRtpFeedbackNackItemCode:
|
| - case kRtcpPayloadSpecificFirItemCode:
|
| - case kRtcpXrRrtrCode:
|
| - case kRtcpXrDlrrCode:
|
| - case kRtcpXrUnknownItemCode:
|
| - rtcp_parser->Iterate();
|
| - NOTREACHED() << "Invalid state";
|
| - break;
|
| - }
|
| - field_type = rtcp_parser->FieldType();
|
| - }
|
| -}
|
| -
|
| -void RtcpReceiver::HandleSenderReport(RtcpParser* rtcp_parser) {
|
| - RtcpFieldTypes rtcp_field_type = rtcp_parser->FieldType();
|
| - const RtcpField& rtcp_field = rtcp_parser->Field();
|
| -
|
| - DCHECK(rtcp_field_type == kRtcpSrCode) << "Invalid state";
|
| -
|
| - // Synchronization source identifier for the originator of this SR packet.
|
| - uint32 remote_ssrc = rtcp_field.sender_report.sender_ssrc;
|
| -
|
| - VLOG(2) << "Cast RTCP received SR from SSRC " << remote_ssrc;
|
| -
|
| - if (remote_ssrc_ == remote_ssrc) {
|
| - transport::RtcpSenderInfo remote_sender_info;
|
| - remote_sender_info.ntp_seconds =
|
| - rtcp_field.sender_report.ntp_most_significant;
|
| - remote_sender_info.ntp_fraction =
|
| - rtcp_field.sender_report.ntp_least_significant;
|
| - remote_sender_info.rtp_timestamp = rtcp_field.sender_report.rtp_timestamp;
|
| - remote_sender_info.send_packet_count =
|
| - rtcp_field.sender_report.sender_packet_count;
|
| - remote_sender_info.send_octet_count =
|
| - rtcp_field.sender_report.sender_octet_count;
|
| - if (receiver_feedback_) {
|
| - receiver_feedback_->OnReceivedSenderReport(remote_sender_info);
|
| - }
|
| - }
|
| - rtcp_field_type = rtcp_parser->Iterate();
|
| - while (rtcp_field_type == kRtcpReportBlockItemCode) {
|
| - HandleReportBlock(&rtcp_field, remote_ssrc);
|
| - rtcp_field_type = rtcp_parser->Iterate();
|
| - }
|
| -}
|
| -
|
| -void RtcpReceiver::HandleReceiverReport(RtcpParser* rtcp_parser) {
|
| - RtcpFieldTypes rtcp_field_type = rtcp_parser->FieldType();
|
| - const RtcpField& rtcp_field = rtcp_parser->Field();
|
| -
|
| - DCHECK(rtcp_field_type == kRtcpRrCode) << "Invalid state";
|
| -
|
| - uint32 remote_ssrc = rtcp_field.receiver_report.sender_ssrc;
|
| -
|
| - VLOG(2) << "Cast RTCP received RR from SSRC " << remote_ssrc;
|
| -
|
| - rtcp_field_type = rtcp_parser->Iterate();
|
| - while (rtcp_field_type == kRtcpReportBlockItemCode) {
|
| - HandleReportBlock(&rtcp_field, remote_ssrc);
|
| - rtcp_field_type = rtcp_parser->Iterate();
|
| - }
|
| -}
|
| -
|
| -void RtcpReceiver::HandleReportBlock(const RtcpField* rtcp_field,
|
| - uint32 remote_ssrc) {
|
| - // This will be called once per report block in the Rtcp packet.
|
| - // We filter out all report blocks that are not for us.
|
| - // Each packet has max 31 RR blocks.
|
| - //
|
| - // We can calculate RTT if we send a send report and get a report block back.
|
| -
|
| - // |rtcp_field.ReportBlockItem.ssrc| is the ssrc identifier of the source to
|
| - // which the information in this reception report block pertains.
|
| -
|
| - const RtcpFieldReportBlockItem& rb = rtcp_field->report_block_item;
|
| -
|
| - // Filter out all report blocks that are not for us.
|
| - if (rb.ssrc != ssrc_) {
|
| - // This block is not for us ignore it.
|
| - return;
|
| - }
|
| - VLOG(2) << "Cast RTCP received RB from SSRC " << remote_ssrc;
|
| -
|
| - transport::RtcpReportBlock report_block;
|
| - report_block.remote_ssrc = remote_ssrc;
|
| - report_block.media_ssrc = rb.ssrc;
|
| - report_block.fraction_lost = rb.fraction_lost;
|
| - report_block.cumulative_lost = rb.cumulative_number_of_packets_lost;
|
| - report_block.extended_high_sequence_number =
|
| - rb.extended_highest_sequence_number;
|
| - report_block.jitter = rb.jitter;
|
| - report_block.last_sr = rb.last_sender_report;
|
| - report_block.delay_since_last_sr = rb.delay_last_sender_report;
|
| -
|
| - if (rtt_feedback_) {
|
| - rtt_feedback_->OnReceivedDelaySinceLastReport(
|
| - rb.ssrc, rb.last_sender_report, rb.delay_last_sender_report);
|
| - }
|
| -}
|
| -
|
| -void RtcpReceiver::HandleSDES(RtcpParser* rtcp_parser) {
|
| - RtcpFieldTypes field_type = rtcp_parser->Iterate();
|
| - while (field_type == kRtcpSdesChunkCode) {
|
| - HandleSDESChunk(rtcp_parser);
|
| - field_type = rtcp_parser->Iterate();
|
| - }
|
| -}
|
| -
|
| -void RtcpReceiver::HandleSDESChunk(RtcpParser* rtcp_parser) {
|
| - const RtcpField& rtcp_field = rtcp_parser->Field();
|
| - VLOG(2) << "Cast RTCP received SDES with cname " << rtcp_field.c_name.name;
|
| -}
|
| -
|
| -void RtcpReceiver::HandleXr(RtcpParser* rtcp_parser) {
|
| - RtcpFieldTypes rtcp_field_type = rtcp_parser->FieldType();
|
| - const RtcpField& rtcp_field = rtcp_parser->Field();
|
| -
|
| - DCHECK(rtcp_field_type == kRtcpXrCode) << "Invalid state";
|
| -
|
| - uint32 remote_ssrc = rtcp_field.extended_report.sender_ssrc;
|
| - rtcp_field_type = rtcp_parser->Iterate();
|
| -
|
| - while (rtcp_field_type == kRtcpXrDlrrCode ||
|
| - rtcp_field_type == kRtcpXrRrtrCode ||
|
| - rtcp_field_type == kRtcpXrUnknownItemCode) {
|
| - if (rtcp_field_type == kRtcpXrRrtrCode) {
|
| - HandleRrtr(rtcp_parser, remote_ssrc);
|
| - } else if (rtcp_field_type == kRtcpXrDlrrCode) {
|
| - HandleDlrr(rtcp_parser);
|
| - }
|
| - rtcp_field_type = rtcp_parser->Iterate();
|
| - }
|
| -}
|
| -
|
| -void RtcpReceiver::HandleRrtr(RtcpParser* rtcp_parser, uint32 remote_ssrc) {
|
| - if (remote_ssrc_ != remote_ssrc) {
|
| - // Not to us.
|
| - return;
|
| - }
|
| - const RtcpField& rtcp_field = rtcp_parser->Field();
|
| - RtcpReceiverReferenceTimeReport remote_time_report;
|
| - remote_time_report.remote_ssrc = remote_ssrc;
|
| - remote_time_report.ntp_seconds = rtcp_field.rrtr.ntp_most_significant;
|
| - remote_time_report.ntp_fraction = rtcp_field.rrtr.ntp_least_significant;
|
| -
|
| - if (receiver_feedback_) {
|
| - receiver_feedback_->OnReceiverReferenceTimeReport(remote_time_report);
|
| - }
|
| -}
|
| -
|
| -void RtcpReceiver::HandleDlrr(RtcpParser* rtcp_parser) {
|
| - const RtcpField& rtcp_field = rtcp_parser->Field();
|
| - if (remote_ssrc_ != rtcp_field.dlrr.receivers_ssrc) {
|
| - // Not to us.
|
| - return;
|
| - }
|
| - if (rtt_feedback_) {
|
| - rtt_feedback_->OnReceivedDelaySinceLastReport(
|
| - rtcp_field.dlrr.receivers_ssrc,
|
| - rtcp_field.dlrr.last_receiver_report,
|
| - rtcp_field.dlrr.delay_last_receiver_report);
|
| - }
|
| -}
|
| -
|
| -void RtcpReceiver::HandleNACK(RtcpParser* rtcp_parser) {
|
| - const RtcpField& rtcp_field = rtcp_parser->Field();
|
| - if (ssrc_ != rtcp_field.nack.media_ssrc) {
|
| - RtcpFieldTypes field_type;
|
| - // Message not to us. Iterate until we have passed this message.
|
| - do {
|
| - field_type = rtcp_parser->Iterate();
|
| - } while (field_type == kRtcpGenericRtpFeedbackNackItemCode);
|
| - return;
|
| - }
|
| - std::list<uint16> nackSequenceNumbers;
|
| -
|
| - RtcpFieldTypes field_type = rtcp_parser->Iterate();
|
| - while (field_type == kRtcpGenericRtpFeedbackNackItemCode) {
|
| - HandleNACKItem(&rtcp_field, &nackSequenceNumbers);
|
| - field_type = rtcp_parser->Iterate();
|
| - }
|
| -}
|
| -
|
| -void RtcpReceiver::HandleNACKItem(const RtcpField* rtcp_field,
|
| - std::list<uint16>* nack_sequence_numbers) {
|
| - nack_sequence_numbers->push_back(rtcp_field->nack_item.packet_id);
|
| -
|
| - uint16 bitmask = rtcp_field->nack_item.bitmask;
|
| - if (bitmask) {
|
| - for (int i = 1; i <= 16; ++i) {
|
| - if (bitmask & 1) {
|
| - nack_sequence_numbers->push_back(rtcp_field->nack_item.packet_id + i);
|
| - }
|
| - bitmask = bitmask >> 1;
|
| - }
|
| - }
|
| -}
|
| -
|
| -void RtcpReceiver::HandleBYE(RtcpParser* rtcp_parser) {
|
| - const RtcpField& rtcp_field = rtcp_parser->Field();
|
| - uint32 remote_ssrc = rtcp_field.bye.sender_ssrc;
|
| - if (remote_ssrc_ == remote_ssrc) {
|
| - VLOG(2) << "Cast RTCP received BYE from SSRC " << remote_ssrc;
|
| - }
|
| - rtcp_parser->Iterate();
|
| -}
|
| -
|
| -void RtcpReceiver::HandlePLI(RtcpParser* rtcp_parser) {
|
| - const RtcpField& rtcp_field = rtcp_parser->Field();
|
| - if (ssrc_ == rtcp_field.pli.media_ssrc) {
|
| - // Received a signal that we need to send a new key frame.
|
| - VLOG(2) << "Cast RTCP received PLI on our SSRC " << ssrc_;
|
| - }
|
| - rtcp_parser->Iterate();
|
| -}
|
| -
|
| -void RtcpReceiver::HandleSendReportRequest(RtcpParser* rtcp_parser) {
|
| - if (receiver_feedback_) {
|
| - receiver_feedback_->OnReceivedSendReportRequest();
|
| - }
|
| - rtcp_parser->Iterate();
|
| -}
|
| -
|
| -void RtcpReceiver::HandleRpsi(RtcpParser* rtcp_parser) {
|
| - const RtcpField& rtcp_field = rtcp_parser->Field();
|
| - if (rtcp_parser->Iterate() != kRtcpPayloadSpecificRpsiCode) {
|
| - return;
|
| - }
|
| - if (rtcp_field.rpsi.number_of_valid_bits % 8 != 0) {
|
| - // Continue
|
| - return;
|
| - }
|
| - uint64 rpsi_picture_id = 0;
|
| -
|
| - // Convert native_bit_string to rpsi_picture_id
|
| - uint8 bytes = rtcp_field.rpsi.number_of_valid_bits / 8;
|
| - for (uint8 n = 0; n < (bytes - 1); ++n) {
|
| - rpsi_picture_id += (rtcp_field.rpsi.native_bit_string[n] & 0x7f);
|
| - rpsi_picture_id <<= 7; // Prepare next.
|
| - }
|
| - rpsi_picture_id += (rtcp_field.rpsi.native_bit_string[bytes - 1] & 0x7f);
|
| -
|
| - VLOG(2) << "Cast RTCP received RPSI with picture_id " << rpsi_picture_id;
|
| -}
|
| -
|
| -void RtcpReceiver::HandlePayloadSpecificApp(RtcpParser* rtcp_parser) {
|
| - const RtcpField& rtcp_field = rtcp_parser->Field();
|
| - uint32 remote_ssrc = rtcp_field.application_specific.sender_ssrc;
|
| - if (remote_ssrc_ != remote_ssrc) {
|
| - // Message not to us. Iterate until we have passed this message.
|
| - RtcpFieldTypes field_type;
|
| - do {
|
| - field_type = rtcp_parser->Iterate();
|
| - } while (field_type == kRtcpPayloadSpecificRembCode ||
|
| - field_type == kRtcpPayloadSpecificRembItemCode ||
|
| - field_type == kRtcpPayloadSpecificCastCode ||
|
| - field_type == kRtcpPayloadSpecificCastNackItemCode);
|
| - return;
|
| - }
|
| -
|
| - RtcpFieldTypes packet_type = rtcp_parser->Iterate();
|
| - switch (packet_type) {
|
| - case kRtcpPayloadSpecificRembCode:
|
| - packet_type = rtcp_parser->Iterate();
|
| - if (packet_type == kRtcpPayloadSpecificRembItemCode) {
|
| - HandlePayloadSpecificRembItem(rtcp_parser);
|
| - rtcp_parser->Iterate();
|
| - }
|
| - break;
|
| - case kRtcpPayloadSpecificCastCode:
|
| - packet_type = rtcp_parser->Iterate();
|
| - if (packet_type == kRtcpPayloadSpecificCastCode) {
|
| - HandlePayloadSpecificCastItem(rtcp_parser);
|
| - }
|
| - break;
|
| - default:
|
| - return;
|
| - }
|
| -}
|
| -
|
| -void RtcpReceiver::HandlePayloadSpecificRembItem(RtcpParser* rtcp_parser) {
|
| - const RtcpField& rtcp_field = rtcp_parser->Field();
|
| -
|
| - for (int i = 0; i < rtcp_field.remb_item.number_of_ssrcs; ++i) {
|
| - if (rtcp_field.remb_item.ssrcs[i] == ssrc_) {
|
| - // Found matching ssrc.
|
| - VLOG(2) << "Cast RTCP received REMB with received_bitrate "
|
| - << rtcp_field.remb_item.bitrate;
|
| - return;
|
| - }
|
| - }
|
| -}
|
| -
|
| -void RtcpReceiver::HandleApplicationSpecificCastReceiverLog(
|
| - RtcpParser* rtcp_parser) {
|
| - const RtcpField& rtcp_field = rtcp_parser->Field();
|
| -
|
| - uint32 remote_ssrc = rtcp_field.cast_receiver_log.sender_ssrc;
|
| - if (remote_ssrc_ != remote_ssrc) {
|
| - // Message not to us. Iterate until we have passed this message.
|
| - RtcpFieldTypes field_type;
|
| - do {
|
| - field_type = rtcp_parser->Iterate();
|
| - } while (field_type == kRtcpApplicationSpecificCastReceiverLogFrameCode ||
|
| - field_type == kRtcpApplicationSpecificCastReceiverLogEventCode);
|
| - return;
|
| - }
|
| - RtcpReceiverLogMessage receiver_log;
|
| - RtcpFieldTypes field_type = rtcp_parser->Iterate();
|
| - while (field_type == kRtcpApplicationSpecificCastReceiverLogFrameCode) {
|
| - RtcpReceiverFrameLogMessage frame_log(
|
| - rtcp_field.cast_receiver_log.rtp_timestamp);
|
| -
|
| - field_type = rtcp_parser->Iterate();
|
| - while (field_type == kRtcpApplicationSpecificCastReceiverLogEventCode) {
|
| - HandleApplicationSpecificCastReceiverEventLog(
|
| - rtcp_field.cast_receiver_log.rtp_timestamp,
|
| - rtcp_parser,
|
| - &frame_log.event_log_messages_);
|
| - field_type = rtcp_parser->Iterate();
|
| - }
|
| -
|
| - if (!frame_log.event_log_messages_.empty())
|
| - receiver_log.push_back(frame_log);
|
| - }
|
| -
|
| - if (receiver_feedback_ && !receiver_log.empty()) {
|
| - receiver_feedback_->OnReceivedReceiverLog(receiver_log);
|
| - }
|
| -}
|
| -
|
| -void RtcpReceiver::HandleApplicationSpecificCastReceiverEventLog(
|
| - uint32 frame_rtp_timestamp,
|
| - RtcpParser* rtcp_parser,
|
| - RtcpReceiverEventLogMessages* event_log_messages) {
|
| - const RtcpField& rtcp_field = rtcp_parser->Field();
|
| -
|
| - const uint8 event = rtcp_field.cast_receiver_log.event;
|
| - const CastLoggingEvent event_type = TranslateToLogEventFromWireFormat(event);
|
| - uint16 packet_id = event_type == PACKET_RECEIVED ?
|
| - rtcp_field.cast_receiver_log.delay_delta_or_packet_id.packet_id : 0;
|
| - const base::TimeTicks event_timestamp =
|
| - base::TimeTicks() +
|
| - base::TimeDelta::FromMilliseconds(
|
| - rtcp_field.cast_receiver_log.event_timestamp_base +
|
| - rtcp_field.cast_receiver_log.event_timestamp_delta);
|
| -
|
| - // The following code checks to see if we have already seen this event.
|
| - // The algorithm works by maintaining a sliding window of events. We have
|
| - // a queue and a set of events. We enqueue every new event and insert it
|
| - // into the set. When the queue becomes too big we remove the oldest event
|
| - // from both the queue and the set.
|
| - ReceiverEventKey key =
|
| - GetReceiverEventKey(
|
| - frame_rtp_timestamp, event_timestamp, event, packet_id);
|
| - if (receiver_event_key_set_.find(key) != receiver_event_key_set_.end()) {
|
| - return;
|
| - } else {
|
| - receiver_event_key_set_.insert(key);
|
| - receiver_event_key_queue_.push(key);
|
| -
|
| - if (receiver_event_key_queue_.size() > receiver_event_history_size_) {
|
| - const ReceiverEventKey oldest_key = receiver_event_key_queue_.front();
|
| - receiver_event_key_queue_.pop();
|
| - receiver_event_key_set_.erase(oldest_key);
|
| - }
|
| - }
|
| -
|
| - RtcpReceiverEventLogMessage event_log;
|
| - event_log.type = event_type;
|
| - event_log.event_timestamp = event_timestamp;
|
| - event_log.delay_delta = base::TimeDelta::FromMilliseconds(
|
| - rtcp_field.cast_receiver_log.delay_delta_or_packet_id.delay_delta);
|
| - event_log.packet_id =
|
| - rtcp_field.cast_receiver_log.delay_delta_or_packet_id.packet_id;
|
| - event_log_messages->push_back(event_log);
|
| -}
|
| -
|
| -void RtcpReceiver::HandlePayloadSpecificCastItem(RtcpParser* rtcp_parser) {
|
| - const RtcpField& rtcp_field = rtcp_parser->Field();
|
| - RtcpCastMessage cast_message(remote_ssrc_);
|
| - cast_message.ack_frame_id_ = ack_frame_id_wrap_helper_.MapTo32bitsFrameId(
|
| - rtcp_field.cast_item.last_frame_id);
|
| - cast_message.target_delay_ms_ = rtcp_field.cast_item.target_delay_ms;
|
| -
|
| - RtcpFieldTypes packet_type = rtcp_parser->Iterate();
|
| - while (packet_type == kRtcpPayloadSpecificCastNackItemCode) {
|
| - const RtcpField& rtcp_field = rtcp_parser->Field();
|
| - HandlePayloadSpecificCastNackItem(
|
| - &rtcp_field, &cast_message.missing_frames_and_packets_);
|
| - packet_type = rtcp_parser->Iterate();
|
| - }
|
| - if (sender_feedback_) {
|
| - sender_feedback_->OnReceivedCastFeedback(cast_message);
|
| - }
|
| -}
|
| -
|
| -void RtcpReceiver::HandlePayloadSpecificCastNackItem(
|
| - const RtcpField* rtcp_field,
|
| - MissingFramesAndPacketsMap* missing_frames_and_packets) {
|
| -
|
| - MissingFramesAndPacketsMap::iterator frame_it =
|
| - missing_frames_and_packets->find(rtcp_field->cast_nack_item.frame_id);
|
| -
|
| - if (frame_it == missing_frames_and_packets->end()) {
|
| - // First missing packet in a frame.
|
| - PacketIdSet empty_set;
|
| - std::pair<MissingFramesAndPacketsMap::iterator, bool> ret =
|
| - missing_frames_and_packets->insert(std::pair<uint8, PacketIdSet>(
|
| - rtcp_field->cast_nack_item.frame_id, empty_set));
|
| - frame_it = ret.first;
|
| - DCHECK(frame_it != missing_frames_and_packets->end()) << "Invalid state";
|
| - }
|
| - uint16 packet_id = rtcp_field->cast_nack_item.packet_id;
|
| - frame_it->second.insert(packet_id);
|
| -
|
| - if (packet_id == kRtcpCastAllPacketsLost) {
|
| - // Special case all packets in a frame is missing.
|
| - return;
|
| - }
|
| - uint8 bitmask = rtcp_field->cast_nack_item.bitmask;
|
| -
|
| - if (bitmask) {
|
| - for (int i = 1; i <= 8; ++i) {
|
| - if (bitmask & 1) {
|
| - frame_it->second.insert(packet_id + i);
|
| - }
|
| - bitmask = bitmask >> 1;
|
| - }
|
| - }
|
| -}
|
| -
|
| -void RtcpReceiver::HandleFIR(RtcpParser* rtcp_parser) {
|
| - const RtcpField& rtcp_field = rtcp_parser->Field();
|
| -
|
| - RtcpFieldTypes field_type = rtcp_parser->Iterate();
|
| - while (field_type == kRtcpPayloadSpecificFirItemCode) {
|
| - HandleFIRItem(&rtcp_field);
|
| - field_type = rtcp_parser->Iterate();
|
| - }
|
| -}
|
| -
|
| -void RtcpReceiver::HandleFIRItem(const RtcpField* rtcp_field) {
|
| - // Is it our sender that is requested to generate a new keyframe.
|
| - if (ssrc_ != rtcp_field->fir_item.ssrc)
|
| - return;
|
| -
|
| - VLOG(2) << "Cast RTCP received FIR on our SSRC " << ssrc_;
|
| -}
|
| -
|
| -} // namespace cast
|
| -} // namespace media
|
|
|