Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Video base/stub impls #3117

Merged
merged 30 commits into from
Feb 17, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
67f843e
core: Add `VideoBackend` to host video decoders
kmeisthax Oct 15, 2020
414bcc2
core: Add video display object
kmeisthax Oct 15, 2020
7298195
swf: Make video-related tags publicly parsable
kmeisthax Oct 16, 2020
98ec2ec
core: Parse `DefineVideoStream` and use it to put videos into the cha…
kmeisthax Oct 16, 2020
267dfbd
core: Also implement `VideoFrame` tag.
kmeisthax Oct 17, 2020
1a489f5
core: Further adjustment to video backend type
kmeisthax Feb 6, 2021
940461f
core: Add software video backend, separate from the null backend, to …
kmeisthax Dec 22, 2020
c7c3539
video: Stub seeking.
kmeisthax Dec 22, 2020
319df7e
core: Allow instantiation of videos
kmeisthax Dec 23, 2020
ec51a29
video: Implement a very basic video decoding loop
kmeisthax Dec 23, 2020
59ad6d1
video: Always decode the first frame
kmeisthax Dec 23, 2020
ad9e8a9
video: Report what frame gave an error
kmeisthax Dec 23, 2020
4e88708
video: Enable software video decoding on web and exporter.
kmeisthax Dec 24, 2020
8fec01d
video: Warn if we are missing a frame to render.
kmeisthax Dec 24, 2020
47257c0
video: Warn if duplicate video frames are encountered
kmeisthax Dec 25, 2020
d7a1833
avm1: Stub impl the `Video` class.
kmeisthax Jan 5, 2021
8caf752
avm2: Stub the `Video` class.
kmeisthax Jan 5, 2021
9d242d8
video: Snap seeks to nearest keyframe
kmeisthax Jan 7, 2021
38cf454
video: Frames with no data associated are treated as empty Pframes.
kmeisthax Jan 8, 2021
b86aeb1
chore: Clippy compliance for stub video backend
kmeisthax Feb 7, 2021
61e93e7
core: Fix various documentation errors in video
kmeisthax Feb 11, 2021
6d6661a
avm2: `Video` is a sealed class.
kmeisthax Feb 11, 2021
6bc3585
core: Seeks before instantiation are valid and should be cached for l…
kmeisthax Feb 12, 2021
2ddc512
core: Rename the video dependency enums to better describe their mean…
kmeisthax Feb 12, 2021
afc5553
chore: Spelling matters
kmeisthax Feb 12, 2021
f41301b
chore: Clippy wants this too
kmeisthax Feb 14, 2021
1412b60
core/video: Make seeking to non-keyframes possible.
torokati44 Feb 12, 2021
f108fff
core/video: Loop to frame modulo num_frames. Fixes z0r.de/1843
torokati44 Feb 12, 2021
c4ad641
core: Future-proof the non-keyframe seek for other stream types.
kmeisthax Feb 15, 2021
8a3fddc
core: Adjust documentation
kmeisthax Feb 16, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion core/src/character.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use crate::backend::audio::SoundHandle;
use crate::display_object::{Bitmap, Button, EditText, Graphic, MorphShape, MovieClip, Text};
use crate::display_object::{
Bitmap, Button, EditText, Graphic, MorphShape, MovieClip, Text, Video,
};
use crate::font::Font;

