Index: extensions/renderer/api/display_source/wifi_display/wifi_display_transport_stream_packetizer.cc |
diff --git a/extensions/renderer/api/display_source/wifi_display/wifi_display_transport_stream_packetizer.cc b/extensions/renderer/api/display_source/wifi_display/wifi_display_transport_stream_packetizer.cc |
index eee0a52c55a6b9fec38ef63025a270afd45f78b2..6c1917eb28b79ab255d90401556e79b113f056d7 100644 |
--- a/extensions/renderer/api/display_source/wifi_display/wifi_display_transport_stream_packetizer.cc |
+++ b/extensions/renderer/api/display_source/wifi_display/wifi_display_transport_stream_packetizer.cc |
@@ -14,6 +14,27 @@ |
#include "extensions/renderer/api/display_source/wifi_display/wifi_display_elementary_stream_packetizer.h" |
namespace extensions { |
+ |
+struct WiFiDisplayTransportStreamPacketizer::ElementaryStreamState { |
+ using ElementaryStreamType = |
+ WiFiDisplayElementaryStreamInfo::ElementaryStreamType; |
+ |
+ ElementaryStreamState(const WiFiDisplayElementaryStreamInfo& stream_info, |
+ uint16_t packet_id, |
+ uint8_t stream_id); |
+ |
+ struct { |
+ uint8_t continuity; |
+ } counters; |
+ uint16_t packet_id; |
+ uint8_t stream_id; |
+ ElementaryStreamType type; |
+ struct { |
+ uint8_t data[4]; |
+ uint8_t size; |
+ } unit_header; |
+}; |
+ |
namespace { |
uint32_t crc32(uint32_t crc, const uint8_t* data, size_t len) { |
@@ -73,127 +94,111 @@ namespace psi { |
const uint8_t kProgramAssociationTableId = 0x00u; |
const uint8_t kProgramMapTableId = 0x02u; |
-const uint16_t kFirstProgramNumber = 0x0001u; |
- |
-const size_t kCrcSize = 4u; |
-const size_t kProgramMapTableElementaryStreamEntryBaseSize = 5u; |
const size_t kTableHeaderSize = 3u; |
-size_t FillInTablePointer(uint8_t* dst, size_t min_size) { |
- size_t i = 1u; |
- if (i < min_size) { |
- std::memset(&dst[i], 0xFF, min_size - i); // Pointer filler bytes |
- i = min_size; |
- } |
- dst[0] = i - 1u; // Pointer field |
- return i; |
+void AppendTablePointer(std::vector<uint8_t>* dst, uint8_t min_size) { |
+ const uint8_t kPointerFieldSize = 1u; |
+ const uint8_t length = |
+ std::max(min_size, kPointerFieldSize) - kPointerFieldSize; |
+ dst->push_back(length); // Pointer field |
+ dst->insert(dst->end(), length, 0xFFu); // Pointer filler bytes |
} |
-size_t FillInTableHeaderAndCrc(uint8_t* header_dst, |
- uint8_t* crc_dst, |
- uint8_t table_id) { |
- size_t i; |
- const uint8_t* const header_end = header_dst + kTableHeaderSize; |
- const uint8_t* const crc_end = crc_dst + kCrcSize; |
- const size_t section_length = static_cast<size_t>(crc_end - header_end); |
+size_t FillInTableHeader(uint8_t* dst, uint8_t table_id, size_t table_size) { |
+ const size_t section_length = table_size - kTableHeaderSize; |
DCHECK_LE(section_length, 1021u); |
- // Table header. |
- i = 0u; |
- header_dst[i++] = table_id; |
- header_dst[i++] = |
- (0x1u << 7) | // Section syntax indicator (1 for PAT and PMT) |
- (0x0u << 6) | // Private bit (0 for PAT and PMT) |
- (0x3u << 4) | // Reserved bits (both bits on) |
- (0x0u << 2) | // Section length unused bits (both bits off) |
- ((section_length >> 8) & 0x03u); // Section length (10 bits) |
- header_dst[i++] = section_length & 0xFFu; // |
+ size_t i = 0u; |
+ dst[i++] = table_id; |
+ dst[i++] = (0x1u << 7) | // Section syntax indicator (1 for PAT and PMT) |
+ (0x0u << 6) | // Private bit (0 for PAT and PMT) |
+ (0x3u << 4) | // Reserved bits (both bits on) |
+ (0x0u << 2) | // Section length unused bits (both bits off) |
+ ((section_length >> 8) & 0x03u); // Section length (10 bits) |
+ dst[i++] = section_length & 0xFFu; // |
DCHECK_EQ(kTableHeaderSize, i); |
- |
- // CRC. |
- uint32_t crc = |
- crc32(0xFFFFFFFFu, header_dst, static_cast<size_t>(crc_dst - header_dst)); |
- i = 0u; |
- // Avoid swapping the crc by reversing write order. |
- crc_dst[i++] = crc & 0xFFu; |
- crc_dst[i++] = (crc >> 8) & 0xFFu; |
- crc_dst[i++] = (crc >> 16) & 0xFFu; |
- crc_dst[i++] = (crc >> 24) & 0xFFu; |
- DCHECK_EQ(kCrcSize, i); |
return i; |
} |
-size_t FillInTableSyntax(uint8_t* dst, |
- uint16_t table_id_extension, |
- uint8_t version_number) { |
- size_t i = 0u; |
- dst[i++] = table_id_extension >> 8; |
- dst[i++] = table_id_extension & 0xFFu; |
- dst[i++] = (0x3u << 6) | // Reserved bits (both bits on) |
- ((version_number & 0x1Fu) << 1) | // Version number (5 bits) |
- (0x1u << 0); // Current indicator |
- dst[i++] = 0u; // Section number |
- dst[i++] = 0u; // Last section number |
- return i; |
+void FillInTableHeaderAndAppendCrc(std::vector<uint8_t>* dst, |
+ size_t table_pos, |
+ uint8_t table_id) { |
+ const size_t kCrcSize = 4u; |
+ |
+ // Fill in a table header. |
+ const size_t table_size = dst->size() + kCrcSize - table_pos; |
+ uint8_t* table_data = &(*dst)[table_pos]; |
+ FillInTableHeader(table_data, table_id, table_size); |
+ |
+ // Append a CRC. Avoid swapping crc_value by reversing write order. |
+ uint32_t crc_value = crc32(0xFFFFFFFFu, table_data, table_size - kCrcSize); |
+ const uint8_t crc[kCrcSize] = {crc_value & 0xFFu, (crc_value >> 8) & 0xFFu, |
+ (crc_value >> 16) & 0xFFu, |
+ (crc_value >> 24) & 0xFFu}; |
+ DCHECK_EQ(kCrcSize, sizeof(crc)); |
+ dst->insert(dst->end(), std::begin(crc), std::end(crc)); |
} |
-size_t FillInProgramAssociationTableEntry(uint8_t* dst, |
- uint16_t program_number, |
- unsigned pmt_packet_id) { |
- size_t i = 0u; |
- dst[i++] = program_number >> 8; |
- dst[i++] = program_number & 0xFFu; |
- dst[i++] = (0x7u << 5) | // Reserved bits (all 3 bits on) |
- ((pmt_packet_id >> 8) & 0x1Fu); // Packet identifier (13 bits) |
- dst[i++] = pmt_packet_id & 0xFFu; // |
- return i; |
+void AppendTableSyntax(std::vector<uint8_t>* dst, |
+ uint16_t table_id_extension, |
+ uint8_t version_number) { |
+ const uint8_t table_syntax[] = { |
+ table_id_extension >> 8, table_id_extension & 0xFFu, |
+ ((0x3u << 6) | // Reserved bits (both bits on) |
+ ((version_number & 0x1Fu) << 1) | // Version number (5 bits) |
+ (true << 0)), // Current indicator |
+ 0u, // Section number |
+ 0u}; // Last section number |
+ dst->insert(dst->end(), std::begin(table_syntax), std::end(table_syntax)); |
} |
-size_t FillInProgramMapTableData(uint8_t* dst, unsigned pcr_packet_id) { |
- size_t i = 0u; |
- dst[i++] = (0x7u << 5) | // Reserved bits (all 3 bits on) |
- ((pcr_packet_id >> 8) & 0x1Fu); // Packet identifier (13 bits) |
- dst[i++] = pcr_packet_id & 0xFFu; // |
- dst[i++] = (0xFu << 4) | // Reserved bits (all 4 bits on) |
- (0x0u << 2) | // Program info length unused bits (both bits off) |
- ((0u >> 8) & 0x3u); // Program info length (10 bits) |
- dst[i++] = 0u & 0xFFu; // |
- // No program descriptors |
- return i; |
+void AppendProgramAssociationTableEntry(std::vector<uint8_t>* dst, |
+ uint16_t program_number, |
+ unsigned pmt_packet_id) { |
+ const uint8_t entry[] = { |
+ program_number >> 8, program_number & 0xFFu, |
+ ((0x7u << 5) | // Reserved bits (all 3 bits on) |
+ ((pmt_packet_id >> 8) & 0x1Fu)), // Packet identifier (13 bits) |
+ pmt_packet_id & 0xFFu}; // |
+ dst->insert(dst->end(), std::begin(entry), std::end(entry)); |
} |
-size_t CalculateElementaryStreamInfoLength( |
- const std::vector<WiFiDisplayElementaryStreamDescriptor>& es_descriptors) { |
- size_t es_info_length = 0u; |
- for (const auto& es_descriptor : es_descriptors) |
- es_info_length += es_descriptor.size(); |
- DCHECK_EQ(0u, es_info_length >> 8); |
- return es_info_length; |
+void AppendProgramMapTableDataWithoutElementaryStreamEntries( |
+ std::vector<uint8_t>* dst, |
+ unsigned pcr_packet_id) { |
+ const uint8_t data[] = { |
+ ((0x7u << 5) | // Reserved bits (all 3 bits on) |
+ ((pcr_packet_id >> 8) & 0x1Fu)), // Packet identifier (13 bits) |
+ pcr_packet_id & 0xFFu, // |
+ ((0xFu << 4) | // Reserved bits (all 4 bits on) |
+ (0x0u << 2) | // Program info length unused bits (both bits off) |
+ ((0u >> 8) & 0x3u)), // Program info length (10 bits) |
+ 0u & 0xFFu}; // |
+ // No program descriptors |
+ dst->insert(dst->end(), std::begin(data), std::end(data)); |
} |
-size_t FillInProgramMapTableElementaryStreamEntry( |
- uint8_t* dst, |
+void AppendProgramMapTableElementaryStreamEntry( |
+ std::vector<uint8_t>* dst, |
uint8_t stream_type, |
unsigned es_packet_id, |
- size_t es_info_length, |
const std::vector<WiFiDisplayElementaryStreamDescriptor>& es_descriptors) { |
- DCHECK_EQ(CalculateElementaryStreamInfoLength(es_descriptors), |
- es_info_length); |
+ size_t es_info_length = 0u; |
+ for (const auto& es_descriptor : es_descriptors) |
+ es_info_length += es_descriptor.size(); |
DCHECK_EQ(0u, es_info_length >> 10); |
- size_t i = 0u; |
- dst[i++] = stream_type; |
- dst[i++] = (0x7u << 5) | // Reserved bits (all 3 bits on) |
- ((es_packet_id >> 8) & 0x1Fu); // Packet identifier (13 bits) |
- dst[i++] = es_packet_id & 0xFFu; // |
- dst[i++] = (0xFu << 4) | // Reserved bits (all 4 bits on) |
- (0x0u << 2) | // ES info length unused bits (both bits off) |
- ((es_info_length >> 8) & 0x3u); // ES info length (10 bits) |
- dst[i++] = es_info_length & 0xFFu; // |
- for (const auto& es_descriptor : es_descriptors) { |
- std::memcpy(&dst[i], es_descriptor.data(), es_descriptor.size()); |
- i += es_descriptor.size(); |
- } |
- return i; |
+ const uint8_t data[] = { |
+ stream_type, |
+ ((0x7u << 5) | // Reserved bits (all 3 bits on) |
+ ((es_packet_id >> 8) & 0x1Fu)), // Packet identifier (13 bits) |
+ es_packet_id & 0xFFu, // |
+ ((0xFu << 4) | // Reserved bits (all 4 bits on) |
+ (0x0u << 2) | // ES info length unused bits (both bits off) |
+ ((es_info_length >> 8) & 0x3u)), // ES info length (10 bits) |
+ es_info_length & 0xFFu}; // |
+ dst->insert(dst->end(), std::begin(data), std::end(data)); |
+ for (const auto& es_descriptor : es_descriptors) |
+ dst->insert(dst->end(), es_descriptor.begin(), es_descriptor.end()); |
} |
} // namespace psi |
@@ -299,8 +304,6 @@ size_t FillInPacketHeader(uint8_t* dst, |
// Code and parameters related to the WiFi Display specification. |
namespace widi { |
-const size_t kUnitHeaderMaxSize = 4u; |
- |
// Maximum interval between meta information which includes: |
// * Program Association Table (PAT) |
// * Program Map Table (PMT) |
@@ -313,6 +316,9 @@ const unsigned kProgramClockReferencePacketId = 0x1000u; |
const unsigned kVideoStreamPacketId = 0x1011u; |
const unsigned kFirstAudioStreamPacketId = 0x1100u; |
+const uint16_t kProgramNumber = 0x0001u; |
+const uint16_t kTransportStreamId = 0x0001u; |
+ |
size_t FillInUnitHeader(uint8_t* dst, |
const WiFiDisplayElementaryStreamInfo& stream_info) { |
size_t i = 0u; |
@@ -324,63 +330,108 @@ size_t FillInUnitHeader(uint8_t* dst, |
WiFiDisplayElementaryStreamDescriptor::LPCMAudioStream>()) { |
dst[i++] = 0xA0u; // Sub stream ID (0th sub stream) |
dst[i++] = WiFiDisplayTransportStreamPacketizer::LPCM::kFramesPerUnit; |
- dst[i++] = ((0x00u << 1) | // Reserved (all 7 bits off) |
- (lpcm_descriptor->emphasis_flag() << 0)); |
- dst[i++] = ((lpcm_descriptor->bits_per_sample() << 6) | |
- (lpcm_descriptor->sampling_frequency() << 3) | |
- (lpcm_descriptor->number_of_channels() << 0)); |
+ dst[i++] = (0x00u << 1) | // Reserved (all 7 bits off) |
+ (lpcm_descriptor->emphasis_flag() << 0); |
+ dst[i++] = (lpcm_descriptor->bits_per_sample() << 6) | |
+ (lpcm_descriptor->sampling_frequency() << 3) | |
+ (lpcm_descriptor->number_of_channels() << 0); |
} |
} |
- DCHECK_LE(i, kUnitHeaderMaxSize); |
return i; |
} |
} // namespace widi |
-} // namespace |
+std::vector<uint8_t> BuildProgramAssociationTable(uint8_t version_number) { |
+ std::vector<uint8_t> table; |
-WiFiDisplayTransportStreamPacket::WiFiDisplayTransportStreamPacket( |
- const uint8_t* header_data, |
- size_t header_size) |
- : header_(header_data, header_size), |
- payload_(header_.end(), 0u), |
- filler_(kPacketSize - header_size) {} |
+ // Append a minimal table pointer. |
+ psi::AppendTablePointer(&table, 0u); |
+ |
+ // Reserve space for a table header. |
+ const size_t table_header_index = table.size(); |
+ table.resize(table.size() + psi::kTableHeaderSize); |
+ |
+ // Append a table syntax. |
+ psi::AppendTableSyntax(&table, widi::kTransportStreamId, version_number); |
+ |
+ // Append program association table data consisting of one entry. |
+ psi::AppendProgramAssociationTableEntry(&table, widi::kProgramNumber, |
+ widi::kProgramMapTablePacketId); |
+ |
+ // Fill in a table header and a CRC now that table size is known. |
+ psi::FillInTableHeaderAndAppendCrc(&table, table_header_index, |
+ psi::kProgramAssociationTableId); |
+ |
+ return table; |
+} |
+ |
+std::vector<uint8_t> BuildProgramMapTable( |
+ uint8_t version_number, |
+ const std::vector<WiFiDisplayElementaryStreamInfo>& stream_infos, |
+ const std::vector< |
+ WiFiDisplayTransportStreamPacketizer::ElementaryStreamState>& |
+ stream_states) { |
+ DCHECK_EQ(stream_infos.size(), stream_states.size()); |
+ |
+ std::vector<uint8_t> table; |
+ |
+ // Append a minimal table pointer. |
+ psi::AppendTablePointer(&table, 0u); |
+ |
+ // Reserve space for a table header. |
+ const size_t table_header_index = table.size(); |
+ table.resize(table.size() + psi::kTableHeaderSize); |
+ |
+ // Append a table syntax. |
+ psi::AppendTableSyntax(&table, widi::kProgramNumber, version_number); |
+ |
+ // Append program map table data. |
+ psi::AppendProgramMapTableDataWithoutElementaryStreamEntries( |
+ &table, widi::kProgramClockReferencePacketId); |
+ for (size_t i = 0; i < stream_infos.size(); ++i) { |
+ psi::AppendProgramMapTableElementaryStreamEntry( |
+ &table, stream_states[i].type, stream_states[i].packet_id, |
+ stream_infos[i].descriptors()); |
+ } |
+ |
+ // Fill in a table header and a CRC now that table size is known. |
+ psi::FillInTableHeaderAndAppendCrc(&table, table_header_index, |
+ psi::kProgramMapTableId); |
+ |
+ return table; |
+} |
+ |
+} // namespace |
WiFiDisplayTransportStreamPacket::WiFiDisplayTransportStreamPacket( |
const uint8_t* header_data, |
size_t header_size, |
- const uint8_t* payload_data) |
+ const uint8_t* payload_data, |
+ size_t payload_size) |
: header_(header_data, header_size), |
- payload_(payload_data, kPacketSize - header_size), |
- filler_(0u) {} |
- |
-struct WiFiDisplayTransportStreamPacketizer::ElementaryStreamState { |
- ElementaryStreamState(WiFiDisplayElementaryStreamInfo info, |
- uint16_t packet_id, |
- uint8_t stream_id) |
- : info(std::move(info)), |
- info_length( |
- psi::CalculateElementaryStreamInfoLength(this->info.descriptors())), |
- packet_id(packet_id), |
- stream_id(stream_id) {} |
- |
- WiFiDisplayElementaryStreamInfo info; |
- uint8_t info_length; |
- struct { |
- uint8_t continuity = 0u; |
- } counters; |
- uint16_t packet_id; |
- uint8_t stream_id; |
-}; |
+ payload_(payload_data, payload_size), |
+ filler_(kPacketSize - header_size - payload_size) {} |
+ |
+WiFiDisplayTransportStreamPacketizer::ElementaryStreamState:: |
+ ElementaryStreamState(const WiFiDisplayElementaryStreamInfo& stream_info, |
+ uint16_t packet_id, |
+ uint8_t stream_id) |
+ : packet_id(packet_id), stream_id(stream_id), type(stream_info.type()) { |
+ std::memset(&counters, 0x00, sizeof(counters)); |
+ unit_header.size = widi::FillInUnitHeader(unit_header.data, stream_info); |
+ DCHECK_LE(unit_header.data + unit_header.size, std::end(unit_header.data)); |
+} |
WiFiDisplayTransportStreamPacketizer::WiFiDisplayTransportStreamPacketizer( |
const base::TimeDelta& delay_for_unit_time_stamps, |
- std::vector<WiFiDisplayElementaryStreamInfo> stream_infos) |
- : delay_for_unit_time_stamps_(delay_for_unit_time_stamps) { |
+ const std::vector<WiFiDisplayElementaryStreamInfo>& stream_infos) |
+ : delay_for_unit_time_stamps_(delay_for_unit_time_stamps), |
+ program_association_table_(BuildProgramAssociationTable(0u)) { |
std::memset(&counters_, 0x00, sizeof(counters_)); |
if (!stream_infos.empty()) |
- CHECK(SetElementaryStreams(std::move(stream_infos))); |
+ CHECK(SetElementaryStreams(stream_infos)); |
} |
WiFiDisplayTransportStreamPacketizer::~WiFiDisplayTransportStreamPacketizer() {} |
@@ -406,22 +457,17 @@ bool WiFiDisplayTransportStreamPacketizer::EncodeElementaryStreamUnit( |
return false; |
} |
- uint8_t unit_header_data[widi::kUnitHeaderMaxSize]; |
- const size_t unit_header_size = |
- widi::FillInUnitHeader(unit_header_data, stream_state.info); |
- |
UpdateDelayForUnitTimeStamps(pts, dts); |
NormalizeUnitTimeStamps(&pts, &dts); |
WiFiDisplayElementaryStreamPacketizer elementary_stream_packetizer; |
WiFiDisplayElementaryStreamPacket elementary_stream_packet = |
elementary_stream_packetizer.EncodeElementaryStreamUnit( |
- stream_state.stream_id, unit_header_data, unit_header_size, unit_data, |
- unit_size, pts, dts); |
+ stream_state.stream_id, stream_state.unit_header.data, |
+ stream_state.unit_header.size, unit_data, unit_size, pts, dts); |
size_t adaptation_field_min_size = 0u; |
uint8_t header_data[WiFiDisplayTransportStreamPacket::kPacketSize]; |
- bool is_payload_unit_end; |
bool is_payload_unit_start = true; |
size_t remaining_unit_size = elementary_stream_packet.unit().size(); |
do { |
@@ -439,7 +485,11 @@ bool WiFiDisplayTransportStreamPacketizer::EncodeElementaryStreamUnit( |
// - Decoding time stamp |
bool adaptation_field_flag = false; |
size_t header_min_size; |
- if (is_payload_unit_start || is_payload_unit_end) { |
+ const bool is_payload_unit_start_or_end = |
+ is_payload_unit_start || |
+ remaining_unit_size <= WiFiDisplayTransportStreamPacket::kPacketSize - |
+ ts::kPacketHeaderSize; |
+ if (is_payload_unit_start_or_end) { |
header_min_size = ts::kPacketHeaderSize; |
if (is_payload_unit_start) { |
header_min_size += elementary_stream_packet.header().size() + |
@@ -473,7 +523,7 @@ bool WiFiDisplayTransportStreamPacketizer::EncodeElementaryStreamUnit( |
elementary_stream_packet.unit_header().size()); |
i += elementary_stream_packet.unit_header().size(); |
DCHECK_EQ(header_min_size + adaptation_field_size, i); |
- } else if (is_payload_unit_end) { |
+ } else if (is_payload_unit_start_or_end) { // Payload unit end |
if (adaptation_field_flag) { |
// Fill in an adaptation field only for padding. |
i += ts::FillInAdaptationField(&header_data[i], false, |
@@ -483,9 +533,10 @@ bool WiFiDisplayTransportStreamPacketizer::EncodeElementaryStreamUnit( |
} |
// Delegate the packet. |
- WiFiDisplayTransportStreamPacket packet( |
+ const WiFiDisplayTransportStreamPacket packet( |
header_data, i, |
- elementary_stream_packet.unit().end() - remaining_unit_size); |
+ elementary_stream_packet.unit().end() - remaining_unit_size, |
+ WiFiDisplayTransportStreamPacket::kPacketSize - i); |
DCHECK_LE(packet.payload().size(), remaining_unit_size); |
remaining_unit_size -= packet.payload().size(); |
if (!OnPacketizedTransportStreamPacket( |
@@ -494,9 +545,6 @@ bool WiFiDisplayTransportStreamPacketizer::EncodeElementaryStreamUnit( |
} |
// Prepare for the next packet. |
- is_payload_unit_end = |
- remaining_unit_size <= |
- WiFiDisplayTransportStreamPacket::kPacketSize - ts::kPacketHeaderSize; |
is_payload_unit_start = false; |
} while (remaining_unit_size > 0u); |
@@ -516,41 +564,19 @@ bool WiFiDisplayTransportStreamPacketizer::EncodeProgramAssociationTable( |
bool flush) { |
DCHECK(CalledOnValidThread()); |
- const uint16_t transport_stream_id = 0x0001u; |
- |
- uint8_t header_data[WiFiDisplayTransportStreamPacket::kPacketSize]; |
- size_t i = 0u; |
- |
// Fill in a packet header. |
- i += ts::FillInPacketHeader(&header_data[i], true, |
- widi::kProgramAssociationTablePacketId, false, |
- counters_.program_association_table_continuity++); |
- |
- // Fill in a minimal table pointer. |
- i += psi::FillInTablePointer(&header_data[i], 0u); |
- |
- // Reserve space for a table header. |
- const size_t table_header_index = i; |
- i += psi::kTableHeaderSize; |
- |
- // Fill in a table syntax. |
- const uint8_t version_number = 0u; |
- i += psi::FillInTableSyntax(&header_data[i], transport_stream_id, |
- version_number); |
- |
- // Fill in program association table data. |
- i += psi::FillInProgramAssociationTableEntry(&header_data[i], |
- psi::kFirstProgramNumber, |
- widi::kProgramMapTablePacketId); |
- |
- // Fill in a table header and a CRC now that the table size is known. |
- i += psi::FillInTableHeaderAndCrc(&header_data[table_header_index], |
- &header_data[i], |
- psi::kProgramAssociationTableId); |
+ uint8_t header_data[ts::kPacketHeaderSize]; |
+ size_t i = ts::FillInPacketHeader( |
+ header_data, true, widi::kProgramAssociationTablePacketId, false, |
+ counters_.program_association_table_continuity++); |
+ DCHECK_EQ(ts::kPacketHeaderSize, i); |
// Delegate the packet. |
return OnPacketizedTransportStreamPacket( |
- WiFiDisplayTransportStreamPacket(header_data, i), flush); |
+ WiFiDisplayTransportStreamPacket(header_data, i, |
+ program_association_table_.data(), |
+ program_association_table_.size()), |
+ flush); |
} |
bool WiFiDisplayTransportStreamPacketizer::EncodeProgramClockReference( |
@@ -581,53 +607,32 @@ bool WiFiDisplayTransportStreamPacketizer::EncodeProgramClockReference( |
// Delegate the packet. |
return OnPacketizedTransportStreamPacket( |
- WiFiDisplayTransportStreamPacket(header_data, i), flush); |
+ WiFiDisplayTransportStreamPacket(header_data, i, header_data + i, 0u), |
+ flush); |
} |
bool WiFiDisplayTransportStreamPacketizer::EncodeProgramMapTables(bool flush) { |
DCHECK(CalledOnValidThread()); |
- DCHECK(!stream_states_.empty()); |
- |
- const uint16_t program_number = psi::kFirstProgramNumber; |
- |
- uint8_t header_data[WiFiDisplayTransportStreamPacket::kPacketSize]; |
- size_t i = 0u; |
+ DCHECK(!program_map_table_.empty()); |
// Fill in a packet header. |
- i += ts::FillInPacketHeader(&header_data[i], true, |
- widi::kProgramMapTablePacketId, false, |
- counters_.program_map_table_continuity++); |
- |
- // Fill in a minimal table pointer. |
- i += psi::FillInTablePointer(&header_data[i], 0u); |
- |
- // Reserve space for a table header. |
- const size_t table_header_index = i; |
- i += psi::kTableHeaderSize; |
- |
- // Fill in a table syntax. |
- i += psi::FillInTableSyntax(&header_data[i], program_number, |
- counters_.program_map_table_version); |
- |
- // Fill in program map table data. |
- i += psi::FillInProgramMapTableData(&header_data[i], |
- widi::kProgramClockReferencePacketId); |
- for (const auto& stream_state : stream_states_) { |
- DCHECK_LE(i + psi::kProgramMapTableElementaryStreamEntryBaseSize + |
- stream_state.info_length + psi::kCrcSize, |
- WiFiDisplayTransportStreamPacket::kPacketSize); |
- i += psi::FillInProgramMapTableElementaryStreamEntry( |
- &header_data[i], stream_state.info.type(), stream_state.packet_id, |
- stream_state.info_length, stream_state.info.descriptors()); |
- } |
- |
- // Fill in a table header and a CRC now that the table size is known. |
- i += psi::FillInTableHeaderAndCrc(&header_data[table_header_index], |
- &header_data[i], psi::kProgramMapTableId); |
+ uint8_t header_data[ts::kPacketHeaderSize]; |
+ size_t i = |
+ ts::FillInPacketHeader(header_data, true, widi::kProgramMapTablePacketId, |
+ false, counters_.program_map_table_continuity++); |
+ DCHECK_EQ(ts::kPacketHeaderSize, i); |
// Delegate the packet. |
return OnPacketizedTransportStreamPacket( |
- WiFiDisplayTransportStreamPacket(header_data, i), flush); |
+ WiFiDisplayTransportStreamPacket(header_data, ts::kPacketHeaderSize, |
+ program_map_table_.data(), |
+ program_map_table_.size()), |
+ flush); |
+} |
+ |
+void WiFiDisplayTransportStreamPacketizer:: |
+ ForceEncodeMetaInformationBeforeNextUnit() { |
+ program_clock_reference_ = base::TimeTicks(); |
} |
void WiFiDisplayTransportStreamPacketizer::NormalizeUnitTimeStamps( |
@@ -650,20 +655,22 @@ void WiFiDisplayTransportStreamPacketizer::NormalizeUnitTimeStamps( |
} |
bool WiFiDisplayTransportStreamPacketizer::SetElementaryStreams( |
- std::vector<WiFiDisplayElementaryStreamInfo> stream_infos) { |
+ const std::vector<WiFiDisplayElementaryStreamInfo>& stream_infos) { |
DCHECK(CalledOnValidThread()); |
std::vector<ElementaryStreamState> new_stream_states; |
new_stream_states.reserve(stream_infos.size()); |
+ // Allocate packet and stream IDs. |
uint8_t audio_stream_id = |
WiFiDisplayElementaryStreamPacketizer::kFirstAudioStreamId; |
uint16_t audio_stream_packet_id = widi::kFirstAudioStreamPacketId; |
uint8_t private_stream_1_id = |
WiFiDisplayElementaryStreamPacketizer::kPrivateStream1Id; |
- uint16_t video_stream_packet_id = widi::kVideoStreamPacketId; |
+ uint8_t video_stream_id = |
+ WiFiDisplayElementaryStreamPacketizer::kFirstVideoStreamId; |
- for (auto& stream_info : stream_infos) { |
+ for (const auto& stream_info : stream_infos) { |
uint16_t packet_id; |
uint8_t stream_id; |
@@ -682,25 +689,33 @@ bool WiFiDisplayTransportStreamPacketizer::SetElementaryStreams( |
stream_id = private_stream_1_id++; |
break; |
case VIDEO_H264: |
- if (video_stream_packet_id != widi::kVideoStreamPacketId) |
+ if (video_stream_id != |
+ WiFiDisplayElementaryStreamPacketizer::kFirstVideoStreamId) { |
return false; |
- packet_id = video_stream_packet_id++; |
- stream_id = WiFiDisplayElementaryStreamPacketizer::kFirstVideoStreamId; |
+ } |
+ packet_id = widi::kVideoStreamPacketId; |
+ stream_id = video_stream_id++; |
break; |
} |
- new_stream_states.emplace_back(std::move(stream_info), packet_id, |
- stream_id); |
+ new_stream_states.emplace_back(stream_info, packet_id, stream_id); |
} |
- // If there are no previous states, there is no previous program map table |
- // to change, either. This ensures that the first encoded program map table |
- // has version 0. |
- if (!stream_states_.empty()) |
- ++counters_.program_map_table_version; |
+ // Build a new program map table. |
+ std::vector<uint8_t> new_program_map_table = BuildProgramMapTable( |
+ counters_.program_map_table_version, stream_infos, new_stream_states); |
+ if (new_program_map_table.size() > |
+ WiFiDisplayTransportStreamPacket::kPacketSize - ts::kPacketHeaderSize) { |
+ return false; |
+ } |
+ // Activate the new program map table and the new states. |
+ ++counters_.program_map_table_version; |
+ program_map_table_.swap(new_program_map_table); |
stream_states_.swap(new_stream_states); |
+ ForceEncodeMetaInformationBeforeNextUnit(); |
+ |
return true; |
} |