core: Add a type to hold playing streams.

Calling `StreamManager::tick` advances all streams to the appropriate time. This is an unlocked timestep to support things like non-stage-FPS video and the like.
This commit is contained in:
David Wendt 2023-03-17 22:25:54 -04:00 committed by kmeisthax
parent 6729c31623
commit 9c13232aa3
3 changed files with 71 additions and 1 deletions

View File

@ -20,6 +20,7 @@ use crate::library::Library;
use crate::loader::LoadManager;
use crate::player::Player;
use crate::prelude::*;
use crate::streams::StreamManager;
use crate::stub::StubCollection;
use crate::tag_utils::{SwfMovie, SwfSlice};
use crate::timer::Timers;
@ -183,6 +184,9 @@ pub struct UpdateContext<'a, 'gc> {
///
/// If we are not doing frame processing, then this is `FramePhase::Enter`.
pub frame_phase: &'a mut FramePhase,
/// Manager of in-progress media streams.
pub stream_manager: &'a mut StreamManager<'gc>,
}
/// Convenience methods for controlling audio.
@ -347,6 +351,7 @@ impl<'a, 'gc> UpdateContext<'a, 'gc> {
frame_rate: self.frame_rate,
actions_since_timeout_check: self.actions_since_timeout_check,
frame_phase: self.frame_phase,
stream_manager: self.stream_manager,
}
}

View File

@ -39,6 +39,7 @@ use crate::limits::ExecutionLimit;
use crate::loader::{LoadBehavior, LoadManager};
use crate::locale::get_current_date_time;
use crate::prelude::*;
use crate::streams::StreamManager;
use crate::string::AvmString;
use crate::stub::StubCollection;
use crate::tag_utils::SwfMovie;
@ -153,6 +154,9 @@ struct GcRootData<'gc> {
/// Manager of active sound instances.
audio_manager: AudioManager<'gc>,
/// List of actively playing streams to decode.
stream_manager: StreamManager<'gc>,
}
impl<'gc> GcRootData<'gc> {
@ -176,6 +180,7 @@ impl<'gc> GcRootData<'gc> {
&mut Option<ContextMenuState<'gc>>,
&mut ExternalInterface<'gc>,
&mut AudioManager<'gc>,
&mut StreamManager<'gc>,
) {
(
self.stage,
@ -192,6 +197,7 @@ impl<'gc> GcRootData<'gc> {
&mut self.current_context_menu,
&mut self.external_interface,
&mut self.audio_manager,
&mut self.stream_manager,
)
}
}
@ -526,10 +532,12 @@ impl Player {
});
self.update_timers(dt);
self.update(|context| {
StreamManager::tick(context, dt);
});
self.audio.tick();
}
}
pub fn time_til_next_timer(&self) -> Option<f64> {
self.time_til_next_timer
}
@ -1731,6 +1739,7 @@ impl Player {
current_context_menu,
external_interface,
audio_manager,
stream_manager,
) = root_data.update_context_params();
let mut update_context = UpdateContext {
@ -1777,6 +1786,7 @@ impl Player {
actions_since_timeout_check: &mut self.actions_since_timeout_check,
frame_phase: &mut self.frame_phase,
stub_tracker: &mut self.stub_tracker,
stream_manager,
};
let old_frame_rate = *update_context.frame_rate;
@ -2273,6 +2283,7 @@ impl PlayerBuilder {
),
timers: Timers::new(),
unbound_text_fields: Vec::new(),
stream_manager: StreamManager::new(),
},
),
},

View File

@ -1,7 +1,61 @@
//! NetStream implementation
use crate::context::UpdateContext;
use crate::loader::Error;
use gc_arena::{Collect, GcCell, MutationContext};
/// Manager for all media streams.
///
/// This does *not* handle data transport; which is delegated to `LoadManager`.
/// `StreamManager` *only* handles decoding or encoding of relevant media
/// streams.
#[derive(Collect)]
#[collect(no_drop)]
pub struct StreamManager<'gc> {
/// List of actively playing streams.
///
/// This is not the total list of all created NetStreams; only the ones
/// that have been configured to play media.
playing_streams: Vec<GcCell<'gc, NetStream>>,
}
impl<'gc> Default for StreamManager<'gc> {
fn default() -> Self {
Self::new()
}
}
impl<'gc> StreamManager<'gc> {
pub fn new() -> Self {
StreamManager {
playing_streams: Vec::new(),
}
}
/// Process all playing media streams.
///
/// This is an unlocked timestep; the `dt` parameter indicates how many
/// milliseconds have elapsed since the last tick. This is intended to
/// support video framerates separate from the Stage frame rate.
///
/// This does not borrow `&mut self` as we need the `UpdateContext`, too.
pub fn tick(_context: &mut UpdateContext<'gc, '_>, _dt: f64) {}
}
/// A stream representing download of some (audiovisual) data.
///
/// `NetStream` interacts with several different parts of player
/// infrastructure:
///
/// * `LoadManager` fills individual `NetStream` buffers with data (or, in the
/// future, empties them out for media upload)
/// * `StreamManager` processes media data in the `NetStream` buffer (in the
/// future, sending it to the audio backend or `SoundManager`)
/// * `Video` display objects linked to this `NetStream` display the latest
/// decoded frame.
///
/// It corresponds directly to the AVM1 and AVM2 `NetStream` classes; it's API
/// is intended to be a VM-agnostic version of those.
#[derive(Clone, Debug, Collect)]
#[collect(require_static)]
pub struct NetStream {