Home | History | Annotate | Download | only in rtp_packetizer
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "media/cast/net/rtp_sender/rtp_packetizer/rtp_packetizer.h"
      6 
      7 #include "base/logging.h"
      8 #include "media/cast/cast_defines.h"
      9 #include "media/cast/net/pacing/paced_sender.h"
     10 #include "net/base/big_endian.h"
     11 
     12 namespace media {
     13 namespace cast {
     14 
     15 static const uint16 kCommonRtpHeaderLength = 12;
     16 static const uint16 kCastRtpHeaderLength = 7;
     17 static const uint8 kCastKeyFrameBitMask = 0x80;
     18 static const uint8 kCastReferenceFrameIdBitMask = 0x40;
     19 
     20 RtpPacketizer::RtpPacketizer(PacedPacketSender* transport,
     21                              PacketStorage* packet_storage,
     22                              RtpPacketizerConfig rtp_packetizer_config)
     23     : config_(rtp_packetizer_config),
     24       transport_(transport),
     25       packet_storage_(packet_storage),
     26       sequence_number_(config_.sequence_number),
     27       rtp_timestamp_(config_.rtp_timestamp),
     28       packet_id_(0),
     29       send_packets_count_(0),
     30       send_octet_count_(0) {
     31   DCHECK(transport) << "Invalid argument";
     32 }
     33 
     34 RtpPacketizer::~RtpPacketizer() {}
     35 
     36 void RtpPacketizer::IncomingEncodedVideoFrame(
     37     const EncodedVideoFrame* video_frame,
     38     const base::TimeTicks& capture_time) {
     39   DCHECK(!config_.audio) << "Invalid state";
     40   if (config_.audio) return;
     41 
     42   // Timestamp is in 90 KHz for video.
     43   rtp_timestamp_ = GetVideoRtpTimestamp(capture_time);
     44   time_last_sent_rtp_timestamp_ = capture_time;
     45 
     46   Cast(video_frame->key_frame,
     47        video_frame->frame_id,
     48        video_frame->last_referenced_frame_id,
     49        rtp_timestamp_,
     50        video_frame->data);
     51 }
     52 
     53 void RtpPacketizer::IncomingEncodedAudioFrame(
     54     const EncodedAudioFrame* audio_frame,
     55     const base::TimeTicks& recorded_time) {
     56   DCHECK(config_.audio) << "Invalid state";
     57   if (!config_.audio) return;
     58 
     59   rtp_timestamp_ += audio_frame->samples;  // Timestamp is in samples for audio.
     60   time_last_sent_rtp_timestamp_ = recorded_time;
     61   Cast(true, audio_frame->frame_id, 0, rtp_timestamp_, audio_frame->data);
     62 }
     63 
     64 uint16 RtpPacketizer::NextSequenceNumber() {
     65   ++sequence_number_;
     66   return sequence_number_ - 1;
     67 }
     68 
     69 bool RtpPacketizer::LastSentTimestamp(base::TimeTicks* time_sent,
     70                                       uint32* rtp_timestamp) const {
     71   if (time_last_sent_rtp_timestamp_.is_null()) return false;
     72 
     73   *time_sent = time_last_sent_rtp_timestamp_;
     74   *rtp_timestamp = rtp_timestamp_;
     75   return true;
     76 }
     77 
     78 // TODO(mikhal): Switch to pass data with a const_ref.
     79 void RtpPacketizer::Cast(bool is_key,
     80                          uint32 frame_id,
     81                          uint32 reference_frame_id,
     82                          uint32 timestamp,
     83                          const std::string& data) {
     84   uint16 rtp_header_length = kCommonRtpHeaderLength + kCastRtpHeaderLength;
     85   uint16 max_length = config_.max_payload_length - rtp_header_length - 1;
     86 
     87   // Split the payload evenly (round number up).
     88   size_t num_packets = (data.size() + max_length) / max_length;
     89   size_t payload_length = (data.size() + num_packets) / num_packets;
     90   DCHECK_LE(payload_length, max_length) << "Invalid argument";
     91 
     92   PacketList packets;
     93 
     94   size_t remaining_size = data.size();
     95   std::string::const_iterator data_iter = data.begin();
     96   while (remaining_size > 0) {
     97     Packet packet;
     98 
     99     if (remaining_size < payload_length) {
    100       payload_length = remaining_size;
    101     }
    102     remaining_size -= payload_length;
    103     BuildCommonRTPheader(&packet, remaining_size == 0, timestamp);
    104 
    105     // Build Cast header.
    106     packet.push_back(
    107         (is_key ? kCastKeyFrameBitMask : 0) | kCastReferenceFrameIdBitMask);
    108     packet.push_back(frame_id);
    109     size_t start_size = packet.size();
    110     packet.resize(start_size + 4);
    111     net::BigEndianWriter big_endian_writer(&(packet[start_size]), 4);
    112     big_endian_writer.WriteU16(packet_id_);
    113     big_endian_writer.WriteU16(static_cast<uint16>(num_packets - 1));
    114     packet.push_back(static_cast<uint8>(reference_frame_id));
    115 
    116     // Copy payload data.
    117     packet.insert(packet.end(), data_iter, data_iter + payload_length);
    118 
    119     // Store packet.
    120     packet_storage_->StorePacket(frame_id, packet_id_, &packet);
    121     ++packet_id_;
    122     data_iter += payload_length;
    123 
    124     // Update stats.
    125     ++send_packets_count_;
    126     send_octet_count_ += payload_length;
    127     packets.push_back(packet);
    128   }
    129   DCHECK(packet_id_ == num_packets) << "Invalid state";
    130 
    131   // Send to network.
    132   transport_->SendPackets(packets);
    133 
    134   // Prepare for next frame.
    135   packet_id_ = 0;
    136 }
    137 
    138 void RtpPacketizer::BuildCommonRTPheader(
    139     Packet* packet, bool marker_bit, uint32 time_stamp) {
    140   packet->push_back(0x80);
    141   packet->push_back(static_cast<uint8>(config_.payload_type) |
    142                     (marker_bit ? kRtpMarkerBitMask : 0));
    143   size_t start_size = packet->size();
    144   packet->resize(start_size + 10);
    145   net::BigEndianWriter big_endian_writer(&((*packet)[start_size]), 10);
    146   big_endian_writer.WriteU16(sequence_number_);
    147   big_endian_writer.WriteU32(time_stamp);
    148   big_endian_writer.WriteU32(config_.ssrc);
    149   ++sequence_number_;
    150 }
    151 
    152 }  // namespace cast
    153 }  // namespace media
    154