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 } // namespace
23 
24 Nalu::Nalu() = default;
25 
26 bool Nalu::Initialize(CodecType type,
27  const uint8_t* data,
28  uint64_t size) {
29  if (type == Nalu::kH264) {
30  return InitializeFromH264(data, size);
31  } else {
32  DCHECK_EQ(Nalu::kH265, type);
33  return InitializeFromH265(data, size);
34  }
35 }
36 
37 // ITU-T H.264 (02/2014) 7.4.1 NAL unit semantics
38 bool Nalu::InitializeFromH264(const uint8_t* data, uint64_t size) {
39  DCHECK(data);
40  if (size == 0)
41  return false;
42  const uint8_t header = data[0];
43  if ((header & 0x80) != 0) {
44  LOG(WARNING) << "forbidden_zero_bit shall be equal to 0 (header 0x"
45  << std::hex << static_cast<int>(header) << ").";
46  return false;
47  }
48 
49  data_ = data;
50  header_size_ = 1;
51  payload_size_ = size - header_size_;
52  ref_idc_ = (header >> 5) & 0x3;
53  type_ = header & 0x1F;
54 
55  // Reserved NAL units are not treated as valid NAL units here.
56  if (type_ == Nalu::H264_Unspecified || type_ == Nalu::H264_Reserved17 ||
57  type_ == Nalu::H264_Reserved18 || type_ >= Nalu::H264_Reserved22) {
58  LOG(WARNING) << "Unspecified or reserved nal_unit_type " << type_
59  << " (header 0x" << std::hex << static_cast<int>(header)
60  << ").";
61  return false;
62  } else if (type_ == Nalu::H264_IDRSlice || type_ == Nalu::H264_SPS ||
63  type_ == Nalu::H264_SPSExtension ||
64  type_ == Nalu::H264_SubsetSPS || type_ == Nalu::H264_PPS) {
65  if (ref_idc_ == 0) {
66  LOG(WARNING) << "nal_ref_idc shall not be equal to 0 for nalu type "
67  << type_ << " (header 0x" << std::hex
68  << static_cast<int>(header) << ").";
69  return false;
70  }
71  } else if (type_ == Nalu::H264_SEIMessage ||
72  (type_ >= Nalu::H264_AUD && type_ <= Nalu::H264_FillerData)) {
73  if (ref_idc_ != 0) {
74  LOG(WARNING) << "nal_ref_idc shall be equal to 0 for nalu type " << type_
75  << " (header 0x" << std::hex << static_cast<int>(header)
76  << ").";
77  return false;
78  }
79  }
80 
81  is_aud_ = type_ == H264_AUD;
82  is_vcl_ = (type_ >= Nalu::H264_NonIDRSlice && type_ <= Nalu::H264_IDRSlice);
83  is_video_slice_ =
84  (type_ == Nalu::H264_NonIDRSlice || type_ == Nalu::H264_IDRSlice);
85  can_start_access_unit_ =
86  (is_vcl_ || type_ == Nalu::H264_AUD || type_ == Nalu::H264_SPS ||
87  type_ == Nalu::H264_PPS || type_ == Nalu::H264_SEIMessage ||
88  (type_ >= Nalu::H264_PrefixNALUnit && type_ <= Nalu::H264_Reserved18));
89  return true;
90 }
91 
92 // ITU-T H.265 (04/2015) 7.4.2.2 NAL unit header semantics
93 bool Nalu::InitializeFromH265(const uint8_t* data, uint64_t size) {
94  DCHECK(data);
95  if (size < 2)
96  return false;
97  const uint16_t header = (data[0] << 8) | data[1];
98  if ((header & 0x8000) != 0) {
99  LOG(WARNING) << "forbidden_zero_bit shall be equal to 0 (header 0x"
100  << std::hex << header << ").";
101  return false;
102  }
103 
104  data_ = data;
105  header_size_ = 2;
106  payload_size_ = size - header_size_;
107 
108  type_ = (header >> 9) & 0x3F;
109  nuh_layer_id_ = (header >> 3) & 0x3F;
110  const int nuh_temporal_id_plus1 = header & 0x7;
111  if (nuh_temporal_id_plus1 == 0) {
112  LOG(WARNING) << "nul_temporal_id_plus1 shall not be equal to 0 (header 0x"
113  << std::hex << header << ").";
114  return false;
115  }
116  nuh_temporal_id_ = nuh_temporal_id_plus1 - 1;
117 
118  if (type_ == Nalu::H265_EOB && nuh_layer_id_ != 0) {
119  LOG(WARNING) << "nuh_layer_id shall be equal to 0 for nalu type " << type_
120  << " (header 0x" << std::hex << header << ").";
121  return false;
122  }
123 
124  // Reserved NAL units are not treated as valid NAL units here.
125  if ((type_ >= Nalu::H265_RSV_VCL_N10 && type_ <= Nalu::H265_RSV_VCL_R15) ||
126  (type_ >= Nalu::H265_RSV_IRAP_VCL22 && type_ < Nalu::H265_RSV_VCL31) ||
127  (type_ >= Nalu::H265_RSV_NVCL41)) {
128  LOG(WARNING) << "Unspecified or reserved nal_unit_type " << type_
129  << " (header 0x" << std::hex << header << ").";
130  return false;
131  } else if ((type_ >= Nalu::H265_BLA_W_LP &&
132  type_ <= Nalu::H265_RSV_IRAP_VCL23) ||
133  type_ == Nalu::H265_VPS || type_ == Nalu::H265_SPS ||
134  type_ == Nalu::H265_EOS || type_ == Nalu::H265_EOB) {
135  if (nuh_temporal_id_ != 0) {
136  LOG(WARNING) << "TemporalId shall be equal to 0 for nalu type " << type_
137  << " (header 0x" << std::hex << header << ").";
138  return false;
139  }
140  } else if (type_ == Nalu::H265_TSA_N || type_ == Nalu::H265_TSA_R ||
141  (nuh_layer_id_ == 0 &&
142  (type_ == Nalu::H265_STSA_N || type_ == Nalu::H265_STSA_R))) {
143  if (nuh_temporal_id_ == 0) {
144  LOG(WARNING) << "TemporalId shall not be equal to 0 for nalu type "
145  << type_ << " (header 0x" << std::hex << header << ").";
146  return false;
147  }
148  }
149 
150  is_aud_ = type_ == H265_AUD;
151  is_vcl_ = type_ >= Nalu::H265_TRAIL_N && type_ <= Nalu::H265_CRA_NUT;
152  is_video_slice_ = is_vcl_;
153  can_start_access_unit_ =
154  nuh_layer_id_ == 0 &&
155  (is_vcl_ || type_ == Nalu::H265_AUD || type_ == Nalu::H265_VPS ||
156  type_ == Nalu::H265_SPS || type_ == Nalu::H265_PPS ||
157  type_ == Nalu::H265_PREFIX_SEI ||
158  (type_ >= Nalu::H265_RSV_NVCL41 && type_ <= Nalu::H265_RSV_NVCL44) ||
159  (type_ >= Nalu::H265_UNSPEC48 && type_ <= Nalu::H265_UNSPEC55));
160  return true;
161 }
162 
163 NaluReader::NaluReader(Nalu::CodecType type,
164  uint8_t nal_length_size,
165  const uint8_t* stream,
166  uint64_t stream_size)
167  : stream_(stream),
168  stream_size_(stream_size),
169  nalu_type_(type),
170  nalu_length_size_(nal_length_size),
171  format_(nal_length_size == 0 ? kAnnexbByteStreamFormat
172  : kNalUnitStreamFormat) {
173  DCHECK(stream);
174 }
175 NaluReader::~NaluReader() {}
176 
177 NaluReader::Result NaluReader::Advance(Nalu* nalu) {
178  if (stream_size_ <= 0)
179  return NaluReader::kEOStream;
180 
181  uint8_t nalu_length_size_or_start_code_size;
182  uint64_t nalu_length;
183  if (format_ == kAnnexbByteStreamFormat) {
184  // This will move |stream_| to the start code.
185  uint64_t nalu_length_with_header;
186  if (!LocateNaluByStartCode(&nalu_length_with_header,
187  &nalu_length_size_or_start_code_size)) {
188  LOG(ERROR) << "Could not find next NALU, bytes left in stream: "
189  << stream_size_;
190  // This is actually an error. Since we always move to past the end of
191  // each NALU, if there is no next start code, then this is the first call
192  // and there are no start codes in the stream.
193  return NaluReader::kInvalidStream;
194  }
195  nalu_length = nalu_length_with_header - nalu_length_size_or_start_code_size;
196  } else {
197  BufferReader reader(stream_, stream_size_);
198  if (!reader.ReadNBytesInto8(&nalu_length, nalu_length_size_))
199  return NaluReader::kInvalidStream;
200  nalu_length_size_or_start_code_size = nalu_length_size_;
201 
202  if (nalu_length + nalu_length_size_ > stream_size_) {
203  LOG(ERROR) << "NALU length exceeds stream size: "
204  << stream_size_ << " < " << nalu_length;
205  return NaluReader::kInvalidStream;
206  }
207  if (nalu_length == 0) {
208  LOG(ERROR) << "NALU size 0";
209  return NaluReader::kInvalidStream;
210  }
211  }
212 
213  const uint8_t* nalu_data = stream_ + nalu_length_size_or_start_code_size;
214  if (!nalu->Initialize(nalu_type_, nalu_data, nalu_length))
215  return NaluReader::kInvalidStream;
216 
217  // Move parser state to after this NALU, so next time Advance
218  // is called, we will effectively be skipping it.
219  stream_ += nalu_length_size_or_start_code_size + nalu_length;
220  stream_size_ -= nalu_length_size_or_start_code_size + nalu_length;
221 
222  DVLOG(4) << "NALU type: " << static_cast<int>(nalu->type())
223  << " at: " << reinterpret_cast<const void*>(nalu->data())
224  << " data size: " << nalu->payload_size();
225 
226  return NaluReader::kOk;
227 }
228 
230  if (stream_size_ >= 3) {
231  if (IsStartCode(stream_))
232  return true;
233  }
234  if (stream_size_ >= 4) {
235  if (stream_[0] == 0x00 && IsStartCode(stream_ + 1))
236  return true;
237  }
238  return false;
239 }
240 
241 // static
242 bool NaluReader::FindStartCode(const uint8_t* data,
243  uint64_t data_size,
244  uint64_t* offset,
245  uint8_t* start_code_size) {
246  uint64_t bytes_left = data_size;
247 
248  while (bytes_left >= 3) {
249  if (IsStartCode(data)) {
250  // Found three-byte start code, set pointer at its beginning.
251  *offset = data_size - bytes_left;
252  *start_code_size = 3;
253 
254  // If there is a zero byte before this start code,
255  // then it's actually a four-byte start code, so backtrack one byte.
256  if (*offset > 0 && *(data - 1) == 0x00) {
257  --(*offset);
258  ++(*start_code_size);
259  }
260 
261  return true;
262  }
263 
264  ++data;
265  --bytes_left;
266  }
267 
268  // End of data: offset is pointing to the first byte that was not considered
269  // as a possible start of a start code.
270  *offset = data_size - bytes_left;
271  *start_code_size = 0;
272  return false;
273 }
274 
275 bool NaluReader::LocateNaluByStartCode(uint64_t* nalu_size,
276  uint8_t* start_code_size) {
277  // Find the start code of next NALU.
278  uint64_t nalu_start_off = 0;
279  uint8_t annexb_start_code_size = 0;
280  if (!FindStartCode(stream_, stream_size_,
281  &nalu_start_off, &annexb_start_code_size)) {
282  DVLOG(4) << "Could not find start code, end of stream?";
283  return false;
284  }
285 
286  // Move the stream to the beginning of the NALU (pointing at the start code).
287  stream_ += nalu_start_off;
288  stream_size_ -= nalu_start_off;
289 
290  const uint8_t* nalu_data = stream_ + annexb_start_code_size;
291  uint64_t max_nalu_data_size = stream_size_ - annexb_start_code_size;
292  if (max_nalu_data_size <= 0) {
293  DVLOG(3) << "End of stream";
294  return false;
295  }
296 
297  // Find the start code of next NALU;
298  // if successful, |nalu_size_without_start_code| is the number of bytes from
299  // after previous start code to before this one;
300  // if next start code is not found, it is still a valid NALU since there
301  // are some bytes left after the first start code: all the remaining bytes
302  // belong to the current NALU.
303  uint64_t nalu_size_without_start_code = 0;
304  uint8_t next_start_code_size = 0;
305  while (true) {
306  if (!FindStartCode(nalu_data, max_nalu_data_size,
307  &nalu_size_without_start_code, &next_start_code_size)) {
308  nalu_data += max_nalu_data_size;
309  break;
310  }
311 
312  nalu_data += nalu_size_without_start_code + next_start_code_size;
313  max_nalu_data_size -= nalu_size_without_start_code + next_start_code_size;
314  // If it is not a valid NAL unit, we will continue searching. This is to
315  // handle the case where emulation prevention are not applied.
316  Nalu nalu;
317  if (nalu.Initialize(nalu_type_, nalu_data, max_nalu_data_size)) {
318  nalu_data -= next_start_code_size;
319  break;
320  }
321  LOG(WARNING) << "Seeing invalid NAL unit. Emulation prevention may not "
322  "have been applied properly. Assuming it is part of the "
323  "previous NAL unit.";
324  }
325  *nalu_size = nalu_data - stream_;
326  *start_code_size = annexb_start_code_size;
327  return true;
328 }
329 
330 } // namespace media
331 } // namespace shaka
uint64_t payload_size() const
Size of this Nalu minus header_size().
Definition: nalu_reader.h:101
int type() const
Definition: nalu_reader.h:112
bool ReadNBytesInto8(uint64_t *v, size_t num_bytes) WARN_UNUSED_RESULT
Result Advance(Nalu *nalu)
Definition: nalu_reader.cc:177
NaluReader(Nalu::CodecType type, uint8_t nal_length_size, const uint8_t *stream, uint64_t stream_size)
Definition: nalu_reader.cc:163
const uint8_t * data() const
This is the pointer to the Nalu data, pointing to the header.
Definition: nalu_reader.h:96