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(
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 pub fn is_ref(&self) -> bool {
254 !matches!(self.reference, Reference::None)
255 }
256
257 pub fn is_second_field(&self) -> bool {
259 matches!(self.field_rank, FieldRank::Second(..))
260 }
261
262 pub fn field_rank(&self) -> &FieldRank {
264 &self.field_rank
265 }
266
267 pub fn reference(&self) -> &Reference {
269 &self.reference
270 }
271
272 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 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 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 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 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 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 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}