Index: extensions/renderer/api/display_source/wifi_display/wifi_display_media_packetizer.cc |
diff --git a/extensions/renderer/api/display_source/wifi_display/wifi_display_media_packetizer.cc b/extensions/renderer/api/display_source/wifi_display/wifi_display_media_packetizer.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..f8f9cf23b5dff1312ed438701f480ad69d22224e |
--- /dev/null |
+++ b/extensions/renderer/api/display_source/wifi_display/wifi_display_media_packetizer.cc |
@@ -0,0 +1,110 @@ |
+// Copyright 2016 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 "extensions/renderer/api/display_source/wifi_display/wifi_display_media_packetizer.h" |
+ |
+#include <utility> |
+ |
+#include "base/logging.h" |
+#include "base/rand_util.h" |
+#include "crypto/random.h" |
+#include "extensions/renderer/api/display_source/wifi_display/wifi_display_elementary_stream_info.h" |
+ |
+namespace extensions { |
+namespace { |
+const size_t kMaxTransportStreamPacketCount = 7u; |
+const uint8_t kProtocolPayloadTypeMP2T = 33u; |
+const uint8_t kProtocolVersion = 2u; |
+} // namespace |
+ |
+WiFiDisplayMediaDatagramPacket::WiFiDisplayMediaDatagramPacket() = default; |
+ |
+WiFiDisplayMediaDatagramPacket::WiFiDisplayMediaDatagramPacket( |
+ WiFiDisplayMediaDatagramPacket&&) = default; |
+ |
+WiFiDisplayMediaPacketizer::WiFiDisplayMediaPacketizer( |
+ const base::TimeDelta& delay_for_unit_time_stamps, |
+ std::vector<WiFiDisplayElementaryStreamInfo> stream_infos, |
+ const PacketizedCallback& on_packetized) |
+ : WiFiDisplayTransportStreamPacketizer(delay_for_unit_time_stamps, |
+ std::move(stream_infos)), |
+ on_packetized_media_datagram_packet_(on_packetized) { |
+ // Sequence numbers are mainly used for detecting lossed packets within one |
+ // RTP session. The initial value SHOULD be random (unpredictable) to make |
+ // known-plaintext attacks on encryption more difficult, in case the packets |
+ // flow through a translator that encrypts them. |
+ crypto::RandBytes(&sequence_number_, sizeof(sequence_number_)); |
+ base::RandBytes(&synchronization_source_identifier_, |
+ sizeof(synchronization_source_identifier_)); |
+} |
+ |
+WiFiDisplayMediaPacketizer::~WiFiDisplayMediaPacketizer() {} |
+ |
+bool WiFiDisplayMediaPacketizer::OnPacketizedTransportStreamPacket( |
+ const WiFiDisplayTransportStreamPacket& transport_stream_packet, |
+ bool flush) { |
+ DCHECK(CalledOnValidThread()); |
+ |
+ if (media_datagram_packet_.empty()) { |
+ // Convert time to the number of 90 kHz ticks since some epoch. |
+ const uint64_t us = static_cast<uint64_t>( |
+ (base::TimeTicks::Now() - base::TimeTicks()).InMicroseconds()); |
+ const uint64_t time_stamp = (us * 90u + 500u) / 1000u; |
+ const uint8_t header_without_identifiers[] = { |
+ (kProtocolVersion << 6 | // Version (2 bits) |
+ 0x0u << 5 | // Padding (no) |
+ 0x0u << 4 | // Extension (no) |
+ 0u << 0), // CSRC count (4 bits) |
+ (0x0u << 7 | // Marker (no) |
+ kProtocolPayloadTypeMP2T << 0), // Payload type (7 bits) |
+ sequence_number_ >> 8, // Sequence number (16 bits) |
+ sequence_number_ & 0xFFu, // |
+ (time_stamp >> 24) & 0xFFu, // Time stamp (32 bits) |
+ (time_stamp >> 16) & 0xFFu, // |
+ (time_stamp >> 8) & 0xFFu, // |
+ time_stamp & 0xFFu}; // |
+ ++sequence_number_; |
+ media_datagram_packet_.reserve( |
+ sizeof(header_without_identifiers) + |
+ sizeof(synchronization_source_identifier_) + |
+ kMaxTransportStreamPacketCount * |
+ WiFiDisplayTransportStreamPacket::kPacketSize); |
+ media_datagram_packet_.insert(media_datagram_packet_.end(), |
+ std::begin(header_without_identifiers), |
+ std::end(header_without_identifiers)); |
+ media_datagram_packet_.insert( |
+ media_datagram_packet_.end(), |
+ std::begin(synchronization_source_identifier_), |
+ std::end(synchronization_source_identifier_)); |
+ DCHECK_EQ(0u, media_datagram_packet_.size() / |
+ WiFiDisplayTransportStreamPacket::kPacketSize); |
+ } |
+ |
+ // Append header and payload data. |
+ media_datagram_packet_.insert(media_datagram_packet_.end(), |
+ transport_stream_packet.header().begin(), |
+ transport_stream_packet.header().end()); |
+ media_datagram_packet_.insert(media_datagram_packet_.end(), |
+ transport_stream_packet.payload().begin(), |
+ transport_stream_packet.payload().end()); |
+ media_datagram_packet_.insert(media_datagram_packet_.end(), |
+ transport_stream_packet.filler().size(), |
+ transport_stream_packet.filler().value()); |
+ |
+ // Combine multiple transport stream packets into one datagram packet |
+ // by delaying delegation whenever possible. |
+ if (!flush) { |
+ const size_t transport_stream_packet_count = |
+ media_datagram_packet_.size() / |
+ WiFiDisplayTransportStreamPacket::kPacketSize; |
+ if (transport_stream_packet_count < kMaxTransportStreamPacketCount) |
+ return true; |
+ } |
+ |
+ WiFiDisplayMediaDatagramPacket packet; |
+ packet.swap(media_datagram_packet_); |
+ return on_packetized_media_datagram_packet_.Run(std::move(packet)); |
+} |
+ |
+} // namespace extensions |