core: Process `onMetaData` to get our stream definition with.
We use `preload_offset` to avoid processing the same metadata multiple times.
This commit is contained in:
parent
286acddfea
commit
3410d9fcf8
|
@ -6,9 +6,14 @@ use crate::loader::Error;
|
||||||
use crate::string::AvmString;
|
use crate::string::AvmString;
|
||||||
use flv_rs::{
|
use flv_rs::{
|
||||||
AudioData as FlvAudioData, Error as FlvError, FlvReader, Header as FlvHeader,
|
AudioData as FlvAudioData, Error as FlvError, FlvReader, Header as FlvHeader,
|
||||||
ScriptData as FlvScriptData, Tag as FlvTag, TagData as FlvTagData, VideoData as FlvVideoData,
|
ScriptData as FlvScriptData, Tag as FlvTag, TagData as FlvTagData, Value as FlvValue,
|
||||||
|
VideoData as FlvVideoData,
|
||||||
};
|
};
|
||||||
use gc_arena::{Collect, GcCell, MutationContext};
|
use gc_arena::{Collect, GcCell, MutationContext};
|
||||||
|
use ruffle_video::VideoStreamHandle;
|
||||||
|
use ruffle_wstr::WStr;
|
||||||
|
use std::io::Seek;
|
||||||
|
use swf::{VideoCodec, VideoDeblocking};
|
||||||
|
|
||||||
/// Manager for all media streams.
|
/// Manager for all media streams.
|
||||||
///
|
///
|
||||||
|
@ -114,7 +119,10 @@ impl<'gc> Eq for NetStream<'gc> {}
|
||||||
#[collect(require_static)]
|
#[collect(require_static)]
|
||||||
pub enum NetStreamType {
|
pub enum NetStreamType {
|
||||||
/// The stream is an FLV.
|
/// The stream is an FLV.
|
||||||
Flv(FlvHeader),
|
Flv {
|
||||||
|
header: FlvHeader,
|
||||||
|
stream: Option<VideoStreamHandle>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Collect)]
|
#[derive(Clone, Debug, Collect)]
|
||||||
|
@ -221,7 +229,10 @@ impl<'gc> NetStream<'gc> {
|
||||||
Ok(header) => {
|
Ok(header) => {
|
||||||
write.offset = reader.into_parts().1;
|
write.offset = reader.into_parts().1;
|
||||||
write.preload_offset = write.offset;
|
write.preload_offset = write.offset;
|
||||||
write.stream_type = Some(NetStreamType::Flv(header));
|
write.stream_type = Some(NetStreamType::Flv {
|
||||||
|
header,
|
||||||
|
stream: None,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
Err(FlvError::EndOfData) => return,
|
Err(FlvError::EndOfData) => return,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
@ -242,8 +253,7 @@ impl<'gc> NetStream<'gc> {
|
||||||
let end_time = write.stream_time + dt;
|
let end_time = write.stream_time + dt;
|
||||||
|
|
||||||
//At this point we should know our stream type.
|
//At this point we should know our stream type.
|
||||||
match write.stream_type.as_ref().expect("known stream type") {
|
if matches!(write.stream_type, Some(NetStreamType::Flv { .. })) {
|
||||||
NetStreamType::Flv(header) => {
|
|
||||||
let mut reader = FlvReader::from_parts(&write.buffer, write.offset);
|
let mut reader = FlvReader::from_parts(&write.buffer, write.offset);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
@ -269,6 +279,10 @@ impl<'gc> NetStream<'gc> {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let tag_needs_preloading = reader.stream_position().expect("valid position")
|
||||||
|
as usize
|
||||||
|
>= write.preload_offset;
|
||||||
|
|
||||||
match tag.data {
|
match tag.data {
|
||||||
FlvTagData::Audio(FlvAudioData {
|
FlvTagData::Audio(FlvAudioData {
|
||||||
format,
|
format,
|
||||||
|
@ -287,7 +301,93 @@ impl<'gc> NetStream<'gc> {
|
||||||
tracing::warn!("Stub: Stream video processing");
|
tracing::warn!("Stub: Stream video processing");
|
||||||
}
|
}
|
||||||
FlvTagData::Script(FlvScriptData(vars)) => {
|
FlvTagData::Script(FlvScriptData(vars)) => {
|
||||||
tracing::warn!("Stub: Stream data processing");
|
let has_stream_already = match write.stream_type {
|
||||||
|
Some(NetStreamType::Flv { stream, .. }) => stream.is_some(),
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut width = None;
|
||||||
|
let mut height = None;
|
||||||
|
let mut video_codec_id = None;
|
||||||
|
let mut frame_rate = None;
|
||||||
|
let mut duration = None;
|
||||||
|
|
||||||
|
for var in vars {
|
||||||
|
if var.name == b"onMetaData" && !has_stream_already {
|
||||||
|
match var.data {
|
||||||
|
FlvValue::Object(subvars) => {
|
||||||
|
for subvar in subvars {
|
||||||
|
match (subvar.name, subvar.data) {
|
||||||
|
(b"width", FlvValue::Number(val)) => {
|
||||||
|
width = Some(val)
|
||||||
|
}
|
||||||
|
(b"height", FlvValue::Number(val)) => {
|
||||||
|
height = Some(val)
|
||||||
|
}
|
||||||
|
(b"videocodecid", FlvValue::Number(val)) => {
|
||||||
|
video_codec_id = Some(val)
|
||||||
|
}
|
||||||
|
(b"framerate", FlvValue::Number(val)) => {
|
||||||
|
frame_rate = Some(val)
|
||||||
|
}
|
||||||
|
(b"duration", FlvValue::Number(val)) => {
|
||||||
|
duration = Some(val)
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => tracing::error!("Invalid FLV metadata tag!"),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tracing::warn!(
|
||||||
|
"Stub: Stream data processing (name: {})",
|
||||||
|
WStr::from_units(var.name)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let (_, position) = reader.into_parts();
|
||||||
|
|
||||||
|
if tag_needs_preloading {
|
||||||
|
if let (
|
||||||
|
Some(width),
|
||||||
|
Some(height),
|
||||||
|
Some(video_codec_id),
|
||||||
|
Some(frame_rate),
|
||||||
|
Some(duration),
|
||||||
|
) = (width, height, video_codec_id, frame_rate, duration)
|
||||||
|
{
|
||||||
|
let num_frames = frame_rate * duration;
|
||||||
|
if let Some(video_codec) = VideoCodec::from_u8(video_codec_id as u8)
|
||||||
|
{
|
||||||
|
match context.video.register_video_stream(
|
||||||
|
num_frames as u32,
|
||||||
|
(width as u16, height as u16),
|
||||||
|
video_codec,
|
||||||
|
VideoDeblocking::UseVideoPacketValue,
|
||||||
|
) {
|
||||||
|
Ok(stream_handle) => match &mut write.stream_type {
|
||||||
|
Some(NetStreamType::Flv { stream, .. }) => {
|
||||||
|
*stream = Some(stream_handle)
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
},
|
||||||
|
Err(e) => tracing::error!(
|
||||||
|
"Got error when registring FLV video stream: {}",
|
||||||
|
e
|
||||||
|
),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tracing::error!(
|
||||||
|
"FLV video stream has invalid codec ID {}",
|
||||||
|
video_codec_id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reader = FlvReader::from_parts(&write.buffer, position);
|
||||||
}
|
}
|
||||||
FlvTagData::Invalid(e) => {
|
FlvTagData::Invalid(e) => {
|
||||||
tracing::error!("FLV data parsing failed: {}", e)
|
tracing::error!("FLV data parsing failed: {}", e)
|
||||||
|
@ -296,5 +396,4 @@ impl<'gc> NetStream<'gc> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue