libbitsub_core/pgs/
display_set.rs1use super::{
4 ObjectDefinitionSegment, PaletteDefinitionSegment, PresentationCompositionSegment, SegmentType,
5 WindowDefinition, WindowDefinitionSegment,
6};
7use crate::utils::BigEndianReader;
8
9#[derive(Debug, Clone)]
11pub struct DisplaySet {
12 pub pts: u32,
14 pub dts: u32,
16 pub composition: Option<PresentationCompositionSegment>,
18 pub palettes: Vec<PaletteDefinitionSegment>,
20 pub objects: Vec<ObjectDefinitionSegment>,
22 pub windows: Vec<WindowDefinitionSegment>,
24}
25
26impl DisplaySet {
27 pub fn new() -> Self {
29 Self {
30 pts: 0,
31 dts: 0,
32 composition: None,
33 palettes: Vec::new(),
34 objects: Vec::new(),
35 windows: Vec::new(),
36 }
37 }
38
39 pub fn parse(data: &[u8], include_header: bool) -> Option<(Self, usize)> {
42 let mut reader = BigEndianReader::new(data);
43 let mut display_set = Self::new();
44
45 loop {
46 let pts: u32;
47 let dts: u32;
48
49 if include_header {
50 let magic = reader.read_u16()?;
52 if magic != 0x5047 {
53 return None; }
55
56 pts = reader.read_u32()?;
57 dts = reader.read_u32()?;
58
59 if display_set.pts == 0 {
60 display_set.pts = pts;
61 display_set.dts = dts;
62 }
63 } else {
64 pts = 0;
65 dts = 0;
66 }
67
68 let segment_type = reader.read_u8()?;
69 let segment_size = reader.read_u16()? as usize;
70
71 if reader.remaining() < segment_size {
73 return None;
74 }
75
76 let start_pos = reader.position();
77
78 match SegmentType::try_from(segment_type) {
79 Ok(SegmentType::PaletteDefinition) => {
80 if let Some(palette) =
81 PaletteDefinitionSegment::parse(&mut reader, segment_size)
82 {
83 display_set.palettes.push(palette);
84 }
85 }
86 Ok(SegmentType::ObjectDefinition) => {
87 if let Some(object) = ObjectDefinitionSegment::parse(&mut reader, segment_size)
88 {
89 display_set.objects.push(object);
90 }
91 }
92 Ok(SegmentType::PresentationComposition) => {
93 if let Some(composition) =
94 PresentationCompositionSegment::parse(&mut reader, segment_size)
95 {
96 display_set.pts = pts;
97 display_set.dts = dts;
98 display_set.composition = Some(composition);
99 }
100 }
101 Ok(SegmentType::WindowDefinition) => {
102 if let Some(window) = WindowDefinitionSegment::parse(&mut reader, segment_size)
103 {
104 display_set.windows.push(window);
105 }
106 }
107 Ok(SegmentType::End) => {
108 break;
110 }
111 Err(_) => {
112 reader.skip(segment_size);
114 }
115 }
116
117 let consumed = reader.position() - start_pos;
119 if consumed < segment_size {
120 reader.skip(segment_size - consumed);
121 }
122 }
123
124 Some((display_set, reader.position()))
125 }
126
127 #[inline]
129 pub fn pts_ms(&self) -> u32 {
130 self.pts / 90
131 }
132
133 pub fn find_window(&self, id: u8) -> Option<&WindowDefinition> {
135 for wds in &self.windows {
136 for window in &wds.windows {
137 if window.id == id {
138 return Some(window);
139 }
140 }
141 }
142 None
143 }
144
145 pub fn find_palette(&self, id: u8) -> Option<&PaletteDefinitionSegment> {
147 self.palettes.iter().find(|p| p.id == id)
148 }
149}
150
151impl Default for DisplaySet {
152 fn default() -> Self {
153 Self::new()
154 }
155}