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