scuffle_flv/video/header/
mod.rs

1//! FLV video tag headers.
2
3use std::io::{self, Seek};
4
5use byteorder::ReadBytesExt;
6use bytes::Bytes;
7use nutype_enum::nutype_enum;
8
9use crate::error::FlvError;
10
11pub mod enhanced;
12pub mod legacy;
13
14nutype_enum! {
15    /// FLV Frame Type
16    ///
17    /// This enum represents the different types of frames in a FLV file.
18    ///
19    /// Defined by:
20    /// - Legacy FLV spec, Annex E.4.3.1
21    pub enum VideoFrameType(u8) {
22        /// A keyframe is a frame that is a complete representation of the video content.
23        KeyFrame = 1,
24        /// An interframe is a frame that is a partial representation of the video content.
25        InterFrame = 2,
26        /// A disposable interframe is a frame that is a partial representation of the video content, but is not required to be displayed. (h263 only)
27        DisposableInterFrame = 3,
28        /// A generated keyframe is a frame that is a complete representation of the video content, but is not a keyframe. (reserved for server use only)
29        GeneratedKeyFrame = 4,
30        /// A video info or command frame is a frame that contains video information or commands.
31        /// If the frame is this type, the body will be a CommandPacket
32        Command = 5,
33    }
34}
35
36nutype_enum! {
37    /// FLV Video Command
38    ///
39    /// Defined by:
40    /// - Legacy FLV spec, Annex E.4.3.1, VideoTagBody
41    /// - Enhanced RTMP spec, page 26, Enhanced Video
42    pub enum VideoCommand(u8) {
43        /// Start of client-side seeking video frame sequence
44        StartSeek = 0,
45        /// End of client-side seeking video frame sequence
46        EndSeek = 1,
47    }
48}
49
50/// A wrapper for the different types of video tag header data.
51#[derive(Debug, Clone, PartialEq)]
52pub enum VideoTagHeaderData {
53    /// Legacy video tag header.
54    Legacy(legacy::LegacyVideoTagHeader),
55    /// Enhanced video tag header.
56    Enhanced(enhanced::ExVideoTagHeader),
57}
58
59/// FLV `VideoTagHeader`
60///
61/// This only describes the video tag header, see [`VideoData`](super::VideoData) for the full video data container.
62///
63/// Defined by:
64/// - Legacy FLV spec, Annex E.4.3.1
65/// - Enhanced RTMP spec, page 26-28, Enhanced Video
66#[derive(Debug, Clone, PartialEq)]
67pub struct VideoTagHeader {
68    /// The frame type of the video data.
69    pub frame_type: VideoFrameType,
70    /// The data of the video tag header.
71    pub data: VideoTagHeaderData,
72}
73
74impl VideoTagHeader {
75    /// Demux the video tag header from the given reader.
76    ///
77    /// If you want to demux the full video data tag, use [`VideoData::demux`](super::VideoData::demux) instead.
78    /// This function will automatically determine whether the given data represents a legacy or an enhanced video tag header
79    /// and demux it accordingly.
80    #[allow(clippy::unusual_byte_groupings)]
81    pub fn demux(reader: &mut io::Cursor<Bytes>) -> Result<Self, FlvError> {
82        let byte = reader.read_u8()?;
83        // seek back one byte so that the codec id can be read again
84        reader.seek_relative(-1)?;
85
86        let is_ex_video_header = (byte & 0b1_000_0000) != 0;
87
88        let data = if !is_ex_video_header {
89            VideoTagHeaderData::Legacy(legacy::LegacyVideoTagHeader::demux(reader)?)
90        } else {
91            VideoTagHeaderData::Enhanced(enhanced::ExVideoTagHeader::demux(reader)?)
92        };
93
94        Ok(VideoTagHeader {
95            frame_type: VideoFrameType::from((byte & 0b0_111_0000) >> 4),
96            data,
97        })
98    }
99}