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}