Skip to main content

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