This implementation allows:
- Accurate seeking to an exact timestamp
- Seeking to the keyframe before a timestamp
- Seeking to the keyframe after a timestamp
These three options will be used to satisfy the playback position
selection in the media element's seeking steps.
By default, MatroskaDemuxer chooses not to seek if the current frame
is closer to the seek target than the keyframe that precedes the seek
target. However, it can be desirable to seek to a keyframe anyway, so
let's allow that.
Reader::seek_to_random_access_point() isn't actually guaranteed to
return a sample iterator that has already gotten a block timestamp.
This verify passes in almost every case, but if we happen to seek to a
timestamp before the second keyframe, we'd crash.
This time provider can later be swapped out for the AudioMixingSink
when it implements the MediaTimeProvider interface, so that frame
timing can be driven by audio when it is present.
The two classes now inherit from a common base MediaTrackBase, to
deduplicate the attributes that are shared between the two.
The integer ID from the container is used for each track's id
attribute.
The kind attribute is set to "main" or "translation" according to:
https://dev.w3.org/html5/html-sourcing-inband-tracks/
The label attribute is set to the human-readable name of the track, if
one is present.
The language attribute is set to a BCP 47 language tag, if one can be
parsed successfully.
This commit implements the functionality to play back audio through
PlaybackManager.
To decode the audio data, AudioDataProviders are created for each track
in the provided media data. These providers will fill their audio block
queue, then sit idle until their corresponding tracks are enabled.
In order to output the audio, one AudioMixingSink is created which
manages a PlaybackStream which requests audio blocks from multiple
AudioDataProviders and mixes them into one buffer with sample-perfect
precision.
With this commit, all PlaybackManager can do is autoplay a file from
start to finish, with no pausing or seeking functionality.
All audio playback functionality has been removed from HTMLMediaElement
and HTMLAudioElement in anticipation of PlaybackManager taking that
over, for both audio-only and audio/video.
Very minor change, which doesn't actually affect our output, since we
were already inputting and outputting microseconds, but it can't hurt
to give FFmpeg's decoder this information as well.
We should be fine to just fall back to zero or the last returned value
if we encounter an error in PlaybackStream::total_time_played(), and
this also simplifies the using code.
There's a fairly complicated interaction between an SVG gradient's paint
transformation and the gradient coordinate transformation required to
correctly draw gradient fills. This was especially noticeable when
scaling down an SVG, resulting in broken gradient coordinates and
graphical glitches.
This changes the objectBoundingBox units to immediately map to the
bounding box's coordinate system, so we can unify the gradient paint
transformation logic and make it a lot simpler. We only need to undo the
bounding box offset and apply the paint transformation to fix a lot of
gradient fill bugs.
We don't need to construct a new AffineTransform and multiply that by
yet another AffineTransform; we can simply translate and scale the
transform that's already in place. No functional changes.
This shrinks every Statement and ECMAScriptFunctionObject by one
pointer, and puts the bytecode cache in the only place that actually
makes use of it anyway: functions.