scuffle_flv/
avc.rs

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/// AVC Packet
10#[derive(Debug, Clone, PartialEq)]
11pub enum AvcPacket {
12    /// AVC NALU
13    Nalu { composition_time: u32, data: Bytes },
14    /// AVC Sequence Header
15    SequenceHeader(AVCDecoderConfigurationRecord),
16    /// AVC End of Sequence
17    EndOfSequence,
18    /// AVC Unknown (we don't know how to parse it)
19    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    /// FLV AVC Packet Type
49    /// Defined in the FLV specification. Chapter 1 - AVCVIDEODATA
50    /// The AVC packet type is used to determine if the video data is a sequence
51    /// header or a NALU.
52    pub enum AvcPacketType(u8) {
53        SeqHdr = 0,
54        Nalu = 1,
55        EndOfSequence = 2,
56    }
57}