cros_codecs/codec/h265/
picture.rs

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