@@ -149,6 +149,12 @@ impl<'gc> Video<'gc> {
149
149
}
150
150
151
151
/// Seek to a particular frame in the video stream.
152
+ ///
153
+ /// This function ensures that the given `frame_id` is valid by first
154
+ /// wrapping it to the underlying video stream's boundaries, and then
155
+ /// snapping it to the last independently seekable frame. Then, all frames
156
+ /// from that keyframe up to the (wrapped) requested frame are decoded in
157
+ /// order. This matches Flash Player behavior.
152
158
pub fn seek ( self , context : & mut UpdateContext < ' _ , ' gc , ' _ > , mut frame_id : u32 ) {
153
159
let read = self . 0 . read ( ) ;
154
160
if let VideoStream :: Uninstantiated ( _) = & read. stream {
@@ -208,20 +214,25 @@ impl<'gc> Video<'gc> {
208
214
drop ( read) ;
209
215
210
216
for fr in sweep_from..=frame_id {
211
- self . do_seek ( context, fr)
217
+ self . seek_internal ( context, fr)
212
218
}
213
219
}
214
220
215
- /// The internals of `seek` factored out, separate from the sweeping mechanism.
216
- fn do_seek ( self , context : & mut UpdateContext < ' _ , ' gc , ' _ > , frame_id : u32 ) {
221
+ /// Decode a single frame of video.
222
+ ///
223
+ /// This function makes no attempt to ensure that the proposed seek is
224
+ /// valid, hence the fact that it's not `pub`. To do a seek that accounts
225
+ /// for keyframes, see `Video.seek`.
226
+ fn seek_internal ( self , context : & mut UpdateContext < ' _ , ' gc , ' _ > , frame_id : u32 ) {
217
227
let read = self . 0 . read ( ) ;
218
228
let source = read. source ;
219
229
let stream = if let VideoStream :: Instantiated ( stream) = & read. stream {
220
230
stream
221
231
} else {
222
- log:: error!( "Attempted to sync uninstantiated video stream! " ) ;
232
+ log:: error!( "Attempted to seek uninstantiated video stream. " ) ;
223
233
return ;
224
234
} ;
235
+
225
236
let res = match & * source. read ( ) {
226
237
VideoSource :: Swf {
227
238
movie,
0 commit comments