1use std::io;
2
3use byteorder::{BigEndian, ReadBytesExt};
4use bytes::Bytes;
5use nutype_enum::nutype_enum;
6use scuffle_bytes_util::BytesCursorExt;
7use scuffle_h264::AVCDecoderConfigurationRecord;
8
9#[derive(Debug, Clone, PartialEq)]
11pub enum AvcPacket {
12 Nalu { composition_time: u32, data: Bytes },
14 SequenceHeader(AVCDecoderConfigurationRecord),
16 EndOfSequence,
18 Unknown {
20 avc_packet_type: AvcPacketType,
21 composition_time: u32,
22 data: Bytes,
23 },
24}
25
26impl AvcPacket {
27 pub fn demux(reader: &mut io::Cursor<Bytes>) -> io::Result<Self> {
28 let avc_packet_type = AvcPacketType::from(reader.read_u8()?);
29 let composition_time = reader.read_u24::<BigEndian>()?;
30
31 match avc_packet_type {
32 AvcPacketType::SeqHdr => Ok(Self::SequenceHeader(AVCDecoderConfigurationRecord::demux(reader)?)),
33 AvcPacketType::Nalu => Ok(Self::Nalu {
34 composition_time,
35 data: reader.extract_remaining(),
36 }),
37 AvcPacketType::EndOfSequence => Ok(Self::EndOfSequence),
38 _ => Ok(Self::Unknown {
39 avc_packet_type,
40 composition_time,
41 data: reader.extract_remaining(),
42 }),
43 }
44 }
45}
46
47nutype_enum! {
48 pub enum AvcPacketType(u8) {
53 SeqHdr = 0,
54 Nalu = 1,
55 EndOfSequence = 2,
56 }
57}