• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
5 use std::cell::RefCell;
6 use std::ops::Deref;
7 use std::rc::Rc;
8 use std::rc::Weak;
9 
10 use log::debug;
11 
12 use crate::codec::h264::parser::MaxLongTermFrameIdx;
13 use crate::codec::h264::parser::RefPicMarking;
14 use crate::codec::h264::parser::Slice;
15 use crate::codec::h264::parser::SliceType;
16 use crate::codec::h264::parser::Sps;
17 use crate::Resolution;
18 
19 #[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
20 pub enum Field {
21     #[default]
22     Frame,
23     Top,
24     Bottom,
25 }
26 
27 impl Field {
28     /// Returns the field of opposite parity.
opposite(&self) -> Self29     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)]
39 pub enum Reference {
40     #[default]
41     None,
42     ShortTerm,
43     LongTerm,
44 }
45 
46 #[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
47 pub 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)]
58 pub 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)]
69 pub 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)]
123 pub struct RcPictureData {
124     pic: Rc<RefCell<PictureData>>,
125 }
126 
127 impl Deref for RcPictureData {
128     type Target = Rc<RefCell<PictureData>>;
129 
deref(&self) -> &Self::Target130     fn deref(&self) -> &Self::Target {
131         &self.pic
132     }
133 }
134 
135 impl PictureData {
new_non_existing(frame_num: u32, timestamp: u64) -> Self136     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.
new_from_slice( slice: &Slice, sps: &Sps, timestamp: u64, first_field: Option<&RcPictureData>, ) -> Self152     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 { idr_pic_id: hdr.idr_pic_id }
163         } else {
164             IsIdr::No
165         };
166 
167         let field = if hdr.field_pic_flag {
168             if hdr.bottom_field_flag {
169                 Field::Bottom
170             } else {
171                 Field::Top
172             }
173         } else {
174             Field::Frame
175         };
176 
177         let reference = if nalu_hdr.ref_idc != 0 { Reference::ShortTerm } else { Reference::None };
178 
179         let pic_num = if !hdr.field_pic_flag { hdr.frame_num } else { 2 * hdr.frame_num + 1 };
180 
181         let (
182             pic_order_cnt_lsb,
183             delta_pic_order_cnt_bottom,
184             delta_pic_order_cnt0,
185             delta_pic_order_cnt1,
186         ) = match sps.pic_order_cnt_type {
187             0 => (
188                 hdr.pic_order_cnt_lsb,
189                 hdr.delta_pic_order_cnt_bottom,
190                 Default::default(),
191                 Default::default(),
192             ),
193             1 => (
194                 Default::default(),
195                 Default::default(),
196                 hdr.delta_pic_order_cnt[0],
197                 hdr.delta_pic_order_cnt[1],
198             ),
199             _ => (Default::default(), Default::default(), Default::default(), Default::default()),
200         };
201 
202         let coded_resolution = Resolution::from((sps.width(), sps.height()));
203 
204         let visible_rect = sps.visible_rectangle();
205 
206         let display_resolution = Resolution {
207             width: visible_rect.max.x - visible_rect.min.x,
208             height: visible_rect.max.y - visible_rect.min.y,
209         };
210 
211         let mut pic = PictureData {
212             pic_order_cnt_type: sps.pic_order_cnt_type,
213             pic_order_cnt_lsb: i32::from(pic_order_cnt_lsb),
214             delta_pic_order_cnt_bottom,
215             delta_pic_order_cnt0,
216             delta_pic_order_cnt1,
217             pic_num: i32::from(pic_num),
218             frame_num: u32::from(hdr.frame_num),
219             nal_ref_idc: nalu_hdr.ref_idc,
220             is_idr,
221             reference,
222             field,
223             ref_pic_marking: hdr.dec_ref_pic_marking.clone(),
224             coded_resolution,
225             display_resolution,
226             timestamp,
227             ..Default::default()
228         };
229 
230         if let Some(first_field) = first_field {
231             pic.set_first_field_to(first_field);
232         }
233 
234         pic
235     }
236 
237     /// Whether the current picture is a reference, either ShortTerm or LongTerm.
is_ref(&self) -> bool238     pub fn is_ref(&self) -> bool {
239         !matches!(self.reference, Reference::None)
240     }
241 
242     /// Whether this picture is a second field.
is_second_field(&self) -> bool243     pub fn is_second_field(&self) -> bool {
244         matches!(self.field_rank, FieldRank::Second(..))
245     }
246 
247     /// Returns the field rank of this picture, including a reference to its other field.
field_rank(&self) -> &FieldRank248     pub fn field_rank(&self) -> &FieldRank {
249         &self.field_rank
250     }
251 
252     /// Returns a reference to the picture's Reference
reference(&self) -> &Reference253     pub fn reference(&self) -> &Reference {
254         &self.reference
255     }
256 
257     /// Mark the picture as a reference picture.
set_reference(&mut self, reference: Reference, apply_to_other_field: bool)258     pub fn set_reference(&mut self, reference: Reference, apply_to_other_field: bool) {
259         log::debug!("Set reference of {:#?} to {:?}", self, reference);
260         self.reference = reference;
261 
262         if apply_to_other_field {
263             if let Some(other_field) = self.other_field() {
264                 log::debug!(
265                     "other_field: Set reference of {:#?} to {:?}",
266                     &other_field.borrow(),
267                     reference
268                 );
269                 other_field.borrow_mut().reference = reference;
270             }
271         }
272     }
273 
274     /// Get a reference to the picture's other field, if there is any
275     /// and its reference is still valid.
other_field(&self) -> Option<Rc<RefCell<PictureData>>>276     pub fn other_field(&self) -> Option<Rc<RefCell<PictureData>>> {
277         match &self.field_rank {
278             FieldRank::Single => None,
279             FieldRank::First(other_field) => other_field.upgrade(),
280             FieldRank::Second(other_field) => Some(other_field.clone()),
281         }
282     }
283 
284     /// Set this picture's second field.
set_second_field_to(&mut self, other_field: &Rc<RefCell<Self>>)285     fn set_second_field_to(&mut self, other_field: &Rc<RefCell<Self>>) {
286         self.field_rank = FieldRank::First(Rc::downgrade(other_field));
287     }
288 
289     /// Whether the current picture is the second field of a complementary ref pair.
is_second_field_of_complementary_ref_pair(&self) -> bool290     pub fn is_second_field_of_complementary_ref_pair(&self) -> bool {
291         self.is_ref()
292             && matches!(self.field_rank(), FieldRank::Second(first_field) if first_field.borrow().is_ref())
293     }
294 
295     /// Set this picture's first field.
set_first_field_to(&mut self, other_field: &Rc<RefCell<Self>>)296     fn set_first_field_to(&mut self, other_field: &Rc<RefCell<Self>>) {
297         self.field_rank = FieldRank::Second(other_field.clone());
298     }
299 
pic_num_f(&self, max_pic_num: i32) -> i32300     pub fn pic_num_f(&self, max_pic_num: i32) -> i32 {
301         if !matches!(self.reference(), Reference::LongTerm) {
302             self.pic_num
303         } else {
304             max_pic_num
305         }
306     }
307 
long_term_pic_num_f(&self, max_long_term_frame_idx: MaxLongTermFrameIdx) -> u32308     pub fn long_term_pic_num_f(&self, max_long_term_frame_idx: MaxLongTermFrameIdx) -> u32 {
309         if matches!(self.reference(), Reference::LongTerm) {
310             self.long_term_pic_num
311         } else {
312             2 * max_long_term_frame_idx.to_value_plus1()
313         }
314     }
315 
316     /// Consume this picture and return a Rc'd version.
317     ///
318     /// If the picture was a second field, adjust the field of the first field to point to this
319     /// one.
into_rc(self) -> RcPictureData320     pub fn into_rc(self) -> RcPictureData {
321         let self_rc = Rc::new(RefCell::new(self));
322 
323         if let FieldRank::Second(first_field) = self_rc.borrow().field_rank() {
324             first_field.borrow_mut().set_second_field_to(&self_rc);
325         }
326 
327         RcPictureData { pic: self_rc }
328     }
329 
330     /// Split a frame into two complementary fields that reference one another.
split_frame(mut self) -> (RcPictureData, RcPictureData)331     pub fn split_frame(mut self) -> (RcPictureData, RcPictureData) {
332         assert!(matches!(self.field, Field::Frame));
333         assert!(matches!(self.field_rank, FieldRank::Single));
334 
335         debug!(
336             "Splitting picture (frame_num, POC) ({:?}, {:?})",
337             self.frame_num, self.pic_order_cnt
338         );
339 
340         let second_pic_order_cnt = if self.top_field_order_cnt < self.bottom_field_order_cnt {
341             self.field = Field::Top;
342             self.pic_order_cnt = self.top_field_order_cnt;
343 
344             self.bottom_field_order_cnt
345         } else {
346             self.field = Field::Bottom;
347             self.pic_order_cnt = self.bottom_field_order_cnt;
348 
349             self.top_field_order_cnt
350         };
351 
352         let second_field = PictureData {
353             top_field_order_cnt: self.top_field_order_cnt,
354             bottom_field_order_cnt: self.bottom_field_order_cnt,
355             frame_num: self.frame_num,
356             reference: self.reference,
357             nonexisting: self.nonexisting,
358             pic_order_cnt: second_pic_order_cnt,
359             field: self.field.opposite(),
360             ..Default::default()
361         };
362 
363         debug!(
364             "Split into picture (frame_num, POC) ({:?}, {:?}), field: {:?}",
365             self.frame_num, self.pic_order_cnt, self.field
366         );
367         debug!(
368             "Split into picture (frame_num, POC) ({:?}, {:?}), field {:?}",
369             second_field.frame_num, second_field.pic_order_cnt, second_field.field
370         );
371 
372         let first_field = Rc::new(RefCell::new(self));
373         let second_field = Rc::new(RefCell::new(second_field));
374 
375         first_field.borrow_mut().set_second_field_to(&second_field);
376         second_field.borrow_mut().set_first_field_to(&first_field);
377 
378         (RcPictureData { pic: first_field }, RcPictureData { pic: second_field })
379     }
380 }
381 
382 impl std::fmt::Debug for PictureData {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result383     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
384         f.debug_struct("PictureData")
385             .field("pic_order_cnt_type", &self.pic_order_cnt_type)
386             .field("top_field_order_cnt", &self.top_field_order_cnt)
387             .field("bottom_field_order_cnt", &self.bottom_field_order_cnt)
388             .field("pic_order_cnt", &self.pic_order_cnt)
389             .field("pic_order_cnt_msb", &self.pic_order_cnt_msb)
390             .field("pic_order_cnt_lsb", &self.pic_order_cnt_lsb)
391             .field("delta_pic_order_cnt_bottom", &self.delta_pic_order_cnt_bottom)
392             .field("delta_pic_order_cnt0", &self.delta_pic_order_cnt0)
393             .field("delta_pic_order_cnt1", &self.delta_pic_order_cnt1)
394             .field("pic_num", &self.pic_num)
395             .field("long_term_pic_num", &self.long_term_pic_num)
396             .field("frame_num", &self.frame_num)
397             .field("frame_num_offset", &self.frame_num_offset)
398             .field("frame_num_wrap", &self.frame_num_wrap)
399             .field("long_term_frame_idx", &self.long_term_frame_idx)
400             .field("coded_resolution", &self.coded_resolution)
401             .field("display_resolution", &self.display_resolution)
402             .field("type_", &self.type_)
403             .field("nal_ref_idc", &self.nal_ref_idc)
404             .field("is_idr", &self.is_idr)
405             .field("reference", &self.reference)
406             .field("ref_pic_list_modification_flag_l0", &self.ref_pic_list_modification_flag_l0)
407             .field("abs_diff_pic_num_minus1", &self.abs_diff_pic_num_minus1)
408             .field("has_mmco_5", &self.has_mmco_5)
409             .field("nonexisting", &self.nonexisting)
410             .field("field", &self.field)
411             .field("ref_pic_marking", &self.ref_pic_marking)
412             .field("field_rank", &self.field_rank)
413             .finish()
414     }
415 }
416