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