scuffle_flv/
header.rs

1use std::io;
2
3use byteorder::{BigEndian, ReadBytesExt};
4use bytes::Bytes;
5use scuffle_bytes_util::BytesCursorExt;
6
7/// The FLV Header
8/// Whenever a FLV file is read these are the first 9 bytes of the file.
9///
10/// Defined by:
11/// - video_file_format_spec_v10.pdf (Chapter 1 - The FLV Header - Page 8)
12/// - video_file_format_spec_v10_1.pdf (Annex E.2 - The FLV Header)
13#[derive(Debug, Clone, PartialEq)]
14pub struct FlvHeader {
15    /// The version of the FLV file.
16    pub version: u8,
17    /// Whether the FLV file has audio.
18    pub has_audio: bool,
19    /// Whether the FLV file has video.
20    pub has_video: bool,
21    /// The extra data in the FLV file.
22    /// Since the header provides a data offset, this is the bytes between the
23    /// end of the header and the start of the data.
24    pub extra: Bytes,
25}
26
27impl FlvHeader {
28    /// Demux the FLV header from the given reader.
29    /// The reader will be returned in the position of the start of the data
30    /// offset.
31    pub fn demux(reader: &mut io::Cursor<Bytes>) -> io::Result<Self> {
32        let start = reader.position() as usize;
33
34        let signature = reader.read_u24::<BigEndian>()?;
35
36        // 0 byte at the beginning because we are only reading 3 bytes not 4.
37        if signature != u32::from_be_bytes([0, b'F', b'L', b'V']) {
38            return Err(io::Error::new(io::ErrorKind::InvalidData, "invalid signature"));
39        }
40
41        let version = reader.read_u8()?;
42        let flags = reader.read_u8()?;
43        let has_audio = (flags & 0b00000100) != 0;
44        let has_video = (flags & 0b00000001) != 0;
45
46        let offset = reader.read_u32::<BigEndian>()? as usize;
47        let end = reader.position() as usize;
48        let size = end - start;
49
50        let extra = reader.extract_bytes(
51            offset
52                .checked_sub(size)
53                .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "invalid offset"))?,
54        )?;
55
56        Ok(FlvHeader {
57            version,
58            has_audio,
59            has_video,
60            extra,
61        })
62    }
63}