DASH Media Packaging SDK
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator
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  LOG(WARNING) << "Unspecified or reserved nal_unit_type " << type_
108  << " (header 0x" << std::hex << static_cast<int>(header)
109  << ").";
110  return false;
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  LOG(WARNING) << "Unspecified or reserved nal_unit_type " << type_
178  << " (header 0x" << std::hex << header << ").";
179  return false;
180  } else if ((type_ >= Nalu::H265_BLA_W_LP &&
181  type_ <= Nalu::H265_RSV_IRAP_VCL23) ||
182  type_ == Nalu::H265_VPS || type_ == Nalu::H265_SPS ||
183  type_ == Nalu::H265_EOS || type_ == Nalu::H265_EOB) {
184  if (nuh_temporal_id_ != 0) {
185  LOG(WARNING) << "TemporalId shall be equal to 0 for nalu type " << type_
186  << " (header 0x" << std::hex << header << ").";
187  return false;
188  }
189  } else if (type_ == Nalu::H265_TSA_N || type_ == Nalu::H265_TSA_R ||
190  (nuh_layer_id_ == 0 &&
191  (type_ == Nalu::H265_STSA_N || type_ == Nalu::H265_STSA_R))) {
192  if (nuh_temporal_id_ == 0) {
193  LOG(WARNING) << "TemporalId shall not be equal to 0 for nalu type "
194  << type_ << " (header 0x" << std::hex << header << ").";
195  return false;
196  }
197  }
198 
199  is_aud_ = type_ == H265_AUD;
200  is_vcl_ = type_ >= Nalu::H265_TRAIL_N && type_ <= Nalu::H265_CRA_NUT;
201  is_video_slice_ = is_vcl_;
202  can_start_access_unit_ =
203  nuh_layer_id_ == 0 &&
204  (is_vcl_ || type_ == Nalu::H265_AUD || type_ == Nalu::H265_VPS ||
205  type_ == Nalu::H265_SPS || type_ == Nalu::H265_PPS ||
206  type_ == Nalu::H265_PREFIX_SEI ||
207  (type_ >= Nalu::H265_RSV_NVCL41 && type_ <= Nalu::H265_RSV_NVCL44) ||
208  (type_ >= Nalu::H265_UNSPEC48 && type_ <= Nalu::H265_UNSPEC55));
209  return true;
210 }
211 
212 NaluReader::NaluReader(Nalu::CodecType type,
213  uint8_t nal_length_size,
214  const uint8_t* stream,
215  uint64_t stream_size)
216  : NaluReader(type,
217  nal_length_size,
218  stream,
219  stream_size,
220  std::vector<SubsampleEntry>()) {}
221 
222 NaluReader::NaluReader(Nalu::CodecType type,
223  uint8_t nal_length_size,
224  const uint8_t* stream,
225  uint64_t stream_size,
226  const std::vector<SubsampleEntry>& subsamples)
227  : stream_(stream),
228  stream_size_(stream_size),
229  nalu_type_(type),
230  nalu_length_size_(nal_length_size),
231  format_(nal_length_size == 0 ? kAnnexbByteStreamFormat
232  : kNalUnitStreamFormat),
233  subsamples_(subsamples) {
234  DCHECK(stream);
235 }
236 
237 NaluReader::~NaluReader() {}
238 
239 NaluReader::Result NaluReader::Advance(Nalu* nalu) {
240  if (stream_size_ <= 0)
241  return NaluReader::kEOStream;
242 
243  uint8_t nalu_length_size_or_start_code_size;
244  uint64_t nalu_length;
245  if (format_ == kAnnexbByteStreamFormat) {
246  // This will move |stream_| to the start code.
247  uint64_t nalu_length_with_header;
248  if (!LocateNaluByStartCode(&nalu_length_with_header,
249  &nalu_length_size_or_start_code_size)) {
250  LOG(ERROR) << "Could not find next NALU, bytes left in stream: "
251  << stream_size_;
252  // This is actually an error. Since we always move to past the end of
253  // each NALU, if there is no next start code, then this is the first call
254  // and there are no start codes in the stream.
255  return NaluReader::kInvalidStream;
256  }
257  nalu_length = nalu_length_with_header - nalu_length_size_or_start_code_size;
258  } else {
259  BufferReader reader(stream_, stream_size_);
260  if (IsNaluLengthEncrypted(nalu_length_size_, subsamples_)) {
261  LOG(ERROR) << "NALU length is encrypted.";
262  return NaluReader::kInvalidStream;
263  }
264  if (!reader.ReadNBytesInto8(&nalu_length, nalu_length_size_))
265  return NaluReader::kInvalidStream;
266  nalu_length_size_or_start_code_size = nalu_length_size_;
267 
268  if (nalu_length + nalu_length_size_ > stream_size_) {
269  LOG(ERROR) << "NALU length exceeds stream size: "
270  << stream_size_ << " < " << nalu_length;
271  return NaluReader::kInvalidStream;
272  }
273  if (nalu_length == 0) {
274  LOG(ERROR) << "NALU size 0";
275  return NaluReader::kInvalidStream;
276  }
277  }
278 
279  const uint8_t* nalu_data = stream_ + nalu_length_size_or_start_code_size;
280  if (!nalu->Initialize(nalu_type_, nalu_data, nalu_length))
281  return NaluReader::kInvalidStream;
282 
283  // Move parser state to after this NALU, so next time Advance
284  // is called, we will effectively be skipping it.
285  stream_ += nalu_length_size_or_start_code_size + nalu_length;
286  stream_size_ -= nalu_length_size_or_start_code_size + nalu_length;
287  UpdateSubsamples(nalu_length_size_or_start_code_size + nalu_length,
288  &subsamples_);
289 
290  DVLOG(4) << "NALU type: " << static_cast<int>(nalu->type())
291  << " at: " << reinterpret_cast<const void*>(nalu->data())
292  << " data size: " << nalu->payload_size();
293 
294  return NaluReader::kOk;
295 }
296 
298  if (stream_size_ >= 3) {
299  if (IsStartCode(stream_))
300  return true;
301  }
302  if (stream_size_ >= 4) {
303  if (stream_[0] == 0x00 && IsStartCode(stream_ + 1))
304  return true;
305  }
306  return false;
307 }
308 
309 // static
310 bool NaluReader::FindStartCode(const uint8_t* data,
311  uint64_t data_size,
312  uint64_t* offset,
313  uint8_t* start_code_size) {
314  uint64_t bytes_left = data_size;
315 
316  while (bytes_left >= 3) {
317  if (IsStartCode(data)) {
318  // Found three-byte start code, set pointer at its beginning.
319  *offset = data_size - bytes_left;
320  *start_code_size = 3;
321 
322  // If there is a zero byte before this start code,
323  // then it's actually a four-byte start code, so backtrack one byte.
324  if (*offset > 0 && *(data - 1) == 0x00) {
325  --(*offset);
326  ++(*start_code_size);
327  }
328 
329  return true;
330  }
331 
332  ++data;
333  --bytes_left;
334  }
335 
336  // End of data: offset is pointing to the first byte that was not considered
337  // as a possible start of a start code.
338  *offset = data_size - bytes_left;
339  *start_code_size = 0;
340  return false;
341 }
342 
343 // static
345  const uint8_t* data,
346  uint64_t data_size,
347  uint64_t* offset,
348  uint8_t* start_code_size,
349  const std::vector<SubsampleEntry>& subsamples) {
350  if (subsamples.empty()) {
351  return FindStartCode(data, data_size, offset, start_code_size);
352  }
353 
354  uint64_t current_offset = 0;
355  for (const SubsampleEntry& subsample : subsamples) {
356  uint16_t clear_bytes = subsample.clear_bytes;
357  if (current_offset + clear_bytes > data_size) {
358  LOG(WARNING) << "The sum of subsample sizes is greater than data_size.";
359  clear_bytes = data_size - current_offset;
360  }
361 
362  // Note that calling FindStartCode() here should get the correct
363  // start_code_size, even tho data + current_offset may be in the middle of
364  // the buffer because data + current_offset - 1 is either it shouldn't be
365  // accessed because it's data - 1 or it is encrypted.
366  const bool found_start_code = FindStartCode(
367  data + current_offset, clear_bytes, offset, start_code_size);
368  if (found_start_code) {
369  *offset += current_offset;
370  return true;
371  }
372  const uint64_t subsample_size =
373  subsample.clear_bytes + subsample.cipher_bytes;
374  current_offset += subsample_size;
375  if (current_offset > data_size) {
376  // Assign data_size here so that the returned offset points to the end of
377  // the data.
378  current_offset = data_size;
379  LOG(WARNING) << "The sum of subsamples is greater than data_size.";
380  break;
381  }
382  }
383 
384  // If there is more that's not specified by the subsample entries, assume it
385  // is in the clear.
386  if (current_offset < data_size) {
387  const bool found_start_code =
388  FindStartCode(data + current_offset, data_size - current_offset, offset,
389  start_code_size);
390  *offset += current_offset;
391  return found_start_code;
392  }
393 
394  // End of data: offset is pointing to the first byte that was not considered
395  // as a possible start of a start code.
396  *offset = current_offset;
397  *start_code_size = 0;
398  return false;
399 }
400 
401 bool NaluReader::LocateNaluByStartCode(uint64_t* nalu_size,
402  uint8_t* start_code_size) {
403  // Find the start code of next NALU.
404  uint64_t nalu_start_off = 0;
405  uint8_t annexb_start_code_size = 0;
407  stream_, stream_size_,
408  &nalu_start_off, &annexb_start_code_size, subsamples_)) {
409  DVLOG(4) << "Could not find start code, end of stream?";
410  return false;
411  }
412 
413  // Move the stream to the beginning of the NALU (pointing at the start code).
414  stream_ += nalu_start_off;
415  stream_size_ -= nalu_start_off;
416  // Shift the subsamples so that next call to FindStartCode() takes the updated
417  // subsample info.
418  UpdateSubsamples(nalu_start_off, &subsamples_);
419 
420  const uint8_t* nalu_data = stream_ + annexb_start_code_size;
421  // This is a temporary subsample entries for finding next nalu. subsamples_
422  // should not be updated below.
423  std::vector<SubsampleEntry> subsamples_for_finding_next_nalu;
424  if (!subsamples_.empty()) {
425  subsamples_for_finding_next_nalu = subsamples_;
426  UpdateSubsamples(annexb_start_code_size, &subsamples_for_finding_next_nalu);
427  }
428  uint64_t max_nalu_data_size = stream_size_ - annexb_start_code_size;
429  if (max_nalu_data_size <= 0) {
430  DVLOG(3) << "End of stream";
431  return false;
432  }
433 
434  // Find the start code of next NALU;
435  // if successful, |nalu_size_without_start_code| is the number of bytes from
436  // after previous start code to before this one;
437  // if next start code is not found, it is still a valid NALU since there
438  // are some bytes left after the first start code: all the remaining bytes
439  // belong to the current NALU.
440  uint64_t nalu_size_without_start_code = 0;
441  uint8_t next_start_code_size = 0;
442  while (true) {
444  nalu_data, max_nalu_data_size,
445  &nalu_size_without_start_code, &next_start_code_size,
446  subsamples_for_finding_next_nalu)) {
447  nalu_data += max_nalu_data_size;
448  break;
449  }
450 
451  nalu_data += nalu_size_without_start_code + next_start_code_size;
452  max_nalu_data_size -= nalu_size_without_start_code + next_start_code_size;
453  UpdateSubsamples(nalu_size_without_start_code + next_start_code_size,
454  &subsamples_for_finding_next_nalu);
455  // If it is not a valid NAL unit, we will continue searching. This is to
456  // handle the case where emulation prevention are not applied.
457  Nalu nalu;
458  if (nalu.Initialize(nalu_type_, nalu_data, max_nalu_data_size)) {
459  nalu_data -= next_start_code_size;
460  break;
461  }
462  LOG(WARNING) << "Seeing invalid NAL unit. Emulation prevention may not "
463  "have been applied properly. Assuming it is part of the "
464  "previous NAL unit.";
465  }
466  *nalu_size = nalu_data - stream_;
467  *start_code_size = annexb_start_code_size;
468  return true;
469 }
470 
471 } // namespace media
472 } // namespace shaka
uint64_t payload_size() const
Size of this Nalu minus header_size().
Definition: nalu_reader.h:102
int type() const
Definition: nalu_reader.h:113
bool ReadNBytesInto8(uint64_t *v, size_t num_bytes) WARN_UNUSED_RESULT
Result Advance(Nalu *nalu)
Definition: nalu_reader.cc:239
NaluReader(Nalu::CodecType type, uint8_t nal_length_size, const uint8_t *stream, uint64_t stream_size)
Definition: nalu_reader.cc:212
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:344
const uint8_t * data() const
This is the pointer to the Nalu data, pointing to the header.
Definition: nalu_reader.h:97