Shaka Packager SDK
nalu_reader.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/codecs/nalu_reader.h>
8 
9 #include <iostream>
10 
11 #include <absl/log/check.h>
12 #include <absl/log/log.h>
13 
14 #include <packager/macros/logging.h>
15 #include <packager/media/base/buffer_reader.h>
16 #include <packager/media/codecs/h264_parser.h>
17 
18 namespace shaka {
19 namespace media {
20 
21 namespace {
22 inline bool IsStartCode(const uint8_t* data) {
23  return data[0] == 0x00 && data[1] == 0x00 && data[2] == 0x01;
24 }
25 
26 // Edits |subsamples| given the number of consumed bytes.
27 void UpdateSubsamples(uint64_t consumed_bytes,
28  std::vector<SubsampleEntry>* subsamples) {
29  if (consumed_bytes == 0 || subsamples->empty()) {
30  return;
31  }
32  size_t num_entries_to_delete = 0;
33  for (SubsampleEntry& subsample : *subsamples) {
34  if (subsample.clear_bytes > consumed_bytes) {
35  subsample.clear_bytes -= consumed_bytes;
36  consumed_bytes = 0;
37  break;
38  }
39  consumed_bytes -= subsample.clear_bytes;
40  subsample.clear_bytes = 0;
41 
42  if (subsample.cipher_bytes > consumed_bytes) {
43  subsample.cipher_bytes -= consumed_bytes;
44  consumed_bytes = 0;
45  break;
46  }
47  consumed_bytes -= subsample.cipher_bytes;
48  subsample.cipher_bytes = 0;
49  ++num_entries_to_delete;
50  }
51 
52  subsamples->erase(subsamples->begin(),
53  subsamples->begin() + num_entries_to_delete);
54 }
55 
56 bool IsNaluLengthEncrypted(
57  uint8_t nalu_length_size,
58  const std::vector<SubsampleEntry>& subsamples) {
59  if (subsamples.empty())
60  return false;
61 
62  for (const SubsampleEntry& subsample : subsamples) {
63  if (subsample.clear_bytes >= nalu_length_size) {
64  return false;
65  }
66  nalu_length_size -= subsample.clear_bytes;
67  if (subsample.cipher_bytes > 0) {
68  return true;
69  }
70  }
71  // Ran out of subsamples. Assume the rest is in the clear.
72  return false;
73 }
74 } // namespace
75 
76 Nalu::Nalu() = default;
77 
78 bool Nalu::Initialize(CodecType type,
79  const uint8_t* data,
80  uint64_t size) {
81  if (type == Nalu::kH264) {
82  return InitializeFromH264(data, size);
83  } else {
84  DCHECK_EQ(Nalu::kH265, type);
85  return InitializeFromH265(data, size);
86  }
87 }
88 
89 // ITU-T H.264 (02/2014) 7.4.1 NAL unit semantics
90 bool Nalu::InitializeFromH264(const uint8_t* data, uint64_t size) {
91  DCHECK(data);
92  if (size == 0)
93  return false;
94  const uint8_t header = data[0];
95  if ((header & 0x80) != 0) {
96  LOG(WARNING) << "forbidden_zero_bit shall be equal to 0 (header 0x"
97  << std::hex << static_cast<int>(header) << ").";
98  return false;
99  }
100 
101  data_ = data;
102  header_size_ = 1;
103  payload_size_ = size - header_size_;
104  ref_idc_ = (header >> 5) & 0x3;
105  type_ = header & 0x1F;
106 
107  // Reserved NAL units are not treated as valid NAL units here.
108  if (type_ == Nalu::H264_Unspecified || type_ == Nalu::H264_Reserved17 ||
109  type_ == Nalu::H264_Reserved18 || type_ >= Nalu::H264_Reserved22) {
110  VLOG(1) << "Unspecified or reserved nal_unit_type " << type_
111  << " (header 0x" << std::hex << static_cast<int>(header) << ").";
112  // Allow reserved NAL units. Some encoders and extended codecs use the
113  // reserved NAL units to carry their private data.
114  } else if (type_ == Nalu::H264_IDRSlice || type_ == Nalu::H264_SPS ||
115  type_ == Nalu::H264_SPSExtension ||
116  type_ == Nalu::H264_SubsetSPS || type_ == Nalu::H264_PPS) {
117  if (ref_idc_ == 0) {
118  LOG(WARNING) << "nal_ref_idc shall not be equal to 0 for nalu type "
119  << type_ << " (header 0x" << std::hex
120  << static_cast<int>(header) << ").";
121  return false;
122  }
123  } else if (type_ == Nalu::H264_SEIMessage ||
124  (type_ >= Nalu::H264_AUD && type_ <= Nalu::H264_FillerData)) {
125  if (ref_idc_ != 0) {
126  LOG(WARNING) << "nal_ref_idc shall be equal to 0 for nalu type " << type_
127  << " (header 0x" << std::hex << static_cast<int>(header)
128  << ").";
129  return false;
130  }
131  }
132 
133  is_aud_ = type_ == H264_AUD;
134  is_vcl_ = (type_ >= Nalu::H264_NonIDRSlice && type_ <= Nalu::H264_IDRSlice);
135  is_video_slice_ =
136  (type_ == Nalu::H264_NonIDRSlice || type_ == Nalu::H264_IDRSlice);
137  can_start_access_unit_ =
138  (is_vcl_ || type_ == Nalu::H264_AUD || type_ == Nalu::H264_SPS ||
139  type_ == Nalu::H264_PPS || type_ == Nalu::H264_SEIMessage ||
140  (type_ >= Nalu::H264_PrefixNALUnit && type_ <= Nalu::H264_Reserved18));
141  return true;
142 }
143 
144 // ITU-T H.265 (04/2015) 7.4.2.2 NAL unit header semantics
145 bool Nalu::InitializeFromH265(const uint8_t* data, uint64_t size) {
146  DCHECK(data);
147  if (size < 2)
148  return false;
149  const uint16_t header = (data[0] << 8) | data[1];
150  if ((header & 0x8000) != 0) {
151  LOG(WARNING) << "forbidden_zero_bit shall be equal to 0 (header 0x"
152  << std::hex << header << ").";
153  return false;
154  }
155 
156  data_ = data;
157  header_size_ = 2;
158  payload_size_ = size - header_size_;
159 
160  type_ = (header >> 9) & 0x3F;
161  nuh_layer_id_ = (header >> 3) & 0x3F;
162  const int nuh_temporal_id_plus1 = header & 0x7;
163  if (nuh_temporal_id_plus1 == 0) {
164  LOG(WARNING) << "nul_temporal_id_plus1 shall not be equal to 0 (header 0x"
165  << std::hex << header << ").";
166  return false;
167  }
168  nuh_temporal_id_ = nuh_temporal_id_plus1 - 1;
169 
170  if (type_ == Nalu::H265_EOB && nuh_layer_id_ != 0) {
171  LOG(WARNING) << "nuh_layer_id shall be equal to 0 for nalu type " << type_
172  << " (header 0x" << std::hex << header << ").";
173  return false;
174  }
175 
176  // Reserved NAL units are not treated as valid NAL units here.
177  if ((type_ >= Nalu::H265_RSV_VCL_N10 && type_ <= Nalu::H265_RSV_VCL_R15) ||
178  (type_ >= Nalu::H265_RSV_IRAP_VCL22 && type_ < Nalu::H265_RSV_VCL31) ||
179  (type_ >= Nalu::H265_RSV_NVCL41)) {
180  VLOG(1) << "Unspecified or reserved nal_unit_type " << type_
181  << " (header 0x" << std::hex << header << ").";
182  // Allow reserved NAL units. Some encoders and extended codecs use the
183  // reserved NAL units to carry their private data. For example, Dolby Vision
184  // uses NAL unit type 62.
185  } else if ((type_ >= Nalu::H265_BLA_W_LP &&
186  type_ <= Nalu::H265_RSV_IRAP_VCL23) ||
187  type_ == Nalu::H265_VPS || type_ == Nalu::H265_SPS ||
188  type_ == Nalu::H265_EOS || type_ == Nalu::H265_EOB) {
189  if (nuh_temporal_id_ != 0) {
190  LOG(WARNING) << "TemporalId shall be equal to 0 for nalu type " << type_
191  << " (header 0x" << std::hex << header << ").";
192  return false;
193  }
194  } else if (type_ == Nalu::H265_TSA_N || type_ == Nalu::H265_TSA_R ||
195  (nuh_layer_id_ == 0 &&
196  (type_ == Nalu::H265_STSA_N || type_ == Nalu::H265_STSA_R))) {
197  if (nuh_temporal_id_ == 0) {
198  LOG(WARNING) << "TemporalId shall not be equal to 0 for nalu type "
199  << type_ << " (header 0x" << std::hex << header << ").";
200  return false;
201  }
202  }
203 
204  is_aud_ = type_ == H265_AUD;
205  is_vcl_ = type_ >= Nalu::H265_TRAIL_N && type_ <= Nalu::H265_RSV_VCL31;
206  is_video_slice_ = is_vcl_;
207  can_start_access_unit_ =
208  nuh_layer_id_ == 0 &&
209  (is_vcl_ || type_ == Nalu::H265_AUD || type_ == Nalu::H265_VPS ||
210  type_ == Nalu::H265_SPS || type_ == Nalu::H265_PPS ||
211  type_ == Nalu::H265_PREFIX_SEI ||
212  (type_ >= Nalu::H265_RSV_NVCL41 && type_ <= Nalu::H265_RSV_NVCL44) ||
213  (type_ >= Nalu::H265_UNSPEC48 && type_ <= Nalu::H265_UNSPEC55));
214  return true;
215 }
216 
217 NaluReader::NaluReader(Nalu::CodecType type,
218  uint8_t nal_length_size,
219  const uint8_t* stream,
220  uint64_t stream_size)
221  : NaluReader(type,
222  nal_length_size,
223  stream,
224  stream_size,
225  std::vector<SubsampleEntry>()) {}
226 
227 NaluReader::NaluReader(Nalu::CodecType type,
228  uint8_t nal_length_size,
229  const uint8_t* stream,
230  uint64_t stream_size,
231  const std::vector<SubsampleEntry>& subsamples)
232  : stream_(stream),
233  stream_size_(stream_size),
234  nalu_type_(type),
235  nalu_length_size_(nal_length_size),
236  format_(nal_length_size == 0 ? kAnnexbByteStreamFormat
237  : kNalUnitStreamFormat),
238  subsamples_(subsamples) {
239  DCHECK(stream);
240 }
241 
242 NaluReader::~NaluReader() {}
243 
244 NaluReader::Result NaluReader::Advance(Nalu* nalu) {
245  if (stream_size_ <= 0)
246  return NaluReader::kEOStream;
247 
248  uint8_t nalu_length_size_or_start_code_size;
249  uint64_t nalu_length;
250  if (format_ == kAnnexbByteStreamFormat) {
251  // This will move |stream_| to the start code.
252  uint64_t nalu_length_with_header;
253  if (!LocateNaluByStartCode(&nalu_length_with_header,
254  &nalu_length_size_or_start_code_size)) {
255  LOG(ERROR) << "Could not find next NALU, bytes left in stream: "
256  << stream_size_;
257  // This is actually an error. Since we always move to past the end of
258  // each NALU, if there is no next start code, then this is the first call
259  // and there are no start codes in the stream.
260  return NaluReader::kInvalidStream;
261  }
262  nalu_length = nalu_length_with_header - nalu_length_size_or_start_code_size;
263  } else {
264  BufferReader reader(stream_, stream_size_);
265  if (IsNaluLengthEncrypted(nalu_length_size_, subsamples_)) {
266  LOG(ERROR) << "NALU length is encrypted.";
267  return NaluReader::kInvalidStream;
268  }
269  if (!reader.ReadNBytesInto8(&nalu_length, nalu_length_size_))
270  return NaluReader::kInvalidStream;
271  nalu_length_size_or_start_code_size = nalu_length_size_;
272 
273  if (nalu_length + nalu_length_size_ > stream_size_) {
274  LOG(ERROR) << "NALU length exceeds stream size: "
275  << stream_size_ << " < " << nalu_length;
276  return NaluReader::kInvalidStream;
277  }
278  if (nalu_length == 0) {
279  LOG(ERROR) << "NALU size 0";
280  return NaluReader::kInvalidStream;
281  }
282  }
283 
284  const uint8_t* nalu_data = stream_ + nalu_length_size_or_start_code_size;
285  if (!nalu->Initialize(nalu_type_, nalu_data, nalu_length))
286  return NaluReader::kInvalidStream;
287 
288  // Move parser state to after this NALU, so next time Advance
289  // is called, we will effectively be skipping it.
290  stream_ += nalu_length_size_or_start_code_size + nalu_length;
291  stream_size_ -= nalu_length_size_or_start_code_size + nalu_length;
292  UpdateSubsamples(nalu_length_size_or_start_code_size + nalu_length,
293  &subsamples_);
294 
295  DVLOG(4) << "NALU type: " << static_cast<int>(nalu->type())
296  << " at: " << reinterpret_cast<const void*>(nalu->data())
297  << " data size: " << nalu->payload_size();
298 
299  return NaluReader::kOk;
300 }
301 
303  if (stream_size_ >= 3) {
304  if (IsStartCode(stream_))
305  return true;
306  }
307  if (stream_size_ >= 4) {
308  if (stream_[0] == 0x00 && IsStartCode(stream_ + 1))
309  return true;
310  }
311  return false;
312 }
313 
314 // static
315 bool NaluReader::FindStartCode(const uint8_t* data,
316  uint64_t data_size,
317  uint64_t* offset,
318  uint8_t* start_code_size) {
319  uint64_t bytes_left = data_size;
320 
321  while (bytes_left >= 3) {
322  if (IsStartCode(data)) {
323  // Found three-byte start code, set pointer at its beginning.
324  *offset = data_size - bytes_left;
325  *start_code_size = 3;
326 
327  // If there is a zero byte before this start code,
328  // then it's actually a four-byte start code, so backtrack one byte.
329  if (*offset > 0 && *(data - 1) == 0x00) {
330  --(*offset);
331  ++(*start_code_size);
332  }
333 
334  return true;
335  }
336 
337  ++data;
338  --bytes_left;
339  }
340 
341  // End of data: offset is pointing to the first byte that was not considered
342  // as a possible start of a start code.
343  *offset = data_size - bytes_left;
344  *start_code_size = 0;
345  return false;
346 }
347 
348 // static
350  const uint8_t* data,
351  uint64_t data_size,
352  uint64_t* offset,
353  uint8_t* start_code_size,
354  const std::vector<SubsampleEntry>& subsamples) {
355  if (subsamples.empty()) {
356  return FindStartCode(data, data_size, offset, start_code_size);
357  }
358 
359  uint64_t current_offset = 0;
360  for (const SubsampleEntry& subsample : subsamples) {
361  uint16_t clear_bytes = subsample.clear_bytes;
362  if (current_offset + clear_bytes > data_size) {
363  LOG(WARNING) << "The sum of subsample sizes is greater than data_size.";
364  clear_bytes = data_size - current_offset;
365  }
366 
367  // Note that calling FindStartCode() here should get the correct
368  // start_code_size, even tho data + current_offset may be in the middle of
369  // the buffer because data + current_offset - 1 is either it shouldn't be
370  // accessed because it's data - 1 or it is encrypted.
371  const bool found_start_code = FindStartCode(
372  data + current_offset, clear_bytes, offset, start_code_size);
373  if (found_start_code) {
374  *offset += current_offset;
375  return true;
376  }
377  const uint64_t subsample_size =
378  subsample.clear_bytes + subsample.cipher_bytes;
379  current_offset += subsample_size;
380  if (current_offset > data_size) {
381  // Assign data_size here so that the returned offset points to the end of
382  // the data.
383  current_offset = data_size;
384  LOG(WARNING) << "The sum of subsamples is greater than data_size.";
385  break;
386  }
387  }
388 
389  // If there is more that's not specified by the subsample entries, assume it
390  // is in the clear.
391  if (current_offset < data_size) {
392  const bool found_start_code =
393  FindStartCode(data + current_offset, data_size - current_offset, offset,
394  start_code_size);
395  *offset += current_offset;
396  return found_start_code;
397  }
398 
399  // End of data: offset is pointing to the first byte that was not considered
400  // as a possible start of a start code.
401  *offset = current_offset;
402  *start_code_size = 0;
403  return false;
404 }
405 
406 bool NaluReader::LocateNaluByStartCode(uint64_t* nalu_size,
407  uint8_t* start_code_size) {
408  // Find the start code of next NALU.
409  uint64_t nalu_start_off = 0;
410  uint8_t annexb_start_code_size = 0;
412  stream_, stream_size_,
413  &nalu_start_off, &annexb_start_code_size, subsamples_)) {
414  DVLOG(4) << "Could not find start code, end of stream?";
415  return false;
416  }
417 
418  // Move the stream to the beginning of the NALU (pointing at the start code).
419  stream_ += nalu_start_off;
420  stream_size_ -= nalu_start_off;
421  // Shift the subsamples so that next call to FindStartCode() takes the updated
422  // subsample info.
423  UpdateSubsamples(nalu_start_off, &subsamples_);
424 
425  const uint8_t* nalu_data = stream_ + annexb_start_code_size;
426  // This is a temporary subsample entries for finding next nalu. subsamples_
427  // should not be updated below.
428  std::vector<SubsampleEntry> subsamples_for_finding_next_nalu;
429  if (!subsamples_.empty()) {
430  subsamples_for_finding_next_nalu = subsamples_;
431  UpdateSubsamples(annexb_start_code_size, &subsamples_for_finding_next_nalu);
432  }
433  uint64_t max_nalu_data_size = stream_size_ - annexb_start_code_size;
434  if (max_nalu_data_size <= 0) {
435  DVLOG(3) << "End of stream";
436  return false;
437  }
438 
439  // Find the start code of next NALU;
440  // if successful, |nalu_size_without_start_code| is the number of bytes from
441  // after previous start code to before this one;
442  // if next start code is not found, it is still a valid NALU since there
443  // are some bytes left after the first start code: all the remaining bytes
444  // belong to the current NALU.
445  uint64_t nalu_size_without_start_code = 0;
446  uint8_t next_start_code_size = 0;
447  while (true) {
449  nalu_data, max_nalu_data_size,
450  &nalu_size_without_start_code, &next_start_code_size,
451  subsamples_for_finding_next_nalu)) {
452  nalu_data += max_nalu_data_size;
453  break;
454  }
455 
456  nalu_data += nalu_size_without_start_code + next_start_code_size;
457  max_nalu_data_size -= nalu_size_without_start_code + next_start_code_size;
458  UpdateSubsamples(nalu_size_without_start_code + next_start_code_size,
459  &subsamples_for_finding_next_nalu);
460  // If it is not a valid NAL unit, we will continue searching. This is to
461  // handle the case where emulation prevention are not applied.
462  Nalu nalu;
463  if (nalu.Initialize(nalu_type_, nalu_data, max_nalu_data_size)) {
464  nalu_data -= next_start_code_size;
465  break;
466  }
467  LOG(WARNING) << "Seeing invalid NAL unit. Emulation prevention may not "
468  "have been applied properly. Assuming it is part of the "
469  "previous NAL unit.";
470  }
471  *nalu_size = nalu_data - stream_;
472  *start_code_size = annexb_start_code_size;
473  return true;
474 }
475 
476 } // namespace media
477 } // namespace shaka
bool ReadNBytesInto8(uint64_t *v, size_t num_bytes)
NaluReader(Nalu::CodecType type, uint8_t nal_length_size, const uint8_t *stream, uint64_t stream_size)
Definition: nalu_reader.cc:217
static bool FindStartCodeInClearRange(const uint8_t *data, uint64_t data_size, uint64_t *offset, uint8_t *start_code_size, const std::vector< SubsampleEntry > &subsamples)
Definition: nalu_reader.cc:349
Result Advance(Nalu *nalu)
Definition: nalu_reader.cc:244
const uint8_t * data() const
This is the pointer to the Nalu data, pointing to the header.
Definition: nalu_reader.h:96
int type() const
Definition: nalu_reader.h:112
uint64_t payload_size() const
Size of this Nalu minus header_size().
Definition: nalu_reader.h:101
All the methods that are virtual are virtual for mocking.
Definition: crypto_flags.cc:66