DASH Media Packaging SDK
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator
h264_parser.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/codecs/h264_parser.h"
6 
7 #include "packager/base/logging.h"
8 #include "packager/base/memory/scoped_ptr.h"
9 #include "packager/base/stl_util.h"
10 #include "packager/media/base/buffer_reader.h"
11 
12 namespace shaka {
13 namespace media {
14 
15 // Implemented according to ISO/IEC 14496-10:2005 7.4.2.1 Sequence parameter set
16 // RBSP semantics.
17 bool ExtractResolutionFromSps(const H264Sps& sps,
18  uint32_t* coded_width,
19  uint32_t* coded_height,
20  uint32_t* pixel_width,
21  uint32_t* pixel_height) {
22  int crop_x = 0;
23  int crop_y = 0;
24  if (sps.frame_cropping_flag) {
25  int sub_width_c = 0;
26  int sub_height_c = 0;
27  // Table 6-1.
28  switch (sps.chroma_format_idc) {
29  case 0: // monochrome
30  // SubWidthC and SubHeightC are not defined for monochrome. For ease of
31  // computation afterwards, assign both to 1.
32  sub_width_c = 1;
33  sub_height_c = 1;
34  break;
35  case 1: // 4:2:0
36  sub_width_c = 2;
37  sub_height_c = 2;
38  break;
39  case 2: // 4:2:2
40  sub_width_c = 2;
41  sub_height_c = 1;
42  break;
43  case 3: // 4:4:4
44  sub_width_c = 1;
45  sub_height_c = 1;
46  break;
47  default:
48  LOG(ERROR) << "Unexpected chroma_format_idc " << sps.chroma_format_idc;
49  return false;
50  }
51 
52  // Formula 7-16, 7-17, 7-18, 7-19.
53  int crop_unit_x = sub_width_c;
54  int crop_unit_y = sub_height_c * (2 - (sps.frame_mbs_only_flag ? 1 : 0));
55  crop_x = crop_unit_x *
56  (sps.frame_crop_left_offset + sps.frame_crop_right_offset);
57  crop_y = crop_unit_y *
58  (sps.frame_crop_top_offset + sps.frame_crop_bottom_offset);
59  }
60 
61  // Formula 7-10, 7-11.
62  int pic_width_in_mbs = sps.pic_width_in_mbs_minus1 + 1;
63  *coded_width = pic_width_in_mbs * 16 - crop_x;
64 
65  // Formula 7-13, 7-15.
66  int pic_height_in_mbs = (2 - (sps.frame_mbs_only_flag ? 1 : 0)) *
67  (sps.pic_height_in_map_units_minus1 + 1);
68  *coded_height = pic_height_in_mbs * 16 - crop_y;
69 
70  // 0 means it wasn't in the SPS and therefore assume 1.
71  *pixel_width = sps.sar_width == 0 ? 1 : sps.sar_width;
72  *pixel_height = sps.sar_height == 0 ? 1 : sps.sar_height;
73  DVLOG(2) << "Found coded_width: " << *coded_width
74  << " coded_height: " << *coded_height
75  << " pixel_width: " << *pixel_width
76  << " pixel_height: " << *pixel_height;
77  return true;
78 }
79 
80 bool H264SliceHeader::IsPSlice() const {
81  return (slice_type % 5 == kPSlice);
82 }
83 
84 bool H264SliceHeader::IsBSlice() const {
85  return (slice_type % 5 == kBSlice);
86 }
87 
88 bool H264SliceHeader::IsISlice() const {
89  return (slice_type % 5 == kISlice);
90 }
91 
92 bool H264SliceHeader::IsSPSlice() const {
93  return (slice_type % 5 == kSPSlice);
94 }
95 
96 bool H264SliceHeader::IsSISlice() const {
97  return (slice_type % 5 == kSISlice);
98 }
99 
100 H264Sps::H264Sps() {
101  memset(this, 0, sizeof(*this));
102 }
103 
104 H264Pps::H264Pps() {
105  memset(this, 0, sizeof(*this));
106 }
107 
108 H264SliceHeader::H264SliceHeader() {
109  memset(this, 0, sizeof(*this));
110 }
111 
112 H264SEIMessage::H264SEIMessage() {
113  memset(this, 0, sizeof(*this));
114 }
115 
116 #define READ_BITS_OR_RETURN(num_bits, out) \
117  do { \
118  if (!br->ReadBits(num_bits, (out))) { \
119  DVLOG(1) \
120  << "Error in stream: unexpected EOS while trying to read " #out; \
121  return kInvalidStream; \
122  } \
123  } while (0)
124 
125 #define READ_BOOL_OR_RETURN(out) \
126  do { \
127  int _out; \
128  if (!br->ReadBits(1, &_out)) { \
129  DVLOG(1) \
130  << "Error in stream: unexpected EOS while trying to read " #out; \
131  return kInvalidStream; \
132  } \
133  *(out) = _out != 0; \
134  } while (0)
135 
136 #define READ_UE_OR_RETURN(out) \
137  do { \
138  if (!br->ReadUE(out)) { \
139  DVLOG(1) << "Error in stream: invalid value while trying to read " #out; \
140  return kInvalidStream; \
141  } \
142  } while (0)
143 
144 #define READ_SE_OR_RETURN(out) \
145  do { \
146  if (!br->ReadSE(out)) { \
147  DVLOG(1) << "Error in stream: invalid value while trying to read " #out; \
148  return kInvalidStream; \
149  } \
150  } while (0)
151 
152 #define IN_RANGE_OR_RETURN(val, min, max) \
153  do { \
154  if ((val) < (min) || (val) > (max)) { \
155  DVLOG(1) << "Error in stream: invalid value, expected " #val " to be" \
156  << " in range [" << (min) << ":" << (max) << "]" \
157  << " found " << (val) << " instead"; \
158  return kInvalidStream; \
159  } \
160  } while (0)
161 
162 #define TRUE_OR_RETURN(a) \
163  do { \
164  if (!(a)) { \
165  DVLOG(1) << "Error in stream: invalid value, expected " << #a; \
166  return kInvalidStream; \
167  } \
168  } while (0)
169 
170 enum AspectRatioIdc {
171  kExtendedSar = 255,
172 };
173 
174 // ISO 14496 part 10
175 // VUI parameters: Table E-1 "Meaning of sample aspect ratio indicator"
176 static const int kTableSarWidth[] = {
177  0, 1, 12, 10, 16, 40, 24, 20, 32, 80, 18, 15, 64, 160, 4, 3, 2
178 };
179 static const int kTableSarHeight[] = {
180  0, 1, 11, 11, 11, 33, 11, 11, 11, 33, 11, 11, 33, 99, 3, 2, 1
181 };
182 COMPILE_ASSERT(arraysize(kTableSarWidth) == arraysize(kTableSarHeight),
183  sar_tables_must_have_same_size);
184 
185 H264Parser::H264Parser() {}
186 
187 H264Parser::~H264Parser() {
188  STLDeleteValues(&active_SPSes_);
189  STLDeleteValues(&active_PPSes_);
190 }
191 
192 const H264Pps* H264Parser::GetPps(int pps_id) {
193  return active_PPSes_[pps_id];
194 }
195 
196 const H264Sps* H264Parser::GetSps(int sps_id) {
197  return active_SPSes_[sps_id];
198 }
199 
200 // Default scaling lists (per spec).
201 static const int kDefault4x4Intra[kH264ScalingList4x4Length] = {
202  6, 13, 13, 20, 20, 20, 28, 28, 28, 28, 32, 32, 32, 37, 37, 42, };
203 
204 static const int kDefault4x4Inter[kH264ScalingList4x4Length] = {
205  10, 14, 14, 20, 20, 20, 24, 24, 24, 24, 27, 27, 27, 30, 30, 34, };
206 
207 static const int kDefault8x8Intra[kH264ScalingList8x8Length] = {
208  6, 10, 10, 13, 11, 13, 16, 16, 16, 16, 18, 18, 18, 18, 18, 23,
209  23, 23, 23, 23, 23, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27,
210  27, 27, 27, 27, 29, 29, 29, 29, 29, 29, 29, 31, 31, 31, 31, 31,
211  31, 33, 33, 33, 33, 33, 36, 36, 36, 36, 38, 38, 38, 40, 40, 42, };
212 
213 static const int kDefault8x8Inter[kH264ScalingList8x8Length] = {
214  9, 13, 13, 15, 13, 15, 17, 17, 17, 17, 19, 19, 19, 19, 19, 21,
215  21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 24, 24, 24, 24,
216  24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27, 27,
217  27, 28, 28, 28, 28, 28, 30, 30, 30, 30, 32, 32, 32, 33, 33, 35, };
218 
219 static inline void DefaultScalingList4x4(
220  int i,
221  int scaling_list4x4[][kH264ScalingList4x4Length]) {
222  DCHECK_LT(i, 6);
223 
224  if (i < 3)
225  memcpy(scaling_list4x4[i], kDefault4x4Intra, sizeof(kDefault4x4Intra));
226  else if (i < 6)
227  memcpy(scaling_list4x4[i], kDefault4x4Inter, sizeof(kDefault4x4Inter));
228 }
229 
230 static inline void DefaultScalingList8x8(
231  int i,
232  int scaling_list8x8[][kH264ScalingList8x8Length]) {
233  DCHECK_LT(i, 6);
234 
235  if (i % 2 == 0)
236  memcpy(scaling_list8x8[i], kDefault8x8Intra, sizeof(kDefault8x8Intra));
237  else
238  memcpy(scaling_list8x8[i], kDefault8x8Inter, sizeof(kDefault8x8Inter));
239 }
240 
241 static void FallbackScalingList4x4(
242  int i,
243  const int default_scaling_list_intra[],
244  const int default_scaling_list_inter[],
245  int scaling_list4x4[][kH264ScalingList4x4Length]) {
246  static const int kScalingList4x4ByteSize =
247  sizeof(scaling_list4x4[0][0]) * kH264ScalingList4x4Length;
248 
249  switch (i) {
250  case 0:
251  memcpy(scaling_list4x4[i], default_scaling_list_intra,
252  kScalingList4x4ByteSize);
253  break;
254 
255  case 1:
256  memcpy(scaling_list4x4[i], scaling_list4x4[0], kScalingList4x4ByteSize);
257  break;
258 
259  case 2:
260  memcpy(scaling_list4x4[i], scaling_list4x4[1], kScalingList4x4ByteSize);
261  break;
262 
263  case 3:
264  memcpy(scaling_list4x4[i], default_scaling_list_inter,
265  kScalingList4x4ByteSize);
266  break;
267 
268  case 4:
269  memcpy(scaling_list4x4[i], scaling_list4x4[3], kScalingList4x4ByteSize);
270  break;
271 
272  case 5:
273  memcpy(scaling_list4x4[i], scaling_list4x4[4], kScalingList4x4ByteSize);
274  break;
275 
276  default:
277  NOTREACHED();
278  break;
279  }
280 }
281 
282 static void FallbackScalingList8x8(
283  int i,
284  const int default_scaling_list_intra[],
285  const int default_scaling_list_inter[],
286  int scaling_list8x8[][kH264ScalingList8x8Length]) {
287  static const int kScalingList8x8ByteSize =
288  sizeof(scaling_list8x8[0][0]) * kH264ScalingList8x8Length;
289 
290  switch (i) {
291  case 0:
292  memcpy(scaling_list8x8[i], default_scaling_list_intra,
293  kScalingList8x8ByteSize);
294  break;
295 
296  case 1:
297  memcpy(scaling_list8x8[i], default_scaling_list_inter,
298  kScalingList8x8ByteSize);
299  break;
300 
301  case 2:
302  memcpy(scaling_list8x8[i], scaling_list8x8[0], kScalingList8x8ByteSize);
303  break;
304 
305  case 3:
306  memcpy(scaling_list8x8[i], scaling_list8x8[1], kScalingList8x8ByteSize);
307  break;
308 
309  case 4:
310  memcpy(scaling_list8x8[i], scaling_list8x8[2], kScalingList8x8ByteSize);
311  break;
312 
313  case 5:
314  memcpy(scaling_list8x8[i], scaling_list8x8[3], kScalingList8x8ByteSize);
315  break;
316 
317  default:
318  NOTREACHED();
319  break;
320  }
321 }
322 
323 H264Parser::Result H264Parser::ParseScalingList(H26xBitReader* br,
324  int size,
325  int* scaling_list,
326  bool* use_default) {
327  // See chapter 7.3.2.1.1.1.
328  int last_scale = 8;
329  int next_scale = 8;
330  int delta_scale;
331 
332  *use_default = false;
333 
334  for (int j = 0; j < size; ++j) {
335  if (next_scale != 0) {
336  READ_SE_OR_RETURN(&delta_scale);
337  IN_RANGE_OR_RETURN(delta_scale, -128, 127);
338  next_scale = (last_scale + delta_scale + 256) & 0xff;
339 
340  if (j == 0 && next_scale == 0) {
341  *use_default = true;
342  return kOk;
343  }
344  }
345 
346  scaling_list[j] = (next_scale == 0) ? last_scale : next_scale;
347  last_scale = scaling_list[j];
348  }
349 
350  return kOk;
351 }
352 
353 H264Parser::Result H264Parser::ParseSpsScalingLists(H26xBitReader* br,
354  H264Sps* sps) {
355  // See 7.4.2.1.1.
356  bool seq_scaling_list_present_flag;
357  bool use_default;
358  Result res;
359 
360  // Parse scaling_list4x4.
361  for (int i = 0; i < 6; ++i) {
362  READ_BOOL_OR_RETURN(&seq_scaling_list_present_flag);
363 
364  if (seq_scaling_list_present_flag) {
365  res = ParseScalingList(br,
366  arraysize(sps->scaling_list4x4[i]),
367  sps->scaling_list4x4[i],
368  &use_default);
369  if (res != kOk)
370  return res;
371 
372  if (use_default)
373  DefaultScalingList4x4(i, sps->scaling_list4x4);
374 
375  } else {
376  FallbackScalingList4x4(
377  i, kDefault4x4Intra, kDefault4x4Inter, sps->scaling_list4x4);
378  }
379  }
380 
381  // Parse scaling_list8x8.
382  for (int i = 0; i < ((sps->chroma_format_idc != 3) ? 2 : 6); ++i) {
383  READ_BOOL_OR_RETURN(&seq_scaling_list_present_flag);
384 
385  if (seq_scaling_list_present_flag) {
386  res = ParseScalingList(br,
387  arraysize(sps->scaling_list8x8[i]),
388  sps->scaling_list8x8[i],
389  &use_default);
390  if (res != kOk)
391  return res;
392 
393  if (use_default)
394  DefaultScalingList8x8(i, sps->scaling_list8x8);
395 
396  } else {
397  FallbackScalingList8x8(
398  i, kDefault8x8Intra, kDefault8x8Inter, sps->scaling_list8x8);
399  }
400  }
401 
402  return kOk;
403 }
404 
405 H264Parser::Result H264Parser::ParsePpsScalingLists(H26xBitReader* br,
406  const H264Sps& sps,
407  H264Pps* pps) {
408  // See 7.4.2.2.
409  bool pic_scaling_list_present_flag;
410  bool use_default;
411  Result res;
412 
413  for (int i = 0; i < 6; ++i) {
414  READ_BOOL_OR_RETURN(&pic_scaling_list_present_flag);
415 
416  if (pic_scaling_list_present_flag) {
417  res = ParseScalingList(br,
418  arraysize(pps->scaling_list4x4[i]),
419  pps->scaling_list4x4[i],
420  &use_default);
421  if (res != kOk)
422  return res;
423 
424  if (use_default)
425  DefaultScalingList4x4(i, pps->scaling_list4x4);
426 
427  } else {
428  if (sps.seq_scaling_matrix_present_flag) {
429  // Table 7-2 fallback rule A in spec.
430  FallbackScalingList4x4(
431  i, kDefault4x4Intra, kDefault4x4Inter, pps->scaling_list4x4);
432  } else {
433  // Table 7-2 fallback rule B in spec.
434  FallbackScalingList4x4(i,
435  sps.scaling_list4x4[0],
436  sps.scaling_list4x4[3],
437  pps->scaling_list4x4);
438  }
439  }
440  }
441 
442  if (pps->transform_8x8_mode_flag) {
443  for (int i = 0; i < ((sps.chroma_format_idc != 3) ? 2 : 6); ++i) {
444  READ_BOOL_OR_RETURN(&pic_scaling_list_present_flag);
445 
446  if (pic_scaling_list_present_flag) {
447  res = ParseScalingList(br,
448  arraysize(pps->scaling_list8x8[i]),
449  pps->scaling_list8x8[i],
450  &use_default);
451  if (res != kOk)
452  return res;
453 
454  if (use_default)
455  DefaultScalingList8x8(i, pps->scaling_list8x8);
456 
457  } else {
458  if (sps.seq_scaling_matrix_present_flag) {
459  // Table 7-2 fallback rule A in spec.
460  FallbackScalingList8x8(
461  i, kDefault8x8Intra, kDefault8x8Inter, pps->scaling_list8x8);
462  } else {
463  // Table 7-2 fallback rule B in spec.
464  FallbackScalingList8x8(i,
465  sps.scaling_list8x8[0],
466  sps.scaling_list8x8[1],
467  pps->scaling_list8x8);
468  }
469  }
470  }
471  }
472  return kOk;
473 }
474 
475 H264Parser::Result H264Parser::ParseAndIgnoreHRDParameters(
476  H26xBitReader* br, bool* hrd_parameters_present) {
477  int data;
478  READ_BOOL_OR_RETURN(&data); // {nal,vcl}_hrd_parameters_present_flag
479  if (!data)
480  return kOk;
481 
482  *hrd_parameters_present = true;
483 
484  int cpb_cnt_minus1;
485  READ_UE_OR_RETURN(&cpb_cnt_minus1);
486  IN_RANGE_OR_RETURN(cpb_cnt_minus1, 0, 31);
487  READ_BITS_OR_RETURN(8, &data); // bit_rate_scale, cpb_size_scale
488  for (int i = 0; i <= cpb_cnt_minus1; ++i) {
489  READ_UE_OR_RETURN(&data); // bit_rate_value_minus1[i]
490  READ_UE_OR_RETURN(&data); // cpb_size_value_minus1[i]
491  READ_BOOL_OR_RETURN(&data); // cbr_flag
492  }
493  READ_BITS_OR_RETURN(20, &data); // cpb/dpb delays, etc.
494 
495  return kOk;
496 }
497 
498 H264Parser::Result H264Parser::ParseVUIParameters(H26xBitReader* br,
499  H264Sps* sps) {
500  bool aspect_ratio_info_present_flag;
501  READ_BOOL_OR_RETURN(&aspect_ratio_info_present_flag);
502  if (aspect_ratio_info_present_flag) {
503  int aspect_ratio_idc;
504  READ_BITS_OR_RETURN(8, &aspect_ratio_idc);
505  if (aspect_ratio_idc == kExtendedSar) {
506  READ_BITS_OR_RETURN(16, &sps->sar_width);
507  READ_BITS_OR_RETURN(16, &sps->sar_height);
508  } else {
509  const int max_aspect_ratio_idc = arraysize(kTableSarWidth) - 1;
510  IN_RANGE_OR_RETURN(aspect_ratio_idc, 0, max_aspect_ratio_idc);
511  sps->sar_width = kTableSarWidth[aspect_ratio_idc];
512  sps->sar_height = kTableSarHeight[aspect_ratio_idc];
513  }
514  }
515 
516  int data;
517  // Read and ignore overscan and video signal type info.
518  READ_BOOL_OR_RETURN(&data); // overscan_info_present_flag
519  if (data)
520  READ_BOOL_OR_RETURN(&data); // overscan_appropriate_flag
521 
522  READ_BOOL_OR_RETURN(&data); // video_signal_type_present_flag
523  if (data) {
524  READ_BITS_OR_RETURN(3, &data); // video_format
525  READ_BOOL_OR_RETURN(&data); // video_full_range_flag
526  READ_BOOL_OR_RETURN(&data); // colour_description_present_flag
527  if (data)
528  READ_BITS_OR_RETURN(24, &data); // color description syntax elements
529  }
530 
531  READ_BOOL_OR_RETURN(&data); // chroma_loc_info_present_flag
532  if (data) {
533  READ_UE_OR_RETURN(&data); // chroma_sample_loc_type_top_field
534  READ_UE_OR_RETURN(&data); // chroma_sample_loc_type_bottom_field
535  }
536 
537  // Read and ignore timing info.
538  READ_BOOL_OR_RETURN(&data); // timing_info_present_flag
539  if (data) {
540  READ_BITS_OR_RETURN(16, &data); // num_units_in_tick
541  READ_BITS_OR_RETURN(16, &data); // num_units_in_tick
542  READ_BITS_OR_RETURN(16, &data); // time_scale
543  READ_BITS_OR_RETURN(16, &data); // time_scale
544  READ_BOOL_OR_RETURN(&data); // fixed_frame_rate_flag
545  }
546 
547  // Read and ignore NAL HRD parameters, if present.
548  bool hrd_parameters_present = false;
549  Result res = ParseAndIgnoreHRDParameters(br, &hrd_parameters_present);
550  if (res != kOk)
551  return res;
552 
553  // Read and ignore VCL HRD parameters, if present.
554  res = ParseAndIgnoreHRDParameters(br, &hrd_parameters_present);
555  if (res != kOk)
556  return res;
557 
558  if (hrd_parameters_present) // One of NAL or VCL params present is enough.
559  READ_BOOL_OR_RETURN(&data); // low_delay_hrd_flag
560 
561  READ_BOOL_OR_RETURN(&data); // pic_struct_present_flag
562  READ_BOOL_OR_RETURN(&sps->bitstream_restriction_flag);
563  if (sps->bitstream_restriction_flag) {
564  READ_BOOL_OR_RETURN(&data); // motion_vectors_over_pic_boundaries_flag
565  READ_UE_OR_RETURN(&data); // max_bytes_per_pic_denom
566  READ_UE_OR_RETURN(&data); // max_bits_per_mb_denom
567  READ_UE_OR_RETURN(&data); // log2_max_mv_length_horizontal
568  READ_UE_OR_RETURN(&data); // log2_max_mv_length_vertical
569  READ_UE_OR_RETURN(&sps->max_num_reorder_frames);
570  READ_UE_OR_RETURN(&sps->max_dec_frame_buffering);
571  TRUE_OR_RETURN(sps->max_dec_frame_buffering >= sps->max_num_ref_frames);
572  IN_RANGE_OR_RETURN(
573  sps->max_num_reorder_frames, 0, sps->max_dec_frame_buffering);
574  }
575 
576  return kOk;
577 }
578 
579 static void FillDefaultSeqScalingLists(H264Sps* sps) {
580  for (int i = 0; i < 6; ++i)
581  for (int j = 0; j < kH264ScalingList4x4Length; ++j)
582  sps->scaling_list4x4[i][j] = 16;
583 
584  for (int i = 0; i < 6; ++i)
585  for (int j = 0; j < kH264ScalingList8x8Length; ++j)
586  sps->scaling_list8x8[i][j] = 16;
587 }
588 
589 H264Parser::Result H264Parser::ParseSps(const Nalu& nalu, int* sps_id) {
590  // See 7.4.2.1.
591  int data;
592  Result res;
593  H26xBitReader reader;
594  reader.Initialize(nalu.data() + nalu.header_size(), nalu.payload_size());
595  H26xBitReader* br = &reader;
596 
597  *sps_id = -1;
598 
599  scoped_ptr<H264Sps> sps(new H264Sps());
600 
601  READ_BITS_OR_RETURN(8, &sps->profile_idc);
602  READ_BOOL_OR_RETURN(&sps->constraint_set0_flag);
603  READ_BOOL_OR_RETURN(&sps->constraint_set1_flag);
604  READ_BOOL_OR_RETURN(&sps->constraint_set2_flag);
605  READ_BOOL_OR_RETURN(&sps->constraint_set3_flag);
606  READ_BOOL_OR_RETURN(&sps->constraint_set4_flag);
607  READ_BOOL_OR_RETURN(&sps->constraint_set5_flag);
608  READ_BITS_OR_RETURN(2, &data); // reserved_zero_2bits
609  READ_BITS_OR_RETURN(8, &sps->level_idc);
610  READ_UE_OR_RETURN(&sps->seq_parameter_set_id);
611  TRUE_OR_RETURN(sps->seq_parameter_set_id < 32);
612 
613  if (sps->profile_idc == 100 || sps->profile_idc == 110 ||
614  sps->profile_idc == 122 || sps->profile_idc == 244 ||
615  sps->profile_idc == 44 || sps->profile_idc == 83 ||
616  sps->profile_idc == 86 || sps->profile_idc == 118 ||
617  sps->profile_idc == 128) {
618  READ_UE_OR_RETURN(&sps->chroma_format_idc);
619  TRUE_OR_RETURN(sps->chroma_format_idc < 4);
620 
621  if (sps->chroma_format_idc == 3)
622  READ_BOOL_OR_RETURN(&sps->separate_colour_plane_flag);
623 
624  READ_UE_OR_RETURN(&sps->bit_depth_luma_minus8);
625  TRUE_OR_RETURN(sps->bit_depth_luma_minus8 < 7);
626 
627  READ_UE_OR_RETURN(&sps->bit_depth_chroma_minus8);
628  TRUE_OR_RETURN(sps->bit_depth_chroma_minus8 < 7);
629 
630  READ_BOOL_OR_RETURN(&sps->qpprime_y_zero_transform_bypass_flag);
631  READ_BOOL_OR_RETURN(&sps->seq_scaling_matrix_present_flag);
632 
633  if (sps->seq_scaling_matrix_present_flag) {
634  DVLOG(4) << "Scaling matrix present";
635  res = ParseSpsScalingLists(br, sps.get());
636  if (res != kOk)
637  return res;
638  } else {
639  FillDefaultSeqScalingLists(sps.get());
640  }
641  } else {
642  sps->chroma_format_idc = 1;
643  FillDefaultSeqScalingLists(sps.get());
644  }
645 
646  if (sps->separate_colour_plane_flag)
647  sps->chroma_array_type = 0;
648  else
649  sps->chroma_array_type = sps->chroma_format_idc;
650 
651  READ_UE_OR_RETURN(&sps->log2_max_frame_num_minus4);
652  TRUE_OR_RETURN(sps->log2_max_frame_num_minus4 < 13);
653 
654  READ_UE_OR_RETURN(&sps->pic_order_cnt_type);
655  TRUE_OR_RETURN(sps->pic_order_cnt_type < 3);
656 
657  sps->expected_delta_per_pic_order_cnt_cycle = 0;
658  if (sps->pic_order_cnt_type == 0) {
659  READ_UE_OR_RETURN(&sps->log2_max_pic_order_cnt_lsb_minus4);
660  TRUE_OR_RETURN(sps->log2_max_pic_order_cnt_lsb_minus4 < 13);
661  } else if (sps->pic_order_cnt_type == 1) {
662  READ_BOOL_OR_RETURN(&sps->delta_pic_order_always_zero_flag);
663  READ_SE_OR_RETURN(&sps->offset_for_non_ref_pic);
664  READ_SE_OR_RETURN(&sps->offset_for_top_to_bottom_field);
665  READ_UE_OR_RETURN(&sps->num_ref_frames_in_pic_order_cnt_cycle);
666  TRUE_OR_RETURN(sps->num_ref_frames_in_pic_order_cnt_cycle < 255);
667 
668  for (int i = 0; i < sps->num_ref_frames_in_pic_order_cnt_cycle; ++i) {
669  READ_SE_OR_RETURN(&sps->offset_for_ref_frame[i]);
670  sps->expected_delta_per_pic_order_cnt_cycle +=
671  sps->offset_for_ref_frame[i];
672  }
673  }
674 
675  READ_UE_OR_RETURN(&sps->max_num_ref_frames);
676  READ_BOOL_OR_RETURN(&sps->gaps_in_frame_num_value_allowed_flag);
677 
678  if (sps->gaps_in_frame_num_value_allowed_flag)
679  return kUnsupportedStream;
680 
681  READ_UE_OR_RETURN(&sps->pic_width_in_mbs_minus1);
682  READ_UE_OR_RETURN(&sps->pic_height_in_map_units_minus1);
683 
684  READ_BOOL_OR_RETURN(&sps->frame_mbs_only_flag);
685  if (!sps->frame_mbs_only_flag)
686  READ_BOOL_OR_RETURN(&sps->mb_adaptive_frame_field_flag);
687 
688  READ_BOOL_OR_RETURN(&sps->direct_8x8_inference_flag);
689 
690  READ_BOOL_OR_RETURN(&sps->frame_cropping_flag);
691  if (sps->frame_cropping_flag) {
692  READ_UE_OR_RETURN(&sps->frame_crop_left_offset);
693  READ_UE_OR_RETURN(&sps->frame_crop_right_offset);
694  READ_UE_OR_RETURN(&sps->frame_crop_top_offset);
695  READ_UE_OR_RETURN(&sps->frame_crop_bottom_offset);
696  }
697 
698  READ_BOOL_OR_RETURN(&sps->vui_parameters_present_flag);
699  if (sps->vui_parameters_present_flag) {
700  DVLOG(4) << "VUI parameters present";
701  res = ParseVUIParameters(br, sps.get());
702  if (res != kOk)
703  return res;
704  }
705 
706  // If an SPS with the same id already exists, replace it.
707  *sps_id = sps->seq_parameter_set_id;
708  delete active_SPSes_[*sps_id];
709  active_SPSes_[*sps_id] = sps.release();
710 
711  return kOk;
712 }
713 
714 H264Parser::Result H264Parser::ParsePps(const Nalu& nalu, int* pps_id) {
715  // See 7.4.2.2.
716  const H264Sps* sps;
717  Result res;
718  H26xBitReader reader;
719  reader.Initialize(nalu.data() + nalu.header_size(), nalu.payload_size());
720  H26xBitReader* br = &reader;
721 
722  *pps_id = -1;
723 
724  scoped_ptr<H264Pps> pps(new H264Pps());
725 
726  READ_UE_OR_RETURN(&pps->pic_parameter_set_id);
727  READ_UE_OR_RETURN(&pps->seq_parameter_set_id);
728  TRUE_OR_RETURN(pps->seq_parameter_set_id < 32);
729 
730  sps = GetSps(pps->seq_parameter_set_id);
731  TRUE_OR_RETURN(sps);
732 
733  READ_BOOL_OR_RETURN(&pps->entropy_coding_mode_flag);
734  READ_BOOL_OR_RETURN(&pps->bottom_field_pic_order_in_frame_present_flag);
735 
736  READ_UE_OR_RETURN(&pps->num_slice_groups_minus1);
737  if (pps->num_slice_groups_minus1 > 1) {
738  DVLOG(1) << "Slice groups not supported";
739  return kUnsupportedStream;
740  }
741 
742  READ_UE_OR_RETURN(&pps->num_ref_idx_l0_default_active_minus1);
743  TRUE_OR_RETURN(pps->num_ref_idx_l0_default_active_minus1 < 32);
744 
745  READ_UE_OR_RETURN(&pps->num_ref_idx_l1_default_active_minus1);
746  TRUE_OR_RETURN(pps->num_ref_idx_l1_default_active_minus1 < 32);
747 
748  READ_BOOL_OR_RETURN(&pps->weighted_pred_flag);
749  READ_BITS_OR_RETURN(2, &pps->weighted_bipred_idc);
750  TRUE_OR_RETURN(pps->weighted_bipred_idc < 3);
751 
752  READ_SE_OR_RETURN(&pps->pic_init_qp_minus26);
753  IN_RANGE_OR_RETURN(pps->pic_init_qp_minus26, -26, 25);
754 
755  READ_SE_OR_RETURN(&pps->pic_init_qs_minus26);
756  IN_RANGE_OR_RETURN(pps->pic_init_qs_minus26, -26, 25);
757 
758  READ_SE_OR_RETURN(&pps->chroma_qp_index_offset);
759  IN_RANGE_OR_RETURN(pps->chroma_qp_index_offset, -12, 12);
760  pps->second_chroma_qp_index_offset = pps->chroma_qp_index_offset;
761 
762  READ_BOOL_OR_RETURN(&pps->deblocking_filter_control_present_flag);
763  READ_BOOL_OR_RETURN(&pps->constrained_intra_pred_flag);
764  READ_BOOL_OR_RETURN(&pps->redundant_pic_cnt_present_flag);
765 
766  if (br->HasMoreRBSPData()) {
767  READ_BOOL_OR_RETURN(&pps->transform_8x8_mode_flag);
768  READ_BOOL_OR_RETURN(&pps->pic_scaling_matrix_present_flag);
769 
770  if (pps->pic_scaling_matrix_present_flag) {
771  DVLOG(4) << "Picture scaling matrix present";
772  res = ParsePpsScalingLists(br, *sps, pps.get());
773  if (res != kOk)
774  return res;
775  }
776 
777  READ_SE_OR_RETURN(&pps->second_chroma_qp_index_offset);
778  }
779 
780  // If a PPS with the same id already exists, replace it.
781  *pps_id = pps->pic_parameter_set_id;
782  delete active_PPSes_[*pps_id];
783  active_PPSes_[*pps_id] = pps.release();
784 
785  return kOk;
786 }
787 
788 H264Parser::Result H264Parser::ParseRefPicListModification(
789  H26xBitReader* br,
790  int num_ref_idx_active_minus1,
791  H264ModificationOfPicNum* ref_list_mods) {
792  H264ModificationOfPicNum* pic_num_mod;
793 
794  if (num_ref_idx_active_minus1 >= 32)
795  return kInvalidStream;
796 
797  for (int i = 0; i < 32; ++i) {
798  pic_num_mod = &ref_list_mods[i];
799  READ_UE_OR_RETURN(&pic_num_mod->modification_of_pic_nums_idc);
800  TRUE_OR_RETURN(pic_num_mod->modification_of_pic_nums_idc < 4);
801 
802  switch (pic_num_mod->modification_of_pic_nums_idc) {
803  case 0:
804  case 1:
805  READ_UE_OR_RETURN(&pic_num_mod->abs_diff_pic_num_minus1);
806  break;
807 
808  case 2:
809  READ_UE_OR_RETURN(&pic_num_mod->long_term_pic_num);
810  break;
811 
812  case 3:
813  // Per spec, list cannot be empty.
814  if (i == 0)
815  return kInvalidStream;
816  return kOk;
817 
818  default:
819  return kInvalidStream;
820  }
821  }
822 
823  // If we got here, we didn't get loop end marker prematurely,
824  // so make sure it is there for our client.
825  int modification_of_pic_nums_idc;
826  READ_UE_OR_RETURN(&modification_of_pic_nums_idc);
827  TRUE_OR_RETURN(modification_of_pic_nums_idc == 3);
828 
829  return kOk;
830 }
831 
832 H264Parser::Result H264Parser::ParseRefPicListModifications(
833  H26xBitReader* br, H264SliceHeader* shdr) {
834  Result res;
835 
836  if (!shdr->IsISlice() && !shdr->IsSISlice()) {
837  READ_BOOL_OR_RETURN(&shdr->ref_pic_list_modification_flag_l0);
838  if (shdr->ref_pic_list_modification_flag_l0) {
839  res = ParseRefPicListModification(br, shdr->num_ref_idx_l0_active_minus1,
840  shdr->ref_list_l0_modifications);
841  if (res != kOk)
842  return res;
843  }
844  }
845 
846  if (shdr->IsBSlice()) {
847  READ_BOOL_OR_RETURN(&shdr->ref_pic_list_modification_flag_l1);
848  if (shdr->ref_pic_list_modification_flag_l1) {
849  res = ParseRefPicListModification(br, shdr->num_ref_idx_l1_active_minus1,
850  shdr->ref_list_l1_modifications);
851  if (res != kOk)
852  return res;
853  }
854  }
855 
856  return kOk;
857 }
858 
859 H264Parser::Result H264Parser::ParseWeightingFactors(
860  H26xBitReader* br,
861  int num_ref_idx_active_minus1,
862  int chroma_array_type,
863  int luma_log2_weight_denom,
864  int chroma_log2_weight_denom,
865  H264WeightingFactors* w_facts) {
866  int def_luma_weight = 1 << luma_log2_weight_denom;
867  int def_chroma_weight = 1 << chroma_log2_weight_denom;
868 
869  for (int i = 0; i < num_ref_idx_active_minus1 + 1; ++i) {
870  READ_BOOL_OR_RETURN(&w_facts->luma_weight_flag);
871  if (w_facts->luma_weight_flag) {
872  READ_SE_OR_RETURN(&w_facts->luma_weight[i]);
873  IN_RANGE_OR_RETURN(w_facts->luma_weight[i], -128, 127);
874 
875  READ_SE_OR_RETURN(&w_facts->luma_offset[i]);
876  IN_RANGE_OR_RETURN(w_facts->luma_offset[i], -128, 127);
877  } else {
878  w_facts->luma_weight[i] = def_luma_weight;
879  w_facts->luma_offset[i] = 0;
880  }
881 
882  if (chroma_array_type != 0) {
883  READ_BOOL_OR_RETURN(&w_facts->chroma_weight_flag);
884  if (w_facts->chroma_weight_flag) {
885  for (int j = 0; j < 2; ++j) {
886  READ_SE_OR_RETURN(&w_facts->chroma_weight[i][j]);
887  IN_RANGE_OR_RETURN(w_facts->chroma_weight[i][j], -128, 127);
888 
889  READ_SE_OR_RETURN(&w_facts->chroma_offset[i][j]);
890  IN_RANGE_OR_RETURN(w_facts->chroma_offset[i][j], -128, 127);
891  }
892  } else {
893  for (int j = 0; j < 2; ++j) {
894  w_facts->chroma_weight[i][j] = def_chroma_weight;
895  w_facts->chroma_offset[i][j] = 0;
896  }
897  }
898  }
899  }
900 
901  return kOk;
902 }
903 
904 H264Parser::Result H264Parser::ParsePredWeightTable(H26xBitReader* br,
905  const H264Sps& sps,
906  H264SliceHeader* shdr) {
907  READ_UE_OR_RETURN(&shdr->luma_log2_weight_denom);
908  TRUE_OR_RETURN(shdr->luma_log2_weight_denom < 8);
909 
910  if (sps.chroma_array_type != 0)
911  READ_UE_OR_RETURN(&shdr->chroma_log2_weight_denom);
912  TRUE_OR_RETURN(shdr->chroma_log2_weight_denom < 8);
913 
914  Result res = ParseWeightingFactors(br,
915  shdr->num_ref_idx_l0_active_minus1,
916  sps.chroma_array_type,
917  shdr->luma_log2_weight_denom,
918  shdr->chroma_log2_weight_denom,
919  &shdr->pred_weight_table_l0);
920  if (res != kOk)
921  return res;
922 
923  if (shdr->IsBSlice()) {
924  res = ParseWeightingFactors(br,
925  shdr->num_ref_idx_l1_active_minus1,
926  sps.chroma_array_type,
927  shdr->luma_log2_weight_denom,
928  shdr->chroma_log2_weight_denom,
929  &shdr->pred_weight_table_l1);
930  if (res != kOk)
931  return res;
932  }
933 
934  return kOk;
935 }
936 
937 H264Parser::Result H264Parser::ParseDecRefPicMarking(H26xBitReader* br,
938  H264SliceHeader* shdr) {
939  if (shdr->idr_pic_flag) {
940  READ_BOOL_OR_RETURN(&shdr->no_output_of_prior_pics_flag);
941  READ_BOOL_OR_RETURN(&shdr->long_term_reference_flag);
942  } else {
943  READ_BOOL_OR_RETURN(&shdr->adaptive_ref_pic_marking_mode_flag);
944 
945  H264DecRefPicMarking* marking;
946  if (shdr->adaptive_ref_pic_marking_mode_flag) {
947  size_t i;
948  for (i = 0; i < arraysize(shdr->ref_pic_marking); ++i) {
949  marking = &shdr->ref_pic_marking[i];
950 
951  READ_UE_OR_RETURN(&marking->memory_mgmnt_control_operation);
952  if (marking->memory_mgmnt_control_operation == 0)
953  break;
954 
955  if (marking->memory_mgmnt_control_operation == 1 ||
956  marking->memory_mgmnt_control_operation == 3)
957  READ_UE_OR_RETURN(&marking->difference_of_pic_nums_minus1);
958 
959  if (marking->memory_mgmnt_control_operation == 2)
960  READ_UE_OR_RETURN(&marking->long_term_pic_num);
961 
962  if (marking->memory_mgmnt_control_operation == 3 ||
963  marking->memory_mgmnt_control_operation == 6)
964  READ_UE_OR_RETURN(&marking->long_term_frame_idx);
965 
966  if (marking->memory_mgmnt_control_operation == 4)
967  READ_UE_OR_RETURN(&marking->max_long_term_frame_idx_plus1);
968 
969  if (marking->memory_mgmnt_control_operation > 6)
970  return kInvalidStream;
971  }
972 
973  if (i == arraysize(shdr->ref_pic_marking)) {
974  DVLOG(1) << "Ran out of dec ref pic marking fields";
975  return kUnsupportedStream;
976  }
977  }
978  }
979 
980  return kOk;
981 }
982 
983 H264Parser::Result H264Parser::ParseSliceHeader(const Nalu& nalu,
984  H264SliceHeader* shdr) {
985  // See 7.4.3.
986  const H264Sps* sps;
987  const H264Pps* pps;
988  Result res;
989  H26xBitReader reader;
990  reader.Initialize(nalu.data() + nalu.header_size(), nalu.payload_size());
991  H26xBitReader* br = &reader;
992 
993  memset(shdr, 0, sizeof(*shdr));
994 
995  shdr->idr_pic_flag = (nalu.type() == 5);
996  shdr->nal_ref_idc = nalu.ref_idc();
997  shdr->nalu_data = nalu.data() + nalu.header_size();
998  shdr->nalu_size = nalu.payload_size();
999 
1000  READ_UE_OR_RETURN(&shdr->first_mb_in_slice);
1001  READ_UE_OR_RETURN(&shdr->slice_type);
1002  TRUE_OR_RETURN(shdr->slice_type < 10);
1003 
1004  READ_UE_OR_RETURN(&shdr->pic_parameter_set_id);
1005 
1006  pps = GetPps(shdr->pic_parameter_set_id);
1007  TRUE_OR_RETURN(pps);
1008 
1009  sps = GetSps(pps->seq_parameter_set_id);
1010  TRUE_OR_RETURN(sps);
1011 
1012  if (sps->separate_colour_plane_flag) {
1013  DVLOG(1) << "Interlaced streams not supported";
1014  return kUnsupportedStream;
1015  }
1016 
1017  READ_BITS_OR_RETURN(sps->log2_max_frame_num_minus4 + 4, &shdr->frame_num);
1018  if (!sps->frame_mbs_only_flag) {
1019  READ_BOOL_OR_RETURN(&shdr->field_pic_flag);
1020  if (shdr->field_pic_flag) {
1021  DVLOG(1) << "Interlaced streams not supported";
1022  return kUnsupportedStream;
1023  }
1024  }
1025 
1026  if (shdr->idr_pic_flag)
1027  READ_UE_OR_RETURN(&shdr->idr_pic_id);
1028 
1029  if (sps->pic_order_cnt_type == 0) {
1030  READ_BITS_OR_RETURN(sps->log2_max_pic_order_cnt_lsb_minus4 + 4,
1031  &shdr->pic_order_cnt_lsb);
1032  if (pps->bottom_field_pic_order_in_frame_present_flag &&
1033  !shdr->field_pic_flag)
1034  READ_SE_OR_RETURN(&shdr->delta_pic_order_cnt_bottom);
1035  }
1036 
1037  if (sps->pic_order_cnt_type == 1 && !sps->delta_pic_order_always_zero_flag) {
1038  READ_SE_OR_RETURN(&shdr->delta_pic_order_cnt[0]);
1039  if (pps->bottom_field_pic_order_in_frame_present_flag &&
1040  !shdr->field_pic_flag)
1041  READ_SE_OR_RETURN(&shdr->delta_pic_order_cnt[1]);
1042  }
1043 
1044  if (pps->redundant_pic_cnt_present_flag) {
1045  READ_UE_OR_RETURN(&shdr->redundant_pic_cnt);
1046  TRUE_OR_RETURN(shdr->redundant_pic_cnt < 128);
1047  }
1048 
1049  if (shdr->IsBSlice())
1050  READ_BOOL_OR_RETURN(&shdr->direct_spatial_mv_pred_flag);
1051 
1052  if (shdr->IsPSlice() || shdr->IsSPSlice() || shdr->IsBSlice()) {
1053  READ_BOOL_OR_RETURN(&shdr->num_ref_idx_active_override_flag);
1054  if (shdr->num_ref_idx_active_override_flag) {
1055  READ_UE_OR_RETURN(&shdr->num_ref_idx_l0_active_minus1);
1056  if (shdr->IsBSlice())
1057  READ_UE_OR_RETURN(&shdr->num_ref_idx_l1_active_minus1);
1058  } else {
1059  shdr->num_ref_idx_l0_active_minus1 =
1060  pps->num_ref_idx_l0_default_active_minus1;
1061  if (shdr->IsBSlice()) {
1062  shdr->num_ref_idx_l1_active_minus1 =
1063  pps->num_ref_idx_l1_default_active_minus1;
1064  }
1065  }
1066  }
1067  if (shdr->field_pic_flag) {
1068  TRUE_OR_RETURN(shdr->num_ref_idx_l0_active_minus1 < 32);
1069  TRUE_OR_RETURN(shdr->num_ref_idx_l1_active_minus1 < 32);
1070  } else {
1071  TRUE_OR_RETURN(shdr->num_ref_idx_l0_active_minus1 < 16);
1072  TRUE_OR_RETURN(shdr->num_ref_idx_l1_active_minus1 < 16);
1073  }
1074 
1075  if (nalu.type() == Nalu::H264_CodedSliceExtension) {
1076  return kUnsupportedStream;
1077  } else {
1078  res = ParseRefPicListModifications(br, shdr);
1079  if (res != kOk)
1080  return res;
1081  }
1082 
1083  if ((pps->weighted_pred_flag && (shdr->IsPSlice() || shdr->IsSPSlice())) ||
1084  (pps->weighted_bipred_idc == 1 && shdr->IsBSlice())) {
1085  res = ParsePredWeightTable(br, *sps, shdr);
1086  if (res != kOk)
1087  return res;
1088  }
1089 
1090  if (nalu.ref_idc() != 0) {
1091  res = ParseDecRefPicMarking(br, shdr);
1092  if (res != kOk)
1093  return res;
1094  }
1095 
1096  if (pps->entropy_coding_mode_flag && !shdr->IsISlice() &&
1097  !shdr->IsSISlice()) {
1098  READ_UE_OR_RETURN(&shdr->cabac_init_idc);
1099  TRUE_OR_RETURN(shdr->cabac_init_idc < 3);
1100  }
1101 
1102  READ_SE_OR_RETURN(&shdr->slice_qp_delta);
1103 
1104  if (shdr->IsSPSlice() || shdr->IsSISlice()) {
1105  if (shdr->IsSPSlice())
1106  READ_BOOL_OR_RETURN(&shdr->sp_for_switch_flag);
1107  READ_SE_OR_RETURN(&shdr->slice_qs_delta);
1108  }
1109 
1110  if (pps->deblocking_filter_control_present_flag) {
1111  READ_UE_OR_RETURN(&shdr->disable_deblocking_filter_idc);
1112  TRUE_OR_RETURN(shdr->disable_deblocking_filter_idc < 3);
1113 
1114  if (shdr->disable_deblocking_filter_idc != 1) {
1115  READ_SE_OR_RETURN(&shdr->slice_alpha_c0_offset_div2);
1116  IN_RANGE_OR_RETURN(shdr->slice_alpha_c0_offset_div2, -6, 6);
1117 
1118  READ_SE_OR_RETURN(&shdr->slice_beta_offset_div2);
1119  IN_RANGE_OR_RETURN(shdr->slice_beta_offset_div2, -6, 6);
1120  }
1121  }
1122 
1123  if (pps->num_slice_groups_minus1 > 0) {
1124  DVLOG(1) << "Slice groups not supported";
1125  return kUnsupportedStream;
1126  }
1127 
1128  size_t epb = br->NumEmulationPreventionBytesRead();
1129  shdr->header_bit_size = (shdr->nalu_size - epb) * 8 - br->NumBitsLeft();
1130 
1131  return kOk;
1132 }
1133 
1134 H264Parser::Result H264Parser::ParseSEI(const Nalu& nalu,
1135  H264SEIMessage* sei_msg) {
1136  int byte;
1137  H26xBitReader reader;
1138  reader.Initialize(nalu.data() + nalu.header_size(), nalu.payload_size());
1139  H26xBitReader* br = &reader;
1140 
1141  memset(sei_msg, 0, sizeof(*sei_msg));
1142 
1143  READ_BITS_OR_RETURN(8, &byte);
1144  while (byte == 0xff) {
1145  sei_msg->type += 255;
1146  READ_BITS_OR_RETURN(8, &byte);
1147  }
1148  sei_msg->type += byte;
1149 
1150  READ_BITS_OR_RETURN(8, &byte);
1151  while (byte == 0xff) {
1152  sei_msg->payload_size += 255;
1153  READ_BITS_OR_RETURN(8, &byte);
1154  }
1155  sei_msg->payload_size += byte;
1156 
1157  DVLOG(4) << "Found SEI message type: " << sei_msg->type
1158  << " payload size: " << sei_msg->payload_size;
1159 
1160  switch (sei_msg->type) {
1161  case H264SEIMessage::kSEIRecoveryPoint:
1162  READ_UE_OR_RETURN(&sei_msg->recovery_point.recovery_frame_cnt);
1163  READ_BOOL_OR_RETURN(&sei_msg->recovery_point.exact_match_flag);
1164  READ_BOOL_OR_RETURN(&sei_msg->recovery_point.broken_link_flag);
1165  READ_BITS_OR_RETURN(2, &sei_msg->recovery_point.changing_slice_group_idc);
1166  break;
1167 
1168  default:
1169  DVLOG(4) << "Unsupported SEI message";
1170  break;
1171  }
1172 
1173  return kOk;
1174 }
1175 
1176 } // namespace media
1177 } // namespace shaka