#[derive(Clone)]
Expand All @@ -13,6 +15,7 @@ pub enum Character<'gc> {
MorphShape(MorphShape<'gc>),
Text(Text<'gc>),
Sound(SoundHandle),
Video(Video<'gc>),
}

unsafe impl<'gc> gc_arena::Collect for Character<'gc> {
Expand All @@ -28,6 +31,7 @@ unsafe impl<'gc> gc_arena::Collect for Character<'gc> {
Character::MorphShape(c) => c.trace(cc),
Character::Text(c) => c.trace(cc),
Character::Sound(c) => c.trace(cc),
Character::Video(c) => c.trace(cc),
}
}
}
2 changes: 1 addition & 1 deletion core/src/display_object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ pub use graphic::Graphic;
pub use morph_shape::{MorphShape, MorphShapeStatic};
pub use movie_clip::{MovieClip, Scene};
pub use text::Text;
use video::Video;
pub use video::Video;

#[derive(Clone, Debug)]
pub struct DisplayObjectBase<'gc> {
Expand Down
28 changes: 27 additions & 1 deletion core/src/display_object/movie_clip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use crate::context::{ActionType, RenderContext, UpdateContext};
use crate::display_object::container::{ChildContainer, TDisplayObjectContainer};
use crate::display_object::{
Bitmap, Button, DisplayObjectBase, EditText, Graphic, MorphShapeStatic, TDisplayObject, Text,
Video,
};
use crate::drawing::Drawing;
use crate::events::{ButtonKeyCode, ClipEvent, ClipEventResult};
Expand All @@ -32,7 +33,7 @@ use std::collections::HashMap;
use std::convert::TryFrom;
use std::sync::Arc;
use swf::read::SwfReadExt;
use swf::{FillStyle, FrameLabelData, LineStyle};
use swf::{FillStyle, FrameLabelData, LineStyle, Tag};

type FrameNumber = u16;

Expand Down Expand Up @@ -288,6 +289,10 @@ impl<'gc> MovieClip<'gc> {
.0
.write(context.gc_context)
.define_sound(context, reader),
TagCode::DefineVideoStream => self
.0
.write(context.gc_context)
.define_video_stream(context, reader),
TagCode::DefineSprite => self.0.write(context.gc_context).define_sprite(
context,
reader,
Expand Down Expand Up @@ -2606,6 +2611,27 @@ impl<'gc, 'a> MovieClipData<'gc> {
Ok(())
}

#[inline]
fn define_video_stream(
&mut self,
context: &mut UpdateContext<'_, 'gc, '_>,
reader: &mut SwfStream,
) -> DecodeResult {
match reader.read_define_video_stream()? {
Tag::DefineVideoStream(streamdef) => {
let id = streamdef.id;
let video = Video::from_swf_tag(self.movie(), streamdef, context.gc_context);
context
.library
.library_for_movie_mut(self.movie())
.register_character(id, Character::Video(video));
}
_ => unreachable!(),
};

Ok(())
}

fn define_sprite(
&mut self,
context: &mut UpdateContext<'_, 'gc, '_>,
Expand Down
49 changes: 38 additions & 11 deletions core/src/display_object/video.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ use crate::display_object::{DisplayObjectBase, TDisplayObject};
use crate::prelude::*;
use crate::tag_utils::SwfMovie;
use crate::types::{Degrees, Percent};
use gc_arena::{Collect, Gc, GcCell};
use swf::CharacterId;
use gc_arena::{Collect, GcCell, MutationContext};
use std::borrow::Borrow;
use std::sync::Arc;
use swf::{CharacterId, DefineVideoStream};

/// A Video display object is a high-level interface to a video player.
///
Expand All @@ -22,30 +24,55 @@ pub struct Video<'gc>(GcCell<'gc, VideoData<'gc>>);
#[collect(no_drop)]
pub struct VideoData<'gc> {
base: DisplayObjectBase<'gc>,
static_data: Gc<'gc, VideoStatic>,
source_stream: GcCell<'gc, VideoSource>,
}

#[derive(Clone, Debug, Collect)]
#[collect(require_static)]
pub struct VideoStatic {
movie: SwfMovie,
id: CharacterId,
width: Twips,
height: Twips,
pub enum VideoSource {
SWF {
kmeisthax marked this conversation as resolved.
Show resolved Hide resolved
movie: Arc<SwfMovie>,
streamdef: DefineVideoStream,
},
}

impl<'gc> Video<'gc> {
/// Construct a Video object that is tied to a SWF file's video stream.
pub fn from_swf_tag(
movie: Arc<SwfMovie>,
streamdef: DefineVideoStream,
mc: MutationContext<'gc, '_>,
) -> Self {
let source_stream = GcCell::allocate(mc, VideoSource::SWF { movie, streamdef });

Video(GcCell::allocate(
mc,
VideoData {
base: Default::default(),
source_stream,
},
))
}
}

impl<'gc> TDisplayObject<'gc> for Video<'gc> {
impl_display_object!(base);

fn id(&self) -> CharacterId {
self.0.read().static_data.id
match (*self.0.read().source_stream.read()).borrow() {
VideoSource::SWF { streamdef, .. } => streamdef.id,
}
}

fn self_bounds(&self) -> BoundingBox {
let mut bounding_box = BoundingBox::default();

bounding_box.set_width(self.0.read().static_data.width);
bounding_box.set_height(self.0.read().static_data.height);
match (*self.0.read().source_stream.read()).borrow() {
VideoSource::SWF { streamdef, .. } => {
bounding_box.set_width(Twips::from_pixels(streamdef.width as f64));
bounding_box.set_height(Twips::from_pixels(streamdef.height as f64));
}
}

bounding_box
}
Expand Down