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