rtp_packetizer.cc revision 116680a4aac90f2aa7413d9095a592090648e557
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" 10424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 11424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)namespace media { 12424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)namespace cast { 13424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 14424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)static const uint16 kCommonRtpHeaderLength = 12; 15424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)static const uint16 kCastRtpHeaderLength = 7; 16424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)static const uint8 kCastKeyFrameBitMask = 0x80; 17424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)static const uint8 kCastReferenceFrameIdBitMask = 0x40; 185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static const uint8 kRtpMarkerBitMask = 0x80; 19424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)RtpPacketizerConfig::RtpPacketizerConfig() 21116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch : payload_type(-1), 225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) max_payload_length(kMaxIpPacketSize - 28), // Default is IP-v4/UDP. 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) sequence_number(0), 24116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ssrc(0) {} 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)RtpPacketizerConfig::~RtpPacketizerConfig() {} 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)RtpPacketizer::RtpPacketizer(PacedSender* const transport, 29424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) PacketStorage* packet_storage, 305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu RtpPacketizerConfig rtp_packetizer_config) 31424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) : config_(rtp_packetizer_config), 32424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) transport_(transport), 33424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) packet_storage_(packet_storage), 34424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) sequence_number_(config_.sequence_number), 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) rtp_timestamp_(0), 36424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) packet_id_(0), 37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) send_packet_count_(0), 38424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) send_octet_count_(0) { 39424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) DCHECK(transport) << "Invalid argument"; 40424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 41424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 42424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)RtpPacketizer::~RtpPacketizer() {} 43424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 44424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)uint16 RtpPacketizer::NextSequenceNumber() { 45424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) ++sequence_number_; 46424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return sequence_number_ - 1; 47424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 48424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void RtpPacketizer::SendFrameAsPackets(const EncodedFrame& frame) { 50424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) uint16 rtp_header_length = kCommonRtpHeaderLength + kCastRtpHeaderLength; 51424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) uint16 max_length = config_.max_payload_length - rtp_header_length - 1; 52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) rtp_timestamp_ = frame.rtp_timestamp; 534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 54424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Split the payload evenly (round number up). 55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size_t num_packets = (frame.data.size() + max_length) / max_length; 56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size_t payload_length = (frame.data.size() + num_packets) / num_packets; 57424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) DCHECK_LE(payload_length, max_length) << "Invalid argument"; 58424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu SendPacketVector packets; 604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size_t remaining_size = frame.data.size(); 62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::string::const_iterator data_iter = frame.data.begin(); 63424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) while (remaining_size > 0) { 640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch PacketRef packet(new base::RefCountedData<Packet>); 654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 66424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (remaining_size < payload_length) { 67424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) payload_length = remaining_size; 68424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 69424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) remaining_size -= payload_length; 70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) BuildCommonRTPheader( 71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) &packet->data, remaining_size == 0, frame.rtp_timestamp); 724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 73424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Build Cast header. 74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // TODO(miu): Should we always set the ref frame bit and the ref_frame_id? 75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK_NE(frame.dependency, EncodedFrame::UNKNOWN_DEPENDENCY); 76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) packet->data.push_back( 77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ((frame.dependency == EncodedFrame::KEY) ? kCastKeyFrameBitMask : 0) | 78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) kCastReferenceFrameIdBitMask); 79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) packet->data.push_back(static_cast<uint8>(frame.frame_id)); 800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch size_t start_size = packet->data.size(); 810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch packet->data.resize(start_size + 4); 82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::BigEndianWriter big_endian_writer( 830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch reinterpret_cast<char*>(&(packet->data[start_size])), 4); 84424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) big_endian_writer.WriteU16(packet_id_); 854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) big_endian_writer.WriteU16(static_cast<uint16>(num_packets - 1)); 86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) packet->data.push_back(static_cast<uint8>(frame.referenced_frame_id)); 87424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 88424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Copy payload data. 890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch packet->data.insert(packet->data.end(), 900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch data_iter, 910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch data_iter + payload_length); 928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) data_iter += payload_length; 934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 94f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const PacketKey key = 95f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) PacedPacketSender::MakePacketKey(frame.reference_time, 96f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) config_.ssrc, 97f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) packet_id_++); 98f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) packets.push_back(make_pair(key, packet)); 99f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 100424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Update stats. 101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ++send_packet_count_; 102424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) send_octet_count_ += payload_length; 103424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 104424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) DCHECK(packet_id_ == num_packets) << "Invalid state"; 1054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 106f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) packet_storage_->StoreFrame(frame.frame_id, packets); 107f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Send to network. 1094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) transport_->SendPackets(packets); 1104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 111424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Prepare for next frame. 112424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) packet_id_ = 0; 113424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 114424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void RtpPacketizer::BuildCommonRTPheader(Packet* packet, 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool marker_bit, 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint32 time_stamp) { 118424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) packet->push_back(0x80); 119424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) packet->push_back(static_cast<uint8>(config_.payload_type) | 120424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) (marker_bit ? kRtpMarkerBitMask : 0)); 1214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) size_t start_size = packet->size(); 12268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) packet->resize(start_size + 10); 123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::BigEndianWriter big_endian_writer( 124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) reinterpret_cast<char*>(&((*packet)[start_size])), 10); 125424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) big_endian_writer.WriteU16(sequence_number_); 126424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) big_endian_writer.WriteU32(time_stamp); 127424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) big_endian_writer.WriteU32(config_.ssrc); 128424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) ++sequence_number_; 129424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 130424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 131424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} // namespace cast 132424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} // namespace media 133