1 /*
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "common_video/h264/pps_parser.h"
12
13 #include <cstdint>
14 #include <limits>
15 #include <vector>
16
17 #include "absl/numeric/bits.h"
18 #include "common_video/h264/h264_common.h"
19 #include "rtc_base/bitstream_reader.h"
20 #include "rtc_base/checks.h"
21
22 namespace webrtc {
23 namespace {
24 constexpr int kMaxPicInitQpDeltaValue = 25;
25 constexpr int kMinPicInitQpDeltaValue = -26;
26 } // namespace
27
28 // General note: this is based off the 02/2014 version of the H.264 standard.
29 // You can find it on this page:
30 // http://www.itu.int/rec/T-REC-H.264
31
ParsePps(const uint8_t * data,size_t length)32 absl::optional<PpsParser::PpsState> PpsParser::ParsePps(const uint8_t* data,
33 size_t length) {
34 // First, parse out rbsp, which is basically the source buffer minus emulation
35 // bytes (the last byte of a 0x00 0x00 0x03 sequence). RBSP is defined in
36 // section 7.3.1 of the H.264 standard.
37 return ParseInternal(H264::ParseRbsp(data, length));
38 }
39
ParsePpsIds(const uint8_t * data,size_t length,uint32_t * pps_id,uint32_t * sps_id)40 bool PpsParser::ParsePpsIds(const uint8_t* data,
41 size_t length,
42 uint32_t* pps_id,
43 uint32_t* sps_id) {
44 RTC_DCHECK(pps_id);
45 RTC_DCHECK(sps_id);
46 // First, parse out rbsp, which is basically the source buffer minus emulation
47 // bytes (the last byte of a 0x00 0x00 0x03 sequence). RBSP is defined in
48 // section 7.3.1 of the H.264 standard.
49 std::vector<uint8_t> unpacked_buffer = H264::ParseRbsp(data, length);
50 BitstreamReader reader(unpacked_buffer);
51 *pps_id = reader.ReadExponentialGolomb();
52 *sps_id = reader.ReadExponentialGolomb();
53 return reader.Ok();
54 }
55
ParsePpsIdFromSlice(const uint8_t * data,size_t length)56 absl::optional<uint32_t> PpsParser::ParsePpsIdFromSlice(const uint8_t* data,
57 size_t length) {
58 std::vector<uint8_t> unpacked_buffer = H264::ParseRbsp(data, length);
59 BitstreamReader slice_reader(unpacked_buffer);
60
61 // first_mb_in_slice: ue(v)
62 slice_reader.ReadExponentialGolomb();
63 // slice_type: ue(v)
64 slice_reader.ReadExponentialGolomb();
65 // pic_parameter_set_id: ue(v)
66 uint32_t slice_pps_id = slice_reader.ReadExponentialGolomb();
67 if (!slice_reader.Ok()) {
68 return absl::nullopt;
69 }
70 return slice_pps_id;
71 }
72
ParseInternal(rtc::ArrayView<const uint8_t> buffer)73 absl::optional<PpsParser::PpsState> PpsParser::ParseInternal(
74 rtc::ArrayView<const uint8_t> buffer) {
75 BitstreamReader reader(buffer);
76 PpsState pps;
77 pps.id = reader.ReadExponentialGolomb();
78 pps.sps_id = reader.ReadExponentialGolomb();
79
80 // entropy_coding_mode_flag: u(1)
81 pps.entropy_coding_mode_flag = reader.Read<bool>();
82 // bottom_field_pic_order_in_frame_present_flag: u(1)
83 pps.bottom_field_pic_order_in_frame_present_flag = reader.Read<bool>();
84
85 // num_slice_groups_minus1: ue(v)
86 uint32_t num_slice_groups_minus1 = reader.ReadExponentialGolomb();
87 if (num_slice_groups_minus1 > 0) {
88 // slice_group_map_type: ue(v)
89 uint32_t slice_group_map_type = reader.ReadExponentialGolomb();
90 if (slice_group_map_type == 0) {
91 for (uint32_t i_group = 0;
92 i_group <= num_slice_groups_minus1 && reader.Ok(); ++i_group) {
93 // run_length_minus1[iGroup]: ue(v)
94 reader.ReadExponentialGolomb();
95 }
96 } else if (slice_group_map_type == 1) {
97 // TODO(sprang): Implement support for dispersed slice group map type.
98 // See 8.2.2.2 Specification for dispersed slice group map type.
99 } else if (slice_group_map_type == 2) {
100 for (uint32_t i_group = 0;
101 i_group <= num_slice_groups_minus1 && reader.Ok(); ++i_group) {
102 // top_left[iGroup]: ue(v)
103 reader.ReadExponentialGolomb();
104 // bottom_right[iGroup]: ue(v)
105 reader.ReadExponentialGolomb();
106 }
107 } else if (slice_group_map_type == 3 || slice_group_map_type == 4 ||
108 slice_group_map_type == 5) {
109 // slice_group_change_direction_flag: u(1)
110 reader.ConsumeBits(1);
111 // slice_group_change_rate_minus1: ue(v)
112 reader.ReadExponentialGolomb();
113 } else if (slice_group_map_type == 6) {
114 // pic_size_in_map_units_minus1: ue(v)
115 uint32_t pic_size_in_map_units = reader.ReadExponentialGolomb() + 1;
116 int slice_group_id_bits = 1 + absl::bit_width(num_slice_groups_minus1);
117
118 // slice_group_id: array of size pic_size_in_map_units, each element
119 // is represented by ceil(log2(num_slice_groups_minus1 + 1)) bits.
120 int64_t bits_to_consume =
121 int64_t{slice_group_id_bits} * pic_size_in_map_units;
122 if (!reader.Ok() || bits_to_consume > std::numeric_limits<int>::max()) {
123 return absl::nullopt;
124 }
125 reader.ConsumeBits(bits_to_consume);
126 }
127 }
128 // num_ref_idx_l0_default_active_minus1: ue(v)
129 reader.ReadExponentialGolomb();
130 // num_ref_idx_l1_default_active_minus1: ue(v)
131 reader.ReadExponentialGolomb();
132 // weighted_pred_flag: u(1)
133 pps.weighted_pred_flag = reader.Read<bool>();
134 // weighted_bipred_idc: u(2)
135 pps.weighted_bipred_idc = reader.ReadBits(2);
136
137 // pic_init_qp_minus26: se(v)
138 pps.pic_init_qp_minus26 = reader.ReadSignedExponentialGolomb();
139 // Sanity-check parsed value
140 if (!reader.Ok() || pps.pic_init_qp_minus26 > kMaxPicInitQpDeltaValue ||
141 pps.pic_init_qp_minus26 < kMinPicInitQpDeltaValue) {
142 return absl::nullopt;
143 }
144 // pic_init_qs_minus26: se(v)
145 reader.ReadExponentialGolomb();
146 // chroma_qp_index_offset: se(v)
147 reader.ReadExponentialGolomb();
148 // deblocking_filter_control_present_flag: u(1)
149 // constrained_intra_pred_flag: u(1)
150 reader.ConsumeBits(2);
151 // redundant_pic_cnt_present_flag: u(1)
152 pps.redundant_pic_cnt_present_flag = reader.ReadBit();
153 if (!reader.Ok()) {
154 return absl::nullopt;
155 }
156
157 return pps;
158 }
159
160 } // namespace webrtc
161