blob: 9b95d12e4350138894c00893d441fb1e490e2892 [file] [log] [blame]
qwu16972f2832023-08-15 09:16:541/*
2 * Copyright (c) 2023 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#include "common_video/h265/h265_bitstream_parser.h"
11
12#include <stdlib.h>
13
14#include <cstdint>
qwu16a9ef1272024-01-17 01:34:5215#include <limits>
qwu16972f2832023-08-15 09:16:5416#include <vector>
17
18#include "common_video/h265/h265_common.h"
19#include "rtc_base/bit_buffer.h"
20#include "rtc_base/bitstream_reader.h"
21#include "rtc_base/logging.h"
22
23#define IN_RANGE_OR_RETURN(val, min, max) \
24 do { \
25 if (!slice_reader.Ok() || (val) < (min) || (val) > (max)) { \
26 RTC_LOG(LS_WARNING) << "Error in stream: invalid value, expected " #val \
27 " to be" \
28 << " in range [" << (min) << ":" << (max) << "]" \
29 << " found " << (val) << " instead"; \
30 return kInvalidStream; \
31 } \
32 } while (0)
33
34#define IN_RANGE_OR_RETURN_NULL(val, min, max) \
35 do { \
36 if (!slice_reader.Ok() || (val) < (min) || (val) > (max)) { \
37 RTC_LOG(LS_WARNING) << "Error in stream: invalid value, expected " #val \
38 " to be" \
39 << " in range [" << (min) << ":" << (max) << "]" \
40 << " found " << (val) << " instead"; \
41 return absl::nullopt; \
42 } \
43 } while (0)
44
45#define IN_RANGE_OR_RETURN_VOID(val, min, max) \
46 do { \
47 if (!slice_reader.Ok() || (val) < (min) || (val) > (max)) { \
48 RTC_LOG(LS_WARNING) << "Error in stream: invalid value, expected " #val \
49 " to be" \
50 << " in range [" << (min) << ":" << (max) << "]" \
51 << " found " << (val) << " instead"; \
52 return; \
53 } \
54 } while (0)
55
56#define TRUE_OR_RETURN(a) \
57 do { \
58 if (!slice_reader.Ok() || !(a)) { \
59 RTC_LOG(LS_WARNING) << "Error in stream: invalid value, expected " \
60 << #a; \
61 return kInvalidStream; \
62 } \
63 } while (0)
64
65namespace {
66
67constexpr int kMaxAbsQpDeltaValue = 51;
68constexpr int kMinQpValue = 0;
69constexpr int kMaxQpValue = 51;
70constexpr int kMaxRefIdxActive = 15;
71
72} // namespace
73
74namespace webrtc {
75
76H265BitstreamParser::H265BitstreamParser() = default;
77H265BitstreamParser::~H265BitstreamParser() = default;
78
79// General note: this is based off the 08/2021 version of the H.265 standard,
80// section 7.3.6.1. You can find it on this page:
81// http://www.itu.int/rec/T-REC-H.265
82H265BitstreamParser::Result H265BitstreamParser::ParseNonParameterSetNalu(
83 const uint8_t* source,
84 size_t source_length,
85 uint8_t nalu_type) {
86 last_slice_qp_delta_ = absl::nullopt;
87 last_slice_pps_id_ = absl::nullopt;
88 const std::vector<uint8_t> slice_rbsp =
89 H265::ParseRbsp(source, source_length);
90 if (slice_rbsp.size() < H265::kNaluHeaderSize)
91 return kInvalidStream;
92
93 BitstreamReader slice_reader(slice_rbsp);
94 slice_reader.ConsumeBits(H265::kNaluHeaderSize * 8);
95
96 // first_slice_segment_in_pic_flag: u(1)
97 bool first_slice_segment_in_pic_flag = slice_reader.Read<bool>();
98 bool irap_pic = (H265::NaluType::kBlaWLp <= nalu_type &&
99 nalu_type <= H265::NaluType::kRsvIrapVcl23);
100 if (irap_pic) {
101 // no_output_of_prior_pics_flag: u(1)
102 slice_reader.ConsumeBits(1);
103 }
104 // slice_pic_parameter_set_id: ue(v)
105 uint32_t pps_id = slice_reader.ReadExponentialGolomb();
106 IN_RANGE_OR_RETURN(pps_id, 0, 63);
107 const H265PpsParser::PpsState* pps = GetPPS(pps_id);
108 TRUE_OR_RETURN(pps);
109 const H265SpsParser::SpsState* sps = GetSPS(pps->sps_id);
110 TRUE_OR_RETURN(sps);
111 bool dependent_slice_segment_flag = 0;
112 if (!first_slice_segment_in_pic_flag) {
113 if (pps->dependent_slice_segments_enabled_flag) {
114 // dependent_slice_segment_flag: u(1)
115 dependent_slice_segment_flag = slice_reader.Read<bool>();
116 }
117
118 // slice_segment_address: u(v)
119 int32_t log2_ctb_size_y = sps->log2_min_luma_coding_block_size_minus3 + 3 +
120 sps->log2_diff_max_min_luma_coding_block_size;
121 uint32_t ctb_size_y = 1 << log2_ctb_size_y;
122 uint32_t pic_width_in_ctbs_y = sps->pic_width_in_luma_samples / ctb_size_y;
123 if (sps->pic_width_in_luma_samples % ctb_size_y)
124 pic_width_in_ctbs_y++;
125
126 uint32_t pic_height_in_ctbs_y =
127 sps->pic_height_in_luma_samples / ctb_size_y;
128 if (sps->pic_height_in_luma_samples % ctb_size_y)
129 pic_height_in_ctbs_y++;
130
131 uint32_t slice_segment_address_bits =
132 H265::Log2Ceiling(pic_height_in_ctbs_y * pic_width_in_ctbs_y);
qwu16a9ef1272024-01-17 01:34:52133 TRUE_OR_RETURN(slice_segment_address_bits !=
134 std::numeric_limits<uint32_t>::max());
qwu16972f2832023-08-15 09:16:54135 slice_reader.ConsumeBits(slice_segment_address_bits);
136 }
137
138 if (dependent_slice_segment_flag == 0) {
139 for (uint32_t i = 0; i < pps->num_extra_slice_header_bits; i++) {
140 // slice_reserved_flag: u(1)
141 slice_reader.ConsumeBits(1);
142 }
143 // slice_type: ue(v)
qwu168db88242023-09-26 06:23:52144 uint32_t slice_type = slice_reader.ReadExponentialGolomb();
qwu16972f2832023-08-15 09:16:54145 IN_RANGE_OR_RETURN(slice_type, 0, 2);
146 if (pps->output_flag_present_flag) {
147 // pic_output_flag: u(1)
148 slice_reader.ConsumeBits(1);
149 }
150 if (sps->separate_colour_plane_flag) {
151 // colour_plane_id: u(2)
152 slice_reader.ConsumeBits(2);
153 }
154 uint32_t num_long_term_sps = 0;
155 uint32_t num_long_term_pics = 0;
qwu16972f2832023-08-15 09:16:54156 std::vector<bool> used_by_curr_pic_lt_flag;
157 bool short_term_ref_pic_set_sps_flag = false;
158 uint32_t short_term_ref_pic_set_idx = 0;
159 H265SpsParser::ShortTermRefPicSet short_term_ref_pic_set;
160 bool slice_temporal_mvp_enabled_flag = 0;
161 if (nalu_type != H265::NaluType::kIdrWRadl &&
162 nalu_type != H265::NaluType::kIdrNLp) {
163 // slice_pic_order_cnt_lsb: u(v)
164 uint32_t slice_pic_order_cnt_lsb_bits =
165 sps->log2_max_pic_order_cnt_lsb_minus4 + 4;
166 slice_reader.ConsumeBits(slice_pic_order_cnt_lsb_bits);
167 // short_term_ref_pic_set_sps_flag: u(1)
168 short_term_ref_pic_set_sps_flag = slice_reader.Read<bool>();
169 if (!short_term_ref_pic_set_sps_flag) {
170 absl::optional<H265SpsParser::ShortTermRefPicSet> ref_pic_set =
171 H265SpsParser::ParseShortTermRefPicSet(
172 sps->num_short_term_ref_pic_sets,
173 sps->num_short_term_ref_pic_sets, sps->short_term_ref_pic_set,
174 sps->sps_max_dec_pic_buffering_minus1
175 [sps->sps_max_sub_layers_minus1],
176 slice_reader);
177 TRUE_OR_RETURN(ref_pic_set);
178 short_term_ref_pic_set = *ref_pic_set;
179
180 } else if (sps->num_short_term_ref_pic_sets > 1) {
181 // short_term_ref_pic_set_idx: u(v)
182 uint32_t short_term_ref_pic_set_idx_bits =
183 H265::Log2Ceiling(sps->num_short_term_ref_pic_sets);
184 if ((1 << short_term_ref_pic_set_idx_bits) <
185 sps->num_short_term_ref_pic_sets) {
186 short_term_ref_pic_set_idx_bits++;
187 }
188 if (short_term_ref_pic_set_idx_bits > 0) {
189 short_term_ref_pic_set_idx =
190 slice_reader.ReadBits(short_term_ref_pic_set_idx_bits);
qwu168be04f42023-09-04 02:15:57191 IN_RANGE_OR_RETURN(short_term_ref_pic_set_idx, 0,
192 sps->num_short_term_ref_pic_sets - 1);
qwu16972f2832023-08-15 09:16:54193 }
194 }
195 if (sps->long_term_ref_pics_present_flag) {
196 if (sps->num_long_term_ref_pics_sps > 0) {
197 // num_long_term_sps: ue(v)
198 num_long_term_sps = slice_reader.ReadExponentialGolomb();
199 IN_RANGE_OR_RETURN(num_long_term_sps, 0,
200 sps->num_long_term_ref_pics_sps);
201 }
202 // num_long_term_pics: ue(v)
203 num_long_term_pics = slice_reader.ReadExponentialGolomb();
204 IN_RANGE_OR_RETURN(num_long_term_pics, 0,
205 kMaxLongTermRefPicSets - num_long_term_sps);
qwu16972f2832023-08-15 09:16:54206 used_by_curr_pic_lt_flag.resize(num_long_term_sps + num_long_term_pics,
207 0);
qwu16972f2832023-08-15 09:16:54208 for (uint32_t i = 0; i < num_long_term_sps + num_long_term_pics; i++) {
209 if (i < num_long_term_sps) {
qwu168be04f42023-09-04 02:15:57210 uint32_t lt_idx_sps = 0;
qwu16972f2832023-08-15 09:16:54211 if (sps->num_long_term_ref_pics_sps > 1) {
212 // lt_idx_sps: u(v)
qwu168be04f42023-09-04 02:15:57213 uint32_t lt_idx_sps_bits =
qwu16972f2832023-08-15 09:16:54214 H265::Log2Ceiling(sps->num_long_term_ref_pics_sps);
qwu168be04f42023-09-04 02:15:57215 lt_idx_sps = slice_reader.ReadBits(lt_idx_sps_bits);
216 IN_RANGE_OR_RETURN(lt_idx_sps, 0,
217 sps->num_long_term_ref_pics_sps - 1);
qwu16972f2832023-08-15 09:16:54218 }
qwu16972f2832023-08-15 09:16:54219 used_by_curr_pic_lt_flag[i] =
qwu168be04f42023-09-04 02:15:57220 sps->used_by_curr_pic_lt_sps_flag[lt_idx_sps];
qwu16972f2832023-08-15 09:16:54221 } else {
222 // poc_lsb_lt: u(v)
223 uint32_t poc_lsb_lt_bits =
224 sps->log2_max_pic_order_cnt_lsb_minus4 + 4;
qwu168be04f42023-09-04 02:15:57225 slice_reader.ConsumeBits(poc_lsb_lt_bits);
qwu16972f2832023-08-15 09:16:54226 // used_by_curr_pic_lt_flag: u(1)
227 used_by_curr_pic_lt_flag[i] = slice_reader.Read<bool>();
228 }
229 // delta_poc_msb_present_flag: u(1)
230 bool delta_poc_msb_present_flag = slice_reader.Read<bool>();
231 if (delta_poc_msb_present_flag) {
232 // delta_poc_msb_cycle_lt: ue(v)
233 int delta_poc_msb_cycle_lt = slice_reader.ReadExponentialGolomb();
234 IN_RANGE_OR_RETURN(
235 delta_poc_msb_cycle_lt, 0,
236 std::pow(2, 32 - sps->log2_max_pic_order_cnt_lsb_minus4 - 4));
237 }
238 }
239 }
240 if (sps->sps_temporal_mvp_enabled_flag) {
241 // slice_temporal_mvp_enabled_flag: u(1)
242 slice_temporal_mvp_enabled_flag = slice_reader.Read<bool>();
243 }
244 }
245
246 if (sps->sample_adaptive_offset_enabled_flag) {
247 // slice_sao_luma_flag: u(1)
248 slice_reader.ConsumeBits(1);
249 uint32_t chroma_array_type =
250 sps->separate_colour_plane_flag == 0 ? sps->chroma_format_idc : 0;
251 if (chroma_array_type != 0) {
252 // slice_sao_chroma_flag: u(1)
253 slice_reader.ConsumeBits(1);
254 }
255 }
256
257 if (slice_type == H265::SliceType::kP ||
258 slice_type == H265::SliceType::kB) {
259 // num_ref_idx_active_override_flag: u(1)
260 bool num_ref_idx_active_override_flag = slice_reader.Read<bool>();
261 uint32_t num_ref_idx_l0_active_minus1 =
262 pps->num_ref_idx_l0_default_active_minus1;
263 uint32_t num_ref_idx_l1_active_minus1 =
264 pps->num_ref_idx_l1_default_active_minus1;
265 if (num_ref_idx_active_override_flag) {
266 // num_ref_idx_l0_active_minus1: ue(v)
267 num_ref_idx_l0_active_minus1 = slice_reader.ReadExponentialGolomb();
268 IN_RANGE_OR_RETURN(num_ref_idx_l0_active_minus1, 0,
269 kMaxRefIdxActive - 1);
270 if (slice_type == H265::SliceType::kB) {
271 // num_ref_idx_l1_active_minus1: ue(v)
272 num_ref_idx_l1_active_minus1 = slice_reader.ReadExponentialGolomb();
273 IN_RANGE_OR_RETURN(num_ref_idx_l1_active_minus1, 0,
274 kMaxRefIdxActive - 1);
275 }
276 }
277
278 uint32_t num_pic_total_curr = 0;
qwu168db88242023-09-26 06:23:52279 uint32_t curr_sps_idx = 0;
qwu16972f2832023-08-15 09:16:54280 if (short_term_ref_pic_set_sps_flag) {
281 curr_sps_idx = short_term_ref_pic_set_idx;
282 } else {
283 curr_sps_idx = sps->num_short_term_ref_pic_sets;
284 }
285 if (sps->short_term_ref_pic_set.size() <= curr_sps_idx) {
286 TRUE_OR_RETURN(!(curr_sps_idx != 0 || short_term_ref_pic_set_sps_flag));
287 }
288 const H265SpsParser::ShortTermRefPicSet* ref_pic_set;
289 if (curr_sps_idx < sps->short_term_ref_pic_set.size()) {
290 ref_pic_set = &(sps->short_term_ref_pic_set[curr_sps_idx]);
291 } else {
292 ref_pic_set = &short_term_ref_pic_set;
293 }
294
295 // Equation 7-57
qwu16a586d4e2023-08-21 07:58:15296 IN_RANGE_OR_RETURN(ref_pic_set->num_negative_pics, 0,
297 kMaxShortTermRefPicSets);
298 IN_RANGE_OR_RETURN(ref_pic_set->num_positive_pics, 0,
299 kMaxShortTermRefPicSets);
qwu16972f2832023-08-15 09:16:54300 for (uint32_t i = 0; i < ref_pic_set->num_negative_pics; i++) {
301 if (ref_pic_set->used_by_curr_pic_s0[i]) {
302 num_pic_total_curr++;
303 }
304 }
305 for (uint32_t i = 0; i < ref_pic_set->num_positive_pics; i++) {
306 if (ref_pic_set->used_by_curr_pic_s1[i]) {
307 num_pic_total_curr++;
308 }
309 }
310 for (uint32_t i = 0; i < num_long_term_sps + num_long_term_pics; i++) {
311 if (used_by_curr_pic_lt_flag[i]) {
312 num_pic_total_curr++;
313 }
314 }
315
316 if (pps->lists_modification_present_flag && num_pic_total_curr > 1) {
317 // ref_pic_lists_modification()
318 uint32_t list_entry_bits = H265::Log2Ceiling(num_pic_total_curr);
319 if ((1 << list_entry_bits) < num_pic_total_curr) {
320 list_entry_bits++;
321 }
322 // ref_pic_list_modification_flag_l0: u(1)
323 bool ref_pic_list_modification_flag_l0 = slice_reader.Read<bool>();
324 if (ref_pic_list_modification_flag_l0) {
325 for (uint32_t i = 0; i < num_ref_idx_l0_active_minus1; i++) {
326 // list_entry_l0: u(v)
327 slice_reader.ConsumeBits(list_entry_bits);
328 }
329 }
330 if (slice_type == H265::SliceType::kB) {
331 // ref_pic_list_modification_flag_l1: u(1)
332 bool ref_pic_list_modification_flag_l1 = slice_reader.Read<bool>();
333 if (ref_pic_list_modification_flag_l1) {
334 for (uint32_t i = 0; i < num_ref_idx_l1_active_minus1; i++) {
335 // list_entry_l1: u(v)
336 slice_reader.ConsumeBits(list_entry_bits);
337 }
338 }
339 }
340 }
341 if (slice_type == H265::SliceType::kB) {
342 // mvd_l1_zero_flag: u(1)
343 slice_reader.ConsumeBits(1);
344 }
345 if (pps->cabac_init_present_flag) {
346 // cabac_init_flag: u(1)
347 slice_reader.ConsumeBits(1);
348 }
349 if (slice_temporal_mvp_enabled_flag) {
350 bool collocated_from_l0_flag = false;
351 if (slice_type == H265::SliceType::kB) {
352 // collocated_from_l0_flag: u(1)
353 collocated_from_l0_flag = slice_reader.Read<bool>();
354 }
355 if ((collocated_from_l0_flag && num_ref_idx_l0_active_minus1 > 0) ||
356 (!collocated_from_l0_flag && num_ref_idx_l1_active_minus1 > 0)) {
357 // collocated_ref_idx: ue(v)
358 uint32_t collocated_ref_idx = slice_reader.ReadExponentialGolomb();
359 if ((slice_type == H265::SliceType::kP ||
360 slice_type == H265::SliceType::kB) &&
361 collocated_from_l0_flag) {
362 IN_RANGE_OR_RETURN(collocated_ref_idx, 0,
363 num_ref_idx_l0_active_minus1);
364 }
365 if (slice_type == H265::SliceType::kB && !collocated_from_l0_flag) {
366 IN_RANGE_OR_RETURN(collocated_ref_idx, 0,
367 num_ref_idx_l1_active_minus1);
368 }
369 }
370 }
371 if (!slice_reader.Ok() ||
372 ((pps->weighted_pred_flag && slice_type == H265::SliceType::kP) ||
373 (pps->weighted_bipred_flag && slice_type == H265::SliceType::kB))) {
374 // pred_weight_table()
375 RTC_LOG(LS_ERROR) << "Streams with pred_weight_table unsupported.";
376 return kUnsupportedStream;
377 }
378 // five_minus_max_num_merge_cand: ue(v)
qwu168be04f42023-09-04 02:15:57379 uint32_t five_minus_max_num_merge_cand =
380 slice_reader.ReadExponentialGolomb();
qwu16972f2832023-08-15 09:16:54381 IN_RANGE_OR_RETURN(5 - five_minus_max_num_merge_cand, 1, 5);
382 }
383 }
384
385 // slice_qp_delta: se(v)
386 int32_t last_slice_qp_delta = slice_reader.ReadSignedExponentialGolomb();
qwu16972f2832023-08-15 09:16:54387 if (!slice_reader.Ok() || (abs(last_slice_qp_delta) > kMaxAbsQpDeltaValue)) {
388 // Something has gone wrong, and the parsed value is invalid.
qwu168be04f42023-09-04 02:15:57389 RTC_LOG(LS_ERROR) << "Parsed QP value out of range.";
qwu16972f2832023-08-15 09:16:54390 return kInvalidStream;
391 }
qwu168be04f42023-09-04 02:15:57392 // 7-54 in H265 spec.
393 IN_RANGE_OR_RETURN(26 + pps->init_qp_minus26 + last_slice_qp_delta,
394 -pps->qp_bd_offset_y, 51);
qwu16972f2832023-08-15 09:16:54395
396 last_slice_qp_delta_ = last_slice_qp_delta;
397 last_slice_pps_id_ = pps_id;
398 if (!slice_reader.Ok()) {
399 return kInvalidStream;
400 }
401
402 return kOk;
403}
404
405const H265PpsParser::PpsState* H265BitstreamParser::GetPPS(uint32_t id) const {
406 auto it = pps_.find(id);
407 if (it == pps_.end()) {
408 RTC_LOG(LS_WARNING) << "Requested a nonexistent PPS id " << id;
409 return nullptr;
410 }
411
412 return &it->second;
413}
414
415const H265SpsParser::SpsState* H265BitstreamParser::GetSPS(uint32_t id) const {
416 auto it = sps_.find(id);
417 if (it == sps_.end()) {
418 RTC_LOG(LS_WARNING) << "Requested a nonexistent SPS id " << id;
419 return nullptr;
420 }
421
422 return &it->second;
423}
424
425void H265BitstreamParser::ParseSlice(const uint8_t* slice, size_t length) {
426 H265::NaluType nalu_type = H265::ParseNaluType(slice[0]);
427 switch (nalu_type) {
428 case H265::NaluType::kVps: {
429 absl::optional<H265VpsParser::VpsState> vps_state;
430 if (length >= H265::kNaluHeaderSize) {
431 vps_state = H265VpsParser::ParseVps(slice + H265::kNaluHeaderSize,
432 length - H265::kNaluHeaderSize);
433 }
434
435 if (!vps_state) {
436 RTC_LOG(LS_WARNING) << "Unable to parse VPS from H265 bitstream.";
437 } else {
438 vps_[vps_state->id] = *vps_state;
439 }
440 break;
441 }
442 case H265::NaluType::kSps: {
443 absl::optional<H265SpsParser::SpsState> sps_state;
444 if (length >= H265::kNaluHeaderSize) {
445 sps_state = H265SpsParser::ParseSps(slice + H265::kNaluHeaderSize,
446 length - H265::kNaluHeaderSize);
447 }
448 if (!sps_state) {
449 RTC_LOG(LS_WARNING) << "Unable to parse SPS from H265 bitstream.";
450 } else {
451 sps_[sps_state->sps_id] = *sps_state;
452 }
453 break;
454 }
455 case H265::NaluType::kPps: {
456 absl::optional<H265PpsParser::PpsState> pps_state;
457 if (length >= H265::kNaluHeaderSize) {
458 std::vector<uint8_t> unpacked_buffer = H265::ParseRbsp(
459 slice + H265::kNaluHeaderSize, length - H265::kNaluHeaderSize);
460 BitstreamReader slice_reader(unpacked_buffer);
461 // pic_parameter_set_id: ue(v)
462 uint32_t pps_id = slice_reader.ReadExponentialGolomb();
463 IN_RANGE_OR_RETURN_VOID(pps_id, 0, 63);
464 // seq_parameter_set_id: ue(v)
465 uint32_t sps_id = slice_reader.ReadExponentialGolomb();
466 IN_RANGE_OR_RETURN_VOID(sps_id, 0, 15);
467 const H265SpsParser::SpsState* sps = GetSPS(sps_id);
468 pps_state = H265PpsParser::ParsePps(
469 slice + H265::kNaluHeaderSize, length - H265::kNaluHeaderSize, sps);
470 }
471 if (!pps_state) {
472 RTC_LOG(LS_WARNING) << "Unable to parse PPS from H265 bitstream.";
473 } else {
474 pps_[pps_state->pps_id] = *pps_state;
475 }
476 break;
477 }
478 case H265::NaluType::kAud:
479 case H265::NaluType::kPrefixSei:
480 case H265::NaluType::kSuffixSei:
qwu16bd396fd2023-10-26 08:52:22481 case H265::NaluType::kAp:
482 case H265::NaluType::kFu:
qwu16972f2832023-08-15 09:16:54483 break;
484 default:
485 Result res = ParseNonParameterSetNalu(slice, length, nalu_type);
486 if (res != kOk) {
487 RTC_LOG(LS_INFO) << "Failed to parse bitstream. Error: " << res;
488 }
489 break;
490 }
491}
492
493absl::optional<uint32_t>
494H265BitstreamParser::ParsePpsIdFromSliceSegmentLayerRbsp(const uint8_t* data,
495 size_t length,
496 uint8_t nalu_type) {
497 std::vector<uint8_t> unpacked_buffer = H265::ParseRbsp(data, length);
498 BitstreamReader slice_reader(unpacked_buffer);
499
500 // first_slice_segment_in_pic_flag: u(1)
501 slice_reader.ConsumeBits(1);
502 if (!slice_reader.Ok()) {
503 return absl::nullopt;
504 }
505
506 if (nalu_type >= H265::NaluType::kBlaWLp &&
507 nalu_type <= H265::NaluType::kRsvIrapVcl23) {
508 // no_output_of_prior_pics_flag: u(1)
509 slice_reader.ConsumeBits(1);
510 }
511
512 // slice_pic_parameter_set_id: ue(v)
513 uint32_t slice_pic_parameter_set_id = slice_reader.ReadExponentialGolomb();
514 IN_RANGE_OR_RETURN_NULL(slice_pic_parameter_set_id, 0, 63);
515 if (!slice_reader.Ok()) {
516 return absl::nullopt;
517 }
518
519 return slice_pic_parameter_set_id;
520}
521
522void H265BitstreamParser::ParseBitstream(
523 rtc::ArrayView<const uint8_t> bitstream) {
524 std::vector<H265::NaluIndex> nalu_indices =
525 H265::FindNaluIndices(bitstream.data(), bitstream.size());
526 for (const H265::NaluIndex& index : nalu_indices)
527 ParseSlice(&bitstream[index.payload_start_offset], index.payload_size);
528}
529
530absl::optional<int> H265BitstreamParser::GetLastSliceQp() const {
531 if (!last_slice_qp_delta_ || !last_slice_pps_id_) {
532 return absl::nullopt;
533 }
Qiu Jianlincc83e322024-01-31 03:13:07534 const H265PpsParser::PpsState* pps = GetPPS(last_slice_pps_id_.value());
qwu16972f2832023-08-15 09:16:54535 if (!pps)
536 return absl::nullopt;
537 const int parsed_qp = 26 + pps->init_qp_minus26 + *last_slice_qp_delta_;
538 if (parsed_qp < kMinQpValue || parsed_qp > kMaxQpValue) {
539 RTC_LOG(LS_ERROR) << "Parsed invalid QP from bitstream.";
540 return absl::nullopt;
541 }
542 return parsed_qp;
543}
544
Qiu Jianlinc32a5092024-02-23 02:34:57545absl::optional<uint32_t> H265BitstreamParser::GetLastSlicePpsId() const {
546 if (!last_slice_pps_id_) {
547 RTC_LOG(LS_ERROR) << "Failed to parse PPS id from bitstream.";
548 return absl::nullopt;
549 }
550
551 return last_slice_pps_id_;
552}
553
qwu16972f2832023-08-15 09:16:54554} // namespace webrtc