1use std::io;
4
5use byteorder::{BigEndian, ReadBytesExt};
6use bytes::Bytes;
7use scuffle_bytes_util::BytesCursorExt;
8
9use crate::error::FlvError;
10
11#[derive(Debug, Clone, PartialEq)]
18pub struct FlvHeader {
19 pub version: u8,
21 pub is_audio_present: bool,
23 pub is_video_present: bool,
25 pub extra: Bytes,
30}
31
32impl FlvHeader {
33 pub fn demux(reader: &mut io::Cursor<Bytes>) -> Result<Self, FlvError> {
37 let start = reader.position() as usize;
38
39 let signature = reader.read_u24::<BigEndian>()?;
40
41 if signature != u32::from_be_bytes([0, b'F', b'L', b'V']) {
43 return Err(FlvError::InvalidSignature(signature));
44 }
45
46 let version = reader.read_u8()?;
47 let flags = reader.read_u8()?;
48 let is_audio_present = (flags & 0b00000100) != 0;
49 let is_video_present = (flags & 0b00000001) != 0;
50
51 let data_offset = reader.read_u32::<BigEndian>()?;
52 let end = reader.position() as usize;
53 let size = end - start;
54
55 let remaining = (data_offset as usize)
56 .checked_sub(size)
57 .ok_or(FlvError::InvalidDataOffset(data_offset))?;
58
59 let extra = reader.extract_bytes(remaining)?;
60
61 Ok(FlvHeader {
62 version,
63 is_audio_present,
64 is_video_present,
65 extra,
66 })
67 }
68}