Cast: Skip receiver log messages with time delta that can't be encoded.
[chromium-blink-merge.git] / media / filters / h264_parser.cc
blobc03ee884d97e7bda5e6c5a2d59798e504cba24b6
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/filters/h264_parser.h"
11 namespace media {
13 bool H264SliceHeader::IsPSlice() const {
14 return (slice_type % 5 == kPSlice);
17 bool H264SliceHeader::IsBSlice() const {
18 return (slice_type % 5 == kBSlice);
21 bool H264SliceHeader::IsISlice() const {
22 return (slice_type % 5 == kISlice);
25 bool H264SliceHeader::IsSPSlice() const {
26 return (slice_type % 5 == kSPSlice);
29 bool H264SliceHeader::IsSISlice() const {
30 return (slice_type % 5 == kSISlice);
33 H264NALU::H264NALU() {
34 memset(this, 0, sizeof(*this));
37 H264SPS::H264SPS() {
38 memset(this, 0, sizeof(*this));
41 H264PPS::H264PPS() {
42 memset(this, 0, sizeof(*this));
45 H264SliceHeader::H264SliceHeader() {
46 memset(this, 0, sizeof(*this));
49 H264SEIMessage::H264SEIMessage() {
50 memset(this, 0, sizeof(*this));
53 #define READ_BITS_OR_RETURN(num_bits, out) \
54 do { \
55 int _out; \
56 if (!br_.ReadBits(num_bits, &_out)) { \
57 DVLOG(1) \
58 << "Error in stream: unexpected EOS while trying to read " #out; \
59 return kInvalidStream; \
60 } \
61 *out = _out; \
62 } while (0)
64 #define READ_BOOL_OR_RETURN(out) \
65 do { \
66 int _out; \
67 if (!br_.ReadBits(1, &_out)) { \
68 DVLOG(1) \
69 << "Error in stream: unexpected EOS while trying to read " #out; \
70 return kInvalidStream; \
71 } \
72 *out = _out != 0; \
73 } while (0)
75 #define READ_UE_OR_RETURN(out) \
76 do { \
77 if (ReadUE(out) != kOk) { \
78 DVLOG(1) << "Error in stream: invalid value while trying to read " #out; \
79 return kInvalidStream; \
80 } \
81 } while (0)
83 #define READ_SE_OR_RETURN(out) \
84 do { \
85 if (ReadSE(out) != kOk) { \
86 DVLOG(1) << "Error in stream: invalid value while trying to read " #out; \
87 return kInvalidStream; \
88 } \
89 } while (0)
91 #define IN_RANGE_OR_RETURN(val, min, max) \
92 do { \
93 if ((val) < (min) || (val) > (max)) { \
94 DVLOG(1) << "Error in stream: invalid value, expected " #val " to be" \
95 << " in range [" << (min) << ":" << (max) << "]" \
96 << " found " << (val) << " instead"; \
97 return kInvalidStream; \
98 } \
99 } while (0)
101 #define TRUE_OR_RETURN(a) \
102 do { \
103 if (!(a)) { \
104 DVLOG(1) << "Error in stream: invalid value, expected " << #a; \
105 return kInvalidStream; \
107 } while (0)
109 enum AspectRatioIdc {
110 kExtendedSar = 255,
113 // ISO 14496 part 10
114 // VUI parameters: Table E-1 "Meaning of sample aspect ratio indicator"
115 static const int kTableSarWidth[] = {
116 0, 1, 12, 10, 16, 40, 24, 20, 32, 80, 18, 15, 64, 160, 4, 3, 2
118 static const int kTableSarHeight[] = {
119 0, 1, 11, 11, 11, 33, 11, 11, 11, 33, 11, 11, 33, 99, 3, 2, 1
121 COMPILE_ASSERT(arraysize(kTableSarWidth) == arraysize(kTableSarHeight),
122 sar_tables_must_have_same_size);
124 H264Parser::H264Parser() {
125 Reset();
128 H264Parser::~H264Parser() {
129 STLDeleteValues(&active_SPSes_);
130 STLDeleteValues(&active_PPSes_);
133 void H264Parser::Reset() {
134 stream_ = NULL;
135 bytes_left_ = 0;
138 void H264Parser::SetStream(const uint8* stream, off_t stream_size) {
139 DCHECK(stream);
140 DCHECK_GT(stream_size, 0);
142 stream_ = stream;
143 bytes_left_ = stream_size;
146 const H264PPS* H264Parser::GetPPS(int pps_id) {
147 return active_PPSes_[pps_id];
150 const H264SPS* H264Parser::GetSPS(int sps_id) {
151 return active_SPSes_[sps_id];
154 static inline bool IsStartCode(const uint8* data) {
155 return data[0] == 0x00 && data[1] == 0x00 && data[2] == 0x01;
158 // static
159 bool H264Parser::FindStartCode(const uint8* data, off_t data_size,
160 off_t* offset, off_t* start_code_size) {
161 DCHECK_GE(data_size, 0);
162 off_t bytes_left = data_size;
164 while (bytes_left >= 3) {
165 if (IsStartCode(data)) {
166 // Found three-byte start code, set pointer at its beginning.
167 *offset = data_size - bytes_left;
168 *start_code_size = 3;
170 // If there is a zero byte before this start code,
171 // then it's actually a four-byte start code, so backtrack one byte.
172 if (*offset > 0 && *(data - 1) == 0x00) {
173 --(*offset);
174 ++(*start_code_size);
177 return true;
180 ++data;
181 --bytes_left;
184 // End of data: offset is pointing to the first byte that was not considered
185 // as a possible start of a start code.
186 // Note: there is no security issue when receiving a negative |data_size|
187 // since in this case, |bytes_left| is equal to |data_size| and thus
188 // |*offset| is equal to 0 (valid offset).
189 *offset = data_size - bytes_left;
190 *start_code_size = 0;
191 return false;
194 bool H264Parser::LocateNALU(off_t* nalu_size, off_t* start_code_size) {
195 // Find the start code of next NALU.
196 off_t nalu_start_off = 0;
197 off_t annexb_start_code_size = 0;
198 if (!FindStartCode(stream_, bytes_left_,
199 &nalu_start_off, &annexb_start_code_size)) {
200 DVLOG(4) << "Could not find start code, end of stream?";
201 return false;
204 // Move the stream to the beginning of the NALU (pointing at the start code).
205 stream_ += nalu_start_off;
206 bytes_left_ -= nalu_start_off;
208 const uint8* nalu_data = stream_ + annexb_start_code_size;
209 off_t max_nalu_data_size = bytes_left_ - annexb_start_code_size;
210 if (max_nalu_data_size <= 0) {
211 DVLOG(3) << "End of stream";
212 return false;
215 // Find the start code of next NALU;
216 // if successful, |nalu_size_without_start_code| is the number of bytes from
217 // after previous start code to before this one;
218 // if next start code is not found, it is still a valid NALU since there
219 // are some bytes left after the first start code: all the remaining bytes
220 // belong to the current NALU.
221 off_t next_start_code_size = 0;
222 off_t nalu_size_without_start_code = 0;
223 if (!FindStartCode(nalu_data, max_nalu_data_size,
224 &nalu_size_without_start_code, &next_start_code_size)) {
225 nalu_size_without_start_code = max_nalu_data_size;
227 *nalu_size = nalu_size_without_start_code + annexb_start_code_size;
228 *start_code_size = annexb_start_code_size;
229 return true;
232 H264Parser::Result H264Parser::ReadUE(int* val) {
233 int num_bits = -1;
234 int bit;
235 int rest;
237 // Count the number of contiguous zero bits.
238 do {
239 READ_BITS_OR_RETURN(1, &bit);
240 num_bits++;
241 } while (bit == 0);
243 if (num_bits > 31)
244 return kInvalidStream;
246 // Calculate exp-Golomb code value of size num_bits.
247 *val = (1 << num_bits) - 1;
249 if (num_bits > 0) {
250 READ_BITS_OR_RETURN(num_bits, &rest);
251 *val += rest;
254 return kOk;
257 H264Parser::Result H264Parser::ReadSE(int* val) {
258 int ue;
259 Result res;
261 // See Chapter 9 in the spec.
262 res = ReadUE(&ue);
263 if (res != kOk)
264 return res;
266 if (ue % 2 == 0)
267 *val = -(ue / 2);
268 else
269 *val = ue / 2 + 1;
271 return kOk;
274 H264Parser::Result H264Parser::AdvanceToNextNALU(H264NALU* nalu) {
275 off_t start_code_size;
276 off_t nalu_size_with_start_code;
277 if (!LocateNALU(&nalu_size_with_start_code, &start_code_size)) {
278 DVLOG(4) << "Could not find next NALU, bytes left in stream: "
279 << bytes_left_;
280 return kEOStream;
283 nalu->data = stream_ + start_code_size;
284 nalu->size = nalu_size_with_start_code - start_code_size;
285 DVLOG(4) << "NALU found: size=" << nalu_size_with_start_code;
287 // Initialize bit reader at the start of found NALU.
288 if (!br_.Initialize(nalu->data, nalu->size))
289 return kEOStream;
291 // Move parser state to after this NALU, so next time AdvanceToNextNALU
292 // is called, we will effectively be skipping it;
293 // other parsing functions will use the position saved
294 // in bit reader for parsing, so we don't have to remember it here.
295 stream_ += nalu_size_with_start_code;
296 bytes_left_ -= nalu_size_with_start_code;
298 // Read NALU header, skip the forbidden_zero_bit, but check for it.
299 int data;
300 READ_BITS_OR_RETURN(1, &data);
301 TRUE_OR_RETURN(data == 0);
303 READ_BITS_OR_RETURN(2, &nalu->nal_ref_idc);
304 READ_BITS_OR_RETURN(5, &nalu->nal_unit_type);
306 DVLOG(4) << "NALU type: " << static_cast<int>(nalu->nal_unit_type)
307 << " at: " << reinterpret_cast<const void*>(nalu->data)
308 << " size: " << nalu->size
309 << " ref: " << static_cast<int>(nalu->nal_ref_idc);
311 return kOk;
314 // Default scaling lists (per spec).
315 static const int kDefault4x4Intra[kH264ScalingList4x4Length] = {
316 6, 13, 13, 20, 20, 20, 28, 28, 28, 28, 32, 32, 32, 37, 37, 42, };
318 static const int kDefault4x4Inter[kH264ScalingList4x4Length] = {
319 10, 14, 14, 20, 20, 20, 24, 24, 24, 24, 27, 27, 27, 30, 30, 34, };
321 static const int kDefault8x8Intra[kH264ScalingList8x8Length] = {
322 6, 10, 10, 13, 11, 13, 16, 16, 16, 16, 18, 18, 18, 18, 18, 23,
323 23, 23, 23, 23, 23, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27,
324 27, 27, 27, 27, 29, 29, 29, 29, 29, 29, 29, 31, 31, 31, 31, 31,
325 31, 33, 33, 33, 33, 33, 36, 36, 36, 36, 38, 38, 38, 40, 40, 42, };
327 static const int kDefault8x8Inter[kH264ScalingList8x8Length] = {
328 9, 13, 13, 15, 13, 15, 17, 17, 17, 17, 19, 19, 19, 19, 19, 21,
329 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 24, 24, 24, 24,
330 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27, 27,
331 27, 28, 28, 28, 28, 28, 30, 30, 30, 30, 32, 32, 32, 33, 33, 35, };
333 static inline void DefaultScalingList4x4(
334 int i,
335 int scaling_list4x4[][kH264ScalingList4x4Length]) {
336 DCHECK_LT(i, 6);
338 if (i < 3)
339 memcpy(scaling_list4x4[i], kDefault4x4Intra, sizeof(kDefault4x4Intra));
340 else if (i < 6)
341 memcpy(scaling_list4x4[i], kDefault4x4Inter, sizeof(kDefault4x4Inter));
344 static inline void DefaultScalingList8x8(
345 int i,
346 int scaling_list8x8[][kH264ScalingList8x8Length]) {
347 DCHECK_LT(i, 6);
349 if (i % 2 == 0)
350 memcpy(scaling_list8x8[i], kDefault8x8Intra, sizeof(kDefault8x8Intra));
351 else
352 memcpy(scaling_list8x8[i], kDefault8x8Inter, sizeof(kDefault8x8Inter));
355 static void FallbackScalingList4x4(
356 int i,
357 const int default_scaling_list_intra[],
358 const int default_scaling_list_inter[],
359 int scaling_list4x4[][kH264ScalingList4x4Length]) {
360 static const int kScalingList4x4ByteSize =
361 sizeof(scaling_list4x4[0][0]) * kH264ScalingList4x4Length;
363 switch (i) {
364 case 0:
365 memcpy(scaling_list4x4[i], default_scaling_list_intra,
366 kScalingList4x4ByteSize);
367 break;
369 case 1:
370 memcpy(scaling_list4x4[i], scaling_list4x4[0], kScalingList4x4ByteSize);
371 break;
373 case 2:
374 memcpy(scaling_list4x4[i], scaling_list4x4[1], kScalingList4x4ByteSize);
375 break;
377 case 3:
378 memcpy(scaling_list4x4[i], default_scaling_list_inter,
379 kScalingList4x4ByteSize);
380 break;
382 case 4:
383 memcpy(scaling_list4x4[i], scaling_list4x4[3], kScalingList4x4ByteSize);
384 break;
386 case 5:
387 memcpy(scaling_list4x4[i], scaling_list4x4[4], kScalingList4x4ByteSize);
388 break;
390 default:
391 NOTREACHED();
392 break;
396 static void FallbackScalingList8x8(
397 int i,
398 const int default_scaling_list_intra[],
399 const int default_scaling_list_inter[],
400 int scaling_list8x8[][kH264ScalingList8x8Length]) {
401 static const int kScalingList8x8ByteSize =
402 sizeof(scaling_list8x8[0][0]) * kH264ScalingList8x8Length;
404 switch (i) {
405 case 0:
406 memcpy(scaling_list8x8[i], default_scaling_list_intra,
407 kScalingList8x8ByteSize);
408 break;
410 case 1:
411 memcpy(scaling_list8x8[i], default_scaling_list_inter,
412 kScalingList8x8ByteSize);
413 break;
415 case 2:
416 memcpy(scaling_list8x8[i], scaling_list8x8[0], kScalingList8x8ByteSize);
417 break;
419 case 3:
420 memcpy(scaling_list8x8[i], scaling_list8x8[1], kScalingList8x8ByteSize);
421 break;
423 case 4:
424 memcpy(scaling_list8x8[i], scaling_list8x8[2], kScalingList8x8ByteSize);
425 break;
427 case 5:
428 memcpy(scaling_list8x8[i], scaling_list8x8[3], kScalingList8x8ByteSize);
429 break;
431 default:
432 NOTREACHED();
433 break;
437 H264Parser::Result H264Parser::ParseScalingList(int size,
438 int* scaling_list,
439 bool* use_default) {
440 // See chapter 7.3.2.1.1.1.
441 int last_scale = 8;
442 int next_scale = 8;
443 int delta_scale;
445 *use_default = false;
447 for (int j = 0; j < size; ++j) {
448 if (next_scale != 0) {
449 READ_SE_OR_RETURN(&delta_scale);
450 IN_RANGE_OR_RETURN(delta_scale, -128, 127);
451 next_scale = (last_scale + delta_scale + 256) & 0xff;
453 if (j == 0 && next_scale == 0) {
454 *use_default = true;
455 return kOk;
459 scaling_list[j] = (next_scale == 0) ? last_scale : next_scale;
460 last_scale = scaling_list[j];
463 return kOk;
466 H264Parser::Result H264Parser::ParseSPSScalingLists(H264SPS* sps) {
467 // See 7.4.2.1.1.
468 bool seq_scaling_list_present_flag;
469 bool use_default;
470 Result res;
472 // Parse scaling_list4x4.
473 for (int i = 0; i < 6; ++i) {
474 READ_BOOL_OR_RETURN(&seq_scaling_list_present_flag);
476 if (seq_scaling_list_present_flag) {
477 res = ParseScalingList(arraysize(sps->scaling_list4x4[i]),
478 sps->scaling_list4x4[i],
479 &use_default);
480 if (res != kOk)
481 return res;
483 if (use_default)
484 DefaultScalingList4x4(i, sps->scaling_list4x4);
486 } else {
487 FallbackScalingList4x4(
488 i, kDefault4x4Intra, kDefault4x4Inter, sps->scaling_list4x4);
492 // Parse scaling_list8x8.
493 for (int i = 0; i < ((sps->chroma_format_idc != 3) ? 2 : 6); ++i) {
494 READ_BOOL_OR_RETURN(&seq_scaling_list_present_flag);
496 if (seq_scaling_list_present_flag) {
497 res = ParseScalingList(arraysize(sps->scaling_list8x8[i]),
498 sps->scaling_list8x8[i],
499 &use_default);
500 if (res != kOk)
501 return res;
503 if (use_default)
504 DefaultScalingList8x8(i, sps->scaling_list8x8);
506 } else {
507 FallbackScalingList8x8(
508 i, kDefault8x8Intra, kDefault8x8Inter, sps->scaling_list8x8);
512 return kOk;
515 H264Parser::Result H264Parser::ParsePPSScalingLists(const H264SPS& sps,
516 H264PPS* pps) {
517 // See 7.4.2.2.
518 bool pic_scaling_list_present_flag;
519 bool use_default;
520 Result res;
522 for (int i = 0; i < 6; ++i) {
523 READ_BOOL_OR_RETURN(&pic_scaling_list_present_flag);
525 if (pic_scaling_list_present_flag) {
526 res = ParseScalingList(arraysize(pps->scaling_list4x4[i]),
527 pps->scaling_list4x4[i],
528 &use_default);
529 if (res != kOk)
530 return res;
532 if (use_default)
533 DefaultScalingList4x4(i, pps->scaling_list4x4);
535 } else {
536 if (sps.seq_scaling_matrix_present_flag) {
537 // Table 7-2 fallback rule A in spec.
538 FallbackScalingList4x4(
539 i, kDefault4x4Intra, kDefault4x4Inter, pps->scaling_list4x4);
540 } else {
541 // Table 7-2 fallback rule B in spec.
542 FallbackScalingList4x4(i,
543 sps.scaling_list4x4[0],
544 sps.scaling_list4x4[3],
545 pps->scaling_list4x4);
550 if (pps->transform_8x8_mode_flag) {
551 for (int i = 0; i < ((sps.chroma_format_idc != 3) ? 2 : 6); ++i) {
552 READ_BOOL_OR_RETURN(&pic_scaling_list_present_flag);
554 if (pic_scaling_list_present_flag) {
555 res = ParseScalingList(arraysize(pps->scaling_list8x8[i]),
556 pps->scaling_list8x8[i],
557 &use_default);
558 if (res != kOk)
559 return res;
561 if (use_default)
562 DefaultScalingList8x8(i, pps->scaling_list8x8);
564 } else {
565 if (sps.seq_scaling_matrix_present_flag) {
566 // Table 7-2 fallback rule A in spec.
567 FallbackScalingList8x8(
568 i, kDefault8x8Intra, kDefault8x8Inter, pps->scaling_list8x8);
569 } else {
570 // Table 7-2 fallback rule B in spec.
571 FallbackScalingList8x8(i,
572 sps.scaling_list8x8[0],
573 sps.scaling_list8x8[1],
574 pps->scaling_list8x8);
579 return kOk;
582 static void FillDefaultSeqScalingLists(H264SPS* sps) {
583 for (int i = 0; i < 6; ++i)
584 for (int j = 0; j < kH264ScalingList4x4Length; ++j)
585 sps->scaling_list4x4[i][j] = 16;
587 for (int i = 0; i < 6; ++i)
588 for (int j = 0; j < kH264ScalingList8x8Length; ++j)
589 sps->scaling_list8x8[i][j] = 16;
592 H264Parser::Result H264Parser::ParseSPS(int* sps_id) {
593 // See 7.4.2.1.
594 int data;
595 Result res;
597 *sps_id = -1;
599 scoped_ptr<H264SPS> sps(new H264SPS());
601 READ_BITS_OR_RETURN(8, &sps->profile_idc);
602 READ_BITS_OR_RETURN(6, &sps->constraint_setx_flag);
603 READ_BITS_OR_RETURN(2, &data);
604 READ_BITS_OR_RETURN(8, &sps->level_idc);
605 READ_UE_OR_RETURN(&sps->seq_parameter_set_id);
606 TRUE_OR_RETURN(sps->seq_parameter_set_id < 32);
608 if (sps->profile_idc == 100 || sps->profile_idc == 110 ||
609 sps->profile_idc == 122 || sps->profile_idc == 244 ||
610 sps->profile_idc == 44 || sps->profile_idc == 83 ||
611 sps->profile_idc == 86 || sps->profile_idc == 118 ||
612 sps->profile_idc == 128) {
613 READ_UE_OR_RETURN(&sps->chroma_format_idc);
614 TRUE_OR_RETURN(sps->chroma_format_idc < 4);
616 if (sps->chroma_format_idc == 3)
617 READ_BOOL_OR_RETURN(&sps->separate_colour_plane_flag);
619 READ_UE_OR_RETURN(&sps->bit_depth_luma_minus8);
620 TRUE_OR_RETURN(sps->bit_depth_luma_minus8 < 7);
622 READ_UE_OR_RETURN(&sps->bit_depth_chroma_minus8);
623 TRUE_OR_RETURN(sps->bit_depth_chroma_minus8 < 7);
625 READ_BOOL_OR_RETURN(&sps->qpprime_y_zero_transform_bypass_flag);
626 READ_BOOL_OR_RETURN(&sps->seq_scaling_matrix_present_flag);
628 if (sps->seq_scaling_matrix_present_flag) {
629 DVLOG(4) << "Scaling matrix present";
630 res = ParseSPSScalingLists(sps.get());
631 if (res != kOk)
632 return res;
633 } else {
634 FillDefaultSeqScalingLists(sps.get());
636 } else {
637 sps->chroma_format_idc = 1;
638 FillDefaultSeqScalingLists(sps.get());
641 if (sps->separate_colour_plane_flag)
642 sps->chroma_array_type = 0;
643 else
644 sps->chroma_array_type = sps->chroma_format_idc;
646 READ_UE_OR_RETURN(&sps->log2_max_frame_num_minus4);
647 TRUE_OR_RETURN(sps->log2_max_frame_num_minus4 < 13);
649 READ_UE_OR_RETURN(&sps->pic_order_cnt_type);
650 TRUE_OR_RETURN(sps->pic_order_cnt_type < 3);
652 sps->expected_delta_per_pic_order_cnt_cycle = 0;
653 if (sps->pic_order_cnt_type == 0) {
654 READ_UE_OR_RETURN(&sps->log2_max_pic_order_cnt_lsb_minus4);
655 TRUE_OR_RETURN(sps->log2_max_pic_order_cnt_lsb_minus4 < 13);
656 } else if (sps->pic_order_cnt_type == 1) {
657 READ_BOOL_OR_RETURN(&sps->delta_pic_order_always_zero_flag);
658 READ_SE_OR_RETURN(&sps->offset_for_non_ref_pic);
659 READ_SE_OR_RETURN(&sps->offset_for_top_to_bottom_field);
660 READ_UE_OR_RETURN(&sps->num_ref_frames_in_pic_order_cnt_cycle);
661 TRUE_OR_RETURN(sps->num_ref_frames_in_pic_order_cnt_cycle < 255);
663 for (int i = 0; i < sps->num_ref_frames_in_pic_order_cnt_cycle; ++i) {
664 READ_SE_OR_RETURN(&sps->offset_for_ref_frame[i]);
665 sps->expected_delta_per_pic_order_cnt_cycle +=
666 sps->offset_for_ref_frame[i];
670 READ_UE_OR_RETURN(&sps->max_num_ref_frames);
671 READ_BOOL_OR_RETURN(&sps->gaps_in_frame_num_value_allowed_flag);
673 if (sps->gaps_in_frame_num_value_allowed_flag)
674 return kUnsupportedStream;
676 READ_UE_OR_RETURN(&sps->pic_width_in_mbs_minus1);
677 READ_UE_OR_RETURN(&sps->pic_height_in_map_units_minus1);
679 READ_BOOL_OR_RETURN(&sps->frame_mbs_only_flag);
680 if (!sps->frame_mbs_only_flag)
681 READ_BOOL_OR_RETURN(&sps->mb_adaptive_frame_field_flag);
683 READ_BOOL_OR_RETURN(&sps->direct_8x8_inference_flag);
685 READ_BOOL_OR_RETURN(&sps->frame_cropping_flag);
686 if (sps->frame_cropping_flag) {
687 READ_UE_OR_RETURN(&sps->frame_crop_left_offset);
688 READ_UE_OR_RETURN(&sps->frame_crop_right_offset);
689 READ_UE_OR_RETURN(&sps->frame_crop_top_offset);
690 READ_UE_OR_RETURN(&sps->frame_crop_bottom_offset);
693 READ_BOOL_OR_RETURN(&sps->vui_parameters_present_flag);
694 if (sps->vui_parameters_present_flag) {
695 bool aspect_ratio_info_present_flag;
696 READ_BOOL_OR_RETURN(&aspect_ratio_info_present_flag);
697 if (aspect_ratio_info_present_flag) {
698 int aspect_ratio_idc;
699 READ_BITS_OR_RETURN(8, &aspect_ratio_idc);
700 if (aspect_ratio_idc == kExtendedSar) {
701 READ_BITS_OR_RETURN(16, &sps->sar_width);
702 READ_BITS_OR_RETURN(16, &sps->sar_height);
703 } else {
704 const int max_aspect_ratio_idc = arraysize(kTableSarWidth) - 1;
705 IN_RANGE_OR_RETURN(aspect_ratio_idc, 0, max_aspect_ratio_idc);
706 sps->sar_width = kTableSarWidth[aspect_ratio_idc];
707 sps->sar_height = kTableSarHeight[aspect_ratio_idc];
712 // If an SPS with the same id already exists, replace it.
713 *sps_id = sps->seq_parameter_set_id;
714 delete active_SPSes_[*sps_id];
715 active_SPSes_[*sps_id] = sps.release();
717 return kOk;
720 H264Parser::Result H264Parser::ParsePPS(int* pps_id) {
721 // See 7.4.2.2.
722 const H264SPS* sps;
723 Result res;
725 *pps_id = -1;
727 scoped_ptr<H264PPS> pps(new H264PPS());
729 READ_UE_OR_RETURN(&pps->pic_parameter_set_id);
730 READ_UE_OR_RETURN(&pps->seq_parameter_set_id);
731 TRUE_OR_RETURN(pps->seq_parameter_set_id < 32);
733 sps = GetSPS(pps->seq_parameter_set_id);
734 TRUE_OR_RETURN(sps);
736 READ_BOOL_OR_RETURN(&pps->entropy_coding_mode_flag);
737 READ_BOOL_OR_RETURN(&pps->bottom_field_pic_order_in_frame_present_flag);
739 READ_UE_OR_RETURN(&pps->num_slice_groups_minus1);
740 if (pps->num_slice_groups_minus1 > 1) {
741 DVLOG(1) << "Slice groups not supported";
742 return kUnsupportedStream;
745 READ_UE_OR_RETURN(&pps->num_ref_idx_l0_default_active_minus1);
746 TRUE_OR_RETURN(pps->num_ref_idx_l0_default_active_minus1 < 32);
748 READ_UE_OR_RETURN(&pps->num_ref_idx_l1_default_active_minus1);
749 TRUE_OR_RETURN(pps->num_ref_idx_l1_default_active_minus1 < 32);
751 READ_BOOL_OR_RETURN(&pps->weighted_pred_flag);
752 READ_BITS_OR_RETURN(2, &pps->weighted_bipred_idc);
753 TRUE_OR_RETURN(pps->weighted_bipred_idc < 3);
755 READ_SE_OR_RETURN(&pps->pic_init_qp_minus26);
756 IN_RANGE_OR_RETURN(pps->pic_init_qp_minus26, -26, 25);
758 READ_SE_OR_RETURN(&pps->pic_init_qs_minus26);
759 IN_RANGE_OR_RETURN(pps->pic_init_qs_minus26, -26, 25);
761 READ_SE_OR_RETURN(&pps->chroma_qp_index_offset);
762 IN_RANGE_OR_RETURN(pps->chroma_qp_index_offset, -12, 12);
763 pps->second_chroma_qp_index_offset = pps->chroma_qp_index_offset;
765 READ_BOOL_OR_RETURN(&pps->deblocking_filter_control_present_flag);
766 READ_BOOL_OR_RETURN(&pps->constrained_intra_pred_flag);
767 READ_BOOL_OR_RETURN(&pps->redundant_pic_cnt_present_flag);
769 if (br_.HasMoreRBSPData()) {
770 READ_BOOL_OR_RETURN(&pps->transform_8x8_mode_flag);
771 READ_BOOL_OR_RETURN(&pps->pic_scaling_matrix_present_flag);
773 if (pps->pic_scaling_matrix_present_flag) {
774 DVLOG(4) << "Picture scaling matrix present";
775 res = ParsePPSScalingLists(*sps, pps.get());
776 if (res != kOk)
777 return res;
780 READ_SE_OR_RETURN(&pps->second_chroma_qp_index_offset);
783 // If a PPS with the same id already exists, replace it.
784 *pps_id = pps->pic_parameter_set_id;
785 delete active_PPSes_[*pps_id];
786 active_PPSes_[*pps_id] = pps.release();
788 return kOk;
791 H264Parser::Result H264Parser::ParseRefPicListModification(
792 int num_ref_idx_active_minus1,
793 H264ModificationOfPicNum* ref_list_mods) {
794 H264ModificationOfPicNum* pic_num_mod;
796 if (num_ref_idx_active_minus1 >= 32)
797 return kInvalidStream;
799 for (int i = 0; i < 32; ++i) {
800 pic_num_mod = &ref_list_mods[i];
801 READ_UE_OR_RETURN(&pic_num_mod->modification_of_pic_nums_idc);
802 TRUE_OR_RETURN(pic_num_mod->modification_of_pic_nums_idc < 4);
804 switch (pic_num_mod->modification_of_pic_nums_idc) {
805 case 0:
806 case 1:
807 READ_UE_OR_RETURN(&pic_num_mod->abs_diff_pic_num_minus1);
808 break;
810 case 2:
811 READ_UE_OR_RETURN(&pic_num_mod->long_term_pic_num);
812 break;
814 case 3:
815 // Per spec, list cannot be empty.
816 if (i == 0)
817 return kInvalidStream;
818 return kOk;
820 default:
821 return kInvalidStream;
825 // If we got here, we didn't get loop end marker prematurely,
826 // so make sure it is there for our client.
827 int modification_of_pic_nums_idc;
828 READ_UE_OR_RETURN(&modification_of_pic_nums_idc);
829 TRUE_OR_RETURN(modification_of_pic_nums_idc == 3);
831 return kOk;
834 H264Parser::Result H264Parser::ParseRefPicListModifications(
835 H264SliceHeader* shdr) {
836 Result res;
838 if (!shdr->IsISlice() && !shdr->IsSISlice()) {
839 READ_BOOL_OR_RETURN(&shdr->ref_pic_list_modification_flag_l0);
840 if (shdr->ref_pic_list_modification_flag_l0) {
841 res = ParseRefPicListModification(shdr->num_ref_idx_l0_active_minus1,
842 shdr->ref_list_l0_modifications);
843 if (res != kOk)
844 return res;
848 if (shdr->IsBSlice()) {
849 READ_BOOL_OR_RETURN(&shdr->ref_pic_list_modification_flag_l1);
850 if (shdr->ref_pic_list_modification_flag_l1) {
851 res = ParseRefPicListModification(shdr->num_ref_idx_l1_active_minus1,
852 shdr->ref_list_l1_modifications);
853 if (res != kOk)
854 return res;
858 return kOk;
861 H264Parser::Result H264Parser::ParseWeightingFactors(
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) {
868 int def_luma_weight = 1 << luma_log2_weight_denom;
869 int def_chroma_weight = 1 << chroma_log2_weight_denom;
871 for (int i = 0; i < num_ref_idx_active_minus1 + 1; ++i) {
872 READ_BOOL_OR_RETURN(&w_facts->luma_weight_flag);
873 if (w_facts->luma_weight_flag) {
874 READ_SE_OR_RETURN(&w_facts->luma_weight[i]);
875 IN_RANGE_OR_RETURN(w_facts->luma_weight[i], -128, 127);
877 READ_SE_OR_RETURN(&w_facts->luma_offset[i]);
878 IN_RANGE_OR_RETURN(w_facts->luma_offset[i], -128, 127);
879 } else {
880 w_facts->luma_weight[i] = def_luma_weight;
881 w_facts->luma_offset[i] = 0;
884 if (chroma_array_type != 0) {
885 READ_BOOL_OR_RETURN(&w_facts->chroma_weight_flag);
886 if (w_facts->chroma_weight_flag) {
887 for (int j = 0; j < 2; ++j) {
888 READ_SE_OR_RETURN(&w_facts->chroma_weight[i][j]);
889 IN_RANGE_OR_RETURN(w_facts->chroma_weight[i][j], -128, 127);
891 READ_SE_OR_RETURN(&w_facts->chroma_offset[i][j]);
892 IN_RANGE_OR_RETURN(w_facts->chroma_offset[i][j], -128, 127);
894 } else {
895 for (int j = 0; j < 2; ++j) {
896 w_facts->chroma_weight[i][j] = def_chroma_weight;
897 w_facts->chroma_offset[i][j] = 0;
903 return kOk;
906 H264Parser::Result H264Parser::ParsePredWeightTable(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);
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);
915 Result res = ParseWeightingFactors(shdr->num_ref_idx_l0_active_minus1,
916 sps.chroma_array_type,
917 shdr->luma_log2_weight_denom,
918 shdr->chroma_log2_weight_denom,
919 &shdr->pred_weight_table_l0);
920 if (res != kOk)
921 return res;
923 if (shdr->IsBSlice()) {
924 res = ParseWeightingFactors(shdr->num_ref_idx_l1_active_minus1,
925 sps.chroma_array_type,
926 shdr->luma_log2_weight_denom,
927 shdr->chroma_log2_weight_denom,
928 &shdr->pred_weight_table_l1);
929 if (res != kOk)
930 return res;
933 return kOk;
936 H264Parser::Result H264Parser::ParseDecRefPicMarking(H264SliceHeader* shdr) {
937 if (shdr->idr_pic_flag) {
938 READ_BOOL_OR_RETURN(&shdr->no_output_of_prior_pics_flag);
939 READ_BOOL_OR_RETURN(&shdr->long_term_reference_flag);
940 } else {
941 READ_BOOL_OR_RETURN(&shdr->adaptive_ref_pic_marking_mode_flag);
943 H264DecRefPicMarking* marking;
944 if (shdr->adaptive_ref_pic_marking_mode_flag) {
945 size_t i;
946 for (i = 0; i < arraysize(shdr->ref_pic_marking); ++i) {
947 marking = &shdr->ref_pic_marking[i];
949 READ_UE_OR_RETURN(&marking->memory_mgmnt_control_operation);
950 if (marking->memory_mgmnt_control_operation == 0)
951 break;
953 if (marking->memory_mgmnt_control_operation == 1 ||
954 marking->memory_mgmnt_control_operation == 3)
955 READ_UE_OR_RETURN(&marking->difference_of_pic_nums_minus1);
957 if (marking->memory_mgmnt_control_operation == 2)
958 READ_UE_OR_RETURN(&marking->long_term_pic_num);
960 if (marking->memory_mgmnt_control_operation == 3 ||
961 marking->memory_mgmnt_control_operation == 6)
962 READ_UE_OR_RETURN(&marking->long_term_frame_idx);
964 if (marking->memory_mgmnt_control_operation == 4)
965 READ_UE_OR_RETURN(&marking->max_long_term_frame_idx_plus1);
967 if (marking->memory_mgmnt_control_operation > 6)
968 return kInvalidStream;
971 if (i == arraysize(shdr->ref_pic_marking)) {
972 DVLOG(1) << "Ran out of dec ref pic marking fields";
973 return kUnsupportedStream;
978 return kOk;
981 H264Parser::Result H264Parser::ParseSliceHeader(const H264NALU& nalu,
982 H264SliceHeader* shdr) {
983 // See 7.4.3.
984 const H264SPS* sps;
985 const H264PPS* pps;
986 Result res;
988 memset(shdr, 0, sizeof(*shdr));
990 shdr->idr_pic_flag = (nalu.nal_unit_type == 5);
991 shdr->nal_ref_idc = nalu.nal_ref_idc;
992 shdr->nalu_data = nalu.data;
993 shdr->nalu_size = nalu.size;
995 READ_UE_OR_RETURN(&shdr->first_mb_in_slice);
996 READ_UE_OR_RETURN(&shdr->slice_type);
997 TRUE_OR_RETURN(shdr->slice_type < 10);
999 READ_UE_OR_RETURN(&shdr->pic_parameter_set_id);
1001 pps = GetPPS(shdr->pic_parameter_set_id);
1002 TRUE_OR_RETURN(pps);
1004 sps = GetSPS(pps->seq_parameter_set_id);
1005 TRUE_OR_RETURN(sps);
1007 if (sps->separate_colour_plane_flag) {
1008 DVLOG(1) << "Interlaced streams not supported";
1009 return kUnsupportedStream;
1012 READ_BITS_OR_RETURN(sps->log2_max_frame_num_minus4 + 4, &shdr->frame_num);
1013 if (!sps->frame_mbs_only_flag) {
1014 READ_BOOL_OR_RETURN(&shdr->field_pic_flag);
1015 if (shdr->field_pic_flag) {
1016 DVLOG(1) << "Interlaced streams not supported";
1017 return kUnsupportedStream;
1021 if (shdr->idr_pic_flag)
1022 READ_UE_OR_RETURN(&shdr->idr_pic_id);
1024 if (sps->pic_order_cnt_type == 0) {
1025 READ_BITS_OR_RETURN(sps->log2_max_pic_order_cnt_lsb_minus4 + 4,
1026 &shdr->pic_order_cnt_lsb);
1027 if (pps->bottom_field_pic_order_in_frame_present_flag &&
1028 !shdr->field_pic_flag)
1029 READ_SE_OR_RETURN(&shdr->delta_pic_order_cnt_bottom);
1032 if (sps->pic_order_cnt_type == 1 && !sps->delta_pic_order_always_zero_flag) {
1033 READ_SE_OR_RETURN(&shdr->delta_pic_order_cnt[0]);
1034 if (pps->bottom_field_pic_order_in_frame_present_flag &&
1035 !shdr->field_pic_flag)
1036 READ_SE_OR_RETURN(&shdr->delta_pic_order_cnt[1]);
1039 if (pps->redundant_pic_cnt_present_flag) {
1040 READ_UE_OR_RETURN(&shdr->redundant_pic_cnt);
1041 TRUE_OR_RETURN(shdr->redundant_pic_cnt < 128);
1044 if (shdr->IsBSlice())
1045 READ_BOOL_OR_RETURN(&shdr->direct_spatial_mv_pred_flag);
1047 if (shdr->IsPSlice() || shdr->IsSPSlice() || shdr->IsBSlice()) {
1048 READ_BOOL_OR_RETURN(&shdr->num_ref_idx_active_override_flag);
1049 if (shdr->num_ref_idx_active_override_flag) {
1050 READ_UE_OR_RETURN(&shdr->num_ref_idx_l0_active_minus1);
1051 if (shdr->IsBSlice())
1052 READ_UE_OR_RETURN(&shdr->num_ref_idx_l1_active_minus1);
1053 } else {
1054 shdr->num_ref_idx_l0_active_minus1 =
1055 pps->num_ref_idx_l0_default_active_minus1;
1056 if (shdr->IsBSlice()) {
1057 shdr->num_ref_idx_l1_active_minus1 =
1058 pps->num_ref_idx_l1_default_active_minus1;
1062 if (shdr->field_pic_flag) {
1063 TRUE_OR_RETURN(shdr->num_ref_idx_l0_active_minus1 < 32);
1064 TRUE_OR_RETURN(shdr->num_ref_idx_l1_active_minus1 < 32);
1065 } else {
1066 TRUE_OR_RETURN(shdr->num_ref_idx_l0_active_minus1 < 16);
1067 TRUE_OR_RETURN(shdr->num_ref_idx_l1_active_minus1 < 16);
1070 if (nalu.nal_unit_type == H264NALU::kCodedSliceExtension) {
1071 return kUnsupportedStream;
1072 } else {
1073 res = ParseRefPicListModifications(shdr);
1074 if (res != kOk)
1075 return res;
1078 if ((pps->weighted_pred_flag && (shdr->IsPSlice() || shdr->IsSPSlice())) ||
1079 (pps->weighted_bipred_idc == 1 && shdr->IsBSlice())) {
1080 res = ParsePredWeightTable(*sps, shdr);
1081 if (res != kOk)
1082 return res;
1085 if (nalu.nal_ref_idc != 0) {
1086 res = ParseDecRefPicMarking(shdr);
1087 if (res != kOk)
1088 return res;
1091 if (pps->entropy_coding_mode_flag && !shdr->IsISlice() &&
1092 !shdr->IsSISlice()) {
1093 READ_UE_OR_RETURN(&shdr->cabac_init_idc);
1094 TRUE_OR_RETURN(shdr->cabac_init_idc < 3);
1097 READ_SE_OR_RETURN(&shdr->slice_qp_delta);
1099 if (shdr->IsSPSlice() || shdr->IsSISlice()) {
1100 if (shdr->IsSPSlice())
1101 READ_BOOL_OR_RETURN(&shdr->sp_for_switch_flag);
1102 READ_SE_OR_RETURN(&shdr->slice_qs_delta);
1105 if (pps->deblocking_filter_control_present_flag) {
1106 READ_UE_OR_RETURN(&shdr->disable_deblocking_filter_idc);
1107 TRUE_OR_RETURN(shdr->disable_deblocking_filter_idc < 3);
1109 if (shdr->disable_deblocking_filter_idc != 1) {
1110 READ_SE_OR_RETURN(&shdr->slice_alpha_c0_offset_div2);
1111 IN_RANGE_OR_RETURN(shdr->slice_alpha_c0_offset_div2, -6, 6);
1113 READ_SE_OR_RETURN(&shdr->slice_beta_offset_div2);
1114 IN_RANGE_OR_RETURN(shdr->slice_beta_offset_div2, -6, 6);
1118 if (pps->num_slice_groups_minus1 > 0) {
1119 DVLOG(1) << "Slice groups not supported";
1120 return kUnsupportedStream;
1123 size_t epb = br_.NumEmulationPreventionBytesRead();
1124 shdr->header_bit_size = (shdr->nalu_size - epb) * 8 - br_.NumBitsLeft();
1126 return kOk;
1129 H264Parser::Result H264Parser::ParseSEI(H264SEIMessage* sei_msg) {
1130 int byte;
1132 memset(sei_msg, 0, sizeof(*sei_msg));
1134 READ_BITS_OR_RETURN(8, &byte);
1135 while (byte == 0xff) {
1136 sei_msg->type += 255;
1137 READ_BITS_OR_RETURN(8, &byte);
1139 sei_msg->type += byte;
1141 READ_BITS_OR_RETURN(8, &byte);
1142 while (byte == 0xff) {
1143 sei_msg->payload_size += 255;
1144 READ_BITS_OR_RETURN(8, &byte);
1146 sei_msg->payload_size += byte;
1148 DVLOG(4) << "Found SEI message type: " << sei_msg->type
1149 << " payload size: " << sei_msg->payload_size;
1151 switch (sei_msg->type) {
1152 case H264SEIMessage::kSEIRecoveryPoint:
1153 READ_UE_OR_RETURN(&sei_msg->recovery_point.recovery_frame_cnt);
1154 READ_BOOL_OR_RETURN(&sei_msg->recovery_point.exact_match_flag);
1155 READ_BOOL_OR_RETURN(&sei_msg->recovery_point.broken_link_flag);
1156 READ_BITS_OR_RETURN(2, &sei_msg->recovery_point.changing_slice_group_idc);
1157 break;
1159 default:
1160 DVLOG(4) << "Unsupported SEI message";
1161 break;
1164 return kOk;
1167 } // namespace media