hevc_parser/
lib.rs

1use anyhow::Result;
2use nom::{IResult, bytes::complete::take_until};
3
4use bitvec_helpers::bitstream_io_reader::BsIoVecReader;
5
6pub mod hevc;
7pub mod utils;
8
9#[cfg(feature = "hevc_io")]
10pub mod io;
11
12use hevc::*;
13use pps::PPSNAL;
14use slice::SliceNAL;
15use sps::SPSNAL;
16use vps::VPSNAL;
17
18use utils::clear_start_code_emulation_prevention_3_byte;
19
20// We don't want to parse large slices because the memory is copied
21const MAX_PARSE_SIZE: usize = 2048;
22
23const HEADER_LEN_3: usize = 3;
24const HEADER_LEN_4: usize = 4;
25const NAL_START_CODE_3: &[u8] = &[0, 0, 1];
26const NAL_START_CODE_4: &[u8] = &[0, 0, 0, 1];
27
28#[derive(Debug, Default, Copy, Clone)]
29pub enum NALUStartCode {
30    #[default]
31    Length3,
32    Length4,
33}
34
35#[derive(Default)]
36pub struct HevcParser {
37    reader: BsIoVecReader,
38    pub nalu_start_code: NALUStartCode,
39
40    nals: Vec<NALUnit>,
41    vps: Vec<VPSNAL>,
42    sps: Vec<SPSNAL>,
43    pps: Vec<PPSNAL>,
44    ordered_frames: Vec<Frame>,
45    frames: Vec<Frame>,
46
47    poc: u64,
48    poc_tid0: u64,
49
50    current_frame: Frame,
51    decoded_index: u64,
52    presentation_index: u64,
53}
54
55impl HevcParser {
56    fn take_until_nal<'a>(tag: &[u8], data: &'a [u8]) -> IResult<&'a [u8], &'a [u8]> {
57        take_until(tag)(data)
58    }
59
60    pub fn with_nalu_start_code(start_code: NALUStartCode) -> HevcParser {
61        HevcParser {
62            nalu_start_code: start_code,
63            ..Default::default()
64        }
65    }
66
67    pub fn get_offsets(&mut self, data: &[u8], offsets: &mut Vec<usize>) {
68        offsets.clear();
69
70        let mut consumed = 0;
71
72        let nal_start_tag = self.nalu_start_code.slice();
73
74        loop {
75            match Self::take_until_nal(nal_start_tag, &data[consumed..]) {
76                Ok(nal) => {
77                    // Byte count before the NAL is the offset
78                    consumed += nal.1.len();
79
80                    offsets.push(consumed);
81
82                    // nom consumes the tag, so add it back
83                    consumed += self.nalu_start_code.size();
84                }
85                _ => return,
86            }
87        }
88    }
89
90    pub fn split_nals(
91        &mut self,
92        data: &[u8],
93        offsets: &[usize],
94        last: usize,
95        parse_nals: bool,
96    ) -> Result<Vec<NALUnit>> {
97        let count = offsets.len();
98
99        let mut nals = Vec::with_capacity(count);
100
101        for (index, offset) in offsets.iter().enumerate() {
102            let size = if offset == &last {
103                data.len() - offset
104            } else {
105                let size = if index == count - 1 {
106                    last - offset
107                } else {
108                    offsets[index + 1] - offset
109                };
110
111                match &data[offset + size - 1..offset + size + 3] {
112                    [0, 0, 0, 1] => size - 1,
113                    _ => size,
114                }
115            };
116
117            let nal = self.parse_nal(data, *offset, size, parse_nals)?;
118
119            nals.push(nal);
120        }
121
122        Ok(nals)
123    }
124
125    fn parse_nal(
126        &mut self,
127        data: &[u8],
128        offset: usize,
129        size: usize,
130        parse_nal: bool,
131    ) -> Result<NALUnit> {
132        let mut nal = NALUnit::default();
133
134        // Assuming [0, 0, 1] header
135        // Offset is at first element
136        let pos = offset + HEADER_LEN_3;
137        let end = offset + size;
138
139        let parsing_end = if size > MAX_PARSE_SIZE {
140            offset + MAX_PARSE_SIZE
141        } else {
142            end
143        };
144
145        nal.start = pos;
146        nal.end = end;
147        nal.decoded_frame_index = self.decoded_index;
148
149        nal.start_code = if offset > 0 {
150            // Previous byte is 0, offset..offset + 3 is [0, 0, 1]
151            // Actual start code is length 4
152            if data[offset - 1] == 0 {
153                NALUStartCode::Length4
154            } else {
155                NALUStartCode::Length3
156            }
157        } else {
158            NALUStartCode::Length3
159        };
160
161        #[allow(deprecated)]
162        {
163            nal.start_code_len = nal.start_code.size() as u8;
164        }
165
166        let buf = &data[pos..parsing_end];
167        self.handle_nal_without_start_code(buf, nal, parse_nal)
168    }
169
170    fn parse_nal_header(&mut self, nal: &mut NALUnit) -> Result<()> {
171        // forbidden_zero_bit
172        self.reader.read_bit()?;
173
174        nal.nal_type = self.reader.read::<6, u8>()?;
175
176        if self.reader.available()? < 9 && matches!(nal.nal_type, NAL_EOS_NUT | NAL_EOB_NUT) {
177        } else {
178            nal.nuh_layer_id = self.reader.read::<6, u8>()?;
179            nal.temporal_id = self.reader.read::<3, u8>()? - 1;
180        }
181
182        Ok(())
183    }
184
185    fn handle_nal_without_start_code(
186        &mut self,
187        data: &[u8],
188        mut nal: NALUnit,
189        parse_nal: bool,
190    ) -> Result<NALUnit> {
191        if parse_nal {
192            let bytes = clear_start_code_emulation_prevention_3_byte(data);
193            self.reader.replace_vec(bytes);
194
195            self.parse_nal_header(&mut nal)?;
196        } else {
197            nal.nal_type = data[0] >> 1;
198        }
199
200        if nal.nuh_layer_id > 0 {
201            return Ok(nal);
202        }
203
204        if parse_nal {
205            self.parse_nal_internal(&mut nal)?;
206            self.nals.push(nal.clone());
207        }
208
209        Ok(nal)
210    }
211
212    fn parse_nal_internal(&mut self, nal: &mut NALUnit) -> Result<()> {
213        match nal.nal_type {
214            NAL_VPS => self.parse_vps()?,
215            NAL_SPS => self.parse_sps()?,
216            NAL_PPS => self.parse_pps()?,
217
218            NAL_TRAIL_R | NAL_TRAIL_N | NAL_TSA_N | NAL_TSA_R | NAL_STSA_N | NAL_STSA_R
219            | NAL_BLA_W_LP | NAL_BLA_W_RADL | NAL_BLA_N_LP | NAL_IDR_W_RADL | NAL_IDR_N_LP
220            | NAL_CRA_NUT | NAL_RADL_N | NAL_RADL_R | NAL_RASL_N | NAL_RASL_R => {
221                self.parse_slice(nal)?;
222
223                self.current_frame.nals.push(nal.clone());
224            }
225            NAL_SEI_SUFFIX | NAL_UNSPEC62 | NAL_UNSPEC63 | NAL_EOS_NUT | NAL_EOB_NUT
226            | NAL_FD_NUT => {
227                // Dolby NALs are suffixed to the slices
228                // And EOS, EOB, FD should be contained within the current AU
229                self.current_frame.nals.push(nal.clone());
230            }
231            _ => {
232                self.add_current_frame();
233
234                nal.decoded_frame_index = self.decoded_index;
235                self.current_frame.nals.push(nal.clone());
236            }
237        };
238
239        // Parameter sets also mean a new frame
240        match nal.nal_type {
241            NAL_VPS | NAL_SPS | NAL_PPS => {
242                self.add_current_frame();
243
244                nal.decoded_frame_index = self.decoded_index;
245                self.current_frame.nals.push(nal.clone());
246            }
247            _ => (),
248        };
249
250        Ok(())
251    }
252
253    fn parse_vps(&mut self) -> Result<()> {
254        let vps = VPSNAL::parse(&mut self.reader)?;
255
256        self.remove_vps(&vps);
257
258        self.vps.push(vps);
259
260        Ok(())
261    }
262
263    fn parse_sps(&mut self) -> Result<()> {
264        let sps = SPSNAL::parse(&mut self.reader)?;
265        self.remove_sps(&sps);
266
267        self.sps.push(sps);
268
269        Ok(())
270    }
271
272    fn parse_pps(&mut self) -> Result<()> {
273        let pps = PPSNAL::parse(&mut self.reader)?;
274
275        self.remove_pps(&pps);
276
277        self.pps.push(pps);
278
279        Ok(())
280    }
281
282    fn parse_slice(&mut self, nal: &mut NALUnit) -> Result<()> {
283        let slice = SliceNAL::parse(
284            &mut self.reader,
285            &self.sps,
286            &self.pps,
287            nal,
288            &mut self.poc_tid0,
289            &mut self.poc,
290        )?;
291
292        // Consecutive slice NALs cases
293        if self.current_frame.first_slice.first_slice_in_pic_flag && slice.first_slice_in_pic_flag {
294            nal.decoded_frame_index = self.decoded_index + 1;
295            self.add_current_frame();
296        }
297
298        if slice.key_frame {
299            self.reorder_frames();
300        }
301
302        if slice.first_slice_in_pic_flag {
303            self.current_frame.first_slice = slice;
304
305            self.current_frame.decoded_number = self.decoded_index;
306        }
307
308        Ok(())
309    }
310
311    fn remove_vps(&mut self, vps: &VPSNAL) {
312        let id = vps.vps_id as usize;
313
314        if let Some(existing_vps) = self.vps.get(id) {
315            if existing_vps == vps {
316                self.vps.remove(id);
317
318                let sps_to_remove: Vec<SPSNAL> = self
319                    .sps
320                    .clone()
321                    .into_iter()
322                    .filter(|sps| sps.vps_id == vps.vps_id)
323                    .collect();
324
325                sps_to_remove.iter().for_each(|sps| self.remove_sps(sps));
326            }
327        }
328    }
329
330    fn remove_sps(&mut self, sps: &SPSNAL) {
331        let id = sps.sps_id as usize;
332
333        if let Some(existing_sps) = self.sps.get(id) {
334            if existing_sps == sps {
335                self.sps.remove(id);
336
337                // Remove all dependent pps
338                self.pps.retain(|pps| pps.sps_id != sps.sps_id);
339            }
340        }
341    }
342
343    fn remove_pps(&mut self, pps: &PPSNAL) {
344        // Remove if same id
345        if let Some(existing_pps) = self.pps.get(pps.pps_id as usize) {
346            if existing_pps == pps {
347                self.pps.remove(pps.pps_id as usize);
348            }
349        }
350    }
351
352    // If we're here, the last slice of a frame was found already
353    fn add_current_frame(&mut self) {
354        if self.current_frame.first_slice.first_slice_in_pic_flag {
355            self.decoded_index += 1;
356
357            self.current_frame.presentation_number =
358                self.current_frame.first_slice.output_picture_number;
359
360            self.current_frame.frame_type = self.current_frame.first_slice.slice_type;
361
362            self.frames.push(self.current_frame.clone());
363
364            self.current_frame = Frame::default();
365        }
366    }
367
368    fn reorder_frames(&mut self) {
369        let mut offset = self.presentation_index;
370
371        self.frames.sort_by_key(|f| f.presentation_number);
372        self.frames.iter_mut().for_each(|f| {
373            f.presentation_number = offset;
374            offset += 1;
375        });
376
377        self.presentation_index = offset;
378        self.ordered_frames.extend_from_slice(&self.frames);
379        self.frames.clear();
380    }
381
382    pub fn display(&self) {
383        println!("{} frames", &self.ordered_frames.len());
384        for frame in &self.ordered_frames {
385            let pict_type = match frame.frame_type {
386                2 => "I",
387                1 => "P",
388                0 => "B",
389                _ => "",
390            };
391
392            println!(
393                "{} display order {} poc {} pos {}",
394                pict_type,
395                frame.presentation_number,
396                frame.first_slice.output_picture_number,
397                frame.decoded_number
398            );
399        }
400    }
401
402    pub fn finish(&mut self) {
403        self.add_current_frame();
404        self.reorder_frames();
405    }
406
407    /// Processed frames in the current GOP
408    /// Cleared every key frame
409    pub fn processed_frames(&self) -> &Vec<Frame> {
410        &self.frames
411    }
412
413    pub fn ordered_frames(&self) -> &Vec<Frame> {
414        &self.ordered_frames
415    }
416
417    pub fn get_nals(&self) -> &Vec<NALUnit> {
418        &self.nals
419    }
420}
421
422impl NALUStartCode {
423    pub const fn slice(&self) -> &[u8] {
424        match self {
425            NALUStartCode::Length3 => NAL_START_CODE_3,
426            NALUStartCode::Length4 => NAL_START_CODE_4,
427        }
428    }
429
430    pub const fn size(&self) -> usize {
431        match self {
432            NALUStartCode::Length3 => HEADER_LEN_3,
433            NALUStartCode::Length4 => HEADER_LEN_4,
434        }
435    }
436}