7#include <packager/media/formats/mp2t/ts_packet_writer_util.h>
9#include <absl/log/check.h>
10#include <absl/log/log.h>
12#include <packager/media/base/buffer_writer.h>
13#include <packager/media/formats/mp2t/continuity_counter.h>
21const int kPcrFieldsSize = 6;
22const uint8_t kSyncByte = 0x47;
26const int kTsPacketHeaderSize = 4;
27const int kTsPacketSize = 188;
28const int kTsPacketMaximumPayloadSize = kTsPacketSize - kTsPacketHeaderSize;
31const uint8_t kPaddingBytes[] = {
32 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
33 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
34 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
35 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
36 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
37 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
38 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
39 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
40 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
41 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
42 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
43 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
44 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
45 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
46 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
47 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
49static_assert(std::size(kPaddingBytes) >= kTsPacketMaximumPayloadSize,
50 "Padding array is not big enough.");
55void WriteAdaptationField(
bool has_pcr,
57 size_t remaining_data_size,
58 BufferWriter* writer) {
60 if (!has_pcr && remaining_data_size == kTsPacketMaximumPayloadSize - 1) {
61 writer->AppendInt(
static_cast<uint8_t
>(0));
66 const int kAdaptationFieldLengthSize = 1;
69 const int kAdaptationFieldHeaderSize = 1;
70 size_t adaptation_field_length =
71 kAdaptationFieldHeaderSize + (has_pcr ? kPcrFieldsSize : 0);
72 if (remaining_data_size < kTsPacketMaximumPayloadSize) {
73 const size_t current_ts_size = kTsPacketHeaderSize + remaining_data_size +
74 adaptation_field_length +
75 kAdaptationFieldLengthSize;
76 if (current_ts_size < kTsPacketSize) {
77 adaptation_field_length += kTsPacketSize - current_ts_size;
81 writer->AppendInt(
static_cast<uint8_t
>(adaptation_field_length));
82 int remaining_bytes =
static_cast<int>(adaptation_field_length);
83 writer->AppendInt(
static_cast<uint8_t
>(
85 static_cast<uint8_t
>(has_pcr) << 4));
90 const uint32_t most_significant_32bits_pcr =
91 static_cast<uint32_t
>(pcr_base >> 1);
92 const uint16_t pcr_last_bit_reserved_and_pcr_extension =
93 ((pcr_base & 1) << 15) | 0x7e00;
94 writer->AppendInt(most_significant_32bits_pcr);
95 writer->AppendInt(pcr_last_bit_reserved_and_pcr_extension);
96 remaining_bytes -= kPcrFieldsSize;
98 DCHECK_GE(remaining_bytes, 0);
99 if (remaining_bytes == 0)
102 DCHECK_GE(
static_cast<int>(std::size(kPaddingBytes)), remaining_bytes);
103 writer->AppendArray(kPaddingBytes, remaining_bytes);
108void WritePayloadToBufferWriter(
const uint8_t* payload,
110 bool payload_unit_start_indicator,
114 ContinuityCounter* continuity_counter,
115 BufferWriter* writer) {
116 size_t payload_bytes_written = 0;
119 const bool must_write_adaptation_header = has_pcr;
120 const size_t bytes_left = payload_size - payload_bytes_written;
121 const bool has_adaptation_field = must_write_adaptation_header ||
122 bytes_left < kTsPacketMaximumPayloadSize;
124 writer->AppendInt(kSyncByte);
125 writer->AppendInt(
static_cast<uint16_t
>(
127 static_cast<int>(payload_unit_start_indicator) << 14 | pid));
129 const uint8_t adaptation_field_control =
130 ((has_adaptation_field ? 1 : 0) << 1) | ((bytes_left != 0) ? 1 : 0);
132 writer->AppendInt(
static_cast<uint8_t
>(adaptation_field_control << 4 |
133 continuity_counter->GetNext()));
135 if (has_adaptation_field) {
136 const size_t before = writer->Size();
137 WriteAdaptationField(has_pcr, pcr_base, bytes_left, writer);
138 const size_t bytes_for_adaptation_field = writer->Size() - before;
140 const size_t write_bytes =
141 kTsPacketMaximumPayloadSize - bytes_for_adaptation_field;
142 writer->AppendArray(payload + payload_bytes_written, write_bytes);
143 payload_bytes_written += write_bytes;
145 writer->AppendArray(payload + payload_bytes_written,
146 kTsPacketMaximumPayloadSize);
147 payload_bytes_written += kTsPacketMaximumPayloadSize;
152 payload_unit_start_indicator =
false;
153 }
while (payload_bytes_written < payload_size);
All the methods that are virtual are virtual for mocking.