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.
5 #include "base/logging.h"
6 #include "base/memory/scoped_ptr.h"
7 #include "base/stl_util.h"
9 #include "media/base/decrypt_config.h"
10 #include "media/filters/h264_parser.h"
14 bool H264SliceHeader::IsPSlice() const {
15 return (slice_type
% 5 == kPSlice
);
18 bool H264SliceHeader::IsBSlice() const {
19 return (slice_type
% 5 == kBSlice
);
22 bool H264SliceHeader::IsISlice() const {
23 return (slice_type
% 5 == kISlice
);
26 bool H264SliceHeader::IsSPSlice() const {
27 return (slice_type
% 5 == kSPSlice
);
30 bool H264SliceHeader::IsSISlice() const {
31 return (slice_type
% 5 == kSISlice
);
34 H264NALU::H264NALU() {
35 memset(this, 0, sizeof(*this));
39 memset(this, 0, sizeof(*this));
43 memset(this, 0, sizeof(*this));
46 H264SliceHeader::H264SliceHeader() {
47 memset(this, 0, sizeof(*this));
50 H264SEIMessage::H264SEIMessage() {
51 memset(this, 0, sizeof(*this));
54 #define READ_BITS_OR_RETURN(num_bits, out) \
57 if (!br_.ReadBits(num_bits, &_out)) { \
59 << "Error in stream: unexpected EOS while trying to read " #out; \
60 return kInvalidStream; \
65 #define READ_BOOL_OR_RETURN(out) \
68 if (!br_.ReadBits(1, &_out)) { \
70 << "Error in stream: unexpected EOS while trying to read " #out; \
71 return kInvalidStream; \
76 #define READ_UE_OR_RETURN(out) \
78 if (ReadUE(out) != kOk) { \
79 DVLOG(1) << "Error in stream: invalid value while trying to read " #out; \
80 return kInvalidStream; \
84 #define READ_SE_OR_RETURN(out) \
86 if (ReadSE(out) != kOk) { \
87 DVLOG(1) << "Error in stream: invalid value while trying to read " #out; \
88 return kInvalidStream; \
92 #define IN_RANGE_OR_RETURN(val, min, max) \
94 if ((val) < (min) || (val) > (max)) { \
95 DVLOG(1) << "Error in stream: invalid value, expected " #val " to be" \
96 << " in range [" << (min) << ":" << (max) << "]" \
97 << " found " << (val) << " instead"; \
98 return kInvalidStream; \
102 #define TRUE_OR_RETURN(a) \
105 DVLOG(1) << "Error in stream: invalid value, expected " << #a; \
106 return kInvalidStream; \
111 // VUI parameters: Table E-1 "Meaning of sample aspect ratio indicator"
112 static const int kTableSarWidth
[] = {
113 0, 1, 12, 10, 16, 40, 24, 20, 32, 80, 18, 15, 64, 160, 4, 3, 2
115 static const int kTableSarHeight
[] = {
116 0, 1, 11, 11, 11, 33, 11, 11, 11, 33, 11, 11, 33, 99, 3, 2, 1
118 static_assert(arraysize(kTableSarWidth
) == arraysize(kTableSarHeight
),
119 "sar tables must have the same size");
121 H264Parser::H264Parser() {
125 H264Parser::~H264Parser() {
126 STLDeleteValues(&active_SPSes_
);
127 STLDeleteValues(&active_PPSes_
);
130 void H264Parser::Reset() {
133 encrypted_ranges_
.clear();
136 void H264Parser::SetStream(const uint8
* stream
, off_t stream_size
) {
137 std::vector
<SubsampleEntry
> subsamples
;
138 SetEncryptedStream(stream
, stream_size
, subsamples
);
141 void H264Parser::SetEncryptedStream(
142 const uint8
* stream
, off_t stream_size
,
143 const std::vector
<SubsampleEntry
>& subsamples
) {
145 DCHECK_GT(stream_size
, 0);
148 bytes_left_
= stream_size
;
150 encrypted_ranges_
.clear();
151 const uint8
* start
= stream
;
152 const uint8
* stream_end
= stream_
+ bytes_left_
;
153 for (size_t i
= 0; i
< subsamples
.size() && start
< stream_end
; ++i
) {
154 start
+= subsamples
[i
].clear_bytes
;
156 const uint8
* end
= std::min(start
+ subsamples
[i
].cypher_bytes
, stream_end
);
157 encrypted_ranges_
.Add(start
, end
);
162 const H264PPS
* H264Parser::GetPPS(int pps_id
) {
163 return active_PPSes_
[pps_id
];
166 const H264SPS
* H264Parser::GetSPS(int sps_id
) {
167 return active_SPSes_
[sps_id
];
170 static inline bool IsStartCode(const uint8
* data
) {
171 return data
[0] == 0x00 && data
[1] == 0x00 && data
[2] == 0x01;
175 bool H264Parser::FindStartCode(const uint8
* data
, off_t data_size
,
176 off_t
* offset
, off_t
* start_code_size
) {
177 DCHECK_GE(data_size
, 0);
178 off_t bytes_left
= data_size
;
180 while (bytes_left
>= 3) {
181 if (IsStartCode(data
)) {
182 // Found three-byte start code, set pointer at its beginning.
183 *offset
= data_size
- bytes_left
;
184 *start_code_size
= 3;
186 // If there is a zero byte before this start code,
187 // then it's actually a four-byte start code, so backtrack one byte.
188 if (*offset
> 0 && *(data
- 1) == 0x00) {
190 ++(*start_code_size
);
200 // End of data: offset is pointing to the first byte that was not considered
201 // as a possible start of a start code.
202 // Note: there is no security issue when receiving a negative |data_size|
203 // since in this case, |bytes_left| is equal to |data_size| and thus
204 // |*offset| is equal to 0 (valid offset).
205 *offset
= data_size
- bytes_left
;
206 *start_code_size
= 0;
210 bool H264Parser::LocateNALU(off_t
* nalu_size
, off_t
* start_code_size
) {
211 // Find the start code of next NALU.
212 off_t nalu_start_off
= 0;
213 off_t annexb_start_code_size
= 0;
215 if (!FindStartCodeInClearRanges(stream_
, bytes_left_
,
216 &nalu_start_off
, &annexb_start_code_size
)) {
217 DVLOG(4) << "Could not find start code, end of stream?";
221 // Move the stream to the beginning of the NALU (pointing at the start code).
222 stream_
+= nalu_start_off
;
223 bytes_left_
-= nalu_start_off
;
225 const uint8
* nalu_data
= stream_
+ annexb_start_code_size
;
226 off_t max_nalu_data_size
= bytes_left_
- annexb_start_code_size
;
227 if (max_nalu_data_size
<= 0) {
228 DVLOG(3) << "End of stream";
232 // Find the start code of next NALU;
233 // if successful, |nalu_size_without_start_code| is the number of bytes from
234 // after previous start code to before this one;
235 // if next start code is not found, it is still a valid NALU since there
236 // are some bytes left after the first start code: all the remaining bytes
237 // belong to the current NALU.
238 off_t next_start_code_size
= 0;
239 off_t nalu_size_without_start_code
= 0;
240 if (!FindStartCodeInClearRanges(nalu_data
, max_nalu_data_size
,
241 &nalu_size_without_start_code
,
242 &next_start_code_size
)) {
243 nalu_size_without_start_code
= max_nalu_data_size
;
245 *nalu_size
= nalu_size_without_start_code
+ annexb_start_code_size
;
246 *start_code_size
= annexb_start_code_size
;
250 bool H264Parser::FindStartCodeInClearRanges(
254 off_t
* start_code_size
) {
255 if (encrypted_ranges_
.size() == 0)
256 return FindStartCode(data
, data_size
, offset
, start_code_size
);
258 DCHECK_GE(data_size
, 0);
259 const uint8
* start
= data
;
261 off_t bytes_left
= data_size
- (start
- data
);
263 if (!FindStartCode(start
, bytes_left
, offset
, start_code_size
))
266 // Construct a Ranges object that represents the region occupied
267 // by the start code and the 1 byte needed to read the NAL unit type.
268 const uint8
* start_code
= start
+ *offset
;
269 const uint8
* start_code_end
= start_code
+ *start_code_size
;
270 Ranges
<const uint8
*> start_code_range
;
271 start_code_range
.Add(start_code
, start_code_end
+ 1);
273 if (encrypted_ranges_
.IntersectionWith(start_code_range
).size() > 0) {
274 // The start code is inside an encrypted section so we need to scan
275 // for another start code.
276 *start_code_size
= 0;
277 start
+= std::min(*offset
+ 1, bytes_left
);
279 } while (*start_code_size
== 0);
281 // Update |*offset| to include the data we skipped over.
282 *offset
+= start
- data
;
286 H264Parser::Result
H264Parser::ReadUE(int* val
) {
291 // Count the number of contiguous zero bits.
293 READ_BITS_OR_RETURN(1, &bit
);
298 return kInvalidStream
;
300 // Calculate exp-Golomb code value of size num_bits.
301 *val
= (1 << num_bits
) - 1;
304 READ_BITS_OR_RETURN(num_bits
, &rest
);
311 H264Parser::Result
H264Parser::ReadSE(int* val
) {
315 // See Chapter 9 in the spec.
328 H264Parser::Result
H264Parser::AdvanceToNextNALU(H264NALU
* nalu
) {
329 off_t start_code_size
;
330 off_t nalu_size_with_start_code
;
331 if (!LocateNALU(&nalu_size_with_start_code
, &start_code_size
)) {
332 DVLOG(4) << "Could not find next NALU, bytes left in stream: "
337 nalu
->data
= stream_
+ start_code_size
;
338 nalu
->size
= nalu_size_with_start_code
- start_code_size
;
339 DVLOG(4) << "NALU found: size=" << nalu_size_with_start_code
;
341 // Initialize bit reader at the start of found NALU.
342 if (!br_
.Initialize(nalu
->data
, nalu
->size
))
345 // Move parser state to after this NALU, so next time AdvanceToNextNALU
346 // is called, we will effectively be skipping it;
347 // other parsing functions will use the position saved
348 // in bit reader for parsing, so we don't have to remember it here.
349 stream_
+= nalu_size_with_start_code
;
350 bytes_left_
-= nalu_size_with_start_code
;
352 // Read NALU header, skip the forbidden_zero_bit, but check for it.
354 READ_BITS_OR_RETURN(1, &data
);
355 TRUE_OR_RETURN(data
== 0);
357 READ_BITS_OR_RETURN(2, &nalu
->nal_ref_idc
);
358 READ_BITS_OR_RETURN(5, &nalu
->nal_unit_type
);
360 DVLOG(4) << "NALU type: " << static_cast<int>(nalu
->nal_unit_type
)
361 << " at: " << reinterpret_cast<const void*>(nalu
->data
)
362 << " size: " << nalu
->size
363 << " ref: " << static_cast<int>(nalu
->nal_ref_idc
);
368 // Default scaling lists (per spec).
369 static const int kDefault4x4Intra
[kH264ScalingList4x4Length
] = {
370 6, 13, 13, 20, 20, 20, 28, 28, 28, 28, 32, 32, 32, 37, 37, 42, };
372 static const int kDefault4x4Inter
[kH264ScalingList4x4Length
] = {
373 10, 14, 14, 20, 20, 20, 24, 24, 24, 24, 27, 27, 27, 30, 30, 34, };
375 static const int kDefault8x8Intra
[kH264ScalingList8x8Length
] = {
376 6, 10, 10, 13, 11, 13, 16, 16, 16, 16, 18, 18, 18, 18, 18, 23,
377 23, 23, 23, 23, 23, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27,
378 27, 27, 27, 27, 29, 29, 29, 29, 29, 29, 29, 31, 31, 31, 31, 31,
379 31, 33, 33, 33, 33, 33, 36, 36, 36, 36, 38, 38, 38, 40, 40, 42, };
381 static const int kDefault8x8Inter
[kH264ScalingList8x8Length
] = {
382 9, 13, 13, 15, 13, 15, 17, 17, 17, 17, 19, 19, 19, 19, 19, 21,
383 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 24, 24, 24, 24,
384 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27, 27,
385 27, 28, 28, 28, 28, 28, 30, 30, 30, 30, 32, 32, 32, 33, 33, 35, };
387 static inline void DefaultScalingList4x4(
389 int scaling_list4x4
[][kH264ScalingList4x4Length
]) {
393 memcpy(scaling_list4x4
[i
], kDefault4x4Intra
, sizeof(kDefault4x4Intra
));
395 memcpy(scaling_list4x4
[i
], kDefault4x4Inter
, sizeof(kDefault4x4Inter
));
398 static inline void DefaultScalingList8x8(
400 int scaling_list8x8
[][kH264ScalingList8x8Length
]) {
404 memcpy(scaling_list8x8
[i
], kDefault8x8Intra
, sizeof(kDefault8x8Intra
));
406 memcpy(scaling_list8x8
[i
], kDefault8x8Inter
, sizeof(kDefault8x8Inter
));
409 static void FallbackScalingList4x4(
411 const int default_scaling_list_intra
[],
412 const int default_scaling_list_inter
[],
413 int scaling_list4x4
[][kH264ScalingList4x4Length
]) {
414 static const int kScalingList4x4ByteSize
=
415 sizeof(scaling_list4x4
[0][0]) * kH264ScalingList4x4Length
;
419 memcpy(scaling_list4x4
[i
], default_scaling_list_intra
,
420 kScalingList4x4ByteSize
);
424 memcpy(scaling_list4x4
[i
], scaling_list4x4
[0], kScalingList4x4ByteSize
);
428 memcpy(scaling_list4x4
[i
], scaling_list4x4
[1], kScalingList4x4ByteSize
);
432 memcpy(scaling_list4x4
[i
], default_scaling_list_inter
,
433 kScalingList4x4ByteSize
);
437 memcpy(scaling_list4x4
[i
], scaling_list4x4
[3], kScalingList4x4ByteSize
);
441 memcpy(scaling_list4x4
[i
], scaling_list4x4
[4], kScalingList4x4ByteSize
);
450 static void FallbackScalingList8x8(
452 const int default_scaling_list_intra
[],
453 const int default_scaling_list_inter
[],
454 int scaling_list8x8
[][kH264ScalingList8x8Length
]) {
455 static const int kScalingList8x8ByteSize
=
456 sizeof(scaling_list8x8
[0][0]) * kH264ScalingList8x8Length
;
460 memcpy(scaling_list8x8
[i
], default_scaling_list_intra
,
461 kScalingList8x8ByteSize
);
465 memcpy(scaling_list8x8
[i
], default_scaling_list_inter
,
466 kScalingList8x8ByteSize
);
470 memcpy(scaling_list8x8
[i
], scaling_list8x8
[0], kScalingList8x8ByteSize
);
474 memcpy(scaling_list8x8
[i
], scaling_list8x8
[1], kScalingList8x8ByteSize
);
478 memcpy(scaling_list8x8
[i
], scaling_list8x8
[2], kScalingList8x8ByteSize
);
482 memcpy(scaling_list8x8
[i
], scaling_list8x8
[3], kScalingList8x8ByteSize
);
491 H264Parser::Result
H264Parser::ParseScalingList(int size
,
494 // See chapter 7.3.2.1.1.1.
499 *use_default
= false;
501 for (int j
= 0; j
< size
; ++j
) {
502 if (next_scale
!= 0) {
503 READ_SE_OR_RETURN(&delta_scale
);
504 IN_RANGE_OR_RETURN(delta_scale
, -128, 127);
505 next_scale
= (last_scale
+ delta_scale
+ 256) & 0xff;
507 if (j
== 0 && next_scale
== 0) {
513 scaling_list
[j
] = (next_scale
== 0) ? last_scale
: next_scale
;
514 last_scale
= scaling_list
[j
];
520 H264Parser::Result
H264Parser::ParseSPSScalingLists(H264SPS
* sps
) {
522 bool seq_scaling_list_present_flag
;
526 // Parse scaling_list4x4.
527 for (int i
= 0; i
< 6; ++i
) {
528 READ_BOOL_OR_RETURN(&seq_scaling_list_present_flag
);
530 if (seq_scaling_list_present_flag
) {
531 res
= ParseScalingList(arraysize(sps
->scaling_list4x4
[i
]),
532 sps
->scaling_list4x4
[i
],
538 DefaultScalingList4x4(i
, sps
->scaling_list4x4
);
541 FallbackScalingList4x4(
542 i
, kDefault4x4Intra
, kDefault4x4Inter
, sps
->scaling_list4x4
);
546 // Parse scaling_list8x8.
547 for (int i
= 0; i
< ((sps
->chroma_format_idc
!= 3) ? 2 : 6); ++i
) {
548 READ_BOOL_OR_RETURN(&seq_scaling_list_present_flag
);
550 if (seq_scaling_list_present_flag
) {
551 res
= ParseScalingList(arraysize(sps
->scaling_list8x8
[i
]),
552 sps
->scaling_list8x8
[i
],
558 DefaultScalingList8x8(i
, sps
->scaling_list8x8
);
561 FallbackScalingList8x8(
562 i
, kDefault8x8Intra
, kDefault8x8Inter
, sps
->scaling_list8x8
);
569 H264Parser::Result
H264Parser::ParsePPSScalingLists(const H264SPS
& sps
,
572 bool pic_scaling_list_present_flag
;
576 for (int i
= 0; i
< 6; ++i
) {
577 READ_BOOL_OR_RETURN(&pic_scaling_list_present_flag
);
579 if (pic_scaling_list_present_flag
) {
580 res
= ParseScalingList(arraysize(pps
->scaling_list4x4
[i
]),
581 pps
->scaling_list4x4
[i
],
587 DefaultScalingList4x4(i
, pps
->scaling_list4x4
);
590 if (sps
.seq_scaling_matrix_present_flag
) {
591 // Table 7-2 fallback rule A in spec.
592 FallbackScalingList4x4(
593 i
, kDefault4x4Intra
, kDefault4x4Inter
, pps
->scaling_list4x4
);
595 // Table 7-2 fallback rule B in spec.
596 FallbackScalingList4x4(i
,
597 sps
.scaling_list4x4
[0],
598 sps
.scaling_list4x4
[3],
599 pps
->scaling_list4x4
);
604 if (pps
->transform_8x8_mode_flag
) {
605 for (int i
= 0; i
< ((sps
.chroma_format_idc
!= 3) ? 2 : 6); ++i
) {
606 READ_BOOL_OR_RETURN(&pic_scaling_list_present_flag
);
608 if (pic_scaling_list_present_flag
) {
609 res
= ParseScalingList(arraysize(pps
->scaling_list8x8
[i
]),
610 pps
->scaling_list8x8
[i
],
616 DefaultScalingList8x8(i
, pps
->scaling_list8x8
);
619 if (sps
.seq_scaling_matrix_present_flag
) {
620 // Table 7-2 fallback rule A in spec.
621 FallbackScalingList8x8(
622 i
, kDefault8x8Intra
, kDefault8x8Inter
, pps
->scaling_list8x8
);
624 // Table 7-2 fallback rule B in spec.
625 FallbackScalingList8x8(i
,
626 sps
.scaling_list8x8
[0],
627 sps
.scaling_list8x8
[1],
628 pps
->scaling_list8x8
);
636 H264Parser::Result
H264Parser::ParseAndIgnoreHRDParameters(
637 bool* hrd_parameters_present
) {
639 READ_BOOL_OR_RETURN(&data
); // {nal,vcl}_hrd_parameters_present_flag
643 *hrd_parameters_present
= true;
646 READ_UE_OR_RETURN(&cpb_cnt_minus1
);
647 IN_RANGE_OR_RETURN(cpb_cnt_minus1
, 0, 31);
648 READ_BITS_OR_RETURN(8, &data
); // bit_rate_scale, cpb_size_scale
649 for (int i
= 0; i
<= cpb_cnt_minus1
; ++i
) {
650 READ_UE_OR_RETURN(&data
); // bit_rate_value_minus1[i]
651 READ_UE_OR_RETURN(&data
); // cpb_size_value_minus1[i]
652 READ_BOOL_OR_RETURN(&data
); // cbr_flag
654 READ_BITS_OR_RETURN(20, &data
); // cpb/dpb delays, etc.
659 H264Parser::Result
H264Parser::ParseVUIParameters(H264SPS
* sps
) {
660 bool aspect_ratio_info_present_flag
;
661 READ_BOOL_OR_RETURN(&aspect_ratio_info_present_flag
);
662 if (aspect_ratio_info_present_flag
) {
663 int aspect_ratio_idc
;
664 READ_BITS_OR_RETURN(8, &aspect_ratio_idc
);
665 if (aspect_ratio_idc
== H264SPS::kExtendedSar
) {
666 READ_BITS_OR_RETURN(16, &sps
->sar_width
);
667 READ_BITS_OR_RETURN(16, &sps
->sar_height
);
669 const int max_aspect_ratio_idc
= arraysize(kTableSarWidth
) - 1;
670 IN_RANGE_OR_RETURN(aspect_ratio_idc
, 0, max_aspect_ratio_idc
);
671 sps
->sar_width
= kTableSarWidth
[aspect_ratio_idc
];
672 sps
->sar_height
= kTableSarHeight
[aspect_ratio_idc
];
677 // Read and ignore overscan and video signal type info.
678 READ_BOOL_OR_RETURN(&data
); // overscan_info_present_flag
680 READ_BOOL_OR_RETURN(&data
); // overscan_appropriate_flag
682 READ_BOOL_OR_RETURN(&data
); // video_signal_type_present_flag
684 READ_BITS_OR_RETURN(3, &data
); // video_format
685 READ_BOOL_OR_RETURN(&data
); // video_full_range_flag
686 READ_BOOL_OR_RETURN(&data
); // colour_description_present_flag
688 READ_BITS_OR_RETURN(24, &data
); // color description syntax elements
691 READ_BOOL_OR_RETURN(&data
); // chroma_loc_info_present_flag
693 READ_UE_OR_RETURN(&data
); // chroma_sample_loc_type_top_field
694 READ_UE_OR_RETURN(&data
); // chroma_sample_loc_type_bottom_field
697 // Read and ignore timing info.
698 READ_BOOL_OR_RETURN(&data
); // timing_info_present_flag
700 READ_BITS_OR_RETURN(16, &data
); // num_units_in_tick
701 READ_BITS_OR_RETURN(16, &data
); // num_units_in_tick
702 READ_BITS_OR_RETURN(16, &data
); // time_scale
703 READ_BITS_OR_RETURN(16, &data
); // time_scale
704 READ_BOOL_OR_RETURN(&data
); // fixed_frame_rate_flag
707 // Read and ignore NAL HRD parameters, if present.
708 bool hrd_parameters_present
= false;
709 Result res
= ParseAndIgnoreHRDParameters(&hrd_parameters_present
);
713 // Read and ignore VCL HRD parameters, if present.
714 res
= ParseAndIgnoreHRDParameters(&hrd_parameters_present
);
718 if (hrd_parameters_present
) // One of NAL or VCL params present is enough.
719 READ_BOOL_OR_RETURN(&data
); // low_delay_hrd_flag
721 READ_BOOL_OR_RETURN(&data
); // pic_struct_present_flag
722 READ_BOOL_OR_RETURN(&sps
->bitstream_restriction_flag
);
723 if (sps
->bitstream_restriction_flag
) {
724 READ_BOOL_OR_RETURN(&data
); // motion_vectors_over_pic_boundaries_flag
725 READ_UE_OR_RETURN(&data
); // max_bytes_per_pic_denom
726 READ_UE_OR_RETURN(&data
); // max_bits_per_mb_denom
727 READ_UE_OR_RETURN(&data
); // log2_max_mv_length_horizontal
728 READ_UE_OR_RETURN(&data
); // log2_max_mv_length_vertical
729 READ_UE_OR_RETURN(&sps
->max_num_reorder_frames
);
730 READ_UE_OR_RETURN(&sps
->max_dec_frame_buffering
);
731 TRUE_OR_RETURN(sps
->max_dec_frame_buffering
>= sps
->max_num_ref_frames
);
733 sps
->max_num_reorder_frames
, 0, sps
->max_dec_frame_buffering
);
739 static void FillDefaultSeqScalingLists(H264SPS
* sps
) {
740 for (int i
= 0; i
< 6; ++i
)
741 for (int j
= 0; j
< kH264ScalingList4x4Length
; ++j
)
742 sps
->scaling_list4x4
[i
][j
] = 16;
744 for (int i
= 0; i
< 6; ++i
)
745 for (int j
= 0; j
< kH264ScalingList8x8Length
; ++j
)
746 sps
->scaling_list8x8
[i
][j
] = 16;
749 H264Parser::Result
H264Parser::ParseSPS(int* sps_id
) {
756 scoped_ptr
<H264SPS
> sps(new H264SPS());
758 READ_BITS_OR_RETURN(8, &sps
->profile_idc
);
759 READ_BOOL_OR_RETURN(&sps
->constraint_set0_flag
);
760 READ_BOOL_OR_RETURN(&sps
->constraint_set1_flag
);
761 READ_BOOL_OR_RETURN(&sps
->constraint_set2_flag
);
762 READ_BOOL_OR_RETURN(&sps
->constraint_set3_flag
);
763 READ_BOOL_OR_RETURN(&sps
->constraint_set4_flag
);
764 READ_BOOL_OR_RETURN(&sps
->constraint_set5_flag
);
765 READ_BITS_OR_RETURN(2, &data
); // reserved_zero_2bits
766 READ_BITS_OR_RETURN(8, &sps
->level_idc
);
767 READ_UE_OR_RETURN(&sps
->seq_parameter_set_id
);
768 TRUE_OR_RETURN(sps
->seq_parameter_set_id
< 32);
770 if (sps
->profile_idc
== 100 || sps
->profile_idc
== 110 ||
771 sps
->profile_idc
== 122 || sps
->profile_idc
== 244 ||
772 sps
->profile_idc
== 44 || sps
->profile_idc
== 83 ||
773 sps
->profile_idc
== 86 || sps
->profile_idc
== 118 ||
774 sps
->profile_idc
== 128) {
775 READ_UE_OR_RETURN(&sps
->chroma_format_idc
);
776 TRUE_OR_RETURN(sps
->chroma_format_idc
< 4);
778 if (sps
->chroma_format_idc
== 3)
779 READ_BOOL_OR_RETURN(&sps
->separate_colour_plane_flag
);
781 READ_UE_OR_RETURN(&sps
->bit_depth_luma_minus8
);
782 TRUE_OR_RETURN(sps
->bit_depth_luma_minus8
< 7);
784 READ_UE_OR_RETURN(&sps
->bit_depth_chroma_minus8
);
785 TRUE_OR_RETURN(sps
->bit_depth_chroma_minus8
< 7);
787 READ_BOOL_OR_RETURN(&sps
->qpprime_y_zero_transform_bypass_flag
);
788 READ_BOOL_OR_RETURN(&sps
->seq_scaling_matrix_present_flag
);
790 if (sps
->seq_scaling_matrix_present_flag
) {
791 DVLOG(4) << "Scaling matrix present";
792 res
= ParseSPSScalingLists(sps
.get());
796 FillDefaultSeqScalingLists(sps
.get());
799 sps
->chroma_format_idc
= 1;
800 FillDefaultSeqScalingLists(sps
.get());
803 if (sps
->separate_colour_plane_flag
)
804 sps
->chroma_array_type
= 0;
806 sps
->chroma_array_type
= sps
->chroma_format_idc
;
808 READ_UE_OR_RETURN(&sps
->log2_max_frame_num_minus4
);
809 TRUE_OR_RETURN(sps
->log2_max_frame_num_minus4
< 13);
811 READ_UE_OR_RETURN(&sps
->pic_order_cnt_type
);
812 TRUE_OR_RETURN(sps
->pic_order_cnt_type
< 3);
814 sps
->expected_delta_per_pic_order_cnt_cycle
= 0;
815 if (sps
->pic_order_cnt_type
== 0) {
816 READ_UE_OR_RETURN(&sps
->log2_max_pic_order_cnt_lsb_minus4
);
817 TRUE_OR_RETURN(sps
->log2_max_pic_order_cnt_lsb_minus4
< 13);
818 } else if (sps
->pic_order_cnt_type
== 1) {
819 READ_BOOL_OR_RETURN(&sps
->delta_pic_order_always_zero_flag
);
820 READ_SE_OR_RETURN(&sps
->offset_for_non_ref_pic
);
821 READ_SE_OR_RETURN(&sps
->offset_for_top_to_bottom_field
);
822 READ_UE_OR_RETURN(&sps
->num_ref_frames_in_pic_order_cnt_cycle
);
823 TRUE_OR_RETURN(sps
->num_ref_frames_in_pic_order_cnt_cycle
< 255);
825 for (int i
= 0; i
< sps
->num_ref_frames_in_pic_order_cnt_cycle
; ++i
) {
826 READ_SE_OR_RETURN(&sps
->offset_for_ref_frame
[i
]);
827 sps
->expected_delta_per_pic_order_cnt_cycle
+=
828 sps
->offset_for_ref_frame
[i
];
832 READ_UE_OR_RETURN(&sps
->max_num_ref_frames
);
833 READ_BOOL_OR_RETURN(&sps
->gaps_in_frame_num_value_allowed_flag
);
835 if (sps
->gaps_in_frame_num_value_allowed_flag
)
836 return kUnsupportedStream
;
838 READ_UE_OR_RETURN(&sps
->pic_width_in_mbs_minus1
);
839 READ_UE_OR_RETURN(&sps
->pic_height_in_map_units_minus1
);
841 READ_BOOL_OR_RETURN(&sps
->frame_mbs_only_flag
);
842 if (!sps
->frame_mbs_only_flag
)
843 READ_BOOL_OR_RETURN(&sps
->mb_adaptive_frame_field_flag
);
845 READ_BOOL_OR_RETURN(&sps
->direct_8x8_inference_flag
);
847 READ_BOOL_OR_RETURN(&sps
->frame_cropping_flag
);
848 if (sps
->frame_cropping_flag
) {
849 READ_UE_OR_RETURN(&sps
->frame_crop_left_offset
);
850 READ_UE_OR_RETURN(&sps
->frame_crop_right_offset
);
851 READ_UE_OR_RETURN(&sps
->frame_crop_top_offset
);
852 READ_UE_OR_RETURN(&sps
->frame_crop_bottom_offset
);
855 READ_BOOL_OR_RETURN(&sps
->vui_parameters_present_flag
);
856 if (sps
->vui_parameters_present_flag
) {
857 DVLOG(4) << "VUI parameters present";
858 res
= ParseVUIParameters(sps
.get());
863 // If an SPS with the same id already exists, replace it.
864 *sps_id
= sps
->seq_parameter_set_id
;
865 delete active_SPSes_
[*sps_id
];
866 active_SPSes_
[*sps_id
] = sps
.release();
871 H264Parser::Result
H264Parser::ParsePPS(int* pps_id
) {
878 scoped_ptr
<H264PPS
> pps(new H264PPS());
880 READ_UE_OR_RETURN(&pps
->pic_parameter_set_id
);
881 READ_UE_OR_RETURN(&pps
->seq_parameter_set_id
);
882 TRUE_OR_RETURN(pps
->seq_parameter_set_id
< 32);
884 sps
= GetSPS(pps
->seq_parameter_set_id
);
887 READ_BOOL_OR_RETURN(&pps
->entropy_coding_mode_flag
);
888 READ_BOOL_OR_RETURN(&pps
->bottom_field_pic_order_in_frame_present_flag
);
890 READ_UE_OR_RETURN(&pps
->num_slice_groups_minus1
);
891 if (pps
->num_slice_groups_minus1
> 1) {
892 DVLOG(1) << "Slice groups not supported";
893 return kUnsupportedStream
;
896 READ_UE_OR_RETURN(&pps
->num_ref_idx_l0_default_active_minus1
);
897 TRUE_OR_RETURN(pps
->num_ref_idx_l0_default_active_minus1
< 32);
899 READ_UE_OR_RETURN(&pps
->num_ref_idx_l1_default_active_minus1
);
900 TRUE_OR_RETURN(pps
->num_ref_idx_l1_default_active_minus1
< 32);
902 READ_BOOL_OR_RETURN(&pps
->weighted_pred_flag
);
903 READ_BITS_OR_RETURN(2, &pps
->weighted_bipred_idc
);
904 TRUE_OR_RETURN(pps
->weighted_bipred_idc
< 3);
906 READ_SE_OR_RETURN(&pps
->pic_init_qp_minus26
);
907 IN_RANGE_OR_RETURN(pps
->pic_init_qp_minus26
, -26, 25);
909 READ_SE_OR_RETURN(&pps
->pic_init_qs_minus26
);
910 IN_RANGE_OR_RETURN(pps
->pic_init_qs_minus26
, -26, 25);
912 READ_SE_OR_RETURN(&pps
->chroma_qp_index_offset
);
913 IN_RANGE_OR_RETURN(pps
->chroma_qp_index_offset
, -12, 12);
914 pps
->second_chroma_qp_index_offset
= pps
->chroma_qp_index_offset
;
916 READ_BOOL_OR_RETURN(&pps
->deblocking_filter_control_present_flag
);
917 READ_BOOL_OR_RETURN(&pps
->constrained_intra_pred_flag
);
918 READ_BOOL_OR_RETURN(&pps
->redundant_pic_cnt_present_flag
);
920 if (br_
.HasMoreRBSPData()) {
921 READ_BOOL_OR_RETURN(&pps
->transform_8x8_mode_flag
);
922 READ_BOOL_OR_RETURN(&pps
->pic_scaling_matrix_present_flag
);
924 if (pps
->pic_scaling_matrix_present_flag
) {
925 DVLOG(4) << "Picture scaling matrix present";
926 res
= ParsePPSScalingLists(*sps
, pps
.get());
931 READ_SE_OR_RETURN(&pps
->second_chroma_qp_index_offset
);
934 // If a PPS with the same id already exists, replace it.
935 *pps_id
= pps
->pic_parameter_set_id
;
936 delete active_PPSes_
[*pps_id
];
937 active_PPSes_
[*pps_id
] = pps
.release();
942 H264Parser::Result
H264Parser::ParseRefPicListModification(
943 int num_ref_idx_active_minus1
,
944 H264ModificationOfPicNum
* ref_list_mods
) {
945 H264ModificationOfPicNum
* pic_num_mod
;
947 if (num_ref_idx_active_minus1
>= 32)
948 return kInvalidStream
;
950 for (int i
= 0; i
< 32; ++i
) {
951 pic_num_mod
= &ref_list_mods
[i
];
952 READ_UE_OR_RETURN(&pic_num_mod
->modification_of_pic_nums_idc
);
953 TRUE_OR_RETURN(pic_num_mod
->modification_of_pic_nums_idc
< 4);
955 switch (pic_num_mod
->modification_of_pic_nums_idc
) {
958 READ_UE_OR_RETURN(&pic_num_mod
->abs_diff_pic_num_minus1
);
962 READ_UE_OR_RETURN(&pic_num_mod
->long_term_pic_num
);
966 // Per spec, list cannot be empty.
968 return kInvalidStream
;
972 return kInvalidStream
;
976 // If we got here, we didn't get loop end marker prematurely,
977 // so make sure it is there for our client.
978 int modification_of_pic_nums_idc
;
979 READ_UE_OR_RETURN(&modification_of_pic_nums_idc
);
980 TRUE_OR_RETURN(modification_of_pic_nums_idc
== 3);
985 H264Parser::Result
H264Parser::ParseRefPicListModifications(
986 H264SliceHeader
* shdr
) {
989 if (!shdr
->IsISlice() && !shdr
->IsSISlice()) {
990 READ_BOOL_OR_RETURN(&shdr
->ref_pic_list_modification_flag_l0
);
991 if (shdr
->ref_pic_list_modification_flag_l0
) {
992 res
= ParseRefPicListModification(shdr
->num_ref_idx_l0_active_minus1
,
993 shdr
->ref_list_l0_modifications
);
999 if (shdr
->IsBSlice()) {
1000 READ_BOOL_OR_RETURN(&shdr
->ref_pic_list_modification_flag_l1
);
1001 if (shdr
->ref_pic_list_modification_flag_l1
) {
1002 res
= ParseRefPicListModification(shdr
->num_ref_idx_l1_active_minus1
,
1003 shdr
->ref_list_l1_modifications
);
1012 H264Parser::Result
H264Parser::ParseWeightingFactors(
1013 int num_ref_idx_active_minus1
,
1014 int chroma_array_type
,
1015 int luma_log2_weight_denom
,
1016 int chroma_log2_weight_denom
,
1017 H264WeightingFactors
* w_facts
) {
1019 int def_luma_weight
= 1 << luma_log2_weight_denom
;
1020 int def_chroma_weight
= 1 << chroma_log2_weight_denom
;
1022 for (int i
= 0; i
< num_ref_idx_active_minus1
+ 1; ++i
) {
1023 READ_BOOL_OR_RETURN(&w_facts
->luma_weight_flag
);
1024 if (w_facts
->luma_weight_flag
) {
1025 READ_SE_OR_RETURN(&w_facts
->luma_weight
[i
]);
1026 IN_RANGE_OR_RETURN(w_facts
->luma_weight
[i
], -128, 127);
1028 READ_SE_OR_RETURN(&w_facts
->luma_offset
[i
]);
1029 IN_RANGE_OR_RETURN(w_facts
->luma_offset
[i
], -128, 127);
1031 w_facts
->luma_weight
[i
] = def_luma_weight
;
1032 w_facts
->luma_offset
[i
] = 0;
1035 if (chroma_array_type
!= 0) {
1036 READ_BOOL_OR_RETURN(&w_facts
->chroma_weight_flag
);
1037 if (w_facts
->chroma_weight_flag
) {
1038 for (int j
= 0; j
< 2; ++j
) {
1039 READ_SE_OR_RETURN(&w_facts
->chroma_weight
[i
][j
]);
1040 IN_RANGE_OR_RETURN(w_facts
->chroma_weight
[i
][j
], -128, 127);
1042 READ_SE_OR_RETURN(&w_facts
->chroma_offset
[i
][j
]);
1043 IN_RANGE_OR_RETURN(w_facts
->chroma_offset
[i
][j
], -128, 127);
1046 for (int j
= 0; j
< 2; ++j
) {
1047 w_facts
->chroma_weight
[i
][j
] = def_chroma_weight
;
1048 w_facts
->chroma_offset
[i
][j
] = 0;
1057 H264Parser::Result
H264Parser::ParsePredWeightTable(const H264SPS
& sps
,
1058 H264SliceHeader
* shdr
) {
1059 READ_UE_OR_RETURN(&shdr
->luma_log2_weight_denom
);
1060 TRUE_OR_RETURN(shdr
->luma_log2_weight_denom
< 8);
1062 if (sps
.chroma_array_type
!= 0)
1063 READ_UE_OR_RETURN(&shdr
->chroma_log2_weight_denom
);
1064 TRUE_OR_RETURN(shdr
->chroma_log2_weight_denom
< 8);
1066 Result res
= ParseWeightingFactors(shdr
->num_ref_idx_l0_active_minus1
,
1067 sps
.chroma_array_type
,
1068 shdr
->luma_log2_weight_denom
,
1069 shdr
->chroma_log2_weight_denom
,
1070 &shdr
->pred_weight_table_l0
);
1074 if (shdr
->IsBSlice()) {
1075 res
= ParseWeightingFactors(shdr
->num_ref_idx_l1_active_minus1
,
1076 sps
.chroma_array_type
,
1077 shdr
->luma_log2_weight_denom
,
1078 shdr
->chroma_log2_weight_denom
,
1079 &shdr
->pred_weight_table_l1
);
1087 H264Parser::Result
H264Parser::ParseDecRefPicMarking(H264SliceHeader
* shdr
) {
1088 size_t bits_left_at_start
= br_
.NumBitsLeft();
1090 if (shdr
->idr_pic_flag
) {
1091 READ_BOOL_OR_RETURN(&shdr
->no_output_of_prior_pics_flag
);
1092 READ_BOOL_OR_RETURN(&shdr
->long_term_reference_flag
);
1094 READ_BOOL_OR_RETURN(&shdr
->adaptive_ref_pic_marking_mode_flag
);
1096 H264DecRefPicMarking
* marking
;
1097 if (shdr
->adaptive_ref_pic_marking_mode_flag
) {
1099 for (i
= 0; i
< arraysize(shdr
->ref_pic_marking
); ++i
) {
1100 marking
= &shdr
->ref_pic_marking
[i
];
1102 READ_UE_OR_RETURN(&marking
->memory_mgmnt_control_operation
);
1103 if (marking
->memory_mgmnt_control_operation
== 0)
1106 if (marking
->memory_mgmnt_control_operation
== 1 ||
1107 marking
->memory_mgmnt_control_operation
== 3)
1108 READ_UE_OR_RETURN(&marking
->difference_of_pic_nums_minus1
);
1110 if (marking
->memory_mgmnt_control_operation
== 2)
1111 READ_UE_OR_RETURN(&marking
->long_term_pic_num
);
1113 if (marking
->memory_mgmnt_control_operation
== 3 ||
1114 marking
->memory_mgmnt_control_operation
== 6)
1115 READ_UE_OR_RETURN(&marking
->long_term_frame_idx
);
1117 if (marking
->memory_mgmnt_control_operation
== 4)
1118 READ_UE_OR_RETURN(&marking
->max_long_term_frame_idx_plus1
);
1120 if (marking
->memory_mgmnt_control_operation
> 6)
1121 return kInvalidStream
;
1124 if (i
== arraysize(shdr
->ref_pic_marking
)) {
1125 DVLOG(1) << "Ran out of dec ref pic marking fields";
1126 return kUnsupportedStream
;
1131 shdr
->dec_ref_pic_marking_bit_size
= bits_left_at_start
- br_
.NumBitsLeft();
1135 H264Parser::Result
H264Parser::ParseSliceHeader(const H264NALU
& nalu
,
1136 H264SliceHeader
* shdr
) {
1142 memset(shdr
, 0, sizeof(*shdr
));
1144 shdr
->idr_pic_flag
= (nalu
.nal_unit_type
== 5);
1145 shdr
->nal_ref_idc
= nalu
.nal_ref_idc
;
1146 shdr
->nalu_data
= nalu
.data
;
1147 shdr
->nalu_size
= nalu
.size
;
1149 READ_UE_OR_RETURN(&shdr
->first_mb_in_slice
);
1150 READ_UE_OR_RETURN(&shdr
->slice_type
);
1151 TRUE_OR_RETURN(shdr
->slice_type
< 10);
1153 READ_UE_OR_RETURN(&shdr
->pic_parameter_set_id
);
1155 pps
= GetPPS(shdr
->pic_parameter_set_id
);
1156 TRUE_OR_RETURN(pps
);
1158 sps
= GetSPS(pps
->seq_parameter_set_id
);
1159 TRUE_OR_RETURN(sps
);
1161 if (sps
->separate_colour_plane_flag
) {
1162 DVLOG(1) << "Interlaced streams not supported";
1163 return kUnsupportedStream
;
1166 READ_BITS_OR_RETURN(sps
->log2_max_frame_num_minus4
+ 4, &shdr
->frame_num
);
1167 if (!sps
->frame_mbs_only_flag
) {
1168 READ_BOOL_OR_RETURN(&shdr
->field_pic_flag
);
1169 if (shdr
->field_pic_flag
) {
1170 DVLOG(1) << "Interlaced streams not supported";
1171 return kUnsupportedStream
;
1175 if (shdr
->idr_pic_flag
)
1176 READ_UE_OR_RETURN(&shdr
->idr_pic_id
);
1178 size_t bits_left_at_pic_order_cnt_start
= br_
.NumBitsLeft();
1179 if (sps
->pic_order_cnt_type
== 0) {
1180 READ_BITS_OR_RETURN(sps
->log2_max_pic_order_cnt_lsb_minus4
+ 4,
1181 &shdr
->pic_order_cnt_lsb
);
1182 if (pps
->bottom_field_pic_order_in_frame_present_flag
&&
1183 !shdr
->field_pic_flag
)
1184 READ_SE_OR_RETURN(&shdr
->delta_pic_order_cnt_bottom
);
1187 if (sps
->pic_order_cnt_type
== 1 && !sps
->delta_pic_order_always_zero_flag
) {
1188 READ_SE_OR_RETURN(&shdr
->delta_pic_order_cnt0
);
1189 if (pps
->bottom_field_pic_order_in_frame_present_flag
&&
1190 !shdr
->field_pic_flag
)
1191 READ_SE_OR_RETURN(&shdr
->delta_pic_order_cnt1
);
1194 shdr
->pic_order_cnt_bit_size
=
1195 bits_left_at_pic_order_cnt_start
- br_
.NumBitsLeft();
1197 if (pps
->redundant_pic_cnt_present_flag
) {
1198 READ_UE_OR_RETURN(&shdr
->redundant_pic_cnt
);
1199 TRUE_OR_RETURN(shdr
->redundant_pic_cnt
< 128);
1202 if (shdr
->IsBSlice())
1203 READ_BOOL_OR_RETURN(&shdr
->direct_spatial_mv_pred_flag
);
1205 if (shdr
->IsPSlice() || shdr
->IsSPSlice() || shdr
->IsBSlice()) {
1206 READ_BOOL_OR_RETURN(&shdr
->num_ref_idx_active_override_flag
);
1207 if (shdr
->num_ref_idx_active_override_flag
) {
1208 READ_UE_OR_RETURN(&shdr
->num_ref_idx_l0_active_minus1
);
1209 if (shdr
->IsBSlice())
1210 READ_UE_OR_RETURN(&shdr
->num_ref_idx_l1_active_minus1
);
1212 shdr
->num_ref_idx_l0_active_minus1
=
1213 pps
->num_ref_idx_l0_default_active_minus1
;
1214 if (shdr
->IsBSlice()) {
1215 shdr
->num_ref_idx_l1_active_minus1
=
1216 pps
->num_ref_idx_l1_default_active_minus1
;
1220 if (shdr
->field_pic_flag
) {
1221 TRUE_OR_RETURN(shdr
->num_ref_idx_l0_active_minus1
< 32);
1222 TRUE_OR_RETURN(shdr
->num_ref_idx_l1_active_minus1
< 32);
1224 TRUE_OR_RETURN(shdr
->num_ref_idx_l0_active_minus1
< 16);
1225 TRUE_OR_RETURN(shdr
->num_ref_idx_l1_active_minus1
< 16);
1228 if (nalu
.nal_unit_type
== H264NALU::kCodedSliceExtension
) {
1229 return kUnsupportedStream
;
1231 res
= ParseRefPicListModifications(shdr
);
1236 if ((pps
->weighted_pred_flag
&& (shdr
->IsPSlice() || shdr
->IsSPSlice())) ||
1237 (pps
->weighted_bipred_idc
== 1 && shdr
->IsBSlice())) {
1238 res
= ParsePredWeightTable(*sps
, shdr
);
1243 if (nalu
.nal_ref_idc
!= 0) {
1244 res
= ParseDecRefPicMarking(shdr
);
1249 if (pps
->entropy_coding_mode_flag
&& !shdr
->IsISlice() &&
1250 !shdr
->IsSISlice()) {
1251 READ_UE_OR_RETURN(&shdr
->cabac_init_idc
);
1252 TRUE_OR_RETURN(shdr
->cabac_init_idc
< 3);
1255 READ_SE_OR_RETURN(&shdr
->slice_qp_delta
);
1257 if (shdr
->IsSPSlice() || shdr
->IsSISlice()) {
1258 if (shdr
->IsSPSlice())
1259 READ_BOOL_OR_RETURN(&shdr
->sp_for_switch_flag
);
1260 READ_SE_OR_RETURN(&shdr
->slice_qs_delta
);
1263 if (pps
->deblocking_filter_control_present_flag
) {
1264 READ_UE_OR_RETURN(&shdr
->disable_deblocking_filter_idc
);
1265 TRUE_OR_RETURN(shdr
->disable_deblocking_filter_idc
< 3);
1267 if (shdr
->disable_deblocking_filter_idc
!= 1) {
1268 READ_SE_OR_RETURN(&shdr
->slice_alpha_c0_offset_div2
);
1269 IN_RANGE_OR_RETURN(shdr
->slice_alpha_c0_offset_div2
, -6, 6);
1271 READ_SE_OR_RETURN(&shdr
->slice_beta_offset_div2
);
1272 IN_RANGE_OR_RETURN(shdr
->slice_beta_offset_div2
, -6, 6);
1276 if (pps
->num_slice_groups_minus1
> 0) {
1277 DVLOG(1) << "Slice groups not supported";
1278 return kUnsupportedStream
;
1281 size_t epb
= br_
.NumEmulationPreventionBytesRead();
1282 shdr
->header_bit_size
= (shdr
->nalu_size
- epb
) * 8 - br_
.NumBitsLeft();
1287 H264Parser::Result
H264Parser::ParseSEI(H264SEIMessage
* sei_msg
) {
1290 memset(sei_msg
, 0, sizeof(*sei_msg
));
1292 READ_BITS_OR_RETURN(8, &byte
);
1293 while (byte
== 0xff) {
1294 sei_msg
->type
+= 255;
1295 READ_BITS_OR_RETURN(8, &byte
);
1297 sei_msg
->type
+= byte
;
1299 READ_BITS_OR_RETURN(8, &byte
);
1300 while (byte
== 0xff) {
1301 sei_msg
->payload_size
+= 255;
1302 READ_BITS_OR_RETURN(8, &byte
);
1304 sei_msg
->payload_size
+= byte
;
1306 DVLOG(4) << "Found SEI message type: " << sei_msg
->type
1307 << " payload size: " << sei_msg
->payload_size
;
1309 switch (sei_msg
->type
) {
1310 case H264SEIMessage::kSEIRecoveryPoint
:
1311 READ_UE_OR_RETURN(&sei_msg
->recovery_point
.recovery_frame_cnt
);
1312 READ_BOOL_OR_RETURN(&sei_msg
->recovery_point
.exact_match_flag
);
1313 READ_BOOL_OR_RETURN(&sei_msg
->recovery_point
.broken_link_flag
);
1314 READ_BITS_OR_RETURN(2, &sei_msg
->recovery_point
.changing_slice_group_idc
);
1318 DVLOG(4) << "Unsupported SEI message";
1325 } // namespace media