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 <memory>
8 #include "packager/base/logging.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 static_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  std::unique_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  READ_UE_OR_RETURN(&sps->pic_width_in_mbs_minus1);
679  READ_UE_OR_RETURN(&sps->pic_height_in_map_units_minus1);
680 
681  READ_BOOL_OR_RETURN(&sps->frame_mbs_only_flag);
682  if (!sps->frame_mbs_only_flag)
683  READ_BOOL_OR_RETURN(&sps->mb_adaptive_frame_field_flag);
684 
685  READ_BOOL_OR_RETURN(&sps->direct_8x8_inference_flag);
686 
687  READ_BOOL_OR_RETURN(&sps->frame_cropping_flag);
688  if (sps->frame_cropping_flag) {
689  READ_UE_OR_RETURN(&sps->frame_crop_left_offset);
690  READ_UE_OR_RETURN(&sps->frame_crop_right_offset);
691  READ_UE_OR_RETURN(&sps->frame_crop_top_offset);
692  READ_UE_OR_RETURN(&sps->frame_crop_bottom_offset);
693  }
694 
695  READ_BOOL_OR_RETURN(&sps->vui_parameters_present_flag);
696  if (sps->vui_parameters_present_flag) {
697  DVLOG(4) << "VUI parameters present";
698  res = ParseVUIParameters(br, sps.get());
699  if (res != kOk)
700  return res;
701  }
702 
703  // If an SPS with the same id already exists, replace it.
704  *sps_id = sps->seq_parameter_set_id;
705  delete active_SPSes_[*sps_id];
706  active_SPSes_[*sps_id] = sps.release();
707 
708  return kOk;
709 }
710 
711 H264Parser::Result H264Parser::ParsePps(const Nalu& nalu, int* pps_id) {
712  // See 7.4.2.2.
713  const H264Sps* sps;
714  Result res;
715  H26xBitReader reader;
716  reader.Initialize(nalu.data() + nalu.header_size(), nalu.payload_size());
717  H26xBitReader* br = &reader;
718 
719  *pps_id = -1;
720 
721  std::unique_ptr<H264Pps> pps(new H264Pps());
722 
723  READ_UE_OR_RETURN(&pps->pic_parameter_set_id);
724  READ_UE_OR_RETURN(&pps->seq_parameter_set_id);
725  TRUE_OR_RETURN(pps->seq_parameter_set_id < 32);
726 
727  sps = GetSps(pps->seq_parameter_set_id);
728  TRUE_OR_RETURN(sps);
729 
730  READ_BOOL_OR_RETURN(&pps->entropy_coding_mode_flag);
731  READ_BOOL_OR_RETURN(&pps->bottom_field_pic_order_in_frame_present_flag);
732 
733  READ_UE_OR_RETURN(&pps->num_slice_groups_minus1);
734  if (pps->num_slice_groups_minus1 > 1) {
735  DVLOG(1) << "Slice groups not supported";
736  return kUnsupportedStream;
737  }
738 
739  READ_UE_OR_RETURN(&pps->num_ref_idx_l0_default_active_minus1);
740  TRUE_OR_RETURN(pps->num_ref_idx_l0_default_active_minus1 < 32);
741 
742  READ_UE_OR_RETURN(&pps->num_ref_idx_l1_default_active_minus1);
743  TRUE_OR_RETURN(pps->num_ref_idx_l1_default_active_minus1 < 32);
744 
745  READ_BOOL_OR_RETURN(&pps->weighted_pred_flag);
746  READ_BITS_OR_RETURN(2, &pps->weighted_bipred_idc);
747  TRUE_OR_RETURN(pps->weighted_bipred_idc < 3);
748 
749  READ_SE_OR_RETURN(&pps->pic_init_qp_minus26);
750  IN_RANGE_OR_RETURN(pps->pic_init_qp_minus26, -26, 25);
751 
752  READ_SE_OR_RETURN(&pps->pic_init_qs_minus26);
753  IN_RANGE_OR_RETURN(pps->pic_init_qs_minus26, -26, 25);
754 
755  READ_SE_OR_RETURN(&pps->chroma_qp_index_offset);
756  IN_RANGE_OR_RETURN(pps->chroma_qp_index_offset, -12, 12);
757  pps->second_chroma_qp_index_offset = pps->chroma_qp_index_offset;
758 
759  READ_BOOL_OR_RETURN(&pps->deblocking_filter_control_present_flag);
760  READ_BOOL_OR_RETURN(&pps->constrained_intra_pred_flag);
761  READ_BOOL_OR_RETURN(&pps->redundant_pic_cnt_present_flag);
762 
763  if (br->HasMoreRBSPData()) {
764  READ_BOOL_OR_RETURN(&pps->transform_8x8_mode_flag);
765  READ_BOOL_OR_RETURN(&pps->pic_scaling_matrix_present_flag);
766 
767  if (pps->pic_scaling_matrix_present_flag) {
768  DVLOG(4) << "Picture scaling matrix present";
769  res = ParsePpsScalingLists(br, *sps, pps.get());
770  if (res != kOk)
771  return res;
772  }
773 
774  READ_SE_OR_RETURN(&pps->second_chroma_qp_index_offset);
775  }
776 
777  // If a PPS with the same id already exists, replace it.
778  *pps_id = pps->pic_parameter_set_id;
779  delete active_PPSes_[*pps_id];
780  active_PPSes_[*pps_id] = pps.release();
781 
782  return kOk;
783 }
784 
785 H264Parser::Result H264Parser::ParseRefPicListModification(
786  H26xBitReader* br,
787  int num_ref_idx_active_minus1,
788  H264ModificationOfPicNum* ref_list_mods) {
789  H264ModificationOfPicNum* pic_num_mod;
790 
791  if (num_ref_idx_active_minus1 >= 32)
792  return kInvalidStream;
793 
794  for (int i = 0; i < 32; ++i) {
795  pic_num_mod = &ref_list_mods[i];
796  READ_UE_OR_RETURN(&pic_num_mod->modification_of_pic_nums_idc);
797  TRUE_OR_RETURN(pic_num_mod->modification_of_pic_nums_idc < 4);
798 
799  switch (pic_num_mod->modification_of_pic_nums_idc) {
800  case 0:
801  case 1:
802  READ_UE_OR_RETURN(&pic_num_mod->abs_diff_pic_num_minus1);
803  break;
804 
805  case 2:
806  READ_UE_OR_RETURN(&pic_num_mod->long_term_pic_num);
807  break;
808 
809  case 3:
810  // Per spec, list cannot be empty.
811  if (i == 0)
812  return kInvalidStream;
813  return kOk;
814 
815  default:
816  return kInvalidStream;
817  }
818  }
819 
820  // If we got here, we didn't get loop end marker prematurely,
821  // so make sure it is there for our client.
822  int modification_of_pic_nums_idc;
823  READ_UE_OR_RETURN(&modification_of_pic_nums_idc);
824  TRUE_OR_RETURN(modification_of_pic_nums_idc == 3);
825 
826  return kOk;
827 }
828 
829 H264Parser::Result H264Parser::ParseRefPicListModifications(
830  H26xBitReader* br, H264SliceHeader* shdr) {
831  Result res;
832 
833  if (!shdr->IsISlice() && !shdr->IsSISlice()) {
834  READ_BOOL_OR_RETURN(&shdr->ref_pic_list_modification_flag_l0);
835  if (shdr->ref_pic_list_modification_flag_l0) {
836  res = ParseRefPicListModification(br, shdr->num_ref_idx_l0_active_minus1,
837  shdr->ref_list_l0_modifications);
838  if (res != kOk)
839  return res;
840  }
841  }
842 
843  if (shdr->IsBSlice()) {
844  READ_BOOL_OR_RETURN(&shdr->ref_pic_list_modification_flag_l1);
845  if (shdr->ref_pic_list_modification_flag_l1) {
846  res = ParseRefPicListModification(br, shdr->num_ref_idx_l1_active_minus1,
847  shdr->ref_list_l1_modifications);
848  if (res != kOk)
849  return res;
850  }
851  }
852 
853  return kOk;
854 }
855 
856 H264Parser::Result H264Parser::ParseWeightingFactors(
857  H26xBitReader* br,
858  int num_ref_idx_active_minus1,
859  int chroma_array_type,
860  int luma_log2_weight_denom,
861  int chroma_log2_weight_denom,
862  H264WeightingFactors* w_facts) {
863  int def_luma_weight = 1 << luma_log2_weight_denom;
864  int def_chroma_weight = 1 << chroma_log2_weight_denom;
865 
866  for (int i = 0; i < num_ref_idx_active_minus1 + 1; ++i) {
867  READ_BOOL_OR_RETURN(&w_facts->luma_weight_flag);
868  if (w_facts->luma_weight_flag) {
869  READ_SE_OR_RETURN(&w_facts->luma_weight[i]);
870  IN_RANGE_OR_RETURN(w_facts->luma_weight[i], -128, 127);
871 
872  READ_SE_OR_RETURN(&w_facts->luma_offset[i]);
873  IN_RANGE_OR_RETURN(w_facts->luma_offset[i], -128, 127);
874  } else {
875  w_facts->luma_weight[i] = def_luma_weight;
876  w_facts->luma_offset[i] = 0;
877  }
878 
879  if (chroma_array_type != 0) {
880  READ_BOOL_OR_RETURN(&w_facts->chroma_weight_flag);
881  if (w_facts->chroma_weight_flag) {
882  for (int j = 0; j < 2; ++j) {
883  READ_SE_OR_RETURN(&w_facts->chroma_weight[i][j]);
884  IN_RANGE_OR_RETURN(w_facts->chroma_weight[i][j], -128, 127);
885 
886  READ_SE_OR_RETURN(&w_facts->chroma_offset[i][j]);
887  IN_RANGE_OR_RETURN(w_facts->chroma_offset[i][j], -128, 127);
888  }
889  } else {
890  for (int j = 0; j < 2; ++j) {
891  w_facts->chroma_weight[i][j] = def_chroma_weight;
892  w_facts->chroma_offset[i][j] = 0;
893  }
894  }
895  }
896  }
897 
898  return kOk;
899 }
900 
901 H264Parser::Result H264Parser::ParsePredWeightTable(H26xBitReader* br,
902  const H264Sps& sps,
903  H264SliceHeader* shdr) {
904  READ_UE_OR_RETURN(&shdr->luma_log2_weight_denom);
905  TRUE_OR_RETURN(shdr->luma_log2_weight_denom < 8);
906 
907  if (sps.chroma_array_type != 0)
908  READ_UE_OR_RETURN(&shdr->chroma_log2_weight_denom);
909  TRUE_OR_RETURN(shdr->chroma_log2_weight_denom < 8);
910 
911  Result res = ParseWeightingFactors(br,
912  shdr->num_ref_idx_l0_active_minus1,
913  sps.chroma_array_type,
914  shdr->luma_log2_weight_denom,
915  shdr->chroma_log2_weight_denom,
916  &shdr->pred_weight_table_l0);
917  if (res != kOk)
918  return res;
919 
920  if (shdr->IsBSlice()) {
921  res = ParseWeightingFactors(br,
922  shdr->num_ref_idx_l1_active_minus1,
923  sps.chroma_array_type,
924  shdr->luma_log2_weight_denom,
925  shdr->chroma_log2_weight_denom,
926  &shdr->pred_weight_table_l1);
927  if (res != kOk)
928  return res;
929  }
930 
931  return kOk;
932 }
933 
934 H264Parser::Result H264Parser::ParseDecRefPicMarking(H26xBitReader* br,
935  H264SliceHeader* shdr) {
936  if (shdr->idr_pic_flag) {
937  READ_BOOL_OR_RETURN(&shdr->no_output_of_prior_pics_flag);
938  READ_BOOL_OR_RETURN(&shdr->long_term_reference_flag);
939  } else {
940  READ_BOOL_OR_RETURN(&shdr->adaptive_ref_pic_marking_mode_flag);
941 
942  H264DecRefPicMarking* marking;
943  if (shdr->adaptive_ref_pic_marking_mode_flag) {
944  size_t i;
945  for (i = 0; i < arraysize(shdr->ref_pic_marking); ++i) {
946  marking = &shdr->ref_pic_marking[i];
947 
948  READ_UE_OR_RETURN(&marking->memory_mgmnt_control_operation);
949  if (marking->memory_mgmnt_control_operation == 0)
950  break;
951 
952  if (marking->memory_mgmnt_control_operation == 1 ||
953  marking->memory_mgmnt_control_operation == 3)
954  READ_UE_OR_RETURN(&marking->difference_of_pic_nums_minus1);
955 
956  if (marking->memory_mgmnt_control_operation == 2)
957  READ_UE_OR_RETURN(&marking->long_term_pic_num);
958 
959  if (marking->memory_mgmnt_control_operation == 3 ||
960  marking->memory_mgmnt_control_operation == 6)
961  READ_UE_OR_RETURN(&marking->long_term_frame_idx);
962 
963  if (marking->memory_mgmnt_control_operation == 4)
964  READ_UE_OR_RETURN(&marking->max_long_term_frame_idx_plus1);
965 
966  if (marking->memory_mgmnt_control_operation > 6)
967  return kInvalidStream;
968  }
969 
970  if (i == arraysize(shdr->ref_pic_marking)) {
971  DVLOG(1) << "Ran out of dec ref pic marking fields";
972  return kUnsupportedStream;
973  }
974  }
975  }
976 
977  return kOk;
978 }
979 
980 H264Parser::Result H264Parser::ParseSliceHeader(const Nalu& nalu,
981  H264SliceHeader* shdr) {
982  // See 7.4.3.
983  const H264Sps* sps;
984  const H264Pps* pps;
985  Result res;
986  H26xBitReader reader;
987  reader.Initialize(nalu.data() + nalu.header_size(), nalu.payload_size());
988  H26xBitReader* br = &reader;
989 
990  memset(shdr, 0, sizeof(*shdr));
991 
992  shdr->idr_pic_flag = (nalu.type() == 5);
993  shdr->nal_ref_idc = nalu.ref_idc();
994  shdr->nalu_data = nalu.data() + nalu.header_size();
995  shdr->nalu_size = nalu.payload_size();
996 
997  READ_UE_OR_RETURN(&shdr->first_mb_in_slice);
998  READ_UE_OR_RETURN(&shdr->slice_type);
999  TRUE_OR_RETURN(shdr->slice_type < 10);
1000 
1001  READ_UE_OR_RETURN(&shdr->pic_parameter_set_id);
1002 
1003  pps = GetPps(shdr->pic_parameter_set_id);
1004  TRUE_OR_RETURN(pps);
1005 
1006  sps = GetSps(pps->seq_parameter_set_id);
1007  TRUE_OR_RETURN(sps);
1008 
1009  if (sps->separate_colour_plane_flag) {
1010  DVLOG(1) << "Interlaced streams not supported";
1011  return kUnsupportedStream;
1012  }
1013 
1014  READ_BITS_OR_RETURN(sps->log2_max_frame_num_minus4 + 4, &shdr->frame_num);
1015  if (!sps->frame_mbs_only_flag) {
1016  READ_BOOL_OR_RETURN(&shdr->field_pic_flag);
1017  if (shdr->field_pic_flag) {
1018  DVLOG(1) << "Interlaced streams not supported";
1019  return kUnsupportedStream;
1020  }
1021  }
1022 
1023  if (shdr->idr_pic_flag)
1024  READ_UE_OR_RETURN(&shdr->idr_pic_id);
1025 
1026  if (sps->pic_order_cnt_type == 0) {
1027  READ_BITS_OR_RETURN(sps->log2_max_pic_order_cnt_lsb_minus4 + 4,
1028  &shdr->pic_order_cnt_lsb);
1029  if (pps->bottom_field_pic_order_in_frame_present_flag &&
1030  !shdr->field_pic_flag)
1031  READ_SE_OR_RETURN(&shdr->delta_pic_order_cnt_bottom);
1032  }
1033 
1034  if (sps->pic_order_cnt_type == 1 && !sps->delta_pic_order_always_zero_flag) {
1035  READ_SE_OR_RETURN(&shdr->delta_pic_order_cnt[0]);
1036  if (pps->bottom_field_pic_order_in_frame_present_flag &&
1037  !shdr->field_pic_flag)
1038  READ_SE_OR_RETURN(&shdr->delta_pic_order_cnt[1]);
1039  }
1040 
1041  if (pps->redundant_pic_cnt_present_flag) {
1042  READ_UE_OR_RETURN(&shdr->redundant_pic_cnt);
1043  TRUE_OR_RETURN(shdr->redundant_pic_cnt < 128);
1044  }
1045 
1046  if (shdr->IsBSlice())
1047  READ_BOOL_OR_RETURN(&shdr->direct_spatial_mv_pred_flag);
1048 
1049  if (shdr->IsPSlice() || shdr->IsSPSlice() || shdr->IsBSlice()) {
1050  READ_BOOL_OR_RETURN(&shdr->num_ref_idx_active_override_flag);
1051  if (shdr->num_ref_idx_active_override_flag) {
1052  READ_UE_OR_RETURN(&shdr->num_ref_idx_l0_active_minus1);
1053  if (shdr->IsBSlice())
1054  READ_UE_OR_RETURN(&shdr->num_ref_idx_l1_active_minus1);
1055  } else {
1056  shdr->num_ref_idx_l0_active_minus1 =
1057  pps->num_ref_idx_l0_default_active_minus1;
1058  if (shdr->IsBSlice()) {
1059  shdr->num_ref_idx_l1_active_minus1 =
1060  pps->num_ref_idx_l1_default_active_minus1;
1061  }
1062  }
1063  }
1064  if (shdr->field_pic_flag) {
1065  TRUE_OR_RETURN(shdr->num_ref_idx_l0_active_minus1 < 32);
1066  TRUE_OR_RETURN(shdr->num_ref_idx_l1_active_minus1 < 32);
1067  } else {
1068  TRUE_OR_RETURN(shdr->num_ref_idx_l0_active_minus1 < 16);
1069  TRUE_OR_RETURN(shdr->num_ref_idx_l1_active_minus1 < 16);
1070  }
1071 
1072  if (nalu.type() == Nalu::H264_CodedSliceExtension) {
1073  return kUnsupportedStream;
1074  } else {
1075  res = ParseRefPicListModifications(br, shdr);
1076  if (res != kOk)
1077  return res;
1078  }
1079 
1080  if ((pps->weighted_pred_flag && (shdr->IsPSlice() || shdr->IsSPSlice())) ||
1081  (pps->weighted_bipred_idc == 1 && shdr->IsBSlice())) {
1082  res = ParsePredWeightTable(br, *sps, shdr);
1083  if (res != kOk)
1084  return res;
1085  }
1086 
1087  if (nalu.ref_idc() != 0) {
1088  res = ParseDecRefPicMarking(br, shdr);
1089  if (res != kOk)
1090  return res;
1091  }
1092 
1093  if (pps->entropy_coding_mode_flag && !shdr->IsISlice() &&
1094  !shdr->IsSISlice()) {
1095  READ_UE_OR_RETURN(&shdr->cabac_init_idc);
1096  TRUE_OR_RETURN(shdr->cabac_init_idc < 3);
1097  }
1098 
1099  READ_SE_OR_RETURN(&shdr->slice_qp_delta);
1100 
1101  if (shdr->IsSPSlice() || shdr->IsSISlice()) {
1102  if (shdr->IsSPSlice())
1103  READ_BOOL_OR_RETURN(&shdr->sp_for_switch_flag);
1104  READ_SE_OR_RETURN(&shdr->slice_qs_delta);
1105  }
1106 
1107  if (pps->deblocking_filter_control_present_flag) {
1108  READ_UE_OR_RETURN(&shdr->disable_deblocking_filter_idc);
1109  TRUE_OR_RETURN(shdr->disable_deblocking_filter_idc < 3);
1110 
1111  if (shdr->disable_deblocking_filter_idc != 1) {
1112  READ_SE_OR_RETURN(&shdr->slice_alpha_c0_offset_div2);
1113  IN_RANGE_OR_RETURN(shdr->slice_alpha_c0_offset_div2, -6, 6);
1114 
1115  READ_SE_OR_RETURN(&shdr->slice_beta_offset_div2);
1116  IN_RANGE_OR_RETURN(shdr->slice_beta_offset_div2, -6, 6);
1117  }
1118  }
1119 
1120  if (pps->num_slice_groups_minus1 > 0) {
1121  DVLOG(1) << "Slice groups not supported";
1122  return kUnsupportedStream;
1123  }
1124 
1125  size_t epb = br->NumEmulationPreventionBytesRead();
1126  shdr->header_bit_size = (shdr->nalu_size - epb) * 8 - br->NumBitsLeft();
1127 
1128  return kOk;
1129 }
1130 
1131 H264Parser::Result H264Parser::ParseSEI(const Nalu& nalu,
1132  H264SEIMessage* sei_msg) {
1133  int byte;
1134  H26xBitReader reader;
1135  reader.Initialize(nalu.data() + nalu.header_size(), nalu.payload_size());
1136  H26xBitReader* br = &reader;
1137 
1138  memset(sei_msg, 0, sizeof(*sei_msg));
1139 
1140  READ_BITS_OR_RETURN(8, &byte);
1141  while (byte == 0xff) {
1142  sei_msg->type += 255;
1143  READ_BITS_OR_RETURN(8, &byte);
1144  }
1145  sei_msg->type += byte;
1146 
1147  READ_BITS_OR_RETURN(8, &byte);
1148  while (byte == 0xff) {
1149  sei_msg->payload_size += 255;
1150  READ_BITS_OR_RETURN(8, &byte);
1151  }
1152  sei_msg->payload_size += byte;
1153 
1154  DVLOG(4) << "Found SEI message type: " << sei_msg->type
1155  << " payload size: " << sei_msg->payload_size;
1156 
1157  switch (sei_msg->type) {
1158  case H264SEIMessage::kSEIRecoveryPoint:
1159  READ_UE_OR_RETURN(&sei_msg->recovery_point.recovery_frame_cnt);
1160  READ_BOOL_OR_RETURN(&sei_msg->recovery_point.exact_match_flag);
1161  READ_BOOL_OR_RETURN(&sei_msg->recovery_point.broken_link_flag);
1162  READ_BITS_OR_RETURN(2, &sei_msg->recovery_point.changing_slice_group_idc);
1163  break;
1164 
1165  default:
1166  DVLOG(4) << "Unsupported SEI message";
1167  break;
1168  }
1169 
1170  return kOk;
1171 }
1172 
1173 } // namespace media
1174 } // namespace shaka