forked from mia/Aegisub
Simplify video playback logic
Originally committed to SVN as r5962.
This commit is contained in:
parent
1f534bc757
commit
2e40652265
4 changed files with 41 additions and 77 deletions
|
@ -433,7 +433,8 @@ void DialogTimingProcessor::Process() {
|
|||
// Keyframe snapping
|
||||
if (keysEnable->IsChecked()) {
|
||||
KeyFrames = c->videoController->GetKeyFrames();
|
||||
KeyFrames.push_back(c->videoController->GetLength() - 1);
|
||||
if (c->videoController->IsLoaded())
|
||||
KeyFrames.push_back(c->videoController->GetLength() - 1);
|
||||
|
||||
long beforeStart = 0;
|
||||
long afterStart = 0;
|
||||
|
|
|
@ -68,26 +68,16 @@
|
|||
#include "video_context.h"
|
||||
#include "video_frame.h"
|
||||
|
||||
/// IDs
|
||||
enum {
|
||||
VIDEO_PLAY_TIMER = 1300
|
||||
};
|
||||
|
||||
BEGIN_EVENT_TABLE(VideoContext, wxEvtHandler)
|
||||
EVT_TIMER(VIDEO_PLAY_TIMER,VideoContext::OnPlayTimer)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
/// @brief Constructor
|
||||
///
|
||||
VideoContext::VideoContext()
|
||||
: startFrame(-1)
|
||||
, endFrame(-1)
|
||||
: playback(this)
|
||||
, startMS(0)
|
||||
, endFrame(0)
|
||||
, playNextFrame(-1)
|
||||
, nextFrame(-1)
|
||||
, isPlaying(false)
|
||||
, keepAudioSync(true)
|
||||
, frame_n(0)
|
||||
, length(0)
|
||||
, arValue(1.)
|
||||
, arType(0)
|
||||
, hasSubtitles(false)
|
||||
|
@ -97,6 +87,7 @@ VideoContext::VideoContext()
|
|||
{
|
||||
Bind(EVT_VIDEO_ERROR, &VideoContext::OnVideoError, this);
|
||||
Bind(EVT_SUBTITLES_ERROR, &VideoContext::OnSubtitlesError, this);
|
||||
Bind(wxEVT_TIMER, &VideoContext::OnPlayTimer, this);
|
||||
|
||||
OPT_SUB("Subtitle/Provider", &VideoContext::Reload, this);
|
||||
OPT_SUB("Video/Provider", &VideoContext::Reload, this);
|
||||
|
@ -127,9 +118,8 @@ void VideoContext::Reset() {
|
|||
if (!ovrFPS.IsLoaded()) TimecodesOpen(videoFPS);
|
||||
|
||||
// Remove video data
|
||||
Stop();
|
||||
frame_n = 0;
|
||||
length = 0;
|
||||
isPlaying = false;
|
||||
nextFrame = -1;
|
||||
|
||||
// Clean up video data
|
||||
|
@ -202,9 +192,6 @@ void VideoContext::SetVideo(const wxString &filename) {
|
|||
}
|
||||
}
|
||||
|
||||
// Gather video parameters
|
||||
length = videoProvider->GetFrameCount();
|
||||
|
||||
// Set filename
|
||||
videoName = filename;
|
||||
config::mru->Add("Video", STD_STR(filename));
|
||||
|
@ -249,7 +236,7 @@ void VideoContext::Reload() {
|
|||
void VideoContext::OnSubtitlesCommit() {
|
||||
if (!IsLoaded()) return;
|
||||
|
||||
bool wasPlaying = isPlaying;
|
||||
bool wasPlaying = IsPlaying();
|
||||
Stop();
|
||||
|
||||
provider->LoadSubtitles(context->ass);
|
||||
|
@ -285,7 +272,7 @@ void VideoContext::JumpToFrame(int n) {
|
|||
if (!IsLoaded()) return;
|
||||
|
||||
// Prevent intervention during playback
|
||||
if (isPlaying && n != playNextFrame) return;
|
||||
if (IsPlaying() && n != playNextFrame) return;
|
||||
|
||||
frame_n = mid(0, n, GetLength() - 1);
|
||||
|
||||
|
@ -312,6 +299,10 @@ int VideoContext::GetHeight() const {
|
|||
return videoProvider->GetHeight();
|
||||
}
|
||||
|
||||
int VideoContext::GetLength() const {
|
||||
return videoProvider->GetFrameCount();
|
||||
}
|
||||
|
||||
void VideoContext::SaveSnapshot(bool raw) {
|
||||
// Get folder
|
||||
static const agi::OptionValue* ssPath = OPT_GET("Path/Screenshot");
|
||||
|
@ -351,7 +342,7 @@ void VideoContext::SaveSnapshot(bool raw) {
|
|||
}
|
||||
|
||||
void VideoContext::NextFrame() {
|
||||
if (!videoProvider.get() || isPlaying || frame_n == videoProvider->GetFrameCount())
|
||||
if (!videoProvider || IsPlaying() || frame_n == videoProvider->GetFrameCount())
|
||||
return;
|
||||
|
||||
JumpToFrame(frame_n + 1);
|
||||
|
@ -364,7 +355,7 @@ void VideoContext::NextFrame() {
|
|||
}
|
||||
|
||||
void VideoContext::PrevFrame() {
|
||||
if (!videoProvider.get() || isPlaying || frame_n == 0)
|
||||
if (!videoProvider || IsPlaying() || frame_n == 0)
|
||||
return;
|
||||
|
||||
JumpToFrame(frame_n - 1);
|
||||
|
@ -377,7 +368,7 @@ void VideoContext::PrevFrame() {
|
|||
}
|
||||
|
||||
void VideoContext::Play() {
|
||||
if (isPlaying) {
|
||||
if (IsPlaying()) {
|
||||
Stop();
|
||||
return;
|
||||
}
|
||||
|
@ -385,18 +376,14 @@ void VideoContext::Play() {
|
|||
if (!IsLoaded()) return;
|
||||
|
||||
// Set variables
|
||||
startFrame = frame_n;
|
||||
endFrame = -1;
|
||||
startMS = TimeAtFrame(frame_n);
|
||||
endFrame = GetLength() - 1;
|
||||
|
||||
// Start playing audio
|
||||
context->audioController->PlayToEnd(context->audioController->SamplesFromMilliseconds(TimeAtFrame(startFrame)));
|
||||
|
||||
//audio->Play will override this if we put it before, so put it after.
|
||||
isPlaying = true;
|
||||
context->audioController->PlayToEnd(context->audioController->SamplesFromMilliseconds(startMS));
|
||||
|
||||
// Start timer
|
||||
playTime.Start();
|
||||
playback.SetOwner(this,VIDEO_PLAY_TIMER);
|
||||
playback.Start(10);
|
||||
}
|
||||
|
||||
|
@ -409,55 +396,39 @@ void VideoContext::PlayLine() {
|
|||
context->audioController->SamplesFromMilliseconds(curline->Start.GetMS()),
|
||||
context->audioController->SamplesFromMilliseconds(curline->End.GetMS())));
|
||||
|
||||
// Set variables
|
||||
isPlaying = true;
|
||||
startFrame = FrameAtTime(context->selectionController->GetActiveLine()->Start.GetMS(),agi::vfr::START);
|
||||
endFrame = FrameAtTime(context->selectionController->GetActiveLine()->End.GetMS(),agi::vfr::END);
|
||||
// Round-trip conversion to convert start to exact
|
||||
int startFrame = FrameAtTime(context->selectionController->GetActiveLine()->Start.GetMS(),agi::vfr::START);
|
||||
startMS = TimeAtFrame(startFrame);
|
||||
endFrame = FrameAtTime(context->selectionController->GetActiveLine()->End.GetMS(),agi::vfr::END) + 1;
|
||||
|
||||
// Jump to start
|
||||
playNextFrame = startFrame;
|
||||
JumpToFrame(startFrame);
|
||||
|
||||
// Set other variables
|
||||
playTime.Start();
|
||||
|
||||
// Start timer
|
||||
playback.SetOwner(this,VIDEO_PLAY_TIMER);
|
||||
playTime.Start();
|
||||
playback.Start(10);
|
||||
}
|
||||
|
||||
void VideoContext::Stop() {
|
||||
if (isPlaying) {
|
||||
if (IsPlaying()) {
|
||||
playback.Stop();
|
||||
isPlaying = false;
|
||||
context->audioController->Stop();
|
||||
}
|
||||
}
|
||||
|
||||
void VideoContext::OnPlayTimer(wxTimerEvent &) {
|
||||
// Get time difference
|
||||
int dif = playTime.Time();
|
||||
int nextFrame = FrameAtTime(startMS + playTime.Time());
|
||||
|
||||
// Find next frame
|
||||
int startMs = TimeAtFrame(startFrame);
|
||||
int nextFrame = frame_n;
|
||||
int i=0;
|
||||
for (i=0;i<10;i++) {
|
||||
if (nextFrame >= length) break;
|
||||
if (dif < TimeAtFrame(nextFrame) - startMs) {
|
||||
break;
|
||||
}
|
||||
nextFrame++;
|
||||
}
|
||||
// Same frame
|
||||
if (nextFrame == frame_n) return;
|
||||
|
||||
// End
|
||||
if (nextFrame >= length || (endFrame != -1 && nextFrame > endFrame)) {
|
||||
if (nextFrame >= endFrame) {
|
||||
Stop();
|
||||
return;
|
||||
}
|
||||
|
||||
// Same frame
|
||||
if (nextFrame == frame_n) return;
|
||||
|
||||
// Next frame is before or over 2 frames ahead, so force audio resync
|
||||
if (context->audioController->IsPlaying() && keepAudioSync && (nextFrame < frame_n || nextFrame > frame_n + 2)) {
|
||||
|
@ -547,7 +518,7 @@ void VideoContext::LoadTimecodes(wxString filename) {
|
|||
}
|
||||
void VideoContext::SaveTimecodes(wxString filename) {
|
||||
try {
|
||||
FPS().Save(STD_STR(filename), IsLoaded() ? length : -1);
|
||||
FPS().Save(STD_STR(filename), IsLoaded() ? GetLength() : -1);
|
||||
config::mru->Add("Timecodes", STD_STR(filename));
|
||||
}
|
||||
catch(const agi::acs::AcsError&) {
|
||||
|
|
|
@ -95,11 +95,11 @@ class VideoContext : public wxEvtHandler {
|
|||
/// DOCME
|
||||
wxTimer playback;
|
||||
|
||||
/// DOCME
|
||||
/// Time since playback was last started
|
||||
wxStopWatch playTime;
|
||||
|
||||
/// DOCME
|
||||
int startFrame;
|
||||
int startMS;
|
||||
|
||||
/// DOCME
|
||||
int endFrame;
|
||||
|
@ -110,18 +110,12 @@ class VideoContext : public wxEvtHandler {
|
|||
/// DOCME
|
||||
int nextFrame;
|
||||
|
||||
/// DOCME
|
||||
bool isPlaying;
|
||||
|
||||
/// DOCME
|
||||
bool keepAudioSync;
|
||||
|
||||
/// DOCME
|
||||
int frame_n;
|
||||
|
||||
/// DOCME
|
||||
int length;
|
||||
|
||||
/// DOCME
|
||||
double arValue;
|
||||
|
||||
|
@ -175,10 +169,10 @@ public:
|
|||
void SaveSnapshot(bool raw);
|
||||
|
||||
/// @brief Is there a video loaded?
|
||||
bool IsLoaded() const { return !!videoProvider.get(); }
|
||||
bool IsLoaded() const { return !!videoProvider; }
|
||||
|
||||
/// @brief Is the video currently playing?
|
||||
bool IsPlaying() const { return isPlaying; }
|
||||
bool IsPlaying() const { return playback.IsRunning(); }
|
||||
|
||||
/// @brief Does the video file loaded have muxed subtitles that we can load?
|
||||
bool HasSubtitles() const { return hasSubtitles; }
|
||||
|
@ -195,7 +189,7 @@ public:
|
|||
int GetHeight() const;
|
||||
|
||||
/// @brief Get the length in frames of the currently open video
|
||||
int GetLength() const { return length; }
|
||||
int GetLength() const;
|
||||
|
||||
/// @brief Get the current frame number
|
||||
int GetFrameN() const { return frame_n; }
|
||||
|
@ -264,6 +258,4 @@ public:
|
|||
|
||||
static VideoContext *Get();
|
||||
static void OnExit();
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
|
|
@ -63,9 +63,7 @@ VideoSlider::VideoSlider (wxWindow* parent, agi::Context *c)
|
|||
|
||||
c->videoSlider = this;
|
||||
|
||||
if (c->videoController->IsLoaded()) {
|
||||
VideoOpened();
|
||||
}
|
||||
VideoOpened();
|
||||
}
|
||||
|
||||
void VideoSlider::SetValue(int value) {
|
||||
|
@ -75,9 +73,11 @@ void VideoSlider::SetValue(int value) {
|
|||
}
|
||||
|
||||
void VideoSlider::VideoOpened() {
|
||||
max = c->videoController->GetLength() - 1;
|
||||
keyframes = c->videoController->GetKeyFrames();
|
||||
Refresh(false);
|
||||
if (c->videoController->IsLoaded()) {
|
||||
max = c->videoController->GetLength() - 1;
|
||||
keyframes = c->videoController->GetKeyFrames();
|
||||
Refresh(false);
|
||||
}
|
||||
}
|
||||
|
||||
void VideoSlider::KeyframesChanged(std::vector<int> const& newKeyframes) {
|
||||
|
|
Loading…
Reference in a new issue