1116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Copyright 2014 The Chromium Authors. All rights reserved.
2424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// found in the LICENSE file.
4424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
5116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "media/cast/net/rtp/rtp_packetizer.h"
6424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/big_endian.h"
8424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/logging.h"
9116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "media/cast/net/pacing/paced_sender.h"
1003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "media/cast/net/rtp/rtp_defines.h"
11424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
12424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)namespace media {
13424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)namespace cast {
14424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)RtpPacketizerConfig::RtpPacketizerConfig()
16116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    : payload_type(-1),
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      max_payload_length(kMaxIpPacketSize - 28),  // Default is IP-v4/UDP.
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      sequence_number(0),
19116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      ssrc(0) {}
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)RtpPacketizerConfig::~RtpPacketizerConfig() {}
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)RtpPacketizer::RtpPacketizer(PacedSender* const transport,
24424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                             PacketStorage* packet_storage,
255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                             RtpPacketizerConfig rtp_packetizer_config)
26424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    : config_(rtp_packetizer_config),
27424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      transport_(transport),
28424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      packet_storage_(packet_storage),
29424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      sequence_number_(config_.sequence_number),
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      rtp_timestamp_(0),
31424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      packet_id_(0),
32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      send_packet_count_(0),
33424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      send_octet_count_(0) {
34424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(transport) << "Invalid argument";
35424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
36424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
37424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)RtpPacketizer::~RtpPacketizer() {}
38424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
39424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)uint16 RtpPacketizer::NextSequenceNumber() {
40424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ++sequence_number_;
41424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return sequence_number_ - 1;
42424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
43424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void RtpPacketizer::SendFrameAsPackets(const EncodedFrame& frame) {
4503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  uint16 rtp_header_length = kRtpHeaderLength + kCastHeaderLength;
46424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  uint16 max_length = config_.max_payload_length - rtp_header_length - 1;
47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  rtp_timestamp_ = frame.rtp_timestamp;
484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
49424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Split the payload evenly (round number up).
50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  size_t num_packets = (frame.data.size() + max_length) / max_length;
51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  size_t payload_length = (frame.data.size() + num_packets) / num_packets;
52424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK_LE(payload_length, max_length) << "Invalid argument";
53424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  SendPacketVector packets;
554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  size_t remaining_size = frame.data.size();
57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::string::const_iterator data_iter = frame.data.begin();
58424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  while (remaining_size > 0) {
590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    PacketRef packet(new base::RefCountedData<Packet>);
604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
61424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (remaining_size < payload_length) {
62424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      payload_length = remaining_size;
63424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
64424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    remaining_size -= payload_length;
65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    BuildCommonRTPheader(
66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        &packet->data, remaining_size == 0, frame.rtp_timestamp);
674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
68424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // Build Cast header.
69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // TODO(miu): Should we always set the ref frame bit and the ref_frame_id?
70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    DCHECK_NE(frame.dependency, EncodedFrame::UNKNOWN_DEPENDENCY);
7103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    uint8 num_extensions = 0;
7203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (frame.new_playout_delay_ms)
7303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      num_extensions++;
7403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    uint8 byte0 = kCastReferenceFrameIdBitMask;
7503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (frame.dependency == EncodedFrame::KEY)
7603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      byte0 |= kCastKeyFrameBitMask;
7703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    DCHECK_LE(num_extensions, kCastExtensionCountmask);
7803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    byte0 |= num_extensions;
7903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    packet->data.push_back(byte0);
80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    packet->data.push_back(static_cast<uint8>(frame.frame_id));
810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    size_t start_size = packet->data.size();
820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    packet->data.resize(start_size + 4);
83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    base::BigEndianWriter big_endian_writer(
840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        reinterpret_cast<char*>(&(packet->data[start_size])), 4);
85424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    big_endian_writer.WriteU16(packet_id_);
864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    big_endian_writer.WriteU16(static_cast<uint16>(num_packets - 1));
87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    packet->data.push_back(static_cast<uint8>(frame.referenced_frame_id));
8803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (frame.new_playout_delay_ms) {
8903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      packet->data.push_back(kCastRtpExtensionAdaptiveLatency << 2);
9003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      packet->data.push_back(2);  // 2 bytes
9103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      packet->data.push_back(
9203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          static_cast<uint8>(frame.new_playout_delay_ms >> 8));
9303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      packet->data.push_back(
9403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          static_cast<uint8>(frame.new_playout_delay_ms));
9503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    }
96424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
97424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // Copy payload data.
980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    packet->data.insert(packet->data.end(),
990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                        data_iter,
1000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                        data_iter + payload_length);
1018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    data_iter += payload_length;
1024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
103f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const PacketKey key =
104f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        PacedPacketSender::MakePacketKey(frame.reference_time,
105f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                         config_.ssrc,
106f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                         packet_id_++);
107f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    packets.push_back(make_pair(key, packet));
108f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
109424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // Update stats.
110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ++send_packet_count_;
111424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    send_octet_count_ += payload_length;
112424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
113424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(packet_id_ == num_packets) << "Invalid state";
1144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
115f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  packet_storage_->StoreFrame(frame.frame_id, packets);
116f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
1174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Send to network.
1184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  transport_->SendPackets(packets);
1194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
120424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Prepare for next frame.
121424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  packet_id_ = 0;
122424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
123424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void RtpPacketizer::BuildCommonRTPheader(Packet* packet,
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                         bool marker_bit,
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                         uint32 time_stamp) {
127424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  packet->push_back(0x80);
128424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  packet->push_back(static_cast<uint8>(config_.payload_type) |
129424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                    (marker_bit ? kRtpMarkerBitMask : 0));
1304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  size_t start_size = packet->size();
13168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  packet->resize(start_size + 10);
132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::BigEndianWriter big_endian_writer(
133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      reinterpret_cast<char*>(&((*packet)[start_size])), 10);
134424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  big_endian_writer.WriteU16(sequence_number_);
135424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  big_endian_writer.WriteU32(time_stamp);
136424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  big_endian_writer.WriteU32(config_.ssrc);
137424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ++sequence_number_;
138424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
139424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
140424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}  // namespace cast
141424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}  // namespace media
142