core: Seeks before instantiation are valid and should be cached for later execution

This commit is contained in:
David Wendt 2021-02-11 21:05:45 -05:00 committed by Mike Welsh
parent 4905e9a83d
commit 4d0b73feeb
1 changed files with 34 additions and 8 deletions

View File

@ -37,7 +37,7 @@ pub struct VideoData<'gc> {
source: GcCell<'gc, VideoSource>,
/// The decoder stream that this video source is associated to.
stream: Option<CollectWrapper<VideoStreamHandle>>,
stream: VideoStream,
/// The last decoded frame in the video stream.
decoded_frame: Option<(u32, CollectWrapper<BitmapHandle>)>,
@ -54,6 +54,20 @@ pub struct VideoData<'gc> {
keyframes: BTreeSet<u32>,
}
/// An optionally-instantiated video stream.
#[derive(Clone, Debug, Collect)]
#[collect(require_static)]
pub enum VideoStream {
/// An uninstanted video stream.
///
/// The stream index parameter is what frame we should seek to once the
/// stream is instantiated.
Uninstantiated(u32),
/// An instantiated video stream.
Instantiated(VideoStreamHandle),
}
#[derive(Clone, Debug, Collect)]
#[collect(require_static)]
pub enum VideoSource {
@ -94,7 +108,7 @@ impl<'gc> Video<'gc> {
VideoData {
base: Default::default(),
source,
stream: None,
stream: VideoStream::Uninstantiated(0),
decoded_frame: None,
object: None,
keyframes: BTreeSet::new(),
@ -138,10 +152,14 @@ impl<'gc> Video<'gc> {
pub fn seek(self, context: &mut UpdateContext<'_, 'gc, '_>, mut frame_id: u32) {
let read = self.0.read();
let source = read.source;
let stream = if let Some(stream) = &read.stream {
let stream = if let VideoStream::Instantiated(stream) = &read.stream {
stream
} else {
log::error!("Attempted to sync uninstantiated video stream!");
drop(read);
let mut write = self.0.write(context.gc_context);
write.stream = VideoStream::Uninstantiated(frame_id);
return;
};
let last_frame = read.decoded_frame.as_ref().map(|(lf, _)| *lf);
@ -170,7 +188,7 @@ impl<'gc> Video<'gc> {
};
context
.video
.decode_video_stream_frame(stream.0, encframe, context.renderer)
.decode_video_stream_frame(*stream, encframe, context.renderer)
.map(|bi| bi.handle)
}
None => {
@ -259,11 +277,19 @@ impl<'gc> TDisplayObject<'gc> for Video<'gc> {
}
}
(Some(CollectWrapper(stream)), movie.clone(), keyframes)
(stream, movie.clone(), keyframes)
}
};
write.stream = stream;
let starting_seek = if let VideoStream::Uninstantiated(seek_to) = write.stream {
seek_to
} else {
log::warn!("Reinstantiating already-instantiated video stream!");
0
};
write.stream = VideoStream::Instantiated(stream);
write.keyframes = keyframes;
if write.object.is_none() {
@ -290,7 +316,7 @@ impl<'gc> TDisplayObject<'gc> for Video<'gc> {
drop(write);
self.seek(context, 0);
self.seek(context, starting_seek);
if run_frame {
self.run_frame(context);