Skip to content

Commit

Permalink
Engine: implement video's FrameRate, Duration and Position properties
Browse files Browse the repository at this point in the history
  • Loading branch information
ivan-mogilko committed Mar 7, 2024
1 parent 5d5af0d commit 7ac562c
Show file tree
Hide file tree
Showing 6 changed files with 27 additions and 10 deletions.
3 changes: 3 additions & 0 deletions Engine/media/video/flic_player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ HError FlicPlayer::OpenImpl(std::unique_ptr<Common::Stream> data_stream,
_frameDepth = 8;
_frameSize = Size(fliwidth, fliheight);
_frameRate = 1000.f / fli_speed;
_frameTime = fli_speed;
_frameCount = fli_frame_count;
_durationMs = fli_frame_count * fli_speed;
return HError::None();
}

Expand Down
5 changes: 4 additions & 1 deletion Engine/media/video/theora_player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,11 @@ HError TheoraPlayer::OpenAPEGStream(Stream *data_stream, const Common::String &n
_usedDepth = target_depth;

_frameDepth = target_depth;
_frameRate = _apegStream->frame_rate;
_frameSize = Size(video_w, video_h);
_frameRate = _apegStream->frame_rate;
_frameTime = 1000.f / _apegStream->frame_rate;
_frameCount = _apegStream->length / _frameTime;
_durationMs = _apegStream->length;
// According to the documentation:
// encoded theora frames must be a multiple of 16 in width and height.
// Which means that the original content may end up positioned on a larger frame.
Expand Down
15 changes: 9 additions & 6 deletions Engine/media/video/videoplayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ HError VideoPlayer::Open(std::unique_ptr<Common::Stream> data_stream,
}

// TODO: actually support dynamic FPS, need to adjust audio speed
_frameTime = 1000.f / _targetFPS;
_targetFrameTime = 1000.f / _targetFPS;
return HError::None();
}

Expand Down Expand Up @@ -216,13 +216,13 @@ void VideoPlayer::SetSpeed(float speed)
break;
}

auto old_frametime = _frameTime;
auto old_frametime = _targetFrameTime;
_targetFPS = _frameRate * speed;
_frameTime = 1000.f / _targetFPS;
_targetFrameTime = 1000.f / _targetFPS;

// Adjust our virtual timestamps by the difference between
// previous play duration, and new duration calculated from the new speed.
float ft_rel = _frameTime / old_frametime;
float ft_rel = _targetFrameTime / old_frametime;
AGS_Clock::duration virtual_play_dur =
AGS_Clock::duration((int64_t)(play_dur.count() * ft_rel));
_firstFrameTime = now - virtual_play_dur;
Expand Down Expand Up @@ -360,7 +360,7 @@ bool VideoPlayer::ProcessVideo(bool force_next)
// TODO: get frame's timestamp if available from decoder?
if (force_next ||
((_videoFrameQueue.size() > 0) &&
duration >= _framesPlayed * _frameTime))
duration >= _framesPlayed * _targetFrameTime))
{
_videoFramePool.push(std::move(_videoReadyFrame));
}
Expand All @@ -372,7 +372,7 @@ bool VideoPlayer::ProcessVideo(bool force_next)
{
// TODO: get frame's timestamp if available from decoder?
if (force_next || _framesPlayed == 0u ||
duration >= _framesPlayed * _frameTime)
duration >= _framesPlayed * _targetFrameTime)
{
_videoReadyFrame = std::move(_videoFrameQueue.front());
_videoFrameQueue.pop_front();
Expand All @@ -387,6 +387,9 @@ bool VideoPlayer::ProcessVideo(bool force_next)
}
}

// TODO: get frame's timestamp if available from decoder?
_posMs = _framesPlayed * _frameTime;

// We are good so long as there's either a ready frame, or frames left in queue
return _videoReadyFrame || !_videoFrameQueue.empty();
}
Expand Down
10 changes: 7 additions & 3 deletions Engine/media/video/videoplayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,9 @@ class VideoPlayer
// Get current playback state
PlaybackState GetPlayState() const { return _playState; }
// Gets duration, in ms
float GetDurationMs() const { return 0 /* TODO */; }
float GetDurationMs() const { return _durationMs; }
// Gets playback position, in ms
float GetPositionMs() const { return 0 /* TODO */; }
float GetPositionMs() const { return _posMs; }

void SetSpeed(float speed);
void SetVolume(float volume);
Expand Down Expand Up @@ -144,6 +144,9 @@ class VideoPlayer
int _frameDepth = 0; // bits per pixel
Size _frameSize{};
float _frameRate = 0.f;
float _frameTime = 0.f;
uint32_t _frameCount = 0;
float _durationMs = 0.f;

private:
// Resume after pause
Expand All @@ -166,10 +169,12 @@ class VideoPlayer
Size _targetSize;
int _targetDepth = 0;
float _targetFPS = 0.f;
float _targetFrameTime = 0.f; // frame duration in ms for "target fps"
uint32_t _videoQueueMax = 5u;
uint32_t _audioQueueMax = 0u; // we don't have a real queue atm
// Playback state
PlaybackState _playState = PlayStateInitial;
float _posMs = 0.f;
// Frames counter, increments with playback, resets on rewind or seek
uint32_t _framesPlayed = 0u;
// Stage timestamps, used to calculate the next frame timing;
Expand All @@ -183,7 +188,6 @@ class VideoPlayer
// Audio output object
std::unique_ptr<OpenAlSource> _audioOut;
// Video
float _frameTime = 0.f; // frame duration in ms
// Helper buffer for retrieving video frames of different size/depth;
// should match "native" video frame size and color depth
std::unique_ptr<Common::Bitmap> _vframeBuf;
Expand Down
1 change: 1 addition & 0 deletions libsrc/allegro/include/allegro/fli.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ AL_VAR(int, fli_pal_dirty_from); /* what part of fli_palette is dirty */
AL_VAR(int, fli_pal_dirty_to);

AL_VAR(int, fli_frame); /* current frame number */
AL_VAR(int, fli_frame_count); /* total number of frames */

AL_VAR(int, fli_speed); /* FLI playback speed factor, in milliseconds */

Expand Down
3 changes: 3 additions & 0 deletions libsrc/allegro/src/fli.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ int fli_pal_dirty_from = INT_MAX; /* what part of fli_palette is dirty */
int fli_pal_dirty_to = INT_MIN;

int fli_frame = 0; /* current frame number in the FLI */
int fli_frame_count = 0; /* total number of frames in the FLI */

int fli_speed = 0; /* speed of the fli playback */

Expand Down Expand Up @@ -857,6 +858,7 @@ static int do_open_fli(void)
}

reset_fli_variables();
fli_frame_count = fli_header.frame_count;
fli_frame = 0;
fli_status = FLI_OK;

Expand Down Expand Up @@ -921,6 +923,7 @@ int open_memory_fli(void *fli_data)
*/
void close_fli(void)
{
fli_frame_count = 0;
fli_speed = 0;

if (fli_file) {
Expand Down

0 comments on commit 7ac562c

Please sign in to comment.