Shaka Packager SDK
ts_packet_writer_util.cc
1 // Copyright 2016 Google LLC. All rights reserved.
2 //
3 // Use of this source code is governed by a BSD-style
4 // license that can be found in the LICENSE file or at
5 // https://developers.google.com/open-source/licenses/bsd
6 
7 #include <packager/media/formats/mp2t/ts_packet_writer_util.h>
8 
9 #include <absl/log/check.h>
10 #include <absl/log/log.h>
11 
12 #include <packager/media/base/buffer_writer.h>
13 #include <packager/media/formats/mp2t/continuity_counter.h>
14 
15 namespace shaka {
16 namespace media {
17 namespace mp2t {
18 
19 namespace {
20 
21 const int kPcrFieldsSize = 6;
22 const uint8_t kSyncByte = 0x47;
23 
24 // This is the size of the first few fields in a TS packet, i.e. TS packet size
25 // without adaptation field or the payload.
26 const int kTsPacketHeaderSize = 4;
27 const int kTsPacketSize = 188;
28 const int kTsPacketMaximumPayloadSize =
29  kTsPacketSize - kTsPacketHeaderSize;
30 
31 // Used for adaptation field padding bytes.
32 const uint8_t kPaddingBytes[] = {
33  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
34  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
35  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
36  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
37  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
38  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
39  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
40  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
41  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
42  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
43  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
44  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
45  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
46  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
47  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
48  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
49  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
50  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
51  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
52  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
53  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
54  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
55  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
56  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
57 };
58 static_assert(std::size(kPaddingBytes) >= kTsPacketMaximumPayloadSize,
59  "Padding array is not big enough.");
60 
61 // |remaining_data_size| is the amount of data that has to be written. This may
62 // be bigger than a TS packet size.
63 // |remaining_data_size| matters if it is short and requires padding.
64 void WriteAdaptationField(bool has_pcr,
65  uint64_t pcr_base,
66  size_t remaining_data_size,
67  BufferWriter* writer) {
68  // Special case where a TS packet requires 1 byte padding.
69  if (!has_pcr && remaining_data_size == kTsPacketMaximumPayloadSize - 1) {
70  writer->AppendInt(static_cast<uint8_t>(0));
71  return;
72  }
73 
74  // The size of the field itself.
75  const int kAdaptationFieldLengthSize = 1;
76 
77  // The size of all leading flags (not including the adaptation_field_length).
78  const int kAdaptationFieldHeaderSize = 1;
79  size_t adaptation_field_length =
80  kAdaptationFieldHeaderSize + (has_pcr ? kPcrFieldsSize : 0);
81  if (remaining_data_size < kTsPacketMaximumPayloadSize) {
82  const size_t current_ts_size = kTsPacketHeaderSize + remaining_data_size +
83  adaptation_field_length +
84  kAdaptationFieldLengthSize;
85  if (current_ts_size < kTsPacketSize) {
86  adaptation_field_length += kTsPacketSize - current_ts_size;
87  }
88  }
89 
90  writer->AppendInt(static_cast<uint8_t>(adaptation_field_length));
91  int remaining_bytes = static_cast<int>(adaptation_field_length);
92  writer->AppendInt(static_cast<uint8_t>(
93  // All flags except PCR_flag are 0.
94  static_cast<uint8_t>(has_pcr) << 4));
95  remaining_bytes -= 1;
96 
97  if (has_pcr) {
98  // program_clock_reference_extension = 0.
99  const uint32_t most_significant_32bits_pcr =
100  static_cast<uint32_t>(pcr_base >> 1);
101  const uint16_t pcr_last_bit_reserved_and_pcr_extension =
102  ((pcr_base & 1) << 15) | 0x7e00; // Set the 6 reserved bits to '1'
103  writer->AppendInt(most_significant_32bits_pcr);
104  writer->AppendInt(pcr_last_bit_reserved_and_pcr_extension);
105  remaining_bytes -= kPcrFieldsSize;
106  }
107  DCHECK_GE(remaining_bytes, 0);
108  if (remaining_bytes == 0)
109  return;
110 
111  DCHECK_GE(static_cast<int>(std::size(kPaddingBytes)), remaining_bytes);
112  writer->AppendArray(kPaddingBytes, remaining_bytes);
113 }
114 
115 } // namespace
116 
117 void WritePayloadToBufferWriter(const uint8_t* payload,
118  size_t payload_size,
119  bool payload_unit_start_indicator,
120  int pid,
121  bool has_pcr,
122  uint64_t pcr_base,
123  ContinuityCounter* continuity_counter,
124  BufferWriter* writer) {
125  size_t payload_bytes_written = 0;
126 
127  do {
128  const bool must_write_adaptation_header = has_pcr;
129  const size_t bytes_left = payload_size - payload_bytes_written;
130  const bool has_adaptation_field = must_write_adaptation_header ||
131  bytes_left < kTsPacketMaximumPayloadSize;
132 
133  writer->AppendInt(kSyncByte);
134  writer->AppendInt(static_cast<uint16_t>(
135  // transport_error_indicator and transport_priority are both '0'.
136  static_cast<int>(payload_unit_start_indicator) << 14 | pid));
137 
138  const uint8_t adaptation_field_control =
139  ((has_adaptation_field ? 1 : 0) << 1) | ((bytes_left != 0) ? 1 : 0);
140  // transport_scrambling_control is '00'.
141  writer->AppendInt(static_cast<uint8_t>(adaptation_field_control << 4 |
142  continuity_counter->GetNext()));
143 
144  if (has_adaptation_field) {
145  const size_t before = writer->Size();
146  WriteAdaptationField(has_pcr, pcr_base, bytes_left, writer);
147  const size_t bytes_for_adaptation_field = writer->Size() - before;
148 
149  const size_t write_bytes =
150  kTsPacketMaximumPayloadSize - bytes_for_adaptation_field;
151  writer->AppendArray(payload + payload_bytes_written, write_bytes);
152  payload_bytes_written += write_bytes;
153  } else {
154  writer->AppendArray(payload + payload_bytes_written,
155  kTsPacketMaximumPayloadSize);
156  payload_bytes_written += kTsPacketMaximumPayloadSize;
157  }
158 
159  // Once written, not needed for this payload.
160  has_pcr = false;
161  payload_unit_start_indicator = false;
162  } while (payload_bytes_written < payload_size);
163 }
164 
165 } // namespace mp2t
166 } // namespace media
167 } // namespace shaka
All the methods that are virtual are virtual for mocking.
Definition: crypto_flags.cc:66