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