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_
,
217 &nalu_start_off
, &annexb_start_code_size
)) {
218 DVLOG(4) << "Could not find start code, end of stream?";
222 // Move the stream to the beginning of the NALU (pointing at the start code).
223 stream_
+= nalu_start_off
;
224 bytes_left_
-= nalu_start_off
;
226 const uint8
* nalu_data
= stream_
+ annexb_start_code_size
;
227 off_t max_nalu_data_size
= bytes_left_
- annexb_start_code_size
;
228 if (max_nalu_data_size
<= 0) {
229 DVLOG(3) << "End of stream";
233 // Find the start code of next NALU;
234 // if successful, |nalu_size_without_start_code| is the number of bytes from
235 // after previous start code to before this one;
236 // if next start code is not found, it is still a valid NALU since there
237 // are some bytes left after the first start code: all the remaining bytes
238 // belong to the current NALU.
239 off_t next_start_code_size
= 0;
240 off_t nalu_size_without_start_code
= 0;
241 if (!FindStartCodeInClearRanges(nalu_data
, max_nalu_data_size
,
243 &nalu_size_without_start_code
,
244 &next_start_code_size
)) {
245 nalu_size_without_start_code
= max_nalu_data_size
;
247 *nalu_size
= nalu_size_without_start_code
+ annexb_start_code_size
;
248 *start_code_size
= annexb_start_code_size
;
252 bool H264Parser::FindStartCodeInClearRanges(
255 const Ranges
<const uint8
*>& encrypted_ranges
,
257 off_t
* start_code_size
) {
258 if (encrypted_ranges
.size() == 0)
259 return FindStartCode(data
, data_size
, offset
, start_code_size
);
261 DCHECK_GE(data_size
, 0);
262 const uint8
* start
= data
;
264 off_t bytes_left
= data_size
- (start
- data
);
266 if (!FindStartCode(start
, bytes_left
, offset
, start_code_size
))
269 // Construct a Ranges object that represents the region occupied
270 // by the start code and the 1 byte needed to read the NAL unit type.
271 const uint8
* start_code
= start
+ *offset
;
272 const uint8
* start_code_end
= start_code
+ *start_code_size
;
273 Ranges
<const uint8
*> start_code_range
;
274 start_code_range
.Add(start_code
, start_code_end
+ 1);
276 if (encrypted_ranges
.IntersectionWith(start_code_range
).size() > 0) {
277 // The start code is inside an encrypted section so we need to scan
278 // for another start code.
279 *start_code_size
= 0;
280 start
+= std::min(*offset
+ 1, bytes_left
);
282 } while (*start_code_size
== 0);
284 // Update |*offset| to include the data we skipped over.
285 *offset
+= start
- data
;
289 H264Parser::Result
H264Parser::ReadUE(int* val
) {
294 // Count the number of contiguous zero bits.
296 READ_BITS_OR_RETURN(1, &bit
);
301 return kInvalidStream
;
303 // Calculate exp-Golomb code value of size num_bits.
304 *val
= (1 << num_bits
) - 1;
307 READ_BITS_OR_RETURN(num_bits
, &rest
);
314 H264Parser::Result
H264Parser::ReadSE(int* val
) {
318 // See Chapter 9 in the spec.
331 H264Parser::Result
H264Parser::AdvanceToNextNALU(H264NALU
* nalu
) {
332 off_t start_code_size
;
333 off_t nalu_size_with_start_code
;
334 if (!LocateNALU(&nalu_size_with_start_code
, &start_code_size
)) {
335 DVLOG(4) << "Could not find next NALU, bytes left in stream: "
340 nalu
->data
= stream_
+ start_code_size
;
341 nalu
->size
= nalu_size_with_start_code
- start_code_size
;
342 DVLOG(4) << "NALU found: size=" << nalu_size_with_start_code
;
344 // Initialize bit reader at the start of found NALU.
345 if (!br_
.Initialize(nalu
->data
, nalu
->size
))
348 // Move parser state to after this NALU, so next time AdvanceToNextNALU
349 // is called, we will effectively be skipping it;
350 // other parsing functions will use the position saved
351 // in bit reader for parsing, so we don't have to remember it here.
352 stream_
+= nalu_size_with_start_code
;
353 bytes_left_
-= nalu_size_with_start_code
;
355 // Read NALU header, skip the forbidden_zero_bit, but check for it.
357 READ_BITS_OR_RETURN(1, &data
);
358 TRUE_OR_RETURN(data
== 0);
360 READ_BITS_OR_RETURN(2, &nalu
->nal_ref_idc
);
361 READ_BITS_OR_RETURN(5, &nalu
->nal_unit_type
);
363 DVLOG(4) << "NALU type: " << static_cast<int>(nalu
->nal_unit_type
)
364 << " at: " << reinterpret_cast<const void*>(nalu
->data
)
365 << " size: " << nalu
->size
366 << " ref: " << static_cast<int>(nalu
->nal_ref_idc
);
371 // Default scaling lists (per spec).
372 static const int kDefault4x4Intra
[kH264ScalingList4x4Length
] = {
373 6, 13, 13, 20, 20, 20, 28, 28, 28, 28, 32, 32, 32, 37, 37, 42, };
375 static const int kDefault4x4Inter
[kH264ScalingList4x4Length
] = {
376 10, 14, 14, 20, 20, 20, 24, 24, 24, 24, 27, 27, 27, 30, 30, 34, };
378 static const int kDefault8x8Intra
[kH264ScalingList8x8Length
] = {
379 6, 10, 10, 13, 11, 13, 16, 16, 16, 16, 18, 18, 18, 18, 18, 23,
380 23, 23, 23, 23, 23, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27,
381 27, 27, 27, 27, 29, 29, 29, 29, 29, 29, 29, 31, 31, 31, 31, 31,
382 31, 33, 33, 33, 33, 33, 36, 36, 36, 36, 38, 38, 38, 40, 40, 42, };
384 static const int kDefault8x8Inter
[kH264ScalingList8x8Length
] = {
385 9, 13, 13, 15, 13, 15, 17, 17, 17, 17, 19, 19, 19, 19, 19, 21,
386 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 24, 24, 24, 24,
387 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27, 27,
388 27, 28, 28, 28, 28, 28, 30, 30, 30, 30, 32, 32, 32, 33, 33, 35, };
390 static inline void DefaultScalingList4x4(
392 int scaling_list4x4
[][kH264ScalingList4x4Length
]) {
396 memcpy(scaling_list4x4
[i
], kDefault4x4Intra
, sizeof(kDefault4x4Intra
));
398 memcpy(scaling_list4x4
[i
], kDefault4x4Inter
, sizeof(kDefault4x4Inter
));
401 static inline void DefaultScalingList8x8(
403 int scaling_list8x8
[][kH264ScalingList8x8Length
]) {
407 memcpy(scaling_list8x8
[i
], kDefault8x8Intra
, sizeof(kDefault8x8Intra
));
409 memcpy(scaling_list8x8
[i
], kDefault8x8Inter
, sizeof(kDefault8x8Inter
));
412 static void FallbackScalingList4x4(
414 const int default_scaling_list_intra
[],
415 const int default_scaling_list_inter
[],
416 int scaling_list4x4
[][kH264ScalingList4x4Length
]) {
417 static const int kScalingList4x4ByteSize
=
418 sizeof(scaling_list4x4
[0][0]) * kH264ScalingList4x4Length
;
422 memcpy(scaling_list4x4
[i
], default_scaling_list_intra
,
423 kScalingList4x4ByteSize
);
427 memcpy(scaling_list4x4
[i
], scaling_list4x4
[0], kScalingList4x4ByteSize
);
431 memcpy(scaling_list4x4
[i
], scaling_list4x4
[1], kScalingList4x4ByteSize
);
435 memcpy(scaling_list4x4
[i
], default_scaling_list_inter
,
436 kScalingList4x4ByteSize
);
440 memcpy(scaling_list4x4
[i
], scaling_list4x4
[3], kScalingList4x4ByteSize
);
444 memcpy(scaling_list4x4
[i
], scaling_list4x4
[4], kScalingList4x4ByteSize
);
453 static void FallbackScalingList8x8(
455 const int default_scaling_list_intra
[],
456 const int default_scaling_list_inter
[],
457 int scaling_list8x8
[][kH264ScalingList8x8Length
]) {
458 static const int kScalingList8x8ByteSize
=
459 sizeof(scaling_list8x8
[0][0]) * kH264ScalingList8x8Length
;
463 memcpy(scaling_list8x8
[i
], default_scaling_list_intra
,
464 kScalingList8x8ByteSize
);
468 memcpy(scaling_list8x8
[i
], default_scaling_list_inter
,
469 kScalingList8x8ByteSize
);
473 memcpy(scaling_list8x8
[i
], scaling_list8x8
[0], kScalingList8x8ByteSize
);
477 memcpy(scaling_list8x8
[i
], scaling_list8x8
[1], kScalingList8x8ByteSize
);
481 memcpy(scaling_list8x8
[i
], scaling_list8x8
[2], kScalingList8x8ByteSize
);
485 memcpy(scaling_list8x8
[i
], scaling_list8x8
[3], kScalingList8x8ByteSize
);
494 H264Parser::Result
H264Parser::ParseScalingList(int size
,
497 // See chapter 7.3.2.1.1.1.
502 *use_default
= false;
504 for (int j
= 0; j
< size
; ++j
) {
505 if (next_scale
!= 0) {
506 READ_SE_OR_RETURN(&delta_scale
);
507 IN_RANGE_OR_RETURN(delta_scale
, -128, 127);
508 next_scale
= (last_scale
+ delta_scale
+ 256) & 0xff;
510 if (j
== 0 && next_scale
== 0) {
516 scaling_list
[j
] = (next_scale
== 0) ? last_scale
: next_scale
;
517 last_scale
= scaling_list
[j
];
523 H264Parser::Result
H264Parser::ParseSPSScalingLists(H264SPS
* sps
) {
525 bool seq_scaling_list_present_flag
;
529 // Parse scaling_list4x4.
530 for (int i
= 0; i
< 6; ++i
) {
531 READ_BOOL_OR_RETURN(&seq_scaling_list_present_flag
);
533 if (seq_scaling_list_present_flag
) {
534 res
= ParseScalingList(arraysize(sps
->scaling_list4x4
[i
]),
535 sps
->scaling_list4x4
[i
],
541 DefaultScalingList4x4(i
, sps
->scaling_list4x4
);
544 FallbackScalingList4x4(
545 i
, kDefault4x4Intra
, kDefault4x4Inter
, sps
->scaling_list4x4
);
549 // Parse scaling_list8x8.
550 for (int i
= 0; i
< ((sps
->chroma_format_idc
!= 3) ? 2 : 6); ++i
) {
551 READ_BOOL_OR_RETURN(&seq_scaling_list_present_flag
);
553 if (seq_scaling_list_present_flag
) {
554 res
= ParseScalingList(arraysize(sps
->scaling_list8x8
[i
]),
555 sps
->scaling_list8x8
[i
],
561 DefaultScalingList8x8(i
, sps
->scaling_list8x8
);
564 FallbackScalingList8x8(
565 i
, kDefault8x8Intra
, kDefault8x8Inter
, sps
->scaling_list8x8
);
572 H264Parser::Result
H264Parser::ParsePPSScalingLists(const H264SPS
& sps
,
575 bool pic_scaling_list_present_flag
;
579 for (int i
= 0; i
< 6; ++i
) {
580 READ_BOOL_OR_RETURN(&pic_scaling_list_present_flag
);
582 if (pic_scaling_list_present_flag
) {
583 res
= ParseScalingList(arraysize(pps
->scaling_list4x4
[i
]),
584 pps
->scaling_list4x4
[i
],
590 DefaultScalingList4x4(i
, pps
->scaling_list4x4
);
593 if (sps
.seq_scaling_matrix_present_flag
) {
594 // Table 7-2 fallback rule A in spec.
595 FallbackScalingList4x4(
596 i
, kDefault4x4Intra
, kDefault4x4Inter
, pps
->scaling_list4x4
);
598 // Table 7-2 fallback rule B in spec.
599 FallbackScalingList4x4(i
,
600 sps
.scaling_list4x4
[0],
601 sps
.scaling_list4x4
[3],
602 pps
->scaling_list4x4
);
607 if (pps
->transform_8x8_mode_flag
) {
608 for (int i
= 0; i
< ((sps
.chroma_format_idc
!= 3) ? 2 : 6); ++i
) {
609 READ_BOOL_OR_RETURN(&pic_scaling_list_present_flag
);
611 if (pic_scaling_list_present_flag
) {
612 res
= ParseScalingList(arraysize(pps
->scaling_list8x8
[i
]),
613 pps
->scaling_list8x8
[i
],
619 DefaultScalingList8x8(i
, pps
->scaling_list8x8
);
622 if (sps
.seq_scaling_matrix_present_flag
) {
623 // Table 7-2 fallback rule A in spec.
624 FallbackScalingList8x8(
625 i
, kDefault8x8Intra
, kDefault8x8Inter
, pps
->scaling_list8x8
);
627 // Table 7-2 fallback rule B in spec.
628 FallbackScalingList8x8(i
,
629 sps
.scaling_list8x8
[0],
630 sps
.scaling_list8x8
[1],
631 pps
->scaling_list8x8
);
639 H264Parser::Result
H264Parser::ParseAndIgnoreHRDParameters(
640 bool* hrd_parameters_present
) {
642 READ_BOOL_OR_RETURN(&data
); // {nal,vcl}_hrd_parameters_present_flag
646 *hrd_parameters_present
= true;
649 READ_UE_OR_RETURN(&cpb_cnt_minus1
);
650 IN_RANGE_OR_RETURN(cpb_cnt_minus1
, 0, 31);
651 READ_BITS_OR_RETURN(8, &data
); // bit_rate_scale, cpb_size_scale
652 for (int i
= 0; i
<= cpb_cnt_minus1
; ++i
) {
653 READ_UE_OR_RETURN(&data
); // bit_rate_value_minus1[i]
654 READ_UE_OR_RETURN(&data
); // cpb_size_value_minus1[i]
655 READ_BOOL_OR_RETURN(&data
); // cbr_flag
657 READ_BITS_OR_RETURN(20, &data
); // cpb/dpb delays, etc.
662 H264Parser::Result
H264Parser::ParseVUIParameters(H264SPS
* sps
) {
663 bool aspect_ratio_info_present_flag
;
664 READ_BOOL_OR_RETURN(&aspect_ratio_info_present_flag
);
665 if (aspect_ratio_info_present_flag
) {
666 int aspect_ratio_idc
;
667 READ_BITS_OR_RETURN(8, &aspect_ratio_idc
);
668 if (aspect_ratio_idc
== H264SPS::kExtendedSar
) {
669 READ_BITS_OR_RETURN(16, &sps
->sar_width
);
670 READ_BITS_OR_RETURN(16, &sps
->sar_height
);
672 const int max_aspect_ratio_idc
= arraysize(kTableSarWidth
) - 1;
673 IN_RANGE_OR_RETURN(aspect_ratio_idc
, 0, max_aspect_ratio_idc
);
674 sps
->sar_width
= kTableSarWidth
[aspect_ratio_idc
];
675 sps
->sar_height
= kTableSarHeight
[aspect_ratio_idc
];
680 // Read and ignore overscan and video signal type info.
681 READ_BOOL_OR_RETURN(&data
); // overscan_info_present_flag
683 READ_BOOL_OR_RETURN(&data
); // overscan_appropriate_flag
685 READ_BOOL_OR_RETURN(&data
); // video_signal_type_present_flag
687 READ_BITS_OR_RETURN(3, &data
); // video_format
688 READ_BOOL_OR_RETURN(&data
); // video_full_range_flag
689 READ_BOOL_OR_RETURN(&data
); // colour_description_present_flag
691 READ_BITS_OR_RETURN(24, &data
); // color description syntax elements
694 READ_BOOL_OR_RETURN(&data
); // chroma_loc_info_present_flag
696 READ_UE_OR_RETURN(&data
); // chroma_sample_loc_type_top_field
697 READ_UE_OR_RETURN(&data
); // chroma_sample_loc_type_bottom_field
700 // Read and ignore timing info.
701 READ_BOOL_OR_RETURN(&data
); // timing_info_present_flag
703 READ_BITS_OR_RETURN(16, &data
); // num_units_in_tick
704 READ_BITS_OR_RETURN(16, &data
); // num_units_in_tick
705 READ_BITS_OR_RETURN(16, &data
); // time_scale
706 READ_BITS_OR_RETURN(16, &data
); // time_scale
707 READ_BOOL_OR_RETURN(&data
); // fixed_frame_rate_flag
710 // Read and ignore NAL HRD parameters, if present.
711 bool hrd_parameters_present
= false;
712 Result res
= ParseAndIgnoreHRDParameters(&hrd_parameters_present
);
716 // Read and ignore VCL HRD parameters, if present.
717 res
= ParseAndIgnoreHRDParameters(&hrd_parameters_present
);
721 if (hrd_parameters_present
) // One of NAL or VCL params present is enough.
722 READ_BOOL_OR_RETURN(&data
); // low_delay_hrd_flag
724 READ_BOOL_OR_RETURN(&data
); // pic_struct_present_flag
725 READ_BOOL_OR_RETURN(&sps
->bitstream_restriction_flag
);
726 if (sps
->bitstream_restriction_flag
) {
727 READ_BOOL_OR_RETURN(&data
); // motion_vectors_over_pic_boundaries_flag
728 READ_UE_OR_RETURN(&data
); // max_bytes_per_pic_denom
729 READ_UE_OR_RETURN(&data
); // max_bits_per_mb_denom
730 READ_UE_OR_RETURN(&data
); // log2_max_mv_length_horizontal
731 READ_UE_OR_RETURN(&data
); // log2_max_mv_length_vertical
732 READ_UE_OR_RETURN(&sps
->max_num_reorder_frames
);
733 READ_UE_OR_RETURN(&sps
->max_dec_frame_buffering
);
734 TRUE_OR_RETURN(sps
->max_dec_frame_buffering
>= sps
->max_num_ref_frames
);
736 sps
->max_num_reorder_frames
, 0, sps
->max_dec_frame_buffering
);
742 static void FillDefaultSeqScalingLists(H264SPS
* sps
) {
743 for (int i
= 0; i
< 6; ++i
)
744 for (int j
= 0; j
< kH264ScalingList4x4Length
; ++j
)
745 sps
->scaling_list4x4
[i
][j
] = 16;
747 for (int i
= 0; i
< 6; ++i
)
748 for (int j
= 0; j
< kH264ScalingList8x8Length
; ++j
)
749 sps
->scaling_list8x8
[i
][j
] = 16;
752 H264Parser::Result
H264Parser::ParseSPS(int* sps_id
) {
759 scoped_ptr
<H264SPS
> sps(new H264SPS());
761 READ_BITS_OR_RETURN(8, &sps
->profile_idc
);
762 READ_BOOL_OR_RETURN(&sps
->constraint_set0_flag
);
763 READ_BOOL_OR_RETURN(&sps
->constraint_set1_flag
);
764 READ_BOOL_OR_RETURN(&sps
->constraint_set2_flag
);
765 READ_BOOL_OR_RETURN(&sps
->constraint_set3_flag
);
766 READ_BOOL_OR_RETURN(&sps
->constraint_set4_flag
);
767 READ_BOOL_OR_RETURN(&sps
->constraint_set5_flag
);
768 READ_BITS_OR_RETURN(2, &data
); // reserved_zero_2bits
769 READ_BITS_OR_RETURN(8, &sps
->level_idc
);
770 READ_UE_OR_RETURN(&sps
->seq_parameter_set_id
);
771 TRUE_OR_RETURN(sps
->seq_parameter_set_id
< 32);
773 if (sps
->profile_idc
== 100 || sps
->profile_idc
== 110 ||
774 sps
->profile_idc
== 122 || sps
->profile_idc
== 244 ||
775 sps
->profile_idc
== 44 || sps
->profile_idc
== 83 ||
776 sps
->profile_idc
== 86 || sps
->profile_idc
== 118 ||
777 sps
->profile_idc
== 128) {
778 READ_UE_OR_RETURN(&sps
->chroma_format_idc
);
779 TRUE_OR_RETURN(sps
->chroma_format_idc
< 4);
781 if (sps
->chroma_format_idc
== 3)
782 READ_BOOL_OR_RETURN(&sps
->separate_colour_plane_flag
);
784 READ_UE_OR_RETURN(&sps
->bit_depth_luma_minus8
);
785 TRUE_OR_RETURN(sps
->bit_depth_luma_minus8
< 7);
787 READ_UE_OR_RETURN(&sps
->bit_depth_chroma_minus8
);
788 TRUE_OR_RETURN(sps
->bit_depth_chroma_minus8
< 7);
790 READ_BOOL_OR_RETURN(&sps
->qpprime_y_zero_transform_bypass_flag
);
791 READ_BOOL_OR_RETURN(&sps
->seq_scaling_matrix_present_flag
);
793 if (sps
->seq_scaling_matrix_present_flag
) {
794 DVLOG(4) << "Scaling matrix present";
795 res
= ParseSPSScalingLists(sps
.get());
799 FillDefaultSeqScalingLists(sps
.get());
802 sps
->chroma_format_idc
= 1;
803 FillDefaultSeqScalingLists(sps
.get());
806 if (sps
->separate_colour_plane_flag
)
807 sps
->chroma_array_type
= 0;
809 sps
->chroma_array_type
= sps
->chroma_format_idc
;
811 READ_UE_OR_RETURN(&sps
->log2_max_frame_num_minus4
);
812 TRUE_OR_RETURN(sps
->log2_max_frame_num_minus4
< 13);
814 READ_UE_OR_RETURN(&sps
->pic_order_cnt_type
);
815 TRUE_OR_RETURN(sps
->pic_order_cnt_type
< 3);
817 sps
->expected_delta_per_pic_order_cnt_cycle
= 0;
818 if (sps
->pic_order_cnt_type
== 0) {
819 READ_UE_OR_RETURN(&sps
->log2_max_pic_order_cnt_lsb_minus4
);
820 TRUE_OR_RETURN(sps
->log2_max_pic_order_cnt_lsb_minus4
< 13);
821 } else if (sps
->pic_order_cnt_type
== 1) {
822 READ_BOOL_OR_RETURN(&sps
->delta_pic_order_always_zero_flag
);
823 READ_SE_OR_RETURN(&sps
->offset_for_non_ref_pic
);
824 READ_SE_OR_RETURN(&sps
->offset_for_top_to_bottom_field
);
825 READ_UE_OR_RETURN(&sps
->num_ref_frames_in_pic_order_cnt_cycle
);
826 TRUE_OR_RETURN(sps
->num_ref_frames_in_pic_order_cnt_cycle
< 255);
828 for (int i
= 0; i
< sps
->num_ref_frames_in_pic_order_cnt_cycle
; ++i
) {
829 READ_SE_OR_RETURN(&sps
->offset_for_ref_frame
[i
]);
830 sps
->expected_delta_per_pic_order_cnt_cycle
+=
831 sps
->offset_for_ref_frame
[i
];
835 READ_UE_OR_RETURN(&sps
->max_num_ref_frames
);
836 READ_BOOL_OR_RETURN(&sps
->gaps_in_frame_num_value_allowed_flag
);
838 if (sps
->gaps_in_frame_num_value_allowed_flag
)
839 return kUnsupportedStream
;
841 READ_UE_OR_RETURN(&sps
->pic_width_in_mbs_minus1
);
842 READ_UE_OR_RETURN(&sps
->pic_height_in_map_units_minus1
);
844 READ_BOOL_OR_RETURN(&sps
->frame_mbs_only_flag
);
845 if (!sps
->frame_mbs_only_flag
)
846 READ_BOOL_OR_RETURN(&sps
->mb_adaptive_frame_field_flag
);
848 READ_BOOL_OR_RETURN(&sps
->direct_8x8_inference_flag
);
850 READ_BOOL_OR_RETURN(&sps
->frame_cropping_flag
);
851 if (sps
->frame_cropping_flag
) {
852 READ_UE_OR_RETURN(&sps
->frame_crop_left_offset
);
853 READ_UE_OR_RETURN(&sps
->frame_crop_right_offset
);
854 READ_UE_OR_RETURN(&sps
->frame_crop_top_offset
);
855 READ_UE_OR_RETURN(&sps
->frame_crop_bottom_offset
);
858 READ_BOOL_OR_RETURN(&sps
->vui_parameters_present_flag
);
859 if (sps
->vui_parameters_present_flag
) {
860 DVLOG(4) << "VUI parameters present";
861 res
= ParseVUIParameters(sps
.get());
866 // If an SPS with the same id already exists, replace it.
867 *sps_id
= sps
->seq_parameter_set_id
;
868 delete active_SPSes_
[*sps_id
];
869 active_SPSes_
[*sps_id
] = sps
.release();
874 H264Parser::Result
H264Parser::ParsePPS(int* pps_id
) {
881 scoped_ptr
<H264PPS
> pps(new H264PPS());
883 READ_UE_OR_RETURN(&pps
->pic_parameter_set_id
);
884 READ_UE_OR_RETURN(&pps
->seq_parameter_set_id
);
885 TRUE_OR_RETURN(pps
->seq_parameter_set_id
< 32);
887 sps
= GetSPS(pps
->seq_parameter_set_id
);
890 READ_BOOL_OR_RETURN(&pps
->entropy_coding_mode_flag
);
891 READ_BOOL_OR_RETURN(&pps
->bottom_field_pic_order_in_frame_present_flag
);
893 READ_UE_OR_RETURN(&pps
->num_slice_groups_minus1
);
894 if (pps
->num_slice_groups_minus1
> 1) {
895 DVLOG(1) << "Slice groups not supported";
896 return kUnsupportedStream
;
899 READ_UE_OR_RETURN(&pps
->num_ref_idx_l0_default_active_minus1
);
900 TRUE_OR_RETURN(pps
->num_ref_idx_l0_default_active_minus1
< 32);
902 READ_UE_OR_RETURN(&pps
->num_ref_idx_l1_default_active_minus1
);
903 TRUE_OR_RETURN(pps
->num_ref_idx_l1_default_active_minus1
< 32);
905 READ_BOOL_OR_RETURN(&pps
->weighted_pred_flag
);
906 READ_BITS_OR_RETURN(2, &pps
->weighted_bipred_idc
);
907 TRUE_OR_RETURN(pps
->weighted_bipred_idc
< 3);
909 READ_SE_OR_RETURN(&pps
->pic_init_qp_minus26
);
910 IN_RANGE_OR_RETURN(pps
->pic_init_qp_minus26
, -26, 25);
912 READ_SE_OR_RETURN(&pps
->pic_init_qs_minus26
);
913 IN_RANGE_OR_RETURN(pps
->pic_init_qs_minus26
, -26, 25);
915 READ_SE_OR_RETURN(&pps
->chroma_qp_index_offset
);
916 IN_RANGE_OR_RETURN(pps
->chroma_qp_index_offset
, -12, 12);
917 pps
->second_chroma_qp_index_offset
= pps
->chroma_qp_index_offset
;
919 READ_BOOL_OR_RETURN(&pps
->deblocking_filter_control_present_flag
);
920 READ_BOOL_OR_RETURN(&pps
->constrained_intra_pred_flag
);
921 READ_BOOL_OR_RETURN(&pps
->redundant_pic_cnt_present_flag
);
923 if (br_
.HasMoreRBSPData()) {
924 READ_BOOL_OR_RETURN(&pps
->transform_8x8_mode_flag
);
925 READ_BOOL_OR_RETURN(&pps
->pic_scaling_matrix_present_flag
);
927 if (pps
->pic_scaling_matrix_present_flag
) {
928 DVLOG(4) << "Picture scaling matrix present";
929 res
= ParsePPSScalingLists(*sps
, pps
.get());
934 READ_SE_OR_RETURN(&pps
->second_chroma_qp_index_offset
);
937 // If a PPS with the same id already exists, replace it.
938 *pps_id
= pps
->pic_parameter_set_id
;
939 delete active_PPSes_
[*pps_id
];
940 active_PPSes_
[*pps_id
] = pps
.release();
945 H264Parser::Result
H264Parser::ParseRefPicListModification(
946 int num_ref_idx_active_minus1
,
947 H264ModificationOfPicNum
* ref_list_mods
) {
948 H264ModificationOfPicNum
* pic_num_mod
;
950 if (num_ref_idx_active_minus1
>= 32)
951 return kInvalidStream
;
953 for (int i
= 0; i
< 32; ++i
) {
954 pic_num_mod
= &ref_list_mods
[i
];
955 READ_UE_OR_RETURN(&pic_num_mod
->modification_of_pic_nums_idc
);
956 TRUE_OR_RETURN(pic_num_mod
->modification_of_pic_nums_idc
< 4);
958 switch (pic_num_mod
->modification_of_pic_nums_idc
) {
961 READ_UE_OR_RETURN(&pic_num_mod
->abs_diff_pic_num_minus1
);
965 READ_UE_OR_RETURN(&pic_num_mod
->long_term_pic_num
);
969 // Per spec, list cannot be empty.
971 return kInvalidStream
;
975 return kInvalidStream
;
979 // If we got here, we didn't get loop end marker prematurely,
980 // so make sure it is there for our client.
981 int modification_of_pic_nums_idc
;
982 READ_UE_OR_RETURN(&modification_of_pic_nums_idc
);
983 TRUE_OR_RETURN(modification_of_pic_nums_idc
== 3);
988 H264Parser::Result
H264Parser::ParseRefPicListModifications(
989 H264SliceHeader
* shdr
) {
992 if (!shdr
->IsISlice() && !shdr
->IsSISlice()) {
993 READ_BOOL_OR_RETURN(&shdr
->ref_pic_list_modification_flag_l0
);
994 if (shdr
->ref_pic_list_modification_flag_l0
) {
995 res
= ParseRefPicListModification(shdr
->num_ref_idx_l0_active_minus1
,
996 shdr
->ref_list_l0_modifications
);
1002 if (shdr
->IsBSlice()) {
1003 READ_BOOL_OR_RETURN(&shdr
->ref_pic_list_modification_flag_l1
);
1004 if (shdr
->ref_pic_list_modification_flag_l1
) {
1005 res
= ParseRefPicListModification(shdr
->num_ref_idx_l1_active_minus1
,
1006 shdr
->ref_list_l1_modifications
);
1015 H264Parser::Result
H264Parser::ParseWeightingFactors(
1016 int num_ref_idx_active_minus1
,
1017 int chroma_array_type
,
1018 int luma_log2_weight_denom
,
1019 int chroma_log2_weight_denom
,
1020 H264WeightingFactors
* w_facts
) {
1022 int def_luma_weight
= 1 << luma_log2_weight_denom
;
1023 int def_chroma_weight
= 1 << chroma_log2_weight_denom
;
1025 for (int i
= 0; i
< num_ref_idx_active_minus1
+ 1; ++i
) {
1026 READ_BOOL_OR_RETURN(&w_facts
->luma_weight_flag
);
1027 if (w_facts
->luma_weight_flag
) {
1028 READ_SE_OR_RETURN(&w_facts
->luma_weight
[i
]);
1029 IN_RANGE_OR_RETURN(w_facts
->luma_weight
[i
], -128, 127);
1031 READ_SE_OR_RETURN(&w_facts
->luma_offset
[i
]);
1032 IN_RANGE_OR_RETURN(w_facts
->luma_offset
[i
], -128, 127);
1034 w_facts
->luma_weight
[i
] = def_luma_weight
;
1035 w_facts
->luma_offset
[i
] = 0;
1038 if (chroma_array_type
!= 0) {
1039 READ_BOOL_OR_RETURN(&w_facts
->chroma_weight_flag
);
1040 if (w_facts
->chroma_weight_flag
) {
1041 for (int j
= 0; j
< 2; ++j
) {
1042 READ_SE_OR_RETURN(&w_facts
->chroma_weight
[i
][j
]);
1043 IN_RANGE_OR_RETURN(w_facts
->chroma_weight
[i
][j
], -128, 127);
1045 READ_SE_OR_RETURN(&w_facts
->chroma_offset
[i
][j
]);
1046 IN_RANGE_OR_RETURN(w_facts
->chroma_offset
[i
][j
], -128, 127);
1049 for (int j
= 0; j
< 2; ++j
) {
1050 w_facts
->chroma_weight
[i
][j
] = def_chroma_weight
;
1051 w_facts
->chroma_offset
[i
][j
] = 0;
1060 H264Parser::Result
H264Parser::ParsePredWeightTable(const H264SPS
& sps
,
1061 H264SliceHeader
* shdr
) {
1062 READ_UE_OR_RETURN(&shdr
->luma_log2_weight_denom
);
1063 TRUE_OR_RETURN(shdr
->luma_log2_weight_denom
< 8);
1065 if (sps
.chroma_array_type
!= 0)
1066 READ_UE_OR_RETURN(&shdr
->chroma_log2_weight_denom
);
1067 TRUE_OR_RETURN(shdr
->chroma_log2_weight_denom
< 8);
1069 Result res
= ParseWeightingFactors(shdr
->num_ref_idx_l0_active_minus1
,
1070 sps
.chroma_array_type
,
1071 shdr
->luma_log2_weight_denom
,
1072 shdr
->chroma_log2_weight_denom
,
1073 &shdr
->pred_weight_table_l0
);
1077 if (shdr
->IsBSlice()) {
1078 res
= ParseWeightingFactors(shdr
->num_ref_idx_l1_active_minus1
,
1079 sps
.chroma_array_type
,
1080 shdr
->luma_log2_weight_denom
,
1081 shdr
->chroma_log2_weight_denom
,
1082 &shdr
->pred_weight_table_l1
);
1090 H264Parser::Result
H264Parser::ParseDecRefPicMarking(H264SliceHeader
* shdr
) {
1091 size_t bits_left_at_start
= br_
.NumBitsLeft();
1093 if (shdr
->idr_pic_flag
) {
1094 READ_BOOL_OR_RETURN(&shdr
->no_output_of_prior_pics_flag
);
1095 READ_BOOL_OR_RETURN(&shdr
->long_term_reference_flag
);
1097 READ_BOOL_OR_RETURN(&shdr
->adaptive_ref_pic_marking_mode_flag
);
1099 H264DecRefPicMarking
* marking
;
1100 if (shdr
->adaptive_ref_pic_marking_mode_flag
) {
1102 for (i
= 0; i
< arraysize(shdr
->ref_pic_marking
); ++i
) {
1103 marking
= &shdr
->ref_pic_marking
[i
];
1105 READ_UE_OR_RETURN(&marking
->memory_mgmnt_control_operation
);
1106 if (marking
->memory_mgmnt_control_operation
== 0)
1109 if (marking
->memory_mgmnt_control_operation
== 1 ||
1110 marking
->memory_mgmnt_control_operation
== 3)
1111 READ_UE_OR_RETURN(&marking
->difference_of_pic_nums_minus1
);
1113 if (marking
->memory_mgmnt_control_operation
== 2)
1114 READ_UE_OR_RETURN(&marking
->long_term_pic_num
);
1116 if (marking
->memory_mgmnt_control_operation
== 3 ||
1117 marking
->memory_mgmnt_control_operation
== 6)
1118 READ_UE_OR_RETURN(&marking
->long_term_frame_idx
);
1120 if (marking
->memory_mgmnt_control_operation
== 4)
1121 READ_UE_OR_RETURN(&marking
->max_long_term_frame_idx_plus1
);
1123 if (marking
->memory_mgmnt_control_operation
> 6)
1124 return kInvalidStream
;
1127 if (i
== arraysize(shdr
->ref_pic_marking
)) {
1128 DVLOG(1) << "Ran out of dec ref pic marking fields";
1129 return kUnsupportedStream
;
1134 shdr
->dec_ref_pic_marking_bit_size
= bits_left_at_start
- br_
.NumBitsLeft();
1138 H264Parser::Result
H264Parser::ParseSliceHeader(const H264NALU
& nalu
,
1139 H264SliceHeader
* shdr
) {
1145 memset(shdr
, 0, sizeof(*shdr
));
1147 shdr
->idr_pic_flag
= (nalu
.nal_unit_type
== 5);
1148 shdr
->nal_ref_idc
= nalu
.nal_ref_idc
;
1149 shdr
->nalu_data
= nalu
.data
;
1150 shdr
->nalu_size
= nalu
.size
;
1152 READ_UE_OR_RETURN(&shdr
->first_mb_in_slice
);
1153 READ_UE_OR_RETURN(&shdr
->slice_type
);
1154 TRUE_OR_RETURN(shdr
->slice_type
< 10);
1156 READ_UE_OR_RETURN(&shdr
->pic_parameter_set_id
);
1158 pps
= GetPPS(shdr
->pic_parameter_set_id
);
1159 TRUE_OR_RETURN(pps
);
1161 sps
= GetSPS(pps
->seq_parameter_set_id
);
1162 TRUE_OR_RETURN(sps
);
1164 if (sps
->separate_colour_plane_flag
) {
1165 DVLOG(1) << "Interlaced streams not supported";
1166 return kUnsupportedStream
;
1169 READ_BITS_OR_RETURN(sps
->log2_max_frame_num_minus4
+ 4, &shdr
->frame_num
);
1170 if (!sps
->frame_mbs_only_flag
) {
1171 READ_BOOL_OR_RETURN(&shdr
->field_pic_flag
);
1172 if (shdr
->field_pic_flag
) {
1173 DVLOG(1) << "Interlaced streams not supported";
1174 return kUnsupportedStream
;
1178 if (shdr
->idr_pic_flag
)
1179 READ_UE_OR_RETURN(&shdr
->idr_pic_id
);
1181 size_t bits_left_at_pic_order_cnt_start
= br_
.NumBitsLeft();
1182 if (sps
->pic_order_cnt_type
== 0) {
1183 READ_BITS_OR_RETURN(sps
->log2_max_pic_order_cnt_lsb_minus4
+ 4,
1184 &shdr
->pic_order_cnt_lsb
);
1185 if (pps
->bottom_field_pic_order_in_frame_present_flag
&&
1186 !shdr
->field_pic_flag
)
1187 READ_SE_OR_RETURN(&shdr
->delta_pic_order_cnt_bottom
);
1190 if (sps
->pic_order_cnt_type
== 1 && !sps
->delta_pic_order_always_zero_flag
) {
1191 READ_SE_OR_RETURN(&shdr
->delta_pic_order_cnt0
);
1192 if (pps
->bottom_field_pic_order_in_frame_present_flag
&&
1193 !shdr
->field_pic_flag
)
1194 READ_SE_OR_RETURN(&shdr
->delta_pic_order_cnt1
);
1197 shdr
->pic_order_cnt_bit_size
=
1198 bits_left_at_pic_order_cnt_start
- br_
.NumBitsLeft();
1200 if (pps
->redundant_pic_cnt_present_flag
) {
1201 READ_UE_OR_RETURN(&shdr
->redundant_pic_cnt
);
1202 TRUE_OR_RETURN(shdr
->redundant_pic_cnt
< 128);
1205 if (shdr
->IsBSlice())
1206 READ_BOOL_OR_RETURN(&shdr
->direct_spatial_mv_pred_flag
);
1208 if (shdr
->IsPSlice() || shdr
->IsSPSlice() || shdr
->IsBSlice()) {
1209 READ_BOOL_OR_RETURN(&shdr
->num_ref_idx_active_override_flag
);
1210 if (shdr
->num_ref_idx_active_override_flag
) {
1211 READ_UE_OR_RETURN(&shdr
->num_ref_idx_l0_active_minus1
);
1212 if (shdr
->IsBSlice())
1213 READ_UE_OR_RETURN(&shdr
->num_ref_idx_l1_active_minus1
);
1215 shdr
->num_ref_idx_l0_active_minus1
=
1216 pps
->num_ref_idx_l0_default_active_minus1
;
1217 if (shdr
->IsBSlice()) {
1218 shdr
->num_ref_idx_l1_active_minus1
=
1219 pps
->num_ref_idx_l1_default_active_minus1
;
1223 if (shdr
->field_pic_flag
) {
1224 TRUE_OR_RETURN(shdr
->num_ref_idx_l0_active_minus1
< 32);
1225 TRUE_OR_RETURN(shdr
->num_ref_idx_l1_active_minus1
< 32);
1227 TRUE_OR_RETURN(shdr
->num_ref_idx_l0_active_minus1
< 16);
1228 TRUE_OR_RETURN(shdr
->num_ref_idx_l1_active_minus1
< 16);
1231 if (nalu
.nal_unit_type
== H264NALU::kCodedSliceExtension
) {
1232 return kUnsupportedStream
;
1234 res
= ParseRefPicListModifications(shdr
);
1239 if ((pps
->weighted_pred_flag
&& (shdr
->IsPSlice() || shdr
->IsSPSlice())) ||
1240 (pps
->weighted_bipred_idc
== 1 && shdr
->IsBSlice())) {
1241 res
= ParsePredWeightTable(*sps
, shdr
);
1246 if (nalu
.nal_ref_idc
!= 0) {
1247 res
= ParseDecRefPicMarking(shdr
);
1252 if (pps
->entropy_coding_mode_flag
&& !shdr
->IsISlice() &&
1253 !shdr
->IsSISlice()) {
1254 READ_UE_OR_RETURN(&shdr
->cabac_init_idc
);
1255 TRUE_OR_RETURN(shdr
->cabac_init_idc
< 3);
1258 READ_SE_OR_RETURN(&shdr
->slice_qp_delta
);
1260 if (shdr
->IsSPSlice() || shdr
->IsSISlice()) {
1261 if (shdr
->IsSPSlice())
1262 READ_BOOL_OR_RETURN(&shdr
->sp_for_switch_flag
);
1263 READ_SE_OR_RETURN(&shdr
->slice_qs_delta
);
1266 if (pps
->deblocking_filter_control_present_flag
) {
1267 READ_UE_OR_RETURN(&shdr
->disable_deblocking_filter_idc
);
1268 TRUE_OR_RETURN(shdr
->disable_deblocking_filter_idc
< 3);
1270 if (shdr
->disable_deblocking_filter_idc
!= 1) {
1271 READ_SE_OR_RETURN(&shdr
->slice_alpha_c0_offset_div2
);
1272 IN_RANGE_OR_RETURN(shdr
->slice_alpha_c0_offset_div2
, -6, 6);
1274 READ_SE_OR_RETURN(&shdr
->slice_beta_offset_div2
);
1275 IN_RANGE_OR_RETURN(shdr
->slice_beta_offset_div2
, -6, 6);
1279 if (pps
->num_slice_groups_minus1
> 0) {
1280 DVLOG(1) << "Slice groups not supported";
1281 return kUnsupportedStream
;
1284 size_t epb
= br_
.NumEmulationPreventionBytesRead();
1285 shdr
->header_bit_size
= (shdr
->nalu_size
- epb
) * 8 - br_
.NumBitsLeft();
1290 H264Parser::Result
H264Parser::ParseSEI(H264SEIMessage
* sei_msg
) {
1293 memset(sei_msg
, 0, sizeof(*sei_msg
));
1295 READ_BITS_OR_RETURN(8, &byte
);
1296 while (byte
== 0xff) {
1297 sei_msg
->type
+= 255;
1298 READ_BITS_OR_RETURN(8, &byte
);
1300 sei_msg
->type
+= byte
;
1302 READ_BITS_OR_RETURN(8, &byte
);
1303 while (byte
== 0xff) {
1304 sei_msg
->payload_size
+= 255;
1305 READ_BITS_OR_RETURN(8, &byte
);
1307 sei_msg
->payload_size
+= byte
;
1309 DVLOG(4) << "Found SEI message type: " << sei_msg
->type
1310 << " payload size: " << sei_msg
->payload_size
;
1312 switch (sei_msg
->type
) {
1313 case H264SEIMessage::kSEIRecoveryPoint
:
1314 READ_UE_OR_RETURN(&sei_msg
->recovery_point
.recovery_frame_cnt
);
1315 READ_BOOL_OR_RETURN(&sei_msg
->recovery_point
.exact_match_flag
);
1316 READ_BOOL_OR_RETURN(&sei_msg
->recovery_point
.broken_link_flag
);
1317 READ_BITS_OR_RETURN(2, &sei_msg
->recovery_point
.changing_slice_group_idc
);
1321 DVLOG(4) << "Unsupported SEI message";
1328 } // namespace media