Shaka Packager SDK
ts_section_pes.cc
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <packager/media/formats/mp2t/ts_section_pes.h>
6 
7 #include <absl/log/check.h>
8 #include <absl/log/log.h>
9 
10 #include <packager/macros/logging.h>
11 #include <packager/media/base/bit_reader.h>
12 #include <packager/media/base/timestamp.h>
13 #include <packager/media/formats/mp2t/es_parser.h>
14 #include <packager/media/formats/mp2t/mp2t_common.h>
15 
16 static const int kPesStartCode = 0x000001;
17 
18 // Given that |time| is coded using 33 bits,
19 // UnrollTimestamp returns the corresponding unrolled timestamp.
20 // The unrolled timestamp is defined by:
21 // |time| + k * (2 ^ 33)
22 // where k is estimated so that the unrolled timestamp
23 // is as close as possible to |previous_unrolled_time|.
24 static int64_t UnrollTimestamp(int64_t previous_unrolled_time, int64_t time) {
25  // Mpeg2 TS timestamps have an accuracy of 33 bits.
26  const int nbits = 33;
27 
28  // |timestamp| has a precision of |nbits|
29  // so make sure the highest bits are set to 0.
30  DCHECK_EQ((time >> nbits), 0);
31 
32  // Consider 3 possibilities to estimate the missing high bits of |time|.
33  int64_t previous_unrolled_time_high = (previous_unrolled_time >> nbits);
34  int64_t time0 = ((previous_unrolled_time_high - 1) << nbits) | time;
35  int64_t time1 = ((previous_unrolled_time_high + 0) << nbits) | time;
36  int64_t time2 = ((previous_unrolled_time_high + 1) << nbits) | time;
37 
38  // Select the min absolute difference with the current time
39  // so as to ensure time continuity.
40  int64_t diff0 = time0 - previous_unrolled_time;
41  int64_t diff1 = time1 - previous_unrolled_time;
42  int64_t diff2 = time2 - previous_unrolled_time;
43  if (diff0 < 0)
44  diff0 = -diff0;
45  if (diff1 < 0)
46  diff1 = -diff1;
47  if (diff2 < 0)
48  diff2 = -diff2;
49 
50  int64_t unrolled_time;
51  int64_t min_diff;
52  if (diff1 < diff0) {
53  unrolled_time = time1;
54  min_diff = diff1;
55  } else {
56  unrolled_time = time0;
57  min_diff = diff0;
58  }
59  if (diff2 < min_diff)
60  unrolled_time = time2;
61 
62  return unrolled_time;
63 }
64 
65 static bool IsTimestampSectionValid(int64_t timestamp_section) {
66  // |pts_section| has 40 bits:
67  // - starting with either '0010' or '0011' or '0001'
68  // - and ending with a marker bit.
69  // See ITU H.222 standard - PES section.
70 
71  // Verify that all the marker bits are set to one.
72  return ((timestamp_section & 0x1) != 0) &&
73  ((timestamp_section & 0x10000) != 0) &&
74  ((timestamp_section & 0x100000000LL) != 0);
75 }
76 
77 static int64_t ConvertTimestampSectionToTimestamp(int64_t timestamp_section) {
78  return (((timestamp_section >> 33) & 0x7) << 30) |
79  (((timestamp_section >> 17) & 0x7fff) << 15) |
80  (((timestamp_section >> 1) & 0x7fff) << 0);
81 }
82 
83 namespace shaka {
84 namespace media {
85 namespace mp2t {
86 
87 TsSectionPes::TsSectionPes(std::unique_ptr<EsParser> es_parser)
88  : es_parser_(es_parser.release()),
89  wait_for_pusi_(true),
90  previous_pts_valid_(false),
91  previous_pts_(0),
92  previous_dts_valid_(false),
93  previous_dts_(0) {
94  DCHECK(es_parser_);
95 }
96 
97 TsSectionPes::~TsSectionPes() {
98 }
99 
100 bool TsSectionPes::Parse(bool payload_unit_start_indicator,
101  const uint8_t* buf,
102  int size) {
103  // Ignore partial PES.
104  if (wait_for_pusi_ && !payload_unit_start_indicator)
105  return true;
106 
107  bool parse_result = true;
108  if (payload_unit_start_indicator) {
109  // Try emitting a packet since we might have a pending PES packet
110  // with an undefined size.
111  // In this case, a unit is emitted when the next unit is coming.
112  int raw_pes_size;
113  const uint8_t* raw_pes;
114  pes_byte_queue_.Peek(&raw_pes, &raw_pes_size);
115  if (raw_pes_size > 0)
116  parse_result = Emit(true);
117 
118  // Reset the state.
119  ResetPesState();
120 
121  // Update the state.
122  wait_for_pusi_ = false;
123  }
124 
125  // Add the data to the parser state.
126  if (size > 0)
127  pes_byte_queue_.Push(buf, size);
128 
129  // Try emitting the current PES packet.
130  return (parse_result && Emit(false));
131 }
132 
133 bool TsSectionPes::Flush() {
134  // Try emitting a packet since we might have a pending PES packet
135  // with an undefined size.
136  RCHECK(Emit(true));
137 
138  // Flush the underlying ES parser.
139  return es_parser_->Flush();
140 }
141 
142 void TsSectionPes::Reset() {
143  ResetPesState();
144 
145  previous_pts_valid_ = false;
146  previous_pts_ = 0;
147  previous_dts_valid_ = false;
148  previous_dts_ = 0;
149 
150  es_parser_->Reset();
151 }
152 
153 bool TsSectionPes::Emit(bool emit_for_unknown_size) {
154  int raw_pes_size;
155  const uint8_t* raw_pes;
156  pes_byte_queue_.Peek(&raw_pes, &raw_pes_size);
157 
158  // A PES should be at least 6 bytes.
159  // Wait for more data to come if not enough bytes.
160  if (raw_pes_size < 6)
161  return true;
162 
163  // Check whether we have enough data to start parsing.
164  int pes_packet_length =
165  (static_cast<int>(raw_pes[4]) << 8) |
166  (static_cast<int>(raw_pes[5]));
167  if ((pes_packet_length == 0 && !emit_for_unknown_size) ||
168  (pes_packet_length != 0 && raw_pes_size < pes_packet_length + 6)) {
169  // Wait for more data to come either because:
170  // - there are not enough bytes,
171  // - or the PES size is unknown and the "force emit" flag is not set.
172  // (PES size might be unknown for video PES packet).
173  return true;
174  }
175  DVLOG(LOG_LEVEL_PES) << "pes_packet_length=" << pes_packet_length;
176 
177  // Parse the packet.
178  bool parse_result = ParseInternal(raw_pes, raw_pes_size);
179 
180  // Reset the state.
181  ResetPesState();
182 
183  return parse_result;
184 }
185 
186 bool TsSectionPes::ParseInternal(const uint8_t* raw_pes, int raw_pes_size) {
187  BitReader bit_reader(raw_pes, raw_pes_size);
188 
189  // Read up to the pes_packet_length (6 bytes).
190  int packet_start_code_prefix;
191  int stream_id;
192  int pes_packet_length;
193  RCHECK(bit_reader.ReadBits(24, &packet_start_code_prefix));
194  RCHECK(bit_reader.ReadBits(8, &stream_id));
195  RCHECK(bit_reader.ReadBits(16, &pes_packet_length));
196 
197  RCHECK(packet_start_code_prefix == kPesStartCode);
198  DVLOG(LOG_LEVEL_PES) << "stream_id=" << stream_id;
199  if (pes_packet_length == 0)
200  pes_packet_length = static_cast<int>(bit_reader.bits_available()) / 8;
201 
202  // Ignore the PES for unknown stream IDs.
203  // ATSC Standard A/52:2012 3. GENERIC IDENTIFICATION OF AN AC-3 STREAM.
204  // AC3/E-AC3 stream uses private stream id.
205  const int kPrivateStream1 = 0xBD;
206  // See ITU H.222 Table 2-22 "Stream_id assignments"
207  bool is_audio_stream_id =
208  ((stream_id & 0xe0) == 0xc0) || stream_id == kPrivateStream1;
209  bool is_video_stream_id = ((stream_id & 0xf0) == 0xe0);
210  if (!is_audio_stream_id && !is_video_stream_id)
211  return true;
212 
213  // Read up to "pes_header_data_length".
214  int dummy_2;
215  int PES_scrambling_control;
216  int PES_priority;
217  int data_alignment_indicator;
218  int copyright;
219  int original_or_copy;
220  int pts_dts_flags;
221  int escr_flag;
222  int es_rate_flag;
223  int dsm_trick_mode_flag;
224  int additional_copy_info_flag;
225  int pes_crc_flag;
226  int pes_extension_flag;
227  int pes_header_data_length;
228  RCHECK(bit_reader.ReadBits(2, &dummy_2));
229  RCHECK(dummy_2 == 0x2);
230  RCHECK(bit_reader.ReadBits(2, &PES_scrambling_control));
231  RCHECK(bit_reader.ReadBits(1, &PES_priority));
232  RCHECK(bit_reader.ReadBits(1, &data_alignment_indicator));
233  RCHECK(bit_reader.ReadBits(1, &copyright));
234  RCHECK(bit_reader.ReadBits(1, &original_or_copy));
235  RCHECK(bit_reader.ReadBits(2, &pts_dts_flags));
236  RCHECK(bit_reader.ReadBits(1, &escr_flag));
237  RCHECK(bit_reader.ReadBits(1, &es_rate_flag));
238  RCHECK(bit_reader.ReadBits(1, &dsm_trick_mode_flag));
239  RCHECK(bit_reader.ReadBits(1, &additional_copy_info_flag));
240  RCHECK(bit_reader.ReadBits(1, &pes_crc_flag));
241  RCHECK(bit_reader.ReadBits(1, &pes_extension_flag));
242  RCHECK(bit_reader.ReadBits(8, &pes_header_data_length));
243  int pes_header_start_size = static_cast<int>(bit_reader.bits_available()) / 8;
244 
245  // Compute the size and the offset of the ES payload.
246  // "6" for the 6 bytes read before and including |pes_packet_length|.
247  // "3" for the 3 bytes read before and including |pes_header_data_length|.
248  int es_size = pes_packet_length - 3 - pes_header_data_length;
249  int es_offset = 6 + 3 + pes_header_data_length;
250  RCHECK(es_size >= 0);
251  RCHECK(es_offset + es_size <= raw_pes_size);
252 
253  // Read the timing information section.
254  bool is_pts_valid = false;
255  bool is_dts_valid = false;
256  int64_t pts_section = 0;
257  int64_t dts_section = 0;
258  if (pts_dts_flags == 0x2) {
259  RCHECK(bit_reader.ReadBits(40, &pts_section));
260  RCHECK((((pts_section >> 36) & 0xf) == 0x2) &&
261  IsTimestampSectionValid(pts_section));
262  is_pts_valid = true;
263  }
264  if (pts_dts_flags == 0x3) {
265  RCHECK(bit_reader.ReadBits(40, &pts_section));
266  RCHECK(bit_reader.ReadBits(40, &dts_section));
267  RCHECK((((pts_section >> 36) & 0xf) == 0x3) &&
268  IsTimestampSectionValid(pts_section));
269  RCHECK((((dts_section >> 36) & 0xf) == 0x1) &&
270  IsTimestampSectionValid(dts_section));
271  is_pts_valid = true;
272  is_dts_valid = true;
273  }
274 
275  // Convert and unroll the timestamps.
276  int64_t media_pts(kNoTimestamp);
277  int64_t media_dts(kNoTimestamp);
278  if (is_dts_valid) {
279  int64_t dts = ConvertTimestampSectionToTimestamp(dts_section);
280  if (previous_dts_valid_)
281  dts = UnrollTimestamp(previous_dts_, dts);
282  previous_dts_ = dts;
283  previous_dts_valid_ = true;
284  media_dts = dts;
285  }
286  if (is_pts_valid) {
287  int64_t pts = ConvertTimestampSectionToTimestamp(pts_section);
288  if (previous_pts_valid_) {
289  pts = UnrollTimestamp(previous_pts_, pts);
290  } else {
291  if (media_dts != kNoTimestamp) {
292  pts = UnrollTimestamp(media_dts, pts);
293  }
294  }
295  previous_pts_ = pts;
296  previous_pts_valid_ = true;
297  media_pts = pts;
298  }
299 
300  // Discard the rest of the PES packet header.
301  DCHECK_EQ(bit_reader.bits_available() % 8, 0u);
302  int pes_header_remaining_size =
303  pes_header_data_length -
304  (pes_header_start_size -
305  static_cast<int>(bit_reader.bits_available()) / 8);
306  RCHECK(pes_header_remaining_size >= 0);
307 
308  // Read the PES packet.
309  DVLOG(LOG_LEVEL_PES) << "Emit a reassembled PES:"
310  << " size=" << es_size << " pts=" << media_pts
311  << " dts=" << media_dts << " data_alignment_indicator="
312  << data_alignment_indicator;
313  return es_parser_->Parse(&raw_pes[es_offset], es_size, media_pts, media_dts);
314 }
315 
316 void TsSectionPes::ResetPesState() {
317  pes_byte_queue_.Reset();
318  wait_for_pusi_ = true;
319 }
320 
321 } // namespace mp2t
322 } // namespace media
323 } // namespace shaka
All the methods that are virtual are virtual for mocking.
Definition: crypto_flags.cc:66