1use std::io;
2
3use byteorder::{BigEndian, ReadBytesExt};
4use bytes::Bytes;
5use scuffle_bytes_util::BytesCursorExt;
6
7#[derive(Debug, Clone, PartialEq)]
14pub struct FlvHeader {
15 pub version: u8,
17 pub has_audio: bool,
19 pub has_video: bool,
21 pub extra: Bytes,
25}
26
27impl FlvHeader {
28 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 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}