flv: `parse` now consumes the back pointer.
We also guarantee that when parsing fails we leave the reader where it is to allow reading later.
This commit is contained in:
parent
3e2a5eb43b
commit
7bf28074c0
|
@ -3,6 +3,8 @@ use crate::script::ScriptData;
|
|||
use crate::sound::AudioData;
|
||||
use crate::video::VideoData;
|
||||
|
||||
use std::io::{Seek, SeekFrom};
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(PartialEq, Debug)]
|
||||
pub enum TagData<'a> {
|
||||
|
@ -21,34 +23,64 @@ pub struct Tag<'a> {
|
|||
impl<'a> Tag<'a> {
|
||||
/// Parse a single FLV tag structure.
|
||||
///
|
||||
/// This assumes the reader is currently pointing at the tag itself, not
|
||||
/// the back-pointers in between the tags.
|
||||
/// FLV files are constructed as a list of tags. Back pointers to prior
|
||||
/// tags are provided to allow reverse seeking. This function ignores the
|
||||
/// back pointer and parses the tag at the current location. At the end of
|
||||
/// parsing, the reader will be pointing to the start of the next tag. Thus,
|
||||
/// repeated calls to `parse` will yield further tags until the end of the
|
||||
/// file.
|
||||
///
|
||||
/// `None` indicates that either:
|
||||
///
|
||||
/// * There is not enough data in the reader to read the next tag
|
||||
/// * The data in the reader is corrupt and not a valid FLV
|
||||
///
|
||||
/// If encountered, the position of the reader will be unchanged.
|
||||
pub fn parse(reader: &mut FlvReader<'a>) -> Option<Self> {
|
||||
let tag_type = reader.read_u8()?;
|
||||
let data_size = reader.read_u24()?;
|
||||
let timestamp = reader.read_u24()?;
|
||||
let timestamp_extended = reader.read_u8()?;
|
||||
let stream_id = reader.read_u24()?;
|
||||
let old_position = reader.stream_position().ok()?;
|
||||
|
||||
let timestamp = ((timestamp_extended as u32) << 24 | timestamp) as i32;
|
||||
let ret = (|| {
|
||||
let _previous_tag_size = reader.read_u32()?;
|
||||
|
||||
match tag_type {
|
||||
8 => Some(Tag {
|
||||
timestamp,
|
||||
stream_id,
|
||||
data: TagData::Audio(AudioData::parse(reader, data_size)?),
|
||||
}),
|
||||
9 => Some(Tag {
|
||||
timestamp,
|
||||
stream_id,
|
||||
data: TagData::Video(VideoData::parse(reader, data_size)?),
|
||||
}),
|
||||
18 => Some(Tag {
|
||||
timestamp,
|
||||
stream_id,
|
||||
data: TagData::Script(ScriptData::parse(reader)?),
|
||||
}),
|
||||
_ => None,
|
||||
let tag_type = reader.read_u8()?;
|
||||
let data_size = reader.read_u24()?;
|
||||
let timestamp = reader.read_u24()?;
|
||||
let timestamp_extended = reader.read_u8()?;
|
||||
let stream_id = reader.read_u24()?;
|
||||
|
||||
let timestamp = ((timestamp_extended as u32) << 24 | timestamp) as i32;
|
||||
|
||||
let new_position = reader.stream_position().ok()? + data_size as u64;
|
||||
|
||||
Some((
|
||||
match tag_type {
|
||||
8 => Tag {
|
||||
timestamp,
|
||||
stream_id,
|
||||
data: TagData::Audio(AudioData::parse(reader, data_size)?),
|
||||
},
|
||||
9 => Tag {
|
||||
timestamp,
|
||||
stream_id,
|
||||
data: TagData::Video(VideoData::parse(reader, data_size)?),
|
||||
},
|
||||
18 => Tag {
|
||||
timestamp,
|
||||
stream_id,
|
||||
data: TagData::Script(ScriptData::parse(reader)?),
|
||||
},
|
||||
_ => return None,
|
||||
},
|
||||
new_position,
|
||||
))
|
||||
})();
|
||||
|
||||
if let Some((tag, new_position)) = ret {
|
||||
reader.seek(SeekFrom::Start(new_position)).ok()?;
|
||||
Some(tag)
|
||||
} else {
|
||||
reader.seek(SeekFrom::Start(old_position)).ok()?;
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -64,8 +96,8 @@ mod tests {
|
|||
#[test]
|
||||
fn read_tag_sounddata() {
|
||||
let data = [
|
||||
0x08, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0xFB, 0x12, 0x34,
|
||||
0x56, 0x78,
|
||||
0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
|
||||
0x00, 0xFB, 0x12, 0x34, 0x56, 0x78,
|
||||
];
|
||||
let mut reader = FlvReader::from_source(&data);
|
||||
|
||||
|
@ -88,8 +120,8 @@ mod tests {
|
|||
#[test]
|
||||
fn read_tag_videodata() {
|
||||
let data = [
|
||||
0x09, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x21, 0x12, 0x34,
|
||||
0x56, 0x78,
|
||||
0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
|
||||
0x00, 0x21, 0x12, 0x34, 0x56, 0x78,
|
||||
];
|
||||
let mut reader = FlvReader::from_source(&data);
|
||||
|
||||
|
@ -110,8 +142,9 @@ mod tests {
|
|||
#[test]
|
||||
fn read_tag_scriptdata() {
|
||||
let data = [
|
||||
0x12, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x03, 0x01,
|
||||
0x02, 0x03, 0x06, 0x00, 0x03, 0x01, 0x02, 0x03, 0x05, 0x00, 0x00, 0x09,
|
||||
0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
|
||||
0x00, 0x00, 0x03, 0x01, 0x02, 0x03, 0x06, 0x00, 0x03, 0x01, 0x02, 0x03, 0x05, 0x00,
|
||||
0x00, 0x09,
|
||||
];
|
||||
let mut reader = FlvReader::from_source(&data);
|
||||
|
||||
|
|
Loading…
Reference in New Issue