Skip to main content

flowly_flv/parser/
tag.rs

1mod audio;
2mod ex_data;
3mod meta;
4mod video;
5
6use crate::{
7    error::Error,
8    reader::FlvReader,
9    tag::{FlvTag, FlvTagData, FlvTagHeader, FlvTagType},
10};
11
12use super::{FlvParser, Parser};
13
14impl<E> Parser<E, FlvTagHeader> for FlvParser {
15    type Error = Error<E>;
16
17    /// Parse FLV tag header.
18    fn parse(&mut self, reader: &mut impl FlvReader) -> Result<FlvTagHeader, Self::Error> {
19        let flags = reader.read_u8()?;
20
21        let tag_type = FlvTagType::from(flags & 0b11111);
22
23        // The size of the tag's data part
24        let data_size = reader.read_u24()?;
25
26        // The timestamp (in milliseconds) of the tag
27        let timestamp = reader.read_u24()?;
28
29        // Extension of the timestamp field to form a SI32 value
30        let timestamp_extended = reader.read_u8()?;
31
32        // The id of stream
33        let stream_id = reader.read_u24()?;
34
35        Ok(FlvTagHeader {
36            tag_type,
37            data_size,
38            timestamp: (u32::from(timestamp_extended) << 24) + timestamp,
39            stream_id,
40        })
41    }
42}
43
44impl<E> Parser<E, FlvTag> for FlvParser {
45    type Error = Error<E>;
46
47    /// Parse FLV tag data.
48    fn parse(&mut self, reader: &mut impl FlvReader) -> Result<FlvTag, Self::Error> {
49        let header: FlvTagHeader = self.parse(reader)?;
50
51        Ok(FlvTag {
52            header,
53            data: match header.tag_type {
54                FlvTagType::Audio => FlvTagData::Audio(self.parse(reader)?),
55                FlvTagType::Video => FlvTagData::Video(self.parse(reader)?),
56                FlvTagType::Metadata => FlvTagData::Meta(self.parse(reader)?),
57                FlvTagType::Unknown(..) => FlvTagData::Unknown,
58            },
59        })
60    }
61}
62
63impl FlvParser {
64    /// Parse FLV tag data.
65    pub(crate) fn parse_flv_data<E>(
66        &mut self,
67        reader: &mut impl FlvReader,
68        tag_type: FlvTagType,
69    ) -> Result<FlvTagData, Error<E>> {
70        Ok(match tag_type {
71            FlvTagType::Audio => FlvTagData::Audio(self.parse(reader)?),
72            FlvTagType::Video => FlvTagData::Video(self.parse(reader)?),
73            FlvTagType::Metadata => FlvTagData::Meta(self.parse(reader)?),
74            FlvTagType::Unknown(..) => FlvTagData::Unknown,
75        })
76    }
77}