1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
// Copyright 2023 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use crate::codec::h265::parser::NaluType;
use crate::codec::h265::parser::Pps;
use crate::codec::h265::parser::Slice;
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
pub enum Reference {
#[default]
None,
ShortTerm,
LongTerm,
}
/// Data associated with an h.265 picture. Most fields are extracted from the
/// slice header and kept for future processing.
#[derive(Debug, Default, Clone, Eq, PartialEq)]
pub struct PictureData {
// Fields extracted from the slice header. These are the CamelCase
// variables, unless noted otherwise.
pub nalu_type: NaluType,
pub no_rasl_output_flag: bool,
pub pic_output_flag: bool,
pub valid_for_prev_tid0_pic: bool,
pub slice_pic_order_cnt_lsb: i32,
pub pic_order_cnt_msb: i32,
pub pic_order_cnt_val: i32,
pub no_output_of_prior_pics_flag: bool,
// Internal state.
pub is_irap: bool,
pub first_picture_after_eos: bool,
reference: Reference,
pub pic_latency_cnt: i32,
pub needed_for_output: bool,
pub short_term_ref_pic_set_size_bits: u32,
}
impl PictureData {
/// Instantiates a new `PictureData` from a slice.
///
/// See 8.1.3 Decoding process for a coded picture with nuh_layer_id equal
/// to 0.
///
/// This will also call the picture order count process (clause 8.3.1) to
/// correctly initialize the POC values.
pub fn new_from_slice(
slice: &Slice<&[u8]>,
pps: &Pps,
first_picture_in_bitstream: bool,
first_picture_after_eos: bool,
prev_tid0_pic: Option<&PictureData>,
max_pic_order_cnt_lsb: i32,
_timestamp: u64,
) -> Self {
let hdr = slice.header();
let nalu_type = slice.nalu().header().nalu_type();
let is_irap = nalu_type.is_irap();
// We assume HandleCraAsBlafFLag == 0, as it is only set through
// external means, which we do not provide.
let mut pic_order_cnt_msb = 0;
let slice_pic_order_cnt_lsb: i32 = hdr.pic_order_cnt_lsb().into();
// Compute the output flags:
// The value of NoRaslOutputFlag is equal to 1 for each IDR access
// unit, each BLA access unit, and each CRA access unit that is the
// first access unit in the bitstream in decoding order, is the first
// access unit that follows an end of sequence NAL unit in decoding
// order, or has HandleCraAsBlaFlag equal to 1.
let no_rasl_output_flag = nalu_type.is_idr()
|| nalu_type.is_bla()
|| (nalu_type.is_cra() && first_picture_in_bitstream)
|| first_picture_after_eos;
let pic_output_flag = if slice.nalu().header().nalu_type().is_rasl() && no_rasl_output_flag
{
false
} else {
hdr.pic_output_flag()
};
// Compute the Picture Order Count. See 8.3.1 Decoding Process for
// Picture Order Count
if !(is_irap && no_rasl_output_flag) {
if let Some(prev_tid0_pic) = prev_tid0_pic {
// Equation (8-1)
let prev_pic_order_cnt_lsb = prev_tid0_pic.slice_pic_order_cnt_lsb;
let prev_pic_order_cnt_msb = prev_tid0_pic.pic_order_cnt_msb;
if (slice_pic_order_cnt_lsb < prev_pic_order_cnt_lsb)
&& (prev_pic_order_cnt_lsb - slice_pic_order_cnt_lsb)
>= (max_pic_order_cnt_lsb / 2)
{
pic_order_cnt_msb = prev_pic_order_cnt_msb + max_pic_order_cnt_lsb;
} else if (slice_pic_order_cnt_lsb > prev_pic_order_cnt_lsb)
&& (slice_pic_order_cnt_lsb - prev_pic_order_cnt_lsb)
> (max_pic_order_cnt_lsb / 2)
{
pic_order_cnt_msb = prev_pic_order_cnt_msb - max_pic_order_cnt_lsb;
} else {
pic_order_cnt_msb = prev_pic_order_cnt_msb;
}
}
}
// Compute whether this picture will be a valid prevTid0Pic, i.e.:
//
// Let prevTid0Pic be the previous picture in decoding order that has
// TemporalId equal to 0 and that is not a RASL, RADL or SLNR picture.
//
// Use this flag to correctly set up the field in the decoder during
// `finish_picture`.
let valid_for_prev_tid0_pic = pps.temporal_id() == 0
&& !nalu_type.is_radl()
&& !nalu_type.is_rasl()
&& !nalu_type.is_slnr();
let no_output_of_prior_pics_flag =
if nalu_type.is_irap() && no_rasl_output_flag && !first_picture_in_bitstream {
nalu_type.is_cra() || hdr.no_output_of_prior_pics_flag()
} else {
false
};
Self {
nalu_type,
no_rasl_output_flag,
no_output_of_prior_pics_flag,
pic_output_flag,
valid_for_prev_tid0_pic,
slice_pic_order_cnt_lsb,
pic_order_cnt_msb,
// Equation (8-2)
pic_order_cnt_val: pic_order_cnt_msb + slice_pic_order_cnt_lsb,
is_irap,
first_picture_after_eos,
reference: Default::default(),
pic_latency_cnt: 0,
needed_for_output: false,
short_term_ref_pic_set_size_bits: hdr.st_rps_bits(),
}
}
/// Whether the current picture is a reference, either ShortTerm or LongTerm.
pub fn is_ref(&self) -> bool {
!matches!(self.reference, Reference::None)
}
pub fn set_reference(&mut self, reference: Reference) {
log::debug!(
"Set reference of POC {} to {:?}",
self.pic_order_cnt_val,
reference
);
self.reference = reference;
}
pub fn reference(&self) -> &Reference {
&self.reference
}
}