cros_codecs/codec/h264/
picture.rs

1// Copyright 2022 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 std::cell::RefCell;
6use std::ops::Deref;
7use std::rc::Rc;
8use std::rc::Weak;
9
10use log::debug;
11
12use crate::codec::h264::parser::MaxLongTermFrameIdx;
13use crate::codec::h264::parser::RefPicMarking;
14use crate::codec::h264::parser::Slice;
15use crate::codec::h264::parser::SliceType;
16use crate::codec::h264::parser::Sps;
17use crate::Resolution;
18
19#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
20pub enum Field {
21    #[default]
22    Frame,
23    Top,
24    Bottom,
25}
26
27impl Field {
28    /// Returns the field of opposite parity.
29    pub fn opposite(&self) -> Self {
30        match *self {
31            Field::Frame => Field::Frame,
32            Field::Top => Field::Bottom,
33            Field::Bottom => Field::Top,
34        }
35    }
36}
37
38#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
39pub enum Reference {
40    #[default]
41    None,
42    ShortTerm,
43    LongTerm,
44}
45
46#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
47pub enum IsIdr {
48    #[default]
49    No,
50    Yes {
51        idr_pic_id: u16,
52    },
53}
54
55/// The rank of a field, i.e. whether it is the first or second one to be parsed from the stream.
56/// This is unrelated to the `Field` type, as the first field can be either `Top` or `Bottom`.
57#[derive(Default, Debug)]
58pub enum FieldRank {
59    /// Frame has a single field.
60    #[default]
61    Single,
62    /// Frame is interlaced, and this is the first field (with a reference to the second one).
63    First(Weak<RefCell<PictureData>>),
64    /// Frame is interlaced, and this is the second field (with a reference to the first one).
65    Second(Rc<RefCell<PictureData>>),
66}
67
68#[derive(Default)]
69pub struct PictureData {
70    pub pic_order_cnt_type: u8,
71    pub top_field_order_cnt: i32,
72    pub bottom_field_order_cnt: i32,
73    pub pic_order_cnt: i32,
74    pub pic_order_cnt_msb: i32,
75    pub pic_order_cnt_lsb: i32,
76    pub delta_pic_order_cnt_bottom: i32,
77    pub delta_pic_order_cnt0: i32,
78    pub delta_pic_order_cnt1: i32,
79
80    pub pic_num: i32,
81    pub long_term_pic_num: u32,
82    pub frame_num: u32,
83    pub frame_num_offset: u32,
84    pub frame_num_wrap: i32,
85    pub long_term_frame_idx: u32,
86
87    pub coded_resolution: Resolution,
88    pub display_resolution: Resolution,
89
90    pub type_: SliceType,
91    pub nal_ref_idc: u8,
92    pub is_idr: IsIdr,
93    reference: Reference,
94    pub ref_pic_list_modification_flag_l0: i32,
95    pub abs_diff_pic_num_minus1: i32,
96
97    // Does memory management op 5 needs to be executed after this
98    // picture has finished decoding?
99    pub has_mmco_5: bool,
100
101    // Created by the decoding process for gaps in frame_num.
102    // Not for decode or output.
103    pub nonexisting: bool,
104
105    pub field: Field,
106
107    // Values from slice_hdr to be used during reference marking and
108    // memory management after finishing this picture.
109    pub ref_pic_marking: RefPicMarking,
110
111    field_rank: FieldRank,
112
113    pub timestamp: u64,
114}
115
116/// A `PictureData` within a `Rc<RefCell>` which field rank is guaranteed to be correct.
117///
118/// The field rank of `PictureData` is only final after both fields have been constructed - namely,
119/// the first field can only point to the second one after the latter is available as a Rc. Methods
120/// [`PictureData::into_rc`] and [`PictureData::split_frame`] take care of this, and is this only
121/// producer of this type, ensuring all instances are correct.
122#[derive(Default, Debug, Clone)]
123pub struct RcPictureData {
124    pic: Rc<RefCell<PictureData>>,
125}
126
127impl Deref for RcPictureData {
128    type Target = Rc<RefCell<PictureData>>;
129
130    fn deref(&self) -> &Self::Target {
131        &self.pic
132    }
133}
134
135impl PictureData {
136    pub fn new_non_existing(frame_num: u32, timestamp: u64) -> Self {
137        PictureData {
138            frame_num,
139            nonexisting: true,
140            nal_ref_idc: 1,
141            field: Field::Frame,
142            pic_num: frame_num as i32,
143            reference: Reference::ShortTerm,
144            timestamp,
145            ..Default::default()
146        }
147    }
148
149    /// Create a new picture from a `slice`, `sps`, and `timestamp`.
150    ///
151    /// `first_field` is set if this picture is the second field of a frame.
152    pub fn new_from_slice(
153        slice: &Slice,
154        sps: &Sps,
155        timestamp: u64,
156        first_field: Option<&RcPictureData>,
157    ) -> Self {
158        let hdr = &slice.header;
159        let nalu_hdr = &slice.nalu.header;
160
161        let is_idr = if nalu_hdr.idr_pic_flag {
162            IsIdr::Yes {
163                idr_pic_id: hdr.idr_pic_id,
164            }
165        } else {
166            IsIdr::No
167        };
168
169        let field = if hdr.field_pic_flag {
170            if hdr.bottom_field_flag {
171                Field::Bottom
172            } else {
173                Field::Top
174            }
175        } else {
176            Field::Frame
177        };
178
179        let reference = if nalu_hdr.ref_idc != 0 {
180            Reference::ShortTerm
181        } else {
182            Reference::None
183        };
184
185        let pic_num = if !hdr.field_pic_flag {
186            hdr.frame_num
187        } else {
188            2 * hdr.frame_num + 1
189        };
190
191        let (
192            pic_order_cnt_lsb,
193            delta_pic_order_cnt_bottom,
194            delta_pic_order_cnt0,
195            delta_pic_order_cnt1,
196        ) = match sps.pic_order_cnt_type {
197            0 => (
198                hdr.pic_order_cnt_lsb,
199                hdr.delta_pic_order_cnt_bottom,
200                Default::default(),
201                Default::default(),
202            ),
203            1 => (
204                Default::default(),
205                Default::default(),
206                hdr.delta_pic_order_cnt[0],
207                hdr.delta_pic_order_cnt[1],
208            ),
209            _ => (
210                Default::default(),
211                Default::default(),
212                Default::default(),
213                Default::default(),
214            ),
215        };
216
217        let coded_resolution = Resolution::from((sps.width(), sps.height()));
218
219        let visible_rect = sps.visible_rectangle();
220
221        let display_resolution = Resolution {
222            width: visible_rect.max.x - visible_rect.min.x,
223            height: visible_rect.max.y - visible_rect.min.y,
224        };
225
226        let mut pic = PictureData {
227            pic_order_cnt_type: sps.pic_order_cnt_type,
228            pic_order_cnt_lsb: i32::from(pic_order_cnt_lsb),
229            delta_pic_order_cnt_bottom,
230            delta_pic_order_cnt0,
231            delta_pic_order_cnt1,
232            pic_num: i32::from(pic_num),
233            frame_num: u32::from(hdr.frame_num),
234            nal_ref_idc: nalu_hdr.ref_idc,
235            is_idr,
236            reference,
237            field,
238            ref_pic_marking: hdr.dec_ref_pic_marking.clone(),
239            coded_resolution,
240            display_resolution,
241            timestamp,
242            ..Default::default()
243        };
244
245        if let Some(first_field) = first_field {
246            pic.set_first_field_to(first_field);
247        }
248
249        pic
250    }
251
252    /// Whether the current picture is a reference, either ShortTerm or LongTerm.
253    pub fn is_ref(&self) -> bool {
254        !matches!(self.reference, Reference::None)
255    }
256
257    /// Whether this picture is a second field.
258    pub fn is_second_field(&self) -> bool {
259        matches!(self.field_rank, FieldRank::Second(..))
260    }
261
262    /// Returns the field rank of this picture, including a reference to its other field.
263    pub fn field_rank(&self) -> &FieldRank {
264        &self.field_rank
265    }
266
267    /// Returns a reference to the picture's Reference
268    pub fn reference(&self) -> &Reference {
269        &self.reference
270    }
271
272    /// Mark the picture as a reference picture.
273    pub fn set_reference(&mut self, reference: Reference, apply_to_other_field: bool) {
274        log::debug!("Set reference of {:#?} to {:?}", self, reference);
275        self.reference = reference;
276
277        if apply_to_other_field {
278            if let Some(other_field) = self.other_field() {
279                log::debug!(
280                    "other_field: Set reference of {:#?} to {:?}",
281                    &other_field.borrow(),
282                    reference
283                );
284                other_field.borrow_mut().reference = reference;
285            }
286        }
287    }
288
289    /// Get a reference to the picture's other field, if there is any
290    /// and its reference is still valid.
291    pub fn other_field(&self) -> Option<Rc<RefCell<PictureData>>> {
292        match &self.field_rank {
293            FieldRank::Single => None,
294            FieldRank::First(other_field) => other_field.upgrade(),
295            FieldRank::Second(other_field) => Some(other_field.clone()),
296        }
297    }
298
299    /// Set this picture's second field.
300    fn set_second_field_to(&mut self, other_field: &Rc<RefCell<Self>>) {
301        self.field_rank = FieldRank::First(Rc::downgrade(other_field));
302    }
303
304    /// Whether the current picture is the second field of a complementary ref pair.
305    pub fn is_second_field_of_complementary_ref_pair(&self) -> bool {
306        self.is_ref()
307            && matches!(self.field_rank(), FieldRank::Second(first_field) if first_field.borrow().is_ref())
308    }
309
310    /// Set this picture's first field.
311    fn set_first_field_to(&mut self, other_field: &Rc<RefCell<Self>>) {
312        self.field_rank = FieldRank::Second(other_field.clone());
313    }
314
315    pub fn pic_num_f(&self, max_pic_num: i32) -> i32 {
316        if !matches!(self.reference(), Reference::LongTerm) {
317            self.pic_num
318        } else {
319            max_pic_num
320        }
321    }
322
323    pub fn long_term_pic_num_f(&self, max_long_term_frame_idx: MaxLongTermFrameIdx) -> u32 {
324        if matches!(self.reference(), Reference::LongTerm) {
325            self.long_term_pic_num
326        } else {
327            2 * max_long_term_frame_idx.to_value_plus1()
328        }
329    }
330
331    /// Consume this picture and return a Rc'd version.
332    ///
333    /// If the picture was a second field, adjust the field of the first field to point to this
334    /// one.
335    pub fn into_rc(self) -> RcPictureData {
336        let self_rc = Rc::new(RefCell::new(self));
337
338        if let FieldRank::Second(first_field) = self_rc.borrow().field_rank() {
339            first_field.borrow_mut().set_second_field_to(&self_rc);
340        }
341
342        RcPictureData { pic: self_rc }
343    }
344
345    /// Split a frame into two complementary fields that reference one another.
346    pub fn split_frame(mut self) -> (RcPictureData, RcPictureData) {
347        assert!(matches!(self.field, Field::Frame));
348        assert!(matches!(self.field_rank, FieldRank::Single));
349
350        debug!(
351            "Splitting picture (frame_num, POC) ({:?}, {:?})",
352            self.frame_num, self.pic_order_cnt
353        );
354
355        let second_pic_order_cnt = if self.top_field_order_cnt < self.bottom_field_order_cnt {
356            self.field = Field::Top;
357            self.pic_order_cnt = self.top_field_order_cnt;
358
359            self.bottom_field_order_cnt
360        } else {
361            self.field = Field::Bottom;
362            self.pic_order_cnt = self.bottom_field_order_cnt;
363
364            self.top_field_order_cnt
365        };
366
367        let second_field = PictureData {
368            top_field_order_cnt: self.top_field_order_cnt,
369            bottom_field_order_cnt: self.bottom_field_order_cnt,
370            frame_num: self.frame_num,
371            reference: self.reference,
372            nonexisting: self.nonexisting,
373            pic_order_cnt: second_pic_order_cnt,
374            field: self.field.opposite(),
375            ..Default::default()
376        };
377
378        debug!(
379            "Split into picture (frame_num, POC) ({:?}, {:?}), field: {:?}",
380            self.frame_num, self.pic_order_cnt, self.field
381        );
382        debug!(
383            "Split into picture (frame_num, POC) ({:?}, {:?}), field {:?}",
384            second_field.frame_num, second_field.pic_order_cnt, second_field.field
385        );
386
387        let first_field = Rc::new(RefCell::new(self));
388        let second_field = Rc::new(RefCell::new(second_field));
389
390        first_field.borrow_mut().set_second_field_to(&second_field);
391        second_field.borrow_mut().set_first_field_to(&first_field);
392
393        (
394            RcPictureData { pic: first_field },
395            RcPictureData { pic: second_field },
396        )
397    }
398}
399
400impl std::fmt::Debug for PictureData {
401    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
402        f.debug_struct("PictureData")
403            .field("pic_order_cnt_type", &self.pic_order_cnt_type)
404            .field("top_field_order_cnt", &self.top_field_order_cnt)
405            .field("bottom_field_order_cnt", &self.bottom_field_order_cnt)
406            .field("pic_order_cnt", &self.pic_order_cnt)
407            .field("pic_order_cnt_msb", &self.pic_order_cnt_msb)
408            .field("pic_order_cnt_lsb", &self.pic_order_cnt_lsb)
409            .field(
410                "delta_pic_order_cnt_bottom",
411                &self.delta_pic_order_cnt_bottom,
412            )
413            .field("delta_pic_order_cnt0", &self.delta_pic_order_cnt0)
414            .field("delta_pic_order_cnt1", &self.delta_pic_order_cnt1)
415            .field("pic_num", &self.pic_num)
416            .field("long_term_pic_num", &self.long_term_pic_num)
417            .field("frame_num", &self.frame_num)
418            .field("frame_num_offset", &self.frame_num_offset)
419            .field("frame_num_wrap", &self.frame_num_wrap)
420            .field("long_term_frame_idx", &self.long_term_frame_idx)
421            .field("coded_resolution", &self.coded_resolution)
422            .field("display_resolution", &self.display_resolution)
423            .field("type_", &self.type_)
424            .field("nal_ref_idc", &self.nal_ref_idc)
425            .field("is_idr", &self.is_idr)
426            .field("reference", &self.reference)
427            .field(
428                "ref_pic_list_modification_flag_l0",
429                &self.ref_pic_list_modification_flag_l0,
430            )
431            .field("abs_diff_pic_num_minus1", &self.abs_diff_pic_num_minus1)
432            .field("has_mmco_5", &self.has_mmco_5)
433            .field("nonexisting", &self.nonexisting)
434            .field("field", &self.field)
435            .field("ref_pic_marking", &self.ref_pic_marking)
436            .field("field_rank", &self.field_rank)
437            .finish()
438    }
439}