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:
parent
6729c31623
commit
9c13232aa3
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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(),
|
||||
},
|
||||
),
|
||||
},
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue