1use 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 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#[derive(Default, Debug)]
58pub enum FieldRank {
59 #[default]
61 Single,
62 First(Weak<RefCell<PictureData>>),
64 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 pub has_mmco_5: bool,
100
101 pub nonexisting: bool,
104
105 pub field: Field,
106
107 pub ref_pic_marking: RefPicMarking,
110
111 field_rank: FieldRank,
112
113 pub timestamp: u64,
114}
115
116#[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 pub fn new_from_slice(slice: &Slice, sps: &Sps, timestamp: u64, first_field: Option<&RcPictureData>) -> Self {
153 let hdr = &slice.header;
154 let nalu_hdr = &slice.nalu.header;
155
156 let is_idr = if nalu_hdr.idr_pic_flag {
157 IsIdr::Yes {
158 idr_pic_id: hdr.idr_pic_id,
159 }
160 } else {
161 IsIdr::No
162 };
163
164 let field = if hdr.field_pic_flag {
165 if hdr.bottom_field_flag {
166 Field::Bottom
167 } else {
168 Field::Top
169 }
170 } else {
171 Field::Frame
172 };
173
174 let reference = if nalu_hdr.ref_idc != 0 {
175 Reference::ShortTerm
176 } else {
177 Reference::None
178 };
179
180 let pic_num = if !hdr.field_pic_flag {
181 hdr.frame_num
182 } else {
183 2 * hdr.frame_num + 1
184 };
185
186 let (pic_order_cnt_lsb, delta_pic_order_cnt_bottom, delta_pic_order_cnt0, delta_pic_order_cnt1) =
187 match sps.pic_order_cnt_type {
188 0 => (
189 hdr.pic_order_cnt_lsb,
190 hdr.delta_pic_order_cnt_bottom,
191 Default::default(),
192 Default::default(),
193 ),
194 1 => (
195 Default::default(),
196 Default::default(),
197 hdr.delta_pic_order_cnt[0],
198 hdr.delta_pic_order_cnt[1],
199 ),
200 _ => (
201 Default::default(),
202 Default::default(),
203 Default::default(),
204 Default::default(),
205 ),
206 };
207
208 let coded_resolution = Resolution::from((sps.width(), sps.height()));
209
210 let visible_rect = sps.visible_rectangle();
211
212 let display_resolution = Resolution {
213 width: visible_rect.max.x - visible_rect.min.x,
214 height: visible_rect.max.y - visible_rect.min.y,
215 };
216
217 let mut pic = PictureData {
218 pic_order_cnt_type: sps.pic_order_cnt_type,
219 pic_order_cnt_lsb: i32::from(pic_order_cnt_lsb),
220 delta_pic_order_cnt_bottom,
221 delta_pic_order_cnt0,
222 delta_pic_order_cnt1,
223 pic_num: i32::from(pic_num),
224 frame_num: u32::from(hdr.frame_num),
225 nal_ref_idc: nalu_hdr.ref_idc,
226 is_idr,
227 reference,
228 field,
229 ref_pic_marking: hdr.dec_ref_pic_marking.clone(),
230 coded_resolution,
231 display_resolution,
232 timestamp,
233 ..Default::default()
234 };
235
236 if let Some(first_field) = first_field {
237 pic.set_first_field_to(first_field);
238 }
239
240 pic
241 }
242
243 pub fn is_ref(&self) -> bool {
245 !matches!(self.reference, Reference::None)
246 }
247
248 pub fn is_second_field(&self) -> bool {
250 matches!(self.field_rank, FieldRank::Second(..))
251 }
252
253 pub fn field_rank(&self) -> &FieldRank {
255 &self.field_rank
256 }
257
258 pub fn reference(&self) -> &Reference {
260 &self.reference
261 }
262
263 pub fn set_reference(&mut self, reference: Reference, apply_to_other_field: bool) {
265 log::debug!("Set reference of {:#?} to {:?}", self, reference);
266 self.reference = reference;
267
268 if apply_to_other_field {
269 if let Some(other_field) = self.other_field() {
270 log::debug!(
271 "other_field: Set reference of {:#?} to {:?}",
272 &other_field.borrow(),
273 reference
274 );
275 other_field.borrow_mut().reference = reference;
276 }
277 }
278 }
279
280 pub fn other_field(&self) -> Option<Rc<RefCell<PictureData>>> {
283 match &self.field_rank {
284 FieldRank::Single => None,
285 FieldRank::First(other_field) => other_field.upgrade(),
286 FieldRank::Second(other_field) => Some(other_field.clone()),
287 }
288 }
289
290 fn set_second_field_to(&mut self, other_field: &Rc<RefCell<Self>>) {
292 self.field_rank = FieldRank::First(Rc::downgrade(other_field));
293 }
294
295 pub fn is_second_field_of_complementary_ref_pair(&self) -> bool {
297 self.is_ref() && matches!(self.field_rank(), FieldRank::Second(first_field) if first_field.borrow().is_ref())
298 }
299
300 fn set_first_field_to(&mut self, other_field: &Rc<RefCell<Self>>) {
302 self.field_rank = FieldRank::Second(other_field.clone());
303 }
304
305 pub fn pic_num_f(&self, max_pic_num: i32) -> i32 {
306 if !matches!(self.reference(), Reference::LongTerm) {
307 self.pic_num
308 } else {
309 max_pic_num
310 }
311 }
312
313 pub fn long_term_pic_num_f(&self, max_long_term_frame_idx: MaxLongTermFrameIdx) -> u32 {
314 if matches!(self.reference(), Reference::LongTerm) {
315 self.long_term_pic_num
316 } else {
317 2 * max_long_term_frame_idx.to_value_plus1()
318 }
319 }
320
321 pub fn into_rc(self) -> RcPictureData {
326 let self_rc = Rc::new(RefCell::new(self));
327
328 if let FieldRank::Second(first_field) = self_rc.borrow().field_rank() {
329 first_field.borrow_mut().set_second_field_to(&self_rc);
330 }
331
332 RcPictureData { pic: self_rc }
333 }
334
335 pub fn split_frame(mut self) -> (RcPictureData, RcPictureData) {
337 assert!(matches!(self.field, Field::Frame));
338 assert!(matches!(self.field_rank, FieldRank::Single));
339
340 debug!(
341 "Splitting picture (frame_num, POC) ({:?}, {:?})",
342 self.frame_num, self.pic_order_cnt
343 );
344
345 let second_pic_order_cnt = if self.top_field_order_cnt < self.bottom_field_order_cnt {
346 self.field = Field::Top;
347 self.pic_order_cnt = self.top_field_order_cnt;
348
349 self.bottom_field_order_cnt
350 } else {
351 self.field = Field::Bottom;
352 self.pic_order_cnt = self.bottom_field_order_cnt;
353
354 self.top_field_order_cnt
355 };
356
357 let second_field = PictureData {
358 top_field_order_cnt: self.top_field_order_cnt,
359 bottom_field_order_cnt: self.bottom_field_order_cnt,
360 frame_num: self.frame_num,
361 reference: self.reference,
362 nonexisting: self.nonexisting,
363 pic_order_cnt: second_pic_order_cnt,
364 field: self.field.opposite(),
365 ..Default::default()
366 };
367
368 debug!(
369 "Split into picture (frame_num, POC) ({:?}, {:?}), field: {:?}",
370 self.frame_num, self.pic_order_cnt, self.field
371 );
372 debug!(
373 "Split into picture (frame_num, POC) ({:?}, {:?}), field {:?}",
374 second_field.frame_num, second_field.pic_order_cnt, second_field.field
375 );
376
377 let first_field = Rc::new(RefCell::new(self));
378 let second_field = Rc::new(RefCell::new(second_field));
379
380 first_field.borrow_mut().set_second_field_to(&second_field);
381 second_field.borrow_mut().set_first_field_to(&first_field);
382
383 (RcPictureData { pic: first_field }, RcPictureData { pic: second_field })
384 }
385}
386
387impl std::fmt::Debug for PictureData {
388 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
389 f.debug_struct("PictureData")
390 .field("pic_order_cnt_type", &self.pic_order_cnt_type)
391 .field("top_field_order_cnt", &self.top_field_order_cnt)
392 .field("bottom_field_order_cnt", &self.bottom_field_order_cnt)
393 .field("pic_order_cnt", &self.pic_order_cnt)
394 .field("pic_order_cnt_msb", &self.pic_order_cnt_msb)
395 .field("pic_order_cnt_lsb", &self.pic_order_cnt_lsb)
396 .field("delta_pic_order_cnt_bottom", &self.delta_pic_order_cnt_bottom)
397 .field("delta_pic_order_cnt0", &self.delta_pic_order_cnt0)
398 .field("delta_pic_order_cnt1", &self.delta_pic_order_cnt1)
399 .field("pic_num", &self.pic_num)
400 .field("long_term_pic_num", &self.long_term_pic_num)
401 .field("frame_num", &self.frame_num)
402 .field("frame_num_offset", &self.frame_num_offset)
403 .field("frame_num_wrap", &self.frame_num_wrap)
404 .field("long_term_frame_idx", &self.long_term_frame_idx)
405 .field("coded_resolution", &self.coded_resolution)
406 .field("display_resolution", &self.display_resolution)
407 .field("type_", &self.type_)
408 .field("nal_ref_idc", &self.nal_ref_idc)
409 .field("is_idr", &self.is_idr)
410 .field("reference", &self.reference)
411 .field(
412 "ref_pic_list_modification_flag_l0",
413 &self.ref_pic_list_modification_flag_l0,
414 )
415 .field("abs_diff_pic_num_minus1", &self.abs_diff_pic_num_minus1)
416 .field("has_mmco_5", &self.has_mmco_5)
417 .field("nonexisting", &self.nonexisting)
418 .field("field", &self.field)
419 .field("ref_pic_marking", &self.ref_pic_marking)
420 .field("field_rank", &self.field_rank)
421 .finish()
422 }
423}